Version 0.11.0

- UI reworked once again
- Hex pattern and text string search implemented
- Code slightly refactored
This commit is contained in:
Nikolaj Schlej 2013-12-04 21:27:12 +01:00
parent 7d8b5fbc20
commit bb6f58f509
26 changed files with 4697 additions and 4327 deletions

View File

@ -139,11 +139,11 @@ INT32
EncodedDataSize = (SizeT) (SourceSize - LZMA_HEADER_SIZE);
LzmaResult = LzmaDecode(
Destination,
(Byte*) Destination,
&DecodedBufSize,
(Byte*)((UINT8*)Source + LZMA_HEADER_SIZE),
&EncodedDataSize,
Source,
(CONST Byte*) Source,
LZMA_PROPS_SIZE,
LZMA_FINISH_END,
&Status,

View File

@ -111,6 +111,11 @@ typedef uint16_t CHAR16;
#define ERASE_POLARITY_TRUE 1
#define ERASE_POLARITY_UNKNOWN 0xFF
// Search modes
#define SEARCH_MODE_HEX 0
#define SEARCH_MODE_ASCII 1
#define SEARCH_MODE_UNICODE 2
// EFI GUID
typedef struct{
UINT8 Data[16];

View File

@ -51,11 +51,16 @@ void FfsEngine::msg(const QString & message, const QModelIndex index)
messageItems.enqueue(MessageListItem(message, NULL, 0, index));
}
QQueue<MessageListItem> FfsEngine::message()
QQueue<MessageListItem> FfsEngine::messages()
{
return messageItems;
}
void FfsEngine::clearMessages()
{
messageItems.clear();
}
QModelIndex FfsEngine::findParentOfType(UINT8 type, const QModelIndex& index) const
{
if(!index.isValid())
@ -1341,46 +1346,20 @@ UINT8 FfsEngine::decompress(const QByteArray & compressedData, const UINT8 compr
scratch = new UINT8[scratchSize];
// Decompress section data
//!TODO: better check needed
// Try EFI1.1 decompression first
if (ERR_SUCCESS != EfiDecompress(data, dataSize, decompressed, decompressedSize, scratch, scratchSize)) {
// Not EFI 1.1, try Tiano
// Try Tiano decompression first
if (ERR_SUCCESS != TianoDecompress(data, dataSize, decompressed, decompressedSize, scratch, scratchSize)) {
// Not Tiano, try EFI 1.1
if (ERR_SUCCESS != EfiDecompress(data, dataSize, decompressed, decompressedSize, scratch, scratchSize)) {
if (algorithm)
*algorithm = COMPRESSION_ALGORITHM_UNKNOWN;
return ERR_STANDARD_DECOMPRESSION_FAILED;
}
else if (algorithm)
*algorithm = COMPRESSION_ALGORITHM_TIANO;
}
else {
// Possible EFI 1.1
// Try decompressing it as Tiano
UINT8* tianoDecompressed = new UINT8[decompressedSize];
UINT8* tianoScratch = new UINT8[scratchSize];
if (ERR_SUCCESS != TianoDecompress(data, dataSize, tianoDecompressed, decompressedSize, tianoScratch, scratchSize)) {
// Not Tiano, definitely EFI 1.1
if (algorithm)
*algorithm = COMPRESSION_ALGORITHM_EFI11;
}
else {
// Both algorithms work
if(memcmp(decompressed, tianoDecompressed, decompressedSize)) {
// If decompressed data are different - it's Tiano for sure
delete[] decompressed;
delete[] scratch;
decompressed = tianoDecompressed;
scratch = tianoScratch;
if (algorithm)
else if (algorithm)
*algorithm = COMPRESSION_ALGORITHM_TIANO;
}
else {
// Data are same - it's EFI 1.1
if (algorithm)
*algorithm = COMPRESSION_ALGORITHM_EFI11;
}
}
}
decompressedData = QByteArray((const char*) decompressed, decompressedSize);
// Free allocated memory
@ -1572,7 +1551,7 @@ UINT8 FfsEngine::reconstruct(const QModelIndex & index, QQueue<QByteArray> & que
QByteArray reconstructed;
UINT8 result;
// No action is needed, just return header + body
// No action is needed, just return header + body + tail
if (item->action() == TreeItem::NoAction) {
reconstructed = item->header().append(item->body()).append(item->tail());
queue.enqueue(reconstructed);
@ -2188,85 +2167,93 @@ UINT8 FfsEngine::growVolume(QByteArray & header, const UINT32 size, UINT32 & new
return ERR_SUCCESS;
}
// Will be refactored later
/*QByteArray FfsEngine::decompressFile(const QModelIndex& index) const
// Search routines
UINT8 FfsEngine::findHexPattern(const QByteArray & pattern, const bool bodyOnly)
{
if (!index.isValid())
return QByteArray();
// Check index item to be FFS file
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
if(item->type() != TreeItem::File)
return QByteArray();
QByteArray file;
UINT32 offset = 0;
// Construct new item body
for (int i = 0; i < item->childCount(); i++) {
// If section is not compressed, add it to new body as is
TreeItem* sectionItem = item->child(i);
if (sectionItem->subtype() != EFI_SECTION_COMPRESSION) {
QByteArray section = sectionItem->header().append(sectionItem->body());
UINT32 align = ALIGN4(offset) - offset;
file.append(QByteArray(align, '\x00')).append(section);
offset += align + section.size();
return findHexPatternIn(treeModel->index(0,0), pattern, bodyOnly);
}
else {
// Construct new section body by adding all child sections to this new section
QByteArray section;
UINT32 subOffset = 0;
for (int j = 0; j < sectionItem->childCount(); j++)
UINT8 FfsEngine::findHexPatternIn(const QModelIndex & index, const QByteArray & pattern, const bool bodyOnly)
{
TreeItem* subSectionItem = sectionItem->child(j);
QByteArray subSection = subSectionItem->header().append(subSectionItem->body());
UINT32 align = ALIGN4(subOffset) - subOffset;
section.append(QByteArray(align, '\x00')).append(subSection);
subOffset += align + subSection.size();
}
// Add newly constructed section to file body
if (pattern.isEmpty())
return ERR_INVALID_PARAMETER;
EFI_COMPRESSION_SECTION sectionHeader;
sectionHeader.Type = EFI_SECTION_COMPRESSION;
sectionHeader.CompressionType = EFI_NOT_COMPRESSED;
sectionHeader.UncompressedLength = section.size();
uint32ToUint24(section.size() + sizeof(EFI_COMPRESSION_SECTION), sectionHeader.Size);
UINT32 align = ALIGN4(offset) - offset;
file.append(QByteArray(align, '\x00'))
.append(QByteArray((const char*) &sectionHeader, sizeof(EFI_COMPRESSION_SECTION)))
.append(section);
offset += align + section.size();
}
if (!index.isValid())
return ERR_SUCCESS;
TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
if (item == rootItem)
return ERR_SUCCESS;
bool hasChildren = (item->childCount() > 0);
for (int i = 0; i < item->childCount(); i++) {
findHexPatternIn(index.child(i, index.column()), pattern, bodyOnly);
}
QByteArray data;
if (hasChildren) {
if(!bodyOnly)
data = item->header();
}
else {
if (bodyOnly)
data = item->body();
else
data = item->header().append(item->body()).append(item->tail());
}
int offset = -1;
while ((offset = data.indexOf(pattern, offset + 1)) >= 0) {
msg(tr("Hex pattern \"%1\" found in %2 at offset %3")
.arg(QString(pattern.toHex()))
.arg(item->data(0).toString())
.arg(offset, 8, 16, QChar('0')),
index);
}
return ERR_SUCCESS;
}
QByteArray header = item->header();
EFI_FFS_FILE_HEADER* fileHeader = (EFI_FFS_FILE_HEADER*) header.data();
// Correct file data checksum, if needed
if (fileHeader->Attributes & FFS_ATTRIB_CHECKSUM) {
UINT32 bufferSize = file.size() - sizeof(EFI_FFS_FILE_HEADER);
fileHeader->IntegrityCheck.Checksum.File = calculateChecksum8((UINT8*)(file.data() + sizeof(EFI_FFS_FILE_HEADER)), bufferSize);
}
// Add file tail, if needed
if(fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT)
file.append(!fileHeader->IntegrityCheck.TailReference);
return header.append(file);
}*/
/*bool FfsEngine::isCompressedFile(const QModelIndex& index) const
UINT8 FfsEngine::findTextPattern(const QString & pattern, const bool unicode, const Qt::CaseSensitivity caseSensitive)
{
if (!index.isValid())
return false;
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
if(item->type() != TreeItem::File)
return false;
for (int i = 0; i < item->childCount(); i++) {
if (item->child(i)->subtype() == EFI_SECTION_COMPRESSION)
return true;
return findTextPatternIn(treeModel->index(0,0), pattern, unicode, caseSensitive);
}
return false;
}*/
UINT8 FfsEngine::findTextPatternIn(const QModelIndex & index, const QString & pattern, const bool unicode, const Qt::CaseSensitivity caseSensitive)
{
if (pattern.isEmpty())
return ERR_INVALID_PARAMETER;
if (!index.isValid())
return ERR_SUCCESS;
TreeItem* item = static_cast<TreeItem*>(index.internalPointer());
if (item == rootItem)
return ERR_SUCCESS;
bool hasChildren = (item->childCount() > 0);
for (int i = 0; i < item->childCount(); i++) {
findTextPatternIn(index.child(i, index.column()), pattern, unicode, caseSensitive);
}
if (hasChildren)
return ERR_SUCCESS;
QString data;
if (unicode)
data = QString::fromUtf16((const ushort*) item->body().data(), item->body().length()/2);
else
data = QString::fromAscii((const char*) item->body().data(), item->body().length());
int offset = -1;
while ((offset = data.indexOf(pattern, offset + 1, caseSensitive)) >= 0) {
msg(tr("%1 text pattern \"%2\" found in %3 at offset %4")
.arg(unicode ? "Unicode" : "ASCII")
.arg(pattern)
.arg(item->data(0).toString())
.arg(unicode ? offset*2 : offset, 8, 16, QChar('0')),
index);
}
return ERR_SUCCESS;
}

View File

@ -38,7 +38,10 @@ public:
TreeModel* model() const;
// Returns message items queue
QQueue<MessageListItem> message();
QQueue<MessageListItem> messages();
// Clears message items queue
void clearMessages();
// Firmware image parsing
UINT8 parseInputFile(const QByteArray & buffer);
@ -74,6 +77,11 @@ public:
UINT8 rebuild(const QModelIndex & index);
UINT8 changeCompression(const QModelIndex & index, const UINT8 algorithm);
// Search routines
UINT8 findHexPattern(const QByteArray & pattern, const bool bodyOnly);
UINT8 findHexPatternIn(const QModelIndex & index, const QByteArray & pattern, const bool bodyOnly);
UINT8 findTextPattern(const QString & pattern, const bool unicode, const Qt::CaseSensitivity caseSensitive);
UINT8 findTextPatternIn(const QModelIndex & index, const QString & pattern, const bool unicode, const Qt::CaseSensitivity caseSensitive);
private:
TreeItem *rootItem;
TreeModel *treeModel;

View File

@ -20,6 +20,10 @@ int main(int argc, char *argv[])
QApplication a(argc, argv);
UEFITool w;
QCoreApplication::setOrganizationName("CodeRush");
QCoreApplication::setOrganizationDomain("coderush.me");
QCoreApplication::setApplicationName("UEFITool");
if (a.arguments().length() > 1)
w.openImageFile(a.arguments().at(1));
w.show();

48
searchdialog.cpp Normal file
View File

@ -0,0 +1,48 @@
/* searchdialog.cpp
Copyright (c) 2013, Nikolaj Schlej. All rights reserved.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*/
#include "searchdialog.h"
SearchDialog::SearchDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::SearchDialog)
{
// Create UI
ui->setupUi(this);
// Connect
//connect(ui->dataTypeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setEditMask()));
//connect(ui->translateFromHexCheckBox, SIGNAL(stateChanged(int)), this, SLOT(setEditMask()));
}
SearchDialog::~SearchDialog()
{
delete ui;
}
/*void SearchDialog::setEditMask()
{
int index = ui->dataTypeComboBox->currentIndex();
QString mask;
if (index == 0) // Hex pattern, max 48 bytes long
mask = "";
else if (index == 1) {
if (ui->translateFromHexCheckBox->isChecked())
mask = "<HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH;_";
else
mask = "<HHHHHHHH-HHHH-HHHH-HHHHHHHHHHHHHHHH;_";
}
else
mask = "";
ui->searchEdit->setInputMask(mask);
}*/

34
searchdialog.h Normal file
View File

@ -0,0 +1,34 @@
/* searchdialog.h
Copyright (c) 2013, Nikolaj Schlej. All rights reserved.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*/
#ifndef SEARCHDIALOG_H
#define SEARCHDIALOG_H
#include <QDialog>
#include "ui_searchdialog.h"
class SearchDialog : public QDialog
{
Q_OBJECT
public:
SearchDialog(QWidget *parent = 0);
~SearchDialog();
Ui::SearchDialog* ui;
private slots:
//void setEditMask();
};
#endif

199
searchdialog.ui Normal file
View File

@ -0,0 +1,199 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SearchDialog</class>
<widget class="QDialog" name="SearchDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>290</width>
<height>172</height>
</rect>
</property>
<property name="windowTitle">
<string>Search</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="searchForLabel">
<property name="text">
<string>Search for:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="dataTypeLabel">
<property name="text">
<string>Data type:</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="searchEdit"/>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="dataTypeComboBox">
<item>
<property name="text">
<string>Hex pattern</string>
</property>
</item>
<item>
<property name="text">
<string>Text string</string>
</property>
</item>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QStackedWidget" name="stackedWidget">
<property name="currentIndex">
<number>1</number>
</property>
<widget class="QWidget" name="hexPage">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QGroupBox" name="hexGroupBox">
<property name="title">
<string>Hex pattern search scope</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QRadioButton" name="allRadioButton">
<property name="text">
<string>Header, data and footer</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="dataOnlyRadioButton">
<property name="text">
<string>Data only</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="textPage">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QGroupBox" name="textGroupBox">
<property name="title">
<string>Text string options</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QCheckBox" name="unicodeCheckBox">
<property name="text">
<string>Unicode</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="caseSensitiveCheckBox">
<property name="text">
<string>Case sensitive</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>searchEdit</tabstop>
<tabstop>dataTypeComboBox</tabstop>
<tabstop>allRadioButton</tabstop>
<tabstop>dataOnlyRadioButton</tabstop>
<tabstop>unicodeCheckBox</tabstop>
<tabstop>caseSensitiveCheckBox</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>SearchDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>173</x>
<y>162</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>216</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>SearchDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>173</x>
<y>162</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>216</y>
</hint>
</hints>
</connection>
<connection>
<sender>dataTypeComboBox</sender>
<signal>activated(int)</signal>
<receiver>stackedWidget</receiver>
<slot>setCurrentIndex(int)</slot>
<hints>
<hint type="sourcelabel">
<x>151</x>
<y>42</y>
</hint>
<hint type="destinationlabel">
<x>88</x>
<y>68</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -18,11 +18,15 @@ UEFITool::UEFITool(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::UEFITool)
{
// Create UI
ui->setupUi(this);
searchDialog = new SearchDialog(this);
ffsEngine = NULL;
//Connect
// Connect signals to slots
connect(ui->actionOpenImageFile, SIGNAL(triggered()), this, SLOT(openImageFile()));
connect(ui->actionSaveImageFile, SIGNAL(triggered()), this, SLOT(saveImageFile()));
connect(ui->actionSearch, SIGNAL(triggered()), this, SLOT(search()));
connect(ui->actionExtract, SIGNAL(triggered()), this, SLOT(extractAsIs()));
connect(ui->actionExtractBody, SIGNAL(triggered()), this, SLOT(extractBody()));
connect(ui->actionExtractUncompressed, SIGNAL(triggered()), this, SLOT(extractUncompressed()));
@ -32,96 +36,31 @@ UEFITool::UEFITool(QWidget *parent) :
connect(ui->actionReplace, SIGNAL(triggered()), this, SLOT(replace()));
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->actionChangeToNone, SIGNAL(triggered()), this, SLOT(changeToNone()));
connect(ui->actionChangeToEfi11, SIGNAL(triggered()), this, SLOT(changeToEfi11()));
connect(ui->actionChangeToTiano, SIGNAL(triggered()), this, SLOT(changeToTiano()));
connect(ui->actionChangeToLzma, SIGNAL(triggered()), this, SLOT(changeToLzma()));
connect(ui->actionMessagesClear, SIGNAL(triggered()), this, SLOT(clearMessages()));
connect(ui->actionAbout, SIGNAL(triggered()), this, SLOT(about()));
connect(ui->actionAboutQt, SIGNAL(triggered()), this, SLOT(aboutQt()));
connect(ui->actionQuit, SIGNAL(triggered()), this, SLOT(exit()));
connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(writeSettings()));
// Enable Drag-and-Drop actions
this->setAcceptDrops(true);
// Create menus
createMenus();
// Initialize non-persistent data
init();
}
void UEFITool::createMenus()
{
// Capsule
capsuleMenu.clear();
capsuleMenu.addAction(ui->actionExtract);
capsuleMenu.addAction(ui->actionExtractBody);
capsuleMenu.addSeparator();
capsuleMenu.addAction(ui->actionRebuild);
// Image
imageMenu.clear();
imageMenu.addAction(ui->actionExtract);
imageMenu.addSeparator();
imageMenu.addAction(ui->actionRebuild);
// Region
regionMenu.clear();
regionMenu.addAction(ui->actionExtract);
regionMenu.addSeparator();
regionMenu.addAction(ui->actionRebuild);
// Padding
paddingMenu.clear();
paddingMenu.addAction(ui->actionExtract);
// Volume
volumeMenu.clear();
volumeMenu.addAction(ui->actionExtract);
volumeMenu.addAction(ui->actionExtractBody);
volumeMenu.addSeparator();
volumeMenu.addAction(ui->actionRebuild);
volumeMenu.addSeparator();
volumeMenu.addAction(ui->actionInsertInto);
volumeMenu.addSeparator();
volumeMenu.addAction(ui->actionRemove);
// File
fileMenu.clear();
fileMenu.addAction(ui->actionExtract);
fileMenu.addAction(ui->actionExtractBody);
//fileMenu.addAction(ui->actionExtractUncompressed);
fileMenu.addSeparator();
fileMenu.addAction(ui->actionRebuild);
fileMenu.addSeparator();
fileMenu.addAction(ui->actionInsertInto);
fileMenu.addAction(ui->actionInsertBefore);
fileMenu.addAction(ui->actionInsertAfter);
fileMenu.addSeparator();
fileMenu.addAction(ui->actionRemove);
// Section
sectionMenu.clear();
sectionMenu.addAction(ui->actionExtract);
sectionMenu.addAction(ui->actionExtractBody);
//sectionMenu.addAction(ui->actionExtractUncompressed);
sectionMenu.addSeparator();
sectionMenu.addAction(ui->actionRebuild);
sectionMenu.addSeparator();
sectionMenu.addAction(ui->actionInsertInto);
sectionMenu.addAction(ui->actionInsertBefore);
sectionMenu.addAction(ui->actionInsertAfter);
sectionMenu.addSeparator();
sectionMenu.addAction(ui->actionRemove);
sectionMenu.addSeparator();
sectionMenu.addMenu(ui->menuChangeCompressionTo);
// Read stored settings
readSettings();
}
UEFITool::~UEFITool()
{
delete ui;
delete ffsEngine;
delete searchDialog;
}
void UEFITool::init()
@ -130,18 +69,14 @@ void UEFITool::init()
ui->messageListWidget->clear();
ui->infoEdit->clear();
// Disable actions and menus
ui->actionExtract->setDisabled(true);
ui->actionExtractBody->setDisabled(true);
ui->actionExtractUncompressed->setDisabled(true);
ui->actionReplace->setDisabled(true);
ui->actionRemove->setDisabled(true);
ui->actionRebuild->setDisabled(true);
ui->actionInsertInto->setDisabled(true);
ui->actionInsertBefore->setDisabled(true);
ui->actionInsertAfter->setDisabled(true);
ui->actionSaveImageFile->setDisabled(true);
ui->menuChangeCompressionTo->setDisabled(true);
// Disable menus
ui->menuCapsuleActions->setDisabled(true);
ui->menuImageActions->setDisabled(true);
ui->menuRegionActions->setDisabled(true);
ui->menuPaddingActions->setDisabled(true);
ui->menuVolumeActions->setDisabled(true);
ui->menuFileActions->setDisabled(true);
ui->menuSectionActions->setDisabled(true);
// Make new ffsEngine
if (ffsEngine)
@ -155,8 +90,6 @@ void UEFITool::init()
connect(ui->structureTreeView->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
this, SLOT(populateUi(const QModelIndex &)));
connect(ui->messageListWidget, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(scrollTreeView(QListWidgetItem*)));
resizeTreeViewColums();
}
void UEFITool::populateUi(const QModelIndex &current)
@ -169,7 +102,19 @@ void UEFITool::populateUi(const QModelIndex &current)
UINT8 subtype = item->subtype();
UINT8 algorithm = item->compression();
// Set info text
ui->infoEdit->setPlainText(item->info());
// Enable menus
ui->menuCapsuleActions->setEnabled(type == TreeItem::Capsule);
ui->menuImageActions->setEnabled(type == TreeItem::Image);
ui->menuRegionActions->setEnabled(type == TreeItem::Region);
ui->menuPaddingActions->setEnabled(type == TreeItem::Padding);
ui->menuVolumeActions->setEnabled(type == TreeItem::Volume);
ui->menuFileActions->setEnabled(type == TreeItem::File);
ui->menuSectionActions->setEnabled(type == TreeItem::Section);
// Enable actions
ui->actionExtract->setDisabled(item->hasEmptyHeader() && item->hasEmptyBody() && item->hasEmptyTail());
ui->actionRebuild->setDisabled(item->hasEmptyHeader() && item->hasEmptyBody() && item->hasEmptyTail());
ui->actionExtractBody->setDisabled(item->hasEmptyHeader());
@ -182,6 +127,29 @@ void UEFITool::populateUi(const QModelIndex &current)
(algorithm == COMPRESSION_ALGORITHM_NONE || COMPRESSION_ALGORITHM_EFI11 || algorithm == COMPRESSION_ALGORITHM_TIANO || algorithm == COMPRESSION_ALGORITHM_LZMA));
}
void UEFITool::search()
{
if (searchDialog->exec() != QDialog::Accepted)
return;
int index = searchDialog->ui->dataTypeComboBox->currentIndex();
if (index == 0) { // Hex pattern
QByteArray pattern = QByteArray::fromHex(searchDialog->ui->searchEdit->text().toAscii());
if (pattern.isEmpty())
return;
ffsEngine->findHexPattern(pattern, searchDialog->ui->dataOnlyRadioButton->isChecked());
showMessages();
}
else if (index == 1) { // Text string
QString pattern = searchDialog->ui->searchEdit->text();
if (pattern.isEmpty())
return;
ffsEngine->findTextPattern(pattern, searchDialog->ui->unicodeCheckBox->isChecked(),
(Qt::CaseSensitivity) searchDialog->ui->caseSensitiveCheckBox->isChecked());
showMessages();
}
}
void UEFITool::rebuild()
{
QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex();
@ -360,7 +328,7 @@ void UEFITool::saveImageFile()
QByteArray reconstructed;
UINT8 result = ffsEngine->reconstructImage(reconstructed);
showMessage();
showMessages();
if (result) {
ui->statusBar->showMessage(tr("Reconstruction failed (%1)").arg(result));
return;
@ -372,7 +340,7 @@ void UEFITool::saveImageFile()
ui->statusBar->showMessage(tr("Reconstructed image written"));
}
void UEFITool::resizeTreeViewColums()
void UEFITool::resizeTreeViewColumns()
{
int count = ffsEngine->model()->columnCount();
for(int i = 0; i < count; i++)
@ -406,13 +374,21 @@ void UEFITool::openImageFile(QString path)
init();
UINT8 result = ffsEngine->parseInputFile(buffer);
showMessage();
showMessages();
if (result)
ui->statusBar->showMessage(tr("Opened file can't be parsed (%1)").arg(result));
else
ui->statusBar->showMessage(tr("Opened: %1").arg(fileInfo.fileName()));
resizeTreeViewColums();
// Enable search
ui->actionSearch->setEnabled(true);
}
void UEFITool::clearMessages()
{
ffsEngine->clearMessages();
messageItems.clear();
ui->messageListWidget->clear();
}
void UEFITool::extract(const UINT8 mode)
@ -500,13 +476,13 @@ void UEFITool::dropEvent(QDropEvent* event)
openImageFile(path);
}
void UEFITool::showMessage()
void UEFITool::showMessages()
{
ui->messageListWidget->clear();
if (!ffsEngine)
return;
messageItems = ffsEngine->message();
messageItems = ffsEngine->messages();
for (int i = 0; i < messageItems.count(); i++) {
ui->messageListWidget->addItem(new MessageListItem(messageItems.at(i)));
}
@ -523,8 +499,13 @@ void UEFITool::scrollTreeView(QListWidgetItem* item)
}
}
void UEFITool::contextMenuEvent (QContextMenuEvent* event)
void UEFITool::contextMenuEvent(QContextMenuEvent* event)
{
if (ui->messageListWidget->underMouse()) {
ui->menuMessages->exec(event->globalPos());
return;
}
if(!ui->structureTreeView->underMouse())
return;
@ -537,25 +518,61 @@ void UEFITool::contextMenuEvent (QContextMenuEvent* event)
switch(item->type())
{
case TreeItem::Capsule:
capsuleMenu.exec(event->globalPos());
ui->menuCapsuleActions->exec(event->globalPos());
break;
case TreeItem::Image:
imageMenu.exec(event->globalPos());
ui->menuImageActions->exec(event->globalPos());
break;
case TreeItem::Region:
regionMenu.exec(event->globalPos());
ui->menuRegionActions->exec(event->globalPos());
break;
case TreeItem::Padding:
paddingMenu.exec(event->globalPos());
ui->menuPaddingActions->exec(event->globalPos());
break;
case TreeItem::Volume:
volumeMenu.exec(event->globalPos());
ui->menuVolumeActions->exec(event->globalPos());
break;
case TreeItem::File:
fileMenu.exec(event->globalPos());
ui->menuFileActions->exec(event->globalPos());
break;
case TreeItem::Section:
sectionMenu.exec(event->globalPos());
ui->menuSectionActions->exec(event->globalPos());
break;
}
}
void UEFITool::readSettings()
{
QSettings settings("UEFITool.ini", QSettings::IniFormat, this);
resize(settings.value("mainWindow/size", QSize(800, 600)).toSize());
move(settings.value("mainWindow/position", QPoint(0, 0)).toPoint());
QList<int> horList, vertList;
horList.append(settings.value("mainWindow/treeWidth", 600).toInt());
horList.append(settings.value("mainWindow/infoWidth", 180).toInt());
vertList.append(settings.value("mainWindow/treeHeight", 400).toInt());
vertList.append(settings.value("mainWindow/messageHeight", 180).toInt());
ui->infoSplitter->setSizes(horList);
ui->messagesSplitter->setSizes(vertList);
resizeTreeViewColumns();
ui->structureTreeView->setColumnWidth(0, settings.value("tree/columnWidth0", ui->structureTreeView->columnWidth(0)).toInt());
ui->structureTreeView->setColumnWidth(1, settings.value("tree/columnWidth1", ui->structureTreeView->columnWidth(1)).toInt());
ui->structureTreeView->setColumnWidth(2, settings.value("tree/columnWidth2", ui->structureTreeView->columnWidth(2)).toInt());
ui->structureTreeView->setColumnWidth(3, settings.value("tree/columnWidth3", ui->structureTreeView->columnWidth(3)).toInt());
//ui->structureTreeView->setColumnWidth(4, settings.value("tree/columnWidth4", 10).toInt());
}
void UEFITool::writeSettings()
{
QSettings settings("UEFITool.ini", QSettings::IniFormat, this);
settings.setValue("mainWindow/size", size());
settings.setValue("mainWindow/position", pos());
settings.setValue("mainWindow/treeWidth", ui->structureGroupBox->width());
settings.setValue("mainWindow/infoWidth", ui->infoGroupBox->width());
settings.setValue("mainWindow/treeHeight", ui->structureGroupBox->height());
settings.setValue("mainWindow/messageHeight", ui->messageGroupBox->height());
settings.setValue("tree/columnWidth0", ui->structureTreeView->columnWidth(0));
settings.setValue("tree/columnWidth1", ui->structureTreeView->columnWidth(1));
settings.setValue("tree/columnWidth2", ui->structureTreeView->columnWidth(2));
settings.setValue("tree/columnWidth3", ui->structureTreeView->columnWidth(3));
//settings.setValue("tree/columnWidth4", ui->structureTreeView->columnWidth(4));
}

