青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

string

string
posts - 27, comments - 177, trackbacks - 0, articles - 0
  C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

深入U(xiǎn)EFI內(nèi)核

前面通過《UEFI原理與編程》一書介紹了如何使用UEFI編寫應(yīng)用程序和驅(qū)動(dòng),編程一書是從上層應(yīng)用和驅(qū)動(dòng)開發(fā)者的角度認(rèn)識(shí)UEFI的,UEFI就像一個(gè)黑盒子,書中詳細(xì)介紹了這個(gè)黑盒子的表面(即UEFI提供給上層開發(fā)者的接口和服務(wù))。接口通過Protocol呈現(xiàn)給開發(fā)者。主要的Protocol包括控制臺(tái)輸入輸出Protocol;文件及硬盤Protocol;操作外部設(shè)備的Protocol(PciIo等);驅(qū)動(dòng)框架Protocol;人機(jī)交互接口Protocol;網(wǎng)絡(luò)Protocol。服務(wù)通過啟動(dòng)服務(wù)和運(yùn)行時(shí)服務(wù)提供,主要包括Protocol服務(wù),內(nèi)存管理服務(wù),事件管理服務(wù)等。UEFI雖然龐大,但它通過模塊化被很清晰的組織在一起,當(dāng)逐步掌握了這些主要的Protocol和服務(wù)之后,UEFI也就變得簡單起來,那么是時(shí)候深入到這個(gè)盒子內(nèi)部,了解UEFI內(nèi)核的運(yùn)行機(jī)制了。 
下面將以系統(tǒng)啟動(dòng)過程為主線介紹UEFI內(nèi)核。

第一條指令(ResetVector)

先說結(jié)論:X86 CPU啟動(dòng)后,將從地址0xFFFFFFF0處開始執(zhí)行(此地址并非內(nèi)存地址。此時(shí),內(nèi)存還遠(yuǎn)遠(yuǎn)沒有初始化。)。這一章來看X86系統(tǒng)是如何實(shí)現(xiàn)這一點(diǎn)的。 
加電或者RESET針腳被激發(fā)(Assert)后[ref intel] CPU會(huì)經(jīng)歷如下幾個(gè)過程: 
1. CPU首先會(huì)進(jìn)行硬件初始化(hardware reset)。 
2. 然后是可選的自檢過程(BIST built-in self-test)。 
3. CPU開始執(zhí)行第一條指令。從此開始CPU進(jìn)入軟件初始化過程。

1.CPU硬件初始化

CPU硬件初始化完成后,CPU被設(shè)置為實(shí)地址模式,地址無分頁。所有寄存器被初始化為特定的值, Cache、TLB(Translation Lookup Table)、BLB(Branch Target Buffer)這三個(gè)部件的內(nèi)容被清空(Invalidate)。

2.自檢

CPU硬件初始化過程中,硬件可能請(qǐng)求執(zhí)行自檢。如果執(zhí)行自檢,自檢完成后,EAX的值為自檢錯(cuò)誤碼,0表示沒有任何錯(cuò)誤;

3.第一條指令

現(xiàn)在,完事俱備,CPU已經(jīng)準(zhǔn)備好,迫不及待地要執(zhí)行第一條指令了。且慢,這是一個(gè)重要的時(shí)刻,此刻決定了CPU能否正常指令,讓我們?cè)敿?xì)了解一下CPU目前的狀態(tài)。 
表1-1 CPU初始化后的寄存器(部分)

RegisterPentium 4 and Intel Xeon ProcessorP6 Family Processor Including DisplayFamily = 06H)Pentium Processor
EFLAGS100000002H00000002H00000002H
EIP0000FFF0H0000FFF0H0000FFF0H
CR060000010H60000010H60000010H
CR2, CR3, CR400000000H00000000H00000000H
CSSelector = F000H 
Base = FFFF0000H 
Limit = FFFFH 
AR = Present, R/W, Accessed
Selector = F000H
Base = FFF0000H
Limit = FFFFH
AR = Present, R/W, Accessed
Selector = F000H
Base = FFFF0000H
Limit = FFFFH
AR = Present, R/W, Accessed
SS, DS, ES, FS, GSSelector = 0000H
Base = 00000000H
Limit = FFFFH
AR = Present, R/W, Accessed
Selector = 0000H
Base = 00000000H 
Limit = FFFFH
AR = Present, R/W, Accessed
Selector = 0000H
Base = 00000000H
Limit = FFFFH
AR = Present, R/W, Accessed
EDX00000FxxH000n06xxH000005xxH
EAX000
EBX, ECX, ESI, EDI, EBP,ESP00000000H00000000H00000000H

