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