2017-04-13 23:30:44 +08:00
|
|
|
/* uefireplace.cpp
|
|
|
|
|
|
|
|
Copyright (c) 2017, mxxxc. 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 "uefireplace.h"
|
|
|
|
|
|
|
|
UEFIReplace::UEFIReplace(QObject *parent) :
|
|
|
|
QObject(parent)
|
|
|
|
{
|
|
|
|
ffsEngine = new FfsEngine(this);
|
|
|
|
model = ffsEngine->treeModel();
|
|
|
|
}
|
|
|
|
|
|
|
|
UEFIReplace::~UEFIReplace()
|
|
|
|
{
|
|
|
|
delete ffsEngine;
|
|
|
|
}
|
|
|
|
|
2018-05-19 23:35:38 +08:00
|
|
|
UINT8 UEFIReplace::replace(const QString & inPath, const QByteArray & guid, const UINT8 sectionType, const QString & contentPath, const QString & outPath, bool replaceOnce)
|
2017-04-13 23:30:44 +08:00
|
|
|
{
|
|
|
|
QFileInfo fileInfo = QFileInfo(inPath);
|
|
|
|
if (!fileInfo.exists())
|
|
|
|
return ERR_FILE_OPEN;
|
|
|
|
|
|
|
|
fileInfo = QFileInfo(contentPath);
|
|
|
|
if (!fileInfo.exists())
|
|
|
|
return ERR_FILE_OPEN;
|
|
|
|
|
|
|
|
QFile inputFile;
|
|
|
|
inputFile.setFileName(inPath);
|
|
|
|
|
|
|
|
if (!inputFile.open(QFile::ReadOnly))
|
|
|
|
return ERR_FILE_READ;
|
|
|
|
|
|
|
|
QByteArray buffer = inputFile.readAll();
|
|
|
|
inputFile.close();
|
|
|
|
|
|
|
|
UINT8 result = ffsEngine->parseImageFile(buffer);
|
|
|
|
if (result)
|
|
|
|
return result;
|
|
|
|
|
|
|
|
QFile contentFile;
|
|
|
|
contentFile.setFileName(contentPath);
|
|
|
|
|
|
|
|
if (!contentFile.open(QFile::ReadOnly))
|
|
|
|
return ERR_FILE_READ;
|
|
|
|
|
|
|
|
QByteArray contents = contentFile.readAll();
|
|
|
|
contentFile.close();
|
|
|
|
|
2018-05-19 23:35:38 +08:00
|
|
|
result = replaceInFile(model->index(0, 0), guid, sectionType, contents, replaceOnce);
|
2017-04-13 23:30:44 +08:00
|
|
|
if (result)
|
|
|
|
return result;
|
|
|
|
|
|
|
|
QByteArray reconstructed;
|
|
|
|
result = ffsEngine->reconstructImageFile(reconstructed);
|
|
|
|
if (result)
|
|
|
|
return result;
|
|
|
|
if (reconstructed == buffer)
|
|
|
|
return ERR_NOTHING_TO_PATCH;
|
|
|
|
|
|
|
|
QFile outputFile;
|
2018-05-19 23:35:38 +08:00
|
|
|
outputFile.setFileName(outPath);
|
2017-04-13 23:30:44 +08:00
|
|
|
if (!outputFile.open(QFile::WriteOnly))
|
|
|
|
return ERR_FILE_WRITE;
|
|
|
|
|
|
|
|
outputFile.resize(0);
|
|
|
|
outputFile.write(reconstructed);
|
|
|
|
outputFile.close();
|
|
|
|
|
|
|
|
return ERR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2018-05-19 23:35:38 +08:00
|
|
|
UINT8 UEFIReplace::replaceInFile(const QModelIndex & index, const QByteArray & guid, const UINT8 sectionType, const QByteArray & newData, bool replaceOnce)
|
2017-04-13 23:30:44 +08:00
|
|
|
{
|
|
|
|
if (!model || !index.isValid())
|
|
|
|
return ERR_INVALID_PARAMETER;
|
2018-05-20 04:53:21 +08:00
|
|
|
bool patched = false;
|
2017-04-13 23:30:44 +08:00
|
|
|
if (model->subtype(index) == sectionType) {
|
|
|
|
QModelIndex fileIndex = model->findParentOfType(index, Types::File);
|
|
|
|
QByteArray fileGuid = model->header(fileIndex).left(sizeof(EFI_GUID));
|
2018-05-20 04:53:21 +08:00
|
|
|
bool guidMatch = fileGuid == guid;
|
|
|
|
if (!guidMatch && sectionType == EFI_SECTION_FREEFORM_SUBTYPE_GUID) {
|
|
|
|
QByteArray subGuid = model->header(index).mid(sizeof(uint32_t), sizeof(EFI_GUID));
|
|
|
|
guidMatch = subGuid == guid;
|
|
|
|
}
|
|
|
|
if (guidMatch && model->action(index) != Actions::Replace) {
|
2018-05-19 23:35:38 +08:00
|
|
|
UINT8 result = ffsEngine->replace(index, newData, REPLACE_MODE_BODY);
|
|
|
|
if (replaceOnce || (result != ERR_SUCCESS && result != ERR_NOTHING_TO_PATCH))
|
|
|
|
return result;
|
2018-05-20 04:53:21 +08:00
|
|
|
patched = result == ERR_SUCCESS;
|
2017-04-13 23:30:44 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (model->rowCount(index) > 0) {
|
|
|
|
for (int i = 0; i < model->rowCount(index); i++) {
|
2018-05-19 23:35:38 +08:00
|
|
|
UINT8 result = replaceInFile(index.child(i, 0), guid, sectionType, newData, replaceOnce);
|
|
|
|
if (result == ERR_SUCCESS) {
|
2017-04-13 23:30:44 +08:00
|
|
|
patched = true;
|
2018-05-19 23:35:38 +08:00
|
|
|
if (replaceOnce)
|
|
|
|
break;
|
|
|
|
} else if (result != ERR_NOTHING_TO_PATCH) {
|
2017-04-13 23:30:44 +08:00
|
|
|
return result;
|
2018-05-19 23:35:38 +08:00
|
|
|
}
|
2017-04-13 23:30:44 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return patched ? ERR_SUCCESS : ERR_NOTHING_TO_PATCH;
|
|
|
|
}
|