📄 rombios.c
字号:
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);}#define CMOS_SHUTDOWN_S3 0xFE//--------------------------------------------------------------------------// machine_reset//-------------------------------------------------------------------------- voidmachine_reset(){ASM_START;we must check whether CMOS_SHUTDOWN_S3 is set or not;if it is s3 resume, just jmp back to normal Post Entry;below port io will prevent s3 resume mov al, #0x0f out 0x70, al in al, 0x71 cmp al, #0xFE jz postASM_END /* 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 */ e.type = 3; 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++;#endif /* Remember how many devices we have */ write_word(IPL_SEG, IPL_COUNT_OFFSET, count); /* Not tried booting anything yet */ write_word(IPL_SEG, IPL_SEQUENCE_OFFSET, 0xffff);}static Bit8uget_boot_vector(i, e)Bit16u i; struct ipl_entry *e; { Bit16u count; Bit16u ss = get_SS(); /* Get the count of boot devices, and refuse to overrun the array */ count = read_word(IPL_SEG, IPL_COUNT_OFFSET); if (i >= count) return 0; /* OK to read this device */ memcpyb(ss, e, IPL_SEG, IPL_TABLE_OFFSET + i * sizeof (*e), sizeof (*e)); return 1;}//--------------------------------------------------------------------------// print_boot_device// displays the boot device//--------------------------------------------------------------------------static char drivetypes[][10]={"", "Floppy","Hard Disk","CD-Rom", "Network"};voidprint_boot_device(type) Bit16u type;{ /* NIC appears as type 0x80 */ if (type == 0x80 ) type = 0x4; if (type == 0 || type > 0x4) BX_PANIC("Bad drive type\n"); printf("Booting from %s...\n", drivetypes[type]);}//--------------------------------------------------------------------------// print_boot_failure// displays the reason why boot failed
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -