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