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