【我所认知的BIOS】->反汇编BIOS之Bootblock(11)

【我所认知的BIOS->反汇编BIOSBootblock(11)

-- 初识BIOS的解压缩

By Lightseed

8/24/2010 

 

      最近一段时间心态不太好,所以blog也没有更新。现在总算是调整过来了,目前我是这么打算,反汇编的文章暂时就写到bootblock这里了。至于如果还有兴趣研究POST部分的爱好者的话,我们可以私聊。后续文章准备写些比较深入点的文章,比较细节点的分析等等。希望大家给点建议,也希望我们BIOS ren共同进步~并且我准备把这个blog搬到BIOS联盟上去。毕竟那面比较专业一点。至此这篇文章也是bootblock反汇编的最后一篇文章了,其中还有一个问题没研究就是award bios的解压缩函数。这个函数用的LHA的压缩和解压缩算法,我没深入研究过。不过据说网上研究过的人比比皆是,再加上这段code一般都不会出错,所以我暂时也不打算深入研究了。如果你已经研究过了,可否和我share一下?

1BIOS的主流程

bootblock的最后阶段,那当然就是把BIOS的压缩代码全部解压缩出来,然后进入到后续的BIOS初始化流程当中去。在这个章节中,我们就来简单探讨一下解压缩和解压缩以后BIOS的大致走向。(关于解压缩的细节,我们再议。)

 

1 BIOS主流程

2、在解压缩BIOS之前的一些初始化

BIOS执行到现在,它本身已经被copy到了RAM中来,并且也正常RAM中跑了。不过为了能够让后续的BIOS跑的更快,更稳的话,我们还需要把内存的一些属性给初始化一下。这里要第一次接触到MTRR的初始化了哦。在前面的基础章节我曾经有和大家探讨过内存的属性的初始化。

http://blog.csdn.net/lightseed/archive/2009/09/28/4603383.aspx

如果您忘记的MTRR的一些东西,那么您可以从这里再回味一下。

_F000:E482                 jmp     far ptr 2000h:0E487h ; Here BIOS copy itself to RAM

_F000:E482                                         ; Althrough BIOS will use FAR JMP to run at 2000:0, but code is continuous.

_F000:E482                                         ; So we can go on disassembling in F0000

_F000:E487 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?

_F000:E487                 xor     ax, ax

_F000:E489                 mov     ss, ax

_F000:E48B                 assume ss:seg000

_F000:E48B                 mov     sp, 0E00h       ; Stack init

_F000:E48E                 call    Check_If_Intel_CPU

_F000:E491                 jz      Yes_its_IntelCPU

_F000:E493                 cmp     ebx, 'tneC'     ; yuanhu+ ;Centaur CPU's identifier

_F000:E49A                 jnz     loc_FE4DB

_F000:E49C

_F000:E49C Yes_its_IntelCPU:                       ; CODE XREF: _F000:E491j

_F000:E49C                 mov     eax, 6060606h

_F000:E4A2                 mov     edx, eax

_F000:E4A5                 mov     ecx, 250h       ; MTTR Address(250H) for 0-512K is WB

_F000:E4AB                 wrmsr                   ; Init memory type range register(MTTR)

_F000:E4AD                 mov     cl, 58h ; 'X'   ; Address(258H) for 512K-640K is WB

_F000:E4AF                 wrmsr

_F000:E4B1                 xor     eax, eax

_F000:E4B4                 mov     edx, eax        ; Disable C0000 - FFFFFh Cacheable

_F000:E4B7                 mov     cl, 59h ; 'Y'

_F000:E4B9                 wrmsr

_F000:E4BB                 mov     cl, 68h ; 'h'

_F000:E4BD

_F000:E4BD EarlySetupMTRRLoop:                     ; CODE XREF: _F000:E4C4j

_F000:E4BD                 wrmsr

_F000:E4BF                 inc     cl

_F000:E4C1                 cmp     cl, 6Fh ; 'o'

