PEI and DXE Q&A

1,请写出开机到os分哪些阶段。

sec->pei->dxe-.bds->tsl->rt->al

2.sec 阶段主要做哪些事?

1,建立cache as ram.

在reset 之后,memory 初始化之前,bios 配置出一段区域用来读写数据,这段区域我们叫datastack.还要配置出一段只读的作为coderegion.

整个过程是这样子的:

名词解释: NEM:  no Eviction mode

evict ,就是赶出的意思, 这时候,cache 既然作为程序的代码段,数据段,也就不允许用作常规用途去缓存memory的内容的,就是它里面的内容不能去被随便更新(evict)

注意:


1.在NEM模式里面,不允许发生C-state状态的迁移。

2.NEM 里面 Prefetcher (分支预测?) 会自动关闭

3.确保所有有AP(Application processor) 处于等sipi 状态,

4.将所有的MTRR寄存器初始化为0.

5. 通过IA32_MTRR_DEF_TYPE MSR 将内存(主存) 配置成 un-cacheable.

6. 用作datastack 和codestack 的大小是有限制的。

7.通过MTRR 把coderegion 配置成write-protected 类型。

8.通过NO_EVICT_MODE(MSR 2E0h) 将cache 置成NO-Eviction mode


;-----------------------------------------------------------------------------
;
;  Section:     SecCarInit
;
;  Description: This function initializes the Cache for Data, Stack, and Code
;               as specified in the  BIOS Writer's Guide.
;
;-----------------------------------------------------------------------------
SecCarInit    PROC    NEAR    PUBLIC
  ;
  ; Detect Boot Guard Boot
  ;
DetectBootGuard:
  mov     ecx, MSR_BOOT_GUARD_SACM_INFO    ;
  rdmsr
  and     eax, 01h
  jnz     BootGuardNemSetup
SkipDetectBootGuard:

  ;
  ;  Enable cache for use as stack and for caching code
  ;  Ensure that the system is in flat 32 bit protected mode.
  ;
  ;  Ensure that only one logical processor in the system is the BSP.
  ;  (Required step for clustered systems).
  ;
  ;  Ensure all APs are in the Wait for SIPI state.
  ;  This includes all other logical processors in the same physical processor
  ;  as the BSP and all logical processors in other physical processors.
  ;  If any APs are awake, the BIOS must put them back into the Wait for
  ;  SIPI state by issuing a broadcast INIT IPI to all excluding self.
  ;
  mov     edi, APIC_ICR_LO               ; 0FEE00300h - Send INIT IPI to all excluding self
  mov     eax, ORALLBUTSELF + ORSELFINIT ; 0000C4500h - Broadcast INIT IPI
  mov     [edi], eax

@@:
  mov     eax, [edi]
  bt      eax, 12                       ; Check if send is in progress
  jc      @B                            ; Loop until idle

  ;   Ensure that all variable-range MTRR valid flags are clear and
  ;   IA32_MTRR_DEF_TYPE MSR E flag is clear.  Note: This is the default state
  ;   after hardware reset.
  ;
  ;   Initialize all fixed-range and variable-range MTRR register fields to 0.
  ;
   mov   ecx, IA32_MTRR_CAP             ; get variable MTRR support
   rdmsr
   movzx ebx, al                        ; EBX = number of variable MTRR pairs
   shl   ebx, 2                         ; *4 for Base/Mask pair and WORD size
   add   ebx, MtrrCountFixed * 2        ; EBX = size of  Fixed and Variable MTRRs

   xor   eax, eax                       ; Clear the low dword to write
   xor   edx, edx                       ; Clear the high dword to write

