2 UEFI MemoryAttributesTable support
4 Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include <Library/BaseLib.h>
11 #include <Library/BaseMemoryLib.h>
12 #include <Library/MemoryAllocationLib.h>
13 #include <Library/UefiBootServicesTableLib.h>
14 #include <Library/DxeServicesTableLib.h>
15 #include <Library/DebugLib.h>
16 #include <Library/UefiLib.h>
18 #include <Guid/EventGroup.h>
20 #include <Guid/MemoryAttributesTable.h>
25 This function for GetMemoryMap() with properties table capability.
27 It calls original GetMemoryMap() to get the original memory map information. Then
28 plus the additional memory map entries for PE Code/Data seperation.
30 @param MemoryMapSize A pointer to the size, in bytes, of the
31 MemoryMap buffer. On input, this is the size of
32 the buffer allocated by the caller. On output,
33 it is the size of the buffer returned by the
34 firmware if the buffer was large enough, or the
35 size of the buffer needed to contain the map if
36 the buffer was too small.
37 @param MemoryMap A pointer to the buffer in which firmware places
38 the current memory map.
39 @param MapKey A pointer to the location in which firmware
40 returns the key for the current memory map.
41 @param DescriptorSize A pointer to the location in which firmware
42 returns the size, in bytes, of an individual
43 EFI_MEMORY_DESCRIPTOR.
44 @param DescriptorVersion A pointer to the location in which firmware
45 returns the version number associated with the
46 EFI_MEMORY_DESCRIPTOR.
48 @retval EFI_SUCCESS The memory map was returned in the MemoryMap
50 @retval EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small. The current
51 buffer size needed to hold the memory map is
52 returned in MemoryMapSize.
53 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
58 CoreGetMemoryMapWithSeparatedImageSection (
59 IN OUT UINTN
*MemoryMapSize
,
60 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
62 OUT UINTN
*DescriptorSize
,
63 OUT UINT32
*DescriptorVersion
66 BOOLEAN mMemoryAttributesTableEnable
= TRUE
;
67 EFI_MEMORY_ATTRIBUTES_TABLE
*mMemoryAttributesTable
= NULL
;
68 BOOLEAN mMemoryAttributesTableReadyToBoot
= FALSE
;
71 Install MemoryAttributesTable.
75 InstallMemoryAttributesTable (
80 EFI_MEMORY_DESCRIPTOR
*MemoryMap
;
81 EFI_MEMORY_DESCRIPTOR
*MemoryMapStart
;
84 UINT32 DescriptorVersion
;
87 UINT32 RuntimeEntryCount
;
88 EFI_MEMORY_ATTRIBUTES_TABLE
*MemoryAttributesTable
;
89 EFI_MEMORY_DESCRIPTOR
*MemoryAttributesEntry
;
91 if (gMemoryMapTerminated
) {
93 // Directly return after MemoryMap terminated.
98 if (!mMemoryAttributesTableEnable
) {
99 DEBUG ((DEBUG_VERBOSE
, "Cannot install Memory Attributes Table "));
100 DEBUG ((EFI_D_VERBOSE
, "because Runtime Driver Section Alignment is not %dK.\n", RUNTIME_PAGE_ALLOCATION_GRANULARITY
>> 10));
104 if (mMemoryAttributesTable
== NULL
) {
106 // InstallConfigurationTable here to occupy one entry for MemoryAttributesTable
107 // before GetMemoryMap below, as InstallConfigurationTable may allocate runtime
108 // memory for the new entry.
110 Status
= gBS
->InstallConfigurationTable (&gEfiMemoryAttributesTableGuid
, (VOID
*) (UINTN
) MAX_ADDRESS
);
111 ASSERT_EFI_ERROR (Status
);
116 Status
= CoreGetMemoryMapWithSeparatedImageSection (
123 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
126 MemoryMap
= AllocatePool (MemoryMapSize
);
127 ASSERT (MemoryMap
!= NULL
);
129 Status
= CoreGetMemoryMapWithSeparatedImageSection (
136 if (EFI_ERROR (Status
)) {
137 FreePool (MemoryMap
);
139 } while (Status
== EFI_BUFFER_TOO_SMALL
);
141 MemoryMapStart
= MemoryMap
;
142 RuntimeEntryCount
= 0;
143 for (Index
= 0; Index
< MemoryMapSize
/DescriptorSize
; Index
++) {
144 switch (MemoryMap
->Type
) {
145 case EfiRuntimeServicesCode
:
146 case EfiRuntimeServicesData
:
147 RuntimeEntryCount
++;
150 MemoryMap
= NEXT_MEMORY_DESCRIPTOR(MemoryMap
, DescriptorSize
);
154 // Allocate MemoryAttributesTable
156 MemoryAttributesTable
= AllocatePool (sizeof(EFI_MEMORY_ATTRIBUTES_TABLE
) + DescriptorSize
* RuntimeEntryCount
);
157 ASSERT (MemoryAttributesTable
!= NULL
);
158 MemoryAttributesTable
->Version
= EFI_MEMORY_ATTRIBUTES_TABLE_VERSION
;
159 MemoryAttributesTable
->NumberOfEntries
= RuntimeEntryCount
;
160 MemoryAttributesTable
->DescriptorSize
= (UINT32
)DescriptorSize
;
161 MemoryAttributesTable
->Reserved
= 0;
162 DEBUG ((EFI_D_VERBOSE
, "MemoryAttributesTable:\n"));
163 DEBUG ((EFI_D_VERBOSE
, " Version - 0x%08x\n", MemoryAttributesTable
->Version
));
164 DEBUG ((EFI_D_VERBOSE
, " NumberOfEntries - 0x%08x\n", MemoryAttributesTable
->NumberOfEntries
));
165 DEBUG ((EFI_D_VERBOSE
, " DescriptorSize - 0x%08x\n", MemoryAttributesTable
->DescriptorSize
));
166 MemoryAttributesEntry
= (EFI_MEMORY_DESCRIPTOR
*)(MemoryAttributesTable
+ 1);
167 MemoryMap
= MemoryMapStart
;
168 for (Index
= 0; Index
< MemoryMapSize
/DescriptorSize
; Index
++) {
169 switch (MemoryMap
->Type
) {
170 case EfiRuntimeServicesCode
:
171 case EfiRuntimeServicesData
:
172 CopyMem (MemoryAttributesEntry
, MemoryMap
, DescriptorSize
);
173 MemoryAttributesEntry
->Attribute
&= (EFI_MEMORY_RO
|EFI_MEMORY_XP
|EFI_MEMORY_RUNTIME
);
174 DEBUG ((EFI_D_VERBOSE
, "Entry (0x%x)\n", MemoryAttributesEntry
));
175 DEBUG ((EFI_D_VERBOSE
, " Type - 0x%x\n", MemoryAttributesEntry
->Type
));
176 DEBUG ((EFI_D_VERBOSE
, " PhysicalStart - 0x%016lx\n", MemoryAttributesEntry
->PhysicalStart
));
177 DEBUG ((EFI_D_VERBOSE
, " VirtualStart - 0x%016lx\n", MemoryAttributesEntry
->VirtualStart
));
178 DEBUG ((EFI_D_VERBOSE
, " NumberOfPages - 0x%016lx\n", MemoryAttributesEntry
->NumberOfPages
));
179 DEBUG ((EFI_D_VERBOSE
, " Attribute - 0x%016lx\n", MemoryAttributesEntry
->Attribute
));
180 MemoryAttributesEntry
= NEXT_MEMORY_DESCRIPTOR(MemoryAttributesEntry
, DescriptorSize
);
183 MemoryMap
= NEXT_MEMORY_DESCRIPTOR(MemoryMap
, DescriptorSize
);
185 MemoryMap
= MemoryMapStart
;
186 FreePool (MemoryMap
);
189 // Update configuratoin table for MemoryAttributesTable.
191 Status
= gBS
->InstallConfigurationTable (&gEfiMemoryAttributesTableGuid
, MemoryAttributesTable
);
192 ASSERT_EFI_ERROR (Status
);
194 if (mMemoryAttributesTable
!= NULL
) {
195 FreePool (mMemoryAttributesTable
);
197 mMemoryAttributesTable
= MemoryAttributesTable
;
201 Install MemoryAttributesTable on memory allocation.
203 @param[in] MemoryType EFI memory type.
206 InstallMemoryAttributesTableOnMemoryAllocation (
207 IN EFI_MEMORY_TYPE MemoryType
211 // Install MemoryAttributesTable after ReadyToBoot on runtime memory allocation.
213 if (mMemoryAttributesTableReadyToBoot
&&
214 ((MemoryType
== EfiRuntimeServicesCode
) || (MemoryType
== EfiRuntimeServicesData
))) {
215 InstallMemoryAttributesTable ();
220 Install MemoryAttributesTable on ReadyToBoot.
222 @param[in] Event The Event this notify function registered to.
223 @param[in] Context Pointer to the context data registered to the Event.
227 InstallMemoryAttributesTableOnReadyToBoot (
232 InstallMemoryAttributesTable ();
233 mMemoryAttributesTableReadyToBoot
= TRUE
;
237 Install initial MemoryAttributesTable on EndOfDxe.
238 Then SMM can consume this information.
240 @param[in] Event The Event this notify function registered to.
241 @param[in] Context Pointer to the context data registered to the Event.
245 InstallMemoryAttributesTableOnEndOfDxe (
250 InstallMemoryAttributesTable ();
254 Initialize MemoryAttrubutesTable support.
258 CoreInitializeMemoryAttributesTable (
263 EFI_EVENT ReadyToBootEvent
;
264 EFI_EVENT EndOfDxeEvent
;
267 // Construct the table at ReadyToBoot.
269 Status
= CoreCreateEventInternal (
272 InstallMemoryAttributesTableOnReadyToBoot
,
274 &gEfiEventReadyToBootGuid
,
277 ASSERT_EFI_ERROR (Status
);
280 // Construct the initial table at EndOfDxe,
281 // then SMM can consume this information.
282 // Use TPL_NOTIFY here, as such SMM code (TPL_CALLBACK)
285 Status
= CoreCreateEventInternal (
288 InstallMemoryAttributesTableOnEndOfDxe
,
290 &gEfiEndOfDxeEventGroupGuid
,
293 ASSERT_EFI_ERROR (Status
);