Move fitParser to ffsParser

- required to set fixed properly
This commit is contained in:
Nikolaj Schlej 2016-07-14 21:22:51 +02:00
parent feb74c3299
commit 59a6f298ee
14 changed files with 244 additions and 348 deletions

View File

@ -9,7 +9,6 @@ SET(PROJECT_SOURCES
../common/nvram.cpp ../common/nvram.cpp
../common/ffsparser.cpp ../common/ffsparser.cpp
../common/ffsreport.cpp ../common/ffsreport.cpp
../common/fitparser.cpp
../common/peimage.cpp ../common/peimage.cpp
../common/treeitem.cpp ../common/treeitem.cpp
../common/treemodel.cpp ../common/treemodel.cpp
@ -32,7 +31,6 @@ SET(PROJECT_HEADERS
../common/nvram.h ../common/nvram.h
../common/ffsparser.h ../common/ffsparser.h
../common/ffsreport.h ../common/ffsreport.h
../common/fitparser.h
../common/peimage.h ../common/peimage.h
../common/types.h ../common/types.h
../common/treeitem.h ../common/treeitem.h

View File

@ -15,7 +15,6 @@ SOURCES += \
../common/nvram.cpp \ ../common/nvram.cpp \
../common/ffsparser.cpp \ ../common/ffsparser.cpp \
../common/ffsreport.cpp \ ../common/ffsreport.cpp \
../common/fitparser.cpp \
../common/peimage.cpp \ ../common/peimage.cpp \
../common/treeitem.cpp \ ../common/treeitem.cpp \
../common/treemodel.cpp \ ../common/treemodel.cpp \
@ -35,7 +34,6 @@ HEADERS += \
../common/nvram.h \ ../common/nvram.h \
../common/ffsparser.h \ ../common/ffsparser.h \
../common/ffsreport.h \ ../common/ffsreport.h \
../common/fitparser.h \
../common/peimage.h \ ../common/peimage.h \
../common/types.h \ ../common/types.h \
../common/treeitem.h \ ../common/treeitem.h \

View File

@ -15,7 +15,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "../common/ffsparser.h" #include "../common/ffsparser.h"
#include "../common/ffsreport.h" #include "../common/ffsreport.h"
#include "../common/fitparser.h"
#include "ffsdumper.h" #include "ffsdumper.h"
int main(int argc, char *argv[]) int main(int argc, char *argv[])
@ -62,36 +61,39 @@ int main(int argc, char *argv[])
} }
// Get last VTF // Get last VTF
QModelIndex lastVtf = ffsParser.getLastVtf(); std::vector<std::vector<QString> > fitTable = ffsParser.getFitTable();
if (lastVtf.isValid()) { if (fitTable.size()) {
// Create fitParser std::cout << "-------------------------------------------------------------------" << std::endl;
FitParser fitParser(&model); std::cout << " Address | Size | Ver | CS | Type " << std::endl;
// Find and parse FIT table std::cout << "-------------------------------------------------------------------" << std::endl;
result = fitParser.parse(model.index(0, 0), lastVtf); for (size_t i = 0; i < fitTable.size(); i++) {
if (U_SUCCESS == result) { std::cout << fitTable[i][0].toLatin1().constData() << " | "
// Show fitParser's messages
std::vector<std::pair<QString, QModelIndex> > 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<std::vector<QString> > 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() << " | "
<< fitTable[i][1].toLatin1().constData() << " | " << fitTable[i][1].toLatin1().constData() << " | "
<< fitTable[i][2].toLatin1().constData() << " | " << fitTable[i][2].toLatin1().constData() << " | "
<< fitTable[i][3].toLatin1().constData() << " | " << fitTable[i][3].toLatin1().constData() << " | "
<< fitTable[i][4].toLatin1().constData() << std::endl; << 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 // Create ffsReport
FfsReport ffsReport(&model); FfsReport ffsReport(&model);
std::vector<QString> report = ffsReport.generate(); std::vector<QString> report = ffsReport.generate();
@ -105,39 +107,25 @@ int main(int argc, char *argv[])
file.close(); file.close();
} }
} }
// Create ffsDumper // Dump all non-leaf elements, with report, default
FfsDumper ffsDumper(&model);
// Dump all non-leaf elements
if (a.arguments().length() == 2) { if (a.arguments().length() == 2) {
return (ffsDumper.dump(model.index(0, 0), fileInfo.fileName().append(".dump")) != U_SUCCESS); 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); 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; 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;
} }

