mirror of
https://github.com/LongSoft/UEFITool.git
synced 2024-11-22 07:58:22 +08:00
Version 0.8.0
- code slightly refactored - solved bug on working with file tail
This commit is contained in:
parent
1c005d5025
commit
3d7dad6bb6
@ -83,6 +83,8 @@ typedef uint16_t CHAR16;
|
|||||||
#define ERR_STANDARD_DECOMPRESSION_FAILED 24
|
#define ERR_STANDARD_DECOMPRESSION_FAILED 24
|
||||||
#define ERR_CUSTOMIZED_DECOMPRESSION_FAILED 25
|
#define ERR_CUSTOMIZED_DECOMPRESSION_FAILED 25
|
||||||
#define ERR_UNKNOWN_COMPRESSION_ALGORITHM 26
|
#define ERR_UNKNOWN_COMPRESSION_ALGORITHM 26
|
||||||
|
#define ERR_UNKNOWN_EXTRACT_MODE 27
|
||||||
|
#define ERR_UNKNOWN_INSERT_MODE 28
|
||||||
#define ERR_NOT_IMPLEMENTED 0xFF
|
#define ERR_NOT_IMPLEMENTED 0xFF
|
||||||
|
|
||||||
// Compression algorithms
|
// Compression algorithms
|
||||||
@ -93,6 +95,11 @@ typedef uint16_t CHAR16;
|
|||||||
#define COMPRESSION_ALGORITHM_LZMA 4
|
#define COMPRESSION_ALGORITHM_LZMA 4
|
||||||
#define COMPRESSION_ALGORITHM_IMLZMA 5
|
#define COMPRESSION_ALGORITHM_IMLZMA 5
|
||||||
|
|
||||||
|
// Item extract modes
|
||||||
|
#define EXTRACT_MODE_AS_IS 0
|
||||||
|
#define EXTRACT_MODE_BODY_ONLY 1
|
||||||
|
#define EXTRACT_MODE_UNCOMPRESSED 2
|
||||||
|
|
||||||
// Item insert modes
|
// Item insert modes
|
||||||
#define INSERT_MODE_APPEND 0
|
#define INSERT_MODE_APPEND 0
|
||||||
#define INSERT_MODE_PREPEND 1
|
#define INSERT_MODE_PREPEND 1
|
||||||
|
@ -25,7 +25,7 @@ QString regionTypeToQString(const UINT8 type)
|
|||||||
case TreeItem::MeRegion:
|
case TreeItem::MeRegion:
|
||||||
return QObject::tr("ME");
|
return QObject::tr("ME");
|
||||||
case TreeItem::BiosRegion:
|
case TreeItem::BiosRegion:
|
||||||
return QObject::tr("Bios");
|
return QObject::tr("BIOS");
|
||||||
case TreeItem::PdrRegion:
|
case TreeItem::PdrRegion:
|
||||||
return QObject::tr("PDR");
|
return QObject::tr("PDR");
|
||||||
default:
|
default:
|
||||||
|
457
ffsengine.cpp
457
ffsengine.cpp
@ -48,66 +48,12 @@ TreeModel* FfsEngine::model() const
|
|||||||
|
|
||||||
void FfsEngine::msg(const QString & message, const QModelIndex index)
|
void FfsEngine::msg(const QString & message, const QModelIndex index)
|
||||||
{
|
{
|
||||||
debugItems.enqueue(new DebugListItem(message, NULL, 0, index));
|
messageItems.enqueue(new MessageListItem(message, NULL, 0, index));
|
||||||
}
|
}
|
||||||
|
|
||||||
QQueue<DebugListItem*> FfsEngine::debugMessage()
|
QQueue<MessageListItem*> FfsEngine::message()
|
||||||
{
|
{
|
||||||
return debugItems;
|
return messageItems;
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray FfsEngine::header(const QModelIndex& index) const
|
|
||||||
{
|
|
||||||
if (!index.isValid())
|
|
||||||
return QByteArray();
|
|
||||||
|
|
||||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
|
||||||
return item->header();
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray FfsEngine::body(const QModelIndex& index) const
|
|
||||||
{
|
|
||||||
if (!index.isValid())
|
|
||||||
return QByteArray();
|
|
||||||
|
|
||||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
|
||||||
return item->body();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FfsEngine::hasEmptyHeader(const QModelIndex& index) const
|
|
||||||
{
|
|
||||||
if (!index.isValid())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
|
||||||
|
|
||||||
return item->hasEmptyHeader();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FfsEngine::hasEmptyBody(const QModelIndex& index) const
|
|
||||||
{
|
|
||||||
if (!index.isValid())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
|
||||||
|
|
||||||
return item->hasEmptyBody();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FfsEngine::setTreeItemName(const QString &data, const QModelIndex &index)
|
|
||||||
{
|
|
||||||
if(!index.isValid())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return treeModel->setItemName(data, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FfsEngine::setTreeItemText(const QString &data, const QModelIndex &index)
|
|
||||||
{
|
|
||||||
if(!index.isValid())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return treeModel->setItemText(data, index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QModelIndex FfsEngine::findParentOfType(UINT8 type, const QModelIndex& index) const
|
QModelIndex FfsEngine::findParentOfType(UINT8 type, const QModelIndex& index) const
|
||||||
@ -128,32 +74,17 @@ QModelIndex FfsEngine::findParentOfType(UINT8 type, const QModelIndex& index) co
|
|||||||
return QModelIndex();
|
return QModelIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FfsEngine::isOfType(UINT8 type, const QModelIndex & index) const
|
bool FfsEngine::hasIntersection(const UINT32 begin1, const UINT32 end1, const UINT32 begin2, const UINT32 end2)
|
||||||
{
|
|
||||||
if (!index.isValid())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
|
||||||
return (item->type() == type);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FfsEngine::isOfSubtype(UINT8 subtype, const QModelIndex & index) const
|
|
||||||
{
|
|
||||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
|
||||||
return (item->subtype() == subtype);
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT8 FfsEngine::hasIntersection(const UINT32 begin1, const UINT32 end1, const UINT32 begin2, const UINT32 end2)
|
|
||||||
{
|
{
|
||||||
if (begin1 < begin2 && begin2 < end1)
|
if (begin1 < begin2 && begin2 < end1)
|
||||||
return 1;
|
return true;
|
||||||
if (begin1 < end2 && end2 < end1)
|
if (begin1 < end2 && end2 < end1)
|
||||||
return 1;
|
return true;
|
||||||
if (begin2 < begin1 && begin1 < end2)
|
if (begin2 < begin1 && begin1 < end2)
|
||||||
return 1;
|
return true;
|
||||||
if (begin2 < end1 && end1 < end2)
|
if (begin2 < end1 && end1 < end2)
|
||||||
return 1;
|
return true;
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Firmware image parsing
|
// Firmware image parsing
|
||||||
@ -222,10 +153,10 @@ UINT8 FfsEngine::parseInputFile(const QByteArray & buffer)
|
|||||||
// Get info
|
// Get info
|
||||||
QString name = tr("BIOS image");
|
QString name = tr("BIOS image");
|
||||||
QString info = tr("Size: %1")
|
QString info = tr("Size: %1")
|
||||||
.arg(buffer.size(), 8, 16, QChar('0'));
|
.arg(flashImage.size(), 8, 16, QChar('0'));
|
||||||
|
|
||||||
// Add tree item
|
// Add tree item
|
||||||
index = treeModel->addItem(TreeItem::Image, 0, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), buffer, index);
|
index = treeModel->addItem(TreeItem::Image, TreeItem::BiosImage, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), flashImage, QByteArray(), index);
|
||||||
return parseBios(flashImage, index);
|
return parseBios(flashImage, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,34 +273,54 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & flashImage, const QModelInde
|
|||||||
QByteArray body;
|
QByteArray body;
|
||||||
QString name;
|
QString name;
|
||||||
QString info;
|
QString info;
|
||||||
|
|
||||||
|
//!TODO: reorganize info
|
||||||
// Intel image
|
// Intel image
|
||||||
name = tr("Intel image");
|
name = tr("Intel image");
|
||||||
info = tr("Size: %1").arg(flashImage.size(), 4, 16, QChar('0'));
|
|
||||||
// Add tree item
|
|
||||||
QModelIndex index = treeModel->addItem(TreeItem::IntelImage, 0, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), flashImage, parent);
|
|
||||||
|
|
||||||
// Descriptor
|
|
||||||
// Get descriptor info
|
|
||||||
body = flashImage.left(FLASH_DESCRIPTOR_SIZE);
|
|
||||||
name = tr("Descriptor region");
|
|
||||||
info = tr("Size: %1\nFlash chips: %2\nRegions: %3\nMasters: %4\nPCH straps: %5\nPROC straps: %6\nICC table entries: %7")
|
info = tr("Size: %1\nFlash chips: %2\nRegions: %3\nMasters: %4\nPCH straps: %5\nPROC straps: %6\nICC table entries: %7")
|
||||||
.arg(FLASH_DESCRIPTOR_SIZE, 8, 16, QChar('0'))
|
.arg(flashImage.size(), 8, 16, QChar('0'))
|
||||||
.arg(descriptorMap->NumberOfFlashChips + 1) //
|
.arg(descriptorMap->NumberOfFlashChips + 1) //
|
||||||
.arg(descriptorMap->NumberOfRegions + 1) // Zero-based numbers in storage
|
.arg(descriptorMap->NumberOfRegions + 1) // Zero-based numbers in storage
|
||||||
.arg(descriptorMap->NumberOfMasters + 1) //
|
.arg(descriptorMap->NumberOfMasters + 1) //
|
||||||
.arg(descriptorMap->NumberOfPchStraps)
|
.arg(descriptorMap->NumberOfPchStraps)
|
||||||
.arg(descriptorMap->NumberOfProcStraps)
|
.arg(descriptorMap->NumberOfProcStraps)
|
||||||
.arg(descriptorMap->NumberOfIccTableEntries);
|
.arg(descriptorMap->NumberOfIccTableEntries);
|
||||||
// Add tree item
|
|
||||||
treeModel->addItem(TreeItem::Region, 0, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), body, index);
|
|
||||||
|
|
||||||
// Sort rest of regions in ascending order
|
// Add Intel image tree item
|
||||||
|
QModelIndex index = treeModel->addItem(TreeItem::Image, TreeItem::IntelImage, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), flashImage, QByteArray(), parent);
|
||||||
|
|
||||||
|
// Descriptor
|
||||||
|
// Get descriptor info
|
||||||
|
body = flashImage.left(FLASH_DESCRIPTOR_SIZE);
|
||||||
|
name = tr("Descriptor region");
|
||||||
|
info = tr("Size: %1").arg(FLASH_DESCRIPTOR_SIZE, 4, 16, QChar('0'));
|
||||||
|
|
||||||
|
// Check regions presence once again
|
||||||
QVector<UINT32> offsets;
|
QVector<UINT32> offsets;
|
||||||
if (regionSection->GbeLimit) offsets.append(gbeBegin);
|
if (regionSection->GbeLimit) {
|
||||||
if (regionSection->MeLimit) offsets.append(meBegin);
|
offsets.append(gbeBegin);
|
||||||
if (regionSection->BiosLimit) offsets.append(biosBegin);
|
info += tr("\nGbE region offset: %1").arg(gbeBegin, 8, 16, QChar('0'));
|
||||||
if (regionSection->PdrLimit) offsets.append(pdrBegin);
|
}
|
||||||
|
if (regionSection->MeLimit) {
|
||||||
|
offsets.append(meBegin);
|
||||||
|
info += tr("\nME region offset: %1").arg(meBegin, 8, 16, QChar('0'));
|
||||||
|
}
|
||||||
|
if (regionSection->BiosLimit) {
|
||||||
|
offsets.append(biosBegin);
|
||||||
|
info += tr("\nBIOS region offset: %1").arg(biosBegin, 8, 16, QChar('0'));
|
||||||
|
}
|
||||||
|
if (regionSection->PdrLimit) {
|
||||||
|
offsets.append(pdrBegin);
|
||||||
|
info += tr("\nPDR region offset: %1").arg(pdrBegin, 8, 16, QChar('0'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add descriptor tree item
|
||||||
|
treeModel->addItem(TreeItem::Region, TreeItem::DescriptorRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), body, QByteArray(), index);
|
||||||
|
|
||||||
|
// Sort regions in ascending order
|
||||||
qSort(offsets);
|
qSort(offsets);
|
||||||
|
|
||||||
|
// Parse regions
|
||||||
UINT8 result;
|
UINT8 result;
|
||||||
for (int i = 0; i < offsets.count(); i++) {
|
for (int i = 0; i < offsets.count(); i++) {
|
||||||
// Parse GbE region
|
// Parse GbE region
|
||||||
@ -391,6 +342,7 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & flashImage, const QModelInde
|
|||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -415,7 +367,7 @@ UINT8 FfsEngine::parseGbeRegion(const QByteArray & gbe, const QModelIndex & pare
|
|||||||
.arg(version->minor);
|
.arg(version->minor);
|
||||||
|
|
||||||
// Add tree item
|
// Add tree item
|
||||||
treeModel->addItem(TreeItem::Region, TreeItem::GbeRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), gbe, parent);
|
treeModel->addItem(TreeItem::Region, TreeItem::GbeRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), gbe, QByteArray(), parent);
|
||||||
|
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -446,7 +398,7 @@ UINT8 FfsEngine::parseMeRegion(const QByteArray & me, const QModelIndex & parent
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add tree item
|
// Add tree item
|
||||||
treeModel->addItem(TreeItem::Region, TreeItem::MeRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), me, parent);
|
treeModel->addItem(TreeItem::Region, TreeItem::MeRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), me, QByteArray(), parent);
|
||||||
|
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -462,7 +414,7 @@ UINT8 FfsEngine::parsePdrRegion(const QByteArray & pdr, const QModelIndex & pare
|
|||||||
arg(pdr.size(), 8, 16, QChar('0'));
|
arg(pdr.size(), 8, 16, QChar('0'));
|
||||||
|
|
||||||
// Add tree item
|
// Add tree item
|
||||||
treeModel->addItem(TreeItem::Region, TreeItem::PdrRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), pdr, parent);
|
treeModel->addItem(TreeItem::Region, TreeItem::PdrRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), pdr, QByteArray(), parent);
|
||||||
|
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -478,133 +430,11 @@ UINT8 FfsEngine::parseBiosRegion(const QByteArray & bios, const QModelIndex & pa
|
|||||||
arg(bios.size(), 8, 16, QChar('0'));
|
arg(bios.size(), 8, 16, QChar('0'));
|
||||||
|
|
||||||
// Add tree item
|
// Add tree item
|
||||||
QModelIndex index = treeModel->addItem(TreeItem::Region, TreeItem::BiosRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), bios, parent);
|
QModelIndex index = treeModel->addItem(TreeItem::Region, TreeItem::BiosRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), bios, QByteArray(), parent);
|
||||||
|
|
||||||
return parseBios(bios, index);
|
return parseBios(bios, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*UINT8 FfsEngine::parseRegion(const QByteArray & flashImage, const UINT16 regionBase, const UINT16 regionLimit, const QModelIndex & parent, QModelIndex & regionIndex)
|
|
||||||
{
|
|
||||||
// Check for empty region or flash image
|
|
||||||
if (!regionLimit || flashImage.size() <= 0)
|
|
||||||
return ERR_EMPTY_REGION;
|
|
||||||
|
|
||||||
// Storing flash image size to unsigned variable, because it can't be negative now and all other values are unsigned
|
|
||||||
UINT32 flashImageSize = (UINT32) flashImage.size();
|
|
||||||
|
|
||||||
// Calculate region offset and size
|
|
||||||
UINT32 regionOffset = calculateRegionOffset(regionBase);
|
|
||||||
UINT32 regionSize = calculateRegionSize(regionBase, regionLimit);
|
|
||||||
|
|
||||||
// Populate descriptor map
|
|
||||||
FLASH_DESCRIPTOR_MAP* descriptorMap = (FLASH_DESCRIPTOR_MAP*) (flashImage.constData() + sizeof(FLASH_DESCRIPTOR_HEADER));
|
|
||||||
|
|
||||||
// Determine presence of 2 flash chips
|
|
||||||
bool twoChips = descriptorMap->NumberOfFlashChips;
|
|
||||||
|
|
||||||
// Determine region subtype
|
|
||||||
UINT8 regionSubtype;
|
|
||||||
FLASH_DESCRIPTOR_REGION_SECTION* regionSection = (FLASH_DESCRIPTOR_REGION_SECTION*) calculateAddress8((UINT8*)flashImage.constData(), descriptorMap->RegionBase);
|
|
||||||
if (regionBase == regionSection->GbeBase)
|
|
||||||
regionSubtype = TreeItem::GbeRegion;
|
|
||||||
else if (regionBase == regionSection->MeBase)
|
|
||||||
regionSubtype = TreeItem::MeRegion;
|
|
||||||
else if (regionBase == regionSection->BiosBase)
|
|
||||||
regionSubtype = TreeItem::BiosRegion;
|
|
||||||
else if (regionBase == regionSection->PdrBase)
|
|
||||||
regionSubtype = TreeItem::PdrRegion;
|
|
||||||
else
|
|
||||||
return ERR_UNKNOWN_ITEM_TYPE;
|
|
||||||
|
|
||||||
// Construct region name
|
|
||||||
QString regionName = regionTypeToQString(regionSubtype);
|
|
||||||
|
|
||||||
// Check region base to be in buffer
|
|
||||||
if (regionOffset >= flashImageSize)
|
|
||||||
{
|
|
||||||
msg(tr("parseRegion: %1 region stored in descriptor not found").arg(regionName), parent);
|
|
||||||
if (twoChips)
|
|
||||||
msg(tr("Two flash chips installed, so it could be in another flash chip\n"
|
|
||||||
"Make a dump from another flash chip and open it to view information about %1 region").arg(regionName), parent);
|
|
||||||
else
|
|
||||||
msg(tr("One flash chip installed, so it is an error caused by damaged or incomplete dump"), parent);
|
|
||||||
msg(tr("Absence of %1 region assumed").arg(regionName), parent);
|
|
||||||
return ERR_INVALID_REGION;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check region to be fully present in buffer
|
|
||||||
else if (regionOffset + regionSize > flashImageSize)
|
|
||||||
{
|
|
||||||
msg(tr("parseRegion: %1 region stored in descriptor overlaps the end of opened file").arg(regionName), parent);
|
|
||||||
if (twoChips)
|
|
||||||
msg(tr("Two flash chips installed, so it could be in another flash chip\n"
|
|
||||||
"Make a dump from another flash chip and open it to view information about %1 region").arg(regionName), parent);
|
|
||||||
else
|
|
||||||
msg(tr("One flash chip installed, so it is an error caused by damaged or incomplete dump"), parent);
|
|
||||||
msg(tr("Absence of %1 region assumed\n").arg(regionName), parent);
|
|
||||||
return ERR_INVALID_REGION;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get info
|
|
||||||
QByteArray body = flashImage.mid(regionOffset, regionSize);
|
|
||||||
QString name;
|
|
||||||
QString info;
|
|
||||||
GBE_MAC* gbeMac;
|
|
||||||
GBE_VERSION* gbeVersion;
|
|
||||||
ME_VERSION* meVersion;
|
|
||||||
INT32 meVersionOffset;
|
|
||||||
info = tr("Size: %1")
|
|
||||||
.arg(body.size(), 8, 16, QChar('0'));
|
|
||||||
switch (regionSubtype)
|
|
||||||
{
|
|
||||||
case TreeItem::GbeRegion:
|
|
||||||
name = tr("GbE region");
|
|
||||||
gbeMac = (GBE_MAC*) body.constData();
|
|
||||||
gbeVersion = (GBE_VERSION*) (body.constData() + GBE_VERSION_OFFSET);
|
|
||||||
info += tr("\nMAC: %1:%2:%3:%4:%5:%6\nVersion: %7.%8")
|
|
||||||
.arg(gbeMac->vendor[0], 2, 16, QChar('0'))
|
|
||||||
.arg(gbeMac->vendor[1], 2, 16, QChar('0'))
|
|
||||||
.arg(gbeMac->vendor[2], 2, 16, QChar('0'))
|
|
||||||
.arg(gbeMac->device[0], 2, 16, QChar('0'))
|
|
||||||
.arg(gbeMac->device[1], 2, 16, QChar('0'))
|
|
||||||
.arg(gbeMac->device[2], 2, 16, QChar('0'))
|
|
||||||
.arg(gbeVersion->major)
|
|
||||||
.arg(gbeVersion->minor);
|
|
||||||
break;
|
|
||||||
case TreeItem::MeRegion:
|
|
||||||
name = tr("ME region");
|
|
||||||
meVersionOffset = body.indexOf(ME_VERSION_SIGNATURE);
|
|
||||||
if (meVersionOffset < 0){
|
|
||||||
info += tr("\nVersion: unknown");
|
|
||||||
msg(tr("parseRegion: ME region version is unknown, it can be damaged"), parent);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
meVersion = (ME_VERSION*) (body.constData() + meVersionOffset);
|
|
||||||
info += tr("\nVersion: %1.%2.%3.%4")
|
|
||||||
.arg(meVersion->major)
|
|
||||||
.arg(meVersion->minor)
|
|
||||||
.arg(meVersion->bugfix)
|
|
||||||
.arg(meVersion->build);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TreeItem::BiosRegion:
|
|
||||||
name = tr("BIOS region");
|
|
||||||
break;
|
|
||||||
case TreeItem::PdrRegion:
|
|
||||||
name = tr("PDR region");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
name = tr("Unknown region");
|
|
||||||
msg(tr("parseRegion: Unknown region"), parent);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add tree item
|
|
||||||
regionIndex = treeModel->addItem(TreeItem::Region, regionSubtype, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), body, parent);
|
|
||||||
|
|
||||||
return ERR_SUCCESS;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
UINT8 FfsEngine::parseBios(const QByteArray & bios, const QModelIndex & parent)
|
UINT8 FfsEngine::parseBios(const QByteArray & bios, const QModelIndex & parent)
|
||||||
{
|
{
|
||||||
// Search for first volume
|
// Search for first volume
|
||||||
@ -625,7 +455,7 @@ UINT8 FfsEngine::parseBios(const QByteArray & bios, const QModelIndex & parent)
|
|||||||
info = tr("Size: %1")
|
info = tr("Size: %1")
|
||||||
.arg(padding.size(), 8, 16, QChar('0'));
|
.arg(padding.size(), 8, 16, QChar('0'));
|
||||||
// Add tree item
|
// Add tree item
|
||||||
treeModel->addItem(TreeItem::Padding, 0, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), padding, parent);
|
treeModel->addItem(TreeItem::Padding, 0, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), padding, QByteArray(), parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search for and parse all volumes
|
// Search for and parse all volumes
|
||||||
@ -644,7 +474,7 @@ UINT8 FfsEngine::parseBios(const QByteArray & bios, const QModelIndex & parent)
|
|||||||
info = tr("Size: %1")
|
info = tr("Size: %1")
|
||||||
.arg(padding.size(), 8, 16, QChar('0'));
|
.arg(padding.size(), 8, 16, QChar('0'));
|
||||||
// Add tree item
|
// Add tree item
|
||||||
treeModel->addItem(TreeItem::Padding, 0, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), padding, parent);
|
treeModel->addItem(TreeItem::Padding, 0, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), padding, QByteArray(), parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get volume size
|
// Get volume size
|
||||||
@ -762,7 +592,7 @@ UINT8 FfsEngine::parseBios(const QByteArray & bios, const QModelIndex & parent)
|
|||||||
info = tr("Size: %2")
|
info = tr("Size: %2")
|
||||||
.arg(padding.size(), 8, 16, QChar('0'));
|
.arg(padding.size(), 8, 16, QChar('0'));
|
||||||
// Add tree item
|
// Add tree item
|
||||||
treeModel->addItem(TreeItem::Padding, 0, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), padding, parent);
|
treeModel->addItem(TreeItem::Padding, 0, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), padding, QByteArray(), parent);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -873,7 +703,7 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, const QModelIndex & par
|
|||||||
// Add tree item
|
// Add tree item
|
||||||
QByteArray header = volume.left(headerSize);
|
QByteArray header = volume.left(headerSize);
|
||||||
QByteArray body = volume.mid(headerSize, volumeSize - headerSize);
|
QByteArray body = volume.mid(headerSize, volumeSize - headerSize);
|
||||||
QModelIndex index = treeModel->addItem(TreeItem::Volume, 0, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, parent, mode);
|
QModelIndex index = treeModel->addItem(TreeItem::Volume, 0, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
|
||||||
|
|
||||||
// Do not parse volumes with unknown FS
|
// Do not parse volumes with unknown FS
|
||||||
if (!parseCurrentVolume)
|
if (!parseCurrentVolume)
|
||||||
@ -986,13 +816,13 @@ UINT8 FfsEngine::parseFile(const QByteArray & file, UINT8 revision, const char e
|
|||||||
|
|
||||||
// Get file body
|
// Get file body
|
||||||
QByteArray body = file.right(file.size() - sizeof(EFI_FFS_FILE_HEADER));
|
QByteArray body = file.right(file.size() - sizeof(EFI_FFS_FILE_HEADER));
|
||||||
UINT32 fileSize = (UINT32) file.size();
|
|
||||||
// For files in Revision 1 volumes, check for file tail presence
|
// For files in Revision 1 volumes, check for file tail presence
|
||||||
|
QByteArray tail;
|
||||||
if (revision == 1 && fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT)
|
if (revision == 1 && fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT)
|
||||||
{
|
{
|
||||||
//Check file tail;
|
//Check file tail;
|
||||||
UINT16* tail = (UINT16*) body.right(sizeof(UINT16)).constData();
|
tail = body.right(sizeof(UINT16));
|
||||||
if (!fileHeader->IntegrityCheck.TailReference == *tail)
|
if (!fileHeader->IntegrityCheck.TailReference == *(UINT16*)tail.constData())
|
||||||
msg(tr("parseVolume: %1, file tail value %2 is not a bitwise not of %3 stored in file header")
|
msg(tr("parseVolume: %1, file tail value %2 is not a bitwise not of %3 stored in file header")
|
||||||
.arg(guidToQString(fileHeader->Name))
|
.arg(guidToQString(fileHeader->Name))
|
||||||
.arg(*tail, 4, 16, QChar('0'))
|
.arg(*tail, 4, 16, QChar('0'))
|
||||||
@ -1000,7 +830,6 @@ UINT8 FfsEngine::parseFile(const QByteArray & file, UINT8 revision, const char e
|
|||||||
|
|
||||||
// Remove tail from file body
|
// Remove tail from file body
|
||||||
body = body.left(body.size() - sizeof(UINT16));
|
body = body.left(body.size() - sizeof(UINT16));
|
||||||
fileSize -= sizeof(UINT16);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse current file by default
|
// Parse current file by default
|
||||||
@ -1069,7 +898,7 @@ UINT8 FfsEngine::parseFile(const QByteArray & file, UINT8 revision, const char e
|
|||||||
.arg(fileHeader->State, 2, 16, QChar('0'));
|
.arg(fileHeader->State, 2, 16, QChar('0'));
|
||||||
|
|
||||||
// Add tree item
|
// Add tree item
|
||||||
QModelIndex index = treeModel->addItem(TreeItem::File, fileHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, parent, mode);
|
QModelIndex index = treeModel->addItem(TreeItem::File, fileHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, tail, parent, mode);
|
||||||
|
|
||||||
if (!parseCurrentFile)
|
if (!parseCurrentFile)
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
@ -1167,7 +996,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, const UINT8 revision,
|
|||||||
.arg(compressedSectionHeader->UncompressedLength, 8, 16, QChar('0'));
|
.arg(compressedSectionHeader->UncompressedLength, 8, 16, QChar('0'));
|
||||||
|
|
||||||
// Add tree item
|
// Add tree item
|
||||||
index = treeModel->addItem(TreeItem::Section, sectionHeader->Type, algorithm, name, "", info, header, body, parent, mode);
|
index = treeModel->addItem(TreeItem::Section, sectionHeader->Type, algorithm, name, "", info, header, body, QByteArray(), parent, mode);
|
||||||
|
|
||||||
// Parse decompressed data
|
// Parse decompressed data
|
||||||
if (parseCurrentSection) {
|
if (parseCurrentSection) {
|
||||||
@ -1214,7 +1043,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, const UINT8 revision,
|
|||||||
.arg(compressionTypeToQString(algorithm));
|
.arg(compressionTypeToQString(algorithm));
|
||||||
|
|
||||||
// Add tree item
|
// Add tree item
|
||||||
index = treeModel->addItem(TreeItem::Section, sectionHeader->Type, algorithm, name, "", info, header, body, parent, mode);
|
index = treeModel->addItem(TreeItem::Section, sectionHeader->Type, algorithm, name, "", info, header, body, QByteArray(), parent, mode);
|
||||||
|
|
||||||
// Parse decompressed data
|
// Parse decompressed data
|
||||||
if (parseCurrentSection) {
|
if (parseCurrentSection) {
|
||||||
@ -1235,7 +1064,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, const UINT8 revision,
|
|||||||
.arg(body.size(), 8, 16, QChar('0'));
|
.arg(body.size(), 8, 16, QChar('0'));
|
||||||
|
|
||||||
// Add tree item
|
// Add tree item
|
||||||
index = treeModel->addItem(TreeItem::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, parent, mode);
|
index = treeModel->addItem(TreeItem::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
|
||||||
|
|
||||||
// Parse section body
|
// Parse section body
|
||||||
result = parseSections(body, revision, empty, index);
|
result = parseSections(body, revision, empty, index);
|
||||||
@ -1264,9 +1093,10 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, const UINT8 revision,
|
|||||||
.arg(body.size(), 8, 16, QChar('0'));
|
.arg(body.size(), 8, 16, QChar('0'));
|
||||||
|
|
||||||
// Add tree item
|
// Add tree item
|
||||||
index = treeModel->addItem(TreeItem::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, parent, mode);
|
index = treeModel->addItem(TreeItem::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
|
||||||
break;
|
break;
|
||||||
case EFI_SECTION_USER_INTERFACE:
|
case EFI_SECTION_USER_INTERFACE:
|
||||||
|
{
|
||||||
header = section.left(sizeof(EFI_USER_INTERFACE_SECTION));
|
header = section.left(sizeof(EFI_USER_INTERFACE_SECTION));
|
||||||
body = section.mid(sizeof(EFI_USER_INTERFACE_SECTION), sectionSize - sizeof(EFI_USER_INTERFACE_SECTION));
|
body = section.mid(sizeof(EFI_USER_INTERFACE_SECTION), sectionSize - sizeof(EFI_USER_INTERFACE_SECTION));
|
||||||
|
|
||||||
@ -1276,12 +1106,11 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, const UINT8 revision,
|
|||||||
.arg(body.size(), 8, 16, QChar('0'));
|
.arg(body.size(), 8, 16, QChar('0'));
|
||||||
|
|
||||||
// Add tree item
|
// Add tree item
|
||||||
index = treeModel->addItem(TreeItem::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, parent, mode);
|
index = treeModel->addItem(TreeItem::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
|
||||||
|
|
||||||
// Rename parent file
|
// Rename parent file
|
||||||
{
|
|
||||||
QString text = QString::fromUtf16((const ushort*)body.constData());
|
QString text = QString::fromUtf16((const ushort*)body.constData());
|
||||||
setTreeItemText(text, findParentOfType(TreeItem::File, parent));
|
treeModel->setItemText(text, findParentOfType(TreeItem::File, parent));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EFI_SECTION_FIRMWARE_VOLUME_IMAGE:
|
case EFI_SECTION_FIRMWARE_VOLUME_IMAGE:
|
||||||
@ -1294,7 +1123,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, const UINT8 revision,
|
|||||||
.arg(body.size(), 8, 16, QChar('0'));
|
.arg(body.size(), 8, 16, QChar('0'));
|
||||||
|
|
||||||
// Add tree item
|
// Add tree item
|
||||||
index = treeModel->addItem(TreeItem::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, parent, mode);
|
index = treeModel->addItem(TreeItem::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
|
||||||
|
|
||||||
// Parse section body as BIOS space
|
// Parse section body as BIOS space
|
||||||
result = parseBios(body, index);
|
result = parseBios(body, index);
|
||||||
@ -1313,7 +1142,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, const UINT8 revision,
|
|||||||
.arg(body.size(), 8, 16, QChar('0'));
|
.arg(body.size(), 8, 16, QChar('0'));
|
||||||
|
|
||||||
// Add tree item
|
// Add tree item
|
||||||
index = treeModel->addItem(TreeItem::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, parent, mode);
|
index = treeModel->addItem(TreeItem::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
|
||||||
|
|
||||||
// Parse section body as BIOS space
|
// Parse section body as BIOS space
|
||||||
result = parseBios(body, index);
|
result = parseBios(body, index);
|
||||||
@ -1331,13 +1160,42 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, const UINT8 revision,
|
|||||||
.arg(body.size(), 8, 16, QChar('0'));
|
.arg(body.size(), 8, 16, QChar('0'));
|
||||||
|
|
||||||
// Add tree item
|
// Add tree item
|
||||||
index = treeModel->addItem(TreeItem::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, parent, mode);
|
index = treeModel->addItem(TreeItem::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
|
||||||
msg(tr("parseFile: Section with unknown type (%1)").arg(sectionHeader->Type, 2, 16, QChar('0')), index);
|
msg(tr("parseFile: Section with unknown type (%1)").arg(sectionHeader->Type, 2, 16, QChar('0')), index);
|
||||||
}
|
}
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Operations on tree items
|
// Operations on tree items
|
||||||
|
UINT8 FfsEngine::extract(const QModelIndex & index, QByteArray & extracted, const UINT8 mode)
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return ERR_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
|
||||||
|
|
||||||
|
if (mode == EXTRACT_MODE_AS_IS) {
|
||||||
|
// Extract as is, with header, body and tail
|
||||||
|
extracted.clear();
|
||||||
|
extracted.append(item->header());
|
||||||
|
extracted.append(item->body());
|
||||||
|
extracted.append(item->tail());
|
||||||
|
}
|
||||||
|
else if (mode == EXTRACT_MODE_BODY_ONLY) {
|
||||||
|
// Extract without header and tail
|
||||||
|
extracted.clear();
|
||||||
|
extracted.append(item->body());
|
||||||
|
}
|
||||||
|
else if (mode == EXTRACT_MODE_UNCOMPRESSED) {
|
||||||
|
// Only possible for files with compressed sections
|
||||||
|
return ERR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return ERR_UNKNOWN_EXTRACT_MODE;
|
||||||
|
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
UINT8 FfsEngine::insert(const QModelIndex & index, const QByteArray & object, const UINT8 type, const UINT8 mode)
|
UINT8 FfsEngine::insert(const QModelIndex & index, const QByteArray & object, const UINT8 type, const UINT8 mode)
|
||||||
{
|
{
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
@ -1464,6 +1322,7 @@ UINT8 FfsEngine::decompress(const QByteArray & compressedData, const UINT8 compr
|
|||||||
scratch = new UINT8[scratchSize];
|
scratch = new UINT8[scratchSize];
|
||||||
|
|
||||||
// Decompress section data
|
// Decompress section data
|
||||||
|
//!TODO: better check needed
|
||||||
// Try EFI1.1 decompression first
|
// Try EFI1.1 decompression first
|
||||||
if (ERR_SUCCESS != EfiDecompress(data, dataSize, decompressed, decompressedSize, scratch, scratchSize)) {
|
if (ERR_SUCCESS != EfiDecompress(data, dataSize, decompressed, decompressedSize, scratch, scratchSize)) {
|
||||||
// Not EFI 1.1, try Tiano
|
// Not EFI 1.1, try Tiano
|
||||||
@ -1498,7 +1357,6 @@ UINT8 FfsEngine::decompress(const QByteArray & compressedData, const UINT8 compr
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Data are same - it's EFI 1.1
|
// Data are same - it's EFI 1.1
|
||||||
msg(tr("EFI1.1"));
|
|
||||||
if (algorithm)
|
if (algorithm)
|
||||||
*algorithm = COMPRESSION_ALGORITHM_EFI11;
|
*algorithm = COMPRESSION_ALGORITHM_EFI11;
|
||||||
}
|
}
|
||||||
@ -1645,15 +1503,12 @@ UINT8 FfsEngine::compress(const QByteArray & data, const UINT8 algorithm, QByteA
|
|||||||
UINT8 FfsEngine::reconstructImage(QByteArray & reconstructed)
|
UINT8 FfsEngine::reconstructImage(QByteArray & reconstructed)
|
||||||
{
|
{
|
||||||
QQueue<QByteArray> queue;
|
QQueue<QByteArray> queue;
|
||||||
reconstructed = QByteArray();
|
UINT8 result = reconstruct(treeModel->index(0,0), queue);
|
||||||
rootItem->setAction(TreeItem::Reconstruct);
|
|
||||||
UINT8 result = reconstruct(rootItem, queue);
|
|
||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
|
reconstructed.clear();
|
||||||
while (!queue.isEmpty())
|
while (!queue.isEmpty())
|
||||||
reconstructed.append(queue.dequeue());
|
reconstructed.append(queue.dequeue());
|
||||||
rootItem->setAction(TreeItem::NoAction);
|
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1681,26 +1536,18 @@ UINT8 FfsEngine::constructPadFile(const UINT32 size, const UINT8 revision, const
|
|||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT8 FfsEngine::reconstruct(TreeItem* item, QQueue<QByteArray> & queue, const UINT8 revision, char empty)
|
UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & queue, const UINT8 revision, char empty)
|
||||||
{
|
{
|
||||||
if (!item)
|
if (!index.isValid())
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
|
|
||||||
QByteArray reconstructed;
|
QByteArray reconstructed;
|
||||||
UINT8 result;
|
UINT8 result;
|
||||||
|
TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
|
||||||
|
|
||||||
// No action is needed, just return header + body
|
// No action is needed, just return header + body
|
||||||
if (item->action() == TreeItem::NoAction) {
|
if (item->action() == TreeItem::NoAction) {
|
||||||
reconstructed = item->header().append(item->body());
|
reconstructed = item->header().append(item->body()).append(item->tail());
|
||||||
// One special case: file with tail
|
|
||||||
if (revision == 1 && item->type() == TreeItem::File) {
|
|
||||||
EFI_FFS_FILE_HEADER* fileHeader = (EFI_FFS_FILE_HEADER*) item->header().constData();
|
|
||||||
if (fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
|
|
||||||
// Append file tail
|
|
||||||
reconstructed.append(!fileHeader->IntegrityCheck.TailReference);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
queue.enqueue(reconstructed);
|
queue.enqueue(reconstructed);
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -1713,7 +1560,7 @@ UINT8 FfsEngine::reconstruct(TreeItem* item, QQueue<QByteArray> & queue, const U
|
|||||||
if (item->type() == TreeItem::Volume) {
|
if (item->type() == TreeItem::Volume) {
|
||||||
EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*) item->header().constData();
|
EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*) item->header().constData();
|
||||||
empty = volumeHeader->Attributes & EFI_FVB_ERASE_POLARITY ? '\xFF' : '\x00';
|
empty = volumeHeader->Attributes & EFI_FVB_ERASE_POLARITY ? '\xFF' : '\x00';
|
||||||
reconstructed.fill(empty, item->header().size() + item->body().size());
|
reconstructed.fill(empty, item->header().size() + item->body().size() + item->tail().size());
|
||||||
queue.enqueue(reconstructed);
|
queue.enqueue(reconstructed);
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -1734,11 +1581,11 @@ UINT8 FfsEngine::reconstruct(TreeItem* item, QQueue<QByteArray> & queue, const U
|
|||||||
QQueue<QByteArray> childrenQueue;
|
QQueue<QByteArray> childrenQueue;
|
||||||
|
|
||||||
switch (item->type()) {
|
switch (item->type()) {
|
||||||
case TreeItem::IntelImage:
|
case TreeItem::Image:
|
||||||
{
|
if (item->subtype() == TreeItem::IntelImage) {
|
||||||
// Reconstruct Intel image
|
// Reconstruct Intel image
|
||||||
// First child will always be descriptor for this type of image
|
// First child will always be descriptor for this type of image
|
||||||
result = reconstruct(item->child(0), childrenQueue);
|
result = reconstruct(index.child(0, index.column()), childrenQueue);
|
||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
QByteArray descriptor = childrenQueue.dequeue();
|
QByteArray descriptor = childrenQueue.dequeue();
|
||||||
@ -1762,7 +1609,7 @@ UINT8 FfsEngine::reconstruct(TreeItem* item, QQueue<QByteArray> & queue, const U
|
|||||||
UINT32 offset = descriptor.size();
|
UINT32 offset = descriptor.size();
|
||||||
// Reconstruct other regions
|
// Reconstruct other regions
|
||||||
for (int i = 1; i < item->childCount(); i++) {
|
for (int i = 1; i < item->childCount(); i++) {
|
||||||
result = reconstruct(item->child(i), childrenQueue);
|
result = reconstruct(index.child(i, index.column()), childrenQueue);
|
||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
switch(item->child(i)->subtype())
|
switch(item->child(i)->subtype())
|
||||||
@ -1796,7 +1643,7 @@ UINT8 FfsEngine::reconstruct(TreeItem* item, QQueue<QByteArray> & queue, const U
|
|||||||
offset = pdrEnd;
|
offset = pdrEnd;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
msg(tr("reconstruct: unknown region type found while reconstructing Intel image"));
|
msg(tr("reconstruct: unknown region type found while reconstructing Intel image"), index);
|
||||||
return ERR_INVALID_REGION;
|
return ERR_INVALID_REGION;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1804,41 +1651,33 @@ UINT8 FfsEngine::reconstruct(TreeItem* item, QQueue<QByteArray> & queue, const U
|
|||||||
reconstructed.append(QByteArray((UINT32)item->body().size() - offset, empty));
|
reconstructed.append(QByteArray((UINT32)item->body().size() - offset, empty));
|
||||||
|
|
||||||
if (reconstructed.size() > item->body().size()) {
|
if (reconstructed.size() > item->body().size()) {
|
||||||
msg(tr("reconstructed: reconstructed body %1 is bigger then original %2 (Type: %3)")
|
msg(tr("reconstruct: reconstructed body %1 is bigger then original %2")
|
||||||
.arg(reconstructed.size(), 8, 16, QChar('0'))
|
.arg(reconstructed.size(), 8, 16, QChar('0'))
|
||||||
.arg(item->body().size(), 8, 16, QChar('0'))
|
.arg(item->body().size(), 8, 16, QChar('0')), index);
|
||||||
.arg(itemTypeToQString(item->type())));
|
|
||||||
return ERR_INVALID_PARAMETER;
|
return ERR_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
else if (reconstructed.size() < item->body().size()) {
|
else if (reconstructed.size() < item->body().size()) {
|
||||||
msg(tr("reconstructed: reconstructed body %1 is smaller then original %2 (Type: %3)")
|
msg(tr("reconstruct: reconstructed body %1 is smaller then original %2")
|
||||||
.arg(reconstructed.size(), 8, 16, QChar('0'))
|
.arg(reconstructed.size(), 8, 16, QChar('0'))
|
||||||
.arg(item->body().size(), 8, 16, QChar('0'))
|
.arg(item->body().size(), 8, 16, QChar('0')), index);
|
||||||
.arg(itemTypeToQString(item->type())));
|
|
||||||
return ERR_INVALID_PARAMETER;
|
return ERR_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enqueue reconstructed item
|
// Enqueue reconstructed item
|
||||||
queue.enqueue(item->header().append(reconstructed));
|
queue.enqueue(item->header().append(reconstructed));
|
||||||
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
break;
|
// BIOS Image must be treated like region
|
||||||
|
|
||||||
case TreeItem::Padding:
|
|
||||||
// Padding can't be changed
|
|
||||||
queue.enqueue(item->body());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TreeItem::Capsule:
|
case TreeItem::Capsule:
|
||||||
if (item->subtype() == TreeItem::AptioCapsule)
|
if (item->subtype() == TreeItem::AptioCapsule)
|
||||||
msg(tr("reconstruct: Aptio extended header checksum and signature are now invalid"));
|
msg(tr("reconstruct: Aptio capsule checksum and signature can now become invalid"), index);
|
||||||
case TreeItem::Root:
|
|
||||||
case TreeItem::Image:
|
|
||||||
case TreeItem::Region:
|
case TreeItem::Region:
|
||||||
|
{
|
||||||
// Reconstruct item body
|
// Reconstruct item body
|
||||||
if (item->childCount()) {
|
if (item->childCount()) {
|
||||||
// Reconstruct item children
|
// Reconstruct item children
|
||||||
for (int i = 0; i < item->childCount(); i++) {
|
for (int i = 0; i < item->childCount(); i++) {
|
||||||
result = reconstruct(item->child(i), childrenQueue);
|
result = reconstruct(index.child(i, index.column()), childrenQueue);
|
||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -1854,23 +1693,22 @@ UINT8 FfsEngine::reconstruct(TreeItem* item, QQueue<QByteArray> & queue, const U
|
|||||||
// Check size of reconstructed image, it must be the same
|
// Check size of reconstructed image, it must be the same
|
||||||
if (item->type() != TreeItem::Root) {
|
if (item->type() != TreeItem::Root) {
|
||||||
if (reconstructed.size() > item->body().size()) {
|
if (reconstructed.size() > item->body().size()) {
|
||||||
msg(tr("reconstructed: reconstructed body %1 is bigger then original %2 (Type: %3)")
|
msg(tr("reconstructed: reconstructed body %1 is bigger then original %2")
|
||||||
.arg(reconstructed.size(), 8, 16, QChar('0'))
|
.arg(reconstructed.size(), 8, 16, QChar('0'))
|
||||||
.arg(item->body().size(), 8, 16, QChar('0'))
|
.arg(item->body().size(), 8, 16, QChar('0')), index);
|
||||||
.arg(itemTypeToQString(item->type())));
|
|
||||||
return ERR_INVALID_PARAMETER;
|
return ERR_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
else if (reconstructed.size() < item->body().size()) {
|
else if (reconstructed.size() < item->body().size()) {
|
||||||
msg(tr("reconstructed: reconstructed body %1 is smaller then original %2 (Type: %3)")
|
msg(tr("reconstructed: reconstructed body %1 is smaller then original %2")
|
||||||
.arg(reconstructed.size(), 8, 16, QChar('0'))
|
.arg(reconstructed.size(), 8, 16, QChar('0'))
|
||||||
.arg(item->body().size(), 8, 16, QChar('0'))
|
.arg(item->body().size(), 8, 16, QChar('0')), index);
|
||||||
.arg(itemTypeToQString(item->type())));
|
|
||||||
return ERR_INVALID_PARAMETER;
|
return ERR_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enqueue reconstructed item
|
// Enqueue reconstructed item
|
||||||
queue.enqueue(item->header().append(reconstructed));
|
queue.enqueue(item->header().append(reconstructed));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TreeItem::Volume:
|
case TreeItem::Volume:
|
||||||
@ -1884,7 +1722,7 @@ UINT8 FfsEngine::reconstruct(TreeItem* item, QQueue<QByteArray> & queue, const U
|
|||||||
// Reconstruct files in volume
|
// Reconstruct files in volume
|
||||||
for (int i = 0; i < item->childCount(); i++) {
|
for (int i = 0; i < item->childCount(); i++) {
|
||||||
// Reconstruct files
|
// Reconstruct files
|
||||||
result = reconstruct(item->child(i), childrenQueue, volumeHeader->Revision, empty);
|
result = reconstruct(index.child(i, index.column()), childrenQueue, volumeHeader->Revision, empty);
|
||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -1952,7 +1790,7 @@ UINT8 FfsEngine::reconstruct(TreeItem* item, QQueue<QByteArray> & queue, const U
|
|||||||
UINT32 vtfOffset = volumeSize - header.size() - file.size();
|
UINT32 vtfOffset = volumeSize - header.size() - file.size();
|
||||||
if (vtfOffset % 8) {
|
if (vtfOffset % 8) {
|
||||||
msg(tr("reconstruct: %1: Wrong size of Volume Top File")
|
msg(tr("reconstruct: %1: Wrong size of Volume Top File")
|
||||||
.arg(guidToQString(volumeHeader->FileSystemGuid)));
|
.arg(guidToQString(volumeHeader->FileSystemGuid)), index);
|
||||||
return ERR_INVALID_FILE;
|
return ERR_INVALID_FILE;
|
||||||
}
|
}
|
||||||
// Insert pad file to fill the gap
|
// Insert pad file to fill the gap
|
||||||
@ -1973,7 +1811,7 @@ UINT8 FfsEngine::reconstruct(TreeItem* item, QQueue<QByteArray> & queue, const U
|
|||||||
// Check if volume can be grown
|
// Check if volume can be grown
|
||||||
UINT8 parentType = item->parent()->type();
|
UINT8 parentType = item->parent()->type();
|
||||||
if(parentType != TreeItem::File && parentType != TreeItem::Section) {
|
if(parentType != TreeItem::File && parentType != TreeItem::Section) {
|
||||||
msg(tr("%1: can't grow root volume").arg(guidToQString(volumeHeader->FileSystemGuid)));
|
msg(tr("%1: can't grow root volume").arg(guidToQString(volumeHeader->FileSystemGuid)), index);
|
||||||
return ERR_INVALID_VOLUME;
|
return ERR_INVALID_VOLUME;
|
||||||
}
|
}
|
||||||
// Grow volume to fit VTF
|
// Grow volume to fit VTF
|
||||||
@ -1985,7 +1823,7 @@ UINT8 FfsEngine::reconstruct(TreeItem* item, QQueue<QByteArray> & queue, const U
|
|||||||
vtfOffset = newSize - header.size() - file.size();
|
vtfOffset = newSize - header.size() - file.size();
|
||||||
if (vtfOffset % 8) {
|
if (vtfOffset % 8) {
|
||||||
msg(tr("reconstruct: %1: Wrong size of Volume Top File")
|
msg(tr("reconstruct: %1: Wrong size of Volume Top File")
|
||||||
.arg(guidToQString(volumeHeader->FileSystemGuid)));
|
.arg(guidToQString(volumeHeader->FileSystemGuid)), index);
|
||||||
return ERR_INVALID_FILE;
|
return ERR_INVALID_FILE;
|
||||||
}
|
}
|
||||||
// Construct pad file
|
// Construct pad file
|
||||||
@ -2012,7 +1850,7 @@ UINT8 FfsEngine::reconstruct(TreeItem* item, QQueue<QByteArray> & queue, const U
|
|||||||
// Check if volume can be grown
|
// Check if volume can be grown
|
||||||
UINT8 parentType = item->parent()->type();
|
UINT8 parentType = item->parent()->type();
|
||||||
if(parentType != TreeItem::File && parentType != TreeItem::Section) {
|
if(parentType != TreeItem::File && parentType != TreeItem::Section) {
|
||||||
msg(tr("%1: can't grow root volume").arg(guidToQString(volumeHeader->FileSystemGuid)));
|
msg(tr("%1: can't grow root volume").arg(guidToQString(volumeHeader->FileSystemGuid)), index);
|
||||||
return ERR_INVALID_VOLUME;
|
return ERR_INVALID_VOLUME;
|
||||||
}
|
}
|
||||||
// Grow volume to fit new body
|
// Grow volume to fit new body
|
||||||
@ -2057,7 +1895,7 @@ UINT8 FfsEngine::reconstruct(TreeItem* item, QQueue<QByteArray> & queue, const U
|
|||||||
if (item->childCount()) {
|
if (item->childCount()) {
|
||||||
for (int i = 0; i < item->childCount(); i++) {
|
for (int i = 0; i < item->childCount(); i++) {
|
||||||
// Reconstruct sections
|
// Reconstruct sections
|
||||||
result = reconstruct(item->child(i), childrenQueue, revision, empty);
|
result = reconstruct(index.child(i, index.column()), childrenQueue, revision, empty);
|
||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -2084,9 +1922,7 @@ UINT8 FfsEngine::reconstruct(TreeItem* item, QQueue<QByteArray> & queue, const U
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Correct file size
|
// Correct file size
|
||||||
UINT8 tailSize = 0;
|
UINT8 tailSize = item->hasEmptyTail() ? 0 : sizeof(UINT16);
|
||||||
if(revision == 1 && (fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT))
|
|
||||||
tailSize = sizeof(UINT16);
|
|
||||||
|
|
||||||
uint32ToUint24(sizeof(EFI_FFS_FILE_HEADER) + reconstructed.size() + tailSize, fileHeader->Size);
|
uint32ToUint24(sizeof(EFI_FFS_FILE_HEADER) + reconstructed.size() + tailSize, fileHeader->Size);
|
||||||
|
|
||||||
@ -2108,9 +1944,9 @@ UINT8 FfsEngine::reconstruct(TreeItem* item, QQueue<QByteArray> & queue, const U
|
|||||||
if (tailSize)
|
if (tailSize)
|
||||||
reconstructed.append(!fileHeader->IntegrityCheck.TailReference);
|
reconstructed.append(!fileHeader->IntegrityCheck.TailReference);
|
||||||
}
|
}
|
||||||
// Use current file body
|
// Use current file body and tail
|
||||||
else
|
else
|
||||||
reconstructed = item->body();
|
reconstructed = item->body().append(item->tail());
|
||||||
|
|
||||||
// Enqueue reconstructed item
|
// Enqueue reconstructed item
|
||||||
queue.enqueue(header.append(reconstructed));
|
queue.enqueue(header.append(reconstructed));
|
||||||
@ -2127,7 +1963,7 @@ UINT8 FfsEngine::reconstruct(TreeItem* item, QQueue<QByteArray> & queue, const U
|
|||||||
// Reconstruct section body
|
// Reconstruct section body
|
||||||
for (int i = 0; i < item->childCount(); i++) {
|
for (int i = 0; i < item->childCount(); i++) {
|
||||||
// Reconstruct subsections
|
// Reconstruct subsections
|
||||||
result = reconstruct(item->child(i), childrenQueue, revision, empty);
|
result = reconstruct(index.child(i, index.column()), childrenQueue, revision, empty);
|
||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -2181,9 +2017,8 @@ UINT8 FfsEngine::reconstruct(TreeItem* item, QQueue<QByteArray> & queue, const U
|
|||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
// Check for auth status valid attribute
|
// Check for auth status valid attribute
|
||||||
if (guidDefinedHeader->Attributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID)
|
if (guidDefinedHeader->Attributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) {
|
||||||
{
|
msg(tr("reconstruct: %1: GUID defined section signature can become invalid invalid")
|
||||||
msg(tr("reconstruct: %1: GUID defined section signature can now become invalid")
|
|
||||||
.arg(guidToQString(guidDefinedHeader->SectionDefinitionGuid)));
|
.arg(guidToQString(guidDefinedHeader->SectionDefinitionGuid)));
|
||||||
}
|
}
|
||||||
// Replace new section body
|
// Replace new section body
|
||||||
@ -2215,7 +2050,6 @@ UINT8 FfsEngine::reconstruct(TreeItem* item, QQueue<QByteArray> & queue, const U
|
|||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
//!TODO: implement other actions
|
|
||||||
return ERR_NOT_IMPLEMENTED;
|
return ERR_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2224,7 +2058,12 @@ UINT8 FfsEngine::growVolume(QByteArray & header, const UINT32 size, UINT32 & new
|
|||||||
// Adjust new size to be representable by current FvBlockMap
|
// Adjust new size to be representable by current FvBlockMap
|
||||||
EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*) header.data();
|
EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*) header.data();
|
||||||
EFI_FV_BLOCK_MAP_ENTRY* blockMap = (EFI_FV_BLOCK_MAP_ENTRY*) (header.data() + sizeof(EFI_FIRMWARE_VOLUME_HEADER));
|
EFI_FV_BLOCK_MAP_ENTRY* blockMap = (EFI_FV_BLOCK_MAP_ENTRY*) (header.data() + sizeof(EFI_FIRMWARE_VOLUME_HEADER));
|
||||||
UINT32 blockMapSize = header.size() - sizeof(EFI_FIRMWARE_VOLUME_HEADER);
|
|
||||||
|
// Get block map size
|
||||||
|
UINT32 extHeaderOffset = volumeHeader->Revision == 2 ? volumeHeader->ExtHeaderOffset : 0;
|
||||||
|
UINT32 blockMapSize = header.size() - extHeaderOffset - sizeof(EFI_FIRMWARE_VOLUME_HEADER);
|
||||||
|
if (blockMapSize % sizeof(EFI_FV_BLOCK_MAP_ENTRY))
|
||||||
|
return ERR_INVALID_VOLUME;
|
||||||
UINT32 blockMapCount = blockMapSize / sizeof(EFI_FV_BLOCK_MAP_ENTRY);
|
UINT32 blockMapCount = blockMapSize / sizeof(EFI_FV_BLOCK_MAP_ENTRY);
|
||||||
|
|
||||||
// Check blockMap validity
|
// Check blockMap validity
|
||||||
@ -2252,7 +2091,7 @@ UINT8 FfsEngine::growVolume(QByteArray & header, const UINT32 size, UINT32 & new
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Will be refactored later
|
// Will be refactored later
|
||||||
QByteArray FfsEngine::decompressFile(const QModelIndex& index) const
|
/*QByteArray FfsEngine::decompressFile(const QModelIndex& index) const
|
||||||
{
|
{
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
return QByteArray();
|
return QByteArray();
|
||||||
@ -2315,9 +2154,9 @@ QByteArray FfsEngine::decompressFile(const QModelIndex& index) const
|
|||||||
file.append(!fileHeader->IntegrityCheck.TailReference);
|
file.append(!fileHeader->IntegrityCheck.TailReference);
|
||||||
|
|
||||||
return header.append(file);
|
return header.append(file);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
bool FfsEngine::isCompressedFile(const QModelIndex& index) const
|
/*bool FfsEngine::isCompressedFile(const QModelIndex& index) const
|
||||||
{
|
{
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
return false;
|
return false;
|
||||||
@ -2332,4 +2171,4 @@ bool FfsEngine::isCompressedFile(const QModelIndex& index) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}*/
|
39
ffsengine.h
39
ffsengine.h
@ -21,7 +21,7 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
#include "basetypes.h"
|
#include "basetypes.h"
|
||||||
#include "treeitem.h"
|
#include "treeitem.h"
|
||||||
#include "treemodel.h"
|
#include "treemodel.h"
|
||||||
#include "debuglistitem.h"
|
#include "messagelistitem.h"
|
||||||
|
|
||||||
class TreeModel;
|
class TreeModel;
|
||||||
|
|
||||||
@ -37,8 +37,8 @@ public:
|
|||||||
// Returns model for Qt view classes
|
// Returns model for Qt view classes
|
||||||
TreeModel* model() const;
|
TreeModel* model() const;
|
||||||
|
|
||||||
// Returns debug items queue
|
// Returns message items queue
|
||||||
QQueue<DebugListItem*> debugMessage();
|
QQueue<MessageListItem*> message();
|
||||||
|
|
||||||
// Firmware image parsing
|
// Firmware image parsing
|
||||||
UINT8 parseInputFile(const QByteArray & buffer);
|
UINT8 parseInputFile(const QByteArray & buffer);
|
||||||
@ -64,38 +64,25 @@ public:
|
|||||||
// Construction routines
|
// Construction routines
|
||||||
UINT8 reconstructImage(QByteArray & reconstructed);
|
UINT8 reconstructImage(QByteArray & reconstructed);
|
||||||
UINT8 constructPadFile(const UINT32 size, const UINT8 revision, const char empty, QByteArray & pad);
|
UINT8 constructPadFile(const UINT32 size, const UINT8 revision, const char empty, QByteArray & pad);
|
||||||
UINT8 reconstruct(TreeItem* item, QQueue<QByteArray> & queue, const UINT8 revision = 2, char empty = '\xFF');
|
UINT8 reconstruct(const QModelIndex & index, QQueue<QByteArray> & queue, const UINT8 revision = 2, char empty = '\xFF');
|
||||||
UINT8 growVolume(QByteArray & header, const UINT32 size, UINT32 & newSize);
|
UINT8 growVolume(QByteArray & header, const UINT32 size, UINT32 & newSize);
|
||||||
|
|
||||||
// Operations on tree items
|
// Operations on tree items
|
||||||
UINT8 insert(const QModelIndex & index, const QByteArray & object, const UINT8 type, const UINT8 mode);
|
UINT8 extract(const QModelIndex & index, QByteArray & extracted, const UINT8 mode);
|
||||||
|
UINT8 insert(const QModelIndex & index, const QByteArray & object, const UINT8 objectType, const UINT8 mode);
|
||||||
UINT8 remove(const QModelIndex & index);
|
UINT8 remove(const QModelIndex & index);
|
||||||
|
|
||||||
// Proxies to model operations
|
|
||||||
QByteArray header(const QModelIndex & index) const;
|
|
||||||
bool hasEmptyHeader(const QModelIndex & index) const;
|
|
||||||
QByteArray body(const QModelIndex & index) const;
|
|
||||||
bool hasEmptyBody(const QModelIndex & index) const;
|
|
||||||
|
|
||||||
// Item-related operations
|
|
||||||
bool isOfType(UINT8 type, const QModelIndex & index) const;
|
|
||||||
bool isOfSubtype(UINT8 subtype, const QModelIndex & index) const;
|
|
||||||
QModelIndex findParentOfType(UINT8 type, const QModelIndex& index) const;
|
|
||||||
|
|
||||||
// Will be refactored later
|
|
||||||
bool isCompressedFile(const QModelIndex & index) const;
|
|
||||||
QByteArray decompressFile(const QModelIndex & index) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TreeItem *rootItem;
|
TreeItem *rootItem;
|
||||||
TreeModel *treeModel;
|
TreeModel *treeModel;
|
||||||
// Debug window helper
|
|
||||||
QQueue<DebugListItem*> debugItems;
|
// Message helper
|
||||||
|
QQueue<MessageListItem*> messageItems;
|
||||||
void msg(const QString & message, const QModelIndex index = QModelIndex());
|
void msg(const QString & message, const QModelIndex index = QModelIndex());
|
||||||
// Internal operations used in insertInTree
|
|
||||||
bool setTreeItemName(const QString & data, const QModelIndex & index);
|
// Internal operations
|
||||||
bool setTreeItemText(const QString & data, const QModelIndex & index);
|
QModelIndex findParentOfType(UINT8 type, const QModelIndex & index) const;
|
||||||
UINT8 hasIntersection(const UINT32 begin1, const UINT32 end1, const UINT32 begin2, const UINT32 end2);
|
bool hasIntersection(const UINT32 begin1, const UINT32 end1, const UINT32 begin2, const UINT32 end2);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* debuglistitem.cpp
|
/* messagelistitem.cpp
|
||||||
|
|
||||||
Copyright (c) 2013, Nikolaj Schlej. All rights reserved.
|
Copyright (c) 2013, Nikolaj Schlej. All rights reserved.
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
@ -11,37 +11,37 @@
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "debuglistitem.h"
|
#include "messagelistitem.h"
|
||||||
|
|
||||||
DebugListItem::DebugListItem(QListWidget * parent, int type, const QModelIndex & index)
|
MessageListItem::MessageListItem(QListWidget * parent, int type, const QModelIndex & index)
|
||||||
: QListWidgetItem(parent, type)
|
: QListWidgetItem(parent, type)
|
||||||
{
|
{
|
||||||
itemIndex = index;
|
itemIndex = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
DebugListItem::DebugListItem(const QString & text, QListWidget * parent, int type, const QModelIndex & index)
|
MessageListItem::MessageListItem(const QString & text, QListWidget * parent, int type, const QModelIndex & index)
|
||||||
: QListWidgetItem(text, parent, type)
|
: QListWidgetItem(text, parent, type)
|
||||||
{
|
{
|
||||||
itemIndex = index;
|
itemIndex = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
DebugListItem::DebugListItem(const QIcon & icon, const QString & text, QListWidget * parent, int type, const QModelIndex & index)
|
MessageListItem::MessageListItem(const QIcon & icon, const QString & text, QListWidget * parent, int type, const QModelIndex & index)
|
||||||
: QListWidgetItem(icon, text, parent, type)
|
: QListWidgetItem(icon, text, parent, type)
|
||||||
{
|
{
|
||||||
itemIndex = index;
|
itemIndex = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
DebugListItem::~DebugListItem()
|
MessageListItem::~MessageListItem()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QModelIndex DebugListItem::index() const
|
QModelIndex MessageListItem::index() const
|
||||||
{
|
{
|
||||||
return itemIndex;
|
return itemIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugListItem::setIndex(QModelIndex & index)
|
void MessageListItem::setIndex(QModelIndex & index)
|
||||||
{
|
{
|
||||||
itemIndex = index;
|
itemIndex = index;
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
/* debuglistitem.h
|
/* messagelistitem.h
|
||||||
|
|
||||||
Copyright (c) 2013, Nikolaj Schlej. All rights reserved.
|
Copyright (c) 2013, Nikolaj Schlej. All rights reserved.
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
@ -11,21 +11,21 @@
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __DEBUGLISTITEM_H__
|
#ifndef __MESSAGELISTITEM_H__
|
||||||
#define __DEBUGLISTITEM_H__
|
#define __MESSAGELISTITEM_H__
|
||||||
|
|
||||||
#include <QModelIndex>
|
#include <QModelIndex>
|
||||||
#include <QListWidgetItem>
|
#include <QListWidgetItem>
|
||||||
|
|
||||||
#include "basetypes.h"
|
#include "basetypes.h"
|
||||||
|
|
||||||
class DebugListItem : public QListWidgetItem
|
class MessageListItem : public QListWidgetItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DebugListItem(QListWidget * parent = 0, int type = Type, const QModelIndex & index = QModelIndex());
|
MessageListItem(QListWidget * parent = 0, int type = Type, const QModelIndex & index = QModelIndex());
|
||||||
DebugListItem(const QString & text, QListWidget * parent = 0, int type = Type, const QModelIndex & index = QModelIndex());
|
MessageListItem(const QString & text, QListWidget * parent = 0, int type = Type, const QModelIndex & index = QModelIndex());
|
||||||
DebugListItem(const QIcon & icon, const QString & text, QListWidget * parent = 0, int type = Type, const QModelIndex & index = QModelIndex());
|
MessageListItem(const QIcon & icon, const QString & text, QListWidget * parent = 0, int type = Type, const QModelIndex & index = QModelIndex());
|
||||||
~DebugListItem();
|
~MessageListItem();
|
||||||
|
|
||||||
QModelIndex index() const;
|
QModelIndex index() const;
|
||||||
void setIndex(QModelIndex & index);
|
void setIndex(QModelIndex & index);
|
23
treeitem.cpp
23
treeitem.cpp
@ -21,8 +21,6 @@ QString itemTypeToQString(const UINT8 type)
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case TreeItem::Root:
|
case TreeItem::Root:
|
||||||
return QObject::tr("Root");
|
return QObject::tr("Root");
|
||||||
case TreeItem::IntelImage:
|
|
||||||
return QObject::tr("Intel image");
|
|
||||||
case TreeItem::Image:
|
case TreeItem::Image:
|
||||||
return QObject::tr("Image");
|
return QObject::tr("Image");
|
||||||
case TreeItem::Capsule:
|
case TreeItem::Capsule:
|
||||||
@ -46,8 +44,13 @@ QString itemSubtypeToQString(const UINT8 type, const UINT8 subtype)
|
|||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case TreeItem::Root:
|
case TreeItem::Root:
|
||||||
case TreeItem::IntelImage:
|
|
||||||
case TreeItem::Image:
|
case TreeItem::Image:
|
||||||
|
if (subtype == TreeItem::IntelImage)
|
||||||
|
return QObject::tr("Intel");
|
||||||
|
else if (subtype == TreeItem::BiosImage)
|
||||||
|
return QObject::tr("BIOS");
|
||||||
|
else
|
||||||
|
return QObject::tr("Unknown");
|
||||||
case TreeItem::Padding:
|
case TreeItem::Padding:
|
||||||
case TreeItem::Volume:
|
case TreeItem::Volume:
|
||||||
return "";
|
return "";
|
||||||
@ -89,7 +92,7 @@ QString compressionTypeToQString(UINT8 algorithm)
|
|||||||
|
|
||||||
TreeItem::TreeItem(const UINT8 type, const UINT8 subtype, const UINT8 compression,
|
TreeItem::TreeItem(const UINT8 type, const UINT8 subtype, const UINT8 compression,
|
||||||
const QString & name, const QString & text, const QString & info,
|
const QString & name, const QString & text, const QString & info,
|
||||||
const QByteArray & header, const QByteArray & body,
|
const QByteArray & header, const QByteArray & body, const QByteArray & tail,
|
||||||
TreeItem *parent)
|
TreeItem *parent)
|
||||||
{
|
{
|
||||||
itemAction = NoAction;
|
itemAction = NoAction;
|
||||||
@ -101,6 +104,7 @@ TreeItem::TreeItem(const UINT8 type, const UINT8 subtype, const UINT8 compressio
|
|||||||
itemInfo = info;
|
itemInfo = info;
|
||||||
itemHeader = header;
|
itemHeader = header;
|
||||||
itemBody = body;
|
itemBody = body;
|
||||||
|
itemTail = tail;
|
||||||
parentItem = parent;
|
parentItem = parent;
|
||||||
|
|
||||||
// Set default names
|
// Set default names
|
||||||
@ -252,6 +256,12 @@ QByteArray TreeItem::body() const
|
|||||||
return itemBody;
|
return itemBody;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QByteArray TreeItem::tail() const
|
||||||
|
{
|
||||||
|
return itemTail;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool TreeItem::hasEmptyHeader() const
|
bool TreeItem::hasEmptyHeader() const
|
||||||
{
|
{
|
||||||
return itemHeader.isEmpty();
|
return itemHeader.isEmpty();
|
||||||
@ -262,6 +272,11 @@ bool TreeItem::hasEmptyBody() const
|
|||||||
return itemBody.isEmpty();
|
return itemBody.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TreeItem::hasEmptyTail() const
|
||||||
|
{
|
||||||
|
return itemTail.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
UINT8 TreeItem::action() const
|
UINT8 TreeItem::action() const
|
||||||
{
|
{
|
||||||
return itemAction;
|
return itemAction;
|
||||||
|
21
treeitem.h
21
treeitem.h
@ -30,16 +30,15 @@ class TreeItem
|
|||||||
public:
|
public:
|
||||||
// Action types
|
// Action types
|
||||||
enum ActionTypes {
|
enum ActionTypes {
|
||||||
NoAction,
|
NoAction = 50,
|
||||||
Remove,
|
Remove,
|
||||||
Reconstruct
|
Reconstruct
|
||||||
};
|
};
|
||||||
|
|
||||||
// Item types
|
// Item types
|
||||||
enum ItemTypes {
|
enum ItemTypes {
|
||||||
Root,
|
Root = 60,
|
||||||
Capsule,
|
Capsule,
|
||||||
IntelImage,
|
|
||||||
Image,
|
Image,
|
||||||
Region,
|
Region,
|
||||||
Padding,
|
Padding,
|
||||||
@ -48,15 +47,21 @@ public:
|
|||||||
Section
|
Section
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Image subtypes
|
||||||
|
enum ImageSubtypes{
|
||||||
|
IntelImage = 70,
|
||||||
|
BiosImage
|
||||||
|
};
|
||||||
|
|
||||||
// Capsule subtypes
|
// Capsule subtypes
|
||||||
enum CapsuleSubtypes {
|
enum CapsuleSubtypes {
|
||||||
AptioCapsule,
|
AptioCapsule = 80,
|
||||||
UefiCapsule
|
UefiCapsule
|
||||||
};
|
};
|
||||||
|
|
||||||
// Region subtypes
|
// Region subtypes
|
||||||
enum RegionSubtypes {
|
enum RegionSubtypes {
|
||||||
DescriptorRegion,
|
DescriptorRegion = 90,
|
||||||
GbeRegion,
|
GbeRegion,
|
||||||
MeRegion,
|
MeRegion,
|
||||||
BiosRegion,
|
BiosRegion,
|
||||||
@ -66,7 +71,8 @@ public:
|
|||||||
// Constructor
|
// Constructor
|
||||||
TreeItem(const UINT8 type, const UINT8 subtype = 0, const UINT8 compression = COMPRESSION_ALGORITHM_NONE,
|
TreeItem(const UINT8 type, const UINT8 subtype = 0, const UINT8 compression = COMPRESSION_ALGORITHM_NONE,
|
||||||
const QString &name = QString(), const QString &text = QString(), const QString &info = QString(),
|
const QString &name = QString(), const QString &text = QString(), const QString &info = QString(),
|
||||||
const QByteArray & header = QByteArray(), const QByteArray & body = QByteArray(), TreeItem *parent = 0);
|
const QByteArray & header = QByteArray(), const QByteArray & body = QByteArray(), const QByteArray & tail = QByteArray(),
|
||||||
|
TreeItem *parent = 0);
|
||||||
// Destructor
|
// Destructor
|
||||||
~TreeItem();
|
~TreeItem();
|
||||||
|
|
||||||
@ -91,6 +97,8 @@ public:
|
|||||||
bool hasEmptyHeader() const;
|
bool hasEmptyHeader() const;
|
||||||
QByteArray body() const;
|
QByteArray body() const;
|
||||||
bool hasEmptyBody() const;
|
bool hasEmptyBody() const;
|
||||||
|
QByteArray tail() const;
|
||||||
|
bool hasEmptyTail() const;
|
||||||
QString info() const;
|
QString info() const;
|
||||||
UINT8 compression() const;
|
UINT8 compression() const;
|
||||||
|
|
||||||
@ -117,6 +125,7 @@ private:
|
|||||||
UINT8 itemCompression;
|
UINT8 itemCompression;
|
||||||
QByteArray itemHeader;
|
QByteArray itemHeader;
|
||||||
QByteArray itemBody;
|
QByteArray itemBody;
|
||||||
|
QByteArray itemTail;
|
||||||
QString itemTypeName;
|
QString itemTypeName;
|
||||||
QString itemSubtypeName;
|
QString itemSubtypeName;
|
||||||
QString itemName;
|
QString itemName;
|
||||||
|
@ -154,8 +154,8 @@ UINT8 TreeModel::setItemAction(const UINT8 action, const QModelIndex &index)
|
|||||||
|
|
||||||
QModelIndex TreeModel::addItem(const UINT8 type, const UINT8 subtype, const UINT8 compression,
|
QModelIndex TreeModel::addItem(const UINT8 type, const UINT8 subtype, const UINT8 compression,
|
||||||
const QString & name, const QString & text, const QString & info,
|
const QString & name, const QString & text, const QString & info,
|
||||||
const QByteArray & header, const QByteArray & body, const QModelIndex & index,
|
const QByteArray & header, const QByteArray & body, const QByteArray & tail,
|
||||||
const UINT8 mode)
|
const QModelIndex & index, const UINT8 mode)
|
||||||
{
|
{
|
||||||
TreeItem *item;
|
TreeItem *item;
|
||||||
TreeItem *parentItem;
|
TreeItem *parentItem;
|
||||||
@ -176,7 +176,7 @@ QModelIndex TreeModel::addItem(const UINT8 type, const UINT8 subtype, const UINT
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TreeItem *newItem = new TreeItem(type, subtype, compression, name, text, info, header, body, parentItem);
|
TreeItem *newItem = new TreeItem(type, subtype, compression, name, text, info, header, body, tail, parentItem);
|
||||||
if (mode == INSERT_MODE_APPEND) {
|
if (mode == INSERT_MODE_APPEND) {
|
||||||
emit layoutAboutToBeChanged();
|
emit layoutAboutToBeChanged();
|
||||||
parentItem->appendChild(newItem);
|
parentItem->appendChild(newItem);
|
||||||
|
@ -47,8 +47,8 @@ public:
|
|||||||
|
|
||||||
QModelIndex addItem(const UINT8 type, const UINT8 subtype = 0, const UINT8 compression = COMPRESSION_ALGORITHM_NONE,
|
QModelIndex addItem(const UINT8 type, const UINT8 subtype = 0, const UINT8 compression = COMPRESSION_ALGORITHM_NONE,
|
||||||
const QString & name = QString(), const QString & text = QString(), const QString & info = QString(),
|
const QString & name = QString(), const QString & text = QString(), const QString & info = QString(),
|
||||||
const QByteArray & header = QByteArray(), const QByteArray & body = QByteArray(), const QModelIndex & index = QModelIndex(),
|
const QByteArray & header = QByteArray(), const QByteArray & body = QByteArray(), const QByteArray & tail = QByteArray(),
|
||||||
const UINT8 mode = INSERT_MODE_APPEND);
|
const QModelIndex & index = QModelIndex(), const UINT8 mode = INSERT_MODE_APPEND);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TreeItem *rootItem;
|
TreeItem *rootItem;
|
||||||
|
165
uefitool.cpp
165
uefitool.cpp
@ -23,7 +23,7 @@ UEFITool::UEFITool(QWidget *parent) :
|
|||||||
|
|
||||||
//Connect
|
//Connect
|
||||||
connect(ui->actionOpenImageFile, SIGNAL(triggered()), this, SLOT(openImageFile()));
|
connect(ui->actionOpenImageFile, SIGNAL(triggered()), this, SLOT(openImageFile()));
|
||||||
connect(ui->actionExtract, SIGNAL(triggered()), this, SLOT(extract()));
|
connect(ui->actionExtract, SIGNAL(triggered()), this, SLOT(extractAsIs()));
|
||||||
connect(ui->actionExtractBody, SIGNAL(triggered()), this, SLOT(extractBody()));
|
connect(ui->actionExtractBody, SIGNAL(triggered()), this, SLOT(extractBody()));
|
||||||
connect(ui->actionExtractUncompressed, SIGNAL(triggered()), this, SLOT(extractUncompressed()));
|
connect(ui->actionExtractUncompressed, SIGNAL(triggered()), this, SLOT(extractUncompressed()));
|
||||||
connect(ui->actionInsertInto, SIGNAL(triggered()), this, SLOT(insertInto()));
|
connect(ui->actionInsertInto, SIGNAL(triggered()), this, SLOT(insertInto()));
|
||||||
@ -49,7 +49,7 @@ UEFITool::~UEFITool()
|
|||||||
void UEFITool::init()
|
void UEFITool::init()
|
||||||
{
|
{
|
||||||
// Clear components
|
// Clear components
|
||||||
ui->debugListWidget->clear();
|
ui->messageListWidget->clear();
|
||||||
ui->infoEdit->clear();
|
ui->infoEdit->clear();
|
||||||
|
|
||||||
// Disable all actions except openImageFile
|
// Disable all actions except openImageFile
|
||||||
@ -72,58 +72,60 @@ void UEFITool::init()
|
|||||||
connect(ui->structureTreeView, SIGNAL(expanded(const QModelIndex &)), this, SLOT(resizeTreeViewColums(void)));
|
connect(ui->structureTreeView, SIGNAL(expanded(const QModelIndex &)), this, SLOT(resizeTreeViewColums(void)));
|
||||||
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->debugListWidget, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(scrollTreeView(QListWidgetItem*)));
|
connect(ui->messageListWidget, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(scrollTreeView(QListWidgetItem*)));
|
||||||
|
|
||||||
resizeTreeViewColums();
|
resizeTreeViewColums();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UEFITool::populateUi(const QModelIndex ¤t)
|
void UEFITool::populateUi(const QModelIndex ¤t)
|
||||||
{
|
{
|
||||||
currentIndex = current;
|
if (!current.isValid())
|
||||||
ui->infoEdit->setPlainText(current.data(Qt::UserRole).toString());
|
return;
|
||||||
ui->actionExtract->setDisabled(ffsEngine->hasEmptyBody(current) && ffsEngine->hasEmptyHeader(current));
|
|
||||||
ui->actionExtractBody->setDisabled(ffsEngine->hasEmptyHeader(current));
|
TreeItem* item = static_cast<TreeItem*>(current.internalPointer());
|
||||||
ui->actionExtractUncompressed->setEnabled(ffsEngine->isCompressedFile(current));
|
UINT8 type = item->type();
|
||||||
ui->actionRemove->setEnabled(ffsEngine->isOfType(TreeItem::Volume, current)
|
UINT8 subtype = item->subtype();
|
||||||
|| ffsEngine->isOfType(TreeItem::File, current)
|
|
||||||
|| ffsEngine->isOfType(TreeItem::Section, current));
|
ui->infoEdit->setPlainText(item->info());
|
||||||
ui->actionInsertInto->setEnabled(ffsEngine->isOfType(TreeItem::Volume, current)
|
ui->actionExtract->setDisabled(item->hasEmptyHeader() && item->hasEmptyBody() && item->hasEmptyTail());
|
||||||
|| ffsEngine->isOfType(TreeItem::File, current)
|
ui->actionExtractBody->setDisabled(item->hasEmptyHeader());
|
||||||
|| (ffsEngine->isOfType(TreeItem::Section, current)
|
//ui->actionExtractUncompressed->setEnabled(ffsEngine->isCompressedFile(current));
|
||||||
&& (ffsEngine->isOfSubtype(EFI_SECTION_COMPRESSION, current)
|
ui->actionRemove->setEnabled(type == TreeItem::Volume || type == TreeItem::File || type == TreeItem::Section);
|
||||||
|| ffsEngine->isOfSubtype(EFI_SECTION_GUID_DEFINED, current)
|
ui->actionInsertInto->setEnabled(type == TreeItem::Volume || type == TreeItem::File
|
||||||
|| ffsEngine->isOfSubtype(EFI_SECTION_DISPOSABLE, current))));
|
|| (type == TreeItem::Section && (subtype == EFI_SECTION_COMPRESSION || subtype == EFI_SECTION_GUID_DEFINED || subtype == EFI_SECTION_DISPOSABLE)));
|
||||||
ui->actionInsertBefore->setEnabled(ffsEngine->isOfType(TreeItem::File, current)
|
ui->actionInsertBefore->setEnabled(type == TreeItem::File || type == TreeItem::Section);
|
||||||
|| ffsEngine->isOfType(TreeItem::Section, current));
|
ui->actionInsertAfter->setEnabled(type == TreeItem::File || type == TreeItem::Section);
|
||||||
ui->actionInsertAfter->setEnabled(ffsEngine->isOfType(TreeItem::File, current)
|
|
||||||
|| ffsEngine->isOfType(TreeItem::Section, current));
|
|
||||||
//ui->actionReplace->setEnabled(ffsEngine->isOfType(TreeItem::File, current));
|
//ui->actionReplace->setEnabled(ffsEngine->isOfType(TreeItem::File, current));
|
||||||
}
|
}
|
||||||
|
|
||||||
void UEFITool::remove()
|
void UEFITool::remove()
|
||||||
{
|
{
|
||||||
UINT8 result = ffsEngine->remove(currentIndex);
|
QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex();
|
||||||
if (result) {
|
if (!index.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
}
|
UINT8 result = ffsEngine->remove(index);
|
||||||
else
|
|
||||||
|
if (result == ERR_SUCCESS)
|
||||||
ui->actionSaveImageFile->setEnabled(true);
|
ui->actionSaveImageFile->setEnabled(true);
|
||||||
|
|
||||||
resizeTreeViewColums();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UEFITool::insert(const UINT8 mode)
|
void UEFITool::insert(const UINT8 mode)
|
||||||
{
|
{
|
||||||
QString path;
|
QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex();
|
||||||
TreeItem* item = static_cast<TreeItem*>(currentIndex.internalPointer());
|
if (!index.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
|
||||||
UINT8 type;
|
UINT8 type;
|
||||||
UINT8 objectType;
|
UINT8 objectType;
|
||||||
|
|
||||||
if (mode == INSERT_MODE_BEFORE || mode == INSERT_MODE_AFTER)
|
if (mode == INSERT_MODE_BEFORE || mode == INSERT_MODE_AFTER)
|
||||||
type = item->parent()->type();
|
type = item->parent()->type();
|
||||||
else
|
else
|
||||||
type = item->type();
|
type = item->type();
|
||||||
|
|
||||||
|
QString path;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case TreeItem::Volume:
|
case TreeItem::Volume:
|
||||||
path = QFileDialog::getOpenFileName(this, tr("Select FFS file to insert"),".","FFS file (*.ffs *.bin);;All files (*.*)");
|
path = QFileDialog::getOpenFileName(this, tr("Select FFS file to insert"),".","FFS file (*.ffs *.bin);;All files (*.*)");
|
||||||
@ -131,7 +133,7 @@ void UEFITool::insert(const UINT8 mode)
|
|||||||
break;
|
break;
|
||||||
case TreeItem::File:
|
case TreeItem::File:
|
||||||
case TreeItem::Section:
|
case TreeItem::Section:
|
||||||
path = QFileDialog::getOpenFileName(this, tr("Select section file to insert"),".","Section file (*.sec *.bin);;All files (*.*)");
|
path = QFileDialog::getOpenFileName(this, tr("Select section file to insert"),".","Section file (*.sct *.bin);;All files (*.*)");
|
||||||
objectType = TreeItem::Section;
|
objectType = TreeItem::Section;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -157,13 +159,11 @@ void UEFITool::insert(const UINT8 mode)
|
|||||||
QByteArray buffer = inputFile.readAll();
|
QByteArray buffer = inputFile.readAll();
|
||||||
inputFile.close();
|
inputFile.close();
|
||||||
|
|
||||||
UINT8 result = ffsEngine->insert(currentIndex, buffer, objectType, mode);
|
UINT8 result = ffsEngine->insert(index, buffer, objectType, mode);
|
||||||
if (result)
|
if (result)
|
||||||
ui->statusBar->showMessage(tr("File can't be inserted (%1)").arg(result));
|
ui->statusBar->showMessage(tr("File can't be inserted (%1)").arg(result));
|
||||||
else
|
else
|
||||||
ui->actionSaveImageFile->setEnabled(true);
|
ui->actionSaveImageFile->setEnabled(true);
|
||||||
|
|
||||||
resizeTreeViewColums();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UEFITool::insertInto()
|
void UEFITool::insertInto()
|
||||||
@ -203,7 +203,7 @@ void UEFITool::saveImageFile()
|
|||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
ui->statusBar->showMessage(tr("Reconstruction failed (%1)").arg(result));
|
ui->statusBar->showMessage(tr("Reconstruction failed (%1)").arg(result));
|
||||||
showDebugMessage();
|
showMessage();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,7 +211,7 @@ void UEFITool::saveImageFile()
|
|||||||
outputFile.write(reconstructed);
|
outputFile.write(reconstructed);
|
||||||
outputFile.close();
|
outputFile.close();
|
||||||
ui->statusBar->showMessage(tr("Reconstructed image written"));
|
ui->statusBar->showMessage(tr("Reconstructed image written"));
|
||||||
showDebugMessage();
|
showMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UEFITool::resizeTreeViewColums()
|
void UEFITool::resizeTreeViewColums()
|
||||||
@ -255,13 +255,45 @@ 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()));
|
||||||
|
|
||||||
showDebugMessage();
|
showMessage();
|
||||||
resizeTreeViewColums();
|
resizeTreeViewColums();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UEFITool::extract()
|
void UEFITool::extract(const UINT8 mode)
|
||||||
{
|
{
|
||||||
QString path = QFileDialog::getSaveFileName(this, tr("Save selected item to binary file"),".","Binary files (*.bin);;All files (*.*)");
|
QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex();
|
||||||
|
if (!index.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
|
||||||
|
UINT8 type = item->type();
|
||||||
|
|
||||||
|
QString path;
|
||||||
|
switch (type) {
|
||||||
|
case TreeItem::Capsule:
|
||||||
|
path = QFileDialog::getSaveFileName(this, tr("Save capsule to binary file"),".","Capsule file (*.cap *.bin);;All files (*.*)");
|
||||||
|
break;
|
||||||
|
case TreeItem::Image:
|
||||||
|
path = QFileDialog::getSaveFileName(this, tr("Save image to binary file"),".","Image file (*.rom *.bin);;All files (*.*)");
|
||||||
|
break;
|
||||||
|
case TreeItem::Region:
|
||||||
|
path = QFileDialog::getSaveFileName(this, tr("Save region to binary file"),".","Region file (*.rgn *.bin);;All files (*.*)");
|
||||||
|
break;
|
||||||
|
case TreeItem::Padding:
|
||||||
|
path = QFileDialog::getSaveFileName(this, tr("Save padding to binary file"),".","Padding file (*.pad *.bin);;All files (*.*)");
|
||||||
|
break;
|
||||||
|
case TreeItem::Volume:
|
||||||
|
path = QFileDialog::getSaveFileName(this, tr("Save volume to binary file"),".","Volume file (*.vol *.bin);;All files (*.*)");
|
||||||
|
break;
|
||||||
|
case TreeItem::File:
|
||||||
|
path = QFileDialog::getSaveFileName(this, tr("Save FFS file to binary file"),".","FFS file (*.ffs *.bin);;All files (*.*)");
|
||||||
|
break;
|
||||||
|
case TreeItem::Section:
|
||||||
|
path = QFileDialog::getSaveFileName(this, tr("Select section file to insert"),".","Section file (*.sct *.bin);;All files (*.*)");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QFile outputFile;
|
QFile outputFile;
|
||||||
outputFile.setFileName(path);
|
outputFile.setFileName(path);
|
||||||
@ -271,43 +303,30 @@ void UEFITool::extract()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QByteArray extracted;
|
||||||
|
UINT8 result = ffsEngine->extract(index, extracted, mode);
|
||||||
|
if (result)
|
||||||
|
ui->statusBar->showMessage(tr("File can't be extracted (%1)").arg(result));
|
||||||
|
else {
|
||||||
outputFile.resize(0);
|
outputFile.resize(0);
|
||||||
outputFile.write(ffsEngine->header(currentIndex) + ffsEngine->body(currentIndex));
|
outputFile.write(extracted);
|
||||||
outputFile.close();
|
outputFile.close();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UEFITool::extractAsIs()
|
||||||
|
{
|
||||||
|
extract(EXTRACT_MODE_AS_IS);
|
||||||
|
}
|
||||||
|
|
||||||
void UEFITool::extractBody()
|
void UEFITool::extractBody()
|
||||||
{
|
{
|
||||||
QString path = QFileDialog::getSaveFileName(this, tr("Save selected item without header to file"),".","Binary files (*.bin);;All files (*.*)");
|
extract(EXTRACT_MODE_BODY_ONLY);
|
||||||
|
|
||||||
QFile outputFile;
|
|
||||||
outputFile.setFileName(path);
|
|
||||||
if (!outputFile.open(QFile::WriteOnly))
|
|
||||||
{
|
|
||||||
ui->statusBar->showMessage(tr("Can't open file for rewriting"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
outputFile.resize(0);
|
|
||||||
outputFile.write(ffsEngine->body(currentIndex));
|
|
||||||
outputFile.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UEFITool::extractUncompressed()
|
void UEFITool::extractUncompressed()
|
||||||
{
|
{
|
||||||
QString path = QFileDialog::getSaveFileName(this, tr("Save selected FFS file as uncompressed to file"),".","FFS files (*.ffs);;All files (*.*)");
|
extract(EXTRACT_MODE_UNCOMPRESSED);
|
||||||
|
|
||||||
QFile outputFile;
|
|
||||||
outputFile.setFileName(path);
|
|
||||||
if (!outputFile.open(QFile::WriteOnly))
|
|
||||||
{
|
|
||||||
ui->statusBar->showMessage(tr("Can't open file for rewriting"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
outputFile.resize(0);
|
|
||||||
outputFile.write(ffsEngine->decompressFile(currentIndex));
|
|
||||||
outputFile.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UEFITool::dragEnterEvent(QDragEnterEvent* event)
|
void UEFITool::dragEnterEvent(QDragEnterEvent* event)
|
||||||
@ -322,22 +341,22 @@ void UEFITool::dropEvent(QDropEvent* event)
|
|||||||
openImageFile(path);
|
openImageFile(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UEFITool::showDebugMessage()
|
void UEFITool::showMessage()
|
||||||
{
|
{
|
||||||
ui->debugListWidget->clear();
|
ui->messageListWidget->clear();
|
||||||
QQueue<DebugListItem*> debugItems = ffsEngine->debugMessage();
|
QQueue<MessageListItem*> messageItems = ffsEngine->message();
|
||||||
for (int i = 0; i < debugItems.count(); i++) {
|
for (int i = 0; i < messageItems.count(); i++) {
|
||||||
ui->debugListWidget->addItem((QListWidgetItem*) debugItems.at(i));
|
ui->messageListWidget->addItem(messageItems.at(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UEFITool::scrollTreeView(QListWidgetItem* item)
|
void UEFITool::scrollTreeView(QListWidgetItem* item)
|
||||||
{
|
{
|
||||||
DebugListItem* debugItem = (DebugListItem*) item;
|
MessageListItem* messageItem = (MessageListItem*) item;
|
||||||
QModelIndex index = debugItem->index();
|
QModelIndex index = messageItem->index();
|
||||||
if (index.isValid()) {
|
if (index.isValid()) {
|
||||||
ui->structureTreeView->scrollTo(index);
|
ui->structureTreeView->scrollTo(index);
|
||||||
ui->structureTreeView->selectionModel()->select(currentIndex, QItemSelectionModel::Clear);
|
ui->structureTreeView->selectionModel()->clearSelection();
|
||||||
ui->structureTreeView->selectionModel()->select(index, QItemSelectionModel::Select);
|
ui->structureTreeView->selectionModel()->select(index, QItemSelectionModel::Select);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -50,7 +50,8 @@ private slots:
|
|||||||
void saveImageFile();
|
void saveImageFile();
|
||||||
void populateUi(const QModelIndex ¤t);
|
void populateUi(const QModelIndex ¤t);
|
||||||
void resizeTreeViewColums();
|
void resizeTreeViewColums();
|
||||||
void extract();
|
void extract(const UINT8 mode);
|
||||||
|
void extractAsIs();
|
||||||
void extractBody();
|
void extractBody();
|
||||||
void extractUncompressed();
|
void extractUncompressed();
|
||||||
void insert(const UINT8 mode);
|
void insert(const UINT8 mode);
|
||||||
@ -64,11 +65,10 @@ private slots:
|
|||||||
private:
|
private:
|
||||||
Ui::UEFITool * ui;
|
Ui::UEFITool * ui;
|
||||||
FfsEngine* ffsEngine;
|
FfsEngine* ffsEngine;
|
||||||
QModelIndex currentIndex;
|
|
||||||
|
|
||||||
void dragEnterEvent(QDragEnterEvent* event);
|
void dragEnterEvent(QDragEnterEvent* event);
|
||||||
void dropEvent(QDropEvent* event);
|
void dropEvent(QDropEvent* event);
|
||||||
void showDebugMessage();
|
void showMessage();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -11,7 +11,7 @@ SOURCES += main.cpp \
|
|||||||
ffsengine.cpp \
|
ffsengine.cpp \
|
||||||
treeitem.cpp \
|
treeitem.cpp \
|
||||||
treemodel.cpp \
|
treemodel.cpp \
|
||||||
debuglistitem.cpp \
|
messagelistitem.cpp \
|
||||||
LZMA/LzmaCompress.c \
|
LZMA/LzmaCompress.c \
|
||||||
LZMA/LzmaDecompress.c \
|
LZMA/LzmaDecompress.c \
|
||||||
LZMA/SDK/C/LzFind.c \
|
LZMA/SDK/C/LzFind.c \
|
||||||
@ -29,7 +29,7 @@ HEADERS += uefitool.h \
|
|||||||
ffsengine.h \
|
ffsengine.h \
|
||||||
treeitem.h \
|
treeitem.h \
|
||||||
treemodel.h \
|
treemodel.h \
|
||||||
debuglistitem.h \
|
messagelistitem.h \
|
||||||
LZMA/LzmaCompress.h \
|
LZMA/LzmaCompress.h \
|
||||||
LZMA/LzmaDecompress.h \
|
LZMA/LzmaDecompress.h \
|
||||||
Tiano/EfiTianoDecompress.h \
|
Tiano/EfiTianoDecompress.h \
|
||||||
|
20
uefitool.ui
20
uefitool.ui
@ -20,7 +20,7 @@
|
|||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>UEFITool 0.7.0</string>
|
<string>UEFITool 0.8.0</string>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="centralWidget">
|
<widget class="QWidget" name="centralWidget">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
@ -135,7 +135,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0" colspan="2">
|
<item row="1" column="0" colspan="2">
|
||||||
<widget class="QGroupBox" name="debugGroupBox">
|
<widget class="QGroupBox" name="messageGroupBox">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@ -149,7 +149,7 @@
|
|||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Debug</string>
|
<string>Message</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
@ -159,7 +159,7 @@
|
|||||||
<number>5</number>
|
<number>5</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QListWidget" name="debugListWidget"/>
|
<widget class="QListWidget" name="messageListWidget"/>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
@ -201,7 +201,7 @@
|
|||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Insert after...</string>
|
<string>Insert object after...</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Insert an object from file after selected object</string>
|
<string>Insert an object from file after selected object</string>
|
||||||
@ -215,7 +215,7 @@
|
|||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Insert before...</string>
|
<string>Insert object before...</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Insert object from file before selected object</string>
|
<string>Insert object from file before selected object</string>
|
||||||
@ -243,10 +243,10 @@
|
|||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Extract...</string>
|
<string>Extract as is...</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Extract selected object to file</string>
|
<string>Extract selected object as is to file</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="shortcut">
|
<property name="shortcut">
|
||||||
<string>Ctrl+E</string>
|
<string>Ctrl+E</string>
|
||||||
@ -257,7 +257,7 @@
|
|||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Extract body...</string>
|
<string>Extract without header...</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Extract selected object without header to file</string>
|
<string>Extract selected object without header to file</string>
|
||||||
@ -310,7 +310,7 @@
|
|||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Insert into...</string>
|
<string>Insert object into...</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Insert object from file into selected object</string>
|
<string>Insert object from file into selected object</string>
|
||||||
|
Loading…
Reference in New Issue
Block a user