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