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