此處我們最關(guān)心的是指令執(zhí)行相關(guān)的兩個(gè)寄存器EIP(Instruction Pointer)、CS(Code Segment)。 
在實(shí)地址模式下(寄存器字長為16位),指令的物理地址是CS << 4 + EIP。段寄存器CS左移四位作為基址,再加上作為偏移的EIP,最終形成指令的物理地址。現(xiàn)代CPU中為了加速指令地址的計(jì)算,為每個(gè)段寄存器增加了兩個(gè)寄存器:Base和Limit。Base存放基址,Limit存放最大偏移值。Base和Limit寄存器不能通過指令直接讀寫,他們的值是在寫段寄存器時(shí)由CPU自動(dòng)設(shè)置的。通常Base等于段寄存器左移四位,如果CS的值為0xF000,CS的Base寄存器則為0xF0000,但CPU初始化時(shí)例外。從表1-1可以看出CS的值為0xF000, 但其Base為0xFFFF0000,EIP為0xFFF0,此時(shí)對(duì)應(yīng)的指令地址為0xFFFF0000+0xFFF0 = 0xFFFFFFF0。0xFFFFFFF0就是CPU將要執(zhí)行的第一條指令。這造成這樣一個(gè)有趣的事實(shí),16位程序眼中的指令地址空間0x0000~0xFFFF(大小為64K)被CPU翻譯到物理地址空間(0xFFFF0000~0xFFFFFFFF)。也就是說,從CPU初始化,到段寄存器被重寫(通過跨段跳轉(zhuǎn)指令)前,指令空間0x0000~0xFFFF通過段寄存器被映射到物理地址空間0xFFFF0000~0xFFFFFFFF。 
前面講到第一條指令地址為0xFFFFFFF0,X86系統(tǒng)初始化時(shí)會(huì)將ROM中的固件映射的(0xFFFFFFFF-固件大小)~0xFFFFFFFF的地址空間。故而0xFFFFFFF0對(duì)應(yīng)ROM中的某條指令,無論ROM中存放的是傳統(tǒng)的BIOS固件,還是存放的UEFI固件,這個(gè)規(guī)則都是一樣的。下面將從這天指令開始繼續(xù)CPU初始化之旅。 
開始講0xFFFFFFF0對(duì)應(yīng)的指令之前,還要熟悉UEFI ROM的的結(jié)構(gòu)。 
ROM固件(Flash Device binary image)由一個(gè)或多個(gè)Firmware volume(FV)構(gòu)成,每個(gè)FV里存放了FFS Image(EFI Firmware File system),F(xiàn)FS Image則由多個(gè)EFI Section構(gòu)成,EFI Section包含了PE32/PE32+/Coff Image文件。 
欲熟悉UEFI ROM的結(jié)構(gòu),先來看.fdf文件的格式。.fdf(Flash Description File)用于生成固件鏡像,它由[Defines]、[FD]、[FV]等幾個(gè)部分組成。

[Defines]

在[Defines]部分可以通過DEFINE定義本文件將要用到的宏,通過SET定義PCD的值。例如OvmfPkg的OvmfPkgX64.fdf文件的[Defines]為

  1. [Defines]
  2. !if $(TARGET) == RELEASE
  3. !ifndef $(FD_SIZE_2MB)
  4. DEFINE FD_SIZE_1MB=
  5. !endif
  6. !endif
  7. !include OvmfPkg.fdf.inc

