diff --git a/UEFITool/gotoaddressdialog.ui b/UEFITool/gotoaddressdialog.ui index d813a6b..8531019 100644 --- a/UEFITool/gotoaddressdialog.ui +++ b/UEFITool/gotoaddressdialog.ui @@ -7,11 +7,11 @@ 0 0 270 - 70 + 86 - Go to address + Select item at address false @@ -56,7 +56,7 @@ - Select tree item at address: + Select item at address: diff --git a/UEFITool/gotobasedialog.h b/UEFITool/gotobasedialog.h new file mode 100644 index 0000000..8023e86 --- /dev/null +++ b/UEFITool/gotobasedialog.h @@ -0,0 +1,23 @@ +#ifndef GOTOBASEDIALOG_H +#define GOTOBASEDIALOG_H + +#include +#include +#include "ui_gotobasedialog.h" +class GoToBaseDialog : public QDialog +{ + Q_OBJECT + +public: + GoToBaseDialog(QWidget* parent = NULL): + QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint), + ui(new Ui::GoToBaseDialog) { + ui->setupUi(this); + } + + ~GoToBaseDialog() {delete ui;} + + Ui::GoToBaseDialog* ui; +}; + +#endif // GOTOBASEDIALOG_H diff --git a/UEFITool/gotooffsetdialog.ui b/UEFITool/gotobasedialog.ui similarity index 91% rename from UEFITool/gotooffsetdialog.ui rename to UEFITool/gotobasedialog.ui index daeff14..0572b1a 100644 --- a/UEFITool/gotooffsetdialog.ui +++ b/UEFITool/gotobasedialog.ui @@ -1,17 +1,17 @@ - GoToOffsetDialog - + GoToBaseDialog + 0 0 270 - 70 + 86 - Go to offset + Select item at base false @@ -56,7 +56,7 @@ - Select tree item at offset: + Select item at base: @@ -100,7 +100,7 @@ buttonBox accepted() - GoToOffsetDialog + GoToBaseDialog accept() @@ -116,7 +116,7 @@ buttonBox rejected() - GoToOffsetDialog + GoToBaseDialog reject() diff --git a/UEFITool/gotooffsetdialog.h b/UEFITool/gotooffsetdialog.h deleted file mode 100644 index ce2b1dd..0000000 --- a/UEFITool/gotooffsetdialog.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef GOTOOFFSETDIALOG_H -#define GOTOOFFSETDIALOG_H - -#include -#include -#include "ui_gotooffsetdialog.h" -class GoToOffsetDialog : public QDialog -{ - Q_OBJECT - -public: - GoToOffsetDialog(QWidget* parent = NULL): - QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint), - ui(new Ui::GoToOffsetDialog) { - ui->setupUi(this); - } - - ~GoToOffsetDialog() {delete ui;} - - Ui::GoToOffsetDialog* ui; -}; - -#endif // GOTOOFFSETDIALOG_H diff --git a/UEFITool/uefitool.cpp b/UEFITool/uefitool.cpp index 5acbc80..23cb60d 100644 --- a/UEFITool/uefitool.cpp +++ b/UEFITool/uefitool.cpp @@ -27,8 +27,8 @@ markingEnabled(true) ui->setupUi(this); searchDialog = new SearchDialog(this); hexViewDialog = new HexViewDialog(this); - goToOffsetDialog = new GoToOffsetDialog(this); goToAddressDialog = new GoToAddressDialog(this); + goToBaseDialog = new GoToBaseDialog(this); model = NULL; ffsParser = NULL; ffsFinder = NULL; @@ -60,7 +60,7 @@ markingEnabled(true) connect(ui->actionAboutQt, SIGNAL(triggered()), this, SLOT(aboutQt())); connect(ui->actionQuit, SIGNAL(triggered()), this, SLOT(exit())); connect(ui->actionGoToData, SIGNAL(triggered()), this, SLOT(goToData())); - connect(ui->actionGoToOffset, SIGNAL(triggered()), this, SLOT(goToOffset())); + connect(ui->actionGoToBase, SIGNAL(triggered()), this, SLOT(goToBase())); connect(ui->actionGoToAddress, SIGNAL(triggered()), this, SLOT(goToAddress())); connect(ui->actionLoadGuidDatabase, SIGNAL(triggered()), this, SLOT(loadGuidDatabase())); connect(ui->actionUnloadGuidDatabase, SIGNAL(triggered()), this, SLOT(unloadGuidDatabase())); @@ -121,7 +121,7 @@ void UEFITool::init() // Disable menus ui->actionSearch->setEnabled(false); - ui->actionGoToOffset->setEnabled(false); + ui->actionGoToBase->setEnabled(false); ui->actionGoToAddress->setEnabled(false); ui->menuCapsuleActions->setEnabled(false); ui->menuImageActions->setEnabled(false); @@ -316,15 +316,15 @@ void UEFITool::bodyHexView() hexViewDialog->exec(); } -void UEFITool::goToOffset() +void UEFITool::goToBase() { - goToOffsetDialog->ui->hexSpinBox->setFocus(); - goToOffsetDialog->ui->hexSpinBox->selectAll(); - if (goToOffsetDialog->exec() != QDialog::Accepted) + goToBaseDialog->ui->hexSpinBox->setFocus(); + goToBaseDialog->ui->hexSpinBox->selectAll(); + if (goToBaseDialog->exec() != QDialog::Accepted) return; - UINT32 offset = (UINT32)goToOffsetDialog->ui->hexSpinBox->value(); - QModelIndex index = model->findByOffset(offset); + UINT32 offset = (UINT32)goToBaseDialog->ui->hexSpinBox->value(); + QModelIndex index = model->findByBase(offset); if (index.isValid()) { ui->structureTreeView->scrollTo(index, QAbstractItemView::PositionAtCenter); ui->structureTreeView->selectionModel()->select(index, QItemSelectionModel::Select | QItemSelectionModel::Rows | QItemSelectionModel::Clear); @@ -339,7 +339,7 @@ void UEFITool::goToAddress() return; UINT32 address = (UINT32)goToAddressDialog->ui->hexSpinBox->value(); - QModelIndex index = model->findByOffset(address - (UINT32)ffsParser->getAddressDiff()); + QModelIndex index = model->findByBase(address - (UINT32)ffsParser->getAddressDiff()); if (index.isValid()) { ui->structureTreeView->scrollTo(index, QAbstractItemView::PositionAtCenter); ui->structureTreeView->selectionModel()->select(index, QItemSelectionModel::Select | QItemSelectionModel::Rows | QItemSelectionModel::Clear); @@ -646,9 +646,9 @@ void UEFITool::openImageFile(QString path) delete ffsReport; ffsReport = new FfsReport(model); - // Enable goToOffset and goToAddress - ui->actionGoToOffset->setEnabled(true); - if (ffsParser->getAddressDiff() < 0xFFFFFFFFUL) + // Enable goToBase and goToAddress + ui->actionGoToBase->setEnabled(true); + if (ffsParser->getAddressDiff() <= 0xFFFFFFFFUL) ui->actionGoToAddress->setEnabled(true); // Enable generateReport @@ -673,7 +673,7 @@ void UEFITool::copyMessage() { clipboard->clear(); if (ui->messagesTabWidget->currentIndex() == TAB_PARSER) // Parser tab - clipboard->setText(ui->parserMessagesListWidget->currentItem()->text()); + clipboard->setText(ui->parserMessagesListWidget->currentItem()->text()); else if (ui->messagesTabWidget->currentIndex() == TAB_SEARCH) // Search tab clipboard->setText(ui->finderMessagesListWidget->currentItem()->text()); else if (ui->messagesTabWidget->currentIndex() == TAB_BUILDER) // Builder tab @@ -903,8 +903,8 @@ void UEFITool::readSettings() searchDialog->ui->guidEdit->setFont(currentFont); searchDialog->ui->hexEdit->setFont(currentFont); hexViewDialog->setFont(currentFont); - goToOffsetDialog->ui->hexSpinBox->setFont(currentFont); goToAddressDialog->ui->hexSpinBox->setFont(currentFont); + goToBaseDialog->ui->hexSpinBox->setFont(currentFont); } void UEFITool::writeSettings() diff --git a/UEFITool/uefitool.h b/UEFITool/uefitool.h index 8410d14..74a70c9 100644 --- a/UEFITool/uefitool.h +++ b/UEFITool/uefitool.h @@ -46,7 +46,7 @@ #include "../common/guiddatabase.h" #include "searchdialog.h" -#include "gotooffsetdialog.h" +#include "gotobasedialog.h" #include "gotoaddressdialog.h" #include "hexviewdialog.h" #include "ffsfinder.h" @@ -78,7 +78,7 @@ private slots: void saveImageFile(); void search(); - void goToOffset(); + void goToBase(); void goToAddress(); void hexView(); @@ -133,7 +133,7 @@ private: FfsBuilder* ffsBuilder; SearchDialog* searchDialog; HexViewDialog* hexViewDialog; - GoToOffsetDialog* goToOffsetDialog; + GoToBaseDialog* goToBaseDialog; GoToAddressDialog* goToAddressDialog; QClipboard* clipboard; QString currentDir; diff --git a/UEFITool/uefitool.pro b/UEFITool/uefitool.pro index a370b6e..6f19476 100644 --- a/UEFITool/uefitool.pro +++ b/UEFITool/uefitool.pro @@ -10,7 +10,7 @@ DEFINES += "U_ENABLE_GUID_DATABASE_SUPPORT" HEADERS += uefitool.h \ searchdialog.h \ hexviewdialog.h \ - gotooffsetdialog.h \ + gotobasedialog.h \ gotoaddressdialog.h \ guidlineedit.h \ ffsfinder.h \ @@ -112,7 +112,7 @@ SOURCES += uefitool_main.cpp \ FORMS += uefitool.ui \ searchdialog.ui \ hexviewdialog.ui \ - gotooffsetdialog.ui \ + gotobasedialog.ui \ gotoaddressdialog.ui RESOURCES += uefitool.qrc diff --git a/UEFITool/uefitool.ui b/UEFITool/uefitool.ui index dbfe6b3..50a5252 100644 --- a/UEFITool/uefitool.ui +++ b/UEFITool/uefitool.ui @@ -519,7 +519,7 @@ - + @@ -822,12 +822,12 @@ Ctrl+D - + false - &Go to offset... + &Select item at base... Ctrl+G @@ -857,7 +857,7 @@ false - Go to &address... + Select item at &address... Ctrl+Shift+G diff --git a/common/ffsparser.cpp b/common/ffsparser.cpp index 44a0700..eb4386b 100644 --- a/common/ffsparser.cpp +++ b/common/ffsparser.cpp @@ -86,7 +86,7 @@ USTATUS FfsParser::parse(const UByteArray & buffer) // Reset global parser state openedImage = buffer; imageBase = 0; - addressDiff = 0x10000000ULL; + addressDiff = 0x100000000ULL; bgAcmFound = false; bgKeyManifestFound = false; bgBootPolicyFound = false; @@ -105,18 +105,16 @@ USTATUS FfsParser::parse(const UByteArray & buffer) // Parse input buffer USTATUS result = performFirstPass(buffer, root); - addOffsetsRecursive(root); - if (result) { - return result; + if (result == U_SUCCESS) { + if (lastVtf.isValid()) { + result = performSecondPass(root); + } + else { + msg(usprintf("%s: not a single Volume Top File is found, the image may be corrupted", __FUNCTION__)); + } } - if (lastVtf.isValid()) { - result = performSecondPass(root); - } - else { - msg(usprintf("%s: not a single Volume Top File is found, the image may be corrupted", __FUNCTION__)); - } - + addInfoRecursive(root); return result; } @@ -152,10 +150,10 @@ USTATUS FfsParser::parseGenericImage(const UByteArray & buffer, const UINT32 loc UString info = usprintf("Full size: %Xh (%u)", buffer.size(), buffer.size()); // Add tree item - index = model->addItem(model->offset(parent) + localOffset, Types::Image, Subtypes::UefiImage, name, UString(), info, UByteArray(), buffer, UByteArray(), Fixed, parent); + index = model->addItem(localOffset, Types::Image, Subtypes::UefiImage, name, UString(), info, UByteArray(), buffer, UByteArray(), Fixed, parent); // Parse the image as raw area - bgProtectedRegionsBase = imageBase = model->offset(parent) + localOffset; + bgProtectedRegionsBase = imageBase = model->base(parent) + localOffset; return parseRawArea(index); } @@ -202,7 +200,7 @@ USTATUS FfsParser::parseCapsule(const UByteArray & capsule, const UINT32 localOf capsuleHeader->Flags); // Add tree item - index = model->addItem(model->offset(parent) + localOffset, Types::Capsule, Subtypes::UefiCapsule, name, UString(), info, header, body, UByteArray(), Fixed, parent); + index = model->addItem(localOffset, Types::Capsule, Subtypes::UefiCapsule, name, UString(), info, header, body, UByteArray(), Fixed, parent); } // Check buffer for being Toshiba capsule header else if (capsule.startsWith(TOSHIBA_CAPSULE_GUID)) { @@ -234,7 +232,7 @@ USTATUS FfsParser::parseCapsule(const UByteArray & capsule, const UINT32 localOf capsuleHeader->Flags); // Add tree item - index = model->addItem(model->offset(parent) + localOffset, Types::Capsule, Subtypes::ToshibaCapsule, name, UString(), info, header, body, UByteArray(), Fixed, parent); + index = model->addItem(localOffset, Types::Capsule, Subtypes::ToshibaCapsule, name, UString(), info, header, body, UByteArray(), Fixed, parent); } // Check buffer for being extended Aptio capsule header else if (capsule.startsWith(APTIO_SIGNED_CAPSULE_GUID) @@ -275,7 +273,7 @@ USTATUS FfsParser::parseCapsule(const UByteArray & capsule, const UINT32 localOf capsuleHeader->CapsuleHeader.Flags); // Add tree item - index = model->addItem(model->offset(parent) + localOffset, Types::Capsule, signedCapsule ? Subtypes::AptioSignedCapsule : Subtypes::AptioUnsignedCapsule, name, UString(), info, header, body, UByteArray(), Fixed, parent); + index = model->addItem(localOffset, Types::Capsule, signedCapsule ? Subtypes::AptioSignedCapsule : Subtypes::AptioUnsignedCapsule, name, UString(), info, header, body, UByteArray(), Fixed, parent); // Show message about possible Aptio signature break if (signedCapsule) { @@ -481,10 +479,10 @@ USTATUS FfsParser::parseIntelImage(const UByteArray & intelImage, const UINT32 l descriptorMap->NumberOfProcStraps); // Set image base - imageBase = model->offset(parent) + localOffset; + imageBase = model->base(parent) + localOffset; // Add Intel image tree item - index = model->addItem(model->offset(parent) + localOffset, Types::Image, Subtypes::IntelImage, name, UString(), info, UByteArray(), intelImage, UByteArray(), Fixed, parent); + index = model->addItem(localOffset, Types::Image, Subtypes::IntelImage, name, UString(), info, UByteArray(), intelImage, UByteArray(), Fixed, parent); // Descriptor // Get descriptor info @@ -592,7 +590,7 @@ USTATUS FfsParser::parseIntelImage(const UByteArray & intelImage, const UINT32 l } // Add descriptor tree item - UModelIndex regionIndex = model->addItem(model->offset(parent) + localOffset, Types::Region, Subtypes::DescriptorRegion, name, UString(), info, UByteArray(), body, UByteArray(), Fixed, index); + UModelIndex regionIndex = model->addItem(localOffset, Types::Region, Subtypes::DescriptorRegion, name, UString(), info, UByteArray(), body, UByteArray(), Fixed, index); // Parse regions @@ -638,7 +636,7 @@ USTATUS FfsParser::parseIntelImage(const UByteArray & intelImage, const UINT32 l padding.size(), padding.size()); // Add tree item - regionIndex = model->addItem(model->offset(parent) + region.offset, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); + regionIndex = model->addItem(region.offset, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); result = U_SUCCESS; } break; default: @@ -674,7 +672,7 @@ USTATUS FfsParser::parseGbeRegion(const UByteArray & gbe, const UINT32 localOffs version->minor); // Add tree item - index = model->addItem(model->offset(parent) + localOffset, Types::Region, Subtypes::GbeRegion, name, UString(), info, UByteArray(), gbe, UByteArray(), Fixed, parent); + index = model->addItem(localOffset, Types::Region, Subtypes::GbeRegion, name, UString(), info, UByteArray(), gbe, UByteArray(), Fixed, parent); return U_SUCCESS; } @@ -726,7 +724,7 @@ USTATUS FfsParser::parseMeRegion(const UByteArray & me, const UINT32 localOffset } // Add tree item - index = model->addItem(model->offset(parent) + localOffset, Types::Region, Subtypes::MeRegion, name, UString(), info, UByteArray(), me, UByteArray(), Fixed, parent); + index = model->addItem(localOffset, Types::Region, Subtypes::MeRegion, name, UString(), info, UByteArray(), me, UByteArray(), Fixed, parent); // Show messages if (emptyRegion) { @@ -753,7 +751,7 @@ USTATUS FfsParser::parsePdrRegion(const UByteArray & pdr, const UINT32 localOffs UString info = usprintf("Full size: %Xh (%u)", pdr.size(), pdr.size()); // Add tree item - index = model->addItem(model->offset(parent) + localOffset, Types::Region, Subtypes::PdrRegion, name, UString(), info, UByteArray(), pdr, UByteArray(), Fixed, parent); + index = model->addItem(localOffset, Types::Region, Subtypes::PdrRegion, name, UString(), info, UByteArray(), pdr, UByteArray(), Fixed, parent); // Parse PDR region as BIOS space USTATUS result = parseRawArea(index); @@ -774,7 +772,7 @@ USTATUS FfsParser::parseGenericRegion(const UINT8 subtype, const UByteArray & re UString info = usprintf("Full size: %Xh (%u)", region.size(), region.size()); // Add tree item - index = model->addItem(model->offset(parent) + localOffset, Types::Region, subtype, name, UString(), info, UByteArray(), region, UByteArray(), Fixed, parent); + index = model->addItem(localOffset, Types::Region, subtype, name, UString(), info, UByteArray(), region, UByteArray(), Fixed, parent); return U_SUCCESS; } @@ -790,7 +788,7 @@ USTATUS FfsParser::parseBiosRegion(const UByteArray & bios, const UINT32 localOf UString info = usprintf("Full size: %Xh (%u)", bios.size(), bios.size()); // Add tree item - index = model->addItem(model->offset(parent) + localOffset, Types::Region, Subtypes::BiosRegion, name, UString(), info, UByteArray(), bios, UByteArray(), Fixed, parent); + index = model->addItem(localOffset, Types::Region, Subtypes::BiosRegion, name, UString(), info, UByteArray(), bios, UByteArray(), Fixed, parent); return parseRawArea(index); } @@ -804,7 +802,6 @@ USTATUS FfsParser::parseRawArea(const UModelIndex & index) // Get item data UByteArray data = model->body(index); UINT32 headerSize = model->header(index).size(); - UINT32 offset = model->offset(index) + headerSize; USTATUS result; UString name; @@ -824,8 +821,9 @@ USTATUS FfsParser::parseRawArea(const UModelIndex & index) // Set base of protected regions to be the first volume if (model->type(index) == Types::Region - && model->subtype(index) == Subtypes::BiosRegion) - bgProtectedRegionsBase = (UINT64)model->offset(index) + prevItemOffset; + && model->subtype(index) == Subtypes::BiosRegion) { + bgProtectedRegionsBase = (UINT64)model->base(index) + prevItemOffset; + } // First item is not at the beginning of this raw area if (prevItemOffset > 0) { @@ -835,7 +833,7 @@ USTATUS FfsParser::parseRawArea(const UModelIndex & index) info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size()); // Add tree item - model->addItem(offset, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); + model->addItem(headerSize, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); } // Search for and parse all items @@ -856,7 +854,7 @@ USTATUS FfsParser::parseRawArea(const UModelIndex & index) info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size()); // Add tree item - model->addItem(offset + paddingOffset, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); + model->addItem(headerSize + paddingOffset, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); } // Check that item is fully present in input @@ -869,7 +867,7 @@ USTATUS FfsParser::parseRawArea(const UModelIndex & index) info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size()); // Add tree item - UModelIndex paddingIndex = model->addItem(offset + itemOffset, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); + UModelIndex paddingIndex = model->addItem(headerSize + itemOffset, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); msg(usprintf("%s: one of volumes inside overlaps the end of data", __FUNCTION__), paddingIndex); // Update variables @@ -925,7 +923,7 @@ USTATUS FfsParser::parseRawArea(const UModelIndex & index) info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size()); // Add tree item - model->addItem(offset + itemOffset, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); + model->addItem(headerSize + itemOffset, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); } // Parse bodies @@ -1041,7 +1039,7 @@ USTATUS FfsParser::parseVolumeHeader(const UByteArray & volume, const UINT32 loc // Acquire alignment alignment = (UINT32)(1UL << ((volumeHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16)); // Check alignment - if (!isUnknown && !model->compressed(parent) && ((model->offset(parent) + localOffset - imageBase) % alignment)) + if (!isUnknown && !model->compressed(parent) && ((model->base(parent) + localOffset - imageBase) % alignment)) msgUnaligned = true; } else { @@ -1119,7 +1117,7 @@ USTATUS FfsParser::parseVolumeHeader(const UByteArray & volume, const UINT32 loc else if (isMicrocodeVolume) subtype = Subtypes::MicrocodeVolume; } - index = model->addItem(model->offset(parent) + localOffset, Types::Volume, subtype, name, text, info, header, body, UByteArray(), Fixed, parent); + index = model->addItem(localOffset, Types::Volume, subtype, name, text, info, header, body, UByteArray(), Movable, parent); // Set parsing data for created volume VOLUME_PARSING_DATA pdata; @@ -1238,7 +1236,7 @@ USTATUS FfsParser::parseVolumeNonUefiData(const UByteArray & data, const UINT32 UString info = usprintf("Full size: %Xh (%u)", data.size(), data.size()); // Add padding tree item - UModelIndex paddingIndex = model->addItem(model->offset(index) + localOffset, Types::Padding, Subtypes::DataPadding, UString("Non-UEFI data"), UString(), info, UByteArray(), data, UByteArray(), Fixed, index); + UModelIndex paddingIndex = model->addItem(localOffset, Types::Padding, Subtypes::DataPadding, UString("Non-UEFI data"), UString(), info, UByteArray(), data, UByteArray(), Fixed, index); msg(usprintf("%s: non-UEFI data found in volume's free space", __FUNCTION__), paddingIndex); // Parse contents as RAW area @@ -1326,7 +1324,7 @@ USTATUS FfsParser::parseVolumeBody(const UModelIndex & index) UString info = usprintf("Full size: %Xh (%u)", free.size(), free.size()); // Add free space item - model->addItem(model->offset(index) + volumeHeaderSize + fileOffset, Types::FreeSpace, 0, UString("Volume free space"), UString(), info, UByteArray(), free, UByteArray(), Movable, index); + model->addItem(volumeHeaderSize + fileOffset, Types::FreeSpace, 0, UString("Volume free space"), UString(), info, UByteArray(), free, UByteArray(), Movable, index); } // Parse non-UEFI data @@ -1337,7 +1335,7 @@ USTATUS FfsParser::parseVolumeBody(const UModelIndex & index) UString info = usprintf("Full size: %Xh (%u)", freeSpace.size(), freeSpace.size()); // Add free space item - model->addItem(model->offset(index) + volumeHeaderSize + fileOffset, Types::FreeSpace, 0, UString("Volume free space"), UString(), info, UByteArray(), freeSpace, UByteArray(), Movable, index); + model->addItem(volumeHeaderSize + fileOffset, Types::FreeSpace, 0, UString("Volume free space"), UString(), info, UByteArray(), freeSpace, UByteArray(), Movable, index); } break; // Exit from parsing loop } @@ -1580,7 +1578,7 @@ USTATUS FfsParser::parseFileHeader(const UByteArray & file, const UINT32 localOf ItemFixedState fixed = (ItemFixedState)((fileHeader->Attributes & FFS_ATTRIB_FIXED) != 0); // Add tree item - index = model->addItem(model->offset(parent) + localOffset, Types::File, fileHeader->Type, name, text, info, header, body, tail, fixed, parent); + index = model->addItem(localOffset, Types::File, fileHeader->Type, name, text, info, header, body, tail, fixed, parent); // Set parsing data for created file FILE_PARSING_DATA pdata; @@ -1706,6 +1704,7 @@ USTATUS FfsParser::parsePadFileBody(const UModelIndex & index) } // Add all bytes before as free space... + UINT32 headerSize = model->header(index).size(); if (nonEmptyByteOffset >= 8) { // Align free space to 8 bytes boundary if (nonEmptyByteOffset != ALIGN8(nonEmptyByteOffset)) @@ -1717,7 +1716,7 @@ USTATUS FfsParser::parsePadFileBody(const UModelIndex & index) UString info = usprintf("Full size: %Xh (%u)", free.size(), free.size()); // Add tree item - model->addItem(model->offset(index) + model->header(index).size(), Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), free, UByteArray(), Movable, index); + model->addItem(headerSize, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), free, UByteArray(), Movable, index); } else { nonEmptyByteOffset = 0; @@ -1730,7 +1729,7 @@ USTATUS FfsParser::parsePadFileBody(const UModelIndex & index) UString info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size()); // Add tree item - UModelIndex dataIndex = model->addItem(model->offset(index) + model->header(index).size() + nonEmptyByteOffset, Types::Padding, Subtypes::DataPadding, UString("Non-UEFI data"), UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); + UModelIndex dataIndex = model->addItem(headerSize + nonEmptyByteOffset, Types::Padding, Subtypes::DataPadding, UString("Non-UEFI data"), UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); // Show message msg(usprintf("%s: non-UEFI data found in pad-file", __FUNCTION__), dataIndex); @@ -1778,7 +1777,7 @@ USTATUS FfsParser::parseSections(const UByteArray & sections, const UModelIndex UString info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size()); // Add tree item - UModelIndex dataIndex = model->addItem(model->offset(index) + headerSize + sectionOffset, Types::Padding, Subtypes::DataPadding, UString("Non-UEFI data"), UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); + UModelIndex dataIndex = model->addItem(headerSize + sectionOffset, Types::Padding, Subtypes::DataPadding, UString("Non-UEFI data"), UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); // Show message msg(usprintf("%s: non-UEFI data found in sections area", __FUNCTION__), dataIndex); @@ -1911,7 +1910,7 @@ USTATUS FfsParser::parseCommonSectionHeader(const UByteArray & section, const UI // Add tree item if (insertIntoTree) { - index = model->addItem(model->offset(parent) + localOffset, Types::Section, type, name, UString(), info, header, body, UByteArray(), Movable, parent); + index = model->addItem(localOffset, Types::Section, type, name, UString(), info, header, body, UByteArray(), Movable, parent); } return U_SUCCESS; @@ -1981,7 +1980,7 @@ USTATUS FfsParser::parseCompressedSectionHeader(const UByteArray & section, cons // Add tree item if (insertIntoTree) { - index = model->addItem(model->offset(parent) + localOffset, Types::Section, sectionHeader->Type, name, UString(), info, header, body, UByteArray(), Movable, parent); + index = model->addItem(localOffset, Types::Section, sectionHeader->Type, name, UString(), info, header, body, UByteArray(), Movable, parent); // Set section parsing data COMPRESSED_SECTION_PARSING_DATA pdata; @@ -2164,7 +2163,7 @@ USTATUS FfsParser::parseGuidedSectionHeader(const UByteArray & section, const UI // Add tree item if (insertIntoTree) { - index = model->addItem(model->offset(parent) + localOffset, Types::Section, sectionHeader->Type, name, UString(), info, header, body, UByteArray(), Movable, parent); + index = model->addItem(localOffset, Types::Section, sectionHeader->Type, name, UString(), info, header, body, UByteArray(), Movable, parent); // Set parsing data GUIDED_SECTION_PARSING_DATA pdata; @@ -2255,7 +2254,7 @@ USTATUS FfsParser::parseFreeformGuidedSectionHeader(const UByteArray & section, // Add tree item if (insertIntoTree) { - index = model->addItem(model->offset(parent) + localOffset, Types::Section, type, name, UString(), info, header, body, UByteArray(), Movable, parent); + index = model->addItem(localOffset, Types::Section, type, name, UString(), info, header, body, UByteArray(), Movable, parent); // Set parsing data FREEFORM_GUIDED_SECTION_PARSING_DATA pdata; @@ -2329,7 +2328,7 @@ USTATUS FfsParser::parseVersionSectionHeader(const UByteArray & section, const U // Add tree item if (insertIntoTree) { - index = model->addItem(model->offset(parent) + localOffset, Types::Section, type, name, UString(), info, header, body, UByteArray(), Movable, parent); + index = model->addItem(localOffset, Types::Section, type, name, UString(), info, header, body, UByteArray(), Movable, parent); } return U_SUCCESS; @@ -2395,7 +2394,7 @@ USTATUS FfsParser::parsePostcodeSectionHeader(const UByteArray & section, const // Add tree item if (insertIntoTree) { - index = model->addItem(model->offset(parent) + localOffset, Types::Section, sectionHeader->Type, name, UString(), info, header, body, UByteArray(), Movable, parent); + index = model->addItem(localOffset, Types::Section, sectionHeader->Type, name, UString(), info, header, body, UByteArray(), Movable, parent); } return U_SUCCESS; @@ -2985,7 +2984,7 @@ USTATUS FfsParser::performSecondPass(const UModelIndex & index) // Calculate address difference const UINT32 vtfSize = model->header(lastVtf).size() + model->body(lastVtf).size() + model->tail(lastVtf).size(); - addressDiff = 0xFFFFFFFFULL - model->offset(lastVtf) - vtfSize + 1; + addressDiff = 0xFFFFFFFFULL - model->base(lastVtf) - vtfSize + 1; // Find and parse FIT parseFit(index); @@ -2993,128 +2992,111 @@ USTATUS FfsParser::performSecondPass(const UModelIndex & index) // Check protected ranges checkProtectedRanges(index); - // Apply address information to index and all it's child items - addMemoryAddressesRecursive(index); - - // Add fixed and compressed - addFixedAndCompressedRecursive(index); + // Check TE files to have original or adjusted base + checkTeImageBase(index); return U_SUCCESS; } -USTATUS FfsParser::addMemoryAddressesRecursive(const UModelIndex & index) +USTATUS FfsParser::checkTeImageBase(const UModelIndex & index) { // Sanity check if (!index.isValid()) return U_SUCCESS; - // Set address value for non-compressed data - if (!model->compressed(index)) { - // Check address sanity - UINT64 address = addressDiff + model->offset(index); - if (address <= 0xFFFFFFFFUL) { - // Update info - UINT32 headerSize = model->header(index).size(); - if (headerSize) { - model->addInfo(index, usprintf("\nHeader memory address: %08Xh", address)); - model->addInfo(index, usprintf("\nData memory address: %08Xh", address + headerSize)); + // Determine relocation type of uncompressed TE image sections + if (model->compressed(index) == false + && model->type(index) == Types::Section + && model->subtype(index) == EFI_SECTION_TE) { + // Obtain required values from parsing data + UINT32 originalImageBase = 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(); + originalImageBase = readUnaligned(pdata).imageBase; + adjustedImageBase = readUnaligned(pdata).adjustedImageBase; + } + + if (imageBase != 0) { + // Check data memory address to be equal to either ImageBase or AdjustedImageBase + UINT64 address = addressDiff + model->base(index); + UINT32 base = (UINT32)address + model->header(index).size(); + + if (imageBase == base) { + imageBaseType = EFI_IMAGE_TE_BASE_ORIGINAL; + } + else if (adjustedImageBase == base) { + imageBaseType = EFI_IMAGE_TE_BASE_ADJUSTED; } else { - model->addInfo(index, usprintf("\nMemory address: %08Xh", address)); - } - - // Determine relocation type of uncompressed TE image sections - if (model->type(index) == Types::Section && model->subtype(index) == EFI_SECTION_TE) { - // Obtain required values from parsing data - UINT32 originalImageBase = 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(); - originalImageBase = readUnaligned(pdata).imageBase; - adjustedImageBase = readUnaligned(pdata).adjustedImageBase; + // 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; } - - 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 if (adjustedImageBase == base) { + else { // The same check for adjustedImageBase + xored = base ^ adjustedImageBase; + if ((xored & (xored - 1)) == 0) { 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(usprintf("%s: TE image base is neither zero, nor original, nor adjusted, nor top-swapped", __FUNCTION__), index); - - // Update parsing data - TE_IMAGE_SECTION_PARSING_DATA pdata; - pdata.imageBaseType = imageBaseType; - pdata.imageBase = originalImageBase; - pdata.adjustedImageBase = adjustedImageBase; - model->setParsingData(index, UByteArray((const char*)&pdata, sizeof(pdata))); } } + + // Show message if imageBaseType is still unknown + if (imageBaseType == EFI_IMAGE_TE_BASE_OTHER) + msg(usprintf("%s: TE image base is neither zero, nor original, nor adjusted, nor top-swapped", __FUNCTION__), index); + + // Update parsing data + TE_IMAGE_SECTION_PARSING_DATA pdata; + pdata.imageBaseType = imageBaseType; + pdata.imageBase = originalImageBase; + pdata.adjustedImageBase = adjustedImageBase; + model->setParsingData(index, UByteArray((const char*)&pdata, sizeof(pdata))); } } // Process child items for (int i = 0; i < model->rowCount(index); i++) { - addMemoryAddressesRecursive(index.child(i, 0)); + checkTeImageBase(index.child(i, 0)); } return U_SUCCESS; } -USTATUS FfsParser::addOffsetsRecursive(const UModelIndex & index) +USTATUS FfsParser::addInfoRecursive(const UModelIndex & index) { // Sanity check if (!index.isValid()) return U_INVALID_PARAMETER; - // Add current offset if the element is not compressed + // Add offset + model->addInfo(index, usprintf("Offset: %Xh\n", model->offset(index)), false); + + // Add current base 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", model->offset(index)), false); + // Add physical address of the whole item or it's header and data portions separately + UINT64 address = addressDiff + model->base(index); + if (address <= 0xFFFFFFFFUL) { + UINT32 headerSize = model->header(index).size(); + if (headerSize) { + model->addInfo(index, usprintf("Data address: %08Xh\n", address + headerSize),false); + model->addInfo(index, usprintf("Header address: %08Xh\n", address), false); + } + else { + model->addInfo(index, usprintf("Address: %08Xh\n", address), false); + } + } + // Add base + model->addInfo(index, usprintf("Base: %Xh\n", model->base(index)), false); } + model->addInfo(index, usprintf("Fixed: %s\n", model->fixed(index) ? "Yes" : "No"), false); // Process child items for (int i = 0; i < model->rowCount(index); i++) { - addOffsetsRecursive(index.child(i, 0)); - } - - return U_SUCCESS; -} - -USTATUS FfsParser::addFixedAndCompressedRecursive(const UModelIndex & index) { - // Sanity check - if (!index.isValid()) - return U_INVALID_PARAMETER; - - // Add fixed and compressed info - model->addInfo(index, usprintf("\nCompressed: %s", model->compressed(index) ? "Yes" : "No")); - model->addInfo(index, usprintf("\nFixed: %s", model->fixed(index) ? "Yes" : "No")); - - // Process child items - for (int i = 0; i < model->rowCount(index); i++) { - addFixedAndCompressedRecursive(index.child(i, 0)); + addInfoRecursive(index.child(i, 0)); } return U_SUCCESS; @@ -3164,7 +3146,7 @@ USTATUS FfsParser::checkProtectedRanges(const UModelIndex & index) msg(usprintf("%s: can't determine DXE volume offset, old AMI protected range hash can't be checked", __FUNCTION__), index); } else { - bgProtectedRanges[i].Offset = model->offset(dxeRootVolumeIndex); + bgProtectedRanges[i].Offset = model->base(dxeRootVolumeIndex); protectedParts = openedImage.mid(bgProtectedRanges[i].Offset, bgProtectedRanges[i].Size); UByteArray digest(SHA256_DIGEST_SIZE, '\x00'); @@ -3173,7 +3155,7 @@ USTATUS FfsParser::checkProtectedRanges(const UModelIndex & index) if (digest != bgProtectedRanges[i].Hash) { msg(usprintf("%s: old AMI protected range [%Xh:%Xh] hash mismatch, opened image may refuse to boot", __FUNCTION__, bgProtectedRanges[i].Offset, bgProtectedRanges[i].Offset + bgProtectedRanges[i].Size), - model->findByOffset(bgProtectedRanges[i].Offset)); + model->findByBase(bgProtectedRanges[i].Offset)); } markProtectedRangeRecursive(index, bgProtectedRanges[i]); @@ -3192,7 +3174,7 @@ USTATUS FfsParser::checkProtectedRanges(const UModelIndex & index) } else { - bgProtectedRanges[i].Offset = model->offset(dxeRootVolumeIndex); + bgProtectedRanges[i].Offset = model->base(dxeRootVolumeIndex); bgProtectedRanges[i].Size = model->header(dxeRootVolumeIndex).size() + model->body(dxeRootVolumeIndex).size() + model->tail(dxeRootVolumeIndex).size(); protectedParts = openedImage.mid(bgProtectedRanges[i].Offset, bgProtectedRanges[i].Size); @@ -3202,7 +3184,7 @@ USTATUS FfsParser::checkProtectedRanges(const UModelIndex & index) if (digest != bgProtectedRanges[i].Hash) { msg(usprintf("%s: post-IBB protected range [%Xh:%Xh] hash mismatch, opened image may refuse to boot", __FUNCTION__, bgProtectedRanges[i].Offset, bgProtectedRanges[i].Offset + bgProtectedRanges[i].Size), - model->findByOffset(bgProtectedRanges[i].Offset)); + model->findByBase(bgProtectedRanges[i].Offset)); } markProtectedRangeRecursive(index, bgProtectedRanges[i]); @@ -3222,7 +3204,7 @@ USTATUS FfsParser::checkProtectedRanges(const UModelIndex & index) if (digest != bgProtectedRanges[i].Hash) { msg(usprintf("%s: AMI protected range [%Xh:%Xh] hash mismatch, opened image may refuse to boot", __FUNCTION__, bgProtectedRanges[i].Offset, bgProtectedRanges[i].Offset + bgProtectedRanges[i].Size), - model->findByOffset(bgProtectedRanges[i].Offset)); + model->findByBase(bgProtectedRanges[i].Offset)); } markProtectedRangeRecursive(index, bgProtectedRanges[i]); @@ -3239,7 +3221,7 @@ USTATUS FfsParser::checkProtectedRanges(const UModelIndex & index) if (digest != bgProtectedRanges[i].Hash) { msg(usprintf("%s: Phoenix protected range [%Xh:%Xh] hash mismatch, opened image may refuse to boot", __FUNCTION__, bgProtectedRanges[i].Offset, bgProtectedRanges[i].Offset + bgProtectedRanges[i].Size), - model->findByOffset(bgProtectedRanges[i].Offset)); + model->findByBase(bgProtectedRanges[i].Offset)); } markProtectedRangeRecursive(index, bgProtectedRanges[i]); @@ -3256,7 +3238,7 @@ USTATUS FfsParser::checkProtectedRanges(const UModelIndex & index) if (digest != bgProtectedRanges[i].Hash) { msg(usprintf("%s: Microsoft protected range [%Xh:%Xh] hash mismatch, opened image may refuse to boot", __FUNCTION__, bgProtectedRanges[i].Offset, bgProtectedRanges[i].Offset + bgProtectedRanges[i].Size), - model->findByOffset(bgProtectedRanges[i].Offset)); + model->findByBase(bgProtectedRanges[i].Offset)); } markProtectedRangeRecursive(index, bgProtectedRanges[i]); @@ -3278,7 +3260,7 @@ USTATUS FfsParser::markProtectedRangeRecursive(const UModelIndex & index, const } // Mark normal items else { - UINT32 currentOffset = model->offset(index); + UINT32 currentOffset = model->base(index); UINT32 currentSize = model->header(index).size() + model->body(index).size() + model->tail(index).size(); if (std::min(currentOffset + currentSize, range.Offset + range.Size) > std::max(currentOffset, range.Offset)) { @@ -3335,7 +3317,7 @@ USTATUS FfsParser::parseVendorHashFile(const UByteArray & fileGuid, const UModel } if (protectedRangesFound) { - securityInfo += usprintf("Phoenix hash file found at offset %Xh\nProtected ranges:", model->offset(index)); + securityInfo += usprintf("Phoenix hash file found at base %Xh\nProtected ranges:", model->base(index)); for (UINT32 i = 0; i < header->NumEntries; i++) { const BG_VENDOR_HASH_FILE_ENTRY* entry = (const BG_VENDOR_HASH_FILE_ENTRY*)(header + 1) + i; securityInfo += usprintf("\nRelativeOffset: %08Xh Size: %Xh\nHash: ", entry->Offset, entry->Size); @@ -3374,7 +3356,7 @@ USTATUS FfsParser::parseVendorHashFile(const UByteArray & fileGuid, const UModel } if (protectedRangesFound) { - securityInfo += usprintf("New AMI hash file found at offset %Xh\nProtected ranges:", model->offset(fileIndex)); + securityInfo += usprintf("New AMI hash file found at base %Xh\nProtected ranges:", model->base(fileIndex)); for (UINT32 i = 0; i < NumEntries; i++) { const BG_VENDOR_HASH_FILE_ENTRY* entry = (const BG_VENDOR_HASH_FILE_ENTRY*)(model->body(index).constData()) + i; securityInfo += usprintf("\nAddress: %08Xh Size: %Xh\nHash: ", entry->Offset, entry->Size); @@ -3388,7 +3370,7 @@ USTATUS FfsParser::parseVendorHashFile(const UByteArray & fileGuid, const UModel msg(usprintf("%s: new AMI hash file found", __FUNCTION__), fileIndex); } else if (size == sizeof(BG_VENDOR_HASH_FILE_HEADER_AMI_OLD)) { - securityInfo += usprintf("Old AMI hash file found at offset %Xh\nProtected range:", model->offset(fileIndex)); + securityInfo += usprintf("Old AMI hash file found at base %Xh\nProtected range:", model->base(fileIndex)); const BG_VENDOR_HASH_FILE_HEADER_AMI_OLD* entry = (const BG_VENDOR_HASH_FILE_HEADER_AMI_OLD*)(model->body(index).constData()); securityInfo += usprintf("\nSize: %Xh\nHash: ", entry->Size); for (UINT8 i = 0; i < sizeof(entry->Hash); i++) { @@ -3444,7 +3426,7 @@ USTATUS FfsParser::parseFit(const UModelIndex & index) if (!fitIndex.isValid()) return U_SUCCESS; - // Explicitly set the item as fixed + // Explicitly set the item containing FIT as fixed model->setFixed(fitIndex, true); // Special case of FIT header @@ -3491,7 +3473,6 @@ USTATUS FfsParser::parseFit(const UModelIndex & index) UModelIndex itemIndex; const FIT_ENTRY* currentEntry = fitHeader + i; UINT32 currentEntrySize = currentEntry->Size; - UINT32 currentEntryOffset; // Check sanity if (currentEntry->Type == FIT_TYPE_HEADER) { @@ -3510,12 +3491,12 @@ USTATUS FfsParser::parseFit(const UModelIndex & index) policy->IndexRegisterAddress); } else if (currentEntry->Address > addressDiff && currentEntry->Address < 0xFFFFFFFFUL) { // Only elements in the image need to be parsed - currentEntryOffset = (UINT32)(currentEntry->Address - addressDiff); - itemIndex = model->findByOffset(currentEntryOffset); + UINT32 currentEntryBase = (UINT32)(currentEntry->Address - addressDiff); + itemIndex = model->findByBase(currentEntryBase); if (itemIndex.isValid()) { USTATUS status = U_INVALID_FIT; UByteArray item = model->header(itemIndex) + model->body(itemIndex) + model->tail(itemIndex); - UINT32 localOffset = currentEntryOffset - model->offset(itemIndex); + UINT32 localOffset = currentEntryBase - model->base(itemIndex); switch (currentEntry->Type) { case FIT_TYPE_MICROCODE: @@ -3551,6 +3532,12 @@ USTATUS FfsParser::parseFit(const UModelIndex & index) } } + if (itemIndex.isValid()) { + // Explicitly set the item referenced by FIT as fixed + // TODO: lift this restriction after FIT builder is ready + model->setFixed(itemIndex, true); + } + // Add entry to fitTable currentStrings.push_back(usprintf("%016" PRIX64 "h", currentEntry->Address)); currentStrings.push_back(usprintf("%08Xh", currentEntrySize, currentEntrySize)); @@ -3602,7 +3589,7 @@ USTATUS FfsParser::findFitRecursive(const UModelIndex & index, UModelIndex & fou offset >= 0; offset = model->body(index).indexOf(FIT_SIGNATURE, offset + 1)) { // FIT candidate found, calculate it's physical address - UINT32 fitAddress = model->offset(index) + (UINT32)addressDiff + model->header(index).size() + (UINT32)offset; + UINT32 fitAddress = model->base(index) + (UINT32)addressDiff + model->header(index).size() + (UINT32)offset; // Check FIT address to be stored in the last VTF if (fitAddress == storedFitAddress) { @@ -3646,8 +3633,7 @@ USTATUS FfsParser::parseFitEntryMicrocode(const UByteArray & microcode, const UI } // Valid microcode found - info = usprintf("LocalOffset: %08Xh, CPUID: %08Xh, Revision: %08Xh, Date: %02X.%02X.%04X", - localOffset, + info = usprintf("CPUID: %08Xh, Revision: %08Xh, Date: %02X.%02X.%04X", header->CpuSignature, header->Revision, header->DateDay, @@ -3688,14 +3674,14 @@ USTATUS FfsParser::parseFitEntryAcm(const UByteArray & acm, const UINT32 localOf // Add ACM header info UString acmInfo; acmInfo += usprintf( - " found at offset %Xh\n" + " found at base %Xh\n" "ModuleType: %04Xh ModuleSubtype: %04Xh HeaderLength: %08Xh\n" "HeaderVersion: %08Xh ChipsetId: %04Xh Flags: %04Xh\n" "ModuleVendor: %04Xh Date: %02X.%02X.%04X ModuleSize: %08Xh\n" "EntryPoint: %08Xh AcmSvn: %04Xh Unknown1: %08Xh\n" "Unknown2: %08Xh GdtBase: %08Xh GdtMax: %08Xh\n" "SegSel: %08Xh KeySize: %08Xh Unknown3: %08Xh", - model->offset(parent) + localOffset, + model->base(parent) + localOffset, header->ModuleType, header->ModuleSubtype, header->ModuleSize * sizeof(UINT32), @@ -3766,9 +3752,9 @@ USTATUS FfsParser::parseFitEntryBootGuardKeyManifest(const UByteArray & keyManif // Add KM header info securityInfo += usprintf( - "Intel BootGuard Key manifest found at offset %Xh\n" + "Intel BootGuard Key manifest found at base %Xh\n" "Tag: __KEYM__ Version: %02Xh KmVersion: %02Xh KmSvn: %02Xh KmId: %02Xh", - model->offset(parent) + localOffset, + model->base(parent) + localOffset, header->Version, header->KmVersion, header->KmSvn, @@ -3874,10 +3860,10 @@ USTATUS FfsParser::parseFitEntryBootGuardBootPolicy(const UByteArray & bootPolic // Add BP header info securityInfo += usprintf( - "Intel BootGuard Boot Policy Manifest found at offset %Xh\n" + "Intel BootGuard Boot Policy Manifest found at base %Xh\n" "Tag: __ACBP__ Version: %02Xh HeaderVersion: %02Xh\n" "PMBPMVersion: %02Xh PBSVN: %02Xh ACMSVN: %02Xh NEMDataStack: %04Xh\n", - model->offset(parent) + localOffset, + model->base(parent) + localOffset, header->Version, header->HeaderVersion, header->PMBPMVersion, @@ -3896,11 +3882,11 @@ USTATUS FfsParser::parseFitEntryBootGuardBootPolicy(const UByteArray & bootPolic const BG_IBB_ELEMENT* elementHeader = (const BG_IBB_ELEMENT*)currentPos; // Valid IBB element found securityInfo += usprintf( - "\nInitial Boot Block Element found at offset %Xh\n" + "\nInitial Boot Block Element found at base %Xh\n" "Tag: __IBBS__ Version: %02Xh Unknown: %02Xh\n" "Flags: %08Xh IbbMchBar: %08Xh VtdBar: %08Xh\n" "PmrlBase: %08Xh PmrlLimit: %08Xh EntryPoint: %08Xh", - model->offset(parent) + localOffset + elementOffset, + model->base(parent) + localOffset + elementOffset, elementHeader->Version, elementHeader->Unknown, elementHeader->Flags, @@ -3951,9 +3937,9 @@ USTATUS FfsParser::parseFitEntryBootGuardBootPolicy(const UByteArray & bootPolic else if (*currentPos == BG_BOOT_POLICY_MANIFEST_PLATFORM_MANUFACTURER_ELEMENT_TAG) { const BG_PLATFORM_MANUFACTURER_ELEMENT* elementHeader = (const BG_PLATFORM_MANUFACTURER_ELEMENT*)currentPos; securityInfo += usprintf( - "\nPlatform Manufacturer Data Element found at offset %Xh\n" + "\nPlatform Manufacturer Data Element found at base %Xh\n" "Tag: __PMDA__ Version: %02Xh DataSize: %02Xh", - model->offset(parent) + localOffset + elementOffset, + model->base(parent) + localOffset + elementOffset, elementHeader->Version, elementHeader->DataSize ); @@ -3995,9 +3981,9 @@ USTATUS FfsParser::parseFitEntryBootGuardBootPolicy(const UByteArray & bootPolic else if (*currentPos == BG_BOOT_POLICY_MANIFEST_SIGNATURE_ELEMENT_TAG) { const BG_BOOT_POLICY_MANIFEST_SIGNATURE_ELEMENT* elementHeader = (const BG_BOOT_POLICY_MANIFEST_SIGNATURE_ELEMENT*)currentPos; securityInfo += usprintf( - "\nBoot Policy Signature Element found at offset %Xh\n" + "\nBoot Policy Signature Element found at base %Xh\n" "Tag: __PMSG__ Version: %02Xh", - model->offset(parent) + localOffset + elementOffset, + model->base(parent) + localOffset + elementOffset, elementHeader->Version ); @@ -4065,7 +4051,7 @@ USTATUS FfsParser::parseMicrocodeVolumeBody(const UModelIndex & index) UString info = usprintf("Full size: %Xh (%u)", ucode.size(), ucode.size()); // Add tree item - model->addItem(model->offset(index) + headerSize + offset, Types::Padding, getPaddingType(ucode), name, UString(), info, UByteArray(), ucode, UByteArray(), Fixed, index); + model->addItem(headerSize + offset, Types::Padding, getPaddingType(ucode), name, UString(), info, UByteArray(), ucode, UByteArray(), Fixed, index); } return U_SUCCESS; } @@ -4138,7 +4124,7 @@ USTATUS FfsParser::parseIntelMicrocodeHeader(const UByteArray & microcode, const ucodeHeader->CpuFlags); // Add tree item - index = model->addItem(model->offset(parent) + localOffset, Types::Microcode, Subtypes::IntelMicrocode, name, UString(), info, header, body, UByteArray(), Fixed, parent); + index = model->addItem(localOffset, Types::Microcode, Subtypes::IntelMicrocode, name, UString(), info, header, body, UByteArray(), Fixed, parent); // No need to parse body further for now return U_SUCCESS; diff --git a/common/ffsparser.h b/common/ffsparser.h index a5ea14f..32bdeb2 100644 --- a/common/ffsparser.h +++ b/common/ffsparser.h @@ -139,9 +139,8 @@ private: // Second pass USTATUS performSecondPass(const UModelIndex & index); - USTATUS addOffsetsRecursive(const UModelIndex & index); - USTATUS addMemoryAddressesRecursive(const UModelIndex & index); - USTATUS addFixedAndCompressedRecursive(const UModelIndex & index); + USTATUS addInfoRecursive(const UModelIndex & index); + USTATUS checkTeImageBase(const UModelIndex & index); USTATUS checkProtectedRanges(const UModelIndex & index); USTATUS markProtectedRangeRecursive(const UModelIndex & index, const BG_PROTECTED_RANGE & range); diff --git a/common/ffsreport.cpp b/common/ffsreport.cpp index df622be..cf94860 100644 --- a/common/ffsreport.cpp +++ b/common/ffsreport.cpp @@ -33,7 +33,7 @@ std::vector FfsReport::generate() } // Generate report recursive - report.push_back(UString(" Type | Subtype | Offset | Size | CRC32 | Name ")); + report.push_back(UString(" Type | Subtype | Base | Size | CRC32 | Name ")); USTATUS result = generateRecursive(report, root); if (result) { report.push_back(usprintf("%s: generateRecursive returned ", __FUNCTION__) + errorCodeToUString(result)); @@ -55,7 +55,7 @@ USTATUS FfsReport::generateRecursive(std::vector & report, const UModel UString text = model->text(index); UString offset = "| N/A "; if ((!model->compressed(index)) || (index.parent().isValid() && !model->compressed(index.parent()))) { - offset = usprintf("| %08X ", model->offset(index)); + offset = usprintf("| %08X ", model->base(index)); } report.push_back( diff --git a/common/nvramparser.cpp b/common/nvramparser.cpp index 8977e89..498d1f2 100644 --- a/common/nvramparser.cpp +++ b/common/nvramparser.cpp @@ -12,6 +12,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. */ +//TODO: relax fixed restrictions once NVRAM builder is ready + // A workaround for compilers not supporting c++11 and c11 // for using PRIX64. #define __STDC_FORMAT_MACROS @@ -46,7 +48,7 @@ USTATUS NvramParser::parseNvarStore(const UModelIndex & index) model->setText(parentFileIndex, UString("NVAR store")); // Get local offset - UINT32 localOffset = model->offset(index) + model->header(index).size(); + UINT32 localOffset = model->header(index).size(); // Get item data const UByteArray data = model->body(index); @@ -101,7 +103,7 @@ USTATUS NvramParser::parseNvarStore(const UModelIndex & index) 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); + model->addItem(localOffset + offset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); } else { // Nothing is parsed yet, but the file is not empty @@ -228,7 +230,7 @@ USTATUS NvramParser::parseNvarStore(const UModelIndex & index) if (entryHeader->Attributes & NVRAM_NVAR_ENTRY_DATA_ONLY) { // Data-only attribute is set isInvalidLink = true; UModelIndex nvarIndex; - // Search prevously added entries for a link to this variable + // Search previously added entries for a link to this variable // WARNING: O(n^2), may be very slow for (int i = model->rowCount(index) - 1; i >= 0; i--) { nvarIndex = index.child(i, 0); @@ -251,7 +253,6 @@ USTATUS NvramParser::parseNvarStore(const UModelIndex & index) subtype = Subtypes::DataNvarEntry; } - //isDataOnly = true; // Do not parse further goto parsing_done; } @@ -351,7 +352,7 @@ USTATUS NvramParser::parseNvarStore(const UModelIndex & index) } // Add tree item - UModelIndex varIndex = model->addItem(localOffset + offset, Types::NvarEntry, subtype, name, text, info, header, body, tail, Movable, index); + UModelIndex varIndex = model->addItem(localOffset + offset, Types::NvarEntry, subtype, name, text, info, header, body, tail, Fixed, index); // Set parsing data for created entry model->setParsingData(varIndex, UByteArray((const char*)&pdata, sizeof(pdata))); @@ -390,7 +391,7 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index) } // Get local offset - UINT32 localOffset = model->offset(index) + model->header(index).size(); + UINT32 localOffset = model->header(index).size(); // Get item data UByteArray data = model->body(index); @@ -483,7 +484,7 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index) 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); + model->addItem(localOffset + storeOffset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); } else { // Nothing is parsed yet, but the file is not empty @@ -1283,7 +1284,7 @@ USTATUS NvramParser::parseFdcStoreBody(const UModelIndex & index) const UByteArray data = model->body(index); // Get local offset - UINT32 localOffset = model->offset(index) + model->header(index).size(); + UINT32 localOffset = model->header(index).size(); // The body is a firmware volume with either a VSS or VSS2 store UModelIndex volumeIndex; @@ -1332,7 +1333,7 @@ USTATUS NvramParser::parseVssStoreBody(const UModelIndex & index, UINT8 alignmen } // Get local offset - UINT32 localOffset = model->offset(index) + model->header(index).size(); + UINT32 localOffset = model->header(index).size(); // Get item data const UByteArray data = model->body(index); @@ -1472,7 +1473,7 @@ USTATUS NvramParser::parseVssStoreBody(const UModelIndex & index, UINT8 alignmen 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); + model->addItem(localOffset + offset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); } else { // Padding // Nothing is parsed yet, but the store is not empty @@ -1531,7 +1532,7 @@ USTATUS NvramParser::parseVssStoreBody(const UModelIndex & index, UINT8 alignmen } // Add tree item - model->addItem(localOffset + offset, Types::VssEntry, subtype, name, text, info, header, body, UByteArray(), Movable, index); + model->addItem(localOffset + offset, Types::VssEntry, subtype, name, text, info, header, body, UByteArray(), Fixed, index); // Apply alignment, if needed if (alignment) { @@ -1552,7 +1553,7 @@ USTATUS NvramParser::parseFsysStoreBody(const UModelIndex & index) return U_INVALID_PARAMETER; // Get local offset - UINT32 localOffset = model->offset(index) + model->header(index).size(); + UINT32 localOffset = model->header(index).size(); // Get item data const UByteArray data = model->body(index); @@ -1594,7 +1595,7 @@ USTATUS NvramParser::parseFsysStoreBody(const UModelIndex & index) info = usprintf("Full size: %Xh (%u)", body.size(), body.size()); // Add free space tree item - model->addItem(localOffset + offset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), body, UByteArray(), Movable, index); + model->addItem(localOffset + offset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), body, UByteArray(), Fixed, index); return U_SUCCESS; } @@ -1630,7 +1631,7 @@ USTATUS NvramParser::parseFsysStoreBody(const UModelIndex & index) body.size(), body.size()); // Add tree item - model->addItem(localOffset + offset, Types::FsysEntry, valid ? Subtypes::NormalFsysEntry : Subtypes::InvalidFsysEntry, UString(name.constData()), UString(), info, header, body, UByteArray(), Movable, index); + model->addItem(localOffset + offset, Types::FsysEntry, valid ? Subtypes::NormalFsysEntry : Subtypes::InvalidFsysEntry, UString(name.constData()), UString(), info, header, body, UByteArray(), Fixed, index); // Move to next variable offset += variableSize; @@ -1655,7 +1656,7 @@ USTATUS NvramParser::parseEvsaStoreBody(const UModelIndex & index) } // Get local offset - UINT32 localOffset = model->offset(index) + model->header(index).size(); + UINT32 localOffset = model->header(index).size(); // Get item data const UByteArray data = model->body(index); @@ -1688,7 +1689,7 @@ USTATUS NvramParser::parseEvsaStoreBody(const UModelIndex & index) if (body.count(emptyByte) == body.size()) { // Free space // Add free space tree item - model->addItem(localOffset + offset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), body, UByteArray(), Movable, index); + model->addItem(localOffset + offset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), body, UByteArray(), Fixed, index); } else { // Add padding tree item @@ -1780,7 +1781,7 @@ USTATUS NvramParser::parseEvsaStoreBody(const UModelIndex & index) if (body.count(emptyByte) == body.size()) { // Free space // Add free space tree item - model->addItem(localOffset + offset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), body, UByteArray(), Movable, index); + model->addItem(localOffset + offset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), body, UByteArray(), Fixed, index); } else { // Add padding tree item @@ -1793,7 +1794,7 @@ USTATUS NvramParser::parseEvsaStoreBody(const UModelIndex & index) } // Add tree item - model->addItem(localOffset + offset, Types::EvsaEntry, subtype, name, UString(), info, header, body, UByteArray(), Movable, index); + model->addItem(localOffset + offset, Types::EvsaEntry, subtype, name, UString(), info, header, body, UByteArray(), Fixed, index); // Move to next variable offset += variableSize; @@ -1854,7 +1855,7 @@ USTATUS NvramParser::parseFlashMapBody(const UModelIndex & index) return U_INVALID_PARAMETER; // Get parsing data for the current item - UINT32 localOffset = model->offset(index) + model->header(index).size(); + UINT32 localOffset = model->header(index).size(); const UByteArray data = model->body(index); @@ -1908,7 +1909,7 @@ USTATUS NvramParser::parseFlashMapBody(const UModelIndex & index) } // Add tree item - model->addItem(localOffset + offset, Types::FlashMapEntry, subtype, name, flashMapGuidToUString(entryHeader->Guid), info, header, UByteArray(), UByteArray(), Movable, index); + model->addItem(localOffset + offset, Types::FlashMapEntry, subtype, name, flashMapGuidToUString(entryHeader->Guid), info, header, UByteArray(), UByteArray(), Fixed, index); // Move to next variable offset += sizeof(PHOENIX_FLASH_MAP_ENTRY); diff --git a/common/treeitem.h b/common/treeitem.h index 880e94a..87d75af 100644 --- a/common/treeitem.h +++ b/common/treeitem.h @@ -45,7 +45,7 @@ public: TreeItem *parent() { return parentItem; } // Getters and setters for item parameters - UINT32 offset() const { return itemOffset; } + UINT32 offset() const { return itemOffset; } void setOffset(const UINT32 offset) { itemOffset = offset; } UINT8 type() const { return itemType; } diff --git a/common/treemodel.cpp b/common/treemodel.cpp index 0f5d3d5..60b29b1 100644 --- a/common/treemodel.cpp +++ b/common/treemodel.cpp @@ -156,6 +156,20 @@ int TreeModel::rowCount(const UModelIndex &parent) const return parentItem->childCount(); } +UINT32 TreeModel::base(const UModelIndex ¤t) const +{ + // TODO: rewrite this as loop if we ever see an image that is too deep for this naive implementation + if (!current.isValid()) + return 0; + + UModelIndex parent = current.parent(); + if (!parent.isValid()) + return offset(current); + else { + return offset(current) + base(parent); + } +} + UINT32 TreeModel::offset(const UModelIndex &index) const { if (!index.isValid()) @@ -303,8 +317,7 @@ void TreeModel::setFixed(const UModelIndex &index, const bool fixed) } // Propagate fixed flag until root - if (item->parent()->type() != Types::Root) - item->parent()->setFixed(fixed); + setFixed(index.parent(), true); } emit dataChanged(index, index); @@ -539,7 +552,7 @@ UModelIndex TreeModel::findLastParentOfType(const UModelIndex& index, UINT8 type return lastParentOfType; } -UModelIndex TreeModel::findByOffset(UINT32 offset) const +UModelIndex TreeModel::findByBase(UINT32 base) const { UModelIndex parentIndex = index(0,0); @@ -547,10 +560,10 @@ goDeeper: int n = rowCount(parentIndex); for (int i = 0; i < n; i++) { UModelIndex currentIndex = parentIndex.child(i, 0); - UINTN currentOffset = this->offset(currentIndex); - UINTN fullSize = header(currentIndex).size() + body(currentIndex).size() + tail(currentIndex).size(); - if ((compressed(currentIndex) == false || (compressed(currentIndex) == true && compressed(currentIndex.parent()) == false)) // Offset is meaningful only for uncompressed items - && currentOffset <= offset && offset < currentOffset + fullSize) { // Offset must be in range [currentOffset, currentOffset + fullSize) + UINT32 currentBase = this->base(currentIndex); + UINT32 fullSize = header(currentIndex).size() + body(currentIndex).size() + tail(currentIndex).size(); + if ((compressed(currentIndex) == false || (compressed(currentIndex) == true && compressed(currentIndex.parent()) == false)) // Base is meaningful only for true uncompressed items + && currentBase <= base && base < currentBase + fullSize) { // Base must be in range [currentBase, currentBase + fullSize) // Found a better candidate parentIndex = currentIndex; goto goDeeper; diff --git a/common/treemodel.h b/common/treemodel.h index bb2e50f..b1ef19e 100644 --- a/common/treemodel.h +++ b/common/treemodel.h @@ -142,34 +142,46 @@ public: int rowCount(const UModelIndex &parent = UModelIndex()) const; int columnCount(const UModelIndex &parent = UModelIndex()) const; + UINT8 action(const UModelIndex &index) const; void setAction(const UModelIndex &index, const UINT8 action); + + UINT32 base(const UModelIndex &index) const; + UINT32 offset(const UModelIndex &index) const; void setOffset(const UModelIndex &index, const UINT32 offset); + + UINT8 type(const UModelIndex &index) const; void setType(const UModelIndex &index, const UINT8 type); + + UINT8 subtype(const UModelIndex &index) const; void setSubtype(const UModelIndex &index, const UINT8 subtype); + + UString name(const UModelIndex &index) const; void setName(const UModelIndex &index, const UString &name); + + UString text(const UModelIndex &index) const; void setText(const UModelIndex &index, const UString &text); + + UString info(const UModelIndex &index) const; void setInfo(const UModelIndex &index, const UString &info); void addInfo(const UModelIndex &index, const UString &info, const bool append = TRUE); + + bool fixed(const UModelIndex &index) const; void setFixed(const UModelIndex &index, const bool fixed); + + bool compressed(const UModelIndex &index) const; void setCompressed(const UModelIndex &index, const bool compressed); + + UINT8 marking(const UModelIndex &index) const; void setMarking(const UModelIndex &index, const UINT8 marking); - - 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; + 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; - bool fixed(const UModelIndex &index) const; - bool compressed(const UModelIndex &index) const; - UINT8 marking(const UModelIndex &index) const; - UINT8 action(const UModelIndex &index) const; UByteArray parsingData(const UModelIndex &index) const; bool hasEmptyParsingData(const UModelIndex &index) const; @@ -183,7 +195,7 @@ public: UModelIndex findParentOfType(const UModelIndex & index, UINT8 type) const; UModelIndex findLastParentOfType(const UModelIndex & index, UINT8 type) const; - UModelIndex findByOffset(UINT32 offset) const; + UModelIndex findByBase(UINT32 base) const; }; #if defined(QT_CORE_LIB) diff --git a/version.h b/version.h index b096193..6bb8fb3 100644 --- a/version.h +++ b/version.h @@ -14,6 +14,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #ifndef VERSION_H #define VERSION_H -#define PROGRAM_VERSION "NE alpha 53" " (" __DATE__ ")" +#define PROGRAM_VERSION "NE alpha 54" " (" __DATE__ ")" #endif // VERSION_H