MemoryAllocationLib.c revision 8789c5e05f3ee45c7831d101caa157b11df3b43b
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**/
39VOID *
40InternalAllocatePages (
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**/
72VOID *
73EFIAPI
74AllocatePages (
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**/
94VOID *
95EFIAPI
96AllocateRuntimePages (
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**/
116VOID *
117EFIAPI
118AllocateReservedPages (
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**/
140VOID
141EFIAPI
142FreePages (
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**/
169VOID *
170InternalAllocateAlignedPages (
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**/
219VOID *
220EFIAPI
221AllocateAlignedPages (
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**/
245VOID *
246EFIAPI
247AllocateAlignedRuntimePages (
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**/
271VOID *
272EFIAPI
273AllocateAlignedReservedPages (
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**/
296VOID
297EFIAPI
298FreeAlignedPages (
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**/
321VOID *
322InternalAllocatePool (
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**/
347VOID *
348EFIAPI
349AllocatePool (
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**/
375VOID *
376EFIAPI
377AllocateRuntimePool (
378  IN UINTN  AllocationSize
379  )
380{
381  return InternalAllocatePool (EfiRuntimeServicesData, AllocationSize);
382}
383
384/**
385  Allocates a buffer of type EfiReservedMemoryType.
386
387  Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType 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**/
396VOID *
397EFIAPI
398AllocateReservedPool (
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**/
419VOID *
420InternalAllocateZeroPool (
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**/
447VOID *
448EFIAPI
449AllocateZeroPool (
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**/
475VOID *
476EFIAPI
477AllocateRuntimeZeroPool (
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**/
497VOID *
498EFIAPI
499AllocateReservedZeroPool (
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**/
523VOID *
524InternalAllocateCopyPool (
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**/
558VOID *
559EFIAPI
560AllocateCopyPool (
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**/
593VOID *
594EFIAPI
595AllocateRuntimeCopyPool (
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**/
619VOID *
620EFIAPI
621AllocateReservedCopyPool (
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**/
641VOID
642EFIAPI
643FreePool (
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