mirror of
https://github.com/LongSoft/UEFITool.git
synced 2024-11-24 17:08:23 +08:00
Partially port UEFIPatch without backing engine ::patch support
This commit is contained in:
parent
d61d789569
commit
3699a7cebc
1
.gitignore
vendored
1
.gitignore
vendored
@ -241,6 +241,7 @@ UEFIDump/UEFIDump
|
||||
UEFIExtract/UEFIExtract
|
||||
UEFIFind/UEFIFind
|
||||
UEFIReplace/UEFIReplace
|
||||
UEFIPatch/UEFIPatch
|
||||
.qmake.stash
|
||||
CMakeCache.txt
|
||||
CMakeFiles
|
||||
|
69
UEFIPatch/CMakeLists.txt
Normal file
69
UEFIPatch/CMakeLists.txt
Normal file
@ -0,0 +1,69 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
PROJECT(UEFIPatch)
|
||||
|
||||
SET(PROJECT_SOURCES
|
||||
uefipatch_main.cpp
|
||||
uefipatch.cpp
|
||||
../common/guiddatabase.cpp
|
||||
../common/types.cpp
|
||||
../common/descriptor.cpp
|
||||
../common/ffs.cpp
|
||||
../common/nvram.cpp
|
||||
../common/nvramparser.cpp
|
||||
../common/ffsparser.cpp
|
||||
../common/ffsbuilder.cpp
|
||||
../common/ffsops.cpp
|
||||
../common/peimage.cpp
|
||||
../common/treeitem.cpp
|
||||
../common/treemodel.cpp
|
||||
../common/utility.cpp
|
||||
../common/LZMA/LzmaCompress.c
|
||||
../common/LZMA/LzmaDecompress.c
|
||||
../common/LZMA/SDK/C/LzFind.c
|
||||
../common/LZMA/SDK/C/LzmaDec.c
|
||||
../common/LZMA/SDK/C/LzmaEnc.c
|
||||
../common/Tiano/EfiTianoDecompress.c
|
||||
../common/Tiano/EfiTianoCompress.c
|
||||
../common/Tiano/EfiTianoCompressLegacy.c
|
||||
../common/ustring.cpp
|
||||
../common/sha256.c
|
||||
../common/bstrlib/bstrlib.c
|
||||
../common/bstrlib/bstrwrap.cpp
|
||||
)
|
||||
|
||||
SET(PROJECT_HEADERS
|
||||
uefipatch.h
|
||||
../common/guiddatabase.h
|
||||
../common/basetypes.h
|
||||
../common/descriptor.h
|
||||
../common/gbe.h
|
||||
../common/me.h
|
||||
../common/ffs.h
|
||||
../common/nvram.h
|
||||
../common/nvramparser.h
|
||||
../common/ffsparser.h
|
||||
../common/ffsbuilder.h
|
||||
../common/ffsops.h
|
||||
../common/peimage.h
|
||||
../common/types.h
|
||||
../common/treeitem.h
|
||||
../common/treemodel.h
|
||||
../common/utility.h
|
||||
../common/LZMA/LzmaDecompress.h
|
||||
../common/Tiano/EfiTianoDecompress.h
|
||||
../common/LZMA/LzmaCompress.h
|
||||
../common/Tiano/EfiTianoCompress.h
|
||||
../common/ubytearray.h
|
||||
../common/ustring.h
|
||||
../common/bootguard.h
|
||||
../common/sha256.h
|
||||
../common/filesystem.h
|
||||
../common/bstrlib/bstrlib.h
|
||||
../common/bstrlib/bstrwrap.h
|
||||
../version.h
|
||||
)
|
||||
|
||||
ADD_DEFINITIONS(-DU_ENABLE_NVRAM_PARSING_SUPPORT -DU_ENABLE_FIT_PARSING_SUPPORT -DU_ENABLE_GUID_DATABASE_SUPPORT)
|
||||
|
||||
ADD_EXECUTABLE(UEFIPatch ${PROJECT_SOURCES} ${PROJECT_HEADERS})
|
37
UEFIPatch/patches-misc.txt
Executable file
37
UEFIPatch/patches-misc.txt
Executable file
@ -0,0 +1,37 @@
|
||||
# Patch string format
|
||||
# FileGuid SectionType PatchType:FindPatternOrOffset:ReplacePattern
|
||||
# Please ensure that the latest symbol in patch string is space
|
||||
|
||||
# Possible section types:
|
||||
# PE32 image 10
|
||||
# Position-independent code 11
|
||||
# TE Image 12
|
||||
# DXE Dependency 13
|
||||
# Version information 14
|
||||
# User interface string 15
|
||||
# 16-bit code 16
|
||||
# Guided freeform 18
|
||||
# Raw data 19
|
||||
# PEI Dependency 1B
|
||||
# SMM Dependency 1C
|
||||
# Please do not try another section types, it can make the resulting image broken
|
||||
|
||||
# Possible patch types:
|
||||
# P - pattern-based, first parameter is a pattern to find, second - a pattern to replace
|
||||
# O - offset-based, first parameter is hexadecimal offset, second - a pattern to replace
|
||||
# Patterns can have . as "any possible value" symbol
|
||||
|
||||
#----------------------------------------------------------------------------------
|
||||
# Set IA32_FEATURE_CONTROL.SGX_LC
|
||||
#----------------------------------------------------------------------------------
|
||||
|
||||
# SiInit | Gemini Lake
|
||||
299D6F8B-2EC9-4E40-9EC6-DDAA7EBF5FD9 10 P:B93A0000000F320D00000400:B93A0000000F320D00000600
|
||||
|
||||
#----------------------------------------------------------------------------------
|
||||
# Broken EFI_SIMPLE_POINTER_PROTOCOL implementation patches
|
||||
# Fixes incorrect pointer position update/click condition on Z87 chips
|
||||
#----------------------------------------------------------------------------------
|
||||
|
||||
# UHCD | ASUS Z87-Pro
|
||||
580DD900-385D-11D7-883A-00500473D4EB 10 P:807A3200745C807A4000:807A32007506807A4000
|
59
UEFIPatch/patches.txt
Executable file
59
UEFIPatch/patches.txt
Executable file
@ -0,0 +1,59 @@
|
||||
# Patch string format
|
||||
# FileGuid SectionType PatchType:FindPatternOrOffset:ReplacePattern
|
||||
# Please ensure that the latest symbol in patch string is space
|
||||
|
||||
# Possible section types:
|
||||
# PE32 image 10
|
||||
# Position-independent code 11
|
||||
# TE Image 12
|
||||
# DXE Dependency 13
|
||||
# Version information 14
|
||||
# User interface string 15
|
||||
# 16-bit code 16
|
||||
# Guided freeform 18
|
||||
# Raw data 19
|
||||
# PEI Dependency 1B
|
||||
# SMM Dependency 1C
|
||||
# Please do not try another section types, it can make the resulting image broken
|
||||
|
||||
# Possible patch types:
|
||||
# P - pattern-based, first parameter is a pattern to find, second - a pattern to replace
|
||||
# O - offset-based, first parameter is hexadecimal offset, second - a pattern to replace
|
||||
# Patterns can have . as "any possible value" symbol
|
||||
|
||||
#----------------------------------------------------------------------------------
|
||||
# OSX CPU Power Management patches
|
||||
# Remove lock from MSR 0xE2 register
|
||||
#----------------------------------------------------------------------------------
|
||||
|
||||
# PowerMgmtDxe | Haswell
|
||||
F7731B4C-58A2-4DF4-8980-5645D39ECE58 10 P:75080FBAE80F89442430:EB080FBAE80F89442430
|
||||
|
||||
# PowerMgmtDxe | Haswell-E
|
||||
F7731B4C-58A2-4DF4-8980-5645D39ECE58 10 P:0FBA6C24380F:0FBA7424380F
|
||||
|
||||
# PowerManagement | Sandy Bridge with ME 8.xx, Ivy Bridge
|
||||
8C783970-F02A-4A4D-AF09-8797A51EEC8D 10 P:75080FBAE80F89442430:EB080FBAE80F89442430
|
||||
|
||||
# PowerManagement | New SB-E/IB-E
|
||||
8C783970-F02A-4A4D-AF09-8797A51EEC8D 10 P:0FBA6C24380F:0FBA7424380F
|
||||
|
||||
# CpuPei | Sandy Bridge with ME 7.xx, old SB-E/IB-E
|
||||
2BB5AFA9-FF33-417B-8497-CB773C2B93BF 10 P:800018EB050D0080:000018EB050D0000
|
||||
|
||||
# PpmInitialize | Broadwell-E
|
||||
3FFCAE95-23CF-4967-94F5-16352F68E43B 10 P:0FBA6C24400F:0FBA7424400F
|
||||
|
||||
# SiInit | Skylake
|
||||
299D6F8B-2EC9-4E40-9EC6-DDAA7EBF5FD9 10 P:75080D00800000:EB080D00800000
|
||||
299D6F8B-2EC9-4E40-9EC6-DDAA7EBF5FD9 12 P:75080D00800000:EB080D00800000
|
||||
|
||||
# SiInit | Kaby Lake
|
||||
299D6F8B-2EC9-4E40-9EC6-DDAA7EBF5FD9 10 P:81E10080000033C1:9090909090909090
|
||||
299D6F8B-2EC9-4E40-9EC6-DDAA7EBF5FD9 12 P:81E10080000033C1:9090909090909090
|
||||
|
||||
# PpmInitialize | Skylake-X
|
||||
3FFCAE95-23CF-4967-94F5-16352F68E43B 10 P:742CB9E2000000:752CB9E2000000
|
||||
|
||||
# CpuInitPei | Skylake-X
|
||||
01359D99-9446-456D-ADA4-50A711C03ADA 12 P:BE0080000023CE0B:BE0000000023CE0B
|
156
UEFIPatch/uefipatch.cpp
Executable file
156
UEFIPatch/uefipatch.cpp
Executable file
@ -0,0 +1,156 @@
|
||||
/* uefipatch.cpp
|
||||
|
||||
Copyright (c) 2018, LongSoft. 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()
|
||||
{
|
||||
model = new TreeModel();
|
||||
ffsParser = new FfsParser(model);
|
||||
ffsBuilder = new FfsBuilder(model, ffsParser);
|
||||
ffsOps = new FfsOperations(model);
|
||||
}
|
||||
|
||||
UEFIPatch::~UEFIPatch()
|
||||
{
|
||||
delete ffsOps;
|
||||
delete ffsBuilder;
|
||||
delete ffsParser;
|
||||
delete model;
|
||||
}
|
||||
|
||||
USTATUS UEFIPatch::patchFromFile(const UString & inPath, const UString & patches, const UString & outPath)
|
||||
{
|
||||
if (!isExistOnFs(patches))
|
||||
return U_INVALID_FILE;
|
||||
|
||||
std::ifstream patchesFile(patches.toLocal8Bit());
|
||||
if (!patchesFile)
|
||||
return U_INVALID_FILE;
|
||||
|
||||
UByteArray buffer;
|
||||
USTATUS result = readFileIntoArray(inPath, buffer);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
result = ffsParser->parse(buffer);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
UINT8 counter = 0;
|
||||
while (!patchesFile.eof()) {
|
||||
std::string line;
|
||||
std::getline(patchesFile, line);
|
||||
// Use sharp symbol as commentary
|
||||
if (line.size() == 0 || line[0] == '#')
|
||||
continue;
|
||||
|
||||
// Split the read line
|
||||
std::vector<UString> list;
|
||||
std::string::size_type prev = 0, curr = 0;
|
||||
while ((curr = line.find(' ', curr)) != std::string::npos) {
|
||||
std::string substring( line.substr(prev, curr-prev) );
|
||||
list.push_back(UString(substring.c_str()));
|
||||
prev = ++curr;
|
||||
}
|
||||
list.push_back(UString(line.substr(prev, curr-prev).c_str()));
|
||||
|
||||
if (list.size() < 3)
|
||||
continue;
|
||||
|
||||
EFI_GUID guid;
|
||||
const char *sectionTypeStr = list[1].toLocal8Bit();
|
||||
char *converted = const_cast<char *>(sectionTypeStr);
|
||||
UINT8 sectionType = (UINT8)std::strtol(sectionTypeStr, &converted, 16);
|
||||
if (converted == sectionTypeStr || !ustringToGuid(list[0], guid))
|
||||
return U_INVALID_PARAMETER;
|
||||
|
||||
std::vector<PatchData> patches;
|
||||
|
||||
for (size_t i = 2; i < list.size(); i++) {
|
||||
std::vector<UByteArray> patchList;
|
||||
std::string patchStr = list.at(i).toLocal8Bit();
|
||||
std::string::size_type prev = 0, curr = 0;
|
||||
while ((curr = line.find(':', curr)) != std::string::npos) {
|
||||
std::string substring( line.substr(prev, curr-prev) );
|
||||
patchList.push_back(UByteArray(substring));
|
||||
prev = ++curr;
|
||||
}
|
||||
patchList.push_back(UByteArray(line.substr(prev, curr-prev)));
|
||||
|
||||
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.push_back(patch);
|
||||
}
|
||||
else if (patch.type == PATCH_TYPE_OFFSET) {
|
||||
patch.offset = patchList.at(1).toUInt(NULL, 16);
|
||||
patch.hexReplacePattern = patchList.at(2);
|
||||
patches.push_back(patch);
|
||||
}
|
||||
else {
|
||||
// Ignore unknown patch type
|
||||
continue;
|
||||
}
|
||||
}
|
||||
result = patchFile(model->index(0, 0), UByteArray((const char*)&guid, sizeof(EFI_GUID)), sectionType, patches);
|
||||
if (result && result != U_NOTHING_TO_PATCH)
|
||||
return result;
|
||||
counter++;
|
||||
}
|
||||
|
||||
UByteArray reconstructed;
|
||||
result = ffsBuilder->build(model->index(0,0), reconstructed);
|
||||
if (result)
|
||||
return result;
|
||||
if (reconstructed == buffer)
|
||||
return U_NOTHING_TO_PATCH;
|
||||
|
||||
std::ofstream outputFile;
|
||||
outputFile.open(outPath.toLocal8Bit(), std::ios::out | std::ios::binary);
|
||||
outputFile.write(reconstructed.constData(), reconstructed.size());
|
||||
outputFile.close();
|
||||
|
||||
return U_SUCCESS;
|
||||
}
|
||||
|
||||
USTATUS UEFIPatch::patchFile(const UModelIndex & index, const UByteArray & fileGuid, const UINT8 sectionType, const std::vector<PatchData> & patches)
|
||||
{
|
||||
if (!model || !index.isValid())
|
||||
return U_INVALID_PARAMETER;
|
||||
if (model->type(index) == Types::Section && model->subtype(index) == sectionType) {
|
||||
UModelIndex fileIndex = model->findParentOfType(index, Types::File);
|
||||
if (model->type(fileIndex) == Types::File &&
|
||||
model->header(fileIndex).left(sizeof(EFI_GUID)) == fileGuid)
|
||||
{
|
||||
// return ffsOps->patch(index, patches);
|
||||
#warning "ffsOps->patch is not implemented!"
|
||||
return U_NOTHING_TO_PATCH;
|
||||
}
|
||||
}
|
||||
|
||||
if (model->rowCount(index) > 0) {
|
||||
for (int i = 0; i < model->rowCount(index); i++) {
|
||||
USTATUS result = patchFile(index.child(i, 0), fileGuid, sectionType, patches);
|
||||
if (!result)
|
||||
break;
|
||||
else if (result != U_NOTHING_TO_PATCH)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return U_NOTHING_TO_PATCH;
|
||||
}
|
52
UEFIPatch/uefipatch.h
Executable file
52
UEFIPatch/uefipatch.h
Executable file
@ -0,0 +1,52 @@
|
||||
/* uefipatch.h
|
||||
|
||||
Copyright (c) 2018, LongSoft. 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 <iterator>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include "../common/basetypes.h"
|
||||
#include "../common/ustring.h"
|
||||
#include "../common/filesystem.h"
|
||||
#include "../common/ffs.h"
|
||||
#include "../common/ffsparser.h"
|
||||
#include "../common/ffsops.h"
|
||||
#include "../common/ffsbuilder.h"
|
||||
#include "../common/utility.h"
|
||||
|
||||
struct PatchData {
|
||||
UINT8 type;
|
||||
UINT32 offset;
|
||||
UByteArray hexFindPattern;
|
||||
UByteArray hexReplacePattern;
|
||||
};
|
||||
|
||||
class UEFIPatch
|
||||
{
|
||||
public:
|
||||
explicit UEFIPatch();
|
||||
~UEFIPatch();
|
||||
|
||||
USTATUS patchFromFile(const UString & inPath, const UString & patches, const UString & outPath);
|
||||
private:
|
||||
USTATUS patchFile(const UModelIndex & index, const UByteArray & fileGuid, const UINT8 sectionType, const std::vector<PatchData> & patches);
|
||||
TreeModel* model;
|
||||
FfsParser* ffsParser;
|
||||
FfsBuilder* ffsBuilder;
|
||||
FfsOperations* ffsOps;
|
||||
};
|
||||
|
||||
#endif
|
90
UEFIPatch/uefipatch_main.cpp
Executable file
90
UEFIPatch/uefipatch_main.cpp
Executable file
@ -0,0 +1,90 @@
|
||||
/* uefipatch_main.cpp
|
||||
|
||||
Copyright (c) 2018, LongSoft. 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 <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include "../version.h"
|
||||
#include "uefipatch.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
UEFIPatch w;
|
||||
USTATUS result = U_SUCCESS;
|
||||
UINT32 argumentsCount = argc;
|
||||
|
||||
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 <<
|
||||
"Patches will be read from patches.txt file by default\n";
|
||||
return U_SUCCESS;
|
||||
}
|
||||
|
||||
UString inputPath = argv[1];
|
||||
UString patches = "patches.txt";
|
||||
UString outputPath = inputPath + ".patched";
|
||||
for (UINT32 i = 2; i < argumentsCount; i++) {
|
||||
if ((!std::strcmp(argv[i], "-o") || !std::strcmp(argv[i], "--output")) && i + 1 < argumentsCount) {
|
||||
outputPath = argv[i+1];
|
||||
i++;
|
||||
} else if (patches == UString("patches.txt")) {
|
||||
patches = argv[i];
|
||||
} else {
|
||||
result = U_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
if (result == U_SUCCESS) {
|
||||
result = w.patchFromFile(inputPath, patches, outputPath);
|
||||
}
|
||||
|
||||
switch (result) {
|
||||
case U_SUCCESS:
|
||||
std::cout << "Image patched" << std::endl;
|
||||
break;
|
||||
case U_INVALID_PARAMETER:
|
||||
std::cout << "Function called with invalid parameter" << std::endl;
|
||||
break;
|
||||
case U_NOTHING_TO_PATCH:
|
||||
std::cout << "No patches can be applied to input file" << std::endl;
|
||||
break;
|
||||
case U_UNKNOWN_PATCH_TYPE:
|
||||
std::cout << "Unknown patch type" << std::endl;
|
||||
break;
|
||||
case U_PATCH_OFFSET_OUT_OF_BOUNDS:
|
||||
std::cout << "Patch offset out of bounds" << std::endl;
|
||||
break;
|
||||
case U_INVALID_SYMBOL:
|
||||
std::cout << "Pattern format mismatch" << std::endl;
|
||||
break;
|
||||
case U_INVALID_FILE:
|
||||
std::cout << patches.toLocal8Bit() << " file not found or can't be read" << std::endl;
|
||||
break;
|
||||
case U_FILE_OPEN:
|
||||
std::cout << "Input file not found" << std::endl;
|
||||
break;
|
||||
case U_FILE_READ:
|
||||
std::cout << "Input file can't be read" << std::endl;
|
||||
break;
|
||||
case U_FILE_WRITE:
|
||||
std::cout << "Output file can't be written" << std::endl;
|
||||
break;
|
||||
default:
|
||||
std::cout << "Error " << result << std::endl;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
@ -71,6 +71,9 @@ typedef size_t USTATUS;
|
||||
#define U_INVALID_STORE_SIZE 49
|
||||
#define U_UNKNOWN_COMPRESSION_ALGORITHM 50
|
||||
#define U_NOTHING_TO_PATCH 51
|
||||
#define U_UNKNOWN_PATCH_TYPE 52
|
||||
#define U_PATCH_OFFSET_OUT_OF_BOUNDS 53
|
||||
#define U_INVALID_SYMBOL 54
|
||||
#define U_NOT_IMPLEMENTED 0xFF
|
||||
|
||||
// UDK porting definitions
|
||||
|
Loading…
Reference in New Issue
Block a user