Support applying patches from terminal, closes #186

This commit is contained in:
vit9696 2019-11-03 16:15:03 +03:00
parent 4bee991c94
commit 31ccb2a054
4 changed files with 98 additions and 3 deletions

View file

@ -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<QByteArray> 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<PatchData> patches;
for (int i = 2; i < list.count(); i++) {
QList<QByteArray> 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<PatchData> & patches)
{

View file

@ -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<PatchData> & patches);
FfsEngine* ffsEngine;

View file

@ -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) {
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) {

View file

@ -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'