From 6f6debb21262a1b97bd5705ce18a3b249a9fba4f Mon Sep 17 00:00:00 2001 From: Nikolaj Schlej Date: Sat, 26 Apr 2025 17:06:26 +0700 Subject: [PATCH] Add volume header info on NumBlocks and Length used to calcualte alternative size of it --- common/ffsparser.cpp | 94 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 80 insertions(+), 14 deletions(-) diff --git a/common/ffsparser.cpp b/common/ffsparser.cpp index 10af799..d8e6ee1 100644 --- a/common/ffsparser.cpp +++ b/common/ffsparser.cpp @@ -703,10 +703,15 @@ USTATUS FfsParser::parseMeRegion(const UByteArray & me, const UINT32 localOffset bool versionFound = true; bool emptyRegion = false; // Check for empty region - if (me.size() == me.count('\xFF') || me.size() == me.count('\x00')) { + if (me.size() == me.count('\xFF')) { // Further parsing not needed emptyRegion = true; - info += ("\nState: empty"); + info += ("\nState: empty (0xFF)"); + } + else if (me.size() == me.count('\x00')) { + // Further parsing not needed + emptyRegion = true; + info += ("\nState: empty (0x00)"); } else { // Search for new signature @@ -724,12 +729,11 @@ USTATUS FfsParser::parseMeRegion(const UByteArray & me, const UINT32 localOffset } } - // Check sanity - if ((UINT32)me.size() < (UINT32)versionOffset + sizeof(ME_VERSION)) - return U_INVALID_REGION; - // Add version information if (versionFound) { + if ((UINT32)me.size() < (UINT32)versionOffset + sizeof(ME_VERSION)) + return U_INVALID_REGION; + const ME_VERSION* version = (const ME_VERSION*)(me.constData() + versionOffset); info += usprintf("\nVersion: %u.%u.%u.%u", version->Major, @@ -766,13 +770,28 @@ USTATUS FfsParser::parsePdrRegion(const UByteArray & pdr, const UINT32 localOffs UString name("PDR region"); UString info = usprintf("Full size: 0x%X (%u)", (UINT32)pdr.size(), (UINT32)pdr.size()); + // Check for empty region + bool emptyRegion = false; + if (pdr.size() == pdr.count('\xFF')) { + // Further parsing not needed + emptyRegion = true; + info += ("\nState: empty (0xFF)"); + } + else if (pdr.size() == pdr.count('\x00')) { + // Further parsing not needed + emptyRegion = true; + info += ("\nState: empty (0x00)"); + } + // Add tree item index = model->addItem(localOffset, Types::Region, Subtypes::PdrRegion, name, UString(), info, UByteArray(), pdr, UByteArray(), Fixed, parent); - // Parse PDR region as BIOS space - USTATUS result = parseRawArea(index); - if (result && result != U_VOLUMES_NOT_FOUND && result != U_INVALID_VOLUME && result != U_STORES_NOT_FOUND) - return result; + if (!emptyRegion) { + // Parse PDR region as BIOS space + USTATUS result = parseRawArea(index); + if (result && result != U_VOLUMES_NOT_FOUND && result != U_INVALID_VOLUME && result != U_STORES_NOT_FOUND) + return result; + } return U_SUCCESS; } @@ -787,12 +806,17 @@ USTATUS FfsParser::parseDevExp1Region(const UByteArray & devExp1, const UINT32 l UString name("DevExp1 region"); UString info = usprintf("Full size: 0x%X (%u)", (UINT32)devExp1.size(), (UINT32)devExp1.size()); - bool emptyRegion = false; // Check for empty region - if (devExp1.size() == devExp1.count('\xFF') || devExp1.size() == devExp1.count('\x00')) { + bool emptyRegion = false; + if (devExp1.size() == devExp1.count('\xFF')) { // Further parsing not needed emptyRegion = true; - info += ("\nState: empty"); + info += ("\nState: empty (0xFF)"); + } + else if (devExp1.size() == devExp1.count('\x00')) { + // Further parsing not needed + emptyRegion = true; + info += ("\nState: empty (0x00)"); } // Add tree item @@ -814,6 +838,19 @@ USTATUS FfsParser::parseGenericRegion(const UINT8 subtype, const UByteArray & re UString name = itemSubtypeToUString(Types::Region, subtype) + UString(" region"); UString info = usprintf("Full size: 0x%X (%u)", (UINT32)region.size(), (UINT32)region.size()); + // Check for empty region + bool emptyRegion = false; + if (region.size() == region.count('\xFF')) { + // Further parsing not needed + emptyRegion = true; + info += ("\nState: empty (0xFF)"); + } + else if (region.size() == region.count('\x00')) { + // Further parsing not needed + emptyRegion = true; + info += ("\nState: empty (0x00)"); + } + // Add tree item index = model->addItem(localOffset, Types::Region, subtype, name, UString(), info, UByteArray(), region, UByteArray(), Fixed, parent); @@ -1486,7 +1523,36 @@ USTATUS FfsParser::parseVolumeHeader(const UByteArray & volume, const UINT32 loc volumeHeader->Checksum) + (msgInvalidChecksum ? usprintf(", invalid, should be 0x%04X", calculated) : UString(", valid")); - // Extended header present + // Block size and blocks number + const EFI_FV_BLOCK_MAP_ENTRY* entry = (const EFI_FV_BLOCK_MAP_ENTRY*)(volume.constData() + sizeof(EFI_FIRMWARE_VOLUME_HEADER)); + UString infoNumBlocks = usprintf("NumBlocks: 0x%X (%u)", entry->NumBlocks, entry->NumBlocks); + UString infoLength = usprintf("Length: 0x%X (%u)", entry->Length, entry->Length); + if (entry->NumBlocks == 0) { + infoNumBlocks += UString(", invalid, can not be zero"); + } + if (entry->Length == 0) { + infoLength += UString(", invalid, can not be zero"); + } + if (entry->NumBlocks != 0 && entry->Length != 0) { + UINT32 volumeAltSize = entry->NumBlocks * entry->Length; + if (volumeSize != volumeAltSize) { + if (volumeAltSize % entry->Length == 0 && volumeSize % entry->Length == 0) { + infoNumBlocks += usprintf(", invalid, should be 0x%X", volumeSize / entry->Length); + infoLength += ", valid"; + } + else if (volumeAltSize % entry->NumBlocks == 0 && volumeSize % entry->NumBlocks == 0) { + infoNumBlocks += ", valid"; + infoLength += usprintf(", invalid, should be 0x%X", volumeSize / entry->NumBlocks); + } + } + else { + infoNumBlocks += ", valid"; + infoLength += ", valid"; + } + } + info += "\n" + infoNumBlocks + "\n" + infoLength; + + // Extended header if (volumeHeader->Revision > 1 && volumeHeader->ExtHeaderOffset) { if ((UINT32)volume.size() < volumeHeader->ExtHeaderOffset + sizeof(EFI_FIRMWARE_VOLUME_EXT_HEADER)) { return U_INVALID_VOLUME;