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