InitMtrrLoop:
   add   ebx, -2
   movzx ecx, WORD PTR cs:MtrrInitTable[ebx]  ; ecx <- address of mtrr to zero
   wrmsr
   jnz   InitMtrrLoop                   ; loop through the whole table

  ;
  ;   Configure the default memory type to un-cacheable (UC) in the
  ;   IA32_MTRR_DEF_TYPE MSR.
  ;
  mov     ecx, MTRR_DEF_TYPE            ; Load the MTRR default type index
  rdmsr
  and     eax, NOT (00000CFFh)          ; Clear the enable bits and def type UC.
  wrmsr

  ; Configure MTRR_PHYS_MASK_HIGH for proper addressing above 4GB
  ; based on the physical address size supported for this processor
  ; This is based on read from CPUID EAX = 080000008h, EAX bits [7:0]
  ;
  ; Examples:
  ;  MTRR_PHYS_MASK_HIGH = 00000000Fh  For 36 bit addressing
  ;  MTRR_PHYS_MASK_HIGH = 0000000FFh  For 40 bit addressing
  ;
  mov   eax, 80000008h                  ; Address sizes leaf
  cpuid
  sub   al, 32
  movzx eax, al
  xor   esi, esi
  bts   esi, eax
  dec   esi                             ; esi <- MTRR_PHYS_MASK_HIGH

  ;
  ;   Configure the DataStack region as write-back (WB) cacheable memory type
  ;   using the variable range MTRRs.
  ;
  ;
  ; Set the base address of the DataStack cache range
  ;
  mov     eax, PcdGet32 (PcdTemporaryRamBase)
  or      eax, MTRR_MEMORY_TYPE_WB
                                        ; Load the write-back cache value
  xor     edx, edx                      ; clear upper dword
  mov     ecx, MTRR_PHYS_BASE_0         ; Load the MTRR index
  wrmsr                                 ; the value in MTRR_PHYS_BASE_0

  ;
  ; Set the mask for the DataStack cache range
  ; Compute MTRR mask value:  Mask = NOT (Size - 1)
  ;
  mov  eax, PcdGet32 (PcdTemporaryRamSize)
  dec  eax
  not  eax
  or   eax, MTRR_PHYS_MASK_VALID
                                        ; turn on the Valid flag
  mov  edx, esi                         ; edx <- MTRR_PHYS_MASK_HIGH
  mov  ecx, MTRR_PHYS_MASK_0            ; For proper addressing above 4GB
  wrmsr                                 ; the value in MTRR_PHYS_BASE_0

  ;
  ;   Configure the BIOS code region as write-protected (WP) cacheable
  ;   memory type using a single variable range MTRR.
  ;
  ;   Ensure region to cache meets MTRR requirements for
  ;   size and alignment.
  ;

  ;
  ; Save MM5 into ESP before program MTRR, because program MTRR will use MM5 as the local variable.
  ; And, ESP is not initialized before CAR is enabled. So, it is safe ot use ESP here.
  ;
  movd esp, mm5

  ;
  ; Get total size of cache from PCD if it need fix value
  ;
  mov     eax, PcdGet32 (PcdNemCodeCacheSize)
  ;
  ; Calculate NEM size
  ; Determine LLC size of the code region and data region combined must not exceed the size
  ; of the (Last Level Cache - 0.5MB).
  ;
  ; Determine Cache Parameter by CPUID Function 04h
  ;
  xor     edi, edi

Find_LLC_parameter:
  mov     ecx, edi
  mov     eax, 4
  cpuid
  inc     edi
  and     al, 0E0h                       ; EAX[7:5] = Cache Level
  cmp     al, 60h                        ; Check to see if it is LLC
  jnz     Find_LLC_parameter
  ;
  ; Got L3 parameters
  ;
  ; This Cache Size in Bytes = (Ways + 1) * (Partitions + 1) * (Line_Size + 1) * (Sets + 1)
  ;  = (EBX[31:22] + 1) * (EBX[21:12] + 1) * (EBX[11:0] + 1) * (ECX + 1)
  ;
  mov     eax, ecx
  inc     eax
  mov     edi, ebx
  shr     ebx, 22
  inc     ebx
  mul     ebx
  mov     ebx, edi
  and     ebx, NOT 0FFC00FFFh
  shr     ebx, 12
  inc     ebx
  mul     ebx
  mov     ebx, edi
  and     ebx, 0FFFh
  inc     ebx
  mul     ebx
  ;
  ; Maximum NEM size <= (Last Level Cache - 0.5MB)
  ;
  sub     eax, 512*1024
Got_NEM_size:
  ;
  ; Code cache size = Total NEM size - DataStack size
  ;
  sub     eax, PcdGet32 (PcdTemporaryRamSize)
  ;
  ; Set the base address of the CodeRegion cache range from PCD
  ; PcdNemCodeCacheBase is set to the offset to flash base,
  ; so add PcdFlashAreaBaseAddress to get the real code base address.
  ;
  mov     edi, PcdGet32 (PcdNemCodeCacheBase)
  add     edi, PcdGet32 (PcdFlashAreaBaseAddress)

  ;
  ; Round up to page size
  ;
  mov     ecx, eax                      ; Save
  and     ecx, 0FFFF0000h               ; Number of pages in 64K
  and     eax, 0FFFFh                   ; Number of "less-than-page" bytes
  jz      Rounded
  mov     eax, 10000h                   ; Add the whole page size

