Changeset View
Changeset View
Standalone View
Standalone View
sys/i386/i386/bios.c
Show First 20 Lines • Show All 323 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
int | int | ||||
bios16(struct bios_args *args, char *fmt, ...) | bios16(struct bios_args *args, char *fmt, ...) | ||||
{ | { | ||||
char *p, *stack, *stack_top; | char *p, *stack, *stack_top; | ||||
va_list ap; | va_list ap; | ||||
int flags = BIOSCODE_FLAG | BIOSDATA_FLAG; | int flags = BIOSCODE_FLAG | BIOSDATA_FLAG; | ||||
u_int i, arg_start, arg_end; | u_int i, arg_start, arg_end; | ||||
pt_entry_t *pte; | void *bios16_pmap_handle; | ||||
pd_entry_t *ptd, orig_ptd; | |||||
arg_start = 0xffffffff; | arg_start = 0xffffffff; | ||||
arg_end = 0; | arg_end = 0; | ||||
/* | /* | ||||
* Some BIOS entrypoints attempt to copy the largest-case | * Some BIOS entrypoints attempt to copy the largest-case | ||||
* argument frame (in order to generalise handling for | * argument frame (in order to generalise handling for | ||||
* different entry types). If our argument frame is | * different entry types). If our argument frame is | ||||
* smaller than this, the BIOS will reach off the top of | * smaller than this, the BIOS will reach off the top of | ||||
Show All 40 Lines | default: | ||||
if (flags & BIOSARGS_FLAG) { | if (flags & BIOSARGS_FLAG) { | ||||
if (arg_end - arg_start > ctob(16)) | if (arg_end - arg_start > ctob(16)) | ||||
return (EACCES); | return (EACCES); | ||||
args->seg.args.base = arg_start; | args->seg.args.base = arg_start; | ||||
args->seg.args.limit = 0xffff; | args->seg.args.limit = 0xffff; | ||||
} | } | ||||
args->seg.code32.base = (u_int)&bios16_jmp & PG_FRAME; | args->seg.code32.base = pmap_pg_frame((u_int)&bios16_jmp); | ||||
args->seg.code32.limit = 0xffff; | args->seg.code32.limit = 0xffff; | ||||
/* | bios16_pmap_handle = pmap_bios16_enter(); | ||||
* no page table, so create one and install it. | |||||
*/ | |||||
pte = (pt_entry_t *)malloc(PAGE_SIZE, M_TEMP, M_WAITOK); | |||||
ptd = IdlePTD; | |||||
*pte = vm86phystk | PG_RW | PG_V; | |||||
orig_ptd = *ptd; | |||||
*ptd = vtophys(pte) | PG_RW | PG_V; | |||||
pmap_invalidate_all(kernel_pmap); /* XXX insurance for now */ | |||||
stack_top = stack; | stack_top = stack; | ||||
va_start(ap, fmt); | va_start(ap, fmt); | ||||
for (p = fmt; p && *p; p++) { | for (p = fmt; p && *p; p++) { | ||||
switch (*p) { | switch (*p) { | ||||
case 'p': /* 32-bit pointer */ | case 'p': /* 32-bit pointer */ | ||||
i = va_arg(ap, u_int); | i = va_arg(ap, u_int); | ||||
*(u_int *)stack = (i - arg_start) | | *(u_int *)stack = (i - arg_start) | | ||||
Show All 35 Lines | default: | ||||
} | } | ||||
va_end(ap); | va_end(ap); | ||||
set_bios_selectors(&args->seg, flags); | set_bios_selectors(&args->seg, flags); | ||||
bioscall_vector.vec16.offset = (u_short)args->entry; | bioscall_vector.vec16.offset = (u_short)args->entry; | ||||
bioscall_vector.vec16.segment = GSEL(GBIOSCODE16_SEL, SEL_KPL); | bioscall_vector.vec16.segment = GSEL(GBIOSCODE16_SEL, SEL_KPL); | ||||
i = bios16_call(&args->r, stack_top); | i = bios16_call(&args->r, stack_top); | ||||
pmap_bios16_leave(bios16_pmap_handle); | |||||
*ptd = orig_ptd; /* remove page table */ | |||||
/* | |||||
* XXX only needs to be invlpg(0) but that doesn't work on the 386 | |||||
*/ | |||||
pmap_invalidate_all(kernel_pmap); | |||||
free(pte, M_TEMP); /* ... and free it */ | |||||
return (i); | return (i); | ||||
} | } | ||||
int | int | ||||
bios_oem_strings(struct bios_oem *oem, u_char *buffer, size_t maxlen) | bios_oem_strings(struct bios_oem *oem, u_char *buffer, size_t maxlen) | ||||
{ | { | ||||
size_t idx = 0; | size_t idx = 0; | ||||
struct bios_oem_signature *sig; | struct bios_oem_signature *sig; | ||||
▲ Show 20 Lines • Show All 282 Lines • Show Last 20 Lines |