Version 0.4.0

- Code is highly refactored
- Editing is (partially) working now
This commit is contained in:
Nikolaj Schlej 2013-11-07 14:46:28 +01:00
parent 981795dee8
commit 4a61fcd9d9
18 changed files with 2629 additions and 1676 deletions

View File

@ -17,12 +17,12 @@
#include "../basetypes.h"
#include "SDK/C/LzmaDec.h"
#define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + 8)
#ifdef __cplusplus
extern "C" {
#endif
#define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + 8)
UINT64
EFIAPI
LShiftU64 (

View File

@ -660,7 +660,7 @@ Returns: (VOID)
}
UINT32
GetInfo (
EfiTianoGetInfo (
VOID *Source,
UINT32 SrcSize,
UINT32 *DstSize,
@ -825,43 +825,6 @@ Returns:
return Status;
}
UINT32
EFIAPI
EfiGetInfo (
VOID *Source,
UINT32 SrcSize,
UINT32 *DstSize,
UINT32 *ScratchSize
)
/*++
Routine Description:
The implementation is same as that of EFI_DECOMPRESS_PROTOCOL.GetInfo().
Arguments:
This - The protocol instance pointer
Source - The source buffer containing the compressed data.
SrcSize - The size of source buffer
DstSize - The size of destination buffer.
ScratchSize - The size of scratch buffer.
Returns:
EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved.
EFI_INVALID_PARAMETER - The source data is corrupted
--*/
{
return GetInfo (
Source,
SrcSize,
DstSize,
ScratchSize
);
}
UINT32
EFIAPI
EfiDecompress (
@ -909,43 +872,6 @@ Returns:
);
}
UINT32
EFIAPI
TianoGetInfo (
VOID *Source,
UINT32 SrcSize,
UINT32 *DstSize,
UINT32 *ScratchSize
)
/*++
Routine Description:
The implementation is same as that of EFI_TIANO_DECOMPRESS_PROTOCOL.GetInfo().
Arguments:
This - The protocol instance pointer
Source - The source buffer containing the compressed data.
SrcSize - The size of source buffer
DstSize - The size of destination buffer.
ScratchSize - The size of scratch buffer.
Returns:
EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved.
EFI_INVALID_PARAMETER - The source data is corrupted
--*/
{
return GetInfo (
Source,
SrcSize,
DstSize,
ScratchSize
);
}
UINT32
EFIAPI
TianoDecompress (

View File

@ -30,10 +30,14 @@ Abstract:
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
UINT32 CompSize;
UINT32 OrigSize;
} EFI_TIANO_HEADER;
UINT32
EFIAPI
EfiGetInfo (
EfiTianoGetInfo (
VOID *Source,
UINT32 SrcSize,
UINT32 *DstSize,
@ -95,36 +99,6 @@ Returns:
--*/
;
UINT32
EFIAPI
TianoGetInfo (
VOID *Source,
UINT32 SrcSize,
UINT32 *DstSize,
UINT32 *ScratchSize
)
/*++
Routine Description:
The implementation is same as that of EFI_TIANO_DECOMPRESS_PROTOCOL.GetInfo().
Arguments:
This - The protocol instance pointer
Source - The source buffer containing the compressed data.
SrcSize - The size of source buffer
DstSize - The size of destination buffer.
ScratchSize - The size of scratch buffer.
Returns:
EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved.
EFI_INVALID_PARAMETER - The source data is corrupted
--*/
;
UINT32
EFIAPI
TianoDecompress (
@ -159,26 +133,6 @@ Returns:
--*/
;
typedef
UINT32
(*GETINFO_FUNCTION) (
VOID *Source,
UINT32 SrcSize,
UINT32 *DstSize,
UINT32 *ScratchSize
);
typedef
UINT32
(*DECOMPRESS_FUNCTION) (
VOID *Source,
UINT32 SrcSize,
VOID *Destination,
UINT32 DstSize,
VOID *Scratch,
UINT32 ScratchSize
);
#ifdef __cplusplus
}
#endif

View File

@ -47,7 +47,7 @@ typedef uint16_t CHAR16;
#if _MSC_EXTENSIONS
//
// Microsoft* compiler requires _EFIAPI useage, __cdecl is Microsoft* specific C.
// Microsoft* compiler requires _EFIAPI usage, __cdecl is Microsoft* specific C.
//
#define EFIAPI __cdecl
#endif
@ -64,14 +64,40 @@ typedef uint16_t CHAR16;
#define ERR_FILE_OPEN 5
#define ERR_FILE_READ 6
#define ERR_FILE_WRITE 7
#define ERR_INVALID_FLASH_DESCRIPTOR 8
#define ERR_BIOS_REGION_NOT_FOUND 9
#define ERR_VOLUMES_NOT_FOUND 10
#define ERR_INVALID_VOLUME 11
#define ERR_VOLUME_REVISION_NOT_SUPPORTED 12
#define ERR_UNKNOWN_FFS 13
#define ERR_INVALID_FILE 14
#define ERR_ITEM_NOT_FOUND 8
#define ERR_UNKNOWN_ITEM_TYPE 9
#define ERR_INVALID_FLASH_DESCRIPTOR 10
#define ERR_INVALID_REGION 11
#define ERR_EMPTY_REGION 12
#define ERR_BIOS_REGION_NOT_FOUND 13
#define ERR_VOLUMES_NOT_FOUND 14
#define ERR_INVALID_VOLUME 15
#define ERR_VOLUME_REVISION_NOT_SUPPORTED 16
#define ERR_VOLUME_GROW_FAILED 17
#define ERR_UNKNOWN_FFS 18
#define ERR_INVALID_FILE 19
#define ERR_INVALID_SECTION 20
#define ERR_UNKNOWN_SECTION 21
#define ERR_STANDARD_COMPRESSION_FAILED 22
#define ERR_CUSTOMIZED_COMPRESSION_FAILED 23
#define ERR_STANDARD_DECOMPRESSION_FAILED 24
#define ERR_CUSTOMIZED_DECOMPRESSION_FAILED 25
#define ERR_UNKNOWN_COMPRESSION_ALGORITHM 26
#define ERR_NOT_IMPLEMENTED 0xFF
// Compression algorithms
#define COMPRESSION_ALGORITHM_UNKNOWN 0
#define COMPRESSION_ALGORITHM_NONE 1
#define COMPRESSION_ALGORITHM_EFI11 2
#define COMPRESSION_ALGORITHM_TIANO 3
#define COMPRESSION_ALGORITHM_LZMA 4
#define COMPRESSION_ALGORITHM_IMLZMA 5
// Item add modes
#define ADD_MODE_APPEND 0
#define ADD_MODE_PREPEND 1
#define ADD_MODE_INSERT_BEFORE 2
#define ADD_MODE_INSERT_AFTER 3
// EFI GUID
typedef struct{

View File

@ -10,7 +10,26 @@ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*/
#include <QObject>
#include "descriptor.h"
#include "treeitem.h"
QString regionTypeToQString(const UINT8 type)
{
switch (type)
{
case TreeItem::GbeRegion:
return QObject::tr("GbE");
case TreeItem::MeRegion:
return QObject::tr("ME");
case TreeItem::BiosRegion:
return QObject::tr("Bios");
case TreeItem::PdrRegion:
return QObject::tr("PDR");
default:
return QObject::tr("Unknown");
};
}
// Calculate address of data structure addressed by descriptor address format
// 8 bit base or limit

View File

@ -13,6 +13,7 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#ifndef __DESCRIPTOR_H__
#define __DESCRIPTOR_H__
#include <QString>
#include "basetypes.h"
// Make sure we use right packing rules
@ -42,12 +43,12 @@ typedef struct {
UINT8 PchStrapsBase; // 0x10 on most machines
UINT8 NumberOfPchStraps; // One-based number of UINT32s to read as PCH Straps, min=0, max=255 (1 Kb)
UINT8 ProcStrapsBase; // 0x20 on most machines
UINT8 NumberOfProcStraps; // Number of PROC staps to be read, can be 0 or 1
UINT8 NumberOfProcStraps; // Number of PROC straps to be read, can be 0 or 1
UINT8 IccTableBase; // 0x21 on most machines
UINT8 NumberOfIccTableEntries; // 0x00 on most machines
UINT8 DmiTableBase; // 0x25 on most machines
UINT8 NumberOfDmiTableEntries; // 0x00 on most machines
UINT16 ReservedZero; // Still unknown, zeroes in all descriptors I have seen
UINT16 ReservedZero; // Still unknown, zeros in all descriptors I have seen
} FLASH_DESCRIPTOR_MAP;
@ -56,9 +57,9 @@ typedef struct {
typedef struct {
UINT8 FirstChipDensity : 3;
UINT8 SecondFlashDensity : 3;
UINT8 ReservedZero0 : 2; // Still unknown, zeroes in all descriptors I have seen
UINT8 ReservedZero1 : 8; // Still unknown, zeroes in all descriptors I have seen
UINT8 ReservedZero2 : 4; // Still unknown, zeroes in all descriptors I have seen
UINT8 ReservedZero0 : 2; // Still unknown, zeros in all descriptors I have seen
UINT8 ReservedZero1 : 8; // Still unknown, zeros in all descriptors I have seen
UINT8 ReservedZero2 : 4; // Still unknown, zeros in all descriptors I have seen
UINT8 FastReadEnabled : 1;
UINT8 FastReadFreqency : 3;
UINT8 FlashReadStatusFrequency : 3;
@ -153,6 +154,8 @@ typedef struct {
// Restore previous packing rules
#pragma pack(pop)
extern QString regionTypeToQString(const UINT8 type);
// Calculate address of data structure addressed by descriptor address format
// 8 bit base or limit
extern UINT8* calculateAddress8(UINT8* baseAddress, const UINT8 baseOrLimit);

29
ffs.h
View File

@ -72,7 +72,7 @@ const QByteArray APTIO_CAPSULE_GUID("\x8B\xA6\x3C\x4A\x23\x77\xFB\x48\x80\x3D\x5
// FvBlockMap ends with an entry {0x00000000, 0x00000000}
typedef struct {
UINT32 NumBlocks;
UINT32 BlockLength;
UINT32 Length;
} EFI_FV_BLOCK_MAP_ENTRY;
// Volume header
@ -85,7 +85,7 @@ typedef struct {
UINT16 HeaderLength;
UINT16 Checksum;
UINT16 ExtHeaderOffset; //Reserved in Revision 1
UINT8 Reserved[1];
UINT8 Reserved;
UINT8 Revision;
//EFI_FV_BLOCK_MAP_ENTRY FvBlockMap[1];
} EFI_FIRMWARE_VOLUME_HEADER;
@ -248,7 +248,7 @@ typedef struct {
// UINT12 ExtendedSize;
//} EFI_FFS_FILE_HEADER2;
// Standart data checksum, used if FFS_ATTRIB_CHECKSUM is clear
// Standard data checksum, used if FFS_ATTRIB_CHECKSUM is clear
#define FFS_FIXED_CHECKSUM 0x5A
#define FFS_FIXED_CHECKSUM2 0xAA
@ -276,12 +276,12 @@ typedef struct {
#define EFI_FV_FILETYPE_FFS_MAX 0xFF
// File attributes
// Revision 1
#define FFS_ATTRIB_TAIL_PRESENT 0x01
#define FFS_ATTRIB_RESERVED 0x80 // ErasePolarity value can be obtained from that bit
#define FFS_ATTRIB_RECOVERY 0x02
//#define FFS_ATTRIB_HEADER_EXTENSION 0x04 //Must be set to zero in Revision 1
#define FFS_ATTRIB_DATA_ALIGNMENT 0x38
#define FFS_ATTRIB_CHECKSUM 0x40
// Revision 1
#define FFS_ATTRIB_TAIL_PRESENT 0x01
// Revision 2
#define FFS_ATTRIB_LARGE_FILE 0x01
#define FFS_ATTRIB_FIXED 0x04
@ -301,7 +301,7 @@ extern const UINT8 ffsAlignmentTable[];
const QByteArray EFI_FFS_VOLUME_TOP_FILE_GUID
("\x2E\x06\xA0\x1B\x79\xC7\x82\x45\x85\x66\x33\x6A\xE8\xF7\x8F\x09", 16);
// FFS size convertion routines
// FFS size conversion routines
extern VOID uint32ToUint24(UINT32 size, UINT8* ffsSize);
extern UINT32 uint24ToUint32(UINT8* ffsSize);
// FFS file 8bit checksum calculation routine
@ -324,7 +324,7 @@ typedef struct {
//} EFI_COMMON_SECTION_HEADER2;
// File section types
#define EFI_SECTION_ALL 0x00 // Imposible attribute for file in the FS
#define EFI_SECTION_ALL 0x00 // Impossible attribute for file in the FS
// Encapsulation section types
#define EFI_SECTION_COMPRESSION 0x01
@ -355,8 +355,8 @@ typedef struct {
// Compression types
#define EFI_NOT_COMPRESSED 0x00
#define EFI_STANDARD_COMPRESSION 0x01 //Tiano for Revision 2, EFI for Revision 1
#define EFI_CUSTOMIZED_COMPRESSION 0x02 //LZMA for Revision 2 Tiano for Revision 1
#define EFI_STANDARD_COMPRESSION 0x01
#define EFI_CUSTOMIZED_COMPRESSION 0x02
//GUID defined section
typedef struct {
@ -376,7 +376,6 @@ typedef struct {
UINT8 Size[3];
UINT8 Type;
UINT16 BuildNumber;
//CHAR16 VersionString[1];
} EFI_VERSION_SECTION;
// Freeform subtype GUID section
@ -386,13 +385,6 @@ typedef struct {
EFI_GUID SubTypeGuid;
} EFI_FREEFORM_SUBTYPE_GUID_SECTION;
// User interface section
typedef struct {
UINT8 Size[3];
UINT8 Type;
//CHAR16 FileNameString[1];
} EFI_USER_INTERFACE_SECTION;
// Other sections
typedef EFI_COMMON_SECTION_HEADER EFI_DISPOSABLE_SECTION;
typedef EFI_COMMON_SECTION_HEADER EFI_RAW_SECTION;
@ -404,6 +396,7 @@ typedef EFI_COMMON_SECTION_HEADER EFI_PIC_SECTION;
typedef EFI_COMMON_SECTION_HEADER EFI_TE_SECTION;
typedef EFI_COMMON_SECTION_HEADER EFI_COMPATIBILITY16_SECTION;
typedef EFI_COMMON_SECTION_HEADER EFI_FIRMWARE_VOLUME_IMAGE_SECTION;
typedef EFI_COMMON_SECTION_HEADER EFI_USER_INTERFACE_SECTION;
//Section routines
extern UINT32 sizeOfSectionHeaderOfType(const UINT8 type);

File diff suppressed because it is too large Load Diff

View File

@ -16,8 +16,10 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <QObject>
#include <QModelIndex>
#include <QByteArray>
#include <QQueue>
#include "basetypes.h"
#include "treeitem.h"
#include "treemodel.h"
class TreeModel;
@ -27,39 +29,63 @@ class FfsEngine : public QObject
Q_OBJECT
public:
// Default constructor and destructor
FfsEngine(QObject *parent = 0);
~FfsEngine(void);
// Returns model for Qt view classes
TreeModel* model() const;
// Returns current message
QString message() const;
// Firmware image parsing
UINT8 parseInputFile(const QByteArray & buffer);
UINT8* parseRegion(const QByteArray & flashImage, UINT8 regionSubtype, const UINT16 regionBase, const UINT16 regionLimit, QModelIndex & index);
UINT8 parseRegion(const QByteArray & flashImage, const UINT8 regionSubtype, const UINT16 regionBase,
const UINT16 regionLimit, const QModelIndex & parent, QModelIndex & regionIndex);
UINT8 parseBios(const QByteArray & bios, const QModelIndex & parent = QModelIndex());
INT32 findNextVolume(const QByteArray & bios, INT32 volumeOffset = 0);
UINT32 getVolumeSize(const QByteArray & bios, INT32 volumeOffset);
UINT8 parseVolume(const QByteArray & volume, UINT32 volumeBase, UINT8 revision, bool erasePolarity, const QModelIndex & parent = QModelIndex());
UINT8 parseFile(const QByteArray & file, UINT8 revision, bool erasePolarity, const QModelIndex & parent = QModelIndex());
UINT8 findNextVolume(const QByteArray & bios, const UINT32 volumeOffset, UINT32 & nextVolumeOffset);
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 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 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 parseSection(const QByteArray & section, const UINT8 revision, const char empty = '\xFF', const QModelIndex & parent = QModelIndex(), const UINT8 mode = ADD_MODE_APPEND);
QModelIndex addTreeItem(const UINT8 type, const UINT8 subtype = 0, const UINT32 offset = 0,
const QByteArray & header = QByteArray(), const QByteArray & body = QByteArray(),
const QModelIndex & parent = QModelIndex());
bool removeItem(const QModelIndex &index);
// Compression routines
UINT8 decompress(const QByteArray & compressed, const UINT8 compressionType, QByteArray & decompressedSection, UINT8 * algorithm = NULL);
UINT8 compress(const QByteArray & data, const UINT8 algorithm, QByteArray & compressedData);
// Construction routines
UINT8 reconstructImage(QByteArray & reconstructed);
UINT8 constructPadFile(const UINT32 size, const UINT8 revision, const char empty, QByteArray & pad);
UINT8 reconstruct(TreeItem* item, QQueue<QByteArray> & queue, const UINT8 revision = 2, char empty = '\xFF');
// Operations on tree items
UINT8 insert(const QModelIndex & index, const QByteArray & object, const UINT8 type, const UINT8 mode);
UINT8 remove(const QModelIndex & index);
// Proxies to model operations
QByteArray header(const QModelIndex & index) const;
bool hasEmptyHeader(const QModelIndex & index) const;
QByteArray body(const QModelIndex & index) const;
bool hasEmptyBody(const QModelIndex & index) const;
// Item-related operations
bool isOfType(UINT8 type, const QModelIndex & index) const;
bool isOfSubtype(UINT8 subtype, const QModelIndex & index) const;
QModelIndex findParentOfType(UINT8 type, const QModelIndex& index) const;
// Will be refactored later
bool isCompressedFile(const QModelIndex & index) const;
QByteArray uncompressFile(const QModelIndex& index) const;
QByteArray decompressFile(const QModelIndex & index) const;
private:
QString text;
TreeItem *rootItem;
TreeModel *treeModel;
// Adds string to message
void msg(const QString & message);
QModelIndex findParentOfType(UINT8 type, const QModelIndex& index) const;
// Internal operations used in insertInTree
bool setTreeItemName(const QString & data, const QModelIndex & index);
bool setTreeItemText(const QString & data, const QModelIndex & index);
};

View File

@ -11,23 +11,97 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*/
#include <QObject>
#include "treeitem.h"
#include "ffs.h"
#include "descriptor.h"
TreeItem::TreeItem(const UINT8 type, const UINT8 subtype, const UINT32 offset, const QString & name, const QString & typeName, const QString & subtypeName,
const QString & text, const QString & info, const QByteArray & header, const QByteArray & body, TreeItem *parent)
QString itemTypeToQString(const UINT8 type)
{
switch (type) {
case TreeItem::Root:
return QObject::tr("Root");
case TreeItem::Capsule:
return QObject::tr("Capsule");
case TreeItem::Descriptor:
return QObject::tr("Flash descriptor");
case TreeItem::Region:
return QObject::tr("Region");
case TreeItem::Volume:
return QObject::tr("Volume");
case TreeItem::Padding:
return QObject::tr("Padding");
case TreeItem::File:
return QObject::tr("File");
case TreeItem::Section:
return QObject::tr("Section");
default:
return QObject::tr("Unknown");
}
}
QString itemSubtypeToQString(const UINT8 type, const UINT8 subtype)
{
switch (type) {
case TreeItem::Root:
case TreeItem::Descriptor:
case TreeItem::Padding:
case TreeItem::Volume:
return "";
case TreeItem::Capsule:
if (subtype == TreeItem::AptioCapsule)
return QObject::tr("Aptio extended");
else if (subtype == TreeItem::UefiCapsule)
return QObject::tr("UEFI 2.0");
else
return QObject::tr("Unknown");
case TreeItem::Region:
return regionTypeToQString(subtype);
case TreeItem::File:
return fileTypeToQString(subtype);
case TreeItem::Section:
return sectionTypeToQString(subtype);
default:
return QObject::tr("Unknown");
}
}
QString compressionTypeToQString(UINT8 algorithm)
{
switch (algorithm) {
case COMPRESSION_ALGORITHM_NONE:
return QObject::tr("None");
case COMPRESSION_ALGORITHM_EFI11:
return QObject::tr("EFI 1.1");
case COMPRESSION_ALGORITHM_TIANO:
return QObject::tr("Tiano");
case COMPRESSION_ALGORITHM_LZMA:
return QObject::tr("LZMA");
case COMPRESSION_ALGORITHM_IMLZMA:
return QObject::tr("Intel modified LZMA");
default:
return QObject::tr("Unknown");
}
}
TreeItem::TreeItem(const UINT8 type, const UINT8 subtype, const UINT8 compression,
const QString & name, const QString & text, const QString & info,
const QByteArray & header, const QByteArray & body,
TreeItem *parent)
{
itemAction = NoAction;
itemType = type;
itemSubtype = subtype;
itemOffset = offset;
itemCompression = compression;
itemName = name;
itemTypeName = typeName;
itemSubtypeName = subtypeName;
itemText = text;
itemInfo = info;
itemHeader = header;
itemBody = body;
parentItem = parent;
// Set default names
setDefaultNames();
}
TreeItem::~TreeItem()
@ -35,19 +109,43 @@ TreeItem::~TreeItem()
qDeleteAll(childItems);
}
void TreeItem::setDefaultNames()
{
itemTypeName = itemTypeToQString(itemType);
itemSubtypeName = itemSubtypeToQString(itemType, itemSubtype);
}
void TreeItem::appendChild(TreeItem *item)
{
childItems.append(item);
}
void TreeItem::removeChild(TreeItem *item)
void TreeItem::prependChild(TreeItem *item)
{
childItems.removeAll(item);
childItems.prepend(item);
}
UINT8 TreeItem::insertChildBefore(TreeItem *item, TreeItem *newItem)
{
int index = childItems.indexOf(item);
if (index == -1)
return ERR_ITEM_NOT_FOUND;
childItems.insert(index, newItem);
return ERR_SUCCESS;
}
UINT8 TreeItem::insertChildAfter(TreeItem *item, TreeItem *newItem)
{
int index = childItems.indexOf(item);
if (index == -1)
return ERR_ITEM_NOT_FOUND;
childItems.insert(index + 1, newItem);
return ERR_SUCCESS;
}
TreeItem *TreeItem::child(int row)
{
return childItems.value(row);
return childItems.value(row, NULL);
}
int TreeItem::childCount() const
@ -57,27 +155,29 @@ int TreeItem::childCount() const
int TreeItem::columnCount() const
{
return 4;
return 5;
}
QString TreeItem::data(int column) const
QVariant TreeItem::data(int column) const
{
switch(column)
{
case 0: //Object
case 0: //Action
if (itemAction == TreeItem::Remove)
return "X";
if (itemAction == TreeItem::Reconstruct)
return "R";
return QVariant();
case 1: //Name
return itemName;
break;
case 1: //Type
case 2: //Type
return itemTypeName;
break;
case 2: //Subtype
case 3: //Subtype
return itemSubtypeName;
break;
case 3: //Text
case 4: //Text
return itemText;
break;
default:
return "";
return QVariant();
}
}
@ -106,7 +206,7 @@ void TreeItem::setSubtypeName(const QString &text)
itemSubtypeName = text;
}
QString TreeItem::info()
QString TreeItem::info() const
{
return itemInfo;
}
@ -124,37 +224,46 @@ int TreeItem::row() const
return 0;
}
UINT8 TreeItem::type()
UINT8 TreeItem::type() const
{
return itemType;
}
UINT8 TreeItem::subtype()
UINT8 TreeItem::subtype() const
{
return itemSubtype;
}
UINT32 TreeItem::offset()
UINT8 TreeItem::compression() const
{
return itemOffset;
return itemCompression;
}
QByteArray TreeItem::header()
QByteArray TreeItem::header() const
{
return itemHeader;
}
QByteArray TreeItem::body()
QByteArray TreeItem::body() const
{
return itemBody;
}
bool TreeItem::hasEmptyHeader()
bool TreeItem::hasEmptyHeader() const
{
return itemHeader.isEmpty();
}
bool TreeItem::hasEmptyBody()
bool TreeItem::hasEmptyBody() const
{
return itemBody.isEmpty();
}
UINT8 TreeItem::action() const
{
return itemAction;
}
void TreeItem::setAction(const UINT8 action)
{
itemAction = action;
}

View File

@ -17,51 +17,107 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <QByteArray>
#include <QList>
#include <QString>
#include <QVariant>
#include "basetypes.h"
extern QString itemTypeToQString(const UINT8 type);
extern QString itemSubtypeToQString(const UINT8 type, const UINT8 subtype);
extern QString compressionTypeToQString(UINT8 algorithm);
class TreeItem
{
public:
TreeItem(const UINT8 type, const UINT8 subtype = 0, const UINT32 offset = 0, const QString & name = QString(), const QString & typeName = QString(), const QString & subtypeName = QString(),
const QString & text = QString(), const QString & info = QString(), const QByteArray & header = QByteArray(), const QByteArray & body = QByteArray(), TreeItem *parent = 0);
// Action types
enum ActionTypes {
NoAction,
Remove,
Reconstruct
};
// Item types
enum ItemTypes {
Root,
Capsule,
Descriptor,
Region,
Padding,
Volume,
File,
Section
};
// Capsule subtypes
enum CapsuleSubtypes {
AptioCapsule,
UefiCapsule
};
// Region subtypes
enum RegionSubtypes {
GbeRegion,
MeRegion,
BiosRegion,
PdrRegion
};
// Constructor
TreeItem(const UINT8 type, const UINT8 subtype = 0, const UINT8 compression = COMPRESSION_ALGORITHM_NONE,
const QString &name = QString(), const QString &text = QString(), const QString &info = QString(),
const QByteArray & header = QByteArray(), const QByteArray & body = QByteArray(), TreeItem *parent = 0);
// Destructor
~TreeItem();
// Operations with items
void appendChild(TreeItem *item);
void removeChild(TreeItem *item);
void prependChild(TreeItem *item);
UINT8 insertChildBefore(TreeItem *item, TreeItem *newItem);
UINT8 insertChildAfter(TreeItem *item, TreeItem *newItem);
// Model support operations
TreeItem *child(int row);
int childCount() const;
int columnCount() const;
QString data(int column) const;
QVariant data(int column) const;
int row() const;
TreeItem *parent();
UINT8 type();
UINT8 subtype();
UINT32 offset();
QByteArray header();
QByteArray body();
QString info();
bool hasEmptyHeader();
bool hasEmptyBody();
// Reading operations for item parameters
UINT8 type() const;
UINT8 subtype() const;
QByteArray header() const;
bool hasEmptyHeader() const;
QByteArray body() const;
bool hasEmptyBody() const;
QString info() const;
UINT8 compression() const;
void setName(const QString &text);
void setText(const QString &text);
// Actions can also be changed
UINT8 action() const;
void setAction(const UINT8 action);
// Text values can be changed after item construction
void setTypeName(const QString &text);
void setSubtypeName(const QString &text);
void setName(const QString &text);
void setText(const QString &text);
void setInfo(const QString &text);
private:
// Set default names after construction
// They can later be changed by set* methods
void setDefaultNames();
QList<TreeItem*> childItems;
UINT8 itemAction;
UINT8 itemType;
UINT8 itemSubtype;
UINT32 itemOffset;
UINT8 itemCompression;
QByteArray itemHeader;
QByteArray itemBody;
QString itemName;
QString itemTypeName;
QString itemSubtypeName;
QString itemName;
QString itemText;
QString itemInfo;
TreeItem *parentItem;

View File

@ -1,80 +0,0 @@
/* treeitemtypes.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 __TREEITEMTYPES_H__
#define __TREEITEMTYPES_H__
// TreeItem types
enum ItemTypes {
RootItem,
CapsuleItem,
DescriptorItem,
RegionItem,
PaddingItem,
VolumeItem,
FileItem,
SectionItem
};
// Capsule subtypes
enum CapsuleSubtypes {
AptioCapsule,
UefiCapsule
};
// Region subtypes
enum RegionSubtypes {
GbeRegion,
MeRegion,
BiosRegion,
PdrRegion
};
// File subtypes
enum FileSubtypes {
RawFile,
FreeformFile,
SecurityCoreFile,
PeiCoreFile,
DxeCoreFile,
PeiModuleFile,
DxeDriverFile,
CombinedPeiDxeFile,
ApplicationFile,
SmmModuleFile,
VolumeImageFile,
CombinedSmmDxeFile,
SmmCoreFile,
PadFile = 0xF0
};
enum SectionSubtypes {
CompressionSection = 0x01,
GuidDefinedSection,
DisposableSection,
Pe32ImageSection = 0x10,
PicImageSection,
TeImageSection,
DxeDepexSection,
VersionSection,
UserInterfaceSection,
Compatibility16Section,
VolumeImageSection,
FreeformSubtypeGuidSection,
RawSection,
PeiDepexSection = 0x1B,
SmmDepexSection
};
#endif

View File

@ -116,46 +116,84 @@ int TreeModel::rowCount(const QModelIndex &parent) const
return parentItem->childCount();
}
bool TreeModel::setItemName(const QString &data, const QModelIndex &index)
UINT8 TreeModel::setItemName(const QString &data, const QModelIndex &index)
{
if(!index.isValid())
return false;
return ERR_INVALID_PARAMETER;
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
item->setName(data);
emit dataChanged(index, index);
return true;
return ERR_SUCCESS;
}
bool TreeModel::setItemText(const QString &data, const QModelIndex &index)
UINT8 TreeModel::setItemText(const QString &data, const QModelIndex &index)
{
if(!index.isValid())
return false;
return ERR_INVALID_PARAMETER;
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
item->setText(data);
emit dataChanged(index, index);
return true;
return ERR_SUCCESS;
}
QModelIndex TreeModel::addItem(const UINT8 type, const UINT8 subtype, const UINT32 offset, const QString & name, const QString & typeName,
const QString & subtypeName, const QString & text, const QString & info,
const QByteArray & header, const QByteArray & body, const QModelIndex & parent)
UINT8 TreeModel::setItemAction(const UINT8 action, const QModelIndex &index)
{
if(!index.isValid())
return ERR_INVALID_PARAMETER;
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
item->setAction(action);
emit dataChanged(index, index);
return ERR_SUCCESS;
}
QModelIndex TreeModel::addItem(const UINT8 type, const UINT8 subtype, const UINT8 compression,
const QString & name, const QString & text, const QString & info,
const QByteArray & header, const QByteArray & body, const QModelIndex & index,
const UINT8 mode)
{
TreeItem *item;
TreeItem *parentItem;
int parentColumn = 0;
if (!parent.isValid())
if (!index.isValid())
parentItem = rootItem;
else
{
parentItem = static_cast<TreeItem*>(parent.internalPointer());
parentColumn = parent.column();
if (mode == ADD_MODE_APPEND || mode == ADD_MODE_PREPEND) {
parentItem = static_cast<TreeItem*>(index.internalPointer());
parentColumn = index.column();
}
else {
item = static_cast<TreeItem*>(index.internalPointer());
parentItem = item->parent();
parentColumn = index.parent().column();
}
}
TreeItem *newItem = new TreeItem(type, subtype, compression, name, text, info, header, body, parentItem);
if (mode == ADD_MODE_APPEND) {
emit layoutAboutToBeChanged();
TreeItem *item = new TreeItem(type, subtype, offset, name, typeName, subtypeName, text, info, header, body, parentItem);
parentItem->appendChild(item);
emit layoutChanged();
return createIndex(parentItem->childCount() - 1, parentColumn, item);
parentItem->appendChild(newItem);
}
else if (mode == ADD_MODE_PREPEND) {
emit layoutAboutToBeChanged();
parentItem->prependChild(newItem);
}
else if (mode == ADD_MODE_INSERT_BEFORE) {
emit layoutAboutToBeChanged();
parentItem->insertChildBefore(item, newItem);
}
else if (mode == ADD_MODE_INSERT_AFTER) {
emit layoutAboutToBeChanged();
parentItem->insertChildAfter(item, newItem);
}
else
return QModelIndex();
emit layoutChanged();
return createIndex(newItem->row(), parentColumn, newItem);
}

View File

@ -41,12 +41,14 @@ public:
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
bool setItemName(const QString &data, const QModelIndex &index);
bool setItemText(const QString &data, const QModelIndex &index);
UINT8 setItemName(const QString &data, const QModelIndex &index);
UINT8 setItemText(const QString &data, const QModelIndex &index);
UINT8 setItemAction(const UINT8 action, const QModelIndex &index);
QModelIndex addItem(const UINT8 type, const UINT8 subtype = 0, const UINT32 offset = 0, const QString & name = QString(),
const QString & typeName = QString(), const QString & subtypeName = QString(), const QString & text = QString(),
const QString & info = QString(), const QByteArray & header = QByteArray(), const QByteArray & body = QByteArray(), const QModelIndex & parent = QModelIndex());
QModelIndex addItem(const UINT8 type, const UINT8 subtype = 0, const UINT8 compression = COMPRESSION_ALGORITHM_NONE,
const QString & name = QString(), const QString & text = QString(), const QString & info = QString(),
const QByteArray & header = QByteArray(), const QByteArray & body = QByteArray(), const QModelIndex & index = QModelIndex(),
const UINT8 mode = ADD_MODE_APPEND);
private:
TreeItem *rootItem;

View File

@ -23,9 +23,15 @@ UEFITool::UEFITool(QWidget *parent) :
//Connect
connect(ui->actionOpenImageFile, SIGNAL(triggered()), this, SLOT(openImageFile()));
connect(ui->actionExtract, SIGNAL(triggered()), this, SLOT(saveAll()));
connect(ui->actionExtractBody, SIGNAL(triggered()), this, SLOT(saveBody()));
connect(ui->actionExtractUncompressed, SIGNAL(triggered()), this, SLOT(saveUncompressedFile()));
connect(ui->actionExtract, SIGNAL(triggered()), this, SLOT(extract()));
connect(ui->actionExtractBody, SIGNAL(triggered()), this, SLOT(extractBody()));
connect(ui->actionExtractUncompressed, SIGNAL(triggered()), this, SLOT(extractUncompressed()));
connect(ui->actionInsertInto, SIGNAL(triggered()), this, SLOT(insertInto()));
connect(ui->actionInsertBefore, SIGNAL(triggered()), this, SLOT(insertBefore()));
connect(ui->actionInsertAfter, SIGNAL(triggered()), this, SLOT(insertAfter()));
connect(ui->actionReplace, SIGNAL(triggered()), this, SLOT(replace()));
connect(ui->actionRemove, SIGNAL(triggered()), this, SLOT(remove()));
connect(ui->actionSaveImageFile, SIGNAL(triggered()), this, SLOT(saveImageFile()));
// Enable Drag-and-Drop actions
this->setAcceptDrops(true);
@ -50,10 +56,11 @@ void UEFITool::init()
ui->actionExtractBody->setDisabled(true);
ui->actionExtractUncompressed->setDisabled(true);
ui->actionReplace->setDisabled(true);
ui->actionDelete->setDisabled(true);
ui->actionReplaceWithPadding->setDisabled(true);
ui->actionRemove->setDisabled(true);
ui->actionInsertInto->setDisabled(true);
ui->actionInsertBefore->setDisabled(true);
ui->actionInsertAfter->setDisabled(true);
ui->actionSaveImageFile->setDisabled(true);
// Make new ffsEngine
ffsEngine = new FfsEngine(this);
@ -64,7 +71,6 @@ void UEFITool::init()
connect(ui->structureTreeView, SIGNAL(expanded(const QModelIndex &)), this, SLOT(resizeTreeViewColums(void)));
connect(ui->structureTreeView->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
this, SLOT(populateUi(const QModelIndex &)));
resizeTreeViewColums();
}
void UEFITool::populateUi(const QModelIndex &current/*, const QModelIndex &previous*/)
@ -75,9 +81,151 @@ void UEFITool::populateUi(const QModelIndex &current/*, const QModelIndex &previ
ui->actionExtract->setDisabled(ffsEngine->hasEmptyBody(current) && ffsEngine->hasEmptyHeader(current));
ui->actionExtractBody->setDisabled(ffsEngine->hasEmptyHeader(current));
ui->actionExtractUncompressed->setEnabled(ffsEngine->isCompressedFile(current));
ui->actionRemove->setEnabled(ffsEngine->isOfType(TreeItem::Volume, current)
|| ffsEngine->isOfType(TreeItem::File, current)
|| ffsEngine->isOfType(TreeItem::Section, current));
ui->actionInsertInto->setEnabled(ffsEngine->isOfType(TreeItem::Volume, current));
ui->actionInsertBefore->setEnabled(ffsEngine->isOfType(TreeItem::File, current));
ui->actionInsertAfter->setEnabled(ffsEngine->isOfType(TreeItem::File, current));
ui->actionReplace->setEnabled(ffsEngine->isOfType(TreeItem::File, current));
}
void UEFITool::resizeTreeViewColums(/*const QModelIndex &index*/)
void UEFITool::remove()
{
UINT8 result = ffsEngine->remove(currentIndex);
if (result) {
ui->debugEdit->setPlainText(ffsEngine->message());
}
else
ui->actionSaveImageFile->setEnabled(true);
resizeTreeViewColums();
}
void UEFITool::insertInto()
{
QString path = QFileDialog::getOpenFileName(this, tr("Select FFS file to insert"),".","FFS file (*.ffs *.bin);;All files (*.*)");
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()
{
QString path = QFileDialog::getOpenFileName(this, tr("Select FFS file to insert"),".","FFS file (*.ffs *.bin);;All files (*.*)");
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()
{
QString path = QFileDialog::getOpenFileName(this, tr("Select FFS file to insert"),".","FFS file (*.ffs *.bin);;All files (*.*)");
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()
{
remove();
insertAfter();
}
void UEFITool::saveImageFile()
{
QString path = QFileDialog::getSaveFileName(this, tr("Save BIOS image file"),".","BIOS image file (*.rom *.bin *.cap *.fd *.fwh);;All files (*.*)");
QFile outputFile;
outputFile.setFileName(path);
if (!outputFile.open(QFile::WriteOnly))
{
ui->statusBar->showMessage(tr("Can't open file for writing"));
return;
}
QByteArray reconstructed;
UINT8 result = ffsEngine->reconstructImage(reconstructed);
if (result)
{
ui->statusBar->showMessage(tr("Reconstruction failed (%1)").arg(result));
ui->debugEdit->setPlainText(ffsEngine->message());
return;
}
outputFile.write(reconstructed);
outputFile.close();
ui->statusBar->showMessage(tr("Reconstructed image written"));
ui->debugEdit->setPlainText(ffsEngine->message());
}
void UEFITool::resizeTreeViewColums()
{
int count = ffsEngine->model()->columnCount();
for(int i = 0; i < count; i++)
@ -95,7 +243,7 @@ void UEFITool::openImageFile(QString path)
QFileInfo fileInfo = QFileInfo(path);
if (!fileInfo.exists())
{
ui->statusBar->showMessage(tr("Please select existing BIOS image file."));
ui->statusBar->showMessage(tr("Please select existing BIOS image file"));
return;
}
@ -104,7 +252,7 @@ void UEFITool::openImageFile(QString path)
if (!inputFile.open(QFile::ReadOnly))
{
ui->statusBar->showMessage(tr("Can't open file for reading. Check file permissions."));
ui->statusBar->showMessage(tr("Can't open file for reading"));
return;
}
@ -119,10 +267,11 @@ void UEFITool::openImageFile(QString path)
ui->statusBar->showMessage(tr("Opened: %1").arg(fileInfo.fileName()));
ui->debugEdit->appendPlainText(ffsEngine->message());
resizeTreeViewColums();
}
void UEFITool::saveAll()
void UEFITool::extract()
{
QString path = QFileDialog::getSaveFileName(this, tr("Save selected item to binary file"),".","Binary files (*.bin);;All files (*.*)");
@ -138,7 +287,7 @@ void UEFITool::saveAll()
outputFile.close();
}
void UEFITool::saveBody()
void UEFITool::extractBody()
{
QString path = QFileDialog::getSaveFileName(this, tr("Save selected item without header to binary file"),".","Binary files (*.bin);;All files (*.*)");
@ -154,7 +303,7 @@ void UEFITool::saveBody()
outputFile.close();
}
void UEFITool::saveUncompressedFile()
void UEFITool::extractUncompressed()
{
QString path = QFileDialog::getSaveFileName(this, tr("Save selected FFS file as uncompressed to binary file"),".","FFS files (*.ffs);;All files (*.*)");
@ -166,7 +315,7 @@ void UEFITool::saveUncompressedFile()
return;
}
outputFile.write(ffsEngine->uncompressFile(currentIndex));
outputFile.write(ffsEngine->decompressFile(currentIndex));
outputFile.close();
}

View File

@ -46,11 +46,17 @@ public:
private slots:
void init();
void openImageFile();
void populateUi(const QModelIndex &current/*, const QModelIndex &previous*/);
void resizeTreeViewColums(/*const QModelIndex &index*/);
void saveAll();
void saveBody();
void saveUncompressedFile();
void saveImageFile();
void populateUi(const QModelIndex &current);
void resizeTreeViewColums();
void extract();
void extractBody();
void extractUncompressed();
void insertInto();
void insertBefore();
void insertAfter();
void replace();
void remove();
private:
Ui::UEFITool * ui;

View File

@ -27,7 +27,6 @@ HEADERS += uefitool.h \
ffs.h \
ffsengine.h \
treeitem.h \
treeitemtypes.h \
treemodel.h \
LZMA/LzmaCompress.h \
LZMA/LzmaDecompress.h \

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>900</width>
<height>700</height>
<height>600</height>
</rect>
</property>
<property name="sizePolicy">
@ -20,7 +20,7 @@
<bool>true</bool>
</property>
<property name="windowTitle">
<string>UEFITool 0.3.0</string>
<string>UEFITool 0.4.0</string>
</property>
<widget class="QWidget" name="centralWidget">
<property name="sizePolicy">
@ -30,6 +30,12 @@
</sizepolicy>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<property name="margin">
<number>5</number>
</property>
<property name="spacing">
<number>5</number>
</property>
<item row="0" column="0">
<widget class="QGroupBox" name="structureGroupBox">
<property name="sizePolicy">
@ -42,6 +48,12 @@
<string>Structure</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="margin">
<number>5</number>
</property>
<property name="spacing">
<number>5</number>
</property>
<item row="0" column="0" colspan="2">
<widget class="QTreeView" name="structureTreeView">
<property name="font">
@ -80,7 +92,7 @@
</property>
<property name="maximumSize">
<size>
<width>216</width>
<width>220</width>
<height>16777215</height>
</size>
</property>
@ -89,7 +101,10 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>3</number>
<number>5</number>
</property>
<property name="margin">
<number>5</number>
</property>
<item>
<widget class="QPlainTextEdit" name="infoEdit">
@ -99,12 +114,6 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>200</width>
<height>16777215</height>
</size>
</property>
<property name="font">
<font>
<family>Consolas</family>
@ -137,6 +146,12 @@
<string>Debug</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>5</number>
</property>
<property name="margin">
<number>5</number>
</property>
<item>
<widget class="QPlainTextEdit" name="debugEdit">
<property name="sizePolicy">
@ -148,7 +163,7 @@
<property name="maximumSize">
<size>
<width>16777215</width>
<height>100</height>
<height>80</height>
</size>
</property>
<property name="baseSize">
@ -194,18 +209,19 @@
<bool>false</bool>
</attribute>
<addaction name="actionOpenImageFile"/>
<addaction name="actionSaveImageFile"/>
<addaction name="separator"/>
<addaction name="actionExtract"/>
<addaction name="actionExtractBody"/>
<addaction name="actionExtractUncompressed"/>
<addaction name="separator"/>
<addaction name="actionInsertInto"/>
<addaction name="actionInsertBefore"/>
<addaction name="actionInsertAfter"/>
<addaction name="separator"/>
<addaction name="actionReplace"/>
<addaction name="separator"/>
<addaction name="actionDelete"/>
<addaction name="actionReplaceWithPadding"/>
<addaction name="actionRemove"/>
<addaction name="separator"/>
</widget>
<action name="actionInsertAfter">
@ -213,7 +229,7 @@
<bool>false</bool>
</property>
<property name="text">
<string>Insert after</string>
<string>Insert after...</string>
</property>
<property name="toolTip">
<string>Insert an object from file after selected object</string>
@ -227,10 +243,10 @@
<bool>false</bool>
</property>
<property name="text">
<string>Insert before</string>
<string>Insert before...</string>
</property>
<property name="toolTip">
<string>Insert an object from file before selected object</string>
<string>Insert object from file before selected object</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+I</string>
@ -255,7 +271,7 @@
<bool>false</bool>
</property>
<property name="text">
<string>Extract</string>
<string>Extract...</string>
</property>
<property name="toolTip">
<string>Extract selected object to file</string>
@ -269,7 +285,7 @@
<bool>false</bool>
</property>
<property name="text">
<string>Extract body</string>
<string>Extract body...</string>
</property>
<property name="toolTip">
<string>Extract selected object without header to file</string>
@ -283,7 +299,7 @@
<bool>false</bool>
</property>
<property name="text">
<string>Extract uncompressed</string>
<string>Extract uncompressed...</string>
</property>
<property name="toolTip">
<string>Extract selected FFS file uncompressing it </string>
@ -292,37 +308,23 @@
<string>Ctrl+Alt+E</string>
</property>
</action>
<action name="actionDelete">
<action name="actionRemove">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Delete</string>
<string>Remove</string>
</property>
<property name="toolTip">
<string>Delete selected object</string>
<string>Remove selected object</string>
</property>
<property name="shortcut">
<string>Ctrl+D</string>
</property>
</action>
<action name="actionReplaceWithPadding">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Replace with padding</string>
</property>
<property name="toolTip">
<string>Delete an object by replacing it with padding</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+D</string>
<string>Ctrl+Del</string>
</property>
</action>
<action name="actionOpenImageFile">
<property name="text">
<string>Open image file</string>
<string>Open image file...</string>
</property>
<property name="toolTip">
<string>Open image file</string>
@ -331,6 +333,34 @@
<string>Ctrl+O</string>
</property>
</action>
<action name="actionInsertInto">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Insert into...</string>
</property>
<property name="toolTip">
<string>Insert object from file into selected object</string>
</property>
<property name="shortcut">
<string>Ctrl+Ins</string>
</property>
</action>
<action name="actionSaveImageFile">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Save image file...</string>
</property>
<property name="toolTip">
<string>Save modified image file</string>
</property>
<property name="shortcut">
<string>Ctrl+S</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>