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