2 UncachedMemoryAllocation lib that uses DXE CPU driver to chnage cachability for
5 Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
7 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.
18 #include <Library/BaseLib.h>
19 #include <Library/BaseMemoryLib.h>
20 #include <Library/MemoryAllocationLib.h>
21 #include <Library/DebugLib.h>
22 #include <Library/UefiBootServicesTableLib.h>
23 #include <Library/UncachedMemoryAllocationLib.h>
24 #include <Library/PcdLib.h>
25 #include <Library/ArmLib.h>
26 #include <Library/DxeServicesTableLib.h>
28 #include <Protocol/Cpu.h>
31 UncachedInternalAllocatePages (
32 IN EFI_MEMORY_TYPE MemoryType
,
37 UncachedInternalAllocateAlignedPages (
38 IN EFI_MEMORY_TYPE MemoryType
,
45 EFI_CPU_ARCH_PROTOCOL
*gDebugUncachedCpu
;
48 // Assume all of memory has the same cache attributes, unless we do our magic
58 LIST_ENTRY mPageList
= INITIALIZE_LIST_HEAD_VARIABLE (mPageList
);
66 FREE_PAGE_NODE
*NewNode
;
68 NewNode
= AllocatePool (sizeof (LIST_ENTRY
));
69 if (NewNode
== NULL
) {
74 NewNode
->Allocation
= Allocation
;
75 NewNode
->Pages
= Pages
;
77 InsertTailList (&mPageList
, &NewNode
->Link
);
88 FREE_PAGE_NODE
*OldNode
;
92 for (Link
= mPageList
.ForwardLink
; Link
!= &mPageList
; Link
= Link
->ForwardLink
) {
93 OldNode
= BASE_CR (Link
, FREE_PAGE_NODE
, Link
);
94 if (OldNode
->Allocation
== Allocation
) {
95 *Pages
= OldNode
->Pages
;
97 RemoveEntryList (&OldNode
->Link
);
108 Converts a cached or uncached address to a physical address suitable for use in SoC registers.
110 @param VirtualAddress The pointer to convert.
112 @return The physical address of the supplied virtual pointer.
116 ConvertToPhysicalAddress (
117 IN VOID
*VirtualAddress
120 return (EFI_PHYSICAL_ADDRESS
)(UINTN
)VirtualAddress
;
125 UncachedInternalAllocatePages (
126 IN EFI_MEMORY_TYPE MemoryType
,
130 return UncachedInternalAllocateAlignedPages (MemoryType
, Pages
, EFI_PAGE_SIZE
);
136 UncachedAllocatePages (
140 return UncachedInternalAllocatePages (EfiBootServicesData
, Pages
);
145 UncachedAllocateRuntimePages (
149 return UncachedInternalAllocatePages (EfiRuntimeServicesData
, Pages
);
154 UncachedAllocateReservedPages (
158 return UncachedInternalAllocatePages (EfiReservedMemoryType
, Pages
);
170 UncachedFreeAlignedPages (Buffer
, Pages
);
176 UncachedInternalAllocateAlignedPages (
177 IN EFI_MEMORY_TYPE MemoryType
,
183 EFI_PHYSICAL_ADDRESS Memory
;
184 EFI_PHYSICAL_ADDRESS AlignedMemory
;
186 UINTN UnalignedPages
;
188 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor
;
191 // Alignment must be a power of two or zero.
193 ASSERT ((Alignment
& (Alignment
- 1)) == 0);
198 if (Alignment
> EFI_PAGE_SIZE
) {
200 // Caculate the total number of pages since alignment is larger than page size.
202 AlignmentMask
= Alignment
- 1;
203 RealPages
= Pages
+ EFI_SIZE_TO_PAGES (Alignment
);
205 // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.
207 ASSERT (RealPages
> Pages
);
209 Status
= gBS
->AllocatePages (AllocateAnyPages
, MemoryType
, RealPages
, &Memory
);
210 if (EFI_ERROR (Status
)) {
213 AlignedMemory
= ((UINTN
) Memory
+ AlignmentMask
) & ~AlignmentMask
;
214 UnalignedPages
= EFI_SIZE_TO_PAGES (AlignedMemory
- (UINTN
) Memory
);
215 if (UnalignedPages
> 0) {
217 // Free first unaligned page(s).
219 Status
= gBS
->FreePages (Memory
, UnalignedPages
);
220 ASSERT_EFI_ERROR (Status
);
222 Memory
= (EFI_PHYSICAL_ADDRESS
) (AlignedMemory
+ EFI_PAGES_TO_SIZE (Pages
));
223 UnalignedPages
= RealPages
- Pages
- UnalignedPages
;
224 if (UnalignedPages
> 0) {
226 // Free last unaligned page(s).
228 Status
= gBS
->FreePages (Memory
, UnalignedPages
);
229 ASSERT_EFI_ERROR (Status
);
233 // Do not over-allocate pages in this case.
235 Status
= gBS
->AllocatePages (AllocateAnyPages
, MemoryType
, Pages
, &Memory
);
236 if (EFI_ERROR (Status
)) {
239 AlignedMemory
= (UINTN
) Memory
;
242 Status
= gDS
->GetMemorySpaceDescriptor (Memory
, &Descriptor
);
243 if (!EFI_ERROR (Status
)) {
244 // We are making an assumption that all of memory has the same default attributes
245 gAttributes
= Descriptor
.Attributes
;
248 Status
= gDS
->SetMemorySpaceAttributes (Memory
, EFI_PAGES_TO_SIZE (Pages
), EFI_MEMORY_WC
);
249 ASSERT_EFI_ERROR (Status
);
251 return (VOID
*)(UINTN
)Memory
;
257 UncachedFreeAlignedPages (
263 EFI_PHYSICAL_ADDRESS Memory
;
267 Memory
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) Buffer
;
268 Status
= gDebugUncachedCpu
->SetMemoryAttributes (gDebugUncachedCpu
, Memory
, EFI_PAGES_TO_SIZE (Pages
), gAttributes
);
270 Status
= gBS
->FreePages (Memory
, Pages
);
271 ASSERT_EFI_ERROR (Status
);
278 UncachedInternalAllocateAlignedPool (
279 IN EFI_MEMORY_TYPE PoolType
,
280 IN UINTN AllocationSize
,
284 VOID
*AlignedAddress
;
287 // Alignment must be a power of two or zero.
289 ASSERT ((Alignment
& (Alignment
- 1)) == 0);
291 if (Alignment
< EFI_PAGE_SIZE
) {
292 Alignment
= EFI_PAGE_SIZE
;
295 AlignedAddress
= UncachedInternalAllocateAlignedPages (PoolType
, EFI_SIZE_TO_PAGES (AllocationSize
), Alignment
);
296 if (AlignedAddress
== NULL
) {
300 AddPagesToList ((VOID
*)(UINTN
)AlignedAddress
, EFI_SIZE_TO_PAGES (AllocationSize
));
302 return (VOID
*) AlignedAddress
;
307 UncachedAllocateAlignedPool (
308 IN UINTN AllocationSize
,
312 return UncachedInternalAllocateAlignedPool (EfiBootServicesData
, AllocationSize
, Alignment
);
317 UncachedAllocateAlignedRuntimePool (
318 IN UINTN AllocationSize
,
322 return UncachedInternalAllocateAlignedPool (EfiRuntimeServicesData
, AllocationSize
, Alignment
);
327 UncachedAllocateAlignedReservedPool (
328 IN UINTN AllocationSize
,
332 return UncachedInternalAllocateAlignedPool (EfiReservedMemoryType
, AllocationSize
, Alignment
);
336 UncachedInternalAllocateAlignedZeroPool (
337 IN EFI_MEMORY_TYPE PoolType
,
338 IN UINTN AllocationSize
,
343 Memory
= UncachedInternalAllocateAlignedPool (PoolType
, AllocationSize
, Alignment
);
344 if (Memory
!= NULL
) {
345 Memory
= ZeroMem (Memory
, AllocationSize
);
352 UncachedAllocateAlignedZeroPool (
353 IN UINTN AllocationSize
,
357 return UncachedInternalAllocateAlignedZeroPool (EfiBootServicesData
, AllocationSize
, Alignment
);
362 UncachedAllocateAlignedRuntimeZeroPool (
363 IN UINTN AllocationSize
,
367 return UncachedInternalAllocateAlignedZeroPool (EfiRuntimeServicesData
, AllocationSize
, Alignment
);
372 UncachedAllocateAlignedReservedZeroPool (
373 IN UINTN AllocationSize
,
377 return UncachedInternalAllocateAlignedZeroPool (EfiReservedMemoryType
, AllocationSize
, Alignment
);
381 UncachedInternalAllocateAlignedCopyPool (
382 IN EFI_MEMORY_TYPE PoolType
,
383 IN UINTN AllocationSize
,
384 IN CONST VOID
*Buffer
,
390 ASSERT (Buffer
!= NULL
);
391 ASSERT (AllocationSize
<= (MAX_ADDRESS
- (UINTN
) Buffer
+ 1));
393 Memory
= UncachedInternalAllocateAlignedPool (PoolType
, AllocationSize
, Alignment
);
394 if (Memory
!= NULL
) {
395 Memory
= CopyMem (Memory
, Buffer
, AllocationSize
);
402 UncachedAllocateAlignedCopyPool (
403 IN UINTN AllocationSize
,
404 IN CONST VOID
*Buffer
,
408 return UncachedInternalAllocateAlignedCopyPool (EfiBootServicesData
, AllocationSize
, Buffer
, Alignment
);
413 UncachedAllocateAlignedRuntimeCopyPool (
414 IN UINTN AllocationSize
,
415 IN CONST VOID
*Buffer
,
419 return UncachedInternalAllocateAlignedCopyPool (EfiRuntimeServicesData
, AllocationSize
, Buffer
, Alignment
);
424 UncachedAllocateAlignedReservedCopyPool (
425 IN UINTN AllocationSize
,
426 IN CONST VOID
*Buffer
,
430 return UncachedInternalAllocateAlignedCopyPool (EfiReservedMemoryType
, AllocationSize
, Buffer
, Alignment
);
435 UncachedFreeAlignedPool (
441 RemovePagesFromList (Allocation
, &Pages
);
443 UncachedFreePages (Allocation
, Pages
);
447 UncachedInternalAllocatePool (
448 IN EFI_MEMORY_TYPE MemoryType
,
449 IN UINTN AllocationSize
452 UINTN CacheLineLength
= ArmDataCacheLineLength ();
453 return UncachedInternalAllocateAlignedPool (MemoryType
, AllocationSize
, CacheLineLength
);
458 UncachedAllocatePool (
459 IN UINTN AllocationSize
462 return UncachedInternalAllocatePool (EfiBootServicesData
, AllocationSize
);
467 UncachedAllocateRuntimePool (
468 IN UINTN AllocationSize
471 return UncachedInternalAllocatePool (EfiRuntimeServicesData
, AllocationSize
);
476 UncachedAllocateReservedPool (
477 IN UINTN AllocationSize
480 return UncachedInternalAllocatePool (EfiReservedMemoryType
, AllocationSize
);
484 UncachedInternalAllocateZeroPool (
485 IN EFI_MEMORY_TYPE PoolType
,
486 IN UINTN AllocationSize
491 Memory
= UncachedInternalAllocatePool (PoolType
, AllocationSize
);
492 if (Memory
!= NULL
) {
493 Memory
= ZeroMem (Memory
, AllocationSize
);
500 UncachedAllocateZeroPool (
501 IN UINTN AllocationSize
504 return UncachedInternalAllocateZeroPool (EfiBootServicesData
, AllocationSize
);
509 UncachedAllocateRuntimeZeroPool (
510 IN UINTN AllocationSize
513 return UncachedInternalAllocateZeroPool (EfiRuntimeServicesData
, AllocationSize
);
518 UncachedAllocateReservedZeroPool (
519 IN UINTN AllocationSize
522 return UncachedInternalAllocateZeroPool (EfiReservedMemoryType
, AllocationSize
);
526 UncachedInternalAllocateCopyPool (
527 IN EFI_MEMORY_TYPE PoolType
,
528 IN UINTN AllocationSize
,
529 IN CONST VOID
*Buffer
534 ASSERT (Buffer
!= NULL
);
535 ASSERT (AllocationSize
<= (MAX_ADDRESS
- (UINTN
) Buffer
+ 1));
537 Memory
= UncachedInternalAllocatePool (PoolType
, AllocationSize
);
538 if (Memory
!= NULL
) {
539 Memory
= CopyMem (Memory
, Buffer
, AllocationSize
);
546 UncachedAllocateCopyPool (
547 IN UINTN AllocationSize
,
548 IN CONST VOID
*Buffer
551 return UncachedInternalAllocateCopyPool (EfiBootServicesData
, AllocationSize
, Buffer
);
556 UncachedAllocateRuntimeCopyPool (
557 IN UINTN AllocationSize
,
558 IN CONST VOID
*Buffer
561 return UncachedInternalAllocateCopyPool (EfiRuntimeServicesData
, AllocationSize
, Buffer
);
566 UncachedAllocateReservedCopyPool (
567 IN UINTN AllocationSize
,
568 IN CONST VOID
*Buffer
571 return UncachedInternalAllocateCopyPool (EfiReservedMemoryType
, AllocationSize
, Buffer
);
580 UncachedFreeAlignedPool (Buffer
);
585 UncachedSafeFreePool (
589 if (Buffer
!= NULL
) {
590 UncachedFreePool (Buffer
);
596 The constructor function caches the pointer of DXE Services Table.
598 The constructor function caches the pointer of DXE Services Table.
599 It will ASSERT() if that operation fails.
600 It will ASSERT() if the pointer of DXE Services Table is NULL.
601 It will always return EFI_SUCCESS.
603 @param ImageHandle The firmware allocated handle for the EFI image.
604 @param SystemTable A pointer to the EFI System Table.
606 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
611 UncachedMemoryAllocationLibConstructor (
612 IN EFI_HANDLE ImageHandle
,
613 IN EFI_SYSTEM_TABLE
*SystemTable
618 Status
= gBS
->LocateProtocol (&gEfiCpuArchProtocolGuid
, NULL
, (VOID
**)&gDebugUncachedCpu
);
619 ASSERT_EFI_ERROR(Status
);