2 UncachedMemoryAllocation lib that uses DXE Service to change 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>
29 UncachedInternalAllocatePages (
30 IN EFI_MEMORY_TYPE MemoryType
,
35 UncachedInternalAllocateAlignedPages (
36 IN EFI_MEMORY_TYPE MemoryType
,
44 // Assume all of memory has the same cache attributes, unless we do our magic
54 LIST_ENTRY mPageList
= INITIALIZE_LIST_HEAD_VARIABLE (mPageList
);
62 FREE_PAGE_NODE
*NewNode
;
64 NewNode
= AllocatePool (sizeof (LIST_ENTRY
));
65 if (NewNode
== NULL
) {
70 NewNode
->Allocation
= Allocation
;
71 NewNode
->Pages
= Pages
;
73 InsertTailList (&mPageList
, &NewNode
->Link
);
84 FREE_PAGE_NODE
*OldNode
;
88 for (Link
= mPageList
.ForwardLink
; Link
!= &mPageList
; Link
= Link
->ForwardLink
) {
89 OldNode
= BASE_CR (Link
, FREE_PAGE_NODE
, Link
);
90 if (OldNode
->Allocation
== Allocation
) {
91 *Pages
= OldNode
->Pages
;
93 RemoveEntryList (&OldNode
->Link
);
104 Converts a cached or uncached address to a physical address suitable for use in SoC registers.
106 @param VirtualAddress The pointer to convert.
108 @return The physical address of the supplied virtual pointer.
112 ConvertToPhysicalAddress (
113 IN VOID
*VirtualAddress
116 return (EFI_PHYSICAL_ADDRESS
)(UINTN
)VirtualAddress
;
121 UncachedInternalAllocatePages (
122 IN EFI_MEMORY_TYPE MemoryType
,
126 return UncachedInternalAllocateAlignedPages (MemoryType
, Pages
, EFI_PAGE_SIZE
);
132 UncachedAllocatePages (
136 return UncachedInternalAllocatePages (EfiBootServicesData
, Pages
);
141 UncachedAllocateRuntimePages (
145 return UncachedInternalAllocatePages (EfiRuntimeServicesData
, Pages
);
150 UncachedAllocateReservedPages (
154 return UncachedInternalAllocatePages (EfiReservedMemoryType
, Pages
);
166 UncachedFreeAlignedPages (Buffer
, Pages
);
172 UncachedInternalAllocateAlignedPages (
173 IN EFI_MEMORY_TYPE MemoryType
,
179 EFI_PHYSICAL_ADDRESS Memory
;
180 EFI_PHYSICAL_ADDRESS AlignedMemory
;
182 UINTN UnalignedPages
;
184 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor
;
187 // Alignment must be a power of two or zero.
189 ASSERT ((Alignment
& (Alignment
- 1)) == 0);
194 if (Alignment
> EFI_PAGE_SIZE
) {
196 // Caculate the total number of pages since alignment is larger than page size.
198 AlignmentMask
= Alignment
- 1;
199 RealPages
= Pages
+ EFI_SIZE_TO_PAGES (Alignment
);
201 // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.
203 ASSERT (RealPages
> Pages
);
205 Status
= gBS
->AllocatePages (AllocateAnyPages
, MemoryType
, RealPages
, &Memory
);
206 if (EFI_ERROR (Status
)) {
209 AlignedMemory
= ((UINTN
) Memory
+ AlignmentMask
) & ~AlignmentMask
;
210 UnalignedPages
= EFI_SIZE_TO_PAGES (AlignedMemory
- (UINTN
) Memory
);
211 if (UnalignedPages
> 0) {
213 // Free first unaligned page(s).
215 Status
= gBS
->FreePages (Memory
, UnalignedPages
);
216 ASSERT_EFI_ERROR (Status
);
218 Memory
= (EFI_PHYSICAL_ADDRESS
) (AlignedMemory
+ EFI_PAGES_TO_SIZE (Pages
));
219 UnalignedPages
= RealPages
- Pages
- UnalignedPages
;
220 if (UnalignedPages
> 0) {
222 // Free last unaligned page(s).
224 Status
= gBS
->FreePages (Memory
, UnalignedPages
);
225 ASSERT_EFI_ERROR (Status
);
229 // Do not over-allocate pages in this case.
231 Status
= gBS
->AllocatePages (AllocateAnyPages
, MemoryType
, Pages
, &Memory
);
232 if (EFI_ERROR (Status
)) {
235 AlignedMemory
= (UINTN
) Memory
;
238 Status
= gDS
->GetMemorySpaceDescriptor (Memory
, &Descriptor
);
239 if (!EFI_ERROR (Status
)) {
240 // We are making an assumption that all of memory has the same default attributes
241 gAttributes
= Descriptor
.Attributes
;
244 Status
= gDS
->SetMemorySpaceAttributes (Memory
, EFI_PAGES_TO_SIZE (Pages
), EFI_MEMORY_WC
);
245 ASSERT_EFI_ERROR (Status
);
247 return (VOID
*)(UINTN
)Memory
;
253 UncachedFreeAlignedPages (
259 EFI_PHYSICAL_ADDRESS Memory
;
263 Memory
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) Buffer
;
264 Status
= gDS
->SetMemorySpaceAttributes (Memory
, EFI_PAGES_TO_SIZE (Pages
), gAttributes
);
266 Status
= gBS
->FreePages (Memory
, Pages
);
267 ASSERT_EFI_ERROR (Status
);
274 UncachedInternalAllocateAlignedPool (
275 IN EFI_MEMORY_TYPE PoolType
,
276 IN UINTN AllocationSize
,
280 VOID
*AlignedAddress
;
283 // Alignment must be a power of two or zero.
285 ASSERT ((Alignment
& (Alignment
- 1)) == 0);
287 if (Alignment
< EFI_PAGE_SIZE
) {
288 Alignment
= EFI_PAGE_SIZE
;
291 AlignedAddress
= UncachedInternalAllocateAlignedPages (PoolType
, EFI_SIZE_TO_PAGES (AllocationSize
), Alignment
);
292 if (AlignedAddress
== NULL
) {
296 AddPagesToList ((VOID
*)(UINTN
)AlignedAddress
, EFI_SIZE_TO_PAGES (AllocationSize
));
298 return (VOID
*) AlignedAddress
;
303 UncachedAllocateAlignedPool (
304 IN UINTN AllocationSize
,
308 return UncachedInternalAllocateAlignedPool (EfiBootServicesData
, AllocationSize
, Alignment
);
313 UncachedAllocateAlignedRuntimePool (
314 IN UINTN AllocationSize
,
318 return UncachedInternalAllocateAlignedPool (EfiRuntimeServicesData
, AllocationSize
, Alignment
);
323 UncachedAllocateAlignedReservedPool (
324 IN UINTN AllocationSize
,
328 return UncachedInternalAllocateAlignedPool (EfiReservedMemoryType
, AllocationSize
, Alignment
);
332 UncachedInternalAllocateAlignedZeroPool (
333 IN EFI_MEMORY_TYPE PoolType
,
334 IN UINTN AllocationSize
,
339 Memory
= UncachedInternalAllocateAlignedPool (PoolType
, AllocationSize
, Alignment
);
340 if (Memory
!= NULL
) {
341 Memory
= ZeroMem (Memory
, AllocationSize
);
348 UncachedAllocateAlignedZeroPool (
349 IN UINTN AllocationSize
,
353 return UncachedInternalAllocateAlignedZeroPool (EfiBootServicesData
, AllocationSize
, Alignment
);
358 UncachedAllocateAlignedRuntimeZeroPool (
359 IN UINTN AllocationSize
,
363 return UncachedInternalAllocateAlignedZeroPool (EfiRuntimeServicesData
, AllocationSize
, Alignment
);
368 UncachedAllocateAlignedReservedZeroPool (
369 IN UINTN AllocationSize
,
373 return UncachedInternalAllocateAlignedZeroPool (EfiReservedMemoryType
, AllocationSize
, Alignment
);
377 UncachedInternalAllocateAlignedCopyPool (
378 IN EFI_MEMORY_TYPE PoolType
,
379 IN UINTN AllocationSize
,
380 IN CONST VOID
*Buffer
,
386 ASSERT (Buffer
!= NULL
);
387 ASSERT (AllocationSize
<= (MAX_ADDRESS
- (UINTN
) Buffer
+ 1));
389 Memory
= UncachedInternalAllocateAlignedPool (PoolType
, AllocationSize
, Alignment
);
390 if (Memory
!= NULL
) {
391 Memory
= CopyMem (Memory
, Buffer
, AllocationSize
);
398 UncachedAllocateAlignedCopyPool (
399 IN UINTN AllocationSize
,
400 IN CONST VOID
*Buffer
,
404 return UncachedInternalAllocateAlignedCopyPool (EfiBootServicesData
, AllocationSize
, Buffer
, Alignment
);
409 UncachedAllocateAlignedRuntimeCopyPool (
410 IN UINTN AllocationSize
,
411 IN CONST VOID
*Buffer
,
415 return UncachedInternalAllocateAlignedCopyPool (EfiRuntimeServicesData
, AllocationSize
, Buffer
, Alignment
);
420 UncachedAllocateAlignedReservedCopyPool (
421 IN UINTN AllocationSize
,
422 IN CONST VOID
*Buffer
,
426 return UncachedInternalAllocateAlignedCopyPool (EfiReservedMemoryType
, AllocationSize
, Buffer
, Alignment
);
431 UncachedFreeAlignedPool (
437 RemovePagesFromList (Allocation
, &Pages
);
439 UncachedFreePages (Allocation
, Pages
);
443 UncachedInternalAllocatePool (
444 IN EFI_MEMORY_TYPE MemoryType
,
445 IN UINTN AllocationSize
448 UINTN CacheLineLength
= ArmDataCacheLineLength ();
449 return UncachedInternalAllocateAlignedPool (MemoryType
, AllocationSize
, CacheLineLength
);
454 UncachedAllocatePool (
455 IN UINTN AllocationSize
458 return UncachedInternalAllocatePool (EfiBootServicesData
, AllocationSize
);
463 UncachedAllocateRuntimePool (
464 IN UINTN AllocationSize
467 return UncachedInternalAllocatePool (EfiRuntimeServicesData
, AllocationSize
);
472 UncachedAllocateReservedPool (
473 IN UINTN AllocationSize
476 return UncachedInternalAllocatePool (EfiReservedMemoryType
, AllocationSize
);
480 UncachedInternalAllocateZeroPool (
481 IN EFI_MEMORY_TYPE PoolType
,
482 IN UINTN AllocationSize
487 Memory
= UncachedInternalAllocatePool (PoolType
, AllocationSize
);
488 if (Memory
!= NULL
) {
489 Memory
= ZeroMem (Memory
, AllocationSize
);
496 UncachedAllocateZeroPool (
497 IN UINTN AllocationSize
500 return UncachedInternalAllocateZeroPool (EfiBootServicesData
, AllocationSize
);
505 UncachedAllocateRuntimeZeroPool (
506 IN UINTN AllocationSize
509 return UncachedInternalAllocateZeroPool (EfiRuntimeServicesData
, AllocationSize
);
514 UncachedAllocateReservedZeroPool (
515 IN UINTN AllocationSize
518 return UncachedInternalAllocateZeroPool (EfiReservedMemoryType
, AllocationSize
);
522 UncachedInternalAllocateCopyPool (
523 IN EFI_MEMORY_TYPE PoolType
,
524 IN UINTN AllocationSize
,
525 IN CONST VOID
*Buffer
530 ASSERT (Buffer
!= NULL
);
531 ASSERT (AllocationSize
<= (MAX_ADDRESS
- (UINTN
) Buffer
+ 1));
533 Memory
= UncachedInternalAllocatePool (PoolType
, AllocationSize
);
534 if (Memory
!= NULL
) {
535 Memory
= CopyMem (Memory
, Buffer
, AllocationSize
);
542 UncachedAllocateCopyPool (
543 IN UINTN AllocationSize
,
544 IN CONST VOID
*Buffer
547 return UncachedInternalAllocateCopyPool (EfiBootServicesData
, AllocationSize
, Buffer
);
552 UncachedAllocateRuntimeCopyPool (
553 IN UINTN AllocationSize
,
554 IN CONST VOID
*Buffer
557 return UncachedInternalAllocateCopyPool (EfiRuntimeServicesData
, AllocationSize
, Buffer
);
562 UncachedAllocateReservedCopyPool (
563 IN UINTN AllocationSize
,
564 IN CONST VOID
*Buffer
567 return UncachedInternalAllocateCopyPool (EfiReservedMemoryType
, AllocationSize
, Buffer
);
576 UncachedFreeAlignedPool (Buffer
);
581 UncachedSafeFreePool (
585 if (Buffer
!= NULL
) {
586 UncachedFreePool (Buffer
);