_F000:E4C4                 jbe     EarlySetupMTRRLoop

_F000:E4C6                 mov     eax, 0C00h

_F000:E4CC                 xor     edx, edx

_F000:E4CF                 mov     cl, 0FFh        ; MTTR Address(2FFH), Enable cache

_F000:E4D1                 wrmsr

_F000:E4D3                 wbinvd                  ; Clear cache

_F000:E4D5                 mov     eax, cr3

_F000:E4D8                 mov     cr3, eax

_F000:E4DB

_F000:E4DB loc_FE4DB:                              ; CODE XREF: _F000:E49Aj

_F000:E4DB                 mov     al, 0FFh

_F000:E4DD                 call    CPU_Cache       ; In order to speed up run bios

_F000:E4E0                 mov     al, 0Ch

_F000:E4E2                 out     80h, al         ; manufacture's diagnostic checkpoint

_F000:E4E4                 call    Search_BBSS_label

_F000:E4E7                 mov     ax, [si+0Eh]    ; Get address of the decompress engine

_F000:E4EA                 mov     si, 0

_F000:E4ED                 mov     ds, si

_F000:E4EF                 mov     si, 6000h       ; Temp buffer for decompressing

_F000:E4F2                 mov     [si], ax        ; Put Funcion address of decompress engine in 6000:0

_F000:E4F4                 mov     al, 0C3h ; '?

_F000:E4F6                 out     80h, al         ; manufacture's diagnostic checkpoint

_F000:E4F8                 call    Decompress_Whole_Bios

_F000:E4FB                 jmp     short loc_FE51F

_F000:E4FD ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?

_F000:E4FD

_F000:E4FD loc_FE4FD:                              ; CODE XREF: Expand_Bios+AEj

_F000:E4FD                                         ; Expand_Bios+B9j

_F000:E4FD                 push    2000h

_F000:E500                 pop     ds

_F000:E501                 assume ds:nothing

_F000:E501                 mov     dword ptr ds:0FFF4h, 2F3131F0h

_F000:E50A                 mov     dword ptr ds:0FFF8h, 392F3131h

_F000:E513                 mov     dword ptr ds:0FFFCh, 0CFFC0039h

_F000:E51C                 mov     ax, 1000h

_F000:E51F

_F000:E51F loc_FE51F:                              ; CODE XREF: _F000:E4FBj

_F000:E51F                 mov     ds, ax          ; BIOS is stiored in 5000h segment, now

_F000:E521                 assume ds:nothing

_F000:E521                 push    ax

_F000:E522                 mov     al, 0C5h ; '?

_F000:E524                 out     80h, al         ; manufacture's diagnostic checkpoint

_F000:E526                 call    Shadow_System_Bios

_F000:E529                 pop     ax

_F000:E52A                 cmp     ax, 5000h

_F000:E52D                 jz      SumOk

_F000:E52F                 jmp     far ptr loc_FF7D0

_F000:E534 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪?

_F000:E534

_F000:E534 SumOk:                                  ; CODE XREF: _F000:E52Dj

_F000:E534                 mov     al, 0

_F000:E536                 call    CPU_Cache         ;Turn cpu cache on to speed up

_F000:E539                 jmp     far ptr loc_FF80D ; Althrough this FAR JUMP is F000:F80D, but we must note that BIOS have been decompressed

_F000:E539                                         ; and store into E0000-FFFFFH. So we must change our bin file to go on disassembling BIOS.

对于上面的MTRR的初始化我就说一点,其他的应该都很明白了。初始化的这些寄存器都是cpu内存的寄存器,对应的特定的MSR会表征CPU在处理特定范围的内存做出对应的处理。其实BIOS做这个过程,目的都是为了让BIOS跑的更快更稳。

3BIOS的解压缩函数

Bootblock跑了这么久,不就是为了解压缩么,到了现在我们终于见到了解压缩函数的真面目。真是“千呼万唤始出来”呀_F000:E4F8这个函数就是把整个压缩的BIOS bin文件给解压缩出来的函数了。(稍后我们再讨论,先飘过。。)