Rounded:
  add     eax, ecx                      ; eax - rounded up code cache size

  ;
  ; Define "local" vars for this routine
  ; @todo as these registers are overlapping with others
  ; Note that mm0 is used to store BIST result for BSP,
  ; mm1 is used to store the number of processor and BSP APIC ID,
  ; mm6 is used to save time-stamp counter value.
  ;
  CODE_SIZE_TO_CACHE    TEXTEQU  <mm3>
  CODE_BASE_TO_CACHE    TEXTEQU  <mm4>
  NEXT_MTRR_INDEX       TEXTEQU  <mm5>
  NEXT_MTRR_SIZE        TEXTEQU  <mm2>
  ;
  ; Initialize "locals"
  ;
  sub     ecx, ecx
  movd    NEXT_MTRR_INDEX, ecx          ; Count from 0 but start from MTRR_PHYS_BASE_1

  ;
  ; Save remaining size to cache
  ;
  movd    CODE_SIZE_TO_CACHE, eax       ; Size of code cache region that must be cached
  mov     edi, 0xFFFFFFFF
  sub     edi, eax
  inc     edi
  test    edi, 0xFFFF
  jz      @f
  add     edi, 0x10000
  and     edi, 0xFFFF0000
@@:
  movd    CODE_BASE_TO_CACHE, edi       ; Base code cache address

NextMtrr:
  ;
  ; Get remaining size to cache
  ;
  movd    eax, CODE_SIZE_TO_CACHE
  and     eax, eax
  jz      CodeRegionMtrrdone            ; If no left size - we are done
  ;
  ; Determine next size to cache.
  ; We start from bottom up. Use the following algorythm:
  ; 1. Get our own alignment. Max size we can cache equals to our alignment
  ; 2. Determine what is bigger - alignment or remaining size to cache.
  ;    If aligment is bigger - cache it.
  ;      Adjust remaing size to cache and base address
  ;      Loop to 1.
  ;    If remaining size to cache is bigger
  ;      Determine the biggest 2^N part of it and cache it.
  ;      Adjust remaing size to cache and base address
  ;      Loop to 1.
  ; 3. End when there is no left size to cache or no left MTRRs
  ;
  movd    edi, CODE_BASE_TO_CACHE
  bsf     ecx, edi                      ; Get index of lowest bit set in base address
  ;
  ; Convert index into size to be cached by next MTRR
  ;
  mov     edx, 1h
  shl     edx, cl                       ; Alignment is in edx
  cmp     edx, eax                      ; What is bigger, alignment or remaining size?
  jbe     gotSize                       ; JIf aligment is less
  ;
  ; Remaining size is bigger. Get the biggest part of it, 2^N in size
  ;
  bsr     ecx, eax                      ; Get index of highest set bit
  ;
  ; Convert index into size to be cached by next MTRR
  ;
  mov     edx, 1
  shl     edx, cl                       ; Size to cache

GotSize:
  mov     eax, edx
  movd    NEXT_MTRR_SIZE, eax           ; Save

  ;
  ; Compute MTRR mask value:  Mask = NOT (Size - 1)
  ;
  dec     eax                           ; eax - size to cache less one byte
  not     eax                           ; eax contains low 32 bits of mask
  or      eax, MTRR_PHYS_MASK_VALID     ; Set valid bit

  ;
  ; Program mask register
  ;
  mov     ecx, MTRR_PHYS_MASK_1         ; setup variable mtrr
  movd    ebx, NEXT_MTRR_INDEX
  add     ecx, ebx

  mov     edx, esi                      ; edx <- MTRR_PHYS_MASK_HIGH
  wrmsr
  ;
  ; Program base register
  ;
  sub     edx, edx
  mov     ecx, MTRR_PHYS_BASE_1         ; setup variable mtrr
  add     ecx, ebx                      ; ebx is still NEXT_MTRR_INDEX

  movd    eax, CODE_BASE_TO_CACHE
  or      eax, MTRR_MEMORY_TYPE_WP      ; set type to write protect
  wrmsr
  ;
  ; Advance and loop
  ; Reduce remaining size to cache
  ;
  movd    ebx, CODE_SIZE_TO_CACHE
  movd    eax, NEXT_MTRR_SIZE
  sub     ebx, eax
  movd    CODE_SIZE_TO_CACHE, ebx

  ;
  ; Increment MTRR index
  ;
  movd    ebx, NEXT_MTRR_INDEX
  add     ebx, 2
  movd    NEXT_MTRR_INDEX, ebx
  ;
  ; Increment base address to cache
  ;
  movd    ebx, CODE_BASE_TO_CACHE
  movd    eax, NEXT_MTRR_SIZE
  add     ebx, eax
  ;
  ; if carry happens, means NEM base + size over 4G
  ;
  jc      CodeRegionMtrrdone
  movd    CODE_BASE_TO_CACHE, ebx

  jmp     NextMtrr