View File

@ -21,18 +21,24 @@
#include <QFile>
#include <QFileDialog>
#include <QFileInfo>
#include <QListWidget>
#include <QMenu>
#include <QMessageBox>
#include <QMimeData>
#include <QPlainTextEdit>
#include <QSettings>
#include <QSplitter>
#include <QString>
#include <QTreeView>
#include <QUrl>
#include "basetypes.h"
#include "ffs.h"
#include "ffsengine.h"
#include "searchdialog.h"
namespace Ui {
class UEFITool;
class UEFITool;
}
class UEFITool : public QMainWindow
@ -48,11 +54,12 @@ public:
private slots:
void init();
void populateUi(const QModelIndex &current);
void resizeTreeViewColumns();
void scrollTreeView(QListWidgetItem* item);
void openImageFile();
void saveImageFile();
void resizeTreeViewColums();
void scrollTreeView(QListWidgetItem* item);
void search();
void extract(const UINT8 mode);
void extractAsIs();
@ -75,30 +82,26 @@ private slots:
void changeToTiano();
void changeToLzma();
void clearMessages();
void about();
void aboutQt();
void exit();
void writeSettings();
private:
Ui::UEFITool * ui;
Ui::UEFITool* ui;
FfsEngine* ffsEngine;
SearchDialog* searchDialog;
QQueue<MessageListItem> messageItems;
void showMessage();
QMenu capsuleMenu;
QMenu imageMenu;
QMenu regionMenu;
QMenu paddingMenu;
QMenu volumeMenu;
QMenu fileMenu;
QMenu sectionMenu;
void createMenus();
void showMessages();
void dragEnterEvent(QDragEnterEvent* event);
void dropEvent(QDropEvent* event);
void contextMenuEvent (QContextMenuEvent* event);
void contextMenuEvent(QContextMenuEvent* event);
void readSettings();
};
#endif