!ifdef, !ifndef, !if, !elseif, !else and !endif 用于編寫條件語句。$(TARGET)是EDK預(yù)定義的宏,其值為build命令-b選項(xiàng)的值。可以看出,編譯Release版本時(shí),通過DEFINE定義了FD_SIZE_1MB宏。 
然后通過!include包含了OvmfPkg.fdf.inc文件,OvmfPkg.fdf.inc內(nèi)容如下

  1. DEFINE BLOCK_SIZE = 0x1000
  2. DEFINE VARS_SIZE = 0x20000
  3. DEFINE VARS_BLOCKS = 0x20
  4. !ifdef $(FD_SIZE_1MB)
  5. DEFINE FW_BASE_ADDRESS = 0xFFF00000
  6. DEFINE FW_SIZE = 0x00100000
  7. DEFINE FW_BLOCKS = 0x100
  8. DEFINE CODE_BASE_ADDRESS = 0xFFF20000
  9. DEFINE CODE_SIZE = 0x000E0000
  10. DEFINE CODE_BLOCKS = 0xE0
  11. DEFINE FVMAIN_SIZE = 0x000CC000
  12. DEFINE SECFV_OFFSET = 0x000EC000
  13. DEFINE SECFV_SIZE = 0x14000
  14. !else
  15. DEFINE FW_BASE_ADDRESS = 0xFFE00000
  16. DEFINE FW_SIZE = 0x00200000
  17. DEFINE FW_BLOCKS = 0x200
  18. DEFINE CODE_BASE_ADDRESS = 0xFFE20000
  19. DEFINE CODE_SIZE = 0x001E0000
  20. DEFINE CODE_BLOCKS = 0x1E0
  21. DEFINE FVMAIN_SIZE = 0x001AC000
  22. DEFINE SECFV_OFFSET = 0x001CC000
  23. DEFINE SECFV_SIZE = 0x34000
  24. !endif
  25. SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFdBaseAddress = $(FW_BASE_ADDRESS)
  26. SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareFdSize = $(FW_SIZE)
  27. SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareBlockSize = $(BLOCK_SIZE)
  28. SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageVariableBase = $(FW_BASE_ADDRESS)
  29. SET gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize = 0xE000
  30. SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogBase = gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageVariableBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
  31. SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogSize = $(BLOCK_SIZE)
  32. SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageFtwWorkingBase = gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogBase + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogSize
  33. SET gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize = $(BLOCK_SIZE)
  34. SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageFtwSpareBase = gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageFtwWorkingBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
  35. SET gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize = 0x1000

通過OvmfPkg.fdf.inc可以看出,編譯RELEASE版本的OVMF時(shí), FW_BASE_ADDRESS(固件基址)被定義為0xFFF00000, FW_SIZE被定義為0x00100000(1 M)。

[FD]

每個(gè)[FD]定義一個(gè)flash device image。flash device image可以是一個(gè)移動(dòng)介質(zhì)的可啟動(dòng)Image,或者系統(tǒng)ROM Image,也可以是用于更新系統(tǒng)ROM的Update("Capsule") Image。 
每個(gè).inf文件可以有多個(gè)[FD],每個(gè)[FD]生成一個(gè).fd鏡像文件。例如OvmfPkgX64.fdf文件定義了[FD.OVMF]、[FD.OVMF_VARS]、[FD.OVMF_CODE]、[FD.MEMFD],編譯后會(huì)生成OVMF.FD、OVMF_VARS.FD、OVMF_CODE.FD、MEMFD.FD四個(gè)鏡像文件。

TOKEN

[FD]塊以TOKEN語句開始,用于定義本FD的基本屬性,每一行定義一個(gè)Token,基本語法如下:

  1. Token = VALUE [| PcdName]

有效的Token包括以下5個(gè)

Token用途
BaseAddressFLASH Device的基址
SizeFLASH Device的大小
ErasePolarity
BlockSize
NumBlocks默認(rèn)值為1

BlockSize可以出現(xiàn)多次,ni=0BlockSizeiNumBlocksi必須等于Size。 
例如Nt32PKG.fdf文件中

  1. [FD.Nt32]
  2. BaseAddress = 0x0|gEfiNt32PkgTokenSpaceGuid.PcdWinNtFdBaseAddress
  3. Size = 0x002a0000
  4. ErasePolarity = 1
  5. BlockSize = 0x10000
  6. NumBlocks = 0x2a

NT32PKG生成的NT32.fd基址為0,在程序中可以通過PCD的gEfiNt32PkgTokenSpaceGuid.PcdWinNtFdBaseAddress訪問這個(gè)值。大小為0x002a0000 = 0x10000 * 0x2a。 
再如下例,Size(0x102000) = 0x10000 * 16 + 0x1000 * 2

  1. [FD.FdMain]
  2. BaseAddress = 0xFFF00000 | \
  3. gEfiMyPlatformTokenSpaceGuid.PcdFlashAreaBaseAddress
  4. Size = 0x102000
  5. ErasePolarity = 1
  6. BlockSize = 0x10000
  7. NumBlocks = 16
  8. BlockSize = 0x1000
  9. NumBlocks = 2

