2 UncachedMemoryAllocation lib that uses DXE CPU driver to chnage cachability for
5 Copyright (c) 2008-2010, Apple Inc. All rights reserved.
7 All rights reserved. This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include <Library/BaseLib.h>
18 #include <Library/BaseMemoryLib.h>
19 #include <Library/MemoryAllocationLib.h>
20 #include <Library/DebugLib.h>
21 #include <Library/UefiBootServicesTableLib.h>
22 #include <Library/UncachedMemoryAllocationLib.h>
23 #include <Library/PcdLib.h>
24 #include <Library/ArmLib.h>
25 #include <Library/DxeServicesTableLib.h>
27 #include <Protocol/Cpu.h>
30 UncachedInternalAllocatePages (
31 IN EFI_MEMORY_TYPE MemoryType
,
36 UncachedInternalAllocateAlignedPages (
37 IN EFI_MEMORY_TYPE MemoryType
,
44 EFI_CPU_ARCH_PROTOCOL
*gDebugUncachedCpu
;
47 // Assume all of memory has the same cache attributes, unless we do our magic
57 LIST_ENTRY mPageList
= INITIALIZE_LIST_HEAD_VARIABLE (mPageList
);
65 FREE_PAGE_NODE
*NewNode
;
67 NewNode
= AllocatePool (sizeof (LIST_ENTRY
));
68 if (NewNode
== NULL
) {
73 NewNode
->Allocation
= Allocation
;
74 NewNode
->Pages
= Pages
;
76 InsertTailList (&mPageList
, &NewNode
->Link
);
87 FREE_PAGE_NODE
*OldNode
;
91 for (Link
= mPageList
.ForwardLink
; Link
!= &mPageList
; Link
= Link
->ForwardLink
) {
92 OldNode
= BASE_CR (Link
, FREE_PAGE_NODE
, Link
);
93 if (OldNode
->Allocation
== Allocation
) {
94 *Pages
= OldNode
->Pages
;
96 RemoveEntryList (&OldNode
->Link
);
107 Converts a cached or uncached address to a physical address suitable for use in SoC registers.
109 @param VirtualAddress The pointer to convert.
111 @return The physical address of the supplied virtual pointer.
115 ConvertToPhysicalAddress (
116 IN VOID
*VirtualAddress
119 return (EFI_PHYSICAL_ADDRESS
)(UINTN
)VirtualAddress
;
124 UncachedInternalAllocatePages (
125 IN EFI_MEMORY_TYPE MemoryType
,
129 return UncachedInternalAllocateAlignedPages (MemoryType
, Pages
, EFI_PAGE_SIZE
);
135 UncachedAllocatePages (
139 return UncachedInternalAllocatePages (EfiBootServicesData
, Pages
);
144 UncachedAllocateRuntimePages (
148 return UncachedInternalAllocatePages (EfiRuntimeServicesData
, Pages
);
153 UncachedAllocateReservedPages (
157 return UncachedInternalAllocatePages (EfiReservedMemoryType
, Pages
);
169 UncachedFreeAlignedPages (Buffer
, Pages
);
175 UncachedInternalAllocateAlignedPages (
176 IN EFI_MEMORY_TYPE MemoryType
,
182 EFI_PHYSICAL_ADDRESS Memory
;
183 EFI_PHYSICAL_ADDRESS AlignedMemory
;
185 UINTN UnalignedPages
;
187 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor
;
190 // Alignment must be a power of two or zero.
192 ASSERT ((Alignment
& (Alignment
- 1)) == 0);
197 if (Alignment
> EFI_PAGE_SIZE
) {
199 // Caculate the total number of pages since alignment is larger than page size.
201 AlignmentMask
= Alignment
- 1;
202 RealPages
= Pages
+ EFI_SIZE_TO_PAGES (Alignment
);
204 // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.
206 ASSERT (RealPages
> Pages
);
208 Status
= gBS
->AllocatePages (AllocateAnyPages
, MemoryType
, RealPages
, &Memory
);
209 if (EFI_ERROR (Status
)) {
212 AlignedMemory
= ((UINTN
) Memory
+ AlignmentMask
) & ~AlignmentMask
;
213 UnalignedPages
= EFI_SIZE_TO_PAGES (AlignedMemory
- (UINTN
) Memory
);
214 if (UnalignedPages
> 0) {
216 // Free first unaligned page(s).
218 Status
= gBS
->FreePages (Memory
, UnalignedPages
);
219 ASSERT_EFI_ERROR (Status
);
221 Memory
= (EFI_PHYSICAL_ADDRESS
) (AlignedMemory
+ EFI_PAGES_TO_SIZE (Pages
));
222 UnalignedPages
= RealPages
- Pages
- UnalignedPages
;
223 if (UnalignedPages
> 0) {
225 // Free last unaligned page(s).
227 Status
= gBS
->FreePages (Memory
, UnalignedPages
);
228 ASSERT_EFI_ERROR (Status
);
232 // Do not over-allocate pages in this case.
234 Status
= gBS
->AllocatePages (AllocateAnyPages
, MemoryType
, Pages
, &Memory
);
235 if (EFI_ERROR (Status
)) {
238 AlignedMemory
= (UINTN
) Memory
;
241 Status
= gDS
->GetMemorySpaceDescriptor (Memory
, &Descriptor
);
242 if (!EFI_ERROR (Status
)) {
243 // We are making an assumption that all of memory has the same default attributes
244 gAttributes
= Descriptor
.Attributes
;
247 Status
= gDebugUncachedCpu
->SetMemoryAttributes (gDebugUncachedCpu
, Memory
, EFI_PAGES_TO_SIZE (Pages
), EFI_MEMORY_UC
);
248 if (EFI_ERROR (Status
)) {
252 return (VOID
*)(UINTN
)Memory
;
258 UncachedFreeAlignedPages (
264 EFI_PHYSICAL_ADDRESS Memory
;
268 Memory
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) Buffer
;
269 Status
= gDebugUncachedCpu
->SetMemoryAttributes (gDebugUncachedCpu
, Memory
, EFI_PAGES_TO_SIZE (Pages
), gAttributes
);
271 Status
= gBS
->FreePages (Memory
, Pages
);
272 ASSERT_EFI_ERROR (Status
);
279 UncachedInternalAllocateAlignedPool (
280 IN EFI_MEMORY_TYPE PoolType
,
281 IN UINTN AllocationSize
,
285 VOID
*AlignedAddress
;
288 // Alignment must be a power of two or zero.
290 ASSERT ((Alignment
& (Alignment
- 1)) == 0);
292 if (Alignment
< EFI_PAGE_SIZE
) {
293 Alignment
= EFI_PAGE_SIZE
;
296 AlignedAddress
= UncachedInternalAllocateAlignedPages (PoolType
, EFI_SIZE_TO_PAGES (AllocationSize
), Alignment
);
297 if (AlignedAddress
== NULL
) {
301 AddPagesToList ((VOID
*)(UINTN
)AlignedAddress
, EFI_SIZE_TO_PAGES (AllocationSize
));
303 return (VOID
*) AlignedAddress
;
308 UncachedAllocateAlignedPool (
309 IN UINTN AllocationSize
,
313 return UncachedInternalAllocateAlignedPool (EfiBootServicesData
, AllocationSize
, Alignment
);
318 UncachedAllocateAlignedRuntimePool (
319 IN UINTN AllocationSize
,
323 return UncachedInternalAllocateAlignedPool (EfiRuntimeServicesData
, AllocationSize
, Alignment
);
328 UncachedAllocateAlignedReservedPool (
329 IN UINTN AllocationSize
,
333 return UncachedInternalAllocateAlignedPool (EfiReservedMemoryType
, AllocationSize
, Alignment
);
337 UncachedInternalAllocateAlignedZeroPool (
338 IN EFI_MEMORY_TYPE PoolType
,
339 IN UINTN AllocationSize
,
344 Memory
= UncachedInternalAllocateAlignedPool (PoolType
, AllocationSize
, Alignment
);
345 if (Memory
!= NULL
) {
346 Memory
= ZeroMem (Memory
, AllocationSize
);
353 UncachedAllocateAlignedZeroPool (
354 IN UINTN AllocationSize
,
358 return UncachedInternalAllocateAlignedZeroPool (EfiBootServicesData
, AllocationSize
, Alignment
);
363 UncachedAllocateAlignedRuntimeZeroPool (
364 IN UINTN AllocationSize
,
368 return UncachedInternalAllocateAlignedZeroPool (EfiRuntimeServicesData
, AllocationSize
, Alignment
);
373 UncachedAllocateAlignedReservedZeroPool (
374 IN UINTN AllocationSize
,
378 return UncachedInternalAllocateAlignedZeroPool (EfiReservedMemoryType
, AllocationSize
, Alignment
);
382 UncachedInternalAllocateAlignedCopyPool (
383 IN EFI_MEMORY_TYPE PoolType
,
384 IN UINTN AllocationSize
,
385 IN CONST VOID
*Buffer
,
391 ASSERT (Buffer
!= NULL
);
392 ASSERT (AllocationSize
<= (MAX_ADDRESS
- (UINTN
) Buffer
+ 1));
394 Memory
= UncachedInternalAllocateAlignedPool (PoolType
, AllocationSize
, Alignment
);
395 if (Memory
!= NULL
) {
396 Memory
= CopyMem (Memory
, Buffer
, AllocationSize
);
403 UncachedAllocateAlignedCopyPool (
404 IN UINTN AllocationSize
,
405 IN CONST VOID
*Buffer
,
409 return UncachedInternalAllocateAlignedCopyPool (EfiBootServicesData
, AllocationSize
, Buffer
, Alignment
);
414 UncachedAllocateAlignedRuntimeCopyPool (
415 IN UINTN AllocationSize
,
416 IN CONST VOID
*Buffer
,
420 return UncachedInternalAllocateAlignedCopyPool (EfiRuntimeServicesData
, AllocationSize
, Buffer
, Alignment
);
425 UncachedAllocateAlignedReservedCopyPool (
426 IN UINTN AllocationSize
,
427 IN CONST VOID
*Buffer
,
431 return UncachedInternalAllocateAlignedCopyPool (EfiReservedMemoryType
, AllocationSize
, Buffer
, Alignment
);
436 UncachedFreeAlignedPool (
442 RemovePagesFromList (Allocation
, &Pages
);
444 UncachedFreePages (Allocation
, Pages
);
448 UncachedInternalAllocatePool (
449 IN EFI_MEMORY_TYPE MemoryType
,
450 IN UINTN AllocationSize
453 UINTN CacheLineLength
= ArmDataCacheLineLength ();
454 return UncachedInternalAllocateAlignedPool (MemoryType
, AllocationSize
, CacheLineLength
);
459 UncachedAllocatePool (
460 IN UINTN AllocationSize
463 return UncachedInternalAllocatePool (EfiBootServicesData
, AllocationSize
);
468 UncachedAllocateRuntimePool (
469 IN UINTN AllocationSize
472 return UncachedInternalAllocatePool (EfiRuntimeServicesData
, AllocationSize
);
477 UncachedAllocateReservedPool (
478 IN UINTN AllocationSize
481 return UncachedInternalAllocatePool (EfiReservedMemoryType
, AllocationSize
);
485 UncachedInternalAllocateZeroPool (
486 IN EFI_MEMORY_TYPE PoolType
,
487 IN UINTN AllocationSize
492 Memory
= UncachedInternalAllocatePool (PoolType
, AllocationSize
);
493 if (Memory
!= NULL
) {
494 Memory
= ZeroMem (Memory
, AllocationSize
);
501 UncachedAllocateZeroPool (
502 IN UINTN AllocationSize
505 return UncachedInternalAllocateZeroPool (EfiBootServicesData
, AllocationSize
);
510 UncachedAllocateRuntimeZeroPool (
511 IN UINTN AllocationSize
514 return UncachedInternalAllocateZeroPool (EfiRuntimeServicesData
, AllocationSize
);
519 UncachedAllocateReservedZeroPool (
520 IN UINTN AllocationSize
523 return UncachedInternalAllocateZeroPool (EfiReservedMemoryType
, AllocationSize
);
527 UncachedInternalAllocateCopyPool (
528 IN EFI_MEMORY_TYPE PoolType
,
529 IN UINTN AllocationSize
,
530 IN CONST VOID
*Buffer
535 ASSERT (Buffer
!= NULL
);
536 ASSERT (AllocationSize
<= (MAX_ADDRESS
- (UINTN
) Buffer
+ 1));
538 Memory
= UncachedInternalAllocatePool (PoolType
, AllocationSize
);
539 if (Memory
!= NULL
) {
540 Memory
= CopyMem (Memory
, Buffer
, AllocationSize
);
547 UncachedAllocateCopyPool (
548 IN UINTN AllocationSize
,
549 IN CONST VOID
*Buffer
552 return UncachedInternalAllocateCopyPool (EfiBootServicesData
, AllocationSize
, Buffer
);
557 UncachedAllocateRuntimeCopyPool (
558 IN UINTN AllocationSize
,
559 IN CONST VOID
*Buffer
562 return UncachedInternalAllocateCopyPool (EfiRuntimeServicesData
, AllocationSize
, Buffer
);
567 UncachedAllocateReservedCopyPool (
568 IN UINTN AllocationSize
,
569 IN CONST VOID
*Buffer
572 return UncachedInternalAllocateCopyPool (EfiReservedMemoryType
, AllocationSize
, Buffer
);
581 UncachedFreeAlignedPool (Buffer
);
586 UncachedSafeFreePool (
590 if (Buffer
!= NULL
) {
591 UncachedFreePool (Buffer
);
597 The constructor function caches the pointer of DXE Services Table.
599 The constructor function caches the pointer of DXE Services Table.
600 It will ASSERT() if that operation fails.
601 It will ASSERT() if the pointer of DXE Services Table is NULL.
602 It will always return EFI_SUCCESS.
604 @param ImageHandle The firmware allocated handle for the EFI image.
605 @param SystemTable A pointer to the EFI System Table.
607 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
612 DebugUncachedMemoryAllocationLibConstructor (
613 IN EFI_HANDLE ImageHandle
,
614 IN EFI_SYSTEM_TABLE
*SystemTable
619 Status
= gBS
->LocateProtocol (&gEfiCpuArchProtocolGuid
, NULL
, (VOID
**)&gDebugUncachedCpu
);
620 ASSERT_EFI_ERROR(Status
);