/* Move cursor to x rows and y cols (0-based). */ void curs_move(int *_x, int *_y, int x, int y) { v86.ctl = 0; v86.addr = 0x10; v86.eax = 0x0200; v86.ebx = 0x0; v86.edx = ((0x00ff & y) << 8) + (0x00ff & x); v86int(); *_x = x; *_y = y; /* If there is ctrl char at this position, cursor would be invisible. * Make it a space instead. */ v86.ctl = 0; v86.addr = 0x10; v86.eax = 0x0800; v86.ebx = 0x0; v86int(); #define isvisible(c) (((c) >= 32) && ((c) < 255)) if (!isvisible(v86.eax & 0x00ff)) { write_char(' ', fg_c, bg_c); } }
/* Clear display from current position to end of screen */ void CD(void) { get_pos(&curx, &cury); if (curx > 0) { v86.ctl = 0; v86.addr = 0x10; v86.eax = 0x0600; v86.ebx = (bg_c << 4) + fg_c; v86.ecx = (cury << 8) + curx; v86.edx = (cury << 8) + 79; v86int(); if (++cury > 24) { end_term(); return; } } v86.ctl = 0; v86.addr = 0x10; v86.eax = 0x0600; v86.ebx = (bg_c << 4) + fg_c; v86.ecx = (cury << 8) + 0; v86.edx = (24 << 8) + 79; v86int(); end_term(); }
uint32_t tcg_hash_extend(uint32_t addr, uint32_t len, uint32_t pcr) { struct TCG_HashAll tcg_hash_all; struct TCG_PassTroughtToTPM tcg_passtrough_to_tpm; char _unused[0x22]; tcg_hash_all.ipb_length = 0x0010; tcg_hash_all._reserved = 0x0000; tcg_hash_all.hash_data_ptr = addr; tcg_hash_all.hash_data_len = len; tcg_hash_all.algorithm_id = TPM_ALGO_SHA1; tcg_passtrough_to_tpm.ipb_length = 0x002a; tcg_passtrough_to_tpm._reserved1 = 0x0000; tcg_passtrough_to_tpm.opb_length = 0x0022; tcg_passtrough_to_tpm._reserved2 = 0x0000; tcg_passtrough_to_tpm.tpm_tag = __htons(TPM_TAG_RQU_COMMAND); tcg_passtrough_to_tpm.input_size = __htonl(0x00000022); tcg_passtrough_to_tpm.cmd_ordinal = __htonl(TPM_ORD_Extend); tcg_passtrough_to_tpm.pcr = __htonl(pcr); v86.addr = 0x1a; v86.eax = 0xbb05; v86.ebx = TCG_MAGIC; v86.ecx = 0x00000000; v86.edx = 0x00000000; v86.es = VTOPSEG(&tcg_hash_all); v86.edi = VTOPOFF(&tcg_hash_all); v86.ds = VTOPSEG(&tcg_passtrough_to_tpm.hash); v86.esi = VTOPOFF(&tcg_passtrough_to_tpm.hash); v86int(); if (v86.eax != TCG_PC_OK) return (v86.eax); v86.addr = 0x1a; v86.eax = 0xbb02; v86.ebx = TCG_MAGIC; v86.ecx = 0x00000000; v86.edx = 0x00000000; v86.es = VTOPSEG(&tcg_passtrough_to_tpm); v86.edi = VTOPOFF(&tcg_passtrough_to_tpm); v86.ds = VTOPSEG(&_unused); v86.esi = VTOPOFF(&_unused); v86int(); return (v86.eax); }
static inline uint32_t memsize(void) { v86.addr = MEM_EXT; v86.eax = 0x8800; v86int(); return v86.eax; }
static inline void putc(int c) { v86.addr = 0x10; v86.eax = 0xe00 | (c & 0xff); v86.ebx = 0x7; v86int(); }
static int vidc_ischar(void) { v86.ctl = V86_FLAGS; v86.addr = 0x16; v86.eax = 0x100; v86int(); return(!(v86.efl & PSL_Z)); }
static void vidc_biosputchar(int c) { v86.ctl = 0; v86.addr = 0x10; v86.eax = 0xe00 | (c & 0xff); v86.ebx = 0x7; v86int(); }
static int vidc_ischar(void) { v86.ctl = 0; v86.addr = 0x18; v86.eax = 0x100; v86int(); return ((v86.ebx >> 8) & 0x1); }
void putc(int c) { v86.ctl = V86_FLAGS; v86.addr = 0x10; v86.eax = 0xe00 | (c & 0xff); v86.ebx = 0x7; v86int(); }
/* Write character and attribute at cursor position. */ void write_char(int c, int fg, int bg) { v86.ctl=0; v86.addr = 0x10; v86.eax = 0x0900+(0x00ff & c); v86.ebx = (bg<<4)+fg; v86.ecx = 0x1; v86int(); }
void bios_getsmap(void) { int n; n = 0; smaplen = 0; /* Count up segments in system memory map */ v86.ebx = 0; do { v86.ctl = V86_FLAGS; v86.addr = 0x15; /* int 0x15 function 0xe820*/ v86.eax = 0xe820; v86.ecx = sizeof(struct smap); v86.edx = SMAPSIG; v86.es = VTOPSEG(&smap); v86.edi = VTOPOFF(&smap); v86int(); if ((v86.efl & 1) || (v86.eax != SMAPSIG)) break; n++; } while (v86.ebx != 0); if (n == 0) return; n += 10; /* spare room */ smapbase = malloc(n * sizeof(*smapbase)); /* Save system memory map */ v86.ebx = 0; do { v86.ctl = V86_FLAGS; v86.addr = 0x15; /* int 0x15 function 0xe820*/ v86.eax = 0xe820; v86.ecx = sizeof(struct smap); v86.edx = SMAPSIG; v86.es = VTOPSEG(&smapbase[smaplen]); v86.edi = VTOPOFF(&smapbase[smaplen]); v86int(); smaplen++; if ((v86.efl & 1) || (v86.eax != SMAPSIG)) break; } while (v86.ebx != 0 && smaplen < n); }
/* Get cursor position on the screen. Result is in edx. Sets * curx and cury appropriately. */ void get_pos(void) { v86.ctl = 0; v86.addr = 0x10; v86.eax = 0x0300; v86.ebx = 0x0; v86int(); curx=v86.edx & 0x00ff; cury=(v86.edx & 0xff00)>>8; }
/* Get cursor position on the screen. Result is in edx. Sets * curx and cury appropriately. */ void get_pos(int *x, int *y) { v86.ctl = 0; v86.addr = 0x10; v86.eax = 0x0300; v86.ebx = 0x0; v86int(); *x = v86.edx & 0x00ff; *y = (v86.edx & 0xff00) >> 8; }
/* Scroll up the whole window by a number of rows. If rows==0, * clear the window. fg and bg are attributes for the new lines * inserted in the window. */ void scroll_up(int rows, int fg, int bg) { if(rows==0) rows=25; v86.ctl = 0; v86.addr = 0x10; v86.eax = 0x0600+(0x00ff & rows); v86.ebx = (bg<<12)+(fg<<8); v86.ecx = 0x0; v86.edx = 0x184f; v86int(); }
static int vidc_getchar(void) { if (vidc_ischar()) { v86.ctl = 0; v86.addr = 0x16; v86.eax = 0x0; v86int(); return(v86.eax & 0xff); } else { return(-1); } }
uint32_t tcg_status_check(void) { if (tpm_enabled == 0xff) { v86.addr = 0x1a; v86.eax = 0xbb00; v86int(); tpm_enabled = v86.eax; } return (tpm_enabled); }
/* Clear display from current position to end of screen */ void CD(void) { get_pos(); v86.ctl = 0; v86.addr = 0x10; v86.eax = 0x0600; v86.ebx = (bg_c<<4)+fg_c; v86.ecx = v86.edx; v86.edx = 0x184f; v86int(); curx=0; curs_move(curx,cury); end_term(); }
int getc(int fn) { /* * The extra comparison against zero is an attempt to work around * what appears to be a bug in QEMU and Bochs. Both emulators * sometimes report a key-press with scancode one and ascii zero * when no such key is pressed in reality. As far as I can tell, * this only happens shortly after a reboot. */ v86.ctl = V86_FLAGS; v86.addr = 0x16; v86.eax = fn << 8; v86int(); return fn == 0 ? v86.eax & 0xff : (!V86_ZR(v86.efl) && (v86.eax & 0xff)); }
/* * Use the BIOS Wait function to pause for (period) microseconds. * * Resolution of this function is variable, but typically around * 1ms. */ void delay(int period) { #ifdef PC98 int i; period = (period + 500) / 1000; for( ; period != 0 ; period--) for(i=800;i != 0; i--) outb(0x5f,0); /* wait 600ns */ #else v86.ctl = 0; v86.addr = 0x15; /* int 0x15, function 0x86 */ v86.eax = 0x8600; v86.ecx = period >> 16; v86.edx = period & 0xffff; v86int(); #endif }
static int bd_int13probe(struct bdinfo *bd) { v86.ctl = V86_FLAGS; v86.addr = 0x13; v86.eax = 0x800; v86.edx = bd->bd_unit; v86int(); if (!(v86.efl & 0x1) && /* carry clear */ ((v86.edx & 0xff) > (bd->bd_unit & 0x7f))) { /* unit # OK */ bd->bd_flags |= BD_MODEINT13; bd->bd_type = v86.ebx & 0xff; return(1); } return(0); }
/* * Return the BIOS time-of-day value. * * XXX uses undocumented BCD support from libstand. */ static int bios_seconds(void) { int hr, minute, sec; unsigned char bios_time[6]; v86.ctl = 0; v86.addr = 0x1c; /* int 0x1c, function 0 */ v86.eax = 0x0000; v86.es = VTOPSEG(bios_time); v86.ebx = VTOPOFF(bios_time); v86int(); hr = bcd2bin(bios_time[3]); minute = bcd2bin(bios_time[4]); sec = bcd2bin(bios_time[5]); return (hr * 3600 + minute * 60 + sec); }
time_t time(time_t *t) { static time_t lasttime, now; int hr, min, sec; #ifdef PC98 unsigned char bios_time[6]; #endif v86.ctl = 0; #ifdef PC98 v86.addr = 0x1c; /* int 0x1c, function 0 */ v86.eax = 0x0000; v86.es = VTOPSEG(bios_time); v86.ebx = VTOPOFF(bios_time); #else v86.addr = 0x1a; /* int 0x1a, function 2 */ v86.eax = 0x0200; #endif v86int(); #ifdef PC98 hr = bcd2bin(bios_time[3]); min = bcd2bin(bios_time[4]); sec = bcd2bin(bios_time[5]); #else hr = bcd2bin((v86.ecx & 0xff00) >> 8); /* hour in %ch */ min = bcd2bin(v86.ecx & 0xff); /* minute in %cl */ sec = bcd2bin((v86.edx & 0xff00) >> 8); /* second in %dh */ #endif now = hr * 3600 + min * 60 + sec; if (now < lasttime) now += 24 * 3600; lasttime = now; if (t != NULL) *t = now; return(now); }
void bios_getmem(void) { uint64_t size; /* Parse system memory map */ v86.ebx = 0; do { v86.ctl = V86_FLAGS; v86.addr = 0x15; /* int 0x15 function 0xe820*/ v86.eax = 0xe820; v86.ecx = sizeof(struct bios_smap_xattr); v86.edx = SMAP_SIG; v86.es = VTOPSEG(&smap); v86.edi = VTOPOFF(&smap); v86int(); if ((V86_CY(v86.efl)) || (v86.eax != SMAP_SIG)) break; /* look for a low-memory segment that's large enough */ if ((smap.type == SMAP_TYPE_MEMORY) && (smap.base == 0) && (smap.length >= (512 * 1024))) { bios_basemem = smap.length; b_bios_probed |= B_BASEMEM_E820; } /* look for the first segment in 'extended' memory */ if ((smap.type == SMAP_TYPE_MEMORY) && (smap.base == 0x100000) && !(bios_getquirks() & BQ_DISTRUST_E820_EXTMEM)) { bios_extmem = smap.length; b_bios_probed |= B_EXTMEM_E820; } /* * Look for the largest segment in 'extended' memory beyond * 1MB but below 4GB. */ if ((smap.type == SMAP_TYPE_MEMORY) && (smap.base > 0x100000) && (smap.base < 0x100000000ull)) { size = smap.length; /* * If this segment crosses the 4GB boundary, truncate it. */ if (smap.base + size > 0x100000000ull) size = 0x100000000ull - smap.base; if (size > high_heap_size) { high_heap_size = size; high_heap_base = smap.base; } } } while (v86.ebx != 0); /* Fall back to the old compatibility function for base memory */ if (bios_basemem == 0) { v86.ctl = 0; v86.addr = 0x12; /* int 0x12 */ v86int(); bios_basemem = (v86.eax & 0xffff) * 1024; b_bios_probed |= B_BASEMEM_12; } /* Fall back through several compatibility functions for extended memory */ if (bios_extmem == 0) { v86.ctl = V86_FLAGS; v86.addr = 0x15; /* int 0x15 function 0xe801*/ v86.eax = 0xe801; v86int(); if (!(V86_CY(v86.efl))) { /* * Clear high_heap; it may end up overlapping * with the segment we're determining here. * Let the default "steal stuff from top of * bios_extmem" code below pick up on it. */ high_heap_size = 0; high_heap_base = 0; /* * %cx is the number of 1KiB blocks between 1..16MiB. * It can only be up to 0x3c00; if it's smaller then * there's a PC AT memory hole so we can't treat * it as contiguous. */ bios_extmem = (v86.ecx & 0xffff) * 1024; if (bios_extmem == (1024 * 0x3c00)) bios_extmem += (v86.edx & 0xffff) * 64 * 1024; /* truncate bios_extmem */ if (bios_extmem > 0x3ff00000) bios_extmem = 0x3ff00000; b_bios_probed |= B_EXTMEM_E801; } } if (bios_extmem == 0) { v86.ctl = 0; v86.addr = 0x15; /* int 0x15 function 0x88*/ v86.eax = 0x8800; v86int(); bios_extmem = (v86.eax & 0xffff) * 1024; b_bios_probed |= B_EXTMEM_8800; } /* Set memtop to actual top of memory */ memtop = memtop_copyin = 0x100000 + bios_extmem; /* * If we have extended memory and did not find a suitable heap * region in the SMAP, use the last 3MB of 'extended' memory as a * high heap candidate. */ if (bios_extmem >= HEAP_MIN && high_heap_size < HEAP_MIN) { high_heap_size = HEAP_MIN; high_heap_base = memtop - HEAP_MIN; } }
void bios_getsmap(void) { struct smap_buf buf; STAILQ_HEAD(smap_head, smap_buf) head = STAILQ_HEAD_INITIALIZER(head); struct smap_buf *cur, *next; u_int n, x; STAILQ_INIT(&head); n = 0; x = 0; v86.ebx = 0; do { v86.ctl = V86_FLAGS; v86.addr = 0x15; v86.eax = 0xe820; /* int 0x15 function 0xe820 */ v86.ecx = SMAP_BUFSIZE; v86.edx = SMAP_SIG; v86.es = VTOPSEG(&buf); v86.edi = VTOPOFF(&buf); v86int(); if (V86_CY(v86.efl) || v86.eax != SMAP_SIG || v86.ecx < sizeof(buf.smap) || v86.ecx > SMAP_BUFSIZE) break; next = malloc(sizeof(*next)); if (next == NULL) break; next->smap = buf.smap; if (v86.ecx == SMAP_BUFSIZE) { next->xattr = buf.xattr; x++; } STAILQ_INSERT_TAIL(&head, next, bufs); n++; } while (v86.ebx != 0); smaplen = n; if (smaplen > 0) { smapbase = malloc(smaplen * sizeof(*smapbase)); if (smapbase != NULL) { n = 0; STAILQ_FOREACH(cur, &head, bufs) smapbase[n++] = cur->smap; } if (smaplen == x) { smapattr = malloc(smaplen * sizeof(*smapattr)); if (smapattr != NULL) { n = 0; STAILQ_FOREACH(cur, &head, bufs) smapattr[n++] = cur->xattr & SMAP_XATTR_MASK; } } else smapattr = NULL; cur = STAILQ_FIRST(&head); while (cur != NULL) { next = STAILQ_NEXT(cur, bufs); free(cur); cur = next; } } }
void bios_getmem(void) { uint64_t size; /* Parse system memory map */ v86.ebx = 0; do { v86.ctl = V86_FLAGS; v86.addr = 0x15; /* int 0x15 function 0xe820*/ v86.eax = 0xe820; v86.ecx = sizeof(struct bios_smap); v86.edx = SMAP_SIG; v86.es = VTOPSEG(&smap); v86.edi = VTOPOFF(&smap); v86int(); if ((V86_CY(v86.efl)) || (v86.eax != SMAP_SIG)) break; /* look for a low-memory segment that's large enough */ if ((smap.type == SMAP_TYPE_MEMORY) && (smap.base == 0) && (smap.length >= (512 * 1024))) bios_basemem = smap.length; /* look for the first segment in 'extended' memory */ if ((smap.type == SMAP_TYPE_MEMORY) && (smap.base == 0x100000)) { bios_extmem = smap.length; } /* * Look for the largest segment in 'extended' memory beyond * 1MB but below 4GB. */ if ((smap.type == SMAP_TYPE_MEMORY) && (smap.base > 0x100000) && (smap.base < 0x100000000ull)) { size = smap.length; /* * If this segment crosses the 4GB boundary, truncate it. */ if (smap.base + size > 0x100000000ull) size = 0x100000000ull - smap.base; if (size > high_heap_size) { high_heap_size = size; high_heap_base = smap.base; } } } while (v86.ebx != 0); /* Fall back to the old compatibility function for base memory */ if (bios_basemem == 0) { v86.ctl = 0; v86.addr = 0x12; /* int 0x12 */ v86int(); bios_basemem = (v86.eax & 0xffff) * 1024; } /* Fall back through several compatibility functions for extended memory */ if (bios_extmem == 0) { v86.ctl = V86_FLAGS; v86.addr = 0x15; /* int 0x15 function 0xe801*/ v86.eax = 0xe801; v86int(); if (!(V86_CY(v86.efl))) { bios_extmem = ((v86.ecx & 0xffff) + ((v86.edx & 0xffff) * 64)) * 1024; } } if (bios_extmem == 0) { v86.ctl = 0; v86.addr = 0x15; /* int 0x15 function 0x88*/ v86.eax = 0x8800; v86int(); bios_extmem = (v86.eax & 0xffff) * 1024; } /* Set memtop to actual top of memory */ memtop = memtop_copyin = 0x100000 + bios_extmem; /* * If we have extended memory and did not find a suitable heap * region in the SMAP, use the last 3MB of 'extended' memory as a * high heap candidate. */ if (bios_extmem >= HEAP_MIN && high_heap_size < HEAP_MIN) { high_heap_size = HEAP_MIN; high_heap_base = memtop - HEAP_MIN; } }
void bios_getsmap(void) { int n; n = 0; smaplen = 0; /* Count up segments in system memory map */ v86.ebx = 0; do { v86.ctl = V86_FLAGS; v86.addr = 0x15; /* int 0x15 function 0xe820*/ v86.eax = 0xe820; v86.ecx = sizeof(struct smap); v86.edx = SMAPSIG; v86.es = VTOPSEG(&smap); v86.edi = VTOPOFF(&smap); v86int(); if ((v86.efl & 1) || (v86.eax != SMAPSIG)) break; n++; } while (v86.ebx != 0); if (n == 0) return; n += 10; /* spare room */ smapbase = malloc(n * sizeof(*smapbase)); /* Save system memory map */ v86.ebx = 0; do { v86.ctl = V86_FLAGS; v86.addr = 0x15; /* int 0x15 function 0xe820*/ v86.eax = 0xe820; v86.ecx = sizeof(struct smap); v86.edx = SMAPSIG; v86.es = VTOPSEG(&smap); v86.edi = VTOPOFF(&smap); v86int(); /* * Our heap is now in high memory and must be removed from * the smap so the kernel does not blow away passed-in * arguments, smap, kenv, etc. * * This wastes a little memory. */ if (smap.type == 1 && smap.base + smap.length > heapbase && smap.base < memtop) { if (smap.base <= heapbase) { if (heapbase - smap.base) { smapbase[smaplen] = smap; smapbase[smaplen].length = heapbase - smap.base; ++smaplen; } } if (smap.base + smap.length >= memtop) { if (smap.base + smap.length - memtop) { smapbase[smaplen] = smap; smapbase[smaplen].base = memtop; smapbase[smaplen].length = smap.base + smap.length - memtop; ++smaplen; } } } else { smapbase[smaplen] = smap; ++smaplen; } if ((v86.efl & 1) || (v86.eax != SMAPSIG)) break; } while (v86.ebx != 0 && smaplen < n); }