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