mirror of
https://github.com/LongSoft/UEFITool.git
synced 2024-11-28 19:08:22 +08:00
Version 0.14.0
Refactoring of engine and UI code to use model instead of items directly. WARNING: this code is untested yet and commited not for release purposes
This commit is contained in:
parent
9bc65c0590
commit
41fb0cbbf5
40
basetypes.h
40
basetypes.h
@ -110,6 +110,46 @@ typedef uint16_t CHAR16;
|
||||
#define SEARCH_MODE_BODY 2
|
||||
#define SEARCH_MODE_ALL 3
|
||||
|
||||
// Actions
|
||||
enum ActionTypes {
|
||||
NoAction = 50,
|
||||
Create,
|
||||
Insert,
|
||||
Replace,
|
||||
Remove,
|
||||
Rebuild
|
||||
};
|
||||
|
||||
// Types
|
||||
enum ItemTypes {
|
||||
Root = 60,
|
||||
Capsule,
|
||||
Image,
|
||||
Region,
|
||||
Padding,
|
||||
Volume,
|
||||
File,
|
||||
Section
|
||||
};
|
||||
// Subtypes
|
||||
enum ImageSubtypes{
|
||||
IntelImage = 70,
|
||||
BiosImage
|
||||
};
|
||||
|
||||
enum CapsuleSubtypes {
|
||||
AptioCapsule = 80,
|
||||
UefiCapsule
|
||||
};
|
||||
|
||||
enum RegionSubtypes {
|
||||
DescriptorRegion = 90,
|
||||
GbeRegion,
|
||||
MeRegion,
|
||||
BiosRegion,
|
||||
PdrRegion
|
||||
};
|
||||
|
||||
// EFI GUID
|
||||
typedef struct{
|
||||
UINT8 Data[16];
|
||||
|
@ -18,15 +18,15 @@ QString regionTypeToQString(const UINT8 type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case TreeItem::DescriptorRegion:
|
||||
case DescriptorRegion:
|
||||
return QObject::tr("Descriptor");
|
||||
case TreeItem::GbeRegion:
|
||||
case GbeRegion:
|
||||
return QObject::tr("GbE");
|
||||
case TreeItem::MeRegion:
|
||||
case MeRegion:
|
||||
return QObject::tr("ME");
|
||||
case TreeItem::BiosRegion:
|
||||
case BiosRegion:
|
||||
return QObject::tr("BIOS");
|
||||
case TreeItem::PdrRegion:
|
||||
case PdrRegion:
|
||||
return QObject::tr("PDR");
|
||||
default:
|
||||
return QObject::tr("Unknown");
|
||||
|
331
ffsengine.cpp
331
ffsengine.cpp
@ -27,19 +27,17 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
FfsEngine::FfsEngine(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
rootItem = new TreeItem(TreeItem::Root);
|
||||
treeModel = new TreeModel(rootItem);
|
||||
model = new TreeModel();
|
||||
}
|
||||
|
||||
FfsEngine::~FfsEngine(void)
|
||||
{
|
||||
delete treeModel;
|
||||
delete rootItem;
|
||||
delete model;
|
||||
}
|
||||
|
||||
TreeModel* FfsEngine::model() const
|
||||
TreeModel* FfsEngine::treeModel() const
|
||||
{
|
||||
return treeModel;
|
||||
return model;
|
||||
}
|
||||
|
||||
void FfsEngine::msg(const QString & message, const QModelIndex index)
|
||||
@ -57,24 +55,6 @@ void FfsEngine::clearMessages()
|
||||
messageItems.clear();
|
||||
}
|
||||
|
||||
QModelIndex FfsEngine::findParentOfType(UINT8 type, const QModelIndex& index) const
|
||||
{
|
||||
if(!index.isValid())
|
||||
return QModelIndex();
|
||||
|
||||
TreeItem *item;
|
||||
QModelIndex parent = index;
|
||||
|
||||
for(item = static_cast<TreeItem*>(parent.internalPointer());
|
||||
item != NULL && item != rootItem && item->type() != type;
|
||||
item = static_cast<TreeItem*>(parent.internalPointer()))
|
||||
parent = parent.parent();
|
||||
if (item != NULL && item != rootItem)
|
||||
return parent;
|
||||
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
bool FfsEngine::hasIntersection(const UINT32 begin1, const UINT32 end1, const UINT32 begin2, const UINT32 end2)
|
||||
{
|
||||
if (begin1 < begin2 && begin2 < end1)
|
||||
@ -116,7 +96,7 @@ UINT8 FfsEngine::parseInputFile(const QByteArray & buffer)
|
||||
.arg(capsuleHeader->Flags, 8, 16, QChar('0'))
|
||||
.arg(capsuleHeader->CapsuleImageSize, 8, 16, QChar('0'));
|
||||
// Add tree item
|
||||
index = treeModel->addItem(TreeItem::Capsule, TreeItem::UefiCapsule, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body);
|
||||
index = model->addItem(Capsule, UefiCapsule, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body);
|
||||
}
|
||||
|
||||
// Check buffer for being extended Aptio capsule header
|
||||
@ -133,7 +113,7 @@ UINT8 FfsEngine::parseInputFile(const QByteArray & buffer)
|
||||
.arg(aptioCapsuleHeader->CapsuleHeader.CapsuleImageSize - aptioCapsuleHeader->RomImageOffset, 8, 16, QChar('0'));
|
||||
//!TODO: more info about Aptio capsule
|
||||
// Add tree item
|
||||
index = treeModel->addItem(TreeItem::Capsule, TreeItem::AptioCapsule, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body);
|
||||
index = model->addItem(Capsule, AptioCapsule, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body);
|
||||
}
|
||||
|
||||
// Skip capsule header to have flash chip image
|
||||
@ -158,7 +138,7 @@ UINT8 FfsEngine::parseInputFile(const QByteArray & buffer)
|
||||
.arg(flashImage.size(), 8, 16, QChar('0'));
|
||||
|
||||
// Add tree item
|
||||
index = treeModel->addItem(TreeItem::Image, TreeItem::BiosImage, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), flashImage, QByteArray(), index);
|
||||
index = model->addItem(Image, BiosImage, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), flashImage, QByteArray(), index);
|
||||
return parseBios(flashImage, index);
|
||||
}
|
||||
|
||||
@ -288,7 +268,7 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & flashImage, QModelIndex & in
|
||||
.arg(descriptorMap->NumberOfIccTableEntries);
|
||||
|
||||
// Add Intel image tree item
|
||||
index = treeModel->addItem(TreeItem::Image, TreeItem::IntelImage, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), flashImage, QByteArray(), parent);
|
||||
index = model->addItem(Image, IntelImage, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), flashImage, QByteArray(), parent);
|
||||
|
||||
// Descriptor
|
||||
// Get descriptor info
|
||||
@ -316,7 +296,7 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & flashImage, QModelIndex & in
|
||||
}
|
||||
|
||||
// Add descriptor tree item
|
||||
treeModel->addItem(TreeItem::Region, TreeItem::DescriptorRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), body, QByteArray(), index);
|
||||
model->addItem(Region, DescriptorRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), body, QByteArray(), index);
|
||||
|
||||
// Sort regions in ascending order
|
||||
qSort(offsets);
|
||||
@ -372,7 +352,7 @@ UINT8 FfsEngine::parseGbeRegion(const QByteArray & gbe, QModelIndex & index, con
|
||||
.arg(version->minor);
|
||||
|
||||
// Add tree item
|
||||
index = treeModel->addItem(TreeItem::Region, TreeItem::GbeRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), gbe, QByteArray(), parent);
|
||||
index = model->addItem( Region, GbeRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), gbe, QByteArray(), parent);
|
||||
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
@ -403,7 +383,7 @@ UINT8 FfsEngine::parseMeRegion(const QByteArray & me, QModelIndex & index, const
|
||||
}
|
||||
|
||||
// Add tree item
|
||||
index = treeModel->addItem(TreeItem::Region, TreeItem::MeRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), me, QByteArray(), parent);
|
||||
index = model->addItem( Region, MeRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), me, QByteArray(), parent);
|
||||
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
@ -419,7 +399,7 @@ UINT8 FfsEngine::parsePdrRegion(const QByteArray & pdr, QModelIndex & index, con
|
||||
arg(pdr.size(), 8, 16, QChar('0'));
|
||||
|
||||
// Add tree item
|
||||
index = treeModel->addItem(TreeItem::Region, TreeItem::PdrRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), pdr, QByteArray(), parent);
|
||||
index = model->addItem( Region, PdrRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), pdr, QByteArray(), parent);
|
||||
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
@ -435,7 +415,7 @@ UINT8 FfsEngine::parseBiosRegion(const QByteArray & bios, QModelIndex & index, c
|
||||
arg(bios.size(), 8, 16, QChar('0'));
|
||||
|
||||
// Add tree item
|
||||
index = treeModel->addItem(TreeItem::Region, TreeItem::BiosRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), bios, QByteArray(), parent);
|
||||
index = model->addItem( Region, BiosRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), bios, QByteArray(), parent);
|
||||
|
||||
return parseBios(bios, index);
|
||||
}
|
||||
@ -460,7 +440,7 @@ UINT8 FfsEngine::parseBios(const QByteArray & bios, const QModelIndex & parent)
|
||||
info = tr("Size: %1")
|
||||
.arg(padding.size(), 8, 16, QChar('0'));
|
||||
// Add tree item
|
||||
treeModel->addItem(TreeItem::Padding, 0, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), padding, QByteArray(), parent);
|
||||
model->addItem( Padding, 0, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), padding, QByteArray(), parent);
|
||||
}
|
||||
|
||||
// Search for and parse all volumes
|
||||
@ -479,7 +459,7 @@ UINT8 FfsEngine::parseBios(const QByteArray & bios, const QModelIndex & parent)
|
||||
info = tr("Size: %1")
|
||||
.arg(padding.size(), 8, 16, QChar('0'));
|
||||
// Add tree item
|
||||
treeModel->addItem(TreeItem::Padding, 0, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), padding, QByteArray(), parent);
|
||||
model->addItem( Padding, 0, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), padding, QByteArray(), parent);
|
||||
}
|
||||
|
||||
// Get volume size
|
||||
@ -598,7 +578,7 @@ UINT8 FfsEngine::parseBios(const QByteArray & bios, const QModelIndex & parent)
|
||||
info = tr("Size: %2")
|
||||
.arg(padding.size(), 8, 16, QChar('0'));
|
||||
// Add tree item
|
||||
treeModel->addItem(TreeItem::Padding, 0, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), padding, QByteArray(), parent);
|
||||
model->addItem( Padding, 0, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), padding, QByteArray(), parent);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -709,7 +689,7 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, QModelIndex & index, co
|
||||
// Add tree item
|
||||
QByteArray header = volume.left(headerSize);
|
||||
QByteArray body = volume.mid(headerSize, volumeSize - headerSize);
|
||||
index = treeModel->addItem(TreeItem::Volume, 0, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
|
||||
index = model->addItem( Volume, 0, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
|
||||
|
||||
// Do not parse volumes with unknown FS
|
||||
if (!parseCurrentVolume)
|
||||
@ -919,7 +899,7 @@ UINT8 FfsEngine::parseFile(const QByteArray & file, QModelIndex & index, const U
|
||||
.arg(fileHeader->State, 2, 16, QChar('0'));
|
||||
|
||||
// Add tree item
|
||||
index = treeModel->addItem(TreeItem::File, fileHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, tail, parent, mode);
|
||||
index = model->addItem( File, fileHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, tail, parent, mode);
|
||||
|
||||
if (!parseCurrentFile)
|
||||
return ERR_SUCCESS;
|
||||
@ -1017,7 +997,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c
|
||||
.arg(compressedSectionHeader->UncompressedLength, 8, 16, QChar('0'));
|
||||
|
||||
// Add tree item
|
||||
index = treeModel->addItem(TreeItem::Section, sectionHeader->Type, algorithm, name, "", info, header, body, QByteArray(), parent, mode);
|
||||
index = model->addItem( Section, sectionHeader->Type, algorithm, name, "", info, header, body, QByteArray(), parent, mode);
|
||||
|
||||
// Parse decompressed data
|
||||
if (parseCurrentSection) {
|
||||
@ -1063,7 +1043,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c
|
||||
.arg(compressionTypeToQString(algorithm));
|
||||
|
||||
// Add tree item
|
||||
index = treeModel->addItem(TreeItem::Section, sectionHeader->Type, algorithm, name, "", info, header, body, QByteArray(), parent, mode);
|
||||
index = model->addItem( Section, sectionHeader->Type, algorithm, name, "", info, header, body, QByteArray(), parent, mode);
|
||||
|
||||
// Parse decompressed data
|
||||
if (parseCurrentSection) {
|
||||
@ -1084,7 +1064,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c
|
||||
.arg(body.size(), 8, 16, QChar('0'));
|
||||
|
||||
// Add tree item
|
||||
index = treeModel->addItem(TreeItem::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
|
||||
index = model->addItem( Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
|
||||
|
||||
// Parse section body
|
||||
result = parseSections(body, index);
|
||||
@ -1113,7 +1093,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c
|
||||
.arg(body.size(), 8, 16, QChar('0'));
|
||||
|
||||
// Add tree item
|
||||
index = treeModel->addItem(TreeItem::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
|
||||
index = model->addItem( Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
|
||||
break;
|
||||
case EFI_SECTION_USER_INTERFACE:
|
||||
{
|
||||
@ -1126,11 +1106,11 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c
|
||||
.arg(body.size(), 8, 16, QChar('0'));
|
||||
|
||||
// Add tree item
|
||||
index = treeModel->addItem(TreeItem::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
|
||||
index = model->addItem( Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
|
||||
|
||||
// Rename parent file
|
||||
QString text = QString::fromUtf16((const ushort*)body.constData());
|
||||
treeModel->setItemText(text, findParentOfType(TreeItem::File, parent));
|
||||
model->setTextString(model->findParentOfType(parent, File), text);
|
||||
}
|
||||
break;
|
||||
case EFI_SECTION_FIRMWARE_VOLUME_IMAGE:
|
||||
@ -1143,7 +1123,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c
|
||||
.arg(body.size(), 8, 16, QChar('0'));
|
||||
|
||||
// Add tree item
|
||||
index = treeModel->addItem(TreeItem::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
|
||||
index = model->addItem( Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
|
||||
|
||||
// Parse section body as BIOS space
|
||||
result = parseBios(body, index);
|
||||
@ -1162,7 +1142,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c
|
||||
.arg(body.size(), 8, 16, QChar('0'));
|
||||
|
||||
// Add tree item
|
||||
index = treeModel->addItem(TreeItem::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
|
||||
index = model->addItem( Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
|
||||
|
||||
// Parse section body as BIOS space
|
||||
result = parseBios(body, index);
|
||||
@ -1180,7 +1160,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c
|
||||
.arg(body.size(), 8, 16, QChar('0'));
|
||||
|
||||
// Add tree item
|
||||
index = treeModel->addItem(TreeItem::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
|
||||
index = model->addItem( Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
|
||||
msg(tr("parseSection: Section with unknown type (%1)").arg(sectionHeader->Type, 2, 16, QChar('0')), index);
|
||||
}
|
||||
return ERR_SUCCESS;
|
||||
@ -1200,14 +1180,13 @@ UINT8 FfsEngine::create(const QModelIndex & index, const UINT8 type, const QByte
|
||||
parent = index.parent();
|
||||
else
|
||||
parent = index;
|
||||
TreeItem * parentItem = static_cast<TreeItem*>(parent.internalPointer());
|
||||
|
||||
// Create item
|
||||
if (type == TreeItem::File) {
|
||||
if (parentItem->type() != TreeItem::Volume)
|
||||
if (type == File) {
|
||||
if (model->type(parent) != Volume)
|
||||
return ERR_INVALID_FILE;
|
||||
|
||||
EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*) parentItem->header().constData();
|
||||
EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*) model->header(parent).constData();
|
||||
UINT8 revision = volumeHeader->Revision;
|
||||
bool erasePolarity = volumeHeader->Attributes & EFI_FVB_ERASE_POLARITY;
|
||||
|
||||
@ -1257,10 +1236,10 @@ UINT8 FfsEngine::create(const QModelIndex & index, const UINT8 type, const QByte
|
||||
return result;
|
||||
|
||||
// Set action
|
||||
treeModel->setItemAction(action, fileIndex);
|
||||
model->setAction(fileIndex, action);
|
||||
}
|
||||
else if (type == TreeItem::Section) {
|
||||
if (parentItem->type() != TreeItem::File && parentItem->type() != TreeItem::Section)
|
||||
else if (type == Section) {
|
||||
if (model->type(parent) != File && model->type(parent) != Section)
|
||||
return ERR_INVALID_SECTION;
|
||||
|
||||
if (header.size() < sizeof(EFI_COMMON_SECTION_HEADER))
|
||||
@ -1303,7 +1282,7 @@ UINT8 FfsEngine::create(const QModelIndex & index, const UINT8 type, const QByte
|
||||
return result;
|
||||
|
||||
// Set create action
|
||||
treeModel->setItemAction(action, sectionIndex);
|
||||
model->setAction(sectionIndex, action);
|
||||
}
|
||||
break;
|
||||
case EFI_SECTION_GUID_DEFINED:{
|
||||
@ -1326,7 +1305,7 @@ UINT8 FfsEngine::create(const QModelIndex & index, const UINT8 type, const QByte
|
||||
return result;
|
||||
|
||||
// Set create action
|
||||
treeModel->setItemAction(action, sectionIndex);
|
||||
model->setAction(sectionIndex, action);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -1343,7 +1322,7 @@ UINT8 FfsEngine::create(const QModelIndex & index, const UINT8 type, const QByte
|
||||
return result;
|
||||
|
||||
// Set create action
|
||||
treeModel->setItemAction(action, sectionIndex);
|
||||
model->setAction(sectionIndex, action);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -1362,24 +1341,23 @@ UINT8 FfsEngine::insert(const QModelIndex & index, const QByteArray & object, co
|
||||
parent = index.parent();
|
||||
else
|
||||
parent = index;
|
||||
TreeItem * parentItem = static_cast<TreeItem*>(parent.internalPointer());
|
||||
|
||||
// Determine type of item to insert
|
||||
UINT8 type;
|
||||
UINT32 headerSize;
|
||||
if (parentItem->type() == TreeItem::Volume) {
|
||||
type = TreeItem::File;
|
||||
if (model->type(parent) == Volume) {
|
||||
type = File;
|
||||
headerSize = sizeof(EFI_FFS_FILE_HEADER);
|
||||
}
|
||||
else if (parentItem->type() == TreeItem::File) {
|
||||
type = TreeItem::Section;
|
||||
else if (model->type(parent) == File) {
|
||||
type = Section;
|
||||
EFI_COMMON_SECTION_HEADER* commonHeader = (EFI_COMMON_SECTION_HEADER*) object.constData();
|
||||
headerSize = sizeOfSectionHeaderOfType(commonHeader->Type);
|
||||
}
|
||||
else
|
||||
return ERR_NOT_IMPLEMENTED;
|
||||
|
||||
return create(index, type, object.left(headerSize), object.right(object.size() - headerSize), mode, TreeItem::Insert);
|
||||
return create(index, type, object.left(headerSize), object.right(object.size() - headerSize), mode, Insert);
|
||||
}
|
||||
|
||||
UINT8 FfsEngine::replace(const QModelIndex & index, const QByteArray & object, const UINT8 mode)
|
||||
@ -1387,29 +1365,27 @@ UINT8 FfsEngine::replace(const QModelIndex & index, const QByteArray & object, c
|
||||
if (!index.isValid())
|
||||
return ERR_INVALID_PARAMETER;
|
||||
|
||||
TreeItem * parentItem = static_cast<TreeItem*>(index.internalPointer());
|
||||
|
||||
// Determine type of item to replace
|
||||
UINT32 headerSize;
|
||||
UINT8 result;
|
||||
if (parentItem->type() == TreeItem::File) {
|
||||
if (model->type(index) == File) {
|
||||
if (mode == REPLACE_MODE_AS_IS) {
|
||||
headerSize = sizeof(EFI_FFS_FILE_HEADER);
|
||||
result = create(index, TreeItem::File, object.left(headerSize), object.right(object.size() - headerSize), CREATE_MODE_AFTER, TreeItem::Replace);
|
||||
result = create(index, File, object.left(headerSize), object.right(object.size() - headerSize), CREATE_MODE_AFTER, Replace);
|
||||
}
|
||||
else if (mode == REPLACE_MODE_BODY)
|
||||
result = create(index, TreeItem::File, parentItem->header(), object, CREATE_MODE_AFTER, TreeItem::Replace);
|
||||
result = create(index, File, model->header(index), object, CREATE_MODE_AFTER, Replace);
|
||||
else
|
||||
return ERR_NOT_IMPLEMENTED;
|
||||
}
|
||||
else if (parentItem->type() == TreeItem::Section) {
|
||||
else if (model->type(index) == Section) {
|
||||
if (mode == REPLACE_MODE_AS_IS) {
|
||||
EFI_COMMON_SECTION_HEADER* commonHeader = (EFI_COMMON_SECTION_HEADER*) object.constData();
|
||||
headerSize = sizeOfSectionHeaderOfType(commonHeader->Type);
|
||||
result = create(index, TreeItem::Section, object.left(headerSize), object.right(object.size() - headerSize), CREATE_MODE_AFTER, TreeItem::Replace);
|
||||
result = create(index, Section, object.left(headerSize), object.right(object.size() - headerSize), CREATE_MODE_AFTER, Replace);
|
||||
}
|
||||
else if (mode == REPLACE_MODE_BODY) {
|
||||
result = create(index, TreeItem::Section, parentItem->header(), object, CREATE_MODE_AFTER, TreeItem::Replace, parentItem->compression());
|
||||
result = create(index, Section, model->header(index), object, CREATE_MODE_AFTER, Replace, model->compression(index));
|
||||
}
|
||||
else
|
||||
return ERR_NOT_IMPLEMENTED;
|
||||
@ -1422,7 +1398,7 @@ UINT8 FfsEngine::replace(const QModelIndex & index, const QByteArray & object, c
|
||||
return result;
|
||||
|
||||
// Set remove action to replaced item
|
||||
treeModel->setItemAction(TreeItem::Remove, index);
|
||||
model->setAction(index, Remove);
|
||||
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
@ -1433,39 +1409,37 @@ UINT8 FfsEngine::extract(const QModelIndex & index, QByteArray & extracted, cons
|
||||
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());
|
||||
extracted.append(model->header(index));
|
||||
extracted.append(model->body(index));
|
||||
extracted.append(model->tail(index));
|
||||
}
|
||||
else if (mode == EXTRACT_MODE_BODY) {
|
||||
// Extract without header and tail
|
||||
extracted.clear();
|
||||
// Special case of compressed bodies
|
||||
if (item->type() == TreeItem::Section) {
|
||||
if (model->type(index) == Section) {
|
||||
QByteArray decompressed;
|
||||
UINT8 result;
|
||||
if (item->subtype() == EFI_SECTION_COMPRESSION) {
|
||||
EFI_COMPRESSION_SECTION* compressedHeader = (EFI_COMPRESSION_SECTION*) item->header().constData();
|
||||
result = decompress(item->body(), compressedHeader->CompressionType, decompressed);
|
||||
if (model->subtype(index) == EFI_SECTION_COMPRESSION) {
|
||||
EFI_COMPRESSION_SECTION* compressedHeader = (EFI_COMPRESSION_SECTION*) model->header(index).constData();
|
||||
result = decompress(model->body(index), compressedHeader->CompressionType, decompressed);
|
||||
if (result)
|
||||
return result;
|
||||
extracted.append(decompressed);
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
else if (item->subtype() == EFI_SECTION_GUID_DEFINED) {
|
||||
else if (model->subtype(index) == EFI_SECTION_GUID_DEFINED) {
|
||||
QByteArray decompressed;
|
||||
// Check if section requires processing
|
||||
EFI_GUID_DEFINED_SECTION* guidDefinedSectionHeader = (EFI_GUID_DEFINED_SECTION*) item->header().constData();
|
||||
EFI_GUID_DEFINED_SECTION* guidDefinedSectionHeader = (EFI_GUID_DEFINED_SECTION*) model->header(index).constData();
|
||||
if (guidDefinedSectionHeader->Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) {
|
||||
// Try to decompress section body using both known compression algorithms
|
||||
result = decompress(item->body(), EFI_STANDARD_COMPRESSION, decompressed);
|
||||
result = decompress(model->body(index), EFI_STANDARD_COMPRESSION, decompressed);
|
||||
if (result) {
|
||||
result = decompress(item->body(), EFI_CUSTOMIZED_COMPRESSION, decompressed);
|
||||
result = decompress(model->body(index), EFI_CUSTOMIZED_COMPRESSION, decompressed);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
@ -1475,7 +1449,7 @@ UINT8 FfsEngine::extract(const QModelIndex & index, QByteArray & extracted, cons
|
||||
}
|
||||
}
|
||||
|
||||
extracted.append(item->body());
|
||||
extracted.append(model->body(index));
|
||||
}
|
||||
else
|
||||
return ERR_UNKNOWN_EXTRACT_MODE;
|
||||
@ -1489,7 +1463,7 @@ UINT8 FfsEngine::remove(const QModelIndex & index)
|
||||
return ERR_INVALID_PARAMETER;
|
||||
|
||||
// Set action for the item
|
||||
treeModel->setItemAction(TreeItem::Remove, index);
|
||||
model->setAction(index, Remove);
|
||||
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
@ -1500,7 +1474,7 @@ UINT8 FfsEngine::rebuild(const QModelIndex & index)
|
||||
return ERR_INVALID_PARAMETER;
|
||||
|
||||
// Set action for the item
|
||||
treeModel->setItemAction(TreeItem::Rebuild, index);
|
||||
model->setAction(index, Rebuild);
|
||||
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
@ -1697,7 +1671,7 @@ UINT8 FfsEngine::compress(const QByteArray & data, const UINT8 algorithm, QByteA
|
||||
UINT8 FfsEngine::reconstructImage(QByteArray & reconstructed)
|
||||
{
|
||||
QQueue<QByteArray> queue;
|
||||
UINT8 result = reconstruct(treeModel->index(0,0), queue);
|
||||
UINT8 result = reconstruct(model->index(0,0), queue);
|
||||
if (result)
|
||||
return result;
|
||||
reconstructed.clear();
|
||||
@ -1740,35 +1714,31 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
||||
if (!index.isValid())
|
||||
return ERR_SUCCESS;
|
||||
|
||||
TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
|
||||
if (item == rootItem)
|
||||
return ERR_SUCCESS;
|
||||
|
||||
QByteArray reconstructed;
|
||||
UINT8 result;
|
||||
|
||||
// No action is needed, just return header + body + tail
|
||||
if (item->action() == TreeItem::NoAction) {
|
||||
reconstructed = item->header().append(item->body()).append(item->tail());
|
||||
if (model->action(index) == NoAction) {
|
||||
reconstructed = model->header(index).append(model->body(index)).append(model->tail(index));
|
||||
queue.enqueue(reconstructed);
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
// Remove item
|
||||
else if (item->action() == TreeItem::Remove) {
|
||||
else if (model->action(index) == Remove) {
|
||||
// Volume can be removed by replacing all it's contents with empty bytes
|
||||
if (item->type() == TreeItem::Volume) {
|
||||
EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*) item->header().constData();
|
||||
if (model->type(index) == Volume) {
|
||||
EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*) model->header(index).constData();
|
||||
char empty = volumeHeader->Attributes & EFI_FVB_ERASE_POLARITY ? '\xFF' : '\x00';
|
||||
reconstructed.fill(empty, item->header().size() + item->body().size() + item->tail().size());
|
||||
reconstructed.fill(empty, model->header(index).size() + model->body(index).size() + model->tail(index).size());
|
||||
queue.enqueue(reconstructed);
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
// File can be removed
|
||||
if (item->type() == TreeItem::File)
|
||||
if (model->type(index) == File)
|
||||
// Add nothing to queue
|
||||
return ERR_SUCCESS;
|
||||
// Section can be removed
|
||||
else if (item->type() == TreeItem::Section)
|
||||
else if (model->type(index) == Section)
|
||||
// Add nothing to queue
|
||||
return ERR_SUCCESS;
|
||||
// Other item types can't be removed
|
||||
@ -1776,12 +1746,15 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
||||
return ERR_NOT_IMPLEMENTED;
|
||||
}
|
||||
// Reconstruct item and it's children recursive
|
||||
else if (item->action() == TreeItem::Create || item->action() == TreeItem::Insert || item->action() == TreeItem::Replace || item->action() == TreeItem::Rebuild) {
|
||||
else if (model->action(index) == Create
|
||||
|| model->action(index) == Insert
|
||||
|| model->action(index) == Replace
|
||||
|| model->action(index) == Rebuild) {
|
||||
QQueue<QByteArray> childrenQueue;
|
||||
|
||||
switch (item->type()) {
|
||||
case TreeItem::Image:
|
||||
if (item->subtype() == TreeItem::IntelImage) {
|
||||
switch (model->type(index)) {
|
||||
case Image:
|
||||
if (model->subtype(index) == IntelImage) {
|
||||
// Reconstruct Intel image
|
||||
// First child will always be descriptor for this type of image
|
||||
result = reconstruct(index.child(0, index.column()), childrenQueue);
|
||||
@ -1808,34 +1781,34 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
||||
UINT32 offset = descriptor.size();
|
||||
// Reconstruct other regions
|
||||
char empty = '\xFF'; //!TODO: determine empty char using one of reserved descriptor fields
|
||||
for (int i = 1; i < item->childCount(); i++) {
|
||||
for (int i = 1; i < model->rowCount(index); i++) {
|
||||
result = reconstruct(index.child(i, index.column()), childrenQueue);
|
||||
if (result)
|
||||
return result;
|
||||
switch(item->child(i)->subtype())
|
||||
switch(model->subtype(model->index(i, 0, index)))
|
||||
{
|
||||
case TreeItem::GbeRegion:
|
||||
case GbeRegion:
|
||||
gbe = childrenQueue.dequeue();
|
||||
if (gbeBegin > offset)
|
||||
reconstructed.append(QByteArray(gbeBegin - offset, empty));
|
||||
reconstructed.append(gbe);
|
||||
offset = gbeEnd;
|
||||
break;
|
||||
case TreeItem::MeRegion:
|
||||
case MeRegion:
|
||||
me = childrenQueue.dequeue();
|
||||
if (meBegin > offset)
|
||||
reconstructed.append(QByteArray(meBegin - offset, empty));
|
||||
reconstructed.append(me);
|
||||
offset = meEnd;
|
||||
break;
|
||||
case TreeItem::BiosRegion:
|
||||
case BiosRegion:
|
||||
bios = childrenQueue.dequeue();
|
||||
if (biosBegin > offset)
|
||||
reconstructed.append(QByteArray(biosBegin - offset, empty));
|
||||
reconstructed.append(bios);
|
||||
offset = biosEnd;
|
||||
break;
|
||||
case TreeItem::PdrRegion:
|
||||
case PdrRegion:
|
||||
pdr = childrenQueue.dequeue();
|
||||
if (pdrBegin > offset)
|
||||
reconstructed.append(QByteArray(pdrBegin - offset, empty));
|
||||
@ -1847,37 +1820,37 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
||||
return ERR_INVALID_REGION;
|
||||
}
|
||||
}
|
||||
if ((UINT32)item->body().size() > offset)
|
||||
reconstructed.append(QByteArray((UINT32)item->body().size() - offset, empty));
|
||||
if ((UINT32)model->body(index).size() > offset)
|
||||
reconstructed.append(QByteArray((UINT32)model->body(index).size() - offset, empty));
|
||||
|
||||
// Check size of reconstructed image, it must be same
|
||||
if (reconstructed.size() > item->body().size()) {
|
||||
if (reconstructed.size() > model->body(index).size()) {
|
||||
msg(tr("reconstruct: reconstructed body %1 is bigger then original %2")
|
||||
.arg(reconstructed.size(), 8, 16, QChar('0'))
|
||||
.arg(item->body().size(), 8, 16, QChar('0')), index);
|
||||
.arg(model->body(index).size(), 8, 16, QChar('0')), index);
|
||||
return ERR_INVALID_PARAMETER;
|
||||
}
|
||||
else if (reconstructed.size() < item->body().size()) {
|
||||
else if (reconstructed.size() < model->body(index).size()) {
|
||||
msg(tr("reconstruct: reconstructed body %1 is smaller then original %2")
|
||||
.arg(reconstructed.size(), 8, 16, QChar('0'))
|
||||
.arg(item->body().size(), 8, 16, QChar('0')), index);
|
||||
.arg(model->body(index).size(), 8, 16, QChar('0')), index);
|
||||
return ERR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// Enqueue reconstructed item
|
||||
queue.enqueue(item->header().append(reconstructed));
|
||||
queue.enqueue(model->header(index).append(reconstructed));
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
// BIOS Image must be treated like region
|
||||
case TreeItem::Capsule:
|
||||
if (item->subtype() == TreeItem::AptioCapsule)
|
||||
case Capsule:
|
||||
if (model->subtype(index) == AptioCapsule)
|
||||
msg(tr("reconstruct: Aptio capsule checksum and signature can now become invalid"), index);
|
||||
case TreeItem::Region:
|
||||
case Region:
|
||||
{
|
||||
// Reconstruct item body
|
||||
if (item->childCount()) {
|
||||
if (model->rowCount(index)) {
|
||||
// Reconstruct item children
|
||||
for (int i = 0; i < item->childCount(); i++) {
|
||||
for (int i = 0; i < model->rowCount(index); i++) {
|
||||
result = reconstruct(index.child(i, index.column()), childrenQueue);
|
||||
if (result)
|
||||
return result;
|
||||
@ -1889,33 +1862,33 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
||||
}
|
||||
// Use stored item body
|
||||
else
|
||||
reconstructed = item->body();
|
||||
reconstructed = model->body(index);
|
||||
|
||||
// Check size of reconstructed image, it must be same
|
||||
if (item->type() != TreeItem::Root) {
|
||||
if (reconstructed.size() > item->body().size()) {
|
||||
if (model->type(index) != Root) {
|
||||
if (reconstructed.size() > model->body(index).size()) {
|
||||
msg(tr("reconstructed: reconstructed body %1 is bigger then original %2")
|
||||
.arg(reconstructed.size(), 8, 16, QChar('0'))
|
||||
.arg(item->body().size(), 8, 16, QChar('0')), index);
|
||||
.arg(model->body(index).size(), 8, 16, QChar('0')), index);
|
||||
return ERR_INVALID_PARAMETER;
|
||||
}
|
||||
else if (reconstructed.size() < item->body().size()) {
|
||||
else if (reconstructed.size() < model->body(index).size()) {
|
||||
msg(tr("reconstructed: reconstructed body %1 is smaller then original %2")
|
||||
.arg(reconstructed.size(), 8, 16, QChar('0'))
|
||||
.arg(item->body().size(), 8, 16, QChar('0')), index);
|
||||
.arg(model->body(index).size(), 8, 16, QChar('0')), index);
|
||||
return ERR_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
// Enqueue reconstructed item
|
||||
queue.enqueue(item->header().append(reconstructed));
|
||||
queue.enqueue(model->header(index).append(reconstructed));
|
||||
}
|
||||
break;
|
||||
|
||||
case TreeItem::Volume:
|
||||
case Volume:
|
||||
{
|
||||
//!TODO: add check for weak aligned volumes
|
||||
QByteArray header = item->header();
|
||||
QByteArray header = model->header(index);
|
||||
EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*) header.data();
|
||||
|
||||
// Recalculate volume header checksum
|
||||
@ -1923,12 +1896,12 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
||||
volumeHeader->Checksum = calculateChecksum16((UINT16*) volumeHeader, volumeHeader->HeaderLength);
|
||||
|
||||
// Reconstruct volume body
|
||||
if (item->childCount()) {
|
||||
if (model->rowCount(index)) {
|
||||
UINT8 polarity = volumeHeader->Attributes & EFI_FVB_ERASE_POLARITY ? ERASE_POLARITY_TRUE : ERASE_POLARITY_FALSE;
|
||||
char empty = volumeHeader->Attributes & EFI_FVB_ERASE_POLARITY ? '\xFF' : '\x00';
|
||||
|
||||
// Reconstruct files in volume
|
||||
for (int i = 0; i < item->childCount(); i++) {
|
||||
for (int i = 0; i < model->rowCount(index); i++) {
|
||||
// Reconstruct files
|
||||
result = reconstruct(index.child(i, index.column()), childrenQueue, volumeHeader->Revision, polarity);
|
||||
if (result)
|
||||
@ -2030,8 +2003,8 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
||||
// No more space left in volume
|
||||
else if (vtfOffset < offset) {
|
||||
// Check if volume can be grown
|
||||
UINT8 parentType = item->parent()->type();
|
||||
if(parentType != TreeItem::File && parentType != TreeItem::Section) {
|
||||
UINT8 parentType = model->type(index.parent());
|
||||
if(parentType != File && parentType != Section) {
|
||||
msg(tr("%1: can't grow root volume").arg(guidToQString(volumeHeader->FileSystemGuid)), index);
|
||||
return ERR_INVALID_VOLUME;
|
||||
}
|
||||
@ -2070,8 +2043,8 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
||||
}
|
||||
else {
|
||||
// Check if volume can be grown
|
||||
UINT8 parentType = item->parent()->type();
|
||||
if(parentType != TreeItem::File && parentType != TreeItem::Section) {
|
||||
UINT8 parentType = model->type(index.parent());
|
||||
if(parentType != File && parentType != Section) {
|
||||
msg(tr("%1: can't grow root volume").arg(guidToQString(volumeHeader->FileSystemGuid)), index);
|
||||
return ERR_INVALID_VOLUME;
|
||||
}
|
||||
@ -2104,16 +2077,16 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
||||
}
|
||||
// Use current volume body
|
||||
else
|
||||
reconstructed = item->body();
|
||||
reconstructed = model->body(index);
|
||||
|
||||
// Enqueue reconstructed item
|
||||
queue.enqueue(header.append(reconstructed));
|
||||
}
|
||||
break;
|
||||
|
||||
case TreeItem::File:
|
||||
case File:
|
||||
{
|
||||
QByteArray header = item->header();
|
||||
QByteArray header = model->header(index);
|
||||
EFI_FFS_FILE_HEADER* fileHeader = (EFI_FFS_FILE_HEADER*) header.data();
|
||||
|
||||
// Check erase polarity
|
||||
@ -2169,8 +2142,8 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
||||
}
|
||||
|
||||
// Reconstruct file body
|
||||
if (item->childCount()) {
|
||||
for (int i = 0; i < item->childCount(); i++) {
|
||||
if (model->rowCount(index)) {
|
||||
for (int i = 0; i < model->rowCount(index); i++) {
|
||||
// Reconstruct sections
|
||||
result = reconstruct(index.child(i, index.column()), childrenQueue, revision, empty);
|
||||
if (result)
|
||||
@ -2199,7 +2172,7 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
||||
}
|
||||
|
||||
// Correct file size
|
||||
UINT8 tailSize = item->hasEmptyTail() ? 0 : sizeof(UINT16);
|
||||
UINT8 tailSize = model->hasEmptyTail(index) ? 0 : sizeof(UINT16);
|
||||
|
||||
uint32ToUint24(sizeof(EFI_FFS_FILE_HEADER) + reconstructed.size() + tailSize, fileHeader->Size);
|
||||
|
||||
@ -2211,7 +2184,7 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
||||
}
|
||||
// Use current file body
|
||||
else
|
||||
reconstructed = item->body();
|
||||
reconstructed = model->body(index);
|
||||
|
||||
// Recalculate data checksum, if needed
|
||||
if (fileHeader->Attributes & FFS_ATTRIB_CHECKSUM) {
|
||||
@ -2223,7 +2196,7 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
||||
fileHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM2;
|
||||
|
||||
// Append tail, if needed
|
||||
if (!item->hasEmptyTail())
|
||||
if (!model->hasEmptyTail(index))
|
||||
reconstructed.append(~fileHeader->IntegrityCheck.TailReference);
|
||||
|
||||
// Set file state
|
||||
@ -2237,15 +2210,15 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
||||
}
|
||||
break;
|
||||
|
||||
case TreeItem::Section:
|
||||
case Section:
|
||||
{
|
||||
QByteArray header = item->header();
|
||||
QByteArray header = model->header(index);
|
||||
EFI_COMMON_SECTION_HEADER* commonHeader = (EFI_COMMON_SECTION_HEADER*) header.data();
|
||||
|
||||
// Section with children
|
||||
if (item->childCount()) {
|
||||
if (model->rowCount(index)) {
|
||||
// Reconstruct section body
|
||||
for (int i = 0; i < item->childCount(); i++) {
|
||||
for (int i = 0; i < model->rowCount(index); i++) {
|
||||
// Reconstruct subsections
|
||||
result = reconstruct(index.child(i, index.column()), childrenQueue);
|
||||
if (result)
|
||||
@ -2275,21 +2248,21 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
||||
}
|
||||
|
||||
// Only this 2 sections can have compressed body
|
||||
if (item->subtype() == EFI_SECTION_COMPRESSION) {
|
||||
if (model->subtype(index) == EFI_SECTION_COMPRESSION) {
|
||||
EFI_COMPRESSION_SECTION* compessionHeader = (EFI_COMPRESSION_SECTION*) header.data();
|
||||
// Set new uncompressed size
|
||||
compessionHeader->UncompressedLength = reconstructed.size();
|
||||
// Compress new section body
|
||||
QByteArray compressed;
|
||||
result = compress(reconstructed, item->compression(), compressed);
|
||||
result = compress(reconstructed, model->compression(index), compressed);
|
||||
if (result)
|
||||
return result;
|
||||
// Correct compression type
|
||||
if (item->compression() == COMPRESSION_ALGORITHM_NONE)
|
||||
if (model->compression(index) == COMPRESSION_ALGORITHM_NONE)
|
||||
compessionHeader->CompressionType = EFI_NOT_COMPRESSED;
|
||||
else if (item->compression() == COMPRESSION_ALGORITHM_LZMA || item->compression() == COMPRESSION_ALGORITHM_IMLZMA)
|
||||
else if (model->compression(index) == COMPRESSION_ALGORITHM_LZMA || model->compression(index) == COMPRESSION_ALGORITHM_IMLZMA)
|
||||
compessionHeader->CompressionType = EFI_CUSTOMIZED_COMPRESSION;
|
||||
else if (item->compression() == COMPRESSION_ALGORITHM_EFI11 || item->compression() == COMPRESSION_ALGORITHM_TIANO)
|
||||
else if (model->compression(index) == COMPRESSION_ALGORITHM_EFI11 || model->compression(index) == COMPRESSION_ALGORITHM_TIANO)
|
||||
compessionHeader->CompressionType = EFI_STANDARD_COMPRESSION;
|
||||
else
|
||||
return ERR_UNKNOWN_COMPRESSION_ALGORITHM;
|
||||
@ -2297,11 +2270,11 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
||||
// Replace new section body
|
||||
reconstructed = compressed;
|
||||
}
|
||||
else if (item->subtype() == EFI_SECTION_GUID_DEFINED) {
|
||||
else if (model->subtype(index) == EFI_SECTION_GUID_DEFINED) {
|
||||
EFI_GUID_DEFINED_SECTION* guidDefinedHeader = (EFI_GUID_DEFINED_SECTION*) header.data();
|
||||
// Compress new section body
|
||||
QByteArray compressed;
|
||||
result = compress(reconstructed, item->compression(), compressed);
|
||||
result = compress(reconstructed, model->compression(index), compressed);
|
||||
if (result)
|
||||
return result;
|
||||
// Check for auth status valid attribute
|
||||
@ -2312,9 +2285,9 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
||||
// Replace new section body
|
||||
reconstructed = compressed;
|
||||
}
|
||||
else if (item->compression() != COMPRESSION_ALGORITHM_NONE) {
|
||||
else if (model->compression(index) != COMPRESSION_ALGORITHM_NONE) {
|
||||
msg(tr("reconstruct: incorreclty required compression for section of type %1")
|
||||
.arg(item->subtype()));
|
||||
.arg(model->subtype(index)));
|
||||
return ERR_INVALID_SECTION;
|
||||
}
|
||||
|
||||
@ -2323,7 +2296,7 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
||||
}
|
||||
// Leaf section
|
||||
else
|
||||
reconstructed = item->body();
|
||||
reconstructed = model->body(index);
|
||||
|
||||
// Enqueue reconstructed item
|
||||
queue.enqueue(header.append(reconstructed));
|
||||
@ -2331,7 +2304,7 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
||||
break;
|
||||
|
||||
default:
|
||||
msg(tr("reconstruct: Unknown item type (%1)").arg(item->type()));
|
||||
msg(tr("reconstruct: Unknown item type (%1)").arg(model->type(index)));
|
||||
return ERR_UNKNOWN_ITEM_TYPE;
|
||||
}
|
||||
|
||||
@ -2382,7 +2355,7 @@ UINT8 FfsEngine::growVolume(QByteArray & header, const UINT32 size, UINT32 & new
|
||||
// Search routines
|
||||
UINT8 FfsEngine::findHexPattern(const QByteArray & pattern, const UINT8 mode)
|
||||
{
|
||||
return findHexPatternIn(treeModel->index(0,0), pattern, mode);
|
||||
return findHexPatternIn(model->index(0,0), pattern, mode);
|
||||
}
|
||||
|
||||
UINT8 FfsEngine::findHexPatternIn(const QModelIndex & index, const QByteArray & pattern, const UINT8 mode)
|
||||
@ -2393,34 +2366,30 @@ UINT8 FfsEngine::findHexPatternIn(const QModelIndex & index, const QByteArray &
|
||||
if (!index.isValid())
|
||||
return ERR_SUCCESS;
|
||||
|
||||
TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
|
||||
if (item == rootItem)
|
||||
return ERR_SUCCESS;
|
||||
|
||||
bool hasChildren = (item->childCount() > 0);
|
||||
for (int i = 0; i < item->childCount(); i++) {
|
||||
bool hasChildren = (model->rowCount(index) > 0);
|
||||
for (int i = 0; i < model->rowCount(index); i++) {
|
||||
findHexPatternIn(index.child(i, index.column()), pattern, mode);
|
||||
}
|
||||
|
||||
QByteArray data;
|
||||
if (hasChildren) {
|
||||
if(mode != SEARCH_MODE_BODY)
|
||||
data = item->header();
|
||||
data = model->header(index);
|
||||
}
|
||||
else {
|
||||
if (mode == SEARCH_MODE_HEADER)
|
||||
data.append(item->header()).append(item->tail());
|
||||
data.append(model->header(index)).append(model->tail(index));
|
||||
else if (mode == SEARCH_MODE_BODY)
|
||||
data.append(item->body());
|
||||
data.append(model->body(index));
|
||||
else
|
||||
data.append(item->header()).append(item->body()).append(item->tail());
|
||||
data.append(model->header(index)).append(model->body(index)).append(model->tail(index));
|
||||
}
|
||||
|
||||
int offset = -1;
|
||||
while ((offset = data.indexOf(pattern, offset + 1)) >= 0) {
|
||||
msg(tr("Hex pattern \"%1\" found in %2 at offset %3")
|
||||
.arg(QString(pattern.toHex()))
|
||||
.arg(item->data(0).toString())
|
||||
.arg(model->nameString(index))
|
||||
.arg(offset, 8, 16, QChar('0')),
|
||||
index);
|
||||
}
|
||||
@ -2430,7 +2399,7 @@ UINT8 FfsEngine::findHexPatternIn(const QModelIndex & index, const QByteArray &
|
||||
|
||||
UINT8 FfsEngine::findTextPattern(const QString & pattern, const bool unicode, const Qt::CaseSensitivity caseSensitive)
|
||||
{
|
||||
return findTextPatternIn(treeModel->index(0,0), pattern, unicode, caseSensitive);
|
||||
return findTextPatternIn(model->index(0,0), pattern, unicode, caseSensitive);
|
||||
}
|
||||
|
||||
UINT8 FfsEngine::findTextPatternIn(const QModelIndex & index, const QString & pattern, const bool unicode, const Qt::CaseSensitivity caseSensitive)
|
||||
@ -2441,12 +2410,8 @@ UINT8 FfsEngine::findTextPatternIn(const QModelIndex & index, const QString & pa
|
||||
if (!index.isValid())
|
||||
return ERR_SUCCESS;
|
||||
|
||||
TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
|
||||
if (item == rootItem)
|
||||
return ERR_SUCCESS;
|
||||
|
||||
bool hasChildren = (item->childCount() > 0);
|
||||
for (int i = 0; i < item->childCount(); i++) {
|
||||
bool hasChildren = (model->rowCount(index) > 0);
|
||||
for (int i = 0; i < model->rowCount(index); i++) {
|
||||
findTextPatternIn(index.child(i, index.column()), pattern, unicode, caseSensitive);
|
||||
}
|
||||
|
||||
@ -2455,16 +2420,16 @@ UINT8 FfsEngine::findTextPatternIn(const QModelIndex & index, const QString & pa
|
||||
|
||||
QString data;
|
||||
if (unicode)
|
||||
data = QString::fromUtf16((const ushort*) item->body().data(), item->body().length()/2);
|
||||
data = QString::fromUtf16((const ushort*) model->body(index).data(), model->body(index).length()/2);
|
||||
else
|
||||
data = QString::fromLatin1((const char*) item->body().data(), item->body().length());
|
||||
data = QString::fromLatin1((const char*) model->body(index).data(), model->body(index).length());
|
||||
|
||||
int offset = -1;
|
||||
while ((offset = data.indexOf(pattern, offset + 1, caseSensitive)) >= 0) {
|
||||
msg(tr("%1 text pattern \"%2\" found in %3 at offset %4")
|
||||
.arg(unicode ? "Unicode" : "ASCII")
|
||||
.arg(pattern)
|
||||
.arg(item->data(0).toString())
|
||||
.arg(model->nameString(index))
|
||||
.arg(unicode ? offset*2 : offset, 8, 16, QChar('0')),
|
||||
index);
|
||||
}
|
||||
|
@ -19,7 +19,6 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#include <QQueue>
|
||||
|
||||
#include "basetypes.h"
|
||||
#include "treeitem.h"
|
||||
#include "treemodel.h"
|
||||
#include "messagelistitem.h"
|
||||
|
||||
@ -35,7 +34,7 @@ public:
|
||||
~FfsEngine(void);
|
||||
|
||||
// Returns model for Qt view classes
|
||||
TreeModel* model() const;
|
||||
TreeModel* treeModel() const;
|
||||
|
||||
// Returns message items queue
|
||||
QQueue<MessageListItem> messages() const;
|
||||
@ -88,15 +87,13 @@ public:
|
||||
UINT8 findTextPatternIn(const QModelIndex & index, const QString & pattern, const bool unicode, const Qt::CaseSensitivity caseSensitive);
|
||||
|
||||
private:
|
||||
TreeItem *rootItem;
|
||||
TreeModel *treeModel;
|
||||
TreeModel *model;
|
||||
|
||||
// Message helper
|
||||
QQueue<MessageListItem> messageItems;
|
||||
void msg(const QString & message, const QModelIndex index = QModelIndex());
|
||||
|
||||
// Internal operations
|
||||
QModelIndex findParentOfType(UINT8 type, const QModelIndex & index) const;
|
||||
bool hasIntersection(const UINT32 begin1, const UINT32 end1, const UINT32 begin2, const UINT32 end2);
|
||||
};
|
||||
|
||||
|
59
treeitem.cpp
59
treeitem.cpp
@ -19,21 +19,21 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
QString itemTypeToQString(const UINT8 type)
|
||||
{
|
||||
switch (type) {
|
||||
case TreeItem::Root:
|
||||
case Root:
|
||||
return QObject::tr("Root");
|
||||
case TreeItem::Image:
|
||||
case Image:
|
||||
return QObject::tr("Image");
|
||||
case TreeItem::Capsule:
|
||||
case Capsule:
|
||||
return QObject::tr("Capsule");
|
||||
case TreeItem::Region:
|
||||
case Region:
|
||||
return QObject::tr("Region");
|
||||
case TreeItem::Volume:
|
||||
case Volume:
|
||||
return QObject::tr("Volume");
|
||||
case TreeItem::Padding:
|
||||
case Padding:
|
||||
return QObject::tr("Padding");
|
||||
case TreeItem::File:
|
||||
case File:
|
||||
return QObject::tr("File");
|
||||
case TreeItem::Section:
|
||||
case Section:
|
||||
return QObject::tr("Section");
|
||||
default:
|
||||
return QObject::tr("Unknown");
|
||||
@ -43,29 +43,29 @@ QString itemTypeToQString(const UINT8 type)
|
||||
QString itemSubtypeToQString(const UINT8 type, const UINT8 subtype)
|
||||
{
|
||||
switch (type) {
|
||||
case TreeItem::Root:
|
||||
case TreeItem::Image:
|
||||
if (subtype == TreeItem::IntelImage)
|
||||
case Root:
|
||||
case Image:
|
||||
if (subtype == IntelImage)
|
||||
return QObject::tr("Intel");
|
||||
else if (subtype == TreeItem::BiosImage)
|
||||
else if (subtype == BiosImage)
|
||||
return QObject::tr("BIOS");
|
||||
else
|
||||
return QObject::tr("Unknown");
|
||||
case TreeItem::Padding:
|
||||
case TreeItem::Volume:
|
||||
case Padding:
|
||||
case Volume:
|
||||
return "";
|
||||
case TreeItem::Capsule:
|
||||
if (subtype == TreeItem::AptioCapsule)
|
||||
case Capsule:
|
||||
if (subtype == AptioCapsule)
|
||||
return QObject::tr("Aptio extended");
|
||||
else if (subtype == TreeItem::UefiCapsule)
|
||||
else if (subtype == UefiCapsule)
|
||||
return QObject::tr("UEFI 2.0");
|
||||
else
|
||||
return QObject::tr("Unknown");
|
||||
case TreeItem::Region:
|
||||
case Region:
|
||||
return regionTypeToQString(subtype);
|
||||
case TreeItem::File:
|
||||
case File:
|
||||
return fileTypeToQString(subtype);
|
||||
case TreeItem::Section:
|
||||
case Section:
|
||||
return sectionTypeToQString(subtype);
|
||||
default:
|
||||
return QObject::tr("Unknown");
|
||||
@ -172,15 +172,15 @@ QVariant TreeItem::data(int column) const
|
||||
case 0: //Name
|
||||
return itemName;
|
||||
case 1: //Action
|
||||
if (itemAction == TreeItem::Create)
|
||||
if (itemAction == Create)
|
||||
return QObject::tr("Create");
|
||||
if (itemAction == TreeItem::Insert)
|
||||
if (itemAction == Insert)
|
||||
return QObject::tr("Insert");
|
||||
if (itemAction == TreeItem::Replace)
|
||||
if (itemAction == Replace)
|
||||
return QObject::tr("Replace");
|
||||
if (itemAction == TreeItem::Remove)
|
||||
if (itemAction == Remove)
|
||||
return QObject::tr("Remove");
|
||||
if (itemAction == TreeItem::Rebuild)
|
||||
if (itemAction == Rebuild)
|
||||
return QObject::tr("Rebuild");
|
||||
return QVariant();
|
||||
case 2: //Type
|
||||
@ -287,12 +287,13 @@ void TreeItem::setAction(const UINT8 action)
|
||||
itemAction = action;
|
||||
|
||||
// On insert action, set insert action for children
|
||||
if (action == TreeItem::Insert)
|
||||
if (action == Insert)
|
||||
for(int i = 0; i < childCount(); i++)
|
||||
child(i)->setAction(TreeItem::Insert);
|
||||
child(i)->setAction(Insert);
|
||||
|
||||
// Set rebuild action for parent, if it has no action now
|
||||
if (parentItem && parentItem->type() != TreeItem::Root && parentItem->action() == TreeItem::NoAction)
|
||||
parentItem->setAction(TreeItem::Rebuild);
|
||||
if (parentItem && parentItem->type() != Root
|
||||
&& parentItem->action() == NoAction)
|
||||
parentItem->setAction(Rebuild);
|
||||
}
|
||||
|
||||
|
45
treeitem.h
45
treeitem.h
@ -28,55 +28,10 @@ extern QString compressionTypeToQString(UINT8 algorithm);
|
||||
class TreeItem
|
||||
{
|
||||
public:
|
||||
// Action types
|
||||
enum ActionTypes {
|
||||
NoAction = 50,
|
||||
Create,
|
||||
Insert,
|
||||
Replace,
|
||||
Remove,
|
||||
Rebuild
|
||||
};
|
||||
|
||||
// Item types
|
||||
enum ItemTypes {
|
||||
Root = 60,
|
||||
Capsule,
|
||||
Image,
|
||||
Region,
|
||||
Padding,
|
||||
Volume,
|
||||
File,
|
||||
Section
|
||||
};
|
||||
|
||||
// Image subtypes
|
||||
enum ImageSubtypes{
|
||||
IntelImage = 70,
|
||||
BiosImage
|
||||
};
|
||||
|
||||
// Capsule subtypes
|
||||
enum CapsuleSubtypes {
|
||||
AptioCapsule = 80,
|
||||
UefiCapsule
|
||||
};
|
||||
|
||||
// Region subtypes
|
||||
enum RegionSubtypes {
|
||||
DescriptorRegion = 90,
|
||||
GbeRegion,
|
||||
MeRegion,
|
||||
BiosRegion,
|
||||
PdrRegion
|
||||
};
|
||||
|
||||
// Constructor
|
||||
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 QByteArray & header = QByteArray(), const QByteArray & body = QByteArray(), const QByteArray & tail = QByteArray(),
|
||||
TreeItem *parent = 0);
|
||||
// Destructor
|
||||
~TreeItem();
|
||||
|
||||
// Operations with items
|
||||
|
204
treemodel.cpp
204
treemodel.cpp
@ -14,14 +14,15 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#include "treeitem.h"
|
||||
#include "treemodel.h"
|
||||
|
||||
TreeModel::TreeModel(TreeItem *root, QObject *parent)
|
||||
TreeModel::TreeModel(QObject *parent)
|
||||
: QAbstractItemModel(parent)
|
||||
{
|
||||
rootItem = root;
|
||||
rootItem = new TreeItem(Root);
|
||||
}
|
||||
|
||||
TreeModel::~TreeModel()
|
||||
{
|
||||
delete rootItem;
|
||||
}
|
||||
|
||||
int TreeModel::columnCount(const QModelIndex &parent) const
|
||||
@ -117,7 +118,6 @@ QModelIndex TreeModel::parent(const QModelIndex &index) const
|
||||
return createIndex(parentItem->row(), 0, parentItem);
|
||||
}
|
||||
|
||||
|
||||
int TreeModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
TreeItem *parentItem;
|
||||
@ -132,60 +132,210 @@ int TreeModel::rowCount(const QModelIndex &parent) const
|
||||
return parentItem->childCount();
|
||||
}
|
||||
|
||||
UINT8 TreeModel::setItemName(const QString &data, const QModelIndex &index)
|
||||
UINT8 TreeModel::type(const QModelIndex &index) const
|
||||
{
|
||||
if(!index.isValid())
|
||||
return ERR_INVALID_PARAMETER;
|
||||
return 0;
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
return item->type();
|
||||
}
|
||||
|
||||
UINT8 TreeModel::subtype(const QModelIndex &index) const
|
||||
{
|
||||
if(!index.isValid())
|
||||
return 0;
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
return item->subtype();
|
||||
}
|
||||
|
||||
QByteArray TreeModel::header(const QModelIndex &index) const
|
||||
{
|
||||
if(!index.isValid())
|
||||
return QByteArray();
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
return item->header();
|
||||
}
|
||||
|
||||
bool TreeModel::hasEmptyHeader(const QModelIndex &index) const
|
||||
{
|
||||
if(!index.isValid())
|
||||
return true;
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
return item->hasEmptyHeader();
|
||||
}
|
||||
|
||||
QByteArray TreeModel::body(const QModelIndex &index) const
|
||||
{
|
||||
if(!index.isValid())
|
||||
return QByteArray();
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
return item->body();
|
||||
}
|
||||
|
||||
bool TreeModel::hasEmptyBody(const QModelIndex &index) const
|
||||
{
|
||||
if(!index.isValid())
|
||||
return true;
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
return item->hasEmptyBody();
|
||||
}
|
||||
|
||||
QByteArray TreeModel::tail(const QModelIndex &index) const
|
||||
{
|
||||
if(!index.isValid())
|
||||
return QByteArray();
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
return item->tail();
|
||||
}
|
||||
|
||||
bool TreeModel::hasEmptyTail(const QModelIndex &index) const
|
||||
{
|
||||
if(!index.isValid())
|
||||
return true;
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
return item->hasEmptyTail();
|
||||
}
|
||||
|
||||
QString TreeModel::info(const QModelIndex &index) const
|
||||
{
|
||||
if(!index.isValid())
|
||||
return QString();
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
return item->info();
|
||||
}
|
||||
|
||||
UINT8 TreeModel::action(const QModelIndex &index) const
|
||||
{
|
||||
if(!index.isValid())
|
||||
return NoAction;
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
return item->action();
|
||||
}
|
||||
|
||||
UINT8 TreeModel::compression(const QModelIndex &index) const
|
||||
{
|
||||
if(!index.isValid())
|
||||
return COMPRESSION_ALGORITHM_UNKNOWN;
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
return item->compression();
|
||||
}
|
||||
|
||||
void TreeModel::setNameString(const QModelIndex &index, const QString &data)
|
||||
{
|
||||
if(!index.isValid())
|
||||
return;
|
||||
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
item->setName(data);
|
||||
emit dataChanged(index, index);
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
UINT8 TreeModel::setItemText(const QString &data, const QModelIndex &index)
|
||||
void TreeModel::setTypeString(const QModelIndex &index, const QString &data)
|
||||
{
|
||||
if(!index.isValid())
|
||||
return ERR_INVALID_PARAMETER;
|
||||
return;
|
||||
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
item->setTypeName(data);
|
||||
emit dataChanged(index, index);
|
||||
}
|
||||
|
||||
void TreeModel::setSubtypeString(const QModelIndex &index, const QString &data)
|
||||
{
|
||||
if(!index.isValid())
|
||||
return;
|
||||
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
item->setSubtypeName(data);
|
||||
emit dataChanged(index, index);
|
||||
}
|
||||
|
||||
void TreeModel::setTextString(const QModelIndex &index, const QString &data)
|
||||
{
|
||||
if(!index.isValid())
|
||||
return;
|
||||
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
item->setText(data);
|
||||
emit dataChanged(index, index);
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
UINT8 TreeModel::setItemAction(const UINT8 action, const QModelIndex &index)
|
||||
QString TreeModel::nameString(const QModelIndex &index) const
|
||||
{
|
||||
if(!index.isValid())
|
||||
return ERR_INVALID_PARAMETER;
|
||||
return QString();
|
||||
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
return item->data(0).toString();
|
||||
}
|
||||
|
||||
QString TreeModel::actionString(const QModelIndex &index) const
|
||||
{
|
||||
if(!index.isValid())
|
||||
return QString();
|
||||
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
return item->data(1).toString();}
|
||||
|
||||
QString TreeModel::typeString(const QModelIndex &index) const
|
||||
{
|
||||
if(!index.isValid())
|
||||
return QString();
|
||||
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
return item->data(2).toString();
|
||||
}
|
||||
|
||||
QString TreeModel::subtypeString(const QModelIndex &index) const
|
||||
{
|
||||
if(!index.isValid())
|
||||
return QString();
|
||||
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
return item->data(3).toString();
|
||||
}
|
||||
|
||||
QString TreeModel::textString(const QModelIndex &index) const
|
||||
{
|
||||
if(!index.isValid())
|
||||
return QString();
|
||||
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
return item->data(4).toString();
|
||||
}
|
||||
|
||||
|
||||
void TreeModel::setAction(const QModelIndex &index, const UINT8 action)
|
||||
{
|
||||
if(!index.isValid())
|
||||
return;
|
||||
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
item->setAction(action);
|
||||
emit dataChanged(this->index(0,0), index);
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
QModelIndex TreeModel::addItem(const UINT8 type, const UINT8 subtype, const UINT8 compression,
|
||||
const QString & name, const QString & text, const QString & info,
|
||||
const QByteArray & header, const QByteArray & body, const QByteArray & tail,
|
||||
const QModelIndex & index, const UINT8 mode)
|
||||
const QModelIndex & parent, const UINT8 mode)
|
||||
{
|
||||
TreeItem *item = 0;
|
||||
TreeItem *parentItem = 0;
|
||||
int parentColumn = 0;
|
||||
|
||||
if (!index.isValid())
|
||||
if (!parent.isValid())
|
||||
parentItem = rootItem;
|
||||
else
|
||||
{
|
||||
if (mode == CREATE_MODE_BEFORE || mode == CREATE_MODE_AFTER) {
|
||||
item = static_cast<TreeItem*>(index.internalPointer());
|
||||
item = static_cast<TreeItem*>(parent.internalPointer());
|
||||
parentItem = item->parent();
|
||||
parentColumn = index.parent().column();
|
||||
parentColumn = parent.parent().column();
|
||||
}
|
||||
else {
|
||||
parentItem = static_cast<TreeItem*>(index.internalPointer());
|
||||
parentColumn = index.column();
|
||||
parentItem = static_cast<TreeItem*>(parent.internalPointer());
|
||||
parentColumn = parent.column();
|
||||
}
|
||||
}
|
||||
|
||||
@ -213,3 +363,21 @@ QModelIndex TreeModel::addItem(const UINT8 type, const UINT8 subtype, const UINT
|
||||
|
||||
return createIndex(newItem->row(), parentColumn, newItem);
|
||||
}
|
||||
|
||||
QModelIndex TreeModel::findParentOfType(const QModelIndex& index, UINT8 type) const
|
||||
{
|
||||
if(!index.isValid())
|
||||
return QModelIndex();
|
||||
|
||||
TreeItem *item;
|
||||
QModelIndex parent = index;
|
||||
|
||||
for(item = static_cast<TreeItem*>(parent.internalPointer());
|
||||
item != NULL && item != rootItem && item->type() != type;
|
||||
item = static_cast<TreeItem*>(parent.internalPointer()))
|
||||
parent = parent.parent();
|
||||
if (item != NULL && item != rootItem)
|
||||
return parent;
|
||||
|
||||
return QModelIndex();
|
||||
}
|
||||
|
32
treemodel.h
32
treemodel.h
@ -28,7 +28,7 @@ class TreeModel : public QAbstractItemModel
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TreeModel(TreeItem *root, QObject *parent = 0);
|
||||
TreeModel(QObject *parent = 0);
|
||||
~TreeModel();
|
||||
|
||||
QVariant data(const QModelIndex &index, int role) const;
|
||||
@ -41,14 +41,36 @@ public:
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
|
||||
UINT8 setItemName(const QString &data, const QModelIndex &index);
|
||||
UINT8 setItemText(const QString &data, const QModelIndex &index);
|
||||
UINT8 setItemAction(const UINT8 action, const QModelIndex &index);
|
||||
QString nameString(const QModelIndex &index) const;
|
||||
QString actionString(const QModelIndex &index) const;
|
||||
QString typeString(const QModelIndex &index) const;
|
||||
QString subtypeString(const QModelIndex &index) const;
|
||||
QString textString(const QModelIndex &index) const;
|
||||
|
||||
void setAction(const QModelIndex &index, const UINT8 action);
|
||||
void setTypeString(const QModelIndex &index, const QString &text);
|
||||
void setSubtypeString(const QModelIndex &index, const QString &text);
|
||||
void setNameString(const QModelIndex &index, const QString &text);
|
||||
void setTextString(const QModelIndex &index, const QString &text);
|
||||
|
||||
UINT8 type(const QModelIndex &index) const;
|
||||
UINT8 subtype(const QModelIndex &index) const;
|
||||
QByteArray header(const QModelIndex &index) const;
|
||||
bool hasEmptyHeader(const QModelIndex &index) const;
|
||||
QByteArray body(const QModelIndex &index) const;
|
||||
bool hasEmptyBody(const QModelIndex &index) const;
|
||||
QByteArray tail(const QModelIndex &index) const;
|
||||
bool hasEmptyTail(const QModelIndex &index) const;
|
||||
QString info(const QModelIndex &index) const;
|
||||
UINT8 action(const QModelIndex &index) const;
|
||||
UINT8 compression(const QModelIndex &index) const;
|
||||
|
||||
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 QByteArray & header = QByteArray(), const QByteArray & body = QByteArray(), const QByteArray & tail = QByteArray(),
|
||||
const QModelIndex & index = QModelIndex(), const UINT8 mode = CREATE_MODE_APPEND);
|
||||
const QModelIndex & parent = QModelIndex(), const UINT8 mode = CREATE_MODE_APPEND);
|
||||
|
||||
QModelIndex findParentOfType(const QModelIndex & index, UINT8 type) const;
|
||||
|
||||
private:
|
||||
TreeItem *rootItem;
|
||||
|
124
uefitool.cpp
124
uefitool.cpp
@ -78,7 +78,7 @@ void UEFITool::init()
|
||||
if (ffsEngine)
|
||||
delete ffsEngine;
|
||||
ffsEngine = new FfsEngine(this);
|
||||
ui->structureTreeView->setModel(ffsEngine->model());
|
||||
ui->structureTreeView->setModel(ffsEngine->treeModel());
|
||||
|
||||
// Connect
|
||||
connect(ui->structureTreeView->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
|
||||
@ -91,32 +91,32 @@ void UEFITool::populateUi(const QModelIndex ¤t)
|
||||
if (!current.isValid())
|
||||
return;
|
||||
|
||||
TreeItem* item = static_cast<TreeItem*>(current.internalPointer());
|
||||
UINT8 type = item->type();
|
||||
UINT8 subtype = item->subtype();
|
||||
TreeModel* model = ffsEngine->treeModel();
|
||||
UINT8 type = model->type(current);
|
||||
UINT8 subtype = model->subtype(current);
|
||||
|
||||
// Set info text
|
||||
ui->infoEdit->setPlainText(item->info());
|
||||
ui->infoEdit->setPlainText(model->info(current));
|
||||
|
||||
// Enable menus
|
||||
ui->menuCapsuleActions->setEnabled(type == TreeItem::Capsule);
|
||||
ui->menuImageActions->setEnabled(type == TreeItem::Image);
|
||||
ui->menuRegionActions->setEnabled(type == TreeItem::Region);
|
||||
ui->menuPaddingActions->setEnabled(type == TreeItem::Padding);
|
||||
ui->menuVolumeActions->setEnabled(type == TreeItem::Volume);
|
||||
ui->menuFileActions->setEnabled(type == TreeItem::File);
|
||||
ui->menuSectionActions->setEnabled(type == TreeItem::Section);
|
||||
ui->menuCapsuleActions->setEnabled(type == Capsule);
|
||||
ui->menuImageActions->setEnabled(type == Image);
|
||||
ui->menuRegionActions->setEnabled(type == Region);
|
||||
ui->menuPaddingActions->setEnabled(type == Padding);
|
||||
ui->menuVolumeActions->setEnabled(type == Volume);
|
||||
ui->menuFileActions->setEnabled(type == File);
|
||||
ui->menuSectionActions->setEnabled(type == Section);
|
||||
|
||||
// Enable actions
|
||||
ui->actionExtract->setDisabled(item->hasEmptyHeader() && item->hasEmptyBody() && item->hasEmptyTail());
|
||||
ui->actionRebuild->setDisabled(item->hasEmptyHeader() && item->hasEmptyBody() && item->hasEmptyTail());
|
||||
ui->actionExtractBody->setDisabled(item->hasEmptyHeader());
|
||||
ui->actionRemove->setEnabled(type == TreeItem::Volume || type == TreeItem::File || type == TreeItem::Section);
|
||||
ui->actionInsertInto->setEnabled(type == TreeItem::Volume || (type == TreeItem::File && subtype != EFI_FV_FILETYPE_ALL && subtype != EFI_FV_FILETYPE_RAW && subtype != EFI_FV_FILETYPE_PAD));
|
||||
ui->actionInsertBefore->setEnabled(type == TreeItem::File || type == TreeItem::Section);
|
||||
ui->actionInsertAfter->setEnabled(type == TreeItem::File || type == TreeItem::Section);
|
||||
ui->actionReplace->setEnabled(type == TreeItem::File || type == TreeItem::Section);
|
||||
ui->actionReplaceBody->setEnabled(type == TreeItem::File || type == TreeItem::Section);
|
||||
ui->actionExtract->setDisabled(model->hasEmptyHeader(current) && model->hasEmptyBody(current) && model->hasEmptyTail(current));
|
||||
ui->actionRebuild->setDisabled(model->hasEmptyHeader(current) && model->hasEmptyBody(current) && model->hasEmptyTail(current));
|
||||
ui->actionExtractBody->setDisabled(model->hasEmptyHeader(current));
|
||||
ui->actionRemove->setEnabled(type == Volume || type == File || type == Section);
|
||||
ui->actionInsertInto->setEnabled(type == Volume || (type == File && subtype != EFI_FV_FILETYPE_ALL && subtype != EFI_FV_FILETYPE_RAW && subtype != EFI_FV_FILETYPE_PAD));
|
||||
ui->actionInsertBefore->setEnabled(type == File || type == Section);
|
||||
ui->actionInsertAfter->setEnabled(type == File || type == Section);
|
||||
ui->actionReplace->setEnabled(type == File || type == Section);
|
||||
ui->actionReplaceBody->setEnabled(type == File || type == Section);
|
||||
}
|
||||
|
||||
void UEFITool::search()
|
||||
@ -179,25 +179,25 @@ void UEFITool::insert(const UINT8 mode)
|
||||
if (!index.isValid())
|
||||
return;
|
||||
|
||||
TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
|
||||
TreeModel* model = ffsEngine->treeModel();
|
||||
UINT8 type;
|
||||
UINT8 objectType;
|
||||
|
||||
if (mode == CREATE_MODE_BEFORE || mode == CREATE_MODE_AFTER)
|
||||
type = item->parent()->type();
|
||||
type = model->type(index.parent());
|
||||
else
|
||||
type = item->type();
|
||||
type = model->type(index);
|
||||
|
||||
QString path;
|
||||
switch (type) {
|
||||
case TreeItem::Volume:
|
||||
case Volume:
|
||||
path = QFileDialog::getOpenFileName(this, tr("Select FFS file to insert"),".","FFS files (*.ffs *.bin);;All files (*.*)");
|
||||
objectType = TreeItem::File;
|
||||
objectType = File;
|
||||
break;
|
||||
case TreeItem::File:
|
||||
case TreeItem::Section:
|
||||
case File:
|
||||
case Section:
|
||||
path = QFileDialog::getOpenFileName(this, tr("Select section file to insert"),".","Section files (*.sct *.bin);;All files (*.*)");
|
||||
objectType = TreeItem::Section;
|
||||
objectType = Section;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
@ -258,16 +258,16 @@ void UEFITool::replace(const UINT8 mode)
|
||||
if (!index.isValid())
|
||||
return;
|
||||
|
||||
TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
|
||||
TreeModel* model = ffsEngine->treeModel();
|
||||
QString path;
|
||||
if (item->type() == TreeItem::File) {
|
||||
if (model->type(index) == File) {
|
||||
if (mode == REPLACE_MODE_AS_IS) {
|
||||
path = QFileDialog::getOpenFileName(this, tr("Select FFS file to replace selected object"),".","FFS files (*.ffs *.bin);;All files (*.*)");
|
||||
}
|
||||
else if (mode == REPLACE_MODE_BODY) {
|
||||
if (item->subtype() == EFI_FV_FILETYPE_ALL || item->subtype() == EFI_FV_FILETYPE_RAW)
|
||||
if (model->subtype(index) == EFI_FV_FILETYPE_ALL || model->subtype(index) == EFI_FV_FILETYPE_RAW)
|
||||
path = QFileDialog::getOpenFileName(this, tr("Select raw file to replace body"),".","Raw files (*.raw *.bin);;All files (*.*)");
|
||||
else if (item->subtype() == EFI_FV_FILETYPE_PAD) // Pad file body can't be replaced
|
||||
else if (model->subtype(index) == EFI_FV_FILETYPE_PAD) // Pad file body can't be replaced
|
||||
return;
|
||||
else
|
||||
path = QFileDialog::getOpenFileName(this, tr("Select FFS file body to replace body"),".","FFS file body files (*.fbd *.bin);;All files (*.*)");
|
||||
@ -275,16 +275,16 @@ void UEFITool::replace(const UINT8 mode)
|
||||
else
|
||||
return;
|
||||
}
|
||||
else if (item->type() == TreeItem::Section) {
|
||||
else if (model->type(index) == Section) {
|
||||
if (mode == REPLACE_MODE_AS_IS) {
|
||||
path = QFileDialog::getOpenFileName(this, tr("Select section file to replace selected object"),".","Section files (*.sec *.bin);;All files (*.*)");
|
||||
}
|
||||
else if (mode == REPLACE_MODE_BODY) {
|
||||
if (item->subtype() == EFI_SECTION_COMPRESSION || item->subtype() == EFI_SECTION_GUID_DEFINED || item->subtype() == EFI_SECTION_DISPOSABLE)
|
||||
if (model->subtype(index) == EFI_SECTION_COMPRESSION || model->subtype(index) == EFI_SECTION_GUID_DEFINED || model->subtype(index) == EFI_SECTION_DISPOSABLE)
|
||||
path = QFileDialog::getOpenFileName(this, tr("Select FFS file body file to replace body"),".","FFS file body files (*.fbd *.bin);;All files (*.*)");
|
||||
else if (item->subtype() == EFI_SECTION_FIRMWARE_VOLUME_IMAGE)
|
||||
else if (model->subtype(index) == EFI_SECTION_FIRMWARE_VOLUME_IMAGE)
|
||||
path = QFileDialog::getOpenFileName(this, tr("Select volume file to replace body"),".","Volume files (*.vol *.bin);;All files (*.*)");
|
||||
else if (item->subtype() == EFI_SECTION_RAW)
|
||||
else if (model->subtype(index) == EFI_SECTION_RAW)
|
||||
path = QFileDialog::getOpenFileName(this, tr("Select raw file to replace body"),".","Raw files (*.raw *.bin);;All files (*.*)");
|
||||
else
|
||||
path = QFileDialog::getOpenFileName(this, tr("Select file to replace body"),".","Binary files (*.bin);;All files (*.*)");
|
||||
@ -335,31 +335,31 @@ void UEFITool::extract(const UINT8 mode)
|
||||
if (!index.isValid())
|
||||
return;
|
||||
|
||||
TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
|
||||
UINT8 type = item->type();
|
||||
TreeModel* model = ffsEngine->treeModel();
|
||||
UINT8 type = model->type(index);
|
||||
|
||||
QString path;
|
||||
if (mode == EXTRACT_MODE_AS_IS) {
|
||||
switch (type) {
|
||||
case TreeItem::Capsule:
|
||||
case Capsule:
|
||||
path = QFileDialog::getSaveFileName(this, tr("Save capsule to file"),".","Capsule files (*.cap *.bin);;All files (*.*)");
|
||||
break;
|
||||
case TreeItem::Image:
|
||||
case Image:
|
||||
path = QFileDialog::getSaveFileName(this, tr("Save image to file"),".","Image files (*.rom *.bin);;All files (*.*)");
|
||||
break;
|
||||
case TreeItem::Region:
|
||||
case Region:
|
||||
path = QFileDialog::getSaveFileName(this, tr("Save region to file"),".","Region files (*.rgn *.bin);;All files (*.*)");
|
||||
break;
|
||||
case TreeItem::Padding:
|
||||
case Padding:
|
||||
path = QFileDialog::getSaveFileName(this, tr("Save padding to file"),".","Padding files (*.pad *.bin);;All files (*.*)");
|
||||
break;
|
||||
case TreeItem::Volume:
|
||||
case Volume:
|
||||
path = QFileDialog::getSaveFileName(this, tr("Save volume to file"),".","Volume files (*.vol *.bin);;All files (*.*)");
|
||||
break;
|
||||
case TreeItem::File:
|
||||
case File:
|
||||
path = QFileDialog::getSaveFileName(this, tr("Save FFS file to file"),".","FFS files (*.ffs *.bin);;All files (*.*)");
|
||||
break;
|
||||
case TreeItem::Section:
|
||||
case Section:
|
||||
path = QFileDialog::getSaveFileName(this, tr("Save section file to file"),".","Section files (*.sct *.bin);;All files (*.*)");
|
||||
break;
|
||||
default:
|
||||
@ -368,22 +368,22 @@ void UEFITool::extract(const UINT8 mode)
|
||||
}
|
||||
else if (mode == EXTRACT_MODE_BODY) {
|
||||
switch (type) {
|
||||
case TreeItem::Capsule:
|
||||
case Capsule:
|
||||
path = QFileDialog::getSaveFileName(this, tr("Save capsule body to image file"),".","Image files (*.rom *.bin);;All files (*.*)");
|
||||
break;
|
||||
case TreeItem::File: {
|
||||
if (item->subtype() == EFI_FV_FILETYPE_ALL || item->subtype() == EFI_FV_FILETYPE_RAW)
|
||||
case File: {
|
||||
if (model->subtype(index) == EFI_FV_FILETYPE_ALL || model->subtype(index) == EFI_FV_FILETYPE_RAW)
|
||||
path = QFileDialog::getSaveFileName(this, tr("Save FFS file body to raw file"),".","Raw files (*.raw *.bin);;All files (*.*)");
|
||||
else
|
||||
path = QFileDialog::getSaveFileName(this, tr("Save FFS file body to file"),".","FFS file body files (*.fbd *.bin);;All files (*.*)");
|
||||
}
|
||||
break;
|
||||
case TreeItem::Section: {
|
||||
if (item->subtype() == EFI_SECTION_COMPRESSION || item->subtype() == EFI_SECTION_GUID_DEFINED || item->subtype() == EFI_SECTION_DISPOSABLE)
|
||||
case Section: {
|
||||
if (model->subtype(index) == EFI_SECTION_COMPRESSION || model->subtype(index) == EFI_SECTION_GUID_DEFINED || model->subtype(index) == EFI_SECTION_DISPOSABLE)
|
||||
path = QFileDialog::getSaveFileName(this, tr("Save encapsulated section body to FFS body file"),".","FFS file body files (*.fbd *.bin);;All files (*.*)");
|
||||
else if (item->subtype() == EFI_SECTION_FIRMWARE_VOLUME_IMAGE)
|
||||
else if (model->subtype(index) == EFI_SECTION_FIRMWARE_VOLUME_IMAGE)
|
||||
path = QFileDialog::getSaveFileName(this, tr("Save section body to volume file"),".","Volume files (*.vol *.bin);;All files (*.*)");
|
||||
else if (item->subtype() == EFI_SECTION_RAW)
|
||||
else if (model->subtype(index) == EFI_SECTION_RAW)
|
||||
path = QFileDialog::getSaveFileName(this, tr("Save section body to raw file"),".","Raw files (*.raw *.bin);;All files (*.*)");
|
||||
else
|
||||
path = QFileDialog::getSaveFileName(this, tr("Save section body to file"),".","Binary files (*.bin);;All files (*.*)");
|
||||
@ -562,28 +562,28 @@ void UEFITool::contextMenuEvent(QContextMenuEvent* event)
|
||||
if(!index.isValid())
|
||||
return;
|
||||
|
||||
TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
|
||||
switch(item->type())
|
||||
TreeModel* model = ffsEngine->treeModel();
|
||||
switch(model->type(index))
|
||||
{
|
||||
case TreeItem::Capsule:
|
||||
case Capsule:
|
||||
ui->menuCapsuleActions->exec(event->globalPos());
|
||||
break;
|
||||
case TreeItem::Image:
|
||||
case Image:
|
||||
ui->menuImageActions->exec(event->globalPos());
|
||||
break;
|
||||
case TreeItem::Region:
|
||||
case Region:
|
||||
ui->menuRegionActions->exec(event->globalPos());
|
||||
break;
|
||||
case TreeItem::Padding:
|
||||
case Padding:
|
||||
ui->menuPaddingActions->exec(event->globalPos());
|
||||
break;
|
||||
case TreeItem::Volume:
|
||||
case Volume:
|
||||
ui->menuVolumeActions->exec(event->globalPos());
|
||||
break;
|
||||
case TreeItem::File:
|
||||
case File:
|
||||
ui->menuFileActions->exec(event->globalPos());
|
||||
break;
|
||||
case TreeItem::Section:
|
||||
case Section:
|
||||
ui->menuSectionActions->exec(event->globalPos());
|
||||
break;
|
||||
}
|
||||
|
@ -20,7 +20,7 @@
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>UEFITool 0.13.0</string>
|
||||
<string>UEFITool 0.14.0</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralWidget">
|
||||
<property name="sizePolicy">
|
||||
|
Loading…
Reference in New Issue
Block a user