接著Token的是可選的DEFINE和SET定義,用于定義本[FD]塊內(nèi)有效的宏和PCD。 
然后是Region列表,每個(gè)Region定義了位置、大小及其中的內(nèi)容,格式為

  1. Offset|Size
  2. [TokenSpaceGuidCName.PcdOffsetCName|TokenSpaceGuidCName.PcdSizeCName]?
  3. [RegionType]?

第一行定義了本Region的偏移位置和大小。 
第二行和第三行為可選項(xiàng)。 
第二行定義對(duì)應(yīng)的PCD值,相當(dāng)于 
SET TokenSpaceGuidCName.PcdOffsetCName = Offset 
SET TokenSpaceGuidCName.PcdSizeCName = Size 
第三行定義本Region包含的內(nèi)容。內(nèi)容可以為數(shù)據(jù)(Data),也可以是FV(Firmware Volume)。 
所有的Region必須按偏移地址升序排列,Region之間不得重疊。 
例如OvmfPkg.fdf.inc文件的[FD.OVMF]塊:

  1. [FD.OVMF]
  2. BaseAddress = $(FW_BASE_ADDRESS)
  3. Size = $(FW_SIZE)
  4. ErasePolarity = 1
  5. BlockSize = $(BLOCK_SIZE)
  6. NumBlocks = $(FW_BLOCKS)
  7. !include VarStore.fdf.inc
  8. $(VARS_SIZE)|$(FVMAIN_SIZE)
  9. FV = FVMAIN_COMPACT
  10. $(SECFV_OFFSET)|$(SECFV_SIZE)
  11. FV = SECFV

通過!include VarStore.fdf.inc引入了數(shù)據(jù)Region,數(shù)據(jù)Reigon后是兩個(gè)Fv。編譯Release版本OVMF時(shí),這兩個(gè)Region為

  1. 0x20000|0x000CC000
  2. FV = FVMAIN_COMPACT
  3. 0x000EC000|0x14000
  4. FV = SECFV

1M的ovmf.fd內(nèi)容組織如下:

地址區(qū)間內(nèi)容
0x00000 ~ 0x01FFFFData
0x20000 ~ 0x0EBFFFFVMAIN_COMPACT
0xEC000 ~ 0x100000SECFV

再來看OVMF.FD的數(shù)據(jù)區(qū),定義在文件VarStore.fdf.inc中,詳細(xì)大家已經(jīng)掌握了其格式。

  1. 0x00000000|0x0000e000
  2. #NV_VARIABLE_STORE
  3. DATA = {
  4. ## This is the EFI_FIRMWARE_VOLUME_HEADER
  5. # ZeroVector []
  6. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  7. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  8. # FileSystemGuid: gEfiSystemNvDataFvGuid =
  9. # { 0xFFF12B8D, 0x7696, 0x4C8B,
  10. # { 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50 }}
  11. 0x8D, 0x2B, 0xF1, 0xFF, 0x96, 0x76, 0x8B, 0x4C,
  12. 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50,
  13. # FvLength: 0x20000
  14. 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
  15. # Signature "_FVH" # Attributes
  16. 0x5f, 0x46, 0x56, 0x48, 0xff, 0xfe, 0x04, 0x00,
  17. # HeaderLength # CheckSum # ExtHeaderOffset #Reserved #Revision
  18. 0x48, 0x00, 0x19, 0xF9, 0x00, 0x00, 0x00, 0x02,
  19. # Blockmap[0]: 0x20 Blocks * 0x1000 Bytes / Block
  20. 0x20, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
  21. # Blockmap[1]: End
  22. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  23. ## This is the VARIABLE_STORE_HEADER
  24. !if $(SECURE_BOOT_ENABLE) == TRUE
  25. # Signature: gEfiAuthenticatedVariableGuid =
  26. # { 0xaaf32c78, 0x947b, 0x439a,
  27. # { 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92 }}
  28. 0x78, 0x2c, 0xf3, 0xaa, 0x7b, 0x94, 0x9a, 0x43,
  29. 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92,
  30. !else
  31. # Signature: gEfiVariableGuid =
  32. # { 0xddcf3616, 0x3275, 0x4164,
  33. # { 0x98, 0xb6, 0xfe, 0x85, 0x70, 0x7f, 0xfe, 0x7d }}
  34. 0x16, 0x36, 0xcf, 0xdd, 0x75, 0x32, 0x64, 0x41,
  35. 0x98, 0xb6, 0xfe, 0x85, 0x70, 0x7f, 0xfe, 0x7d,
  36. !endif
  37. # Size: 0xe000 (gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize) -
  38. # 0x48 (size of EFI_FIRMWARE_VOLUME_HEADER) = 0xdfb8
  39. # This can speed up the Variable Dispatch a bit.
  40. 0xB8, 0xDF, 0x00, 0x00,
  41. # FORMATTED: 0x5A #HEALTHY: 0xFE #Reserved: UINT16 #Reserved1: UINT32
  42. 0x5A, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  43. }
  44. 0x0000e000|0x00001000
  45. #NV_EVENT_LOG
  46. 0x0000f000|0x00001000
  47. #NV_FTW_WORKING
  48. DATA = {
  49. # EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER->Signature = gEdkiiWorkingBlockSignatureGuid =
  50. # { 0x9e58292b, 0x7c68, 0x497d, { 0xa0, 0xce, 0x65, 0x0, 0xfd, 0x9f, 0x1b, 0x95 }}
  51. 0x2b, 0x29, 0x58, 0x9e, 0x68, 0x7c, 0x7d, 0x49,
  52. 0xa0, 0xce, 0x65, 0x0, 0xfd, 0x9f, 0x1b, 0x95,
  53. # Crc:UINT32 #WorkingBlockValid:1, WorkingBlockInvalid:1, Reserved
  54. 0x2c, 0xaf, 0x2c, 0x64, 0xFE, 0xFF, 0xFF, 0xFF,
  55. # WriteQueueSize: UINT64
  56. 0xE0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  57. }
  58. 0x00010000|0x00010000
  59. #NV_FTW_SPAR

