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