From 52c7a56f681bb9bd1b0b93e8fd4a16221bdc1d3f Mon Sep 17 00:00:00 2001 From: Cr4sh Date: Thu, 27 Oct 2016 23:31:15 +0700 Subject: [PATCH] NE Alpha 34 --- UEFITool/uefitool.cpp | 26 +- UEFITool/uefitool.desktop | 0 common/basetypes.h | 10 +- common/ffs.cpp | 32 +- common/ffs.h | 12 +- common/ffsbuilder.cpp | 4 +- common/ffsops.cpp | 26 +- common/ffsparser.cpp | 692 +++++++++++++++++++------------------- common/ffsparser.h | 34 +- common/nvramparser.cpp | 478 +++++++++++--------------- common/nvramparser.h | 33 +- common/parsingdata.h | 48 +-- common/treeitem.cpp | 6 +- common/treeitem.h | 22 +- common/treemodel.cpp | 77 +++-- common/treemodel.h | 29 +- common/utility.cpp | 48 +-- common/utility.h | 8 +- 18 files changed, 731 insertions(+), 854 deletions(-) mode change 100755 => 100644 UEFITool/uefitool.desktop diff --git a/UEFITool/uefitool.cpp b/UEFITool/uefitool.cpp index 191acfe..e237b2f 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("NE Alpha33")) +version(tr("NE Alpha34")) { clipboard = QApplication::clipboard(); @@ -205,7 +205,9 @@ void UEFITool::populateUi(const QModelIndex ¤t) bool UEFITool::enableExtractBodyUncompressed(const QModelIndex ¤t) { - if (current.isValid() && model->type(current) == Types::Section && + // TODO: rewrite based on model->compressed() + U_UNUSED_PARAMETER(current); + /*if (current.isValid() && model->type(current) == Types::Section && (model->subtype(current) == EFI_SECTION_COMPRESSION || model->subtype(current) == EFI_SECTION_GUID_DEFINED)) { // Get parsing data PARSING_DATA pdata = parsingDataFromUModelIndex(current); @@ -222,7 +224,7 @@ bool UEFITool::enableExtractBodyUncompressed(const QModelIndex ¤t) return true; } } - } + }*/ return false; } @@ -304,17 +306,24 @@ void UEFITool::goToData() QModelIndex parent = model->parent(index); for (int i = index.row(); i < model->rowCount(parent); i++) { - PARSING_DATA pdata = parsingDataFromUModelIndex(index); - UINT32 lastVariableFlag = pdata.emptyByte ? 0xFFFFFF : 0; - if (pdata.nvar.next == lastVariableFlag) { + if (model->hasEmptyParsingData(index)) + continue; + + UByteArray data = model->parsingData(index); + const NVAR_ENTRY_PARSING_DATA* pdata = (const NVAR_ENTRY_PARSING_DATA*)data.constData(); + UINT32 lastVariableFlag = pdata->emptyByte ? 0xFFFFFF : 0; + UINT32 offset = model->offset(index); + if (pdata->next == lastVariableFlag) { ui->structureTreeView->scrollTo(index, QAbstractItemView::PositionAtCenter); ui->structureTreeView->selectionModel()->select(index, QItemSelectionModel::Select | QItemSelectionModel::Rows | QItemSelectionModel::Clear); } for (int j = i + 1; j < model->rowCount(parent); j++) { QModelIndex currentIndex = parent.child(j, 0); - PARSING_DATA currentPdata = parsingDataFromUModelIndex(currentIndex); - if (currentPdata.offset == pdata.offset + pdata.nvar.next) { + if (model->hasEmptyParsingData(currentIndex)) + continue; + + if (model->offset(currentIndex) == offset + pdata->next) { index = currentIndex; break; } @@ -324,6 +333,7 @@ void UEFITool::goToData() void UEFITool::insert(const UINT8 mode) { + U_UNUSED_PARAMETER(mode); /*QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex(); if (!index.isValid()) return; diff --git a/UEFITool/uefitool.desktop b/UEFITool/uefitool.desktop old mode 100755 new mode 100644 diff --git a/common/basetypes.h b/common/basetypes.h index b4d4bc1..201171a 100644 --- a/common/basetypes.h +++ b/common/basetypes.h @@ -139,7 +139,10 @@ typedef unsigned int UINTN; // EFI GUID typedef struct EFI_GUID_ { - UINT8 Data[16]; + UINT32 Data1; + UINT16 Data2; + UINT16 Data3; + UINT8 Data4[8]; } EFI_GUID; // EFI Time @@ -157,9 +160,14 @@ typedef struct EFI_TIME_ { UINT8 : 8; } EFI_TIME; +// Aling to 4 or 8 bytes #define ALIGN4(Value) (((Value)+3) & ~3) #define ALIGN8(Value) (((Value)+7) & ~7) +// Unused parameter declaration +#define U_UNUSED_PARAMETER(x) ((void)x) + +// Assert macro #include #define ASSERT(x) assert(x) diff --git a/common/ffs.cpp b/common/ffs.cpp index 1197193..a6d25d8 100644 --- a/common/ffs.cpp +++ b/common/ffs.cpp @@ -46,17 +46,17 @@ UINT32 uint24ToUint32(const UINT8* ffsSize) UString guidToUString(const EFI_GUID & guid) { return usprintf("%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", - *(const UINT32*)&guid.Data[0], - *(const UINT16*)&guid.Data[4], - *(const UINT16*)&guid.Data[6], - guid.Data[8], - guid.Data[9], - guid.Data[10], - guid.Data[11], - guid.Data[12], - guid.Data[13], - guid.Data[14], - guid.Data[15]); + guid.Data1, + guid.Data2, + guid.Data3, + guid.Data4[0], + guid.Data4[1], + guid.Data4[2], + guid.Data4[3], + guid.Data4[4], + guid.Data4[5], + guid.Data4[6], + guid.Data4[7]); } UString fileTypeToUString(const UINT8 type) @@ -72,10 +72,12 @@ UString fileTypeToUString(const UINT8 type) case EFI_FV_FILETYPE_DRIVER: return UString("DXE driver"); case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER: return UString("Combined PEI/DXE"); case EFI_FV_FILETYPE_APPLICATION: return UString("Application"); - case EFI_FV_FILETYPE_SMM: return UString("SMM module"); + case EFI_FV_FILETYPE_MM: return UString("SMM module"); case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE: return UString("Volume image"); - case EFI_FV_FILETYPE_COMBINED_SMM_DXE: return UString("Combined SMM/DXE"); - case EFI_FV_FILETYPE_SMM_CORE: return UString("SMM core"); + case EFI_FV_FILETYPE_COMBINED_MM_DXE: return UString("Combined SMM/DXE"); + case EFI_FV_FILETYPE_MM_CORE: return UString("SMM core"); + case EFI_FV_FILETYPE_MM_STANDALONE: return UString("MM standalone module"); + case EFI_FV_FILETYPE_MM_CORE_STANDALONE: return UString("MM standalone core"); case EFI_FV_FILETYPE_PAD: return UString("Pad"); default: return UString("Unknown"); }; @@ -99,7 +101,7 @@ UString sectionTypeToUString(const UINT8 type) case EFI_SECTION_FREEFORM_SUBTYPE_GUID: return UString("Freeform subtype GUID"); case EFI_SECTION_RAW: return UString("Raw"); case EFI_SECTION_PEI_DEPEX: return UString("PEI dependency"); - case EFI_SECTION_SMM_DEPEX: return UString("SMM dependency"); + case EFI_SECTION_MM_DEPEX: return UString("MM dependency"); case INSYDE_SECTION_POSTCODE: return UString("Insyde postcode"); case PHOENIX_SECTION_POSTCODE: return UString("Phoenix postcode"); default: return UString("Unknown"); diff --git a/common/ffs.h b/common/ffs.h index 64d46cf..99799f5 100644 --- a/common/ffs.h +++ b/common/ffs.h @@ -306,10 +306,12 @@ UINT32 ExtendedSize; #define EFI_FV_FILETYPE_DRIVER 0x07 #define EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER 0x08 #define EFI_FV_FILETYPE_APPLICATION 0x09 -#define EFI_FV_FILETYPE_SMM 0x0A +#define EFI_FV_FILETYPE_MM 0x0A #define EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE 0x0B -#define EFI_FV_FILETYPE_COMBINED_SMM_DXE 0x0C -#define EFI_FV_FILETYPE_SMM_CORE 0x0D +#define EFI_FV_FILETYPE_COMBINED_MM_DXE 0x0C +#define EFI_FV_FILETYPE_MM_CORE 0x0D +#define EFI_FV_FILETYPE_MM_STANDALONE 0x0E +#define EFI_FV_FILETYPE_MM_CORE_STANDALONE 0x0F #define EFI_FV_FILETYPE_OEM_MIN 0xC0 #define EFI_FV_FILETYPE_OEM_MAX 0xDF #define EFI_FV_FILETYPE_DEBUG_MIN 0xE0 @@ -336,7 +338,7 @@ extern const UINT8 ffsAlignmentTable[]; #define EFI_FILE_MARKED_FOR_UPDATE 0x08 #define EFI_FILE_DELETED 0x10 #define EFI_FILE_HEADER_INVALID 0x20 - +#define EFI_FILE_ERASE_POLARITY 0x80 // Defined as "all other bits must be set to ERASE_POLARITY" in UEFI PI Vol3 // PEI apriori file const UByteArray EFI_PEI_APRIORI_FILE_GUID ("\x0A\xCC\x45\x1B\x6A\x15\x8A\x42\xAF\x62\x49\x86\x4D\xA0\xE6\xE6", 16); @@ -406,7 +408,7 @@ typedef struct EFI_COMMON_SECTION_HEADER_APPLE { #define EFI_SECTION_FREEFORM_SUBTYPE_GUID 0x18 #define EFI_SECTION_RAW 0x19 #define EFI_SECTION_PEI_DEPEX 0x1B -#define EFI_SECTION_SMM_DEPEX 0x1C +#define EFI_SECTION_MM_DEPEX 0x1C #define PHOENIX_SECTION_POSTCODE 0xF0 // Specific to Phoenix SCT images #define INSYDE_SECTION_POSTCODE 0x20 // Specific to Insyde H2O images diff --git a/common/ffsbuilder.cpp b/common/ffsbuilder.cpp index e2d6d4c..fcdffde 100644 --- a/common/ffsbuilder.cpp +++ b/common/ffsbuilder.cpp @@ -23,9 +23,7 @@ USTATUS FfsBuilder::erase(const UModelIndex & index, UByteArray & erased) if (!index.isValid()) return U_INVALID_PARAMETER; - PARSING_DATA pdata = parsingDataFromUModelIndex(index); - erased.fill(pdata.emptyByte); - return U_SUCCESS; + return U_NOT_IMPLEMENTED; } USTATUS FfsBuilder::build(const UModelIndex & root, UByteArray & image) diff --git a/common/ffsops.cpp b/common/ffsops.cpp index f34bb65..3922e6b 100644 --- a/common/ffsops.cpp +++ b/common/ffsops.cpp @@ -21,33 +21,12 @@ USTATUS FfsOperations::extract(const UModelIndex & index, UString & name, UByteA if (!index.isValid()) return U_INVALID_PARAMETER; - // Get data from parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(index); - // Construct a name for extracted data UString itemName = model->name(index); UString itemText = model->text(index); // Default name - name = itemName.replace(' ', '_').replace('/', '_').replace('-', '_'); - - switch (model->type(index)) { - case Types::Volume: if (pdata.volume.hasExtendedHeader) name = guidToUString(pdata.volume.extendedHeaderGuid).replace('-', '_'); break; - case Types::NvarEntry: - case Types::VssEntry: - case Types::FsysEntry: - case Types::EvsaEntry: - case Types::FlashMapEntry: - case Types::File: name = itemText.isEmpty() ? itemName : itemText.replace(' ', '_').replace('-', '_'); break; - case Types::Section: { - // Get parent file name - UModelIndex fileIndex = model->findParentOfType(index, Types::File); - UString fileText = model->text(fileIndex); - name = fileText.isEmpty() ? model->name(fileIndex) : fileText.replace(' ', '_').replace('-', '_'); - // Append section subtype name - name += '_' + itemName.replace(' ', '_'); - } break; - } + name = uniqueItemName(index); // Get extracted data if (mode == EXTRACT_MODE_AS_IS) { @@ -90,9 +69,6 @@ USTATUS FfsOperations::replace(const UModelIndex & index, const UString & data, if (!index.isValid()) return U_INVALID_PARAMETER; - // Get data from parsing data - //PARSING_DATA pdata = parsingDataFromQModelIndex(index); - if (mode == REPLACE_MODE_AS_IS) { return U_NOT_IMPLEMENTED; } diff --git a/common/ffsparser.cpp b/common/ffsparser.cpp index 5c92a1a..38ef060 100644 --- a/common/ffsparser.cpp +++ b/common/ffsparser.cpp @@ -103,7 +103,7 @@ USTATUS FfsParser::performFirstPass(const UByteArray & buffer, UModelIndex & ind capsuleOffsetFixup = capsuleHeaderSize; // Add tree item - index = model->addItem(Types::Capsule, Subtypes::UefiCapsule, name, UString(), info, header, body, UByteArray(), true); + index = model->addItem(0, Types::Capsule, Subtypes::UefiCapsule, name, UString(), info, header, body, UByteArray(), Fixed); } // Check buffer for being Toshiba capsule header else if (buffer.startsWith(TOSHIBA_CAPSULE_GUID)) { @@ -137,7 +137,7 @@ USTATUS FfsParser::performFirstPass(const UByteArray & buffer, UModelIndex & ind capsuleOffsetFixup = capsuleHeaderSize; // Add tree item - index = model->addItem(Types::Capsule, Subtypes::ToshibaCapsule, name, UString(), info, header, body, UByteArray(), true); + index = model->addItem(0, Types::Capsule, Subtypes::ToshibaCapsule, name, UString(), info, header, body, UByteArray(), Fixed); } // Check buffer for being extended Aptio capsule header else if (buffer.startsWith(APTIO_SIGNED_CAPSULE_GUID) || buffer.startsWith(APTIO_UNSIGNED_CAPSULE_GUID)) { @@ -179,7 +179,7 @@ USTATUS FfsParser::performFirstPass(const UByteArray & buffer, UModelIndex & ind capsuleOffsetFixup = capsuleHeaderSize; // Add tree item - index = model->addItem(Types::Capsule, signedCapsule ? Subtypes::AptioSignedCapsule : Subtypes::AptioUnsignedCapsule, name, UString(), info, header, body, UByteArray(), true); + index = model->addItem(0, Types::Capsule, signedCapsule ? Subtypes::AptioSignedCapsule : Subtypes::AptioUnsignedCapsule, name, UString(), info, header, body, UByteArray(), Fixed); // Show message about possible Aptio signature break if (signedCapsule) { @@ -198,10 +198,11 @@ USTATUS FfsParser::performFirstPass(const UByteArray & buffer, UModelIndex & ind if (descriptorHeader->Signature == FLASH_DESCRIPTOR_SIGNATURE) { // Parse as Intel image UModelIndex imageIndex; - result = parseIntelImage(flashImage, capsuleHeaderSize, index, imageIndex); + result = parseIntelImage(flashImage, capsuleOffsetFixup, index, imageIndex); if (result != U_INVALID_FLASH_DESCRIPTOR) { - if (!index.isValid()) + if (!index.isValid()) { index = imageIndex; + } return result; } } @@ -210,12 +211,8 @@ USTATUS FfsParser::performFirstPass(const UByteArray & buffer, UModelIndex & ind UString name("UEFI image"); UString info = usprintf("Full size: %Xh (%u)", flashImage.size(), flashImage.size()); - // Construct parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(index); - pdata.offset = capsuleHeaderSize; - // Add tree item - UModelIndex biosIndex = model->addItem(Types::Image, Subtypes::UefiImage, name, UString(), info, UByteArray(), flashImage, UByteArray(), true, parsingDataToUByteArray(pdata), index); + UModelIndex biosIndex = model->addItem(capsuleOffsetFixup, Types::Image, Subtypes::UefiImage, name, UString(), info, UByteArray(), flashImage, UByteArray(), Fixed, index); // Parse the image result = parseRawArea(biosIndex); @@ -224,15 +221,12 @@ USTATUS FfsParser::performFirstPass(const UByteArray & buffer, UModelIndex & ind return result; } -USTATUS FfsParser::parseIntelImage(const UByteArray & intelImage, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index) +USTATUS FfsParser::parseIntelImage(const UByteArray & intelImage, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index) { // Sanity check if (intelImage.isEmpty()) return EFI_INVALID_PARAMETER; - // Get parent's parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(parent); - // Store the beginning of descriptor as descriptor base address const UINT8* descriptor = (const UINT8*)intelImage.constData(); @@ -485,10 +479,10 @@ USTATUS FfsParser::parseIntelImage(const UByteArray & intelImage, const UINT32 p descriptorMap->NumberOfProcStraps); // Construct parsing data - pdata.offset = parentOffset; + //pdata.offset = localOffset; // Add Intel image tree item - index = model->addItem(Types::Image, Subtypes::IntelImage, name, UString(), info, UByteArray(), intelImage, UByteArray(), true, parsingDataToUByteArray(pdata), parent); + index = model->addItem(localOffset, Types::Image, Subtypes::IntelImage, name, UString(), info, UByteArray(), intelImage, UByteArray(), Fixed, parent); // Descriptor // Get descriptor info @@ -500,7 +494,7 @@ USTATUS FfsParser::parseIntelImage(const UByteArray & intelImage, const UINT32 p for (size_t i = 0; i < regions.size(); i++) { if (regions[i].type != Subtypes::ZeroPadding && regions[i].type != Subtypes::OnePadding && regions[i].type != Subtypes::DataPadding) info += UString("\n") + itemSubtypeToUString(Types::Region, regions[i].type) - + usprintf(" region offset: %Xh", regions[i].offset + parentOffset); + + usprintf(" region offset: %Xh", regions[i].offset + localOffset); } // Region access settings @@ -575,7 +569,7 @@ USTATUS FfsParser::parseIntelImage(const UByteArray & intelImage, const UINT32 p } // Add descriptor tree item - UModelIndex regionIndex = model->addItem(Types::Region, Subtypes::DescriptorRegion, name, UString(), info, UByteArray(), body, UByteArray(), true, parsingDataToUByteArray(pdata), index); + UModelIndex regionIndex = model->addItem(localOffset, Types::Region, Subtypes::DescriptorRegion, name, UString(), info, UByteArray(), body, UByteArray(), Fixed, index); // Parse regions UINT8 result = U_SUCCESS; @@ -608,19 +602,13 @@ USTATUS FfsParser::parseIntelImage(const UByteArray & intelImage, const UINT32 p // Add padding between regions UByteArray padding = intelImage.mid(region.offset, region.length); - // Get parent's parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(index); - // Get info name = UString("Padding"); info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size()); - // Construct parsing data - pdata.offset = parentOffset + region.offset; - // Add tree item - regionIndex = model->addItem(Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), true, parsingDataToUByteArray(pdata), index); + regionIndex = model->addItem(localOffset + region.offset, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); result = U_SUCCESS; } break; default: @@ -628,14 +616,15 @@ USTATUS FfsParser::parseIntelImage(const UByteArray & intelImage, const UINT32 p result = U_INVALID_FLASH_DESCRIPTOR; } // Store the first failed result as a final result - if (!parseResult && result) + if (!parseResult && result) { parseResult = result; + } } return parseResult; } -USTATUS FfsParser::parseGbeRegion(const UByteArray & gbe, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index) +USTATUS FfsParser::parseGbeRegion(const UByteArray & gbe, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index) { // Check sanity if (gbe.isEmpty()) @@ -643,9 +632,6 @@ USTATUS FfsParser::parseGbeRegion(const UByteArray & gbe, const UINT32 parentOff if ((UINT32)gbe.size() < GBE_VERSION_OFFSET + sizeof(GBE_VERSION)) return U_INVALID_REGION; - // Get parent's parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(parent); - // Get info UString name("GbE region"); const GBE_MAC_ADDRESS* mac = (const GBE_MAC_ADDRESS*)gbe.constData(); @@ -657,24 +643,18 @@ USTATUS FfsParser::parseGbeRegion(const UByteArray & gbe, const UINT32 parentOff version->major, version->minor); - // Construct parsing data - pdata.offset += parentOffset; - // Add tree item - index = model->addItem(Types::Region, Subtypes::GbeRegion, name, UString(), info, UByteArray(), gbe, UByteArray(), true, parsingDataToUByteArray(pdata), parent); + index = model->addItem(model->offset(parent) + localOffset, Types::Region, Subtypes::GbeRegion, name, UString(), info, UByteArray(), gbe, UByteArray(), Fixed, parent); return U_SUCCESS; } -USTATUS FfsParser::parseMeRegion(const UByteArray & me, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index) +USTATUS FfsParser::parseMeRegion(const UByteArray & me, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index) { // Check sanity if (me.isEmpty()) return U_EMPTY_REGION; - // Get parent's parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(parent); - // Get info UString name("ME region"); UString info = usprintf("Full size: %Xh (%u)", me.size(), me.size()); @@ -715,11 +695,8 @@ USTATUS FfsParser::parseMeRegion(const UByteArray & me, const UINT32 parentOffse } } - // Construct parsing data - pdata.offset += parentOffset; - // Add tree item - index = model->addItem(Types::Region, Subtypes::MeRegion, name, UString(), info, UByteArray(), me, UByteArray(), true, parsingDataToUByteArray(pdata), parent); + index = model->addItem(model->offset(parent) + localOffset, Types::Region, Subtypes::MeRegion, name, UString(), info, UByteArray(), me, UByteArray(), Fixed, parent); // Show messages if (emptyRegion) { @@ -732,24 +709,18 @@ USTATUS FfsParser::parseMeRegion(const UByteArray & me, const UINT32 parentOffse return U_SUCCESS; } -USTATUS FfsParser::parsePdrRegion(const UByteArray & pdr, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index) +USTATUS FfsParser::parsePdrRegion(const UByteArray & pdr, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index) { // Check sanity if (pdr.isEmpty()) return U_EMPTY_REGION; - // Get parent's parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(parent); - // Get info UString name("PDR region"); UString info = usprintf("Full size: %Xh (%u)", pdr.size(), pdr.size()); - // Construct parsing data - pdata.offset += parentOffset; - // Add tree item - index = model->addItem(Types::Region, Subtypes::PdrRegion, name, UString(), info, UByteArray(), pdr, UByteArray(), true, parsingDataToUByteArray(pdata), parent); + index = model->addItem(model->offset(parent) + localOffset, Types::Region, Subtypes::PdrRegion, name, UString(), info, UByteArray(), pdr, UByteArray(), Fixed, parent); // Parse PDR region as BIOS space UINT8 result = parseRawArea(index); @@ -759,46 +730,34 @@ USTATUS FfsParser::parsePdrRegion(const UByteArray & pdr, const UINT32 parentOff return U_SUCCESS; } -USTATUS FfsParser::parseGeneralRegion(const UINT8 subtype, const UByteArray & region, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index) +USTATUS FfsParser::parseGeneralRegion(const UINT8 subtype, const UByteArray & region, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index) { // Check sanity if (region.isEmpty()) return U_EMPTY_REGION; - // Get parent's parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(parent); - // Get info UString name = itemSubtypeToUString(Types::Region, subtype) + UString(" region"); UString info = usprintf("Full size: %Xh (%u)", region.size(), region.size()); - // Construct parsing data - pdata.offset += parentOffset; - // Add tree item - index = model->addItem(Types::Region, subtype, name, UString(), info, UByteArray(), region, UByteArray(), true, parsingDataToUByteArray(pdata), parent); + index = model->addItem(model->offset(parent) + localOffset, Types::Region, subtype, name, UString(), info, UByteArray(), region, UByteArray(), Fixed, parent); return U_SUCCESS; } -USTATUS FfsParser::parseBiosRegion(const UByteArray & bios, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index) +USTATUS FfsParser::parseBiosRegion(const UByteArray & bios, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index) { // Sanity check if (bios.isEmpty()) return U_EMPTY_REGION; - // Get parent's parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(parent); - // Get info UString name("BIOS region"); UString info = usprintf("Full size: %Xh (%u)", bios.size(), bios.size()); - // Construct parsing data - pdata.offset += parentOffset; - // Add tree item - index = model->addItem(Types::Region, Subtypes::BiosRegion, name, UString(), info, UByteArray(), bios, UByteArray(), true, parsingDataToUByteArray(pdata), parent); + index = model->addItem(model->offset(parent) + localOffset, Types::Region, Subtypes::BiosRegion, name, UString(), info, UByteArray(), bios, UByteArray(), Fixed, parent); return parseRawArea(index); } @@ -810,9 +769,8 @@ USTATUS FfsParser::parseRawArea(const UModelIndex & index) return U_INVALID_PARAMETER; // Get parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(index); UINT32 headerSize = model->header(index).size(); - UINT32 offset = pdata.offset + headerSize; + UINT32 offset = model->offset(index) + headerSize; // Get item data UByteArray data = model->body(index); @@ -834,11 +792,8 @@ USTATUS FfsParser::parseRawArea(const UModelIndex & index) name = UString("Padding"); info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size()); - // Construct parsing data - pdata.offset = offset; - // Add tree item - model->addItem(Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), true, parsingDataToUByteArray(pdata), index); + model->addItem(offset, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); } // Search for and parse all volumes @@ -857,11 +812,8 @@ USTATUS FfsParser::parseRawArea(const UModelIndex & index) name = UString("Padding"); info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size()); - // Construct parsing data - pdata.offset = offset + paddingOffset; - // Add tree item - model->addItem(Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), true, parsingDataToUByteArray(pdata), index); + model->addItem(offset + paddingOffset, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); } // Get volume size @@ -875,24 +827,15 @@ USTATUS FfsParser::parseRawArea(const UModelIndex & index) // Check that volume is fully present in input if (volumeSize > (UINT32)data.size() || volumeOffset + volumeSize > (UINT32)data.size()) { - msg(UString("parseRawArea: one of volumes inside overlaps the end of data"), index); - return U_INVALID_VOLUME; - } - - UByteArray volume = data.mid(volumeOffset, volumeSize); - if (volumeSize > (UINT32)volume.size()) { // Mark the rest as padding and finish the parsing - UByteArray padding = data.right(volume.size()); + UByteArray padding = data.mid(volumeOffset); // Get info name = UString("Padding"); info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size()); - // Construct parsing data - pdata.offset = offset + volumeOffset; - // Add tree item - UModelIndex paddingIndex = model->addItem(Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), true, parsingDataToUByteArray(pdata), index); + UModelIndex paddingIndex = model->addItem(offset + volumeOffset, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); msg(UString("parseRawArea: one of volumes inside overlaps the end of data"), paddingIndex); // Update variables @@ -900,9 +843,10 @@ USTATUS FfsParser::parseRawArea(const UModelIndex & index) prevVolumeSize = padding.size(); break; } - + // Parse current volume's header UModelIndex volumeIndex; + UByteArray volume = data.mid(volumeOffset, volumeSize); result = parseVolumeHeader(volume, headerSize + volumeOffset, index, volumeIndex); if (result) msg(UString("parseRawArea: volume header parsing failed with error ") + errorCodeToUString(result), index); @@ -930,11 +874,8 @@ USTATUS FfsParser::parseRawArea(const UModelIndex & index) name = UString("Padding"); info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size()); - // Construct parsing data - pdata.offset = offset + headerSize + volumeOffset; - // Add tree item - model->addItem(Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), true, parsingDataToUByteArray(pdata), index); + model->addItem(offset + volumeOffset, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); } // Parse bodies @@ -955,15 +896,12 @@ USTATUS FfsParser::parseRawArea(const UModelIndex & index) return U_SUCCESS; } -USTATUS FfsParser::parseVolumeHeader(const UByteArray & volume, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index) +USTATUS FfsParser::parseVolumeHeader(const UByteArray & volume, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index) { // Sanity check if (volume.isEmpty()) return U_INVALID_PARAMETER; - // Get parent's parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(parent); - // Check that there is space for the volume header if ((UINT32)volume.size() < sizeof(EFI_FIRMWARE_VOLUME_HEADER)) { msg(usprintf("parseVolumeHeader: input volume size %Xh (%u) is smaller than volume header size 40h (64)", volume.size(), volume.size())); @@ -987,7 +925,7 @@ USTATUS FfsParser::parseVolumeHeader(const UByteArray & volume, const UINT32 par // Calculate volume header size UINT32 headerSize; - EFI_GUID extendedHeaderGuid = {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }}; + EFI_GUID extendedHeaderGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0 }}; bool hasExtendedHeader = false; if (volumeHeader->Revision > 1 && volumeHeader->ExtHeaderOffset) { hasExtendedHeader = true; @@ -1007,7 +945,7 @@ USTATUS FfsParser::parseVolumeHeader(const UByteArray & volume, const UINT32 par UINT8 ffsVersion = 0; // Check for FFS v2 volume - UByteArray guid = UByteArray((const char*)volumeHeader->FileSystemGuid.Data, sizeof(EFI_GUID)); + UByteArray guid = UByteArray((const char*)&volumeHeader->FileSystemGuid, sizeof(EFI_GUID)); if (std::find(FFSv2Volumes.begin(), FFSv2Volumes.end(), guid) != FFSv2Volumes.end()) { isUnknown = false; ffsVersion = 2; @@ -1044,7 +982,7 @@ USTATUS FfsParser::parseVolumeHeader(const UByteArray & volume, const UINT32 par // Acquire alignment alignment = (UINT32)pow(2.0, (int)(volumeHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16); // Check alignment - if (!isUnknown && !model->compressed(parent) && ((pdata.offset + parentOffset - capsuleOffsetFixup) % alignment)) + if (!isUnknown && !model->compressed(parent) && ((model->offset(parent) + localOffset - capsuleOffsetFixup) % alignment)) msgUnaligned = true; } else @@ -1109,18 +1047,6 @@ USTATUS FfsParser::parseVolumeHeader(const UByteArray & volume, const UINT32 par extendedHeader->ExtHeaderSize, extendedHeader->ExtHeaderSize) + guidToUString(extendedHeader->FvName); } - // Construct parsing data - pdata.offset += parentOffset; - pdata.emptyByte = emptyByte; - pdata.ffsVersion = ffsVersion; - pdata.volume.hasExtendedHeader = hasExtendedHeader ? TRUE : FALSE; - pdata.volume.extendedHeaderGuid = extendedHeaderGuid; - pdata.volume.alignment = alignment; - pdata.volume.revision = volumeHeader->Revision; - pdata.volume.hasAppleCrc32 = hasAppleCrc32; - pdata.volume.hasAppleFSO = hasAppleFSO; - pdata.volume.isWeakAligned = (volumeHeader->Revision > 1 && (volumeHeader->Attributes & EFI_FVB2_WEAK_ALIGNMENT)); - // Add text UString text; if (hasAppleCrc32) @@ -1138,7 +1064,20 @@ USTATUS FfsParser::parseVolumeHeader(const UByteArray & volume, const UINT32 par else if (isNvramVolume) subtype = Subtypes::NvramVolume; } - index = model->addItem(Types::Volume, subtype, name, text, info, header, body, UByteArray(), true, parsingDataToUByteArray(pdata), parent); + index = model->addItem(model->offset(parent) + localOffset, Types::Volume, subtype, name, text, info, header, body, UByteArray(), Fixed, parent); + + // Set parsing data for created item + VOLUME_PARSING_DATA pdata; + pdata.emptyByte = emptyByte; + pdata.ffsVersion = ffsVersion; + pdata.hasExtendedHeader = hasExtendedHeader ? TRUE : FALSE; + pdata.extendedHeaderGuid = extendedHeaderGuid; + pdata.alignment = alignment; + pdata.revision = volumeHeader->Revision; + pdata.hasAppleCrc32 = hasAppleCrc32; + pdata.hasAppleFSO = hasAppleFSO; + pdata.isWeakAligned = (volumeHeader->Revision > 1 && (volumeHeader->Attributes & EFI_FVB2_WEAK_ALIGNMENT)); + model->setParsingData(index, UByteArray((const char*)&pdata, sizeof(pdata))); // Show messages if (isUnknown) @@ -1155,7 +1094,7 @@ USTATUS FfsParser::parseVolumeHeader(const UByteArray & volume, const UINT32 par return U_SUCCESS; } -USTATUS FfsParser::findNextVolume(const UModelIndex & index, const UByteArray & bios, const UINT32 parentOffset, const UINT32 volumeOffset, UINT32 & nextVolumeOffset) +USTATUS FfsParser::findNextVolume(const UModelIndex & index, const UByteArray & bios, const UINT32 localOffset, const UINT32 volumeOffset, UINT32 & nextVolumeOffset) { int nextIndex = bios.indexOf(EFI_FV_SIGNATURE, volumeOffset); if (nextIndex < EFI_FV_SIGNATURE_OFFSET) @@ -1166,14 +1105,14 @@ USTATUS FfsParser::findNextVolume(const UModelIndex & index, const UByteArray & const EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (const EFI_FIRMWARE_VOLUME_HEADER*)(bios.constData() + nextIndex - EFI_FV_SIGNATURE_OFFSET); if (volumeHeader->FvLength < sizeof(EFI_FIRMWARE_VOLUME_HEADER) + 2 * sizeof(EFI_FV_BLOCK_MAP_ENTRY) || volumeHeader->FvLength >= 0xFFFFFFFFUL) { msg(usprintf("findNextVolume: volume candidate at offset %Xh skipped, has invalid FvLength %" PRIX64 "h", - parentOffset + (nextIndex - EFI_FV_SIGNATURE_OFFSET), + localOffset + (nextIndex - EFI_FV_SIGNATURE_OFFSET), volumeHeader->FvLength), index); continue; } if (volumeHeader->Revision != 1 && volumeHeader->Revision != 2) { msg(usprintf("findNextVolume: volume candidate at offset %Xh skipped, has invalid Revision byte value %02Xh", - parentOffset + (nextIndex - EFI_FV_SIGNATURE_OFFSET) - ,volumeHeader->Revision), index); + localOffset + (nextIndex - EFI_FV_SIGNATURE_OFFSET), + volumeHeader->Revision), index); continue; } // All checks passed, volume found @@ -1187,7 +1126,7 @@ USTATUS FfsParser::findNextVolume(const UModelIndex & index, const UByteArray & return U_SUCCESS; } -USTATUS FfsParser::getVolumeSize(const UByteArray & bios, UINT32 volumeOffset, UINT32 & volumeSize, UINT32 & bmVolumeSize) +USTATUS FfsParser::getVolumeSize(const UByteArray & bios, const UINT32 volumeOffset, UINT32 & volumeSize, UINT32 & bmVolumeSize) { // Check that there is space for the volume header and at least two block map entries. if ((UINT32)bios.size() < volumeOffset + sizeof(EFI_FIRMWARE_VOLUME_HEADER) + 2 * sizeof(EFI_FV_BLOCK_MAP_ENTRY)) @@ -1220,23 +1159,17 @@ USTATUS FfsParser::getVolumeSize(const UByteArray & bios, UINT32 volumeOffset, U return U_SUCCESS; } -USTATUS FfsParser::parseVolumeNonUefiData(const UByteArray & data, const UINT32 parentOffset, const UModelIndex & index) +USTATUS FfsParser::parseVolumeNonUefiData(const UByteArray & data, const UINT32 localOffset, const UModelIndex & index) { // Sanity check if (!index.isValid()) return U_INVALID_PARAMETER; - // Get parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(index); - - // Add parent offset - pdata.offset += parentOffset; - // Get info 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"), UString(), info, UByteArray(), data, UByteArray(), true, parsingDataToUByteArray(pdata), index); + UModelIndex paddingIndex = model->addItem(model->offset(index) + localOffset, Types::Padding, Subtypes::DataPadding, UString("Non-UEFI data"), UString(), info, UByteArray(), data, UByteArray(), Fixed, index); msg(UString("parseVolumeNonUefiData: non-UEFI data found in volume's free space"), paddingIndex); // Parse contents as RAW area @@ -1253,15 +1186,22 @@ USTATUS FfsParser::parseVolumeBody(const UModelIndex & index) UByteArray volumeBody = model->body(index); UINT32 volumeHeaderSize = model->header(index).size(); - // Get parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(index); - UINT32 offset = pdata.offset; - // Parse VSS NVRAM volumes with a dedicated function if (model->subtype(index) == Subtypes::NvramVolume) return nvramParser.parseNvramVolumeBody(index); - if (pdata.ffsVersion != 2 && pdata.ffsVersion != 3) // Don't parse unknown volumes + // Get required values from parsing data + UINT8 emptyByte = 0xFF; + UINT8 ffsVersion = 2; + if (model->hasEmptyParsingData(index) == false) { + UByteArray data = model->parsingData(index); + const VOLUME_PARSING_DATA* pdata = (const VOLUME_PARSING_DATA*)data.constData(); + emptyByte = pdata->emptyByte; + ffsVersion = pdata->ffsVersion; + } + + // Check for unknown FFS version + if (ffsVersion != 2 && ffsVersion != 3) return U_SUCCESS; // Search for and parse all files @@ -1269,31 +1209,29 @@ USTATUS FfsParser::parseVolumeBody(const UModelIndex & index) UINT32 fileOffset = 0; while (fileOffset < volumeBodySize) { - UINT32 fileSize = getFileSize(volumeBody, fileOffset, pdata.ffsVersion); + UINT32 fileSize = getFileSize(volumeBody, fileOffset, ffsVersion); // Check file size if (fileSize < sizeof(EFI_FFS_FILE_HEADER) || fileSize > volumeBodySize - fileOffset) { // Check that we are at the empty space UByteArray header = volumeBody.mid(fileOffset, sizeof(EFI_FFS_FILE_HEADER)); - if (header.count(pdata.emptyByte) == header.size()) { //Empty space + if (header.count(emptyByte) == header.size()) { //Empty space // Check free space to be actually free UByteArray freeSpace = volumeBody.mid(fileOffset); - if (freeSpace.count(pdata.emptyByte) != freeSpace.size()) { + if (freeSpace.count(emptyByte) != freeSpace.size()) { // Search for the first non-empty byte UINT32 i; UINT32 size = freeSpace.size(); const UINT8* current = (UINT8*)freeSpace.constData(); for (i = 0; i < size; i++) { - if (*current++ != pdata.emptyByte) + if (*current++ != emptyByte) break; } // Align found index to file alignment // It must be possible because minimum 16 bytes of empty were found before - if (i != ALIGN8(i)) + if (i != ALIGN8(i)) { i = ALIGN8(i) - 8; - - // Construct parsing data - pdata.offset = offset + volumeHeaderSize + fileOffset; + } // Add all bytes before as free space if (i > 0) { @@ -1303,21 +1241,18 @@ 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"), UString(), info, UByteArray(), free, UByteArray(), false, parsingDataToUByteArray(pdata), index); + model->addItem(model->offset(index) + volumeHeaderSize + fileOffset, Types::FreeSpace, 0, UString("Volume free space"), UString(), info, UByteArray(), free, UByteArray(), Movable, index); } // Parse non-UEFI data parseVolumeNonUefiData(freeSpace.mid(i), volumeHeaderSize + fileOffset + i, index); } else { - // Construct parsing data - pdata.offset = offset + volumeHeaderSize + fileOffset; - // Get info UString info = usprintf("Full size: %Xh (%u)", freeSpace.size(), freeSpace.size()); // Add free space item - model->addItem(Types::FreeSpace, 0, UString("Volume free space"), UString(), info, UByteArray(), freeSpace, UByteArray(), false, parsingDataToUByteArray(pdata), index); + model->addItem(model->offset(index) + volumeHeaderSize + fileOffset, Types::FreeSpace, 0, UString("Volume free space"), UString(), info, UByteArray(), freeSpace, UByteArray(), Movable, index); } break; // Exit from parsing loop } @@ -1332,7 +1267,7 @@ USTATUS FfsParser::parseVolumeBody(const UModelIndex & index) UByteArray file = volumeBody.mid(fileOffset, fileSize); UByteArray header = file.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)) { + if (ffsVersion == 3 && (fileHeader->Attributes & FFS_ATTRIB_LARGE_FILE)) { header = file.left(sizeof(EFI_FFS_FILE_HEADER2)); } @@ -1354,9 +1289,8 @@ USTATUS FfsParser::parseVolumeBody(const UModelIndex & index) if (model->type(current) != Types::File || model->subtype(current) == EFI_FV_FILETYPE_PAD) continue; - // Get current file parsing data - PARSING_DATA currentPdata = parsingDataFromUModelIndex(current); - UByteArray currentGuid((const char*)¤tPdata.file.guid, sizeof(EFI_GUID)); + // Get current file GUID + UByteArray currentGuid(model->header(current).constData(), sizeof(EFI_GUID)); // Check files after current for having an equal GUID for (int j = i + 1; j < model->rowCount(index); j++) { @@ -1366,13 +1300,12 @@ USTATUS FfsParser::parseVolumeBody(const UModelIndex & index) if (model->type(another) != Types::File) continue; - // Get another file parsing data - PARSING_DATA anotherPdata = parsingDataFromUModelIndex(another); - UByteArray anotherGuid((const char*)&anotherPdata.file.guid, sizeof(EFI_GUID)); + // Get another file GUID + UByteArray anotherGuid(model->header(another).constData(), sizeof(EFI_GUID)); // Check GUIDs for being equal if (currentGuid == anotherGuid) { - msg(UString("parseVolumeBody: file with duplicate GUID ") + guidToUString(anotherPdata.file.guid), another); + msg(UString("parseVolumeBody: file with duplicate GUID ") + guidToUString(*(EFI_GUID*)(anotherGuid.data())), another); } } } @@ -1417,7 +1350,7 @@ UINT32 FfsParser::getFileSize(const UByteArray & volume, const UINT32 fileOffset return 0; } -USTATUS FfsParser::parseFileHeader(const UByteArray & file, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index) +USTATUS FfsParser::parseFileHeader(const UByteArray & file, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index) { // Sanity check if (file.isEmpty()) @@ -1426,13 +1359,24 @@ USTATUS FfsParser::parseFileHeader(const UByteArray & file, const UINT32 parentO if ((UINT32)file.size() < sizeof(EFI_FFS_FILE_HEADER)) return U_INVALID_FILE; - // Get parent's parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(parent); + // Obtain required information from parent volume + UINT8 ffsVersion = 2; + bool isWeakAligned = false; + UINT32 volumeAlignment = 0xFFFFFFFF; + UINT8 volumeRevision = 2; + UModelIndex parentVolumeIndex = model->findParentOfType(parent, Types::Volume); + if (parentVolumeIndex.isValid() && model->hasEmptyParsingData(parentVolumeIndex) == false) { + UByteArray data = model->parsingData(parentVolumeIndex); + const VOLUME_PARSING_DATA* pdata = (const VOLUME_PARSING_DATA*)data.constData(); + ffsVersion = pdata->ffsVersion; + volumeAlignment = pdata->alignment; + volumeRevision = pdata->revision; + } // Get file header UByteArray header = file.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)) { + if (ffsVersion == 3 && (fileHeader->Attributes & FFS_ATTRIB_LARGE_FILE)) { if ((UINT32)file.size() < sizeof(EFI_FFS_FILE_HEADER2)) return U_INVALID_FILE; header = file.left(sizeof(EFI_FFS_FILE_HEADER2)); @@ -1442,13 +1386,13 @@ USTATUS FfsParser::parseFileHeader(const UByteArray & file, const UINT32 parentO bool msgUnalignedFile = false; UINT8 alignmentPower = ffsAlignmentTable[(fileHeader->Attributes & FFS_ATTRIB_DATA_ALIGNMENT) >> 3]; UINT32 alignment = (UINT32)pow(2.0, alignmentPower); - if ((parentOffset + header.size()) % alignment) + if ((localOffset + header.size()) % alignment) msgUnalignedFile = true; // Check file alignment agains volume alignment - bool msgFileAlignmentIsGreaterThanVolumes = false; - if (!pdata.volume.isWeakAligned && pdata.volume.alignment < alignment) - msgFileAlignmentIsGreaterThanVolumes = true; + bool msgFileAlignmentIsGreaterThanVolumeAlignment = false; + if (!isWeakAligned && volumeAlignment < alignment) + msgFileAlignmentIsGreaterThanVolumeAlignment = true; // Check header checksum UByteArray tempHeader = header; @@ -1467,25 +1411,25 @@ USTATUS FfsParser::parseFileHeader(const UByteArray & file, const UINT32 parentO if (fileHeader->Attributes & FFS_ATTRIB_CHECKSUM) { UINT32 bufferSize = file.size() - header.size(); // Exclude file tail from data checksum calculation - if (pdata.volume.revision == 1 && (fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT)) + if (volumeRevision == 1 && (fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT)) bufferSize -= sizeof(UINT16); calculatedData = calculateChecksum8((const UINT8*)(file.constData() + header.size()), bufferSize); if (fileHeader->IntegrityCheck.Checksum.File != calculatedData) msgInvalidDataChecksum = true; } // Data checksum must be one of predefined values - else if (pdata.volume.revision == 1 && fileHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) { + else if (volumeRevision == 1 && fileHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) { calculatedData = FFS_FIXED_CHECKSUM; msgInvalidDataChecksum = true; } - else if (pdata.volume.revision == 2 && fileHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM2) { + else if (volumeRevision == 2 && fileHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM2) { calculatedData = FFS_FIXED_CHECKSUM2; msgInvalidDataChecksum = true; } // Check file type bool msgUnknownType = false; - if (fileHeader->Type > EFI_FV_FILETYPE_SMM_CORE && fileHeader->Type != EFI_FV_FILETYPE_PAD) { + if (fileHeader->Type > EFI_FV_FILETYPE_MM_CORE_STANDALONE && fileHeader->Type != EFI_FV_FILETYPE_PAD) { msgUnknownType = true; }; @@ -1495,8 +1439,7 @@ USTATUS FfsParser::parseFileHeader(const UByteArray & file, const UINT32 parentO // Check for file tail presence UByteArray tail; bool msgInvalidTailValue = false; - if (pdata.volume.revision == 1 && (fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT)) - { + if (volumeRevision == 1 && (fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT)) { //Check file tail; UINT16 tailValue = *(UINT16*)body.right(sizeof(UINT16)).constData(); if (fileHeader->IntegrityCheck.TailReference != (UINT16)~tailValue) @@ -1527,9 +1470,6 @@ USTATUS FfsParser::parseFileHeader(const UByteArray & file, const UINT32 parentO usprintf("\nHeader checksum: %02Xh", fileHeader->IntegrityCheck.Checksum.Header) + (msgInvalidHeaderChecksum ? usprintf(", invalid, should be %02Xh", calculatedHeader) : UString(", valid")) + usprintf("\nData checksum: %02Xh", fileHeader->IntegrityCheck.Checksum.File) + (msgInvalidDataChecksum ? usprintf(", invalid, should be %02Xh", calculatedData) : UString(", valid")); - // Add file GUID to parsing data - pdata.file.guid = fileHeader->Name; - UString text; bool isVtf = false; // Check if the file is a Volume Top File @@ -1541,15 +1481,18 @@ USTATUS FfsParser::parseFileHeader(const UByteArray & file, const UINT32 parentO text = UString("Volume Top File"); } - // Construct parsing data - bool fixed = (fileHeader->Attributes & FFS_ATTRIB_FIXED) != 0; - pdata.offset += parentOffset; - + // Construct fixed state + ItemFixedState fixed = (ItemFixedState)((fileHeader->Attributes & FFS_ATTRIB_FIXED) != 0); // Add tree item - index = model->addItem(Types::File, fileHeader->Type, name, text, info, header, body, tail, fixed, parsingDataToUByteArray(pdata), parent); + index = model->addItem(model->offset(parent) + localOffset, Types::File, fileHeader->Type, name, text, info, header, body, tail, fixed, parent); - // Overwrite lastVtf, if needed + // Set parsing data for created file + FILE_PARSING_DATA pdata; + pdata.emptyByte = (fileHeader->State & EFI_FILE_ERASE_POLARITY) ? 0xFF : 0x00; + pdata.guid = fileHeader->Name; + + // Override lastVtf index, if needed if (isVtf) { lastVtf = index; } @@ -1557,8 +1500,8 @@ USTATUS FfsParser::parseFileHeader(const UByteArray & file, const UINT32 parentO // Show messages if (msgUnalignedFile) msg(UString("parseFileHeader: unaligned file"), index); - if (msgFileAlignmentIsGreaterThanVolumes) - msg(usprintf("parseFileHeader: file alignment %Xh is greater than parent volume alignment %Xh", alignment, pdata.volume.alignment), index); + if (msgFileAlignmentIsGreaterThanVolumeAlignment) + msg(usprintf("parseFileHeader: file alignment %Xh is greater than parent volume alignment %Xh", alignment, volumeAlignment), index); if (msgInvalidHeaderChecksum) msg(UString("parseFileHeader: invalid header checksum"), index); if (msgInvalidDataChecksum) @@ -1609,11 +1552,8 @@ USTATUS FfsParser::parseFileBody(const UModelIndex & index) // Parse raw files as raw areas if (model->subtype(index) == EFI_FV_FILETYPE_RAW || model->subtype(index) == EFI_FV_FILETYPE_ALL) { - // Get data from parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(index); - // Parse NVAR store - if (UByteArray((const char*)&pdata.file.guid, sizeof(EFI_GUID)) == NVRAM_NVAR_STORE_FILE_GUID) + if (UByteArray(model->header(index).constData(), sizeof(EFI_GUID)) == NVRAM_NVAR_STORE_FILE_GUID) return nvramParser.parseNvarStore(index); return parseRawArea(index); @@ -1629,54 +1569,57 @@ USTATUS FfsParser::parsePadFileBody(const UModelIndex & index) if (!index.isValid()) return U_INVALID_PARAMETER; - // Get data from parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(index); - // Check if all bytes of the file are empty UByteArray body = model->body(index); - if (body.size() == body.count(pdata.emptyByte)) + + // Obtain required information from parent file + UINT8 emptyByte = 0xFF; + UModelIndex parentFileIndex = model->findParentOfType(index, Types::File); + if (parentFileIndex.isValid() && model->hasEmptyParsingData(parentFileIndex) == false) { + UByteArray data = model->parsingData(index); + const FILE_PARSING_DATA* pdata = (const FILE_PARSING_DATA*)data.constData(); + emptyByte = pdata->emptyByte; + } + + // Check if the while PAD file is empty + if (body.size() == body.count(emptyByte)) return U_SUCCESS; // Search for the first non-empty byte - UINT32 i; + UINT32 nonEmptyByteOffset; UINT32 size = body.size(); const UINT8* current = (const UINT8*)body.constData(); - for (i = 0; i < size; i++) { - if (*current++ != pdata.emptyByte) + for (nonEmptyByteOffset = 0; nonEmptyByteOffset < size; nonEmptyByteOffset++) { + if (*current++ != emptyByte) break; } // Add all bytes before as free space... - if (i >= 8) { + if (nonEmptyByteOffset >= 8) { // Align free space to 8 bytes boundary - if (i != ALIGN8(i)) - i = ALIGN8(i) - 8; + if (nonEmptyByteOffset != ALIGN8(nonEmptyByteOffset)) + nonEmptyByteOffset = ALIGN8(nonEmptyByteOffset) - 8; - UByteArray free = body.left(i); + UByteArray free = body.left(nonEmptyByteOffset); // Get info UString info = usprintf("Full size: %Xh (%u)", free.size(), free.size()); - // Constuct parsing data - pdata.offset += model->header(index).size(); - // Add tree item - model->addItem(Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), free, UByteArray(), false, parsingDataToUByteArray(pdata), index); + model->addItem(model->offset(index) + model->header(index).size(), Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), free, UByteArray(), Movable, index); + } + else { + nonEmptyByteOffset = 0; } - else - i = 0; // ... and all bytes after as a padding - UByteArray padding = body.mid(i); + UByteArray padding = body.mid(nonEmptyByteOffset); // Get info UString info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size()); - // Constuct parsing data - pdata.offset += i; - // Add tree item - UModelIndex dataIndex = model->addItem(Types::Padding, Subtypes::DataPadding, UString("Non-UEFI data"), UString(), info, UByteArray(), padding, UByteArray(), true, parsingDataToUByteArray(pdata), index); + UModelIndex dataIndex = model->addItem(model->offset(index) + nonEmptyByteOffset, Types::Padding, Subtypes::DataPadding, UString("Non-UEFI data"), UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); // Show message msg(UString("parsePadFileBody: non-UEFI data found in pad-file"), dataIndex); @@ -1693,18 +1636,24 @@ USTATUS FfsParser::parseSections(const UByteArray & sections, const UModelIndex if (!index.isValid()) return U_INVALID_PARAMETER; - // Get data from parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(index); - // Search for and parse all sections UINT32 bodySize = sections.size(); UINT32 headerSize = model->header(index).size(); UINT32 sectionOffset = 0; - USTATUS result = U_SUCCESS; + + // Obtain required information from parent volume + UINT8 ffsVersion = 2; + UModelIndex parentVolumeIndex = model->findParentOfType(index, Types::Volume); + if (parentVolumeIndex.isValid() && model->hasEmptyParsingData(parentVolumeIndex) == false) { + UByteArray data = model->parsingData(parentVolumeIndex); + const VOLUME_PARSING_DATA* pdata = (const VOLUME_PARSING_DATA*)data.constData(); + ffsVersion = pdata->ffsVersion; + } + while (sectionOffset < bodySize) { // Get section size - UINT32 sectionSize = getSectionSize(sections, sectionOffset, pdata.ffsVersion); + UINT32 sectionSize = getSectionSize(sections, sectionOffset, ffsVersion); // Check section size if (sectionSize < sizeof(EFI_COMMON_SECTION_HEADER) || sectionSize > (bodySize - sectionOffset)) { @@ -1712,14 +1661,12 @@ USTATUS FfsParser::parseSections(const UByteArray & sections, const UModelIndex 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"), UString(), info, UByteArray(), padding, UByteArray(), true, parsingDataToUByteArray(pdata), index); + UModelIndex dataIndex = model->addItem(model->offset(index) + headerSize + sectionOffset, Types::Padding, Subtypes::DataPadding, UString("Non-UEFI data"), UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); // Show message msg(UString("parseSections: non-UEFI data found in sections area"), dataIndex); @@ -1728,8 +1675,9 @@ USTATUS FfsParser::parseSections(const UByteArray & sections, const UModelIndex break; } // Preparsing - else + else { return U_INVALID_SECTION; + } } // Parse section header @@ -1764,7 +1712,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 insertIntoTree) +USTATUS FfsParser::parseSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree) { // Check sanity if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER)) @@ -1773,40 +1721,46 @@ 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, 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 EFI_SECTION_COMPRESSION: return parseCompressedSectionHeader(section, localOffset, parent, index, insertIntoTree); + case EFI_SECTION_GUID_DEFINED: return parseGuidedSectionHeader(section, localOffset, parent, index, insertIntoTree); + case EFI_SECTION_FREEFORM_SUBTYPE_GUID: return parseFreeformGuidedSectionHeader(section, localOffset, parent, index, insertIntoTree); + case EFI_SECTION_VERSION: return parseVersionSectionHeader(section, localOffset, parent, index, insertIntoTree); case PHOENIX_SECTION_POSTCODE: - case INSYDE_SECTION_POSTCODE: return parsePostcodeSectionHeader(section, parentOffset, parent, index, insertIntoTree); + case INSYDE_SECTION_POSTCODE: return parsePostcodeSectionHeader(section, localOffset, parent, index, insertIntoTree); // Common case EFI_SECTION_DISPOSABLE: case EFI_SECTION_DXE_DEPEX: case EFI_SECTION_PEI_DEPEX: - case EFI_SECTION_SMM_DEPEX: + case EFI_SECTION_MM_DEPEX: case EFI_SECTION_PE32: case EFI_SECTION_PIC: case EFI_SECTION_TE: 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, insertIntoTree); + case EFI_SECTION_RAW: return parseCommonSectionHeader(section, localOffset, parent, index, insertIntoTree); // Unknown default: - USTATUS result = parseCommonSectionHeader(section, parentOffset, parent, index, insertIntoTree); + USTATUS result = parseCommonSectionHeader(section, localOffset, 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 insertIntoTree) +USTATUS FfsParser::parseCommonSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree) { // Check sanity if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER)) return U_INVALID_SECTION; - // Get data from parent's parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(parent); + // Obtain required information from parent volume + UINT8 ffsVersion = 2; + UModelIndex parentVolumeIndex = model->findParentOfType(index, Types::Volume); + if (parentVolumeIndex.isValid() && model->hasEmptyParsingData(parentVolumeIndex) == false) { + UByteArray data = model->parsingData(parentVolumeIndex); + const VOLUME_PARSING_DATA* pdata = (const VOLUME_PARSING_DATA*)data.constData(); + ffsVersion = pdata->ffsVersion; + } // Obtain header fields UINT32 headerSize; @@ -1819,7 +1773,7 @@ USTATUS FfsParser::parseCommonSectionHeader(const UByteArray & section, const UI 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) + if (ffsVersion == 3 && uint24ToUint32(sectionHeader->Size) == EFI_SECTION2_IS_USED) headerSize = sizeof(EFI_COMMON_SECTION_HEADER2); type = sectionHeader->Type; } @@ -1839,24 +1793,27 @@ USTATUS FfsParser::parseCommonSectionHeader(const UByteArray & section, const UI headerSize, headerSize, body.size(), body.size()); - // Construct parsing data - pdata.offset += parentOffset; - // Add tree item if (insertIntoTree) { - index = model->addItem(Types::Section, type, name, UString(), info, header, body, UByteArray(), false, parsingDataToUByteArray(pdata), parent); + index = model->addItem(model->offset(parent) + localOffset, Types::Section, type, name, UString(), info, header, body, UByteArray(), Movable, parent); } return U_SUCCESS; } -USTATUS FfsParser::parseCompressedSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree) +USTATUS FfsParser::parseCompressedSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree) { // Check sanity if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER)) return U_INVALID_SECTION; - // Get data from parent's parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(parent); + // Obtain required information from parent volume + UINT8 ffsVersion = 2; + UModelIndex parentVolumeIndex = model->findParentOfType(index, Types::Volume); + if (parentVolumeIndex.isValid() && model->hasEmptyParsingData(parentVolumeIndex) == false) { + UByteArray data = model->parsingData(parentVolumeIndex); + const VOLUME_PARSING_DATA* pdata = (const VOLUME_PARSING_DATA*)data.constData(); + ffsVersion = pdata->ffsVersion; + } // Obtain header fields UINT32 headerSize; @@ -1872,7 +1829,7 @@ USTATUS FfsParser::parseCompressedSectionHeader(const UByteArray & section, cons compressionType = (UINT8)appleSectionHeader->CompressionType; uncompressedLength = appleSectionHeader->UncompressedLength; } - else if (pdata.ffsVersion == 3 && uint24ToUint32(sectionHeader->Size) == EFI_SECTION2_IS_USED) { // Check for extended header section + else if (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 U_INVALID_SECTION; @@ -1904,26 +1861,33 @@ USTATUS FfsParser::parseCompressedSectionHeader(const UByteArray & section, cons compressionType, uncompressedLength, uncompressedLength); - // Construct parsing data - pdata.offset += parentOffset; - pdata.section.compressed.compressionType = compressionType; - pdata.section.compressed.uncompressedSize = uncompressedLength; - // Add tree item if (insertIntoTree) { - index = model->addItem(Types::Section, sectionHeader->Type, name, UString(), info, header, body, UByteArray(), false, parsingDataToUByteArray(pdata), parent); + index = model->addItem(model->offset(parent) + localOffset, Types::Section, sectionHeader->Type, name, UString(), info, header, body, UByteArray(), Movable, parent); + + // Set section parsing data + COMPRESSED_SECTION_PARSING_DATA pdata; + pdata.compressionType = compressionType; + pdata.uncompressedSize = uncompressedLength; + model->setParsingData(index, UByteArray((const char*)&pdata, sizeof(pdata))); } return U_SUCCESS; } -USTATUS FfsParser::parseGuidedSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree) +USTATUS FfsParser::parseGuidedSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree) { // Check sanity if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER)) return U_INVALID_SECTION; - // Get data from parent's parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(parent); + // Obtain required information from parent volume + UINT8 ffsVersion = 2; + UModelIndex parentVolumeIndex = model->findParentOfType(index, Types::Volume); + if (parentVolumeIndex.isValid() && model->hasEmptyParsingData(parentVolumeIndex) == false) { + UByteArray data = model->parsingData(parentVolumeIndex); + const VOLUME_PARSING_DATA* pdata = (const VOLUME_PARSING_DATA*)data.constData(); + ffsVersion = pdata->ffsVersion; + } // Obtain header fields UINT32 headerSize; @@ -1943,7 +1907,7 @@ USTATUS FfsParser::parseGuidedSectionHeader(const UByteArray & section, const UI dataOffset = appleSectionHeader->DataOffset; attributes = appleSectionHeader->Attributes; } - else if (pdata.ffsVersion == 3 && uint24ToUint32(sectionHeader->Size) == EFI_SECTION2_IS_USED) { // Check for extended header section + else if (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 U_INVALID_SECTION; @@ -2060,13 +2024,14 @@ USTATUS FfsParser::parseGuidedSectionHeader(const UByteArray & section, const UI // Append additional info info += additionalInfo; - // Construct parsing data - pdata.offset += parentOffset; - pdata.section.guidDefined.guid = guid; - // Add tree item if (insertIntoTree) { - index = model->addItem(Types::Section, sectionHeader->Type, name, UString(), info, header, body, UByteArray(), false, parsingDataToUByteArray(pdata), parent); + index = model->addItem(model->offset(parent) + localOffset, Types::Section, sectionHeader->Type, name, UString(), info, header, body, UByteArray(), Movable, parent); + + // Set parsing data + GUIDED_SECTION_PARSING_DATA pdata; + pdata.guid = guid; + model->setParsingData(index, UByteArray((const char*)&pdata, sizeof(pdata))); // Show messages if (msgSignedSectionFound) @@ -2088,14 +2053,20 @@ 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 insertIntoTree) +USTATUS FfsParser::parseFreeformGuidedSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree) { // Check sanity if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER)) return U_INVALID_SECTION; - // Get data from parent's parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(parent); + // Obtain required information from parent volume + UINT8 ffsVersion = 2; + UModelIndex parentVolumeIndex = model->findParentOfType(index, Types::Volume); + if (parentVolumeIndex.isValid() && model->hasEmptyParsingData(parentVolumeIndex) == false) { + UByteArray data = model->parsingData(parentVolumeIndex); + const VOLUME_PARSING_DATA* pdata = (const VOLUME_PARSING_DATA*)data.constData(); + ffsVersion = pdata->ffsVersion; + } // Obtain header fields UINT32 headerSize; @@ -2111,7 +2082,7 @@ USTATUS FfsParser::parseFreeformGuidedSectionHeader(const UByteArray & section, guid = appleSectionHeader->SubTypeGuid; type = appleHeader->Type; } - else if (pdata.ffsVersion == 3 && uint24ToUint32(sectionHeader->Size) == EFI_SECTION2_IS_USED) { // Check for extended header section + else if (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 U_INVALID_SECTION; @@ -2142,13 +2113,14 @@ USTATUS FfsParser::parseFreeformGuidedSectionHeader(const UByteArray & section, body.size(), body.size()) + guidToUString(guid); - // Construct parsing data - pdata.offset += parentOffset; - pdata.section.freeformSubtypeGuid.guid = guid; - // Add tree item if (insertIntoTree) { - index = model->addItem(Types::Section, type, name, UString(), info, header, body, UByteArray(), false, parsingDataToUByteArray(pdata), parent); + index = model->addItem(model->offset(parent) + localOffset, Types::Section, type, name, UString(), info, header, body, UByteArray(), Movable, parent); + + // Set parsing data + FREEFORM_GUIDED_SECTION_PARSING_DATA pdata; + pdata.guid = guid; + model->setParsingData(index, UByteArray((const char*)&pdata, sizeof(pdata))); // Rename section model->setName(index, guidToUString(guid)); @@ -2156,14 +2128,20 @@ 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 insertIntoTree) +USTATUS FfsParser::parseVersionSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree) { // Check sanity if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER)) return U_INVALID_SECTION; - // Get data from parent's parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(parent); + // Obtain required information from parent volume + UINT8 ffsVersion = 2; + UModelIndex parentVolumeIndex = model->findParentOfType(index, Types::Volume); + if (parentVolumeIndex.isValid() && model->hasEmptyParsingData(parentVolumeIndex) == false) { + UByteArray data = model->parsingData(parentVolumeIndex); + const VOLUME_PARSING_DATA* pdata = (const VOLUME_PARSING_DATA*)data.constData(); + ffsVersion = pdata->ffsVersion; + } // Obtain header fields UINT32 headerSize; @@ -2179,7 +2157,7 @@ USTATUS FfsParser::parseVersionSectionHeader(const UByteArray & section, const U buildNumber = versionHeader->BuildNumber; type = appleHeader->Type; } - else if (pdata.ffsVersion == 3 && uint24ToUint32(sectionHeader->Size) == EFI_SECTION2_IS_USED) { // Check for extended header section + else if (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; @@ -2208,24 +2186,27 @@ USTATUS FfsParser::parseVersionSectionHeader(const UByteArray & section, const U body.size(), body.size(), buildNumber); - // Construct parsing data - pdata.offset += parentOffset; - // Add tree item if (insertIntoTree) { - index = model->addItem(Types::Section, type, name, UString(), info, header, body, UByteArray(), false, parsingDataToUByteArray(pdata), parent); + index = model->addItem(model->offset(parent) + localOffset, Types::Section, type, name, UString(), info, header, body, UByteArray(), Movable, parent); } return U_SUCCESS; } -USTATUS FfsParser::parsePostcodeSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree) +USTATUS FfsParser::parsePostcodeSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree) { // Check sanity if ((UINT32)section.size() < sizeof(EFI_COMMON_SECTION_HEADER)) return U_INVALID_SECTION; - // Get data from parent's parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(parent); + // Obtain required information from parent volume + UINT8 ffsVersion = 2; + UModelIndex parentVolumeIndex = model->findParentOfType(index, Types::Volume); + if (parentVolumeIndex.isValid() && model->hasEmptyParsingData(parentVolumeIndex) == false) { + UByteArray data = model->parsingData(parentVolumeIndex); + const VOLUME_PARSING_DATA* pdata = (const VOLUME_PARSING_DATA*)data.constData(); + ffsVersion = pdata->ffsVersion; + } // Obtain header fields UINT32 headerSize; @@ -2241,7 +2222,7 @@ USTATUS FfsParser::parsePostcodeSectionHeader(const UByteArray & section, const postCode = postcodeHeader->Postcode; type = appleHeader->Type; } - else if (pdata.ffsVersion == 3 && uint24ToUint32(sectionHeader->Size) == EFI_SECTION2_IS_USED) { // Check for extended header section + else if (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; @@ -2270,12 +2251,9 @@ USTATUS FfsParser::parsePostcodeSectionHeader(const UByteArray & section, const body.size(), body.size(), postCode); - // Construct parsing data - pdata.offset += parentOffset; - // Add tree item if (insertIntoTree) { - index = model->addItem(Types::Section, sectionHeader->Type, name, UString(), info, header, body, UByteArray(), false, parsingDataToUByteArray(pdata), parent); + index = model->addItem(model->offset(parent) + localOffset, Types::Section, sectionHeader->Type, name, UString(), info, header, body, UByteArray(), Movable, parent); } return U_SUCCESS; } @@ -2301,7 +2279,7 @@ USTATUS FfsParser::parseSectionBody(const UModelIndex & index) case EFI_SECTION_VERSION: return parseVersionSectionBody(index); case EFI_SECTION_DXE_DEPEX: case EFI_SECTION_PEI_DEPEX: - case EFI_SECTION_SMM_DEPEX: return parseDepexSectionBody(index); + case EFI_SECTION_MM_DEPEX: return parseDepexSectionBody(index); case EFI_SECTION_TE: return parseTeImageSectionBody(index); case EFI_SECTION_PE32: case EFI_SECTION_PIC: return parsePeImageSectionBody(index); @@ -2323,26 +2301,32 @@ USTATUS FfsParser::parseCompressedSectionBody(const UModelIndex & index) if (!index.isValid()) return U_INVALID_PARAMETER; - // Get data from parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(index); - UINT8 algorithm = pdata.section.compressed.compressionType; + // Obtain required information from parsing data + UINT8 compressionType = EFI_NOT_COMPRESSED; + UINT32 uncompressedSize = model->body(index).size(); + if (model->hasEmptyParsingData(index) == false) { + UByteArray data = model->parsingData(index); + const COMPRESSED_SECTION_PARSING_DATA* pdata = (const COMPRESSED_SECTION_PARSING_DATA*)data.constData(); + compressionType = pdata->compressionType; + uncompressedSize = pdata->uncompressedSize; + } // Decompress section + UINT8 algorithm = COMPRESSION_ALGORITHM_NONE; UByteArray decompressed; UByteArray efiDecompressed; - USTATUS result = decompress(model->body(index), algorithm, decompressed, efiDecompressed); + USTATUS result = decompress(model->body(index), compressionType, algorithm, decompressed, efiDecompressed); if (result) { msg(UString("parseCompressedSectionBody: decompression failed with error ") + errorCodeToUString(result), index); return U_SUCCESS; } // Check reported uncompressed size - if (pdata.section.compressed.uncompressedSize != (UINT32)decompressed.size()) { + if (uncompressedSize != (UINT32)decompressed.size()) { msg(usprintf("parseCompressedSectionBody: decompressed size stored in header %Xh (%u) differs from actual %Xh (%u)", - pdata.section.compressed.uncompressedSize, - pdata.section.compressed.uncompressedSize, - decompressed.size(), - decompressed.size()), index); + uncompressedSize, uncompressedSize, + decompressed.size(), decompressed.size()), + index); model->addInfo(index, usprintf("\nActual decompressed size: %Xh (%u)", decompressed.size(), decompressed.size())); } @@ -2365,12 +2349,16 @@ USTATUS FfsParser::parseCompressedSectionBody(const UModelIndex & index) // Add info model->addInfo(index, UString("\nCompression algorithm: ") + compressionTypeToUString(algorithm)); - // Update data - pdata.section.compressed.algorithm = algorithm; + // Update parsing data + COMPRESSED_SECTION_PARSING_DATA pdata; + pdata.algorithm = algorithm; + pdata.compressionType = compressionType; + pdata.uncompressedSize = uncompressedSize; + model->setParsingData(index, UByteArray((const char*)&pdata, sizeof(pdata))); + if (algorithm != COMPRESSION_ALGORITHM_NONE) model->setCompressed(index, true); - model->setParsingData(index, parsingDataToUByteArray(pdata)); - + // Parse decompressed data return parseSections(decompressed, index, true); } @@ -2381,9 +2369,13 @@ USTATUS FfsParser::parseGuidedSectionBody(const UModelIndex & index) if (!index.isValid()) return U_INVALID_PARAMETER; - // Get data from parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(index); - EFI_GUID guid = pdata.section.guidDefined.guid; + // Obtain required information from parsing data + EFI_GUID guid = { 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0 }}; + if (model->hasEmptyParsingData(index) == false) { + UByteArray data = model->parsingData(index); + const GUIDED_SECTION_PARSING_DATA* pdata = (const GUIDED_SECTION_PARSING_DATA*)data.constData(); + guid = pdata->guid; + } // Check if section requires processing UByteArray processed = model->body(index); @@ -2394,8 +2386,7 @@ USTATUS FfsParser::parseGuidedSectionBody(const UModelIndex & index) UByteArray baGuid = UByteArray((const char*)&guid, sizeof(EFI_GUID)); // Tiano compressed section if (baGuid == EFI_GUIDED_SECTION_TIANO) { - algorithm = EFI_STANDARD_COMPRESSION; - USTATUS result = decompress(model->body(index), algorithm, processed, efiDecompressed); + USTATUS result = decompress(model->body(index), EFI_STANDARD_COMPRESSION, algorithm, processed, efiDecompressed); if (result) { parseCurrentSection = false; msg(UString("parseGuidedSectionBody: decompression failed with error ") + errorCodeToUString(result), index); @@ -2424,8 +2415,7 @@ USTATUS FfsParser::parseGuidedSectionBody(const UModelIndex & index) } // LZMA compressed section else if (baGuid == EFI_GUIDED_SECTION_LZMA || baGuid == EFI_GUIDED_SECTION_LZMAF86) { - algorithm = EFI_CUSTOMIZED_COMPRESSION; - USTATUS result = decompress(model->body(index), algorithm, processed, efiDecompressed); + USTATUS result = decompress(model->body(index), EFI_CUSTOMIZED_COMPRESSION, algorithm, processed, efiDecompressed); if (result) { parseCurrentSection = false; msg(UString("parseGuidedSectionBody: decompression failed with error ") + errorCodeToUString(result), index); @@ -2448,7 +2438,6 @@ USTATUS FfsParser::parseGuidedSectionBody(const UModelIndex & index) // Update data if (algorithm != COMPRESSION_ALGORITHM_NONE) model->setCompressed(index, true); - model->setParsingData(index, parsingDataToUByteArray(pdata)); if (!parseCurrentSection) { msg(UString("parseGuidedSectionBody: GUID defined section can not be processed"), index); @@ -2637,11 +2626,11 @@ USTATUS FfsParser::parseRawSectionBody(const UModelIndex & index) // Check for apriori file UModelIndex parentFile = model->findParentOfType(index, Types::File); + if (!parentFile.isValid()) + return U_INVALID_FILE; //TODO: better return code // Get parent file parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(parentFile); - UByteArray parentFileGuid((const char*)&pdata.file.guid, sizeof(EFI_GUID)); - + UByteArray parentFileGuid(model->header(parentFile).constData(), sizeof(EFI_GUID)); if (parentFileGuid == EFI_PEI_APRIORI_FILE_GUID) { // PEI apriori file // Parse apriori file list UString str; @@ -2799,14 +2788,13 @@ USTATUS FfsParser::parseTeImageSectionBody(const UModelIndex & index) teHeader->ImageBase, teHeader->ImageBase + teHeader->StrippedSize - sizeof(EFI_IMAGE_TE_HEADER)); } - - // Get data from parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(index); - pdata.section.teImage.imageBase = (UINT32)teHeader->ImageBase; - pdata.section.teImage.adjustedImageBase = (UINT32)(teHeader->ImageBase + teHeader->StrippedSize - sizeof(EFI_IMAGE_TE_HEADER)); // Update parsing data - model->setParsingData(index, parsingDataToUByteArray(pdata)); + TE_IMAGE_SECTION_PARSING_DATA pdata; + pdata.imageBaseType = EFI_IMAGE_TE_BASE_OTHER; // Will be determined later + pdata.imageBase = (UINT32)teHeader->ImageBase; + pdata.adjustedImageBase = (UINT32)(teHeader->ImageBase + teHeader->StrippedSize - sizeof(EFI_IMAGE_TE_HEADER)); + model->setParsingData(index, UByteArray((const char*)&pdata, sizeof(pdata))); // Add TE info model->addInfo(index, info); @@ -2827,12 +2815,9 @@ USTATUS FfsParser::performSecondPass(const UModelIndex & index) return U_SUCCESS; } - // Get parsing data for the last VTF - PARSING_DATA pdata = parsingDataFromUModelIndex(lastVtf); - // Calculate address difference const UINT32 vtfSize = model->header(lastVtf).size() + model->body(lastVtf).size() + model->tail(lastVtf).size(); - const UINT32 diff = 0xFFFFFFFFUL - pdata.offset - vtfSize + 1; + const UINT32 diff = 0xFFFFFFFFUL - model->offset(lastVtf) - vtfSize + 1; // Find and parse FIT parseFit(index, diff); @@ -2970,9 +2955,6 @@ USTATUS FfsParser::findFitRecursive(const UModelIndex & index, const UINT32 diff return U_SUCCESS; } - // Get parsing data for the current item - PARSING_DATA pdata = parsingDataFromUModelIndex(index); - // Check for all FIT signatures in item's body UByteArray lastVtfBody = model->body(lastVtf); UINT32 storedFitAddress = *(const UINT32*)(lastVtfBody.constData() + lastVtfBody.size() - FIT_POINTER_OFFSET); @@ -2980,7 +2962,7 @@ USTATUS FfsParser::findFitRecursive(const UModelIndex & index, const UINT32 diff offset >= 0; offset = model->body(index).indexOf(FIT_SIGNATURE, offset + 1)) { // FIT candidate found, calculate it's physical address - UINT32 fitAddress = pdata.offset + diff + model->header(index).size() + (UINT32)offset; + UINT32 fitAddress = model->offset(index) + diff + model->header(index).size() + (UINT32)offset; // Check FIT address to be stored in the last VTF if (fitAddress == storedFitAddress) { @@ -3004,55 +2986,68 @@ USTATUS FfsParser::addMemoryAddressesRecursive(const UModelIndex & index, const // Set address value for non-compressed data if (!model->compressed(index)) { - // Get parsing data for the current item - PARSING_DATA pdata = parsingDataFromUModelIndex(index); - // Check address sanity - if ((const UINT64)diff + pdata.offset <= 0xFFFFFFFFUL) { + UINT64 address = (const UINT64)diff + model->offset(index); + if (address <= 0xFFFFFFFFUL) { // Update info - pdata.address = diff + pdata.offset; UINT32 headerSize = model->header(index).size(); if (headerSize) { - model->addInfo(index, usprintf("\nHeader memory address: %08Xh", pdata.address)); - model->addInfo(index, usprintf("\nData memory address: %08Xh", pdata.address + headerSize)); + model->addInfo(index, usprintf("\nHeader memory address: %08Xh", address)); + model->addInfo(index, usprintf("\nData memory address: %08Xh", address + headerSize)); } else { - model->addInfo(index, usprintf("\nMemory address: %08Xh", pdata.address)); + model->addInfo(index, usprintf("\nMemory address: %08Xh", address)); } - // Special case of uncompressed TE image sections + // Determine relocation type 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 - 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; + // Obtain required values from parsing data + UINT32 imageBase = 0; + UINT32 adjustedImageBase = 0; + UINT8 imageBaseType = EFI_IMAGE_TE_BASE_OTHER; + if (model->hasEmptyParsingData(index) == false) { + UByteArray data = model->parsingData(index); + const TE_IMAGE_SECTION_PARSING_DATA* pdata = (const TE_IMAGE_SECTION_PARSING_DATA*)data.constData(); + imageBase = pdata->imageBase; + adjustedImageBase = pdata->adjustedImageBase; } - else if (pdata.section.teImage.adjustedImageBase == base) { - pdata.section.teImage.imageBaseType = EFI_IMAGE_TE_BASE_ADJUSTED; - } - 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; + + if (imageBase != 0) { + // Check data memory address to be equal to either ImageBase or AdjustedImageBase + UINT32 base = (UINT32)address + headerSize; + + if (imageBase == base) { + 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; + else if (adjustedImageBase == base) { + imageBaseType = EFI_IMAGE_TE_BASE_ADJUSTED; + } + else { + // Check for one-bit difference + UINT32 xored = base ^ 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 + imageBaseType = EFI_IMAGE_TE_BASE_ORIGINAL; + } + else { // The same check for adjustedImageBase + xored = base ^ adjustedImageBase; + if ((xored & (xored - 1)) == 0) { + imageBaseType = EFI_IMAGE_TE_BASE_ADJUSTED; + } } } + + // Show message if imageBaseType is still unknown + if (imageBaseType == EFI_IMAGE_TE_BASE_OTHER) + msg(UString("addMemoryAddressesRecursive: TE image base is neither zero, nor original, nor adjusted, nor top-swapped"), index); + + // Update parsing data + TE_IMAGE_SECTION_PARSING_DATA pdata; + pdata.imageBaseType = imageBaseType; + pdata.imageBase = imageBase; + pdata.adjustedImageBase = adjustedImageBase; + model->setParsingData(index, UByteArray((const char*)&pdata, sizeof(pdata))); } - - // 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 - model->setParsingData(index, parsingDataToUByteArray(pdata)); } } @@ -3070,13 +3065,10 @@ USTATUS FfsParser::addOffsetsRecursive(const UModelIndex & index) if (!index.isValid()) return U_INVALID_PARAMETER; - // Get parsing data for the current item - PARSING_DATA pdata = parsingDataFromUModelIndex(index); - // Add current offset if the element is not compressed // or it's compressed, but it's parent isn't if ((!model->compressed(index)) || (index.parent().isValid() && !model->compressed(index.parent()))) { - model->addInfo(index, usprintf("Offset: %Xh\n", pdata.offset), false); + model->addInfo(index, usprintf("Offset: %Xh\n", model->offset(index)), false); } // Process child items diff --git a/common/ffsparser.h b/common/ffsparser.h index 7ac6543..ecd4d95 100644 --- a/common/ffsparser.h +++ b/common/ffsparser.h @@ -62,30 +62,30 @@ private: USTATUS performFirstPass(const UByteArray & imageFile, UModelIndex & index); USTATUS parseRawArea(const UModelIndex & index); - USTATUS parseVolumeHeader(const UByteArray & volume, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index); + USTATUS parseVolumeHeader(const UByteArray & volume, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index); USTATUS parseVolumeBody(const UModelIndex & index); - USTATUS parseFileHeader(const UByteArray & file, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index); + USTATUS parseFileHeader(const UByteArray & file, const UINT32 localOffset, 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 insertIntoTree); + USTATUS parseSectionHeader(const UByteArray & section, const UINT32 localOffset, 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); - USTATUS parseGbeRegion(const UByteArray & gbe, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index); - USTATUS parseMeRegion(const UByteArray & me, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index); - USTATUS parseBiosRegion(const UByteArray & bios, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index); - USTATUS parsePdrRegion(const UByteArray & pdr, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index); - USTATUS parseGeneralRegion(const UINT8 subtype, const UByteArray & region, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index); + USTATUS parseIntelImage(const UByteArray & intelImage, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & root); + USTATUS parseGbeRegion(const UByteArray & gbe, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index); + USTATUS parseMeRegion(const UByteArray & me, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index); + USTATUS parseBiosRegion(const UByteArray & bios, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index); + USTATUS parsePdrRegion(const UByteArray & pdr, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index); + USTATUS parseGeneralRegion(const UINT8 subtype, const UByteArray & region, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index); USTATUS parsePadFileBody(const UModelIndex & index); - USTATUS parseVolumeNonUefiData(const UByteArray & data, const UINT32 parentOffset, const UModelIndex & index); + USTATUS parseVolumeNonUefiData(const UByteArray & data, const UINT32 localOffset, const UModelIndex & index); 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 parseCommonSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree); + USTATUS parseCompressedSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree); + USTATUS parseGuidedSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree); + USTATUS parseFreeformGuidedSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree); + USTATUS parseVersionSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree); + USTATUS parsePostcodeSectionHeader(const UByteArray & section, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index, const bool insertIntoTree); USTATUS parseCompressedSectionBody(const UModelIndex & index); USTATUS parseGuidedSectionBody(const UModelIndex & index); @@ -97,7 +97,7 @@ private: USTATUS parseTeImageSectionBody(const UModelIndex & index); USTATUS parseAprioriRawSection(const UByteArray & body, UString & parsed); - USTATUS findNextVolume(const UModelIndex & index, const UByteArray & bios, const UINT32 parentOffset, const UINT32 volumeOffset, UINT32 & nextVolumeOffset); + USTATUS findNextVolume(const UModelIndex & index, const UByteArray & bios, const UINT32 localOffset, 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); diff --git a/common/nvramparser.cpp b/common/nvramparser.cpp index 70557e7..201673f 100644 --- a/common/nvramparser.cpp +++ b/common/nvramparser.cpp @@ -28,20 +28,27 @@ USTATUS NvramParser::parseNvarStore(const UModelIndex & index) if (!index.isValid()) return U_INVALID_PARAMETER; - // Get parsing data for the current item - PARSING_DATA pdata = parsingDataFromUModelIndex(index); - UINT32 parentOffset = pdata.offset + model->header(index).size(); + // Obtain required information from parent file + UINT8 emptyByte = 0xFF; + UModelIndex parentFileIndex = model->findParentOfType(index, Types::File); + if (parentFileIndex.isValid() && model->hasEmptyParsingData(parentFileIndex) == false) { + UByteArray data = model->parsingData(index); + const FILE_PARSING_DATA* pdata = (const FILE_PARSING_DATA*)data.constData(); + emptyByte = pdata->emptyByte; + } + + // Rename parent file + model->setText(parentFileIndex, UString("NVAR store")); + + // Get local offset + UINT32 localOffset = model->offset(index) + model->header(index).size(); // Get item data const UByteArray data = model->body(index); - // Rename parent file - model->setText(model->findParentOfType(index, Types::File), UString("NVAR store")); - + // Parse all entries UINT32 offset = 0; UINT32 guidsInStore = 0; - const UINT8 emptyByte = pdata.emptyByte; - // Parse all entries while (1) { bool msgUnknownExtDataFormat = false; bool msgExtHeaderTooLong = false; @@ -81,16 +88,15 @@ USTATUS NvramParser::parseNvarStore(const UModelIndex & index) if (unparsedSize < sizeof(NVAR_ENTRY_HEADER) || entryHeader->Signature != NVRAM_NVAR_ENTRY_SIGNATURE || unparsedSize < entryHeader->Size) { - // Check if the data left is a free space or a padding UByteArray padding = data.mid(offset, unparsedSize); - UINT8 type; - - if ((UINT32)padding.count(emptyByte) == unparsedSize) { - // It's a free space - name = ("Free space"); - type = Types::FreeSpace; - subtype = 0; + + // Get info + UString info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size()); + + if ((UINT32)padding.count(emptyByte) == unparsedSize) { // Free space + // Add tree item + model->addItem(localOffset + offset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), padding, UByteArray(), Movable, index); } else { // Nothing is parsed yet, but the file is not empty @@ -99,18 +105,10 @@ USTATUS NvramParser::parseNvarStore(const UModelIndex & index) return U_SUCCESS; } - // It's a padding - name = UString("Padding"); - type = Types::Padding; - subtype = getPaddingType(padding); + // Add tree item + model->addItem(localOffset + offset, Types::Padding, getPaddingType(padding), UString("Padding"), UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); } - // Get info - UString info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size()); - // Construct parsing data - pdata.offset = parentOffset + offset; - // Add tree item - model->addItem(type, subtype, name, UString(), info, UByteArray(), padding, UByteArray(), false, parsingDataToUByteArray(pdata), index); - + // Add GUID store area UByteArray guidArea = data.right(guidAreaSize); // Get info @@ -118,10 +116,8 @@ USTATUS NvramParser::parseNvarStore(const UModelIndex & index) info = usprintf("Full size: %Xh (%u)\nGUIDs in store: %u", guidArea.size(), guidArea.size(), guidsInStore); - // Construct parsing data - pdata.offset = parentOffset + offset + padding.size(); // Add tree item - model->addItem(Types::Padding, getPaddingType(guidArea), name, UString(), info, UByteArray(), guidArea, UByteArray(), false, parsingDataToUByteArray(pdata), index); + model->addItem(localOffset + offset + padding.size(), Types::Padding, getPaddingType(guidArea), name, UString(), info, UByteArray(), guidArea, UByteArray(), Fixed, index); return U_SUCCESS; } @@ -130,10 +126,12 @@ USTATUS NvramParser::parseNvarStore(const UModelIndex & index) header = data.mid(offset, sizeof(NVAR_ENTRY_HEADER)); body = data.mid(offset + sizeof(NVAR_ENTRY_HEADER), entryHeader->Size - sizeof(NVAR_ENTRY_HEADER)); - UINT32 lastVariableFlag = pdata.emptyByte ? 0xFFFFFF : 0; + UINT32 lastVariableFlag = emptyByte ? 0xFFFFFF : 0; // Set default next to predefined last value - pdata.nvar.next = lastVariableFlag; + NVAR_ENTRY_PARSING_DATA pdata; + pdata.emptyByte = emptyByte; + pdata.next = lastVariableFlag; // Entry is marked as invalid if ((entryHeader->Attributes & NVRAM_NVAR_ENTRY_VALID) == 0) { // Valid attribute is not set @@ -145,7 +143,7 @@ USTATUS NvramParser::parseNvarStore(const UModelIndex & index) // Add next node information to parsing data if (entryHeader->Next != lastVariableFlag) { subtype = Subtypes::LinkNvarEntry; - pdata.nvar.next = entryHeader->Next; + pdata.next = entryHeader->Next; } // Entry with extended header @@ -228,10 +226,13 @@ USTATUS NvramParser::parseNvarStore(const UModelIndex & index) // Search prevously added entries for a link to this variable for (int i = 0; i < model->rowCount(index); i++) { nvarIndex = index.child(i, 0); - PARSING_DATA nvarPdata = parsingDataFromUModelIndex(nvarIndex); - if (nvarPdata.nvar.isValid && nvarPdata.nvar.next + nvarPdata.offset - parentOffset == offset) { // Previous link is present and valid - isInvalidLink = false; - break; + if (model->hasEmptyParsingData(nvarIndex) == false) { + UByteArray nvarData = model->parsingData(nvarIndex); + const NVAR_ENTRY_PARSING_DATA* nvarPdata = (const NVAR_ENTRY_PARSING_DATA*)nvarData.constData(); + if (nvarPdata->isValid && nvarPdata->next + model->offset(nvarIndex) - localOffset == offset) { // Previous link is present and valid + isInvalidLink = false; + break; + } } } // Check if the link is valid @@ -287,16 +288,16 @@ parsing_done: UString info; // Rename invalid entries according to their types - pdata.nvar.isValid = TRUE; + pdata.isValid = TRUE; if (isInvalid) { name = UString("Invalid"); subtype = Subtypes::InvalidNvarEntry; - pdata.nvar.isValid = FALSE; + pdata.isValid = FALSE; } else if (isInvalidLink) { name = UString("Invalid link"); subtype = Subtypes::InvalidLinkNvarEntry; - pdata.nvar.isValid = FALSE; + pdata.isValid = FALSE; } else // Add GUID info for valid entries info += UString("Variable GUID: ") + name + UString("\n"); @@ -319,7 +320,7 @@ parsing_done: // Add next node info if (!isInvalid && entryHeader->Next != lastVariableFlag) - info += usprintf("\nNext node at offset: %Xh", parentOffset + offset + entryHeader->Next); + info += usprintf("\nNext node at offset: %Xh", localOffset + offset + entryHeader->Next); // Add extended header info if (hasExtendedHeader) { @@ -341,11 +342,11 @@ parsing_done: info += UString("\nHash: ") + UString(hash.toHex().constData()); } - // Add correct offset to parsing data - pdata.offset = parentOffset + offset; - // Add tree item - UModelIndex varIndex = model->addItem(Types::NvarEntry, subtype, name, text, info, header, body, tail, false, parsingDataToUByteArray(pdata), index); + UModelIndex varIndex = model->addItem(localOffset + offset, Types::NvarEntry, subtype, name, text, info, header, body, tail, Movable, index); + + // Set parsing data for created entry + model->setParsingData(varIndex, UByteArray((const char*)&pdata, sizeof(pdata))); // Show messages if (msgUnknownExtDataFormat) msg(UString("parseNvarStore: unknown extended data format"), varIndex); @@ -372,9 +373,16 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index) if (!index.isValid()) return U_INVALID_PARAMETER; - // Get parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(index); - UINT32 parentOffset = pdata.offset + model->header(index).size(); + // Obtain required fields from parsing data + UINT8 emptyByte = 0xFF; + if (model->hasEmptyParsingData(index) == false) { + UByteArray data = model->parsingData(index); + const VOLUME_PARSING_DATA* pdata = (const VOLUME_PARSING_DATA*)data.constData(); + emptyByte = pdata->emptyByte; + } + + // Get local offset + UINT32 localOffset = model->offset(index) + model->header(index).size(); // Get item data UByteArray data = model->body(index); @@ -382,7 +390,7 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index) // Search for first store USTATUS result; UINT32 prevStoreOffset; - result = findNextStore(index, data, parentOffset, 0, prevStoreOffset); + result = findNextStore(index, data, localOffset, 0, prevStoreOffset); if (result) return result; @@ -395,11 +403,8 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index) name = UString("Padding"); info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size()); - // Construct parsing data - pdata.offset = parentOffset; - // Add tree item - model->addItem(Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), true, parsingDataToUByteArray(pdata), index); + model->addItem(localOffset, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); } // Search for and parse all stores @@ -418,11 +423,8 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index) name = UString("Padding"); info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size()); - // Construct parsing data - pdata.offset = parentOffset + paddingOffset; - // Add tree item - model->addItem(Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), true, parsingDataToUByteArray(pdata), index); + model->addItem(localOffset + paddingOffset, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); } // Get store size @@ -442,11 +444,8 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index) name = UString("Padding"); info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size()); - // Construct parsing data - pdata.offset = parentOffset + storeOffset; - // Add tree item - UModelIndex paddingIndex = model->addItem(Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), true, parsingDataToUByteArray(pdata), index); + UModelIndex paddingIndex = model->addItem(localOffset + storeOffset, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); msg(UString("parseNvramVolumeBody: one of stores inside overlaps the end of data"), paddingIndex); // Update variables @@ -455,30 +454,30 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index) break; } - UByteArray store = data.mid(storeOffset, storeSize); // Parse current store header UModelIndex storeIndex; - result = parseStoreHeader(store, parentOffset + storeOffset, index, storeIndex); + UByteArray store = data.mid(storeOffset, storeSize); + result = parseStoreHeader(store, localOffset + storeOffset, index, storeIndex); if (result) msg(UString("parseNvramVolumeBody: store header parsing failed with error ") + errorCodeToUString(result), index); // Go to next store prevStoreOffset = storeOffset; prevStoreSize = storeSize; - result = findNextStore(index, data, parentOffset, storeOffset + prevStoreSize, storeOffset); + result = findNextStore(index, data, localOffset, storeOffset + prevStoreSize, storeOffset); } // Padding/free space at the end storeOffset = prevStoreOffset + prevStoreSize; if ((UINT32)data.size() > storeOffset) { UByteArray padding = data.mid(storeOffset); - UINT8 type; - UINT8 subtype; - if (padding.count(pdata.emptyByte) == padding.size()) { - // It's a free space - name = UString("Free space"); - type = Types::FreeSpace; - subtype = 0; + // Add info + info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size()); + + if (padding.count(emptyByte) == padding.size()) { // Free space + + // Add tree item + model->addItem(localOffset + storeOffset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), padding, UByteArray(), Movable, index); } else { // Nothing is parsed yet, but the file is not empty @@ -487,20 +486,9 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index) return U_SUCCESS; } - // It's a padding - name = UString("Padding"); - type = Types::Padding; - subtype = getPaddingType(padding); + // Add tree item + model->addItem(localOffset + storeOffset, Types::Padding, getPaddingType(padding), UString("Padding"), UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); } - - // Add info - info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size()); - - // Construct parsing data - pdata.offset = parentOffset + storeOffset; - - // Add tree item - model->addItem(type, subtype, name, UString(), info, UByteArray(), padding, UByteArray(), true, parsingDataToUByteArray(pdata), index); } // Parse bodies @@ -518,7 +506,7 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index) return U_SUCCESS; } -USTATUS NvramParser::findNextStore(const UModelIndex & index, const UByteArray & volume, const UINT32 parentOffset, const UINT32 storeOffset, UINT32 & nextStoreOffset) +USTATUS NvramParser::findNextStore(const UModelIndex & index, const UByteArray & volume, const UINT32 localOffset, const UINT32 storeOffset, UINT32 & nextStoreOffset) { UINT32 dataSize = volume.size(); @@ -531,11 +519,11 @@ USTATUS NvramParser::findNextStore(const UModelIndex & index, const UByteArray & if (*currentPos == NVRAM_VSS_STORE_SIGNATURE || *currentPos == NVRAM_APPLE_SVS_STORE_SIGNATURE) { //$VSS or $SVS signatures found, perform checks const VSS_VARIABLE_STORE_HEADER* vssHeader = (const VSS_VARIABLE_STORE_HEADER*)currentPos; if (vssHeader->Format != NVRAM_VSS_VARIABLE_STORE_FORMATTED) { - msg(usprintf("findNextStore: VSS store candidate at offset %Xh skipped, has invalid format %02Xh", parentOffset + offset, vssHeader->Format), index); + msg(usprintf("findNextStore: VSS store candidate at offset %Xh skipped, has invalid format %02Xh", localOffset + offset, vssHeader->Format), index); continue; } if (vssHeader->Size == 0 || vssHeader->Size == 0xFFFFFFFF) { - msg(usprintf("findNextStore: VSS store candidate at offset %Xh skipped, has invalid size %Xh", parentOffset + offset, vssHeader->Size), index); + msg(usprintf("findNextStore: VSS store candidate at offset %Xh skipped, has invalid size %Xh", localOffset + offset, vssHeader->Size), index); continue; } // All checks passed, store found @@ -544,7 +532,7 @@ USTATUS NvramParser::findNextStore(const UModelIndex & index, const UByteArray & else if (*currentPos == NVRAM_FDC_VOLUME_SIGNATURE) { //FDC signature found const FDC_VOLUME_HEADER* fdcHeader = (const FDC_VOLUME_HEADER*)currentPos; if (fdcHeader->Size == 0 || fdcHeader->Size == 0xFFFFFFFF) { - msg(usprintf("findNextStore: FDC store candidate at offset %Xh skipped, has invalid size %Xh", parentOffset + offset, fdcHeader->Size), index); + msg(usprintf("findNextStore: FDC store candidate at offset %Xh skipped, has invalid size %Xh", localOffset + offset, fdcHeader->Size), index); continue; } // All checks passed, store found @@ -553,7 +541,7 @@ USTATUS NvramParser::findNextStore(const UModelIndex & index, const UByteArray & else if (*currentPos == NVRAM_APPLE_FSYS_STORE_SIGNATURE || *currentPos == NVRAM_APPLE_GAID_STORE_SIGNATURE) { //Fsys or Gaid signature found const APPLE_FSYS_STORE_HEADER* fsysHeader = (const APPLE_FSYS_STORE_HEADER*)currentPos; if (fsysHeader->Size == 0 || fsysHeader->Size == 0xFFFF) { - msg(usprintf("findNextStore: Fsys store candidate at offset %Xh skipped, has invalid size %Xh", parentOffset + offset, fsysHeader->Size), index); + msg(usprintf("findNextStore: Fsys store candidate at offset %Xh skipped, has invalid size %Xh", localOffset + offset, fsysHeader->Size), index); continue; } // All checks passed, store found @@ -565,11 +553,11 @@ USTATUS NvramParser::findNextStore(const UModelIndex & index, const UByteArray & const EVSA_STORE_ENTRY* evsaHeader = (const EVSA_STORE_ENTRY*)(currentPos - 1); if (evsaHeader->Header.Type != NVRAM_EVSA_ENTRY_TYPE_STORE) { - msg(usprintf("findNextStore: EVSA store candidate at offset %Xh skipped, has invalid type %02Xh", parentOffset + offset - 4, evsaHeader->Header.Type), index); + msg(usprintf("findNextStore: EVSA store candidate at offset %Xh skipped, has invalid type %02Xh", localOffset + offset - 4, evsaHeader->Header.Type), index); continue; } if (evsaHeader->StoreSize == 0 || evsaHeader->StoreSize == 0xFFFFFFFF) { - msg(usprintf("findNextStore: EVSA store candidate at offset %Xh skipped, has invalid size %Xh", parentOffset + offset, evsaHeader->StoreSize), index); + msg(usprintf("findNextStore: EVSA store candidate at offset %Xh skipped, has invalid size %Xh", localOffset + offset, evsaHeader->StoreSize), index); continue; } // All checks passed, store found @@ -585,14 +573,14 @@ USTATUS NvramParser::findNextStore(const UModelIndex & index, const UByteArray & const EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32* ftwHeader = (const EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32*)currentPos; if (ftwHeader->WriteQueueSize % 0x10 == 0x04) { // Header with 32 bit WriteQueueSize if (ftwHeader->WriteQueueSize == 0 || ftwHeader->WriteQueueSize == 0xFFFFFFFF) { - msg(usprintf("findNextStore: FTW block candidate at offset %Xh skipped, has invalid body size %Xh", parentOffset + offset, ftwHeader->WriteQueueSize), index); + msg(usprintf("findNextStore: FTW block candidate at offset %Xh skipped, has invalid body size %Xh", localOffset + offset, ftwHeader->WriteQueueSize), index); continue; } } else if (ftwHeader->WriteQueueSize % 0x10 == 0x00) { // Header with 64 bit WriteQueueSize const EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64* ftw64Header = (const EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64*)currentPos; if (ftw64Header->WriteQueueSize == 0 || ftw64Header->WriteQueueSize >= 0xFFFFFFFF) { - msg(usprintf("findNextStore: FTW block candidate at offset %Xh skipped, has invalid body size %Xh", parentOffset + offset, ftw64Header->WriteQueueSize), index); + msg(usprintf("findNextStore: FTW block candidate at offset %Xh skipped, has invalid body size %Xh", localOffset + offset, ftw64Header->WriteQueueSize), index); continue; } } @@ -733,7 +721,7 @@ USTATUS NvramParser::getStoreSize(const UByteArray & data, const UINT32 storeOff return U_SUCCESS; } -USTATUS NvramParser::parseVssStoreHeader(const UByteArray & store, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index) +USTATUS NvramParser::parseVssStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index) { const UINT32 dataSize = (const UINT32)store.size(); @@ -754,9 +742,6 @@ USTATUS NvramParser::parseVssStoreHeader(const UByteArray & store, const UINT32 return U_SUCCESS; } - // Get parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(parent); - // Construct header and body UByteArray header = store.left(sizeof(VSS_VARIABLE_STORE_HEADER)); UByteArray body = store.mid(sizeof(VSS_VARIABLE_STORE_HEADER), vssStoreHeader->Size - sizeof(VSS_VARIABLE_STORE_HEADER)); @@ -773,16 +758,13 @@ USTATUS NvramParser::parseVssStoreHeader(const UByteArray & store, const UINT32 vssStoreHeader->State, vssStoreHeader->Unknown); - // Add correct offset - pdata.offset = parentOffset; - // Add tree item - index = model->addItem(Types::VssStore, 0, name, UString(), info, header, body, UByteArray(), true, parsingDataToUByteArray(pdata), parent); + index = model->addItem(localOffset, Types::VssStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, parent); return U_SUCCESS; } -USTATUS NvramParser::parseFtwStoreHeader(const UByteArray & store, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index) +USTATUS NvramParser::parseFtwStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index) { const UINT32 dataSize = (const UINT32)store.size(); @@ -792,6 +774,15 @@ USTATUS NvramParser::parseFtwStoreHeader(const UByteArray & store, const UINT32 return U_SUCCESS; } + // Obtain required information from parent volume + UINT8 emptyByte = 0xFF; + UModelIndex parentVolumeIndex = model->findParentOfType(index, Types::Volume); + if (parentVolumeIndex.isValid() && model->hasEmptyParsingData(parentVolumeIndex) == false) { + UByteArray data = model->parsingData(parentVolumeIndex); + const VOLUME_PARSING_DATA* pdata = (const VOLUME_PARSING_DATA*)data.constData(); + emptyByte = pdata->ffsVersion; + } + // Get FTW block headers const EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32* ftw32BlockHeader = (const EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32*)store.constData(); const EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64* ftw64BlockHeader = (const EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64*)store.constData(); @@ -814,9 +805,6 @@ USTATUS NvramParser::parseFtwStoreHeader(const UByteArray & store, const UINT32 return U_SUCCESS; } - // Get parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(parent); - // Construct header and body UINT32 headerSize = has32bitHeader ? sizeof(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32) : sizeof(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64); UByteArray header = store.left(headerSize); @@ -825,8 +813,8 @@ USTATUS NvramParser::parseFtwStoreHeader(const UByteArray & store, const UINT32 // Check block header checksum UByteArray crcHeader = header; EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32* crcFtwBlockHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32*)header.data(); - crcFtwBlockHeader->Crc = pdata.emptyByte ? 0xFFFFFFFF : 0; - crcFtwBlockHeader->State = pdata.emptyByte ? 0xFF : 0; + crcFtwBlockHeader->Crc = emptyByte ? 0xFFFFFFFF : 0; + crcFtwBlockHeader->State = emptyByte ? 0xFF : 0; UINT32 calculatedCrc = crc32(0, (const UINT8*)crcFtwBlockHeader, headerSize); // Add info @@ -840,16 +828,13 @@ USTATUS NvramParser::parseFtwStoreHeader(const UByteArray & store, const UINT32 ftw32BlockHeader->Crc) + (ftw32BlockHeader->Crc != calculatedCrc ? usprintf(", invalid, should be %08Xh", calculatedCrc) : UString(", valid")); - // Add correct offset - pdata.offset = parentOffset; - // Add tree item - index = model->addItem(Types::FtwStore, 0, name, UString(), info, header, body, UByteArray(), true, parsingDataToUByteArray(pdata), parent); + index = model->addItem(localOffset, Types::FtwStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, parent); return U_SUCCESS; } -USTATUS NvramParser::parseFdcStoreHeader(const UByteArray & store, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index) +USTATUS NvramParser::parseFdcStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index) { const UINT32 dataSize = (const UINT32)store.size(); @@ -897,9 +882,6 @@ USTATUS NvramParser::parseFdcStoreHeader(const UByteArray & store, const UINT32 return U_SUCCESS; } - // Get parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(parent); - // Construct header and body UByteArray header = store.left(headerSize); UByteArray body = store.mid(headerSize, fdcStoreHeader->Size - headerSize); @@ -913,16 +895,13 @@ USTATUS NvramParser::parseFdcStoreHeader(const UByteArray & store, const UINT32 // TODO: add internal headers info - // Add correct offset - pdata.offset = parentOffset; - // Add tree item - index = model->addItem(Types::FdcStore, 0, name, UString(), info, header, body, UByteArray(), true, parsingDataToUByteArray(pdata), parent); + index = model->addItem(localOffset, Types::FdcStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, parent); return U_SUCCESS; } -USTATUS NvramParser::parseFsysStoreHeader(const UByteArray & store, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index) +USTATUS NvramParser::parseFsysStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index) { const UINT32 dataSize = (const UINT32)store.size(); @@ -943,9 +922,6 @@ USTATUS NvramParser::parseFsysStoreHeader(const UByteArray & store, const UINT32 return U_SUCCESS; } - // Get parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(parent); - // Construct header and body UByteArray header = store.left(sizeof(APPLE_FSYS_STORE_HEADER)); UByteArray body = store.mid(sizeof(APPLE_FSYS_STORE_HEADER), fsysStoreHeader->Size - sizeof(APPLE_FSYS_STORE_HEADER) - sizeof(UINT32)); @@ -966,16 +942,13 @@ USTATUS NvramParser::parseFsysStoreHeader(const UByteArray & store, const UINT32 fsysStoreHeader->Unknown1) + (storedCrc != calculatedCrc ? usprintf(", invalid, should be %08Xh", calculatedCrc) : UString(", valid")); - // Add correct offset - pdata.offset = parentOffset; - // Add tree item - index = model->addItem(Types::FsysStore, 0, name, UString(), info, header, body, UByteArray(), true, parsingDataToUByteArray(pdata), parent); + index = model->addItem(localOffset, Types::FsysStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, parent); return U_SUCCESS; } -USTATUS NvramParser::parseEvsaStoreHeader(const UByteArray & store, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index) +USTATUS NvramParser::parseEvsaStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index) { const UINT32 dataSize = (const UINT32)store.size(); @@ -996,9 +969,6 @@ USTATUS NvramParser::parseEvsaStoreHeader(const UByteArray & store, const UINT32 return U_SUCCESS; } - // Get parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(parent); - // Construct header and body UByteArray header = store.left(evsaStoreHeader->Header.Size); UByteArray body = store.mid(evsaStoreHeader->Header.Size, evsaStoreHeader->StoreSize - evsaStoreHeader->Header.Size); @@ -1017,16 +987,13 @@ USTATUS NvramParser::parseEvsaStoreHeader(const UByteArray & store, const UINT32 evsaStoreHeader->Header.Checksum) + (evsaStoreHeader->Header.Checksum != calculated ? usprintf("%, invalid, should be %02Xh", calculated) : UString(", valid")); - // Add correct offset - pdata.offset = parentOffset; - // Add tree item - index = model->addItem(Types::EvsaStore, 0, name, UString(), info, header, body, UByteArray(), true, parsingDataToUByteArray(pdata), parent); + index = model->addItem(localOffset, Types::EvsaStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, parent); return U_SUCCESS; } -USTATUS NvramParser::parseFlashMapStoreHeader(const UByteArray & store, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index) +USTATUS NvramParser::parseFlashMapStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index) { const UINT32 dataSize = (const UINT32)store.size(); @@ -1048,9 +1015,6 @@ USTATUS NvramParser::parseFlashMapStoreHeader(const UByteArray & store, const UI return U_SUCCESS; } - // Get parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(parent); - // Construct header and body UByteArray header = store.left(sizeof(PHOENIX_FLASH_MAP_HEADER)); UByteArray body = store.mid(sizeof(PHOENIX_FLASH_MAP_HEADER), flashMapSize - sizeof(PHOENIX_FLASH_MAP_HEADER)); @@ -1063,16 +1027,13 @@ USTATUS NvramParser::parseFlashMapStoreHeader(const UByteArray & store, const UI body.size(), body.size(), flashMapHeader->NumEntries); - // Add correct offset - pdata.offset = parentOffset; - // Add tree item - index = model->addItem(Types::FlashMapStore, 0, name, UString(), info, header, body, UByteArray(), true, parsingDataToUByteArray(pdata), parent); + index = model->addItem(localOffset, Types::FlashMapStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, parent); return U_SUCCESS; } -USTATUS NvramParser::parseCmdbStoreHeader(const UByteArray & store, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index) +USTATUS NvramParser::parseCmdbStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index) { const UINT32 dataSize = (const UINT32)store.size(); @@ -1093,9 +1054,6 @@ USTATUS NvramParser::parseCmdbStoreHeader(const UByteArray & store, const UINT32 // Get store header const PHOENIX_CMDB_HEADER* cmdbHeader = (const PHOENIX_CMDB_HEADER*)store.constData(); - // Get parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(parent); - // Construct header and body UByteArray header = store.left(cmdbHeader->TotalSize); UByteArray body = store.mid(cmdbHeader->TotalSize, cmdbSize - cmdbHeader->TotalSize); @@ -1107,16 +1065,13 @@ USTATUS NvramParser::parseCmdbStoreHeader(const UByteArray & store, const UINT32 header.size(), header.size(), body.size(), body.size()); - // Add correct offset - pdata.offset = parentOffset; - // Add tree item - index = model->addItem(Types::CmdbStore, 0, name, UString(), info, header, body, UByteArray(), true, parsingDataToUByteArray(pdata), parent); + index = model->addItem(localOffset, Types::CmdbStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, parent); return U_SUCCESS; } -USTATUS NvramParser::parseSlicPubkeyHeader(const UByteArray & store, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index) +USTATUS NvramParser::parseSlicPubkeyHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index) { const UINT32 dataSize = (const UINT32)store.size(); @@ -1137,9 +1092,6 @@ USTATUS NvramParser::parseSlicPubkeyHeader(const UByteArray & store, const UINT3 return U_SUCCESS; } - // Get parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(parent); - // Construct header and body UByteArray header = store.left(sizeof(OEM_ACTIVATION_PUBKEY)); @@ -1155,16 +1107,13 @@ USTATUS NvramParser::parseSlicPubkeyHeader(const UByteArray & store, const UINT3 pubkeyHeader->BitLength, pubkeyHeader->Exponent); - // Add correct offset - pdata.offset = parentOffset; - // Add tree item - index = model->addItem(Types::SlicData, Subtypes::PubkeySlicData, name, UString(), info, header, UByteArray(), UByteArray(), true, parsingDataToUByteArray(pdata), parent); + index = model->addItem(localOffset, Types::SlicData, Subtypes::PubkeySlicData, name, UString(), info, header, UByteArray(), UByteArray(), Fixed, parent); return U_SUCCESS; } -USTATUS NvramParser::parseSlicMarkerHeader(const UByteArray & store, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index) +USTATUS NvramParser::parseSlicMarkerHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index) { const UINT32 dataSize = (const UINT32)store.size(); @@ -1185,9 +1134,6 @@ USTATUS NvramParser::parseSlicMarkerHeader(const UByteArray & store, const UINT3 return U_SUCCESS; } - // Get parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(parent); - // Construct header and body UByteArray header = store.left(sizeof(OEM_ACTIVATION_MARKER)); @@ -1202,16 +1148,14 @@ USTATUS NvramParser::parseSlicMarkerHeader(const UByteArray & store, const UINT3 (const char*)UString((const char*)&(markerHeader->OemTableId)).left(8).toLocal8Bit(), markerHeader->SlicVersion); - // Add correct offset - pdata.offset = parentOffset; // Add tree item - index = model->addItem(Types::SlicData, Subtypes::MarkerSlicData, name, UString(), info, header, UByteArray(), UByteArray(), true, parsingDataToUByteArray(pdata), parent); + index = model->addItem(localOffset, Types::SlicData, Subtypes::MarkerSlicData, name, UString(), info, header, UByteArray(), UByteArray(), Fixed, parent); return U_SUCCESS; } -USTATUS NvramParser::parseIntelMicrocodeHeader(const UByteArray & store, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index) +USTATUS NvramParser::parseIntelMicrocodeHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index) { const UINT32 dataSize = (const UINT32)store.size(); @@ -1232,14 +1176,11 @@ USTATUS NvramParser::parseIntelMicrocodeHeader(const UByteArray & store, const U return U_SUCCESS; } - // Get parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(parent); - // Construct header and body UByteArray header = store.left(sizeof(INTEL_MICROCODE_HEADER)); UByteArray body = store.mid(sizeof(INTEL_MICROCODE_HEADER), ucodeHeader->DataSize); - //TODO: recalculate checksum + //TODO: recalculate microcode checksum // Add info UString name("Intel microcode"); @@ -1254,16 +1195,13 @@ USTATUS NvramParser::parseIntelMicrocodeHeader(const UByteArray & store, const U ucodeHeader->LoaderRevision, ucodeHeader->CpuFlags); - // Add correct offset - pdata.offset = parentOffset; - // Add tree item - index = model->addItem(Types::Microcode, Subtypes::IntelMicrocode, name, UString(), info, header, body, UByteArray(), true, parsingDataToUByteArray(pdata), parent); + index = model->addItem(localOffset, Types::Microcode, Subtypes::IntelMicrocode, name, UString(), info, header, body, UByteArray(), Fixed, parent); return U_SUCCESS; } -USTATUS NvramParser::parseStoreHeader(const UByteArray & store, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index) +USTATUS NvramParser::parseStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index) { const UINT32 dataSize = (const UINT32)store.size(); const UINT32* signature = (const UINT32*)store.constData(); @@ -1276,35 +1214,35 @@ USTATUS NvramParser::parseStoreHeader(const UByteArray & store, const UINT32 par // Check signature and run parser function needed // VSS/SVS store if (*signature == NVRAM_VSS_STORE_SIGNATURE || *signature == NVRAM_APPLE_SVS_STORE_SIGNATURE) - return parseVssStoreHeader(store, parentOffset, parent, index); + return parseVssStoreHeader(store, localOffset, parent, index); // FTW store else if (*signature == NVRAM_MAIN_STORE_VOLUME_GUID_DATA1 || *signature == EDKII_WORKING_BLOCK_SIGNATURE_GUID_DATA1) - return parseFtwStoreHeader(store, parentOffset, parent, index); + return parseFtwStoreHeader(store, localOffset, parent, index); // FDC store else if (*signature == NVRAM_FDC_VOLUME_SIGNATURE) - return parseFdcStoreHeader(store, parentOffset, parent, index); + return parseFdcStoreHeader(store, localOffset, parent, index); // Apple Fsys/Gaid store else if (*signature == NVRAM_APPLE_FSYS_STORE_SIGNATURE || *signature == NVRAM_APPLE_GAID_STORE_SIGNATURE) - return parseFsysStoreHeader(store, parentOffset, parent, index); + return parseFsysStoreHeader(store, localOffset, parent, index); // EVSA store else if (*(signature + 1) == NVRAM_EVSA_STORE_SIGNATURE) - return parseEvsaStoreHeader(store, parentOffset, parent, index); + return parseEvsaStoreHeader(store, localOffset, parent, index); // Phoenix SCT flash map else if (*signature == NVRAM_PHOENIX_FLASH_MAP_SIGNATURE_PART1) - return parseFlashMapStoreHeader(store, parentOffset, parent, index); + return parseFlashMapStoreHeader(store, localOffset, parent, index); // Phoenix CMDB store else if (*signature == NVRAM_PHOENIX_CMDB_HEADER_SIGNATURE) - return parseCmdbStoreHeader(store, parentOffset, parent, index); + return parseCmdbStoreHeader(store, localOffset, parent, index); // SLIC pubkey else if (*(signature + 4) == OEM_ACTIVATION_PUBKEY_MAGIC) - return parseSlicPubkeyHeader(store, parentOffset, parent, index); + return parseSlicPubkeyHeader(store, localOffset, parent, index); // SLIC marker else if (*(const UINT64*)(store.constData() + 26) == OEM_ACTIVATION_MARKER_WINDOWS_FLAG) - return parseSlicMarkerHeader(store, parentOffset, parent, index); + return parseSlicMarkerHeader(store, localOffset, parent, index); // Intel microcode // Must be checked after SLIC marker because of the same *signature values else if (*signature == INTEL_MICROCODE_HEADER_VERSION) - return parseIntelMicrocodeHeader(store, parentOffset, parent, index); + return parseIntelMicrocodeHeader(store, localOffset, parent, index); msg(usprintf("parseStoreHeader: don't know how to parse a header with signature %08Xh", *signature), parent); return U_SUCCESS; @@ -1316,9 +1254,19 @@ USTATUS NvramParser::parseVssStoreBody(const UModelIndex & index) if (!index.isValid()) return U_INVALID_PARAMETER; - // Get parsing data for the current item - PARSING_DATA pdata = parsingDataFromUModelIndex(index); - UINT32 parentOffset = pdata.offset + model->header(index).size(); + // Obtain required information from parent volume + UINT8 emptyByte = 0xFF; + UModelIndex parentVolumeIndex = model->findParentOfType(index, Types::Volume); + if (parentVolumeIndex.isValid() && model->hasEmptyParsingData(parentVolumeIndex) == false) { + UByteArray data = model->parsingData(parentVolumeIndex); + const VOLUME_PARSING_DATA* pdata = (const VOLUME_PARSING_DATA*)data.constData(); + emptyByte = pdata->ffsVersion; + } + + // Get local offset + UINT32 localOffset = model->offset(index) + model->header(index).size(); + + // Get item data const UByteArray data = model->body(index); // Check that the is enough space for variable header @@ -1432,36 +1380,24 @@ USTATUS NvramParser::parseVssStoreBody(const UModelIndex & index) if (!variableSize) { // Check if the data left is a free space or a padding UByteArray padding = data.mid(offset, unparsedSize); - UINT8 type; + // Get info + UString info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size()); - if (padding.count(pdata.emptyByte) == padding.size()) { - // It's a free space - name = UString("Free space"); - type = Types::FreeSpace; - subtype = 0; + if (padding.count(emptyByte) == padding.size()) { // Free space + // Add tree item + model->addItem(localOffset + offset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), padding, UByteArray(), Movable, index); } - else { + else { // Padding // Nothing is parsed yet, but the store is not empty if (!offset) { msg(UString("parseVssStoreBody: store can't be parsed as VSS store"), index); return U_SUCCESS; } - // It's a padding - name = UString("Padding"); - type = Types::Padding; - subtype = getPaddingType(padding); + // Add tree item + model->addItem(localOffset + offset, Types::Padding, getPaddingType(padding), UString("Padding"), UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); } - // Get info - UString info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size()); - - // Construct parsing data - pdata.offset = parentOffset + offset; - - // Add tree item - model->addItem(type, subtype, name, UString(), info, UByteArray(), padding, UByteArray(), false, parsingDataToUByteArray(pdata), index); - return U_SUCCESS; } @@ -1501,11 +1437,8 @@ USTATUS NvramParser::parseVssStoreBody(const UModelIndex & index) else subtype = Subtypes::StandardVssEntry; - // Add correct offset to parsing data - pdata.offset = parentOffset + offset; - // Add tree item - model->addItem(Types::VssEntry, subtype, name, text, info, header, body, UByteArray(), false, parsingDataToUByteArray(pdata), index); + model->addItem(localOffset + offset, Types::VssEntry, subtype, name, text, info, header, body, UByteArray(), Movable, index); // Move to next variable offset += variableSize; @@ -1520,9 +1453,10 @@ USTATUS NvramParser::parseFsysStoreBody(const UModelIndex & index) if (!index.isValid()) return U_INVALID_PARAMETER; - // Get parsing data for the current item - PARSING_DATA pdata = parsingDataFromUModelIndex(index); - UINT32 parentOffset = pdata.offset + model->header(index).size(); + // Get local offset + UINT32 localOffset = model->offset(index) + model->header(index).size(); + + // Get item data const UByteArray data = model->body(index); // Check that the is enough space for variable header @@ -1549,12 +1483,9 @@ USTATUS NvramParser::parseFsysStoreBody(const UModelIndex & index) // There is no data afterward, add EOF variable and free space and return UByteArray header = data.mid(offset, sizeof(UINT8) + nameSize); UString info = usprintf("Full size: %Xh (%u)", header.size(), header.size()); - - // Add correct offset to parsing data - pdata.offset = parentOffset + offset; - + // Add EOF tree item - model->addItem(Types::FsysEntry, 0, UString("EOF"), UString(), info, header, UByteArray(), UByteArray(), false, parsingDataToUByteArray(pdata), index); + model->addItem(localOffset + offset, Types::FsysEntry, 0, UString("EOF"), UString(), info, header, UByteArray(), UByteArray(), Fixed, index); // Add free space offset += header.size(); @@ -1562,11 +1493,8 @@ USTATUS NvramParser::parseFsysStoreBody(const UModelIndex & index) UByteArray body = data.mid(offset); info = usprintf("Full size: %Xh (%u)", body.size(), body.size()); - // Add correct offset to parsing data - pdata.offset = parentOffset + offset; - // Add free space tree item - model->addItem(Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), body, UByteArray(), false, parsingDataToUByteArray(pdata), index); + model->addItem(localOffset + offset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), body, UByteArray(), Movable, index); return U_SUCCESS; } @@ -1582,11 +1510,8 @@ USTATUS NvramParser::parseFsysStoreBody(const UModelIndex & index) UByteArray body = data.mid(offset); UString info = usprintf("Full size: %Xh (%u)", body.size(), body.size()); - // Add correct offset to parsing data - pdata.offset = parentOffset + offset; - - // Add free space tree item - model->addItem(Types::Padding, getPaddingType(body), UString("Padding"), UString(), info, UByteArray(), body, UByteArray(), false, parsingDataToUByteArray(pdata), index); + // Add padding tree item + model->addItem(localOffset + offset, Types::Padding, getPaddingType(body), UString("Padding"), UString(), info, UByteArray(), body, UByteArray(), Fixed, index); // Show message msg(UString("parseFsysStoreBody: next variable appears too big, added as padding"), index); @@ -1604,11 +1529,8 @@ USTATUS NvramParser::parseFsysStoreBody(const UModelIndex & index) header.size(), header.size(), body.size(), body.size()); - // Add correct offset to parsing data - pdata.offset = parentOffset + offset; - // Add tree item - model->addItem(Types::FsysEntry, 0, UString(name.constData()), UString(), info, header, body, UByteArray(), false, parsingDataToUByteArray(pdata), index); + model->addItem(localOffset + offset, Types::FsysEntry, 0, UString(name.constData()), UString(), info, header, body, UByteArray(), Movable, index); // Move to next variable offset += variableSize; @@ -1623,9 +1545,19 @@ USTATUS NvramParser::parseEvsaStoreBody(const UModelIndex & index) if (!index.isValid()) return U_INVALID_PARAMETER; - // Get parsing data for the current item - PARSING_DATA pdata = parsingDataFromUModelIndex(index); - UINT32 parentOffset = pdata.offset + model->header(index).size(); + // Obtain required information from parent volume + UINT8 emptyByte = 0xFF; + UModelIndex parentVolumeIndex = model->findParentOfType(index, Types::Volume); + if (parentVolumeIndex.isValid() && model->hasEmptyParsingData(parentVolumeIndex) == false) { + UByteArray data = model->parsingData(parentVolumeIndex); + const VOLUME_PARSING_DATA* pdata = (const VOLUME_PARSING_DATA*)data.constData(); + emptyByte = pdata->ffsVersion; + } + + // Get local offset + UINT32 localOffset = model->offset(index) + model->header(index).size(); + + // Get item data const UByteArray data = model->body(index); // Check that the is enough space for entry header @@ -1654,26 +1586,18 @@ USTATUS NvramParser::parseEvsaStoreBody(const UModelIndex & index) UByteArray body = data.mid(offset); UString info = usprintf("Full size: %Xh (%u)", body.size(), body.size()); - // Checke type - UString name("Free space"); - UINT8 type = Types::FreeSpace; - UINT8 subtype = 0; - if (getPaddingType(body) == Subtypes::DataPadding) { - name = UString("Padding"); - type = Types::Padding; - subtype = Subtypes::DataPadding; + if (body.count(emptyByte) == body.size()) { // Free space + // Add free space tree item + UModelIndex itemIndex = model->addItem(localOffset + offset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), body, UByteArray(), Movable, index); } + else { + // Add padding tree item + UModelIndex itemIndex = model->addItem(localOffset + offset, Types::Padding, getPaddingType(body), UString("Padding"), UString(), info, UByteArray(), body, UByteArray(), Fixed, index); - // Add correct offset to parsing data - pdata.offset = parentOffset + offset; - - // Add free space tree item - UModelIndex itemIndex = model->addItem(type, subtype, name, UString(), info, UByteArray(), body, UByteArray(), false, parsingDataToUByteArray(pdata), index); - - // Show message - if (type == Types::Padding) + // Show message + msg(UString("parseEvsaStoreBody: variable parsing failed, the rest of unparsed store added as padding"), itemIndex); - + } break; } variableSize = entryHeader->Size; @@ -1755,33 +1679,22 @@ USTATUS NvramParser::parseEvsaStoreBody(const UModelIndex & index) UByteArray body = data.mid(offset); UString info = usprintf("Full size: %Xh (%u)", body.size(), body.size()); - // Check type - UString name("Free space"); - UINT8 type = Types::FreeSpace; - UINT8 subtype = 0; - if (getPaddingType(body) == Subtypes::DataPadding) { - name = UString("Padding"); - type = Types::Padding; - subtype = Subtypes::DataPadding; + if (body.count(emptyByte) == body.size()) { // Free space + // Add free space tree item + UModelIndex itemIndex = model->addItem(localOffset + offset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), body, UByteArray(), Movable, index); } + else { + // Add padding tree item + UModelIndex itemIndex = model->addItem(localOffset + offset, Types::Padding, getPaddingType(body), UString("Padding"), UString(), info, UByteArray(), body, UByteArray(), Fixed, index); - // Add correct offset to parsing data - pdata.offset = parentOffset + offset; - - // Add free space tree item - UModelIndex itemIndex = model->addItem(type, subtype, name, UString(), info, UByteArray(), body, UByteArray(), false, parsingDataToUByteArray(pdata), index); - - // Show message - if (type == Types::Padding) - msg(usprintf("parseEvsaStoreBody: unknown variable of type %02Xh found at offset %Xh, the rest of unparsed store added as padding",entryHeader->Type, offset), itemIndex); + // Show message + msg(usprintf("parseEvsaStoreBody: unknown variable of type %02Xh found at offset %Xh, the rest of unparsed store added as padding", entryHeader->Type, offset), itemIndex); + } break; } - // Add correct offset to parsing data - pdata.offset = parentOffset + offset; - // Add tree item - model->addItem(Types::EvsaEntry, subtype, name, UString(), info, header, body, UByteArray(), false, parsingDataToUByteArray(pdata), index); + model->addItem(localOffset + offset, Types::EvsaEntry, subtype, name, UString(), info, header, body, UByteArray(), Movable, index); // Move to next variable offset += variableSize; @@ -1842,8 +1755,7 @@ USTATUS NvramParser::parseFlashMapBody(const UModelIndex & index) return U_INVALID_PARAMETER; // Get parsing data for the current item - PARSING_DATA pdata = parsingDataFromUModelIndex(index); - UINT32 parentOffset = pdata.offset + model->header(index).size(); + UINT32 localOffset = model->offset(index) + model->header(index).size(); const UByteArray data = model->body(index); @@ -1860,11 +1772,8 @@ USTATUS NvramParser::parseFlashMapBody(const UModelIndex & index) UByteArray body = data.mid(offset); UString info = usprintf("Full size: %Xh (%u)", body.size(), body.size()); - // Add correct offset to parsing data - pdata.offset = parentOffset + offset; - - // Add free space tree item - model->addItem(Types::Padding, getPaddingType(body), UString("Padding"), UString(), info, UByteArray(), body, UByteArray(), false, parsingDataToUByteArray(pdata), index); + // Add padding tree item + model->addItem(localOffset + offset, Types::Padding, getPaddingType(body), UString("Padding"), UString(), info, UByteArray(), body, UByteArray(), Fixed, index); // Show message if (unparsedSize < entryHeader->Size) @@ -1887,9 +1796,6 @@ USTATUS NvramParser::parseFlashMapBody(const UModelIndex & index) entryHeader->Size, entryHeader->Offset); - // Add correct offset to parsing data - pdata.offset = parentOffset + offset; - // Determine subtype UINT8 subtype = 0; switch (entryHeader->DataType) { @@ -1902,7 +1808,7 @@ USTATUS NvramParser::parseFlashMapBody(const UModelIndex & index) } // Add tree item - model->addItem(Types::FlashMapEntry, subtype, name, flashMapGuidToUString(entryHeader->Guid), info, header, UByteArray(), UByteArray(), true, parsingDataToUByteArray(pdata), index); + model->addItem(localOffset + offset, Types::FlashMapEntry, subtype, name, flashMapGuidToUString(entryHeader->Guid), info, header, UByteArray(), UByteArray(), Movable, index); // Move to next variable offset += sizeof(PHOENIX_FLASH_MAP_ENTRY); diff --git a/common/nvramparser.h b/common/nvramparser.h index 10678c4..f8de4c1 100644 --- a/common/nvramparser.h +++ b/common/nvramparser.h @@ -46,20 +46,20 @@ private: messagesVector.push_back(std::pair(message, index)); }; - USTATUS findNextStore(const UModelIndex & index, const UByteArray & volume, const UINT32 parentOffset, const UINT32 storeOffset, UINT32 & nextStoreOffset); + USTATUS findNextStore(const UModelIndex & index, const UByteArray & volume, const UINT32 localOffset, const UINT32 storeOffset, UINT32 & nextStoreOffset); USTATUS getStoreSize(const UByteArray & data, const UINT32 storeOffset, UINT32 & storeSize); - USTATUS parseStoreHeader(const UByteArray & store, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index); + USTATUS parseStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index); - USTATUS parseVssStoreHeader(const UByteArray & store, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index); - USTATUS parseFtwStoreHeader(const UByteArray & store, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index); - USTATUS parseFdcStoreHeader(const UByteArray & store, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index); - USTATUS parseFsysStoreHeader(const UByteArray & store, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index); - USTATUS parseEvsaStoreHeader(const UByteArray & store, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index); - USTATUS parseFlashMapStoreHeader(const UByteArray & store, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index); - USTATUS parseCmdbStoreHeader(const UByteArray & store, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index); - USTATUS parseSlicPubkeyHeader(const UByteArray & store, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index); - USTATUS parseSlicMarkerHeader(const UByteArray & store, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index); - USTATUS parseIntelMicrocodeHeader(const UByteArray & store, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index); + USTATUS parseVssStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index); + USTATUS parseFtwStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index); + USTATUS parseFdcStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index); + USTATUS parseFsysStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index); + USTATUS parseEvsaStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index); + USTATUS parseFlashMapStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index); + USTATUS parseCmdbStoreHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index); + USTATUS parseSlicPubkeyHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index); + USTATUS parseSlicMarkerHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index); + USTATUS parseIntelMicrocodeHeader(const UByteArray & store, const UINT32 localOffset, const UModelIndex & parent, UModelIndex & index); USTATUS parseVssStoreBody(const UModelIndex & index); USTATUS parseFsysStoreBody(const UModelIndex & index); @@ -71,20 +71,17 @@ class NvramParser { public: // Default constructor and destructor - NvramParser(TreeModel* treeModel) : model(treeModel) {} + NvramParser(TreeModel* treeModel) { U_UNUSED_PARAMETER(treeModel); } ~NvramParser() {} // Returns messages - std::vector > getMessages() const { return messagesVector; } + std::vector > getMessages() const { return std::vector >(); } // Clears messages - void clearMessages() { messagesVector.clear(); } + void clearMessages() {} // NVRAM parsing USTATUS parseNvramVolumeBody(const UModelIndex &) { return U_SUCCESS; } USTATUS parseNvarStore(const UModelIndex &) { return U_SUCCESS; } -private: - TreeModel *model; - std::vector > messagesVector; }; #endif // U_ENABLE_NVRAM_PARSING_SUPPORT #endif // NVRAMPARSER_H diff --git a/common/parsingdata.h b/common/parsingdata.h index b52870d..622968e 100644 --- a/common/parsingdata.h +++ b/common/parsingdata.h @@ -20,6 +20,8 @@ routines without the need of backward traversal #include "basetypes.h" typedef struct VOLUME_PARSING_DATA_ { + UINT8 ffsVersion; + UINT8 emptyByte; EFI_GUID extendedHeaderGuid; UINT32 alignment; UINT8 revision; @@ -30,54 +32,30 @@ typedef struct VOLUME_PARSING_DATA_ { } VOLUME_PARSING_DATA; typedef struct FILE_PARSING_DATA_ { + UINT8 emptyByte; EFI_GUID guid; } FILE_PARSING_DATA; +typedef struct GUID_PARSING_DATA_ { + EFI_GUID guid; +} GUIDED_SECTION_PARSING_DATA, FREEFORM_GUIDED_SECTION_PARSING_DATA; + typedef struct COMPRESSED_SECTION_PARSING_DATA_ { UINT32 uncompressedSize; UINT8 compressionType; UINT8 algorithm; } COMPRESSED_SECTION_PARSING_DATA; -typedef struct GUIDED_SECTION_PARSING_DATA_ { - EFI_GUID guid; -} GUIDED_SECTION_PARSING_DATA; - -typedef struct FREEFORM_GUIDED_SECTION_PARSING_DATA_ { - EFI_GUID guid; -} FREEFORM_GUIDED_SECTION_PARSING_DATA; - typedef struct TE_IMAGE_SECTION_PARSING_DATA_ { - UINT32 imageBase; - UINT32 adjustedImageBase; - UINT8 imageBaseType; + UINT32 imageBase; + UINT32 adjustedImageBase; + UINT8 imageBaseType; } TE_IMAGE_SECTION_PARSING_DATA; -typedef struct SECTION_PARSING_DATA_ { - union { - COMPRESSED_SECTION_PARSING_DATA compressed; - GUIDED_SECTION_PARSING_DATA guidDefined; - FREEFORM_GUIDED_SECTION_PARSING_DATA freeformSubtypeGuid; - TE_IMAGE_SECTION_PARSING_DATA teImage; - }; -} SECTION_PARSING_DATA; - typedef struct NVAR_ENTRY_PARSING_DATA_ { - UINT32 next; + UINT8 emptyByte; BOOLEAN isValid; + UINT32 next; } NVAR_ENTRY_PARSING_DATA; -typedef struct PARSING_DATA_ { - UINT8 emptyByte; - UINT8 ffsVersion; - UINT32 offset; - UINT32 address; - union { - VOLUME_PARSING_DATA volume; - FILE_PARSING_DATA file; - SECTION_PARSING_DATA section; - NVAR_ENTRY_PARSING_DATA nvar; - }; -} PARSING_DATA; - -#endif // NVRAM_H +#endif // PARSINGDATA_H diff --git a/common/treeitem.cpp b/common/treeitem.cpp index ce65a0b..801edf4 100644 --- a/common/treeitem.cpp +++ b/common/treeitem.cpp @@ -14,12 +14,13 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "treeitem.h" #include "types.h" -TreeItem::TreeItem(const UINT8 type, const UINT8 subtype, +TreeItem::TreeItem(const UINT32 offset, const UINT8 type, const UINT8 subtype, const UString & name, const UString & text, const UString & info, const UByteArray & header, const UByteArray & body, const UByteArray & tail, - const bool fixed, const bool compressed, const UByteArray & parsingData, + const bool fixed, const bool compressed, TreeItem *parent) : itemAction(Actions::NoAction), + itemOffset(offset), itemType(type), itemSubtype(subtype), itemName(name), @@ -28,7 +29,6 @@ TreeItem::TreeItem(const UINT8 type, const UINT8 subtype, itemHeader(header), itemBody(body), itemTail(tail), - itemParsingData(parsingData), itemFixed(fixed), itemCompressed(compressed), parentItem(parent) diff --git a/common/treeitem.h b/common/treeitem.h index 17c57a4..a18e9b2 100644 --- a/common/treeitem.h +++ b/common/treeitem.h @@ -24,9 +24,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. class TreeItem { public: - TreeItem(const UINT8 type, const UINT8 subtype, const UString &name, const UString &text, const UString &info, + TreeItem(const UINT32 offset, const UINT8 type, const UINT8 subtype, const UString &name, const UString &text, const UString &info, const UByteArray & header, const UByteArray & body, const UByteArray & tail, - const bool fixed, const bool compressed, const UByteArray & parsingData, + const bool fixed, const bool compressed, TreeItem *parent = 0); ~TreeItem(); // Non-trivial implementation in CPP file @@ -45,8 +45,8 @@ public: TreeItem *parent() { return parentItem; } // Getters and setters for item parameters - UString name() const { return itemName; } - void setName(const UString &text) { itemName = text; } + UINT32 offset() const { return itemOffset; } + void setOffset(const UINT32 offset) { itemOffset = offset; } UINT8 type() const { return itemType; } void setType(const UINT8 type) { itemType = type; } @@ -54,6 +54,9 @@ public: UINT8 subtype() const { return itemSubtype; } void setSubtype(const UINT8 subtype) { itemSubtype = subtype; } + UString name() const { return itemName; } + void setName(const UString &text) { itemName = text; } + UString text() const { return itemText; } void setText(const UString &text) { itemText = text; } @@ -66,10 +69,6 @@ public: UByteArray tail() const { return itemTail; }; bool hasEmptyTail() const { return itemTail.isEmpty(); } - UByteArray parsingData() const { return itemParsingData; } - bool hasEmptyParsingData() const { return itemParsingData.isEmpty(); } - void setParsingData(const UByteArray & data) { itemParsingData = data; } - UString info() const { return itemInfo; } void addInfo(const UString &info, const bool append) { if (append) itemInfo += info; else itemInfo = info + itemInfo; } void setInfo(const UString &info) { itemInfo = info; } @@ -83,8 +82,13 @@ public: bool compressed() const { return itemCompressed; } void setCompressed(const bool compressed) { itemCompressed = compressed; } + UByteArray parsingData() const { return itemParsingData; }; + bool hasEmptyParsingData() const { return itemParsingData.isEmpty(); } + void setParsingData(const UByteArray & pdata) { itemParsingData = pdata; } + private: std::list childItems; + UINT32 itemOffset; UINT8 itemAction; UINT8 itemType; UINT8 itemSubtype; @@ -94,9 +98,9 @@ private: UByteArray itemHeader; UByteArray itemBody; UByteArray itemTail; - UByteArray itemParsingData; bool itemFixed; bool itemCompressed; + UByteArray itemParsingData; TreeItem* parentItem; }; diff --git a/common/treemodel.cpp b/common/treemodel.cpp index 7a7e106..3cd77b3 100644 --- a/common/treemodel.cpp +++ b/common/treemodel.cpp @@ -157,6 +157,14 @@ int TreeModel::rowCount(const UModelIndex &parent) const return parentItem->childCount(); } +UINT32 TreeModel::offset(const UModelIndex &index) const +{ + if (!index.isValid()) + return 0; + TreeItem *item = static_cast(index.internalPointer()); + return item->offset(); +} + UINT8 TreeModel::type(const UModelIndex &index) const { if (!index.isValid()) @@ -221,22 +229,6 @@ bool TreeModel::hasEmptyTail(const UModelIndex &index) const return item->hasEmptyTail(); } -UByteArray TreeModel::parsingData(const UModelIndex &index) const -{ - if (!index.isValid()) - return UByteArray(); - TreeItem *item = static_cast(index.internalPointer()); - return item->parsingData(); -} - -bool TreeModel::hasEmptyParsingData(const UModelIndex &index) const -{ - if (!index.isValid()) - return true; - TreeItem *item = static_cast(index.internalPointer()); - return item->hasEmptyParsingData(); -} - UString TreeModel::name(const UModelIndex &index) const { if (!index.isValid()) @@ -320,6 +312,25 @@ void TreeModel::setCompressed(const UModelIndex &index, const bool compressed) emit dataChanged(index, index); } +void TreeModel::setOffset(const UModelIndex &index, const UINT32 offset) +{ + if (!index.isValid()) + return; + + TreeItem *item = static_cast(index.internalPointer()); + item->setOffset(offset); + emit dataChanged(index, index); +} + +void TreeModel::setType(const UModelIndex &index, const UINT8 data) +{ + if (!index.isValid()) + return; + + TreeItem *item = static_cast(index.internalPointer()); + item->setType(data); + emit dataChanged(index, index); +} void TreeModel::setSubtype(const UModelIndex & index, const UINT8 subtype) { @@ -341,16 +352,6 @@ void TreeModel::setName(const UModelIndex &index, const UString &data) emit dataChanged(index, index); } -void TreeModel::setType(const UModelIndex &index, const UINT8 data) -{ - if (!index.isValid()) - return; - - TreeItem *item = static_cast(index.internalPointer()); - item->setType(data); - emit dataChanged(index, index); -} - void TreeModel::setText(const UModelIndex &index, const UString &data) { if (!index.isValid()) @@ -391,6 +392,24 @@ void TreeModel::setAction(const UModelIndex &index, const UINT8 action) emit dataChanged(index, index); } +UByteArray TreeModel::parsingData(const UModelIndex &index) const +{ + if (!index.isValid()) + return UByteArray(); + + TreeItem *item = static_cast(index.internalPointer()); + return item->parsingData(); +} + +bool TreeModel::hasEmptyParsingData(const UModelIndex &index) const +{ + if (!index.isValid()) + return true; + + TreeItem *item = static_cast(index.internalPointer()); + return item->hasEmptyParsingData(); +} + void TreeModel::setParsingData(const UModelIndex &index, const UByteArray &data) { if (!index.isValid()) @@ -401,10 +420,10 @@ void TreeModel::setParsingData(const UModelIndex &index, const UByteArray &data) emit dataChanged(this->index(0, 0), index); } -UModelIndex TreeModel::addItem(const UINT8 type, const UINT8 subtype, +UModelIndex TreeModel::addItem(const UINT32 offset, const UINT8 type, const UINT8 subtype, const UString & name, const UString & text, const UString & info, const UByteArray & header, const UByteArray & body, const UByteArray & tail, - const bool fixed, const UByteArray & parsingData, + const ItemFixedState fixed, const UModelIndex & parent, const UINT8 mode) { TreeItem *item = 0; @@ -426,7 +445,7 @@ UModelIndex TreeModel::addItem(const UINT8 type, const UINT8 subtype, } } - TreeItem *newItem = new TreeItem(type, subtype, name, text, info, header, body, tail, fixed, this->compressed(parent), parsingData, parentItem); + TreeItem *newItem = new TreeItem(offset, type, subtype, name, text, info, header, body, tail, Movable, this->compressed(parent), parentItem); if (mode == CREATE_MODE_APPEND) { emit layoutAboutToBeChanged(); diff --git a/common/treemodel.h b/common/treemodel.h index fcc64a3..d255b3d 100644 --- a/common/treemodel.h +++ b/common/treemodel.h @@ -14,6 +14,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #ifndef TREEMODEL_H #define TREEMODEL_H +enum ItemFixedState { + Movable, + Fixed +}; + #if defined(QT_CORE_LIB) // Use Qt classes #include @@ -88,7 +93,7 @@ public: QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; TreeModel(QObject *parent = 0) : QAbstractItemModel(parent) { - rootItem = new TreeItem(Types::Root, 0, UString(), UString(), UString(), UByteArray(), UByteArray(), UByteArray(), TRUE, FALSE, UByteArray()); + rootItem = new TreeItem(0, Types::Root, 0, UString(), UString(), UString(), UByteArray(), UByteArray(), UByteArray(), TRUE, FALSE); } #else @@ -107,7 +112,7 @@ public: UString headerData(int section, int orientation, int role = 0) const; TreeModel() { - rootItem = new TreeItem(Types::Root, 0, UString(), UString(), UString(), UByteArray(), UByteArray(), UByteArray(), TRUE, FALSE, UByteArray()); + rootItem = new TreeItem(0, Types::Root, 0, UString(), UString(), UString(), UByteArray(), UByteArray(), UByteArray(), TRUE, FALSE); } bool hasIndex(int row, int column, const UModelIndex &parent = UModelIndex()) const { @@ -131,37 +136,41 @@ public: int columnCount(const UModelIndex &parent = UModelIndex()) const; void setAction(const UModelIndex &index, const UINT8 action); + void setOffset(const UModelIndex &index, const UINT32 offset); void setType(const UModelIndex &index, const UINT8 type); void setSubtype(const UModelIndex &index, const UINT8 subtype); void setName(const UModelIndex &index, const UString &name); void setText(const UModelIndex &index, const UString &text); void setInfo(const UModelIndex &index, const UString &info); void addInfo(const UModelIndex &index, const UString &info, const bool append = TRUE); - void setParsingData(const UModelIndex &index, const UByteArray &data); void setFixed(const UModelIndex &index, const bool fixed); void setCompressed(const UModelIndex &index, const bool compressed); + UINT32 offset(const UModelIndex &index) const; + UINT8 type(const UModelIndex &index) const; + UINT8 subtype(const UModelIndex &index) const; UString name(const UModelIndex &index) const; UString text(const UModelIndex &index) const; UString info(const UModelIndex &index) const; - UINT8 type(const UModelIndex &index) const; - UINT8 subtype(const UModelIndex &index) const; UByteArray header(const UModelIndex &index) const; bool hasEmptyHeader(const UModelIndex &index) const; UByteArray body(const UModelIndex &index) const; bool hasEmptyBody(const UModelIndex &index) const; UByteArray tail(const UModelIndex &index) const; bool hasEmptyTail(const UModelIndex &index) const; - UByteArray parsingData(const UModelIndex &index) const; - bool hasEmptyParsingData(const UModelIndex &index) const; - UINT8 action(const UModelIndex &index) const; bool fixed(const UModelIndex &index) const; bool compressed(const UModelIndex &index) const; - UModelIndex addItem(const UINT8 type, const UINT8 subtype, + UINT8 action(const UModelIndex &index) const; + + UByteArray parsingData(const UModelIndex &index) const; + bool hasEmptyParsingData(const UModelIndex &index) const; + void setParsingData(const UModelIndex &index, const UByteArray &pdata); + + UModelIndex addItem(const UINT32 offset, const UINT8 type, const UINT8 subtype, const UString & name, const UString & text, const UString & info, const UByteArray & header, const UByteArray & body, const UByteArray & tail, - const bool fixed, const UByteArray & parsingData = UByteArray(), + const ItemFixedState fixed, const UModelIndex & parent = UModelIndex(), const UINT8 mode = CREATE_MODE_APPEND); UModelIndex findParentOfType(const UModelIndex & index, UINT8 type) const; diff --git a/common/utility.cpp b/common/utility.cpp index 9b9e4dd..175ee14 100644 --- a/common/utility.cpp +++ b/common/utility.cpp @@ -19,31 +19,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "LZMA/LzmaCompress.h" #include "LZMA/LzmaDecompress.h" -// Returns either new parsing data instance or obtains it from index -PARSING_DATA parsingDataFromUModelIndex(const UModelIndex & index) -{ - if (index.isValid()) { - TreeModel* model = (TreeModel*)index.model(); - if (!model->hasEmptyParsingData(index)) - return *(PARSING_DATA*)model->parsingData(index).data(); - } - - PARSING_DATA data; - data.offset = 0; - data.address = 0; - data.ffsVersion = 0; // Unknown by default - data.emptyByte = 0xFF; // Default value for SPI flash - - // Type-specific parts remain unitialized - return data; -} - -// Converts parsing data to byte array -UByteArray parsingDataToUByteArray(const PARSING_DATA & pdata) -{ - return UByteArray((const char*)&pdata, sizeof(PARSING_DATA)); -} - // Returns unique name string based for tree item UString uniqueItemName(const UModelIndex & index) { @@ -53,9 +28,6 @@ UString uniqueItemName(const UModelIndex & index) // Get model from index const TreeModel* model = (const TreeModel*)index.model(); - - // Get data from parsing data - PARSING_DATA pdata = parsingDataFromUModelIndex(index); // Construct the name UString itemName = model->name(index); @@ -64,9 +36,19 @@ UString uniqueItemName(const UModelIndex & index) // Default name UString name = itemName; switch (model->type(index)) { - case Types::Volume: - if (pdata.volume.hasExtendedHeader) name = guidToUString(pdata.volume.extendedHeaderGuid); - break; + case Types::Volume: { + UINT8 hasExtendedHeader = FALSE; + EFI_GUID extendedHeaderGuid = { 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } }; + if (model->hasEmptyParsingData(index) == false) { + UByteArray data = model->parsingData(index); + const VOLUME_PARSING_DATA* pdata = (const VOLUME_PARSING_DATA*)data.constData(); + hasExtendedHeader = pdata->hasExtendedHeader; + extendedHeaderGuid = pdata->extendedHeaderGuid; + } + + if (hasExtendedHeader) + name = guidToUString(extendedHeaderGuid).replace('-', '_'); + } break; case Types::NvarEntry: case Types::VssEntry: case Types::FsysEntry: @@ -204,7 +186,7 @@ UINT32 crc32(UINT32 initial, const UINT8* buffer, const UINT32 length) } // Compression routines -USTATUS decompress(const UByteArray & compressedData, UINT8 & algorithm, UByteArray & decompressedData, UByteArray & efiDecompressedData) +USTATUS decompress(const UByteArray & compressedData, const UINT8 compressionType, UINT8 & algorithm, UByteArray & decompressedData, UByteArray & efiDecompressedData) { const UINT8* data; UINT32 dataSize; @@ -215,7 +197,7 @@ USTATUS decompress(const UByteArray & compressedData, UINT8 & algorithm, UByteAr UINT32 scratchSize = 0; const EFI_TIANO_HEADER* header; - switch (algorithm) + switch (compressionType) { case EFI_NOT_COMPRESSED: decompressedData = compressedData; diff --git a/common/utility.h b/common/utility.h index 18e1e96..6c15b72 100644 --- a/common/utility.h +++ b/common/utility.h @@ -19,12 +19,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "treemodel.h" #include "parsingdata.h" -// Returns either new parsing data instance or obtains it from index -PARSING_DATA parsingDataFromUModelIndex(const UModelIndex & index); - -// Converts parsing data to byte array -UByteArray parsingDataToUByteArray(const PARSING_DATA & pdata); - // Returns unique name string based for tree item UString uniqueItemName(const UModelIndex & index); @@ -32,7 +26,7 @@ UString uniqueItemName(const UModelIndex & index); UString errorCodeToUString(UINT8 errorCode); // Decompression routine -USTATUS decompress(const UByteArray & compressed, UINT8 & algorithm, UByteArray & decompressed, UByteArray & efiDecompressed); +USTATUS decompress(const UByteArray & compressed, const UINT8 compressionType, UINT8 & algorithm, UByteArray & decompressed, UByteArray & efiDecompressed); // Compression routine //USTATUS compress(const UByteArray & decompressed, UByteArray & compressed, const UINT8 & algorithm);