[FV]

下面來看在FD中作為Region的FV(Firmare Volume)。一個(gè)FV定義了一個(gè)固件卷,其內(nèi)容包含一些列二進(jìn)制Image,這些Image按[FV]中排列的順序排列在最終生成固件中。 
[FV.UiFvName]中UiFvName用于標(biāo)示這個(gè)FV,通過 FV = UiFvName可以在其他FV和FD中引用UiFvName。 
先睹為快,下面是[FV.SECFV]

  1. [FV.SECFV]
  2. BlockSize = 0x1000
  3. FvAlignment = 16
  4. ERASE_POLARITY = 1
  5. MEMORY_MAPPED = TRUE
  6. STICKY_WRITE = TRUE
  7. LOCK_CAP = TRUE
  8. LOCK_STATUS = TRUE
  9. WRITE_DISABLED_CAP = TRUE
  10. WRITE_ENABLED_CAP = TRUE
  11. WRITE_STATUS = TRUE
  12. WRITE_LOCK_CAP = TRUE
  13. WRITE_LOCK_STATUS = TRUE
  14. READ_DISABLED_CAP = TRUE
  15. READ_ENABLED_CAP = TRUE
  16. READ_STATUS = TRUE
  17. READ_LOCK_CAP = TRUE
  18. READ_LOCK_STATUS = TRUE
  19. #
  20. # SEC Phase modules
  21. #
  22. INF OvmfPkg/Sec/SecMain.inf
  23. INF RuleOverride=RESET_VECTOR OvmfPkg/ResetVector/ResetVector.inf

[FV]首先是Token,定義了本FV的基本屬性,例如BlockSize等。 
然后可以通過DEFINE 定義宏,通過SET定義PCD。 
在然后就是內(nèi)容列表了。內(nèi)容可以通過INF、FILE定義,也可以通過SECTION、APRIORI包含一系列內(nèi)容。

INF

通過INF包含一個(gè)模塊,其語法如下

  1. INF [Options] PathAndInfFileName

例如【FV.SECFV]中,通過INF 定義了SecMain.inf、ResetVector.inf,這兩個(gè)模塊將會(huì)按順序存放在這個(gè)FV中。編譯ResetVector.inf模塊時(shí)將會(huì)按RESET_VECTOR指定的規(guī)則生成.efi文件。

FILE

通過FILE包含文件的語法有兩種,一種是包含單個(gè)文件,一種表示包含多個(gè)文件

  1. FILE Type $(NAMED_GUID) [Options] FileName
  2. 或者
  3. FILE Type = $(NAMED_GUID) [Options] {
  4. SECTION SECTION_TYPE = FileName
  5. SECTION SECTION_TYPE = FileName
  6. }