CodeRegionMtrrdone:
  ;
  ; Program the variable MTRR's MASK register for WDB
  ; (Write Data Buffer, used in MRC, must be WC type)
  ;
  mov     ecx, MTRR_PHYS_MASK_1
  movd    ebx, NEXT_MTRR_INDEX
  add     ecx, ebx
  mov     edx, esi                                          ; edx <- MTRR_PHYS_MASK_HIGH
  mov     eax, WDB_REGION_SIZE_MASK OR MTRR_PHYS_MASK_VALID ; turn on the Valid flag
  wrmsr

  ;
  ; Program the variable MTRR's BASE register for WDB
  ;
  dec     ecx
  xor     edx, edx
  mov     eax, WDB_REGION_BASE_ADDRESS OR MTRR_MEMORY_TYPE_WC
  wrmsr

  ;
  ; Enable the MTRRs by setting the IA32_MTRR_DEF_TYPE MSR E flag.
  ;
  mov     ecx, MTRR_DEF_TYPE            ; Load the MTRR default type index
  rdmsr
  or      eax, MTRR_DEF_TYPE_E          ; Enable variable range MTRRs
  wrmsr

  ;
  ; Enable the logical processor's (BSP) cache: execute INVD and set
  ; CR0.CD = 0, CR0.NW = 0.
  ;
  mov     eax, cr0
  and     eax, NOT (CR0_CACHE_DISABLE + CR0_NO_WRITE)
  invd
  mov     cr0, eax
  ;
  ; Enable No-Eviction Mode Setup State by setting
  ; NO_EVICT_MODE  MSR 2E0h bit [0] = '1'.
  ;
  mov     ecx, NO_EVICT_MODE
  rdmsr
  or      eax, 1
  wrmsr

  ;
  ; Restore MM5 from ESP after program MTRR
  ;
  movd mm5, esp

  ;
  ; Restore MM4 which is Patch Pointer.
  ; Current implementation it's the same with the PcdNemCodeCacheBase + PcdFlashAreaBaseAddress
  ;
  mov     edi, PcdGet32 (PcdNemCodeCacheBase)
  add     edi, PcdGet32 (PcdFlashAreaBaseAddress)
  movd    mm4, edi

  ;
  ; One location in each 64-byte cache line of the DataStack region
  ; must be written to set all cache values to the modified state.
  ;
  mov     edi, PcdGet32 (PcdTemporaryRamBase)
  mov     ecx, PcdGet32 (PcdTemporaryRamSize)
  shr     ecx, 6
  mov     eax, CACHE_INIT_VALUE
@@:
  mov  [edi], eax
  sfence
  add  edi, 64
  loopd  @b

  ;
  ; Enable No-Eviction Mode Run State by setting
  ; NO_EVICT_MODE MSR 2E0h bit [1] = '1'.
  ;
  mov     ecx, NO_EVICT_MODE
  rdmsr
  or      eax, 2
  wrmsr

  jmp     FinishedCacheConfig

  ;
  ; Jump to here when Boot Guard boot and NEM is initialized by Boot Guard ACM
  ;
