SEC phase


下面是摘自PI Specification . Vol 1_PEI中的描述SEC Phase的話。http://www.uefi.org/
The Security (SEC) phase is the first phase in the PI Architecture architecture and is responsible for the following:Handling all platform restart eventsCreating a temporary memory storeServing as the root of trust in the systemPassing handoff information to the PEI Foundation
In addition to the minimum architecturally required handoff information, the SEC phase can pass optional information to the PEI Foundation, such as the SEC Platform Information PPI or information about the health of the processor.
下面來看代碼是怎樣實現這些function。代碼下載:https://github.com/tianocore/edk2

EDK2 Code:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; file: UefiCpuPkg\ResetVector\Vtf0\Ia16\ResetVectorVtf0.asm
resetVector:
;
; Reset Vector
;
; This is where the processor will begin execution
;
    nop
    nop
    jmp     EarlyBspInitReal16

ALIGN   16
fourGigabytes:     


; file: UefiCpuPkg\ResetVector\Vtf0\Ia16\Init16.asm

; 16-bit initialization code
;
; @param[out] DI    'BP' to indicate boot-strap processor
;
EarlyBspInitReal16:
    mov     di, 'BP'



; file: UefiCpuPkg\ResetVector\Vtf0\Main.asm
; @file
; Main routine of the pre-SEC code up through the jump into SEC
;

;
; Modified:  EBX, ECX, EDX, EBP
;
; @param[in,out]  RAX/EAX  Initial value of the EAX register
;                          (BIST: Built-in Self Test)
; @param[in,out]  DI       'BP': boot-strap processor, or
;                          'AP': application processor
; @param[out]     RBP/EBP  Address of Boot Firmware Volume (BFV)
;
; @return         None  This routine jumps to SEC and does not return
;
Main16:
    OneTimeCall EarlyInit16
    ;
    ; Transition the processor from 16-bit real mode to 32-bit flat mode
    ;
    OneTimeCall TransitionFromReal16To32BitFlat

BITS    32
    ;
    ; Search for the Boot Firmware Volume (BFV)
    ;
    OneTimeCall Flat32SearchForBfvBase
    ;
    ; EBP - Start of BFV
    ;
    ; Search for the SEC entry point
    ;
    OneTimeCall Flat32SearchForSecEntryPoint
    ;
    ; ESI - SEC Core entry point
    ; EBP - Start of BFV
    ;
%ifdef ARCH_IA32
    ;
    ; Restore initial EAX value into the EAX register
    ;
    mov     eax, esp
    ;
    ; Jump to the 32-bit SEC entry point
    ;
    jmp     esi

%else
    ;
    ; Transition the processor from 32-bit flat mode to 64-bit flat mode
    ;
    OneTimeCall Transition32FlatTo64Flat

BITS    64
    ;
    ; Some values were calculated in 32-bit mode.  Make sure the upper
    ; 32-bits of 64-bit registers are zero for these values.
    ;
    mov     rax, 0x00000000ffffffff
    and     rsi, rax
    and     rbp, rax
    and     rsp, rax
    ;
    ; RSI - SEC Core entry point
    ; RBP - Start of BFV
    ;
    ; Restore initial EAX value into the RAX register
    ;
    mov     rax, rsp
    ;
    ; Jump to the 64-bit SEC entry point
    ;
    jmp     rsi
%endif
接下來調用SecCore Entry Point,不同的硬件平臺會有不同的實現方式,原理相似。
# Module Name:
#
#  SecEntry.S
#
# Abstract:
#
#  This is the code that begins in protected mode.
#   It will transfer the control to pei core.
#
#------------------------------------------------------------------------------------------------------------------------------------------
ASM_GLOBAL  ASM_PFX(SecStartup)
# Pcds
ASM_GLOBAL  ASM_PFX(PcdGet32 (PcdPayloadFdMemBase))
#
# SecCore Entry Point
#
# Processor is in flat protected mode
#
# @param[in]  EAX   Initial value of the EAX register (BIST: Built-in Self Test)
# @param[in]  DI    'BP': boot-strap processor, or 'AP': application processor
# @param[in]  EBP   Pointer to the start of the Boot Firmware Volume
#
# @return     None  This routine does not return
#
ASM_GLOBAL ASM_PFX(_ModuleEntryPoint)
ASM_PFX(_ModuleEntryPoint):
  #
  # Disable all the interrupts
  #
  cli
  
  #
  # Construct the temporary memory at 0x80000, length 0x10000
  #
  movl $(BASE_512KB + SIZE_64KB), %esp
  #
  # Pass BFV into the PEI Core
  #
  pushl ASM_PFX(PcdGet32 (PcdPayloadFdMemBase))
  
  #
  # Pass stack base into the PEI Core
  #
  pushl $BASE_512KB
  #
  # Pass stack size into the PEI Core
  #
  pushl $SIZE_64KB
  #
  # Pass Control into the PEI Core
  #
  call SecStartup
  
  #
  # Never return to here
  #
  jmp .
