Changeset View
Changeset View
Standalone View
Standalone View
sys/i386/i386/bios.c
Show First 20 Lines • Show All 299 Lines • ▼ Show 20 Lines | ssdtosd(&ssd, &p_gdt[GBIOSUTIL_SEL].sd); | ||||
if (flags & BIOSARGS_FLAG) { | if (flags & BIOSARGS_FLAG) { | ||||
ssd.ssd_base = seg->args.base; | ssd.ssd_base = seg->args.base; | ||||
ssd.ssd_limit = seg->args.limit; | ssd.ssd_limit = seg->args.limit; | ||||
ssdtosd(&ssd, &p_gdt[GBIOSARGS_SEL].sd); | ssdtosd(&ssd, &p_gdt[GBIOSARGS_SEL].sd); | ||||
} | } | ||||
} | } | ||||
extern int vm86pa; | extern int vm86pa; | ||||
extern u_long vm86phystk; | |||||
extern void bios16_jmp(void); | extern void bios16_jmp(void); | ||||
/* | /* | ||||
* this routine is really greedy with selectors, and uses 5: | * this routine is really greedy with selectors, and uses 5: | ||||
* | * | ||||
* 32-bit code selector: to return to kernel | * 32-bit code selector: to return to kernel | ||||
* 16-bit code selector: for running code | * 16-bit code selector: for running code | ||||
* data selector: for 16-bit data | * data selector: for 16-bit data | ||||
* util selector: extra utility selector | * util selector: extra utility selector | ||||
* args selector: to handle pointers | * args selector: to handle pointers | ||||
* | * | ||||
* the util selector is set from the util16 entry in bios16_args, if a | * the util selector is set from the util16 entry in bios16_args, if a | ||||
* "U" specifier is seen. | * "U" specifier is seen. | ||||
* | * | ||||
* See <machine/pc/bios.h> for description of format specifiers | * See <machine/pc/bios.h> for description of format specifiers | ||||
*/ | */ | ||||
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; | pt_entry_t *pte; | ||||
pd_entry_t *ptd; | 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 | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | 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 = (u_int)&bios16_jmp & PG_FRAME; | ||||
args->seg.code32.limit = 0xffff; | args->seg.code32.limit = 0xffff; | ||||
ptd = (pd_entry_t *)rcr3(); | |||||
#if defined(PAE) || defined(PAE_TABLES) | |||||
if (ptd == IdlePDPT) | |||||
#else | |||||
if (ptd == IdlePTD) | |||||
#endif | |||||
{ | |||||
/* | /* | ||||
* no page table, so create one and install it. | * no page table, so create one and install it. | ||||
*/ | */ | ||||
pte = (pt_entry_t *)malloc(PAGE_SIZE, M_TEMP, M_WAITOK); | pte = (pt_entry_t *)malloc(PAGE_SIZE, M_TEMP, M_WAITOK); | ||||
ptd = (pd_entry_t *)((u_int)IdlePTD + KERNBASE); | ptd = IdlePTD; | ||||
*pte = (vm86pa - PAGE_SIZE) | PG_RW | PG_V; | *pte = vm86phystk | PG_RW | PG_V; | ||||
orig_ptd = *ptd; | |||||
*ptd = vtophys(pte) | PG_RW | PG_V; | *ptd = vtophys(pte) | PG_RW | PG_V; | ||||
} else { | |||||
/* | |||||
* this is a user-level page table | |||||
*/ | |||||
pte = PTmap; | |||||
*pte = (vm86pa - PAGE_SIZE) | PG_RW | PG_V; | |||||
} | |||||
pmap_invalidate_all(kernel_pmap); /* XXX insurance for now */ | 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); | ||||
Show All 37 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); | ||||
if (pte == PTmap) { | *ptd = orig_ptd; /* remove page table */ | ||||
*pte = 0; /* remove entry */ | |||||
/* | /* | ||||
* XXX only needs to be invlpg(0) but that doesn't work on the 386 | * XXX only needs to be invlpg(0) but that doesn't work on the 386 | ||||
*/ | */ | ||||
pmap_invalidate_all(kernel_pmap); | pmap_invalidate_all(kernel_pmap); | ||||
} else { | |||||
*ptd = 0; /* 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 */ | 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 |