Update rombios.c
RFC PATCH 1/1 Update rombios.c
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 :-)
Best Regards,
Akio Takebe
tools/firmware/rombios/rombios.c +2439 -1884
@@ -1,5 +1,5 @@///////////////////////////////////////////////////////////////////////// -// $Id: rombios.c,v 1.138 2005/05/07 15:55:26 vruppert Exp $ +// $Id: rombios.c,v 1.221 2008/12/07 17:32:29 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002 MandrakeSoft S.A.
@@ -22,9 +22,9 @@// // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -// ROM BIOS for use with Bochs/Plex x86 emulation environment +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +// ROM BIOS for use with Bochs/Plex86/QEMU emulation environment #define uint8_t unsigned char#define uint16_t unsigned short
@@ -81,10 +81,10 @@// // NOTES for El-Torito Boot ([email protected]) // - CD-ROM booting is only available if ATA/ATAPI Driver is available -// - Current code is only able to boot mono-session cds +// - Current code is only able to boot mono-session cds // - Current code can not boot and emulate a hard-disk // the bios will panic otherwise -// - Current code also use memory in EBDA segement. +// - Current code also use memory in EBDA segement. // - I used cmos byte 0x3D to store extended information on boot-device // - Code has to be modified modified to handle multiple cdrom drives // - Here are the cdrom boot failure codes:
@@ -102,13 +102,13 @@// 12 : can not read cd - boot image // // ATA driver -// - EBDA segment. +// - EBDA segment. // I used memory starting at 0x121 in the segment // - the translation policy is defined in cmos regs 0x39 & 0x3a // // TODO : // -// int74 +// int74 // - needs to be reworked. Uses direct [bp] offsets. (?) // // int13:
@@ -128,13 +128,13 @@// - Implement remaining int13_cdemu functions (as defined by El-Torito specs) // - cdrom drive is hardcoded to ide 0 device 1 in several places. see "FIXME ElTorito Hardcoded" // - int13 Fix DL when emulating a cd. In that case DL is decremented before calling real int13. -// This is ok. But DL should be reincremented afterwards. +// This is ok. But DL should be reincremented afterwards. // - Fix all "FIXME ElTorito Various" // - should be able to boot any cdrom instead of the first one // // BCC Bug: find a generic way to handle the bug of #asm after an "if" (fixed in 0.16.7) -#define DEBUG_ROMBIOS 0 +#include "rombios.h" #define DEBUG_ATA 0#define DEBUG_INT13_HD 0
@@ -159,7 +159,7 @@#define BX_USE_ATADRV 1#define BX_ELTORITO_BOOT 1 -#define BX_TCGBIOS 0/* main switch for TCG BIOS ext. */ +#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)
@@ -181,7 +181,6 @@// EBDA is used for PS/2 mouse support, and IDE BIOS, etc. #define EBDA_SEG 0x9FC0#define EBDA_SIZE 1 // In KiB -#define EBDA_SEG_PTR 0x40E/* Find true EBDA segment at 0:40E */ #define BASE_MEM_IN_K (640 - EBDA_SIZE)/* 256 bytes at 0x9ff00 -- 0x9ffff is used for the IPL boot table. */
@@ -189,15 +188,13 @@#define IPL_TABLE_ENTRIES 8#define IPL_COUNT_OFFSET 0x0380/* u16: number of valid table entries */ #define IPL_SEQUENCE_OFFSET 0x0382/* u16: next boot device */ - -// Define the application NAME -#ifdef HVMASSIST -# define BX_APPNAME "HVMAssist" -#elif PLEX86 -# define BX_APPNAME "Plex86" -#else -# define BX_APPNAME "Bochs" -#endif +#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
@@ -216,15 +213,10 @@# error APM BIOS can only be used with 386+ cpu#endif -#ifndef BX_SMP_PROCESSORS -#define BX_SMP_PROCESSORS 1 -# warning BX_SMP_PROCESSORS not defined, defaulting to 1 -#endif - -#define PANIC_PORT 0x400 -#define PANIC_PORT2 0x401 -#define INFO_PORT 0x402 -#define DEBUG_PORT 0x403 +// define this if you want to make PCIBIOS working on a specific bridge only +// undef enables PCIBIOS when at least one PCI device is found +// i440FX is emulated by Bochs and QEMU +#define PCI_FIXED_HOST_BRIDGE 0x12378086 ;; i440FX PCI bridge// #20 is dec 20 // #$20 is hex 20 = 32
@@ -257,7 +249,7 @@MACRO HALT ;; the HALT macro is called with the line number of the HALT call. - ;; The line number is then sent to the PANIC_PORT, causing Bochs/Plex + ;; The line number is then sent to the PANIC_PORT, causing Bochs/Plex ;; to print a BX_PANIC message. This will normally halt the simulation ;; with a message such as "BIOS panic at rombios.c, line 4091". ;; However, users can choose to make panics non-fatal and continue.
@@ -296,9 +288,9 @@void memsetb (seg ,offset ,value ,count );void memcpyb (dseg ,doffset ,sseg ,soffset ,count );void memcpyd (dseg ,doffset ,sseg ,soffset ,count ); - +// memset of count bytes - void + void memsetb(seg,offset,value,count) Bit16u seg; Bit16u offset;
@@ -308,14 +300,14 @@ASM_START push bp mov bp, sp - + push ax push cx push es push di - + mov cx, 10[bp] ; count - cmp cx, #0x00 + test cx, cx je memsetb_end mov ax, 4[bp] ; segment mov es, ax
@@ -325,19 +317,19 @@cld repstosb - + memsetb_end: pop di pop es pop cx pop ax - + pop bp ASM_END } - +// memcpy of count bytes - void + void memcpyb(dseg,doffset,sseg,soffset,count) Bit16u dseg; Bit16u doffset;
@@ -348,16 +340,16 @@ASM_START push bp mov bp, sp - + push ax push cx push es push di push ds push si - + mov cx, 12[bp] ; count - cmp cx, #0x0000 + test cx, cx je memcpyb_end mov ax, 4[bp] ; dsegment mov es, ax
@@ -370,7 +362,7 @@cld repmovsb - + memcpyb_end: pop si pop ds
@@ -378,14 +370,13 @@ pop es pop cx pop ax - + pop bp ASM_END } -#if 0 // memcpy of count dword - void + void memcpyd(dseg,doffset,sseg,soffset,count) Bit16u dseg; Bit16u doffset;
@@ -396,16 +387,16 @@ASM_START push bp mov bp, sp - + push ax push cx push es push di push ds push si - + mov cx, 12[bp] ; count - cmp cx, #0x0000 + test cx, cx je memcpyd_end mov ax, 4[bp] ; dsegment mov es, ax
@@ -418,7 +409,7 @@cld repmovsd - + memcpyd_end: pop si pop ds
@@ -426,16 +417,15 @@ pop es pop cx pop ax - + pop bp ASM_END } -#endif // read_dword and write_dword functions static Bit32u read_dword ();static void write_dword (); - + Bit32u read_dword(seg, offset) Bit16u seg;
@@ -444,25 +434,24 @@ASM_START push bp mov bp, sp - + push bx push ds mov ax, 4[bp] ; segment mov ds, ax mov bx, 6[bp] ; offset mov ax, [bx] - inc bx - inc bx + add bx, #2 mov dx, [bx] ;; ax = return value (word) ;; dx = return value (word) pop ds pop bx - + pop bp ASM_END } - + void write_dword(seg, offset, data) Bit16u seg;
@@ -472,7 +461,7 @@ASM_START push bp mov bp, sp - + push ax push bx push ds
@@ -481,50 +470,49 @@ mov bx, 6[bp] ; offset mov ax, 8[bp] ; data word mov [bx], ax ; write data word - inc bx - inc bx + add bx, #2 mov ax, 10[bp] ; data word mov [bx], ax ; write data word pop ds pop bx pop ax - + pop bp ASM_END } - +// Bit32u (unsigned long) and long helper functions ASM_START - + ;; and function landl: landul: - SEG SS + SEG SS and ax,[di] - SEG SS + SEG SS and bx,2[di] ret - + ;; add function laddl: laddul: - SEG SS + SEG SS add ax,[di] - SEG SS + SEG SS adc bx,2[di] ret - + ;; cmp function lcmpl: lcmpul: and eax, #0x0000FFFF shl ebx, #16 - add eax, ebx + or eax, ebx shr ebx, #16 SEG SS cmp eax, dword ptr [di] ret - + ;; sub function lsubl: lsubul:
@@ -533,26 +521,26 @@ SEG SS sbb bx,2[di] ret - + ;; mul function lmull: lmulul: and eax, #0x0000FFFF shl ebx, #16 - add eax, ebx + or eax, ebx SEG SS mul eax, dword ptr [di] mov ebx, eax shr ebx, #16 ret - + ;; dec function ldecl: ldecul: SEG SS dec dword ptr [bx] ret - + ;; or function lorl: lorul:
@@ -561,31 +549,31 @@ SEG SS or bx,2[di] ret - + ;; inc function lincl: lincul: SEG SS inc dword ptr [bx] ret - + ;; tst function ltstl: ltstul: and eax, #0x0000FFFF shl ebx, #16 - add eax, ebx + or eax, ebx shr ebx, #16 test eax, eax ret - + ;; sr function lsrul: mov cx,di jcxz lsr_exit and eax, #0x0000FFFF shl ebx, #16 - add eax, ebx + or eax, ebx lsr_loop: shr eax, #1 loop lsr_loop
@@ -593,7 +581,7 @@ shr ebx, #16 lsr_exit: ret - + ;; sl function lsll: lslul:
@@ -601,15 +589,15 @@ jcxz lsl_exit and eax, #0x0000FFFF shl ebx, #16 - add eax, ebx - lsl_loop: + or eax, ebx + lsl_loop: shl eax, #1 loop lsl_loop mov ebx, eax shr ebx, #16 lsl_exit: ret - + idiv_: cwd idiv bx
@@ -623,7 +611,7 @@ ldivul: and eax, #0x0000FFFF shl ebx, #16 -add eax, ebx +or eax, ebx xor edx, edx SEG SS mov bx, 2[di]
@@ -672,7 +660,7 @@Bit8u revision;Bit8u checksum; } dpte_t; - + typedef struct { Bit8u iface; // ISA or PCI Bit16u iobase1; // IO Base 1
@@ -685,15 +673,15 @@Bit8u device;// Detected type of attached devices (hd/cd/none) Bit8u removable;// Removable device flag Bit8u lock;// Locks for removable devices -// Bit8u lba_capable; // LBA capable flag - always yes for bochs devices -Bit8u mode;// transfert mode : PIO 16/32 bits - IRQ - ISADMA - PCIDMA +Bit8u mode;// transfer mode : PIO 16/32 bits - IRQ - ISADMA - PCIDMA Bit16u blksize;// block size Bit8u translation;// type of translation chs_t lchs;// Logical CHS chs_t pchs;// Physical CHS -Bit32u sectors;// Total sectors count +Bit32u sectors_low;// Total sectors count +Bit32u sectors_high; } ata_device_t; typedef struct {
@@ -704,10 +692,10 @@ata_device_t devices[BX_MAX_ATA_DEVICES ];// // map between (bios hd id - 0x80) and ata channels -Bit8u hdcount, hdidmap[BX_MAX_ATA_DEVICES ]; +Bit8u hdcount, hdidmap[BX_MAX_ATA_DEVICES ];// map between (bios cd id - 0xE0) and ata channels -Bit8u cdcount, cdidmap[BX_MAX_ATA_DEVICES ]; +Bit8u cdcount, cdidmap[BX_MAX_ATA_DEVICES ];// Buffer for DPTE table dpte_t dpte;
@@ -717,9 +705,9 @@Bit32u trsfbytes; } ata_t; - -#if BX_ELTORITO_BOOT - // ElTorito Device Emulation data + +#if BX_ELTORITO_BOOT + // ElTorito Device Emulation data typedef struct { Bit8u active; Bit8u media;
@@ -730,20 +718,20 @@Bit16u buffer_segment;Bit16u load_segment;Bit16u sector_count; - +// Virtual device chs_t vdevice; } cdemu_t;#endif // BX_ELTORITO_BOOT - +#include "32bitgateway.h" // for access to EBDA area -// The EBDA structure should conform to -// http://www.cybertrails.com/~fys/rombios.htm document +// 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 0x9fc00, and the boot -// device tables are at 0x9ff00 -- 0x9ffff +// EBDA must be at most 768 bytes; it lives at EBDA_SEG, and the boot +// device tables are at EBDA_SEG:IPL_TABLE_OFFSET typedef struct { unsigned char ebda_size; unsigned char cmos_shutdown_status;
@@ -765,7 +753,7 @@upcall_t upcall; } ebda_data_t; - +#define EBDA_CMOS_SHUTDOWN_STATUS_OFFSET 1#define EbdaData ((ebda_data_t *) 0)
@@ -779,7 +767,7 @@Bit32u lba1;Bit32u lba2; } int13ext_t; - +#define Int13Ext ((int13ext_t *) 0)// Disk Physical Table definition
@@ -805,7 +793,7 @@Bit8u reserved3; Bit8u checksum; } dpt_t; - +#define Int13DPT ((dpt_t *) 0)#endif // BX_USE_ATADRV
@@ -835,9 +823,9 @@ } r16;struct {Bit32u filler[4 ]; -Bit8u bl, bh; +Bit8u bl, bh;Bit16u filler1; -Bit8u dl, dh; +Bit8u dl, dh;Bit16u filler2;Bit8u cl, ch;Bit16u filler3;
@@ -870,6 +858,14 @@Bit16u cs;flags_t flags; } iret_addr_t; + +typedef struct { +Bit16u type; +Bit16u flags; +Bit32u vector; +Bit32u description; +Bit32u reserved; + }ipl_entry_t ;
@@ -910,8 +906,6 @@static void int70_function ();static void int74_function ();static Bit16u get_CS (); -//static Bit16u get_DS(); -//static void set_DS(); static Bit16u get_SS ();static unsigned int enqueue_key ();static unsigned int dequeue_key ();
@@ -930,7 +924,10 @@static void keyboard_panic ();static void shutdown_status_panic ();static void nmi_handler_msg (); - +static void delay_ticks (); +static void delay_ticks_and_check_for_keystroke (); + +static void interactive_bootkey ();static void print_bios_banner ();static void print_boot_device ();static void print_boot_failure ();
@@ -964,33 +961,9 @@#endif // BX_ELTORITO_BOOT -static char bios_cvs_version_string[] ="$Revision: 1.138 $" ; -static char bios_date_string[] ="$Date: 2005/05/07 15:55:26 $" ; - -static char CVSID [] ="$Id: rombios.c,v 1.138 2005/05/07 15:55:26 vruppert Exp $" ; - -/* Offset to skip the CVS $Id: prefix */ -#define bios_version_string (CVSID + 4) - -#define BIOS_PRINTF_HALT 1 -#define BIOS_PRINTF_SCREEN 2 -#define BIOS_PRINTF_INFO 4 -#define BIOS_PRINTF_DEBUG 8 -#define BIOS_PRINTF_ALL (BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO) -#define BIOS_PRINTF_DEBHALT (BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO | BIOS_PRINTF_HALT) - -#define printf(format, p...) bios_printf(BIOS_PRINTF_SCREEN, format, ##p) - -// Defines the output macros. -// BX_DEBUG goes to INFO port until we can easily choose debug info on a -// per-device basis. Debug info are sent only in debug mode -#if DEBUG_ROMBIOS -# define BX_DEBUG(format, p...) bios_printf(BIOS_PRINTF_INFO, format, ##p) -#else -# define BX_DEBUG(format, p...) -#endif -#define BX_INFO(format, p...) bios_printf(BIOS_PRINTF_INFO, format, ##p) -#define BX_PANIC(format, p...) bios_printf(BIOS_PRINTF_DEBHALT, format, ##p) +static char bios_cvs_version_string[] ="$Revision: 1.221 $ $Date: 2008/12/07 17:32:29 $" ; + +#define BIOS_COPYRIGHT_STRING "(c) 2002 MandrakeSoft S.A. Written by Kevin Lawton & the Bochs team."#if DEBUG_ATA # define BX_DEBUG_ATA(a...) BX_DEBUG(a)
@@ -1163,9 +1136,9 @@ { 0x5100, 0x5133, 0x7600, none, 0x20 }, /* 3 PgDn */ { 0x5200, 0x5230, none, none, 0x20 }, /* 0 Ins */ { 0x5300, 0x532e, none, none, 0x20 }, /* Del */ - { none, none, none, none, none }, /* ??? */ - { none, none, none, none, none }, /* ??? */ - { none, none, none, none, none }, /* ??? */ + { none, none, none, none, none }, + { none, none, none, none, none }, + { 0x565c, 0x567c, none, none, none }, /* \| */ { 0x8500, 0x8700, 0x8900, 0x8b00, none }, /* F11 */ { 0x8600, 0x8800, 0x8a00, 0x8c00, none }, /* F12 */ };
@@ -1422,31 +1395,6 @@ ASM_END } -// Bit16u -//get_DS() -//{ -//ASM_START -// mov ax, ds -//ASM_END -//} -// -// void -//set_DS(ds_selector) -// Bit16u ds_selector; -//{ -//ASM_START -// push bp -// mov bp, sp -// -// push ax -// mov ax, 4[bp] ; ds_selector -// mov ds, ax -// pop ax -// -// pop bp -//ASM_END -//} -Bit16u get_SS () {
@@ -1462,7 +1410,7 @@Bit8u nr_entries =read_byte (0x9000 ,0x1e8 );Bit32u base_mem;if (nr_entries >32 ) - 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
@@ -1570,7 +1518,7 @@ pop bp ASM_END } - + void send(action, c) Bit16u action;
@@ -1626,14 +1574,121 @@send (action, val - (nval *10 ) +'0' ); } +void +put_luint (action, val, width, neg) +Bit16u action; +unsigned long val; +short width; +bx_bool neg; +{ +unsigned long nval = val /10 ; +if (nval) +put_luint (action, nval, width -1 , neg); +else { +while (--width >0 )send (action,' ' ); +if (neg)send (action,'-' ); + } +send (action, val - (nval *10 ) +'0' ); +} + +void put_str (action, segment, offset) +Bit16u action; +Bit16u segment; +Bit16u offset; +{ +Bit8u c; + +while (c =read_byte (segment, offset)) { +send (action, c); + offset++; + } +} + +void +delay_ticks (ticks) +Bit16u ticks; +{ +long ticks_to_wait, delta; +Bit32u prev_ticks, t; + +/* +* The 0:046c wraps around at 'midnight' according to a 18.2Hz clock. +* We also have to be careful about interrupt storms. +*/ +ASM_START + pushf +sti +ASM_END + ticks_to_wait = ticks; + prev_ticks =read_dword (0x0 ,0x46c ); +do + { +ASM_START + hlt +ASM_END + t =read_dword (0x0 ,0x46c ); +if (t > prev_ticks) + { + delta = t - prev_ticks;/* The temp var is required or bcc screws up. */ + ticks_to_wait -= delta; + } +else if (t < prev_ticks) + { + ticks_to_wait -= t;/* wrapped */ + } + + prev_ticks = t; + }while (ticks_to_wait >0 ); +ASM_START + cli +popf +ASM_END +} + +Bit8u +check_for_keystroke () +{ +ASM_START + mov ax, #0x100 + int #0x16 + jz no_key + mov al, #1 + jmp done +no_key: + xor al, al +done: +ASM_END +} + + Bit8u +get_keystroke() +{ +ASM_START + mov ax, #0x0 + int #0x16 + xchg ah, al +ASM_END +} + + void +delay_ticks_and_check_for_keystroke(ticks, count) + Bit16u ticks, count; +{ +Bit16u i; +for (i =1 ; i <= count; i++) { +delay_ticks (ticks); +if (check_for_keystroke ()) +break ; + } +} +//-------------------------------------------------------------------------- // 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 +// A compact variable argument printf function. +// +// Supports %[format_width][length]format +// where format can be x,X,u,d,s,S,c +// and the optional length modifier is l (ell) //-------------------------------------------------------------------------- void bios_printf (action ,s )
@@ -1644,7 +1699,7 @@bx_bool in_format;short i;Bit16u *arg_ptr; -Bit16u arg_seg, arg, nibble, shift_count, format_width; +Bit16u arg_seg, arg, nibble, hibyte, shift_count, format_width, hexadd; arg_ptr = &s; arg_seg =get_SS ();
@@ -1671,16 +1726,48 @@else { arg_ptr++;// increment to next arg arg =read_word (arg_seg, arg_ptr); -if (c =='x' ) { +if (c =='x' || c =='X' ) {if (format_width ==0 ) format_width =4 ; +if (c =='x' ) + hexadd ='a' ; +else + hexadd ='A' ;for (i=format_width-1 ; i>=0 ; i--) { nibble = (arg >> (4 * i)) &0x000f ; -send (action, (nibble<=9 )? (nibble+'0' ) : (nibble-10 +'A' )); +send (action, (nibble<=9 )? (nibble+'0' ) : (nibble-10 +hexadd)); } }else if (c =='u' ) {put_uint (action, arg, format_width,0 ); + } +else if (c =='l' ) { + s++; + c =read_byte (get_CS (), s);/* is it ld,lx,lu? */ + arg_ptr++;/* increment to next arg */ + hibyte =read_word (arg_seg, arg_ptr); +if (c =='d' ) { +if (hibyte &0x8000 ) +put_luint (action,0L -(((Bit32u ) hibyte <<16 ) | arg), format_width-1 ,1 ); +else +put_luint (action, ((Bit32u ) hibyte <<16 ) | arg, format_width,0 ); + } +else if (c =='u' ) { +put_luint (action, ((Bit32u ) hibyte <<16 ) | arg, format_width,0 ); + } +else if (c =='x' || c =='X' ) + { +if (format_width ==0 ) + format_width =8 ; +if (c =='x' ) + hexadd ='a' ; +else + hexadd ='A' ; +for (i=format_width-1 ; i>=0 ; i--) { + nibble = ((((Bit32u ) hibyte <<16 ) | arg) >> (4 * i)) &0x000f ; +send (action, (nibble<=9 )? (nibble+'0' ) : (nibble-10 +hexadd)); + } + } }else if (c =='d' ) {if (arg &0x8000 )
@@ -1689,7 +1776,13 @@put_int (action, arg, format_width,0 ); }else if (c =='s' ) { -bios_printf (action & (~BIOS_PRINTF_HALT ), arg); +put_str (action,get_CS (), arg); + } +else if (c =='S' ) { + hibyte = arg; + arg_ptr++; + arg =read_word (arg_seg, arg_ptr); +put_str (action, hibyte, arg); }else if (c =='c' ) {send (action, arg);
@@ -1706,7 +1799,7 @@ }if (action &BIOS_PRINTF_HALT ) { -// freeze in a busy loop. +// freeze in a busy loop. ASM_START cli halt2_loop:
@@ -1740,8 +1833,8 @@ max =0x2000 ; } } - -// Due to timer issues, and if the IPS setting is > 15000000, + +// 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
@@ -1878,12 +1971,11 @@keyboard_panic (status) Bit16u status; { -// If you're getting a 993 keyboard panic here, +// 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//--------------------------------------------------------------------------
@@ -1939,6 +2031,11 @@BX_PANIC ("Unimplemented shutdown status: %02x\n" ,(Bit8u )status); } +void s3_resume_panic () +{ +BX_PANIC ("Returned from s3_resume.\n" ); +} +//-------------------------------------------------------------------------- // print_bios_banner // displays a the bios version
@@ -1946,74 +2043,84 @@void print_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); +printf (BX_APPNAME " BIOS - build: %s\n%s\nOptions: " , +BIOS_BUILD_DATE , bios_cvs_version_string); + printf( +#if BX_APM + "apmbios " +#endif +#if BX_PCIBIOS + "pcibios " +#endif +#if BX_ELTORITO_BOOT + "eltorito " +#endif +#if BX_ROMBIOS32 + "rombios32 " +#endif #if BX_TCGBIOS -printf ("TCG-enabled BIOS.\n" ); -#endif -printf ("\n" ); -} - +"TCG-enabled" +#endif + "\n\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 +// 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). +// 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 //-------------------------------------------------------------------------- -struct ipl_entry { -Bit16u type; -Bit16u flags; -Bit32u vector; -Bit32u description; -Bit32u reserved; -}; - -static void -init_boot_vectors () -{ -struct ipl_entry e; +static char drivetypes[][10 ]={"" ,"Floppy" ,"Hard Disk" ,"CD-Rom" ,"Network" }; + +static void +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 (EBDA_SEG ,IPL_TABLE_OFFSET ,0 ,0xff ); +memsetb (ebda_seg,IPL_TABLE_OFFSET ,0 ,IPL_SIZE ); + +/* User selected device not set */ +write_word (ebda_seg,IPL_BOOTFIRST_OFFSET ,0xFFFF );/* Floppy drive */ - e.type =1 ; e.flags =0 ; e.vector =0 ; e.description =0 ; e.reserved =0 ; -memcpyb (EBDA_SEG ,IPL_TABLE_OFFSET + count *sizeof (e), ss, &e,sizeof (e)); + e.type =IPL_TYPE_FLOPPY ; e.flags =0 ; e.vector =0 ; e.description =0 ; e.reserved =0 ; +memcpyb (ebda_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 (EBDA_SEG ,IPL_TABLE_OFFSET + count *sizeof (e), ss, &e,sizeof (e)); + e.type =IPL_TYPE_HARDDISK ; e.flags =0 ; e.vector =0 ; e.description =0 ; e.reserved =0 ; +memcpyb (ebda_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 (EBDA_SEG ,IPL_TABLE_OFFSET + count *sizeof (e), ss, &e,sizeof (e)); + e.type =IPL_TYPE_CDROM ; e.flags =0 ; e.vector =0 ; e.description =0 ; e.reserved =0 ; +memcpyb (ebda_seg,IPL_TABLE_OFFSET + count *sizeof (e), ss, &e,sizeof (e)); count++; -#endif +#endif /* Remember how many devices we have */ -write_word (EBDA_SEG ,IPL_COUNT_OFFSET , count); +write_word (ebda_seg,IPL_COUNT_OFFSET , count);/* Not tried booting anything yet */ -write_word (EBDA_SEG ,IPL_SEQUENCE_OFFSET ,0xffff ); +write_word (ebda_seg,IPL_SEQUENCE_OFFSET ,0xffff ); }static Bit8u get_boot_vector (i, e) -Bit16u i;struct ipl_entry *e; +Bit16u i;ipl_entry_t *e; {Bit16u count;Bit16u ss =get_SS ();
@@ -2026,22 +2133,107 @@return 1 ; } +#if BX_ELTORITO_BOOT +void +interactive_bootkey () +{ +ipl_entry_t e; +Bit16u count; +char description[33 ]; +Bit8u scan_code; +Bit8u i; +Bit16u ss =get_SS (); +Bit16u valid_choice =0 ; +Bit16u ebda_seg =read_word (0x0040 ,0x000E ); + +while (check_for_keystroke ()) +get_keystroke (); + +printf ("\nPress F12 for boot menu.\n\n" ); + +delay_ticks_and_check_for_keystroke (11 ,5 );/* ~3 seconds */ +if (check_for_keystroke ()) + { + scan_code =get_keystroke (); +if (scan_code ==0x86 )/* F12 */ + { +while (check_for_keystroke ()) +get_keystroke (); + +printf ("Select boot device:\n\n" ); + + count =read_word (ebda_seg,IPL_COUNT_OFFSET ); +for (i =0 ; i < count; i++) + { +memcpyb (ss, &e, ebda_seg,IPL_TABLE_OFFSET + i *sizeof (e),sizeof (e)); +printf ("%d. " , i+1 ); +switch (e.type) + { +case IPL_TYPE_FLOPPY : +case IPL_TYPE_HARDDISK : +case IPL_TYPE_CDROM : +printf ("%s\n" , drivetypes[e.type]); +break ; +case IPL_TYPE_BEV : +printf ("%s" , drivetypes[4 ]); +if (e.description !=0 ) + { +memcpyb (ss, &description, (Bit16u)(e.description >>16 ), (Bit16u)(e.description &0xffff ),32 ); + description[32 ] =0 ; +printf (" [%S]" , ss, description); + } +printf ("\n" ); +break ; + } + } + + count++; +while (!valid_choice) { + scan_code =get_keystroke (); +if (scan_code ==0x01 || scan_code ==0x58 )/* ESC or F12 */ + { + valid_choice =1 ; + } +else if (scan_code <= count) + { + valid_choice =1 ; + scan_code -=1 ; +/* Set user selected device */ +write_word (ebda_seg,IPL_BOOTFIRST_OFFSET , scan_code); + } + } +printf ("\n" ); + } + } +} +#endif // BX_ELTORITO_BOOT //-------------------------------------------------------------------------- // print_boot_device // displays the boot device //-------------------------------------------------------------------------- -static char drivetypes[][10 ]={"" ,"Floppy" ,"Hard Disk" ,"CD-Rom" ,"Network" }; -void -print_boot_device (type) +print_boot_device (e) +ipl_entry_t *e; +{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]); +char description[33 ]; +Bit16u ss =get_SS (); + type = e->type; +/* NIC appears as type 0x80 */ +if (type ==IPL_TYPE_BEV ) type =0x4 ; +if (type ==0 || type >0x4 )BX_PANIC ("Bad drive type\n" ); +printf ("Booting from %s" , drivetypes[type]); +/* print product string if BEV */ +if (type ==4 && e->description !=0 ) { +/* first 32 bytes are significant */ +memcpyb (ss, &description, (Bit16u)(e->description >>16 ), (Bit16u)(e->description &0xffff ),32 ); +/* terminate string */ + description[32 ] =0 ; +printf (" [%S]" , ss, description); + } +printf ("...\n" ); }//--------------------------------------------------------------------------
@@ -2052,17 +2244,17 @@ print_boot_failure(type, reason)Bit16u type;Bit8u reason; { -if (type ==0 || type >0x3 )BX_PANIC ("Bad drive type\n" ); +if (type ==0 || type >0x3 )BX_PANIC ("Bad drive type\n" );printf ("Boot from %s failed" , drivetypes[type]);if (type <4 ) {/* Report the reason too */ -if (reason==0 ) -printf (": not a bootable disk" ); -else -printf (": could not read the boot disk" ); - } -printf ("\n" ); +if (reason==0 ) +printf (": not a bootable disk" ); +else +printf (": could not read the boot disk" ); + } +printf ("\n\n" ); }//--------------------------------------------------------------------------
@@ -2074,219 +2266,9 @@Bit16u code; {bios_printf (BIOS_PRINTF_SCREEN |BIOS_PRINTF_INFO ,"CDROM boot failure code : %04x\n" ,code); - +return ; } - -#define WAIT_HZ 18 -/** -* Check for keystroke. -* @returns True if keystroke available, False if not. -*/ -Bit8u check_for_keystroke() -{ -ASM_START - mov ax, #0x100 - int #0x16 - jz no_key - mov al, #1 - jmp done -no_key: - xor al, al -done: -ASM_END -} - -/** - * Get keystroke. - * @returns BIOS scan code. - */ -Bit8u get_keystroke() -{ -ASM_START - mov ax, #0x0 - int #0x16 - xchg ah, al -ASM_END -} - -/** - * Waits (sleeps) for the given number of ticks. - * Checks for keystroke. - * - * @returns BIOS scan code if available, 0 if not. - * @param ticks Number of ticks to sleep. - * @param stop_on_key Whether to stop immediately upon keypress. - */ -Bit8u wait(ticks, stop_on_key) - Bit16u ticks; - Bit8u stop_on_key; -{ - long ticks_to_wait, delta; - Bit32u prev_ticks, t; - Bit8u scan_code = 0; - - /* - * The 0:046c wraps around at 'midnight' according to a 18.2Hz clock. - * We also have to be careful about interrupt storms. - */ - ticks_to_wait = ticks; - prev_ticks = read_dword(0x0, 0x46c); - do - { - t = read_dword(0x0, 0x46c); - if (t > prev_ticks) - { - delta = t - prev_ticks; /* The temp var is required or bcc screws up. */ - ticks_to_wait -= delta; - } - else if (t < prev_ticks) - ticks_to_wait -= t; /* wrapped */ - prev_ticks = t; - - if (check_for_keystroke()) - { - scan_code = get_keystroke(); - bios_printf(BIOS_PRINTF_DEBUG, "Key pressed: %x\n", scan_code); - if (stop_on_key) - return scan_code; - } - } while (ticks_to_wait > 0); - return scan_code; -} - -static void clearscreen() { - /* Hide cursor, clear screen and move cursor to starting position */ -ASM_START - push bx - push cx - push dx - - mov ax, #0x100 - mov cx, #0x1000 - int #0x10 - - mov ax, #0x700 - mov bh, #7 - xor cx, cx - mov dx, #0x184f - int #0x10 - - mov ax, #0x200 - xor bx, bx - xor dx, dx - int #0x10 - - pop dx - pop cx - pop bx -ASM_END -} - -int bootmenu(selected) - int selected; -{ - Bit8u scode; - int max; - Bit16u ebda_seg = read_word(0x0040, 0x000E); - - /* get the number of boot devices */ - max = read_word(ebda_seg, IPL_COUNT_OFFSET); - - for(;;) { - if (selected > max || selected < 1) selected = 1; - clearscreen(); - bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "\n\n\n\n\n\n\n"); - bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, " Select boot device\n\n"); - bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, " 1. Floppy\n"); - bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, " 2. Hard drive\n"); - bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, " 3. CD-ROM\n"); - if (max == 4) - bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, " 4. Network\n"); - bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "\n\n Currently selected: %d\n", selected); - - do { - scode = wait(WAIT_HZ, 1); - } while (scode == 0); - switch(scode) { - case 0x02: - case 0x03: - case 0x04: - selected = scode - 1; - break; - case 0x05: - if (max == 4) - selected = scode -1 ; - else - scode = 0; - break; - case 0x48: - selected -= 1; - if (selected < 1) - selected = 1; - scode = 0; - break; - case 0x50: - selected += 1; - if (selected > max) - selected = max; - scode = 0; - break; - case 0x1c: - break; - default: - scode = 0; - break; - } - if (scode != 0) - break; - } - - switch (selected) { - case 1: - return 0x3D; - case 2: - return 0x3E; - case 3: - return 0x3F; - case 4: - return 0x58; - default: - return 0; - } -} - -void interactive_bootkey() -{ - Bit16u i; - Bit8u scan = 0; - - bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, - "\n\nPress F10 to select boot device.\n"); - - scan = wait(1, 0); - if (scan == 0x44) - scan = bootmenu(inb_cmos(0x3d) & 0x0f); - - /* set the default based on the keypress or menu */ - switch(scan) { - case 0x3D: - outb_cmos(0x3d, 0x01); - break; - case 0x3E: - outb_cmos(0x3d, 0x02); - break; - case 0x3F: - outb_cmos(0x3d, 0x03); - break; - case 0x58: - outb_cmos(0x3d, 0x04); - break; - default: - break; - } -} -void nmi_handler_msg ()
@@ -2306,7 +2288,7 @@#if BX_DEBUG_SERIAL outb (BX_DEBUG_PORT +UART_LCR ,0x03 );/* setup for serial logging: 8N1 */ #endif -BX_INFO ("%s\n" , bios_version_string); +BX_INFO ("%s\n" , bios_cvs_version_string); } bx_bool
@@ -2341,41 +2323,35 @@outb (0xfedc ,0x00 ); } -void +int s3_resume () {Bit32u s3_wakeup_vector; -Bit16u s3_wakeup_ip, s3_wakeup_cs; -Bit8u cmos_shutdown_status; - -ASM_START - push ds - push ax - xor ax, ax - mov ds, ax - mov ax, word ptr [EBDA_SEG_PTR] - mov ds, ax - mov al, [EBDA_CMOS_SHUTDOWN_STATUS_OFFSET] - mov .s3_resume.cmos_shutdown_status[bp], al - pop ax - pop ds -ASM_END - - if (cmos_shutdown_status != CMOS_SHUTDOWN_S3) - return; - +Bit8u s3_resume_flag; + + s3_resume_flag =read_byte (0x40 ,0xb0 ); +#ifdef HVMASSIST s3_wakeup_vector =get_s3_waking_vector (); -if (!s3_wakeup_vector) -return ; - - s3_wakeup_ip = s3_wakeup_vector &0xF ; - s3_wakeup_cs = s3_wakeup_vector >>4 ; - -ASM_START - push .s3_resume.s3_wakeup_cs[bp] - push .s3_resume.s3_wakeup_ip[bp] -retf -ASM_END +#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 !=CMOS_SHUTDOWN_S3 || !s3_wakeup_vector) +return 0 ; + +write_byte (0x40 ,0xb0 ,0 ); + +/* setup wakeup vector */ +write_word (0x40 ,0xb6 , (s3_wakeup_vector &0xF ));/* IP */ +write_word (0x40 ,0xb8 , (s3_wakeup_vector >>4 ));/* CS */ + +BX_INFO ("S3 resume jump to %x:%x\n" , (s3_wakeup_vector >>4 ), + (s3_wakeup_vector &0xF )); +ASM_START + jmpf [0x04b6] +ASM_END +return 1 ; }#if BX_USE_ATADRV
@@ -2425,6 +2401,7 @@// bits 7-4 of the device/head (CB_DH) reg #define ATA_CB_DH_DEV0 0xa0 // select device 0#define ATA_CB_DH_DEV1 0xb0 // select device 1 +#define ATA_CB_DH_LBA 0x40 // use LBA// status reg (CB_STAT and CB_ASTAT) bits #define ATA_CB_STAT_BSY 0x80 // busy
@@ -2474,6 +2451,7 @@#define ATA_CMD_READ_SECTORS 0x20#define ATA_CMD_READ_VERIFY_SECTORS 0x40#define ATA_CMD_RECALIBRATE 0x10 +#define ATA_CMD_REQUEST_SENSE 0x03#define ATA_CMD_SEEK 0x70#define ATA_CMD_SET_FEATURES 0xEF#define ATA_CMD_SET_MULTIPLE_MODE 0xC6
@@ -2518,7 +2496,7 @@#define ATA_DATA_NO 0x00#define ATA_DATA_IN 0x01#define ATA_DATA_OUT 0x02 - +// --------------------------------------------------------------------------- // ATA/ATAPI driver : initialization // ---------------------------------------------------------------------------
@@ -2527,7 +2505,7 @@Bit16u ebda_seg=read_word (0x0040 ,0x000E );Bit8u channel, device; -// Channels info init. +// Channels info init. for (channel=0 ; channel<BX_MAX_ATA_INTERFACES ; channel++) {write_byte (ebda_seg,&EbdaData->ata.channels[channel].iface,ATA_IFACE_NONE );write_word (ebda_seg,&EbdaData->ata.channels[channel].iobase1,0x0 );
@@ -2535,7 +2513,7 @@write_byte (ebda_seg,&EbdaData->ata.channels[channel].irq,0 ); } -// Devices info init. +// Devices info init. for (device=0 ; device<BX_MAX_ATA_DEVICES ; device++) {write_byte (ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_NONE );write_byte (ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_NONE );
@@ -2550,11 +2528,12 @@write_word (ebda_seg,&EbdaData->ata.devices[device].pchs.heads,0 );write_word (ebda_seg,&EbdaData->ata.devices[device].pchs.cylinders,0 );write_word (ebda_seg,&EbdaData->ata.devices[device].pchs.spt,0 ); - -write_dword (ebda_seg,&EbdaData->ata.devices[device].sectors,0L ); - } - -// hdidmap and cdidmap init. + +write_dword (ebda_seg,&EbdaData->ata.devices[device].sectors_low,0L ); +write_dword (ebda_seg,&EbdaData->ata.devices[device].sectors_high,0L ); + } + +// hdidmap and cdidmap init. for (device=0 ; device<BX_MAX_ATA_DEVICES ; device++) {write_byte (ebda_seg,&EbdaData->ata.hdidmap[device],BX_MAX_ATA_DEVICES );write_byte (ebda_seg,&EbdaData->ata.cdidmap[device],BX_MAX_ATA_DEVICES );
@@ -2562,6 +2541,58 @@write_byte (ebda_seg,&EbdaData->ata.hdcount,0 );write_byte (ebda_seg,&EbdaData->ata.cdcount,0 ); +} + +#define TIMEOUT 0 +#define BSY 1 +#define NOT_BSY 2 +#define NOT_BSY_DRQ 3 +#define NOT_BSY_NOT_DRQ 4 +#define NOT_BSY_RDY 5 + +#define IDE_TIMEOUT 32000u //32 seconds max for IDE ops + +int await_ide (); +static int await_ide (when_done,base,timeout) +Bit8u when_done; +Bit16u base; +Bit16u timeout; +{ +Bit32u time=0 ,last=0 ; +Bit16u status; +Bit8u result; + status =inb (base +ATA_CB_STAT );// for the times you're supposed to throw one away +for (;;) { + status =inb (base+ATA_CB_STAT ); + time++; +if (when_done ==BSY ) + result = status &ATA_CB_STAT_BSY ; +else if (when_done ==NOT_BSY ) + result = !(status &ATA_CB_STAT_BSY ); +else if (when_done ==NOT_BSY_DRQ ) + result = !(status &ATA_CB_STAT_BSY ) && (status &ATA_CB_STAT_DRQ ); +else if (when_done ==NOT_BSY_NOT_DRQ ) + result = !(status &ATA_CB_STAT_BSY ) && !(status &ATA_CB_STAT_DRQ ); +else if (when_done ==NOT_BSY_RDY ) + result = !(status &ATA_CB_STAT_BSY ) && (status &ATA_CB_STAT_RDY ); +else if (when_done ==TIMEOUT ) + result =0 ; + +if (result)return 0 ; +if (time>>16 != last)// mod 2048 each 16 ms + { + last = time >>16 ; +BX_DEBUG_ATA ("await_ide: (TIMEOUT,BSY,!BSY,!BSY_DRQ,!BSY_!DRQ,!BSY_RDY) %d time= %ld timeout= %d\n" ,when_done,time>>11 , timeout); + } +if (status &ATA_CB_STAT_ERR ) + { +BX_DEBUG_ATA ("await_ide: ERROR (TIMEOUT,BSY,!BSY,!BSY_DRQ,!BSY_!DRQ,!BSY_RDY) %d time= %ld timeout= %d\n" ,when_done,time>>11 , timeout); +return -1 ; + } +if ((timeout ==0 ) || ((time>>11 ) > timeout))break ; + } +BX_INFO ("IDE time out\n" ); +return -1 ; }// ---------------------------------------------------------------------------
@@ -2604,7 +2635,7 @@// Device detection hdcount=cdcount=0 ; - +for (device=0 ; device<BX_MAX_ATA_DEVICES ; device++) {Bit16u iobase1, iobase2;Bit8u channel, slave, shift;
@@ -2634,33 +2665,34 @@if ( (sc ==0x55 ) && (sn ==0xaa ) ) {write_byte (ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_UNKNOWN ); - +// reset the channel -ata_reset (device); - +ata_reset (device); +// check for ATA or ATAPI outb (iobase1+ATA_CB_DH , slave ?ATA_CB_DH_DEV1 :ATA_CB_DH_DEV0 ); sc =inb (iobase1+ATA_CB_SC ); sn =inb (iobase1+ATA_CB_SN ); -if ( (sc==0x01 ) && (sn==0x01 ) ) { +if ((sc==0x01 ) && (sn==0x01 )) { cl =inb (iobase1+ATA_CB_CL ); ch =inb (iobase1+ATA_CB_CH ); st =inb (iobase1+ATA_CB_STAT ); -if ( (cl==0x14 ) && (ch==0xeb ) ) { +if ((cl==0x14 ) && (ch==0xeb )) {write_byte (ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_ATAPI ); - } -else if ( (cl==0x00 ) && (ch==0x00 ) && (st!=0x00 ) ) { + }else if ((cl==0x00 ) && (ch==0x00 ) && (st!=0x00 )) {write_byte (ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_ATA ); - } - } - } + }else if ((cl==0xff ) && (ch==0xff )) { +write_byte (ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_NONE ); + } + } + } type=read_byte (ebda_seg,&EbdaData->ata.devices[device].type); - -// Now we send a IDENTIFY command to ATA device + +// Now we send a IDENTIFY command to ATA device if (type ==ATA_TYPE_ATA ) { -Bit32u sectors; +Bit32u sectors_low, sectors_high;Bit16u cylinders, heads, spt, blksize;Bit8u translation, removable, mode;
@@ -2671,21 +2703,26 @@write_byte (ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_HD );write_byte (ebda_seg,&EbdaData->ata.devices[device].mode,ATA_MODE_PIO16 ); -if (ata_cmd_data_in (device,ATA_CMD_IDENTIFY_DEVICE ,1 ,0 ,0 ,0 ,0L ,get_SS (),buffer) !=0 ) +if (ata_cmd_data_in (device,ATA_CMD_IDENTIFY_DEVICE ,1 ,0 ,0 ,0 ,0L ,0L ,get_SS (),buffer) !=0 )BX_PANIC ("ata-detect: Failed to detect ATA device\n" ); removable = (read_byte (get_SS (),buffer+0 ) &0x80 ) ?1 :0 ; -#ifndef NO_PIO32 +#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 heads =read_word (get_SS (),buffer+(3 *2 ));// word 3 spt =read_word (get_SS (),buffer+(6 *2 ));// word 6 - sectors =read_dword (get_SS (),buffer+(60 *2 ));// word 60 and word 61 +if (read_word (get_SS (),buffer+(83 *2 )) & (1 <<10 )) {// word 83 - lba48 support + sectors_low =read_dword (get_SS (),buffer+(100 *2 ));// word 100 and word 101 + sectors_high =read_dword (get_SS (),buffer+(102 *2 ));// word 102 and word 103 + }else { + sectors_low =read_dword (get_SS (),buffer+(60 *2 ));// word 60 and word 61 + sectors_high =0 ; + }write_byte (ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_HD );write_byte (ebda_seg,&EbdaData->ata.devices[device].removable, removable);
@@ -2694,7 +2731,8 @@write_word (ebda_seg,&EbdaData->ata.devices[device].pchs.heads, heads);write_word (ebda_seg,&EbdaData->ata.devices[device].pchs.cylinders, cylinders);write_word (ebda_seg,&EbdaData->ata.devices[device].pchs.spt, spt); -write_dword (ebda_seg,&EbdaData->ata.devices[device].sectors, sectors); +write_dword (ebda_seg,&EbdaData->ata.devices[device].sectors_low, sectors_low); +write_dword (ebda_seg,&EbdaData->ata.devices[device].sectors_high, sectors_high);BX_INFO ("ata%d-%d: PCHS=%u/%d/%d translation=" , channel, slave,cylinders, heads, spt); translation =inb_cmos (0x39 + channel/2 );
@@ -2722,14 +2760,14 @@break ;case ATA_TRANSLATION_LBA : spt =63 ; - sectors /=63 ; - heads = sectors /1024 ; + sectors_low /=63 ; + heads = sectors_low /1024 ;if (heads>128 ) heads =255 ;else if (heads>64 ) heads =128 ;else if (heads>32 ) heads =64 ;else if (heads>16 ) heads =32 ;else heads=16 ; - cylinders = sectors / heads; + cylinders = sectors_low / heads;break ;case ATA_TRANSLATION_RECHS :// Take care not to overflow
@@ -2756,15 +2794,15 @@write_word (ebda_seg,&EbdaData->ata.devices[device].lchs.heads, heads);write_word (ebda_seg,&EbdaData->ata.devices[device].lchs.cylinders, cylinders);write_word (ebda_seg,&EbdaData->ata.devices[device].lchs.spt, spt); - -// fill hdidmap + +// fill hdidmap write_byte (ebda_seg,&EbdaData->ata.hdidmap[hdcount], device); hdcount++; } - +// Now we send a IDENTIFY command to ATAPI device if (type ==ATA_TYPE_ATAPI ) { - +Bit8u type, removable, mode;Bit16u blksize;
@@ -2775,12 +2813,12 @@write_byte (ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_CDROM );write_byte (ebda_seg,&EbdaData->ata.devices[device].mode,ATA_MODE_PIO16 ); -if (ata_cmd_data_in (device,ATA_CMD_IDENTIFY_DEVICE_PACKET ,1 ,0 ,0 ,0 ,0L ,get_SS (),buffer) !=0 ) +if (ata_cmd_data_in (device,ATA_CMD_IDENTIFY_DEVICE_PACKET ,1 ,0 ,0 ,0 ,0L ,0L ,get_SS (),buffer) !=0 )BX_PANIC ("ata-detect: Failed to detect ATAPI device\n" ); type =read_byte (get_SS (),buffer+1 ) &0x1f ; removable = (read_byte (get_SS (),buffer+0 ) &0x80 ) ?1 :0 ; -#ifndef NO_PIO32 +#ifndef NO_PIO32 mode =read_byte (get_SS (),buffer+96 ) ?ATA_MODE_PIO32 :ATA_MODE_PIO16 ;#endif blksize =2048 ;
@@ -2790,24 +2828,24 @@write_byte (ebda_seg,&EbdaData->ata.devices[device].mode, mode);write_word (ebda_seg,&EbdaData->ata.devices[device].blksize, blksize); -// fill cdidmap +// fill cdidmap write_byte (ebda_seg,&EbdaData->ata.cdidmap[cdcount], device); cdcount++; } - + {Bit32u sizeinmb;Bit16u ataversion;Bit8u c, i, version, model[41 ]; - +switch (type) {case ATA_TYPE_ATA : - sizeinmb =read_dword (ebda_seg,&EbdaData->ata.devices[device].sectors); - sizeinmb >>=11 ; + sizeinmb = (read_dword (ebda_seg,&EbdaData->ata.devices[device].sectors_high) <<21 ) + | (read_dword (ebda_seg,&EbdaData->ata.devices[device].sectors_low) >>11 );case ATA_TYPE_ATAPI :// Read ATA/ATAPI version ataversion=((Bit16u)(read_byte (get_SS (),buffer+161 ))<<8 )|read_byte (get_SS (),buffer+160 ); -for (version=15 ;version>0 ;version--) { +for (version=15 ;version>0 ;version--) {if ((ataversion&(1 <<version))!=0 )break ; }
@@ -2816,7 +2854,7 @@for (i=0 ;i<20 ;i++){write_byte (get_SS (),model+(i*2 ),read_byte (get_SS (),buffer+(i*2 )+54 +1 ));write_byte (get_SS (),model+(i*2 )+1 ,read_byte (get_SS (),buffer+(i*2 )+54 )); - } + }// Reformat write_byte (get_SS (),model+40 ,0x00 );
@@ -2824,7 +2862,13 @@if (read_byte (get_SS (),model+i)==0x20 )write_byte (get_SS (),model+i,0x00 );else break ; - } + } +if (i>36 ) { +write_byte (get_SS (),model+36 ,0x00 ); +for (i=35 ;i>32 ;i--){ +write_byte (get_SS (),model+i,0x2E ); + } + }break ; }
@@ -2832,10 +2876,10 @@case ATA_TYPE_ATA :printf ("ata%d %s: " ,channel,slave?" slave" :"master" ); i=0 ;while (c=read_byte (get_SS (),model+i++))printf ("%c" ,c); -if (sizeinmb <1UL <<16 ) -printf (" ATA-%d Hard-Disk (%04u MBytes)\n" ,version,(Bit16u )sizeinmb); -else -printf (" ATA-%d Hard-Disk (%04u GBytes)\n" ,version,(Bit16u)(sizeinmb>>10 )); +if (sizeinmb < (1UL <<16 )) +printf (" ATA-%d Hard-Disk (%4u MBytes)\n" , version, (Bit16u )sizeinmb); +else +printf (" ATA-%d Hard-Disk (%4u GBytes)\n" , version, (Bit16u)(sizeinmb>>10 ));break ;case ATA_TYPE_ATAPI :printf ("ata%d %s: " ,channel,slave?" slave" :"master" );
@@ -2856,17 +2900,17 @@write_byte (ebda_seg,&EbdaData->ata.hdcount, hdcount);write_byte (ebda_seg,&EbdaData->ata.cdcount, cdcount);write_byte (0x40 ,0x75 , hdcount); - +printf ("\n" );// FIXME : should use bios=cmos|auto|disable bits // FIXME : should know about translation bits -// FIXME : move hard_drive_post here - -} - -// --------------------------------------------------------------------------- -// ATA/ATAPI driver : software reset +// FIXME : move hard_drive_post here + +} + +// --------------------------------------------------------------------------- +// ATA/ATAPI driver : software reset // --------------------------------------------------------------------------- // ATA-3 // 8.2.1 Software reset - Device 0
@@ -2876,7 +2920,8 @@ {Bit16u ebda_seg=read_word (0x0040 ,0x000E );Bit16u iobase1, iobase2; -Bit8u channel, slave, sn, sc; +Bit8u channel, slave, sn, sc; +Bit8u type;Bit16u max; channel = device /2 ;
@@ -2891,16 +2936,13 @@outb (iobase2+ATA_CB_DC ,ATA_CB_DC_HD15 |ATA_CB_DC_NIEN |ATA_CB_DC_SRST );// 8.2.1 (b) -- wait for BSY - max=0xff ; -while (--max>0 ) { -Bit8u status =inb (iobase1+ATA_CB_STAT ); -if ((status &ATA_CB_STAT_BSY ) !=0 )break ; - } +await_ide (BSY , iobase1,20 );// 8.2.1 (f) -- clear SRST outb (iobase2+ATA_CB_DC ,ATA_CB_DC_HD15 |ATA_CB_DC_NIEN ); -if (read_byte (ebda_seg,&EbdaData->ata.devices[device].type) !=ATA_TYPE_NONE ) { + type=read_byte (ebda_seg,&EbdaData->ata.devices[device].type); +if (type !=ATA_TYPE_NONE ) {// 8.2.1 (g) -- check for sc==sn==0x01 // select device
@@ -2909,21 +2951,14 @@ sn =inb (iobase1+ATA_CB_SN );if ( (sc==0x01 ) && (sn==0x01 ) ) { +if (type ==ATA_TYPE_ATA )//ATA +await_ide (NOT_BSY_RDY , iobase1,IDE_TIMEOUT ); +else //ATAPI +await_ide (NOT_BSY , iobase1,IDE_TIMEOUT ); + }// 8.2.1 (h) -- wait for not BSY - max=0xff ; -while (--max>0 ) { -Bit8u status =inb (iobase1+ATA_CB_STAT ); -if ((status &ATA_CB_STAT_BSY ) ==0 )break ; - } - } - } - -// 8.2.1 (i) -- wait for DRDY - max=0xfff ; -while (--max>0 ) { -Bit8u status =inb (iobase1+ATA_CB_STAT ); -if ((status &ATA_CB_STAT_RDY ) !=0 )break ; +await_ide (NOT_BSY , iobase1,IDE_TIMEOUT ); }// Enable interrupts
@@ -2931,7 +2966,7 @@ }// --------------------------------------------------------------------------- -// ATA/ATAPI driver : execute a non data command +// ATA/ATAPI driver : execute a non data command // --------------------------------------------------------------------------- Bit16u ata_cmd_non_data ()
@@ -2949,9 +2984,9 @@// 5 : more sectors to read/verify // 6 : no sectors left to write // 7 : more sectors to write -Bit16u ata_cmd_data_in (device, command, count, cylinder, head, sector, lba, segment, offset) +Bit16u ata_cmd_data_in (device, command, count, cylinder, head, sector, lba_low, lba_high, segment, offset)Bit16u device, command, count, cylinder, head, sector, segment, offset; -Bit32u lba; +Bit32u lba_low, lba_high; {Bit16u ebda_seg=read_word (0x0040 ,0x000E );Bit16u iobase1, iobase2, blksize;
@@ -2980,22 +3015,20 @@// sector will be 0 only on lba access. Convert to lba-chs if (sector ==0 ) { -if ((count >=1 <<8 ) || (lba + count >=1UL <<28 )) { +if ((count >=1 <<8 ) || lba_high || (lba_low + count >=1UL <<28 )) {outb (iobase1 +ATA_CB_FR ,0x00 );outb (iobase1 +ATA_CB_SC , (count >>8 ) &0xff ); -outb (iobase1 +ATA_CB_SN , lba >>24 ); -outb (iobase1 +ATA_CB_CL ,0 ); -outb (iobase1 +ATA_CB_CH ,0 ); +outb (iobase1 +ATA_CB_SN , lba_low >>24 ); +outb (iobase1 +ATA_CB_CL , lba_high &0xff ); +outb (iobase1 +ATA_CB_CH , lba_high >>8 ); command |=0x04 ; count &= (1UL <<8 ) -1 ; - lba &= (1UL <<24 ) -1 ; - } - sector = (Bit16u) (lba &0x000000ffL ); - lba >>=8 ; - cylinder = (Bit16u) (lba &0x0000ffffL ); - lba >>=16 ; - head = ((Bit16u) (lba &0x0000000fL )) |0x40 ; - } + lba_low &= (1UL <<24 ) -1 ; + } + sector = (Bit16u) (lba_low &0x000000ffL ); + cylinder = (Bit16u) ((lba_low>>8 ) &0x0000ffffL ); + head = ((Bit16u) ((lba_low>>24 ) &0x0000000fL )) |ATA_CB_DH_LBA ; + }outb (iobase1 +ATA_CB_FR ,0x00 );outb (iobase1 +ATA_CB_SC , count);
@@ -3005,10 +3038,8 @@outb (iobase1 +ATA_CB_DH , (slave ?ATA_CB_DH_DEV1 :ATA_CB_DH_DEV0 ) | (Bit8u ) head );outb (iobase1 +ATA_CB_CMD , command); -while (1 ) { - status =inb (iobase1 +ATA_CB_STAT ); -if ( !(status &ATA_CB_STAT_BSY ) )break ; - } +await_ide (NOT_BSY_DRQ , iobase1,IDE_TIMEOUT ); + status =inb (iobase1 +ATA_CB_STAT );if (status &ATA_CB_STAT_ERR ) {BX_DEBUG_ATA ("ata_cmd_data_in : read error\n" );
@@ -3029,12 +3060,12 @@ASM_START push bp mov bp, sp - mov di, _ata_cmd_data_in.offset + 2[bp] - mov ax, _ata_cmd_data_in.segment + 2[bp] - mov cx, _ata_cmd_data_in.blksize + 2[bp] + mov di, _ata_cmd_data_in.offset + 2[bp] + mov ax, _ata_cmd_data_in.segment + 2[bp] + mov cx, _ata_cmd_data_in.blksize + 2[bp] ;; adjust if there will be an overrun. 2K max sector size - cmp di, #0xf800 ;; + cmp di, #0xf800 ;; jbe ata_in_no_adjust ata_in_adjust:
@@ -3046,7 +3077,7 @@ mov dx, _ata_cmd_data_in.iobase1 + 2[bp] ;; ATA data read port - mov ah, _ata_cmd_data_in.mode + 2[bp] + mov ah, _ata_cmd_data_in.mode + 2[bp] cmp ah, #ATA_MODE_PIO32 je ata_in_32
@@ -3068,9 +3099,10 @@ current++;write_word (ebda_seg, &EbdaData->ata.trsfsectors,current); count--; +await_ide (NOT_BSY , iobase1,IDE_TIMEOUT ); status =inb (iobase1 +ATA_CB_STAT );if (count ==0 ) { -if ( (status & (ATA_CB_STAT_BSY |ATA_CB_STAT_RDY |ATA_CB_STAT_DRQ |ATA_CB_STAT_ERR ) ) +if ( (status & (ATA_CB_STAT_BSY |ATA_CB_STAT_RDY |ATA_CB_STAT_DRQ |ATA_CB_STAT_ERR ) ) !=ATA_CB_STAT_RDY ) {BX_DEBUG_ATA ("ata_cmd_data_in : no sectors left (status %02x)\n" , (unsigned ) status);return 4 ;
@@ -3078,7 +3110,7 @@break ; }else { -if ( (status & (ATA_CB_STAT_BSY |ATA_CB_STAT_RDY |ATA_CB_STAT_DRQ |ATA_CB_STAT_ERR ) ) +if ( (status & (ATA_CB_STAT_BSY |ATA_CB_STAT_RDY |ATA_CB_STAT_DRQ |ATA_CB_STAT_ERR ) ) != (ATA_CB_STAT_RDY |ATA_CB_STAT_DRQ ) ) {BX_DEBUG_ATA ("ata_cmd_data_in : more sectors left (status %02x)\n" , (unsigned ) status);return 5 ;
@@ -3103,9 +3135,9 @@// 5 : more sectors to read/verify // 6 : no sectors left to write // 7 : more sectors to write -Bit16u ata_cmd_data_out (device, command, count, cylinder, head, sector, lba, segment, offset) +Bit16u ata_cmd_data_out (device, command, count, cylinder, head, sector, lba_low, lba_high, segment, offset)Bit16u device, command, count, cylinder, head, sector, segment, offset; -Bit32u lba; +Bit32u lba_low, lba_high; {Bit16u ebda_seg=read_word (0x0040 ,0x000E );Bit16u iobase1, iobase2, blksize;
@@ -3134,22 +3166,20 @@// sector will be 0 only on lba access. Convert to lba-chs if (sector ==0 ) { -if ((count >=1 <<8 ) || (lba + count >=1UL <<28 )) { +if ((count >=1 <<8 ) || lba_high || (lba_low + count >=1UL <<28 )) {outb (iobase1 +ATA_CB_FR ,0x00 );outb (iobase1 +ATA_CB_SC , (count >>8 ) &0xff ); -outb (iobase1 +ATA_CB_SN , lba >>24 ); -outb (iobase1 +ATA_CB_CL ,0 ); -outb (iobase1 +ATA_CB_CH ,0 ); +outb (iobase1 +ATA_CB_SN , lba_low >>24 ); +outb (iobase1 +ATA_CB_CL , lba_high &0xff ); +outb (iobase1 +ATA_CB_CH , lba_high >>8 ); command |=0x04 ; count &= (1UL <<8 ) -1 ; - lba &= (1UL <<24 ) -1 ; - } - sector = (Bit16u) (lba &0x000000ffL ); - lba >>=8 ; - cylinder = (Bit16u) (lba &0x0000ffffL ); - lba >>=16 ; - head = ((Bit16u) (lba &0x0000000fL )) |0x40 ; - } + lba_low &= (1UL <<24 ) -1 ; + } + sector = (Bit16u) (lba_low &0x000000ffL ); + cylinder = (Bit16u) ((lba_low>>8 ) &0x0000ffffL ); + head = ((Bit16u) ((lba_low>>24 ) &0x0000000fL )) |ATA_CB_DH_LBA ; + }outb (iobase1 +ATA_CB_FR ,0x00 );outb (iobase1 +ATA_CB_SC , count);
@@ -3159,10 +3189,8 @@outb (iobase1 +ATA_CB_DH , (slave ?ATA_CB_DH_DEV1 :ATA_CB_DH_DEV0 ) | (Bit8u ) head );outb (iobase1 +ATA_CB_CMD , command); -while (1 ) { - status =inb (iobase1 +ATA_CB_STAT ); -if ( !(status &ATA_CB_STAT_BSY ) )break ; - } +await_ide (NOT_BSY_DRQ , iobase1,IDE_TIMEOUT ); + status =inb (iobase1 +ATA_CB_STAT );if (status &ATA_CB_STAT_ERR ) {BX_DEBUG_ATA ("ata_cmd_data_out : read error\n" );
@@ -3183,12 +3211,12 @@ASM_START push bp mov bp, sp - mov si, _ata_cmd_data_out.offset + 2[bp] - mov ax, _ata_cmd_data_out.segment + 2[bp] - mov cx, _ata_cmd_data_out.blksize + 2[bp] + mov si, _ata_cmd_data_out.offset + 2[bp] + mov ax, _ata_cmd_data_out.segment + 2[bp] + mov cx, _ata_cmd_data_out.blksize + 2[bp] ;; adjust if there will be an overrun. 2K max sector size - cmp si, #0xf800 ;; + cmp si, #0xf800 ;; jbe ata_out_no_adjust ata_out_adjust:
@@ -3200,7 +3228,7 @@ mov dx, _ata_cmd_data_out.iobase1 + 2[bp] ;; ATA data write port - mov ah, _ata_cmd_data_out.mode + 2[bp] + mov ah, _ata_cmd_data_out.mode + 2[bp] cmp ah, #ATA_MODE_PIO32 je ata_out_32
@@ -3226,7 +3254,7 @@ count--; status =inb (iobase1 +ATA_CB_STAT );if (count ==0 ) { -if ( (status & (ATA_CB_STAT_BSY |ATA_CB_STAT_RDY |ATA_CB_STAT_DF |ATA_CB_STAT_DRQ |ATA_CB_STAT_ERR ) ) +if ( (status & (ATA_CB_STAT_BSY |ATA_CB_STAT_RDY |ATA_CB_STAT_DF |ATA_CB_STAT_DRQ |ATA_CB_STAT_ERR ) ) !=ATA_CB_STAT_RDY ) {BX_DEBUG_ATA ("ata_cmd_data_out : no sectors left (status %02x)\n" , (unsigned ) status);return 6 ;
@@ -3234,7 +3262,7 @@break ; }else { -if ( (status & (ATA_CB_STAT_BSY |ATA_CB_STAT_RDY |ATA_CB_STAT_DRQ |ATA_CB_STAT_ERR ) ) +if ( (status & (ATA_CB_STAT_BSY |ATA_CB_STAT_RDY |ATA_CB_STAT_DRQ |ATA_CB_STAT_ERR ) ) != (ATA_CB_STAT_RDY |ATA_CB_STAT_DRQ ) ) {BX_DEBUG_ATA ("ata_cmd_data_out : more sectors left (status %02x)\n" , (unsigned ) status);return 7 ;
@@ -3301,19 +3329,17 @@if (status &ATA_CB_STAT_BSY )return 2 ;outb (iobase2 +ATA_CB_DC ,ATA_CB_DC_HD15 |ATA_CB_DC_NIEN ); -// outb(iobase1 + ATA_CB_FR, 0x00); -// outb(iobase1 + ATA_CB_SC, 0x00); -// outb(iobase1 + ATA_CB_SN, 0x00); +outb (iobase1 +ATA_CB_FR ,0x00 ); +outb (iobase1 +ATA_CB_SC ,0x00 ); +outb (iobase1 +ATA_CB_SN ,0x00 );outb (iobase1 +ATA_CB_CL ,0xfff0 &0x00ff );outb (iobase1 +ATA_CB_CH ,0xfff0 >>8 );outb (iobase1 +ATA_CB_DH , slave ?ATA_CB_DH_DEV1 :ATA_CB_DH_DEV0 );outb (iobase1 +ATA_CB_CMD ,ATA_CMD_PACKET );// Device should ok to receive command -while (1 ) { - status =inb (iobase1 +ATA_CB_STAT ); -if ( !(status &ATA_CB_STAT_BSY ) )break ; - } +await_ide (NOT_BSY_DRQ , iobase1,IDE_TIMEOUT ); + status =inb (iobase1 +ATA_CB_STAT );if (status &ATA_CB_STAT_ERR ) {BX_DEBUG_ATA ("ata_cmd_packet : error, status is %02x\n" ,status);
@@ -3330,13 +3356,13 @@// Send command to device ASM_START sti ;; enable higher priority interrupts - + push bpmov bp, sp - - mov si, _ata_cmd_packet.cmdoff + 2[bp] - mov ax, _ata_cmd_packet.cmdseg + 2[bp] - mov cx, _ata_cmd_packet.cmdlen + 2[bp] + + mov si, _ata_cmd_packet.cmdoff + 2[bp] + mov ax, _ata_cmd_packet.cmdseg + 2[bp] + mov cx, _ata_cmd_packet.cmdlen + 2[bp] mov es, ax ;; segment in es mov dx, _ata_cmd_packet.iobase1 + 2[bp] ;; ATA data write port
@@ -3349,32 +3375,38 @@ASM_END if (inout == ATA_DATA_NO) { +await_ide (NOT_BSY , iobase1,IDE_TIMEOUT ); status =inb (iobase1 +ATA_CB_STAT ); } else { +Bit16u loops =0 ; +Bit8u sc;while (1 ) { +if (loops ==0 ) {//first time through + status =inb (iobase2 +ATA_CB_ASTAT ); +await_ide (NOT_BSY_DRQ , iobase1,IDE_TIMEOUT ); + } +else +await_ide (NOT_BSY , iobase1,IDE_TIMEOUT ); + loops++; + status =inb (iobase1 +ATA_CB_STAT ); + sc =inb (iobase1 +ATA_CB_SC );// Check if command completed -if ( (status & (ATA_CB_STAT_BSY |ATA_CB_STAT_DRQ ) ) ==0 )break ; +if (((inb (iobase1 +ATA_CB_SC )&0x7 )==0x3 ) && + ((status & (ATA_CB_STAT_RDY |ATA_CB_STAT_ERR )) ==ATA_CB_STAT_RDY ))break ;if (status &ATA_CB_STAT_ERR ) {BX_DEBUG_ATA ("ata_cmd_packet : error (status %02x)\n" ,status);return 3 ; } -// Device must be ready to send data -if ( (status & (ATA_CB_STAT_BSY |ATA_CB_STAT_RDY |ATA_CB_STAT_DRQ |ATA_CB_STAT_ERR ) ) - != (ATA_CB_STAT_RDY |ATA_CB_STAT_DRQ ) ) { -BX_DEBUG_ATA ("ata_cmd_packet : not ready (status %02x)\n" , status); -return 4 ; - } -// Normalize address bufseg += (bufoff /16 ); bufoff %=16 ; - +// Get the byte count lcount = ((Bit16u)(inb (iobase1 +ATA_CB_CH ))<<8 )+inb (iobase1 +ATA_CB_CL );
@@ -3435,10 +3467,10 @@ mov dx, _ata_cmd_packet.iobase1 + 2[bp] ;; ATA data read port - mov cx, _ata_cmd_packet.lbefore + 2[bp] + mov cx, _ata_cmd_packet.lbefore + 2[bp] jcxz ata_packet_no_before - mov ah, _ata_cmd_packet.lmode + 2[bp] + mov ah, _ata_cmd_packet.lmode + 2[bp] cmp ah, #ATA_MODE_PIO32 je ata_packet_in_before_32
@@ -3455,14 +3487,14 @@ pop eax ata_packet_no_before: - mov cx, _ata_cmd_packet.lcount + 2[bp] + mov cx, _ata_cmd_packet.lcount + 2[bp] jcxz ata_packet_after - mov di, _ata_cmd_packet.bufoff + 2[bp] - mov ax, _ata_cmd_packet.bufseg + 2[bp] + mov di, _ata_cmd_packet.bufoff + 2[bp] + mov ax, _ata_cmd_packet.bufseg + 2[bp] mov es, ax - mov ah, _ata_cmd_packet.lmode + 2[bp] + mov ah, _ata_cmd_packet.lmode + 2[bp] cmp ah, #ATA_MODE_PIO32 je ata_packet_in_32
@@ -3476,10 +3508,10 @@ insd ;; CX dwords transfered to port(DX) to ES:[DI] ata_packet_after: - mov cx, _ata_cmd_packet.lafter + 2[bp] + mov cx, _ata_cmd_packet.lafter + 2[bp] jcxz ata_packet_done - mov ah, _ata_cmd_packet.lmode + 2[bp] + mov ah, _ata_cmd_packet.lmode + 2[bp] cmp ah, #ATA_MODE_PIO32 je ata_packet_in_after_32
@@ -3509,7 +3541,7 @@ }// Final check, device must be ready -if ( (status & (ATA_CB_STAT_BSY |ATA_CB_STAT_RDY |ATA_CB_STAT_DF |ATA_CB_STAT_DRQ |ATA_CB_STAT_ERR ) ) +if ( (status & (ATA_CB_STAT_BSY |ATA_CB_STAT_RDY |ATA_CB_STAT_DF |ATA_CB_STAT_DRQ |ATA_CB_STAT_ERR ) ) !=ATA_CB_STAT_RDY ) {BX_DEBUG_ATA ("ata_cmd_packet : not ready (status %02x)\n" , (unsigned ) status);return 4 ;
@@ -3528,55 +3560,108 @@// Start of ATA/ATAPI generic functions // --------------------------------------------------------------------------- -Bit16u -atapi_get_sense (device) +Bit16u +atapi_get_sense (device, seg, asc, ascq)Bit16u device; {Bit8u atacmd[12 ]; -Bit8u buffer[16 ]; +Bit8u buffer[18 ];Bit8u i;memsetb (get_SS (),atacmd,0 ,12 ); -// Request SENSE - atacmd[0 ]=0x03 ; - atacmd[4 ]=0x20 ; -if (ata_cmd_packet (device,12 ,get_SS (), atacmd,0 ,16L ,ATA_DATA_IN ,get_SS (), buffer) !=0 ) +// Request SENSE + atacmd[0 ]=ATA_CMD_REQUEST_SENSE ; + atacmd[4 ]=sizeof (buffer); +if (ata_cmd_packet (device,12 ,get_SS (), atacmd,0 ,18L ,ATA_DATA_IN ,get_SS (), buffer) !=0 )return 0x0002 ; -if ((buffer[0 ] &0x7e ) ==0x70 ) { -return (((Bit16u )buffer[2 ]&0x0f )*0x100 )+buffer[12 ]; - } +write_byte (seg,asc,buffer[12 ]); +write_byte (seg,ascq,buffer[13 ]);return 0 ; } -Bit16u +Bit16u atapi_is_ready (device)Bit16u device; { -Bit8u atacmd[12 ]; -Bit8u buffer[]; - -memsetb (get_SS (),atacmd,0 ,12 ); - -// Test Unit Ready -if (ata_cmd_packet (device,12 ,get_SS (), atacmd,0 ,0L ,ATA_DATA_NO ,get_SS (), buffer) !=0 ) -return 0x000f ; - -if (atapi_get_sense (device) !=0 ) { -memsetb (get_SS (),atacmd,0 ,12 ); - -// try to send Test Unit Ready again -if (ata_cmd_packet (device,12 ,get_SS (), atacmd,0 ,0L ,ATA_DATA_NO ,get_SS (), buffer) !=0 ) -return 0x000f ; - -return atapi_get_sense (device); - } +Bit8u packet[12 ]; +Bit8u buf[8 ]; +Bit32u block_len; +Bit32u sectors; +Bit32u timeout;//measured in ms +Bit32u time; +Bit8u asc, ascq; +Bit8u in_progress; +Bit16u ebda_seg =read_word (0x0040 ,0x000E ); +if (read_byte (ebda_seg,&EbdaData->ata.devices[device].type) !=ATA_TYPE_ATAPI ) { +printf ("not implemented for non-ATAPI device\n" ); +return -1 ; + } + +BX_DEBUG_ATA ("ata_detect_medium: begin\n" ); +memsetb (get_SS (),packet,0 ,sizeof packet); + packet[0 ] =0x25 ;/* READ CAPACITY */ + +/* Retry READ CAPACITY 50 times unless MEDIUM NOT PRESENT +* is reported by the device. If the device reports "IN PROGRESS", +* 30 seconds is added. */ + timeout =5000 ; + time =0 ; + in_progress =0 ; +while (time < timeout) { +if (ata_cmd_packet (device,sizeof (packet),get_SS (), packet,0 ,8L ,ATA_DATA_IN ,get_SS (), buf) ==0 ) + goto ok; + +if (atapi_get_sense (device,get_SS (), &asc, &ascq) ==0 ) { +if (asc ==0x3a ) {/* MEDIUM NOT PRESENT */ +BX_DEBUG_ATA ("Device reports MEDIUM NOT PRESENT\n" ); +return -1 ; + } + +if (asc ==0x04 && ascq ==0x01 && !in_progress) { +/* IN PROGRESS OF BECOMING READY */ +printf ("Waiting for device to detect medium... " ); +/* Allow 30 seconds more */ + timeout =30000 ; + in_progress =1 ; + } + } + time +=100 ; + } +BX_DEBUG_ATA ("read capacity failed\n" ); +return -1 ; +ok: + + block_len = (Bit32u ) buf[4 ] <<24 + | (Bit32u ) buf[5 ] <<16 + | (Bit32u ) buf[6 ] <<8 + | (Bit32u ) buf[7 ] <<0 ; +BX_DEBUG_ATA ("block_len=%u\n" , block_len); + +if (block_len!=2048 && block_len!=512 ) + { +printf ("Unsupported sector size %u\n" , block_len); +return -1 ; + } +write_dword (ebda_seg,&EbdaData->ata.devices[device].blksize, block_len); + + sectors = (Bit32u ) buf[0 ] <<24 + | (Bit32u ) buf[1 ] <<16 + | (Bit32u ) buf[2 ] <<8 + | (Bit32u ) buf[3 ] <<0 ; + +BX_DEBUG_ATA ("sectors=%u\n" , sectors); +if (block_len ==2048 ) + sectors <<=2 ;/* # of sectors in 512-byte "soft" sector */ +if (sectors !=read_dword (ebda_seg,&EbdaData->ata.devices[device].sectors_low)) +printf ("%dMB medium detected\n" , sectors>>(20 -9 )); +write_dword (ebda_seg,&EbdaData->ata.devices[device].sectors_low, sectors);return 0 ; } -Bit16u +Bit16u atapi_is_cdrom (device)Bit8u device; {
@@ -3636,7 +3721,7 @@// // Returns ah: emulated drive, al: error code // -Bit16u +Bit16u cdrom_boot () {Bit16u ebda_seg=read_word (0x0040 ,0x000E );
@@ -3649,9 +3734,12 @@for (device=0 ; device<BX_MAX_ATA_DEVICES ;device++) {if (atapi_is_cdrom (device))break ; } - +// if not found if (device >=BX_MAX_ATA_DEVICES )return 2 ; + +if (error =atapi_is_ready (device) !=0 ) +BX_INFO ("ata_is_ready returned %d\n" ,error);// Read the Boot Record Volume Descriptor memsetb (get_SS (),atacmd,0 ,12 );
@@ -3672,7 +3760,7 @@ }for (i=0 ;i<23 ;i++)if (buffer[7 +i]!=read_byte (0xf000 ,&eltorito[i]))return 6 ; - +// ok, now we calculate the Boot catalog address lba=buffer[0x4A ]*0x1000000 +buffer[0x49 ]*0x10000 +buffer[0x48 ]*0x100 +buffer[0x47 ];
@@ -3687,7 +3775,7 @@ atacmd[5 ]=(lba &0x000000ff );if ((error =ata_cmd_packet (device,12 ,get_SS (), atacmd,0 ,2048L ,ATA_DATA_IN ,get_SS (), buffer)) !=0 )return 7 ; - +// Validation entry if (buffer[0x00 ]!=0x01 )return 8 ;// Header if (buffer[0x01 ]!=0x00 )return 9 ;// Platform
@@ -3706,10 +3794,10 @@write_byte (ebda_seg,&EbdaData->cdemu.media,buffer[0x21 ]);if (buffer[0x21 ]==0 ){ -// FIXME ElTorito Hardcoded. cdrom is hardcoded as device 0xE0. +// FIXME ElTorito Hardcoded. cdrom is hardcoded as device 0xE0. // Win2000 cd boot needs to know it booted from cd write_byte (ebda_seg,&EbdaData->cdemu.emulated_drive,0xE0 ); - } + }else if (buffer[0x21 ]<4 )write_byte (ebda_seg,&EbdaData->cdemu.emulated_drive,0x00 );else
@@ -3723,7 +3811,7 @@write_word (ebda_seg,&EbdaData->cdemu.load_segment,boot_segment);write_word (ebda_seg,&EbdaData->cdemu.buffer_segment,0x0000 ); - + nbsectors=buffer[0x27 ]*0x100 +buffer[0x26 ];write_word (ebda_seg,&EbdaData->cdemu.sector_count,nbsectors);
@@ -3748,7 +3836,6 @@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
@@ -3769,7 +3856,7 @@case 0x04 :// Harddrive write_word (ebda_seg,&EbdaData->cdemu.vdevice.spt,read_byte (boot_segment,446 +6 )&0x3f );write_word (ebda_seg,&EbdaData->cdemu.vdevice.cylinders, - (read_byte (boot_segment,446 +6 )<<2 ) +read_byte (boot_segment,446 +7 ) +1 ); + (read_byte (boot_segment,446 +6 )<<2 ) +read_byte (boot_segment,446 +7 ) +1 );write_word (ebda_seg,&EbdaData->cdemu.vdevice.heads,read_byte (boot_segment,446 +5 ) +1 );break ; }
@@ -3782,7 +3869,7 @@write_byte (ebda_seg, &EbdaData->ata.hdcount,read_byte (ebda_seg, &EbdaData->ata.hdcount) +1 ); } - +// everything is ok, so from now on, the emulation is active if (read_byte (ebda_seg,&EbdaData->cdemu.media)!=0 )write_byte (ebda_seg,&EbdaData->cdemu.active,0x01 );
@@ -4128,9 +4215,10 @@ regs.u.r8.al =inb_cmos (0x30 ); regs.u.r8.ah =inb_cmos (0x31 ); -// limit to 15M -if (regs.u.r16.ax >0x3c00 ) - regs.u.r16.ax =0x3c00 ; +// According to Ralf Brown's interrupt the limit should be 15M, +// but real machines mostly return max. 63M. +if (regs.u.r16.ax >0xffc0 ) + regs.u.r16.ax =0xffc0 ;CLEAR_CF ();#endif
@@ -4348,13 +4436,35 @@case 3 :// Set Resolution BX_DEBUG_INT15 ("case 3:\n" ); -// BX: +// BH: // 0 = 25 dpi, 1 count per millimeter // 1 = 50 dpi, 2 counts per millimeter // 2 = 100 dpi, 4 counts per millimeter // 3 = 200 dpi, 8 counts per millimeter -CLEAR_CF (); - regs.u.r8.ah =0 ; + comm_byte =inhibit_mouse_int_and_events ();// disable IRQ12 and packets +if (regs.u.r8.bh <4 ) { + ret =send_to_mouse_ctrl (0xE8 );// set resolution command +if (ret ==0 ) { + ret =get_mouse_data (&mouse_data1); +if (mouse_data1 !=0xfa ) +BX_PANIC ("Mouse status returned %02x (should be ack)\n" , (unsigned )mouse_data1); + ret =send_to_mouse_ctrl (regs.u.r8.bh); + ret =get_mouse_data (&mouse_data1); +if (mouse_data1 !=0xfa ) +BX_PANIC ("Mouse status returned %02x (should be ack)\n" , (unsigned )mouse_data1); +CLEAR_CF (); + regs.u.r8.ah =0 ; + }else { +// error +SET_CF (); + regs.u.r8.ah =UNSUPPORTED_FUNCTION ; + } + }else { +// error +SET_CF (); + regs.u.r8.ah =UNSUPPORTED_FUNCTION ; + } +set_kbd_command_byte (comm_byte);// restore IRQ12 and serial enable break ;case 4 :// Get Device ID
@@ -4476,7 +4586,30 @@ break; } } -#endif +#endif // BX_USE_PS2_MOUSE + + +void set_e820_range (ES ,DI , start, end, type) +Bit16u ES ; +Bit16u DI ; +Bit32u start; +Bit32u end; +Bit16u type; +{ +write_word (ES ,DI , start); +write_word (ES ,DI +2 , start >>16 ); +write_word (ES ,DI +4 ,0x00 ); +write_word (ES ,DI +6 ,0x00 ); + + end -= start; +write_word (ES ,DI +8 , end); +write_word (ES ,DI +10 , end >>16 ); +write_word (ES ,DI +12 ,0x0000 ); +write_word (ES ,DI +14 ,0x0000 ); + +write_word (ES ,DI +16 , type); +write_word (ES ,DI +18 ,0x0 ); +}void int15_function32 (regs ,ES ,DS ,FLAGS )
@@ -4490,17 +4623,20 @@switch (regs.u.r8.ah) {case 0x86 : -// Wait for CX:DX microseconds. currently using the -// refresh request port 0x61 bit4, toggling every 15usec +// Wait for CX:DX microseconds. currently using the +// refresh request port 0x61 bit4, toggling every 15usec CX = regs.u.r16.cx;DX = regs.u.r16.dx;ASM_START + sti + ;; Get the count in eax - mov ax, .int15_function32.CX [bp] + mov bx, sp + mov ax, _int15_function32.CX [bx] shl eax, #16 - mov ax, .int15_function32.DX [bp] + mov ax, _int15_function32.DX [bx] ;; convert to numbers of 15usec ticks mov ebx, #15
@@ -4531,7 +4667,8 @@case 0xe8 :switch (regs.u.r8.al) { -case 0x20 : { +#ifdef HVMASSIST +case 0x20 : {Bit16u e820_table_size =read_word (0xe000 ,0x8 ) *0x14 ;if (regs.u.r32.edx !=0x534D4150 )/* SMAP */
@@ -4579,7 +4716,7 @@// 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 ;
@@ -4607,7 +4744,7 @@ regs.u.r16.bx = regs.u.r16.dx;break ; } -default :/* AH=0xE8?? but not implemented */ +default :/* AH=0xE8?? but not implemented */ goto int15_unimplemented; }break ;
@@ -4620,16 +4757,178 @@ regs.u.r8.ah =UNSUPPORTED_FUNCTION ;break ; } +#else +case 0x20 :// coded by osmaker aka K.J. +if (regs.u.r32.edx ==0x534D4150 ) + { + extended_memory_size =inb_cmos (0x35 ); + extended_memory_size <<=8 ; + extended_memory_size |=inb_cmos (0x34 ); + extended_memory_size *=64 ; +// greater than EFF00000??? +if (extended_memory_size >0x3bc000 ) { + extended_memory_size =0x3bc000 ;// everything after this is reserved memory until we get to 0x100000000 + } + extended_memory_size *=1024 ; + extended_memory_size += (16L *1024 *1024 ); + +if (extended_memory_size <= (16L *1024 *1024 )) { + extended_memory_size =inb_cmos (0x31 ); + extended_memory_size <<=8 ; + extended_memory_size |=inb_cmos (0x30 ); + extended_memory_size *=1024 ; + extended_memory_size += (1L *1024 *1024 ); + } + +switch (regs.u.r16.bx) + { +case 0 : +set_e820_range (ES , regs.u.r16.di, +0x0000000L ,0x0009f000L ,1 ); + regs.u.r32.ebx =1 ; + regs.u.r32.eax =0x534D4150 ; + regs.u.r32.ecx =0x14 ; +CLEAR_CF (); +return ; +break ; +case 1 : +set_e820_range (ES , regs.u.r16.di, +0x0009f000L ,0x000a0000L ,2 ); + regs.u.r32.ebx =2 ; + regs.u.r32.eax =0x534D4150 ; + regs.u.r32.ecx =0x14 ; +CLEAR_CF (); +return ; +break ; +case 2 : +set_e820_range (ES , regs.u.r16.di, +0x000e8000L ,0x00100000L ,2 ); + regs.u.r32.ebx =3 ; + regs.u.r32.eax =0x534D4150 ; + regs.u.r32.ecx =0x14 ; +CLEAR_CF (); +return ; +break ; +case 3 : +#if BX_ROMBIOS32 +set_e820_range (ES , regs.u.r16.di, +0x00100000L , + extended_memory_size -ACPI_DATA_SIZE ,1 ); + regs.u.r32.ebx =4 ; +#else +set_e820_range (ES , regs.u.r16.di, +0x00100000L , + extended_memory_size,1 ); + regs.u.r32.ebx =5 ; +#endif + regs.u.r32.eax =0x534D4150 ; + regs.u.r32.ecx =0x14 ; +CLEAR_CF (); +return ; +break ; +case 4 : +set_e820_range (ES , regs.u.r16.di, + extended_memory_size -ACPI_DATA_SIZE , + extended_memory_size,3 );// ACPI RAM + regs.u.r32.ebx =5 ; + regs.u.r32.eax =0x534D4150 ; + regs.u.r32.ecx =0x14 ; +CLEAR_CF (); +return ; +break ; +case 5 : +/* 256KB BIOS area at the end of 4 GB */ +set_e820_range (ES , regs.u.r16.di, +0xfffc0000L ,0x00000000L ,2 ); + regs.u.r32.ebx =0 ; + regs.u.r32.eax =0x534D4150 ; + regs.u.r32.ecx =0x14 ; +CLEAR_CF (); +return ; +default :/* AX=E820, DX=534D4150, BX unrecognized */ + goto int15_unimplemented; +break ; + } + }else { +// if DX != 0x534D4150) + goto int15_unimplemented; + } +break ; + +case 0x01 : +// do we have any reason to fail here ? +CLEAR_CF (); + +// my real system sets ax and bx to 0 +// this is confirmed by Ralph Brown list +// but syslinux v1.48 is known to behave +// strangely if ax is set to 0 +// regs.u.r16.ax = 0; +// regs.u.r16.bx = 0; + +// 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 >0x3c00 ) + { + regs.u.r16.cx =0x3c00 ; + } + +// Get the amount of extended memory above 16M in 64k blocs + regs.u.r8.dl =inb_cmos (0x34 ); + regs.u.r8.dh =inb_cmos (0x35 ); + +// 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 ; + } +#endif /* HVMASSIST */ }void int16_function (DI ,SI ,BP ,SP ,BX ,DX ,CX ,AX ,FLAGS )Bit16u DI ,SI ,BP ,SP ,BX ,DX ,CX ,AX ,FLAGS ; { -Bit8u scan_code, ascii_code, shift_flags, count; +Bit8u scan_code, ascii_code, shift_flags, led_flags, count;Bit16u kbd_code, max;BX_DEBUG_INT16 ("int16: AX=%04x BX=%04x CX=%04x DX=%04x \n" ,AX ,BX ,CX ,DX ); + + shift_flags =read_byte (0x0040 ,0x17 ); + led_flags =read_byte (0x0040 ,0x97 ); +if ((((shift_flags >>4 ) &0x07 ) ^ (led_flags &0x07 )) !=0 ) { +ASM_START + cli +ASM_END + outb(0x60, 0xed); +while ((inb (0x64 ) &0x01 ) ==0 )outb (0x80 ,0x21 ); +if ((inb (0x60 ) ==0xfa )) { + led_flags &=0xf8 ; + led_flags |= ((shift_flags >>4 ) &0x07 ); +outb (0x60 , led_flags &0x07 ); +while ((inb (0x64 ) &0x01 ) ==0 )outb (0x80 ,0x21 ); +inb (0x60 ); +write_byte (0x0040 ,0x97 , led_flags); + } +ASM_START + sti +ASM_END + }switch (GET_AH ()) {case 0x00 :/* read keyboard input */
@@ -4668,7 +4967,7 @@break ;case 0x09 :/* GET KEYBOARD FUNCTIONALITY */ -// bit Bochs Description +// bit Bochs Description // 7 0 reserved // 6 0 INT 16/AH=20h-22h supported (122-key keyboard support) // 5 1 INT 16/AH=10h-12h supported (enhanced keyboard support)
@@ -4698,7 +4997,7 @@ kbd_code |= (inb (0x60 ) <<8 ); } }while (--count>0 ); - } + } }BX =kbd_code;break ;
@@ -4725,7 +5024,8 @@case 0x12 :/* get extended keyboard status */ shift_flags =read_byte (0x0040 ,0x17 );SET_AL (shift_flags); - shift_flags =read_byte (0x0040 ,0x18 ); + shift_flags =read_byte (0x0040 ,0x18 ) &0x73 ; + shift_flags |=read_byte (0x0040 ,0x96 ) &0x0c ;SET_AH (shift_flags);BX_DEBUG_INT16 ("int16: func 12 sending %04x\n" ,AX );break ;
@@ -4740,7 +5040,7 @@case 0x6F :if (GET_AL () ==0x08 ) -SET_AH (0x02 );// unsupported, aka normal keyboard +SET_AH (0x02 );// unsupported, aka normal keyboard default :BX_INFO ("KBD: unsupported int 16h function %02x\n" ,GET_AH ());
@@ -4881,7 +5181,7 @@Bit16u DI ,SI ,BP ,SP ,BX ,DX ,CX ,AX ; {Bit8u scancode, asciicode, shift_flags; -Bit8u mf2_flags, mf2_state, led_flags; +Bit8u mf2_flags, mf2_state;// // DS has been set to F000 before call
@@ -4899,7 +5199,6 @@ shift_flags =read_byte (0x0040 ,0x17 ); mf2_flags =read_byte (0x0040 ,0x18 ); mf2_state =read_byte (0x0040 ,0x96 ); - led_flags =read_byte (0x0040 ,0x97 ); asciicode =0 ;switch (scancode) {
@@ -4908,8 +5207,6 @@write_byte (0x0040 ,0x17 , shift_flags); mf2_flags |=0x40 ;write_byte (0x0040 ,0x18 , mf2_flags); - led_flags ^=0x04 ; -write_byte (0x0040 ,0x97 , led_flags);break ;case 0xba :/* Caps Lock release */ mf2_flags &= ~0x40 ;
@@ -4917,11 +5214,8 @@break ;case 0x2a :/* L Shift press */ -/*shift_flags &= ~0x40;*/ shift_flags |=0x02 ;write_byte (0x0040 ,0x17 , shift_flags); - led_flags &= ~0x04 ; -write_byte (0x0040 ,0x97 , led_flags);break ;case 0xaa :/* L Shift release */ shift_flags &= ~0x02 ;
@@ -4929,11 +5223,8 @@break ;case 0x36 :/* R Shift press */ -/*shift_flags &= ~0x40;*/ shift_flags |=0x01 ;write_byte (0x0040 ,0x17 , shift_flags); - led_flags &= ~0x04 ; -write_byte (0x0040 ,0x97 , led_flags);break ;case 0xb6 :/* R Shift release */ shift_flags &= ~0x01 ;
@@ -4941,71 +5232,75 @@break ;case 0x1d :/* Ctrl press */ - shift_flags |=0x04 ; -write_byte (0x0040 ,0x17 , shift_flags); -if (mf2_state &0x01 ) { - mf2_flags |=0x04 ; - }else { - mf2_flags |=0x01 ; - } -write_byte (0x0040 ,0x18 , mf2_flags); +if ((mf2_state &0x01 ) ==0 ) { + shift_flags |=0x04 ; +write_byte (0x0040 ,0x17 , shift_flags); +if (mf2_state &0x02 ) { + mf2_state |=0x04 ; +write_byte (0x0040 ,0x96 , mf2_state); + }else { + mf2_flags |=0x01 ; +write_byte (0x0040 ,0x18 , mf2_flags); + } + }break ;case 0x9d :/* Ctrl release */ - shift_flags &= ~0x04 ; -write_byte (0x0040 ,0x17 , shift_flags); -if (mf2_state &0x01 ) { - mf2_flags &= ~0x04 ; - }else { - mf2_flags &= ~0x01 ; - } -write_byte (0x0040 ,0x18 , mf2_flags); +if ((mf2_state &0x01 ) ==0 ) { + shift_flags &= ~0x04 ; +write_byte (0x0040 ,0x17 , shift_flags); +if (mf2_state &0x02 ) { + mf2_state &= ~0x04 ; +write_byte (0x0040 ,0x96 , mf2_state); + }else { + mf2_flags &= ~0x01 ; +write_byte (0x0040 ,0x18 , mf2_flags); + } + }break ;case 0x38 :/* Alt press */ shift_flags |=0x08 ;write_byte (0x0040 ,0x17 , shift_flags); -if (mf2_state &0x01 ) { - mf2_flags |=0x08 ; +if (mf2_state &0x02 ) { + mf2_state |=0x08 ; +write_byte (0x0040 ,0x96 , mf2_state); }else { mf2_flags |=0x02 ; - } -write_byte (0x0040 ,0x18 , mf2_flags); +write_byte (0x0040 ,0x18 , mf2_flags); + }break ;case 0xb8 :/* Alt release */ shift_flags &= ~0x08 ;write_byte (0x0040 ,0x17 , shift_flags); -if (mf2_state &0x01 ) { - mf2_flags &= ~0x08 ; +if (mf2_state &0x02 ) { + mf2_state &= ~0x08 ; +write_byte (0x0040 ,0x96 , mf2_state); }else { mf2_flags &= ~0x02 ; - } -write_byte (0x0040 ,0x18 , mf2_flags); +write_byte (0x0040 ,0x18 , mf2_flags); + }break ;case 0x45 :/* Num Lock press */ -if ((mf2_state &0x01 ) ==0 ) { +if ((mf2_state &0x03 ) ==0 ) { mf2_flags |=0x20 ;write_byte (0x0040 ,0x18 , mf2_flags); shift_flags ^=0x20 ; - led_flags ^=0x02 ;write_byte (0x0040 ,0x17 , shift_flags); -write_byte (0x0040 ,0x97 , led_flags); - } + }break ;case 0xc5 :/* Num Lock release */ -if ((mf2_state &0x01 ) ==0 ) { +if ((mf2_state &0x03 ) ==0 ) { mf2_flags &= ~0x20 ;write_byte (0x0040 ,0x18 , mf2_flags); - } + }break ;case 0x46 :/* Scroll Lock press */ mf2_flags |=0x10 ;write_byte (0x0040 ,0x18 , mf2_flags); shift_flags ^=0x10 ; - led_flags ^=0x01 ;write_byte (0x0040 ,0x17 , shift_flags); -write_byte (0x0040 ,0x97 , led_flags);break ;case 0xc6 :/* Scroll Lock release */
@@ -5018,50 +5313,55 @@machine_reset ();/* Fall through */ default : -if (scancode &0x80 )return ;/* toss key releases ... */ +if (scancode &0x80 ) { +break ;/* toss key releases ... */ + }if (scancode >MAX_SCAN_CODE ) { -BX_INFO ("KBD: int09h_handler(): unknown scancode (%x) read!\n" , scancode); -return ; - } +BX_INFO ("KBD: int09h_handler(): unknown scancode read: 0x%02x!\n" , scancode); +return ; + }if (shift_flags &0x08 ) {/* ALT */ asciicode = scan_to_scanascii[scancode].alt; scancode = scan_to_scanascii[scancode].alt >>8 ; - } -else if (shift_flags &0x04 ) {/* CONTROL */ + }else if (shift_flags &0x04 ) {/* CONTROL */ asciicode = scan_to_scanascii[scancode].control; scancode = scan_to_scanascii[scancode].control >>8 ; - } -else if (shift_flags &0x03 ) {/* LSHIFT + RSHIFT */ -/* check if lock state should be ignored + }else if (((mf2_state &0x02 ) >0 ) && ((scancode >=0x47 ) && (scancode <=0x53 ))) { +/* extended keys handling */ + asciicode =0xe0 ; + scancode = scan_to_scanascii[scancode].normal >>8 ; + }else if (shift_flags &0x03 ) {/* LSHIFT + RSHIFT */ +/* check if lock state should be ignored * because a SHIFT key are pressed */ - +if (shift_flags & scan_to_scanascii[scancode].lock_flags) { asciicode = scan_to_scanascii[scancode].normal; scancode = scan_to_scanascii[scancode].normal >>8 ; - } -else { + }else { asciicode = scan_to_scanascii[scancode].shift; scancode = scan_to_scanascii[scancode].shift >>8 ; - } - } -else { + } + }else {/* check if lock is on */
Lines of this file are not shown. View the raw message.
tools/firmware/rombios/rombios.h new file +70 -0
70 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel
Part of the diff is not shown here. View the raw message.
Quoted 16 lines · Stefan Berger
[email protected] wrote on 12/17/2008 09:50:35 AM:
Quoted 5 lines
Akio Takebe <[email protected]>
Sent by: [email protected]Subject
Quoted 8 lines
[Xen-devel] [Patch][RFC] Update
rombios.cHi, 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?
Quoted 5 lines
There are at least some problems now in the recent Boch's BIOSes with code sections filling up (spill into other functions' code and bcc not telling you about it) that require some rearranging of the code so that the TCGBIOS part fits in when activated. I can fix this when your code has been committed into the xen repository.
Thank you for your kindness.
Best Regards,
Akio Takebe
Quoted 9 lines · Akio Takebe
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 :-)
I forgot Singed-off-by line.
Best Regards,
Akio Takebe
Quoted 9 lines · Akio Takebe
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.c renamed from rombios.bochs.c +588 -124
@@ -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_ENDcase 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, Cwrite_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 segmentmov 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 segmentmov 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 AXmov 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 AXpush di ;;Save DI ;; Push addr of ROM entry pointpush 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, #0x0000je 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, #0xb1jne 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.h renamed from rombios.bochs.h +5 -2
@@ -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
[email protected]
http://lists.xensource.com/xen-devel
Hi,
Quoted 7 lines · Akio Takebe
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 :-)
Does the boot-options menu work properly after the patch? This bit of code looks suspect to me; surely some more translation is necessary to turn a scan code into an offset into the boot device table:
+ while (!valid_choice) {
+ scan_code = get_keystroke();
+ if (scan_code == 0x01 || scan_code == 0x58) /* ESC or F12 */
+ {
+ valid_choice = 1;
+ }
+ else if (scan_code <= count)
+ {
+ valid_choice = 1;
+ scan_code -= 1;
+ /* Set user selected device */
+ write_word(ebda_seg, IPL_BOOTFIRST_OFFSET, scan_code);+ }
+ }
Otherwise, this patch looks good to me, though it's enormous so I haven't looked at every detail.
Also: does this update mean that the Xen rombios now has two separate 32-bit extensions? Might it be worth using the upstream one instead of maintaining our own?
Cheers,
Tim.
Signature · 3 lines
Tim Deegan <[email protected]> Principal Software Engineer, Citrix Systems (R&D) Ltd. [Company #02300071, SL9 0DZ, UK.]
Quoted 20 lines · Tim Deegan
Hi,
Quoted 7 lines · Akio Takebe
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 :-)
Does the boot-options menu work properly after the patch? This bit of code looks suspect to me; surely some more translation is necessary to turn a scan code into an offset into the boot device table:
tools/firmware/rombios/rombios.c +4
-0+while (!valid_choice) { + scan_code =get_keystroke (); +if (scan_code ==0x01 || scan_code ==0x58 )/* ESC or F12 */ + {
tools/firmware/rombios/rombios.c line 2204
Quoted 10 lines
tools/firmware/rombios/rombios.c +10
-0+ valid_choice =1 ; + } +else if (scan_code <= count) + { + valid_choice =1 ; + scan_code -=1 ; +/* Set user selected device */ +write_word (ebda_seg,IPL_BOOTFIRST_OFFSET , scan_code); + } + }
Thank you for your review.
I used the bochs upstream code instead of xen's
because I want to use the upstream code.
It works fine. The scan_codes are below.
http://www.arl.wustl.edu/~lockwood/class/cs306/books/artofasm/APNDXC.PDF
Quoted 7 lines
Otherwise, this patch looks good to me, though it's enormous so I haven't looked at every detail.
Also: does this update mean that the Xen rombios now has two separate 32-bit extensions? Might it be worth using the upstream one instead of maintaining our own?
I added "#define LAGACY" in rombios.h
So the patch uses Xen's 32bit extentions.
As you said, using the upstream one may be better. But merging the upstream's 32bits extentions looks difficult because xen initialize some parts of BIOS data in hvmloader.
Best Regards,
Akio Takebe
Quoted 2 lines · Akio Takebe
It works fine. The
scan_codesare below.
http://www.arl.wustl.edu/~lockwood/class/cs306/books/artofasm/APNDXC.PDF
Ah, I see. :)
Quoted 5 lines
I added "#define LAGACY" in
rombios.h
So the patch uses Xen's 32bit extentions.
As you said, using the upstream one may be better. But merging the upstream's 32bits extentions looks difficult because xen initialize some parts of BIOS data in hvmloader.
Sure. There's certainly no need to do anything as part of this patch.
Cheers,
Tim.
Signature · 3 lines
Tim Deegan <[email protected]> Principal Software Engineer, Citrix Systems (R&D) Ltd. [Company #02300071, SL9 0DZ, UK.]