NE A21: deQtization begins

- added FfsBuilder code and UI, but reconstruction routines for volumes,
files and sections are still not ready
- FfsOps moved to common
- QVector and QPair aren't used anymore, replaces with std::vector and
std::pair
- common classes are now independent from QObject
- next step is to replace QString with CBString from bstrlib
This commit is contained in:
Nikolaj Schlej 2016-03-01 08:20:44 +01:00
parent b7ec76e091
commit 2024c1898b
21 changed files with 729 additions and 658 deletions

View file

@ -72,13 +72,14 @@ typedef UINT8 STATUS;
#define ERR_UNKNOWN_COMPRESSION_TYPE 26
#define ERR_DEPEX_PARSE_FAILED 27
#define ERR_UNKNOWN_EXTRACT_MODE 28
#define ERR_UNKNOWN_IMAGE_TYPE 29
#define ERR_UNKNOWN_PE_OPTIONAL_HEADER_TYPE 30
#define ERR_UNKNOWN_RELOCATION_TYPE 31
#define ERR_DIR_ALREADY_EXIST 32
#define ERR_DIR_CREATE 33
#define ERR_TRUNCATED_IMAGE 34
#define ERR_INVALID_CAPSULE 35
#define ERR_UNKNOWN_REPLACE_MODE 29
#define ERR_UNKNOWN_IMAGE_TYPE 30
#define ERR_UNKNOWN_PE_OPTIONAL_HEADER_TYPE 31
#define ERR_UNKNOWN_RELOCATION_TYPE 32
#define ERR_DIR_ALREADY_EXIST 33
#define ERR_DIR_CREATE 34
#define ERR_TRUNCATED_IMAGE 35
#define ERR_INVALID_CAPSULE 36
#define ERR_NOT_IMPLEMENTED 0xFF
// UDK porting definitions

View file

@ -10,7 +10,6 @@ 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"
// Calculate address of data structure addressed by descriptor address format

View file

@ -13,7 +13,6 @@ 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

View file

@ -13,19 +13,19 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <QObject>
#include "ffs.h"
const QVector<QByteArray> FFSv2Volumes =
QVector<QByteArray>()
<< EFI_FIRMWARE_FILE_SYSTEM_GUID
<< EFI_FIRMWARE_FILE_SYSTEM2_GUID
<< EFI_APPLE_BOOT_VOLUME_FILE_SYSTEM_GUID
<< EFI_APPLE_BOOT_VOLUME_FILE_SYSTEM2_GUID
<< EFI_INTEL_FILE_SYSTEM_GUID
<< EFI_INTEL_FILE_SYSTEM2_GUID
<< EFI_SONY_FILE_SYSTEM_GUID;
const std::vector<QByteArray> FFSv2Volumes({
EFI_FIRMWARE_FILE_SYSTEM_GUID,
EFI_FIRMWARE_FILE_SYSTEM2_GUID,
EFI_APPLE_BOOT_VOLUME_FILE_SYSTEM_GUID,
EFI_APPLE_BOOT_VOLUME_FILE_SYSTEM2_GUID,
EFI_INTEL_FILE_SYSTEM_GUID,
EFI_INTEL_FILE_SYSTEM2_GUID,
EFI_SONY_FILE_SYSTEM_GUID
});
const QVector<QByteArray> FFSv3Volumes =
QVector<QByteArray>()
<< EFI_FIRMWARE_FILE_SYSTEM3_GUID;
const std::vector<QByteArray> FFSv3Volumes({
EFI_FIRMWARE_FILE_SYSTEM3_GUID
});
const UINT8 ffsAlignmentTable[] =
{ 0, 4, 7, 9, 10, 12, 15, 16 };

View file

@ -15,7 +15,6 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <QByteArray>
#include <QString>
#include <QVector>
#include "basetypes.h"
// C++ functions
@ -138,13 +137,13 @@ const QByteArray EFI_SONY_FILE_SYSTEM_GUID
// 4F494156-AED6-4D64-A537-B8A5557BCEEC // Sony 1
// Vector of volume GUIDs with FFSv2-compatible files
extern const QVector<QByteArray> FFSv2Volumes;
extern const std::vector<QByteArray> FFSv2Volumes;
const QByteArray EFI_FIRMWARE_FILE_SYSTEM3_GUID // 5473C07A-3DCB-4dca-BD6F-1E9689E7349A
("\x7A\xC0\x73\x54\xCB\x3D\xCA\x4D\xBD\x6F\x1E\x96\x89\xE7\x34\x9A", 16);
// Vector of volume GUIDs with FFSv3-compatible files
extern const QVector<QByteArray> FFSv3Volumes;
extern const std::vector<QByteArray> FFSv3Volumes;
// Firmware volume signature
const QByteArray EFI_FV_SIGNATURE("_FVH", 4);

View file

