]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Gcd/Gcd.c
BaseTools: small cleanup
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Gcd / Gcd.c
CommitLineData
23c98c94 1/** @file\r
2 The file contains the GCD related services in the EFI Boot Services Table.\r
022c6d45 3 The GCD services are used to manage the memory and I/O regions that\r
e94a9ff7 4 are accessible to the CPU that is executing the DXE core.\r
504214c4 5\r
7328295c 6Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>\r
cd5ebaa0 7This program and the accompanying materials\r
23c98c94 8are licensed and made available under the terms and conditions of the BSD License\r
9which accompanies this distribution. The full text of the license may be found at\r
10http://opensource.org/licenses/bsd-license.php\r
11\r
12THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
28a00297 14\r
504214c4 15**/\r
28a00297 16\r
9c4ac31c 17#include "DxeMain.h"\r
ec90508b 18#include "Gcd.h"\r
7fef06af 19#include "Mem/HeapGuard.h"\r
28a00297 20\r
21#define MINIMUM_INITIAL_MEMORY_SIZE 0x10000\r
22\r
23#define MEMORY_ATTRIBUTE_MASK (EFI_RESOURCE_ATTRIBUTE_PRESENT | \\r
24 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \\r
25 EFI_RESOURCE_ATTRIBUTE_TESTED | \\r
26 EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED | \\r
27 EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED | \\r
28 EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED | \\r
6db13692 29 EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED | \\r
28a00297 30 EFI_RESOURCE_ATTRIBUTE_16_BIT_IO | \\r
31 EFI_RESOURCE_ATTRIBUTE_32_BIT_IO | \\r
a671a012
LG
32 EFI_RESOURCE_ATTRIBUTE_64_BIT_IO | \\r
33 EFI_RESOURCE_ATTRIBUTE_PERSISTENT )\r
28a00297 34\r
35#define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \\r
36 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \\r
37 EFI_RESOURCE_ATTRIBUTE_TESTED )\r
38\r
39#define INITIALIZED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \\r
40 EFI_RESOURCE_ATTRIBUTE_INITIALIZED )\r
41\r
42#define PRESENT_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT)\r
43\r
14dde9e9
JW
44#define EXCLUSIVE_MEMORY_ATTRIBUTES (EFI_MEMORY_UC | EFI_MEMORY_WC | \\r
45 EFI_MEMORY_WT | EFI_MEMORY_WB | \\r
46 EFI_MEMORY_WP | EFI_MEMORY_UCE)\r
47\r
48#define NONEXCLUSIVE_MEMORY_ATTRIBUTES (EFI_MEMORY_XP | EFI_MEMORY_RP | \\r
49 EFI_MEMORY_RO)\r
50\r
28a00297 51//\r
52// Module Variables\r
53//\r
54EFI_LOCK mGcdMemorySpaceLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);\r
55EFI_LOCK mGcdIoSpaceLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);\r
56LIST_ENTRY mGcdMemorySpaceMap = INITIALIZE_LIST_HEAD_VARIABLE (mGcdMemorySpaceMap);\r
57LIST_ENTRY mGcdIoSpaceMap = INITIALIZE_LIST_HEAD_VARIABLE (mGcdIoSpaceMap);\r
58\r
59EFI_GCD_MAP_ENTRY mGcdMemorySpaceMapEntryTemplate = {\r
60 EFI_GCD_MAP_SIGNATURE,\r
022c6d45 61 {\r
e94a9ff7 62 NULL,\r
63 NULL\r
64 },\r
28a00297 65 0,\r
66 0,\r
67 0,\r
68 0,\r
69 EfiGcdMemoryTypeNonExistent,\r
70 (EFI_GCD_IO_TYPE) 0,\r
71 NULL,\r
72 NULL\r
73};\r
74\r
75EFI_GCD_MAP_ENTRY mGcdIoSpaceMapEntryTemplate = {\r
76 EFI_GCD_MAP_SIGNATURE,\r
e94a9ff7 77 {\r
78 NULL,\r
79 NULL\r
80 },\r
28a00297 81 0,\r
82 0,\r
83 0,\r
84 0,\r
85 (EFI_GCD_MEMORY_TYPE) 0,\r
86 EfiGcdIoTypeNonExistent,\r
87 NULL,\r
88 NULL\r
89};\r
90\r
91GCD_ATTRIBUTE_CONVERSION_ENTRY mAttributeConversionTable[] = {\r
74705ca5
SZ
92 { EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE, EFI_MEMORY_UC, TRUE },\r
93 { EFI_RESOURCE_ATTRIBUTE_UNCACHED_EXPORTED, EFI_MEMORY_UCE, TRUE },\r
94 { EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE, EFI_MEMORY_WC, TRUE },\r
95 { EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE, EFI_MEMORY_WT, TRUE },\r
96 { EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE, EFI_MEMORY_WB, TRUE },\r
97 { EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE, EFI_MEMORY_RP, TRUE },\r
98 { EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTABLE, EFI_MEMORY_WP, TRUE },\r
99 { EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE, EFI_MEMORY_XP, TRUE },\r
100 { EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE, EFI_MEMORY_RO, TRUE },\r
101 { EFI_RESOURCE_ATTRIBUTE_PRESENT, EFI_MEMORY_PRESENT, FALSE },\r
102 { EFI_RESOURCE_ATTRIBUTE_INITIALIZED, EFI_MEMORY_INITIALIZED, FALSE },\r
103 { EFI_RESOURCE_ATTRIBUTE_TESTED, EFI_MEMORY_TESTED, FALSE },\r
104 { EFI_RESOURCE_ATTRIBUTE_PERSISTABLE, EFI_MEMORY_NV, TRUE },\r
105 { EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE, EFI_MEMORY_MORE_RELIABLE, TRUE },\r
106 { 0, 0, FALSE }\r
28a00297 107};\r
108\r
f9d1f97c 109///\r
110/// Lookup table used to print GCD Memory Space Map\r
111///\r
112GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mGcdMemoryTypeNames[] = {\r
113 "NonExist ", // EfiGcdMemoryTypeNonExistent\r
114 "Reserved ", // EfiGcdMemoryTypeReserved\r
115 "SystemMem", // EfiGcdMemoryTypeSystemMemory\r
116 "MMIO ", // EfiGcdMemoryTypeMemoryMappedIo\r
35ac962b 117 "PersisMem", // EfiGcdMemoryTypePersistent\r
74705ca5 118 "MoreRelia", // EfiGcdMemoryTypeMoreReliable\r
f9d1f97c 119 "Unknown " // EfiGcdMemoryTypeMaximum\r
120};\r
121\r
122///\r
123/// Lookup table used to print GCD I/O Space Map\r
124///\r
125GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mGcdIoTypeNames[] = {\r
126 "NonExist", // EfiGcdIoTypeNonExistent\r
127 "Reserved", // EfiGcdIoTypeReserved\r
128 "I/O ", // EfiGcdIoTypeIo\r
129 "Unknown " // EfiGcdIoTypeMaximum \r
130};\r
131\r
132///\r
133/// Lookup table used to print GCD Allocation Types\r
134///\r
135GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mGcdAllocationTypeNames[] = {\r
136 "AnySearchBottomUp ", // EfiGcdAllocateAnySearchBottomUp\r
137 "MaxAddressSearchBottomUp ", // EfiGcdAllocateMaxAddressSearchBottomUp\r
138 "AtAddress ", // EfiGcdAllocateAddress\r
139 "AnySearchTopDown ", // EfiGcdAllocateAnySearchTopDown\r
140 "MaxAddressSearchTopDown ", // EfiGcdAllocateMaxAddressSearchTopDown\r
141 "Unknown " // EfiGcdMaxAllocateType\r
142};\r
143\r
144/**\r
145 Dump the entire contents if the GCD Memory Space Map using DEBUG() macros when\r
146 PcdDebugPrintErrorLevel has the DEBUG_GCD bit set.\r
147\r
aa927cae 148 @param InitialMap TRUE if the initial GCD Memory Map is being dumped. Otherwise, FALSE.\r
149 \r
f9d1f97c 150**/\r
151VOID\r
152EFIAPI\r
153CoreDumpGcdMemorySpaceMap (\r
aa927cae 154 BOOLEAN InitialMap\r
f9d1f97c 155 )\r
156{\r
aa927cae 157 DEBUG_CODE (\r
158 EFI_STATUS Status;\r
159 UINTN NumberOfDescriptors;\r
160 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;\r
161 UINTN Index;\r
162 \r
163 Status = CoreGetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);\r
3d267c70 164 ASSERT (Status == EFI_SUCCESS && MemorySpaceMap != NULL);\r
aa927cae 165\r
166 if (InitialMap) {\r
167 DEBUG ((DEBUG_GCD, "GCD:Initial GCD Memory Space Map\n"));\r
168 }\r
169 DEBUG ((DEBUG_GCD, "GCDMemType Range Capabilities Attributes \n"));\r
170 DEBUG ((DEBUG_GCD, "========== ================================= ================ ================\n"));\r
171 for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
172 DEBUG ((DEBUG_GCD, "%a %016lx-%016lx %016lx %016lx%c\n", \r
173 mGcdMemoryTypeNames[MIN (MemorySpaceMap[Index].GcdMemoryType, EfiGcdMemoryTypeMaximum)],\r
174 MemorySpaceMap[Index].BaseAddress, \r
175 MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - 1,\r
176 MemorySpaceMap[Index].Capabilities, \r
177 MemorySpaceMap[Index].Attributes,\r
178 MemorySpaceMap[Index].ImageHandle == NULL ? ' ' : '*'\r
179 ));\r
180 }\r
181 DEBUG ((DEBUG_GCD, "\n"));\r
182 FreePool (MemorySpaceMap);\r
183 );\r
f9d1f97c 184}\r
185\r
186/**\r
187 Dump the entire contents if the GCD I/O Space Map using DEBUG() macros when \r
188 PcdDebugPrintErrorLevel has the DEBUG_GCD bit set.\r
189\r
aa927cae 190 @param InitialMap TRUE if the initial GCD I/O Map is being dumped. Otherwise, FALSE.\r
191 \r
f9d1f97c 192**/\r
193VOID\r
194EFIAPI\r
195CoreDumpGcdIoSpaceMap (\r
aa927cae 196 BOOLEAN InitialMap\r
f9d1f97c 197 )\r
198{\r
aa927cae 199 DEBUG_CODE (\r
200 EFI_STATUS Status;\r
201 UINTN NumberOfDescriptors;\r
202 EFI_GCD_IO_SPACE_DESCRIPTOR *IoSpaceMap;\r
203 UINTN Index;\r
204 \r
205 Status = CoreGetIoSpaceMap (&NumberOfDescriptors, &IoSpaceMap);\r
3d267c70 206 ASSERT (Status == EFI_SUCCESS && IoSpaceMap != NULL);\r
aa927cae 207 \r
208 if (InitialMap) {\r
209 DEBUG ((DEBUG_GCD, "GCD:Initial GCD I/O Space Map\n"));\r
210 } \r
211 \r
212 DEBUG ((DEBUG_GCD, "GCDIoType Range \n"));\r
213 DEBUG ((DEBUG_GCD, "========== =================================\n"));\r
214 for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
215 DEBUG ((DEBUG_GCD, "%a %016lx-%016lx%c\n", \r
216 mGcdIoTypeNames[MIN (IoSpaceMap[Index].GcdIoType, EfiGcdIoTypeMaximum)],\r
217 IoSpaceMap[Index].BaseAddress, \r
218 IoSpaceMap[Index].BaseAddress + IoSpaceMap[Index].Length - 1,\r
219 IoSpaceMap[Index].ImageHandle == NULL ? ' ' : '*'\r
220 ));\r
221 }\r
222 DEBUG ((DEBUG_GCD, "\n"));\r
223 FreePool (IoSpaceMap);\r
224 );\r
f9d1f97c 225}\r
226 \r
d12a2ecb 227/**\r
228 Validate resource descriptor HOB's attributes.\r
229\r
230 If Attributes includes some memory resource's settings, it should include \r
231 the corresponding capabilites also.\r
f9d1f97c 232\r
d12a2ecb 233 @param Attributes Resource descriptor HOB attributes.\r
234\r
235**/\r
236VOID\r
237CoreValidateResourceDescriptorHobAttributes (\r
238 IN UINT64 Attributes\r
239 )\r
240{\r
241 ASSERT (((Attributes & EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED) == 0) ||\r
242 ((Attributes & EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE) != 0));\r
243 ASSERT (((Attributes & EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED) == 0) ||\r
244 ((Attributes & EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTABLE) != 0));\r
245 ASSERT (((Attributes & EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED) == 0) ||\r
246 ((Attributes & EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE) != 0));\r
6db13692
SZ
247 ASSERT (((Attributes & EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED) == 0) ||\r
248 ((Attributes & EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE) != 0));\r
a671a012
LG
249 ASSERT (((Attributes & EFI_RESOURCE_ATTRIBUTE_PERSISTENT) == 0) ||\r
250 ((Attributes & EFI_RESOURCE_ATTRIBUTE_PERSISTABLE) != 0));\r
d12a2ecb 251}\r
162ed594 252\r
253/**\r
254 Acquire memory lock on mGcdMemorySpaceLock.\r
255\r
256**/\r
28a00297 257VOID\r
258CoreAcquireGcdMemoryLock (\r
259 VOID\r
260 )\r
28a00297 261{\r
262 CoreAcquireLock (&mGcdMemorySpaceLock);\r
263}\r
264\r
265\r
162ed594 266\r
267/**\r
268 Release memory lock on mGcdMemorySpaceLock.\r
269\r
270**/\r
28a00297 271VOID\r
272CoreReleaseGcdMemoryLock (\r
273 VOID\r
274 )\r
28a00297 275{\r
276 CoreReleaseLock (&mGcdMemorySpaceLock);\r
277}\r
278\r
279\r
162ed594 280\r
281/**\r
282 Acquire memory lock on mGcdIoSpaceLock.\r
283\r
284**/\r
28a00297 285VOID\r
286CoreAcquireGcdIoLock (\r
287 VOID\r
288 )\r
28a00297 289{\r
290 CoreAcquireLock (&mGcdIoSpaceLock);\r
291}\r
292\r
162ed594 293\r
294/**\r
295 Release memory lock on mGcdIoSpaceLock.\r
296\r
297**/\r
28a00297 298VOID\r
299CoreReleaseGcdIoLock (\r
300 VOID\r
301 )\r
28a00297 302{\r
303 CoreReleaseLock (&mGcdIoSpaceLock);\r
304}\r
305\r
306\r
307\r
308//\r
309// GCD Initialization Worker Functions\r
310//\r
162ed594 311/**\r
312 Aligns a value to the specified boundary.\r
313\r
022c6d45 314 @param Value 64 bit value to align\r
315 @param Alignment Log base 2 of the boundary to align Value to\r
316 @param RoundUp TRUE if Value is to be rounded up to the nearest\r
317 aligned boundary. FALSE is Value is to be\r
318 rounded down to the nearest aligned boundary.\r
162ed594 319\r
320 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.\r
321\r
322**/\r
28a00297 323UINT64\r
324AlignValue (\r
325 IN UINT64 Value,\r
326 IN UINTN Alignment,\r
327 IN BOOLEAN RoundUp\r
328 )\r
28a00297 329{\r
330 UINT64 AlignmentMask;\r
331\r
332 AlignmentMask = LShiftU64 (1, Alignment) - 1;\r
333 if (RoundUp) {\r
334 Value += AlignmentMask;\r
335 }\r
336 return Value & (~AlignmentMask);\r
337}\r
338\r
28a00297 339\r
162ed594 340/**\r
28a00297 341 Aligns address to the page boundary.\r
342\r
022c6d45 343 @param Value 64 bit address to align\r
28a00297 344\r
162ed594 345 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.\r
28a00297 346\r
162ed594 347**/\r
28a00297 348UINT64\r
162ed594 349PageAlignAddress (\r
28a00297 350 IN UINT64 Value\r
351 )\r
162ed594 352{\r
353 return AlignValue (Value, EFI_PAGE_SHIFT, TRUE);\r
354}\r
28a00297 355\r
28a00297 356\r
162ed594 357/**\r
28a00297 358 Aligns length to the page boundary.\r
359\r
022c6d45 360 @param Value 64 bit length to align\r
28a00297 361\r
162ed594 362 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.\r
28a00297 363\r
162ed594 364**/\r
162ed594 365UINT64\r
366PageAlignLength (\r
367 IN UINT64 Value\r
368 )\r
28a00297 369{\r
370 return AlignValue (Value, EFI_PAGE_SHIFT, FALSE);\r
371}\r
372\r
373//\r
374// GCD Memory Space Worker Functions\r
375//\r
162ed594 376\r
377/**\r
378 Allocate pool for two entries.\r
379\r
022c6d45 380 @param TopEntry An entry of GCD map\r
381 @param BottomEntry An entry of GCD map\r
162ed594 382\r
022c6d45 383 @retval EFI_OUT_OF_RESOURCES No enough buffer to be allocated.\r
162ed594 384 @retval EFI_SUCCESS Both entries successfully allocated.\r
385\r
386**/\r
28a00297 387EFI_STATUS\r
388CoreAllocateGcdMapEntry (\r
389 IN OUT EFI_GCD_MAP_ENTRY **TopEntry,\r
390 IN OUT EFI_GCD_MAP_ENTRY **BottomEntry\r
391 )\r
28a00297 392{\r
7fef06af
JW
393 //\r
394 // Set to mOnGuarding to TRUE before memory allocation. This will make sure\r
395 // that the entry memory is not "guarded" by HeapGuard. Otherwise it might\r
396 // cause problem when it's freed (if HeapGuard is enabled).\r
397 //\r
398 mOnGuarding = TRUE;\r
9c4ac31c 399 *TopEntry = AllocateZeroPool (sizeof (EFI_GCD_MAP_ENTRY));\r
7fef06af 400 mOnGuarding = FALSE;\r
28a00297 401 if (*TopEntry == NULL) {\r
402 return EFI_OUT_OF_RESOURCES;\r
403 }\r
404\r
7fef06af 405 mOnGuarding = TRUE;\r
9c4ac31c 406 *BottomEntry = AllocateZeroPool (sizeof (EFI_GCD_MAP_ENTRY));\r
7fef06af 407 mOnGuarding = FALSE;\r
28a00297 408 if (*BottomEntry == NULL) {\r
409 CoreFreePool (*TopEntry);\r
410 return EFI_OUT_OF_RESOURCES;\r
411 }\r
412\r
413 return EFI_SUCCESS;\r
414}\r
415\r
162ed594 416\r
417/**\r
418 Internal function. Inserts a new descriptor into a sorted list\r
419\r
022c6d45 420 @param Link The linked list to insert the range BaseAddress\r
421 and Length into\r
422 @param Entry A pointer to the entry that is inserted\r
423 @param BaseAddress The base address of the new range\r
424 @param Length The length of the new range in bytes\r
425 @param TopEntry Top pad entry to insert if needed.\r
426 @param BottomEntry Bottom pad entry to insert if needed.\r
162ed594 427\r
428 @retval EFI_SUCCESS The new range was inserted into the linked list\r
429\r
430**/\r
28a00297 431EFI_STATUS\r
432CoreInsertGcdMapEntry (\r
433 IN LIST_ENTRY *Link,\r
434 IN EFI_GCD_MAP_ENTRY *Entry,\r
435 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
436 IN UINT64 Length,\r
437 IN EFI_GCD_MAP_ENTRY *TopEntry,\r
438 IN EFI_GCD_MAP_ENTRY *BottomEntry\r
439 )\r
28a00297 440{\r
441 ASSERT (Length != 0);\r
28a00297 442\r
443 if (BaseAddress > Entry->BaseAddress) {\r
f75316c3 444 ASSERT (BottomEntry->Signature == 0);\r
445\r
28a00297 446 CopyMem (BottomEntry, Entry, sizeof (EFI_GCD_MAP_ENTRY));\r
447 Entry->BaseAddress = BaseAddress;\r
448 BottomEntry->EndAddress = BaseAddress - 1;\r
449 InsertTailList (Link, &BottomEntry->Link);\r
022c6d45 450 }\r
28a00297 451\r
452 if ((BaseAddress + Length - 1) < Entry->EndAddress) {\r
f75316c3 453 ASSERT (TopEntry->Signature == 0);\r
454\r
28a00297 455 CopyMem (TopEntry, Entry, sizeof (EFI_GCD_MAP_ENTRY));\r
456 TopEntry->BaseAddress = BaseAddress + Length;\r
457 Entry->EndAddress = BaseAddress + Length - 1;\r
458 InsertHeadList (Link, &TopEntry->Link);\r
459 }\r
460\r
461 return EFI_SUCCESS;\r
462}\r
463\r
162ed594 464\r
465/**\r
e94a9ff7 466 Merge the Gcd region specified by Link and its adjacent entry.\r
162ed594 467\r
022c6d45 468 @param Link Specify the entry to be merged (with its\r
469 adjacent entry).\r
470 @param Forward Direction (forward or backward).\r
471 @param Map Boundary.\r
162ed594 472\r
022c6d45 473 @retval EFI_SUCCESS Successfully returned.\r
162ed594 474 @retval EFI_UNSUPPORTED These adjacent regions could not merge.\r
475\r
476**/\r
28a00297 477EFI_STATUS\r
478CoreMergeGcdMapEntry (\r
479 IN LIST_ENTRY *Link,\r
480 IN BOOLEAN Forward,\r
481 IN LIST_ENTRY *Map\r
482 )\r
28a00297 483{\r
484 LIST_ENTRY *AdjacentLink;\r
485 EFI_GCD_MAP_ENTRY *Entry;\r
486 EFI_GCD_MAP_ENTRY *AdjacentEntry;\r
487\r
488 //\r
489 // Get adjacent entry\r
490 //\r
491 if (Forward) {\r
492 AdjacentLink = Link->ForwardLink;\r
493 } else {\r
494 AdjacentLink = Link->BackLink;\r
495 }\r
496\r
497 //\r
498 // If AdjacentLink is the head of the list, then no merge can be performed\r
499 //\r
500 if (AdjacentLink == Map) {\r
501 return EFI_SUCCESS;\r
502 }\r
503\r
504 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
505 AdjacentEntry = CR (AdjacentLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
506\r
507 if (Entry->Capabilities != AdjacentEntry->Capabilities) {\r
508 return EFI_UNSUPPORTED;\r
509 }\r
510 if (Entry->Attributes != AdjacentEntry->Attributes) {\r
511 return EFI_UNSUPPORTED;\r
512 }\r
513 if (Entry->GcdMemoryType != AdjacentEntry->GcdMemoryType) {\r
514 return EFI_UNSUPPORTED;\r
515 }\r
516 if (Entry->GcdIoType != AdjacentEntry->GcdIoType) {\r
517 return EFI_UNSUPPORTED;\r
518 }\r
519 if (Entry->ImageHandle != AdjacentEntry->ImageHandle) {\r
520 return EFI_UNSUPPORTED;\r
521 }\r
522 if (Entry->DeviceHandle != AdjacentEntry->DeviceHandle) {\r
523 return EFI_UNSUPPORTED;\r
524 }\r
525\r
526 if (Forward) {\r
527 Entry->EndAddress = AdjacentEntry->EndAddress;\r
528 } else {\r
529 Entry->BaseAddress = AdjacentEntry->BaseAddress;\r
530 }\r
531 RemoveEntryList (AdjacentLink);\r
532 CoreFreePool (AdjacentEntry);\r
533\r
534 return EFI_SUCCESS;\r
535}\r
536\r
162ed594 537\r
538/**\r
539 Merge adjacent entries on total chain.\r
540\r
022c6d45 541 @param TopEntry Top entry of GCD map.\r
542 @param BottomEntry Bottom entry of GCD map.\r
543 @param StartLink Start link of the list for this loop.\r
544 @param EndLink End link of the list for this loop.\r
545 @param Map Boundary.\r
162ed594 546\r
547 @retval EFI_SUCCESS GCD map successfully cleaned up.\r
548\r
549**/\r
28a00297 550EFI_STATUS\r
551CoreCleanupGcdMapEntry (\r
552 IN EFI_GCD_MAP_ENTRY *TopEntry,\r
553 IN EFI_GCD_MAP_ENTRY *BottomEntry,\r
554 IN LIST_ENTRY *StartLink,\r
555 IN LIST_ENTRY *EndLink,\r
556 IN LIST_ENTRY *Map\r
557 )\r
28a00297 558{\r
559 LIST_ENTRY *Link;\r
560\r
561 if (TopEntry->Signature == 0) {\r
562 CoreFreePool (TopEntry);\r
563 }\r
564 if (BottomEntry->Signature == 0) {\r
565 CoreFreePool (BottomEntry);\r
566 }\r
567\r
568 Link = StartLink;\r
569 while (Link != EndLink->ForwardLink) {\r
570 CoreMergeGcdMapEntry (Link, FALSE, Map);\r
571 Link = Link->ForwardLink;\r
572 }\r
573 CoreMergeGcdMapEntry (EndLink, TRUE, Map);\r
574\r
575 return EFI_SUCCESS;\r
576}\r
577\r
162ed594 578\r
579/**\r
580 Search a segment of memory space in GCD map. The result is a range of GCD entry list.\r
581\r
022c6d45 582 @param BaseAddress The start address of the segment.\r
583 @param Length The length of the segment.\r
584 @param StartLink The first GCD entry involves this segment of\r
585 memory space.\r
586 @param EndLink The first GCD entry involves this segment of\r
587 memory space.\r
588 @param Map Points to the start entry to search.\r
162ed594 589\r
022c6d45 590 @retval EFI_SUCCESS Successfully found the entry.\r
162ed594 591 @retval EFI_NOT_FOUND Not found.\r
592\r
593**/\r
28a00297 594EFI_STATUS\r
595CoreSearchGcdMapEntry (\r
596 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
597 IN UINT64 Length,\r
598 OUT LIST_ENTRY **StartLink,\r
599 OUT LIST_ENTRY **EndLink,\r
600 IN LIST_ENTRY *Map\r
601 )\r
28a00297 602{\r
603 LIST_ENTRY *Link;\r
604 EFI_GCD_MAP_ENTRY *Entry;\r
605\r
606 ASSERT (Length != 0);\r
607\r
608 *StartLink = NULL;\r
609 *EndLink = NULL;\r
610\r
611 Link = Map->ForwardLink;\r
612 while (Link != Map) {\r
613 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
614 if (BaseAddress >= Entry->BaseAddress && BaseAddress <= Entry->EndAddress) {\r
615 *StartLink = Link;\r
616 }\r
617 if (*StartLink != NULL) {\r
022c6d45 618 if ((BaseAddress + Length - 1) >= Entry->BaseAddress &&\r
28a00297 619 (BaseAddress + Length - 1) <= Entry->EndAddress ) {\r
620 *EndLink = Link;\r
621 return EFI_SUCCESS;\r
622 }\r
623 }\r
624 Link = Link->ForwardLink;\r
625 }\r
e94a9ff7 626\r
28a00297 627 return EFI_NOT_FOUND;\r
628}\r
629\r
28a00297 630\r
162ed594 631/**\r
28a00297 632 Count the amount of GCD map entries.\r
633\r
022c6d45 634 @param Map Points to the start entry to do the count loop.\r
28a00297 635\r
162ed594 636 @return The count.\r
28a00297 637\r
162ed594 638**/\r
162ed594 639UINTN\r
640CoreCountGcdMapEntry (\r
641 IN LIST_ENTRY *Map\r
642 )\r
28a00297 643{\r
644 UINTN Count;\r
645 LIST_ENTRY *Link;\r
646\r
647 Count = 0;\r
648 Link = Map->ForwardLink;\r
649 while (Link != Map) {\r
650 Count++;\r
651 Link = Link->ForwardLink;\r
652 }\r
022c6d45 653\r
28a00297 654 return Count;\r
655}\r
656\r
657\r
28a00297 658\r
162ed594 659/**\r
28a00297 660 Return the memory attribute specified by Attributes\r
661\r
022c6d45 662 @param Attributes A num with some attribute bits on.\r
28a00297 663\r
162ed594 664 @return The enum value of memory attribute.\r
28a00297 665\r
162ed594 666**/\r
162ed594 667UINT64\r
668ConverToCpuArchAttributes (\r
669 UINT64 Attributes\r
23c98c94 670 )\r
28a00297 671{\r
14dde9e9 672 UINT64 CpuArchAttributes;\r
28a00297 673\r
14dde9e9 674 CpuArchAttributes = Attributes & NONEXCLUSIVE_MEMORY_ATTRIBUTES;\r
28a00297 675\r
14dde9e9
JW
676 if ( (Attributes & EFI_MEMORY_UC) == EFI_MEMORY_UC) {\r
677 CpuArchAttributes |= EFI_MEMORY_UC;\r
678 } else if ( (Attributes & EFI_MEMORY_WC ) == EFI_MEMORY_WC) {\r
679 CpuArchAttributes |= EFI_MEMORY_WC;\r
680 } else if ( (Attributes & EFI_MEMORY_WT ) == EFI_MEMORY_WT) {\r
681 CpuArchAttributes |= EFI_MEMORY_WT;\r
682 } else if ( (Attributes & EFI_MEMORY_WB) == EFI_MEMORY_WB) {\r
683 CpuArchAttributes |= EFI_MEMORY_WB;\r
684 } else if ( (Attributes & EFI_MEMORY_UCE) == EFI_MEMORY_UCE) {\r
685 CpuArchAttributes |= EFI_MEMORY_UCE;\r
686 } else if ( (Attributes & EFI_MEMORY_WP) == EFI_MEMORY_WP) {\r
687 CpuArchAttributes |= EFI_MEMORY_WP;\r
28a00297 688 }\r
689\r
14dde9e9 690 return CpuArchAttributes;\r
28a00297 691}\r
692\r
162ed594 693\r
694/**\r
695 Do operation on a segment of memory space specified (add, free, remove, change attribute ...).\r
696\r
022c6d45 697 @param Operation The type of the operation\r
698 @param GcdMemoryType Additional information for the operation\r
699 @param GcdIoType Additional information for the operation\r
700 @param BaseAddress Start address of the segment\r
701 @param Length length of the segment\r
702 @param Capabilities The alterable attributes of a newly added entry\r
703 @param Attributes The attributes needs to be set\r
704\r
705 @retval EFI_INVALID_PARAMETER Length is 0 or address (length) not aligned when\r
706 setting attribute.\r
707 @retval EFI_SUCCESS Action successfully done.\r
708 @retval EFI_UNSUPPORTED Could not find the proper descriptor on this\r
709 segment or set an upsupported attribute.\r
710 @retval EFI_ACCESS_DENIED Operate on an space non-exist or is used for an\r
711 image.\r
712 @retval EFI_NOT_FOUND Free a non-using space or remove a non-exist\r
713 space, and so on.\r
162ed594 714 @retval EFI_OUT_OF_RESOURCES No buffer could be allocated.\r
fc8ff20f 715 @retval EFI_NOT_AVAILABLE_YET The attributes cannot be set because CPU architectural protocol\r
716 is not available yet.\r
162ed594 717**/\r
28a00297 718EFI_STATUS\r
719CoreConvertSpace (\r
720 IN UINTN Operation,\r
721 IN EFI_GCD_MEMORY_TYPE GcdMemoryType,\r
722 IN EFI_GCD_IO_TYPE GcdIoType,\r
723 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
724 IN UINT64 Length,\r
725 IN UINT64 Capabilities,\r
726 IN UINT64 Attributes\r
727 )\r
28a00297 728{\r
729 EFI_STATUS Status;\r
730 LIST_ENTRY *Map;\r
731 LIST_ENTRY *Link;\r
732 EFI_GCD_MAP_ENTRY *Entry;\r
733 EFI_GCD_MAP_ENTRY *TopEntry;\r
734 EFI_GCD_MAP_ENTRY *BottomEntry;\r
735 LIST_ENTRY *StartLink;\r
736 LIST_ENTRY *EndLink;\r
f9d1f97c 737 UINT64 CpuArchAttributes;\r
28a00297 738\r
739 if (Length == 0) {\r
aa927cae 740 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER));\r
28a00297 741 return EFI_INVALID_PARAMETER;\r
742 }\r
743\r
744 Map = NULL;\r
71f68914 745 if ((Operation & GCD_MEMORY_SPACE_OPERATION) != 0) {\r
28a00297 746 CoreAcquireGcdMemoryLock ();\r
747 Map = &mGcdMemorySpaceMap;\r
fbbb4211 748 } else if ((Operation & GCD_IO_SPACE_OPERATION) != 0) {\r
28a00297 749 CoreAcquireGcdIoLock ();\r
750 Map = &mGcdIoSpaceMap;\r
fbbb4211 751 } else {\r
752 ASSERT (FALSE);\r
28a00297 753 }\r
754\r
755 //\r
756 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length\r
757 //\r
758 Status = CoreSearchGcdMapEntry (BaseAddress, Length, &StartLink, &EndLink, Map);\r
759 if (EFI_ERROR (Status)) {\r
760 Status = EFI_UNSUPPORTED;\r
761\r
762 goto Done;\r
763 }\r
d2fbaaab 764 ASSERT (StartLink != NULL && EndLink != NULL);\r
28a00297 765\r
766 //\r
767 // Verify that the list of descriptors are unallocated non-existent memory.\r
768 //\r
769 Link = StartLink;\r
770 while (Link != EndLink->ForwardLink) {\r
771 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
772 switch (Operation) {\r
773 //\r
774 // Add operations\r
775 //\r
776 case GCD_ADD_MEMORY_OPERATION:\r
777 if (Entry->GcdMemoryType != EfiGcdMemoryTypeNonExistent ||\r
778 Entry->ImageHandle != NULL ) {\r
779 Status = EFI_ACCESS_DENIED;\r
780 goto Done;\r
781 }\r
782 break;\r
783 case GCD_ADD_IO_OPERATION:\r
784 if (Entry->GcdIoType != EfiGcdIoTypeNonExistent ||\r
785 Entry->ImageHandle != NULL ) {\r
786 Status = EFI_ACCESS_DENIED;\r
787 goto Done;\r
788 }\r
789 break;\r
790 //\r
791 // Free operations\r
792 //\r
793 case GCD_FREE_MEMORY_OPERATION:\r
794 case GCD_FREE_IO_OPERATION:\r
795 if (Entry->ImageHandle == NULL) {\r
796 Status = EFI_NOT_FOUND;\r
797 goto Done;\r
798 }\r
799 break;\r
800 //\r
801 // Remove operations\r
802 //\r
803 case GCD_REMOVE_MEMORY_OPERATION:\r
804 if (Entry->GcdMemoryType == EfiGcdMemoryTypeNonExistent) {\r
805 Status = EFI_NOT_FOUND;\r
806 goto Done;\r
807 }\r
808 if (Entry->ImageHandle != NULL) {\r
809 Status = EFI_ACCESS_DENIED;\r
810 goto Done;\r
811 }\r
812 break;\r
813 case GCD_REMOVE_IO_OPERATION:\r
814 if (Entry->GcdIoType == EfiGcdIoTypeNonExistent) {\r
815 Status = EFI_NOT_FOUND;\r
816 goto Done;\r
817 }\r
818 if (Entry->ImageHandle != NULL) {\r
819 Status = EFI_ACCESS_DENIED;\r
820 goto Done;\r
821 }\r
822 break;\r
823 //\r
771ee501 824 // Set attributes operation\r
28a00297 825 //\r
826 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION:\r
71f68914 827 if ((Attributes & EFI_MEMORY_RUNTIME) != 0) {\r
28a00297 828 if ((BaseAddress & EFI_PAGE_MASK) != 0 || (Length & EFI_PAGE_MASK) != 0) {\r
829 Status = EFI_INVALID_PARAMETER;\r
28a00297 830 goto Done;\r
831 }\r
832 }\r
833 if ((Entry->Capabilities & Attributes) != Attributes) {\r
834 Status = EFI_UNSUPPORTED;\r
835 goto Done;\r
836 }\r
837 break;\r
736a692e
HT
838 //\r
839 // Set capabilities operation\r
840 //\r
841 case GCD_SET_CAPABILITIES_MEMORY_OPERATION:\r
842 if ((BaseAddress & EFI_PAGE_MASK) != 0 || (Length & EFI_PAGE_MASK) != 0) {\r
843 Status = EFI_INVALID_PARAMETER;\r
844\r
845 goto Done;\r
771ee501 846 }\r
736a692e 847 //\r
771ee501 848 // Current attributes must still be supported with new capabilities\r
736a692e
HT
849 //\r
850 if ((Capabilities & Entry->Attributes) != Entry->Attributes) {\r
851 Status = EFI_UNSUPPORTED;\r
852 goto Done;\r
853 }\r
771ee501 854 break;\r
28a00297 855 }\r
856 Link = Link->ForwardLink;\r
857 }\r
858\r
859 //\r
860 // Allocate work space to perform this operation\r
861 //\r
862 Status = CoreAllocateGcdMapEntry (&TopEntry, &BottomEntry);\r
863 if (EFI_ERROR (Status)) {\r
864 Status = EFI_OUT_OF_RESOURCES;\r
865 goto Done;\r
866 }\r
d2fbaaab 867 ASSERT (TopEntry != NULL && BottomEntry != NULL);\r
28a00297 868\r
28a00297 869 if (Operation == GCD_SET_ATTRIBUTES_MEMORY_OPERATION) {\r
870 //\r
871 // Call CPU Arch Protocol to attempt to set attributes on the range\r
872 //\r
873 CpuArchAttributes = ConverToCpuArchAttributes (Attributes);\r
0c9f2cb1
KM
874 //\r
875 // CPU arch attributes include page attributes and cache attributes. \r
876 // Only page attributes supports to be cleared, but not cache attributes.\r
877 // Caller is expected to use GetMemorySpaceDescriptor() to get the current\r
878 // attributes, AND/OR attributes, and then calls SetMemorySpaceAttributes()\r
879 // to set the new attributes.\r
880 // So 0 CPU arch attributes should not happen as memory should always have\r
881 // a cache attribute (no matter UC or WB, etc). \r
882 //\r
883 // Here, 0 CPU arch attributes will be filtered to be compatible with the\r
884 // case that caller just calls SetMemorySpaceAttributes() with none CPU\r
885 // arch attributes (for example, RUNTIME) as the purpose of the case is not\r
886 // to clear CPU arch attributes.\r
887 //\r
888 if (CpuArchAttributes != 0) {\r
fc8ff20f 889 if (gCpu == NULL) {\r
890 Status = EFI_NOT_AVAILABLE_YET;\r
891 } else {\r
f9d1f97c 892 Status = gCpu->SetMemoryAttributes (\r
893 gCpu,\r
894 BaseAddress,\r
895 Length,\r
896 CpuArchAttributes\r
897 );\r
fc8ff20f 898 }\r
899 if (EFI_ERROR (Status)) {\r
900 CoreFreePool (TopEntry);\r
901 CoreFreePool (BottomEntry);\r
902 goto Done;\r
28a00297 903 }\r
904 }\r
28a00297 905 }\r
906\r
907 //\r
908 // Convert/Insert the list of descriptors from StartLink to EndLink\r
909 //\r
910 Link = StartLink;\r
911 while (Link != EndLink->ForwardLink) {\r
912 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
913 CoreInsertGcdMapEntry (Link, Entry, BaseAddress, Length, TopEntry, BottomEntry);\r
914 switch (Operation) {\r
915 //\r
916 // Add operations\r
917 //\r
918 case GCD_ADD_MEMORY_OPERATION:\r
919 Entry->GcdMemoryType = GcdMemoryType;\r
920 if (GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) {\r
921 Entry->Capabilities = Capabilities | EFI_MEMORY_RUNTIME | EFI_MEMORY_PORT_IO;\r
922 } else {\r
923 Entry->Capabilities = Capabilities | EFI_MEMORY_RUNTIME;\r
924 }\r
925 break;\r
926 case GCD_ADD_IO_OPERATION:\r
927 Entry->GcdIoType = GcdIoType;\r
928 break;\r
929 //\r
930 // Free operations\r
931 //\r
932 case GCD_FREE_MEMORY_OPERATION:\r
933 case GCD_FREE_IO_OPERATION:\r
934 Entry->ImageHandle = NULL;\r
935 Entry->DeviceHandle = NULL;\r
936 break;\r
937 //\r
938 // Remove operations\r
939 //\r
940 case GCD_REMOVE_MEMORY_OPERATION:\r
941 Entry->GcdMemoryType = EfiGcdMemoryTypeNonExistent;\r
942 Entry->Capabilities = 0;\r
943 break;\r
944 case GCD_REMOVE_IO_OPERATION:\r
945 Entry->GcdIoType = EfiGcdIoTypeNonExistent;\r
946 break;\r
947 //\r
771ee501 948 // Set attributes operation\r
28a00297 949 //\r
950 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION:\r
0c9f2cb1
KM
951 if (CpuArchAttributes == 0) {\r
952 //\r
953 // Keep original CPU arch attributes when caller just calls\r
954 // SetMemorySpaceAttributes() with none CPU arch attributes (for example, RUNTIME).\r
955 //\r
956 Attributes |= (Entry->Attributes & (EXCLUSIVE_MEMORY_ATTRIBUTES | NONEXCLUSIVE_MEMORY_ATTRIBUTES));\r
957 }\r
28a00297 958 Entry->Attributes = Attributes;\r
959 break;\r
771ee501
EC
960 //\r
961 // Set capabilities operation\r
962 //\r
736a692e
HT
963 case GCD_SET_CAPABILITIES_MEMORY_OPERATION:\r
964 Entry->Capabilities = Capabilities;\r
771ee501 965 break;\r
28a00297 966 }\r
967 Link = Link->ForwardLink;\r
968 }\r
969\r
970 //\r
971 // Cleanup\r
972 //\r
973 Status = CoreCleanupGcdMapEntry (TopEntry, BottomEntry, StartLink, EndLink, Map);\r
974\r
975Done:\r
aa927cae 976 DEBUG ((DEBUG_GCD, " Status = %r\n", Status));\r
f9d1f97c 977\r
71f68914 978 if ((Operation & GCD_MEMORY_SPACE_OPERATION) != 0) {\r
28a00297 979 CoreReleaseGcdMemoryLock ();\r
aa927cae 980 CoreDumpGcdMemorySpaceMap (FALSE);\r
28a00297 981 }\r
71f68914 982 if ((Operation & GCD_IO_SPACE_OPERATION) != 0) {\r
28a00297 983 CoreReleaseGcdIoLock ();\r
aa927cae 984 CoreDumpGcdIoSpaceMap (FALSE);\r
28a00297 985 }\r
986\r
987 return Status;\r
988}\r
989\r
162ed594 990\r
991/**\r
992 Check whether an entry could be used to allocate space.\r
993\r
022c6d45 994 @param Operation Allocate memory or IO\r
995 @param Entry The entry to be tested\r
996 @param GcdMemoryType The desired memory type\r
997 @param GcdIoType The desired IO type\r
162ed594 998\r
022c6d45 999 @retval EFI_NOT_FOUND The memory type does not match or there's an\r
1000 image handle on the entry.\r
1001 @retval EFI_UNSUPPORTED The operation unsupported.\r
1002 @retval EFI_SUCCESS It's ok for this entry to be used to allocate\r
162ed594 1003 space.\r
1004\r
1005**/\r
28a00297 1006EFI_STATUS\r
1007CoreAllocateSpaceCheckEntry (\r
1008 IN UINTN Operation,\r
1009 IN EFI_GCD_MAP_ENTRY *Entry,\r
1010 IN EFI_GCD_MEMORY_TYPE GcdMemoryType,\r
1011 IN EFI_GCD_IO_TYPE GcdIoType\r
1012 )\r
28a00297 1013{\r
1014 if (Entry->ImageHandle != NULL) {\r
1015 return EFI_NOT_FOUND;\r
1016 }\r
1017 switch (Operation) {\r
1018 case GCD_ALLOCATE_MEMORY_OPERATION:\r
1019 if (Entry->GcdMemoryType != GcdMemoryType) {\r
1020 return EFI_NOT_FOUND;\r
1021 }\r
1022 break;\r
1023 case GCD_ALLOCATE_IO_OPERATION:\r
1024 if (Entry->GcdIoType != GcdIoType) {\r
1025 return EFI_NOT_FOUND;\r
1026 }\r
1027 break;\r
1028 default:\r
1029 return EFI_UNSUPPORTED;\r
1030 }\r
1031 return EFI_SUCCESS;\r
1032}\r
1033\r
162ed594 1034\r
1035/**\r
1036 Allocate space on specified address and length.\r
1037\r
022c6d45 1038 @param Operation The type of operation (memory or IO)\r
1039 @param GcdAllocateType The type of allocate operation\r
1040 @param GcdMemoryType The desired memory type\r
1041 @param GcdIoType The desired IO type\r
1042 @param Alignment Align with 2^Alignment\r
1043 @param Length Length to allocate\r
1044 @param BaseAddress Base address to allocate\r
1045 @param ImageHandle The image handle consume the allocated space.\r
1046 @param DeviceHandle The device handle consume the allocated space.\r
1047\r
1048 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
1049 @retval EFI_NOT_FOUND No descriptor for the desired space exists.\r
162ed594 1050 @retval EFI_SUCCESS Space successfully allocated.\r
1051\r
1052**/\r
28a00297 1053EFI_STATUS\r
1054CoreAllocateSpace (\r
1055 IN UINTN Operation,\r
1056 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType,\r
1057 IN EFI_GCD_MEMORY_TYPE GcdMemoryType,\r
1058 IN EFI_GCD_IO_TYPE GcdIoType,\r
1059 IN UINTN Alignment,\r
1060 IN UINT64 Length,\r
1061 IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,\r
1062 IN EFI_HANDLE ImageHandle,\r
1063 IN EFI_HANDLE DeviceHandle OPTIONAL\r
1064 )\r
28a00297 1065{\r
1066 EFI_STATUS Status;\r
1067 EFI_PHYSICAL_ADDRESS AlignmentMask;\r
1068 EFI_PHYSICAL_ADDRESS MaxAddress;\r
1069 LIST_ENTRY *Map;\r
1070 LIST_ENTRY *Link;\r
1071 LIST_ENTRY *SubLink;\r
1072 EFI_GCD_MAP_ENTRY *Entry;\r
1073 EFI_GCD_MAP_ENTRY *TopEntry;\r
1074 EFI_GCD_MAP_ENTRY *BottomEntry;\r
1075 LIST_ENTRY *StartLink;\r
1076 LIST_ENTRY *EndLink;\r
1077 BOOLEAN Found;\r
1078\r
1079 //\r
1080 // Make sure parameters are valid\r
1081 //\r
3d78c020 1082 if ((UINT32)GcdAllocateType >= EfiGcdMaxAllocateType) {\r
aa927cae 1083 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER));\r
28a00297 1084 return EFI_INVALID_PARAMETER;\r
1085 }\r
3d78c020 1086 if ((UINT32)GcdMemoryType >= EfiGcdMemoryTypeMaximum) {\r
aa927cae 1087 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER));\r
28a00297 1088 return EFI_INVALID_PARAMETER;\r
1089 }\r
3d78c020 1090 if ((UINT32)GcdIoType >= EfiGcdIoTypeMaximum) {\r
aa927cae 1091 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER));\r
28a00297 1092 return EFI_INVALID_PARAMETER;\r
1093 }\r
1094 if (BaseAddress == NULL) {\r
aa927cae 1095 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER));\r
28a00297 1096 return EFI_INVALID_PARAMETER;\r
1097 }\r
1098 if (ImageHandle == NULL) {\r
aa927cae 1099 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER));\r
28a00297 1100 return EFI_INVALID_PARAMETER;\r
1101 }\r
1102 if (Alignment >= 64) {\r
aa927cae 1103 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_NOT_FOUND));\r
28a00297 1104 return EFI_NOT_FOUND;\r
1105 }\r
1106 if (Length == 0) {\r
aa927cae 1107 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER));\r
28a00297 1108 return EFI_INVALID_PARAMETER;\r
1109 }\r
1110\r
1111 Map = NULL;\r
71f68914 1112 if ((Operation & GCD_MEMORY_SPACE_OPERATION) != 0) {\r
28a00297 1113 CoreAcquireGcdMemoryLock ();\r
1114 Map = &mGcdMemorySpaceMap;\r
fbbb4211 1115 } else if ((Operation & GCD_IO_SPACE_OPERATION) != 0) {\r
28a00297 1116 CoreAcquireGcdIoLock ();\r
1117 Map = &mGcdIoSpaceMap;\r
fbbb4211 1118 } else {\r
1119 ASSERT (FALSE);\r
28a00297 1120 }\r
1121\r
1122 Found = FALSE;\r
1123 StartLink = NULL;\r
1124 EndLink = NULL;\r
1125 //\r
1126 // Compute alignment bit mask\r
1127 //\r
1128 AlignmentMask = LShiftU64 (1, Alignment) - 1;\r
1129\r
1130 if (GcdAllocateType == EfiGcdAllocateAddress) {\r
1131 //\r
1132 // Verify that the BaseAddress passed in is aligned correctly\r
1133 //\r
1134 if ((*BaseAddress & AlignmentMask) != 0) {\r
1135 Status = EFI_NOT_FOUND;\r
1136 goto Done;\r
1137 }\r
1138\r
1139 //\r
1140 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length\r
1141 //\r
1142 Status = CoreSearchGcdMapEntry (*BaseAddress, Length, &StartLink, &EndLink, Map);\r
1143 if (EFI_ERROR (Status)) {\r
1144 Status = EFI_NOT_FOUND;\r
1145 goto Done;\r
1146 }\r
d2fbaaab 1147 ASSERT (StartLink != NULL && EndLink != NULL);\r
28a00297 1148\r
1149 //\r
1150 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.\r
1151 //\r
1152 Link = StartLink;\r
1153 while (Link != EndLink->ForwardLink) {\r
1154 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
1155 Link = Link->ForwardLink;\r
1156 Status = CoreAllocateSpaceCheckEntry (Operation, Entry, GcdMemoryType, GcdIoType);\r
1157 if (EFI_ERROR (Status)) {\r
1158 goto Done;\r
1159 }\r
1160 }\r
1161 Found = TRUE;\r
1162 } else {\r
1163\r
1164 Entry = CR (Map->BackLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
1165\r
1166 //\r
1167 // Compute the maximum address to use in the search algorithm\r
1168 //\r
1169 if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchBottomUp ||\r
1170 GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown ) {\r
1171 MaxAddress = *BaseAddress;\r
1172 } else {\r
1173 MaxAddress = Entry->EndAddress;\r
1174 }\r
1175\r
1176 //\r
1177 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.\r
1178 //\r
1179 if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown ||\r
1180 GcdAllocateType == EfiGcdAllocateAnySearchTopDown ) {\r
1181 Link = Map->BackLink;\r
1182 } else {\r
1183 Link = Map->ForwardLink;\r
1184 }\r
1185 while (Link != Map) {\r
1186 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
1187\r
1188 if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown ||\r
1189 GcdAllocateType == EfiGcdAllocateAnySearchTopDown ) {\r
1190 Link = Link->BackLink;\r
1191 } else {\r
1192 Link = Link->ForwardLink;\r
1193 }\r
1194\r
1195 Status = CoreAllocateSpaceCheckEntry (Operation, Entry, GcdMemoryType, GcdIoType);\r
1196 if (EFI_ERROR (Status)) {\r
1197 continue;\r
1198 }\r
1199\r
1200 if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown ||\r
e94a9ff7 1201 GcdAllocateType == EfiGcdAllocateAnySearchTopDown) {\r
28a00297 1202 if ((Entry->BaseAddress + Length) > MaxAddress) {\r
1203 continue;\r
1204 }\r
1205 if (Length > (Entry->EndAddress + 1)) {\r
1206 Status = EFI_NOT_FOUND;\r
1207 goto Done;\r
1208 }\r
1209 if (Entry->EndAddress > MaxAddress) {\r
1210 *BaseAddress = MaxAddress;\r
1211 } else {\r
1212 *BaseAddress = Entry->EndAddress;\r
1213 }\r
1214 *BaseAddress = (*BaseAddress + 1 - Length) & (~AlignmentMask);\r
1215 } else {\r
1216 *BaseAddress = (Entry->BaseAddress + AlignmentMask) & (~AlignmentMask);\r
1217 if ((*BaseAddress + Length - 1) > MaxAddress) {\r
1218 Status = EFI_NOT_FOUND;\r
1219 goto Done;\r
1220 }\r
1221 }\r
1222\r
1223 //\r
1224 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length\r
1225 //\r
1226 Status = CoreSearchGcdMapEntry (*BaseAddress, Length, &StartLink, &EndLink, Map);\r
1227 if (EFI_ERROR (Status)) {\r
1228 Status = EFI_NOT_FOUND;\r
1229 goto Done;\r
1230 }\r
d2fbaaab 1231 ASSERT (StartLink != NULL && EndLink != NULL);\r
28a00297 1232\r
1233 Link = StartLink;\r
1234 //\r
1235 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.\r
1236 //\r
1237 Found = TRUE;\r
1238 SubLink = StartLink;\r
1239 while (SubLink != EndLink->ForwardLink) {\r
1240 Entry = CR (SubLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
1241 Status = CoreAllocateSpaceCheckEntry (Operation, Entry, GcdMemoryType, GcdIoType);\r
1242 if (EFI_ERROR (Status)) {\r
1243 Link = SubLink;\r
1244 Found = FALSE;\r
1245 break;\r
1246 }\r
1247 SubLink = SubLink->ForwardLink;\r
1248 }\r
1249 if (Found) {\r
1250 break;\r
1251 }\r
1252 }\r
1253 }\r
1254 if (!Found) {\r
1255 Status = EFI_NOT_FOUND;\r
1256 goto Done;\r
1257 }\r
1258\r
1259 //\r
1260 // Allocate work space to perform this operation\r
1261 //\r
1262 Status = CoreAllocateGcdMapEntry (&TopEntry, &BottomEntry);\r
1263 if (EFI_ERROR (Status)) {\r
1264 Status = EFI_OUT_OF_RESOURCES;\r
1265 goto Done;\r
1266 }\r
d2fbaaab 1267 ASSERT (TopEntry != NULL && BottomEntry != NULL);\r
28a00297 1268\r
1269 //\r
1270 // Convert/Insert the list of descriptors from StartLink to EndLink\r
1271 //\r
1272 Link = StartLink;\r
1273 while (Link != EndLink->ForwardLink) {\r
1274 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
1275 CoreInsertGcdMapEntry (Link, Entry, *BaseAddress, Length, TopEntry, BottomEntry);\r
1276 Entry->ImageHandle = ImageHandle;\r
1277 Entry->DeviceHandle = DeviceHandle;\r
1278 Link = Link->ForwardLink;\r
1279 }\r
1280\r
1281 //\r
1282 // Cleanup\r
1283 //\r
1284 Status = CoreCleanupGcdMapEntry (TopEntry, BottomEntry, StartLink, EndLink, Map);\r
1285\r
1286Done:\r
aa927cae 1287 DEBUG ((DEBUG_GCD, " Status = %r", Status));\r
1288 if (!EFI_ERROR (Status)) {\r
1289 DEBUG ((DEBUG_GCD, " (BaseAddress = %016lx)", *BaseAddress));\r
1290 }\r
1291 DEBUG ((DEBUG_GCD, "\n"));\r
f9d1f97c 1292 \r
71f68914 1293 if ((Operation & GCD_MEMORY_SPACE_OPERATION) != 0) {\r
28a00297 1294 CoreReleaseGcdMemoryLock ();\r
aa927cae 1295 CoreDumpGcdMemorySpaceMap (FALSE);\r
28a00297 1296 }\r
71f68914 1297 if ((Operation & GCD_IO_SPACE_OPERATION) !=0) {\r
28a00297 1298 CoreReleaseGcdIoLock ();\r
aa927cae 1299 CoreDumpGcdIoSpaceMap (FALSE);\r
28a00297 1300 }\r
aa927cae 1301\r
28a00297 1302 return Status;\r
1303}\r
1304\r
28a00297 1305\r
162ed594 1306/**\r
28a00297 1307 Add a segment of memory to GCD map.\r
1308\r
022c6d45 1309 @param GcdMemoryType Memory type of the segment.\r
1310 @param BaseAddress Base address of the segment.\r
1311 @param Length Length of the segment.\r
1312 @param Capabilities alterable attributes of the segment.\r
28a00297 1313\r
022c6d45 1314 @retval EFI_INVALID_PARAMETER Invalid parameters.\r
162ed594 1315 @retval EFI_SUCCESS Successfully add a segment of memory space.\r
28a00297 1316\r
162ed594 1317**/\r
162ed594 1318EFI_STATUS\r
1319CoreInternalAddMemorySpace (\r
1320 IN EFI_GCD_MEMORY_TYPE GcdMemoryType,\r
1321 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
1322 IN UINT64 Length,\r
1323 IN UINT64 Capabilities\r
1324 )\r
28a00297 1325{\r
f9d1f97c 1326 DEBUG ((DEBUG_GCD, "GCD:AddMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));\r
1327 DEBUG ((DEBUG_GCD, " GcdMemoryType = %a\n", mGcdMemoryTypeNames[MIN (GcdMemoryType, EfiGcdMemoryTypeMaximum)]));\r
1328 DEBUG ((DEBUG_GCD, " Capabilities = %016lx\n", Capabilities));\r
1329\r
28a00297 1330 //\r
1331 // Make sure parameters are valid\r
1332 //\r
1333 if (GcdMemoryType <= EfiGcdMemoryTypeNonExistent || GcdMemoryType >= EfiGcdMemoryTypeMaximum) {\r
1334 return EFI_INVALID_PARAMETER;\r
1335 }\r
1336\r
1337 return CoreConvertSpace (GCD_ADD_MEMORY_OPERATION, GcdMemoryType, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, Capabilities, 0);\r
1338}\r
1339\r
1340//\r
1341// GCD Core Services\r
1342//\r
162ed594 1343\r
1344/**\r
1345 Allocates nonexistent memory, reserved memory, system memory, or memorymapped\r
1346 I/O resources from the global coherency domain of the processor.\r
1347\r
022c6d45 1348 @param GcdAllocateType The type of allocate operation\r
1349 @param GcdMemoryType The desired memory type\r
1350 @param Alignment Align with 2^Alignment\r
1351 @param Length Length to allocate\r
1352 @param BaseAddress Base address to allocate\r
1353 @param ImageHandle The image handle consume the allocated space.\r
1354 @param DeviceHandle The device handle consume the allocated space.\r
162ed594 1355\r
022c6d45 1356 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
1357 @retval EFI_NOT_FOUND No descriptor contains the desired space.\r
162ed594 1358 @retval EFI_SUCCESS Memory space successfully allocated.\r
1359\r
1360**/\r
28a00297 1361EFI_STATUS\r
3b6ffb6a 1362EFIAPI\r
28a00297 1363CoreAllocateMemorySpace (\r
1364 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType,\r
1365 IN EFI_GCD_MEMORY_TYPE GcdMemoryType,\r
1366 IN UINTN Alignment,\r
1367 IN UINT64 Length,\r
1368 IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,\r
1369 IN EFI_HANDLE ImageHandle,\r
1370 IN EFI_HANDLE DeviceHandle OPTIONAL\r
1371 )\r
28a00297 1372{\r
7328295c
MK
1373 if (BaseAddress != NULL) {\r
1374 DEBUG ((DEBUG_GCD, "GCD:AllocateMemorySpace(Base=%016lx,Length=%016lx)\n", *BaseAddress, Length));\r
1375 } else {\r
1376 DEBUG ((DEBUG_GCD, "GCD:AllocateMemorySpace(Base=<NULL>,Length=%016lx)\n", Length));\r
1377 }\r
f9d1f97c 1378 DEBUG ((DEBUG_GCD, " GcdAllocateType = %a\n", mGcdAllocationTypeNames[MIN (GcdAllocateType, EfiGcdMaxAllocateType)]));\r
1379 DEBUG ((DEBUG_GCD, " GcdMemoryType = %a\n", mGcdMemoryTypeNames[MIN (GcdMemoryType, EfiGcdMemoryTypeMaximum)]));\r
1380 DEBUG ((DEBUG_GCD, " Alignment = %016lx\n", LShiftU64 (1, Alignment)));\r
1381 DEBUG ((DEBUG_GCD, " ImageHandle = %p\n", ImageHandle));\r
1382 DEBUG ((DEBUG_GCD, " DeviceHandle = %p\n", DeviceHandle));\r
1383 \r
28a00297 1384 return CoreAllocateSpace (\r
022c6d45 1385 GCD_ALLOCATE_MEMORY_OPERATION,\r
1386 GcdAllocateType,\r
1387 GcdMemoryType,\r
1388 (EFI_GCD_IO_TYPE) 0,\r
1389 Alignment,\r
1390 Length,\r
1391 BaseAddress,\r
1392 ImageHandle,\r
28a00297 1393 DeviceHandle\r
1394 );\r
1395}\r
1396\r
162ed594 1397\r
1398/**\r
1399 Adds reserved memory, system memory, or memory-mapped I/O resources to the\r
1400 global coherency domain of the processor.\r
1401\r
022c6d45 1402 @param GcdMemoryType Memory type of the memory space.\r
1403 @param BaseAddress Base address of the memory space.\r
1404 @param Length Length of the memory space.\r
1405 @param Capabilities alterable attributes of the memory space.\r
162ed594 1406\r
1407 @retval EFI_SUCCESS Merged this memory space into GCD map.\r
1408\r
1409**/\r
28a00297 1410EFI_STATUS\r
3b6ffb6a 1411EFIAPI\r
28a00297 1412CoreAddMemorySpace (\r
1413 IN EFI_GCD_MEMORY_TYPE GcdMemoryType,\r
1414 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
1415 IN UINT64 Length,\r
1416 IN UINT64 Capabilities\r
1417 )\r
28a00297 1418{\r
1419 EFI_STATUS Status;\r
1420 EFI_PHYSICAL_ADDRESS PageBaseAddress;\r
1421 UINT64 PageLength;\r
1422\r
1423 Status = CoreInternalAddMemorySpace (GcdMemoryType, BaseAddress, Length, Capabilities);\r
1424\r
74705ca5 1425 if (!EFI_ERROR (Status) && ((GcdMemoryType == EfiGcdMemoryTypeSystemMemory) || (GcdMemoryType == EfiGcdMemoryTypeMoreReliable))) {\r
28a00297 1426\r
74705ca5 1427 PageBaseAddress = PageAlignAddress (BaseAddress);\r
28a00297 1428 PageLength = PageAlignLength (BaseAddress + Length - PageBaseAddress);\r
1429\r
1430 Status = CoreAllocateMemorySpace (\r
1431 EfiGcdAllocateAddress,\r
1432 GcdMemoryType,\r
022c6d45 1433 EFI_PAGE_SHIFT,\r
28a00297 1434 PageLength,\r
1435 &PageBaseAddress,\r
1436 gDxeCoreImageHandle,\r
1437 NULL\r
1438 );\r
1439\r
1440 if (!EFI_ERROR (Status)) {\r
1441 CoreAddMemoryDescriptor (\r
1442 EfiConventionalMemory,\r
1443 PageBaseAddress,\r
1444 RShiftU64 (PageLength, EFI_PAGE_SHIFT),\r
1445 Capabilities\r
1446 );\r
1447 } else {\r
1448 for (; PageLength != 0; PageLength -= EFI_PAGE_SIZE, PageBaseAddress += EFI_PAGE_SIZE) {\r
1449 Status = CoreAllocateMemorySpace (\r
1450 EfiGcdAllocateAddress,\r
1451 GcdMemoryType,\r
022c6d45 1452 EFI_PAGE_SHIFT,\r
28a00297 1453 EFI_PAGE_SIZE,\r
1454 &PageBaseAddress,\r
1455 gDxeCoreImageHandle,\r
1456 NULL\r
1457 );\r
1458\r
1459 if (!EFI_ERROR (Status)) {\r
1460 CoreAddMemoryDescriptor (\r
1461 EfiConventionalMemory,\r
1462 PageBaseAddress,\r
1463 1,\r
1464 Capabilities\r
1465 );\r
1466 }\r
1467 }\r
1468 }\r
1469 }\r
1470 return Status;\r
1471}\r
1472\r
28a00297 1473\r
162ed594 1474/**\r
28a00297 1475 Frees nonexistent memory, reserved memory, system memory, or memory-mapped\r
162ed594 1476 I/O resources from the global coherency domain of the processor.\r
28a00297 1477\r
022c6d45 1478 @param BaseAddress Base address of the memory space.\r
1479 @param Length Length of the memory space.\r
28a00297 1480\r
162ed594 1481 @retval EFI_SUCCESS Space successfully freed.\r
28a00297 1482\r
162ed594 1483**/\r
28a00297 1484EFI_STATUS\r
3b6ffb6a 1485EFIAPI\r
162ed594 1486CoreFreeMemorySpace (\r
28a00297 1487 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
1488 IN UINT64 Length\r
1489 )\r
162ed594 1490{\r
f9d1f97c 1491 DEBUG ((DEBUG_GCD, "GCD:FreeMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));\r
1492\r
162ed594 1493 return CoreConvertSpace (GCD_FREE_MEMORY_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, 0);\r
1494}\r
28a00297 1495\r
28a00297 1496\r
162ed594 1497/**\r
28a00297 1498 Removes reserved memory, system memory, or memory-mapped I/O resources from\r
162ed594 1499 the global coherency domain of the processor.\r
28a00297 1500\r
022c6d45 1501 @param BaseAddress Base address of the memory space.\r
1502 @param Length Length of the memory space.\r
28a00297 1503\r
162ed594 1504 @retval EFI_SUCCESS Successfully remove a segment of memory space.\r
28a00297 1505\r
162ed594 1506**/\r
1507EFI_STATUS\r
3b6ffb6a 1508EFIAPI\r
162ed594 1509CoreRemoveMemorySpace (\r
1510 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
1511 IN UINT64 Length\r
1512 )\r
28a00297 1513{\r
f9d1f97c 1514 DEBUG ((DEBUG_GCD, "GCD:RemoveMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));\r
1515 \r
28a00297 1516 return CoreConvertSpace (GCD_REMOVE_MEMORY_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, 0);\r
1517}\r
1518\r
162ed594 1519\r
1520/**\r
1521 Build a memory descriptor according to an entry.\r
1522\r
022c6d45 1523 @param Descriptor The descriptor to be built\r
162ed594 1524 @param Entry According to this entry\r
1525\r
1526**/\r
28a00297 1527VOID\r
1528BuildMemoryDescriptor (\r
1529 IN OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor,\r
1530 IN EFI_GCD_MAP_ENTRY *Entry\r
1531 )\r
28a00297 1532{\r
1533 Descriptor->BaseAddress = Entry->BaseAddress;\r
1534 Descriptor->Length = Entry->EndAddress - Entry->BaseAddress + 1;\r
1535 Descriptor->Capabilities = Entry->Capabilities;\r
1536 Descriptor->Attributes = Entry->Attributes;\r
1537 Descriptor->GcdMemoryType = Entry->GcdMemoryType;\r
1538 Descriptor->ImageHandle = Entry->ImageHandle;\r
1539 Descriptor->DeviceHandle = Entry->DeviceHandle;\r
1540}\r
1541\r
28a00297 1542\r
162ed594 1543/**\r
28a00297 1544 Retrieves the descriptor for a memory region containing a specified address.\r
1545\r
022c6d45 1546 @param BaseAddress Specified start address\r
1547 @param Descriptor Specified length\r
28a00297 1548\r
022c6d45 1549 @retval EFI_INVALID_PARAMETER Invalid parameter\r
162ed594 1550 @retval EFI_SUCCESS Successfully get memory space descriptor.\r
28a00297 1551\r
162ed594 1552**/\r
1553EFI_STATUS\r
3b6ffb6a 1554EFIAPI\r
162ed594 1555CoreGetMemorySpaceDescriptor (\r
1556 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
1557 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor\r
1558 )\r
28a00297 1559{\r
1560 EFI_STATUS Status;\r
1561 LIST_ENTRY *StartLink;\r
1562 LIST_ENTRY *EndLink;\r
1563 EFI_GCD_MAP_ENTRY *Entry;\r
1564\r
1565 //\r
1566 // Make sure parameters are valid\r
1567 //\r
1568 if (Descriptor == NULL) {\r
1569 return EFI_INVALID_PARAMETER;\r
1570 }\r
1571\r
1572 CoreAcquireGcdMemoryLock ();\r
1573\r
1574 //\r
022c6d45 1575 // Search for the list of descriptors that contain BaseAddress\r
28a00297 1576 //\r
1577 Status = CoreSearchGcdMapEntry (BaseAddress, 1, &StartLink, &EndLink, &mGcdMemorySpaceMap);\r
1578 if (EFI_ERROR (Status)) {\r
1579 Status = EFI_NOT_FOUND;\r
1580 } else {\r
d2fbaaab 1581 ASSERT (StartLink != NULL && EndLink != NULL);\r
28a00297 1582 //\r
1583 // Copy the contents of the found descriptor into Descriptor\r
1584 //\r
1585 Entry = CR (StartLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
1586 BuildMemoryDescriptor (Descriptor, Entry);\r
1587 }\r
1588\r
1589 CoreReleaseGcdMemoryLock ();\r
1590\r
1591 return Status;\r
1592}\r
1593\r
162ed594 1594\r
1595/**\r
1596 Modifies the attributes for a memory region in the global coherency domain of the\r
1597 processor.\r
1598\r
022c6d45 1599 @param BaseAddress Specified start address\r
1600 @param Length Specified length\r
1601 @param Attributes Specified attributes\r
162ed594 1602\r
fc8ff20f 1603 @retval EFI_SUCCESS The attributes were set for the memory region.\r
1604 @retval EFI_INVALID_PARAMETER Length is zero. \r
1605 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory\r
1606 resource range specified by BaseAddress and Length.\r
1607 @retval EFI_UNSUPPORTED The bit mask of attributes is not support for the memory resource\r
1608 range specified by BaseAddress and Length.\r
1609 @retval EFI_ACCESS_DEFINED The attributes for the memory resource range specified by\r
1610 BaseAddress and Length cannot be modified.\r
1611 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of\r
1612 the memory resource range.\r
1613 @retval EFI_NOT_AVAILABLE_YET The attributes cannot be set because CPU architectural protocol is\r
1614 not available yet.\r
162ed594 1615\r
1616**/\r
28a00297 1617EFI_STATUS\r
3b6ffb6a 1618EFIAPI\r
28a00297 1619CoreSetMemorySpaceAttributes (\r
1620 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
1621 IN UINT64 Length,\r
1622 IN UINT64 Attributes\r
1623 )\r
162ed594 1624{\r
f9d1f97c 1625 DEBUG ((DEBUG_GCD, "GCD:SetMemorySpaceAttributes(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));\r
1626 DEBUG ((DEBUG_GCD, " Attributes = %016lx\n", Attributes));\r
1627\r
162ed594 1628 return CoreConvertSpace (GCD_SET_ATTRIBUTES_MEMORY_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, Attributes);\r
1629}\r
28a00297 1630\r
28a00297 1631\r
771ee501
EC
1632/**\r
1633 Modifies the capabilities for a memory region in the global coherency domain of the\r
1634 processor.\r
1635\r
1636 @param BaseAddress The physical address that is the start address of a memory region.\r
1637 @param Length The size in bytes of the memory region.\r
1638 @param Capabilities The bit mask of capabilities that the memory region supports.\r
1639\r
1640 @retval EFI_SUCCESS The capabilities were set for the memory region.\r
1641 @retval EFI_INVALID_PARAMETER Length is zero.\r
1642 @retval EFI_UNSUPPORTED The capabilities specified by Capabilities do not include the\r
1643 memory region attributes currently in use.\r
1644 @retval EFI_ACCESS_DENIED The capabilities for the memory resource range specified by\r
1645 BaseAddress and Length cannot be modified.\r
1646 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the capabilities\r
1647 of the memory resource range.\r
1648**/\r
1649EFI_STATUS\r
1650EFIAPI\r
1651CoreSetMemorySpaceCapabilities (\r
1652 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
1653 IN UINT64 Length,\r
1654 IN UINT64 Capabilities\r
1655 )\r
1656{\r
736a692e
HT
1657 EFI_STATUS Status;\r
1658\r
771ee501 1659 DEBUG ((DEBUG_GCD, "GCD:CoreSetMemorySpaceCapabilities(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));\r
736a692e
HT
1660 DEBUG ((DEBUG_GCD, " Capabilities = %016lx\n", Capabilities));\r
1661\r
1662 Status = CoreConvertSpace (GCD_SET_CAPABILITIES_MEMORY_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, Capabilities, 0);\r
771ee501 1663 if (!EFI_ERROR(Status)) {\r
32fd9c41 1664 CoreUpdateMemoryAttributes(BaseAddress, RShiftU64(Length, EFI_PAGE_SHIFT), Capabilities & (~EFI_MEMORY_RUNTIME));\r
736a692e
HT
1665 }\r
1666\r
771ee501
EC
1667 return Status;\r
1668}\r
1669\r
1670\r
162ed594 1671/**\r
1672 Returns a map of the memory resources in the global coherency domain of the\r
1673 processor.\r
28a00297 1674\r
022c6d45 1675 @param NumberOfDescriptors Number of descriptors.\r
1676 @param MemorySpaceMap Descriptor array\r
28a00297 1677\r
022c6d45 1678 @retval EFI_INVALID_PARAMETER Invalid parameter\r
1679 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate\r
162ed594 1680 @retval EFI_SUCCESS Successfully get memory space map.\r
28a00297 1681\r
162ed594 1682**/\r
28a00297 1683EFI_STATUS\r
3b6ffb6a 1684EFIAPI\r
28a00297 1685CoreGetMemorySpaceMap (\r
1686 OUT UINTN *NumberOfDescriptors,\r
1687 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR **MemorySpaceMap\r
1688 )\r
28a00297 1689{\r
1690 EFI_STATUS Status;\r
1691 LIST_ENTRY *Link;\r
1692 EFI_GCD_MAP_ENTRY *Entry;\r
1693 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor;\r
1694\r
1695 //\r
1696 // Make sure parameters are valid\r
1697 //\r
1698 if (NumberOfDescriptors == NULL) {\r
1699 return EFI_INVALID_PARAMETER;\r
1700 }\r
1701 if (MemorySpaceMap == NULL) {\r
1702 return EFI_INVALID_PARAMETER;\r
1703 }\r
1704\r
1705 CoreAcquireGcdMemoryLock ();\r
1706\r
1707 //\r
1708 // Count the number of descriptors\r
1709 //\r
1710 *NumberOfDescriptors = CoreCountGcdMapEntry (&mGcdMemorySpaceMap);\r
1711\r
1712 //\r
1713 // Allocate the MemorySpaceMap\r
1714 //\r
9c4ac31c 1715 *MemorySpaceMap = AllocatePool (*NumberOfDescriptors * sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR));\r
28a00297 1716 if (*MemorySpaceMap == NULL) {\r
1717 Status = EFI_OUT_OF_RESOURCES;\r
1718 goto Done;\r
1719 }\r
1720\r
1721 //\r
1722 // Fill in the MemorySpaceMap\r
1723 //\r
1724 Descriptor = *MemorySpaceMap;\r
1725 Link = mGcdMemorySpaceMap.ForwardLink;\r
1726 while (Link != &mGcdMemorySpaceMap) {\r
1727 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
1728 BuildMemoryDescriptor (Descriptor, Entry);\r
1729 Descriptor++;\r
1730 Link = Link->ForwardLink;\r
1731 }\r
1732 Status = EFI_SUCCESS;\r
1733\r
1734Done:\r
1735 CoreReleaseGcdMemoryLock ();\r
1736 return Status;\r
1737}\r
1738\r
162ed594 1739\r
1740/**\r
1741 Adds reserved I/O or I/O resources to the global coherency domain of the processor.\r
1742\r
022c6d45 1743 @param GcdIoType IO type of the segment.\r
1744 @param BaseAddress Base address of the segment.\r
1745 @param Length Length of the segment.\r
162ed594 1746\r
022c6d45 1747 @retval EFI_SUCCESS Merged this segment into GCD map.\r
162ed594 1748 @retval EFI_INVALID_PARAMETER Parameter not valid\r
1749\r
1750**/\r
28a00297 1751EFI_STATUS\r
3b6ffb6a 1752EFIAPI\r
28a00297 1753CoreAddIoSpace (\r
1754 IN EFI_GCD_IO_TYPE GcdIoType,\r
1755 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
1756 IN UINT64 Length\r
1757 )\r
28a00297 1758{\r
f9d1f97c 1759 DEBUG ((DEBUG_GCD, "GCD:AddIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));\r
1760 DEBUG ((DEBUG_GCD, " GcdIoType = %a\n", mGcdIoTypeNames[MIN (GcdIoType, EfiGcdIoTypeMaximum)]));\r
1761 \r
28a00297 1762 //\r
1763 // Make sure parameters are valid\r
1764 //\r
1765 if (GcdIoType <= EfiGcdIoTypeNonExistent || GcdIoType >= EfiGcdIoTypeMaximum) {\r
1766 return EFI_INVALID_PARAMETER;\r
1767 }\r
1768 return CoreConvertSpace (GCD_ADD_IO_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, GcdIoType, BaseAddress, Length, 0, 0);\r
1769}\r
1770\r
162ed594 1771\r
1772/**\r
1773 Allocates nonexistent I/O, reserved I/O, or I/O resources from the global coherency\r
1774 domain of the processor.\r
1775\r
022c6d45 1776 @param GcdAllocateType The type of allocate operation\r
1777 @param GcdIoType The desired IO type\r
1778 @param Alignment Align with 2^Alignment\r
1779 @param Length Length to allocate\r
1780 @param BaseAddress Base address to allocate\r
1781 @param ImageHandle The image handle consume the allocated space.\r
1782 @param DeviceHandle The device handle consume the allocated space.\r
162ed594 1783\r
022c6d45 1784 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
1785 @retval EFI_NOT_FOUND No descriptor contains the desired space.\r
162ed594 1786 @retval EFI_SUCCESS IO space successfully allocated.\r
1787\r
1788**/\r
28a00297 1789EFI_STATUS\r
3b6ffb6a 1790EFIAPI\r
28a00297 1791CoreAllocateIoSpace (\r
1792 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType,\r
1793 IN EFI_GCD_IO_TYPE GcdIoType,\r
1794 IN UINTN Alignment,\r
1795 IN UINT64 Length,\r
1796 IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,\r
1797 IN EFI_HANDLE ImageHandle,\r
1798 IN EFI_HANDLE DeviceHandle OPTIONAL\r
1799 )\r
28a00297 1800{\r
7328295c
MK
1801 if (BaseAddress != NULL) {\r
1802 DEBUG ((DEBUG_GCD, "GCD:AllocateIoSpace(Base=%016lx,Length=%016lx)\n", *BaseAddress, Length));\r
1803 } else {\r
1804 DEBUG ((DEBUG_GCD, "GCD:AllocateIoSpace(Base=<NULL>,Length=%016lx)\n", Length));\r
1805 }\r
f9d1f97c 1806 DEBUG ((DEBUG_GCD, " GcdAllocateType = %a\n", mGcdAllocationTypeNames[MIN (GcdAllocateType, EfiGcdMaxAllocateType)]));\r
5d1cf216 1807 DEBUG ((DEBUG_GCD, " GcdIoType = %a\n", mGcdIoTypeNames[MIN (GcdIoType, EfiGcdIoTypeMaximum)]));\r
f9d1f97c 1808 DEBUG ((DEBUG_GCD, " Alignment = %016lx\n", LShiftU64 (1, Alignment)));\r
1809 DEBUG ((DEBUG_GCD, " ImageHandle = %p\n", ImageHandle));\r
1810 DEBUG ((DEBUG_GCD, " DeviceHandle = %p\n", DeviceHandle));\r
1811 \r
28a00297 1812 return CoreAllocateSpace (\r
022c6d45 1813 GCD_ALLOCATE_IO_OPERATION,\r
1814 GcdAllocateType,\r
1815 (EFI_GCD_MEMORY_TYPE) 0,\r
1816 GcdIoType,\r
1817 Alignment,\r
1818 Length,\r
1819 BaseAddress,\r
1820 ImageHandle,\r
28a00297 1821 DeviceHandle\r
1822 );\r
1823}\r
1824\r
28a00297 1825\r
162ed594 1826/**\r
28a00297 1827 Frees nonexistent I/O, reserved I/O, or I/O resources from the global coherency\r
162ed594 1828 domain of the processor.\r
28a00297 1829\r
022c6d45 1830 @param BaseAddress Base address of the segment.\r
1831 @param Length Length of the segment.\r
28a00297 1832\r
162ed594 1833 @retval EFI_SUCCESS Space successfully freed.\r
28a00297 1834\r
162ed594 1835**/\r
28a00297 1836EFI_STATUS\r
3b6ffb6a 1837EFIAPI\r
162ed594 1838CoreFreeIoSpace (\r
28a00297 1839 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
1840 IN UINT64 Length\r
1841 )\r
162ed594 1842{\r
f9d1f97c 1843 DEBUG ((DEBUG_GCD, "GCD:FreeIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));\r
1844\r
162ed594 1845 return CoreConvertSpace (GCD_FREE_IO_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, 0);\r
1846}\r
28a00297 1847\r
28a00297 1848\r
162ed594 1849/**\r
28a00297 1850 Removes reserved I/O or I/O resources from the global coherency domain of the\r
162ed594 1851 processor.\r
28a00297 1852\r
022c6d45 1853 @param BaseAddress Base address of the segment.\r
1854 @param Length Length of the segment.\r
28a00297 1855\r
162ed594 1856 @retval EFI_SUCCESS Successfully removed a segment of IO space.\r
28a00297 1857\r
162ed594 1858**/\r
1859EFI_STATUS\r
3b6ffb6a 1860EFIAPI\r
162ed594 1861CoreRemoveIoSpace (\r
1862 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
1863 IN UINT64 Length\r
1864 )\r
28a00297 1865{\r
f9d1f97c 1866 DEBUG ((DEBUG_GCD, "GCD:RemoveIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));\r
1867 \r
28a00297 1868 return CoreConvertSpace (GCD_REMOVE_IO_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, 0);\r
1869}\r
1870\r
162ed594 1871\r
1872/**\r
1873 Build a IO descriptor according to an entry.\r
1874\r
022c6d45 1875 @param Descriptor The descriptor to be built\r
162ed594 1876 @param Entry According to this entry\r
1877\r
1878**/\r
28a00297 1879VOID\r
1880BuildIoDescriptor (\r
1881 IN EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor,\r
1882 IN EFI_GCD_MAP_ENTRY *Entry\r
1883 )\r
28a00297 1884{\r
1885 Descriptor->BaseAddress = Entry->BaseAddress;\r
1886 Descriptor->Length = Entry->EndAddress - Entry->BaseAddress + 1;\r
1887 Descriptor->GcdIoType = Entry->GcdIoType;\r
1888 Descriptor->ImageHandle = Entry->ImageHandle;\r
1889 Descriptor->DeviceHandle = Entry->DeviceHandle;\r
1890}\r
1891\r
28a00297 1892\r
162ed594 1893/**\r
28a00297 1894 Retrieves the descriptor for an I/O region containing a specified address.\r
1895\r
022c6d45 1896 @param BaseAddress Specified start address\r
1897 @param Descriptor Specified length\r
28a00297 1898\r
022c6d45 1899 @retval EFI_INVALID_PARAMETER Descriptor is NULL.\r
162ed594 1900 @retval EFI_SUCCESS Successfully get the IO space descriptor.\r
28a00297 1901\r
162ed594 1902**/\r
1903EFI_STATUS\r
3b6ffb6a 1904EFIAPI\r
162ed594 1905CoreGetIoSpaceDescriptor (\r
1906 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
1907 OUT EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor\r
1908 )\r
28a00297 1909{\r
1910 EFI_STATUS Status;\r
1911 LIST_ENTRY *StartLink;\r
1912 LIST_ENTRY *EndLink;\r
1913 EFI_GCD_MAP_ENTRY *Entry;\r
1914\r
1915 //\r
1916 // Make sure parameters are valid\r
1917 //\r
1918 if (Descriptor == NULL) {\r
1919 return EFI_INVALID_PARAMETER;\r
1920 }\r
1921\r
1922 CoreAcquireGcdIoLock ();\r
1923\r
1924 //\r
022c6d45 1925 // Search for the list of descriptors that contain BaseAddress\r
28a00297 1926 //\r
1927 Status = CoreSearchGcdMapEntry (BaseAddress, 1, &StartLink, &EndLink, &mGcdIoSpaceMap);\r
1928 if (EFI_ERROR (Status)) {\r
1929 Status = EFI_NOT_FOUND;\r
1930 } else {\r
d2fbaaab 1931 ASSERT (StartLink != NULL && EndLink != NULL);\r
28a00297 1932 //\r
1933 // Copy the contents of the found descriptor into Descriptor\r
1934 //\r
1935 Entry = CR (StartLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
1936 BuildIoDescriptor (Descriptor, Entry);\r
1937 }\r
1938\r
1939 CoreReleaseGcdIoLock ();\r
1940\r
1941 return Status;\r
1942}\r
1943\r
28a00297 1944\r
162ed594 1945/**\r
28a00297 1946 Returns a map of the I/O resources in the global coherency domain of the processor.\r
1947\r
022c6d45 1948 @param NumberOfDescriptors Number of descriptors.\r
1949 @param IoSpaceMap Descriptor array\r
28a00297 1950\r
022c6d45 1951 @retval EFI_INVALID_PARAMETER Invalid parameter\r
1952 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate\r
162ed594 1953 @retval EFI_SUCCESS Successfully get IO space map.\r
28a00297 1954\r
162ed594 1955**/\r
1956EFI_STATUS\r
3b6ffb6a 1957EFIAPI\r
162ed594 1958CoreGetIoSpaceMap (\r
1959 OUT UINTN *NumberOfDescriptors,\r
1960 OUT EFI_GCD_IO_SPACE_DESCRIPTOR **IoSpaceMap\r
1961 )\r
28a00297 1962{\r
1963 EFI_STATUS Status;\r
1964 LIST_ENTRY *Link;\r
1965 EFI_GCD_MAP_ENTRY *Entry;\r
1966 EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor;\r
1967\r
1968 //\r
1969 // Make sure parameters are valid\r
1970 //\r
1971 if (NumberOfDescriptors == NULL) {\r
1972 return EFI_INVALID_PARAMETER;\r
1973 }\r
1974 if (IoSpaceMap == NULL) {\r
1975 return EFI_INVALID_PARAMETER;\r
1976 }\r
1977\r
1978 CoreAcquireGcdIoLock ();\r
1979\r
1980 //\r
1981 // Count the number of descriptors\r
1982 //\r
1983 *NumberOfDescriptors = CoreCountGcdMapEntry (&mGcdIoSpaceMap);\r
1984\r
1985 //\r
1986 // Allocate the IoSpaceMap\r
1987 //\r
9c4ac31c 1988 *IoSpaceMap = AllocatePool (*NumberOfDescriptors * sizeof (EFI_GCD_IO_SPACE_DESCRIPTOR));\r
28a00297 1989 if (*IoSpaceMap == NULL) {\r
1990 Status = EFI_OUT_OF_RESOURCES;\r
1991 goto Done;\r
1992 }\r
1993\r
1994 //\r
1995 // Fill in the IoSpaceMap\r
1996 //\r
1997 Descriptor = *IoSpaceMap;\r
1998 Link = mGcdIoSpaceMap.ForwardLink;\r
1999 while (Link != &mGcdIoSpaceMap) {\r
2000 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
2001 BuildIoDescriptor (Descriptor, Entry);\r
2002 Descriptor++;\r
2003 Link = Link->ForwardLink;\r
2004 }\r
2005 Status = EFI_SUCCESS;\r
2006\r
2007Done:\r
2008 CoreReleaseGcdIoLock ();\r
2009 return Status;\r
022c6d45 2010}\r
28a00297 2011\r
aa927cae 2012\r
162ed594 2013/**\r
2014 Converts a Resource Descriptor HOB attributes mask to an EFI Memory Descriptor\r
2015 capabilities mask\r
2016\r
022c6d45 2017 @param GcdMemoryType Type of resource in the GCD memory map.\r
2018 @param Attributes The attribute mask in the Resource Descriptor\r
2019 HOB.\r
162ed594 2020\r
2021 @return The capabilities mask for an EFI Memory Descriptor.\r
2022\r
2023**/\r
28a00297 2024UINT64\r
2025CoreConvertResourceDescriptorHobAttributesToCapabilities (\r
2026 EFI_GCD_MEMORY_TYPE GcdMemoryType,\r
2027 UINT64 Attributes\r
2028 )\r
28a00297 2029{\r
2030 UINT64 Capabilities;\r
2031 GCD_ATTRIBUTE_CONVERSION_ENTRY *Conversion;\r
022c6d45 2032\r
28a00297 2033 //\r
2034 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask\r
2035 //\r
2036 for (Capabilities = 0, Conversion = mAttributeConversionTable; Conversion->Attribute != 0; Conversion++) {\r
74705ca5 2037 if (Conversion->Memory || ((GcdMemoryType != EfiGcdMemoryTypeSystemMemory) && (GcdMemoryType != EfiGcdMemoryTypeMoreReliable))) {\r
28a00297 2038 if (Attributes & Conversion->Attribute) {\r
2039 Capabilities |= Conversion->Capability;\r
2040 }\r
2041 }\r
2042 }\r
022c6d45 2043\r
28a00297 2044 return Capabilities;\r
2045}\r
2046\r
3a05b131
SZ
2047/**\r
2048 Calculate total memory bin size neeeded.\r
2049\r
2050 @return The total memory bin size neeeded.\r
2051\r
2052**/\r
2053UINT64\r
2054CalculateTotalMemoryBinSizeNeeded (\r
2055 VOID\r
2056 )\r
2057{\r
2058 UINTN Index;\r
2059 UINT64 TotalSize;\r
2060\r
2061 //\r
2062 // Loop through each memory type in the order specified by the gMemoryTypeInformation[] array\r
2063 //\r
2064 TotalSize = 0;\r
2065 for (Index = 0; gMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {\r
2066 TotalSize += LShiftU64 (gMemoryTypeInformation[Index].NumberOfPages, EFI_PAGE_SHIFT);\r
2067 }\r
2068\r
2069 return TotalSize;\r
2070}\r
28a00297 2071\r
162ed594 2072/**\r
c18f12d3 2073 External function. Initializes memory services based on the memory\r
2074 descriptor HOBs. This function is responsible for priming the memory\r
2075 map, so memory allocations and resource allocations can be made.\r
2076 The first part of this function can not depend on any memory services\r
2077 until at least one memory descriptor is provided to the memory services.\r
28a00297 2078\r
022c6d45 2079 @param HobStart The start address of the HOB.\r
2080 @param MemoryBaseAddress Start address of memory region found to init DXE\r
2081 core.\r
2082 @param MemoryLength Length of memory region found to init DXE core.\r
28a00297 2083\r
162ed594 2084 @retval EFI_SUCCESS Memory services successfully initialized.\r
28a00297 2085\r
162ed594 2086**/\r
2087EFI_STATUS\r
2088CoreInitializeMemoryServices (\r
2089 IN VOID **HobStart,\r
2090 OUT EFI_PHYSICAL_ADDRESS *MemoryBaseAddress,\r
2091 OUT UINT64 *MemoryLength\r
2092 )\r
28a00297 2093{\r
2094 EFI_PEI_HOB_POINTERS Hob;\r
2095 EFI_MEMORY_TYPE_INFORMATION *EfiMemoryTypeInformation;\r
2096 UINTN DataSize;\r
2097 BOOLEAN Found;\r
2098 EFI_HOB_HANDOFF_INFO_TABLE *PhitHob;\r
2099 EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;\r
2100 EFI_HOB_RESOURCE_DESCRIPTOR *PhitResourceHob;\r
2101 EFI_PHYSICAL_ADDRESS BaseAddress;\r
2102 UINT64 Length;\r
2103 UINT64 Attributes;\r
2104 UINT64 Capabilities;\r
c4c085a2 2105 EFI_PHYSICAL_ADDRESS TestedMemoryBaseAddress;\r
2106 UINT64 TestedMemoryLength;\r
28a00297 2107 EFI_PHYSICAL_ADDRESS HighAddress;\r
28a00297 2108 EFI_HOB_GUID_TYPE *GuidHob;\r
3a05b131
SZ
2109 UINT32 ReservedCodePageNumber;\r
2110 UINT64 MinimalMemorySizeNeeded;\r
28a00297 2111\r
2112 //\r
2113 // Point at the first HOB. This must be the PHIT HOB.\r
2114 //\r
2115 Hob.Raw = *HobStart;\r
2116 ASSERT (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_HANDOFF);\r
2117\r
2118 //\r
2119 // Initialize the spin locks and maps in the memory services.\r
2120 // Also fill in the memory services into the EFI Boot Services Table\r
2121 //\r
2122 CoreInitializePool ();\r
2123\r
2124 //\r
2125 // Initialize Local Variables\r
2126 //\r
2127 PhitResourceHob = NULL;\r
28a00297 2128 ResourceHob = NULL;\r
2129 BaseAddress = 0;\r
2130 Length = 0;\r
2131 Attributes = 0;\r
28a00297 2132\r
2133 //\r
2134 // Cache the PHIT HOB for later use\r
2135 //\r
2136 PhitHob = Hob.HandoffInformationTable;\r
54ea99a7 2137 \r
852081fc 2138 if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {\r
54ea99a7 2139 ReservedCodePageNumber = PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber);\r
2140 ReservedCodePageNumber += PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber);\r
2141 \r
2142 //\r
2143 // cache the Top address for loading modules at Fixed Address \r
2144 //\r
2145 gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress = PhitHob->EfiMemoryTop \r
2146 + EFI_PAGES_TO_SIZE(ReservedCodePageNumber);\r
2147 }\r
28a00297 2148 //\r
2149 // See if a Memory Type Information HOB is available\r
2150 //\r
2151 GuidHob = GetFirstGuidHob (&gEfiMemoryTypeInformationGuid);\r
2152 if (GuidHob != NULL) {\r
2153 EfiMemoryTypeInformation = GET_GUID_HOB_DATA (GuidHob);\r
2154 DataSize = GET_GUID_HOB_DATA_SIZE (GuidHob);\r
2155 if (EfiMemoryTypeInformation != NULL && DataSize > 0 && DataSize <= (EfiMaxMemoryType + 1) * sizeof (EFI_MEMORY_TYPE_INFORMATION)) {\r
2156 CopyMem (&gMemoryTypeInformation, EfiMemoryTypeInformation, DataSize);\r
2157 }\r
2158 }\r
2159\r
3a05b131
SZ
2160 //\r
2161 // Include the total memory bin size needed to make sure memory bin could be allocated successfully.\r
2162 //\r
2163 MinimalMemorySizeNeeded = MINIMUM_INITIAL_MEMORY_SIZE + CalculateTotalMemoryBinSizeNeeded ();\r
2164\r
28a00297 2165 //\r
c4c085a2 2166 // Find the Resource Descriptor HOB that contains PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop\r
28a00297 2167 //\r
28a00297 2168 Found = FALSE;\r
2169 for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {\r
c4c085a2 2170 //\r
2171 // Skip all HOBs except Resource Descriptor HOBs\r
2172 //\r
2173 if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
2174 continue;\r
2175 }\r
28a00297 2176\r
c4c085a2 2177 //\r
2178 // Skip Resource Descriptor HOBs that do not describe tested system memory\r
2179 //\r
2180 ResourceHob = Hob.ResourceDescriptor;\r
2181 if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) {\r
2182 continue;\r
2183 }\r
2184 if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) {\r
2185 continue;\r
2186 }\r
2187\r
2188 //\r
2189 // Skip Resource Descriptor HOBs that do not contain the PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop\r
2190 //\r
2191 if (PhitHob->EfiFreeMemoryBottom < ResourceHob->PhysicalStart) {\r
2192 continue;\r
2193 }\r
2194 if (PhitHob->EfiFreeMemoryTop > (ResourceHob->PhysicalStart + ResourceHob->ResourceLength)) {\r
2195 continue;\r
2196 }\r
2197\r
2198 //\r
2199 // Cache the resource descriptor HOB for the memory region described by the PHIT HOB\r
2200 //\r
2201 PhitResourceHob = ResourceHob;\r
2202 Found = TRUE;\r
2203\r
2204 //\r
3a05b131 2205 // Compute range between PHIT EfiMemoryTop and the end of the Resource Descriptor HOB\r
c4c085a2 2206 //\r
2207 Attributes = PhitResourceHob->ResourceAttribute;\r
2208 BaseAddress = PageAlignAddress (PhitHob->EfiMemoryTop);\r
2209 Length = PageAlignLength (ResourceHob->PhysicalStart + ResourceHob->ResourceLength - BaseAddress);\r
3a05b131 2210 if (Length < MinimalMemorySizeNeeded) {\r
c4c085a2 2211 //\r
2212 // If that range is not large enough to intialize the DXE Core, then \r
2213 // Compute range between PHIT EfiFreeMemoryBottom and PHIT EfiFreeMemoryTop\r
2214 //\r
2215 BaseAddress = PageAlignAddress (PhitHob->EfiFreeMemoryBottom);\r
2216 Length = PageAlignLength (PhitHob->EfiFreeMemoryTop - BaseAddress);\r
3a05b131 2217 if (Length < MinimalMemorySizeNeeded) {\r
c4c085a2 2218 //\r
2219 // If that range is not large enough to intialize the DXE Core, then \r
2220 // Compute range between the start of the Resource Descriptor HOB and the start of the HOB List\r
2221 //\r
2222 BaseAddress = PageAlignAddress (ResourceHob->PhysicalStart);\r
2223 Length = PageAlignLength ((UINT64)((UINTN)*HobStart - BaseAddress));\r
28a00297 2224 }\r
2225 }\r
c4c085a2 2226 break;\r
28a00297 2227 }\r
2228\r
2229 //\r
2230 // Assert if a resource descriptor HOB for the memory region described by the PHIT was not found\r
2231 //\r
2232 ASSERT (Found);\r
2233\r
2234 //\r
3a05b131
SZ
2235 // Take the range in the resource descriptor HOB for the memory region described\r
2236 // by the PHIT as higher priority if it is big enough. It can make the memory bin\r
2237 // allocated to be at the same memory region with PHIT that has more better compatibility\r
2238 // to avoid memory fragmentation for some code practices assume and allocate <4G ACPI memory.\r
28a00297 2239 //\r
3a05b131 2240 if (Length < MinimalMemorySizeNeeded) {\r
c4c085a2 2241 //\r
3a05b131
SZ
2242 // Search all the resource descriptor HOBs from the highest possible addresses down for a memory\r
2243 // region that is big enough to initialize the DXE core. Always skip the PHIT Resource HOB.\r
2244 // The max address must be within the physically addressible range for the processor.\r
c4c085a2 2245 //\r
3a05b131
SZ
2246 HighAddress = MAX_ADDRESS;\r
2247 for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {\r
2248 //\r
2249 // Skip the Resource Descriptor HOB that contains the PHIT\r
2250 //\r
2251 if (Hob.ResourceDescriptor == PhitResourceHob) {\r
2252 continue;\r
2253 }\r
2254 //\r
2255 // Skip all HOBs except Resource Descriptor HOBs\r
2256 //\r
2257 if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
2258 continue;\r
2259 }\r
28a00297 2260\r
3a05b131
SZ
2261 //\r
2262 // Skip Resource Descriptor HOBs that do not describe tested system memory below MAX_ADDRESS\r
2263 //\r
2264 ResourceHob = Hob.ResourceDescriptor;\r
2265 if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) {\r
2266 continue;\r
2267 }\r
2268 if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) {\r
2269 continue;\r
2270 }\r
2271 if ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength) > (EFI_PHYSICAL_ADDRESS)MAX_ADDRESS) {\r
2272 continue;\r
2273 }\r
c4c085a2 2274\r
3a05b131
SZ
2275 //\r
2276 // Skip Resource Descriptor HOBs that are below a previously found Resource Descriptor HOB\r
2277 //\r
2278 if (HighAddress != (EFI_PHYSICAL_ADDRESS)MAX_ADDRESS && ResourceHob->PhysicalStart <= HighAddress) {\r
2279 continue;\r
2280 }\r
2281\r
2282 //\r
2283 // Skip Resource Descriptor HOBs that are not large enough to initilize the DXE Core\r
2284 //\r
2285 TestedMemoryBaseAddress = PageAlignAddress (ResourceHob->PhysicalStart);\r
2286 TestedMemoryLength = PageAlignLength (ResourceHob->PhysicalStart + ResourceHob->ResourceLength - TestedMemoryBaseAddress);\r
2287 if (TestedMemoryLength < MinimalMemorySizeNeeded) {\r
2288 continue;\r
2289 }\r
2290\r
2291 //\r
2292 // Save the range described by the Resource Descriptor that is large enough to initilize the DXE Core\r
2293 //\r
2294 BaseAddress = TestedMemoryBaseAddress;\r
2295 Length = TestedMemoryLength;\r
2296 Attributes = ResourceHob->ResourceAttribute; \r
2297 HighAddress = ResourceHob->PhysicalStart;\r
c4c085a2 2298 }\r
c4c085a2 2299 }\r
28a00297 2300\r
3a05b131
SZ
2301 DEBUG ((EFI_D_INFO, "CoreInitializeMemoryServices:\n"));\r
2302 DEBUG ((EFI_D_INFO, " BaseAddress - 0x%lx Length - 0x%lx MinimalMemorySizeNeeded - 0x%lx\n", BaseAddress, Length, MinimalMemorySizeNeeded));\r
28a00297 2303\r
2304 //\r
2305 // If no memory regions are found that are big enough to initialize the DXE core, then ASSERT().\r
2306 //\r
3a05b131 2307 ASSERT (Length >= MinimalMemorySizeNeeded);\r
28a00297 2308\r
2309 //\r
2310 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask\r
2311 //\r
74705ca5
SZ
2312 if ((Attributes & EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE) == EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE) {\r
2313 Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeMoreReliable, Attributes);\r
2314 } else {\r
2315 Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeSystemMemory, Attributes);\r
2316 }\r
28a00297 2317\r
2318 //\r
2319 // Declare the very first memory region, so the EFI Memory Services are available.\r
2320 //\r
2321 CoreAddMemoryDescriptor (\r
2322 EfiConventionalMemory,\r
2323 BaseAddress,\r
2324 RShiftU64 (Length, EFI_PAGE_SHIFT),\r
2325 Capabilities\r
2326 );\r
2327\r
2328 *MemoryBaseAddress = BaseAddress;\r
2329 *MemoryLength = Length;\r
2330\r
2331 return EFI_SUCCESS;\r
2332}\r
2333\r
28a00297 2334\r
162ed594 2335/**\r
2336 External function. Initializes the GCD and memory services based on the memory\r
28a00297 2337 descriptor HOBs. This function is responsible for priming the GCD map and the\r
c18f12d3 2338 memory map, so memory allocations and resource allocations can be made. The\r
2339 HobStart will be relocated to a pool buffer.\r
28a00297 2340\r
022c6d45 2341 @param HobStart The start address of the HOB\r
2342 @param MemoryBaseAddress Start address of memory region found to init DXE\r
2343 core.\r
2344 @param MemoryLength Length of memory region found to init DXE core.\r
28a00297 2345\r
162ed594 2346 @retval EFI_SUCCESS GCD services successfully initialized.\r
28a00297 2347\r
162ed594 2348**/\r
2349EFI_STATUS\r
2350CoreInitializeGcdServices (\r
e94a9ff7 2351 IN OUT VOID **HobStart,\r
162ed594 2352 IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress,\r
2353 IN UINT64 MemoryLength\r
2354 )\r
28a00297 2355{\r
e94a9ff7 2356 EFI_PEI_HOB_POINTERS Hob;\r
28a00297 2357 VOID *NewHobList;\r
e94a9ff7 2358 EFI_HOB_HANDOFF_INFO_TABLE *PhitHob;\r
28a00297 2359 UINT8 SizeOfMemorySpace;\r
2360 UINT8 SizeOfIoSpace;\r
2361 EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;\r
2362 EFI_PHYSICAL_ADDRESS BaseAddress;\r
2363 UINT64 Length;\r
2364 EFI_STATUS Status;\r
2365 EFI_GCD_MAP_ENTRY *Entry;\r
2366 EFI_GCD_MEMORY_TYPE GcdMemoryType;\r
2367 EFI_GCD_IO_TYPE GcdIoType;\r
2368 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;\r
2369 EFI_HOB_MEMORY_ALLOCATION *MemoryHob;\r
2370 EFI_HOB_FIRMWARE_VOLUME *FirmwareVolumeHob;\r
2371 UINTN NumberOfDescriptors;\r
2372 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;\r
2373 UINTN Index;\r
2374 UINT64 Capabilities;\r
2375 EFI_HOB_CPU * CpuHob;\r
a46bbdd3 2376 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMapHobList;\r
e94a9ff7 2377\r
28a00297 2378 //\r
2379 // Cache the PHIT HOB for later use\r
2380 //\r
2381 PhitHob = (EFI_HOB_HANDOFF_INFO_TABLE *)(*HobStart);\r
2382\r
2383 //\r
2384 // Get the number of address lines in the I/O and Memory space for the CPU\r
2385 //\r
2386 CpuHob = GetFirstHob (EFI_HOB_TYPE_CPU);\r
2387 ASSERT (CpuHob != NULL);\r
2388 SizeOfMemorySpace = CpuHob->SizeOfMemorySpace;\r
2389 SizeOfIoSpace = CpuHob->SizeOfIoSpace;\r
022c6d45 2390\r
28a00297 2391 //\r
2392 // Initialize the GCD Memory Space Map\r
2393 //\r
9c4ac31c 2394 Entry = AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY), &mGcdMemorySpaceMapEntryTemplate);\r
28a00297 2395 ASSERT (Entry != NULL);\r
2396\r
2397 Entry->EndAddress = LShiftU64 (1, SizeOfMemorySpace) - 1;\r
2398\r
2399 InsertHeadList (&mGcdMemorySpaceMap, &Entry->Link);\r
2400\r
aa927cae 2401 CoreDumpGcdMemorySpaceMap (TRUE);\r
f9d1f97c 2402 \r
28a00297 2403 //\r
2404 // Initialize the GCD I/O Space Map\r
2405 //\r
9c4ac31c 2406 Entry = AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY), &mGcdIoSpaceMapEntryTemplate);\r
28a00297 2407 ASSERT (Entry != NULL);\r
2408\r
2409 Entry->EndAddress = LShiftU64 (1, SizeOfIoSpace) - 1;\r
2410\r
2411 InsertHeadList (&mGcdIoSpaceMap, &Entry->Link);\r
2412\r
aa927cae 2413 CoreDumpGcdIoSpaceMap (TRUE);\r
f9d1f97c 2414 \r
28a00297 2415 //\r
022c6d45 2416 // Walk the HOB list and add all resource descriptors to the GCD\r
28a00297 2417 //\r
2418 for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {\r
2419\r
2420 GcdMemoryType = EfiGcdMemoryTypeNonExistent;\r
2421 GcdIoType = EfiGcdIoTypeNonExistent;\r
2422\r
2423 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
2424\r
2425 ResourceHob = Hob.ResourceDescriptor;\r
2426\r
2427 switch (ResourceHob->ResourceType) {\r
2428 case EFI_RESOURCE_SYSTEM_MEMORY:\r
2429 if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == TESTED_MEMORY_ATTRIBUTES) {\r
74705ca5
SZ
2430 if ((ResourceHob->ResourceAttribute & EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE) == EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE) {\r
2431 GcdMemoryType = EfiGcdMemoryTypeMoreReliable;\r
2432 } else {\r
2433 GcdMemoryType = EfiGcdMemoryTypeSystemMemory;\r
2434 }\r
28a00297 2435 }\r
2436 if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == INITIALIZED_MEMORY_ATTRIBUTES) {\r
2437 GcdMemoryType = EfiGcdMemoryTypeReserved;\r
2438 }\r
2439 if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == PRESENT_MEMORY_ATTRIBUTES) {\r
2440 GcdMemoryType = EfiGcdMemoryTypeReserved;\r
2441 }\r
a671a012 2442 if ((ResourceHob->ResourceAttribute & EFI_RESOURCE_ATTRIBUTE_PERSISTENT) == EFI_RESOURCE_ATTRIBUTE_PERSISTENT) {\r
35ac962b 2443 GcdMemoryType = EfiGcdMemoryTypePersistent;\r
a671a012 2444 }\r
28a00297 2445 break;\r
2446 case EFI_RESOURCE_MEMORY_MAPPED_IO:\r
2447 case EFI_RESOURCE_FIRMWARE_DEVICE:\r
2448 GcdMemoryType = EfiGcdMemoryTypeMemoryMappedIo;\r
2449 break;\r
2450 case EFI_RESOURCE_MEMORY_MAPPED_IO_PORT:\r
2451 case EFI_RESOURCE_MEMORY_RESERVED:\r
2452 GcdMemoryType = EfiGcdMemoryTypeReserved;\r
2453 break;\r
2454 case EFI_RESOURCE_IO:\r
2455 GcdIoType = EfiGcdIoTypeIo;\r
2456 break;\r
2457 case EFI_RESOURCE_IO_RESERVED:\r
2458 GcdIoType = EfiGcdIoTypeReserved;\r
2459 break;\r
2460 }\r
2461\r
2462 if (GcdMemoryType != EfiGcdMemoryTypeNonExistent) {\r
d12a2ecb 2463 //\r
2464 // Validate the Resource HOB Attributes\r
2465 //\r
2466 CoreValidateResourceDescriptorHobAttributes (ResourceHob->ResourceAttribute);\r
2467\r
28a00297 2468 //\r
2469 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask\r
2470 //\r
2471 Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities (\r
2472 GcdMemoryType,\r
2473 ResourceHob->ResourceAttribute\r
2474 );\r
2475\r
2476 Status = CoreInternalAddMemorySpace (\r
2477 GcdMemoryType,\r
2478 ResourceHob->PhysicalStart,\r
2479 ResourceHob->ResourceLength,\r
2480 Capabilities\r
2481 );\r
2482 }\r
2483\r
2484 if (GcdIoType != EfiGcdIoTypeNonExistent) {\r
2485 Status = CoreAddIoSpace (\r
2486 GcdIoType,\r
2487 ResourceHob->PhysicalStart,\r
2488 ResourceHob->ResourceLength\r
2489 );\r
2490 }\r
2491 }\r
2492 }\r
2493\r
2494 //\r
2495 // Allocate first memory region from the GCD by the DXE core\r
2496 //\r
74705ca5
SZ
2497 Status = CoreGetMemorySpaceDescriptor (MemoryBaseAddress, &Descriptor);\r
2498 if (!EFI_ERROR (Status)) {\r
2499 ASSERT ((Descriptor.GcdMemoryType == EfiGcdMemoryTypeSystemMemory) ||\r
2500 (Descriptor.GcdMemoryType == EfiGcdMemoryTypeMoreReliable));\r
2501 Status = CoreAllocateMemorySpace (\r
2502 EfiGcdAllocateAddress,\r
2503 Descriptor.GcdMemoryType,\r
2504 0,\r
2505 MemoryLength,\r
2506 &MemoryBaseAddress,\r
2507 gDxeCoreImageHandle,\r
2508 NULL\r
2509 );\r
2510 }\r
28a00297 2511\r
2512 //\r
2513 // Walk the HOB list and allocate all memory space that is consumed by memory allocation HOBs,\r
2514 // and Firmware Volume HOBs. Also update the EFI Memory Map with the memory allocation HOBs.\r
2515 //\r
2516 for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {\r
2517 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) {\r
2518 MemoryHob = Hob.MemoryAllocation;\r
2519 BaseAddress = MemoryHob->AllocDescriptor.MemoryBaseAddress;\r
f942f107 2520 Status = CoreGetMemorySpaceDescriptor (BaseAddress, &Descriptor);\r
28a00297 2521 if (!EFI_ERROR (Status)) {\r
f942f107 2522 Status = CoreAllocateMemorySpace (\r
2523 EfiGcdAllocateAddress,\r
022c6d45 2524 Descriptor.GcdMemoryType,\r
f942f107 2525 0,\r
2526 MemoryHob->AllocDescriptor.MemoryLength,\r
2527 &BaseAddress,\r
2528 gDxeCoreImageHandle,\r
2529 NULL\r
2530 );\r
74705ca5
SZ
2531 if (!EFI_ERROR (Status) &&\r
2532 ((Descriptor.GcdMemoryType == EfiGcdMemoryTypeSystemMemory) ||\r
2533 (Descriptor.GcdMemoryType == EfiGcdMemoryTypeMoreReliable))) {\r
28a00297 2534 CoreAddMemoryDescriptor (\r
2535 MemoryHob->AllocDescriptor.MemoryType,\r
2536 MemoryHob->AllocDescriptor.MemoryBaseAddress,\r
2537 RShiftU64 (MemoryHob->AllocDescriptor.MemoryLength, EFI_PAGE_SHIFT),\r
2538 Descriptor.Capabilities & (~EFI_MEMORY_RUNTIME)\r
2539 );\r
2540 }\r
2541 }\r
2542 }\r
2543\r
2544 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV) {\r
2545 FirmwareVolumeHob = Hob.FirmwareVolume;\r
2546 BaseAddress = FirmwareVolumeHob->BaseAddress;\r
2547 Status = CoreAllocateMemorySpace (\r
2548 EfiGcdAllocateAddress,\r
022c6d45 2549 EfiGcdMemoryTypeMemoryMappedIo,\r
28a00297 2550 0,\r
2551 FirmwareVolumeHob->Length,\r
2552 &BaseAddress,\r
2553 gDxeCoreImageHandle,\r
2554 NULL\r
2555 );\r
2556 }\r
2557 }\r
2558\r
28a00297 2559 //\r
2560 // Add and allocate the remaining unallocated system memory to the memory services.\r
2561 //\r
2562 Status = CoreGetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);\r
311a71b2 2563 ASSERT (Status == EFI_SUCCESS);\r
2564\r
a46bbdd3 2565 MemorySpaceMapHobList = NULL;\r
28a00297 2566 for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
74705ca5
SZ
2567 if ((MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeSystemMemory) ||\r
2568 (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeMoreReliable)) {\r
28a00297 2569 if (MemorySpaceMap[Index].ImageHandle == NULL) {\r
2570 BaseAddress = PageAlignAddress (MemorySpaceMap[Index].BaseAddress);\r
2571 Length = PageAlignLength (MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - BaseAddress);\r
383c303c 2572 if (Length == 0 || MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length < BaseAddress) {\r
2573 continue;\r
2574 }\r
a46bbdd3
SZ
2575 if (((UINTN) MemorySpaceMap[Index].BaseAddress <= (UINTN) (*HobStart)) &&\r
2576 ((UINTN) (MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) >= (UINTN) PhitHob->EfiFreeMemoryBottom)) {\r
2577 //\r
2578 // Skip the memory space that covers HOB List, it should be processed\r
2579 // after HOB List relocation to avoid the resources allocated by others\r
2580 // to corrupt HOB List before its relocation.\r
2581 //\r
2582 MemorySpaceMapHobList = &MemorySpaceMap[Index];\r
2583 continue;\r
2584 }\r
28a00297 2585 CoreAddMemoryDescriptor (\r
2586 EfiConventionalMemory,\r
2587 BaseAddress,\r
2588 RShiftU64 (Length, EFI_PAGE_SHIFT),\r
2589 MemorySpaceMap[Index].Capabilities & (~EFI_MEMORY_RUNTIME)\r
2590 );\r
2591 Status = CoreAllocateMemorySpace (\r
2592 EfiGcdAllocateAddress,\r
74705ca5 2593 MemorySpaceMap[Index].GcdMemoryType,\r
28a00297 2594 0,\r
2595 Length,\r
2596 &BaseAddress,\r
2597 gDxeCoreImageHandle,\r
2598 NULL\r
2599 );\r
2600 }\r
2601 }\r
2602 }\r
a46bbdd3
SZ
2603\r
2604 //\r
2605 // Relocate HOB List to an allocated pool buffer.\r
2606 // The relocation should be at after all the tested memory resources added\r
2607 // (except the memory space that covers HOB List) to the memory services,\r
2608 // because the memory resource found in CoreInitializeMemoryServices()\r
2609 // may have not enough remaining resource for HOB List.\r
2610 //\r
2611 NewHobList = AllocateCopyPool (\r
2612 (UINTN) PhitHob->EfiFreeMemoryBottom - (UINTN) (*HobStart),\r
2613 *HobStart\r
2614 );\r
2615 ASSERT (NewHobList != NULL);\r
2616\r
2617 *HobStart = NewHobList;\r
2618 gHobList = NewHobList;\r
2619\r
2620 if (MemorySpaceMapHobList != NULL) {\r
2621 //\r
2622 // Add and allocate the memory space that covers HOB List to the memory services\r
2623 // after HOB List relocation.\r
2624 //\r
2625 BaseAddress = PageAlignAddress (MemorySpaceMapHobList->BaseAddress);\r
2626 Length = PageAlignLength (MemorySpaceMapHobList->BaseAddress + MemorySpaceMapHobList->Length - BaseAddress);\r
2627 CoreAddMemoryDescriptor (\r
2628 EfiConventionalMemory,\r
2629 BaseAddress,\r
2630 RShiftU64 (Length, EFI_PAGE_SHIFT),\r
2631 MemorySpaceMapHobList->Capabilities & (~EFI_MEMORY_RUNTIME)\r
2632 );\r
2633 Status = CoreAllocateMemorySpace (\r
2634 EfiGcdAllocateAddress,\r
2635 MemorySpaceMapHobList->GcdMemoryType,\r
2636 0,\r
2637 Length,\r
2638 &BaseAddress,\r
2639 gDxeCoreImageHandle,\r
2640 NULL\r
2641 );\r
2642 }\r
2643\r
28a00297 2644 CoreFreePool (MemorySpaceMap);\r
2645\r
2646 return EFI_SUCCESS;\r
2647}\r