BootGuardNemSetup:
  ;
  ; Finished with cache configuration
  ;
  ; Configure MTRR_PHYS_MASK_HIGH for proper addressing above 4GB
  ; based on the physical address size supported for this processor
  ; This is based on read from CPUID EAX = 080000008h, EAX bits [7:0]
  ;
  ; Examples:
  ;  MTRR_PHYS_MASK_HIGH = 00000000Fh  For 36 bit addressing
  ;  MTRR_PHYS_MASK_HIGH = 0000000FFh  For 40 bit addressing
  ;
  mov   eax, 80000008h                  ; Address sizes leaf
  cpuid
  sub   al, 32
  movzx eax, al
  xor   esi, esi
  bts   esi, eax
  dec   esi                             ; esi <- MTRR_PHYS_MASK_HIGH

  ;
  ; Configure the DataStack region as write-back (WB) cacheable memory type
  ; using the variable range MTRRs.
  ;
  ;
  ; Find available MTRR
  ;
  CALL_EBP     FindFreeMtrr

  ;
  ; Set the base address of the DataStack cache range
  ;
  mov     eax, PcdGet32 (PcdTemporaryRamBase)
  or      eax, MTRR_MEMORY_TYPE_WB
                                        ; Load the write-back cache value
  xor     edx, edx                      ; clear upper dword
  wrmsr                                 ; the value in MTRR_PHYS_BASE_0

  ;
  ; Set the mask for the DataStack cache range
  ; Compute MTRR mask value:  Mask = NOT (Size - 1)
  ;
  mov  eax, PcdGet32 (PcdTemporaryRamSize)
  dec  eax
  not  eax
  or   eax, MTRR_PHYS_MASK_VALID
                                        ; turn on the Valid flag
  mov  edx, esi                         ; edx <- MTRR_PHYS_MASK_HIGH
  inc  ecx
  wrmsr                                 ; the value in MTRR_PHYS_BASE_0

  ;
  ; Program the variable MTRR's MASK register for WDB
  ; (Write Data Buffer, used in MRC, must be WC type)
  ;

  ;
  ; Find available MTRR
  ;
  CALL_EBP     FindFreeMtrr

FoundAvailableMtrr:
  ;
  ; Program the variable MTRR's BASE register for WDB
  ;
  xor     edx, edx
  mov     eax, WDB_REGION_BASE_ADDRESS OR MTRR_MEMORY_TYPE_WC
  wrmsr

  inc     ecx
  mov     edx, esi                                          ; edx <- MTRR_PHYS_MASK_HIGH
  mov     eax, WDB_REGION_SIZE_MASK OR MTRR_PHYS_MASK_VALID ; turn on the Valid flag
  wrmsr

  ;
  ; One location in each 64-byte cache line of the DataStack region
  ; must be written to set all cache values to the modified state.
  ;
  mov     edi, PcdGet32 (PcdTemporaryRamBase)
  mov     ecx, PcdGet32 (PcdTemporaryRamSize)
  shr     ecx, 6
  mov     eax, CACHE_INIT_VALUE
@@:
  mov  [edi], eax
  sfence
  add  edi, 64
  loopd  @b

  ;
  ; Finished with cache configuration
  ;
FinishedCacheConfig:

  ;
  ; Optionally Test the Region
  ;

  ;
  ; Test area by writing and reading
  ;
  cld
  mov     edi, PcdGet32 (PcdTemporaryRamBase)
  mov     ecx, PcdGet32 (PcdTemporaryRamSize)
  shr     ecx, 2
  mov     eax, CACHE_TEST_VALUE
TestDataStackArea:
  stosd
  cmp     eax, DWORD PTR [edi-4]
  jnz     DataStackTestFail
  loop    TestDataStackArea
  jmp     DataStackTestPass

  ;
  ; Cache test failed
  ;
DataStackTestFail:
  STATUS_CODE (0D0h)
  jmp     $

  ;
  ; Configuration test failed
  ;
ConfigurationTestFailed:
  STATUS_CODE (0D1h)
  jmp     $

DataStackTestPass:

  ;
  ; At this point you may continue normal execution.  Typically this would include
  ; reserving stack, initializing the stack pointer, etc.
  ;

  ;
  ; Temporary Set stack top pointer for C code usage.
  ;
  mov     esp, PcdGet32 (PcdTemporaryRamBase)
  add     esp, PcdGet32 (PcdTemporaryRamSize)
  ;
  ; program resource decoding
  ;
  pushad
  call    EarlyCycleDecoding
  popad
  pushad
  call    SerialIoUartConfiguration
  popad

  ;
  ; After memory initialization is complete, please follow the algorithm in the BIOS
  ; Writer's Guide to properly transition to a normal system configuration.
  ; The algorithm covers the required sequence to properly exit this mode.
  ;
  xor    eax, eax

SecCarInitExit:

  RET_ESI

SecCarInit    ENDP

2. 跳到保护模式

3. 找到pei core, 并验证其是否正确

4.再找到BFV把控制权交给pei.

 

3. sec 是什么语言写的?  汇编语言

4. 什么是Boot firmware volume?

第一个被执行的firmware volume,遵循 efi file system.包含pei core和peim,在开机时sec会到固定位置找到bfv.

 

5. pei 最主要做哪些事?

