OpenCore: Use direct PE loading for Secure Boot (#108)

Implement and integrate a PE image loader to circumvent UEFI Secure Boot when Apple Secure Boot is used.
This commit is contained in:
Download-Fritz 2020-08-24 12:52:34 +02:00 committed by GitHub
parent ee7aaa37e1
commit a97b74e83c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 3039 additions and 49 deletions

1
.gitignore vendored
View File

@ -24,6 +24,7 @@ Utilities/TestKextInject/Result.xml
Utilities/TestMacho/Macho
Utilities/TestRsaPreprocess/RsaPreprocess
Utilities/TestSmbios/Smbios
Utilities/TestPeCoff/PeCoff
*.o
*.exe
DICT

View File

@ -0,0 +1,722 @@
/** @file
EFI image format for PE32, PE32+ and TE. Please note some data structures are
different for PE32 and PE32+. EFI_IMAGE_NT_HEADERS32 is for PE32 and
EFI_IMAGE_NT_HEADERS64 is for PE32+.
This file is coded to the Visual Studio, Microsoft Portable Executable and
Common Object File Format Specification, Revision 8.3 - February 6, 2013.
This file also includes some definitions in PI Specification, Revision 1.0.
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
Portions Copyright (c) 2016 - 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef OC_PE_IMAGE_H
#define OC_PE_IMAGE_H
//
// PE32+ Subsystem type for EFI images
//
#define EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION 10
#define EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11
#define EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12
#define EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER 13 ///< defined PI Specification, 1.0
//
// PE32+ Machine type for EFI images
//
#define IMAGE_FILE_MACHINE_I386 0x014c
#define IMAGE_FILE_MACHINE_IA64 0x0200
#define IMAGE_FILE_MACHINE_EBC 0x0EBC
#define IMAGE_FILE_MACHINE_X64 0x8664
#define IMAGE_FILE_MACHINE_ARMTHUMB_MIXED 0x01c2
#define IMAGE_FILE_MACHINE_ARM64 0xAA64
//
// EXE file formats
//
#define EFI_IMAGE_DOS_SIGNATURE SIGNATURE_16('M', 'Z')
#define EFI_IMAGE_OS2_SIGNATURE SIGNATURE_16('N', 'E')
#define EFI_IMAGE_OS2_SIGNATURE_LE SIGNATURE_16('L', 'E')
#define EFI_IMAGE_NT_SIGNATURE SIGNATURE_32('P', 'E', '\0', '\0')
///
/// PE images can start with an optional DOS header, so if an image is run
/// under DOS it can print an error message.
///
typedef struct {
UINT16 e_magic; ///< Magic number.
UINT16 e_cblp; ///< Bytes on last page of file.
UINT16 e_cp; ///< Pages in file.
UINT16 e_crlc; ///< Relocations.
UINT16 e_cparhdr; ///< Size of header in paragraphs.
UINT16 e_minalloc; ///< Minimum extra paragraphs needed.
UINT16 e_maxalloc; ///< Maximum extra paragraphs needed.
UINT16 e_ss; ///< Initial (relative) SS value.
UINT16 e_sp; ///< Initial SP value.
UINT16 e_csum; ///< Checksum.
UINT16 e_ip; ///< Initial IP value.
UINT16 e_cs; ///< Initial (relative) CS value.
UINT16 e_lfarlc; ///< File address of relocation table.
UINT16 e_ovno; ///< Overlay number.
UINT16 e_res[4]; ///< Reserved words.
UINT16 e_oemid; ///< OEM identifier (for e_oeminfo).
UINT16 e_oeminfo; ///< OEM information; e_oemid specific.
UINT16 e_res2[10]; ///< Reserved words.
UINT32 e_lfanew; ///< File address of new exe header.
} EFI_IMAGE_DOS_HEADER;
///
/// COFF File Header (Object and Image).
///
typedef struct {
UINT16 Machine;
UINT16 NumberOfSections;
UINT32 TimeDateStamp;
UINT32 PointerToSymbolTable;
UINT32 NumberOfSymbols;
UINT16 SizeOfOptionalHeader;
UINT16 Characteristics;
} EFI_IMAGE_FILE_HEADER;
///
/// Size of EFI_IMAGE_FILE_HEADER.
///
#define EFI_IMAGE_SIZEOF_FILE_HEADER 20
//
// Characteristics
//
#define EFI_IMAGE_FILE_RELOCS_STRIPPED 1 ///< 0x0001 Relocation info stripped from file.
///
/// Header Data Directories.
///
typedef struct {
UINT32 VirtualAddress;
UINT32 Size;
} EFI_IMAGE_DATA_DIRECTORY;
//
// Directory Entries
//
#define EFI_IMAGE_DIRECTORY_ENTRY_EXPORT 0
#define EFI_IMAGE_DIRECTORY_ENTRY_IMPORT 1
#define EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE 2
#define EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION 3
#define EFI_IMAGE_DIRECTORY_ENTRY_SECURITY 4
#define EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC 5
#define EFI_IMAGE_DIRECTORY_ENTRY_DEBUG 6
#define EFI_IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7
#define EFI_IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8
#define EFI_IMAGE_DIRECTORY_ENTRY_TLS 9
#define EFI_IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10
#define EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES 16
///
/// @attention
/// EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC means PE32 and
/// EFI_IMAGE_OPTIONAL_HEADER32 must be used. The data structures only vary
/// after NT additional fields.
///
#define EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b
///
/// @attention
/// EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC means PE32+ and
/// EFI_IMAGE_OPTIONAL_HEADER64 must be used. The data structures only vary
/// after NT additional fields.
///
#define EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
///
/// @attention
/// EFI_IMAGE_NT_HEADERS32 is for use ONLY by tools.
///
typedef struct {
UINT32 Signature;
EFI_IMAGE_FILE_HEADER FileHeader;
} EFI_IMAGE_NT_HEADERS_COMMON_HDR;
STATIC_ASSERT (
sizeof (EFI_IMAGE_NT_HEADERS_COMMON_HDR) == sizeof (UINT32) + sizeof (EFI_IMAGE_FILE_HEADER),
"Unsupported padding."
);
///
/// @attention
/// EFI_IMAGE_NT_HEADERS32 is for use ONLY by tools.
///
typedef struct {
EFI_IMAGE_NT_HEADERS_COMMON_HDR CommonHeader;
///
/// Standard fields.
///
UINT16 Magic;
UINT8 MajorLinkerVersion;
UINT8 MinorLinkerVersion;
UINT32 SizeOfCode;
UINT32 SizeOfInitializedData;
UINT32 SizeOfUninitializedData;
UINT32 AddressOfEntryPoint;
UINT32 BaseOfCode;
UINT32 BaseOfData; ///< PE32 contains this additional field, which is absent in PE32+.
///
/// Optional Header Windows-Specific Fields.
///
UINT32 ImageBase;
UINT32 SectionAlignment;
UINT32 FileAlignment;
UINT16 MajorOperatingSystemVersion;
UINT16 MinorOperatingSystemVersion;
UINT16 MajorImageVersion;
UINT16 MinorImageVersion;
UINT16 MajorSubsystemVersion;
UINT16 MinorSubsystemVersion;
UINT32 Win32VersionValue;
UINT32 SizeOfImage;
UINT32 SizeOfHeaders;
UINT32 CheckSum;
UINT16 Subsystem;
UINT16 DllCharacteristics;
UINT32 SizeOfStackReserve;
UINT32 SizeOfStackCommit;
UINT32 SizeOfHeapReserve;
UINT32 SizeOfHeapCommit;
UINT32 LoaderFlags;
UINT32 NumberOfRvaAndSizes;
EFI_IMAGE_DATA_DIRECTORY DataDirectory[];
} EFI_IMAGE_NT_HEADERS32;
///
/// @attention
/// EFI_IMAGE_HEADERS64 is for use ONLY by tools.
///
typedef struct {
EFI_IMAGE_NT_HEADERS_COMMON_HDR CommonHeader;
///
/// Standard fields.
///
UINT16 Magic;
UINT8 MajorLinkerVersion;
UINT8 MinorLinkerVersion;
UINT32 SizeOfCode;
UINT32 SizeOfInitializedData;
UINT32 SizeOfUninitializedData;
UINT32 AddressOfEntryPoint;
UINT32 BaseOfCode;
///
/// Optional Header Windows-Specific Fields.
///
UINT64 ImageBase;
UINT32 SectionAlignment;
UINT32 FileAlignment;
UINT16 MajorOperatingSystemVersion;
UINT16 MinorOperatingSystemVersion;
UINT16 MajorImageVersion;
UINT16 MinorImageVersion;
UINT16 MajorSubsystemVersion;
UINT16 MinorSubsystemVersion;
UINT32 Win32VersionValue;
UINT32 SizeOfImage;
UINT32 SizeOfHeaders;
UINT32 CheckSum;
UINT16 Subsystem;
UINT16 DllCharacteristics;
UINT64 SizeOfStackReserve;
UINT64 SizeOfStackCommit;
UINT64 SizeOfHeapReserve;
UINT64 SizeOfHeapCommit;
UINT32 LoaderFlags;
UINT32 NumberOfRvaAndSizes;
EFI_IMAGE_DATA_DIRECTORY DataDirectory[];
} EFI_IMAGE_NT_HEADERS64;
//
// Other Windows Subsystem Values
//
#define EFI_IMAGE_SUBSYSTEM_UNKNOWN 0
#define EFI_IMAGE_SUBSYSTEM_NATIVE 1
#define EFI_IMAGE_SUBSYSTEM_WINDOWS_GUI 2
#define EFI_IMAGE_SUBSYSTEM_WINDOWS_CUI 3
#define EFI_IMAGE_SUBSYSTEM_OS2_CUI 5
#define EFI_IMAGE_SUBSYSTEM_POSIX_CUI 7
///
/// Length of ShortName.
///
#define EFI_IMAGE_SIZEOF_SHORT_NAME 8
///
/// Section Table. This table immediately follows the optional header.
///
typedef struct {
UINT8 Name[EFI_IMAGE_SIZEOF_SHORT_NAME];
UINT32 VirtualSize;
UINT32 VirtualAddress;
UINT32 SizeOfRawData;
UINT32 PointerToRawData;
UINT32 PointerToRelocations;
UINT32 PointerToLinenumbers;
UINT16 NumberOfRelocations;
UINT16 NumberOfLinenumbers;
UINT32 Characteristics;
} EFI_IMAGE_SECTION_HEADER;
//
// Section Flags Values
//
#define EFI_IMAGE_SCN_TYPE_NO_PAD BIT3 ///< 0x00000008 ///< Reserved.
#define EFI_IMAGE_SCN_CNT_CODE BIT5 ///< 0x00000020
#define EFI_IMAGE_SCN_CNT_INITIALIZED_DATA BIT6 ///< 0x00000040
#define EFI_IMAGE_SCN_CNT_UNINITIALIZED_DATA BIT7 ///< 0x00000080
#define EFI_IMAGE_SCN_LNK_OTHER BIT8 ///< 0x00000100 ///< Reserved.
#define EFI_IMAGE_SCN_LNK_INFO BIT9 ///< 0x00000200 ///< Section contains comments or some other type of information.
#define EFI_IMAGE_SCN_LNK_REMOVE BIT11 ///< 0x00000800 ///< Section contents will not become part of image.
#define EFI_IMAGE_SCN_LNK_COMDAT BIT12 ///< 0x00001000
#define EFI_IMAGE_SCN_ALIGN_1BYTES BIT20 ///< 0x00100000
#define EFI_IMAGE_SCN_ALIGN_2BYTES BIT21 ///< 0x00200000
#define EFI_IMAGE_SCN_ALIGN_4BYTES (BIT20|BIT21) ///< 0x00300000
#define EFI_IMAGE_SCN_ALIGN_8BYTES BIT22 ///< 0x00400000
#define EFI_IMAGE_SCN_ALIGN_16BYTES (BIT20|BIT22) ///< 0x00500000
#define EFI_IMAGE_SCN_ALIGN_32BYTES (BIT21|BIT22) ///< 0x00600000
#define EFI_IMAGE_SCN_ALIGN_64BYTES (BIT20|BIT21|BIT22) ///< 0x00700000
#define EFI_IMAGE_SCN_MEM_DISCARDABLE BIT25 ///< 0x02000000
#define EFI_IMAGE_SCN_MEM_NOT_CACHED BIT26 ///< 0x04000000
#define EFI_IMAGE_SCN_MEM_NOT_PAGED BIT27 ///< 0x08000000
#define EFI_IMAGE_SCN_MEM_SHARED BIT28 ///< 0x10000000
#define EFI_IMAGE_SCN_MEM_EXECUTE BIT29 ///< 0x20000000
#define EFI_IMAGE_SCN_MEM_READ BIT30 ///< 0x40000000
#define EFI_IMAGE_SCN_MEM_WRITE BIT31 ///< 0x80000000
///
/// Size of a Symbol Table Record.
///
#define EFI_IMAGE_SIZEOF_SYMBOL 18
//
// Symbols have a section number of the section in which they are
// defined. Otherwise, section numbers have the following meanings:
//
#define EFI_IMAGE_SYM_UNDEFINED (UINT16) 0 ///< Symbol is undefined or is common.
#define EFI_IMAGE_SYM_ABSOLUTE (UINT16) -1 ///< Symbol is an absolute value.
#define EFI_IMAGE_SYM_DEBUG (UINT16) -2 ///< Symbol is a special debug item.
//
// Symbol Type (fundamental) values.
//
#define EFI_IMAGE_SYM_TYPE_NULL 0 ///< no type.
#define EFI_IMAGE_SYM_TYPE_VOID 1 ///< no valid type.
#define EFI_IMAGE_SYM_TYPE_CHAR 2 ///< type character.
#define EFI_IMAGE_SYM_TYPE_SHORT 3 ///< type short integer.
#define EFI_IMAGE_SYM_TYPE_INT 4
#define EFI_IMAGE_SYM_TYPE_LONG 5
#define EFI_IMAGE_SYM_TYPE_FLOAT 6
#define EFI_IMAGE_SYM_TYPE_DOUBLE 7
#define EFI_IMAGE_SYM_TYPE_STRUCT 8
#define EFI_IMAGE_SYM_TYPE_UNION 9
#define EFI_IMAGE_SYM_TYPE_ENUM 10 ///< enumeration.
#define EFI_IMAGE_SYM_TYPE_MOE 11 ///< member of enumeration.
#define EFI_IMAGE_SYM_TYPE_BYTE 12
#define EFI_IMAGE_SYM_TYPE_WORD 13
#define EFI_IMAGE_SYM_TYPE_UINT 14
#define EFI_IMAGE_SYM_TYPE_DWORD 15
//
// Symbol Type (derived) values.
//
#define EFI_IMAGE_SYM_DTYPE_NULL 0 ///< no derived type.
#define EFI_IMAGE_SYM_DTYPE_POINTER 1
#define EFI_IMAGE_SYM_DTYPE_FUNCTION 2
#define EFI_IMAGE_SYM_DTYPE_ARRAY 3
//
// Storage classes.
//
#define EFI_IMAGE_SYM_CLASS_END_OF_FUNCTION ((UINT8) -1)
#define EFI_IMAGE_SYM_CLASS_NULL 0
#define EFI_IMAGE_SYM_CLASS_AUTOMATIC 1
#define EFI_IMAGE_SYM_CLASS_EXTERNAL 2
#define EFI_IMAGE_SYM_CLASS_STATIC 3
#define EFI_IMAGE_SYM_CLASS_REGISTER 4
#define EFI_IMAGE_SYM_CLASS_EXTERNAL_DEF 5
#define EFI_IMAGE_SYM_CLASS_LABEL 6
#define EFI_IMAGE_SYM_CLASS_UNDEFINED_LABEL 7
#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_STRUCT 8
#define EFI_IMAGE_SYM_CLASS_ARGUMENT 9
#define EFI_IMAGE_SYM_CLASS_STRUCT_TAG 10
#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_UNION 11
#define EFI_IMAGE_SYM_CLASS_UNION_TAG 12
#define EFI_IMAGE_SYM_CLASS_TYPE_DEFINITION 13
#define EFI_IMAGE_SYM_CLASS_UNDEFINED_STATIC 14
#define EFI_IMAGE_SYM_CLASS_ENUM_TAG 15
#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_ENUM 16
#define EFI_IMAGE_SYM_CLASS_REGISTER_PARAM 17
#define EFI_IMAGE_SYM_CLASS_BIT_FIELD 18
#define EFI_IMAGE_SYM_CLASS_BLOCK 100
#define EFI_IMAGE_SYM_CLASS_FUNCTION 101
#define EFI_IMAGE_SYM_CLASS_END_OF_STRUCT 102
#define EFI_IMAGE_SYM_CLASS_FILE 103
#define EFI_IMAGE_SYM_CLASS_SECTION 104
#define EFI_IMAGE_SYM_CLASS_WEAK_EXTERNAL 105
//
// type packing constants
//
#define EFI_IMAGE_N_BTMASK 017
#define EFI_IMAGE_N_TMASK 060
#define EFI_IMAGE_N_TMASK1 0300
#define EFI_IMAGE_N_TMASK2 0360
#define EFI_IMAGE_N_BTSHFT 4
#define EFI_IMAGE_N_TSHIFT 2
//
// Communal selection types.
//
#define EFI_IMAGE_COMDAT_SELECT_NODUPLICATES 1
#define EFI_IMAGE_COMDAT_SELECT_ANY 2
#define EFI_IMAGE_COMDAT_SELECT_SAME_SIZE 3
#define EFI_IMAGE_COMDAT_SELECT_EXACT_MATCH 4
#define EFI_IMAGE_COMDAT_SELECT_ASSOCIATIVE 5
//
// the following values only be referred in PeCoff, not defined in PECOFF.
//
#define EFI_IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY 1
#define EFI_IMAGE_WEAK_EXTERN_SEARCH_LIBRARY 2
#define EFI_IMAGE_WEAK_EXTERN_SEARCH_ALIAS 3
///
/// Relocation format.
///
typedef struct {
UINT32 VirtualAddress;
UINT32 SymbolTableIndex;
UINT16 Type;
} EFI_IMAGE_RELOCATION;
///
/// Size of EFI_IMAGE_RELOCATION
///
#define EFI_IMAGE_SIZEOF_RELOCATION 10
//
// I386 relocation types.
//
#define EFI_IMAGE_REL_I386_ABSOLUTE 0x0000 ///< Reference is absolute, no relocation is necessary.
#define EFI_IMAGE_REL_I386_DIR16 0x0001 ///< Direct 16-bit reference to the symbols virtual address.
#define EFI_IMAGE_REL_I386_REL16 0x0002 ///< PC-relative 16-bit reference to the symbols virtual address.
#define EFI_IMAGE_REL_I386_DIR32 0x0006 ///< Direct 32-bit reference to the symbols virtual address.
#define EFI_IMAGE_REL_I386_DIR32NB 0x0007 ///< Direct 32-bit reference to the symbols virtual address, base not included.
#define EFI_IMAGE_REL_I386_SEG12 0x0009 ///< Direct 16-bit reference to the segment-selector bits of a 32-bit virtual address.
#define EFI_IMAGE_REL_I386_SECTION 0x000A
#define EFI_IMAGE_REL_I386_SECREL 0x000B
#define EFI_IMAGE_REL_I386_REL32 0x0014 ///< PC-relative 32-bit reference to the symbols virtual address.
//
// x64 processor relocation types.
//
#define IMAGE_REL_AMD64_ABSOLUTE 0x0000
#define IMAGE_REL_AMD64_ADDR64 0x0001
#define IMAGE_REL_AMD64_ADDR32 0x0002
#define IMAGE_REL_AMD64_ADDR32NB 0x0003
#define IMAGE_REL_AMD64_REL32 0x0004
#define IMAGE_REL_AMD64_REL32_1 0x0005
#define IMAGE_REL_AMD64_REL32_2 0x0006
#define IMAGE_REL_AMD64_REL32_3 0x0007
#define IMAGE_REL_AMD64_REL32_4 0x0008
#define IMAGE_REL_AMD64_REL32_5 0x0009
#define IMAGE_REL_AMD64_SECTION 0x000A
#define IMAGE_REL_AMD64_SECREL 0x000B
#define IMAGE_REL_AMD64_SECREL7 0x000C
#define IMAGE_REL_AMD64_TOKEN 0x000D
#define IMAGE_REL_AMD64_SREL32 0x000E
#define IMAGE_REL_AMD64_PAIR 0x000F
#define IMAGE_REL_AMD64_SSPAN32 0x0010
///
/// Based relocation format.
///
typedef struct {
UINT32 VirtualAddress;
UINT32 SizeOfBlock;
UINT16 Relocations[];
} EFI_IMAGE_BASE_RELOCATION;
///
/// Size of EFI_IMAGE_BASE_RELOCATION.
///
#define EFI_IMAGE_SIZEOF_BASE_RELOCATION 8
//
// Based relocation types.
//
#define EFI_IMAGE_REL_BASED_ABSOLUTE 0
#define EFI_IMAGE_REL_BASED_HIGH 1
#define EFI_IMAGE_REL_BASED_LOW 2
#define EFI_IMAGE_REL_BASED_HIGHLOW 3
#define EFI_IMAGE_REL_BASED_HIGHADJ 4
#define EFI_IMAGE_REL_BASED_MIPS_JMPADDR 5
#define EFI_IMAGE_REL_BASED_ARM_MOV32A 5
#define EFI_IMAGE_REL_BASED_ARM_MOV32T 7
#define EFI_IMAGE_REL_BASED_IA64_IMM64 9
#define EFI_IMAGE_REL_BASED_MIPS_JMPADDR16 9
#define EFI_IMAGE_REL_BASED_DIR64 10
///
/// Line number format.
///
typedef struct {
union {
UINT32 SymbolTableIndex; ///< Symbol table index of function name if Linenumber is 0.
UINT32 VirtualAddress; ///< Virtual address of line number.
} Type;
UINT16 Linenumber; ///< Line number.
} EFI_IMAGE_LINENUMBER;
///
/// Size of EFI_IMAGE_LINENUMBER.
///
#define EFI_IMAGE_SIZEOF_LINENUMBER 6
//
// Archive format.
//
#define EFI_IMAGE_ARCHIVE_START_SIZE 8
#define EFI_IMAGE_ARCHIVE_START "!<arch>\n"
#define EFI_IMAGE_ARCHIVE_END "`\n"
#define EFI_IMAGE_ARCHIVE_PAD "\n"
#define EFI_IMAGE_ARCHIVE_LINKER_MEMBER "/ "
#define EFI_IMAGE_ARCHIVE_LONGNAMES_MEMBER "// "
///
/// Archive Member Headers
///
typedef struct {
UINT8 Name[16]; ///< File member name - `/' terminated.
UINT8 Date[12]; ///< File member date - decimal.
UINT8 UserID[6]; ///< File member user id - decimal.
UINT8 GroupID[6]; ///< File member group id - decimal.
UINT8 Mode[8]; ///< File member mode - octal.
UINT8 Size[10]; ///< File member size - decimal.
UINT8 EndHeader[2]; ///< String to end header. (0x60 0x0A).
} EFI_IMAGE_ARCHIVE_MEMBER_HEADER;
///
/// Size of EFI_IMAGE_ARCHIVE_MEMBER_HEADER.
///
#define EFI_IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60
//
// DLL Support
//
///
/// Export Directory Table.
///
typedef struct {
UINT32 Characteristics;
UINT32 TimeDateStamp;
UINT16 MajorVersion;
UINT16 MinorVersion;
UINT32 Name;
UINT32 Base;
UINT32 NumberOfFunctions;
UINT32 NumberOfNames;
UINT32 AddressOfFunctions;
UINT32 AddressOfNames;
UINT32 AddressOfNameOrdinals;
} EFI_IMAGE_EXPORT_DIRECTORY;
///
/// Hint/Name Table.
///
typedef struct {
UINT16 Hint;
UINT8 Name[1];
} EFI_IMAGE_IMPORT_BY_NAME;
///
/// Import Address Table RVA (Thunk Table).
///
typedef struct {
union {
UINT32 Function;
UINT32 Ordinal;
EFI_IMAGE_IMPORT_BY_NAME *AddressOfData;
} u1;
} EFI_IMAGE_THUNK_DATA;
#define EFI_IMAGE_ORDINAL_FLAG BIT31 ///< Flag for PE32.
#define EFI_IMAGE_SNAP_BY_ORDINAL(Ordinal) ((Ordinal & EFI_IMAGE_ORDINAL_FLAG) != 0)
#define EFI_IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff)
///
/// Import Directory Table
///
typedef struct {
UINT32 Characteristics;
UINT32 TimeDateStamp;
UINT32 ForwarderChain;
UINT32 Name;
EFI_IMAGE_THUNK_DATA *FirstThunk;
} EFI_IMAGE_IMPORT_DESCRIPTOR;
///
/// Debug Directory Format.
///
typedef struct {
UINT32 Characteristics;
UINT32 TimeDateStamp;
UINT16 MajorVersion;
UINT16 MinorVersion;
UINT32 Type;
UINT32 SizeOfData;
UINT32 RVA; ///< The address of the debug data when loaded, relative to the image base.
UINT32 FileOffset; ///< The file pointer to the debug data.
} EFI_IMAGE_DEBUG_DIRECTORY_ENTRY;
#define EFI_IMAGE_DEBUG_TYPE_CODEVIEW 2 ///< The Visual C++ debug information.
///
/// Debug Data Structure defined in Microsoft C++.
///
#define CODEVIEW_SIGNATURE_NB10 SIGNATURE_32('N', 'B', '1', '0')
typedef struct {
UINT32 Signature; ///< "NB10"
UINT32 Unknown;
UINT32 Unknown2;
UINT32 Unknown3;
//
// Filename of .PDB goes here
//
} EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY;
///
/// Debug Data Structure defined in Microsoft C++.
///
#define CODEVIEW_SIGNATURE_RSDS SIGNATURE_32('R', 'S', 'D', 'S')
typedef struct {
UINT32 Signature; ///< "RSDS".
UINT32 Unknown;
UINT32 Unknown2;
UINT32 Unknown3;
UINT32 Unknown4;
UINT32 Unknown5;
//
// Filename of .PDB goes here
//
} EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY;
///
/// Debug Data Structure defined by Apple Mach-O to Coff utility.
///
#define CODEVIEW_SIGNATURE_MTOC SIGNATURE_32('M', 'T', 'O', 'C')
typedef struct {
UINT32 Signature; ///< "MTOC".
UINT64 MachOUuid[2];
//
// Filename of .DLL (Mach-O with debug info) goes here
//
} EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY;
///
/// Resource directory entry format.
///
typedef struct {
union {
struct {
UINT32 NameOffset:31;
UINT32 NameIsString:1;
} s;
UINT32 Id;
} u1;
union {
UINT32 OffsetToData;
struct {
UINT32 OffsetToDirectory:31;
UINT32 DataIsDirectory:1;
} s;
} u2;
} EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY;
///
/// Resource format.
///
typedef struct {
UINT32 Characteristics;
UINT32 TimeDateStamp;
UINT16 MajorVersion;
UINT16 MinorVersion;
UINT16 NumberOfNamedEntries;
UINT16 NumberOfIdEntries;
EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY Entires[];
} EFI_IMAGE_RESOURCE_DIRECTORY;
///
/// Resource directory entry for string.
///
typedef struct {
UINT16 Length;
CHAR16 String[1];
} EFI_IMAGE_RESOURCE_DIRECTORY_STRING;
///
/// Resource directory entry for data array.
///
typedef struct {
UINT32 OffsetToData;
UINT32 Size;
UINT32 CodePage;
UINT32 Reserved;
} EFI_IMAGE_RESOURCE_DATA_ENTRY;
///
/// Header format for TE images, defined in the PI Specification, 1.0.
///
typedef struct {
UINT16 Signature; ///< The signature for TE format = "VZ".
UINT16 Machine; ///< From the original file header.
UINT8 NumberOfSections; ///< From the original file header.
UINT8 Subsystem; ///< From original optional header.
UINT16 StrippedSize; ///< Number of bytes we removed from the header.
UINT32 AddressOfEntryPoint; ///< Offset to entry point -- from original optional header.
UINT32 BaseOfCode; ///< From original image -- required for ITP debug.
UINT64 ImageBase; ///< From original file header.
EFI_IMAGE_DATA_DIRECTORY DataDirectory[2]; ///< Only base relocation and debug directory.
} EFI_TE_IMAGE_HEADER;
#define EFI_TE_IMAGE_HEADER_SIGNATURE SIGNATURE_16('V', 'Z')
//
// Data directory indexes in our TE image header
//
#define EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC 0
#define EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG 1
///
/// Union of PE32, PE32+, and TE headers.
///
typedef union {
EFI_IMAGE_NT_HEADERS_COMMON_HDR PeCommon;
EFI_IMAGE_NT_HEADERS32 Pe32;
EFI_IMAGE_NT_HEADERS64 Pe32Plus;
EFI_TE_IMAGE_HEADER Te;
} EFI_IMAGE_OPTIONAL_HEADER_UNION;
#endif // OC_PE_IMAGE_H

View File

@ -72,11 +72,13 @@ OcAppleSecureBootSetDmgLoading (
/**
Get DMG loading status on Apple Secure Boot protocol.
@param[out] RealPolicy Actual secure boot policy, optional.
@retval TRUE when loading DMG.
**/
BOOLEAN
OcAppleSecureBootGetDmgLoading (
VOID
OUT UINT8 *RealPolicy OPTIONAL
);
/**

View File

@ -1238,4 +1238,43 @@ OcRegisterBootOption (
IN CONST CHAR16 *FilePath
);
/**
Initialises custom Boot Services overrides to support direct images.
**/
VOID
OcInitDirectImageLoader (
VOID
);
/**
Make DirectImageLoader the default for Apple Secure Boot.
**/
VOID
OcActivateDirectImageLoader (
VOID
);
/**
Simplified load image routine, which bypasses UEFI and loads the image directly.
@param[in] BootPolicy Ignored.
@param[in] ParentImageHandle The caller's image handle.
@param[in] DevicePath Ignored.
@param[in] SourceBuffer Pointer to the memory location containing image to be loaded.
@param[in] SourceSize The size in bytes of SourceBuffer.
@param[out] ImageHandle The pointer to the returned image handle created on success.
@retval EFI_SUCCESS on success.
**/
EFI_STATUS
EFIAPI
OcDirectLoadImage (
IN BOOLEAN BootPolicy,
IN EFI_HANDLE ParentImageHandle,
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
IN VOID *SourceBuffer OPTIONAL,
IN UINTN SourceSize,
OUT EFI_HANDLE *ImageHandle
);
#endif // OC_BOOT_MANAGEMENT_LIB_H

View File

@ -109,6 +109,13 @@ OcOverflowMulAddU32 (
UINT32 *Result
);
BOOLEAN
OcOverflowAlignUpU32 (
UINT32 Value,
UINT32 Alignment,
UINT32 *Result
);
BOOLEAN
OcOverflowAddS32 (
INT32 A,

View File

@ -0,0 +1,198 @@
/** @file
Provides services to load and relocate a PE/COFF image.
The PE/COFF Loader Library abstracts the implementation of a PE/COFF loader for
IA-32, x86, and EBC processor types. The library functions are memory-based
and can be ported easily to any environment.
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef OC_PE_COFF_LIB_H
#define OC_PE_COFF_LIB_H
#include <IndustryStandard/OcPeImage.h>
// TODO: move?
/**
Performs digest on a data buffer of the specified length. This function can
be called multiple times to compute the digest of long or discontinuous data streams.
If HashContext is NULL, then ASSERT().
@param[in,out] HashContext Pointer to the MD5 context.
@param[in] Data Pointer to the buffer containing the data to be hashed.
@param[in] DataLength Length of Data buffer in bytes.
@retval TRUE HASH data digest succeeded.
@retval FALSE Invalid HASH context. After HashFinal function has been called, the
HASH context cannot be reused.
**/
typedef
BOOLEAN
(EFIAPI *HASH_UPDATE)(
IN OUT VOID *HashContext,
IN CONST VOID *Data,
IN UINTN DataLength
);
//
// Return status codes from the PE/COFF Loader services
//
#define IMAGE_ERROR_SUCCESS 0U
#define IMAGE_ERROR_IMAGE_READ 1U
#define IMAGE_ERROR_INVALID_PE_HEADER_SIGNATURE 2U
#define IMAGE_ERROR_INVALID_MACHINE_TYPE 3U
#define IMAGE_ERROR_INVALID_SUBSYSTEM 4U
#define IMAGE_ERROR_INVALID_IMAGE_ADDRESS 5U
#define IMAGE_ERROR_INVALID_IMAGE_SIZE 6U
#define IMAGE_ERROR_INVALID_SECTION_ALIGNMENT 7U
#define IMAGE_ERROR_SECTION_NOT_LOADED 8U
#define IMAGE_ERROR_FAILED_RELOCATION 9U
#define IMAGE_ERROR_FAILED_ICACHE_FLUSH 10U
#define IMAGE_ERROR_UNSUPPORTED 11U
typedef UINTN IMAGE_STATUS;
typedef enum {
ImageTypeTe,
ImageTypePe32,
ImageTypePe32Plus,
ImageTypeMax
} IMAGE_LOADER_IMAGE_TYPE;
///
/// The context structure used while PE/COFF image is being loaded and relocated.
///
typedef struct {
///
/// Set by OcPeCoffLoaderInitializeContext() to the ImageBase in the PE/COFF header.
///
UINT64 ImageBase;
//
// Before LoadImage returns, a pointer to the raw file image.
// After LoadImage returns, a pointer to the loaded image.
//
VOID *FileBuffer;
///
/// Set by OcPeCoffLoaderInitializeContext() to the SizeOfImage in the PE/COFF header.
/// Image size includes the size of Debug Entry if it is present.
///
UINT32 SizeOfImage;
UINT32 SectionAlignment;
///
/// Set by OcPeCoffLoaderInitializeContext() to offset to the PE/COFF header.
/// If the PE/COFF image does not start with a DOS header, this value is zero.
/// Otherwise, it's the offset to the PE/COFF header.
///
UINT32 ExeHdrOffset;
///
/// Is set by OcPeCoffLoaderInitializeContext() to the Section Alignment in the PE/COFF header.
///
UINT32 SizeOfHeaders;
UINT32 AddressOfEntryPoint;
///
/// Set by OcPeCoffLoaderInitializeContext() to TRUE if the PE/COFF image does not contain
/// relocation information.
///
BOOLEAN RelocsStripped;
///
/// Set by OcPeCoffLoaderInitializeContext() to TRUE if the image is a TE image.
/// For a definition of the TE Image format, see the Platform Initialization Pre-EFI
/// Initialization Core Interface Specification.
///
UINT8 ImageType;
UINT16 Subsystem;
UINT16 Machine;
UINT32 TeStrippedOffset;
UINT32 RelocDirRva;
UINT32 RelocDirSize;
} PE_COFF_LOADER_IMAGE_CONTEXT;
/**
Retrieves information about a PE/COFF image.
Computes the ExeHdrOffset, IsTeImage, ImageType, ImageAddress, ImageSize,
DestinationAddress, RelocsStripped, SectionAlignment, SizeOfHeaders, and
DebugDirectoryEntryRva fields of the ImageContext structure.
If ImageContext is NULL, then return RETURN_INVALID_PARAMETER.
If the PE/COFF image accessed through the ImageRead service in the ImageContext
structure is not a supported PE/COFF image type, then return RETURN_UNSUPPORTED.
If any errors occur while computing the fields of ImageContext,
then the error status is returned in the ImageError field of ImageContext.
If the image is a TE image, then SectionAlignment is set to 0.
The ImageRead and Handle fields of ImageContext structure must be valid prior
to invoking this service.
@param ImageContext The pointer to the image context structure that
describes the PE/COFF image that needs to be
examined by this function.
@retval RETURN_SUCCESS The information on the PE/COFF image was collected.
@retval RETURN_INVALID_PARAMETER ImageContext is NULL.
@retval RETURN_UNSUPPORTED The PE/COFF image is not supported.
**/
IMAGE_STATUS
OcPeCoffLoaderInitializeContext (
OUT PE_COFF_LOADER_IMAGE_CONTEXT *Context,
IN CONST VOID *FileBuffer,
IN UINTN FileSize
);
/**
Loads a PE/COFF image into memory.
Loads the PE/COFF image accessed through the ImageRead service of ImageContext into the buffer
specified by the ImageAddress and ImageSize fields of ImageContext. The caller must allocate
the load buffer and fill in the ImageAddress and ImageSize fields prior to calling this function.
The EntryPoint, FixupDataSize, CodeView, PdbPointer and HiiResourceData fields of ImageContext are computed.
The ImageRead, Handle, ExeHdrOffset, IsTeImage, Machine, ImageType, ImageAddress, ImageSize,
DestinationAddress, RelocsStripped, SectionAlignment, SizeOfHeaders, and DebugDirectoryEntryRva
fields of the ImageContext structure must be valid prior to invoking this service.
If ImageContext is NULL, then ASSERT().
Note that if the platform does not maintain coherency between the instruction cache(s) and the data
cache(s) in hardware, then the caller is responsible for performing cache maintenance operations
prior to transferring control to a PE/COFF image that is loaded using this library.
@param ImageContext The pointer to the image context structure that describes the PE/COFF
image that is being loaded.
@retval RETURN_SUCCESS The PE/COFF image was loaded into the buffer specified by
the ImageAddress and ImageSize fields of ImageContext.
Extended status information is in the ImageError field of ImageContext.
@retval RETURN_BUFFER_TOO_SMALL The caller did not provide a large enough buffer.
Extended status information is in the ImageError field of ImageContext.
@retval RETURN_LOAD_ERROR The PE/COFF image is an EFI Runtime image with no relocations.
Extended status information is in the ImageError field of ImageContext.
@retval RETURN_INVALID_PARAMETER The image address is invalid.
Extended status information is in the ImageError field of ImageContext.
**/
IMAGE_STATUS
OcPeCoffLoaderLoadImage (
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *Context,
OUT VOID *Destination,
IN UINT32 DestinationSize
);
IMAGE_STATUS
OcPeCoffLoaderRelocateImage (
IN CONST PE_COFF_LOADER_IMAGE_CONTEXT *Context,
IN UINTN BaseAddress
);
BOOLEAN
OcPeCoffLoaderHashImage (
IN CONST PE_COFF_LOADER_IMAGE_CONTEXT *Context,
IN HASH_UPDATE HashUpdate,
IN OUT VOID *HashContext
);
#endif // OC_PE_COFF_LIB_H

View File

@ -18,6 +18,7 @@
#include <Library/MemoryAllocationLib.h>
#include <Library/OcApfsLib.h>
#include <Library/OcAppleImageVerificationLib.h>
#include <Library/OcAppleSecureBootLib.h>
#include <Library/OcBootManagementLib.h>
#include <Library/OcConsoleLib.h>
#include <Library/OcDriverConnectionLib.h>
@ -239,6 +240,9 @@ ApfsStartDriver (
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
EFI_HANDLE ImageHandle;
EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
EFI_IMAGE_LOAD LoadImage;
APPLE_SECURE_BOOT_PROTOCOL *SecureBoot;
UINT8 Policy;
Status = VerifyApplePeImageSignature (
DriverBuffer,
@ -272,8 +276,26 @@ ApfsStartDriver (
DevicePath = NULL;
}
SecureBoot = OcAppleSecureBootGetProtocol ();
ASSERT (SecureBoot != NULL);
Status = SecureBoot->GetPolicy (
SecureBoot,
&Policy
);
//
// Load directly when we have Apple Secure Boot.
// - Either normal.
// - Or during DMG loading.
//
if ((!EFI_ERROR (Status) && Policy != AppleImg4SbModeDisabled)
|| (OcAppleSecureBootGetDmgLoading (&Policy) && Policy != AppleImg4SbModeDisabled)) {
LoadImage = OcDirectLoadImage;
} else {
LoadImage = gBS->LoadImage;
}
ImageHandle = NULL;
Status = gBS->LoadImage (
Status = LoadImage (
FALSE,
gImageHandle,
DevicePath,

View File

@ -37,6 +37,7 @@ STATIC APPLE_SECURE_BOOT_PROTOCOL *mSecureBoot;
STATIC CHAR8 mSbHardwareModel[16];
STATIC UINT64 mSbEcid;
STATIC BOOLEAN mDmgLoading = FALSE;
STATIC UINT8 mDmgLoadingPolicy = AppleImg4SbModeMedium;
STATIC BOOLEAN mSbAvailable = TRUE;
STATIC UINT8 mSbPolicy = AppleImg4SbModeMedium;
STATIC UINT8 mSbWindowsPolicy = 1;
@ -958,24 +959,33 @@ OcAppleSecureBootSetDmgLoading (
IN BOOLEAN LoadingDmg
)
{
EFI_STATUS Status;
ASSERT (mSecureBoot != NULL);
mDmgLoading = LoadingDmg;
Status = mSecureBoot->GetPolicy (mSecureBoot, &mDmgLoadingPolicy);
if (EFI_ERROR (Status)) {
mDmgLoadingPolicy = AppleImg4SbModeMedium;
}
if (LoadingDmg) {
DEBUG ((DEBUG_INFO, "OCB: Disabling secure boot for Apple images\n"));
DEBUG ((DEBUG_INFO, "OCSB: Disabling secure boot for Apple images\n"));
mSecureBoot->SetAvailability (mSecureBoot, FALSE);
} else {
DEBUG ((DEBUG_INFO, "OCB: Reenabling secure boot after Apple images\n"));
DEBUG ((DEBUG_INFO, "OCSB: Reenabling secure boot after Apple images\n"));
mSecureBoot->SetAvailability (mSecureBoot, FALSE);
}
}
BOOLEAN
OcAppleSecureBootGetDmgLoading (
VOID
OUT UINT8 *RealPolicy OPTIONAL
)
{
if (RealPolicy != NULL) {
*RealPolicy = mDmgLoadingPolicy;
}
return mDmgLoading;
}
@ -1015,7 +1025,8 @@ OcAppleSecureBootVerify (
// they do not even have global manifests in DMG images.
// Can consider checking boot.efi codesign integrity if we want.
//
if (Policy == AppleImg4SbModeDisabled && OcAppleSecureBootGetDmgLoading ()) {
if (Policy == AppleImg4SbModeDisabled && OcAppleSecureBootGetDmgLoading (NULL)) {
DEBUG ((DEBUG_INFO, "OCSB: Direct booting for DMG image\n"));
return EFI_SUCCESS;
}
@ -1023,6 +1034,7 @@ OcAppleSecureBootVerify (
// For everything else it is unsupported, meaning let the system decide.
//
if (Policy == AppleImg4SbModeDisabled) {
DEBUG ((DEBUG_INFO, "OCSB: Secure boot is disabled, skipping\n"));
return EFI_UNSUPPORTED;
}
@ -1034,7 +1046,7 @@ OcAppleSecureBootVerify (
&ManifestSize
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCB: No IMG4 found - %r\n", Status));
DEBUG ((DEBUG_INFO, "OCSB: No IMG4 found - %r\n", Status));
return EFI_UNSUPPORTED;
}
@ -1055,18 +1067,12 @@ OcAppleSecureBootVerify (
FALSE
);
//
// This is our signature, but the file is corrupted.
//
if (Status == EFI_SECURITY_VIOLATION) {
DEBUG ((DEBUG_WARN, "OCB: IMG4 %08X verification gave secure violation\n"));
return EFI_SECURITY_VIOLATION;
}
//
// We are successful.
//
if (!EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCSB: Verified IMG4 without issues\n"));
FreePool (ManifestBuffer);
return Status;
}
}
@ -1074,5 +1080,7 @@ OcAppleSecureBootVerify (
//
// No suitable signature.
//
DEBUG ((DEBUG_INFO, "OCSB: No suitable signature - %r\n", Status));
FreePool (ManifestBuffer);
return EFI_UNSUPPORTED;
}

View File

@ -1841,7 +1841,7 @@ OcLoadBootEntry (
if (!EFI_ERROR (Status)) {
Status = Context->StartImage (BootEntry, EntryHandle, NULL, NULL);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "OCB: StartImage failed - %r\n", Status));
DEBUG ((DEBUG_WARN, "OCB: StartImage failed - %r\n", Status));
//
// Unload dmg if any.
//

View File

@ -176,14 +176,4 @@ InternalSystemActionResetNvram (
VOID
);
/**
Initialises custom gBS->LoadImage override.
@retval EFI_SUCCESS on success.
**/
EFI_STATUS
InternalInitImageLoader (
VOID
);
#endif // BOOT_MANAGEMENET_INTERNAL_H

View File

@ -14,7 +14,10 @@
#include "BootManagementInternal.h"
#include <IndustryStandard/OcPeImage.h>
#include <Protocol/DevicePath.h>
#include <Protocol/LoadedImage.h>
#include <Protocol/SimpleFileSystem.h>
#include <Guid/AppleVariable.h>
@ -33,12 +36,44 @@
#include <Library/OcFileLib.h>
#include <Library/OcMachoLib.h>
#include <Library/OcStringLib.h>
#include <Library/OcPeCoffLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/PrintLib.h>
STATIC EFI_IMAGE_LOAD mOriginalEfiLoadImage;
#if defined(MDE_CPU_IA32)
#define OC_IMAGE_FILE_MACHINE IMAGE_FILE_MACHINE_I386
#elif defined(MDE_CPU_X64)
#define OC_IMAGE_FILE_MACHINE IMAGE_FILE_MACHINE_X64
#else
#error Unsupported architecture.
#endif
STATIC EFI_GUID mOcLoadedImageProtocolGuid = {
0x1f3c963d, 0xf9dc, 0x4537, { 0xbb, 0x06, 0xd8, 0x08, 0x46, 0x4a, 0x85, 0x2e }
};
typedef struct {
EFI_IMAGE_ENTRY_POINT EntryPoint;
EFI_PHYSICAL_ADDRESS ImageArea;
UINTN PageCount;
EFI_STATUS Status;
VOID *JumpBuffer;
BASE_LIBRARY_JUMP_BUFFER *JumpContext;
CHAR16 *ExitData;
UINTN ExitDataSize;
UINT16 Subsystem;
BOOLEAN Started;
EFI_LOADED_IMAGE_PROTOCOL LoadedImage;
} OC_LOADED_IMAGE_PROTOCOL;
STATIC EFI_IMAGE_LOAD mOriginalEfiLoadImage;
STATIC EFI_IMAGE_START mOriginalEfiStartImage;
STATIC EFI_IMAGE_UNLOAD mOriginalEfiUnloadImage;
STATIC EFI_EXIT mOriginalEfiExit;
STATIC EFI_HANDLE mCurrentImageHandle;
STATIC BOOLEAN mDirectImageLoaderEnabled;
STATIC
EFI_STATUS
@ -148,6 +183,409 @@ InternalUpdateLoadedImage (
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
OcDirectLoadImage (
IN BOOLEAN BootPolicy,
IN EFI_HANDLE ParentImageHandle,
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
IN VOID *SourceBuffer OPTIONAL,
IN UINTN SourceSize,
OUT EFI_HANDLE *ImageHandle
)
{
EFI_STATUS Status;
IMAGE_STATUS ImageStatus;
PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
EFI_PHYSICAL_ADDRESS DestinationArea;
VOID *DestinationBuffer;
OC_LOADED_IMAGE_PROTOCOL *OcLoadedImage;
EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
ASSERT (SourceBuffer != NULL);
//
// Initialize the image context.
//
ImageStatus = OcPeCoffLoaderInitializeContext (
&ImageContext,
SourceBuffer,
SourceSize
);
if (ImageStatus != IMAGE_ERROR_SUCCESS) {
DEBUG ((DEBUG_INFO, "OCB: PeCoff init failure - %d\n", ImageStatus));
return EFI_UNSUPPORTED;
}
//
// Reject images that are not meant for the platform's architecture.
//
if (ImageContext.Machine != OC_IMAGE_FILE_MACHINE) {
DEBUG ((DEBUG_INFO, "OCB: PeCoff wrong machine - %x\n", ImageContext.Machine));
return EFI_UNSUPPORTED;
}
//
// Reject RT drivers for the moment.
//
if (ImageContext.Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {
DEBUG ((DEBUG_INFO, "OCB: PeCoff no support for RT drivers\n"));
return EFI_UNSUPPORTED;
}
//
// Allocate the image destination memory.
// FIXME: RT drivers require EfiRuntimeServicesCode.
//
Status = gBS->AllocatePages (
AllocateAnyPages,
ImageContext.Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
? EfiLoaderCode : EfiBootServicesCode,
EFI_SIZE_TO_PAGES (ImageContext.SizeOfImage),
&DestinationArea
);
if (EFI_ERROR (Status)) {
return Status;
}
DestinationBuffer = (VOID *)(UINTN) DestinationArea;
//
// Load SourceBuffer into DestinationBuffer.
//
ImageStatus = OcPeCoffLoaderLoadImage (
&ImageContext,
DestinationBuffer,
ImageContext.SizeOfImage
);
if (ImageStatus != IMAGE_ERROR_SUCCESS) {
DEBUG ((DEBUG_INFO, "OCB: PeCoff load image error - %d\n", ImageStatus));
FreePages (DestinationBuffer, EFI_SIZE_TO_PAGES (ImageContext.SizeOfImage));
return EFI_UNSUPPORTED;
}
//
// Relocate the loaded image to the destination address.
//
ImageStatus = OcPeCoffLoaderRelocateImage (
&ImageContext,
(UINTN) DestinationBuffer
);
if (ImageStatus != IMAGE_ERROR_SUCCESS) {
DEBUG ((DEBUG_INFO, "OCB: PeCoff relocate image error - %d\n", ImageStatus));
FreePages (DestinationBuffer, EFI_SIZE_TO_PAGES (ImageContext.SizeOfImage));
return EFI_UNSUPPORTED;
}
//
// Construct a LoadedImage protocol for the image.
//
OcLoadedImage = AllocateZeroPool (sizeof (*OcLoadedImage));
if (OcLoadedImage == NULL) {
FreePages (DestinationBuffer, EFI_SIZE_TO_PAGES (ImageContext.SizeOfImage));
return EFI_OUT_OF_RESOURCES;
}
OcLoadedImage->EntryPoint = (EFI_IMAGE_ENTRY_POINT) ((UINTN) DestinationBuffer + ImageContext.AddressOfEntryPoint);
OcLoadedImage->ImageArea = DestinationArea;
OcLoadedImage->PageCount = EFI_SIZE_TO_PAGES (ImageContext.SizeOfImage);
OcLoadedImage->Subsystem = ImageContext.Subsystem;
LoadedImage = &OcLoadedImage->LoadedImage;
LoadedImage->Revision = EFI_LOADED_IMAGE_INFORMATION_REVISION;
LoadedImage->ParentHandle = ParentImageHandle;
LoadedImage->SystemTable = gST;
LoadedImage->ImageBase = DestinationBuffer;
LoadedImage->ImageSize = ImageContext.SizeOfImage;
//
// FIXME: Support RT drivers.
//
if (ImageContext.Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {
LoadedImage->ImageCodeType = EfiLoaderCode;
LoadedImage->ImageDataType = EfiLoaderData;
} else {
LoadedImage->ImageCodeType = EfiBootServicesCode;
LoadedImage->ImageDataType = EfiBootServicesData;
}
//
// Install LoadedImage and the image's entry point.
//
*ImageHandle = NULL;
Status = gBS->InstallMultipleProtocolInterfaces (
ImageHandle,
&gEfiLoadedImageProtocolGuid,
LoadedImage,
&mOcLoadedImageProtocolGuid,
OcLoadedImage,
NULL
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCB: PeCoff proto install error - %r\n", Status));
FreePool (OcLoadedImage);
FreePages (DestinationBuffer, EFI_SIZE_TO_PAGES (ImageContext.SizeOfImage));
return Status;
}
DEBUG ((DEBUG_VERBOSE, "OCB: Loaded image at %p\n", *ImageHandle));
return EFI_SUCCESS;
}
/**
Unload image routine for OcDirectLoadImage.
@param[in] OcLoadedImage Our loaded image instance.
@param[in] ImageHandle Handle that identifies the image to be unloaded.
@retval EFI_SUCCESS The image has been unloaded.
**/
STATIC
EFI_STATUS
InternalDirectUnloadImage (
IN OC_LOADED_IMAGE_PROTOCOL *OcLoadedImage,
IN EFI_HANDLE ImageHandle
)
{
EFI_STATUS Status;
EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
LoadedImage = &OcLoadedImage->LoadedImage;
if (LoadedImage->Unload != NULL) {
Status = LoadedImage->Unload (ImageHandle);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Do not allow to execute Unload multiple times.
//
LoadedImage->Unload = NULL;
} else if (OcLoadedImage->Started) {
return EFI_UNSUPPORTED;
}
Status = gBS->UninstallMultipleProtocolInterfaces (
ImageHandle,
&gEfiLoadedImageProtocolGuid,
LoadedImage,
&mOcLoadedImageProtocolGuid,
OcLoadedImage,
NULL
);
if (EFI_ERROR (Status)) {
return Status;
}
gBS->FreePages (OcLoadedImage->ImageArea, OcLoadedImage->PageCount);
FreePool (OcLoadedImage);
//
// NOTE: Avoid EFI 1.10 extension of closing opened protocols.
//
return EFI_SUCCESS;
}
/**
Unload image routine for OcDirectLoadImage.
@param[in] OcLoadedImage Our loaded image instance.
@param[in] ImageHandle Handle that identifies the image to be unloaded.
@param[in] ExitStatus The image's exit code.
@param[in] ExitDataSize The size, in bytes, of ExitData. Ignored if ExitStatus is EFI_SUCCESS.
@param[in] ExitData The pointer to a data buffer that includes a Null-terminated string,
optionally followed by additional binary data. The string is a
description that the caller may use to further indicate the reason
for the image's exit. ExitData is only valid if ExitStatus
is something other than EFI_SUCCESS. The ExitData buffer
must be allocated by calling AllocatePool().
@retval EFI_SUCCESS The image has been unloaded.
**/
STATIC
EFI_STATUS
InternalDirectExit (
IN OC_LOADED_IMAGE_PROTOCOL *OcLoadedImage,
IN EFI_HANDLE ImageHandle,
IN EFI_STATUS ExitStatus,
IN UINTN ExitDataSize,
IN CHAR16 *ExitData OPTIONAL
)
{
EFI_TPL OldTpl;
DEBUG ((
DEBUG_VERBOSE, "OCB: Exit %p %p (%d) - %r\n",
ImageHandle,
mCurrentImageHandle,
OcLoadedImage->Started,
ExitStatus
));
//
// Prevent possible reentrance to this function for the same ImageHandle.
//
OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
//
// If the image has not been started just free its resources.
// Should not happen normally.
//
if (!OcLoadedImage->Started) {
InternalDirectUnloadImage (OcLoadedImage, ImageHandle);
gBS->RestoreTPL (OldTpl);
return EFI_SUCCESS;
}
//
// If the image has been started, verify this image can exit.
//
if (ImageHandle != mCurrentImageHandle) {
DEBUG ((DEBUG_LOAD|DEBUG_ERROR, "Exit: Image is not exitable image\n"));
gBS->RestoreTPL (OldTpl);
return EFI_INVALID_PARAMETER;
}
//
// Set the return status.
//
OcLoadedImage->Status = ExitStatus;
//
// If there's ExitData info provide it.
//
if (ExitData != NULL) {
OcLoadedImage->ExitDataSize = ExitDataSize;
OcLoadedImage->ExitData = AllocatePool (OcLoadedImage->ExitDataSize);
if (OcLoadedImage->ExitData != NULL) {
CopyMem (OcLoadedImage->ExitData, ExitData, OcLoadedImage->ExitDataSize);
} else {
OcLoadedImage->ExitDataSize = 0;
}
}
//
// return to StartImage
//
gBS->RestoreTPL (OldTpl);
LongJump (OcLoadedImage->JumpContext, (UINTN)-1);
//
// If we return from LongJump, then it is an error
//
ASSERT (FALSE);
CpuDeadLoop ();
return EFI_ACCESS_DENIED;
}
/**
Simplified start image routine for OcDirectLoadImage.
@param[in] OcLoadedImage Our loaded image instance.
@param[in] ImageHandle Handle of image to be started.
@param[out] ExitDataSize The pointer to the size, in bytes, of ExitData.
@param[out] ExitData The pointer to a pointer to a data buffer that includes a Null-terminated
string, optionally followed by additional binary data.
@retval EFI_SUCCESS on success.
**/
STATIC
EFI_STATUS
InternalDirectStartImage (
IN OC_LOADED_IMAGE_PROTOCOL *OcLoadedImage,
IN EFI_HANDLE ImageHandle,
OUT UINTN *ExitDataSize,
OUT CHAR16 **ExitData OPTIONAL
)
{
EFI_STATUS Status;
EFI_HANDLE LastImage;
UINTN SetJumpFlag;
//
// Push the current image.
//
LastImage = mCurrentImageHandle;
mCurrentImageHandle = ImageHandle;
//
// Set long jump for Exit() support
// JumpContext must be aligned on a CPU specific boundary.
// Overallocate the buffer and force the required alignment
//
OcLoadedImage->JumpBuffer = AllocatePool (
sizeof (BASE_LIBRARY_JUMP_BUFFER) + BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT
);
if (OcLoadedImage->JumpBuffer == NULL) {
//
// Pop the current start image context
//
mCurrentImageHandle = LastImage;
return EFI_OUT_OF_RESOURCES;
}
OcLoadedImage->JumpContext = ALIGN_POINTER (
OcLoadedImage->JumpBuffer, BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT
);
SetJumpFlag = SetJump (OcLoadedImage->JumpContext);
//
// The initial call to SetJump() must always return 0.
// Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump().
//
if (SetJumpFlag == 0) {
//
// Invoke the manually loaded image entry point.
//
DEBUG ((DEBUG_VERBOSE, "OCB: Starting image %p\n", ImageHandle));
OcLoadedImage->Started = TRUE;
OcLoadedImage->Status = OcLoadedImage->EntryPoint (
ImageHandle,
OcLoadedImage->LoadedImage.SystemTable
);
//
// If the image returns, exit it through Exit()
//
InternalDirectExit (OcLoadedImage, ImageHandle, OcLoadedImage->Status, 0, NULL);
}
FreePool (OcLoadedImage->JumpBuffer);
//
// Pop the current image.
//
mCurrentImageHandle = LastImage;
//
// NOTE: EFI 1.10 is not supported, refer to
// https://github.com/tianocore/edk2/blob/d8dd54f071cfd60a2dcf5426764a89cd91213420/MdeModulePkg/Core/Dxe/Image/Image.c#L1686-L1697
//
//
// Return the exit data to the caller
//
if (ExitData != NULL && ExitDataSize != NULL) {
*ExitDataSize = OcLoadedImage->ExitDataSize;
*ExitData = OcLoadedImage->ExitData;
} else if (OcLoadedImage->ExitData != NULL) {
//
// Caller doesn't want the exit data, free it
//
FreePool (OcLoadedImage->ExitData);
OcLoadedImage->ExitData = NULL;
}
//
// Save the Status because Image will get destroyed if it is unloaded.
//
Status = OcLoadedImage->Status;
//
// If the image returned an error, or if the image is an application
// unload it
//
if (EFI_ERROR (OcLoadedImage->Status)
|| OcLoadedImage->Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {
InternalDirectUnloadImage (OcLoadedImage, ImageHandle);
}
return Status;
}
STATIC
EFI_STATUS
EFIAPI
@ -198,7 +636,7 @@ InternalEfiLoadImage (
}
}
if (DevicePath != NULL && SourceBuffer != NULL) {
if (DevicePath != NULL && SourceBuffer != NULL && mDirectImageLoaderEnabled) {
SecureBootStatus = OcAppleSecureBootVerify (
DevicePath,
SourceBuffer,
@ -226,6 +664,17 @@ InternalEfiLoadImage (
#else
Status = FatFilterArchitecture64 ((UINT8 **) &SourceBuffer, &RealSize);
#endif
DEBUG ((
DEBUG_INFO,
"OCB: Arch filtering %p(%u)->%p(%u) - %r\n",
AllocatedBuffer,
(UINT32) SourceSize,
SourceBuffer,
RealSize,
Status
));
if (!EFI_ERROR (Status)) {
SourceSize = RealSize;
} else if (AllocatedBuffer != NULL) {
@ -234,21 +683,37 @@ InternalEfiLoadImage (
}
}
//
// Load the image ourselves in secure boot mode.
//
if (SecureBootStatus == EFI_SUCCESS) {
//
// TODO: Here we should use a custom COFF loader!
//
if (SourceBuffer != NULL) {
Status = OcDirectLoadImage (
FALSE,
ParentImageHandle,
DevicePath,
SourceBuffer,
SourceSize,
ImageHandle
);
} else {
//
// We verified the image, but contained garbage.
// This should not happen, just abort.
//
Status = EFI_UNSUPPORTED;
}
} else {
Status = mOriginalEfiLoadImage (
BootPolicy,
ParentImageHandle,
DevicePath,
SourceBuffer,
SourceSize,
ImageHandle
);
}
Status = mOriginalEfiLoadImage (
BootPolicy,
ParentImageHandle,
DevicePath,
SourceBuffer,
SourceSize,
ImageHandle
);
if (AllocatedBuffer != NULL) {
FreePool (AllocatedBuffer);
}
@ -264,15 +729,126 @@ InternalEfiLoadImage (
return Status;
}
STATIC
EFI_STATUS
InternalInitImageLoader (
EFIAPI
InternalEfiStartImage (
IN EFI_HANDLE ImageHandle,
OUT UINTN *ExitDataSize,
OUT CHAR16 **ExitData OPTIONAL
)
{
EFI_STATUS Status;
OC_LOADED_IMAGE_PROTOCOL *OcLoadedImage;
//
// If we loaded the image, invoke the entry point manually.
//
Status = gBS->HandleProtocol (
ImageHandle,
&mOcLoadedImageProtocolGuid,
(VOID **) &OcLoadedImage
);
if (!EFI_ERROR (Status)) {
return InternalDirectStartImage (
OcLoadedImage,
ImageHandle,
ExitDataSize,
ExitData
);
}
return mOriginalEfiStartImage (ImageHandle, ExitDataSize, ExitData);
}
STATIC
EFI_STATUS
EFIAPI
InternalEfiUnloadImage (
IN EFI_HANDLE ImageHandle
)
{
EFI_STATUS Status;
OC_LOADED_IMAGE_PROTOCOL *OcLoadedImage;
//
// If we loaded the image, do the unloading manually.
//
Status = gBS->HandleProtocol (
ImageHandle,
&mOcLoadedImageProtocolGuid,
(VOID **) &OcLoadedImage
);
if (!EFI_ERROR (Status)) {
return InternalDirectUnloadImage (
OcLoadedImage,
ImageHandle
);
}
return mOriginalEfiUnloadImage (ImageHandle);
}
STATIC
EFI_STATUS
EFIAPI
InternalEfiExit (
IN EFI_HANDLE ImageHandle,
IN EFI_STATUS ExitStatus,
IN UINTN ExitDataSize,
IN CHAR16 *ExitData OPTIONAL
)
{
EFI_STATUS Status;
OC_LOADED_IMAGE_PROTOCOL *OcLoadedImage;
//
// If we loaded the image, do the exit manually.
//
Status = gBS->HandleProtocol (
ImageHandle,
&mOcLoadedImageProtocolGuid,
(VOID **) &OcLoadedImage
);
DEBUG ((DEBUG_VERBOSE, "OCB: InternalEfiExit %p - %r / %r\n", ImageHandle, ExitStatus, Status));
if (!EFI_ERROR (Status)) {
return InternalDirectExit (
OcLoadedImage,
ImageHandle,
ExitStatus,
ExitDataSize,
ExitData
);
}
return mOriginalEfiExit (ImageHandle, ExitStatus, ExitDataSize, ExitData);
}
VOID
OcInitDirectImageLoader (
VOID
)
{
mOriginalEfiLoadImage = gBS->LoadImage;
gBS->LoadImage = InternalEfiLoadImage;
mOriginalEfiLoadImage = gBS->LoadImage;
mOriginalEfiStartImage = gBS->StartImage;
mOriginalEfiUnloadImage = gBS->UnloadImage;
mOriginalEfiExit = gBS->Exit;
gBS->LoadImage = InternalEfiLoadImage;
gBS->StartImage = InternalEfiStartImage;
gBS->UnloadImage = InternalEfiUnloadImage;
gBS->Exit = InternalEfiExit;
gBS->Hdr.CRC32 = 0;
gBS->CalculateCrc32 (gBS, gBS->Hdr.HeaderSize, &gBS->Hdr.CRC32);
return EFI_SUCCESS;
}
VOID
OcActivateDirectImageLoader (
VOID
)
{
mDirectImageLoaderEnabled = TRUE;
}

View File

@ -505,10 +505,7 @@ OcRunBootPicker (
SaidWelcome = FALSE;
Status = InternalInitImageLoader ();
if (EFI_ERROR (Status)) {
return Status;
}
OcActivateDirectImageLoader ();
//
// Reset NVRAM right away if requested by a key combination.

View File

@ -110,6 +110,7 @@
OcGuardLib
OcFileLib
OcMachoLib
OcPeCoffLib
OcRtcLib
OcXmlLib
TimerLib

View File

@ -0,0 +1,36 @@
/** @file
OcGuardLib
Copyright (c) 2020, Download-Fritz
All rights reserved.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Base.h>
#include <Library/BaseLib.h>
#include <Library/OcGuardLib.h>
BOOLEAN
OcOverflowAlignUpU32 (
UINT32 Value,
UINT32 Alignment,
UINT32 *Result
)
{
BOOLEAN Status;
Status = OcOverflowAddU32 (Value, Alignment - 1U, Result);
*Result &= ~(Alignment - 1U);
return Status;
}

View File

@ -29,6 +29,7 @@
#
[Sources]
Alignment.c
BitOverflow.c
Canary.c
NativeOverflow.c

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,36 @@
## @file
# PE/COFF Loader Library implementation.
#
# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = OcPeCoffLib
FILE_GUID = 556f5d10-7309-4af4-b80a-8196bd60946e
MODULE_TYPE = BASE
VERSION_STRING = 1.0
LIBRARY_CLASS = OcPeCoffLib
[Sources]
OcPeCoffLib.c
[Packages]
MdePkg/MdePkg.dec
OpenCorePkg/OpenCorePkg.dec
[LibraryClasses]
BaseLib
BaseMemoryLib
DebugLib
MemoryAllocationLib
OcGuardLib
[FixedPcd]
gOpenCorePkgTokenSpaceGuid.PcdImageLoaderLoadHeader
gOpenCorePkgTokenSpaceGuid.PcdImageLoaderHashProhibitOverlap

View File

@ -702,6 +702,9 @@
## @Prompt Allow these signature hashing algorithms for cryptographic usage.
gOpenCorePkgTokenSpaceGuid.PcdOcCryptoAllowedSigHashTypes|0x07|UINT16|0x00000501
gOpenCorePkgTokenSpaceGuid.PcdImageLoaderLoadHeader|TRUE|BOOLEAN|0x00000600
gOpenCorePkgTokenSpaceGuid.PcdImageLoaderHashProhibitOverlap|TRUE|BOOLEAN|0x00000601
[LibraryClasses]
## @libraryclass
OcAcpiLib|Include/Acidanthera/Library/OcAcpiLib.h

View File

@ -108,6 +108,7 @@
OcUnicodeCollationEngLocalLib|OpenCorePkg/Library/OcUnicodeCollationEngLib/OcUnicodeCollationEngLocalLib.inf
OcVirtualFsLib|OpenCorePkg/Library/OcVirtualFsLib/OcVirtualFsLib.inf
OcXmlLib|OpenCorePkg/Library/OcXmlLib/OcXmlLib.inf
OcPeCoffLib|OpenCorePkg/Library/OcPeCoffLib/OcPeCoffLib.inf
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
@ -225,6 +226,7 @@
OpenCorePkg/Library/OcUnicodeCollationEngLib/OcUnicodeCollationEngLocalLib.inf
OpenCorePkg/Library/OcVirtualFsLib/OcVirtualFsLib.inf
OpenCorePkg/Library/OcXmlLib/OcXmlLib.inf
OpenCorePkg/Library/OcPeCoffLib/OcPeCoffLib.inf
OpenCorePkg/Platform/CrScreenshotDxe/CrScreenshotDxe.inf
OpenCorePkg/Platform/OpenCanopy/OpenCanopy.inf
OpenCorePkg/Platform/OpenCore/OpenCore.inf

View File

@ -516,6 +516,8 @@ OcLoadUefiSupport (
OcReinstallProtocols (Config);
OcInitDirectImageLoader ();
OcLoadAppleSecureBoot (Config);
OcLoadUefiInputSupport (Config);

View File

@ -24,6 +24,8 @@ extern UINT32 _gPcd_FixedAtBuild_PcdMaximumLinkedListLength;
extern BOOLEAN _gPcd_FixedAtBuild_PcdVerifyNodeInList;
extern UINT32 _gPcd_FixedAtBuild_PcdCpuNumberOfReservedVariableMtrrs;
extern UINT32 _gPcd_FixedAtBuild_PcdMaximumDevicePathNodeCount;
extern BOOLEAN _gPcd_FixedAtBuild_PcdImageLoaderHashProhibitOverlap;
extern BOOLEAN _gPcd_FixedAtBuild_PcdImageLoaderLoadHeader;
#define _PCD_GET_MODE_32_PcdUefiLibMaxPrintBufferSize _gPcd_FixedAtBuild_PcdUefiLibMaxPrintBufferSize
#define _PCD_GET_MODE_BOOL_PcdUgaConsumeSupport _gPcd_FixedAtBuild_PcdUgaConsumeSupport
@ -42,5 +44,7 @@ extern UINT32 _gPcd_FixedAtBuild_PcdMaximumDevicePathNodeCount;
// this will not be of any effect at userspace
#define _PCD_GET_MODE_64_PcdPciExpressBaseAddress 0
#define _PCD_GET_MODE_32_PcdMaximumDevicePathNodeCount _gPcd_FixedAtBuild_PcdMaximumDevicePathNodeCount
#define _PCD_GET_MODE_BOOL_PcdImageLoaderHashProhibitOverlap _gPcd_FixedAtBuild_PcdImageLoaderHashProhibitOverlap
#define _PCD_GET_MODE_BOOL_PcdImageLoaderLoadHeader _gPcd_FixedAtBuild_PcdImageLoaderLoadHeader
#endif // OC_USER_PCD_H

View File

@ -17,6 +17,8 @@
#define _PCD_VALUE_PcdVerifyNodeInList ((BOOLEAN)0U)
#define _PCD_VALUE_PcdCpuNumberOfReservedVariableMtrrs 0x2U
#define _PCD_VALUE_PcdMaximumDevicePathNodeCount 0U
#define _PCD_VALUE_PcdImageLoaderHashProhibitOverlap 1U
#define _PCD_VALUE_PcdImageLoaderLoadHeader 0U
UINT32 _gPcd_FixedAtBuild_PcdUefiLibMaxPrintBufferSize = _PCD_VALUE_PcdUefiLibMaxPrintBufferSize;
BOOLEAN _gPcd_FixedAtBuild_PcdUgaConsumeSupport = _PCD_VALUE_PcdUgaConsumeSupport;
@ -30,3 +32,5 @@ UINT32 _gPcd_FixedAtBuild_PcdMaximumLinkedListLength = _PCD_VALUE_PcdMaximumLink
BOOLEAN _gPcd_FixedAtBuild_PcdVerifyNodeInList = _PCD_VALUE_PcdVerifyNodeInList;
UINT32 _gPcd_FixedAtBuild_PcdCpuNumberOfReservedVariableMtrrs = _PCD_VALUE_PcdCpuNumberOfReservedVariableMtrrs;
UINT32 _gPcd_FixedAtBuild_PcdMaximumDevicePathNodeCount = _PCD_VALUE_PcdMaximumDevicePathNodeCount;
BOOLEAN _gPcd_FixedAtBuild_PcdImageLoaderHashProhibitOverlap = _PCD_VALUE_PcdImageLoaderHashProhibitOverlap;
BOOLEAN _gPcd_FixedAtBuild_PcdImageLoaderLoadHeader = _PCD_VALUE_PcdImageLoaderLoadHeader;

View File

@ -112,7 +112,7 @@ ifneq ($(STANDALONE),1)
#
# OcGuardLib targets.
#
OBJS += BitOverflow.o NativeOverflow.o TripleOverflow.o
OBJS += BitOverflow.o NativeOverflow.o TripleOverflow.o Alignment.o
#
# OcSerializeLib targets.
#

View File

@ -0,0 +1,11 @@
## @file
# Copyright (c) 2020, vit9696. All rights reserved.
# SPDX-License-Identifier: BSD-3-Clause
##
PROJECT = PeCoff
PRODUCT = $(PROJECT)$(SUFFIX)
OBJS = $(PROJECT).o \
OcPeCoffLib.o
VPATH = ../../Library/OcPeCoffLib
include ../../User/Makefile

View File

@ -0,0 +1,149 @@
/** @file
Copyright (c) 2018, vit9696. All rights reserved.
SPDX-License-Identifier: BSD-3-Clause
**/
#include "../Include/Uefi.h"
#include <Library/OcPeCoffLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/DebugLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <stdio.h>
#include <string.h>
#include <File.h>
/**
clang -g -fsanitize=undefined,address -Wno-incompatible-pointer-types-discards-qualifiers -fshort-wchar -I../Include -I../../Include -I../../../MdePkg/Include/ -I../../../EfiPkg/Include/ -include ../Include/Base.h DiskImage.c ../../Library/OcXmlLib/OcXmlLib.c ../../Library/OcTemplateLib/OcTemplateLib.c ../../Library/OcSerializeLib/OcSerializeLib.c ../../Library/OcMiscLib/Base64Decode.c ../../Library/OcStringLib/OcAsciiLib.c ../../Library/OcAppleDiskImageLib/OcAppleDiskImageLib.c ../../Library/OcAppleDiskImageLib/OcAppleDiskImageLibInternal.c ../../Library/OcMiscLib/DataPatcher.c ../../Library/OcCompressionLib/zlib/zlib_uefi.c ../../Library/OcCompressionLib/zlib/adler32.c ../../Library/OcCompressionLib/zlib/deflate.c ../../Library/OcCompressionLib/zlib/crc32.c ../../Library/OcCompressionLib/zlib/compress.c ../../Library/OcCompressionLib/zlib/infback.c ../../Library/OcCompressionLib/zlib/inffast.c ../../Library/OcCompressionLib/zlib/inflate.c ../../Library/OcCompressionLib/zlib/inftrees.c ../../Library/OcCompressionLib/zlib/trees.c ../../Library/OcCompressionLib/zlib/uncompr.c ../../Library/OcCryptoLib/Sha256.c ../../Library/OcCryptoLib/Rsa2048Sha256.c ../../Library/OcAppleKeysLib/OcAppleKeysLib.c ../../Library/OcAppleChunklistLib/OcAppleChunklistLib.c ../../Library/OcAppleRamDiskLib/OcAppleRamDiskLib.c ../../Library/OcFileLib/ReadFile.c ../../Library/OcFileLib/FileProtocol.c -o DiskImage
clang-mp-7.0 -DFUZZING_TEST=1 -g -fsanitize=undefined,address,fuzzer -Wno-incompatible-pointer-types-discards-qualifiers -fshort-wchar -I../Include -I../../Include -I../../../MdePkg/Include/ -I../../../EfiPkg/Include/ -include ../Include/Base.h DiskImage.c ../../Library/OcXmlLib/OcXmlLib.c ../../Library/OcTemplateLib/OcTemplateLib.c ../../Library/OcSerializeLib/OcSerializeLib.c ../../Library/OcMiscLib/Base64Decode.c ../../Library/OcStringLib/OcAsciiLib.c ../../Library/OcAppleDiskImageLib/OcAppleDiskImageLib.c ../../Library/OcAppleDiskImageLib/OcAppleDiskImageLibInternal.c ../../Library/OcMiscLib/DataPatcher.c ../../Library/OcCompressionLib/zlib/zlib_uefi.c ../../Library/OcCompressionLib/zlib/adler32.c ../../Library/OcCompressionLib/zlib/deflate.c ../../Library/OcCompressionLib/zlib/crc32.c ../../Library/OcCompressionLib/zlib/compress.c ../../Library/OcCompressionLib/zlib/infback.c ../../Library/OcCompressionLib/zlib/inffast.c ../../Library/OcCompressionLib/zlib/inflate.c ../../Library/OcCompressionLib/zlib/inftrees.c ../../Library/OcCompressionLib/zlib/trees.c ../../Library/OcCompressionLib/zlib/uncompr.c ../../Library/OcCryptoLib/Sha256.c ../../Library/OcCryptoLib/Rsa2048Sha256.c ../../Library/OcAppleKeysLib/OcAppleKeysLib.c ../../Library/OcAppleChunklistLib/OcAppleChunklistLib.c ../../Library/OcAppleRamDiskLib/OcAppleRamDiskLib.c../../Library/OcFileLib/ReadFile.c ../../Library/OcFileLib/FileProtocol.c -o DiskImage
rm -rf DICT fuzz*.log ; mkdir DICT ; UBSAN_OPTIONS='halt_on_error=1' ./DiskImage -jobs=4 DICT -rss_limit_mb=4096
**/
#ifdef FUZZING_TEST
#define main no_main
#include <sanitizer/asan_interface.h>
#else
#define ASAN_POISON_MEMORY_REGION(addr, size)
#define ASAN_UNPOISON_MEMORY_REGION(addr, size)
#endif
#if 0
#include <CommonCrypto/CommonDigest.h>
#endif
EFI_STATUS
TestImageLoad (
IN VOID *SourceBuffer,
IN UINTN SourceSize
)
{
EFI_STATUS Status;
IMAGE_STATUS ImageStatus;
PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
EFI_PHYSICAL_ADDRESS DestinationArea;
VOID *DestinationBuffer;
//
// Initialize the image context.
//
ImageStatus = OcPeCoffLoaderInitializeContext (
&ImageContext,
SourceBuffer,
SourceSize
);
if (ImageStatus != IMAGE_ERROR_SUCCESS) {
DEBUG ((DEBUG_INFO, "OCB: PeCoff init failure - %d\n", ImageStatus));
return EFI_UNSUPPORTED;
}
//
// Reject images that are not meant for the platform's architecture.
//
if (ImageContext.Machine != IMAGE_FILE_MACHINE_X64) {
DEBUG ((DEBUG_INFO, "OCB: PeCoff wrong machine - %x\n", ImageContext.Machine));
return EFI_UNSUPPORTED;
}
//
// Reject RT drivers for the moment.
//
if (ImageContext.Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {
DEBUG ((DEBUG_INFO, "OCB: PeCoff no support for RT drivers\n"));
return EFI_UNSUPPORTED;
}
//
// Allocate the image destination memory.
// FIXME: RT drivers require EfiRuntimeServicesCode.
//
Status = gBS->AllocatePages (
AllocateAnyPages,
EfiBootServicesCode,
EFI_SIZE_TO_PAGES (ImageContext.SizeOfImage),
&DestinationArea
);
if (EFI_ERROR (Status)) {
return Status;
}
DestinationBuffer = (VOID *)(UINTN) DestinationArea;
//
// Load SourceBuffer into DestinationBuffer.
//
ImageStatus = OcPeCoffLoaderLoadImage (
&ImageContext,
DestinationBuffer,
ImageContext.SizeOfImage
);
if (ImageStatus != IMAGE_ERROR_SUCCESS) {
DEBUG ((DEBUG_INFO, "OCB: PeCoff load image error - %d\n", ImageStatus));
FreePages (DestinationBuffer, EFI_SIZE_TO_PAGES (ImageContext.SizeOfImage));
return EFI_UNSUPPORTED;
}
//
// Relocate the loaded image to the destination address.
//
ImageStatus = OcPeCoffLoaderRelocateImage (
&ImageContext,
(UINTN) DestinationBuffer
);
FreePages (DestinationBuffer, EFI_SIZE_TO_PAGES (ImageContext.SizeOfImage));
if (ImageStatus != IMAGE_ERROR_SUCCESS) {
DEBUG ((DEBUG_INFO, "OCB: PeCoff relocate image error - %d\n", ImageStatus));
return EFI_UNSUPPORTED;
}
return EFI_SUCCESS;
}
int main (int argc, char *argv[]) {
if (argc < 2) {
printf ("Please provide a valid PE image path\n");
return -1;
}
PcdGet32 (PcdFixedDebugPrintErrorLevel) |= DEBUG_INFO;
PcdGet32 (PcdDebugPrintErrorLevel) |= DEBUG_INFO;
uint8_t *Image;
uint32_t ImageSize;
if ((Image = readFile (argv[1], &ImageSize)) == NULL) {
printf ("Read fail\n");
return 1;
}
EFI_STATUS Status = TestImageLoad (Image, ImageSize);
free(Image);
if (EFI_ERROR (Status)) {
return 1;
}
return 0;
}

View File

@ -14,6 +14,7 @@ buildutil() {
"TestImg4"
"TestKextInject"
"TestMacho"
"TestPeCoff"
"TestRsaPreprocess"
"TestSmbios"
)