📄 rombios.c
字号:
/* data */#define UART_RBR 0x00#define UART_THR 0x00/* control */#define UART_IER 0x01#define UART_IIR 0x02#define UART_FCR 0x02#define UART_LCR 0x03#define UART_MCR 0x04#define UART_DLL 0x00#define UART_DLM 0x01/* status */#define UART_LSR 0x05#define UART_MSR 0x06#define UART_SCR 0x07int uart_can_tx_byte(base_port) Bit16u base_port;{ return inb(base_port + UART_LSR) & 0x20;}void uart_wait_to_tx_byte(base_port) Bit16u base_port;{ while (!uart_can_tx_byte(base_port));}void uart_wait_until_sent(base_port) Bit16u base_port;{ while (!(inb(base_port + UART_LSR) & 0x40));}void uart_tx_byte(base_port, data) Bit16u base_port; Bit8u data;{ uart_wait_to_tx_byte(base_port); outb(base_port + UART_THR, data); uart_wait_until_sent(base_port);}#endif voidwrch(c) Bit8u c;{ ASM_START push bp mov bp, sp push bx mov ah, #0x0e mov al, 4[bp] xor bx,bx int #0x10 pop bx pop bp ASM_END} voidsend(action, c) Bit16u action; Bit8u c;{#if BX_DEBUG_SERIAL if (c == '\n') uart_tx_byte(BX_DEBUG_PORT, '\r'); uart_tx_byte(BX_DEBUG_PORT, c);#endif#ifdef HVMASSIST outb(0xE9, c);#endif#if BX_VIRTUAL_PORTS if (action & BIOS_PRINTF_DEBUG) outb(DEBUG_PORT, c); if (action & BIOS_PRINTF_INFO) outb(INFO_PORT, c);#endif if (action & BIOS_PRINTF_SCREEN) { if (c == '\n') wrch('\r'); wrch(c); }} voidput_int(action, val, width, neg) Bit16u action; short val, width; bx_bool neg;{ short nval = val / 10; if (nval) put_int(action, nval, width - 1, neg); else { while (--width > 0) send(action, ' '); if (neg) send(action, '-'); } send(action, val - (nval * 10) + '0');} voidput_uint(action, val, width, neg) Bit16u action; unsigned short val; short width; bx_bool neg;{ unsigned short nval = val / 10; if (nval) put_uint(action, nval, width - 1, neg); else { while (--width > 0) send(action, ' '); if (neg) send(action, '-'); } send(action, val - (nval * 10) + '0');}//--------------------------------------------------------------------------// bios_printf()// A compact variable argument printf function which prints its output via// an I/O port so that it can be logged by Bochs/Plex. // Currently, only %x is supported (or %02x, %04x, etc).//// Supports %[format_width][format]// where format can be d,x,c,s//-------------------------------------------------------------------------- voidbios_printf(action, s) Bit16u action; Bit8u *s;{ Bit8u c, format_char; bx_bool in_format; short i; Bit16u *arg_ptr; Bit16u arg_seg, arg, nibble, shift_count, format_width; arg_ptr = &s; arg_seg = get_SS(); in_format = 0; format_width = 0; if ((action & BIOS_PRINTF_DEBHALT) == BIOS_PRINTF_DEBHALT) {#if BX_VIRTUAL_PORTS outb(PANIC_PORT2, 0x00);#endif bios_printf (BIOS_PRINTF_SCREEN, "FATAL: "); } while (c = read_byte(get_CS(), s)) { if ( c == '%' ) { in_format = 1; format_width = 0; } else if (in_format) { if ( (c>='0') && (c<='9') ) { format_width = (format_width * 10) + (c - '0'); } else { arg_ptr++; // increment to next arg arg = read_word(arg_seg, arg_ptr); if (c == 'x') { if (format_width == 0) format_width = 4; for (i=format_width-1; i>=0; i--) { nibble = (arg >> (4 * i)) & 0x000f; send (action, (nibble<=9)? (nibble+'0') : (nibble-10+'A')); } } else if (c == 'u') { put_uint(action, arg, format_width, 0); } else if (c == 'd') { if (arg & 0x8000) put_int(action, -arg, format_width - 1, 1); else put_int(action, arg, format_width, 0); } else if (c == 's') { bios_printf(action & (~BIOS_PRINTF_HALT), arg); } else if (c == 'c') { send(action, arg); } else BX_PANIC("bios_printf: unknown format\n"); in_format = 0; } } else { send(action, c); } s ++; } if (action & BIOS_PRINTF_HALT) { // freeze in a busy loop. ASM_START cli halt2_loop: hlt jmp halt2_loopASM_END }}//--------------------------------------------------------------------------// keyboard_init//--------------------------------------------------------------------------// this file is based on LinuxBIOS implementation of keyboard.c// could convert to #asm to gain space voidkeyboard_init(){ Bit16u max; /* ------------------- Flush buffers ------------------------*/ /* Wait until buffer is empty */ max=0xffff; while ( (inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x00); /* flush incoming keys */ max=0x2000; while (--max > 0) { outb(0x80, 0x00); if (inb(0x64) & 0x01) { inb(0x60); max = 0x2000; } } // Due to timer issues, and if the IPS setting is > 15000000, // the incoming keys might not be flushed here. That will // cause a panic a few lines below. See sourceforge bug report : // [ 642031 ] FATAL: Keyboard RESET error:993 /* ------------------- controller side ----------------------*/ /* send cmd = 0xAA, self test 8042 */ outb(0x64, 0xaa); /* Wait until buffer is empty */ max=0xffff; while ( (inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x00); if (max==0x0) keyboard_panic(00); /* Wait for data */ max=0xffff; while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x01); if (max==0x0) keyboard_panic(01); /* read self-test result, 0x55 should be returned from 0x60 */ if ((inb(0x60) != 0x55)){ keyboard_panic(991); } /* send cmd = 0xAB, keyboard interface test */ outb(0x64,0xab); /* Wait until buffer is empty */ max=0xffff; while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x10); if (max==0x0) keyboard_panic(10); /* Wait for data */ max=0xffff; while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x11); if (max==0x0) keyboard_panic(11); /* read keyboard interface test result, */ /* 0x00 should be returned form 0x60 */ if ((inb(0x60) != 0x00)) { keyboard_panic(992); } /* Enable Keyboard clock */ outb(0x64,0xae); outb(0x64,0xa8); /* ------------------- keyboard side ------------------------*/ /* reset kerboard and self test (keyboard side) */ outb(0x60, 0xff); /* Wait until buffer is empty */ max=0xffff; while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x20); if (max==0x0) keyboard_panic(20); /* Wait for data */ max=0xffff; while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x21); if (max==0x0) keyboard_panic(21); /* keyboard should return ACK */ if ((inb(0x60) != 0xfa)) { keyboard_panic(993); } /* Wait for data */ max=0xffff; while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x31); if (max==0x0) keyboard_panic(31); if ((inb(0x60) != 0xaa)) { keyboard_panic(994); } /* Disable keyboard */ outb(0x60, 0xf5); /* Wait until buffer is empty */ max=0xffff; while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x40); if (max==0x0) keyboard_panic(40); /* Wait for data */ max=0xffff; while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x41); if (max==0x0) keyboard_panic(41); /* keyboard should return ACK */ if ((inb(0x60) != 0xfa)) { keyboard_panic(995); } /* Write Keyboard Mode */ outb(0x64, 0x60); /* Wait until buffer is empty */ max=0xffff; while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x50); if (max==0x0) keyboard_panic(50); /* send cmd: scan code convert, disable mouse, enable IRQ 1 */ outb(0x60, 0x61); /* Wait until buffer is empty */ max=0xffff; while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x60); if (max==0x0) keyboard_panic(60); /* Enable keyboard */ outb(0x60, 0xf4); /* Wait until buffer is empty */ max=0xffff; while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x70); if (max==0x0) keyboard_panic(70); /* Wait for data */ max=0xffff; while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x71); if (max==0x0) keyboard_panic(70); /* keyboard should return ACK */ if ((inb(0x60) != 0xfa)) { keyboard_panic(996); } outb(0x80, 0x77);}//--------------------------------------------------------------------------// keyboard_panic//-------------------------------------------------------------------------- voidkeyboard_panic(status) Bit16u status;{ // If you're getting a 993 keyboard panic here, // please see the comment in keyboard_init BX_PANIC("Keyboard error:%u\n",status);}//--------------------------------------------------------------------------// machine_reset//-------------------------------------------------------------------------- voidmachine_reset(){ /* Frob the keyboard reset line to reset the processor */ outb(0x64, 0x60); /* Map the flags register at data port (0x60) */ outb(0x60, 0x14); /* Set the flags to system|disable */ outb(0x64, 0xfe); /* Pulse output 0 (system reset) low */ BX_PANIC("Couldn't reset the machine\n");}//--------------------------------------------------------------------------// clobber_entry_point// Because PV drivers in HVM guests detach some of the emulated devices, // it is not safe to do a soft reboot by just dropping to real mode and// jumping at ffff:0000. -- the boot drives might have disappeared!// This rather foul function overwrites(!) the BIOS entry point // to point at machine-reset, which will cause the Xen tools to// rebuild the whole machine from scratch.//-------------------------------------------------------------------------- void clobber_entry_point() { /* The instruction at the entry point is one byte (0xea) for the * jump opcode, then two bytes of address, then two of segment. * Overwrite the address bytes.*/ write_word(0xffff, 0x0001, machine_reset); }//--------------------------------------------------------------------------// shutdown_status_panic// called when the shutdown statsu is not implemented, displays the status//-------------------------------------------------------------------------- voidshutdown_status_panic(status) Bit16u status;{ BX_PANIC("Unimplemented shutdown status: %02x\n",(Bit8u)status);}//--------------------------------------------------------------------------// print_bios_banner// displays a the bios version//--------------------------------------------------------------------------voidprint_bios_banner(){ printf(BX_APPNAME" BIOS, %d cpu%s, ", BX_SMP_PROCESSORS, BX_SMP_PROCESSORS>1?"s":""); printf("%s %s\n", bios_cvs_version_string, bios_date_string);#if BX_TCGBIOS printf("TCG-enabled BIOS.\n");#endif printf("\n");}//--------------------------------------------------------------------------// BIOS Boot Specification 1.0.1 compatibility//// Very basic support for the BIOS Boot Specification, which allows expansion // ROMs to register themselves as boot devices, instead of just stealing the // INT 19h boot vector.// // This is a hack: to do it properly requires a proper PnP BIOS and we aren't// one; we just lie to the option ROMs to make them behave correctly. // We also don't support letting option ROMs register as bootable disk // drives (BCVs), only as bootable devices (BEVs). //// http://www.phoenix.com/en/Customer+Services/White+Papers-Specs/pc+industry+specifications.htm//--------------------------------------------------------------------------/* 256 bytes at 0x9ff00 -- 0x9ffff is used for the IPL boot table. */#define IPL_SEG 0x9ff0#define IPL_TABLE_OFFSET 0x0000#define IPL_TABLE_ENTRIES 8#define IPL_COUNT_OFFSET 0x0080 /* u16: number of valid table entries */#define IPL_SEQUENCE_OFFSET 0x0082 /* u16: next boot device */struct ipl_entry { Bit16u type; Bit16u flags; Bit32u vector; Bit32u description; Bit32u reserved;};static void init_boot_vectors() { struct ipl_entry e; Bit16u count = 0; Bit16u ss = get_SS(); /* Clear out the IPL table. */ memsetb(IPL_SEG, IPL_TABLE_OFFSET, 0, 0xff); /* Floppy drive */ e.type = 1; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0; memcpyb(IPL_SEG, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e)); count++; /* First HDD */ e.type = 2; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0; memcpyb(IPL_SEG, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e)); count++;#if BX_ELTORITO_BOOT /* CDROM */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -