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