]> git.proxmox.com Git - mirror_edk2.git/blob - StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/SetPermissions.c
StandaloneMmPkg: Fix ECC error 5007 in StandaloneMmCoreEntryPoint
[mirror_edk2.git] / StandaloneMmPkg / Library / StandaloneMmCoreEntryPoint / AArch64 / SetPermissions.c
1 /** @file
2 Locate, get and update PE/COFF permissions during Standalone MM
3 Foundation Entry point on ARM platforms.
4
5 Copyright (c) 2017 - 2021, Arm Ltd. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10
11 #include <PiMm.h>
12
13 #include <PiPei.h>
14 #include <Guid/MmramMemoryReserve.h>
15 #include <Guid/MpInformation.h>
16
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>
25
26 #include <IndustryStandard/ArmStdSmc.h>
27
28 EFI_STATUS
29 EFIAPI
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
38 )
39 {
40 EFI_IMAGE_SECTION_HEADER SectionHeader;
41 RETURN_STATUS Status;
42 EFI_PHYSICAL_ADDRESS Base;
43 UINTN Size;
44 UINTN ReadSize;
45 UINTN Index;
46
47 ASSERT (ImageContext != NULL);
48
49 //
50 // Iterate over the sections
51 //
52 for (Index = 0; Index < NumberOfSections; Index++) {
53 //
54 // Read section header from file
55 //
56 Size = sizeof (EFI_IMAGE_SECTION_HEADER);
57 ReadSize = Size;
58 Status = ImageContext->ImageRead (
59 ImageContext->Handle,
60 SectionHeaderOffset,
61 &Size,
62 &SectionHeader
63 );
64
65 if (RETURN_ERROR (Status) || (Size != ReadSize)) {
66 DEBUG ((DEBUG_ERROR,
67 "%a: ImageContext->ImageRead () failed (Status = %r)\n",
68 __FUNCTION__, Status));
69 return Status;
70 }
71
72 DEBUG ((DEBUG_INFO,
73 "%a: Section %d of image at 0x%lx has 0x%x permissions\n",
74 __FUNCTION__, Index, ImageContext->ImageAddress, SectionHeader.Characteristics));
75 DEBUG ((DEBUG_INFO,
76 "%a: Section %d of image at 0x%lx has %a name\n",
77 __FUNCTION__, Index, ImageContext->ImageAddress, SectionHeader.Name));
78 DEBUG ((DEBUG_INFO,
79 "%a: Section %d of image at 0x%lx has 0x%x address\n",
80 __FUNCTION__, Index, ImageContext->ImageAddress,
81 ImageContext->ImageAddress + SectionHeader.VirtualAddress));
82 DEBUG ((DEBUG_INFO,
83 "%a: Section %d of image at 0x%lx has 0x%x data\n",
84 __FUNCTION__, Index, ImageContext->ImageAddress, SectionHeader.PointerToRawData));
85
86 //
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.
89 //
90 if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_MEM_EXECUTE) == 0) {
91 Base = ImageBase + SectionHeader.VirtualAddress;
92
93 TextUpdater (Base, SectionHeader.Misc.VirtualSize);
94
95 if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_MEM_WRITE) != 0) {
96 ReadWriteUpdater (Base, SectionHeader.Misc.VirtualSize);
97 DEBUG ((DEBUG_INFO,
98 "%a: Mapping section %d of image at 0x%lx with RW-XN permissions\n",
99 __FUNCTION__, Index, ImageContext->ImageAddress));
100 } else {
101 DEBUG ((DEBUG_INFO,
102 "%a: Mapping section %d of image at 0x%lx with RO-XN permissions\n",
103 __FUNCTION__, Index, ImageContext->ImageAddress));
104 }
105 } else {
106 DEBUG ((DEBUG_INFO,
107 "%a: Ignoring section %d of image at 0x%lx with 0x%x permissions\n",
108 __FUNCTION__, Index, ImageContext->ImageAddress, SectionHeader.Characteristics));
109 }
110 SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
111 }
112
113 return RETURN_SUCCESS;
114 }
115
116 EFI_STATUS
117 EFIAPI
118 LocateStandaloneMmCorePeCoffData (
119 IN EFI_FIRMWARE_VOLUME_HEADER *BfvAddress,
120 IN OUT VOID **TeData,
121 IN OUT UINTN *TeDataSize
122 )
123 {
124 EFI_FFS_FILE_HEADER *FileHeader;
125 EFI_STATUS Status;
126
127 FileHeader = NULL;
128 Status = FfsFindNextFile (
129 EFI_FV_FILETYPE_SECURITY_CORE,
130 BfvAddress,
131 &FileHeader
132 );
133
134 if (EFI_ERROR (Status)) {
135 DEBUG ((DEBUG_ERROR, "Unable to locate Standalone MM FFS file - 0x%x\n",
136 Status));
137 return Status;
138 }
139
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",
145 Status));
146 return Status;
147 }
148 }
149
150 DEBUG ((DEBUG_INFO, "Found Standalone MM PE data - 0x%x\n", *TeData));
151 return Status;
152 }
153
154 STATIC
155 EFI_STATUS
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
161 )
162 {
163 RETURN_STATUS Status;
164 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
165 EFI_IMAGE_OPTIONAL_HEADER_UNION HdrData;
166 UINTN Size;
167 UINTN ReadSize;
168
169 ASSERT (ImageContext != NULL);
170 ASSERT (SectionHeaderOffset != NULL);
171 ASSERT (NumberOfSections != NULL);
172
173 Status = PeCoffLoaderGetImageInfo (ImageContext);
174 if (RETURN_ERROR (Status)) {
175 DEBUG ((DEBUG_ERROR,
176 "%a: PeCoffLoaderGetImageInfo () failed (Status == %r)\n",
177 __FUNCTION__, Status));
178 return Status;
179 }
180
181 if (ImageContext->SectionAlignment < EFI_PAGE_SIZE) {
182 //
183 // The sections need to be at least 4 KB aligned, since that is the
184 // granularity at which we can tighten permissions.
185 //
186 if (!ImageContext->IsTeImage) {
187 DEBUG ((DEBUG_WARN,
188 "%a: non-TE Image at 0x%lx has SectionAlignment < 4 KB (%lu)\n",
189 __FUNCTION__, ImageContext->ImageAddress, ImageContext->SectionAlignment));
190 return RETURN_UNSUPPORTED;
191 }
192 ImageContext->SectionAlignment = EFI_PAGE_SIZE;
193 }
194
195 //
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.
200 //
201 Hdr.Union = &HdrData;
202 Size = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION);
203 ReadSize = Size;
204 Status = ImageContext->ImageRead (
205 ImageContext->Handle,
206 ImageContext->PeCoffHeaderOffset,
207 &Size,
208 Hdr.Pe32
209 );
210
211 if (RETURN_ERROR (Status) || (Size != ReadSize)) {
212 DEBUG ((DEBUG_ERROR,
213 "%a: TmpContext->ImageRead () failed (Status = %r)\n",
214 __FUNCTION__, Status));
215 return Status;
216 }
217
218 *ImageBase = ImageContext->ImageAddress;
219 if (!ImageContext->IsTeImage) {
220 ASSERT (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE);
221
222 *SectionHeaderOffset = ImageContext->PeCoffHeaderOffset + sizeof (UINT32) +
223 sizeof (EFI_IMAGE_FILE_HEADER);
224 *NumberOfSections = Hdr.Pe32->FileHeader.NumberOfSections;
225
226 switch (Hdr.Pe32->OptionalHeader.Magic) {
227 case EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC:
228 *SectionHeaderOffset += Hdr.Pe32->FileHeader.SizeOfOptionalHeader;
229 break;
230 case EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC:
231 *SectionHeaderOffset += Hdr.Pe32Plus->FileHeader.SizeOfOptionalHeader;
232 break;
233 default:
234 ASSERT (FALSE);
235 }
236 } else {
237 *SectionHeaderOffset = (UINTN)(sizeof (EFI_TE_IMAGE_HEADER));
238 *NumberOfSections = Hdr.Te->NumberOfSections;
239 *ImageBase -= (UINT32)Hdr.Te->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER);
240 }
241 return RETURN_SUCCESS;
242 }
243
244 EFI_STATUS
245 EFIAPI
246 GetStandaloneMmCorePeCoffSections (
247 IN VOID *TeData,
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
252 )
253 {
254 EFI_STATUS Status;
255
256 // Initialize the Image Context
257 ZeroMem (ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));
258 ImageContext->Handle = TeData;
259 ImageContext->ImageRead = PeCoffLoaderImageReadFromMemory;
260
261 DEBUG ((DEBUG_INFO, "Found Standalone MM PE data - 0x%x\n", TeData));
262
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));
267 return Status;
268 }
269
270 DEBUG ((DEBUG_INFO, "Standalone MM Core PE-COFF SectionHeaderOffset - 0x%x, NumberOfSections - %d\n",
271 *SectionHeaderOffset, *NumberOfSections));
272
273 return Status;
274 }