(1)detecting and recovery 坏掉的FV

(2)初始化系统内存

(3)把控制权交给dxe

 

6. pei 有哪些元件,分别做什么的?

(1) pei core: 可以视为pei的核心,用来dispatch peim 和提供基本的service.

(2)pei module: 被pei core所dispatch来做各种任务和初始化。功能有对processor, chipset,device做基本的初始和其他特定的功能。

(3)ppi: peim和peim之间沟通的介面

(4)pei dispatcher 为pei core 的一部分,用来搜寻和执行peim.

(5)pei service: 功能由pei core所提供给peim使用。

 

7. pei service 有哪些? 各service 功能 ?

(1)ppi service

(2)boot mode service

(3)hob service

(4)firmware volume service

(5)memory service

(6)status code service


7.1.1ppi service :: installppi 具体分析

 181-187: PeiInstallPpi() 定义, 安装输入的PPI服务列表到PeiCore数据库里面,并触发满足条件的call back 函数。输入参数是PeiService

指针及安装的PPI列表,返回值是标识是否安装成功的状态值。


193-195: 对输入的参数进行检查,如果输入的PPI列表为空,则是非法输入值,返回不合法的状态。


197-200: 通过PeiService指针,获得PeiCore的内部数据结构,从从进一步获得内部维护的PPI数据库。


214-216:当内部维护的PPI数据库已经被填满,则无法继续存储更多的PPI, 此时返回资源不够的状态值。


217-226:检查传进来的参数到底是不是一个合法的PPI,如果不是,打印出有问题的部分。

229-230:记录PPI到内部维护的PPI数据库,并输出调式信息。


232 - 238: 检查当前的PPI是不是输入列表中的最后一个PPI,如果是的话,则退出循环。

239-240:跳到下一个PPI,再继续安装。


243-253:当有新的PPI安装以后,调用派遣通知函数,触发满足条件的callback函数。

256: 如果PPI列表里面的所有的 PPI都成功安装了,返回成功标识的状态值。


7.1.2 :: PeiNotifyPpi 具体实现:

420-423 : PeiNotifyPpi() 定义,安装PPI的回调函数列表到PPI数据库,并触发满足条件的回调函数。输入参数分别PeiService指针及回调函数列表,

返回值是标识是否安装成功的状态值。

435-437:对输入参数的检查,如果输入的PPI回调函数列表为空,则是不合法的输入值,返回不合法的状态。


439: 通过PeiService指针,获得PeiCore的内部数据结构,从而进一步的获得内部维护的PPI及回调函数的数据库。

450: 遍历输入的PPI回调函数列表,安装它们到内部维护的PPI回调函数数据库。

451-458: 当内部维护的PPI回调函数数据库已经被填满,则无法继续存储更多的PPI回调函数,此时返回资源不够的状态值。

460-467:如果需要安装的PPI回调函数没有标识自己是回调类型的PPI,则是不合法的PPI回调函数,它无法被安装,打印出有问题的部分。

469-471: 记录派遣类型的PPI回调函数的个数,以便在安装完成后立即对回调类型的PPI进行派遣,即核查它们是否满足回调条件,一旦满足,则它们

立即触发。

484-485: 跳到下一个PPI回调函数,再继续安装。

8. pei 的code在哪里执行?

cache as ram

 

9 pei dispatch 四大rule

:peim 未被dispatch, peim 为正确的格式,peim为可信赖的,peim的dependency条件符合。

9.1 PeiDispatcher的具体实现:


 640: 传进来两个指向结构体的指针,这两个结构体具体为:


10,什么时dependency? dependency关系记录在哪里?如何表示?

一个peim 在执行时,有可能会用到其他peim的功能。所以要等其他peim先执行后,并install ppi至 ppi database中,

该peim才能使用,该ppi也才能继续执行下去。dependency 关系放在在fv的一个特殊的section中,一个peim有可能会

需要很多其他peim先执行才能执行,所以表示方法用boolean运算符 and, or, 和sequencing .

 

11. 如何dispatch other fv?

不一定所有的peim都在bfv中,有可能在其他的fv,所以要用dispatch other fv的机制。此时需要一个特别的peim来告诉

pei core 说其他fv还有peim要dispatch, 所以当pei core dispatch 到这个peim时,会把其他peim的dispatch顺序加到

pei core 的搜寻algorithm中。

 

12. 什么是notification

假设一个peim有十个function,在执行完九个后,最后一个function 需要其他peim的功能,但该peim尚未被dispatch,

