]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.c
ArmPkg/UncachedMemoryAllocationLib: set XP bit via CPU arch protocol
[mirror_edk2.git] / ArmPkg / Library / UncachedMemoryAllocationLib / UncachedMemoryAllocationLib.c
... / ...
CommitLineData
1/** @file\r
2 UncachedMemoryAllocation lib that uses DXE Service to change cachability for\r
3 a buffer.\r
4\r
5 Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>\r
6 Copyright (c) 2014, AMR Ltd. All rights reserved.<BR>\r
7\r
8 This program and the accompanying materials\r
9 are licensed and made available under the terms and conditions of the BSD License\r
10 which accompanies this distribution. The full text of the license may be found at\r
11 http://opensource.org/licenses/bsd-license.php\r
12\r
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
15\r
16**/\r
17\r
18#include <Base.h>\r
19#include <Library/BaseLib.h>\r
20#include <Library/BaseMemoryLib.h>\r
21#include <Library/MemoryAllocationLib.h>\r
22#include <Library/DebugLib.h>\r
23#include <Library/UefiBootServicesTableLib.h>\r
24#include <Library/UncachedMemoryAllocationLib.h>\r
25#include <Library/PcdLib.h>\r
26#include <Library/ArmLib.h>\r
27#include <Library/DxeServicesTableLib.h>\r
28#include <Library/CacheMaintenanceLib.h>\r
29\r
30#include <Protocol/Cpu.h>\r
31\r
32STATIC EFI_CPU_ARCH_PROTOCOL *mCpu;\r
33\r
34VOID *\r
35UncachedInternalAllocatePages (\r
36 IN EFI_MEMORY_TYPE MemoryType,\r
37 IN UINTN Pages\r
38 );\r
39\r
40VOID *\r
41UncachedInternalAllocateAlignedPages (\r
42 IN EFI_MEMORY_TYPE MemoryType,\r
43 IN UINTN Pages,\r
44 IN UINTN Alignment\r
45 );\r
46\r
47\r
48\r
49typedef struct {\r
50 EFI_PHYSICAL_ADDRESS Base;\r
51 VOID *Allocation;\r
52 UINTN Pages;\r
53 EFI_MEMORY_TYPE MemoryType;\r
54 BOOLEAN Allocated;\r
55 LIST_ENTRY Link;\r
56 UINT64 Attributes;\r
57} FREE_PAGE_NODE;\r
58\r
59STATIC LIST_ENTRY mPageList = INITIALIZE_LIST_HEAD_VARIABLE (mPageList);\r
60// Track the size of the non-allocated buffer in the linked-list\r
61STATIC UINTN mFreedBufferSize = 0;\r
62\r
63/**\r
64 * This function firstly checks if the requested allocation can fit into one\r
65 * of the previously allocated buffer.\r
66 * If the requested allocation does not fit in the existing pool then\r
67 * the function makes a new allocation.\r
68 *\r
69 * @param MemoryType Type of memory requested for the new allocation\r
70 * @param Pages Number of requested page\r
71 * @param Alignment Required alignment\r
72 * @param Allocation Address of the newly allocated buffer\r
73 *\r
74 * @return EFI_SUCCESS If the function manage to allocate a buffer\r
75 * @return !EFI_SUCCESS If the function did not manage to allocate a buffer\r
76 */\r
77STATIC\r
78EFI_STATUS\r
79AllocatePagesFromList (\r
80 IN EFI_MEMORY_TYPE MemoryType,\r
81 IN UINTN Pages,\r
82 IN UINTN Alignment,\r
83 OUT VOID **Allocation\r
84 )\r
85{\r
86 EFI_STATUS Status;\r
87 LIST_ENTRY *Link;\r
88 FREE_PAGE_NODE *Node;\r
89 FREE_PAGE_NODE *NewNode;\r
90 UINTN AlignmentMask;\r
91 EFI_PHYSICAL_ADDRESS Memory;\r
92 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;\r
93\r
94 // Alignment must be a power of two or zero.\r
95 ASSERT ((Alignment & (Alignment - 1)) == 0);\r
96\r
97 //\r
98 // Look in our list for the smallest page that could satisfy the new allocation\r
99 //\r
100 Node = NULL;\r
101 NewNode = NULL;\r
102 for (Link = mPageList.ForwardLink; Link != &mPageList; Link = Link->ForwardLink) {\r
103 Node = BASE_CR (Link, FREE_PAGE_NODE, Link);\r
104 if ((Node->Allocated == FALSE) && (Node->MemoryType == MemoryType)) {\r
105 // We have a node that fits our requirements\r
106 if (((UINTN)Node->Base & (Alignment - 1)) == 0) {\r
107 // We found a page that matches the page size\r
108 if (Node->Pages == Pages) {\r
109 Node->Allocated = TRUE;\r
110 Node->Allocation = (VOID*)(UINTN)Node->Base;\r
111 *Allocation = Node->Allocation;\r
112\r
113 // Update the size of the freed buffer\r
114 mFreedBufferSize -= Pages * EFI_PAGE_SIZE;\r
115 return EFI_SUCCESS;\r
116 } else if (Node->Pages > Pages) {\r
117 if (NewNode == NULL) {\r
118 // It is the first node that could contain our new allocation\r
119 NewNode = Node;\r
120 } else if (NewNode->Pages > Node->Pages) {\r
121 // This node offers a smaller number of page.\r
122 NewNode = Node;\r
123 }\r
124 }\r
125 }\r
126 }\r
127 }\r
128 // Check if we have found a node that could contain our new allocation\r
129 if (NewNode != NULL) {\r
130 NewNode->Allocated = TRUE;\r
131 NewNode->Allocation = (VOID*)(UINTN)NewNode->Base;\r
132 *Allocation = NewNode->Allocation;\r
133 mFreedBufferSize -= NewNode->Pages * EFI_PAGE_SIZE;\r
134 return EFI_SUCCESS;\r
135 }\r
136\r
137 //\r
138 // Otherwise, we need to allocate a new buffer\r
139 //\r
140\r
141 // We do not want to over-allocate in case the alignment requirement does not\r
142 // require extra pages\r
143 if (Alignment > EFI_PAGE_SIZE) {\r
144 AlignmentMask = Alignment - 1;\r
145 Pages += EFI_SIZE_TO_PAGES (Alignment);\r
146 } else {\r
147 AlignmentMask = 0;\r
148 }\r
149\r
150 Status = gBS->AllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory);\r
151 if (EFI_ERROR (Status)) {\r
152 return Status;\r
153 }\r
154\r
155 Status = gDS->GetMemorySpaceDescriptor (Memory, &Descriptor);\r
156 if (EFI_ERROR (Status)) {\r
157 goto FreePages;\r
158 }\r
159\r
160 Status = gDS->SetMemorySpaceAttributes (Memory, EFI_PAGES_TO_SIZE (Pages),\r
161 EFI_MEMORY_WC);\r
162 if (EFI_ERROR (Status)) {\r
163 goto FreePages;\r
164 }\r
165\r
166 //\r
167 // EFI_CPU_ARCH_PROTOCOL::SetMemoryAttributes() will preserve the original\r
168 // memory type attribute if no memory type is passed. Permission attributes\r
169 // will be replaced, so EFI_MEMORY_RO will be removed if present (although\r
170 // it would be a bug if that were the case for an AllocatePages() allocation)\r
171 //\r
172 Status = mCpu->SetMemoryAttributes (mCpu, Memory, EFI_PAGES_TO_SIZE (Pages),\r
173 EFI_MEMORY_XP);\r
174 if (EFI_ERROR (Status)) {\r
175 goto FreePages;\r
176 }\r
177\r
178 InvalidateDataCacheRange ((VOID *)(UINTN)Memory, EFI_PAGES_TO_SIZE (Pages));\r
179\r
180 NewNode = AllocatePool (sizeof (FREE_PAGE_NODE));\r
181 if (NewNode == NULL) {\r
182 ASSERT (FALSE);\r
183 Status = EFI_OUT_OF_RESOURCES;\r
184 goto FreePages;\r
185 }\r
186\r
187 NewNode->Base = Memory;\r
188 NewNode->Allocation = (VOID*)(((UINTN)Memory + AlignmentMask) & ~AlignmentMask);\r
189 NewNode->Pages = Pages;\r
190 NewNode->Allocated = TRUE;\r
191 NewNode->MemoryType = MemoryType;\r
192 NewNode->Attributes = Descriptor.Attributes;\r
193\r
194 InsertTailList (&mPageList, &NewNode->Link);\r
195\r
196 *Allocation = NewNode->Allocation;\r
197 return EFI_SUCCESS;\r
198\r
199FreePages:\r
200 gBS->FreePages (Memory, Pages);\r
201 return Status;\r
202}\r
203\r
204/**\r
205 * Free the memory allocation\r
206 *\r
207 * This function will actually try to find the allocation in the linked list.\r
208 * And it will then mark the entry as freed.\r
209 *\r
210 * @param Allocation Base address of the buffer to free\r
211 *\r
212 * @return EFI_SUCCESS The allocation has been freed\r
213 * @return EFI_NOT_FOUND The allocation was not found in the pool.\r
214 * @return EFI_INVALID_PARAMETER If Allocation is NULL\r
215 *\r
216 */\r
217STATIC\r
218EFI_STATUS\r
219FreePagesFromList (\r
220 IN VOID *Allocation\r
221 )\r
222{\r
223 LIST_ENTRY *Link;\r
224 FREE_PAGE_NODE *Node;\r
225\r
226 if (Allocation == NULL) {\r
227 return EFI_INVALID_PARAMETER;\r
228 }\r
229\r
230 for (Link = mPageList.ForwardLink; Link != &mPageList; Link = Link->ForwardLink) {\r
231 Node = BASE_CR (Link, FREE_PAGE_NODE, Link);\r
232 if ((UINTN)Node->Allocation == (UINTN)Allocation) {\r
233 Node->Allocated = FALSE;\r
234\r
235 // Update the size of the freed buffer\r
236 mFreedBufferSize += Node->Pages * EFI_PAGE_SIZE;\r
237\r
238 // If the size of the non-allocated reaches the threshold we raise a warning.\r
239 // It might be an expected behaviour in some cases.\r
240 // We might device to free some of these buffers later on.\r
241 if (mFreedBufferSize > PcdGet64 (PcdArmFreeUncachedMemorySizeThreshold)) {\r
242 DEBUG ((EFI_D_WARN, "Warning: The list of non-allocated buffer has reach the threshold.\n"));\r
243 }\r
244 return EFI_SUCCESS;\r
245 }\r
246 }\r
247\r
248 return EFI_NOT_FOUND;\r
249}\r
250\r
251/**\r
252 * This function is automatically invoked when the driver exits\r
253 * It frees all the non-allocated memory buffer.\r
254 * This function is not responsible to free allocated buffer (eg: case of memory leak,\r
255 * runtime allocation).\r
256 */\r
257EFI_STATUS\r
258EFIAPI\r
259UncachedMemoryAllocationLibConstructor (\r
260 IN EFI_HANDLE ImageHandle,\r
261 IN EFI_SYSTEM_TABLE *SystemTable\r
262 )\r
263{\r
264 return gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&mCpu);\r
265}\r
266\r
267EFI_STATUS\r
268EFIAPI\r
269UncachedMemoryAllocationLibDestructor (\r
270 IN EFI_HANDLE ImageHandle,\r
271 IN EFI_SYSTEM_TABLE *SystemTable\r
272 )\r
273{\r
274 LIST_ENTRY *Link;\r
275 FREE_PAGE_NODE *OldNode;\r
276\r
277 // Test if the list is empty\r
278 Link = mPageList.ForwardLink;\r
279 if (Link == &mPageList) {\r
280 return EFI_SUCCESS;\r
281 }\r
282\r
283 // Free all the pages and nodes\r
284 do {\r
285 OldNode = BASE_CR (Link, FREE_PAGE_NODE, Link);\r
286 // Point to the next entry\r
287 Link = Link->ForwardLink;\r
288\r
289 // We only free the non-allocated buffer\r
290 if (OldNode->Allocated == FALSE) {\r
291 gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)OldNode->Base, OldNode->Pages);\r
292\r
293 gDS->SetMemorySpaceAttributes ((EFI_PHYSICAL_ADDRESS)(UINTN)OldNode->Base,\r
294 EFI_PAGES_TO_SIZE (OldNode->Pages), OldNode->Attributes);\r
295\r
296 RemoveEntryList (&OldNode->Link);\r
297 FreePool (OldNode);\r
298 }\r
299 } while (Link != &mPageList);\r
300\r
301 return EFI_SUCCESS;\r
302}\r
303\r
304/**\r
305 Converts a cached or uncached address to a physical address suitable for use in SoC registers.\r
306\r
307 @param VirtualAddress The pointer to convert.\r
308\r
309 @return The physical address of the supplied virtual pointer.\r
310\r
311**/\r
312EFI_PHYSICAL_ADDRESS\r
313ConvertToPhysicalAddress (\r
314 IN VOID *VirtualAddress\r
315 )\r
316{\r
317 return (EFI_PHYSICAL_ADDRESS)(UINTN)VirtualAddress;\r
318}\r
319\r
320\r
321VOID *\r
322UncachedInternalAllocatePages (\r
323 IN EFI_MEMORY_TYPE MemoryType,\r
324 IN UINTN Pages\r
325 )\r
326{\r
327 return UncachedInternalAllocateAlignedPages (MemoryType, Pages, EFI_PAGE_SIZE);\r
328}\r
329\r
330\r
331VOID *\r
332EFIAPI\r
333UncachedAllocatePages (\r
334 IN UINTN Pages\r
335 )\r
336{\r
337 return UncachedInternalAllocatePages (EfiBootServicesData, Pages);\r
338}\r
339\r
340VOID *\r
341EFIAPI\r
342UncachedAllocateRuntimePages (\r
343 IN UINTN Pages\r
344 )\r
345{\r
346 return UncachedInternalAllocatePages (EfiRuntimeServicesData, Pages);\r
347}\r
348\r
349VOID *\r
350EFIAPI\r
351UncachedAllocateReservedPages (\r
352 IN UINTN Pages\r
353 )\r
354{\r
355 return UncachedInternalAllocatePages (EfiReservedMemoryType, Pages);\r
356}\r
357\r
358\r
359\r
360VOID\r
361EFIAPI\r
362UncachedFreePages (\r
363 IN VOID *Buffer,\r
364 IN UINTN Pages\r
365 )\r
366{\r
367 UncachedFreeAlignedPages (Buffer, Pages);\r
368 return;\r
369}\r
370\r
371\r
372VOID *\r
373UncachedInternalAllocateAlignedPages (\r
374 IN EFI_MEMORY_TYPE MemoryType,\r
375 IN UINTN Pages,\r
376 IN UINTN Alignment\r
377 )\r
378{\r
379 EFI_STATUS Status;\r
380 VOID *Allocation;\r
381\r
382 if (Pages == 0) {\r
383 return NULL;\r
384 }\r
385\r
386 Allocation = NULL;\r
387 Status = AllocatePagesFromList (MemoryType, Pages, Alignment, &Allocation);\r
388 if (EFI_ERROR (Status)) {\r
389 ASSERT_EFI_ERROR (Status);\r
390 return NULL;\r
391 } else {\r
392 return Allocation;\r
393 }\r
394}\r
395\r
396\r
397VOID\r
398EFIAPI\r
399UncachedFreeAlignedPages (\r
400 IN VOID *Buffer,\r
401 IN UINTN Pages\r
402 )\r
403{\r
404 FreePagesFromList (Buffer);\r
405}\r
406\r
407\r
408VOID *\r
409UncachedInternalAllocateAlignedPool (\r
410 IN EFI_MEMORY_TYPE PoolType,\r
411 IN UINTN AllocationSize,\r
412 IN UINTN Alignment\r
413 )\r
414{\r
415 VOID *AlignedAddress;\r
416\r
417 //\r
418 // Alignment must be a power of two or zero.\r
419 //\r
420 ASSERT ((Alignment & (Alignment - 1)) == 0);\r
421\r
422 if (Alignment < EFI_PAGE_SIZE) {\r
423 Alignment = EFI_PAGE_SIZE;\r
424 }\r
425\r
426 AlignedAddress = UncachedInternalAllocateAlignedPages (PoolType, EFI_SIZE_TO_PAGES (AllocationSize), Alignment);\r
427 if (AlignedAddress == NULL) {\r
428 return NULL;\r
429 }\r
430\r
431 return (VOID *) AlignedAddress;\r
432}\r
433\r
434VOID *\r
435EFIAPI\r
436UncachedAllocateAlignedPool (\r
437 IN UINTN AllocationSize,\r
438 IN UINTN Alignment\r
439 )\r
440{\r
441 return UncachedInternalAllocateAlignedPool (EfiBootServicesData, AllocationSize, Alignment);\r
442}\r
443\r
444VOID *\r
445EFIAPI\r
446UncachedAllocateAlignedRuntimePool (\r
447 IN UINTN AllocationSize,\r
448 IN UINTN Alignment\r
449 )\r
450{\r
451 return UncachedInternalAllocateAlignedPool (EfiRuntimeServicesData, AllocationSize, Alignment);\r
452}\r
453\r
454VOID *\r
455EFIAPI\r
456UncachedAllocateAlignedReservedPool (\r
457 IN UINTN AllocationSize,\r
458 IN UINTN Alignment\r
459 )\r
460{\r
461 return UncachedInternalAllocateAlignedPool (EfiReservedMemoryType, AllocationSize, Alignment);\r
462}\r
463\r
464VOID *\r
465UncachedInternalAllocateAlignedZeroPool (\r
466 IN EFI_MEMORY_TYPE PoolType,\r
467 IN UINTN AllocationSize,\r
468 IN UINTN Alignment\r
469 )\r
470{\r
471 VOID *Memory;\r
472 Memory = UncachedInternalAllocateAlignedPool (PoolType, AllocationSize, Alignment);\r
473 if (Memory != NULL) {\r
474 Memory = ZeroMem (Memory, AllocationSize);\r
475 }\r
476 return Memory;\r
477}\r
478\r
479VOID *\r
480EFIAPI\r
481UncachedAllocateAlignedZeroPool (\r
482 IN UINTN AllocationSize,\r
483 IN UINTN Alignment\r
484 )\r
485{\r
486 return UncachedInternalAllocateAlignedZeroPool (EfiBootServicesData, AllocationSize, Alignment);\r
487}\r
488\r
489VOID *\r
490EFIAPI\r
491UncachedAllocateAlignedRuntimeZeroPool (\r
492 IN UINTN AllocationSize,\r
493 IN UINTN Alignment\r
494 )\r
495{\r
496 return UncachedInternalAllocateAlignedZeroPool (EfiRuntimeServicesData, AllocationSize, Alignment);\r
497}\r
498\r
499VOID *\r
500EFIAPI\r
501UncachedAllocateAlignedReservedZeroPool (\r
502 IN UINTN AllocationSize,\r
503 IN UINTN Alignment\r
504 )\r
505{\r
506 return UncachedInternalAllocateAlignedZeroPool (EfiReservedMemoryType, AllocationSize, Alignment);\r
507}\r
508\r
509VOID *\r
510UncachedInternalAllocateAlignedCopyPool (\r
511 IN EFI_MEMORY_TYPE PoolType,\r
512 IN UINTN AllocationSize,\r
513 IN CONST VOID *Buffer,\r
514 IN UINTN Alignment\r
515 )\r
516{\r
517 VOID *Memory;\r
518\r
519 ASSERT (Buffer != NULL);\r
520 ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN) Buffer + 1));\r
521\r
522 Memory = UncachedInternalAllocateAlignedPool (PoolType, AllocationSize, Alignment);\r
523 if (Memory != NULL) {\r
524 Memory = CopyMem (Memory, Buffer, AllocationSize);\r
525 }\r
526 return Memory;\r
527}\r
528\r
529VOID *\r
530EFIAPI\r
531UncachedAllocateAlignedCopyPool (\r
532 IN UINTN AllocationSize,\r
533 IN CONST VOID *Buffer,\r
534 IN UINTN Alignment\r
535 )\r
536{\r
537 return UncachedInternalAllocateAlignedCopyPool (EfiBootServicesData, AllocationSize, Buffer, Alignment);\r
538}\r
539\r
540VOID *\r
541EFIAPI\r
542UncachedAllocateAlignedRuntimeCopyPool (\r
543 IN UINTN AllocationSize,\r
544 IN CONST VOID *Buffer,\r
545 IN UINTN Alignment\r
546 )\r
547{\r
548 return UncachedInternalAllocateAlignedCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer, Alignment);\r
549}\r
550\r
551VOID *\r
552EFIAPI\r
553UncachedAllocateAlignedReservedCopyPool (\r
554 IN UINTN AllocationSize,\r
555 IN CONST VOID *Buffer,\r
556 IN UINTN Alignment\r
557 )\r
558{\r
559 return UncachedInternalAllocateAlignedCopyPool (EfiReservedMemoryType, AllocationSize, Buffer, Alignment);\r
560}\r
561\r
562VOID\r
563EFIAPI\r
564UncachedFreeAlignedPool (\r
565 IN VOID *Allocation\r
566 )\r
567{\r
568 UncachedFreePages (Allocation, 0);\r
569}\r
570\r
571VOID *\r
572UncachedInternalAllocatePool (\r
573 IN EFI_MEMORY_TYPE MemoryType,\r
574 IN UINTN AllocationSize\r
575 )\r
576{\r
577 UINTN CacheLineLength = ArmCacheWritebackGranule ();\r
578 return UncachedInternalAllocateAlignedPool (MemoryType, AllocationSize, CacheLineLength);\r
579}\r
580\r
581VOID *\r
582EFIAPI\r
583UncachedAllocatePool (\r
584 IN UINTN AllocationSize\r
585 )\r
586{\r
587 return UncachedInternalAllocatePool (EfiBootServicesData, AllocationSize);\r
588}\r
589\r
590VOID *\r
591EFIAPI\r
592UncachedAllocateRuntimePool (\r
593 IN UINTN AllocationSize\r
594 )\r
595{\r
596 return UncachedInternalAllocatePool (EfiRuntimeServicesData, AllocationSize);\r
597}\r
598\r
599VOID *\r
600EFIAPI\r
601UncachedAllocateReservedPool (\r
602 IN UINTN AllocationSize\r
603 )\r
604{\r
605 return UncachedInternalAllocatePool (EfiReservedMemoryType, AllocationSize);\r
606}\r
607\r
608VOID *\r
609UncachedInternalAllocateZeroPool (\r
610 IN EFI_MEMORY_TYPE PoolType,\r
611 IN UINTN AllocationSize\r
612 )\r
613{\r
614 VOID *Memory;\r
615\r
616 Memory = UncachedInternalAllocatePool (PoolType, AllocationSize);\r
617 if (Memory != NULL) {\r
618 Memory = ZeroMem (Memory, AllocationSize);\r
619 }\r
620 return Memory;\r
621}\r
622\r
623VOID *\r
624EFIAPI\r
625UncachedAllocateZeroPool (\r
626 IN UINTN AllocationSize\r
627 )\r
628{\r
629 return UncachedInternalAllocateZeroPool (EfiBootServicesData, AllocationSize);\r
630}\r
631\r
632VOID *\r
633EFIAPI\r
634UncachedAllocateRuntimeZeroPool (\r
635 IN UINTN AllocationSize\r
636 )\r
637{\r
638 return UncachedInternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize);\r
639}\r
640\r
641VOID *\r
642EFIAPI\r
643UncachedAllocateReservedZeroPool (\r
644 IN UINTN AllocationSize\r
645 )\r
646{\r
647 return UncachedInternalAllocateZeroPool (EfiReservedMemoryType, AllocationSize);\r
648}\r
649\r
650VOID *\r
651UncachedInternalAllocateCopyPool (\r
652 IN EFI_MEMORY_TYPE PoolType,\r
653 IN UINTN AllocationSize,\r
654 IN CONST VOID *Buffer\r
655 )\r
656{\r
657 VOID *Memory;\r
658\r
659 ASSERT (Buffer != NULL);\r
660 ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN) Buffer + 1));\r
661\r
662 Memory = UncachedInternalAllocatePool (PoolType, AllocationSize);\r
663 if (Memory != NULL) {\r
664 Memory = CopyMem (Memory, Buffer, AllocationSize);\r
665 }\r
666 return Memory;\r
667}\r
668\r
669VOID *\r
670EFIAPI\r
671UncachedAllocateCopyPool (\r
672 IN UINTN AllocationSize,\r
673 IN CONST VOID *Buffer\r
674 )\r
675{\r
676 return UncachedInternalAllocateCopyPool (EfiBootServicesData, AllocationSize, Buffer);\r
677}\r
678\r
679VOID *\r
680EFIAPI\r
681UncachedAllocateRuntimeCopyPool (\r
682 IN UINTN AllocationSize,\r
683 IN CONST VOID *Buffer\r
684 )\r
685{\r
686 return UncachedInternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer);\r
687}\r
688\r
689VOID *\r
690EFIAPI\r
691UncachedAllocateReservedCopyPool (\r
692 IN UINTN AllocationSize,\r
693 IN CONST VOID *Buffer\r
694 )\r
695{\r
696 return UncachedInternalAllocateCopyPool (EfiReservedMemoryType, AllocationSize, Buffer);\r
697}\r
698\r
699VOID\r
700EFIAPI\r
701UncachedFreePool (\r
702 IN VOID *Buffer\r
703 )\r
704{\r
705 UncachedFreeAlignedPool (Buffer);\r
706}\r
707\r
708VOID\r
709EFIAPI\r
710UncachedSafeFreePool (\r
711 IN VOID *Buffer\r
712 )\r
713{\r
714 if (Buffer != NULL) {\r
715 UncachedFreePool (Buffer);\r
716 Buffer = NULL;\r
717 }\r
718}\r
719\r