]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.c
ARM Packages: Removed trailing spaces
[mirror_edk2.git] / ArmPkg / Library / UncachedMemoryAllocationLib / UncachedMemoryAllocationLib.c
CommitLineData
2ef2b01e 1/** @file\r
a7463b30 2 UncachedMemoryAllocation lib that uses DXE Service to change cachability for\r
883b666e 3 a buffer.\r
2ef2b01e 4\r
d6ebcab7 5 Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>\r
3402aac7 6\r
d6ebcab7 7 This program and the accompanying materials\r
2ef2b01e
A
8 are licensed and made available under the terms and conditions of the BSD License\r
9 which accompanies this distribution. The full text of the license may be found at\r
10 http://opensource.org/licenses/bsd-license.php\r
11\r
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15**/\r
16\r
44c01161 17#include <Base.h>\r
883b666e 18#include <Library/BaseLib.h>\r
2ef2b01e 19#include <Library/BaseMemoryLib.h>\r
883b666e 20#include <Library/MemoryAllocationLib.h>\r
2ef2b01e
A
21#include <Library/DebugLib.h>\r
22#include <Library/UefiBootServicesTableLib.h>\r
23#include <Library/UncachedMemoryAllocationLib.h>\r
24#include <Library/PcdLib.h>\r
25#include <Library/ArmLib.h>\r
883b666e 26#include <Library/DxeServicesTableLib.h>\r
27\r
883b666e 28VOID *\r
29UncachedInternalAllocatePages (\r
3402aac7 30 IN EFI_MEMORY_TYPE MemoryType,\r
883b666e 31 IN UINTN Pages\r
32 );\r
33\r
34VOID *\r
35UncachedInternalAllocateAlignedPages (\r
3402aac7 36 IN EFI_MEMORY_TYPE MemoryType,\r
883b666e 37 IN UINTN Pages,\r
38 IN UINTN Alignment\r
39 );\r
3402aac7
RC
40\r
41\r
2ef2b01e 42\r
883b666e 43//\r
44// Assume all of memory has the same cache attributes, unless we do our magic\r
45//\r
46UINT64 gAttributes;\r
47\r
48typedef struct {\r
49 VOID *Allocation;\r
50 UINTN Pages;\r
51 LIST_ENTRY Link;\r
52} FREE_PAGE_NODE;\r
53\r
54LIST_ENTRY mPageList = INITIALIZE_LIST_HEAD_VARIABLE (mPageList);\r
55\r
56VOID\r
57AddPagesToList (\r
58 IN VOID *Allocation,\r
59 UINTN Pages\r
2ef2b01e
A
60 )\r
61{\r
883b666e 62 FREE_PAGE_NODE *NewNode;\r
3402aac7 63\r
883b666e 64 NewNode = AllocatePool (sizeof (LIST_ENTRY));\r
65 if (NewNode == NULL) {\r
66 ASSERT (FALSE);\r
67 return;\r
68 }\r
3402aac7 69\r
883b666e 70 NewNode->Allocation = Allocation;\r
71 NewNode->Pages = Pages;\r
3402aac7 72\r
883b666e 73 InsertTailList (&mPageList, &NewNode->Link);\r
2ef2b01e
A
74}\r
75\r
883b666e 76\r
2ef2b01e 77VOID\r
883b666e 78RemovePagesFromList (\r
79 OUT VOID *Allocation,\r
80 OUT UINTN *Pages\r
2ef2b01e
A
81 )\r
82{\r
883b666e 83 LIST_ENTRY *Link;\r
84 FREE_PAGE_NODE *OldNode;\r
85\r
86 *Pages = 0;\r
3402aac7 87\r
883b666e 88 for (Link = mPageList.ForwardLink; Link != &mPageList; Link = Link->ForwardLink) {\r
89 OldNode = BASE_CR (Link, FREE_PAGE_NODE, Link);\r
90 if (OldNode->Allocation == Allocation) {\r
91 *Pages = OldNode->Pages;\r
3402aac7 92\r
883b666e 93 RemoveEntryList (&OldNode->Link);\r
94 FreePool (OldNode);\r
95 return;\r
96 }\r
97 }\r
98\r
99 return;\r
2ef2b01e
A
100}\r
101\r
883b666e 102\r
103/**\r
104 Converts a cached or uncached address to a physical address suitable for use in SoC registers.\r
105\r
106 @param VirtualAddress The pointer to convert.\r
107\r
108 @return The physical address of the supplied virtual pointer.\r
109\r
110**/\r
111EFI_PHYSICAL_ADDRESS\r
112ConvertToPhysicalAddress (\r
113 IN VOID *VirtualAddress\r
114 )\r
115{\r
116 return (EFI_PHYSICAL_ADDRESS)(UINTN)VirtualAddress;\r
117}\r
118\r
119\r
2ef2b01e
A
120VOID *\r
121UncachedInternalAllocatePages (\r
3402aac7 122 IN EFI_MEMORY_TYPE MemoryType,\r
2ef2b01e
A
123 IN UINTN Pages\r
124 )\r
125{\r
883b666e 126 return UncachedInternalAllocateAlignedPages (MemoryType, Pages, EFI_PAGE_SIZE);\r
2ef2b01e
A
127}\r
128\r
883b666e 129\r
2ef2b01e
A
130VOID *\r
131EFIAPI\r
132UncachedAllocatePages (\r
133 IN UINTN Pages\r
134 )\r
135{\r
136 return UncachedInternalAllocatePages (EfiBootServicesData, Pages);\r
137}\r
138\r
139VOID *\r
140EFIAPI\r
141UncachedAllocateRuntimePages (\r
142 IN UINTN Pages\r
143 )\r
144{\r
145 return UncachedInternalAllocatePages (EfiRuntimeServicesData, Pages);\r
146}\r
147\r
148VOID *\r
149EFIAPI\r
150UncachedAllocateReservedPages (\r
151 IN UINTN Pages\r
152 )\r
153{\r
154 return UncachedInternalAllocatePages (EfiReservedMemoryType, Pages);\r
155}\r
156\r
883b666e 157\r
158\r
2ef2b01e
A
159VOID\r
160EFIAPI\r
161UncachedFreePages (\r
162 IN VOID *Buffer,\r
163 IN UINTN Pages\r
164 )\r
165{\r
883b666e 166 UncachedFreeAlignedPages (Buffer, Pages);\r
167 return;\r
2ef2b01e
A
168}\r
169\r
883b666e 170\r
2ef2b01e
A
171VOID *\r
172UncachedInternalAllocateAlignedPages (\r
3402aac7 173 IN EFI_MEMORY_TYPE MemoryType,\r
2ef2b01e
A
174 IN UINTN Pages,\r
175 IN UINTN Alignment\r
176 )\r
177{\r
883b666e 178 EFI_STATUS Status;\r
179 EFI_PHYSICAL_ADDRESS Memory;\r
180 EFI_PHYSICAL_ADDRESS AlignedMemory;\r
181 UINTN AlignmentMask;\r
182 UINTN UnalignedPages;\r
183 UINTN RealPages;\r
184 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;\r
2ef2b01e
A
185\r
186 //\r
187 // Alignment must be a power of two or zero.\r
188 //\r
189 ASSERT ((Alignment & (Alignment - 1)) == 0);\r
3402aac7 190\r
2ef2b01e
A
191 if (Pages == 0) {\r
192 return NULL;\r
193 }\r
194 if (Alignment > EFI_PAGE_SIZE) {\r
195 //\r
196 // Caculate the total number of pages since alignment is larger than page size.\r
197 //\r
198 AlignmentMask = Alignment - 1;\r
199 RealPages = Pages + EFI_SIZE_TO_PAGES (Alignment);\r
200 //\r
201 // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.\r
202 //\r
203 ASSERT (RealPages > Pages);\r
3402aac7 204\r
2ef2b01e
A
205 Status = gBS->AllocatePages (AllocateAnyPages, MemoryType, RealPages, &Memory);\r
206 if (EFI_ERROR (Status)) {\r
207 return NULL;\r
208 }\r
209 AlignedMemory = ((UINTN) Memory + AlignmentMask) & ~AlignmentMask;\r
210 UnalignedPages = EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN) Memory);\r
211 if (UnalignedPages > 0) {\r
212 //\r
213 // Free first unaligned page(s).\r
214 //\r
215 Status = gBS->FreePages (Memory, UnalignedPages);\r
216 ASSERT_EFI_ERROR (Status);\r
217 }\r
218 Memory = (EFI_PHYSICAL_ADDRESS) (AlignedMemory + EFI_PAGES_TO_SIZE (Pages));\r
219 UnalignedPages = RealPages - Pages - UnalignedPages;\r
220 if (UnalignedPages > 0) {\r
221 //\r
222 // Free last unaligned page(s).\r
223 //\r
224 Status = gBS->FreePages (Memory, UnalignedPages);\r
225 ASSERT_EFI_ERROR (Status);\r
226 }\r
227 } else {\r
228 //\r
229 // Do not over-allocate pages in this case.\r
230 //\r
231 Status = gBS->AllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory);\r
232 if (EFI_ERROR (Status)) {\r
233 return NULL;\r
234 }\r
235 AlignedMemory = (UINTN) Memory;\r
236 }\r
3402aac7 237\r
883b666e 238 Status = gDS->GetMemorySpaceDescriptor (Memory, &Descriptor);\r
239 if (!EFI_ERROR (Status)) {\r
240 // We are making an assumption that all of memory has the same default attributes\r
241 gAttributes = Descriptor.Attributes;\r
2ef2b01e 242 }\r
3402aac7 243\r
3f5aa193 244 Status = gDS->SetMemorySpaceAttributes (Memory, EFI_PAGES_TO_SIZE (Pages), EFI_MEMORY_WC);\r
44c01161 245 ASSERT_EFI_ERROR (Status);\r
3402aac7 246\r
883b666e 247 return (VOID *)(UINTN)Memory;\r
2ef2b01e
A
248}\r
249\r
2ef2b01e
A
250\r
251VOID\r
252EFIAPI\r
253UncachedFreeAlignedPages (\r
254 IN VOID *Buffer,\r
255 IN UINTN Pages\r
256 )\r
257{\r
883b666e 258 EFI_STATUS Status;\r
3402aac7 259 EFI_PHYSICAL_ADDRESS Memory;\r
2ef2b01e
A
260\r
261 ASSERT (Pages != 0);\r
3402aac7 262\r
883b666e 263 Memory = (EFI_PHYSICAL_ADDRESS) (UINTN) Buffer;\r
a7463b30 264 Status = gDS->SetMemorySpaceAttributes (Memory, EFI_PAGES_TO_SIZE (Pages), gAttributes);\r
3402aac7 265\r
883b666e 266 Status = gBS->FreePages (Memory, Pages);\r
2ef2b01e
A
267 ASSERT_EFI_ERROR (Status);\r
268}\r
269\r
883b666e 270\r
271\r
272\r
2ef2b01e
A
273VOID *\r
274UncachedInternalAllocateAlignedPool (\r
275 IN EFI_MEMORY_TYPE PoolType,\r
276 IN UINTN AllocationSize,\r
277 IN UINTN Alignment\r
278 )\r
279{\r
883b666e 280 VOID *AlignedAddress;\r
3402aac7 281\r
2ef2b01e
A
282 //\r
283 // Alignment must be a power of two or zero.\r
284 //\r
285 ASSERT ((Alignment & (Alignment - 1)) == 0);\r
286\r
883b666e 287 if (Alignment < EFI_PAGE_SIZE) {\r
288 Alignment = EFI_PAGE_SIZE;\r
2ef2b01e 289 }\r
3402aac7 290\r
883b666e 291 AlignedAddress = UncachedInternalAllocateAlignedPages (PoolType, EFI_SIZE_TO_PAGES (AllocationSize), Alignment);\r
292 if (AlignedAddress == NULL) {\r
2ef2b01e
A
293 return NULL;\r
294 }\r
295\r
883b666e 296 AddPagesToList ((VOID *)(UINTN)AlignedAddress, EFI_SIZE_TO_PAGES (AllocationSize));\r
2ef2b01e
A
297\r
298 return (VOID *) AlignedAddress;\r
299}\r
300\r
301VOID *\r
302EFIAPI\r
303UncachedAllocateAlignedPool (\r
304 IN UINTN AllocationSize,\r
305 IN UINTN Alignment\r
306 )\r
307{\r
308 return UncachedInternalAllocateAlignedPool (EfiBootServicesData, AllocationSize, Alignment);\r
309}\r
310\r
311VOID *\r
312EFIAPI\r
313UncachedAllocateAlignedRuntimePool (\r
314 IN UINTN AllocationSize,\r
315 IN UINTN Alignment\r
316 )\r
317{\r
318 return UncachedInternalAllocateAlignedPool (EfiRuntimeServicesData, AllocationSize, Alignment);\r
319}\r
320\r
321VOID *\r
322EFIAPI\r
323UncachedAllocateAlignedReservedPool (\r
324 IN UINTN AllocationSize,\r
325 IN UINTN Alignment\r
326 )\r
327{\r
328 return UncachedInternalAllocateAlignedPool (EfiReservedMemoryType, AllocationSize, Alignment);\r
329}\r
330\r
331VOID *\r
332UncachedInternalAllocateAlignedZeroPool (\r
333 IN EFI_MEMORY_TYPE PoolType,\r
334 IN UINTN AllocationSize,\r
335 IN UINTN Alignment\r
336 )\r
337{\r
338 VOID *Memory;\r
339 Memory = UncachedInternalAllocateAlignedPool (PoolType, AllocationSize, Alignment);\r
340 if (Memory != NULL) {\r
341 Memory = ZeroMem (Memory, AllocationSize);\r
342 }\r
343 return Memory;\r
344}\r
345\r
346VOID *\r
347EFIAPI\r
348UncachedAllocateAlignedZeroPool (\r
349 IN UINTN AllocationSize,\r
350 IN UINTN Alignment\r
351 )\r
352{\r
353 return UncachedInternalAllocateAlignedZeroPool (EfiBootServicesData, AllocationSize, Alignment);\r
354}\r
355\r
356VOID *\r
357EFIAPI\r
358UncachedAllocateAlignedRuntimeZeroPool (\r
359 IN UINTN AllocationSize,\r
360 IN UINTN Alignment\r
361 )\r
362{\r
363 return UncachedInternalAllocateAlignedZeroPool (EfiRuntimeServicesData, AllocationSize, Alignment);\r
364}\r
365\r
366VOID *\r
367EFIAPI\r
368UncachedAllocateAlignedReservedZeroPool (\r
369 IN UINTN AllocationSize,\r
370 IN UINTN Alignment\r
371 )\r
372{\r
373 return UncachedInternalAllocateAlignedZeroPool (EfiReservedMemoryType, AllocationSize, Alignment);\r
374}\r
375\r
376VOID *\r
377UncachedInternalAllocateAlignedCopyPool (\r
378 IN EFI_MEMORY_TYPE PoolType,\r
379 IN UINTN AllocationSize,\r
380 IN CONST VOID *Buffer,\r
381 IN UINTN Alignment\r
382 )\r
383{\r
384 VOID *Memory;\r
3402aac7 385\r
2ef2b01e
A
386 ASSERT (Buffer != NULL);\r
387 ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN) Buffer + 1));\r
388\r
389 Memory = UncachedInternalAllocateAlignedPool (PoolType, AllocationSize, Alignment);\r
390 if (Memory != NULL) {\r
391 Memory = CopyMem (Memory, Buffer, AllocationSize);\r
392 }\r
393 return Memory;\r
394}\r
395\r
396VOID *\r
397EFIAPI\r
398UncachedAllocateAlignedCopyPool (\r
399 IN UINTN AllocationSize,\r
400 IN CONST VOID *Buffer,\r
401 IN UINTN Alignment\r
402 )\r
403{\r
404 return UncachedInternalAllocateAlignedCopyPool (EfiBootServicesData, AllocationSize, Buffer, Alignment);\r
405}\r
406\r
407VOID *\r
408EFIAPI\r
409UncachedAllocateAlignedRuntimeCopyPool (\r
410 IN UINTN AllocationSize,\r
411 IN CONST VOID *Buffer,\r
412 IN UINTN Alignment\r
413 )\r
414{\r
415 return UncachedInternalAllocateAlignedCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer, Alignment);\r
416}\r
417\r
418VOID *\r
419EFIAPI\r
420UncachedAllocateAlignedReservedCopyPool (\r
421 IN UINTN AllocationSize,\r
422 IN CONST VOID *Buffer,\r
423 IN UINTN Alignment\r
424 )\r
425{\r
426 return UncachedInternalAllocateAlignedCopyPool (EfiReservedMemoryType, AllocationSize, Buffer, Alignment);\r
427}\r
428\r
429VOID\r
430EFIAPI\r
431UncachedFreeAlignedPool (\r
883b666e 432 IN VOID *Allocation\r
2ef2b01e
A
433 )\r
434{\r
883b666e 435 UINTN Pages;\r
3402aac7 436\r
883b666e 437 RemovePagesFromList (Allocation, &Pages);\r
2ef2b01e 438\r
883b666e 439 UncachedFreePages (Allocation, Pages);\r
2ef2b01e
A
440}\r
441\r
442VOID *\r
443UncachedInternalAllocatePool (\r
3402aac7 444 IN EFI_MEMORY_TYPE MemoryType,\r
2ef2b01e
A
445 IN UINTN AllocationSize\r
446 )\r
447{\r
883b666e 448 UINTN CacheLineLength = ArmDataCacheLineLength ();\r
449 return UncachedInternalAllocateAlignedPool (MemoryType, AllocationSize, CacheLineLength);\r
2ef2b01e
A
450}\r
451\r
452VOID *\r
453EFIAPI\r
454UncachedAllocatePool (\r
455 IN UINTN AllocationSize\r
456 )\r
457{\r
458 return UncachedInternalAllocatePool (EfiBootServicesData, AllocationSize);\r
459}\r
460\r
461VOID *\r
462EFIAPI\r
463UncachedAllocateRuntimePool (\r
464 IN UINTN AllocationSize\r
465 )\r
466{\r
467 return UncachedInternalAllocatePool (EfiRuntimeServicesData, AllocationSize);\r
468}\r
469\r
470VOID *\r
471EFIAPI\r
472UncachedAllocateReservedPool (\r
473 IN UINTN AllocationSize\r
474 )\r
475{\r
476 return UncachedInternalAllocatePool (EfiReservedMemoryType, AllocationSize);\r
477}\r
478\r
479VOID *\r
480UncachedInternalAllocateZeroPool (\r
3402aac7 481 IN EFI_MEMORY_TYPE PoolType,\r
2ef2b01e 482 IN UINTN AllocationSize\r
3402aac7 483 )\r
2ef2b01e
A
484{\r
485 VOID *Memory;\r
486\r
487 Memory = UncachedInternalAllocatePool (PoolType, AllocationSize);\r
488 if (Memory != NULL) {\r
489 Memory = ZeroMem (Memory, AllocationSize);\r
490 }\r
491 return Memory;\r
492}\r
493\r
494VOID *\r
495EFIAPI\r
496UncachedAllocateZeroPool (\r
497 IN UINTN AllocationSize\r
498 )\r
499{\r
500 return UncachedInternalAllocateZeroPool (EfiBootServicesData, AllocationSize);\r
501}\r
502\r
503VOID *\r
504EFIAPI\r
505UncachedAllocateRuntimeZeroPool (\r
506 IN UINTN AllocationSize\r
507 )\r
508{\r
509 return UncachedInternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize);\r
510}\r
511\r
512VOID *\r
513EFIAPI\r
514UncachedAllocateReservedZeroPool (\r
515 IN UINTN AllocationSize\r
516 )\r
517{\r
518 return UncachedInternalAllocateZeroPool (EfiReservedMemoryType, AllocationSize);\r
519}\r
520\r
521VOID *\r
522UncachedInternalAllocateCopyPool (\r
3402aac7 523 IN EFI_MEMORY_TYPE PoolType,\r
2ef2b01e
A
524 IN UINTN AllocationSize,\r
525 IN CONST VOID *Buffer\r
3402aac7 526 )\r
2ef2b01e
A
527{\r
528 VOID *Memory;\r
529\r
530 ASSERT (Buffer != NULL);\r
531 ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN) Buffer + 1));\r
532\r
533 Memory = UncachedInternalAllocatePool (PoolType, AllocationSize);\r
534 if (Memory != NULL) {\r
535 Memory = CopyMem (Memory, Buffer, AllocationSize);\r
536 }\r
537 return Memory;\r
3402aac7 538}\r
2ef2b01e
A
539\r
540VOID *\r
541EFIAPI\r
542UncachedAllocateCopyPool (\r
543 IN UINTN AllocationSize,\r
544 IN CONST VOID *Buffer\r
545 )\r
546{\r
547 return UncachedInternalAllocateCopyPool (EfiBootServicesData, AllocationSize, Buffer);\r
548}\r
549\r
550VOID *\r
551EFIAPI\r
552UncachedAllocateRuntimeCopyPool (\r
553 IN UINTN AllocationSize,\r
554 IN CONST VOID *Buffer\r
555 )\r
556{\r
557 return UncachedInternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer);\r
558}\r
559\r
560VOID *\r
561EFIAPI\r
562UncachedAllocateReservedCopyPool (\r
563 IN UINTN AllocationSize,\r
564 IN CONST VOID *Buffer\r
565 )\r
566{\r
567 return UncachedInternalAllocateCopyPool (EfiReservedMemoryType, AllocationSize, Buffer);\r
568}\r
569\r
570VOID\r
571EFIAPI\r
572UncachedFreePool (\r
573 IN VOID *Buffer\r
574 )\r
575{\r
883b666e 576 UncachedFreeAlignedPool (Buffer);\r
2ef2b01e
A
577}\r
578\r
579VOID\r
580EFIAPI\r
581UncachedSafeFreePool (\r
582 IN VOID *Buffer\r
583 )\r
584{\r
585 if (Buffer != NULL) {\r
586 UncachedFreePool (Buffer);\r
587 Buffer = NULL;\r
588 }\r
589}\r
590\r