]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Gcd/Gcd.c
FatPkg: Change use of EFI_D_* to DEBUG_*
[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
978b9d51
JB
2100/**\r
2101 Find the largest region in the specified region that is not covered by an existing memory allocation\r
2102\r
2103 @param BaseAddress On input start of the region to check.\r
2104 On output start of the largest free region.\r
2105 @param Length On input size of region to check.\r
2106 On output size of the largest free region.\r
2107 @param MemoryHob Hob pointer for the first memory allocation pointer to check\r
2108**/\r
2109VOID\r
2110FindLargestFreeRegion (\r
2111 IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,\r
2112 IN OUT UINT64 *Length,\r
2113 IN EFI_HOB_MEMORY_ALLOCATION *MemoryHob\r
2114 )\r
2115{\r
2116 EFI_PHYSICAL_ADDRESS TopAddress;\r
2117 EFI_PHYSICAL_ADDRESS AllocatedTop;\r
2118 EFI_PHYSICAL_ADDRESS LowerBase;\r
2119 UINT64 LowerSize;\r
2120 EFI_PHYSICAL_ADDRESS UpperBase;\r
2121 UINT64 UpperSize;\r
2122\r
2123 TopAddress = *BaseAddress + *Length;\r
2124 while (MemoryHob != NULL) {\r
2125 AllocatedTop = MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength;\r
2126\r
2127 if ((MemoryHob->AllocDescriptor.MemoryBaseAddress >= *BaseAddress) &&\r
2128 (AllocatedTop <= TopAddress)) {\r
2129 LowerBase = *BaseAddress;\r
2130 LowerSize = MemoryHob->AllocDescriptor.MemoryBaseAddress - *BaseAddress;\r
2131 UpperBase = AllocatedTop;\r
2132 UpperSize = TopAddress - AllocatedTop;\r
2133\r
2134 if (LowerSize != 0) {\r
2135 FindLargestFreeRegion (&LowerBase, &LowerSize, (EFI_HOB_MEMORY_ALLOCATION *) GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, GET_NEXT_HOB (MemoryHob)));\r
2136 }\r
2137 if (UpperSize != 0) {\r
2138 FindLargestFreeRegion (&UpperBase, &UpperSize, (EFI_HOB_MEMORY_ALLOCATION *) GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, GET_NEXT_HOB (MemoryHob)));\r
2139 }\r
2140\r
2141 if (UpperSize >= LowerSize) {\r
2142 *Length = UpperSize;\r
2143 *BaseAddress = UpperBase;\r
2144 } else {\r
2145 *Length = LowerSize;\r
2146 *BaseAddress = LowerBase;\r
2147 }\r
2148 return;\r
2149 }\r
2150 MemoryHob = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, GET_NEXT_HOB (MemoryHob));\r
2151 }\r
2152}\r
2153\r
162ed594 2154/**\r
c18f12d3 2155 External function. Initializes memory services based on the memory\r
2156 descriptor HOBs. This function is responsible for priming the memory\r
2157 map, so memory allocations and resource allocations can be made.\r
2158 The first part of this function can not depend on any memory services\r
2159 until at least one memory descriptor is provided to the memory services.\r
28a00297 2160\r
022c6d45 2161 @param HobStart The start address of the HOB.\r
2162 @param MemoryBaseAddress Start address of memory region found to init DXE\r
2163 core.\r
2164 @param MemoryLength Length of memory region found to init DXE core.\r
28a00297 2165\r
162ed594 2166 @retval EFI_SUCCESS Memory services successfully initialized.\r
28a00297 2167\r
162ed594 2168**/\r
2169EFI_STATUS\r
2170CoreInitializeMemoryServices (\r
2171 IN VOID **HobStart,\r
2172 OUT EFI_PHYSICAL_ADDRESS *MemoryBaseAddress,\r
2173 OUT UINT64 *MemoryLength\r
2174 )\r
28a00297 2175{\r
2176 EFI_PEI_HOB_POINTERS Hob;\r
2177 EFI_MEMORY_TYPE_INFORMATION *EfiMemoryTypeInformation;\r
2178 UINTN DataSize;\r
2179 BOOLEAN Found;\r
2180 EFI_HOB_HANDOFF_INFO_TABLE *PhitHob;\r
2181 EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;\r
2182 EFI_HOB_RESOURCE_DESCRIPTOR *PhitResourceHob;\r
2183 EFI_PHYSICAL_ADDRESS BaseAddress;\r
2184 UINT64 Length;\r
2185 UINT64 Attributes;\r
2186 UINT64 Capabilities;\r
c4c085a2 2187 EFI_PHYSICAL_ADDRESS TestedMemoryBaseAddress;\r
2188 UINT64 TestedMemoryLength;\r
28a00297 2189 EFI_PHYSICAL_ADDRESS HighAddress;\r
28a00297 2190 EFI_HOB_GUID_TYPE *GuidHob;\r
3a05b131
SZ
2191 UINT32 ReservedCodePageNumber;\r
2192 UINT64 MinimalMemorySizeNeeded;\r
28a00297 2193\r
2194 //\r
2195 // Point at the first HOB. This must be the PHIT HOB.\r
2196 //\r
2197 Hob.Raw = *HobStart;\r
2198 ASSERT (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_HANDOFF);\r
2199\r
2200 //\r
2201 // Initialize the spin locks and maps in the memory services.\r
2202 // Also fill in the memory services into the EFI Boot Services Table\r
2203 //\r
2204 CoreInitializePool ();\r
2205\r
2206 //\r
2207 // Initialize Local Variables\r
2208 //\r
2209 PhitResourceHob = NULL;\r
28a00297 2210 ResourceHob = NULL;\r
2211 BaseAddress = 0;\r
2212 Length = 0;\r
2213 Attributes = 0;\r
28a00297 2214\r
2215 //\r
2216 // Cache the PHIT HOB for later use\r
2217 //\r
2218 PhitHob = Hob.HandoffInformationTable;\r
d1102dba 2219\r
852081fc 2220 if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {\r
d1102dba
LG
2221 ReservedCodePageNumber = PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber);\r
2222 ReservedCodePageNumber += PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber);\r
2223\r
2224 //\r
2225 // cache the Top address for loading modules at Fixed Address\r
2226 //\r
2227 gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress = PhitHob->EfiMemoryTop\r
54ea99a7 2228 + EFI_PAGES_TO_SIZE(ReservedCodePageNumber);\r
2229 }\r
28a00297 2230 //\r
2231 // See if a Memory Type Information HOB is available\r
2232 //\r
2233 GuidHob = GetFirstGuidHob (&gEfiMemoryTypeInformationGuid);\r
2234 if (GuidHob != NULL) {\r
2235 EfiMemoryTypeInformation = GET_GUID_HOB_DATA (GuidHob);\r
2236 DataSize = GET_GUID_HOB_DATA_SIZE (GuidHob);\r
2237 if (EfiMemoryTypeInformation != NULL && DataSize > 0 && DataSize <= (EfiMaxMemoryType + 1) * sizeof (EFI_MEMORY_TYPE_INFORMATION)) {\r
2238 CopyMem (&gMemoryTypeInformation, EfiMemoryTypeInformation, DataSize);\r
2239 }\r
2240 }\r
2241\r
3a05b131
SZ
2242 //\r
2243 // Include the total memory bin size needed to make sure memory bin could be allocated successfully.\r
2244 //\r
2245 MinimalMemorySizeNeeded = MINIMUM_INITIAL_MEMORY_SIZE + CalculateTotalMemoryBinSizeNeeded ();\r
2246\r
28a00297 2247 //\r
c4c085a2 2248 // Find the Resource Descriptor HOB that contains PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop\r
28a00297 2249 //\r
28a00297 2250 Found = FALSE;\r
2251 for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {\r
c4c085a2 2252 //\r
2253 // Skip all HOBs except Resource Descriptor HOBs\r
2254 //\r
2255 if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
2256 continue;\r
2257 }\r
28a00297 2258\r
c4c085a2 2259 //\r
2260 // Skip Resource Descriptor HOBs that do not describe tested system memory\r
2261 //\r
2262 ResourceHob = Hob.ResourceDescriptor;\r
2263 if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) {\r
2264 continue;\r
2265 }\r
2266 if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) {\r
2267 continue;\r
2268 }\r
2269\r
2270 //\r
2271 // Skip Resource Descriptor HOBs that do not contain the PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop\r
2272 //\r
2273 if (PhitHob->EfiFreeMemoryBottom < ResourceHob->PhysicalStart) {\r
2274 continue;\r
2275 }\r
2276 if (PhitHob->EfiFreeMemoryTop > (ResourceHob->PhysicalStart + ResourceHob->ResourceLength)) {\r
2277 continue;\r
2278 }\r
2279\r
2280 //\r
2281 // Cache the resource descriptor HOB for the memory region described by the PHIT HOB\r
2282 //\r
2283 PhitResourceHob = ResourceHob;\r
2284 Found = TRUE;\r
2285\r
2286 //\r
3a05b131 2287 // Compute range between PHIT EfiMemoryTop and the end of the Resource Descriptor HOB\r
c4c085a2 2288 //\r
2289 Attributes = PhitResourceHob->ResourceAttribute;\r
2290 BaseAddress = PageAlignAddress (PhitHob->EfiMemoryTop);\r
2291 Length = PageAlignLength (ResourceHob->PhysicalStart + ResourceHob->ResourceLength - BaseAddress);\r
978b9d51 2292 FindLargestFreeRegion (&BaseAddress, &Length, (EFI_HOB_MEMORY_ALLOCATION *)GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION));\r
3a05b131 2293 if (Length < MinimalMemorySizeNeeded) {\r
c4c085a2 2294 //\r
d1102dba 2295 // If that range is not large enough to intialize the DXE Core, then\r
c4c085a2 2296 // Compute range between PHIT EfiFreeMemoryBottom and PHIT EfiFreeMemoryTop\r
2297 //\r
2298 BaseAddress = PageAlignAddress (PhitHob->EfiFreeMemoryBottom);\r
2299 Length = PageAlignLength (PhitHob->EfiFreeMemoryTop - BaseAddress);\r
978b9d51 2300 //This region is required to have no memory allocation inside it, skip check for entries in HOB List\r
3a05b131 2301 if (Length < MinimalMemorySizeNeeded) {\r
c4c085a2 2302 //\r
d1102dba 2303 // If that range is not large enough to intialize the DXE Core, then\r
c4c085a2 2304 // Compute range between the start of the Resource Descriptor HOB and the start of the HOB List\r
2305 //\r
2306 BaseAddress = PageAlignAddress (ResourceHob->PhysicalStart);\r
2307 Length = PageAlignLength ((UINT64)((UINTN)*HobStart - BaseAddress));\r
978b9d51 2308 FindLargestFreeRegion (&BaseAddress, &Length, (EFI_HOB_MEMORY_ALLOCATION *)GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION));\r
28a00297 2309 }\r
2310 }\r
c4c085a2 2311 break;\r
28a00297 2312 }\r
2313\r
2314 //\r
2315 // Assert if a resource descriptor HOB for the memory region described by the PHIT was not found\r
2316 //\r
2317 ASSERT (Found);\r
2318\r
2319 //\r
3a05b131
SZ
2320 // Take the range in the resource descriptor HOB for the memory region described\r
2321 // by the PHIT as higher priority if it is big enough. It can make the memory bin\r
2322 // allocated to be at the same memory region with PHIT that has more better compatibility\r
2323 // to avoid memory fragmentation for some code practices assume and allocate <4G ACPI memory.\r
28a00297 2324 //\r
3a05b131 2325 if (Length < MinimalMemorySizeNeeded) {\r
c4c085a2 2326 //\r
3a05b131
SZ
2327 // Search all the resource descriptor HOBs from the highest possible addresses down for a memory\r
2328 // region that is big enough to initialize the DXE core. Always skip the PHIT Resource HOB.\r
2329 // The max address must be within the physically addressible range for the processor.\r
c4c085a2 2330 //\r
36b07547 2331 HighAddress = MAX_ALLOC_ADDRESS;\r
3a05b131
SZ
2332 for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {\r
2333 //\r
2334 // Skip the Resource Descriptor HOB that contains the PHIT\r
2335 //\r
2336 if (Hob.ResourceDescriptor == PhitResourceHob) {\r
2337 continue;\r
2338 }\r
2339 //\r
2340 // Skip all HOBs except Resource Descriptor HOBs\r
2341 //\r
2342 if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
2343 continue;\r
2344 }\r
28a00297 2345\r
3a05b131 2346 //\r
36b07547 2347 // Skip Resource Descriptor HOBs that do not describe tested system memory below MAX_ALLOC_ADDRESS\r
3a05b131
SZ
2348 //\r
2349 ResourceHob = Hob.ResourceDescriptor;\r
2350 if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) {\r
2351 continue;\r
2352 }\r
2353 if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) {\r
2354 continue;\r
2355 }\r
36b07547 2356 if ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength) > (EFI_PHYSICAL_ADDRESS)MAX_ALLOC_ADDRESS) {\r
3a05b131
SZ
2357 continue;\r
2358 }\r
c4c085a2 2359\r
3a05b131
SZ
2360 //\r
2361 // Skip Resource Descriptor HOBs that are below a previously found Resource Descriptor HOB\r
2362 //\r
36b07547 2363 if (HighAddress != (EFI_PHYSICAL_ADDRESS)MAX_ALLOC_ADDRESS && ResourceHob->PhysicalStart <= HighAddress) {\r
3a05b131
SZ
2364 continue;\r
2365 }\r
2366\r
2367 //\r
2368 // Skip Resource Descriptor HOBs that are not large enough to initilize the DXE Core\r
2369 //\r
2370 TestedMemoryBaseAddress = PageAlignAddress (ResourceHob->PhysicalStart);\r
2371 TestedMemoryLength = PageAlignLength (ResourceHob->PhysicalStart + ResourceHob->ResourceLength - TestedMemoryBaseAddress);\r
978b9d51 2372 FindLargestFreeRegion (&TestedMemoryBaseAddress, &TestedMemoryLength, (EFI_HOB_MEMORY_ALLOCATION *)GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION));\r
3a05b131
SZ
2373 if (TestedMemoryLength < MinimalMemorySizeNeeded) {\r
2374 continue;\r
2375 }\r
2376\r
2377 //\r
2378 // Save the range described by the Resource Descriptor that is large enough to initilize the DXE Core\r
2379 //\r
2380 BaseAddress = TestedMemoryBaseAddress;\r
2381 Length = TestedMemoryLength;\r
d1102dba 2382 Attributes = ResourceHob->ResourceAttribute;\r
3a05b131 2383 HighAddress = ResourceHob->PhysicalStart;\r
c4c085a2 2384 }\r
c4c085a2 2385 }\r
28a00297 2386\r
3a05b131
SZ
2387 DEBUG ((EFI_D_INFO, "CoreInitializeMemoryServices:\n"));\r
2388 DEBUG ((EFI_D_INFO, " BaseAddress - 0x%lx Length - 0x%lx MinimalMemorySizeNeeded - 0x%lx\n", BaseAddress, Length, MinimalMemorySizeNeeded));\r
28a00297 2389\r
2390 //\r
2391 // If no memory regions are found that are big enough to initialize the DXE core, then ASSERT().\r
2392 //\r
3a05b131 2393 ASSERT (Length >= MinimalMemorySizeNeeded);\r
28a00297 2394\r
2395 //\r
2396 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask\r
2397 //\r
74705ca5
SZ
2398 if ((Attributes & EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE) == EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE) {\r
2399 Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeMoreReliable, Attributes);\r
2400 } else {\r
2401 Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeSystemMemory, Attributes);\r
2402 }\r
28a00297 2403\r
2404 //\r
2405 // Declare the very first memory region, so the EFI Memory Services are available.\r
2406 //\r
2407 CoreAddMemoryDescriptor (\r
2408 EfiConventionalMemory,\r
2409 BaseAddress,\r
2410 RShiftU64 (Length, EFI_PAGE_SHIFT),\r
2411 Capabilities\r
2412 );\r
2413\r
2414 *MemoryBaseAddress = BaseAddress;\r
2415 *MemoryLength = Length;\r
2416\r
2417 return EFI_SUCCESS;\r
2418}\r
2419\r
28a00297 2420\r
162ed594 2421/**\r
2422 External function. Initializes the GCD and memory services based on the memory\r
28a00297 2423 descriptor HOBs. This function is responsible for priming the GCD map and the\r
c18f12d3 2424 memory map, so memory allocations and resource allocations can be made. The\r
2425 HobStart will be relocated to a pool buffer.\r
28a00297 2426\r
022c6d45 2427 @param HobStart The start address of the HOB\r
2428 @param MemoryBaseAddress Start address of memory region found to init DXE\r
2429 core.\r
2430 @param MemoryLength Length of memory region found to init DXE core.\r
28a00297 2431\r
162ed594 2432 @retval EFI_SUCCESS GCD services successfully initialized.\r
28a00297 2433\r
162ed594 2434**/\r
2435EFI_STATUS\r
2436CoreInitializeGcdServices (\r
e94a9ff7 2437 IN OUT VOID **HobStart,\r
162ed594 2438 IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress,\r
2439 IN UINT64 MemoryLength\r
2440 )\r
28a00297 2441{\r
e94a9ff7 2442 EFI_PEI_HOB_POINTERS Hob;\r
28a00297 2443 VOID *NewHobList;\r
e94a9ff7 2444 EFI_HOB_HANDOFF_INFO_TABLE *PhitHob;\r
28a00297 2445 UINT8 SizeOfMemorySpace;\r
2446 UINT8 SizeOfIoSpace;\r
2447 EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;\r
2448 EFI_PHYSICAL_ADDRESS BaseAddress;\r
2449 UINT64 Length;\r
2450 EFI_STATUS Status;\r
2451 EFI_GCD_MAP_ENTRY *Entry;\r
2452 EFI_GCD_MEMORY_TYPE GcdMemoryType;\r
2453 EFI_GCD_IO_TYPE GcdIoType;\r
2454 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;\r
2455 EFI_HOB_MEMORY_ALLOCATION *MemoryHob;\r
2456 EFI_HOB_FIRMWARE_VOLUME *FirmwareVolumeHob;\r
2457 UINTN NumberOfDescriptors;\r
2458 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;\r
2459 UINTN Index;\r
2460 UINT64 Capabilities;\r
2461 EFI_HOB_CPU * CpuHob;\r
a46bbdd3 2462 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMapHobList;\r
e94a9ff7 2463\r
28a00297 2464 //\r
2465 // Cache the PHIT HOB for later use\r
2466 //\r
2467 PhitHob = (EFI_HOB_HANDOFF_INFO_TABLE *)(*HobStart);\r
2468\r
2469 //\r
2470 // Get the number of address lines in the I/O and Memory space for the CPU\r
2471 //\r
2472 CpuHob = GetFirstHob (EFI_HOB_TYPE_CPU);\r
2473 ASSERT (CpuHob != NULL);\r
2474 SizeOfMemorySpace = CpuHob->SizeOfMemorySpace;\r
2475 SizeOfIoSpace = CpuHob->SizeOfIoSpace;\r
022c6d45 2476\r
28a00297 2477 //\r
2478 // Initialize the GCD Memory Space Map\r
2479 //\r
9c4ac31c 2480 Entry = AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY), &mGcdMemorySpaceMapEntryTemplate);\r
28a00297 2481 ASSERT (Entry != NULL);\r
2482\r
2483 Entry->EndAddress = LShiftU64 (1, SizeOfMemorySpace) - 1;\r
2484\r
2485 InsertHeadList (&mGcdMemorySpaceMap, &Entry->Link);\r
2486\r
aa927cae 2487 CoreDumpGcdMemorySpaceMap (TRUE);\r
d1102dba 2488\r
28a00297 2489 //\r
2490 // Initialize the GCD I/O Space Map\r
2491 //\r
9c4ac31c 2492 Entry = AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY), &mGcdIoSpaceMapEntryTemplate);\r
28a00297 2493 ASSERT (Entry != NULL);\r
2494\r
2495 Entry->EndAddress = LShiftU64 (1, SizeOfIoSpace) - 1;\r
2496\r
2497 InsertHeadList (&mGcdIoSpaceMap, &Entry->Link);\r
2498\r
aa927cae 2499 CoreDumpGcdIoSpaceMap (TRUE);\r
d1102dba 2500\r
28a00297 2501 //\r
022c6d45 2502 // Walk the HOB list and add all resource descriptors to the GCD\r
28a00297 2503 //\r
2504 for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {\r
2505\r
2506 GcdMemoryType = EfiGcdMemoryTypeNonExistent;\r
2507 GcdIoType = EfiGcdIoTypeNonExistent;\r
2508\r
2509 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
2510\r
2511 ResourceHob = Hob.ResourceDescriptor;\r
2512\r
2513 switch (ResourceHob->ResourceType) {\r
2514 case EFI_RESOURCE_SYSTEM_MEMORY:\r
2515 if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == TESTED_MEMORY_ATTRIBUTES) {\r
74705ca5
SZ
2516 if ((ResourceHob->ResourceAttribute & EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE) == EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE) {\r
2517 GcdMemoryType = EfiGcdMemoryTypeMoreReliable;\r
2518 } else {\r
2519 GcdMemoryType = EfiGcdMemoryTypeSystemMemory;\r
2520 }\r
28a00297 2521 }\r
2522 if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == INITIALIZED_MEMORY_ATTRIBUTES) {\r
2523 GcdMemoryType = EfiGcdMemoryTypeReserved;\r
2524 }\r
2525 if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == PRESENT_MEMORY_ATTRIBUTES) {\r
2526 GcdMemoryType = EfiGcdMemoryTypeReserved;\r
2527 }\r
a671a012 2528 if ((ResourceHob->ResourceAttribute & EFI_RESOURCE_ATTRIBUTE_PERSISTENT) == EFI_RESOURCE_ATTRIBUTE_PERSISTENT) {\r
35ac962b 2529 GcdMemoryType = EfiGcdMemoryTypePersistent;\r
a671a012 2530 }\r
28a00297 2531 break;\r
2532 case EFI_RESOURCE_MEMORY_MAPPED_IO:\r
2533 case EFI_RESOURCE_FIRMWARE_DEVICE:\r
2534 GcdMemoryType = EfiGcdMemoryTypeMemoryMappedIo;\r
2535 break;\r
2536 case EFI_RESOURCE_MEMORY_MAPPED_IO_PORT:\r
2537 case EFI_RESOURCE_MEMORY_RESERVED:\r
2538 GcdMemoryType = EfiGcdMemoryTypeReserved;\r
2539 break;\r
2540 case EFI_RESOURCE_IO:\r
2541 GcdIoType = EfiGcdIoTypeIo;\r
2542 break;\r
2543 case EFI_RESOURCE_IO_RESERVED:\r
2544 GcdIoType = EfiGcdIoTypeReserved;\r
2545 break;\r
2546 }\r
2547\r
2548 if (GcdMemoryType != EfiGcdMemoryTypeNonExistent) {\r
d12a2ecb 2549 //\r
2550 // Validate the Resource HOB Attributes\r
2551 //\r
2552 CoreValidateResourceDescriptorHobAttributes (ResourceHob->ResourceAttribute);\r
2553\r
28a00297 2554 //\r
2555 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask\r
2556 //\r
2557 Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities (\r
2558 GcdMemoryType,\r
2559 ResourceHob->ResourceAttribute\r
2560 );\r
2561\r
2562 Status = CoreInternalAddMemorySpace (\r
2563 GcdMemoryType,\r
2564 ResourceHob->PhysicalStart,\r
2565 ResourceHob->ResourceLength,\r
2566 Capabilities\r
2567 );\r
2568 }\r
2569\r
2570 if (GcdIoType != EfiGcdIoTypeNonExistent) {\r
2571 Status = CoreAddIoSpace (\r
2572 GcdIoType,\r
2573 ResourceHob->PhysicalStart,\r
2574 ResourceHob->ResourceLength\r
2575 );\r
2576 }\r
2577 }\r
2578 }\r
2579\r
2580 //\r
2581 // Allocate first memory region from the GCD by the DXE core\r
2582 //\r
74705ca5
SZ
2583 Status = CoreGetMemorySpaceDescriptor (MemoryBaseAddress, &Descriptor);\r
2584 if (!EFI_ERROR (Status)) {\r
2585 ASSERT ((Descriptor.GcdMemoryType == EfiGcdMemoryTypeSystemMemory) ||\r
2586 (Descriptor.GcdMemoryType == EfiGcdMemoryTypeMoreReliable));\r
2587 Status = CoreAllocateMemorySpace (\r
2588 EfiGcdAllocateAddress,\r
2589 Descriptor.GcdMemoryType,\r
2590 0,\r
2591 MemoryLength,\r
2592 &MemoryBaseAddress,\r
2593 gDxeCoreImageHandle,\r
2594 NULL\r
2595 );\r
2596 }\r
28a00297 2597\r
2598 //\r
2599 // Walk the HOB list and allocate all memory space that is consumed by memory allocation HOBs,\r
2600 // and Firmware Volume HOBs. Also update the EFI Memory Map with the memory allocation HOBs.\r
2601 //\r
2602 for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {\r
2603 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) {\r
2604 MemoryHob = Hob.MemoryAllocation;\r
2605 BaseAddress = MemoryHob->AllocDescriptor.MemoryBaseAddress;\r
f942f107 2606 Status = CoreGetMemorySpaceDescriptor (BaseAddress, &Descriptor);\r
28a00297 2607 if (!EFI_ERROR (Status)) {\r
f942f107 2608 Status = CoreAllocateMemorySpace (\r
2609 EfiGcdAllocateAddress,\r
022c6d45 2610 Descriptor.GcdMemoryType,\r
f942f107 2611 0,\r
2612 MemoryHob->AllocDescriptor.MemoryLength,\r
2613 &BaseAddress,\r
2614 gDxeCoreImageHandle,\r
2615 NULL\r
2616 );\r
74705ca5
SZ
2617 if (!EFI_ERROR (Status) &&\r
2618 ((Descriptor.GcdMemoryType == EfiGcdMemoryTypeSystemMemory) ||\r
2619 (Descriptor.GcdMemoryType == EfiGcdMemoryTypeMoreReliable))) {\r
28a00297 2620 CoreAddMemoryDescriptor (\r
2621 MemoryHob->AllocDescriptor.MemoryType,\r
2622 MemoryHob->AllocDescriptor.MemoryBaseAddress,\r
2623 RShiftU64 (MemoryHob->AllocDescriptor.MemoryLength, EFI_PAGE_SHIFT),\r
2624 Descriptor.Capabilities & (~EFI_MEMORY_RUNTIME)\r
2625 );\r
2626 }\r
2627 }\r
2628 }\r
2629\r
2630 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV) {\r
2631 FirmwareVolumeHob = Hob.FirmwareVolume;\r
2632 BaseAddress = FirmwareVolumeHob->BaseAddress;\r
2633 Status = CoreAllocateMemorySpace (\r
2634 EfiGcdAllocateAddress,\r
022c6d45 2635 EfiGcdMemoryTypeMemoryMappedIo,\r
28a00297 2636 0,\r
2637 FirmwareVolumeHob->Length,\r
2638 &BaseAddress,\r
2639 gDxeCoreImageHandle,\r
2640 NULL\r
2641 );\r
2642 }\r
2643 }\r
2644\r
28a00297 2645 //\r
2646 // Add and allocate the remaining unallocated system memory to the memory services.\r
2647 //\r
2648 Status = CoreGetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);\r
311a71b2 2649 ASSERT (Status == EFI_SUCCESS);\r
2650\r
a46bbdd3 2651 MemorySpaceMapHobList = NULL;\r
28a00297 2652 for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
74705ca5
SZ
2653 if ((MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeSystemMemory) ||\r
2654 (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeMoreReliable)) {\r
28a00297 2655 if (MemorySpaceMap[Index].ImageHandle == NULL) {\r
2656 BaseAddress = PageAlignAddress (MemorySpaceMap[Index].BaseAddress);\r
2657 Length = PageAlignLength (MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - BaseAddress);\r
383c303c 2658 if (Length == 0 || MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length < BaseAddress) {\r
2659 continue;\r
2660 }\r
a46bbdd3
SZ
2661 if (((UINTN) MemorySpaceMap[Index].BaseAddress <= (UINTN) (*HobStart)) &&\r
2662 ((UINTN) (MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) >= (UINTN) PhitHob->EfiFreeMemoryBottom)) {\r
2663 //\r
2664 // Skip the memory space that covers HOB List, it should be processed\r
2665 // after HOB List relocation to avoid the resources allocated by others\r
2666 // to corrupt HOB List before its relocation.\r
2667 //\r
2668 MemorySpaceMapHobList = &MemorySpaceMap[Index];\r
2669 continue;\r
2670 }\r
28a00297 2671 CoreAddMemoryDescriptor (\r
2672 EfiConventionalMemory,\r
2673 BaseAddress,\r
2674 RShiftU64 (Length, EFI_PAGE_SHIFT),\r
2675 MemorySpaceMap[Index].Capabilities & (~EFI_MEMORY_RUNTIME)\r
2676 );\r
2677 Status = CoreAllocateMemorySpace (\r
2678 EfiGcdAllocateAddress,\r
74705ca5 2679 MemorySpaceMap[Index].GcdMemoryType,\r
28a00297 2680 0,\r
2681 Length,\r
2682 &BaseAddress,\r
2683 gDxeCoreImageHandle,\r
2684 NULL\r
2685 );\r
2686 }\r
2687 }\r
2688 }\r
a46bbdd3
SZ
2689\r
2690 //\r
2691 // Relocate HOB List to an allocated pool buffer.\r
2692 // The relocation should be at after all the tested memory resources added\r
2693 // (except the memory space that covers HOB List) to the memory services,\r
2694 // because the memory resource found in CoreInitializeMemoryServices()\r
2695 // may have not enough remaining resource for HOB List.\r
2696 //\r
2697 NewHobList = AllocateCopyPool (\r
2698 (UINTN) PhitHob->EfiFreeMemoryBottom - (UINTN) (*HobStart),\r
2699 *HobStart\r
2700 );\r
2701 ASSERT (NewHobList != NULL);\r
2702\r
2703 *HobStart = NewHobList;\r
2704 gHobList = NewHobList;\r
2705\r
2706 if (MemorySpaceMapHobList != NULL) {\r
2707 //\r
2708 // Add and allocate the memory space that covers HOB List to the memory services\r
2709 // after HOB List relocation.\r
2710 //\r
2711 BaseAddress = PageAlignAddress (MemorySpaceMapHobList->BaseAddress);\r
2712 Length = PageAlignLength (MemorySpaceMapHobList->BaseAddress + MemorySpaceMapHobList->Length - BaseAddress);\r
2713 CoreAddMemoryDescriptor (\r
2714 EfiConventionalMemory,\r
2715 BaseAddress,\r
2716 RShiftU64 (Length, EFI_PAGE_SHIFT),\r
2717 MemorySpaceMapHobList->Capabilities & (~EFI_MEMORY_RUNTIME)\r
2718 );\r
2719 Status = CoreAllocateMemorySpace (\r
2720 EfiGcdAllocateAddress,\r
2721 MemorySpaceMapHobList->GcdMemoryType,\r
2722 0,\r
2723 Length,\r
2724 &BaseAddress,\r
2725 gDxeCoreImageHandle,\r
2726 NULL\r
2727 );\r
2728 }\r
2729\r
28a00297 2730 CoreFreePool (MemorySpaceMap);\r
2731\r
2732 return EFI_SUCCESS;\r
2733}\r