With new bigger hard disks available, more often is seen problem with old BIOSes those do not support bigger disks. Special case is Award BIOS 4.51PG prior to 05/1999 that freezes with disks above 34 GB. The only possibility how to boot the computer is to set the disk to "None". Some operating systems can use these disks, but not all of them will correctly set up the chipset registers for fastest operation - so the disk could be slow. And of course, it is not possible to boot from such a disk. The solutions are:
E000:1E10 89 04 mov [si],ax E000:1E12 26: 8B 45 02 mov ax,WORD PTR ES:[DI+1*2] ;word 1 = cylinders E000:1E16 26: 8A 75 06 mov dh,BYTE PTR ES:[DI+3*2] ;word 3 = heads E000:1E1A 26: 8A 55 0C mov dl,BYTE PTR ES:[DI+6*2] ;word 6 = sectors E000:1E1E 26: F6 45 01 80 test byte ptr es:[di+1],80h ;Is ATA device? E000:1E23 75 31 jnz short @F ;No,skip E000:1E25 26: F6 45 63 02 test byte ptr ES:[DI+49*2+1],2 ;check word 49(LBA) to E000:1E2A 74 2A jz short @F ;confirm word 60-61 is valid? E000:1E2C 26: 66| 83 7D 78 00 cmp dword ptr ES:[DI+60*2],0 E000:1E32 74 22 je short @F E000:1E34 26: 66| 83 7D 78 FF cmp dword ptr ES:[DI+60*2],0ffffffffh E000:1E3A 74 1A je short @F E000:1E3C 26: 81 7D 7A 0FF0 cmp word ptr ES:[DI+61*2],0ff0h E000:1E42 77 12 ja short @F E000:1E44 52 push dx E000:1E45 8A C6 mov al,dh E000:1E47 F6 E2 mul dl E000:1E49 8B C8 mov cx,ax E000:1E4B 26: 8B 45 78 mov ax,ES:[DI+60*2] ;word 60 = physical sectors low dword E000:1E4F 26: 8B 55 7A mov dx,ES:[DI+61*2] ;word 61 = physical sectors high dword E000:1E53 F7 F1 div cx ;Divide overflow here!!! E000:1E55 5A pop dx @@: E000:1E56 89 44 02 mov [si+2],ax E000:1E59 80 FE 10 cmp dh,16 E000:1E5C 0F 87 01FF ja Set_HDD_none E000:1E60 88 74 04 mov BYTE PTR [si+4],dh ;store heads E000:1E63 88 54 10 mov BYTE PTR [si+10],dl ;store sectorsAll hard disks with capacity above 8.4GB shall report 16383 cylinders, 16 heads and 63 sectors per track. The correct size is read LBA_sectors. Maximum disk size without divide overflow is 65535 * 16 * 63 * 512 = 33822351360 bytes = 34 GB.
E000:1E34 26: 81 7D 7A 03F0 cmp word ptr ES:[DI+61*2],03f0h E000:1E3A 72 02 jb small E000:1E3C B2 FF mov dl,255 E000:1E3E 90 small: nop E000:1E3F 90 nop E000:1E40 90 nop E000:1E41 90 nop E000:1E42 90 nop E000:1E43 90 nop
Now all disks with capacity 37, 40 and 60 GB are correctly autodetected, and it is possible to boot from them.
But new problem arises with disks with capacity over 65535 MB - there is divide overflow in displaying the value on the POST screen, and with displaying the size in "Standard CMOS Setup".
The right solution is more complicated. At first, for HX BIOS, the code is located in different part of ROM, called XGROUP CODE or Extended system BIOS. It can be extracted from the compressed image by Award CBROM utility by executing:
cbrom 5hx29.bin /other 4100:0 extractreleased from the compressed BIOS:
cbrom 5hx29.bin /other 4100:0 releaseadded to the compressed BIOS:
cbrom 5hx29.bin /other 4100:0 awardext.rom
It must be noted that some other BIOSes contain the same code in the main (F000 segment) BIOS.
At first, new variable on the stack HDDSIZE_Unit is created, its value is 2 if HDDSIZE variable contains size in megabytes, and 3 for gigabytes.
HDDSIZE_Unit equ USERINTSTACK+96 ;byte (0220h) HDDSIZE_MB equ 2 HDDSIZE_GB equ 3New procedure for calculating HDD size is created:
;---------------------------------------------- ;calculate HDD size ;Input : AL = heads of HDD ; AH = sectors of HDD ; CX = cylinders of HDD ;Output: HDDSIZE[bp] = size of HDD ; HDDSIZE_Unit[bp] = unit of HDD's size ;---------------------------------------------- public Cal_HDD_Size X:2610 Cal_HDD_Size: X:2610 66| 50 push eax X:2612 66| 51 push ecx X:2614 66| 52 push edx X:2616 F6 E4 mul ah ;heads * sectors X:2618 F7 E1 mul cx ; * cylinders X:261A 66| C1 C8 10 ror eax,16 ;shift high word to low X:261E 8B C2 mov ax,dx ;set high word = DX X:2620 66| C1 C8 10 ror eax,16 X:2624 66| 33 D2 xor edx,edx ;clear divided number X:2627 66| B9 000007A1 mov ecx,1000000/512 ;set diving number X:262D 66| F7 F1 div ecx X:2630 B2 02 mov dl,HDDSIZE_MB ;assume MB (below 0ffffh) X:2632 66| 3D 0000FFFF cmp eax,0ffffh ;size over 0ffffh X:2638 72 11 jb short Fill_HDDSIZE_Stack;No,skip X:263A 66| C1 C8 10 ror eax,16 X:263E 8B D0 mov dx,ax X:2640 66| C1 C8 10 ror eax,16 X:2644 B9 03E8 mov cx,1000 ;transfer to GB X:2647 F7 F1 div cx X:2649 B2 03 mov dl,HDDSIZE_GB ;set GB string X:264B Fill_HDDSIZE_Stack: X:264B 88 96 0220 mov HDDSIZE_Unit[bp],dl ;set unit of HDD size X:264F 89 86 009C mov HDDSIZE[bp],ax ;set HDD size X:2653 66| 5A pop edx X:2655 66| 59 pop ecx X:2657 66| 58 pop eax X:2659 C3 retOld code causing divide overflow during displaying the POST (configuration) screen before boot:
;------------------- ;calculate HDD size ;------------------- -- MACRO F000_call Get_HDD_CMOS_Info X:08DB 0E push cs X:08DC 68 08E7 push ret_addr_1 X:08DF 68 7120 push offset Get_HDD_CMOS_Info X:08E2 EA E0008000 jmp far ptr E000:8000 X:08E7 ret_addr_1 X:08E7 1E push ds X:08E8 53 push bx X:08E9 75 1D jnz short Get_User_Type X:08EB 0F B6 02 movzx ax,byte ptr [bp+si] ;Hdd type no. X:08EE FE C8 dec al X:08F0 C1 E0 04 shl ax,4 X:08F3 BB 52D2 mov bx,offset HDISK_PARMS X:08F6 03 D8 add bx,ax X:08F8 68 F000 push 0f000h X:08FB 1F pop ds X:08FC 0F B6 47 02 movzx ax,byte ptr [bx+2] ;heads X:0900 0F B6 4F 0E movzx cx,byte ptr [bx+14] ;sectors X:0904 8B 1F mov bx,[bx] ;cylinders X:0906 EB 0A jmp short Disp_HDD_Size X:0908 Get_User_Type: X:0908 0F B6 43 02 movzx ax,byte ptr [bp+di+2] ;heads X:090C 0F B6 4B 07 movzx cx,byte ptr [bp+di+7] ;sectors X:0910 8B 1B mov bx,[bp+di+0] ;cylinders X:0912 Disp_HDD_Size: X:0912 C1 E1 02 shl cx,2 X:0915 F7 E1 mul cx X:0917 F7 E3 mul bx X:0919 5B pop bx X:091A 1F pop ds X:091B B9 1E84 mov cx,15625/2 X:091E F7 F1 div cx ;Divide overflow here!!! X:0920 89 86 009C mov HDDSIZE[bp],ax -- MACRO F000_call Disp_Word_Int5 X:0924 0E push cs X:0925 68 0930 push offset ret_addr_2 X:0928 68 3F72 push offset Disp_Word_Int5 X:092B EA E0008000 jmp far ptr E000:8000 X:0930 ret_addr_2: X:0930 BE 0620 mov si,offset MB_Str X:0933 @@: -- MACRO post_func_call Disp_Str_In_BIOS X:0933 0E push cs X:0934 68 093F push offset ret_addr_3 X:0937 68 8BD8 push offset Disp_Str_In_BIOS X:093A EA F0004AE2 jmp far ptr Post_call_proc ; (F000:4AE2) X:093F ret_addr_3: X:093F C3 retNew modified code, using new procedure and variables:
;------------------- ;calculate HDD size ;------------------- -- MACRO F000_call Get_HDD_CMOS_Info X:08DB 0E push cs X:08DC 68 08E7 push ret_addr_1 X:08DF 68 7120 push offset Get_HDD_CMOS_Info X:08E2 EA E0008000 jmp far ptr E000:8000 X:08E7 ret_addr_1 X:08E7 1E push ds X:08E8 53 push bx X:08E9 75 1B jnz short Get_User_Type X:08EB 0F B6 02 movzx ax,byte ptr [bp+si] ;Hdd type no. X:08EE FE C8 dec al X:08F0 C1 E0 04 shl ax,4 X:08F3 BB 52D2 mov bx,offset HDISK_PARMS X:08F6 03 D8 add bx,ax X:08F8 68 F000 push 0f000h X:08FB 1F pop ds X:08FC 8A 47 02 mov al,byte ptr [bx+2] ;heads X:08FF 8A 67 0E mov ah,byte ptr [bx+14] ;sectors X:0902 8B 0F mov cx,[bx] ;cylinders X:0904 EB 08 jmp short Disp_HDD_Size ; (090E) X:0906 Get_User_Type: X:0906 8A 43 02 mov al,[bp+di+2] ;heads X:0909 8A 63 07 mov ah,[bp+di+7] ;sectors X:090C 8B 0B mov cx,[bp+di+0] ;cylinders X:090E Disp_HDD_Size: X:090E E8 1CFF call Cal_HDD_Size ; (2610) X:0911 5B pop bx X:0912 1F pop ds X:0913 8B 86 009C mov ax,HDDSIZE[bp] -- MACRO F000_call Disp_Word_Int5 X:0917 0E push cs X:0918 68 0926 push offset ret_addr_2 X:091B 68 3F72 push offset Disp_Word_Int5 X:091E EA E0008000 jmp far ptr E000:8000 X:0923 47 42 00 GB_str db 'GB', 0 X:0926 ret_addr_2: X:0926 BE 0620 mov si,offset MB_Str X:0929 80 BE 0220 02 cmp byte ptr HDDSIZE_Unit[bp],HDDSIZE_MB X:092E 76 03 jbe short @F X:0930 BE 0923 mov si,offset GB_Str X:0933 @@: -- MACRO post_func_call Disp_Str_In_BIOS X:0933 0E push cs X:0934 68 093F push offset ret_addr_3 X:0937 68 8BD8 push offset Disp_Str_In_BIOS X:093A EA F0004AE2 jmp far ptr Post_call_proc ; (F000:4AE2) X:093F ret_addr_3: X:093F C3 ret
The second place with divide overflow is displaying HDD size during manual setup (User setting). The divide overflow occurs in Transfer_Hdd_Parms procedure, it is too long, so I will comment only important place:
X:2304 E9 00BD jmp Not_Hdd ; (23C4) ........ ........ ;------------------- ;calculate HDD size ;------------------- X:23A4 51 push cx X:23A5 32 E4 xor ah,ah X:23A7 8A 86 0096 mov al,HEAD[bp] X:23AB 32 ED xor ch,ch X:23AD 8A 8E 009B mov cl,SECTOR[bp] X:23B1 C1 E1 02 shl cx,2 X:23B4 F7 E1 mul cx X:23B6 F7 A6 0094 mul word ptr CYLINDER[bp] X:23BA B9 1E84 mov cx,15625/2 X:23BD F7 F1 div cx ;Divide overflow here!!! X:23BF 89 86 009C mov HDDSIZE[bp],ax X:23C3 59 pop cx X:23C4 Not_Hdd: X:23C4 5E pop si X:23C5 C3 ret
and new version, using new procedure and variables:
X:2304 E9 00AC jmp Not_Hdd ; (23B3) ........ ........ ;------------------- ;calculate HDD size ;------------------- X:23A4 8A 86 0096 mov al,HEAD[bp] X:23A8 8A A6 009B mov ah,SECTOR[bp] X:23AC 8B 8E 0094 mov cx,CYLINDER[bp] X:23B0 E8 025D call Cal_HDD_Size ; (2610) X:23B3 Not_Hdd: X:23B3 5E pop si X:23B4 C3 ret and remaining 17 bytes are not important.
In the old standard setup, the size of HDD is in megabytes, but there is no indication of it. With new routines, the size may be either in MB or GB so it is necessary to display it. The following patch achieves it:
X:20CF E8 00AA call Check_If_HDD_Type_Item ; (217C) X:20D2 75 23 jnz short Show_User_Exit X:20D4 E8 FC5A call X_Read_Item_Value ; (1D31)to new code
X:20CF E8 00AA call Check_If_HDD_Type_Item ; (217C) X:20D2 75 23 jnz short Show_User_Exit X:20D4 E8 0583 call Patch_GB ; (265A)and add special "patch" procedure is created at the end of the code:
X:265A Patch_GB: X:265A B0 4D mov al,'M' X:265C 80 BE 0220 02 cmp byte ptr HDDSIZE_Unit[bp],HDDSIZE_MB X:2661 76 02 jbe short @F X:2663 B0 47 mov al,'G' X:2665 @@: X:2665 FF B6 0080 push word ptr ATTRIBUTE[bp] X:2669 FF B6 0081 push word ptr CURSOR_X[bp] X:266D 80 86 0081 08 add byte ptr CURSOR_X[bp],8 X:2672 E8 F6FD call X_VNORMAL ; (1D72) X:2675 E8 E8DD call X_Display_Char ; (0F55) X:2678 8F 86 0081 pop word ptr CURSOR_X[bp] X:267C 8F 86 0080 pop word ptr ATTRIBUTE[bp] X:2680 E8 F6AE call X_Read_Item_Value ; (1D31) X:2683 C3 retn
It will be not so easy to find addresses of X_VNORMAL and X_Display_Char procedures. In case they are located in main F000 segment BIOS, the names are VNORMAL and Display_Char respectively. VNORMAL procedure looks like this:
;[]========================================================================[] ;Function : Set the display attrib to NORMAL ; ;Input : None ; ;Output : byte ptr ATTRIBUTE[bp] updated ; ;Registers: All preserved ;[]========================================================================[] F000:3993 Vnormal proc near F000:3993 50 push ax F000:3994 53 push bx F000:3995 8B 9E 014B mov bx,Color_Offset[bp] F000:3999 2E: 8A 07 mov al,cs:[bx].CNORMAL F000:399C 88 86 0080 mov ATTRIBUTE[bp],al F000:39A0 5B pop bx F000:39A1 58 pop ax F000:39A2 C3 ret Vnormal endpand the X_VNORMAL procedure located in XGROUP CODE:
X:1D72 X_Vnormal proc near -- MACRO F000_call Vnormal X:1D72 0E push cs X:1D73 68 1D7E push offset ret_addr_4 X:1D76 68 3993 push offset Vnormal X:1D79 EA E0008000 jmp far E000:8000 X:1D7E ret_addr_4 X:1D7E C3 ret X_Vnormal endp
Display_Char procedure in the main BIOS. It may slightly differ.
;[]========================================================================[] ;Funtion : Display 1 character on screen ; ;Input : al = ASCII code ; ;Output : CURSOR_X[bp] & CURSOR_Y[bp] changed ; ;Registers: FLAG - Destroyed ; Others - Preserved ;[]========================================================================[] F000:39F0 Display_Char proc near F000:39F0 50 push ax F000:39F1 53 push bx F000:39F2 51 push cx F000:39F3 52 push dx F000:39F4 9C pushf F000:39F5 50 push ax ;Set cursor position to display item name F000:39F6 8A 96 0081 mov dl,CURSOR_X[bp] ;get column position F000:39FA 8A B6 0082 mov dh,CURSOR_Y[bp] ;get row position F000:39FE 32 FF xor bh,bh ;first page F000:3A00 B4 02 mov ah,2 ;set cursor position F000:3A02 E8 0017 Call Check_Call_Source ; (3A1C) F000:3A05 58 pop ax F000:3A06 B4 09 mov ah,09h ;write TTY F000:3A08 8A 9E 0080 mov bl,byte ptr ATTRIBUTE[bp] F000:3A0C B9 0001 mov cx,1 F000:3A0F E8 000A Call Check_Call_Source ; (3A1C) F000:3A12 Exit_Display_Char: F000:3A12 FE 86 0081 inc byte ptr CURSOR_X[bp] F000:3A16 9D popf F000:3A17 5A pop dx F000:3A18 59 pop cx F000:3A19 5B pop bx F000:3A1A 58 pop ax F000:3A1B C3 ret Display_Char endp
X_Display_Char located in XGROUP CODE:
X:0F55 X_Display_Char proc near -- MACRO F000_call Display_Char X:0F55 0E push cs X:0F56 68 0F61 push offset ret_addr_5 X:0F59 68 39F0 push offset Display_Char X:0F5C EA E0008000 jmp far E000:8000 X:0F61 ret_addr_5 X:0F61 C3 ret X_Display_Char endp
F000_call_proc is used for calling procedures in F000 segment from other segment
E000:8000 F000_call_proc: E000:8000 68 EC31 push offset F000_func_end E000:8003 50 push ax E000:8004 9C pushf E000:8005 FA cli E000:8006 87 EC xchg bp,sp E000:8008 8B 46 04 mov ax,[bp+4] E000:800B 87 46 06 xchg [bp+6],ax E000:800E 89 46 04 mov [bp+4],ax E000:8011 87 EC xchg bp,sp E000:8013 9D popf E000:8014 58 pop ax E000:8015 EA F000EC30 jmp far F000_VECT ; (F000:EC30) .... .... F000:EC30 F000_VECT: F000:EC30 C3 retn F000:EC31 F000_func_end: F000:EC31 CB retf
Post_call_proc is used for calling procedures in E000 segment (POST) from other segment
F000:4AE2 Post_call_proc: F000:4AE2 68 8031 push offset POST_func_end F000:4AE5 50 push ax F000:4AE6 9C pushf F000:4AE7 FA cli F000:4AE8 87 EC xchg bp,sp F000:4AEA 8B 46 04 mov ax,[bp+4] F000:4AED 87 46 06 xchg [bp+6],ax F000:4AF0 89 46 04 mov [bp+4],ax F000:4AF3 87 EC xchg bp,sp F000:4AF5 9D popf F000:4AF6 58 pop ax F000:4AF7 EA E0008030 jmp far ptr POST_VECT ; (E000:8030) .... .... E000:8030 POST_VECT: E000:8030 C3 retn E000:8031 POST_func_end: E000:8031 CB retf
All modifications are done by the same way as are done in newer Award BIOSes (after 04/1999), and if possible, the routines are the same.
Now I want to add correct detection of AMD K6-2+ and K6-III+ processors. Original routines are:
ALIGN 16 ;CPU table for AMD s-series CPUs E000:3F20 Cpu_AMDs: E000:3F20 0500 18D5 dw 0500H,CPU_AMD5K86 E000:3F24 0510 18D5 dw 0510H,CPU_AMD5K86 E000:3F28 0520 18D5 dw 0520H,CPU_AMD5K86 E000:3F2C 0530 18D5 dw 0530H,CPU_AMD5K86 E000:3F30 0560 18D5 dw 0560H,CPU_AMD5K86 E000:3F34 0570 18D5 dw 0570H,CPU_AMD5K86 E000:3F38 0580 18D5 dw 0580H,CPU_AMD5K86 E000:3F3C 0590 18D5 dw 0590H,CPU_AMD5K86 E000:3F40 0430 50C3 dw 0430h,(CPU_AMD486PLUS) ;DX2 plus WT E000:3F44 0470 58C3 dw 0470h,(CPU_AMD486WB_PLUS) ;DX2 plus WB E000:3F48 0480 90C5 dw 0480h,(CPU_AMD486DX4PLUS) ;DX4 plus WT E000:3F4C 0490 98C5 dw 0490h,(CPU_AMD486DX4WB_PLUS) ;DX4 plus WB E000:3F50 04E0 30D3 dw 04E0h,(CPU_AMDDX5WT) ;DX5 plus WT E000:3F54 04F0 38D3 dw 04F0h,(CPU_AMDDX5WB) ;DX5 plus WB E000:3F58 FFFF dw -1 ;if CPU type is AMD K6, then return with K6 string E000:8E6E E8 03B3 call Check_K6_CPU ;K6 ? E000:8E71 75 05 jne Is_Not_K6 ;no ! E000:8E73 E8 03D8 call TreatK6String E000:8E76 EB 1E jmp GoCpuDisaplay E000:8E78 Is_Not_K6: ;[]-------------------------[] ;Input : None ;Ouput : ZF - K6 ; NZ - not K6 ;[]-------------------------[] E000:9224 Check_K6_CPU Proc Near E000:9224 80 BE 01E0 03 cmp byte ptr CPU_LEVEL[bp], LEVEL_586 E000:9229 75 22 jne @F E000:922B 80 BE 01DB 02 cmp byte ptr CPU_BRAND[bp], CPU_BRAND_AMD E000:9230 75 1B jne @F E000:9232 66| 60 pushad E000:9234 E8 FF93 call Read_CpuID ;read CPU ID E000:9237 24 F0 and al, 0F0h E000:9239 3D 0590 cmp ax, 0590h ;new K6 E000:923C 74 0D je Yes_NewK6 E000:923E 3D 0580 cmp ax, 0580h ;new K6 E000:9241 74 08 je Yes_NewK6 E000:9243 3D 0570 cmp ax, 0570h ;new K6 E000:9246 74 03 je Yes_NewK6 E000:9248 3D 0560 cmp ax, 0560h ;K6 ? E000:924B Yes_NewK6: E000:924B 66| 61 popad E000:924D @@: E000:924D C3 ret Check_K6_CPU Endp ;[]------------------------------------------------------[] ;Function: Return proper CPU string for K6 series CPU ;Input : None ;Output : SI - offset of CPU string to display ;Note : "AMD-K6(tm)/xxx" for 056x & 057x ; "AMD-K6(tm)-2/xxx" for 058x ; "AMD-K6(tm)-3/xxx" for 059x ;[]------------------------------------------------------[] E000:924E TreatK6String proc near E000:924E 66| 50 push eax E000:9250 E8 FF77 call Read_CpuID ;read CPU ID E000:9253 24 F0 and al, 0F0h E000:9255 BE 909A mov si, offset Cpu_AmdK6_3_Str ;"AMD-K6-3" for 059x E000:9258 3C 90 cmp al, 090H ;model 9 ? E000:925A 74 0A je K6Str_Ok E000:925C BE 908D mov si, offset Cpu_AmdK6_3D_Str ;"AMD-K6-2" for 058x E000:925F 3C 80 cmp al, 080H ;model 8 ? E000:9261 74 03 je K6Str_Ok E000:9263 BE 9082 mov si, offset Cpu_AmdK6_Str ;"AMD-K6" for 056x ;and 057x E000:9266 K6Str_Ok: E000:9266 66| 58 pop eax E000:9268 C3 ret TreatK6String endp
Necessary Modifications:
At first, I don't suppose that in this motherboard will be used 486 processor, so I can safely overwrite:
E000:3F3C 0590 18D5 dw 0590H,CPU_AMD5K86 E000:3F40 05D0 18D5 dw 05D0h,CPU_AMD5K86 E000:3F44 0470 58C3 dw 0470h,(CPU_AMD486WB_PLUS) ;DX2 plus WB
Then I need to modify Check_K6_CPU procedure to include 5D0 processor:
;[]-------------------------[] ;Input : None ;Ouput : ZF - K6 ; NZ - not K6 ;[]-------------------------[] E000:9224 Check_K6_CPU Proc Near E000:9224 80 BE 01E0 03 cmp byte ptr CPU_LEVEL[bp], LEVEL_586 E000:9229 75 22 jne @F E000:922B 80 BE 01DB 02 cmp byte ptr CPU_BRAND[bp], CPU_BRAND_AMD E000:9230 75 1B jne @F E000:9232 66| 60 pushad E000:9234 E8 FF93 call Read_CpuID ;read CPU ID E000:9237 24 F0 and al, 0F0h E000:9239 3D 05D0 cmp ax, 05D0h E000:923C 77 0D ja Not_NewK6 E000:923E 3D 0560 cmp ax, 0560h E000:9241 72 08 jb Not_NewK6 E000:9243 31 D2 xor dx,dx ;set ZF E000:9245 90 nop E000:9246 90 nop E000:9247 90 nop E000:9248 90 nop E000:9249 90 nop E000:924A 90 nop E000:924B Not_NewK6: E000:924B 66| 61 popad E000:924D @@: E000:924D C3 ret Check_K6_CPU Endp
Detection of K6-2+ and K6-III+ processors must be added to the end of code in E000 segment, I will also correct the string for K6-III, it shall not be K6-3.
;[]------------------------------------------------------[] ;Function: Return proper CPU string for K6 series CPU ;Input : None ;Output : SI - offset of CPU string to display ;Note : "AMD-K6(tm)/xxx" for 056x & 057x ; "AMD-K6(tm)-2/xxx" for 058x ; "AMD-K6(tm)-3/xxx" for 059x ;[]------------------------------------------------------[] E000:924E TreatK6String proc near E000:924E 66| 50 push eax E000:9250 E9 5DAE jmp K6Plus_Str E000:9253 From_K6Plus_Str: E000:9253 24 F0 and al, 0F0h E000:9255 BE F038 mov si, offset Cpu_AmdK6_3_Str ;"AMD-K6-3" for 059x E000:9258 3C 90 cmp al, 090H ;model 9 ? E000:925A 74 0A je K6Str_Ok E000:925C BE 908D mov si, offset Cpu_AmdK6_3D_Str ;"AMD-K6-2" for 058x E000:925F 3C 80 cmp al, 080H ;model 8 ? E000:9261 74 03 je K6Str_Ok E000:9263 BE 9082 mov si, offset Cpu_AmdK6_Str ;"AMD-K6" for 056x ;and 057x E000:9266 K6Str_Ok: E000:9266 66| 58 pop eax E000:9268 C3 ret TreatK6String endp E000:F001 K6Plus_Str: E000:F001 E8 A1C6 call Read_CpuID ; (91CA) E000:F004 24 FC and al,0FCh E000:F006 BE F01A mov si,offset Cpu_AmdK6_3P_Str E000:F009 3C D0 cmp al,0D0h E000:F00B 74 0A je short K6PStr_Ok E000:F00D BE F02A mov si,offset Cpu_AmdK6_2P_Str E000:F010 3C D4 cmp al,0D4h E000:F012 74 03 je short K6PStr_Ok E000:F014 E9 A23C jmp From_K6Plus_Str E000:F017 K6PStr_Ok: E000:F017 66| 58 pop eax E000:F019 C3 retn E000:F01A Cpu_AmdK6_3P_Str: E000:F01A 41 4D 44 2D 4B 36 db 'AMD-K6(tm)-III+',0 E000:F020 28 74 6D 29 2D 49 E000:F026 49 49 2B 00 E000:F02A Cpu_AmdK6_2P_Str: E000:F02A 41 4D 44 2D 4B 36 db 'AMD-K6(tm)-2+',0 E000:F030 28 74 6D 29 2D 32 E000:F036 2B 00 E000:F038 Cpu_AmdK6_3_Str: E000:F038 41 4D 44 2D 4B 36 db 'AMD-K6(tm)-III',0 E000:F03E 28 74 6D 29 2D 49 E000:F044 49 49 00
Here is description of modification of frequency table. In HX BIOS are used separated tables for all multipliers, multiplier is read from the processor.
(old version of bus speed table without 90 and 95 MHz) CPU100 EQU 10110000B ;B0 CPU83 EQU 10100000B ;A0 CPU75 EQU 10010000B ;90 CPU66 EQU 10000000B ;80 CPU60 EQU 01110000B ;70 CPU50 EQU 01100000B ;60 E000:4403 4462 AMD_Mult_Tbl dw offset Mult_4_5 E000:4405 4475 dw offset Mult_5 E000:4407 444F dw offset Mult_4 E000:4409 4488 dw offset Mult_5_5 E000:440B 4413 dw offset Mult_2_5 E000:440D 4429 dw offset Mult_3 E000:440F 4495 dw offset Mult_6 E000:4411 443C dw offset Mult_3_5 E000:4413 FA F5 B0 Mult_2_5 db 250, 245, CPU100 ;100x2.5 E000:4416 D0 CA A0 db 208, 202, CPU83 ;83x2.5 E000:4419 BC B7 90 db 188, 183, CPU75 ;75x2.5 E000:441C A6 A1 80 db 166, 161, CPU66 ;66x2.5 E000:441F 96 91 70 db 150, 145, CPU60 ;60x2.5 E000:4422 8A 87 60 db 138, 135, CPU50 ;55x2.5 E000:4425 7D 78 60 db 125, 120, CPU50 ;50x2.5 E000:4418 00 db 0 E000:4429 FA F5 A0 Mult_3 db 250, 245, CPU83 ;83x3 E000:442C E1 DC 90 db 225, 220, CPU75 ;75x3 E000:442F C8 C3 80 db 200, 195, CPU66 ;66x3 E000:4432 B4 B3 70 db 180, 179, CPU60 ;60x3 E000:4435 96 91 60 db 150, 145, CPU50 ;50x3 E000:4438 2C 28 B0 db 300-256, 296-256, CPU100 ;100x3 E000:443B 00 db 0 E000:443C E7 E2 80 Mult_3_5 db 231, 226, CPU66 ;66x3.5 E000:443F D2 CD 70 db 210, 205, CPU60 ;60x3.5 E000:4442 AF AA 60 db 175, 170, CPU50 ;50x3.5 E000:4445 5E 5A B0 db 350-256, 346-256, CPU100 ;100x3.5 E000:4448 22 1E A0 db 290-256, 286-256, CPU83 ;83x3.5 E000:444B 06 06 90 db 262-256, 262-256, CPU75 ;75x3.5 E000:444E 00 db 0 E000:444F F0 EB 70 Mult_4: db 240, 235, CPU60 ;60x4 E000:4452 C8 C3 60 db 200, 195, CPU50 ;50x4 E000:4455 90 8C B0 db 400-256, 396-256, CPU100 ;100x4 E000:4458 4C 49 A0 db 332-256, 329-256, CPU83 ;83x4 E000:445B 2B 28 90 db 299-256, 296-256, CPU75 ;75x4 E000:445E 09 06 80 db 265-256, 262-256, CPU66 ;66x4 E000:4461 00 db 0 E000:4462 E1 DC 60 Mult_4_5: db 225, 220, CPU50 ;50x4.5 E000:4465 C2 BE B0 db 450-256, 446-256, CPU100 ;100x4.5 E000:4468 75 72 A0 db 373-256, 370-256, CPU83 ;83x4.5 E000:446B 51 4E 90 db 337-256, 334-256, CPU75 ;75x4.5 E000:446E 2B 28 80 db 299-256, 296-256, CPU66 ;66x4.5 E000:4471 0D 0A 70 db 269-256, 266-256, CPU60 ;60x4.5 E000:4474 00 db 0 E000:4475 FA DC 60 Mult_5: db 250, 220, CPU50 ;50x5 E000:4478 F4 F0 B0 db 500-256, 496-256, CPU100 ;100x5 E000:447B 9E 9B A0 db 414-256, 411-256, CPU83 ;83x5 E000:447E 76 73 90 db 374-256, 371-256, CPU75 ;75x5 E000:4481 4C 46 80 db 332-256, 326-256, CPU66 ;66x5 E000:4484 2B 28 70 db 299-256, 296-256, CPU60 ;60x5 E000:4487 00 db 0 E000:4488 9C 98 90 Mult_5_5: db 412-256, 408-256, CPU75 ;75x5.5 E000:448B 6A 66 80 db 362-256, 358-256, CPU66 ;66x5.5 E000:448E 49 45 70 db 329-256, 325-256, CPU60 ;60x5.5 E000:4491 12 0E 60 db 274-256, 270-256, CPU50 ;50x5.5 E000:4494 00 db 0 E000:4495 00 Mult_6 db 0 ;Input : BX - real CPU clock (detected by RDTSC instruction) ;Output: carry set - It is AMD K6 model 8 CPU & ; si contains poiter to the right speed table ; no carry - Not K6 model 8 CPU E000:4496 Get_AMD_Model8_Clock_Tbl Proc Near E000:4496 50 push ax E000:4497 53 push bx E000:4498 E8 4D89 call Check_K6_CPU E000:449B F8 clc E000:449C 75 24 jne Not_Model8_CPU E000:449E E8 4D29 call Read_CpuID ;read CPU ID E000:44A1 3D 0588 cmp ax,0588h E000:44A4 72 1C jb Not_Model8_CPU ;No, skip ! E000:44A6 66| B9 C0000087 mov ecx,0c0000087h ;read bus ratio steping E000:44AC 0F 32 RDMSR E000:44AE 24 07 and ax, 00000111b ;AL = 000 -> 4.5x ; 001 -> 5.0x ; 010 -> 4.0x ; 011 -> 5.5x ; 100 -> 2.5x ; 101 -> 3.0x ; 110 -> 6.0x ; 111 -> 3.5x E000:44B0 32 E4 xor ah,ah E000:44B2 24 07 and al,7 E000:44B4 D1 E0 shl ax,1 E000:44B6 BE 4403 mov si,offset AMD_Mult_Tbl E000:44B9 03 F0 add si,ax E000:44BB 2E: 8B 34 mov si,cs:[si] E000:44BE F9 stc E000:44BF 5B pop bx E000:44C0 58 pop ax E000:44C1 C3 retn E000:44C2 Not_Model8_CPU: E000:44C2 F8 clc E000:44C3 5B pop bx E000:44C4 58 pop ax E000:44C5 C3 retn Get_AMD_Model8_Clock_Tbl Endp
Comment: For AMD K6-2+ and K6-III+, the multiplier for "100" is 2.0, not 2.5. I don't suppose the use of these procesors with multiplier 2.
Now it's clear why 2.9 BIOS reports 256 MHz for multiplier set to 6 - the table is empty. I rewrote the table and omitted 100 and 83 MHz bus speed. GA-586HX is posible to switch to bus speed 50, 55, 60 and 66 MHz. 75 MHz is rework with PhaseLink PLL52C59-14T or IC WORKS W48C60-234, 83 MHz for PhaseLink PLL52C59-14A. 83 MHz I defined only for multiplier 6 because of lack of space and I don't suppose that somebody will rework the motherboard to bus speed 83 MHz and then use slow processor.
E000:4403 4453 AMD_Mult_Tbl dw offset Mult_4_5 E000:4405 4463 dw offset Mult_5 E000:4407 4443 dw offset Mult_4 E000:4409 4473 dw offset Mult_5_5 E000:440B 4413 dw offset Mult_2_5 E000:440D 4423 dw offset Mult_3 E000:440F 4483 dw offset Mult_6 E000:4411 4433 dw offset Mult_3_5 E000:4413 BC B7 90 Mult_2_5: db 188, 183, CPU75 ;75x2.5 E000:4416 A6 A1 80 db 166, 161, CPU66 ;66x2.5 E000:4419 96 91 70 db 150, 145, CPU60 ;60x2.5 E000:441C 8A 85 60 db 138, 133, CPU50 ;55x2.5 E000:441F 7D 78 60 db 125, 120, CPU50 ;50x2.5 E000:4422 00 db 0 E000:4423 E1 DC 90 Mult_3: db 225, 220, CPU75 ;75x3 E000:4426 C8 C3 80 db 200, 195, CPU66 ;66x3 E000:4429 B4 AF 70 db 180, 175, CPU60 ;60x3 E000:442C A5 A0 60 db 165, 160, CPU50 ;55x3 E000:442F 96 91 60 db 150, 145, CPU50 ;50x3 E000:4432 00 db 0 E000:4433 E9 E4 80 Mult_3_5 db 233, 228, CPU66 ;66x3.5 E000:4436 D2 CD 70 db 210, 205, CPU60 ;60x3.5 E000:4439 C1 BC 60 db 193, 188, CPU50 ;55x3.5 E000:443C AF AA 60 db 175, 170, CPU50 ;50x3.5 E000:443F 07 02 90 db 263-256, 258-256, CPU75 ;75x3.5 E000:4442 00 db 0 E000:4443 F0 EB 70 Mult_4: db 240, 235, CPU60 ;60x4 E000:4446 DC D7 60 db 220, 215, CPU50 ;55x4 E000:4449 C8 C3 60 db 200, 195, CPU50 ;50x4 E000:444C 2C 27 90 db 300-256, 295-256, CPU75 ;75x4 E000:444F 0A 05 80 db 266-256, 261-256, CPU66 ;66x4 E000:4452 00 db 0 E000:4453 F8 F3 60 Mult_4_5: db 248, 243, CPU50 ;55x4.5 E000:4456 E1 DC 60 db 225, 220, CPU50 ;50x4.5 E000:4459 52 4D 90 db 338-256, 333-256, CPU75 ;75x4.5 E000:445C 2C 27 80 db 300-256, 295-256, CPU66 ;66x4.5 E000:445F 0E 09 70 db 270-256, 265-256, CPU60 ;60x4.5 E000:4462 00 db 0 E000:4463 FA F5 60 Mult_5: db 250, 245, CPU50 ;50x5 E000:4466 77 72 90 db 375-256, 370-256, CPU75 ;75x5 E000:4469 4D 48 80 db 333-256, 328-256, CPU66 ;66x5 E000:446C 2C 27 70 db 300-256, 295-256, CPU60 ;60x5 E000:446F 13 0E 60 db 275-256, 270-256, CPU50 ;55x5 E000:4472 00 db 0 E000:4473 9D 98 90 Mult_5_5: db 413-256, 408-256, CPU75 ;75x5.5 E000:4476 6E 69 80 db 366-256, 361-256, CPU66 ;66x5.5 E000:4479 4A 45 70 db 330-256, 325-256, CPU60 ;60x5.5 E000:447C 2F 2A 60 db 303-256, 298-256, CPU50 ;55x5.5 E000:447F 13 0E 60 db 275-256, 270-256, CPU50 ;50x5.5 E000:4482 00 db 0 E000:4483 F4 EF A0 Mult_6: db 500-256, 495-256, CPU83 ;83x6 E000:4486 C2 BD 90 db 450-256, 445-256, CPU75 ;75x6 E000:4489 90 8B 80 db 400-256, 395-256, CPU66 ;66x6 E000:448C 68 63 70 db 360-256, 355-256, CPU60 ;60x6 E000:448F 4A 45 60 db 330-256, 325-256, CPU50 ;55x6 E000:4492 2C 27 60 db 300-256, 295-256, CPU50 ;50x6 E000:4495 00 db 0
Finally I decided not to overwrite tests for all ones and all zeroes in LBA size field and I modified the procedure:
E000:1E3C E8 D208 call Patch_32GB E000:1E3F 90 nop E000:1E40 90 nop E000:1E41 90 nop E000:F047 Patch_32GB: E000:F047 26: 81 7D 7A 03F0 cmp word ptr ES:[DI+61*2],03f0h E000:F04D 72 02 jb small E000:F04F B2 FF mov dl,255 E000:F051 small: E000:F051 26: 81 7D 7A 5000 cmp word ptr ES:[DI+61*2],5000h E000:F057 C3 ret
Useful links:
Petr Soucek, 06-Jul-2002