From 31ccb2a0542734f8eb976789056c9253c68a0054 Mon Sep 17 00:00:00 2001 From: vit9696 Date: Sun, 3 Nov 2019 16:15:03 +0300 Subject: [PATCH] Support applying patches from terminal, closes #186 --- UEFIPatch/uefipatch.cpp | 80 ++++++++++++++++++++++++++++++++++++ UEFIPatch/uefipatch.h | 1 + UEFIPatch/uefipatch_main.cpp | 16 ++++++-- basetypes.h | 4 ++ 4 files changed, 98 insertions(+), 3 deletions(-) diff --git a/UEFIPatch/uefipatch.cpp b/UEFIPatch/uefipatch.cpp index 19129a0..3f4c091 100644 --- a/UEFIPatch/uefipatch.cpp +++ b/UEFIPatch/uefipatch.cpp @@ -121,6 +121,86 @@ UINT8 UEFIPatch::patchFromFile(const QString & path, const QString & patches, co return ERR_SUCCESS; } +UINT8 UEFIPatch::patchFromArg(const QString & path, const QString & patch, const QString & outputPath) +{ + QFileInfo fileInfo = QFileInfo(path); + + if (!fileInfo.exists()) + return ERR_FILE_OPEN; + + QFile inputFile; + inputFile.setFileName(path); + + if (!inputFile.open(QFile::ReadOnly)) + return ERR_FILE_READ; + + QByteArray buffer = inputFile.readAll(); + inputFile.close(); + + UINT8 result = ffsEngine->parseImageFile(buffer); + if (result) + return result; + + if (patch != nullptr && !patch.isEmpty()) { + QByteArray line = patch.toUtf8(); + + QList list = line.split(' '); + if (list.count() < 3) + return ERR_INVALID_PARAMETER; + + QUuid uuid = QUuid(list.at(0)); + QByteArray guid = QByteArray::fromRawData((const char*)&uuid.data1, sizeof(EFI_GUID)); + bool converted; + UINT8 sectionType = (UINT8)list.at(1).toUShort(&converted, 16); + if (!converted) + return ERR_INVALID_PARAMETER; + + QVector patches; + + for (int i = 2; i < list.count(); i++) { + QList patchList = list.at(i).split(':'); + PatchData patch; + patch.type = *(UINT8*)patchList.at(0).constData(); + if (patch.type == PATCH_TYPE_PATTERN) { + patch.offset = 0xFFFFFFFF; + patch.hexFindPattern = patchList.at(1); + patch.hexReplacePattern = patchList.at(2); + patches.append(patch); + } + else if (patch.type == PATCH_TYPE_OFFSET) { + patch.offset = patchList.at(1).toUInt(NULL, 16); + patch.hexReplacePattern = patchList.at(2); + patches.append(patch); + } + else { + // Ignore unknown patch type + continue; + } + } + result = patchFile(model->index(0, 0), guid, sectionType, patches); + if (result && result != ERR_NOTHING_TO_PATCH) + return result; + } + + QByteArray reconstructed; + result = ffsEngine->reconstructImageFile(reconstructed); + if (result) + return result; + if (reconstructed == buffer) + return ERR_NOTHING_TO_PATCH; + + QFile outputFile; + outputFile.setFileName(outputPath); + if (!outputFile.open(QFile::WriteOnly)) + return ERR_FILE_WRITE; + + outputFile.resize(0); + outputFile.write(reconstructed); + outputFile.close(); + + return ERR_SUCCESS; +} + UINT8 UEFIPatch::patchFile(const QModelIndex & index, const QByteArray & fileGuid, const UINT8 sectionType, const QVector & patches) { diff --git a/UEFIPatch/uefipatch.h b/UEFIPatch/uefipatch.h index d42b31d..b3f70d1 100644 --- a/UEFIPatch/uefipatch.h +++ b/UEFIPatch/uefipatch.h @@ -34,6 +34,7 @@ public: ~UEFIPatch(); UINT8 patchFromFile(const QString & path, const QString & patches, const QString & outputPath); + UINT8 patchFromArg(const QString & path, const QString & patch, const QString & outputPath); private: UINT8 patchFile(const QModelIndex & index, const QByteArray & fileGuid, const UINT8 sectionType, const QVector & patches); FfsEngine* ffsEngine; diff --git a/UEFIPatch/uefipatch_main.cpp b/UEFIPatch/uefipatch_main.cpp index ee1c9c9..f70439a 100644 --- a/UEFIPatch/uefipatch_main.cpp +++ b/UEFIPatch/uefipatch_main.cpp @@ -33,7 +33,8 @@ int main(int argc, char *argv[]) if (argumentsCount < 2) { std::cout << "UEFIPatch " PROGRAM_VERSION " - UEFI image file patching utility" << std::endl << std::endl << - "Usage: UEFIPatch image_file [patches.txt] [-o output]" << std::endl << std::endl << + "Usage: UEFIPatch image_file [patches.txt] [-o output]" << std::endl << + "Usage: UEFIPatch image_file [-p \"Guid SectionType Patch\"] [-o output]" << std::endl << std::endl << "Patches will be read from patches.txt file by default\n"; return ERR_SUCCESS; } @@ -41,8 +42,13 @@ int main(int argc, char *argv[]) QString inputPath = a.arguments().at(1); QString patches = "patches.txt"; QString outputPath = inputPath + ".patched"; + int patchFrom = PATCH_FROM_FILE; for (UINT32 i = 2; i < argumentsCount; i++) { - if ((args.at(i) == "-o" || args.at(i) == "--output") && i + 1 < argumentsCount) { + if ((args.at(i) == "-p" || args.at(i) == "--patch") && i + 1 < argumentsCount) { + patchFrom = PATCH_FROM_ARG; + patches = args.at(i+1); + i++; + } else if ((args.at(i) == "-o" || args.at(i) == "--output") && i + 1 < argumentsCount) { outputPath = args.at(i+1); i++; } else if (patches == "patches.txt") { @@ -53,7 +59,11 @@ int main(int argc, char *argv[]) } if (result == ERR_SUCCESS) { - result = w.patchFromFile(inputPath, patches, outputPath); + if (patchFrom == PATCH_FROM_FILE) { + result = w.patchFromFile(inputPath, patches, outputPath); + } else if (patchFrom == PATCH_FROM_ARG) { + result = w.patchFromArg(inputPath, patches, outputPath); + } } switch (result) { diff --git a/basetypes.h b/basetypes.h index 04c65b2..007203e 100644 --- a/basetypes.h +++ b/basetypes.h @@ -127,6 +127,10 @@ typedef size_t UINTN; #define PATCH_MODE_HEADER 0 #define PATCH_MODE_BODY 1 +// Patch from +#define PATCH_FROM_FILE 0 +#define PATCH_FROM_ARG 1 + // Patch types #define PATCH_TYPE_OFFSET 'O' #define PATCH_TYPE_PATTERN 'P'