]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Gcd/Gcd.c
Remove notice for PXE_OPFLAGS_GET_MEDIA_STATUS and PXE_STATFLAGS_GET_STATUS_NO_MEDIA_...
[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
23c98c94 6Copyright (c) 2006 - 2008, Intel Corporation. <BR>\r
7All rights reserved. This program and the accompanying materials\r
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
602\r
603 //\r
604 // Verify that the list of descriptors are unallocated non-existent memory.\r
605 //\r
606 Link = StartLink;\r
607 while (Link != EndLink->ForwardLink) {\r
608 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
609 switch (Operation) {\r
610 //\r
611 // Add operations\r
612 //\r
613 case GCD_ADD_MEMORY_OPERATION:\r
614 if (Entry->GcdMemoryType != EfiGcdMemoryTypeNonExistent ||\r
615 Entry->ImageHandle != NULL ) {\r
616 Status = EFI_ACCESS_DENIED;\r
617 goto Done;\r
618 }\r
619 break;\r
620 case GCD_ADD_IO_OPERATION:\r
621 if (Entry->GcdIoType != EfiGcdIoTypeNonExistent ||\r
622 Entry->ImageHandle != NULL ) {\r
623 Status = EFI_ACCESS_DENIED;\r
624 goto Done;\r
625 }\r
626 break;\r
627 //\r
628 // Free operations\r
629 //\r
630 case GCD_FREE_MEMORY_OPERATION:\r
631 case GCD_FREE_IO_OPERATION:\r
632 if (Entry->ImageHandle == NULL) {\r
633 Status = EFI_NOT_FOUND;\r
634 goto Done;\r
635 }\r
636 break;\r
637 //\r
638 // Remove operations\r
639 //\r
640 case GCD_REMOVE_MEMORY_OPERATION:\r
641 if (Entry->GcdMemoryType == EfiGcdMemoryTypeNonExistent) {\r
642 Status = EFI_NOT_FOUND;\r
643 goto Done;\r
644 }\r
645 if (Entry->ImageHandle != NULL) {\r
646 Status = EFI_ACCESS_DENIED;\r
647 goto Done;\r
648 }\r
649 break;\r
650 case GCD_REMOVE_IO_OPERATION:\r
651 if (Entry->GcdIoType == EfiGcdIoTypeNonExistent) {\r
652 Status = EFI_NOT_FOUND;\r
653 goto Done;\r
654 }\r
655 if (Entry->ImageHandle != NULL) {\r
656 Status = EFI_ACCESS_DENIED;\r
657 goto Done;\r
658 }\r
659 break;\r
660 //\r
661 // Set attribute operations\r
662 //\r
663 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION:\r
71f68914 664 if ((Attributes & EFI_MEMORY_RUNTIME) != 0) {\r
28a00297 665 if ((BaseAddress & EFI_PAGE_MASK) != 0 || (Length & EFI_PAGE_MASK) != 0) {\r
666 Status = EFI_INVALID_PARAMETER;\r
28a00297 667 goto Done;\r
668 }\r
669 }\r
670 if ((Entry->Capabilities & Attributes) != Attributes) {\r
671 Status = EFI_UNSUPPORTED;\r
672 goto Done;\r
673 }\r
674 break;\r
675 }\r
676 Link = Link->ForwardLink;\r
677 }\r
678\r
679 //\r
680 // Allocate work space to perform this operation\r
681 //\r
682 Status = CoreAllocateGcdMapEntry (&TopEntry, &BottomEntry);\r
683 if (EFI_ERROR (Status)) {\r
684 Status = EFI_OUT_OF_RESOURCES;\r
685 goto Done;\r
686 }\r
687\r
28a00297 688 if (Operation == GCD_SET_ATTRIBUTES_MEMORY_OPERATION) {\r
689 //\r
690 // Call CPU Arch Protocol to attempt to set attributes on the range\r
691 //\r
692 CpuArchAttributes = ConverToCpuArchAttributes (Attributes);\r
693 if ( CpuArchAttributes != INVALID_CPU_ARCH_ATTRIBUTES ) {\r
694 Status = CoreLocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&CpuArch);\r
695 if (EFI_ERROR (Status)) {\r
696 Status = EFI_ACCESS_DENIED;\r
697 goto Done;\r
698 }\r
699\r
700 Status = CpuArch->SetMemoryAttributes (\r
701 CpuArch,\r
702 BaseAddress,\r
703 Length,\r
704 CpuArchAttributes\r
705 );\r
706 if (EFI_ERROR (Status)) {\r
707 goto Done;\r
708 }\r
709 }\r
710\r
711 }\r
712\r
713 //\r
714 // Convert/Insert the list of descriptors from StartLink to EndLink\r
715 //\r
716 Link = StartLink;\r
717 while (Link != EndLink->ForwardLink) {\r
718 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
719 CoreInsertGcdMapEntry (Link, Entry, BaseAddress, Length, TopEntry, BottomEntry);\r
720 switch (Operation) {\r
721 //\r
722 // Add operations\r
723 //\r
724 case GCD_ADD_MEMORY_OPERATION:\r
725 Entry->GcdMemoryType = GcdMemoryType;\r
726 if (GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) {\r
727 Entry->Capabilities = Capabilities | EFI_MEMORY_RUNTIME | EFI_MEMORY_PORT_IO;\r
728 } else {\r
729 Entry->Capabilities = Capabilities | EFI_MEMORY_RUNTIME;\r
730 }\r
731 break;\r
732 case GCD_ADD_IO_OPERATION:\r
733 Entry->GcdIoType = GcdIoType;\r
734 break;\r
735 //\r
736 // Free operations\r
737 //\r
738 case GCD_FREE_MEMORY_OPERATION:\r
739 case GCD_FREE_IO_OPERATION:\r
740 Entry->ImageHandle = NULL;\r
741 Entry->DeviceHandle = NULL;\r
742 break;\r
743 //\r
744 // Remove operations\r
745 //\r
746 case GCD_REMOVE_MEMORY_OPERATION:\r
747 Entry->GcdMemoryType = EfiGcdMemoryTypeNonExistent;\r
748 Entry->Capabilities = 0;\r
749 break;\r
750 case GCD_REMOVE_IO_OPERATION:\r
751 Entry->GcdIoType = EfiGcdIoTypeNonExistent;\r
752 break;\r
753 //\r
754 // Set attribute operations\r
755 //\r
756 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION:\r
757 Entry->Attributes = Attributes;\r
758 break;\r
759 }\r
760 Link = Link->ForwardLink;\r
761 }\r
762\r
763 //\r
764 // Cleanup\r
765 //\r
766 Status = CoreCleanupGcdMapEntry (TopEntry, BottomEntry, StartLink, EndLink, Map);\r
767\r
768Done:\r
71f68914 769 if ((Operation & GCD_MEMORY_SPACE_OPERATION) != 0) {\r
28a00297 770 CoreReleaseGcdMemoryLock ();\r
771 }\r
71f68914 772 if ((Operation & GCD_IO_SPACE_OPERATION) != 0) {\r
28a00297 773 CoreReleaseGcdIoLock ();\r
774 }\r
775\r
776 return Status;\r
777}\r
778\r
162ed594 779\r
780/**\r
781 Check whether an entry could be used to allocate space.\r
782\r
022c6d45 783 @param Operation Allocate memory or IO\r
784 @param Entry The entry to be tested\r
785 @param GcdMemoryType The desired memory type\r
786 @param GcdIoType The desired IO type\r
162ed594 787\r
022c6d45 788 @retval EFI_NOT_FOUND The memory type does not match or there's an\r
789 image handle on the entry.\r
790 @retval EFI_UNSUPPORTED The operation unsupported.\r
791 @retval EFI_SUCCESS It's ok for this entry to be used to allocate\r
162ed594 792 space.\r
793\r
794**/\r
28a00297 795EFI_STATUS\r
796CoreAllocateSpaceCheckEntry (\r
797 IN UINTN Operation,\r
798 IN EFI_GCD_MAP_ENTRY *Entry,\r
799 IN EFI_GCD_MEMORY_TYPE GcdMemoryType,\r
800 IN EFI_GCD_IO_TYPE GcdIoType\r
801 )\r
28a00297 802{\r
803 if (Entry->ImageHandle != NULL) {\r
804 return EFI_NOT_FOUND;\r
805 }\r
806 switch (Operation) {\r
807 case GCD_ALLOCATE_MEMORY_OPERATION:\r
808 if (Entry->GcdMemoryType != GcdMemoryType) {\r
809 return EFI_NOT_FOUND;\r
810 }\r
811 break;\r
812 case GCD_ALLOCATE_IO_OPERATION:\r
813 if (Entry->GcdIoType != GcdIoType) {\r
814 return EFI_NOT_FOUND;\r
815 }\r
816 break;\r
817 default:\r
818 return EFI_UNSUPPORTED;\r
819 }\r
820 return EFI_SUCCESS;\r
821}\r
822\r
162ed594 823\r
824/**\r
825 Allocate space on specified address and length.\r
826\r
022c6d45 827 @param Operation The type of operation (memory or IO)\r
828 @param GcdAllocateType The type of allocate operation\r
829 @param GcdMemoryType The desired memory type\r
830 @param GcdIoType The desired IO type\r
831 @param Alignment Align with 2^Alignment\r
832 @param Length Length to allocate\r
833 @param BaseAddress Base address to allocate\r
834 @param ImageHandle The image handle consume the allocated space.\r
835 @param DeviceHandle The device handle consume the allocated space.\r
836\r
837 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
838 @retval EFI_NOT_FOUND No descriptor for the desired space exists.\r
162ed594 839 @retval EFI_SUCCESS Space successfully allocated.\r
840\r
841**/\r
28a00297 842EFI_STATUS\r
843CoreAllocateSpace (\r
844 IN UINTN Operation,\r
845 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType,\r
846 IN EFI_GCD_MEMORY_TYPE GcdMemoryType,\r
847 IN EFI_GCD_IO_TYPE GcdIoType,\r
848 IN UINTN Alignment,\r
849 IN UINT64 Length,\r
850 IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,\r
851 IN EFI_HANDLE ImageHandle,\r
852 IN EFI_HANDLE DeviceHandle OPTIONAL\r
853 )\r
28a00297 854{\r
855 EFI_STATUS Status;\r
856 EFI_PHYSICAL_ADDRESS AlignmentMask;\r
857 EFI_PHYSICAL_ADDRESS MaxAddress;\r
858 LIST_ENTRY *Map;\r
859 LIST_ENTRY *Link;\r
860 LIST_ENTRY *SubLink;\r
861 EFI_GCD_MAP_ENTRY *Entry;\r
862 EFI_GCD_MAP_ENTRY *TopEntry;\r
863 EFI_GCD_MAP_ENTRY *BottomEntry;\r
864 LIST_ENTRY *StartLink;\r
865 LIST_ENTRY *EndLink;\r
866 BOOLEAN Found;\r
867\r
868 //\r
869 // Make sure parameters are valid\r
870 //\r
871 if (GcdAllocateType < 0 || GcdAllocateType >= EfiGcdMaxAllocateType) {\r
872 return EFI_INVALID_PARAMETER;\r
873 }\r
874 if (GcdMemoryType < 0 || GcdMemoryType >= EfiGcdMemoryTypeMaximum) {\r
875 return EFI_INVALID_PARAMETER;\r
876 }\r
877 if (GcdIoType < 0 || GcdIoType >= EfiGcdIoTypeMaximum) {\r
878 return EFI_INVALID_PARAMETER;\r
879 }\r
880 if (BaseAddress == NULL) {\r
881 return EFI_INVALID_PARAMETER;\r
882 }\r
883 if (ImageHandle == NULL) {\r
884 return EFI_INVALID_PARAMETER;\r
885 }\r
886 if (Alignment >= 64) {\r
887 return EFI_NOT_FOUND;\r
888 }\r
889 if (Length == 0) {\r
890 return EFI_INVALID_PARAMETER;\r
891 }\r
892\r
893 Map = NULL;\r
71f68914 894 if ((Operation & GCD_MEMORY_SPACE_OPERATION) != 0) {\r
28a00297 895 CoreAcquireGcdMemoryLock ();\r
896 Map = &mGcdMemorySpaceMap;\r
fbbb4211 897 } else if ((Operation & GCD_IO_SPACE_OPERATION) != 0) {\r
28a00297 898 CoreAcquireGcdIoLock ();\r
899 Map = &mGcdIoSpaceMap;\r
fbbb4211 900 } else {\r
901 ASSERT (FALSE);\r
28a00297 902 }\r
903\r
904 Found = FALSE;\r
905 StartLink = NULL;\r
906 EndLink = NULL;\r
907 //\r
908 // Compute alignment bit mask\r
909 //\r
910 AlignmentMask = LShiftU64 (1, Alignment) - 1;\r
911\r
912 if (GcdAllocateType == EfiGcdAllocateAddress) {\r
913 //\r
914 // Verify that the BaseAddress passed in is aligned correctly\r
915 //\r
916 if ((*BaseAddress & AlignmentMask) != 0) {\r
917 Status = EFI_NOT_FOUND;\r
918 goto Done;\r
919 }\r
920\r
921 //\r
922 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length\r
923 //\r
924 Status = CoreSearchGcdMapEntry (*BaseAddress, Length, &StartLink, &EndLink, Map);\r
925 if (EFI_ERROR (Status)) {\r
926 Status = EFI_NOT_FOUND;\r
927 goto Done;\r
928 }\r
929\r
930 //\r
931 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.\r
932 //\r
933 Link = StartLink;\r
934 while (Link != EndLink->ForwardLink) {\r
935 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
936 Link = Link->ForwardLink;\r
937 Status = CoreAllocateSpaceCheckEntry (Operation, Entry, GcdMemoryType, GcdIoType);\r
938 if (EFI_ERROR (Status)) {\r
939 goto Done;\r
940 }\r
941 }\r
942 Found = TRUE;\r
943 } else {\r
944\r
945 Entry = CR (Map->BackLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
946\r
947 //\r
948 // Compute the maximum address to use in the search algorithm\r
949 //\r
950 if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchBottomUp ||\r
951 GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown ) {\r
952 MaxAddress = *BaseAddress;\r
953 } else {\r
954 MaxAddress = Entry->EndAddress;\r
955 }\r
956\r
957 //\r
958 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.\r
959 //\r
960 if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown ||\r
961 GcdAllocateType == EfiGcdAllocateAnySearchTopDown ) {\r
962 Link = Map->BackLink;\r
963 } else {\r
964 Link = Map->ForwardLink;\r
965 }\r
966 while (Link != Map) {\r
967 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
968\r
969 if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown ||\r
970 GcdAllocateType == EfiGcdAllocateAnySearchTopDown ) {\r
971 Link = Link->BackLink;\r
972 } else {\r
973 Link = Link->ForwardLink;\r
974 }\r
975\r
976 Status = CoreAllocateSpaceCheckEntry (Operation, Entry, GcdMemoryType, GcdIoType);\r
977 if (EFI_ERROR (Status)) {\r
978 continue;\r
979 }\r
980\r
981 if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown ||\r
e94a9ff7 982 GcdAllocateType == EfiGcdAllocateAnySearchTopDown) {\r
28a00297 983 if ((Entry->BaseAddress + Length) > MaxAddress) {\r
984 continue;\r
985 }\r
986 if (Length > (Entry->EndAddress + 1)) {\r
987 Status = EFI_NOT_FOUND;\r
988 goto Done;\r
989 }\r
990 if (Entry->EndAddress > MaxAddress) {\r
991 *BaseAddress = MaxAddress;\r
992 } else {\r
993 *BaseAddress = Entry->EndAddress;\r
994 }\r
995 *BaseAddress = (*BaseAddress + 1 - Length) & (~AlignmentMask);\r
996 } else {\r
997 *BaseAddress = (Entry->BaseAddress + AlignmentMask) & (~AlignmentMask);\r
998 if ((*BaseAddress + Length - 1) > MaxAddress) {\r
999 Status = EFI_NOT_FOUND;\r
1000 goto Done;\r
1001 }\r
1002 }\r
1003\r
1004 //\r
1005 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length\r
1006 //\r
1007 Status = CoreSearchGcdMapEntry (*BaseAddress, Length, &StartLink, &EndLink, Map);\r
1008 if (EFI_ERROR (Status)) {\r
1009 Status = EFI_NOT_FOUND;\r
1010 goto Done;\r
1011 }\r
1012\r
1013 Link = StartLink;\r
1014 //\r
1015 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.\r
1016 //\r
1017 Found = TRUE;\r
1018 SubLink = StartLink;\r
1019 while (SubLink != EndLink->ForwardLink) {\r
1020 Entry = CR (SubLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
1021 Status = CoreAllocateSpaceCheckEntry (Operation, Entry, GcdMemoryType, GcdIoType);\r
1022 if (EFI_ERROR (Status)) {\r
1023 Link = SubLink;\r
1024 Found = FALSE;\r
1025 break;\r
1026 }\r
1027 SubLink = SubLink->ForwardLink;\r
1028 }\r
1029 if (Found) {\r
1030 break;\r
1031 }\r
1032 }\r
1033 }\r
1034 if (!Found) {\r
1035 Status = EFI_NOT_FOUND;\r
1036 goto Done;\r
1037 }\r
1038\r
1039 //\r
1040 // Allocate work space to perform this operation\r
1041 //\r
1042 Status = CoreAllocateGcdMapEntry (&TopEntry, &BottomEntry);\r
1043 if (EFI_ERROR (Status)) {\r
1044 Status = EFI_OUT_OF_RESOURCES;\r
1045 goto Done;\r
1046 }\r
1047\r
1048 //\r
1049 // Convert/Insert the list of descriptors from StartLink to EndLink\r
1050 //\r
1051 Link = StartLink;\r
1052 while (Link != EndLink->ForwardLink) {\r
1053 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
1054 CoreInsertGcdMapEntry (Link, Entry, *BaseAddress, Length, TopEntry, BottomEntry);\r
1055 Entry->ImageHandle = ImageHandle;\r
1056 Entry->DeviceHandle = DeviceHandle;\r
1057 Link = Link->ForwardLink;\r
1058 }\r
1059\r
1060 //\r
1061 // Cleanup\r
1062 //\r
1063 Status = CoreCleanupGcdMapEntry (TopEntry, BottomEntry, StartLink, EndLink, Map);\r
1064\r
1065Done:\r
71f68914 1066 if ((Operation & GCD_MEMORY_SPACE_OPERATION) != 0) {\r
28a00297 1067 CoreReleaseGcdMemoryLock ();\r
1068 }\r
71f68914 1069 if ((Operation & GCD_IO_SPACE_OPERATION) !=0) {\r
28a00297 1070 CoreReleaseGcdIoLock ();\r
1071 }\r
1072\r
1073 return Status;\r
1074}\r
1075\r
28a00297 1076\r
162ed594 1077/**\r
28a00297 1078 Add a segment of memory to GCD map.\r
1079\r
022c6d45 1080 @param GcdMemoryType Memory type of the segment.\r
1081 @param BaseAddress Base address of the segment.\r
1082 @param Length Length of the segment.\r
1083 @param Capabilities alterable attributes of the segment.\r
28a00297 1084\r
022c6d45 1085 @retval EFI_INVALID_PARAMETER Invalid parameters.\r
162ed594 1086 @retval EFI_SUCCESS Successfully add a segment of memory space.\r
28a00297 1087\r
162ed594 1088**/\r
162ed594 1089EFI_STATUS\r
1090CoreInternalAddMemorySpace (\r
1091 IN EFI_GCD_MEMORY_TYPE GcdMemoryType,\r
1092 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
1093 IN UINT64 Length,\r
1094 IN UINT64 Capabilities\r
1095 )\r
28a00297 1096{\r
1097 //\r
1098 // Make sure parameters are valid\r
1099 //\r
1100 if (GcdMemoryType <= EfiGcdMemoryTypeNonExistent || GcdMemoryType >= EfiGcdMemoryTypeMaximum) {\r
1101 return EFI_INVALID_PARAMETER;\r
1102 }\r
1103\r
1104 return CoreConvertSpace (GCD_ADD_MEMORY_OPERATION, GcdMemoryType, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, Capabilities, 0);\r
1105}\r
1106\r
1107//\r
1108// GCD Core Services\r
1109//\r
162ed594 1110\r
1111/**\r
1112 Allocates nonexistent memory, reserved memory, system memory, or memorymapped\r
1113 I/O resources from the global coherency domain of the processor.\r
1114\r
022c6d45 1115 @param GcdAllocateType The type of allocate operation\r
1116 @param GcdMemoryType The desired memory type\r
1117 @param Alignment Align with 2^Alignment\r
1118 @param Length Length to allocate\r
1119 @param BaseAddress Base address to allocate\r
1120 @param ImageHandle The image handle consume the allocated space.\r
1121 @param DeviceHandle The device handle consume the allocated space.\r
162ed594 1122\r
022c6d45 1123 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
1124 @retval EFI_NOT_FOUND No descriptor contains the desired space.\r
162ed594 1125 @retval EFI_SUCCESS Memory space successfully allocated.\r
1126\r
1127**/\r
28a00297 1128EFI_STATUS\r
3b6ffb6a 1129EFIAPI\r
28a00297 1130CoreAllocateMemorySpace (\r
1131 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType,\r
1132 IN EFI_GCD_MEMORY_TYPE GcdMemoryType,\r
1133 IN UINTN Alignment,\r
1134 IN UINT64 Length,\r
1135 IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,\r
1136 IN EFI_HANDLE ImageHandle,\r
1137 IN EFI_HANDLE DeviceHandle OPTIONAL\r
1138 )\r
28a00297 1139{\r
1140 return CoreAllocateSpace (\r
022c6d45 1141 GCD_ALLOCATE_MEMORY_OPERATION,\r
1142 GcdAllocateType,\r
1143 GcdMemoryType,\r
1144 (EFI_GCD_IO_TYPE) 0,\r
1145 Alignment,\r
1146 Length,\r
1147 BaseAddress,\r
1148 ImageHandle,\r
28a00297 1149 DeviceHandle\r
1150 );\r
1151}\r
1152\r
162ed594 1153\r
1154/**\r
1155 Adds reserved memory, system memory, or memory-mapped I/O resources to the\r
1156 global coherency domain of the processor.\r
1157\r
022c6d45 1158 @param GcdMemoryType Memory type of the memory space.\r
1159 @param BaseAddress Base address of the memory space.\r
1160 @param Length Length of the memory space.\r
1161 @param Capabilities alterable attributes of the memory space.\r
162ed594 1162\r
1163 @retval EFI_SUCCESS Merged this memory space into GCD map.\r
1164\r
1165**/\r
28a00297 1166EFI_STATUS\r
3b6ffb6a 1167EFIAPI\r
28a00297 1168CoreAddMemorySpace (\r
1169 IN EFI_GCD_MEMORY_TYPE GcdMemoryType,\r
1170 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
1171 IN UINT64 Length,\r
1172 IN UINT64 Capabilities\r
1173 )\r
28a00297 1174{\r
1175 EFI_STATUS Status;\r
1176 EFI_PHYSICAL_ADDRESS PageBaseAddress;\r
1177 UINT64 PageLength;\r
1178\r
1179 Status = CoreInternalAddMemorySpace (GcdMemoryType, BaseAddress, Length, Capabilities);\r
1180\r
1181 if (!EFI_ERROR (Status) && GcdMemoryType == EfiGcdMemoryTypeSystemMemory) {\r
1182\r
1183 PageBaseAddress = PageAlignLength (BaseAddress);\r
1184 PageLength = PageAlignLength (BaseAddress + Length - PageBaseAddress);\r
1185\r
1186 Status = CoreAllocateMemorySpace (\r
1187 EfiGcdAllocateAddress,\r
1188 GcdMemoryType,\r
022c6d45 1189 EFI_PAGE_SHIFT,\r
28a00297 1190 PageLength,\r
1191 &PageBaseAddress,\r
1192 gDxeCoreImageHandle,\r
1193 NULL\r
1194 );\r
1195\r
1196 if (!EFI_ERROR (Status)) {\r
1197 CoreAddMemoryDescriptor (\r
1198 EfiConventionalMemory,\r
1199 PageBaseAddress,\r
1200 RShiftU64 (PageLength, EFI_PAGE_SHIFT),\r
1201 Capabilities\r
1202 );\r
1203 } else {\r
1204 for (; PageLength != 0; PageLength -= EFI_PAGE_SIZE, PageBaseAddress += EFI_PAGE_SIZE) {\r
1205 Status = CoreAllocateMemorySpace (\r
1206 EfiGcdAllocateAddress,\r
1207 GcdMemoryType,\r
022c6d45 1208 EFI_PAGE_SHIFT,\r
28a00297 1209 EFI_PAGE_SIZE,\r
1210 &PageBaseAddress,\r
1211 gDxeCoreImageHandle,\r
1212 NULL\r
1213 );\r
1214\r
1215 if (!EFI_ERROR (Status)) {\r
1216 CoreAddMemoryDescriptor (\r
1217 EfiConventionalMemory,\r
1218 PageBaseAddress,\r
1219 1,\r
1220 Capabilities\r
1221 );\r
1222 }\r
1223 }\r
1224 }\r
1225 }\r
1226 return Status;\r
1227}\r
1228\r
28a00297 1229\r
162ed594 1230/**\r
28a00297 1231 Frees nonexistent memory, reserved memory, system memory, or memory-mapped\r
162ed594 1232 I/O resources from the global coherency domain of the processor.\r
28a00297 1233\r
022c6d45 1234 @param BaseAddress Base address of the memory space.\r
1235 @param Length Length of the memory space.\r
28a00297 1236\r
162ed594 1237 @retval EFI_SUCCESS Space successfully freed.\r
28a00297 1238\r
162ed594 1239**/\r
28a00297 1240EFI_STATUS\r
3b6ffb6a 1241EFIAPI\r
162ed594 1242CoreFreeMemorySpace (\r
28a00297 1243 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
1244 IN UINT64 Length\r
1245 )\r
162ed594 1246{\r
1247 return CoreConvertSpace (GCD_FREE_MEMORY_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, 0);\r
1248}\r
28a00297 1249\r
28a00297 1250\r
162ed594 1251/**\r
28a00297 1252 Removes reserved memory, system memory, or memory-mapped I/O resources from\r
162ed594 1253 the global coherency domain of the processor.\r
28a00297 1254\r
022c6d45 1255 @param BaseAddress Base address of the memory space.\r
1256 @param Length Length of the memory space.\r
28a00297 1257\r
162ed594 1258 @retval EFI_SUCCESS Successfully remove a segment of memory space.\r
28a00297 1259\r
162ed594 1260**/\r
1261EFI_STATUS\r
3b6ffb6a 1262EFIAPI\r
162ed594 1263CoreRemoveMemorySpace (\r
1264 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
1265 IN UINT64 Length\r
1266 )\r
28a00297 1267{\r
1268 return CoreConvertSpace (GCD_REMOVE_MEMORY_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, 0);\r
1269}\r
1270\r
162ed594 1271\r
1272/**\r
1273 Build a memory descriptor according to an entry.\r
1274\r
022c6d45 1275 @param Descriptor The descriptor to be built\r
162ed594 1276 @param Entry According to this entry\r
1277\r
1278**/\r
28a00297 1279VOID\r
1280BuildMemoryDescriptor (\r
1281 IN OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor,\r
1282 IN EFI_GCD_MAP_ENTRY *Entry\r
1283 )\r
28a00297 1284{\r
1285 Descriptor->BaseAddress = Entry->BaseAddress;\r
1286 Descriptor->Length = Entry->EndAddress - Entry->BaseAddress + 1;\r
1287 Descriptor->Capabilities = Entry->Capabilities;\r
1288 Descriptor->Attributes = Entry->Attributes;\r
1289 Descriptor->GcdMemoryType = Entry->GcdMemoryType;\r
1290 Descriptor->ImageHandle = Entry->ImageHandle;\r
1291 Descriptor->DeviceHandle = Entry->DeviceHandle;\r
1292}\r
1293\r
28a00297 1294\r
162ed594 1295/**\r
28a00297 1296 Retrieves the descriptor for a memory region containing a specified address.\r
1297\r
022c6d45 1298 @param BaseAddress Specified start address\r
1299 @param Descriptor Specified length\r
28a00297 1300\r
022c6d45 1301 @retval EFI_INVALID_PARAMETER Invalid parameter\r
162ed594 1302 @retval EFI_SUCCESS Successfully get memory space descriptor.\r
28a00297 1303\r
162ed594 1304**/\r
1305EFI_STATUS\r
3b6ffb6a 1306EFIAPI\r
162ed594 1307CoreGetMemorySpaceDescriptor (\r
1308 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
1309 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor\r
1310 )\r
28a00297 1311{\r
1312 EFI_STATUS Status;\r
1313 LIST_ENTRY *StartLink;\r
1314 LIST_ENTRY *EndLink;\r
1315 EFI_GCD_MAP_ENTRY *Entry;\r
1316\r
1317 //\r
1318 // Make sure parameters are valid\r
1319 //\r
1320 if (Descriptor == NULL) {\r
1321 return EFI_INVALID_PARAMETER;\r
1322 }\r
1323\r
1324 CoreAcquireGcdMemoryLock ();\r
1325\r
1326 //\r
022c6d45 1327 // Search for the list of descriptors that contain BaseAddress\r
28a00297 1328 //\r
1329 Status = CoreSearchGcdMapEntry (BaseAddress, 1, &StartLink, &EndLink, &mGcdMemorySpaceMap);\r
1330 if (EFI_ERROR (Status)) {\r
1331 Status = EFI_NOT_FOUND;\r
1332 } else {\r
1333 //\r
1334 // Copy the contents of the found descriptor into Descriptor\r
1335 //\r
1336 Entry = CR (StartLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
1337 BuildMemoryDescriptor (Descriptor, Entry);\r
1338 }\r
1339\r
1340 CoreReleaseGcdMemoryLock ();\r
1341\r
1342 return Status;\r
1343}\r
1344\r
162ed594 1345\r
1346/**\r
1347 Modifies the attributes for a memory region in the global coherency domain of the\r
1348 processor.\r
1349\r
022c6d45 1350 @param BaseAddress Specified start address\r
1351 @param Length Specified length\r
1352 @param Attributes Specified attributes\r
162ed594 1353\r
022c6d45 1354 @retval EFI_SUCCESS Successfully set attribute of a segment of\r
162ed594 1355 memory space.\r
1356\r
1357**/\r
28a00297 1358EFI_STATUS\r
3b6ffb6a 1359EFIAPI\r
28a00297 1360CoreSetMemorySpaceAttributes (\r
1361 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
1362 IN UINT64 Length,\r
1363 IN UINT64 Attributes\r
1364 )\r
162ed594 1365{\r
1366 return CoreConvertSpace (GCD_SET_ATTRIBUTES_MEMORY_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, Attributes);\r
1367}\r
28a00297 1368\r
28a00297 1369\r
162ed594 1370/**\r
1371 Returns a map of the memory resources in the global coherency domain of the\r
1372 processor.\r
28a00297 1373\r
022c6d45 1374 @param NumberOfDescriptors Number of descriptors.\r
1375 @param MemorySpaceMap Descriptor array\r
28a00297 1376\r
022c6d45 1377 @retval EFI_INVALID_PARAMETER Invalid parameter\r
1378 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate\r
162ed594 1379 @retval EFI_SUCCESS Successfully get memory space map.\r
28a00297 1380\r
162ed594 1381**/\r
28a00297 1382EFI_STATUS\r
3b6ffb6a 1383EFIAPI\r
28a00297 1384CoreGetMemorySpaceMap (\r
1385 OUT UINTN *NumberOfDescriptors,\r
1386 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR **MemorySpaceMap\r
1387 )\r
28a00297 1388{\r
1389 EFI_STATUS Status;\r
1390 LIST_ENTRY *Link;\r
1391 EFI_GCD_MAP_ENTRY *Entry;\r
1392 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor;\r
1393\r
1394 //\r
1395 // Make sure parameters are valid\r
1396 //\r
1397 if (NumberOfDescriptors == NULL) {\r
1398 return EFI_INVALID_PARAMETER;\r
1399 }\r
1400 if (MemorySpaceMap == NULL) {\r
1401 return EFI_INVALID_PARAMETER;\r
1402 }\r
1403\r
1404 CoreAcquireGcdMemoryLock ();\r
1405\r
1406 //\r
1407 // Count the number of descriptors\r
1408 //\r
1409 *NumberOfDescriptors = CoreCountGcdMapEntry (&mGcdMemorySpaceMap);\r
1410\r
1411 //\r
1412 // Allocate the MemorySpaceMap\r
1413 //\r
9c4ac31c 1414 *MemorySpaceMap = AllocatePool (*NumberOfDescriptors * sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR));\r
28a00297 1415 if (*MemorySpaceMap == NULL) {\r
1416 Status = EFI_OUT_OF_RESOURCES;\r
1417 goto Done;\r
1418 }\r
1419\r
1420 //\r
1421 // Fill in the MemorySpaceMap\r
1422 //\r
1423 Descriptor = *MemorySpaceMap;\r
1424 Link = mGcdMemorySpaceMap.ForwardLink;\r
1425 while (Link != &mGcdMemorySpaceMap) {\r
1426 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
1427 BuildMemoryDescriptor (Descriptor, Entry);\r
1428 Descriptor++;\r
1429 Link = Link->ForwardLink;\r
1430 }\r
1431 Status = EFI_SUCCESS;\r
1432\r
1433Done:\r
1434 CoreReleaseGcdMemoryLock ();\r
1435 return Status;\r
1436}\r
1437\r
162ed594 1438\r
1439/**\r
1440 Adds reserved I/O or I/O resources to the global coherency domain of the processor.\r
1441\r
022c6d45 1442 @param GcdIoType IO type of the segment.\r
1443 @param BaseAddress Base address of the segment.\r
1444 @param Length Length of the segment.\r
162ed594 1445\r
022c6d45 1446 @retval EFI_SUCCESS Merged this segment into GCD map.\r
162ed594 1447 @retval EFI_INVALID_PARAMETER Parameter not valid\r
1448\r
1449**/\r
28a00297 1450EFI_STATUS\r
3b6ffb6a 1451EFIAPI\r
28a00297 1452CoreAddIoSpace (\r
1453 IN EFI_GCD_IO_TYPE GcdIoType,\r
1454 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
1455 IN UINT64 Length\r
1456 )\r
28a00297 1457{\r
1458 //\r
1459 // Make sure parameters are valid\r
1460 //\r
1461 if (GcdIoType <= EfiGcdIoTypeNonExistent || GcdIoType >= EfiGcdIoTypeMaximum) {\r
1462 return EFI_INVALID_PARAMETER;\r
1463 }\r
1464 return CoreConvertSpace (GCD_ADD_IO_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, GcdIoType, BaseAddress, Length, 0, 0);\r
1465}\r
1466\r
162ed594 1467\r
1468/**\r
1469 Allocates nonexistent I/O, reserved I/O, or I/O resources from the global coherency\r
1470 domain of the processor.\r
1471\r
022c6d45 1472 @param GcdAllocateType The type of allocate operation\r
1473 @param GcdIoType The desired IO type\r
1474 @param Alignment Align with 2^Alignment\r
1475 @param Length Length to allocate\r
1476 @param BaseAddress Base address to allocate\r
1477 @param ImageHandle The image handle consume the allocated space.\r
1478 @param DeviceHandle The device handle consume the allocated space.\r
162ed594 1479\r
022c6d45 1480 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
1481 @retval EFI_NOT_FOUND No descriptor contains the desired space.\r
162ed594 1482 @retval EFI_SUCCESS IO space successfully allocated.\r
1483\r
1484**/\r
28a00297 1485EFI_STATUS\r
3b6ffb6a 1486EFIAPI\r
28a00297 1487CoreAllocateIoSpace (\r
1488 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType,\r
1489 IN EFI_GCD_IO_TYPE GcdIoType,\r
1490 IN UINTN Alignment,\r
1491 IN UINT64 Length,\r
1492 IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,\r
1493 IN EFI_HANDLE ImageHandle,\r
1494 IN EFI_HANDLE DeviceHandle OPTIONAL\r
1495 )\r
28a00297 1496{\r
1497 return CoreAllocateSpace (\r
022c6d45 1498 GCD_ALLOCATE_IO_OPERATION,\r
1499 GcdAllocateType,\r
1500 (EFI_GCD_MEMORY_TYPE) 0,\r
1501 GcdIoType,\r
1502 Alignment,\r
1503 Length,\r
1504 BaseAddress,\r
1505 ImageHandle,\r
28a00297 1506 DeviceHandle\r
1507 );\r
1508}\r
1509\r
28a00297 1510\r
162ed594 1511/**\r
28a00297 1512 Frees nonexistent I/O, reserved I/O, or I/O resources from the global coherency\r
162ed594 1513 domain of the processor.\r
28a00297 1514\r
022c6d45 1515 @param BaseAddress Base address of the segment.\r
1516 @param Length Length of the segment.\r
28a00297 1517\r
162ed594 1518 @retval EFI_SUCCESS Space successfully freed.\r
28a00297 1519\r
162ed594 1520**/\r
28a00297 1521EFI_STATUS\r
3b6ffb6a 1522EFIAPI\r
162ed594 1523CoreFreeIoSpace (\r
28a00297 1524 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
1525 IN UINT64 Length\r
1526 )\r
162ed594 1527{\r
1528 return CoreConvertSpace (GCD_FREE_IO_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, 0);\r
1529}\r
28a00297 1530\r
28a00297 1531\r
162ed594 1532/**\r
28a00297 1533 Removes reserved I/O or I/O resources from the global coherency domain of the\r
162ed594 1534 processor.\r
28a00297 1535\r
022c6d45 1536 @param BaseAddress Base address of the segment.\r
1537 @param Length Length of the segment.\r
28a00297 1538\r
162ed594 1539 @retval EFI_SUCCESS Successfully removed a segment of IO space.\r
28a00297 1540\r
162ed594 1541**/\r
1542EFI_STATUS\r
3b6ffb6a 1543EFIAPI\r
162ed594 1544CoreRemoveIoSpace (\r
1545 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
1546 IN UINT64 Length\r
1547 )\r
28a00297 1548{\r
1549 return CoreConvertSpace (GCD_REMOVE_IO_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, 0);\r
1550}\r
1551\r
162ed594 1552\r
1553/**\r
1554 Build a IO descriptor according to an entry.\r
1555\r
022c6d45 1556 @param Descriptor The descriptor to be built\r
162ed594 1557 @param Entry According to this entry\r
1558\r
1559**/\r
28a00297 1560VOID\r
1561BuildIoDescriptor (\r
1562 IN EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor,\r
1563 IN EFI_GCD_MAP_ENTRY *Entry\r
1564 )\r
28a00297 1565{\r
1566 Descriptor->BaseAddress = Entry->BaseAddress;\r
1567 Descriptor->Length = Entry->EndAddress - Entry->BaseAddress + 1;\r
1568 Descriptor->GcdIoType = Entry->GcdIoType;\r
1569 Descriptor->ImageHandle = Entry->ImageHandle;\r
1570 Descriptor->DeviceHandle = Entry->DeviceHandle;\r
1571}\r
1572\r
28a00297 1573\r
162ed594 1574/**\r
28a00297 1575 Retrieves the descriptor for an I/O region containing a specified address.\r
1576\r
022c6d45 1577 @param BaseAddress Specified start address\r
1578 @param Descriptor Specified length\r
28a00297 1579\r
022c6d45 1580 @retval EFI_INVALID_PARAMETER Descriptor is NULL.\r
162ed594 1581 @retval EFI_SUCCESS Successfully get the IO space descriptor.\r
28a00297 1582\r
162ed594 1583**/\r
1584EFI_STATUS\r
3b6ffb6a 1585EFIAPI\r
162ed594 1586CoreGetIoSpaceDescriptor (\r
1587 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
1588 OUT EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor\r
1589 )\r
28a00297 1590{\r
1591 EFI_STATUS Status;\r
1592 LIST_ENTRY *StartLink;\r
1593 LIST_ENTRY *EndLink;\r
1594 EFI_GCD_MAP_ENTRY *Entry;\r
1595\r
1596 //\r
1597 // Make sure parameters are valid\r
1598 //\r
1599 if (Descriptor == NULL) {\r
1600 return EFI_INVALID_PARAMETER;\r
1601 }\r
1602\r
1603 CoreAcquireGcdIoLock ();\r
1604\r
1605 //\r
022c6d45 1606 // Search for the list of descriptors that contain BaseAddress\r
28a00297 1607 //\r
1608 Status = CoreSearchGcdMapEntry (BaseAddress, 1, &StartLink, &EndLink, &mGcdIoSpaceMap);\r
1609 if (EFI_ERROR (Status)) {\r
1610 Status = EFI_NOT_FOUND;\r
1611 } else {\r
1612 //\r
1613 // Copy the contents of the found descriptor into Descriptor\r
1614 //\r
1615 Entry = CR (StartLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
1616 BuildIoDescriptor (Descriptor, Entry);\r
1617 }\r
1618\r
1619 CoreReleaseGcdIoLock ();\r
1620\r
1621 return Status;\r
1622}\r
1623\r
28a00297 1624\r
162ed594 1625/**\r
28a00297 1626 Returns a map of the I/O resources in the global coherency domain of the processor.\r
1627\r
022c6d45 1628 @param NumberOfDescriptors Number of descriptors.\r
1629 @param IoSpaceMap Descriptor array\r
28a00297 1630\r
022c6d45 1631 @retval EFI_INVALID_PARAMETER Invalid parameter\r
1632 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate\r
162ed594 1633 @retval EFI_SUCCESS Successfully get IO space map.\r
28a00297 1634\r
162ed594 1635**/\r
1636EFI_STATUS\r
3b6ffb6a 1637EFIAPI\r
162ed594 1638CoreGetIoSpaceMap (\r
1639 OUT UINTN *NumberOfDescriptors,\r
1640 OUT EFI_GCD_IO_SPACE_DESCRIPTOR **IoSpaceMap\r
1641 )\r
28a00297 1642{\r
1643 EFI_STATUS Status;\r
1644 LIST_ENTRY *Link;\r
1645 EFI_GCD_MAP_ENTRY *Entry;\r
1646 EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor;\r
1647\r
1648 //\r
1649 // Make sure parameters are valid\r
1650 //\r
1651 if (NumberOfDescriptors == NULL) {\r
1652 return EFI_INVALID_PARAMETER;\r
1653 }\r
1654 if (IoSpaceMap == NULL) {\r
1655 return EFI_INVALID_PARAMETER;\r
1656 }\r
1657\r
1658 CoreAcquireGcdIoLock ();\r
1659\r
1660 //\r
1661 // Count the number of descriptors\r
1662 //\r
1663 *NumberOfDescriptors = CoreCountGcdMapEntry (&mGcdIoSpaceMap);\r
1664\r
1665 //\r
1666 // Allocate the IoSpaceMap\r
1667 //\r
9c4ac31c 1668 *IoSpaceMap = AllocatePool (*NumberOfDescriptors * sizeof (EFI_GCD_IO_SPACE_DESCRIPTOR));\r
28a00297 1669 if (*IoSpaceMap == NULL) {\r
1670 Status = EFI_OUT_OF_RESOURCES;\r
1671 goto Done;\r
1672 }\r
1673\r
1674 //\r
1675 // Fill in the IoSpaceMap\r
1676 //\r
1677 Descriptor = *IoSpaceMap;\r
1678 Link = mGcdIoSpaceMap.ForwardLink;\r
1679 while (Link != &mGcdIoSpaceMap) {\r
1680 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
1681 BuildIoDescriptor (Descriptor, Entry);\r
1682 Descriptor++;\r
1683 Link = Link->ForwardLink;\r
1684 }\r
1685 Status = EFI_SUCCESS;\r
1686\r
1687Done:\r
1688 CoreReleaseGcdIoLock ();\r
1689 return Status;\r
022c6d45 1690}\r
28a00297 1691\r
162ed594 1692\r
1693/**\r
1694 Converts a Resource Descriptor HOB attributes mask to an EFI Memory Descriptor\r
1695 capabilities mask\r
1696\r
022c6d45 1697 @param GcdMemoryType Type of resource in the GCD memory map.\r
1698 @param Attributes The attribute mask in the Resource Descriptor\r
1699 HOB.\r
162ed594 1700\r
1701 @return The capabilities mask for an EFI Memory Descriptor.\r
1702\r
1703**/\r
28a00297 1704UINT64\r
1705CoreConvertResourceDescriptorHobAttributesToCapabilities (\r
1706 EFI_GCD_MEMORY_TYPE GcdMemoryType,\r
1707 UINT64 Attributes\r
1708 )\r
28a00297 1709{\r
1710 UINT64 Capabilities;\r
1711 GCD_ATTRIBUTE_CONVERSION_ENTRY *Conversion;\r
022c6d45 1712\r
28a00297 1713 //\r
1714 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask\r
1715 //\r
1716 for (Capabilities = 0, Conversion = mAttributeConversionTable; Conversion->Attribute != 0; Conversion++) {\r
1717 if (Conversion->Memory || (GcdMemoryType != EfiGcdMemoryTypeSystemMemory)) {\r
1718 if (Attributes & Conversion->Attribute) {\r
1719 Capabilities |= Conversion->Capability;\r
1720 }\r
1721 }\r
1722 }\r
022c6d45 1723\r
28a00297 1724 return Capabilities;\r
1725}\r
1726\r
28a00297 1727\r
162ed594 1728/**\r
c18f12d3 1729 External function. Initializes memory services based on the memory\r
1730 descriptor HOBs. This function is responsible for priming the memory\r
1731 map, so memory allocations and resource allocations can be made.\r
1732 The first part of this function can not depend on any memory services\r
1733 until at least one memory descriptor is provided to the memory services.\r
28a00297 1734\r
022c6d45 1735 @param HobStart The start address of the HOB.\r
1736 @param MemoryBaseAddress Start address of memory region found to init DXE\r
1737 core.\r
1738 @param MemoryLength Length of memory region found to init DXE core.\r
28a00297 1739\r
162ed594 1740 @retval EFI_SUCCESS Memory services successfully initialized.\r
28a00297 1741\r
162ed594 1742**/\r
1743EFI_STATUS\r
1744CoreInitializeMemoryServices (\r
1745 IN VOID **HobStart,\r
1746 OUT EFI_PHYSICAL_ADDRESS *MemoryBaseAddress,\r
1747 OUT UINT64 *MemoryLength\r
1748 )\r
28a00297 1749{\r
1750 EFI_PEI_HOB_POINTERS Hob;\r
1751 EFI_MEMORY_TYPE_INFORMATION *EfiMemoryTypeInformation;\r
1752 UINTN DataSize;\r
1753 BOOLEAN Found;\r
1754 EFI_HOB_HANDOFF_INFO_TABLE *PhitHob;\r
1755 EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;\r
1756 EFI_HOB_RESOURCE_DESCRIPTOR *PhitResourceHob;\r
1757 EFI_PHYSICAL_ADDRESS BaseAddress;\r
1758 UINT64 Length;\r
1759 UINT64 Attributes;\r
1760 UINT64 Capabilities;\r
1761 EFI_PHYSICAL_ADDRESS MaxMemoryBaseAddress;\r
1762 UINT64 MaxMemoryLength;\r
1763 UINT64 MaxMemoryAttributes;\r
1764 EFI_PHYSICAL_ADDRESS MaxAddress;\r
1765 EFI_PHYSICAL_ADDRESS HighAddress;\r
1766 EFI_HOB_RESOURCE_DESCRIPTOR *MaxResourceHob;\r
1767 EFI_HOB_GUID_TYPE *GuidHob;\r
54ea99a7 1768 UINT32 ReservedCodePageNumber;\r
28a00297 1769\r
1770 //\r
1771 // Point at the first HOB. This must be the PHIT HOB.\r
1772 //\r
1773 Hob.Raw = *HobStart;\r
1774 ASSERT (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_HANDOFF);\r
1775\r
1776 //\r
1777 // Initialize the spin locks and maps in the memory services.\r
1778 // Also fill in the memory services into the EFI Boot Services Table\r
1779 //\r
1780 CoreInitializePool ();\r
1781\r
1782 //\r
1783 // Initialize Local Variables\r
1784 //\r
1785 PhitResourceHob = NULL;\r
1786 MaxResourceHob = NULL;\r
1787 ResourceHob = NULL;\r
1788 BaseAddress = 0;\r
1789 Length = 0;\r
1790 Attributes = 0;\r
1791 MaxMemoryBaseAddress = 0;\r
1792 MaxMemoryLength = 0;\r
1793 MaxMemoryAttributes = 0;\r
1794\r
1795 //\r
1796 // Cache the PHIT HOB for later use\r
1797 //\r
1798 PhitHob = Hob.HandoffInformationTable;\r
54ea99a7 1799 \r
852081fc 1800 if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {\r
54ea99a7 1801 ReservedCodePageNumber = PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber);\r
1802 ReservedCodePageNumber += PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber);\r
1803 \r
1804 //\r
1805 // cache the Top address for loading modules at Fixed Address \r
1806 //\r
1807 gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress = PhitHob->EfiMemoryTop \r
1808 + EFI_PAGES_TO_SIZE(ReservedCodePageNumber);\r
1809 }\r
28a00297 1810 //\r
1811 // See if a Memory Type Information HOB is available\r
1812 //\r
1813 GuidHob = GetFirstGuidHob (&gEfiMemoryTypeInformationGuid);\r
1814 if (GuidHob != NULL) {\r
1815 EfiMemoryTypeInformation = GET_GUID_HOB_DATA (GuidHob);\r
1816 DataSize = GET_GUID_HOB_DATA_SIZE (GuidHob);\r
1817 if (EfiMemoryTypeInformation != NULL && DataSize > 0 && DataSize <= (EfiMaxMemoryType + 1) * sizeof (EFI_MEMORY_TYPE_INFORMATION)) {\r
1818 CopyMem (&gMemoryTypeInformation, EfiMemoryTypeInformation, DataSize);\r
1819 }\r
1820 }\r
1821\r
1822 //\r
1823 // Find the Resource Descriptor HOB that contains range FreeMemoryBaseAddress..FreeMemoryLength\r
1824 //\r
1825 Length = 0;\r
1826 Found = FALSE;\r
1827 for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {\r
1828\r
1829 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
1830\r
1831 ResourceHob = Hob.ResourceDescriptor;\r
1832\r
1833 if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&\r
1834 (ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == TESTED_MEMORY_ATTRIBUTES ) {\r
1835\r
022c6d45 1836 if (PhitHob->EfiFreeMemoryBottom >= ResourceHob->PhysicalStart &&\r
28a00297 1837 PhitHob->EfiFreeMemoryTop <= (ResourceHob->PhysicalStart + ResourceHob->ResourceLength) ) {\r
1838\r
1839 //\r
1840 // Cache the resource descriptor HOB for the memory region described by the PHIT HOB\r
1841 //\r
1842 PhitResourceHob = ResourceHob;\r
1843 Found = TRUE;\r
1844\r
1845 Attributes = PhitResourceHob->ResourceAttribute;\r
1846 BaseAddress = PageAlignAddress (PhitHob->EfiMemoryTop);\r
1847 Length = PageAlignLength (ResourceHob->PhysicalStart + ResourceHob->ResourceLength - BaseAddress);\r
1848 if (Length < MINIMUM_INITIAL_MEMORY_SIZE) {\r
1849 BaseAddress = PageAlignAddress (PhitHob->EfiFreeMemoryBottom);\r
1850 Length = PageAlignLength (PhitHob->EfiFreeMemoryTop - BaseAddress);\r
1851 if (Length < MINIMUM_INITIAL_MEMORY_SIZE) {\r
1852 BaseAddress = PageAlignAddress (ResourceHob->PhysicalStart);\r
1853 Length = PageAlignLength ((UINT64)((UINTN)*HobStart - BaseAddress));\r
1854 }\r
1855 }\r
1856 break;\r
1857 }\r
1858 }\r
1859 }\r
1860 }\r
1861\r
1862 //\r
1863 // Assert if a resource descriptor HOB for the memory region described by the PHIT was not found\r
1864 //\r
1865 ASSERT (Found);\r
1866\r
1867 //\r
1868 // Search all the resource descriptor HOBs from the highest possible addresses down for a memory\r
1869 // region that is big enough to initialize the DXE core. Always skip the PHIT Resource HOB.\r
1870 // The max address must be within the physically addressible range for the processor.\r
1871 //\r
1872 MaxMemoryLength = 0;\r
f3f2e05d 1873 MaxAddress = MAX_ADDRESS;\r
28a00297 1874 do {\r
1875 HighAddress = 0;\r
1876 Found = FALSE;\r
1877 //\r
1878 // Search for a tested memory region that is below MaxAddress\r
1879 //\r
1880 for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {\r
1881\r
1882 //\r
1883 // See if this is a resource descriptor HOB that does not contain the PHIT.\r
1884 //\r
1885 if (Hob.ResourceDescriptor != PhitResourceHob && GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
1886\r
1887 ResourceHob = Hob.ResourceDescriptor;\r
1888 //\r
1889 // See if this resource descrior HOB describes tested system memory below MaxAddress\r
1890 //\r
e94a9ff7 1891 if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&\r
1892 (ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == TESTED_MEMORY_ATTRIBUTES &&\r
1893 ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MaxAddress) {\r
28a00297 1894 //\r
1895 // See if this is the highest tested system memory region below MaxAddress\r
1896 //\r
1897 if (ResourceHob->PhysicalStart > HighAddress) {\r
1898\r
1899 MaxResourceHob = ResourceHob;\r
1900 HighAddress = MaxResourceHob->PhysicalStart;\r
1901 Found = TRUE;\r
1902 }\r
1903 }\r
1904 }\r
1905 }\r
1906 if (Found) {\r
1907 //\r
1908 // Compute the size of the tested memory region below MaxAddrees\r
1909 //\r
1910 MaxMemoryBaseAddress = PageAlignAddress (MaxResourceHob->PhysicalStart);\r
1911 MaxMemoryLength = PageAlignLength (MaxResourceHob->PhysicalStart + MaxResourceHob->ResourceLength - MaxMemoryBaseAddress);\r
1912 MaxMemoryAttributes = MaxResourceHob->ResourceAttribute;\r
1913 }\r
1914 MaxAddress = ResourceHob->PhysicalStart;\r
1915 } while (Found && MaxMemoryLength < MINIMUM_INITIAL_MEMORY_SIZE);\r
1916\r
e94a9ff7 1917 if ((Length < MINIMUM_INITIAL_MEMORY_SIZE) ||\r
1918 (MaxMemoryBaseAddress > BaseAddress && MaxMemoryLength >= MINIMUM_INITIAL_MEMORY_SIZE)) {\r
28a00297 1919 BaseAddress = MaxMemoryBaseAddress;\r
1920 Length = MaxMemoryLength;\r
1921 Attributes = MaxMemoryAttributes;\r
1922 }\r
1923\r
1924 //\r
1925 // If no memory regions are found that are big enough to initialize the DXE core, then ASSERT().\r
1926 //\r
1927 ASSERT (Length >= MINIMUM_INITIAL_MEMORY_SIZE);\r
1928\r
1929 //\r
1930 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask\r
1931 //\r
1932 Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeSystemMemory, Attributes);\r
1933\r
1934 //\r
1935 // Declare the very first memory region, so the EFI Memory Services are available.\r
1936 //\r
1937 CoreAddMemoryDescriptor (\r
1938 EfiConventionalMemory,\r
1939 BaseAddress,\r
1940 RShiftU64 (Length, EFI_PAGE_SHIFT),\r
1941 Capabilities\r
1942 );\r
1943\r
1944 *MemoryBaseAddress = BaseAddress;\r
1945 *MemoryLength = Length;\r
1946\r
1947 return EFI_SUCCESS;\r
1948}\r
1949\r
28a00297 1950\r
162ed594 1951/**\r
1952 External function. Initializes the GCD and memory services based on the memory\r
28a00297 1953 descriptor HOBs. This function is responsible for priming the GCD map and the\r
c18f12d3 1954 memory map, so memory allocations and resource allocations can be made. The\r
1955 HobStart will be relocated to a pool buffer.\r
28a00297 1956\r
022c6d45 1957 @param HobStart The start address of the HOB\r
1958 @param MemoryBaseAddress Start address of memory region found to init DXE\r
1959 core.\r
1960 @param MemoryLength Length of memory region found to init DXE core.\r
28a00297 1961\r
162ed594 1962 @retval EFI_SUCCESS GCD services successfully initialized.\r
28a00297 1963\r
162ed594 1964**/\r
1965EFI_STATUS\r
1966CoreInitializeGcdServices (\r
e94a9ff7 1967 IN OUT VOID **HobStart,\r
162ed594 1968 IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress,\r
1969 IN UINT64 MemoryLength\r
1970 )\r
28a00297 1971{\r
e94a9ff7 1972 EFI_PEI_HOB_POINTERS Hob;\r
28a00297 1973 VOID *NewHobList;\r
e94a9ff7 1974 EFI_HOB_HANDOFF_INFO_TABLE *PhitHob;\r
28a00297 1975 UINT8 SizeOfMemorySpace;\r
1976 UINT8 SizeOfIoSpace;\r
1977 EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;\r
1978 EFI_PHYSICAL_ADDRESS BaseAddress;\r
1979 UINT64 Length;\r
1980 EFI_STATUS Status;\r
1981 EFI_GCD_MAP_ENTRY *Entry;\r
1982 EFI_GCD_MEMORY_TYPE GcdMemoryType;\r
1983 EFI_GCD_IO_TYPE GcdIoType;\r
1984 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;\r
1985 EFI_HOB_MEMORY_ALLOCATION *MemoryHob;\r
1986 EFI_HOB_FIRMWARE_VOLUME *FirmwareVolumeHob;\r
1987 UINTN NumberOfDescriptors;\r
1988 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;\r
1989 UINTN Index;\r
1990 UINT64 Capabilities;\r
1991 EFI_HOB_CPU * CpuHob;\r
e94a9ff7 1992\r
28a00297 1993 //\r
1994 // Cache the PHIT HOB for later use\r
1995 //\r
1996 PhitHob = (EFI_HOB_HANDOFF_INFO_TABLE *)(*HobStart);\r
1997\r
1998 //\r
1999 // Get the number of address lines in the I/O and Memory space for the CPU\r
2000 //\r
2001 CpuHob = GetFirstHob (EFI_HOB_TYPE_CPU);\r
2002 ASSERT (CpuHob != NULL);\r
2003 SizeOfMemorySpace = CpuHob->SizeOfMemorySpace;\r
2004 SizeOfIoSpace = CpuHob->SizeOfIoSpace;\r
022c6d45 2005\r
28a00297 2006 //\r
2007 // Initialize the GCD Memory Space Map\r
2008 //\r
9c4ac31c 2009 Entry = AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY), &mGcdMemorySpaceMapEntryTemplate);\r
28a00297 2010 ASSERT (Entry != NULL);\r
2011\r
2012 Entry->EndAddress = LShiftU64 (1, SizeOfMemorySpace) - 1;\r
2013\r
2014 InsertHeadList (&mGcdMemorySpaceMap, &Entry->Link);\r
2015\r
2016 //\r
2017 // Initialize the GCD I/O Space Map\r
2018 //\r
9c4ac31c 2019 Entry = AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY), &mGcdIoSpaceMapEntryTemplate);\r
28a00297 2020 ASSERT (Entry != NULL);\r
2021\r
2022 Entry->EndAddress = LShiftU64 (1, SizeOfIoSpace) - 1;\r
2023\r
2024 InsertHeadList (&mGcdIoSpaceMap, &Entry->Link);\r
2025\r
2026 //\r
022c6d45 2027 // Walk the HOB list and add all resource descriptors to the GCD\r
28a00297 2028 //\r
2029 for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {\r
2030\r
2031 GcdMemoryType = EfiGcdMemoryTypeNonExistent;\r
2032 GcdIoType = EfiGcdIoTypeNonExistent;\r
2033\r
2034 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
2035\r
2036 ResourceHob = Hob.ResourceDescriptor;\r
2037\r
2038 switch (ResourceHob->ResourceType) {\r
2039 case EFI_RESOURCE_SYSTEM_MEMORY:\r
2040 if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == TESTED_MEMORY_ATTRIBUTES) {\r
2041 GcdMemoryType = EfiGcdMemoryTypeSystemMemory;\r
2042 }\r
2043 if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == INITIALIZED_MEMORY_ATTRIBUTES) {\r
2044 GcdMemoryType = EfiGcdMemoryTypeReserved;\r
2045 }\r
2046 if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == PRESENT_MEMORY_ATTRIBUTES) {\r
2047 GcdMemoryType = EfiGcdMemoryTypeReserved;\r
2048 }\r
2049 break;\r
2050 case EFI_RESOURCE_MEMORY_MAPPED_IO:\r
2051 case EFI_RESOURCE_FIRMWARE_DEVICE:\r
2052 GcdMemoryType = EfiGcdMemoryTypeMemoryMappedIo;\r
2053 break;\r
2054 case EFI_RESOURCE_MEMORY_MAPPED_IO_PORT:\r
2055 case EFI_RESOURCE_MEMORY_RESERVED:\r
2056 GcdMemoryType = EfiGcdMemoryTypeReserved;\r
2057 break;\r
2058 case EFI_RESOURCE_IO:\r
2059 GcdIoType = EfiGcdIoTypeIo;\r
2060 break;\r
2061 case EFI_RESOURCE_IO_RESERVED:\r
2062 GcdIoType = EfiGcdIoTypeReserved;\r
2063 break;\r
2064 }\r
2065\r
2066 if (GcdMemoryType != EfiGcdMemoryTypeNonExistent) {\r
28a00297 2067 //\r
2068 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask\r
2069 //\r
2070 Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities (\r
2071 GcdMemoryType,\r
2072 ResourceHob->ResourceAttribute\r
2073 );\r
2074\r
2075 Status = CoreInternalAddMemorySpace (\r
2076 GcdMemoryType,\r
2077 ResourceHob->PhysicalStart,\r
2078 ResourceHob->ResourceLength,\r
2079 Capabilities\r
2080 );\r
2081 }\r
2082\r
2083 if (GcdIoType != EfiGcdIoTypeNonExistent) {\r
2084 Status = CoreAddIoSpace (\r
2085 GcdIoType,\r
2086 ResourceHob->PhysicalStart,\r
2087 ResourceHob->ResourceLength\r
2088 );\r
2089 }\r
2090 }\r
2091 }\r
2092\r
2093 //\r
2094 // Allocate first memory region from the GCD by the DXE core\r
2095 //\r
2096 Status = CoreAllocateMemorySpace (\r
2097 EfiGcdAllocateAddress,\r
2098 EfiGcdMemoryTypeSystemMemory,\r
2099 0,\r
2100 MemoryLength,\r
2101 &MemoryBaseAddress,\r
2102 gDxeCoreImageHandle,\r
2103 NULL\r
2104 );\r
2105\r
2106 //\r
2107 // Walk the HOB list and allocate all memory space that is consumed by memory allocation HOBs,\r
2108 // and Firmware Volume HOBs. Also update the EFI Memory Map with the memory allocation HOBs.\r
2109 //\r
2110 for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {\r
2111 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) {\r
2112 MemoryHob = Hob.MemoryAllocation;\r
2113 BaseAddress = MemoryHob->AllocDescriptor.MemoryBaseAddress;\r
f942f107 2114 Status = CoreGetMemorySpaceDescriptor (BaseAddress, &Descriptor);\r
28a00297 2115 if (!EFI_ERROR (Status)) {\r
f942f107 2116 Status = CoreAllocateMemorySpace (\r
2117 EfiGcdAllocateAddress,\r
022c6d45 2118 Descriptor.GcdMemoryType,\r
f942f107 2119 0,\r
2120 MemoryHob->AllocDescriptor.MemoryLength,\r
2121 &BaseAddress,\r
2122 gDxeCoreImageHandle,\r
2123 NULL\r
2124 );\r
2125 if (!EFI_ERROR (Status) && Descriptor.GcdMemoryType == EfiGcdMemoryTypeSystemMemory) {\r
28a00297 2126 CoreAddMemoryDescriptor (\r
2127 MemoryHob->AllocDescriptor.MemoryType,\r
2128 MemoryHob->AllocDescriptor.MemoryBaseAddress,\r
2129 RShiftU64 (MemoryHob->AllocDescriptor.MemoryLength, EFI_PAGE_SHIFT),\r
2130 Descriptor.Capabilities & (~EFI_MEMORY_RUNTIME)\r
2131 );\r
2132 }\r
2133 }\r
2134 }\r
2135\r
2136 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV) {\r
2137 FirmwareVolumeHob = Hob.FirmwareVolume;\r
2138 BaseAddress = FirmwareVolumeHob->BaseAddress;\r
2139 Status = CoreAllocateMemorySpace (\r
2140 EfiGcdAllocateAddress,\r
022c6d45 2141 EfiGcdMemoryTypeMemoryMappedIo,\r
28a00297 2142 0,\r
2143 FirmwareVolumeHob->Length,\r
2144 &BaseAddress,\r
2145 gDxeCoreImageHandle,\r
2146 NULL\r
2147 );\r
2148 }\r
2149 }\r
2150\r
2151 //\r
2152 // Relocate HOB List to an allocated pool buffer.\r
2153 //\r
9c4ac31c 2154 NewHobList = AllocateCopyPool (\r
022c6d45 2155 (UINTN)PhitHob->EfiFreeMemoryBottom - (UINTN)(*HobStart),\r
28a00297 2156 *HobStart\r
2157 );\r
2158 ASSERT (NewHobList != NULL);\r
2159\r
2160 *HobStart = NewHobList;\r
05339bd7 2161 gHobList = NewHobList;\r
28a00297 2162\r
2163 //\r
2164 // Add and allocate the remaining unallocated system memory to the memory services.\r
2165 //\r
2166 Status = CoreGetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);\r
311a71b2 2167 ASSERT (Status == EFI_SUCCESS);\r
2168\r
28a00297 2169 for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
2170 if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeSystemMemory) {\r
2171 if (MemorySpaceMap[Index].ImageHandle == NULL) {\r
2172 BaseAddress = PageAlignAddress (MemorySpaceMap[Index].BaseAddress);\r
2173 Length = PageAlignLength (MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - BaseAddress);\r
383c303c 2174 if (Length == 0 || MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length < BaseAddress) {\r
2175 continue;\r
2176 }\r
28a00297 2177 CoreAddMemoryDescriptor (\r
2178 EfiConventionalMemory,\r
2179 BaseAddress,\r
2180 RShiftU64 (Length, EFI_PAGE_SHIFT),\r
2181 MemorySpaceMap[Index].Capabilities & (~EFI_MEMORY_RUNTIME)\r
2182 );\r
2183 Status = CoreAllocateMemorySpace (\r
2184 EfiGcdAllocateAddress,\r
2185 EfiGcdMemoryTypeSystemMemory,\r
2186 0,\r
2187 Length,\r
2188 &BaseAddress,\r
2189 gDxeCoreImageHandle,\r
2190 NULL\r
2191 );\r
2192 }\r
2193 }\r
2194 }\r
2195 CoreFreePool (MemorySpaceMap);\r
2196\r
2197 return EFI_SUCCESS;\r
2198}\r