]> git.proxmox.com Git - mirror_edk2.git/blob - StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/SetPermissions.c
StandaloneMmPkg: Replace BSD License with BSD+Patent License
[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 - 2018, 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 UINT32 SectionHeaderOffset,
33 IN CONST UINT16 NumberOfSections,
34 IN REGION_PERMISSION_UPDATE_FUNC TextUpdater,
35 IN REGION_PERMISSION_UPDATE_FUNC ReadOnlyUpdater,
36 IN REGION_PERMISSION_UPDATE_FUNC ReadWriteUpdater
37 )
38 {
39 EFI_IMAGE_SECTION_HEADER SectionHeader;
40 RETURN_STATUS Status;
41 EFI_PHYSICAL_ADDRESS Base;
42 UINTN Size;
43 UINTN ReadSize;
44 UINTN Index;
45
46 ASSERT (ImageContext != NULL);
47
48 //
49 // Iterate over the sections
50 //
51 for (Index = 0; Index < NumberOfSections; Index++) {
52 //
53 // Read section header from file
54 //
55 Size = sizeof (EFI_IMAGE_SECTION_HEADER);
56 ReadSize = Size;
57 Status = ImageContext->ImageRead (
58 ImageContext->Handle,
59 SectionHeaderOffset,
60 &Size,
61 &SectionHeader
62 );
63
64 if (RETURN_ERROR (Status) || (Size != ReadSize)) {
65 DEBUG ((DEBUG_ERROR,
66 "%a: ImageContext->ImageRead () failed (Status = %r)\n",
67 __FUNCTION__, Status));
68 return Status;
69 }
70
71 DEBUG ((DEBUG_INFO,
72 "%a: Section %d of image at 0x%lx has 0x%x permissions\n",
73 __FUNCTION__, Index, ImageContext->ImageAddress, SectionHeader.Characteristics));
74 DEBUG ((DEBUG_INFO,
75 "%a: Section %d of image at 0x%lx has %a name\n",
76 __FUNCTION__, Index, ImageContext->ImageAddress, SectionHeader.Name));
77 DEBUG ((DEBUG_INFO,
78 "%a: Section %d of image at 0x%lx has 0x%x address\n",
79 __FUNCTION__, Index, ImageContext->ImageAddress,
80 ImageContext->ImageAddress + SectionHeader.VirtualAddress));
81 DEBUG ((DEBUG_INFO,
82 "%a: Section %d of image at 0x%lx has 0x%x data\n",
83 __FUNCTION__, Index, ImageContext->ImageAddress, SectionHeader.PointerToRawData));
84
85 //
86 // If the section is marked as XN then remove the X attribute. Furthermore,
87 // if it is a writeable section then mark it appropriately as well.
88 //
89 if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_MEM_EXECUTE) == 0) {
90 Base = ImageContext->ImageAddress + SectionHeader.VirtualAddress;
91
92 TextUpdater (Base, SectionHeader.Misc.VirtualSize);
93
94 if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_MEM_WRITE) != 0) {
95 ReadWriteUpdater (Base, SectionHeader.Misc.VirtualSize);
96 DEBUG ((DEBUG_INFO,
97 "%a: Mapping section %d of image at 0x%lx with RW-XN permissions\n",
98 __FUNCTION__, Index, ImageContext->ImageAddress));
99 } else {
100 DEBUG ((DEBUG_INFO,
101 "%a: Mapping section %d of image at 0x%lx with RO-XN permissions\n",
102 __FUNCTION__, Index, ImageContext->ImageAddress));
103 }
104 } else {
105 DEBUG ((DEBUG_INFO,
106 "%a: Ignoring section %d of image at 0x%lx with 0x%x permissions\n",
107 __FUNCTION__, Index, ImageContext->ImageAddress, SectionHeader.Characteristics));
108 }
109 SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
110 }
111
112 return RETURN_SUCCESS;
113 }
114
115 EFI_STATUS
116 EFIAPI
117 LocateStandaloneMmCorePeCoffData (
118 IN EFI_FIRMWARE_VOLUME_HEADER *BfvAddress,
119 IN OUT VOID **TeData,
120 IN OUT UINTN *TeDataSize
121 )
122 {
123 EFI_FFS_FILE_HEADER *FileHeader = NULL;
124 EFI_STATUS Status;
125
126 Status = FfsFindNextFile (
127 EFI_FV_FILETYPE_SECURITY_CORE,
128 BfvAddress,
129 &FileHeader
130 );
131
132 if (EFI_ERROR (Status)) {
133 DEBUG ((DEBUG_ERROR, "Unable to locate Standalone MM FFS file - 0x%x\n",
134 Status));
135 return Status;
136 }
137
138 Status = FfsFindSectionData (EFI_SECTION_PE32, FileHeader, TeData, TeDataSize);
139 if (EFI_ERROR (Status)) {
140 Status = FfsFindSectionData (EFI_SECTION_TE, FileHeader, TeData, TeDataSize);
141 if (EFI_ERROR (Status)) {
142 DEBUG ((DEBUG_ERROR, "Unable to locate Standalone MM Section data - %r\n",
143 Status));
144 return Status;
145 }
146 }
147
148 DEBUG ((DEBUG_INFO, "Found Standalone MM PE data - 0x%x\n", *TeData));
149 return Status;
150 }
151
152 STATIC
153 EFI_STATUS
154 GetPeCoffSectionInformation (
155 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
156 OUT UINT32 *SectionHeaderOffset,
157 OUT UINT16 *NumberOfSections
158 )
159 {
160 RETURN_STATUS Status;
161 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
162 EFI_IMAGE_OPTIONAL_HEADER_UNION HdrData;
163 UINTN Size;
164 UINTN ReadSize;
165
166 ASSERT (ImageContext != NULL);
167 ASSERT (SectionHeaderOffset != NULL);
168 ASSERT (NumberOfSections != NULL);
169
170 Status = PeCoffLoaderGetImageInfo (ImageContext);
171 if (RETURN_ERROR (Status)) {
172 DEBUG ((DEBUG_ERROR,
173 "%a: PeCoffLoaderGetImageInfo () failed (Status == %r)\n",
174 __FUNCTION__, Status));
175 return Status;
176 }
177
178 if (ImageContext->SectionAlignment < EFI_PAGE_SIZE) {
179 //
180 // The sections need to be at least 4 KB aligned, since that is the
181 // granularity at which we can tighten permissions.
182 //
183 if (!ImageContext->IsTeImage) {
184 DEBUG ((DEBUG_WARN,
185 "%a: non-TE Image at 0x%lx has SectionAlignment < 4 KB (%lu)\n",
186 __FUNCTION__, ImageContext->ImageAddress, ImageContext->SectionAlignment));
187 return RETURN_UNSUPPORTED;
188 }
189 ImageContext->SectionAlignment = EFI_PAGE_SIZE;
190 }
191
192 //
193 // Read the PE/COFF Header. For PE32 (32-bit) this will read in too much
194 // data, but that should not hurt anything. Hdr.Pe32->OptionalHeader.Magic
195 // determines if this is a PE32 or PE32+ image. The magic is in the same
196 // location in both images.
197 //
198 Hdr.Union = &HdrData;
199 Size = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION);
200 ReadSize = Size;
201 Status = ImageContext->ImageRead (
202 ImageContext->Handle,
203 ImageContext->PeCoffHeaderOffset,
204 &Size,
205 Hdr.Pe32
206 );
207
208 if (RETURN_ERROR (Status) || (Size != ReadSize)) {
209 DEBUG ((DEBUG_ERROR,
210 "%a: TmpContext->ImageRead () failed (Status = %r)\n",
211 __FUNCTION__, Status));
212 return Status;
213 }
214
215 if (!ImageContext->IsTeImage) {
216 ASSERT (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE);
217
218 *SectionHeaderOffset = ImageContext->PeCoffHeaderOffset + sizeof (UINT32) +
219 sizeof (EFI_IMAGE_FILE_HEADER);
220 *NumberOfSections = Hdr.Pe32->FileHeader.NumberOfSections;
221
222 switch (Hdr.Pe32->OptionalHeader.Magic) {
223 case EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC:
224 *SectionHeaderOffset += Hdr.Pe32->FileHeader.SizeOfOptionalHeader;
225 break;
226 case EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC:
227 *SectionHeaderOffset += Hdr.Pe32Plus->FileHeader.SizeOfOptionalHeader;
228 break;
229 default:
230 ASSERT (FALSE);
231 }
232 } else {
233 *SectionHeaderOffset = (UINTN)(sizeof (EFI_TE_IMAGE_HEADER));
234 *NumberOfSections = Hdr.Te->NumberOfSections;
235 ImageContext->ImageAddress -= (UINT32)Hdr.Te->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER);
236 }
237 return RETURN_SUCCESS;
238 }
239
240 EFI_STATUS
241 EFIAPI
242 GetStandaloneMmCorePeCoffSections (
243 IN VOID *TeData,
244 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
245 IN OUT UINT32 *SectionHeaderOffset,
246 IN OUT UINT16 *NumberOfSections
247 )
248 {
249 EFI_STATUS Status;
250
251 // Initialize the Image Context
252 ZeroMem (ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));
253 ImageContext->Handle = TeData;
254 ImageContext->ImageRead = PeCoffLoaderImageReadFromMemory;
255
256 DEBUG ((DEBUG_INFO, "Found Standalone MM PE data - 0x%x\n", TeData));
257
258 Status = GetPeCoffSectionInformation (ImageContext, SectionHeaderOffset, NumberOfSections);
259 if (EFI_ERROR (Status)) {
260 DEBUG ((DEBUG_ERROR, "Unable to locate Standalone MM Core PE-COFF Section information - %r\n", Status));
261 return Status;
262 }
263
264 DEBUG ((DEBUG_INFO, "Standalone MM Core PE-COFF SectionHeaderOffset - 0x%x, NumberOfSections - %d\n",
265 *SectionHeaderOffset, *NumberOfSections));
266
267 return Status;
268 }