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