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