EFI Inside

Материал из Wiki.ROM.by
Перейти к: навигация, поиск

EFI, как мало в этом звуке... Пропустим одиозные утверждения о всемогуществе оного и давно морально погибшем BIOS-е. Перейдём к "практическо-прикладной" стороне - что и как работает, где и чем с ним бороться.

/* Разбор проведём на примере биоса от Intel D945GTP */

/* Нижеизлагаемое - "в процессе" (т.е. прямо в процессе разбора), потому возможны исправления в последствии. Указания на неточности (равно как и грубые ошибки :) ) - всячески приветствуются (путём исправления здесь же). */

Старт

Плохое начинается прямо со старта.

FFFF:FFF0 wbinvd
FFFF:FFF2 jmp     loc_FF00
...
FFFF:FF00 loc_FF00:
FFFF:FF00 mov     esi, 0FFFFFB00h ; Start
FFFF:FF06 jmp     short $+2
FFFF:FF08 mov     ebp, eax          ; Save BIST
FFFF:FF0B xor     eax, eax
FFFF:FF0E mov     ax, cs
FFFF:FF10 mov     ds, ax
FFFF:FF12 lgdt    cs:qword_FF90
FFFF:FF19 mov     eax, cr0
FFFF:FF1C or      eax, 3
FFFF:FF20 mov     cr0, eax
FFFF:FF23 mov     eax, cr4
FFFF:FF26 or      eax, 600h
FFFF:FF2C mov     cr4, eax
FFFF:FF2F mov     ax, 18h
FFFF:FF32 mov     ds, ax
FFFF:FF34 mov     es, ax
FFFF:FF36 mov     fs, ax
FFFF:FF38 mov     gs, ax
FFFF:FF3A mov     ss, ax
FFFF:FF3C jmp     large [fword ptr cs:byte_FF44]
...
loc_FFFFFF42:
FFFF:FF42 jmp     esi ; jmp to Start
; -----------------------------------
FFFF:FF44 dd offset loc_FFFFFF42

Плохое - это переключение в защищённый режим работы. Всё - "с места - в карьер", никаких "биосных штучек".

Start:
FFFFFB00 xor     eax, eax
FFFFFB02 inc     eax
FFFFFB03 cpuid
FFFFFB05 mov     eax, cr0
FFFFFB08 or      eax, 60000000h
FFFFFB0D wbinvd
FFFFFB0F mov     cr0, eax        ; Disable Cache
FFFFFB12 mov     esi, offset word_FFFFFE37 ; 2FF
FFFFFB17 mov     edi, 1Ch
FFFFFB1C xor     eax, eax
FFFFFB1E xor     edx, edx
loc_FFFFFB20:
FFFFFB20 movzx   ecx, word ptr cs:[esi]
FFFFFB24 wrmsr
FFFFFB26 add     esi, 2
FFFFFB29 dec     edi
FFFFFB2A jnz     short loc_FFFFFB20
FFFFFB2C jmp     short $+2
FFFFFB2E mov     dx, 0CF8h
FFFFFB32 mov     eax, 8000F8D8h  ; Firmware Hub Decode Enable Register
FFFFFB37 out     dx, eax
FFFFFB38 add     dx, 4
FFFFFB3C mov     ax, 0FFCFh      ; Default Value
FFFFFB40 out     dx, ax
FFFFFB42 mov     eax, offset CPU_0F43.data
...

Далее следует первичная инициализация системы, где кроме "преинициализации" микрокодов, происходит весьма хитрые манипуляции с кэшем:

...
FFFFFCE1 loc_FFFFFCE1:
FFFFFCE1 mov     eax, cr0
FFFFFCE4 and     eax, 9FFFFFFFh
FFFFFCE9 wbinvd
FFFFFCEB mov     cr0, eax        ; Enable Cache
FFFFFCEE
FFFFFCEE cld
FFFFFCEF mov     esi, 0FEF00000h
FFFFFCF4 mov     edi, esi
FFFFFCF6 mov     ecx, 800h
FFFFFCFB rep lodsd
FFFFFCFD mov     esi, 0FEF00000h
FFFFFD02 mov     edi, esi
FFFFFD04 mov     ecx, 800h
FFFFFD09 mov     eax, 5AA55AA5h
FFFFFD0E rep stosd
FFFFFD10
FFFFFD10 mov     eax, cr0
FFFFFD13 or      eax, 60000000h
FFFFFD18 mov     cr0, eax        ; Disable Cache
FFFFFD1B jmp     short $+2
FFFFFD1D
FFFFFD1D mov     esp, 0FEF02000h ; Set ESP to CAR
FFFFFD22 xor     eax, eax
FFFFFD24 inc     eax
FFFFFD25 cpuid
FFFFFD27 shr     ebx, 10h
FFFFFD2A and     ebx, 0FFh
FFFFFD30 push    ebx
FFFFFD31 cmp     bl, 1
FFFFFD34 jbe     short loc_FFFFFD4E
FFFFFD36 mov     ecx, 203h
FFFFFD3B rdmsr
FFFFFD3D shr     eax, 0Ch
FFFFFD40 push    ax
FFFFFD42 mov     ecx, 202h
FFFFFD47 rdmsr
FFFFFD49 shr     eax, 0Ch
FFFFFD4C push    ax
FFFFFD4E
FFFFFD4E loc_FFFFFD4E:

