mirror of
https://github.com/LongSoft/UEFITool.git
synced 2024-11-25 01:18:22 +08:00
Version 0.12.0
- bug with wrong file tail creation solved - "Replace" and "Replace body" actions added - "Change compression" menu and actions removed, will be returned later - minor refactoring and bugfixes done
This commit is contained in:
parent
5e1b476c86
commit
862fc6b242
38
basetypes.h
38
basetypes.h
@ -45,16 +45,7 @@ typedef uint16_t CHAR16;
|
|||||||
#define NULL ((VOID *) 0)
|
#define NULL ((VOID *) 0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if _MSC_EXTENSIONS
|
#define EFIAPI
|
||||||
//
|
|
||||||
// Microsoft* compiler requires _EFIAPI usage, __cdecl is Microsoft* specific C.
|
|
||||||
//
|
|
||||||
#define EFIAPI __cdecl
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if __GNUC__
|
|
||||||
#define EFIAPI __attribute__((cdecl))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define ERR_SUCCESS 0
|
#define ERR_SUCCESS 0
|
||||||
#define ERR_INVALID_PARAMETER 1
|
#define ERR_INVALID_PARAMETER 1
|
||||||
@ -95,16 +86,19 @@ 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
|
// Item create modes
|
||||||
#define EXTRACT_MODE_AS_IS 0
|
#define CREATE_MODE_APPEND 0
|
||||||
#define EXTRACT_MODE_BODY_ONLY 1
|
#define CREATE_MODE_PREPEND 1
|
||||||
#define EXTRACT_MODE_UNCOMPRESSED 2
|
#define CREATE_MODE_BEFORE 2
|
||||||
|
#define CREATE_MODE_AFTER 3
|
||||||
|
|
||||||
// Item insert modes
|
// Item extract modes
|
||||||
#define INSERT_MODE_APPEND 0
|
#define EXTRACT_MODE_AS_IS 0
|
||||||
#define INSERT_MODE_PREPEND 1
|
#define EXTRACT_MODE_BODY 1
|
||||||
#define INSERT_MODE_BEFORE 2
|
|
||||||
#define INSERT_MODE_AFTER 3
|
// Item replace modes
|
||||||
|
#define REPLACE_MODE_AS_IS 0
|
||||||
|
#define REPLACE_MODE_BODY 1
|
||||||
|
|
||||||
// Erase polarity types
|
// Erase polarity types
|
||||||
#define ERASE_POLARITY_FALSE 0
|
#define ERASE_POLARITY_FALSE 0
|
||||||
@ -112,9 +106,9 @@ typedef uint16_t CHAR16;
|
|||||||
#define ERASE_POLARITY_UNKNOWN 0xFF
|
#define ERASE_POLARITY_UNKNOWN 0xFF
|
||||||
|
|
||||||
// Search modes
|
// Search modes
|
||||||
#define SEARCH_MODE_HEX 0
|
#define SEARCH_MODE_HEADER 1
|
||||||
#define SEARCH_MODE_ASCII 1
|
#define SEARCH_MODE_BODY 2
|
||||||
#define SEARCH_MODE_UNICODE 2
|
#define SEARCH_MODE_ALL 3
|
||||||
|
|
||||||
// EFI GUID
|
// EFI GUID
|
||||||
typedef struct{
|
typedef struct{
|
||||||
|
10
ffs.h
10
ffs.h
@ -245,7 +245,7 @@ typedef struct {
|
|||||||
// UINT8 Attributes;
|
// UINT8 Attributes;
|
||||||
// UINT8 Size[3];
|
// UINT8 Size[3];
|
||||||
// UINT8 State;
|
// UINT8 State;
|
||||||
// UINT12 ExtendedSize;
|
// UINT32 ExtendedSize;
|
||||||
//} EFI_FFS_FILE_HEADER2;
|
//} EFI_FFS_FILE_HEADER2;
|
||||||
|
|
||||||
// Standard data checksum, used if FFS_ATTRIB_CHECKSUM is clear
|
// Standard data checksum, used if FFS_ATTRIB_CHECKSUM is clear
|
||||||
@ -277,14 +277,12 @@ typedef struct {
|
|||||||
|
|
||||||
// File attributes
|
// File attributes
|
||||||
#define FFS_ATTRIB_RESERVED 0x80 // ErasePolarity value can be obtained from that bit
|
#define FFS_ATTRIB_RESERVED 0x80 // ErasePolarity value can be obtained from that bit
|
||||||
|
#define FFS_ATTRIB_TAIL_PRESENT 0x01
|
||||||
#define FFS_ATTRIB_RECOVERY 0x02
|
#define FFS_ATTRIB_RECOVERY 0x02
|
||||||
|
#define FFS_ATTRIB_FIXED 0x04
|
||||||
#define FFS_ATTRIB_DATA_ALIGNMENT 0x38
|
#define FFS_ATTRIB_DATA_ALIGNMENT 0x38
|
||||||
#define FFS_ATTRIB_CHECKSUM 0x40
|
#define FFS_ATTRIB_CHECKSUM 0x40
|
||||||
// Revision 1
|
//#define FFS_ATTRIB_LARGE_FILE 0x01 //This attribute is removed in new PI 1.3 specification, nice
|
||||||
#define FFS_ATTRIB_TAIL_PRESENT 0x01
|
|
||||||
// Revision 2
|
|
||||||
#define FFS_ATTRIB_LARGE_FILE 0x01
|
|
||||||
#define FFS_ATTRIB_FIXED 0x04
|
|
||||||
|
|
||||||
// FFS alignment table
|
// FFS alignment table
|
||||||
extern const UINT8 ffsAlignmentTable[];
|
extern const UINT8 ffsAlignmentTable[];
|
||||||
|
470
ffsengine.cpp
470
ffsengine.cpp
@ -28,10 +28,6 @@ FfsEngine::FfsEngine(QObject *parent)
|
|||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
{
|
{
|
||||||
rootItem = new TreeItem(TreeItem::Root);
|
rootItem = new TreeItem(TreeItem::Root);
|
||||||
rootItem->setName("Name");
|
|
||||||
rootItem->setTypeName("Type");
|
|
||||||
rootItem->setSubtypeName("Subtype");
|
|
||||||
rootItem->setText("Text");
|
|
||||||
treeModel = new TreeModel(rootItem);
|
treeModel = new TreeModel(rootItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,7 +146,8 @@ UINT8 FfsEngine::parseInputFile(const QByteArray & buffer)
|
|||||||
UINT8 result;
|
UINT8 result;
|
||||||
if (descriptorHeader->Signature == FLASH_DESCRIPTOR_SIGNATURE) {
|
if (descriptorHeader->Signature == FLASH_DESCRIPTOR_SIGNATURE) {
|
||||||
// Parse as Intel image
|
// Parse as Intel image
|
||||||
result = parseIntelImage(flashImage, index);
|
QModelIndex imageIndex;
|
||||||
|
result = parseIntelImage(flashImage, imageIndex, index);
|
||||||
if (result != ERR_INVALID_FLASH_DESCRIPTOR)
|
if (result != ERR_INVALID_FLASH_DESCRIPTOR)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -165,7 +162,7 @@ UINT8 FfsEngine::parseInputFile(const QByteArray & buffer)
|
|||||||
return parseBios(flashImage, index);
|
return parseBios(flashImage, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT8 FfsEngine::parseIntelImage(const QByteArray & flashImage, const QModelIndex & parent)
|
UINT8 FfsEngine::parseIntelImage(const QByteArray & flashImage, QModelIndex & index, const QModelIndex & parent)
|
||||||
{
|
{
|
||||||
FLASH_DESCRIPTOR_MAP* descriptorMap;
|
FLASH_DESCRIPTOR_MAP* descriptorMap;
|
||||||
FLASH_DESCRIPTOR_REGION_SECTION* regionSection;
|
FLASH_DESCRIPTOR_REGION_SECTION* regionSection;
|
||||||
@ -291,7 +288,7 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & flashImage, const QModelInde
|
|||||||
.arg(descriptorMap->NumberOfIccTableEntries);
|
.arg(descriptorMap->NumberOfIccTableEntries);
|
||||||
|
|
||||||
// Add Intel image tree item
|
// Add Intel image tree item
|
||||||
QModelIndex index = treeModel->addItem(TreeItem::Image, TreeItem::IntelImage, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), flashImage, QByteArray(), parent);
|
index = treeModel->addItem(TreeItem::Image, TreeItem::IntelImage, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), flashImage, QByteArray(), parent);
|
||||||
|
|
||||||
// Descriptor
|
// Descriptor
|
||||||
// Get descriptor info
|
// Get descriptor info
|
||||||
@ -329,19 +326,23 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & flashImage, const QModelInde
|
|||||||
for (int i = 0; i < offsets.count(); i++) {
|
for (int i = 0; i < offsets.count(); i++) {
|
||||||
// Parse GbE region
|
// Parse GbE region
|
||||||
if (offsets.at(i) == gbeBegin) {
|
if (offsets.at(i) == gbeBegin) {
|
||||||
result = parseGbeRegion(gbe, index);
|
QModelIndex gbeIndex;
|
||||||
|
result = parseGbeRegion(gbe, gbeIndex, index);
|
||||||
}
|
}
|
||||||
// Parse ME region
|
// Parse ME region
|
||||||
else if (offsets.at(i) == meBegin) {
|
else if (offsets.at(i) == meBegin) {
|
||||||
result = parseMeRegion(me, index);
|
QModelIndex meIndex;
|
||||||
|
result = parseMeRegion(me, meIndex, index);
|
||||||
}
|
}
|
||||||
// Parse BIOS region
|
// Parse BIOS region
|
||||||
else if (offsets.at(i) == biosBegin) {
|
else if (offsets.at(i) == biosBegin) {
|
||||||
result = parseBiosRegion(bios, index);
|
QModelIndex biosIndex;
|
||||||
|
result = parseBiosRegion(bios, biosIndex, index);
|
||||||
}
|
}
|
||||||
// Parse PDR region
|
// Parse PDR region
|
||||||
else if (offsets.at(i) == pdrBegin) {
|
else if (offsets.at(i) == pdrBegin) {
|
||||||
result = parsePdrRegion(pdr, index);
|
QModelIndex pdrIndex;
|
||||||
|
result = parsePdrRegion(pdr, pdrIndex, index);
|
||||||
}
|
}
|
||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
@ -350,7 +351,7 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & flashImage, const QModelInde
|
|||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT8 FfsEngine::parseGbeRegion(const QByteArray & gbe, const QModelIndex & parent)
|
UINT8 FfsEngine::parseGbeRegion(const QByteArray & gbe, QModelIndex & index, const QModelIndex & parent)
|
||||||
{
|
{
|
||||||
if (gbe.isEmpty())
|
if (gbe.isEmpty())
|
||||||
return ERR_EMPTY_REGION;
|
return ERR_EMPTY_REGION;
|
||||||
@ -371,12 +372,12 @@ 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, QByteArray(), parent);
|
index = treeModel->addItem(TreeItem::Region, TreeItem::GbeRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), gbe, QByteArray(), parent);
|
||||||
|
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT8 FfsEngine::parseMeRegion(const QByteArray & me, const QModelIndex & parent)
|
UINT8 FfsEngine::parseMeRegion(const QByteArray & me, QModelIndex & index, const QModelIndex & parent)
|
||||||
{
|
{
|
||||||
if (me.isEmpty())
|
if (me.isEmpty())
|
||||||
return ERR_EMPTY_REGION;
|
return ERR_EMPTY_REGION;
|
||||||
@ -402,12 +403,12 @@ 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, QByteArray(), parent);
|
index = treeModel->addItem(TreeItem::Region, TreeItem::MeRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), me, QByteArray(), parent);
|
||||||
|
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT8 FfsEngine::parsePdrRegion(const QByteArray & pdr, const QModelIndex & parent)
|
UINT8 FfsEngine::parsePdrRegion(const QByteArray & pdr, QModelIndex & index, const QModelIndex & parent)
|
||||||
{
|
{
|
||||||
if (pdr.isEmpty())
|
if (pdr.isEmpty())
|
||||||
return ERR_EMPTY_REGION;
|
return ERR_EMPTY_REGION;
|
||||||
@ -418,12 +419,12 @@ 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, QByteArray(), parent);
|
index = treeModel->addItem(TreeItem::Region, TreeItem::PdrRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), pdr, QByteArray(), parent);
|
||||||
|
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT8 FfsEngine::parseBiosRegion(const QByteArray & bios, const QModelIndex & parent)
|
UINT8 FfsEngine::parseBiosRegion(const QByteArray & bios, QModelIndex & index, const QModelIndex & parent)
|
||||||
{
|
{
|
||||||
if (bios.isEmpty())
|
if (bios.isEmpty())
|
||||||
return ERR_EMPTY_REGION;
|
return ERR_EMPTY_REGION;
|
||||||
@ -434,14 +435,14 @@ 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, QByteArray(), parent);
|
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::parseBios(const QByteArray & bios, const QModelIndex & parent)
|
UINT8 FfsEngine::parseBios(const QByteArray & bios, const QModelIndex & parent)
|
||||||
{
|
{
|
||||||
// Search for first volume
|
// Search for first volume
|
||||||
UINT32 prevVolumeOffset;
|
UINT32 prevVolumeOffset;
|
||||||
UINT8 result;
|
UINT8 result;
|
||||||
result = findNextVolume(bios, 0, prevVolumeOffset);
|
result = findNextVolume(bios, 0, prevVolumeOffset);
|
||||||
@ -577,7 +578,8 @@ UINT8 FfsEngine::parseBios(const QByteArray & bios, const QModelIndex & parent)
|
|||||||
msg(tr("parseBios: Unknown volume revision (%1)").arg(volumeHeader->Revision), parent);
|
msg(tr("parseBios: Unknown volume revision (%1)").arg(volumeHeader->Revision), parent);
|
||||||
|
|
||||||
// Parse volume
|
// Parse volume
|
||||||
UINT8 result = parseVolume(bios.mid(volumeOffset, volumeSize), parent);
|
QModelIndex index;
|
||||||
|
UINT8 result = parseVolume(bios.mid(volumeOffset, volumeSize), index, parent);
|
||||||
if (result)
|
if (result)
|
||||||
msg(tr("parseBios: Volume parsing failed (%1)").arg(result), parent);
|
msg(tr("parseBios: Volume parsing failed (%1)").arg(result), parent);
|
||||||
|
|
||||||
@ -640,7 +642,7 @@ UINT8 FfsEngine::getVolumeSize(const QByteArray & bios, UINT32 volumeOffset, UIN
|
|||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT8 FfsEngine::parseVolume(const QByteArray & volume, const QModelIndex & parent, const UINT8 mode)
|
UINT8 FfsEngine::parseVolume(const QByteArray & volume, QModelIndex & index, const QModelIndex & parent, const UINT8 mode)
|
||||||
{
|
{
|
||||||
// Populate volume header
|
// Populate volume header
|
||||||
EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*) (volume.constData());
|
EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*) (volume.constData());
|
||||||
@ -707,7 +709,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, QByteArray(), parent, mode);
|
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)
|
||||||
@ -752,7 +754,8 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, const QModelIndex & par
|
|||||||
files.enqueue(header.left(sizeof(EFI_GUID)));
|
files.enqueue(header.left(sizeof(EFI_GUID)));
|
||||||
|
|
||||||
// Parse file
|
// Parse file
|
||||||
result = parseFile(file, volumeHeader->Revision, empty, index);
|
QModelIndex fileIndex;
|
||||||
|
result = parseFile(file, fileIndex, empty == '\xFF' ? ERASE_POLARITY_TRUE : ERASE_POLARITY_FALSE, index);
|
||||||
if (result)
|
if (result)
|
||||||
msg(tr("parseVolume: Parse FFS file failed (%1)").arg(result), index);
|
msg(tr("parseVolume: Parse FFS file failed (%1)").arg(result), index);
|
||||||
|
|
||||||
@ -775,7 +778,7 @@ UINT8 FfsEngine::getFileSize(const QByteArray & volume, const UINT32 fileOffset,
|
|||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT8 FfsEngine::parseFile(const QByteArray & file, UINT8 revision, const UINT8 erasePolarity, const QModelIndex & parent, const UINT8 mode)
|
UINT8 FfsEngine::parseFile(const QByteArray & file, QModelIndex & index, const UINT8 erasePolarity, const QModelIndex & parent, const UINT8 mode)
|
||||||
{
|
{
|
||||||
// Populate file header
|
// Populate file header
|
||||||
EFI_FFS_FILE_HEADER* fileHeader = (EFI_FFS_FILE_HEADER*) file.constData();
|
EFI_FFS_FILE_HEADER* fileHeader = (EFI_FFS_FILE_HEADER*) file.constData();
|
||||||
@ -812,7 +815,7 @@ UINT8 FfsEngine::parseFile(const QByteArray & file, UINT8 revision, const UINT8
|
|||||||
if (fileHeader->Attributes & FFS_ATTRIB_CHECKSUM) {
|
if (fileHeader->Attributes & FFS_ATTRIB_CHECKSUM) {
|
||||||
UINT32 bufferSize = file.size() - sizeof(EFI_FFS_FILE_HEADER);
|
UINT32 bufferSize = file.size() - sizeof(EFI_FFS_FILE_HEADER);
|
||||||
// Exclude file tail from data checksum calculation
|
// Exclude file tail from data checksum calculation
|
||||||
if(revision == 1 && fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT)
|
if(fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT)
|
||||||
bufferSize -= sizeof(UINT16);
|
bufferSize -= sizeof(UINT16);
|
||||||
calculated = calculateChecksum8((UINT8*)(file.constData() + sizeof(EFI_FFS_FILE_HEADER)), bufferSize);
|
calculated = calculateChecksum8((UINT8*)(file.constData() + sizeof(EFI_FFS_FILE_HEADER)), bufferSize);
|
||||||
if (fileHeader->IntegrityCheck.Checksum.File != calculated) {
|
if (fileHeader->IntegrityCheck.Checksum.File != calculated) {
|
||||||
@ -833,16 +836,17 @@ UINT8 FfsEngine::parseFile(const QByteArray & file, UINT8 revision, const UINT8
|
|||||||
|
|
||||||
// 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));
|
||||||
// For files in Revision 1 volumes, check for file tail presence
|
// Check for file tail presence
|
||||||
QByteArray tail;
|
QByteArray tail;
|
||||||
if (revision == 1 && fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT)
|
if (fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT)
|
||||||
{
|
{
|
||||||
//Check file tail;
|
//Check file tail;
|
||||||
tail = body.right(sizeof(UINT16));
|
tail = body.right(sizeof(UINT16));
|
||||||
if (!fileHeader->IntegrityCheck.TailReference == *(UINT16*)tail.constData())
|
UINT16 tailValue = *(UINT16*) tail.constData();
|
||||||
msg(tr("parseFile: %1, file tail value %2 is not a bitwise not of %3 stored in file header")
|
if (fileHeader->IntegrityCheck.TailReference != (UINT16)~tailValue)
|
||||||
|
msg(tr("parseFile: %1, bitwise not of tail value %2 differs from %3 stored in file header")
|
||||||
.arg(guidToQString(fileHeader->Name))
|
.arg(guidToQString(fileHeader->Name))
|
||||||
.arg(*tail, 4, 16, QChar('0'))
|
.arg(~tailValue, 4, 16, QChar('0'))
|
||||||
.arg(fileHeader->IntegrityCheck.TailReference, 4, 16, QChar('0')), parent);
|
.arg(fileHeader->IntegrityCheck.TailReference, 4, 16, QChar('0')), parent);
|
||||||
|
|
||||||
// Remove tail from file body
|
// Remove tail from file body
|
||||||
@ -915,7 +919,7 @@ UINT8 FfsEngine::parseFile(const QByteArray & file, UINT8 revision, const UINT8
|
|||||||
.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, tail, parent, mode);
|
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;
|
||||||
@ -951,14 +955,16 @@ UINT8 FfsEngine::parseSections(const QByteArray & body, const QModelIndex & pare
|
|||||||
UINT32 sectionSize;
|
UINT32 sectionSize;
|
||||||
UINT32 bodySize = body.size();
|
UINT32 bodySize = body.size();
|
||||||
UINT8 result;
|
UINT8 result;
|
||||||
while (true) {
|
|
||||||
|
while (true) {
|
||||||
// Get section size
|
// Get section size
|
||||||
result = getSectionSize(body, sectionOffset, sectionSize);
|
result = getSectionSize(body, sectionOffset, sectionSize);
|
||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
// Parse section
|
// Parse section
|
||||||
result = parseSection(body.mid(sectionOffset, sectionSize), parent);
|
QModelIndex sectionIndex;
|
||||||
|
result = parseSection(body.mid(sectionOffset, sectionSize), sectionIndex, parent);
|
||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
@ -974,7 +980,7 @@ UINT8 FfsEngine::parseSections(const QByteArray & body, const QModelIndex & pare
|
|||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT8 FfsEngine::parseSection(const QByteArray & section, const QModelIndex & parent, const UINT8 mode)
|
UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, const QModelIndex & parent, const UINT8 mode)
|
||||||
{
|
{
|
||||||
EFI_COMMON_SECTION_HEADER* sectionHeader = (EFI_COMMON_SECTION_HEADER*) (section.constData());
|
EFI_COMMON_SECTION_HEADER* sectionHeader = (EFI_COMMON_SECTION_HEADER*) (section.constData());
|
||||||
UINT32 sectionSize = uint24ToUint32(sectionHeader->Size);
|
UINT32 sectionSize = uint24ToUint32(sectionHeader->Size);
|
||||||
@ -984,11 +990,9 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, const QModelIndex & pa
|
|||||||
QByteArray body;
|
QByteArray body;
|
||||||
UINT32 headerSize;
|
UINT32 headerSize;
|
||||||
UINT8 result;
|
UINT8 result;
|
||||||
QModelIndex index;
|
|
||||||
|
|
||||||
|
|
||||||
switch (sectionHeader->Type) {
|
switch (sectionHeader->Type) {
|
||||||
// Encapsulated sections
|
// Encapsulated sections
|
||||||
case EFI_SECTION_COMPRESSION:
|
case EFI_SECTION_COMPRESSION:
|
||||||
{
|
{
|
||||||
bool parseCurrentSection = true;
|
bool parseCurrentSection = true;
|
||||||
@ -1047,7 +1051,6 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, const QModelIndex & pa
|
|||||||
parseCurrentSection = false;
|
parseCurrentSection = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get info
|
// Get info
|
||||||
@ -1090,7 +1093,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, const QModelIndex & pa
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Leaf sections
|
// Leaf sections
|
||||||
case EFI_SECTION_PE32:
|
case EFI_SECTION_PE32:
|
||||||
case EFI_SECTION_PIC:
|
case EFI_SECTION_PIC:
|
||||||
case EFI_SECTION_TE:
|
case EFI_SECTION_TE:
|
||||||
@ -1184,6 +1187,248 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, const QModelIndex & pa
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Operations on tree items
|
// Operations on tree items
|
||||||
|
UINT8 FfsEngine::create(const QModelIndex & index, const UINT8 type, const QByteArray & header, const QByteArray & body, const UINT8 mode, const UINT8 action, const UINT8 algorithm)
|
||||||
|
{
|
||||||
|
QByteArray created;
|
||||||
|
UINT8 result;
|
||||||
|
|
||||||
|
if (!index.isValid() || !index.parent().isValid())
|
||||||
|
return ERR_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
QModelIndex parent;
|
||||||
|
if (mode == CREATE_MODE_BEFORE || mode == CREATE_MODE_AFTER)
|
||||||
|
parent = index.parent();
|
||||||
|
else
|
||||||
|
parent = index;
|
||||||
|
TreeItem * parentItem = static_cast<TreeItem*>(parent.internalPointer());
|
||||||
|
|
||||||
|
// Create item
|
||||||
|
if (type == TreeItem::File) {
|
||||||
|
if (parentItem->type() != TreeItem::Volume)
|
||||||
|
return ERR_INVALID_FILE;
|
||||||
|
|
||||||
|
EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*) parentItem->header().constData();
|
||||||
|
UINT8 revision = volumeHeader->Revision;
|
||||||
|
bool erasePolarity = volumeHeader->Attributes & EFI_FVB_ERASE_POLARITY;
|
||||||
|
|
||||||
|
if (header.size() != sizeof(EFI_FFS_FILE_HEADER))
|
||||||
|
return ERR_INVALID_FILE;
|
||||||
|
|
||||||
|
QByteArray newHeader = header;
|
||||||
|
EFI_FFS_FILE_HEADER* fileHeader = (EFI_FFS_FILE_HEADER*) newHeader.data();
|
||||||
|
|
||||||
|
// Correct file size
|
||||||
|
UINT8 tailSize = fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT ? sizeof(UINT16) : 0;
|
||||||
|
uint32ToUint24(sizeof(EFI_FFS_FILE_HEADER) + body.size() + tailSize, fileHeader->Size);
|
||||||
|
|
||||||
|
// Recalculate header checksum
|
||||||
|
fileHeader->IntegrityCheck.Checksum.Header = 0;
|
||||||
|
fileHeader->IntegrityCheck.Checksum.File = 0;
|
||||||
|
fileHeader->IntegrityCheck.Checksum.Header = calculateChecksum8((UINT8*) fileHeader, sizeof(EFI_FFS_FILE_HEADER) - 1);
|
||||||
|
|
||||||
|
// Recalculate data checksum, if needed
|
||||||
|
if (fileHeader->Attributes & FFS_ATTRIB_CHECKSUM) {
|
||||||
|
fileHeader->IntegrityCheck.Checksum.File = calculateChecksum8((UINT8*) body.constData(), body.size());
|
||||||
|
}
|
||||||
|
else if (revision == 1)
|
||||||
|
fileHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
|
||||||
|
else
|
||||||
|
fileHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM2;
|
||||||
|
|
||||||
|
// Append body
|
||||||
|
created.append(body);
|
||||||
|
|
||||||
|
// Append tail, if needed
|
||||||
|
if (tailSize)
|
||||||
|
created.append(~fileHeader->IntegrityCheck.TailReference);
|
||||||
|
|
||||||
|
// Set file state
|
||||||
|
UINT8 state = EFI_FILE_DATA_VALID | EFI_FILE_HEADER_VALID | EFI_FILE_HEADER_CONSTRUCTION;
|
||||||
|
if (erasePolarity)
|
||||||
|
state = ~state;
|
||||||
|
fileHeader->State = state;
|
||||||
|
|
||||||
|
// Prepend header
|
||||||
|
created.prepend(newHeader);
|
||||||
|
|
||||||
|
// Parse file
|
||||||
|
QModelIndex fileIndex;
|
||||||
|
result = parseFile(created, fileIndex, erasePolarity ? ERASE_POLARITY_TRUE : ERASE_POLARITY_FALSE, index, mode);
|
||||||
|
if (result)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
// Set action
|
||||||
|
treeModel->setItemAction(action, fileIndex);
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (type == TreeItem::Section) {
|
||||||
|
if (parentItem->type() != TreeItem::File && parentItem->type() != TreeItem::Section)
|
||||||
|
return ERR_INVALID_SECTION;
|
||||||
|
|
||||||
|
if (header.size() < sizeof(EFI_COMMON_SECTION_HEADER))
|
||||||
|
return ERR_INVALID_SECTION;
|
||||||
|
|
||||||
|
QByteArray newHeader = header;
|
||||||
|
EFI_COMMON_SECTION_HEADER* commonHeader = (EFI_COMMON_SECTION_HEADER*) newHeader.data();
|
||||||
|
|
||||||
|
switch (commonHeader->Type)
|
||||||
|
{
|
||||||
|
case EFI_SECTION_COMPRESSION: {
|
||||||
|
EFI_COMPRESSION_SECTION* sectionHeader = (EFI_COMPRESSION_SECTION*) newHeader.data();
|
||||||
|
// Correct uncompressed size
|
||||||
|
sectionHeader->UncompressedLength = body.size();
|
||||||
|
// Set compression type
|
||||||
|
if (algorithm == COMPRESSION_ALGORITHM_NONE)
|
||||||
|
sectionHeader->CompressionType = EFI_NOT_COMPRESSED;
|
||||||
|
else if (algorithm == COMPRESSION_ALGORITHM_EFI11 || algorithm == COMPRESSION_ALGORITHM_TIANO)
|
||||||
|
sectionHeader->CompressionType = EFI_STANDARD_COMPRESSION;
|
||||||
|
else if (algorithm == COMPRESSION_ALGORITHM_LZMA || algorithm == COMPRESSION_ALGORITHM_IMLZMA)
|
||||||
|
sectionHeader->CompressionType = EFI_CUSTOMIZED_COMPRESSION;
|
||||||
|
else
|
||||||
|
return ERR_UNKNOWN_COMPRESSION_ALGORITHM;
|
||||||
|
// Compress body
|
||||||
|
QByteArray compressed;
|
||||||
|
result = compress(body, algorithm, compressed);
|
||||||
|
if (result)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
// Correct section size
|
||||||
|
uint32ToUint24(header.size() + compressed.size(), commonHeader->Size);
|
||||||
|
|
||||||
|
// Append header and body
|
||||||
|
created.append(newHeader).append(compressed);
|
||||||
|
|
||||||
|
// Parse section
|
||||||
|
QModelIndex sectionIndex;
|
||||||
|
result = parseSection(created, sectionIndex, index, mode);
|
||||||
|
if (result)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
// Set create action
|
||||||
|
treeModel->setItemAction(action, sectionIndex);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EFI_SECTION_GUID_DEFINED:{
|
||||||
|
// Compress body
|
||||||
|
QByteArray compressed;
|
||||||
|
result = compress(body, algorithm, compressed);
|
||||||
|
if (result)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
// Correct section size
|
||||||
|
uint32ToUint24(header.size() + compressed.size(), commonHeader->Size);
|
||||||
|
|
||||||
|
// Append header and body
|
||||||
|
created.append(newHeader).append(compressed);
|
||||||
|
|
||||||
|
// Parse section
|
||||||
|
QModelIndex sectionIndex;
|
||||||
|
result = parseSection(created, sectionIndex, index, mode);
|
||||||
|
if (result)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
// Set create action
|
||||||
|
treeModel->setItemAction(action, sectionIndex);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Correct section size
|
||||||
|
uint32ToUint24(header.size() + body.size(), commonHeader->Size);
|
||||||
|
|
||||||
|
// Append header and body
|
||||||
|
created.append(newHeader).append(body);
|
||||||
|
|
||||||
|
// Parse section
|
||||||
|
QModelIndex sectionIndex;
|
||||||
|
result = parseSection(created, sectionIndex, index, mode);
|
||||||
|
if (result)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
// Set create action
|
||||||
|
treeModel->setItemAction(action, sectionIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return ERR_NOT_IMPLEMENTED;
|
||||||
|
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT8 FfsEngine::insert(const QModelIndex & index, const QByteArray & object, const UINT8 mode)
|
||||||
|
{
|
||||||
|
if (!index.isValid() || !index.parent().isValid())
|
||||||
|
return ERR_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
QModelIndex parent;
|
||||||
|
if (mode == CREATE_MODE_BEFORE || mode == CREATE_MODE_AFTER)
|
||||||
|
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;
|
||||||
|
headerSize = sizeof(EFI_FFS_FILE_HEADER);
|
||||||
|
}
|
||||||
|
else if (parentItem->type() == TreeItem::File) {
|
||||||
|
type = TreeItem::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);
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT8 FfsEngine::replace(const QModelIndex & index, const QByteArray & object, const UINT8 mode)
|
||||||
|
{
|
||||||
|
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 (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);
|
||||||
|
}
|
||||||
|
else if (mode == REPLACE_MODE_BODY)
|
||||||
|
result = create(index, TreeItem::File, parentItem->header(), object, CREATE_MODE_AFTER, TreeItem::Replace);
|
||||||
|
else
|
||||||
|
return ERR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
else if (parentItem->type() == TreeItem::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);
|
||||||
|
}
|
||||||
|
else if (mode == REPLACE_MODE_BODY)
|
||||||
|
result = create(index, TreeItem::Section, parentItem->header(), object, CREATE_MODE_AFTER, TreeItem::Replace);
|
||||||
|
else
|
||||||
|
return ERR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return ERR_NOT_IMPLEMENTED;
|
||||||
|
|
||||||
|
// Check create result
|
||||||
|
if (result)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
// Set remove action to replaced item
|
||||||
|
treeModel->setItemAction(TreeItem::Remove, index);
|
||||||
|
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
UINT8 FfsEngine::extract(const QModelIndex & index, QByteArray & extracted, const UINT8 mode)
|
UINT8 FfsEngine::extract(const QModelIndex & index, QByteArray & extracted, const UINT8 mode)
|
||||||
{
|
{
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
@ -1198,14 +1443,40 @@ UINT8 FfsEngine::extract(const QModelIndex & index, QByteArray & extracted, cons
|
|||||||
extracted.append(item->body());
|
extracted.append(item->body());
|
||||||
extracted.append(item->tail());
|
extracted.append(item->tail());
|
||||||
}
|
}
|
||||||
else if (mode == EXTRACT_MODE_BODY_ONLY) {
|
else if (mode == EXTRACT_MODE_BODY) {
|
||||||
// Extract without header and tail
|
// Extract without header and tail
|
||||||
extracted.clear();
|
extracted.clear();
|
||||||
extracted.append(item->body());
|
// Special case of compressed bodies
|
||||||
}
|
if (item->type() == TreeItem::Section) {
|
||||||
else if (mode == EXTRACT_MODE_UNCOMPRESSED) {
|
QByteArray decompressed;
|
||||||
// Only possible for files with compressed sections
|
UINT8 result;
|
||||||
return ERR_NOT_IMPLEMENTED;
|
if (item->subtype() == EFI_SECTION_COMPRESSION) {
|
||||||
|
EFI_COMPRESSION_SECTION* compressedHeader = (EFI_COMPRESSION_SECTION*) item->header().constData();
|
||||||
|
result = decompress(item->body(), compressedHeader->CompressionType, decompressed);
|
||||||
|
if (result)
|
||||||
|
return result;
|
||||||
|
extracted.append(decompressed);
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
else if (item->subtype() == EFI_SECTION_GUID_DEFINED) {
|
||||||
|
QByteArray decompressed;
|
||||||
|
// Check if section requires processing
|
||||||
|
EFI_GUID_DEFINED_SECTION* guidDefinedSectionHeader = (EFI_GUID_DEFINED_SECTION*) item->header().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);
|
||||||
|
if (result) {
|
||||||
|
result = decompress(item->body(), EFI_CUSTOMIZED_COMPRESSION, decompressed);
|
||||||
|
if (result)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
extracted.append(decompressed);
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extracted.append(item->body());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return ERR_UNKNOWN_EXTRACT_MODE;
|
return ERR_UNKNOWN_EXTRACT_MODE;
|
||||||
@ -1213,66 +1484,6 @@ UINT8 FfsEngine::extract(const QModelIndex & index, QByteArray & extracted, cons
|
|||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT8 FfsEngine::insert(const QModelIndex & index, const QByteArray & object, const UINT8 type, const UINT8 mode)
|
|
||||||
{
|
|
||||||
if (!index.isValid())
|
|
||||||
return ERR_INVALID_PARAMETER;
|
|
||||||
|
|
||||||
// Only files and sections can now be inserted
|
|
||||||
if (type == TreeItem::File) {
|
|
||||||
QModelIndex parent;
|
|
||||||
if (mode == INSERT_MODE_BEFORE || mode == INSERT_MODE_AFTER)
|
|
||||||
parent = index.parent();
|
|
||||||
else
|
|
||||||
parent = index;
|
|
||||||
|
|
||||||
// Parent type must be volume
|
|
||||||
TreeItem * parentItem = static_cast<TreeItem*>(parent.internalPointer());
|
|
||||||
if (parentItem->type() != TreeItem::Volume) {
|
|
||||||
msg(tr("insert: file can't be inserted into something that is not volume"), parent);
|
|
||||||
return ERR_INVALID_VOLUME;
|
|
||||||
}
|
|
||||||
|
|
||||||
EFI_FIRMWARE_VOLUME_HEADER* header = (EFI_FIRMWARE_VOLUME_HEADER*) parentItem->header().constData();
|
|
||||||
|
|
||||||
// Parse file
|
|
||||||
UINT8 result = parseFile(object, header->Revision, ERASE_POLARITY_UNKNOWN, index, mode);
|
|
||||||
if (result)
|
|
||||||
return result;
|
|
||||||
// Set rebuild action for parent
|
|
||||||
treeModel->setItemAction(TreeItem::Rebuild, parent);
|
|
||||||
}
|
|
||||||
else if (type == TreeItem::Section) {
|
|
||||||
QModelIndex parent;
|
|
||||||
if (mode == INSERT_MODE_BEFORE || mode == INSERT_MODE_AFTER)
|
|
||||||
parent = index.parent();
|
|
||||||
else
|
|
||||||
parent = index;
|
|
||||||
|
|
||||||
// Parent type must be file or encapsulation section
|
|
||||||
TreeItem * parentItem = static_cast<TreeItem*>(parent.internalPointer());
|
|
||||||
if (parentItem->type() == TreeItem::File || (parentItem->type() == TreeItem::Section &&
|
|
||||||
(parentItem->subtype() == EFI_SECTION_COMPRESSION ||
|
|
||||||
parentItem->subtype() == EFI_SECTION_GUID_DEFINED ||
|
|
||||||
parentItem->subtype() == EFI_SECTION_DISPOSABLE))) {
|
|
||||||
// Parse section
|
|
||||||
UINT8 result = parseSection(object, index, mode);
|
|
||||||
if (result)
|
|
||||||
return result;
|
|
||||||
// Set rebuild action for parent
|
|
||||||
treeModel->setItemAction(TreeItem::Rebuild, parent);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
msg(tr("insert: section can't be inserted into something that is not file or encapsulation section"), parent);
|
|
||||||
return ERR_INVALID_FILE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return ERR_NOT_IMPLEMENTED;
|
|
||||||
|
|
||||||
return ERR_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT8 FfsEngine::remove(const QModelIndex & index)
|
UINT8 FfsEngine::remove(const QModelIndex & index)
|
||||||
{
|
{
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
@ -1295,20 +1506,6 @@ UINT8 FfsEngine::rebuild(const QModelIndex & index)
|
|||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT8 FfsEngine::changeCompression(const QModelIndex & index, const UINT8 algorithm)
|
|
||||||
{
|
|
||||||
if (!index.isValid())
|
|
||||||
return ERR_INVALID_PARAMETER;
|
|
||||||
|
|
||||||
// Set compression for the item
|
|
||||||
treeModel->setItemCompression(algorithm, index);
|
|
||||||
|
|
||||||
// Set action for the item
|
|
||||||
treeModel->setItemAction(TreeItem::Modify, index);
|
|
||||||
|
|
||||||
return ERR_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compression routines
|
// Compression routines
|
||||||
UINT8 FfsEngine::decompress(const QByteArray & compressedData, const UINT8 compressionType, QByteArray & decompressedData, UINT8 * algorithm)
|
UINT8 FfsEngine::decompress(const QByteArray & compressedData, const UINT8 compressionType, QByteArray & decompressedData, UINT8 * algorithm)
|
||||||
{
|
{
|
||||||
@ -1580,7 +1777,7 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
|||||||
return ERR_NOT_IMPLEMENTED;
|
return ERR_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
// Reconstruct item and it's children recursive
|
// Reconstruct item and it's children recursive
|
||||||
else if (item->action() == TreeItem::Modify || item->action() == TreeItem::Rebuild) {
|
else if (item->action() == TreeItem::Create || item->action() == TreeItem::Insert || item->action() == TreeItem::Replace || item->action() == TreeItem::Rebuild) {
|
||||||
QQueue<QByteArray> childrenQueue;
|
QQueue<QByteArray> childrenQueue;
|
||||||
|
|
||||||
switch (item->type()) {
|
switch (item->type()) {
|
||||||
@ -1914,7 +2111,7 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Construct empty char for this file
|
// Construct empty char for this file
|
||||||
char empty = erasePolarity == ERASE_POLARITY_TRUE ? '\xFF' : '\x00';
|
char empty = (erasePolarity == ERASE_POLARITY_TRUE ? '\xFF' : '\x00');
|
||||||
|
|
||||||
// Check file state
|
// Check file state
|
||||||
// Invert it first if erase polarity is true
|
// Invert it first if erase polarity is true
|
||||||
@ -2015,7 +2212,7 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
|||||||
|
|
||||||
// Append tail, if needed
|
// Append tail, if needed
|
||||||
if (!item->hasEmptyTail())
|
if (!item->hasEmptyTail())
|
||||||
reconstructed.append(!fileHeader->IntegrityCheck.TailReference);
|
reconstructed.append(~fileHeader->IntegrityCheck.TailReference);
|
||||||
|
|
||||||
// Set file state
|
// Set file state
|
||||||
state = EFI_FILE_DATA_VALID | EFI_FILE_HEADER_VALID | EFI_FILE_HEADER_CONSTRUCTION;
|
state = EFI_FILE_DATA_VALID | EFI_FILE_HEADER_VALID | EFI_FILE_HEADER_CONSTRUCTION;
|
||||||
@ -2075,13 +2272,16 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
|||||||
result = compress(reconstructed, item->compression(), compressed);
|
result = compress(reconstructed, item->compression(), compressed);
|
||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
// Correct compression type
|
// Correct compression type
|
||||||
if (item->compression() == COMPRESSION_ALGORITHM_NONE)
|
if (item->compression() == COMPRESSION_ALGORITHM_NONE)
|
||||||
compessionHeader->CompressionType = EFI_NOT_COMPRESSED;
|
compessionHeader->CompressionType = EFI_NOT_COMPRESSED;
|
||||||
else if (item->compression() == COMPRESSION_ALGORITHM_LZMA || item->compression() == COMPRESSION_ALGORITHM_IMLZMA)
|
else if (item->compression() == COMPRESSION_ALGORITHM_LZMA || item->compression() == COMPRESSION_ALGORITHM_IMLZMA)
|
||||||
compessionHeader->CompressionType = EFI_CUSTOMIZED_COMPRESSION;
|
compessionHeader->CompressionType = EFI_CUSTOMIZED_COMPRESSION;
|
||||||
else
|
else if (item->compression() == COMPRESSION_ALGORITHM_EFI11 || item->compression() == COMPRESSION_ALGORITHM_TIANO)
|
||||||
compessionHeader->CompressionType = EFI_STANDARD_COMPRESSION;
|
compessionHeader->CompressionType = EFI_STANDARD_COMPRESSION;
|
||||||
|
else
|
||||||
|
return ERR_UNKNOWN_COMPRESSION_ALGORITHM;
|
||||||
|
|
||||||
// Replace new section body
|
// Replace new section body
|
||||||
reconstructed = compressed;
|
reconstructed = compressed;
|
||||||
}
|
}
|
||||||
@ -2101,7 +2301,7 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
|||||||
reconstructed = compressed;
|
reconstructed = compressed;
|
||||||
}
|
}
|
||||||
else if (item->compression() != COMPRESSION_ALGORITHM_NONE) {
|
else if (item->compression() != COMPRESSION_ALGORITHM_NONE) {
|
||||||
msg(tr("reconstruct: compression required for section of type %1")
|
msg(tr("reconstruct: incorreclty required compression for section of type %1")
|
||||||
.arg(item->subtype()));
|
.arg(item->subtype()));
|
||||||
return ERR_INVALID_SECTION;
|
return ERR_INVALID_SECTION;
|
||||||
}
|
}
|
||||||
@ -2168,12 +2368,12 @@ UINT8 FfsEngine::growVolume(QByteArray & header, const UINT32 size, UINT32 & new
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Search routines
|
// Search routines
|
||||||
UINT8 FfsEngine::findHexPattern(const QByteArray & pattern, const bool bodyOnly)
|
UINT8 FfsEngine::findHexPattern(const QByteArray & pattern, const UINT8 mode)
|
||||||
{
|
{
|
||||||
return findHexPatternIn(treeModel->index(0,0), pattern, bodyOnly);
|
return findHexPatternIn(treeModel->index(0,0), pattern, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT8 FfsEngine::findHexPatternIn(const QModelIndex & index, const QByteArray & pattern, const bool bodyOnly)
|
UINT8 FfsEngine::findHexPatternIn(const QModelIndex & index, const QByteArray & pattern, const UINT8 mode)
|
||||||
{
|
{
|
||||||
if (pattern.isEmpty())
|
if (pattern.isEmpty())
|
||||||
return ERR_INVALID_PARAMETER;
|
return ERR_INVALID_PARAMETER;
|
||||||
@ -2187,19 +2387,21 @@ UINT8 FfsEngine::findHexPatternIn(const QModelIndex & index, const QByteArray &
|
|||||||
|
|
||||||
bool hasChildren = (item->childCount() > 0);
|
bool hasChildren = (item->childCount() > 0);
|
||||||
for (int i = 0; i < item->childCount(); i++) {
|
for (int i = 0; i < item->childCount(); i++) {
|
||||||
findHexPatternIn(index.child(i, index.column()), pattern, bodyOnly);
|
findHexPatternIn(index.child(i, index.column()), pattern, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray data;
|
QByteArray data;
|
||||||
if (hasChildren) {
|
if (hasChildren) {
|
||||||
if(!bodyOnly)
|
if(mode != SEARCH_MODE_BODY)
|
||||||
data = item->header();
|
data = item->header();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (bodyOnly)
|
if (mode == SEARCH_MODE_HEADER)
|
||||||
data = item->body();
|
data.append(item->header()).append(item->tail());
|
||||||
|
else if (mode == SEARCH_MODE_BODY)
|
||||||
|
data.append(item->body());
|
||||||
else
|
else
|
||||||
data = item->header().append(item->body()).append(item->tail());
|
data.append(item->header()).append(item->body()).append(item->tail());
|
||||||
}
|
}
|
||||||
|
|
||||||
int offset = -1;
|
int offset = -1;
|
||||||
|
36
ffsengine.h
36
ffsengine.h
@ -45,20 +45,20 @@ public:
|
|||||||
|
|
||||||
// Firmware image parsing
|
// Firmware image parsing
|
||||||
UINT8 parseInputFile(const QByteArray & buffer);
|
UINT8 parseInputFile(const QByteArray & buffer);
|
||||||
UINT8 parseIntelImage(const QByteArray & flashImage, const QModelIndex & parent = QModelIndex());
|
UINT8 parseIntelImage(const QByteArray & flashImage, QModelIndex & index, const QModelIndex & parent = QModelIndex());
|
||||||
UINT8 parseGbeRegion(const QByteArray & gbe, const QModelIndex & parent = QModelIndex());
|
UINT8 parseGbeRegion(const QByteArray & gbe, QModelIndex & index, const QModelIndex & parent);
|
||||||
UINT8 parseMeRegion(const QByteArray & me, const QModelIndex & parent = QModelIndex());
|
UINT8 parseMeRegion(const QByteArray & me, QModelIndex & index, const QModelIndex & parent);
|
||||||
UINT8 parseBiosRegion(const QByteArray & bios, const QModelIndex & parent = QModelIndex());
|
UINT8 parseBiosRegion(const QByteArray & bios, QModelIndex & index, const QModelIndex & parent);
|
||||||
UINT8 parsePdrRegion(const QByteArray & pdr, const QModelIndex & parent = QModelIndex());
|
UINT8 parsePdrRegion(const QByteArray & pdr, QModelIndex & index, const QModelIndex & parent);
|
||||||
UINT8 parseBios(const QByteArray & bios, const QModelIndex & parent = QModelIndex());
|
UINT8 parseBios(const QByteArray & bios, const QModelIndex & parent = QModelIndex());
|
||||||
UINT8 findNextVolume(const QByteArray & bios, const UINT32 volumeOffset, UINT32 & nextVolumeOffset);
|
UINT8 findNextVolume(const QByteArray & bios, const UINT32 volumeOffset, UINT32 & nextVolumeOffset);
|
||||||
UINT8 getVolumeSize(const QByteArray & bios, const UINT32 volumeOffset, UINT32 & volumeSize);
|
UINT8 getVolumeSize(const QByteArray & bios, const UINT32 volumeOffset, UINT32 & volumeSize);
|
||||||
UINT8 parseVolume(const QByteArray & volume, const QModelIndex & parent = QModelIndex(), const UINT8 mode = INSERT_MODE_APPEND);
|
UINT8 parseVolume(const QByteArray & volume, QModelIndex & index, const QModelIndex & parent = QModelIndex(), const UINT8 mode = CREATE_MODE_APPEND);
|
||||||
UINT8 getFileSize(const QByteArray & volume, const UINT32 fileOffset, UINT32 & fileSize);
|
UINT8 getFileSize(const QByteArray & volume, const UINT32 fileOffset, UINT32 & fileSize);
|
||||||
UINT8 parseFile(const QByteArray & file, const UINT8 revision, const UINT8 erasePolarity = ERASE_POLARITY_UNKNOWN, const QModelIndex & parent = QModelIndex(), const UINT8 mode = INSERT_MODE_APPEND);
|
UINT8 parseFile(const QByteArray & file, QModelIndex & index, const UINT8 erasePolarity = ERASE_POLARITY_UNKNOWN, const QModelIndex & parent = QModelIndex(), const UINT8 mode = CREATE_MODE_APPEND);
|
||||||
UINT8 getSectionSize(const QByteArray & file, const UINT32 sectionOffset, UINT32 & sectionSize);
|
UINT8 getSectionSize(const QByteArray & file, const UINT32 sectionOffset, UINT32 & sectionSize);
|
||||||
UINT8 parseSections(const QByteArray & body, const QModelIndex & parent = QModelIndex());
|
UINT8 parseSections(const QByteArray & body, const QModelIndex & parent = QModelIndex());
|
||||||
UINT8 parseSection(const QByteArray & section, const QModelIndex & parent = QModelIndex(), const UINT8 mode = INSERT_MODE_APPEND);
|
UINT8 parseSection(const QByteArray & section, QModelIndex & index, const QModelIndex & parent = QModelIndex(), const UINT8 mode = CREATE_MODE_APPEND);
|
||||||
|
|
||||||
// Compression routines
|
// Compression routines
|
||||||
UINT8 decompress(const QByteArray & compressed, const UINT8 compressionType, QByteArray & decompressedData, UINT8 * algorithm = NULL);
|
UINT8 decompress(const QByteArray & compressed, const UINT8 compressionType, QByteArray & decompressedData, UINT8 * algorithm = NULL);
|
||||||
@ -71,22 +71,26 @@ public:
|
|||||||
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 extract(const QModelIndex & index, QByteArray & extracted, 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 create(const QModelIndex & index, const UINT8 type, const QByteArray & header, const QByteArray & body, const UINT8 mode, const UINT8 action, const UINT8 algorithm = COMPRESSION_ALGORITHM_NONE);
|
||||||
UINT8 rebuild(const QModelIndex & index);
|
UINT8 insert(const QModelIndex & index, const QByteArray & object, const UINT8 mode);
|
||||||
UINT8 changeCompression(const QModelIndex & index, const UINT8 algorithm);
|
UINT8 replace(const QModelIndex & index, const QByteArray & object, const UINT8 mode);
|
||||||
|
|
||||||
|
UINT8 remove(const QModelIndex & index);
|
||||||
|
|
||||||
|
UINT8 rebuild(const QModelIndex & index);
|
||||||
|
|
||||||
// Search routines
|
// Search routines
|
||||||
UINT8 findHexPattern(const QByteArray & pattern, const bool bodyOnly);
|
UINT8 findHexPattern(const QByteArray & pattern, const UINT8 mode);
|
||||||
UINT8 findHexPatternIn(const QModelIndex & index, const QByteArray & pattern, const bool bodyOnly);
|
UINT8 findHexPatternIn(const QModelIndex & index, const QByteArray & pattern, const UINT8 mode);
|
||||||
UINT8 findTextPattern(const QString & pattern, const bool unicode, const Qt::CaseSensitivity caseSensitive);
|
UINT8 findTextPattern(const QString & pattern, const bool unicode, const Qt::CaseSensitivity caseSensitive);
|
||||||
UINT8 findTextPatternIn(const QModelIndex & index, const QString & pattern, const bool unicode, const Qt::CaseSensitivity caseSensitive);
|
UINT8 findTextPatternIn(const QModelIndex & index, const QString & pattern, const bool unicode, const Qt::CaseSensitivity caseSensitive);
|
||||||
private:
|
private:
|
||||||
TreeItem *rootItem;
|
TreeItem *rootItem;
|
||||||
TreeModel *treeModel;
|
TreeModel *treeModel;
|
||||||
|
|
||||||
// Message helper
|
// Message helper
|
||||||
QQueue<MessageListItem> messageItems;
|
QQueue<MessageListItem> messageItems;
|
||||||
void msg(const QString & message, const QModelIndex index = QModelIndex());
|
void msg(const QString & message, const QModelIndex index = QModelIndex());
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>290</width>
|
<width>290</width>
|
||||||
<height>172</height>
|
<height>195</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
@ -77,14 +77,21 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QRadioButton" name="allRadioButton">
|
<widget class="QRadioButton" name="allRadioButton">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Header, data and footer</string>
|
<string>Header and body</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QRadioButton" name="dataOnlyRadioButton">
|
<widget class="QRadioButton" name="headerOnlyRadioButton">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Data only</string>
|
<string>Header only</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="bodyOnlyRadioButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Body only</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="checked">
|
<property name="checked">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
@ -140,7 +147,7 @@
|
|||||||
<tabstop>searchEdit</tabstop>
|
<tabstop>searchEdit</tabstop>
|
||||||
<tabstop>dataTypeComboBox</tabstop>
|
<tabstop>dataTypeComboBox</tabstop>
|
||||||
<tabstop>allRadioButton</tabstop>
|
<tabstop>allRadioButton</tabstop>
|
||||||
<tabstop>dataOnlyRadioButton</tabstop>
|
<tabstop>bodyOnlyRadioButton</tabstop>
|
||||||
<tabstop>unicodeCheckBox</tabstop>
|
<tabstop>unicodeCheckBox</tabstop>
|
||||||
<tabstop>caseSensitiveCheckBox</tabstop>
|
<tabstop>caseSensitiveCheckBox</tabstop>
|
||||||
<tabstop>buttonBox</tabstop>
|
<tabstop>buttonBox</tabstop>
|
||||||
|
32
treeitem.cpp
32
treeitem.cpp
@ -172,12 +172,16 @@ QVariant TreeItem::data(int column) const
|
|||||||
case 0: //Name
|
case 0: //Name
|
||||||
return itemName;
|
return itemName;
|
||||||
case 1: //Action
|
case 1: //Action
|
||||||
if (itemAction == TreeItem::Modify)
|
if (itemAction == TreeItem::Create)
|
||||||
return "M";
|
return QObject::tr("Create");
|
||||||
|
if (itemAction == TreeItem::Insert)
|
||||||
|
return QObject::tr("Insert");
|
||||||
|
if (itemAction == TreeItem::Replace)
|
||||||
|
return QObject::tr("Replace");
|
||||||
if (itemAction == TreeItem::Remove)
|
if (itemAction == TreeItem::Remove)
|
||||||
return "X";
|
return QObject::tr("Remove");
|
||||||
if (itemAction == TreeItem::Rebuild)
|
if (itemAction == TreeItem::Rebuild)
|
||||||
return "R";
|
return QObject::tr("Rebuild");
|
||||||
return QVariant();
|
return QVariant();
|
||||||
case 2: //Type
|
case 2: //Type
|
||||||
return itemTypeName;
|
return itemTypeName;
|
||||||
@ -220,11 +224,6 @@ QString TreeItem::info() const
|
|||||||
return itemInfo;
|
return itemInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TreeItem::setInfo(const QString &text)
|
|
||||||
{
|
|
||||||
itemInfo = text;
|
|
||||||
}
|
|
||||||
|
|
||||||
int TreeItem::row() const
|
int TreeItem::row() const
|
||||||
{
|
{
|
||||||
if (parentItem)
|
if (parentItem)
|
||||||
@ -287,12 +286,13 @@ void TreeItem::setAction(const UINT8 action)
|
|||||||
{
|
{
|
||||||
itemAction = action;
|
itemAction = action;
|
||||||
|
|
||||||
// Set rebuild action for parent
|
// On insert action, set insert action for children
|
||||||
if (parentItem)
|
if (action == TreeItem::Insert)
|
||||||
parentItem->setAction(TreeItem::Rebuild);
|
for(int i = 0; i < childCount(); i++)
|
||||||
|
child(i)->setAction(TreeItem::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);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TreeItem::setCompression(const UINT8 algorithm)
|
|
||||||
{
|
|
||||||
itemCompression = algorithm;
|
|
||||||
}
|
|
19
treeitem.h
19
treeitem.h
@ -31,7 +31,9 @@ public:
|
|||||||
// Action types
|
// Action types
|
||||||
enum ActionTypes {
|
enum ActionTypes {
|
||||||
NoAction = 50,
|
NoAction = 50,
|
||||||
Modify,
|
Create,
|
||||||
|
Insert,
|
||||||
|
Replace,
|
||||||
Remove,
|
Remove,
|
||||||
Rebuild
|
Rebuild
|
||||||
};
|
};
|
||||||
@ -104,17 +106,12 @@ public:
|
|||||||
UINT8 action() const;
|
UINT8 action() const;
|
||||||
UINT8 compression() const;
|
UINT8 compression() const;
|
||||||
|
|
||||||
// Action can be changed
|
// Some values can be changed after item construction
|
||||||
void setAction(const UINT8 action);
|
void setAction(const UINT8 action);
|
||||||
// Compression can be changed
|
void setTypeName(const QString &text);
|
||||||
void setCompression(const UINT8 algorithm);
|
|
||||||
|
|
||||||
// Text values can be changed after item construction
|
|
||||||
void setTypeName(const QString &text);
|
|
||||||
void setSubtypeName(const QString &text);
|
void setSubtypeName(const QString &text);
|
||||||
void setName(const QString &text);
|
void setName(const QString &text);
|
||||||
void setText(const QString &text);
|
void setText(const QString &text);
|
||||||
void setInfo(const QString &text);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Set default names after construction
|
// Set default names after construction
|
||||||
@ -129,9 +126,9 @@ private:
|
|||||||
QByteArray itemHeader;
|
QByteArray itemHeader;
|
||||||
QByteArray itemBody;
|
QByteArray itemBody;
|
||||||
QByteArray itemTail;
|
QByteArray itemTail;
|
||||||
QString itemTypeName;
|
QString itemName;
|
||||||
|
QString itemTypeName;
|
||||||
QString itemSubtypeName;
|
QString itemSubtypeName;
|
||||||
QString itemName;
|
|
||||||
QString itemText;
|
QString itemText;
|
||||||
QString itemInfo;
|
QString itemInfo;
|
||||||
TreeItem *parentItem;
|
TreeItem *parentItem;
|
||||||
|
@ -61,8 +61,21 @@ Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const
|
|||||||
QVariant TreeModel::headerData(int section, Qt::Orientation orientation,
|
QVariant TreeModel::headerData(int section, Qt::Orientation orientation,
|
||||||
int role) const
|
int role) const
|
||||||
{
|
{
|
||||||
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
|
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
|
||||||
return rootItem->data(section);
|
switch(section)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return tr("Name");
|
||||||
|
case 1:
|
||||||
|
return tr("Action");
|
||||||
|
case 2:
|
||||||
|
return tr("Type");
|
||||||
|
case 3:
|
||||||
|
return tr("Subtype");
|
||||||
|
case 4:
|
||||||
|
return tr("Text");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
@ -152,17 +165,6 @@ UINT8 TreeModel::setItemAction(const UINT8 action, const QModelIndex &index)
|
|||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT8 TreeModel::setItemCompression(const UINT8 algorithm, const QModelIndex &index)
|
|
||||||
{
|
|
||||||
if(!index.isValid())
|
|
||||||
return ERR_INVALID_PARAMETER;
|
|
||||||
|
|
||||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
|
||||||
item->setCompression(algorithm);
|
|
||||||
emit dataChanged(this->index(0,0), index);
|
|
||||||
return ERR_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 QByteArray & tail,
|
const QByteArray & header, const QByteArray & body, const QByteArray & tail,
|
||||||
@ -176,7 +178,7 @@ QModelIndex TreeModel::addItem(const UINT8 type, const UINT8 subtype, const UINT
|
|||||||
parentItem = rootItem;
|
parentItem = rootItem;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (mode == INSERT_MODE_BEFORE || mode == INSERT_MODE_AFTER) {
|
if (mode == CREATE_MODE_BEFORE || mode == CREATE_MODE_AFTER) {
|
||||||
item = static_cast<TreeItem*>(index.internalPointer());
|
item = static_cast<TreeItem*>(index.internalPointer());
|
||||||
parentItem = item->parent();
|
parentItem = item->parent();
|
||||||
parentColumn = index.parent().column();
|
parentColumn = index.parent().column();
|
||||||
@ -188,19 +190,19 @@ QModelIndex TreeModel::addItem(const UINT8 type, const UINT8 subtype, const UINT
|
|||||||
}
|
}
|
||||||
|
|
||||||
TreeItem *newItem = new TreeItem(type, subtype, compression, name, text, info, header, body, tail, parentItem);
|
TreeItem *newItem = new TreeItem(type, subtype, compression, name, text, info, header, body, tail, parentItem);
|
||||||
if (mode == INSERT_MODE_APPEND) {
|
if (mode == CREATE_MODE_APPEND) {
|
||||||
emit layoutAboutToBeChanged();
|
emit layoutAboutToBeChanged();
|
||||||
parentItem->appendChild(newItem);
|
parentItem->appendChild(newItem);
|
||||||
}
|
}
|
||||||
else if (mode == INSERT_MODE_PREPEND) {
|
else if (mode == CREATE_MODE_PREPEND) {
|
||||||
emit layoutAboutToBeChanged();
|
emit layoutAboutToBeChanged();
|
||||||
parentItem->prependChild(newItem);
|
parentItem->prependChild(newItem);
|
||||||
}
|
}
|
||||||
else if (mode == INSERT_MODE_BEFORE) {
|
else if (mode == CREATE_MODE_BEFORE) {
|
||||||
emit layoutAboutToBeChanged();
|
emit layoutAboutToBeChanged();
|
||||||
parentItem->insertChildBefore(item, newItem);
|
parentItem->insertChildBefore(item, newItem);
|
||||||
}
|
}
|
||||||
else if (mode == INSERT_MODE_AFTER) {
|
else if (mode == CREATE_MODE_AFTER) {
|
||||||
emit layoutAboutToBeChanged();
|
emit layoutAboutToBeChanged();
|
||||||
parentItem->insertChildAfter(item, newItem);
|
parentItem->insertChildAfter(item, newItem);
|
||||||
}
|
}
|
||||||
|
@ -44,12 +44,11 @@ public:
|
|||||||
UINT8 setItemName(const QString &data, const QModelIndex &index);
|
UINT8 setItemName(const QString &data, const QModelIndex &index);
|
||||||
UINT8 setItemText(const QString &data, const QModelIndex &index);
|
UINT8 setItemText(const QString &data, const QModelIndex &index);
|
||||||
UINT8 setItemAction(const UINT8 action, const QModelIndex &index);
|
UINT8 setItemAction(const UINT8 action, const QModelIndex &index);
|
||||||
UINT8 setItemCompression(const UINT8 algorithm, const QModelIndex &index);
|
|
||||||
|
|
||||||
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 QByteArray & tail = QByteArray(),
|
const QByteArray & header = QByteArray(), const QByteArray & body = QByteArray(), const QByteArray & tail = QByteArray(),
|
||||||
const QModelIndex & index = QModelIndex(), const UINT8 mode = INSERT_MODE_APPEND);
|
const QModelIndex & index = QModelIndex(), const UINT8 mode = CREATE_MODE_APPEND);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TreeItem *rootItem;
|
TreeItem *rootItem;
|
||||||
|
311
uefitool.cpp
311
uefitool.cpp
@ -29,17 +29,13 @@ UEFITool::UEFITool(QWidget *parent) :
|
|||||||
connect(ui->actionSearch, SIGNAL(triggered()), this, SLOT(search()));
|
connect(ui->actionSearch, SIGNAL(triggered()), this, SLOT(search()));
|
||||||
connect(ui->actionExtract, SIGNAL(triggered()), this, SLOT(extractAsIs()));
|
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->actionInsertInto, SIGNAL(triggered()), this, SLOT(insertInto()));
|
connect(ui->actionInsertInto, SIGNAL(triggered()), this, SLOT(insertInto()));
|
||||||
connect(ui->actionInsertBefore, SIGNAL(triggered()), this, SLOT(insertBefore()));
|
connect(ui->actionInsertBefore, SIGNAL(triggered()), this, SLOT(insertBefore()));
|
||||||
connect(ui->actionInsertAfter, SIGNAL(triggered()), this, SLOT(insertAfter()));
|
connect(ui->actionInsertAfter, SIGNAL(triggered()), this, SLOT(insertAfter()));
|
||||||
connect(ui->actionReplace, SIGNAL(triggered()), this, SLOT(replace()));
|
connect(ui->actionReplace, SIGNAL(triggered()), this, SLOT(replaceAsIs()));
|
||||||
|
connect(ui->actionReplaceBody, SIGNAL(triggered()), this, SLOT(replaceBody()));
|
||||||
connect(ui->actionRemove, SIGNAL(triggered()), this, SLOT(remove()));
|
connect(ui->actionRemove, SIGNAL(triggered()), this, SLOT(remove()));
|
||||||
connect(ui->actionRebuild, SIGNAL(triggered()), this, SLOT(rebuild()));
|
connect(ui->actionRebuild, SIGNAL(triggered()), this, SLOT(rebuild()));
|
||||||
connect(ui->actionChangeToNone, SIGNAL(triggered()), this, SLOT(changeToNone()));
|
|
||||||
connect(ui->actionChangeToEfi11, SIGNAL(triggered()), this, SLOT(changeToEfi11()));
|
|
||||||
connect(ui->actionChangeToTiano, SIGNAL(triggered()), this, SLOT(changeToTiano()));
|
|
||||||
connect(ui->actionChangeToLzma, SIGNAL(triggered()), this, SLOT(changeToLzma()));
|
|
||||||
connect(ui->actionMessagesClear, SIGNAL(triggered()), this, SLOT(clearMessages()));
|
connect(ui->actionMessagesClear, SIGNAL(triggered()), this, SLOT(clearMessages()));
|
||||||
connect(ui->actionAbout, SIGNAL(triggered()), this, SLOT(about()));
|
connect(ui->actionAbout, SIGNAL(triggered()), this, SLOT(about()));
|
||||||
connect(ui->actionAboutQt, SIGNAL(triggered()), this, SLOT(aboutQt()));
|
connect(ui->actionAboutQt, SIGNAL(triggered()), this, SLOT(aboutQt()));
|
||||||
@ -85,8 +81,6 @@ void UEFITool::init()
|
|||||||
ui->structureTreeView->setModel(ffsEngine->model());
|
ui->structureTreeView->setModel(ffsEngine->model());
|
||||||
|
|
||||||
// Connect
|
// Connect
|
||||||
//connect(ui->structureTreeView, SIGNAL(collapsed(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->messageListWidget, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(scrollTreeView(QListWidgetItem*)));
|
connect(ui->messageListWidget, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(scrollTreeView(QListWidgetItem*)));
|
||||||
@ -100,7 +94,6 @@ void UEFITool::populateUi(const QModelIndex ¤t)
|
|||||||
TreeItem* item = static_cast<TreeItem*>(current.internalPointer());
|
TreeItem* item = static_cast<TreeItem*>(current.internalPointer());
|
||||||
UINT8 type = item->type();
|
UINT8 type = item->type();
|
||||||
UINT8 subtype = item->subtype();
|
UINT8 subtype = item->subtype();
|
||||||
UINT8 algorithm = item->compression();
|
|
||||||
|
|
||||||
// Set info text
|
// Set info text
|
||||||
ui->infoEdit->setPlainText(item->info());
|
ui->infoEdit->setPlainText(item->info());
|
||||||
@ -119,12 +112,11 @@ void UEFITool::populateUi(const QModelIndex ¤t)
|
|||||||
ui->actionRebuild->setDisabled(item->hasEmptyHeader() && item->hasEmptyBody() && item->hasEmptyTail());
|
ui->actionRebuild->setDisabled(item->hasEmptyHeader() && item->hasEmptyBody() && item->hasEmptyTail());
|
||||||
ui->actionExtractBody->setDisabled(item->hasEmptyHeader());
|
ui->actionExtractBody->setDisabled(item->hasEmptyHeader());
|
||||||
ui->actionRemove->setEnabled(type == TreeItem::Volume || type == TreeItem::File || type == TreeItem::Section);
|
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_RAW && subtype != EFI_FV_FILETYPE_PAD)
|
ui->actionInsertInto->setEnabled(type == TreeItem::Volume || (type == TreeItem::File && subtype != EFI_FV_FILETYPE_ALL && subtype != EFI_FV_FILETYPE_RAW && subtype != EFI_FV_FILETYPE_PAD));
|
||||||
|| (type == TreeItem::Section && (subtype == EFI_SECTION_COMPRESSION || subtype == EFI_SECTION_GUID_DEFINED || subtype == EFI_SECTION_DISPOSABLE)));
|
|
||||||
ui->actionInsertBefore->setEnabled(type == TreeItem::File || type == TreeItem::Section);
|
ui->actionInsertBefore->setEnabled(type == TreeItem::File || type == TreeItem::Section);
|
||||||
ui->actionInsertAfter->setEnabled(type == TreeItem::File || type == TreeItem::Section);
|
ui->actionInsertAfter->setEnabled(type == TreeItem::File || type == TreeItem::Section);
|
||||||
ui->menuChangeCompressionTo->setEnabled(type == TreeItem::Section && subtype == EFI_SECTION_COMPRESSION &&
|
ui->actionReplace->setEnabled(type == TreeItem::File || type == TreeItem::Section);
|
||||||
(algorithm == COMPRESSION_ALGORITHM_NONE || COMPRESSION_ALGORITHM_EFI11 || algorithm == COMPRESSION_ALGORITHM_TIANO || algorithm == COMPRESSION_ALGORITHM_LZMA));
|
ui->actionReplaceBody->setEnabled(type == TreeItem::File || type == TreeItem::Section);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UEFITool::search()
|
void UEFITool::search()
|
||||||
@ -137,7 +129,14 @@ void UEFITool::search()
|
|||||||
QByteArray pattern = QByteArray::fromHex(searchDialog->ui->searchEdit->text().toLatin1());
|
QByteArray pattern = QByteArray::fromHex(searchDialog->ui->searchEdit->text().toLatin1());
|
||||||
if (pattern.isEmpty())
|
if (pattern.isEmpty())
|
||||||
return;
|
return;
|
||||||
ffsEngine->findHexPattern(pattern, searchDialog->ui->dataOnlyRadioButton->isChecked());
|
UINT8 mode;
|
||||||
|
if (searchDialog->ui->headerOnlyRadioButton->isChecked())
|
||||||
|
mode = SEARCH_MODE_HEADER;
|
||||||
|
else if (searchDialog->ui->bodyOnlyRadioButton->isChecked())
|
||||||
|
mode = SEARCH_MODE_BODY;
|
||||||
|
else
|
||||||
|
mode = SEARCH_MODE_ALL;
|
||||||
|
ffsEngine->findHexPattern(pattern, mode);
|
||||||
showMessages();
|
showMessages();
|
||||||
}
|
}
|
||||||
else if (index == 1) { // Text string
|
else if (index == 1) { // Text string
|
||||||
@ -184,7 +183,7 @@ void UEFITool::insert(const UINT8 mode)
|
|||||||
UINT8 type;
|
UINT8 type;
|
||||||
UINT8 objectType;
|
UINT8 objectType;
|
||||||
|
|
||||||
if (mode == INSERT_MODE_BEFORE || mode == INSERT_MODE_AFTER)
|
if (mode == CREATE_MODE_BEFORE || mode == CREATE_MODE_AFTER)
|
||||||
type = item->parent()->type();
|
type = item->parent()->type();
|
||||||
else
|
else
|
||||||
type = item->type();
|
type = item->type();
|
||||||
@ -221,7 +220,7 @@ void UEFITool::insert(const UINT8 mode)
|
|||||||
QByteArray buffer = inputFile.readAll();
|
QByteArray buffer = inputFile.readAll();
|
||||||
inputFile.close();
|
inputFile.close();
|
||||||
|
|
||||||
UINT8 result = ffsEngine->insert(index, buffer, objectType, mode);
|
UINT8 result = ffsEngine->insert(index, buffer, 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
|
||||||
@ -230,67 +229,189 @@ void UEFITool::insert(const UINT8 mode)
|
|||||||
|
|
||||||
void UEFITool::insertInto()
|
void UEFITool::insertInto()
|
||||||
{
|
{
|
||||||
insert(INSERT_MODE_PREPEND);
|
insert(CREATE_MODE_PREPEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UEFITool::insertBefore()
|
void UEFITool::insertBefore()
|
||||||
{
|
{
|
||||||
insert(INSERT_MODE_BEFORE);
|
insert(CREATE_MODE_BEFORE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UEFITool::insertAfter()
|
void UEFITool::insertAfter()
|
||||||
{
|
{
|
||||||
insert(INSERT_MODE_AFTER);
|
insert(CREATE_MODE_AFTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UEFITool::replace()
|
void UEFITool::replaceAsIs()
|
||||||
{
|
{
|
||||||
|
replace(REPLACE_MODE_AS_IS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UEFITool::changeToEfi11()
|
void UEFITool::replaceBody()
|
||||||
|
{
|
||||||
|
replace(REPLACE_MODE_BODY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UEFITool::replace(const UINT8 mode)
|
||||||
|
{
|
||||||
|
QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex();
|
||||||
|
if (!index.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
|
||||||
|
QString path;
|
||||||
|
if (item->type() == TreeItem::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)
|
||||||
|
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
|
||||||
|
return;
|
||||||
|
else
|
||||||
|
path = QFileDialog::getOpenFileName(this, tr("Select FFS file body to replace body"),".","FFS file body files (*.fbd *.bin);;All files (*.*)");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (item->type() == TreeItem::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)
|
||||||
|
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)
|
||||||
|
path = QFileDialog::getOpenFileName(this, tr("Select volume file to replace body"),".","Volume files (*.vol *.bin);;All files (*.*)");
|
||||||
|
else if (item->subtype() == 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 (*.*)");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
|
||||||
|
QFileInfo fileInfo = QFileInfo(path);
|
||||||
|
if (!fileInfo.exists()) {
|
||||||
|
ui->statusBar->showMessage(tr("Please select existing file"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFile inputFile;
|
||||||
|
inputFile.setFileName(path);
|
||||||
|
|
||||||
|
if (!inputFile.open(QFile::ReadOnly)) {
|
||||||
|
ui->statusBar->showMessage(tr("Can't open file for reading"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray buffer = inputFile.readAll();
|
||||||
|
inputFile.close();
|
||||||
|
|
||||||
|
UINT8 result = ffsEngine->replace(index, buffer, mode);
|
||||||
|
if (result)
|
||||||
|
ui->statusBar->showMessage(tr("File can't be replaced (%1)").arg(result));
|
||||||
|
else
|
||||||
|
ui->actionSaveImageFile->setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UEFITool::extractAsIs()
|
||||||
|
{
|
||||||
|
extract(EXTRACT_MODE_AS_IS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UEFITool::extractBody()
|
||||||
|
{
|
||||||
|
extract(EXTRACT_MODE_BODY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UEFITool::extract(const UINT8 mode)
|
||||||
{
|
{
|
||||||
QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex();
|
QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex();
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
UINT8 result = ffsEngine->changeCompression(index, COMPRESSION_ALGORITHM_EFI11);
|
TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
|
||||||
|
UINT8 type = item->type();
|
||||||
|
|
||||||
if (result == ERR_SUCCESS)
|
QString path;
|
||||||
ui->actionSaveImageFile->setEnabled(true);
|
if (mode == EXTRACT_MODE_AS_IS) {
|
||||||
}
|
switch (type) {
|
||||||
|
case TreeItem::Capsule:
|
||||||
|
path = QFileDialog::getSaveFileName(this, tr("Save capsule to file"),".","Capsule files (*.cap *.bin);;All files (*.*)");
|
||||||
|
break;
|
||||||
|
case TreeItem::Image:
|
||||||
|
path = QFileDialog::getSaveFileName(this, tr("Save image to file"),".","Image files (*.rom *.bin);;All files (*.*)");
|
||||||
|
break;
|
||||||
|
case TreeItem::Region:
|
||||||
|
path = QFileDialog::getSaveFileName(this, tr("Save region to file"),".","Region files (*.rgn *.bin);;All files (*.*)");
|
||||||
|
break;
|
||||||
|
case TreeItem::Padding:
|
||||||
|
path = QFileDialog::getSaveFileName(this, tr("Save padding to file"),".","Padding files (*.pad *.bin);;All files (*.*)");
|
||||||
|
break;
|
||||||
|
case TreeItem::Volume:
|
||||||
|
path = QFileDialog::getSaveFileName(this, tr("Save volume to file"),".","Volume files (*.vol *.bin);;All files (*.*)");
|
||||||
|
break;
|
||||||
|
case TreeItem::File:
|
||||||
|
path = QFileDialog::getSaveFileName(this, tr("Save FFS file to file"),".","FFS files (*.ffs *.bin);;All files (*.*)");
|
||||||
|
break;
|
||||||
|
case TreeItem::Section:
|
||||||
|
path = QFileDialog::getSaveFileName(this, tr("Save section file to file"),".","Section files (*.sct *.bin);;All files (*.*)");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
path = QFileDialog::getSaveFileName(this, tr("Save object to file"),".","Binary files (*.bin);;All files (*.*)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (mode == EXTRACT_MODE_BODY) {
|
||||||
|
switch (type) {
|
||||||
|
case TreeItem::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)
|
||||||
|
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)
|
||||||
|
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)
|
||||||
|
path = QFileDialog::getSaveFileName(this, tr("Save section body to volume file"),".","Volume files (*.vol *.bin);;All files (*.*)");
|
||||||
|
else if (item->subtype() == EFI_SECTION_RAW)
|
||||||
|
path = QFileDialog::getOpenFileName(this, tr("Select 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 (*.*)");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
path = QFileDialog::getSaveFileName(this, tr("Save object to file"),".","Binary files (*.bin);;All files (*.*)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
path = QFileDialog::getSaveFileName(this, tr("Save object to file"),".","Binary files (*.bin);;All files (*.*)");
|
||||||
|
|
||||||
void UEFITool::changeToTiano()
|
QFile outputFile;
|
||||||
{
|
outputFile.setFileName(path);
|
||||||
QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex();
|
if (!outputFile.open(QFile::WriteOnly)) {
|
||||||
if (!index.isValid())
|
ui->statusBar->showMessage(tr("Can't open file for rewriting"));
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
UINT8 result = ffsEngine->changeCompression(index, COMPRESSION_ALGORITHM_TIANO);
|
QByteArray extracted;
|
||||||
if (result == ERR_SUCCESS)
|
UINT8 result = ffsEngine->extract(index, extracted, mode);
|
||||||
ui->actionSaveImageFile->setEnabled(true);
|
if (result)
|
||||||
}
|
ui->statusBar->showMessage(tr("File can't be extracted (%1)").arg(result));
|
||||||
|
else {
|
||||||
void UEFITool::changeToLzma()
|
outputFile.resize(0);
|
||||||
{
|
outputFile.write(extracted);
|
||||||
QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex();
|
outputFile.close();
|
||||||
if (!index.isValid())
|
}
|
||||||
return;
|
|
||||||
|
|
||||||
UINT8 result = ffsEngine->changeCompression(index, COMPRESSION_ALGORITHM_LZMA);
|
|
||||||
if (result == ERR_SUCCESS)
|
|
||||||
ui->actionSaveImageFile->setEnabled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UEFITool::changeToNone()
|
|
||||||
{
|
|
||||||
QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex();
|
|
||||||
if (!index.isValid())
|
|
||||||
return;
|
|
||||||
|
|
||||||
UINT8 result = ffsEngine->changeCompression(index, COMPRESSION_ALGORITHM_NONE);
|
|
||||||
if (result == ERR_SUCCESS)
|
|
||||||
ui->actionSaveImageFile->setEnabled(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UEFITool::about()
|
void UEFITool::about()
|
||||||
@ -317,7 +438,7 @@ void UEFITool::exit()
|
|||||||
|
|
||||||
void UEFITool::saveImageFile()
|
void UEFITool::saveImageFile()
|
||||||
{
|
{
|
||||||
QString path = QFileDialog::getSaveFileName(this, tr("Save BIOS image file"),".","BIOS image files (*.rom *.bin *.cap *.fd *.wph *.efi);;All files (*.*)");
|
QString path = QFileDialog::getSaveFileName(this, tr("Save BIOS image file"),".","BIOS image files (*.rom *.bin *.cap *.bio *.fd *.wph *.efi);;All files (*.*)");
|
||||||
|
|
||||||
QFile outputFile;
|
QFile outputFile;
|
||||||
outputFile.setFileName(path);
|
outputFile.setFileName(path);
|
||||||
@ -340,12 +461,12 @@ void UEFITool::saveImageFile()
|
|||||||
ui->statusBar->showMessage(tr("Reconstructed image written"));
|
ui->statusBar->showMessage(tr("Reconstructed image written"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void UEFITool::resizeTreeViewColumns()
|
/*void UEFITool::resizeTreeViewColumns()
|
||||||
{
|
{
|
||||||
int count = ffsEngine->model()->columnCount();
|
int count = ffsEngine->model()->columnCount();
|
||||||
for(int i = 0; i < count; i++)
|
for(int i = 0; i < count; i++)
|
||||||
ui->structureTreeView->resizeColumnToContents(i);
|
ui->structureTreeView->resizeColumnToContents(i);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
void UEFITool::openImageFile()
|
void UEFITool::openImageFile()
|
||||||
{
|
{
|
||||||
@ -391,79 +512,6 @@ void UEFITool::clearMessages()
|
|||||||
ui->messageListWidget->clear();
|
ui->messageListWidget->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UEFITool::extract(const UINT8 mode)
|
|
||||||
{
|
|
||||||
QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex();
|
|
||||||
if (!index.isValid())
|
|
||||||
return;
|
|
||||||
|
|
||||||
TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
|
|
||||||
UINT8 type = item->type();
|
|
||||||
|
|
||||||
QString path;
|
|
||||||
if(mode == EXTRACT_MODE_AS_IS) {
|
|
||||||
switch (type) {
|
|
||||||
case TreeItem::Capsule:
|
|
||||||
path = QFileDialog::getSaveFileName(this, tr("Save capsule to binary file"),".","Capsule files (*.cap *.bin);;All files (*.*)");
|
|
||||||
break;
|
|
||||||
case TreeItem::Image:
|
|
||||||
path = QFileDialog::getSaveFileName(this, tr("Save image to binary file"),".","Image files (*.rom *.bin);;All files (*.*)");
|
|
||||||
break;
|
|
||||||
case TreeItem::Region:
|
|
||||||
path = QFileDialog::getSaveFileName(this, tr("Save region to binary file"),".","Region files (*.rgn *.bin);;All files (*.*)");
|
|
||||||
break;
|
|
||||||
case TreeItem::Padding:
|
|
||||||
path = QFileDialog::getSaveFileName(this, tr("Save padding to binary file"),".","Padding files (*.pad *.bin);;All files (*.*)");
|
|
||||||
break;
|
|
||||||
case TreeItem::Volume:
|
|
||||||
path = QFileDialog::getSaveFileName(this, tr("Save volume to binary file"),".","Volume files (*.vol *.bin);;All files (*.*)");
|
|
||||||
break;
|
|
||||||
case TreeItem::File:
|
|
||||||
path = QFileDialog::getSaveFileName(this, tr("Save FFS file to binary file"),".","FFS files (*.ffs *.bin);;All files (*.*)");
|
|
||||||
break;
|
|
||||||
case TreeItem::Section:
|
|
||||||
path = QFileDialog::getSaveFileName(this, tr("Save section file to binary file"),".","Section files (*.sct *.bin);;All files (*.*)");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
path = QFileDialog::getSaveFileName(this, tr("Save object to binary file"),".","Binary files (*.bin);;All files (*.*)");
|
|
||||||
|
|
||||||
QFile outputFile;
|
|
||||||
outputFile.setFileName(path);
|
|
||||||
if (!outputFile.open(QFile::WriteOnly)) {
|
|
||||||
ui->statusBar->showMessage(tr("Can't open file for rewriting"));
|
|
||||||
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.write(extracted);
|
|
||||||
outputFile.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void UEFITool::extractAsIs()
|
|
||||||
{
|
|
||||||
extract(EXTRACT_MODE_AS_IS);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UEFITool::extractBody()
|
|
||||||
{
|
|
||||||
extract(EXTRACT_MODE_BODY_ONLY);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UEFITool::extractUncompressed()
|
|
||||||
{
|
|
||||||
extract(EXTRACT_MODE_UNCOMPRESSED);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UEFITool::dragEnterEvent(QDragEnterEvent* event)
|
void UEFITool::dragEnterEvent(QDragEnterEvent* event)
|
||||||
{
|
{
|
||||||
if (event->mimeData()->hasFormat("text/uri-list"))
|
if (event->mimeData()->hasFormat("text/uri-list"))
|
||||||
@ -553,7 +601,6 @@ void UEFITool::readSettings()
|
|||||||
vertList.append(settings.value("mainWindow/messageHeight", 180).toInt());
|
vertList.append(settings.value("mainWindow/messageHeight", 180).toInt());
|
||||||
ui->infoSplitter->setSizes(horList);
|
ui->infoSplitter->setSizes(horList);
|
||||||
ui->messagesSplitter->setSizes(vertList);
|
ui->messagesSplitter->setSizes(vertList);
|
||||||
resizeTreeViewColumns();
|
|
||||||
ui->structureTreeView->setColumnWidth(0, settings.value("tree/columnWidth0", ui->structureTreeView->columnWidth(0)).toInt());
|
ui->structureTreeView->setColumnWidth(0, settings.value("tree/columnWidth0", ui->structureTreeView->columnWidth(0)).toInt());
|
||||||
ui->structureTreeView->setColumnWidth(1, settings.value("tree/columnWidth1", ui->structureTreeView->columnWidth(1)).toInt());
|
ui->structureTreeView->setColumnWidth(1, settings.value("tree/columnWidth1", ui->structureTreeView->columnWidth(1)).toInt());
|
||||||
ui->structureTreeView->setColumnWidth(2, settings.value("tree/columnWidth2", ui->structureTreeView->columnWidth(2)).toInt());
|
ui->structureTreeView->setColumnWidth(2, settings.value("tree/columnWidth2", ui->structureTreeView->columnWidth(2)).toInt());
|
||||||
|
16
uefitool.h
16
uefitool.h
@ -54,7 +54,7 @@ public:
|
|||||||
private slots:
|
private slots:
|
||||||
void init();
|
void init();
|
||||||
void populateUi(const QModelIndex ¤t);
|
void populateUi(const QModelIndex ¤t);
|
||||||
void resizeTreeViewColumns();
|
//void resizeTreeViewColumns();
|
||||||
void scrollTreeView(QListWidgetItem* item);
|
void scrollTreeView(QListWidgetItem* item);
|
||||||
|
|
||||||
void openImageFile();
|
void openImageFile();
|
||||||
@ -64,23 +64,19 @@ private slots:
|
|||||||
void extract(const UINT8 mode);
|
void extract(const UINT8 mode);
|
||||||
void extractAsIs();
|
void extractAsIs();
|
||||||
void extractBody();
|
void extractBody();
|
||||||
void extractUncompressed();
|
|
||||||
|
|
||||||
void insert(const UINT8 mode);
|
void insert(const UINT8 mode);
|
||||||
void insertInto();
|
void insertInto();
|
||||||
void insertBefore();
|
void insertBefore();
|
||||||
void insertAfter();
|
void insertAfter();
|
||||||
|
|
||||||
void replace();
|
void replace(const UINT8 mode);
|
||||||
|
void replaceAsIs();
|
||||||
|
void replaceBody();
|
||||||
|
|
||||||
void remove();
|
void rebuild();
|
||||||
|
|
||||||
void rebuild();
|
void remove();
|
||||||
|
|
||||||
void changeToNone();
|
|
||||||
void changeToEfi11();
|
|
||||||
void changeToTiano();
|
|
||||||
void changeToLzma();
|
|
||||||
|
|
||||||
void clearMessages();
|
void clearMessages();
|
||||||
|
|
||||||
|
91
uefitool.ui
91
uefitool.ui
@ -20,7 +20,7 @@
|
|||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>UEFITool 0.11.0</string>
|
<string>UEFITool 0.12.0</string>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="centralWidget">
|
<widget class="QWidget" name="centralWidget">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
@ -222,21 +222,15 @@
|
|||||||
<addaction name="actionInsertBefore"/>
|
<addaction name="actionInsertBefore"/>
|
||||||
<addaction name="actionInsertAfter"/>
|
<addaction name="actionInsertAfter"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
|
<addaction name="actionReplace"/>
|
||||||
|
<addaction name="actionReplaceBody"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
<addaction name="actionRemove"/>
|
<addaction name="actionRemove"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="menuSectionActions">
|
<widget class="QMenu" name="menuSectionActions">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>&Section</string>
|
<string>&Section</string>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QMenu" name="menuChangeCompressionTo">
|
|
||||||
<property name="title">
|
|
||||||
<string>Change compression to</string>
|
|
||||||
</property>
|
|
||||||
<addaction name="actionChangeToNone"/>
|
|
||||||
<addaction name="actionChangeToTiano"/>
|
|
||||||
<addaction name="actionChangeToEfi11"/>
|
|
||||||
<addaction name="actionChangeToLzma"/>
|
|
||||||
</widget>
|
|
||||||
<addaction name="actionExtract"/>
|
<addaction name="actionExtract"/>
|
||||||
<addaction name="actionExtractBody"/>
|
<addaction name="actionExtractBody"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
@ -246,9 +240,11 @@
|
|||||||
<addaction name="actionInsertBefore"/>
|
<addaction name="actionInsertBefore"/>
|
||||||
<addaction name="actionInsertAfter"/>
|
<addaction name="actionInsertAfter"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
|
<addaction name="actionReplace"/>
|
||||||
|
<addaction name="actionReplaceBody"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
<addaction name="actionRemove"/>
|
<addaction name="actionRemove"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="menuChangeCompressionTo"/>
|
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="menuMessages">
|
<widget class="QMenu" name="menuMessages">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
@ -289,7 +285,7 @@
|
|||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Insert &before...</string>
|
<string>Insert b&efore...</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>
|
||||||
@ -303,10 +299,10 @@
|
|||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Rep&lace</string>
|
<string>Rep&lace as is...</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Replace selected object with an object from file</string>
|
<string>Replace selected object as is with an object from file</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="shortcut">
|
<property name="shortcut">
|
||||||
<string>Ctrl+R</string>
|
<string>Ctrl+R</string>
|
||||||
@ -331,29 +327,15 @@
|
|||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Extract &without header...</string>
|
<string>Extract &body...</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Extract selected object without header to file</string>
|
<string>Extract body of selected object to file</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="shortcut">
|
<property name="shortcut">
|
||||||
<string>Ctrl+Shift+E</string>
|
<string>Ctrl+Shift+E</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionExtractUncompressed">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Extract &uncompressed...</string>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Extract selected FFS file uncompressing it </string>
|
|
||||||
</property>
|
|
||||||
<property name="shortcut">
|
|
||||||
<string>Ctrl+Alt+E</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="actionRemove">
|
<action name="actionRemove">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
@ -421,30 +403,6 @@
|
|||||||
<string>Ctrl+Space</string>
|
<string>Ctrl+Space</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionChangeToTiano">
|
|
||||||
<property name="text">
|
|
||||||
<string>&Tiano</string>
|
|
||||||
</property>
|
|
||||||
<property name="shortcut">
|
|
||||||
<string>Ctrl+T</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="actionChangeToEfi11">
|
|
||||||
<property name="text">
|
|
||||||
<string>&EFI 1.1</string>
|
|
||||||
</property>
|
|
||||||
<property name="shortcut">
|
|
||||||
<string>Ctrl+Shift+T</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="actionChangeToLzma">
|
|
||||||
<property name="text">
|
|
||||||
<string>&LZMA</string>
|
|
||||||
</property>
|
|
||||||
<property name="shortcut">
|
|
||||||
<string>Ctrl+L</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="actionAbout">
|
<action name="actionAbout">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&About UEFITool</string>
|
<string>&About UEFITool</string>
|
||||||
@ -472,14 +430,6 @@
|
|||||||
<enum>QAction::QuitRole</enum>
|
<enum>QAction::QuitRole</enum>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionChangeToNone">
|
|
||||||
<property name="text">
|
|
||||||
<string>&Uncompressed</string>
|
|
||||||
</property>
|
|
||||||
<property name="shortcut">
|
|
||||||
<string>Ctrl+U</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="actionSearch">
|
<action name="actionSearch">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
@ -495,10 +445,27 @@
|
|||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&Clear</string>
|
<string>&Clear</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Clear messages</string>
|
||||||
|
</property>
|
||||||
<property name="shortcut">
|
<property name="shortcut">
|
||||||
<string>Ctrl+Backspace</string>
|
<string>Ctrl+Backspace</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionReplaceBody">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Replace b&ody...</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Replace body of selected object with a data from file</string>
|
||||||
|
</property>
|
||||||
|
<property name="shortcut">
|
||||||
|
<string>Ctrl+Shift+R</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<layoutdefault spacing="6" margin="11"/>
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
Loading…
Reference in New Issue
Block a user