1 | /** @file
|
---|
2 | Provides services to load and relocate a PE/COFF image.
|
---|
3 |
|
---|
4 | The PE/COFF Loader Library abstracts the implementation of a PE/COFF loader for
|
---|
5 | IA-32, x86, IPF, and EBC processor types. The library functions are memory-based
|
---|
6 | and can be ported easily to any environment.
|
---|
7 |
|
---|
8 | Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
|
---|
9 | This program and the accompanying materials are licensed and made available under
|
---|
10 | the terms and conditions of the BSD License that accompanies this distribution.
|
---|
11 | The full text of the license may be found at
|
---|
12 | http://opensource.org/licenses/bsd-license.php.
|
---|
13 |
|
---|
14 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
---|
15 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
---|
16 |
|
---|
17 | **/
|
---|
18 |
|
---|
19 | #ifndef __BASE_PE_COFF_LIB_H__
|
---|
20 | #define __BASE_PE_COFF_LIB_H__
|
---|
21 |
|
---|
22 | #include <IndustryStandard/PeImage.h>
|
---|
23 | //
|
---|
24 | // Return status codes from the PE/COFF Loader services
|
---|
25 | //
|
---|
26 | #define IMAGE_ERROR_SUCCESS 0
|
---|
27 | #define IMAGE_ERROR_IMAGE_READ 1
|
---|
28 | #define IMAGE_ERROR_INVALID_PE_HEADER_SIGNATURE 2
|
---|
29 | #define IMAGE_ERROR_INVALID_MACHINE_TYPE 3
|
---|
30 | #define IMAGE_ERROR_INVALID_SUBSYSTEM 4
|
---|
31 | #define IMAGE_ERROR_INVALID_IMAGE_ADDRESS 5
|
---|
32 | #define IMAGE_ERROR_INVALID_IMAGE_SIZE 6
|
---|
33 | #define IMAGE_ERROR_INVALID_SECTION_ALIGNMENT 7
|
---|
34 | #define IMAGE_ERROR_SECTION_NOT_LOADED 8
|
---|
35 | #define IMAGE_ERROR_FAILED_RELOCATION 9
|
---|
36 | #define IMAGE_ERROR_FAILED_ICACHE_FLUSH 10
|
---|
37 | #define IMAGE_ERROR_UNSUPPORTED 11
|
---|
38 |
|
---|
39 | /**
|
---|
40 | Reads contents of a PE/COFF image.
|
---|
41 |
|
---|
42 | A function of this type reads contents of the PE/COFF image specified by FileHandle. The read
|
---|
43 | operation copies ReadSize bytes from the PE/COFF image starting at byte offset FileOffset into
|
---|
44 | the buffer specified by Buffer. The size of the buffer actually read is returned in ReadSize.
|
---|
45 | If FileOffset specifies an offset past the end of the PE/COFF image, a ReadSize of 0 is returned.
|
---|
46 | A function of this type must be registered in the ImageRead field of a PE_COFF_LOADER_IMAGE_CONTEXT
|
---|
47 | structure for the PE/COFF Loader Library service to function correctly. This function abstracts access
|
---|
48 | to a PE/COFF image so it can be implemented in an environment specific manner. For example, SEC and PEI
|
---|
49 | environments may access memory directly to read the contents of a PE/COFF image, and DXE or UEFI
|
---|
50 | environments may require protocol services to read the contents of PE/COFF image
|
---|
51 | stored on FLASH, disk, or network devices.
|
---|
52 |
|
---|
53 | If FileHandle is not a valid handle, then ASSERT().
|
---|
54 | If ReadSize is NULL, then ASSERT().
|
---|
55 | If Buffer is NULL, then ASSERT().
|
---|
56 |
|
---|
57 | @param FileHandle Pointer to the file handle to read the PE/COFF image.
|
---|
58 | @param FileOffset Offset into the PE/COFF image to begin the read operation.
|
---|
59 | @param ReadSize On input, the size in bytes of the requested read operation.
|
---|
60 | On output, the number of bytes actually read.
|
---|
61 | @param Buffer Output buffer that contains the data read from the PE/COFF image.
|
---|
62 |
|
---|
63 | @retval RETURN_SUCCESS The specified portion of the PE/COFF image was
|
---|
64 | read and the size return in ReadSize.
|
---|
65 | @retval RETURN_DEVICE_ERROR The specified portion of the PE/COFF image
|
---|
66 | could not be read due to a device error.
|
---|
67 |
|
---|
68 | **/
|
---|
69 | typedef
|
---|
70 | RETURN_STATUS
|
---|
71 | (EFIAPI *PE_COFF_LOADER_READ_FILE)(
|
---|
72 | IN VOID *FileHandle,
|
---|
73 | IN UINTN FileOffset,
|
---|
74 | IN OUT UINTN *ReadSize,
|
---|
75 | OUT VOID *Buffer
|
---|
76 | );
|
---|
77 |
|
---|
78 | ///
|
---|
79 | /// The context structure used while PE/COFF image is being loaded and relocated.
|
---|
80 | ///
|
---|
81 | typedef struct {
|
---|
82 | ///
|
---|
83 | /// Set by PeCoffLoaderGetImageInfo() to the ImageBase in the PE/COFF header.
|
---|
84 | ///
|
---|
85 | PHYSICAL_ADDRESS ImageAddress;
|
---|
86 | ///
|
---|
87 | /// Set by PeCoffLoaderGetImageInfo() to the SizeOfImage in the PE/COFF header.
|
---|
88 | /// Image size includes the size of Debug Entry if it is present.
|
---|
89 | ///
|
---|
90 | UINT64 ImageSize;
|
---|
91 | ///
|
---|
92 | /// Is set to zero by PeCoffLoaderGetImageInfo(). If DestinationAddress is non-zero,
|
---|
93 | /// PeCoffLoaderRelocateImage() will relocate the image using this base address.
|
---|
94 | /// If the DestinationAddress is zero, the ImageAddress will be used as the base
|
---|
95 | /// address of relocation.
|
---|
96 | ///
|
---|
97 | PHYSICAL_ADDRESS DestinationAddress;
|
---|
98 | ///
|
---|
99 | /// PeCoffLoaderLoadImage() sets EntryPoint to to the entry point of the PE/COFF image.
|
---|
100 | ///
|
---|
101 | PHYSICAL_ADDRESS EntryPoint;
|
---|
102 | ///
|
---|
103 | /// Passed in by the caller to PeCoffLoaderGetImageInfo() and PeCoffLoaderLoadImage()
|
---|
104 | /// to abstract accessing the image from the library.
|
---|
105 | ///
|
---|
106 | PE_COFF_LOADER_READ_FILE ImageRead;
|
---|
107 | ///
|
---|
108 | /// Used as the FileHandle passed into the ImageRead function when it's called.
|
---|
109 | ///
|
---|
110 | VOID *Handle;
|
---|
111 | ///
|
---|
112 | /// Caller allocated buffer of size FixupDataSize that can be optionally allocated
|
---|
113 | /// prior to calling PeCoffLoaderRelocateImage().
|
---|
114 | /// This buffer is filled with the information used to fix up the image.
|
---|
115 | /// The fixups have been applied to the image and this entry is just for information.
|
---|
116 | ///
|
---|
117 | VOID *FixupData;
|
---|
118 | ///
|
---|
119 | /// Set by PeCoffLoaderGetImageInfo() to the Section Alignment in the PE/COFF header.
|
---|
120 | /// If the image is a TE image, then this field is set to 0.
|
---|
121 | ///
|
---|
122 | UINT32 SectionAlignment;
|
---|
123 | ///
|
---|
124 | /// Set by PeCoffLoaderGetImageInfo() to offset to the PE/COFF header.
|
---|
125 | /// If the PE/COFF image does not start with a DOS header, this value is zero.
|
---|
126 | /// Otherwise, it's the offset to the PE/COFF header.
|
---|
127 | ///
|
---|
128 | UINT32 PeCoffHeaderOffset;
|
---|
129 | ///
|
---|
130 | /// Set by PeCoffLoaderGetImageInfo() to the Relative Virtual Address of the debug directory,
|
---|
131 | /// if it exists in the image
|
---|
132 | ///
|
---|
133 | UINT32 DebugDirectoryEntryRva;
|
---|
134 | ///
|
---|
135 | /// Set by PeCoffLoaderLoadImage() to CodeView area of the PE/COFF Debug directory.
|
---|
136 | ///
|
---|
137 | VOID *CodeView;
|
---|
138 | ///
|
---|
139 | /// Set by PeCoffLoaderLoadImage() to point to the PDB entry contained in the CodeView area.
|
---|
140 | /// The PdbPointer points to the filename of the PDB file used for source-level debug of
|
---|
141 | /// the image by a debugger.
|
---|
142 | ///
|
---|
143 | CHAR8 *PdbPointer;
|
---|
144 | ///
|
---|
145 | /// Is set by PeCoffLoaderGetImageInfo() to the Section Alignment in the PE/COFF header.
|
---|
146 | ///
|
---|
147 | UINTN SizeOfHeaders;
|
---|
148 | ///
|
---|
149 | /// Not used by this library class. Other library classes that layer on top of this library
|
---|
150 | /// class fill in this value as part of their GetImageInfo call.
|
---|
151 | /// This allows the caller of the library to know what type of memory needs to be allocated
|
---|
152 | /// to load and relocate the image.
|
---|
153 | ///
|
---|
154 | UINT32 ImageCodeMemoryType;
|
---|
155 | ///
|
---|
156 | /// Not used by this library class. Other library classes that layer on top of this library
|
---|
157 | /// class fill in this value as part of their GetImageInfo call.
|
---|
158 | /// This allows the caller of the library to know what type of memory needs to be allocated
|
---|
159 | /// to load and relocate the image.
|
---|
160 | ///
|
---|
161 | UINT32 ImageDataMemoryType;
|
---|
162 | ///
|
---|
163 | /// Set by any of the library functions if they encounter an error.
|
---|
164 | ///
|
---|
165 | UINT32 ImageError;
|
---|
166 | ///
|
---|
167 | /// Set by PeCoffLoaderLoadImage() to indicate the size of FixupData that the caller must
|
---|
168 | /// allocate before calling PeCoffLoaderRelocateImage().
|
---|
169 | ///
|
---|
170 | UINTN FixupDataSize;
|
---|
171 | ///
|
---|
172 | /// Set by PeCoffLoaderGetImageInfo() to the machine type stored in the PE/COFF header.
|
---|
173 | ///
|
---|
174 | UINT16 Machine;
|
---|
175 | ///
|
---|
176 | /// Set by PeCoffLoaderGetImageInfo() to the subsystem type stored in the PE/COFF header.
|
---|
177 | ///
|
---|
178 | UINT16 ImageType;
|
---|
179 | ///
|
---|
180 | /// Set by PeCoffLoaderGetImageInfo() to TRUE if the PE/COFF image does not contain
|
---|
181 | /// relocation information.
|
---|
182 | ///
|
---|
183 | BOOLEAN RelocationsStripped;
|
---|
184 | ///
|
---|
185 | /// Set by PeCoffLoaderGetImageInfo() to TRUE if the image is a TE image.
|
---|
186 | /// For a definition of the TE Image format, see the Platform Initialization Pre-EFI
|
---|
187 | /// Initialization Core Interface Specification.
|
---|
188 | ///
|
---|
189 | BOOLEAN IsTeImage;
|
---|
190 | ///
|
---|
191 | /// Set by PeCoffLoaderLoadImage() to the HII resource offset
|
---|
192 | /// if the image contains a custom PE/COFF resource with the type 'HII'.
|
---|
193 | /// Otherwise, the entry remains to be 0.
|
---|
194 | ///
|
---|
195 | PHYSICAL_ADDRESS HiiResourceData;
|
---|
196 | #ifdef VBOX /* Mach-O FAT support. */
|
---|
197 | ///
|
---|
198 | /// Indicates that this is a FAT image.
|
---|
199 | ///
|
---|
200 | BOOLEAN IsFat;
|
---|
201 | ///
|
---|
202 | /// The EFI image offset within the FAT file.
|
---|
203 | ///
|
---|
204 | UINT32 FatOffset;
|
---|
205 | #endif
|
---|
206 | ///
|
---|
207 | /// Private storage for implementation specific data.
|
---|
208 | ///
|
---|
209 | UINT64 Context;
|
---|
210 | } PE_COFF_LOADER_IMAGE_CONTEXT;
|
---|
211 |
|
---|
212 | /**
|
---|
213 | Retrieves information about a PE/COFF image.
|
---|
214 |
|
---|
215 | Computes the PeCoffHeaderOffset, IsTeImage, ImageType, ImageAddress, ImageSize,
|
---|
216 | DestinationAddress, RelocationsStripped, SectionAlignment, SizeOfHeaders, and
|
---|
217 | DebugDirectoryEntryRva fields of the ImageContext structure.
|
---|
218 | If ImageContext is NULL, then return RETURN_INVALID_PARAMETER.
|
---|
219 | If the PE/COFF image accessed through the ImageRead service in the ImageContext
|
---|
220 | structure is not a supported PE/COFF image type, then return RETURN_UNSUPPORTED.
|
---|
221 | If any errors occur while computing the fields of ImageContext,
|
---|
222 | then the error status is returned in the ImageError field of ImageContext.
|
---|
223 | If the image is a TE image, then SectionAlignment is set to 0.
|
---|
224 | The ImageRead and Handle fields of ImageContext structure must be valid prior
|
---|
225 | to invoking this service.
|
---|
226 |
|
---|
227 | @param ImageContext The pointer to the image context structure that
|
---|
228 | describes the PE/COFF image that needs to be
|
---|
229 | examined by this function.
|
---|
230 |
|
---|
231 | @retval RETURN_SUCCESS The information on the PE/COFF image was collected.
|
---|
232 | @retval RETURN_INVALID_PARAMETER ImageContext is NULL.
|
---|
233 | @retval RETURN_UNSUPPORTED The PE/COFF image is not supported.
|
---|
234 |
|
---|
235 | **/
|
---|
236 | RETURN_STATUS
|
---|
237 | EFIAPI
|
---|
238 | PeCoffLoaderGetImageInfo (
|
---|
239 | IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
|
---|
240 | );
|
---|
241 |
|
---|
242 | /**
|
---|
243 | Applies relocation fixups to a PE/COFF image that was loaded with PeCoffLoaderLoadImage().
|
---|
244 |
|
---|
245 | If the DestinationAddress field of ImageContext is 0, then use the ImageAddress field of
|
---|
246 | ImageContext as the relocation base address. Otherwise, use the DestinationAddress field
|
---|
247 | of ImageContext as the relocation base address. The caller must allocate the relocation
|
---|
248 | fixup log buffer and fill in the FixupData field of ImageContext prior to calling this function.
|
---|
249 |
|
---|
250 | The ImageRead, Handle, PeCoffHeaderOffset, IsTeImage, Machine, ImageType, ImageAddress,
|
---|
251 | ImageSize, DestinationAddress, RelocationsStripped, SectionAlignment, SizeOfHeaders,
|
---|
252 | DebugDirectoryEntryRva, EntryPoint, FixupDataSize, CodeView, PdbPointer, and FixupData of
|
---|
253 | the ImageContext structure must be valid prior to invoking this service.
|
---|
254 |
|
---|
255 | If ImageContext is NULL, then ASSERT().
|
---|
256 |
|
---|
257 | Note that if the platform does not maintain coherency between the instruction cache(s) and the data
|
---|
258 | cache(s) in hardware, then the caller is responsible for performing cache maintenance operations
|
---|
259 | prior to transferring control to a PE/COFF image that is loaded using this library.
|
---|
260 |
|
---|
261 | @param ImageContext The pointer to the image context structure that describes the PE/COFF
|
---|
262 | image that is being relocated.
|
---|
263 |
|
---|
264 | @retval RETURN_SUCCESS The PE/COFF image was relocated.
|
---|
265 | Extended status information is in the ImageError field of ImageContext.
|
---|
266 | @retval RETURN_LOAD_ERROR The image in not a valid PE/COFF image.
|
---|
267 | Extended status information is in the ImageError field of ImageContext.
|
---|
268 | @retval RETURN_UNSUPPORTED A relocation record type is not supported.
|
---|
269 | Extended status information is in the ImageError field of ImageContext.
|
---|
270 |
|
---|
271 | **/
|
---|
272 | RETURN_STATUS
|
---|
273 | EFIAPI
|
---|
274 | PeCoffLoaderRelocateImage (
|
---|
275 | IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
|
---|
276 | );
|
---|
277 |
|
---|
278 | /**
|
---|
279 | Loads a PE/COFF image into memory.
|
---|
280 |
|
---|
281 | Loads the PE/COFF image accessed through the ImageRead service of ImageContext into the buffer
|
---|
282 | specified by the ImageAddress and ImageSize fields of ImageContext. The caller must allocate
|
---|
283 | the load buffer and fill in the ImageAddress and ImageSize fields prior to calling this function.
|
---|
284 | The EntryPoint, FixupDataSize, CodeView, PdbPointer and HiiResourceData fields of ImageContext are computed.
|
---|
285 | The ImageRead, Handle, PeCoffHeaderOffset, IsTeImage, Machine, ImageType, ImageAddress, ImageSize,
|
---|
286 | DestinationAddress, RelocationsStripped, SectionAlignment, SizeOfHeaders, and DebugDirectoryEntryRva
|
---|
287 | fields of the ImageContext structure must be valid prior to invoking this service.
|
---|
288 |
|
---|
289 | If ImageContext is NULL, then ASSERT().
|
---|
290 |
|
---|
291 | Note that if the platform does not maintain coherency between the instruction cache(s) and the data
|
---|
292 | cache(s) in hardware, then the caller is responsible for performing cache maintenance operations
|
---|
293 | prior to transferring control to a PE/COFF image that is loaded using this library.
|
---|
294 |
|
---|
295 | @param ImageContext The pointer to the image context structure that describes the PE/COFF
|
---|
296 | image that is being loaded.
|
---|
297 |
|
---|
298 | @retval RETURN_SUCCESS The PE/COFF image was loaded into the buffer specified by
|
---|
299 | the ImageAddress and ImageSize fields of ImageContext.
|
---|
300 | Extended status information is in the ImageError field of ImageContext.
|
---|
301 | @retval RETURN_BUFFER_TOO_SMALL The caller did not provide a large enough buffer.
|
---|
302 | Extended status information is in the ImageError field of ImageContext.
|
---|
303 | @retval RETURN_LOAD_ERROR The PE/COFF image is an EFI Runtime image with no relocations.
|
---|
304 | Extended status information is in the ImageError field of ImageContext.
|
---|
305 | @retval RETURN_INVALID_PARAMETER The image address is invalid.
|
---|
306 | Extended status information is in the ImageError field of ImageContext.
|
---|
307 |
|
---|
308 | **/
|
---|
309 | RETURN_STATUS
|
---|
310 | EFIAPI
|
---|
311 | PeCoffLoaderLoadImage (
|
---|
312 | IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
|
---|
313 | );
|
---|
314 |
|
---|
315 |
|
---|
316 | /**
|
---|
317 | Reads contents of a PE/COFF image from a buffer in system memory.
|
---|
318 |
|
---|
319 | This is the default implementation of a PE_COFF_LOADER_READ_FILE function
|
---|
320 | that assumes FileHandle pointer to the beginning of a PE/COFF image.
|
---|
321 | This function reads contents of the PE/COFF image that starts at the system memory
|
---|
322 | address specified by FileHandle. The read operation copies ReadSize bytes from the
|
---|
323 | PE/COFF image starting at byte offset FileOffset into the buffer specified by Buffer.
|
---|
324 | The size of the buffer actually read is returned in ReadSize.
|
---|
325 |
|
---|
326 | If FileHandle is NULL, then ASSERT().
|
---|
327 | If ReadSize is NULL, then ASSERT().
|
---|
328 | If Buffer is NULL, then ASSERT().
|
---|
329 |
|
---|
330 | @param FileHandle The pointer to base of the input stream
|
---|
331 | @param FileOffset Offset into the PE/COFF image to begin the read operation.
|
---|
332 | @param ReadSize On input, the size in bytes of the requested read operation.
|
---|
333 | On output, the number of bytes actually read.
|
---|
334 | @param Buffer Output buffer that contains the data read from the PE/COFF image.
|
---|
335 |
|
---|
336 | @retval RETURN_SUCCESS The data is read from FileOffset from the Handle into
|
---|
337 | the buffer.
|
---|
338 | **/
|
---|
339 | RETURN_STATUS
|
---|
340 | EFIAPI
|
---|
341 | PeCoffLoaderImageReadFromMemory (
|
---|
342 | IN VOID *FileHandle,
|
---|
343 | IN UINTN FileOffset,
|
---|
344 | IN OUT UINTN *ReadSize,
|
---|
345 | OUT VOID *Buffer
|
---|
346 | );
|
---|
347 |
|
---|
348 |
|
---|
349 | /**
|
---|
350 | Reapply fixups on a fixed up PE32/PE32+ image to allow virutal calling at EFI
|
---|
351 | runtime.
|
---|
352 |
|
---|
353 | This function reapplies relocation fixups to the PE/COFF image specified by ImageBase
|
---|
354 | and ImageSize so the image will execute correctly when the PE/COFF image is mapped
|
---|
355 | to the address specified by VirtualImageBase. RelocationData must be identical
|
---|
356 | to the FiuxupData buffer from the PE_COFF_LOADER_IMAGE_CONTEXT structure
|
---|
357 | after this PE/COFF image was relocated with PeCoffLoaderRelocateImage().
|
---|
358 |
|
---|
359 | Note that if the platform does not maintain coherency between the instruction cache(s) and the data
|
---|
360 | cache(s) in hardware, then the caller is responsible for performing cache maintenance operations
|
---|
361 | prior to transferring control to a PE/COFF image that is loaded using this library.
|
---|
362 |
|
---|
363 | @param ImageBase The base address of a PE/COFF image that has been loaded
|
---|
364 | and relocated into system memory.
|
---|
365 | @param VirtImageBase The request virtual address that the PE/COFF image is to
|
---|
366 | be fixed up for.
|
---|
367 | @param ImageSize The size, in bytes, of the PE/COFF image.
|
---|
368 | @param RelocationData A pointer to the relocation data that was collected when the PE/COFF
|
---|
369 | image was relocated using PeCoffLoaderRelocateImage().
|
---|
370 |
|
---|
371 | **/
|
---|
372 | VOID
|
---|
373 | EFIAPI
|
---|
374 | PeCoffLoaderRelocateImageForRuntime (
|
---|
375 | IN PHYSICAL_ADDRESS ImageBase,
|
---|
376 | IN PHYSICAL_ADDRESS VirtImageBase,
|
---|
377 | IN UINTN ImageSize,
|
---|
378 | IN VOID *RelocationData
|
---|
379 | );
|
---|
380 |
|
---|
381 | /**
|
---|
382 | Unloads a loaded PE/COFF image from memory and releases its taken resource.
|
---|
383 | Releases any environment specific resources that were allocated when the image
|
---|
384 | specified by ImageContext was loaded using PeCoffLoaderLoadImage().
|
---|
385 |
|
---|
386 | For NT32 emulator, the PE/COFF image loaded by system needs to release.
|
---|
387 | For real platform, the PE/COFF image loaded by Core doesn't needs to be unloaded,
|
---|
388 | this function can simply return RETURN_SUCCESS.
|
---|
389 |
|
---|
390 | If ImageContext is NULL, then ASSERT().
|
---|
391 |
|
---|
392 | @param ImageContext Pointer to the image context structure that describes the PE/COFF
|
---|
393 | image to be unloaded.
|
---|
394 |
|
---|
395 | @retval RETURN_SUCCESS The PE/COFF image was unloaded successfully.
|
---|
396 | **/
|
---|
397 | RETURN_STATUS
|
---|
398 | EFIAPI
|
---|
399 | PeCoffLoaderUnloadImage (
|
---|
400 | IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
|
---|
401 | );
|
---|
402 | #endif
|
---|