mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-12-02 13:03:28 +01:00
591 lines
19 KiB
C
591 lines
19 KiB
C
/** @file
|
|
Provides APIs to inspect, load, and relocate PE/COFF Images.
|
|
|
|
No implementation of this library may use global variable pointers, as this
|
|
may cause the emission of Image relocations for this address. This is
|
|
incompatible with the concept of Image self-relocation, where the Image is
|
|
loaded in a similar fashion to XIP Images into the memory at an address
|
|
unknown at compile-time. As such, Image relocation must be safe to perform
|
|
without any Image relocations applied earlier.
|
|
|
|
Copyright (c) 2020 - 2021, Marvin Häuser. All rights reserved.<BR>
|
|
Copyright (c) 2020, Vitaly Cheptsov. All rights reserved.<BR>
|
|
Copyright (c) 2020, ISP RAS. All rights reserved.<BR>
|
|
|
|
SPDX-License-Identifier: BSD-3-Clause
|
|
**/
|
|
|
|
#ifndef PE_COFF_LIB2_H_
|
|
#define PE_COFF_LIB2_H_
|
|
|
|
#include <IndustryStandard/PeImage2.h>
|
|
|
|
#include <Guid/WinCertificate.h>
|
|
|
|
typedef enum {
|
|
UefiImageOriginFv = 0,
|
|
UefiImageOriginOptionROM = 1,
|
|
UefiImageOriginUserImage = 2,
|
|
UefiImageOriginMax
|
|
} UEFI_IMAGE_ORIGIN;
|
|
///
|
|
/// If set, less than 4KB aligned image from firmware volume prevents boot.
|
|
///
|
|
#define PCD_IMAGE_PROTECTION_POLICY_FV_STOP_BOOT BIT31
|
|
|
|
// FIXME: Where to put this?
|
|
//
|
|
// PcdImageLoaderAlignmentPolicy bits.
|
|
//
|
|
|
|
///
|
|
/// If set, unaligned Image sections are permitted.
|
|
///
|
|
#define PCD_ALIGNMENT_POLICY_CONTIGUOUS_SECTIONS BIT0
|
|
///
|
|
/// If set, unaligned Image Relocation Block sizes are permitted.
|
|
///
|
|
#define PCD_ALIGNMENT_POLICY_RELOCATION_BLOCK_SIZES BIT1
|
|
///
|
|
/// If set, unaligned Image certificate sizes are permitted.
|
|
///
|
|
#define PCD_ALIGNMENT_POLICY_CERTIFICATE_SIZES BIT2
|
|
|
|
// FIXME: Rework docs to consider Inplace dependencies
|
|
|
|
/**
|
|
Returns whether the Image targets the UEFI Subsystem.
|
|
|
|
@param[in] Subsystem The Subsystem value from the Image Headers.
|
|
**/
|
|
#define IMAGE_IS_EFI_SUBYSYSTEM(Subsystem) \
|
|
((Subsystem) >= EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION && \
|
|
(Subsystem) <= EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER)
|
|
|
|
///
|
|
/// Image type enumeration for Image format identification from the context.
|
|
///
|
|
typedef enum {
|
|
PeCoffLoaderTypePe32,
|
|
PeCoffLoaderTypePe32Plus,
|
|
PeCoffLoaderTypeMax
|
|
} PE_COFF_LOADER_IMAGE_TYPE;
|
|
|
|
///
|
|
/// Image context structure used for abstraction and bookkeeping.
|
|
/// This structure is publicly exposed for memory allocation reasons and must
|
|
/// not be accessed directly outside of the library implementation.
|
|
///
|
|
typedef struct {
|
|
///
|
|
/// The preferred load address of the Image.
|
|
///
|
|
UINT64 ImageBase;
|
|
///
|
|
/// A pointer to the Image raw file buffer.
|
|
///
|
|
CONST VOID *FileBuffer;
|
|
///
|
|
/// The size, in Bytes, of FileBuffer.
|
|
///
|
|
UINT32 FileSize;
|
|
///
|
|
/// A pointer to the loaded Image destination.
|
|
///
|
|
VOID *ImageBuffer;
|
|
///
|
|
/// The offset of the Section Headers from the beginning of the raw file.
|
|
///
|
|
UINT32 SectionsOffset;
|
|
///
|
|
/// The number of Sections in the Image.
|
|
///
|
|
UINT16 NumberOfSections;
|
|
///
|
|
/// The size, in Bytes, required to load the Image.
|
|
///
|
|
UINT32 SizeOfImage;
|
|
///
|
|
/// The alignment, in Bytes, of Image Sections virtual addresses.
|
|
///
|
|
UINT32 SectionAlignment;
|
|
///
|
|
/// The offset of the Image Header from the beginning of the raw file.
|
|
///
|
|
UINT32 ExeHdrOffset;
|
|
///
|
|
/// The combined size, in Bytes, of all Image Headers.
|
|
///
|
|
UINT32 SizeOfHeaders;
|
|
///
|
|
/// The RVA of the Image entry point.
|
|
///
|
|
UINT32 AddressOfEntryPoint;
|
|
///
|
|
/// Indicates whether relocation information has been stripped from the Image.
|
|
///
|
|
BOOLEAN RelocsStripped;
|
|
///
|
|
/// The file format of the Image raw file, refer to PE_COFF_LOADER_IMAGE_TYPE.
|
|
///
|
|
UINT8 ImageType;
|
|
///
|
|
/// The Subsystem value from the Image Header.
|
|
///
|
|
UINT16 Subsystem;
|
|
///
|
|
/// The Machine value from the Image Header.
|
|
///
|
|
UINT16 Machine;
|
|
///
|
|
/// The RVA of the Relocation Directory.
|
|
///
|
|
UINT32 RelocDirRva;
|
|
///
|
|
/// The size, in Bytes, of the Relocation Directory.
|
|
///
|
|
UINT32 RelocDirSize;
|
|
///
|
|
/// The RVA of the Security Directory.
|
|
///
|
|
UINT32 SecDirOffset;
|
|
///
|
|
/// The size, in Bytes, of the Security Directory.
|
|
///
|
|
UINT32 SecDirSize;
|
|
} PE_COFF_LOADER_IMAGE_CONTEXT;
|
|
|
|
///
|
|
/// Image runtime context used to relocate the Image during runtime.
|
|
///
|
|
typedef struct PE_COFF_LOADER_RUNTIME_CONTEXT_ PE_COFF_LOADER_RUNTIME_CONTEXT;
|
|
|
|
/**
|
|
Adds the digest of Data to HashContext. This function can be called multiple
|
|
times to compute the digest of discontinuous data.
|
|
|
|
@param[in,out] HashContext The context of the current hash.
|
|
@param[in] Data The data to be hashed.
|
|
@param[in] DataSize The size, in Bytes, of Data.
|
|
|
|
@returns Whether hashing has been successful.
|
|
**/
|
|
typedef
|
|
BOOLEAN
|
|
(EFIAPI *PE_COFF_LOADER_HASH_UPDATE)(
|
|
IN OUT VOID *HashContext,
|
|
IN CONST VOID *Data,
|
|
IN UINTN DataSize
|
|
);
|
|
|
|
/**
|
|
Verify the TE, PE32, or PE32+ Image and initialise Context.
|
|
|
|
Used offsets and ranges must be aligned and in the bounds of the raw file.
|
|
Image Section Headers and basic Relocation information must be well-formed.
|
|
|
|
FileBuffer must remain valid for the entire lifetime of Context.
|
|
|
|
@param[out] Context The context describing the Image.
|
|
@param[in] FileBuffer The file data to parse as PE Image.
|
|
@param[in] FileSize The size, in Bytes, of FileBuffer.
|
|
|
|
@retval RETURN_SUCCESS The Image context has been initialised successfully.
|
|
@retval other The file data is malformed.
|
|
**/
|
|
RETURN_STATUS
|
|
PeCoffInitializeContext (
|
|
OUT PE_COFF_LOADER_IMAGE_CONTEXT *Context,
|
|
IN CONST VOID *FileBuffer,
|
|
IN UINT32 FileSize,
|
|
IN UINT8 ImageOrigin
|
|
);
|
|
|
|
/**
|
|
Hashes the Image using the Authenticode (PE/COFF Specification 8.1 Appendix A)
|
|
algorithm.
|
|
|
|
@param[in,out] Context The context describing the Image. Must have been
|
|
initialised by PeCoffInitializeContext().
|
|
@param[in,out] HashContext The context of the current hash. Must have been
|
|
initialised for usage with the HashUpdate
|
|
function.
|
|
@param[in] HashUpdate The data hashing function.
|
|
|
|
@returns Whether hashing has been successful.
|
|
**/
|
|
BOOLEAN
|
|
PeCoffHashImageAuthenticode (
|
|
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *Context,
|
|
IN OUT VOID *HashContext,
|
|
IN PE_COFF_LOADER_HASH_UPDATE HashUpdate
|
|
);
|
|
|
|
/**
|
|
Load the Image into the destination memory space.
|
|
|
|
@param[in,out] Context The context describing the Image. Must have
|
|
been initialised by PeCoffInitializeContext().
|
|
@param[out] Destination The Image destination memory. Must be
|
|
allocated from page memory.
|
|
@param[in] DestinationSize The size, in Bytes, of Destination. Must be
|
|
sufficent to load the Image with regards to
|
|
its Image section alignment.
|
|
|
|
@retval RETURN_SUCCESS The Image was loaded successfully.
|
|
@retval other The Image could not be loaded successfully.
|
|
**/
|
|
RETURN_STATUS
|
|
PeCoffLoadImage (
|
|
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *Context,
|
|
OUT VOID *Destination,
|
|
IN UINT32 DestinationSize
|
|
);
|
|
|
|
// FIXME: Docs
|
|
BOOLEAN
|
|
PeCoffImageIsInplace (
|
|
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *Context
|
|
);
|
|
|
|
/**
|
|
Equivalent to the PeCoffLoadImage() function for inplace-loading. Ensures that
|
|
all important raw file offsets match the respective RVAs.
|
|
|
|
@param[in,out] Context The context describing the Image. Must have been
|
|
initialised by PeCoffInitializeContext().
|
|
|
|
@retval RETURN_SUCCESS The Image has been inplace-loaded successfully.
|
|
@retval other The Image is not suitable for inplace-loading.
|
|
**/
|
|
RETURN_STATUS
|
|
PeCoffLoadImageInplace (
|
|
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *Context
|
|
);
|
|
|
|
// FIXME: Docs
|
|
RETURN_STATUS
|
|
PeCoffRelocateImageInplace (
|
|
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *Context
|
|
);
|
|
|
|
/**
|
|
Retrieves the size required to bookkeep Image runtime relocation information.
|
|
|
|
May only be called when PeCoffGetRelocsStripped() returns FALSE.
|
|
|
|
@param[in,out] Context The context describing the Image. Must have been
|
|
loaded by PeCoffLoadImage().
|
|
@param[out] Size On output, the size, in Bytes, required for the
|
|
bookkeeping buffer.
|
|
|
|
@retval RETURN_SUCCESS The Image runtime context size for the Image was
|
|
retrieved successfully.
|
|
@retval other The Image runtime context size for the Image could not
|
|
be retrieved successfully.
|
|
**/
|
|
RETURN_STATUS
|
|
PeCoffLoaderGetRuntimeContextSize (
|
|
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *Context,
|
|
OUT UINT32 *Size
|
|
);
|
|
|
|
/**
|
|
Relocate the Image for boot-time usage.
|
|
|
|
May only be called when PeCoffGetRelocsStripped() returns FALSE, or with
|
|
BaseAddress == PeCoffGetImageBase().
|
|
|
|
@param[in,out] Context The context describing the Image. Must have
|
|
been loaded by PeCoffLoadImage().
|
|
@param[in] BaseAddress The address to relocate the Image to.
|
|
@param[out] RuntimeContext If not NULL, on output, a bookkeeping data
|
|
required for Image runtime relocation.
|
|
@param[in] RuntimeContextSize The size, in Bytes, of RuntimeContext. Must
|
|
be at least as big as the size returned by
|
|
PeCoffLoaderGetRuntimeContextSize().
|
|
|
|
@retval RETURN_SUCCESS The Image has been relocated successfully.
|
|
@retval other The Image Relocation Directory is malformed.
|
|
**/
|
|
RETURN_STATUS
|
|
PeCoffRelocateImage (
|
|
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *Context,
|
|
IN UINT64 BaseAddress,
|
|
OUT PE_COFF_LOADER_RUNTIME_CONTEXT *RuntimeContext OPTIONAL,
|
|
IN UINT32 RuntimeContextSize
|
|
);
|
|
|
|
/**
|
|
Relocate Image for Runtime usage.
|
|
|
|
May only be called when PeCoffGetRelocsStripped() returns FALSE, or with
|
|
BaseAddress == PeCoffGetImageBase().
|
|
|
|
@param[in,out] Image The Image destination memory. Must have been
|
|
relocated by PeCoffRelocateImage().
|
|
@param[in] ImageSize The size, in Bytes, of Image.
|
|
@param[in] BaseAddress The address to relocate the Image to.
|
|
@param[in] RuntimeContext The Relocation context obtained by
|
|
PeCoffRelocateImage().
|
|
|
|
@retval RETURN_SUCCESS The Image has been relocated successfully.
|
|
@retval other The Image could not be relocated successfully.
|
|
**/
|
|
RETURN_STATUS
|
|
PeCoffRuntimeRelocateImage (
|
|
IN OUT VOID *Image,
|
|
IN UINT32 ImageSize,
|
|
IN UINT64 BaseAddress,
|
|
IN CONST PE_COFF_LOADER_RUNTIME_CONTEXT *RuntimeContext
|
|
);
|
|
|
|
/**
|
|
Discards optional Image Sections to disguise sensitive data.
|
|
|
|
This may destruct the Image Relocation Directory and as such, no function that
|
|
performs Image relocation may be called after this function has been invoked.
|
|
|
|
@param[in,out] Context The context describing the Image. Must have been
|
|
loaded by PeCoffLoadImage().
|
|
**/
|
|
VOID
|
|
PeCoffDiscardSections (
|
|
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *Context
|
|
);
|
|
|
|
/**
|
|
Retrieves the Image PDB path.
|
|
|
|
@param[in,out] Context The context describing the Image. Must have been
|
|
initialised by PeCoffInitializeContext().
|
|
@param[out] PdbPath On output, a pointer to the Image PDB path.
|
|
@param[out] PdbPathSize On output, the size, in Bytes, of *PdbPath.
|
|
|
|
@retval RETURN_SUCCESS The Image PDB path was retrieved successfully.
|
|
@retval other The Image PDB path could not be retrieved
|
|
successfully.
|
|
**/
|
|
RETURN_STATUS
|
|
PeCoffGetPdbPath (
|
|
IN CONST PE_COFF_LOADER_IMAGE_CONTEXT *Context,
|
|
OUT CONST CHAR8 **PdbPath,
|
|
OUT UINT32 *PdbPathSize
|
|
);
|
|
|
|
/**
|
|
Retrieves the first certificate from the Image Certificate Directory.
|
|
|
|
@param[in,out] Context The context describing the Image. Must have been
|
|
initialised by PeCoffInitializeContext().
|
|
@param[out] Certificate On output, the first certificate of the Image.
|
|
|
|
@retval RETURN_SUCCESS The certificate has been retrieved successfully.
|
|
@retval RETURN_NOT_FOUND There is no such certificate.
|
|
@retval other The Image Certificate Directory is malformed.
|
|
**/
|
|
RETURN_STATUS
|
|
PeCoffGetFirstCertificate (
|
|
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *Context,
|
|
OUT CONST WIN_CERTIFICATE **Certificate
|
|
);
|
|
|
|
/**
|
|
Retrieves the next certificate from the Image Certificate Directory.
|
|
|
|
@param[in,out] Context The context describing the Image. Must have been
|
|
initialised by PeCoffInitializeContext().
|
|
@param[out] Certificate On input, the current certificate of the Image.
|
|
Must have been retrieved by
|
|
PeCoffGetFirstCertificate().
|
|
On output, the next certificate of the Image.
|
|
|
|
@retval RETURN_SUCCESS The certificate has been retrieved successfully.
|
|
@retval RETURN_NOT_FOUND There is no such certificate.
|
|
@retval other The Image Certificate Directory is malformed.
|
|
**/
|
|
RETURN_STATUS
|
|
PeCoffGetNextCertificate (
|
|
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *Context,
|
|
IN OUT CONST WIN_CERTIFICATE **Certificate
|
|
);
|
|
|
|
/**
|
|
Retrieves the Image Section Table.
|
|
|
|
@param[in,out] Context The context describing the Image. Must have been
|
|
initialised by PeCoffInitializeContext().
|
|
@param[out] Sections On output, points to the Image Section Table.
|
|
|
|
@returns The number of sections in the Image Section Table.
|
|
**/
|
|
UINT16
|
|
PeCoffGetSectionTable (
|
|
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *Context,
|
|
OUT CONST EFI_IMAGE_SECTION_HEADER **Sections
|
|
);
|
|
|
|
/**
|
|
Retrieves the Image HII data RVA.
|
|
|
|
@param[in,out] Context The context describing the Image. Must have been
|
|
initialised by PeCoffInitializeContext().
|
|
@param[out] HiiRva On output, the RVA of the HII resource data.
|
|
@param[out] HiiSize On output, the size, in Bytes, of HiiRva.
|
|
|
|
@retval RETURN_SUCCESS The Image HII data has been retrieved successfully.
|
|
@retval RETURN_NOT_FOUND The Image HII data could not be found.
|
|
@retval other The Image Resource Directory is malformed.
|
|
**/
|
|
RETURN_STATUS
|
|
PeCoffGetHiiDataRva (
|
|
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *Context,
|
|
OUT UINT32 *HiiRva,
|
|
OUT UINT32 *HiiSize
|
|
);
|
|
|
|
/**
|
|
Retrieve the Image entry point RVA.
|
|
|
|
@param[in,out] Context The context describing the Image. Must have been
|
|
initialised by PeCoffInitializeContext().
|
|
|
|
@returns The Image entry point RVA.
|
|
**/
|
|
UINT32
|
|
PeCoffGetAddressOfEntryPoint (
|
|
IN CONST PE_COFF_LOADER_IMAGE_CONTEXT *Context
|
|
);
|
|
|
|
/**
|
|
Retrieves the Image machine type.
|
|
|
|
@param[in,out] Context The context describing the Image. Must have been
|
|
initialised by PeCoffInitializeContext().
|
|
|
|
@returns The Image machine type.
|
|
**/
|
|
UINT16
|
|
PeCoffGetMachine (
|
|
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *Context
|
|
);
|
|
|
|
/**
|
|
Retrieves the Image subsystem type.
|
|
|
|
@param[in,out] Context The context describing the Image. Must have been
|
|
initialised by PeCoffInitializeContext().
|
|
|
|
@returns The Image subsystem type.
|
|
**/
|
|
UINT16
|
|
PeCoffGetSubsystem (
|
|
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *Context
|
|
);
|
|
|
|
/**
|
|
Retrieves the Image section alignment.
|
|
|
|
@param[in,out] Context The context describing the Image. Must have been
|
|
initialised by PeCoffInitializeContext().
|
|
|
|
@returns The Image section alignment.
|
|
**/
|
|
UINT32
|
|
PeCoffGetSectionAlignment (
|
|
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *Context
|
|
);
|
|
|
|
/**
|
|
Retrieves the size, in Bytes, of the Image memory space.
|
|
|
|
@param[in,out] Context The context describing the Image. Must have been
|
|
initialised by PeCoffInitializeContext().
|
|
|
|
@returns The size of the Image memory space.
|
|
**/
|
|
UINT32
|
|
PeCoffGetSizeOfImage (
|
|
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *Context
|
|
);
|
|
|
|
/**
|
|
Retrieves the Image preferred load address.
|
|
|
|
@param[in,out] Context The context describing the Image. Must have been
|
|
initialised by PeCoffInitializeContext().
|
|
|
|
@returns The Image preferred load address.
|
|
**/
|
|
UINT64
|
|
PeCoffGetImageBase (
|
|
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *Context
|
|
);
|
|
|
|
/**
|
|
Retrieves the size, in Bytes, of the Image Headers.
|
|
|
|
@param[in,out] Context The context describing the Image. Must have been
|
|
initialised by PeCoffInitializeContext().
|
|
|
|
@returns The size of the Image Headers.
|
|
**/
|
|
UINT32
|
|
PeCoffGetSizeOfHeaders (
|
|
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *Context
|
|
);
|
|
|
|
/**
|
|
Returns whether the Image relocations have been stripped.
|
|
|
|
@param[in,out] Context The context describing the Image. Must have been
|
|
initialised by PeCoffInitializeContext().
|
|
|
|
@returns Whether the Image relocations have been stripped.
|
|
**/
|
|
BOOLEAN
|
|
PeCoffGetRelocsStripped (
|
|
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *Context
|
|
);
|
|
|
|
/**
|
|
Retrieves the Image load address PeCoffLoadImage() has loaded the Image to.
|
|
|
|
May be called only after PeCoffLoadImage() has succeeded.
|
|
|
|
@param[in,out] Context The context describing the Image. Must have been
|
|
initialised by PeCoffInitializeContext().
|
|
|
|
@returns The Image load address.
|
|
**/
|
|
UINTN
|
|
PeCoffLoaderGetImageAddress (
|
|
IN CONST PE_COFF_LOADER_IMAGE_CONTEXT *Context
|
|
);
|
|
|
|
/**
|
|
Retrieve the immediate data encoded in an ARM MOVW/MOVT instruciton pair.
|
|
|
|
@param[in] Instructions Pointer to an ARM MOVW/MOVT insturction pair.
|
|
|
|
@returns The Immediate address encoded in the instructions.
|
|
**/
|
|
UINT32
|
|
PeCoffThumbMovwMovtImmediateAddress (
|
|
IN CONST VOID *Instructions
|
|
);
|
|
|
|
/**
|
|
Relocate an ARM MOVW/MOVT immediate instruction instruction pair.
|
|
|
|
@param[in,out] Instructions Pointer to ARM MOVW/MOVT instruction pair.
|
|
@param[in] Adjust The delta to add to the addresses.
|
|
**/
|
|
VOID
|
|
PeCoffThumbMovwMovtImmediateFixup (
|
|
IN OUT VOID *Instructions,
|
|
IN UINT64 Adjust
|
|
);
|
|
|
|
#endif // PE_COFF_LIB2_H_
|