- 源码EDK2:Tianocore
- UEFI源码分析系列第二篇,DXE阶段的内存服务
- 第一部分,内存服务的初始化过程
- DXE阶段源码目录
MdeModulePkg/Core/Dxe
- 源码版本为UDK2017
- 目前最新版2018代码在
/Dxe/Mem/
下多了HeapGuard.c
这个文件,看名称应该是用来守护堆操作防止异常的。在UDK2017中并没有这个特性,所以我们的分析按照UDK2017的代码来。 - 关于
HeapGuard
的讨论将列为单独一部分,敬请期待。
内存服务的初始化
在DxeMain中调用以下函数来初始化内存服务
/** /Dxe/DxeMain/DxeMain.c **/
269 //
270 // Initialize Memory Services
271 //
272 CoreInitializeMemoryServices (&HobStart, &MemoryBaseAddress, &MemoryLength);
该函数位于/Dxe/Gcd/Gcd.c
中
/** /Dxe/Gcd/Gcd.c **/
2054 EFI_STATUS
2055 CoreInitializeMemoryServices (
2056 IN VOID **HobStart,
2057 OUT EFI_PHYSICAL_ADDRESS *MemoryBaseAddress,
2058 OUT UINT64 *MemoryLength
2059 )
2060 {
/** 进行内存服务初始化操作 **/
2295 *MemoryBaseAddress = BaseAddress;
2296 *MemoryLength = Length;
2297
2298 return EFI_SUCCESS;
2299 }
1)转换HOB数据
1)把指向HOB数据的指针HobStart
转换成HOB格式的数据,本质就是把地址传给相应结构体的变量
HOB数据结构定义于/MdePkg/Include/Pi/PiHob.h
操作HOB数据的方法由库/MdePkg/Library/DxeHobLib
提供,该库的头文件位于/MdePkg/Include/Library/HobLib.h
, 头文件中包含来几个操作HOB数据的宏定义,如GET_HOB_TYPE
宏来获取HOB类型。
/** /Dxe/Gcd/Gcd.c **/
2079 //
2080 // Point at the first HOB. This must be the PHIT HOB.
2081 //
2082 Hob.Raw = *HobStart;
2083 ASSERT (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_HANDOFF);
注意到变量Hob
的类型是EFI_PEI_HOB_POINTERS
,本质上是一个union
类型的数据结构。
使用union
最大的好处是提高源码的可读性和间接性。利用该类型中所有域的取值均一样的特点,在不同的使用方法下,可以使用不同的变量名字,一方面可以省去强制类型转换的麻烦,另一方面可以直接体现出当前的使用需求。
/** /MdePkg/Include/Pi/PiHob.h **/
458 ///
459 /// Union of all the possible HOB Types.
460 ///
461 typedef union {
462 EFI_HOB_GENERIC_HEADER *Header;
463 EFI_HOB_HANDOFF_INFO_TABLE *HandoffInformationTable;
464 EFI_HOB_MEMORY_ALLOCATION *MemoryAllocation;
465 EFI_HOB_MEMORY_ALLOCATION_BSP_STORE *MemoryAllocationBspStore;
466 EFI_HOB_MEMORY_ALLOCATION_STACK *MemoryAllocationStack;
467 EFI_HOB_MEMORY_ALLOCATION_MODULE *MemoryAllocationModule;
468 EFI_HOB_RESOURCE_DESCRIPTOR *ResourceDescriptor;
469 EFI_HOB_GUID_TYPE *Guid;
470 EFI_HOB_FIRMWARE_VOLUME *FirmwareVolume;
471 EFI_HOB_FIRMWARE_VOLUME2 *FirmwareVolume2;
472 EFI_HOB_CPU *Cpu;
473 EFI_HOB_MEMORY_POOL *Pool;
474 EFI_HOB_UEFI_CAPSULE *Capsule;
475 UINT8 *Raw;
476 } EFI_PEI_HOB_POINTERS;
2)初始化内存池
2)初始化内存池
/** /Dxe/Gcd/Gcd.c **/
2077 //
2078 // Initialize the spin locks and maps in the memory services.
2079 // Also fill in the memory services into the EFI Boot Services Table
2080 //
2081 CoreInitializePool ();
该函数的实现位于/Dxe/Mem/Pool.c
/** /Dxe/Mem/Pool.c **/
118 VOID
119 CoreInitializePool (
120 VOID
121 )
122 {
123 UINTN Type;
124 UINTN Index;
125
126 for (Type=0; Type < EfiMaxMemoryType; Type++) {
127 mPoolHead[Type].Signature = 0;
128 mPoolHead[Type].Used = 0;
129 mPoolHead[Type].MemoryType = (EFI_MEMORY_TYPE) Type;
130 for (Index=0; Index < MAX_POOL_LIST; Index++) {
131 InitializeListHead (&mPoolHead[Type].FreeList[Index]);
132 }
133 }
134 }
做的事情很简单,就是把全局变量mPoolHead
初始化,Pool
数据结构的定义也在Pool.c
文件中。
/** /Dxe/Mem/Pool.c **/
71 #define POOL_SIGNATURE SIGNATURE_32('p','l','s','t')
72 typedef struct {
73 INTN Signature;
74 UINTN Used;
75 EFI_MEMORY_TYPE MemoryType;
76 LIST_ENTRY FreeList[MAX_POOL_LIST];
77 LIST_ENTRY Link;
78 } POOL;
79
80 //
81 // Pool header for each memory type.
82 //
83 POOL mPoolHead[EfiMaxMemoryType];
全局变量mPoolHead
对每种内存类型EFI_MEMORY_TYPE
均有一组FreeList
来维护可用的内存空间。
内存类型是以枚举类型定义于/MdePkg/Include/Uefi/UefiMultiPhase.h
中。
/** /MdePkg/Include/Uefi/UefiMultiPhase.h **/
19 ///
20 /// Enumeration of memory types introduced in UEFI.
21 ///
22 typedef enum {
23 ///
24 /// Not used.
25 ///
26 EfiReservedMemoryType,
27 ///
28 /// The code portions of a loaded application.
29 /// (Note that UEFI OS loaders are UEFI applications.)
30 ///
31 EfiLoaderCode,
32 ///
33 /// The data portions of a loaded application and the default data allocation
34 /// type used by an application to allocate pool memory.
35 ///
36 EfiLoaderData,
37 ///
38 /// The code portions of a loaded Boot Services Driver.
39 ///
40 EfiBootServicesCode,
41 ///
42 /// The data portions of a loaded Boot Serves Driver, and the default data
43 /// allocation type used by a Boot Services Driver to allocate pool memory.
44 ///