2 Locate, get and update PE/COFF permissions during Standalone MM
3 Foundation Entry point on ARM platforms.
5 Copyright (c) 2017 - 2021, Arm Ltd. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
14 #include <Guid/MmramMemoryReserve.h>
15 #include <Guid/MpInformation.h>
17 #include <Library/AArch64/StandaloneMmCoreEntryPoint.h>
18 #include <Library/ArmMmuLib.h>
19 #include <Library/ArmSvcLib.h>
20 #include <Library/DebugLib.h>
21 #include <Library/HobLib.h>
22 #include <Library/BaseLib.h>
23 #include <Library/BaseMemoryLib.h>
24 #include <Library/SerialPortLib.h>
26 #include <IndustryStandard/ArmStdSmc.h>
30 UpdateMmFoundationPeCoffPermissions (
31 IN CONST PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
,
32 IN EFI_PHYSICAL_ADDRESS ImageBase
,
33 IN UINT32 SectionHeaderOffset
,
34 IN CONST UINT16 NumberOfSections
,
35 IN REGION_PERMISSION_UPDATE_FUNC TextUpdater
,
36 IN REGION_PERMISSION_UPDATE_FUNC ReadOnlyUpdater
,
37 IN REGION_PERMISSION_UPDATE_FUNC ReadWriteUpdater
40 EFI_IMAGE_SECTION_HEADER SectionHeader
;
42 EFI_PHYSICAL_ADDRESS Base
;
47 ASSERT (ImageContext
!= NULL
);
50 // Iterate over the sections
52 for (Index
= 0; Index
< NumberOfSections
; Index
++) {
54 // Read section header from file
56 Size
= sizeof (EFI_IMAGE_SECTION_HEADER
);
58 Status
= ImageContext
->ImageRead (
65 if (RETURN_ERROR (Status
) || (Size
!= ReadSize
)) {
67 "%a: ImageContext->ImageRead () failed (Status = %r)\n",
68 __FUNCTION__
, Status
));
73 "%a: Section %d of image at 0x%lx has 0x%x permissions\n",
74 __FUNCTION__
, Index
, ImageContext
->ImageAddress
, SectionHeader
.Characteristics
));
76 "%a: Section %d of image at 0x%lx has %a name\n",
77 __FUNCTION__
, Index
, ImageContext
->ImageAddress
, SectionHeader
.Name
));
79 "%a: Section %d of image at 0x%lx has 0x%x address\n",
80 __FUNCTION__
, Index
, ImageContext
->ImageAddress
,
81 ImageContext
->ImageAddress
+ SectionHeader
.VirtualAddress
));
83 "%a: Section %d of image at 0x%lx has 0x%x data\n",
84 __FUNCTION__
, Index
, ImageContext
->ImageAddress
, SectionHeader
.PointerToRawData
));
87 // If the section is marked as XN then remove the X attribute. Furthermore,
88 // if it is a writeable section then mark it appropriately as well.
90 if ((SectionHeader
.Characteristics
& EFI_IMAGE_SCN_MEM_EXECUTE
) == 0) {
91 Base
= ImageBase
+ SectionHeader
.VirtualAddress
;
93 TextUpdater (Base
, SectionHeader
.Misc
.VirtualSize
);
95 if ((SectionHeader
.Characteristics
& EFI_IMAGE_SCN_MEM_WRITE
) != 0) {
96 ReadWriteUpdater (Base
, SectionHeader
.Misc
.VirtualSize
);
98 "%a: Mapping section %d of image at 0x%lx with RW-XN permissions\n",
99 __FUNCTION__
, Index
, ImageContext
->ImageAddress
));
102 "%a: Mapping section %d of image at 0x%lx with RO-XN permissions\n",
103 __FUNCTION__
, Index
, ImageContext
->ImageAddress
));
107 "%a: Ignoring section %d of image at 0x%lx with 0x%x permissions\n",
108 __FUNCTION__
, Index
, ImageContext
->ImageAddress
, SectionHeader
.Characteristics
));
110 SectionHeaderOffset
+= sizeof (EFI_IMAGE_SECTION_HEADER
);
113 return RETURN_SUCCESS
;
118 LocateStandaloneMmCorePeCoffData (
119 IN EFI_FIRMWARE_VOLUME_HEADER
*BfvAddress
,
120 IN OUT VOID
**TeData
,
121 IN OUT UINTN
*TeDataSize
124 EFI_FFS_FILE_HEADER
*FileHeader
;
128 Status
= FfsFindNextFile (
129 EFI_FV_FILETYPE_SECURITY_CORE
,
134 if (EFI_ERROR (Status
)) {
135 DEBUG ((DEBUG_ERROR
, "Unable to locate Standalone MM FFS file - 0x%x\n",
140 Status
= FfsFindSectionData (EFI_SECTION_PE32
, FileHeader
, TeData
, TeDataSize
);
141 if (EFI_ERROR (Status
)) {
142 Status
= FfsFindSectionData (EFI_SECTION_TE
, FileHeader
, TeData
, TeDataSize
);
143 if (EFI_ERROR (Status
)) {
144 DEBUG ((DEBUG_ERROR
, "Unable to locate Standalone MM Section data - %r\n",
150 DEBUG ((DEBUG_INFO
, "Found Standalone MM PE data - 0x%x\n", *TeData
));
156 GetPeCoffSectionInformation (
157 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
,
158 OUT EFI_PHYSICAL_ADDRESS
*ImageBase
,
159 OUT UINT32
*SectionHeaderOffset
,
160 OUT UINT16
*NumberOfSections
163 RETURN_STATUS Status
;
164 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
165 EFI_IMAGE_OPTIONAL_HEADER_UNION HdrData
;
169 ASSERT (ImageContext
!= NULL
);
170 ASSERT (SectionHeaderOffset
!= NULL
);
171 ASSERT (NumberOfSections
!= NULL
);
173 Status
= PeCoffLoaderGetImageInfo (ImageContext
);
174 if (RETURN_ERROR (Status
)) {
176 "%a: PeCoffLoaderGetImageInfo () failed (Status == %r)\n",
177 __FUNCTION__
, Status
));
181 if (ImageContext
->SectionAlignment
< EFI_PAGE_SIZE
) {
183 // The sections need to be at least 4 KB aligned, since that is the
184 // granularity at which we can tighten permissions.
186 if (!ImageContext
->IsTeImage
) {
188 "%a: non-TE Image at 0x%lx has SectionAlignment < 4 KB (%lu)\n",
189 __FUNCTION__
, ImageContext
->ImageAddress
, ImageContext
->SectionAlignment
));
190 return RETURN_UNSUPPORTED
;
192 ImageContext
->SectionAlignment
= EFI_PAGE_SIZE
;
196 // Read the PE/COFF Header. For PE32 (32-bit) this will read in too much
197 // data, but that should not hurt anything. Hdr.Pe32->OptionalHeader.Magic
198 // determines if this is a PE32 or PE32+ image. The magic is in the same
199 // location in both images.
201 Hdr
.Union
= &HdrData
;
202 Size
= sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION
);
204 Status
= ImageContext
->ImageRead (
205 ImageContext
->Handle
,
206 ImageContext
->PeCoffHeaderOffset
,
211 if (RETURN_ERROR (Status
) || (Size
!= ReadSize
)) {
213 "%a: TmpContext->ImageRead () failed (Status = %r)\n",
214 __FUNCTION__
, Status
));
218 *ImageBase
= ImageContext
->ImageAddress
;
219 if (!ImageContext
->IsTeImage
) {
220 ASSERT (Hdr
.Pe32
->Signature
== EFI_IMAGE_NT_SIGNATURE
);
222 *SectionHeaderOffset
= ImageContext
->PeCoffHeaderOffset
+ sizeof (UINT32
) +
223 sizeof (EFI_IMAGE_FILE_HEADER
);
224 *NumberOfSections
= Hdr
.Pe32
->FileHeader
.NumberOfSections
;
226 switch (Hdr
.Pe32
->OptionalHeader
.Magic
) {
227 case EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
:
228 *SectionHeaderOffset
+= Hdr
.Pe32
->FileHeader
.SizeOfOptionalHeader
;
230 case EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
:
231 *SectionHeaderOffset
+= Hdr
.Pe32Plus
->FileHeader
.SizeOfOptionalHeader
;
237 *SectionHeaderOffset
= (UINTN
)(sizeof (EFI_TE_IMAGE_HEADER
));
238 *NumberOfSections
= Hdr
.Te
->NumberOfSections
;
239 *ImageBase
-= (UINT32
)Hdr
.Te
->StrippedSize
- sizeof (EFI_TE_IMAGE_HEADER
);
241 return RETURN_SUCCESS
;
246 GetStandaloneMmCorePeCoffSections (
248 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
,
249 OUT EFI_PHYSICAL_ADDRESS
*ImageBase
,
250 IN OUT UINT32
*SectionHeaderOffset
,
251 IN OUT UINT16
*NumberOfSections
256 // Initialize the Image Context
257 ZeroMem (ImageContext
, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT
));
258 ImageContext
->Handle
= TeData
;
259 ImageContext
->ImageRead
= PeCoffLoaderImageReadFromMemory
;
261 DEBUG ((DEBUG_INFO
, "Found Standalone MM PE data - 0x%x\n", TeData
));
263 Status
= GetPeCoffSectionInformation (ImageContext
, ImageBase
,
264 SectionHeaderOffset
, NumberOfSections
);
265 if (EFI_ERROR (Status
)) {
266 DEBUG ((DEBUG_ERROR
, "Unable to locate Standalone MM Core PE-COFF Section information - %r\n", Status
));
270 DEBUG ((DEBUG_INFO
, "Standalone MM Core PE-COFF SectionHeaderOffset - 0x%x, NumberOfSections - %d\n",
271 *SectionHeaderOffset
, *NumberOfSections
));