未完待續。。。。

子函數:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
OneTimeCall是宏,用於模擬call指令,OneTimeCallRet 配合使用,因爲在Reset Vector部分還沒有RAM可用

%macro  OneTimeCall 1        
    jmp     %1
%1 %+ OneTimerCallReturn:
%endmacro

%macro  OneTimeCallRet 1
    jmp     %1 %+ OneTimerCallReturn
%endmacro

/* %macro是定義多行宏,定義一個名爲OneTimeCall 的宏,接收一個參數(nasm彙編)*/
/*   %macro  宏名  參數名列表
          宏體
      %endmacro  */

OneTimeCall EarlyInit16相當於:
jmp EarlyInit16
EarlyInit16OneTimerCallReturn:    /*  需要注意的是%+可以連接字符串 */
下面依此類推
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;
; Modified:  EAX
;
; @param[in]  EAX   Initial value of the EAX register (BIST: Built-in Self Test)
; @param[out] ESP   Initial value of the EAX register (BIST: Built-in Self Test)
;
EarlyInit16:
    ;
    ; ESP -  Initial value of the EAX register (BIST: Built-in Self Test)
    ;
    mov     esp, eax
    debugInitialize
    OneTimeCallRet EarlyInit16
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; @file
; Transition from 16 bit real mode into 32 bit flat protected mode
%define SEC_DEFAULT_CR0  0x40000023
%define SEC_DEFAULT_CR4  0x640

BITS    16
;
; Modified:  EAX, EBX
;
TransitionFromReal16To32BitFlat:
    debugShowPostCode POSTCODE_16BIT_MODE
    cli           ; 0中斷標誌,防止有些硬件中斷對程序的干擾 
    mov     bx, 0xf000
    mov     ds, bx
    mov     bx, ADDR16_OF(gdtr)             ; %define ADDR16_OF(x) (0x10000 - fourGigabytes + x) 

;A new base address must be loaded into the GDTR as part of the processor initialization process for protected-mode operation
 
o32 lgdt    [cs:bx]                                      ; lgdt   Load global descriptor table (GDT) register 
    mov     eax, SEC_DEFAULT_CR0      ; %define SEC_DEFAULT_CR0  0x40000023
    mov     cr0, eax                                     ; enter protector mode(enable bit : CD / NE / MP  / PE)
    jmp     LINEAR_CODE_SEL:dword ADDR_OF(jumpTo32BitAndLandHere)

BITS    32
jumpTo32BitAndLandHere:
    mov     eax, SEC_DEFAULT_CR4        ; %define SEC_DEFAULT_CR4  0x640
    mov     cr4, eax                                       ; enable MCE/OSFXSR/OSXMMEXCPT bit
    debugShowPostCode POSTCODE_32BIT_MODE
    ; Now we're in Protected16
    ; Set up the selectors for protected mode entry
    mov     ax, LINEAR_SEL
    mov     ds, ax
    mov     es, ax
    mov     fs, ax
    mov     gs, ax
    mov     ss, ax
    OneTimeCallRet TransitionFromReal16To32BitFlat
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; @file
; Search for the Boot Firmware Volume (BFV) base address
BITS    32
;
; Modified:  EAX, EBX
; Preserved: EDI, ESP
;
; @param[out]  EBP  Address of Boot Firmware Volume (BFV)
;
Flat32SearchForBfvBase:
    xor     eax, eax               ; clean eax

searchingForBfvHeaderLoop:
    ;
    ; We check for a firmware volume at every 4KB address in the top 16MB
    ; just below 4GB.  (Addresses at 0xffHHH000 where H is any hex digit.)
    ;
    sub     eax, 0x1000
    cmp     eax, 0xff000000
    jb      searchedForBfvHeaderButNotFound
    ;
    ; Check FFS GUID
    ;
    cmp     dword [eax + 0x10], FFS_GUID_DWORD0
    jne     searchingForBfvHeaderLoop
    cmp     dword [eax + 0x14], FFS_GUID_DWORD1
    jne     searchingForBfvHeaderLoop
    cmp     dword [eax + 0x18], FFS_GUID_DWORD2
    jne     searchingForBfvHeaderLoop
    cmp     dword [eax + 0x1c], FFS_GUID_DWORD3
    jne     searchingForBfvHeaderLoop
    ;
    ; Check FV Length
    ;
    cmp     dword [eax + 0x24], 0
    jne     searchingForBfvHeaderLoop
    mov     ebx, eax
    add     ebx, dword [eax + 0x20]
    jnz     searchingForBfvHeaderLoop
    jmp     searchedForBfvHeaderAndItWasFound
