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