Compare commits

...

71 commits

Author SHA1 Message Date
vit9696
4bee991c94 Implement custom LZMA dictionary size support, fixes #154 2018-12-30 18:37:27 +03:00
vit9696
e6f84f9f7d Version bump 2018-06-24 17:07:52 +03:00
vit9696
35c207dd8c More proper solution to #137 2018-06-23 19:46:56 +03:00
vit9696
c4567dcffc Attempt to workaround #137 2018-06-23 00:39:51 +03:00
vit9696
4bb759780f Unify version scheme 2018-05-22 00:43:34 +03:00
vit9696
8ea96ffd5d Support replacing raw sections and ffs via -asis 2018-05-21 10:07:33 +03:00
vit9696
e5d868977e Deploy as prerelease to avoid confusion 2018-05-20 00:02:35 +03:00
vit9696
65263f1000 Allow subguid matching for UEFIReplace 2018-05-19 23:53:21 +03:00
vit9696
dd90367387 Fix recursion in UEFIReplace 2018-05-19 23:35:57 +03:00
vit9696
b5961a7155 Add -o / --output flag to UEFIPatch 2018-05-19 18:55:51 +03:00
vit9696
8db52ea51a Implement replace all and add -o (--output) path to UEFIReplace 2018-05-19 18:35:38 +03:00
vit9696
63e40c058a Increment version 2018-05-08 21:49:11 +03:00
vit9696
f507d71ead Backport decompression updates from new_engine 2018-05-08 19:22:07 +03:00
vit9696
b3f7beb236 Initial Windows build support 2018-05-08 02:28:03 +03:00
vit9696
f321a6c7a8 Add misc patches unrelated to Intel PowerManagement 2018-05-07 22:12:50 +03:00
vit9696
66c9d4a2cf Implement external patches.txt path for UEFIPatch 2018-05-07 22:01:17 +03:00
vit9696
f383646033 Fix UEFITool path on Linux 2018-05-07 21:42:03 +03:00
vit9696
912a1b25b2 Fix compiler warning, closes #121 2018-05-07 21:37:44 +03:00
vit9696
3395cc7a1a Add Linux x86-64 CI support 2018-05-07 21:36:24 +03:00
vit9696
e25ed49b27 Do not try to rebase removed sections, fixes #92 2018-05-07 08:01:09 +03:00
vit9696
3993bd7090 Improve descriptor version handling 2018-05-06 23:28:52 +03:00
vit9696
acb1a4d099 Fix Intel descriptor version parsing at reading 2018-05-06 15:29:08 +03:00
vit9696
03274ff47c Properly read Intel descriptor version, thx @platomav 2018-05-06 15:11:21 +03:00
vit9696
539408c667 Recognise B360MHD3.F3 descriptor version 2018-05-06 11:31:39 +03:00
vit9696
5e81b20c85 Version bump 2018-05-04 21:49:56 +03:00
vit9696
dd28665644 Remove legacy UEFIFind and UEFIExtract in favour of new_engine branch 2018-05-04 21:42:54 +03:00
vit9696
fe13f1efe9 Backport TianoDecompress fix for Xcode (https://bugzilla.tianocore.org/show_bug.cgi?id=635) 2018-05-04 20:46:06 +03:00
vit9696
26b40c229a Merge pull request #130 from vit9696/ci-master
Travis Mac
2018-05-04 06:52:01 +03:00
vit9696
7da3f6b793 Add deploy key 2018-05-04 06:40:04 +03:00
vit9696
3284737952 Implement mac builds with deploy 2018-05-03 22:27:40 +03:00
vit9696
fd4d75957e Fix rebuild reversion 2018-05-03 20:41:27 +03:00
Alex Matrosov
88ed04cd4c Merge pull request #128 from vit9696/recover-skylake
Recover Skylake patches
2018-05-01 20:04:25 -07:00
vit9696
462f693ad6 Recover Skylake patches 2018-05-01 23:27:35 +03:00
Alex Matrosov
a5ce9ab3d9 bugfix 2018-04-29 22:38:54 -07:00
Alex Matrosov
956a804dd5 Merge pull request #126 from HackingThings/master
Fix for EC region parse
2018-04-14 16:04:57 -07:00
HackingThings
dcdb85497d Fix EC region parse
Fixing Copy&Paste bug
2018-04-14 10:40:31 -07:00
Alex Matrosov
ea5ae2f2c8 fixed rebase PEI files with nonstandard alignment 2018-02-25 15:40:14 -08:00
Alex Matrosov
341ee144f9 Merge pull request #113 from interferenc/master
Fixed patches for Skylake-X
2018-02-22 11:59:43 -08:00
Marton Farago
50ff6dc038 Fixed patches for Skylake-X
D71C8BA4-4AF2-4D0D-B1BA-F2409F0C20D3 is a completly unrelated GUID (UncoreInitPei), so while it contains a code block that looks like an MSR 0xE2 lock, that has nothing to do with it.

3FFCAE95-23CF-4967-94F5-16352F68E43B has a better patch that just jumps over the whole lock enforcing block

01359D99-9446-456D-ADA4-50A711C03ADA also needs a patch, this runs on wake from S3 sleep and lock the register again if not patched.
2018-02-15 07:39:34 +01:00
Cr4sh
df95f0755c multiple fixes 2018-02-15 06:04:34 +03:00
Alex Matrosov
9d623c91e6 fix for #99 2018-01-22 23:58:29 -08:00
Alex Matrosov
3ffdae1123 0.22.1 multiple FFSv3 support fixes, thanks to @osresearch
+ multiple FFSv3 support fixes, thanks to @osresearch
+ fixed removal of FFS files with opposite EP bit value
+ disabled creation of large sections (too buggy now, will be fixed later)
2017-12-10 21:54:50 -08:00
Alex Matrosov
73019876cf add FFSv3 support with large files and large sections 2017-12-10 16:54:40 -08:00
Alex Matrosov
75225ecc28 Merge pull request #76 from mxxxc/master
Add UEFIReplace.
2017-05-06 17:24:47 -07:00
Mark
5ba63418bd Add UEFIReplace. 2017-04-14 03:24:24 +02:00
Dmytro Oleksiuk
dbeda3fc9d Merge pull request #69 from adriandumitru/Develop
Add Kaby Lake support.
2017-02-12 10:23:06 +03:00
Adrian Dumitru
b700177e4a Add Kaby Lake support. 2017-01-25 00:30:53 +02:00
Alex Matrosov
8cfd93c8eb Update patches.txt 2016-08-21 15:48:13 -07:00
Nikolaj Schlej
d54f215e67 Forgot to bump UP version 2015-11-12 09:38:14 +01:00
Nikolaj Schlej
19cc031244 UT 0.21.5 /UP 0.3.9 untested
- fixed various crashes reported in #39
- changes aren't tested yet, please don't use until #39 is fixed
2015-11-12 09:37:38 +01:00
Nikolaj Schlej
7ebbc58b9b UT 0.21.4 / UP 0.3.8
- fixed a bug introduced in 0.21.3 commit
2015-10-04 22:28:44 +02:00
Nikolaj Schlej
9d0bcd0bed Fix a compiler warning 2015-10-04 22:05:38 +02:00
Nikolaj Schlej
1ab52fde35 UT 0.21.3 / UP 0.3.7
- solved a bug with Gigabyte-specific descriptor settings (BIOS region
has size of the whole image), thanks to lordkag for #37
2015-10-04 21:58:44 +02:00
Nikolaj Schlej
388dd25093 UT 0.21.2
- fixed a bug with tailed files extraction and replacing (#35)
- fixed a bug with wrong source of padding after all Intel image regions
(#34)
2015-10-02 09:38:30 +02:00
Nikolaj Schlej
ed038c21bf Corrected #34
- padding data was a part of the image, now BIOS region
2015-10-01 08:24:35 +02:00
Nikolaj Schlej
93881e4892 Corrected EC region placement 2015-09-12 21:40:45 +02:00
Nikolaj Schlej
4e8431b169 UT 0.21.1
- added replace action for paddings
- fixed a rare visual bug (wrong image sizes in reconstructRegion
messages)
- parts of the new flash region map are defined a bit better
2015-09-12 21:01:42 +02:00
Nikolaj Schlej
9c7c94702d Replace action for paddings
- and a very small visual bugfix
2015-09-12 20:46:21 +02:00
Nikolaj Schlej
e5cf61f89a Small fixes of FLASH_DESCRIPTOR_REGION_SECTION definition 2015-09-12 19:44:59 +02:00
Nikolaj Schlej
8a14965463 Spellchecking
Corrections of issue #32
2015-09-08 08:54:42 +02:00
Nikolaj Schlej
c286459676 UP 0.3.6
- changed version number due to rebuild with engine version 0.21.0
2015-09-06 23:51:50 +02:00
Nikolaj Schlej
aa80837bf5 UT 0.21.0
- added support for new Intel descriptor type, based on
[this](http://review.coreboot.org/gitweb?p=coreboot.git;a=commit;h=1f7fd720c81755144423f2d4062c39cc651adc0a)
coreboot commit, thanks to lordkag for issue #32
- solved a bug with incorrect volume free space item placement during
volume replace, now works as expected
- solved an issue with incorrect Aptio capsule parsing introduced in
0.20.8
2015-09-06 23:46:26 +02:00
Nikolaj Schlej
9c4ddbec62 UT 0.20.8
- data after the latest region of Intel image is in tree now
- added Intel, Lenovo and Toshiba-specific capsule GUIDs to the list of
known GUIDs
- fixed bogus "File with invalid size" message while working on almost
full volumes
- pressing Cancel on "Open in new window" dialog now works as expected

Big thanks to Lordkag for spotting most of the issues (#31).
2015-08-30 10:52:19 +02:00
Nikolaj Schlej
63e5a4dd1c UT 0.20.7
- added "Open in new window..." action
2015-08-13 20:28:19 +02:00
Nikolaj Schlej
1109e44379 Create LICENSE.md 2015-08-11 18:12:12 +02:00
Nikolaj Schlej
c5fec376f7 Engine 0.20.6
- added support for recalculation of Apple-specific free space offset
value stored in volume's ZeroVector. Thanks to osxreverser for reporting
the issue #29.
- ZeroVectorCRC renamed to AppleCRC32, because it's Apple-specific after
all.
- ParsingData handling removed from old codebase, because it's only
needed for the new engine.
2015-07-05 13:28:53 +02:00
Nikolaj Schlej
d78df75de6 Update version numbers 2015-05-17 10:39:31 +02:00
Nikolaj Schlej
3013398a9d Engine 0.20.5
- raw file header was included twice during reconstruction as region
2015-05-17 10:38:04 +02:00
Nikolaj Schlej
b9b5758d2d Merge pull request #21 from cyrozap/master
Use Travis CI for build testing
2015-03-29 07:36:47 +02:00
cyrozap
351285dfbf Fixing Travis build 2015-03-28 22:20:38 -04:00
cyrozap
92c9754c02 Add Travis CI configuration 2015-03-28 22:15:06 -04:00
48 changed files with 2128 additions and 1224 deletions

28
.appveyor.yml Normal file
View file

@ -0,0 +1,28 @@
image: Visual Studio 2015
environment:
matrix:
- MSYS2_ARCH: i686
MSYSTEM: MINGW32
clone_depth: 10
build_script:
- cd %APPVEYOR_BUILD_FOLDER%
- set PATH=C:\msys64\mingw32\bin;C:\msys64\usr\bin;%PATH%
- bash ./unixbuild.sh
deploy:
provider: GitHub
force_update: true
auth_token:
secure: zSJnpSnrKY1NO5RPVBaD/uq7UPyc+GW7ecjPFqEMsLjtnd6H+iNfROdoeuxJgt5T
artifact: Binaries
prerelease: true
on:
appveyor_repo_tag: true
artifacts:
- path: dist\**\*.zip
name: Binaries

8
.gitignore vendored
View file

@ -233,4 +233,10 @@ Makefile
UEFIExtract/UEFIExtract UEFIExtract/UEFIExtract
UEFIFind/UEFIFind UEFIFind/UEFIFind
UEFIPatch/UEFIPatch UEFIPatch/UEFIPatch
UEFITool UEFIReplace/UEFIReplace
UEFITool
.qmake.stash
UEFITool.app/
uefitool_plugin_import.cpp
DerivedData
*.xcodeproj

52
.travis.yml Normal file
View file

@ -0,0 +1,52 @@
language: cpp
matrix:
include:
- os: osx
osx_image: xcode9.2
compiler: clang
script:
- ./unixbuild.sh
deploy:
provider: releases
skip_cleanup: true
file: "dist/*.zip"
file_glob: true
api_key:
secure: "WjYd93lVLKHULBpUXS/WtGrkdXyAwxHOUnLJotyDmQipAQP5Ox7Kj12JwkSJGEmVOEdcbIQJyi0QxPjn1UYbYsAt6Op8zrjnYLS4G4fMdBtcxprWzid85uTW7oAAIFs7ygMVhpzxRKpu70yNb683vbThqNmaOu6RyG9aJOLtPAg="
on:
tags: true
- os: linux
dist: trusty
compiler: clang
before_install:
- sudo apt-get update -qq
- sudo apt-get install -qq qt5-default qt5-qmake qtbase5-dev-tools cmake
script:
- ./unixbuild.sh
- os: linux
dist: trusty
compiler: gcc
before_install:
- sudo apt-get update -qq
- sudo apt-get install -qq qt5-default qt5-qmake qtbase5-dev-tools cmake
script:
- ./unixbuild.sh
deploy:
provider: releases
skip_cleanup: true
file: "dist/*.zip"
file_glob: true
api_key:
secure: "WjYd93lVLKHULBpUXS/WtGrkdXyAwxHOUnLJotyDmQipAQP5Ox7Kj12JwkSJGEmVOEdcbIQJyi0QxPjn1UYbYsAt6Op8zrjnYLS4G4fMdBtcxprWzid85uTW7oAAIFs7ygMVhpzxRKpu70yNb683vbThqNmaOu6RyG9aJOLtPAg="
on:
tags: true

23
LICENSE.md Normal file
View file

@ -0,0 +1,23 @@
Copyright (c) 2015, Nikolaj Schlej
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -25,7 +25,7 @@ static ISzAlloc SzAllocForLzma = { &AllocForLzma, &FreeForLzma };
SRes OnProgress(void *p, UInt64 inSize, UInt64 outSize) SRes OnProgress(void *p, UInt64 inSize, UInt64 outSize)
{ {
(void)p; (void) inSize; (void) outSize; (void)p; (void)inSize; (void)outSize;
return SZ_OK; return SZ_OK;
} }
@ -34,9 +34,9 @@ static ICompressProgress g_ProgressCallback = { &OnProgress };
STATIC STATIC
UINT64 UINT64
EFIAPI EFIAPI
RShiftU64( RShiftU64 (
UINT64 Operand, UINT64 Operand,
UINT32 Count UINT32 Count
) )
{ {
return Operand >> Count; return Operand >> Count;
@ -44,8 +44,8 @@ UINT32 Count
VOID VOID
SetEncodedSizeOfBuf( SetEncodedSizeOfBuf(
UINT64 EncodedSize, UINT64 EncodedSize,
UINT8 *EncodedData UINT8* EncodedData
) )
{ {
INT32 Index; INT32 Index;
@ -58,13 +58,14 @@ UINT8 *EncodedData
} }
} }
INT32 EFI_STATUS
EFIAPI EFIAPI
LzmaCompress( LzmaCompress (
CONST UINT8 *Source, CONST UINT8 *Source,
UINT32 SourceSize, UINT32 SourceSize,
UINT8 *Destination, UINT8 *Destination,
UINT32 *DestinationSize UINT32 *DestinationSize,
UINT32 DictionarySize
) )
{ {
SRes LzmaResult; SRes LzmaResult;
@ -72,14 +73,14 @@ UINT32 *DestinationSize
SizeT propsSize = LZMA_PROPS_SIZE; SizeT propsSize = LZMA_PROPS_SIZE;
SizeT destLen = SourceSize + SourceSize / 3 + 128; SizeT destLen = SourceSize + SourceSize / 3 + 128;
if (*DestinationSize < destLen) if (*DestinationSize < (UINT32)destLen)
{ {
*DestinationSize = destLen; *DestinationSize = (UINT32)destLen;
return ERR_BUFFER_TOO_SMALL; return EFI_BUFFER_TOO_SMALL;
} }
LzmaEncProps_Init(&props); LzmaEncProps_Init(&props);
props.dictSize = LZMA_DICTIONARY_SIZE; props.dictSize = DictionarySize;
props.level = 9; props.level = 9;
props.fb = 273; props.fb = 273;
@ -87,7 +88,7 @@ UINT32 *DestinationSize
(Byte*)((UINT8*)Destination + LZMA_HEADER_SIZE), (Byte*)((UINT8*)Destination + LZMA_HEADER_SIZE),
&destLen, &destLen,
Source, Source,
SourceSize, (SizeT)SourceSize,
&props, &props,
(UINT8*)Destination, (UINT8*)Destination,
&propsSize, &propsSize,
@ -96,14 +97,14 @@ UINT32 *DestinationSize
&SzAllocForLzma, &SzAllocForLzma,
&SzAllocForLzma); &SzAllocForLzma);
*DestinationSize = destLen + LZMA_HEADER_SIZE; *DestinationSize = (UINT32)(destLen + LZMA_HEADER_SIZE);
SetEncodedSizeOfBuf((UINT64)SourceSize, Destination); SetEncodedSizeOfBuf(SourceSize, Destination);
if (LzmaResult == SZ_OK) { if (LzmaResult == SZ_OK) {
return ERR_SUCCESS; return EFI_SUCCESS;
} }
else { else {
return ERR_INVALID_PARAMETER; return EFI_INVALID_PARAMETER;
} }
} }

View file

@ -11,8 +11,8 @@
*/ */
#ifndef __LZMACOMPRESS_H__ #ifndef LZMACOMPRESS_H
#define __LZMACOMPRESS_H__ #define LZMACOMPRESS_H
#include "SDK/C/Types.h" #include "SDK/C/Types.h"
#include "../basetypes.h" #include "../basetypes.h"
@ -21,19 +21,21 @@
extern "C" { extern "C" {
#endif #endif
#define LZMA_DICTIONARY_SIZE 0x800000 #define DEFAULT_LZMA_DICTIONARY_SIZE 0x800000
#define _LZMA_SIZE_OPT #define _LZMA_SIZE_OPT
INT32 EFI_STATUS
EFIAPI EFIAPI
LzmaCompress( LzmaCompress (
const UINT8 *Source, const UINT8 *Source,
UINT32 SourceSize, UINT32 SourceSize,
UINT8 *Destination, UINT8 *Destination,
UINT32 *DestinationSize UINT32 *DestinationSize,
UINT32 DictionarySize
); );
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif
#endif // LZMACOMPRESS_H

View file

@ -19,10 +19,10 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
UINT64 UINT64
EFIAPI EFIAPI
LShiftU64( LShiftU64 (
UINT64 Operand, UINT64 Operand,
UINT32 Count UINT32 Count
) )
{ {
return Operand << Count; return Operand << Count;
} }
@ -39,12 +39,12 @@ Get the size of the uncompressed buffer by parsing EncodeData header.
@return The size of the uncompressed buffer. @return The size of the uncompressed buffer.
*/ */
UINT64 UINT64
GetDecodedSizeOfBuf( GetDecodedSizeOfBuf (
UINT8 *EncodedData UINT8 *EncodedData
) )
{ {
UINT64 DecodedSize; UINT64 DecodedSize;
INT32 Index; INT32 Index;
// Parse header // Parse header
DecodedSize = 0; DecodedSize = 0;
@ -85,22 +85,27 @@ DestinationSize and the size of the scratch
buffer was returned ScratchSize. buffer was returned ScratchSize.
*/ */
INT32 EFI_STATUS
EFIAPI EFIAPI
LzmaGetInfo( LzmaGetInfo (
CONST VOID *Source, CONST VOID *Source,
UINT32 SourceSize, UINT32 SourceSize,
UINT32 *DestinationSize UINT32 *DestinationSize
) )
{ {
UInt64 DecodedSize; UINT64 DecodedSize;
ASSERT(SourceSize >= LZMA_HEADER_SIZE);
(void)SourceSize;
ASSERT(SourceSize >= LZMA_HEADER_SIZE); (void)SourceSize;
DecodedSize = GetDecodedSizeOfBuf((UINT8*)Source); DecodedSize = GetDecodedSizeOfBuf((UINT8*)Source);
*DestinationSize = (UINT32)DecodedSize; if (DecodedSize <= UINT32_MAX) {
return ERR_SUCCESS; *DestinationSize = (UINT32)DecodedSize;
return ERR_SUCCESS;
}
else {
return ERR_INVALID_PARAMETER;
}
} }
/* /*
@ -122,13 +127,13 @@ the uncompressed buffer is returned Destination.
The source buffer specified by Source is corrupted The source buffer specified by Source is corrupted
(not a valid compressed format). (not a valid compressed format).
*/ */
INT32 EFI_STATUS
EFIAPI EFIAPI
LzmaDecompress( LzmaDecompress (
CONST VOID *Source, CONST VOID *Source,
UINT32 SourceSize, UINT32 SourceSize,
VOID *Destination VOID *Destination
) )
{ {
SRes LzmaResult; SRes LzmaResult;
ELzmaStatus Status; ELzmaStatus Status;

View file

@ -11,8 +11,8 @@
*/ */
#ifndef __LZMADECOMPRESS_H__ #ifndef LZMADECOMPRESS_H
#define __LZMADECOMPRESS_H__ #define LZMADECOMPRESS_H
#include "../basetypes.h" #include "../basetypes.h"
#include "SDK/C/LzmaDec.h" #include "SDK/C/LzmaDec.h"
@ -23,13 +23,6 @@ extern "C" {
#define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + 8) #define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + 8)
UINT64
EFIAPI
LShiftU64(
UINT64 Operand,
UINT32 Count
);
/* /*
Given a Lzma compressed source buffer, this function retrieves the size of Given a Lzma compressed source buffer, this function retrieves the size of
the uncompressed buffer and the size of the scratch buffer required the uncompressed buffer and the size of the scratch buffer required
@ -57,12 +50,12 @@ extern "C" {
buffer was returned ScratchSize. buffer was returned ScratchSize.
*/ */
INT32 EFI_STATUS
EFIAPI EFIAPI
LzmaGetInfo( LzmaGetInfo (
const VOID *Source, CONST VOID *Source,
UINT32 SourceSize, UINT32 SourceSize,
UINT32 *DestinationSize UINT32 *DestinationSize
); );
/* /*
@ -84,15 +77,16 @@ extern "C" {
The source buffer specified by Source is corrupted The source buffer specified by Source is corrupted
(not a valid compressed format). (not a valid compressed format).
*/ */
INT32 EFI_STATUS
EFIAPI EFIAPI
LzmaDecompress( LzmaDecompress (
const VOID *Source, CONST VOID *Source,
UINT32 SourceSize, UINT32 SourceSize,
VOID *Destination VOID *Destination
); );
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif
#endif // LZMADECOMPRESS_H

View file

@ -69,18 +69,15 @@ PutDword(
STATIC STATIC
EFI_STATUS EFI_STATUS
AllocateMemory ( AllocateMemory (VOID);
);
STATIC STATIC
VOID VOID
FreeMemory ( FreeMemory (VOID);
);
STATIC STATIC
VOID VOID
InitSlide ( InitSlide (VOID);
);
STATIC STATIC
NODE NODE
@ -105,28 +102,23 @@ Split (
STATIC STATIC
VOID VOID
InsertNode ( InsertNode (VOID);
);
STATIC STATIC
VOID VOID
DeleteNode ( DeleteNode (VOID);
);
STATIC STATIC
VOID VOID
GetNextMatch ( GetNextMatch (VOID);
);
STATIC STATIC
EFI_STATUS EFI_STATUS
Encode ( Encode (VOID);
);
STATIC STATIC
VOID VOID
CountTFreq ( CountTFreq (VOID);
);
STATIC STATIC
VOID VOID
@ -138,8 +130,7 @@ WritePTLen (
STATIC STATIC
VOID VOID
WriteCLen ( WriteCLen (VOID);
);
STATIC STATIC
VOID VOID
@ -155,8 +146,7 @@ EncodeP (
STATIC STATIC
VOID VOID
SendBlock ( SendBlock (VOID);
);
STATIC STATIC
VOID VOID
@ -167,18 +157,15 @@ Output (
STATIC STATIC
VOID VOID
HufEncodeStart ( HufEncodeStart (VOID);
);
STATIC STATIC
VOID VOID
HufEncodeEnd ( HufEncodeEnd (VOID);
);
STATIC STATIC
VOID VOID
MakeCrcTable ( MakeCrcTable (VOID);
);
STATIC STATIC
VOID VOID
@ -196,8 +183,7 @@ FreadCrc (
STATIC STATIC
VOID VOID
InitPutBits ( InitPutBits (VOID);
);
STATIC STATIC
VOID VOID
@ -506,17 +492,24 @@ Returns:
UINT32 i; UINT32 i;
mText = malloc (WNDSIZ * 2 + MAXMATCH); mText = malloc (WNDSIZ * 2 + MAXMATCH);
if (!mText) return EFI_OUT_OF_RESOURCES;
for (i = 0 ; i < WNDSIZ * 2 + MAXMATCH; i ++) { for (i = 0 ; i < WNDSIZ * 2 + MAXMATCH; i ++) {
mText[i] = 0; mText[i] = 0;
} }
mLevel = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof(*mLevel)); mLevel = malloc((WNDSIZ + UINT8_MAX + 1) * sizeof(*mLevel));
mChildCount = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof(*mChildCount)); if (!mLevel) return EFI_OUT_OF_RESOURCES;
mPosition = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof(*mPosition)); mChildCount = malloc((WNDSIZ + UINT8_MAX + 1) * sizeof(*mChildCount));
mParent = malloc (WNDSIZ * 2 * sizeof(*mParent)); if (!mChildCount) return EFI_OUT_OF_RESOURCES;
mPrev = malloc (WNDSIZ * 2 * sizeof(*mPrev)); mPosition = malloc((WNDSIZ + UINT8_MAX + 1) * sizeof(*mPosition));
mNext = malloc ((MAX_HASH_VAL + 1) * sizeof(*mNext)); if (!mPosition) return EFI_OUT_OF_RESOURCES;
mParent = malloc(WNDSIZ * 2 * sizeof(*mParent));
if (!mParent) return EFI_OUT_OF_RESOURCES;
mPrev = malloc(WNDSIZ * 2 * sizeof(*mPrev));
if (!mPrev) return EFI_OUT_OF_RESOURCES;
mNext = malloc((MAX_HASH_VAL + 1) * sizeof(*mNext));
if (!mNext) return EFI_OUT_OF_RESOURCES;
mBufSiz = 16 * 1024U; mBufSiz = 16 * 1024U;
while ((mBuf = malloc(mBufSiz)) == NULL) { while ((mBuf = malloc(mBufSiz)) == NULL) {
mBufSiz = (mBufSiz / 10U) * 9U; mBufSiz = (mBufSiz / 10U) * 9U;

View file

@ -20,8 +20,8 @@ Header file for compression routine.
*/ */
#ifndef _EFITIANOCOMPRESS_H_ #ifndef EFITIANOCOMPRESS_H
#define _EFITIANOCOMPRESS_H_ #define EFITIANOCOMPRESS_H
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
@ -115,4 +115,4 @@ extern "C" {
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif #endif // EFITIANOCOMPRESS_H

View file

@ -529,17 +529,24 @@ STATIC
{ {
UINT32 Index; UINT32 Index;
mText = malloc (WNDSIZ * 2 + MAXMATCH); mText = malloc (WNDSIZ * 2 + MAXMATCH);
if (!mText) return EFI_OUT_OF_RESOURCES;
for (Index = 0; Index < WNDSIZ * 2 + MAXMATCH; Index++) { for (Index = 0; Index < WNDSIZ * 2 + MAXMATCH; Index++) {
mText[Index] = 0; mText[Index] = 0;
} }
mLevel = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mLevel)); mLevel = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mLevel));
mChildCount = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mChildCount)); if (!mLevel) return EFI_OUT_OF_RESOURCES;
mPosition = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mPosition)); mChildCount = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mChildCount));
mParent = malloc (WNDSIZ * 2 * sizeof (*mParent)); if (!mChildCount) return EFI_OUT_OF_RESOURCES;
mPrev = malloc (WNDSIZ * 2 * sizeof (*mPrev)); mPosition = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mPosition));
mNext = malloc ((MAX_HASH_VAL + 1) * sizeof (*mNext)); if (!mPosition) return EFI_OUT_OF_RESOURCES;
mParent = malloc (WNDSIZ * 2 * sizeof (*mParent));
if (!mParent) return EFI_OUT_OF_RESOURCES;
mPrev = malloc (WNDSIZ * 2 * sizeof (*mPrev));
if (!mPrev) return EFI_OUT_OF_RESOURCES;
mNext = malloc ((MAX_HASH_VAL + 1) * sizeof (*mNext));
if (!mNext) return EFI_OUT_OF_RESOURCES;
mBufSiz = BLKSIZ; mBufSiz = BLKSIZ;
mBuf = malloc (mBufSiz); mBuf = malloc (mBufSiz);

View file

@ -100,10 +100,10 @@ Returns: (VOID)
--*/ --*/
{ {
Sd->mBitBuf = (UINT32)(Sd->mBitBuf << NumOfBits); Sd->mBitBuf = (UINT32) (((UINT64)Sd->mBitBuf) << NumOfBits);
while (NumOfBits > Sd->mBitCount) { while (NumOfBits > Sd->mBitCount) {
Sd->mBitBuf |= (UINT32)(Sd->mSubBitBuf << (NumOfBits = (UINT16)(NumOfBits - Sd->mBitCount))); Sd->mBitBuf |= (UINT32) (((UINT64)Sd->mSubBitBuf) << (NumOfBits = (UINT16) (NumOfBits - Sd->mBitCount)));
if (Sd->mCompSize > 0) { if (Sd->mCompSize > 0) {
// //

View file

@ -21,8 +21,8 @@ Providing both EFI and Tiano decompress algorithms.
--*/ --*/
#ifndef _EFITIANODECOMPRESS_H_ #ifndef EFITIANODECOMPRESS_H
#define _EFITIANODECOMPRESS_H_ #define EFITIANODECOMPRESS_H
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
@ -32,110 +32,107 @@ Providing both EFI and Tiano decompress algorithms.
extern "C" { extern "C" {
#endif #endif
typedef struct { typedef struct EFI_TIANO_HEADER_ {
UINT32 CompSize; UINT32 CompSize;
UINT32 OrigSize; UINT32 OrigSize;
} EFI_TIANO_HEADER; } EFI_TIANO_HEADER;
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
EfiTianoGetInfo( EfiTianoGetInfo(
const VOID *Source, const VOID *Source,
UINT32 SrcSize, UINT32 SrcSize,
UINT32 *DstSize, UINT32 *DstSize,
UINT32 *ScratchSize UINT32 *ScratchSize
) )
/*++ /*++
Routine Description: Routine Description:
The implementation is same as that of EFI_DECOMPRESS_PROTOCOL.GetInfo(). The implementation is same as that of EFI_DECOMPRESS_PROTOCOL.GetInfo().
Arguments: Arguments:
This - The protocol instance pointer Source - The source buffer containing the compressed data.
Source - The source buffer containing the compressed data. SrcSize - The size of source buffer
SrcSize - The size of source buffer DstSize - The size of destination buffer.
DstSize - The size of destination buffer. ScratchSize - The size of scratch buffer.
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 successfully retrieved.
EFI_INVALID_PARAMETER - The source data is corrupted EFI_INVALID_PARAMETER - The source data is corrupted
--*/ --*/
; ;
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
EfiDecompress( EfiDecompress(
const VOID *Source, const VOID *Source,
UINT32 SrcSize, UINT32 SrcSize,
VOID *Destination, VOID *Destination,
UINT32 DstSize, UINT32 DstSize,
VOID *Scratch, VOID *Scratch,
UINT32 ScratchSize UINT32 ScratchSize
) );
/*++ /*++
Routine Description: Routine Description:
The implementation is same as that of EFI_DECOMPRESS_PROTOCOL.Decompress(). The implementation is same as that of EFI_DECOMPRESS_PROTOCOL.Decompress().
Arguments: Arguments:
This - The protocol instance pointer Source - The source buffer containing the compressed data.
Source - The source buffer containing the compressed data. SrcSize - The size of source buffer
SrcSize - The size of source buffer Destination - The destination buffer to store the decompressed data
Destination - The destination buffer to store the decompressed data DstSize - The size of destination buffer.
DstSize - The size of destination buffer. Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.
Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. ScratchSize - The size of scratch buffer.
ScratchSize - The size of scratch buffer.
Returns: Returns:
EFI_SUCCESS - Decompression is successful EFI_SUCCESS - Decompression is successful
EFI_INVALID_PARAMETER - The source data is corrupted EFI_INVALID_PARAMETER - The source data is corrupted
--*/ --*/
; ;
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
TianoDecompress( TianoDecompress(
const VOID *Source, const VOID *Source,
UINT32 SrcSize, UINT32 SrcSize,
VOID *Destination, VOID *Destination,
UINT32 DstSize, UINT32 DstSize,
VOID *Scratch, VOID *Scratch,
UINT32 ScratchSize UINT32 ScratchSize
) )
/*++ /*++
Routine Description: Routine Description:
The implementation is same as that of EFI_TIANO_DECOMPRESS_PROTOCOL.Decompress(). The implementation is same as that of EFI_TIANO_DECOMPRESS_PROTOCOL.Decompress().
Arguments: Arguments:
This - The protocol instance pointer Source - The source buffer containing the compressed data.
Source - The source buffer containing the compressed data. SrcSize - The size of source buffer
SrcSize - The size of source buffer Destination - The destination buffer to store the decompressed data
Destination - The destination buffer to store the decompressed data DstSize - The size of destination buffer.
DstSize - The size of destination buffer. Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.
Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. ScratchSize - The size of scratch buffer.
ScratchSize - The size of scratch buffer.
Returns: Returns:
EFI_SUCCESS - Decompression is successful EFI_SUCCESS - Decompression is successful
EFI_INVALID_PARAMETER - The source data is corrupted EFI_INVALID_PARAMETER - The source data is corrupted
--*/ --*/
; ;
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif #endif // EFITIANODECOMPRESS_H

View file

@ -1,49 +0,0 @@
/* uefiextract.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 "uefiextract.h"
UEFIExtract::UEFIExtract(QObject *parent) :
QObject(parent)
{
ffsEngine = new FfsEngine(this);
}
UEFIExtract::~UEFIExtract()
{
delete ffsEngine;
}
UINT8 UEFIExtract::init(const QString & path)
{
fileInfo = QFileInfo(path);
if (!fileInfo.exists())
return ERR_FILE_OPEN;
QFile inputFile;
inputFile.setFileName(path);
if (!inputFile.open(QFile::ReadOnly))
return ERR_FILE_OPEN;
QByteArray buffer = inputFile.readAll();
inputFile.close();
return ffsEngine->parseImageFile(buffer);
}
UINT8 UEFIExtract::extract(QString guid)
{
return ffsEngine->dump(ffsEngine->treeModel()->index(0, 0), fileInfo.fileName().append(".dump"), guid);
}

View file

@ -1,43 +0,0 @@
/* uefiextract.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 __UEFIEXTRACT_H__
#define __UEFIEXTRACT_H__
#include <QObject>
#include <QByteArray>
#include <QString>
#include <QDir>
#include <QFileInfo>
#include "../basetypes.h"
#include "../ffsengine.h"
class UEFIExtract : public QObject
{
Q_OBJECT
public:
explicit UEFIExtract(QObject *parent = 0);
~UEFIExtract();
UINT8 init(const QString & path);
UINT8 extract(QString guid = QString());
private:
FfsEngine* ffsEngine;
QFileInfo fileInfo;
};
#endif

View file

@ -1,60 +0,0 @@
/* uefiextract_main.cpp
Copyright (c) 2015, 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 "uefiextract.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
a.setOrganizationName("CodeRush");
a.setOrganizationDomain("coderush.me");
a.setApplicationName("UEFIExtract");
UEFIExtract w;
UINT8 result = ERR_SUCCESS;
UINT32 returned = 0;
if (a.arguments().length() > 32) {
std::cout << "Too many arguments" << std::endl;
return 1;
}
if (a.arguments().length() > 1 ) {
if (w.init(a.arguments().at(1)))
return 1;
if (a.arguments().length() == 2) {
result = w.extract();
if (result)
return 2;
}
else {
for (int i = 2; i < a.arguments().length(); i++) {
result = w.extract(a.arguments().at(i));
if (result)
returned |= (1 << (i - 1));
}
return returned;
}
}
else {
std::cout << "UEFIExtract 0.4.4" << std::endl << std::endl <<
"Usage: uefiextract imagefile [FileGUID_1 FileGUID_2 ... FileGUID_31]" << std::endl <<
"Returned value is a bit mask where 0 on position N meant File with GUID_N was found and unpacked, 1 otherwise" << std::endl;
return 1;
}
}

View file

@ -1,160 +0,0 @@
/* uefifind.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 "uefifind.h"
UEFIFind::UEFIFind(QObject *parent) :
QObject(parent)
{
ffsEngine = new FfsEngine(this);
model = ffsEngine->treeModel();
initDone = false;
}
UEFIFind::~UEFIFind()
{
model = NULL;
delete ffsEngine;
}
UINT8 UEFIFind::init(const QString & path)
{
UINT8 result;
fileInfo = QFileInfo(path);
if (!fileInfo.exists())
return ERR_FILE_OPEN;
QFile inputFile;
inputFile.setFileName(path);
if (!inputFile.open(QFile::ReadOnly))
return ERR_FILE_OPEN;
QByteArray buffer = inputFile.readAll();
inputFile.close();
result = ffsEngine->parseImageFile(buffer);
if (result)
return result;
initDone = true;
return ERR_SUCCESS;
}
QString UEFIFind::guidToQString(const UINT8* guid)
{
const UINT32 u32 = *(const UINT32*)guid;
const UINT16 u16_1 = *(const UINT16*)(guid + 4);
const UINT16 u16_2 = *(const UINT16*)(guid + 6);
const UINT8 u8_1 = *(const UINT8*)(guid + 8);
const UINT8 u8_2 = *(const UINT8*)(guid + 9);
const UINT8 u8_3 = *(const UINT8*)(guid + 10);
const UINT8 u8_4 = *(const UINT8*)(guid + 11);
const UINT8 u8_5 = *(const UINT8*)(guid + 12);
const UINT8 u8_6 = *(const UINT8*)(guid + 13);
const UINT8 u8_7 = *(const UINT8*)(guid + 14);
const UINT8 u8_8 = *(const UINT8*)(guid + 15);
return QString("%1-%2-%3-%4%5-%6%7%8%9%10%11").hexarg2(u32, 8).hexarg2(u16_1, 4).hexarg2(u16_2, 4).hexarg2(u8_1, 2).hexarg2(u8_2, 2)
.hexarg2(u8_3, 2).hexarg2(u8_4, 2).hexarg2(u8_5, 2).hexarg2(u8_6, 2).hexarg2(u8_7, 2).hexarg2(u8_8, 2);
}
UINT8 UEFIFind::find(const UINT8 mode, const bool count, const QString & hexPattern, QString & result)
{
QModelIndex root = model->index(0, 0);
QSet<QPair<QModelIndex, QModelIndex> > files;
result.clear();
UINT8 returned = findFileRecursive(root, hexPattern, mode, files);
if (returned)
return returned;
if (count) {
if (files.count())
result.append(QString("%1\n").arg(files.count()));
return ERR_SUCCESS;
}
QPair<QModelIndex, QModelIndex> indexes;
Q_FOREACH(indexes, files) {
QByteArray data = model->header(indexes.first).left(16);
result.append(guidToQString((const UINT8*)data.constData()));
// Special case of freeform subtype GUID files
if (indexes.second.isValid() && model->subtype(indexes.second) == EFI_SECTION_FREEFORM_SUBTYPE_GUID) {
data = model->header(indexes.second).left(sizeof(EFI_FREEFORM_SUBTYPE_GUID_SECTION));
result.append(" ").append(guidToQString((const UINT8*)data.constData() + sizeof(EFI_COMMON_SECTION_HEADER)));
}
result.append("\n");
}
return ERR_SUCCESS;
}
UINT8 UEFIFind::findFileRecursive(const QModelIndex index, const QString & hexPattern, const UINT8 mode, QSet<QPair<QModelIndex, QModelIndex> > & files)
{
if (!index.isValid())
return ERR_SUCCESS;
if (hexPattern.isEmpty())
return ERR_INVALID_PARAMETER;
// Check for "all substrings" pattern
if (hexPattern.count('.') == hexPattern.length())
return ERR_SUCCESS;
bool hasChildren = (model->rowCount(index) > 0);
for (int i = 0; i < model->rowCount(index); i++) {
findFileRecursive(index.child(i, index.column()), hexPattern, mode, files);
}
QByteArray data;
if (hasChildren) {
if (mode == SEARCH_MODE_HEADER || mode == SEARCH_MODE_ALL)
data.append(model->header(index));
}
else {
if (mode == SEARCH_MODE_HEADER)
data.append(model->header(index));
else if (mode == SEARCH_MODE_BODY)
data.append(model->body(index));
else
data.append(model->header(index)).append(model->body(index));
}
QString hexBody = QString(data.toHex());
QRegExp regexp = QRegExp(QString(hexPattern), Qt::CaseInsensitive);
INT32 offset = regexp.indexIn(hexBody);
while (offset >= 0) {
if (offset % 2 == 0) {
if (model->type(index) != Types::File) {
QModelIndex ffs = model->findParentOfType(index, Types::File);
if (model->type(index) == Types::Section && model->subtype(index) == EFI_SECTION_FREEFORM_SUBTYPE_GUID)
files.insert(QPair<QModelIndex, QModelIndex>(ffs, index));
else
files.insert(QPair<QModelIndex, QModelIndex>(ffs, QModelIndex()));
}
else
files.insert(QPair<QModelIndex, QModelIndex>(index, QModelIndex()));
break;
}
offset = regexp.indexIn(hexBody, offset + 1);
}
return ERR_SUCCESS;
}

View file

@ -1,43 +0,0 @@
QT += core
QT -= gui
TARGET = UEFIFind
TEMPLATE = app
CONFIG += console
CONFIG -= app_bundle
DEFINES += _CONSOLE _DISABLE_ENGINE_MESSAGES
SOURCES += uefifind_main.cpp \
uefifind.cpp \
../types.cpp \
../descriptor.cpp \
../ffs.cpp \
../ffsengine.cpp \
../peimage.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 \
../Tiano/EfiTianoCompressLegacy.c
HEADERS += uefifind.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

View file

@ -1,72 +0,0 @@
/* uefifind_main.cpp
Copyright (c) 2015, 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 <iostream>
#include "uefifind.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
a.setOrganizationName("CodeRush");
a.setOrganizationDomain("coderush.me");
a.setApplicationName("UEFIFind");
UEFIFind w;
UINT8 result;
if (a.arguments().length() == 5) {
result = w.init(a.arguments().at(4));
if (result)
return result;
// Get search mode
UINT8 mode;
if (a.arguments().at(1) == QString("header"))
mode = SEARCH_MODE_HEADER;
else if (a.arguments().at(1) == QString("body"))
mode = SEARCH_MODE_BODY;
else if (a.arguments().at(1) == QString("all"))
mode = SEARCH_MODE_ALL;
else
return ERR_INVALID_PARAMETER;
// Get result type
bool count;
if (a.arguments().at(2) == QString("list"))
count = false;
else if (a.arguments().at(2) == QString("count"))
count = true;
else
return ERR_INVALID_PARAMETER;
// Go find the supplied pattern
QString found;
result = w.find(mode, count, a.arguments().at(3), found);
if (result)
return result;
// Nothing was found
if (found.isEmpty())
return ERR_ITEM_NOT_FOUND;
// Print result
std::cout << found.toStdString();
return ERR_SUCCESS;
}
else {
std::cout << "UEFIFind 0.3.4" << std::endl << std::endl <<
"Usage: uefifind {header | body | all} {list | count} pattern imagefile\n";
return ERR_INVALID_PARAMETER;
}
}

View 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

View file

@ -34,9 +34,26 @@ F7731B4C-58A2-4DF4-8980-5645D39ECE58 10 P:0FBA6C24380F:0FBA7424380F
# PowerManagement | Sandy Bridge with ME 8.xx, Ivy Bridge # PowerManagement | Sandy Bridge with ME 8.xx, Ivy Bridge
8C783970-F02A-4A4D-AF09-8797A51EEC8D 10 P:75080FBAE80F89442430:EB080FBAE80F89442430 8C783970-F02A-4A4D-AF09-8797A51EEC8D 10 P:75080FBAE80F89442430:EB080FBAE80F89442430
# PowerManagement | New SB-E/IB-E # PowerManagement | New SB-E/IB-E
8C783970-F02A-4A4D-AF09-8797A51EEC8D 10 P:0FBA6C24380F:0FBA7424380F 8C783970-F02A-4A4D-AF09-8797A51EEC8D 10 P:0FBA6C24380F:0FBA7424380F
# CpuPei | Sandy Bridge with ME 7.xx, old SB-E/IB-E # CpuPei | Sandy Bridge with ME 7.xx, old SB-E/IB-E
2BB5AFA9-FF33-417B-8497-CB773C2B93BF 10 P:800018EB050D0080:000018EB050D0000 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

View file

@ -25,15 +25,15 @@ UEFIPatch::~UEFIPatch()
delete ffsEngine; delete ffsEngine;
} }
UINT8 UEFIPatch::patchFromFile(QString path) UINT8 UEFIPatch::patchFromFile(const QString & path, const QString & patches, const QString & outputPath)
{ {
QFileInfo patchInfo = QFileInfo("patches.txt"); QFileInfo patchInfo = QFileInfo(patches);
if (!patchInfo.exists()) if (!patchInfo.exists())
return ERR_INVALID_FILE; return ERR_INVALID_FILE;
QFile file; QFile file;
file.setFileName("patches.txt"); file.setFileName(patches);
if (!file.open(QFile::ReadOnly | QFile::Text)) if (!file.open(QFile::ReadOnly | QFile::Text))
return ERR_INVALID_FILE; return ERR_INVALID_FILE;
@ -110,7 +110,7 @@ UINT8 UEFIPatch::patchFromFile(QString path)
return ERR_NOTHING_TO_PATCH; return ERR_NOTHING_TO_PATCH;
QFile outputFile; QFile outputFile;
outputFile.setFileName(path.append(".patched")); outputFile.setFileName(outputPath);
if (!outputFile.open(QFile::WriteOnly)) if (!outputFile.open(QFile::WriteOnly))
return ERR_FILE_WRITE; return ERR_FILE_WRITE;

View file

@ -33,9 +33,7 @@ public:
explicit UEFIPatch(QObject *parent = 0); explicit UEFIPatch(QObject *parent = 0);
~UEFIPatch(); ~UEFIPatch();
UINT8 patchFromFile(QString path); UINT8 patchFromFile(const QString & path, const QString & patches, const QString & outputPath);
UINT8 patch(QString path, QString fileGuid, QString findPattern, QString replacePattern);
private: private:
UINT8 patchFile(const QModelIndex & index, const QByteArray & fileGuid, const UINT8 sectionType, const QVector<PatchData> & patches); UINT8 patchFile(const QModelIndex & index, const QByteArray & fileGuid, const UINT8 sectionType, const QVector<PatchData> & patches);
FfsEngine* ffsEngine; FfsEngine* ffsEngine;

View file

@ -36,6 +36,7 @@ HEADERS += uefipatch.h \
../ffsengine.h \ ../ffsengine.h \
../treeitem.h \ ../treeitem.h \
../treemodel.h \ ../treemodel.h \
../version.h \
../LZMA/LzmaCompress.h \ ../LZMA/LzmaCompress.h \
../LZMA/LzmaDecompress.h \ ../LZMA/LzmaDecompress.h \
../Tiano/EfiTianoDecompress.h \ ../Tiano/EfiTianoDecompress.h \

View file

@ -1,6 +1,6 @@
/* uefipatch_main.cpp /* uefipatch_main.cpp
Copyright (c) 2015, Nikolaj Schlej. All rights reserved. Copyright (c) 2018, LongSoft. All rights reserved.
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
@ -14,29 +14,48 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <QString> #include <QString>
#include <QStringList> #include <QStringList>
#include <iostream> #include <iostream>
#include <string>
#include "../version.h"
#include "uefipatch.h" #include "uefipatch.h"
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
QCoreApplication a(argc, argv); QCoreApplication a(argc, argv);
a.setOrganizationName("CodeRush"); a.setOrganizationName("LongSoft");
a.setOrganizationDomain("coderush.me"); a.setOrganizationDomain("longsoft.me");
a.setApplicationName("UEFIPatch"); a.setApplicationName("UEFIPatch");
UEFIPatch w; UEFIPatch w;
UINT8 result = ERR_SUCCESS; UINT8 result = ERR_SUCCESS;
UINT32 argumentsCount = a.arguments().length(); const QStringList &args = a.arguments();
UINT32 argumentsCount = args.length();
if (argumentsCount == 2) {
result = w.patchFromFile(a.arguments().at(1)); if (argumentsCount < 2) {
} std::cout << "UEFIPatch " PROGRAM_VERSION " - UEFI image file patching utility" << std::endl << std::endl <<
else { "Usage: UEFIPatch image_file [patches.txt] [-o output]" << std::endl << std::endl <<
std::cout << "UEFIPatch 0.3.4 - UEFI image file patching utility" << std::endl << std::endl << "Patches will be read from patches.txt file by default\n";
"Usage: UEFIPatch image_file" << std::endl << std::endl <<
"Patches will be read from patches.txt file\n";
return ERR_SUCCESS; return ERR_SUCCESS;
} }
QString inputPath = a.arguments().at(1);
QString patches = "patches.txt";
QString outputPath = inputPath + ".patched";
for (UINT32 i = 2; i < argumentsCount; i++) {
if ((args.at(i) == "-o" || args.at(i) == "--output") && i + 1 < argumentsCount) {
outputPath = args.at(i+1);
i++;
} else if (patches == "patches.txt") {
patches = args.at(i);
} else {
result = ERR_INVALID_PARAMETER;
}
}
if (result == ERR_SUCCESS) {
result = w.patchFromFile(inputPath, patches, outputPath);
}
switch (result) { switch (result) {
case ERR_SUCCESS: case ERR_SUCCESS:
std::cout << "Image patched" << std::endl; std::cout << "Image patched" << std::endl;
@ -57,7 +76,7 @@ int main(int argc, char *argv[])
std::cout << "Pattern format mismatch" << std::endl; 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.toStdString() << " file not found or can't be read" << std::endl;
break; break;
case ERR_FILE_OPEN: case ERR_FILE_OPEN:
std::cout << "Input file not found" << std::endl; std::cout << "Input file not found" << std::endl;

122
UEFIReplace/uefireplace.cpp Normal file
View file

@ -0,0 +1,122 @@
/* 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;
}
UINT8 UEFIReplace::replace(const QString & inPath, const QByteArray & guid, const UINT8 sectionType, const QString & contentPath, const QString & outPath, bool replaceAsIs, bool replaceOnce)
{
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();
result = replaceInFile(model->index(0, 0), guid, sectionType, contents,
replaceAsIs ? REPLACE_MODE_AS_IS : REPLACE_MODE_BODY, replaceOnce);
if (result)
return result;
QByteArray reconstructed;
result = ffsEngine->reconstructImageFile(reconstructed);
if (result)
return result;
if (reconstructed == buffer)
return ERR_NOTHING_TO_PATCH;
QFile outputFile;
outputFile.setFileName(outPath);
if (!outputFile.open(QFile::WriteOnly))
return ERR_FILE_WRITE;
outputFile.resize(0);
outputFile.write(reconstructed);
outputFile.close();
return ERR_SUCCESS;
}
UINT8 UEFIReplace::replaceInFile(const QModelIndex & index, const QByteArray & guid, const UINT8 sectionType, const QByteArray & newData, const UINT8 mode, bool replaceOnce)
{
if (!model || !index.isValid())
return ERR_INVALID_PARAMETER;
bool patched = false;
if (model->subtype(index) == sectionType) {
QModelIndex fileIndex = index;
if (model->type(index) != Types::File)
fileIndex = model->findParentOfType(index, Types::File);
QByteArray fileGuid = model->header(fileIndex).left(sizeof(EFI_GUID));
bool guidMatch = fileGuid == guid;
if (!guidMatch && sectionType == EFI_SECTION_FREEFORM_SUBTYPE_GUID) {
QByteArray subGuid = model->header(index).mid(sizeof(UINT32), sizeof(EFI_GUID));
guidMatch = subGuid == guid;
}
if (guidMatch && model->action(index) != Actions::Replace) {
UINT8 result = ffsEngine->replace(index, newData, mode);
if (replaceOnce || (result != ERR_SUCCESS && result != ERR_NOTHING_TO_PATCH))
return result;
patched = result == ERR_SUCCESS;
}
}
if (model->rowCount(index) > 0) {
for (int i = 0; i < model->rowCount(index); i++) {
UINT8 result = replaceInFile(index.child(i, 0), guid, sectionType, newData, mode, replaceOnce);
if (result == ERR_SUCCESS) {
patched = true;
if (replaceOnce)
break;
} else if (result != ERR_NOTHING_TO_PATCH) {
return result;
}
}
}
return patched ? ERR_SUCCESS : ERR_NOTHING_TO_PATCH;
}

View file

@ -1,52 +1,41 @@
/* uefifind.h /* uefireplace.h
Copyright (c) 2017, mxxxc. All rights reserved.
Copyright (c) 2014, Nikolaj Schlej. All rights reserved.
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,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*/ */
#ifndef __UEFIFIND_H__ #ifndef __UEFIREPLACE_H__
#define __UEFIFIND_H__ #define __UEFIREPLACE_H__
#include <QObject> #include <QObject>
#include <QByteArray> #include <QByteArray>
#include <QString> #include <QString>
#include <QDir> #include <QStringList>
#include <QFileInfo> #include <QFileInfo>
#include <QPair>
#include <QSet>
#include <QString>
#include <QUuid> #include <QUuid>
#include "../basetypes.h" #include "../basetypes.h"
#include "../ffsengine.h"
#include "../ffs.h" #include "../ffs.h"
#include "../ffsengine.h"
class UEFIFind : public QObject class UEFIReplace : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit UEFIFind(QObject *parent = 0); explicit UEFIReplace(QObject *parent = 0);
~UEFIFind(); ~UEFIReplace();
UINT8 init(const QString & path); UINT8 replace(const QString & inPath, const QByteArray & guid, const UINT8 sectionType, const QString & contentPath, const QString & outPath, bool replaceAsIs, bool replaceOnce);
UINT8 find(const UINT8 mode, const bool count, const QString & hexPattern, QString & result);
private: private:
UINT8 findFileRecursive(const QModelIndex index, const QString & hexPattern, const UINT8 mode, QSet<QPair<QModelIndex, QModelIndex> > & files); UINT8 replaceInFile(const QModelIndex & index, const QByteArray & guid, const UINT8 sectionType, const QByteArray & contents, const UINT8 mode, bool replaceOnce);
QString guidToQString(const UINT8* guid);
FfsEngine* ffsEngine; FfsEngine* ffsEngine;
TreeModel* model; TreeModel* model;
QFileInfo fileInfo;
bool initDone;
}; };
#endif #endif

View file

@ -1,14 +1,14 @@
QT += core QT += core
QT -= gui QT -= gui
TARGET = UEFIExtract TARGET = UEFIReplace
TEMPLATE = app TEMPLATE = app
CONFIG += console CONFIG += console
CONFIG -= app_bundle CONFIG -= app_bundle
DEFINES += _CONSOLE DEFINES += _CONSOLE
SOURCES += uefiextract_main.cpp \ SOURCES += uefireplace_main.cpp \
uefiextract.cpp \ uefireplace.cpp \
../types.cpp \ ../types.cpp \
../descriptor.cpp \ ../descriptor.cpp \
../ffs.cpp \ ../ffs.cpp \
@ -25,7 +25,7 @@ SOURCES += uefiextract_main.cpp \
../Tiano/EfiTianoCompress.c \ ../Tiano/EfiTianoCompress.c \
../Tiano/EfiTianoCompressLegacy.c ../Tiano/EfiTianoCompressLegacy.c
HEADERS += uefiextract.h \ HEADERS += uefireplace.h \
../basetypes.h \ ../basetypes.h \
../descriptor.h \ ../descriptor.h \
../gbe.h \ ../gbe.h \
@ -36,8 +36,8 @@ HEADERS += uefiextract.h \
../ffsengine.h \ ../ffsengine.h \
../treeitem.h \ ../treeitem.h \
../treemodel.h \ ../treemodel.h \
../version.h \
../LZMA/LzmaCompress.h \ ../LZMA/LzmaCompress.h \
../LZMA/LzmaDecompress.h \ ../LZMA/LzmaDecompress.h \
../Tiano/EfiTianoDecompress.h \ ../Tiano/EfiTianoDecompress.h \
../Tiano/EfiTianoCompress.h ../Tiano/EfiTianoCompress.h

View file

@ -0,0 +1,98 @@
/* uefireplace_main.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 <QCoreApplication>
#include <QString>
#include <QStringList>
#include <iostream>
#include "../version.h"
#include "uefireplace.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
a.setOrganizationName("LongSoft");
a.setOrganizationDomain("longsoft.me");
a.setApplicationName("UEFIReplace");
UEFIReplace r;
UINT8 result = ERR_SUCCESS;
QStringList args = a.arguments();
if (args.length() < 5) {
std::cout << "UEFIReplace " PROGRAM_VERSION " - UEFI image file replacement utility" << std::endl << std::endl <<
"Usage: UEFIReplace image_file guid section_type contents_file [-o output] [-all] [-asis]" << std::endl;
return ERR_SUCCESS;
}
QUuid uuid = QUuid(args.at(2));
QByteArray guid = QByteArray::fromRawData((const char*)&uuid.data1, sizeof(EFI_GUID));
bool converted;
UINT8 sectionType = (UINT8)args.at(3).toUShort(&converted, 16);
if (!converted) {
result = ERR_INVALID_PARAMETER;
} else {
QString output = args.at(1) + ".patched";
bool replaceOnce = true;
bool replaceAsIs = false;
for (int i = 5, sz = args.size(); i < sz; i++) {
if ((args.at(i) == "-o" || args.at(i) == "--output") && i + 1 < sz) {
output = args.at(i+1);
i++;
} else if (args.at(i) == "-all") {
replaceOnce = false;
} else if (args.at(i) == "-asis") {
replaceAsIs = true;
} else {
result = ERR_INVALID_PARAMETER;
}
}
if (result == ERR_SUCCESS) {
result = r.replace(args.at(1), guid, sectionType, args.at(4), output, replaceAsIs, replaceOnce);
}
}
switch (result) {
case ERR_SUCCESS:
std::cout << "File replaced" << std::endl;
break;
case ERR_INVALID_PARAMETER:
std::cout << "Function called with invalid parameter" << std::endl;
break;
case ERR_INVALID_FILE:
std::cout << "Invalid/corrupted file specified" << std::endl;
break;
case ERR_INVALID_SECTION:
std::cout << "Invalid/corrupted section specified" << std::endl;
break;
case ERR_NOTHING_TO_PATCH:
std::cout << "No replacements can be applied to input file" << std::endl;
break;
case ERR_NOT_IMPLEMENTED:
std::cout << "Can't replace body of this section type" << 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;
}

View file

@ -16,6 +16,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <stdarg.h> #include <stdarg.h>
#include <stdint.h> #include <stdint.h>
#include <stddef.h>
typedef uint8_t BOOLEAN; typedef uint8_t BOOLEAN;
typedef int8_t INT8; typedef int8_t INT8;
@ -28,7 +29,7 @@ typedef int64_t INT64;
typedef uint64_t UINT64; typedef uint64_t UINT64;
typedef char CHAR8; typedef char CHAR8;
typedef uint16_t CHAR16; typedef uint16_t CHAR16;
typedef unsigned int UINTN; typedef size_t UINTN;
#define CONST const #define CONST const
#define VOID void #define VOID void
@ -85,6 +86,8 @@ typedef unsigned int UINTN;
#define ERR_INVALID_SYMBOL 40 #define ERR_INVALID_SYMBOL 40
#define ERR_NOTHING_TO_PATCH 41 #define ERR_NOTHING_TO_PATCH 41
#define ERR_DEPEX_PARSE_FAILED 42 #define ERR_DEPEX_PARSE_FAILED 42
#define ERR_TRUNCATED_IMAGE 43
#define ERR_BAD_RELOCATION_ENTRY 44
#define ERR_NOT_IMPLEMENTED 0xFF #define ERR_NOT_IMPLEMENTED 0xFF
// UDK porting definitions // UDK porting definitions

View file

@ -17,11 +17,11 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "basetypes.h" #include "basetypes.h"
// Make sure we use right packing rules // Make sure we use right packing rules
#pragma pack(push,1) #pragma pack(push, 1)
// Flash descriptor header // Flash descriptor header
typedef struct _FLASH_DESCRIPTOR_HEADER { typedef struct _FLASH_DESCRIPTOR_HEADER {
UINT8 FfVector[16]; // Must be 16 0xFFs UINT8 FfVector[16]; // Must be 16 0xFFs
UINT32 Signature; // 0x0FF0A55A UINT32 Signature; // 0x0FF0A55A
} FLASH_DESCRIPTOR_HEADER; } FLASH_DESCRIPTOR_HEADER;
@ -31,40 +31,59 @@ typedef struct _FLASH_DESCRIPTOR_HEADER {
// Descriptor region size // Descriptor region size
#define FLASH_DESCRIPTOR_SIZE 0x1000 #define FLASH_DESCRIPTOR_SIZE 0x1000
// Descriptor version was reserved in older firmware
#define FLASH_DESCRIPTOR_VERSION_INVALID 0xFFFFFFFF
// The only known version found in Coffee Lake
#define FLASH_DESCRIPTOR_VERSION_MAJOR 1
#define FLASH_DESCRIPTOR_VERSION_MINOR 0
// Descriptor version present in Coffee Lake and newer
typedef struct _FLASH_DESCRIPTOR_VERSION {
UINT32 Reserved : 14;
UINT32 Minor : 7;
UINT32 Major : 11;
} FLASH_DESCRIPTOR_VERSION;
// Descriptor map // Descriptor map
// Base fields are storing bits [11:4] of actual base addresses, all other bits are 0 // Base fields are storing bits [11:4] of actual base addresses, all other bits are 0
typedef struct _FLASH_DESCRIPTOR_MAP { typedef struct _FLASH_DESCRIPTOR_MAP {
UINT8 ComponentBase; // 0x03 on most machines // FLMAP0
UINT8 NumberOfFlashChips; // Zero-based number of flash chips installed on board UINT32 ComponentBase : 8;
UINT8 RegionBase; // 0x04 on most machines UINT32 NumberOfFlashChips : 2; // Zero-based number of flash chips installed on board
UINT8 NumberOfRegions; // Zero-based number of flash regions (descriptor is always included) UINT32 : 6;
UINT8 MasterBase; // 0x06 on most machines UINT32 RegionBase : 8;
UINT8 NumberOfMasters; // Zero-based number of flash masters UINT32 NumberOfRegions : 3; // Reserved in v2 descriptor
UINT8 PchStrapsBase; // 0x10 on most machines UINT32 : 5;
UINT8 NumberOfPchStraps; // One-based number of UINT32s to read as PCH Straps, min=0, max=255 (1 Kb) // FLMAP 1
UINT8 ProcStrapsBase; // 0x20 on most machines UINT32 MasterBase : 8;
UINT8 NumberOfProcStraps; // Number of PROC straps to be read, can be 0 or 1 UINT32 NumberOfMasters : 2; // Zero-based number of flash masters
UINT8 IccTableBase; // 0x21 on most machines UINT32 : 6;
UINT8 NumberOfIccTableEntries; // 0x00 on most machines UINT32 PchStrapsBase : 8;
UINT8 DmiTableBase; // 0x25 on most machines UINT32 NumberOfPchStraps : 8; // One-based number of UINT32s to read as PCH straps, min=0, max=255 (1 Kb)
UINT8 NumberOfDmiTableEntries; // 0x00 on most machines // FLMAP 2
UINT16 ReservedZero; // Still unknown, zeros in all descriptors I have seen UINT32 ProcStrapsBase : 8;
UINT32 NumberOfProcStraps : 8; // One-based number of UINT32s to read as processor straps, min=0, max=255 (1 Kb)
UINT32: 16;
// FLMAP 3
UINT32 DescriptorVersion; // Reserved prior to Coffee Lake
} FLASH_DESCRIPTOR_MAP; } FLASH_DESCRIPTOR_MAP;
#define FLASH_DESCRIPTOR_MAX_BASE 0xE0
// Component section // Component section
// Flash parameters DWORD structure // Flash parameters DWORD structure
typedef struct _FLASH_PARAMETERS { typedef struct _FLASH_PARAMETERS {
UINT8 FirstChipDensity : 3; UINT8 FirstChipDensity : 4;
UINT8 SecondChipDensity : 3; UINT8 SecondChipDensity : 4;
UINT8 ReservedZero0 : 2; // Still unknown, zeros in all descriptors I have seen UINT8 : 8;
UINT8 ReservedZero1 : 8; // Still unknown, zeros in all descriptors I have seen UINT8 : 1;
UINT8 ReservedZero2 : 4; // Still unknown, zeros in all descriptors I have seen UINT8 ReadClockFrequency : 3; // Hardcoded value of 20 Mhz (000b) in v1 descriptors and 17 Mhz (110b) in v2 ones
UINT8 FastReadEnabled : 1; UINT8 FastReadEnabled : 1;
UINT8 FastReadFreqency : 3; UINT8 FastReadFrequency : 3;
UINT8 FlashReadStatusFrequency : 3;
UINT8 FlashWriteFrequency : 3; UINT8 FlashWriteFrequency : 3;
UINT8 FlashReadStatusFrequency : 3;
UINT8 DualOutputFastReadSupported : 1; UINT8 DualOutputFastReadSupported : 1;
UINT8 ReservedZero3 : 1; // Still unknown, zero in all descriptors I have seen UINT8 : 1;
} FLASH_PARAMETERS; } FLASH_PARAMETERS;
// Flash densities // Flash densities
@ -74,11 +93,16 @@ typedef struct _FLASH_PARAMETERS {
#define FLASH_DENSITY_4MB 0x03 #define FLASH_DENSITY_4MB 0x03
#define FLASH_DENSITY_8MB 0x04 #define FLASH_DENSITY_8MB 0x04
#define FLASH_DENSITY_16MB 0x05 #define FLASH_DENSITY_16MB 0x05
#define FLASH_DENSITY_32MB 0x06
#define FLASH_DENSITY_64MB 0x07
#define FLASH_DENSITY_UNUSED 0x0F
// Flash frequencies // Flash frequencies
#define FLASH_FREQUENCY_20MHZ 0x00 #define FLASH_FREQUENCY_20MHZ 0x00
#define FLASH_FREQUENCY_33MHZ 0x01 #define FLASH_FREQUENCY_33MHZ 0x01
#define FLASH_FREQUENCY_50MHZ 0x04 #define FLASH_FREQUENCY_48MHZ 0x02
#define FLASH_FREQUENCY_50MHZ_30MHZ 0x04
#define FLASH_FREQUENCY_17MHZ 0x06
// Component section structure // Component section structure
typedef struct _FLASH_DESCRIPTOR_COMPONENT_SECTION { typedef struct _FLASH_DESCRIPTOR_COMPONENT_SECTION {
@ -87,52 +111,82 @@ typedef struct _FLASH_DESCRIPTOR_COMPONENT_SECTION {
UINT8 InvalidInstruction1; // UINT8 InvalidInstruction1; //
UINT8 InvalidInstruction2; // UINT8 InvalidInstruction2; //
UINT8 InvalidInstruction3; // UINT8 InvalidInstruction3; //
UINT16 PartitionBoundary; // Upper 16 bit of partition boundary address. Default is 0x0000, which makes the boundary to be 0x00001000
UINT16 ReservedZero; // Still unknown, zero in all descriptors I have seen
} FLASH_DESCRIPTOR_COMPONENT_SECTION; } FLASH_DESCRIPTOR_COMPONENT_SECTION;
// Component section structure
typedef struct _FLASH_DESCRIPTOR_COMPONENT_SECTION_V2 {
FLASH_PARAMETERS FlashParameters;
UINT8 InvalidInstruction0; // Instructions for SPI chip, that must not be executed, like FLASH ERASE
UINT8 InvalidInstruction1; //
UINT8 InvalidInstruction2; //
UINT8 InvalidInstruction3; //
UINT8 InvalidInstruction4; //
UINT8 InvalidInstruction5; //
UINT8 InvalidInstruction6; //
UINT8 InvalidInstruction7; //
} FLASH_DESCRIPTOR_COMPONENT_SECTION_V2;
// Region section // Region section
// All base and limit register are storing upper part of actual UINT32 base and limit // All base and limit register are storing upper part of actual UINT32 base and limit
// If limit is zero - region is not present // If limit is zero - region is not present
typedef struct _FLASH_DESCRIPTOR_REGION_SECTION { typedef struct _FLASH_DESCRIPTOR_REGION_SECTION {
UINT16 ReservedZero; // Still unknown, zero in all descriptors I have seen UINT16 DescriptorBase; // Descriptor
UINT16 FlashBlockEraseSize; // Size of block erased by single BLOCK ERASE command UINT16 DescriptorLimit; //
UINT16 BiosBase; UINT16 BiosBase; // BIOS
UINT16 BiosLimit; UINT16 BiosLimit; //
UINT16 MeBase; UINT16 MeBase; // ME
UINT16 MeLimit; UINT16 MeLimit; //
UINT16 GbeBase; UINT16 GbeBase; // GbE
UINT16 GbeLimit; UINT16 GbeLimit; //
UINT16 PdrBase; UINT16 PdrBase; // PDR
UINT16 PdrLimit; UINT16 PdrLimit; //
UINT16 Region5Base; // Reserved region
UINT16 Region5Limit; //
UINT16 Region6Base; // Reserved region
UINT16 Region6Limit; //
UINT16 Region7Base; // Reserved region
UINT16 Region7Limit; //
UINT16 EcBase; // EC
UINT16 EcLimit; //
} FLASH_DESCRIPTOR_REGION_SECTION; } FLASH_DESCRIPTOR_REGION_SECTION;
// Flash block erase sizes
#define FLASH_BLOCK_ERASE_SIZE_4KB 0x0000
#define FLASH_BLOCK_ERASE_SIZE_8KB 0x0001
#define FLASH_BLOCK_ERASE_SIZE_64KB 0x000F
// Master section // Master section
typedef struct _FLASH_DESCRIPTOR_MASTER_SECTION { typedef struct _FLASH_DESCRIPTOR_MASTER_SECTION {
UINT16 BiosId; UINT16 BiosId;
UINT8 BiosRead; UINT8 BiosRead;
UINT8 BiosWrite; UINT8 BiosWrite;
UINT16 MeId; UINT16 MeId;
UINT8 MeRead; UINT8 MeRead;
UINT8 MeWrite; UINT8 MeWrite;
UINT16 GbeId; UINT16 GbeId;
UINT8 GbeRead; UINT8 GbeRead;
UINT8 GbeWrite; UINT8 GbeWrite;
} FLASH_DESCRIPTOR_MASTER_SECTION; } FLASH_DESCRIPTOR_MASTER_SECTION;
// Master section v2 (Skylake+)
typedef struct _FLASH_DESCRIPTOR_MASTER_SECTION_V2 {
UINT32 : 8;
UINT32 BiosRead : 12;
UINT32 BiosWrite : 12;
UINT32 : 8;
UINT32 MeRead : 12;
UINT32 MeWrite : 12;
UINT32 : 8;
UINT32 GbeRead : 12;
UINT32 GbeWrite : 12;
UINT32 :32;
UINT32 : 8;
UINT32 EcRead : 12;
UINT32 EcWrite : 12;
} FLASH_DESCRIPTOR_MASTER_SECTION_V2;
// Region access bits in master section // Region access bits in master section
#define FLASH_DESCRIPTOR_REGION_ACCESS_DESC 0x01 #define FLASH_DESCRIPTOR_REGION_ACCESS_DESC 0x01
#define FLASH_DESCRIPTOR_REGION_ACCESS_BIOS 0x02 #define FLASH_DESCRIPTOR_REGION_ACCESS_BIOS 0x02
#define FLASH_DESCRIPTOR_REGION_ACCESS_ME 0x04 #define FLASH_DESCRIPTOR_REGION_ACCESS_ME 0x04
#define FLASH_DESCRIPTOR_REGION_ACCESS_GBE 0x08 #define FLASH_DESCRIPTOR_REGION_ACCESS_GBE 0x08
#define FLASH_DESCRIPTOR_REGION_ACCESS_PDR 0x10 #define FLASH_DESCRIPTOR_REGION_ACCESS_PDR 0x10
#define FLASH_DESCRIPTOR_REGION_ACCESS_EC 0x20
//!TODO: Describe PCH and PROC straps sections, as well as ICC and DMI tables
// Base address of descriptor upper map // Base address of descriptor upper map
#define FLASH_DESCRIPTOR_UPPER_MAP_BASE 0x0EFC #define FLASH_DESCRIPTOR_UPPER_MAP_BASE 0x0EFC
@ -155,7 +209,7 @@ typedef struct _VSCC_TABLE_ENTRY {
// Base address and size of OEM section // Base address and size of OEM section
#define FLASH_DESCRIPTOR_OEM_SECTION_BASE 0x0F00 #define FLASH_DESCRIPTOR_OEM_SECTION_BASE 0x0F00
#define FLASH_DESCRIPTOR_OEM_SECTION_SIZE 0xFF #define FLASH_DESCRIPTOR_OEM_SECTION_SIZE 0x100
// Restore previous packing rules // Restore previous packing rules
#pragma pack(pop) #pragma pack(pop)

21
ffs.cpp
View file

@ -30,7 +30,10 @@ const QVector<QByteArray> FFSv3Volumes =
const UINT8 ffsAlignmentTable[] = const UINT8 ffsAlignmentTable[] =
{ 0, 4, 7, 9, 10, 12, 15, 16 }; { 0, 4, 7, 9, 10, 12, 15, 16 };
UINT8 calculateChecksum8(const UINT8* buffer, UINT32 bufferSize) const UINT8 ffsAlignment2Table[] =
{ 17, 18, 19, 20, 21, 22, 23, 24 };
UINT8 calculateSum8(const UINT8* buffer, UINT32 bufferSize)
{ {
if (!buffer) if (!buffer)
return 0; return 0;
@ -40,7 +43,15 @@ UINT8 calculateChecksum8(const UINT8* buffer, UINT32 bufferSize)
while (bufferSize--) while (bufferSize--)
counter += buffer[bufferSize]; counter += buffer[bufferSize];
return (UINT8)0x100 - counter; return counter;
}
UINT8 calculateChecksum8(const UINT8* buffer, UINT32 bufferSize)
{
if (!buffer)
return 0;
return (UINT8)0x100 - calculateSum8(buffer, bufferSize);
} }
UINT16 calculateChecksum16(const UINT16* buffer, UINT32 bufferSize) UINT16 calculateChecksum16(const UINT16* buffer, UINT32 bufferSize)
@ -120,6 +131,8 @@ QString fileTypeToQString(const UINT8 type)
case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE: return QObject::tr("Volume image"); case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE: return QObject::tr("Volume image");
case EFI_FV_FILETYPE_COMBINED_SMM_DXE: return QObject::tr("Combined SMM/DXE"); case EFI_FV_FILETYPE_COMBINED_SMM_DXE: return QObject::tr("Combined SMM/DXE");
case EFI_FV_FILETYPE_SMM_CORE: return QObject::tr("SMM core"); case EFI_FV_FILETYPE_SMM_CORE: return QObject::tr("SMM core");
case EFI_FV_FILETYPE_SMM_STANDALONE: return QObject::tr("SMM standalone");
case EFI_FV_FILETYPE_SMM_CORE_STANDALONE: return QObject::tr("SMM core standalone");
case EFI_FV_FILETYPE_PAD: return QObject::tr("Pad"); case EFI_FV_FILETYPE_PAD: return QObject::tr("Pad");
default: return QObject::tr("Unknown"); default: return QObject::tr("Unknown");
}; };
@ -156,9 +169,9 @@ UINT32 sizeOfSectionHeader(const EFI_COMMON_SECTION_HEADER* header)
return 0; return 0;
bool extended = false; bool extended = false;
/*if (uint24ToUint32(header->Size) == EFI_SECTION2_IS_USED) { if (uint24ToUint32(header->Size) == EFI_SECTION2_IS_USED) {
extended = true; extended = true;
}*/ }
switch (header->Type) switch (header->Type)
{ {

45
ffs.h
View file

@ -32,7 +32,7 @@ extern QString sectionTypeToQString(const UINT8 type);
//***************************************************************************** //*****************************************************************************
// EFI Capsule // EFI Capsule
//***************************************************************************** //*****************************************************************************
// Capsule header // Standard EFI Capsule header
typedef struct _EFI_CAPSULE_HEADER { typedef struct _EFI_CAPSULE_HEADER {
EFI_GUID CapsuleGuid; EFI_GUID CapsuleGuid;
UINT32 HeaderSize; UINT32 HeaderSize;
@ -49,16 +49,32 @@ typedef struct _EFI_CAPSULE_HEADER {
const QByteArray EFI_CAPSULE_GUID const QByteArray EFI_CAPSULE_GUID
("\xBD\x86\x66\x3B\x76\x0D\x30\x40\xB7\x0E\xB5\x51\x9E\x2F\xC5\xA0", 16); ("\xBD\x86\x66\x3B\x76\x0D\x30\x40\xB7\x0E\xB5\x51\x9E\x2F\xC5\xA0", 16);
// Intel capsule GUID
const QByteArray INTEL_CAPSULE_GUID
("\xB9\x82\x91\x53\xB5\xAB\x91\x43\xB6\x9A\xE3\xA9\x43\xF7\x2F\xCC", 16);
// Toshiba EFI Capsule header
typedef struct _TOSHIBA_CAPSULE_HEADER {
EFI_GUID CapsuleGuid;
UINT32 HeaderSize;
UINT32 FullSize;
UINT32 Flags;
} TOSHIBA_CAPSULE_HEADER;
// Toshiba capsule GUID
const QByteArray TOSHIBA_CAPSULE_GUID
("\x62\x70\xE0\x3B\x51\x1D\xD2\x45\x83\x2B\xF0\x93\x25\x7E\xD4\x61", 16);
// AMI Aptio extended capsule header // AMI Aptio extended capsule header
typedef struct _APTIO_CAPSULE_HEADER { typedef struct _APTIO_CAPSULE_HEADER {
EFI_CAPSULE_HEADER CapsuleHeader; EFI_CAPSULE_HEADER CapsuleHeader;
UINT16 RomImageOffset; // offset in bytes from the beginning of the capsule header to the start of UINT16 RomImageOffset; // offset in bytes from the beginning of the capsule header to the start of
// the capsule volume // the capsule volume
//!TODO: Enable certificate and ROM layout reading //!TODO: Enable certificate and ROM layout reading
//UINT16 RomLayoutOffset; // offset to the table of the module descriptors in the capsule's volume //UINT16 RomLayoutOffset; // offset to the table of the module descriptors in the capsule's volume
// that are included in the signature calculation // that are included in the signature calculation
//FW_CERTIFICATE FWCert; //FW_CERTIFICATE FWCert;
//ROM_AREA RomAreaMap[1]; //ROM_AREA RomAreaMap[1];
} APTIO_CAPSULE_HEADER; } APTIO_CAPSULE_HEADER;
// AMI Aptio signed extended capsule GUID // AMI Aptio signed extended capsule GUID
@ -93,7 +109,7 @@ typedef struct _EFI_FIRMWARE_VOLUME_HEADER {
UINT16 ExtHeaderOffset; //Reserved in Revision 1 UINT16 ExtHeaderOffset; //Reserved in Revision 1
UINT8 Reserved; UINT8 Reserved;
UINT8 Revision; UINT8 Revision;
//EFI_FV_BLOCK_MAP_ENTRY FvBlockMap[1]; //EFI_FV_BLOCK_MAP_ENTRY FvBlockMap[2];
} EFI_FIRMWARE_VOLUME_HEADER; } EFI_FIRMWARE_VOLUME_HEADER;
// Standard file system GUIDs // Standard file system GUIDs
@ -252,8 +268,8 @@ extern UINT16 calculateChecksum16(const UINT16* buffer, UINT32 bufferSize);
// Integrity check // Integrity check
typedef union { typedef union {
struct { struct {
UINT8 Header; UINT8 Header;
UINT8 File; UINT8 File;
} Checksum; } Checksum;
UINT16 TailReference; // Revision 1 UINT16 TailReference; // Revision 1
UINT16 Checksum16; // Revision 2 UINT16 Checksum16; // Revision 2
@ -276,7 +292,7 @@ UINT8 Type;
UINT8 Attributes; UINT8 Attributes;
UINT8 Size[3]; // Set to 0xFFFFFF UINT8 Size[3]; // Set to 0xFFFFFF
UINT8 State; UINT8 State;
UINT32 ExtendedSize; UINT64 ExtendedSize;
} EFI_FFS_FILE_HEADER2; } EFI_FFS_FILE_HEADER2;
// Standard data checksum, used if FFS_ATTRIB_CHECKSUM is clear // Standard data checksum, used if FFS_ATTRIB_CHECKSUM is clear
@ -298,6 +314,8 @@ UINT32 ExtendedSize;
#define EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE 0x0B #define EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE 0x0B
#define EFI_FV_FILETYPE_COMBINED_SMM_DXE 0x0C #define EFI_FV_FILETYPE_COMBINED_SMM_DXE 0x0C
#define EFI_FV_FILETYPE_SMM_CORE 0x0D #define EFI_FV_FILETYPE_SMM_CORE 0x0D
#define EFI_FV_FILETYPE_SMM_STANDALONE 0x0E
#define EFI_FV_FILETYPE_SMM_CORE_STANDALONE 0x0F
#define EFI_FV_FILETYPE_OEM_MIN 0xC0 #define EFI_FV_FILETYPE_OEM_MIN 0xC0
#define EFI_FV_FILETYPE_OEM_MAX 0xDF #define EFI_FV_FILETYPE_OEM_MAX 0xDF
#define EFI_FV_FILETYPE_DEBUG_MIN 0xE0 #define EFI_FV_FILETYPE_DEBUG_MIN 0xE0
@ -310,6 +328,7 @@ UINT32 ExtendedSize;
#define FFS_ATTRIB_TAIL_PRESENT 0x01 // Valid only for revision 1 volumes #define FFS_ATTRIB_TAIL_PRESENT 0x01 // Valid only for revision 1 volumes
#define FFS_ATTRIB_RECOVERY 0x02 // Valid only for revision 1 volumes #define FFS_ATTRIB_RECOVERY 0x02 // Valid only for revision 1 volumes
#define FFS_ATTRIB_LARGE_FILE 0x01 // Valid only for FFSv3 volumes #define FFS_ATTRIB_LARGE_FILE 0x01 // Valid only for FFSv3 volumes
#define FFS_ATTRIB_DATA_ALIGNMENT2 0x02 // Valid only for revision 2 volumes
#define FFS_ATTRIB_FIXED 0x04 #define FFS_ATTRIB_FIXED 0x04
#define FFS_ATTRIB_DATA_ALIGNMENT 0x38 #define FFS_ATTRIB_DATA_ALIGNMENT 0x38
#define FFS_ATTRIB_CHECKSUM 0x40 #define FFS_ATTRIB_CHECKSUM 0x40
@ -317,6 +336,9 @@ UINT32 ExtendedSize;
// FFS alignment table // FFS alignment table
extern const UINT8 ffsAlignmentTable[]; extern const UINT8 ffsAlignmentTable[];
// Extended FFS alignment table
extern const UINT8 ffsAlignment2Table[];
// File states // File states
#define EFI_FILE_HEADER_CONSTRUCTION 0x01 #define EFI_FILE_HEADER_CONSTRUCTION 0x01
#define EFI_FILE_HEADER_VALID 0x02 #define EFI_FILE_HEADER_VALID 0x02
@ -324,6 +346,7 @@ extern const UINT8 ffsAlignmentTable[];
#define EFI_FILE_MARKED_FOR_UPDATE 0x08 #define EFI_FILE_MARKED_FOR_UPDATE 0x08
#define EFI_FILE_DELETED 0x10 #define EFI_FILE_DELETED 0x10
#define EFI_FILE_HEADER_INVALID 0x20 #define EFI_FILE_HEADER_INVALID 0x20
#define EFI_FILE_ERASE_POLARITY 0x80 // Defined as "all other bits must be set to ERASE_POLARITY" in UEFI PI
// PEI apriori file // PEI apriori file
const QByteArray EFI_PEI_APRIORI_FILE_GUID const QByteArray EFI_PEI_APRIORI_FILE_GUID
@ -344,7 +367,9 @@ const QByteArray EFI_FFS_PAD_FILE_GUID
// FFS size conversion routines // FFS size conversion routines
extern VOID uint32ToUint24(UINT32 size, UINT8* ffsSize); extern VOID uint32ToUint24(UINT32 size, UINT8* ffsSize);
extern UINT32 uint24ToUint32(const UINT8* ffsSize); extern UINT32 uint24ToUint32(const UINT8* ffsSize);
// FFS file 8bit checksum calculation routine
// FFS file 8bit checksum calculation routines
extern UINT8 calculateSum8(const UINT8* buffer, UINT32 bufferSize);
extern UINT8 calculateChecksum8(const UINT8* buffer, UINT32 bufferSize); extern UINT8 calculateChecksum8(const UINT8* buffer, UINT32 bufferSize);
//***************************************************************************** //*****************************************************************************
@ -512,7 +537,7 @@ typedef EFI_COMMON_SECTION_HEADER2 EFI_FIRMWARE_VOLUME_IMAGE_SECTION2;
typedef EFI_COMMON_SECTION_HEADER EFI_USER_INTERFACE_SECTION; typedef EFI_COMMON_SECTION_HEADER EFI_USER_INTERFACE_SECTION;
typedef EFI_COMMON_SECTION_HEADER2 EFI_USER_INTERFACE_SECTION2; typedef EFI_COMMON_SECTION_HEADER2 EFI_USER_INTERFACE_SECTION2;
//Section routines // Section routines
extern UINT32 sizeOfSectionHeader(const EFI_COMMON_SECTION_HEADER* header); extern UINT32 sizeOfSectionHeader(const EFI_COMMON_SECTION_HEADER* header);
//***************************************************************************** //*****************************************************************************

File diff suppressed because it is too large Load diff

View file

@ -67,22 +67,23 @@ public:
UINT8 parseMeRegion(const QByteArray & me, QModelIndex & index, const QModelIndex & parent, const UINT8 mode = CREATE_MODE_APPEND); UINT8 parseMeRegion(const QByteArray & me, QModelIndex & index, const QModelIndex & parent, const UINT8 mode = CREATE_MODE_APPEND);
UINT8 parseBiosRegion(const QByteArray & bios, QModelIndex & index, const QModelIndex & parent, const UINT8 mode = CREATE_MODE_APPEND); UINT8 parseBiosRegion(const QByteArray & bios, QModelIndex & index, const QModelIndex & parent, const UINT8 mode = CREATE_MODE_APPEND);
UINT8 parsePdrRegion(const QByteArray & pdr, QModelIndex & index, const QModelIndex & parent, const UINT8 mode = CREATE_MODE_APPEND); UINT8 parsePdrRegion(const QByteArray & pdr, QModelIndex & index, const QModelIndex & parent, const UINT8 mode = CREATE_MODE_APPEND);
UINT8 parseEcRegion(const QByteArray & ec, QModelIndex & index, const QModelIndex & parent, const UINT8 mode = CREATE_MODE_APPEND);
UINT8 parseBios(const QByteArray & bios, const QModelIndex & parent = QModelIndex()); UINT8 parseBios(const QByteArray & bios, const QModelIndex & parent = QModelIndex());
UINT8 parseVolume(const QByteArray & volume, QModelIndex & index, const QModelIndex & parent = QModelIndex(), const UINT8 mode = CREATE_MODE_APPEND); UINT8 parseVolume(const QByteArray & volume, QModelIndex & index, const QModelIndex & parent = QModelIndex(), const UINT8 mode = CREATE_MODE_APPEND);
UINT8 parseFile(const QByteArray & file, QModelIndex & index, const UINT8 erasePolarity = ERASE_POLARITY_UNKNOWN, const QModelIndex & parent = QModelIndex(), const UINT8 mode = CREATE_MODE_APPEND); UINT8 parseFile(const QByteArray & file, QModelIndex & index, const UINT8 revision = 2, const UINT8 erasePolarity = ERASE_POLARITY_UNKNOWN, const QModelIndex & parent = QModelIndex(), const UINT8 mode = CREATE_MODE_APPEND);
UINT8 parseSections(const QByteArray & body, const QModelIndex & parent = QModelIndex()); UINT8 parseSections(const QByteArray & body, const QModelIndex & parent = QModelIndex());
UINT8 parseSection(const QByteArray & section, QModelIndex & index, const QModelIndex & parent = QModelIndex(), const UINT8 mode = CREATE_MODE_APPEND); UINT8 parseSection(const QByteArray & section, QModelIndex & index, const QModelIndex & parent = QModelIndex(), const UINT8 mode = CREATE_MODE_APPEND);
// Compression routines // Compression routines
UINT8 decompress(const QByteArray & compressed, const UINT8 compressionType, QByteArray & decompressedData, UINT8 * algorithm = NULL); UINT8 decompress(const QByteArray & compressed, const UINT8 compressionType, QByteArray & decompressedData, UINT8 * algorithm = NULL);
UINT8 compress(const QByteArray & data, const UINT8 algorithm, QByteArray & compressedData); UINT8 compress(const QByteArray & data, const UINT8 algorithm, const UINT32 dictionarySize, QByteArray & compressedData);
// Construction routines // Construction routines
UINT8 reconstructImageFile(QByteArray &reconstructed); UINT8 reconstructImageFile(QByteArray &reconstructed);
UINT8 reconstruct(const QModelIndex &index, QByteArray & reconstructed); UINT8 reconstruct(const QModelIndex &index, QByteArray & reconstructed);
UINT8 reconstructIntelImage(const QModelIndex& index, QByteArray & reconstructed); UINT8 reconstructIntelImage(const QModelIndex& index, QByteArray & reconstructed);
UINT8 reconstructRegion(const QModelIndex& index, QByteArray & reconstructed); UINT8 reconstructRegion(const QModelIndex& index, QByteArray & reconstructed, bool includeHeader = true);
UINT8 reconstructBios(const QModelIndex& index, QByteArray & reconstructed); UINT8 reconstructPadding(const QModelIndex& index, QByteArray & reconstructed);
UINT8 reconstructVolume(const QModelIndex& index, QByteArray & reconstructed); UINT8 reconstructVolume(const QModelIndex& index, QByteArray & reconstructed);
UINT8 reconstructFile(const QModelIndex& index, const UINT8 revision, const UINT8 erasePolarity, const UINT32 base, QByteArray& reconstructed); UINT8 reconstructFile(const QModelIndex& index, const UINT8 revision, const UINT8 erasePolarity, const UINT32 base, QByteArray& reconstructed);
UINT8 reconstructSection(const QModelIndex& index, const UINT32 base, QByteArray & reconstructed); UINT8 reconstructSection(const QModelIndex& index, const UINT32 base, QByteArray & reconstructed);
@ -94,6 +95,7 @@ public:
UINT8 replace(const QModelIndex & index, const QByteArray & object, const UINT8 mode); UINT8 replace(const QModelIndex & index, const QByteArray & object, const UINT8 mode);
UINT8 remove(const QModelIndex & index); UINT8 remove(const QModelIndex & index);
UINT8 rebuild(const QModelIndex & index); UINT8 rebuild(const QModelIndex & index);
UINT8 doNotRebuild(const QModelIndex & index);
UINT8 dump(const QModelIndex & index, const QString & path, const QString & filter = QString()); UINT8 dump(const QModelIndex & index, const QString & path, const QString & filter = QString());
UINT8 patch(const QModelIndex & index, const QVector<PatchData> & patches); UINT8 patch(const QModelIndex & index, const QVector<PatchData> & patches);
@ -115,7 +117,6 @@ private:
UINT8 parseDepexSection(const QByteArray & body, QString & parsed); UINT8 parseDepexSection(const QByteArray & body, QString & parsed);
UINT8 findNextVolume(const QByteArray & bios, const UINT32 volumeOffset, UINT32 & nextVolumeOffset); UINT8 findNextVolume(const QByteArray & bios, const UINT32 volumeOffset, UINT32 & nextVolumeOffset);
UINT8 getVolumeSize(const QByteArray & bios, const UINT32 volumeOffset, UINT32 & volumeSize, UINT32 & bmVolumeSize); UINT8 getVolumeSize(const QByteArray & bios, const UINT32 volumeOffset, UINT32 & volumeSize, UINT32 & bmVolumeSize);
UINT8 getFileSize(const QByteArray & volume, const UINT32 fileOffset, UINT32 & fileSize);
UINT8 getSectionSize(const QByteArray & file, const UINT32 sectionOffset, UINT32 & sectionSize); UINT8 getSectionSize(const QByteArray & file, const UINT32 sectionOffset, UINT32 & sectionSize);
// Reconstruction helpers // Reconstruction helpers
@ -125,7 +126,7 @@ private:
// Rebase routines // Rebase routines
UINT8 getBase(const QByteArray& file, UINT32& base); UINT8 getBase(const QByteArray& file, UINT32& base);
UINT8 getEntryPoint(const QByteArray& file, UINT32 &entryPoint); UINT8 getEntryPoint(const QByteArray& file, UINT32 &entryPoint);
UINT8 rebase(QByteArray & executable, const UINT32 base); UINT8 rebase(QByteArray & executable, const UINT32 base, const QModelIndex & index);
void rebasePeiFiles(const QModelIndex & index); void rebasePeiFiles(const QModelIndex & index);
// Patch routines // Patch routines

View file

@ -17,18 +17,18 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
TreeItem::TreeItem(const UINT8 type, const UINT8 subtype, const UINT8 compression, TreeItem::TreeItem(const UINT8 type, const UINT8 subtype, const UINT8 compression,
const QString & name, const QString & text, const QString & info, const QString & name, const QString & text, const QString & info,
const QByteArray & header, const QByteArray & body, const QByteArray & parsingData, const QByteArray & header, const QByteArray & body,
TreeItem *parent) : TreeItem *parent) :
itemAction(Actions::NoAction), itemAction(Actions::NoAction),
itemType(type), itemType(type),
itemSubtype(subtype), itemSubtype(subtype),
itemCompression(compression), itemCompression(compression),
itemDictionarySize(0),
itemName(name), itemName(name),
itemText(text), itemText(text),
itemInfo(info), itemInfo(info),
itemHeader(header), itemHeader(header),
itemBody(body), itemBody(body),
itemParsingData(parsingData),
parentItem(parent) parentItem(parent)
{ {
} }
@ -184,11 +184,6 @@ QByteArray TreeItem::body() const
return itemBody; return itemBody;
} }
QByteArray TreeItem::parsingData() const
{
return itemParsingData;
}
bool TreeItem::hasEmptyHeader() const bool TreeItem::hasEmptyHeader() const
{ {
return itemHeader.isEmpty(); return itemHeader.isEmpty();
@ -199,21 +194,21 @@ bool TreeItem::hasEmptyBody() const
return itemBody.isEmpty(); return itemBody.isEmpty();
} }
bool TreeItem::hasEmptyParsingData() const
{
return itemParsingData.isEmpty();
}
void TreeItem::setParsingData(const QByteArray & data)
{
itemParsingData = data;
}
UINT8 TreeItem::action() const UINT8 TreeItem::action() const
{ {
return itemAction; return itemAction;
} }
UINT32 TreeItem::dictionarySize() const
{
return itemDictionarySize;
}
void TreeItem::setDictionarySize(const UINT32 dictionarySize)
{
itemDictionarySize = dictionarySize;
}
void TreeItem::setAction(const UINT8 action) void TreeItem::setAction(const UINT8 action)
{ {
itemAction = action; itemAction = action;
@ -228,4 +223,3 @@ void TreeItem::setAction(const UINT8 action)
&& parentItem->action() == Actions::NoAction) && parentItem->action() == Actions::NoAction)
parentItem->setAction(Actions::Rebuild); parentItem->setAction(Actions::Rebuild);
} }

View file

@ -26,7 +26,7 @@ class TreeItem
public: public:
TreeItem(const UINT8 type, const UINT8 subtype = 0, const UINT8 compression = COMPRESSION_ALGORITHM_NONE, TreeItem(const UINT8 type, const UINT8 subtype = 0, const UINT8 compression = COMPRESSION_ALGORITHM_NONE,
const QString &name = QString(), const QString &text = QString(), const QString &info = QString(), const QString &name = QString(), const QString &text = QString(), const QString &info = QString(),
const QByteArray & header = QByteArray(), const QByteArray & body = QByteArray(), const QByteArray & parsingData = QByteArray(), const QByteArray & header = QByteArray(), const QByteArray & body = QByteArray(),
TreeItem *parent = 0); TreeItem *parent = 0);
~TreeItem(); ~TreeItem();
@ -63,10 +63,6 @@ public:
QByteArray body() const; QByteArray body() const;
bool hasEmptyBody() const; bool hasEmptyBody() const;
QByteArray parsingData() const;
bool hasEmptyParsingData() const;
void setParsingData(const QByteArray & data);
QString info() const; QString info() const;
void addInfo(const QString &info); void addInfo(const QString &info);
void setInfo(const QString &info); void setInfo(const QString &info);
@ -76,18 +72,21 @@ public:
UINT8 compression() const; UINT8 compression() const;
UINT32 dictionarySize() const;
void setDictionarySize(const UINT32 dictionarySize);
private: private:
QList<TreeItem*> childItems; QList<TreeItem*> childItems;
UINT8 itemAction; UINT8 itemAction;
UINT8 itemType; UINT8 itemType;
UINT8 itemSubtype; UINT8 itemSubtype;
UINT8 itemCompression; UINT8 itemCompression;
UINT32 itemDictionarySize;
QString itemName; QString itemName;
QString itemText; QString itemText;
QString itemInfo; QString itemInfo;
QByteArray itemHeader; QByteArray itemHeader;
QByteArray itemBody; QByteArray itemBody;
QByteArray itemParsingData;
TreeItem *parentItem; TreeItem *parentItem;
}; };

View file

@ -178,22 +178,6 @@ bool TreeModel::hasEmptyBody(const QModelIndex &index) const
return item->hasEmptyBody(); return item->hasEmptyBody();
} }
QByteArray TreeModel::parsingData(const QModelIndex &index) const
{
if (!index.isValid())
return QByteArray();
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
return item->parsingData();
}
bool TreeModel::hasEmptyParsingData(const QModelIndex &index) const
{
if (!index.isValid())
return true;
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
return item->hasEmptyParsingData();
}
QString TreeModel::name(const QModelIndex &index) const QString TreeModel::name(const QModelIndex &index) const
{ {
if (!index.isValid()) if (!index.isValid())
@ -234,6 +218,14 @@ UINT8 TreeModel::compression(const QModelIndex &index) const
return item->compression(); return item->compression();
} }
UINT32 TreeModel::dictionarySize(const QModelIndex &index) const
{
if (!index.isValid())
return 0;
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
return item->dictionarySize();
}
void TreeModel::setSubtype(const QModelIndex & index, const UINT8 subtype) void TreeModel::setSubtype(const QModelIndex & index, const UINT8 subtype)
{ {
if (!index.isValid()) if (!index.isValid())
@ -284,20 +276,19 @@ void TreeModel::setAction(const QModelIndex &index, const UINT8 action)
emit dataChanged(this->index(0, 0), index); emit dataChanged(this->index(0, 0), index);
} }
void TreeModel::setParsingData(const QModelIndex &index, const QByteArray &data) void TreeModel::setDictionarySize(const QModelIndex &index, const UINT32 dictionarySize)
{ {
if (!index.isValid()) if (!index.isValid())
return; return;
TreeItem *item = static_cast<TreeItem*>(index.internalPointer()); TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
item->setParsingData(data); item->setDictionarySize(dictionarySize);
emit dataChanged(this->index(0, 0), index); emit dataChanged(this->index(0, 0), index);
} }
QModelIndex TreeModel::addItem(const UINT8 type, const UINT8 subtype, const UINT8 compression, QModelIndex TreeModel::addItem(const UINT8 type, const UINT8 subtype, const UINT8 compression,
const QString & name, const QString & text, const QString & info, const QString & name, const QString & text, const QString & info,
const QByteArray & header, const QByteArray & body, const QByteArray & parsingData, const QByteArray & header, const QByteArray & body, const QModelIndex & parent, const UINT8 mode)
const QModelIndex & parent, const UINT8 mode)
{ {
TreeItem *item = 0; TreeItem *item = 0;
TreeItem *parentItem = 0; TreeItem *parentItem = 0;
@ -318,7 +309,7 @@ QModelIndex TreeModel::addItem(const UINT8 type, const UINT8 subtype, const UINT
} }
} }
TreeItem *newItem = new TreeItem(type, subtype, compression, name, text, info, header, body, parsingData, parentItem); TreeItem *newItem = new TreeItem(type, subtype, compression, name, text, info, header, body, parentItem);
if (mode == CREATE_MODE_APPEND) { if (mode == CREATE_MODE_APPEND) {
emit layoutAboutToBeChanged(); emit layoutAboutToBeChanged();
parentItem->appendChild(newItem); parentItem->appendChild(newItem);

View file

@ -47,7 +47,7 @@ public:
void setSubtype(const QModelIndex &index, const UINT8 subtype); void setSubtype(const QModelIndex &index, const UINT8 subtype);
void setName(const QModelIndex &index, const QString &name); void setName(const QModelIndex &index, const QString &name);
void setText(const QModelIndex &index, const QString &text); void setText(const QModelIndex &index, const QString &text);
void setParsingData(const QModelIndex &index, const QByteArray &data); void setDictionarySize(const QModelIndex &index, const UINT32 dictionarySize);
QString name(const QModelIndex &index) const; QString name(const QModelIndex &index) const;
QString text(const QModelIndex &index) const; QString text(const QModelIndex &index) const;
@ -58,14 +58,13 @@ public:
bool hasEmptyHeader(const QModelIndex &index) const; bool hasEmptyHeader(const QModelIndex &index) const;
QByteArray body(const QModelIndex &index) const; QByteArray body(const QModelIndex &index) const;
bool hasEmptyBody(const QModelIndex &index) const; bool hasEmptyBody(const QModelIndex &index) const;
QByteArray parsingData(const QModelIndex &index) const;
bool hasEmptyParsingData(const QModelIndex &index) const;
UINT8 action(const QModelIndex &index) const; UINT8 action(const QModelIndex &index) const;
UINT8 compression(const QModelIndex &index) const; UINT8 compression(const QModelIndex &index) const;
UINT32 dictionarySize(const QModelIndex &index) const;
QModelIndex addItem(const UINT8 type, const UINT8 subtype = 0, const UINT8 compression = COMPRESSION_ALGORITHM_NONE, QModelIndex addItem(const UINT8 type, const UINT8 subtype = 0, const UINT8 compression = COMPRESSION_ALGORITHM_NONE,
const QString & name = QString(), const QString & text = QString(), const QString & info = QString(), const QString & name = QString(), const QString & text = QString(), const QString & info = QString(),
const QByteArray & header = QByteArray(), const QByteArray & body = QByteArray(), const QByteArray & parsingData = QByteArray(), const QByteArray & header = QByteArray(), const QByteArray & body = QByteArray(),
const QModelIndex & parent = QModelIndex(), const UINT8 mode = CREATE_MODE_APPEND); const QModelIndex & parent = QModelIndex(), const UINT8 mode = CREATE_MODE_APPEND);
QModelIndex findParentOfType(const QModelIndex & index, UINT8 type) const; QModelIndex findParentOfType(const QModelIndex & index, UINT8 type) const;

View file

@ -24,11 +24,13 @@ QString regionTypeToQString(const UINT8 type)
case Subtypes::GbeRegion: case Subtypes::GbeRegion:
return QObject::tr("GbE"); return QObject::tr("GbE");
case Subtypes::MeRegion: case Subtypes::MeRegion:
return QObject::tr("ME/TXE"); return QObject::tr("ME");
case Subtypes::BiosRegion: case Subtypes::BiosRegion:
return QObject::tr("BIOS"); return QObject::tr("BIOS");
case Subtypes::PdrRegion: case Subtypes::PdrRegion:
return QObject::tr("PDR"); return QObject::tr("PDR");
case Subtypes::EcRegion:
return QObject::tr("EC");
default: default:
return QObject::tr("Unknown"); return QObject::tr("Unknown");
}; };
@ -67,7 +69,7 @@ QString itemSubtypeToQString(const UINT8 type, const UINT8 subtype)
case Types::Image: case Types::Image:
if (subtype == Subtypes::IntelImage) if (subtype == Subtypes::IntelImage)
return QObject::tr("Intel"); return QObject::tr("Intel");
else if (Subtypes::UefiImage) else if (subtype == Subtypes::UefiImage)
return QObject::tr("UEFI"); return QObject::tr("UEFI");
else else
return QObject::tr("Unknown subtype"); return QObject::tr("Unknown subtype");
@ -80,7 +82,7 @@ QString itemSubtypeToQString(const UINT8 type, const UINT8 subtype)
return QObject::tr("Non-empty"); return QObject::tr("Non-empty");
else else
return QObject::tr("Unknown subtype"); return QObject::tr("Unknown subtype");
case Types::Volume: case Types::Volume:
if (subtype == Subtypes::UnknownVolume) if (subtype == Subtypes::UnknownVolume)
return QObject::tr("Unknown"); return QObject::tr("Unknown");
else if (subtype == Subtypes::Ffs2Volume) else if (subtype == Subtypes::Ffs2Volume)
@ -89,14 +91,16 @@ QString itemSubtypeToQString(const UINT8 type, const UINT8 subtype)
return QObject::tr("FFSv3"); return QObject::tr("FFSv3");
else else
return QObject::tr("Unknown subtype"); return QObject::tr("Unknown subtype");
case Types::Capsule: case Types::Capsule:
if (subtype == Subtypes::AptioSignedCapsule) if (subtype == Subtypes::AptioSignedCapsule)
return QObject::tr("Aptio signed"); return QObject::tr("Aptio signed");
else if (subtype == Subtypes::AptioUnsignedCapsule) else if (subtype == Subtypes::AptioUnsignedCapsule)
return QObject::tr("Aptio unsigned"); return QObject::tr("Aptio unsigned");
else if (subtype == Subtypes::UefiCapsule) else if (subtype == Subtypes::UefiCapsule)
return QObject::tr("UEFI 2.0 "); return QObject::tr("UEFI 2.0");
else else if (subtype == Subtypes::ToshibaCapsule)
return QObject::tr("Toshiba");
else
return QObject::tr("Unknown subtype"); return QObject::tr("Unknown subtype");
case Types::Region: case Types::Region:
return regionTypeToQString(subtype); return regionTypeToQString(subtype);
@ -146,7 +150,9 @@ QString actionTypeToQString(const UINT8 action)
return QObject::tr("Rebuild"); return QObject::tr("Rebuild");
case Actions::Rebase: case Actions::Rebase:
return QObject::tr("Rebase"); return QObject::tr("Rebase");
case Actions::DoNotRebuild:
return QObject::tr("Do not rebuild");
default: default:
return QObject::tr("Unknown"); return QObject::tr("Unknown");
} }
} }

30
types.h
View file

@ -26,7 +26,8 @@ namespace Actions
Replace, Replace,
Remove, Remove,
Rebuild, Rebuild,
Rebase Rebase,
DoNotRebuild
}; };
} }
@ -54,7 +55,8 @@ namespace Subtypes {
enum CapsuleSubtypes { enum CapsuleSubtypes {
AptioSignedCapsule = 80, AptioSignedCapsule = 80,
AptioUnsignedCapsule, AptioUnsignedCapsule,
UefiCapsule UefiCapsule,
ToshibaCapsule
}; };
enum VolumeSubtypes { enum VolumeSubtypes {
@ -68,7 +70,8 @@ namespace Subtypes {
GbeRegion, GbeRegion,
MeRegion, MeRegion,
BiosRegion, BiosRegion,
PdrRegion PdrRegion,
EcRegion
}; };
enum PaddingSubtypes { enum PaddingSubtypes {
@ -85,25 +88,4 @@ extern QString itemSubtypeToQString(const UINT8 type, const UINT8 subtype);
extern QString compressionTypeToQString(const UINT8 algorithm); extern QString compressionTypeToQString(const UINT8 algorithm);
extern QString regionTypeToQString(const UINT8 type); extern QString regionTypeToQString(const UINT8 type);
enum ParsingDataTypes {
UnknownParsingData,
VolumeParsingData,
FileParsingData
};
typedef union _PARSING_DATA_UNION {
struct _PARSING_DATA_UNION_VOLUME {
bool HasZeroVectorCRC;
} Volume;
struct _PARSING_DATA_UNION_FILE {
UINT32 Offset;
} File;
} PARSING_DATA_UNION;
typedef struct _PARSING_DATA {
UINT8 Type;
PARSING_DATA_UNION Data;
} PARSING_DATA;
#endif #endif

View file

@ -11,13 +11,14 @@
*/ */
#include "version.h"
#include "uefitool.h" #include "uefitool.h"
#include "ui_uefitool.h" #include "ui_uefitool.h"
UEFITool::UEFITool(QWidget *parent) : UEFITool::UEFITool(QWidget *parent) :
QMainWindow(parent), QMainWindow(parent),
ui(new Ui::UEFITool), ui(new Ui::UEFITool),
version(tr("0.20.4")) version(tr(PROGRAM_VERSION))
{ {
clipboard = QApplication::clipboard(); clipboard = QApplication::clipboard();
@ -31,6 +32,7 @@ version(tr("0.20.4"))
// Connect signals to slots // Connect signals to slots
connect(ui->actionOpenImageFile, SIGNAL(triggered()), this, SLOT(openImageFile())); connect(ui->actionOpenImageFile, SIGNAL(triggered()), this, SLOT(openImageFile()));
connect(ui->actionOpenImageFileInNewWindow, SIGNAL(triggered()), this, SLOT(openImageFileInNewWindow()));
connect(ui->actionSaveImageFile, SIGNAL(triggered()), this, SLOT(saveImageFile())); connect(ui->actionSaveImageFile, SIGNAL(triggered()), this, SLOT(saveImageFile()));
connect(ui->actionSearch, SIGNAL(triggered()), this, SLOT(search())); connect(ui->actionSearch, SIGNAL(triggered()), this, SLOT(search()));
connect(ui->actionExtract, SIGNAL(triggered()), this, SLOT(extractAsIs())); connect(ui->actionExtract, SIGNAL(triggered()), this, SLOT(extractAsIs()));
@ -42,6 +44,7 @@ version(tr("0.20.4"))
connect(ui->actionReplaceBody, SIGNAL(triggered()), this, SLOT(replaceBody())); connect(ui->actionReplaceBody, SIGNAL(triggered()), this, SLOT(replaceBody()));
connect(ui->actionRemove, SIGNAL(triggered()), this, SLOT(remove())); connect(ui->actionRemove, SIGNAL(triggered()), this, SLOT(remove()));
connect(ui->actionRebuild, SIGNAL(triggered()), this, SLOT(rebuild())); connect(ui->actionRebuild, SIGNAL(triggered()), this, SLOT(rebuild()));
connect(ui->actionDoNotRebuild, SIGNAL(triggered()), this, SLOT(doNotRebuild()));
connect(ui->actionMessagesCopy, SIGNAL(triggered()), this, SLOT(copyMessage())); connect(ui->actionMessagesCopy, SIGNAL(triggered()), this, SLOT(copyMessage()));
connect(ui->actionMessagesCopyAll, SIGNAL(triggered()), this, SLOT(copyAllMessages())); connect(ui->actionMessagesCopyAll, SIGNAL(triggered()), this, SLOT(copyAllMessages()));
connect(ui->actionMessagesClear, SIGNAL(triggered()), this, SLOT(clearMessages())); connect(ui->actionMessagesClear, SIGNAL(triggered()), this, SLOT(clearMessages()));
@ -83,6 +86,11 @@ UEFITool::~UEFITool()
delete searchDialog; delete searchDialog;
} }
void UEFITool::setProgramPath(QString path)
{
currentProgramPath = path;
};
void UEFITool::init() void UEFITool::init()
{ {
// Clear components // Clear components
@ -140,6 +148,7 @@ void UEFITool::populateUi(const QModelIndex &current)
// Enable actions // Enable actions
ui->actionExtract->setDisabled(model->hasEmptyHeader(current) && model->hasEmptyBody(current)); ui->actionExtract->setDisabled(model->hasEmptyHeader(current) && model->hasEmptyBody(current));
ui->actionRebuild->setEnabled(type == Types::Volume || type == Types::File || type == Types::Section); ui->actionRebuild->setEnabled(type == Types::Volume || type == Types::File || type == Types::Section);
ui->actionDoNotRebuild->setEnabled(type== Types::Region || type == Types::Volume || type == Types::File || type == Types::Section);
ui->actionExtractBody->setDisabled(model->hasEmptyBody(current)); ui->actionExtractBody->setDisabled(model->hasEmptyBody(current));
ui->actionRemove->setEnabled(type == Types::Volume || type == Types::File || type == Types::Section); ui->actionRemove->setEnabled(type == Types::Volume || type == Types::File || type == Types::Section);
ui->actionInsertInto->setEnabled((type == Types::Volume && subtype != Subtypes::UnknownVolume) || ui->actionInsertInto->setEnabled((type == Types::Volume && subtype != Subtypes::UnknownVolume) ||
@ -147,7 +156,7 @@ void UEFITool::populateUi(const QModelIndex &current)
(type == Types::Section && (subtype == EFI_SECTION_COMPRESSION || subtype == EFI_SECTION_GUID_DEFINED || subtype == EFI_SECTION_DISPOSABLE))); (type == Types::Section && (subtype == EFI_SECTION_COMPRESSION || subtype == EFI_SECTION_GUID_DEFINED || subtype == EFI_SECTION_DISPOSABLE)));
ui->actionInsertBefore->setEnabled(type == Types::File || type == Types::Section); ui->actionInsertBefore->setEnabled(type == Types::File || type == Types::Section);
ui->actionInsertAfter->setEnabled(type == Types::File || type == Types::Section); ui->actionInsertAfter->setEnabled(type == Types::File || type == Types::Section);
ui->actionReplace->setEnabled((type == Types::Region && subtype != Subtypes::DescriptorRegion) || type == Types::Volume || type == Types::File || type == Types::Section); ui->actionReplace->setEnabled((type == Types::Region && subtype != Subtypes::DescriptorRegion) || type == Types::Padding || type == Types::Volume || type == Types::File || type == Types::Section);
ui->actionReplaceBody->setEnabled(type == Types::Volume || type == Types::File || type == Types::Section); ui->actionReplaceBody->setEnabled(type == Types::Volume || type == Types::File || type == Types::Section);
ui->actionMessagesCopy->setEnabled(false); ui->actionMessagesCopy->setEnabled(false);
} }
@ -214,6 +223,18 @@ void UEFITool::rebuild()
ui->actionSaveImageFile->setEnabled(true); ui->actionSaveImageFile->setEnabled(true);
} }
void UEFITool::doNotRebuild()
{
QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex();
if (!index.isValid())
return;
UINT8 result = ffsEngine->doNotRebuild(index);
if (result == ERR_SUCCESS)
ui->actionSaveImageFile->setEnabled(true);
}
void UEFITool::remove() void UEFITool::remove()
{ {
QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex(); QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex();
@ -321,6 +342,13 @@ void UEFITool::replace(const UINT8 mode)
else else
return; return;
} }
else if (model->type(index) == Types::Padding) {
if (mode == REPLACE_MODE_AS_IS) {
path = QFileDialog::getOpenFileName(this, tr("Select padding file to replace selected object"), currentDir, "Padding files (*.pad *.bin);;All files (*)");
}
else
return;
}
else if (model->type(index) == Types::Volume) { else if (model->type(index) == Types::Volume) {
if (mode == REPLACE_MODE_AS_IS) { if (mode == REPLACE_MODE_AS_IS) {
path = QFileDialog::getOpenFileName(this, tr("Select volume file to replace selected object"), currentDir, "Volume files (*.vol *.bin);;All files (*)"); path = QFileDialog::getOpenFileName(this, tr("Select volume file to replace selected object"), currentDir, "Volume files (*.vol *.bin);;All files (*)");
@ -358,6 +386,8 @@ void UEFITool::replace(const UINT8 mode)
path = QFileDialog::getOpenFileName(this, tr("Select volume file to replace body"), currentDir, "Volume files (*.vol *.bin);;All files (*)"); path = QFileDialog::getOpenFileName(this, tr("Select volume file to replace body"), currentDir, "Volume files (*.vol *.bin);;All files (*)");
else if (model->subtype(index) == EFI_SECTION_RAW) else if (model->subtype(index) == EFI_SECTION_RAW)
path = QFileDialog::getOpenFileName(this, tr("Select raw file to replace body"), currentDir, "Raw files (*.raw *.bin);;All files (*)"); path = QFileDialog::getOpenFileName(this, tr("Select raw file to replace body"), currentDir, "Raw files (*.raw *.bin);;All files (*)");
else if (model->subtype(index) == EFI_SECTION_PE32 || model->subtype(index) == EFI_SECTION_TE || model->subtype(index) == EFI_SECTION_PIC)
path = QFileDialog::getOpenFileName(this, tr("Select EFI executable file to replace body"), currentDir, "EFI executable files (*.efi *.dxe *.pei *.bin);;All files (*)");
else else
path = QFileDialog::getOpenFileName(this, tr("Select file to replace body"), currentDir, "Binary files (*.bin);;All files (*)"); path = QFileDialog::getOpenFileName(this, tr("Select file to replace body"), currentDir, "Binary files (*.bin);;All files (*)");
} }
@ -447,7 +477,7 @@ void UEFITool::extract(const UINT8 mode)
case Types::Capsule: case Types::Capsule:
path = QFileDialog::getSaveFileName(this, tr("Save capsule body to image file"), currentDir, "Image files (*.rom *.bin);;All files (*)"); path = QFileDialog::getSaveFileName(this, tr("Save capsule body to image file"), currentDir, "Image files (*.rom *.bin);;All files (*)");
break; break;
case Types::Volume: case Types::Volume:
path = QFileDialog::getSaveFileName(this, tr("Save volume body to file"), currentDir, "Volume body files (*.vbd *.bin);;All files (*)"); path = QFileDialog::getSaveFileName(this, tr("Save volume body to file"), currentDir, "Volume body files (*.vbd *.bin);;All files (*)");
break; break;
case Types::File: { case Types::File: {
@ -521,7 +551,7 @@ void UEFITool::exit()
void UEFITool::saveImageFile() void UEFITool::saveImageFile()
{ {
QString path = QFileDialog::getSaveFileName(this, tr("Save BIOS image file"), currentDir, "BIOS image files (*.rom *.bin *.cap *.bio *.fd *.wph *.efi *.dec);;All files (*)"); QString path = QFileDialog::getSaveFileName(this, tr("Save BIOS image file"), currentDir, "BIOS image files (*.rom *.bin *.cap *.bio *.fd *.wph *.dec);;All files (*)");
if (path.isEmpty()) if (path.isEmpty())
return; return;
@ -552,10 +582,18 @@ void UEFITool::saveImageFile()
void UEFITool::openImageFile() void UEFITool::openImageFile()
{ {
QString path = QFileDialog::getOpenFileName(this, tr("Open BIOS image file"), currentDir, "BIOS image files (*.rom *.bin *.cap *.bio *.fd *.wph *.efi *.dec);;All files (*)"); QString path = QFileDialog::getOpenFileName(this, tr("Open BIOS image file"), currentDir, "BIOS image files (*.rom *.bin *.cap *.bio *.fd *.wph *.dec);;All files (*)");
openImageFile(path); openImageFile(path);
} }
void UEFITool::openImageFileInNewWindow()
{
QString path = QFileDialog::getOpenFileName(this, tr("Open BIOS image file in new window"), currentDir, "BIOS image files (*.rom *.bin *.cap *.bio *.fd *.wph *.dec);;All files (*)");
if (path.trimmed().isEmpty())
return;
QProcess::startDetached(currentProgramPath, QStringList(path));
}
void UEFITool::openImageFile(QString path) void UEFITool::openImageFile(QString path)
{ {
if (path.trimmed().isEmpty()) if (path.trimmed().isEmpty())

View file

@ -27,6 +27,7 @@
#include <QMessageBox> #include <QMessageBox>
#include <QMimeData> #include <QMimeData>
#include <QPlainTextEdit> #include <QPlainTextEdit>
#include <QProcess>
#include <QSettings> #include <QSettings>
#include <QSplitter> #include <QSplitter>
#include <QString> #include <QString>
@ -51,6 +52,7 @@ public:
~UEFITool(); ~UEFITool();
void openImageFile(QString path); void openImageFile(QString path);
void setProgramPath(QString path);
private slots: private slots:
void init(); void init();
@ -58,6 +60,7 @@ public:
void scrollTreeView(QListWidgetItem* item); void scrollTreeView(QListWidgetItem* item);
void openImageFile(); void openImageFile();
void openImageFileInNewWindow();
void saveImageFile(); void saveImageFile();
void search(); void search();
@ -75,6 +78,7 @@ public:
void replaceBody(); void replaceBody();
void rebuild(); void rebuild();
void doNotRebuild();
void remove(); void remove();
@ -95,6 +99,7 @@ private:
SearchDialog* searchDialog; SearchDialog* searchDialog;
QClipboard* clipboard; QClipboard* clipboard;
QString currentDir; QString currentDir;
QString currentProgramPath;
QQueue<MessageListItem> messageItems; QQueue<MessageListItem> messageItems;
const QString version; const QString version;

View file

@ -39,6 +39,7 @@ HEADERS += uefitool.h \
treemodel.h \ treemodel.h \
messagelistitem.h \ messagelistitem.h \
guidlineedit.h \ guidlineedit.h \
version.h \
LZMA/LzmaCompress.h \ LZMA/LzmaCompress.h \
LZMA/LzmaDecompress.h \ LZMA/LzmaDecompress.h \
Tiano/EfiTianoDecompress.h \ Tiano/EfiTianoDecompress.h \

View file

@ -180,7 +180,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>800</width> <width>800</width>
<height>21</height> <height>31</height>
</rect> </rect>
</property> </property>
<widget class="QMenu" name="menuFile"> <widget class="QMenu" name="menuFile">
@ -188,6 +188,7 @@
<string>&amp;File</string> <string>&amp;File</string>
</property> </property>
<addaction name="actionOpenImageFile"/> <addaction name="actionOpenImageFile"/>
<addaction name="actionOpenImageFileInNewWindow"/>
<addaction name="actionSaveImageFile"/> <addaction name="actionSaveImageFile"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionSearch"/> <addaction name="actionSearch"/>
@ -224,6 +225,8 @@
</property> </property>
<addaction name="actionExtract"/> <addaction name="actionExtract"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionDoNotRebuild"/>
<addaction name="separator"/>
<addaction name="actionReplace"/> <addaction name="actionReplace"/>
</widget> </widget>
<widget class="QMenu" name="menuPaddingActions"> <widget class="QMenu" name="menuPaddingActions">
@ -231,6 +234,8 @@
<string>&amp;Padding</string> <string>&amp;Padding</string>
</property> </property>
<addaction name="actionExtract"/> <addaction name="actionExtract"/>
<addaction name="separator"/>
<addaction name="actionReplace"/>
</widget> </widget>
<widget class="QMenu" name="menuVolumeActions"> <widget class="QMenu" name="menuVolumeActions">
<property name="title"> <property name="title">
@ -240,6 +245,7 @@
<addaction name="actionExtractBody"/> <addaction name="actionExtractBody"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionRebuild"/> <addaction name="actionRebuild"/>
<addaction name="actionDoNotRebuild"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionInsertInto"/> <addaction name="actionInsertInto"/>
<addaction name="separator"/> <addaction name="separator"/>
@ -254,6 +260,7 @@
<addaction name="actionExtractBody"/> <addaction name="actionExtractBody"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionRebuild"/> <addaction name="actionRebuild"/>
<addaction name="actionDoNotRebuild"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionInsertInto"/> <addaction name="actionInsertInto"/>
<addaction name="actionInsertBefore"/> <addaction name="actionInsertBefore"/>
@ -272,6 +279,7 @@
<addaction name="actionExtractBody"/> <addaction name="actionExtractBody"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionRebuild"/> <addaction name="actionRebuild"/>
<addaction name="actionDoNotRebuild"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionInsertInto"/> <addaction name="actionInsertInto"/>
<addaction name="actionInsertBefore"/> <addaction name="actionInsertBefore"/>
@ -281,7 +289,6 @@
<addaction name="actionReplaceBody"/> <addaction name="actionReplaceBody"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionRemove"/> <addaction name="actionRemove"/>
<addaction name="separator"/>
</widget> </widget>
<widget class="QMenu" name="menuMessages"> <widget class="QMenu" name="menuMessages">
<property name="title"> <property name="title">
@ -522,6 +529,28 @@
<string>Ctrl+Alt+C</string> <string>Ctrl+Alt+C</string>
</property> </property>
</action> </action>
<action name="actionOpenImageFileInNewWindow">
<property name="text">
<string>&amp;Open image file in new window...</string>
</property>
<property name="toolTip">
<string>Open image file in new window</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+O</string>
</property>
</action>
<action name="actionDoNotRebuild">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>&amp;Do not rebuild</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+Space</string>
</property>
</action>
</widget> </widget>
<layoutdefault spacing="6" margin="11"/> <layoutdefault spacing="6" margin="11"/>
<resources/> <resources/>

View file

@ -23,6 +23,7 @@ int main(int argc, char *argv[])
a.setApplicationName("UEFITool"); a.setApplicationName("UEFITool");
UEFITool w; UEFITool w;
w.setProgramPath(a.arguments().at(0));
if (a.arguments().length() > 1) if (a.arguments().length() > 1)
w.openImageFile(a.arguments().at(1)); w.openImageFile(a.arguments().at(1));
w.show(); w.show();

118
unixbuild.sh Executable file
View file

@ -0,0 +1,118 @@
#!/bin/bash
UTARGET=$(uname)
BINSUFFIX=""
if [ "$UTARGET" = "Darwin" ]; then
export UPLATFORM="mac"
elif [ "$UTARGET" = "Linux" ]; then
export UPLATFORM="linux_$(uname -m)"
elif [ "${UTARGET/MINGW32/}" != "$UTARGET" ]; then
export UPLATFORM="win32"
export BINSUFFIX=".exe"
else
# Fallback to something...
export UPLATFORM="$UTARGET"
fi
if [ "$UPLATFORM" = "mac" ]; then
if [ ! -d /opt/qt56sm ]; then
curl -L -o /tmp/qt-5.6.3-static-mac.zip https://github.com/distdb/qtbuilds/blob/master/qt-5.6.3-static-mac.zip?raw=true || exit 1
qtsum=$(shasum -a 256 /tmp/qt-5.6.3-static-mac.zip | cut -f1 -d' ')
qtexpsum="214d22d8572ea6162753c8dd251d79275f3b22d49204718c637d722409e0cfcb"
if [ "$qtsum" != "$qtexpsum" ]; then
echo "Qt hash $qtsum does not match $qtexpsum"
exit 1
fi
sudo mkdir -p /opt || exit 1
cd /opt || exit 1
sudo unzip -q /tmp/qt-5.6.3-static-mac.zip || exit 1
cd - || exit 1
fi
export PATH="/opt/qt56sm/bin:$PATH"
elif [ "$UPLATFORM" = "win32" ]; then
# Install missing dependencies
pacman -S --noconfirm --needed zip unzip curl perl mingw-w64-i686-toolchain mingw-w64-i686-cmake || exit 1
# Fix PATH to support running shasum.
export PATH="/usr/bin/core_perl:$PATH"
if [ ! -d "/c/Qt/5.6/mingw49_32_release_static/" ]; then
curl -L -o /tmp/qt-5.6.3-static-win32.zip https://github.com/distdb/qtbuilds/blob/master/qt-5.6.3-static-win32.zip?raw=true || exit 1
qtsum=$(shasum -a 256 /tmp/qt-5.6.3-static-win32.zip | cut -f1 -d' ')
qtexpsum="bcd85145d6fed00da37498c08c49d763c6fa883337f754880b5c786899e6bb1d"
if [ "$qtsum" != "$qtexpsum" ]; then
echo "Qt hash $qtsum does not match $qtexpsum"
exit 1
fi
mkdir -p /c/Qt/5.6 || exit 1
cd /c/Qt/5.6 || exit 1
unzip -q /tmp/qt-5.6.3-static-win32.zip || exit 1
cd - || exit 1
fi
export PATH="/c/Qt/5.6/mingw49_32_release_static/bin:$PATH"
fi
echo "Attempting to build UEFITool for ${UPLATFORM}..."
UEFITOOL_VER=$(cat version.h | grep PROGRAM_VERSION | cut -d'"' -f2)
build_tool() {
echo "Building $1 $2"
# Check version
if [ "$(echo "$2" | grep '^[0-9]*\.[0-9]*\.[0-9]*$')" != "$2" ]; then
echo "Invalid $1 version!"
exit 1
fi
# Tools are in subdirectories
if [ "$1" != "UEFITool" ]; then
cd "$1" || exit 1
fi
# Build
# -flto is flawed on CI atm
if [ "$UPLATFORM" = "mac" ]; then
qmake $3 QMAKE_CXXFLAGS+=-flto QMAKE_LFLAGS+=-flto CONFIG+=optimize_size || exit 1
elif [ "$UPLATFORM" = "win32" ]; then
qmake $3 QMAKE_CXXFLAGS="-static -flto -Os" QMAKE_LFLAGS="-static -flto -Os" CONFIG+=optimize_size CONFIG+=staticlib CONFIG+=static || exit 1
else
qmake $3 CONFIG+=optimize_size || exit 1
fi
make || exit 1
# Move the binary out of the dir
if [ "$UPLATFORM" = "win32" ]; then
mv "release/${1}${BINSUFFIX}" "${1}${BINSUFFIX}" || exit 1
fi
# Archive
if [ "$1" = "UEFITool" ]; then
if [ "$UPLATFORM" = "mac" ]; then
strip -x UEFITool.app/Contents/MacOS/UEFITool || exit 1
zip -qry dist/"${1}_${2}_${UPLATFORM}.zip" UEFITool.app ${4} || exit 1
else
strip -x "${1}${BINSUFFIX}" || exit 1
zip -qry dist/"${1}_${2}_${UPLATFORM}.zip" "${1}${BINSUFFIX}" ${4} || exit 1
fi
else
strip -x "${1}${BINSUFFIX}" || exit 1
zip -qry ../dist/"${1}_${2}_${UPLATFORM}.zip" "${1}${BINSUFFIX}" ${4} || exit 1
fi
# Return to parent
if [ "$1" != "UEFITool" ]; then
cd - || exit 1
fi
}
rm -rf dist
mkdir -p dist || exit 1
build_tool UEFITool "$UEFITOOL_VER" uefitool.pro
build_tool UEFIPatch "$UEFITOOL_VER" uefipatch.pro patches*.txt
build_tool UEFIReplace "$UEFITOOL_VER" uefireplace.pro
exit 0

19
version.h Normal file
View file

@ -0,0 +1,19 @@
/* types.h
Copyright (c) 2015, 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 VERSION_H
#define VERSION_H
#define PROGRAM_VERSION "0.26.0"
#endif // VERSION_H