Compare commits

...

47 commits

Author SHA1 Message Date
vit9696
bdec60c173 Version bump 2018-05-04 21:49:56 +03:00
vit9696
46443370f2 Remove legacy UEFIFind and UEFIExtract in favour of new_engine branch 2018-05-04 21:42:54 +03:00
vit9696
dff0142d6e Backport TianoDecompress fix for Xcode (https://bugzilla.tianocore.org/show_bug.cgi?id=635) 2018-05-04 20:46:06 +03:00
vit9696
0b242e9fb4
Merge pull request #130 from vit9696/ci-master
Travis Mac
2018-05-04 06:52:01 +03:00
vit9696
15b606f924 Add deploy key 2018-05-04 06:40:04 +03:00
vit9696
a9629c0400 Implement mac builds with deploy 2018-05-03 22:27:40 +03:00
vit9696
88b0658b53 Fix rebuild reversion 2018-05-03 20:41:27 +03:00
Alex Matrosov
b44dace867
Merge pull request #128 from vit9696/recover-skylake
Recover Skylake patches
2018-05-01 20:04:25 -07:00
vit9696
2de7e3b219 Recover Skylake patches 2018-05-01 23:27:35 +03:00
Alex Matrosov
85161d37b4 bugfix 2018-04-29 22:38:54 -07:00
Alex Matrosov
3b5976bbec
Merge pull request #126 from HackingThings/master
Fix for EC region parse
2018-04-14 16:04:57 -07:00
HackingThings
b1e9ebf31f Fix EC region parse
Fixing Copy&Paste bug
2018-04-14 10:40:31 -07:00
Alex Matrosov
60d6494841 fixed rebase PEI files with nonstandard alignment 2018-02-25 15:40:14 -08:00
Alex Matrosov
8714e4c15e
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
41 changed files with 5103 additions and 4504 deletions

3
.gitignore vendored
View file

@ -233,4 +233,5 @@ Makefile
UEFIExtract/UEFIExtract
UEFIFind/UEFIFind
UEFIPatch/UEFIPatch
UEFITool
UEFIReplace/UEFIReplace
UEFITool

44
.travis.yml Normal file
View file

@ -0,0 +1,44 @@
language: cpp
matrix:
include:
- os: osx
osx_image: xcode9.2
compiler: clang
script:
- ./macbuild.sh
deploy:
provider: releases
skip_cleanup: true
file: "dist/*.zip"
file_glob: true
api_key:
secure: "WjYd93lVLKHULBpUXS/WtGrkdXyAwxHOUnLJotyDmQipAQP5Ox7Kj12JwkSJGEmVOEdcbIQJyi0QxPjn1UYbYsAt6Op8zrjnYLS4G4fMdBtcxprWzid85uTW7oAAIFs7ygMVhpzxRKpu70yNb683vbThqNmaOu6RyG9aJOLtPAg="
on:
tags: true
- os: linux
compiler: clang
before_install:
- sudo add-apt-repository --yes ppa:ubuntu-sdk-team/ppa
- sudo apt-get update -qq
- sudo apt-get install -qq qt5-qmake qtbase5-dev qtdeclarative5-dev libqt5webkit5-dev libsqlite3-dev
script:
- qmake -qt=qt5 uefitool.pro
- make
- os: linux
compiler: gcc
before_install:
- sudo add-apt-repository --yes ppa:ubuntu-sdk-team/ppa
- sudo apt-get update -qq
- sudo apt-get install -qq qt5-qmake qtbase5-dev qtdeclarative5-dev libqt5webkit5-dev libsqlite3-dev
script:
- qmake -qt=qt5 uefitool.pro
- make

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,8 +25,8 @@ static ISzAlloc SzAllocForLzma = { &AllocForLzma, &FreeForLzma };
SRes OnProgress(void *p, UInt64 inSize, UInt64 outSize)
{
(void)p; (void) inSize; (void) outSize;
return SZ_OK;
(void)p; (void)inSize; (void)outSize;
return SZ_OK;
}
static ICompressProgress g_ProgressCallback = { &OnProgress };
@ -34,76 +34,76 @@ static ICompressProgress g_ProgressCallback = { &OnProgress };
STATIC
UINT64
EFIAPI
RShiftU64(
UINT64 Operand,
UINT32 Count
RShiftU64 (
UINT64 Operand,
UINT32 Count
)
{
return Operand >> Count;
return Operand >> Count;
}
VOID
SetEncodedSizeOfBuf(
UINT64 EncodedSize,
UINT8 *EncodedData
SetEncodedSizeOfBuf (
UINT64 EncodedSize,
UINT8 *EncodedData
)
{
INT32 Index;
INT32 Index;
EncodedData[LZMA_PROPS_SIZE] = EncodedSize & 0xFF;
for (Index = LZMA_PROPS_SIZE + 1; Index <= LZMA_PROPS_SIZE + 7; Index++)
{
EncodedSize = RShiftU64(EncodedSize, 8);
EncodedData[Index] = EncodedSize & 0xFF;
}
EncodedData[LZMA_PROPS_SIZE] = EncodedSize & 0xFF;
for (Index = LZMA_PROPS_SIZE + 1; Index <= LZMA_PROPS_SIZE + 7; Index++)
{
EncodedSize = RShiftU64(EncodedSize, 8);
EncodedData[Index] = EncodedSize & 0xFF;
}
}
INT32
EFIAPI
LzmaCompress(
CONST UINT8 *Source,
UINT32 SourceSize,
UINT8 *Destination,
UINT32 *DestinationSize
CONST UINT8 *Source,
UINTN SourceSize,
UINT8 *Destination,
UINTN *DestinationSize
)
{
SRes LzmaResult;
CLzmaEncProps props;
SizeT propsSize = LZMA_PROPS_SIZE;
SizeT destLen = SourceSize + SourceSize / 3 + 128;
SRes LzmaResult;
CLzmaEncProps props;
SizeT propsSize = LZMA_PROPS_SIZE;
SizeT destLen = SourceSize + SourceSize / 3 + 128;
if (*DestinationSize < destLen)
{
*DestinationSize = destLen;
return ERR_BUFFER_TOO_SMALL;
}
if (*DestinationSize < destLen)
{
*DestinationSize = destLen;
return ERR_BUFFER_TOO_SMALL;
}
LzmaEncProps_Init(&props);
props.dictSize = LZMA_DICTIONARY_SIZE;
props.level = 9;
props.fb = 273;
LzmaEncProps_Init(&props);
props.dictSize = LZMA_DICTIONARY_SIZE;
props.level = 9;
props.fb = 273;
LzmaResult = LzmaEncode(
(Byte*)((UINT8*)Destination + LZMA_HEADER_SIZE),
&destLen,
Source,
SourceSize,
&props,
(UINT8*)Destination,
&propsSize,
props.writeEndMark,
&g_ProgressCallback,
&SzAllocForLzma,
&SzAllocForLzma);
LzmaResult = LzmaEncode(
(Byte*)((UINT8*)Destination + LZMA_HEADER_SIZE),
&destLen,
Source,
SourceSize,
&props,
(UINT8*)Destination,
&propsSize,
props.writeEndMark,
&g_ProgressCallback,
&SzAllocForLzma,
&SzAllocForLzma);
*DestinationSize = destLen + LZMA_HEADER_SIZE;
*DestinationSize = destLen + LZMA_HEADER_SIZE;
SetEncodedSizeOfBuf((UINT64)SourceSize, Destination);
SetEncodedSizeOfBuf(SourceSize, Destination);
if (LzmaResult == SZ_OK) {
return ERR_SUCCESS;
}
else {
return ERR_INVALID_PARAMETER;
}
if (LzmaResult == SZ_OK) {
return ERR_SUCCESS;
}
else {
return ERR_INVALID_PARAMETER;
}
}

View file

@ -28,9 +28,9 @@ extern "C" {
EFIAPI
LzmaCompress(
const UINT8 *Source,
UINT32 SourceSize,
UINTN SourceSize,
UINT8 *Destination,
UINT32 *DestinationSize
UINTN *DestinationSize
);
#ifdef __cplusplus

View file

@ -20,11 +20,11 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
UINT64
EFIAPI
LShiftU64(
UINT64 Operand,
UINT32 Count
UINT64 Operand,
UINT32 Count
)
{
return Operand << Count;
return Operand << Count;
}
static void * AllocForLzma(void *p, size_t size) { (void)p; return malloc(size); }
@ -40,18 +40,18 @@ Get the size of the uncompressed buffer by parsing EncodeData header.
*/
UINT64
GetDecodedSizeOfBuf(
UINT8 *EncodedData
UINT8 *EncodedData
)
{
UINT64 DecodedSize;
INT32 Index;
UINT64 DecodedSize;
INT32 Index;
// Parse header
DecodedSize = 0;
for (Index = LZMA_PROPS_SIZE + 7; Index >= LZMA_PROPS_SIZE; Index--)
DecodedSize = LShiftU64(DecodedSize, 8) + EncodedData[Index];
// Parse header
DecodedSize = 0;
for (Index = LZMA_PROPS_SIZE + 7; Index >= LZMA_PROPS_SIZE; Index--)
DecodedSize = LShiftU64(DecodedSize, 8) + EncodedData[Index];
return DecodedSize;
return DecodedSize;
}
//
@ -88,19 +88,15 @@ buffer was returned ScratchSize.
INT32
EFIAPI
LzmaGetInfo(
CONST VOID *Source,
UINT32 SourceSize,
UINT32 *DestinationSize
CONST VOID *Source,
UINTN SourceSize,
UINTN *DestinationSize
)
{
UInt64 DecodedSize;
ASSERT(SourceSize >= LZMA_HEADER_SIZE); (void)SourceSize;
ASSERT(SourceSize >= LZMA_HEADER_SIZE); (void)SourceSize;
DecodedSize = GetDecodedSizeOfBuf((UINT8*)Source);
*DestinationSize = (UINT32)DecodedSize;
return ERR_SUCCESS;
*DestinationSize = (UINTN)GetDecodedSizeOfBuf((UINT8*)Source);
return ERR_SUCCESS;
}
/*
@ -125,35 +121,35 @@ The source buffer specified by Source is corrupted
INT32
EFIAPI
LzmaDecompress(
CONST VOID *Source,
UINT32 SourceSize,
VOID *Destination
CONST VOID *Source,
UINTN SourceSize,
VOID *Destination
)
{
SRes LzmaResult;
ELzmaStatus Status;
SizeT DecodedBufSize;
SizeT EncodedDataSize;
SRes LzmaResult;
ELzmaStatus Status;
SizeT DecodedBufSize;
SizeT EncodedDataSize;
DecodedBufSize = (SizeT)GetDecodedSizeOfBuf((UINT8*)Source);
EncodedDataSize = (SizeT)(SourceSize - LZMA_HEADER_SIZE);
DecodedBufSize = (SizeT)GetDecodedSizeOfBuf((UINT8*)Source);
EncodedDataSize = (SizeT)(SourceSize - LZMA_HEADER_SIZE);
LzmaResult = LzmaDecode(
(Byte*)Destination,
&DecodedBufSize,
(Byte*)((UINT8*)Source + LZMA_HEADER_SIZE),
&EncodedDataSize,
(CONST Byte*) Source,
LZMA_PROPS_SIZE,
LZMA_FINISH_END,
&Status,
&SzAllocForLzma
);
LzmaResult = LzmaDecode(
(Byte*)Destination,
&DecodedBufSize,
(Byte*)((UINT8*)Source + LZMA_HEADER_SIZE),
&EncodedDataSize,
(CONST Byte*) Source,
LZMA_PROPS_SIZE,
LZMA_FINISH_END,
&Status,
&SzAllocForLzma
);
if (LzmaResult == SZ_OK) {
return ERR_SUCCESS;
}
else {
return ERR_INVALID_PARAMETER;
}
if (LzmaResult == SZ_OK) {
return ERR_SUCCESS;
}
else {
return ERR_INVALID_PARAMETER;
}
}

View file

@ -61,8 +61,8 @@ extern "C" {
EFIAPI
LzmaGetInfo(
const VOID *Source,
UINT32 SourceSize,
UINT32 *DestinationSize
UINTN SourceSize,
UINTN *DestinationSize
);
/*
@ -88,8 +88,8 @@ extern "C" {
EFIAPI
LzmaDecompress(
const VOID *Source,
UINT32 SourceSize,
VOID *Destination
UINTN SourceSize,
VOID *Destination
);
#ifdef __cplusplus

File diff suppressed because it is too large Load diff

View file

@ -32,85 +32,82 @@ Header file for compression routine.
extern "C" {
#endif
/*++
/*++
Routine Description:
Routine Description:
Tiano compression routine.
Tiano compression routine.
Arguments:
Arguments:
SrcBuffer - The buffer storing the source data
SrcSize - The size of source data
DstBuffer - The buffer to store the compressed data
DstSize - On input, the size of DstBuffer; On output,
the size of the actual compressed data.
SrcBuffer - The buffer storing the source data
SrcSize - The size of source data
DstBuffer - The buffer to store the compressed data
DstSize - On input, the size of DstBuffer; On output,
the size of the actual compressed data.
Returns:
Returns:
EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. this case,
DstSize contains the size needed.
EFI_SUCCESS - Compression is successful.
EFI_OUT_OF_RESOURCES - No resource to complete function.
EFI_INVALID_PARAMETER - Parameter supplied is wrong.
EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. this case,
DstSize contains the size needed.
EFI_SUCCESS - Compression is successful.
EFI_OUT_OF_RESOURCES - No resource to complete function.
EFI_INVALID_PARAMETER - Parameter supplied is wrong.
--*/
EFI_STATUS
TianoCompress(
CONST VOID *SrcBuffer,
UINT32 SrcSize,
VOID *DstBuffer,
UINT32 *DstSize
)
;
--*/
EFI_STATUS
TianoCompress(
IN CONST VOID *SrcBuffer,
IN UINT32 SrcSize,
IN VOID *DstBuffer,
IN OUT UINT32 *DstSize
);
EFI_STATUS
TianoCompressLegacy(
CONST VOID *SrcBuffer,
UINT32 SrcSize,
VOID *DstBuffer,
UINT32 *DstSize
)
;
/*++
EFI_STATUS
TianoCompressLegacy(
CONST VOID *SrcBuffer,
UINT32 SrcSize,
VOID *DstBuffer,
UINT32 *DstSize
);
/*++
Routine Description:
Routine Description:
EFI 1.1 compression routine.
EFI 1.1 compression routine.
Arguments:
Arguments:
SrcBuffer - The buffer storing the source data
SrcSize - The size of source data
DstBuffer - The buffer to store the compressed data
DstSize - On input, the size of DstBuffer; On output,
the size of the actual compressed data.
SrcBuffer - The buffer storing the source data
SrcSize - The size of source data
DstBuffer - The buffer to store the compressed data
DstSize - On input, the size of DstBuffer; On output,
the size of the actual compressed data.
Returns:
Returns:
EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. this case,
DstSize contains the size needed.
EFI_SUCCESS - Compression is successful.
EFI_OUT_OF_RESOURCES - No resource to complete function.
EFI_INVALID_PARAMETER - Parameter supplied is wrong.
EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. this case,
DstSize contains the size needed.
EFI_SUCCESS - Compression is successful.
EFI_OUT_OF_RESOURCES - No resource to complete function.
EFI_INVALID_PARAMETER - Parameter supplied is wrong.
--*/
EFI_STATUS
EfiCompress(
CONST VOID *SrcBuffer,
UINT32 SrcSize,
VOID *DstBuffer,
UINT32 *DstSize
)
;
EFI_STATUS
EfiCompressLegacy(
CONST VOID *SrcBuffer,
UINT32 SrcSize,
VOID *DstBuffer,
UINT32 *DstSize
)
;
--*/
EFI_STATUS
EfiCompress(
IN CONST VOID *SrcBuffer,
IN UINT32 SrcSize,
IN VOID *DstBuffer,
IN OUT UINT32 *DstSize
);
EFI_STATUS
EfiCompressLegacy(
CONST VOID *SrcBuffer,
UINT32 SrcSize,
VOID *DstBuffer,
UINT32 *DstSize
);
#ifdef __cplusplus
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -37,14 +37,13 @@ extern "C" {
UINT32 OrigSize;
} EFI_TIANO_HEADER;
EFI_STATUS
EFIAPI
EfiTianoGetInfo(
const VOID *Source,
UINT32 SrcSize,
UINT32 *DstSize,
UINT32 *ScratchSize
)
EFI_STATUS
EfiTianoGetInfo(
IN const VOID *Source,
IN UINT32 SrcSize,
OUT UINT32 *DstSize,
OUT UINT32 *ScratchSize
)
/*++
Routine Description:
@ -67,16 +66,16 @@ extern "C" {
--*/
;
EFI_STATUS
EFIAPI
EfiDecompress(
const VOID *Source,
UINT32 SrcSize,
VOID *Destination,
UINT32 DstSize,
VOID *Scratch,
UINT32 ScratchSize
)
EFI_STATUS
EFIAPI
EfiDecompress(
IN const VOID *Source,
IN UINT32 SrcSize,
IN OUT VOID *Destination,
IN UINT32 DstSize,
IN OUT VOID *Scratch,
IN UINT32 ScratchSize
)
/*++
Routine Description:
@ -101,16 +100,16 @@ extern "C" {
--*/
;
EFI_STATUS
EFIAPI
TianoDecompress(
const VOID *Source,
UINT32 SrcSize,
VOID *Destination,
UINT32 DstSize,
VOID *Scratch,
UINT32 ScratchSize
)
EFI_STATUS
EFIAPI
TianoDecompress(
IN const VOID *Source,
IN UINT32 SrcSize,
IN OUT VOID *Destination,
IN UINT32 DstSize,
IN OUT VOID *Scratch,
IN UINT32 ScratchSize
)
/*++
Routine Description:

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,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,52 +0,0 @@
/* uefifind.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 __UEFIFIND_H__
#define __UEFIFIND_H__
#include <QObject>
#include <QByteArray>
#include <QString>
#include <QDir>
#include <QFileInfo>
#include <QPair>
#include <QSet>
#include <QString>
#include <QUuid>
#include "../basetypes.h"
#include "../ffsengine.h"
#include "../ffs.h"
class UEFIFind : public QObject
{
Q_OBJECT
public:
explicit UEFIFind(QObject *parent = 0);
~UEFIFind();
UINT8 init(const QString & path);
UINT8 find(const UINT8 mode, const bool count, const QString & hexPattern, QString & result);
private:
UINT8 findFileRecursive(const QModelIndex index, const QString & hexPattern, const UINT8 mode, QSet<QPair<QModelIndex, QModelIndex> > & files);
QString guidToQString(const UINT8* guid);
FfsEngine* ffsEngine;
TreeModel* model;
QFileInfo fileInfo;
bool initDone;
};
#endif

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

@ -34,9 +34,26 @@ F7731B4C-58A2-4DF4-8980-5645D39ECE58 10 P:0FBA6C24380F:0FBA7424380F
# PowerManagement | Sandy Bridge with ME 8.xx, Ivy Bridge
8C783970-F02A-4A4D-AF09-8797A51EEC8D 10 P:75080FBAE80F89442430:EB080FBAE80F89442430
# PowerManagement | New SB-E/IB-E
8C783970-F02A-4A4D-AF09-8797A51EEC8D 10 P:0FBA6C24380F:0FBA7424380F
# CpuPei | Sandy Bridge with ME 7.xx, old SB-E/IB-E
2BB5AFA9-FF33-417B-8497-CB773C2B93BF 10 P:800018EB050D0080:000018EB050D0000
# PpmInitialize | Broadwell-E
3FFCAE95-23CF-4967-94F5-16352F68E43B 10 P:0FBA6C24400F:0FBA7424400F
# SiInit | Skylake
299D6F8B-2EC9-4E40-9EC6-DDAA7EBF5FD9 10 P:75080D00800000:EB080D00800000
299D6F8B-2EC9-4E40-9EC6-DDAA7EBF5FD9 12 P:75080D00800000:EB080D00800000
# SiInit | Kaby Lake
299D6F8B-2EC9-4E40-9EC6-DDAA7EBF5FD9 10 P:81E10080000033C1:9090909090909090
299D6F8B-2EC9-4E40-9EC6-DDAA7EBF5FD9 12 P:81E10080000033C1:9090909090909090
# PpmInitialize | Skylake-X
3FFCAE95-23CF-4967-94F5-16352F68E43B 10 P:742CB9E2000000:752CB9E2000000
# CpuInitPei | Skylake-X
01359D99-9446-456D-ADA4-50A711C03ADA 12 P:BE0080000023CE0B:BE0000000023CE0B

View file

@ -1,6 +1,6 @@
/* uefipatch_main.cpp
Copyright (c) 2015, Nikolaj Schlej. All rights reserved.
Copyright (c) 2018, LongSoft. All rights reserved.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@ -19,8 +19,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
a.setOrganizationName("CodeRush");
a.setOrganizationDomain("coderush.me");
a.setOrganizationName("LongSoft");
a.setOrganizationDomain("longsoft.me");
a.setApplicationName("UEFIPatch");
UEFIPatch w;
@ -31,7 +31,7 @@ int main(int argc, char *argv[])
result = w.patchFromFile(a.arguments().at(1));
}
else {
std::cout << "UEFIPatch 0.3.4 - UEFI image file patching utility" << std::endl << std::endl <<
std::cout << "UEFIPatch 0.3.14 - UEFI image file patching utility" << std::endl << std::endl <<
"Usage: UEFIPatch image_file" << std::endl << std::endl <<
"Patches will be read from patches.txt file\n";
return ERR_SUCCESS;

108
UEFIReplace/uefireplace.cpp Normal file
View file

@ -0,0 +1,108 @@
/* 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(QString inPath, const QByteArray & guid, const UINT8 sectionType, const QString contentPath)
{
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);
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(inPath.append(".patched"));
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)
{
if (!model || !index.isValid())
return ERR_INVALID_PARAMETER;
if (model->subtype(index) == sectionType) {
QModelIndex fileIndex = model->findParentOfType(index, Types::File);
QByteArray fileGuid = model->header(fileIndex).left(sizeof(EFI_GUID));
if (fileGuid == guid) {
return ffsEngine->replace(index, newData, REPLACE_MODE_BODY);
}
}
bool patched = false;
if (model->rowCount(index) > 0) {
for (int i = 0; i < model->rowCount(index); i++) {
UINT8 result = replaceInFile(index.child(i, 0), guid, sectionType, newData);
if (!result) {
patched = true;
break;
} else if (result != ERR_NOTHING_TO_PATCH)
return result;
}
}
return patched ? ERR_SUCCESS : ERR_NOTHING_TO_PATCH;
}

View file

@ -1,43 +1,41 @@
/* uefiextract.h
Copyright (c) 2014, Nikolaj Schlej. All rights reserved.
/* uefireplace.h
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.
*/
#ifndef __UEFIEXTRACT_H__
#define __UEFIEXTRACT_H__
#ifndef __UEFIREPLACE_H__
#define __UEFIREPLACE_H__
#include <QObject>
#include <QByteArray>
#include <QString>
#include <QDir>
#include <QStringList>
#include <QFileInfo>
#include <QUuid>
#include "../basetypes.h"
#include "../ffs.h"
#include "../ffsengine.h"
class UEFIExtract : public QObject
class UEFIReplace : public QObject
{
Q_OBJECT
public:
explicit UEFIExtract(QObject *parent = 0);
~UEFIExtract();
explicit UEFIReplace(QObject *parent = 0);
~UEFIReplace();
UINT8 init(const QString & path);
UINT8 extract(QString guid = QString());
UINT8 replace(const QString inPath, const QByteArray & guid, const UINT8 sectionType, const QString contentPath);
private:
UINT8 replaceInFile(const QModelIndex & index, const QByteArray & guid, const UINT8 sectionType, const QByteArray & contents);
FfsEngine* ffsEngine;
QFileInfo fileInfo;
TreeModel* model;
};
#endif

View file

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

View file

@ -0,0 +1,78 @@
/* 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 "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 0.1.2 - UEFI image file replacement utility" << std::endl << std::endl <<
"Usage: UEFIReplace image_file guid section_type contents_file" << 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
result = r.replace(args.at(1), guid, sectionType, args.at(4));
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

@ -85,6 +85,8 @@ typedef unsigned int UINTN;
#define ERR_INVALID_SYMBOL 40
#define ERR_NOTHING_TO_PATCH 41
#define ERR_DEPEX_PARSE_FAILED 42
#define ERR_TRUNCATED_IMAGE 43
#define ERR_BAD_RELOCATION_ENTRY 44
#define ERR_NOT_IMPLEMENTED 0xFF
// UDK porting definitions

View file

@ -17,11 +17,11 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "basetypes.h"
// Make sure we use right packing rules
#pragma pack(push,1)
#pragma pack(push, 1)
// 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
} FLASH_DESCRIPTOR_HEADER;
@ -34,37 +34,41 @@ typedef struct _FLASH_DESCRIPTOR_HEADER {
// Descriptor map
// Base fields are storing bits [11:4] of actual base addresses, all other bits are 0
typedef struct _FLASH_DESCRIPTOR_MAP {
UINT8 ComponentBase; // 0x03 on most machines
UINT8 NumberOfFlashChips; // Zero-based number of flash chips installed on board
UINT8 RegionBase; // 0x04 on most machines
UINT8 NumberOfRegions; // Zero-based number of flash regions (descriptor is always included)
UINT8 MasterBase; // 0x06 on most machines
UINT8 NumberOfMasters; // Zero-based number of flash masters
UINT8 PchStrapsBase; // 0x10 on most machines
UINT8 NumberOfPchStraps; // One-based number of UINT32s to read as PCH Straps, min=0, max=255 (1 Kb)
UINT8 ProcStrapsBase; // 0x20 on most machines
UINT8 NumberOfProcStraps; // Number of PROC straps to be read, can be 0 or 1
UINT8 IccTableBase; // 0x21 on most machines
UINT8 NumberOfIccTableEntries; // 0x00 on most machines
UINT8 DmiTableBase; // 0x25 on most machines
UINT8 NumberOfDmiTableEntries; // 0x00 on most machines
UINT16 ReservedZero; // Still unknown, zeros in all descriptors I have seen
// FLMAP0
UINT32 ComponentBase : 8;
UINT32 NumberOfFlashChips : 2; // Zero-based number of flash chips installed on board
UINT32 : 6;
UINT32 RegionBase : 8;
UINT32 NumberOfRegions : 3; // Reserved in v2 descriptor
UINT32 : 5;
// FLMAP 1
UINT32 MasterBase : 8;
UINT32 NumberOfMasters : 2; // Zero-based number of flash masters
UINT32 : 6;
UINT32 PchStrapsBase : 8;
UINT32 NumberOfPchStraps : 8; // One-based number of UINT32s to read as PCH straps, min=0, max=255 (1 Kb)
// FLMAP 2
UINT32 ProcStrapsBase : 8;
UINT32 NumberOfProcStraps : 8; // One-based number of UINT32s to read as processor straps, min=0, max=255 (1 Kb)
UINT32: 16;
} FLASH_DESCRIPTOR_MAP;
#define FLASH_DESCRIPTOR_MAX_BASE 0xE0
// Component section
// Flash parameters DWORD structure
typedef struct _FLASH_PARAMETERS {
UINT8 FirstChipDensity : 3;
UINT8 SecondChipDensity : 3;
UINT8 ReservedZero0 : 2; // Still unknown, zeros in all descriptors I have seen
UINT8 ReservedZero1 : 8; // Still unknown, zeros in all descriptors I have seen
UINT8 ReservedZero2 : 4; // Still unknown, zeros in all descriptors I have seen
UINT8 FirstChipDensity : 4;
UINT8 SecondChipDensity : 4;
UINT8 : 8;
UINT8 : 1;
UINT8 ReadClockFrequency : 3; // Hardcoded value of 20 Mhz (000b) in v1 descriptors and 17 Mhz (110b) in v2 ones
UINT8 FastReadEnabled : 1;
UINT8 FastReadFreqency : 3;
UINT8 FlashReadStatusFrequency : 3;
UINT8 FastReadFrequency : 3;
UINT8 FlashWriteFrequency : 3;
UINT8 FlashReadStatusFrequency : 3;
UINT8 DualOutputFastReadSupported : 1;
UINT8 ReservedZero3 : 1; // Still unknown, zero in all descriptors I have seen
UINT8 : 1;
} FLASH_PARAMETERS;
// Flash densities
@ -74,11 +78,16 @@ typedef struct _FLASH_PARAMETERS {
#define FLASH_DENSITY_4MB 0x03
#define FLASH_DENSITY_8MB 0x04
#define FLASH_DENSITY_16MB 0x05
#define FLASH_DENSITY_32MB 0x06
#define FLASH_DENSITY_64MB 0x07
#define FLASH_DENSITY_UNUSED 0x0F
// Flash frequencies
#define FLASH_FREQUENCY_20MHZ 0x00
#define FLASH_FREQUENCY_33MHZ 0x01
#define FLASH_FREQUENCY_50MHZ 0x04
#define FLASH_FREQUENCY_20MHZ 0x00
#define FLASH_FREQUENCY_33MHZ 0x01
#define FLASH_FREQUENCY_48MHZ 0x02
#define FLASH_FREQUENCY_50MHZ_30MHZ 0x04
#define FLASH_FREQUENCY_17MHZ 0x06
// Component section structure
typedef struct _FLASH_DESCRIPTOR_COMPONENT_SECTION {
@ -87,52 +96,82 @@ typedef struct _FLASH_DESCRIPTOR_COMPONENT_SECTION {
UINT8 InvalidInstruction1; //
UINT8 InvalidInstruction2; //
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;
// 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
// All base and limit register are storing upper part of actual UINT32 base and limit
// If limit is zero - region is not present
typedef struct _FLASH_DESCRIPTOR_REGION_SECTION {
UINT16 ReservedZero; // Still unknown, zero in all descriptors I have seen
UINT16 FlashBlockEraseSize; // Size of block erased by single BLOCK ERASE command
UINT16 BiosBase;
UINT16 BiosLimit;
UINT16 MeBase;
UINT16 MeLimit;
UINT16 GbeBase;
UINT16 GbeLimit;
UINT16 PdrBase;
UINT16 PdrLimit;
UINT16 DescriptorBase; // Descriptor
UINT16 DescriptorLimit; //
UINT16 BiosBase; // BIOS
UINT16 BiosLimit; //
UINT16 MeBase; // ME
UINT16 MeLimit; //
UINT16 GbeBase; // GbE
UINT16 GbeLimit; //
UINT16 PdrBase; // PDR
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 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
typedef struct _FLASH_DESCRIPTOR_MASTER_SECTION {
UINT16 BiosId;
UINT8 BiosRead;
UINT8 BiosWrite;
UINT8 BiosRead;
UINT8 BiosWrite;
UINT16 MeId;
UINT8 MeRead;
UINT8 MeWrite;
UINT8 MeRead;
UINT8 MeWrite;
UINT16 GbeId;
UINT8 GbeRead;
UINT8 GbeWrite;
UINT8 GbeRead;
UINT8 GbeWrite;
} 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
#define FLASH_DESCRIPTOR_REGION_ACCESS_DESC 0x01
#define FLASH_DESCRIPTOR_REGION_ACCESS_BIOS 0x02
#define FLASH_DESCRIPTOR_REGION_ACCESS_ME 0x04
#define FLASH_DESCRIPTOR_REGION_ACCESS_GBE 0x08
#define FLASH_DESCRIPTOR_REGION_ACCESS_PDR 0x10
//!TODO: Describe PCH and PROC straps sections, as well as ICC and DMI tables
#define FLASH_DESCRIPTOR_REGION_ACCESS_EC 0x20
// Base address of descriptor upper map
#define FLASH_DESCRIPTOR_UPPER_MAP_BASE 0x0EFC
@ -155,7 +194,7 @@ typedef struct _VSCC_TABLE_ENTRY {
// Base address and size of OEM section
#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
#pragma pack(pop)

21
ffs.cpp
View file

@ -30,7 +30,10 @@ const QVector<QByteArray> FFSv3Volumes =
const UINT8 ffsAlignmentTable[] =
{ 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)
return 0;
@ -40,7 +43,15 @@ UINT8 calculateChecksum8(const UINT8* buffer, UINT32 bufferSize)
while (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)
@ -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_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_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");
default: return QObject::tr("Unknown");
};
@ -156,9 +169,9 @@ UINT32 sizeOfSectionHeader(const EFI_COMMON_SECTION_HEADER* header)
return 0;
bool extended = false;
/*if (uint24ToUint32(header->Size) == EFI_SECTION2_IS_USED) {
if (uint24ToUint32(header->Size) == EFI_SECTION2_IS_USED) {
extended = true;
}*/
}
switch (header->Type)
{

45
ffs.h
View file

@ -32,7 +32,7 @@ extern QString sectionTypeToQString(const UINT8 type);
//*****************************************************************************
// EFI Capsule
//*****************************************************************************
// Capsule header
// Standard EFI Capsule header
typedef struct _EFI_CAPSULE_HEADER {
EFI_GUID CapsuleGuid;
UINT32 HeaderSize;
@ -49,16 +49,32 @@ typedef struct _EFI_CAPSULE_HEADER {
const QByteArray EFI_CAPSULE_GUID
("\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
typedef struct _APTIO_CAPSULE_HEADER {
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
//!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
//FW_CERTIFICATE FWCert;
//ROM_AREA RomAreaMap[1];
//ROM_AREA RomAreaMap[1];
} APTIO_CAPSULE_HEADER;
// AMI Aptio signed extended capsule GUID
@ -93,7 +109,7 @@ typedef struct _EFI_FIRMWARE_VOLUME_HEADER {
UINT16 ExtHeaderOffset; //Reserved in Revision 1
UINT8 Reserved;
UINT8 Revision;
//EFI_FV_BLOCK_MAP_ENTRY FvBlockMap[1];
//EFI_FV_BLOCK_MAP_ENTRY FvBlockMap[2];
} EFI_FIRMWARE_VOLUME_HEADER;
// Standard file system GUIDs
@ -252,8 +268,8 @@ extern UINT16 calculateChecksum16(const UINT16* buffer, UINT32 bufferSize);
// Integrity check
typedef union {
struct {
UINT8 Header;
UINT8 File;
UINT8 Header;
UINT8 File;
} Checksum;
UINT16 TailReference; // Revision 1
UINT16 Checksum16; // Revision 2
@ -276,7 +292,7 @@ UINT8 Type;
UINT8 Attributes;
UINT8 Size[3]; // Set to 0xFFFFFF
UINT8 State;
UINT32 ExtendedSize;
UINT64 ExtendedSize;
} EFI_FFS_FILE_HEADER2;
// 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_COMBINED_SMM_DXE 0x0C
#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_MAX 0xDF
#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_RECOVERY 0x02 // Valid only for revision 1 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_DATA_ALIGNMENT 0x38
#define FFS_ATTRIB_CHECKSUM 0x40
@ -317,6 +336,9 @@ UINT32 ExtendedSize;
// FFS alignment table
extern const UINT8 ffsAlignmentTable[];
// Extended FFS alignment table
extern const UINT8 ffsAlignment2Table[];
// File states
#define EFI_FILE_HEADER_CONSTRUCTION 0x01
#define EFI_FILE_HEADER_VALID 0x02
@ -324,6 +346,7 @@ extern const UINT8 ffsAlignmentTable[];
#define EFI_FILE_MARKED_FOR_UPDATE 0x08
#define EFI_FILE_DELETED 0x10
#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
const QByteArray EFI_PEI_APRIORI_FILE_GUID
@ -344,7 +367,9 @@ const QByteArray EFI_FFS_PAD_FILE_GUID
// FFS size conversion routines
extern VOID uint32ToUint24(UINT32 size, 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);
//*****************************************************************************
@ -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_HEADER2 EFI_USER_INTERFACE_SECTION2;
//Section routines
// Section routines
extern UINT32 sizeOfSectionHeader(const EFI_COMMON_SECTION_HEADER* header);
//*****************************************************************************

File diff suppressed because it is too large Load diff

View file

@ -67,9 +67,10 @@ public:
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 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 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 parseSection(const QByteArray & section, QModelIndex & index, const QModelIndex & parent = QModelIndex(), const UINT8 mode = CREATE_MODE_APPEND);
@ -81,8 +82,8 @@ public:
UINT8 reconstructImageFile(QByteArray &reconstructed);
UINT8 reconstruct(const QModelIndex &index, QByteArray & reconstructed);
UINT8 reconstructIntelImage(const QModelIndex& index, QByteArray & reconstructed);
UINT8 reconstructRegion(const QModelIndex& index, QByteArray & reconstructed);
UINT8 reconstructBios(const QModelIndex& index, QByteArray & reconstructed);
UINT8 reconstructRegion(const QModelIndex& index, QByteArray & reconstructed, bool includeHeader = true);
UINT8 reconstructPadding(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 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 remove(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 patch(const QModelIndex & index, const QVector<PatchData> & patches);
@ -115,7 +117,6 @@ private:
UINT8 parseDepexSection(const QByteArray & body, QString & parsed);
UINT8 findNextVolume(const QByteArray & bios, const UINT32 volumeOffset, UINT32 & nextVolumeOffset);
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);
// Reconstruction helpers
@ -125,7 +126,7 @@ private:
// Rebase routines
UINT8 getBase(const QByteArray& file, UINT32& base);
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);
// Patch routines

63
macbuild.sh Executable file
View file

@ -0,0 +1,63 @@
#!/bin/bash
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"
echo "Attempting to build UEFITool for macOS..."
UEFITOOL_VER=$(cat uefitool.cpp | grep ^version | cut -d'"' -f2)
UEFIPATCH_VER=$(cat UEFIPatch/uefipatch_main.cpp | grep '"UEFIPatch [0-9]' | cut -d'"' -f2 | cut -d' ' -f2)
UEFIREPLACE_VER=$(cat UEFIReplace/uefireplace_main.cpp | grep '"UEFIReplace [0-9]' | cut -d'"' -f2 | 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
qmake $3 QMAKE_CXXFLAGS+=-flto QMAKE_LFLAGS+=-flto CONFIG+=optimize_size || exit 1
make || exit 1
# Archive
if [ "$1" = "UEFITool" ]; then
strip -x UEFITool.app/Contents/MacOS/UEFITool || exit 1
zip -qry dist/"UEFITool_${UEFITOOL_VER}_mac.zip" UEFITool.app "${4}" || exit 1
else
strip -x "$1" || exit 1
zip -qry ../dist/"${1}_${2}_mac.zip" "${1}" "${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 "$UEFIPATCH_VER" uefipatch.pro patches.txt
build_tool UEFIReplace "$UEFIREPLACE_VER" uefireplace.pro
exit 0

View file

@ -17,7 +17,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
TreeItem::TreeItem(const UINT8 type, const UINT8 subtype, const UINT8 compression,
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) :
itemAction(Actions::NoAction),
itemType(type),
@ -28,7 +28,6 @@ TreeItem::TreeItem(const UINT8 type, const UINT8 subtype, const UINT8 compressio
itemInfo(info),
itemHeader(header),
itemBody(body),
itemParsingData(parsingData),
parentItem(parent)
{
}
@ -184,11 +183,6 @@ QByteArray TreeItem::body() const
return itemBody;
}
QByteArray TreeItem::parsingData() const
{
return itemParsingData;
}
bool TreeItem::hasEmptyHeader() const
{
return itemHeader.isEmpty();
@ -199,16 +193,6 @@ bool TreeItem::hasEmptyBody() const
return itemBody.isEmpty();
}
bool TreeItem::hasEmptyParsingData() const
{
return itemParsingData.isEmpty();
}
void TreeItem::setParsingData(const QByteArray & data)
{
itemParsingData = data;
}
UINT8 TreeItem::action() const
{
return itemAction;

View file

@ -26,7 +26,7 @@ class TreeItem
public:
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 QByteArray & header = QByteArray(), const QByteArray & body = QByteArray(), const QByteArray & parsingData = QByteArray(),
const QByteArray & header = QByteArray(), const QByteArray & body = QByteArray(),
TreeItem *parent = 0);
~TreeItem();
@ -63,10 +63,6 @@ public:
QByteArray body() const;
bool hasEmptyBody() const;
QByteArray parsingData() const;
bool hasEmptyParsingData() const;
void setParsingData(const QByteArray & data);
QString info() const;
void addInfo(const QString &info);
void setInfo(const QString &info);
@ -87,7 +83,6 @@ private:
QString itemInfo;
QByteArray itemHeader;
QByteArray itemBody;
QByteArray itemParsingData;
TreeItem *parentItem;
};

View file

@ -178,22 +178,6 @@ bool TreeModel::hasEmptyBody(const QModelIndex &index) const
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
{
if (!index.isValid())
@ -284,20 +268,9 @@ void TreeModel::setAction(const QModelIndex &index, const UINT8 action)
emit dataChanged(this->index(0, 0), index);
}
void TreeModel::setParsingData(const QModelIndex &index, const QByteArray &data)
{
if (!index.isValid())
return;
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
item->setParsingData(data);
emit dataChanged(this->index(0, 0), index);
}
QModelIndex TreeModel::addItem(const UINT8 type, const UINT8 subtype, const UINT8 compression,
const QString & name, const QString & text, const QString & info,
const QByteArray & header, const QByteArray & body, const QByteArray & parsingData,
const QModelIndex & parent, const UINT8 mode)
const QByteArray & header, const QByteArray & body, const QModelIndex & parent, const UINT8 mode)
{
TreeItem *item = 0;
TreeItem *parentItem = 0;
@ -318,7 +291,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) {
emit layoutAboutToBeChanged();
parentItem->appendChild(newItem);

View file

@ -65,7 +65,7 @@ public:
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 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);
QModelIndex findParentOfType(const QModelIndex & index, UINT8 type) const;

View file

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

30
types.h
View file

@ -26,7 +26,8 @@ namespace Actions
Replace,
Remove,
Rebuild,
Rebase
Rebase,
DoNotRebuild
};
}
@ -54,7 +55,8 @@ namespace Subtypes {
enum CapsuleSubtypes {
AptioSignedCapsule = 80,
AptioUnsignedCapsule,
UefiCapsule
UefiCapsule,
ToshibaCapsule
};
enum VolumeSubtypes {
@ -68,7 +70,8 @@ namespace Subtypes {
GbeRegion,
MeRegion,
BiosRegion,
PdrRegion
PdrRegion,
EcRegion
};
enum PaddingSubtypes {
@ -85,25 +88,4 @@ extern QString itemSubtypeToQString(const UINT8 type, const UINT8 subtype);
extern QString compressionTypeToQString(const UINT8 algorithm);
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

View file

@ -16,8 +16,8 @@
UEFITool::UEFITool(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::UEFITool),
version(tr("0.20.4"))
ui(new Ui::UEFITool),
version(tr("0.23.1"))
{
clipboard = QApplication::clipboard();
@ -31,6 +31,7 @@ version(tr("0.20.4"))
// Connect signals to slots
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->actionSearch, SIGNAL(triggered()), this, SLOT(search()));
connect(ui->actionExtract, SIGNAL(triggered()), this, SLOT(extractAsIs()));
@ -42,6 +43,7 @@ version(tr("0.20.4"))
connect(ui->actionReplaceBody, SIGNAL(triggered()), this, SLOT(replaceBody()));
connect(ui->actionRemove, SIGNAL(triggered()), this, SLOT(remove()));
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->actionMessagesCopyAll, SIGNAL(triggered()), this, SLOT(copyAllMessages()));
connect(ui->actionMessagesClear, SIGNAL(triggered()), this, SLOT(clearMessages()));
@ -83,6 +85,11 @@ UEFITool::~UEFITool()
delete searchDialog;
}
void UEFITool::setProgramPath(QString path)
{
currentProgramPath = path;
};
void UEFITool::init()
{
// Clear components
@ -140,6 +147,7 @@ void UEFITool::populateUi(const QModelIndex &current)
// Enable actions
ui->actionExtract->setDisabled(model->hasEmptyHeader(current) && model->hasEmptyBody(current));
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->actionRemove->setEnabled(type == Types::Volume || type == Types::File || type == Types::Section);
ui->actionInsertInto->setEnabled((type == Types::Volume && subtype != Subtypes::UnknownVolume) ||
@ -147,7 +155,7 @@ void UEFITool::populateUi(const QModelIndex &current)
(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->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->actionMessagesCopy->setEnabled(false);
}
@ -214,6 +222,18 @@ void UEFITool::rebuild()
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()
{
QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex();
@ -321,6 +341,13 @@ void UEFITool::replace(const UINT8 mode)
else
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) {
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 (*)");
@ -358,6 +385,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 (*)");
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 (*)");
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
path = QFileDialog::getOpenFileName(this, tr("Select file to replace body"), currentDir, "Binary files (*.bin);;All files (*)");
}
@ -447,7 +476,7 @@ void UEFITool::extract(const UINT8 mode)
case Types::Capsule:
path = QFileDialog::getSaveFileName(this, tr("Save capsule body to image file"), currentDir, "Image files (*.rom *.bin);;All files (*)");
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 (*)");
break;
case Types::File: {
@ -521,7 +550,7 @@ void UEFITool::exit()
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())
return;
@ -552,10 +581,18 @@ void UEFITool::saveImageFile()
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);
}
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)
{
if (path.trimmed().isEmpty())

View file

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

View file

@ -180,7 +180,7 @@
<x>0</x>
<y>0</y>
<width>800</width>
<height>21</height>
<height>31</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
@ -188,6 +188,7 @@
<string>&amp;File</string>
</property>
<addaction name="actionOpenImageFile"/>
<addaction name="actionOpenImageFileInNewWindow"/>
<addaction name="actionSaveImageFile"/>
<addaction name="separator"/>
<addaction name="actionSearch"/>
@ -224,6 +225,8 @@
</property>
<addaction name="actionExtract"/>
<addaction name="separator"/>
<addaction name="actionDoNotRebuild"/>
<addaction name="separator"/>
<addaction name="actionReplace"/>
</widget>
<widget class="QMenu" name="menuPaddingActions">
@ -231,6 +234,8 @@
<string>&amp;Padding</string>
</property>
<addaction name="actionExtract"/>
<addaction name="separator"/>
<addaction name="actionReplace"/>
</widget>
<widget class="QMenu" name="menuVolumeActions">
<property name="title">
@ -240,6 +245,7 @@
<addaction name="actionExtractBody"/>
<addaction name="separator"/>
<addaction name="actionRebuild"/>
<addaction name="actionDoNotRebuild"/>
<addaction name="separator"/>
<addaction name="actionInsertInto"/>
<addaction name="separator"/>
@ -254,6 +260,7 @@
<addaction name="actionExtractBody"/>
<addaction name="separator"/>
<addaction name="actionRebuild"/>
<addaction name="actionDoNotRebuild"/>
<addaction name="separator"/>
<addaction name="actionInsertInto"/>
<addaction name="actionInsertBefore"/>
@ -272,6 +279,7 @@
<addaction name="actionExtractBody"/>
<addaction name="separator"/>
<addaction name="actionRebuild"/>
<addaction name="actionDoNotRebuild"/>
<addaction name="separator"/>
<addaction name="actionInsertInto"/>
<addaction name="actionInsertBefore"/>
@ -281,7 +289,6 @@
<addaction name="actionReplaceBody"/>
<addaction name="separator"/>
<addaction name="actionRemove"/>
<addaction name="separator"/>
</widget>
<widget class="QMenu" name="menuMessages">
<property name="title">
@ -522,6 +529,28 @@
<string>Ctrl+Alt+C</string>
</property>
</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>
<layoutdefault spacing="6" margin="11"/>
<resources/>

View file

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