diff --git a/UEFITool/uefitool.cpp b/UEFITool/uefitool.cpp index b4fcf36..a7fee01 100644 --- a/UEFITool/uefitool.cpp +++ b/UEFITool/uefitool.cpp @@ -17,7 +17,7 @@ UEFITool::UEFITool(QWidget *parent) : QMainWindow(parent), ui(new Ui::UEFITool), -version(tr("0.30.0_alpha27")) +version(tr("0.30.0_alpha28")) { clipboard = QApplication::clipboard(); diff --git a/common/ffs.h b/common/ffs.h index b4dec78..ade17b3 100644 --- a/common/ffs.h +++ b/common/ffs.h @@ -368,14 +368,24 @@ typedef struct EFI_COMMON_SECTION_HEADER_ { // Large file common section header typedef struct EFI_COMMON_SECTION_HEADER2_ { - UINT8 Size[3]; //Must be 0xFFFFFF for this header to be used + UINT8 Size[3]; // Must be 0xFFFFFF for this header to be used UINT8 Type; UINT32 ExtendedSize; } EFI_COMMON_SECTION_HEADER2; +// Apple common section header +typedef struct EFI_COMMON_SECTION_HEADER_APPLE { + UINT8 Size[3]; + UINT8 Type; + UINT32 Reserved; // Must be 0x7FFF for this header to be used +} EFI_COMMON_SECTION_HEADER_APPLE; + // Section2 usage indicator #define EFI_SECTION2_IS_USED 0xFFFFFF +// Apple section usage indicator +#define EFI_SECTION_APPLE_USED 0x7FFF + // File section types #define EFI_SECTION_ALL 0x00 // Impossible attribute for file in the FS @@ -398,23 +408,18 @@ typedef struct EFI_COMMON_SECTION_HEADER2_ { #define EFI_SECTION_PEI_DEPEX 0x1B #define EFI_SECTION_SMM_DEPEX 0x1C #define PHOENIX_SECTION_POSTCODE 0xF0 // Specific to Phoenix SCT images -#define INSYDE_SECTION_POSTCODE 0x20 // Specific to Insyde images +#define INSYDE_SECTION_POSTCODE 0x20 // Specific to Insyde H2O images // Compression section typedef struct EFI_COMPRESSION_SECTION_ { - UINT8 Size[3]; - UINT8 Type; UINT32 UncompressedLength; UINT8 CompressionType; } EFI_COMPRESSION_SECTION; -typedef struct EFI_COMPRESSION_SECTION2_ { - UINT8 Size[3]; - UINT8 Type; - UINT32 ExtendedSize; +typedef struct EFI_COMPRESSION_SECTION_APPLE_ { UINT32 UncompressedLength; - UINT8 CompressionType; -} EFI_COMPRESSION_SECTION2; + UINT32 CompressionType; +} EFI_COMPRESSION_SECTION_APPLE; // Compression types #define EFI_NOT_COMPRESSED 0x00 @@ -423,21 +428,17 @@ typedef struct EFI_COMPRESSION_SECTION2_ { //GUID defined section typedef struct EFI_GUID_DEFINED_SECTION_ { - UINT8 Size[3]; - UINT8 Type; EFI_GUID SectionDefinitionGuid; UINT16 DataOffset; UINT16 Attributes; } EFI_GUID_DEFINED_SECTION; -typedef struct EFI_GUID_DEFINED_SECTION2_ { - UINT8 Size[3]; - UINT8 Type; - UINT32 ExtendedSize; +typedef struct EFI_GUID_DEFINED_SECTION_APPLE_ { EFI_GUID SectionDefinitionGuid; UINT16 DataOffset; UINT16 Attributes; -} EFI_GUID_DEFINED_SECTION2; + UINT32 Reserved; +} EFI_GUID_DEFINED_SECTION_APPLE; // Attributes for GUID defined section #define EFI_GUIDED_SECTION_PROCESSING_REQUIRED 0x01 @@ -453,7 +454,7 @@ const QByteArray EFI_GUIDED_SECTION_TIANO // A31280AD-481E-41B6-95E8-127F4C98477 const QByteArray EFI_GUIDED_SECTION_LZMA // EE4E5898-3914-4259-9D6E-DC7BD79403CF ("\x98\x58\x4E\xEE\x14\x39\x59\x42\x9D\x6E\xDC\x7B\xD7\x94\x03\xCF", 16); -const QByteArray EFI_FIRMWARE_CONTENTS_SIGNED_GUID //0F9D89E8-9259-4F76-A5AF-0C89E34023DF +const QByteArray EFI_FIRMWARE_CONTENTS_SIGNED_GUID // 0F9D89E8-9259-4F76-A5AF-0C89E34023DF ("\xE8\x89\x9D\x0F\x59\x92\x76\x4F\xA5\xAF\x0C\x89\xE3\x40\x23\xDF", 16); //#define WIN_CERT_TYPE_PKCS_SIGNED_DATA 0x0002 @@ -475,8 +476,6 @@ typedef struct WIN_CERTIFICATE_UEFI_GUID_ { // WIN_CERTIFICATE_UEFI_GUID.CertType const QByteArray EFI_CERT_TYPE_RSA2048_SHA256_GUID ("\x14\x74\x71\xA7\x16\xC6\x77\x49\x94\x20\x84\x47\x12\xA7\x35\xBF"); -//const QByteArray EFI_CERT_TYPE_PKCS7_GUID -//("\x9D\xD2\xAF\x4A\xDF\x68\xEE\x49\x8A\xA9\x34\x7D\x37\x56\x65\xA7"); // WIN_CERTIFICATE_UEFI_GUID.CertData typedef struct EFI_CERT_BLOCK_RSA_2048_SHA256_ { @@ -487,70 +486,19 @@ typedef struct EFI_CERT_BLOCK_RSA_2048_SHA256_ { // Version section typedef struct EFI_VERSION_SECTION_ { - UINT8 Size[3]; - UINT8 Type; UINT16 BuildNumber; } EFI_VERSION_SECTION; -typedef struct EFI_VERSION_SECTION2_ { - UINT8 Size[3]; - UINT8 Type; - UINT32 ExtendedSize; - UINT16 BuildNumber; -} EFI_VERSION_SECTION2; - // Freeform subtype GUID section typedef struct EFI_FREEFORM_SUBTYPE_GUID_SECTION_ { - UINT8 Size[3]; - UINT8 Type; EFI_GUID SubTypeGuid; } EFI_FREEFORM_SUBTYPE_GUID_SECTION; -typedef struct EFI_FREEFORM_SUBTYPE_GUID_SECTION2_ { - UINT8 Size[3]; - UINT8 Type; - UINT32 ExtendedSize; - EFI_GUID SubTypeGuid; -} EFI_FREEFORM_SUBTYPE_GUID_SECTION2; - // Phoenix SCT and Insyde postcode section typedef struct POSTCODE_SECTION_ { - UINT8 Size[3]; - UINT8 Type; UINT32 Postcode; } POSTCODE_SECTION; -typedef struct POSTCODE_SECTION2_ { - UINT8 Size[3]; - UINT8 Type; - UINT32 ExtendedSize; - UINT32 Postcode; -} POSTCODE_SECTION2; - -// Other sections -typedef EFI_COMMON_SECTION_HEADER EFI_DISPOSABLE_SECTION; -typedef EFI_COMMON_SECTION_HEADER2 EFI_DISPOSABLE_SECTION2; -typedef EFI_COMMON_SECTION_HEADER EFI_RAW_SECTION; -typedef EFI_COMMON_SECTION_HEADER2 EFI_RAW_SECTION2; -typedef EFI_COMMON_SECTION_HEADER EFI_DXE_DEPEX_SECTION; -typedef EFI_COMMON_SECTION_HEADER2 EFI_DXE_DEPEX_SECTION2; -typedef EFI_COMMON_SECTION_HEADER EFI_PEI_DEPEX_SECTION; -typedef EFI_COMMON_SECTION_HEADER2 EFI_PEI_DEPEX_SECTION2; -typedef EFI_COMMON_SECTION_HEADER EFI_SMM_DEPEX_SECTION; -typedef EFI_COMMON_SECTION_HEADER2 EFI_SMM_DEPEX_SECTION2; -typedef EFI_COMMON_SECTION_HEADER EFI_PE32_SECTION; -typedef EFI_COMMON_SECTION_HEADER2 EFI_PE32_SECTION2; -typedef EFI_COMMON_SECTION_HEADER EFI_PIC_SECTION; -typedef EFI_COMMON_SECTION_HEADER2 EFI_PIC_SECTION2; -typedef EFI_COMMON_SECTION_HEADER EFI_TE_SECTION; -typedef EFI_COMMON_SECTION_HEADER2 EFI_TE_SECTION2; -typedef EFI_COMMON_SECTION_HEADER EFI_COMPATIBILITY16_SECTION; -typedef EFI_COMMON_SECTION_HEADER2 EFI_COMPATIBILITY16_SECTION2; -typedef EFI_COMMON_SECTION_HEADER EFI_FIRMWARE_VOLUME_IMAGE_SECTION; -typedef EFI_COMMON_SECTION_HEADER2 EFI_FIRMWARE_VOLUME_IMAGE_SECTION2; -typedef EFI_COMMON_SECTION_HEADER EFI_USER_INTERFACE_SECTION; -typedef EFI_COMMON_SECTION_HEADER2 EFI_USER_INTERFACE_SECTION2; - //***************************************************************************** // EFI Dependency Expression //***************************************************************************** diff --git a/common/ffsparser.cpp b/common/ffsparser.cpp index 3b68ebf..95ceb40 100644 --- a/common/ffsparser.cpp +++ b/common/ffsparser.cpp @@ -1870,23 +1870,37 @@ STATUS FfsParser::parseCommonSectionHeader(const QByteArray & section, const UIN // Check sanity if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER)) return ERR_INVALID_SECTION; - + // Get data from parent's parsing data PARSING_DATA pdata = parsingDataFromQModelIndex(parent); // Obtain header fields - const EFI_COMMON_SECTION_HEADER* sectionHeader = (const EFI_COMMON_SECTION_HEADER*)(section.constData()); - UINT32 headerSize = sizeof(EFI_COMMON_SECTION_HEADER); - if (pdata.ffsVersion == 3 && uint24ToUint32(sectionHeader->Size) == EFI_SECTION2_IS_USED) - headerSize = sizeof(EFI_COMMON_SECTION_HEADER2); + UINT32 headerSize; + UINT8 type; + const EFI_COMMON_SECTION_HEADER_APPLE* appleHeader = (const EFI_COMMON_SECTION_HEADER_APPLE*)(section.constData()); + if ((UINT32)section.size() >= sizeof(EFI_COMMON_SECTION_HEADER_APPLE) && appleHeader->Reserved == EFI_SECTION_APPLE_USED) { + headerSize = sizeof(EFI_COMMON_SECTION_HEADER_APPLE); + type = appleHeader->Type; + } + else { + const EFI_COMMON_SECTION_HEADER* sectionHeader = (const EFI_COMMON_SECTION_HEADER*)(section.constData()); + headerSize = sizeof(EFI_COMMON_SECTION_HEADER); + if (pdata.ffsVersion == 3 && uint24ToUint32(sectionHeader->Size) == EFI_SECTION2_IS_USED) + headerSize = sizeof(EFI_COMMON_SECTION_HEADER2); + type = sectionHeader->Type; + } + // Check sanity again + if ((UINT32)section.size() < headerSize) + return ERR_INVALID_SECTION; + QByteArray header = section.left(headerSize); QByteArray body = section.mid(headerSize); // Get info - QString name = sectionTypeToQString(sectionHeader->Type) + QObject::tr(" section"); + QString name = sectionTypeToQString(type) + QObject::tr(" section"); QString info = QObject::tr("Type: %1h\nFull size: %2h (%3)\nHeader size: %4h (%5)\nBody size: %6h (%7)") - .hexarg2(sectionHeader->Type, 2) + .hexarg2(type, 2) .hexarg(section.size()).arg(section.size()) .hexarg(headerSize).arg(headerSize) .hexarg(body.size()).arg(body.size()); @@ -1896,7 +1910,7 @@ STATUS FfsParser::parseCommonSectionHeader(const QByteArray & section, const UIN // Add tree item if (!preparse) { - index = model->addItem(Types::Section, sectionHeader->Type, name, QString(), info, header, body, QByteArray(), true, parsingDataToQByteArray(pdata), parent); + index = model->addItem(Types::Section, type, name, QString(), info, header, body, QByteArray(), true, parsingDataToQByteArray(pdata), parent); } return ERR_SUCCESS; } @@ -1904,27 +1918,45 @@ STATUS FfsParser::parseCommonSectionHeader(const QByteArray & section, const UIN STATUS FfsParser::parseCompressedSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index, const bool preparse) { // Check sanity - if ((UINT32)section.size() < sizeof(EFI_COMPRESSION_SECTION)) + if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER)) return ERR_INVALID_SECTION; // Get data from parent's parsing data PARSING_DATA pdata = parsingDataFromQModelIndex(parent); // Obtain header fields + UINT32 headerSize; + UINT8 compressionType; + UINT32 uncompressedLength; const EFI_COMMON_SECTION_HEADER* sectionHeader = (const EFI_COMMON_SECTION_HEADER*)(section.constData()); - const EFI_COMPRESSION_SECTION* compressedSectionHeader = (const EFI_COMPRESSION_SECTION*)sectionHeader; - UINT32 headerSize = sizeof(EFI_COMPRESSION_SECTION); - UINT8 compressionType = compressedSectionHeader->CompressionType; - UINT32 uncompressedLength = compressedSectionHeader->UncompressedLength; - if (pdata.ffsVersion == 3 && uint24ToUint32(sectionHeader->Size) == EFI_SECTION2_IS_USED) { - if ((UINT32)section.size() < sizeof(EFI_COMPRESSION_SECTION2)) + const EFI_COMMON_SECTION_HEADER2* section2Header = (const EFI_COMMON_SECTION_HEADER2*)(section.constData()); + const EFI_COMMON_SECTION_HEADER_APPLE* appleHeader = (const EFI_COMMON_SECTION_HEADER_APPLE*)(section.constData()); + + if ((UINT32)section.size() >= sizeof(EFI_COMMON_SECTION_HEADER_APPLE) && appleHeader->Reserved == EFI_SECTION_APPLE_USED) { // Check for apple section + const EFI_COMPRESSION_SECTION_APPLE* appleSectionHeader = (const EFI_COMPRESSION_SECTION_APPLE*)(appleHeader + 1); + headerSize = sizeof(EFI_COMMON_SECTION_HEADER_APPLE) + sizeof(EFI_COMPRESSION_SECTION_APPLE); + compressionType = (UINT8)appleSectionHeader->CompressionType; + uncompressedLength = appleSectionHeader->UncompressedLength; + } + else if (pdata.ffsVersion == 3 && uint24ToUint32(sectionHeader->Size) == EFI_SECTION2_IS_USED) { // Check for extended header section + const EFI_COMPRESSION_SECTION* compressedSectionHeader = (const EFI_COMPRESSION_SECTION*)(section2Header + 1); + if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER2) + sizeof(EFI_COMPRESSION_SECTION)) return ERR_INVALID_SECTION; - const EFI_COMPRESSION_SECTION2* compressedSectionHeader2 = (const EFI_COMPRESSION_SECTION2*)sectionHeader; - headerSize = sizeof(EFI_COMPRESSION_SECTION2); - compressionType = compressedSectionHeader2->CompressionType; + headerSize = sizeof(EFI_COMMON_SECTION_HEADER2) + sizeof(EFI_COMPRESSION_SECTION); + compressionType = compressedSectionHeader->CompressionType; + uncompressedLength = compressedSectionHeader->UncompressedLength; + } + else { // Normal section + const EFI_COMPRESSION_SECTION* compressedSectionHeader = (const EFI_COMPRESSION_SECTION*)(sectionHeader + 1); + headerSize = sizeof(EFI_COMMON_SECTION_HEADER) + sizeof(EFI_COMPRESSION_SECTION); + compressionType = compressedSectionHeader->CompressionType; uncompressedLength = compressedSectionHeader->UncompressedLength; } + // Check sanity again + if ((UINT32)section.size() < headerSize) + return ERR_INVALID_SECTION; + QByteArray header = section.left(headerSize); QByteArray body = section.mid(headerSize); @@ -1953,28 +1985,49 @@ STATUS FfsParser::parseCompressedSectionHeader(const QByteArray & section, const STATUS FfsParser::parseGuidedSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index, const bool preparse) { // Check sanity - if ((UINT32)section.size() < sizeof(EFI_GUID_DEFINED_SECTION)) + if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER)) return ERR_INVALID_SECTION; // Get data from parent's parsing data PARSING_DATA pdata = parsingDataFromQModelIndex(parent); // Obtain header fields + UINT32 headerSize; + EFI_GUID guid; + UINT16 dataOffset; + UINT16 attributes; const EFI_COMMON_SECTION_HEADER* sectionHeader = (const EFI_COMMON_SECTION_HEADER*)(section.constData()); - const EFI_GUID_DEFINED_SECTION* guidDefinedSectionHeader = (const EFI_GUID_DEFINED_SECTION*)sectionHeader; - EFI_GUID guid = guidDefinedSectionHeader->SectionDefinitionGuid; - UINT16 dataOffset = guidDefinedSectionHeader->DataOffset; - UINT16 attributes = guidDefinedSectionHeader->Attributes; - UINT32 nextHeaderOffset = sizeof(EFI_GUID_DEFINED_SECTION); - if (pdata.ffsVersion == 3 && uint24ToUint32(sectionHeader->Size) == EFI_SECTION2_IS_USED) { - if ((UINT32)section.size() < sizeof(EFI_GUID_DEFINED_SECTION2)) + const EFI_COMMON_SECTION_HEADER2* section2Header = (const EFI_COMMON_SECTION_HEADER2*)(section.constData()); + const EFI_COMMON_SECTION_HEADER_APPLE* appleHeader = (const EFI_COMMON_SECTION_HEADER_APPLE*)(section.constData()); + + if ((UINT32)section.size() >= sizeof(EFI_COMMON_SECTION_HEADER_APPLE) && appleHeader->Reserved == EFI_SECTION_APPLE_USED) { // Check for apple section + const EFI_GUID_DEFINED_SECTION_APPLE* appleSectionHeader = (const EFI_GUID_DEFINED_SECTION_APPLE*)(appleHeader + 1); + headerSize = sizeof(EFI_COMMON_SECTION_HEADER_APPLE) + sizeof(EFI_GUID_DEFINED_SECTION_APPLE); + if ((UINT32)section.size() < headerSize) return ERR_INVALID_SECTION; - const EFI_GUID_DEFINED_SECTION2* guidDefinedSectionHeader2 = (const EFI_GUID_DEFINED_SECTION2*)sectionHeader; - guid = guidDefinedSectionHeader2->SectionDefinitionGuid; - dataOffset = guidDefinedSectionHeader2->DataOffset; - attributes = guidDefinedSectionHeader2->Attributes; - nextHeaderOffset = sizeof(EFI_GUID_DEFINED_SECTION2); + guid = appleSectionHeader->SectionDefinitionGuid; + dataOffset = appleSectionHeader->DataOffset; + attributes = appleSectionHeader->Attributes; } + else if (pdata.ffsVersion == 3 && uint24ToUint32(sectionHeader->Size) == EFI_SECTION2_IS_USED) { // Check for extended header section + const EFI_GUID_DEFINED_SECTION* guidDefinedSectionHeader = (const EFI_GUID_DEFINED_SECTION*)(section2Header + 1); + if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER2) + sizeof(EFI_GUID_DEFINED_SECTION)) + return ERR_INVALID_SECTION; + headerSize = sizeof(EFI_COMMON_SECTION_HEADER2) + sizeof(EFI_GUID_DEFINED_SECTION); + guid = guidDefinedSectionHeader->SectionDefinitionGuid; + dataOffset = guidDefinedSectionHeader->DataOffset; + attributes = guidDefinedSectionHeader->Attributes; + } + else { // Normal section + const EFI_GUID_DEFINED_SECTION* guidDefinedSectionHeader = (const EFI_GUID_DEFINED_SECTION*)(sectionHeader + 1); + headerSize = sizeof(EFI_COMMON_SECTION_HEADER) + sizeof(EFI_GUID_DEFINED_SECTION); + guid = guidDefinedSectionHeader->SectionDefinitionGuid; + dataOffset = guidDefinedSectionHeader->DataOffset; + attributes = guidDefinedSectionHeader->Attributes; + } + // Check sanity again + if ((UINT32)section.size() < headerSize) + return ERR_INVALID_SECTION; // Check for special GUIDed sections QByteArray additionalInfo; @@ -1991,10 +2044,10 @@ STATUS FfsParser::parseGuidedSectionHeader(const QByteArray & section, const UIN msgNoAuthStatusAttribute = true; } - if ((UINT32)section.size() < nextHeaderOffset + sizeof(UINT32)) + if ((UINT32)section.size() < headerSize + sizeof(UINT32)) return ERR_INVALID_SECTION; - UINT32 crc = *(UINT32*)(section.constData() + nextHeaderOffset); + UINT32 crc = *(UINT32*)(section.constData() + headerSize); additionalInfo += QObject::tr("\nChecksum type: CRC32"); // Calculate CRC32 of section data UINT32 calculated = crc32(0, (const UINT8*)section.constData() + dataOffset, section.size() - dataOffset); @@ -2019,10 +2072,10 @@ STATUS FfsParser::parseGuidedSectionHeader(const QByteArray & section, const UIN } // Get certificate type and length - if ((UINT32)section.size() < nextHeaderOffset + sizeof(WIN_CERTIFICATE)) + if ((UINT32)section.size() < headerSize + sizeof(WIN_CERTIFICATE)) return ERR_INVALID_SECTION; - const WIN_CERTIFICATE* winCertificate = (const WIN_CERTIFICATE*)(section.constData() + nextHeaderOffset); + const WIN_CERTIFICATE* winCertificate = (const WIN_CERTIFICATE*)(section.constData() + headerSize); UINT32 certLength = winCertificate->Length; UINT16 certType = winCertificate->CertificateType; @@ -2038,7 +2091,7 @@ STATUS FfsParser::parseGuidedSectionHeader(const QByteArray & section, const UIN additionalInfo += QObject::tr("\nCertificate type: UEFI"); // Get certificate GUID - const WIN_CERTIFICATE_UEFI_GUID* winCertificateUefiGuid = (const WIN_CERTIFICATE_UEFI_GUID*)(section.constData() + nextHeaderOffset); + const WIN_CERTIFICATE_UEFI_GUID* winCertificateUefiGuid = (const WIN_CERTIFICATE_UEFI_GUID*)(section.constData() + headerSize); QByteArray certTypeGuid((const char*)&winCertificateUefiGuid->CertType, sizeof(EFI_GUID)); if (certTypeGuid == EFI_CERT_TYPE_RSA2048_SHA256_GUID) { @@ -2104,32 +2157,52 @@ STATUS FfsParser::parseGuidedSectionHeader(const QByteArray & section, const UIN STATUS FfsParser::parseFreeformGuidedSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index, const bool preparse) { // Check sanity - if ((UINT32)section.size() < sizeof(EFI_FREEFORM_SUBTYPE_GUID_SECTION)) + if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER)) return ERR_INVALID_SECTION; // Get data from parent's parsing data PARSING_DATA pdata = parsingDataFromQModelIndex(parent); // Obtain header fields + UINT32 headerSize; + EFI_GUID guid; + UINT8 type; const EFI_COMMON_SECTION_HEADER* sectionHeader = (const EFI_COMMON_SECTION_HEADER*)(section.constData()); - const EFI_FREEFORM_SUBTYPE_GUID_SECTION* fsgHeader = (const EFI_FREEFORM_SUBTYPE_GUID_SECTION*)sectionHeader; - UINT32 headerSize = sizeof(EFI_FREEFORM_SUBTYPE_GUID_SECTION); - EFI_GUID guid = fsgHeader->SubTypeGuid; - if (pdata.ffsVersion == 3 && uint24ToUint32(sectionHeader->Size) == EFI_SECTION2_IS_USED) { - if ((UINT32)section.size() < sizeof(EFI_FREEFORM_SUBTYPE_GUID_SECTION2)) - return ERR_INVALID_SECTION; - const EFI_FREEFORM_SUBTYPE_GUID_SECTION2* fsgHeader2 = (const EFI_FREEFORM_SUBTYPE_GUID_SECTION2*)sectionHeader; - headerSize = sizeof(EFI_FREEFORM_SUBTYPE_GUID_SECTION2); - guid = fsgHeader2->SubTypeGuid; + const EFI_COMMON_SECTION_HEADER2* section2Header = (const EFI_COMMON_SECTION_HEADER2*)(section.constData()); + const EFI_COMMON_SECTION_HEADER_APPLE* appleHeader = (const EFI_COMMON_SECTION_HEADER_APPLE*)(section.constData()); + + if ((UINT32)section.size() >= sizeof(EFI_COMMON_SECTION_HEADER_APPLE) && appleHeader->Reserved == EFI_SECTION_APPLE_USED) { // Check for apple section + const EFI_FREEFORM_SUBTYPE_GUID_SECTION* appleSectionHeader = (const EFI_FREEFORM_SUBTYPE_GUID_SECTION*)(appleHeader + 1); + headerSize = sizeof(EFI_COMMON_SECTION_HEADER_APPLE) + sizeof(EFI_FREEFORM_SUBTYPE_GUID_SECTION); + guid = appleSectionHeader->SubTypeGuid; + type = appleHeader->Type; } + else if (pdata.ffsVersion == 3 && uint24ToUint32(sectionHeader->Size) == EFI_SECTION2_IS_USED) { // Check for extended header section + const EFI_FREEFORM_SUBTYPE_GUID_SECTION* fsgSectionHeader = (const EFI_FREEFORM_SUBTYPE_GUID_SECTION*)(section2Header + 1); + if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER2) + sizeof(EFI_FREEFORM_SUBTYPE_GUID_SECTION)) + return ERR_INVALID_SECTION; + headerSize = sizeof(EFI_COMMON_SECTION_HEADER2) + sizeof(EFI_FREEFORM_SUBTYPE_GUID_SECTION); + guid = fsgSectionHeader->SubTypeGuid; + type = section2Header->Type; + } + else { // Normal section + const EFI_FREEFORM_SUBTYPE_GUID_SECTION* fsgSectionHeader = (const EFI_FREEFORM_SUBTYPE_GUID_SECTION*)(sectionHeader + 1); + headerSize = sizeof(EFI_COMMON_SECTION_HEADER) + sizeof(EFI_FREEFORM_SUBTYPE_GUID_SECTION); + guid = fsgSectionHeader->SubTypeGuid; + type = sectionHeader->Type; + } + + // Check sanity again + if ((UINT32)section.size() < headerSize) + return ERR_INVALID_SECTION; QByteArray header = section.left(headerSize); QByteArray body = section.mid(headerSize); // Get info - QString name = sectionTypeToQString(sectionHeader->Type) + QObject::tr(" section"); + QString name = sectionTypeToQString(type) + QObject::tr(" section"); QString info = QObject::tr("Type: %1h\nFull size: %2h (%3)\nHeader size: %4h (%5)\nBody size: %6h (%7)\nSubtype GUID: %8") - .hexarg2(fsgHeader->Type, 2) + .hexarg2(type, 2) .hexarg(section.size()).arg(section.size()) .hexarg(header.size()).arg(header.size()) .hexarg(body.size()).arg(body.size()) @@ -2141,7 +2214,7 @@ STATUS FfsParser::parseFreeformGuidedSectionHeader(const QByteArray & section, c // Add tree item if (!preparse) { - index = model->addItem(Types::Section, sectionHeader->Type, name, QString(), info, header, body, QByteArray(), false, parsingDataToQByteArray(pdata), parent); + index = model->addItem(Types::Section, type, name, QString(), info, header, body, QByteArray(), false, parsingDataToQByteArray(pdata), parent); // Rename section model->setName(index, guidToQString(guid)); @@ -2152,32 +2225,50 @@ STATUS FfsParser::parseFreeformGuidedSectionHeader(const QByteArray & section, c STATUS FfsParser::parseVersionSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index, const bool preparse) { // Check sanity - if ((UINT32)section.size() < sizeof(EFI_VERSION_SECTION)) + if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER)) return ERR_INVALID_SECTION; // Get data from parent's parsing data PARSING_DATA pdata = parsingDataFromQModelIndex(parent); // Obtain header fields + UINT32 headerSize; + UINT16 buildNumber; + UINT8 type; const EFI_COMMON_SECTION_HEADER* sectionHeader = (const EFI_COMMON_SECTION_HEADER*)(section.constData()); - const EFI_VERSION_SECTION* versionHeader = (const EFI_VERSION_SECTION*)sectionHeader; - UINT32 headerSize = sizeof(EFI_VERSION_SECTION); - UINT16 buildNumber = versionHeader->BuildNumber; - if (pdata.ffsVersion == 3 && uint24ToUint32(sectionHeader->Size) == EFI_SECTION2_IS_USED) { - if ((UINT32)section.size() < sizeof(EFI_VERSION_SECTION2)) - return ERR_INVALID_SECTION; - const EFI_VERSION_SECTION2* versionHeader2 = (const EFI_VERSION_SECTION2*)sectionHeader; - headerSize = sizeof(EFI_VERSION_SECTION2); - buildNumber = versionHeader2->BuildNumber; + const EFI_COMMON_SECTION_HEADER2* section2Header = (const EFI_COMMON_SECTION_HEADER2*)(section.constData()); + const EFI_COMMON_SECTION_HEADER_APPLE* appleHeader = (const EFI_COMMON_SECTION_HEADER_APPLE*)(section.constData()); + + if ((UINT32)section.size() >= sizeof(EFI_COMMON_SECTION_HEADER_APPLE) && appleHeader->Reserved == EFI_SECTION_APPLE_USED) { // Check for apple section + const EFI_VERSION_SECTION* versionHeader = (const EFI_VERSION_SECTION*)(appleHeader + 1); + headerSize = sizeof(EFI_COMMON_SECTION_HEADER_APPLE) + sizeof(EFI_VERSION_SECTION); + buildNumber = versionHeader->BuildNumber; + type = appleHeader->Type; } + else if (pdata.ffsVersion == 3 && uint24ToUint32(sectionHeader->Size) == EFI_SECTION2_IS_USED) { // Check for extended header section + const EFI_VERSION_SECTION* versionHeader = (const EFI_VERSION_SECTION*)(section2Header + 1); + headerSize = sizeof(EFI_COMMON_SECTION_HEADER2) + sizeof(EFI_VERSION_SECTION); + buildNumber = versionHeader->BuildNumber; + type = section2Header->Type; + } + else { // Normal section + const EFI_VERSION_SECTION* versionHeader = (const EFI_VERSION_SECTION*)(sectionHeader + 1); + headerSize = sizeof(EFI_COMMON_SECTION_HEADER) + sizeof(EFI_VERSION_SECTION); + buildNumber = versionHeader->BuildNumber; + type = sectionHeader->Type; + } + + // Check sanity again + if ((UINT32)section.size() < headerSize) + return ERR_INVALID_SECTION; QByteArray header = section.left(headerSize); QByteArray body = section.mid(headerSize); // Get info - QString name = sectionTypeToQString(sectionHeader->Type) + QObject::tr(" section"); + QString name = sectionTypeToQString(type) + QObject::tr(" section"); QString info = QObject::tr("Type: %1h\nFull size: %2h (%3)\nHeader size: %4h (%5)\nBody size: %6h (%7)\nBuild number: %8") - .hexarg2(versionHeader->Type, 2) + .hexarg2(type, 2) .hexarg(section.size()).arg(section.size()) .hexarg(header.size()).arg(header.size()) .hexarg(body.size()).arg(body.size()) @@ -2188,7 +2279,7 @@ STATUS FfsParser::parseVersionSectionHeader(const QByteArray & section, const UI // Add tree item if (!preparse) { - index = model->addItem(Types::Section, sectionHeader->Type, name, QString(), info, header, body, QByteArray(), false, parsingDataToQByteArray(pdata), parent); + index = model->addItem(Types::Section, type, name, QString(), info, header, body, QByteArray(), false, parsingDataToQByteArray(pdata), parent); } return ERR_SUCCESS; } @@ -2196,32 +2287,50 @@ STATUS FfsParser::parseVersionSectionHeader(const QByteArray & section, const UI STATUS FfsParser::parsePostcodeSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index, const bool preparse) { // Check sanity - if ((UINT32)section.size() < sizeof(POSTCODE_SECTION)) + if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER)) return ERR_INVALID_SECTION; // Get data from parent's parsing data PARSING_DATA pdata = parsingDataFromQModelIndex(parent); // Obtain header fields + UINT32 headerSize; + UINT32 postCode; + UINT8 type; const EFI_COMMON_SECTION_HEADER* sectionHeader = (const EFI_COMMON_SECTION_HEADER*)(section.constData()); - const POSTCODE_SECTION* postcodeHeader = (const POSTCODE_SECTION*)sectionHeader; - UINT32 headerSize = sizeof(POSTCODE_SECTION); - UINT32 postCode = postcodeHeader->Postcode; - if (pdata.ffsVersion == 3 && uint24ToUint32(sectionHeader->Size) == EFI_SECTION2_IS_USED) { - if ((UINT32)section.size() < sizeof(POSTCODE_SECTION2)) - return ERR_INVALID_SECTION; - const POSTCODE_SECTION2* postcodeHeader2 = (const POSTCODE_SECTION2*)sectionHeader; - headerSize = sizeof(POSTCODE_SECTION2); - postCode = postcodeHeader2->Postcode; + const EFI_COMMON_SECTION_HEADER2* section2Header = (const EFI_COMMON_SECTION_HEADER2*)(section.constData()); + const EFI_COMMON_SECTION_HEADER_APPLE* appleHeader = (const EFI_COMMON_SECTION_HEADER_APPLE*)(section.constData()); + + if ((UINT32)section.size() >= sizeof(EFI_COMMON_SECTION_HEADER_APPLE) && appleHeader->Reserved == EFI_SECTION_APPLE_USED) { // Check for apple section + const POSTCODE_SECTION* postcodeHeader = (const POSTCODE_SECTION*)(appleHeader + 1); + headerSize = sizeof(EFI_COMMON_SECTION_HEADER_APPLE) + sizeof(POSTCODE_SECTION); + postCode = postcodeHeader->Postcode; + type = appleHeader->Type; } + else if (pdata.ffsVersion == 3 && uint24ToUint32(sectionHeader->Size) == EFI_SECTION2_IS_USED) { // Check for extended header section + const POSTCODE_SECTION* postcodeHeader = (const POSTCODE_SECTION*)(section2Header + 1); + headerSize = sizeof(EFI_COMMON_SECTION_HEADER2) + sizeof(POSTCODE_SECTION); + postCode = postcodeHeader->Postcode; + type = section2Header->Type; + } + else { // Normal section + const POSTCODE_SECTION* postcodeHeader = (const POSTCODE_SECTION*)(sectionHeader + 1); + headerSize = sizeof(EFI_COMMON_SECTION_HEADER) + sizeof(POSTCODE_SECTION); + postCode = postcodeHeader->Postcode; + type = sectionHeader->Type; + } + + // Check sanity again + if ((UINT32)section.size() < headerSize) + return ERR_INVALID_SECTION; QByteArray header = section.left(headerSize); QByteArray body = section.mid(headerSize); // Get info - QString name = sectionTypeToQString(sectionHeader->Type) + QObject::tr(" section"); + QString name = sectionTypeToQString(type) + QObject::tr(" section"); QString info = QObject::tr("Type: %1h\nFull size: %2h (%3)\nHeader size: %4h (%5)\nBody size: %6h (%7)\nPostcode: %8h") - .hexarg2(postcodeHeader->Type, 2) + .hexarg2(type, 2) .hexarg(section.size()).arg(section.size()) .hexarg(header.size()).arg(header.size()) .hexarg(body.size()).arg(body.size()) diff --git a/common/peimage.cpp b/common/peimage.cpp index c0f81a6..47f3d70 100644 --- a/common/peimage.cpp +++ b/common/peimage.cpp @@ -18,16 +18,20 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. QString machineTypeToQString(UINT16 machineType) { switch (machineType) { - case EFI_IMAGE_FILE_MACHINE_AMD64: return QObject::tr("x86-64"); - case EFI_IMAGE_FILE_MACHINE_ARM: return QObject::tr("ARM"); - case EFI_IMAGE_FILE_MACHINE_ARMNT: return QObject::tr("ARMv7"); - case EFI_IMAGE_FILE_MACHINE_ARM64: return QObject::tr("ARM64"); - case EFI_IMAGE_FILE_MACHINE_EBC: return QObject::tr("EBC"); - case EFI_IMAGE_FILE_MACHINE_I386: return QObject::tr("x86"); - case EFI_IMAGE_FILE_MACHINE_IA64: return QObject::tr("IA64"); - case EFI_IMAGE_FILE_MACHINE_POWERPC: return QObject::tr("PowerPC"); - case EFI_IMAGE_FILE_MACHINE_POWERPCFP: return QObject::tr("PowerPC FP"); - case EFI_IMAGE_FILE_MACHINE_THUMB: return QObject::tr("Thumb"); - default: return QObject::tr("Unknown %1h").hexarg2(machineType, 4); + case EFI_IMAGE_FILE_MACHINE_AMD64: return QObject::tr("x86-64"); + case EFI_IMAGE_FILE_MACHINE_ARM: return QObject::tr("ARM"); + case EFI_IMAGE_FILE_MACHINE_ARMNT: return QObject::tr("ARMv7"); + case EFI_IMAGE_FILE_MACHINE_APPLE_ARM: return QObject::tr("Apple ARM"); + case EFI_IMAGE_FILE_MACHINE_AARCH64: return QObject::tr("AARCH64"); + case EFI_IMAGE_FILE_MACHINE_EBC: return QObject::tr("EBC"); + case EFI_IMAGE_FILE_MACHINE_I386: return QObject::tr("x86"); + case EFI_IMAGE_FILE_MACHINE_IA64: return QObject::tr("IA64"); + case EFI_IMAGE_FILE_MACHINE_POWERPC: return QObject::tr("PowerPC"); + case EFI_IMAGE_FILE_MACHINE_POWERPCFP: return QObject::tr("PowerPC FP"); + case EFI_IMAGE_FILE_MACHINE_THUMB: return QObject::tr("ARM Thumb"); + case EFI_IMAGE_FILE_MACHINE_RISCV32: return QObject::tr("RISC-V 32-bit"); + case EFI_IMAGE_FILE_MACHINE_RISCV64: return QObject::tr("RISC-V 64-bit"); + case EFI_IMAGE_FILE_MACHINE_RISCV128: return QObject::tr("RISC-V 128-bit"); + default: return QObject::tr("Unknown %1h").hexarg2(machineType, 4); } } \ No newline at end of file diff --git a/common/peimage.h b/common/peimage.h index 0d0260b..5eaa44a 100644 --- a/common/peimage.h +++ b/common/peimage.h @@ -1,726 +1,737 @@ -/* peimage.h - -Copyright (c) 2015, Nikolaj Schlej. All rights reserved. -Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved. -Portions copyright (c) 2008 - 2009, Apple Inc. 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. - -*/ - -#ifndef PEIMAGE_H -#define PEIMAGE_H - -#include -#include "basetypes.h" - -extern QString machineTypeToQString(UINT16 machineType); - -// Make sure we use right packing rules -#pragma pack(push, 1) - -// -// 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 - -// -// PE32+ Machine type for EFI images -// -#define EFI_IMAGE_FILE_MACHINE_I386 0x014c // x86 -#define EFI_IMAGE_FILE_MACHINE_ARM 0x01c0 // ARM little endian -#define EFI_IMAGE_FILE_MACHINE_THUMB 0x01c2 // ARM or Thumb (interworking) -#define EFI_IMAGE_FILE_MACHINE_ARMNT 0x01c4 // ARMv7 (or higher) Thumb mode only -#define EFI_IMAGE_FILE_MACHINE_POWERPC 0x01f0 // Power PC little endian -#define EFI_IMAGE_FILE_MACHINE_POWERPCFP 0x01f1 // Power PC with floating point support -#define EFI_IMAGE_FILE_MACHINE_IA64 0x0200 // Itanium -#define EFI_IMAGE_FILE_MACHINE_EBC 0x0ebc // EFI Byte Code -#define EFI_IMAGE_FILE_MACHINE_AMD64 0x8664 // x86-64 -#define EFI_IMAGE_FILE_MACHINE_ARM64 0xaa64 // ARMv8 in 64-bit mode - -// -// EXE file formats -// -#define EFI_IMAGE_DOS_SIGNATURE 0x5A4D // MZ -#define EFI_IMAGE_PE_SIGNATURE 0x00004550 // PE - -// -// 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 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 0x0001 // Relocation info stripped from file -#define EFI_IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 // File is executable (i.e. no unresolved external references) -#define EFI_IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line numbers stripped from file -#define EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 // Local symbols stripped from file -#define EFI_IMAGE_FILE_BYTES_REVERSED_LO 0x0080 // Bytes of machine word are reversed -#define EFI_IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine -#define EFI_IMAGE_FILE_DEBUG_STRIPPED 0x0200 // Debugging info stripped from file in .DBG file -#define EFI_IMAGE_FILE_SYSTEM 0x1000 // System File -#define EFI_IMAGE_FILE_DLL 0x2000 // File is a DLL -#define EFI_IMAGE_FILE_BYTES_REVERSED_HI 0x8000 // Bytes of machine word are reversed - -// -// 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 - -// -// 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_PE_OPTIONAL_HDR32_MAGIC 0x10b - -// -// Optional Header Standard Fields for PE32 -// -typedef struct { - // - // 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_NUMBER_OF_DIRECTORY_ENTRIES]; -} EFI_IMAGE_OPTIONAL_HEADER32; - -// -// 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_PE_OPTIONAL_HDR64_MAGIC 0x20b - -// -// Optional Header Standard Fields for PE32+. -// -typedef struct { - // - // 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_NUMBER_OF_DIRECTORY_ENTRIES]; -} EFI_IMAGE_OPTIONAL_HEADER64; - -// Union for pointers to either PE32 or PE32+ headers -typedef union _EFI_IMAGE_OPTIONAL_HEADER_POINTERS_UNION { - const EFI_IMAGE_OPTIONAL_HEADER32* H32; - const EFI_IMAGE_OPTIONAL_HEADER64* H64; -} EFI_IMAGE_OPTIONAL_HEADER_POINTERS_UNION; - -typedef struct -{ - UINT32 Signature; - //EFI_IMAGE_FILE_HEADER FileHeader; - //EFI_IMAGE_OPTIONAL_HEADER OptionalHeader; -} EFI_IMAGE_PE_HEADER; - -// -// 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]; - union { - UINT32 PhysicalAddress; - UINT32 VirtualSize; - } Misc; - UINT32 VirtualAddress; - UINT32 SizeOfRawData; - UINT32 PointerToRawData; - UINT32 PointerToRelocations; - UINT32 PointerToLinenumbers; - UINT16 NumberOfRelocations; - UINT16 NumberOfLinenumbers; - UINT32 Characteristics; -} EFI_IMAGE_SECTION_HEADER; - -// -// Size of EFI_IMAGE_SECTION_HEADER -// -#define EFI_IMAGE_SIZEOF_SECTION_HEADER 40 - -// -// Section Flags Values -// -#define EFI_IMAGE_SCN_TYPE_NO_PAD 0x00000008 // Reserved -#define EFI_IMAGE_SCN_CNT_CODE 0x00000020 -#define EFI_IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 -#define EFI_IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 - -#define EFI_IMAGE_SCN_LNK_OTHER 0x00000100 // Reserved -#define EFI_IMAGE_SCN_LNK_INFO 0x00000200 // Section contains comments or some other type of information -#define EFI_IMAGE_SCN_LNK_REMOVE 0x00000800 // Section contents will not become part of image -#define EFI_IMAGE_SCN_LNK_COMDAT 0x00001000 - -#define EFI_IMAGE_SCN_ALIGN_1BYTES 0x00100000 -#define EFI_IMAGE_SCN_ALIGN_2BYTES 0x00200000 -#define EFI_IMAGE_SCN_ALIGN_4BYTES 0x00300000 -#define EFI_IMAGE_SCN_ALIGN_8BYTES 0x00400000 -#define EFI_IMAGE_SCN_ALIGN_16BYTES 0x00500000 -#define EFI_IMAGE_SCN_ALIGN_32BYTES 0x00600000 -#define EFI_IMAGE_SCN_ALIGN_64BYTES 0x00700000 - -#define EFI_IMAGE_SCN_MEM_DISCARDABLE 0x02000000 -#define EFI_IMAGE_SCN_MEM_NOT_CACHED 0x04000000 -#define EFI_IMAGE_SCN_MEM_NOT_PAGED 0x08000000 -#define EFI_IMAGE_SCN_MEM_SHARED 0x10000000 -#define EFI_IMAGE_SCN_MEM_EXECUTE 0x20000000 -#define EFI_IMAGE_SCN_MEM_READ 0x40000000 -#define EFI_IMAGE_SCN_MEM_WRITE 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 EFI_IMAGE_REL_AMD64_ABSOLUTE 0x0000 -#define EFI_IMAGE_REL_AMD64_ADDR64 0x0001 -#define EFI_IMAGE_REL_AMD64_ADDR32 0x0002 -#define EFI_IMAGE_REL_AMD64_ADDR32NB 0x0003 -#define EFI_IMAGE_REL_AMD64_REL32 0x0004 -#define EFI_IMAGE_REL_AMD64_REL32_1 0x0005 -#define EFI_IMAGE_REL_AMD64_REL32_2 0x0006 -#define EFI_IMAGE_REL_AMD64_REL32_3 0x0007 -#define EFI_IMAGE_REL_AMD64_REL32_4 0x0008 -#define EFI_IMAGE_REL_AMD64_REL32_5 0x0009 -#define EFI_IMAGE_REL_AMD64_SECTION 0x000A -#define EFI_IMAGE_REL_AMD64_SECREL 0x000B -#define EFI_IMAGE_REL_AMD64_SECREL7 0x000C -#define EFI_IMAGE_REL_AMD64_TOKEN 0x000D -#define EFI_IMAGE_REL_AMD64_SREL32 0x000E -#define EFI_IMAGE_REL_AMD64_PAIR 0x000F -#define EFI_IMAGE_REL_AMD64_SSPAN32 0x0010 - -// -// Based relocation format -// -typedef struct { - UINT32 VirtualAddress; - UINT32 SizeOfBlock; -} 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 line number 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 "!\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 0x80000000 // 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 0x3031424E // NB10 -typedef struct { - UINT32 Signature; - 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 0x53445352 // RSDS -typedef struct { - UINT32 Signature; - 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 0x434F544D // MTOC -typedef struct { - UINT32 Signature; - UINT8 MachOUuid[16]; - // - // Filename of .DLL (Mach-O with debug info) goes here - // -} EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY; - -// -// Resource format -// -typedef struct { - UINT32 Characteristics; - UINT32 TimeDateStamp; - UINT16 MajorVersion; - UINT16 MinorVersion; - UINT16 NumberOfNamedEntries; - UINT16 NumberOfIdEntries; - // - // Array of EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY entries goes here - // -} EFI_IMAGE_RESOURCE_DIRECTORY; - -// -// 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 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 original file header - UINT8 NumberOfSections; // From original file header - UINT8 Subsystem; // From original optional header - UINT16 StrippedSize; // Number of bytes we removed from 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_IMAGE_TE_HEADER; - -#define EFI_IMAGE_TE_SIGNATURE 0x5A56 // VZ - -// -// Data directory indexes in our TE image header -// -#define EFI_IMAGE_TE_DIRECTORY_ENTRY_BASERELOC 0 -#define EFI_IMAGE_TE_DIRECTORY_ENTRY_DEBUG 1 - -// Restore previous packing rules -#pragma pack(pop) -#endif // PEIMAGE_H +/* peimage.h + +Copyright (c) 2015, Nikolaj Schlej. All rights reserved. +Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved. +Portions copyright (c) 2008 - 2009, Apple Inc. 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. + +*/ + +#ifndef PEIMAGE_H +#define PEIMAGE_H + +#include +#include "basetypes.h" + +extern QString machineTypeToQString(UINT16 machineType); + +// Make sure we use right packing rules +#pragma pack(push, 1) + +// +// 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 + +// +// PE32+ Machine type for EFI images +// +#define EFI_IMAGE_FILE_MACHINE_I386 0x014c // x86 +#define EFI_IMAGE_FILE_MACHINE_ARM 0x01c0 // ARM little endian +#define EFI_IMAGE_FILE_MACHINE_THUMB 0x01c2 // ARM or Thumb (interworking) +#define EFI_IMAGE_FILE_MACHINE_ARMNT 0x01c4 // ARMv7 (or higher) Thumb mode only +#define EFI_IMAGE_FILE_MACHINE_APPLE_ARM 0x01c6 // Apple ARM +#define EFI_IMAGE_FILE_MACHINE_POWERPC 0x01f0 // Power PC little endian +#define EFI_IMAGE_FILE_MACHINE_POWERPCFP 0x01f1 // Power PC with floating point support +#define EFI_IMAGE_FILE_MACHINE_IA64 0x0200 // Itanium +#define EFI_IMAGE_FILE_MACHINE_EBC 0x0ebc // EFI Byte Code +#define EFI_IMAGE_FILE_MACHINE_AMD64 0x8664 // x86-64 +#define EFI_IMAGE_FILE_MACHINE_AARCH64 0xaa64 // ARMv8 in 64-bit mode +#define EFI_IMAGE_FILE_MACHINE_RISCV32 0x5032 // RISC-V 32-bit +#define EFI_IMAGE_FILE_MACHINE_RISCV64 0x5064 // RISC-V 64-bit +#define EFI_IMAGE_FILE_MACHINE_RISCV128 0x5128 // RISC-V 128-bit +// +// EXE file formats +// +#define EFI_IMAGE_DOS_SIGNATURE 0x5A4D // MZ +#define EFI_IMAGE_PE_SIGNATURE 0x00004550 // PE + +// +// 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 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 0x0001 // Relocation info stripped from file +#define EFI_IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 // File is executable (i.e. no unresolved external references) +#define EFI_IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line numbers stripped from file +#define EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 // Local symbols stripped from file +#define EFI_IMAGE_FILE_BYTES_REVERSED_LO 0x0080 // Bytes of machine word are reversed +#define EFI_IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine +#define EFI_IMAGE_FILE_DEBUG_STRIPPED 0x0200 // Debugging info stripped from file in .DBG file +#define EFI_IMAGE_FILE_SYSTEM 0x1000 // System File +#define EFI_IMAGE_FILE_DLL 0x2000 // File is a DLL +#define EFI_IMAGE_FILE_BYTES_REVERSED_HI 0x8000 // Bytes of machine word are reversed + +// +// 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 + +// +// 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_PE_OPTIONAL_HDR32_MAGIC 0x10b + +// +// Optional Header Standard Fields for PE32 +// +typedef struct { + // + // 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_NUMBER_OF_DIRECTORY_ENTRIES]; +} EFI_IMAGE_OPTIONAL_HEADER32; + +// +// 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_PE_OPTIONAL_HDR64_MAGIC 0x20b + +// +// Optional Header Standard Fields for PE32+. +// +typedef struct { + // + // 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_NUMBER_OF_DIRECTORY_ENTRIES]; +} EFI_IMAGE_OPTIONAL_HEADER64; + +// Union for pointers to either PE32 or PE32+ headers +typedef union _EFI_IMAGE_OPTIONAL_HEADER_POINTERS_UNION { + const EFI_IMAGE_OPTIONAL_HEADER32* H32; + const EFI_IMAGE_OPTIONAL_HEADER64* H64; +} EFI_IMAGE_OPTIONAL_HEADER_POINTERS_UNION; + +typedef struct +{ + UINT32 Signature; + //EFI_IMAGE_FILE_HEADER FileHeader; + //EFI_IMAGE_OPTIONAL_HEADER OptionalHeader; +} EFI_IMAGE_PE_HEADER; + +// +// 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]; + union { + UINT32 PhysicalAddress; + UINT32 VirtualSize; + } Misc; + UINT32 VirtualAddress; + UINT32 SizeOfRawData; + UINT32 PointerToRawData; + UINT32 PointerToRelocations; + UINT32 PointerToLinenumbers; + UINT16 NumberOfRelocations; + UINT16 NumberOfLinenumbers; + UINT32 Characteristics; +} EFI_IMAGE_SECTION_HEADER; + +// +// Size of EFI_IMAGE_SECTION_HEADER +// +#define EFI_IMAGE_SIZEOF_SECTION_HEADER 40 + +// +// Section Flags Values +// +#define EFI_IMAGE_SCN_TYPE_NO_PAD 0x00000008 // Reserved +#define EFI_IMAGE_SCN_CNT_CODE 0x00000020 +#define EFI_IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 +#define EFI_IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 + +#define EFI_IMAGE_SCN_LNK_OTHER 0x00000100 // Reserved +#define EFI_IMAGE_SCN_LNK_INFO 0x00000200 // Section contains comments or some other type of information +#define EFI_IMAGE_SCN_LNK_REMOVE 0x00000800 // Section contents will not become part of image +#define EFI_IMAGE_SCN_LNK_COMDAT 0x00001000 + +#define EFI_IMAGE_SCN_ALIGN_1BYTES 0x00100000 +#define EFI_IMAGE_SCN_ALIGN_2BYTES 0x00200000 +#define EFI_IMAGE_SCN_ALIGN_4BYTES 0x00300000 +#define EFI_IMAGE_SCN_ALIGN_8BYTES 0x00400000 +#define EFI_IMAGE_SCN_ALIGN_16BYTES 0x00500000 +#define EFI_IMAGE_SCN_ALIGN_32BYTES 0x00600000 +#define EFI_IMAGE_SCN_ALIGN_64BYTES 0x00700000 + +#define EFI_IMAGE_SCN_MEM_DISCARDABLE 0x02000000 +#define EFI_IMAGE_SCN_MEM_NOT_CACHED 0x04000000 +#define EFI_IMAGE_SCN_MEM_NOT_PAGED 0x08000000 +#define EFI_IMAGE_SCN_MEM_SHARED 0x10000000 +#define EFI_IMAGE_SCN_MEM_EXECUTE 0x20000000 +#define EFI_IMAGE_SCN_MEM_READ 0x40000000 +#define EFI_IMAGE_SCN_MEM_WRITE 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 relocation types +// +#define EFI_IMAGE_REL_AMD64_ABSOLUTE 0x0000 +#define EFI_IMAGE_REL_AMD64_ADDR64 0x0001 +#define EFI_IMAGE_REL_AMD64_ADDR32 0x0002 +#define EFI_IMAGE_REL_AMD64_ADDR32NB 0x0003 +#define EFI_IMAGE_REL_AMD64_REL32 0x0004 +#define EFI_IMAGE_REL_AMD64_REL32_1 0x0005 +#define EFI_IMAGE_REL_AMD64_REL32_2 0x0006 +#define EFI_IMAGE_REL_AMD64_REL32_3 0x0007 +#define EFI_IMAGE_REL_AMD64_REL32_4 0x0008 +#define EFI_IMAGE_REL_AMD64_REL32_5 0x0009 +#define EFI_IMAGE_REL_AMD64_SECTION 0x000A +#define EFI_IMAGE_REL_AMD64_SECREL 0x000B +#define EFI_IMAGE_REL_AMD64_SECREL7 0x000C +#define EFI_IMAGE_REL_AMD64_TOKEN 0x000D +#define EFI_IMAGE_REL_AMD64_SREL32 0x000E +#define EFI_IMAGE_REL_AMD64_PAIR 0x000F +#define EFI_IMAGE_REL_AMD64_SSPAN32 0x0010 + +// +// RISC-V relocation types +// +#define EFI_IMAGE_REL_BASED_RISCV_HI20 0x0005 +#define EFI_IMAGE_REL_BASED_RISCV_LO12I 0x0007 +#define EFI_IMAGE_REL_BASED_RISCV_LO12S 0x0008 + +// +// Based relocation format +// +typedef struct { + UINT32 VirtualAddress; + UINT32 SizeOfBlock; +} 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 line number 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 "!\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 0x80000000 // 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 0x3031424E // NB10 +typedef struct { + UINT32 Signature; + 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 0x53445352 // RSDS +typedef struct { + UINT32 Signature; + 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 0x434F544D // MTOC +typedef struct { + UINT32 Signature; + UINT8 MachOUuid[16]; + // + // Filename of .DLL (Mach-O with debug info) goes here + // +} EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY; + +// +// Resource format +// +typedef struct { + UINT32 Characteristics; + UINT32 TimeDateStamp; + UINT16 MajorVersion; + UINT16 MinorVersion; + UINT16 NumberOfNamedEntries; + UINT16 NumberOfIdEntries; + // + // Array of EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY entries goes here + // +} EFI_IMAGE_RESOURCE_DIRECTORY; + +// +// 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 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 original file header + UINT8 NumberOfSections; // From original file header + UINT8 Subsystem; // From original optional header + UINT16 StrippedSize; // Number of bytes we removed from 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_IMAGE_TE_HEADER; + +#define EFI_IMAGE_TE_SIGNATURE 0x5A56 // VZ + +// +// Data directory indexes in our TE image header +// +#define EFI_IMAGE_TE_DIRECTORY_ENTRY_BASERELOC 0 +#define EFI_IMAGE_TE_DIRECTORY_ENTRY_DEBUG 1 + +// Restore previous packing rules +#pragma pack(pop) +#endif // PEIMAGE_H