]> git.proxmox.com Git - mirror_edk2.git/blame - StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/SetPermissions.c
SourceLevelDebugPkg: Replace BSD License with BSD+Patent License
[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
4b28452d
AB
146 Status = FfsFindSectionData (EFI_SECTION_TE, FileHeader, TeData, TeDataSize);\r
147 if (EFI_ERROR (Status)) {\r
148 DEBUG ((DEBUG_ERROR, "Unable to locate Standalone MM Section data - %r\n",\r
149 Status));\r
150 return Status;\r
151 }\r
184558d0
SV
152 }\r
153\r
154 DEBUG ((DEBUG_INFO, "Found Standalone MM PE data - 0x%x\n", *TeData));\r
155 return Status;\r
156}\r
157\r
158STATIC\r
159EFI_STATUS\r
160GetPeCoffSectionInformation (\r
4b28452d
AB
161 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,\r
162 OUT UINT32 *SectionHeaderOffset,\r
163 OUT UINT16 *NumberOfSections\r
184558d0
SV
164 )\r
165{\r
166 RETURN_STATUS Status;\r
167 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
168 EFI_IMAGE_OPTIONAL_HEADER_UNION HdrData;\r
169 UINTN Size;\r
170 UINTN ReadSize;\r
171\r
172 ASSERT (ImageContext != NULL);\r
184558d0
SV
173 ASSERT (SectionHeaderOffset != NULL);\r
174 ASSERT (NumberOfSections != NULL);\r
175\r
4b28452d
AB
176 Status = PeCoffLoaderGetImageInfo (ImageContext);\r
177 if (RETURN_ERROR (Status)) {\r
178 DEBUG ((DEBUG_ERROR,\r
179 "%a: PeCoffLoaderGetImageInfo () failed (Status == %r)\n",\r
180 __FUNCTION__, Status));\r
181 return Status;\r
184558d0
SV
182 }\r
183\r
4b28452d 184 if (ImageContext->SectionAlignment < EFI_PAGE_SIZE) {\r
184558d0
SV
185 //\r
186 // The sections need to be at least 4 KB aligned, since that is the\r
187 // granularity at which we can tighten permissions.\r
188 //\r
4b28452d 189 if (!ImageContext->IsTeImage) {\r
184558d0
SV
190 DEBUG ((DEBUG_WARN,\r
191 "%a: non-TE Image at 0x%lx has SectionAlignment < 4 KB (%lu)\n",\r
4b28452d
AB
192 __FUNCTION__, ImageContext->ImageAddress, ImageContext->SectionAlignment));\r
193 return RETURN_UNSUPPORTED;\r
184558d0 194 }\r
4b28452d 195 ImageContext->SectionAlignment = EFI_PAGE_SIZE;\r
184558d0
SV
196 }\r
197\r
198 //\r
199 // Read the PE/COFF Header. For PE32 (32-bit) this will read in too much\r
200 // data, but that should not hurt anything. Hdr.Pe32->OptionalHeader.Magic\r
201 // determines if this is a PE32 or PE32+ image. The magic is in the same\r
202 // location in both images.\r
203 //\r
204 Hdr.Union = &HdrData;\r
205 Size = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION);\r
206 ReadSize = Size;\r
4b28452d
AB
207 Status = ImageContext->ImageRead (\r
208 ImageContext->Handle,\r
209 ImageContext->PeCoffHeaderOffset,\r
184558d0
SV
210 &Size,\r
211 Hdr.Pe32\r
212 );\r
213\r
214 if (RETURN_ERROR (Status) || (Size != ReadSize)) {\r
215 DEBUG ((DEBUG_ERROR,\r
216 "%a: TmpContext->ImageRead () failed (Status = %r)\n",\r
217 __FUNCTION__, Status));\r
218 return Status;\r
219 }\r
220\r
4b28452d
AB
221 if (!ImageContext->IsTeImage) {\r
222 ASSERT (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE);\r
223\r
224 *SectionHeaderOffset = ImageContext->PeCoffHeaderOffset + sizeof (UINT32) +\r
225 sizeof (EFI_IMAGE_FILE_HEADER);\r
226 *NumberOfSections = Hdr.Pe32->FileHeader.NumberOfSections;\r
227\r
228 switch (Hdr.Pe32->OptionalHeader.Magic) {\r
229 case EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC:\r
230 *SectionHeaderOffset += Hdr.Pe32->FileHeader.SizeOfOptionalHeader;\r
231 break;\r
232 case EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC:\r
233 *SectionHeaderOffset += Hdr.Pe32Plus->FileHeader.SizeOfOptionalHeader;\r
234 break;\r
235 default:\r
236 ASSERT (FALSE);\r
237 }\r
238 } else {\r
239 *SectionHeaderOffset = (UINTN)(sizeof (EFI_TE_IMAGE_HEADER));\r
240 *NumberOfSections = Hdr.Te->NumberOfSections;\r
241 ImageContext->ImageAddress -= (UINT32)Hdr.Te->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER);\r
184558d0 242 }\r
184558d0
SV
243 return RETURN_SUCCESS;\r
244}\r
245\r
246EFI_STATUS\r
247EFIAPI\r
248GetStandaloneMmCorePeCoffSections (\r
249 IN VOID *TeData,\r
250 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,\r
251 IN OUT UINT32 *SectionHeaderOffset,\r
252 IN OUT UINT16 *NumberOfSections\r
253 )\r
254{\r
255 EFI_STATUS Status;\r
184558d0
SV
256\r
257 // Initialize the Image Context\r
258 ZeroMem (ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));\r
259 ImageContext->Handle = TeData;\r
260 ImageContext->ImageRead = PeCoffLoaderImageReadFromMemory;\r
261\r
262 DEBUG ((DEBUG_INFO, "Found Standalone MM PE data - 0x%x\n", TeData));\r
263\r
4b28452d 264 Status = GetPeCoffSectionInformation (ImageContext, SectionHeaderOffset, NumberOfSections);\r
184558d0 265 if (EFI_ERROR (Status)) {\r
4b28452d 266 DEBUG ((DEBUG_ERROR, "Unable to locate Standalone MM Core PE-COFF Section information - %r\n", Status));\r
184558d0
SV
267 return Status;\r
268 }\r
269\r
270 DEBUG ((DEBUG_INFO, "Standalone MM Core PE-COFF SectionHeaderOffset - 0x%x, NumberOfSections - %d\n",\r
271 *SectionHeaderOffset, *NumberOfSections));\r
272\r
273 return Status;\r
274}\r