View File

@ -27,7 +27,6 @@ version(tr("NE Alpha32"))
hexViewDialog = new HexViewDialog(this); hexViewDialog = new HexViewDialog(this);
model = NULL; model = NULL;
ffsParser = NULL; ffsParser = NULL;
fitParser = NULL;
ffsFinder = NULL; ffsFinder = NULL;
ffsOps = NULL; ffsOps = NULL;
ffsBuilder = NULL; ffsBuilder = NULL;
@ -72,7 +71,6 @@ version(tr("NE Alpha32"))
#endif #endif
ui->infoEdit->setFont(font); ui->infoEdit->setFont(font);
ui->parserMessagesListWidget->setFont(font); ui->parserMessagesListWidget->setFont(font);
ui->fitMessagesListWidget->setFont(font);
ui->finderMessagesListWidget->setFont(font); ui->finderMessagesListWidget->setFont(font);
ui->builderMessagesListWidget->setFont(font); ui->builderMessagesListWidget->setFont(font);
ui->fitTableWidget->setFont(font); ui->fitTableWidget->setFont(font);
@ -93,7 +91,6 @@ UEFITool::~UEFITool()
delete ffsBuilder; delete ffsBuilder;
delete ffsOps; delete ffsOps;
delete ffsFinder; delete ffsFinder;
delete fitParser;
delete ffsParser; delete ffsParser;
delete model; delete model;
delete hexViewDialog; delete hexViewDialog;
@ -136,17 +133,12 @@ void UEFITool::init()
// ... and ffsParser // ... and ffsParser
delete ffsParser; delete ffsParser;
ffsParser = new FfsParser(model); ffsParser = new FfsParser(model);
// ... and fitParser
delete fitParser;
fitParser = new FitParser(model);
// Connect // Connect
connect(ui->structureTreeView->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), connect(ui->structureTreeView->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
this, SLOT(populateUi(const QModelIndex &))); this, SLOT(populateUi(const QModelIndex &)));
connect(ui->parserMessagesListWidget, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(scrollTreeView(QListWidgetItem*))); connect(ui->parserMessagesListWidget, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(scrollTreeView(QListWidgetItem*)));
connect(ui->parserMessagesListWidget, SIGNAL(itemEntered(QListWidgetItem*)), this, SLOT(enableMessagesCopyActions(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(itemDoubleClicked(QListWidgetItem*)), this, SLOT(scrollTreeView(QListWidgetItem*)));
connect(ui->finderMessagesListWidget, SIGNAL(itemEntered(QListWidgetItem*)), this, SLOT(enableMessagesCopyActions(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(itemDoubleClicked(QListWidgetItem*)), this, SLOT(scrollTreeView(QListWidgetItem*)));
@ -748,13 +740,6 @@ void UEFITool::openImageFile(QString path)
else else
ui->statusBar->showMessage(tr("Opened: %1").arg(fileInfo.fileName())); 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 ... // Enable search ...
delete ffsFinder; delete ffsFinder;
ffsFinder = new FfsFinder(model); ffsFinder = new FfsFinder(model);
@ -763,6 +748,9 @@ void UEFITool::openImageFile(QString path)
delete ffsOps; delete ffsOps;
ffsOps = new FfsOperations(model); ffsOps = new FfsOperations(model);
// Enable or disable FIT tab
showFitTable();
// Set current directory // Set current directory
currentDir = fileInfo.absolutePath(); currentDir = fileInfo.absolutePath();
} }
@ -772,8 +760,6 @@ void UEFITool::copyMessage()
clipboard->clear(); clipboard->clear();
if (ui->messagesTabWidget->currentIndex() == 0) // Parser tab if (ui->messagesTabWidget->currentIndex() == 0) // Parser tab
clipboard->setText(ui->parserMessagesListWidget->currentItem()->text()); 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 else if (ui->messagesTabWidget->currentIndex() == 2) // Search tab
clipboard->setText(ui->finderMessagesListWidget->currentItem()->text()); clipboard->setText(ui->finderMessagesListWidget->currentItem()->text());
else if (ui->messagesTabWidget->currentIndex() == 3) // Builder tab else if (ui->messagesTabWidget->currentIndex() == 3) // Builder tab
@ -789,11 +775,6 @@ void UEFITool::copyAllMessages()
text.append(ui->parserMessagesListWidget->item(i)->text()).append("\n"); text.append(ui->parserMessagesListWidget->item(i)->text()).append("\n");
clipboard->setText(text); 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 else if (ui->messagesTabWidget->currentIndex() == 2) { // Search tab
for (INT32 i = 0; i < ui->finderMessagesListWidget->count(); i++) for (INT32 i = 0; i < ui->finderMessagesListWidget->count(); i++)
text.append(ui->finderMessagesListWidget->item(i)->text()).append("\n"); text.append(ui->finderMessagesListWidget->item(i)->text()).append("\n");
@ -818,10 +799,6 @@ void UEFITool::clearMessages()
if (ffsParser) ffsParser->clearMessages(); if (ffsParser) ffsParser->clearMessages();
ui->parserMessagesListWidget->clear(); 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 else if (ui->messagesTabWidget->currentIndex() == 2) { // Search tab
if (ffsFinder) ffsFinder->clearMessages(); if (ffsFinder) ffsFinder->clearMessages();
ui->finderMessagesListWidget->clear(); ui->finderMessagesListWidget->clear();
@ -863,21 +840,6 @@ void UEFITool::showParserMessages()
ui->parserMessagesListWidget->scrollToBottom(); ui->parserMessagesListWidget->scrollToBottom();
} }
void UEFITool::showFitMessages()
{
ui->fitMessagesListWidget->clear();
if (!fitParser)
return;
std::vector<std::pair<QString, QModelIndex> > messages = fitParser->getMessages();
std::pair<QString, QModelIndex> msg;
foreach (msg, messages) {
ui->fitMessagesListWidget->addItem(new MessageListItem(msg.first, NULL, 0, msg.second));
}
ui->fitMessagesListWidget->scrollToBottom();
}
void UEFITool::showFinderMessages() void UEFITool::showFinderMessages()
{ {
ui->finderMessagesListWidget->clear(); ui->finderMessagesListWidget->clear();
@ -923,7 +885,6 @@ void UEFITool::scrollTreeView(QListWidgetItem* item)
void UEFITool::contextMenuEvent(QContextMenuEvent* event) void UEFITool::contextMenuEvent(QContextMenuEvent* event)
{ {
if (ui->parserMessagesListWidget->underMouse() || if (ui->parserMessagesListWidget->underMouse() ||
ui->fitMessagesListWidget->underMouse() ||
ui->finderMessagesListWidget->underMouse() || ui->finderMessagesListWidget->underMouse() ||
ui->builderMessagesListWidget->underMouse()) { ui->builderMessagesListWidget->underMouse()) {
ui->menuMessages->exec(event->globalPos()); ui->menuMessages->exec(event->globalPos());
@ -999,10 +960,13 @@ void UEFITool::writeSettings()
void UEFITool::showFitTable() void UEFITool::showFitTable()
{ {
std::vector<std::vector<QString> > fitTable = fitParser->getFitTable(); std::vector<std::vector<QString> > fitTable = ffsParser->getFitTable();
if (fitTable.empty()) { if (fitTable.empty()) {
// Disable FIT tab
ui->messagesTabWidget->setTabEnabled(1, false);
return; return;
} }
// Enable FIT tab // Enable FIT tab
ui->messagesTabWidget->setTabEnabled(1, true); ui->messagesTabWidget->setTabEnabled(1, true);
@ -1010,7 +974,7 @@ void UEFITool::showFitTable()
ui->fitTableWidget->clear(); ui->fitTableWidget->clear();
ui->fitTableWidget->setRowCount(fitTable.size()); ui->fitTableWidget->setRowCount(fitTable.size());
ui->fitTableWidget->setColumnCount(5); 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->setEditTriggers(QAbstractItemView::NoEditTriggers);
ui->fitTableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); ui->fitTableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->fitTableWidget->setSelectionMode(QAbstractItemView::SingleSelection); ui->fitTableWidget->setSelectionMode(QAbstractItemView::SingleSelection);

View File

@ -38,7 +38,6 @@
#include "../common/utility.h" #include "../common/utility.h"
#include "../common/ffs.h" #include "../common/ffs.h"
#include "../common/ffsparser.h" #include "../common/ffsparser.h"
#include "../common/fitparser.h"
#include "../common/ffsops.h" #include "../common/ffsops.h"
#include "../common/ffsbuilder.h" #include "../common/ffsbuilder.h"
@ -109,7 +108,6 @@ private:
Ui::UEFITool* ui; Ui::UEFITool* ui;
TreeModel* model; TreeModel* model;
FfsParser* ffsParser; FfsParser* ffsParser;
FitParser* fitParser;
FfsFinder* ffsFinder; FfsFinder* ffsFinder;
FfsOperations* ffsOps; FfsOperations* ffsOps;
FfsBuilder* ffsBuilder; FfsBuilder* ffsBuilder;
@ -128,7 +126,6 @@ private:
void readSettings(); void readSettings();
void showParserMessages(); void showParserMessages();
void showFinderMessages(); void showFinderMessages();
void showFitMessages();
void showFitTable(); void showFitTable();
void showBuilderMessages(); void showBuilderMessages();
}; };

View File

@ -24,7 +24,6 @@ HEADERS += uefitool.h \
../common/parsingdata.h \ ../common/parsingdata.h \
../common/ffsbuilder.h \ ../common/ffsbuilder.h \
../common/ffsparser.h \ ../common/ffsparser.h \
../common/fitparser.h \
../common/treeitem.h \ ../common/treeitem.h \
../common/treemodel.h \ ../common/treemodel.h \
../common/LZMA/LzmaCompress.h \ ../common/LZMA/LzmaCompress.h \
@ -53,7 +52,6 @@ SOURCES += uefitool_main.cpp \
../common/utility.cpp \ ../common/utility.cpp \
../common/ffsbuilder.cpp \ ../common/ffsbuilder.cpp \
../common/ffsparser.cpp \ ../common/ffsparser.cpp \
../common/fitparser.cpp \
../common/treeitem.cpp \ ../common/treeitem.cpp \
../common/treemodel.cpp \ ../common/treemodel.cpp \
../common/LZMA/LzmaCompress.c \ ../common/LZMA/LzmaCompress.c \

View File

@ -199,11 +199,6 @@
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<widget class="QTableWidget" name="fitTableWidget"/> <widget class="QTableWidget" name="fitTableWidget"/>
<widget class="QListWidget" name="fitMessagesListWidget">
<property name="mouseTracking">
<bool>true</bool>
</property>
</widget>
</widget> </widget>
</item> </item>
</layout> </layout>

View File

@ -2853,7 +2853,7 @@ USTATUS FfsParser::parseTeImageSectionBody(const UModelIndex & index)
usprintf("\nNumber of sections: %u\nSubsystem: %02Xh\nStripped size: %Xh (%u)\n" 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", "Base of code: %Xh\nAddress of entry point: %Xh\nImage base: %" PRIX64 "h\nAdjusted image base: %" PRIX64 "h",
teHeader->NumberOfSections, teHeader->NumberOfSections,
teHeader->Subsystem, teHeader->Subsystem,
teHeader->StrippedSize, teHeader->StrippedSize, teHeader->StrippedSize, teHeader->StrippedSize,
teHeader->BaseOfCode, teHeader->BaseOfCode,
teHeader->AddressOfEntryPoint, 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); msg(UString("performSecondPass: the last VTF appears inside compressed item, the image may be damaged"), lastVtf);
return U_SUCCESS; return U_SUCCESS;
} }
// Get parsing data for the last VTF // Get parsing data for the last VTF
PARSING_DATA pdata = parsingDataFromUModelIndex(lastVtf); 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 vtfSize = model->header(lastVtf).size() + model->body(lastVtf).size() + model->tail(lastVtf).size();
const UINT32 diff = 0xFFFFFFFFUL - pdata.offset - vtfSize + 1; const UINT32 diff = 0xFFFFFFFFUL - pdata.offset - vtfSize + 1;
// Find and parse FIT
parseFit(index, diff);
// Apply address information to index and all it's child items // Apply address information to index and all it's child items
addMemoryAddressesRecursive(index, diff); 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<UString> 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; return U_SUCCESS;
} }
@ -2968,10 +3127,6 @@ USTATUS FfsParser::addOffsetsRecursive(const UModelIndex & index)
model->addInfo(index, usprintf("Offset: %Xh\n", pdata.offset), false); 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 // Process child items
for (int i = 0; i < model->rowCount(index); i++) { for (int i = 0; i < model->rowCount(index); i++) {
addOffsetsRecursive(index.child(i, 0)); addOffsetsRecursive(index.child(i, 0));

View File

@ -48,8 +48,8 @@ public:
// Firmware image parsing // Firmware image parsing
USTATUS parse(const UByteArray &buffer); USTATUS parse(const UByteArray &buffer);
// Retuns index of the last VTF after parsing is done // Obtain parsed FIT table
const UModelIndex getLastVtf() {return lastVtf;}; std::vector<std::vector<UString> > getFitTable() const { return fitTable; }
private: private:
TreeModel *model; TreeModel *model;
@ -60,6 +60,10 @@ private:
UModelIndex lastVtf; UModelIndex lastVtf;
UINT32 capsuleOffsetFixup; UINT32 capsuleOffsetFixup;
std::vector<std::vector<UString> > fitTable;
// First pass
USTATUS performFirstPass(const UByteArray & imageFile, UModelIndex & index);
USTATUS parseRawArea(const UModelIndex & index); USTATUS parseRawArea(const UModelIndex & index);
USTATUS parseVolumeHeader(const UByteArray & volume, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index); USTATUS parseVolumeHeader(const UByteArray & volume, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index);
@ -103,11 +107,6 @@ private:
UINT32 getFileSize(const UByteArray & volume, const UINT32 fileOffset, const UINT8 ffsVersion); UINT32 getFileSize(const UByteArray & volume, const UINT32 fileOffset, const UINT8 ffsVersion);
UINT32 getSectionSize(const UByteArray & file, const UINT32 sectionOffset, 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 // NVRAM parsing
USTATUS parseNvramVolumeBody(const UModelIndex & index); USTATUS parseNvramVolumeBody(const UModelIndex & index);
USTATUS findNextStore(const UModelIndex & index, const UByteArray & volume, const UINT32 parentOffset, const UINT32 storeOffset, UINT32 & nextStoreOffset); USTATUS findNextStore(const UModelIndex & index, const UByteArray & volume, const UINT32 parentOffset, const UINT32 storeOffset, UINT32 & nextStoreOffset);
@ -130,6 +129,14 @@ private:
USTATUS parseFsysStoreBody(const UModelIndex & index); USTATUS parseFsysStoreBody(const UModelIndex & index);
USTATUS parseEvsaStoreBody(const UModelIndex & index); USTATUS parseEvsaStoreBody(const UModelIndex & index);
USTATUS parseFlashMapBody(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 #endif // FFSPARSER_H

View File

@ -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<UString> 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;
}

View File

@ -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 <vector>
#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<std::pair<UString, UModelIndex> > getMessages() const { return messagesVector; };
// Clears messages
void clearMessages() { messagesVector.clear(); }
USTATUS parse(const UModelIndex & index, const UModelIndex & lastVtf);
std::vector<std::vector<UString> > getFitTable() const { return fitTable; }
private:
TreeModel *model;
std::vector<std::pair<UString, UModelIndex> > messagesVector;
UModelIndex lastVtf;
std::vector<std::vector<UString> > 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<UString, UModelIndex>(message, index));
}
};
#endif // FITPARSER_H

View File

@ -13,6 +13,7 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "ustring.h" #include "ustring.h"
#include "types.h" #include "types.h"
#include "ffs.h" #include "ffs.h"
#include "fit.h"
UString regionTypeToUString(const UINT8 type) UString regionTypeToUString(const UINT8 type)
{ {
@ -161,4 +162,21 @@ UString actionTypeToUString(const UINT8 action)
} }
return UString("Unknown"); 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 ");
}
} }

View File

@ -144,5 +144,6 @@ extern UString itemTypeToUString(const UINT8 type);
extern UString itemSubtypeToUString(const UINT8 type, const UINT8 subtype); extern UString itemSubtypeToUString(const UINT8 type, const UINT8 subtype);
extern UString compressionTypeToUString(const UINT8 algorithm); extern UString compressionTypeToUString(const UINT8 algorithm);
extern UString regionTypeToUString(const UINT8 type); extern UString regionTypeToUString(const UINT8 type);
extern UString fitEntryTypeToUString(const UINT8 type);
#endif // TYPES_H #endif // TYPES_H

View File

@ -113,14 +113,14 @@ class QHexEdit : public QAbstractScrollArea
*/ */
Q_PROPERTY(QColor selectionColor READ selectionColor WRITE setSelectionColor) 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 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 through the data and select data; modifying is not possible. This
property's default is false. property's default is false.
*/ */
Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly) 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. data. Default is lowercase.
*/ */
Q_PROPERTY(bool upperCase READ isUpperCase WRITE setUpperCase) Q_PROPERTY(bool upperCase READ isUpperCase WRITE setUpperCase)