Update gHobList in DXE core when GCD relocates hob list.
[people/mcb30/edk2.git] / edk2 / EdkModulePkg / Core / Dxe / Gcd / gcd.c
1 /*++\r
2 \r
3 Copyright (c) 2006, Intel Corporation                                                         \r
4 All rights reserved. This program and the accompanying materials                          \r
5 are licensed and made available under the terms and conditions of the BSD License         \r
6 which accompanies this distribution.  The full text of the license may be found at        \r
7 http://opensource.org/licenses/bsd-license.php                                            \r
8                                                                                           \r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
11 \r
12 Module Name:\r
13 \r
14     gcd.c\r
15 \r
16 Abstract:\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
51 EFI_LOCK           mGcdMemorySpaceLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);\r
52 EFI_LOCK           mGcdIoSpaceLock     = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);\r
53 LIST_ENTRY         mGcdMemorySpaceMap  = INITIALIZE_LIST_HEAD_VARIABLE (mGcdMemorySpaceMap);\r
54 LIST_ENTRY         mGcdIoSpaceMap      = INITIALIZE_LIST_HEAD_VARIABLE (mGcdIoSpaceMap);\r
55 \r
56 EFI_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
64   (EFI_GCD_IO_TYPE) 0,\r
65   NULL,\r
66   NULL\r
67 };\r
68 \r
69 EFI_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
76   (EFI_GCD_MEMORY_TYPE) 0,\r
77   EfiGcdIoTypeNonExistent,\r
78   NULL,\r
79   NULL\r
80 };\r
81 \r
82 GCD_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
97 VOID\r
98 CoreAcquireGcdMemoryLock (\r
99   VOID\r
100   )\r
101 /*++\r
102 \r
103 Routine Description:\r
104     Acquire memory lock on mGcdMemorySpaceLock\r
105 \r
106 Arguments:\r
107     None\r
108 \r
109 Returns:\r
110     None\r
111 \r
112 --*/\r
113 {\r
114   CoreAcquireLock (&mGcdMemorySpaceLock);\r
115 }\r
116 \r
117 \r
118 VOID\r
119 CoreReleaseGcdMemoryLock (\r
120   VOID\r
121   )\r
122 /*++\r
123 \r
124 Routine Description:\r
125     Release memory lock on mGcdMemorySpaceLock\r
126 \r
127 Arguments:\r
128     None\r
129 \r
130 Returns:\r
131     None\r
132 \r
133 --*/\r
134 {\r
135   CoreReleaseLock (&mGcdMemorySpaceLock);\r
136 }\r
137 \r
138 \r
139 STATIC\r
140 VOID\r
141 CoreAcquireGcdIoLock (\r
142   VOID\r
143   )\r
144 /*++\r
145 \r
146 Routine Description:\r
147     Acquire memory lock on mGcdIoSpaceLock\r
148 \r
149 Arguments:\r
150     None\r
151 \r
152 Returns:\r
153     None\r
154 \r
155 --*/\r
156 {\r
157   CoreAcquireLock (&mGcdIoSpaceLock);\r
158 }\r
159 \r
160 STATIC\r
161 VOID\r
162 CoreReleaseGcdIoLock (\r
163   VOID\r
164   )\r
165 /*++\r
166 \r
167 Routine Description:\r
168     Release memory lock on mGcdIoSpaceLock\r
169 \r
170 Arguments:\r
171     None\r
172 \r
173 Returns:\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
186 STATIC\r
187 UINT64\r
188 AlignValue (\r
189   IN UINT64   Value,\r
190   IN UINTN    Alignment,\r
191   IN BOOLEAN  RoundUp\r
192   )\r
193 /*++\r
194 \r
195 Routine Description:\r
196 \r
197   Aligns a value to the specified boundary.\r
198 \r
199 Arguments:\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
206 Returns:\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
221 STATIC\r
222 UINT64\r
223 PageAlignAddress (\r
224   IN UINT64 Value\r
225   )\r
226 /*++\r
227 \r
228 Routine Description:\r
229 \r
230   Aligns address to the page boundary.\r
231 \r
232 Arguments:\r
233 \r
234   Value     - 64 bit address to align\r
235 \r
236 Returns:\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
245 STATIC\r
246 UINT64\r
247 PageAlignLength (\r
248   IN UINT64 Value\r
249   )\r
250 /*++\r
251 \r
252 Routine Description:\r
253 \r
254   Aligns length to the page boundary.\r
255 \r
256 Arguments:\r
257 \r
258   Value     - 64 bit length to align\r
259 \r
260 Returns:\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
272 STATIC\r
273 EFI_STATUS\r
274 CoreAllocateGcdMapEntry (\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
280 Routine Description:\r
281 \r
282   Allocate pool for two entries.\r
283 \r
284 Arguments:\r
285 \r
286   TopEntry      - An entry of GCD map\r
287   BottomEntry   - An entry of GCD map\r
288 \r
289 Returns:\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
310 STATIC\r
311 EFI_STATUS\r
312 CoreInsertGcdMapEntry (\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
322 Routine Description:\r
323 \r
324   Internal function.  Inserts a new descriptor into a sorted list\r
325 \r
326 Arguments:\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
340 Returns:\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
367 STATIC\r
368 EFI_STATUS\r
369 CoreMergeGcdMapEntry (\r
370   IN LIST_ENTRY      *Link,\r
371   IN BOOLEAN         Forward,\r
372   IN LIST_ENTRY      *Map\r
373   )\r
374 /*++\r
375 \r
376 Routine Description:\r
377 \r
378   Merge the Gcd region specified by Link and its adjacent entry\r
379 \r
380 Arguments:\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
388 Returns:\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
449 STATIC\r
450 EFI_STATUS\r
451 CoreCleanupGcdMapEntry (\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
460 Routine Description:\r
461 \r
462   Merge adjacent entries on total chain.\r
463 \r
464 Arguments:\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
476 Returns:\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
501 STATIC\r
502 EFI_STATUS\r
503 CoreSearchGcdMapEntry (\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
512 Routine 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
516 Arguments:\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
528 Returns:\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
562 STATIC\r
563 UINTN\r
564 CoreCountGcdMapEntry (\r
565   IN LIST_ENTRY  *Map\r
566   )\r
567 /*++\r
568 \r
569 Routine Description:\r
570 \r
571   Count the amount of GCD map entries.\r
572 \r
573 Arguments:\r
574 \r
575   Map       - Points to the start entry to do the count loop.\r
576 \r
577 Returns:\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
596 STATIC\r
597 UINT64\r
598 ConverToCpuArchAttributes (\r
599   UINT64 Attributes\r
600   ) \r
601 /*++\r
602 \r
603 Routine Description:\r
604 \r
605   Return the memory attribute specified by Attributes\r
606 \r
607 Arguments:\r
608 \r
609   Attributes        - A num with some attribute bits on.\r
610 \r
611 Returns:\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
641 STATIC\r
642 EFI_STATUS\r
643 CoreConvertSpace (\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
654 Routine Description:\r
655 \r
656   Do operation on a segment of memory space specified (add, free, remove, change attribute ...).\r
657 \r
658 Arguments:\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
674 Returns:\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
689 Returns:\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
898 Done:\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
909 STATIC\r
910 EFI_STATUS\r
911 CoreAllocateSpaceCheckEntry (\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
919 Routine Description:\r
920 \r
921   Check whether an entry could be used to allocate space.\r
922 \r
923 Arguments:\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
933 Returns:\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
963 STATIC\r
964 EFI_STATUS\r
965 CoreAllocateSpace (\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
978 Routine Description:\r
979 \r
980   Allocate space on specified address and length.\r
981 \r
982 Arguments:\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
1002 Returns:\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
1108       MaxAddress = *BaseAddress;\r
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
1117         GcdAllocateType == EfiGcdAllocateAnySearchTopDown ) {\r
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
1221 Done:\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
1232 STATIC\r
1233 EFI_STATUS\r
1234 CoreInternalAddMemorySpace (\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
1242 Routine Description:\r
1243 \r
1244   Add a segment of memory to GCD map.\r
1245 \r
1246 Arguments:\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
1256 Returns:\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
1271   return CoreConvertSpace (GCD_ADD_MEMORY_OPERATION, GcdMemoryType, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, Capabilities, 0);\r
1272 }\r
1273 \r
1274 //\r
1275 // GCD Core Services\r
1276 //\r
1277 EFI_STATUS\r
1278 CoreAllocateMemorySpace (\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
1289 Routine Description:\r
1290 \r
1291   Allocates nonexistent memory, reserved memory, system memory, or memorymapped\r
1292 I/O resources from the global coherency domain of the processor.\r
1293 \r
1294 Arguments:\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
1310 Returns:\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
1324            (EFI_GCD_IO_TYPE) 0, \r
1325            Alignment, \r
1326            Length, \r
1327            BaseAddress, \r
1328            ImageHandle, \r
1329            DeviceHandle\r
1330            );\r
1331 }\r
1332 \r
1333 EFI_STATUS\r
1334 CoreAddMemorySpace (\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
1342 Routine Description:\r
1343 \r
1344   Adds reserved memory, system memory, or memory-mapped I/O resources to the\r
1345 global coherency domain of the processor.\r
1346 \r
1347 Arguments:\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
1357 Returns:\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
1417 EFI_STATUS\r
1418 CoreFreeMemorySpace (\r
1419   IN EFI_PHYSICAL_ADDRESS  BaseAddress,\r
1420   IN UINT64                Length\r
1421   )\r
1422 /*++\r
1423 \r
1424 Routine Description:\r
1425 \r
1426   Frees nonexistent memory, reserved memory, system memory, or memory-mapped\r
1427 I/O resources from the global coherency domain of the processor.\r
1428 \r
1429 Arguments:\r
1430 \r
1431   BaseAddress       - Base address of the memory space.\r
1432   \r
1433   Length            - Length of the memory space.\r
1434   \r
1435 Returns:\r
1436 \r
1437   EFI_SUCCESS       - Space successfully freed.\r
1438 \r
1439 --*/\r
1440 {\r
1441   return CoreConvertSpace (GCD_FREE_MEMORY_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, 0);\r
1442 }\r
1443 \r
1444 EFI_STATUS\r
1445 CoreRemoveMemorySpace (\r
1446   IN EFI_PHYSICAL_ADDRESS  BaseAddress,\r
1447   IN UINT64                Length\r
1448   )\r
1449 /*++\r
1450 \r
1451 Routine Description:\r
1452 \r
1453   Removes reserved memory, system memory, or memory-mapped I/O resources from\r
1454 the global coherency domain of the processor.\r
1455 \r
1456 Arguments:\r
1457 \r
1458   BaseAddress       - Base address of the memory space.\r
1459   \r
1460   Length            - Length of the memory space.\r
1461   \r
1462 Returns:\r
1463 \r
1464   EFI_SUCCESS       - Successfully remove a segment of memory space.\r
1465 \r
1466 --*/\r
1467 {\r
1468   return CoreConvertSpace (GCD_REMOVE_MEMORY_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, 0);\r
1469 }\r
1470 \r
1471 STATIC\r
1472 VOID\r
1473 BuildMemoryDescriptor (\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
1479 Routine Description:\r
1480 \r
1481   Build a memory descriptor according to an entry.\r
1482 \r
1483 Arguments:\r
1484 \r
1485   Descriptor          - The descriptor to be built\r
1486   \r
1487   Entry               - According to this entry\r
1488 \r
1489 Returns:\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
1504 EFI_STATUS\r
1505 CoreGetMemorySpaceDescriptor (\r
1506   IN  EFI_PHYSICAL_ADDRESS             BaseAddress,\r
1507   OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR  *Descriptor\r
1508   )\r
1509 /*++\r
1510 \r
1511 Routine Description:\r
1512 \r
1513   Retrieves the descriptor for a memory region containing a specified address.\r
1514 \r
1515 Arguments:\r
1516 \r
1517   BaseAddress       - Specified start address\r
1518   \r
1519   Descriptor        - Specified length\r
1520 \r
1521 Returns:\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
1562 EFI_STATUS\r
1563 CoreSetMemorySpaceAttributes (\r
1564   IN EFI_PHYSICAL_ADDRESS  BaseAddress,\r
1565   IN UINT64                Length,\r
1566   IN UINT64                Attributes\r
1567   )\r
1568 /*++\r
1569 \r
1570 Routine Description:\r
1571 \r
1572   Modifies the attributes for a memory region in the global coherency domain of the\r
1573 processor.\r
1574 \r
1575 Arguments:\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
1583 Returns:\r
1584 \r
1585   EFI_SUCCESS       - Successfully set attribute of a segment of memory space.\r
1586 \r
1587 --*/\r
1588 {\r
1589   return CoreConvertSpace (GCD_SET_ATTRIBUTES_MEMORY_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, Attributes);\r
1590 }\r
1591 \r
1592 EFI_STATUS\r
1593 CoreGetMemorySpaceMap (\r
1594   OUT UINTN                            *NumberOfDescriptors,\r
1595   OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR  **MemorySpaceMap\r
1596   )\r
1597 /*++\r
1598 \r
1599 Routine Description:\r
1600 \r
1601   Returns a map of the memory resources in the global coherency domain of the\r
1602 processor.\r
1603 \r
1604 Arguments:\r
1605 \r
1606   NumberOfDescriptors       - Number of descriptors.\r
1607   \r
1608   MemorySpaceMap            - Descriptor array\r
1609 \r
1610 Returns:\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
1664 Done:\r
1665   CoreReleaseGcdMemoryLock ();\r
1666   return Status;\r
1667 }\r
1668 \r
1669 EFI_STATUS\r
1670 CoreAddIoSpace (\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
1677 Routine Description:\r
1678 \r
1679   Adds reserved I/O or I/O resources to the global coherency domain of the processor.\r
1680 \r
1681 Arguments:\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
1689 Returns:\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
1702   return CoreConvertSpace (GCD_ADD_IO_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, GcdIoType, BaseAddress, Length, 0, 0);\r
1703 }\r
1704 \r
1705 EFI_STATUS\r
1706 CoreAllocateIoSpace (\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
1717 Routine Description:\r
1718 \r
1719   Allocates nonexistent I/O, reserved I/O, or I/O resources from the global coherency\r
1720 domain of the processor.\r
1721 \r
1722 Arguments:\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
1738 Returns:\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
1751            (EFI_GCD_MEMORY_TYPE) 0, \r
1752            GcdIoType, \r
1753            Alignment, \r
1754            Length, \r
1755            BaseAddress, \r
1756            ImageHandle, \r
1757            DeviceHandle\r
1758            );\r
1759 }\r
1760 \r
1761 EFI_STATUS\r
1762 CoreFreeIoSpace (\r
1763   IN EFI_PHYSICAL_ADDRESS  BaseAddress,\r
1764   IN UINT64                Length\r
1765   )\r
1766 /*++\r
1767 \r
1768 Routine Description:\r
1769 \r
1770   Frees nonexistent I/O, reserved I/O, or I/O resources from the global coherency\r
1771 domain of the processor.\r
1772 \r
1773 Arguments:\r
1774 \r
1775   BaseAddress       - Base address of the segment.\r
1776   \r
1777   Length            - Length of the segment.\r
1778   \r
1779 Returns:\r
1780 \r
1781   EFI_SUCCESS       - Space successfully freed.\r
1782 \r
1783 --*/\r
1784 {\r
1785   return CoreConvertSpace (GCD_FREE_IO_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, 0);\r
1786 }\r
1787 \r
1788 EFI_STATUS\r
1789 CoreRemoveIoSpace (\r
1790   IN EFI_PHYSICAL_ADDRESS  BaseAddress,\r
1791   IN UINT64                Length\r
1792   )\r
1793 /*++\r
1794 \r
1795 Routine Description:\r
1796 \r
1797   Removes reserved I/O or I/O resources from the global coherency domain of the\r
1798 processor.\r
1799 \r
1800 Arguments:\r
1801 \r
1802   BaseAddress       - Base address of the segment.\r
1803   \r
1804   Length            - Length of the segment.\r
1805   \r
1806 Returns:\r
1807 \r
1808   EFI_SUCCESS       - Successfully removed a segment of IO space.\r
1809 \r
1810 --*/\r
1811 {\r
1812   return CoreConvertSpace (GCD_REMOVE_IO_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, 0);\r
1813 }\r
1814 \r
1815 STATIC\r
1816 VOID\r
1817 BuildIoDescriptor (\r
1818   IN EFI_GCD_IO_SPACE_DESCRIPTOR  *Descriptor,\r
1819   IN EFI_GCD_MAP_ENTRY            *Entry\r
1820   )\r
1821 /*++\r
1822 \r
1823 Routine Description:\r
1824 \r
1825   Build a IO descriptor according to an entry.\r
1826 \r
1827 Arguments:\r
1828 \r
1829   Descriptor          - The descriptor to be built\r
1830   \r
1831   Entry               - According to this entry\r
1832 \r
1833 Returns:\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
1846 EFI_STATUS\r
1847 CoreGetIoSpaceDescriptor (\r
1848   IN  EFI_PHYSICAL_ADDRESS         BaseAddress,\r
1849   OUT EFI_GCD_IO_SPACE_DESCRIPTOR  *Descriptor\r
1850   )\r
1851 /*++\r
1852 \r
1853 Routine Description:\r
1854 \r
1855   Retrieves the descriptor for an I/O region containing a specified address.\r
1856 \r
1857 Arguments:\r
1858 \r
1859   BaseAddress       - Specified start address\r
1860   \r
1861   Descriptor        - Specified length\r
1862 \r
1863 Returns:\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
1904 EFI_STATUS\r
1905 CoreGetIoSpaceMap (\r
1906   OUT UINTN                        *NumberOfDescriptors,\r
1907   OUT EFI_GCD_IO_SPACE_DESCRIPTOR  **IoSpaceMap\r
1908   )\r
1909 /*++\r
1910 \r
1911 Routine Description:\r
1912 \r
1913   Returns a map of the I/O resources in the global coherency domain of the processor.\r
1914 \r
1915 Arguments:\r
1916 \r
1917   NumberOfDescriptors       - Number of descriptors.\r
1918   \r
1919   IoSpaceMap                - Descriptor array\r
1920 \r
1921 Returns:\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
1975 Done:\r
1976   CoreReleaseGcdIoLock ();\r
1977   return Status;\r
1978 }  \r
1979 \r
1980 STATIC\r
1981 UINT64\r
1982 CoreConvertResourceDescriptorHobAttributesToCapabilities (\r
1983   EFI_GCD_MEMORY_TYPE  GcdMemoryType,\r
1984   UINT64               Attributes\r
1985   )\r
1986 /*++\r
1987 \r
1988 Routine Description:\r
1989 \r
1990   Converts a Resource Descriptor HOB attributes mask to an EFI Memory Descriptor \r
1991   capabilities mask\r
1992 \r
1993 Arguments:\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
1998 Returns:\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
2021 EFI_STATUS\r
2022 CoreInitializeMemoryServices (\r
2023   IN  VOID                  **HobStart,\r
2024   OUT EFI_PHYSICAL_ADDRESS  *MemoryBaseAddress,\r
2025   OUT UINT64                *MemoryLength\r
2026   )\r
2027 /*++\r
2028 \r
2029 Routine 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
2038 Arguments:\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
2044 Returns:\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
2106     if (EfiMemoryTypeInformation != NULL && DataSize > 0 && DataSize <= (EfiMaxMemoryType + 1) * sizeof (EFI_MEMORY_TYPE_INFORMATION)) {\r
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
2243 EFI_STATUS\r
2244 CoreInitializeGcdServices (\r
2245   IN VOID                  **HobStart,\r
2246   IN EFI_PHYSICAL_ADDRESS  MemoryBaseAddress,\r
2247   IN UINT64                MemoryLength\r
2248   )\r
2249 /*++\r
2250 \r
2251 Routine 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
2260 Arguments:\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
2269 Returns:\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   gHobList  = NewHobList;\r
2465 \r
2466   //\r
2467   // Add and allocate the remaining unallocated system memory to the memory services.\r
2468   //\r
2469   Status = CoreGetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);\r
2470   for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
2471     if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeSystemMemory) {\r
2472       if (MemorySpaceMap[Index].ImageHandle == NULL) {\r
2473         BaseAddress  = PageAlignAddress (MemorySpaceMap[Index].BaseAddress);\r
2474         Length       = PageAlignLength  (MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - BaseAddress);\r
2475         CoreAddMemoryDescriptor (\r
2476           EfiConventionalMemory,\r
2477           BaseAddress,\r
2478           RShiftU64 (Length, EFI_PAGE_SHIFT),\r
2479           MemorySpaceMap[Index].Capabilities & (~EFI_MEMORY_RUNTIME)\r
2480           );\r
2481         Status = CoreAllocateMemorySpace (\r
2482                    EfiGcdAllocateAddress,\r
2483                    EfiGcdMemoryTypeSystemMemory,\r
2484                    0,\r
2485                    Length,\r
2486                    &BaseAddress,\r
2487                    gDxeCoreImageHandle,\r
2488                    NULL\r
2489                    );\r
2490       }\r
2491     }\r
2492   }\r
2493   CoreFreePool (MemorySpaceMap);\r
2494 \r
2495   return EFI_SUCCESS;\r
2496 }\r