diff --git a/UEFITool/ffsops.cpp b/UEFITool/ffsops.cpp index f3e7538..82e7b18 100644 --- a/UEFITool/ffsops.cpp +++ b/UEFITool/ffsops.cpp @@ -44,7 +44,7 @@ STATUS FfsOperations::extract(const QModelIndex & index, QString & name, QByteAr return ERR_INVALID_PARAMETER; // Get data from parsing data - PARSING_DATA pdata = getParsingData(index); + PARSING_DATA pdata = parsingDataFromQByteArray(index); // Construct a name for extracted data QString itemName = model->name(index); diff --git a/UEFITool/uefitool.cpp b/UEFITool/uefitool.cpp index ea07f50..44a4db3 100644 --- a/UEFITool/uefitool.cpp +++ b/UEFITool/uefitool.cpp @@ -17,7 +17,7 @@ UEFITool::UEFITool(QWidget *parent) : QMainWindow(parent), ui(new Ui::UEFITool), -version(tr("0.30.0_alpha2")) +version(tr("0.30.0_alpha3")) { clipboard = QApplication::clipboard(); @@ -593,7 +593,7 @@ void UEFITool::openImageFile(QString path) inputFile.close(); init(); - this->setWindowTitle(tr("UEFITool %1 - %2").arg(version).arg(fileInfo.fileName())); + setWindowTitle(tr("UEFITool %1 - %2").arg(version).arg(fileInfo.fileName())); UINT8 result = ffsParser->parseImageFile(buffer, model->index(0,0)); showParserMessages(); diff --git a/common/ffsbuilder.cpp b/common/ffsbuilder.cpp index 3707071..3394954 100644 --- a/common/ffsbuilder.cpp +++ b/common/ffsbuilder.cpp @@ -11,3 +11,262 @@ 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() +{ +} + +void FfsBuilder::msg(const QString & message, const QModelIndex & index) +{ + messagesVector.push_back(QPair(message, index)); +} + +QVector > FfsBuilder::getMessages() const +{ + return messagesVector; +} + +void FfsBuilder::clearMessages() +{ + messagesVector.clear(); +} + +STATUS FfsBuilder::build(const QModelIndex & root, QByteArray & image) +{ + return ERR_NOT_IMPLEMENTED; +} + +STATUS FfsBuilder::buildCapsule(const QModelIndex & index, QByteArray & capsule) +{ + // Sanity check + if (!index.isValid()) + return ERR_INVALID_PARAMETER; + + STATUS result; + + // No action required + if (model->action(index) == Actions::NoAction) { + capsule = model->header(index).append(model->body(index)); + return ERR_SUCCESS; + } + + // Rebuild or Replace + else if (model->action(index) == Actions::Rebuild + || model->action(index) == Actions::Replace) { + if (model->rowCount(index)) { + // Clear the supplied QByteArray + capsule.clear(); + + // Reconstruct children + for (int i = 0; i < model->rowCount(index); i++) { + QModelIndex currentChild = index.child(i, 0); + QByteArray currentData; + // Check child type + if (model->type(currentChild) == Types::Image) { + result = buildImage(currentChild, currentData); + if (!result) { + capsule.append(currentData); + } + else { + msg(tr("buildCapsule: building of \"%1\" failed with error \"%2\", original item data used").arg(model->name(currentChild)).arg(errorCodeToQString(result)), currentChild); + capsule.append(model->header(currentChild)).append(model->body(currentChild)); + } + } + else { + msg(tr("buildCapsule: unexpected child item of type \"%1\" can't be processed, original item data used").arg(itemTypeToQString(model->type(currentChild))), currentChild); + capsule.append(model->header(currentChild)).append(model->body(currentChild)); + } + } + + // Check size of reconstructed capsule, it must remain the same + if (capsule.size() > model->body(index).size()) { + msg(tr("buildCapsule: new capsule size %1h (%2) is bigger than the original %3h (%4)") + .hexarg(capsule.size()).arg(capsule.size()) + .hexarg(model->body(index).size()).arg(model->body(index).size()), + index); + return ERR_INVALID_PARAMETER; + } + else if (capsule.size() < model->body(index).size()) { + msg(tr("buildCapsule: new capsule size %1h (%2) is smaller than the original %3h (%4)") + .hexarg(capsule.size()).arg(capsule.size()) + .hexarg(model->body(index).size()).arg(model->body(index).size()), + index); + return ERR_INVALID_PARAMETER; + } + } + else + capsule = model->body(index); + + // Build successful, append header + capsule = model->header(index).append(capsule); + return ERR_SUCCESS; + } + msg(tr("buildCapsule: unexpected action \"%1\"").arg(actionTypeToQString(model->action(index))), index); + return ERR_NOT_IMPLEMENTED; +} + +STATUS FfsBuilder::buildImage(const QModelIndex & index, QByteArray & intelImage) +{ + return ERR_NOT_IMPLEMENTED; +} + +STATUS FfsBuilder::buildRawArea(const QModelIndex & index, QByteArray & rawArea) +{ + // Sanity check + 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)); + return ERR_SUCCESS; + } + + // Rebuild or Replace + else if (model->action(index) == Actions::Rebuild + || model->action(index) == Actions::Replace) { + if (model->rowCount(index)) { + // Clear the supplied QByteArray + rawArea.clear(); + + // Reconstruct children + for (int i = 0; i < model->rowCount(index); i++) { + QModelIndex currentChild = index.child(i, 0); + QByteArray currentData; + // Check child type + if (model->type(currentChild) == Types::Volume) { + result = buildVolume(currentChild, currentData); + } + else if (model->type(currentChild) == Types::Padding) { + result = buildPadding(currentChild, currentData); + } + else { + msg(tr("buildRawArea: unexpected child item of type \"%1\" can't be processed, original item data used").arg(itemTypeToQString(model->type(currentChild))), currentChild); + result = ERR_SUCCESS; + 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 used").arg(model->name(currentChild)).arg(errorCodeToQString(result)), currentChild); + currentData = model->header(currentChild).append(model->body(currentChild)); + } + // Append current data + rawArea.append(currentData); + } + + // Check size of reconstructed raw area, it must remain the same + if (rawArea.size() > model->body(index).size()) { + msg(tr("buildRawArea: new raw area size %1h (%2) is bigger than the original %3h (%4)") + .hexarg(rawArea.size()).arg(rawArea.size()) + .hexarg(model->body(index).size()).arg(model->body(index).size()), + index); + return ERR_INVALID_PARAMETER; + } + else if (rawArea.size() < model->body(index).size()) { + msg(tr("buildRawArea: new raw area size %1h (%2) is smaller than the original %3h (%4)") + .hexarg(rawArea.size()).arg(rawArea.size()) + .hexarg(model->body(index).size()).arg(model->body(index).size()), + index); + return ERR_INVALID_PARAMETER; + } + } + else + rawArea = model->body(index); + + // Build successful, append header + rawArea = model->header(index).append(rawArea); + return ERR_SUCCESS; + } + + msg(tr("buildRawArea: unexpected action \"%1\"").arg(actionTypeToQString(model->action(index))), index); + return ERR_NOT_IMPLEMENTED; +} + +STATUS FfsBuilder::buildVolume(const QModelIndex & index, QByteArray & volume) +{ + return ERR_NOT_IMPLEMENTED; +} + +STATUS FfsBuilder::buildPadding(const QModelIndex & index, QByteArray & padding) +{ + // Sanity check + if (!index.isValid()) + return ERR_INVALID_PARAMETER; + + // No action required + if (model->action(index) == Actions::NoAction) { + padding = model->header(index).append(model->body(index)); + return ERR_SUCCESS; + } + + // Erase + else if (model->action(index) == Actions::Erase) { + padding.fill('\xFF', model->header(index).size() + model->body(index).size()); + return ERR_SUCCESS; + } + + msg(tr("buildPadding: unexpected action \"%1\"").arg(actionTypeToQString(model->action(index))), index); + return ERR_NOT_IMPLEMENTED; +} + +STATUS FfsBuilder::buildNonUefiData(const QModelIndex & index, QByteArray & data) +{ + // Sanity check + if (!index.isValid()) + return ERR_INVALID_PARAMETER; + + // No action required + if (model->action(index) == Actions::NoAction) { + data = model->header(index).append(model->body(index)); + return ERR_SUCCESS; + } + + // Erase + else if (model->action(index) == Actions::Erase) { + data.fill('\xFF', model->header(index).size() + model->body(index).size()); + return ERR_SUCCESS; + } + + msg(tr("buildNonUefiData: unexpected action \"%1\"").arg(actionTypeToQString(model->action(index))), index); + return ERR_NOT_IMPLEMENTED; +} + +STATUS FfsBuilder::buildFreeSpace(const QModelIndex & index, QByteArray & freeSpace) +{ + // Sanity check + if (!index.isValid()) + return ERR_INVALID_PARAMETER; + + // No action required + if (model->action(index) == Actions::NoAction) { + freeSpace = model->header(index).append(model->body(index)); + return ERR_SUCCESS; + } + + msg(tr("buildFreeSpace: unexpected action \"%1\"").arg(actionTypeToQString(model->action(index))), index); + return ERR_NOT_IMPLEMENTED; +} + +STATUS FfsBuilder::buildPadFile(const QModelIndex & index, QByteArray & padFile) +{ + return ERR_NOT_IMPLEMENTED; +} + +STATUS FfsBuilder::buildFile(const QModelIndex & index, QByteArray & file) +{ + return ERR_NOT_IMPLEMENTED; +} + +STATUS FfsBuilder::buildSection(const QModelIndex & index, QByteArray & section) +{ + return ERR_NOT_IMPLEMENTED; +} + diff --git a/common/ffsbuilder.h b/common/ffsbuilder.h index cda9b95..6f136d7 100644 --- a/common/ffsbuilder.h +++ b/common/ffsbuilder.h @@ -14,4 +14,47 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #ifndef __FFSBUILDER_H__ #define __FFSBUILDER_H__ +#include +#include +#include +#include + +#include "../common/basetypes.h" +#include "../common/treemodel.h" +#include "../common/ffs.h" +#include "../common/utility.h" + +class FfsBuilder : public QObject +{ + Q_OBJECT + +public: + explicit FfsBuilder(const TreeModel * treeModel, QObject *parent = 0); + ~FfsBuilder(); + + QVector > getMessages() const; + void clearMessages(); + + STATUS build(const QModelIndex & root, QByteArray & image); + +private: + const TreeModel* model; + QVector > messagesVector; + void msg(const QString & message, const QModelIndex &index = QModelIndex()); + + // UEFI standard structures + STATUS buildCapsule(const QModelIndex & index, QByteArray & capsule); + STATUS buildImage(const QModelIndex & index, QByteArray & intelImage); + STATUS buildRegion(const QModelIndex & index, QByteArray & region); + STATUS buildRawArea(const QModelIndex & index, QByteArray & rawArea); + STATUS buildVolume(const QModelIndex & index, QByteArray & volume); + STATUS buildPadding(const QModelIndex & index, QByteArray & padding); + STATUS buildNonUefiData(const QModelIndex & index, QByteArray & data); + STATUS buildFreeSpace(const QModelIndex & index, QByteArray & freeSpace); + STATUS buildPadFile(const QModelIndex & index, QByteArray & padFile); + STATUS buildFile(const QModelIndex & index, QByteArray & file); + STATUS buildSection(const QModelIndex & index, QByteArray & section); + +}; + #endif diff --git a/common/ffsparser.cpp b/common/ffsparser.cpp index c443218..94407a5 100644 --- a/common/ffsparser.cpp +++ b/common/ffsparser.cpp @@ -84,11 +84,11 @@ STATUS FfsParser::parseImageFile(const QByteArray & buffer, const QModelIndex & .hexarg2(capsuleHeader->Flags, 8); // Construct parsing data - PARSING_DATA pdata = getParsingData(QModelIndex()); + PARSING_DATA pdata = parsingDataFromQByteArray(QModelIndex()); pdata.fixed = TRUE; // Add tree item - index = model->addItem(Types::Capsule, Subtypes::UefiCapsule, name, QString(), info, header, body, convertParsingData(pdata), root); + index = model->addItem(Types::Capsule, Subtypes::UefiCapsule, name, QString(), info, header, body, parsingDataToQByteArray(pdata), root); } // Check buffer for being extended Aptio signed capsule header else if (buffer.startsWith(APTIO_SIGNED_CAPSULE_GUID) || buffer.startsWith(APTIO_UNSIGNED_CAPSULE_GUID)) { @@ -107,11 +107,11 @@ STATUS FfsParser::parseImageFile(const QByteArray & buffer, const QModelIndex & .hexarg2(capsuleHeader->CapsuleHeader.Flags, 8); // Construct parsing data - PARSING_DATA pdata = getParsingData(QModelIndex()); + PARSING_DATA pdata = parsingDataFromQByteArray(QModelIndex()); pdata.fixed = TRUE; // Add tree item - index = model->addItem(Types::Capsule, signedCapsule ? Subtypes::AptioSignedCapsule : Subtypes::AptioUnsignedCapsule, name, QString(), info, header, body, convertParsingData(pdata), root); + index = model->addItem(Types::Capsule, signedCapsule ? Subtypes::AptioSignedCapsule : Subtypes::AptioUnsignedCapsule, name, QString(), info, header, body, parsingDataToQByteArray(pdata), root); // Show message about possible Aptio signature break if (signedCapsule) { @@ -145,12 +145,12 @@ STATUS FfsParser::parseImageFile(const QByteArray & buffer, const QModelIndex & .hexarg(capsuleHeaderSize).hexarg(flashImage.size()).arg(flashImage.size()); // Construct parsing data - PARSING_DATA pdata = getParsingData(index); + PARSING_DATA pdata = parsingDataFromQByteArray(index); pdata.fixed = TRUE; pdata.offset = capsuleHeaderSize; // Add tree item - QModelIndex biosIndex = model->addItem(Types::Image, Subtypes::UefiImage, name, QString(), info, QByteArray(), flashImage, convertParsingData(pdata), index); + QModelIndex biosIndex = model->addItem(Types::Image, Subtypes::UefiImage, name, QString(), info, QByteArray(), flashImage, parsingDataToQByteArray(pdata), index); // Parse the image return parseRawArea(flashImage, biosIndex); @@ -163,7 +163,7 @@ STATUS FfsParser::parseIntelImage(const QByteArray & intelImage, const QModelInd return EFI_INVALID_PARAMETER; // Get parent's parsing data - PARSING_DATA pdata = getParsingData(parent); + PARSING_DATA pdata = parsingDataFromQByteArray(parent); // Store the beginning of descriptor as descriptor base address const UINT8* descriptor = (const UINT8*)intelImage.constData(); @@ -297,7 +297,7 @@ STATUS FfsParser::parseIntelImage(const QByteArray & intelImage, const QModelInd if (pdata.isOnFlash) info.prepend(tr("Offset: %1h\n").hexarg(pdata.offset)); // Add Intel image tree item - index = model->addItem(Types::Image, Subtypes::IntelImage, name, QString(), info, QByteArray(), intelImage, convertParsingData(pdata), parent); + index = model->addItem(Types::Image, Subtypes::IntelImage, name, QString(), info, QByteArray(), intelImage, parsingDataToQByteArray(pdata), parent); // Descriptor // Get descriptor info @@ -365,7 +365,7 @@ STATUS FfsParser::parseIntelImage(const QByteArray & intelImage, const QModelInd } // Add descriptor tree item - model->addItem(Types::Region, Subtypes::DescriptorRegion, name, QString(), info, QByteArray(), body, convertParsingData(pdata), index); + model->addItem(Types::Region, Subtypes::DescriptorRegion, name, QString(), info, QByteArray(), body, parsingDataToQByteArray(pdata), index); // Sort regions in ascending order qSort(offsets); @@ -407,7 +407,7 @@ STATUS FfsParser::parseGbeRegion(const QByteArray & gbe, const UINT32 parentOffs return ERR_EMPTY_REGION; // Get parent's parsing data - PARSING_DATA pdata = getParsingData(parent); + PARSING_DATA pdata = parsingDataFromQByteArray(parent); // Get info QString name = tr("GbE region"); @@ -430,7 +430,7 @@ STATUS FfsParser::parseGbeRegion(const QByteArray & gbe, const UINT32 parentOffs if (pdata.isOnFlash) info.prepend(tr("Offset: %1h\n").hexarg(pdata.offset)); // Add tree item - index = model->addItem(Types::Region, Subtypes::GbeRegion, name, QString(), info, QByteArray(), gbe, convertParsingData(pdata), parent); + index = model->addItem(Types::Region, Subtypes::GbeRegion, name, QString(), info, QByteArray(), gbe, parsingDataToQByteArray(pdata), parent); return ERR_SUCCESS; } @@ -442,7 +442,7 @@ STATUS FfsParser::parseMeRegion(const QByteArray & me, const UINT32 parentOffset return ERR_EMPTY_REGION; // Get parent's parsing data - PARSING_DATA pdata = getParsingData(parent); + PARSING_DATA pdata = parsingDataFromQByteArray(parent); // Get info QString name = tr("ME region"); @@ -487,7 +487,7 @@ STATUS FfsParser::parseMeRegion(const QByteArray & me, const UINT32 parentOffset if (pdata.isOnFlash) info.prepend(tr("Offset: %1h\n").hexarg(pdata.offset)); // Add tree item - index = model->addItem(Types::Region, Subtypes::MeRegion, name, QString(), info, QByteArray(), me, convertParsingData(pdata), parent); + index = model->addItem(Types::Region, Subtypes::MeRegion, name, QString(), info, QByteArray(), me, parsingDataToQByteArray(pdata), parent); // Show messages if (emptyRegion) { @@ -507,7 +507,7 @@ STATUS FfsParser::parsePdrRegion(const QByteArray & pdr, const UINT32 parentOffs return ERR_EMPTY_REGION; // Get parent's parsing data - PARSING_DATA pdata = getParsingData(parent); + PARSING_DATA pdata = parsingDataFromQByteArray(parent); // Get info QString name = tr("PDR region"); @@ -520,7 +520,7 @@ STATUS FfsParser::parsePdrRegion(const QByteArray & pdr, const UINT32 parentOffs if (pdata.isOnFlash) info.prepend(tr("Offset: %1h\n").hexarg(pdata.offset)); // Add tree item - index = model->addItem(Types::Region, Subtypes::PdrRegion, name, QString(), info, QByteArray(), pdr, convertParsingData(pdata), parent); + index = model->addItem(Types::Region, Subtypes::PdrRegion, name, QString(), info, QByteArray(), pdr, parsingDataToQByteArray(pdata), parent); // Parse PDR region as BIOS space UINT8 result = parseRawArea(pdr, index); @@ -537,7 +537,7 @@ STATUS FfsParser::parseBiosRegion(const QByteArray & bios, const UINT32 parentOf return ERR_EMPTY_REGION; // Get parent's parsing data - PARSING_DATA pdata = getParsingData(parent); + PARSING_DATA pdata = parsingDataFromQByteArray(parent); // Get info QString name = tr("BIOS region"); @@ -550,7 +550,7 @@ STATUS FfsParser::parseBiosRegion(const QByteArray & bios, const UINT32 parentOf if (pdata.isOnFlash) info.prepend(tr("Offset: %1h\n").hexarg(pdata.offset)); // Add tree item - index = model->addItem(Types::Region, Subtypes::BiosRegion, name, QString(), info, QByteArray(), bios, convertParsingData(pdata), parent); + index = model->addItem(Types::Region, Subtypes::BiosRegion, name, QString(), info, QByteArray(), bios, parsingDataToQByteArray(pdata), parent); return parseRawArea(bios, index); } @@ -571,7 +571,7 @@ STATUS FfsParser::parseRawArea(const QByteArray & data, const QModelIndex & inde return ERR_INVALID_PARAMETER; // Get parsing data - PARSING_DATA pdata = getParsingData(index); + PARSING_DATA pdata = parsingDataFromQByteArray(index); UINT32 offset = pdata.offset; UINT32 headerSize = model->header(index).size(); @@ -598,7 +598,7 @@ STATUS FfsParser::parseRawArea(const QByteArray & data, const QModelIndex & inde if (pdata.isOnFlash) info.prepend(tr("Offset: %1h\n").hexarg(pdata.offset)); // Add tree item - model->addItem(Types::Padding, getPaddingType(padding), name, QString(), info, QByteArray(), padding, convertParsingData(pdata), index); + model->addItem(Types::Padding, getPaddingType(padding), name, QString(), info, QByteArray(), padding, parsingDataToQByteArray(pdata), index); } // Search for and parse all volumes @@ -624,7 +624,7 @@ STATUS FfsParser::parseRawArea(const QByteArray & data, const QModelIndex & inde if (pdata.isOnFlash) info.prepend(tr("Offset: %1h\n").hexarg(pdata.offset)); // Add tree item - model->addItem(Types::Padding, getPaddingType(padding), name, QString(), info, QByteArray(), padding, convertParsingData(pdata), index); + model->addItem(Types::Padding, getPaddingType(padding), name, QString(), info, QByteArray(), padding, parsingDataToQByteArray(pdata), index); } // Get volume size @@ -651,7 +651,7 @@ STATUS FfsParser::parseRawArea(const QByteArray & data, const QModelIndex & inde if (pdata.isOnFlash) info.prepend(tr("Offset: %1h\n").hexarg(pdata.offset)); // Add tree item - QModelIndex paddingIndex = model->addItem(Types::Padding, getPaddingType(padding), name, QString(), info, QByteArray(), padding, convertParsingData(pdata), index); + QModelIndex paddingIndex = model->addItem(Types::Padding, getPaddingType(padding), name, QString(), info, QByteArray(), padding, parsingDataToQByteArray(pdata), index); msg(tr("parseRawArea: one of volumes inside overlaps the end of data"), paddingIndex); // Update variables @@ -696,7 +696,7 @@ STATUS FfsParser::parseRawArea(const QByteArray & data, const QModelIndex & inde if (pdata.isOnFlash) info.prepend(tr("Offset: %1h\n").hexarg(pdata.offset)); // Add tree item - model->addItem(Types::Padding, getPaddingType(padding), name, QString(), info, QByteArray(), padding, convertParsingData(pdata), index); + model->addItem(Types::Padding, getPaddingType(padding), name, QString(), info, QByteArray(), padding, parsingDataToQByteArray(pdata), index); } //Parse bodies @@ -724,7 +724,7 @@ STATUS FfsParser::parseVolumeHeader(const QByteArray & volume, const UINT32 pare return ERR_INVALID_PARAMETER; // Get parent's parsing data - PARSING_DATA pdata = getParsingData(parent); + PARSING_DATA pdata = parsingDataFromQByteArray(parent); // Populate volume header const EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (const EFI_FIRMWARE_VOLUME_HEADER*)(volume.constData()); @@ -882,7 +882,7 @@ STATUS FfsParser::parseVolumeHeader(const QByteArray & volume, const UINT32 pare else if (ffsVersion == 3) subtype = Subtypes::Ffs3Volume; } - index = model->addItem(Types::Volume, subtype, name, text, info, header, body, convertParsingData(pdata), parent); + index = model->addItem(Types::Volume, subtype, name, text, info, header, body, parsingDataToQByteArray(pdata), parent); // Show messages if (isUnknown) @@ -945,7 +945,7 @@ STATUS FfsParser::parseVolumeBody(const QModelIndex & index) UINT32 volumeHeaderSize = model->header(index).size(); // Get parsing data - PARSING_DATA pdata = getParsingData(index); + PARSING_DATA pdata = parsingDataFromQByteArray(index); UINT32 offset = pdata.offset; if (pdata.ffsVersion != 2 && pdata.ffsVersion != 3) // Don't parse unknown volumes @@ -992,7 +992,7 @@ STATUS FfsParser::parseVolumeBody(const QModelIndex & index) if (pdata.isOnFlash) info.prepend(tr("Offset: %1h\n").hexarg(pdata.offset)); // Add free space item - model->addItem(Types::FreeSpace, 0, tr("Volume free space"), "", info, QByteArray(), free, convertParsingData(pdata), index); + model->addItem(Types::FreeSpace, 0, tr("Volume free space"), "", info, QByteArray(), free, parsingDataToQByteArray(pdata), index); } // ... and all bytes after as a padding pdata.fixed = TRUE; // Non-UEFI data is fixed @@ -1004,7 +1004,7 @@ STATUS FfsParser::parseVolumeBody(const QModelIndex & index) if (pdata.isOnFlash) info.prepend(tr("Offset: %1h\n").hexarg(pdata.offset)); // Add padding tree item - QModelIndex dataIndex = model->addItem(Types::Padding, Subtypes::DataPadding, tr("Non-UEFI data"), "", info, QByteArray(), padding, convertParsingData(pdata), index); + QModelIndex dataIndex = model->addItem(Types::Padding, Subtypes::DataPadding, tr("Non-UEFI data"), "", info, QByteArray(), padding, parsingDataToQByteArray(pdata), index); msg(tr("parseVolumeBody: non-UEFI data found in volume's free space"), dataIndex); } else { @@ -1017,7 +1017,7 @@ STATUS FfsParser::parseVolumeBody(const QModelIndex & index) if (pdata.isOnFlash) info.prepend(tr("Offset: %1h\n").hexarg(pdata.offset)); // Add free space item - model->addItem(Types::FreeSpace, 0, tr("Volume free space"), "", info, QByteArray(), freeSpace, convertParsingData(pdata), index); + model->addItem(Types::FreeSpace, 0, tr("Volume free space"), "", info, QByteArray(), freeSpace, parsingDataToQByteArray(pdata), index); } break; // Exit from parsing loop } @@ -1032,7 +1032,7 @@ STATUS FfsParser::parseVolumeBody(const QModelIndex & index) if (pdata.isOnFlash) info.prepend(tr("Offset: %1h\n").hexarg(pdata.offset)); // Add padding tree item - QModelIndex dataIndex = model->addItem(Types::Padding, Subtypes::DataPadding, tr("Non-UEFI data"), "", info, QByteArray(), padding, convertParsingData(pdata), index); + QModelIndex dataIndex = model->addItem(Types::Padding, Subtypes::DataPadding, tr("Non-UEFI data"), "", info, QByteArray(), padding, parsingDataToQByteArray(pdata), index); // Show message msg(tr("parseVolumeBody: non-UEFI data found inside volume's file space"), dataIndex); @@ -1124,7 +1124,7 @@ STATUS FfsParser::parseFileHeader(const QByteArray & file, const UINT32 parentOf return ERR_INVALID_PARAMETER; // Get parent's parsing data - PARSING_DATA pdata = getParsingData(parent); + PARSING_DATA pdata = parsingDataFromQByteArray(parent); // Get file header QByteArray header = file.left(sizeof(EFI_FFS_FILE_HEADER)); @@ -1224,7 +1224,7 @@ STATUS FfsParser::parseFileHeader(const QByteArray & file, const UINT32 parentOf if (pdata.isOnFlash) info.prepend(tr("Offset: %1h\n").hexarg(pdata.offset)); // Add tree item - index = model->addItem(Types::File, fileHeader->Type, name, "", info, header, body, convertParsingData(pdata), parent); + index = model->addItem(Types::File, fileHeader->Type, name, "", info, header, body, parsingDataToQByteArray(pdata), parent); // Show messages if (msgUnalignedFile) @@ -1290,7 +1290,7 @@ STATUS FfsParser::parsePadFileBody(const QModelIndex & index) return ERR_INVALID_PARAMETER; // Get data from parsing data - PARSING_DATA pdata = getParsingData(index); + PARSING_DATA pdata = parsingDataFromQByteArray(index); // Check if all bytes of the file are empty QByteArray body = model->body(index); @@ -1322,7 +1322,7 @@ STATUS FfsParser::parsePadFileBody(const QModelIndex & index) if (pdata.isOnFlash) info.prepend(tr("Offset: %1h\n").hexarg(pdata.offset)); // Add tree item - model->addItem(Types::FreeSpace, 0, tr("Free space"), QString(), info, QByteArray(), free, convertParsingData(pdata), index); + model->addItem(Types::FreeSpace, 0, tr("Free space"), QString(), info, QByteArray(), free, parsingDataToQByteArray(pdata), index); } else i = 0; @@ -1339,7 +1339,7 @@ STATUS FfsParser::parsePadFileBody(const QModelIndex & index) if (pdata.isOnFlash) info.prepend(tr("Offset: %1h\n").hexarg(pdata.offset)); // Add tree item - QModelIndex dataIndex = model->addItem(Types::Padding, Subtypes::DataPadding, tr("Non-UEFI data"), "", info, QByteArray(), padding, convertParsingData(pdata), index); + QModelIndex dataIndex = model->addItem(Types::Padding, Subtypes::DataPadding, tr("Non-UEFI data"), "", info, QByteArray(), padding, parsingDataToQByteArray(pdata), index); // Show message msg(tr("parsePadFileBody: non-UEFI data found in pad-file"), dataIndex); @@ -1357,7 +1357,7 @@ STATUS FfsParser::parseSections(QByteArray sections, const QModelIndex & index) return ERR_INVALID_PARAMETER; // Get data from parsing data - PARSING_DATA pdata = getParsingData(index); + PARSING_DATA pdata = parsingDataFromQByteArray(index); // Search for and parse all sections UINT32 bodySize = sections.size(); @@ -1381,7 +1381,7 @@ STATUS FfsParser::parseSections(QByteArray sections, const QModelIndex & index) if (pdata.isOnFlash) info.prepend(tr("Offset: %1h\n").hexarg(pdata.offset)); // Add tree item - QModelIndex dataIndex = model->addItem(Types::Padding, Subtypes::DataPadding, tr("Non-UEFI data"), "", info, QByteArray(), padding, convertParsingData(pdata), index); + QModelIndex dataIndex = model->addItem(Types::Padding, Subtypes::DataPadding, tr("Non-UEFI data"), "", info, QByteArray(), padding, parsingDataToQByteArray(pdata), index); // Show message msg(tr("parseSections: non-UEFI data found in sections area"), dataIndex); @@ -1453,7 +1453,7 @@ STATUS FfsParser::parseSectionHeader(const QByteArray & section, const UINT32 pa STATUS FfsParser::parseCommonSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index) { // Get data from parent's parsing data - PARSING_DATA pdata = getParsingData(parent); + PARSING_DATA pdata = parsingDataFromQByteArray(parent); // Obtain header fields const EFI_COMMON_SECTION_HEADER* sectionHeader = (const EFI_COMMON_SECTION_HEADER*)(section.constData()); @@ -1477,7 +1477,7 @@ STATUS FfsParser::parseCommonSectionHeader(const QByteArray & section, const UIN if (pdata.isOnFlash) info.prepend(tr("Offset: %1h\n").hexarg(pdata.offset)); // Add tree item - index = model->addItem(Types::Section, sectionHeader->Type, name, QString(), info, header, body, convertParsingData(pdata), parent); + index = model->addItem(Types::Section, sectionHeader->Type, name, QString(), info, header, body, parsingDataToQByteArray(pdata), parent); return ERR_SUCCESS; } @@ -1485,7 +1485,7 @@ STATUS FfsParser::parseCommonSectionHeader(const QByteArray & section, const UIN STATUS FfsParser::parseCompressedSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index) { // Get data from parent's parsing data - PARSING_DATA pdata = getParsingData(parent); + PARSING_DATA pdata = parsingDataFromQByteArray(parent); // Obtain header fields const EFI_COMMON_SECTION_HEADER* sectionHeader = (const EFI_COMMON_SECTION_HEADER*)(section.constData()); @@ -1520,7 +1520,7 @@ STATUS FfsParser::parseCompressedSectionHeader(const QByteArray & section, const if (pdata.isOnFlash) info.prepend(tr("Offset: %1h\n").hexarg(pdata.offset)); // Add tree item - index = model->addItem(Types::Section, sectionHeader->Type, name, QString(), info, header, body, convertParsingData(pdata), parent); + index = model->addItem(Types::Section, sectionHeader->Type, name, QString(), info, header, body, parsingDataToQByteArray(pdata), parent); return ERR_SUCCESS; } @@ -1528,7 +1528,7 @@ STATUS FfsParser::parseCompressedSectionHeader(const QByteArray & section, const STATUS FfsParser::parseGuidedSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index) { // Get data from parent's parsing data - PARSING_DATA pdata = getParsingData(parent); + PARSING_DATA pdata = parsingDataFromQByteArray(parent); // Obtain header fields const EFI_COMMON_SECTION_HEADER* sectionHeader = (const EFI_COMMON_SECTION_HEADER*)(section.constData()); @@ -1564,7 +1564,7 @@ STATUS FfsParser::parseGuidedSectionHeader(const QByteArray & section, const UIN if (pdata.isOnFlash) info.prepend(tr("Offset: %1h\n").hexarg(pdata.offset)); // Add tree item - index = model->addItem(Types::Section, sectionHeader->Type, name, QString(), info, header, body, convertParsingData(pdata), parent); + index = model->addItem(Types::Section, sectionHeader->Type, name, QString(), info, header, body, parsingDataToQByteArray(pdata), parent); return ERR_SUCCESS; } @@ -1572,7 +1572,7 @@ STATUS FfsParser::parseGuidedSectionHeader(const QByteArray & section, const UIN STATUS FfsParser::parseFreeformGuidedSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index) { // Get data from parent's parsing data - PARSING_DATA pdata = getParsingData(parent); + PARSING_DATA pdata = parsingDataFromQByteArray(parent); // Obtain header fields const EFI_COMMON_SECTION_HEADER* sectionHeader = (const EFI_COMMON_SECTION_HEADER*)(section.constData()); @@ -1640,7 +1640,7 @@ STATUS FfsParser::parseFreeformGuidedSectionHeader(const QByteArray & section, c if (pdata.isOnFlash) info.prepend(tr("Offset: %1h\n").hexarg(pdata.offset)); // Add tree item - index = model->addItem(Types::Section, sectionHeader->Type, name, QString(), info, header, body, convertParsingData(pdata), parent); + index = model->addItem(Types::Section, sectionHeader->Type, name, QString(), info, header, body, parsingDataToQByteArray(pdata), parent); // Show messages if (msgSigned) @@ -1659,7 +1659,7 @@ STATUS FfsParser::parseFreeformGuidedSectionHeader(const QByteArray & section, c STATUS FfsParser::parseVersionSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index) { // Get data from parent's parsing data - PARSING_DATA pdata = getParsingData(parent); + PARSING_DATA pdata = parsingDataFromQByteArray(parent); // Obtain header fields const EFI_COMMON_SECTION_HEADER* sectionHeader = (const EFI_COMMON_SECTION_HEADER*)(section.constData()); @@ -1689,7 +1689,7 @@ STATUS FfsParser::parseVersionSectionHeader(const QByteArray & section, const UI if (pdata.isOnFlash) info.prepend(tr("Offset: %1h\n").hexarg(pdata.offset)); // Add tree item - index = model->addItem(Types::Section, sectionHeader->Type, name, QString(), info, header, body, convertParsingData(pdata), parent); + index = model->addItem(Types::Section, sectionHeader->Type, name, QString(), info, header, body, parsingDataToQByteArray(pdata), parent); return ERR_SUCCESS; } @@ -1697,7 +1697,7 @@ STATUS FfsParser::parseVersionSectionHeader(const QByteArray & section, const UI STATUS FfsParser::parsePostcodeSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index) { // Get data from parent's parsing data - PARSING_DATA pdata = getParsingData(parent); + PARSING_DATA pdata = parsingDataFromQByteArray(parent); // Obtain header fields const EFI_COMMON_SECTION_HEADER* sectionHeader = (const EFI_COMMON_SECTION_HEADER*)(section.constData()); @@ -1727,7 +1727,7 @@ STATUS FfsParser::parsePostcodeSectionHeader(const QByteArray & section, const U if (pdata.isOnFlash) info.prepend(tr("Offset: %1h\n").hexarg(pdata.offset)); // Add tree item - index = model->addItem(Types::Section, sectionHeader->Type, name, QString(), info, header, body, convertParsingData(pdata), parent); + index = model->addItem(Types::Section, sectionHeader->Type, name, QString(), info, header, body, parsingDataToQByteArray(pdata), parent); return ERR_SUCCESS; } @@ -1773,7 +1773,7 @@ STATUS FfsParser::parseCompressedSectionBody(const QModelIndex & index) return ERR_INVALID_PARAMETER; // Get data from parsing data - PARSING_DATA pdata = getParsingData(index); + PARSING_DATA pdata = parsingDataFromQByteArray(index); UINT8 algorithm = pdata.section.compressed.compressionType; // Decompress section @@ -1800,7 +1800,7 @@ STATUS FfsParser::parseCompressedSectionBody(const QModelIndex & index) // Update parsing data pdata.isOnFlash = (algorithm == COMPRESSION_ALGORITHM_NONE); // Data is not on flash unless not compressed pdata.section.compressed.algorithm = algorithm; - model->setParsingData(index, convertParsingData(pdata)); + model->setParsingData(index, parsingDataToQByteArray(pdata)); // Parse decompressed data return parseSections(decompressed, index); @@ -1813,7 +1813,7 @@ STATUS FfsParser::parseGuidedSectionBody(const QModelIndex & index) return ERR_INVALID_PARAMETER; // Get data from parsing data - PARSING_DATA pdata = getParsingData(index); + PARSING_DATA pdata = parsingDataFromQByteArray(index); UINT32 attributes = pdata.section.guidDefined.attributes; EFI_GUID guid = pdata.section.guidDefined.guid; @@ -1895,7 +1895,7 @@ STATUS FfsParser::parseGuidedSectionBody(const QModelIndex & index) // Update parsing data pdata.isOnFlash = (algorithm == COMPRESSION_ALGORITHM_NONE); // Data is not on flash unless not compressed - model->setParsingData(index, convertParsingData(pdata)); + model->setParsingData(index, parsingDataToQByteArray(pdata)); if (!parseCurrentSection) { msg(tr("parseGuidedSectionBody: GUID defined section can not be processed"), index); diff --git a/common/peimage.cpp b/common/peimage.cpp index 6845e6e..c0f81a6 100644 --- a/common/peimage.cpp +++ b/common/peimage.cpp @@ -17,14 +17,17 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. QString machineTypeToQString(UINT16 machineType) { - switch (machineType){ - case IMAGE_FILE_MACHINE_AMD64: return QObject::tr("x86-64"); - case IMAGE_FILE_MACHINE_ARM: return QObject::tr("ARM"); - case IMAGE_FILE_MACHINE_ARMV7: return QObject::tr("ARMv7"); - case IMAGE_FILE_MACHINE_EBC: return QObject::tr("EBC"); - case IMAGE_FILE_MACHINE_I386: return QObject::tr("x86"); - case IMAGE_FILE_MACHINE_IA64: return QObject::tr("IA64"); - case IMAGE_FILE_MACHINE_THUMB: return QObject::tr("Thumb"); - default: return QObject::tr("Unknown %1h").hexarg2(machineType, 4); + switch (machineType) { + case EFI_IMAGE_FILE_MACHINE_AMD64: return QObject::tr("x86-64"); + case EFI_IMAGE_FILE_MACHINE_ARM: return QObject::tr("ARM"); + case EFI_IMAGE_FILE_MACHINE_ARMNT: return QObject::tr("ARMv7"); + case EFI_IMAGE_FILE_MACHINE_ARM64: return QObject::tr("ARM64"); + case EFI_IMAGE_FILE_MACHINE_EBC: return QObject::tr("EBC"); + case EFI_IMAGE_FILE_MACHINE_I386: return QObject::tr("x86"); + case EFI_IMAGE_FILE_MACHINE_IA64: return QObject::tr("IA64"); + case EFI_IMAGE_FILE_MACHINE_POWERPC: return QObject::tr("PowerPC"); + case EFI_IMAGE_FILE_MACHINE_POWERPCFP: return QObject::tr("PowerPC FP"); + case EFI_IMAGE_FILE_MACHINE_THUMB: return QObject::tr("Thumb"); + default: return QObject::tr("Unknown %1h").hexarg2(machineType, 4); } } \ No newline at end of file diff --git a/common/peimage.h b/common/peimage.h index c81cbbf..6cc4d9d 100644 --- a/common/peimage.h +++ b/common/peimage.h @@ -36,13 +36,16 @@ extern QString machineTypeToQString(UINT16 machineType); // // PE32+ Machine type for EFI images // -#define IMAGE_FILE_MACHINE_AMD64 0x8664 -#define IMAGE_FILE_MACHINE_ARM 0x01c0 -#define IMAGE_FILE_MACHINE_ARMV7 0x01c4 -#define IMAGE_FILE_MACHINE_EBC 0x0ebc -#define IMAGE_FILE_MACHINE_I386 0x014c -#define IMAGE_FILE_MACHINE_IA64 0x0200 -#define IMAGE_FILE_MACHINE_THUMB 0x01c2 +#define EFI_IMAGE_FILE_MACHINE_I386 0x014c // x86 +#define EFI_IMAGE_FILE_MACHINE_ARM 0x01c0 // ARM little endian +#define EFI_IMAGE_FILE_MACHINE_THUMB 0x01c2 // ARM or Thumb (interworking) +#define EFI_IMAGE_FILE_MACHINE_ARMNT 0x01c4 // ARMv7 (or higher) Thumb mode only +#define EFI_IMAGE_FILE_MACHINE_POWERPC 0x01f0 // Power PC little endian +#define EFI_IMAGE_FILE_MACHINE_POWERPCFP 0x01f1 // Power PC with floating point support +#define EFI_IMAGE_FILE_MACHINE_IA64 0x0200 // Itanium +#define EFI_IMAGE_FILE_MACHINE_EBC 0x0ebc // EFI Byte Code +#define EFI_IMAGE_FILE_MACHINE_AMD64 0x8664 // x86-64 +#define EFI_IMAGE_FILE_MACHINE_ARM64 0xaa64 // ARMv8 in 64-bit mode // // EXE file formats @@ -438,25 +441,25 @@ typedef struct { #define EFI_IMAGE_REL_I386_REL32 0x0014 // PC-relative 32-bit reference to the symbols virtual address // -// x64 processor relocation types. +// x64 processor relocation types // -#define IMAGE_REL_AMD64_ABSOLUTE 0x0000 -#define IMAGE_REL_AMD64_ADDR64 0x0001 -#define IMAGE_REL_AMD64_ADDR32 0x0002 -#define IMAGE_REL_AMD64_ADDR32NB 0x0003 -#define IMAGE_REL_AMD64_REL32 0x0004 -#define IMAGE_REL_AMD64_REL32_1 0x0005 -#define IMAGE_REL_AMD64_REL32_2 0x0006 -#define IMAGE_REL_AMD64_REL32_3 0x0007 -#define IMAGE_REL_AMD64_REL32_4 0x0008 -#define IMAGE_REL_AMD64_REL32_5 0x0009 -#define IMAGE_REL_AMD64_SECTION 0x000A -#define IMAGE_REL_AMD64_SECREL 0x000B -#define IMAGE_REL_AMD64_SECREL7 0x000C -#define IMAGE_REL_AMD64_TOKEN 0x000D -#define IMAGE_REL_AMD64_SREL32 0x000E -#define IMAGE_REL_AMD64_PAIR 0x000F -#define IMAGE_REL_AMD64_SSPAN32 0x0010 +#define EFI_IMAGE_REL_AMD64_ABSOLUTE 0x0000 +#define EFI_IMAGE_REL_AMD64_ADDR64 0x0001 +#define EFI_IMAGE_REL_AMD64_ADDR32 0x0002 +#define EFI_IMAGE_REL_AMD64_ADDR32NB 0x0003 +#define EFI_IMAGE_REL_AMD64_REL32 0x0004 +#define EFI_IMAGE_REL_AMD64_REL32_1 0x0005 +#define EFI_IMAGE_REL_AMD64_REL32_2 0x0006 +#define EFI_IMAGE_REL_AMD64_REL32_3 0x0007 +#define EFI_IMAGE_REL_AMD64_REL32_4 0x0008 +#define EFI_IMAGE_REL_AMD64_REL32_5 0x0009 +#define EFI_IMAGE_REL_AMD64_SECTION 0x000A +#define EFI_IMAGE_REL_AMD64_SECREL 0x000B +#define EFI_IMAGE_REL_AMD64_SECREL7 0x000C +#define EFI_IMAGE_REL_AMD64_TOKEN 0x000D +#define EFI_IMAGE_REL_AMD64_SREL32 0x000E +#define EFI_IMAGE_REL_AMD64_PAIR 0x000F +#define EFI_IMAGE_REL_AMD64_SSPAN32 0x0010 // // Based relocation format diff --git a/common/types.h b/common/types.h index ec605b4..62aa196 100644 --- a/common/types.h +++ b/common/types.h @@ -21,6 +21,7 @@ namespace Actions { enum ActionTypes { NoAction = 50, + Erase, Create, Insert, Replace, diff --git a/common/utility.cpp b/common/utility.cpp index 6489519..0054cf2 100644 --- a/common/utility.cpp +++ b/common/utility.cpp @@ -20,7 +20,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "LZMA/LzmaDecompress.h" // Returns either new parsing data instance or obtains it from index -PARSING_DATA getParsingData(const QModelIndex & index) +PARSING_DATA parsingDataFromQByteArray(const QModelIndex & index) { if (index.isValid()) { TreeModel* model = (TreeModel*)index.model(); @@ -39,7 +39,7 @@ PARSING_DATA getParsingData(const QModelIndex & index) } // Converts parsing data to byte array -QByteArray convertParsingData(const PARSING_DATA & pdata) +QByteArray parsingDataToQByteArray(const PARSING_DATA & pdata) { return QByteArray((const char*)&pdata, sizeof(PARSING_DATA)); } diff --git a/common/utility.h b/common/utility.h index 07fcf6c..708e683 100644 --- a/common/utility.h +++ b/common/utility.h @@ -20,10 +20,10 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "parsingdata.h" // Returns either new parsing data instance or obtains it from index -PARSING_DATA getParsingData(const QModelIndex & index); +PARSING_DATA parsingDataFromQByteArray(const QModelIndex & index); // Converts parsing data to byte array -QByteArray convertParsingData(const PARSING_DATA & pdata); +QByteArray parsingDataToQByteArray(const PARSING_DATA & pdata); // Converts error code to QString extern QString errorCodeToQString(UINT8 errorCode);