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