例如[FV.DXEFV]有如下內(nèi)容。

  1. #Type為FREEFORM,表示二進(jìn)制內(nèi)容。
  2. FILE FREEFORM = PCD(gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLogoFile) {
  3. SECTION RAW = MdeModulePkg/Logo/Logo.bmp
  4. }
  5. FILE DRIVER = 5D695E11-9B3F-4b83-B25F-4A8D5D69BE07 {
  6. SECTION PE32 = Intel3.5/EFIX64/E3507X2.EFI
  7. }

可用的Type包括:

TYPE
RAW
FREEFORM
SEC
PEI_CORE
DXE_CORE
PEIM
DRIVER
COMBO_PEIM_DRIVER
SMM_CORE
DXE_SMM_DRIVER
APPLICATION
FV_IMAGE
DISPOSABLE
0x00~0xFF

通過分析[FD.OVMF]及[FV.SECFV]可以知道,在生成的OVMF.FD文件中位于文件最后的是ResetVector.inf模塊。OVMF.FD可以燒到系統(tǒng)ROM中作為系統(tǒng)固件。前面已經(jīng)講過開機(jī)時(shí)ROM將被映射到0xFFFFFFFF最靠后的內(nèi)存中。那么第一條指令對(duì)應(yīng)地址0xFFFFFFF0將位于ResetVector.inf模塊。 
ResetVector.inf內(nèi)容如下:

  1. [Defines]
  2. INF_VERSION = 0x00010005
  3. BASE_NAME = ResetVector
  4. FILE_GUID = 1BA0062E-C779-4582-8566-336AE8F78F09
  5. MODULE_TYPE = SEC
  6. VERSION_STRING = 1.1
  7. [Sources]
  8. ResetVector.nasmb
  9. [Packages]
  10. MdePkg/MdePkg.dec
  11. UefiCpuPkg/UefiCpuPkg.dec
  12. [BuildOptions]
  13. *_*_IA32_NASMB_FLAGS = -I$(WORKSPACE)/UefiCpuPkg/ResetVector/Vtf0/
  14. *_*_X64_NASMB_FLAGS = -I$(WORKSPACE)/UefiCpuPkg/ResetVector/Vtf0/

ResetVector.inf包含了源文件ResetVector.nasmb,內(nèi)容如下:

  1. %ifndef ARCH_IA32
  2. %ifndef ARCH_X64
  3. #include <Base.h>
  4. #if defined (MDE_CPU_IA32)
  5. %define ARCH_IA32
  6. #elif defined (MDE_CPU_X64)
  7. %define ARCH_X64
  8. #endif
  9. %endif
  10. %endif
  11. %ifdef ARCH_IA32
  12. %ifdef ARCH_X64
  13. %error "Only one of ARCH_IA32 or ARCH_X64 can be defined."
  14. %endif
  15. %elifdef ARCH_X64
  16. %else
  17. %error "Either ARCH_IA32 or ARCH_X64 must be defined."
  18. %endif
  19. %include "CommonMacros.inc"
  20. %include "PostCodes.inc"
  21. %ifdef DEBUG_PORT80
  22. %include "Port80Debug.asm"
  23. %elifdef DEBUG_SERIAL
  24. %include "SerialDebug.asm"
  25. %else
  26. %include "DebugDisabled.asm"
  27. %endif
  28. %include "Ia32/SearchForBfvBase.asm"
  29. %include "Ia32/SearchForSecEntry.asm"
  30. %ifdef ARCH_X64
  31. %include "Ia32/Flat32ToFlat64.asm"
  32. %include "Ia32/PageTables64.asm"
  33. %endif
  34. %include "Ia16/Real16ToFlat32.asm"
  35. %include "Ia16/Init16.asm"
  36. %include "Main.asm"
  37. %include "Ia16/ResetVectorVtf0.asm"

位于最后的是ResetVectorVtf0.asm,其內(nèi)容如下:

  1. BITS 16
  2. ALIGN 16
  3. %ifdef ALIGN_TOP_TO_4K_FOR_PAGING
  4. TIMES (0x1000 - ($ - EndOfPageTables) - 0x20) DB 0
  5. %endif
  6. applicationProcessorEntryPoint:
  7. jmp EarlyApInitReal16
  8. ALIGN 8
  9. DD 0
  10. vtfSignature:
  11. DB 'V', 'T', 'F', 0
  12. ALIGN 16
  13. resetVector:
  14. ; This is where the processor will begin execution
  15. ;
  16. nop
  17. nop
  18. jmp EarlyBspInitReal16
  19. ALIGN 16
  20. fourGigabytes:

