Add support for Apple-specific section headers

- and some new PE machine types
This commit is contained in:
Nikolaj Schlej 2016-05-04 19:41:03 +02:00
parent cd1cc09b39
commit 2d932da1f3
5 changed files with 955 additions and 883 deletions

View File

@ -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();

View File

@ -373,9 +373,19 @@ typedef struct EFI_COMMON_SECTION_HEADER2_ {
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
@ -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
//*****************************************************************************

View File

@ -1875,18 +1875,32 @@ STATUS FfsParser::parseCommonSectionHeader(const QByteArray & section, const UIN
PARSING_DATA pdata = parsingDataFromQModelIndex(parent);
// Obtain header fields
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());
UINT32 headerSize = sizeof(EFI_COMMON_SECTION_HEADER);
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,26 +1918,44 @@ 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())

View File

@ -21,13 +21,17 @@ QString machineTypeToQString(UINT16 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_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("Thumb");
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);
}
}

View File

@ -39,13 +39,16 @@ extern QString machineTypeToQString(UINT16 machineType);
#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_ARM64 0xaa64 // ARMv8 in 64-bit mode
#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
//
@ -439,8 +442,9 @@ typedef struct {
#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
// x64 relocation types
//
#define EFI_IMAGE_REL_AMD64_ABSOLUTE 0x0000
#define EFI_IMAGE_REL_AMD64_ADDR64 0x0001
@ -460,6 +464,13 @@ typedef struct {
#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
//