View File

@ -6,6 +6,7 @@ TEMPLATE = app
SOURCES += main.cpp \
uefitool.cpp \
searchdialog.cpp \
descriptor.cpp \
ffs.cpp \
ffsengine.cpp \
@ -20,7 +21,9 @@ SOURCES += main.cpp \
Tiano/EfiTianoDecompress.c \
Tiano/EfiCompress.c \
Tiano/TianoCompress.c
HEADERS += uefitool.h \
searchdialog.h \
basetypes.h \
descriptor.h \
gbe.h \
@ -34,6 +37,10 @@ HEADERS += uefitool.h \
LZMA/LzmaDecompress.h \
Tiano/EfiTianoDecompress.h \
Tiano/EfiTianoCompress.h
FORMS += uefitool.ui
FORMS += uefitool.ui \
searchdialog.ui
RC_FILE = uefitool.rc
ICON = uefitool.icns

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
<width>834</width>
<height>499</height>
</rect>
</property>
<property name="sizePolicy">
@ -20,7 +20,7 @@
<bool>true</bool>
</property>
<property name="windowTitle">
<string>UEFITool 0.10.0</string>
<string>UEFITool 0.11.0</string>
</property>
<widget class="QWidget" name="centralWidget">
<property name="sizePolicy">
@ -29,24 +29,32 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<layout class="QHBoxLayout" name="horizontalLayout_7">
<property name="spacing">
<number>5</number>
<number>0</number>
</property>
<property name="margin">
<number>8</number>
<number>0</number>
</property>
<item>
<widget class="QGroupBox" name="groupBox">
<widget class="QSplitter" name="messagesSplitter">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QSplitter" name="infoSplitter">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QGroupBox" name="structureGroupBox">
<property name="title">
<string>Structure</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="spacing">
<number>5</number>
<number>0</number>
</property>
<property name="margin">
<number>8</number>
<number>5</number>
</property>
<item>
<widget class="QTreeView" name="structureTreeView">
@ -75,103 +83,16 @@
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QStatusBar" name="statusBar"/>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>21</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<widget class="QGroupBox" name="infoGroupBox">
<property name="title">
<string>&amp;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&amp;ction</string>
</property>
<widget class="QMenu" name="menuChangeCompressionTo">
<property name="enabled">
<bool>true</bool>
</property>
<property name="title">
<string>Change &amp;compression to</string>
</property>
<addaction name="actionChangeToNone"/>
<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&amp;elp</string>
</property>
<addaction name="actionAbout"/>
<addaction name="actionAboutQt"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuAction"/>
<addaction name="menuHelp"/>
</widget>
<widget class="QDockWidget" name="infoDockWidget">
<property name="minimumSize">
<size>
<width>89</width>
<height>111</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>180</width>
<height>524287</height>
</size>
</property>
<property name="features">
<set>QDockWidget::DockWidgetMovable</set>
</property>
<property name="allowedAreas">
<set>Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea</set>
</property>
<property name="windowTitle">
<string>Information</string>
</property>
<attribute name="dockWidgetArea">
<number>2</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<property name="spacing">
<number>5</number>
<number>0</number>
</property>
<property name="margin">
<number>8</number>
<number>5</number>
</property>
<item>
<widget class="QPlainTextEdit" name="infoEdit">
@ -192,38 +113,16 @@
</layout>
</widget>
</widget>
<widget class="QDockWidget" name="messageDockWidget">
<property name="minimumSize">
<size>
<width>91</width>
<height>113</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>524287</width>
<height>113</height>
</size>
</property>
<property name="features">
<set>QDockWidget::DockWidgetMovable</set>
</property>
<property name="allowedAreas">
<set>Qt::BottomDockWidgetArea|Qt::TopDockWidgetArea</set>
</property>
<property name="windowTitle">
<widget class="QGroupBox" name="messageGroupBox">
<property name="title">
<string>Messages</string>
</property>
<attribute name="dockWidgetArea">
<number>8</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_2">
<layout class="QVBoxLayout" name="verticalLayout_3">
<layout class="QHBoxLayout" name="horizontalLayout_6">
<property name="spacing">
<number>5</number>
<number>0</number>
</property>
<property name="margin">
<number>8</number>
<number>5</number>
</property>
<item>
<widget class="QListWidget" name="messageListWidget"/>
@ -231,6 +130,146 @@
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QStatusBar" name="statusBar"/>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>834</width>
<height>21</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>&amp;File</string>
</property>
<addaction name="actionOpenImageFile"/>
<addaction name="actionSaveImageFile"/>
<addaction name="separator"/>
<addaction name="actionSearch"/>
<addaction name="separator"/>
<addaction name="actionQuit"/>
</widget>
<widget class="QMenu" name="menuHelp">
<property name="title">
<string>H&amp;elp</string>
</property>
<addaction name="actionAbout"/>
<addaction name="actionAboutQt"/>
</widget>
<widget class="QMenu" name="menuAction">
<property name="title">
<string>&amp;Action</string>
</property>
<widget class="QMenu" name="menuCapsuleActions">
<property name="title">
<string>&amp;Capsule</string>
</property>
<addaction name="actionExtract"/>
<addaction name="actionExtractBody"/>
<addaction name="separator"/>
<addaction name="actionRebuild"/>
</widget>
<widget class="QMenu" name="menuImageActions">
<property name="title">
<string>&amp;Image</string>
</property>
<addaction name="actionExtract"/>
<addaction name="separator"/>
<addaction name="actionRebuild"/>
</widget>
<widget class="QMenu" name="menuRegionActions">
<property name="title">
<string>&amp;Region</string>
</property>
<addaction name="actionExtract"/>
<addaction name="separator"/>
<addaction name="actionRebuild"/>
</widget>
<widget class="QMenu" name="menuPaddingActions">
<property name="title">
<string>&amp;Padding</string>
</property>
<addaction name="actionExtract"/>
</widget>
<widget class="QMenu" name="menuVolumeActions">
<property name="title">
<string>&amp;Volume</string>
</property>
<addaction name="actionExtract"/>
<addaction name="actionExtractBody"/>
<addaction name="separator"/>
<addaction name="actionRebuild"/>
<addaction name="separator"/>
<addaction name="actionInsertInto"/>
<addaction name="separator"/>
<addaction name="actionRemove"/>
</widget>
<widget class="QMenu" name="menuFileActions">
<property name="title">
<string>&amp;File</string>
</property>
<addaction name="actionExtract"/>
<addaction name="actionExtractBody"/>
<addaction name="separator"/>
<addaction name="actionRebuild"/>
<addaction name="separator"/>
<addaction name="actionInsertInto"/>
<addaction name="actionInsertBefore"/>
<addaction name="actionInsertAfter"/>
<addaction name="separator"/>
<addaction name="actionRemove"/>
</widget>
<widget class="QMenu" name="menuSectionActions">
<property name="title">
<string>&amp;Section</string>
</property>
<widget class="QMenu" name="menuChangeCompressionTo">
<property name="title">
<string>Change compression to</string>
</property>
<addaction name="actionChangeToNone"/>
<addaction name="actionChangeToTiano"/>
<addaction name="actionChangeToEfi11"/>
<addaction name="actionChangeToLzma"/>
</widget>
<addaction name="actionExtract"/>
<addaction name="actionExtractBody"/>
<addaction name="separator"/>
<addaction name="actionRebuild"/>
<addaction name="separator"/>
<addaction name="actionInsertInto"/>
<addaction name="actionInsertBefore"/>
<addaction name="actionInsertAfter"/>
<addaction name="separator"/>
<addaction name="actionRemove"/>
<addaction name="separator"/>
<addaction name="menuChangeCompressionTo"/>
</widget>
<widget class="QMenu" name="menuMessages">
<property name="title">
<string>&amp;Messages</string>
</property>
<addaction name="actionMessagesClear"/>
</widget>
<addaction name="menuCapsuleActions"/>
<addaction name="menuImageActions"/>
<addaction name="menuRegionActions"/>
<addaction name="menuPaddingActions"/>
<addaction name="menuVolumeActions"/>
<addaction name="menuFileActions"/>
<addaction name="menuSectionActions"/>
<addaction name="separator"/>
<addaction name="menuMessages"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuAction"/>
<addaction name="menuHelp"/>
</widget>
<action name="actionInsertAfter">
<property name="enabled">
<bool>false</bool>
@ -441,6 +480,25 @@
<string>Ctrl+U</string>
</property>
</action>
<action name="actionSearch">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Sear&amp;ch...</string>
</property>
<property name="shortcut">
<string>Ctrl+F</string>
</property>
</action>
<action name="actionMessagesClear">
<property name="text">
<string>&amp;Clear</string>
</property>
<property name="shortcut">
<string>Ctrl+Backspace</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>