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