[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [Patch][RFC] Update rombios.c
Akio Takebe wrote: > Hi, all > > This patch update rombios to the latest Bochs's. > I'd like to corabolate bochs community to enhance the guest bios. > I'm not familiar around TCGBIOS. > So could you review the patch? > > I tested boot/shutdown, S3 suspend/resume with linux guest. > Any comments are welcome :-) This attached file is diffs from the latest rombios of bochs. I hope it helps you at reviewing my patch. Best Regards, Akio Takebe --- rombios.bochs.c 2008-12-18 08:44:57.000000000 +0900 +++ rombios.c 2008-12-17 23:33:37.000000000 +0900 @@ -26,6 +26,18 @@ // ROM BIOS for use with Bochs/Plex86/QEMU emulation environment +#define uint8_t unsigned char +#define uint16_t unsigned short +#define uint32_t unsigned long +#include "../hvmloader/config.h" + +#define HVMASSIST +#undef HVMTEST + +// Xen full virtualization does not handle unaligned IO with page crossing. +// Disable 32-bit PIO as a workaround. +#undef NO_PIO32 + // ROM BIOS compatability entry points: // =================================== @@ -147,6 +159,8 @@ #define BX_USE_ATADRV 1 #define BX_ELTORITO_BOOT 1 +#define BX_TCGBIOS 0 /* main switch for TCG BIOS ext. */ + #define BX_MAX_ATA_INTERFACES 4 #define BX_MAX_ATA_DEVICES (BX_MAX_ATA_INTERFACES*2) @@ -170,18 +184,18 @@ #define BASE_MEM_IN_K (640 - EBDA_SIZE) /* 256 bytes at 0x9ff00 -- 0x9ffff is used for the IPL boot table. */ -#define IPL_SEG 0x9ff0 -#define IPL_TABLE_OFFSET 0x0000 +#define IPL_TABLE_OFFSET 0x0300 /* offset from EBDA */ #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 */ -#define IPL_BOOTFIRST_OFFSET 0x0084 /* u16: user selected device */ +#define IPL_COUNT_OFFSET 0x0380 /* u16: number of valid table entries */ +#define IPL_SEQUENCE_OFFSET 0x0382 /* u16: next boot device */ +#define IPL_BOOTFIRST_OFFSET 0x0384 /* u16: user selected device */ #define IPL_SIZE 0xff #define IPL_TYPE_FLOPPY 0x01 #define IPL_TYPE_HARDDISK 0x02 #define IPL_TYPE_CDROM 0x03 #define IPL_TYPE_BEV 0x80 + // Sanity Checks #if BX_USE_ATADRV && BX_CPU<3 # error The ATA/ATAPI Driver can only to be used with a 386+ cpu @@ -710,14 +724,18 @@ typedef struct { } cdemu_t; #endif // BX_ELTORITO_BOOT +#include "32bitgateway.h" + // for access to EBDA area // The EBDA structure should conform to // http://www.frontiernet.net/~fys/rombios.htm document // I made the ata and cdemu structs begin at 0x121 in the EBDA seg // EBDA must be at most 768 bytes; it lives at EBDA_SEG, and the boot - // device tables are at IPL_SEG + // device tables are at EBDA_SEG:IPL_TABLE_OFFSET typedef struct { - unsigned char filler1[0x3D]; + unsigned char ebda_size; + unsigned char cmos_shutdown_status; + unsigned char filler1[0x3B]; // FDPT - Can be splitted in data members if needed unsigned char fdpt0[0x10]; @@ -733,8 +751,10 @@ typedef struct { cdemu_t cdemu; #endif // BX_ELTORITO_BOOT + upcall_t upcall; } ebda_data_t; + #define EBDA_CMOS_SHUTDOWN_STATUS_OFFSET 1 #define EbdaData ((ebda_data_t *) 0) // for access to the int13ext structure @@ -863,6 +883,7 @@ static Bit16u read_word(); static void write_byte(); static void write_word(); static void bios_printf(); +static void copy_e820_table(); static Bit8u inhibit_mouse_int_and_events(); static void enable_mouse_int_and_events(); @@ -880,7 +901,7 @@ static void int14_function(); static void int15_function(); static void int16_function(); static void int17_function(); -static void int19_function(); +static void int18_function(); static void int1a_function(); static void int70_function(); static void int74_function(); @@ -1382,6 +1403,53 @@ ASM_START ASM_END } +#ifdef HVMASSIST +void +copy_e820_table() +{ + Bit8u nr_entries = read_byte(0x9000, 0x1e8); + Bit32u base_mem; + if (nr_entries > 32) + nr_entries = 32; + write_word(0xe000, 0x8, nr_entries); + memcpyb(0xe000, 0x10, 0x9000, 0x2d0, nr_entries * 0x14); + /* Report the proper base memory size at address 0x0413: otherwise + * non-e820 code will clobber things if BASE_MEM_IN_K is bigger than + * the first e820 entry. Get the size by reading the second 64bit + * field of the first e820 slot. */ + base_mem = read_dword(0x9000, 0x2d0 + 8); + write_word(0x40, 0x13, base_mem >> 10); +} + +void +set_rom_write_access(action) + Bit16u action; +{ + Bit16u off = (Bit16u)&((struct bios_info *)0)->xen_pfiob; +ASM_START + mov si,.set_rom_write_access.off[bp] + push ds + mov ax,#(ACPI_PHYSICAL_ADDRESS >> 4) + mov ds,ax + mov dx,[si] + pop ds + mov ax,.set_rom_write_access.action[bp] + out dx,al +ASM_END +} + +void enable_rom_write_access() +{ + set_rom_write_access(0); +} + +void disable_rom_write_access() +{ + set_rom_write_access(PFFLAG_ROM_LOCK); +} + +#endif /* HVMASSIST */ + #if BX_DEBUG_SERIAL /* serial debug port*/ #define BX_DEBUG_PORT 0x03f8 @@ -1460,6 +1528,9 @@ send(action, c) 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); @@ -1906,6 +1977,49 @@ keyboard_panic(status) BX_PANIC("Keyboard error:%u\n",status); } +#define CMOS_SHUTDOWN_S3 0xFE +//-------------------------------------------------------------------------- +// machine_reset +//-------------------------------------------------------------------------- + void +machine_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 post +ASM_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 @@ -1944,6 +2058,9 @@ print_bios_banner() #if BX_ROMBIOS32 "rombios32 " #endif +#if BX_TCGBIOS + "TCG-enabled" +#endif "\n\n"); } @@ -1970,34 +2087,35 @@ init_boot_vectors() ipl_entry_t e; Bit16u count = 0; Bit16u ss = get_SS(); + Bit16u ebda_seg = read_word(0x0040, 0x000E); /* Clear out the IPL table. */ - memsetb(IPL_SEG, IPL_TABLE_OFFSET, 0, IPL_SIZE); + memsetb(ebda_seg, IPL_TABLE_OFFSET, 0, IPL_SIZE); /* User selected device not set */ - write_word(IPL_SEG, IPL_BOOTFIRST_OFFSET, 0xFFFF); + write_word(ebda_seg, IPL_BOOTFIRST_OFFSET, 0xFFFF); /* Floppy drive */ e.type = IPL_TYPE_FLOPPY; 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)); + memcpyb(ebda_seg, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e)); count++; /* First HDD */ e.type = IPL_TYPE_HARDDISK; 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)); + memcpyb(ebda_seg, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e)); count++; #if BX_ELTORITO_BOOT /* CDROM */ e.type = IPL_TYPE_CDROM; 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)); + memcpyb(ebda_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); + write_word(ebda_seg, IPL_COUNT_OFFSET, count); /* Not tried booting anything yet */ - write_word(IPL_SEG, IPL_SEQUENCE_OFFSET, 0xffff); + write_word(ebda_seg, IPL_SEQUENCE_OFFSET, 0xffff); } static Bit8u @@ -2006,11 +2124,12 @@ Bit16u i; ipl_entry_t *e; { Bit16u count; Bit16u ss = get_SS(); + Bit16u ebda_seg = read_word(0x0040, 0x000E); /* Get the count of boot devices, and refuse to overrun the array */ - count = read_word(IPL_SEG, IPL_COUNT_OFFSET); + count = read_word(ebda_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)); + memcpyb(ss, e, ebda_seg, IPL_TABLE_OFFSET + i * sizeof (*e), sizeof (*e)); return 1; } @@ -2025,11 +2144,12 @@ interactive_bootkey() Bit8u i; Bit16u ss = get_SS(); Bit16u valid_choice = 0; + Bit16u ebda_seg = read_word(0x0040, 0x000E); while (check_for_keystroke()) get_keystroke(); - printf("Press F12 for boot menu.\n\n"); + printf("\nPress F12 for boot menu.\n\n"); delay_ticks_and_check_for_keystroke(11, 5); /* ~3 seconds */ if (check_for_keystroke()) @@ -2042,10 +2162,10 @@ interactive_bootkey() printf("Select boot device:\n\n"); - count = read_word(IPL_SEG, IPL_COUNT_OFFSET); + count = read_word(ebda_seg, IPL_COUNT_OFFSET); for (i = 0; i < count; i++) { - memcpyb(ss, &e, IPL_SEG, IPL_TABLE_OFFSET + i * sizeof (e), sizeof (e)); + memcpyb(ss, &e, ebda_seg, IPL_TABLE_OFFSET + i * sizeof (e), sizeof (e)); printf("%d. ", i+1); switch(e.type) { @@ -2079,7 +2199,7 @@ interactive_bootkey() valid_choice = 1; scan_code -= 1; /* Set user selected device */ - write_word(IPL_SEG, IPL_BOOTFIRST_OFFSET, scan_code); + write_word(ebda_seg, IPL_BOOTFIRST_OFFSET, scan_code); } } printf("\n"); @@ -2126,7 +2246,7 @@ print_boot_failure(type, reason) { if (type == 0 || type > 0x3) BX_PANIC("Bad drive type\n"); - printf("Boot failed"); + printf("Boot from %s failed", drivetypes[type]); if (type < 4) { /* Report the reason too */ if (reason==0) @@ -2210,10 +2330,14 @@ s3_resume() Bit8u s3_resume_flag; s3_resume_flag = read_byte(0x40, 0xb0); +#ifdef HVMASSIST + s3_wakeup_vector = get_s3_waking_vector(); +#else s3_wakeup_vector = read_dword(0x40, 0xb2); +#endif BX_INFO("S3 resume called %x 0x%lx\n", s3_resume_flag, s3_wakeup_vector); - if (s3_resume_flag != 0xFE || !s3_wakeup_vector) + if (s3_resume_flag != CMOS_SHUTDOWN_S3 || !s3_wakeup_vector) return 0; write_byte(0x40, 0xb0, 0); @@ -2572,6 +2696,9 @@ void ata_detect( ) Bit16u cylinders, heads, spt, blksize; Bit8u translation, removable, mode; + // default mode to PIO16 + mode = ATA_MODE_PIO16; + //Temporary values to do the transfer write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_HD); write_byte(ebda_seg,&EbdaData->ata.devices[device].mode, ATA_MODE_PIO16); @@ -2580,7 +2707,9 @@ void ata_detect( ) BX_PANIC("ata-detect: Failed to detect ATA device\n"); removable = (read_byte(get_SS(),buffer+0) & 0x80) ? 1 : 0; +#ifndef NO_PIO32 mode = read_byte(get_SS(),buffer+96) ? ATA_MODE_PIO32 : ATA_MODE_PIO16; +#endif blksize = read_word(get_SS(),buffer+10); cylinders = read_word(get_SS(),buffer+(1*2)); // word 1 @@ -2677,6 +2806,9 @@ void ata_detect( ) Bit8u type, removable, mode; Bit16u blksize; + // default mode to PIO16 + mode = ATA_MODE_PIO16; + //Temporary values to do the transfer write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_CDROM); write_byte(ebda_seg,&EbdaData->ata.devices[device].mode, ATA_MODE_PIO16); @@ -2686,7 +2818,9 @@ void ata_detect( ) type = read_byte(get_SS(),buffer+1) & 0x1f; removable = (read_byte(get_SS(),buffer+0) & 0x80) ? 1 : 0; +#ifndef NO_PIO32 mode = read_byte(get_SS(),buffer+96) ? ATA_MODE_PIO32 : ATA_MODE_PIO16; +#endif blksize = 2048; write_byte(ebda_seg,&EbdaData->ata.devices[device].device, type); @@ -3651,6 +3785,13 @@ cdrom_boot() // Initial/Default Entry if(buffer[0x20]!=0x88)return 11; // Bootable +#if BX_TCGBIOS + /* specs: 8.2.3 step 5 and 8.2.5.6, measure El Torito boot catalog */ + /* measure 2048 bytes (one sector) */ + tcpa_add_bootdevice((Bit32u)1L, (Bit32u)0L); /* bootcd = 1 */ + tcpa_ipl((Bit32u)2L,(Bit32u)get_SS(),(Bit32u)buffer,(Bit32u)2048L); +#endif + write_byte(ebda_seg,&EbdaData->cdemu.media,buffer[0x21]); if(buffer[0x21]==0){ // FIXME ElTorito Hardcoded. cdrom is hardcoded as device 0xE0. @@ -3689,6 +3830,12 @@ cdrom_boot() if((error = ata_cmd_packet(device, 12, get_SS(), atacmd, 0, nbsectors*512L, ATA_DATA_IN, boot_segment,0)) != 0) return 12; +#if BX_TCGBIOS + /* specs: 8.2.3 step 4 and 8.2.5.6, measure El Torito boot image */ + /* measure 1st 512 bytes */ + tcpa_ipl((Bit32u)1L,(Bit32u)boot_segment,(Bit32u)0L,(Bit32u)512L); +#endif + // Remember the media type switch(read_byte(ebda_seg,&EbdaData->cdemu.media)) { case 0x01: // 1.2M floppy @@ -4487,11 +4634,9 @@ ASM_START ;; Get the count in eax mov bx, sp - SEG SS - mov ax, _int15_function32.CX [bx] + mov ax, _int15_function32.CX [bx] shl eax, #16 - SEG SS - mov ax, _int15_function32.DX [bx] + mov ax, _int15_function32.DX [bx] ;; convert to numbers of 15usec ticks mov ebx, #15 @@ -4522,6 +4667,97 @@ ASM_END case 0xe8: switch(regs.u.r8.al) { +#ifdef HVMASSIST + case 0x20: { + Bit16u e820_table_size = read_word(0xe000, 0x8) * 0x14; + + if (regs.u.r32.edx != 0x534D4150) /* SMAP */ + goto int15_unimplemented; + + if ((regs.u.r16.bx / 0x14) * 0x14 == regs.u.r16.bx) { + if (regs.u.r16.bx + 0x14 <= e820_table_size) + memcpyb(ES, regs.u.r16.di, + 0xe000, 0x10 + regs.u.r16.bx, 0x14); + regs.u.r32.ebx += 0x14; + if ((regs.u.r32.ebx + 0x14 - 1) > e820_table_size) + regs.u.r32.ebx = 0; + } else if (regs.u.r16.bx == 1) { + Bit32u base, type; + Bit16u off; + for (off = 0; off < e820_table_size; off += 0x14) { + base = read_dword(0xe000, 0x10 + off); + type = read_dword(0xe000, 0x20 + off); + if ((base >= 0x100000) && (type == 1)) + break; + } + if (off == e820_table_size) { + SET_CF(); + break; + } + memcpyb(ES, regs.u.r16.di, 0xe000, 0x10 + off, 0x14); + regs.u.r32.ebx = 0; + } else { /* AX=E820, DX=534D4150, BX unrecognized */ + goto int15_unimplemented; + } + + regs.u.r32.eax = 0x534D4150; + regs.u.r32.ecx = 0x14; + CLEAR_CF(); + break; + } + + case 0x01: { + Bit16u off, e820_table_size = read_word(0xe000, 0x8) * 0x14; + Bit32u base, type, size; + + // do we have any reason to fail here ? + CLEAR_CF(); + + // Get the amount of extended memory (above 1M) + regs.u.r8.cl = inb_cmos(0x30); + regs.u.r8.ch = inb_cmos(0x31); + + // limit to 15M + if (regs.u.r16.cx > (15*1024)) + regs.u.r16.cx = 15*1024; + + // Find first RAM E820 entry >= 1MB. + for (off = 0; off < e820_table_size; off += 0x14) { + base = read_dword(0xe000, 0x10 + off); + type = read_dword(0xe000, 0x20 + off); + if ((base >= 0x100000) && (type == 1)) + break; + } + + // If there is RAM above 16MB, return amount in 64kB chunks. + regs.u.r16.dx = 0; + if (off != e820_table_size) { + size = base + read_dword(0xe000, 0x18 + off); + if (size > 0x1000000) { + size -= 0x1000000; + regs.u.r16.dx = (Bit16u)(size >> 16); + } + } + + // Set configured memory equal to extended memory + regs.u.r16.ax = regs.u.r16.cx; + regs.u.r16.bx = regs.u.r16.dx; + break; + } + default: /* AH=0xE8?? but not implemented */ + goto int15_unimplemented; + } + break; + int15_unimplemented: + // fall into the default + default: + BX_INFO("*** int 15h function AX=%04x, BX=%04x not yet supported!\n", + (unsigned) regs.u.r16.ax, (unsigned) regs.u.r16.bx); + SET_CF(); + regs.u.r8.ah = UNSUPPORTED_FUNCTION; + break; + } +#else case 0x20: // coded by osmaker aka K.J. if(regs.u.r32.edx == 0x534D4150) { @@ -4661,6 +4897,7 @@ ASM_END regs.u.r8.ah = UNSUPPORTED_FUNCTION; break; } +#endif /* HVMASSIST */ } void @@ -5071,6 +5308,10 @@ int09_function(DI, SI, BP, SP, BX, DX, C write_byte(0x0040, 0x18, mf2_flags); break; + case 0x53: /* Del */ + if ((shift_flags & 0x0c) == 0x0c) /* Ctrl + Alt */ + machine_reset(); + /* Fall through */ default: if (scancode & 0x80) { break; /* toss key releases ... */ @@ -7971,7 +8212,7 @@ int17_function(regs, ds, iret_addr) } void -int19_function(seq_nr) +int18_function(seq_nr) Bit16u seq_nr; { Bit16u ebda_seg=read_word(0x0040,0x000E); @@ -8011,13 +8252,13 @@ Bit16u seq_nr; bootdev &= 0xf; /* Read user selected device */ - bootfirst = read_word(IPL_SEG, IPL_BOOTFIRST_OFFSET); + bootfirst = read_word(ebda_seg, IPL_BOOTFIRST_OFFSET); if (bootfirst != 0xFFFF) { bootdev = bootfirst; /* User selected device not set */ - write_word(IPL_SEG, IPL_BOOTFIRST_OFFSET, 0xFFFF); + write_word(ebda_seg, IPL_BOOTFIRST_OFFSET, 0xFFFF); /* Reset boot sequence */ - write_word(IPL_SEG, IPL_SEQUENCE_OFFSET, 0xFFFF); + write_word(ebda_seg, IPL_SEQUENCE_OFFSET, 0xFFFF); } else if (bootdev == 0) BX_PANIC("No bootable device.\n"); /* Translate from CMOS runes to an IPL table offset by subtracting 1 */ @@ -8057,8 +8298,8 @@ ASM_START push cx push dx - mov dl, _int19_function.bootdrv + 2[bp] - mov ax, _int19_function.bootseg + 2[bp] + mov dl, _int18_function.bootdrv + 2[bp] + mov ax, _int18_function.bootseg + 2[bp] mov es, ax ;; segment xor bx, bx ;; offset mov ah, #0x02 ;; function 2, read diskette sector @@ -8069,7 +8310,7 @@ ASM_START int #0x13 ;; read sector jnc int19_load_done mov ax, #0x0001 - mov _int19_function.status + 2[bp], ax + mov _int18_function.status + 2[bp], ax int19_load_done: pop dx @@ -8093,6 +8334,11 @@ ASM_END } } +#if BX_TCGBIOS + tcpa_add_bootdevice((Bit32u)0L, (Bit32u)bootdrv); + tcpa_ipl((Bit32u)0L,(Bit32u)bootseg,(Bit32u)0L,(Bit32u)512L); /* specs: 8.2.3 steps 4 and 5 */ +#endif + /* Canonicalize bootseg:bootip */ bootip = (bootseg & 0x0fff) << 4; bootseg &= 0xf000; @@ -8111,7 +8357,10 @@ ASM_END bootdrv = (Bit8u)(status>>8); bootseg = read_word(ebda_seg,&EbdaData->cdemu.load_segment); - bootip = 0; + + /* Canonicalize bootseg:bootip */ + bootip = (bootseg & 0x0fff) << 4; + bootseg &= 0xf000; break; #endif @@ -8129,18 +8378,18 @@ ASM_END /* Jump to the boot vector */ ASM_START mov bp, sp - push cs - push #int18_handler +// push cs +// push #int18_handler ;; Build an iret stack frame that will take us to the boot vector. ;; iret pops ip, then cs, then flags, so push them in the opposite order. pushf - mov ax, _int19_function.bootseg + 0[bp] + mov ax, _int18_function.bootseg + 0[bp] push ax - mov ax, _int19_function.bootip + 0[bp] + mov ax, _int18_function.bootip + 0[bp] push ax ;; Set the magic number in ax and the boot drive in dl. mov ax, #0xaa55 - mov dl, _int19_function.bootdrv + 0[bp] + mov dl, _int18_function.bootdrv + 0[bp] ;; Zero some of the other registers. xor bx, bx mov ds, bx @@ -8625,51 +8874,47 @@ int18_handler: ;; Boot Failure recovery: xor ax, ax mov ss, ax - ;; Get the boot sequence number out of the IPL memory - mov bx, #IPL_SEG + ;; The first time we do this it will have been set to -1 so + ;; we will start from device 0. + mov ds, ax + mov bx, word ptr [0x40E] ;; EBDA segment mov ds, bx ;; Set segment mov bx, IPL_SEQUENCE_OFFSET ;; BX is now the sequence number inc bx ;; ++ mov IPL_SEQUENCE_OFFSET, bx ;; Write it back mov ds, ax ;; and reset the segment to zero. - ;; Carry on in the INT 19h handler, using the new sequence number + ;; Call the C code for the next boot device push bx - jmp int19_next_boot + call _int18_function + + ;; Boot failed: invoke the boot recovery function... + int #0x18 ;---------- ;- INT19h - ;---------- int19_relocated: ;; Boot function, relocated - ;; int19 was beginning to be really complex, so now it - ;; just calls a C function that does the work - - push bp - mov bp, sp + ;; + ;; *** Warning: INT 19h resets the whole machine *** + ;; + ;; 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 + ;; invoking INT 19h -- the boot drives might have disappeared! + ;; If the user asks for a soft reboot, the only thing we can do is + ;; reset the whole machine. When it comes back up, the normal BIOS + ;; boot sequence will start, which is more or less the required behaviour. + ;; + ;; Reset SP and SS - ;; Reset SS and SP mov ax, #0xfffe mov sp, ax xor ax, ax mov ss, ax - ;; Start from the first boot device (0, in AX) - mov bx, #IPL_SEG - mov ds, bx ;; Set segment to write to the IPL memory - mov IPL_SEQUENCE_OFFSET, ax ;; Save the sequence number - mov ds, ax ;; and reset the segment. - - push ax - -int19_next_boot: - - ;; Call the C code for the next boot device - call _int19_function - - ;; Boot failed: invoke the boot recovery function - int #0x18 + call _machine_reset ;---------- ;- INT1Ch - @@ -8779,8 +9024,8 @@ hard_drive_post: SET_INT_VECTOR(0x76, #0xF000, #int76_handler) ;; INT 41h: hard disk 0 configuration pointer ;; INT 46h: hard disk 1 configuration pointer - SET_INT_VECTOR(0x41, #EBDA_SEG, #0x003D) - SET_INT_VECTOR(0x46, #EBDA_SEG, #0x004D) + SET_INT_VECTOR(0x41, word ptr [0x40E], #0x003D) /* EBDA:003D */ + SET_INT_VECTOR(0x46, word ptr [0x40E], #0x004D) /* EBDA:004D */ ;; move disk geometry data from CMOS to EBDA disk parameter table(s) mov al, #0x12 @@ -8809,7 +9054,9 @@ post_d0_type47: ;; 22 landing zone high D ;; 23 sectors/track E - mov ax, #EBDA_SEG + xor ax, ax + mov ds, ax + mov ax, word ptr [0x40E] ;; EBDA segment mov ds, ax ;;; Filling EBDA table for hard disk 0. @@ -8955,7 +9202,9 @@ post_d1_type47: ;; 0x2b landing zone high D ;; 0x2c sectors/track E ;;; Fill EBDA table for hard disk 1. - mov ax, #EBDA_SEG + xor ax, ax + mov ds, ax + mov ax, word ptr [0x40E] ;; EBDA segment mov ds, ax mov al, #0x28 out #0x70, al @@ -9255,6 +9504,10 @@ use16 386 #endif +ASM_END +#include "32bitgateway.c" +ASM_START + ;-------------------- #if BX_PCIBIOS use32 386 @@ -9696,79 +9949,79 @@ pci_routing_table_structure_start: ;; first slot entry PCI-to-ISA (embedded) db 0 ;; pci bus number db 0x08 ;; pci device number (bit 7-3) - db 0x60 ;; link value INTA#: pointer into PCI2ISA config space - dw 0xdef8 ;; IRQ bitmap INTA# - db 0x61 ;; link value INTB# - dw 0xdef8 ;; IRQ bitmap INTB# - db 0x62 ;; link value INTC# - dw 0xdef8 ;; IRQ bitmap INTC# - db 0x63 ;; link value INTD# - dw 0xdef8 ;; IRQ bitmap INTD# - db 0 ;; physical slot (0 = embedded) - db 0 ;; reserved - ;; second slot entry: 1st PCI slot - db 0 ;; pci bus number - db 0x10 ;; pci device number (bit 7-3) - db 0x61 ;; link value INTA# - dw 0xdef8 ;; IRQ bitmap INTA# + db 0x61 ;; link value INTA#: pointer into PCI2ISA config space + dw 0x0c20 ;; IRQ bitmap INTA# db 0x62 ;; link value INTB# - dw 0xdef8 ;; IRQ bitmap INTB# + dw 0x0c20 ;; IRQ bitmap INTB# db 0x63 ;; link value INTC# - dw 0xdef8 ;; IRQ bitmap INTC# + dw 0x0c20 ;; IRQ bitmap INTC# db 0x60 ;; link value INTD# - dw 0xdef8 ;; IRQ bitmap INTD# - db 1 ;; physical slot (0 = embedded) + dw 0x0c20 ;; IRQ bitmap INTD# + db 0 ;; physical slot (0 = embedded) db 0 ;; reserved - ;; third slot entry: 2nd PCI slot + ;; second slot entry: 1st PCI slot db 0 ;; pci bus number - db 0x18 ;; pci device number (bit 7-3) + db 0x10 ;; pci device number (bit 7-3) db 0x62 ;; link value INTA# - dw 0xdef8 ;; IRQ bitmap INTA# + dw 0x0c20 ;; IRQ bitmap INTA# db 0x63 ;; link value INTB# - dw 0xdef8 ;; IRQ bitmap INTB# + dw 0x0c20 ;; IRQ bitmap INTB# db 0x60 ;; link value INTC# - dw 0xdef8 ;; IRQ bitmap INTC# + dw 0x0c20 ;; IRQ bitmap INTC# db 0x61 ;; link value INTD# - dw 0xdef8 ;; IRQ bitmap INTD# - db 2 ;; physical slot (0 = embedded) + dw 0x0c20 ;; IRQ bitmap INTD# + db 1 ;; physical slot (0 = embedded) db 0 ;; reserved - ;; 4th slot entry: 3rd PCI slot + ;; third slot entry: 2nd PCI slot db 0 ;; pci bus number - db 0x20 ;; pci device number (bit 7-3) + db 0x18 ;; pci device number (bit 7-3) db 0x63 ;; link value INTA# - dw 0xdef8 ;; IRQ bitmap INTA# + dw 0x0c20 ;; IRQ bitmap INTA# db 0x60 ;; link value INTB# - dw 0xdef8 ;; IRQ bitmap INTB# + dw 0x0c20 ;; IRQ bitmap INTB# db 0x61 ;; link value INTC# - dw 0xdef8 ;; IRQ bitmap INTC# + dw 0x0c20 ;; IRQ bitmap INTC# db 0x62 ;; link value INTD# - dw 0xdef8 ;; IRQ bitmap INTD# - db 3 ;; physical slot (0 = embedded) + dw 0x0c20 ;; IRQ bitmap INTD# + db 2 ;; physical slot (0 = embedded) db 0 ;; reserved - ;; 5th slot entry: 4rd PCI slot + ;; 4th slot entry: 3rd PCI slot db 0 ;; pci bus number - db 0x28 ;; pci device number (bit 7-3) + db 0x20 ;; pci device number (bit 7-3) db 0x60 ;; link value INTA# - dw 0xdef8 ;; IRQ bitmap INTA# + dw 0x0c20 ;; IRQ bitmap INTA# db 0x61 ;; link value INTB# - dw 0xdef8 ;; IRQ bitmap INTB# + dw 0x0c20 ;; IRQ bitmap INTB# db 0x62 ;; link value INTC# - dw 0xdef8 ;; IRQ bitmap INTC# + dw 0x0c20 ;; IRQ bitmap INTC# db 0x63 ;; link value INTD# - dw 0xdef8 ;; IRQ bitmap INTD# - db 4 ;; physical slot (0 = embedded) + dw 0x0c20 ;; IRQ bitmap INTD# + db 3 ;; physical slot (0 = embedded) db 0 ;; reserved - ;; 6th slot entry: 5rd PCI slot + ;; 5th slot entry: 4rd PCI slot db 0 ;; pci bus number - db 0x30 ;; pci device number (bit 7-3) + db 0x28 ;; pci device number (bit 7-3) db 0x61 ;; link value INTA# - dw 0xdef8 ;; IRQ bitmap INTA# + dw 0x0c20 ;; IRQ bitmap INTA# db 0x62 ;; link value INTB# - dw 0xdef8 ;; IRQ bitmap INTB# + dw 0x0c20 ;; IRQ bitmap INTB# db 0x63 ;; link value INTC# - dw 0xdef8 ;; IRQ bitmap INTC# + dw 0x0c20 ;; IRQ bitmap INTC# db 0x60 ;; link value INTD# - dw 0xdef8 ;; IRQ bitmap INTD# + dw 0x0c20 ;; IRQ bitmap INTD# + db 4 ;; physical slot (0 = embedded) + db 0 ;; reserved + ;; 6th slot entry: 5rd PCI slot + db 0 ;; pci bus number + db 0x30 ;; pci device number (bit 7-3) + db 0x62 ;; link value INTA# + dw 0x0c20 ;; IRQ bitmap INTA# + db 0x63 ;; link value INTB# + dw 0x0c20 ;; IRQ bitmap INTB# + db 0x60 ;; link value INTC# + dw 0x0c20 ;; IRQ bitmap INTC# + db 0x61 ;; link value INTD# + dw 0x0c20 ;; IRQ bitmap INTD# db 5 ;; physical slot (0 = embedded) db 0 ;; reserved pci_routing_table_structure_end: @@ -10185,7 +10438,6 @@ checksum_loop: pnp_string: .ascii "$PnP" - rom_scan: ;; Scan for existence of valid expansion ROMS. ;; Video ROM: from 0xC0000..0xC7FFF in 2k increments @@ -10199,6 +10451,10 @@ rom_scan: ;; 2 ROM length in 512-byte blocks ;; 3 ROM initialization entry point (FAR CALL) +#if BX_TCGBIOS + call _tcpa_start_option_rom_scan /* specs: 3.2.3.3 + 10.4.3 */ +#endif + rom_scan_loop: push ax ;; Save AX mov ds, cx @@ -10219,18 +10475,49 @@ block_count_rounded: xor bx, bx ;; Restore DS back to 0000: mov ds, bx +#if BX_TCGBIOS + push ax + push ds + push ecx + xor ax, ax + mov ds, ax + and ecx, #0xffff + push ecx ;; segment where option rom is located at + call _tcpa_option_rom /* specs: 3.2.3.3 */ + add sp, #4 ;; pop segment + pop ecx ;; original ecx + pop ds + pop ax +#endif push ax ;; Save AX push di ;; Save DI ;; Push addr of ROM entry point push cx ;; Push seg push #0x0003 ;; Push offset + ;; Get the BDF into ax before invoking the option ROM + mov bl, [2] + mov al, bl + shr al, #7 + cmp al, #1 + jne fetch_bdf + mov ax, ds ;; Increment the DS since rom size larger than an segment + add ax, #0x1000 + mov ds, ax +fetch_bdf: + shl bx, #9 + xor ax, ax + mov al, [bx] + ;; Point ES:DI at "$PnP", which tells the ROM that we are a PnP BIOS. ;; That should stop it grabbing INT 19h; we will use its BEV instead. - mov ax, #0xf000 - mov es, ax + mov bx, #0xf000 + mov es, bx lea di, pnp_string + xor bx, bx ;; Restore DS back to 0000: + mov ds, bx + mov bp, sp ;; Call ROM init routine using seg:off on stack db 0xff ;; call_far ss:[bp+0] db 0x5e @@ -10250,21 +10537,47 @@ block_count_rounded: mov ax, 2[bx] cmp ax, #0x506e jne no_bev + + mov ax, 0x16[bx] ;; 0x16 is the offset of Boot Connection Vector + cmp ax, #0x0000 + je no_bcv + + ;; Option ROM has BCV. Run it now. + push cx ;; Push seg + push ax ;; Push offset + + ;; Point ES:DI at "$PnP", which tells the ROM that we are a PnP BIOS. + mov bx, #0xf000 + mov es, bx + lea di, pnp_string + /* jump to BCV function entry pointer */ + mov bp, sp ;; Call ROM BCV routine using seg:off on stack + db 0xff ;; call_far ss:[bp+0] + db 0x5e + db 0 + cli ;; In case expansion ROM BIOS turns IF on + add sp, #2 ;; Pop offset value + pop cx ;; Pop seg value (restore CX) + jmp no_bev + +no_bcv: mov ax, 0x1a[bx] ;; 0x1A is also the offset into the expansion header of... cmp ax, #0x0000 ;; the Bootstrap Entry Vector, or zero if there is none. je no_bev ;; Found a device that thinks it can boot the system. Record its BEV and product name string. mov di, 0x10[bx] ;; Pointer to the product name string or zero if none - mov bx, #IPL_SEG ;; Go to the segment where the IPL table lives + xor bx, bx mov ds, bx + mov bx, word ptr [0x40E] ;; EBDA segment + mov ds, bx ;; Go to the segment where the IPL table lives mov bx, IPL_COUNT_OFFSET ;; Read the number of entries so far cmp bx, #IPL_TABLE_ENTRIES je no_bev ;; Get out if the table is full shl bx, #0x4 ;; Turn count into offset (entries are 16 bytes) - mov 0[bx], #IPL_TYPE_BEV ;; This entry is a BEV device - mov 6[bx], cx ;; Build a far pointer from the segment... - mov 4[bx], ax ;; and the offset + mov IPL_TABLE_OFFSET+0[bx], #IPL_TYPE_BEV ;; This entry is a BEV device + mov IPL_TABLE_OFFSET+6[bx], cx ;; Build a far pointer from the segment... + mov IPL_TABLE_OFFSET+4[bx], ax ;; and the offset cmp di, #0x0000 je no_prod_str mov 0xA[bx], cx ;; Build a far pointer from the segment... @@ -10289,6 +10602,64 @@ rom_scan_increment: mov ds, ax ret +#ifdef HVMASSIST + +; Copy the SMBIOS entry point from where hvmloader left it. +; The entry point must be somewhere in 0xf0000-0xfffff on a 16-byte boundary, +; but the tables themselves can be elsewhere. +smbios_init: + push ax + push cx + push es + push ds + push di + push si + + mov cx, #0x001f ; 0x1f bytes to copy + mov ax, #0xf000 + mov es, ax ; destination segment is 0xf0000 + mov di, #smbios_entry_point ; destination offset + mov ax, #(SMBIOS_PHYSICAL_ADDRESS>>4) + mov ds, ax + mov si, #(SMBIOS_PHYSICAL_ADDRESS&15) + cld + rep + movsb + + pop si + pop di + pop ds + pop es + pop cx + pop ax + + ret + +#endif + +#if BX_TCGBIOS +; The section between the POST entry and the NMI entry is filling up +; and causes crashes if this code was directly there +tcpa_post_part1: + call _tcpa_acpi_init + + push dword #0 + call _tcpa_initialize_tpm + add sp, #4 + + call _tcpa_do_measure_POSTs + call _tcpa_wake_event /* specs: 3.2.3.7 */ + ret + +tcpa_post_part2: + call _tcpa_calling_int19h /* specs: 8.2.3 step 1 */ + call _tcpa_add_event_separators /* specs: 8.2.3 step 2 */ + /* we do not call int 19h handler but keep following eventlog */ + call _tcpa_returned_int19h /* specs: 8.2.3 step 3/7 */ + ret +#endif + + post_init_pic: mov al, #0x11 ; send initialisation commands out 0x20, al @@ -10483,9 +10854,16 @@ post_default_ints: ;; int 1C already points at dummy_iret_handler (above) mov al, #0x34 ; timer0: binary count, 16bit count, mode 2 out 0x43, al +#ifdef HVMASSIST + mov al, #0x0b ; #0xe90b = 20 Hz (temporary, until we fix xen/vmx support) + out 0x40, al ; lsb + mov al, #0xe9 + out 0x40, al ; msb +#else mov al, #0x00 ; maximum count of 0000H = 18.2Hz out 0x40, al out 0x40, al +#endif ;; Keyboard SET_INT_VECTOR(0x09, #0xF000, #int09_handler) @@ -10527,6 +10905,9 @@ post_default_ints: in al, 0x71 mov 0x0410, ax +#if BX_TCGBIOS + call tcpa_post_part1 +#endif ;; Parallel setup SET_INT_VECTOR(0x0F, #0xF000, #dummy_iret_handler) @@ -10626,6 +11007,14 @@ post_default_ints: ;; #endif // BX_ELTORITO_BOOT +#ifdef HVMASSIST + call _enable_rom_write_access + call _clobber_entry_point + call _copy_e820_table + call smbios_init + call _disable_rom_write_access +#endif + call _init_boot_vectors mov cx, #0xc800 ;; init option roms @@ -10636,8 +11025,14 @@ post_default_ints: call _interactive_bootkey #endif // BX_ELTORITO_BOOT +#if BX_TCGBIOS + call tcpa_post_part2 +#endif + sti ;; enable interrupts - int #0x19 + ;; Start the boot sequence. See the comments in int19_relocated + ;; for why we use INT 18h instead of INT 19h here. + int #0x18 .org 0xe2c3 ; NMI Handler Entry Point nmi: @@ -11118,6 +11513,21 @@ db 0x00 ;; base 23:16 ;---------- .org 0xfe6e ; INT 1Ah Time-of-day Service Entry Point int1a_handler: +#if BX_TCGBIOS + cmp ah, #0xbb + jne no_tcg + pushf + push ds + push es + pushad + call _int1a_function32 + popad + pop es + pop ds + popf + iret +no_tcg: +#endif #if BX_PCIBIOS cmp ah, #0xb1 jne int1a_normal @@ -11224,8 +11634,17 @@ dummy_iret_handler: HALT(__LINE__) iret +#ifdef HVMTEST +.org 0xffe0 + jmp 0xf000:post; +#endif + .org 0xfff0 ; Power-up Entry Point - jmp 0xf000:post +#ifdef HVMTEST + jmp 0xd000:0x0003; +#else + jmp 0xf000:post +#endif .org 0xfff5 ; ASCII Date ROM was built - 8 characters in MM/DD/YY .ascii BIOS_BUILD_DATE @@ -11373,8 +11792,53 @@ static Bit8u vgafont8[128*8]= 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00, }; +#ifdef HVMASSIST ASM_START + +// space for addresses in 32bit BIOS area; currently 256/4 entries +// are allocated +.org 0xcb00 +jmptable: +db 0x5F, 0x5F, 0x5F, 0x4A, 0x4D, 0x50, 0x54 ;; ___JMPT +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 64 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 128 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 192 bytes + +// +// MP Tables +// just carve out some blank space for HVMLOADER to write the MP tables to +// +// NOTE: There should be enough space for a 32 processor entry MP table +// .org 0xcc00 +db 0x5F, 0x5F, 0x5F, 0x48, 0x56, 0x4D, 0x4D, 0x50 ;; ___HVMMP +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 64 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 128 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 192 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 256 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 320 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 384 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 448 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 512 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 576 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 640 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 704 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 768 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 832 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 896 bytes + +.align 16 +smbios_entry_point: +db 0,0,0,0,0,0,0,0 ; 8 bytes +db 0,0,0,0,0,0,0,0 ; 16 bytes +db 0,0,0,0,0,0,0,0 ; 24 bytes +db 0,0,0,0,0,0,0 ; 31 bytes +ASM_END + +#endif // HVMASSIST +ASM_START +.org 0xcff0 bios_table_area_end: // bcc-generated data will be placed here ASM_END + --- rombios.bochs.h 2008-12-18 08:46:18.000000000 +0900 +++ rombios.h 2008-12-17 23:33:44.000000000 +0900 @@ -20,13 +20,14 @@ /* define it to include QEMU specific code */ //#define BX_QEMU +#define LEGACY #ifndef LEGACY # define BX_ROMBIOS32 1 #else # define BX_ROMBIOS32 0 #endif -#define DEBUG_ROMBIOS 0 +#define DEBUG_ROMBIOS 1 #define PANIC_PORT 0x400 #define PANIC_PORT2 0x401 @@ -58,7 +59,9 @@ #define SMB_IO_BASE 0xb100 // Define the application NAME -#if defined(BX_QEMU) +#if define HVMASSIST +# define BX_APPNAME "HVMAssist" +#elif defined(BX_QEMU) # define BX_APPNAME "QEMU" #elif defined(PLEX86) # define BX_APPNAME "Plex86" _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |