Award BIOS Patching

1. Introduction

Welcome to another article written by me, Pinczakko (^__^). It's a follow up from my other BIOS articles. This article explains the trick to patch the Award system bios a.k.a original.tmp with the help of only these tools:

All of the aforementioned tools are running within Windows XP service pack 2.

The primary purpose of this BIOS modification trick is to avoid the use of third-party Award BIOS modification tools. Namely, BIOS modification tools such as awardmod or awardbios-editor (awdbedit). Some might ask why we have to avoid those tools? actually we don't have to avoid them. But, based on my experience, it's faster to carry out Award BIOS modification without those tools. That's all. Anyway, This trick can be extended to another BIOS code injection technique or another kind of modification techniques. The possibility is limitless, just use your imagination ;-).

You have to note that the trick explained here has only been tested and works successfully on award version 4.51PGNM bios, i.e. VD30728.bin (256KB), the latest version of BIOS for Iwill VD133 motherboard. Thus, proceed at your own risk if you eager to try it. You have been warned.

This article will be hard to grasp if you haven't done any BIOS modification before, particularly Award BIOS. So, please help yourself in that case. I've made couple of preliminary articles in this website in case you wonder where to start. They are provided in the list below in a systematic manner. It's better to read them sequentially as presented below to maximize your understanding.

Once you've grasped the articles in the points above, just proceed accordingly. I guarantee you won't be confused in anyway, he..he..he.. :p

Allright. Since I'm an avid manga reader (Naruto manga), I will use some "manga derived terms" in this article for my reading pleasure codenamed Pinczakko ™ naming convention. I'll provide you with the dictionary first hand, so you won't get lost. Enjoy ;-).

Note that not all of the types of jutsu/technique mentioned above will be presented in this article. It depends on the circumstances. But, all of them eventually will show up in my later arcticles. Have phun (^__^).

2. Modbin Internals

During modbin's execution, when we started to modify the BIOS binary that's currently opened, modbin will generate 2 temporary files, i.e. BIOS.ROM and ORIGINAL.TMP. These are the details:

These temporary files are created within the directory of the modbin's executable. Below is a screenshot showing how it works.

3. System-BIOS Patching Ninjutsu

As mentioned in section 2, modbin creates temporary BIOS.ROM and ORIGINAL.TMP during its execution. Thus, during the existence of these temporary files, we can edit the temporary ORIGINAL.TMP. The net effect of modifying this binary will be applied to the overall BIOS binary when we exit modbin and save all the changes. Modbin is working under the hood to compress the modified temporary original.tmp into the BIOS binary that you saved. Now, can you see the pattern? It is a neat way to modify the system BIOS without relying to "third party" BIOS modification tools such as Award BIOS Editor, awardmod, etc.! We don't have to worry about the checksums either, since modbin will fix it for us. Below is a system-BIOS modification ninjutsu that I've tested and works flawlessly:

This ninjutsu works perfectly as expected in my experiments.

3.1. The Secret Of The Sharingan

As expected, the next ninjutsu that we have to master is the ninjutsu to disassemble ORIGINAL.TMP to find the routine that we want to patch. Certainly, IDA Pro is one of our ultimate arsenal to do this. However, we need more than just arsenal to accomplish this mission, we also need a neat ninjutsu. That ninjutsu is called sharingan.To put simply, sharingan is the ninjutsu to recognize a unique byte pattern within a binary file for certain purpose(s). Why would we need a unique byte pattern? It's because, with that information, we can recognize a procedure that is "interesting" to us in many similar binary files at one shot. For example, we can find the same procedure within the system BIOS for a few different mainboards that have the same type of BIOS, e.g. the same Award BIOS version. Mastering the concept of sharingan is very important, not only to this particular BIOS problem. It can be used in many other field (use your imagination for that). That's why it deserved its own section.

3.1.1. Byte Patterns a.k.a Signatures of Binary Files

We might be tempted to think that it's very hard to find pattern on binary file with 256 possible combination per byte. This fact may holds true to some degree. However, BIOS binary contains more code than data section, eventhough they are overlapped. Thus, finding a byte pattern is quite easy, since x86 code (its instruction bytes) has particular rules that must be adhered to. Just like other processor architectures. In addition, it's very natural not to waste precious space in the memory (RAM and BIOS chip) by repeating the same group of instructions/machine-codes over and over again. This space-saving technique is accomplished by forming a procedure/routine for group of instruction that will be invoked from another section of the binary. This last fact leave us with the huge possibility to find unique group of instructions (thus, a byte pattern) within the binary since they are rarely repeated (the same procedure is rarely repeated in the binary, only being called from another section). This byte pattern sometimes called signature.

The task of forming a new signature is not too hard, these are the "algorithm":