此时可能用notify的功能告诉pei core,需要ppi才能执行,然后就继续dispatch其他peim,当有ppi被install,就会和notify

的ppi guid做比较,如果是notify的ppi就跳回到下notify的peim去把剩下的function执行完,提供了一个call back 的机制。

 

13. 什么是 PPI?

peim 和peim 的沟通介面,当peim需要提供功能给其他peim使用时,需要先install 一个PPI至ppi database中,其他的

peim 就可以通过pei core 来使用该ppi,ppi 的栏们为guid和interface.guid是128位的数据,它是唯一性的,即使不同的

在同一时间建立也不会相同,Interface是一个function pointer, 用来指向ppi 所提供的function.

应该说interface 指向一堆数据,可以是一个函数指针,也可以是多个。

///
/// The data structure through which a PEIM describes available services to the PEI Foundation.
/// 
typedef struct {
  ///
  /// This field is a set of flags describing the characteristics of this imported table entry.
  /// All flags are defined as EFI_PEI_PPI_DESCRIPTOR_***, which can also be combined into one.
  ///
  UINTN     Flags;
  ///
  /// The address of the EFI_GUID that names the interface.
  ///
  EFI_GUID  *Guid;
  ///
  /// A pointer to the PPI. It contains the information necessary to install a service.
  ///
  VOID      *Ppi;
} EFI_PEI_PPI_DESCRIPTOR;

ppi 是长这个样子的

struct _EFI_PEI_S3_RESUME2_PPI {
  ///
  /// Restores the platform to its preboot configuration for an S3 resume and
  /// jumps to the OS waking vector.
  ///
  EFI_PEI_S3_RESUME_PPI_RESTORE_CONFIG2  S3RestoreConfig2;
};


 

14. 什么是hob?

由pei 阶段传送给dxe的信息只能通过hob来传送,所以他包含dxe所需的所有信息,如phit, physical memory,firmware

volume ,dxe core, dxe stack/bsp, guid hob, 它是linking list的数据结构,标头为phit,其中包含了boot mode的信息,

尾巴是termination.如果搜寻hob时找到termination表示没有些hob,guid hob 是由chipset vendor 提供的信息,

有自己的格式,不想被其他人所使用,是属于private information.

 关于hob 的一些具体函数 解析:

PeiCreateHob 创建hob,并返回hob的地址


070-077:PeiCreateHob() 定义, 创建请求类型的HOB数据块,并返回HOB数据块的地址。输入 参数分别是PeiService指针、HOB类型及长度、用于存储创建的HOB地址的

指针,返回值是标识是否成功创建的状态值。

085-088: 获得HOB列表的起始地址。

090:HOB列表的起始是HandOffHob 数据块,存储当前的系统信息。

92-94: 调整新创建HOB长度为8字节对齐,并计算当前可用的HOB数据块的空间。


103-107: 如果可用的空间不足够创建请求的HOB时,则打印出调试信息说明当前系统资源不足够满足系统运行,并返回系统资源不够的状态值。

110-113: 当空间足够时,追加新的HOB在当前HOB列表的最末端,并记录HOB数据块的地址。

121-123:更新可用空间的末端地址,因为新的HOB占用了一部分空间。

124:返回成功的状态值。


15, Recovery 的步骤

(1)由platform policy来决定是否要reset  platform.

(2)不管platform有没有reset,core dispatch都会做reset,然后重新dispatch,只dispatch有标为recovery的peim.

