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