位于0xFFFFFFF0(fourGigabytes-16)處的是指標(biāo)resetVector:,從此處開始的第一條有效指令是 jmp EarlyBspInitReal16。 
可以通過反匯編OVMF.fd驗(yàn)證, 
OVMF.FD最后16字節(jié)為

  1. 0x000FFFF0 90 90 E9 AB FF 90 90 90 90 90 90 90 90 90 90 90

指令碼90對(duì)應(yīng)的指令正是nop,E9 AB FF對(duì)應(yīng)的指令是 jmp FFAB, 跳轉(zhuǎn)到EIP+(FFAB)處執(zhí)行, E9 AB FF對(duì)應(yīng)的EIP為0x000FFFF2,那么下一條指令的EIP為0x000FFFF5, FFAB是-0x55, 0x000FFFF5 - 0x55 = 0xFFFA0. 0xFFFA0正是EarlyBspInitReal16。編譯后的匯編碼位于OvmfX64\RELEASE_VS2010x86\X64\OvmfPkg\ResetVector\ResetVector\OUTPUT\ResetVector.lst文件中。

  1. <1> EarlyBspInitReal16:
  2. BF4250 <1> mov di, 'BP'
  3. EB0B <1> jmp short Main16

OVMF.FD中偏移0xFFFA0處的地址碼為:

  1. 0x00FFFA0 BF 42 50 EB 0B BF 41 50 EB 06 66 89 C4 E9 03 00

BF 42 50正是mov di, 'BP'對(duì)應(yīng)的指令碼。 
再往后就是CPU軟件初始化的過程了。

Feedback

# re: 深入U(xiǎn)EFI內(nèi)核(一)ResetVector  回復(fù)  更多評(píng)論   

2015-07-13 11:01 by PlayBoy
不明覺厲

# re: 深入U(xiǎn)EFI內(nèi)核(一)ResetVector  回復(fù)  更多評(píng)論   

2015-07-13 22:45 by 胡俊杰
深度好文,期待樓主這個(gè)系列下一篇大作

# re: 深入U(xiǎn)EFI內(nèi)核(一)ResetVector  回復(fù)  更多評(píng)論   

2015-08-26 09:29 by winux
對(duì)于BUILD編譯NT32PKG生成的secMain.exe與OVMF.pkg編譯出來的OVMF固件有什么區(qū)別?我編譯出來的grub.efi,通過qemu虛擬機(jī),加載ovmf.fd的固件啟動(dòng),能夠運(yùn)行虛擬盤里的grub.efi。可是secMain.exe執(zhí)行后,進(jìn)入到fs0:后,運(yùn)行拷貝在secMain.exe同目錄的grub.efi時(shí),卻直接退出了。我理解secMain.exe應(yīng)該也可以模擬呀,需要怎么操作呢?

