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