]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c
MdeModulePkg: Add MemoryAttributesTable generation.
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Misc / MemoryAttributesTable.c
CommitLineData
98c4b005
JY
1/** @file\r
2 UEFI MemoryAttributesTable support\r
3\r
4Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>\r
5This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include <PiDxe.h>\r
16#include <Library/BaseLib.h>\r
17#include <Library/BaseMemoryLib.h>\r
18#include <Library/MemoryAllocationLib.h>\r
19#include <Library/UefiBootServicesTableLib.h>\r
20#include <Library/DxeServicesTableLib.h>\r
21#include <Library/DebugLib.h>\r
22#include <Library/UefiLib.h>\r
23\r
24#include <Guid/EventGroup.h>\r
25\r
26#include <Guid/MemoryAttributesTable.h>\r
27#include <Guid/PropertiesTable.h>\r
28\r
29#include "DxeMain.h"\r
30\r
31/**\r
32 This function for GetMemoryMap() with properties table capability.\r
33\r
34 It calls original GetMemoryMap() to get the original memory map information. Then\r
35 plus the additional memory map entries for PE Code/Data seperation.\r
36\r
37 @param MemoryMapSize A pointer to the size, in bytes, of the\r
38 MemoryMap buffer. On input, this is the size of\r
39 the buffer allocated by the caller. On output,\r
40 it is the size of the buffer returned by the\r
41 firmware if the buffer was large enough, or the\r
42 size of the buffer needed to contain the map if\r
43 the buffer was too small.\r
44 @param MemoryMap A pointer to the buffer in which firmware places\r
45 the current memory map.\r
46 @param MapKey A pointer to the location in which firmware\r
47 returns the key for the current memory map.\r
48 @param DescriptorSize A pointer to the location in which firmware\r
49 returns the size, in bytes, of an individual\r
50 EFI_MEMORY_DESCRIPTOR.\r
51 @param DescriptorVersion A pointer to the location in which firmware\r
52 returns the version number associated with the\r
53 EFI_MEMORY_DESCRIPTOR.\r
54\r
55 @retval EFI_SUCCESS The memory map was returned in the MemoryMap\r
56 buffer.\r
57 @retval EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small. The current\r
58 buffer size needed to hold the memory map is\r
59 returned in MemoryMapSize.\r
60 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
61\r
62**/\r
63EFI_STATUS\r
64EFIAPI\r
65CoreGetMemoryMapPropertiesTable (\r
66 IN OUT UINTN *MemoryMapSize,\r
67 IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,\r
68 OUT UINTN *MapKey,\r
69 OUT UINTN *DescriptorSize,\r
70 OUT UINT32 *DescriptorVersion\r
71 );\r
72\r
73extern EFI_PROPERTIES_TABLE mPropertiesTable;\r
74\r
75BOOLEAN mIsConstructingMemoryAttributesTable = FALSE;\r
76\r
77/**\r
78 Install MemoryAttributesTable.\r
79\r
80 @param[in] Event The Event this notify function registered to.\r
81 @param[in] Context Pointer to the context data registered to the Event.\r
82**/\r
83VOID\r
84EFIAPI\r
85InstallMemoryAttributesTable (\r
86 EFI_EVENT Event,\r
87 VOID *Context\r
88 )\r
89{\r
90 UINTN MemoryMapSize;\r
91 EFI_MEMORY_DESCRIPTOR *MemoryMap;\r
92 EFI_MEMORY_DESCRIPTOR *MemoryMapStart;\r
93 UINTN MapKey;\r
94 UINTN DescriptorSize;\r
95 UINT32 DescriptorVersion;\r
96 UINTN Index;\r
97 EFI_STATUS Status;\r
98 UINT32 RuntimeEntryCount;\r
99 EFI_MEMORY_ATTRIBUTES_TABLE *MemoryAttributesTable;\r
100 EFI_MEMORY_DESCRIPTOR *MemoryAttributesEntry;\r
101\r
102 if ((mPropertiesTable.MemoryProtectionAttribute & EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA) == 0) {\r
103 DEBUG ((EFI_D_VERBOSE, "MemoryProtectionAttribute NON_EXECUTABLE_PE_DATA is not set, "));\r
104 DEBUG ((EFI_D_VERBOSE, "because Runtime Driver Section Alignment is not %dK.\n", EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT >> 10));\r
105 return ;\r
106 }\r
107\r
108 mIsConstructingMemoryAttributesTable = TRUE;\r
109\r
110 MemoryMapSize = 0;\r
111 MemoryMap = NULL;\r
112 Status = CoreGetMemoryMapPropertiesTable (\r
113 &MemoryMapSize,\r
114 MemoryMap,\r
115 &MapKey,\r
116 &DescriptorSize,\r
117 &DescriptorVersion\r
118 );\r
119 ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
120\r
121 do {\r
122 MemoryMap = AllocatePool (MemoryMapSize);\r
123 ASSERT (MemoryMap != NULL);\r
124\r
125 Status = CoreGetMemoryMapPropertiesTable (\r
126 &MemoryMapSize,\r
127 MemoryMap,\r
128 &MapKey,\r
129 &DescriptorSize,\r
130 &DescriptorVersion\r
131 );\r
132 if (EFI_ERROR (Status)) {\r
133 FreePool (MemoryMap);\r
134 }\r
135 } while (Status == EFI_BUFFER_TOO_SMALL);\r
136\r
137 MemoryMapStart = MemoryMap;\r
138 RuntimeEntryCount = 0;\r
139 for (Index = 0; Index < MemoryMapSize/DescriptorSize; Index++) {\r
140 switch (MemoryMap->Type) {\r
141 case EfiRuntimeServicesCode:\r
142 case EfiRuntimeServicesData:\r
143 RuntimeEntryCount ++;\r
144 break;\r
145 }\r
146 MemoryMap = NEXT_MEMORY_DESCRIPTOR(MemoryMap, DescriptorSize);\r
147 }\r
148\r
149 //\r
150 // Allocate MemoryAttributesTable\r
151 //\r
152 MemoryAttributesTable = AllocatePool (sizeof(EFI_MEMORY_ATTRIBUTES_TABLE) + DescriptorSize * RuntimeEntryCount);\r
153 ASSERT (MemoryAttributesTable != NULL);\r
154 MemoryAttributesTable->Version = EFI_MEMORY_ATTRIBUTES_TABLE_VERSION;\r
155 MemoryAttributesTable->NumberOfEntries = RuntimeEntryCount;\r
156 MemoryAttributesTable->DescriptorSize = (UINT32)DescriptorSize;\r
157 MemoryAttributesTable->Reserved = 0;\r
158 DEBUG ((EFI_D_VERBOSE, "MemoryAttributesTable:\n"));\r
159 DEBUG ((EFI_D_VERBOSE, " Version - 0x%08x\n", MemoryAttributesTable->Version));\r
160 DEBUG ((EFI_D_VERBOSE, " NumberOfEntries - 0x%08x\n", MemoryAttributesTable->NumberOfEntries));\r
161 DEBUG ((EFI_D_VERBOSE, " DescriptorSize - 0x%08x\n", MemoryAttributesTable->DescriptorSize));\r
162 MemoryAttributesEntry = (EFI_MEMORY_DESCRIPTOR *)(MemoryAttributesTable + 1);\r
163 MemoryMap = MemoryMapStart;\r
164 for (Index = 0; Index < MemoryMapSize/DescriptorSize; Index++) {\r
165 switch (MemoryMap->Type) {\r
166 case EfiRuntimeServicesCode:\r
167 case EfiRuntimeServicesData:\r
168 CopyMem (MemoryAttributesEntry, MemoryMap, DescriptorSize);\r
169 MemoryAttributesEntry->Attribute &= (EFI_MEMORY_RO|EFI_MEMORY_XP|EFI_MEMORY_RUNTIME);\r
170 DEBUG ((EFI_D_VERBOSE, "Entry (0x%x)\n", MemoryAttributesEntry));\r
171 DEBUG ((EFI_D_VERBOSE, " Type - 0x%x\n", MemoryAttributesEntry->Type));\r
172 DEBUG ((EFI_D_VERBOSE, " PhysicalStart - 0x%016lx\n", MemoryAttributesEntry->PhysicalStart));\r
173 DEBUG ((EFI_D_VERBOSE, " VirtualStart - 0x%016lx\n", MemoryAttributesEntry->VirtualStart));\r
174 DEBUG ((EFI_D_VERBOSE, " NumberOfPages - 0x%016lx\n", MemoryAttributesEntry->NumberOfPages));\r
175 DEBUG ((EFI_D_VERBOSE, " Attribute - 0x%016lx\n", MemoryAttributesEntry->Attribute));\r
176 MemoryAttributesEntry = NEXT_MEMORY_DESCRIPTOR(MemoryAttributesEntry, DescriptorSize);\r
177 break;\r
178 }\r
179 MemoryMap = NEXT_MEMORY_DESCRIPTOR(MemoryMap, DescriptorSize);\r
180 }\r
181\r
182 Status = gBS->InstallConfigurationTable (&gEfiMemoryAttributesTableGuid, MemoryAttributesTable);\r
183 ASSERT_EFI_ERROR (Status);\r
184\r
185 mIsConstructingMemoryAttributesTable = FALSE;\r
186}\r
187\r
188/**\r
189 Initialize MemoryAttrubutesTable support.\r
190**/\r
191VOID\r
192EFIAPI\r
193CoreInitializeMemoryAttributesTable (\r
194 VOID\r
195 )\r
196{\r
197 EFI_STATUS Status;\r
198 EFI_EVENT ReadyToBootEvent;\r
199\r
200 //\r
201 // Construct the table at ReadyToBoot, because this should be\r
202 // last point to allocate RuntimeCode/RuntimeData.\r
203 //\r
204 Status = gBS->CreateEventEx (\r
205 EVT_NOTIFY_SIGNAL,\r
206 TPL_NOTIFY,\r
207 InstallMemoryAttributesTable,\r
208 NULL,\r
209 &gEfiEventReadyToBootGuid,\r
210 &ReadyToBootEvent\r
211 );\r
212 ASSERT_EFI_ERROR (Status);\r
213 return ;\r
214}\r