mirror of
https://github.com/LongSoft/UEFITool.git
synced 2024-11-25 01:18:22 +08:00
NE_aplha5
Added FIT detection, parsing and UI, finally
This commit is contained in:
parent
f3d731c599
commit
407e558b60
@ -44,7 +44,7 @@ STATUS FfsOperations::extract(const QModelIndex & index, QString & name, QByteAr
|
|||||||
return ERR_INVALID_PARAMETER;
|
return ERR_INVALID_PARAMETER;
|
||||||
|
|
||||||
// Get data from parsing data
|
// Get data from parsing data
|
||||||
PARSING_DATA pdata = parsingDataFromQByteArray(index);
|
PARSING_DATA pdata = parsingDataFromQModelIndex(index);
|
||||||
|
|
||||||
// Construct a name for extracted data
|
// Construct a name for extracted data
|
||||||
QString itemName = model->name(index);
|
QString itemName = model->name(index);
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
UEFITool::UEFITool(QWidget *parent) :
|
UEFITool::UEFITool(QWidget *parent) :
|
||||||
QMainWindow(parent),
|
QMainWindow(parent),
|
||||||
ui(new Ui::UEFITool),
|
ui(new Ui::UEFITool),
|
||||||
version(tr("0.30.0_alpha4"))
|
version(tr("0.30.0_alpha5"))
|
||||||
{
|
{
|
||||||
clipboard = QApplication::clipboard();
|
clipboard = QApplication::clipboard();
|
||||||
|
|
||||||
@ -26,6 +26,7 @@ version(tr("0.30.0_alpha4"))
|
|||||||
searchDialog = new SearchDialog(this);
|
searchDialog = new SearchDialog(this);
|
||||||
model = NULL;
|
model = NULL;
|
||||||
ffsParser = NULL;
|
ffsParser = NULL;
|
||||||
|
fitParser = NULL;
|
||||||
ffsFinder = NULL;
|
ffsFinder = NULL;
|
||||||
ffsOps = NULL;
|
ffsOps = NULL;
|
||||||
|
|
||||||
@ -69,6 +70,7 @@ version(tr("0.30.0_alpha4"))
|
|||||||
ui->infoEdit->setFont(font);
|
ui->infoEdit->setFont(font);
|
||||||
ui->parserMessagesListWidget->setFont(font);
|
ui->parserMessagesListWidget->setFont(font);
|
||||||
ui->finderMessagesListWidget->setFont(font);
|
ui->finderMessagesListWidget->setFont(font);
|
||||||
|
ui->fitTableWidget->setFont(font);
|
||||||
ui->structureTreeView->setFont(font);
|
ui->structureTreeView->setFont(font);
|
||||||
searchDialog->ui->guidEdit->setFont(font);
|
searchDialog->ui->guidEdit->setFont(font);
|
||||||
searchDialog->ui->hexEdit->setFont(font);
|
searchDialog->ui->hexEdit->setFont(font);
|
||||||
@ -84,6 +86,7 @@ UEFITool::~UEFITool()
|
|||||||
{
|
{
|
||||||
delete ffsOps;
|
delete ffsOps;
|
||||||
delete ffsFinder;
|
delete ffsFinder;
|
||||||
|
delete fitParser;
|
||||||
delete ffsParser;
|
delete ffsParser;
|
||||||
delete model;
|
delete model;
|
||||||
delete searchDialog;
|
delete searchDialog;
|
||||||
@ -95,6 +98,7 @@ void UEFITool::init()
|
|||||||
// Clear components
|
// Clear components
|
||||||
ui->parserMessagesListWidget->clear();
|
ui->parserMessagesListWidget->clear();
|
||||||
ui->finderMessagesListWidget->clear();
|
ui->finderMessagesListWidget->clear();
|
||||||
|
ui->fitTableWidget->clear();
|
||||||
ui->infoEdit->clear();
|
ui->infoEdit->clear();
|
||||||
|
|
||||||
// Set window title
|
// Set window title
|
||||||
@ -120,6 +124,10 @@ void UEFITool::init()
|
|||||||
if (ffsParser)
|
if (ffsParser)
|
||||||
delete ffsParser;
|
delete ffsParser;
|
||||||
ffsParser = new FfsParser(model);
|
ffsParser = new FfsParser(model);
|
||||||
|
// ... and fitParser
|
||||||
|
if (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 &)),
|
||||||
@ -602,6 +610,12 @@ 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
|
||||||
|
//!TODO: expand and chek errors
|
||||||
|
result = fitParser->parse(model->index(0, 0), ffsParser->getLastVtf());
|
||||||
|
if (!result)
|
||||||
|
showFitTable();
|
||||||
|
|
||||||
// Enable search ...
|
// Enable search ...
|
||||||
if (ffsFinder)
|
if (ffsFinder)
|
||||||
delete ffsFinder;
|
delete ffsFinder;
|
||||||
@ -789,3 +803,78 @@ void UEFITool::writeSettings()
|
|||||||
settings.setValue("tree/columnWidth2", ui->structureTreeView->columnWidth(2));
|
settings.setValue("tree/columnWidth2", ui->structureTreeView->columnWidth(2));
|
||||||
settings.setValue("tree/columnWidth3", ui->structureTreeView->columnWidth(3));
|
settings.setValue("tree/columnWidth3", ui->structureTreeView->columnWidth(3));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UEFITool::showFitTable()
|
||||||
|
{
|
||||||
|
QVector<QPair<FIT_ENTRY, QString> > fitEntries = fitParser->getFitEntries();
|
||||||
|
if (fitEntries.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Set up the FIT table
|
||||||
|
ui->fitTableWidget->clear();
|
||||||
|
ui->fitTableWidget->setRowCount(fitEntries.length());
|
||||||
|
ui->fitTableWidget->setColumnCount(6);
|
||||||
|
//ui->fitTableWidget->verticalHeader()->setVisible(false);
|
||||||
|
ui->fitTableWidget->setHorizontalHeaderLabels(QStringList() << tr("Address") << tr("Size") << tr("Version") << tr("Type") << tr("Checksum") << tr("Remark"));
|
||||||
|
ui->fitTableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||||
|
ui->fitTableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||||
|
ui->fitTableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||||
|
ui->fitTableWidget->horizontalHeader()->setStretchLastSection(true);
|
||||||
|
|
||||||
|
// Add all data to the table widget
|
||||||
|
for (INT32 i = 0; i < fitEntries.length(); i++) {
|
||||||
|
FIT_ENTRY* entry = &(fitEntries[i].first);
|
||||||
|
if (i)
|
||||||
|
ui->fitTableWidget->setItem(i, 0, new QTableWidgetItem(tr("%1h").hexarg2(entry->Address, 16)));
|
||||||
|
else
|
||||||
|
ui->fitTableWidget->setItem(i, 0, new QTableWidgetItem(tr("_FIT_ ")));
|
||||||
|
|
||||||
|
ui->fitTableWidget->setItem(i, 1, new QTableWidgetItem(tr("%1h (%2)").hexarg2(entry->Size * 16, 8).arg(entry->Size * 16)));
|
||||||
|
ui->fitTableWidget->setItem(i, 2, new QTableWidgetItem(tr("%1h").hexarg2(entry->Version, 4)));
|
||||||
|
|
||||||
|
QString typeString;
|
||||||
|
switch (entry->Type & 0x7F) {
|
||||||
|
case FIT_TYPE_HEADER:
|
||||||
|
typeString.append(tr("Header"));
|
||||||
|
break;
|
||||||
|
case FIT_TYPE_MICROCODE:
|
||||||
|
typeString.append(tr("Microcode"));
|
||||||
|
break;
|
||||||
|
case FIT_TYPE_BIOS_AC_MODULE:
|
||||||
|
typeString.append(tr("BIOS ACM"));
|
||||||
|
break;
|
||||||
|
case FIT_TYPE_BIOS_INIT_MODULE:
|
||||||
|
typeString.append(tr("BIOS Init"));
|
||||||
|
break;
|
||||||
|
case FIT_TYPE_TPM_POLICY:
|
||||||
|
typeString.append(tr("TPM Policy"));
|
||||||
|
break;
|
||||||
|
case FIT_TYPE_BIOS_POLICY_DATA:
|
||||||
|
typeString.append(tr("BIOS Policy Data"));
|
||||||
|
break;
|
||||||
|
case FIT_TYPE_TXT_CONF_POLICY:
|
||||||
|
typeString.append(tr("TXT Configuration Policy"));
|
||||||
|
break;
|
||||||
|
case FIT_TYPE_AC_KEY_MANIFEST:
|
||||||
|
typeString.append(tr("BootGuard Key Manifest"));
|
||||||
|
break;
|
||||||
|
case FIT_TYPE_AC_BOOT_POLICY:
|
||||||
|
typeString.append(tr("BootGuard Boot Policy"));
|
||||||
|
break;
|
||||||
|
case FIT_TYPE_EMPTY:
|
||||||
|
typeString.append(tr("Empty"));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
typeString.append(tr("Unknown"));
|
||||||
|
}
|
||||||
|
|
||||||
|
ui->fitTableWidget->setItem(i, 3, new QTableWidgetItem(typeString));
|
||||||
|
ui->fitTableWidget->setItem(i, 4, new QTableWidgetItem(tr("%1h").hexarg2(entry->Checksum, 2)));
|
||||||
|
ui->fitTableWidget->setItem(i, 5, new QTableWidgetItem(fitEntries[i].second));
|
||||||
|
}
|
||||||
|
|
||||||
|
ui->fitTableWidget->resizeColumnsToContents();
|
||||||
|
ui->fitTableWidget->resizeRowsToContents();
|
||||||
|
ui->messagesTabWidget->setCurrentIndex(2);
|
||||||
|
|
||||||
|
}
|
@ -37,6 +37,7 @@
|
|||||||
#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 "searchdialog.h"
|
#include "searchdialog.h"
|
||||||
#include "messagelistitem.h"
|
#include "messagelistitem.h"
|
||||||
#include "ffsfinder.h"
|
#include "ffsfinder.h"
|
||||||
@ -97,6 +98,7 @@ 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;
|
||||||
SearchDialog* searchDialog;
|
SearchDialog* searchDialog;
|
||||||
@ -110,6 +112,7 @@ private:
|
|||||||
void readSettings();
|
void readSettings();
|
||||||
void showParserMessages();
|
void showParserMessages();
|
||||||
void showFinderMessages();
|
void showFinderMessages();
|
||||||
|
void showFitTable();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -18,6 +18,7 @@ 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 \
|
||||||
@ -47,6 +48,7 @@ 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 \
|
||||||
|
@ -202,6 +202,31 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QWidget" name="fitTab">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>FIT</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QTableWidget" name="fitTableWidget"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -30,36 +30,6 @@ const QVector<QByteArray> FFSv3Volumes =
|
|||||||
const UINT8 ffsAlignmentTable[] =
|
const UINT8 ffsAlignmentTable[] =
|
||||||
{ 0, 4, 7, 9, 10, 12, 15, 16 };
|
{ 0, 4, 7, 9, 10, 12, 15, 16 };
|
||||||
|
|
||||||
UINT8 calculateChecksum8(const UINT8* buffer, UINT32 bufferSize)
|
|
||||||
{
|
|
||||||
if (!buffer)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
UINT8 counter = 0;
|
|
||||||
|
|
||||||
while (bufferSize--)
|
|
||||||
counter += buffer[bufferSize];
|
|
||||||
|
|
||||||
return (UINT8)(0x100 - counter);
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT16 calculateChecksum16(const UINT16* buffer, UINT32 bufferSize)
|
|
||||||
{
|
|
||||||
if (!buffer)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
UINT16 counter = 0;
|
|
||||||
UINT32 index = 0;
|
|
||||||
|
|
||||||
bufferSize /= sizeof(UINT16);
|
|
||||||
|
|
||||||
for (; index < bufferSize; index++) {
|
|
||||||
counter = (UINT16)(counter + buffer[index]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (UINT16)(0x10000 - counter);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID uint32ToUint24(UINT32 size, UINT8* ffsSize)
|
VOID uint32ToUint24(UINT32 size, UINT8* ffsSize)
|
||||||
{
|
{
|
||||||
ffsSize[2] = (UINT8)((size) >> 16);
|
ffsSize[2] = (UINT8)((size) >> 16);
|
||||||
|
@ -240,9 +240,6 @@ typedef struct _EFI_FIRMWARE_VOLUME_EXT_ENTRY_GUID_TYPE {
|
|||||||
//UINT8 Data[];
|
//UINT8 Data[];
|
||||||
} EFI_FIRMWARE_VOLUME_EXT_ENTRY_GUID_TYPE;
|
} EFI_FIRMWARE_VOLUME_EXT_ENTRY_GUID_TYPE;
|
||||||
|
|
||||||
// Volume header 16bit checksum calculation routine
|
|
||||||
extern UINT16 calculateChecksum16(const UINT16* buffer, UINT32 bufferSize);
|
|
||||||
|
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
// EFI FFS File
|
// EFI FFS File
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
@ -341,8 +338,6 @@ const QByteArray EFI_FFS_PAD_FILE_GUID
|
|||||||
// FFS size conversion routines
|
// FFS size conversion routines
|
||||||
extern VOID uint32ToUint24(UINT32 size, UINT8* ffsSize);
|
extern VOID uint32ToUint24(UINT32 size, UINT8* ffsSize);
|
||||||
extern UINT32 uint24ToUint32(const UINT8* ffsSize);
|
extern UINT32 uint24ToUint32(const UINT8* ffsSize);
|
||||||
// FFS file 8bit checksum calculation routine
|
|
||||||
extern UINT8 calculateChecksum8(const UINT8* buffer, UINT32 bufferSize);
|
|
||||||
|
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
// EFI FFS File Section
|
// EFI FFS File Section
|
||||||
|
@ -43,7 +43,7 @@ STATUS FfsBuilder::erase(const QModelIndex & index, QByteArray & erased)
|
|||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
return ERR_INVALID_PARAMETER;
|
return ERR_INVALID_PARAMETER;
|
||||||
|
|
||||||
PARSING_DATA pdata = parsingDataFromQByteArray(index);
|
PARSING_DATA pdata = parsingDataFromQModelIndex(index);
|
||||||
erased.fill(pdata.emptyByte);
|
erased.fill(pdata.emptyByte);
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,7 @@ STATUS FfsParser::parseImageFile(const QByteArray & buffer, const QModelIndex &
|
|||||||
.hexarg2(capsuleHeader->Flags, 8);
|
.hexarg2(capsuleHeader->Flags, 8);
|
||||||
|
|
||||||
// Construct parsing data
|
// Construct parsing data
|
||||||
PARSING_DATA pdata = parsingDataFromQByteArray(QModelIndex());
|
PARSING_DATA pdata = parsingDataFromQModelIndex(QModelIndex());
|
||||||
pdata.fixed = TRUE;
|
pdata.fixed = TRUE;
|
||||||
|
|
||||||
// Add tree item
|
// Add tree item
|
||||||
@ -108,7 +108,7 @@ STATUS FfsParser::parseImageFile(const QByteArray & buffer, const QModelIndex &
|
|||||||
.hexarg2(capsuleHeader->CapsuleHeader.Flags, 8);
|
.hexarg2(capsuleHeader->CapsuleHeader.Flags, 8);
|
||||||
|
|
||||||
// Construct parsing data
|
// Construct parsing data
|
||||||
PARSING_DATA pdata = parsingDataFromQByteArray(QModelIndex());
|
PARSING_DATA pdata = parsingDataFromQModelIndex(QModelIndex());
|
||||||
pdata.fixed = TRUE;
|
pdata.fixed = TRUE;
|
||||||
|
|
||||||
// Add tree item
|
// Add tree item
|
||||||
@ -146,7 +146,7 @@ STATUS FfsParser::parseImageFile(const QByteArray & buffer, const QModelIndex &
|
|||||||
.hexarg(capsuleHeaderSize).hexarg(flashImage.size()).arg(flashImage.size());
|
.hexarg(capsuleHeaderSize).hexarg(flashImage.size()).arg(flashImage.size());
|
||||||
|
|
||||||
// Construct parsing data
|
// Construct parsing data
|
||||||
PARSING_DATA pdata = parsingDataFromQByteArray(index);
|
PARSING_DATA pdata = parsingDataFromQModelIndex(index);
|
||||||
pdata.fixed = TRUE;
|
pdata.fixed = TRUE;
|
||||||
pdata.offset = capsuleHeaderSize;
|
pdata.offset = capsuleHeaderSize;
|
||||||
|
|
||||||
@ -160,7 +160,7 @@ STATUS FfsParser::parseImageFile(const QByteArray & buffer, const QModelIndex &
|
|||||||
|
|
||||||
// Check if the last VTF is found
|
// Check if the last VTF is found
|
||||||
if (!lastVtf.isValid()) {
|
if (!lastVtf.isValid()) {
|
||||||
msg(tr("parseImageFile: not a single Volume Top File is found, physical memory addresses can't be calculated"), biosIndex);
|
msg(tr("parseImageFile: not a single Volume Top File is found, the image may be corrupted"), biosIndex);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return performSecondPass(biosIndex);
|
return performSecondPass(biosIndex);
|
||||||
@ -176,7 +176,7 @@ STATUS FfsParser::parseIntelImage(const QByteArray & intelImage, const QModelInd
|
|||||||
return EFI_INVALID_PARAMETER;
|
return EFI_INVALID_PARAMETER;
|
||||||
|
|
||||||
// Get parent's parsing data
|
// Get parent's parsing data
|
||||||
PARSING_DATA pdata = parsingDataFromQByteArray(parent);
|
PARSING_DATA pdata = parsingDataFromQModelIndex(parent);
|
||||||
|
|
||||||
// Store the beginning of descriptor as descriptor base address
|
// Store the beginning of descriptor as descriptor base address
|
||||||
const UINT8* descriptor = (const UINT8*)intelImage.constData();
|
const UINT8* descriptor = (const UINT8*)intelImage.constData();
|
||||||
@ -412,7 +412,7 @@ STATUS FfsParser::parseIntelImage(const QByteArray & intelImage, const QModelInd
|
|||||||
|
|
||||||
// Check if the last VTF is found
|
// Check if the last VTF is found
|
||||||
if (!lastVtf.isValid()) {
|
if (!lastVtf.isValid()) {
|
||||||
msg(tr("parseIntelImage: not a single Volume Top File is found, physical memory addresses can't be calculated"), index);
|
msg(tr("parseIntelImage: not a single Volume Top File is found, the image may be corrupted"), index);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return performSecondPass(index);
|
return performSecondPass(index);
|
||||||
@ -428,7 +428,7 @@ STATUS FfsParser::parseGbeRegion(const QByteArray & gbe, const UINT32 parentOffs
|
|||||||
return ERR_EMPTY_REGION;
|
return ERR_EMPTY_REGION;
|
||||||
|
|
||||||
// Get parent's parsing data
|
// Get parent's parsing data
|
||||||
PARSING_DATA pdata = parsingDataFromQByteArray(parent);
|
PARSING_DATA pdata = parsingDataFromQModelIndex(parent);
|
||||||
|
|
||||||
// Get info
|
// Get info
|
||||||
QString name = tr("GbE region");
|
QString name = tr("GbE region");
|
||||||
@ -463,7 +463,7 @@ STATUS FfsParser::parseMeRegion(const QByteArray & me, const UINT32 parentOffset
|
|||||||
return ERR_EMPTY_REGION;
|
return ERR_EMPTY_REGION;
|
||||||
|
|
||||||
// Get parent's parsing data
|
// Get parent's parsing data
|
||||||
PARSING_DATA pdata = parsingDataFromQByteArray(parent);
|
PARSING_DATA pdata = parsingDataFromQModelIndex(parent);
|
||||||
|
|
||||||
// Get info
|
// Get info
|
||||||
QString name = tr("ME region");
|
QString name = tr("ME region");
|
||||||
@ -528,7 +528,7 @@ STATUS FfsParser::parsePdrRegion(const QByteArray & pdr, const UINT32 parentOffs
|
|||||||
return ERR_EMPTY_REGION;
|
return ERR_EMPTY_REGION;
|
||||||
|
|
||||||
// Get parent's parsing data
|
// Get parent's parsing data
|
||||||
PARSING_DATA pdata = parsingDataFromQByteArray(parent);
|
PARSING_DATA pdata = parsingDataFromQModelIndex(parent);
|
||||||
|
|
||||||
// Get info
|
// Get info
|
||||||
QString name = tr("PDR region");
|
QString name = tr("PDR region");
|
||||||
@ -558,7 +558,7 @@ STATUS FfsParser::parseBiosRegion(const QByteArray & bios, const UINT32 parentOf
|
|||||||
return ERR_EMPTY_REGION;
|
return ERR_EMPTY_REGION;
|
||||||
|
|
||||||
// Get parent's parsing data
|
// Get parent's parsing data
|
||||||
PARSING_DATA pdata = parsingDataFromQByteArray(parent);
|
PARSING_DATA pdata = parsingDataFromQModelIndex(parent);
|
||||||
|
|
||||||
// Get info
|
// Get info
|
||||||
QString name = tr("BIOS region");
|
QString name = tr("BIOS region");
|
||||||
@ -592,7 +592,7 @@ STATUS FfsParser::parseRawArea(const QByteArray & data, const QModelIndex & inde
|
|||||||
return ERR_INVALID_PARAMETER;
|
return ERR_INVALID_PARAMETER;
|
||||||
|
|
||||||
// Get parsing data
|
// Get parsing data
|
||||||
PARSING_DATA pdata = parsingDataFromQByteArray(index);
|
PARSING_DATA pdata = parsingDataFromQModelIndex(index);
|
||||||
UINT32 offset = pdata.offset;
|
UINT32 offset = pdata.offset;
|
||||||
UINT32 headerSize = model->header(index).size();
|
UINT32 headerSize = model->header(index).size();
|
||||||
|
|
||||||
@ -746,7 +746,7 @@ STATUS FfsParser::parseVolumeHeader(const QByteArray & volume, const UINT32 pare
|
|||||||
return ERR_INVALID_PARAMETER;
|
return ERR_INVALID_PARAMETER;
|
||||||
|
|
||||||
// Get parent's parsing data
|
// Get parent's parsing data
|
||||||
PARSING_DATA pdata = parsingDataFromQByteArray(parent);
|
PARSING_DATA pdata = parsingDataFromQModelIndex(parent);
|
||||||
|
|
||||||
// Populate volume header
|
// Populate volume header
|
||||||
const EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (const EFI_FIRMWARE_VOLUME_HEADER*)(volume.constData());
|
const EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (const EFI_FIRMWARE_VOLUME_HEADER*)(volume.constData());
|
||||||
@ -831,14 +831,14 @@ STATUS FfsParser::parseVolumeHeader(const QByteArray & volume, const UINT32 pare
|
|||||||
UINT8 emptyByte = volumeHeader->Attributes & EFI_FVB_ERASE_POLARITY ? '\xFF' : '\x00';
|
UINT8 emptyByte = volumeHeader->Attributes & EFI_FVB_ERASE_POLARITY ? '\xFF' : '\x00';
|
||||||
|
|
||||||
// Check for Apple CRC32 in ZeroVector
|
// Check for Apple CRC32 in ZeroVector
|
||||||
bool hasZeroVectorCRC32 = false;
|
bool hasAppleCrc32 = false;
|
||||||
UINT32 volumeSize = volume.size();
|
UINT32 volumeSize = volume.size();
|
||||||
UINT32 crc32FromZeroVector = *(UINT32*)(volume.constData() + 8);
|
UINT32 appleCrc32 = *(UINT32*)(volume.constData() + 8);
|
||||||
if (crc32FromZeroVector != 0) {
|
if (appleCrc32 != 0) {
|
||||||
// Calculate CRC32 of the volume body
|
// Calculate CRC32 of the volume body
|
||||||
UINT32 crc = crc32(0, (const UINT8*)(volume.constData() + volumeHeader->HeaderLength), volumeSize - volumeHeader->HeaderLength);
|
UINT32 crc = crc32(0, (const UINT8*)(volume.constData() + volumeHeader->HeaderLength), volumeSize - volumeHeader->HeaderLength);
|
||||||
if (crc == crc32FromZeroVector) {
|
if (crc == appleCrc32) {
|
||||||
hasZeroVectorCRC32 = true;
|
hasAppleCrc32 = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -865,11 +865,6 @@ STATUS FfsParser::parseVolumeHeader(const QByteArray & volume, const UINT32 pare
|
|||||||
.hexarg2(volumeHeader->Attributes, 8)
|
.hexarg2(volumeHeader->Attributes, 8)
|
||||||
.arg(emptyByte ? "1" : "0");
|
.arg(emptyByte ? "1" : "0");
|
||||||
|
|
||||||
// Apple CRC32 volume
|
|
||||||
if (hasZeroVectorCRC32) {
|
|
||||||
info += tr("\nCRC32 in ZeroVector: valid");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extended header present
|
// Extended header present
|
||||||
if (volumeHeader->Revision > 1 && volumeHeader->ExtHeaderOffset) {
|
if (volumeHeader->Revision > 1 && volumeHeader->ExtHeaderOffset) {
|
||||||
const EFI_FIRMWARE_VOLUME_EXT_HEADER* extendedHeader = (const EFI_FIRMWARE_VOLUME_EXT_HEADER*)(volume.constData() + volumeHeader->ExtHeaderOffset);
|
const EFI_FIRMWARE_VOLUME_EXT_HEADER* extendedHeader = (const EFI_FIRMWARE_VOLUME_EXT_HEADER*)(volume.constData() + volumeHeader->ExtHeaderOffset);
|
||||||
@ -887,14 +882,14 @@ STATUS FfsParser::parseVolumeHeader(const QByteArray & volume, const UINT32 pare
|
|||||||
pdata.volume.extendedHeaderGuid = extendedHeaderGuid;
|
pdata.volume.extendedHeaderGuid = extendedHeaderGuid;
|
||||||
pdata.volume.alignment = alignment;
|
pdata.volume.alignment = alignment;
|
||||||
pdata.volume.revision = volumeHeader->Revision;
|
pdata.volume.revision = volumeHeader->Revision;
|
||||||
pdata.volume.hasZeroVectorCRC32 = hasZeroVectorCRC32;
|
pdata.volume.hasAppleCrc32 = hasAppleCrc32;
|
||||||
pdata.volume.isWeakAligned = (volumeHeader->Revision > 1 && (volumeHeader->Attributes & EFI_FVB2_WEAK_ALIGNMENT));
|
pdata.volume.isWeakAligned = (volumeHeader->Revision > 1 && (volumeHeader->Attributes & EFI_FVB2_WEAK_ALIGNMENT));
|
||||||
if (pdata.isOnFlash) info.prepend(tr("Offset: %1h\n").hexarg(pdata.offset));
|
if (pdata.isOnFlash) info.prepend(tr("Offset: %1h\n").hexarg(pdata.offset));
|
||||||
|
|
||||||
// Add text
|
// Add text
|
||||||
QString text;
|
QString text;
|
||||||
if (hasZeroVectorCRC32)
|
if (hasAppleCrc32)
|
||||||
text += tr("ZeroVectorCRC32 ");
|
text += tr("AppleCRC32 ");
|
||||||
|
|
||||||
// Add tree item
|
// Add tree item
|
||||||
UINT8 subtype = Subtypes::UnknownVolume;
|
UINT8 subtype = Subtypes::UnknownVolume;
|
||||||
@ -967,7 +962,7 @@ STATUS FfsParser::parseVolumeBody(const QModelIndex & index)
|
|||||||
UINT32 volumeHeaderSize = model->header(index).size();
|
UINT32 volumeHeaderSize = model->header(index).size();
|
||||||
|
|
||||||
// Get parsing data
|
// Get parsing data
|
||||||
PARSING_DATA pdata = parsingDataFromQByteArray(index);
|
PARSING_DATA pdata = parsingDataFromQModelIndex(index);
|
||||||
UINT32 offset = pdata.offset;
|
UINT32 offset = pdata.offset;
|
||||||
|
|
||||||
if (pdata.ffsVersion != 2 && pdata.ffsVersion != 3) // Don't parse unknown volumes
|
if (pdata.ffsVersion != 2 && pdata.ffsVersion != 3) // Don't parse unknown volumes
|
||||||
@ -1146,7 +1141,7 @@ STATUS FfsParser::parseFileHeader(const QByteArray & file, const UINT32 parentOf
|
|||||||
return ERR_INVALID_PARAMETER;
|
return ERR_INVALID_PARAMETER;
|
||||||
|
|
||||||
// Get parent's parsing data
|
// Get parent's parsing data
|
||||||
PARSING_DATA pdata = parsingDataFromQByteArray(parent);
|
PARSING_DATA pdata = parsingDataFromQModelIndex(parent);
|
||||||
|
|
||||||
// Get file header
|
// Get file header
|
||||||
QByteArray header = file.left(sizeof(EFI_FFS_FILE_HEADER));
|
QByteArray header = file.left(sizeof(EFI_FFS_FILE_HEADER));
|
||||||
@ -1328,7 +1323,7 @@ STATUS FfsParser::parsePadFileBody(const QModelIndex & index)
|
|||||||
return ERR_INVALID_PARAMETER;
|
return ERR_INVALID_PARAMETER;
|
||||||
|
|
||||||
// Get data from parsing data
|
// Get data from parsing data
|
||||||
PARSING_DATA pdata = parsingDataFromQByteArray(index);
|
PARSING_DATA pdata = parsingDataFromQModelIndex(index);
|
||||||
|
|
||||||
// Check if all bytes of the file are empty
|
// Check if all bytes of the file are empty
|
||||||
QByteArray body = model->body(index);
|
QByteArray body = model->body(index);
|
||||||
@ -1395,7 +1390,7 @@ STATUS FfsParser::parseSections(QByteArray sections, const QModelIndex & index)
|
|||||||
return ERR_INVALID_PARAMETER;
|
return ERR_INVALID_PARAMETER;
|
||||||
|
|
||||||
// Get data from parsing data
|
// Get data from parsing data
|
||||||
PARSING_DATA pdata = parsingDataFromQByteArray(index);
|
PARSING_DATA pdata = parsingDataFromQModelIndex(index);
|
||||||
|
|
||||||
// Search for and parse all sections
|
// Search for and parse all sections
|
||||||
UINT32 bodySize = sections.size();
|
UINT32 bodySize = sections.size();
|
||||||
@ -1491,7 +1486,7 @@ STATUS FfsParser::parseSectionHeader(const QByteArray & section, const UINT32 pa
|
|||||||
STATUS FfsParser::parseCommonSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index)
|
STATUS FfsParser::parseCommonSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index)
|
||||||
{
|
{
|
||||||
// Get data from parent's parsing data
|
// Get data from parent's parsing data
|
||||||
PARSING_DATA pdata = parsingDataFromQByteArray(parent);
|
PARSING_DATA pdata = parsingDataFromQModelIndex(parent);
|
||||||
|
|
||||||
// Obtain header fields
|
// Obtain header fields
|
||||||
const EFI_COMMON_SECTION_HEADER* sectionHeader = (const EFI_COMMON_SECTION_HEADER*)(section.constData());
|
const EFI_COMMON_SECTION_HEADER* sectionHeader = (const EFI_COMMON_SECTION_HEADER*)(section.constData());
|
||||||
@ -1523,7 +1518,7 @@ STATUS FfsParser::parseCommonSectionHeader(const QByteArray & section, const UIN
|
|||||||
STATUS FfsParser::parseCompressedSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index)
|
STATUS FfsParser::parseCompressedSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index)
|
||||||
{
|
{
|
||||||
// Get data from parent's parsing data
|
// Get data from parent's parsing data
|
||||||
PARSING_DATA pdata = parsingDataFromQByteArray(parent);
|
PARSING_DATA pdata = parsingDataFromQModelIndex(parent);
|
||||||
|
|
||||||
// Obtain header fields
|
// Obtain header fields
|
||||||
const EFI_COMMON_SECTION_HEADER* sectionHeader = (const EFI_COMMON_SECTION_HEADER*)(section.constData());
|
const EFI_COMMON_SECTION_HEADER* sectionHeader = (const EFI_COMMON_SECTION_HEADER*)(section.constData());
|
||||||
@ -1566,7 +1561,7 @@ STATUS FfsParser::parseCompressedSectionHeader(const QByteArray & section, const
|
|||||||
STATUS FfsParser::parseGuidedSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index)
|
STATUS FfsParser::parseGuidedSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index)
|
||||||
{
|
{
|
||||||
// Get data from parent's parsing data
|
// Get data from parent's parsing data
|
||||||
PARSING_DATA pdata = parsingDataFromQByteArray(parent);
|
PARSING_DATA pdata = parsingDataFromQModelIndex(parent);
|
||||||
|
|
||||||
// Obtain header fields
|
// Obtain header fields
|
||||||
const EFI_COMMON_SECTION_HEADER* sectionHeader = (const EFI_COMMON_SECTION_HEADER*)(section.constData());
|
const EFI_COMMON_SECTION_HEADER* sectionHeader = (const EFI_COMMON_SECTION_HEADER*)(section.constData());
|
||||||
@ -1610,7 +1605,7 @@ STATUS FfsParser::parseGuidedSectionHeader(const QByteArray & section, const UIN
|
|||||||
STATUS FfsParser::parseFreeformGuidedSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index)
|
STATUS FfsParser::parseFreeformGuidedSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index)
|
||||||
{
|
{
|
||||||
// Get data from parent's parsing data
|
// Get data from parent's parsing data
|
||||||
PARSING_DATA pdata = parsingDataFromQByteArray(parent);
|
PARSING_DATA pdata = parsingDataFromQModelIndex(parent);
|
||||||
|
|
||||||
// Obtain header fields
|
// Obtain header fields
|
||||||
const EFI_COMMON_SECTION_HEADER* sectionHeader = (const EFI_COMMON_SECTION_HEADER*)(section.constData());
|
const EFI_COMMON_SECTION_HEADER* sectionHeader = (const EFI_COMMON_SECTION_HEADER*)(section.constData());
|
||||||
@ -1697,7 +1692,7 @@ STATUS FfsParser::parseFreeformGuidedSectionHeader(const QByteArray & section, c
|
|||||||
STATUS FfsParser::parseVersionSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index)
|
STATUS FfsParser::parseVersionSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index)
|
||||||
{
|
{
|
||||||
// Get data from parent's parsing data
|
// Get data from parent's parsing data
|
||||||
PARSING_DATA pdata = parsingDataFromQByteArray(parent);
|
PARSING_DATA pdata = parsingDataFromQModelIndex(parent);
|
||||||
|
|
||||||
// Obtain header fields
|
// Obtain header fields
|
||||||
const EFI_COMMON_SECTION_HEADER* sectionHeader = (const EFI_COMMON_SECTION_HEADER*)(section.constData());
|
const EFI_COMMON_SECTION_HEADER* sectionHeader = (const EFI_COMMON_SECTION_HEADER*)(section.constData());
|
||||||
@ -1735,7 +1730,7 @@ STATUS FfsParser::parseVersionSectionHeader(const QByteArray & section, const UI
|
|||||||
STATUS FfsParser::parsePostcodeSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index)
|
STATUS FfsParser::parsePostcodeSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index)
|
||||||
{
|
{
|
||||||
// Get data from parent's parsing data
|
// Get data from parent's parsing data
|
||||||
PARSING_DATA pdata = parsingDataFromQByteArray(parent);
|
PARSING_DATA pdata = parsingDataFromQModelIndex(parent);
|
||||||
|
|
||||||
// Obtain header fields
|
// Obtain header fields
|
||||||
const EFI_COMMON_SECTION_HEADER* sectionHeader = (const EFI_COMMON_SECTION_HEADER*)(section.constData());
|
const EFI_COMMON_SECTION_HEADER* sectionHeader = (const EFI_COMMON_SECTION_HEADER*)(section.constData());
|
||||||
@ -1812,7 +1807,7 @@ STATUS FfsParser::parseCompressedSectionBody(const QModelIndex & index)
|
|||||||
return ERR_INVALID_PARAMETER;
|
return ERR_INVALID_PARAMETER;
|
||||||
|
|
||||||
// Get data from parsing data
|
// Get data from parsing data
|
||||||
PARSING_DATA pdata = parsingDataFromQByteArray(index);
|
PARSING_DATA pdata = parsingDataFromQModelIndex(index);
|
||||||
UINT8 algorithm = pdata.section.compressed.compressionType;
|
UINT8 algorithm = pdata.section.compressed.compressionType;
|
||||||
|
|
||||||
// Decompress section
|
// Decompress section
|
||||||
@ -1852,7 +1847,7 @@ STATUS FfsParser::parseGuidedSectionBody(const QModelIndex & index)
|
|||||||
return ERR_INVALID_PARAMETER;
|
return ERR_INVALID_PARAMETER;
|
||||||
|
|
||||||
// Get data from parsing data
|
// Get data from parsing data
|
||||||
PARSING_DATA pdata = parsingDataFromQByteArray(index);
|
PARSING_DATA pdata = parsingDataFromQModelIndex(index);
|
||||||
UINT32 attributes = pdata.section.guidDefined.attributes;
|
UINT32 attributes = pdata.section.guidDefined.attributes;
|
||||||
EFI_GUID guid = pdata.section.guidDefined.guid;
|
EFI_GUID guid = pdata.section.guidDefined.guid;
|
||||||
|
|
||||||
@ -2243,7 +2238,7 @@ STATUS FfsParser::parseTeImageSectionBody(const QModelIndex & index)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get data from parsing data
|
// Get data from parsing data
|
||||||
PARSING_DATA pdata = parsingDataFromQByteArray(index);
|
PARSING_DATA pdata = parsingDataFromQModelIndex(index);
|
||||||
pdata.section.teImage.imageBase = teHeader->ImageBase;
|
pdata.section.teImage.imageBase = teHeader->ImageBase;
|
||||||
pdata.section.teImage.adjustedImageBase = teHeader->ImageBase + teHeader->StrippedSize - sizeof(EFI_IMAGE_TE_HEADER);
|
pdata.section.teImage.adjustedImageBase = teHeader->ImageBase + teHeader->StrippedSize - sizeof(EFI_IMAGE_TE_HEADER);
|
||||||
|
|
||||||
@ -2264,22 +2259,19 @@ STATUS FfsParser::performSecondPass(const QModelIndex & index)
|
|||||||
return ERR_INVALID_PARAMETER;
|
return ERR_INVALID_PARAMETER;
|
||||||
|
|
||||||
// Get parsing data for the last VTF
|
// Get parsing data for the last VTF
|
||||||
PARSING_DATA pdata = parsingDataFromQByteArray(lastVtf);
|
PARSING_DATA pdata = parsingDataFromQModelIndex(lastVtf);
|
||||||
if (!pdata.isOnFlash) {
|
if (!pdata.isOnFlash) {
|
||||||
msg(tr("addPhysicalAddressInfo: the last VTF appears inside compressed item, the image may be damaged"), lastVtf);
|
msg(tr("performSecondPass: the last VTF appears inside compressed item, the image may be damaged"), lastVtf);
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate address difference
|
// Calculate address difference
|
||||||
const UINT32 vtfSize = model->header(lastVtf).size() + model->body(lastVtf).size() + (pdata.file.hasTail ? sizeof(UINT16) : 0);
|
const UINT32 vtfSize = model->header(lastVtf).size() + model->body(lastVtf).size() + (pdata.file.hasTail ? sizeof(UINT16) : 0);
|
||||||
const UINT32 diff = 0xFFFFFFFF - pdata.offset - vtfSize + 1;
|
const UINT32 diff = 0xFFFFFFFFUL - pdata.offset - vtfSize + 1;
|
||||||
|
|
||||||
// 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);
|
||||||
|
|
||||||
// Find and parse FIT
|
|
||||||
parseFit();
|
|
||||||
|
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2290,12 +2282,12 @@ STATUS FfsParser::addMemoryAddressesRecursive(const QModelIndex & index, const U
|
|||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
|
|
||||||
// Get parsing data for the current item
|
// Get parsing data for the current item
|
||||||
PARSING_DATA pdata = parsingDataFromQByteArray(index);
|
PARSING_DATA pdata = parsingDataFromQModelIndex(index);
|
||||||
|
|
||||||
// Set address value for non-compressed data
|
// Set address value for non-compressed data
|
||||||
if (pdata.isOnFlash) {
|
if (pdata.isOnFlash) {
|
||||||
// Check address sanity
|
// Check address sanity
|
||||||
if ((const UINT64)diff + pdata.offset <= 0xFFFFFFFF) {
|
if ((const UINT64)diff + pdata.offset <= 0xFFFFFFFFUL) {
|
||||||
// Update info
|
// Update info
|
||||||
pdata.address = diff + pdata.offset;
|
pdata.address = diff + pdata.offset;
|
||||||
UINT32 headerSize = model->header(index).size();
|
UINT32 headerSize = model->header(index).size();
|
||||||
@ -2335,13 +2327,69 @@ STATUS FfsParser::addMemoryAddressesRecursive(const QModelIndex & index, const U
|
|||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATUS FfsParser::parseFit()
|
/*STATUS FfsParser::parseFit(const QModelIndex & index)
|
||||||
{
|
{
|
||||||
// Check sanity
|
// Check sanity
|
||||||
if (!lastVtf.isValid)
|
if (!lastVtf.isValid())
|
||||||
return EFI_INVALID_PARAMETER;
|
return EFI_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
// Search for FIT
|
||||||
|
QModelIndex fitIndex;
|
||||||
|
STATUS result = findFitRecursive(index, fitIndex);
|
||||||
|
if (result)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
// FIT not found
|
||||||
|
if (!fitIndex.isValid())
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
|
||||||
|
// Get parsing data for the current item
|
||||||
|
PARSING_DATA pdata = parsingDataFromQModelIndex(fitIndex);
|
||||||
|
|
||||||
|
// Explicitly set the item as fixed
|
||||||
|
pdata.fixed = TRUE;
|
||||||
|
|
||||||
|
// Set modified parsing data
|
||||||
|
model->setParsingData(fitIndex, parsingDataToQByteArray(pdata));
|
||||||
|
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STATUS FfsParser::findFitRecursive(const QModelIndex & index, QModelIndex & found)
|
||||||
|
{
|
||||||
|
// Sanity check
|
||||||
|
if (!index.isValid())
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
|
||||||
|
// Process child items
|
||||||
|
for (int i = 0; i < model->rowCount(index); i++) {
|
||||||
|
findFitRecursive(index.child(i, 0), found);
|
||||||
|
if (found.isValid())
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get parsing data for the current item
|
||||||
|
PARSING_DATA pdata = parsingDataFromQModelIndex(index);
|
||||||
|
|
||||||
|
// Check item's address to be in required range
|
||||||
|
INT32 offset = model->body(index).indexOf(FIT_SIGNATURE);
|
||||||
|
// Check for FIT signature in item's body
|
||||||
|
if (offset >= 0) {
|
||||||
|
// FIT candidate found, calculate it's offset and physical address
|
||||||
|
UINT32 fitOffset = pdata.offset + model->header(index).size() + (UINT32)offset;
|
||||||
|
UINT32 fitAddress = pdata.address + model->header(index).size() + (UINT32)offset;
|
||||||
|
|
||||||
|
// Check FIT address to be in the last VTF
|
||||||
|
QByteArray lastVtfBody = model->body(lastVtf);
|
||||||
|
if (*(const UINT32*)(lastVtfBody.constData() + lastVtfBody.size() - FIT_POINTER_OFFSET) == fitAddress) {
|
||||||
|
msg(tr("findFitRecursive: FIT table found at offset %1h, physical address %2h")
|
||||||
|
.hexarg2(fitOffset, 8)
|
||||||
|
.hexarg2(fitAddress, 8),
|
||||||
|
index);
|
||||||
|
found = index;
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
}*/
|
@ -53,6 +53,9 @@ public:
|
|||||||
STATUS parseSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
|
STATUS parseSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
|
||||||
STATUS parseSectionBody(const QModelIndex & index);
|
STATUS parseSectionBody(const QModelIndex & index);
|
||||||
|
|
||||||
|
// Retuns index of the last VTF after parsing is done
|
||||||
|
const QModelIndex getLastVtf() {return lastVtf;};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TreeModel *model;
|
TreeModel *model;
|
||||||
QVector<QPair<QString, QModelIndex> > messagesVector;
|
QVector<QPair<QString, QModelIndex> > messagesVector;
|
||||||
@ -92,7 +95,8 @@ private:
|
|||||||
|
|
||||||
STATUS performSecondPass(const QModelIndex & index);
|
STATUS performSecondPass(const QModelIndex & index);
|
||||||
STATUS addMemoryAddressesRecursive(const QModelIndex & index, const UINT32 diff);
|
STATUS addMemoryAddressesRecursive(const QModelIndex & index, const UINT32 diff);
|
||||||
STATUS parseFit();
|
/*STATUS parseFit(const QModelIndex & index);
|
||||||
|
STATUS findFitRecursive(const QModelIndex & index, QModelIndex & found);*/
|
||||||
|
|
||||||
// Internal operations
|
// Internal operations
|
||||||
BOOLEAN hasIntersection(const UINT32 begin1, const UINT32 end1, const UINT32 begin2, const UINT32 end2);
|
BOOLEAN hasIntersection(const UINT32 begin1, const UINT32 end1, const UINT32 begin2, const UINT32 end2);
|
||||||
|
12
common/fit.h
12
common/fit.h
@ -20,10 +20,7 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
#pragma pack(push,1)
|
#pragma pack(push,1)
|
||||||
|
|
||||||
// Memory address of a pointer to FIT, 40h back from the end of flash chip
|
// Memory address of a pointer to FIT, 40h back from the end of flash chip
|
||||||
#define FIT_POINTER_ADDRESS 0xFFFFFFC0
|
#define FIT_POINTER_OFFSET 0x40
|
||||||
|
|
||||||
// FIT can reside in the last 1 MB of the flash chip
|
|
||||||
#define FIT_TABLE_LOWEST_ADDRESS 0xFF000000
|
|
||||||
|
|
||||||
// Entry types
|
// Entry types
|
||||||
#define FIT_TYPE_HEADER 0x00
|
#define FIT_TYPE_HEADER 0x00
|
||||||
@ -35,7 +32,7 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
#define FIT_TYPE_TXT_CONF_POLICY 0x0A
|
#define FIT_TYPE_TXT_CONF_POLICY 0x0A
|
||||||
#define FIT_TYPE_AC_KEY_MANIFEST 0x0B
|
#define FIT_TYPE_AC_KEY_MANIFEST 0x0B
|
||||||
#define FIT_TYPE_AC_BOOT_POLICY 0x0C
|
#define FIT_TYPE_AC_BOOT_POLICY 0x0C
|
||||||
#define FIT_TYPE_EMPTY 0xFF
|
#define FIT_TYPE_EMPTY 0x7F
|
||||||
|
|
||||||
#define FIT_HEADER_VERSION 0x0100
|
#define FIT_HEADER_VERSION 0x0100
|
||||||
#define FIT_MICROCODE_VERSION 0x0100
|
#define FIT_MICROCODE_VERSION 0x0100
|
||||||
@ -45,10 +42,9 @@ const QByteArray FIT_SIGNATURE
|
|||||||
|
|
||||||
typedef struct _FIT_ENTRY {
|
typedef struct _FIT_ENTRY {
|
||||||
UINT64 Address;
|
UINT64 Address;
|
||||||
UINT64 ReservedSize;
|
UINT32 Size;
|
||||||
UINT16 Version;
|
UINT16 Version;
|
||||||
UINT8 ChecksumValid : 1;
|
UINT8 Type;
|
||||||
UINT8 Type : 7;
|
|
||||||
UINT8 Checksum;
|
UINT8 Checksum;
|
||||||
} FIT_ENTRY;
|
} FIT_ENTRY;
|
||||||
|
|
||||||
|
152
common/fitparser.cpp
Normal file
152
common/fitparser.cpp
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
/* 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"
|
||||||
|
#include "types.h"
|
||||||
|
#include "treemodel.h"
|
||||||
|
|
||||||
|
|
||||||
|
FitParser::FitParser(TreeModel* treeModel, QObject *parent)
|
||||||
|
: QObject(parent), model(treeModel)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
FitParser::~FitParser()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
STATUS FitParser::parse(const QModelIndex & index, const QModelIndex & lastVtfIndex)
|
||||||
|
{
|
||||||
|
// Check sanity
|
||||||
|
if (!index.isValid() || !lastVtfIndex.isValid())
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
// Store lastVtfIndex
|
||||||
|
lastVtf = lastVtfIndex;
|
||||||
|
|
||||||
|
// Search for FIT
|
||||||
|
QModelIndex fitIndex;
|
||||||
|
UINT32 fitOffset;
|
||||||
|
STATUS result = findFitRecursive(index, fitIndex, fitOffset);
|
||||||
|
if (result)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
// FIT not found
|
||||||
|
if (!fitIndex.isValid())
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
|
||||||
|
// Get parsing data for the current item
|
||||||
|
PARSING_DATA pdata = parsingDataFromQModelIndex(fitIndex);
|
||||||
|
|
||||||
|
// Explicitly set the item as fixed
|
||||||
|
pdata.fixed = TRUE;
|
||||||
|
|
||||||
|
// Set modified parsing data
|
||||||
|
model->setParsingData(fitIndex, parsingDataToQByteArray(pdata));
|
||||||
|
|
||||||
|
// Add all FIT entries into QVector
|
||||||
|
const FIT_ENTRY* fitHeader = (const FIT_ENTRY*)(model->body(fitIndex).constData() + fitOffset);
|
||||||
|
|
||||||
|
// Special case of FIT header
|
||||||
|
QString remark;
|
||||||
|
|
||||||
|
// Check FIT checksum, if present
|
||||||
|
if (fitHeader->Type & 0x80) {
|
||||||
|
// Calculate FIT entry checksum
|
||||||
|
UINT32 fitSize = (fitHeader->Size & 0xFFFFFF) << 4;
|
||||||
|
UINT8 calculated = calculateChecksum8((const UINT8*)fitHeader, fitSize);
|
||||||
|
if (calculated) {
|
||||||
|
remark.append(tr("Invalid FIT table checksum, ").hexarg2(calculated, 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check fit header version and type
|
||||||
|
if (fitHeader->Version != FIT_HEADER_VERSION) {
|
||||||
|
remark.append(tr("Invalid FIT header version, "));
|
||||||
|
}
|
||||||
|
if ((fitHeader->Type & 0x7F) != FIT_TYPE_HEADER) {
|
||||||
|
remark.append(tr("Invalid FIT header type, "));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the last ", " from remark string, if needed
|
||||||
|
if (!remark.isEmpty())
|
||||||
|
remark = remark.left(remark.length() - 2);
|
||||||
|
|
||||||
|
// Add FIT header to fitEntries vector
|
||||||
|
fitEntries.append(QPair<FIT_ENTRY, QString>(*fitHeader, remark));
|
||||||
|
|
||||||
|
// Process all other entries
|
||||||
|
for (UINT32 i = 1; i < fitHeader->Size; i++) {
|
||||||
|
remark.clear();
|
||||||
|
const FIT_ENTRY* currentEntry = fitHeader + i;
|
||||||
|
|
||||||
|
// Check entry type
|
||||||
|
switch (currentEntry->Type & 0x7F) {
|
||||||
|
case FIT_TYPE_HEADER:
|
||||||
|
remark.append(tr("Second FIT header found, the table is damaged"));
|
||||||
|
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:
|
||||||
|
remark.append(tr("Modified image may not work"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fitEntries.append(QPair<FIT_ENTRY, QString>(*currentEntry, remark));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATUS FitParser::findFitRecursive(const QModelIndex & index, QModelIndex & found, UINT32 & fitOffset)
|
||||||
|
{
|
||||||
|
// Sanity check
|
||||||
|
if (!index.isValid())
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
|
||||||
|
// Process child items
|
||||||
|
for (int i = 0; i < model->rowCount(index); i++) {
|
||||||
|
findFitRecursive(index.child(i, 0), found, fitOffset);
|
||||||
|
if (found.isValid())
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get parsing data for the current item
|
||||||
|
PARSING_DATA pdata = parsingDataFromQModelIndex(index);
|
||||||
|
|
||||||
|
// Check item's address to be in required range
|
||||||
|
INT32 offset = model->body(index).indexOf(FIT_SIGNATURE);
|
||||||
|
// Check for FIT signature in item's body
|
||||||
|
if (offset >= 0) {
|
||||||
|
// 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
|
||||||
|
QByteArray lastVtfBody = model->body(lastVtf);
|
||||||
|
if (*(const UINT32*)(lastVtfBody.constData() + lastVtfBody.size() - FIT_POINTER_OFFSET) == fitAddress) {
|
||||||
|
found = index;
|
||||||
|
fitOffset = offset;
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
}
|
50
common/fitparser.h
Normal file
50
common/fitparser.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/* 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 <QObject>
|
||||||
|
#include <QModelIndex>
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QVector>
|
||||||
|
|
||||||
|
#include "basetypes.h"
|
||||||
|
#include "treemodel.h"
|
||||||
|
#include "utility.h"
|
||||||
|
#include "parsingdata.h"
|
||||||
|
#include "fit.h"
|
||||||
|
|
||||||
|
class TreeModel;
|
||||||
|
|
||||||
|
class FitParser : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Default constructor and destructor
|
||||||
|
FitParser(TreeModel* treeModel, QObject *parent = 0);
|
||||||
|
~FitParser();
|
||||||
|
|
||||||
|
STATUS parse(const QModelIndex & index, const QModelIndex & lastVtf);
|
||||||
|
QVector<QPair<FIT_ENTRY, QString> > getFitEntries() const { return fitEntries; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
TreeModel *model;
|
||||||
|
QModelIndex lastVtf;
|
||||||
|
QVector<QPair<FIT_ENTRY, QString> > fitEntries;
|
||||||
|
|
||||||
|
STATUS findFitRecursive(const QModelIndex & index, QModelIndex & found, UINT32 & fitOffset);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -34,7 +34,8 @@ typedef struct _VOLUME_PARSING_DATA {
|
|||||||
UINT32 alignment;
|
UINT32 alignment;
|
||||||
UINT8 revision;
|
UINT8 revision;
|
||||||
BOOLEAN hasExtendedHeader;
|
BOOLEAN hasExtendedHeader;
|
||||||
BOOLEAN hasZeroVectorCRC32;
|
BOOLEAN hasAppleCrc32;
|
||||||
|
BOOLEAN hasAppleFSO;
|
||||||
BOOLEAN isWeakAligned;
|
BOOLEAN isWeakAligned;
|
||||||
} VOLUME_PARSING_DATA;
|
} VOLUME_PARSING_DATA;
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
#include "LZMA/LzmaDecompress.h"
|
#include "LZMA/LzmaDecompress.h"
|
||||||
|
|
||||||
// Returns either new parsing data instance or obtains it from index
|
// Returns either new parsing data instance or obtains it from index
|
||||||
PARSING_DATA parsingDataFromQByteArray(const QModelIndex & index)
|
PARSING_DATA parsingDataFromQModelIndex(const QModelIndex & index)
|
||||||
{
|
{
|
||||||
if (index.isValid()) {
|
if (index.isValid()) {
|
||||||
TreeModel* model = (TreeModel*)index.model();
|
TreeModel* model = (TreeModel*)index.model();
|
||||||
@ -257,3 +257,34 @@ STATUS decompress(const QByteArray & compressedData, UINT8 & algorithm, QByteArr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 8bit checksum calculation routine
|
||||||
|
UINT8 calculateChecksum8(const UINT8* buffer, UINT32 bufferSize)
|
||||||
|
{
|
||||||
|
if (!buffer)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
UINT8 counter = 0;
|
||||||
|
|
||||||
|
while (bufferSize--)
|
||||||
|
counter += buffer[bufferSize];
|
||||||
|
|
||||||
|
return (UINT8)(0x100 - counter);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 16bit checksum calculation routine
|
||||||
|
UINT16 calculateChecksum16(const UINT16* buffer, UINT32 bufferSize)
|
||||||
|
{
|
||||||
|
if (!buffer)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
UINT16 counter = 0;
|
||||||
|
UINT32 index = 0;
|
||||||
|
|
||||||
|
bufferSize /= sizeof(UINT16);
|
||||||
|
|
||||||
|
for (; index < bufferSize; index++) {
|
||||||
|
counter = (UINT16)(counter + buffer[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (UINT16)(0x10000 - counter);
|
||||||
|
}
|
@ -20,7 +20,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
#include "parsingdata.h"
|
#include "parsingdata.h"
|
||||||
|
|
||||||
// Returns either new parsing data instance or obtains it from index
|
// Returns either new parsing data instance or obtains it from index
|
||||||
PARSING_DATA parsingDataFromQByteArray(const QModelIndex & index);
|
PARSING_DATA parsingDataFromQModelIndex(const QModelIndex & index);
|
||||||
|
|
||||||
// Converts parsing data to byte array
|
// Converts parsing data to byte array
|
||||||
QByteArray parsingDataToQByteArray(const PARSING_DATA & pdata);
|
QByteArray parsingDataToQByteArray(const PARSING_DATA & pdata);
|
||||||
@ -34,7 +34,13 @@ extern STATUS decompress(const QByteArray & compressed, UINT8 & algorithm, QByte
|
|||||||
// Compression routine
|
// Compression routine
|
||||||
//STATUS compress(const QByteArray & decompressed, QByteArray & compressed, const UINT8 & algorithm);
|
//STATUS compress(const QByteArray & decompressed, QByteArray & compressed, const UINT8 & algorithm);
|
||||||
|
|
||||||
// CRC32
|
// CRC32 calculation routine
|
||||||
extern UINT32 crc32(UINT32 initial, const UINT8* buffer, UINT32 length);
|
extern UINT32 crc32(UINT32 initial, const UINT8* buffer, UINT32 length);
|
||||||
|
|
||||||
|
// 8bit checksum calculation routine
|
||||||
|
extern UINT8 calculateChecksum8(const UINT8* buffer, UINT32 bufferSize);
|
||||||
|
|
||||||
|
// 16bit checksum calculation routine
|
||||||
|
extern UINT16 calculateChecksum16(const UINT16* buffer, UINT32 bufferSize);
|
||||||
|
|
||||||
#endif
|
#endif
|
Loading…
Reference in New Issue
Block a user