mirror of
https://github.com/LongSoft/UEFITool.git
synced 2024-11-25 01:18:22 +08:00
UEFIPatch 0.1.0
- new command-line utility to patch files inside UEFI image - corrected bug with wrong header size calculation for GUID_DEFINED_SECTION with PROCESSING_REQUIRED attribute set - patch routine implemented in ffsEngine, will be added to UEFITool soon
This commit is contained in:
parent
02a240ba18
commit
1c34c1bf84
17
UEFIPatch/patches.txt
Normal file
17
UEFIPatch/patches.txt
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# PowerMgmtDxe | Haswell
|
||||||
|
F7731B4C-58A2-4DF4-8980-5645D39ECE58 75080FBAE80F89442430 EB080FBAE80F89442430
|
||||||
|
# PowerMgmtDxe | Haswell-E
|
||||||
|
F7731B4C-58A2-4DF4-8980-5645D39ECE58 0FBA6C24380F 0FBA7424380F
|
||||||
|
|
||||||
|
# PowerManagement | Sandy Bridge with ME 8.xx, Ivy Bridge
|
||||||
|
8C783970-F02A-4A4D-AF09-8797A51EEC8D 75080FBAE80F89442430 EB080FBAE80F89442430
|
||||||
|
# PowerManagement | New SB-E/IB-E
|
||||||
|
8C783970-F02A-4A4D-AF09-8797A51EEC8D 0FBA6C24380F 0FBA7424380F
|
||||||
|
|
||||||
|
# CpuPei | Sandy Bridge with ME 7.xx, old SB-E/IB-E
|
||||||
|
2BB5AFA9-FF33-417B-8497-CB773C2B93BF 800018EB050D0080 000018EB050D0000
|
||||||
|
|
||||||
|
# You can add your own patch here
|
||||||
|
# Format is simple: "file_GUID search_pattern replace_pattern"
|
||||||
|
# String beginned with '#' symbol is a comment and will be ignored by the program
|
||||||
|
|
165
UEFIPatch/uefipatch.cpp
Normal file
165
UEFIPatch/uefipatch.cpp
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
/* uefipatch.cpp
|
||||||
|
|
||||||
|
Copyright (c) 2014, 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 "uefipatch.h"
|
||||||
|
|
||||||
|
UEFIPatch::UEFIPatch(QObject *parent) :
|
||||||
|
QObject(parent)
|
||||||
|
{
|
||||||
|
ffsEngine = new FfsEngine(this);
|
||||||
|
model = ffsEngine->treeModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
UEFIPatch::~UEFIPatch()
|
||||||
|
{
|
||||||
|
delete ffsEngine;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT8 UEFIPatch::patchFromFile(QString path)
|
||||||
|
{
|
||||||
|
QFileInfo patchInfo = QFileInfo("patches.txt");
|
||||||
|
|
||||||
|
if (!patchInfo.exists())
|
||||||
|
return ERR_INVALID_FILE;
|
||||||
|
|
||||||
|
QFile file;
|
||||||
|
file.setFileName("patches.txt");
|
||||||
|
|
||||||
|
if (!file.open(QFile::ReadOnly | QFile::Text))
|
||||||
|
return ERR_INVALID_FILE;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
while (!file.atEnd()) {
|
||||||
|
QByteArray line = file.readLine();
|
||||||
|
// Use sharp sign as commentary
|
||||||
|
if (line.count() == 0 || line[0] == '#')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
QList<QByteArray> list = line.split(' ');
|
||||||
|
if (list.count() < 3)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
QUuid uuid = QUuid(list.at(0));
|
||||||
|
QByteArray guid = QByteArray::fromRawData((const char*)&uuid.data1, sizeof(EFI_GUID));
|
||||||
|
result = patchFile(model->index(0, 0), guid, QByteArray::fromHex(list.at(1)), QByteArray::fromHex(list.at(2)));
|
||||||
|
if (result)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray reconstructed;
|
||||||
|
result = ffsEngine->reconstructImageFile(reconstructed);
|
||||||
|
if (result)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
if (reconstructed == buffer) {
|
||||||
|
return ERR_ITEM_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFile outputFile;
|
||||||
|
outputFile.setFileName(path.append(".patched"));
|
||||||
|
if (!outputFile.open(QFile::WriteOnly))
|
||||||
|
return ERR_FILE_WRITE;
|
||||||
|
|
||||||
|
outputFile.resize(0);
|
||||||
|
outputFile.write(reconstructed);
|
||||||
|
outputFile.close();
|
||||||
|
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT8 UEFIPatch::patch(QString path, QString fileGuid, QString findPattern, QString replacePattern)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
|
|
||||||
|
QUuid uuid = QUuid(fileGuid);
|
||||||
|
QByteArray guid = QByteArray::fromRawData((const char*)&uuid.data1, sizeof(EFI_GUID));
|
||||||
|
result = patchFile(model->index(0, 0), guid, QByteArray::fromHex(findPattern.toLatin1()), QByteArray::fromHex(replacePattern.toLatin1()));
|
||||||
|
if (result)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
QByteArray reconstructed;
|
||||||
|
result = ffsEngine->reconstructImageFile(reconstructed);
|
||||||
|
if (result)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
if (reconstructed == buffer) {
|
||||||
|
return ERR_ITEM_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFile outputFile;
|
||||||
|
outputFile.setFileName(path.append(".patched"));
|
||||||
|
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 QByteArray & findPattern, const QByteArray & replacePattern)
|
||||||
|
{
|
||||||
|
if (!model || !index.isValid())
|
||||||
|
return ERR_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
if (model->type(index) == Types::File && model->header(index).left(sizeof(EFI_GUID)) == fileGuid) {
|
||||||
|
return ffsEngine->patch(index, findPattern, replacePattern, PATCH_MODE_BODY);
|
||||||
|
}
|
||||||
|
|
||||||
|
int childCount = model->rowCount(index);
|
||||||
|
if (childCount > 0) {
|
||||||
|
UINT8 result;
|
||||||
|
for (int i = 0; i < childCount; i++) {
|
||||||
|
result = patchFile(index.child(i, 0), fileGuid, findPattern, replacePattern);
|
||||||
|
if (result)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
}
|
45
UEFIPatch/uefipatch.h
Normal file
45
UEFIPatch/uefipatch.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/* uefipatch.h
|
||||||
|
|
||||||
|
Copyright (c) 2014, 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 __UEFIPATCH_H__
|
||||||
|
#define __UEFIPATCH_H__
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <QString>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QUuid>
|
||||||
|
|
||||||
|
#include "../basetypes.h"
|
||||||
|
#include "../ffs.h"
|
||||||
|
#include "../ffsengine.h"
|
||||||
|
|
||||||
|
class UEFIPatch : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit UEFIPatch(QObject *parent = 0);
|
||||||
|
~UEFIPatch();
|
||||||
|
|
||||||
|
UINT8 patchFromFile(QString path);
|
||||||
|
UINT8 patch(QString path, QString fileGuid, QString findPattern, QString replacePattern);
|
||||||
|
|
||||||
|
private:
|
||||||
|
UINT8 patchFile(const QModelIndex & index, const QByteArray & fileGuid, const QByteArray & findPattern, const QByteArray & replacePattern);
|
||||||
|
FfsEngine* ffsEngine;
|
||||||
|
TreeModel* model;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
39
UEFIPatch/uefipatch.pro
Normal file
39
UEFIPatch/uefipatch.pro
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
QT += core
|
||||||
|
QT -= gui
|
||||||
|
|
||||||
|
TARGET = UEFIPatch
|
||||||
|
TEMPLATE = app
|
||||||
|
CONFIG += console
|
||||||
|
|
||||||
|
SOURCES += uefipatch_main.cpp \
|
||||||
|
uefipatch.cpp \
|
||||||
|
../types.cpp \
|
||||||
|
../descriptor.cpp \
|
||||||
|
../ffs.cpp \
|
||||||
|
../ffsengine.cpp \
|
||||||
|
../treeitem.cpp \
|
||||||
|
../treemodel.cpp \
|
||||||
|
../LZMA/LzmaCompress.c \
|
||||||
|
../LZMA/LzmaDecompress.c \
|
||||||
|
../LZMA/SDK/C/LzFind.c \
|
||||||
|
../LZMA/SDK/C/LzmaDec.c \
|
||||||
|
../LZMA/SDK/C/LzmaEnc.c \
|
||||||
|
../Tiano/EfiTianoDecompress.c \
|
||||||
|
../Tiano/EfiTianoCompress.c
|
||||||
|
|
||||||
|
HEADERS += uefipatch.h \
|
||||||
|
../basetypes.h \
|
||||||
|
../descriptor.h \
|
||||||
|
../gbe.h \
|
||||||
|
../me.h \
|
||||||
|
../ffs.h \
|
||||||
|
../peimage.h \
|
||||||
|
../types.h \
|
||||||
|
../ffsengine.h \
|
||||||
|
../treeitem.h \
|
||||||
|
../treemodel.h \
|
||||||
|
../LZMA/LzmaCompress.h \
|
||||||
|
../LZMA/LzmaDecompress.h \
|
||||||
|
../Tiano/EfiTianoDecompress.h \
|
||||||
|
../Tiano/EfiTianoCompress.h
|
||||||
|
|
73
UEFIPatch/uefipatch_main.cpp
Normal file
73
UEFIPatch/uefipatch_main.cpp
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
/* uefipatch_main.cpp
|
||||||
|
|
||||||
|
Copyright (c) 2014, 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 <QCoreApplication>
|
||||||
|
#include <QString>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <iostream>
|
||||||
|
#include "uefipatch.h"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
QCoreApplication a(argc, argv);
|
||||||
|
a.setOrganizationName("CodeRush");
|
||||||
|
a.setOrganizationDomain("coderush.me");
|
||||||
|
a.setApplicationName("UEFIExtract");
|
||||||
|
|
||||||
|
UEFIPatch w;
|
||||||
|
UINT8 result = ERR_SUCCESS;
|
||||||
|
UINT32 argumentsCount = a.arguments().length();
|
||||||
|
|
||||||
|
|
||||||
|
if (argumentsCount == 2) {
|
||||||
|
result = w.patchFromFile(a.arguments().at(1));
|
||||||
|
}
|
||||||
|
else if (argumentsCount == 5) {
|
||||||
|
result = w.patch(a.arguments().at(1), a.arguments().at(2), a.arguments().at(3), a.arguments().at(4));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result = ERR_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
switch (result) {
|
||||||
|
case ERR_INVALID_PARAMETER:
|
||||||
|
std::cout << "UEFIPatch 0.1.0 - UEFI image file patching utility" << std::endl << std::endl <<
|
||||||
|
"Usage: UEFIPatch image_file [ffs_file_guid search_pattern replace_pattern]" << std::endl << std::endl <<
|
||||||
|
"image_file - full or relative path to UEFI image file" << std::endl <<
|
||||||
|
"ffs_file_guid - GUID of FFS file to be patched" << std::endl <<
|
||||||
|
"search_pattern - pattern to search" << std::endl <<
|
||||||
|
"replace_pattern - pattern to replace" << std::endl << std::endl <<
|
||||||
|
"If only image_file parameter is specified, patches will be read from patches.txt file";
|
||||||
|
break;
|
||||||
|
case ERR_SUCCESS:
|
||||||
|
std::cout << "Image patched" << std::endl;
|
||||||
|
break;
|
||||||
|
case ERR_ITEM_NOT_FOUND:
|
||||||
|
std::cout << "FFS file or search pattern not found in input file" << std::endl;
|
||||||
|
break;
|
||||||
|
case ERR_INVALID_FILE:
|
||||||
|
std::cout << "patches.txt file not found or can't be read" << std::endl;
|
||||||
|
break;
|
||||||
|
case ERR_FILE_OPEN:
|
||||||
|
std::cout << "Input file not found" << std::endl;
|
||||||
|
break;
|
||||||
|
case ERR_FILE_READ:
|
||||||
|
std::cout << "Input file can't be read" << std::endl;
|
||||||
|
break;
|
||||||
|
case ERR_FILE_WRITE:
|
||||||
|
std::cout << "Output file can't be written" << std::endl;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
std::cout << "Error " << result << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
@ -85,6 +85,7 @@ typedef uint16_t CHAR16;
|
|||||||
#define ERR_COMPLEX_BLOCK_MAP 35
|
#define ERR_COMPLEX_BLOCK_MAP 35
|
||||||
#define ERR_DIR_ALREADY_EXIST 36
|
#define ERR_DIR_ALREADY_EXIST 36
|
||||||
#define ERR_DIR_CREATE 37
|
#define ERR_DIR_CREATE 37
|
||||||
|
#define ERR_UNKNOWN_PATCH_MODE 38
|
||||||
#define ERR_NOT_IMPLEMENTED 0xFF
|
#define ERR_NOT_IMPLEMENTED 0xFF
|
||||||
|
|
||||||
// Compression algorithms
|
// Compression algorithms
|
||||||
@ -109,6 +110,10 @@ typedef uint16_t CHAR16;
|
|||||||
#define REPLACE_MODE_AS_IS 0
|
#define REPLACE_MODE_AS_IS 0
|
||||||
#define REPLACE_MODE_BODY 1
|
#define REPLACE_MODE_BODY 1
|
||||||
|
|
||||||
|
// Item patch modes
|
||||||
|
#define PATCH_MODE_HEADER 0
|
||||||
|
#define PATCH_MODE_BODY 1
|
||||||
|
|
||||||
// Erase polarity types
|
// Erase polarity types
|
||||||
#define ERASE_POLARITY_FALSE 0
|
#define ERASE_POLARITY_FALSE 0
|
||||||
#define ERASE_POLARITY_TRUE 1
|
#define ERASE_POLARITY_TRUE 1
|
||||||
@ -119,6 +124,8 @@ typedef uint16_t CHAR16;
|
|||||||
#define SEARCH_MODE_BODY 2
|
#define SEARCH_MODE_BODY 2
|
||||||
#define SEARCH_MODE_ALL 3
|
#define SEARCH_MODE_ALL 3
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// EFI GUID
|
// EFI GUID
|
||||||
typedef struct {
|
typedef struct {
|
||||||
UINT8 Data[16];
|
UINT8 Data[16];
|
||||||
|
13
ffs.cpp
13
ffs.cpp
@ -165,14 +165,19 @@ QString sectionTypeToQString(const UINT8 type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT32 sizeOfSectionHeaderOfType(const UINT8 type)
|
UINT32 sizeOfSectionHeader(EFI_COMMON_SECTION_HEADER* header)
|
||||||
{
|
{
|
||||||
switch (type)
|
if (!header)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
switch (header->Type)
|
||||||
{
|
{
|
||||||
case EFI_SECTION_COMPRESSION:
|
case EFI_SECTION_COMPRESSION:
|
||||||
return sizeof(EFI_COMMON_SECTION_HEADER);
|
return sizeof(EFI_COMMON_SECTION_HEADER);
|
||||||
case EFI_SECTION_GUID_DEFINED:
|
case EFI_SECTION_GUID_DEFINED: {
|
||||||
return sizeof(EFI_GUID_DEFINED_SECTION);
|
EFI_GUID_DEFINED_SECTION* gdsHeader = (EFI_GUID_DEFINED_SECTION*)header;
|
||||||
|
return gdsHeader->DataOffset;
|
||||||
|
}
|
||||||
case EFI_SECTION_DISPOSABLE:
|
case EFI_SECTION_DISPOSABLE:
|
||||||
return sizeof(EFI_DISPOSABLE_SECTION);
|
return sizeof(EFI_DISPOSABLE_SECTION);
|
||||||
case EFI_SECTION_PE32:
|
case EFI_SECTION_PE32:
|
||||||
|
2
ffs.h
2
ffs.h
@ -416,7 +416,7 @@ typedef EFI_COMMON_SECTION_HEADER EFI_FIRMWARE_VOLUME_IMAGE_SECTION;
|
|||||||
typedef EFI_COMMON_SECTION_HEADER EFI_USER_INTERFACE_SECTION;
|
typedef EFI_COMMON_SECTION_HEADER EFI_USER_INTERFACE_SECTION;
|
||||||
|
|
||||||
//Section routines
|
//Section routines
|
||||||
extern UINT32 sizeOfSectionHeaderOfType(const UINT8 type);
|
extern UINT32 sizeOfSectionHeader(EFI_COMMON_SECTION_HEADER* header);
|
||||||
|
|
||||||
// Restore previous packing rules
|
// Restore previous packing rules
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
@ -1132,7 +1132,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c
|
|||||||
case EFI_SECTION_PEI_DEPEX:
|
case EFI_SECTION_PEI_DEPEX:
|
||||||
case EFI_SECTION_SMM_DEPEX:
|
case EFI_SECTION_SMM_DEPEX:
|
||||||
case EFI_SECTION_COMPATIBILITY16: {
|
case EFI_SECTION_COMPATIBILITY16: {
|
||||||
headerSize = sizeOfSectionHeaderOfType(sectionHeader->Type);
|
headerSize = sizeOfSectionHeader(sectionHeader);
|
||||||
header = section.left(headerSize);
|
header = section.left(headerSize);
|
||||||
body = section.mid(headerSize, sectionSize - headerSize);
|
body = section.mid(headerSize, sectionSize - headerSize);
|
||||||
|
|
||||||
@ -1509,12 +1509,12 @@ UINT8 FfsEngine::insert(const QModelIndex & index, const QByteArray & object, co
|
|||||||
else if (model->type(parent) == Types::File) {
|
else if (model->type(parent) == Types::File) {
|
||||||
type = Types::Section;
|
type = Types::Section;
|
||||||
EFI_COMMON_SECTION_HEADER* commonHeader = (EFI_COMMON_SECTION_HEADER*)object.constData();
|
EFI_COMMON_SECTION_HEADER* commonHeader = (EFI_COMMON_SECTION_HEADER*)object.constData();
|
||||||
headerSize = sizeOfSectionHeaderOfType(commonHeader->Type);
|
headerSize = sizeOfSectionHeader(commonHeader);
|
||||||
}
|
}
|
||||||
else if (model->type(parent) == Types::Section) {
|
else if (model->type(parent) == Types::Section) {
|
||||||
type = Types::Section;
|
type = Types::Section;
|
||||||
EFI_COMMON_SECTION_HEADER* commonHeader = (EFI_COMMON_SECTION_HEADER*)object.constData();
|
EFI_COMMON_SECTION_HEADER* commonHeader = (EFI_COMMON_SECTION_HEADER*)object.constData();
|
||||||
headerSize = sizeOfSectionHeaderOfType(commonHeader->Type);
|
headerSize = sizeOfSectionHeader(commonHeader);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return ERR_NOT_IMPLEMENTED;
|
return ERR_NOT_IMPLEMENTED;
|
||||||
@ -1549,7 +1549,7 @@ UINT8 FfsEngine::replace(const QModelIndex & index, const QByteArray & object, c
|
|||||||
else if (model->type(index) == Types::Section) {
|
else if (model->type(index) == Types::Section) {
|
||||||
if (mode == REPLACE_MODE_AS_IS) {
|
if (mode == REPLACE_MODE_AS_IS) {
|
||||||
EFI_COMMON_SECTION_HEADER* commonHeader = (EFI_COMMON_SECTION_HEADER*)object.constData();
|
EFI_COMMON_SECTION_HEADER* commonHeader = (EFI_COMMON_SECTION_HEADER*)object.constData();
|
||||||
headerSize = sizeOfSectionHeaderOfType(commonHeader->Type);
|
headerSize = sizeOfSectionHeader(commonHeader);
|
||||||
result = create(index, Types::Section, object.left(headerSize), object.right(object.size() - headerSize), CREATE_MODE_AFTER, Actions::Replace);
|
result = create(index, Types::Section, object.left(headerSize), object.right(object.size() - headerSize), CREATE_MODE_AFTER, Actions::Replace);
|
||||||
}
|
}
|
||||||
else if (mode == REPLACE_MODE_BODY) {
|
else if (mode == REPLACE_MODE_BODY) {
|
||||||
@ -1754,7 +1754,7 @@ UINT8 FfsEngine::decompress(const QByteArray & compressedData, const UINT8 compr
|
|||||||
// Shitty compressed section with a section header between COMPRESSED_SECTION_HEADER and LZMA_HEADER
|
// Shitty compressed section with a section header between COMPRESSED_SECTION_HEADER and LZMA_HEADER
|
||||||
// We must determine section header size by checking it's type before we can unpack that non-standard compressed section
|
// We must determine section header size by checking it's type before we can unpack that non-standard compressed section
|
||||||
shittySectionHeader = (EFI_COMMON_SECTION_HEADER*)data;
|
shittySectionHeader = (EFI_COMMON_SECTION_HEADER*)data;
|
||||||
shittySectionSize = sizeOfSectionHeaderOfType(shittySectionHeader->Type);
|
shittySectionSize = sizeOfSectionHeader(shittySectionHeader);
|
||||||
|
|
||||||
// Decompress section data once again
|
// Decompress section data once again
|
||||||
data += shittySectionSize;
|
data += shittySectionSize;
|
||||||
@ -1852,7 +1852,7 @@ UINT8 FfsEngine::compress(const QByteArray & data, const UINT8 algorithm, QByteA
|
|||||||
{
|
{
|
||||||
QByteArray header = data.left(sizeof(EFI_COMMON_SECTION_HEADER));
|
QByteArray header = data.left(sizeof(EFI_COMMON_SECTION_HEADER));
|
||||||
EFI_COMMON_SECTION_HEADER* sectionHeader = (EFI_COMMON_SECTION_HEADER*)header.constData();
|
EFI_COMMON_SECTION_HEADER* sectionHeader = (EFI_COMMON_SECTION_HEADER*)header.constData();
|
||||||
UINT32 headerSize = sizeOfSectionHeaderOfType(sectionHeader->Type);
|
UINT32 headerSize = sizeOfSectionHeader(sectionHeader);
|
||||||
header = data.left(headerSize);
|
header = data.left(headerSize);
|
||||||
QByteArray newData = data.mid(headerSize);
|
QByteArray newData = data.mid(headerSize);
|
||||||
if (LzmaCompress((UINT8*)newData.constData(), newData.size(), NULL, &compressedSize) != ERR_BUFFER_TOO_SMALL)
|
if (LzmaCompress((UINT8*)newData.constData(), newData.size(), NULL, &compressedSize) != ERR_BUFFER_TOO_SMALL)
|
||||||
@ -3198,3 +3198,48 @@ UINT8 FfsEngine::dump(const QModelIndex & index, const QString path)
|
|||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UINT8 FfsEngine::patch(const QModelIndex & index, const QByteArray & findPattern, const QByteArray & replacePattern, const UINT8 mode)
|
||||||
|
{
|
||||||
|
if (!index.isValid() || findPattern.isEmpty())
|
||||||
|
return ERR_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
// Skip removed files
|
||||||
|
if (model->action(index) == Actions::Remove)
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
|
||||||
|
// Patch header
|
||||||
|
if (mode == PATCH_MODE_HEADER && model->header(index).contains(findPattern)) {
|
||||||
|
QByteArray patched = model->header(index);
|
||||||
|
patched.replace(findPattern, replacePattern).append(model->body(index));
|
||||||
|
msg(tr("Header of %1 patched, %2 -> %3")
|
||||||
|
.arg(model->nameString(index))
|
||||||
|
.arg(QString(findPattern.toHex()))
|
||||||
|
.arg(QString(replacePattern.toHex())), index);
|
||||||
|
return replace(index, patched, REPLACE_MODE_AS_IS);
|
||||||
|
}
|
||||||
|
// Patch body
|
||||||
|
else if (mode == PATCH_MODE_BODY) {
|
||||||
|
if (model->rowCount(index)) {
|
||||||
|
UINT8 result;
|
||||||
|
for (int i = 0; i < model->rowCount(index); i++) {
|
||||||
|
result = patch(index.child(i, 0), findPattern, replacePattern, PATCH_MODE_BODY);
|
||||||
|
if (result)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (model->body(index).contains(findPattern)){
|
||||||
|
QByteArray patched = model->body(index);
|
||||||
|
patched.replace(findPattern, replacePattern);
|
||||||
|
patched.prepend(model->header(index));
|
||||||
|
msg(tr("Body of %1 patched, %2 -> %3")
|
||||||
|
.arg(model->nameString(index))
|
||||||
|
.arg(QString(findPattern.toHex()))
|
||||||
|
.arg(QString(replacePattern.toHex())), index);
|
||||||
|
return replace(index, patched, REPLACE_MODE_AS_IS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return ERR_UNKNOWN_PATCH_MODE;
|
||||||
|
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
}
|
@ -86,6 +86,7 @@ public:
|
|||||||
UINT8 remove(const QModelIndex & index);
|
UINT8 remove(const QModelIndex & index);
|
||||||
UINT8 rebuild(const QModelIndex & index);
|
UINT8 rebuild(const QModelIndex & index);
|
||||||
UINT8 dump(const QModelIndex & index, const QString path);
|
UINT8 dump(const QModelIndex & index, const QString path);
|
||||||
|
UINT8 patch(const QModelIndex & index, const QByteArray & findPattern, const QByteArray & replacePattern, const UINT8 mode);
|
||||||
|
|
||||||
// Search routines
|
// Search routines
|
||||||
UINT8 findHexPattern(const QByteArray & pattern, const UINT8 mode);
|
UINT8 findHexPattern(const QByteArray & pattern, const UINT8 mode);
|
||||||
|
Loading…
Reference in New Issue
Block a user