1 /** @file
2   PE/COFF Loader Library implementation that wraps a protocol passed up from
3   SEC/PEI via a HOB. This is done to save space.
4 
5   Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
6   Portions copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
7   SPDX-License-Identifier: BSD-2-Clause-Patent
8 
9 **/
10 
11 #include <PiDxe.h>
12 #include <Library/DebugLib.h>
13 #include <Library/HobLib.h>
14 
15 #include <Protocol/PeCoffLoader.h>
16 
17 
18 PE_COFF_LOADER_PROTOCOL  *gPeCoffLoader = NULL;
19 
20 
21 /**
22   Retrieves information about a PE/COFF image.
23 
24   Computes the PeCoffHeaderOffset, IsTeImage, ImageType, ImageAddress, ImageSize,
25   DestinationAddress, RelocationsStripped, SectionAlignment, SizeOfHeaders, and
26   DebugDirectoryEntryRva fields of the ImageContext structure.
27   If ImageContext is NULL, then return RETURN_INVALID_PARAMETER.
28   If the PE/COFF image accessed through the ImageRead service in the ImageContext
29   structure is not a supported PE/COFF image type, then return RETURN_UNSUPPORTED.
30   If any errors occur while computing the fields of ImageContext,
31   then the error status is returned in the ImageError field of ImageContext.
32   If the image is a TE image, then SectionAlignment is set to 0.
33   The ImageRead and Handle fields of ImageContext structure must be valid prior
34   to invoking this service.
35 
36   @param  ImageContext              Pointer to the image context structure that describes the PE/COFF
37                                     image that needs to be examined by this function.
38 
39   @retval RETURN_SUCCESS            The information on the PE/COFF image was collected.
40   @retval RETURN_INVALID_PARAMETER  ImageContext is NULL.
41   @retval RETURN_UNSUPPORTED        The PE/COFF image is not supported.
42 
43 **/
44 RETURN_STATUS
45 EFIAPI
PeCoffLoaderGetImageInfo(IN OUT PE_COFF_LOADER_IMAGE_CONTEXT * ImageContext)46 PeCoffLoaderGetImageInfo (
47   IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
48   )
49 {
50   return gPeCoffLoader->GetImageInfo (ImageContext);
51 }
52 
53 
54 /**
55   Applies relocation fixups to a PE/COFF image that was loaded with PeCoffLoaderLoadImage().
56 
57   If the DestinationAddress field of ImageContext is 0, then use the ImageAddress field of
58   ImageContext as the relocation base address.  Otherwise, use the DestinationAddress field
59   of ImageContext as the relocation base address.  The caller must allocate the relocation
60   fixup log buffer and fill in the FixupData field of ImageContext prior to calling this function.
61 
62   The ImageRead, Handle, PeCoffHeaderOffset, IsTeImage, Machine, ImageType, ImageAddress,
63   ImageSize, DestinationAddress, RelocationsStripped, SectionAlignment, SizeOfHeaders,
64   DebugDirectoryEntryRva, EntryPoint, FixupDataSize, CodeView, PdbPointer, and FixupData of
65   the ImageContext structure must be valid prior to invoking this service.
66 
67   If ImageContext is NULL, then ASSERT().
68 
69   Note that if the platform does not maintain coherency between the instruction cache(s) and the data
70   cache(s) in hardware, then the caller is responsible for performing cache maintenance operations
71   prior to transferring control to a PE/COFF image that is loaded using this library.
72 
73   @param  ImageContext        Pointer to the image context structure that describes the PE/COFF
74                               image that is being relocated.
75 
76   @retval RETURN_SUCCESS      The PE/COFF image was relocated.
77                               Extended status information is in the ImageError field of ImageContext.
78   @retval RETURN_LOAD_ERROR   The image in not a valid PE/COFF image.
79                               Extended status information is in the ImageError field of ImageContext.
80   @retval RETURN_UNSUPPORTED  A relocation record type is not supported.
81                               Extended status information is in the ImageError field of ImageContext.
82 
83 **/
84 RETURN_STATUS
85 EFIAPI
PeCoffLoaderRelocateImage(IN OUT PE_COFF_LOADER_IMAGE_CONTEXT * ImageContext)86 PeCoffLoaderRelocateImage (
87   IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
88   )
89 {
90   return gPeCoffLoader->RelocateImage (ImageContext);
91 }
92 
93 /**
94   Loads a PE/COFF image into memory.
95 
96   Loads the PE/COFF image accessed through the ImageRead service of ImageContext into the buffer
97   specified by the ImageAddress and ImageSize fields of ImageContext.  The caller must allocate
98   the load buffer and fill in the ImageAddress and ImageSize fields prior to calling this function.
99   The EntryPoint, FixupDataSize, CodeView, PdbPointer and HiiResourceData fields of ImageContext are computed.
100   The ImageRead, Handle, PeCoffHeaderOffset, IsTeImage, Machine, ImageType, ImageAddress, ImageSize,
101   DestinationAddress, RelocationsStripped, SectionAlignment, SizeOfHeaders, and DebugDirectoryEntryRva
102   fields of the ImageContext structure must be valid prior to invoking this service.
103 
104   If ImageContext is NULL, then ASSERT().
105 
106   Note that if the platform does not maintain coherency between the instruction cache(s) and the data
107   cache(s) in hardware, then the caller is responsible for performing cache maintenance operations
108   prior to transferring control to a PE/COFF image that is loaded using this library.
109 
110   @param  ImageContext              Pointer to the image context structure that describes the PE/COFF
111                                     image that is being loaded.
112 
113   @retval RETURN_SUCCESS            The PE/COFF image was loaded into the buffer specified by
114                                     the ImageAddress and ImageSize fields of ImageContext.
115                                     Extended status information is in the ImageError field of ImageContext.
116   @retval RETURN_BUFFER_TOO_SMALL   The caller did not provide a large enough buffer.
117                                     Extended status information is in the ImageError field of ImageContext.
118   @retval RETURN_LOAD_ERROR         The PE/COFF image is an EFI Runtime image with no relocations.
119                                     Extended status information is in the ImageError field of ImageContext.
120   @retval RETURN_INVALID_PARAMETER  The image address is invalid.
121                                     Extended status information is in the ImageError field of ImageContext.
122 
123 **/
124 RETURN_STATUS
125 EFIAPI
PeCoffLoaderLoadImage(IN OUT PE_COFF_LOADER_IMAGE_CONTEXT * ImageContext)126 PeCoffLoaderLoadImage (
127   IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
128   )
129 {
130   return gPeCoffLoader->LoadImage (ImageContext);
131 }
132 
133 
134 
135 /**
136   Reads contents of a PE/COFF image from a buffer in system memory.
137 
138   This is the default implementation of a PE_COFF_LOADER_READ_FILE function
139   that assumes FileHandle pointer to the beginning of a PE/COFF image.
140   This function reads contents of the PE/COFF image that starts at the system memory
141   address specified by FileHandle. The read operation copies ReadSize bytes from the
142   PE/COFF image starting at byte offset FileOffset into the buffer specified by Buffer.
143   The size of the buffer actually read is returned in ReadSize.
144 
145   If FileHandle is NULL, then ASSERT().
146   If ReadSize is NULL, then ASSERT().
147   If Buffer is NULL, then ASSERT().
148 
149   @param  FileHandle        Pointer to base of the input stream
150   @param  FileOffset        Offset into the PE/COFF image to begin the read operation.
151   @param  ReadSize          On input, the size in bytes of the requested read operation.
152                             On output, the number of bytes actually read.
153   @param  Buffer            Output buffer that contains the data read from the PE/COFF image.
154 
155   @retval RETURN_SUCCESS    Data is read from FileOffset from the Handle into
156                             the buffer.
157 **/
158 RETURN_STATUS
159 EFIAPI
PeCoffLoaderImageReadFromMemory(IN VOID * FileHandle,IN UINTN FileOffset,IN OUT UINTN * ReadSize,OUT VOID * Buffer)160 PeCoffLoaderImageReadFromMemory (
161   IN     VOID    *FileHandle,
162   IN     UINTN   FileOffset,
163   IN OUT UINTN   *ReadSize,
164   OUT    VOID    *Buffer
165   )
166 {
167   return gPeCoffLoader->ReadFromMemory (
168                           FileHandle,
169                           FileOffset,
170                           ReadSize,
171                           Buffer
172                           );
173 
174 }
175 
176 
177 
178 /**
179   Reapply fixups on a fixed up PE32/PE32+ image to allow virutal calling at EFI
180   runtime.
181 
182   This function reapplies relocation fixups to the PE/COFF image specified by ImageBase
183   and ImageSize so the image will execute correctly when the PE/COFF image is mapped
184   to the address specified by VirtualImageBase. RelocationData must be identical
185   to the FiuxupData buffer from the PE_COFF_LOADER_IMAGE_CONTEXT structure
186   after this PE/COFF image was relocated with PeCoffLoaderRelocateImage().
187 
188   Note that if the platform does not maintain coherency between the instruction cache(s) and the data
189   cache(s) in hardware, then the caller is responsible for performing cache maintenance operations
190   prior to transferring control to a PE/COFF image that is loaded using this library.
191 
192   @param  ImageBase          Base address of a PE/COFF image that has been loaded
193                              and relocated into system memory.
194   @param  VirtImageBase      The request virtual address that the PE/COFF image is to
195                              be fixed up for.
196   @param  ImageSize          The size, in bytes, of the PE/COFF image.
197   @param  RelocationData     A pointer to the relocation data that was collected when the PE/COFF
198                              image was relocated using PeCoffLoaderRelocateImage().
199 
200 **/
201 VOID
202 EFIAPI
PeCoffLoaderRelocateImageForRuntime(IN PHYSICAL_ADDRESS ImageBase,IN PHYSICAL_ADDRESS VirtImageBase,IN UINTN ImageSize,IN VOID * RelocationData)203 PeCoffLoaderRelocateImageForRuntime (
204   IN  PHYSICAL_ADDRESS        ImageBase,
205   IN  PHYSICAL_ADDRESS        VirtImageBase,
206   IN  UINTN                   ImageSize,
207   IN  VOID                    *RelocationData
208   )
209 {
210   return gPeCoffLoader->RelocateImageForRuntime (
211                           ImageBase,
212                           VirtImageBase,
213                           ImageSize,
214                           RelocationData
215                           );
216 }
217 
218 
219 /**
220   Unloads a loaded PE/COFF image from memory and releases its taken resource.
221   Releases any environment specific resources that were allocated when the image
222   specified by ImageContext was loaded using PeCoffLoaderLoadImage().
223 
224   For NT32 emulator, the PE/COFF image loaded by system needs to release.
225   For real platform, the PE/COFF image loaded by Core doesn't needs to be unloaded,
226   this function can simply return RETURN_SUCCESS.
227 
228   If ImageContext is NULL, then ASSERT().
229 
230   @param  ImageContext              Pointer to the image context structure that describes the PE/COFF
231                                     image to be unloaded.
232 
233   @retval RETURN_SUCCESS            The PE/COFF image was unloaded successfully.
234 **/
235 RETURN_STATUS
236 EFIAPI
PeCoffLoaderUnloadImage(IN OUT PE_COFF_LOADER_IMAGE_CONTEXT * ImageContext)237 PeCoffLoaderUnloadImage (
238   IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
239   )
240 {
241   return gPeCoffLoader->UnloadImage (ImageContext);
242 }
243 
244 typedef struct {
245   EFI_HOB_GUID_TYPE             Hob;
246   VOID                          *Interface;
247 } PROTOCOL_HOB;
248 
249 
250 /**
251   The constructor function caches the pointer of DXE Services Table.
252 
253   The constructor function caches the pointer of DXE Services Table.
254   It will ASSERT() if that operation fails.
255   It will ASSERT() if the pointer of DXE Services Table is NULL.
256   It will always return EFI_SUCCESS.
257 
258   @param  ImageHandle   The firmware allocated handle for the EFI image.
259   @param  SystemTable   A pointer to the EFI System Table.
260 
261   @retval EFI_SUCCESS   The constructor always returns EFI_SUCCESS.
262 
263 **/
264 EFI_STATUS
265 EFIAPI
DxeHobPeCoffLibConstructor(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)266 DxeHobPeCoffLibConstructor (
267   IN EFI_HANDLE        ImageHandle,
268   IN EFI_SYSTEM_TABLE  *SystemTable
269   )
270 {
271   PROTOCOL_HOB   *Hob;
272 
273   Hob = GetFirstGuidHob (&gPeCoffLoaderProtocolGuid);
274   if (Hob == NULL) {
275     return EFI_NOT_FOUND;
276   }
277 
278   gPeCoffLoader = Hob->Interface;
279   return EFI_SUCCESS;
280 }
281 
282 
283