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