Version 0.5.0

- Minor bugs corrected
- Implemented section insertion
- Replace temporary removed
This commit is contained in:
Nikolaj Schlej 2013-11-14 11:40:39 +01:00
parent 4a61fcd9d9
commit 6ff5119048
9 changed files with 190 additions and 161 deletions

View File

@ -93,11 +93,11 @@ typedef uint16_t CHAR16;
#define COMPRESSION_ALGORITHM_LZMA 4 #define COMPRESSION_ALGORITHM_LZMA 4
#define COMPRESSION_ALGORITHM_IMLZMA 5 #define COMPRESSION_ALGORITHM_IMLZMA 5
// Item add modes // Item insert modes
#define ADD_MODE_APPEND 0 #define INSERT_MODE_APPEND 0
#define ADD_MODE_PREPEND 1 #define INSERT_MODE_PREPEND 1
#define ADD_MODE_INSERT_BEFORE 2 #define INSERT_MODE_BEFORE 2
#define ADD_MODE_INSERT_AFTER 3 #define INSERT_MODE_AFTER 3
// EFI GUID // EFI GUID
typedef struct{ typedef struct{

View File

@ -372,11 +372,10 @@ 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 == ERR_VOLUMES_NOT_FOUND) {
{
//msg(tr("No volumes found in BIOS space"));
return result; return result;
} }
// First volume is not at the beginning of BIOS space // First volume is not at the beginning of BIOS space
QString name; QString name;
QString info; QString info;
@ -514,10 +513,23 @@ UINT8 FfsEngine::parseBios(const QByteArray & bios, const QModelIndex & parent)
prevVolumeSize = volumeSize; prevVolumeSize = volumeSize;
result = findNextVolume(bios, volumeOffset + prevVolumeSize, volumeOffset); result = findNextVolume(bios, volumeOffset + prevVolumeSize, volumeOffset);
if (result == ERR_VOLUMES_NOT_FOUND) if (result) {
UINT32 endPaddingSize = bios.size() - prevVolumeOffset - prevVolumeSize;
// Padding at the end of BIOS space
if (endPaddingSize > 0) {
QByteArray padding = bios.right(endPaddingSize);
// Get info
name = tr("Padding");
info = tr("Size: %2")
.arg(padding.size(), 8, 16, QChar('0'));
// Add tree item
treeModel->addItem(TreeItem::Padding, 0, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), padding, parent);
}
break; break;
} }
}
return ERR_SUCCESS; return ERR_SUCCESS;
} }
@ -576,7 +588,7 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, const QModelIndex & par
msg(tr("parseBios: Volume header checksum is invalid")); msg(tr("parseBios: Volume header checksum is invalid"));
} }
// Check for presence of extended header, only if header revision is not 1 // Check for presence of extended header, only if header revision is greater then 1
UINT32 headerSize; UINT32 headerSize;
if (volumeHeader->Revision > 1 && volumeHeader->ExtHeaderOffset) { if (volumeHeader->Revision > 1 && volumeHeader->ExtHeaderOffset) {
EFI_FIRMWARE_VOLUME_EXT_HEADER* extendedHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER*) ((UINT8*) volumeHeader + volumeHeader->ExtHeaderOffset); EFI_FIRMWARE_VOLUME_EXT_HEADER* extendedHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER*) ((UINT8*) volumeHeader + volumeHeader->ExtHeaderOffset);
@ -598,10 +610,16 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, const QModelIndex & par
QByteArray body = volume.mid(headerSize, volumeHeader->FvLength - headerSize); QByteArray body = volume.mid(headerSize, volumeHeader->FvLength - headerSize);
QModelIndex index = treeModel->addItem(TreeItem::Volume, 0, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, parent, mode); QModelIndex index = treeModel->addItem(TreeItem::Volume, 0, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, parent, mode);
// Do not parse volumes with unknown FS
if (!parseCurrentVolume)
return ERR_SUCCESS;
// Search for and parse all files // Search for and parse all files
UINT32 fileOffset = headerSize; UINT32 fileOffset = headerSize;
UINT32 fileSize; UINT32 fileSize;
UINT8 result; UINT8 result;
QQueue<QByteArray> files;
while (true) { while (true) {
result = getFileSize(volume, fileOffset, fileSize); result = getFileSize(volume, fileOffset, fileSize);
if (result) if (result)
@ -616,9 +634,9 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, const QModelIndex & par
QByteArray file = volume.mid(fileOffset, fileSize); QByteArray file = volume.mid(fileOffset, fileSize);
QByteArray header = file.left(sizeof(EFI_FFS_FILE_HEADER)); QByteArray header = file.left(sizeof(EFI_FFS_FILE_HEADER));
// We are now at empty space in the end of volume // If we are at empty space in the end of volume
if (header.count(empty) == header.size()) if (header.count(empty) == header.size())
break; break; // Exit from loop
// Check file alignment // Check file alignment
EFI_FFS_FILE_HEADER* fileHeader = (EFI_FFS_FILE_HEADER*) header.constData(); EFI_FFS_FILE_HEADER* fileHeader = (EFI_FFS_FILE_HEADER*) header.constData();
@ -628,6 +646,14 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, const QModelIndex & par
msg(tr("parseVolume: %1, unaligned file").arg(guidToQString(fileHeader->Name))); msg(tr("parseVolume: %1, unaligned file").arg(guidToQString(fileHeader->Name)));
} }
// Check file GUID
if (fileHeader->Type != EFI_FV_FILETYPE_PAD && files.indexOf(header.left(sizeof(EFI_GUID))) != -1)
msg(tr("%1: file with duplicate GUID").arg(guidToQString(fileHeader->Name)));
// Add file GUID to queue
files.enqueue(header.left(sizeof(EFI_GUID)));
// Parse file
result = parseFile(file, volumeHeader->Revision, empty, index); result = parseFile(file, volumeHeader->Revision, empty, index);
if (result) if (result)
msg(tr("parseVolume: Parse FFS file failed (%1)").arg(result)); msg(tr("parseVolume: Parse FFS file failed (%1)").arg(result));
@ -790,13 +816,13 @@ UINT8 FfsEngine::parseFile(const QByteArray & file, UINT8 revision, const char e
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)); msg(tr("parseVolume: Parse file as BIOS failed (%1)").arg(result));
return ERR_SUCCESS;
} }
// Parse sections // Parse sections
else {
result = parseSections(body, revision, empty, index); result = parseSections(body, revision, empty, index);
if (result) if (result)
return result; return result;
}
return ERR_SUCCESS; return ERR_SUCCESS;
} }
@ -959,11 +985,11 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, const UINT8 revision,
case EFI_SECTION_PIC: case EFI_SECTION_PIC:
case EFI_SECTION_TE: case EFI_SECTION_TE:
case EFI_SECTION_VERSION: case EFI_SECTION_VERSION:
case EFI_SECTION_COMPATIBILITY16:
case EFI_SECTION_FREEFORM_SUBTYPE_GUID: case EFI_SECTION_FREEFORM_SUBTYPE_GUID:
case EFI_SECTION_DXE_DEPEX: case EFI_SECTION_DXE_DEPEX:
case EFI_SECTION_PEI_DEPEX: case EFI_SECTION_PEI_DEPEX:
case EFI_SECTION_SMM_DEPEX: case EFI_SECTION_SMM_DEPEX:
case EFI_SECTION_COMPATIBILITY16:
headerSize = sizeOfSectionHeaderOfType(sectionHeader->Type); headerSize = sizeOfSectionHeaderOfType(sectionHeader->Type);
header = section.left(headerSize); header = section.left(headerSize);
body = section.mid(headerSize, sectionSize - headerSize); body = section.mid(headerSize, sectionSize - headerSize);
@ -997,6 +1023,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, const UINT8 revision,
case EFI_SECTION_FIRMWARE_VOLUME_IMAGE: case EFI_SECTION_FIRMWARE_VOLUME_IMAGE:
header = section.left(sizeof(EFI_FIRMWARE_VOLUME_IMAGE_SECTION)); header = section.left(sizeof(EFI_FIRMWARE_VOLUME_IMAGE_SECTION));
body = section.mid(sizeof(EFI_FIRMWARE_VOLUME_IMAGE_SECTION), sectionSize - sizeof(EFI_FIRMWARE_VOLUME_IMAGE_SECTION)); body = section.mid(sizeof(EFI_FIRMWARE_VOLUME_IMAGE_SECTION), sectionSize - sizeof(EFI_FIRMWARE_VOLUME_IMAGE_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'))
@ -1015,6 +1042,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, const UINT8 revision,
case EFI_SECTION_RAW: case EFI_SECTION_RAW:
header = section.left(sizeof(EFI_RAW_SECTION)); header = section.left(sizeof(EFI_RAW_SECTION));
body = section.mid(sizeof(EFI_RAW_SECTION), sectionSize - sizeof(EFI_RAW_SECTION)); body = section.mid(sizeof(EFI_RAW_SECTION), sectionSize - sizeof(EFI_RAW_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'))
@ -1055,22 +1083,21 @@ UINT8 FfsEngine::insert(const QModelIndex & index, const QByteArray & object, co
// Only files and sections can now be inserted // Only files and sections can now be inserted
if (type == TreeItem::File) { if (type == TreeItem::File) {
QModelIndex parent; QModelIndex parent;
if (mode == ADD_MODE_APPEND || mode == ADD_MODE_PREPEND) if (mode == INSERT_MODE_BEFORE || mode == INSERT_MODE_AFTER)
parent = index;
else
parent = index.parent(); parent = index.parent();
else
parent = index;
// Parent type must be volume // Parent type must be volume
TreeItem * parentItem = static_cast<TreeItem*>(parent.internalPointer()); TreeItem * parentItem = static_cast<TreeItem*>(parent.internalPointer());
if (parentItem->type() != TreeItem::Volume) { if (parentItem->type() != TreeItem::Volume) {
msg(tr("insertInto: file can't be inserted into something that is not volume")); msg(tr("insert: file can't be inserted into something that is not volume"));
return ERR_INVALID_VOLUME; return ERR_INVALID_VOLUME;
} }
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
//!TODO: add check for same GUIDs
UINT8 result = parseFile(object, header->Revision, header->Attributes & EFI_FVB_ERASE_POLARITY ? '\xFF' : '\x00', index, mode); UINT8 result = parseFile(object, header->Revision, header->Attributes & EFI_FVB_ERASE_POLARITY ? '\xFF' : '\x00', index, mode);
if (result) if (result)
return result; return result;
@ -1081,7 +1108,40 @@ UINT8 FfsEngine::insert(const QModelIndex & index, const QByteArray & object, co
} }
else if (type == TreeItem::Section) { else if (type == TreeItem::Section) {
return ERR_NOT_IMPLEMENTED; 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))) {
QModelIndex volumeIndex = findParentOfType(TreeItem::Volume, parent);
if (!volumeIndex.isValid()) {
msg(tr("insert: Parent volume not found"));
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
UINT8 result = parseSection(object, header->Revision, header->Attributes & EFI_FVB_ERASE_POLARITY ? '\xFF' : '\x00', index, mode);
if (result)
return result;
// Set reconstruct action for all parents
for (;parent.isValid(); parent = parent.parent())
treeModel->setItemAction(TreeItem::Reconstruct, parent);
}
else {
msg(tr("insert: section can't be inserted into something that is not file or encapsulation section"));
return ERR_INVALID_FILE;
}
} }
else else
return ERR_NOT_IMPLEMENTED; return ERR_NOT_IMPLEMENTED;

View File

@ -44,15 +44,15 @@ public:
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 = ADD_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 = ADD_MODE_APPEND); UINT8 parseFile(const QByteArray & file, const UINT8 revision, const char empty = '\xFF', 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 UINT8 revision, const char empty = '\xFF', const QModelIndex & parent = QModelIndex());
UINT8 parseSection(const QByteArray & section, const UINT8 revision, const char empty = '\xFF', const QModelIndex & parent = QModelIndex(), const UINT8 mode = ADD_MODE_APPEND); UINT8 parseSection(const QByteArray & section, const UINT8 revision, const char empty = '\xFF', const QModelIndex & parent = QModelIndex(), const UINT8 mode = INSERT_MODE_APPEND);
// Compression routines // Compression routines
UINT8 decompress(const QByteArray & compressed, const UINT8 compressionType, QByteArray & decompressedSection, UINT8 * algorithm = NULL); UINT8 decompress(const QByteArray & compressed, const UINT8 compressionType, QByteArray & decompressedData, UINT8 * algorithm = NULL);
UINT8 compress(const QByteArray & data, const UINT8 algorithm, QByteArray & compressedData); UINT8 compress(const QByteArray & data, const UINT8 algorithm, QByteArray & compressedData);
// Construction routines // Construction routines

View File

@ -162,14 +162,14 @@ QVariant TreeItem::data(int column) const
{ {
switch(column) switch(column)
{ {
case 0: //Action case 0: //Name
return itemName;
case 1: //Action
if (itemAction == TreeItem::Remove) if (itemAction == TreeItem::Remove)
return "X"; return "X";
if (itemAction == TreeItem::Reconstruct) if (itemAction == TreeItem::Reconstruct)
return "R"; return "R";
return QVariant(); return QVariant();
case 1: //Name
return itemName;
case 2: //Type case 2: //Type
return itemTypeName; return itemTypeName;
case 3: //Subtype case 3: //Subtype

View File

@ -162,31 +162,31 @@ QModelIndex TreeModel::addItem(const UINT8 type, const UINT8 subtype, const UINT
parentItem = rootItem; parentItem = rootItem;
else else
{ {
if (mode == ADD_MODE_APPEND || mode == ADD_MODE_PREPEND) { if (mode == INSERT_MODE_BEFORE || mode == INSERT_MODE_AFTER) {
parentItem = static_cast<TreeItem*>(index.internalPointer());
parentColumn = index.column();
}
else {
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();
} }
else {
parentItem = static_cast<TreeItem*>(index.internalPointer());
parentColumn = index.column();
}
} }
TreeItem *newItem = new TreeItem(type, subtype, compression, name, text, info, header, body, parentItem); TreeItem *newItem = new TreeItem(type, subtype, compression, name, text, info, header, body, parentItem);
if (mode == ADD_MODE_APPEND) { if (mode == INSERT_MODE_APPEND) {
emit layoutAboutToBeChanged(); emit layoutAboutToBeChanged();
parentItem->appendChild(newItem); parentItem->appendChild(newItem);
} }
else if (mode == ADD_MODE_PREPEND) { else if (mode == INSERT_MODE_PREPEND) {
emit layoutAboutToBeChanged(); emit layoutAboutToBeChanged();
parentItem->prependChild(newItem); parentItem->prependChild(newItem);
} }
else if (mode == ADD_MODE_INSERT_BEFORE) { else if (mode == INSERT_MODE_BEFORE) {
emit layoutAboutToBeChanged(); emit layoutAboutToBeChanged();
parentItem->insertChildBefore(item, newItem); parentItem->insertChildBefore(item, newItem);
} }
else if (mode == ADD_MODE_INSERT_AFTER) { else if (mode == INSERT_MODE_AFTER) {
emit layoutAboutToBeChanged(); emit layoutAboutToBeChanged();
parentItem->insertChildAfter(item, newItem); parentItem->insertChildAfter(item, newItem);
} }

View File

@ -48,7 +48,7 @@ public:
QModelIndex addItem(const UINT8 type, const UINT8 subtype = 0, const UINT8 compression = COMPRESSION_ALGORITHM_NONE, QModelIndex addItem(const UINT8 type, const UINT8 subtype = 0, const UINT8 compression = COMPRESSION_ALGORITHM_NONE,
const QString & name = QString(), const QString & text = QString(), const QString & info = QString(), const QString & name = QString(), const QString & text = QString(), const QString & info = QString(),
const QByteArray & header = QByteArray(), const QByteArray & body = QByteArray(), const QModelIndex & index = QModelIndex(), const QByteArray & header = QByteArray(), const QByteArray & body = QByteArray(), const QModelIndex & index = QModelIndex(),
const UINT8 mode = ADD_MODE_APPEND); const UINT8 mode = INSERT_MODE_APPEND);
private: private:
TreeItem *rootItem; TreeItem *rootItem;

View File

@ -32,10 +32,11 @@ UEFITool::UEFITool(QWidget *parent) :
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->actionSaveImageFile, SIGNAL(triggered()), this, SLOT(saveImageFile())); connect(ui->actionSaveImageFile, SIGNAL(triggered()), this, SLOT(saveImageFile()));
// Enable Drag-and-Drop actions // Enable Drag-and-Drop actions
this->setAcceptDrops(true); this->setAcceptDrops(true);
// Initialise non-persistent data // Initialize non-persistent data
init(); init();
} }
@ -71,11 +72,12 @@ void UEFITool::init()
connect(ui->structureTreeView, SIGNAL(expanded(const QModelIndex &)), this, SLOT(resizeTreeViewColums(void))); connect(ui->structureTreeView, SIGNAL(expanded(const QModelIndex &)), this, SLOT(resizeTreeViewColums(void)));
connect(ui->structureTreeView->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), connect(ui->structureTreeView->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
this, SLOT(populateUi(const QModelIndex &))); this, SLOT(populateUi(const QModelIndex &)));
resizeTreeViewColums();
} }
void UEFITool::populateUi(const QModelIndex &current/*, const QModelIndex &previous*/) void UEFITool::populateUi(const QModelIndex &current)
{ {
//!TODO: make widget
currentIndex = current; currentIndex = current;
ui->infoEdit->setPlainText(current.data(Qt::UserRole).toString()); ui->infoEdit->setPlainText(current.data(Qt::UserRole).toString());
ui->actionExtract->setDisabled(ffsEngine->hasEmptyBody(current) && ffsEngine->hasEmptyHeader(current)); ui->actionExtract->setDisabled(ffsEngine->hasEmptyBody(current) && ffsEngine->hasEmptyHeader(current));
@ -84,10 +86,14 @@ void UEFITool::populateUi(const QModelIndex &current/*, const QModelIndex &previ
ui->actionRemove->setEnabled(ffsEngine->isOfType(TreeItem::Volume, current) ui->actionRemove->setEnabled(ffsEngine->isOfType(TreeItem::Volume, current)
|| ffsEngine->isOfType(TreeItem::File, current) || ffsEngine->isOfType(TreeItem::File, current)
|| ffsEngine->isOfType(TreeItem::Section, current)); || ffsEngine->isOfType(TreeItem::Section, current));
ui->actionInsertInto->setEnabled(ffsEngine->isOfType(TreeItem::Volume, current)); ui->actionInsertInto->setEnabled(ffsEngine->isOfType(TreeItem::Volume, current)
ui->actionInsertBefore->setEnabled(ffsEngine->isOfType(TreeItem::File, current)); || ffsEngine->isOfType(TreeItem::File, current)
ui->actionInsertAfter->setEnabled(ffsEngine->isOfType(TreeItem::File, current)); || ffsEngine->isOfType(TreeItem::Section, current));
ui->actionReplace->setEnabled(ffsEngine->isOfType(TreeItem::File, current)); ui->actionInsertBefore->setEnabled(ffsEngine->isOfType(TreeItem::File, current)
|| ffsEngine->isOfType(TreeItem::Section, current));
ui->actionInsertAfter->setEnabled(ffsEngine->isOfType(TreeItem::File, current)
|| ffsEngine->isOfType(TreeItem::Section, current));
//ui->actionReplace->setEnabled(ffsEngine->isOfType(TreeItem::File, current));
} }
void UEFITool::remove() void UEFITool::remove()
@ -98,109 +104,87 @@ void UEFITool::remove()
} }
else else
ui->actionSaveImageFile->setEnabled(true); ui->actionSaveImageFile->setEnabled(true);
resizeTreeViewColums();
resizeTreeViewColums();
}
void UEFITool::insert(const UINT8 mode)
{
QString path;
TreeItem* item = static_cast<TreeItem*>(currentIndex.internalPointer());
UINT8 type;
UINT8 objectType;
if (mode == INSERT_MODE_BEFORE || mode == INSERT_MODE_BEFORE)
type = item->parent()->type();
else
type = item->type();
switch (type) {
case TreeItem::Volume:
path = QFileDialog::getOpenFileName(this, tr("Select FFS file to insert"),".","FFS file (*.ffs *.bin);;All files (*.*)");
objectType = TreeItem::File;
break;
case TreeItem::File:
case TreeItem::Section:
path = QFileDialog::getOpenFileName(this, tr("Select section file to insert"),".","Section file (*.sec *.bin);;All files (*.*)");
objectType = TreeItem::Section;
break;
default:
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->insert(currentIndex, buffer, objectType, mode);
if (result)
ui->statusBar->showMessage(tr("File can't be inserted (%1)").arg(result));
else
ui->actionSaveImageFile->setEnabled(true);
resizeTreeViewColums();
} }
void UEFITool::insertInto() void UEFITool::insertInto()
{ {
QString path = QFileDialog::getOpenFileName(this, tr("Select FFS file to insert"),".","FFS file (*.ffs *.bin);;All files (*.*)"); insert(INSERT_MODE_PREPEND);
QFileInfo fileInfo = QFileInfo(path);
if (!fileInfo.exists())
{
ui->statusBar->showMessage(tr("Please select existing FFS 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->insert(currentIndex, buffer, TreeItem::File, ADD_MODE_PREPEND);
if (result)
ui->statusBar->showMessage(tr("FFS file can't be inserted (%1)").arg(result));
else
ui->actionSaveImageFile->setEnabled(true);
resizeTreeViewColums();
} }
void UEFITool::insertBefore() void UEFITool::insertBefore()
{ {
QString path = QFileDialog::getOpenFileName(this, tr("Select FFS file to insert"),".","FFS file (*.ffs *.bin);;All files (*.*)"); insert(INSERT_MODE_BEFORE);
QFileInfo fileInfo = QFileInfo(path);
if (!fileInfo.exists())
{
ui->statusBar->showMessage(tr("Please select existing FFS 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->insert(currentIndex, buffer, TreeItem::File, ADD_MODE_INSERT_BEFORE);
if (result)
ui->statusBar->showMessage(tr("FFS file can't be inserted (%1)").arg(result));
else
ui->actionSaveImageFile->setEnabled(true);
resizeTreeViewColums();
} }
void UEFITool::insertAfter() void UEFITool::insertAfter()
{ {
QString path = QFileDialog::getOpenFileName(this, tr("Select FFS file to insert"),".","FFS file (*.ffs *.bin);;All files (*.*)"); insert(INSERT_MODE_AFTER);
QFileInfo fileInfo = QFileInfo(path);
if (!fileInfo.exists())
{
ui->statusBar->showMessage(tr("Please select existing FFS 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->insert(currentIndex, buffer, TreeItem::File, ADD_MODE_INSERT_AFTER);
if (result)
ui->statusBar->showMessage(tr("FFS file can't be inserted (%1)").arg(result));
else
ui->actionSaveImageFile->setEnabled(true);
resizeTreeViewColums();
} }
void UEFITool::replace() void UEFITool::replace()
{ {
remove();
insertAfter();
} }
void UEFITool::saveImageFile() void UEFITool::saveImageFile()
{ {
QString path = QFileDialog::getSaveFileName(this, tr("Save BIOS image file"),".","BIOS image file (*.rom *.bin *.cap *.fd *.fwh);;All files (*.*)"); QString path = QFileDialog::getSaveFileName(this, tr("Save BIOS image file"),".","BIOS image file (*.rom *.bin *.cap *.fd *.wph *.efi);;All files (*.*)");
QFile outputFile; QFile outputFile;
outputFile.setFileName(path); outputFile.setFileName(path);
@ -219,6 +203,7 @@ void UEFITool::saveImageFile()
return; return;
} }
outputFile.resize(0);
outputFile.write(reconstructed); outputFile.write(reconstructed);
outputFile.close(); outputFile.close();
ui->statusBar->showMessage(tr("Reconstructed image written")); ui->statusBar->showMessage(tr("Reconstructed image written"));
@ -243,7 +228,7 @@ void UEFITool::openImageFile(QString path)
QFileInfo fileInfo = QFileInfo(path); QFileInfo fileInfo = QFileInfo(path);
if (!fileInfo.exists()) if (!fileInfo.exists())
{ {
ui->statusBar->showMessage(tr("Please select existing BIOS image file")); ui->statusBar->showMessage(tr("Please select existing file"));
return; return;
} }
@ -262,7 +247,7 @@ void UEFITool::openImageFile(QString path)
init(); init();
UINT8 result = ffsEngine->parseInputFile(buffer); UINT8 result = ffsEngine->parseInputFile(buffer);
if (result) if (result)
ui->statusBar->showMessage(tr("Opened file can't be parsed as UEFI image (%1)").arg(result)); ui->statusBar->showMessage(tr("Opened file can't be parsed (%1)").arg(result));
else else
ui->statusBar->showMessage(tr("Opened: %1").arg(fileInfo.fileName())); ui->statusBar->showMessage(tr("Opened: %1").arg(fileInfo.fileName()));
@ -279,66 +264,49 @@ void UEFITool::extract()
outputFile.setFileName(path); outputFile.setFileName(path);
if (!outputFile.open(QFile::WriteOnly)) if (!outputFile.open(QFile::WriteOnly))
{ {
ui->statusBar->showMessage(tr("Can't open file for writing. Check file permissions.")); ui->statusBar->showMessage(tr("Can't open file for rewriting"));
return; return;
} }
outputFile.resize(0);
outputFile.write(ffsEngine->header(currentIndex) + ffsEngine->body(currentIndex)); outputFile.write(ffsEngine->header(currentIndex) + ffsEngine->body(currentIndex));
outputFile.close(); outputFile.close();
} }
void UEFITool::extractBody() void UEFITool::extractBody()
{ {
QString path = QFileDialog::getSaveFileName(this, tr("Save selected item without header to binary file"),".","Binary files (*.bin);;All files (*.*)"); QString path = QFileDialog::getSaveFileName(this, tr("Save selected item without header to file"),".","Binary files (*.bin);;All files (*.*)");
QFile outputFile; QFile outputFile;
outputFile.setFileName(path); outputFile.setFileName(path);
if (!outputFile.open(QFile::WriteOnly)) if (!outputFile.open(QFile::WriteOnly))
{ {
ui->statusBar->showMessage(tr("Can't open file for writing. Check file permissions.")); ui->statusBar->showMessage(tr("Can't open file for rewriting"));
return; return;
} }
outputFile.resize(0);
outputFile.write(ffsEngine->body(currentIndex)); outputFile.write(ffsEngine->body(currentIndex));
outputFile.close(); outputFile.close();
} }
void UEFITool::extractUncompressed() void UEFITool::extractUncompressed()
{ {
QString path = QFileDialog::getSaveFileName(this, tr("Save selected FFS file as uncompressed to binary file"),".","FFS files (*.ffs);;All files (*.*)"); QString path = QFileDialog::getSaveFileName(this, tr("Save selected FFS file as uncompressed to file"),".","FFS files (*.ffs);;All files (*.*)");
QFile outputFile; QFile outputFile;
outputFile.setFileName(path); outputFile.setFileName(path);
if (!outputFile.open(QFile::WriteOnly)) if (!outputFile.open(QFile::WriteOnly))
{ {
ui->statusBar->showMessage(tr("Can't open file for writing. Check file permissions.")); ui->statusBar->showMessage(tr("Can't open file for rewriting"));
return; return;
} }
outputFile.resize(0);
outputFile.write(ffsEngine->decompressFile(currentIndex)); outputFile.write(ffsEngine->decompressFile(currentIndex));
outputFile.close(); outputFile.close();
} }
/*void UEFITool::saveImageFile()
{
QString path = QFileDialog::getSaveFileName(this, tr("Save BIOS image file"),".","BIOS image file (*.rom *.bin *.cap *.fd *.fwh);;All files (*.*)");
QFileInfo fileInfo = QFileInfo(path);
if (!fileInfo.exists())
{
ui->statusBar->showMessage(tr("Please select existing BIOS image file."));
return;
}
QFile outputFile;
outputFile.setFileName(path);
if (!outputFile.open(QFile::ReadWrite))
{
ui->statusBar->showMessage(tr("Can't open file for writing. Check file permissions."));
return;
}
}*/
void UEFITool::dragEnterEvent(QDragEnterEvent* event) void UEFITool::dragEnterEvent(QDragEnterEvent* event)
{ {
if (event->mimeData()->hasFormat("text/uri-list")) if (event->mimeData()->hasFormat("text/uri-list"))

View File

@ -52,6 +52,7 @@ private slots:
void extract(); void extract();
void extractBody(); void extractBody();
void extractUncompressed(); void extractUncompressed();
void insert(const UINT8 mode);
void insertInto(); void insertInto();
void insertBefore(); void insertBefore();
void insertAfter(); void insertAfter();

View File

@ -20,7 +20,7 @@
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>UEFITool 0.4.0</string> <string>UEFITool 0.5.0</string>
</property> </property>
<widget class="QWidget" name="centralWidget"> <widget class="QWidget" name="centralWidget">
<property name="sizePolicy"> <property name="sizePolicy">
@ -203,7 +203,7 @@
<string>toolBar</string> <string>toolBar</string>
</property> </property>
<attribute name="toolBarArea"> <attribute name="toolBarArea">
<enum>TopToolBarArea</enum> <enum>LeftToolBarArea</enum>
</attribute> </attribute>
<attribute name="toolBarBreak"> <attribute name="toolBarBreak">
<bool>false</bool> <bool>false</bool>