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