Once we formed the signature, the task of patching a system BIOS file is an easy task. We can even build a "patcher" to automate the process (^__^).

Nevertheless, we can also note the mapping between the location of the code as seen in the disassembler and its hex values shown in the hexeditor to locate certain procedure. But, very often this method is too laborious (-_-).

3.1.2. Attacking With Sharingan

Contrary to the ordinary sharingan in the Naruto manga, our sharingan attacks without using genjutsu type technique, he..he..he.. . OK, enough with the manga thingie. Let's get back to our business.

Attacking with sharingan is not as easy as one might think. It needs a quite deliberate background on the subject that we are targeting. To be able to locate some delicate procedure that we want to patch, we have to know something about it to make an intelligent guess about its location. In windows binary file, a call to certain operating system function is the hint that we need. But, what about BIOS binary? Well, these are the tips:

In principle, we have to know the big picture and then narrowing the target in each step. For BIOS binary, in most cases we have to particularly aware of the hardware protocol that we are targeting and the address range (memory or I/O) that relates to the protocol. Once the protocol is known, we can look for the procedure quite easily, since the BIOS routines will be the implementation of the protocol, perhaps with only modest modification from the samples in the protocol documention ;-).

Grasping the concept of sharingan need some serious practice. Thus, the next subsections will show us some signatures in the system BIOS and the method used to find and to patch it.

3.2. Case 1: Sharingan Attack to The EPA Procedure

This sub-section is only a warming up. Don't get too excited yet :p. The EPA procedure in award BIOS is a quite a well-known procedure. Thus, the signature is already quite widespread on the net ;-).

In my BIOS, to modify the EPA Procedure, we can look for the "80 8EE1 0110 F646 1430" byte pattern, i.e.

Hex values                    Assembly Code 

80 8E E1 01 10            or    byte ptr [bp+1E1h], 10h 

F6 46 14 30               test  byte ptr [bp+14h], 30h

and subsequently patch it, as ilustrated in the BIOS modification change log below.

Changes in VD30728X.BIN:

source file name   : VD30728B.BIN

modified file name : VD30728X.BIN


Modification goal: This modification supposed to disable the EPA Procedure completely.

Before modification the code looks like (disassembled original.tmp):

.........

E000:1E4C B8 00 F0                  mov   ax, 0F000h

E000:1E4F 8E D8                     mov   ds, ax

E000:1E51                           assume ds:_F000h

E000:1E51 E8 8C 11                  call  exec_nnoprom_100h

E000:1E54 73 03                     jnb   short skip_epa_proc

E000:1E56 E8 C3 00                  call  EPA_Procedure   

E000:1E59                         skip_epa_proc:              ; CODE XREF: POST_12S+8C 

E000:1E59 E8 AF 01                  call  init_EGA_video 

......... 

E000:1F1C                         EPA_Procedure proc near     ; CODE XREF: POST_12S+8E

E000:1F1C 80 8E E1 01 10            or    byte ptr [bp+1E1h], 10h

E000:1F21 F6 46 14 30               test  byte ptr [bp+14h], 30h

E000:1F25 74 01                     jz    short loc_E000_1F28

E000:1F27 C3                        retn

E000:1F28                         ; ---------------------------------------------------------------------------

E000:1F28                         loc_E000_1F28:              ; CODE XREF: EPA_Procedure+9

E000:1F28 06                        push  es

.........

After modification the code looks like (disassembled original.tmp):

.........

E000:1E4C B8 00 F0                  mov   ax, 0F000h

E000:1E4F 8E D8                     mov   ds, ax

E000:1E51                           assume ds:nothing

E000:1E51 90                        nop

E000:1E52 90                        nop

E000:1E53 90                        nop

E000:1E54 90                        nop

E000:1E55 90                        nop

E000:1E56 90                        nop

E000:1E57 90                        nop

E000:1E58 90                        nop                     

E000:1E59 E8 AF 01                  call  init_EGA_Video 

.........

Testing result: Goal reached, the BIOS doesn't display EPA Logo as intended and the system still works normally.

If you want to try this modification yourself, patch the highlighted instructions by using hexeditor to NOP (90h) as shown above. In this sample, the signature is already known in advance. Hence, we have no difficulty to carry-out the modification.

3.3. Case 2: Sharingan Attack to The Clock Generator Initialization Routine

In this second modification round, we will try to disable/deactivate one of the clock-line output from the clock generator chip. These are details of the modification:

source file name   : VD30728B.BIN

modified file name : VD30728X.BIN


Modification goal: This modification supposed to disable/deactivate one of the clock-line output from the clock generator chip.

This case is more difficult than the previous one since hints about our target are rare at best. These are the facts that we know:

