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/SecurePartitionEntryPoint/SetPermissions.c

402lines · modecode

1/** @file
2 Locate, get and update PE/COFF permissions during Standalone MM
3 Foundation Entry point on ARM platforms.
4
5Copyright (c) 2017 - 2021, Arm Ltd. All rights reserved.<BR>
6SPDX-License-Identifier: BSD-2-Clause-Patent
7
8**/
9
10#include <PiMm.h>
11
12#include <PiPei.h>
13#include <Guid/MmramMemoryReserve.h>
14#include <Guid/MpInformation.h>
15
16#include <Library/ArmStandaloneMmCoreEntryPoint.h>
17#include <Library/ArmMmuLib.h>
18#include <Library/ArmSvcLib.h>
19#include <Library/DebugLib.h>
20#include <Library/HobLib.h>
21#include <Library/BaseLib.h>
22#include <Library/BaseMemoryLib.h>
23#include <Library/SerialPortLib.h>
24
25#include <IndustryStandard/ArmStdSmc.h>
26
27/**
28 Privileged firmware assigns RO & Executable attributes to all memory occupied
29 by the Boot Firmware Volume. This function sets the correct permissions of
30 sections in the Standalone MM Core module to be able to access RO and RW data
31 and make further progress in the boot process.
32
33 @param [in] ImageContext Pointer to PE/COFF image context
34 @param [in] ImageBase Base of image in memory
35 @param [in] SectionHeaderOffset Offset of PE/COFF image section header
36 @param [in] NumberOfSections Number of Sections
37 @param [in] TextUpdater Function to change code permissions
38 @param [in] ReadOnlyUpdater Function to change RO permissions
39 @param [in] ReadWriteUpdater Function to change RW permissions
40
41**/
42EFI_STATUS
43EFIAPI
44UpdateMmFoundationPeCoffPermissions (
45 IN CONST PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
46 IN EFI_PHYSICAL_ADDRESS ImageBase,
47 IN UINT32 SectionHeaderOffset,
48 IN CONST UINT16 NumberOfSections,
49 IN REGION_PERMISSION_UPDATE_FUNC TextUpdater,
50 IN REGION_PERMISSION_UPDATE_FUNC ReadOnlyUpdater,
51 IN REGION_PERMISSION_UPDATE_FUNC ReadWriteUpdater
52 )
53{
54 EFI_IMAGE_SECTION_HEADER SectionHeader;
55 RETURN_STATUS Status;
56 EFI_PHYSICAL_ADDRESS Base;
57 UINTN Size;
58 UINTN ReadSize;
59 UINTN Index;
60
61 ASSERT (ImageContext != NULL);
62
63 //
64 // Iterate over the sections
65 //
66 for (Index = 0; Index < NumberOfSections; Index++) {
67 //
68 // Read section header from file
69 //
70 Size = sizeof (EFI_IMAGE_SECTION_HEADER);
71 ReadSize = Size;
72 Status = ImageContext->ImageRead (
73 ImageContext->Handle,
74 SectionHeaderOffset,
75 &Size,
76 &SectionHeader
77 );
78
79 if (RETURN_ERROR (Status) || (Size != ReadSize)) {
80 DEBUG ((
81 DEBUG_ERROR,
82 "%a: ImageContext->ImageRead () failed (Status = %r)\n",
83 __func__,
84 Status
85 ));
86 return Status;
87 }
88
89 DEBUG ((
90 DEBUG_INFO,
91 "%a: Section %d of image at 0x%lx has 0x%x permissions\n",
92 __func__,
93 Index,
94 ImageContext->ImageAddress,
95 SectionHeader.Characteristics
96 ));
97 DEBUG ((
98 DEBUG_INFO,
99 "%a: Section %d of image at 0x%lx has %a name\n",
100 __func__,
101 Index,
102 ImageContext->ImageAddress,
103 SectionHeader.Name
104 ));
105 DEBUG ((
106 DEBUG_INFO,
107 "%a: Section %d of image at 0x%lx has 0x%x address\n",
108 __func__,
109 Index,
110 ImageContext->ImageAddress,
111 ImageContext->ImageAddress + SectionHeader.VirtualAddress
112 ));
113 DEBUG ((
114 DEBUG_INFO,
115 "%a: Section %d of image at 0x%lx has 0x%x data\n",
116 __func__,
117 Index,
118 ImageContext->ImageAddress,
119 SectionHeader.PointerToRawData
120 ));
121 DEBUG ((
122 DEBUG_INFO,
123 "%a: Section %d of image at 0x%lx has %d bytes size\n",
124 __FUNCTION__,
125 Index,
126 ImageContext->ImageAddress,
127 SectionHeader.Misc.VirtualSize
128 ));
129
130 // Skip sections with a size of 0
131 if (SectionHeader.Misc.VirtualSize == 0) {
132 DEBUG ((
133 DEBUG_INFO,
134 "%a: Skipping section %a \n",
135 __FUNCTION__,
136 SectionHeader.Name
137 ));
138 continue;
139 }
140
141 //
142 // If the section is marked as XN then remove the X attribute. Furthermore,
143 // if it is a writeable section then mark it appropriately as well.
144 //
145 if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_MEM_EXECUTE) == 0) {
146 Base = ImageBase + SectionHeader.VirtualAddress;
147
148 TextUpdater (Base, SectionHeader.Misc.VirtualSize);
149
150 if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_MEM_WRITE) != 0) {
151 ReadWriteUpdater (Base, SectionHeader.Misc.VirtualSize);
152 DEBUG ((
153 DEBUG_INFO,
154 "%a: Mapping section %d of image at 0x%lx with RW-XN permissions\n",
155 __func__,
156 Index,
157 ImageContext->ImageAddress
158 ));
159 } else {
160 DEBUG ((
161 DEBUG_INFO,
162 "%a: Mapping section %d of image at 0x%lx with RO-XN permissions\n",
163 __func__,
164 Index,
165 ImageContext->ImageAddress
166 ));
167 }
168 } else {
169 DEBUG ((
170 DEBUG_INFO,
171 "%a: Ignoring section %d of image at 0x%lx with 0x%x permissions\n",
172 __func__,
173 Index,
174 ImageContext->ImageAddress,
175 SectionHeader.Characteristics
176 ));
177 }
178
179 SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
180 }
181
182 return RETURN_SUCCESS;
183}
184
185/**
186 Privileged firmware assigns RO & Executable attributes to all memory occupied
187 by the Boot Firmware Volume. This function locates the Standalone MM Core
188 module PE/COFF image in the BFV and returns this information.
189
190 @param [in] BfvAddress Base Address of Boot Firmware Volume
191 @param [in, out] TeData Pointer to address for allocating memory
192 for PE/COFF image data
193 @param [in, out] TeDataSize Pointer to size of PE/COFF image data
194
195**/
196EFI_STATUS
197EFIAPI
198LocateStandaloneMmCorePeCoffData (
199 IN EFI_FIRMWARE_VOLUME_HEADER *BfvAddress,
200 IN OUT VOID **TeData,
201 IN OUT UINTN *TeDataSize
202 )
203{
204 EFI_FFS_FILE_HEADER *FileHeader;
205 EFI_STATUS Status;
206
207 FileHeader = NULL;
208 Status = FfsFindNextFile (
209 EFI_FV_FILETYPE_SECURITY_CORE,
210 BfvAddress,
211 &FileHeader
212 );
213
214 if (EFI_ERROR (Status)) {
215 DEBUG ((
216 DEBUG_ERROR,
217 "Unable to locate Standalone MM FFS file - 0x%x\n",
218 Status
219 ));
220 return Status;
221 }
222
223 Status = FfsFindSectionData (EFI_SECTION_PE32, FileHeader, TeData, TeDataSize);
224 if (EFI_ERROR (Status)) {
225 Status = FfsFindSectionData (EFI_SECTION_TE, FileHeader, TeData, TeDataSize);
226 if (EFI_ERROR (Status)) {
227 DEBUG ((
228 DEBUG_ERROR,
229 "Unable to locate Standalone MM Section data - %r\n",
230 Status
231 ));
232 return Status;
233 }
234 }
235
236 DEBUG ((DEBUG_INFO, "Found Standalone MM PE data - 0x%x\n", *TeData));
237 return Status;
238}
239
240/**
241 Returns the PC COFF section information.
242
243 @param [in, out] ImageContext Pointer to PE/COFF image context
244 @param [out] ImageBase Base of image in memory
245 @param [out] SectionHeaderOffset Offset of PE/COFF image section header
246 @param [out] NumberOfSections Number of Sections
247
248**/
249STATIC
250EFI_STATUS
251GetPeCoffSectionInformation (
252 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
253 OUT EFI_PHYSICAL_ADDRESS *ImageBase,
254 OUT UINT32 *SectionHeaderOffset,
255 OUT UINT16 *NumberOfSections
256 )
257{
258 RETURN_STATUS Status;
259 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
260 EFI_IMAGE_OPTIONAL_HEADER_UNION HdrData;
261 UINTN Size;
262 UINTN ReadSize;
263
264 ASSERT (ImageContext != NULL);
265 ASSERT (SectionHeaderOffset != NULL);
266 ASSERT (NumberOfSections != NULL);
267
268 Status = PeCoffLoaderGetImageInfo (ImageContext);
269 if (RETURN_ERROR (Status)) {
270 DEBUG ((
271 DEBUG_ERROR,
272 "%a: PeCoffLoaderGetImageInfo () failed (Status == %r)\n",
273 __func__,
274 Status
275 ));
276 return Status;
277 }
278
279 if (ImageContext->SectionAlignment < EFI_PAGE_SIZE) {
280 //
281 // The sections need to be at least 4 KB aligned, since that is the
282 // granularity at which we can tighten permissions.
283 //
284 if (!ImageContext->IsTeImage) {
285 DEBUG ((
286 DEBUG_WARN,
287 "%a: non-TE Image at 0x%lx has SectionAlignment < 4 KB (%lu)\n",
288 __func__,
289 ImageContext->ImageAddress,
290 ImageContext->SectionAlignment
291 ));
292 return RETURN_UNSUPPORTED;
293 }
294
295 ImageContext->SectionAlignment = EFI_PAGE_SIZE;
296 }
297
298 //
299 // Read the PE/COFF Header. For PE32 (32-bit) this will read in too much
300 // data, but that should not hurt anything. Hdr.Pe32->OptionalHeader.Magic
301 // determines if this is a PE32 or PE32+ image. The magic is in the same
302 // location in both images.
303 //
304 Hdr.Union = &HdrData;
305 Size = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION);
306 ReadSize = Size;
307 Status = ImageContext->ImageRead (
308 ImageContext->Handle,
309 ImageContext->PeCoffHeaderOffset,
310 &Size,
311 Hdr.Pe32
312 );
313
314 if (RETURN_ERROR (Status) || (Size != ReadSize)) {
315 DEBUG ((
316 DEBUG_ERROR,
317 "%a: TmpContext->ImageRead () failed (Status = %r)\n",
318 __func__,
319 Status
320 ));
321 return Status;
322 }
323
324 *ImageBase = ImageContext->ImageAddress;
325 if (!ImageContext->IsTeImage) {
326 ASSERT (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE);
327
328 *SectionHeaderOffset = ImageContext->PeCoffHeaderOffset + sizeof (UINT32) +
329 sizeof (EFI_IMAGE_FILE_HEADER);
330 *NumberOfSections = Hdr.Pe32->FileHeader.NumberOfSections;
331
332 switch (Hdr.Pe32->OptionalHeader.Magic) {
333 case EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC:
334 *SectionHeaderOffset += Hdr.Pe32->FileHeader.SizeOfOptionalHeader;
335 break;
336 case EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC:
337 *SectionHeaderOffset += Hdr.Pe32Plus->FileHeader.SizeOfOptionalHeader;
338 break;
339 default:
340 ASSERT (FALSE);
341 }
342 } else {
343 *SectionHeaderOffset = (UINTN)(sizeof (EFI_TE_IMAGE_HEADER));
344 *NumberOfSections = Hdr.Te->NumberOfSections;
345 *ImageBase -= (UINT32)Hdr.Te->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER);
346 }
347
348 return RETURN_SUCCESS;
349}
350
351/**
352 Privileged firmware assigns RO & Executable attributes to all memory occupied
353 by the Boot Firmware Volume. This function locates the section information of
354 the Standalone MM Core module to be able to change permissions of the
355 individual sections later in the boot process.
356
357 @param [in] TeData Pointer to PE/COFF image data
358 @param [in, out] ImageContext Pointer to PE/COFF image context
359 @param [out] ImageBase Pointer to ImageBase variable
360 @param [in, out] SectionHeaderOffset Offset of PE/COFF image section header
361 @param [in, out] NumberOfSections Number of Sections
362
363**/
364EFI_STATUS
365EFIAPI
366GetStandaloneMmCorePeCoffSections (
367 IN VOID *TeData,
368 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
369 OUT EFI_PHYSICAL_ADDRESS *ImageBase,
370 IN OUT UINT32 *SectionHeaderOffset,
371 IN OUT UINT16 *NumberOfSections
372 )
373{
374 EFI_STATUS Status;
375
376 // Initialize the Image Context
377 ZeroMem (ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));
378 ImageContext->Handle = TeData;
379 ImageContext->ImageRead = PeCoffLoaderImageReadFromMemory;
380
381 DEBUG ((DEBUG_INFO, "Found Standalone MM PE data - 0x%x\n", TeData));
382
383 Status = GetPeCoffSectionInformation (
384 ImageContext,
385 ImageBase,
386 SectionHeaderOffset,
387 NumberOfSections
388 );
389 if (EFI_ERROR (Status)) {
390 DEBUG ((DEBUG_ERROR, "Unable to locate Standalone MM Core PE-COFF Section information - %r\n", Status));
391 return Status;
392 }
393
394 DEBUG ((
395 DEBUG_INFO,
396 "Standalone MM Core PE-COFF SectionHeaderOffset - 0x%x, NumberOfSections - %d\n",
397 *SectionHeaderOffset,
398 *NumberOfSections
399 ));
400
401 return Status;
402}