4、解压缩后把BIOS copyE000F000段的内存中去

BIOS被自己彻底解压缩了以后,在_F000:E526这行中就是把BIOS5000Hcopy到高端内存中去的函数。我要着重和大家探讨一下它。其实也很简单啦,只是觉得它比较重要,所以要单独拎出来说说。代码如下:

_F000:88C0 ; 圹圹圹圹圹圹圹?S U B R O U T I N E 圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹?

_F000:88C0

_F000:88C0

_F000:88C0 Shadow_System_Bios proc near            ; CODE XREF: _F000:E526p

_F000:88C0                 mov     cx, 95h ; '?   ; Programmable Attribute Map 5 E000-E800

_F000:88C3                 mov     al, 22h ; '"'   ; Write Only: All writes are sent to DRAM. Reads are serviced by DMI

_F000:88C5                 call    Set_Pci_byte

_F000:88C8                 mov     cx, 96h ; '?   ; Programmable Attribute Map 6 E800-F000

_F000:88CB                 mov     al, 22h ; '"'   ; Write Only: All writes are sent to DRAM. Reads are serviced by DMI

_F000:88CD                 call    Set_Pci_byte

_F000:88D0                 push    ds

_F000:88D1                 mov     si, ds          ; From 5000h segment

_F000:88D3                 mov     di, 0E000h      ; To E000H segment

_F000:88D6                 mov     cx, 8000h       ; 64 KB will be moved

_F000:88D9                 call    Move_code

_F000:88DC                 pop     ds

_F000:88DD                 assume ds:nothing

_F000:88DD                 mov     cx, 96h ; '?   ; Programmable Attribute Map 6 E800-F000

_F000:88E0                 mov     al, 11h         ; Read Only: All reads are serviced by DRAM. All writes are forwarded to the

_F000:88E0                                         ; DMI.

_F000:88E2                 call    Set_Pci_byte

_F000:88E5                 mov     cx, 95h ; '?

_F000:88E8                 mov     al, 11h         ; Read Only: All reads are serviced by DRAM. All writes are forwarded to the

_F000:88E8                                         ; DMI.

_F000:88EA                 call    Set_Pci_byte

_F000:88ED                 mov     cx, 90h ; '?   ; Programmable Attribute Map 0 F0000-FFFFFH

_F000:88F0                 call    Get_Pci_Byte

_F000:88F3                 and     al, 0Fh

_F000:88F5                 or      al, 20h         ; Write Only: All writes are sent to DRAM. Reads are serviced by DMI.

_F000:88F7                 call    Set_Pci_byte

_F000:88FA                 mov     si, ds

_F000:88FC                 add     si, 1000h       ; From 6000h segment

_F000:8900                 mov     di, 0F000h      ; To F000h segment

_F000:8903                 mov     cx, 8000h       ; 64 KB will be moved

_F000:8906                 call    Move_code

_F000:8909                 mov     cx, 90h ; '?

_F000:890C                 call    Get_Pci_Byte

_F000:890F                 and     al, 0Fh

_F000:8911                 or      al, 10h         ; Read Only: All reads are serviced by DRAM. All writes are forwarded to the

_F000:8911                                         ; DMI.

_F000:8913                 call    Set_Pci_byte

_F000:8916                 clc

_F000:8917                 retn

_F000:8917 Shadow_System_Bios endp

看看上面的函数,算法其实也比较简单的,只是可能大家对北桥的寄存器不太了解。我在上面均加了详细的注释,如果还是不太明白的那就多查阅一下北桥的相关寄存器哦。

5BIOS彻底换血

_F000:E539主要是这行,我需要强调一下。这里用了一个FAR jmp,而段地址是F000。用这个FAR jmp就是为了进入到当前被copy到了F000段的被解压缩出来的BIOS中去。到此应该Bootblock的使命就是彻底完成了。那么bootblock的系列文章也应该差不多要画上句号了。

 

 

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页