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