UEFI.源码分析.DXE的内存服务.第一部分.初始化
Posted 木艮氵
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UEFI.源码分析.DXE的内存服务.第一部分.初始化相关的知识,希望对你有一定的参考价值。
- 源码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 ///
45 EfiBootServicesData,
46 ///
47 /// The code portions of a loaded Runtime Services Driver.
48 ///
49 EfiRuntimeServicesCode,
50 ///
51 /// The data portions of a loaded Runtime Services Driver and the default
52 /// data allocation type used by a Runtime Services Driver to allocate pool memory.
53 ///
54 EfiRuntimeServicesData,
55 ///
56 /// Free (unallocated) memory.
57 ///
58 EfiConventionalMemory,
59 ///
60 /// Memory in which errors have been detected.
61 ///
62 EfiUnusableMemory,
63 ///
64 /// Memory that holds the ACPI tables.
65 ///
66 EfiACPIReclaimMemory,
67 ///
68 /// Address space reserved for use by the firmware.
69 ///
70 EfiACPIMemoryNVS,
71 ///
72 /// Used by system firmware to request that a memory-mapped IO region
73 /// be mapped by the OS to a virtual address so it can be accessed by EFI runtime services.
74 ///
75 EfiMemoryMappedIO,
76 ///
77 /// System memory-mapped IO region that is used to translate memory
78 /// cycles to IO cycles by the processor.
79 ///
80 EfiMemoryMappedIOPortSpace,
81 ///
82 /// Address space reserved by the firmware for code that is part of the processor.
83 ///
84 EfiPalCode,
85 ///
86 /// A memory region that operates as EfiConventionalMemory,
87 /// however it happens to also support byte-addressable non-volatility.
88 ///
89 EfiPersistentMemory,
90 EfiMaxMemoryType
91 EFI_MEMORY_TYPE;
3)获取内存类型信息
3) 获取HOB中关于内存类型的数据信息,如果存在,则拷贝到全局变量gMemoryTypeInformation
中。
/** /Dxe/Gcd/Gcd.c **/
2115 //
2116 // See if a Memory Type Information HOB is available
2117 //
2118 GuidHob = GetFirstGuidHob (&gEfiMemoryTypeInformationGuid);
2119 if (GuidHob != NULL)
2120 EfiMemoryTypeInformation = GET_GUID_HOB_DATA (GuidHob);
2121 DataSize = GET_GUID_HOB_DATA_SIZE (GuidHob);
2122 if (EfiMemoryTypeInformation != NULL && DataSize > 0 && DataSize <= (EfiMaxMemoryType + 1) * sizeof (EFI_MEMORY_TYPE_INFORMATION))
2123 CopyMem (&gMemoryTypeInformation, EfiMemoryTypeInformation, DataSize);
2124
2125
全局变量gMemoryTypeInformation
定义于/Dxe/Mem/Page.c
中。
/** /Dxe/Mem/Page.c **/
75 EFI_MEMORY_TYPE_INFORMATION gMemoryTypeInformation[EfiMaxMemoryType + 1] =
76 EfiReservedMemoryType, 0 ,
77 EfiLoaderCode, 0 ,
78 EfiLoaderData, 0 ,
79 EfiBootServicesCode, 0 ,
80 EfiBootServicesData, 0 ,
81 EfiRuntimeServicesCode, 0 ,
82 EfiRuntimeServicesData, 0 ,
83 EfiConventionalMemory, 0 ,
84 EfiUnusableMemory, 0 ,
85 EfiACPIReclaimMemory, 0 ,
86 EfiACPIMemoryNVS, 0 ,
87 EfiMemoryMappedIO, 0 ,
88 EfiMemoryMappedIOPortSpace, 0 ,
89 EfiPalCode, 0 ,
90 EfiPersistentMemory, 0 ,
91 EfiMaxMemoryType, 0
92 ;
类型EFI_MEMORY_TYPE_INFORMATION
则定义于/MdeModulePkg/Include/Guid/MemoryTpyeInformation.h
中。
该类型EFI_MEMORY_TYPE_INFORMATION
是对内存类型所占用页数的一个统计。注意到HOB数据是由PEI阶段传递而来,所有PEI阶段应该把每种内存类型所需的页数算好后存入HOB传递给DXE。
DXE找到该HOB后便拷贝出来到全局变量gMemoryTypeInformation
中。
/* /MdeModulePkg/Include/Guid/MemoryTpyeInformation.h **/
21 #ifndef __MEMORY_TYPE_INFORMATION_GUID_H__
22 #define __MEMORY_TYPE_INFORMATION_GUID_H__
23
24 #define EFI_MEMORY_TYPE_INFORMATION_GUID \\
25 0x4c19049f,0x4137,0x4dd3, 0x9c,0x10,0x8b,0x97,0xa8,0x3f,0xfd,0xfa
26
27 #define EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME L"MemoryTypeInformation"
28
29 extern EFI_GUID gEfiMemoryTypeInformationGuid;
30
31 typedef struct
32 UINT32 Type; ///< EFI memory type defined in UEFI specification.
33 UINT32 NumberOfPages; ///< The pages of this type memory.
34 EFI_MEMORY_TYPE_INFORMATION;
4)计算所需资源大小
4) 计算所需的内存资源
/** /Dxe/Gcd/Gcd.c **/
2127 //
2128 // Include the total memory bin size needed to make sure memory bin could be allocated successfully.
2129 //
2130 MinimalMemorySizeNeeded = MINIMUM_INITIAL_MEMORY_SIZE + CalculateTotalMemoryBinSizeNeeded ();
其中MINIMUM_INITIAL_MEMORY_SIZE
定义于本文件
/** /Dxe/Gcd/Gcd.c **/
20 #define MINIMUM_INITIAL_MEMORY_SIZE 0x10000
函数CalculateTotalMemoryBinSizeNeeded
也定义于本文件,其遍历全局变量gMemoryTypeInformation
来计算所需的内存资源数。
/** /Dxe/Gcd/Gcd.c **/
2020 UINT64
2021 CalculateTotalMemoryBinSizeNeeded (
2022 VOID
2023 )
2024
2025 UINTN Index;
2026 UINT64 TotalSize;
2027
2028 //
2029 // Loop through each memory type in the order specified by the gMemoryTypeInformation[] array
2030 //
2031 TotalSize = 0;
2032 for (Index = 0; gMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++)
2033 TotalSize += LShiftU64 (gMemoryTypeInformation[Index].NumberOfPages, EFI_PAGE_SHIFT);
2034
2035
2036 return TotalSize;
2037
5)根据HOB寻找可用内存资源
5) 遍历所有的HOB数据,来获取可用的内存资源信息
/** /Dxe/Gcd/Gcd.c **/
2135 Found = FALSE;
2136 for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob))
判断该HOB的类型,若不是EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
则跳过。
2140 if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR)
2141 continue;
2142
如果是资源描述的HOB数据,则进一步判断是否是系统内存的资源描述,并且保证该内存区域是测试过的内存区域。
2147 ResourceHob = Hob.ResourceDescriptor;
2148 if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY)
2149 continue;
2150
2151 if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES)
2152 continue;
2153
进一步判断该内存区域是否包含了HOB信息头所描述的空闲内存区域。
HOB数据的最开始是一个信息头数据结构,即EFI_HOB_HANDOFF_INFO_TABLE
,其指明了PEI阶段堆的内存空间的地址范围。
本次循环所寻找的HOB资源,其描述的内存空间需要包含HOB信息头所描述的可用内存资源
2103 PhitHob = Hob.HandoffInformationTable;
2158 if (PhitHob->EfiFreeMemoryBottom < ResourceHob->PhysicalStart)
2159 continue;
2160
2161 if (PhitHob->EfiFreeMemoryTop > (ResourceHob->PhysicalStart + ResourceHob->ResourceLength))
2162 continue;
2163
找到则保存该HOB数据
2168 PhitResourceHob = ResourceHob;
2169 Found = TRUE;
计算并比较不同可用区域的大小是否满足4)中的最小需求
2171 //
2172 // Compute range between PHIT EfiMemoryTop and the end of the Resource Descriptor HOB
2173 //
2174 Attributes = PhitResourceHob->ResourceAttribute;
2175 BaseAddress = PageAlignAddress (PhitHob->EfiMemoryTop);
2176 Length = PageAlignLength (ResourceHob->PhysicalStart + ResourceHob->ResourceLength - BaseAddress);
2177 if (Length < MinimalMemorySizeNeeded)
2178 //
2179 // If that range is not large enough to intialize the DXE Core, then
2180 // Compute range between PHIT EfiFreeMemoryBottom and PHIT EfiFreeMemoryTop
2181 //
2182 BaseAddress = PageAlignAddress (PhitHob->EfiFreeMemoryBottom);
2183 Length = PageAlignLength (PhitHob->EfiFreeMemoryTop - BaseAddress);
2184 if (Length < MinimalMemorySizeNeeded)
2185 //
2186 // If that range is not large enough to intialize the DXE Core, then
2187 // Compute range between the start of the Resource Descriptor HOB and the start of the HOB List
2188 //
2189 BaseAddress = PageAlignAddress (ResourceHob->PhysicalStart);
2190 Length = PageAlignLength ((UINT64)((UINTN)*HobStart - BaseAddress));
2191
2192
2193 break;
这边需要详细解释HOB数据的位置以及PEI阶段的堆空间,才有可能完全理解这段代码的含义。
6)若找不到则继续寻找
6) 若5)中找到的可用内存空间仍旧不满足最小的内存需求,则继续寻找其他空间
2207 if (Length < MinimalMemorySizeNeeded)
/** 寻找其他内存空间 **/
2266
首先获取到地址上限
2074 EFI_PHYSICAL_ADDRESS HighAddress;
2213 HighAddress = MAX_ADDRESS;
宏MAX_ADDRESS
定义于MdePkg/Include/$arch/ProcessorBind.h
文件中。
搜索可以采用grep
命令快速定位到寻找的内容,不过如果对源码结构比较熟悉,或想凭自己的理解摸索一下,建议直接到文件目录中寻找。往往我是没什么别的办法来才使用这个命令。
~/edk2 (UDK2017*) $ grep "#define MAX_ADDRESS" -Rn
MdePkg/Include/AArch64/ProcessorBind.h:94:#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFFULL
MdePkg/Include/Arm/ProcessorBind.h:100:#define MAX_ADDRESS 0xFFFFFFFF
MdePkg/Include/Ipf/ProcessorBind.h:237:#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFFULL
MdePkg/Include/Ia32/ProcessorBind.h:247:#define MAX_ADDRESS 0xFFFFFFFF
MdePkg/Include/Ebc/ProcessorBind.h:104:#define MAX_ADDRESS ((UINTN) ~0)
MdePkg/Include/X64/ProcessorBind.h:261:#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFFULL
grep: EmulatorPkg/Unix/Host/X11IncludeHack: 没有那个文件或目录
BaseTools/Source/C/Include/AArch64/ProcessorBind.h:96:#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFF
BaseTools/Source/C/Include/Arm/ProcessorBind.h:94:#define MAX_ADDRESS 0xFFFFFFFF
BaseTools/Source/C/Include/Ia32/ProcessorBind.h:137:#define MAX_ADDRESS 0xFFFFFFFF
BaseTools/Source/C/Include/X64/ProcessorBind.h:156:#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFFULL
遍历HOB数据,跳过5)中所找到的HOB,跳过不是资源描述的,跳过不是描述系统内存资源的,跳过内存资源是没有经过测试的
但是不要求包含HOB信息头描述的可用内存区域了
2214 for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob))
2218 if (Hob.ResourceDescriptor == PhitResourceHob)
2219 continue;
2220
2224 if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR)
2225 continue;
2226
2231 ResourceHob = Hob.ResourceDescriptor;
2232 if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY)
2233 continue;
2234
2235 if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES)
2236 continue;
2237
跳过最高地址超过了上限的HOB数据
2238 if ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength) > (EFI_PHYSICAL_ADDRESS)MAX_ADDRESS)
2239 continue;
2240
跳过所描述地址空间低于 上一个遍历的HOB数据的地址空间 的HOB数据,for
循环的最后会修改HighAddress
的值。
2238 if ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength) > (EFI_PHYSICAL_ADDRESS)MAX_ADDRESS)
2239 continue;
2240
2264 HighAddress = ResourceHob->PhysicalStart;
2265 // end for
跳过不满足空间需求的
2252 TestedMemoryBaseAddress = PageAlignAddress (ResourceHob->PhysicalStart);
2253 TestedMemoryLength = PageAlignLength (ResourceHob->PhysicalStart + ResourceHob->ResourceLength - TestedMemoryBaseAddress);
2254 if (TestedMemoryLength < MinimalMemorySizeNeeded)
2255 continue;
2256
好的,我们找到了
2261 BaseAddress = TestedMemoryBaseAddress;
2262 Length = TestedMemoryLength;
2263 Attributes = ResourceHob->ResourceAttribute;
输出到DEBUG信息中,表示很开心 :)
2268 DEBUG ((EFI_D_INFO, "CoreInitializeMemoryServices:\\n"));
2269 DEBUG ((EFI_D_INFO, " BaseAddress - 0x%lx Length - 0x%lx MinimalMemorySizeNeeded - 0x%lx\\n", BaseAddress, Length, MinimalMemorySizeNeeded));
assert一下,表示很有信心:)如果到这里还找不到,那就没法继续了
2274 ASSERT (Length >= MinimalMemorySizeNeeded);
7)转换内存属性到掩码形式
7) 把内存资源的属性Atrributes
转换成Memory Capabilities掩码
2276 //
2277 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2278 //
2279 if ((Attributes & EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE) == EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE)
2280 Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeMoreReliable, Attributes);
2281 else
2282 Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeSystemMemory, Attributes);
2283
8)添加内存资源描述符,建立内存服务
8) 使用该内存区域建立最初的内存资源,之后内存服务已经完全可用了
2285 //
2286 // Declare the very first memory region, so the EFI Memory Services are available.
2287 //
2288 CoreAddMemoryDescriptor (
2289 EfiConventionalMemory,
2290 BaseAddress,
2291 RShiftU64 (Length, EFI_PAGE_SHIFT),
2292 Capabilities
2293 );
函数CoreAddMemoryDescriptor
位于/Dxe/Mem/Page.c
中。
/** /Dxe/Mem/Page.c **/
530 VOID
531 CoreAddMemoryDescriptor (
532 IN EFI_MEMORY_TYPE Type,
533 IN EFI_PHYSICAL_ADDRESS Start,
534 IN UINT64 NumberOfPages,
535 IN UINT64 Attribute
536 )
537
/** 建立内存服务 **/
679
检查是否页对齐
/** /Dxe/Mem/Page.c **/
543 if ((Start & EFI_PAGE_MASK) != 0)
544 return;
545
检查内存类型的合法性
/** /Dxe/Mem/Page.c **/
547 if (Type >= EfiMaxMemoryType && Type < MEMORY_TYPE_OEM_RESERVED_MIN)
548 return;
549
内存类型的范围描述在/Dxe/Mem/Imem.h
中
/** /Dxe/Mem/Imem.h **/
18 //
19 // +---------------------------------------------------+
20 // | 0..(EfiMaxMemoryType - 1) - Normal memory type |
21 // +---------------------------------------------------+
22 // | EfiMaxMemoryType..0x6FFFFFFF - Invalid |
23 // +---------------------------------------------------+
24 // | 0x70000000..0x7FFFFFFF - OEM reserved |
25 // +---------------------------------------------------+
26 // | 0x80000000..0xFFFFFFFF - OS reserved |
27 // +---------------------------------------------------+
28 //
29 #define MEMORY_TYPE_OS_RESERVED_MIN 0x80000000
30 #define MEMORY_TYPE_OS_RESERVED_MAX 0xFFFFFFFF
31 #define MEMORY_TYPE_OEM_RESERVED_MIN 0x70000000
32 #define MEMORY_TYPE_OEM_RESERVED_MAX 0x7FFFFFFF
随后开始真正的建立内存服务。
/** /Dxe/Mem/Page.c **/
550 CoreAcquireMemoryLock ();
551 End = Start + LShiftU64 (NumberOfPages, EFI_PAGE_SHIFT) - 1;
552 CoreAddRange (Type, Start, End, Attribute);
553 CoreFreeMemoryMapStack ();
554 CoreReleaseMemoryLock ();
明明以为到这里就开始建立了,结果却又跳转到一个函数。
实际上复杂的系统中这种情况很常见,真正干实际事情的代码隐藏在层层调用之中。这是因为往往需要有大量的检查工作,而且如果所有代码都放在一个函数里实现,通常会显得很臃肿。
Lock机制
在这里就不详细讲了,最底层的实现是禁中断。这是因为UEFI系统只用了一个处理器核。详细会在异步事件机制
中分析。
CoreAddRange
将在后面操作内存的接口函数中详细描述。
/** /Dxe/Mem/Page.c **/
569 if (mMemoryTypeInformationInitialized)
570 return;
571
内存服务建立后,我们需要使用MemoryTypeInformation
信息来进行测试。全局变量mMemoryTypeInformationInitialized
用于标记是否完成来内存测试工作,在本函数的结尾会标记为TRUE
,若在某次申请测试时出错则会直接返回,从而该标记不会被置为真。
在前文的3)中从HOB中获取的内存类型信息,描述了各种类型的内存所需要的页数,随后在4)中我们据此计算出了最小的内存空间需求。之后的5)和6)均是在这最小的内存空间需求下寻找合适的内存空间。
首先我们遍历所有的内存类型信息
/** /Dxe/Mem/Page.c **/
577 for (Index = 0; gMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++)
581 Type = (EFI_MEMORY_TYPE) (gMemoryTypeInformation[Index].Type);
582 if ((UINT32)Type > EfiMaxMemoryType)
583 continue;
584
如果某个内存类型所需要的页数不为零,则申请这么多页大小的空间。CoreAllocatePages
会在后面详述。
/** /Dxe/Mem/Page.c **/
585 if (gMemoryTypeInformation[Index].NumberOfPages != 0)
589 Status = CoreAllocatePages (
590 AllocateAnyPages,
591 Type,
592 gMemoryTypeInformation[Index].NumberOfPages,
593 以上是关于UEFI.源码分析.DXE的内存服务.第一部分.初始化的主要内容,如果未能解决你的问题,请参考以下文章
UEFI.源码分析.DXE的异步事件服务.第一部分.事件驱动
UEFI.源码分析.DXE的异步事件服务.第一部分.事件驱动
UEFI.源码分析.DXE的异步事件服务.第二部分.任务优先级
UEFI.源码分析.DXE的异步事件服务.第二部分.任务优先级