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