microsoft/mu_feature_ffa

Public

mirrored from https://github.com/microsoft/mu_feature_ffaAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v0.1.7

Branches

Tags

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

Clone

HTTPS

Download ZIP

FfaFeaturePkg/Library/SecurePartitionEntryPoint/SetPermissions.c

402lines · modeblame

4737fd0cKun Qin1 years ago1/** @file
2Locate, get and update PE/COFF permissions during Standalone MM
3Foundation 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>
2eee9be7Aaron4 months ago17#include <Library/MmuLib.h>
4737fd0cKun Qin1 years ago18#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/**
28Privileged firmware assigns RO & Executable attributes to all memory occupied
29by the Boot Firmware Volume. This function sets the correct permissions of
30sections in the Standalone MM Core module to be able to access RO and RW data
31and 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 (
45IN CONST PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
46IN EFI_PHYSICAL_ADDRESS ImageBase,
47IN UINT32 SectionHeaderOffset,
48IN CONST UINT16 NumberOfSections,
49IN REGION_PERMISSION_UPDATE_FUNC TextUpdater,
50IN REGION_PERMISSION_UPDATE_FUNC ReadOnlyUpdater,
51IN REGION_PERMISSION_UPDATE_FUNC ReadWriteUpdater
52)
53{
54EFI_IMAGE_SECTION_HEADER SectionHeader;
55RETURN_STATUS Status;
56EFI_PHYSICAL_ADDRESS Base;
57UINTN Size;
58UINTN ReadSize;
59UINTN Index;
60
61ASSERT (ImageContext != NULL);
62
63//
64// Iterate over the sections
65//
66for (Index = 0; Index < NumberOfSections; Index++) {
67//
68// Read section header from file
69//
70Size = sizeof (EFI_IMAGE_SECTION_HEADER);
71ReadSize = Size;
72Status = ImageContext->ImageRead (
73ImageContext->Handle,
74SectionHeaderOffset,
75&Size,
76&SectionHeader
77);
78
79if (RETURN_ERROR (Status) || (Size != ReadSize)) {
80DEBUG ((
81DEBUG_ERROR,
82"%a: ImageContext->ImageRead () failed (Status = %r)\n",
83__func__,
84Status
85));
86return Status;
87}
88
89DEBUG ((
90DEBUG_INFO,
91"%a: Section %d of image at 0x%lx has 0x%x permissions\n",
92__func__,
93Index,
94ImageContext->ImageAddress,
95SectionHeader.Characteristics
96));
97DEBUG ((
98DEBUG_INFO,
99"%a: Section %d of image at 0x%lx has %a name\n",
100__func__,
101Index,
102ImageContext->ImageAddress,
103SectionHeader.Name
104));
105DEBUG ((
106DEBUG_INFO,
107"%a: Section %d of image at 0x%lx has 0x%x address\n",
108__func__,
109Index,
110ImageContext->ImageAddress,
111ImageContext->ImageAddress + SectionHeader.VirtualAddress
112));
113DEBUG ((
114DEBUG_INFO,
115"%a: Section %d of image at 0x%lx has 0x%x data\n",
116__func__,
117Index,
118ImageContext->ImageAddress,
119SectionHeader.PointerToRawData
120));
121DEBUG ((
122DEBUG_INFO,
123"%a: Section %d of image at 0x%lx has %d bytes size\n",
124__FUNCTION__,
125Index,
126ImageContext->ImageAddress,
127SectionHeader.Misc.VirtualSize
128));
129
130// Skip sections with a size of 0
131if (SectionHeader.Misc.VirtualSize == 0) {
132DEBUG ((
133DEBUG_INFO,
134"%a: Skipping section %a \n",
135__FUNCTION__,
136SectionHeader.Name
137));
138continue;
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//
145if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_MEM_EXECUTE) == 0) {
146Base = ImageBase + SectionHeader.VirtualAddress;
147
148TextUpdater (Base, SectionHeader.Misc.VirtualSize);
149
150if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_MEM_WRITE) != 0) {
151ReadWriteUpdater (Base, SectionHeader.Misc.VirtualSize);
152DEBUG ((
153DEBUG_INFO,
154"%a: Mapping section %d of image at 0x%lx with RW-XN permissions\n",
155__func__,
156Index,
157ImageContext->ImageAddress
158));
159} else {
160DEBUG ((
161DEBUG_INFO,
162"%a: Mapping section %d of image at 0x%lx with RO-XN permissions\n",
163__func__,
164Index,
165ImageContext->ImageAddress
166));
167}
168} else {
169DEBUG ((
170DEBUG_INFO,
171"%a: Ignoring section %d of image at 0x%lx with 0x%x permissions\n",
172__func__,
173Index,
174ImageContext->ImageAddress,
175SectionHeader.Characteristics
176));
177}
178
179SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
180}
181
182return RETURN_SUCCESS;
183}
184
185/**
186Privileged firmware assigns RO & Executable attributes to all memory occupied
187by the Boot Firmware Volume. This function locates the Standalone MM Core
188module 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
192for PE/COFF image data
193@param [in, out] TeDataSize Pointer to size of PE/COFF image data
194
195**/
196EFI_STATUS
197EFIAPI
198LocateStandaloneMmCorePeCoffData (
199IN EFI_FIRMWARE_VOLUME_HEADER *BfvAddress,
200IN OUT VOID **TeData,
201IN OUT UINTN *TeDataSize
202)
203{
204EFI_FFS_FILE_HEADER *FileHeader;
205EFI_STATUS Status;
206
207FileHeader = NULL;
208Status = FfsFindNextFile (
209EFI_FV_FILETYPE_SECURITY_CORE,
210BfvAddress,
211&FileHeader
212);
213
214if (EFI_ERROR (Status)) {
215DEBUG ((
216DEBUG_ERROR,
217"Unable to locate Standalone MM FFS file - 0x%x\n",
218Status
219));
220return Status;
221}
222
223Status = FfsFindSectionData (EFI_SECTION_PE32, FileHeader, TeData, TeDataSize);
224if (EFI_ERROR (Status)) {
225Status = FfsFindSectionData (EFI_SECTION_TE, FileHeader, TeData, TeDataSize);
226if (EFI_ERROR (Status)) {
227DEBUG ((
228DEBUG_ERROR,
229"Unable to locate Standalone MM Section data - %r\n",
230Status
231));
232return Status;
233}
234}
235
236DEBUG ((DEBUG_INFO, "Found Standalone MM PE data - 0x%x\n", *TeData));
237return Status;
238}
239
240/**
241Returns 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 (
252IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
253OUT EFI_PHYSICAL_ADDRESS *ImageBase,
254OUT UINT32 *SectionHeaderOffset,
255OUT UINT16 *NumberOfSections
256)
257{
258RETURN_STATUS Status;
259EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
260EFI_IMAGE_OPTIONAL_HEADER_UNION HdrData;
261UINTN Size;
262UINTN ReadSize;
263
264ASSERT (ImageContext != NULL);
265ASSERT (SectionHeaderOffset != NULL);
266ASSERT (NumberOfSections != NULL);
267
268Status = PeCoffLoaderGetImageInfo (ImageContext);
269if (RETURN_ERROR (Status)) {
270DEBUG ((
271DEBUG_ERROR,
272"%a: PeCoffLoaderGetImageInfo () failed (Status == %r)\n",
273__func__,
274Status
275));
276return Status;
277}
278
279if (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//
284if (!ImageContext->IsTeImage) {
285DEBUG ((
286DEBUG_WARN,
287"%a: non-TE Image at 0x%lx has SectionAlignment < 4 KB (%lu)\n",
288__func__,
289ImageContext->ImageAddress,
290ImageContext->SectionAlignment
291));
292return RETURN_UNSUPPORTED;
293}
294
295ImageContext->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//
304Hdr.Union = &HdrData;
305Size = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION);
306ReadSize = Size;
307Status = ImageContext->ImageRead (
308ImageContext->Handle,
309ImageContext->PeCoffHeaderOffset,
310&Size,
311Hdr.Pe32
312);
313
314if (RETURN_ERROR (Status) || (Size != ReadSize)) {
315DEBUG ((
316DEBUG_ERROR,
317"%a: TmpContext->ImageRead () failed (Status = %r)\n",
318__func__,
319Status
320));
321return Status;
322}
323
324*ImageBase = ImageContext->ImageAddress;
325if (!ImageContext->IsTeImage) {
326ASSERT (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE);
327
328*SectionHeaderOffset = ImageContext->PeCoffHeaderOffset + sizeof (UINT32) +
329sizeof (EFI_IMAGE_FILE_HEADER);
330*NumberOfSections = Hdr.Pe32->FileHeader.NumberOfSections;
331
332switch (Hdr.Pe32->OptionalHeader.Magic) {
333case EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC:
334*SectionHeaderOffset += Hdr.Pe32->FileHeader.SizeOfOptionalHeader;
335break;
336case EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC:
337*SectionHeaderOffset += Hdr.Pe32Plus->FileHeader.SizeOfOptionalHeader;
338break;
339default:
340ASSERT (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
348return RETURN_SUCCESS;
349}
350
351/**
352Privileged firmware assigns RO & Executable attributes to all memory occupied
353by the Boot Firmware Volume. This function locates the section information of
354the Standalone MM Core module to be able to change permissions of the
355individual 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 (
367IN VOID *TeData,
368IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
369OUT EFI_PHYSICAL_ADDRESS *ImageBase,
370IN OUT UINT32 *SectionHeaderOffset,
371IN OUT UINT16 *NumberOfSections
372)
373{
374EFI_STATUS Status;
375
376// Initialize the Image Context
377ZeroMem (ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));
378ImageContext->Handle = TeData;
379ImageContext->ImageRead = PeCoffLoaderImageReadFromMemory;
380
381DEBUG ((DEBUG_INFO, "Found Standalone MM PE data - 0x%x\n", TeData));
382
383Status = GetPeCoffSectionInformation (
384ImageContext,
385ImageBase,
386SectionHeaderOffset,
387NumberOfSections
388);
389if (EFI_ERROR (Status)) {
390DEBUG ((DEBUG_ERROR, "Unable to locate Standalone MM Core PE-COFF Section information - %r\n", Status));
391return Status;
392}
393
394DEBUG ((
395DEBUG_INFO,
396"Standalone MM Core PE-COFF SectionHeaderOffset - 0x%x, NumberOfSections - %d\n",
397*SectionHeaderOffset,
398*NumberOfSections
399));
400
401return Status;
402}