From fe56c5c84c1db302a1c083ffc70811d6547bbb97 Mon Sep 17 00:00:00 2001 From: Nikolaj Schlej Date: Sat, 16 Jul 2016 07:02:33 +0200 Subject: [PATCH] UT NE A32 - improved parsing of volume's non-UEFI data - improved detection of top-swap for TE images - other minor fixes --- common/ffs.h | 1 - common/ffsbuilder.h | 1 + common/ffsparser.cpp | 214 +++++++++++++++++-------------------------- common/ffsparser.h | 22 ++--- common/parsingdata.h | 2 +- common/peimage.h | 5 + 6 files changed, 102 insertions(+), 143 deletions(-) diff --git a/common/ffs.h b/common/ffs.h index 1c12ce6..34f8141 100644 --- a/common/ffs.h +++ b/common/ffs.h @@ -502,7 +502,6 @@ typedef struct POSTCODE_SECTION_ { //***************************************************************************** // EFI Dependency Expression //***************************************************************************** - #define EFI_DEP_OPCODE_SIZE 1 /// diff --git a/common/ffsbuilder.h b/common/ffsbuilder.h index 14bf3c0..0669ec2 100644 --- a/common/ffsbuilder.h +++ b/common/ffsbuilder.h @@ -22,6 +22,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "treemodel.h" #include "descriptor.h" #include "ffs.h" +#include "peimage.h" #include "utility.h" class FfsBuilder diff --git a/common/ffsparser.cpp b/common/ffsparser.cpp index 694d6ab..7d9939f 100644 --- a/common/ffsparser.cpp +++ b/common/ffsparser.cpp @@ -1034,25 +1034,7 @@ USTATUS FfsParser::parseVolumeHeader(const UByteArray & volume, const UINT32 par msgAlignmentBitsSet = true; } // Do not check for volume alignment on revision 1 volumes - // No one gives a single crap about setting it correctly - /*else { - if (volumeHeader->Attributes & EFI_FVB_ALIGNMENT_2) alignment = 2; - if (volumeHeader->Attributes & EFI_FVB_ALIGNMENT_4) alignment = 4; - if (volumeHeader->Attributes & EFI_FVB_ALIGNMENT_8) alignment = 8; - if (volumeHeader->Attributes & EFI_FVB_ALIGNMENT_16) alignment = 16; - if (volumeHeader->Attributes & EFI_FVB_ALIGNMENT_32) alignment = 32; - if (volumeHeader->Attributes & EFI_FVB_ALIGNMENT_64) alignment = 64; - if (volumeHeader->Attributes & EFI_FVB_ALIGNMENT_128) alignment = 128; - if (volumeHeader->Attributes & EFI_FVB_ALIGNMENT_256) alignment = 256; - if (volumeHeader->Attributes & EFI_FVB_ALIGNMENT_512) alignment = 512; - if (volumeHeader->Attributes & EFI_FVB_ALIGNMENT_1K) alignment = 1024; - if (volumeHeader->Attributes & EFI_FVB_ALIGNMENT_2K) alignment = 2048; - if (volumeHeader->Attributes & EFI_FVB_ALIGNMENT_4K) alignment = 4096; - if (volumeHeader->Attributes & EFI_FVB_ALIGNMENT_8K) alignment = 8192; - if (volumeHeader->Attributes & EFI_FVB_ALIGNMENT_16K) alignment = 16384; - if (volumeHeader->Attributes & EFI_FVB_ALIGNMENT_32K) alignment = 32768; - if (volumeHeader->Attributes & EFI_FVB_ALIGNMENT_64K) alignment = 65536; - }*/ + // No one gives a single damn about setting it correctly } else if (volumeHeader->Revision == 2) { // Acquire alignment @@ -1249,61 +1231,18 @@ USTATUS FfsParser::parseVolumeNonUefiData(const UByteArray & data, const UINT32 // Get parsing data PARSING_DATA pdata = parsingDataFromUModelIndex(index); - // Modify it + // Add parent offset pdata.offset += parentOffset; - // Search for VTF GUID backwards in received data - UByteArray padding = data; - UByteArray vtf; - INT32 vtfIndex = data.lastIndexOf(EFI_FFS_VOLUME_TOP_FILE_GUID); - if (vtfIndex >= 0) { // VTF candidate found inside non-UEFI data - padding = data.left(vtfIndex); - vtf = data.mid(vtfIndex); - const EFI_FFS_FILE_HEADER* fileHeader = (const EFI_FFS_FILE_HEADER*)vtf.constData(); - if ((UINT32)vtf.size() < sizeof(EFI_FFS_FILE_HEADER) // VTF candidate is too small to be a real VTF in FFSv1/v2 volume - || (pdata.ffsVersion == 3 - && (fileHeader->Attributes & FFS_ATTRIB_LARGE_FILE) - && (UINT32)vtf.size() < sizeof(EFI_FFS_FILE_HEADER2))) { // VTF candidate is too small to be a real VTF in FFSv3 volume - vtfIndex = -1; - padding = data; - vtf.clear(); - } - } - - // Add non-UEFI data first // Get info - UString info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size()); + UString info = usprintf("Full size: %Xh (%u)", data.size(), data.size()); // Add padding tree item - UModelIndex paddingIndex = model->addItem(Types::Padding, Subtypes::DataPadding, UString("Non-UEFI data"), "", info, UByteArray(), padding, UByteArray(), true, parsingDataToUByteArray(pdata), index); + UModelIndex paddingIndex = model->addItem(Types::Padding, Subtypes::DataPadding, UString("Non-UEFI data"), UString(), info, UByteArray(), data, UByteArray(), true, parsingDataToUByteArray(pdata), index); msg(UString("parseVolumeNonUefiData: non-UEFI data found in volume's free space"), paddingIndex); - if (vtfIndex >= 0) { - // Get VTF file header - UByteArray header = vtf.left(sizeof(EFI_FFS_FILE_HEADER)); - const EFI_FFS_FILE_HEADER* fileHeader = (const EFI_FFS_FILE_HEADER*)header.constData(); - if (pdata.ffsVersion == 3 && (fileHeader->Attributes & FFS_ATTRIB_LARGE_FILE)) { - header = vtf.left(sizeof(EFI_FFS_FILE_HEADER2)); - } - - //Parse VTF file header - UModelIndex fileIndex; - USTATUS result = parseFileHeader(vtf, parentOffset + vtfIndex, index, fileIndex); - if (result) { - msg(UString("parseVolumeNonUefiData: VTF file header parsing failed with error ") + errorCodeToUString(result), index); - - // Add the rest as non-UEFI data too - pdata.offset += vtfIndex; - // Get info - UString info = usprintf("Full size: %Xh (%u)", vtf.size(), vtf.size()); - - // Add padding tree item - UModelIndex paddingIndex = model->addItem(Types::Padding, Subtypes::DataPadding, UString("Non-UEFI data"), "", info, UByteArray(), vtf, UByteArray(), true, parsingDataToUByteArray(pdata), index); - msg(("parseVolumeNonUefiData: non-UEFI data found in volume's free space"), paddingIndex); - } - } - - return U_SUCCESS; + // Parse contents as RAW area + return parseRawArea(paddingIndex); } USTATUS FfsParser::parseVolumeBody(const UModelIndex & index) @@ -1366,7 +1305,7 @@ USTATUS FfsParser::parseVolumeBody(const UModelIndex & index) UString info = usprintf("Full size: %Xh (%u)", free.size(), free.size()); // Add free space item - model->addItem(Types::FreeSpace, 0, UString("Volume free space"), "", info, UByteArray(), free, UByteArray(), false, parsingDataToUByteArray(pdata), index); + model->addItem(Types::FreeSpace, 0, UString("Volume free space"), UString(), info, UByteArray(), free, UByteArray(), false, parsingDataToUByteArray(pdata), index); } // Parse non-UEFI data @@ -1380,7 +1319,7 @@ USTATUS FfsParser::parseVolumeBody(const UModelIndex & index) UString info = usprintf("Full size: %Xh (%u)", freeSpace.size(), freeSpace.size()); // Add free space item - model->addItem(Types::FreeSpace, 0, UString("Volume free space"), "", info, UByteArray(), freeSpace, UByteArray(), false, parsingDataToUByteArray(pdata), index); + model->addItem(Types::FreeSpace, 0, UString("Volume free space"), UString(), info, UByteArray(), freeSpace, UByteArray(), false, parsingDataToUByteArray(pdata), index); } break; // Exit from parsing loop } @@ -1683,7 +1622,7 @@ USTATUS FfsParser::parseFileBody(const UModelIndex & index) } // Parse sections - return parseSections(model->body(index), index); + return parseSections(model->body(index), index, true); } USTATUS FfsParser::parsePadFileBody(const UModelIndex & index) @@ -1739,7 +1678,7 @@ USTATUS FfsParser::parsePadFileBody(const UModelIndex & index) pdata.offset += i; // Add tree item - UModelIndex dataIndex = model->addItem(Types::Padding, Subtypes::DataPadding, UString("Non-UEFI data"), "", info, UByteArray(), padding, UByteArray(), true, parsingDataToUByteArray(pdata), index); + UModelIndex dataIndex = model->addItem(Types::Padding, Subtypes::DataPadding, UString("Non-UEFI data"), UString(), info, UByteArray(), padding, UByteArray(), true, parsingDataToUByteArray(pdata), index); // Show message msg(UString("parsePadFileBody: non-UEFI data found in pad-file"), dataIndex); @@ -1750,7 +1689,7 @@ USTATUS FfsParser::parsePadFileBody(const UModelIndex & index) return U_SUCCESS; } -USTATUS FfsParser::parseSections(const UByteArray & sections, const UModelIndex & index, const bool preparse) +USTATUS FfsParser::parseSections(const UByteArray & sections, const UModelIndex & index, const bool insertIntoTree) { // Sanity check if (!index.isValid()) @@ -1771,34 +1710,35 @@ USTATUS FfsParser::parseSections(const UByteArray & sections, const UModelIndex // Check section size if (sectionSize < sizeof(EFI_COMMON_SECTION_HEADER) || sectionSize > (bodySize - sectionOffset)) { - // Add padding to fill the rest of sections - UByteArray padding = sections.mid(sectionOffset); - // Get info - UString info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size()); - - // Constuct parsing data - pdata.offset += headerSize + sectionOffset; - // Final parsing - if (!preparse) { + if (insertIntoTree) { + // Add padding to fill the rest of sections + UByteArray padding = sections.mid(sectionOffset); + // Get info + UString info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size()); + + // Constuct parsing data + pdata.offset += headerSize + sectionOffset; + // Add tree item - UModelIndex dataIndex = model->addItem(Types::Padding, Subtypes::DataPadding, UString("Non-UEFI data"), "", info, UByteArray(), padding, UByteArray(), true, parsingDataToUByteArray(pdata), index); + UModelIndex dataIndex = model->addItem(Types::Padding, Subtypes::DataPadding, UString("Non-UEFI data"), UString(), info, UByteArray(), padding, UByteArray(), true, parsingDataToUByteArray(pdata), index); // Show message msg(UString("parseSections: non-UEFI data found in sections area"), dataIndex); + + // Exit from parsing loop + break; } // Preparsing - else { + else return U_INVALID_SECTION; - } - break; // Exit from parsing loop } // Parse section header UModelIndex sectionIndex; - result = parseSectionHeader(sections.mid(sectionOffset, sectionSize), headerSize + sectionOffset, index, sectionIndex, preparse); + result = parseSectionHeader(sections.mid(sectionOffset, sectionSize), headerSize + sectionOffset, index, sectionIndex, insertIntoTree); if (result) { - if (!preparse) + if (insertIntoTree) msg(UString("parseSections: section header parsing failed with error ") + errorCodeToUString(result), index); else return U_INVALID_SECTION; @@ -1808,7 +1748,7 @@ USTATUS FfsParser::parseSections(const UByteArray & sections, const UModelIndex sectionOffset = ALIGN4(sectionOffset); } - //Parse bodies, will be skipped on preparse phase + // Parse bodies, will be skipped if insertIntoTree is not required for (int i = 0; i < model->rowCount(index); i++) { UModelIndex current = index.child(i, 0); switch (model->type(current)) { @@ -1826,7 +1766,7 @@ USTATUS FfsParser::parseSections(const UByteArray & sections, const UModelIndex return U_SUCCESS; } -USTATUS FfsParser::parseSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool preparse) +USTATUS FfsParser::parseSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree) { // Check sanity if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER)) @@ -1835,12 +1775,12 @@ USTATUS FfsParser::parseSectionHeader(const UByteArray & section, const UINT32 p const EFI_COMMON_SECTION_HEADER* sectionHeader = (const EFI_COMMON_SECTION_HEADER*)(section.constData()); switch (sectionHeader->Type) { // Special - case EFI_SECTION_COMPRESSION: return parseCompressedSectionHeader(section, parentOffset, parent, index, preparse); - case EFI_SECTION_GUID_DEFINED: return parseGuidedSectionHeader(section, parentOffset, parent, index, preparse); - case EFI_SECTION_FREEFORM_SUBTYPE_GUID: return parseFreeformGuidedSectionHeader(section, parentOffset, parent, index, preparse); - case EFI_SECTION_VERSION: return parseVersionSectionHeader(section, parentOffset, parent, index, preparse); + case EFI_SECTION_COMPRESSION: return parseCompressedSectionHeader(section, parentOffset, parent, index, insertIntoTree); + case EFI_SECTION_GUID_DEFINED: return parseGuidedSectionHeader(section, parentOffset, parent, index, insertIntoTree); + case EFI_SECTION_FREEFORM_SUBTYPE_GUID: return parseFreeformGuidedSectionHeader(section, parentOffset, parent, index, insertIntoTree); + case EFI_SECTION_VERSION: return parseVersionSectionHeader(section, parentOffset, parent, index, insertIntoTree); case PHOENIX_SECTION_POSTCODE: - case INSYDE_SECTION_POSTCODE: return parsePostcodeSectionHeader(section, parentOffset, parent, index, preparse); + case INSYDE_SECTION_POSTCODE: return parsePostcodeSectionHeader(section, parentOffset, parent, index, insertIntoTree); // Common case EFI_SECTION_DISPOSABLE: case EFI_SECTION_DXE_DEPEX: @@ -1852,16 +1792,16 @@ USTATUS FfsParser::parseSectionHeader(const UByteArray & section, const UINT32 p case EFI_SECTION_COMPATIBILITY16: case EFI_SECTION_USER_INTERFACE: case EFI_SECTION_FIRMWARE_VOLUME_IMAGE: - case EFI_SECTION_RAW: return parseCommonSectionHeader(section, parentOffset, parent, index, preparse); + case EFI_SECTION_RAW: return parseCommonSectionHeader(section, parentOffset, parent, index, insertIntoTree); // Unknown default: - USTATUS result = parseCommonSectionHeader(section, parentOffset, parent, index, preparse); + USTATUS result = parseCommonSectionHeader(section, parentOffset, parent, index, insertIntoTree); msg(usprintf("parseSectionHeader: section with unknown type %02Xh", sectionHeader->Type), index); return result; } } -USTATUS FfsParser::parseCommonSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool preparse) +USTATUS FfsParser::parseCommonSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree) { // Check sanity if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER)) @@ -1905,13 +1845,13 @@ USTATUS FfsParser::parseCommonSectionHeader(const UByteArray & section, const UI pdata.offset += parentOffset; // Add tree item - if (!preparse) { + if (insertIntoTree) { index = model->addItem(Types::Section, type, name, UString(), info, header, body, UByteArray(), false, parsingDataToUByteArray(pdata), parent); } return U_SUCCESS; } -USTATUS FfsParser::parseCompressedSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool preparse) +USTATUS FfsParser::parseCompressedSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree) { // Check sanity if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER)) @@ -1972,13 +1912,13 @@ USTATUS FfsParser::parseCompressedSectionHeader(const UByteArray & section, cons pdata.section.compressed.uncompressedSize = uncompressedLength; // Add tree item - if (!preparse) { + if (insertIntoTree) { index = model->addItem(Types::Section, sectionHeader->Type, name, UString(), info, header, body, UByteArray(), false, parsingDataToUByteArray(pdata), parent); } return U_SUCCESS; } -USTATUS FfsParser::parseGuidedSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool preparse) +USTATUS FfsParser::parseGuidedSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree) { // Check sanity if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER)) @@ -2127,7 +2067,7 @@ USTATUS FfsParser::parseGuidedSectionHeader(const UByteArray & section, const UI pdata.section.guidDefined.guid = guid; // Add tree item - if (!preparse) { + if (insertIntoTree) { index = model->addItem(Types::Section, sectionHeader->Type, name, UString(), info, header, body, UByteArray(), false, parsingDataToUByteArray(pdata), parent); // Show messages @@ -2150,7 +2090,7 @@ USTATUS FfsParser::parseGuidedSectionHeader(const UByteArray & section, const UI return U_SUCCESS; } -USTATUS FfsParser::parseFreeformGuidedSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool preparse) +USTATUS FfsParser::parseFreeformGuidedSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree) { // Check sanity if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER)) @@ -2209,7 +2149,7 @@ USTATUS FfsParser::parseFreeformGuidedSectionHeader(const UByteArray & section, pdata.section.freeformSubtypeGuid.guid = guid; // Add tree item - if (!preparse) { + if (insertIntoTree) { index = model->addItem(Types::Section, type, name, UString(), info, header, body, UByteArray(), false, parsingDataToUByteArray(pdata), parent); // Rename section @@ -2218,7 +2158,7 @@ USTATUS FfsParser::parseFreeformGuidedSectionHeader(const UByteArray & section, return U_SUCCESS; } -USTATUS FfsParser::parseVersionSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool preparse) +USTATUS FfsParser::parseVersionSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree) { // Check sanity if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER)) @@ -2274,13 +2214,13 @@ USTATUS FfsParser::parseVersionSectionHeader(const UByteArray & section, const U pdata.offset += parentOffset; // Add tree item - if (!preparse) { + if (insertIntoTree) { index = model->addItem(Types::Section, type, name, UString(), info, header, body, UByteArray(), false, parsingDataToUByteArray(pdata), parent); } return U_SUCCESS; } -USTATUS FfsParser::parsePostcodeSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool preparse) +USTATUS FfsParser::parsePostcodeSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree) { // Check sanity if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER)) @@ -2336,7 +2276,7 @@ USTATUS FfsParser::parsePostcodeSectionHeader(const UByteArray & section, const pdata.offset += parentOffset; // Add tree item - if (!preparse) { + if (insertIntoTree) { index = model->addItem(Types::Section, sectionHeader->Type, name, UString(), info, header, body, UByteArray(), false, parsingDataToUByteArray(pdata), parent); } return U_SUCCESS; @@ -2357,7 +2297,7 @@ USTATUS FfsParser::parseSectionBody(const UModelIndex & index) // Encapsulation case EFI_SECTION_COMPRESSION: return parseCompressedSectionBody(index); case EFI_SECTION_GUID_DEFINED: return parseGuidedSectionBody(index); - case EFI_SECTION_DISPOSABLE: return parseSections(model->body(index), index); + case EFI_SECTION_DISPOSABLE: return parseSections(model->body(index), index, true); // Leaf case EFI_SECTION_FREEFORM_SUBTYPE_GUID: return parseRawArea(index); case EFI_SECTION_VERSION: return parseVersionSectionBody(index); @@ -2411,11 +2351,11 @@ USTATUS FfsParser::parseCompressedSectionBody(const UModelIndex & index) // Check for undecided compression algorithm, this is a special case if (algorithm == COMPRESSION_ALGORITHM_UNDECIDED) { // Try preparse of sections decompressed with Tiano algorithm - if (U_SUCCESS == parseSections(decompressed, index, true)) { + if (U_SUCCESS == parseSections(decompressed, index, false)) { algorithm = COMPRESSION_ALGORITHM_TIANO; } // Try preparse of sections decompressed with EFI 1.1 algorithm - else if (U_SUCCESS == parseSections(efiDecompressed, index, true)) { + else if (U_SUCCESS == parseSections(efiDecompressed, index, false)) { algorithm = COMPRESSION_ALGORITHM_EFI11; decompressed = efiDecompressed; } @@ -2434,7 +2374,7 @@ USTATUS FfsParser::parseCompressedSectionBody(const UModelIndex & index) model->setParsingData(index, parsingDataToUByteArray(pdata)); // Parse decompressed data - return parseSections(decompressed, index); + return parseSections(decompressed, index, true); } USTATUS FfsParser::parseGuidedSectionBody(const UModelIndex & index) @@ -2466,11 +2406,11 @@ USTATUS FfsParser::parseGuidedSectionBody(const UModelIndex & index) // Check for undecided compression algorithm, this is a special case if (algorithm == COMPRESSION_ALGORITHM_UNDECIDED) { // Try preparse of sections decompressed with Tiano algorithm - if (U_SUCCESS == parseSections(processed, index, true)) { + if (U_SUCCESS == parseSections(processed, index, false)) { algorithm = COMPRESSION_ALGORITHM_TIANO; } // Try preparse of sections decompressed with EFI 1.1 algorithm - else if (U_SUCCESS == parseSections(efiDecompressed, index, true)) { + else if (U_SUCCESS == parseSections(efiDecompressed, index, false)) { algorithm = COMPRESSION_ALGORITHM_EFI11; processed = efiDecompressed; } @@ -2516,7 +2456,7 @@ USTATUS FfsParser::parseGuidedSectionBody(const UModelIndex & index) return U_SUCCESS; } - return parseSections(processed, index); + return parseSections(processed, index, true); } USTATUS FfsParser::parseVersionSectionBody(const UModelIndex & index) @@ -2912,9 +2852,6 @@ USTATUS FfsParser::addFixedAndCompressedRecursive(const UModelIndex & index) { if (!index.isValid()) return U_INVALID_PARAMETER; - // Get parsing data for the current item - PARSING_DATA pdata = parsingDataFromUModelIndex(index); - // Add fixed and compressed info model->addInfo(index, usprintf("\nCompressed: %s", model->compressed(index) ? "Yes" : "No")); model->addInfo(index, usprintf("\nFixed: %s", model->fixed(index) ? "Yes" : "No")); @@ -2959,8 +2896,9 @@ USTATUS FfsParser::parseFit(const UModelIndex & index, const UINT32 diff) FIT_ENTRY* tempFitHeader = (FIT_ENTRY*)tempFIT.data(); tempFitHeader->Checksum = 0; UINT8 calculated = calculateChecksum8((const UINT8*)tempFitHeader, fitSize); + calculated |= 0x80; // Set checksum flag on calculated checksum if (calculated != fitHeader->Checksum) { - msg(usprintf("Invalid FIT table checksum %02Xh, should be %02Xh", fitHeader->Checksum, calculated), fitIndex); + msg(usprintf("parseFit: invalid FIT table checksum %02Xh, should be %02Xh", fitHeader->Checksum, calculated), fitIndex); } } @@ -2987,7 +2925,7 @@ USTATUS FfsParser::parseFit(const UModelIndex & index, const UINT32 diff) // Check entry type switch (currentEntry->Type & 0x7F) { case FIT_TYPE_HEADER: - msg(UString("Second FIT header found, the table is damaged"), fitIndex); + msg(UString("parseFit: second FIT header found, the table is damaged"), fitIndex); break; case FIT_TYPE_EMPTY: @@ -3016,7 +2954,7 @@ USTATUS FfsParser::parseFit(const UModelIndex & index, const UINT32 diff) } if (msgModifiedImageMayNotWork) - msg(UString("Opened image may not work after any modification"), fitIndex); + msg(UString("parseFit: opened image may not work after any modification"), fitIndex); return U_SUCCESS; } @@ -3050,11 +2988,11 @@ USTATUS FfsParser::findFitRecursive(const UModelIndex & index, const UINT32 diff if (fitAddress == storedFitAddress) { found = index; fitOffset = offset; - msg(usprintf("Real FIT table found at physical address %08Xh", fitAddress), found); + msg(usprintf("findFitRecursive: real FIT table found at physical address %08Xh", fitAddress), found); return U_SUCCESS; } else if (model->rowCount(index) == 0) // Show messages only to leaf items - msg(UString("FIT table candidate found, but not referenced from the last VTF"), index); + msg(UString("findFitRecursive: FIT table candidate found, but not referenced from the last VTF"), index); } return U_SUCCESS; @@ -3087,16 +3025,32 @@ USTATUS FfsParser::addMemoryAddressesRecursive(const UModelIndex & index, const // Special case of uncompressed TE image sections if (model->type(index) == Types::Section && model->subtype(index) == EFI_SECTION_TE) { // Check data memory address to be equal to either ImageBase or AdjustedImageBase - if (pdata.section.teImage.imageBase == pdata.address + headerSize) { - pdata.section.teImage.revision = 1; + UINT32 base = pdata.address + headerSize; + pdata.section.teImage.imageBaseType = EFI_IMAGE_TE_BASE_OTHER; + + if (pdata.section.teImage.imageBase == base) { + pdata.section.teImage.imageBaseType = EFI_IMAGE_TE_BASE_ORIGINAL; } - else if (pdata.section.teImage.adjustedImageBase == pdata.address + headerSize) { - pdata.section.teImage.revision = 2; + else if (pdata.section.teImage.adjustedImageBase == base) { + pdata.section.teImage.imageBaseType = EFI_IMAGE_TE_BASE_ADJUSTED; } - else { - msg(UString("addMemoryAddressesRecursive: image base is neither original nor adjusted, it's likely a part of backup PEI volume or DXE volume, but can also be damaged"), index); - pdata.section.teImage.revision = 0; + else { + // Check for one-bit difference + UINT32 xored = base ^ pdata.section.teImage.imageBase; // XOR result can't be zero + if ((xored & (xored - 1)) == 0) { // Check that XOR result is a power of 2, i.e. has exactly one bit set + pdata.section.teImage.imageBaseType = EFI_IMAGE_TE_BASE_ORIGINAL; + } + else { // The same check for adjustedImageBase + xored = base ^ pdata.section.teImage.adjustedImageBase; + if ((xored & (xored - 1)) == 0) { + pdata.section.teImage.imageBaseType = EFI_IMAGE_TE_BASE_ADJUSTED; + } + } } + + // Show message if imageBaseType is still unknown + if (pdata.section.teImage.imageBase != 0 && pdata.section.teImage.imageBaseType == EFI_IMAGE_TE_BASE_OTHER) + msg(UString("addMemoryAddressesRecursive: TE image base is neither zero, nor original, nor adjusted, nor top-swapped"), index); } // Set modified parsing data diff --git a/common/ffsparser.h b/common/ffsparser.h index 4f93d49..258cb53 100644 --- a/common/ffsparser.h +++ b/common/ffsparser.h @@ -70,7 +70,7 @@ private: USTATUS parseVolumeBody(const UModelIndex & index); USTATUS parseFileHeader(const UByteArray & file, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index); USTATUS parseFileBody(const UModelIndex & index); - USTATUS parseSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool preparse = false); + USTATUS parseSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree); USTATUS parseSectionBody(const UModelIndex & index); USTATUS parseIntelImage(const UByteArray & intelImage, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & root); @@ -83,13 +83,13 @@ private: USTATUS parsePadFileBody(const UModelIndex & index); USTATUS parseVolumeNonUefiData(const UByteArray & data, const UINT32 parentOffset, const UModelIndex & index); - USTATUS parseSections(const UByteArray & sections, const UModelIndex & index, const bool preparse = false); - USTATUS parseCommonSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool preparse); - USTATUS parseCompressedSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool preparse); - USTATUS parseGuidedSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool preparse); - USTATUS parseFreeformGuidedSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool preparse); - USTATUS parseVersionSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool preparse); - USTATUS parsePostcodeSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool preparse); + USTATUS parseSections(const UByteArray & sections, const UModelIndex & index, const bool insertIntoTree); + USTATUS parseCommonSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree); + USTATUS parseCompressedSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree); + USTATUS parseGuidedSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree); + USTATUS parseFreeformGuidedSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree); + USTATUS parseVersionSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree); + USTATUS parsePostcodeSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree); USTATUS parseCompressedSectionBody(const UModelIndex & index); USTATUS parseGuidedSectionBody(const UModelIndex & index); @@ -100,12 +100,12 @@ private: USTATUS parsePeImageSectionBody(const UModelIndex & index); USTATUS parseTeImageSectionBody(const UModelIndex & index); - UINT8 getPaddingType(const UByteArray & padding); + UINT8 getPaddingType(const UByteArray & padding); USTATUS parseAprioriRawSection(const UByteArray & body, UString & parsed); USTATUS findNextVolume(const UModelIndex & index, const UByteArray & bios, const UINT32 parentOffset, const UINT32 volumeOffset, UINT32 & nextVolumeOffset); USTATUS getVolumeSize(const UByteArray & bios, const UINT32 volumeOffset, UINT32 & volumeSize, UINT32 & bmVolumeSize); - UINT32 getFileSize(const UByteArray & volume, const UINT32 fileOffset, const UINT8 ffsVersion); - UINT32 getSectionSize(const UByteArray & file, const UINT32 sectionOffset, const UINT8 ffsVersion); + UINT32 getFileSize(const UByteArray & volume, const UINT32 fileOffset, const UINT8 ffsVersion); + UINT32 getSectionSize(const UByteArray & file, const UINT32 sectionOffset, const UINT8 ffsVersion); // NVRAM parsing USTATUS parseNvramVolumeBody(const UModelIndex & index); diff --git a/common/parsingdata.h b/common/parsingdata.h index f981171..b52870d 100644 --- a/common/parsingdata.h +++ b/common/parsingdata.h @@ -50,7 +50,7 @@ typedef struct FREEFORM_GUIDED_SECTION_PARSING_DATA_ { typedef struct TE_IMAGE_SECTION_PARSING_DATA_ { UINT32 imageBase; UINT32 adjustedImageBase; - UINT8 revision; + UINT8 imageBaseType; } TE_IMAGE_SECTION_PARSING_DATA; typedef struct SECTION_PARSING_DATA_ { diff --git a/common/peimage.h b/common/peimage.h index 0d5b1e7..6c14d9c 100644 --- a/common/peimage.h +++ b/common/peimage.h @@ -728,6 +728,11 @@ typedef struct { #define EFI_IMAGE_TE_SIGNATURE 0x5A56 // VZ +// Image base types +#define EFI_IMAGE_TE_BASE_OTHER 0 +#define EFI_IMAGE_TE_BASE_ORIGINAL 1 +#define EFI_IMAGE_TE_BASE_ADJUSTED 2 + // // Data directory indexes in our TE image header //