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