mirror of
https://github.com/LongSoft/UEFITool.git
synced 2024-11-22 16:08:23 +08:00
UEFIPatch 0.2.0 / UEFITool 0.18.0
- updated EFI11/Tiano compression and decompression code to UDK2014 versions - UEFIPatch rewritten to support offset-based patches and patterns with placeholder symbols
This commit is contained in:
parent
a3854ad059
commit
c23aef47be
File diff suppressed because it is too large
Load Diff
@ -1,13 +1,14 @@
|
|||||||
/* EFI/Tiano Compress Header
|
/* EfiTianoCompress.h
|
||||||
|
|
||||||
Copyright (c) 2004 - 2008, Intel Corporation. All rights reserved.
|
Copyright (c) 2014, Nikolaj Schlej. All rights reserved.<BR>
|
||||||
|
Copyright (c) 2004 - 2008, Intel Corporation. All rights reserved.<BR>
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
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
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
http://opensource.org/licenses/bsd-license.php
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
Module Name:
|
Module Name:
|
||||||
|
|
||||||
@ -54,12 +55,12 @@ Returns:
|
|||||||
EFI_INVALID_PARAMETER - Parameter supplied is wrong.
|
EFI_INVALID_PARAMETER - Parameter supplied is wrong.
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
INT32
|
UINT8
|
||||||
TianoCompress (
|
TianoCompress (
|
||||||
UINT8 *SrcBuffer,
|
CONST VOID *SrcBuffer,
|
||||||
UINT32 SrcSize,
|
CONST UINT64 SrcSize,
|
||||||
UINT8 *DstBuffer,
|
VOID *DstBuffer,
|
||||||
UINT32 *DstSize
|
UINT64 *DstSize
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -86,12 +87,12 @@ Returns:
|
|||||||
EFI_INVALID_PARAMETER - Parameter supplied is wrong.
|
EFI_INVALID_PARAMETER - Parameter supplied is wrong.
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
INT32
|
UINT8
|
||||||
EfiCompress (
|
EfiCompress (
|
||||||
UINT8 *SrcBuffer,
|
CONST VOID *SrcBuffer,
|
||||||
UINT32 SrcSize,
|
CONST UINT64 SrcSize,
|
||||||
UINT8 *DstBuffer,
|
VOID *DstBuffer,
|
||||||
UINT32 *DstSize
|
UINT64 *DstSize
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*++
|
/*++ EfiTianoDecompress.c
|
||||||
|
|
||||||
Copyright (c) 2004 - 2006, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2014, Nikolaj Schlej. All rights reserved.<BR>
|
||||||
|
Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
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
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
@ -28,7 +29,9 @@ Decompressor. Algorithm Ported from OPSD code (Decomp.asm)
|
|||||||
#define MAXMATCH 256
|
#define MAXMATCH 256
|
||||||
#define THRESHOLD 3
|
#define THRESHOLD 3
|
||||||
#define CODE_BIT 16
|
#define CODE_BIT 16
|
||||||
//#define UINT8_MAX 0xff
|
#ifndef UINT8_MAX
|
||||||
|
#define UINT8_MAX 0xff
|
||||||
|
#endif
|
||||||
#define BAD_TABLE - 1
|
#define BAD_TABLE - 1
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -69,7 +72,7 @@ UINT16 mCTable[4096];
|
|||||||
UINT16 mPTTable[256];
|
UINT16 mPTTable[256];
|
||||||
|
|
||||||
//
|
//
|
||||||
// The length of the field 'Position Set Code Length Array Size'Block Header.
|
// The length of the field 'Position Set Code Length Array Size' in Block Header.
|
||||||
// For EFI 1.1 de/compression algorithm, mPBit = 4
|
// For EFI 1.1 de/compression algorithm, mPBit = 4
|
||||||
// For Tiano de/compression algorithm, mPBit = 5
|
// For Tiano de/compression algorithm, mPBit = 5
|
||||||
//
|
//
|
||||||
@ -79,14 +82,14 @@ UINT8 mPBit;
|
|||||||
STATIC
|
STATIC
|
||||||
VOID
|
VOID
|
||||||
FillBuf(
|
FillBuf(
|
||||||
SCRATCH_DATA *Sd,
|
IN SCRATCH_DATA *Sd,
|
||||||
UINT16 NumOfBits
|
IN UINT16 NumOfBits
|
||||||
)
|
)
|
||||||
/*++
|
/*++
|
||||||
|
|
||||||
Routine Description:
|
Routine Description:
|
||||||
|
|
||||||
Shift mBitBuf NumOfBits left. ReadNumOfBits of bits from source.
|
Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
|
|
||||||
@ -112,7 +115,8 @@ while (NumOfBits > Sd->mBitCount) {
|
|||||||
Sd->mSubBitBuf = Sd->mSrcBase[Sd->mInBuf++];
|
Sd->mSubBitBuf = Sd->mSrcBase[Sd->mInBuf++];
|
||||||
Sd->mBitCount = 8;
|
Sd->mBitCount = 8;
|
||||||
|
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
//
|
//
|
||||||
// No more bits from the source, just pad zero bit.
|
// No more bits from the source, just pad zero bit.
|
||||||
//
|
//
|
||||||
@ -129,16 +133,16 @@ Sd->mBitBuf |= Sd->mSubBitBuf >> Sd->mBitCount;
|
|||||||
STATIC
|
STATIC
|
||||||
UINT32
|
UINT32
|
||||||
GetBits(
|
GetBits(
|
||||||
SCRATCH_DATA *Sd,
|
IN SCRATCH_DATA *Sd,
|
||||||
UINT16 NumOfBits
|
IN UINT16 NumOfBits
|
||||||
)
|
)
|
||||||
/*++
|
/*++
|
||||||
|
|
||||||
Routine Description:
|
Routine Description:
|
||||||
|
|
||||||
Get NumOfBits of bits from mBitBuf. Fill mBitBuf with subsequent
|
Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent
|
||||||
NumOfBits of bits from source. Returns NumOfBits of bits that are
|
NumOfBits of bits from source. Returns NumOfBits of bits that are
|
||||||
popped.
|
popped out.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
|
|
||||||
@ -147,27 +151,27 @@ NumOfBits - The number of bits to pop and read.
|
|||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
The bits that are popped.
|
The bits that are popped out.
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
{
|
{
|
||||||
UINT32 Bits;
|
UINT32 OutBits;
|
||||||
|
|
||||||
Bits = (UINT32) (Sd->mBitBuf >> (BITBUFSIZ - NumOfBits));
|
OutBits = (UINT32)(Sd->mBitBuf >> (BITBUFSIZ - NumOfBits));
|
||||||
|
|
||||||
FillBuf(Sd, NumOfBits);
|
FillBuf(Sd, NumOfBits);
|
||||||
|
|
||||||
return Bits;
|
return OutBits;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC
|
STATIC
|
||||||
UINT16
|
UINT16
|
||||||
MakeTable(
|
MakeTable(
|
||||||
SCRATCH_DATA *Sd,
|
IN SCRATCH_DATA *Sd,
|
||||||
UINT16 NumOfChar,
|
IN UINT16 NumOfChar,
|
||||||
UINT8 *BitLen,
|
IN UINT8 *BitLen,
|
||||||
UINT16 TableBits,
|
IN UINT16 TableBits,
|
||||||
UINT16 *Table
|
OUT UINT16 *Table
|
||||||
)
|
)
|
||||||
/*++
|
/*++
|
||||||
|
|
||||||
@ -203,14 +207,33 @@ UINT16 Avail;
|
|||||||
UINT16 NextCode;
|
UINT16 NextCode;
|
||||||
UINT16 Mask;
|
UINT16 Mask;
|
||||||
|
|
||||||
for (Index = 1; Index <= 16; Index++) {
|
//
|
||||||
|
// TableBits should not be greater than 16.
|
||||||
|
//
|
||||||
|
if (TableBits >= (sizeof(Count) / sizeof(UINT16))) {
|
||||||
|
return (UINT16)BAD_TABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Initialize Count array starting from Index 0, as there is a possibility of Count array being uninitialized.
|
||||||
|
//
|
||||||
|
for (Index = 0; Index <= 16; Index++) {
|
||||||
Count[Index] = 0;
|
Count[Index] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Index = 0; Index < NumOfChar; Index++) {
|
for (Index = 0; Index < NumOfChar; Index++) {
|
||||||
|
//
|
||||||
|
// Count array index should not be greater than or equal to its size.
|
||||||
|
//
|
||||||
|
if (BitLen[Index] < (sizeof(Count) / sizeof(UINT16))) {
|
||||||
Count[BitLen[Index]]++;
|
Count[BitLen[Index]]++;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
return (UINT16)BAD_TABLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Start[0] = 0;
|
||||||
Start[1] = 0;
|
Start[1] = 0;
|
||||||
|
|
||||||
for (Index = 1; Index <= 16; Index++) {
|
for (Index = 1; Index <= 16; Index++) {
|
||||||
@ -249,7 +272,7 @@ Mask = (UINT16) (1U << (15 - TableBits));
|
|||||||
for (Char = 0; Char < NumOfChar; Char++) {
|
for (Char = 0; Char < NumOfChar; Char++) {
|
||||||
|
|
||||||
Len = BitLen[Char];
|
Len = BitLen[Char];
|
||||||
if (Len == 0) {
|
if (Len == 0 || Len >= 17) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,25 +284,32 @@ for (Char = 0; Char < NumOfChar; Char++) {
|
|||||||
// Check to prevent possible heap corruption
|
// Check to prevent possible heap corruption
|
||||||
if (Index >= (UINT16)(1U << TableBits))
|
if (Index >= (UINT16)(1U << TableBits))
|
||||||
return (UINT16)BAD_TABLE;
|
return (UINT16)BAD_TABLE;
|
||||||
|
|
||||||
Table[Index] = Char;
|
Table[Index] = Char;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
Index3 = Start[Len];
|
Index3 = Start[Len];
|
||||||
Pointer = &Table[Index3 >> JuBits];
|
Pointer = &Table[Index3 >> JuBits];
|
||||||
Index = (UINT16)(Len - TableBits);
|
Index = (UINT16)(Len - TableBits);
|
||||||
|
|
||||||
while (Index != 0) {
|
while (Index != 0) {
|
||||||
if (*Pointer == 0) {
|
//
|
||||||
|
// Avail should be lesser than size of mRight and mLeft to prevent buffer overflow.
|
||||||
|
//
|
||||||
|
if ((*Pointer == 0) && (Avail < sizeof(Sd->mRight) / sizeof(UINT16)) && (Avail < sizeof(Sd->mLeft) / sizeof(UINT16))) {
|
||||||
Sd->mRight[Avail] = Sd->mLeft[Avail] = 0;
|
Sd->mRight[Avail] = Sd->mLeft[Avail] = 0;
|
||||||
*Pointer = Avail++;
|
*Pointer = Avail++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Index3 & Mask) {
|
//
|
||||||
|
// *Pointer should be lesser than size of mRight and mLeft to prevent buffer overflow.
|
||||||
|
//
|
||||||
|
if ((Index3 & Mask) && (*Pointer < (sizeof(Sd->mRight) / sizeof(UINT16)))) {
|
||||||
Pointer = &Sd->mRight[*Pointer];
|
Pointer = &Sd->mRight[*Pointer];
|
||||||
} else {
|
}
|
||||||
|
else if (*Pointer < (sizeof(Sd->mLeft) / sizeof(UINT16))) {
|
||||||
Pointer = &Sd->mLeft[*Pointer];
|
Pointer = &Sd->mLeft[*Pointer];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,7 +332,7 @@ return 0;
|
|||||||
STATIC
|
STATIC
|
||||||
UINT32
|
UINT32
|
||||||
DecodeP(
|
DecodeP(
|
||||||
SCRATCH_DATA *Sd
|
IN SCRATCH_DATA *Sd
|
||||||
)
|
)
|
||||||
/*++
|
/*++
|
||||||
|
|
||||||
@ -333,7 +363,8 @@ if (Val >= MAXNP) {
|
|||||||
|
|
||||||
if (Sd->mBitBuf & Mask) {
|
if (Sd->mBitBuf & Mask) {
|
||||||
Val = Sd->mRight[Val];
|
Val = Sd->mRight[Val];
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
Val = Sd->mLeft[Val];
|
Val = Sd->mLeft[Val];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,10 +387,10 @@ return Pos;
|
|||||||
STATIC
|
STATIC
|
||||||
UINT16
|
UINT16
|
||||||
ReadPTLen(
|
ReadPTLen(
|
||||||
SCRATCH_DATA *Sd,
|
IN SCRATCH_DATA *Sd,
|
||||||
UINT16 nn,
|
IN UINT16 nn,
|
||||||
UINT16 nbit,
|
IN UINT16 nbit,
|
||||||
UINT16 Special
|
IN UINT16 Special
|
||||||
)
|
)
|
||||||
/*++
|
/*++
|
||||||
|
|
||||||
@ -388,6 +419,13 @@ UINT32 Mask;
|
|||||||
|
|
||||||
Number = (UINT16)GetBits(Sd, nbit);
|
Number = (UINT16)GetBits(Sd, nbit);
|
||||||
|
|
||||||
|
if ((Number > sizeof(Sd->mPTLen)) || (nn > sizeof(Sd->mPTLen))) {
|
||||||
|
//
|
||||||
|
// Fail if Number or nn is greater than size of mPTLen
|
||||||
|
//
|
||||||
|
return (UINT16)BAD_TABLE;
|
||||||
|
}
|
||||||
|
|
||||||
if (Number == 0) {
|
if (Number == 0) {
|
||||||
CharC = (UINT16)GetBits(Sd, nbit);
|
CharC = (UINT16)GetBits(Sd, nbit);
|
||||||
|
|
||||||
@ -423,6 +461,12 @@ while (Index < Number) {
|
|||||||
if (Index == Special) {
|
if (Index == Special) {
|
||||||
CharC = (UINT16)GetBits(Sd, 2);
|
CharC = (UINT16)GetBits(Sd, 2);
|
||||||
while ((INT16)(--CharC) >= 0) {
|
while ((INT16)(--CharC) >= 0) {
|
||||||
|
if (Index >= sizeof(Sd->mPTLen)) {
|
||||||
|
//
|
||||||
|
// Fail if Index is greater than or equal to mPTLen
|
||||||
|
//
|
||||||
|
return (UINT16)BAD_TABLE;
|
||||||
|
}
|
||||||
Sd->mPTLen[Index++] = 0;
|
Sd->mPTLen[Index++] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -486,7 +530,8 @@ while (Index < Number) {
|
|||||||
|
|
||||||
if (Mask & Sd->mBitBuf) {
|
if (Mask & Sd->mBitBuf) {
|
||||||
CharC = Sd->mRight[CharC];
|
CharC = Sd->mRight[CharC];
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
CharC = Sd->mLeft[CharC];
|
CharC = Sd->mLeft[CharC];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -503,9 +548,11 @@ while (Index < Number) {
|
|||||||
|
|
||||||
if (CharC == 0) {
|
if (CharC == 0) {
|
||||||
CharC = 1;
|
CharC = 1;
|
||||||
} else if (CharC == 1) {
|
}
|
||||||
|
else if (CharC == 1) {
|
||||||
CharC = (UINT16)(GetBits(Sd, 4) + 3);
|
CharC = (UINT16)(GetBits(Sd, 4) + 3);
|
||||||
} else if (CharC == 2) {
|
}
|
||||||
|
else if (CharC == 2) {
|
||||||
CharC = (UINT16)(GetBits(Sd, CBIT) + 20);
|
CharC = (UINT16)(GetBits(Sd, CBIT) + 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -513,7 +560,8 @@ while (Index < Number) {
|
|||||||
Sd->mCLen[Index++] = 0;
|
Sd->mCLen[Index++] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
Sd->mCLen[Index++] = (UINT8)(CharC - 2);
|
Sd->mCLen[Index++] = (UINT8)(CharC - 2);
|
||||||
|
|
||||||
@ -580,7 +628,8 @@ if (Index2 >= NC) {
|
|||||||
do {
|
do {
|
||||||
if (Sd->mBitBuf & Mask) {
|
if (Sd->mBitBuf & Mask) {
|
||||||
Index2 = Sd->mRight[Index2];
|
Index2 = Sd->mRight[Index2];
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
Index2 = Sd->mLeft[Index2];
|
Index2 = Sd->mLeft[Index2];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -634,11 +683,13 @@ for (;;) {
|
|||||||
//
|
//
|
||||||
if (Sd->mOutBuf >= Sd->mOrigSize) {
|
if (Sd->mOutBuf >= Sd->mOrigSize) {
|
||||||
return;
|
return;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
Sd->mDstBase[Sd->mOutBuf++] = (UINT8)CharC;
|
Sd->mDstBase[Sd->mOutBuf++] = (UINT8)CharC;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
//
|
//
|
||||||
// Process a Pointer
|
// Process a Pointer
|
||||||
//
|
//
|
||||||
@ -647,10 +698,6 @@ for (;;) {
|
|||||||
BytesRemain = CharC;
|
BytesRemain = CharC;
|
||||||
|
|
||||||
DataIdx = Sd->mOutBuf - DecodeP(Sd) - 1;
|
DataIdx = Sd->mOutBuf - DecodeP(Sd) - 1;
|
||||||
if (DataIdx >= Sd->mOrigSize) {
|
|
||||||
Sd->mBadTableFlag = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
BytesRemain--;
|
BytesRemain--;
|
||||||
while ((INT16)(BytesRemain) >= 0) {
|
while ((INT16)(BytesRemain) >= 0) {
|
||||||
@ -663,16 +710,14 @@ for (;;) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT32
|
EFI_STATUS
|
||||||
EfiTianoGetInfo (
|
GetInfo(
|
||||||
VOID *Source,
|
IN VOID *Source,
|
||||||
UINT32 SrcSize,
|
IN UINT32 SrcSize,
|
||||||
UINT32 *DstSize,
|
OUT UINT32 *DstSize,
|
||||||
UINT32 *ScratchSize
|
OUT UINT32 *ScratchSize
|
||||||
)
|
)
|
||||||
/*++
|
/*++
|
||||||
|
|
||||||
@ -689,7 +734,7 @@ ScratchSize - The size of scratch buffer.
|
|||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successfully retrieved.
|
EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved.
|
||||||
EFI_INVALID_PARAMETER - The source data is corrupted
|
EFI_INVALID_PARAMETER - The source data is corrupted
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
@ -700,22 +745,22 @@ UINT8 *Src;
|
|||||||
|
|
||||||
Src = Source;
|
Src = Source;
|
||||||
if (SrcSize < 8) {
|
if (SrcSize < 8) {
|
||||||
return ERR_INVALID_PARAMETER;
|
return EFI_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
*DstSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24);
|
*DstSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24);
|
||||||
return ERR_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT32
|
EFI_STATUS
|
||||||
Decompress(
|
Decompress(
|
||||||
VOID *Source,
|
IN VOID *Source,
|
||||||
UINT32 SrcSize,
|
IN UINT32 SrcSize,
|
||||||
VOID *Destination,
|
IN OUT VOID *Destination,
|
||||||
UINT32 DstSize,
|
IN UINT32 DstSize,
|
||||||
VOID *Scratch,
|
IN OUT VOID *Scratch,
|
||||||
UINT32 ScratchSize,
|
IN UINT32 ScratchSize,
|
||||||
UINT8 Version
|
IN UINT8 Version
|
||||||
)
|
)
|
||||||
/*++
|
/*++
|
||||||
|
|
||||||
@ -745,23 +790,23 @@ EFI_INVALID_PARAMETER - The source data is corrupted
|
|||||||
UINT32 Index;
|
UINT32 Index;
|
||||||
UINT32 CompSize;
|
UINT32 CompSize;
|
||||||
UINT32 OrigSize;
|
UINT32 OrigSize;
|
||||||
UINT32 Status;
|
EFI_STATUS Status;
|
||||||
SCRATCH_DATA *Sd;
|
SCRATCH_DATA *Sd;
|
||||||
UINT8 *Src;
|
UINT8 *Src;
|
||||||
UINT8 *Dst;
|
UINT8 *Dst;
|
||||||
|
|
||||||
Status = ERR_SUCCESS;
|
Status = EFI_SUCCESS;
|
||||||
Src = Source;
|
Src = Source;
|
||||||
Dst = Destination;
|
Dst = Destination;
|
||||||
|
|
||||||
if (ScratchSize < sizeof(SCRATCH_DATA)) {
|
if (ScratchSize < sizeof(SCRATCH_DATA)) {
|
||||||
return ERR_INVALID_PARAMETER;
|
return EFI_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
Sd = (SCRATCH_DATA *)Scratch;
|
Sd = (SCRATCH_DATA *)Scratch;
|
||||||
|
|
||||||
if (SrcSize < 8) {
|
if (SrcSize < 8) {
|
||||||
return ERR_INVALID_PARAMETER;
|
return EFI_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24);
|
CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24);
|
||||||
@ -775,11 +820,11 @@ if (OrigSize == 0) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (SrcSize < CompSize + 8) {
|
if (SrcSize < CompSize + 8) {
|
||||||
return ERR_INVALID_PARAMETER;
|
return EFI_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DstSize != OrigSize) {
|
if (DstSize != OrigSize) {
|
||||||
return ERR_INVALID_PARAMETER;
|
return EFI_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
Src = Src + 8;
|
Src = Src + 8;
|
||||||
@ -788,7 +833,7 @@ for (Index = 0; Index < sizeof (SCRATCH_DATA); Index++) {
|
|||||||
((UINT8 *)Sd)[Index] = 0;
|
((UINT8 *)Sd)[Index] = 0;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// The length of the field 'Position Set Code Length Array Size'Block Header.
|
// The length of the field 'Position Set Code Length Array Size' in Block Header.
|
||||||
// For EFI 1.1 de/compression algorithm(Version 1), mPBit = 4
|
// For EFI 1.1 de/compression algorithm(Version 1), mPBit = 4
|
||||||
// For Tiano de/compression algorithm(Version 2), mPBit = 5
|
// For Tiano de/compression algorithm(Version 2), mPBit = 5
|
||||||
//
|
//
|
||||||
@ -805,7 +850,7 @@ default:
|
|||||||
//
|
//
|
||||||
// Currently, only have 2 versions
|
// Currently, only have 2 versions
|
||||||
//
|
//
|
||||||
return ERR_INVALID_PARAMETER;
|
return EFI_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
Sd->mSrcBase = Src;
|
Sd->mSrcBase = Src;
|
||||||
@ -827,27 +872,64 @@ if (Sd->mBadTableFlag != 0) {
|
|||||||
//
|
//
|
||||||
// Something wrong with the source
|
// Something wrong with the source
|
||||||
//
|
//
|
||||||
Status = ERR_INVALID_PARAMETER;
|
Status = EFI_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT32
|
EFI_STATUS
|
||||||
EFIAPI
|
EFIAPI
|
||||||
EfiDecompress (
|
EfiTianoGetInfo(
|
||||||
VOID *Source,
|
IN VOID *Source,
|
||||||
UINT32 SrcSize,
|
IN UINT32 SrcSize,
|
||||||
VOID *Destination,
|
OUT UINT32 *DstSize,
|
||||||
UINT32 DstSize,
|
OUT UINT32 *ScratchSize
|
||||||
VOID *Scratch,
|
|
||||||
UINT32 ScratchSize
|
|
||||||
)
|
)
|
||||||
/*++
|
/*++
|
||||||
|
|
||||||
Routine Description:
|
Routine Description:
|
||||||
|
|
||||||
The implementation is same as that of EFI_DECOMPRESS_PROTOCOL.Decompress().
|
The implementation of EFI_DECOMPRESS_PROTOCOL.GetInfo().
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
This - The protocol instance pointer
|
||||||
|
Source - The source buffer containing the compressed data.
|
||||||
|
SrcSize - The size of source buffer
|
||||||
|
DstSize - The size of destination buffer.
|
||||||
|
ScratchSize - The size of scratch buffer.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successful retrieved.
|
||||||
|
EFI_INVALID_PARAMETER - The source data is corrupted
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
return GetInfo(
|
||||||
|
Source,
|
||||||
|
SrcSize,
|
||||||
|
DstSize,
|
||||||
|
ScratchSize
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
EfiDecompress(
|
||||||
|
IN VOID *Source,
|
||||||
|
IN UINT32 SrcSize,
|
||||||
|
IN OUT VOID *Destination,
|
||||||
|
IN UINT32 DstSize,
|
||||||
|
IN OUT VOID *Scratch,
|
||||||
|
IN UINT32 ScratchSize
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
The implementation of EFI_DECOMPRESS_PROTOCOL.Decompress().
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
|
|
||||||
@ -880,21 +962,21 @@ return Decompress (
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT32
|
EFI_STATUS
|
||||||
EFIAPI
|
EFIAPI
|
||||||
TianoDecompress(
|
TianoDecompress(
|
||||||
VOID *Source,
|
IN VOID *Source,
|
||||||
UINT32 SrcSize,
|
IN UINT32 SrcSize,
|
||||||
VOID *Destination,
|
IN OUT VOID *Destination,
|
||||||
UINT32 DstSize,
|
IN UINT32 DstSize,
|
||||||
VOID *Scratch,
|
IN OUT VOID *Scratch,
|
||||||
UINT32 ScratchSize
|
IN UINT32 ScratchSize
|
||||||
)
|
)
|
||||||
/*++
|
/*++
|
||||||
|
|
||||||
Routine Description:
|
Routine Description:
|
||||||
|
|
||||||
The implementation is same as that of EFI_TIANO_DECOMPRESS_PROTOCOL.Decompress().
|
The implementation of EFI_TIANO_DECOMPRESS_PROTOCOL.Decompress().
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
|
|
||||||
@ -926,4 +1008,3 @@ return Decompress (
|
|||||||
2
|
2
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*++
|
/* EfiTianoDecompress.h
|
||||||
|
|
||||||
Copyright (c) 2004 - 2006, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2014, Nikolaj Schlej. All rights reserved.<BR>
|
||||||
|
Copyright (c) 2004 - 2008, Intel Corporation. All rights reserved.<BR>
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
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
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
@ -30,12 +31,13 @@ Providing both EFI and Tiano decompress algorithms.
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
UINT32 CompSize;
|
UINT32 CompSize;
|
||||||
UINT32 OrigSize;
|
UINT32 OrigSize;
|
||||||
} EFI_TIANO_HEADER;
|
} EFI_TIANO_HEADER;
|
||||||
|
|
||||||
UINT32
|
EFI_STATUS
|
||||||
EFIAPI
|
EFIAPI
|
||||||
EfiTianoGetInfo (
|
EfiTianoGetInfo (
|
||||||
VOID *Source,
|
VOID *Source,
|
||||||
@ -65,7 +67,7 @@ EFI_INVALID_PARAMETER - The source data is corrupted
|
|||||||
--*/
|
--*/
|
||||||
;
|
;
|
||||||
|
|
||||||
UINT32
|
EFI_STATUS
|
||||||
EFIAPI
|
EFIAPI
|
||||||
EfiDecompress (
|
EfiDecompress (
|
||||||
VOID *Source,
|
VOID *Source,
|
||||||
@ -99,7 +101,7 @@ EFI_INVALID_PARAMETER - The source data is corrupted
|
|||||||
--*/
|
--*/
|
||||||
;
|
;
|
||||||
|
|
||||||
UINT32
|
EFI_STATUS
|
||||||
EFIAPI
|
EFIAPI
|
||||||
TianoDecompress (
|
TianoDecompress (
|
||||||
VOID *Source,
|
VOID *Source,
|
||||||
|
@ -56,6 +56,7 @@ UINT8 UEFIPatch::patchFromFile(QString path)
|
|||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
UINT8 counter = 0;
|
||||||
while (!file.atEnd()) {
|
while (!file.atEnd()) {
|
||||||
QByteArray line = file.readLine();
|
QByteArray line = file.readLine();
|
||||||
// Use sharp sign as commentary
|
// Use sharp sign as commentary
|
||||||
@ -68,98 +69,81 @@ UINT8 UEFIPatch::patchFromFile(QString path)
|
|||||||
|
|
||||||
QUuid uuid = QUuid(list.at(0));
|
QUuid uuid = QUuid(list.at(0));
|
||||||
QByteArray guid = QByteArray::fromRawData((const char*)&uuid.data1, sizeof(EFI_GUID));
|
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)));
|
bool converted;
|
||||||
if (result)
|
UINT8 sectionType = (UINT8)list.at(1).toUShort(&converted, 16);
|
||||||
return result;
|
if (!converted)
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
return ERR_INVALID_PARAMETER;
|
||||||
|
|
||||||
if (model->type(index) == Types::File && model->header(index).left(sizeof(EFI_GUID)) == fileGuid) {
|
QVector<PatchData> patches;
|
||||||
return ffsEngine->patch(index, findPattern, replacePattern, PATCH_MODE_BODY);
|
|
||||||
|
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;
|
||||||
|
counter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
int childCount = model->rowCount(index);
|
QByteArray reconstructed;
|
||||||
if (childCount > 0) {
|
result = ffsEngine->reconstructImageFile(reconstructed);
|
||||||
UINT8 result;
|
|
||||||
for (int i = 0; i < childCount; i++) {
|
|
||||||
result = patchFile(index.child(i, 0), fileGuid, findPattern, replacePattern);
|
|
||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
|
if (reconstructed == buffer)
|
||||||
|
return ERR_NOTHING_TO_PATCH;
|
||||||
|
|
||||||
|
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 UINT8 sectionType, const QVector<PatchData> & patches)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!model || !index.isValid())
|
||||||
|
return ERR_INVALID_PARAMETER;
|
||||||
|
if (model->type(index) == Types::Section && model->subtype(index) == sectionType) {
|
||||||
|
QModelIndex fileIndex = model->findParentOfType(index, Types::File);
|
||||||
|
if (model->type(fileIndex) == Types::File &&
|
||||||
|
model->header(fileIndex).left(sizeof(EFI_GUID)) == fileGuid)
|
||||||
|
{
|
||||||
|
return ffsEngine->patch(index, patches);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (model->rowCount(index) > 0) {
|
||||||
|
for (int i = 0; i < model->rowCount(index); i++) {
|
||||||
|
UINT8 result = patchFile(index.child(i, 0), fileGuid, sectionType, patches);
|
||||||
|
if (!result)
|
||||||
|
break;
|
||||||
|
else if (result != ERR_NOTHING_TO_PATCH)
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERR_SUCCESS;
|
return ERR_NOTHING_TO_PATCH;
|
||||||
}
|
}
|
@ -37,7 +37,7 @@ public:
|
|||||||
UINT8 patch(QString path, QString fileGuid, QString findPattern, QString replacePattern);
|
UINT8 patch(QString path, QString fileGuid, QString findPattern, QString replacePattern);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UINT8 patchFile(const QModelIndex & index, const QByteArray & fileGuid, const QByteArray & findPattern, const QByteArray & replacePattern);
|
UINT8 patchFile(const QModelIndex & index, const QByteArray & fileGuid, const UINT8 sectionType, const QVector<PatchData> & patches);
|
||||||
FfsEngine* ffsEngine;
|
FfsEngine* ffsEngine;
|
||||||
TreeModel* model;
|
TreeModel* model;
|
||||||
};
|
};
|
||||||
|
@ -27,31 +27,34 @@ int main(int argc, char *argv[])
|
|||||||
UINT8 result = ERR_SUCCESS;
|
UINT8 result = ERR_SUCCESS;
|
||||||
UINT32 argumentsCount = a.arguments().length();
|
UINT32 argumentsCount = a.arguments().length();
|
||||||
|
|
||||||
|
|
||||||
if (argumentsCount == 2) {
|
if (argumentsCount == 2) {
|
||||||
result = w.patchFromFile(a.arguments().at(1));
|
result = w.patchFromFile(a.arguments().at(1));
|
||||||
}
|
}
|
||||||
else if (argumentsCount == 5) {
|
else {
|
||||||
result = w.patch(a.arguments().at(1), a.arguments().at(2), a.arguments().at(3), a.arguments().at(4));
|
std::cout << "UEFIPatch 0.2.0 - UEFI image file patching utility" << std::endl << std::endl <<
|
||||||
|
"Usage: UEFIPatch image_file" << std::endl << std::endl <<
|
||||||
|
"Patches will be read from patches.txt file\n";
|
||||||
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
result = ERR_INVALID_PARAMETER;
|
|
||||||
|
|
||||||
switch (result) {
|
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:
|
case ERR_SUCCESS:
|
||||||
std::cout << "Image patched" << std::endl;
|
std::cout << "Image patched" << std::endl;
|
||||||
break;
|
break;
|
||||||
case ERR_ITEM_NOT_FOUND:
|
case ERR_INVALID_PARAMETER:
|
||||||
std::cout << "FFS file or search pattern not found in input file" << std::endl;
|
std::cout << "Function called with invalid parameter" << std::endl;
|
||||||
|
break;
|
||||||
|
case ERR_NOTHING_TO_PATCH:
|
||||||
|
std::cout << "No patches can be applied to input file" << std::endl;
|
||||||
|
break;
|
||||||
|
case ERR_UNKNOWN_PATCH_TYPE:
|
||||||
|
std::cout << "Unknown patch type" << std::endl;
|
||||||
|
break;
|
||||||
|
case ERR_PATCH_OFFSET_OUT_OF_BOUNDS:
|
||||||
|
std::cout << "Patch offset out of bounds" << std::endl;
|
||||||
|
break;
|
||||||
|
case ERR_INVALID_SYMBOL:
|
||||||
|
std::cout << "Pattern format mismatch" << std::endl;
|
||||||
break;
|
break;
|
||||||
case ERR_INVALID_FILE:
|
case ERR_INVALID_FILE:
|
||||||
std::cout << "patches.txt file not found or can't be read" << std::endl;
|
std::cout << "patches.txt file not found or can't be read" << std::endl;
|
||||||
|
24
basetypes.h
24
basetypes.h
@ -45,8 +45,6 @@ typedef uint16_t CHAR16;
|
|||||||
#define NULL ((VOID *) 0)
|
#define NULL ((VOID *) 0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define EFIAPI
|
|
||||||
|
|
||||||
#define ERR_SUCCESS 0
|
#define ERR_SUCCESS 0
|
||||||
#define ERR_INVALID_PARAMETER 1
|
#define ERR_INVALID_PARAMETER 1
|
||||||
#define ERR_BUFFER_TOO_SMALL 2
|
#define ERR_BUFFER_TOO_SMALL 2
|
||||||
@ -85,9 +83,23 @@ 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_UNKNOWN_PATCH_TYPE 38
|
||||||
|
#define ERR_PATCH_OFFSET_OUT_OF_BOUNDS 39
|
||||||
|
#define ERR_INVALID_SYMBOL 40
|
||||||
|
#define ERR_NOTHING_TO_PATCH 41
|
||||||
#define ERR_NOT_IMPLEMENTED 0xFF
|
#define ERR_NOT_IMPLEMENTED 0xFF
|
||||||
|
|
||||||
|
// UDK porting definitions
|
||||||
|
#define IN
|
||||||
|
#define OUT
|
||||||
|
#define EFIAPI
|
||||||
|
#define EFI_STATUS UINT8
|
||||||
|
#define EFI_SUCCESS ERR_SUCCESS
|
||||||
|
#define EFI_INVALID_PARAMETER ERR_INVALID_PARAMETER
|
||||||
|
#define EFI_OUT_OF_RESOURCES ERR_OUT_OF_RESOURCES
|
||||||
|
#define EFI_BUFFER_TOO_SMALL ERR_BUFFER_TOO_SMALL
|
||||||
|
#define EFI_ERROR(X) X
|
||||||
|
|
||||||
// Compression algorithms
|
// Compression algorithms
|
||||||
#define COMPRESSION_ALGORITHM_UNKNOWN 0
|
#define COMPRESSION_ALGORITHM_UNKNOWN 0
|
||||||
#define COMPRESSION_ALGORITHM_NONE 1
|
#define COMPRESSION_ALGORITHM_NONE 1
|
||||||
@ -114,6 +126,10 @@ typedef uint16_t CHAR16;
|
|||||||
#define PATCH_MODE_HEADER 0
|
#define PATCH_MODE_HEADER 0
|
||||||
#define PATCH_MODE_BODY 1
|
#define PATCH_MODE_BODY 1
|
||||||
|
|
||||||
|
// Patch types
|
||||||
|
#define PATCH_TYPE_OFFSET 'O'
|
||||||
|
#define PATCH_TYPE_PATTERN 'P'
|
||||||
|
|
||||||
// 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
|
||||||
@ -124,8 +140,6 @@ 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];
|
||||||
|
154
ffsengine.cpp
154
ffsengine.cpp
@ -1797,7 +1797,6 @@ UINT8 FfsEngine::decompress(const QByteArray & compressedData, const UINT8 compr
|
|||||||
UINT8 FfsEngine::compress(const QByteArray & data, const UINT8 algorithm, QByteArray & compressedData)
|
UINT8 FfsEngine::compress(const QByteArray & data, const UINT8 algorithm, QByteArray & compressedData)
|
||||||
{
|
{
|
||||||
UINT8* compressed;
|
UINT8* compressed;
|
||||||
UINT32 compressedSize = 0;
|
|
||||||
|
|
||||||
switch (algorithm) {
|
switch (algorithm) {
|
||||||
case COMPRESSION_ALGORITHM_NONE:
|
case COMPRESSION_ALGORITHM_NONE:
|
||||||
@ -1808,10 +1807,11 @@ UINT8 FfsEngine::compress(const QByteArray & data, const UINT8 algorithm, QByteA
|
|||||||
break;
|
break;
|
||||||
case COMPRESSION_ALGORITHM_EFI11:
|
case COMPRESSION_ALGORITHM_EFI11:
|
||||||
{
|
{
|
||||||
if (EfiCompress((UINT8*)data.constData(), data.size(), NULL, &compressedSize) != ERR_BUFFER_TOO_SMALL)
|
UINT64 compressedSize = 0;
|
||||||
|
if (EfiCompress(data.constData(), data.size(), NULL, &compressedSize) != ERR_BUFFER_TOO_SMALL)
|
||||||
return ERR_STANDARD_COMPRESSION_FAILED;
|
return ERR_STANDARD_COMPRESSION_FAILED;
|
||||||
compressed = new UINT8[compressedSize];
|
compressed = new UINT8[compressedSize];
|
||||||
if (EfiCompress((UINT8*)data.constData(), data.size(), compressed, &compressedSize) != ERR_SUCCESS) {
|
if (EfiCompress(data.constData(), data.size(), compressed, &compressedSize) != ERR_SUCCESS) {
|
||||||
delete[] compressed;
|
delete[] compressed;
|
||||||
return ERR_STANDARD_COMPRESSION_FAILED;
|
return ERR_STANDARD_COMPRESSION_FAILED;
|
||||||
}
|
}
|
||||||
@ -1822,10 +1822,11 @@ UINT8 FfsEngine::compress(const QByteArray & data, const UINT8 algorithm, QByteA
|
|||||||
break;
|
break;
|
||||||
case COMPRESSION_ALGORITHM_TIANO:
|
case COMPRESSION_ALGORITHM_TIANO:
|
||||||
{
|
{
|
||||||
if (TianoCompress((UINT8*)data.constData(), data.size(), NULL, &compressedSize) != ERR_BUFFER_TOO_SMALL)
|
UINT64 compressedSize = 0;
|
||||||
|
if (TianoCompress(data.constData(), data.size(), NULL, &compressedSize) != ERR_BUFFER_TOO_SMALL)
|
||||||
return ERR_STANDARD_COMPRESSION_FAILED;
|
return ERR_STANDARD_COMPRESSION_FAILED;
|
||||||
compressed = new UINT8[compressedSize];
|
compressed = new UINT8[compressedSize];
|
||||||
if (TianoCompress((UINT8*)data.constData(), data.size(), compressed, &compressedSize) != ERR_SUCCESS) {
|
if (TianoCompress(data.constData(), data.size(), compressed, &compressedSize) != ERR_SUCCESS) {
|
||||||
delete[] compressed;
|
delete[] compressed;
|
||||||
return ERR_STANDARD_COMPRESSION_FAILED;
|
return ERR_STANDARD_COMPRESSION_FAILED;
|
||||||
}
|
}
|
||||||
@ -1836,6 +1837,7 @@ UINT8 FfsEngine::compress(const QByteArray & data, const UINT8 algorithm, QByteA
|
|||||||
break;
|
break;
|
||||||
case COMPRESSION_ALGORITHM_LZMA:
|
case COMPRESSION_ALGORITHM_LZMA:
|
||||||
{
|
{
|
||||||
|
UINT32 compressedSize = 0;
|
||||||
if (LzmaCompress((const UINT8*)data.constData(), data.size(), NULL, &compressedSize) != ERR_BUFFER_TOO_SMALL)
|
if (LzmaCompress((const UINT8*)data.constData(), data.size(), NULL, &compressedSize) != ERR_BUFFER_TOO_SMALL)
|
||||||
return ERR_CUSTOMIZED_COMPRESSION_FAILED;
|
return ERR_CUSTOMIZED_COMPRESSION_FAILED;
|
||||||
compressed = new UINT8[compressedSize];
|
compressed = new UINT8[compressedSize];
|
||||||
@ -1850,6 +1852,7 @@ UINT8 FfsEngine::compress(const QByteArray & data, const UINT8 algorithm, QByteA
|
|||||||
break;
|
break;
|
||||||
case COMPRESSION_ALGORITHM_IMLZMA:
|
case COMPRESSION_ALGORITHM_IMLZMA:
|
||||||
{
|
{
|
||||||
|
UINT32 compressedSize = 0;
|
||||||
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 = sizeOfSectionHeader(sectionHeader);
|
UINT32 headerSize = sizeOfSectionHeader(sectionHeader);
|
||||||
@ -2645,6 +2648,7 @@ UINT8 FfsEngine::reconstructSection(const QModelIndex& index, const UINT32 base,
|
|||||||
|
|
||||||
// Reconstruction successful
|
// Reconstruction successful
|
||||||
reconstructed = header.append(reconstructed);
|
reconstructed = header.append(reconstructed);
|
||||||
|
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3198,48 +3202,126 @@ 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)
|
UINT8 FfsEngine::patch(const QModelIndex & index, const QVector<PatchData> & patches)
|
||||||
{
|
{
|
||||||
if (!index.isValid() || findPattern.isEmpty())
|
if (!index.isValid() || patches.isEmpty() || model->rowCount(index))
|
||||||
return ERR_INVALID_PARAMETER;
|
return ERR_INVALID_PARAMETER;
|
||||||
|
|
||||||
// Skip removed files
|
// Skip removed items
|
||||||
if (model->action(index) == Actions::Remove)
|
if (model->action(index) == Actions::Remove)
|
||||||
return ERR_SUCCESS;
|
return ERR_NOTHING_TO_PATCH;
|
||||||
|
|
||||||
// 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;
|
UINT8 result;
|
||||||
for (int i = 0; i < model->rowCount(index); i++) {
|
|
||||||
result = patch(index.child(i, 0), findPattern, replacePattern, PATCH_MODE_BODY);
|
// Apply patches to item's body
|
||||||
|
QByteArray body = model->body(index);
|
||||||
|
PatchData current;
|
||||||
|
Q_FOREACH(current, patches)
|
||||||
|
{
|
||||||
|
if (current.type == PATCH_TYPE_OFFSET) {
|
||||||
|
result = patchViaOffset(body, current.offset, current.hexReplacePattern);
|
||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
else if (current.type == PATCH_TYPE_PATTERN) {
|
||||||
else if (model->body(index).contains(findPattern)){
|
result = patchViaPattern(body, current.hexFindPattern, current.hexReplacePattern);
|
||||||
QByteArray patched = model->body(index);
|
if (result)
|
||||||
patched.replace(findPattern, replacePattern);
|
return result;
|
||||||
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
|
else
|
||||||
return ERR_UNKNOWN_PATCH_MODE;
|
return ERR_UNKNOWN_PATCH_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (body != model->body(index)) {
|
||||||
|
QByteArray patched = model->header(index);
|
||||||
|
patched.append(body);
|
||||||
|
return replace(index, patched, REPLACE_MODE_AS_IS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERR_NOTHING_TO_PATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT8 FfsEngine::patchViaOffset(QByteArray & data, const UINT32 offset, const QByteArray & hexReplacePattern)
|
||||||
|
{
|
||||||
|
QByteArray body = data;
|
||||||
|
|
||||||
|
// Skip patterns with odd length
|
||||||
|
if (hexReplacePattern.length() % 2 > 0)
|
||||||
|
return ERR_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
// Check offset bounds
|
||||||
|
if (offset > body.length() - hexReplacePattern.length() / 2)
|
||||||
|
return ERR_PATCH_OFFSET_OUT_OF_BOUNDS;
|
||||||
|
|
||||||
|
// Parse replace pattern
|
||||||
|
QByteArray replacePattern;
|
||||||
|
bool converted;
|
||||||
|
for (int i = 0; i < hexReplacePattern.length() / 2; i++) {
|
||||||
|
QByteArray hex = hexReplacePattern.mid(2 * i, 2);
|
||||||
|
UINT8 value = 0;
|
||||||
|
|
||||||
|
if (!hex.contains('.')) { // Normal byte pattern
|
||||||
|
value = (UINT8)hex.toUShort(&converted, 16);
|
||||||
|
if (!converted)
|
||||||
|
return ERR_INVALID_SYMBOL;
|
||||||
|
}
|
||||||
|
else { // Placeholder byte pattern
|
||||||
|
if (hex[0] == '.' && hex[1] == '.') { // Full byte placeholder
|
||||||
|
value = body.at(offset + i);
|
||||||
|
}
|
||||||
|
else if (hex[0] == '.') {// Upper byte part placeholder
|
||||||
|
hex[0] = '0';
|
||||||
|
value = (UINT8)(body.at(offset + i) & 0xF0);
|
||||||
|
value += (UINT8)hex.toUShort(&converted, 16);
|
||||||
|
if (!converted)
|
||||||
|
return ERR_INVALID_SYMBOL;
|
||||||
|
}
|
||||||
|
else if (hex[1] == '.') { // Lower byte part placeholder
|
||||||
|
hex[1] = '0';
|
||||||
|
value = (UINT8)(body.at(offset + i) & 0x0F);
|
||||||
|
value += (UINT8)hex.toUShort(&converted, 16);
|
||||||
|
if (!converted)
|
||||||
|
return ERR_INVALID_SYMBOL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return ERR_INVALID_SYMBOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append calculated value to real pattern
|
||||||
|
replacePattern.append(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
body.replace(offset, replacePattern.length(), replacePattern);
|
||||||
|
msg(tr("patch: replaced %1 bytes at offset 0x%2 %3 -> %4")
|
||||||
|
.arg(replacePattern.length())
|
||||||
|
.arg(offset, 8, 16, QChar('0'))
|
||||||
|
.arg(QString(data.mid(offset, replacePattern.length()).toHex()))
|
||||||
|
.arg(QString(replacePattern.toHex())));
|
||||||
|
data = body;
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT8 FfsEngine::patchViaPattern(QByteArray & data, const QByteArray hexFindPattern, const QByteArray & hexReplacePattern)
|
||||||
|
{
|
||||||
|
QByteArray body = data;
|
||||||
|
|
||||||
|
// Skip patterns with odd length
|
||||||
|
if (hexFindPattern.length() % 2 > 0 || hexReplacePattern.length() % 2 > 0)
|
||||||
|
return ERR_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
// Convert file body to hex;
|
||||||
|
QString hexBody = QString(body.toHex());
|
||||||
|
QRegExp regexp = QRegExp(QString(hexFindPattern), Qt::CaseInsensitive);
|
||||||
|
INT64 offset = regexp.indexIn(hexBody);
|
||||||
|
while (offset >= 0) {
|
||||||
|
if (offset % 2 == 0) {
|
||||||
|
UINT8 result = patchViaOffset(body, offset/2, hexReplacePattern);
|
||||||
|
if (result)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
offset = regexp.indexIn(hexBody, offset + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
data = body;
|
||||||
return ERR_SUCCESS;
|
return ERR_SUCCESS;
|
||||||
}
|
}
|
13
ffsengine.h
13
ffsengine.h
@ -32,6 +32,13 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
|
|
||||||
class TreeModel;
|
class TreeModel;
|
||||||
|
|
||||||
|
struct PatchData {
|
||||||
|
UINT8 type;
|
||||||
|
UINT32 offset;
|
||||||
|
QByteArray hexFindPattern;
|
||||||
|
QByteArray hexReplacePattern;
|
||||||
|
};
|
||||||
|
|
||||||
class FfsEngine : public QObject
|
class FfsEngine : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -86,7 +93,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);
|
UINT8 patch(const QModelIndex & index, const QVector<PatchData> & patches);
|
||||||
|
|
||||||
// Search routines
|
// Search routines
|
||||||
UINT8 findHexPattern(const QByteArray & pattern, const UINT8 mode);
|
UINT8 findHexPattern(const QByteArray & pattern, const UINT8 mode);
|
||||||
@ -120,6 +127,10 @@ private:
|
|||||||
// Patch routines
|
// Patch routines
|
||||||
UINT8 patchVtf(QByteArray &vtf);
|
UINT8 patchVtf(QByteArray &vtf);
|
||||||
|
|
||||||
|
// Patch helpers
|
||||||
|
UINT8 patchViaOffset(QByteArray & data, const UINT32 offset, const QByteArray & hexReplacePattern);
|
||||||
|
UINT8 patchViaPattern(QByteArray & data, const QByteArray hexFindPattern, const QByteArray & hexReplacePattern);
|
||||||
|
|
||||||
#ifndef _CONSOLE
|
#ifndef _CONSOLE
|
||||||
QQueue<MessageListItem> messageItems;
|
QQueue<MessageListItem> messageItems;
|
||||||
#endif
|
#endif
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>UEFITool 0.17.10</string>
|
<string>UEFITool 0.18.0</string>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="centralWidget">
|
<widget class="QWidget" name="centralWidget">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
|
Loading…
Reference in New Issue
Block a user