(3)读取boot mode 来决定要dispatch哪些peim.

 

 






  • 9
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
[说明] DiSQLiteApi.dcu 文件根据实际开发环境在包内进行选择 本版本的 ASqlite 是基于 livu999 大侠的修改版继续魔改 原帖地址:http://download.csdn.net/download/ilvu999/6369053 本版本只支持 D2009 以上的 Unicode 版本的 Delphi 原作者在主要单元文件已经说明清楚了,老版本 Delphi 请绕道 为了照顾 XE2 下使用的朋友,故最后做了兼容 再照顾一下 DBGrid,令其不再显示 (MEMO) 另外做了兼容,在 XE8 开发环境及 64 位平台下通过基本测试            katar1024 (网名:阿龙) 2017-08-22 大改支持 TWideMemo,在此解决乱码问题 修正启用 SQLiteDateFormat 的情况下读取非正规日期字符串引起异常的 bug 查询语句中表名和字段名用中括号 [] 引括,可以使用 Index 之,等保留字段名 删除属性 CharacterEncode,一律按默认的 Uft-8 格式存取字符串 删除属性 DriverDll,已经启用 SQLite 静态库方式编译并链接,不需携带 dll 使用 DISQlite 的静态库编译,版本 3.8.3,兼容性和稳定性均良好 2017-08-23 插入和更新操作只针对已修改的字段进行处理和提交,提高执行效率 插入记录后,同步读取库中的数字和日期默认值,对取值自动分配 id 有意义 所有调试记录代码全部加了条件编译块控制,减小体积,提高调度效率 优化类型数据存取分支代码,减少体积,提高读写效率 去除初次读取数据 100 字节大小缓冲区的限制,防止字符串乱码 其它性能优化 其它 bug 修复 2017-08-24 修正设计器属性框中 Active 属性设置为 True,但运行时未打开查询的 bug ftString、ftWideString、ftMemo、ftWideMemo 等字符串字段通过乱码测试 Memo 字段添加显示功能,控件不再显示(MEMO)或(WIDEMEMO) Memo 字段支持 AsInteger、AsDataTime 等数据功能(设计器预定义的字段无效) 2017-08-25 修改关键属性时自动关闭数据连接 TransactionType、TempStore, DefaultSynchronous 等属性从字符串值修改为枚举值 修正 TypeLess 功能 添加 TASQLiteBaseQuery 一些关键属性在设计器中改变后自动关闭查询的功能 修正 Filtered 属性在设计器中改变后,但结果没变的 bug PS: 本来想弄个批处理提交功能的(BatchedUpdates 或 CachedUpdates), 在某些场合很实用,但最近改的问题太多了,改得好累,等下次真正用到了再补上 对 SQLite 的初恋蛮深的,但不得不吐槽,想说爱它真的很不容易
[说明] DiSQLiteApi.dcu 文件根据实际开发环境在包内进行选择 本版本的 ASqlite 是基于 livu999 大侠的修改版继续魔改 原帖地址:http://download.csdn.net/download/ilvu999/6369053 本版本只支持 D2009 以上的 Unicode 版本的 Delphi 原作者在主要单元文件已经说明清楚了,老版本 Delphi 请绕道 为了照顾 XE2 下使用的朋友,故最后做了兼容 再照顾一下 DBGrid,令其不再显示 (MEMO) 另外做了兼容,在 XE8 开发环境及 64 位平台下通过基本测试            katar1024 (网名:阿龙) 2017-08-22 大改支持 TWideMemo,在此解决乱码问题 修正启用 SQLiteDateFormat 的情况下读取非正规日期字符串引起异常的 bug 查询语句中表名和字段名用中括号 [] 引括,可以使用 Index 之,等保留字段名 删除属性 CharacterEncode,一律按默认的 Uft-8 格式存取字符串 删除属性 DriverDll,已经启用 SQLite 静态库方式编译并链接,不需携带 dll 使用 DISQlite 的静态库编译,版本 3.8.3,兼容性和稳定性均良好 2017-08-23 插入和更新操作只针对已修改的字段进行处理和提交,提高执行效率 插入记录后,同步读取库中的数字和日期默认值,对取值自动分配 id 有意义 所有调试记录代码全部加了条件编译块控制,减小体积,提高调度效率 优化类型数据存取分支代码,减少体积,提高读写效率 去除初次读取数据 100 字节大小缓冲区的限制,防止字符串乱码 其它性能优化 其它 bug 修复 2017-08-24 修正设计器属性框中 Active 属性设置为 True,但运行时未打开查询的 bug ftString、ftWideString、ftMemo、ftWideMemo 等字符串字段通过乱码测试 Memo 字段添加显示功能,控件不再显示(MEMO)或(WIDEMEMO) Memo 字段支持 AsInteger、AsDataTime 等数据功能(设计器预定义的字段无效) 2017-08-25 修改关键属性时自动关闭数据连接 TransactionType、TempStore, DefaultSynchronous 等属性从字符串值修改为枚举值 修正 TypeLess 功能 添加 TASQLiteBaseQuery 一些关键属性在设计器中改变后自动关闭查询的功能 修正 Filtered 属性在设计器中改变后,但结果没变的 bug PS: 本来想弄个批处理提交功能的(BatchedUpdates 或 CachedUpdates), 在某些场合很实用,但最近改的问题太多了,改得好累,等下次真正用到了再补上 对 SQLite 的初恋蛮深的,但不得不吐槽,想说爱它真的很不容易

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值