CAR - не имеет никакого отношения к машинам. Это есть режим работы системы - "Cache as RAM", когда кэш используется как память. Размер такой "халявной" памяти равняется объёму кэша второго уровня делённому на ассоциативность. Например, для Core 2 Duo это поулучится 2Мб / 8 = 256кБ (для каждого ядра отдельно) - "выше крыши".

Именно поэтому, в частности, последним идёт выключение кэша - ведь он должен "работать памятью". И именно поэтому "в туда" устанавливается стэкпоинтер. В общем, после всех таких фокусов и "внезапно появившейся" памяти - происходит стандартный (в смысле - как при наличии "реальной" памяти) переход на "начало начала":

loc_FFFFFD4E:
FFFFFD4E push    ebp
FFFFFD4F push    dword ptr ds:word_FFFFFFFC
FFFFFD55 push    2000h ; Stack Size
FFFFFD5A mov     edi, offset _PeiMain ; PeiMain
FFFFFD5F call    dword ptr [edi]

PEI

Всё, закончился ассемблер "человеческий". :) Далее лишь плоды компиляторов, потому "членораздельный" код "без полста" найти не получится. Берём в руки доступные исходники и весь остальной разбор лишь с помощью оных.

FFFF03FB PeiMain       proc near
FFFF03FB
FFFF03FB var_C           = dword ptr -0Ch
FFFF03FB var_8           = dword ptr -8
FFFF03FB arg_0           = dword ptr  8
FFFF03FB arg_4           = dword ptr  0Ch
FFFF03FB
FFFF03FB                 push    ebp
FFFF03FC                 mov     ebp, esp        ; push    ebp
FFFF03FC                                         ; push    dword ptr ds:word_FFFFFFFC
FFFF03FC                                         ; push    2000h
FFFF03FE                 sub     esp, 10h
FFFF0401                 mov     eax, [ebp+arg_0] ; 2000h
FFFF0404                 mov     [ebp+var_8], eax
FFFF0407                 mov     eax, [ebp+arg_4] ; ds:word_FFFFFFFC
FFFF040A                 mov     [ebp+var_C], eax
FFFF040D
FFFF040D                 lea     eax, [ebp-10h]
FFFF0410                 push    0               ; *OldCoreData
FFFF0412                 push    eax             ; *PeiStartupDescriptor
FFFF0413                 mov     dword ptr [ebp-10h], offset xor_eax_eax
FFFF041A                 mov     dword ptr [ebp-4], offset _EFI_SEC_PLATFORM_INFORMATION_GUID
FFFF0421                 call    PeiCore
; ---------------------------------------------------------------------------------------
; The entry routine to Pei Core, invoked by PeiMain during transition
; from SEC to PEI. After switching stack in the PEI core, it will restart
; with the old core data.
; Arguments:
;   PeiStartupDescriptor - Information and services provided by SEC phase.
;   OldCoreData          - Pointer to old core data that is used to init the core's data areas.
; ---------------------------------------------------------------------------------------
FFFF0426                 pop     ecx
FFFF0427                 pop     ecx
FFFF0428                 leave
FFFF0429                 retn
FFFF0429 PeiMain         endp

PEI - есть Pre-EFI Initialization phase. Т.е. в проекции на BIOS (в "классическом" понимания этого слова) - это код, выполняемый в бутблоке, т.е на самой начальной стадии работы компьютера, который подготавливает работу для "основной" части кода BIOS-POST / EFI-DXE (Driver Execution Environment phase).

FFFF042A PeiCore         proc near               ; CODE XREF: PeiMain+26↑p
FFFF042A                                         ; DATA XREF: PeiCore+238↓o
FFFF042A
FFFF042A var_84          = dword ptr -84h
FFFF042A OldCoreData     = dword ptr  8
FFFF042A PeiStartupDescriptor= dword ptr  0Ch
FFFF042A
FFFF042A                 push    ebp
FFFF042B                 mov     ebp, esp
FFFF042D                 sub     esp, 1A4h
FFFF0433                 push    ebx
FFFF0434                 mov     ebx, [ebp+PeiStartupDescriptor]
FFFF0437                 push    esi
FFFF0438                 push    edi
FFFF0439
FFFF0439                 push    [ebp+OldCoreData]
FFFF043C                 mov     ecx, ebx
FFFF043E
FFFF043E PrivateData.PS = &mPS;
FFFF043E                 lea     eax, [ebp-1A0h]
FFFF0444
FFFF0444 PrivateData.Signature = PEI_CORE_HANDLE_SIGNATURE;
FFFF0444                 mov     dword ptr [ebp-1A4h], 'CieP' ; 'PeiC' = PEI_CORE_HANDLE_SIGNATURE
FFFF044E                 mov     dword ptr [ebp-1A0h], offset EFI_PEI_SERVICES
FFFF0458
FFFF0458 InitializeMemoryServices (&PrivateData.PS, PeiStartupDescriptor, OldCoreData);
FFFF0458                 call    InitializeMemoryServices

Персональные инструменты
Google