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/Pool.c

333lines · modecode

1/** @file
2 SMM Memory pool management functions.
3
4 Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8**/
9
10#include <PiMm.h>
11
12#include <Library/BaseLib.h>
13#include <Library/DebugLib.h>
14
15#include "SecurePartitionMemoryAllocationLib.h"
16
17typedef struct {
18 UINT32 Signature;
19 BOOLEAN Available;
20 EFI_MEMORY_TYPE Type;
21 UINTN Size;
22} POOL_HEADER;
23
24typedef struct {
25 POOL_HEADER Header;
26 LIST_ENTRY Link;
27} FREE_POOL_HEADER;
28
29//
30// MIN_POOL_SHIFT must not be less than 5
31//
32#define MIN_POOL_SHIFT 6
33#define MIN_POOL_SIZE (1 << MIN_POOL_SHIFT)
34
35//
36// MAX_POOL_SHIFT must not be less than EFI_PAGE_SHIFT - 1
37//
38#define MAX_POOL_SHIFT (EFI_PAGE_SHIFT - 1)
39#define MAX_POOL_SIZE (1 << MAX_POOL_SHIFT)
40
41//
42// MAX_POOL_INDEX are calculated by maximum and minimum pool sizes
43//
44#define MAX_POOL_INDEX (MAX_POOL_SHIFT - MIN_POOL_SHIFT + 1)
45
46LIST_ENTRY mMmPoolLists[MAX_POOL_INDEX];
47//
48// To cache the MMRAM base since when Loading modules At fixed address feature is enabled,
49// all module is assigned an offset relative the MMRAM base in build time.
50//
51GLOBAL_REMOVE_IF_UNREFERENCED EFI_PHYSICAL_ADDRESS gLoadModuleAtFixAddressMmramBase = 0;
52
53/**
54 Called to initialize the memory service.
55
56 @param MmramRangeCount Number of MMRAM Regions
57 @param MmramRanges Pointer to MMRAM Descriptors
58
59**/
60VOID
61MmInitializeMemoryServices (
62 IN UINTN MmramRangeCount,
63 IN EFI_MMRAM_DESCRIPTOR *MmramRanges
64 )
65{
66 UINTN Index;
67
68 //
69 // Initialize Pool list
70 //
71 for (Index = sizeof (mMmPoolLists) / sizeof (*mMmPoolLists); Index > 0;) {
72 InitializeListHead (&mMmPoolLists[--Index]);
73 }
74
75 //
76 // Initialize free MMRAM regions
77 //
78 for (Index = 0; Index < MmramRangeCount; Index++) {
79 //
80 // BUGBUG: Add legacy MMRAM region is buggy.
81 //
82 if (MmramRanges[Index].CpuStart < BASE_1MB) {
83 continue;
84 }
85
86 DEBUG ((
87 DEBUG_INFO,
88 "MmAddMemoryRegion %d : 0x%016lx - 0x%016lx\n",
89 Index,
90 MmramRanges[Index].CpuStart,
91 MmramRanges[Index].PhysicalSize
92 ));
93 MmAddMemoryRegion (
94 MmramRanges[Index].CpuStart,
95 MmramRanges[Index].PhysicalSize,
96 EfiConventionalMemory,
97 MmramRanges[Index].RegionState
98 );
99 }
100}
101
102/**
103 Internal Function. Allocate a pool by specified PoolIndex.
104
105 @param PoolIndex Index which indicate the Pool size.
106 @param FreePoolHdr The returned Free pool.
107
108 @retval EFI_OUT_OF_RESOURCES Allocation failed.
109 @retval EFI_SUCCESS Pool successfully allocated.
110
111**/
112EFI_STATUS
113InternalAllocPoolByIndex (
114 IN UINTN PoolIndex,
115 OUT FREE_POOL_HEADER **FreePoolHdr
116 )
117{
118 EFI_STATUS Status;
119 FREE_POOL_HEADER *Hdr;
120 EFI_PHYSICAL_ADDRESS Address;
121
122 ASSERT (PoolIndex <= MAX_POOL_INDEX);
123 Status = EFI_SUCCESS;
124 Hdr = NULL;
125 if (PoolIndex == MAX_POOL_INDEX) {
126 Status = MmInternalAllocatePages (
127 AllocateAnyPages,
128 EfiRuntimeServicesData,
129 EFI_SIZE_TO_PAGES (MAX_POOL_SIZE << 1),
130 &Address
131 );
132 if (EFI_ERROR (Status)) {
133 return EFI_OUT_OF_RESOURCES;
134 }
135
136 Hdr = (FREE_POOL_HEADER *)(UINTN)Address;
137 } else if (!IsListEmpty (&mMmPoolLists[PoolIndex])) {
138 Hdr = BASE_CR (GetFirstNode (&mMmPoolLists[PoolIndex]), FREE_POOL_HEADER, Link);
139 RemoveEntryList (&Hdr->Link);
140 } else {
141 Status = InternalAllocPoolByIndex (PoolIndex + 1, &Hdr);
142 if (!EFI_ERROR (Status)) {
143 Hdr->Header.Size >>= 1;
144 Hdr->Header.Available = TRUE;
145 InsertHeadList (&mMmPoolLists[PoolIndex], &Hdr->Link);
146 Hdr = (FREE_POOL_HEADER *)((UINT8 *)Hdr + Hdr->Header.Size);
147 }
148 }
149
150 if (!EFI_ERROR (Status)) {
151 Hdr->Header.Size = MIN_POOL_SIZE << PoolIndex;
152 Hdr->Header.Available = FALSE;
153 }
154
155 *FreePoolHdr = Hdr;
156 return Status;
157}
158
159/**
160 Internal Function. Free a pool by specified PoolIndex.
161
162 @param FreePoolHdr The pool to free.
163
164 @retval EFI_SUCCESS Pool successfully freed.
165
166**/
167EFI_STATUS
168InternalFreePoolByIndex (
169 IN FREE_POOL_HEADER *FreePoolHdr
170 )
171{
172 UINTN PoolIndex;
173
174 ASSERT ((FreePoolHdr->Header.Size & (FreePoolHdr->Header.Size - 1)) == 0);
175 ASSERT (((UINTN)FreePoolHdr & (FreePoolHdr->Header.Size - 1)) == 0);
176 ASSERT (FreePoolHdr->Header.Size >= MIN_POOL_SIZE);
177
178 PoolIndex = (UINTN)(HighBitSet32 ((UINT32)FreePoolHdr->Header.Size) - MIN_POOL_SHIFT);
179 FreePoolHdr->Header.Available = TRUE;
180 if (PoolIndex >= MAX_POOL_INDEX) {
181 ASSERT (PoolIndex < MAX_POOL_INDEX);
182 return EFI_OUT_OF_RESOURCES;
183 }
184
185 InsertHeadList (&mMmPoolLists[PoolIndex], &FreePoolHdr->Link);
186 return EFI_SUCCESS;
187}
188
189/**
190 Allocate pool of a particular type.
191
192 @param PoolType Type of pool to allocate.
193 @param Size The amount of pool to allocate.
194 @param Buffer The address to return a pointer to the allocated
195 pool.
196
197 @retval EFI_INVALID_PARAMETER PoolType not valid.
198 @retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed.
199 @retval EFI_SUCCESS Pool successfully allocated.
200
201**/
202EFI_STATUS
203EFIAPI
204MmInternalAllocatePool (
205 IN EFI_MEMORY_TYPE PoolType,
206 IN UINTN Size,
207 OUT VOID **Buffer
208 )
209{
210 POOL_HEADER *PoolHdr;
211 FREE_POOL_HEADER *FreePoolHdr;
212 EFI_STATUS Status;
213 EFI_PHYSICAL_ADDRESS Address;
214 UINTN PoolIndex;
215
216 if ((PoolType != EfiRuntimeServicesCode) &&
217 (PoolType != EfiRuntimeServicesData))
218 {
219 return EFI_INVALID_PARAMETER;
220 }
221
222 Size += sizeof (*PoolHdr);
223 if (Size > MAX_POOL_SIZE) {
224 Size = EFI_SIZE_TO_PAGES (Size);
225 Status = MmInternalAllocatePages (AllocateAnyPages, PoolType, Size, &Address);
226 if (EFI_ERROR (Status)) {
227 return Status;
228 }
229
230 PoolHdr = (POOL_HEADER *)(UINTN)Address;
231 PoolHdr->Size = EFI_PAGES_TO_SIZE (Size);
232 PoolHdr->Available = FALSE;
233 *Buffer = PoolHdr + 1;
234 return Status;
235 }
236
237 Size = (Size + MIN_POOL_SIZE - 1) >> MIN_POOL_SHIFT;
238 PoolIndex = (UINTN)HighBitSet32 ((UINT32)Size);
239 if ((Size & (Size - 1)) != 0) {
240 PoolIndex++;
241 }
242
243 Status = InternalAllocPoolByIndex (PoolIndex, &FreePoolHdr);
244 if (!EFI_ERROR (Status)) {
245 *Buffer = &FreePoolHdr->Header + 1;
246 }
247
248 return Status;
249}
250
251/**
252 Allocate pool of a particular type.
253
254 @param PoolType Type of pool to allocate.
255 @param Size The amount of pool to allocate.
256 @param Buffer The address to return a pointer to the allocated
257 pool.
258
259 @retval EFI_INVALID_PARAMETER PoolType not valid.
260 @retval EFI_OUT_OF_RESOURCES Size exceeds max pool size or allocation failed.
261 @retval EFI_SUCCESS Pool successfully allocated.
262
263**/
264EFI_STATUS
265EFIAPI
266MmAllocatePool (
267 IN EFI_MEMORY_TYPE PoolType,
268 IN UINTN Size,
269 OUT VOID **Buffer
270 )
271{
272 EFI_STATUS Status;
273
274 Status = MmInternalAllocatePool (PoolType, Size, Buffer);
275 return Status;
276}
277
278/**
279 Frees pool.
280
281 @param Buffer The allocated pool entry to free.
282
283 @retval EFI_INVALID_PARAMETER Buffer is not a valid value.
284 @retval EFI_SUCCESS Pool successfully freed.
285
286**/
287EFI_STATUS
288EFIAPI
289MmInternalFreePool (
290 IN VOID *Buffer
291 )
292{
293 FREE_POOL_HEADER *FreePoolHdr;
294
295 if (Buffer == NULL) {
296 return EFI_INVALID_PARAMETER;
297 }
298
299 FreePoolHdr = (FREE_POOL_HEADER *)((POOL_HEADER *)Buffer - 1);
300 ASSERT (!FreePoolHdr->Header.Available);
301
302 if (FreePoolHdr->Header.Size > MAX_POOL_SIZE) {
303 ASSERT (((UINTN)FreePoolHdr & EFI_PAGE_MASK) == 0);
304 ASSERT ((FreePoolHdr->Header.Size & EFI_PAGE_MASK) == 0);
305 return MmInternalFreePages (
306 (EFI_PHYSICAL_ADDRESS)(UINTN)FreePoolHdr,
307 EFI_SIZE_TO_PAGES (FreePoolHdr->Header.Size)
308 );
309 }
310
311 return InternalFreePoolByIndex (FreePoolHdr);
312}
313
314/**
315 Frees pool.
316
317 @param Buffer The allocated pool entry to free.
318
319 @retval EFI_INVALID_PARAMETER Buffer is not a valid value.
320 @retval EFI_SUCCESS Pool successfully freed.
321
322**/
323EFI_STATUS
324EFIAPI
325MmFreePool (
326 IN VOID *Buffer
327 )
328{
329 EFI_STATUS Status;
330
331 Status = MmInternalFreePool (Buffer);
332 return Status;
333}
334