From 59a6f298ee96f27fac98f16168f3d5ba101aa74c Mon Sep 17 00:00:00 2001 From: Nikolaj Schlej Date: Thu, 14 Jul 2016 21:22:51 +0200 Subject: [PATCH] Move fitParser to ffsParser - required to set fixed properly --- UEFIDump/CMakeLists.txt | 2 - UEFIExtract/uefiextract.pro | 2 - UEFIExtract/uefiextract_main.cpp | 92 ++++++++--------- UEFITool/uefitool.cpp | 52 ++-------- UEFITool/uefitool.h | 3 - UEFITool/uefitool.pro | 2 - UEFITool/uefitool.ui | 5 - common/ffsparser.cpp | 167 +++++++++++++++++++++++++++++-- common/ffsparser.h | 21 ++-- common/fitparser.cpp | 164 ------------------------------ common/fitparser.h | 59 ----------- common/types.cpp | 18 ++++ common/types.h | 1 + qhexedit2/qhexedit.h | 4 +- 14 files changed, 244 insertions(+), 348 deletions(-) delete mode 100644 common/fitparser.cpp delete mode 100644 common/fitparser.h diff --git a/UEFIDump/CMakeLists.txt b/UEFIDump/CMakeLists.txt index e69b7e1..6130845 100644 --- a/UEFIDump/CMakeLists.txt +++ b/UEFIDump/CMakeLists.txt @@ -9,7 +9,6 @@ SET(PROJECT_SOURCES ../common/nvram.cpp ../common/ffsparser.cpp ../common/ffsreport.cpp - ../common/fitparser.cpp ../common/peimage.cpp ../common/treeitem.cpp ../common/treemodel.cpp @@ -32,7 +31,6 @@ SET(PROJECT_HEADERS ../common/nvram.h ../common/ffsparser.h ../common/ffsreport.h - ../common/fitparser.h ../common/peimage.h ../common/types.h ../common/treeitem.h diff --git a/UEFIExtract/uefiextract.pro b/UEFIExtract/uefiextract.pro index 32e7642..c9a86f7 100644 --- a/UEFIExtract/uefiextract.pro +++ b/UEFIExtract/uefiextract.pro @@ -15,7 +15,6 @@ SOURCES += \ ../common/nvram.cpp \ ../common/ffsparser.cpp \ ../common/ffsreport.cpp \ - ../common/fitparser.cpp \ ../common/peimage.cpp \ ../common/treeitem.cpp \ ../common/treemodel.cpp \ @@ -35,7 +34,6 @@ HEADERS += \ ../common/nvram.h \ ../common/ffsparser.h \ ../common/ffsreport.h \ - ../common/fitparser.h \ ../common/peimage.h \ ../common/types.h \ ../common/treeitem.h \ diff --git a/UEFIExtract/uefiextract_main.cpp b/UEFIExtract/uefiextract_main.cpp index f30b116..ccf7d33 100644 --- a/UEFIExtract/uefiextract_main.cpp +++ b/UEFIExtract/uefiextract_main.cpp @@ -15,7 +15,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "../common/ffsparser.h" #include "../common/ffsreport.h" -#include "../common/fitparser.h" #include "ffsdumper.h" int main(int argc, char *argv[]) @@ -62,36 +61,39 @@ int main(int argc, char *argv[]) } // Get last VTF - QModelIndex lastVtf = ffsParser.getLastVtf(); - if (lastVtf.isValid()) { - // Create fitParser - FitParser fitParser(&model); - // Find and parse FIT table - result = fitParser.parse(model.index(0, 0), lastVtf); - if (U_SUCCESS == result) { - // Show fitParser's messages - std::vector > fitMessages = fitParser.getMessages(); - for (size_t i = 0; i < fitMessages.size(); i++) { - std::cout << fitMessages[i].first.toLatin1().constData() << std::endl; - } - - // Show FIT table - std::vector > fitTable = fitParser.getFitTable(); - if (fitTable.size()) { - std::cout << "-------------------------------------------------------------------" << std::endl; - std::cout << " Address | Size | Ver | Type | CS " << std::endl; - std::cout << "-------------------------------------------------------------------" << std::endl; - for (size_t i = 0; i < fitTable.size(); i++) { - std::cout << fitTable[i][0].toLatin1().constData() << " | " + std::vector > fitTable = ffsParser.getFitTable(); + if (fitTable.size()) { + std::cout << "-------------------------------------------------------------------" << std::endl; + std::cout << " Address | Size | Ver | CS | Type " << std::endl; + std::cout << "-------------------------------------------------------------------" << std::endl; + for (size_t i = 0; i < fitTable.size(); i++) { + std::cout << fitTable[i][0].toLatin1().constData() << " | " << fitTable[i][1].toLatin1().constData() << " | " << fitTable[i][2].toLatin1().constData() << " | " << fitTable[i][3].toLatin1().constData() << " | " << fitTable[i][4].toLatin1().constData() << std::endl; - } - } - } + } } + + // Create ffsDumper + FfsDumper ffsDumper(&model); + + // Dump only leaf elements, no report + if (a.arguments().length() == 3 && a.arguments().at(2) == QString("dump")) { + return (ffsDumper.dump(model.index(0, 0), fileInfo.fileName().append(".dump")) != U_SUCCESS); + } + else if (a.arguments().length() > 3 || + (a.arguments().length() == 3 && a.arguments().at(2) != QString("all") && a.arguments().at(2) != QString("report"))) { // Dump specific files, without report + UINT32 returned = 0; + for (int i = 2; i < a.arguments().length(); i++) { + result = ffsDumper.dump(model.index(0, 0), fileInfo.fileName().append(".dump"), true, a.arguments().at(i)); + if (result) + returned |= (1 << (i - 1)); + } + return returned; + } + // Create ffsReport FfsReport ffsReport(&model); std::vector report = ffsReport.generate(); @@ -105,39 +107,25 @@ int main(int argc, char *argv[]) file.close(); } } - - // Create ffsDumper - FfsDumper ffsDumper(&model); - - // Dump all non-leaf elements + + // Dump all non-leaf elements, with report, default if (a.arguments().length() == 2) { return (ffsDumper.dump(model.index(0, 0), fileInfo.fileName().append(".dump")) != U_SUCCESS); } - else if (a.arguments().length() == 3 && a.arguments().at(2) == QString("all")) { // Dump everything + else if (a.arguments().length() == 3 && a.arguments().at(2) == QString("all")) { // Dump every elementm with report return (ffsDumper.dump(model.index(0, 0), fileInfo.fileName().append(".dump"), true) != U_SUCCESS); } - else if (a.arguments().length() == 3 && a.arguments().at(2) == QString("none")) { // Skip dumping + else if (a.arguments().length() == 3 && a.arguments().at(2) == QString("report")) { // Skip dumping return 0; } - else { // Dump specific files - UINT32 returned = 0; - for (int i = 2; i < a.arguments().length(); i++) { - result = ffsDumper.dump(model.index(0, 0), fileInfo.fileName().append(".dump"), true, a.arguments().at(i)); - if (result) - returned |= (1 << (i - 1)); - } - return returned; - } - - return 0; - } - else { // Show version and usage information - std::cout << "UEFIExtract 0.12.2" << std::endl << std::endl - << "Usage: UEFIExtract imagefile - generate report and dump only leaf tree items into .dump folder" << std::endl - << " UEFIExtract imagefile all - generate report and dump all tree items" << std::endl - << " UEFIExtract imagefile none - only generate report, no dump needed" << std::endl - << " UIFIExtract imagefile GUID_1 GUID_2 ... GUID_31 - dump only FFS file(s) with specific GUID(s)" << std::endl - << "Return value is a bit mask where 0 at position N means that file with GUID_N was found and unpacked, 1 otherwise" << std::endl; - return 1; } + // If parameters are different, show version and usage information + std::cout << "UEFIExtract 0.13.0" << std::endl << std::endl + << "Usage: UEFIExtract imagefile - generate report and dump only leaf tree items into .dump folder." << std::endl + << " UEFIExtract imagefile all - generate report and dump all tree items." << std::endl + << " UEFIExtract imagefile dump - only generate dump, no report needed." << std::endl + << " UEFIExtract imagefile report - only generate report, no dump needed." << std::endl + << " UEFIExtract imagefile GUID_1 GUID_2 ... GUID_31 - dump only FFS file(s) with specific GUID(s), without report." << std::endl + << "Return value is a bit mask where 0 at position N means that file with GUID_N was found and unpacked, 1 otherwise." << std::endl; + return 1; } \ No newline at end of file diff --git a/UEFITool/uefitool.cpp b/UEFITool/uefitool.cpp index b04020d..574312e 100644 --- a/UEFITool/uefitool.cpp +++ b/UEFITool/uefitool.cpp @@ -27,7 +27,6 @@ version(tr("NE Alpha32")) hexViewDialog = new HexViewDialog(this); model = NULL; ffsParser = NULL; - fitParser = NULL; ffsFinder = NULL; ffsOps = NULL; ffsBuilder = NULL; @@ -72,7 +71,6 @@ version(tr("NE Alpha32")) #endif ui->infoEdit->setFont(font); ui->parserMessagesListWidget->setFont(font); - ui->fitMessagesListWidget->setFont(font); ui->finderMessagesListWidget->setFont(font); ui->builderMessagesListWidget->setFont(font); ui->fitTableWidget->setFont(font); @@ -93,7 +91,6 @@ UEFITool::~UEFITool() delete ffsBuilder; delete ffsOps; delete ffsFinder; - delete fitParser; delete ffsParser; delete model; delete hexViewDialog; @@ -136,17 +133,12 @@ void UEFITool::init() // ... and ffsParser delete ffsParser; ffsParser = new FfsParser(model); - // ... and fitParser - delete fitParser; - fitParser = new FitParser(model); // Connect connect(ui->structureTreeView->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(populateUi(const QModelIndex &))); connect(ui->parserMessagesListWidget, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(scrollTreeView(QListWidgetItem*))); connect(ui->parserMessagesListWidget, SIGNAL(itemEntered(QListWidgetItem*)), this, SLOT(enableMessagesCopyActions(QListWidgetItem*))); - connect(ui->fitMessagesListWidget, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(scrollTreeView(QListWidgetItem*))); - connect(ui->fitMessagesListWidget, SIGNAL(itemEntered(QListWidgetItem*)), this, SLOT(enableMessagesCopyActions(QListWidgetItem*))); connect(ui->finderMessagesListWidget, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(scrollTreeView(QListWidgetItem*))); connect(ui->finderMessagesListWidget, SIGNAL(itemEntered(QListWidgetItem*)), this, SLOT(enableMessagesCopyActions(QListWidgetItem*))); connect(ui->builderMessagesListWidget, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(scrollTreeView(QListWidgetItem*))); @@ -748,13 +740,6 @@ void UEFITool::openImageFile(QString path) else ui->statusBar->showMessage(tr("Opened: %1").arg(fileInfo.fileName())); - // Parse FIT - result = fitParser->parse(model->index(0, 0), ffsParser->getLastVtf()); - showFitMessages(); - if (!result) { - showFitTable(); - } - // Enable search ... delete ffsFinder; ffsFinder = new FfsFinder(model); @@ -763,6 +748,9 @@ void UEFITool::openImageFile(QString path) delete ffsOps; ffsOps = new FfsOperations(model); + // Enable or disable FIT tab + showFitTable(); + // Set current directory currentDir = fileInfo.absolutePath(); } @@ -772,8 +760,6 @@ void UEFITool::copyMessage() clipboard->clear(); if (ui->messagesTabWidget->currentIndex() == 0) // Parser tab clipboard->setText(ui->parserMessagesListWidget->currentItem()->text()); - else if (ui->messagesTabWidget->currentIndex() == 1) // FIT tab - clipboard->setText(ui->fitMessagesListWidget->currentItem()->text()); else if (ui->messagesTabWidget->currentIndex() == 2) // Search tab clipboard->setText(ui->finderMessagesListWidget->currentItem()->text()); else if (ui->messagesTabWidget->currentIndex() == 3) // Builder tab @@ -789,11 +775,6 @@ void UEFITool::copyAllMessages() text.append(ui->parserMessagesListWidget->item(i)->text()).append("\n"); clipboard->setText(text); } - else if (ui->messagesTabWidget->currentIndex() == 1) { // FIT tab - for (INT32 i = 0; i < ui->fitMessagesListWidget->count(); i++) - text.append(ui->fitMessagesListWidget->item(i)->text()).append("\n"); - clipboard->setText(text); - } else if (ui->messagesTabWidget->currentIndex() == 2) { // Search tab for (INT32 i = 0; i < ui->finderMessagesListWidget->count(); i++) text.append(ui->finderMessagesListWidget->item(i)->text()).append("\n"); @@ -818,10 +799,6 @@ void UEFITool::clearMessages() if (ffsParser) ffsParser->clearMessages(); ui->parserMessagesListWidget->clear(); } - else if (ui->messagesTabWidget->currentIndex() == 1) { // FIT tab - if (fitParser) fitParser->clearMessages(); - ui->fitMessagesListWidget->clear(); - } else if (ui->messagesTabWidget->currentIndex() == 2) { // Search tab if (ffsFinder) ffsFinder->clearMessages(); ui->finderMessagesListWidget->clear(); @@ -863,21 +840,6 @@ void UEFITool::showParserMessages() ui->parserMessagesListWidget->scrollToBottom(); } -void UEFITool::showFitMessages() -{ - ui->fitMessagesListWidget->clear(); - if (!fitParser) - return; - - std::vector > messages = fitParser->getMessages(); - std::pair msg; - foreach (msg, messages) { - ui->fitMessagesListWidget->addItem(new MessageListItem(msg.first, NULL, 0, msg.second)); - } - - ui->fitMessagesListWidget->scrollToBottom(); -} - void UEFITool::showFinderMessages() { ui->finderMessagesListWidget->clear(); @@ -923,7 +885,6 @@ void UEFITool::scrollTreeView(QListWidgetItem* item) void UEFITool::contextMenuEvent(QContextMenuEvent* event) { if (ui->parserMessagesListWidget->underMouse() || - ui->fitMessagesListWidget->underMouse() || ui->finderMessagesListWidget->underMouse() || ui->builderMessagesListWidget->underMouse()) { ui->menuMessages->exec(event->globalPos()); @@ -999,10 +960,13 @@ void UEFITool::writeSettings() void UEFITool::showFitTable() { - std::vector > fitTable = fitParser->getFitTable(); + std::vector > fitTable = ffsParser->getFitTable(); if (fitTable.empty()) { + // Disable FIT tab + ui->messagesTabWidget->setTabEnabled(1, false); return; } + // Enable FIT tab ui->messagesTabWidget->setTabEnabled(1, true); @@ -1010,7 +974,7 @@ void UEFITool::showFitTable() ui->fitTableWidget->clear(); ui->fitTableWidget->setRowCount(fitTable.size()); ui->fitTableWidget->setColumnCount(5); - ui->fitTableWidget->setHorizontalHeaderLabels(QStringList() << tr("Address") << tr("Size") << tr("Version") << tr("Type") << tr("Checksum")); + ui->fitTableWidget->setHorizontalHeaderLabels(QStringList() << tr("Address") << tr("Size") << tr("Version") << tr("Checksum") << tr("Type")); ui->fitTableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); ui->fitTableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); ui->fitTableWidget->setSelectionMode(QAbstractItemView::SingleSelection); diff --git a/UEFITool/uefitool.h b/UEFITool/uefitool.h index 36a91f8..6f6f40a 100644 --- a/UEFITool/uefitool.h +++ b/UEFITool/uefitool.h @@ -38,7 +38,6 @@ #include "../common/utility.h" #include "../common/ffs.h" #include "../common/ffsparser.h" -#include "../common/fitparser.h" #include "../common/ffsops.h" #include "../common/ffsbuilder.h" @@ -109,7 +108,6 @@ private: Ui::UEFITool* ui; TreeModel* model; FfsParser* ffsParser; - FitParser* fitParser; FfsFinder* ffsFinder; FfsOperations* ffsOps; FfsBuilder* ffsBuilder; @@ -128,7 +126,6 @@ private: void readSettings(); void showParserMessages(); void showFinderMessages(); - void showFitMessages(); void showFitTable(); void showBuilderMessages(); }; diff --git a/UEFITool/uefitool.pro b/UEFITool/uefitool.pro index 89ba999..1e15a6e 100644 --- a/UEFITool/uefitool.pro +++ b/UEFITool/uefitool.pro @@ -24,7 +24,6 @@ HEADERS += uefitool.h \ ../common/parsingdata.h \ ../common/ffsbuilder.h \ ../common/ffsparser.h \ - ../common/fitparser.h \ ../common/treeitem.h \ ../common/treemodel.h \ ../common/LZMA/LzmaCompress.h \ @@ -53,7 +52,6 @@ SOURCES += uefitool_main.cpp \ ../common/utility.cpp \ ../common/ffsbuilder.cpp \ ../common/ffsparser.cpp \ - ../common/fitparser.cpp \ ../common/treeitem.cpp \ ../common/treemodel.cpp \ ../common/LZMA/LzmaCompress.c \ diff --git a/UEFITool/uefitool.ui b/UEFITool/uefitool.ui index 29969f8..886435e 100644 --- a/UEFITool/uefitool.ui +++ b/UEFITool/uefitool.ui @@ -199,11 +199,6 @@ Qt::Horizontal - - - true - - diff --git a/common/ffsparser.cpp b/common/ffsparser.cpp index f109c28..694d6ab 100644 --- a/common/ffsparser.cpp +++ b/common/ffsparser.cpp @@ -2853,7 +2853,7 @@ USTATUS FfsParser::parseTeImageSectionBody(const UModelIndex & index) usprintf("\nNumber of sections: %u\nSubsystem: %02Xh\nStripped size: %Xh (%u)\n" "Base of code: %Xh\nAddress of entry point: %Xh\nImage base: %" PRIX64 "h\nAdjusted image base: %" PRIX64 "h", teHeader->NumberOfSections, - teHeader->Subsystem, + teHeader->Subsystem, teHeader->StrippedSize, teHeader->StrippedSize, teHeader->BaseOfCode, teHeader->AddressOfEntryPoint, @@ -2887,7 +2887,7 @@ USTATUS FfsParser::performSecondPass(const UModelIndex & index) msg(UString("performSecondPass: the last VTF appears inside compressed item, the image may be damaged"), lastVtf); return U_SUCCESS; } - + // Get parsing data for the last VTF PARSING_DATA pdata = parsingDataFromUModelIndex(lastVtf); @@ -2895,9 +2895,168 @@ USTATUS FfsParser::performSecondPass(const UModelIndex & index) const UINT32 vtfSize = model->header(lastVtf).size() + model->body(lastVtf).size() + model->tail(lastVtf).size(); const UINT32 diff = 0xFFFFFFFFUL - pdata.offset - vtfSize + 1; + // Find and parse FIT + parseFit(index, diff); + // Apply address information to index and all it's child items addMemoryAddressesRecursive(index, diff); + // Add fixed and compressed + addFixedAndCompressedRecursive(index); + + return U_SUCCESS; +} + +USTATUS FfsParser::addFixedAndCompressedRecursive(const UModelIndex & index) { + // Sanity check + if (!index.isValid()) + return U_INVALID_PARAMETER; + + // Get parsing data for the current item + PARSING_DATA pdata = parsingDataFromUModelIndex(index); + + // Add fixed and compressed info + model->addInfo(index, usprintf("\nCompressed: %s", model->compressed(index) ? "Yes" : "No")); + model->addInfo(index, usprintf("\nFixed: %s", model->fixed(index) ? "Yes" : "No")); + + // Process child items + for (int i = 0; i < model->rowCount(index); i++) { + addFixedAndCompressedRecursive(index.child(i, 0)); + } + + return U_SUCCESS; +} + +USTATUS FfsParser::parseFit(const UModelIndex & index, const UINT32 diff) +{ + // Check sanity + if (!index.isValid()) + return EFI_INVALID_PARAMETER; + + // Search for FIT + UModelIndex fitIndex; + UINT32 fitOffset; + USTATUS result = findFitRecursive(index, diff, fitIndex, fitOffset); + if (result) + return result; + + // FIT not found + if (!fitIndex.isValid()) + return U_SUCCESS; + + // Explicitly set the item as fixed + model->setFixed(fitIndex, true); + + // Special case of FIT header + UByteArray fitBody = model->body(fitIndex); + const FIT_ENTRY* fitHeader = (const FIT_ENTRY*)(fitBody.constData() + fitOffset); + + // Check FIT checksum, if present + UINT32 fitSize = (fitHeader->Size & 0xFFFFFF) << 4; + if (fitHeader->Type & 0x80) { + // Calculate FIT entry checksum + UByteArray tempFIT = model->body(fitIndex).mid(fitOffset, fitSize); + FIT_ENTRY* tempFitHeader = (FIT_ENTRY*)tempFIT.data(); + tempFitHeader->Checksum = 0; + UINT8 calculated = calculateChecksum8((const UINT8*)tempFitHeader, fitSize); + if (calculated != fitHeader->Checksum) { + msg(usprintf("Invalid FIT table checksum %02Xh, should be %02Xh", fitHeader->Checksum, calculated), fitIndex); + } + } + + // Check fit header type + if ((fitHeader->Type & 0x7F) != FIT_TYPE_HEADER) { + msg(("Invalid FIT header type"), fitIndex); + } + + // Add FIT header to fitTable + std::vector currentStrings; + currentStrings.push_back(UString("_FIT_ ")); + currentStrings.push_back(usprintf("%08Xh", fitSize)); + currentStrings.push_back(usprintf("%04Xh", fitHeader->Version)); + currentStrings.push_back(usprintf("%02Xh", fitHeader->Checksum)); + currentStrings.push_back(fitEntryTypeToUString(fitHeader->Type)); + fitTable.push_back(currentStrings); + + // Process all other entries + bool msgModifiedImageMayNotWork = false; + for (UINT32 i = 1; i < fitHeader->Size; i++) { + currentStrings.clear(); + const FIT_ENTRY* currentEntry = fitHeader + i; + + // Check entry type + switch (currentEntry->Type & 0x7F) { + case FIT_TYPE_HEADER: + msg(UString("Second FIT header found, the table is damaged"), fitIndex); + break; + + case FIT_TYPE_EMPTY: + case FIT_TYPE_MICROCODE: + break; + + case FIT_TYPE_BIOS_AC_MODULE: + case FIT_TYPE_BIOS_INIT_MODULE: + case FIT_TYPE_TPM_POLICY: + case FIT_TYPE_BIOS_POLICY_DATA: + case FIT_TYPE_TXT_CONF_POLICY: + case FIT_TYPE_AC_KEY_MANIFEST: + case FIT_TYPE_AC_BOOT_POLICY: + default: + msgModifiedImageMayNotWork = true; + break; + } + + // Add entry to fitTable + currentStrings.push_back(usprintf("%016" PRIX64, currentEntry->Address)); + currentStrings.push_back(usprintf("%08Xh", currentEntry->Size, currentEntry->Size)); + currentStrings.push_back(usprintf("%04Xh", currentEntry->Version)); + currentStrings.push_back(usprintf("%02Xh", currentEntry->Checksum)); + currentStrings.push_back(fitEntryTypeToUString(currentEntry->Type)); + fitTable.push_back(currentStrings); + } + + if (msgModifiedImageMayNotWork) + msg(UString("Opened image may not work after any modification"), fitIndex); + + return U_SUCCESS; +} + +USTATUS FfsParser::findFitRecursive(const UModelIndex & index, const UINT32 diff, UModelIndex & found, UINT32 & fitOffset) +{ + // Sanity check + if (!index.isValid()) + return U_SUCCESS; + + // Process child items + for (int i = 0; i < model->rowCount(index); i++) { + findFitRecursive(index.child(i, 0), diff, found, fitOffset); + if (found.isValid()) + 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); + for (INT32 offset = model->body(index).indexOf(FIT_SIGNATURE); + 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; + + // Check FIT address to be stored in the last VTF + if (fitAddress == storedFitAddress) { + found = index; + fitOffset = offset; + msg(usprintf("Real FIT table found at physical address %08Xh", fitAddress), found); + return U_SUCCESS; + } + else if (model->rowCount(index) == 0) // Show messages only to leaf items + msg(UString("FIT table candidate found, but not referenced from the last VTF"), index); + } + return U_SUCCESS; } @@ -2968,10 +3127,6 @@ USTATUS FfsParser::addOffsetsRecursive(const UModelIndex & index) model->addInfo(index, usprintf("Offset: %Xh\n", pdata.offset), false); } - //TODO: show FIT file fixed attribute correctly - 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++) { addOffsetsRecursive(index.child(i, 0)); diff --git a/common/ffsparser.h b/common/ffsparser.h index e809e2b..4f93d49 100644 --- a/common/ffsparser.h +++ b/common/ffsparser.h @@ -48,8 +48,8 @@ public: // Firmware image parsing USTATUS parse(const UByteArray &buffer); - // Retuns index of the last VTF after parsing is done - const UModelIndex getLastVtf() {return lastVtf;}; + // Obtain parsed FIT table + std::vector > getFitTable() const { return fitTable; } private: TreeModel *model; @@ -60,6 +60,10 @@ private: UModelIndex lastVtf; UINT32 capsuleOffsetFixup; + std::vector > fitTable; + + // First pass + 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); @@ -103,11 +107,6 @@ private: UINT32 getFileSize(const UByteArray & volume, const UINT32 fileOffset, const UINT8 ffsVersion); UINT32 getSectionSize(const UByteArray & file, const UINT32 sectionOffset, const UINT8 ffsVersion); - USTATUS performFirstPass(const UByteArray & imageFile, UModelIndex & index); - USTATUS performSecondPass(const UModelIndex & index); - USTATUS addOffsetsRecursive(const UModelIndex & index); - USTATUS addMemoryAddressesRecursive(const UModelIndex & index, const UINT32 diff); - // NVRAM parsing USTATUS parseNvramVolumeBody(const UModelIndex & index); USTATUS findNextStore(const UModelIndex & index, const UByteArray & volume, const UINT32 parentOffset, const UINT32 storeOffset, UINT32 & nextStoreOffset); @@ -130,6 +129,14 @@ private: USTATUS parseFsysStoreBody(const UModelIndex & index); USTATUS parseEvsaStoreBody(const UModelIndex & index); USTATUS parseFlashMapBody(const UModelIndex & index); + + // Second pass + USTATUS performSecondPass(const UModelIndex & index); + USTATUS addOffsetsRecursive(const UModelIndex & index); + USTATUS addMemoryAddressesRecursive(const UModelIndex & index, const UINT32 diff); + USTATUS addFixedAndCompressedRecursive(const UModelIndex & index); + USTATUS parseFit(const UModelIndex & index, const UINT32 diff); + USTATUS findFitRecursive(const UModelIndex & index, const UINT32 diff, UModelIndex & found, UINT32 & fitOffset); }; #endif // FFSPARSER_H diff --git a/common/fitparser.cpp b/common/fitparser.cpp deleted file mode 100644 index 74ab7e3..0000000 --- a/common/fitparser.cpp +++ /dev/null @@ -1,164 +0,0 @@ -/* fitparser.cpp - -Copyright (c) 2015, Nikolaj Schlej. All rights reserved. -This program and the accompanying materials -are licensed and made available under the terms and conditions of the BSD License -which accompanies this distribution. The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -*/ -#include "fitparser.h" - -USTATUS FitParser::parse(const UModelIndex & index, const UModelIndex & lastVtfIndex) -{ - // Check sanity - if (!index.isValid() || !lastVtfIndex.isValid()) - return EFI_INVALID_PARAMETER; - - // Store lastVtfIndex - lastVtf = lastVtfIndex; - - // Search for FIT - UModelIndex fitIndex; - UINT32 fitOffset; - USTATUS result = findFitRecursive(index, fitIndex, fitOffset); - if (result) - return result; - - // FIT not found - if (!fitIndex.isValid()) - return U_SUCCESS; - - // Explicitly set the item as fixed - model->setFixed(index, true); - - // Special case of FIT header - UByteArray fitBody = model->body(fitIndex); - const FIT_ENTRY* fitHeader = (const FIT_ENTRY*)(fitBody.constData() + fitOffset); - - // Check FIT checksum, if present - UINT32 fitSize = (fitHeader->Size & 0xFFFFFF) << 4; - if (fitHeader->Type & 0x80) { - // Calculate FIT entry checksum - UByteArray tempFIT = model->body(fitIndex).mid(fitOffset, fitSize); - FIT_ENTRY* tempFitHeader = (FIT_ENTRY*)tempFIT.data(); - tempFitHeader->Checksum = 0; - UINT8 calculated = calculateChecksum8((const UINT8*)tempFitHeader, fitSize); - if (calculated != fitHeader->Checksum) { - msg(usprintf("Invalid FIT table checksum %02Xh, should be %02Xh", fitHeader->Checksum, calculated), fitIndex); - } - } - - // Check fit header type - if ((fitHeader->Type & 0x7F) != FIT_TYPE_HEADER) { - msg(("Invalid FIT header type"), fitIndex); - } - - // Add FIT header to fitTable - std::vector currentStrings; - currentStrings.push_back(UString("_FIT_ ")); - currentStrings.push_back(usprintf("%08X", fitSize)); - currentStrings.push_back(usprintf("%04X", fitHeader->Version)); - currentStrings.push_back(fitEntryTypeToUString(fitHeader->Type)); - currentStrings.push_back(usprintf("%02X", fitHeader->Checksum)); - fitTable.push_back(currentStrings); - - // Process all other entries - bool msgModifiedImageMayNotWork = false; - for (UINT32 i = 1; i < fitHeader->Size; i++) { - currentStrings.clear(); - const FIT_ENTRY* currentEntry = fitHeader + i; - - // Check entry type - switch (currentEntry->Type & 0x7F) { - case FIT_TYPE_HEADER: - msg(UString("Second FIT header found, the table is damaged"), fitIndex); - break; - - case FIT_TYPE_EMPTY: - case FIT_TYPE_MICROCODE: - break; - - case FIT_TYPE_BIOS_AC_MODULE: - case FIT_TYPE_BIOS_INIT_MODULE: - case FIT_TYPE_TPM_POLICY: - case FIT_TYPE_BIOS_POLICY_DATA: - case FIT_TYPE_TXT_CONF_POLICY: - case FIT_TYPE_AC_KEY_MANIFEST: - case FIT_TYPE_AC_BOOT_POLICY: - default: - msgModifiedImageMayNotWork = true; - break; - } - - // Add entry to fitTable - currentStrings.push_back(usprintf("%016X",currentEntry->Address)); - currentStrings.push_back(usprintf("%08X", currentEntry->Size)); - currentStrings.push_back(usprintf("%04X", currentEntry->Version)); - currentStrings.push_back(fitEntryTypeToUString(currentEntry->Type)); - currentStrings.push_back(usprintf("%02X", currentEntry->Checksum)); - fitTable.push_back(currentStrings); - } - - if (msgModifiedImageMayNotWork) - msg(("Opened image may not work after any modification")); - - return U_SUCCESS; -} - -UString FitParser::fitEntryTypeToUString(UINT8 type) -{ - switch (type & 0x7F) { - case FIT_TYPE_HEADER: return ("Header "); - case FIT_TYPE_MICROCODE: return ("Microcode "); - case FIT_TYPE_BIOS_AC_MODULE: return ("BIOS ACM "); - case FIT_TYPE_BIOS_INIT_MODULE: return ("BIOS Init "); - case FIT_TYPE_TPM_POLICY: return ("TPM Policy "); - case FIT_TYPE_BIOS_POLICY_DATA: return ("BIOS Policy Data "); - case FIT_TYPE_TXT_CONF_POLICY: return ("TXT Configuration Policy"); - case FIT_TYPE_AC_KEY_MANIFEST: return ("BootGuard Key Manifest "); - case FIT_TYPE_AC_BOOT_POLICY: return ("BootGuard Boot Policy "); - case FIT_TYPE_EMPTY: return ("Empty "); - default: return ("Unknown "); - } -} - -USTATUS FitParser::findFitRecursive(const UModelIndex & index, UModelIndex & found, UINT32 & fitOffset) -{ - // Sanity check - if (!index.isValid()) - return U_SUCCESS; - - // Process child items - for (int i = 0; i < model->rowCount(index); i++) { - findFitRecursive(index.child(i, 0), found, fitOffset); - if (found.isValid()) - return U_SUCCESS; - } - - // Get parsing data for the current item - PARSING_DATA pdata = parsingDataFromUModelIndex(index); - - // Check for all FIT signatures in item's body - for (INT32 offset = model->body(index).indexOf(FIT_SIGNATURE); - offset >= 0; - offset = model->body(index).indexOf(FIT_SIGNATURE, offset + 1)) { - // FIT candidate found, calculate it's physical address - UINT32 fitAddress = pdata.address + model->header(index).size() + (UINT32)offset; - - // Check FIT address to be in the last VTF - UByteArray lastVtfBody = model->body(lastVtf); - if (*(const UINT32*)(lastVtfBody.constData() + lastVtfBody.size() - FIT_POINTER_OFFSET) == fitAddress) { - found = index; - fitOffset = offset; - msg(usprintf("Real FIT table found at physical address %Xh", fitAddress), found); - return U_SUCCESS; - } - else if (model->rowCount(index) == 0) // Show messages only to leaf items - msg(("FIT table candidate found, but not referenced from the last VTF"), index); - } - - return U_SUCCESS; -} \ No newline at end of file diff --git a/common/fitparser.h b/common/fitparser.h deleted file mode 100644 index 3b4dac8..0000000 --- a/common/fitparser.h +++ /dev/null @@ -1,59 +0,0 @@ -/* fitparser.h - -Copyright (c) 2015, Nikolaj Schlej. All rights reserved. -This program and the accompanying materials -are licensed and made available under the terms and conditions of the BSD License -which accompanies this distribution. The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -*/ - -#ifndef FITPARSER_H -#define FITPARSER_H - -#include - -#include "ustring.h" -#include "ubytearray.h" -#include "treemodel.h" -#include "utility.h" -#include "parsingdata.h" -#include "fit.h" -#include "types.h" -#include "treemodel.h" - -class TreeModel; - -class FitParser -{ -public: - // Default constructor and destructor - FitParser(TreeModel* treeModel) : model(treeModel) {} - ~FitParser() {} - - // Returns messages - std::vector > getMessages() const { return messagesVector; }; - // Clears messages - void clearMessages() { messagesVector.clear(); } - - USTATUS parse(const UModelIndex & index, const UModelIndex & lastVtf); - std::vector > getFitTable() const { return fitTable; } - -private: - TreeModel *model; - std::vector > messagesVector; - UModelIndex lastVtf; - std::vector > fitTable; - - USTATUS findFitRecursive(const UModelIndex & index, UModelIndex & found, UINT32 & fitOffset); - UString fitEntryTypeToUString(UINT8 type); - - // Message helper - void msg(const UString & message, const UModelIndex &index = UModelIndex()) { - messagesVector.push_back(std::pair(message, index)); - } -}; - -#endif // FITPARSER_H diff --git a/common/types.cpp b/common/types.cpp index ac90a58..4a3a4d9 100644 --- a/common/types.cpp +++ b/common/types.cpp @@ -13,6 +13,7 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "ustring.h" #include "types.h" #include "ffs.h" +#include "fit.h" UString regionTypeToUString(const UINT8 type) { @@ -161,4 +162,21 @@ UString actionTypeToUString(const UINT8 action) } return UString("Unknown"); +} + +UString fitEntryTypeToUString(const UINT8 type) +{ + switch (type & 0x7F) { + case FIT_TYPE_HEADER: return ("FIT Header "); + case FIT_TYPE_MICROCODE: return ("Microcode "); + case FIT_TYPE_BIOS_AC_MODULE: return ("BIOS ACM "); + case FIT_TYPE_BIOS_INIT_MODULE: return ("BIOS Init "); + case FIT_TYPE_TPM_POLICY: return ("TPM Policy "); + case FIT_TYPE_BIOS_POLICY_DATA: return ("BIOS Policy Data "); + case FIT_TYPE_TXT_CONF_POLICY: return ("TXT Configuration Policy"); + case FIT_TYPE_AC_KEY_MANIFEST: return ("BootGuard Key Manifest "); + case FIT_TYPE_AC_BOOT_POLICY: return ("BootGuard Boot Policy "); + case FIT_TYPE_EMPTY: return ("Empty "); + default: return ("Unknown "); + } } \ No newline at end of file diff --git a/common/types.h b/common/types.h index b114f3a..8480dbe 100644 --- a/common/types.h +++ b/common/types.h @@ -144,5 +144,6 @@ extern UString itemTypeToUString(const UINT8 type); extern UString itemSubtypeToUString(const UINT8 type, const UINT8 subtype); extern UString compressionTypeToUString(const UINT8 algorithm); extern UString regionTypeToUString(const UINT8 type); +extern UString fitEntryTypeToUString(const UINT8 type); #endif // TYPES_H diff --git a/qhexedit2/qhexedit.h b/qhexedit2/qhexedit.h index 23ce871..0c6659a 100644 --- a/qhexedit2/qhexedit.h +++ b/qhexedit2/qhexedit.h @@ -113,14 +113,14 @@ class QHexEdit : public QAbstractScrollArea */ Q_PROPERTY(QColor selectionColor READ selectionColor WRITE setSelectionColor) - /*! Porperty readOnly sets (setReadOnly()) or gets (isReadOnly) the mode + /*! Property readOnly sets (setReadOnly()) or gets (isReadOnly) the mode in which the editor works. In readonly mode the the user can only navigate through the data and select data; modifying is not possible. This property's default is false. */ Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly) - /*! Porperty upperCase sets (setUpperCase()) or gets (isUpperCase) the case of hex + /*! Property upperCase sets (setUpperCase()) or gets (isUpperCase) the case of hex data. Default is lowercase. */ Q_PROPERTY(bool upperCase READ isUpperCase WRITE setUpperCase)