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 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php.
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 #include <Guid/MmramMemoryReserve.h>
21 #include <Guid/MpInformation.h>
23 #include <Library/AArch64/StandaloneMmCoreEntryPoint.h>
24 #include <Library/ArmMmuLib.h>
25 #include <Library/ArmSvcLib.h>
26 #include <Library/DebugLib.h>
27 #include <Library/HobLib.h>
28 #include <Library/BaseLib.h>
29 #include <Library/BaseMemoryLib.h>
30 #include <Library/SerialPortLib.h>
32 #include <IndustryStandard/ArmStdSmc.h>
36 UpdateMmFoundationPeCoffPermissions (
37 IN CONST PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
,
38 IN UINT32 SectionHeaderOffset
,
39 IN CONST UINT16 NumberOfSections
,
40 IN REGION_PERMISSION_UPDATE_FUNC TextUpdater
,
41 IN REGION_PERMISSION_UPDATE_FUNC ReadOnlyUpdater
,
42 IN REGION_PERMISSION_UPDATE_FUNC ReadWriteUpdater
45 EFI_IMAGE_SECTION_HEADER SectionHeader
;
47 EFI_PHYSICAL_ADDRESS Base
;
52 ASSERT (ImageContext
!= NULL
);
55 // Iterate over the sections
57 for (Index
= 0; Index
< NumberOfSections
; Index
++) {
59 // Read section header from file
61 Size
= sizeof (EFI_IMAGE_SECTION_HEADER
);
63 Status
= ImageContext
->ImageRead (
70 if (RETURN_ERROR (Status
) || (Size
!= ReadSize
)) {
72 "%a: ImageContext->ImageRead () failed (Status = %r)\n",
73 __FUNCTION__
, Status
));
78 "%a: Section %d of image at 0x%lx has 0x%x permissions\n",
79 __FUNCTION__
, Index
, ImageContext
->ImageAddress
, SectionHeader
.Characteristics
));
81 "%a: Section %d of image at 0x%lx has %a name\n",
82 __FUNCTION__
, Index
, ImageContext
->ImageAddress
, SectionHeader
.Name
));
84 "%a: Section %d of image at 0x%lx has 0x%x address\n",
85 __FUNCTION__
, Index
, ImageContext
->ImageAddress
,
86 ImageContext
->ImageAddress
+ SectionHeader
.VirtualAddress
));
88 "%a: Section %d of image at 0x%lx has 0x%x data\n",
89 __FUNCTION__
, Index
, ImageContext
->ImageAddress
, SectionHeader
.PointerToRawData
));
92 // If the section is marked as XN then remove the X attribute. Furthermore,
93 // if it is a writeable section then mark it appropriately as well.
95 if ((SectionHeader
.Characteristics
& EFI_IMAGE_SCN_MEM_EXECUTE
) == 0) {
96 Base
= ImageContext
->ImageAddress
+ SectionHeader
.VirtualAddress
;
98 TextUpdater (Base
, SectionHeader
.Misc
.VirtualSize
);
100 if ((SectionHeader
.Characteristics
& EFI_IMAGE_SCN_MEM_WRITE
) != 0) {
101 ReadWriteUpdater (Base
, SectionHeader
.Misc
.VirtualSize
);
103 "%a: Mapping section %d of image at 0x%lx with RW-XN permissions\n",
104 __FUNCTION__
, Index
, ImageContext
->ImageAddress
));
107 "%a: Mapping section %d of image at 0x%lx with RO-XN permissions\n",
108 __FUNCTION__
, Index
, ImageContext
->ImageAddress
));
112 "%a: Ignoring section %d of image at 0x%lx with 0x%x permissions\n",
113 __FUNCTION__
, Index
, ImageContext
->ImageAddress
, SectionHeader
.Characteristics
));
115 SectionHeaderOffset
+= sizeof (EFI_IMAGE_SECTION_HEADER
);
118 return RETURN_SUCCESS
;
123 LocateStandaloneMmCorePeCoffData (
124 IN EFI_FIRMWARE_VOLUME_HEADER
*BfvAddress
,
125 IN OUT VOID
**TeData
,
126 IN OUT UINTN
*TeDataSize
129 EFI_FFS_FILE_HEADER
*FileHeader
= NULL
;
132 Status
= FfsFindNextFile (
133 EFI_FV_FILETYPE_SECURITY_CORE
,
138 if (EFI_ERROR (Status
)) {
139 DEBUG ((DEBUG_ERROR
, "Unable to locate Standalone MM FFS file - 0x%x\n",
144 Status
= FfsFindSectionData (EFI_SECTION_PE32
, FileHeader
, TeData
, TeDataSize
);
145 if (EFI_ERROR (Status
)) {
146 Status
= FfsFindSectionData (EFI_SECTION_TE
, FileHeader
, TeData
, TeDataSize
);
147 if (EFI_ERROR (Status
)) {
148 DEBUG ((DEBUG_ERROR
, "Unable to locate Standalone MM Section data - %r\n",
154 DEBUG ((DEBUG_INFO
, "Found Standalone MM PE data - 0x%x\n", *TeData
));
160 GetPeCoffSectionInformation (
161 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
,
162 OUT UINT32
*SectionHeaderOffset
,
163 OUT UINT16
*NumberOfSections
166 RETURN_STATUS Status
;
167 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
168 EFI_IMAGE_OPTIONAL_HEADER_UNION HdrData
;
172 ASSERT (ImageContext
!= NULL
);
173 ASSERT (SectionHeaderOffset
!= NULL
);
174 ASSERT (NumberOfSections
!= NULL
);
176 Status
= PeCoffLoaderGetImageInfo (ImageContext
);
177 if (RETURN_ERROR (Status
)) {
179 "%a: PeCoffLoaderGetImageInfo () failed (Status == %r)\n",
180 __FUNCTION__
, Status
));
184 if (ImageContext
->SectionAlignment
< EFI_PAGE_SIZE
) {
186 // The sections need to be at least 4 KB aligned, since that is the
187 // granularity at which we can tighten permissions.
189 if (!ImageContext
->IsTeImage
) {
191 "%a: non-TE Image at 0x%lx has SectionAlignment < 4 KB (%lu)\n",
192 __FUNCTION__
, ImageContext
->ImageAddress
, ImageContext
->SectionAlignment
));
193 return RETURN_UNSUPPORTED
;
195 ImageContext
->SectionAlignment
= EFI_PAGE_SIZE
;
199 // Read the PE/COFF Header. For PE32 (32-bit) this will read in too much
200 // data, but that should not hurt anything. Hdr.Pe32->OptionalHeader.Magic
201 // determines if this is a PE32 or PE32+ image. The magic is in the same
202 // location in both images.
204 Hdr
.Union
= &HdrData
;
205 Size
= sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION
);
207 Status
= ImageContext
->ImageRead (
208 ImageContext
->Handle
,
209 ImageContext
->PeCoffHeaderOffset
,
214 if (RETURN_ERROR (Status
) || (Size
!= ReadSize
)) {
216 "%a: TmpContext->ImageRead () failed (Status = %r)\n",
217 __FUNCTION__
, Status
));
221 if (!ImageContext
->IsTeImage
) {
222 ASSERT (Hdr
.Pe32
->Signature
== EFI_IMAGE_NT_SIGNATURE
);
224 *SectionHeaderOffset
= ImageContext
->PeCoffHeaderOffset
+ sizeof (UINT32
) +
225 sizeof (EFI_IMAGE_FILE_HEADER
);
226 *NumberOfSections
= Hdr
.Pe32
->FileHeader
.NumberOfSections
;
228 switch (Hdr
.Pe32
->OptionalHeader
.Magic
) {
229 case EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
:
230 *SectionHeaderOffset
+= Hdr
.Pe32
->FileHeader
.SizeOfOptionalHeader
;
232 case EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
:
233 *SectionHeaderOffset
+= Hdr
.Pe32Plus
->FileHeader
.SizeOfOptionalHeader
;
239 *SectionHeaderOffset
= (UINTN
)(sizeof (EFI_TE_IMAGE_HEADER
));
240 *NumberOfSections
= Hdr
.Te
->NumberOfSections
;
241 ImageContext
->ImageAddress
-= (UINT32
)Hdr
.Te
->StrippedSize
- sizeof (EFI_TE_IMAGE_HEADER
);
243 return RETURN_SUCCESS
;
248 GetStandaloneMmCorePeCoffSections (
250 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
,
251 IN OUT UINT32
*SectionHeaderOffset
,
252 IN OUT UINT16
*NumberOfSections
257 // Initialize the Image Context
258 ZeroMem (ImageContext
, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT
));
259 ImageContext
->Handle
= TeData
;
260 ImageContext
->ImageRead
= PeCoffLoaderImageReadFromMemory
;
262 DEBUG ((DEBUG_INFO
, "Found Standalone MM PE data - 0x%x\n", TeData
));
264 Status
= GetPeCoffSectionInformation (ImageContext
, 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
));