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