microsoft/mu_feature_ffa

Public

mirrored fromhttps://github.com/microsoft/mu_feature_ffaAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
ef8c8ffe3e9cd9f6fd3732ade9463d4841c3472e

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

FfaFeaturePkg/Library/SecurePartitionMemoryAllocationLib/SecurePartitionMemoryAllocationLib.c

1054lines · modecode

1/** @file
2 Support routines for memory allocation routines based on Standalone MM Core internal functions.
3
4 Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) 2016 - 2021, ARM Limited. All rights reserved.<BR>
6
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9**/
10
11#include <PiMm.h>
12
13#include <libfdt.h>
14
15#include <Guid/MmramMemoryReserve.h>
16#include <Library/MemoryAllocationLib.h>
17#include <Library/SecurePartitionServicesTableLib.h>
18#include <Library/BaseMemoryLib.h>
19#include <Library/DebugLib.h>
20
21#include "SecurePartitionMemoryAllocationLib.h"
22
23/**
24 Allocates one or more 4KB pages of a certain memory type.
25
26 Allocates the number of 4KB pages of a certain memory type and returns a pointer to the allocated
27 buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL is returned.
28 If there is not enough memory remaining to satisfy the request, then NULL is returned.
29
30 @param MemoryType The type of memory to allocate.
31 @param Pages The number of 4 KB pages to allocate.
32
33 @return A pointer to the allocated buffer or NULL if allocation fails.
34
35**/
36VOID *
37InternalAllocatePages (
38 IN EFI_MEMORY_TYPE MemoryType,
39 IN UINTN Pages
40 )
41{
42 EFI_STATUS Status;
43 EFI_PHYSICAL_ADDRESS Memory;
44
45 if (Pages == 0) {
46 return NULL;
47 }
48
49 Status = MmAllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory);
50 if (EFI_ERROR (Status)) {
51 return NULL;
52 }
53
54 return (VOID *)(UINTN)Memory;
55}
56
57/**
58 Allocates one or more 4KB pages of type EfiBootServicesData.
59
60 Allocates the number of 4KB pages of type EfiBootServicesData and returns a pointer to the
61 allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL
62 is returned. If there is not enough memory remaining to satisfy the request, then NULL is
63 returned.
64
65 @param Pages The number of 4 KB pages to allocate.
66
67 @return A pointer to the allocated buffer or NULL if allocation fails.
68
69**/
70VOID *
71EFIAPI
72AllocatePages (
73 IN UINTN Pages
74 )
75{
76 return InternalAllocatePages (EfiRuntimeServicesData, Pages);
77}
78
79/**
80 Allocates one or more 4KB pages of type EfiRuntimeServicesData.
81
82 Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer to the
83 allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL
84 is returned. If there is not enough memory remaining to satisfy the request, then NULL is
85 returned.
86
87 @param Pages The number of 4 KB pages to allocate.
88
89 @return A pointer to the allocated buffer or NULL if allocation fails.
90
91**/
92VOID *
93EFIAPI
94AllocateRuntimePages (
95 IN UINTN Pages
96 )
97{
98 return InternalAllocatePages (EfiRuntimeServicesData, Pages);
99}
100
101/**
102 Allocates one or more 4KB pages of type EfiReservedMemoryType.
103
104 Allocates the number of 4KB pages of type EfiReservedMemoryType and returns a pointer to the
105 allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL
106 is returned. If there is not enough memory remaining to satisfy the request, then NULL is
107 returned.
108
109 @param Pages The number of 4 KB pages to allocate.
110
111 @return A pointer to the allocated buffer or NULL if allocation fails.
112
113**/
114VOID *
115EFIAPI
116AllocateReservedPages (
117 IN UINTN Pages
118 )
119{
120 return NULL;
121}
122
123/**
124 Frees one or more 4KB pages that were previously allocated with one of the page allocation
125 functions in the Memory Allocation Library.
126
127 Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer
128 must have been allocated on a previous call to the page allocation services of the Memory
129 Allocation Library. If it is not possible to free allocated pages, then this function will
130 perform no actions.
131
132 If Buffer was not allocated with a page allocation function in the Memory Allocation Library,
133 then ASSERT().
134 If Pages is zero, then ASSERT().
135
136 @param Buffer Pointer to the buffer of pages to free.
137 @param Pages The number of 4 KB pages to free.
138
139**/
140VOID
141EFIAPI
142FreePages (
143 IN VOID *Buffer,
144 IN UINTN Pages
145 )
146{
147 EFI_STATUS Status;
148
149 ASSERT (Pages != 0);
150 ASSERT (Buffer != NULL);
151 Status = MmFreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)Buffer, Pages);
152 ASSERT_EFI_ERROR (Status);
153}
154
155/**
156 Allocates one or more 4KB pages of a certain memory type at a specified alignment.
157
158 Allocates the number of 4KB pages specified by Pages of a certain memory type with an alignment
159 specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is returned.
160 If there is not enough memory at the specified alignment remaining to satisfy the request, then
161 NULL is returned.
162 If Alignment is not a power of two and Alignment is not zero, then ASSERT().
163 If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().
164
165 @param MemoryType The type of memory to allocate.
166 @param Pages The number of 4 KB pages to allocate.
167 @param Alignment The requested alignment of the allocation. Must be a power of two.
168 If Alignment is zero, then byte alignment is used.
169
170 @return A pointer to the allocated buffer or NULL if allocation fails.
171
172**/
173VOID *
174InternalAllocateAlignedPages (
175 IN EFI_MEMORY_TYPE MemoryType,
176 IN UINTN Pages,
177 IN UINTN Alignment
178 )
179{
180 EFI_STATUS Status;
181 EFI_PHYSICAL_ADDRESS Memory;
182 UINTN AlignedMemory;
183 UINTN AlignmentMask;
184 UINTN UnalignedPages;
185 UINTN RealPages;
186
187 //
188 // Alignment must be a power of two or zero.
189 //
190 ASSERT ((Alignment & (Alignment - 1)) == 0);
191
192 if (Pages == 0) {
193 return NULL;
194 }
195
196 if (Alignment > EFI_PAGE_SIZE) {
197 //
198 // Calculate the total number of pages since alignment is larger than page size.
199 //
200 AlignmentMask = Alignment - 1;
201 RealPages = Pages + EFI_SIZE_TO_PAGES (Alignment);
202 //
203 // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.
204 //
205 ASSERT (RealPages > Pages);
206
207 Status = MmAllocatePages (AllocateAnyPages, MemoryType, RealPages, &Memory);
208 if (EFI_ERROR (Status)) {
209 return NULL;
210 }
211
212 AlignedMemory = ((UINTN)Memory + AlignmentMask) & ~AlignmentMask;
213 UnalignedPages = EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN)Memory);
214 if (UnalignedPages > 0) {
215 //
216 // Free first unaligned page(s).
217 //
218 Status = MmFreePages (Memory, UnalignedPages);
219 ASSERT_EFI_ERROR (Status);
220 }
221
222 Memory = (EFI_PHYSICAL_ADDRESS)(AlignedMemory + EFI_PAGES_TO_SIZE (Pages));
223 UnalignedPages = RealPages - Pages - UnalignedPages;
224 if (UnalignedPages > 0) {
225 //
226 // Free last unaligned page(s).
227 //
228 Status = MmFreePages (Memory, UnalignedPages);
229 ASSERT_EFI_ERROR (Status);
230 }
231 } else {
232 //
233 // Do not over-allocate pages in this case.
234 //
235 Status = MmAllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory);
236 if (EFI_ERROR (Status)) {
237 return NULL;
238 }
239
240 AlignedMemory = (UINTN)Memory;
241 }
242
243 return (VOID *)AlignedMemory;
244}
245
246/**
247 Allocates one or more 4KB pages of type EfiBootServicesData at a specified alignment.
248
249 Allocates the number of 4KB pages specified by Pages of type EfiBootServicesData with an
250 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is
251 returned. If there is not enough memory at the specified alignment remaining to satisfy the
252 request, then NULL is returned.
253
254 If Alignment is not a power of two and Alignment is not zero, then ASSERT().
255 If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().
256
257 @param Pages The number of 4 KB pages to allocate.
258 @param Alignment The requested alignment of the allocation. Must be a power of two.
259 If Alignment is zero, then byte alignment is used.
260
261 @return A pointer to the allocated buffer or NULL if allocation fails.
262
263**/
264VOID *
265EFIAPI
266AllocateAlignedPages (
267 IN UINTN Pages,
268 IN UINTN Alignment
269 )
270{
271 return InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment);
272}
273
274/**
275 Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment.
276
277 Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData with an
278 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is
279 returned. If there is not enough memory at the specified alignment remaining to satisfy the
280 request, then NULL is returned.
281
282 If Alignment is not a power of two and Alignment is not zero, then ASSERT().
283 If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().
284
285 @param Pages The number of 4 KB pages to allocate.
286 @param Alignment The requested alignment of the allocation. Must be a power of two.
287 If Alignment is zero, then byte alignment is used.
288
289 @return A pointer to the allocated buffer or NULL if allocation fails.
290
291**/
292VOID *
293EFIAPI
294AllocateAlignedRuntimePages (
295 IN UINTN Pages,
296 IN UINTN Alignment
297 )
298{
299 return InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment);
300}
301
302/**
303 Allocates one or more 4KB pages of type EfiReservedMemoryType at a specified alignment.
304
305 Allocates the number of 4KB pages specified by Pages of type EfiReservedMemoryType with an
306 alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is
307 returned. If there is not enough memory at the specified alignment remaining to satisfy the
308 request, then NULL is returned.
309
310 If Alignment is not a power of two and Alignment is not zero, then ASSERT().
311 If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().
312
313 @param Pages The number of 4 KB pages to allocate.
314 @param Alignment The requested alignment of the allocation. Must be a power of two.
315 If Alignment is zero, then byte alignment is used.
316
317 @return A pointer to the allocated buffer or NULL if allocation fails.
318
319**/
320VOID *
321EFIAPI
322AllocateAlignedReservedPages (
323 IN UINTN Pages,
324 IN UINTN Alignment
325 )
326{
327 return NULL;
328}
329
330/**
331 Frees one or more 4KB pages that were previously allocated with one of the aligned page
332 allocation functions in the Memory Allocation Library.
333
334 Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer
335 must have been allocated on a previous call to the aligned page allocation services of the Memory
336 Allocation Library. If it is not possible to free allocated pages, then this function will
337 perform no actions.
338
339 If Buffer was not allocated with an aligned page allocation function in the Memory Allocation
340 Library, then ASSERT().
341 If Pages is zero, then ASSERT().
342
343 @param Buffer Pointer to the buffer of pages to free.
344 @param Pages The number of 4 KB pages to free.
345
346**/
347VOID
348EFIAPI
349FreeAlignedPages (
350 IN VOID *Buffer,
351 IN UINTN Pages
352 )
353{
354 EFI_STATUS Status;
355
356 ASSERT (Pages != 0);
357 ASSERT (Buffer != NULL);
358 Status = MmFreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)Buffer, Pages);
359 ASSERT_EFI_ERROR (Status);
360}
361
362/**
363 Allocates a buffer of a certain pool type.
364
365 Allocates the number bytes specified by AllocationSize of a certain pool type and returns a
366 pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is
367 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.
368
369 @param MemoryType The type of memory to allocate.
370 @param AllocationSize The number of bytes to allocate.
371
372 @return A pointer to the allocated buffer or NULL if allocation fails.
373
374**/
375VOID *
376InternalAllocatePool (
377 IN EFI_MEMORY_TYPE MemoryType,
378 IN UINTN AllocationSize
379 )
380{
381 EFI_STATUS Status;
382 VOID *Memory;
383
384 Memory = NULL;
385
386 Status = MmAllocatePool (MemoryType, AllocationSize, &Memory);
387 if (EFI_ERROR (Status)) {
388 Memory = NULL;
389 }
390
391 return Memory;
392}
393
394/**
395 Allocates a buffer of type EfiBootServicesData.
396
397 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData and returns a
398 pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is
399 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.
400
401 @param AllocationSize The number of bytes to allocate.
402
403 @return A pointer to the allocated buffer or NULL if allocation fails.
404
405**/
406VOID *
407EFIAPI
408AllocatePool (
409 IN UINTN AllocationSize
410 )
411{
412 return InternalAllocatePool (EfiRuntimeServicesData, AllocationSize);
413}
414
415/**
416 Allocates a buffer of type EfiRuntimeServicesData.
417
418 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData and returns
419 a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is
420 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.
421
422 @param AllocationSize The number of bytes to allocate.
423
424 @return A pointer to the allocated buffer or NULL if allocation fails.
425
426**/
427VOID *
428EFIAPI
429AllocateRuntimePool (
430 IN UINTN AllocationSize
431 )
432{
433 return InternalAllocatePool (EfiRuntimeServicesData, AllocationSize);
434}
435
436/**
437 Allocates a buffer of type EfiReservedMemoryType.
438
439 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType and returns
440 a pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is
441 returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.
442
443 @param AllocationSize The number of bytes to allocate.
444
445 @return A pointer to the allocated buffer or NULL if allocation fails.
446
447**/
448VOID *
449EFIAPI
450AllocateReservedPool (
451 IN UINTN AllocationSize
452 )
453{
454 return NULL;
455}
456
457/**
458 Allocates and zeros a buffer of a certain pool type.
459
460 Allocates the number bytes specified by AllocationSize of a certain pool type, clears the buffer
461 with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a valid
462 buffer of 0 size is returned. If there is not enough memory remaining to satisfy the request,
463 then NULL is returned.
464
465 @param PoolType The type of memory to allocate.
466 @param AllocationSize The number of bytes to allocate and zero.
467
468 @return A pointer to the allocated buffer or NULL if allocation fails.
469
470**/
471VOID *
472InternalAllocateZeroPool (
473 IN EFI_MEMORY_TYPE PoolType,
474 IN UINTN AllocationSize
475 )
476{
477 VOID *Memory;
478
479 Memory = InternalAllocatePool (PoolType, AllocationSize);
480 if (Memory != NULL) {
481 Memory = ZeroMem (Memory, AllocationSize);
482 }
483
484 return Memory;
485}
486
487/**
488 Allocates and zeros a buffer of type EfiBootServicesData.
489
490 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, clears the
491 buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a
492 valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the
493 request, then NULL is returned.
494
495 @param AllocationSize The number of bytes to allocate and zero.
496
497 @return A pointer to the allocated buffer or NULL if allocation fails.
498
499**/
500VOID *
501EFIAPI
502AllocateZeroPool (
503 IN UINTN AllocationSize
504 )
505{
506 return InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize);
507}
508
509/**
510 Allocates and zeros a buffer of type EfiRuntimeServicesData.
511
512 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, clears the
513 buffer with zeros, and returns a pointer to the allocated buffer. If AllocationSize is 0, then a
514 valid buffer of 0 size is returned. If there is not enough memory remaining to satisfy the
515 request, then NULL is returned.
516
517 @param AllocationSize The number of bytes to allocate and zero.
518
519 @return A pointer to the allocated buffer or NULL if allocation fails.
520
521**/
522VOID *
523EFIAPI
524AllocateRuntimeZeroPool (
525 IN UINTN AllocationSize
526 )
527{
528 return InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize);
529}
530
531/**
532 Allocates and zeros a buffer of type EfiReservedMemoryType.
533
534 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, 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**/
544VOID *
545EFIAPI
546AllocateReservedZeroPool (
547 IN UINTN AllocationSize
548 )
549{
550 return NULL;
551}
552
553/**
554 Copies a buffer to an allocated buffer of a certain pool type.
555
556 Allocates the number bytes specified by AllocationSize of a certain pool type, copies
557 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
558 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there
559 is not enough memory remaining to satisfy the request, then NULL is returned.
560 If Buffer is NULL, then ASSERT().
561 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
562
563 @param PoolType The type of pool to allocate.
564 @param AllocationSize The number of bytes to allocate and zero.
565 @param Buffer The buffer to copy to the allocated buffer.
566
567 @return A pointer to the allocated buffer or NULL if allocation fails.
568
569**/
570VOID *
571InternalAllocateCopyPool (
572 IN EFI_MEMORY_TYPE PoolType,
573 IN UINTN AllocationSize,
574 IN CONST VOID *Buffer
575 )
576{
577 VOID *Memory;
578
579 ASSERT (Buffer != NULL);
580 ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN)Buffer + 1));
581
582 Memory = InternalAllocatePool (PoolType, AllocationSize);
583 if (Memory != NULL) {
584 Memory = CopyMem (Memory, Buffer, AllocationSize);
585 }
586
587 return Memory;
588}
589
590/**
591 Copies a buffer to an allocated buffer of type EfiBootServicesData.
592
593 Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, copies
594 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
595 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there
596 is not enough memory remaining to satisfy the request, then NULL is returned.
597
598 If Buffer is NULL, then ASSERT().
599 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
600
601 @param AllocationSize The number of bytes to allocate and zero.
602 @param Buffer The buffer to copy to the allocated buffer.
603
604 @return A pointer to the allocated buffer or NULL if allocation fails.
605
606**/
607VOID *
608EFIAPI
609AllocateCopyPool (
610 IN UINTN AllocationSize,
611 IN CONST VOID *Buffer
612 )
613{
614 return InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer);
615}
616
617/**
618 Copies a buffer to an allocated buffer of type EfiRuntimeServicesData.
619
620 Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, copies
621 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
622 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there
623 is not enough memory remaining to satisfy the request, then NULL is returned.
624
625 If Buffer is NULL, then ASSERT().
626 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
627
628 @param AllocationSize The number of bytes to allocate and zero.
629 @param Buffer The buffer to copy to the allocated buffer.
630
631 @return A pointer to the allocated buffer or NULL if allocation fails.
632
633**/
634VOID *
635EFIAPI
636AllocateRuntimeCopyPool (
637 IN UINTN AllocationSize,
638 IN CONST VOID *Buffer
639 )
640{
641 return InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer);
642}
643
644/**
645 Copies a buffer to an allocated buffer of type EfiReservedMemoryType.
646
647 Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, copies
648 AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
649 allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. If there
650 is not enough memory remaining to satisfy the request, then NULL is returned.
651
652 If Buffer is NULL, then ASSERT().
653 If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
654
655 @param AllocationSize The number of bytes to allocate and zero.
656 @param Buffer The buffer to copy to the allocated buffer.
657
658 @return A pointer to the allocated buffer or NULL if allocation fails.
659
660**/
661VOID *
662EFIAPI
663AllocateReservedCopyPool (
664 IN UINTN AllocationSize,
665 IN CONST VOID *Buffer
666 )
667{
668 return NULL;
669}
670
671/**
672 Reallocates a buffer of a specified memory type.
673
674 Allocates and zeros the number bytes specified by NewSize from memory of the type
675 specified by PoolType. If OldBuffer is not NULL, then the smaller of OldSize and
676 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
677 OldBuffer is freed. A pointer to the newly allocated buffer is returned.
678 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not
679 enough memory remaining to satisfy the request, then NULL is returned.
680
681 If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
682 is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
683
684 @param PoolType The type of pool to allocate.
685 @param OldSize The size, in bytes, of OldBuffer.
686 @param NewSize The size, in bytes, of the buffer to reallocate.
687 @param OldBuffer The buffer to copy to the allocated buffer. This is an optional
688 parameter that may be NULL.
689
690 @return A pointer to the allocated buffer or NULL if allocation fails.
691
692**/
693VOID *
694InternalReallocatePool (
695 IN EFI_MEMORY_TYPE PoolType,
696 IN UINTN OldSize,
697 IN UINTN NewSize,
698 IN VOID *OldBuffer OPTIONAL
699 )
700{
701 VOID *NewBuffer;
702
703 NewBuffer = InternalAllocateZeroPool (PoolType, NewSize);
704 if ((NewBuffer != NULL) && (OldBuffer != NULL)) {
705 CopyMem (NewBuffer, OldBuffer, MIN (OldSize, NewSize));
706 FreePool (OldBuffer);
707 }
708
709 return NewBuffer;
710}
711
712/**
713 Reallocates a buffer of type EfiBootServicesData.
714
715 Allocates and zeros the number bytes specified by NewSize from memory of type
716 EfiBootServicesData. If OldBuffer is not NULL, then the smaller of OldSize and
717 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
718 OldBuffer is freed. A pointer to the newly allocated buffer is returned.
719 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not
720 enough memory remaining to satisfy the request, then NULL is returned.
721
722 If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
723 is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
724
725 @param OldSize The size, in bytes, of OldBuffer.
726 @param NewSize The size, in bytes, of the buffer to reallocate.
727 @param OldBuffer The buffer to copy to the allocated buffer. This is an optional
728 parameter that may be NULL.
729
730 @return A pointer to the allocated buffer or NULL if allocation fails.
731
732**/
733VOID *
734EFIAPI
735ReallocatePool (
736 IN UINTN OldSize,
737 IN UINTN NewSize,
738 IN VOID *OldBuffer OPTIONAL
739 )
740{
741 return InternalReallocatePool (EfiRuntimeServicesData, OldSize, NewSize, OldBuffer);
742}
743
744/**
745 Reallocates a buffer of type EfiRuntimeServicesData.
746
747 Allocates and zeros the number bytes specified by NewSize from memory of type
748 EfiRuntimeServicesData. If OldBuffer is not NULL, then the smaller of OldSize and
749 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
750 OldBuffer is freed. A pointer to the newly allocated buffer is returned.
751 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not
752 enough memory remaining to satisfy the request, then NULL is returned.
753
754 If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
755 is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
756
757 @param OldSize The size, in bytes, of OldBuffer.
758 @param NewSize The size, in bytes, of the buffer to reallocate.
759 @param OldBuffer The buffer to copy to the allocated buffer. This is an optional
760 parameter that may be NULL.
761
762 @return A pointer to the allocated buffer or NULL if allocation fails.
763
764**/
765VOID *
766EFIAPI
767ReallocateRuntimePool (
768 IN UINTN OldSize,
769 IN UINTN NewSize,
770 IN VOID *OldBuffer OPTIONAL
771 )
772{
773 return InternalReallocatePool (EfiRuntimeServicesData, OldSize, NewSize, OldBuffer);
774}
775
776/**
777 Reallocates a buffer of type EfiReservedMemoryType.
778
779 Allocates and zeros the number bytes specified by NewSize from memory of type
780 EfiReservedMemoryType. If OldBuffer is not NULL, then the smaller of OldSize and
781 NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
782 OldBuffer is freed. A pointer to the newly allocated buffer is returned.
783 If NewSize is 0, then a valid buffer of 0 size is returned. If there is not
784 enough memory remaining to satisfy the request, then NULL is returned.
785
786 If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
787 is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
788
789 @param OldSize The size, in bytes, of OldBuffer.
790 @param NewSize The size, in bytes, of the buffer to reallocate.
791 @param OldBuffer The buffer to copy to the allocated buffer. This is an optional
792 parameter that may be NULL.
793
794 @return A pointer to the allocated buffer or NULL if allocation fails.
795
796**/
797VOID *
798EFIAPI
799ReallocateReservedPool (
800 IN UINTN OldSize,
801 IN UINTN NewSize,
802 IN VOID *OldBuffer OPTIONAL
803 )
804{
805 return NULL;
806}
807
808/**
809 Frees a buffer that was previously allocated with one of the pool allocation functions in the
810 Memory Allocation Library.
811
812 Frees the buffer specified by Buffer. Buffer must have been allocated on a previous call to the
813 pool allocation services of the Memory Allocation Library. If it is not possible to free pool
814 resources, then this function will perform no actions.
815
816 If Buffer was not allocated with a pool allocation function in the Memory Allocation Library,
817 then ASSERT().
818
819 @param Buffer Pointer to the buffer to free.
820
821**/
822VOID
823EFIAPI
824FreePool (
825 IN VOID *Buffer
826 )
827{
828 EFI_STATUS Status;
829
830 Status = MmFreePool (Buffer);
831 ASSERT_EFI_ERROR (Status);
832}
833
834STATIC
835EFI_STATUS
836ReadProperty32 (
837 IN VOID *DtbAddress,
838 IN INT32 Offset,
839 IN CHAR8 *Property,
840 OUT UINT32 *Value
841 )
842{
843 CONST UINT32 *Property32;
844
845 Property32 = fdt_getprop (DtbAddress, Offset, Property, NULL);
846 if (Property32 == NULL) {
847 DEBUG ((
848 DEBUG_ERROR,
849 "%a: Missing in FF-A boot information manifest\n",
850 Property
851 ));
852 return EFI_INVALID_PARAMETER;
853 }
854
855 *Value = fdt32_to_cpu (*Property32);
856
857 return EFI_SUCCESS;
858}
859
860STATIC
861EFI_STATUS
862ReadProperty64 (
863 IN VOID *DtbAddress,
864 IN INT32 Offset,
865 IN CHAR8 *Property,
866 OUT UINT64 *Value
867 )
868{
869 CONST UINT64 *Property64;
870
871 Property64 = fdt_getprop (DtbAddress, Offset, Property, NULL);
872 if (Property64 == NULL) {
873 DEBUG ((
874 DEBUG_ERROR,
875 "%a: Missing in FF-A boot information manifest\n",
876 Property
877 ));
878 return EFI_INVALID_PARAMETER;
879 }
880
881 *Value = fdt64_to_cpu (*Property64);
882
883 return EFI_SUCCESS;
884}
885
886STATIC
887BOOLEAN
888CheckDescription (
889 IN VOID *DtbAddress,
890 IN INT32 Offset,
891 OUT CHAR8 *Description,
892 OUT UINT32 Size
893 )
894{
895 CONST CHAR8 *Property;
896 INT32 LenP;
897
898 Property = fdt_getprop (DtbAddress, Offset, "description", &LenP);
899 if (Property == NULL) {
900 return FALSE;
901 }
902
903 return CompareMem (Description, Property, MIN (Size, (UINT32)LenP)) == 0;
904}
905
906STATIC
907BOOLEAN
908ReadRegionInfo (
909 IN VOID *DtbAddress,
910 IN INT32 Node,
911 IN CHAR8 *Region,
912 IN UINTN RegionStrSize,
913 IN UINT32 PageSize,
914 OUT UINT64 *Address,
915 OUT UINT64 *Size
916 )
917{
918 BOOLEAN FoundBuffer;
919 INTN Status = 0;
920 UINT32 LocalSize;
921
922 FoundBuffer = CheckDescription (
923 DtbAddress,
924 Node,
925 Region,
926 RegionStrSize
927 );
928 if (!FoundBuffer) {
929 return FALSE;
930 }
931
932 DEBUG ((DEBUG_INFO, "Found Node: %a\n", Region));
933 Status = ReadProperty64 (
934 DtbAddress,
935 Node,
936 "base-address",
937 Address
938 );
939 if (Status != EFI_SUCCESS) {
940 DEBUG ((DEBUG_ERROR, "base-address missing in DTB"));
941 return FALSE;
942 }
943
944 DEBUG ((
945 DEBUG_INFO,
946 "base = 0x%llx\n",
947 *Address
948 ));
949
950 Status = ReadProperty32 (
951 DtbAddress,
952 Node,
953 "pages-count",
954 &LocalSize
955 );
956 if (Status != EFI_SUCCESS) {
957 DEBUG ((DEBUG_ERROR, "pages-count missing in DTB"));
958 return FALSE;
959 }
960
961 DEBUG ((DEBUG_ERROR, "pages-count: 0x%lx\n", LocalSize));
962
963 *Size = LocalSize * PageSize;
964 DEBUG ((
965 DEBUG_INFO,
966 "Size = 0x%llx\n",
967 *Size
968 ));
969
970 return TRUE;
971}
972
973/**
974 The constructor function calls MmInitializeMemoryServices to initialize
975 memory in MMRAM and caches EFI_MM_SYSTEM_TABLE pointer.
976
977 @param [in] ImageHandle The firmware allocated handle for the EFI image.
978 @param [in] MmSystemTable A pointer to the Management mode System Table.
979
980 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
981
982**/
983EFI_STATUS
984EFIAPI
985MemoryAllocationLibConstructor (
986 IN EFI_HANDLE ImageHandle,
987 IN EFI_MM_SYSTEM_TABLE *MmSystemTable
988 )
989{
990 EFI_MMRAM_DESCRIPTOR MmramRange;
991 INT32 Node;
992 INT32 Offset;
993 VOID *DtbAddress;
994 BOOLEAN Result;
995
996 DtbAddress = gSpst->FDTAddress;
997 DEBUG ((DEBUG_INFO, "%a - 0x%x\n", __func__, DtbAddress));
998
999 Offset = fdt_node_offset_by_compatible (DtbAddress, -1, "arm,ffa-manifest-1.0");
1000
1001 DEBUG ((DEBUG_INFO, "Offset = %d \n", Offset));
1002
1003 Offset = fdt_subnode_offset_namelen (
1004 DtbAddress,
1005 Offset,
1006 "memory-regions",
1007 sizeof ("memory-regions") - 1
1008 );
1009 if (Offset < 1) {
1010 DEBUG ((
1011 DEBUG_ERROR,
1012 "%a: Missing in FF-A boot information manifest\n",
1013 "memory-regions"
1014 ));
1015 return EFI_INVALID_PARAMETER;
1016 }
1017
1018 DEBUG ((DEBUG_INFO, "mem region offset = %d \n", Offset));
1019
1020 for (Node = fdt_first_subnode (DtbAddress, Offset);
1021 Node >= 0;
1022 Node = fdt_next_subnode (DtbAddress, Node))
1023 {
1024 Result = ReadRegionInfo (
1025 DtbAddress,
1026 Node,
1027 "heap",
1028 sizeof ("heap") - 1,
1029 EFI_PAGE_SIZE,
1030 &MmramRange.CpuStart,
1031 &MmramRange.PhysicalSize
1032 );
1033 if (!Result) {
1034 DEBUG ((DEBUG_ERROR, "Failed to read heap region\n"));
1035 return EFI_UNSUPPORTED;
1036 }
1037
1038 DEBUG ((
1039 DEBUG_INFO,
1040 "MmramRange: 0x%016lx - 0x%016lx\n",
1041 MmramRange.CpuStart,
1042 MmramRange.PhysicalSize
1043 ));
1044
1045 //
1046 // Initialize memory service using free MMRAM
1047 //
1048 DEBUG ((DEBUG_INFO, "MmInitializeMemoryServices\n"));
1049 MmInitializeMemoryServices (1, (VOID *)(UINTN)&MmramRange);
1050 break;
1051 }
1052
1053 return EFI_SUCCESS;
1054}
1055