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