]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/SmmMemoryAllocationProfileLib/MemoryAllocationLib.c
MdePkg/ProcessorBind: add defines for page allocation granularity
[mirror_edk2.git] / MdeModulePkg / Library / SmmMemoryAllocationProfileLib / MemoryAllocationLib.c
CommitLineData
022a9bf7
SZ
1/** @file\r
2 Support routines for memory allocation routines based \r
3 on SMM Services Table services for SMM phase drivers, with memory profile support.\r
4 \r
5 The PI System Management Mode Core Interface Specification only allows the use\r
6 of EfiRuntimeServicesCode and EfiRuntimeServicesData memory types for memory \r
7 allocations through the SMM Services Table as the SMRAM space should be \r
8 reserved after BDS phase. The functions in the Memory Allocation Library use\r
9 EfiBootServicesData as the default memory allocation type. For this SMM \r
10 specific instance of the Memory Allocation Library, EfiRuntimeServicesData \r
11 is used as the default memory type for all allocations. In addition, \r
12 allocation for the Reserved memory types are not supported and will always \r
13 return NULL.\r
14\r
16f69227 15 Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>\r
022a9bf7
SZ
16 This program and the accompanying materials \r
17 are licensed and made available under the terms and conditions of the BSD License \r
18 which accompanies this distribution. The full text of the license may be found at \r
19 http://opensource.org/licenses/bsd-license.php. \r
20\r
21 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
22 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
23\r
24**/\r
25\r
26#include <PiSmm.h>\r
27\r
28#include <Protocol/SmmAccess2.h>\r
29#include <Library/MemoryAllocationLib.h>\r
30#include <Library/UefiBootServicesTableLib.h>\r
31#include <Library/SmmServicesTableLib.h>\r
32#include <Library/BaseMemoryLib.h>\r
33#include <Library/DebugLib.h>\r
34\r
35#include <Library/MemoryProfileLib.h>\r
36\r
37EFI_SMRAM_DESCRIPTOR *mSmramRanges;\r
38UINTN mSmramRangeCount;\r
39\r
40/**\r
41 The constructor function caches SMRAM ranges that are present in the system.\r
42 \r
43 It will ASSERT() if SMM Access2 Protocol doesn't exist.\r
44 It will ASSERT() if SMRAM ranges can't be got.\r
45 It will ASSERT() if Resource can't be allocated for cache SMRAM range. \r
46 It will always return EFI_SUCCESS.\r
47\r
48 @param ImageHandle The firmware allocated handle for the EFI image.\r
49 @param SystemTable A pointer to the EFI System Table.\r
50\r
51 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.\r
52\r
53**/\r
54EFI_STATUS\r
55EFIAPI\r
56SmmMemoryAllocationLibConstructor (\r
57 IN EFI_HANDLE ImageHandle,\r
58 IN EFI_SYSTEM_TABLE *SystemTable\r
59 )\r
60{\r
61 EFI_STATUS Status;\r
62 EFI_SMM_ACCESS2_PROTOCOL *SmmAccess;\r
63 UINTN Size;\r
64\r
65 //\r
66 // Locate SMM Access2 Protocol\r
67 //\r
68 Status = gBS->LocateProtocol (\r
69 &gEfiSmmAccess2ProtocolGuid, \r
70 NULL, \r
71 (VOID **)&SmmAccess\r
72 );\r
73 ASSERT_EFI_ERROR (Status);\r
74\r
75 //\r
76 // Get SMRAM range information\r
77 //\r
78 Size = 0;\r
79 Status = SmmAccess->GetCapabilities (SmmAccess, &Size, NULL);\r
80 ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
81\r
82 mSmramRanges = (EFI_SMRAM_DESCRIPTOR *) AllocatePool (Size);\r
83 ASSERT (mSmramRanges != NULL);\r
84\r
85 Status = SmmAccess->GetCapabilities (SmmAccess, &Size, mSmramRanges);\r
86 ASSERT_EFI_ERROR (Status);\r
87\r
88 mSmramRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR);\r
89\r
90 return EFI_SUCCESS;\r
91}\r
92\r
93/**\r
94 If SMM driver exits with an error, it must call this routine \r
95 to free the allocated resource before the exiting.\r
96\r
97 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
98 @param[in] SystemTable A pointer to the EFI System Table.\r
99\r
100 @retval EFI_SUCCESS The deconstructor always returns EFI_SUCCESS.\r
101**/\r
102EFI_STATUS\r
103EFIAPI\r
104SmmMemoryAllocationLibDestructor (\r
105 IN EFI_HANDLE ImageHandle,\r
106 IN EFI_SYSTEM_TABLE *SystemTable\r
107 )\r
108{\r
109 FreePool (mSmramRanges);\r
110\r
111 return EFI_SUCCESS;\r
112}\r
113\r
114/**\r
115 Check whether the start address of buffer is within any of the SMRAM ranges.\r
116\r
117 @param[in] Buffer The pointer to the buffer to be checked.\r
118\r
3b28e744 119 @retval TRUE The buffer is in SMRAM ranges.\r
022a9bf7
SZ
120 @retval FALSE The buffer is out of SMRAM ranges.\r
121**/\r
122BOOLEAN\r
123EFIAPI\r
124BufferInSmram (\r
125 IN VOID *Buffer\r
126 )\r
127{\r
128 UINTN Index;\r
129\r
130 for (Index = 0; Index < mSmramRangeCount; Index ++) {\r
131 if (((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer >= mSmramRanges[Index].CpuStart) && \r
132 ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer < (mSmramRanges[Index].CpuStart + mSmramRanges[Index].PhysicalSize))) {\r
133 return TRUE;\r
134 }\r
135 }\r
136\r
137 return FALSE;\r
138}\r
139\r
140/**\r
141 Allocates one or more 4KB pages of a certain memory type.\r
142\r
143 Allocates the number of 4KB pages of a certain memory type and returns a pointer \r
144 to the allocated buffer. The buffer returned is aligned on a 4KB boundary. If \r
145 Pages is 0, then NULL is returned. If there is not enough memory remaining to \r
146 satisfy the request, then NULL is returned.\r
147\r
148 @param MemoryType The type of memory to allocate.\r
149 @param Pages The number of 4 KB pages to allocate.\r
150\r
151 @return A pointer to the allocated buffer or NULL if allocation fails.\r
152\r
153**/\r
154VOID *\r
155InternalAllocatePages (\r
156 IN EFI_MEMORY_TYPE MemoryType, \r
157 IN UINTN Pages\r
158 )\r
159{\r
160 EFI_STATUS Status;\r
161 EFI_PHYSICAL_ADDRESS Memory; \r
162\r
163 if (Pages == 0) {\r
164 return NULL;\r
165 }\r
166\r
167 Status = gSmst->SmmAllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory);\r
168 if (EFI_ERROR (Status)) {\r
169 return NULL;\r
170 }\r
171 return (VOID *) (UINTN) Memory;\r
172}\r
173\r
174/**\r
175 Allocates one or more 4KB pages of type EfiRuntimeServicesData.\r
176\r
177 Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer \r
178 to the allocated buffer. The buffer returned is aligned on a 4KB boundary. If \r
179 Pages is 0, then NULL is returned. If there is not enough memory remaining to \r
180 satisfy the request, then NULL is returned.\r
181\r
182 @param Pages The number of 4 KB pages to allocate.\r
183\r
184 @return A pointer to the allocated buffer or NULL if allocation fails.\r
185\r
186**/\r
187VOID *\r
188EFIAPI\r
189AllocatePages (\r
190 IN UINTN Pages\r
191 )\r
192{\r
193 VOID *Buffer;\r
194\r
195 Buffer = InternalAllocatePages (EfiRuntimeServicesData, Pages);\r
196 if (Buffer != NULL) {\r
197 MemoryProfileLibRecord (\r
198 (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0),\r
199 MEMORY_PROFILE_ACTION_LIB_ALLOCATE_PAGES,\r
200 EfiRuntimeServicesData,\r
201 Buffer,\r
202 EFI_PAGES_TO_SIZE(Pages),\r
203 NULL\r
204 );\r
205 }\r
206 return Buffer;\r
207}\r
208\r
209/**\r
210 Allocates one or more 4KB pages of type EfiRuntimeServicesData.\r
211\r
212 Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a \r
213 pointer to the allocated buffer. The buffer returned is aligned on a 4KB boundary. \r
214 If Pages is 0, then NULL is returned. If there is not enough memory remaining \r
215 to satisfy the request, then NULL is returned.\r
216\r
217 @param Pages The number of 4 KB pages to allocate.\r
218\r
219 @return A pointer to the allocated buffer or NULL if allocation fails.\r
220\r
221**/\r
222VOID *\r
223EFIAPI\r
224AllocateRuntimePages (\r
225 IN UINTN Pages\r
226 )\r
227{\r
228 VOID *Buffer;\r
229\r
230 Buffer = InternalAllocatePages (EfiRuntimeServicesData, Pages);\r
231 if (Buffer != NULL) {\r
232 MemoryProfileLibRecord (\r
233 (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0),\r
234 MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_PAGES,\r
235 EfiRuntimeServicesData,\r
236 Buffer,\r
237 EFI_PAGES_TO_SIZE(Pages),\r
238 NULL\r
239 );\r
240 }\r
241 return Buffer;\r
242}\r
243\r
244/**\r
245 Allocates one or more 4KB pages of type EfiReservedMemoryType.\r
246\r
247 Allocates the number of 4KB pages of type EfiReservedMemoryType and returns a \r
248 pointer to the allocated buffer. The buffer returned is aligned on a 4KB boundary. \r
249 If Pages is 0, then NULL is returned. If there is not enough memory remaining \r
250 to satisfy the request, then NULL is returned.\r
251\r
252 @param Pages The number of 4 KB pages to allocate.\r
253\r
254 @return A pointer to the allocated buffer or NULL if allocation fails.\r
255\r
256**/\r
257VOID *\r
258EFIAPI\r
259AllocateReservedPages (\r
260 IN UINTN Pages\r
261 )\r
262{\r
263 return NULL;\r
264}\r
265\r
266/**\r
267 Frees one or more 4KB pages that were previously allocated with one of the page allocation\r
268 functions in the Memory Allocation Library.\r
269\r
270 Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. \r
271 Buffer must have been allocated on a previous call to the page allocation services \r
272 of the Memory Allocation Library. If it is not possible to free allocated pages, \r
273 then this function will perform no actions.\r
274 \r
275 If Buffer was not allocated with a page allocation function in the Memory Allocation \r
276 Library, then ASSERT().\r
277 If Pages is zero, then ASSERT().\r
278 \r
279 @param Buffer The pointer to the buffer of pages to free.\r
280 @param Pages The number of 4 KB pages to free.\r
281\r
282**/\r
283VOID\r
284EFIAPI\r
285FreePages (\r
286 IN VOID *Buffer,\r
287 IN UINTN Pages\r
288 )\r
289{\r
290 EFI_STATUS Status;\r
291\r
292 ASSERT (Pages != 0);\r
293 if (BufferInSmram (Buffer)) {\r
294 //\r
295 // When Buffer is in SMRAM range, it should be allocated by gSmst->SmmAllocatePages() service.\r
296 // So, gSmst->SmmFreePages() service is used to free it.\r
297 //\r
298 Status = gSmst->SmmFreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);\r
299 } else {\r
300 //\r
301 // When Buffer is out of SMRAM range, it should be allocated by gBS->AllocatePages() service.\r
302 // So, gBS->FreePages() service is used to free it.\r
303 //\r
304 Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);\r
305 }\r
306 ASSERT_EFI_ERROR (Status);\r
307}\r
308\r
309/**\r
310 Allocates one or more 4KB pages of a certain memory type at a specified alignment.\r
311\r
312 Allocates the number of 4KB pages specified by Pages of a certain memory type \r
313 with an alignment specified by Alignment. The allocated buffer is returned. \r
314 If Pages is 0, then NULL is returned. If there is not enough memory at the \r
315 specified alignment remaining to satisfy the request, then NULL is returned.\r
316 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
317 If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().\r
318\r
319 @param MemoryType The type of memory to allocate.\r
320 @param Pages The number of 4 KB pages to allocate.\r
321 @param Alignment The requested alignment of the allocation. \r
322 Must be a power of two.\r
323 If Alignment is zero, then byte alignment is used.\r
324\r
325 @return A pointer to the allocated buffer or NULL if allocation fails.\r
326\r
327**/\r
328VOID *\r
329InternalAllocateAlignedPages (\r
330 IN EFI_MEMORY_TYPE MemoryType, \r
331 IN UINTN Pages,\r
332 IN UINTN Alignment\r
333 )\r
334{\r
335 EFI_STATUS Status;\r
336 EFI_PHYSICAL_ADDRESS Memory;\r
337 UINTN AlignedMemory;\r
338 UINTN AlignmentMask;\r
339 UINTN UnalignedPages;\r
340 UINTN RealPages;\r
341\r
342 //\r
343 // Alignment must be a power of two or zero.\r
344 //\r
345 ASSERT ((Alignment & (Alignment - 1)) == 0);\r
346 \r
347 if (Pages == 0) {\r
348 return NULL;\r
349 }\r
350 if (Alignment > EFI_PAGE_SIZE) {\r
351 //\r
352 // Calculate the total number of pages since alignment is larger than page size.\r
353 //\r
354 AlignmentMask = Alignment - 1;\r
355 RealPages = Pages + EFI_SIZE_TO_PAGES (Alignment);\r
356 //\r
357 // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.\r
358 //\r
359 ASSERT (RealPages > Pages);\r
360 \r
361 Status = gSmst->SmmAllocatePages (AllocateAnyPages, MemoryType, RealPages, &Memory);\r
362 if (EFI_ERROR (Status)) {\r
363 return NULL;\r
364 }\r
365 AlignedMemory = ((UINTN) Memory + AlignmentMask) & ~AlignmentMask;\r
366 UnalignedPages = EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN) Memory);\r
367 if (UnalignedPages > 0) {\r
368 //\r
369 // Free first unaligned page(s).\r
370 //\r
371 Status = gSmst->SmmFreePages (Memory, UnalignedPages);\r
372 ASSERT_EFI_ERROR (Status);\r
373 }\r
16f69227 374 Memory = AlignedMemory + EFI_PAGES_TO_SIZE (Pages);\r
022a9bf7
SZ
375 UnalignedPages = RealPages - Pages - UnalignedPages;\r
376 if (UnalignedPages > 0) {\r
377 //\r
378 // Free last unaligned page(s).\r
379 //\r
380 Status = gSmst->SmmFreePages (Memory, UnalignedPages);\r
381 ASSERT_EFI_ERROR (Status);\r
382 }\r
383 } else {\r
384 //\r
385 // Do not over-allocate pages in this case.\r
386 //\r
387 Status = gSmst->SmmAllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory);\r
388 if (EFI_ERROR (Status)) {\r
389 return NULL;\r
390 }\r
391 AlignedMemory = (UINTN) Memory;\r
392 }\r
393 return (VOID *) AlignedMemory;\r
394}\r
395\r
396/**\r
397 Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment.\r
398\r
399 Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData \r
400 with an alignment specified by Alignment. The allocated buffer is returned. \r
401 If Pages is 0, then NULL is returned. If there is not enough memory at the \r
402 specified alignment remaining to satisfy the request, then NULL is returned.\r
403 \r
404 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
405 If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().\r
406\r
407 @param Pages The number of 4 KB pages to allocate.\r
408 @param Alignment The requested alignment of the allocation. \r
409 Must be a power of two.\r
410 If Alignment is zero, then byte alignment is used.\r
411\r
412 @return A pointer to the allocated buffer or NULL if allocation fails.\r
413\r
414**/\r
415VOID *\r
416EFIAPI\r
417AllocateAlignedPages (\r
418 IN UINTN Pages,\r
419 IN UINTN Alignment\r
420 )\r
421{\r
422 VOID *Buffer;\r
423\r
424 Buffer = InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment);\r
425 if (Buffer != NULL) {\r
426 MemoryProfileLibRecord (\r
427 (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0),\r
428 MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_PAGES,\r
429 EfiRuntimeServicesData,\r
430 Buffer,\r
431 EFI_PAGES_TO_SIZE(Pages),\r
432 NULL\r
433 );\r
434 }\r
435 return Buffer;\r
436}\r
437\r
438/**\r
439 Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment.\r
440\r
441 Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData \r
442 with an alignment specified by Alignment. The allocated buffer is returned. \r
443 If Pages is 0, then NULL is returned. If there is not enough memory at the \r
444 specified alignment remaining to satisfy the request, then NULL is returned.\r
445 \r
446 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
447 If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().\r
448\r
449 @param Pages The number of 4 KB pages to allocate.\r
450 @param Alignment The requested alignment of the allocation. \r
451 Must be a power of two.\r
452 If Alignment is zero, then byte alignment is used.\r
453\r
454 @return A pointer to the allocated buffer or NULL if allocation fails.\r
455\r
456**/\r
457VOID *\r
458EFIAPI\r
459AllocateAlignedRuntimePages (\r
460 IN UINTN Pages,\r
461 IN UINTN Alignment\r
462 )\r
463{\r
464 VOID *Buffer;\r
465\r
466 Buffer = InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment);\r
467 if (Buffer != NULL) {\r
468 MemoryProfileLibRecord (\r
469 (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0),\r
470 MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RUNTIME_PAGES,\r
471 EfiRuntimeServicesData,\r
472 Buffer,\r
473 EFI_PAGES_TO_SIZE(Pages),\r
474 NULL\r
475 );\r
476 }\r
477 return Buffer;\r
478}\r
479\r
480/**\r
481 Allocates one or more 4KB pages of type EfiReservedMemoryType at a specified alignment.\r
482\r
483 Allocates the number of 4KB pages specified by Pages of type EfiReservedMemoryType \r
484 with an alignment specified by Alignment. The allocated buffer is returned. \r
485 If Pages is 0, then NULL is returned. If there is not enough memory at the \r
486 specified alignment remaining to satisfy the request, then NULL is returned.\r
487 \r
488 If Alignment is not a power of two and Alignment is not zero, then ASSERT().\r
489 If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().\r
490\r
491 @param Pages The number of 4 KB pages to allocate.\r
492 @param Alignment The requested alignment of the allocation. \r
493 Must be a power of two.\r
494 If Alignment is zero, then byte alignment is used.\r
495\r
496 @return A pointer to the allocated buffer or NULL if allocation fails.\r
497\r
498**/\r
499VOID *\r
500EFIAPI\r
501AllocateAlignedReservedPages (\r
502 IN UINTN Pages,\r
503 IN UINTN Alignment\r
504 )\r
505{\r
506 return NULL;\r
507}\r
508\r
509/**\r
510 Frees one or more 4KB pages that were previously allocated with one of the aligned page\r
511 allocation functions in the Memory Allocation Library.\r
512\r
513 Frees the number of 4KB pages specified by Pages from the buffer specified by \r
514 Buffer. Buffer must have been allocated on a previous call to the aligned page \r
515 allocation services of the Memory Allocation Library. If it is not possible to \r
516 free allocated pages, then this function will perform no actions.\r
517 \r
518 If Buffer was not allocated with an aligned page allocation function in the \r
519 Memory Allocation Library, then ASSERT().\r
520 If Pages is zero, then ASSERT().\r
521 \r
522 @param Buffer The pointer to the buffer of pages to free.\r
523 @param Pages The number of 4 KB pages to free.\r
524\r
525**/\r
526VOID\r
527EFIAPI\r
528FreeAlignedPages (\r
529 IN VOID *Buffer,\r
530 IN UINTN Pages\r
531 )\r
532{\r
533 EFI_STATUS Status;\r
534\r
535 ASSERT (Pages != 0);\r
536 if (BufferInSmram (Buffer)) {\r
537 //\r
538 // When Buffer is in SMRAM range, it should be allocated by gSmst->SmmAllocatePages() service.\r
539 // So, gSmst->SmmFreePages() service is used to free it.\r
540 //\r
541 Status = gSmst->SmmFreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);\r
542 } else {\r
543 //\r
544 // When Buffer is out of SMRAM range, it should be allocated by gBS->AllocatePages() service.\r
545 // So, gBS->FreePages() service is used to free it.\r
546 //\r
547 Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);\r
548 }\r
549 ASSERT_EFI_ERROR (Status);\r
550}\r
551\r
552/**\r
553 Allocates a buffer of a certain pool type.\r
554\r
555 Allocates the number bytes specified by AllocationSize of a certain pool type \r
556 and returns a pointer to the allocated buffer. If AllocationSize is 0, then a \r
557 valid buffer of 0 size is returned. If there is not enough memory remaining to \r
558 satisfy the request, then NULL is returned.\r
559\r
560 @param MemoryType The type of memory to allocate.\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
567InternalAllocatePool (\r
568 IN EFI_MEMORY_TYPE MemoryType, \r
569 IN UINTN AllocationSize\r
570 )\r
571{\r
572 EFI_STATUS Status;\r
573 VOID *Memory;\r
574\r
575 Status = gSmst->SmmAllocatePool (MemoryType, AllocationSize, &Memory);\r
576 if (EFI_ERROR (Status)) {\r
577 Memory = NULL;\r
578 }\r
579 return Memory;\r
580}\r
581\r
582/**\r
583 Allocates a buffer of type EfiRuntimeServicesData.\r
584\r
585 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData \r
586 and returns a pointer to the allocated buffer. If AllocationSize is 0, then a \r
587 valid buffer of 0 size is returned. If there is not enough memory remaining to \r
588 satisfy the request, then NULL is returned.\r
589\r
590 @param AllocationSize The number of bytes to allocate.\r
591\r
592 @return A pointer to the allocated buffer or NULL if allocation fails.\r
593\r
594**/\r
595VOID *\r
596EFIAPI\r
597AllocatePool (\r
598 IN UINTN AllocationSize\r
599 )\r
600{\r
601 VOID *Buffer;\r
602\r
603 Buffer = InternalAllocatePool (EfiRuntimeServicesData, AllocationSize);\r
604 if (Buffer != NULL) {\r
605 MemoryProfileLibRecord (\r
606 (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0),\r
607 MEMORY_PROFILE_ACTION_LIB_ALLOCATE_POOL,\r
608 EfiRuntimeServicesData,\r
609 Buffer,\r
610 AllocationSize,\r
611 NULL\r
612 );\r
613 }\r
614 return Buffer;\r
615}\r
616\r
617/**\r
618 Allocates a buffer of type EfiRuntimeServicesData.\r
619\r
620 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData \r
621 and returns a pointer to the allocated buffer. If AllocationSize is 0, then a \r
622 valid buffer of 0 size is returned. If there is not enough memory remaining to \r
623 satisfy the request, then NULL is returned.\r
624\r
625 @param AllocationSize The number of bytes to allocate.\r
626\r
627 @return A pointer to the allocated buffer or NULL if allocation fails.\r
628\r
629**/\r
630VOID *\r
631EFIAPI\r
632AllocateRuntimePool (\r
633 IN UINTN AllocationSize\r
634 )\r
635{\r
636 VOID *Buffer;\r
637\r
638 Buffer = InternalAllocatePool (EfiRuntimeServicesData, AllocationSize);\r
639 if (Buffer != NULL) {\r
640 MemoryProfileLibRecord (\r
641 (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0),\r
642 MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_POOL,\r
643 EfiRuntimeServicesData,\r
644 Buffer,\r
645 AllocationSize,\r
646 NULL\r
647 );\r
648 }\r
649 return Buffer;\r
650}\r
651\r
652/**\r
653 Allocates a buffer of type EfiReservedMemoryType.\r
654\r
655 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType \r
656 and returns a pointer to the allocated buffer. If AllocationSize is 0, then a \r
657 valid buffer of 0 size is returned. If there is not enough memory remaining to \r
658 satisfy the request, then NULL is returned.\r
659\r
660 @param AllocationSize The number of bytes to allocate.\r
661\r
662 @return A pointer to the allocated buffer or NULL if allocation fails.\r
663\r
664**/\r
665VOID *\r
666EFIAPI\r
667AllocateReservedPool (\r
668 IN UINTN AllocationSize\r
669 )\r
670{\r
671 return NULL;\r
672}\r
673\r
674/**\r
675 Allocates and zeros a buffer of a certain pool type.\r
676\r
677 Allocates the number bytes specified by AllocationSize of a certain pool type, \r
678 clears the buffer with zeros, and returns a pointer to the allocated buffer. \r
679 If AllocationSize is 0, then a valid buffer of 0 size is returned. If there is \r
680 not enough memory remaining to satisfy the request, then NULL is returned.\r
681\r
682 @param PoolType The type of memory to allocate.\r
683 @param AllocationSize The number of bytes to allocate and zero.\r
684\r
685 @return A pointer to the allocated buffer or NULL if allocation fails.\r
686\r
687**/\r
688VOID *\r
689InternalAllocateZeroPool (\r
690 IN EFI_MEMORY_TYPE PoolType, \r
691 IN UINTN AllocationSize\r
692 ) \r
693{\r
694 VOID *Memory;\r
695\r
696 Memory = InternalAllocatePool (PoolType, AllocationSize);\r
697 if (Memory != NULL) {\r
698 Memory = ZeroMem (Memory, AllocationSize);\r
699 }\r
700 return Memory;\r
701}\r
702\r
703/**\r
704 Allocates and zeros a buffer of type EfiRuntimeServicesData.\r
705\r
706 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, \r
707 clears the buffer with zeros, and returns a pointer to the allocated buffer. \r
708 If AllocationSize is 0, then a valid buffer of 0 size is returned. If there is \r
709 not enough memory remaining to satisfy the request, then NULL is returned.\r
710\r
711 @param AllocationSize The number of bytes to allocate and zero.\r
712\r
713 @return A pointer to the allocated buffer or NULL if allocation fails.\r
714\r
715**/\r
716VOID *\r
717EFIAPI\r
718AllocateZeroPool (\r
719 IN UINTN AllocationSize\r
720 )\r
721{\r
722 VOID *Buffer;\r
723\r
724 Buffer = InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize);\r
725 if (Buffer != NULL) {\r
726 MemoryProfileLibRecord (\r
727 (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0),\r
728 MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ZERO_POOL,\r
729 EfiRuntimeServicesData,\r
730 Buffer,\r
731 AllocationSize,\r
732 NULL\r
733 );\r
734 }\r
735 return Buffer;\r
736}\r
737\r
738/**\r
739 Allocates and zeros a buffer of type EfiRuntimeServicesData.\r
740\r
741 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, \r
742 clears the buffer with zeros, and returns a pointer to the allocated buffer. \r
743 If AllocationSize is 0, then a valid buffer of 0 size is returned. If there is \r
744 not enough memory remaining to satisfy the request, then NULL is returned.\r
745\r
746 @param AllocationSize The number of bytes to allocate and zero.\r
747\r
748 @return A pointer to the allocated buffer or NULL if allocation fails.\r
749\r
750**/\r
751VOID *\r
752EFIAPI\r
753AllocateRuntimeZeroPool (\r
754 IN UINTN AllocationSize\r
755 )\r
756{\r
757 VOID *Buffer;\r
758\r
759 Buffer = InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize);\r
760 if (Buffer != NULL) {\r
761 MemoryProfileLibRecord (\r
762 (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0),\r
763 MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_ZERO_POOL,\r
764 EfiRuntimeServicesData,\r
765 Buffer,\r
766 AllocationSize,\r
767 NULL\r
768 );\r
769 }\r
770 return Buffer;\r
771}\r
772\r
773/**\r
774 Allocates and zeros a buffer of type EfiReservedMemoryType.\r
775\r
776 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, \r
777 clears the buffer with zeros, and returns a pointer to the allocated buffer. \r
778 If AllocationSize is 0, then a valid buffer of 0 size is returned. If there is \r
779 not enough memory remaining to satisfy the request, then NULL is returned.\r
780\r
781 @param AllocationSize The number of bytes to allocate and zero.\r
782\r
783 @return A pointer to the allocated buffer or NULL if allocation fails.\r
784\r
785**/\r
786VOID *\r
787EFIAPI\r
788AllocateReservedZeroPool (\r
789 IN UINTN AllocationSize\r
790 )\r
791{\r
792 return NULL;\r
793}\r
794\r
795/**\r
796 Copies a buffer to an allocated buffer of a certain pool type.\r
797\r
798 Allocates the number bytes specified by AllocationSize of a certain pool type, \r
799 copies AllocationSize bytes from Buffer to the newly allocated buffer, and returns \r
800 a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer \r
801 of 0 size is returned. If there is not enough memory remaining to satisfy the \r
802 request, then NULL is returned. If Buffer is NULL, then ASSERT().\r
803 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). \r
804\r
805 @param PoolType The type of pool to allocate.\r
806 @param AllocationSize The number of bytes to allocate and zero.\r
807 @param Buffer The buffer to copy to the allocated buffer.\r
808\r
809 @return A pointer to the allocated buffer or NULL if allocation fails.\r
810\r
811**/\r
812VOID *\r
813InternalAllocateCopyPool (\r
814 IN EFI_MEMORY_TYPE PoolType, \r
815 IN UINTN AllocationSize,\r
816 IN CONST VOID *Buffer\r
817 ) \r
818{\r
819 VOID *Memory;\r
820\r
821 ASSERT (Buffer != NULL);\r
822 ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN) Buffer + 1));\r
823\r
824 Memory = InternalAllocatePool (PoolType, AllocationSize);\r
825 if (Memory != NULL) {\r
826 Memory = CopyMem (Memory, Buffer, AllocationSize);\r
827 }\r
828 return Memory;\r
829} \r
830\r
831/**\r
832 Copies a buffer to an allocated buffer of type EfiRuntimeServicesData.\r
833\r
834 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, \r
835 copies AllocationSize bytes from Buffer to the newly allocated buffer, and returns \r
836 a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer \r
837 of 0 size is returned. If there is not enough memory remaining to satisfy the \r
838 request, then NULL is returned.\r
839 \r
840 If Buffer is NULL, then ASSERT().\r
841 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). \r
842\r
843 @param AllocationSize The number of bytes to allocate and zero.\r
844 @param Buffer The buffer to copy to the allocated buffer.\r
845\r
846 @return A pointer to the allocated buffer or NULL if allocation fails.\r
847\r
848**/\r
849VOID *\r
850EFIAPI\r
851AllocateCopyPool (\r
852 IN UINTN AllocationSize,\r
853 IN CONST VOID *Buffer\r
854 )\r
855{\r
856 VOID *NewBuffer;\r
857\r
858 NewBuffer = InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer);\r
859 if (NewBuffer != NULL) {\r
860 MemoryProfileLibRecord (\r
861 (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0),\r
862 MEMORY_PROFILE_ACTION_LIB_ALLOCATE_COPY_POOL,\r
863 EfiRuntimeServicesData,\r
864 NewBuffer,\r
865 AllocationSize,\r
866 NULL\r
867 );\r
868 }\r
869 return NewBuffer;\r
870}\r
871\r
872/**\r
873 Copies a buffer to an allocated buffer of type EfiRuntimeServicesData.\r
874\r
875 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, \r
876 copies AllocationSize bytes from Buffer to the newly allocated buffer, and returns \r
877 a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer \r
878 of 0 size is returned. If there is not enough memory remaining to satisfy the \r
879 request, then NULL is returned.\r
880 \r
881 If Buffer is NULL, then ASSERT().\r
882 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). \r
883\r
884 @param AllocationSize The number of bytes to allocate and zero.\r
885 @param Buffer The buffer to copy to the allocated buffer.\r
886\r
887 @return A pointer to the allocated buffer or NULL if allocation fails.\r
888\r
889**/\r
890VOID *\r
891EFIAPI\r
892AllocateRuntimeCopyPool (\r
893 IN UINTN AllocationSize,\r
894 IN CONST VOID *Buffer\r
895 )\r
896{\r
897 VOID *NewBuffer;\r
898\r
899 NewBuffer = InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer);\r
900 if (NewBuffer != NULL) {\r
901 MemoryProfileLibRecord (\r
902 (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0),\r
903 MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_COPY_POOL,\r
904 EfiRuntimeServicesData,\r
905 NewBuffer,\r
906 AllocationSize,\r
907 NULL\r
908 );\r
909 }\r
910 return NewBuffer;\r
911}\r
912\r
913/**\r
914 Copies a buffer to an allocated buffer of type EfiReservedMemoryType.\r
915\r
916 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, \r
917 copies AllocationSize bytes from Buffer to the newly allocated buffer, and returns \r
918 a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer \r
919 of 0 size is returned. If there is not enough memory remaining to satisfy the \r
920 request, then NULL is returned.\r
921 \r
922 If Buffer is NULL, then ASSERT().\r
923 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). \r
924\r
925 @param AllocationSize The number of bytes to allocate and zero.\r
926 @param Buffer The buffer to copy to the allocated buffer.\r
927\r
928 @return A pointer to the allocated buffer or NULL if allocation fails.\r
929\r
930**/\r
931VOID *\r
932EFIAPI\r
933AllocateReservedCopyPool (\r
934 IN UINTN AllocationSize,\r
935 IN CONST VOID *Buffer\r
936 )\r
937{\r
938 return NULL;\r
939}\r
940\r
941/**\r
942 Reallocates a buffer of a specified memory type.\r
943\r
944 Allocates and zeros the number bytes specified by NewSize from memory of the type\r
945 specified by PoolType. If OldBuffer is not NULL, then the smaller of OldSize and \r
946 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and \r
947 OldBuffer is freed. A pointer to the newly allocated buffer is returned. \r
948 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not \r
949 enough memory remaining to satisfy the request, then NULL is returned.\r
950 \r
951 If the allocation of the new buffer is successful and the smaller of NewSize \r
952 and OldSize is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().\r
953\r
954 @param PoolType The type of pool to allocate.\r
955 @param OldSize The size, in bytes, of OldBuffer.\r
956 @param NewSize The size, in bytes, of the buffer to reallocate.\r
957 @param OldBuffer The buffer to copy to the allocated buffer. This is an \r
958 optional parameter that may be NULL.\r
959\r
960 @return A pointer to the allocated buffer or NULL if allocation fails.\r
961\r
962**/\r
963VOID *\r
964InternalReallocatePool (\r
965 IN EFI_MEMORY_TYPE PoolType, \r
966 IN UINTN OldSize,\r
967 IN UINTN NewSize,\r
968 IN VOID *OldBuffer OPTIONAL\r
969 )\r
970{\r
971 VOID *NewBuffer;\r
972\r
973 NewBuffer = InternalAllocateZeroPool (PoolType, NewSize);\r
974 if (NewBuffer != NULL && OldBuffer != NULL) {\r
975 CopyMem (NewBuffer, OldBuffer, MIN (OldSize, NewSize));\r
976 FreePool (OldBuffer);\r
977 }\r
978 return NewBuffer;\r
979}\r
980\r
981/**\r
982 Reallocates a buffer of type EfiRuntimeServicesData.\r
983\r
984 Allocates and zeros the number bytes specified by NewSize from memory of type\r
985 EfiRuntimeServicesData. If OldBuffer is not NULL, then the smaller of OldSize and \r
986 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and \r
987 OldBuffer is freed. A pointer to the newly allocated buffer is returned. \r
988 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not \r
989 enough memory remaining to satisfy the request, then NULL is returned.\r
990 \r
991 If the allocation of the new buffer is successful and the smaller of NewSize \r
992 and OldSize is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().\r
993\r
994 @param OldSize The size, in bytes, of OldBuffer.\r
995 @param NewSize The size, in bytes, of the buffer to reallocate.\r
996 @param OldBuffer The buffer to copy to the allocated buffer. This is an \r
997 optional parameter that may be NULL.\r
998\r
999 @return A pointer to the allocated buffer or NULL if allocation fails.\r
1000\r
1001**/\r
1002VOID *\r
1003EFIAPI\r
1004ReallocatePool (\r
1005 IN UINTN OldSize,\r
1006 IN UINTN NewSize,\r
1007 IN VOID *OldBuffer OPTIONAL\r
1008 )\r
1009{\r
1010 VOID *Buffer;\r
1011\r
1012 Buffer = InternalReallocatePool (EfiRuntimeServicesData, OldSize, NewSize, OldBuffer);\r
1013 if (Buffer != NULL) {\r
1014 MemoryProfileLibRecord (\r
1015 (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0),\r
1016 MEMORY_PROFILE_ACTION_LIB_REALLOCATE_POOL,\r
1017 EfiRuntimeServicesData,\r
1018 Buffer,\r
1019 NewSize,\r
1020 NULL\r
1021 );\r
1022 }\r
1023 return Buffer;\r
1024}\r
1025\r
1026/**\r
1027 Reallocates a buffer of type EfiRuntimeServicesData.\r
1028\r
1029 Allocates and zeros the number bytes specified by NewSize from memory of type\r
1030 EfiRuntimeServicesData. If OldBuffer is not NULL, then the smaller of OldSize \r
1031 and NewSize bytes are copied from OldBuffer to the newly allocated buffer, and \r
1032 OldBuffer is freed. A pointer to the newly allocated buffer is returned. \r
1033 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not \r
1034 enough memory remaining to satisfy the request, then NULL is returned.\r
1035\r
1036 If the allocation of the new buffer is successful and the smaller of NewSize \r
1037 and OldSize is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().\r
1038\r
1039 @param OldSize The size, in bytes, of OldBuffer.\r
1040 @param NewSize The size, in bytes, of the buffer to reallocate.\r
1041 @param OldBuffer The buffer to copy to the allocated buffer. This is an \r
1042 optional parameter that may be NULL.\r
1043\r
1044 @return A pointer to the allocated buffer or NULL if allocation fails.\r
1045\r
1046**/\r
1047VOID *\r
1048EFIAPI\r
1049ReallocateRuntimePool (\r
1050 IN UINTN OldSize,\r
1051 IN UINTN NewSize,\r
1052 IN VOID *OldBuffer OPTIONAL\r
1053 )\r
1054{\r
1055 VOID *Buffer;\r
1056\r
1057 Buffer = InternalReallocatePool (EfiRuntimeServicesData, OldSize, NewSize, OldBuffer);\r
1058 if (Buffer != NULL) {\r
1059 MemoryProfileLibRecord (\r
1060 (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0),\r
1061 MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RUNTIME_POOL,\r
1062 EfiRuntimeServicesData,\r
1063 Buffer,\r
1064 NewSize,\r
1065 NULL\r
1066 );\r
1067 }\r
1068 return Buffer;\r
1069}\r
1070\r
1071/**\r
1072 Reallocates a buffer of type EfiReservedMemoryType.\r
1073\r
1074 Allocates and zeros the number bytes specified by NewSize from memory of type\r
1075 EfiReservedMemoryType. If OldBuffer is not NULL, then the smaller of OldSize \r
1076 and NewSize bytes are copied from OldBuffer to the newly allocated buffer, and \r
1077 OldBuffer is freed. A pointer to the newly allocated buffer is returned. \r
1078 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not \r
1079 enough memory remaining to satisfy the request, then NULL is returned.\r
1080\r
1081 If the allocation of the new buffer is successful and the smaller of NewSize \r
1082 and OldSize is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().\r
1083\r
1084 @param OldSize The size, in bytes, of OldBuffer.\r
1085 @param NewSize The size, in bytes, of the buffer to reallocate.\r
1086 @param OldBuffer The buffer to copy to the allocated buffer. This is an \r
1087 optional parameter that may be NULL.\r
1088\r
1089 @return A pointer to the allocated buffer or NULL if allocation fails.\r
1090\r
1091**/\r
1092VOID *\r
1093EFIAPI\r
1094ReallocateReservedPool (\r
1095 IN UINTN OldSize,\r
1096 IN UINTN NewSize,\r
1097 IN VOID *OldBuffer OPTIONAL\r
1098 )\r
1099{\r
1100 return NULL;\r
1101}\r
1102\r
1103/**\r
1104 Frees a buffer that was previously allocated with one of the pool allocation \r
1105 functions in the Memory Allocation Library.\r
1106\r
1107 Frees the buffer specified by Buffer. Buffer must have been allocated on a \r
1108 previous call to the pool allocation services of the Memory Allocation Library. \r
1109 If it is not possible to free pool resources, then this function will perform \r
1110 no actions.\r
1111 \r
1112 If Buffer was not allocated with a pool allocation function in the Memory \r
1113 Allocation Library, then ASSERT().\r
1114\r
1115 @param Buffer The pointer to the buffer to free.\r
1116\r
1117**/\r
1118VOID\r
1119EFIAPI\r
1120FreePool (\r
1121 IN VOID *Buffer\r
1122 )\r
1123{\r
1124 EFI_STATUS Status;\r
1125\r
1126 if (BufferInSmram (Buffer)) {\r
1127 //\r
1128 // When Buffer is in SMRAM range, it should be allocated by gSmst->SmmAllocatePool() service.\r
1129 // So, gSmst->SmmFreePool() service is used to free it.\r
1130 //\r
1131 Status = gSmst->SmmFreePool (Buffer);\r
1132 } else {\r
1133 //\r
1134 // When Buffer is out of SMRAM range, it should be allocated by gBS->AllocatePool() service.\r
1135 // So, gBS->FreePool() service is used to free it.\r
1136 //\r
1137 Status = gBS->FreePool (Buffer);\r
1138 }\r
1139 ASSERT_EFI_ERROR (Status);\r
1140}\r