]> git.proxmox.com Git - mirror_edk2.git/blob - MdePkg/Library/SmmMemoryAllocationLib/MemoryAllocationLib.c
Update MemoryAllocationLib.AllocateAlignedPages API comments for memory overflow...
[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 - 2013, 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 If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().
289
290 @param MemoryType The type of memory to allocate.
291 @param Pages The number of 4 KB pages to allocate.
292 @param Alignment The requested alignment of the allocation.
293 Must be a power of two.
294 If Alignment is zero, then byte alignment is used.
295
296 @return A pointer to the allocated buffer or NULL if allocation fails.
297
298 **/
299 VOID *
300 InternalAllocateAlignedPages (
301 IN EFI_MEMORY_TYPE MemoryType,
302 IN UINTN Pages,
303 IN UINTN Alignment
304 )
305 {
306 EFI_STATUS Status;
307 EFI_PHYSICAL_ADDRESS Memory;
308 UINTN AlignedMemory;
309 UINTN AlignmentMask;
310 UINTN UnalignedPages;
311 UINTN RealPages;
312
313 //
314 // Alignment must be a power of two or zero.
315 //
316 ASSERT ((Alignment & (Alignment - 1)) == 0);
317
318 if (Pages == 0) {
319 return NULL;
320 }
321 if (Alignment > EFI_PAGE_SIZE) {
322 //
323 // Caculate the total number of pages since alignment is larger than page size.
324 //
325 AlignmentMask = Alignment - 1;
326 RealPages = Pages + EFI_SIZE_TO_PAGES (Alignment);
327 //
328 // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.
329 //
330 ASSERT (RealPages > Pages);
331
332 Status = gSmst->SmmAllocatePages (AllocateAnyPages, MemoryType, RealPages, &Memory);
333 if (EFI_ERROR (Status)) {
334 return NULL;
335 }
336 AlignedMemory = ((UINTN) Memory + AlignmentMask) & ~AlignmentMask;
337 UnalignedPages = EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN) Memory);
338 if (UnalignedPages > 0) {
339 //
340 // Free first unaligned page(s).
341 //
342 Status = gSmst->SmmFreePages (Memory, UnalignedPages);
343 ASSERT_EFI_ERROR (Status);
344 }
345 Memory = (EFI_PHYSICAL_ADDRESS) (AlignedMemory + EFI_PAGES_TO_SIZE (Pages));
346 UnalignedPages = RealPages - Pages - UnalignedPages;
347 if (UnalignedPages > 0) {
348 //
349 // Free last unaligned page(s).
350 //
351 Status = gSmst->SmmFreePages (Memory, UnalignedPages);
352 ASSERT_EFI_ERROR (Status);
353 }
354 } else {
355 //
356 // Do not over-allocate pages in this case.
357 //
358 Status = gSmst->SmmAllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory);
359 if (EFI_ERROR (Status)) {
360 return NULL;
361 }
362 AlignedMemory = (UINTN) Memory;
363 }
364 return (VOID *) AlignedMemory;
365 }
366
367 /**
368 Allocates one or more 4KB pages of type EfiBootServicesData at a specified alignment.
369
370 Allocates the number of 4KB pages specified by Pages of type EfiBootServicesData
371 with an alignment specified by Alignment. The allocated buffer is returned.
372 If Pages is 0, then NULL is returned. If there is not enough memory at the
373 specified alignment remaining to satisfy the request, then NULL is returned.
374
375 If Alignment is not a power of two and Alignment is not zero, then ASSERT().
376 If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().
377
378 @param Pages The number of 4 KB pages to allocate.
379 @param Alignment The requested alignment of the allocation.
380 Must be a power of two.
381 If Alignment is zero, then byte alignment is used.
382
383 @return A pointer to the allocated buffer or NULL if allocation fails.
384
385 **/
386 VOID *
387 EFIAPI
388 AllocateAlignedPages (
389 IN UINTN Pages,
390 IN UINTN Alignment
391 )
392 {
393 return InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment);
394 }
395
396 /**
397 Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment.
398
399 Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData
400 with an alignment specified by Alignment. The allocated buffer is returned.
401 If Pages is 0, then NULL is returned. If there is not enough memory at the
402 specified alignment remaining to satisfy the request, then NULL is returned.
403
404 If Alignment is not a power of two and Alignment is not zero, then ASSERT().
405 If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().
406
407 @param Pages The number of 4 KB pages to allocate.
408 @param Alignment The requested alignment of the allocation.
409 Must be a power of two.
410 If Alignment is zero, then byte alignment is used.
411
412 @return A pointer to the allocated buffer or NULL if allocation fails.
413
414 **/
415 VOID *
416 EFIAPI
417 AllocateAlignedRuntimePages (
418 IN UINTN Pages,
419 IN UINTN Alignment
420 )
421 {
422 return InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment);
423 }
424
425 /**
426 Allocates one or more 4KB pages of type EfiReservedMemoryType at a specified alignment.
427
428 Allocates the number of 4KB pages specified by Pages of type EfiReservedMemoryType
429 with an alignment specified by Alignment. The allocated buffer is returned.
430 If Pages is 0, then NULL is returned. If there is not enough memory at the
431 specified alignment remaining to satisfy the request, then NULL is returned.
432
433 If Alignment is not a power of two and Alignment is not zero, then ASSERT().
434 If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().
435
436 @param Pages The number of 4 KB pages to allocate.
437 @param Alignment The requested alignment of the allocation.
438 Must be a power of two.
439 If Alignment is zero, then byte alignment is used.
440
441 @return A pointer to the allocated buffer or NULL if allocation fails.
442
443 **/
444 VOID *
445 EFIAPI
446 AllocateAlignedReservedPages (
447 IN UINTN Pages,
448 IN UINTN Alignment
449 )
450 {
451 return NULL;
452 }
453
454 /**
455 Frees one or more 4KB pages that were previously allocated with one of the aligned page
456 allocation functions in the Memory Allocation Library.
457
458 Frees the number of 4KB pages specified by Pages from the buffer specified by
459 Buffer. Buffer must have been allocated on a previous call to the aligned page
460 allocation services of the Memory Allocation Library. If it is not possible to
461 free allocated pages, then this function will perform no actions.
462
463 If Buffer was not allocated with an aligned page allocation function in the
464 Memory Allocation Library, then ASSERT().
465 If Pages is zero, then ASSERT().
466
467 @param Buffer The pointer to the buffer of pages to free.
468 @param Pages The number of 4 KB pages to free.
469
470 **/
471 VOID
472 EFIAPI
473 FreeAlignedPages (
474 IN VOID *Buffer,
475 IN UINTN Pages
476 )
477 {
478 EFI_STATUS Status;
479
480 ASSERT (Pages != 0);
481 if (BufferInSmram (Buffer)) {
482 //
483 // When Buffer is in SMRAM range, it should be allocated by gSmst->SmmAllocatePages() service.
484 // So, gSmst->SmmFreePages() service is used to free it.
485 //
486 Status = gSmst->SmmFreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);
487 } else {
488 //
489 // When Buffer is out of SMRAM range, it should be allocated by gBS->AllocatePages() service.
490 // So, gBS->FreePages() service is used to free it.
491 //
492 Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);
493 }
494 ASSERT_EFI_ERROR (Status);
495 }
496
497 /**
498 Allocates a buffer of a certain pool type.
499
500 Allocates the number bytes specified by AllocationSize of a certain pool type
501 and returns a pointer to the allocated buffer. If AllocationSize is 0, then a
502 valid buffer of 0 size is returned. If there is not enough memory remaining to
503 satisfy the request, then NULL is returned.
504
505 @param MemoryType The type of memory to allocate.
506 @param AllocationSize The number of bytes to allocate.
507
508 @return A pointer to the allocated buffer or NULL if allocation fails.
509
510 **/
511 VOID *
512 InternalAllocatePool (
513 IN EFI_MEMORY_TYPE MemoryType,
514 IN UINTN AllocationSize
515 )
516 {
517 EFI_STATUS Status;
518 VOID *Memory;
519
520 Status = gSmst->SmmAllocatePool (MemoryType, AllocationSize, &Memory);
521 if (EFI_ERROR (Status)) {
522 Memory = NULL;
523 }
524 return Memory;
525 }
526
527 /**
528 Allocates a buffer of type EfiBootServicesData.
529
530 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData
531 and returns a pointer to the allocated buffer. If AllocationSize is 0, then a
532 valid buffer of 0 size is returned. If there is not enough memory remaining to
533 satisfy the request, then NULL is returned.
534
535 @param AllocationSize The number of bytes to allocate.
536
537 @return A pointer to the allocated buffer or NULL if allocation fails.
538
539 **/
540 VOID *
541 EFIAPI
542 AllocatePool (
543 IN UINTN AllocationSize
544 )
545 {
546 return InternalAllocatePool (EfiRuntimeServicesData, AllocationSize);
547 }
548
549 /**
550 Allocates a buffer of type EfiRuntimeServicesData.
551
552 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData
553 and returns a pointer to the allocated buffer. If AllocationSize is 0, then a
554 valid buffer of 0 size is returned. If there is not enough memory remaining to
555 satisfy the request, then NULL is returned.
556
557 @param AllocationSize The number of bytes to allocate.
558
559 @return A pointer to the allocated buffer or NULL if allocation fails.
560
561 **/
562 VOID *
563 EFIAPI
564 AllocateRuntimePool (
565 IN UINTN AllocationSize
566 )
567 {
568 return InternalAllocatePool (EfiRuntimeServicesData, AllocationSize);
569 }
570
571 /**
572 Allocates a buffer of type EfiReservedMemoryType.
573
574 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType
575 and returns a pointer to the allocated buffer. If AllocationSize is 0, then a
576 valid buffer of 0 size is returned. If there is not enough memory remaining to
577 satisfy the request, then NULL is returned.
578
579 @param AllocationSize The number of bytes to allocate.
580
581 @return A pointer to the allocated buffer or NULL if allocation fails.
582
583 **/
584 VOID *
585 EFIAPI
586 AllocateReservedPool (
587 IN UINTN AllocationSize
588 )
589 {
590 return NULL;
591 }
592
593 /**
594 Allocates and zeros a buffer of a certain pool type.
595
596 Allocates the number bytes specified by AllocationSize of a certain pool type,
597 clears the buffer with zeros, and returns a pointer to the allocated buffer.
598 If AllocationSize is 0, then a valid buffer of 0 size is returned. If there is
599 not enough memory remaining to satisfy the request, then NULL is returned.
600
601 @param PoolType The type of memory to allocate.
602 @param AllocationSize The number of bytes to allocate and zero.
603
604 @return A pointer to the allocated buffer or NULL if allocation fails.
605
606 **/
607 VOID *
608 InternalAllocateZeroPool (
609 IN EFI_MEMORY_TYPE PoolType,
610 IN UINTN AllocationSize
611 )
612 {
613 VOID *Memory;
614
615 Memory = InternalAllocatePool (PoolType, AllocationSize);
616 if (Memory != NULL) {
617 Memory = ZeroMem (Memory, AllocationSize);
618 }
619 return Memory;
620 }
621
622 /**
623 Allocates and zeros a buffer of type EfiBootServicesData.
624
625 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData,
626 clears the buffer with zeros, and returns a pointer to the allocated buffer.
627 If AllocationSize is 0, then a valid buffer of 0 size is returned. If there is
628 not enough memory remaining to satisfy the request, then NULL is returned.
629
630 @param AllocationSize The number of bytes to allocate and zero.
631
632 @return A pointer to the allocated buffer or NULL if allocation fails.
633
634 **/
635 VOID *
636 EFIAPI
637 AllocateZeroPool (
638 IN UINTN AllocationSize
639 )
640 {
641 return InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize);
642 }
643
644 /**
645 Allocates and zeros a buffer of type EfiRuntimeServicesData.
646
647 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData,
648 clears the buffer with zeros, and returns a pointer to the allocated buffer.
649 If AllocationSize is 0, then a valid buffer of 0 size is returned. If there is
650 not enough memory remaining to satisfy the request, then NULL is returned.
651
652 @param AllocationSize The number of bytes to allocate and zero.
653
654 @return A pointer to the allocated buffer or NULL if allocation fails.
655
656 **/
657 VOID *
658 EFIAPI
659 AllocateRuntimeZeroPool (
660 IN UINTN AllocationSize
661 )
662 {
663 return InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize);
664 }
665
666 /**
667 Allocates and zeros a buffer of type EfiReservedMemoryType.
668
669 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType,
670 clears the buffer with zeros, and returns a pointer to the allocated buffer.
671 If AllocationSize is 0, then a valid buffer of 0 size is returned. If there is
672 not enough memory remaining to satisfy the request, then NULL is returned.
673
674 @param AllocationSize The number of bytes to allocate and zero.
675
676 @return A pointer to the allocated buffer or NULL if allocation fails.
677
678 **/
679 VOID *
680 EFIAPI
681 AllocateReservedZeroPool (
682 IN UINTN AllocationSize
683 )
684 {
685 return NULL;
686 }
687
688 /**
689 Copies a buffer to an allocated buffer of a certain pool type.
690
691 Allocates the number bytes specified by AllocationSize of a certain pool type,
692 copies AllocationSize bytes from Buffer to the newly allocated buffer, and returns
693 a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer
694 of 0 size is returned. If there is not enough memory remaining to satisfy the
695 request, then NULL is returned. If Buffer is NULL, then ASSERT().
696 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
697
698 @param PoolType The type of pool to allocate.
699 @param AllocationSize The number of bytes to allocate and zero.
700 @param Buffer The buffer to copy to the allocated buffer.
701
702 @return A pointer to the allocated buffer or NULL if allocation fails.
703
704 **/
705 VOID *
706 InternalAllocateCopyPool (
707 IN EFI_MEMORY_TYPE PoolType,
708 IN UINTN AllocationSize,
709 IN CONST VOID *Buffer
710 )
711 {
712 VOID *Memory;
713
714 ASSERT (Buffer != NULL);
715 ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN) Buffer + 1));
716
717 Memory = InternalAllocatePool (PoolType, AllocationSize);
718 if (Memory != NULL) {
719 Memory = CopyMem (Memory, Buffer, AllocationSize);
720 }
721 return Memory;
722 }
723
724 /**
725 Copies a buffer to an allocated buffer of type EfiBootServicesData.
726
727 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData,
728 copies AllocationSize bytes from Buffer to the newly allocated buffer, and returns
729 a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer
730 of 0 size is returned. If there is not enough memory remaining to satisfy the
731 request, then NULL is returned.
732
733 If Buffer is NULL, then ASSERT().
734 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
735
736 @param AllocationSize The number of bytes to allocate and zero.
737 @param Buffer The buffer to copy to the allocated buffer.
738
739 @return A pointer to the allocated buffer or NULL if allocation fails.
740
741 **/
742 VOID *
743 EFIAPI
744 AllocateCopyPool (
745 IN UINTN AllocationSize,
746 IN CONST VOID *Buffer
747 )
748 {
749 return InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer);
750 }
751
752 /**
753 Copies a buffer to an allocated buffer of type EfiRuntimeServicesData.
754
755 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData,
756 copies AllocationSize bytes from Buffer to the newly allocated buffer, and returns
757 a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer
758 of 0 size is returned. If there is not enough memory remaining to satisfy the
759 request, then NULL is returned.
760
761 If Buffer is NULL, then ASSERT().
762 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
763
764 @param AllocationSize The number of bytes to allocate and zero.
765 @param Buffer The buffer to copy to the allocated buffer.
766
767 @return A pointer to the allocated buffer or NULL if allocation fails.
768
769 **/
770 VOID *
771 EFIAPI
772 AllocateRuntimeCopyPool (
773 IN UINTN AllocationSize,
774 IN CONST VOID *Buffer
775 )
776 {
777 return InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer);
778 }
779
780 /**
781 Copies a buffer to an allocated buffer of type EfiReservedMemoryType.
782
783 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType,
784 copies AllocationSize bytes from Buffer to the newly allocated buffer, and returns
785 a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer
786 of 0 size is returned. If there is not enough memory remaining to satisfy the
787 request, then NULL is returned.
788
789 If Buffer is NULL, then ASSERT().
790 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
791
792 @param AllocationSize The number of bytes to allocate and zero.
793 @param Buffer The buffer to copy to the allocated buffer.
794
795 @return A pointer to the allocated buffer or NULL if allocation fails.
796
797 **/
798 VOID *
799 EFIAPI
800 AllocateReservedCopyPool (
801 IN UINTN AllocationSize,
802 IN CONST VOID *Buffer
803 )
804 {
805 return NULL;
806 }
807
808 /**
809 Reallocates a buffer of a specified memory type.
810
811 Allocates and zeros the number bytes specified by NewSize from memory of the type
812 specified by PoolType. If OldBuffer is not NULL, then the smaller of OldSize and
813 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
814 OldBuffer is freed. A pointer to the newly allocated buffer is returned.
815 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not
816 enough memory remaining to satisfy the request, then NULL is returned.
817
818 If the allocation of the new buffer is successful and the smaller of NewSize
819 and OldSize is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
820
821 @param PoolType The type of pool to allocate.
822 @param OldSize The size, in bytes, of OldBuffer.
823 @param NewSize The size, in bytes, of the buffer to reallocate.
824 @param OldBuffer The buffer to copy to the allocated buffer. This is an
825 optional parameter that may be NULL.
826
827 @return A pointer to the allocated buffer or NULL if allocation fails.
828
829 **/
830 VOID *
831 InternalReallocatePool (
832 IN EFI_MEMORY_TYPE PoolType,
833 IN UINTN OldSize,
834 IN UINTN NewSize,
835 IN VOID *OldBuffer OPTIONAL
836 )
837 {
838 VOID *NewBuffer;
839
840 NewBuffer = InternalAllocateZeroPool (PoolType, NewSize);
841 if (NewBuffer != NULL && OldBuffer != NULL) {
842 CopyMem (NewBuffer, OldBuffer, MIN (OldSize, NewSize));
843 FreePool (OldBuffer);
844 }
845 return NewBuffer;
846 }
847
848 /**
849 Reallocates a buffer of type EfiBootServicesData.
850
851 Allocates and zeros the number bytes specified by NewSize from memory of type
852 EfiBootServicesData. If OldBuffer is not NULL, then the smaller of OldSize and
853 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
854 OldBuffer is freed. A pointer to the newly allocated buffer is returned.
855 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not
856 enough memory remaining to satisfy the request, then NULL is returned.
857
858 If the allocation of the new buffer is successful and the smaller of NewSize
859 and OldSize is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
860
861 @param OldSize The size, in bytes, of OldBuffer.
862 @param NewSize The size, in bytes, of the buffer to reallocate.
863 @param OldBuffer The buffer to copy to the allocated buffer. This is an
864 optional parameter that may be NULL.
865
866 @return A pointer to the allocated buffer or NULL if allocation fails.
867
868 **/
869 VOID *
870 EFIAPI
871 ReallocatePool (
872 IN UINTN OldSize,
873 IN UINTN NewSize,
874 IN VOID *OldBuffer OPTIONAL
875 )
876 {
877 return InternalReallocatePool (EfiRuntimeServicesData, OldSize, NewSize, OldBuffer);
878 }
879
880 /**
881 Reallocates a buffer of type EfiRuntimeServicesData.
882
883 Allocates and zeros the number bytes specified by NewSize from memory of type
884 EfiRuntimeServicesData. If OldBuffer is not NULL, then the smaller of OldSize
885 and NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
886 OldBuffer is freed. A pointer to the newly allocated buffer is returned.
887 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not
888 enough memory remaining to satisfy the request, then NULL is returned.
889
890 If the allocation of the new buffer is successful and the smaller of NewSize
891 and OldSize is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
892
893 @param OldSize The size, in bytes, of OldBuffer.
894 @param NewSize The size, in bytes, of the buffer to reallocate.
895 @param OldBuffer The buffer to copy to the allocated buffer. This is an
896 optional parameter that may be NULL.
897
898 @return A pointer to the allocated buffer or NULL if allocation fails.
899
900 **/
901 VOID *
902 EFIAPI
903 ReallocateRuntimePool (
904 IN UINTN OldSize,
905 IN UINTN NewSize,
906 IN VOID *OldBuffer OPTIONAL
907 )
908 {
909 return InternalReallocatePool (EfiRuntimeServicesData, OldSize, NewSize, OldBuffer);
910 }
911
912 /**
913 Reallocates a buffer of type EfiReservedMemoryType.
914
915 Allocates and zeros the number bytes specified by NewSize from memory of type
916 EfiReservedMemoryType. If OldBuffer is not NULL, then the smaller of OldSize
917 and NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
918 OldBuffer is freed. A pointer to the newly allocated buffer is returned.
919 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not
920 enough memory remaining to satisfy the request, then NULL is returned.
921
922 If the allocation of the new buffer is successful and the smaller of NewSize
923 and OldSize is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
924
925 @param OldSize The size, in bytes, of OldBuffer.
926 @param NewSize The size, in bytes, of the buffer to reallocate.
927 @param OldBuffer The buffer to copy to the allocated buffer. This is an
928 optional parameter that may be NULL.
929
930 @return A pointer to the allocated buffer or NULL if allocation fails.
931
932 **/
933 VOID *
934 EFIAPI
935 ReallocateReservedPool (
936 IN UINTN OldSize,
937 IN UINTN NewSize,
938 IN VOID *OldBuffer OPTIONAL
939 )
940 {
941 return NULL;
942 }
943
944 /**
945 Frees a buffer that was previously allocated with one of the pool allocation
946 functions in the Memory Allocation Library.
947
948 Frees the buffer specified by Buffer. Buffer must have been allocated on a
949 previous call to the pool allocation services of the Memory Allocation Library.
950 If it is not possible to free pool resources, then this function will perform
951 no actions.
952
953 If Buffer was not allocated with a pool allocation function in the Memory
954 Allocation Library, then ASSERT().
955
956 @param Buffer The pointer to the buffer to free.
957
958 **/
959 VOID
960 EFIAPI
961 FreePool (
962 IN VOID *Buffer
963 )
964 {
965 EFI_STATUS Status;
966
967 if (BufferInSmram (Buffer)) {
968 //
969 // When Buffer is in SMRAM range, it should be allocated by gSmst->SmmAllocatePool() service.
970 // So, gSmst->SmmFreePool() service is used to free it.
971 //
972 Status = gSmst->SmmFreePool (Buffer);
973 } else {
974 //
975 // When Buffer is out of SMRAM range, it should be allocated by gBS->AllocatePool() service.
976 // So, gBS->FreePool() service is used to free it.
977 //
978 Status = gBS->FreePool (Buffer);
979 }
980 ASSERT_EFI_ERROR (Status);
981 }