]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/DxeMemoryAllocationLib/MemoryAllocationLib.c
Import some Pei and Dxe related instances for MdePkg.
[mirror_edk2.git] / MdePkg / Library / DxeMemoryAllocationLib / MemoryAllocationLib.c
CommitLineData
e386b444 1/** @file\r
2 Support routines for memory allocation routines for use with drivers.\r
3\r
4 Copyright (c) 2006, Intel Corporation<BR>\r
5 All rights reserved. This program and the accompanying materials \r
6 are licensed and made available under the terms and conditions of the BSD License \r
7 which accompanies this distribution. The full text of the license may be found at \r
8 http://opensource.org/licenses/bsd-license.php \r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
12\r
13 Module Name: MemoryAllocationLib.c\r
14\r
15**/\r
16\r
17//\r
18// Include common header file for this module.\r
19//\r
20#include "CommonHeader.h"\r
21\r
22#include "MemoryAllocationLibInternals.h"\r
23\r
24/**\r
25 Allocates one or more 4KB pages of a certain memory type.\r
26\r
27 Allocates the number of 4KB pages of a certain memory type and returns a pointer to the allocated\r
28 buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL is returned.\r
29 If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
30\r
31 @param MemoryType The type of memory to allocate.\r
32 @param Pages The number of 4 KB pages to allocate.\r
33\r
34 @return A pointer to the allocated buffer or NULL if allocation fails.\r
35\r
36**/\r
37VOID *\r
38InternalAllocatePages (\r
39 IN EFI_MEMORY_TYPE MemoryType, \r
40 IN UINTN Pages\r
41 )\r
42{\r
43 EFI_STATUS Status;\r
44 EFI_PHYSICAL_ADDRESS Memory; \r
45\r
46 if (Pages == 0) {\r
47 return NULL;\r
48 }\r
49\r
50 Status = gBS->AllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory);\r
51 if (EFI_ERROR (Status)) {\r
52 Memory = 0;\r
53 }\r
54 return (VOID *) (UINTN) Memory;\r
55}\r
56\r
57/**\r
58 Allocates one or more 4KB pages of type EfiBootServicesData.\r
59\r
60 Allocates the number of 4KB pages of type EfiBootServicesData and returns a pointer to the\r
61 allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL\r
62 is returned. If there is not enough memory remaining to satisfy the request, then NULL is\r
63 returned.\r
64\r
65 @param Pages The number of 4 KB pages to allocate.\r
66\r
67 @return A pointer to the allocated buffer or NULL if allocation fails.\r
68\r
69**/\r
70VOID *\r
71EFIAPI\r
72AllocatePages (\r
73 IN UINTN Pages\r
74 )\r
75{\r
76 return InternalAllocatePages (EfiBootServicesData, Pages);\r
77}\r
78\r
79/**\r
80 Allocates one or more 4KB pages of type EfiRuntimeServicesData.\r
81\r
82 Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer to the\r
83 allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL\r
84 is returned. If there is not enough memory remaining to satisfy the request, then NULL is\r
85 returned.\r
86\r
87 @param Pages The number of 4 KB pages to allocate.\r
88\r
89 @return A pointer to the allocated buffer or NULL if allocation fails.\r
90\r
91**/\r
92VOID *\r
93EFIAPI\r
94AllocateRuntimePages (\r
95 IN UINTN Pages\r
96 )\r
97{\r
98 return InternalAllocatePages (EfiRuntimeServicesData, Pages);\r
99}\r
100\r
101/**\r
102 Allocates one or more 4KB pages of type EfiReservedMemoryType.\r
103\r
104 Allocates the number of 4KB pages of type EfiReservedMemoryType and returns a pointer to the\r
105 allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL\r
106 is returned. If there is not enough memory remaining to satisfy the request, then NULL is\r
107 returned.\r
108\r
109 @param Pages The number of 4 KB pages to allocate.\r
110\r
111 @return A pointer to the allocated buffer or NULL if allocation fails.\r
112\r
113**/\r
114VOID *\r
115EFIAPI\r
116AllocateReservedPages (\r
117 IN UINTN Pages\r
118 )\r
119{\r
120 return InternalAllocatePages (EfiReservedMemoryType, Pages);\r
121}\r
122\r
123/**\r
124 Frees one or more 4KB pages that were previously allocated with one of the page allocation\r
125 functions in the Memory Allocation Library.\r
126\r
127 Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer\r
128 must have been allocated on a previous call to the page allocation services of the Memory\r
129 Allocation Library.\r
130 If Buffer was not allocated with a page allocation function in the Memory Allocation Library,\r
131 then ASSERT().\r
132 If Pages is zero, then ASSERT().\r
133 \r
134 @param Buffer Pointer to the buffer of pages to free.\r
135 @param Pages The number of 4 KB pages to free.\r
136\r
137**/\r
138VOID\r
139EFIAPI\r
140FreePages (\r
141 IN VOID *Buffer,\r
142 IN UINTN Pages\r
143 )\r
144{\r
145 EFI_STATUS Status;\r
146\r
147 ASSERT (Pages != 0);\r
148 Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);\r
149 ASSERT_EFI_ERROR (Status);\r
150}\r
151\r
152/**\r
153 Allocates one or more 4KB pages of a certain memory type at a specified alignment.\r
154\r
155 Allocates the number of 4KB pages specified by Pages of a certain memory type with an alignment\r
156 specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is returned.\r
157 If there is not enough memory at the specified alignment remaining to satisfy the request, then\r
158 NULL is returned.\r
159 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
160\r
161 @param MemoryType The type of memory to allocate.\r
162 @param Pages The number of 4 KB pages to allocate.\r
163 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
164 If Alignment is zero, then byte alignment is used.\r
165\r
166 @return A pointer to the allocated buffer or NULL if allocation fails.\r
167\r
168**/\r
169VOID *\r
170InternalAllocateAlignedPages (\r
171 IN EFI_MEMORY_TYPE MemoryType, \r
172 IN UINTN Pages,\r
173 IN UINTN Alignment\r
174 )\r
175{\r
176 EFI_STATUS Status;\r
177 EFI_PHYSICAL_ADDRESS Memory;\r
178 UINTN AlignedMemory;\r
179 UINTN AlignmentMask;\r
180 UINTN UnalignedPages;\r
181 UINTN RealPages;\r
182\r
183 //\r
184 // Alignment must be a power of two or zero.\r
185 //\r
186 ASSERT ((Alignment & (Alignment - 1)) == 0);\r
187 \r
188 if (Pages == 0) {\r
189 return NULL;\r
190 }\r
191 if (Alignment > EFI_PAGE_SIZE) {\r
192 //\r
193 // Caculate the total number of pages since alignment is larger than page size.\r
194 //\r
195 AlignmentMask = Alignment - 1;\r
196 RealPages = Pages + EFI_SIZE_TO_PAGES (Alignment);\r
197 //\r
198 // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.\r
199 //\r
200 ASSERT (RealPages > Pages);\r
201 \r
202 Status = gBS->AllocatePages (AllocateAnyPages, MemoryType, RealPages, &Memory);\r
203 if (EFI_ERROR (Status)) {\r
204 return NULL;\r
205 }\r
206 AlignedMemory = ((UINTN) Memory + AlignmentMask) & ~AlignmentMask;\r
207 UnalignedPages = EFI_SIZE_TO_PAGES ((UINTN) Memory - AlignedMemory);\r
208 if (UnalignedPages > 0) {\r
209 //\r
210 // Free first unaligned page(s).\r
211 //\r
212 Status = gBS->FreePages (Memory, UnalignedPages);\r
213 ASSERT_EFI_ERROR (Status);\r
214 }\r
215 Memory = (EFI_PHYSICAL_ADDRESS) (AlignedMemory + EFI_PAGES_TO_SIZE (Pages));\r
216 UnalignedPages = RealPages - Pages - UnalignedPages;\r
217 if (UnalignedPages > 0) {\r
218 //\r
219 // Free last unaligned page(s).\r
220 //\r
221 Status = gBS->FreePages (Memory, UnalignedPages);\r
222 ASSERT_EFI_ERROR (Status);\r
223 }\r
224 } else {\r
225 //\r
226 // Do not over-allocate pages in this case.\r
227 //\r
228 Status = gBS->AllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory);\r
229 if (EFI_ERROR (Status)) {\r
230 return NULL;\r
231 }\r
232 AlignedMemory = (UINTN) Memory;\r
233 }\r
234 return (VOID *) AlignedMemory;\r
235}\r
236\r
237/**\r
238 Allocates one or more 4KB pages of type EfiBootServicesData at a specified alignment.\r
239\r
240 Allocates the number of 4KB pages specified by Pages of type EfiBootServicesData with an\r
241 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is\r
242 returned. If there is not enough memory at the specified alignment remaining to satisfy the\r
243 request, then NULL is returned.\r
244 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
245\r
246 @param Pages The number of 4 KB pages to allocate.\r
247 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
248 If Alignment is zero, then byte alignment is used.\r
249\r
250 @return A pointer to the allocated buffer or NULL if allocation fails.\r
251\r
252**/\r
253VOID *\r
254EFIAPI\r
255AllocateAlignedPages (\r
256 IN UINTN Pages,\r
257 IN UINTN Alignment\r
258 )\r
259{\r
260 return InternalAllocateAlignedPages (EfiBootServicesData, Pages, Alignment);\r
261}\r
262\r
263/**\r
264 Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment.\r
265\r
266 Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData with an\r
267 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is\r
268 returned. If there is not enough memory at the specified alignment remaining to satisfy the\r
269 request, then NULL is returned.\r
270 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
271\r
272 @param Pages The number of 4 KB pages to allocate.\r
273 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
274 If Alignment is zero, then byte alignment is used.\r
275\r
276 @return A pointer to the allocated buffer or NULL if allocation fails.\r
277\r
278**/\r
279VOID *\r
280EFIAPI\r
281AllocateAlignedRuntimePages (\r
282 IN UINTN Pages,\r
283 IN UINTN Alignment\r
284 )\r
285{\r
286 return InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment);\r
287}\r
288\r
289/**\r
290 Allocates one or more 4KB pages of type EfiReservedMemoryType at a specified alignment.\r
291\r
292 Allocates the number of 4KB pages specified by Pages of type EfiReservedMemoryType with an\r
293 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is\r
294 returned. If there is not enough memory at the specified alignment remaining to satisfy the\r
295 request, then NULL is returned.\r
296 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
297\r
298 @param Pages The number of 4 KB pages to allocate.\r
299 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
300 If Alignment is zero, then byte alignment is used.\r
301\r
302 @return A pointer to the allocated buffer or NULL if allocation fails.\r
303\r
304**/\r
305VOID *\r
306EFIAPI\r
307AllocateAlignedReservedPages (\r
308 IN UINTN Pages,\r
309 IN UINTN Alignment\r
310 )\r
311{\r
312 return InternalAllocateAlignedPages (EfiReservedMemoryType, Pages, Alignment);\r
313}\r
314\r
315/**\r
316 Frees one or more 4KB pages that were previously allocated with one of the aligned page\r
317 allocation functions in the Memory Allocation Library.\r
318\r
319 Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer\r
320 must have been allocated on a previous call to the aligned page allocation services of the Memory\r
321 Allocation Library.\r
322 If Buffer was not allocated with an aligned page allocation function in the Memory Allocation\r
323 Library, then ASSERT().\r
324 If Pages is zero, then ASSERT().\r
325 \r
326 @param Buffer Pointer to the buffer of pages to free.\r
327 @param Pages The number of 4 KB pages to free.\r
328\r
329**/\r
330VOID\r
331EFIAPI\r
332FreeAlignedPages (\r
333 IN VOID *Buffer,\r
334 IN UINTN Pages\r
335 )\r
336{\r
337 EFI_STATUS Status;\r
338\r
339 ASSERT (Pages != 0);\r
340 Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);\r
341 ASSERT_EFI_ERROR (Status);\r
342}\r
343\r
344/**\r
345 Allocates a buffer of a certain pool type.\r
346\r
347 Allocates the number bytes specified by AllocationSize of a certain pool type and returns a\r
348 pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is\r
349 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
350\r
351 @param MemoryType The type of memory to allocate.\r
352 @param AllocationSize The number of bytes to allocate.\r
353\r
354 @return A pointer to the allocated buffer or NULL if allocation fails.\r
355\r
356**/\r
357VOID *\r
358InternalAllocatePool (\r
359 IN EFI_MEMORY_TYPE MemoryType, \r
360 IN UINTN AllocationSize\r
361 )\r
362{\r
363 EFI_STATUS Status;\r
364 VOID *Memory;\r
365\r
366 Status = gBS->AllocatePool (MemoryType, AllocationSize, &Memory);\r
367 if (EFI_ERROR (Status)) {\r
368 Memory = NULL;\r
369 }\r
370 return Memory;\r
371}\r
372\r
373/**\r
374 Allocates a buffer of type EfiBootServicesData.\r
375\r
376 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData and returns a\r
377 pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is\r
378 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
379\r
380 @param AllocationSize The number of bytes to allocate.\r
381\r
382 @return A pointer to the allocated buffer or NULL if allocation fails.\r
383\r
384**/\r
385VOID *\r
386EFIAPI\r
387AllocatePool (\r
388 IN UINTN AllocationSize\r
389 )\r
390{\r
391 return InternalAllocatePool (EfiBootServicesData, AllocationSize);\r
392}\r
393\r
394/**\r
395 Allocates a buffer of type EfiRuntimeServicesData.\r
396\r
397 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData and returns\r
398 a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is\r
399 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
400\r
401 @param AllocationSize The number of bytes to allocate.\r
402\r
403 @return A pointer to the allocated buffer or NULL if allocation fails.\r
404\r
405**/\r
406VOID *\r
407EFIAPI\r
408AllocateRuntimePool (\r
409 IN UINTN AllocationSize\r
410 )\r
411{\r
412 return InternalAllocatePool (EfiRuntimeServicesData, AllocationSize);\r
413}\r
414\r
415/**\r
416 Allocates a buffer of type EfieservedMemoryType.\r
417\r
418 Allocates the number bytes specified by AllocationSize of type EfieservedMemoryType and returns\r
419 a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is\r
420 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
421\r
422 @param AllocationSize The number of bytes to allocate.\r
423\r
424 @return A pointer to the allocated buffer or NULL if allocation fails.\r
425\r
426**/\r
427VOID *\r
428EFIAPI\r
429AllocateReservedPool (\r
430 IN UINTN AllocationSize\r
431 )\r
432{\r
433 return InternalAllocatePool (EfiReservedMemoryType, AllocationSize);\r
434}\r
435\r
436/**\r
437 Allocates and zeros a buffer of a certian pool type.\r
438\r
439 Allocates the number bytes specified by AllocationSize of a certian pool type, clears the buffer\r
440 with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a valid\r
441 buffer of 0 size is returned. If there is not enough memory remaining to satisfy the request,\r
442 then NULL is returned.\r
443\r
444 @param PoolType The type of memory to allocate.\r
445 @param AllocationSize The number of bytes to allocate and zero.\r
446\r
447 @return A pointer to the allocated buffer or NULL if allocation fails.\r
448\r
449**/\r
450VOID *\r
451InternalAllocateZeroPool (\r
452 IN EFI_MEMORY_TYPE PoolType, \r
453 IN UINTN AllocationSize\r
454 ) \r
455{\r
456 VOID *Memory;\r
457\r
458 Memory = InternalAllocatePool (PoolType, AllocationSize);\r
459 if (Memory != NULL) {\r
460 Memory = ZeroMem (Memory, AllocationSize);\r
461 }\r
462 return Memory;\r
463}\r
464\r
465/**\r
466 Allocates and zeros a buffer of type EfiBootServicesData.\r
467\r
468 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, clears the\r
469 buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a\r
470 valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the\r
471 request, then NULL is returned.\r
472\r
473 @param AllocationSize The number of bytes to allocate and zero.\r
474\r
475 @return A pointer to the allocated buffer or NULL if allocation fails.\r
476\r
477**/\r
478VOID *\r
479EFIAPI\r
480AllocateZeroPool (\r
481 IN UINTN AllocationSize\r
482 )\r
483{\r
484 return InternalAllocateZeroPool (EfiBootServicesData, AllocationSize);\r
485}\r
486\r
487/**\r
488 Allocates and zeros a buffer of type EfiRuntimeServicesData.\r
489\r
490 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, clears the\r
491 buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a\r
492 valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the\r
493 request, then NULL is returned.\r
494\r
495 @param AllocationSize The number of bytes to allocate and zero.\r
496\r
497 @return A pointer to the allocated buffer or NULL if allocation fails.\r
498\r
499**/\r
500VOID *\r
501EFIAPI\r
502AllocateRuntimeZeroPool (\r
503 IN UINTN AllocationSize\r
504 )\r
505{\r
506 return InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize);\r
507}\r
508\r
509/**\r
510 Allocates and zeros a buffer of type EfiReservedMemoryType.\r
511\r
512 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, clears the\r
513 buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a\r
514 valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the\r
515 request, then NULL is returned.\r
516\r
517 @param AllocationSize The number of bytes to allocate and zero.\r
518\r
519 @return A pointer to the allocated buffer or NULL if allocation fails.\r
520\r
521**/\r
522VOID *\r
523EFIAPI\r
524AllocateReservedZeroPool (\r
525 IN UINTN AllocationSize\r
526 )\r
527{\r
528 return InternalAllocateZeroPool (EfiReservedMemoryType, AllocationSize);\r
529}\r
530\r
531/**\r
532 Copies a buffer to an allocated buffer of a certian pool type.\r
533\r
534 Allocates the number bytes specified by AllocationSize of a certian pool type, copies\r
535 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the\r
536 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there\r
537 is not enough memory remaining to satisfy the request, then NULL is returned.\r
538 If Buffer is NULL, then ASSERT().\r
539 If AllocationSize is greater than (MAX_ADDRESS ? Buffer + 1), then ASSERT(). \r
540\r
541 @param PoolType The type of pool to allocate.\r
542 @param AllocationSize The number of bytes to allocate and zero.\r
543 @param Buffer The buffer to copy to the allocated buffer.\r
544\r
545 @return A pointer to the allocated buffer or NULL if allocation fails.\r
546\r
547**/\r
548VOID *\r
549InternalAllocateCopyPool (\r
550 IN EFI_MEMORY_TYPE PoolType, \r
551 IN UINTN AllocationSize,\r
552 IN CONST VOID *Buffer\r
553 ) \r
554{\r
555 VOID *Memory;\r
556\r
557 ASSERT (Buffer != NULL);\r
558 ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN) Buffer + 1));\r
559\r
560 Memory = InternalAllocatePool (PoolType, AllocationSize);\r
561 if (Memory != NULL) {\r
562 Memory = CopyMem (Memory, Buffer, AllocationSize);\r
563 }\r
564 return Memory;\r
565} \r
566\r
567/**\r
568 Copies a buffer to an allocated buffer of type EfiBootServicesData.\r
569\r
570 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, copies\r
571 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the\r
572 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there\r
573 is not enough memory remaining to satisfy the request, then NULL is returned.\r
574 If Buffer is NULL, then ASSERT().\r
575 If AllocationSize is greater than (MAX_ADDRESS ? Buffer + 1), then ASSERT(). \r
576\r
577 @param AllocationSize The number of bytes to allocate and zero.\r
578 @param Buffer The buffer to copy to the allocated buffer.\r
579\r
580 @return A pointer to the allocated buffer or NULL if allocation fails.\r
581\r
582**/\r
583VOID *\r
584EFIAPI\r
585AllocateCopyPool (\r
586 IN UINTN AllocationSize,\r
587 IN CONST VOID *Buffer\r
588 )\r
589{\r
590 return InternalAllocateCopyPool (EfiBootServicesData, AllocationSize, Buffer);\r
591}\r
592\r
593/**\r
594 Copies a buffer to an allocated buffer of type EfiRuntimeServicesData.\r
595\r
596 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, copies\r
597 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the\r
598 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there\r
599 is not enough memory remaining to satisfy the request, then NULL is returned.\r
600 If Buffer is NULL, then ASSERT().\r
601 If AllocationSize is greater than (MAX_ADDRESS ? Buffer + 1), then ASSERT(). \r
602\r
603 @param AllocationSize The number of bytes to allocate and zero.\r
604 @param Buffer The buffer to copy to the allocated buffer.\r
605\r
606 @return A pointer to the allocated buffer or NULL if allocation fails.\r
607\r
608**/\r
609VOID *\r
610EFIAPI\r
611AllocateRuntimeCopyPool (\r
612 IN UINTN AllocationSize,\r
613 IN CONST VOID *Buffer\r
614 )\r
615{\r
616 return InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer);\r
617}\r
618\r
619/**\r
620 Copies a buffer to an allocated buffer of type EfiReservedMemoryType.\r
621\r
622 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, copies\r
623 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the\r
624 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there\r
625 is not enough memory remaining to satisfy the request, then NULL is returned.\r
626 If Buffer is NULL, then ASSERT().\r
627 If AllocationSize is greater than (MAX_ADDRESS ? Buffer + 1), then ASSERT(). \r
628\r
629 @param AllocationSize The number of bytes to allocate and zero.\r
630 @param Buffer The buffer to copy to the allocated buffer.\r
631\r
632 @return A pointer to the allocated buffer or NULL if allocation fails.\r
633\r
634**/\r
635VOID *\r
636EFIAPI\r
637AllocateReservedCopyPool (\r
638 IN UINTN AllocationSize,\r
639 IN CONST VOID *Buffer\r
640 )\r
641{\r
642 return InternalAllocateCopyPool (EfiReservedMemoryType, AllocationSize, Buffer);\r
643}\r
644\r
645/**\r
646 Frees a buffer that was previously allocated with one of the pool allocation functions in the\r
647 Memory Allocation Library.\r
648\r
649 Frees the buffer specified by Buffer. Buffer must have been allocated on a previous call to the\r
650 pool allocation services of the Memory Allocation Library.\r
651 If Buffer was not allocated with a pool allocation function in the Memory Allocation Library,\r
652 then ASSERT().\r
653\r
654 @param Buffer Pointer to the buffer to free.\r
655\r
656**/\r
657VOID\r
658EFIAPI\r
659FreePool (\r
660 IN VOID *Buffer\r
661 )\r
662{\r
663 EFI_STATUS Status;\r
664\r
665 Status = gBS->FreePool (Buffer);\r
666 ASSERT_EFI_ERROR (Status);\r
667}\r
668\r
669/**\r
670 Allocates a buffer of a certain pool type at a specified alignment.\r
671\r
672 Allocates the number bytes specified by AllocationSize of a certain pool type with an alignment\r
673 specified by Alignment. The allocated buffer is returned. If AllocationSize is 0, then a valid\r
674 buffer of 0 size is returned. If there is not enough memory at the specified alignment remaining\r
675 to satisfy the request, then NULL is returned.\r
676 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
677\r
678 @param PoolType The type of pool to allocate.\r
679 @param AllocationSize The number of bytes to allocate.\r
680 @param Alignment The requested alignment of the allocation. Must be a power of two. If Alignment is zero, then byte alignment is used.\r
681 If Alignment is zero, then byte alignment is used.\r
682\r
683 @return A pointer to the allocated buffer or NULL if allocation fails.\r
684\r
685**/\r
686VOID *\r
687InternalAllocateAlignedPool (\r
688 IN EFI_MEMORY_TYPE PoolType,\r
689 IN UINTN AllocationSize,\r
690 IN UINTN Alignment\r
691 )\r
692{\r
693 VOID *RawAddress;\r
694 UINTN AlignedAddress;\r
695 UINTN AlignmentMask;\r
696 UINTN OverAllocationSize;\r
697 UINTN RealAllocationSize;\r
698 VOID **FreePointer;\r
699\r
700 //\r
701 // Alignment must be a power of two or zero.\r
702 //\r
703 ASSERT ((Alignment & (Alignment - 1)) == 0);\r
704 \r
705 if (Alignment == 0) {\r
706 AlignmentMask = Alignment;\r
707 } else {\r
708 AlignmentMask = Alignment - 1;\r
709 }\r
710 //\r
711 // Calculate the extra memory size, over-allocate memory pool and get the aligned memory address. \r
712 //\r
713 OverAllocationSize = sizeof (RawAddress) + AlignmentMask;\r
714 RealAllocationSize = AllocationSize + OverAllocationSize;\r
715 //\r
716 // Make sure that AllocationSize plus OverAllocationSize does not overflow. \r
717 //\r
718 ASSERT (RealAllocationSize > AllocationSize); \r
719\r
720 RawAddress = InternalAllocatePool (PoolType, RealAllocationSize);\r
721 if (RawAddress == NULL) {\r
722 return NULL;\r
723 }\r
724 AlignedAddress = ((UINTN) RawAddress + OverAllocationSize) & ~AlignmentMask;\r
725 //\r
726 // Save the original memory address just before the aligned address.\r
727 //\r
728 FreePointer = (VOID **)(AlignedAddress - sizeof (RawAddress));\r
729 *FreePointer = RawAddress;\r
730\r
731 return (VOID *) AlignedAddress;\r
732}\r
733\r
734/**\r
735 Allocates a buffer of type EfiBootServicesData at a specified alignment.\r
736\r
737 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData with an\r
738 alignment specified by Alignment. The allocated buffer is returned. If AllocationSize is 0,\r
739 then a valid buffer of 0 size is returned. If there is not enough memory at the specified\r
740 alignment remaining to satisfy the request, then NULL is returned.\r
741 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
742\r
743 @param AllocationSize The number of bytes to allocate.\r
744 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
745 If Alignment is zero, then byte alignment is used.\r
746\r
747 @return A pointer to the allocated buffer or NULL if allocation fails.\r
748\r
749**/\r
750VOID *\r
751EFIAPI\r
752AllocateAlignedPool (\r
753 IN UINTN AllocationSize,\r
754 IN UINTN Alignment\r
755 )\r
756{\r
757 return InternalAllocateAlignedPool (EfiBootServicesData, AllocationSize, Alignment);\r
758}\r
759\r
760/**\r
761 Allocates a buffer of type EfiRuntimeServicesData at a specified alignment.\r
762\r
763 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData with an\r
764 alignment specified by Alignment. The allocated buffer is returned. If AllocationSize is 0,\r
765 then a valid buffer of 0 size is returned. If there is not enough memory at the specified\r
766 alignment remaining to satisfy the request, then NULL is returned.\r
767 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
768\r
769 @param AllocationSize The number of bytes to allocate.\r
770 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
771 If Alignment is zero, then byte alignment is used.\r
772\r
773 @return A pointer to the allocated buffer or NULL if allocation fails.\r
774\r
775**/\r
776VOID *\r
777EFIAPI\r
778AllocateAlignedRuntimePool (\r
779 IN UINTN AllocationSize,\r
780 IN UINTN Alignment\r
781 )\r
782{\r
783 return InternalAllocateAlignedPool (EfiRuntimeServicesData, AllocationSize, Alignment);\r
784}\r
785\r
786/**\r
787 Allocates a buffer of type EfieservedMemoryType at a specified alignment.\r
788\r
789 Allocates the number bytes specified by AllocationSize of type EfieservedMemoryType with an\r
790 alignment specified by Alignment. The allocated buffer is returned. If AllocationSize is 0,\r
791 then a valid buffer of 0 size is returned. If there is not enough memory at the specified\r
792 alignment remaining to satisfy the request, then NULL is returned.\r
793 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
794\r
795 @param AllocationSize The number of bytes to allocate.\r
796 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
797 If Alignment is zero, then byte alignment is used.\r
798\r
799 @return A pointer to the allocated buffer or NULL if allocation fails.\r
800\r
801**/\r
802VOID *\r
803EFIAPI\r
804AllocateAlignedReservedPool (\r
805 IN UINTN AllocationSize,\r
806 IN UINTN Alignment\r
807 )\r
808{\r
809 return InternalAllocateAlignedPool (EfiReservedMemoryType, AllocationSize, Alignment);\r
810}\r
811\r
812/**\r
813 Allocates and zeros a buffer of a certain pool type at a specified alignment.\r
814\r
815 Allocates the number bytes specified by AllocationSize of a certain pool type with an alignment\r
816 specified by Alignment, clears the buffer with zeros, and returns a pointer to the allocated\r
817 buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there is not\r
818 enough memory at the specified alignment remaining to satisfy the request, then NULL is returned.\r
819 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
820\r
821 @param PoolType The type of pool to allocate.\r
822 @param AllocationSize The number of bytes to allocate.\r
823 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
824 If Alignment is zero, then byte alignment is used.\r
825\r
826 @return A pointer to the allocated buffer or NULL if allocation fails.\r
827\r
828**/\r
829VOID *\r
830InternalAllocateAlignedZeroPool (\r
831 IN EFI_MEMORY_TYPE PoolType,\r
832 IN UINTN AllocationSize,\r
833 IN UINTN Alignment\r
834 )\r
835{\r
836 VOID *Memory;\r
837 Memory = InternalAllocateAlignedPool (PoolType, AllocationSize, Alignment);\r
838 if (Memory != NULL) {\r
839 Memory = ZeroMem (Memory, AllocationSize);\r
840 }\r
841 return Memory;\r
842}\r
843\r
844/**\r
845 Allocates and zeros a buffer of type EfiBootServicesData at a specified alignment.\r
846\r
847 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData with an\r
848 alignment specified by Alignment, clears the buffer with zeros, and returns a pointer to the\r
849 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there\r
850 is not enough memory at the specified alignment remaining to satisfy the request, then NULL is\r
851 returned.\r
852 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
853\r
854 @param AllocationSize The number of bytes to allocate.\r
855 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
856 If Alignment is zero, then byte alignment is used.\r
857\r
858 @return A pointer to the allocated buffer or NULL if allocation fails.\r
859\r
860**/\r
861VOID *\r
862EFIAPI\r
863AllocateAlignedZeroPool (\r
864 IN UINTN AllocationSize,\r
865 IN UINTN Alignment\r
866 )\r
867{\r
868 return InternalAllocateAlignedZeroPool (EfiBootServicesData, AllocationSize, Alignment);\r
869}\r
870\r
871/**\r
872 Allocates and zeros a buffer of type EfiRuntimeServicesData at a specified alignment.\r
873\r
874 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData with an\r
875 alignment specified by Alignment, clears the buffer with zeros, and returns a pointer to the\r
876 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there\r
877 is not enough memory at the specified alignment remaining to satisfy the request, then NULL is\r
878 returned.\r
879 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
880\r
881 @param AllocationSize The number of bytes to allocate.\r
882 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
883 If Alignment is zero, then byte alignment is used.\r
884\r
885 @return A pointer to the allocated buffer or NULL if allocation fails.\r
886\r
887**/\r
888VOID *\r
889EFIAPI\r
890AllocateAlignedRuntimeZeroPool (\r
891 IN UINTN AllocationSize,\r
892 IN UINTN Alignment\r
893 )\r
894{\r
895 return InternalAllocateAlignedZeroPool (EfiRuntimeServicesData, AllocationSize, Alignment);\r
896}\r
897\r
898/**\r
899 Allocates and zeros a buffer of type EfieservedMemoryType at a specified alignment.\r
900\r
901 Allocates the number bytes specified by AllocationSize of type EfieservedMemoryType with an\r
902 alignment specified by Alignment, clears the buffer with zeros, and returns a pointer to the\r
903 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there\r
904 is not enough memory at the specified alignment remaining to satisfy the request, then NULL is\r
905 returned.\r
906 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
907\r
908 @param AllocationSize The number of bytes to allocate.\r
909 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
910 If Alignment is zero, then byte alignment is used.\r
911\r
912 @return A pointer to the allocated buffer or NULL if allocation fails.\r
913\r
914**/\r
915VOID *\r
916EFIAPI\r
917AllocateAlignedReservedZeroPool (\r
918 IN UINTN AllocationSize,\r
919 IN UINTN Alignment\r
920 )\r
921{\r
922 return InternalAllocateAlignedZeroPool (EfiReservedMemoryType, AllocationSize, Alignment);\r
923}\r
924\r
925/**\r
926 Copies a buffer to an allocated buffer of a certain pool type at a specified alignment.\r
927\r
928 Allocates the number bytes specified by AllocationSize of a certain pool type with an alignment\r
929 specified by Alignment. The allocated buffer is returned. If AllocationSize is 0, then a valid\r
930 buffer of 0 size is returned. If there is not enough memory at the specified alignment remaining\r
931 to satisfy the request, then NULL is returned.\r
932 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
933\r
934 @param PoolType The type of pool to allocate.\r
935 @param AllocationSize The number of bytes to allocate.\r
936 @param Buffer The buffer to copy to the allocated buffer.\r
937 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
938 If Alignment is zero, then byte alignment is used.\r
939\r
940 @return A pointer to the allocated buffer or NULL if allocation fails.\r
941\r
942**/\r
943VOID *\r
944InternalAllocateAlignedCopyPool (\r
945 IN EFI_MEMORY_TYPE PoolType,\r
946 IN UINTN AllocationSize,\r
947 IN CONST VOID *Buffer,\r
948 IN UINTN Alignment\r
949 )\r
950{\r
951 VOID *Memory;\r
952 \r
953 ASSERT (Buffer != NULL);\r
954 ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN) Buffer + 1));\r
955\r
956 Memory = InternalAllocateAlignedPool (PoolType, AllocationSize, Alignment);\r
957 if (Memory != NULL) {\r
958 Memory = CopyMem (Memory, Buffer, AllocationSize);\r
959 }\r
960 return Memory;\r
961}\r
962\r
963/**\r
964 Copies a buffer to an allocated buffer of type EfiBootServicesData at a specified alignment.\r
965\r
966 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData type with an\r
967 alignment specified by Alignment. The allocated buffer is returned. If AllocationSize is 0,\r
968 then a valid buffer of 0 size is returned. If there is not enough memory at the specified\r
969 alignment remaining to satisfy the request, then NULL is returned.\r
970 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
971\r
972 @param AllocationSize The number of bytes to allocate.\r
973 @param Buffer The buffer to copy to the allocated buffer.\r
974 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
975 If Alignment is zero, then byte alignment is used.\r
976\r
977 @return A pointer to the allocated buffer or NULL if allocation fails.\r
978\r
979**/\r
980VOID *\r
981EFIAPI\r
982AllocateAlignedCopyPool (\r
983 IN UINTN AllocationSize,\r
984 IN CONST VOID *Buffer,\r
985 IN UINTN Alignment\r
986 )\r
987{\r
988 return InternalAllocateAlignedCopyPool (EfiBootServicesData, AllocationSize, Buffer, Alignment);\r
989}\r
990\r
991/**\r
992 Copies a buffer to an allocated buffer of type EfiRuntimeServicesData at a specified alignment.\r
993\r
994 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData type with an\r
995 alignment specified by Alignment. The allocated buffer is returned. If AllocationSize is 0,\r
996 then a valid buffer of 0 size is returned. If there is not enough memory at the specified\r
997 alignment remaining to satisfy the request, then NULL is returned.\r
998 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
999\r
1000 @param AllocationSize The number of bytes to allocate.\r
1001 @param Buffer The buffer to copy to the allocated buffer.\r
1002 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
1003 If Alignment is zero, then byte alignment is used.\r
1004\r
1005 @return A pointer to the allocated buffer or NULL if allocation fails.\r
1006\r
1007**/\r
1008VOID *\r
1009EFIAPI\r
1010AllocateAlignedRuntimeCopyPool (\r
1011 IN UINTN AllocationSize,\r
1012 IN CONST VOID *Buffer,\r
1013 IN UINTN Alignment\r
1014 )\r
1015{\r
1016 return InternalAllocateAlignedCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer, Alignment);\r
1017}\r
1018\r
1019/**\r
1020 Copies a buffer to an allocated buffer of type EfiReservedMemoryType at a specified alignment.\r
1021\r
1022 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType type with an\r
1023 alignment specified by Alignment. The allocated buffer is returned. If AllocationSize is 0,\r
1024 then a valid buffer of 0 size is returned. If there is not enough memory at the specified\r
1025 alignment remaining to satisfy the request, then NULL is returned.\r
1026 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
1027\r
1028 @param AllocationSize The number of bytes to allocate.\r
1029 @param Buffer The buffer to copy to the allocated buffer.\r
1030 @param Alignment The requested alignment of the allocation. Must be a power of two.\r
1031 If Alignment is zero, then byte alignment is used.\r
1032\r
1033 @return A pointer to the allocated buffer or NULL if allocation fails.\r
1034\r
1035**/\r
1036VOID *\r
1037EFIAPI\r
1038AllocateAlignedReservedCopyPool (\r
1039 IN UINTN AllocationSize,\r
1040 IN CONST VOID *Buffer,\r
1041 IN UINTN Alignment\r
1042 )\r
1043{\r
1044 return InternalAllocateAlignedCopyPool (EfiReservedMemoryType, AllocationSize, Buffer, Alignment);\r
1045}\r
1046\r
1047/**\r
1048 Frees a buffer that was previously allocated with one of the aligned pool allocation functions \r
1049 in the Memory Allocation Library.\r
1050\r
1051 Frees the buffer specified by Buffer. Buffer must have been allocated on a previous call to the\r
1052 aligned pool allocation services of the Memory Allocation Library.\r
1053 If Buffer was not allocated with an aligned pool allocation function in the Memory Allocation\r
1054 Library, then ASSERT().\r
1055\r
1056 @param Buffer Pointer to the buffer to free.\r
1057\r
1058**/\r
1059VOID\r
1060EFIAPI\r
1061FreeAlignedPool (\r
1062 IN VOID *Buffer\r
1063 )\r
1064{\r
1065 VOID *RawAddress;\r
1066 VOID **FreePointer;\r
1067 EFI_STATUS Status;\r
1068\r
1069 //\r
1070 // Get the pre-saved original address in the over-allocate pool.\r
1071 //\r
1072 FreePointer = (VOID **)((UINTN) Buffer - sizeof (RawAddress));\r
1073 RawAddress = *FreePointer;\r
1074\r
1075 Status = gBS->FreePool (RawAddress);\r
1076 ASSERT_EFI_ERROR (Status);\r
1077}\r