Compare commits

...

32 commits

Author SHA1 Message Date
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
26 changed files with 1485 additions and 539 deletions

3
.gitignore vendored
View file

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

14
.travis.yml Normal file
View file

@ -0,0 +1,14 @@
language: cpp
compiler:
- clang
- 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

@ -1,6 +1,6 @@
/* uefiextract_main.cpp /* uefiextract_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
@ -19,8 +19,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
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("UEFIExtract"); a.setApplicationName("UEFIExtract");
UEFIExtract w; UEFIExtract w;
@ -52,7 +52,7 @@ int main(int argc, char *argv[])
} }
else { else {
std::cout << "UEFIExtract 0.4.4" << std::endl << std::endl << std::cout << "UEFIExtract 0.4.5" << std::endl << std::endl <<
"Usage: uefiextract imagefile [FileGUID_1 FileGUID_2 ... FileGUID_31]" << 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; "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; return 1;

View file

@ -34,9 +34,27 @@ 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
# SiInit | Skylake-X
D71C8BA4-4AF2-4D0D-B1BA-F2409F0C20D3 10 P:81E10080000033C1:9090909090909090
D71C8BA4-4AF2-4D0D-B1BA-F2409F0C20D3 12 P:81E10080000033C1:9090909090909090
# PpmInitialize | Skylake-X, Kaby Lake-X
3FFCAE95-23CF-4967-94F5-16352F68E43B 10 P:0FBAE80F:0FBAE00F

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
@ -19,8 +19,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
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;
@ -31,7 +31,7 @@ int main(int argc, char *argv[])
result = w.patchFromFile(a.arguments().at(1)); result = w.patchFromFile(a.arguments().at(1));
} }
else { else {
std::cout << "UEFIPatch 0.3.4 - UEFI image file patching utility" << std::endl << std::endl << std::cout << "UEFIPatch 0.3.12 - UEFI image file patching utility" << std::endl << std::endl <<
"Usage: UEFIPatch image_file" << std::endl << std::endl << "Usage: UEFIPatch image_file" << std::endl << std::endl <<
"Patches will be read from patches.txt file\n"; "Patches will be read from patches.txt file\n";
return ERR_SUCCESS; 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;
}

41
UEFIReplace/uefireplace.h Normal file
View file

@ -0,0 +1,41 @@
/* 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 __UEFIREPLACE_H__
#define __UEFIREPLACE_H__
#include <QObject>
#include <QByteArray>
#include <QString>
#include <QStringList>
#include <QFileInfo>
#include <QUuid>
#include "../basetypes.h"
#include "../ffs.h"
#include "../ffsengine.h"
class UEFIReplace : public QObject
{
Q_OBJECT
public:
explicit UEFIReplace(QObject *parent = 0);
~UEFIReplace();
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;
TreeModel* model;
};
#endif

View file

@ -0,0 +1,42 @@
QT += core
QT -= gui
TARGET = UEFIReplace
TEMPLATE = app
CONFIG += console
CONFIG -= app_bundle
DEFINES += _CONSOLE
SOURCES += uefireplace_main.cpp \
uefireplace.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 += uefireplace.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

@ -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.1 - 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_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;
@ -34,37 +34,41 @@ typedef struct _FLASH_DESCRIPTOR_HEADER {
// 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;
} 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 +78,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 +96,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 +194,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,9 +67,10 @@ 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);
@ -81,8 +82,8 @@ public:
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);
@ -115,7 +116,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 +125,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,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, 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),
@ -28,7 +28,6 @@ TreeItem::TreeItem(const UINT8 type, const UINT8 subtype, const UINT8 compressio
itemInfo(info), itemInfo(info),
itemHeader(header), itemHeader(header),
itemBody(body), itemBody(body),
itemParsingData(parsingData),
parentItem(parent) parentItem(parent)
{ {
} }
@ -184,11 +183,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,16 +193,6 @@ 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;

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);
@ -87,7 +83,6 @@ private:
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())
@ -284,20 +268,9 @@ 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)
{
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, 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 +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) { if (mode == CREATE_MODE_APPEND) {
emit layoutAboutToBeChanged(); emit layoutAboutToBeChanged();
parentItem->appendChild(newItem); 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, 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);
@ -149,4 +153,4 @@ QString actionTypeToQString(const UINT8 action)
default: default:
return QObject::tr("Unknown"); return QObject::tr("Unknown");
} }
} }

27
types.h
View file

@ -54,7 +54,8 @@ namespace Subtypes {
enum CapsuleSubtypes { enum CapsuleSubtypes {
AptioSignedCapsule = 80, AptioSignedCapsule = 80,
AptioUnsignedCapsule, AptioUnsignedCapsule,
UefiCapsule UefiCapsule,
ToshibaCapsule
}; };
enum VolumeSubtypes { enum VolumeSubtypes {
@ -68,7 +69,8 @@ namespace Subtypes {
GbeRegion, GbeRegion,
MeRegion, MeRegion,
BiosRegion, BiosRegion,
PdrRegion PdrRegion,
EcRegion
}; };
enum PaddingSubtypes { enum PaddingSubtypes {
@ -85,25 +87,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

@ -16,8 +16,8 @@
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("0.22.3"))
{ {
clipboard = QApplication::clipboard(); clipboard = QApplication::clipboard();
@ -31,6 +31,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()));
@ -83,6 +84,11 @@ UEFITool::~UEFITool()
delete searchDialog; delete searchDialog;
} }
void UEFITool::setProgramPath(QString path)
{
currentProgramPath = path;
};
void UEFITool::init() void UEFITool::init()
{ {
// Clear components // Clear components
@ -147,7 +153,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);
} }
@ -321,6 +327,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 +371,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 +462,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 +536,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 +567,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();
@ -95,6 +98,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

@ -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"/>
@ -231,6 +232,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">
@ -522,6 +525,17 @@
<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>
</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();