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