searchedForBfvHeaderButNotFound:
    ;
    ; Hang if the SEC entry point was not found
    ;
    debugShowPostCode POSTCODE_BFV_NOT_FOUND
    ;
    ; 0xbfbfbfbf in the EAX & EBP registers helps signal what failed
    ; for debugging purposes.
    ;
    mov     eax, 0xBFBFBFBF
    mov     ebp, eax
    jmp     $
searchedForBfvHeaderAndItWasFound:
    mov     ebp, eax
    debugShowPostCode POSTCODE_BFV_FOUND
    OneTimeCallRet Flat32SearchForBfvBase
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; @file
; Search for the SEC Core entry point
BITS    32
%define EFI_FV_FILETYPE_SECURITY_CORE         0x03
;
; Modified:  EAX, EBX, ECX, EDX
; Preserved: EDI, EBP, ESP
;
; @param[in]   EBP  Address of Boot Firmware Volume (BFV)
; @param[out]  ESI  SEC Core Entry Point Address
;
Flat32SearchForSecEntryPoint:
    ;
    ; Initialize EBP and ESI to 0
    ;
    xor     ebx, ebx
    mov     esi, ebx
    ;
    ; Pass over the BFV header
    ;
    mov     eax, ebp
    mov     bx, [ebp + 0x30]
    add     eax, ebx
    jc      secEntryPointWasNotFound
    jmp     searchingForFfsFileHeaderLoop
moveForwardWhileSearchingForFfsFileHeaderLoop:
    ;
    ; Make forward progress in the search
    ;
    inc     eax
    jc      secEntryPointWasNotFound
searchingForFfsFileHeaderLoop:
    test    eax, eax
    jz      secEntryPointWasNotFound
    ;
    ; Ensure 8 byte alignment
    ;
    add     eax, 7
    jc      secEntryPointWasNotFound
    and     al, 0xf8
    ;
    ; Look to see if there is an FFS file at eax
    ;
    mov     bl, [eax + 0x17]
    test    bl, 0x20
    jz      moveForwardWhileSearchingForFfsFileHeaderLoop
    mov     ecx, [eax + 0x14]
    and     ecx, 0x00ffffff
    or      ecx, ecx
    jz      moveForwardWhileSearchingForFfsFileHeaderLoop
    add     ecx, eax
    jz      jumpSinceWeFoundTheLastFfsFile
    jc      moveForwardWhileSearchingForFfsFileHeaderLoop
jumpSinceWeFoundTheLastFfsFile:
    ;
    ; There seems to be a valid file at eax
    ;
    cmp     byte [eax + 0x12], EFI_FV_FILETYPE_SECURITY_CORE ; Check File Type
    jne     readyToTryFfsFileAtEcx
fileTypeIsSecCore:
    OneTimeCall GetEntryPointOfFfsFile
    test    eax, eax
    jnz     doneSeachingForSecEntryPoint
readyToTryFfsFileAtEcx:
    ;
    ; Try the next FFS file at ECX
    ;
    mov     eax, ecx
    jmp     searchingForFfsFileHeaderLoop
secEntryPointWasNotFound:
    xor     eax, eax
doneSeachingForSecEntryPoint:
    mov     esi, eax
    test    esi, esi
    jnz     secCoreEntryPointWasFound
secCoreEntryPointWasNotFound:
    ;
    ; Hang if the SEC entry point was not found
    ;
    debugShowPostCode POSTCODE_SEC_NOT_FOUND
    jz      $
secCoreEntryPointWasFound:
    debugShowPostCode POSTCODE_SEC_FOUND
    OneTimeCallRet Flat32SearchForSecEntryPoint
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Transition from 32 bit flat protected mode into 64 bit flat protected mode

BITS    32
;
; Modified:  EAX
;
Transition32FlatTo64Flat:
    OneTimeCall SetCr3ForPageTables64
    mov     eax, cr4
    bts     eax, 5                      ; enable PAE
    mov     cr4, eax                    
    mov     ecx, 0xc0000080
    rdmsr
    bts     eax, 8                      ; set LME
    wrmsr
    mov     eax, cr0
    bts     eax, 31                     ; set PG
    mov     cr0, eax                  ; enable paging
    jmp     LINEAR_CODE64_SEL:ADDR_OF(jumpTo64BitAndLandHere)

BITS    64
jumpTo64BitAndLandHere:
    debugShowPostCode POSTCODE_64BIT_MODE
    OneTimeCallRet Transition32FlatTo64Flat
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; @file
; Sets the CR3 register for 64-bit paging
BITS    32
;
; Modified:  EAX
;
SetCr3ForPageTables64:
    ;
    ; These pages are built into the ROM image in X64/PageTables.asm
    ;
    mov     eax, ADDR_OF(TopLevelPageDirectory)
    mov     cr3, eax
    OneTimeCallRet SetCr3ForPageTables64
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章