@ -12,8 +12,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*/
#include "ffsbuilder.h"
FfsBuilder::FfsBuilder(const TreeModel* treeModel, QObject *parent)
: QObject(parent), model(treeModel)
FfsBuilder::FfsBuilder(const TreeModel* treeModel)
: model(treeModel)
{
}
@ -23,10 +23,10 @@ FfsBuilder::~FfsBuilder()
void FfsBuilder::msg(const QString & message, const QModelIndex & index)
{
messagesVector.push_back(QPair<QString, QModelIndex>(message, index));
messagesVector.push_back(std::pair<QString, QModelIndex>(message, index));
}
QVector<QPair<QString, QModelIndex> > FfsBuilder::getMessages() const
std::vector<std::pair<QString, QModelIndex> > FfsBuilder::getMessages() const
{
return messagesVector;
}
@ -47,6 +47,27 @@ STATUS FfsBuilder::erase(const QModelIndex & index, QByteArray & erased)
return ERR_SUCCESS;
}
STATUS FfsBuilder::build(const QModelIndex & root, QByteArray & image)
{
// Sanity check
if (!root.isValid())
return ERR_INVALID_PARAMETER;
if (model->type(root) == Types::Capsule) {
return buildCapsule(root, image);
}
else if (model->type(root) == Types::Image) {
if (model->subtype(root) == Subtypes::IntelImage) {
return buildIntelImage(root, image);
}
else if (model->subtype(root) == Subtypes::IntelImage) {
return buildRawArea(root, image);
}
}
return ERR_NOT_IMPLEMENTED;
}
STATUS FfsBuilder::buildCapsule(const QModelIndex & index, QByteArray & capsule)
{
// Sanity check
@ -69,7 +90,7 @@ STATUS FfsBuilder::buildCapsule(const QModelIndex & index, QByteArray & capsule)
// Right now there is only one capsule image element supported
if (model->rowCount(index) != 1) {
msg(tr("buildCapsule: building of capsules with %1 elements are not supported, original item data is used").arg(model->rowCount(index)), index);
msg(QObject::tr("buildCapsule: building of capsules with %1 elements are not supported, original item data is used").arg(model->rowCount(index)), index);
// Use original item data
capsule = model->header(index).append(model->body(index));
return ERR_SUCCESS;
@ -82,21 +103,27 @@ STATUS FfsBuilder::buildCapsule(const QModelIndex & index, QByteArray & capsule)
// Check image type
if (model->type(imageIndex) == Types::Image) {
STATUS result;
if (model->subtype(imageIndex) == Subtypes::IntelImage)
if (model->subtype(imageIndex) == Subtypes::IntelImage) {
result = buildIntelImage(imageIndex, imageData);
else
}
else if (model->subtype(imageIndex) == Subtypes::UefiImage) {
result = buildRawArea(imageIndex, imageData);
}
else {
msg(QObject::tr("buildCapsule: unexpected item of subtype %1 can't be processed, original item data is used").arg(model->subtype(imageIndex)), imageIndex);
capsule.append(model->header(imageIndex)).append(model->body(imageIndex));
}
// Check build result
if (result) {
msg(tr("buildCapsule: building of \"%1\" failed with error \"%2\", original item data is used").arg(model->name(imageIndex)).arg(errorCodeToQString(result)), imageIndex);
msg(QObject::tr("buildCapsule: building of \"%1\" failed with error \"%2\", original item data is used").arg(model->name(imageIndex)).arg(errorCodeToQString(result)), imageIndex);
capsule.append(model->header(imageIndex)).append(model->body(imageIndex));
}
else
capsule.append(imageData);
}
else {
msg(tr("buildCapsule: unexpected child item of type \"%1\" can't be processed, original item data is used").arg(itemTypeToQString(model->type(imageIndex))), imageIndex);
msg(QObject::tr("buildCapsule: unexpected item of type %1 can't be processed, original item data is used").arg(model->type(imageIndex)), imageIndex);
capsule.append(model->header(imageIndex)).append(model->body(imageIndex));
}
@ -104,12 +131,12 @@ STATUS FfsBuilder::buildCapsule(const QModelIndex & index, QByteArray & capsule)
UINT32 newSize = capsule.size();
UINT32 oldSize = model->body(index).size();
if (newSize > oldSize) {
msg(tr("buildCapsule: new capsule body size %1h (%2) is bigger than the original %3h (%4)")
msg(QObject::tr("buildCapsule: new capsule body size %1h (%2) is bigger than the original %3h (%4)")
.hexarg(newSize).arg(newSize).hexarg(oldSize).arg(oldSize),index);
return ERR_INVALID_PARAMETER;
}
else if (newSize < oldSize) {
msg(tr("buildCapsule: new capsule body size %1h (%2) is smaller than the original %3h (%4)")
msg(QObject::tr("buildCapsule: new capsule body size %1h (%2) is smaller than the original %3h (%4)")
.hexarg(newSize).arg(newSize).hexarg(oldSize).arg(oldSize), index);
return ERR_INVALID_PARAMETER;
}
@ -122,7 +149,7 @@ STATUS FfsBuilder::buildCapsule(const QModelIndex & index, QByteArray & capsule)
return ERR_SUCCESS;
}
msg(tr("buildCapsule: unexpected action \"%1\"").arg(actionTypeToQString(model->action(index))), index);
msg(QObject::tr("buildCapsule: unexpected action \"%1\"").arg(actionTypeToQString(model->action(index))), index);
return ERR_NOT_IMPLEMENTED;
}
@ -138,22 +165,17 @@ STATUS FfsBuilder::buildIntelImage(const QModelIndex & index, QByteArray & intel
return ERR_SUCCESS;
}
// Other supported actions
// Rebuild
else if (model->action(index) == Actions::Rebuild) {
intelImage.clear();
// First child will always be descriptor for this type of image, and it's read only
QByteArray descriptor = model->header(index.child(0, 0)).append(model->body(index.child(0, 0)));
// Other regions can be in different order, GbE, PDR and EC may be skipped
QByteArray gbe;
QByteArray me;
QByteArray bios;
QByteArray pdr;
QByteArray ec;
QByteArray padding;
// First child will always be descriptor for this type of image, and it's read only
intelImage.append(model->header(index.child(0, 0)).append(model->body(index.child(0, 0))));
// Process other regions
for (int i = 1; i < model->rowCount(index); i++) {
QModelIndex currentRegion = index.child(i, 0);
// Skip regions with Remove action
if (model->action(currentRegion) == Actions::Remove)
continue;
@ -161,89 +183,53 @@ STATUS FfsBuilder::buildIntelImage(const QModelIndex & index, QByteArray & intel
// Check item type to be either region or padding
UINT8 type = model->type(currentRegion);
if (type == Types::Padding) {
if (!padding.isEmpty()) {
msg(tr("buildIntelImage: more than one padding found during image rebuild, the latest one is used"), index);
}
padding = model->header(currentRegion).append(model->body(currentRegion));
// Add padding as is
intelImage.append(model->header(currentRegion).append(model->body(currentRegion)));
continue;
}
// Check region subtype
STATUS result;
QByteArray region;
UINT8 regionType = model->subtype(currentRegion);
switch (regionType) {
case Subtypes::GbeRegion:
if (!gbe.isEmpty()) {
msg(tr("buildIntelImage: more than one GbE region found during image rebuild, the latest one is used"), index);
}
result = buildGbeRegion(currentRegion, gbe);
if (result) {
msg(tr("buildIntelImage: building of GbE region failed with error \"%1\", original item data is used").arg(errorCodeToQString(result)), currentRegion);
gbe = model->header(currentRegion).append(model->body(currentRegion));
}
break;
case Subtypes::MeRegion:
if (!me.isEmpty()) {
msg(tr("buildIntelImage: more than one ME region found during image rebuild, the latest one is used"), index);
}
result = buildMeRegion(currentRegion, me);
if (result) {
msg(tr("buildIntelImage: building of ME region failed with error \"%1\", original item data is used").arg(errorCodeToQString(result)), currentRegion);
me = model->header(currentRegion).append(model->body(currentRegion));
}
break;
case Subtypes::BiosRegion:
if (!bios.isEmpty()) {
msg(tr("buildIntelImage: more than one BIOS region found during image rebuild, the latest one is used"), index);
}
result = buildRawArea(currentRegion, bios);
if (result) {
msg(tr("buildIntelImage: building of BIOS region failed with error \"%1\", original item data is used").arg(errorCodeToQString(result)), currentRegion);
bios = model->header(currentRegion).append(model->body(currentRegion));
}
break;
case Subtypes::PdrRegion:
if (!pdr.isEmpty()) {
msg(tr("buildIntelImage: more than one PDR region found during image rebuild, the latest one is used"), index);
}
result = buildPdrRegion(currentRegion, pdr);
result = buildRawArea(currentRegion, region);
if (result) {
msg(tr("buildIntelImage: building of PDR region failed with error \"%1\", original item data is used").arg(errorCodeToQString(result)), currentRegion);
pdr = model->header(currentRegion).append(model->body(currentRegion));
msg(QObject::tr("buildIntelImage: building of %1 region failed with error \"%2\", original item data is used").arg(regionTypeToQString(regionType)).arg(errorCodeToQString(result)), currentRegion);
region = model->header(currentRegion).append(model->body(currentRegion));
}
break;
case Subtypes::GbeRegion:
case Subtypes::MeRegion:
case Subtypes::EcRegion:
if (!ec.isEmpty()) {
msg(tr("buildIntelImage: more than one EC region found during image rebuild, the latest one is used"), index);
}
result = buildEcRegion(currentRegion, ec);
if (result) {
msg(tr("buildIntelImage: building of EC region failed with error \"%1\", original item data is used").arg(errorCodeToQString(result)), currentRegion);
ec = model->header(currentRegion).append(model->body(currentRegion));
}
case Subtypes::Reserved1Region:
case Subtypes::Reserved2Region:
case Subtypes::Reserved3Region:
case Subtypes::Reserved4Region:
// Add region as is
region = model->header(currentRegion).append(model->body(currentRegion));
break;
default:
msg(tr("buildIntelImage: don't know how to build region of unknown type"), index);
msg(QObject::tr("buildIntelImage: don't know how to build region of unknown type"), index);
return ERR_UNKNOWN_ITEM_TYPE;
}
// Append the resulting region
intelImage.append(region);
}
// Check size of new image, it must be same as old one
UINT32 newSize = intelImage.size();
UINT32 oldSize = model->body(index).size();
if (newSize > oldSize) {
msg(tr("buildIntelImage: new image size %1h (%2) is bigger than the original %3h (%4)")
msg(QObject::tr("buildIntelImage: new image size %1h (%2) is bigger than the original %3h (%4)")
.hexarg(newSize).arg(newSize).hexarg(oldSize).arg(oldSize), index);
return ERR_INVALID_PARAMETER;
}
else if (newSize < oldSize) {
msg(tr("buildIntelImage: new image size %1h (%2) is smaller than the original %3h (%4)")
msg(QObject::tr("buildIntelImage: new image size %1h (%2) is smaller than the original %3h (%4)")
.hexarg(newSize).arg(newSize).hexarg(oldSize).arg(oldSize), index);
return ERR_INVALID_PARAMETER;
}
@ -252,27 +238,7 @@ STATUS FfsBuilder::buildIntelImage(const QModelIndex & index, QByteArray & intel
return ERR_SUCCESS;
}
msg(tr("buildIntelImage: unexpected action \"%1\"").arg(actionTypeToQString(model->action(index))), index);
return ERR_NOT_IMPLEMENTED;
}
STATUS FfsBuilder::buildGbeRegion(const QModelIndex & index, QByteArray & region)
{
return ERR_NOT_IMPLEMENTED;
}
STATUS FfsBuilder::buildMeRegion(const QModelIndex & index, QByteArray & region)
{
return ERR_NOT_IMPLEMENTED;
}
STATUS FfsBuilder::buildPdrRegion(const QModelIndex & index, QByteArray & region)
{
return ERR_NOT_IMPLEMENTED;
}
STATUS FfsBuilder::buildEcRegion(const QModelIndex & index, QByteArray & region)
{
msg(QObject::tr("buildIntelImage: unexpected action \"%1\"").arg(actionTypeToQString(model->action(index))), index);
return ERR_NOT_IMPLEMENTED;
}
@ -282,8 +248,6 @@ STATUS FfsBuilder::buildRawArea(const QModelIndex & index, QByteArray & rawArea,
if (!index.isValid())
return ERR_INVALID_PARAMETER;
STATUS result;
// No action required
if (model->action(index) == Actions::NoAction) {
rawArea = model->header(index).append(model->body(index));
@ -299,6 +263,7 @@ STATUS FfsBuilder::buildRawArea(const QModelIndex & index, QByteArray & rawArea,
// Build children
for (int i = 0; i < model->rowCount(index); i++) {
STATUS result = ERR_SUCCESS;
QModelIndex currentChild = index.child(i, 0);
QByteArray currentData;
// Check child type
@ -309,13 +274,12 @@ STATUS FfsBuilder::buildRawArea(const QModelIndex & index, QByteArray & rawArea,
result = buildPadding(currentChild, currentData);
}
else {
msg(tr("buildRawArea: unexpected child item of type \"%1\" can't be processed, original item data is used").arg(itemTypeToQString(model->type(currentChild))), currentChild);
result = ERR_SUCCESS;
msg(QObject::tr("buildRawArea: unexpected item of type %1 can't be processed, original item data is used").arg(model->type(currentChild)), currentChild);
currentData = model->header(currentChild).append(model->body(currentChild));
}
// Check build result
if (result) {
msg(tr("buildRawArea: building of \"%1\" failed with error \"%2\", original item data is used").arg(model->name(currentChild)).arg(errorCodeToQString(result)), currentChild);
msg(QObject::tr("buildRawArea: building of %1 failed with error \"%2\", original item data is used").arg(model->name(currentChild)).arg(errorCodeToQString(result)), currentChild);
currentData = model->header(currentChild).append(model->body(currentChild));
}
// Append current data
@ -326,12 +290,12 @@ STATUS FfsBuilder::buildRawArea(const QModelIndex & index, QByteArray & rawArea,
UINT32 newSize = rawArea.size();
UINT32 oldSize = model->body(index).size();
if (newSize > oldSize) {
msg(tr("buildRawArea: new area size %1h (%2) is bigger than the original %3h (%4)")
msg(QObject::tr("buildRawArea: new area size %1h (%2) is bigger than the original %3h (%4)")
.hexarg(newSize).arg(newSize).hexarg(oldSize).arg(oldSize), index);
return ERR_INVALID_PARAMETER;
}
else if (newSize < oldSize) {
msg(tr("buildRawArea: new area size %1h (%2) is smaller than the original %3h (%4)")
msg(QObject::tr("buildRawArea: new area size %1h (%2) is smaller than the original %3h (%4)")
.hexarg(newSize).arg(newSize).hexarg(oldSize).arg(oldSize), index);
return ERR_INVALID_PARAMETER;
}
@ -345,7 +309,7 @@ STATUS FfsBuilder::buildRawArea(const QModelIndex & index, QByteArray & rawArea,
return ERR_SUCCESS;
}
msg(tr("buildRawArea: unexpected action \"%1\"").arg(actionTypeToQString(model->action(index))), index);
msg(QObject::tr("buildRawArea: unexpected action \"%1\"").arg(actionTypeToQString(model->action(index))), index);
return ERR_NOT_IMPLEMENTED;
}
@ -365,11 +329,11 @@ STATUS FfsBuilder::buildPadding(const QModelIndex & index, QByteArray & padding)
else if (model->action(index) == Actions::Erase) {
padding = model->header(index).append(model->body(index));
if(erase(index, padding))
msg(tr("buildPadding: erase failed, original item data is used"), index);
msg(QObject::tr("buildPadding: erase failed, original item data is used"), index);
return ERR_SUCCESS;
}
msg(tr("buildPadding: unexpected action \"%1\"").arg(actionTypeToQString(model->action(index))), index);
msg(QObject::tr("buildPadding: unexpected action \"%1\"").arg(actionTypeToQString(model->action(index))), index);
return ERR_NOT_IMPLEMENTED;
}
@ -389,11 +353,11 @@ STATUS FfsBuilder::buildNonUefiData(const QModelIndex & index, QByteArray & data
else if (model->action(index) == Actions::Erase) {
data = model->header(index).append(model->body(index));
if (erase(index, data))
msg(tr("buildNonUefiData: erase failed, original item data is used"), index);
msg(QObject::tr("buildNonUefiData: erase failed, original item data is used"), index);
return ERR_SUCCESS;
}
msg(tr("buildNonUefiData: unexpected action \"%1\"").arg(actionTypeToQString(model->action(index))), index);
msg(QObject::tr("buildNonUefiData: unexpected action \"%1\"").arg(actionTypeToQString(model->action(index))), index);
return ERR_NOT_IMPLEMENTED;
}
@ -409,7 +373,7 @@ STATUS FfsBuilder::buildFreeSpace(const QModelIndex & index, QByteArray & freeSp
return ERR_SUCCESS;
}
msg(tr("buildFreeSpace: unexpected action \"%1\"").arg(actionTypeToQString(model->action(index))), index);
msg(QObject::tr("buildFreeSpace: unexpected action \"%1\"").arg(actionTypeToQString(model->action(index))), index);
return ERR_NOT_IMPLEMENTED;
}
@ -433,7 +397,4 @@ STATUS FfsBuilder::buildSection(const QModelIndex & index, QByteArray & section)
return ERR_NOT_IMPLEMENTED;
}
STATUS FfsBuilder::build(const QModelIndex & root, QByteArray & image)
{
return ERR_NOT_IMPLEMENTED;
}

View file

@ -14,6 +14,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#ifndef __FFSBUILDER_H__
#define __FFSBUILDER_H__
#include <vector>
#include <QObject>
#include <QByteArray>
#include <QString>
@ -25,31 +27,24 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "ffs.h"
#include "utility.h"
class FfsBuilder : public QObject
class FfsBuilder
{
Q_OBJECT
public:
explicit FfsBuilder(const TreeModel * treeModel, QObject *parent = 0);
explicit FfsBuilder(const TreeModel * treeModel);
~FfsBuilder();
QVector<QPair<QString, QModelIndex> > getMessages() const;
std::vector<std::pair<QString, QModelIndex> > getMessages() const;
void clearMessages();
STATUS build(const QModelIndex & root, QByteArray & image);
private:
const TreeModel* model;
QVector<QPair<QString, QModelIndex> > messagesVector;
std::vector<std::pair<QString, QModelIndex> > messagesVector;
void msg(const QString & message, const QModelIndex &index = QModelIndex());
// UEFI standard structures
STATUS buildCapsule(const QModelIndex & index, QByteArray & capsule);
STATUS buildIntelImage(const QModelIndex & index, QByteArray & intelImage);
STATUS buildGbeRegion(const QModelIndex & index, QByteArray & region);
STATUS buildMeRegion(const QModelIndex & index, QByteArray & region);
STATUS buildPdrRegion(const QModelIndex & index, QByteArray & region);
STATUS buildEcRegion(const QModelIndex & index, QByteArray & region);
STATUS buildRawArea(const QModelIndex & index, QByteArray & rawArea, bool addHeader = true);
STATUS buildPadding(const QModelIndex & index, QByteArray & padding);
STATUS buildVolume(const QModelIndex & index, QByteArray & volume);

168
common/ffsops.cpp Normal file
View file

@ -0,0 +1,168 @@
/* fssops.cpp
Copyright (c) 2015, 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 "ffsops.h"
FfsOperations::FfsOperations(TreeModel* treeModel)
: model(treeModel)
{
}
FfsOperations::~FfsOperations()
{
}
void FfsOperations::msg(const QString & message, const QModelIndex & index)
{
messagesVector.push_back(std::pair<QString, QModelIndex>(message, index));
}
std::vector<std::pair<QString, QModelIndex> > FfsOperations::getMessages() const
{
return messagesVector;
}
void FfsOperations::clearMessages()
{
messagesVector.clear();
}
STATUS FfsOperations::extract(const QModelIndex & index, QString & name, QByteArray & extracted, const UINT8 mode)
{
// Sanity check
if (!index.isValid())
return ERR_INVALID_PARAMETER;
// Get data from parsing data
PARSING_DATA pdata = parsingDataFromQModelIndex(index);
// Construct a name for extracted data
QString itemName = model->name(index);
QString itemText = model->text(index);
switch (model->type(index)) {
case Types::Volume: {
if (pdata.volume.hasExtendedHeader)
name = guidToQString(pdata.volume.extendedHeaderGuid);
else
name = itemName;
} break;
case Types::File: {
name = itemText.isEmpty() ? itemName : itemText.replace(' ', '_');
} break;
case Types::Section: {
// Get parent file name
QModelIndex fileIndex = model->findParentOfType(index, Types::File);
QString fileText = model->text(fileIndex);
name = fileText.isEmpty() ? model->name(fileIndex) : fileText.replace(' ', '_');
// Append section subtype name
name += QChar('_') + itemName.replace(' ', '_');
} break;
case Types::Capsule:
case Types::Image:
case Types::Region:
case Types::Padding:
default:
name = itemName.replace(' ', '_').replace('/', '_');
}
// Get extracted data
if (mode == EXTRACT_MODE_AS_IS) {
// Extract as is, with header body and tail
extracted.clear();
extracted.append(model->header(index));
extracted.append(model->body(index));
// Handle file tail
if (model->type(index) == Types::File) {
if (pdata.file.hasTail)
extracted.append(pdata.file.tailArray[0]).append(pdata.file.tailArray[1]);
}
}
else if (mode == EXTRACT_MODE_BODY) {
name += QObject::tr("_body");
// Extract without header and tail
extracted.clear();
extracted.append(model->body(index));
}
else if (mode == EXTRACT_MODE_BODY_UNCOMPRESSED) {
name += QObject::tr("_body_unc");
// Extract without header and tail, uncompressed
extracted.clear();
// There is no need to redo decompression, we can use child items
for (int i = 0; i < model->rowCount(index); i++) {
QModelIndex childIndex = index.child(i, 0);
extracted.append(model->header(childIndex));
extracted.append(model->body(childIndex));
}
}
else
return ERR_UNKNOWN_EXTRACT_MODE;
return ERR_SUCCESS;
}
STATUS FfsOperations::replace(const QModelIndex & index, const QString & data, const UINT8 mode)
{
// Sanity check
if (!index.isValid())
return ERR_INVALID_PARAMETER;
// Get data from parsing data
//PARSING_DATA pdata = parsingDataFromQModelIndex(index);
if (mode == REPLACE_MODE_AS_IS) {
return ERR_NOT_IMPLEMENTED;
}
else if (mode == REPLACE_MODE_BODY) {
return ERR_NOT_IMPLEMENTED;
}
else
return ERR_UNKNOWN_REPLACE_MODE;
return ERR_NOT_IMPLEMENTED;
}
STATUS FfsOperations::remove(const QModelIndex & index)
{
// Sanity check
if (!index.isValid())
return ERR_INVALID_PARAMETER;
// Set remove action
model->setAction(index, Actions::Remove);
return ERR_SUCCESS;
}
STATUS FfsOperations::rebuild(const QModelIndex & index)
{
// Sanity check
if (!index.isValid())
return ERR_INVALID_PARAMETER;
// On insert action, set insert action for children
//if (action == Actions::Insert)
// for (int i = 0; i < item->childCount(); i++)
// setAction(index.child(i, 0), Actions::Insert);
// Set rebuild action
model->setAction(index, Actions::Rebuild);
// Rebuild parent, if it has no action now
QModelIndex parent = index.parent();
if (parent.isValid() && model->type(parent) != Types::Root
&& model->action(parent) == Actions::NoAction)
rebuild(parent);
return ERR_SUCCESS;
}

51
common/ffsops.h Normal file
View file

@ -0,0 +1,51 @@
/* fssops.h
Copyright (c) 2015, 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 __FFSOPS_H__
#define __FFSOPS_H__
#include <vector>
#include <QObject>
#include <QByteArray>
#include <QString>
#include <QModelIndex>
#include "basetypes.h"
#include "treemodel.h"
#include "ffs.h"
#include "utility.h"
class FfsOperations
{
public:
explicit FfsOperations(TreeModel * treeModel);
~FfsOperations();
std::vector<std::pair<QString, QModelIndex> > getMessages() const;
void clearMessages();
STATUS extract(const QModelIndex & index, QString & name, QByteArray & extracted, const UINT8 mode);
STATUS replace(const QModelIndex & index, const QString & data, const UINT8 mode);
STATUS remove(const QModelIndex & index);
STATUS rebuild(const QModelIndex & index);
private:
TreeModel* model;
std::vector<std::pair<QString, QModelIndex> > messagesVector;
void msg(const QString & message, const QModelIndex &index = QModelIndex());
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -13,13 +13,11 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#ifndef __FFSPARSER_H__
#define __FFSPARSER_H__
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <vector>
#include <QObject>
#include <QModelIndex>
#include <QByteArray>
#include <QVector>
#include "basetypes.h"
#include "treemodel.h"
@ -36,22 +34,30 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
class TreeModel;
class FfsParser : public QObject
class FfsParser
{
Q_OBJECT
public:
// Default constructor and destructor
FfsParser(TreeModel* treeModel, QObject *parent = 0);
FfsParser(TreeModel* treeModel);
~FfsParser();
// Returns messages
QVector<QPair<QString, QModelIndex> > getMessages() const;
std::vector<std::pair<QString, QModelIndex> > getMessages() const;
// Clears messages
void clearMessages();
// Firmware image parsing
STATUS parse(const QByteArray &buffer);
// Retuns index of the last VTF after parsing is done
const QModelIndex getLastVtf() {return lastVtf;};
private:
TreeModel *model;
std::vector<std::pair<QString, QModelIndex> > messagesVector;
QModelIndex lastVtf;
UINT32 capsuleOffsetFixup;
STATUS parseRawArea(const QByteArray & data, const QModelIndex & index);
STATUS parseVolumeHeader(const QByteArray & volume, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
STATUS parseVolumeBody(const QModelIndex & index);
@ -60,15 +66,6 @@ public:
STATUS parseSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index, const bool preparse = false);
STATUS parseSectionBody(const QModelIndex & index);
// Retuns index of the last VTF after parsing is done
const QModelIndex getLastVtf() {return lastVtf;};
private:
TreeModel *model;
QVector<QPair<QString, QModelIndex> > messagesVector;
QModelIndex lastVtf;
UINT32 capsuleOffsetFixup;
STATUS parseIntelImage(const QByteArray & intelImage, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & root);
STATUS parseGbeRegion(const QByteArray & gbe, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
STATUS parseMeRegion(const QByteArray & me, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
@ -78,8 +75,8 @@ private:
STATUS parsePadFileBody(const QModelIndex & index);
STATUS parseVolumeNonUefiData(const QByteArray & data, const UINT32 parentOffset, const QModelIndex & index);
STATUS parseSections(const QByteArray & sections, const QModelIndex & index, const bool preparse = false);
STATUS parseSections(const QByteArray & sections, const QModelIndex & index, const bool preparse = false);
STATUS parseCommonSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index, const bool preparse);
STATUS parseCompressedSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index, const bool preparse);
STATUS parseGuidedSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index, const bool preparse);

View file

@ -10,12 +10,10 @@ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*/
#include "fitparser.h"
#include "types.h"
#include "treemodel.h"
FitParser::FitParser(TreeModel* treeModel, QObject *parent)
: QObject(parent), model(treeModel)
FitParser::FitParser(TreeModel* treeModel)
: model(treeModel)
{
}
@ -25,10 +23,10 @@ FitParser::~FitParser()
void FitParser::msg(const QString & message, const QModelIndex & index)
{
messagesVector.push_back(QPair<QString, QModelIndex>(message, index));
messagesVector.push_back(std::pair<QString, QModelIndex>(message, index));
}
QVector<QPair<QString, QModelIndex> > FitParser::getMessages() const
std::vector<std::pair<QString, QModelIndex> > FitParser::getMessages() const
{
return messagesVector;
}
@ -73,23 +71,23 @@ STATUS FitParser::parse(const QModelIndex & index, const QModelIndex & lastVtfIn
tempFitHeader->Checksum = 0;
UINT8 calculated = calculateChecksum8((const UINT8*)tempFitHeader, fitSize);
if (calculated != fitHeader->Checksum) {
msg(tr("Invalid FIT table checksum %1h, should be %2h").hexarg2(fitHeader->Checksum, 2).hexarg2(calculated, 2), fitIndex);
msg(QObject::tr("Invalid FIT table checksum %1h, should be %2h").hexarg2(fitHeader->Checksum, 2).hexarg2(calculated, 2), fitIndex);
}
}
// Check fit header type
if ((fitHeader->Type & 0x7F) != FIT_TYPE_HEADER) {
msg(tr("Invalid FIT header type"), fitIndex);
msg(QObject::tr("Invalid FIT header type"), fitIndex);
}
// Add FIT header to fitTable
QVector<QString> currentStrings;
currentStrings += tr("_FIT_ ");
currentStrings += tr("%1").hexarg2(fitSize, 8);
currentStrings += tr("%1").hexarg2(fitHeader->Version, 4);
currentStrings += fitEntryTypeToQString(fitHeader->Type);
currentStrings += tr("%1").hexarg2(fitHeader->Checksum, 2);
fitTable.append(currentStrings);
std::vector<QString> currentStrings;
currentStrings.push_back(QObject::tr("_FIT_ "));
currentStrings.push_back(QObject::tr("%1").hexarg2(fitSize, 8));
currentStrings.push_back(QObject::tr("%1").hexarg2(fitHeader->Version, 4));
currentStrings.push_back(fitEntryTypeToQString(fitHeader->Type));
currentStrings.push_back(QObject::tr("%1").hexarg2(fitHeader->Checksum, 2));
fitTable.push_back(currentStrings);
// Process all other entries
bool msgModifiedImageMayNotWork = false;
@ -100,7 +98,7 @@ STATUS FitParser::parse(const QModelIndex & index, const QModelIndex & lastVtfIn
// Check entry type
switch (currentEntry->Type & 0x7F) {
case FIT_TYPE_HEADER:
msg(tr("Second FIT header found, the table is damaged"), fitIndex);
msg(QObject::tr("Second FIT header found, the table is damaged"), fitIndex);
break;
case FIT_TYPE_EMPTY:
@ -120,16 +118,16 @@ STATUS FitParser::parse(const QModelIndex & index, const QModelIndex & lastVtfIn
}
// Add entry to fitTable
currentStrings += tr("%1").hexarg2(currentEntry->Address, 16);
currentStrings += tr("%1").hexarg2(currentEntry->Size, 8);
currentStrings += tr("%1").hexarg2(currentEntry->Version, 4);
currentStrings += fitEntryTypeToQString(currentEntry->Type);
currentStrings += tr("%1").hexarg2(currentEntry->Checksum, 2);
fitTable.append(currentStrings);
currentStrings.push_back(QObject::tr("%1").hexarg2(currentEntry->Address, 16));
currentStrings.push_back(QObject::tr("%1").hexarg2(currentEntry->Size, 8));
currentStrings.push_back(QObject::tr("%1").hexarg2(currentEntry->Version, 4));
currentStrings.push_back(fitEntryTypeToQString(currentEntry->Type));
currentStrings.push_back(QObject::tr("%1").hexarg2(currentEntry->Checksum, 2));
fitTable.push_back(currentStrings);
}
if (msgModifiedImageMayNotWork)
msg(tr("Opened image may not work after any modification"));
msg(QObject::tr("Opened image may not work after any modification"));
return ERR_SUCCESS;
}
@ -137,17 +135,17 @@ STATUS FitParser::parse(const QModelIndex & index, const QModelIndex & lastVtfIn
QString FitParser::fitEntryTypeToQString(UINT8 type)
{
switch (type & 0x7F) {
case FIT_TYPE_HEADER: return tr("Header");
case FIT_TYPE_MICROCODE: return tr("Microcode");
case FIT_TYPE_BIOS_AC_MODULE: return tr("BIOS ACM");
case FIT_TYPE_BIOS_INIT_MODULE: return tr("BIOS Init");
case FIT_TYPE_TPM_POLICY: return tr("TPM Policy");
case FIT_TYPE_BIOS_POLICY_DATA: return tr("BIOS Policy Data");
case FIT_TYPE_TXT_CONF_POLICY: return tr("TXT Configuration Policy");
case FIT_TYPE_AC_KEY_MANIFEST: return tr("BootGuard Key Manifest");
case FIT_TYPE_AC_BOOT_POLICY: return tr("BootGuard Boot Policy");
case FIT_TYPE_EMPTY: return tr("Empty");
default: return tr("Unknown");
case FIT_TYPE_HEADER: return QObject::tr("Header");
case FIT_TYPE_MICROCODE: return QObject::tr("Microcode");
case FIT_TYPE_BIOS_AC_MODULE: return QObject::tr("BIOS ACM");
case FIT_TYPE_BIOS_INIT_MODULE: return QObject::tr("BIOS Init");
case FIT_TYPE_TPM_POLICY: return QObject::tr("TPM Policy");
case FIT_TYPE_BIOS_POLICY_DATA: return QObject::tr("BIOS Policy Data");
case FIT_TYPE_TXT_CONF_POLICY: return QObject::tr("TXT Configuration Policy");
case FIT_TYPE_AC_KEY_MANIFEST: return QObject::tr("BootGuard Key Manifest");
case FIT_TYPE_AC_BOOT_POLICY: return QObject::tr("BootGuard Boot Policy");
case FIT_TYPE_EMPTY: return QObject::tr("Empty");
default: return QObject::tr("Unknown");
}
}
@ -179,11 +177,11 @@ STATUS FitParser::findFitRecursive(const QModelIndex & index, QModelIndex & foun
if (*(const UINT32*)(lastVtfBody.constData() + lastVtfBody.size() - FIT_POINTER_OFFSET) == fitAddress) {
found = index;
fitOffset = offset;
msg(tr("Real FIT table found at physical address %1h").hexarg(fitAddress), found);
msg(QObject::tr("Real FIT table found at physical address %1h").hexarg(fitAddress), found);
return ERR_SUCCESS;
}
else if (model->rowCount(index) == 0) // Show messages only to leaf items
msg(tr("FIT table candidate found, but not referenced from the last VTF"), index);
msg(QObject::tr("FIT table candidate found, but not referenced from the last VTF"), index);
}
return ERR_SUCCESS;

View file

@ -13,42 +13,41 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#ifndef __FITPARSER_H__
#define __FITPARSER_H__
#include <vector>
#include <QObject>
#include <QModelIndex>
#include <QByteArray>
#include <QStringList>
#include <QVector>
#include "basetypes.h"
#include "treemodel.h"
#include "utility.h"
#include "parsingdata.h"
#include "fit.h"
#include "types.h"
#include "treemodel.h"
class TreeModel;
class FitParser : public QObject
class FitParser
{
Q_OBJECT
public:
// Default constructor and destructor
FitParser(TreeModel* treeModel, QObject *parent = 0);
FitParser(TreeModel* treeModel);
~FitParser();
// Returns messages
QVector<QPair<QString, QModelIndex> > getMessages() const;
std::vector<std::pair<QString, QModelIndex> > getMessages() const;
// Clears messages
void clearMessages();
STATUS parse(const QModelIndex & index, const QModelIndex & lastVtf);
QVector<QVector<QString> > getFitTable() const { return fitTable; }
std::vector<std::vector<QString> > getFitTable() const { return fitTable; }
private:
TreeModel *model;
QVector<QPair<QString, QModelIndex> > messagesVector;
std::vector<std::pair<QString, QModelIndex> > messagesVector;
QModelIndex lastVtf;
QVector<QVector<QString> > fitTable;
std::vector<std::vector<QString> > fitTable;
STATUS findFitRecursive(const QModelIndex & index, QModelIndex & found, UINT32 & fitOffset);
QString fitEntryTypeToQString(UINT8 type);

View file

@ -345,17 +345,6 @@ void TreeModel::setAction(const QModelIndex &index, const UINT8 action)
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
item->setAction(action);
// On insert action, set insert action for children
if (action == Actions::Insert)
for (int i = 0; i < item->childCount(); i++)
setAction(index.child(i, 0), Actions::Insert);
// Set rebuild action for parent, if it has no action now
if (index.parent().isValid() && this->type(index.parent()) != Types::Root
&& this->action(index.parent()) == Actions::NoAction)
setAction(index.parent(), Actions::Rebuild);
emit dataChanged(index, index);
}

View file

@ -76,6 +76,7 @@ QString errorCodeToQString(UINT8 errorCode)
case ERR_CUSTOMIZED_DECOMPRESSION_FAILED: return QObject::tr("Customized compression failed");
case ERR_UNKNOWN_COMPRESSION_TYPE: return QObject::tr("Unknown compression type");
case ERR_UNKNOWN_EXTRACT_MODE: return QObject::tr("Unknown extract mode");
case ERR_UNKNOWN_REPLACE_MODE: return QObject::tr("Unknown replace mode");
//case ERR_UNKNOWN_INSERT_MODE: return QObject::tr("Unknown insert mode");
case ERR_UNKNOWN_IMAGE_TYPE: return QObject::tr("Unknown executable image type");
case ERR_UNKNOWN_PE_OPTIONAL_HEADER_TYPE: return QObject::tr("Unknown PE optional header type");