下面是摘自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 events
• Creating a temporary memory store
• Serving as the root of trust in the system
• Passing 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'
jmp short Main16
; file: UefiCpuPkg\ResetVector\Vtf0\Main.asm
; @file
; Main routine of the pre-SEC code up through the jump into SEC
;
BITS 16
;
; 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
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~