The first step is to disassemble the BIOS and follow the POST_Jump_Table as described in [2]. We look for the CPU initialization routine from the POST_Jump_Table. I found it at POST_9S as follows (disassembled original.tmp):

E000:61C2                         Begin_E000_POST_Jmp_Table

E000:61C2 4E 15                     dw 154Eh                  ; restore warm-boot flag

E000:61C4 6F 15                     dw 156Fh                  ; dummy

E000:61C6 71 15                     dw 1571h                  ; initialize KBC (Keyboard Controller), halt on error

E000:61C8 D2 16                     dw 16D2h                  ; 1. check Fseg in RAM, beep on-error;

E000:61C8                                                     ; 2. identify FlashROM chip

E000:61CA 45 17                     dw 1745h                  ; chk CMOS circuit

E000:61CC 8A 17                     dw 178Ah                  ; Chipset reg Default values (code in awardext.rom, data in Fseg)

E000:61CE 98 17                     dw 1798h                  ; 1. init CPU Flags

E000:61CE                                                     ; 2. disable A20

E000:61D0 B8 17                     dw 17B8h                  ; 1. init interrupt vector

E000:61D0                                                     ; 2. initialize "signatures" used for Ext_BIOS components

E000:61D0                                                     ;    decompression.

E000:61D0                                                     ; 3. init PwrMgmtCtlr

E000:61D2 4B 19                     dw 194Bh                  ; 1. init FPU <<========================================                       

E000:61D2                                                     ; 2. init microcode (init CPU)

E000:61D2                                                     ; 3. init FSB (clock gen)

E000:61D2                                                     ; 4. init W87381D VID regs  .........

E000:194B                         POST_9S proc near 

E000:194B 1E                        push  ds 

E000:194C 80 66 3D FE               and   byte ptr [bp+3Dh], 0FEh 

E000:1950 E8 F1 00                  call  call_init_FPU 

E000:1953 B8 00 00                  mov   ax, 0 

E000:1956 8E D8                     mov   ds, ax 

E000:1958                           assume ds:nothing 

E000:1958 8A 46 3D                  mov   al, [bp+3Dh] 

E000:195B A2 B4 04                  mov   ds:byte_0_4B4, al 

E000:195E BE 18 08                  mov   si, 818h 

E000:1961 E8 1A 53                  call  F0_Setup_BIOS_Defaults? 

E000:1964 0A C0                     or    al, al 

E000:1966 74 05                     jz    short next 

E000:1968 80 0E BA 04 80            or    ds:byte_0_4BA, 80h 

E000:196D                         next:                       ; CODE XREF: POST_9S+1B 

E000:196D BE 95 08                  mov   si, 895h 

E000:1970 E8 0B 53                  call  F0_Setup_BIOS_Defaults? 

E000:1973 0A C0                     or    al, al 

E000:1975 74 05                     jz    short next_ 

E000:1977 80 0E AC 04 10            or    ds:byte_0_4AC, 10h 

E000:197C                         next_:                      ; CODE XREF: POST_9S+2A 

E000:197C F6 46 10 0F               test  byte ptr [bp+10h], 0Fh 

E000:1980 74 13                     jz    short _next_ 

E000:1982 80 4E 14 40               or    byte ptr [bp+14h], 40h 

E000:1986 BE 4A 08                  mov   si, 84Ah 

E000:1989 E8 F2 52                  call  F0_Setup_BIOS_Defaults? 

E000:198C 0A C0                     or    al, al 

E000:198E 74 05                     jz    short _next_ 

E000:1990 80 0E AC 04 20            or    ds:byte_0_4AC, 20h 

E000:1995                         _next_:                     ; CODE XREF: POST_9S+35 

E000:1995                                                     ; POST_9S+43 

E000:1995 BF 03 00                  mov   di, 3 

E000:1998 9A 10 50 00 60            call  init_Chipset_Reg_again?? 

E000:199D E8 1E 22                  call  init_microcode 

E000:19A0 E8 9D 2D                  call  nullsub_4 

E000:19A3 E8 D6 3F                  call  unknown? 

E000:19A6 68 00 E0                  push  0E000h 

E000:19A9 68 B7 19                  push  19B7h 

E000:19AC 68 31 EC                  push  0EC31h 

E000:19AF 68 04 50                  push  5004h 

E000:19B2 EA 30 EC 00 F0            jmp   far ptr F000_Vector E000:19B7                         

; --------------------------------------------------------------------------- 

E000:19B7 E8 66 3C                  call  Init_FSB            ; SMBus dev 69h init (clock gen chip) 

E000:19BA E8 3A 3C                  call  call_init_W3781D_VID_reg 

E000:19BD 1F                        pop   ds 

E000:19BE                           assume ds:nothing 

E000:19BE F8                        clc 

E000:19BF C3                        retn 

