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