1. 程式人生 > >EFI基本概念之HOB

EFI基本概念之HOB

1 基本概念及用法

HOB是Hand-offblock的縮寫。是PEI階段向DXE傳遞系統資訊的手段。PEI階段構建一些HOB結構,然後將其作為引數傳給DXE階段函式,DXE Core會根據其使用平臺相關資源。

HOB是系列的連續的記憶體結構體,可以認為其由三部分構成:第一部分,是PHIT頭,它描述了HOB的起始地址以及總的記憶體使用;第二部分是各個Hob列表,DXE階段會根據這一部分獲取上關資源;第三部分是結束部分。

1.1 PHIT頭:

typedef struct {

EFI_HOB_GENERIC_HEADER  Header;

UINT32                  Version;

EFI_BOOT_MODE           BootMode;

EFI_PHYSICAL_ADDRESS   EfiMemoryTop;

EFI_PHYSICAL_ADDRESS   EfiMemoryBottom;

EFI_PHYSICAL_ADDRESS   EfiFreeMemoryTop;

EFI_PHYSICAL_ADDRESS   EfiFreeMemoryBottom;

EFI_PHYSICAL_ADDRESS   EfiEndOfHobList;

} EFI_HOB_HANDOFF_INFO_TABLE;

1.2 HOB列表中的一個

typedef struct {

EFI_HOB_GENERIC_HEADER           Header;

EFI_HOB_MEMORY_ALLOCATION_HEADER AllocDescriptor;

} EFI_HOB_MEMORY_ALLOCATION;

1.3 EFI_HOB_GENERIC_HEADER

typedef struct {

UINT16    HobType;

UINT16    HobLength;

UINT32    Reserved;

} EFI_HOB_GENERIC_HEADER;

每一個HOB,都有一個HEADER,來指示該HOB的型別。包括PHIT頭,也會有HEADER。下面來看一下HOB定義的型別有哪些:

#define EFI_HOB_TYPE_HANDOFF             

0x0001

#define EFI_HOB_TYPE_MEMORY_ALLOCATION    0x0002

#define EFI_HOB_TYPE_RESOURCE_DESCRIPTOR  0x0003

#define EFI_HOB_TYPE_GUID_EXTENSION       0x0004

#define EFI_HOB_TYPE_FV                   0x0005

#define EFI_HOB_TYPE_CPU                  0x0006

#define EFI_HOB_TYPE_MEMORY_POOL          0x0007

#define EFI_HOB_TYPE_FV2                  0x0009

#define EFI_HOB_TYPE_LOAD_PEIM_UNUSED     0x000A

#define EFI_HOB_TYPE_UEFI_CAPSULE         0x000B

#define EFI_HOB_TYPE_UNUSED               0xFFFE

#define EFI_HOB_TYPE_END_OF_HOB_LIST      0xFFFF

我是從UDK2014上拷貝出來的,不知道最新的PI SPEC有沒有增加。當然如果規範沒定義,也可以根據需要自己定義,因為自已是生產者自己也是消費者。

2. HOB相關函式

2.1建立HOB

EFI_STATUS

EFIAPI

PeiCreateHob (

IN CONSTEFI_PEI_SERVICES  **PeiServices,

IN UINT16            Type,

IN UINT16            Length,

IN OUT VOID          **Hob

)

{

Step1. 獲取HOB列表的首地址,即PHIT頭。

Step2. 確定是否有足夠的空間建立該HOB

Step3. 找到結束標誌的HOB,將其改寫成該HOB型別。並將結束標誌的HOB移至該HOB下方。

Step4. 更新PHITHOB

}

在建立該HOB後,我們就可以將該HOB的實際資料填至相應區域內。

2.2 獲取HobList首地址

EFI_STATUS

EFIAPI

PeiGetHobList (

IN CONSTEFI_PEI_SERVICES  **PeiServices,

IN OUT VOID          **HobList

)

{

   Step1. 如果用來接收HOB的HobList為空,返回非法。

Step2. 由引數PeiSerivces得到PEI Core例項,進而獲得HobList首地址。

}

2.3 DXE階段使用HOB

HOB的真正使用是在DXE階段,當然PEI階段也可以使用,但程式碼中並沒有那麼用。DXE階段使用HOB時,必須先解析其結構。具體如下:

2.3.1 獲取HOBList首地址

VOID *

EFIAPI

GetHobList (

VOID

)

{

ASSERT (mHobList!= NULL);

return mHobList;

}

2.3.2 獲取給定型別的HOB

VOID *

EFIAPI

GetFirstHob (

IN UINT16                 Type

)

{

VOID      *HobList;

HobList =GetHobList ();

return GetNextHob(Type, HobList);

}

其中GetNextHob()會根據HOB型別,返回其第一個匹配的HOB。

2.3.3 GetNextHob()獲取型別匹配的HOB

VOID *

EFIAPI

GetNextHob (

IN UINT16                 Type,

IN CONSTVOID             *HobStart

)

{

Step1. HobStart不準為空。

Step2. 將HobStart作為地址,賦值給Hob。

Step3. 判斷其是否是HOB的結尾,如果是,則沒找到。否則進入Step4。

Step4. 比較該HOB型別是不是和找的型別一致,如果一致,則將其返回。否則進入Step5。Step5. 找到緊鄰該HOB的下一個HOB,繼續Step3。

}

2.3.4 GET_NEXT_HOB的用法

在2.3.3中,想找到某HOB的下一個HOB,則需要計算當前HOB大小,並且跳過該HOB。這就需要用到GET_NEXT_HOB巨集定義。

#define GET_NEXT_HOB(HobStart) \

(VOID *)(*(UINT8**)&(HobStart) + GET_HOB_LENGTH (HobStart))

而GET_HOB_LENTGH的原型為

#define GET_HOB_LENGTH(HobStart) \

((*(EFI_HOB_GENERIC_HEADER **)&(HobStart))->HobLength)

所以檢索HOB最重要的一個欄位是Header的HobLength欄位。有了它,我們就可以正確地檢索每一個HOB了。