]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/PeiMemoryAllocationLib/MemoryAllocationLib.c
Only reserve the aligned memory instead of reserving the unaligned memory in PeiMemor...
[mirror_edk2.git] / MdePkg / Library / PeiMemoryAllocationLib / MemoryAllocationLib.c
CommitLineData
e386b444 1/** @file\r
9e6fa6d2
LG
2 Support routines for memory allocation routines \r
3 based on PeiService for PEI phase drivers.\r
e386b444 4\r
6809c872 5 Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>\r
19388d29 6 This program and the accompanying materials \r
e386b444 7 are licensed and made available under the terms and conditions of the BSD License \r
8 which accompanies this distribution. The full text of the license may be found at \r
2fc59a00 9 http://opensource.org/licenses/bsd-license.php. \r
e386b444 10\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
13\r
e386b444 14**/\r
15\r
c892d846 16\r
c7d265a9 17#include <PiPei.h>\r
c892d846 18\r
19\r
c7d265a9 20#include <Library/MemoryAllocationLib.h>\r
1c280088 21#include <Library/PeiServicesLib.h>\r
c7d265a9 22#include <Library/BaseMemoryLib.h>\r
23#include <Library/DebugLib.h>\r
1dde8b08 24#include <Library/HobLib.h>\r
e386b444 25\r
e386b444 26\r
27/**\r
28 Allocates one or more 4KB pages of a certain memory type.\r
29\r
30 Allocates the number of 4KB pages of a certain memory type and returns a pointer to the allocated\r
31 buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL is returned.\r
32 If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
33\r
34 @param MemoryType The type of memory to allocate.\r
35 @param Pages The number of 4 KB pages to allocate.\r
36\r
37 @return A pointer to the allocated buffer or NULL if allocation fails.\r
38\r
39**/\r
40VOID *\r
41InternalAllocatePages (\r
42 IN EFI_MEMORY_TYPE MemoryType, \r
43 IN UINTN Pages\r
44 )\r
45{\r
46 EFI_STATUS Status;\r
47 EFI_PHYSICAL_ADDRESS Memory; \r
1dde8b08
LG
48 EFI_MEMORY_TYPE RequestType;\r
49 EFI_PEI_HOB_POINTERS Hob;\r
e386b444 50\r
51 if (Pages == 0) {\r
52 return NULL;\r
53 }\r
54\r
1dde8b08
LG
55 RequestType = MemoryType;\r
56 if (MemoryType == EfiReservedMemoryType) {\r
57 //\r
58 // PEI AllocatePages() doesn't support EfiReservedMemoryType. \r
59 // Change RequestType to EfiBootServicesData for memory allocation.\r
60 //\r
61 RequestType = EfiBootServicesData;\r
62 }\r
63\r
64 Status = PeiServicesAllocatePages (RequestType, Pages, &Memory);\r
e386b444 65 if (EFI_ERROR (Status)) {\r
9e6fa6d2 66 return NULL;\r
e386b444 67 }\r
1dde8b08
LG
68 \r
69 if (MemoryType == EfiReservedMemoryType) {\r
70 //\r
71 // Memory type needs to be updated to EfiReservedMemoryType. Per PI spec Volume 1, \r
72 // PEI AllocatePages() will automate the creation of the Memory Allocation HOB types. \r
73 // Search Memory Allocation HOB and find the matched memory region,\r
74 // then change its memory type to EfiReservedMemoryType.\r
75 //\r
76 Hob.Raw = GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION);\r
77 while (Hob.Raw != NULL && Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress != Memory) {\r
78 Hob.Raw = GET_NEXT_HOB (Hob);\r
79 Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw);\r
80 }\r
81 ASSERT (Hob.Raw != NULL);\r
82 Hob.MemoryAllocation->AllocDescriptor.MemoryType = EfiReservedMemoryType;\r
83 }\r
84\r
e386b444 85 return (VOID *) (UINTN) Memory;\r
86}\r
87\r
88/**\r
89 Allocates one or more 4KB pages of type EfiBootServicesData.\r
90\r
91 Allocates the number of 4KB pages of type EfiBootServicesData and returns a pointer to the\r
92 allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL\r
93 is returned. If there is not enough memory remaining to satisfy the request, then NULL is\r
94 returned.\r
95\r
96 @param Pages The number of 4 KB pages to allocate.\r
97\r
98 @return A pointer to the allocated buffer or NULL if allocation fails.\r
99\r
100**/\r
101VOID *\r
102EFIAPI\r
103AllocatePages (\r
104 IN UINTN Pages\r
105 )\r
106{\r
107 return InternalAllocatePages (EfiBootServicesData, Pages);\r
108}\r
109\r
110/**\r
111 Allocates one or more 4KB pages of type EfiRuntimeServicesData.\r
112\r
113 Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer to the\r
114 allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL\r
115 is returned. If there is not enough memory remaining to satisfy the request, then NULL is\r
116 returned.\r
117\r
118 @param Pages The number of 4 KB pages to allocate.\r
119\r
120 @return A pointer to the allocated buffer or NULL if allocation fails.\r
121\r
122**/\r
123VOID *\r
124EFIAPI\r
125AllocateRuntimePages (\r
126 IN UINTN Pages\r
127 )\r
128{\r
129 return InternalAllocatePages (EfiRuntimeServicesData, Pages);\r
130}\r
131\r
132/**\r
133 Allocates one or more 4KB pages of type EfiReservedMemoryType.\r
134\r
135 Allocates the number of 4KB pages of type EfiReservedMemoryType and returns a pointer to the\r
136 allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL\r
137 is returned. If there is not enough memory remaining to satisfy the request, then NULL is\r
138 returned.\r
139\r
140 @param Pages The number of 4 KB pages to allocate.\r
141\r
142 @return A pointer to the allocated buffer or NULL if allocation fails.\r
143\r
144**/\r
145VOID *\r
146EFIAPI\r
147AllocateReservedPages (\r
148 IN UINTN Pages\r
149 )\r
150{\r
151 return InternalAllocatePages (EfiReservedMemoryType, Pages);\r
152}\r
153\r
154/**\r
155 Frees one or more 4KB pages that were previously allocated with one of the page allocation\r
156 functions in the Memory Allocation Library.\r
157\r
158 Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer\r
159 must have been allocated on a previous call to the page allocation services of the Memory\r
6e10b70a 160 Allocation Library. If it is not possible to free allocated pages, then this function will\r
446b94b0 161 perform no actions.\r
9638ba6d 162 \r
e386b444 163 If Buffer was not allocated with a page allocation function in the Memory Allocation Library,\r
164 then ASSERT().\r
165 If Pages is zero, then ASSERT().\r
166 \r
2fc59a00 167 @param Buffer The pointer to the buffer of pages to free.\r
e386b444 168 @param Pages The number of 4 KB pages to free.\r
169\r
170**/\r
171VOID\r
172EFIAPI\r
173FreePages (\r
174 IN VOID *Buffer,\r
175 IN UINTN Pages\r
176 )\r
177{\r
6e10b70a 178 ASSERT (Pages != 0);\r
e386b444 179 //\r
180 // PEI phase does not support to free pages, so leave it as NOP.\r
181 //\r
182}\r
183\r
184/**\r
185 Allocates one or more 4KB pages of a certain memory type at a specified alignment.\r
186\r
187 Allocates the number of 4KB pages specified by Pages of a certain memory type with an alignment\r
188 specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is returned.\r
189 If there is not enough memory at the specified alignment remaining to satisfy the request, then\r
190 NULL is returned.\r
191 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
1346352d 192 If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().\r
e386b444 193\r
194 @param MemoryType The type of memory to allocate.\r
195 @param Pages The number of 4 KB pages to allocate.\r
58380e9c 196 @param Alignment The requested alignment of the allocation. \r
197 Must be a power of two.\r
e386b444 198 If Alignment is zero, then byte alignment is used.\r
199\r
200 @return A pointer to the allocated buffer or NULL if allocation fails.\r
201\r
202**/\r
203VOID *\r
204InternalAllocateAlignedPages (\r
205 IN EFI_MEMORY_TYPE MemoryType, \r
206 IN UINTN Pages,\r
207 IN UINTN Alignment\r
208 )\r
209{\r
6809c872
LG
210 EFI_PHYSICAL_ADDRESS Memory;\r
211 EFI_PHYSICAL_ADDRESS AlignedMemory;\r
212 EFI_PEI_HOB_POINTERS Hob;\r
213 BOOLEAN SkipBeforeMemHob = FALSE;\r
214 BOOLEAN SkipAfterMemHob = FALSE;\r
215 EFI_PHYSICAL_ADDRESS HobBaseAddress;\r
216 UINT64 HobLength;\r
217 EFI_MEMORY_TYPE HobMemoryType;\r
218 UINTN TotalPages;\r
e386b444 219\r
220 //\r
221 // Alignment must be a power of two or zero.\r
222 //\r
223 ASSERT ((Alignment & (Alignment - 1)) == 0);\r
224\r
225 if (Pages == 0) {\r
226 return NULL;\r
227 }\r
228 //\r
229 // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.\r
230 //\r
6809c872
LG
231 ASSERT (Pages <= (MAX_ADDRESS - EFI_SIZE_TO_PAGES (Alignment))); \r
232\r
e386b444 233 //\r
234 // We would rather waste some memory to save PEI code size.\r
6809c872
LG
235 // meaning in addition to the requested size for the aligned mem,\r
236 // we simply reserve an overhead memory equal to Alignmemt(page-aligned), no matter what.\r
237 // The overhead mem size could be reduced later with more involved malloc mechanisms\r
238 // (e.g., somthing that can detect the alignment boundary before allocating memory or \r
239 // can request that memory be allocated at a certain address that is aleady aligned).\r
240 //\r
241 TotalPages = Pages + (Alignment <= EFI_PAGE_SIZE ? 0 : EFI_SIZE_TO_PAGES(Alignment));\r
242 Memory = (EFI_PHYSICAL_ADDRESS) (UINTN) InternalAllocatePages (MemoryType, TotalPages);\r
243 if (Memory == 0) {\r
244 DEBUG((DEBUG_INFO, "Out of memory resource! \n"));\r
245 return NULL;\r
246 }\r
247 DEBUG ((DEBUG_INFO, "Allocated Memory unaligned: Address = 0x%LX, Pages = 0x%X, Type = %d \n", Memory, TotalPages, (UINTN) MemoryType));\r
248\r
249 //\r
250 // Alignment calculation\r
251 //\r
252 AlignedMemory = Memory;\r
253 if (Alignment > EFI_PAGE_SIZE) {\r
254 AlignedMemory = ALIGN_VALUE (Memory, Alignment);\r
255 }\r
256 DEBUG ((DEBUG_INFO, "After aligning to 0x%X bytes: Address = 0x%LX, Pages = 0x%X \n", Alignment, AlignedMemory, Pages));\r
257\r
258 //\r
259 // In general three HOBs cover the total allocated space.\r
260 // The aligned portion is covered by the aligned mem HOB and\r
261 // the unaligned(to be freed) portions before and after the aligned portion are covered by newly created HOBs.\r
e386b444 262 //\r
6809c872
LG
263 // Before mem HOB covers the region between "Memory" and "AlignedMemory"\r
264 // Aligned mem HOB covers the region between "AlignedMemory" and "AlignedMemory + EFI_PAGES_TO_SIZE(Pages)"\r
265 // After mem HOB covers the region between "AlignedMemory + EFI_PAGES_TO_SIZE(Pages)" and "Memory + EFI_PAGES_TO_SIZE(TotalPages)"\r
266 //\r
267 // The before or after mem HOBs need to be skipped under special cases where the aligned portion\r
268 // touches either the top or bottom of the original allocated space.\r
269 //\r
270 if (Memory == AlignedMemory) {\r
271 SkipBeforeMemHob = TRUE;\r
272 }\r
273 if ((Memory + EFI_PAGES_TO_SIZE(TotalPages)) == (AlignedMemory + EFI_PAGES_TO_SIZE(Pages))) {\r
274 //\r
275 // This condition is never met in the current implementation.\r
276 // There is always some after-mem since the overhead mem(used in TotalPages)\r
277 // is no less than Alignment.\r
278 //\r
279 SkipAfterMemHob = TRUE;\r
280 }\r
281\r
282 // \r
283 // Search for the mem HOB referring to the original(unaligned) allocation \r
284 // and update the size and type if needed.\r
285 //\r
286 Hob.Raw = GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION);\r
287 while (Hob.Raw != NULL) {\r
288 if (Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress == Memory) {\r
289 break;\r
290 }\r
291 Hob.Raw = GET_NEXT_HOB (Hob);\r
292 Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw);\r
293 }\r
294 ASSERT (Hob.Raw != NULL);\r
295 if (SkipBeforeMemHob) {\r
296 //\r
297 // Use this HOB as aligned mem HOB as there is no portion before it.\r
298 //\r
299 HobLength = EFI_PAGES_TO_SIZE(Pages);\r
300 Hob.MemoryAllocation->AllocDescriptor.MemoryLength = HobLength;\r
301 } else {\r
302 //\r
303 // Use this HOB as before mem HOB and create a new HOB for the aligned portion \r
304 //\r
305 HobLength = (AlignedMemory - Memory); \r
306 Hob.MemoryAllocation->AllocDescriptor.MemoryLength = HobLength;\r
307 Hob.MemoryAllocation->AllocDescriptor.MemoryType = EfiConventionalMemory;\r
308 }\r
309\r
310 HobBaseAddress = Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress;\r
311 HobMemoryType = Hob.MemoryAllocation->AllocDescriptor.MemoryType;\r
312\r
313 //\r
314 // Build the aligned mem HOB if needed\r
315 //\r
316 if (!SkipBeforeMemHob) {\r
317 DEBUG((DEBUG_INFO, "Updated before-mem HOB with BaseAddress = %LX, Length = %LX, MemoryType = %d \n",\r
318 HobBaseAddress, HobLength, (UINTN) HobMemoryType));\r
319\r
320 HobBaseAddress = AlignedMemory;\r
321 HobLength = EFI_PAGES_TO_SIZE(Pages);\r
322 HobMemoryType = MemoryType;\r
323\r
324 BuildMemoryAllocationHob (\r
325 HobBaseAddress,\r
326 HobLength,\r
327 HobMemoryType\r
328 );\r
329\r
330 DEBUG((DEBUG_INFO, "Created aligned-mem HOB with BaseAddress = %LX, Length = %LX, MemoryType = %d \n",\r
331 HobBaseAddress, HobLength, (UINTN) HobMemoryType));\r
e386b444 332 } else {\r
6809c872
LG
333 if (HobBaseAddress != 0) {\r
334 DEBUG((DEBUG_INFO, "Updated aligned-mem HOB with BaseAddress = %LX, Length = %LX, MemoryType = %d \n",\r
335 HobBaseAddress, HobLength, (UINTN) HobMemoryType));\r
336 }\r
e386b444 337 }\r
6809c872
LG
338\r
339\r
340 //\r
341 // Build the after mem HOB if needed\r
342 //\r
343 if (!SkipAfterMemHob) {\r
344 HobBaseAddress = AlignedMemory + EFI_PAGES_TO_SIZE(Pages);\r
345 HobLength = (Memory + EFI_PAGES_TO_SIZE(TotalPages)) - (AlignedMemory + EFI_PAGES_TO_SIZE(Pages));\r
346 HobMemoryType = EfiConventionalMemory;\r
347\r
348 BuildMemoryAllocationHob (\r
349 HobBaseAddress,\r
350 HobLength,\r
351 HobMemoryType\r
352 );\r
353\r
354 DEBUG((DEBUG_INFO, "Created after-mem HOB with BaseAddress = %LX, Length = %LX, MemoryType = %d \n",\r
355 HobBaseAddress, HobLength, (UINTN) HobMemoryType));\r
356 }\r
357\r
358 return (VOID *) (UINTN) AlignedMemory;\r
e386b444 359}\r
360\r
361/**\r
362 Allocates one or more 4KB pages of type EfiBootServicesData at a specified alignment.\r
363\r
364 Allocates the number of 4KB pages specified by Pages of type EfiBootServicesData with an\r
365 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is\r
366 returned. If there is not enough memory at the specified alignment remaining to satisfy the\r
367 request, then NULL is returned.\r
9638ba6d 368 \r
e386b444 369 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
1346352d 370 If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().\r
e386b444 371\r
372 @param Pages The number of 4 KB pages to allocate.\r
58380e9c 373 @param Alignment The requested alignment of the allocation. \r
374 Must be a power of two.\r
e386b444 375 If Alignment is zero, then byte alignment is used.\r
376\r
377 @return A pointer to the allocated buffer or NULL if allocation fails.\r
378\r
379**/\r
380VOID *\r
381EFIAPI\r
382AllocateAlignedPages (\r
383 IN UINTN Pages,\r
384 IN UINTN Alignment\r
385 )\r
386{\r
387 return InternalAllocateAlignedPages (EfiBootServicesData, Pages, Alignment);\r
388}\r
389\r
390/**\r
391 Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment.\r
392\r
393 Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData with an\r
394 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is\r
395 returned. If there is not enough memory at the specified alignment remaining to satisfy the\r
396 request, then NULL is returned.\r
9638ba6d 397 \r
e386b444 398 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
1346352d 399 If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().\r
e386b444 400\r
401 @param Pages The number of 4 KB pages to allocate.\r
58380e9c 402 @param Alignment The requested alignment of the allocation. \r
403 Must be a power of two.\r
e386b444 404 If Alignment is zero, then byte alignment is used.\r
405\r
406 @return A pointer to the allocated buffer or NULL if allocation fails.\r
407\r
408**/\r
409VOID *\r
410EFIAPI\r
411AllocateAlignedRuntimePages (\r
412 IN UINTN Pages,\r
413 IN UINTN Alignment\r
414 )\r
415{\r
416 return InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment);\r
417}\r
418\r
419/**\r
420 Allocates one or more 4KB pages of type EfiReservedMemoryType at a specified alignment.\r
421\r
422 Allocates the number of 4KB pages specified by Pages of type EfiReservedMemoryType with an\r
423 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is\r
424 returned. If there is not enough memory at the specified alignment remaining to satisfy the\r
425 request, then NULL is returned.\r
9638ba6d 426 \r
e386b444 427 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
1346352d 428 If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().\r
e386b444 429\r
430 @param Pages The number of 4 KB pages to allocate.\r
58380e9c 431 @param Alignment The requested alignment of the allocation. \r
432 Must be a power of two.\r
e386b444 433 If Alignment is zero, then byte alignment is used.\r
434\r
435 @return A pointer to the allocated buffer or NULL if allocation fails.\r
436\r
437**/\r
438VOID *\r
439EFIAPI\r
440AllocateAlignedReservedPages (\r
441 IN UINTN Pages,\r
442 IN UINTN Alignment\r
443 )\r
444{\r
445 return InternalAllocateAlignedPages (EfiReservedMemoryType, Pages, Alignment);\r
446}\r
447\r
448/**\r
449 Frees one or more 4KB pages that were previously allocated with one of the aligned page\r
450 allocation functions in the Memory Allocation Library.\r
451\r
452 Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer\r
453 must have been allocated on a previous call to the aligned page allocation services of the Memory\r
6e10b70a 454 Allocation Library. If it is not possible to free allocated pages, then this function will \r
446b94b0 455 perform no actions.\r
9638ba6d 456 \r
e386b444 457 If Buffer was not allocated with an aligned page allocation function in the Memory Allocation\r
458 Library, then ASSERT().\r
459 If Pages is zero, then ASSERT().\r
460 \r
2fc59a00 461 @param Buffer The pointer to the buffer of pages to free.\r
e386b444 462 @param Pages The number of 4 KB pages to free.\r
463\r
464**/\r
465VOID\r
466EFIAPI\r
467FreeAlignedPages (\r
468 IN VOID *Buffer,\r
469 IN UINTN Pages\r
470 )\r
471{\r
6e10b70a 472 ASSERT (Pages != 0);\r
e386b444 473 //\r
474 // PEI phase does not support to free pages, so leave it as NOP.\r
475 //\r
476}\r
477\r
478/**\r
479 Allocates a buffer of a certain pool type.\r
480\r
481 Allocates the number bytes specified by AllocationSize of a certain pool type and returns a\r
482 pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is\r
483 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
484\r
485 @param MemoryType The type of memory to allocate.\r
486 @param AllocationSize The number of bytes to allocate.\r
487\r
488 @return A pointer to the allocated buffer or NULL if allocation fails.\r
489\r
490**/\r
491VOID *\r
492InternalAllocatePool (\r
493 IN EFI_MEMORY_TYPE MemoryType, \r
494 IN UINTN AllocationSize\r
495 )\r
496{\r
497 //\r
498 // If we need lots of small runtime/reserved memory type from PEI in the future, \r
499 // we can consider providing a more complex algorithm that allocates runtime pages and \r
500 // provide pool allocations from those pages. \r
501 //\r
502 return InternalAllocatePages (MemoryType, EFI_SIZE_TO_PAGES (AllocationSize));\r
503}\r
504\r
505/**\r
506 Allocates a buffer of type EfiBootServicesData.\r
507\r
508 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData and returns a\r
509 pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is\r
510 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
511\r
512 @param AllocationSize The number of bytes to allocate.\r
513\r
514 @return A pointer to the allocated buffer or NULL if allocation fails.\r
515\r
516**/\r
517VOID *\r
518EFIAPI\r
519AllocatePool (\r
520 IN UINTN AllocationSize\r
521 )\r
522{\r
523 EFI_STATUS Status;\r
e386b444 524 VOID *Buffer;\r
525 \r
1c280088 526 Status = PeiServicesAllocatePool (AllocationSize, &Buffer);\r
e386b444 527 if (EFI_ERROR (Status)) {\r
528 Buffer = NULL;\r
529 }\r
530 return Buffer;\r
531}\r
532\r
533/**\r
534 Allocates a buffer of type EfiRuntimeServicesData.\r
535\r
536 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData and returns\r
537 a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is\r
538 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
539\r
540 @param AllocationSize The number of bytes to allocate.\r
541\r
542 @return A pointer to the allocated buffer or NULL if allocation fails.\r
543\r
544**/\r
545VOID *\r
546EFIAPI\r
547AllocateRuntimePool (\r
548 IN UINTN AllocationSize\r
549 )\r
550{\r
551 return InternalAllocatePool (EfiRuntimeServicesData, AllocationSize);\r
552}\r
553\r
554/**\r
8789c5e0 555 Allocates a buffer of type EfiReservedMemoryType.\r
e386b444 556\r
8789c5e0 557 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType and returns\r
e386b444 558 a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is\r
559 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.\r
560\r
561 @param AllocationSize The number of bytes to allocate.\r
562\r
563 @return A pointer to the allocated buffer or NULL if allocation fails.\r
564\r
565**/\r
566VOID *\r
567EFIAPI\r
568AllocateReservedPool (\r
569 IN UINTN AllocationSize\r
570 )\r
571{\r
572 return InternalAllocatePool (EfiReservedMemoryType, AllocationSize);\r
573}\r
574\r
575/**\r
446b94b0 576 Allocates and zeros a buffer of a certain pool type.\r
e386b444 577\r
446b94b0 578 Allocates the number bytes specified by AllocationSize of a certain pool type, clears the buffer\r
e386b444 579 with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a valid\r
580 buffer of 0 size is returned. If there is not enough memory remaining to satisfy the request,\r
581 then NULL is returned.\r
582\r
583 @param PoolType The type of memory to allocate.\r
584 @param AllocationSize The number of bytes to allocate and zero.\r
585\r
586 @return A pointer to the allocated buffer or NULL if allocation fails.\r
587\r
588**/\r
589VOID *\r
590InternalAllocateZeroPool (\r
591 IN EFI_MEMORY_TYPE PoolType, \r
592 IN UINTN AllocationSize\r
593 ) \r
594{\r
595 VOID *Memory;\r
596\r
597 Memory = InternalAllocatePool (PoolType, AllocationSize);\r
598 if (Memory != NULL) {\r
599 Memory = ZeroMem (Memory, AllocationSize);\r
600 }\r
601 return Memory;\r
602}\r
603\r
604/**\r
605 Allocates and zeros a buffer of type EfiBootServicesData.\r
606\r
607 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, clears the\r
608 buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a\r
609 valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the\r
610 request, then NULL is returned.\r
611\r
612 @param AllocationSize The number of bytes to allocate and zero.\r
613\r
614 @return A pointer to the allocated buffer or NULL if allocation fails.\r
615\r
616**/\r
617VOID *\r
618EFIAPI\r
619AllocateZeroPool (\r
620 IN UINTN AllocationSize\r
621 )\r
622{\r
623 VOID *Memory;\r
624\r
625 Memory = AllocatePool (AllocationSize);\r
626 if (Memory != NULL) {\r
627 Memory = ZeroMem (Memory, AllocationSize);\r
628 }\r
629 return Memory;\r
630}\r
631\r
632/**\r
633 Allocates and zeros a buffer of type EfiRuntimeServicesData.\r
634\r
635 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, clears the\r
636 buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a\r
637 valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the\r
638 request, then NULL is returned.\r
639\r
640 @param AllocationSize The number of bytes to allocate and zero.\r
641\r
642 @return A pointer to the allocated buffer or NULL if allocation fails.\r
643\r
644**/\r
645VOID *\r
646EFIAPI\r
647AllocateRuntimeZeroPool (\r
648 IN UINTN AllocationSize\r
649 )\r
650{\r
651 return InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize);\r
652}\r
653\r
654/**\r
655 Allocates and zeros a buffer of type EfiReservedMemoryType.\r
656\r
657 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, clears the\r
658 buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a\r
659 valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the\r
660 request, then NULL is returned.\r
661\r
662 @param AllocationSize The number of bytes to allocate and zero.\r
663\r
664 @return A pointer to the allocated buffer or NULL if allocation fails.\r
665\r
666**/\r
667VOID *\r
668EFIAPI\r
669AllocateReservedZeroPool (\r
670 IN UINTN AllocationSize\r
671 )\r
672{\r
673 return InternalAllocateZeroPool (EfiReservedMemoryType, AllocationSize);\r
674}\r
675\r
676/**\r
446b94b0 677 Copies a buffer to an allocated buffer of a certain pool type.\r
e386b444 678\r
446b94b0 679 Allocates the number bytes specified by AllocationSize of a certain pool type, copies\r
e386b444 680 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the\r
681 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there\r
682 is not enough memory remaining to satisfy the request, then NULL is returned.\r
683 If Buffer is NULL, then ASSERT().\r
9e6fa6d2 684 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). \r
e386b444 685\r
686 @param PoolType The type of pool to allocate.\r
687 @param AllocationSize The number of bytes to allocate and zero.\r
688 @param Buffer The buffer to copy to the allocated buffer.\r
689\r
690 @return A pointer to the allocated buffer or NULL if allocation fails.\r
691\r
692**/\r
693VOID *\r
694InternalAllocateCopyPool (\r
695 IN EFI_MEMORY_TYPE PoolType, \r
696 IN UINTN AllocationSize,\r
697 IN CONST VOID *Buffer\r
698 ) \r
699{\r
700 VOID *Memory;\r
701\r
702 ASSERT (Buffer != NULL);\r
703 ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN) Buffer + 1));\r
704\r
705 Memory = InternalAllocatePool (PoolType, AllocationSize);\r
706 if (Memory != NULL) {\r
707 Memory = CopyMem (Memory, Buffer, AllocationSize);\r
708 }\r
709 return Memory;\r
710} \r
711\r
712/**\r
713 Copies a buffer to an allocated buffer of type EfiBootServicesData.\r
714\r
715 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, copies\r
716 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the\r
717 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there\r
718 is not enough memory remaining to satisfy the request, then NULL is returned.\r
9638ba6d 719 \r
e386b444 720 If Buffer is NULL, then ASSERT().\r
9e6fa6d2 721 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). \r
e386b444 722\r
723 @param AllocationSize The number of bytes to allocate and zero.\r
724 @param Buffer The buffer to copy to the allocated buffer.\r
725\r
726 @return A pointer to the allocated buffer or NULL if allocation fails.\r
727\r
728**/\r
729VOID *\r
730EFIAPI\r
731AllocateCopyPool (\r
732 IN UINTN AllocationSize,\r
733 IN CONST VOID *Buffer\r
734 )\r
735{\r
736 VOID *Memory;\r
737\r
738 ASSERT (Buffer != NULL);\r
739 ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN) Buffer + 1));\r
740\r
741 Memory = AllocatePool (AllocationSize);\r
742 if (Memory != NULL) {\r
743 Memory = CopyMem (Memory, Buffer, AllocationSize);\r
744 }\r
745 return Memory;\r
746}\r
747\r
748/**\r
749 Copies a buffer to an allocated buffer of type EfiRuntimeServicesData.\r
750\r
751 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, copies\r
752 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the\r
753 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there\r
754 is not enough memory remaining to satisfy the request, then NULL is returned.\r
9638ba6d 755 \r
e386b444 756 If Buffer is NULL, then ASSERT().\r
9e6fa6d2 757 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). \r
e386b444 758\r
759 @param AllocationSize The number of bytes to allocate and zero.\r
760 @param Buffer The buffer to copy to the allocated buffer.\r
761\r
762 @return A pointer to the allocated buffer or NULL if allocation fails.\r
763\r
764**/\r
765VOID *\r
766EFIAPI\r
767AllocateRuntimeCopyPool (\r
768 IN UINTN AllocationSize,\r
769 IN CONST VOID *Buffer\r
770 )\r
771{\r
772 return InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer);\r
773}\r
774\r
775/**\r
776 Copies a buffer to an allocated buffer of type EfiReservedMemoryType.\r
777\r
778 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, copies\r
779 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the\r
780 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there\r
781 is not enough memory remaining to satisfy the request, then NULL is returned.\r
9638ba6d 782 \r
e386b444 783 If Buffer is NULL, then ASSERT().\r
9e6fa6d2 784 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). \r
e386b444 785\r
786 @param AllocationSize The number of bytes to allocate and zero.\r
787 @param Buffer The buffer to copy to the allocated buffer.\r
788\r
789 @return A pointer to the allocated buffer or NULL if allocation fails.\r
790\r
791**/\r
792VOID *\r
793EFIAPI\r
794AllocateReservedCopyPool (\r
795 IN UINTN AllocationSize,\r
796 IN CONST VOID *Buffer\r
797 )\r
798{\r
799 return InternalAllocateCopyPool (EfiReservedMemoryType, AllocationSize, Buffer);\r
800}\r
801\r
3b6a71fc 802/**\r
803 Reallocates a buffer of a specified memory type.\r
804\r
805 Allocates and zeros the number bytes specified by NewSize from memory of the type\r
806 specified by PoolType. If OldBuffer is not NULL, then the smaller of OldSize and \r
807 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and \r
808 OldBuffer is freed. A pointer to the newly allocated buffer is returned. \r
809 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not \r
810 enough memory remaining to satisfy the request, then NULL is returned.\r
811 \r
56304569 812 If the allocation of the new buffer is successful and the smaller of NewSize and OldSize\r
813 is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().\r
3b6a71fc 814\r
815 @param PoolType The type of pool to allocate.\r
816 @param OldSize The size, in bytes, of OldBuffer.\r
817 @param NewSize The size, in bytes, of the buffer to reallocate.\r
58380e9c 818 @param OldBuffer The buffer to copy to the allocated buffer. This is an \r
819 optional parameter that may be NULL.\r
3b6a71fc 820\r
821 @return A pointer to the allocated buffer or NULL if allocation fails.\r
822\r
823**/\r
824VOID *\r
3b6a71fc 825InternalReallocatePool (\r
826 IN EFI_MEMORY_TYPE PoolType, \r
827 IN UINTN OldSize,\r
828 IN UINTN NewSize,\r
829 IN VOID *OldBuffer OPTIONAL\r
830 )\r
831{\r
832 VOID *NewBuffer;\r
833\r
6babbe1f 834 NewBuffer = InternalAllocateZeroPool (PoolType, NewSize);\r
3b6a71fc 835 if (NewBuffer != NULL && OldBuffer != NULL) {\r
836 CopyMem (NewBuffer, OldBuffer, MIN (OldSize, NewSize));\r
837 FreePool (OldBuffer);\r
838 }\r
839 return NewBuffer;\r
840}\r
841\r
842/**\r
843 Reallocates a buffer of type EfiBootServicesData.\r
844\r
845 Allocates and zeros the number bytes specified by NewSize from memory of type\r
846 EfiBootServicesData. If OldBuffer is not NULL, then the smaller of OldSize and \r
847 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and \r
848 OldBuffer is freed. A pointer to the newly allocated buffer is returned. \r
849 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not \r
850 enough memory remaining to satisfy the request, then NULL is returned.\r
851 \r
56304569 852 If the allocation of the new buffer is successful and the smaller of NewSize and OldSize\r
853 is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().\r
3b6a71fc 854\r
855 @param OldSize The size, in bytes, of OldBuffer.\r
856 @param NewSize The size, in bytes, of the buffer to reallocate.\r
857 @param OldBuffer The buffer to copy to the allocated buffer. This is an optional \r
858 parameter that may be NULL.\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
865ReallocatePool (\r
866 IN UINTN OldSize,\r
867 IN UINTN NewSize,\r
868 IN VOID *OldBuffer OPTIONAL\r
869 )\r
870{\r
871 return InternalReallocatePool (EfiBootServicesData, OldSize, NewSize, OldBuffer);\r
872}\r
873\r
874/**\r
875 Reallocates a buffer of type EfiRuntimeServicesData.\r
876\r
877 Allocates and zeros the number bytes specified by NewSize from memory of type\r
878 EfiRuntimeServicesData. If OldBuffer is not NULL, then the smaller of OldSize and \r
879 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and \r
880 OldBuffer is freed. A pointer to the newly allocated buffer is returned. \r
881 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not \r
882 enough memory remaining to satisfy the request, then NULL is returned.\r
883\r
56304569 884 If the allocation of the new buffer is successful and the smaller of NewSize and OldSize\r
885 is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().\r
3b6a71fc 886\r
887 @param OldSize The size, in bytes, of OldBuffer.\r
888 @param NewSize The size, in bytes, of the buffer to reallocate.\r
889 @param OldBuffer The buffer to copy to the allocated buffer. This is an optional \r
890 parameter that may be NULL.\r
891\r
892 @return A pointer to the allocated buffer or NULL if allocation fails.\r
893\r
894**/\r
895VOID *\r
896EFIAPI\r
897ReallocateRuntimePool (\r
898 IN UINTN OldSize,\r
899 IN UINTN NewSize,\r
900 IN VOID *OldBuffer OPTIONAL\r
901 )\r
902{\r
903 return InternalReallocatePool (EfiRuntimeServicesData, OldSize, NewSize, OldBuffer);\r
904}\r
905\r
906/**\r
907 Reallocates a buffer of type EfiReservedMemoryType.\r
908\r
909 Allocates and zeros the number bytes specified by NewSize from memory of type\r
910 EfiReservedMemoryType. If OldBuffer is not NULL, then the smaller of OldSize and \r
911 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and \r
912 OldBuffer is freed. A pointer to the newly allocated buffer is returned. \r
913 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not \r
914 enough memory remaining to satisfy the request, then NULL is returned.\r
2297186d 915\r
56304569 916 If the allocation of the new buffer is successful and the smaller of NewSize and OldSize\r
917 is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().\r
3b6a71fc 918\r
919 @param OldSize The size, in bytes, of OldBuffer.\r
920 @param NewSize The size, in bytes, of the buffer to reallocate.\r
58380e9c 921 @param OldBuffer The buffer to copy to the allocated buffer. This is an \r
922 optional parameter that may be NULL.\r
3b6a71fc 923\r
924 @return A pointer to the allocated buffer or NULL if allocation fails.\r
925\r
926**/\r
927VOID *\r
928EFIAPI\r
929ReallocateReservedPool (\r
930 IN UINTN OldSize,\r
931 IN UINTN NewSize,\r
932 IN VOID *OldBuffer OPTIONAL\r
933 )\r
934{\r
935 return InternalReallocatePool (EfiReservedMemoryType, OldSize, NewSize, OldBuffer);\r
936}\r
937\r
e386b444 938/**\r
939 Frees a buffer that was previously allocated with one of the pool allocation functions in the\r
940 Memory Allocation Library.\r
941\r
942 Frees the buffer specified by Buffer. Buffer must have been allocated on a previous call to the\r
6e10b70a 943 pool allocation services of the Memory Allocation Library. If it is not possible to free pool\r
446b94b0 944 resources, then this function will perform no actions.\r
9638ba6d 945 \r
e386b444 946 If Buffer was not allocated with a pool allocation function in the Memory Allocation Library,\r
947 then ASSERT().\r
948\r
2fc59a00 949 @param Buffer The pointer to the buffer to free.\r
e386b444 950\r
951**/\r
952VOID\r
953EFIAPI\r
954FreePool (\r
955 IN VOID *Buffer\r
956 )\r
957{\r
958 //\r
959 // PEI phase does not support to free pool, so leave it as NOP.\r
960 //\r
961}\r
962\r
7d582d6b 963\r