只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久久久一区二区三区四区| 中国成人黄色视屏| 美女成人午夜| 久久久久网址| 亚洲激情视频网| 欧美福利小视频| 麻豆av一区二区三区| 亚洲韩国青草视频| 亚洲国产一区二区a毛片| 欧美高清在线精品一区| 亚洲人成网站999久久久综合| 欧美大片在线观看| 欧美chengren| 在线视频亚洲一区| 一区二区精品在线| 国产精品视频久久久| 久久aⅴ国产紧身牛仔裤| 午夜精品久久99蜜桃的功能介绍| 国产日韩一区二区三区在线| 久久精品一区中文字幕| 久久久久久久久一区二区| 在线日韩电影| 亚洲日本中文字幕| 欧美午夜国产| 欧美在线观看一区| 久久久91精品国产一区二区三区| 在线不卡欧美| 最新亚洲视频| 国产精品男gay被猛男狂揉视频| 欧美一区二区成人| 久久久久久久久久久一区| 最新中文字幕亚洲| av不卡在线| 国产一区二区三区四区在线观看| 美女91精品| 欧美日韩www| 久久成人资源| 免费欧美视频| 亚洲永久字幕| 久久久精品动漫| av成人黄色| 亚洲欧美日韩一区二区在线| 亚洲高清资源综合久久精品| 亚洲精品色婷婷福利天堂| 国产精品一二三四区| 美女主播视频一区| 欧美日韩小视频| 久久久久久久网| 欧美久久久久| 久久精品九九| 欧美激情第9页| 欧美一级淫片播放口| 理论片一区二区在线| 亚洲欧美精品suv| 美女亚洲精品| 香蕉久久久久久久av网站| 久久综合伊人77777| 亚洲一区二区三区四区五区午夜| 欧美中文字幕视频在线观看| 日韩亚洲精品电影| 小处雏高清一区二区三区| 亚洲人成人一区二区在线观看| 亚洲综合国产激情另类一区| 亚洲精品一二三区| 欧美一区二区三区在| 99视频在线观看一区三区| 久久狠狠亚洲综合| 亚洲免费一在线| 免费观看国产成人| 久久av一区二区三区亚洲| 欧美激情综合色| 久久亚洲不卡| 国产精品白丝jk黑袜喷水| 欧美国产在线电影| 国产亚洲精品aa| 在线午夜精品自拍| 亚洲经典视频在线观看| 欧美一区在线视频| 亚洲一区免费观看| 欧美国产日韩二区| 玖玖在线精品| 国产精品人成在线观看免费 | 欧美区一区二| 久久亚洲欧美| 国产精品视频你懂的| 亚洲青色在线| 亚洲高清视频一区| 欧美一区二区三区四区视频| 亚洲一区二区三区影院| 欧美成人免费大片| 欧美gay视频| 国产一区二区中文| 亚洲在线日韩| 亚洲一本大道在线| 欧美日本在线播放| 欧美激情在线| 亚洲国产二区| 久久精品水蜜桃av综合天堂| 欧美一区二区黄| 国产精品黄视频| 一区二区欧美精品| 久久深夜福利免费观看| 久久国产精品一区二区| 国产精品精品视频| 日韩一级欧洲| 99亚洲精品| 欧美极品影院| 亚洲国产精品成人一区二区| 亚洲电影激情视频网站| 久久精品国产99精品国产亚洲性色| 欧美一区二区黄| 国产乱码精品一区二区三区忘忧草| 日韩亚洲欧美在线观看| 日韩亚洲欧美中文三级| 欧美国产日产韩国视频| 欧美激情四色| 亚洲人成高清| 女女同性精品视频| 欧美国产亚洲另类动漫| 亚洲黄色在线看| 美腿丝袜亚洲色图| 欧美福利视频在线| 91久久精品日日躁夜夜躁国产| 久久视频这里只有精品| 快射av在线播放一区| 狠狠综合久久| 久久五月婷婷丁香社区| 欧美第一黄网免费网站| 亚洲精品国产日韩| 欧美国产第一页| 亚洲精品无人区| 亚洲视频综合| 国产精品美女久久| 亚洲欧美日韩另类精品一区二区三区| 欧美一区二区三区免费观看视频| 国产精品网站视频| 欧美一区二区黄色| 久久综合久久久久88| 亚洲国产一二三| 欧美人在线观看| 在线视频日本亚洲性| 欧美在线视频a| 激情久久久久久久| 免费成人av资源网| 亚洲日本va午夜在线影院| 一区二区高清视频| 国产精品入口66mio| 久久精品动漫| 欧美国产激情| 一区二区三区视频在线看 | 亚洲电影专区| 在线视频欧美精品| 国产精品亚洲视频| 久久精品中文| 亚洲黄色毛片| 亚洲一区二区在线免费观看| 国产精品中文字幕在线观看| 久久精品99国产精品酒店日本| 欧美国产综合| 亚洲制服少妇| 海角社区69精品视频| 免费看av成人| 亚洲无限乱码一二三四麻| 久久久久国色av免费观看性色| 亚洲国产精品日韩| 欧美三级视频在线播放| 欧美一级播放| 亚洲黄页一区| 欧美一级成年大片在线观看| 在线观看成人一级片| 欧美日韩三级电影在线| 欧美一区免费视频| 91久久综合| 久久国产一区| 亚洲精品影视| 国产亚洲欧美一区二区| 欧美国产日本| 欧美亚洲自偷自偷| 最新国产の精品合集bt伙计| 久久成人av少妇免费| 亚洲人成在线播放网站岛国| 国产精品视频导航| 欧美国产另类| 欧美一区二区三区久久精品茉莉花| 亚洲盗摄视频| 久久大逼视频| 一本一本a久久| 一区二区三区自拍| 国产精品国产自产拍高清av王其 | 亚洲精品美女久久久久| 久久精品日韩一区二区三区| 夜夜嗨av一区二区三区中文字幕| 国产性做久久久久久| 欧美精品入口| 久久深夜福利免费观看| 亚洲一级黄色| 亚洲激情社区| 久久手机免费观看| 亚洲永久免费| 亚洲美女在线看|