Merge pull request #5 from NikolajSchlej/CUI

Cui
This commit is contained in:
Nikolaj Schlej 2014-04-22 03:16:49 +02:00
commit 14c19ce664
10 changed files with 316 additions and 23 deletions

13
ffs.h
View File

@ -48,7 +48,8 @@ typedef struct {
#define EFI_CAPSULE_HEADER_FLAG_POPULATE_SYSTEM_TABLE 0x00020000
// Standard 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);
const QByteArray EFI_CAPSULE_GUID
("\xBD\x86\x66\x3B\x76\x0D\x30\x40\xB7\x0E\xB5\x51\x9E\x2F\xC5\xA0", 16);
// AMI Aptio extended capsule header
typedef struct {
@ -379,6 +380,16 @@ typedef struct {
#define EFI_GUIDED_SECTION_PROCESSING_REQUIRED 0x01
#define EFI_GUIDED_SECTION_AUTH_STATUS_VALID 0x02
// GUIDs of GUID-defined sections
const QByteArray EFI_GUIDED_SECTION_CRC32 // FC1BCDB0-7D31-49AA-936A-A4600D9DD083
("\xB0\xCD\x1B\xFC\x31\x7D\xAA\x49\x93\x6A\xA4\x60\x0D\x9D\xD0\x83", 16);
const QByteArray EFI_GUIDED_SECTION_TIANO // A31280AD-481E-41B6-95E8-127F4C984779
("\xAD\x80\x12\xA3\x1E\x48\xB6\x41\x95\xE8\x12\x7F\x4C\x98\x47\x79", 16);
const QByteArray EFI_GUIDED_SECTION_LZMA // EE4E5898-3914-4259-9D6E-DC7BD79403CF
("\x98\x58\x4E\xEE\x14\x39\x59\x42\x9D\x6E\xDC\x7B\xD7\x94\x03\xCF", 16);
// Version section
typedef struct {
UINT8 Size[3];

View File

@ -24,6 +24,8 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "LZMA/LzmaCompress.h"
#include "LZMA/LzmaDecompress.h"
#include <iostream>
FfsEngine::FfsEngine(QObject *parent)
: QObject(parent)
{
@ -44,9 +46,14 @@ TreeModel* FfsEngine::treeModel() const
void FfsEngine::msg(const QString & message, const QModelIndex & index)
{
#ifndef _CONSOLE
messageItems.enqueue(MessageListItem(message, NULL, 0, index));
#else
std::cout << message.toLatin1().constData() << std::endl;
#endif
}
#ifndef _CONSOLE
QQueue<MessageListItem> FfsEngine::messages() const
{
return messageItems;
@ -56,6 +63,7 @@ void FfsEngine::clearMessages()
{
messageItems.clear();
}
#endif
bool FfsEngine::hasIntersection(const UINT32 begin1, const UINT32 end1, const UINT32 begin2, const UINT32 end2)
{
@ -1086,30 +1094,68 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c
guidDefinedSectionHeader = (EFI_GUID_DEFINED_SECTION*) (header.constData());
body = section.mid(guidDefinedSectionHeader->DataOffset, sectionSize - guidDefinedSectionHeader->DataOffset);
QByteArray decompressed = body;
// Get info
name = guidToQString(guidDefinedSectionHeader->SectionDefinitionGuid);
info = tr("Type: %1\nSize: %2\nData offset: %3\nAttributes: %4")
.arg(sectionHeader->Type, 2, 16, QChar('0'))
.arg(body.size(), 8, 16, QChar('0'))
.arg(guidDefinedSectionHeader->DataOffset, 4, 16, QChar('0'))
.arg(guidDefinedSectionHeader->Attributes, 4, 16, QChar('0'));
UINT8 algorithm = COMPRESSION_ALGORITHM_NONE;
// Check if section requires processing
if (guidDefinedSectionHeader->Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) {
// Try to decompress section body using both known compression algorithms
algorithm = COMPRESSION_ALGORITHM_UNKNOWN;
// Tiano
result = decompress(body, EFI_STANDARD_COMPRESSION, decompressed, &algorithm);
if (result) {
// Tiano compressed section
if (QByteArray((const char*)&guidDefinedSectionHeader->SectionDefinitionGuid, sizeof(EFI_GUID)) == EFI_GUIDED_SECTION_TIANO) {
algorithm = COMPRESSION_ALGORITHM_UNKNOWN;
info += tr("\nCompression type: Tiano");
result = decompress(body, EFI_STANDARD_COMPRESSION, decompressed, &algorithm);
if (result) {
msg(tr("parseSection: GUID defined section can not be decompressed (%1)").arg(result), parent);
parseCurrentSection = false;
}
}
// LZMA compressed section
else if (QByteArray((const char*)&guidDefinedSectionHeader->SectionDefinitionGuid, sizeof(EFI_GUID)) == EFI_GUIDED_SECTION_LZMA) {
algorithm = COMPRESSION_ALGORITHM_UNKNOWN;
info += tr("\nCompression type: LZMA");
result = decompress(body, EFI_CUSTOMIZED_COMPRESSION, decompressed, &algorithm);
if (result) {
msg(tr("parseSection: GUID defined section can not be decompressed (%1)").arg(result), parent);
parseCurrentSection = false;
}
}
// Unknown GUIDed section
else {
msg(tr("parseSection: GUID defined section (%1) with unknown processing method")
.arg(guidToQString(guidDefinedSectionHeader->SectionDefinitionGuid)), parent);
parseCurrentSection = false;
}
}
// Check if section requires checksum calculation
else if (guidDefinedSectionHeader->Attributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID)
{
// CRC32 section
if (QByteArray((const char*)&guidDefinedSectionHeader->SectionDefinitionGuid, sizeof(EFI_GUID)) == EFI_GUIDED_SECTION_CRC32) {
info += tr("\nChecksum type: CRC32");
// Calculate CRC32 of section data
UINT32 crc = crc32(0, NULL, 0);
crc = crc32(crc, (const UINT8*) body.constData(), body.size());
// Check stored CRC32
if (crc == *(UINT32*)(header.constData() + sizeof(EFI_GUID_DEFINED_SECTION))) {
info += tr("\nChecksum: valid");
}
else {
info += tr("\nChecksum: invalid");
msg(tr("parseSection: GUID defined section with invalid CRC32"), parent);
}
}
else {
msg(tr("parseSection: GUID defined section (%1) with unknown authentification method")
.arg(guidToQString(guidDefinedSectionHeader->SectionDefinitionGuid)), parent);
}
}
// Get info
name = guidToQString(guidDefinedSectionHeader->SectionDefinitionGuid);
info = tr("Type: %1\nSize: %2\nData offset: %3\nAttributes: %4\nCompression type: %5")
.arg(sectionHeader->Type, 2, 16, QChar('0'))
.arg(body.size(), 8, 16, QChar('0'))
.arg(guidDefinedSectionHeader->DataOffset, 4, 16, QChar('0'))
.arg(guidDefinedSectionHeader->Attributes, 4, 16, QChar('0'))
.arg(compressionTypeToQString(algorithm));
// Add tree item
index = model->addItem(Types::Section, sectionHeader->Type, algorithm, name, "", info, header, body, QByteArray(), parent, mode);
@ -2577,8 +2623,18 @@ UINT8 FfsEngine::reconstructSection(const QModelIndex& index, const UINT32 base,
return result;
// Check for authentication status valid attribute
if (guidDefinedHeader->Attributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) {
msg(tr("reconstructSection: %1: GUID defined section signature can now become invalid")
.arg(guidToQString(guidDefinedHeader->SectionDefinitionGuid)), index);
// CRC32 section
if (QByteArray((const char*)&guidDefinedHeader->SectionDefinitionGuid, sizeof(EFI_GUID)) == EFI_GUIDED_SECTION_CRC32) {
// Calculate CRC32 of section data
UINT32 crc = crc32(0, NULL, 0);
crc = crc32(crc, (const UINT8*)compressed.constData(), compressed.size());
// Store new CRC32
*(UINT32*)(header.data() + sizeof(EFI_GUID_DEFINED_SECTION)) = crc;
}
else {
msg(tr("reconstructSection: %1: GUID defined section authentification info can become invalid")
.arg(guidToQString(guidDefinedHeader->SectionDefinitionGuid)), index);
}
}
// Replace new section body
reconstructed = compressed;
@ -3068,3 +3124,55 @@ UINT8 FfsEngine::getBase(const QByteArray& file, UINT32& base)
return ERR_SUCCESS;
}
UINT32 FfsEngine::crc32(UINT32 initial, const UINT8* buffer, UINT32 length)
{
static const UINT32 crcTable[256] = {
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535,
0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD,
0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D,
0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4,
0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC,
0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,
0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F,
0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB,
0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA,
0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE,
0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A,
0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409,
0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739,
0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268,
0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0,
0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8,
0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF,
0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703,
0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7,
0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE,
0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6,
0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D,
0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5,
0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605,
0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D };
UINT32 crc32;
UINT32 i;
/** accumulate crc32 for buffer **/
crc32 = initial ^ 0xFFFFFFFF;
for (i = 0; i < length; i++) {
crc32 = (crc32 >> 8) ^ crcTable[(crc32 ^ buffer[i]) & 0xFF];
}
return(crc32 ^ 0xFFFFFFFF);
}

View File

@ -20,9 +20,12 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "basetypes.h"
#include "treemodel.h"
#include "messagelistitem.h"
#include "peimage.h"
#ifndef _CONSOLE
#include "messagelistitem.h"
#endif
class TreeModel;
class FfsEngine : public QObject
@ -37,11 +40,12 @@ public:
// Returns model for Qt view classes
TreeModel* treeModel() const;
#ifndef _CONSOLE
// Returns message items queue
QQueue<MessageListItem> messages() const;
// Clears message items queue
void clearMessages();
#endif
// Firmware image parsing
UINT8 parseImageFile(const QByteArray & buffer);
@ -110,12 +114,15 @@ private:
// Patch routines
UINT8 patchVtf(QByteArray &vtf);
// Message helper
#ifndef _CONSOLE
QQueue<MessageListItem> messageItems;
#endif
// Message helper
void msg(const QString & message, const QModelIndex &index = QModelIndex());
// Internal operations
bool hasIntersection(const UINT32 begin1, const UINT32 end1, const UINT32 begin2, const UINT32 end2);
UINT32 crc32(UINT32 initial, const UINT8* buffer, UINT32 length);
};
#endif

48
uefiextract.cpp Normal file
View File

@ -0,0 +1,48 @@
/* 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::extractAll(QString path)
{
QFileInfo 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();
UINT8 result = ffsEngine->parseImageFile(buffer);
if (result)
return result;
return ERR_SUCCESS;
}

39
uefiextract.h Normal file
View File

@ -0,0 +1,39 @@
/* uefiextract.h
Copyright (c) 2014, Nikolaj Schlej. All rights reserved.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*/
#ifndef __UEFIEXTRACT_H__
#define __UEFIEXTRACT_H__
#include <QObject>
#include <QByteArray>
#include <QString>
#include <QFileInfo>
#include "basetypes.h"
#include "ffsengine.h"
class UEFIExtract : public QObject
{
Q_OBJECT
public:
explicit UEFIExtract(QObject *parent = 0);
~UEFIExtract();
UINT8 extractAll(QString path);
private:
FfsEngine* ffsEngine;
};
#endif

41
uefiextract.pro Normal file
View File

@ -0,0 +1,41 @@
QT += core
QT -= gui
TARGET = UEFIExtract
TEMPLATE = app
CONFIG += console
SOURCES += uefiextract_main.cpp \
uefiextract.cpp \
types.cpp \
descriptor.cpp \
ffs.cpp \
ffsengine.cpp \
treeitem.cpp \
treemodel.cpp \
messagelistitem.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
HEADERS += uefiextract.h \
basetypes.h \
descriptor.h \
gbe.h \
me.h \
ffs.h \
peimage.h \
types.h \
ffsengine.h \
treeitem.h \
treemodel.h \
messagelistitem.h \
LZMA/LzmaCompress.h \
LZMA/LzmaDecompress.h \
Tiano/EfiTianoDecompress.h \
Tiano/EfiTianoCompress.h

39
uefiextract_main.cpp Normal file
View File

@ -0,0 +1,39 @@
/* uefiextract_main.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 <QCoreApplication>
#include <QString>
#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;
if (a.arguments().length() > 1) {
UINT8 result = w.extractAll(a.arguments().at(1));
//!TODO: error messages
return result;
}
else {
std::cout << "UEFIExtract 0.1.0" << std::endl << std::endl <<
"Usage: uefiextract imagefile\n" << std::endl;
return 0;
}
return a.exec();
}

View File

@ -4,7 +4,7 @@ greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = UEFITool
TEMPLATE = app
SOURCES += main.cpp \
SOURCES += uefitool_main.cpp \
uefitool.cpp \
searchdialog.cpp \
types.cpp \

View File

@ -20,7 +20,7 @@
<bool>true</bool>
</property>
<property name="windowTitle">
<string>UEFITool 0.17.8</string>
<string>UEFITool 0.17.9</string>
</property>
<widget class="QWidget" name="centralWidget">
<property name="sizePolicy">

View File

@ -1,4 +1,4 @@
/* main.cpp
/* uefitool_main.cpp
Copyright (c) 2014, Nikolaj Schlej. All rights reserved.
This program and the accompanying materials