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