E000:19BF                         POST_9S endp ; sp = -8

As you can see in the code above, this POST_9S is very suspicios. It initializes the FPU (there's an fninit instruction in the called procedure) and the second hint: it calls the microcode initialization routine. The microcode initialization routine is described in [2]. Hence, we proceed further into this procedure until we find (or may not found) our target. I found out that one of the procedure call in this POST_9S is working through the SMBus I/O port. I subsequently name that procedure as Init_FSB and proceed to analyze it. Here's the code:

E000:5620                         Init_FSB proc near          ; CODE XREF: POST_9S+6C

E000:5620 66 60                     pushad

E000:5622 1E                        push  ds

E000:5623 06                        push  es

E000:5624 9C                        pushf

E000:5625 0E                        push  cs

E000:5626 1F                        pop   ds

E000:5627                           assume ds:_E000h 

E000:5627 0E                        push  cs 

E000:5628 68 33 56                  push  5633h 

E000:562B 68 8E 50                  push  508Eh               ; E_seg_RW_Enable 

E000:562E EA 88 61 00 E0            jmp   far ptr Fseg_vector E000:5633                         

; --------------------------------------------------------------------------- 

E000:5633 E8 18 00                  call  nullsub_24 

E000:5636 E8 22 00                  call  Init_FSB_n_Clock_Lines 

E000:5639 0E                        push  cs 

E000:563A 68 45 56                  push  5645h 

E000:563D 68 3B 52                  push  523Bh               ; goto_E_seg_R_Enable 

E000:5640 EA 88 61 00 E0            jmp   far ptr Fseg_vector E000:5645                         

; --------------------------------------------------------------------------- 

E000:5645 E8 43 01                  call  call_init_SMBus_dev_69h ; init clock generator 

E000:5648 9D                        popf 

E000:5649 07                        pop   es 

E000:564A 1F                        pop   ds 

E000:564B                           assume ds:nothing 

E000:564B 66 61                     popad 

E000:564D C3                        retn 

E000:564D                         Init_FSB endp ; sp = -0Ch

The next step is to analyze the SMBus related routine. Note that the base address of the SMBus is found after analyzing the bootblock. It is at I/O port 5000h. This base address is relocatable in the processor address space. That's why preliminary analysis in the bootblock code is needed. Also note that Init_FSB initialize the ds register to point to segment E000h. These informations are needed in later analysis. The SMBus related routine code as follows:

.........

E000:5650                         begin_clockgen_init_val

E000:5650 06                        db 6

E000:5651 00                        db 0 

E000:5652 0F                        db 0Fh 

E000:5653 7F                        db 7Fh 

E000:5654 FF                        db 0FFh 

E000:5655 FF                        db 0FFh 

E000:5656 3F                        db 3Fh 

E000:5657 24                        db 24h 

E000:5657                         end_clockgen_init_val 

......... 

E000:578B                         call_init_SMBus_dev_69h proc near 

E000:578B                                                     ; CODE XREF: Init_FSB+25 

E000:578B E8 01 00                  call  init_SMBus_device_69h 

E000:578E C3                        retn 

E000:578E                         call_init_SMBus_dev_69h endp 

E000:578F                         -- init_SMBus_device_69h -- 

E000:578F                         This is a very intriguing procedure. 

E000:578F                         But, I think it initializes the Clock Generator! 

E000:578F                         It's very unfortunate that the Clock Generator datasheet is not available :( 

E000:578F                         ; --------------- S U B R O U T I N E --------------------------------------- 

E000:578F                         init_SMBus_device_69h proc near 

E000:578F                                                     ; CODE XREF: call_init_SMBus_dev_69h 

E000:578F BA 04 50                  mov   dx, 5004h 

E000:5792 B0 D2                     mov   al, 0D2h ; 'T'      ; execute write command to SMBus device 69h 

E000:5794 EE                        out   dx, al 

E000:5795 E6 EB                     out   0EBh, al 

E000:5797 E6 EB                     out   0EBh, al 

E000:5799 BA 00 50                  mov   dx, 5000h 

E000:579C                         SMBUS_Host_is_busy:         ; CODE XREF: init_SMBus_device_69h+15 

E000:579C EC                        in    al, dx 

E000:579D E6 EB                     out   0EBh, al 

E000:579F EE                        out   dx, al 

E000:57A0 E6 EB                     out   0EBh, al 

E000:57A2 0A C0                     or    al, al 

E000:57A4 75 F6                     jnz   short SMBUS_Host_is_busy 

E000:57A6 BA 02 50                  mov   dx, 5002h 

E000:57A9 EC                        in    al, dx 

E000:57AA E6 EB                     out   0EBh, al 

E000:57AC E6 EB                     out   0EBh, al 

E000:57AE BE 50 56                  mov   si, 5650h 

E000:57B1 BA 05 50                  mov   dx, 5005h 

E000:57B4 2E 8A 04                  mov   al, cs:[si] 

E000:57B7 EE                        out   dx, al 

E000:57B8 E6 EB                     out   0EBh, al 

E000:57BA E6 EB                     out   0EBh, al 

E000:57BC BE 51 56                  mov   si, 5651h 

E000:57BF BA 07 50                  mov   dx, 5007h 

E000:57C2                         next_SMBUS_data:            ; CODE XREF: init_SMBus_device_69h+42

E000:57C2 2E 8A 04                  mov   al, cs:[si]

E000:57C5 EE                        out   dx, al

E000:57C6 E6 EB                     out   0EBh, al

E000:57C8 E6 EB                     out   0EBh, al

E000:57CA 83 C6 01                  add   si, 1

E000:57CD 81 FE 57 56               cmp   si, 5657h 

E000:57D1 75 EF                     jnz   short next_SMBUS_data 

E000:57D3 BA 02 50                  mov   dx, 5002h 

E000:57D6 B0 54                     mov   al, 54h ; 'T'       ; start SMBUS block write 

E000:57D8 EE                        out   dx, al 

E000:57D9 E6 EB                     out   0EBh, al 

E000:57DB E6 EB                     out   0EBh, al 

E000:57DD 33 C9                     xor   cx, cx 

E000:57DF BA 00 50                  mov   dx, 5000h 

E000:57E2                         host_not_done_yet:          ; CODE XREF: init_SMBus_device_69h+5A 

E000:57E2 EC                        in    al, dx 

E000:57E3 E6 EB                     out   0EBh, al 

E000:57E5 A8 02                     test  al, 2 

E000:57E7 75 02                     jnz   short done E000:57E9 E2 F7                     loop  host_not_done_yet 

E000:57EB                         done:                       ; CODE XREF: init_SMBus_device_69h+58 

E000:57EB C3                        retn 

E000:57EB                         init_SMBus_device_69h endp

As you can see in the code above, there's a routine that carry-out a "block-write" into the device that is attached to the SMBus, the device number is 69h. The block of data that's written to the SMBus is located at E000:5651h-E000:5657h. Since this procedure is located near the CPU initialization routine, our intuition told us that the corresponding device must be a clock generator chip. A comparison to other similar chip's datasheet, i.e. clock generator datasheet confirm that. I used winbond's clock generator data sheet (W83194R-37) for that. In the datasheet, it says it can generate clock for several PCI devices, an AGP devices, some SDRAM modules and some CPUs. It's also mentioned in the datasheet that the initialization is carried-out by using the SMBus to access the configuration register of the chip. With the init_SMBus_device_69h procedure at hand, I try to find another procedure that is called by Init_FSB to modify the block of data that is written into the SMBus device 69h. I found the call to the procedure in Init_FSB and name it as Init_FSB_n_Clock_Lines. The procedure as follows:

.........

E000:5650                         begin_clockgen_init_val

E000:5650 06                        db 6

E000:5651 00                        db 0 

E000:5652 0F                        db 0Fh 

E000:5653 7F                        db 7Fh 

E000:5654 FF                        db 0FFh 

E000:5655 FF                        db 0FFh 

E000:5656 3F                        db 3Fh 

E000:5657 24                        db 24h 

E000:5657                         end_clockgen_init_val 

.........        

E000:565B                         Init_FSB_n_Clock_Lines proc near ; CODE XREF: Init_FSB+16

E000:565B BE 5A 15                  mov   si, 155Ah

E000:565E E8 1D 16                  call  F0_Setup_BIOS_Defaults? ; DRAM type?

E000:5661 0A C0                     or    al, al

E000:5663 0F 85 85 00               jnz   next

E000:5667 E8 78 42                  call  XGROUP_Set_RAM_type_2_SDRAM

E000:566A BE 54 56                  mov   si, 5654h           ; SMBUS cmd index, hmmm what is it :? 

E000:566D A8 03                     test  al, 3 

E000:566F 75 04                     jnz   short bank01_populated 

E000:5671 2E 80 24 FE               and   byte ptr cs:[si], 0FEh ; disable clock-line for bank-0&1 in ClockGen-Chip 

E000:5675                         bank01_populated:           ; CODE XREF: Init_FSB_n_Clock_Lines+14 

E000:5675 A8 0C                     test  al, 0Ch 

E000:5677 75 04                     jnz   short bank23_populated 

E000:5679 2E 80 24 FD               and   byte ptr cs:[si], 0FDh ; disable clock-line for bank-2&3 in ClockGen-Chip 

E000:567D                         bank23_populated:           ; CODE XREF: Init_FSB_n_Clock_Lines+1C 

E000:567D A8 30                     test  al, 30h 

E000:567F 75 04                     jnz   short bank45_populated 

E000:5681 2E 80 24 FF               and   byte ptr cs:[si], 0FFh 

E000:5685                         bank45_populated:           ; CODE XREF: Init_FSB_n_Clock_Lines+24 

E000:5685 BE 53 56                  mov   si, 5653h 

E000:5688 B9 04 78                  mov   cx, 7804h           ; PCI bus0,devFh,func0,reg4h -- init PCI clock line 

E000:568B 56                        push  si 

E000:568C 0E                        push  cs 

E000:568D 68 98 56                  push  5698h 

E000:5690 68 AA 51                  push  51AAh               ; PCI_Bus0_Read_cfg_byte 

E000:5693 EA 88 61 00 E0            jmp   far ptr Fseg_vector E000:5698                         

; --------------------------------------------------------------------------- 

E000:5698 5E                        pop   si 

E000:5699 3C FF                     cmp   al, 0FFh            ; is read failed/device not exist? 

E000:569B 75 04                     jnz   short PCI_Bus_0_Dev_Fh_exist 

E000:569D 2E 80 24 BF               and   byte ptr cs:[si], 0BFh ; disable PCI clock output 

E000:56A1                         PCI_Bus_0_Dev_Fh_exist:     ; CODE XREF: Init_FSB_n_Clock_Lines+40 

E000:56A1 B9 04 80                  mov   cx, 8004h           ; PCI bus0,dev10h,func0,reg4h  -- init PCI clock line 

E000:56A4 56                        push  si 

E000:56A5 0E                        push  cs 

E000:56A6 68 B1 56                  push  56B1h 

E000:56A9 68 AA 51                  push  51AAh               ; PCI_Bus0_Read_cfg_byte 

E000:56AC EA 88 61 00 E0            jmp   far ptr Fseg_vector E000:56B1                         

; --------------------------------------------------------------------------- 

E000:56B1 5E                        pop   si 

E000:56B2 3C FF                     cmp   al, 0FFh            ; is read failed/device not exist? 

E000:56B4 75 04                     jnz   short PCI_Bus_0_Dev_10h_exist 

E000:56B6 2E 80 24 FE               and   byte ptr cs:[si], 0FEh ; disable PCI clock output 

E000:56BA                         PCI_Bus_0_Dev_10h_exist:    ; CODE XREF: Init_FSB_n_Clock_Lines+59 

E000:56BA B9 04 90                  mov   cx, 9004h           ; PCI bus0,dev12h,func0,reg4h -- init PCI clock line 

E000:56BD 56                        push  si 

E000:56BE 0E                        push  cs 

E000:56BF 68 CA 56                  push  56CAh 

E000:56C2 68 AA 51                  push  51AAh               ; PCI_Bus0_Read_cfg_byte 

E000:56C5 EA 88 61 00 E0            jmp   far ptr Fseg_vector E000:56CA                         

; --------------------------------------------------------------------------- 

E000:56CA 5E                        pop   si 

E000:56CB 3C FF                     cmp   al, 0FFh            ; is read failed/device not exist? 

E000:56CD 75 04                     jnz   short PCI_Bus_0_Dev_12h_exist 

E000:56CF 2E 80 24 EF               and   byte ptr cs:[si], 0EFh ; disable PCI clock output 

E000:56D3                         PCI_Bus_0_Dev_12h_exist:    ; CODE XREF: Init_FSB_n_Clock_Lines+72

E000:56D3 B9 04 98                  mov   cx, 9804h           ; PCI bus0,dev13h,func0,reg4h -- init PCI clock line

E000:56D6 56                        push  si

E000:56D7 0E                        push  cs

E000:56D8 68 E3 56                  push  56E3h

E000:56DB 68 AA 51                  push  51AAh               ; PCI_Bus0_Read_cfg_byte

E000:56DE EA 88 61 00 E0            jmp   far ptr Fseg_vector

E000:56E3                         ; ---------------------------------------------------------------------------

E000:56E3 5E                        pop   si

E000:56E4 3C FF                     cmp   al, 0FFh            ; is read failed/device not exist?

E000:56E6 75 04                     jnz   short next

E000:56E8 2E 80 24 F7               and   byte ptr cs:[si], 0F7h ; disable PCI clock output 

E000:56EC                         next:                       ; CODE XREF: Init_FSB_n_Clock_Lines+8 

E000:56EC                                                     ; Init_FSB_n_Clock_Lines+8B 

E000:56EC B0 A0                     mov   al, 0A0h ; 'a' 

E000:56EE E8 17 43                  call  F0_Read_Port_73h 

E000:56F1 3C 55                     cmp   al, 55h ; 'U' 

E000:56F3 74 7A                     jz    short setup_DRAM_clock? 

E000:56F5 B0 A1                     mov   al, 0A1h ; 'a' 

E000:56F7 E8 0E 43                  call  F0_Read_Port_73h 

E000:56FA 24 F0                     and   al, 0F0h 

E000:56FC BE 51 56                  mov   si, 5651h 

E000:56FF 2E 80 0C 08               or    byte ptr cs:[si], 8 

E000:5703 50                        push  ax 

E000:5704 B9 68 00                  mov   cx, 68h ; 'h'       ; DRAM Control 

E000:5707 0E                        push  cs 

E000:5708 68 13 57                  push  5713h 

E000:570B 68 0B F7                  push  0F70Bh              ; Read_PCI_Bus0_Byte 

E000:570E EA 88 61 00 E0            jmp   far ptr Fseg_vector 

E000:5713                         ; --------------------------------------------------------------------------- 

E000:5713 A8 02                     test  al, 2               ; FSB = 133Mhz/Reserved? 

E000:5715 74 13                     jz    short FSB_66MHz_or_100MHz 

E000:5717 58                        pop   ax 

E000:5718 8A D8                     mov   bl, al 

E000:571A 24 C0                     and   al, 0C0h 

E000:571C 3C C0                     cmp   al, 0C0h ; 'L' 

E000:571E 8A C3                     mov   al, bl 

E000:5720 74 3C                     jz    short FSB_init_done 

E000:5722 B0 F0                     mov   al, 0F0h ; '?' 

E000:5724 83 4E 38 40               or    word ptr [bp+38h], 40h 

E000:5728 EB 34                     jmp   short FSB_init_done 

E000:572A                         ; --------------------------------------------------------------------------- 

E000:572A                         FSB_66MHz_or_100MHz:        ; CODE XREF: Init_FSB_n_Clock_Lines+BA 

E000:572A A8 01                     test  al, 1 

E000:572C 74 1B                     jz    short FSB_66MHz 

E000:572E 58                        pop   ax 

E000:572F 8A D8                     mov   bl, al 

E000:5731 24 C0                     and   al, 0C0h 

E000:5733 3C 00                     cmp   al, 0 

E000:5735 74 04                     jz    short loc_E000_573B 

E000:5737 8A C3                     mov   al, bl 

E000:5739 75 23                     jnz   short FSB_init_done 

E000:573B                         loc_E000_573B:              ; CODE XREF: Init_FSB_n_Clock_Lines+DA 

E000:573B 8A C3                     mov   al, bl 

E000:573D 3C 00                     cmp   al, 0 

E000:573F 74 1D                     jz    short FSB_init_done 

E000:5741                         loc_E000_5741: 

E000:5741 B0 70                     mov   al, 70h ; 'p' 

E000:5743 83 4E 38 40               or    word ptr [bp+38h], 40h 

E000:5747 EB 15                     jmp   short FSB_init_done 

E000:5749                         ; --------------------------------------------------------------------------- 

E000:5749                         FSB_66MHz:                  ; CODE XREF: Init_FSB_n_Clock_Lines+D1 

000:5749 58                        pop   ax 

E000:574A 8A D8                     mov   bl, al 

E000:574C 3C 00                     cmp   al, 0 

E000:574E 74 08                     jz    short loc_E000_5758 

E000:5750 24 C0                     and   al, 0C0h 

E000:5752 3C 00                     cmp   al, 0 

E000:5754 8A C3                     mov   al, bl 

E000:5756 74 06                     jz    short FSB_init_done 

E000:5758                         loc_E000_5758:              ; CODE XREF: Init_FSB_n_Clock_Lines+F3 

E000:5758 B0 30                     mov   al, 30h ; '0' 

E000:575A 83 4E 38 40               or    word ptr [bp+38h], 40h 

E000:575E                         FSB_init_done:              ; CODE XREF: Init_FSB_n_Clock_Lines+C5 

E000:575E                                                     ; Init_FSB_n_Clock_Lines+CD ... 

E000:575E 50                        push  ax 

E000:575F 24 80                     and   al, 80h 

E000:5761 A8 80                     test  al, 80h 

E000:5763 58                        pop   ax 

E000:5764 74 04                     jz    short loc_E000_576A 

E000:5766 2E 80 0C 04               or    byte ptr cs:[si], 4 

E000:576A                         loc_E000_576A:              ; CODE XREF: Init_FSB_n_Clock_Lines+109 

E000:576A 24 7F                     and   al, 7Fh 

E000:576C 2E 08 04                  or    cs:[si], al 

E000:576F                         setup_DRAM_clock?:          ; CODE XREF: Init_FSB_n_Clock_Lines+98 

E000:576F BE 73 15                  mov   si, 1573h 

E000:5772 E8 09 15                  call  F0_Setup_BIOS_Defaults? 

E000:5775 0A C0                     or    al, al 

E000:5777 74 11                     jz    short exit 

E000:5779 BE 51 56                  mov   si, 5651h 

E000:577C 2E 80 0C 02               or    byte ptr cs:[si], 2 

E000:5780 FE C8                     dec   al 

E000:5782 A8 01                     test  al, 1 

E000:5784 74 04                     jz    short exit 

E000:5786 2E 80 0C 80               or    byte ptr cs:[si], 80h 

E000:578A                         exit:                       ; CODE XREF: Init_FSB_n_Clock_Lines+11C 

E000:578A                                                     ; Init_FSB_n_Clock_Lines+129 

E000:578A C3                        retn 

E000:578A                         Init_FSB_n_Clock_Lines endp ; sp = -0Eh

After reading the procedure, some more hints shows up, such as checking the availability of certain PCI device, followed by modifcation of the SMBus command (block of data that is later sent through the SMBus). I suspect that this routine modifies the output of the clock generator to certain PCI clock lines. The only way to confirm this is by modifying the suspected routine and observe the effect of the modification. Thus, I carried out a small experiment. I modify the code so that the PCI clock-line to device in PCI bus 0 device number 13h will be disabled, as follows:

E000:565B                         Init_FSB_n_Clock_Lines proc near ......... E000:56D3                         PCI_Bus_0_Dev_12h_exist:        ; CODE XREF: seg000:56CD E000:56D3 90                        nop

E000:56D4 90                        nop

E000:56D5 90                        nop

E000:56D6 90                        nop

E000:56D7 90                        nop

E000:56D8 90                        nop

E000:56D9 90                        nop

E000:56DA 90                        nop

E000:56DB 90                        nop

E000:56DC 90                        nop

E000:56DD 90                        nop

E000:56DE 90                        nop

E000:56DF 90                        nop

E000:56E0 90                        nop

E000:56E1 90                        nop

E000:56E2 90                        nop

E000:56E3 90                        nop

E000:56E4 90                        nop

E000:56E5 90                        nop

E000:56E6 90                        nop

E000:56E7 90                        nop

E000:56E8 2E 80 24 F7               and   byte ptr cs:[si], 0F7h  ; disable PCI clock output at PCI Bus 0 Dev 13h

E000:56EC

E000:56EC                         next:                           ; CODE XREF: seg000:5663

E000:56EC B0 A0                     mov   al, 0A0h ; 'a'

.........

E000:578A                         Init_FSB_n_Clock_Lines endp

With the original BIOS, the device that resides at PCI bus 0 device 13h is a Realtek 8139 LAN card. This card is attached to the PCI expansion slot of the Iwill VD133 mainboard. Thus, the modification above will disable the clock-line for this PCI slot.

After flashing the modified BIOS (with clock output to PCI bus 0 dev 13h disabled), I checked the existence of the device in windows and during power-up (in the BIOS screen for PCI devices). The network card is not shown, eventhough the card is installed. Voila', our guess is right! The code is indeed controlling the clock generator setting for PCI bus 0 Device 13h.

However, reflashing the original BIOS again wouldn't bring back the PCI slot to active immediately. I have to shutdown the system totally and starting it back to make the PCI slot active again. Simple system restart is not enough to carry out a clock-generator re-initialization.

As before, if you want to try this modification yourself, patch the highlighted instructions by using hexeditor as shown above. But again, remember that proceed at your own risk.

Anyway, you might expect me to provide you with a signature for this clock-generator initialization routine. Unfortunately, I don't. Because I think that after going through the article this far you can figure it out yourself ;-).

OK, the modification story ended-up here. Now, we know how to deal even with the most obscure kind of modification with incomplete datasheet at hand (^__^).

4. Generic System-BIOS Patching Ninjutsu

I've tried to apply the trick described in section 3 to Modbin6 version 2.01 for Award BIOS version 6 binary. But, I haven't try the modified BIOS yet. The preliminary test shows that Modbin6 generates temporary ORIGINAL.BIN, MLSTRING.BIN and XGROUP.BIN files. Nevertheless, further tests are needed to find-out its properties.

From the experiments that I've carried-out, it's clear that possibly, most of the sytem-BIOS altering programs, such as modbin , generates temporary files during their execution. Thus, we can use that opportunity to patch the binary, provided that we've known their structure in advance. In the mean time, we can conclude that the general system-BIOS patching steps are as follows:

The principles above supposedly work for all kind of BIOS. Hence, it's a matter of having the right utility at hand.

Have a nice day (^__^).

5. References

Copyright © Darmawan M S a.k.a Pinczakko