From 4160a6a58023f65daf17c05926bc148a009ae0b1 Mon Sep 17 00:00:00 2001 From: Cr4sh Date: Thu, 3 Nov 2016 02:40:38 +0700 Subject: [PATCH] NE Alpha 35 --- UEFIDump/uefidump.cpp | 20 +++-- UEFIDump/uefidump_main.cpp | 2 +- UEFIExtract/uefiextract_main.cpp | 21 ++--- UEFIFind/uefifind.cpp | 2 +- UEFIFind/uefifind.h | 1 + UEFITool/gotooffsetdialog.h | 23 +++++ UEFITool/gotooffsetdialog.ui | 138 ++++++++++++++++++++++++++++++ UEFITool/searchdialog.cpp | 2 +- UEFITool/uefitool.cpp | 141 +++++++++++++++++++++++-------- UEFITool/uefitool.h | 15 +++- UEFITool/uefitool.pro | 8 +- UEFITool/uefitool.ui | 67 +++++++++++++-- bstrlib/bstrlib.c | 2 +- common/ffsbuilder.cpp | 14 +++ common/ffsops.cpp | 2 + common/ffsparser.cpp | 52 ++++++++++-- common/ffsparser.h | 10 +-- common/nvramparser.cpp | 13 +-- common/peimage.cpp | 2 +- common/treeitem.cpp | 2 +- common/treemodel.cpp | 23 +++++ common/treemodel.h | 6 +- common/ubytearray.h | 2 +- common/utility.cpp | 3 +- 24 files changed, 477 insertions(+), 94 deletions(-) create mode 100644 UEFITool/gotooffsetdialog.h create mode 100644 UEFITool/gotooffsetdialog.ui diff --git a/UEFIDump/uefidump.cpp b/UEFIDump/uefidump.cpp index c8daf79..df2849d 100644 --- a/UEFIDump/uefidump.cpp +++ b/UEFIDump/uefidump.cpp @@ -13,6 +13,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "uefidump.h" #include "../common/ffs.h" +#include "../common/utility.h" #include #include #include @@ -77,17 +78,18 @@ USTATUS UEFIDumper::dump(const UByteArray & buffer, const UString & inPath, cons } // Show FIT table - std::vector > fitTable = ffsParser.getFitTable(); + std::vector, UModelIndex > > fitTable = ffsParser.getFitTable(); if (fitTable.size()) { - std::cout << "-------------------------------------------------------------------" << std::endl; - std::cout << " Address | Size | Ver | CS | Type " << std::endl; - std::cout << "-------------------------------------------------------------------" << std::endl; + std::cout << "-------------------------------------------------------------------------" << std::endl; + std::cout << " Address | Size | Ver | CS | Type / Info " << std::endl; + std::cout << "-------------------------------------------------------------------------" << std::endl; for (size_t i = 0; i < fitTable.size(); i++) { - std::cout << (const char*)fitTable[i][0].toLocal8Bit() << " | " - << (const char*)fitTable[i][1].toLocal8Bit() << " | " - << (const char*)fitTable[i][2].toLocal8Bit() << " | " - << (const char*)fitTable[i][3].toLocal8Bit() << " | " - << (const char*)fitTable[i][4].toLocal8Bit() << std::endl; + std::cout << (const char*)fitTable[i].first[0].toLocal8Bit() << " | " + << (const char*)fitTable[i].first[1].toLocal8Bit() << " | " + << (const char*)fitTable[i].first[2].toLocal8Bit() << " | " + << (const char*)fitTable[i].first[3].toLocal8Bit() << " | " + << (const char*)fitTable[i].first[4].toLocal8Bit() << " | " + << (const char*)fitTable[i].first[5].toLocal8Bit() << std::endl; } } diff --git a/UEFIDump/uefidump_main.cpp b/UEFIDump/uefidump_main.cpp index be1a153..1c28c24 100644 --- a/UEFIDump/uefidump_main.cpp +++ b/UEFIDump/uefidump_main.cpp @@ -29,7 +29,7 @@ int main(int argc, char *argv[]) return (uefidumper.dump(buffer, UString(argv[1])) != U_SUCCESS); } - std::cout << "UEFIDump 0.1.2" << std::endl << std::endl + std::cout << "UEFIDump 0.1.3" << std::endl << std::endl << "Usage: UEFIDump imagefile" << std::endl; return 0; } diff --git a/UEFIExtract/uefiextract_main.cpp b/UEFIExtract/uefiextract_main.cpp index 4bdc732..b88df0a 100644 --- a/UEFIExtract/uefiextract_main.cpp +++ b/UEFIExtract/uefiextract_main.cpp @@ -61,17 +61,18 @@ int main(int argc, char *argv[]) } // Get last VTF - std::vector > fitTable = ffsParser.getFitTable(); + std::vector, QModelIndex > > fitTable = ffsParser.getFitTable(); if (fitTable.size()) { - std::cout << "-------------------------------------------------------------------" << std::endl; - std::cout << " Address | Size | Ver | CS | Type " << std::endl; - std::cout << "-------------------------------------------------------------------" << std::endl; + std::cout << "---------------------------------------------------------------------------" << std::endl; + std::cout << " Address | Size | Ver | CS | Type / Info " << 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; + std::cout << fitTable[i].first[0].toLatin1().constData() << " | " + << fitTable[i].first[1].toLatin1().constData() << " | " + << fitTable[i].first[2].toLatin1().constData() << " | " + << fitTable[i].first[3].toLatin1().constData() << " | " + << fitTable[i].first[4].toLatin1().constData() << " | " + << fitTable[i].first[5].toLatin1().constData() << std::endl; } } @@ -120,7 +121,7 @@ int main(int argc, char *argv[]) } } // If parameters are different, show version and usage information - std::cout << "UEFIExtract 0.13.1" << std::endl << std::endl + std::cout << "UEFIExtract 0.13.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 dump - only generate dump, no report needed." << std::endl diff --git a/UEFIFind/uefifind.cpp b/UEFIFind/uefifind.cpp index ba6a376..97b374c 100644 --- a/UEFIFind/uefifind.cpp +++ b/UEFIFind/uefifind.cpp @@ -70,7 +70,7 @@ USTATUS UEFIFind::find(const UINT8 mode, const bool count, const QString & hexPa return U_SUCCESS; } - for (std::set >::const_iterator citer = files.cbegin(); citer != files.cend(); ++citer) { + for (std::set >::const_iterator citer = files.begin(); citer != files.end(); ++citer) { QByteArray data(16, '\x00'); std::pair indexes = *citer; if (!model->hasEmptyHeader(indexes.first)) diff --git a/UEFIFind/uefifind.h b/UEFIFind/uefifind.h index 69cd1a5..c4f53c8 100644 --- a/UEFIFind/uefifind.h +++ b/UEFIFind/uefifind.h @@ -14,6 +14,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #ifndef UEFIFIND_H #define UEFIFIND_H +#include #include #include diff --git a/UEFITool/gotooffsetdialog.h b/UEFITool/gotooffsetdialog.h new file mode 100644 index 0000000..ce2b1dd --- /dev/null +++ b/UEFITool/gotooffsetdialog.h @@ -0,0 +1,23 @@ +#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/gotooffsetdialog.ui b/UEFITool/gotooffsetdialog.ui new file mode 100644 index 0000000..bad9d1c --- /dev/null +++ b/UEFITool/gotooffsetdialog.ui @@ -0,0 +1,138 @@ + + + GoToOffsetDialog + + + + 0 + 0 + 204 + 70 + + + + Go to offset + + + false + + + + 5 + + + 5 + + + 5 + + + 5 + + + 5 + + + + + + + + + 5 + + + 5 + + + 5 + + + 5 + + + 5 + + + + + Select tree item at: + + + + + + + + 0 + 0 + + + + + + + 0x + + + 1000000000 + + + 16 + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + buttonBox + + + + + buttonBox + accepted() + GoToOffsetDialog + accept() + + + 182 + 185 + + + 157 + 194 + + + + + buttonBox + rejected() + GoToOffsetDialog + reject() + + + 182 + 185 + + + 286 + 194 + + + + + diff --git a/UEFITool/searchdialog.cpp b/UEFITool/searchdialog.cpp index c9b716d..74f37b9 100644 --- a/UEFITool/searchdialog.cpp +++ b/UEFITool/searchdialog.cpp @@ -14,7 +14,7 @@ #include "searchdialog.h" SearchDialog::SearchDialog(QWidget *parent) : -QDialog(parent), +QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint), ui(new Ui::SearchDialog), hexValidator(QRegExp("([0-9a-fA-F\\. ])*")), guidValidator(QRegExp("[0-9a-fA-F\\.]{8}-[0-9a-fA-F\\.]{4}-[0-9a-fA-F\\.]{4}-[0-9a-fA-F\\.]{4}-[0-9a-fA-F\\.]{12}")) diff --git a/UEFITool/uefitool.cpp b/UEFITool/uefitool.cpp index e237b2f..399c590 100644 --- a/UEFITool/uefitool.cpp +++ b/UEFITool/uefitool.cpp @@ -14,10 +14,11 @@ #include "uefitool.h" #include "ui_uefitool.h" + UEFITool::UEFITool(QWidget *parent) : QMainWindow(parent), -ui(new Ui::UEFITool), -version(tr("NE Alpha34")) +ui(new Ui::UEFITool), +version(tr("NE Alpha35")) { clipboard = QApplication::clipboard(); @@ -25,6 +26,7 @@ version(tr("NE Alpha34")) ui->setupUi(this); searchDialog = new SearchDialog(this); hexViewDialog = new HexViewDialog(this); + goToOffsetDialog = new GoToOffsetDialog(this); model = NULL; ffsParser = NULL; ffsFinder = NULL; @@ -54,6 +56,7 @@ version(tr("NE Alpha34")) 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(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(writeSettings())); // Enable Drag-and-Drop actions @@ -78,6 +81,7 @@ version(tr("NE Alpha34")) searchDialog->ui->guidEdit->setFont(font); searchDialog->ui->hexEdit->setFont(font); hexViewDialog->setFont(font); + goToOffsetDialog->ui->hexSpinBox->setFont(font); // Initialize non-persistent data init(); @@ -113,18 +117,18 @@ void UEFITool::init() setWindowTitle(tr("UEFITool %1").arg(version)); // Disable menus - ui->menuCapsuleActions->setDisabled(true); - ui->menuImageActions->setDisabled(true); - ui->menuRegionActions->setDisabled(true); - ui->menuPaddingActions->setDisabled(true); - ui->menuVolumeActions->setDisabled(true); - ui->menuFileActions->setDisabled(true); - ui->menuSectionActions->setDisabled(true); - ui->menuStoreActions->setDisabled(true); - ui->menuVariableActions->setDisabled(true); - - ui->actionMessagesCopy->setDisabled(true); - ui->actionMessagesCopyAll->setDisabled(true); + ui->actionSearch->setEnabled(false); + ui->actionGoToOffset->setEnabled(false); + ui->menuCapsuleActions->setEnabled(false); + ui->menuImageActions->setEnabled(false); + ui->menuRegionActions->setEnabled(false); + ui->menuPaddingActions->setEnabled(false); + ui->menuVolumeActions->setEnabled(false); + ui->menuFileActions->setEnabled(false); + ui->menuSectionActions->setEnabled(false); + ui->menuStoreActions->setEnabled(false); + ui->menuVariableActions->setEnabled(false); + ui->menuMessageActions->setEnabled(false); // Create new model ... delete model; @@ -137,12 +141,24 @@ void UEFITool::init() // Connect connect(ui->structureTreeView->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(populateUi(const QModelIndex &))); + connect(ui->structureTreeView->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), + this, SLOT(populateUi(const QItemSelection &))); connect(ui->parserMessagesListWidget, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(scrollTreeView(QListWidgetItem*))); connect(ui->parserMessagesListWidget, 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*))); connect(ui->builderMessagesListWidget, SIGNAL(itemEntered(QListWidgetItem*)), this, SLOT(enableMessagesCopyActions(QListWidgetItem*))); + connect(ui->fitTableWidget, SIGNAL(itemDoubleClicked(QTableWidgetItem*)), this, SLOT(scrollTreeView(QTableWidgetItem*))); + connect(ui->messagesTabWidget, SIGNAL(currentChanged(int)), this, SLOT(currentTabChanged(int))); +} + +void UEFITool::populateUi(const QItemSelection &selected) +{ + if (selected.isEmpty()) + return; + + populateUi(selected.indexes().at(0)); } void UEFITool::populateUi(const QModelIndex ¤t) @@ -200,7 +216,8 @@ void UEFITool::populateUi(const QModelIndex ¤t) //ui->actionInsertAfter->setEnabled(type == Types::File || type == Types::Section); //ui->actionReplace->setEnabled((type == Types::Region && subtype != Subtypes::DescriptorRegion) || type == Types::Volume || type == Types::File || type == Types::Section); //ui->actionReplaceBody->setEnabled(type == Types::Volume || type == Types::File || type == Types::Section); - ui->actionMessagesCopy->setEnabled(false); + + ui->menuMessageActions->setEnabled(false); } bool UEFITool::enableExtractBodyUncompressed(const QModelIndex ¤t) @@ -296,6 +313,19 @@ void UEFITool::hexView() hexViewDialog->exec(); } +void UEFITool::goToOffset() +{ + if (goToOffsetDialog->exec() != QDialog::Accepted) + return; + + UINT32 offset = (UINT32)goToOffsetDialog->ui->hexSpinBox->value(); + QModelIndex index = model->findByOffset(offset); + if (index.isValid()) { + ui->structureTreeView->scrollTo(index, QAbstractItemView::PositionAtCenter); + ui->structureTreeView->selectionModel()->select(index, QItemSelectionModel::Select | QItemSelectionModel::Rows | QItemSelectionModel::Clear); + } +} + void UEFITool::goToData() { QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex(); @@ -334,6 +364,7 @@ void UEFITool::goToData() void UEFITool::insert(const UINT8 mode) { U_UNUSED_PARAMETER(mode); + /*QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex(); if (!index.isValid()) return; @@ -413,6 +444,9 @@ void UEFITool::replaceBody() void UEFITool::replace(const UINT8 mode) { + U_UNUSED_PARAMETER(mode); + + /* QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex(); if (!index.isValid()) return; @@ -502,6 +536,7 @@ void UEFITool::replace(const UINT8 mode) return; } ui->actionSaveImageFile->setEnabled(true); + */ } void UEFITool::extractAsIs() @@ -626,22 +661,26 @@ void UEFITool::extract(const UINT8 mode) void UEFITool::rebuild() { + /* UModelIndex index = ui->structureTreeView->selectionModel()->currentIndex(); if (!index.isValid()) return; if (U_SUCCESS == ffsOps->rebuild(index)) ui->actionSaveImageFile->setEnabled(true); + */ } void UEFITool::remove() { + /* UModelIndex index = ui->structureTreeView->selectionModel()->currentIndex(); if (!index.isValid()) return; if (U_SUCCESS == ffsOps->remove(index)) ui->actionSaveImageFile->setEnabled(true); + */ } void UEFITool::about() @@ -671,7 +710,7 @@ void UEFITool::exit() void UEFITool::saveImageFile() { - QString path = QFileDialog::getSaveFileName(this, tr("Save BIOS image file"), currentDir, "BIOS image files (*.rom *.bin *.cap *.scap *.bio *.fd *.wph *.dec);;All files (*)"); + /*QString path = QFileDialog::getSaveFileName(this, tr("Save BIOS image file"), currentDir, "BIOS image files (*.rom *.bin *.cap *.scap *.bio *.fd *.wph *.dec);;All files (*)"); if (path.isEmpty()) return; @@ -699,6 +738,7 @@ void UEFITool::saveImageFile() outputFile.close(); if (QMessageBox::Yes == QMessageBox::information(this, tr("Image build successful"), tr("Open the resulting file?"), QMessageBox::Yes, QMessageBox::No)) openImageFile(path); + */ } void UEFITool::openImageFile() @@ -758,6 +798,11 @@ void UEFITool::openImageFile(QString path) delete ffsOps; ffsOps = new FfsOperations(model); + // Set max offset and enable goToOffset + // FIXME: doesn't work properly + //goToOffsetDialog->ui->hexSpinBox->setMaximum(buffer.size() - 1); + ui->actionGoToOffset->setEnabled(true); + // Enable or disable FIT tab showFitTable(); @@ -765,6 +810,14 @@ void UEFITool::openImageFile(QString path) currentDir = fileInfo.absolutePath(); } +void UEFITool::enableMessagesCopyActions(QListWidgetItem* item) +{ + ui->menuMessageActions->setEnabled(item != NULL); + ui->actionMessagesCopy->setEnabled(item != NULL); + ui->actionMessagesCopyAll->setEnabled(item != NULL); + ui->actionMessagesClear->setEnabled(item != NULL); +} + void UEFITool::copyMessage() { clipboard->clear(); @@ -797,12 +850,6 @@ void UEFITool::copyAllMessages() } } -void UEFITool::enableMessagesCopyActions(QListWidgetItem* item) -{ - ui->actionMessagesCopy->setEnabled(item != NULL); - ui->actionMessagesCopyAll->setEnabled(item != NULL); -} - void UEFITool::clearMessages() { if (ui->messagesTabWidget->currentIndex() == 0) { // Parser tab @@ -818,8 +865,10 @@ void UEFITool::clearMessages() ui->builderMessagesListWidget->clear(); } + ui->menuMessageActions->setEnabled(false); ui->actionMessagesCopy->setEnabled(false); ui->actionMessagesCopyAll->setEnabled(false); + ui->actionMessagesClear->setEnabled(false); } void UEFITool::dragEnterEvent(QDragEnterEvent* event) @@ -843,7 +892,9 @@ void UEFITool::showParserMessages() std::vector > messages = ffsParser->getMessages(); std::pair msg; foreach (msg, messages) { - ui->parserMessagesListWidget->addItem(new MessageListItem(msg.first, NULL, 0, msg.second)); + QListWidgetItem* item = new QListWidgetItem(msg.first, NULL, 0); + item->setData(Qt::UserRole, msg.second); + ui->parserMessagesListWidget->addItem(item); } ui->messagesTabWidget->setCurrentIndex(0); @@ -859,7 +910,9 @@ void UEFITool::showFinderMessages() std::vector > messages = ffsFinder->getMessages(); std::pair msg; foreach (msg, messages) { - ui->finderMessagesListWidget->addItem(new MessageListItem(msg.first, NULL, 0, msg.second)); + QListWidgetItem* item = new QListWidgetItem(msg.first, NULL, 0); + item->setData(Qt::UserRole, msg.second); + ui->finderMessagesListWidget->addItem(item); } ui->messagesTabWidget->setCurrentIndex(2); @@ -875,7 +928,9 @@ void UEFITool::showBuilderMessages() std::vector > messages = ffsBuilder->getMessages(); std::pair msg; foreach (msg, messages) { - ui->builderMessagesListWidget->addItem(new MessageListItem(msg.first, NULL, 0, msg.second)); + QListWidgetItem* item = new QListWidgetItem(msg.first, NULL, 0); + item->setData(Qt::UserRole, msg.second); + ui->builderMessagesListWidget->addItem(item); } ui->messagesTabWidget->setCurrentIndex(3); @@ -884,8 +939,16 @@ void UEFITool::showBuilderMessages() void UEFITool::scrollTreeView(QListWidgetItem* item) { - MessageListItem* messageItem = static_cast(item); - QModelIndex index = messageItem->index(); + QModelIndex index = item->data(Qt::UserRole).toModelIndex(); + if (index.isValid()) { + ui->structureTreeView->scrollTo(index, QAbstractItemView::PositionAtCenter); + ui->structureTreeView->selectionModel()->select(index, QItemSelectionModel::Select | QItemSelectionModel::Rows | QItemSelectionModel::Clear); + } +} + +void UEFITool::scrollTreeView(QTableWidgetItem* item) +{ + QModelIndex index = item->data(Qt::UserRole).toModelIndex(); if (index.isValid()) { ui->structureTreeView->scrollTo(index, QAbstractItemView::PositionAtCenter); ui->structureTreeView->selectionModel()->select(index, QItemSelectionModel::Select | QItemSelectionModel::Rows | QItemSelectionModel::Clear); @@ -897,7 +960,7 @@ void UEFITool::contextMenuEvent(QContextMenuEvent* event) if (ui->parserMessagesListWidget->underMouse() || ui->finderMessagesListWidget->underMouse() || ui->builderMessagesListWidget->underMouse()) { - ui->menuMessages->exec(event->globalPos()); + ui->menuMessageActions->exec(event->globalPos()); return; } @@ -970,7 +1033,7 @@ void UEFITool::writeSettings() void UEFITool::showFitTable() { - std::vector > fitTable = ffsParser->getFitTable(); + std::vector, UModelIndex> > fitTable = ffsParser->getFitTable(); if (fitTable.empty()) { // Disable FIT tab ui->messagesTabWidget->setTabEnabled(1, false); @@ -983,8 +1046,8 @@ void UEFITool::showFitTable() // Set up the FIT table ui->fitTableWidget->clear(); ui->fitTableWidget->setRowCount(fitTable.size()); - ui->fitTableWidget->setColumnCount(5); - ui->fitTableWidget->setHorizontalHeaderLabels(QStringList() << tr("Address") << tr("Size") << tr("Version") << tr("Checksum") << tr("Type")); + ui->fitTableWidget->setColumnCount(6); + ui->fitTableWidget->setHorizontalHeaderLabels(QStringList() << tr("Address") << tr("Size") << tr("Version") << tr("Checksum") << tr("Type") << tr("Information")); ui->fitTableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); ui->fitTableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); ui->fitTableWidget->setSelectionMode(QAbstractItemView::SingleSelection); @@ -992,8 +1055,10 @@ void UEFITool::showFitTable() // Add all data to the table widget for (size_t i = 0; i < fitTable.size(); i++) { - for (UINT8 j = 0; j < 5; j++) { - ui->fitTableWidget->setItem(i, j, new QTableWidgetItem(fitTable[i][j])); + for (UINT8 j = 0; j < 6; j++) { + QTableWidgetItem* item = new QTableWidgetItem(fitTable[i].first[j]); + item->setData(Qt::UserRole, fitTable[i].second); + ui->fitTableWidget->setItem(i, j, item); } } @@ -1001,3 +1066,13 @@ void UEFITool::showFitTable() ui->fitTableWidget->resizeRowsToContents(); ui->messagesTabWidget->setCurrentIndex(1); } + +void UEFITool::currentTabChanged(int index) +{ + U_UNUSED_PARAMETER(index); + + ui->menuMessageActions->setEnabled(false); + ui->actionMessagesCopy->setEnabled(false); + ui->actionMessagesCopyAll->setEnabled(false); + ui->actionMessagesClear->setEnabled(false); +} \ No newline at end of file diff --git a/UEFITool/uefitool.h b/UEFITool/uefitool.h index 6f6f40a..0c9eaa2 100644 --- a/UEFITool/uefitool.h +++ b/UEFITool/uefitool.h @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -42,8 +43,8 @@ #include "../common/ffsbuilder.h" #include "searchdialog.h" +#include "gotooffsetdialog.h" #include "hexviewdialog.h" -#include "messagelistitem.h" #include "ffsfinder.h" namespace Ui { @@ -63,16 +64,20 @@ public: private slots: void init(); + void populateUi(const QItemSelection &selected); void populateUi(const QModelIndex ¤t); - void scrollTreeView(QListWidgetItem* item); + void scrollTreeView(QListWidgetItem* item); // For messages + void scrollTreeView(QTableWidgetItem* item); // For FIT table entries void openImageFile(); void openImageFileInNewWindow(); void saveImageFile(); + + void search(); + void goToOffset(); void hexView(); - void goToData(); void extract(const UINT8 mode); @@ -104,6 +109,8 @@ private slots: void exit(); void writeSettings(); + void currentTabChanged(int index); + private: Ui::UEFITool* ui; TreeModel* model; @@ -113,6 +120,7 @@ private: FfsBuilder* ffsBuilder; SearchDialog* searchDialog; HexViewDialog* hexViewDialog; + GoToOffsetDialog* goToOffsetDialog; QClipboard* clipboard; QString currentDir; QString currentProgramPath; @@ -128,6 +136,7 @@ private: void showFinderMessages(); void showFitTable(); void showBuilderMessages(); + }; #endif // UEFITOOL_H diff --git a/UEFITool/uefitool.pro b/UEFITool/uefitool.pro index b2832db..34e23e3 100644 --- a/UEFITool/uefitool.pro +++ b/UEFITool/uefitool.pro @@ -8,7 +8,6 @@ DEFINES += "U_ENABLE_NVRAM_PARSING_SUPPORT" HEADERS += uefitool.h \ searchdialog.h \ hexviewdialog.h \ - messagelistitem.h \ guidlineedit.h \ ffsfinder.h \ ../common/nvram.h \ @@ -36,13 +35,13 @@ HEADERS += uefitool.h \ ../common/ubytearray.h \ ../qhexedit2/qhexedit.h \ ../qhexedit2/chunks.h \ - ../qhexedit2/commands.h + ../qhexedit2/commands.h \ + gotooffsetdialog.h SOURCES += uefitool_main.cpp \ uefitool.cpp \ searchdialog.cpp \ hexviewdialog.cpp \ - messagelistitem.cpp \ guidlineedit.cpp \ ffsfinder.cpp \ ../common/nvram.cpp \ @@ -72,7 +71,8 @@ SOURCES += uefitool_main.cpp \ FORMS += uefitool.ui \ searchdialog.ui \ - hexviewdialog.ui + hexviewdialog.ui \ + gotooffsetdialog.ui RC_FILE = uefitool.rc diff --git a/UEFITool/uefitool.ui b/UEFITool/uefitool.ui index 886435e..b4f002f 100644 --- a/UEFITool/uefitool.ui +++ b/UEFITool/uefitool.ui @@ -284,8 +284,6 @@ - - @@ -300,6 +298,9 @@ &Action + + false + &Capsule @@ -309,6 +310,9 @@ + + false + &Image @@ -317,6 +321,9 @@ + + false + &Region @@ -329,6 +336,9 @@ + + false + &Padding @@ -337,6 +347,9 @@ + + false + &Volume @@ -353,6 +366,9 @@ + + false + &File @@ -373,6 +389,9 @@ + + false + &Section @@ -393,7 +412,10 @@ - + + + false + &Messages @@ -403,6 +425,9 @@ + + false + Variable @@ -424,6 +449,9 @@ + + false + S&tore @@ -441,6 +469,9 @@ + + + @@ -451,7 +482,7 @@ - + @@ -609,6 +640,9 @@ About &Qt + + Shift+F1 + QAction::AboutQtRole @@ -633,6 +667,9 @@ + + false + Clea&r @@ -658,6 +695,9 @@ + + false + &Copy @@ -666,6 +706,9 @@ + + false + Copy &all @@ -700,7 +743,10 @@ false - Go to &data + Go &to data + + + Ctrl+T @@ -714,6 +760,17 @@ Ctrl+D + + + false + + + &Go to offset... + + + Ctrl+G + + diff --git a/bstrlib/bstrlib.c b/bstrlib/bstrlib.c index aa2c000..9e1d64a 100644 --- a/bstrlib/bstrlib.c +++ b/bstrlib/bstrlib.c @@ -557,7 +557,7 @@ size_t len; a->slen = i; len = strlen (str + i); - if (len + 1 > INT_MAX - i || + if (len + 1 > (size_t)(INT_MAX - i) || 0 > balloc (a, (int) (i + len + 1))) return BSTR_ERR; bBlockCopy (a->data + i, str + i, (size_t) len + 1); a->slen += (int) len; diff --git a/common/ffsbuilder.cpp b/common/ffsbuilder.cpp index fcdffde..d31e512 100644 --- a/common/ffsbuilder.cpp +++ b/common/ffsbuilder.cpp @@ -19,6 +19,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. USTATUS FfsBuilder::erase(const UModelIndex & index, UByteArray & erased) { + U_UNUSED_PARAMETER(erased); + // Sanity check if (!index.isValid()) return U_INVALID_PARAMETER; @@ -358,21 +360,33 @@ USTATUS FfsBuilder::buildFreeSpace(const UModelIndex & index, UByteArray & freeS USTATUS FfsBuilder::buildVolume(const UModelIndex & index, UByteArray & volume) { + U_UNUSED_PARAMETER(index); + U_UNUSED_PARAMETER(volume); + return U_NOT_IMPLEMENTED; } USTATUS FfsBuilder::buildPadFile(const UModelIndex & index, UByteArray & padFile) { + U_UNUSED_PARAMETER(index); + U_UNUSED_PARAMETER(padFile); + return U_NOT_IMPLEMENTED; } USTATUS FfsBuilder::buildFile(const UModelIndex & index, UByteArray & file) { + U_UNUSED_PARAMETER(index); + U_UNUSED_PARAMETER(file); + return U_NOT_IMPLEMENTED; } USTATUS FfsBuilder::buildSection(const UModelIndex & index, UByteArray & section) { + U_UNUSED_PARAMETER(index); + U_UNUSED_PARAMETER(section); + return U_NOT_IMPLEMENTED; } diff --git a/common/ffsops.cpp b/common/ffsops.cpp index 3922e6b..6f94039 100644 --- a/common/ffsops.cpp +++ b/common/ffsops.cpp @@ -65,6 +65,8 @@ USTATUS FfsOperations::extract(const UModelIndex & index, UString & name, UByteA USTATUS FfsOperations::replace(const UModelIndex & index, const UString & data, const UINT8 mode) { + U_UNUSED_PARAMETER(data); + // Sanity check if (!index.isValid()) return U_INVALID_PARAMETER; diff --git a/common/ffsparser.cpp b/common/ffsparser.cpp index 38ef060..49c9002 100644 --- a/common/ffsparser.cpp +++ b/common/ffsparser.cpp @@ -15,7 +15,7 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include #include -#include +#include #include "descriptor.h" #include "ffs.h" @@ -478,9 +478,6 @@ USTATUS FfsParser::parseIntelImage(const UByteArray & intelImage, const UINT32 l descriptorMap->NumberOfPchStraps, descriptorMap->NumberOfProcStraps); - // Construct parsing data - //pdata.offset = localOffset; - // Add Intel image tree item index = model->addItem(localOffset, Types::Image, Subtypes::IntelImage, name, UString(), info, UByteArray(), intelImage, UByteArray(), Fixed, parent); @@ -2866,6 +2863,7 @@ USTATUS FfsParser::parseFit(const UModelIndex & index, const UINT32 diff) return U_SUCCESS; // Explicitly set the item as fixed + // TODO: update info model->setFixed(fitIndex, true); // Special case of FIT header @@ -2890,20 +2888,24 @@ USTATUS FfsParser::parseFit(const UModelIndex & index, const UINT32 diff) msg(("Invalid FIT header type"), fitIndex); - // Add FIT header to fitTable + // Add FIT header 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); + currentStrings.push_back(UString("")); // Empty info for FIT header + fitTable.push_back(std::pair, UModelIndex>(currentStrings, fitIndex)); // Process all other entries bool msgModifiedImageMayNotWork = false; + UModelIndex itemIndex; + UString info; for (UINT32 i = 1; i < fitHeader->Size; i++) { currentStrings.clear(); const FIT_ENTRY* currentEntry = fitHeader + i; + UINT32 currentEntrySize = currentEntry->Size; // Check entry type switch (currentEntry->Type & 0x7F) { @@ -2912,7 +2914,40 @@ USTATUS FfsParser::parseFit(const UModelIndex & index, const UINT32 diff) break; case FIT_TYPE_EMPTY: + break; + case FIT_TYPE_MICROCODE: + //TODO: refactor into function with error reporting + if (currentEntry->Address > diff && currentEntry->Address < 0xFFFFFFFFUL) { + UINT32 offset = currentEntry->Address - diff; + UModelIndex mcIndex = model->findByOffset(offset); + UByteArray mcFile = model->header(mcIndex) + model->body(mcIndex) + model->tail(mcIndex); + + UINT32 mcOffset = offset - model->offset(mcIndex); + if (mcOffset + sizeof(INTEL_MICROCODE_HEADER) <= (UINT32)mcFile.size()) { + const INTEL_MICROCODE_HEADER* header = (const INTEL_MICROCODE_HEADER*)(mcFile.constData() + mcOffset); + if (header->Version == INTEL_MICROCODE_HEADER_VERSION) { + bool reservedBytesValid = true; + for (UINT8 i = 0; i < sizeof(header->Reserved); i++) + if (header->Reserved[i] != INTEL_MICROCODE_HEADER_RESERVED_BYTE) { + reservedBytesValid = false; + break; + } + if (reservedBytesValid) { + UINT32 mcSize = header->TotalSize; + if (mcOffset + mcSize <= (UINT32)mcFile.size()) { + info = usprintf("LocalOffset %08Xh, CPUID %Xh, Revision %Xh, Date %08Xh", + mcOffset, + header->CpuSignature, + header->Revision, + header->Date); + currentEntrySize = header->TotalSize; + itemIndex = mcIndex; + } + } + } + } + } break; case FIT_TYPE_BIOS_AC_MODULE: @@ -2929,11 +2964,12 @@ USTATUS FfsParser::parseFit(const UModelIndex & index, const UINT32 diff) // 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("%08Xh", currentEntrySize, currentEntrySize)); currentStrings.push_back(usprintf("%04Xh", currentEntry->Version)); currentStrings.push_back(usprintf("%02Xh", currentEntry->Checksum)); currentStrings.push_back(fitEntryTypeToUString(currentEntry->Type)); - fitTable.push_back(currentStrings); + currentStrings.push_back(info); + fitTable.push_back(std::pair, UModelIndex>(currentStrings, itemIndex)); } if (msgModifiedImageMayNotWork) diff --git a/common/ffsparser.h b/common/ffsparser.h index ecd4d95..eeb8de4 100644 --- a/common/ffsparser.h +++ b/common/ffsparser.h @@ -32,7 +32,7 @@ public: std::vector > getMessages() const { std::vector > nvramVector = nvramParser.getMessages(); std::vector > resultVector = messagesVector; - resultVector.insert(std::end(resultVector), std::begin(nvramVector), std::end(nvramVector)); + resultVector.insert(resultVector.end(), nvramVector.begin(), nvramVector.end()); return resultVector; } @@ -43,7 +43,7 @@ public: USTATUS parse(const UByteArray &buffer); // Obtain parsed FIT table - std::vector > getFitTable() const { return fitTable; } + std::vector, UModelIndex> > getFitTable() const { return fitTable; } private: TreeModel *model; @@ -52,11 +52,11 @@ private: messagesVector.push_back(std::pair(message, index)); }; + NvramParser nvramParser; + UModelIndex lastVtf; UINT32 capsuleOffsetFixup; - std::vector > fitTable; - - NvramParser nvramParser; + std::vector, UModelIndex> > fitTable; // First pass USTATUS performFirstPass(const UByteArray & imageFile, UModelIndex & index); diff --git a/common/nvramparser.cpp b/common/nvramparser.cpp index 201673f..0434841 100644 --- a/common/nvramparser.cpp +++ b/common/nvramparser.cpp @@ -12,7 +12,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. */ -#include +#include +#include #include "nvramparser.h" #include "parsingdata.h" @@ -1184,13 +1185,14 @@ USTATUS NvramParser::parseIntelMicrocodeHeader(const UByteArray & store, const U // Add info UString name("Intel microcode"); - UString info = usprintf("Revision: 1h\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\n" - "Date: %08Xh\nCPU signature: %08Xh\nChecksum: %08Xh\nLoader revision: %08Xh\nCPU flags: %08Xh", + UString info = usprintf("\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\n" + "Date: %08Xh\nCPU signature: %08Xh\nRevision: %08Xh\nChecksum: %08Xh\nLoader revision: %08Xh\nCPU flags: %08Xh", ucodeHeader->TotalSize, ucodeHeader->TotalSize, header.size(), header.size(), body.size(), body.size(), ucodeHeader->Date, ucodeHeader->CpuSignature, + ucodeHeader->Revision, ucodeHeader->Checksum, ucodeHeader->LoaderRevision, ucodeHeader->CpuFlags); @@ -1588,14 +1590,13 @@ USTATUS NvramParser::parseEvsaStoreBody(const UModelIndex & index) if (body.count(emptyByte) == body.size()) { // Free space // Add free space tree item - UModelIndex itemIndex = model->addItem(localOffset + offset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), body, UByteArray(), Movable, index); + model->addItem(localOffset + offset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), body, UByteArray(), Movable, index); } else { // Add padding tree item UModelIndex itemIndex = model->addItem(localOffset + offset, Types::Padding, getPaddingType(body), UString("Padding"), UString(), info, UByteArray(), body, UByteArray(), Fixed, index); // Show message - msg(UString("parseEvsaStoreBody: variable parsing failed, the rest of unparsed store added as padding"), itemIndex); } break; @@ -1681,7 +1682,7 @@ USTATUS NvramParser::parseEvsaStoreBody(const UModelIndex & index) if (body.count(emptyByte) == body.size()) { // Free space // Add free space tree item - UModelIndex itemIndex = model->addItem(localOffset + offset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), body, UByteArray(), Movable, index); + model->addItem(localOffset + offset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), body, UByteArray(), Movable, index); } else { // Add padding tree item diff --git a/common/peimage.cpp b/common/peimage.cpp index 534d0c8..c3dfe9b 100644 --- a/common/peimage.cpp +++ b/common/peimage.cpp @@ -20,7 +20,7 @@ UString machineTypeToUString(UINT16 machineType) case EFI_IMAGE_FILE_MACHINE_ARM: return UString("ARM"); case EFI_IMAGE_FILE_MACHINE_ARMNT: return UString("ARMv7"); case EFI_IMAGE_FILE_MACHINE_APPLE_ARM: return UString("Apple ARM"); - case EFI_IMAGE_FILE_MACHINE_AARCH64: return UString("AARCH64"); + case EFI_IMAGE_FILE_MACHINE_AARCH64: return UString("AArch64"); case EFI_IMAGE_FILE_MACHINE_EBC: return UString("EBC"); case EFI_IMAGE_FILE_MACHINE_I386: return UString("x86"); case EFI_IMAGE_FILE_MACHINE_IA64: return UString("IA64"); diff --git a/common/treeitem.cpp b/common/treeitem.cpp index 801edf4..e18b142 100644 --- a/common/treeitem.cpp +++ b/common/treeitem.cpp @@ -19,8 +19,8 @@ TreeItem::TreeItem(const UINT32 offset, const UINT8 type, const UINT8 subtype, const UByteArray & header, const UByteArray & body, const UByteArray & tail, const bool fixed, const bool compressed, TreeItem *parent) : - itemAction(Actions::NoAction), itemOffset(offset), + itemAction(Actions::NoAction), itemType(type), itemSubtype(subtype), itemName(name), diff --git a/common/treemodel.cpp b/common/treemodel.cpp index 3cd77b3..021e240 100644 --- a/common/treemodel.cpp +++ b/common/treemodel.cpp @@ -13,6 +13,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "treemodel.h" +#include "stack" + #if defined(QT_CORE_LIB) QVariant TreeModel::data(const UModelIndex &index, int role) const { @@ -491,4 +493,25 @@ UModelIndex TreeModel::findParentOfType(const UModelIndex& index, UINT8 type) co return parent; return UModelIndex(); +} + +UModelIndex TreeModel::findByOffset(UINT32 offset) const +{ + UModelIndex parentIndex = index(0,0); + +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) + // Found a better candidate + parentIndex = currentIndex; + goto goDeeper; + } + } + + return (parentIndex == index(0, 0) ? UModelIndex() : parentIndex); } \ No newline at end of file diff --git a/common/treemodel.h b/common/treemodel.h index d255b3d..1c9dc9b 100644 --- a/common/treemodel.h +++ b/common/treemodel.h @@ -93,7 +93,7 @@ public: QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; TreeModel(QObject *parent = 0) : QAbstractItemModel(parent) { - rootItem = new TreeItem(0, Types::Root, 0, UString(), UString(), UString(), UByteArray(), UByteArray(), UByteArray(), TRUE, FALSE); + rootItem = new TreeItem(0, Types::Root, 0, UString(), UString(), UString(), UByteArray(), UByteArray(), UByteArray(), true, false); } #else @@ -129,8 +129,7 @@ public: delete rootItem; } - UModelIndex index(int row, int column, - const UModelIndex &parent = UModelIndex()) const; + UModelIndex index(int row, int column, const UModelIndex &parent = UModelIndex()) const; UModelIndex parent(const UModelIndex &index) const; int rowCount(const UModelIndex &parent = UModelIndex()) const; int columnCount(const UModelIndex &parent = UModelIndex()) const; @@ -174,6 +173,7 @@ public: const UModelIndex & parent = UModelIndex(), const UINT8 mode = CREATE_MODE_APPEND); UModelIndex findParentOfType(const UModelIndex & index, UINT8 type) const; + UModelIndex findByOffset(UINT32 offset) const; }; #if defined(QT_CORE_LIB) diff --git a/common/ubytearray.h b/common/ubytearray.h index 647b53c..1fa1e75 100644 --- a/common/ubytearray.h +++ b/common/ubytearray.h @@ -43,7 +43,7 @@ public: void clear() { d.clear(); } UByteArray toUpper() { std::basic_string s = d; std::transform(s.begin(), s.end(), s.begin(), ::toupper); return UByteArray(s); } - uint32_t toUInt(bool* ok = NULL, const uint8_t base = 10) { return (uint32_t)std::strtoul(d.c_str(), NULL, base); } + uint32_t toUInt(bool* ok = NULL, const uint8_t base = 10) { return (uint32_t)strtoul(d.c_str(), NULL, base); } int32_t size() const { return d.size(); } int32_t count(char ch) const { return std::count(d.begin(), d.end(), ch); } diff --git a/common/utility.cpp b/common/utility.cpp index 175ee14..c96fe50 100644 --- a/common/utility.cpp +++ b/common/utility.cpp @@ -47,7 +47,8 @@ UString uniqueItemName(const UModelIndex & index) } if (hasExtendedHeader) - name = guidToUString(extendedHeaderGuid).replace('-', '_'); + name = guidToUString(extendedHeaderGuid); + name.findreplace('-', '_'); } break; case Types::NvarEntry: case Types::VssEntry: