Modification of GigaByte GA-586HX BIOS rev 2.9 for support of HDD above 32 GiB

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:

This document describes all modifications that are necessary to modify Award 4.51PG BIOS that does not support disks above 34 GB. The modification is described in detail for GA586HX BIOS ver. 2.9 so anyone with sufficient knowledge can modify other BIOSes too.

First modification - breaking the 32 GiB (34 GB) barrier

The behavior of bad BIOS is that it freezes during disk detection just after memory test. Here is the code:
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 sectors
All 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.
The simplest solution is to replace HEADS value with 255, then the maximum disk size is 539 GB (without other limits). The easiest way how to modify the BIOS is to overwrite part of the code that is usually not necessary - the check for invalid bytes in words 60 and 61. The replacement code then will be:
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".

Second modification - breaking the 65 GB barrier

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 extract
released from the compressed BIOS:
cbrom 5hx29.bin /other 4100:0 release
added 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	3
New 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				ret
Old 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				ret
New 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		endp
and 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.

AMD K6-2+ and AMD K6-III+ detection

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:

AWDhack v1.3

Various BIOS tools

Wim's BIOS page

Petr Soucek, 06-Jul-2002