]> git.proxmox.com Git - mirror_edk2.git/blob - MdePkg/Library/UefiMemoryAllocationLib/MemoryAllocationLib.c
Remove SafeFreePool from MemoryAllocationLib as this API's name is misleading. Its...
[mirror_edk2.git] / MdePkg / Library / UefiMemoryAllocationLib / MemoryAllocationLib.c
1 /** @file
2 Support routines for memory allocation routines based
3 on boot services for Dxe phase drivers.
4
5 Copyright (c) 2006 - 2008, Intel Corporation<BR>
6 All rights reserved. This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16
17 #include <Uefi.h>
18
19
20 #include <Library/MemoryAllocationLib.h>
21 #include <Library/UefiBootServicesTableLib.h>
22 #include <Library/BaseMemoryLib.h>
23 #include <Library/DebugLib.h>
24
25 /**
26 Allocates one or more 4KB pages of a certain memory type.
27
28 Allocates the number of 4KB pages of a certain memory type and returns a pointer to the allocated
29 buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL is returned.
30 If there is not enough memory remaining to satisfy the request, then NULL is returned.
31
32 @param MemoryType The type of memory to allocate.
33 @param Pages The number of 4 KB pages to allocate.
34
35 @return A pointer to the allocated buffer or NULL if allocation fails.
36
37 **/
38 VOID *
39 InternalAllocatePages (
40 IN EFI_MEMORY_TYPE MemoryType,
41 IN UINTN Pages
42 )
43 {
44 EFI_STATUS Status;
45 EFI_PHYSICAL_ADDRESS Memory;
46
47 if (Pages == 0) {
48 return NULL;
49 }
50
51 Status = gBS->AllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory);
52 if (EFI_ERROR (Status)) {
53 return NULL;
54 }
55 return (VOID *) (UINTN) Memory;
56 }
57
58 /**
59 Allocates one or more 4KB pages of type EfiBootServicesData.
60
61 Allocates the number of 4KB pages of type EfiBootServicesData and returns a pointer to the
62 allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL
63 is returned. If there is not enough memory remaining to satisfy the request, then NULL is
64 returned.
65
66 @param Pages The number of 4 KB pages to allocate.
67
68 @return A pointer to the allocated buffer or NULL if allocation fails.
69
70 **/
71 VOID *
72 EFIAPI
73 AllocatePages (
74 IN UINTN Pages
75 )
76 {
77 return InternalAllocatePages (EfiBootServicesData, Pages);
78 }
79
80 /**
81 Allocates one or more 4KB pages of type EfiRuntimeServicesData.
82
83 Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer to the
84 allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL
85 is returned. If there is not enough memory remaining to satisfy the request, then NULL is
86 returned.
87
88 @param Pages The number of 4 KB pages to allocate.
89
90 @return A pointer to the allocated buffer or NULL if allocation fails.
91
92 **/
93 VOID *
94 EFIAPI
95 AllocateRuntimePages (
96 IN UINTN Pages
97 )
98 {
99 return InternalAllocatePages (EfiRuntimeServicesData, Pages);
100 }
101
102 /**
103 Allocates one or more 4KB pages of type EfiReservedMemoryType.
104
105 Allocates the number of 4KB pages of type EfiReservedMemoryType and returns a pointer to the
106 allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL
107 is returned. If there is not enough memory remaining to satisfy the request, then NULL is
108 returned.
109
110 @param Pages The number of 4 KB pages to allocate.
111
112 @return A pointer to the allocated buffer or NULL if allocation fails.
113
114 **/
115 VOID *
116 EFIAPI
117 AllocateReservedPages (
118 IN UINTN Pages
119 )
120 {
121 return InternalAllocatePages (EfiReservedMemoryType, Pages);
122 }
123
124 /**
125 Frees one or more 4KB pages that were previously allocated with one of the page allocation
126 functions in the Memory Allocation Library.
127
128 Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer
129 must have been allocated on a previous call to the page allocation services of the Memory
130 Allocation Library.
131 If Buffer was not allocated with a page allocation function in the Memory Allocation Library,
132 then ASSERT().
133 If Pages is zero, then ASSERT().
134
135 @param Buffer Pointer to the buffer of pages to free.
136 @param Pages The number of 4 KB pages to free.
137
138 **/
139 VOID
140 EFIAPI
141 FreePages (
142 IN VOID *Buffer,
143 IN UINTN Pages
144 )
145 {
146 EFI_STATUS Status;
147
148 ASSERT (Pages != 0);
149 Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);
150 ASSERT_EFI_ERROR (Status);
151 }
152
153 /**
154 Allocates one or more 4KB pages of a certain memory type at a specified alignment.
155
156 Allocates the number of 4KB pages specified by Pages of a certain memory type with an alignment
157 specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is returned.
158 If there is not enough memory at the specified alignment remaining to satisfy the request, then
159 NULL is returned.
160 If Alignment is not a power of two and Alignment is not zero, then ASSERT().
161
162 @param MemoryType The type of memory to allocate.
163 @param Pages The number of 4 KB pages to allocate.
164 @param Alignment The requested alignment of the allocation. Must be a power of two.
165 If Alignment is zero, then byte alignment is used.
166
167 @return A pointer to the allocated buffer or NULL if allocation fails.
168
169 **/
170 VOID *
171 InternalAllocateAlignedPages (
172 IN EFI_MEMORY_TYPE MemoryType,
173 IN UINTN Pages,
174 IN UINTN Alignment
175 )
176 {
177 EFI_STATUS Status;
178 EFI_PHYSICAL_ADDRESS Memory;
179 UINTN AlignedMemory;
180 UINTN AlignmentMask;
181 UINTN UnalignedPages;
182 UINTN RealPages;
183
184 //
185 // Alignment must be a power of two or zero.
186 //
187 ASSERT ((Alignment & (Alignment - 1)) == 0);
188
189 if (Pages == 0) {
190 return NULL;
191 }
192 if (Alignment > EFI_PAGE_SIZE) {
193 //
194 // Caculate the total number of pages since alignment is larger than page size.
195 //
196 AlignmentMask = Alignment - 1;
197 RealPages = Pages + EFI_SIZE_TO_PAGES (Alignment);
198 //
199 // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.
200 //
201 ASSERT (RealPages > Pages);
202
203 Status = gBS->AllocatePages (AllocateAnyPages, MemoryType, RealPages, &Memory);
204 if (EFI_ERROR (Status)) {
205 return NULL;
206 }
207 AlignedMemory = ((UINTN) Memory + AlignmentMask) & ~AlignmentMask;
208 UnalignedPages = EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN) Memory);
209 if (UnalignedPages > 0) {
210 //
211 // Free first unaligned page(s).
212 //
213 Status = gBS->FreePages (Memory, UnalignedPages);
214 ASSERT_EFI_ERROR (Status);
215 }
216 Memory = (EFI_PHYSICAL_ADDRESS) (AlignedMemory + EFI_PAGES_TO_SIZE (Pages));
217 UnalignedPages = RealPages - Pages - UnalignedPages;
218 if (UnalignedPages > 0) {
219 //
220 // Free last unaligned page(s).
221 //
222 Status = gBS->FreePages (Memory, UnalignedPages);
223 ASSERT_EFI_ERROR (Status);
224 }
225 } else {
226 //
227 // Do not over-allocate pages in this case.
228 //
229 Status = gBS->AllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory);
230 if (EFI_ERROR (Status)) {
231 return NULL;
232 }
233 AlignedMemory = (UINTN) Memory;
234 }
235 return (VOID *) AlignedMemory;
236 }
237
238 /**
239 Allocates one or more 4KB pages of type EfiBootServicesData at a specified alignment.
240
241 Allocates the number of 4KB pages specified by Pages of type EfiBootServicesData with an
242 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is
243 returned. If there is not enough memory at the specified alignment remaining to satisfy the
244 request, then NULL is returned.
245 If Alignment is not a power of two and Alignment is not zero, then ASSERT().
246
247 @param Pages The number of 4 KB pages to allocate.
248 @param Alignment The requested alignment of the allocation. Must be a power of two.
249 If Alignment is zero, then byte alignment is used.
250
251 @return A pointer to the allocated buffer or NULL if allocation fails.
252
253 **/
254 VOID *
255 EFIAPI
256 AllocateAlignedPages (
257 IN UINTN Pages,
258 IN UINTN Alignment
259 )
260 {
261 return InternalAllocateAlignedPages (EfiBootServicesData, Pages, Alignment);
262 }
263
264 /**
265 Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment.
266
267 Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData with an
268 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is
269 returned. If there is not enough memory at the specified alignment remaining to satisfy the
270 request, then NULL is returned.
271 If Alignment is not a power of two and Alignment is not zero, then ASSERT().
272
273 @param Pages The number of 4 KB pages to allocate.
274 @param Alignment The requested alignment of the allocation. Must be a power of two.
275 If Alignment is zero, then byte alignment is used.
276
277 @return A pointer to the allocated buffer or NULL if allocation fails.
278
279 **/
280 VOID *
281 EFIAPI
282 AllocateAlignedRuntimePages (
283 IN UINTN Pages,
284 IN UINTN Alignment
285 )
286 {
287 return InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment);
288 }
289
290 /**
291 Allocates one or more 4KB pages of type EfiReservedMemoryType at a specified alignment.
292
293 Allocates the number of 4KB pages specified by Pages of type EfiReservedMemoryType with an
294 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is
295 returned. If there is not enough memory at the specified alignment remaining to satisfy the
296 request, then NULL is returned.
297 If Alignment is not a power of two and Alignment is not zero, then ASSERT().
298
299 @param Pages The number of 4 KB pages to allocate.
300 @param Alignment The requested alignment of the allocation. Must be a power of two.
301 If Alignment is zero, then byte alignment is used.
302
303 @return A pointer to the allocated buffer or NULL if allocation fails.
304
305 **/
306 VOID *
307 EFIAPI
308 AllocateAlignedReservedPages (
309 IN UINTN Pages,
310 IN UINTN Alignment
311 )
312 {
313 return InternalAllocateAlignedPages (EfiReservedMemoryType, Pages, Alignment);
314 }
315
316 /**
317 Frees one or more 4KB pages that were previously allocated with one of the aligned page
318 allocation functions in the Memory Allocation Library.
319
320 Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer
321 must have been allocated on a previous call to the aligned page allocation services of the Memory
322 Allocation Library.
323 If Buffer was not allocated with an aligned page allocation function in the Memory Allocation
324 Library, then ASSERT().
325 If Pages is zero, then ASSERT().
326
327 @param Buffer Pointer to the buffer of pages to free.
328 @param Pages The number of 4 KB pages to free.
329
330 **/
331 VOID
332 EFIAPI
333 FreeAlignedPages (
334 IN VOID *Buffer,
335 IN UINTN Pages
336 )
337 {
338 EFI_STATUS Status;
339
340 ASSERT (Pages != 0);
341 Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);
342 ASSERT_EFI_ERROR (Status);
343 }
344
345 /**
346 Allocates a buffer of a certain pool type.
347
348 Allocates the number bytes specified by AllocationSize of a certain pool type and returns a
349 pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is
350 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.
351
352 @param MemoryType The type of memory to allocate.
353 @param AllocationSize The number of bytes to allocate.
354
355 @return A pointer to the allocated buffer or NULL if allocation fails.
356
357 **/
358 VOID *
359 InternalAllocatePool (
360 IN EFI_MEMORY_TYPE MemoryType,
361 IN UINTN AllocationSize
362 )
363 {
364 EFI_STATUS Status;
365 VOID *Memory;
366
367 Status = gBS->AllocatePool (MemoryType, AllocationSize, &Memory);
368 if (EFI_ERROR (Status)) {
369 Memory = NULL;
370 }
371 return Memory;
372 }
373
374 /**
375 Allocates a buffer of type EfiBootServicesData.
376
377 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData and returns a
378 pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is
379 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.
380
381 @param AllocationSize The number of bytes to allocate.
382
383 @return A pointer to the allocated buffer or NULL if allocation fails.
384
385 **/
386 VOID *
387 EFIAPI
388 AllocatePool (
389 IN UINTN AllocationSize
390 )
391 {
392 return InternalAllocatePool (EfiBootServicesData, AllocationSize);
393 }
394
395 /**
396 Allocates a buffer of type EfiRuntimeServicesData.
397
398 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData and returns
399 a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is
400 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.
401
402 @param AllocationSize The number of bytes to allocate.
403
404 @return A pointer to the allocated buffer or NULL if allocation fails.
405
406 **/
407 VOID *
408 EFIAPI
409 AllocateRuntimePool (
410 IN UINTN AllocationSize
411 )
412 {
413 return InternalAllocatePool (EfiRuntimeServicesData, AllocationSize);
414 }
415
416 /**
417 Allocates a buffer of type EfieservedMemoryType.
418
419 Allocates the number bytes specified by AllocationSize of type EfieservedMemoryType and returns
420 a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is
421 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.
422
423 @param AllocationSize The number of bytes to allocate.
424
425 @return A pointer to the allocated buffer or NULL if allocation fails.
426
427 **/
428 VOID *
429 EFIAPI
430 AllocateReservedPool (
431 IN UINTN AllocationSize
432 )
433 {
434 return InternalAllocatePool (EfiReservedMemoryType, AllocationSize);
435 }
436
437 /**
438 Allocates and zeros a buffer of a certian pool type.
439
440 Allocates the number bytes specified by AllocationSize of a certian pool type, clears the buffer
441 with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a valid
442 buffer of 0 size is returned. If there is not enough memory remaining to satisfy the request,
443 then NULL is returned.
444
445 @param PoolType The type of memory to allocate.
446 @param AllocationSize The number of bytes to allocate and zero.
447
448 @return A pointer to the allocated buffer or NULL if allocation fails.
449
450 **/
451 VOID *
452 InternalAllocateZeroPool (
453 IN EFI_MEMORY_TYPE PoolType,
454 IN UINTN AllocationSize
455 )
456 {
457 VOID *Memory;
458
459 Memory = InternalAllocatePool (PoolType, AllocationSize);
460 if (Memory != NULL) {
461 Memory = ZeroMem (Memory, AllocationSize);
462 }
463 return Memory;
464 }
465
466 /**
467 Allocates and zeros a buffer of type EfiBootServicesData.
468
469 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, clears the
470 buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a
471 valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the
472 request, then NULL is returned.
473
474 @param AllocationSize The number of bytes to allocate and zero.
475
476 @return A pointer to the allocated buffer or NULL if allocation fails.
477
478 **/
479 VOID *
480 EFIAPI
481 AllocateZeroPool (
482 IN UINTN AllocationSize
483 )
484 {
485 return InternalAllocateZeroPool (EfiBootServicesData, AllocationSize);
486 }
487
488 /**
489 Allocates and zeros a buffer of type EfiRuntimeServicesData.
490
491 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, clears the
492 buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a
493 valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the
494 request, then NULL is returned.
495
496 @param AllocationSize The number of bytes to allocate and zero.
497
498 @return A pointer to the allocated buffer or NULL if allocation fails.
499
500 **/
501 VOID *
502 EFIAPI
503 AllocateRuntimeZeroPool (
504 IN UINTN AllocationSize
505 )
506 {
507 return InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize);
508 }
509
510 /**
511 Allocates and zeros a buffer of type EfiReservedMemoryType.
512
513 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, clears the
514 buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a
515 valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the
516 request, then NULL is returned.
517
518 @param AllocationSize The number of bytes to allocate and zero.
519
520 @return A pointer to the allocated buffer or NULL if allocation fails.
521
522 **/
523 VOID *
524 EFIAPI
525 AllocateReservedZeroPool (
526 IN UINTN AllocationSize
527 )
528 {
529 return InternalAllocateZeroPool (EfiReservedMemoryType, AllocationSize);
530 }
531
532 /**
533 Copies a buffer to an allocated buffer of a certian pool type.
534
535 Allocates the number bytes specified by AllocationSize of a certian pool type, copies
536 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
537 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there
538 is not enough memory remaining to satisfy the request, then NULL is returned.
539 If Buffer is NULL, then ASSERT().
540 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
541
542 @param PoolType The type of pool to allocate.
543 @param AllocationSize The number of bytes to allocate and zero.
544 @param Buffer The buffer to copy to the allocated buffer.
545
546 @return A pointer to the allocated buffer or NULL if allocation fails.
547
548 **/
549 VOID *
550 InternalAllocateCopyPool (
551 IN EFI_MEMORY_TYPE PoolType,
552 IN UINTN AllocationSize,
553 IN CONST VOID *Buffer
554 )
555 {
556 VOID *Memory;
557
558 ASSERT (Buffer != NULL);
559 ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN) Buffer + 1));
560
561 Memory = InternalAllocatePool (PoolType, AllocationSize);
562 if (Memory != NULL) {
563 Memory = CopyMem (Memory, Buffer, AllocationSize);
564 }
565 return Memory;
566 }
567
568 /**
569 Copies a buffer to an allocated buffer of type EfiBootServicesData.
570
571 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, copies
572 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
573 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there
574 is not enough memory remaining to satisfy the request, then NULL is returned.
575 If Buffer is NULL, then ASSERT().
576 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
577
578 @param AllocationSize The number of bytes to allocate and zero.
579 @param Buffer The buffer to copy to the allocated buffer.
580
581 @return A pointer to the allocated buffer or NULL if allocation fails.
582
583 **/
584 VOID *
585 EFIAPI
586 AllocateCopyPool (
587 IN UINTN AllocationSize,
588 IN CONST VOID *Buffer
589 )
590 {
591 return InternalAllocateCopyPool (EfiBootServicesData, AllocationSize, Buffer);
592 }
593
594 /**
595 Copies a buffer to an allocated buffer of type EfiRuntimeServicesData.
596
597 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, copies
598 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
599 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there
600 is not enough memory remaining to satisfy the request, then NULL is returned.
601 If Buffer is NULL, then ASSERT().
602 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
603
604 @param AllocationSize The number of bytes to allocate and zero.
605 @param Buffer The buffer to copy to the allocated buffer.
606
607 @return A pointer to the allocated buffer or NULL if allocation fails.
608
609 **/
610 VOID *
611 EFIAPI
612 AllocateRuntimeCopyPool (
613 IN UINTN AllocationSize,
614 IN CONST VOID *Buffer
615 )
616 {
617 return InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer);
618 }
619
620 /**
621 Copies a buffer to an allocated buffer of type EfiReservedMemoryType.
622
623 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, copies
624 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
625 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there
626 is not enough memory remaining to satisfy the request, then NULL is returned.
627 If Buffer is NULL, then ASSERT().
628 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
629
630 @param AllocationSize The number of bytes to allocate and zero.
631 @param Buffer The buffer to copy to the allocated buffer.
632
633 @return A pointer to the allocated buffer or NULL if allocation fails.
634
635 **/
636 VOID *
637 EFIAPI
638 AllocateReservedCopyPool (
639 IN UINTN AllocationSize,
640 IN CONST VOID *Buffer
641 )
642 {
643 return InternalAllocateCopyPool (EfiReservedMemoryType, AllocationSize, Buffer);
644 }
645
646 /**
647 Frees a buffer that was previously allocated with one of the pool allocation functions in the
648 Memory Allocation Library.
649
650 Frees the buffer specified by Buffer. Buffer must have been allocated on a previous call to the
651 pool allocation services of the Memory Allocation Library.
652 If Buffer was not allocated with a pool allocation function in the Memory Allocation Library,
653 then ASSERT().
654
655 @param Buffer Pointer to the buffer to free.
656
657 **/
658 VOID
659 EFIAPI
660 FreePool (
661 IN VOID *Buffer
662 )
663 {
664 EFI_STATUS Status;
665
666 Status = gBS->FreePool (Buffer);
667 ASSERT_EFI_ERROR (Status);
668 }
669