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