]> git.proxmox.com Git - mirror_edk2.git/blame - StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/SetPermissions.c
StandaloneMmPkg/StandaloneMmCoreEntryPoint: use %a modifier for ASCII strings
[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
5Copyright (c) 2017 - 2018, ARM Ltd. All rights reserved.<BR>\r
6This program and the accompanying materials\r
7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php.\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16\r
17#include <PiMm.h>\r
18\r
19#include <PiPei.h>\r
20#include <Guid/MmramMemoryReserve.h>\r
21#include <Guid/MpInformation.h>\r
22\r
23#include <Library/AArch64/StandaloneMmCoreEntryPoint.h>\r
24#include <Library/ArmMmuLib.h>\r
25#include <Library/ArmSvcLib.h>\r
26#include <Library/DebugLib.h>\r
27#include <Library/HobLib.h>\r
28#include <Library/BaseLib.h>\r
29#include <Library/BaseMemoryLib.h>\r
30#include <Library/SerialPortLib.h>\r
31\r
32#include <IndustryStandard/ArmStdSmc.h>\r
33\r
34EFI_STATUS\r
35EFIAPI\r
36UpdateMmFoundationPeCoffPermissions (\r
37 IN CONST PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,\r
38 IN UINT32 SectionHeaderOffset,\r
39 IN CONST UINT16 NumberOfSections,\r
40 IN REGION_PERMISSION_UPDATE_FUNC TextUpdater,\r
41 IN REGION_PERMISSION_UPDATE_FUNC ReadOnlyUpdater,\r
42 IN REGION_PERMISSION_UPDATE_FUNC ReadWriteUpdater\r
43 )\r
44{\r
45 EFI_IMAGE_SECTION_HEADER SectionHeader;\r
46 RETURN_STATUS Status;\r
47 EFI_PHYSICAL_ADDRESS Base;\r
48 UINTN Size;\r
49 UINTN ReadSize;\r
50 UINTN Index;\r
51\r
52 ASSERT (ImageContext != NULL);\r
53\r
54 //\r
55 // Iterate over the sections\r
56 //\r
57 for (Index = 0; Index < NumberOfSections; Index++) {\r
58 //\r
59 // Read section header from file\r
60 //\r
61 Size = sizeof (EFI_IMAGE_SECTION_HEADER);\r
62 ReadSize = Size;\r
63 Status = ImageContext->ImageRead (\r
64 ImageContext->Handle,\r
65 SectionHeaderOffset,\r
66 &Size,\r
67 &SectionHeader\r
68 );\r
69\r
70 if (RETURN_ERROR (Status) || (Size != ReadSize)) {\r
71 DEBUG ((DEBUG_ERROR,\r
72 "%a: ImageContext->ImageRead () failed (Status = %r)\n",\r
73 __FUNCTION__, Status));\r
74 return Status;\r
75 }\r
76\r
77 DEBUG ((DEBUG_INFO,\r
78 "%a: Section %d of image at 0x%lx has 0x%x permissions\n",\r
79 __FUNCTION__, Index, ImageContext->ImageAddress, SectionHeader.Characteristics));\r
80 DEBUG ((DEBUG_INFO,\r
41915a19 81 "%a: Section %d of image at 0x%lx has %a name\n",\r
184558d0
SV
82 __FUNCTION__, Index, ImageContext->ImageAddress, SectionHeader.Name));\r
83 DEBUG ((DEBUG_INFO,\r
84 "%a: Section %d of image at 0x%lx has 0x%x address\n",\r
85 __FUNCTION__, Index, ImageContext->ImageAddress,\r
86 ImageContext->ImageAddress + SectionHeader.VirtualAddress));\r
87 DEBUG ((DEBUG_INFO,\r
88 "%a: Section %d of image at 0x%lx has 0x%x data\n",\r
89 __FUNCTION__, Index, ImageContext->ImageAddress, SectionHeader.PointerToRawData));\r
90\r
91 //\r
92 // If the section is marked as XN then remove the X attribute. Furthermore,\r
93 // if it is a writeable section then mark it appropriately as well.\r
94 //\r
95 if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_MEM_EXECUTE) == 0) {\r
96 Base = ImageContext->ImageAddress + SectionHeader.VirtualAddress;\r
97\r
98 TextUpdater (Base, SectionHeader.Misc.VirtualSize);\r
99\r
100 if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_MEM_WRITE) != 0) {\r
101 ReadWriteUpdater (Base, SectionHeader.Misc.VirtualSize);\r
102 DEBUG ((DEBUG_INFO,\r
103 "%a: Mapping section %d of image at 0x%lx with RW-XN permissions\n",\r
104 __FUNCTION__, Index, ImageContext->ImageAddress));\r
105 } else {\r
106 DEBUG ((DEBUG_INFO,\r
107 "%a: Mapping section %d of image at 0x%lx with RO-XN permissions\n",\r
108 __FUNCTION__, Index, ImageContext->ImageAddress));\r
109 }\r
110 } else {\r
111 DEBUG ((DEBUG_INFO,\r
112 "%a: Ignoring section %d of image at 0x%lx with 0x%x permissions\n",\r
113 __FUNCTION__, Index, ImageContext->ImageAddress, SectionHeader.Characteristics));\r
114 }\r
115 SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);\r
116 }\r
117\r
118 return RETURN_SUCCESS;\r
119}\r
120\r
121EFI_STATUS\r
122EFIAPI\r
123LocateStandaloneMmCorePeCoffData (\r
124 IN EFI_FIRMWARE_VOLUME_HEADER *BfvAddress,\r
125 IN OUT VOID **TeData,\r
126 IN OUT UINTN *TeDataSize\r
127 )\r
128{\r
129 EFI_FFS_FILE_HEADER *FileHeader = NULL;\r
130 EFI_STATUS Status;\r
131\r
132 Status = FfsFindNextFile (\r
133 EFI_FV_FILETYPE_SECURITY_CORE,\r
134 BfvAddress,\r
135 &FileHeader\r
136 );\r
137\r
138 if (EFI_ERROR (Status)) {\r
139 DEBUG ((DEBUG_ERROR, "Unable to locate Standalone MM FFS file - 0x%x\n",\r
140 Status));\r
141 return Status;\r
142 }\r
143\r
144 Status = FfsFindSectionData (EFI_SECTION_PE32, FileHeader, TeData, TeDataSize);\r
145 if (EFI_ERROR (Status)) {\r
146 DEBUG ((DEBUG_ERROR, "Unable to locate Standalone MM Section data - 0x%x\n",\r
147 Status));\r
148 return Status;\r
149 }\r
150\r
151 DEBUG ((DEBUG_INFO, "Found Standalone MM PE data - 0x%x\n", *TeData));\r
152 return Status;\r
153}\r
154\r
155STATIC\r
156EFI_STATUS\r
157GetPeCoffSectionInformation (\r
158 IN CONST PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,\r
159 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *TmpContext,\r
160 IN OUT UINT32 *SectionHeaderOffset,\r
161 IN OUT UINT16 *NumberOfSections\r
162 )\r
163{\r
164 RETURN_STATUS Status;\r
165 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
166 EFI_IMAGE_OPTIONAL_HEADER_UNION HdrData;\r
167 UINTN Size;\r
168 UINTN ReadSize;\r
169\r
170 ASSERT (ImageContext != NULL);\r
171 ASSERT (TmpContext != NULL);\r
172 ASSERT (SectionHeaderOffset != NULL);\r
173 ASSERT (NumberOfSections != NULL);\r
174\r
175 //\r
176 // We need to copy ImageContext since PeCoffLoaderGetImageInfo ()\r
177 // will mangle the ImageAddress field\r
178 //\r
179 CopyMem (TmpContext, ImageContext, sizeof (*TmpContext));\r
180\r
181 if (TmpContext->PeCoffHeaderOffset == 0) {\r
182 Status = PeCoffLoaderGetImageInfo (TmpContext);\r
183 if (RETURN_ERROR (Status)) {\r
184 DEBUG ((DEBUG_ERROR,\r
185 "%a: PeCoffLoaderGetImageInfo () failed (Status = %r)\n",\r
186 __FUNCTION__, Status));\r
187 return Status;\r
188 }\r
189 }\r
190\r
191 if (TmpContext->IsTeImage &&\r
192 TmpContext->ImageAddress == ImageContext->ImageAddress) {\r
193 DEBUG ((DEBUG_INFO, "%a: ignoring XIP TE image at 0x%lx\n", __FUNCTION__,\r
194 ImageContext->ImageAddress));\r
195 return RETURN_UNSUPPORTED;\r
196 }\r
197\r
198 if (TmpContext->SectionAlignment < EFI_PAGE_SIZE) {\r
199 //\r
200 // The sections need to be at least 4 KB aligned, since that is the\r
201 // granularity at which we can tighten permissions.\r
202 //\r
203 if (!TmpContext->IsTeImage) {\r
204 DEBUG ((DEBUG_WARN,\r
205 "%a: non-TE Image at 0x%lx has SectionAlignment < 4 KB (%lu)\n",\r
206 __FUNCTION__, ImageContext->ImageAddress, TmpContext->SectionAlignment));\r
207 }\r
208 return RETURN_UNSUPPORTED;\r
209 }\r
210\r
211 //\r
212 // Read the PE/COFF Header. For PE32 (32-bit) this will read in too much\r
213 // data, but that should not hurt anything. Hdr.Pe32->OptionalHeader.Magic\r
214 // determines if this is a PE32 or PE32+ image. The magic is in the same\r
215 // location in both images.\r
216 //\r
217 Hdr.Union = &HdrData;\r
218 Size = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION);\r
219 ReadSize = Size;\r
220 Status = TmpContext->ImageRead (\r
221 TmpContext->Handle,\r
222 TmpContext->PeCoffHeaderOffset,\r
223 &Size,\r
224 Hdr.Pe32\r
225 );\r
226\r
227 if (RETURN_ERROR (Status) || (Size != ReadSize)) {\r
228 DEBUG ((DEBUG_ERROR,\r
229 "%a: TmpContext->ImageRead () failed (Status = %r)\n",\r
230 __FUNCTION__, Status));\r
231 return Status;\r
232 }\r
233\r
234 ASSERT (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE);\r
235\r
236 *SectionHeaderOffset = TmpContext->PeCoffHeaderOffset + sizeof (UINT32) +\r
237 sizeof (EFI_IMAGE_FILE_HEADER);\r
238 *NumberOfSections = Hdr.Pe32->FileHeader.NumberOfSections;\r
239\r
240 switch (Hdr.Pe32->OptionalHeader.Magic) {\r
241 case EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC:\r
242 *SectionHeaderOffset += Hdr.Pe32->FileHeader.SizeOfOptionalHeader;\r
243 break;\r
244 case EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC:\r
245 *SectionHeaderOffset += Hdr.Pe32Plus->FileHeader.SizeOfOptionalHeader;\r
246 break;\r
247 default:\r
248 ASSERT (FALSE);\r
249 }\r
250\r
251 return RETURN_SUCCESS;\r
252}\r
253\r
254EFI_STATUS\r
255EFIAPI\r
256GetStandaloneMmCorePeCoffSections (\r
257 IN VOID *TeData,\r
258 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,\r
259 IN OUT UINT32 *SectionHeaderOffset,\r
260 IN OUT UINT16 *NumberOfSections\r
261 )\r
262{\r
263 EFI_STATUS Status;\r
264 PE_COFF_LOADER_IMAGE_CONTEXT TmpContext;\r
265\r
266 // Initialize the Image Context\r
267 ZeroMem (ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));\r
268 ImageContext->Handle = TeData;\r
269 ImageContext->ImageRead = PeCoffLoaderImageReadFromMemory;\r
270\r
271 DEBUG ((DEBUG_INFO, "Found Standalone MM PE data - 0x%x\n", TeData));\r
272\r
273 Status = PeCoffLoaderGetImageInfo (ImageContext);\r
274 if (EFI_ERROR (Status)) {\r
275 DEBUG ((DEBUG_ERROR, "Unable to locate Standalone MM Core PE-COFF Image information - 0x%x\n", Status));\r
276 return Status;\r
277 }\r
278\r
279 Status = GetPeCoffSectionInformation (ImageContext, &TmpContext, SectionHeaderOffset, NumberOfSections);\r
280 if (EFI_ERROR (Status)) {\r
281 DEBUG ((DEBUG_ERROR, "Unable to locate Standalone MM Core PE-COFF Section information - 0x%x\n", Status));\r
282 return Status;\r
283 }\r
284\r
285 DEBUG ((DEBUG_INFO, "Standalone MM Core PE-COFF SectionHeaderOffset - 0x%x, NumberOfSections - %d\n",\r
286 *SectionHeaderOffset, *NumberOfSections));\r
287\r
288 return Status;\r
289}\r