mirror of
https://github.com/LongSoft/UEFITool.git
synced 2024-11-22 07:58:22 +08:00
Version 0.9.0
- fixed all interaction with file state - added application meny - added actions for changing compression method for selected compressed section
This commit is contained in:
parent
a858cc23f5
commit
bfd8edcdf9
@ -106,6 +106,11 @@ typedef uint16_t CHAR16;
|
|||||||
#define INSERT_MODE_BEFORE 2
|
#define INSERT_MODE_BEFORE 2
|
||||||
#define INSERT_MODE_AFTER 3
|
#define INSERT_MODE_AFTER 3
|
||||||
|
|
||||||
|
// Erase polarity types
|
||||||
|
#define ERASE_POLARITY_FALSE 0
|
||||||
|
#define ERASE_POLARITY_TRUE 1
|
||||||
|
#define ERASE_POLARITY_UNKNOWN 0xFF
|
||||||
|
|
||||||
// EFI GUID
|
// EFI GUID
|
||||||
typedef struct{
|
typedef struct{
|
||||||
UINT8 Data[16];
|
UINT8 Data[16];
|
||||||
|
1
ffs.h
1
ffs.h
@ -296,6 +296,7 @@ extern const UINT8 ffsAlignmentTable[];
|
|||||||
#define EFI_FILE_MARKED_FOR_UPDATE 0x08
|
#define EFI_FILE_MARKED_FOR_UPDATE 0x08
|
||||||
#define EFI_FILE_DELETED 0x10
|
#define EFI_FILE_DELETED 0x10
|
||||||
#define EFI_FILE_HEADER_INVALID 0x20
|
#define EFI_FILE_HEADER_INVALID 0x20
|
||||||
|
#define EFI_FILE_ERASE_POLARITY 0x80
|
||||||
|
|
||||||
// Volume top file
|
// Volume top file
|
||||||
const QByteArray EFI_FFS_VOLUME_TOP_FILE_GUID
|
const QByteArray EFI_FFS_VOLUME_TOP_FILE_GUID
|
||||||
|
511
ffsengine.cpp
511
ffsengine.cpp
@ -274,7 +274,6 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & flashImage, const QModelInde
|
|||||||
QString name;
|
QString name;
|
||||||
QString info;
|
QString info;
|
||||||
|
|
||||||
//!TODO: reorganize info
|
|
||||||
// Intel image
|
// Intel image
|
||||||
name = tr("Intel image");
|
name = tr("Intel image");
|
||||||
info = tr("Size: %1\nFlash chips: %2\nRegions: %3\nMasters: %4\nPCH straps: %5\nPROC straps: %6\nICC table entries: %7")
|
info = tr("Size: %1\nFlash chips: %2\nRegions: %3\nMasters: %4\nPCH straps: %5\nPROC straps: %6\nICC table entries: %7")
|
||||||
@ -441,7 +440,7 @@ UINT8 FfsEngine::parseBios(const QByteArray & bios, const QModelIndex & parent)
|
|||||||
UINT32 prevVolumeOffset;
|
UINT32 prevVolumeOffset;
|
||||||
UINT8 result;
|
UINT8 result;
|
||||||
result = findNextVolume(bios, 0, prevVolumeOffset);
|
result = findNextVolume(bios, 0, prevVolumeOffset);
|
||||||
if (result == ERR_VOLUMES_NOT_FOUND) {
|
if (result) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -771,10 +770,23 @@ UINT8 FfsEngine::getFileSize(const QByteArray & volume, const UINT32 fileOffset,
|
|||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT8 FfsEngine::parseFile(const QByteArray & file, UINT8 revision, const char empty, const QModelIndex & parent, const UINT8 mode)
|
UINT8 FfsEngine::parseFile(const QByteArray & file, UINT8 revision, const UINT8 erasePolarity, const QModelIndex & parent, const UINT8 mode)
|
||||||
{
|
{
|
||||||
|
// 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();
|
||||||
|
|
||||||
|
// Check file state
|
||||||
|
// Determine file erase polarity
|
||||||
|
bool fileErasePolarity = fileHeader->State | EFI_FILE_ERASE_POLARITY;
|
||||||
|
|
||||||
|
// Check file erase polarity to be the same as parent erase polarity
|
||||||
|
if (erasePolarity != ERASE_POLARITY_UNKNOWN && (bool) erasePolarity != fileErasePolarity) {
|
||||||
|
msg(tr("parseFile: %1, erase polarity differs from parent erase polarity"), parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct empty byte for this file
|
||||||
|
char empty = fileErasePolarity ? '\xFF' : '\x00';
|
||||||
|
|
||||||
// Check header checksum
|
// Check header checksum
|
||||||
QByteArray header = file.left(sizeof(EFI_FFS_FILE_HEADER));
|
QByteArray header = file.left(sizeof(EFI_FFS_FILE_HEADER));
|
||||||
QByteArray tempHeader = header;
|
QByteArray tempHeader = header;
|
||||||
@ -784,7 +796,7 @@ UINT8 FfsEngine::parseFile(const QByteArray & file, UINT8 revision, const char e
|
|||||||
UINT8 calculated = calculateChecksum8((UINT8*) tempFileHeader, sizeof(EFI_FFS_FILE_HEADER) - 1);
|
UINT8 calculated = calculateChecksum8((UINT8*) tempFileHeader, sizeof(EFI_FFS_FILE_HEADER) - 1);
|
||||||
if (fileHeader->IntegrityCheck.Checksum.Header != calculated)
|
if (fileHeader->IntegrityCheck.Checksum.Header != calculated)
|
||||||
{
|
{
|
||||||
msg(tr("parseVolume: %1, stored header checksum %2 differs from calculated %3")
|
msg(tr("parseFile: %1, stored header checksum %2 differs from calculated %3")
|
||||||
.arg(guidToQString(fileHeader->Name))
|
.arg(guidToQString(fileHeader->Name))
|
||||||
.arg(fileHeader->IntegrityCheck.Checksum.Header, 2, 16, QChar('0'))
|
.arg(fileHeader->IntegrityCheck.Checksum.Header, 2, 16, QChar('0'))
|
||||||
.arg(calculated, 2, 16, QChar('0')), parent);
|
.arg(calculated, 2, 16, QChar('0')), parent);
|
||||||
@ -799,7 +811,7 @@ UINT8 FfsEngine::parseFile(const QByteArray & file, UINT8 revision, const char e
|
|||||||
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) {
|
||||||
msg(tr("parseVolume: %1, stored data checksum %2 differs from calculated %3")
|
msg(tr("parseFile: %1, stored data checksum %2 differs from calculated %3")
|
||||||
.arg(guidToQString(fileHeader->Name))
|
.arg(guidToQString(fileHeader->Name))
|
||||||
.arg(fileHeader->IntegrityCheck.Checksum.File, 2, 16, QChar('0'))
|
.arg(fileHeader->IntegrityCheck.Checksum.File, 2, 16, QChar('0'))
|
||||||
.arg(calculated, 2, 16, QChar('0')), parent);
|
.arg(calculated, 2, 16, QChar('0')), parent);
|
||||||
@ -823,7 +835,7 @@ UINT8 FfsEngine::parseFile(const QByteArray & file, UINT8 revision, const char e
|
|||||||
//Check file tail;
|
//Check file tail;
|
||||||
tail = body.right(sizeof(UINT16));
|
tail = body.right(sizeof(UINT16));
|
||||||
if (!fileHeader->IntegrityCheck.TailReference == *(UINT16*)tail.constData())
|
if (!fileHeader->IntegrityCheck.TailReference == *(UINT16*)tail.constData())
|
||||||
msg(tr("parseVolume: %1, file tail value %2 is not a bitwise not of %3 stored in file header")
|
msg(tr("parseFile: %1, file tail value %2 is not a bitwise not of %3 stored in file header")
|
||||||
.arg(guidToQString(fileHeader->Name))
|
.arg(guidToQString(fileHeader->Name))
|
||||||
.arg(*tail, 4, 16, QChar('0'))
|
.arg(*tail, 4, 16, QChar('0'))
|
||||||
.arg(fileHeader->IntegrityCheck.TailReference, 4, 16, QChar('0')), parent);
|
.arg(fileHeader->IntegrityCheck.TailReference, 4, 16, QChar('0')), parent);
|
||||||
@ -875,7 +887,7 @@ UINT8 FfsEngine::parseFile(const QByteArray & file, UINT8 revision, const char e
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
parseCurrentFile = false;
|
parseCurrentFile = false;
|
||||||
msg(tr("parseVolume: Unknown file type (%1)").arg(fileHeader->Type, 2, 16, QChar('0')), parent);
|
msg(tr("parseFile: Unknown file type (%1)").arg(fileHeader->Type, 2, 16, QChar('0')), parent);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check for empty file
|
// Check for empty file
|
||||||
@ -908,12 +920,12 @@ UINT8 FfsEngine::parseFile(const QByteArray & file, UINT8 revision, const char e
|
|||||||
if (parseAsBios) {
|
if (parseAsBios) {
|
||||||
result = parseBios(body, index);
|
result = parseBios(body, index);
|
||||||
if (result && result != ERR_VOLUMES_NOT_FOUND)
|
if (result && result != ERR_VOLUMES_NOT_FOUND)
|
||||||
msg(tr("parseVolume: Parse file as BIOS failed (%1)").arg(result), index);
|
msg(tr("parseFile: Parse file as BIOS failed (%1)").arg(result), index);
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse sections
|
// Parse sections
|
||||||
result = parseSections(body, revision, empty, index);
|
result = parseSections(body, index);
|
||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
@ -927,38 +939,37 @@ UINT8 FfsEngine::getSectionSize(const QByteArray & file, const UINT32 sectionOff
|
|||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT8 FfsEngine::parseSections(const QByteArray & body, const UINT8 revision, const char empty, const QModelIndex & parent)
|
UINT8 FfsEngine::parseSections(const QByteArray & body, const QModelIndex & parent)
|
||||||
{
|
{
|
||||||
// Search for and parse all sections
|
// Search for and parse all sections
|
||||||
UINT32 sectionOffset = 0;
|
UINT32 sectionOffset = 0;
|
||||||
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), revision, empty, parent);
|
result = parseSection(body.mid(sectionOffset, sectionSize), parent);
|
||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
// Move to next section
|
// Move to next section
|
||||||
sectionOffset += sectionSize;
|
sectionOffset += sectionSize;
|
||||||
sectionOffset = ALIGN4(sectionOffset);
|
sectionOffset = ALIGN4(sectionOffset);
|
||||||
|
|
||||||
// Exit from loop if no sections left
|
// Exit from loop if no sections left
|
||||||
if (sectionOffset >= bodySize)
|
if (sectionOffset >= bodySize)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT8 FfsEngine::parseSection(const QByteArray & section, const UINT8 revision,
|
UINT8 FfsEngine::parseSection(const QByteArray & section, const QModelIndex & parent, const UINT8 mode)
|
||||||
const char empty, 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);
|
||||||
@ -970,8 +981,9 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, const UINT8 revision,
|
|||||||
UINT8 result;
|
UINT8 result;
|
||||||
QModelIndex index;
|
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;
|
||||||
@ -984,7 +996,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, const UINT8 revision,
|
|||||||
// Decompress section
|
// Decompress section
|
||||||
result = decompress(body, compressedSectionHeader->CompressionType, decompressed, &algorithm);
|
result = decompress(body, compressedSectionHeader->CompressionType, decompressed, &algorithm);
|
||||||
if (result) {
|
if (result) {
|
||||||
msg(tr("parseFile: Section decompression failed (%1)").arg(result), parent);
|
msg(tr("parseSection: Section decompression failed (%1)").arg(result), parent);
|
||||||
parseCurrentSection = false;
|
parseCurrentSection = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1000,7 +1012,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, const UINT8 revision,
|
|||||||
|
|
||||||
// Parse decompressed data
|
// Parse decompressed data
|
||||||
if (parseCurrentSection) {
|
if (parseCurrentSection) {
|
||||||
result = parseSections(decompressed, revision, empty, index);
|
result = parseSections(decompressed, index);
|
||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -1026,7 +1038,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, const UINT8 revision,
|
|||||||
if (result) {
|
if (result) {
|
||||||
result = decompress(body, EFI_CUSTOMIZED_COMPRESSION, decompressed, &algorithm);
|
result = decompress(body, EFI_CUSTOMIZED_COMPRESSION, decompressed, &algorithm);
|
||||||
if (result) {
|
if (result) {
|
||||||
msg(tr("parseFile: GUID defined section can not be decompressed (%1)").arg(result), parent);
|
msg(tr("parseSection: GUID defined section can not be decompressed (%1)").arg(result), parent);
|
||||||
parseCurrentSection = false;
|
parseCurrentSection = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1047,7 +1059,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, const UINT8 revision,
|
|||||||
|
|
||||||
// Parse decompressed data
|
// Parse decompressed data
|
||||||
if (parseCurrentSection) {
|
if (parseCurrentSection) {
|
||||||
result = parseSections(decompressed, revision, empty, index);
|
result = parseSections(decompressed, index);
|
||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -1059,7 +1071,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, const UINT8 revision,
|
|||||||
body = section.mid(sizeof(EFI_DISPOSABLE_SECTION), sectionSize - sizeof(EFI_DISPOSABLE_SECTION));
|
body = section.mid(sizeof(EFI_DISPOSABLE_SECTION), sectionSize - sizeof(EFI_DISPOSABLE_SECTION));
|
||||||
|
|
||||||
// Get info
|
// Get info
|
||||||
info = tr("Type: %1\nSize: %2")
|
info = tr("parseSection: %1\nSize: %2")
|
||||||
.arg(sectionHeader->Type, 2, 16, QChar('0'))
|
.arg(sectionHeader->Type, 2, 16, QChar('0'))
|
||||||
.arg(body.size(), 8, 16, QChar('0'));
|
.arg(body.size(), 8, 16, QChar('0'));
|
||||||
|
|
||||||
@ -1067,13 +1079,13 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, const UINT8 revision,
|
|||||||
index = treeModel->addItem(TreeItem::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
|
index = treeModel->addItem(TreeItem::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
|
||||||
|
|
||||||
// Parse section body
|
// Parse section body
|
||||||
result = parseSections(body, revision, empty, index);
|
result = parseSections(body, index);
|
||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
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:
|
||||||
@ -1097,20 +1109,20 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, const UINT8 revision,
|
|||||||
break;
|
break;
|
||||||
case EFI_SECTION_USER_INTERFACE:
|
case EFI_SECTION_USER_INTERFACE:
|
||||||
{
|
{
|
||||||
header = section.left(sizeof(EFI_USER_INTERFACE_SECTION));
|
header = section.left(sizeof(EFI_USER_INTERFACE_SECTION));
|
||||||
body = section.mid(sizeof(EFI_USER_INTERFACE_SECTION), sectionSize - sizeof(EFI_USER_INTERFACE_SECTION));
|
body = section.mid(sizeof(EFI_USER_INTERFACE_SECTION), sectionSize - sizeof(EFI_USER_INTERFACE_SECTION));
|
||||||
|
|
||||||
// Get info
|
// Get info
|
||||||
info = tr("Type: %1\nSize: %2")
|
info = tr("Type: %1\nSize: %2")
|
||||||
.arg(sectionHeader->Type, 2, 16, QChar('0'))
|
.arg(sectionHeader->Type, 2, 16, QChar('0'))
|
||||||
.arg(body.size(), 8, 16, QChar('0'));
|
.arg(body.size(), 8, 16, QChar('0'));
|
||||||
|
|
||||||
// Add tree item
|
// Add tree item
|
||||||
index = treeModel->addItem(TreeItem::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
|
index = treeModel->addItem(TreeItem::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
|
||||||
|
|
||||||
// Rename parent file
|
// Rename parent file
|
||||||
QString text = QString::fromUtf16((const ushort*)body.constData());
|
QString text = QString::fromUtf16((const ushort*)body.constData());
|
||||||
treeModel->setItemText(text, findParentOfType(TreeItem::File, parent));
|
treeModel->setItemText(text, findParentOfType(TreeItem::File, parent));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EFI_SECTION_FIRMWARE_VOLUME_IMAGE:
|
case EFI_SECTION_FIRMWARE_VOLUME_IMAGE:
|
||||||
@ -1128,7 +1140,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, const UINT8 revision,
|
|||||||
// Parse section body as BIOS space
|
// Parse section body as BIOS space
|
||||||
result = parseBios(body, index);
|
result = parseBios(body, index);
|
||||||
if (result && result != ERR_VOLUMES_NOT_FOUND) {
|
if (result && result != ERR_VOLUMES_NOT_FOUND) {
|
||||||
msg(tr("parseFile: Firmware volume image can not be parsed (%1)").arg(result), index);
|
msg(tr("parseSection: Firmware volume image can not be parsed as BIOS (%1)").arg(result), index);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1147,7 +1159,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, const UINT8 revision,
|
|||||||
// Parse section body as BIOS space
|
// Parse section body as BIOS space
|
||||||
result = parseBios(body, index);
|
result = parseBios(body, index);
|
||||||
if (result && result != ERR_VOLUMES_NOT_FOUND) {
|
if (result && result != ERR_VOLUMES_NOT_FOUND) {
|
||||||
msg(tr("parseFile: Raw section can not be parsed as BIOS (%1)").arg(result), index);
|
msg(tr("parseSection: Raw section can not be parsed as BIOS (%1)").arg(result), index);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1161,7 +1173,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, const UINT8 revision,
|
|||||||
|
|
||||||
// Add tree item
|
// Add tree item
|
||||||
index = treeModel->addItem(TreeItem::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
|
index = treeModel->addItem(TreeItem::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode);
|
||||||
msg(tr("parseFile: Section with unknown type (%1)").arg(sectionHeader->Type, 2, 16, QChar('0')), index);
|
msg(tr("parseSection: Section with unknown type (%1)").arg(sectionHeader->Type, 2, 16, QChar('0')), index);
|
||||||
}
|
}
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -1219,14 +1231,11 @@ UINT8 FfsEngine::insert(const QModelIndex & index, const QByteArray & object, co
|
|||||||
EFI_FIRMWARE_VOLUME_HEADER* header = (EFI_FIRMWARE_VOLUME_HEADER*) parentItem->header().constData();
|
EFI_FIRMWARE_VOLUME_HEADER* header = (EFI_FIRMWARE_VOLUME_HEADER*) parentItem->header().constData();
|
||||||
|
|
||||||
// Parse file
|
// Parse file
|
||||||
UINT8 result = parseFile(object, header->Revision, header->Attributes & EFI_FVB_ERASE_POLARITY ? '\xFF' : '\x00', index, mode);
|
UINT8 result = parseFile(object, header->Revision, ERASE_POLARITY_UNKNOWN, index, mode);
|
||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
|
// Set rebuild action for parent
|
||||||
// Set reconstruct action for all it's parents
|
treeModel->setItemAction(TreeItem::Rebuild, parent);
|
||||||
for (;parent.isValid(); parent = parent.parent())
|
|
||||||
treeModel->setItemAction(TreeItem::Reconstruct, parent);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (type == TreeItem::Section) {
|
else if (type == TreeItem::Section) {
|
||||||
QModelIndex parent;
|
QModelIndex parent;
|
||||||
@ -1239,25 +1248,14 @@ UINT8 FfsEngine::insert(const QModelIndex & index, const QByteArray & object, co
|
|||||||
TreeItem * parentItem = static_cast<TreeItem*>(parent.internalPointer());
|
TreeItem * parentItem = static_cast<TreeItem*>(parent.internalPointer());
|
||||||
if (parentItem->type() == TreeItem::File || (parentItem->type() == TreeItem::Section &&
|
if (parentItem->type() == TreeItem::File || (parentItem->type() == TreeItem::Section &&
|
||||||
(parentItem->subtype() == EFI_SECTION_COMPRESSION ||
|
(parentItem->subtype() == EFI_SECTION_COMPRESSION ||
|
||||||
parentItem->subtype() == EFI_SECTION_GUID_DEFINED ||
|
parentItem->subtype() == EFI_SECTION_GUID_DEFINED ||
|
||||||
parentItem->subtype() == EFI_SECTION_DISPOSABLE))) {
|
parentItem->subtype() == EFI_SECTION_DISPOSABLE))) {
|
||||||
QModelIndex volumeIndex = findParentOfType(TreeItem::Volume, parent);
|
|
||||||
if (!volumeIndex.isValid()) {
|
|
||||||
msg(tr("insert: Parent volume not found"), parent);
|
|
||||||
return ERR_INVALID_VOLUME;
|
|
||||||
}
|
|
||||||
|
|
||||||
TreeItem * volumeItem = static_cast<TreeItem*>(volumeIndex.internalPointer());
|
|
||||||
EFI_FIRMWARE_VOLUME_HEADER* header = (EFI_FIRMWARE_VOLUME_HEADER*) volumeItem->header().constData();
|
|
||||||
|
|
||||||
// Parse section
|
// Parse section
|
||||||
UINT8 result = parseSection(object, header->Revision, header->Attributes & EFI_FVB_ERASE_POLARITY ? '\xFF' : '\x00', index, mode);
|
UINT8 result = parseSection(object, index, mode);
|
||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
|
// Set rebuild action for parent
|
||||||
// Set reconstruct action for all parents
|
treeModel->setItemAction(TreeItem::Rebuild, parent);
|
||||||
for (;parent.isValid(); parent = parent.parent())
|
|
||||||
treeModel->setItemAction(TreeItem::Reconstruct, parent);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
msg(tr("insert: section can't be inserted into something that is not file or encapsulation section"), parent);
|
msg(tr("insert: section can't be inserted into something that is not file or encapsulation section"), parent);
|
||||||
@ -1278,9 +1276,27 @@ UINT8 FfsEngine::remove(const QModelIndex & index)
|
|||||||
// Set action for the item
|
// Set action for the item
|
||||||
treeModel->setItemAction(TreeItem::Remove, index);
|
treeModel->setItemAction(TreeItem::Remove, index);
|
||||||
|
|
||||||
// Set reconstruct action for all it's parents
|
return ERR_SUCCESS;
|
||||||
for (QModelIndex parent = index.parent(); parent.isValid(); parent = parent.parent())
|
}
|
||||||
treeModel->setItemAction(TreeItem::Reconstruct, parent);
|
|
||||||
|
UINT8 FfsEngine::rebuild(const QModelIndex & index)
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return ERR_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
// Set action for the item
|
||||||
|
treeModel->setItemAction(TreeItem::Rebuild, index);
|
||||||
|
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT8 FfsEngine::changeCompression(const QModelIndex & index, const UINT8 algorithm)
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return ERR_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
// Set action for the item
|
||||||
|
treeModel->setItemCompression(algorithm, index);
|
||||||
|
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -1512,21 +1528,26 @@ UINT8 FfsEngine::reconstructImage(QByteArray & reconstructed)
|
|||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT8 FfsEngine::constructPadFile(const UINT32 size, const UINT8 revision, const char empty, QByteArray & pad)
|
UINT8 FfsEngine::constructPadFile(const UINT32 size, const UINT8 revision, const UINT8 erasePolarity, QByteArray & pad)
|
||||||
{
|
{
|
||||||
if (size < sizeof(EFI_FFS_FILE_HEADER))
|
if (size < sizeof(EFI_FFS_FILE_HEADER) || erasePolarity == ERASE_POLARITY_UNKNOWN)
|
||||||
return ERR_INVALID_PARAMETER;
|
return ERR_INVALID_PARAMETER;
|
||||||
|
|
||||||
pad = QByteArray(size, empty);
|
pad = QByteArray(size, erasePolarity == ERASE_POLARITY_TRUE ? '\xFF' : '\x00');
|
||||||
EFI_FFS_FILE_HEADER* header = (EFI_FFS_FILE_HEADER*) pad.data();
|
EFI_FFS_FILE_HEADER* header = (EFI_FFS_FILE_HEADER*) pad.data();
|
||||||
uint32ToUint24(size, header->Size);
|
uint32ToUint24(size, header->Size);
|
||||||
header->Attributes = 0x00;
|
header->Attributes = 0x00;
|
||||||
header->Type = EFI_FV_FILETYPE_PAD;
|
header->Type = EFI_FV_FILETYPE_PAD;
|
||||||
header->State = 0xF8; //TODO: Check state of pad file in section with empty = 0x00
|
header->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
|
||||||
|
// Invert state bits if erase polarity is true
|
||||||
|
if (erasePolarity == ERASE_POLARITY_TRUE)
|
||||||
|
header->State = ~header->State;
|
||||||
|
|
||||||
// Calculate header checksum
|
// Calculate header checksum
|
||||||
header->IntegrityCheck.Checksum.Header = 0;
|
header->IntegrityCheck.Checksum.Header = 0;
|
||||||
header->IntegrityCheck.Checksum.File = 0;
|
header->IntegrityCheck.Checksum.File = 0;
|
||||||
header->IntegrityCheck.Checksum.Header = calculateChecksum8((UINT8*) header, sizeof(EFI_FFS_FILE_HEADER) - 1);
|
header->IntegrityCheck.Checksum.Header = calculateChecksum8((UINT8*) header, sizeof(EFI_FFS_FILE_HEADER) - 1);
|
||||||
|
|
||||||
// Set data checksum
|
// Set data checksum
|
||||||
if (revision == 1)
|
if (revision == 1)
|
||||||
header->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
|
header->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
|
||||||
@ -1536,14 +1557,17 @@ UINT8 FfsEngine::constructPadFile(const UINT32 size, const UINT8 revision, const
|
|||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & queue, const UINT8 revision, char empty)
|
UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & queue, const UINT8 revision, const UINT8 erasePolarity)
|
||||||
{
|
{
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
|
|
||||||
|
TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
|
||||||
|
if (item == rootItem)
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
|
||||||
QByteArray reconstructed;
|
QByteArray reconstructed;
|
||||||
UINT8 result;
|
UINT8 result;
|
||||||
TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
|
|
||||||
|
|
||||||
// No action is needed, just return header + body
|
// No action is needed, just return header + body
|
||||||
if (item->action() == TreeItem::NoAction) {
|
if (item->action() == TreeItem::NoAction) {
|
||||||
@ -1553,13 +1577,10 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
|||||||
}
|
}
|
||||||
// Remove item
|
// Remove item
|
||||||
else if (item->action() == TreeItem::Remove) {
|
else if (item->action() == TreeItem::Remove) {
|
||||||
// Root item can't be removed
|
|
||||||
if (item == rootItem)
|
|
||||||
return ERR_INVALID_PARAMETER;
|
|
||||||
// Volume can be removed by replacing all it's contents with empty bytes
|
// Volume can be removed by replacing all it's contents with empty bytes
|
||||||
if (item->type() == TreeItem::Volume) {
|
if (item->type() == TreeItem::Volume) {
|
||||||
EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*) item->header().constData();
|
EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*) item->header().constData();
|
||||||
empty = volumeHeader->Attributes & EFI_FVB_ERASE_POLARITY ? '\xFF' : '\x00';
|
char empty = volumeHeader->Attributes & EFI_FVB_ERASE_POLARITY ? '\xFF' : '\x00';
|
||||||
reconstructed.fill(empty, item->header().size() + item->body().size() + item->tail().size());
|
reconstructed.fill(empty, item->header().size() + item->body().size() + item->tail().size());
|
||||||
queue.enqueue(reconstructed);
|
queue.enqueue(reconstructed);
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
@ -1567,7 +1588,7 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
|||||||
// File can be removed
|
// File can be removed
|
||||||
if (item->type() == TreeItem::File)
|
if (item->type() == TreeItem::File)
|
||||||
// Add nothing to queue
|
// Add nothing to queue
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
// Section can be removed
|
// Section can be removed
|
||||||
else if (item->type() == TreeItem::Section)
|
else if (item->type() == TreeItem::Section)
|
||||||
// Add nothing to queue
|
// Add nothing to queue
|
||||||
@ -1577,7 +1598,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::Reconstruct) {
|
else if (item->action() == TreeItem::Rebuild) {
|
||||||
QQueue<QByteArray> childrenQueue;
|
QQueue<QByteArray> childrenQueue;
|
||||||
|
|
||||||
switch (item->type()) {
|
switch (item->type()) {
|
||||||
@ -1608,6 +1629,7 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
|||||||
|
|
||||||
UINT32 offset = descriptor.size();
|
UINT32 offset = descriptor.size();
|
||||||
// Reconstruct other regions
|
// Reconstruct other regions
|
||||||
|
char empty = '\xFF'; //!TODO: determine empty char using one of reserved descriptor fields
|
||||||
for (int i = 1; i < item->childCount(); i++) {
|
for (int i = 1; i < item->childCount(); i++) {
|
||||||
result = reconstruct(index.child(i, index.column()), childrenQueue);
|
result = reconstruct(index.child(i, index.column()), childrenQueue);
|
||||||
if (result)
|
if (result)
|
||||||
@ -1637,7 +1659,7 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
|||||||
break;
|
break;
|
||||||
case TreeItem::PdrRegion:
|
case TreeItem::PdrRegion:
|
||||||
pdr = childrenQueue.dequeue();
|
pdr = childrenQueue.dequeue();
|
||||||
if (pdrBegin > offset)
|
if (pdrBegin > offset)
|
||||||
reconstructed.append(QByteArray(pdrBegin - offset, empty));
|
reconstructed.append(QByteArray(pdrBegin - offset, empty));
|
||||||
reconstructed.append(pdr);
|
reconstructed.append(pdr);
|
||||||
offset = pdrEnd;
|
offset = pdrEnd;
|
||||||
@ -1650,6 +1672,7 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
|||||||
if ((UINT32)item->body().size() > offset)
|
if ((UINT32)item->body().size() > offset)
|
||||||
reconstructed.append(QByteArray((UINT32)item->body().size() - offset, empty));
|
reconstructed.append(QByteArray((UINT32)item->body().size() - offset, empty));
|
||||||
|
|
||||||
|
// Check size of reconstructed image, it must be same
|
||||||
if (reconstructed.size() > item->body().size()) {
|
if (reconstructed.size() > item->body().size()) {
|
||||||
msg(tr("reconstruct: reconstructed body %1 is bigger then original %2")
|
msg(tr("reconstruct: reconstructed body %1 is bigger then original %2")
|
||||||
.arg(reconstructed.size(), 8, 16, QChar('0'))
|
.arg(reconstructed.size(), 8, 16, QChar('0'))
|
||||||
@ -1690,7 +1713,7 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
|||||||
else
|
else
|
||||||
reconstructed = item->body();
|
reconstructed = item->body();
|
||||||
|
|
||||||
// Check size of reconstructed image, it must be the same
|
// Check size of reconstructed image, it must be same
|
||||||
if (item->type() != TreeItem::Root) {
|
if (item->type() != TreeItem::Root) {
|
||||||
if (reconstructed.size() > item->body().size()) {
|
if (reconstructed.size() > item->body().size()) {
|
||||||
msg(tr("reconstructed: reconstructed body %1 is bigger then original %2")
|
msg(tr("reconstructed: reconstructed body %1 is bigger then original %2")
|
||||||
@ -1715,14 +1738,21 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
|||||||
{
|
{
|
||||||
//!TODO: add check for weak aligned volumes
|
//!TODO: add check for weak aligned volumes
|
||||||
QByteArray header = item->header();
|
QByteArray header = item->header();
|
||||||
EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*) header.constData();
|
EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*) header.data();
|
||||||
empty = volumeHeader->Attributes & EFI_FVB_ERASE_POLARITY ? '\xFF' : '\x00';
|
|
||||||
|
// Recalculate volume header checksum
|
||||||
|
volumeHeader->Checksum = 0;
|
||||||
|
volumeHeader->Checksum = calculateChecksum16((UINT8*) volumeHeader, volumeHeader->HeaderLength);
|
||||||
|
|
||||||
// Reconstruct volume body
|
// Reconstruct volume body
|
||||||
if (item->childCount()) {
|
if (item->childCount()) {
|
||||||
|
UINT8 polarity = volumeHeader->Attributes & EFI_FVB_ERASE_POLARITY ? ERASE_POLARITY_TRUE : ERASE_POLARITY_FALSE;
|
||||||
|
char empty = volumeHeader->Attributes & EFI_FVB_ERASE_POLARITY ? '\xFF' : '\x00';
|
||||||
|
|
||||||
// Reconstruct files in volume
|
// Reconstruct files in volume
|
||||||
for (int i = 0; i < item->childCount(); i++) {
|
for (int i = 0; i < item->childCount(); i++) {
|
||||||
// Reconstruct files
|
// Reconstruct files
|
||||||
result = reconstruct(index.child(i, index.column()), childrenQueue, volumeHeader->Revision, empty);
|
result = reconstruct(index.child(i, index.column()), childrenQueue, volumeHeader->Revision, polarity);
|
||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -1773,7 +1803,7 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
|||||||
}
|
}
|
||||||
// Construct pad file
|
// Construct pad file
|
||||||
QByteArray pad;
|
QByteArray pad;
|
||||||
result = constructPadFile(size, revision, empty, pad);
|
result = constructPadFile(size, revision, polarity, pad);
|
||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
// Append constructed pad file to volume body
|
// Append constructed pad file to volume body
|
||||||
@ -1799,7 +1829,7 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
|||||||
UINT32 size = vtfOffset - offset;
|
UINT32 size = vtfOffset - offset;
|
||||||
// Construct pad file
|
// Construct pad file
|
||||||
QByteArray pad;
|
QByteArray pad;
|
||||||
result = constructPadFile(size, revision, empty, pad);
|
result = constructPadFile(size, revision, polarity, pad);
|
||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
// Append constructed pad file to volume body
|
// Append constructed pad file to volume body
|
||||||
@ -1828,7 +1858,7 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
|||||||
}
|
}
|
||||||
// Construct pad file
|
// Construct pad file
|
||||||
QByteArray pad;
|
QByteArray pad;
|
||||||
result = constructPadFile(vtfOffset - offset, revision, empty, pad);
|
result = constructPadFile(vtfOffset - offset, revision, polarity, pad);
|
||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
// Append constructed pad file to volume body
|
// Append constructed pad file to volume body
|
||||||
@ -1891,6 +1921,59 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
|||||||
QByteArray header = item->header();
|
QByteArray header = item->header();
|
||||||
EFI_FFS_FILE_HEADER* fileHeader = (EFI_FFS_FILE_HEADER*) header.data();
|
EFI_FFS_FILE_HEADER* fileHeader = (EFI_FFS_FILE_HEADER*) header.data();
|
||||||
|
|
||||||
|
// Check erase polarity
|
||||||
|
if (erasePolarity == ERASE_POLARITY_UNKNOWN) {
|
||||||
|
msg(tr("reconstruct: %1, unknown erase polarity").arg(guidToQString(fileHeader->Name)), index);
|
||||||
|
return ERR_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct empty char for this file
|
||||||
|
char empty = erasePolarity == ERASE_POLARITY_TRUE ? '\xFF' : '\x00';
|
||||||
|
|
||||||
|
// Check file state
|
||||||
|
// Invert it first if erase polarity is true
|
||||||
|
UINT8 state = fileHeader->State;
|
||||||
|
if (erasePolarity == ERASE_POLARITY_TRUE)
|
||||||
|
state = ~state;
|
||||||
|
|
||||||
|
// Order of this checks must be preserved
|
||||||
|
// Check file to have valid state, or delete it otherwise
|
||||||
|
if (state & EFI_FILE_HEADER_INVALID) {
|
||||||
|
// File marked to have invalid header and must be deleted
|
||||||
|
// Do not add anything to queue
|
||||||
|
msg(tr("reconstruct: %1, file is HEADER_INVALID state, and will be removed from reconstructed image")
|
||||||
|
.arg(guidToQString(fileHeader->Name)), index);
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
else if (state & EFI_FILE_DELETED) {
|
||||||
|
// File marked to have been deleted form and must be deleted
|
||||||
|
// Do not add anything to queue
|
||||||
|
msg(tr("reconstruct: %1, file is in DELETED state, and will be removed from reconstructed image")
|
||||||
|
.arg(guidToQString(fileHeader->Name)), index);
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
else if (state & EFI_FILE_MARKED_FOR_UPDATE) {
|
||||||
|
// File is marked for update, the mark must be removed
|
||||||
|
msg(tr("reconstruct: %1, file MARKED_FOR_UPDATE state cleared")
|
||||||
|
.arg(guidToQString(fileHeader->Name)), index);
|
||||||
|
state &= ~EFI_FILE_MARKED_FOR_UPDATE;
|
||||||
|
}
|
||||||
|
else if (state & EFI_FILE_DATA_VALID) {
|
||||||
|
// File is in good condition, reconstruct it
|
||||||
|
}
|
||||||
|
else if (state & EFI_FILE_HEADER_VALID) {
|
||||||
|
// Header is valid, but data is not, so file must be deleted
|
||||||
|
msg(tr("reconstruct: %1, file is in HEADER_VALID (but not in DATA_VALID) state, and will be removed from reconstructed image")
|
||||||
|
.arg(guidToQString(fileHeader->Name)), index);
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
else if (state & EFI_FILE_HEADER_CONSTRUCTION) {
|
||||||
|
// Header construction not finished, so file must be deleted
|
||||||
|
msg(tr("reconstruct: %1, file is in HEADER_CONSTRUCTION (but not in DATA_VALID) state, and will be removed from reconstructed image")
|
||||||
|
.arg(guidToQString(fileHeader->Name)), index);
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
// Reconstruct file body
|
// Reconstruct file body
|
||||||
if (item->childCount()) {
|
if (item->childCount()) {
|
||||||
for (int i = 0; i < item->childCount(); i++) {
|
for (int i = 0; i < item->childCount(); i++) {
|
||||||
@ -1931,22 +2014,28 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
|||||||
fileHeader->IntegrityCheck.Checksum.File = 0;
|
fileHeader->IntegrityCheck.Checksum.File = 0;
|
||||||
fileHeader->IntegrityCheck.Checksum.Header = calculateChecksum8((UINT8*) fileHeader, sizeof(EFI_FFS_FILE_HEADER) - 1);
|
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*) reconstructed.constData(), reconstructed.size());
|
|
||||||
}
|
|
||||||
else if (revision == 1)
|
|
||||||
fileHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
|
|
||||||
else
|
|
||||||
fileHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM2;
|
|
||||||
|
|
||||||
// Append tail, if needed
|
|
||||||
if (tailSize)
|
|
||||||
reconstructed.append(!fileHeader->IntegrityCheck.TailReference);
|
|
||||||
}
|
}
|
||||||
// Use current file body and tail
|
// Use current file body
|
||||||
else
|
else
|
||||||
reconstructed = item->body().append(item->tail());
|
reconstructed = item->body();
|
||||||
|
|
||||||
|
// Recalculate data checksum, if needed
|
||||||
|
if (fileHeader->Attributes & FFS_ATTRIB_CHECKSUM) {
|
||||||
|
fileHeader->IntegrityCheck.Checksum.File = calculateChecksum8((UINT8*) reconstructed.constData(), reconstructed.size());
|
||||||
|
}
|
||||||
|
else if (revision == 1)
|
||||||
|
fileHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
|
||||||
|
else
|
||||||
|
fileHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM2;
|
||||||
|
|
||||||
|
// Append tail, if needed
|
||||||
|
if (!item->hasEmptyTail())
|
||||||
|
reconstructed.append(!fileHeader->IntegrityCheck.TailReference);
|
||||||
|
|
||||||
|
// Set file state
|
||||||
|
state = EFI_FILE_DATA_VALID | EFI_FILE_HEADER_VALID | EFI_FILE_HEADER_CONSTRUCTION;
|
||||||
|
if (erasePolarity == ERASE_POLARITY_TRUE)
|
||||||
|
state = ~state;
|
||||||
|
|
||||||
// Enqueue reconstructed item
|
// Enqueue reconstructed item
|
||||||
queue.enqueue(header.append(reconstructed));
|
queue.enqueue(header.append(reconstructed));
|
||||||
@ -1963,7 +2052,7 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
|||||||
// Reconstruct section body
|
// Reconstruct section body
|
||||||
for (int i = 0; i < item->childCount(); i++) {
|
for (int i = 0; i < item->childCount(); i++) {
|
||||||
// Reconstruct subsections
|
// Reconstruct subsections
|
||||||
result = reconstruct(index.child(i, index.column()), childrenQueue, revision, empty);
|
result = reconstruct(index.child(i, index.column()), childrenQueue);
|
||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -1977,7 +2066,7 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
|||||||
if (alignment) {
|
if (alignment) {
|
||||||
alignment = 4 - alignment;
|
alignment = 4 - alignment;
|
||||||
offset += alignment;
|
offset += alignment;
|
||||||
reconstructed.append(QByteArray(alignment, empty));
|
reconstructed.append(QByteArray(alignment, '\x00'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get section from queue
|
// Get section from queue
|
||||||
@ -1985,6 +2074,7 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
|||||||
|
|
||||||
// Append current subsection to new section body
|
// Append current subsection to new section body
|
||||||
reconstructed.append(section);
|
reconstructed.append(section);
|
||||||
|
|
||||||
// Change current file offset
|
// Change current file offset
|
||||||
offset += section.size();
|
offset += section.size();
|
||||||
}
|
}
|
||||||
@ -2049,6 +2139,65 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
|
|||||||
|
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
/*// Compress object with new compression algorithm
|
||||||
|
else if (item->action() == TreeItem::EfiCompress || item->action() == TreeItem::TianoCompress || item->action() == TreeItem::LzmaCompress) {
|
||||||
|
// Select algorithm
|
||||||
|
UINT8 algorithm;
|
||||||
|
if (item->action() == TreeItem::EfiCompress)
|
||||||
|
algorithm = COMPRESSION_ALGORITHM_EFI11;
|
||||||
|
else if (item->action() == TreeItem::TianoCompress)
|
||||||
|
algorithm = COMPRESSION_ALGORITHM_TIANO;
|
||||||
|
else if (item->action() == TreeItem::LzmaCompress)
|
||||||
|
algorithm = COMPRESSION_ALGORITHM_LZMA;
|
||||||
|
else
|
||||||
|
return ERR_UNKNOWN_COMPRESSION_ALGORITHM;
|
||||||
|
|
||||||
|
// Possible only for compressed sections with EFI1.1, Tiano or LZMA algorithm
|
||||||
|
if (item->type() == TreeItem::Section && item->subtype() == EFI_SECTION_COMPRESSION &&
|
||||||
|
(item->compression() == COMPRESSION_ALGORITHM_EFI11 || item->compression() == COMPRESSION_ALGORITHM_TIANO || item->compression() == COMPRESSION_ALGORITHM_LZMA)) {
|
||||||
|
QByteArray header = item->header();
|
||||||
|
EFI_COMPRESSION_SECTION* sectionHeader = (EFI_COMPRESSION_SECTION*) header.data();
|
||||||
|
if (!item->childCount())
|
||||||
|
return ERR_INVALID_SECTION;
|
||||||
|
|
||||||
|
QQueue<QByteArray> childrenQueue;
|
||||||
|
for (int i = 0; i < item->childCount(); i++) {
|
||||||
|
// Reconstruct subsections
|
||||||
|
result = reconstruct(index.child(i, index.column()), childrenQueue);
|
||||||
|
if (result)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct new section body
|
||||||
|
UINT32 offset = 0;
|
||||||
|
while (!childrenQueue.isEmpty())
|
||||||
|
{
|
||||||
|
// Align to 4 byte boundary
|
||||||
|
UINT8 alignment = offset % 4;
|
||||||
|
if (alignment) {
|
||||||
|
alignment = 4 - alignment;
|
||||||
|
offset += alignment;
|
||||||
|
reconstructed.append(QByteArray(alignment, '\x00'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get section from queue
|
||||||
|
QByteArray section = childrenQueue.dequeue();
|
||||||
|
|
||||||
|
// Append current subsection to new section body
|
||||||
|
reconstructed.append(section);
|
||||||
|
|
||||||
|
// Change current file offset
|
||||||
|
offset += section.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compress new section body using determined compression algorithm
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return ERR_NOT_IMPLEMENTED;
|
||||||
|
|
||||||
|
}*/
|
||||||
|
|
||||||
return ERR_NOT_IMPLEMENTED;
|
return ERR_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
@ -2093,82 +2242,82 @@ UINT8 FfsEngine::growVolume(QByteArray & header, const UINT32 size, UINT32 & new
|
|||||||
// Will be refactored later
|
// Will be refactored later
|
||||||
/*QByteArray FfsEngine::decompressFile(const QModelIndex& index) const
|
/*QByteArray FfsEngine::decompressFile(const QModelIndex& index) const
|
||||||
{
|
{
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
return QByteArray();
|
return QByteArray();
|
||||||
|
|
||||||
// Check index item to be FFS file
|
// Check index item to be FFS file
|
||||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||||
if(item->type() != TreeItem::File)
|
if(item->type() != TreeItem::File)
|
||||||
return QByteArray();
|
return QByteArray();
|
||||||
|
|
||||||
QByteArray file;
|
QByteArray file;
|
||||||
UINT32 offset = 0;
|
UINT32 offset = 0;
|
||||||
// Construct new item body
|
// Construct new item body
|
||||||
for (int i = 0; i < item->childCount(); i++) {
|
for (int i = 0; i < item->childCount(); i++) {
|
||||||
// If section is not compressed, add it to new body as is
|
// If section is not compressed, add it to new body as is
|
||||||
TreeItem* sectionItem = item->child(i);
|
TreeItem* sectionItem = item->child(i);
|
||||||
if (sectionItem->subtype() != EFI_SECTION_COMPRESSION) {
|
if (sectionItem->subtype() != EFI_SECTION_COMPRESSION) {
|
||||||
QByteArray section = sectionItem->header().append(sectionItem->body());
|
QByteArray section = sectionItem->header().append(sectionItem->body());
|
||||||
UINT32 align = ALIGN4(offset) - offset;
|
UINT32 align = ALIGN4(offset) - offset;
|
||||||
file.append(QByteArray(align, '\x00')).append(section);
|
file.append(QByteArray(align, '\x00')).append(section);
|
||||||
offset += align + section.size();
|
offset += align + section.size();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Construct new section body by adding all child sections to this new section
|
// Construct new section body by adding all child sections to this new section
|
||||||
QByteArray section;
|
QByteArray section;
|
||||||
UINT32 subOffset = 0;
|
UINT32 subOffset = 0;
|
||||||
for (int j = 0; j < sectionItem->childCount(); j++)
|
for (int j = 0; j < sectionItem->childCount(); j++)
|
||||||
{
|
{
|
||||||
TreeItem* subSectionItem = sectionItem->child(j);
|
TreeItem* subSectionItem = sectionItem->child(j);
|
||||||
QByteArray subSection = subSectionItem->header().append(subSectionItem->body());
|
QByteArray subSection = subSectionItem->header().append(subSectionItem->body());
|
||||||
UINT32 align = ALIGN4(subOffset) - subOffset;
|
UINT32 align = ALIGN4(subOffset) - subOffset;
|
||||||
section.append(QByteArray(align, '\x00')).append(subSection);
|
section.append(QByteArray(align, '\x00')).append(subSection);
|
||||||
subOffset += align + subSection.size();
|
subOffset += align + subSection.size();
|
||||||
}
|
}
|
||||||
// Add newly constructed section to file body
|
// Add newly constructed section to file body
|
||||||
|
|
||||||
EFI_COMPRESSION_SECTION sectionHeader;
|
EFI_COMPRESSION_SECTION sectionHeader;
|
||||||
sectionHeader.Type = EFI_SECTION_COMPRESSION;
|
sectionHeader.Type = EFI_SECTION_COMPRESSION;
|
||||||
sectionHeader.CompressionType = EFI_NOT_COMPRESSED;
|
sectionHeader.CompressionType = EFI_NOT_COMPRESSED;
|
||||||
sectionHeader.UncompressedLength = section.size();
|
sectionHeader.UncompressedLength = section.size();
|
||||||
uint32ToUint24(section.size() + sizeof(EFI_COMPRESSION_SECTION), sectionHeader.Size);
|
uint32ToUint24(section.size() + sizeof(EFI_COMPRESSION_SECTION), sectionHeader.Size);
|
||||||
UINT32 align = ALIGN4(offset) - offset;
|
UINT32 align = ALIGN4(offset) - offset;
|
||||||
file.append(QByteArray(align, '\x00'))
|
file.append(QByteArray(align, '\x00'))
|
||||||
.append(QByteArray((const char*) §ionHeader, sizeof(EFI_COMPRESSION_SECTION)))
|
.append(QByteArray((const char*) §ionHeader, sizeof(EFI_COMPRESSION_SECTION)))
|
||||||
.append(section);
|
.append(section);
|
||||||
offset += align + section.size();
|
offset += align + section.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray header = item->header();
|
QByteArray header = item->header();
|
||||||
EFI_FFS_FILE_HEADER* fileHeader = (EFI_FFS_FILE_HEADER*) header.data();
|
EFI_FFS_FILE_HEADER* fileHeader = (EFI_FFS_FILE_HEADER*) header.data();
|
||||||
|
|
||||||
// Correct file data checksum, if needed
|
// Correct file data checksum, if needed
|
||||||
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);
|
||||||
fileHeader->IntegrityCheck.Checksum.File = calculateChecksum8((UINT8*)(file.data() + sizeof(EFI_FFS_FILE_HEADER)), bufferSize);
|
fileHeader->IntegrityCheck.Checksum.File = calculateChecksum8((UINT8*)(file.data() + sizeof(EFI_FFS_FILE_HEADER)), bufferSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add file tail, if needed
|
// Add file tail, if needed
|
||||||
if(fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT)
|
if(fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT)
|
||||||
file.append(!fileHeader->IntegrityCheck.TailReference);
|
file.append(!fileHeader->IntegrityCheck.TailReference);
|
||||||
|
|
||||||
return header.append(file);
|
return header.append(file);
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
/*bool FfsEngine::isCompressedFile(const QModelIndex& index) const
|
/*bool FfsEngine::isCompressedFile(const QModelIndex& index) const
|
||||||
{
|
{
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||||
if(item->type() != TreeItem::File)
|
if(item->type() != TreeItem::File)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (int i = 0; i < item->childCount(); i++) {
|
for (int i = 0; i < item->childCount(); i++) {
|
||||||
if (item->child(i)->subtype() == EFI_SECTION_COMPRESSION)
|
if (item->child(i)->subtype() == EFI_SECTION_COMPRESSION)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}*/
|
}*/
|
||||||
|
12
ffsengine.h
12
ffsengine.h
@ -52,10 +52,10 @@ public:
|
|||||||
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, const QModelIndex & parent = QModelIndex(), const UINT8 mode = INSERT_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 char empty = '\xFF', const QModelIndex & parent = QModelIndex(), const UINT8 mode = INSERT_MODE_APPEND);
|
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 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 UINT8 revision, const char empty = '\xFF', const QModelIndex & parent = QModelIndex());
|
UINT8 parseSections(const QByteArray & body, const QModelIndex & parent = QModelIndex());
|
||||||
UINT8 parseSection(const QByteArray & section, const UINT8 revision, const char empty = '\xFF', const QModelIndex & parent = QModelIndex(), const UINT8 mode = INSERT_MODE_APPEND);
|
UINT8 parseSection(const QByteArray & section, const QModelIndex & parent = QModelIndex(), const UINT8 mode = INSERT_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);
|
||||||
@ -63,14 +63,16 @@ public:
|
|||||||
|
|
||||||
// Construction routines
|
// Construction routines
|
||||||
UINT8 reconstructImage(QByteArray & reconstructed);
|
UINT8 reconstructImage(QByteArray & reconstructed);
|
||||||
UINT8 constructPadFile(const UINT32 size, const UINT8 revision, const char empty, QByteArray & pad);
|
UINT8 constructPadFile(const UINT32 size, const UINT8 revision, const UINT8 erasePolarity, QByteArray & pad);
|
||||||
UINT8 reconstruct(const QModelIndex & index, QQueue<QByteArray> & queue, const UINT8 revision = 2, char empty = '\xFF');
|
UINT8 reconstruct(const QModelIndex & index, QQueue<QByteArray> & queue, const UINT8 revision = 2, const UINT8 erasePolarity = ERASE_POLARITY_UNKNOWN);
|
||||||
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 insert(const QModelIndex & index, const QByteArray & object, const UINT8 objectType, const UINT8 mode);
|
||||||
UINT8 remove(const QModelIndex & index);
|
UINT8 remove(const QModelIndex & index);
|
||||||
|
UINT8 rebuild(const QModelIndex & index);
|
||||||
|
UINT8 changeCompression(const QModelIndex & index, const UINT8 algorithm);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TreeItem *rootItem;
|
TreeItem *rootItem;
|
||||||
|
16
treeitem.cpp
16
treeitem.cpp
@ -174,7 +174,7 @@ QVariant TreeItem::data(int column) const
|
|||||||
case 1: //Action
|
case 1: //Action
|
||||||
if (itemAction == TreeItem::Remove)
|
if (itemAction == TreeItem::Remove)
|
||||||
return "X";
|
return "X";
|
||||||
if (itemAction == TreeItem::Reconstruct)
|
if (itemAction == TreeItem::Rebuild)
|
||||||
return "R";
|
return "R";
|
||||||
return QVariant();
|
return QVariant();
|
||||||
case 2: //Type
|
case 2: //Type
|
||||||
@ -261,7 +261,6 @@ QByteArray TreeItem::tail() const
|
|||||||
return itemTail;
|
return itemTail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool TreeItem::hasEmptyHeader() const
|
bool TreeItem::hasEmptyHeader() const
|
||||||
{
|
{
|
||||||
return itemHeader.isEmpty();
|
return itemHeader.isEmpty();
|
||||||
@ -281,7 +280,20 @@ UINT8 TreeItem::action() const
|
|||||||
{
|
{
|
||||||
return itemAction;
|
return itemAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TreeItem::setAction(const UINT8 action)
|
void TreeItem::setAction(const UINT8 action)
|
||||||
{
|
{
|
||||||
itemAction = action;
|
itemAction = action;
|
||||||
|
|
||||||
|
// Set rebuild action for parent
|
||||||
|
if (parentItem)
|
||||||
|
parentItem->setAction(TreeItem::Rebuild);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TreeItem::setCompression(const UINT8 algorithm)
|
||||||
|
{
|
||||||
|
itemCompression = algorithm;
|
||||||
|
|
||||||
|
// Set rebuild action
|
||||||
|
setAction(TreeItem::Rebuild);
|
||||||
}
|
}
|
@ -32,7 +32,7 @@ public:
|
|||||||
enum ActionTypes {
|
enum ActionTypes {
|
||||||
NoAction = 50,
|
NoAction = 50,
|
||||||
Remove,
|
Remove,
|
||||||
Reconstruct
|
Rebuild
|
||||||
};
|
};
|
||||||
|
|
||||||
// Item types
|
// Item types
|
||||||
@ -100,11 +100,13 @@ public:
|
|||||||
QByteArray tail() const;
|
QByteArray tail() const;
|
||||||
bool hasEmptyTail() const;
|
bool hasEmptyTail() const;
|
||||||
QString info() const;
|
QString info() const;
|
||||||
|
UINT8 action() const;
|
||||||
UINT8 compression() const;
|
UINT8 compression() const;
|
||||||
|
|
||||||
// Actions can also be changed
|
// Action can be changed
|
||||||
UINT8 action() const;
|
|
||||||
void setAction(const UINT8 action);
|
void setAction(const UINT8 action);
|
||||||
|
// Compression can be changed
|
||||||
|
void setCompression(const UINT8 algorithm);
|
||||||
|
|
||||||
// Text values can be changed after item construction
|
// Text values can be changed after item construction
|
||||||
void setTypeName(const QString &text);
|
void setTypeName(const QString &text);
|
||||||
@ -123,6 +125,7 @@ private:
|
|||||||
UINT8 itemType;
|
UINT8 itemType;
|
||||||
UINT8 itemSubtype;
|
UINT8 itemSubtype;
|
||||||
UINT8 itemCompression;
|
UINT8 itemCompression;
|
||||||
|
UINT8 itemNewCompression;
|
||||||
QByteArray itemHeader;
|
QByteArray itemHeader;
|
||||||
QByteArray itemBody;
|
QByteArray itemBody;
|
||||||
QByteArray itemTail;
|
QByteArray itemTail;
|
||||||
|
@ -148,7 +148,18 @@ UINT8 TreeModel::setItemAction(const UINT8 action, const QModelIndex &index)
|
|||||||
|
|
||||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||||
item->setAction(action);
|
item->setAction(action);
|
||||||
emit dataChanged(index, index);
|
emit dataChanged(this->index(0,0), index);
|
||||||
|
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;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,6 +44,7 @@ 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(),
|
||||||
|
83
uefitool.cpp
83
uefitool.cpp
@ -31,8 +31,14 @@ UEFITool::UEFITool(QWidget *parent) :
|
|||||||
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(replace()));
|
||||||
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->actionSaveImageFile, SIGNAL(triggered()), this, SLOT(saveImageFile()));
|
connect(ui->actionSaveImageFile, SIGNAL(triggered()), this, SLOT(saveImageFile()));
|
||||||
|
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->actionAbout, SIGNAL(triggered()), this, SLOT(about()));
|
||||||
|
connect(ui->actionAboutQt, SIGNAL(triggered()), this, SLOT(aboutQt()));
|
||||||
|
connect(ui->actionQuit, SIGNAL(triggered()), this, SLOT(exit()));
|
||||||
// Enable Drag-and-Drop actions
|
// Enable Drag-and-Drop actions
|
||||||
this->setAcceptDrops(true);
|
this->setAcceptDrops(true);
|
||||||
|
|
||||||
@ -58,6 +64,7 @@ void UEFITool::init()
|
|||||||
ui->actionExtractUncompressed->setDisabled(true);
|
ui->actionExtractUncompressed->setDisabled(true);
|
||||||
ui->actionReplace->setDisabled(true);
|
ui->actionReplace->setDisabled(true);
|
||||||
ui->actionRemove->setDisabled(true);
|
ui->actionRemove->setDisabled(true);
|
||||||
|
ui->actionRebuild->setDisabled(true);
|
||||||
ui->actionInsertInto->setDisabled(true);
|
ui->actionInsertInto->setDisabled(true);
|
||||||
ui->actionInsertBefore->setDisabled(true);
|
ui->actionInsertBefore->setDisabled(true);
|
||||||
ui->actionInsertAfter->setDisabled(true);
|
ui->actionInsertAfter->setDisabled(true);
|
||||||
@ -87,9 +94,11 @@ 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();
|
||||||
|
|
||||||
ui->infoEdit->setPlainText(item->info());
|
ui->infoEdit->setPlainText(item->info());
|
||||||
ui->actionExtract->setDisabled(item->hasEmptyHeader() && item->hasEmptyBody() && item->hasEmptyTail());
|
ui->actionExtract->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->actionExtractUncompressed->setEnabled(ffsEngine->isCompressedFile(current));
|
//ui->actionExtractUncompressed->setEnabled(ffsEngine->isCompressedFile(current));
|
||||||
ui->actionRemove->setEnabled(type == TreeItem::Volume || type == TreeItem::File || type == TreeItem::Section);
|
ui->actionRemove->setEnabled(type == TreeItem::Volume || type == TreeItem::File || type == TreeItem::Section);
|
||||||
@ -98,6 +107,26 @@ void UEFITool::populateUi(const QModelIndex ¤t)
|
|||||||
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->actionReplace->setEnabled(ffsEngine->isOfType(TreeItem::File, current));
|
//ui->actionReplace->setEnabled(ffsEngine->isOfType(TreeItem::File, current));
|
||||||
|
ui->actionChangeToEfi11->setEnabled(type == TreeItem::Section && subtype == EFI_SECTION_COMPRESSION &&
|
||||||
|
(algorithm == COMPRESSION_ALGORITHM_NONE || algorithm == COMPRESSION_ALGORITHM_TIANO || algorithm == COMPRESSION_ALGORITHM_LZMA));
|
||||||
|
ui->actionChangeToTiano->setEnabled(type == TreeItem::Section && subtype == EFI_SECTION_COMPRESSION &&
|
||||||
|
(algorithm == COMPRESSION_ALGORITHM_NONE || algorithm == COMPRESSION_ALGORITHM_EFI11 || algorithm == COMPRESSION_ALGORITHM_LZMA));
|
||||||
|
ui->actionChangeToLzma->setEnabled(type == TreeItem::Section && subtype == EFI_SECTION_COMPRESSION &&
|
||||||
|
(algorithm == COMPRESSION_ALGORITHM_NONE || algorithm == COMPRESSION_ALGORITHM_EFI11 || algorithm == COMPRESSION_ALGORITHM_TIANO));
|
||||||
|
ui->menuChangeCompressionTo->setEnabled(ui->actionChangeToEfi11->isEnabled() ||
|
||||||
|
ui->actionChangeToTiano->isEnabled() || ui->actionChangeToLzma->isEnabled());
|
||||||
|
}
|
||||||
|
|
||||||
|
void UEFITool::rebuild()
|
||||||
|
{
|
||||||
|
QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex();
|
||||||
|
if (!index.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
UINT8 result = ffsEngine->rebuild(index);
|
||||||
|
|
||||||
|
if (result == ERR_SUCCESS)
|
||||||
|
ui->actionSaveImageFile->setEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UEFITool::remove()
|
void UEFITool::remove()
|
||||||
@ -188,6 +217,58 @@ void UEFITool::replace()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UEFITool::changeToEfi11()
|
||||||
|
{
|
||||||
|
QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex();
|
||||||
|
if (!index.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
UINT8 result = ffsEngine->changeCompression(index, COMPRESSION_ALGORITHM_EFI11);
|
||||||
|
|
||||||
|
if (result == ERR_SUCCESS)
|
||||||
|
ui->actionSaveImageFile->setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UEFITool::changeToTiano()
|
||||||
|
{
|
||||||
|
QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex();
|
||||||
|
if (!index.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
UINT8 result = ffsEngine->changeCompression(index, COMPRESSION_ALGORITHM_TIANO);
|
||||||
|
if (result == ERR_SUCCESS)
|
||||||
|
ui->actionSaveImageFile->setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UEFITool::changeToLzma()
|
||||||
|
{
|
||||||
|
QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex();
|
||||||
|
if (!index.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
UINT8 result = ffsEngine->changeCompression(index, COMPRESSION_ALGORITHM_LZMA);
|
||||||
|
if (result == ERR_SUCCESS)
|
||||||
|
ui->actionSaveImageFile->setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UEFITool::about()
|
||||||
|
{
|
||||||
|
QMessageBox::about(this, tr("About UEFITool"), tr(
|
||||||
|
"Copyright (c) 2013, Nikolaj Schlej aka CodeRush.\n\n"
|
||||||
|
"The program is dedicated to RevoGirl. Rest in peace, young genius.\n\n"
|
||||||
|
"The program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License.\n"
|
||||||
|
"The full text of the license may be found at\nhttp://opensource.org/licenses/bsd-license.php\n\n"
|
||||||
|
"THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN \"AS IS\" BASIS,\n"
|
||||||
|
"WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND,\n"
|
||||||
|
"EITHER EXPRESS OR IMPLIED."
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
void UEFITool::aboutQt()
|
||||||
|
{
|
||||||
|
QMessageBox::aboutQt(this, tr("About Qt"));
|
||||||
|
}
|
||||||
|
|
||||||
void UEFITool::saveImageFile()
|
void UEFITool::saveImageFile()
|
||||||
{
|
{
|
||||||
QString path = QFileDialog::getSaveFileName(this, tr("Save BIOS image file"),".","BIOS image file (*.rom *.bin *.cap *.fd *.wph *.efi);;All files (*.*)");
|
QString path = QFileDialog::getSaveFileName(this, tr("Save BIOS image file"),".","BIOS image file (*.rom *.bin *.cap *.fd *.wph *.efi);;All files (*.*)");
|
||||||
|
@ -60,6 +60,12 @@ private slots:
|
|||||||
void insertAfter();
|
void insertAfter();
|
||||||
void replace();
|
void replace();
|
||||||
void remove();
|
void remove();
|
||||||
|
void rebuild();
|
||||||
|
void changeToEfi11();
|
||||||
|
void changeToTiano();
|
||||||
|
void changeToLzma();
|
||||||
|
void about();
|
||||||
|
void aboutQt();
|
||||||
void scrollTreeView(QListWidgetItem* item);
|
void scrollTreeView(QListWidgetItem* item);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
160
uefitool.ui
160
uefitool.ui
@ -20,7 +20,7 @@
|
|||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>UEFITool 0.8.1</string>
|
<string>UEFITool 0.9.0</string>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="centralWidget">
|
<widget class="QWidget" name="centralWidget">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
@ -183,6 +183,10 @@
|
|||||||
<addaction name="actionOpenImageFile"/>
|
<addaction name="actionOpenImageFile"/>
|
||||||
<addaction name="actionSaveImageFile"/>
|
<addaction name="actionSaveImageFile"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
|
<addaction name="actionRebuild"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
|
<addaction name="actionRemove"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
<addaction name="actionExtract"/>
|
<addaction name="actionExtract"/>
|
||||||
<addaction name="actionExtractBody"/>
|
<addaction name="actionExtractBody"/>
|
||||||
<addaction name="actionExtractUncompressed"/>
|
<addaction name="actionExtractUncompressed"/>
|
||||||
@ -192,22 +196,79 @@
|
|||||||
<addaction name="actionInsertAfter"/>
|
<addaction name="actionInsertAfter"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="actionReplace"/>
|
<addaction name="actionReplace"/>
|
||||||
<addaction name="separator"/>
|
</widget>
|
||||||
<addaction name="actionRemove"/>
|
<widget class="QMenuBar" name="menuBar">
|
||||||
<addaction name="separator"/>
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>1100</width>
|
||||||
|
<height>21</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<widget class="QMenu" name="menuFile">
|
||||||
|
<property name="title">
|
||||||
|
<string>&File</string>
|
||||||
|
</property>
|
||||||
|
<addaction name="actionOpenImageFile"/>
|
||||||
|
<addaction name="actionSaveImageFile"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
|
<addaction name="actionQuit"/>
|
||||||
|
</widget>
|
||||||
|
<widget class="QMenu" name="menuAction">
|
||||||
|
<property name="title">
|
||||||
|
<string>A&ction</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QMenu" name="menuChangeCompressionTo">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="title">
|
||||||
|
<string>Change &compression to</string>
|
||||||
|
</property>
|
||||||
|
<addaction name="actionChangeToTiano"/>
|
||||||
|
<addaction name="actionChangeToEfi11"/>
|
||||||
|
<addaction name="actionChangeToLzma"/>
|
||||||
|
</widget>
|
||||||
|
<addaction name="actionRebuild"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
|
<addaction name="actionRemove"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
|
<addaction name="actionExtract"/>
|
||||||
|
<addaction name="actionExtractBody"/>
|
||||||
|
<addaction name="actionExtractUncompressed"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
|
<addaction name="actionInsertInto"/>
|
||||||
|
<addaction name="actionInsertAfter"/>
|
||||||
|
<addaction name="actionInsertBefore"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
|
<addaction name="actionReplace"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
|
<addaction name="menuChangeCompressionTo"/>
|
||||||
|
</widget>
|
||||||
|
<widget class="QMenu" name="menuHelp">
|
||||||
|
<property name="title">
|
||||||
|
<string>H&elp</string>
|
||||||
|
</property>
|
||||||
|
<addaction name="actionAbout"/>
|
||||||
|
<addaction name="actionAboutQt"/>
|
||||||
|
</widget>
|
||||||
|
<addaction name="menuFile"/>
|
||||||
|
<addaction name="menuAction"/>
|
||||||
|
<addaction name="menuHelp"/>
|
||||||
</widget>
|
</widget>
|
||||||
<action name="actionInsertAfter">
|
<action name="actionInsertAfter">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Insert object after...</string>
|
<string>Insert &after...</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Insert an object from file after selected object</string>
|
<string>Insert an object from file after selected object</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="shortcut">
|
<property name="shortcut">
|
||||||
<string>Ctrl+I</string>
|
<string>Ctrl+Shift+I</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionInsertBefore">
|
<action name="actionInsertBefore">
|
||||||
@ -215,13 +276,13 @@
|
|||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Insert object before...</string>
|
<string>Insert &before...</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Insert object from file before selected object</string>
|
<string>Insert object from file before selected object</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="shortcut">
|
<property name="shortcut">
|
||||||
<string>Ctrl+Shift+I</string>
|
<string>Ctrl+Alt+I</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionReplace">
|
<action name="actionReplace">
|
||||||
@ -229,7 +290,7 @@
|
|||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Replace</string>
|
<string>Rep&lace</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Replace selected object with an object from file</string>
|
<string>Replace selected object with an object from file</string>
|
||||||
@ -243,7 +304,7 @@
|
|||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Extract as is...</string>
|
<string>E&xtract as is...</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Extract selected object as is to file</string>
|
<string>Extract selected object as is to file</string>
|
||||||
@ -257,7 +318,7 @@
|
|||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Extract without header...</string>
|
<string>Extract &without header...</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Extract selected object without header to file</string>
|
<string>Extract selected object without header to file</string>
|
||||||
@ -271,7 +332,7 @@
|
|||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Extract uncompressed...</string>
|
<string>Extract &uncompressed...</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Extract selected FFS file uncompressing it </string>
|
<string>Extract selected FFS file uncompressing it </string>
|
||||||
@ -285,7 +346,7 @@
|
|||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Remove</string>
|
<string>Re&move</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Remove selected object</string>
|
<string>Remove selected object</string>
|
||||||
@ -296,7 +357,7 @@
|
|||||||
</action>
|
</action>
|
||||||
<action name="actionOpenImageFile">
|
<action name="actionOpenImageFile">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Open image file...</string>
|
<string>&Open image file...</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Open image file</string>
|
<string>Open image file</string>
|
||||||
@ -310,13 +371,13 @@
|
|||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Insert object into...</string>
|
<string>Insert &into...</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Insert object from file into selected object</string>
|
<string>Insert object from file into selected object</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="shortcut">
|
<property name="shortcut">
|
||||||
<string>Ctrl+Ins</string>
|
<string>Ctrl+I</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionSaveImageFile">
|
<action name="actionSaveImageFile">
|
||||||
@ -324,7 +385,7 @@
|
|||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Save image file...</string>
|
<string>&Save image file...</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Save modified image file</string>
|
<string>Save modified image file</string>
|
||||||
@ -333,6 +394,71 @@
|
|||||||
<string>Ctrl+S</string>
|
<string>Ctrl+S</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionRebuild">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>&Rebuild</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Rebuild selected object</string>
|
||||||
|
</property>
|
||||||
|
<property name="shortcut">
|
||||||
|
<string>Ctrl+Space</string>
|
||||||
|
</property>
|
||||||
|
</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">
|
||||||
|
<property name="text">
|
||||||
|
<string>&About UEFITool</string>
|
||||||
|
</property>
|
||||||
|
<property name="shortcut">
|
||||||
|
<string>F1</string>
|
||||||
|
</property>
|
||||||
|
<property name="menuRole">
|
||||||
|
<enum>QAction::AboutRole</enum>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="actionAboutQt">
|
||||||
|
<property name="text">
|
||||||
|
<string>About &Qt</string>
|
||||||
|
</property>
|
||||||
|
<property name="menuRole">
|
||||||
|
<enum>QAction::AboutQtRole</enum>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="actionQuit">
|
||||||
|
<property name="text">
|
||||||
|
<string>&Quit</string>
|
||||||
|
</property>
|
||||||
|
<property name="menuRole">
|
||||||
|
<enum>QAction::QuitRole</enum>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<layoutdefault spacing="6" margin="11"/>
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
Loading…
Reference in New Issue
Block a user