2 Locate, get and update PE/COFF permissions during Standalone MM
3 Foundation Entry point on ARM platforms.
5 Copyright (c) 2017 - 2018, 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 UINT32 SectionHeaderOffset
,
33 IN CONST UINT16 NumberOfSections
,
34 IN REGION_PERMISSION_UPDATE_FUNC TextUpdater
,
35 IN REGION_PERMISSION_UPDATE_FUNC ReadOnlyUpdater
,
36 IN REGION_PERMISSION_UPDATE_FUNC ReadWriteUpdater
39 EFI_IMAGE_SECTION_HEADER SectionHeader
;
41 EFI_PHYSICAL_ADDRESS Base
;
46 ASSERT (ImageContext
!= NULL
);
49 // Iterate over the sections
51 for (Index
= 0; Index
< NumberOfSections
; Index
++) {
53 // Read section header from file
55 Size
= sizeof (EFI_IMAGE_SECTION_HEADER
);
57 Status
= ImageContext
->ImageRead (
64 if (RETURN_ERROR (Status
) || (Size
!= ReadSize
)) {
66 "%a: ImageContext->ImageRead () failed (Status = %r)\n",
67 __FUNCTION__
, Status
));
72 "%a: Section %d of image at 0x%lx has 0x%x permissions\n",
73 __FUNCTION__
, Index
, ImageContext
->ImageAddress
, SectionHeader
.Characteristics
));
75 "%a: Section %d of image at 0x%lx has %a name\n",
76 __FUNCTION__
, Index
, ImageContext
->ImageAddress
, SectionHeader
.Name
));
78 "%a: Section %d of image at 0x%lx has 0x%x address\n",
79 __FUNCTION__
, Index
, ImageContext
->ImageAddress
,
80 ImageContext
->ImageAddress
+ SectionHeader
.VirtualAddress
));
82 "%a: Section %d of image at 0x%lx has 0x%x data\n",
83 __FUNCTION__
, Index
, ImageContext
->ImageAddress
, SectionHeader
.PointerToRawData
));
86 // If the section is marked as XN then remove the X attribute. Furthermore,
87 // if it is a writeable section then mark it appropriately as well.
89 if ((SectionHeader
.Characteristics
& EFI_IMAGE_SCN_MEM_EXECUTE
) == 0) {
90 Base
= ImageContext
->ImageAddress
+ SectionHeader
.VirtualAddress
;
92 TextUpdater (Base
, SectionHeader
.Misc
.VirtualSize
);
94 if ((SectionHeader
.Characteristics
& EFI_IMAGE_SCN_MEM_WRITE
) != 0) {
95 ReadWriteUpdater (Base
, SectionHeader
.Misc
.VirtualSize
);
97 "%a: Mapping section %d of image at 0x%lx with RW-XN permissions\n",
98 __FUNCTION__
, Index
, ImageContext
->ImageAddress
));
101 "%a: Mapping section %d of image at 0x%lx with RO-XN permissions\n",
102 __FUNCTION__
, Index
, ImageContext
->ImageAddress
));
106 "%a: Ignoring section %d of image at 0x%lx with 0x%x permissions\n",
107 __FUNCTION__
, Index
, ImageContext
->ImageAddress
, SectionHeader
.Characteristics
));
109 SectionHeaderOffset
+= sizeof (EFI_IMAGE_SECTION_HEADER
);
112 return RETURN_SUCCESS
;
117 LocateStandaloneMmCorePeCoffData (
118 IN EFI_FIRMWARE_VOLUME_HEADER
*BfvAddress
,
119 IN OUT VOID
**TeData
,
120 IN OUT UINTN
*TeDataSize
123 EFI_FFS_FILE_HEADER
*FileHeader
= NULL
;
126 Status
= FfsFindNextFile (
127 EFI_FV_FILETYPE_SECURITY_CORE
,
132 if (EFI_ERROR (Status
)) {
133 DEBUG ((DEBUG_ERROR
, "Unable to locate Standalone MM FFS file - 0x%x\n",
138 Status
= FfsFindSectionData (EFI_SECTION_PE32
, FileHeader
, TeData
, TeDataSize
);
139 if (EFI_ERROR (Status
)) {
140 Status
= FfsFindSectionData (EFI_SECTION_TE
, FileHeader
, TeData
, TeDataSize
);
141 if (EFI_ERROR (Status
)) {
142 DEBUG ((DEBUG_ERROR
, "Unable to locate Standalone MM Section data - %r\n",
148 DEBUG ((DEBUG_INFO
, "Found Standalone MM PE data - 0x%x\n", *TeData
));
154 GetPeCoffSectionInformation (
155 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
,
156 OUT UINT32
*SectionHeaderOffset
,
157 OUT UINT16
*NumberOfSections
160 RETURN_STATUS Status
;
161 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
162 EFI_IMAGE_OPTIONAL_HEADER_UNION HdrData
;
166 ASSERT (ImageContext
!= NULL
);
167 ASSERT (SectionHeaderOffset
!= NULL
);
168 ASSERT (NumberOfSections
!= NULL
);
170 Status
= PeCoffLoaderGetImageInfo (ImageContext
);
171 if (RETURN_ERROR (Status
)) {
173 "%a: PeCoffLoaderGetImageInfo () failed (Status == %r)\n",
174 __FUNCTION__
, Status
));
178 if (ImageContext
->SectionAlignment
< EFI_PAGE_SIZE
) {
180 // The sections need to be at least 4 KB aligned, since that is the
181 // granularity at which we can tighten permissions.
183 if (!ImageContext
->IsTeImage
) {
185 "%a: non-TE Image at 0x%lx has SectionAlignment < 4 KB (%lu)\n",
186 __FUNCTION__
, ImageContext
->ImageAddress
, ImageContext
->SectionAlignment
));
187 return RETURN_UNSUPPORTED
;
189 ImageContext
->SectionAlignment
= EFI_PAGE_SIZE
;
193 // Read the PE/COFF Header. For PE32 (32-bit) this will read in too much
194 // data, but that should not hurt anything. Hdr.Pe32->OptionalHeader.Magic
195 // determines if this is a PE32 or PE32+ image. The magic is in the same
196 // location in both images.
198 Hdr
.Union
= &HdrData
;
199 Size
= sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION
);
201 Status
= ImageContext
->ImageRead (
202 ImageContext
->Handle
,
203 ImageContext
->PeCoffHeaderOffset
,
208 if (RETURN_ERROR (Status
) || (Size
!= ReadSize
)) {
210 "%a: TmpContext->ImageRead () failed (Status = %r)\n",
211 __FUNCTION__
, Status
));
215 if (!ImageContext
->IsTeImage
) {
216 ASSERT (Hdr
.Pe32
->Signature
== EFI_IMAGE_NT_SIGNATURE
);
218 *SectionHeaderOffset
= ImageContext
->PeCoffHeaderOffset
+ sizeof (UINT32
) +
219 sizeof (EFI_IMAGE_FILE_HEADER
);
220 *NumberOfSections
= Hdr
.Pe32
->FileHeader
.NumberOfSections
;
222 switch (Hdr
.Pe32
->OptionalHeader
.Magic
) {
223 case EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
:
224 *SectionHeaderOffset
+= Hdr
.Pe32
->FileHeader
.SizeOfOptionalHeader
;
226 case EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
:
227 *SectionHeaderOffset
+= Hdr
.Pe32Plus
->FileHeader
.SizeOfOptionalHeader
;
233 *SectionHeaderOffset
= (UINTN
)(sizeof (EFI_TE_IMAGE_HEADER
));
234 *NumberOfSections
= Hdr
.Te
->NumberOfSections
;
235 ImageContext
->ImageAddress
-= (UINT32
)Hdr
.Te
->StrippedSize
- sizeof (EFI_TE_IMAGE_HEADER
);
237 return RETURN_SUCCESS
;
242 GetStandaloneMmCorePeCoffSections (
244 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
,
245 IN OUT UINT32
*SectionHeaderOffset
,
246 IN OUT UINT16
*NumberOfSections
251 // Initialize the Image Context
252 ZeroMem (ImageContext
, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT
));
253 ImageContext
->Handle
= TeData
;
254 ImageContext
->ImageRead
= PeCoffLoaderImageReadFromMemory
;
256 DEBUG ((DEBUG_INFO
, "Found Standalone MM PE data - 0x%x\n", TeData
));
258 Status
= GetPeCoffSectionInformation (ImageContext
, SectionHeaderOffset
, NumberOfSections
);
259 if (EFI_ERROR (Status
)) {
260 DEBUG ((DEBUG_ERROR
, "Unable to locate Standalone MM Core PE-COFF Section information - %r\n", Status
));
264 DEBUG ((DEBUG_INFO
, "Standalone MM Core PE-COFF SectionHeaderOffset - 0x%x, NumberOfSections - %d\n",
265 *SectionHeaderOffset
, *NumberOfSections
));