]> git.proxmox.com Git - mirror_edk2.git/blame - StandaloneMmPkg/Library/StandaloneMmPeCoffExtraActionLib/AArch64/StandaloneMmPeCoffExtraActionLib.c
StandaloneMmPkg/StandaloneMmPeCoffExtraActionLib: ignore runtime attribute
[mirror_edk2.git] / StandaloneMmPkg / Library / StandaloneMmPeCoffExtraActionLib / AArch64 / StandaloneMmPeCoffExtraActionLib.c
CommitLineData
f7f94ffe
SG
1/**@file\r
2\r
3Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>\r
4Portions copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>\r
5Portions copyright (c) 2011 - 2018, ARM Ltd. All rights reserved.<BR>\r
6\r
7This program and the accompanying materials\r
8are licensed and made available under the terms and conditions of the BSD License\r
9which accompanies this distribution. The full text of the license may be found at\r
10http://opensource.org/licenses/bsd-license.php\r
11\r
12THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15**/\r
16\r
17#include <PiDxe.h>\r
18\r
19#include <Library/ArmMmuLib.h>\r
20#include <Library/BaseLib.h>\r
21#include <Library/BaseMemoryLib.h>\r
22#include <Library/DebugLib.h>\r
23#include <Library/PcdLib.h>\r
24#include <Library/PeCoffLib.h>\r
25#include <Library/PeCoffExtraActionLib.h>\r
26\r
27typedef RETURN_STATUS (*REGION_PERMISSION_UPDATE_FUNC) (\r
28 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
29 IN UINT64 Length\r
30 );\r
31\r
32STATIC\r
33RETURN_STATUS\r
34UpdatePeCoffPermissions (\r
35 IN CONST PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,\r
36 IN REGION_PERMISSION_UPDATE_FUNC NoExecUpdater,\r
37 IN REGION_PERMISSION_UPDATE_FUNC ReadOnlyUpdater\r
38 )\r
39{\r
40 RETURN_STATUS Status;\r
41 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
42 EFI_IMAGE_OPTIONAL_HEADER_UNION HdrData;\r
43 UINTN Size;\r
44 UINTN ReadSize;\r
45 UINT32 SectionHeaderOffset;\r
46 UINTN NumberOfSections;\r
47 UINTN Index;\r
48 EFI_IMAGE_SECTION_HEADER SectionHeader;\r
49 PE_COFF_LOADER_IMAGE_CONTEXT TmpContext;\r
50 EFI_PHYSICAL_ADDRESS Base;\r
51\r
52 //\r
53 // We need to copy ImageContext since PeCoffLoaderGetImageInfo ()\r
54 // will mangle the ImageAddress field\r
55 //\r
56 CopyMem (&TmpContext, ImageContext, sizeof (TmpContext));\r
57\r
58 if (TmpContext.PeCoffHeaderOffset == 0) {\r
59 Status = PeCoffLoaderGetImageInfo (&TmpContext);\r
60 if (RETURN_ERROR (Status)) {\r
61 DEBUG ((DEBUG_ERROR,\r
62 "%a: PeCoffLoaderGetImageInfo () failed (Status = %r)\n",\r
63 __FUNCTION__, Status));\r
64 return Status;\r
65 }\r
66 }\r
67\r
68 if (TmpContext.IsTeImage &&\r
69 TmpContext.ImageAddress == ImageContext->ImageAddress) {\r
70 DEBUG ((DEBUG_INFO, "%a: ignoring XIP TE image at 0x%lx\n", __FUNCTION__,\r
71 ImageContext->ImageAddress));\r
72 return RETURN_SUCCESS;\r
73 }\r
74\r
75 if (TmpContext.SectionAlignment < EFI_PAGE_SIZE) {\r
76 //\r
77 // The sections need to be at least 4 KB aligned, since that is the\r
78 // granularity at which we can tighten permissions. So just clear the\r
79 // noexec permissions on the entire region.\r
80 //\r
81 if (!TmpContext.IsTeImage) {\r
82 DEBUG ((DEBUG_WARN,\r
83 "%a: non-TE Image at 0x%lx has SectionAlignment < 4 KB (%lu)\n",\r
84 __FUNCTION__, ImageContext->ImageAddress, TmpContext.SectionAlignment));\r
85 }\r
86 Base = ImageContext->ImageAddress & ~(EFI_PAGE_SIZE - 1);\r
87 Size = ImageContext->ImageAddress - Base + ImageContext->ImageSize;\r
88 return NoExecUpdater (Base, ALIGN_VALUE (Size, EFI_PAGE_SIZE));\r
89 }\r
90\r
91 //\r
92 // Read the PE/COFF Header. For PE32 (32-bit) this will read in too much\r
93 // data, but that should not hurt anything. Hdr.Pe32->OptionalHeader.Magic\r
94 // determines if this is a PE32 or PE32+ image. The magic is in the same\r
95 // location in both images.\r
96 //\r
97 Hdr.Union = &HdrData;\r
98 Size = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION);\r
99 ReadSize = Size;\r
100 Status = TmpContext.ImageRead (TmpContext.Handle,\r
101 TmpContext.PeCoffHeaderOffset, &Size, Hdr.Pe32);\r
102 if (RETURN_ERROR (Status) || (Size != ReadSize)) {\r
103 DEBUG ((DEBUG_ERROR,\r
104 "%a: TmpContext.ImageRead () failed (Status = %r)\n",\r
105 __FUNCTION__, Status));\r
106 return Status;\r
107 }\r
108\r
109 ASSERT (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE);\r
110\r
111 SectionHeaderOffset = TmpContext.PeCoffHeaderOffset + sizeof (UINT32) +\r
112 sizeof (EFI_IMAGE_FILE_HEADER);\r
113 NumberOfSections = (UINTN)(Hdr.Pe32->FileHeader.NumberOfSections);\r
114\r
115 switch (Hdr.Pe32->OptionalHeader.Magic) {\r
116 case EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC:\r
117 SectionHeaderOffset += Hdr.Pe32->FileHeader.SizeOfOptionalHeader;\r
118 break;\r
119 case EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC:\r
120 SectionHeaderOffset += Hdr.Pe32Plus->FileHeader.SizeOfOptionalHeader;\r
121 break;\r
122 default:\r
123 ASSERT (FALSE);\r
124 }\r
125\r
126 //\r
127 // Iterate over the sections\r
128 //\r
129 for (Index = 0; Index < NumberOfSections; Index++) {\r
130 //\r
131 // Read section header from file\r
132 //\r
133 Size = sizeof (EFI_IMAGE_SECTION_HEADER);\r
134 ReadSize = Size;\r
135 Status = TmpContext.ImageRead (TmpContext.Handle, SectionHeaderOffset,\r
136 &Size, &SectionHeader);\r
137 if (RETURN_ERROR (Status) || (Size != ReadSize)) {\r
138 DEBUG ((DEBUG_ERROR,\r
139 "%a: TmpContext.ImageRead () failed (Status = %r)\n",\r
140 __FUNCTION__, Status));\r
141 return Status;\r
142 }\r
143\r
144 Base = TmpContext.ImageAddress + SectionHeader.VirtualAddress;\r
145\r
146 if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_MEM_EXECUTE) == 0) {\r
147\r
77746e70 148 if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_MEM_WRITE) == 0) {\r
f7f94ffe
SG
149\r
150 DEBUG ((DEBUG_INFO,\r
151 "%a: Mapping section %d of image at 0x%lx with RO-XN permissions and size 0x%x\n",\r
152 __FUNCTION__, Index, Base, SectionHeader.Misc.VirtualSize));\r
153 ReadOnlyUpdater (Base, SectionHeader.Misc.VirtualSize);\r
154 } else {\r
155 DEBUG ((DEBUG_WARN,\r
156 "%a: Mapping section %d of image at 0x%lx with RW-XN permissions and size 0x%x\n",\r
157 __FUNCTION__, Index, Base, SectionHeader.Misc.VirtualSize));\r
158 }\r
159 } else {\r
f7f94ffe
SG
160 DEBUG ((DEBUG_INFO,\r
161 "%a: Mapping section %d of image at 0x%lx with RO-X permissions and size 0x%x\n",\r
162 __FUNCTION__, Index, Base, SectionHeader.Misc.VirtualSize));\r
77746e70 163 ReadOnlyUpdater (Base, SectionHeader.Misc.VirtualSize);\r
f7f94ffe
SG
164 NoExecUpdater (Base, SectionHeader.Misc.VirtualSize);\r
165 }\r
166\r
167 SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);\r
168 }\r
169 return RETURN_SUCCESS;\r
170}\r
171\r
172/**\r
173 Performs additional actions after a PE/COFF image has been loaded and relocated.\r
174\r
175 If ImageContext is NULL, then ASSERT().\r
176\r
177 @param ImageContext Pointer to the image context structure that describes the\r
178 PE/COFF image that has already been loaded and relocated.\r
179\r
180**/\r
181VOID\r
182EFIAPI\r
183PeCoffLoaderRelocateImageExtraAction (\r
184 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext\r
185 )\r
186{\r
187 UpdatePeCoffPermissions (\r
188 ImageContext,\r
189 ArmClearMemoryRegionNoExec,\r
190 ArmSetMemoryRegionReadOnly\r
191 );\r
192}\r
193\r
194\r
195\r
196/**\r
197 Performs additional actions just before a PE/COFF image is unloaded. Any resources\r
198 that were allocated by PeCoffLoaderRelocateImageExtraAction() must be freed.\r
199\r
200 If ImageContext is NULL, then ASSERT().\r
201\r
202 @param ImageContext Pointer to the image context structure that describes the\r
203 PE/COFF image that is being unloaded.\r
204\r
205**/\r
206VOID\r
207EFIAPI\r
208PeCoffLoaderUnloadImageExtraAction (\r
209 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext\r
210 )\r
211{\r
212 UpdatePeCoffPermissions (\r
213 ImageContext,\r
214 ArmSetMemoryRegionNoExec,\r
215 ArmClearMemoryRegionReadOnly\r
216 );\r
217}\r