]> git.proxmox.com Git - mirror_edk2.git/blame - StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/SetPermissions.c
StandaloneMmPkg: Fix ECC error 4002 in StandaloneMmCoreEntryPoint
[mirror_edk2.git] / StandaloneMmPkg / Library / StandaloneMmCoreEntryPoint / AArch64 / SetPermissions.c
CommitLineData
184558d0
SV
1/** @file\r
2 Locate, get and update PE/COFF permissions during Standalone MM\r
3 Foundation Entry point on ARM platforms.\r
4\r
7aa9d752 5Copyright (c) 2017 - 2021, Arm Ltd. All rights reserved.<BR>\r
86094561 6SPDX-License-Identifier: BSD-2-Clause-Patent\r
184558d0
SV
7\r
8**/\r
9\r
10\r
11#include <PiMm.h>\r
12\r
13#include <PiPei.h>\r
14#include <Guid/MmramMemoryReserve.h>\r
15#include <Guid/MpInformation.h>\r
16\r
17#include <Library/AArch64/StandaloneMmCoreEntryPoint.h>\r
18#include <Library/ArmMmuLib.h>\r
19#include <Library/ArmSvcLib.h>\r
20#include <Library/DebugLib.h>\r
21#include <Library/HobLib.h>\r
22#include <Library/BaseLib.h>\r
23#include <Library/BaseMemoryLib.h>\r
24#include <Library/SerialPortLib.h>\r
25\r
26#include <IndustryStandard/ArmStdSmc.h>\r
27\r
764942a2
SM
28/**\r
29 Privileged firmware assigns RO & Executable attributes to all memory occupied\r
30 by the Boot Firmware Volume. This function sets the correct permissions of\r
31 sections in the Standalone MM Core module to be able to access RO and RW data\r
32 and make further progress in the boot process.\r
33\r
34 @param [in] ImageContext Pointer to PE/COFF image context\r
35 @param [in] ImageBase Base of image in memory\r
36 @param [in] SectionHeaderOffset Offset of PE/COFF image section header\r
37 @param [in] NumberOfSections Number of Sections\r
38 @param [in] TextUpdater Function to change code permissions\r
39 @param [in] ReadOnlyUpdater Function to change RO permissions\r
40 @param [in] ReadWriteUpdater Function to change RW permissions\r
41\r
42**/\r
184558d0
SV
43EFI_STATUS\r
44EFIAPI\r
45UpdateMmFoundationPeCoffPermissions (\r
46 IN CONST PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,\r
493f2c69 47 IN EFI_PHYSICAL_ADDRESS ImageBase,\r
184558d0
SV
48 IN UINT32 SectionHeaderOffset,\r
49 IN CONST UINT16 NumberOfSections,\r
50 IN REGION_PERMISSION_UPDATE_FUNC TextUpdater,\r
51 IN REGION_PERMISSION_UPDATE_FUNC ReadOnlyUpdater,\r
52 IN REGION_PERMISSION_UPDATE_FUNC ReadWriteUpdater\r
53 )\r
54{\r
55 EFI_IMAGE_SECTION_HEADER SectionHeader;\r
56 RETURN_STATUS Status;\r
57 EFI_PHYSICAL_ADDRESS Base;\r
58 UINTN Size;\r
59 UINTN ReadSize;\r
60 UINTN Index;\r
61\r
62 ASSERT (ImageContext != NULL);\r
63\r
64 //\r
65 // Iterate over the sections\r
66 //\r
67 for (Index = 0; Index < NumberOfSections; Index++) {\r
68 //\r
69 // Read section header from file\r
70 //\r
71 Size = sizeof (EFI_IMAGE_SECTION_HEADER);\r
72 ReadSize = Size;\r
73 Status = ImageContext->ImageRead (\r
74 ImageContext->Handle,\r
75 SectionHeaderOffset,\r
76 &Size,\r
77 &SectionHeader\r
78 );\r
79\r
80 if (RETURN_ERROR (Status) || (Size != ReadSize)) {\r
81 DEBUG ((DEBUG_ERROR,\r
82 "%a: ImageContext->ImageRead () failed (Status = %r)\n",\r
83 __FUNCTION__, Status));\r
84 return Status;\r
85 }\r
86\r
87 DEBUG ((DEBUG_INFO,\r
88 "%a: Section %d of image at 0x%lx has 0x%x permissions\n",\r
89 __FUNCTION__, Index, ImageContext->ImageAddress, SectionHeader.Characteristics));\r
90 DEBUG ((DEBUG_INFO,\r
41915a19 91 "%a: Section %d of image at 0x%lx has %a name\n",\r
184558d0
SV
92 __FUNCTION__, Index, ImageContext->ImageAddress, SectionHeader.Name));\r
93 DEBUG ((DEBUG_INFO,\r
94 "%a: Section %d of image at 0x%lx has 0x%x address\n",\r
95 __FUNCTION__, Index, ImageContext->ImageAddress,\r
96 ImageContext->ImageAddress + SectionHeader.VirtualAddress));\r
97 DEBUG ((DEBUG_INFO,\r
98 "%a: Section %d of image at 0x%lx has 0x%x data\n",\r
99 __FUNCTION__, Index, ImageContext->ImageAddress, SectionHeader.PointerToRawData));\r
100\r
101 //\r
102 // If the section is marked as XN then remove the X attribute. Furthermore,\r
103 // if it is a writeable section then mark it appropriately as well.\r
104 //\r
105 if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_MEM_EXECUTE) == 0) {\r
493f2c69 106 Base = ImageBase + SectionHeader.VirtualAddress;\r
184558d0
SV
107\r
108 TextUpdater (Base, SectionHeader.Misc.VirtualSize);\r
109\r
110 if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_MEM_WRITE) != 0) {\r
111 ReadWriteUpdater (Base, SectionHeader.Misc.VirtualSize);\r
112 DEBUG ((DEBUG_INFO,\r
113 "%a: Mapping section %d of image at 0x%lx with RW-XN permissions\n",\r
114 __FUNCTION__, Index, ImageContext->ImageAddress));\r
115 } else {\r
116 DEBUG ((DEBUG_INFO,\r
117 "%a: Mapping section %d of image at 0x%lx with RO-XN permissions\n",\r
118 __FUNCTION__, Index, ImageContext->ImageAddress));\r
119 }\r
120 } else {\r
121 DEBUG ((DEBUG_INFO,\r
122 "%a: Ignoring section %d of image at 0x%lx with 0x%x permissions\n",\r
123 __FUNCTION__, Index, ImageContext->ImageAddress, SectionHeader.Characteristics));\r
124 }\r
125 SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);\r
126 }\r
127\r
128 return RETURN_SUCCESS;\r
129}\r
130\r
764942a2
SM
131/**\r
132 Privileged firmware assigns RO & Executable attributes to all memory occupied\r
133 by the Boot Firmware Volume. This function locates the Standalone MM Core\r
134 module PE/COFF image in the BFV and returns this information.\r
135\r
136 @param [in] BfvAddress Base Address of Boot Firmware Volume\r
137 @param [in, out] TeData Pointer to address for allocating memory\r
138 for PE/COFF image data\r
139 @param [in, out] TeDataSize Pointer to size of PE/COFF image data\r
140\r
141**/\r
184558d0
SV
142EFI_STATUS\r
143EFIAPI\r
144LocateStandaloneMmCorePeCoffData (\r
145 IN EFI_FIRMWARE_VOLUME_HEADER *BfvAddress,\r
146 IN OUT VOID **TeData,\r
147 IN OUT UINTN *TeDataSize\r
148 )\r
149{\r
7aa9d752 150 EFI_FFS_FILE_HEADER *FileHeader;\r
184558d0
SV
151 EFI_STATUS Status;\r
152\r
7aa9d752 153 FileHeader = NULL;\r
184558d0
SV
154 Status = FfsFindNextFile (\r
155 EFI_FV_FILETYPE_SECURITY_CORE,\r
156 BfvAddress,\r
157 &FileHeader\r
158 );\r
159\r
160 if (EFI_ERROR (Status)) {\r
161 DEBUG ((DEBUG_ERROR, "Unable to locate Standalone MM FFS file - 0x%x\n",\r
162 Status));\r
163 return Status;\r
164 }\r
165\r
166 Status = FfsFindSectionData (EFI_SECTION_PE32, FileHeader, TeData, TeDataSize);\r
167 if (EFI_ERROR (Status)) {\r
4b28452d
AB
168 Status = FfsFindSectionData (EFI_SECTION_TE, FileHeader, TeData, TeDataSize);\r
169 if (EFI_ERROR (Status)) {\r
170 DEBUG ((DEBUG_ERROR, "Unable to locate Standalone MM Section data - %r\n",\r
171 Status));\r
172 return Status;\r
173 }\r
184558d0
SV
174 }\r
175\r
176 DEBUG ((DEBUG_INFO, "Found Standalone MM PE data - 0x%x\n", *TeData));\r
177 return Status;\r
178}\r
179\r
764942a2
SM
180/**\r
181 Returns the PC COFF section information.\r
182\r
183 @param [in, out] ImageContext Pointer to PE/COFF image context\r
184 @param [out] ImageBase Base of image in memory\r
185 @param [out] SectionHeaderOffset Offset of PE/COFF image section header\r
186 @param [out] NumberOfSections Number of Sections\r
187\r
188**/\r
184558d0
SV
189STATIC\r
190EFI_STATUS\r
191GetPeCoffSectionInformation (\r
4b28452d 192 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,\r
493f2c69 193 OUT EFI_PHYSICAL_ADDRESS *ImageBase,\r
4b28452d
AB
194 OUT UINT32 *SectionHeaderOffset,\r
195 OUT UINT16 *NumberOfSections\r
184558d0
SV
196 )\r
197{\r
198 RETURN_STATUS Status;\r
199 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
200 EFI_IMAGE_OPTIONAL_HEADER_UNION HdrData;\r
201 UINTN Size;\r
202 UINTN ReadSize;\r
203\r
204 ASSERT (ImageContext != NULL);\r
184558d0
SV
205 ASSERT (SectionHeaderOffset != NULL);\r
206 ASSERT (NumberOfSections != NULL);\r
207\r
4b28452d
AB
208 Status = PeCoffLoaderGetImageInfo (ImageContext);\r
209 if (RETURN_ERROR (Status)) {\r
210 DEBUG ((DEBUG_ERROR,\r
211 "%a: PeCoffLoaderGetImageInfo () failed (Status == %r)\n",\r
212 __FUNCTION__, Status));\r
213 return Status;\r
184558d0
SV
214 }\r
215\r
4b28452d 216 if (ImageContext->SectionAlignment < EFI_PAGE_SIZE) {\r
184558d0
SV
217 //\r
218 // The sections need to be at least 4 KB aligned, since that is the\r
219 // granularity at which we can tighten permissions.\r
220 //\r
4b28452d 221 if (!ImageContext->IsTeImage) {\r
184558d0
SV
222 DEBUG ((DEBUG_WARN,\r
223 "%a: non-TE Image at 0x%lx has SectionAlignment < 4 KB (%lu)\n",\r
4b28452d
AB
224 __FUNCTION__, ImageContext->ImageAddress, ImageContext->SectionAlignment));\r
225 return RETURN_UNSUPPORTED;\r
184558d0 226 }\r
4b28452d 227 ImageContext->SectionAlignment = EFI_PAGE_SIZE;\r
184558d0
SV
228 }\r
229\r
230 //\r
231 // Read the PE/COFF Header. For PE32 (32-bit) this will read in too much\r
232 // data, but that should not hurt anything. Hdr.Pe32->OptionalHeader.Magic\r
233 // determines if this is a PE32 or PE32+ image. The magic is in the same\r
234 // location in both images.\r
235 //\r
236 Hdr.Union = &HdrData;\r
237 Size = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION);\r
238 ReadSize = Size;\r
4b28452d
AB
239 Status = ImageContext->ImageRead (\r
240 ImageContext->Handle,\r
241 ImageContext->PeCoffHeaderOffset,\r
184558d0
SV
242 &Size,\r
243 Hdr.Pe32\r
244 );\r
245\r
246 if (RETURN_ERROR (Status) || (Size != ReadSize)) {\r
247 DEBUG ((DEBUG_ERROR,\r
248 "%a: TmpContext->ImageRead () failed (Status = %r)\n",\r
249 __FUNCTION__, Status));\r
250 return Status;\r
251 }\r
252\r
493f2c69 253 *ImageBase = ImageContext->ImageAddress;\r
4b28452d
AB
254 if (!ImageContext->IsTeImage) {\r
255 ASSERT (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE);\r
256\r
257 *SectionHeaderOffset = ImageContext->PeCoffHeaderOffset + sizeof (UINT32) +\r
258 sizeof (EFI_IMAGE_FILE_HEADER);\r
259 *NumberOfSections = Hdr.Pe32->FileHeader.NumberOfSections;\r
260\r
261 switch (Hdr.Pe32->OptionalHeader.Magic) {\r
262 case EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC:\r
263 *SectionHeaderOffset += Hdr.Pe32->FileHeader.SizeOfOptionalHeader;\r
264 break;\r
265 case EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC:\r
266 *SectionHeaderOffset += Hdr.Pe32Plus->FileHeader.SizeOfOptionalHeader;\r
267 break;\r
268 default:\r
269 ASSERT (FALSE);\r
270 }\r
271 } else {\r
272 *SectionHeaderOffset = (UINTN)(sizeof (EFI_TE_IMAGE_HEADER));\r
273 *NumberOfSections = Hdr.Te->NumberOfSections;\r
493f2c69 274 *ImageBase -= (UINT32)Hdr.Te->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER);\r
184558d0 275 }\r
184558d0
SV
276 return RETURN_SUCCESS;\r
277}\r
278\r
764942a2
SM
279/**\r
280 Privileged firmware assigns RO & Executable attributes to all memory occupied\r
281 by the Boot Firmware Volume. This function locates the section information of\r
282 the Standalone MM Core module to be able to change permissions of the\r
283 individual sections later in the boot process.\r
284\r
285 @param [in] TeData Pointer to PE/COFF image data\r
286 @param [in, out] ImageContext Pointer to PE/COFF image context\r
287 @param [out] ImageBase Pointer to ImageBase variable\r
288 @param [in, out] SectionHeaderOffset Offset of PE/COFF image section header\r
289 @param [in, out] NumberOfSections Number of Sections\r
290\r
291**/\r
184558d0
SV
292EFI_STATUS\r
293EFIAPI\r
294GetStandaloneMmCorePeCoffSections (\r
295 IN VOID *TeData,\r
296 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,\r
493f2c69 297 OUT EFI_PHYSICAL_ADDRESS *ImageBase,\r
184558d0
SV
298 IN OUT UINT32 *SectionHeaderOffset,\r
299 IN OUT UINT16 *NumberOfSections\r
300 )\r
301{\r
302 EFI_STATUS Status;\r
184558d0
SV
303\r
304 // Initialize the Image Context\r
305 ZeroMem (ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));\r
306 ImageContext->Handle = TeData;\r
307 ImageContext->ImageRead = PeCoffLoaderImageReadFromMemory;\r
308\r
309 DEBUG ((DEBUG_INFO, "Found Standalone MM PE data - 0x%x\n", TeData));\r
310\r
493f2c69
AB
311 Status = GetPeCoffSectionInformation (ImageContext, ImageBase,\r
312 SectionHeaderOffset, NumberOfSections);\r
184558d0 313 if (EFI_ERROR (Status)) {\r
4b28452d 314 DEBUG ((DEBUG_ERROR, "Unable to locate Standalone MM Core PE-COFF Section information - %r\n", Status));\r
184558d0
SV
315 return Status;\r
316 }\r
317\r
318 DEBUG ((DEBUG_INFO, "Standalone MM Core PE-COFF SectionHeaderOffset - 0x%x, NumberOfSections - %d\n",\r
319 *SectionHeaderOffset, *NumberOfSections));\r
320\r
321 return Status;\r
322}\r