Improve firmware parser and tool robustness

closes #241
This commit is contained in:
joevt 2021-10-07 18:51:39 +03:00 committed by vit9696
parent e14547c497
commit f9c35f77a6
41 changed files with 415 additions and 324 deletions

2
.gitignore vendored
View file

@ -238,6 +238,7 @@ UEFITool.app/
UEFITool/XCBuildData UEFITool/XCBuildData
UEFIDump/UEFIDump UEFIDump/UEFIDump
UEFIExtract/UEFIExtract UEFIExtract/UEFIExtract
UEFIExtract/guids.csv
UEFIFind/UEFIFind UEFIFind/UEFIFind
.qmake.stash .qmake.stash
CMakeCache.txt CMakeCache.txt
@ -250,3 +251,4 @@ CMakeScripts
UEFITool/qrc_uefitool.cpp UEFITool/qrc_uefitool.cpp
XcodeQT5 XcodeQT5
XcodeQT6 XcodeQT6
*.dSYM

View file

@ -21,16 +21,20 @@ USTATUS FfsDumper::dump(const UModelIndex & root, const UString & path, const Du
counterHeader = counterBody = counterRaw = counterInfo = 0; counterHeader = counterBody = counterRaw = counterInfo = 0;
fileList.clear(); fileList.clear();
if (changeDirectory(path)) if (changeDirectory(path)) {
printf("Directory \"%s\" already exists.\n", (const char*)path.toLocal8Bit());
return U_DIR_ALREADY_EXIST; return U_DIR_ALREADY_EXIST;
}
currentPath = path; currentPath = path;
USTATUS result = recursiveDump(root, path, dumpMode, sectionType, guid); USTATUS result = recursiveDump(root, path, dumpMode, sectionType, guid);
if (result) { if (result) {
printf("Error %lu returned from recursiveDump (directory \"%s\").\n", result, (const char*)path.toLocal8Bit());
return result; return result;
} else if (!dumped) { } else if (!dumped) {
removeDirectory(path); removeDirectory(path);
printf("Removed directory \"%s\" since nothing was dumped.\n", (const char*)path.toLocal8Bit());
return U_ITEM_NOT_FOUND; return U_ITEM_NOT_FOUND;
} }
@ -48,8 +52,10 @@ USTATUS FfsDumper::recursiveDump(const UModelIndex & index, const UString & path
guidToUString(readUnaligned((const EFI_GUID*)model->header(index).constData())) == guid || guidToUString(readUnaligned((const EFI_GUID*)model->header(index).constData())) == guid ||
guidToUString(readUnaligned((const EFI_GUID*)model->header(model->findParentOfType(index, Types::File)).constData())) == guid) { guidToUString(readUnaligned((const EFI_GUID*)model->header(model->findParentOfType(index, Types::File)).constData())) == guid) {
if (!changeDirectory(path) && !makeDirectory(path)) if (!changeDirectory(path) && !makeDirectory(path)) {
printf("Cannot use directory \"%s\" (recursiveDump part 1).\n", (const char*)path.toLocal8Bit());
return U_DIR_CREATE; return U_DIR_CREATE;
}
if (currentPath != path) { if (currentPath != path) {
counterHeader = counterBody = counterRaw = counterInfo = 0; counterHeader = counterBody = counterRaw = counterInfo = 0;
@ -72,8 +78,10 @@ USTATUS FfsDumper::recursiveDump(const UModelIndex & index, const UString & path
counterHeader++; counterHeader++;
std::ofstream file(filename.toLocal8Bit(), std::ofstream::binary); std::ofstream file(filename.toLocal8Bit(), std::ofstream::binary);
if (!file) if (!file) {
printf("Cannot open header \"%s\".\n", (const char*)filename.toLocal8Bit());
return U_FILE_OPEN; return U_FILE_OPEN;
}
const UByteArray &data = model->header(index); const UByteArray &data = model->header(index);
file.write(data.constData(), data.size()); file.write(data.constData(), data.size());
@ -92,8 +100,10 @@ USTATUS FfsDumper::recursiveDump(const UModelIndex & index, const UString & path
counterBody++; counterBody++;
std::ofstream file(filename.toLocal8Bit(), std::ofstream::binary); std::ofstream file(filename.toLocal8Bit(), std::ofstream::binary);
if (!file) if (!file) {
printf("Cannot open body \"%s\".\n", (const char*)filename.toLocal8Bit());
return U_FILE_OPEN; return U_FILE_OPEN;
}
const UByteArray &data = model->body(index); const UByteArray &data = model->body(index);
file.write(data.constData(), data.size()); file.write(data.constData(), data.size());
@ -121,8 +131,10 @@ USTATUS FfsDumper::recursiveDump(const UModelIndex & index, const UString & path
counterRaw++; counterRaw++;
std::ofstream file(filename.toLocal8Bit(), std::ofstream::binary); std::ofstream file(filename.toLocal8Bit(), std::ofstream::binary);
if (!file) if (!file) {
printf("Cannot open file \"%s\".\n", (const char*)filename.toLocal8Bit());
return U_FILE_OPEN; return U_FILE_OPEN;
}
const UByteArray &headerData = model->header(fileIndex); const UByteArray &headerData = model->header(fileIndex);
const UByteArray &bodyData = model->body(fileIndex); const UByteArray &bodyData = model->body(fileIndex);
@ -155,8 +167,10 @@ USTATUS FfsDumper::recursiveDump(const UModelIndex & index, const UString & path
counterInfo++; counterInfo++;
std::ofstream file(filename.toLocal8Bit()); std::ofstream file(filename.toLocal8Bit());
if (!file) if (!file) {
printf("Cannot open info \"%s\".\n", (const char*)filename.toLocal8Bit());
return U_FILE_OPEN; return U_FILE_OPEN;
}
file << info.toLocal8Bit(); file << info.toLocal8Bit();
@ -174,15 +188,20 @@ USTATUS FfsDumper::recursiveDump(const UModelIndex & index, const UString & path
UString childPath = path; UString childPath = path;
if (dumpMode == DUMP_ALL || dumpMode == DUMP_CURRENT) { if (dumpMode == DUMP_ALL || dumpMode == DUMP_CURRENT) {
if (!changeDirectory(path) && !makeDirectory(path)) if (!changeDirectory(path) && !makeDirectory(path)) {
printf("Cannot use directory \"%s\" (recursiveDump part 2).\n", (const char*)path.toLocal8Bit());
return U_DIR_CREATE; return U_DIR_CREATE;
}
childPath = usprintf("%s/%d %s", path.toLocal8Bit(), i, UString name = usprintf("%d %s", i, (useText ? model->text(childIndex) : model->name(childIndex)).toLocal8Bit());
(useText ? model->text(childIndex) : model->name(childIndex)).toLocal8Bit()); fixFileName (name, false);
childPath = usprintf("%s/%s", path.toLocal8Bit(), name.toLocal8Bit());
} }
result = recursiveDump(childIndex, childPath, dumpMode, sectionType, guid); result = recursiveDump(childIndex, childPath, dumpMode, sectionType, guid);
if (result) if (result) {
printf("Error %lu returned from recursiveDump (child directory \"%s\").\n", result, (const char*)childPath.toLocal8Bit());
return result; return result;
}
} }
return U_SUCCESS; return U_SUCCESS;

View file

@ -41,27 +41,8 @@ USTATUS UEFIDumper::dump(const UByteArray & buffer, const UString & inPath, cons
USTATUS result = ffsParser.parse(buffer); USTATUS result = ffsParser.parse(buffer);
if (result) if (result)
return result; return result;
// Show ffsParser messages
std::vector<std::pair<UString, UModelIndex> > messages = ffsParser.getMessages();
for (size_t i = 0; i < messages.size(); i++) {
std::cout << messages[i].first << std::endl;
}
// Show FIT table ffsParser.outputInfo();
std::vector<std::pair<std::vector<UString>, UModelIndex > > fitTable = ffsParser.getFitTable();
if (fitTable.size()) {
std::cout << "-------------------------------------------------------------------------" << std::endl;
std::cout << " Address | Size | Ver | CS | Type / Info " << std::endl;
std::cout << "-------------------------------------------------------------------------" << std::endl;
for (size_t i = 0; i < fitTable.size(); i++) {
std::cout << fitTable[i].first[0].toLocal8Bit() << " | "
<< fitTable[i].first[1].toLocal8Bit() << " | "
<< fitTable[i].first[2].toLocal8Bit() << " | "
<< fitTable[i].first[3].toLocal8Bit() << " | "
<< fitTable[i].first[4].toLocal8Bit() << " | "
<< fitTable[i].first[5].toLocal8Bit() << std::endl;
}
}
// Create ffsReport // Create ffsReport
FfsReport ffsReport(&model); FfsReport ffsReport(&model);
@ -123,8 +104,10 @@ USTATUS UEFIDumper::recursiveDump(const UModelIndex & index)
name = orgName + UString("_") + usprintf("%03d", i); name = orgName + UString("_") + usprintf("%03d", i);
} }
if (!nameFound) if (!nameFound) {
printf("Cannot find unique name for \"%s\".\n", (const char*)orgName.toLocal8Bit());
return U_INVALID_PARAMETER; //TODO: replace with proper errorCode return U_INVALID_PARAMETER; //TODO: replace with proper errorCode
}
// Add header and body only for leaf sections // Add header and body only for leaf sections
if (model.rowCount(index) == 0) { if (model.rowCount(index) == 0) {

View file

@ -57,36 +57,7 @@ int main(int argc, char *argv[])
if (result) if (result)
return result; return result;
// Show ffsParser's messages ffsParser.outputInfo();
std::vector<std::pair<UString, UModelIndex> > messages = ffsParser.getMessages();
for (size_t i = 0; i < messages.size(); i++) {
std::cout << messages[i].first.toLocal8Bit() << std::endl;
}
// Get last VTF
std::vector<std::pair<std::vector<UString>, UModelIndex > > fitTable = ffsParser.getFitTable();
if (fitTable.size()) {
std::cout << "---------------------------------------------------------------------------" << std::endl;
std::cout << " Address | Size | Ver | CS | Type / Info " << std::endl;
std::cout << "---------------------------------------------------------------------------" << std::endl;
for (size_t i = 0; i < fitTable.size(); i++) {
std::cout << fitTable[i].first[0].toLocal8Bit() << " | "
<< fitTable[i].first[1].toLocal8Bit() << " | "
<< fitTable[i].first[2].toLocal8Bit() << " | "
<< fitTable[i].first[3].toLocal8Bit() << " | "
<< fitTable[i].first[4].toLocal8Bit() << " | "
<< fitTable[i].first[5].toLocal8Bit() << std::endl;
}
}
// Get security info
UString secInfo = ffsParser.getSecurityInfo();
if (!secInfo.isEmpty()) {
std::cout << "------------------------------------------------------------------------" << std::endl;
std::cout << "Security Info" << std::endl;
std::cout << "------------------------------------------------------------------------" << std::endl;
std::cout << secInfo << std::endl;
}
// Create ffsDumper // Create ffsDumper
FfsDumper ffsDumper(&model); FfsDumper ffsDumper(&model);

View file

@ -59,7 +59,7 @@ USTATUS UEFIFind::find(const UINT8 mode, const bool count, const UString & hexPa
if (count) { if (count) {
if (!files.empty()) if (!files.empty())
result += usprintf("%d\n", files.size()); result += usprintf("%lu\n", files.size());
return U_SUCCESS; return U_SUCCESS;
} }

View file

@ -13,6 +13,12 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "ffsfinder.h" #include "ffsfinder.h"
#if QT_VERSION_MAJOR >= 6
#include <QRegularExpression>
#else
#include <QRegExp>
#endif
USTATUS FfsFinder::findHexPattern(const UModelIndex & index, const UByteArray & hexPattern, const UINT8 mode) USTATUS FfsFinder::findHexPattern(const UModelIndex & index, const UByteArray & hexPattern, const UINT8 mode)
{ {
//TODO: use FfsUtils. //TODO: use FfsUtils.

View file

@ -16,12 +16,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <vector> #include <vector>
#if QT_VERSION_MAJOR >= 6
#include <QRegularExpression>
#else
#include <QRegExp>
#endif
#include "../common/ubytearray.h" #include "../common/ubytearray.h"
#include "../common/ustring.h" #include "../common/ustring.h"
#include "../common/basetypes.h" #include "../common/basetypes.h"

View file

@ -46,7 +46,7 @@ void GuidLineEdit::keyPressEvent(QKeyEvent * event)
if (txt[i] != QChar('-')) if (txt[i] != QChar('-'))
txt[i] = QChar('.'); txt[i] = QChar('.');
} }
else else
txt[pos] = QChar('.'); txt[pos] = QChar('.');
setCursorPosition(0); setCursorPosition(0);

View file

@ -32,8 +32,8 @@ CharCommand::CharCommand(Chunks * chunks, CCmd cmd, qint64 charPos, char newChar
_charPos = charPos; _charPos = charPos;
_newChar = newChar; _newChar = newChar;
_cmd = cmd; _cmd = cmd;
_wasChanged = false; _wasChanged = false;
_oldChar = ' '; _oldChar = ' ';
} }
bool CharCommand::mergeWith(const QUndoCommand *command) bool CharCommand::mergeWith(const QUndoCommand *command)

View file

@ -124,10 +124,10 @@ void QHexEdit::setAsciiArea(bool asciiArea)
{ {
if (!asciiArea) if (!asciiArea)
_editAreaIsAscii = false; _editAreaIsAscii = false;
_asciiArea = asciiArea; _asciiArea = asciiArea;
adjust(); adjust();
setCursorPosition(_cursorPosition); setCursorPosition(_cursorPosition);
viewport()->update(); viewport()->update();
} }
bool QHexEdit::asciiArea() bool QHexEdit::asciiArea()
@ -753,8 +753,8 @@ void QHexEdit::keyPressEvent(QKeyEvent *event)
QByteArray ba = _chunks->data(getSelectionBegin(), getSelectionEnd() - getSelectionBegin()).toHex(); QByteArray ba = _chunks->data(getSelectionBegin(), getSelectionEnd() - getSelectionBegin()).toHex();
for (qint64 idx = 32; idx < ba.size(); idx += 33) for (qint64 idx = 32; idx < ba.size(); idx += 33)
ba.insert((int)idx, "\n"); ba.insert((int)idx, "\n");
if(_upperCase) if(_upperCase)
ba = ba.toUpper(); ba = ba.toUpper();
QClipboard *clipboard = QApplication::clipboard(); QClipboard *clipboard = QApplication::clipboard();
clipboard->setText(ba); clipboard->setText(ba);
} }

View file

@ -647,6 +647,7 @@ void UEFITool::openImageFile(QString path)
// Parse the image // Parse the image
USTATUS result = ffsParser->parse(buffer); USTATUS result = ffsParser->parse(buffer);
showParserMessages(); showParserMessages();
if (result) { if (result) {
QMessageBox::critical(this, tr("Image parsing failed"), errorCodeToUString(result), QMessageBox::Ok); QMessageBox::critical(this, tr("Image parsing failed"), errorCodeToUString(result), QMessageBox::Ok);
@ -655,6 +656,8 @@ void UEFITool::openImageFile(QString path)
else else
ui->statusBar->showMessage(tr("Opened: %1").arg(fileInfo.fileName())); ui->statusBar->showMessage(tr("Opened: %1").arg(fileInfo.fileName()));
ffsParser->outputInfo();
// Enable or disable FIT tab // Enable or disable FIT tab
showFitTable(); showFitTable();
@ -796,7 +799,7 @@ void UEFITool::showParserMessages()
#if QT_VERSION_MAJOR < 6 #if QT_VERSION_MAJOR < 6
std::pair<QString, QModelIndex> msg; std::pair<QString, QModelIndex> msg;
foreach (msg, messages) { foreach (msg, messages) {
#else #else
for (const auto &msg : messages) { for (const auto &msg : messages) {

View file

@ -41,6 +41,7 @@ HEADERS += uefitool.h \
../common/LZMA/LzmaDecompress.h \ ../common/LZMA/LzmaDecompress.h \
../common/Tiano/EfiTianoDecompress.h \ ../common/Tiano/EfiTianoDecompress.h \
../common/Tiano/EfiTianoCompress.h \ ../common/Tiano/EfiTianoCompress.h \
../common/uinttypes.h \
../common/ustring.h \ ../common/ustring.h \
../common/ubytearray.h \ ../common/ubytearray.h \
../common/bootguard.h \ ../common/bootguard.h \
@ -123,7 +124,5 @@ FORMS += uefitool.ui \
RESOURCES += uefitool.qrc RESOURCES += uefitool.qrc
RC_FILE = uefitool.rc RC_FILE = uefitool.rc
ICON = icons/uefitool.icns ICON = icons/uefitool.icns
ICONFILE.files = icons/uefitool.icns
ICONFILE.path = Contents/Resources
QMAKE_BUNDLE_DATA += ICONFILE QMAKE_BUNDLE_DATA += ICONFILE
QMAKE_INFO_PLIST = Info.plist QMAKE_INFO_PLIST = Info.plist

View file

@ -188,7 +188,7 @@ typedef struct EFI_TIME_ {
UINT8 Reserved0; UINT8 Reserved0;
UINT32 Nanosecond; // Nanosecond: 0 - 999,999,999 UINT32 Nanosecond; // Nanosecond: 0 - 999,999,999
INT16 TimeZone; // TimeZone: -1440 to 1440 or UNSPECIFIED (0x07FF) INT16 TimeZone; // TimeZone: -1440 to 1440 or UNSPECIFIED (0x07FF)
UINT8 Daylight; // Daylight: ADJUST_DAYLIGHT (1) or IN_DAYLIGHT (2) UINT8 Daylight; // Daylight: ADJUST_DAYLIGHT (1) or IN_DAYLIGHT (2)
UINT8 Reserved1; UINT8 Reserved1;
} EFI_TIME; } EFI_TIME;

View file

@ -22,6 +22,7 @@ extern "C" {
#include <string.h> #include <string.h>
#include <limits.h> #include <limits.h>
#include <ctype.h> #include <ctype.h>
#include "../uinttypes.h"
#if !defined (BSTRLIB_VSNP_OK) && !defined (BSTRLIB_NOVSNP) #if !defined (BSTRLIB_VSNP_OK) && !defined (BSTRLIB_NOVSNP)
# if defined (__TURBOC__) && !defined (__BORLANDC__) # if defined (__TURBOC__) && !defined (__BORLANDC__)
@ -138,9 +139,9 @@ extern int brtrimws (bstring b);
extern int btrimws (bstring b); extern int btrimws (bstring b);
#if !defined (BSTRLIB_NOVSNP) #if !defined (BSTRLIB_NOVSNP)
extern bstring bformat (const char * fmt, ...); extern bstring bformat (const char * fmt, ...) ATTRIBUTE_FORMAT_(printf, 1, 2);
extern int bformata (bstring b, const char * fmt, ...); extern int bformata (bstring b, const char * fmt, ...) ATTRIBUTE_FORMAT_(printf, 2, 3);
extern int bassignformat (bstring b, const char * fmt, ...); extern int bassignformat (bstring b, const char * fmt, ...) ATTRIBUTE_FORMAT_(printf, 2, 3);
extern int bvcformata (bstring b, int count, const char * fmt, va_list arglist); extern int bvcformata (bstring b, int count, const char * fmt, va_list arglist);
#define bvformata(ret, b, fmt, lastarg) { \ #define bvformata(ret, b, fmt, lastarg) { \

View file

@ -52,6 +52,7 @@
#include <stdlib.h> #include <stdlib.h>
#include "bstrlib.h" #include "bstrlib.h"
#include "../ubytearray.h" #include "../ubytearray.h"
#include "../uinttypes.h"
#ifdef __cplusplus #ifdef __cplusplus
@ -331,8 +332,8 @@ struct CBString : public tagbstring {
void trunc (int len); void trunc (int len);
// Miscellaneous methods. // Miscellaneous methods.
void format (const char * fmt, ...); void format (const char * fmt, ...) ATTRIBUTE_FORMAT_(printf, 2, 3);
void formata (const char * fmt, ...); void formata (const char * fmt, ...) ATTRIBUTE_FORMAT_(printf, 2, 3);
void fill (int length, unsigned char fill = ' '); void fill (int length, unsigned char fill = ' ');
void repeat (int count); void repeat (int count);
void ltrim (const CBString& b = CBString (bsStaticBlkParms (" \t\v\f\r\n"))); void ltrim (const CBString& b = CBString (bsStaticBlkParms (" \t\v\f\r\n")));
@ -364,10 +365,13 @@ struct CBString : public tagbstring {
// QString compatibility methods // QString compatibility methods
const char *toLocal8Bit() const { return *this; } const char *toLocal8Bit() const { return *this; }
bool contains(const char *str) { return find(str) >= 0; } bool contains(const char *str) { return find(str) >= 0; }
bool endsWith(const char *str) { int len = strlen(str); return (slen >= len && (find(str, slen - len) == (slen - len))); }
bool isEmpty() const { return slen == 0; } bool isEmpty() const { return slen == 0; }
void clear() { *this = ""; } void clear() { *this = ""; }
CBString left(int len) const { return midstr(0, len); } CBString left(int len) const { return midstr(0, len); }
CBString mid(int pos, int len) const { return midstr(pos, len); } CBString mid(int pos, int len) const { return midstr(pos, len); }
CBString chopped(int len) const { return midstr(slen - len, len); }
void chop(int len) { trunc(((slen > len) ? slen - len : 0)); }
static CBString fromUtf16(const unsigned short* str) { static CBString fromUtf16(const unsigned short* str) {
// Naive implementation assuming that only ASCII LE part of UCS2 is used, str may not be aligned. // Naive implementation assuming that only ASCII LE part of UCS2 is used, str may not be aligned.
CBString msg; CBString msg;

View file

@ -275,8 +275,8 @@ typedef struct EFI_FIRMWARE_VOLUME_EXT_ENTRY_GUID_TYPE_ {
// 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
@ -406,7 +406,7 @@ typedef struct EFI_COMMON_SECTION_HEADER2_ {
// Apple common section header // Apple common section header
typedef struct EFI_COMMON_SECTION_HEADER_APPLE { typedef struct EFI_COMMON_SECTION_HEADER_APPLE {
UINT8 Size[3]; UINT8 Size[3];
UINT8 Type; UINT8 Type;
UINT32 Reserved; // Must be 0x7FFF for this header to be used UINT32 Reserved; // Must be 0x7FFF for this header to be used
} EFI_COMMON_SECTION_HEADER_APPLE; } EFI_COMMON_SECTION_HEADER_APPLE;

View file

@ -79,7 +79,7 @@ USTATUS FfsBuilder::buildCapsule(const UModelIndex & index, UByteArray & capsule
} }
// Rebuild or Replace // Rebuild or Replace
else if (model->action(index) == Actions::Rebuild else if (model->action(index) == Actions::Rebuild
|| model->action(index) == Actions::Replace) { || model->action(index) == Actions::Replace) {
if (model->rowCount(index)) { if (model->rowCount(index)) {
// Clear the supplied UByteArray // Clear the supplied UByteArray
@ -272,7 +272,7 @@ USTATUS FfsBuilder::buildRawArea(const UModelIndex & index, UByteArray & rawArea
return U_SUCCESS; return U_SUCCESS;
} }
// Rebuild or Replace // Rebuild or Replace
else if (model->action(index) == Actions::Rebuild else if (model->action(index) == Actions::Rebuild
|| model->action(index) == Actions::Replace) { || model->action(index) == Actions::Replace) {
// Rebuild if there is at least 1 child // Rebuild if there is at least 1 child
if (model->rowCount(index)) { if (model->rowCount(index)) {

View file

@ -10,15 +10,11 @@ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*/ */
// A workaround for compilers not supporting c++11 and c11
// for using PRIX64.
#define __STDC_FORMAT_MACROS
#include "ffsparser.h" #include "ffsparser.h"
#include <map> #include <map>
#include <algorithm> #include <algorithm>
#include <inttypes.h> #include <iostream>
#include "descriptor.h" #include "descriptor.h"
#include "ffs.h" #include "ffs.h"
@ -26,7 +22,6 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "me.h" #include "me.h"
#include "fit.h" #include "fit.h"
#include "nvram.h" #include "nvram.h"
#include "utility.h"
#include "peimage.h" #include "peimage.h"
#include "parsingdata.h" #include "parsingdata.h"
#include "types.h" #include "types.h"
@ -34,6 +29,7 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "nvramparser.h" #include "nvramparser.h"
#include "meparser.h" #include "meparser.h"
#include "uinttypes.h"
#ifndef QT_CORE_LIB #ifndef QT_CORE_LIB
namespace Qt { namespace Qt {
@ -67,6 +63,7 @@ struct BPDT_PARTITION_INFO {
struct CPD_PARTITION_INFO { struct CPD_PARTITION_INFO {
CPD_ENTRY ptEntry; CPD_ENTRY ptEntry;
UINT8 type; UINT8 type;
bool hasMetaData;
UModelIndex index; UModelIndex index;
friend bool operator< (const CPD_PARTITION_INFO & lhs, const CPD_PARTITION_INFO & rhs){ return lhs.ptEntry.Offset.Offset < rhs.ptEntry.Offset.Offset; } friend bool operator< (const CPD_PARTITION_INFO & lhs, const CPD_PARTITION_INFO & rhs){ return lhs.ptEntry.Offset.Offset < rhs.ptEntry.Offset.Offset; }
}; };
@ -164,7 +161,7 @@ USTATUS FfsParser::parseGenericImage(const UByteArray & buffer, const UINT32 loc
{ {
// Parse as generic UEFI image // Parse as generic UEFI image
UString name("UEFI image"); UString name("UEFI image");
UString info = usprintf("Full size: %Xh (%u)", buffer.size(), buffer.size()); UString info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")", buffer.size(), buffer.size());
// Add tree item // Add tree item
index = model->addItem(localOffset, Types::Image, Subtypes::UefiImage, name, UString(), info, UByteArray(), buffer, UByteArray(), Fixed, parent); index = model->addItem(localOffset, Types::Image, Subtypes::UefiImage, name, UString(), info, UByteArray(), buffer, UByteArray(), Fixed, parent);
@ -211,7 +208,7 @@ USTATUS FfsParser::parseCapsule(const UByteArray & capsule, const UINT32 localOf
UByteArray body = capsule.mid(capsuleHeaderSize); UByteArray body = capsule.mid(capsuleHeaderSize);
UString name("UEFI capsule"); UString name("UEFI capsule");
UString info = UString("Capsule GUID: ") + guidToUString(capsuleHeader->CapsuleGuid, false) + UString info = UString("Capsule GUID: ") + guidToUString(capsuleHeader->CapsuleGuid, false) +
usprintf("\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nImage size: %Xh (%u)\nFlags: %08Xh", usprintf("\nFull size: %" PRIXQ "h (%" PRIuQ ")\nHeader size: %Xh (%u)\nImage size: %Xh (%u)\nFlags: %08Xh",
capsule.size(), capsule.size(), capsule.size(), capsule.size(),
capsuleHeaderSize, capsuleHeaderSize, capsuleHeaderSize, capsuleHeaderSize,
capsuleHeader->CapsuleImageSize - capsuleHeaderSize, capsuleHeader->CapsuleImageSize - capsuleHeaderSize, capsuleHeader->CapsuleImageSize - capsuleHeaderSize, capsuleHeader->CapsuleImageSize - capsuleHeaderSize,
@ -243,7 +240,7 @@ USTATUS FfsParser::parseCapsule(const UByteArray & capsule, const UINT32 localOf
UByteArray body = capsule.mid(capsuleHeaderSize); UByteArray body = capsule.mid(capsuleHeaderSize);
UString name("Toshiba capsule"); UString name("Toshiba capsule");
UString info = UString("Capsule GUID: ") + guidToUString(capsuleHeader->CapsuleGuid, false) + UString info = UString("Capsule GUID: ") + guidToUString(capsuleHeader->CapsuleGuid, false) +
usprintf("\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nImage size: %Xh (%u)\nFlags: %08Xh", usprintf("\nFull size: %" PRIXQ "h (%" PRIuQ ")\nHeader size: %Xh (%u)\nImage size: %Xh (%u)\nFlags: %08Xh",
capsule.size(), capsule.size(), capsule.size(), capsule.size(),
capsuleHeaderSize, capsuleHeaderSize, capsuleHeaderSize, capsuleHeaderSize,
capsuleHeader->FullSize - capsuleHeaderSize, capsuleHeader->FullSize - capsuleHeaderSize, capsuleHeader->FullSize - capsuleHeaderSize, capsuleHeader->FullSize - capsuleHeaderSize,
@ -284,7 +281,7 @@ USTATUS FfsParser::parseCapsule(const UByteArray & capsule, const UINT32 localOf
UByteArray body = capsule.mid(capsuleHeaderSize); UByteArray body = capsule.mid(capsuleHeaderSize);
UString name("AMI Aptio capsule"); UString name("AMI Aptio capsule");
UString info = UString("Capsule GUID: ") + guidToUString(capsuleHeader->CapsuleHeader.CapsuleGuid, false) + UString info = UString("Capsule GUID: ") + guidToUString(capsuleHeader->CapsuleHeader.CapsuleGuid, false) +
usprintf("\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nImage size: %Xh (%u)\nFlags: %08Xh", usprintf("\nFull size: %" PRIXQ "h (%" PRIuQ ")\nHeader size: %Xh (%u)\nImage size: %Xh (%u)\nFlags: %08Xh",
capsule.size(), capsule.size(), capsule.size(), capsule.size(),
capsuleHeaderSize, capsuleHeaderSize, capsuleHeaderSize, capsuleHeaderSize,
capsuleHeader->CapsuleHeader.CapsuleImageSize - capsuleHeaderSize, capsuleHeader->CapsuleHeader.CapsuleImageSize - capsuleHeaderSize, capsuleHeader->CapsuleHeader.CapsuleImageSize - capsuleHeaderSize, capsuleHeader->CapsuleHeader.CapsuleImageSize - capsuleHeaderSize,
@ -488,7 +485,7 @@ USTATUS FfsParser::parseIntelImage(const UByteArray & intelImage, const UINT32 l
// Intel image // Intel image
UString name("Intel image"); UString name("Intel image");
UString info = usprintf("Full size: %Xh (%u)\nFlash chips: %u\nRegions: %u\nMasters: %u\nPCH straps: %u\nPROC straps: %u", UString info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")\nFlash chips: %u\nRegions: %u\nMasters: %u\nPCH straps: %u\nPROC straps: %u",
intelImage.size(), intelImage.size(), intelImage.size(), intelImage.size(),
descriptorMap->NumberOfFlashChips + 1, // descriptorMap->NumberOfFlashChips + 1, //
descriptorMap->NumberOfRegions + 1, // Zero-based numbers in storage descriptorMap->NumberOfRegions + 1, // Zero-based numbers in storage
@ -652,7 +649,7 @@ USTATUS FfsParser::parseIntelImage(const UByteArray & intelImage, const UINT32 l
// Get info // Get info
name = UString("Padding"); name = UString("Padding");
info = usprintf("Full size: %Xh (%u)", info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")",
padding.size(), padding.size()); padding.size(), padding.size());
// Add tree item // Add tree item
@ -684,7 +681,7 @@ USTATUS FfsParser::parseGbeRegion(const UByteArray & gbe, const UINT32 localOffs
UString name("GbE region"); UString name("GbE region");
const GBE_MAC_ADDRESS* mac = (const GBE_MAC_ADDRESS*)gbe.constData(); const GBE_MAC_ADDRESS* mac = (const GBE_MAC_ADDRESS*)gbe.constData();
const GBE_VERSION* version = (const GBE_VERSION*)(gbe.constData() + GBE_VERSION_OFFSET); const GBE_VERSION* version = (const GBE_VERSION*)(gbe.constData() + GBE_VERSION_OFFSET);
UString info = usprintf("Full size: %Xh (%u)\nMAC: %02X:%02X:%02X:%02X:%02X:%02X\nVersion: %u.%u", UString info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")\nMAC: %02X:%02X:%02X:%02X:%02X:%02X\nVersion: %u.%u",
gbe.size(), gbe.size(), gbe.size(), gbe.size(),
mac->vendor[0], mac->vendor[1], mac->vendor[2], mac->vendor[0], mac->vendor[1], mac->vendor[2],
mac->device[0], mac->device[1], mac->device[2], mac->device[0], mac->device[1], mac->device[2],
@ -705,7 +702,7 @@ USTATUS FfsParser::parseMeRegion(const UByteArray & me, const UINT32 localOffset
// Get info // Get info
UString name("ME region"); UString name("ME region");
UString info = usprintf("Full size: %Xh (%u)", me.size(), me.size()); UString info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")", me.size(), me.size());
// Parse region // Parse region
bool versionFound = true; bool versionFound = true;
@ -768,7 +765,7 @@ USTATUS FfsParser::parsePdrRegion(const UByteArray & pdr, const UINT32 localOffs
// Get info // Get info
UString name("PDR region"); UString name("PDR region");
UString info = usprintf("Full size: %Xh (%u)", pdr.size(), pdr.size()); UString info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")", pdr.size(), pdr.size());
// Add tree item // Add tree item
index = model->addItem(localOffset, Types::Region, Subtypes::PdrRegion, name, UString(), info, UByteArray(), pdr, UByteArray(), Fixed, parent); index = model->addItem(localOffset, Types::Region, Subtypes::PdrRegion, name, UString(), info, UByteArray(), pdr, UByteArray(), Fixed, parent);
@ -789,7 +786,7 @@ USTATUS FfsParser::parseDevExp1Region(const UByteArray & devExp1, const UINT32 l
// Get info // Get info
UString name("DevExp1 region"); UString name("DevExp1 region");
UString info = usprintf("Full size: %Xh (%u)", devExp1.size(), devExp1.size()); UString info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")", devExp1.size(), devExp1.size());
bool emptyRegion = false; bool emptyRegion = false;
// Check for empty region // Check for empty region
@ -816,7 +813,7 @@ USTATUS FfsParser::parseGenericRegion(const UINT8 subtype, const UByteArray & re
// Get info // Get info
UString name = itemSubtypeToUString(Types::Region, subtype) + UString(" region"); UString name = itemSubtypeToUString(Types::Region, subtype) + UString(" region");
UString info = usprintf("Full size: %Xh (%u)", region.size(), region.size()); UString info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")", region.size(), region.size());
// Add tree item // Add tree item
index = model->addItem(localOffset, Types::Region, subtype, name, UString(), info, UByteArray(), region, UByteArray(), Fixed, parent); index = model->addItem(localOffset, Types::Region, subtype, name, UString(), info, UByteArray(), region, UByteArray(), Fixed, parent);
@ -832,7 +829,7 @@ USTATUS FfsParser::parseBiosRegion(const UByteArray & bios, const UINT32 localOf
// Get info // Get info
UString name("BIOS region"); UString name("BIOS region");
UString info = usprintf("Full size: %Xh (%u)", bios.size(), bios.size()); UString info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")", bios.size(), bios.size());
// Add tree item // Add tree item
index = model->addItem(localOffset, Types::Region, Subtypes::BiosRegion, name, UString(), info, UByteArray(), bios, UByteArray(), Fixed, parent); index = model->addItem(localOffset, Types::Region, Subtypes::BiosRegion, name, UString(), info, UByteArray(), bios, UByteArray(), Fixed, parent);
@ -877,7 +874,7 @@ USTATUS FfsParser::parseRawArea(const UModelIndex & index)
// Get info // Get info
UByteArray padding = data.left(prevItemOffset); UByteArray padding = data.left(prevItemOffset);
name = UString("Padding"); name = UString("Padding");
info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size()); info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")", padding.size(), padding.size());
// Add tree item // Add tree item
model->addItem(headerSize, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); model->addItem(headerSize, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index);
@ -898,7 +895,7 @@ USTATUS FfsParser::parseRawArea(const UModelIndex & index)
// Get info // Get info
name = UString("Padding"); name = UString("Padding");
info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size()); info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")", padding.size(), padding.size());
// Add tree item // Add tree item
model->addItem(headerSize + paddingOffset, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); model->addItem(headerSize + paddingOffset, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index);
@ -911,7 +908,7 @@ USTATUS FfsParser::parseRawArea(const UModelIndex & index)
// Get info // Get info
name = UString("Padding"); name = UString("Padding");
info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size()); info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")", padding.size(), padding.size());
// Add tree item // Add tree item
UModelIndex paddingIndex = model->addItem(headerSize + itemOffset, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); UModelIndex paddingIndex = model->addItem(headerSize + itemOffset, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index);
@ -951,7 +948,7 @@ USTATUS FfsParser::parseRawArea(const UModelIndex & index)
// Get info // Get info
name = UString("BPDT region"); name = UString("BPDT region");
info = usprintf("Full size: %Xh (%u)", bpdtStore.size(), bpdtStore.size()); info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")", bpdtStore.size(), bpdtStore.size());
// Add tree item // Add tree item
UModelIndex bpdtIndex = model->addItem(headerSize + itemOffset, Types::BpdtStore, 0, name, UString(), info, UByteArray(), bpdtStore, UByteArray(), Fixed, index); UModelIndex bpdtIndex = model->addItem(headerSize + itemOffset, Types::BpdtStore, 0, name, UString(), info, UByteArray(), bpdtStore, UByteArray(), Fixed, index);
@ -984,7 +981,7 @@ USTATUS FfsParser::parseRawArea(const UModelIndex & index)
// Get info // Get info
name = UString("Padding"); name = UString("Padding");
info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size()); info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")", padding.size(), padding.size());
// Add tree item // Add tree item
model->addItem(headerSize + itemOffset, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); model->addItem(headerSize + itemOffset, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index);
@ -1029,8 +1026,8 @@ USTATUS FfsParser::parseVolumeHeader(const UByteArray & volume, const UINT32 loc
return U_INVALID_PARAMETER; return U_INVALID_PARAMETER;
// Check that there is space for the volume header // Check that there is space for the volume header
if ((UINT32)volume.size() < sizeof(EFI_FIRMWARE_VOLUME_HEADER)) { if ((UINT32)volume.size() < sizeof(EFI_FIRMWARE_VOLUME_HEADER)) {
msg(usprintf("%s: input volume size %Xh (%u) is smaller than volume header size 40h (64)", __FUNCTION__, volume.size(), volume.size())); msg(usprintf("%s: input volume size %" PRIXQ "h (%" PRIuQ ") is smaller than volume header size 40h (64)", __FUNCTION__, volume.size(), volume.size()));
return U_INVALID_VOLUME; return U_INVALID_VOLUME;
} }
@ -1344,7 +1341,7 @@ USTATUS FfsParser::findNextRawAreaItem(const UModelIndex & index, const UINT32 l
continue; continue;
} }
// Calculate alternative volume size using it's BlockMap // Calculate alternative volume size using its BlockMap
nextItemAlternativeSize = 0; nextItemAlternativeSize = 0;
const EFI_FV_BLOCK_MAP_ENTRY* entry = (const EFI_FV_BLOCK_MAP_ENTRY*)(data.constData() + offset - EFI_FV_SIGNATURE_OFFSET + sizeof(EFI_FIRMWARE_VOLUME_HEADER)); const EFI_FV_BLOCK_MAP_ENTRY* entry = (const EFI_FV_BLOCK_MAP_ENTRY*)(data.constData() + offset - EFI_FV_SIGNATURE_OFFSET + sizeof(EFI_FIRMWARE_VOLUME_HEADER));
while (entry->NumBlocks != 0 && entry->Length != 0) { while (entry->NumBlocks != 0 && entry->Length != 0) {
@ -1421,7 +1418,7 @@ USTATUS FfsParser::parseVolumeNonUefiData(const UByteArray & data, const UINT32
return U_INVALID_PARAMETER; return U_INVALID_PARAMETER;
// Get info // Get info
UString info = usprintf("Full size: %Xh (%u)", data.size(), data.size()); UString info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")", data.size(), data.size());
// Add padding tree item // Add padding tree item
UModelIndex paddingIndex = model->addItem(localOffset, Types::Padding, Subtypes::DataPadding, UString("Non-UEFI data"), UString(), info, UByteArray(), data, UByteArray(), Fixed, index); UModelIndex paddingIndex = model->addItem(localOffset, Types::Padding, Subtypes::DataPadding, UString("Non-UEFI data"), UString(), info, UByteArray(), data, UByteArray(), Fixed, index);
@ -1520,7 +1517,7 @@ USTATUS FfsParser::parseVolumeBody(const UModelIndex & index)
UByteArray free = freeSpace.left(i); UByteArray free = freeSpace.left(i);
// Get info // Get info
UString info = usprintf("Full size: %Xh (%u)", free.size(), free.size()); UString info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")", free.size(), free.size());
// Add free space item // Add free space item
model->addItem(volumeHeaderSize + fileOffset, Types::FreeSpace, 0, UString("Volume free space"), UString(), info, UByteArray(), free, UByteArray(), Movable, index); model->addItem(volumeHeaderSize + fileOffset, Types::FreeSpace, 0, UString("Volume free space"), UString(), info, UByteArray(), free, UByteArray(), Movable, index);
@ -1531,7 +1528,7 @@ USTATUS FfsParser::parseVolumeBody(const UModelIndex & index)
} }
else { else {
// Get info // Get info
UString info = usprintf("Full size: %Xh (%u)", freeSpace.size(), freeSpace.size()); UString info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")", freeSpace.size(), freeSpace.size());
// Add free space item // Add free space item
model->addItem(volumeHeaderSize + fileOffset, Types::FreeSpace, 0, UString("Volume free space"), UString(), info, UByteArray(), freeSpace, UByteArray(), Movable, index); model->addItem(volumeHeaderSize + fileOffset, Types::FreeSpace, 0, UString("Volume free space"), UString(), info, UByteArray(), freeSpace, UByteArray(), Movable, index);
@ -1764,7 +1761,7 @@ USTATUS FfsParser::parseFileHeader(const UByteArray & file, const UINT32 localOf
} }
info = UString("File GUID: ") + guidToUString(fileHeader->Name, false) + info = UString("File GUID: ") + guidToUString(fileHeader->Name, false) +
usprintf("\nType: %02Xh\nAttributes: %02Xh\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nTail size: %Xh (%u)\nState: %02Xh", usprintf("\nType: %02Xh\nAttributes: %02Xh\nFull size: %" PRIXQ "h (%" PRIuQ ")\nHeader size: %" PRIXQ "h (%" PRIuQ ")\nBody size: %" PRIXQ "h (%" PRIuQ ")\nTail size: %" PRIXQ "h (%" PRIuQ ")\nState: %02Xh",
fileHeader->Type, fileHeader->Type,
fileHeader->Attributes, fileHeader->Attributes,
header.size() + body.size() + tail.size(), header.size() + body.size() + tail.size(), header.size() + body.size() + tail.size(), header.size() + body.size() + tail.size(),
@ -1943,7 +1940,7 @@ USTATUS FfsParser::parsePadFileBody(const UModelIndex & index)
UByteArray free = body.left(nonEmptyByteOffset); UByteArray free = body.left(nonEmptyByteOffset);
// Get info // Get info
UString info = usprintf("Full size: %Xh (%u)", free.size(), free.size()); UString info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")", free.size(), free.size());
// Add tree item // Add tree item
model->addItem(headerSize, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), free, UByteArray(), Movable, index); model->addItem(headerSize, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), free, UByteArray(), Movable, index);
@ -1956,7 +1953,7 @@ USTATUS FfsParser::parsePadFileBody(const UModelIndex & index)
UByteArray padding = body.mid(nonEmptyByteOffset); UByteArray padding = body.mid(nonEmptyByteOffset);
// Get info // Get info
UString info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size()); UString info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")", padding.size(), padding.size());
// Add tree item // Add tree item
UModelIndex dataIndex = model->addItem(headerSize + nonEmptyByteOffset, Types::Padding, Subtypes::DataPadding, UString("Non-UEFI data"), UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); UModelIndex dataIndex = model->addItem(headerSize + nonEmptyByteOffset, Types::Padding, Subtypes::DataPadding, UString("Non-UEFI data"), UString(), info, UByteArray(), padding, UByteArray(), Fixed, index);
@ -2004,7 +2001,7 @@ USTATUS FfsParser::parseSections(const UByteArray & sections, const UModelIndex
UByteArray padding = sections.mid(sectionOffset); UByteArray padding = sections.mid(sectionOffset);
// Get info // Get info
UString info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size()); UString info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")", padding.size(), padding.size());
// Add tree item // Add tree item
UModelIndex dataIndex = model->addItem(headerSize + sectionOffset, Types::Padding, Subtypes::DataPadding, UString("Non-UEFI data"), UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); UModelIndex dataIndex = model->addItem(headerSize + sectionOffset, Types::Padding, Subtypes::DataPadding, UString("Non-UEFI data"), UString(), info, UByteArray(), padding, UByteArray(), Fixed, index);
@ -2137,7 +2134,7 @@ USTATUS FfsParser::parseCommonSectionHeader(const UByteArray & section, const UI
// Get info // Get info
UString name = sectionTypeToUString(type) + UString(" section"); UString name = sectionTypeToUString(type) + UString(" section");
UString info = usprintf("Type: %02Xh\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)", UString info = usprintf("Type: %02Xh\nFull size: %" PRIXQ "h (%" PRIuQ ")\nHeader size: %Xh (%u)\nBody size: %" PRIXQ "h (%" PRIuQ ")",
type, type,
section.size(), section.size(), section.size(), section.size(),
headerSize, headerSize, headerSize, headerSize,
@ -2205,7 +2202,7 @@ USTATUS FfsParser::parseCompressedSectionHeader(const UByteArray & section, cons
// Get info // Get info
UString name = sectionTypeToUString(sectionHeader->Type) + UString(" section"); UString name = sectionTypeToUString(sectionHeader->Type) + UString(" section");
UString info = usprintf("Type: %02Xh\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nCompression type: %02Xh\nDecompressed size: %Xh (%u)", UString info = usprintf("Type: %02Xh\nFull size: %" PRIXQ "h (%" PRIuQ ")\nHeader size: %Xh (%u)\nBody size: %" PRIXQ "h (%" PRIuQ ")\nCompression type: %02Xh\nDecompressed size: %Xh (%u)",
sectionHeader->Type, sectionHeader->Type,
section.size(), section.size(), section.size(), section.size(),
headerSize, headerSize, headerSize, headerSize,
@ -2385,7 +2382,7 @@ USTATUS FfsParser::parseGuidedSectionHeader(const UByteArray & section, const UI
// Get info // Get info
UString name = guidToUString(guid); UString name = guidToUString(guid);
UString info = UString("Section GUID: ") + guidToUString(guid, false) + UString info = UString("Section GUID: ") + guidToUString(guid, false) +
usprintf("\nType: %02Xh\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nData offset: %Xh\nAttributes: %04Xh", usprintf("\nType: %02Xh\nFull size: %" PRIXQ "h (%" PRIuQ ")\nHeader size: %" PRIXQ "h (%" PRIuQ ")\nBody size: %" PRIXQ "h (%" PRIuQ ")\nData offset: %Xh\nAttributes: %04Xh",
sectionHeader->Type, sectionHeader->Type,
section.size(), section.size(), section.size(), section.size(),
header.size(), header.size(), header.size(), header.size(),
@ -2480,7 +2477,7 @@ USTATUS FfsParser::parseFreeformGuidedSectionHeader(const UByteArray & section,
// Get info // Get info
UString name = sectionTypeToUString(type) + (" section"); UString name = sectionTypeToUString(type) + (" section");
UString info = usprintf("Type: %02Xh\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nSubtype GUID: ", UString info = usprintf("Type: %02Xh\nFull size: %" PRIXQ "h (%" PRIuQ ")\nHeader size: %" PRIXQ "h (%" PRIuQ ")\nBody size: %" PRIXQ "h (%" PRIuQ ")\nSubtype GUID: ",
type, type,
section.size(), section.size(), section.size(), section.size(),
header.size(), header.size(), header.size(), header.size(),
@ -2554,7 +2551,7 @@ USTATUS FfsParser::parseVersionSectionHeader(const UByteArray & section, const U
// Get info // Get info
UString name = sectionTypeToUString(type) + (" section"); UString name = sectionTypeToUString(type) + (" section");
UString info = usprintf("Type: %02Xh\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nBuild number: %u", UString info = usprintf("Type: %02Xh\nFull size: %" PRIXQ "h (%" PRIuQ ")\nHeader size: %" PRIXQ "h (%" PRIuQ ")\nBody size: %" PRIXQ "h (%" PRIuQ ")\nBuild number: %u",
type, type,
section.size(), section.size(), section.size(), section.size(),
header.size(), header.size(), header.size(), header.size(),
@ -2620,7 +2617,7 @@ USTATUS FfsParser::parsePostcodeSectionHeader(const UByteArray & section, const
// Get info // Get info
UString name = sectionTypeToUString(type) + (" section"); UString name = sectionTypeToUString(type) + (" section");
UString info = usprintf("Type: %02Xh\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nPostcode: %Xh", UString info = usprintf("Type: %02Xh\nFull size: %" PRIXQ "h (%" PRIuQ ")\nHeader size: %" PRIXQ "h (%" PRIuQ ")\nBody size: %" PRIXQ "h (%" PRIuQ ")\nPostcode: %Xh",
type, type,
section.size(), section.size(), section.size(), section.size(),
header.size(), header.size(), header.size(), header.size(),
@ -2701,11 +2698,11 @@ USTATUS FfsParser::parseCompressedSectionBody(const UModelIndex & index)
// Check reported uncompressed size // Check reported uncompressed size
if (uncompressedSize != (UINT32)decompressed.size()) { if (uncompressedSize != (UINT32)decompressed.size()) {
msg(usprintf("parseCompressedSectionBody: decompressed size stored in header %Xh (%u) differs from actual %Xh (%u)", msg(usprintf("parseCompressedSectionBody: decompressed size stored in header %Xh (%u) differs from actual %" PRIXQ "h (%" PRIuQ ")",
uncompressedSize, uncompressedSize, uncompressedSize, uncompressedSize,
decompressed.size(), decompressed.size()), decompressed.size(), decompressed.size()),
index); index);
model->addInfo(index, usprintf("\nActual decompressed size: %Xh (%u)", decompressed.size(), decompressed.size())); model->addInfo(index, usprintf("\nActual decompressed size: %" PRIXQ "h (%" PRIuQ ")", decompressed.size(), decompressed.size()));
} }
// Check for undecided compression algorithm, this is a special case // Check for undecided compression algorithm, this is a special case
@ -2793,7 +2790,7 @@ USTATUS FfsParser::parseGuidedSectionBody(const UModelIndex & index)
} }
info += UString("\nCompression algorithm: ") + compressionTypeToUString(algorithm); info += UString("\nCompression algorithm: ") + compressionTypeToUString(algorithm);
info += usprintf("\nDecompressed size: %Xh (%u)", processed.size(), processed.size()); info += usprintf("\nDecompressed size: %" PRIXQ "h (%" PRIuQ ")", processed.size(), processed.size());
} }
// LZMA compressed section // LZMA compressed section
else if (baGuid == EFI_GUIDED_SECTION_LZMA) { else if (baGuid == EFI_GUIDED_SECTION_LZMA) {
@ -2805,7 +2802,7 @@ USTATUS FfsParser::parseGuidedSectionBody(const UModelIndex & index)
if (algorithm == COMPRESSION_ALGORITHM_LZMA) { if (algorithm == COMPRESSION_ALGORITHM_LZMA) {
info += UString("\nCompression algorithm: LZMA"); info += UString("\nCompression algorithm: LZMA");
info += usprintf("\nDecompressed size: %Xh (%u)", processed.size(), processed.size()); info += usprintf("\nDecompressed size: %" PRIXQ "h (%" PRIuQ ")", processed.size(), processed.size());
info += usprintf("\nLZMA dictionary size: %Xh", dictionarySize); info += usprintf("\nLZMA dictionary size: %Xh", dictionarySize);
} }
else { else {
@ -2823,7 +2820,7 @@ USTATUS FfsParser::parseGuidedSectionBody(const UModelIndex & index)
if (algorithm == COMPRESSION_ALGORITHM_LZMAF86) { if (algorithm == COMPRESSION_ALGORITHM_LZMAF86) {
info += UString("\nCompression algorithm: LZMAF86"); info += UString("\nCompression algorithm: LZMAF86");
info += usprintf("\nDecompressed size: %Xh (%u)", processed.size(), processed.size()); info += usprintf("\nDecompressed size: %" PRIXQ "h (%" PRIuQ ")", processed.size(), processed.size());
info += usprintf("\nLZMA dictionary size: %Xh", dictionarySize); info += usprintf("\nLZMA dictionary size: %Xh", dictionarySize);
} }
else { else {
@ -2840,7 +2837,7 @@ USTATUS FfsParser::parseGuidedSectionBody(const UModelIndex & index)
} }
info += UString("\nCompression algorithm: GZip"); info += UString("\nCompression algorithm: GZip");
info += usprintf("\nDecompressed size: %Xh (%u)", processed.size(), processed.size()); info += usprintf("\nDecompressed size: %" PRIXQ "h (%" PRIuQ ")", processed.size(), processed.size());
} }
// Add info // Add info
@ -3370,18 +3367,18 @@ USTATUS FfsParser::addInfoRecursive(const UModelIndex & index)
model->addInfo(index, usprintf("Offset: %Xh\n", model->offset(index)), false); model->addInfo(index, usprintf("Offset: %Xh\n", model->offset(index)), false);
// Add current base if the element is not compressed // Add current base if the element is not compressed
// or it's compressed, but it's parent isn't // or it's compressed, but its parent isn't
if ((!model->compressed(index)) || (index.parent().isValid() && !model->compressed(index.parent()))) { if ((!model->compressed(index)) || (index.parent().isValid() && !model->compressed(index.parent()))) {
// Add physical address of the whole item or it's header and data portions separately // Add physical address of the whole item or its header and data portions separately
UINT64 address = addressDiff + model->base(index); UINT64 address = addressDiff + model->base(index);
if (address <= 0xFFFFFFFFUL) { if (address <= 0xFFFFFFFFUL) {
UINT32 headerSize = (UINT32)model->header(index).size(); UINT32 headerSize = (UINT32)model->header(index).size();
if (headerSize) { if (headerSize) {
model->addInfo(index, usprintf("Data address: %08Xh\n", address + headerSize),false); model->addInfo(index, usprintf("Data address: %08llXh\n", address + headerSize),false);
model->addInfo(index, usprintf("Header address: %08Xh\n", address), false); model->addInfo(index, usprintf("Header address: %08llXh\n", address), false);
} }
else { else {
model->addInfo(index, usprintf("Address: %08Xh\n", address), false); model->addInfo(index, usprintf("Address: %08llXh\n", address), false);
} }
} }
// Add base // Add base
@ -3863,7 +3860,7 @@ USTATUS FfsParser::parseFit(const UModelIndex & index)
// Add entry to fitTable // Add entry to fitTable
currentStrings.push_back(usprintf("%016" PRIX64 "h", currentEntry->Address)); currentStrings.push_back(usprintf("%016" PRIX64 "h", currentEntry->Address));
currentStrings.push_back(usprintf("%08Xh", currentEntrySize, currentEntrySize)); currentStrings.push_back(usprintf("%08Xh", currentEntrySize));
currentStrings.push_back(usprintf("%04Xh", currentEntry->Version)); currentStrings.push_back(usprintf("%04Xh", currentEntry->Version));
currentStrings.push_back(usprintf("%02Xh", currentEntry->Checksum)); currentStrings.push_back(usprintf("%02Xh", currentEntry->Checksum));
currentStrings.push_back(fitEntryTypeToUString(currentEntry->Type)); currentStrings.push_back(fitEntryTypeToUString(currentEntry->Type));
@ -3916,7 +3913,7 @@ void FfsParser::findFitRecursive(const UModelIndex & index, UModelIndex & found,
for (INT32 offset = (INT32)model->body(index).indexOf(FIT_SIGNATURE); for (INT32 offset = (INT32)model->body(index).indexOf(FIT_SIGNATURE);
offset >= 0; offset >= 0;
offset = (INT32)model->body(index).indexOf(FIT_SIGNATURE, offset + 1)) { offset = (INT32)model->body(index).indexOf(FIT_SIGNATURE, offset + 1)) {
// FIT candidate found, calculate it's physical address // FIT candidate found, calculate its physical address
UINT32 fitAddress = (UINT32)(model->base(index) + (UINT32)addressDiff + model->header(index).size() + (UINT32)offset); UINT32 fitAddress = (UINT32)(model->base(index) + (UINT32)addressDiff + model->header(index).size() + (UINT32)offset);
// Check FIT address to be stored in the last VTF // Check FIT address to be stored in the last VTF
@ -3988,12 +3985,12 @@ USTATUS FfsParser::parseFitEntryAcm(const UByteArray & acm, const UINT32 localOf
// Add ACM header info // Add ACM header info
UString acmInfo; UString acmInfo;
acmInfo += usprintf(" found at base %Xh\n" acmInfo += usprintf(" found at base %Xh\n"
"ModuleType: %04Xh ModuleSubtype: %04Xh HeaderLength: %08Xh\n" "ModuleType: %04Xh ModuleSubtype: %04Xh HeaderLength: %08lXh\n"
"HeaderVersion: %08Xh ChipsetId: %04Xh Flags: %04Xh\n" "HeaderVersion: %08Xh ChipsetId: %04Xh Flags: %04Xh\n"
"ModuleVendor: %04Xh Date: %02X.%02X.%04X ModuleSize: %08Xh\n" "ModuleVendor: %04Xh Date: %02X.%02X.%04X ModuleSize: %08lXh\n"
"EntryPoint: %08Xh AcmSvn: %04Xh Unknown1: %08Xh\n" "EntryPoint: %08Xh AcmSvn: %04Xh Unknown1: %08Xh\n"
"Unknown2: %08Xh GdtBase: %08Xh GdtMax: %08Xh\n" "Unknown2: %08Xh GdtBase: %08Xh GdtMax: %08Xh\n"
"SegSel: %08Xh KeySize: %08Xh Unknown3: %08Xh", "SegSel: %08Xh KeySize: %08lXh Unknown3: %08lXh",
model->base(parent) + localOffset, model->base(parent) + localOffset,
header->ModuleType, header->ModuleType,
header->ModuleSubtype, header->ModuleSubtype,
@ -4197,7 +4194,7 @@ USTATUS FfsParser::parseFitEntryBootGuardBootPolicy(const UByteArray & bootPolic
securityInfo += usprintf( securityInfo += usprintf(
"\nInitial Boot Block Element found at base %Xh\n" "\nInitial Boot Block Element found at base %Xh\n"
"Tag: __IBBS__ Version: %02Xh Unknown: %02Xh\n" "Tag: __IBBS__ Version: %02Xh Unknown: %02Xh\n"
"Flags: %08Xh IbbMchBar: %08Xh VtdBar: %08Xh\n" "Flags: %08Xh IbbMchBar: %08llXh VtdBar: %08llXh\n"
"PmrlBase: %08Xh PmrlLimit: %08Xh EntryPoint: %08Xh", "PmrlBase: %08Xh PmrlLimit: %08Xh EntryPoint: %08Xh",
model->base(parent) + localOffset + elementOffset, model->base(parent) + localOffset + elementOffset,
elementHeader->Version, elementHeader->Version,
@ -4361,7 +4358,7 @@ USTATUS FfsParser::parseMicrocodeVolumeBody(const UModelIndex & index)
if (offset < bodySize) { if (offset < bodySize) {
// Get info // Get info
UString name = UString("Padding"); UString name = UString("Padding");
UString info = usprintf("Full size: %Xh (%u)", ucode.size(), ucode.size()); UString info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")", ucode.size(), ucode.size());
// Add tree item // Add tree item
model->addItem(headerSize + offset, Types::Padding, getPaddingType(ucode), name, UString(), info, UByteArray(), ucode, UByteArray(), Fixed, index); model->addItem(headerSize + offset, Types::Padding, getPaddingType(ucode), name, UString(), info, UByteArray(), ucode, UByteArray(), Fixed, index);
@ -4482,7 +4479,7 @@ USTATUS FfsParser::parseIntelMicrocodeHeader(const UByteArray & microcode, const
// Add info // Add info
UString name("Intel microcode"); UString name("Intel microcode");
UString info = usprintf("Full size: %Xh (%u)\nHeader size: 0h (0u)\nBody size: %Xh (%u)\nTail size: 0h (0u)\n" UString info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")\nHeader size: 0h (0u)\nBody size: %" PRIXQ "h (%" PRIuQ ")\nTail size: 0h (0u)\n"
"Date: %02X.%02X.%04x\nCPU signature: %08Xh\nRevision: %08Xh\nCPU flags: %02Xh\nChecksum: %08Xh, ", "Date: %02X.%02X.%04x\nCPU signature: %08Xh\nRevision: %08Xh\nCPU flags: %02Xh\nChecksum: %08Xh, ",
microcodeBinary.size(), microcodeBinary.size(), microcodeBinary.size(), microcodeBinary.size(),
microcodeBinary.size(), microcodeBinary.size(), microcodeBinary.size(), microcodeBinary.size(),
@ -4501,7 +4498,7 @@ USTATUS FfsParser::parseIntelMicrocodeHeader(const UByteArray & microcode, const
if (msgInvalidChecksum) if (msgInvalidChecksum)
msg(usprintf("%s: invalid microcode checksum %08Xh, should be %08Xh", __FUNCTION__, ucodeHeader->Checksum, calculated), index); msg(usprintf("%s: invalid microcode checksum %08Xh, should be %08Xh", __FUNCTION__, ucodeHeader->Checksum, calculated), index);
if (msgUnknownOrDamagedMicrocodeTail) if (msgUnknownOrDamagedMicrocodeTail)
msg(usprintf("%s: extended header of size %Xh (%u) found, but it's damaged or has unknown format", __FUNCTION__, tail.size(), tail.size()), index); msg(usprintf("%s: extended header of size %" PRIXQ "h (%" PRIuQ ") found, but it's damaged or has unknown format", __FUNCTION__, tail.size(), tail.size()), index);
// No need to parse the body further for now // No need to parse the body further for now
return U_SUCCESS; return U_SUCCESS;
@ -4533,7 +4530,7 @@ USTATUS FfsParser::parseBpdtRegion(const UByteArray & region, const UINT32 local
UByteArray body = region.mid(sizeof(BPDT_HEADER), ptBodySize); UByteArray body = region.mid(sizeof(BPDT_HEADER), ptBodySize);
UString name = UString("BPDT partition table"); UString name = UString("BPDT partition table");
UString info = usprintf("Full size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nNumber of entries: %u\nVersion: %2Xh\n" UString info = usprintf("Full size: %Xh (%u)\nHeader size: %" PRIXQ "h (%" PRIuQ ")\nBody size: %Xh (%u)\nNumber of entries: %u\nVersion: %2Xh\n"
"IFWI version: %Xh\nFITC version: %u.%u.%u.%u", "IFWI version: %Xh\nFITC version: %u.%u.%u.%u",
ptSize, ptSize, ptSize, ptSize,
header.size(), header.size(), header.size(), header.size(),
@ -4558,7 +4555,7 @@ USTATUS FfsParser::parseBpdtRegion(const UByteArray & region, const UINT32 local
// Get info // Get info
name = bpdtEntryTypeToUString(ptEntry->Type); name = bpdtEntryTypeToUString(ptEntry->Type);
info = usprintf("Full size: %Xh (%u)\nType: %Xh\nPartition offset: %Xh\nPartition length: %Xh", info = usprintf("Full size: %lXh (%lu)\nType: %Xh\nPartition offset: %Xh\nPartition length: %Xh",
sizeof(BPDT_ENTRY), sizeof(BPDT_ENTRY), sizeof(BPDT_ENTRY), sizeof(BPDT_ENTRY),
ptEntry->Type, ptEntry->Type,
ptEntry->Offset, ptEntry->Offset,
@ -4591,7 +4588,7 @@ USTATUS FfsParser::parseBpdtRegion(const UByteArray & region, const UINT32 local
// Get info // Get info
name = UString("Padding"); name = UString("Padding");
info = usprintf("Full size: %Xh (%u)", info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")",
partition.size(), partition.size()); partition.size(), partition.size());
// Add tree item // Add tree item
@ -4632,7 +4629,7 @@ make_partition_table_consistent:
goto make_partition_table_consistent; goto make_partition_table_consistent;
} }
else { else {
msg(usprintf("%s: BPDT partition can't fit into it's region, truncated", __FUNCTION__), partitions[i].index); msg(usprintf("%s: BPDT partition can't fit into its region, truncated", __FUNCTION__), partitions[i].index);
partitions[i].ptEntry.Size = regionSize - (UINT32)partitions[i].ptEntry.Offset; partitions[i].ptEntry.Size = regionSize - (UINT32)partitions[i].ptEntry.Offset;
} }
} }
@ -4673,7 +4670,7 @@ make_partition_table_consistent:
UByteArray partition = region.mid(partitions[i].ptEntry.Offset, partitions[i].ptEntry.Size); UByteArray partition = region.mid(partitions[i].ptEntry.Offset, partitions[i].ptEntry.Size);
UByteArray signature = partition.left(sizeof(UINT32)); UByteArray signature = partition.left(sizeof(UINT32));
UString info = usprintf("Full size: %Xh (%u)\nType: %Xh", UString info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")\nType: %Xh",
partition.size(), partition.size(), partition.size(), partition.size(),
partitions[i].ptEntry.Type) + partitions[i].ptEntry.Type) +
UString("\nSplit sub-partition first part: ") + (partitions[i].ptEntry.SplitSubPartitionFirstPart ? "Yes" : "No") + UString("\nSplit sub-partition first part: ") + (partitions[i].ptEntry.SplitSubPartitionFirstPart ? "Yes" : "No") +
@ -4708,7 +4705,7 @@ make_partition_table_consistent:
// Get info // Get info
name = UString("Padding"); name = UString("Padding");
info = usprintf("Full size: %Xh (%u)", info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")",
padding.size(), padding.size()); padding.size(), padding.size());
// Add tree item // Add tree item
@ -4723,7 +4720,7 @@ make_partition_table_consistent:
// Get info // Get info
name = UString("Padding"); name = UString("Padding");
info = usprintf("Full size: %Xh (%u)", info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")",
padding.size(), padding.size()); padding.size(), padding.size());
// Add tree item // Add tree item
@ -4770,7 +4767,7 @@ USTATUS FfsParser::parseCpdRegion(const UByteArray & region, const UINT32 localO
UByteArray header = region.left(ptHeaderSize); UByteArray header = region.left(ptHeaderSize);
UByteArray body = region.mid(ptHeaderSize); UByteArray body = region.mid(ptHeaderSize);
UString name = usprintf("CPD partition table"); UString name = usprintf("CPD partition table");
UString info = usprintf("Full size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nNumber of entries: %u\n" UString info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")\nHeader size: %" PRIXQ "h (%" PRIuQ ")\nBody size: %" PRIXQ "h (%" PRIuQ ")\nNumber of entries: %u\n"
"Header version: %02X\nEntry version: %02X", "Header version: %02X\nEntry version: %02X",
region.size(), region.size(), region.size(), region.size(),
header.size(), header.size(), header.size(), header.size(),
@ -4792,11 +4789,8 @@ USTATUS FfsParser::parseCpdRegion(const UByteArray & region, const UINT32 localO
UByteArray entry((const char*)cpdEntry, sizeof(CPD_ENTRY)); UByteArray entry((const char*)cpdEntry, sizeof(CPD_ENTRY));
// Get info // Get info
name = usprintf("%c%c%c%c%c%c%c%c%c%c%c%c", name = usprintf("%.12s", cpdEntry->EntryName);
cpdEntry->EntryName[0], cpdEntry->EntryName[1], cpdEntry->EntryName[2], cpdEntry->EntryName[3], info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")\nEntry offset: %Xh\nEntry length: %Xh\nHuffman compressed: ",
cpdEntry->EntryName[4], cpdEntry->EntryName[5], cpdEntry->EntryName[6], cpdEntry->EntryName[7],
cpdEntry->EntryName[8], cpdEntry->EntryName[9], cpdEntry->EntryName[10], cpdEntry->EntryName[11]);
info = usprintf("Full size: %Xh (%u)\nEntry offset: %Xh\nEntry length: %Xh\nHuffman compressed: ",
entry.size(), entry.size(), entry.size(), entry.size(),
cpdEntry->Offset.Offset, cpdEntry->Offset.Offset,
cpdEntry->Length) cpdEntry->Length)
@ -4814,6 +4808,7 @@ USTATUS FfsParser::parseCpdRegion(const UByteArray & region, const UINT32 localO
partition.type = Types::CpdPartition; partition.type = Types::CpdPartition;
partition.ptEntry = *cpdEntry; partition.ptEntry = *cpdEntry;
partition.index = entryIndex; partition.index = entryIndex;
partition.hasMetaData = false;
partitions.push_back(partition); partitions.push_back(partition);
} }
} }
@ -4824,7 +4819,7 @@ USTATUS FfsParser::parseCpdRegion(const UByteArray & region, const UINT32 localO
// Get info // Get info
name = UString("Padding"); name = UString("Padding");
info = usprintf("Full size: %Xh (%u)", info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")",
partition.size(), partition.size()); partition.size(), partition.size());
// Add tree item // Add tree item
@ -4839,15 +4834,12 @@ USTATUS FfsParser::parseCpdRegion(const UByteArray & region, const UINT32 localO
// Because lenghts for all Huffmann-compressed partitions mean nothing at all, we need to split all partitions into 2 classes: // Because lenghts for all Huffmann-compressed partitions mean nothing at all, we need to split all partitions into 2 classes:
// 1. CPD manifest (should be the first) // 1. CPD manifest (should be the first)
// 2. Metadata entries (should begin right after partition manifest and end before any code partition) // 2. Metadata entries (should begin right after partition manifest and end before any code partition)
UINT32 i = 1; UINT32 i = 1; // manifest is index 0, .met partitions start at index 1
while (i < partitions.size()) { while (i < partitions.size()) {
name = usprintf("%c%c%c%c%c%c%c%c%c%c%c%c", name = usprintf("%.12s", partitions[i].ptEntry.EntryName);
partitions[i].ptEntry.EntryName[0], partitions[i].ptEntry.EntryName[1], partitions[i].ptEntry.EntryName[2], partitions[i].ptEntry.EntryName[3],
partitions[i].ptEntry.EntryName[4], partitions[i].ptEntry.EntryName[5], partitions[i].ptEntry.EntryName[6], partitions[i].ptEntry.EntryName[7],
partitions[i].ptEntry.EntryName[8], partitions[i].ptEntry.EntryName[9], partitions[i].ptEntry.EntryName[10], partitions[i].ptEntry.EntryName[11]);
// Check if the current entry is metadata entry // Check if the current entry is metadata entry
if (!name.contains(".met")) { if (!name.endsWith(".met")) {
// No need to parse further, all metadata partitions are parsed // No need to parse further, all metadata partitions are parsed
break; break;
} }
@ -4869,23 +4861,18 @@ USTATUS FfsParser::parseCpdRegion(const UByteArray & region, const UINT32 localO
} }
// Search down for corresponding code partition // Search down for corresponding code partition
// Construct it's name by replacing last 4 non-zero butes of the name with zeros // Construct its name by removing the .met suffix
UINT32 j = 0; name.chop(4);
for (UINT32 k = 11; k > 0 && j < 4; k--) {
if (name[k] != '\x00') {
name[k] = '\x00';
j++;
}
}
// Search // Search
j = i + 1; bool found = false;
UINT32 j = i + 1;
while (j < partitions.size()) { while (j < partitions.size()) {
if (name == usprintf("%c%c%c%c%c%c%c%c%c%c%c%c", UString namej = usprintf("%.12s", partitions[j].ptEntry.EntryName);
partitions[j].ptEntry.EntryName[0], partitions[j].ptEntry.EntryName[1], partitions[j].ptEntry.EntryName[2], partitions[j].ptEntry.EntryName[3],
partitions[j].ptEntry.EntryName[4], partitions[j].ptEntry.EntryName[5], partitions[j].ptEntry.EntryName[6], partitions[j].ptEntry.EntryName[7], if (name == namej) {
partitions[j].ptEntry.EntryName[8], partitions[j].ptEntry.EntryName[9], partitions[j].ptEntry.EntryName[10], partitions[j].ptEntry.EntryName[11])) { found = true;
// Found it, update it's Length if needed // Found it, update its Length if needed
if (partitions[j].ptEntry.Offset.HuffmanCompressed) { if (partitions[j].ptEntry.Offset.HuffmanCompressed) {
partitions[j].ptEntry.Length = length; partitions[j].ptEntry.Length = length;
} }
@ -4894,12 +4881,17 @@ USTATUS FfsParser::parseCpdRegion(const UByteArray & region, const UINT32 localO
partitions[j].ptEntry.Length, length), partitions[j].index); partitions[j].ptEntry.Length, length), partitions[j].index);
partitions[j].ptEntry.Length = length; // Believe metadata partitions[j].ptEntry.Length = length; // Believe metadata
} }
partitions[j].hasMetaData = true;
// No need to search further // No need to search further
break; break;
} }
// Check the next partition // Check the next partition
j++; j++;
} }
if (!found) {
msg(usprintf("%s: no code partition", __FUNCTION__), partitions[i].index);
}
// Check the next partition // Check the next partition
i++; i++;
} }
@ -4937,13 +4929,27 @@ make_partition_table_consistent:
goto make_partition_table_consistent; goto make_partition_table_consistent;
} }
else { else {
msg(usprintf("%s: CPD partition can't fit into it's region, truncated", __FUNCTION__), partitions[i].index); if (!partitions[i].hasMetaData && partitions[i].ptEntry.Offset.HuffmanCompressed) {
msg(usprintf("%s: CPD partition is compressed but doesn't have metadata and can't fit into its region, length adjusted", __FUNCTION__),
partitions[i].index);
}
else {
msg(usprintf("%s: CPD partition can't fit into its region, truncated", __FUNCTION__), partitions[i].index);
}
partitions[i].ptEntry.Length = (UINT32)region.size() - (UINT32)partitions[i].ptEntry.Offset.Offset; partitions[i].ptEntry.Length = (UINT32)region.size() - (UINT32)partitions[i].ptEntry.Offset.Offset;
} }
} }
// Check for intersection with previous partition // Check for intersection with previous partition
if (partitions[i].ptEntry.Offset.Offset < previousPartitionEnd) { if (partitions[i].ptEntry.Offset.Offset < previousPartitionEnd) {
// Check if previous partition was compressed but did not have metadata
if (!partitions[i - 1].hasMetaData && partitions[i - 1].ptEntry.Offset.HuffmanCompressed) {
msg(usprintf("%s: CPD partition is compressed but doesn't have metadata, length adjusted", __FUNCTION__),
partitions[i - 1].index);
partitions[i - 1].ptEntry.Length = (UINT32)partitions[i].ptEntry.Offset.Offset - (UINT32)partitions[i - 1].ptEntry.Offset.Offset;
goto make_partition_table_consistent;
}
// Check if current partition is located inside previous one // Check if current partition is located inside previous one
if (partitions[i].ptEntry.Offset.Offset + partitions[i].ptEntry.Length <= previousPartitionEnd) { if (partitions[i].ptEntry.Offset.Offset + partitions[i].ptEntry.Length <= previousPartitionEnd) {
msg(usprintf("%s: CPD partition is located inside another CPD partition, skipped", __FUNCTION__), msg(usprintf("%s: CPD partition is located inside another CPD partition, skipped", __FUNCTION__),
@ -4982,10 +4988,7 @@ make_partition_table_consistent:
UByteArray partition = region.mid(partitions[i].ptEntry.Offset.Offset, partitions[i].ptEntry.Length); UByteArray partition = region.mid(partitions[i].ptEntry.Offset.Offset, partitions[i].ptEntry.Length);
// Get info // Get info
name = usprintf("%c%c%c%c%c%c%c%c%c%c%c%c", name = usprintf("%.12s", partitions[i].ptEntry.EntryName);
partitions[i].ptEntry.EntryName[0], partitions[i].ptEntry.EntryName[1], partitions[i].ptEntry.EntryName[2], partitions[i].ptEntry.EntryName[3],
partitions[i].ptEntry.EntryName[4], partitions[i].ptEntry.EntryName[5], partitions[i].ptEntry.EntryName[6], partitions[i].ptEntry.EntryName[7],
partitions[i].ptEntry.EntryName[8], partitions[i].ptEntry.EntryName[9], partitions[i].ptEntry.EntryName[10], partitions[i].ptEntry.EntryName[11]);
// It's a manifest // It's a manifest
if (name.contains(".man")) { if (name.contains(".man")) {
@ -4997,8 +5000,8 @@ make_partition_table_consistent:
UByteArray body = partition.mid(header.size()); UByteArray body = partition.mid(header.size());
info += usprintf( info += usprintf(
"\nHeader type: %u\nHeader length: %Xh (%u)\nHeader version: %Xh\nFlags: %08Xh\nVendor: %Xh\n" "\nHeader type: %u\nHeader length: %lXh (%lu)\nHeader version: %Xh\nFlags: %08Xh\nVendor: %Xh\n"
"Date: %Xh\nSize: %Xh (%u)\nVersion: %u.%u.%u.%u\nSecurity version number: %u\nModulus size: %Xh (%u)\nExponent size: %Xh (%u)", "Date: %Xh\nSize: %lXh (%lu)\nVersion: %u.%u.%u.%u\nSecurity version number: %u\nModulus size: %lXh (%lu)\nExponent size: %lXh (%lu)",
manifestHeader->HeaderType, manifestHeader->HeaderType,
manifestHeader->HeaderLength * sizeof(UINT32), manifestHeader->HeaderLength * sizeof(UINT32), manifestHeader->HeaderLength * sizeof(UINT32), manifestHeader->HeaderLength * sizeof(UINT32),
manifestHeader->HeaderVersion, manifestHeader->HeaderVersion,
@ -5021,13 +5024,13 @@ make_partition_table_consistent:
} }
// It's a metadata // It's a metadata
else if (name.contains(".met")) { else if (name.contains(".met")) {
info = usprintf("Full size: %Xh (%u)\nEntry offset: %Xh\nEntry length: %Xh\nHuffman compressed: ", info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")\nEntry offset: %Xh\nEntry length: %Xh\nHuffman compressed: ",
partition.size(), partition.size(), partition.size(), partition.size(),
partitions[i].ptEntry.Offset.Offset, partitions[i].ptEntry.Offset.Offset,
partitions[i].ptEntry.Length) partitions[i].ptEntry.Length)
+ (partitions[i].ptEntry.Offset.HuffmanCompressed ? "Yes" : "No"); + (partitions[i].ptEntry.Offset.HuffmanCompressed ? "Yes" : "No");
// Calculate SHA256 hash over the metadata and add it to it's info // Calculate SHA256 hash over the metadata and add it to its info
UByteArray hash(SHA256_DIGEST_SIZE, '\x00'); UByteArray hash(SHA256_DIGEST_SIZE, '\x00');
sha256(partition.constData(), partition.size(), hash.data()); sha256(partition.constData(), partition.size(), hash.data());
info += UString("\nMetadata hash: ") + UString(hash.toHex().constData()); info += UString("\nMetadata hash: ") + UString(hash.toHex().constData());
@ -5040,13 +5043,13 @@ make_partition_table_consistent:
} }
// It's a key // It's a key
else if (name.contains(".key")) { else if (name.contains(".key")) {
info = usprintf("Full size: %Xh (%u)\nEntry offset: %Xh\nEntry length: %Xh\nHuffman compressed: ", info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")\nEntry offset: %Xh\nEntry length: %Xh\nHuffman compressed: ",
partition.size(), partition.size(), partition.size(), partition.size(),
partitions[i].ptEntry.Offset.Offset, partitions[i].ptEntry.Offset.Offset,
partitions[i].ptEntry.Length) partitions[i].ptEntry.Length)
+ (partitions[i].ptEntry.Offset.HuffmanCompressed ? "Yes" : "No"); + (partitions[i].ptEntry.Offset.HuffmanCompressed ? "Yes" : "No");
// Calculate SHA256 hash over the key and add it to it's info // Calculate SHA256 hash over the key and add it to its info
UByteArray hash(SHA256_DIGEST_SIZE, '\x00'); UByteArray hash(SHA256_DIGEST_SIZE, '\x00');
sha256(partition.constData(), partition.size(), hash.data()); sha256(partition.constData(), partition.size(), hash.data());
info += UString("\nHash: ") + UString(hash.toHex().constData()); info += UString("\nHash: ") + UString(hash.toHex().constData());
@ -5059,13 +5062,13 @@ make_partition_table_consistent:
} }
// It's a code // It's a code
else { else {
info = usprintf("Full size: %Xh (%u)\nEntry offset: %Xh\nEntry length: %Xh\nHuffman compressed: ", info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")\nEntry offset: %Xh\nEntry length: %Xh\nHuffman compressed: ",
partition.size(), partition.size(), partition.size(), partition.size(),
partitions[i].ptEntry.Offset.Offset, partitions[i].ptEntry.Offset.Offset,
partitions[i].ptEntry.Length) partitions[i].ptEntry.Length)
+ (partitions[i].ptEntry.Offset.HuffmanCompressed ? "Yes" : "No"); + (partitions[i].ptEntry.Offset.HuffmanCompressed ? "Yes" : "No");
// Calculate SHA256 hash over the code and add it to it's info // Calculate SHA256 hash over the code and add it to its info
UByteArray hash(SHA256_DIGEST_SIZE, '\x00'); UByteArray hash(SHA256_DIGEST_SIZE, '\x00');
sha256(partition.constData(), partition.size(), hash.data()); sha256(partition.constData(), partition.size(), hash.data());
info += UString("\nHash: ") + UString(hash.toHex().constData()); info += UString("\nHash: ") + UString(hash.toHex().constData());
@ -5079,7 +5082,7 @@ make_partition_table_consistent:
// Get info // Get info
name = UString("Padding"); name = UString("Padding");
info = usprintf("Full size: %Xh (%u)", partition.size(), partition.size()); info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")", partition.size(), partition.size());
// Add tree item // Add tree item
model->addItem(localOffset + partitions[i].ptEntry.Offset.Offset, Types::Padding, getPaddingType(partition), name, UString(), info, UByteArray(), partition, UByteArray(), Fixed, parent); model->addItem(localOffset + partitions[i].ptEntry.Offset.Offset, Types::Padding, getPaddingType(partition), name, UString(), info, UByteArray(), partition, UByteArray(), Fixed, parent);
@ -5107,7 +5110,7 @@ USTATUS FfsParser::parseCpdExtensionsArea(const UModelIndex & index)
UByteArray partition = body.mid(offset, extHeader->Length); UByteArray partition = body.mid(offset, extHeader->Length);
UString name = cpdExtensionTypeToUstring(extHeader->Type); UString name = cpdExtensionTypeToUstring(extHeader->Type);
UString info = usprintf("Full size: %Xh (%u)\nType: %Xh", partition.size(), partition.size(), extHeader->Type); UString info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")\nType: %Xh", partition.size(), partition.size(), extHeader->Type);
// Parse Signed Package Info a bit further // Parse Signed Package Info a bit further
UModelIndex extIndex; UModelIndex extIndex;
@ -5117,14 +5120,14 @@ USTATUS FfsParser::parseCpdExtensionsArea(const UModelIndex & index)
const CPD_EXT_SIGNED_PACKAGE_INFO* infoHeader = (const CPD_EXT_SIGNED_PACKAGE_INFO*)header.constData(); const CPD_EXT_SIGNED_PACKAGE_INFO* infoHeader = (const CPD_EXT_SIGNED_PACKAGE_INFO*)header.constData();
info = usprintf("Full size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nType: %Xh\n" info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")\nHeader size: %" PRIXQ "h (%" PRIuQ ")\nBody size: %" PRIXQ "h (%" PRIuQ ")\nType: %Xh\n"
"Package name: %c%c%c%c\nVersion control number: %Xh\nSecurity version number: %Xh\n" "Package name: %.4s\nVersion control number: %Xh\nSecurity version number: %Xh\n"
"Usage bitmap: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", "Usage bitmap: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
partition.size(), partition.size(), partition.size(), partition.size(),
header.size(), header.size(), header.size(), header.size(),
body.size(), body.size(), body.size(), body.size(),
infoHeader->ExtensionType, infoHeader->ExtensionType,
infoHeader->PackageName[0], infoHeader->PackageName[1], infoHeader->PackageName[2], infoHeader->PackageName[3], infoHeader->PackageName,
infoHeader->Vcn, infoHeader->Vcn,
infoHeader->Svn, infoHeader->Svn,
infoHeader->UsageBitmap[0], infoHeader->UsageBitmap[1], infoHeader->UsageBitmap[2], infoHeader->UsageBitmap[3], infoHeader->UsageBitmap[0], infoHeader->UsageBitmap[1], infoHeader->UsageBitmap[2], infoHeader->UsageBitmap[3],
@ -5142,15 +5145,15 @@ USTATUS FfsParser::parseCpdExtensionsArea(const UModelIndex & index)
// This hash is stored reversed // This hash is stored reversed
// Need to reverse it back to normal // Need to reverse it back to normal
UByteArray hash((const char*)&attrHeader->CompletePartitionHash, sizeof(attrHeader->CompletePartitionHash)); UByteArray hash((const char*)&attrHeader->CompletePartitionHash, attrHeader->HashSize);
std::reverse(hash.begin(), hash.end()); std::reverse(hash.begin(), hash.end());
info = usprintf("Full size: %Xh (%u)\nType: %Xh\n" info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")\nType: %Xh\n"
"Partition name: %c%c%c%c\nPartition length: %Xh\nPartition version major: %Xh\nPartition version minor: %Xh\n" "Partition name: %.4s\nPartition length: %Xh\nPartition version major: %Xh\nPartition version minor: %Xh\n"
"Data format version: %Xh\nInstance ID: %Xh\nHash algorithm: %Xh\nHash size: %Xh\nAction on update: %Xh", "Data format version: %Xh\nInstance ID: %Xh\nHash algorithm: %Xh\nHash size: %Xh\nAction on update: %Xh",
partition.size(), partition.size(), partition.size(), partition.size(),
attrHeader->ExtensionType, attrHeader->ExtensionType,
attrHeader->PartitionName[0], attrHeader->PartitionName[1], attrHeader->PartitionName[2], attrHeader->PartitionName[3], attrHeader->PartitionName,
attrHeader->CompletePartitionLength, attrHeader->CompletePartitionLength,
attrHeader->PartitionVersionMajor, attrHeader->PartitionVersionMinor, attrHeader->PartitionVersionMajor, attrHeader->PartitionVersionMinor,
attrHeader->DataFormatVersion, attrHeader->DataFormatVersion,
@ -5169,17 +5172,22 @@ USTATUS FfsParser::parseCpdExtensionsArea(const UModelIndex & index)
// Add tree item // Add tree item
extIndex = model->addItem(offset, Types::CpdExtension, 0, name, UString(), info, UByteArray(), partition, UByteArray(), Fixed, index); extIndex = model->addItem(offset, Types::CpdExtension, 0, name, UString(), info, UByteArray(), partition, UByteArray(), Fixed, index);
if (sizeof (attrHeader->CompletePartitionHash) != attrHeader->HashSize) {
msg(usprintf("%s: IFWI Partition Manifest hash size is %d, expected %lu", __FUNCTION__, attrHeader->HashSize, sizeof (attrHeader->CompletePartitionHash)), extIndex);
}
} }
// Parse Module Attributes a bit further // Parse Module Attributes a bit further
else if (extHeader->Type == CPD_EXT_TYPE_MODULE_ATTRIBUTES) { else if (extHeader->Type == CPD_EXT_TYPE_MODULE_ATTRIBUTES) {
const CPD_EXT_MODULE_ATTRIBUTES* attrHeader = (const CPD_EXT_MODULE_ATTRIBUTES*)partition.constData(); const CPD_EXT_MODULE_ATTRIBUTES* attrHeader = (const CPD_EXT_MODULE_ATTRIBUTES*)partition.constData();
int hashSize = partition.size() - offsetof(CPD_EXT_MODULE_ATTRIBUTES, ImageHash);
// This hash is stored reversed // This hash is stored reversed
// Need to reverse it back to normal // Need to reverse it back to normal
UByteArray hash((const char*)&attrHeader->ImageHash, sizeof(attrHeader->ImageHash)); UByteArray hash((const char*)&attrHeader->ImageHash, hashSize);
std::reverse(hash.begin(), hash.end()); std::reverse(hash.begin(), hash.end());
info = usprintf("Full size: %Xh (%u)\nType: %Xh\n" info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")\nType: %Xh\n"
"Compression type: %Xh\nUncompressed size: %Xh (%u)\nCompressed size: %Xh (%u)\nGlobal module ID: %Xh\nImage hash: ", "Compression type: %Xh\nUncompressed size: %Xh (%u)\nCompressed size: %Xh (%u)\nGlobal module ID: %Xh\nImage hash: ",
partition.size(), partition.size(), partition.size(), partition.size(),
attrHeader->ExtensionType, attrHeader->ExtensionType,
@ -5190,6 +5198,9 @@ USTATUS FfsParser::parseCpdExtensionsArea(const UModelIndex & index)
// Add tree item // Add tree item
extIndex = model->addItem(offset, Types::CpdExtension, 0, name, UString(), info, UByteArray(), partition, UByteArray(), Fixed, index); extIndex = model->addItem(offset, Types::CpdExtension, 0, name, UString(), info, UByteArray(), partition, UByteArray(), Fixed, index);
if (hashSize != sizeof (attrHeader->ImageHash)) {
msg(usprintf("%s: Module Attributes hash size is %d, expected %lu", __FUNCTION__, hashSize, sizeof (attrHeader->ImageHash)), extIndex);
}
} }
// Parse everything else // Parse everything else
else { else {
@ -5221,26 +5232,26 @@ USTATUS FfsParser::parseSignedPackageInfoData(const UModelIndex & index)
while (offset < (UINT32)body.size()) { while (offset < (UINT32)body.size()) {
const CPD_EXT_SIGNED_PACKAGE_INFO_MODULE* moduleHeader = (const CPD_EXT_SIGNED_PACKAGE_INFO_MODULE*)(body.constData() + offset); const CPD_EXT_SIGNED_PACKAGE_INFO_MODULE* moduleHeader = (const CPD_EXT_SIGNED_PACKAGE_INFO_MODULE*)(body.constData() + offset);
if (sizeof(CPD_EXT_SIGNED_PACKAGE_INFO_MODULE) <= ((UINT32)body.size() - offset)) { if (sizeof(CPD_EXT_SIGNED_PACKAGE_INFO_MODULE) <= ((UINT32)body.size() - offset)) {
UByteArray module((const char*)moduleHeader, sizeof(CPD_EXT_SIGNED_PACKAGE_INFO_MODULE)); UByteArray module((const char*)moduleHeader, sizeof(CPD_EXT_SIGNED_PACKAGE_INFO_MODULE) - sizeof (moduleHeader->MetadataHash) + moduleHeader->HashSize);
UString name = usprintf("%c%c%c%c%c%c%c%c%c%c%c%c", UString name = usprintf("%.12s", moduleHeader->Name);
moduleHeader->Name[0], moduleHeader->Name[1], moduleHeader->Name[2], moduleHeader->Name[3],
moduleHeader->Name[4], moduleHeader->Name[5], moduleHeader->Name[6], moduleHeader->Name[7],
moduleHeader->Name[8], moduleHeader->Name[9], moduleHeader->Name[10],moduleHeader->Name[11]);
// This hash is stored reversed // This hash is stored reversed
// Need to reverse it back to normal // Need to reverse it back to normal
UByteArray hash((const char*)&moduleHeader->MetadataHash, sizeof(moduleHeader->MetadataHash)); UByteArray hash((const char*)&moduleHeader->MetadataHash, moduleHeader->HashSize);
std::reverse(hash.begin(), hash.end()); std::reverse(hash.begin(), hash.end());
UString info = usprintf("Full size: %X (%u)\nType: %Xh\nHash algorithm: %Xh\nHash size: %Xh (%u)\nMetadata size: %Xh (%u)\nMetadata hash: ", UString info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")\nType: %Xh\nHash algorithm: %Xh\nHash size: %Xh (%u)\nMetadata size: %Xh (%u)\nMetadata hash: ",
module.size(), module.size(), module.size(), module.size(),
moduleHeader->Type, moduleHeader->Type,
moduleHeader->HashAlgorithm, moduleHeader->HashAlgorithm,
moduleHeader->HashSize, moduleHeader->HashSize, moduleHeader->HashSize, moduleHeader->HashSize,
moduleHeader->MetadataSize, moduleHeader->MetadataSize) + UString(hash.toHex().constData()); moduleHeader->MetadataSize, moduleHeader->MetadataSize) + UString(hash.toHex().constData());
// Add tree otem // Add tree otem
model->addItem(offset, Types::CpdSpiEntry, 0, name, UString(), info, UByteArray(), module, UByteArray(), Fixed, index); UModelIndex extIndex = model->addItem(offset, Types::CpdSpiEntry, 0, name, UString(), info, UByteArray(), module, UByteArray(), Fixed, index);
if (sizeof (moduleHeader->MetadataHash) != moduleHeader->HashSize) {
msg(usprintf("%s: CPD Signed Package Info hash size is %d, expected %lu", __FUNCTION__, moduleHeader->HashSize, sizeof (moduleHeader->MetadataHash)), extIndex);
}
offset += module.size(); offset += module.size();
} }
@ -5250,3 +5261,37 @@ USTATUS FfsParser::parseSignedPackageInfoData(const UModelIndex & index)
return U_SUCCESS; return U_SUCCESS;
} }
void FfsParser::outputInfo(void) {
// Show ffsParser's messages
std::vector<std::pair<UString, UModelIndex> > messages = getMessages();
for (size_t i = 0; i < messages.size(); i++) {
std::cout << (const char *)messages[i].first.toLocal8Bit() << std::endl;
}
// Get last VTF
std::vector<std::pair<std::vector<UString>, UModelIndex > > fitTable = getFitTable();
if (fitTable.size()) {
std::cout << "---------------------------------------------------------------------------" << std::endl;
std::cout << " Address | Size | Ver | CS | Type / Info " << std::endl;
std::cout << "---------------------------------------------------------------------------" << std::endl;
for (size_t i = 0; i < fitTable.size(); i++) {
std::cout
<< (const char *)fitTable[i].first[0].toLocal8Bit() << " | "
<< (const char *)fitTable[i].first[1].toLocal8Bit() << " | "
<< (const char *)fitTable[i].first[2].toLocal8Bit() << " | "
<< (const char *)fitTable[i].first[3].toLocal8Bit() << " | "
<< (const char *)fitTable[i].first[4].toLocal8Bit() << " | "
<< (const char *)fitTable[i].first[5].toLocal8Bit() << std::endl;
}
}
// Get security info
UString secInfo = getSecurityInfo();
if (!secInfo.isEmpty()) {
std::cout << "------------------------------------------------------------------------" << std::endl;
std::cout << "Security Info" << std::endl;
std::cout << "------------------------------------------------------------------------" << std::endl;
std::cout << (const char *)secInfo.toLocal8Bit() << std::endl;
}
}

View file

@ -46,7 +46,7 @@ public:
FfsParser(TreeModel* treeModel); FfsParser(TreeModel* treeModel);
~FfsParser(); ~FfsParser();
// Obtain parser messages // Obtain parser messages
std::vector<std::pair<UString, UModelIndex> > getMessages() const; std::vector<std::pair<UString, UModelIndex> > getMessages() const;
// Clear messages // Clear messages
void clearMessages() { messagesVector.clear(); } void clearMessages() { messagesVector.clear(); }
@ -63,6 +63,9 @@ public:
// Obtain offset/address difference // Obtain offset/address difference
UINT64 getAddressDiff() { return addressDiff; } UINT64 getAddressDiff() { return addressDiff; }
// Output some info to stdout
void outputInfo(void);
private: private:
TreeModel *model; TreeModel *model;
std::vector<std::pair<UString, UModelIndex> > messagesVector; std::vector<std::pair<UString, UModelIndex> > messagesVector;

View file

@ -14,6 +14,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "ffsreport.h" #include "ffsreport.h"
#include "ffs.h" #include "ffs.h"
#include "utility.h" #include "utility.h"
#include "uinttypes.h"
std::vector<UString> FfsReport::generate() std::vector<UString> FfsReport::generate()
{ {
@ -62,7 +63,7 @@ USTATUS FfsReport::generateRecursive(std::vector<UString> & report, const UModel
UString(" ") + itemTypeToUString(model->type(index)).leftJustified(16) UString(" ") + itemTypeToUString(model->type(index)).leftJustified(16)
+ UString("| ") + itemSubtypeToUString(model->type(index), model->subtype(index)).leftJustified(22) + UString("| ") + itemSubtypeToUString(model->type(index), model->subtype(index)).leftJustified(22)
+ offset + offset
+ usprintf("| %08X | %08X | ", data.size(), crc) + usprintf("| %08" PRIXQ " | %08X | ", data.size(), crc)
+ urepeated('-', level) + UString(" ") + model->name(index) + (text.isEmpty() ? UString() : UString(" | ") + text) + urepeated('-', level) + UString(" ") + model->name(index) + (text.isEmpty() ? UString() : UString(" | ") + text)
); );

View file

@ -22,7 +22,7 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
// Memory address of a pointer to FIT, 40h back from the end of flash chip // Memory address of a pointer to FIT, 40h back from the end of flash chip
#define FIT_POINTER_OFFSET 0x40 #define FIT_POINTER_OFFSET 0x40
// Entry types // Entry types
#define FIT_TYPE_HEADER 0x00 #define FIT_TYPE_HEADER 0x00
#define FIT_TYPE_MICROCODE 0x01 #define FIT_TYPE_MICROCODE 0x01
#define FIT_TYPE_BIOS_AC_MODULE 0x02 #define FIT_TYPE_BIOS_AC_MODULE 0x02
@ -38,7 +38,7 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#define FIT_MICROCODE_VERSION 0x0100 #define FIT_MICROCODE_VERSION 0x0100
const UByteArray FIT_SIGNATURE const UByteArray FIT_SIGNATURE
("\x5F\x46\x49\x54\x5F\x20\x20\x20", 8); ("\x5F\x46\x49\x54\x5F\x20\x20\x20", 8);
typedef struct FIT_ENTRY_ { typedef struct FIT_ENTRY_ {
UINT64 Address; UINT64 Address;

View file

@ -64,7 +64,7 @@ void initGuidDatabase(const UString & path, UINT32* numEntries)
if (line.size() == 0 || line[0] == '#') if (line.size() == 0 || line[0] == '#')
continue; continue;
// GUID and name are comma-separated // GUID and name are comma-separated
std::vector<UString> lineParts; std::vector<UString> lineParts;
std::string::size_type prev = 0, curr = 0; std::string::size_type prev = 0, curr = 0;
while ((curr = line.find(',', curr)) != std::string::npos) { while ((curr = line.find(',', curr)) != std::string::npos) {
@ -103,7 +103,7 @@ void initGuidDatabase(const UString & path, UINT32* numEntries)
UString guidDatabaseLookup(const EFI_GUID & guid) UString guidDatabaseLookup(const EFI_GUID & guid)
{ {
U_UNUSED_PARAMETER(guid); U_UNUSED_PARAMETER(guid);
return UString(); return UString();
} }
#endif #endif

View file

@ -12,7 +12,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*/ */
#include <inttypes.h>
#include <map> #include <map>
#include "ffs.h" #include "ffs.h"
@ -20,6 +19,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "meparser.h" #include "meparser.h"
#include "parsingdata.h" #include "parsingdata.h"
#include "utility.h" #include "utility.h"
#include "uinttypes.h"
#ifdef U_ENABLE_ME_PARSING_SUPPORT #ifdef U_ENABLE_ME_PARSING_SUPPORT
@ -138,7 +138,7 @@ USTATUS MeParser::parseFptRegion(const UByteArray & region, const UModelIndex &
UByteArray body = region.mid(header.size(), ptBodySize); UByteArray body = region.mid(header.size(), ptBodySize);
UString name = UString("FPT partition table"); UString name = UString("FPT partition table");
UString info = usprintf("Full size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nROM bypass vector: %s\nNumber of entries: %u\nHeader version: %02Xh\nEntry version: %02Xh\n" UString info = usprintf("Full size: %Xh (%u)\nHeader size: %" PRIXQ "h (%" PRIuQ ")\nBody size: %Xh (%u)\nROM bypass vector: %s\nNumber of entries: %u\nHeader version: %02Xh\nEntry version: %02Xh\n"
"Header length: %02Xh\nTicks to add: %04Xh\nTokens to add: %04Xh\nUMA size: %Xh\nFlash layout: %Xh\nFITC version: %u.%u.%u.%u\nChecksum: %02Xh, ", "Header length: %02Xh\nTicks to add: %04Xh\nTokens to add: %04Xh\nUMA size: %Xh\nFlash layout: %Xh\nFITC version: %u.%u.%u.%u\nChecksum: %02Xh, ",
ptSize, ptSize, ptSize, ptSize,
header.size(), header.size(), header.size(), header.size(),
@ -173,7 +173,7 @@ USTATUS MeParser::parseFptRegion(const UByteArray & region, const UModelIndex &
// Get info // Get info
name = visibleAsciiOrHex((UINT8*)ptEntry->Name, 4); name = visibleAsciiOrHex((UINT8*)ptEntry->Name, 4);
info = usprintf("Full size: %Xh (%u)\nPartition offset: %Xh\nPartition length: %Xh\nPartition type: %02Xh", info = usprintf("Full size: %lXh (%lu)\nPartition offset: %Xh\nPartition length: %Xh\nPartition type: %02Xh",
sizeof(FPT_HEADER_ENTRY), sizeof(FPT_HEADER_ENTRY), sizeof(FPT_HEADER_ENTRY), sizeof(FPT_HEADER_ENTRY),
ptEntry->Offset, ptEntry->Offset,
ptEntry->Size, ptEntry->Size,
@ -276,8 +276,8 @@ make_partition_table_consistent:
if (partitions[i].type == Types::FptPartition) { if (partitions[i].type == Types::FptPartition) {
UModelIndex partitionIndex; UModelIndex partitionIndex;
// Get info // Get info
name = visibleAsciiOrHex((UINT8*) partitions[i].ptEntry.Name, 4); name = visibleAsciiOrHex((UINT8*) partitions[i].ptEntry.Name, 4);
info = usprintf("Full size: %Xh (%u)\nPartition type: %02Xh\n", info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")\nPartition type: %02Xh\n",
partition.size(), partition.size(), partition.size(), partition.size(),
partitions[i].ptEntry.Type); partitions[i].ptEntry.Type);
@ -293,7 +293,7 @@ make_partition_table_consistent:
else if (partitions[i].type == Types::Padding) { else if (partitions[i].type == Types::Padding) {
// Get info // Get info
name = UString("Padding"); name = UString("Padding");
info = usprintf("Full size: %Xh (%u)", partition.size(), partition.size()); info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")", partition.size(), partition.size());
// Add tree item // Add tree item
model->addItem(partitions[i].ptEntry.Offset, Types::Padding, getPaddingType(partition), name, UString(), info, UByteArray(), partition, UByteArray(), Fixed, parent); model->addItem(partitions[i].ptEntry.Offset, Types::Padding, getPaddingType(partition), name, UString(), info, UByteArray(), partition, UByteArray(), Fixed, parent);
@ -318,14 +318,14 @@ USTATUS MeParser::parseIfwi16Region(const UByteArray & region, const UModelIndex
UByteArray header = region.left(ptSize); UByteArray header = region.left(ptSize);
UString name = UString("IFWI 1.6 header"); UString name = UString("IFWI 1.6 header");
UString info = usprintf("Full size: %Xh (%u)\n" UString info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")\n"
"Data partition offset: %Xh\nData partition size: %Xh\n" "Data partition offset: %Xh\nData partition size: %Xh\n"
"Boot1 partition offset: %Xh\nBoot1 partition size: %Xh\n" "Boot1 partition offset: %Xh\nBoot1 partition size: %Xh\n"
"Boot2 partition offset: %Xh\nBoot2 partition size: %Xh\n" "Boot2 partition offset: %Xh\nBoot2 partition size: %Xh\n"
"Boot3 partition offset: %Xh\nBoot3 partition size: %Xh\n" "Boot3 partition offset: %Xh\nBoot3 partition size: %Xh\n"
"Boot4 partition offset: %Xh\nBoot4 partition size: %Xh\n" "Boot4 partition offset: %Xh\nBoot4 partition size: %Xh\n"
"Boot5 partition offset: %Xh\nBoot5 partition size: %Xh\n" "Boot5 partition offset: %Xh\nBoot5 partition size: %Xh\n"
"Checksum: %Xh", "Checksum: %llXh",
header.size(), header.size(), header.size(), header.size(),
ifwiHeader->DataPartition.Offset, ifwiHeader->DataPartition.Size, ifwiHeader->DataPartition.Offset, ifwiHeader->DataPartition.Size,
ifwiHeader->BootPartition[0].Offset, ifwiHeader->BootPartition[0].Size, ifwiHeader->BootPartition[0].Offset, ifwiHeader->BootPartition[0].Size,
@ -440,7 +440,7 @@ make_partition_table_consistent:
} }
// Get info // Get info
info = usprintf("Full size: %Xh (%u)\n", info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")\n",
partition.size(), partition.size()); partition.size(), partition.size());
// Add tree item // Add tree item
@ -460,7 +460,7 @@ make_partition_table_consistent:
else if (partitions[i].type == Types::Padding) { else if (partitions[i].type == Types::Padding) {
// Get info // Get info
name = UString("Padding"); name = UString("Padding");
info = usprintf("Full size: %Xh (%u)", partition.size(), partition.size()); info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")", partition.size(), partition.size());
// Add tree item // Add tree item
model->addItem(partitions[i].ptEntry.Offset, Types::Padding, getPaddingType(partition), name, UString(), info, UByteArray(), partition, UByteArray(), Fixed, parent); model->addItem(partitions[i].ptEntry.Offset, Types::Padding, getPaddingType(partition), name, UString(), info, UByteArray(), partition, UByteArray(), Fixed, parent);
@ -486,7 +486,7 @@ USTATUS MeParser::parseIfwi17Region(const UByteArray & region, const UModelIndex
UByteArray header = region.left(ptSize); UByteArray header = region.left(ptSize);
UString name = UString("IFWI 1.7 header"); UString name = UString("IFWI 1.7 header");
UString info = usprintf("Full size: %Xh (%u)\n" UString info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")\n"
"Flags: %02Xh\n" "Flags: %02Xh\n"
"Reserved: %02Xh\n" "Reserved: %02Xh\n"
"Checksum: %Xh\n" "Checksum: %Xh\n"
@ -626,7 +626,7 @@ make_partition_table_consistent:
} }
// Get info // Get info
info = usprintf("Full size: %Xh (%u)\n", info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")\n",
partition.size(), partition.size()); partition.size(), partition.size());
// Add tree item // Add tree item
@ -646,7 +646,7 @@ make_partition_table_consistent:
else if (partitions[i].type == Types::Padding) { else if (partitions[i].type == Types::Padding) {
// Get info // Get info
name = UString("Padding"); name = UString("Padding");
info = usprintf("Full size: %Xh (%u)", partition.size(), partition.size()); info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")", partition.size(), partition.size());
// Add tree item // Add tree item
model->addItem(partitions[i].ptEntry.Offset, Types::Padding, getPaddingType(partition), name, UString(), info, UByteArray(), partition, UByteArray(), Fixed, parent); model->addItem(partitions[i].ptEntry.Offset, Types::Padding, getPaddingType(partition), name, UString(), info, UByteArray(), partition, UByteArray(), Fixed, parent);

View file

@ -25,14 +25,14 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "sha256.h" #include "sha256.h"
#ifdef U_ENABLE_ME_PARSING_SUPPORT #ifdef U_ENABLE_ME_PARSING_SUPPORT
class MeParser class MeParser
{ {
public: public:
// Default constructor and destructor // Default constructor and destructor
MeParser(TreeModel* treeModel, FfsParser* parser) : model(treeModel), ffsParser(parser) {} MeParser(TreeModel* treeModel, FfsParser* parser) : model(treeModel), ffsParser(parser) {}
~MeParser() {} ~MeParser() {}
// Returns messages // Returns messages
std::vector<std::pair<UString, UModelIndex> > getMessages() const { return messagesVector; } std::vector<std::pair<UString, UModelIndex> > getMessages() const { return messagesVector; }
// Clears messages // Clears messages
void clearMessages() { messagesVector.clear(); } void clearMessages() { messagesVector.clear(); }
@ -53,14 +53,14 @@ private:
USTATUS parseIfwi17Region(const UByteArray & region, const UModelIndex & parent, UModelIndex & index); USTATUS parseIfwi17Region(const UByteArray & region, const UModelIndex & parent, UModelIndex & index);
}; };
#else #else
class MeParser class MeParser
{ {
public: public:
// Default constructor and destructor // Default constructor and destructor
MeParser(TreeModel* treeModel, FfsParser* parser) { U_UNUSED_PARAMETER(treeModel); U_UNUSED_PARAMETER(parser); } MeParser(TreeModel* treeModel, FfsParser* parser) { U_UNUSED_PARAMETER(treeModel); U_UNUSED_PARAMETER(parser); }
~MeParser() {} ~MeParser() {}
// Returns messages // Returns messages
std::vector<std::pair<UString, UModelIndex> > getMessages() const { return std::vector<std::pair<UString, UModelIndex> >(); } std::vector<std::pair<UString, UModelIndex> > getMessages() const { return std::vector<std::pair<UString, UModelIndex> >(); }
// Clears messages // Clears messages
void clearMessages() {} void clearMessages() {}

View file

@ -15,7 +15,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
UString nvarAttributesToUString(const UINT8 attributes) UString nvarAttributesToUString(const UINT8 attributes)
{ {
if (attributes == 0x00 || attributes == 0xFF) if (attributes == 0x00 || attributes == 0xFF)
return UString(); return UString();
UString str; UString str;

View file

@ -147,7 +147,7 @@ typedef struct VSS_APPLE_VARIABLE_HEADER_ {
// Authenticated variable header, used for SecureBoot vars // Authenticated variable header, used for SecureBoot vars
typedef struct VSS_AUTH_VARIABLE_HEADER_ { typedef struct VSS_AUTH_VARIABLE_HEADER_ {
UINT16 StartId; // Variable start marker AA55 UINT16 StartId; // Variable start marker AA55
UINT8 State; // Variable state UINT8 State; // Variable state
UINT8 Reserved; UINT8 Reserved;
UINT32 Attributes; // Variable attributes UINT32 Attributes; // Variable attributes
UINT64 MonotonicCounter; // Monotonic counter against replay attack UINT64 MonotonicCounter; // Monotonic counter against replay attack
@ -164,7 +164,7 @@ typedef struct VSS_AUTH_VARIABLE_HEADER_ {
#define NVRAM_VSS_VARIABLE_HEADER_VALID 0x7f // Variable has valid header #define NVRAM_VSS_VARIABLE_HEADER_VALID 0x7f // Variable has valid header
#define NVRAM_VSS_VARIABLE_ADDED 0x3f // Variable has been completely added #define NVRAM_VSS_VARIABLE_ADDED 0x3f // Variable has been completely added
#define NVRAM_VSS_INTEL_VARIABLE_VALID 0xfc // Intel special variable valid #define NVRAM_VSS_INTEL_VARIABLE_VALID 0xfc // Intel special variable valid
#define NVRAM_VSS_INTEL_VARIABLE_INVALID 0xf8 // Intel special variable invalid #define NVRAM_VSS_INTEL_VARIABLE_INVALID 0xf8 // Intel special variable invalid
// VSS variable attributes // VSS variable attributes
#define NVRAM_VSS_VARIABLE_NON_VOLATILE 0x00000001 #define NVRAM_VSS_VARIABLE_NON_VOLATILE 0x00000001

View file

@ -14,11 +14,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
//TODO: relax fixed restrictions once NVRAM builder is ready //TODO: relax fixed restrictions once NVRAM builder is ready
// A workaround for compilers not supporting c++11 and c11
// for using PRIX64.
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#include <map> #include <map>
#include "nvramparser.h" #include "nvramparser.h"
@ -27,6 +22,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "nvram.h" #include "nvram.h"
#include "ffs.h" #include "ffs.h"
#include "fit.h" #include "fit.h"
#include "uinttypes.h"
#ifdef U_ENABLE_NVRAM_PARSING_SUPPORT #ifdef U_ENABLE_NVRAM_PARSING_SUPPORT
USTATUS NvramParser::parseNvarStore(const UModelIndex & index) USTATUS NvramParser::parseNvarStore(const UModelIndex & index)
@ -96,14 +92,14 @@ USTATUS NvramParser::parseNvarStore(const UModelIndex & index)
UByteArray padding = data.mid(offset, unparsedSize); UByteArray padding = data.mid(offset, unparsedSize);
// Get info // Get info
UString info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size()); UString info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")", padding.size(), padding.size());
if ((UINT32)padding.count(emptyByte) == unparsedSize) { // Free space if ((UINT32)padding.count(emptyByte) == unparsedSize) { // Free space
// Add tree item // Add tree item
model->addItem(localOffset + offset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); model->addItem(localOffset + offset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), padding, UByteArray(), Fixed, index);
} }
else { else {
// Nothing is parsed yet, but the file is not empty // Nothing is parsed yet, but the file is not empty
if (!offset) { if (!offset) {
msg(usprintf("%s: file can't be parsed as NVAR variables store", __FUNCTION__), index); msg(usprintf("%s: file can't be parsed as NVAR variables store", __FUNCTION__), index);
return U_SUCCESS; return U_SUCCESS;
@ -117,7 +113,7 @@ USTATUS NvramParser::parseNvarStore(const UModelIndex & index)
UByteArray guidArea = data.right(guidAreaSize); UByteArray guidArea = data.right(guidAreaSize);
// Get info // Get info
name = UString("GUID store"); name = UString("GUID store");
info = usprintf("Full size: %Xh (%u)\nGUIDs in store: %u", info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")\nGUIDs in store: %u",
guidArea.size(), guidArea.size(), guidArea.size(), guidArea.size(),
guidsInStore); guidsInStore);
// Add tree item // Add tree item
@ -323,7 +319,7 @@ USTATUS NvramParser::parseNvarStore(const UModelIndex & index)
info += usprintf("GUID index: %u\n", guidIndex); info += usprintf("GUID index: %u\n", guidIndex);
// Add header, body and extended data info // Add header, body and extended data info
info += usprintf("Full size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)", info += usprintf("Full size: %Xh (%u)\nHeader size: %" PRIXQ "h (%" PRIuQ ")\nBody size: %" PRIXQ "h (%" PRIuQ ")",
entryHeader->Size, entryHeader->Size, entryHeader->Size, entryHeader->Size,
header.size(), header.size(), header.size(), header.size(),
body.size(), body.size()); body.size(), body.size());
@ -366,9 +362,9 @@ USTATUS NvramParser::parseNvarStore(const UModelIndex & index)
// Show messages // Show messages
if (msgUnknownExtDataFormat) msg(usprintf("%s: unknown extended data format", __FUNCTION__), varIndex); if (msgUnknownExtDataFormat) msg(usprintf("%s: unknown extended data format", __FUNCTION__), varIndex);
if (msgExtHeaderTooLong) msg(usprintf("%s: extended header size (%Xh) is greater than body size (%Xh)", __FUNCTION__, if (msgExtHeaderTooLong) msg(usprintf("%s: extended header size (%Xh) is greater than body size (%" PRIXQ "h)", __FUNCTION__,
extendedHeaderSize, body.size()), varIndex); extendedHeaderSize, body.size()), varIndex);
if (msgExtDataTooShort) msg(usprintf("%s: extended header size (%Xh) is too small for timestamp and hash", __FUNCTION__, if (msgExtDataTooShort) msg(usprintf("%s: extended header size (%" PRIXQ "h) is too small for timestamp and hash", __FUNCTION__,
tail.size()), varIndex); tail.size()), varIndex);
// Try parsing the entry data as NVAR storage if it begins with NVAR signature // Try parsing the entry data as NVAR storage if it begins with NVAR signature
@ -417,7 +413,7 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index)
// Get info // Get info
UByteArray padding = data.left(prevStoreOffset); UByteArray padding = data.left(prevStoreOffset);
name = UString("Padding"); name = UString("Padding");
info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size()); info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")", padding.size(), padding.size());
// Add tree item // Add tree item
model->addItem(localOffset, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); model->addItem(localOffset, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index);
@ -436,7 +432,7 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index)
// Get info // Get info
name = UString("Padding"); name = UString("Padding");
info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size()); info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")", padding.size(), padding.size());
// Add tree item // Add tree item
model->addItem(localOffset + paddingOffset, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); model->addItem(localOffset + paddingOffset, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index);
@ -457,7 +453,7 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index)
// Get info // Get info
name = UString("Padding"); name = UString("Padding");
info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size()); info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")", padding.size(), padding.size());
// Add tree item // Add tree item
UModelIndex paddingIndex = model->addItem(localOffset + storeOffset, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); UModelIndex paddingIndex = model->addItem(localOffset + storeOffset, Types::Padding, getPaddingType(padding), name, UString(), info, UByteArray(), padding, UByteArray(), Fixed, index);
@ -487,14 +483,14 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index)
if ((UINT32)data.size() > storeOffset) { if ((UINT32)data.size() > storeOffset) {
UByteArray padding = data.mid(storeOffset); UByteArray padding = data.mid(storeOffset);
// Add info // Add info
info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size()); info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")", padding.size(), padding.size());
if (padding.count(emptyByte) == padding.size()) { // Free space if (padding.count(emptyByte) == padding.size()) { // Free space
// Add tree item // Add tree item
model->addItem(localOffset + storeOffset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); model->addItem(localOffset + storeOffset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), padding, UByteArray(), Fixed, index);
} }
else { else {
// Nothing is parsed yet, but the file is not empty // Nothing is parsed yet, but the file is not empty
if (!storeOffset) { if (!storeOffset) {
msg(usprintf("%s: can't be parsed as NVRAM volume", __FUNCTION__), index); msg(usprintf("%s: can't be parsed as NVRAM volume", __FUNCTION__), index);
return U_SUCCESS; return U_SUCCESS;
@ -548,7 +544,7 @@ USTATUS NvramParser::findNextStore(const UModelIndex & index, const UByteArray &
if (dataSize < sizeof(UINT32)) if (dataSize < sizeof(UINT32))
return U_STORES_NOT_FOUND; return U_STORES_NOT_FOUND;
// TODO: add checks for restSize // TODO: add checks for restSize
UINT32 offset = storeOffset; UINT32 offset = storeOffset;
for (; offset < dataSize - sizeof(UINT32); offset++) { for (; offset < dataSize - sizeof(UINT32); offset++) {
const UINT32* currentPos = (const UINT32*)(volume.constData() + offset); const UINT32* currentPos = (const UINT32*)(volume.constData() + offset);
@ -633,7 +629,7 @@ USTATUS NvramParser::findNextStore(const UModelIndex & index, const UByteArray &
else if (ftwHeader->WriteQueueSize % 0x10 == 0x00) { // Header with 64 bit WriteQueueSize else if (ftwHeader->WriteQueueSize % 0x10 == 0x00) { // Header with 64 bit WriteQueueSize
const EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64* ftw64Header = (const EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64*)currentPos; const EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64* ftw64Header = (const EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64*)currentPos;
if (ftw64Header->WriteQueueSize == 0 || ftw64Header->WriteQueueSize >= 0xFFFFFFFF) { if (ftw64Header->WriteQueueSize == 0 || ftw64Header->WriteQueueSize >= 0xFFFFFFFF) {
msg(usprintf("%s: FTW block candidate at offset %Xh skipped, has invalid body size %Xh", __FUNCTION__, localOffset + offset, ftw64Header->WriteQueueSize), index); msg(usprintf("%s: FTW block candidate at offset %Xh skipped, has invalid body size %llXh", __FUNCTION__, localOffset + offset, ftw64Header->WriteQueueSize), index);
continue; continue;
} }
} }
@ -816,7 +812,7 @@ USTATUS NvramParser::parseVssStoreHeader(const UByteArray & store, const UINT32
name = UString("VSS store"); name = UString("VSS store");
} }
UString info = usprintf("Signature: %Xh\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nFormat: %02Xh\nState: %02Xh\nUnknown: %04Xh", UString info = usprintf("Signature: %Xh\nFull size: %Xh (%u)\nHeader size: %" PRIXQ "h (%" PRIuQ ")\nBody size: %" PRIXQ "h (%" PRIuQ ")\nFormat: %02Xh\nState: %02Xh\nUnknown: %04Xh",
vssStoreHeader->Signature, vssStoreHeader->Signature,
storeSize, storeSize, storeSize, storeSize,
header.size(), header.size(), header.size(), header.size(),
@ -865,7 +861,7 @@ USTATUS NvramParser::parseVss2StoreHeader(const UByteArray & store, const UINT32
// Add info // Add info
UString name = UString("VSS2 store"); UString name = UString("VSS2 store");
UString info = UString("Signature: ") + guidToUString(vssStoreHeader->Signature, false) + UString info = UString("Signature: ") + guidToUString(vssStoreHeader->Signature, false) +
usprintf("\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nFormat: %02Xh\nState: %02Xh\nUnknown: %04Xh", usprintf("\nFull size: %Xh (%u)\nHeader size: %" PRIXQ "h (%" PRIuQ ")\nBody size: %" PRIXQ "h (%" PRIuQ ")\nFormat: %02Xh\nState: %02Xh\nUnknown: %04Xh",
storeSize, storeSize, storeSize, storeSize,
header.size(), header.size(), header.size(), header.size(),
body.size(), body.size(), body.size(), body.size(),
@ -935,7 +931,7 @@ USTATUS NvramParser::parseFtwStoreHeader(const UByteArray & store, const UINT32
// Add info // Add info
UString name("FTW store"); UString name("FTW store");
UString info = UString("Signature: ") + guidToUString(ftw32BlockHeader->Signature, false) + UString info = UString("Signature: ") + guidToUString(ftw32BlockHeader->Signature, false) +
usprintf("\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nState: %02Xh\nHeader CRC32: %08Xh", usprintf("\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %" PRIXQ "h (%" PRIuQ ")\nState: %02Xh\nHeader CRC32: %08Xh",
ftwBlockSize, ftwBlockSize, ftwBlockSize, ftwBlockSize,
headerSize, headerSize, headerSize, headerSize,
body.size(), body.size(), body.size(), body.size(),
@ -976,7 +972,7 @@ USTATUS NvramParser::parseFdcStoreHeader(const UByteArray & store, const UINT32
// Add info // Add info
UString name("FDC store"); UString name("FDC store");
UString info = usprintf("Signature: _FDC\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)", UString info = usprintf("Signature: _FDC\nFull size: %Xh (%u)\nHeader size: %" PRIXQ "h (%" PRIuQ ")\nBody size: %" PRIXQ "h (%" PRIuQ ")",
fdcStoreHeader->Size, fdcStoreHeader->Size, fdcStoreHeader->Size, fdcStoreHeader->Size,
header.size(), header.size(), header.size(), header.size(),
body.size(), body.size()); body.size(), body.size());
@ -1019,13 +1015,14 @@ USTATUS NvramParser::parseFsysStoreHeader(const UByteArray & store, const UINT32
// Add info // Add info
bool isGaidStore = (fsysStoreHeader->Signature == NVRAM_APPLE_GAID_STORE_SIGNATURE); bool isGaidStore = (fsysStoreHeader->Signature == NVRAM_APPLE_GAID_STORE_SIGNATURE);
UString name = isGaidStore ? UString("Gaid store") : UString("Fsys store"); UString name = isGaidStore ? UString("Gaid store") : UString("Fsys store");
UString info = usprintf("Signature: %s\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nUnknown0: %02Xh\nUnknown1: %08Xh\nCRC32: %08Xh", UString info = usprintf("Signature: %s\nFull size: %Xh (%u)\nHeader size: %" PRIXQ "h (%" PRIuQ ")\nBody size: %" PRIXQ "h (%" PRIuQ ")\nUnknown0: %02Xh\nUnknown1: %08Xh\nCRC32: %08Xh",
isGaidStore ? "Gaid" : "Fsys", isGaidStore ? "Gaid" : "Fsys",
fsysStoreHeader->Size, fsysStoreHeader->Size, fsysStoreHeader->Size, fsysStoreHeader->Size,
header.size(), header.size(), header.size(), header.size(),
body.size(), body.size(), body.size(), body.size(),
fsysStoreHeader->Unknown0, fsysStoreHeader->Unknown0,
fsysStoreHeader->Unknown1) fsysStoreHeader->Unknown1,
storedCrc)
+ (storedCrc != calculatedCrc ? usprintf(", invalid, should be %08Xh", calculatedCrc) : UString(", valid")); + (storedCrc != calculatedCrc ? usprintf(", invalid, should be %08Xh", calculatedCrc) : UString(", valid"));
// Add tree item // Add tree item
@ -1064,14 +1061,14 @@ USTATUS NvramParser::parseEvsaStoreHeader(const UByteArray & store, const UINT32
// Add info // Add info
UString name("EVSA store"); UString name("EVSA store");
UString info = usprintf("Signature: EVSA\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nType: %02Xh\nAttributes: %08Xh\nChecksum: %02Xh", UString info = usprintf("Signature: EVSA\nFull size: %Xh (%u)\nHeader size: %" PRIXQ "h (%" PRIuQ ")\nBody size: %" PRIXQ "h (%" PRIuQ ")\nType: %02Xh\nAttributes: %08Xh\nChecksum: %02Xh",
evsaStoreHeader->StoreSize, evsaStoreHeader->StoreSize, evsaStoreHeader->StoreSize, evsaStoreHeader->StoreSize,
header.size(), header.size(), header.size(), header.size(),
body.size(), body.size(), body.size(), body.size(),
evsaStoreHeader->Header.Type, evsaStoreHeader->Header.Type,
evsaStoreHeader->Attributes, evsaStoreHeader->Attributes,
evsaStoreHeader->Header.Checksum) + evsaStoreHeader->Header.Checksum) +
(evsaStoreHeader->Header.Checksum != calculated ? usprintf("%, invalid, should be %02Xh", calculated) : UString(", valid")); (evsaStoreHeader->Header.Checksum != calculated ? usprintf(", invalid, should be %02Xh", calculated) : UString(", valid"));
// Add tree item // Add tree item
index = model->addItem(localOffset, Types::EvsaStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, parent); index = model->addItem(localOffset, Types::EvsaStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, parent);
@ -1107,7 +1104,7 @@ USTATUS NvramParser::parseFlashMapStoreHeader(const UByteArray & store, const UI
// Add info // Add info
UString name("Phoenix SCT flash map"); UString name("Phoenix SCT flash map");
UString info = usprintf("Signature: _FLASH_MAP\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nNumber of entries: %u", UString info = usprintf("Signature: _FLASH_MAP\nFull size: %Xh (%u)\nHeader size: %" PRIXQ "h (%" PRIuQ ")\nBody size: %" PRIXQ "h (%" PRIuQ ")\nNumber of entries: %u",
flashMapSize, flashMapSize, flashMapSize, flashMapSize,
header.size(), header.size(), header.size(), header.size(),
body.size(), body.size(), body.size(), body.size(),
@ -1146,7 +1143,7 @@ USTATUS NvramParser::parseCmdbStoreHeader(const UByteArray & store, const UINT32
// Add info // Add info
UString name("CMDB store"); UString name("CMDB store");
UString info = usprintf("Signature: CMDB\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)", UString info = usprintf("Signature: CMDB\nFull size: %Xh (%u)\nHeader size: %" PRIXQ "h (%" PRIuQ ")\nBody size: %" PRIXQ "h (%" PRIuQ ")",
cmdbSize, cmdbSize, cmdbSize, cmdbSize,
header.size(), header.size(), header.size(), header.size(),
body.size(), body.size()); body.size(), body.size());
@ -1183,7 +1180,7 @@ USTATUS NvramParser::parseSlicPubkeyHeader(const UByteArray & store, const UINT3
// Add info // Add info
UString name("SLIC pubkey"); UString name("SLIC pubkey");
UString info = usprintf("Type: 0h\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: 0h (0)\n" UString info = usprintf("Type: 0h\nFull size: %Xh (%u)\nHeader size: %" PRIXQ "h (%" PRIuQ ")\nBody size: 0h (0)\n"
"Key type: %02Xh\nVersion: %02Xh\nAlgorithm: %08Xh\nMagic: RSA1\nBit length: %08Xh\nExponent: %08Xh", "Key type: %02Xh\nVersion: %02Xh\nAlgorithm: %08Xh\nMagic: RSA1\nBit length: %08Xh\nExponent: %08Xh",
pubkeyHeader->Size, pubkeyHeader->Size, pubkeyHeader->Size, pubkeyHeader->Size,
header.size(), header.size(), header.size(), header.size(),
@ -1225,7 +1222,7 @@ USTATUS NvramParser::parseSlicMarkerHeader(const UByteArray & store, const UINT3
// Add info // Add info
UString name("SLIC marker"); UString name("SLIC marker");
UString info = usprintf("Type: 1h\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: 0h (0)\n" UString info = usprintf("Type: 1h\nFull size: %Xh (%u)\nHeader size: %" PRIXQ "h (%" PRIuQ ")\nBody size: 0h (0)\n"
"Version: %08Xh\nOEM ID: %s\nOEM table ID: %s\nWindows flag: WINDOWS\nSLIC version: %08Xh", "Version: %08Xh\nOEM ID: %s\nOEM table ID: %s\nWindows flag: WINDOWS\nSLIC version: %08Xh",
markerHeader->Size, markerHeader->Size, markerHeader->Size, markerHeader->Size,
header.size(), header.size(), header.size(), header.size(),
@ -1394,7 +1391,7 @@ USTATUS NvramParser::parseVssStoreBody(const UModelIndex & index, UINT8 alignmen
UINT32 variableSize = 0; UINT32 variableSize = 0;
if (unparsedSize >= sizeof(VSS_VARIABLE_HEADER) if (unparsedSize >= sizeof(VSS_VARIABLE_HEADER)
&& variableHeader->StartId == NVRAM_VSS_VARIABLE_START_ID) { && variableHeader->StartId == NVRAM_VSS_VARIABLE_START_ID) {
// Apple VSS variable with CRC32 of the data // Apple VSS variable with CRC32 of the data
if (variableHeader->Attributes & NVRAM_VSS_VARIABLE_APPLE_DATA_CHECKSUM) { if (variableHeader->Attributes & NVRAM_VSS_VARIABLE_APPLE_DATA_CHECKSUM) {
isAppleCrc32 = true; isAppleCrc32 = true;
if (unparsedSize < sizeof(VSS_APPLE_VARIABLE_HEADER)) { if (unparsedSize < sizeof(VSS_APPLE_VARIABLE_HEADER)) {
@ -1486,14 +1483,14 @@ USTATUS NvramParser::parseVssStoreBody(const UModelIndex & index, UINT8 alignmen
// Check if the data left is a free space or a padding // Check if the data left is a free space or a padding
UByteArray padding = data.mid(offset, unparsedSize); UByteArray padding = data.mid(offset, unparsedSize);
// Get info // Get info
UString info = usprintf("Full size: %Xh (%u)", padding.size(), padding.size()); UString info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")", padding.size(), padding.size());
if (padding.count(emptyByte) == padding.size()) { // Free space if (padding.count(emptyByte) == padding.size()) { // Free space
// Add tree item // Add tree item
model->addItem(localOffset + offset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), padding, UByteArray(), Fixed, index); model->addItem(localOffset + offset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), padding, UByteArray(), Fixed, index);
} }
else { // Padding else { // Padding
// Nothing is parsed yet, but the store is not empty // Nothing is parsed yet, but the store is not empty
if (!offset) { if (!offset) {
msg(usprintf("%s: store can't be parsed as VSS store", __FUNCTION__), index); msg(usprintf("%s: store can't be parsed as VSS store", __FUNCTION__), index);
return U_SUCCESS; return U_SUCCESS;
@ -1525,7 +1522,7 @@ USTATUS NvramParser::parseVssStoreBody(const UModelIndex & index, UINT8 alignmen
} }
// Add info // Add info
info += usprintf("Full size: %Xh (%u)\nHeader size %Xh (%u)\nBody size: %Xh (%u)\nState: %02Xh\nReserved: %02Xh\nAttributes: %08Xh (", info += usprintf("Full size: %Xh (%u)\nHeader size: %" PRIXQ "h (%" PRIuQ ")\nBody size: %" PRIXQ "h (%" PRIuQ ")\nState: %02Xh\nReserved: %02Xh\nAttributes: %08Xh (",
variableSize, variableSize, variableSize, variableSize,
header.size(), header.size(), header.size(), header.size(),
body.size(), body.size(), body.size(), body.size(),
@ -1606,7 +1603,7 @@ USTATUS NvramParser::parseFsysStoreBody(const UModelIndex & index)
if (nameSize == 3 && name[0] == 'E' && name[1] == 'O' && name[2] == 'F') { if (nameSize == 3 && name[0] == 'E' && name[1] == 'O' && name[2] == 'F') {
// There is no data afterward, add EOF variable and free space and return // There is no data afterward, add EOF variable and free space and return
UByteArray header = data.mid(offset, sizeof(UINT8) + nameSize); UByteArray header = data.mid(offset, sizeof(UINT8) + nameSize);
UString info = usprintf("Full size: %Xh (%u)", header.size(), header.size()); UString info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")", header.size(), header.size());
// Add EOF tree item // Add EOF tree item
model->addItem(localOffset + offset, Types::FsysEntry, Subtypes::NormalFsysEntry, UString("EOF"), UString(), info, header, UByteArray(), UByteArray(), Fixed, index); model->addItem(localOffset + offset, Types::FsysEntry, Subtypes::NormalFsysEntry, UString("EOF"), UString(), info, header, UByteArray(), UByteArray(), Fixed, index);
@ -1614,7 +1611,7 @@ USTATUS NvramParser::parseFsysStoreBody(const UModelIndex & index)
// Add free space // Add free space
offset += header.size(); offset += header.size();
UByteArray body = data.mid(offset); UByteArray body = data.mid(offset);
info = usprintf("Full size: %Xh (%u)", body.size(), body.size()); info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")", body.size(), body.size());
// Add free space tree item // Add free space tree item
model->addItem(localOffset + offset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), body, UByteArray(), Fixed, index); model->addItem(localOffset + offset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), body, UByteArray(), Fixed, index);
@ -1631,7 +1628,7 @@ USTATUS NvramParser::parseFsysStoreBody(const UModelIndex & index)
else { else {
// Last variable is bad, add the rest as padding and return // Last variable is bad, add the rest as padding and return
UByteArray body = data.mid(offset); UByteArray body = data.mid(offset);
UString info = usprintf("Full size: %Xh (%u)", body.size(), body.size()); UString info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")", body.size(), body.size());
// Add padding tree item // Add padding tree item
model->addItem(localOffset + offset, Types::Padding, getPaddingType(body), UString("Padding"), UString(), info, UByteArray(), body, UByteArray(), Fixed, index); model->addItem(localOffset + offset, Types::Padding, getPaddingType(body), UString("Padding"), UString(), info, UByteArray(), body, UByteArray(), Fixed, index);
@ -1647,7 +1644,7 @@ USTATUS NvramParser::parseFsysStoreBody(const UModelIndex & index)
UByteArray body = data.mid(offset + sizeof(UINT8) + nameSize + sizeof(UINT16), dataSize); UByteArray body = data.mid(offset + sizeof(UINT8) + nameSize + sizeof(UINT16), dataSize);
// Add info // Add info
UString info = usprintf("Full size: %Xh (%u)\nHeader size %Xh (%u)\nBody size: %Xh (%u)", UString info = usprintf("Full size: %Xh (%u)\nHeader size: %" PRIXQ "h (%" PRIuQ ")\nBody size: %" PRIXQ "h (%" PRIuQ ")",
variableSize, variableSize, variableSize, variableSize,
header.size(), header.size(), header.size(), header.size(),
body.size(), body.size()); body.size(), body.size());
@ -1707,7 +1704,7 @@ USTATUS NvramParser::parseEvsaStoreBody(const UModelIndex & index)
variableSize = sizeof(EVSA_ENTRY_HEADER); variableSize = sizeof(EVSA_ENTRY_HEADER);
if (unparsedSize < variableSize || unparsedSize < entryHeader->Size) { if (unparsedSize < variableSize || unparsedSize < entryHeader->Size) {
body = data.mid(offset); body = data.mid(offset);
info = usprintf("Full size: %Xh (%u)", body.size(), body.size()); info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")", body.size(), body.size());
if (body.count(emptyByte) == body.size()) { // Free space if (body.count(emptyByte) == body.size()) { // Free space
// Add free space tree item // Add free space tree item
@ -1735,7 +1732,7 @@ USTATUS NvramParser::parseEvsaStoreBody(const UModelIndex & index)
body = data.mid(offset + sizeof(EVSA_GUID_ENTRY), guidHeader->Header.Size - sizeof(EVSA_GUID_ENTRY)); body = data.mid(offset + sizeof(EVSA_GUID_ENTRY), guidHeader->Header.Size - sizeof(EVSA_GUID_ENTRY));
EFI_GUID guid = *(EFI_GUID*)body.constData(); EFI_GUID guid = *(EFI_GUID*)body.constData();
name = guidToUString(guid); name = guidToUString(guid);
info = UString("GUID: ") + guidToUString(guid, false) + usprintf("\nFull size: %Xh (%u)\nHeader size %Xh (%u)\nBody size: %Xh (%u)\nType: %02Xh\nChecksum: %02Xh", info = UString("GUID: ") + guidToUString(guid, false) + usprintf("\nFull size: %Xh (%u)\nHeader size: %" PRIXQ "h (%" PRIuQ ")\nBody size: %" PRIXQ "h (%" PRIuQ ")\nType: %02Xh\nChecksum: %02Xh",
variableSize, variableSize, variableSize, variableSize,
header.size(), header.size(), header.size(), header.size(),
body.size(), body.size(), body.size(), body.size(),
@ -1759,7 +1756,7 @@ USTATUS NvramParser::parseEvsaStoreBody(const UModelIndex & index)
name = UString::fromUtf16((const CHAR16*)body.constData()); name = UString::fromUtf16((const CHAR16*)body.constData());
#endif #endif
info = UString("Name: ") + name + usprintf("\nFull size: %Xh (%u)\nHeader size %Xh (%u)\nBody size: %Xh (%u)\nType: %02Xh\nChecksum: %02Xh", info = UString("Name: ") + name + usprintf("\nFull size: %Xh (%u)\nHeader size: %" PRIXQ "h (%" PRIuQ ")\nBody size: %" PRIXQ "h (%" PRIuQ ")\nType: %02Xh\nChecksum: %02Xh",
variableSize, variableSize, variableSize, variableSize,
header.size(), header.size(), header.size(), header.size(),
body.size(), body.size(), body.size(), body.size(),
@ -1788,7 +1785,7 @@ USTATUS NvramParser::parseEvsaStoreBody(const UModelIndex & index)
header = data.mid(offset, headerSize); header = data.mid(offset, headerSize);
body = data.mid(offset + headerSize, dataSize); body = data.mid(offset + headerSize, dataSize);
name = UString("Data"); name = UString("Data");
info = usprintf("Full size: %Xh (%u)\nHeader size %Xh (%u)\nBody size: %Xh (%u)\nType: %02Xh\nChecksum: %02Xh", info = usprintf("Full size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nType: %02Xh\nChecksum: %02Xh",
variableSize, variableSize, variableSize, variableSize,
headerSize, headerSize, headerSize, headerSize,
dataSize, dataSize, dataSize, dataSize,
@ -1805,7 +1802,7 @@ USTATUS NvramParser::parseEvsaStoreBody(const UModelIndex & index)
// Unknown entry or free space // Unknown entry or free space
else { else {
body = data.mid(offset); body = data.mid(offset);
info = usprintf("Full size: %Xh (%u)", body.size(), body.size()); info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")", body.size(), body.size());
if (body.count(emptyByte) == body.size()) { // Free space if (body.count(emptyByte) == body.size()) { // Free space
// Add free space tree item // Add free space tree item
@ -1903,7 +1900,7 @@ USTATUS NvramParser::parseFlashMapBody(const UModelIndex & index)
if (unparsedSize < sizeof(PHOENIX_FLASH_MAP_ENTRY)) { if (unparsedSize < sizeof(PHOENIX_FLASH_MAP_ENTRY)) {
// Last variable is bad, add the rest as padding and return // Last variable is bad, add the rest as padding and return
UByteArray body = data.mid(offset); UByteArray body = data.mid(offset);
UString info = usprintf("Full size: %Xh (%u)", body.size(), body.size()); UString info = usprintf("Full size: %" PRIXQ "h (%" PRIuQ ")", body.size(), body.size());
// Add padding tree item // Add padding tree item
model->addItem(localOffset + offset, Types::Padding, getPaddingType(body), UString("Padding"), UString(), info, UByteArray(), body, UByteArray(), Fixed, index); model->addItem(localOffset + offset, Types::Padding, getPaddingType(body), UString("Padding"), UString(), info, UByteArray(), body, UByteArray(), Fixed, index);
@ -1923,7 +1920,7 @@ USTATUS NvramParser::parseFlashMapBody(const UModelIndex & index)
// Add info // Add info
UString info = UString("Entry GUID: ") + guidToUString(entryHeader->Guid, false) + UString info = UString("Entry GUID: ") + guidToUString(entryHeader->Guid, false) +
usprintf("\nFull size: 24h (36)\nHeader size: 24h (36)\nBody size: 0h (0)\n" usprintf("\nFull size: 24h (36)\nHeader size: 24h (36)\nBody size: 0h (0)\n"
"Entry type: %04Xh\nData type: %04Xh\nMemory address: %08Xh\nSize: %08Xh\nOffset: %08Xh", "Entry type: %04Xh\nData type: %04Xh\nMemory address: %08llXh\nSize: %08Xh\nOffset: %08Xh",
entryHeader->EntryType, entryHeader->EntryType,
entryHeader->DataType, entryHeader->DataType,
entryHeader->PhysicalAddress, entryHeader->PhysicalAddress,

View file

@ -24,14 +24,14 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "ffsparser.h" #include "ffsparser.h"
#ifdef U_ENABLE_NVRAM_PARSING_SUPPORT #ifdef U_ENABLE_NVRAM_PARSING_SUPPORT
class NvramParser class NvramParser
{ {
public: public:
// Default constructor and destructor // Default constructor and destructor
NvramParser(TreeModel* treeModel, FfsParser* parser) : model(treeModel), ffsParser(parser) {} NvramParser(TreeModel* treeModel, FfsParser* parser) : model(treeModel), ffsParser(parser) {}
~NvramParser() {} ~NvramParser() {}
// Returns messages // Returns messages
std::vector<std::pair<UString, UModelIndex> > getMessages() const { return messagesVector; } std::vector<std::pair<UString, UModelIndex> > getMessages() const { return messagesVector; }
// Clears messages // Clears messages
void clearMessages() { messagesVector.clear(); } void clearMessages() { messagesVector.clear(); }
@ -70,14 +70,14 @@ private:
USTATUS parseFlashMapBody(const UModelIndex & index); USTATUS parseFlashMapBody(const UModelIndex & index);
}; };
#else #else
class NvramParser class NvramParser
{ {
public: public:
// Default constructor and destructor // Default constructor and destructor
NvramParser(TreeModel* treeModel, FfsParser* parser) { U_UNUSED_PARAMETER(treeModel); U_UNUSED_PARAMETER(parser); } NvramParser(TreeModel* treeModel, FfsParser* parser) { U_UNUSED_PARAMETER(treeModel); U_UNUSED_PARAMETER(parser); }
~NvramParser() {} ~NvramParser() {}
// Returns messages // Returns messages
std::vector<std::pair<UString, UModelIndex> > getMessages() const { return std::vector<std::pair<UString, UModelIndex> >(); } std::vector<std::pair<UString, UModelIndex> > getMessages() const { return std::vector<std::pair<UString, UModelIndex> >(); }
// Clears messages // Clears messages
void clearMessages() {} void clearMessages() {}

View file

@ -45,7 +45,7 @@ extern UString machineTypeToUString(UINT16 machineType);
#define EFI_IMAGE_FILE_MACHINE_IA64 0x0200 // Itanium #define EFI_IMAGE_FILE_MACHINE_IA64 0x0200 // Itanium
#define EFI_IMAGE_FILE_MACHINE_EBC 0x0ebc // EFI Byte Code #define EFI_IMAGE_FILE_MACHINE_EBC 0x0ebc // EFI Byte Code
#define EFI_IMAGE_FILE_MACHINE_AMD64 0x8664 // x86-64 #define EFI_IMAGE_FILE_MACHINE_AMD64 0x8664 // x86-64
#define EFI_IMAGE_FILE_MACHINE_AARCH64 0xaa64 // ARMv8 in 64-bit mode #define EFI_IMAGE_FILE_MACHINE_AARCH64 0xaa64 // ARMv8 in 64-bit mode
#define EFI_IMAGE_FILE_MACHINE_RISCV32 0x5032 // RISC-V 32-bit #define EFI_IMAGE_FILE_MACHINE_RISCV32 0x5032 // RISC-V 32-bit
#define EFI_IMAGE_FILE_MACHINE_RISCV64 0x5064 // RISC-V 64-bit #define EFI_IMAGE_FILE_MACHINE_RISCV64 0x5064 // RISC-V 64-bit
#define EFI_IMAGE_FILE_MACHINE_RISCV128 0x5128 // RISC-V 128-bit #define EFI_IMAGE_FILE_MACHINE_RISCV128 0x5128 // RISC-V 128-bit

View file

@ -108,10 +108,10 @@ static void sha256_compress(struct sha256_state *md, unsigned char *buf)
W[i - 16]; W[i - 16];
} }
/* Compress */ /* Compress */
#define RND(a,b,c,d,e,f,g,h,i) \ #define RND(a,b,c,d,e,f,g,h,i) \
t0 = (uint32_t)(h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]); \ t0 = (uint32_t)(h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]); \
t1 = (uint32_t)(Sigma0(a) + Maj(a, b, c)); \ t1 = (uint32_t)(Sigma0(a) + Maj(a, b, c)); \
d += t0; \ d += t0; \
h = t0 + t1; h = t0 + t1;
for (i = 0; i < 64; ++i) { for (i = 0; i < 64; ++i) {
RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i); RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i);

View file

@ -14,11 +14,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "treeitem.h" #include "treeitem.h"
#include "types.h" #include "types.h"
TreeItem::TreeItem(const UINT32 offset, const UINT8 type, const UINT8 subtype, TreeItem::TreeItem(const UINT32 offset, const UINT8 type, const UINT8 subtype,
const UString & name, const UString & text, const UString & info, const UString & name, const UString & text, const UString & info,
const UByteArray & header, const UByteArray & body, const UByteArray & tail, const UByteArray & header, const UByteArray & body, const UByteArray & tail,
const bool fixed, const bool compressed, const bool fixed, const bool compressed,
TreeItem *parent) : TreeItem *parent) :
itemOffset(offset), itemOffset(offset),
itemAction(Actions::NoAction), itemAction(Actions::NoAction),
itemType(type), itemType(type),
@ -94,8 +94,8 @@ int TreeItem::row() const
} }
TreeItem* TreeItem::child(int row) TreeItem* TreeItem::child(int row)
{ {
std::list<TreeItem*>::iterator child = childItems.begin(); std::list<TreeItem*>::iterator child = childItems.begin();
std::advance(child, row); std::advance(child, row);
return *child; return *child;
} }

View file

@ -334,8 +334,8 @@ void TreeModel::setCompressed(const UModelIndex &index, const bool compressed)
emit dataChanged(index, index); emit dataChanged(index, index);
} }
void TreeModel::TreeModel::setMarkingEnabled(const bool enabled) void TreeModel::TreeModel::setMarkingEnabled(const bool enabled)
{ {
markingEnabledFlag = enabled; markingEnabledFlag = enabled;
emit dataChanged(UModelIndex(), UModelIndex()); emit dataChanged(UModelIndex(), UModelIndex());

View file

@ -37,7 +37,7 @@ enum ItemFixedState {
#define UModelIndex QModelIndex #define UModelIndex QModelIndex
#else #else
// Use own implementation // Use own implementation
#include "ustring.h" #include "ustring.h"
#include "ubytearray.h" #include "ubytearray.h"
#include "basetypes.h" #include "basetypes.h"

View file

@ -97,14 +97,14 @@ UString itemSubtypeToUString(const UINT8 type, const UINT8 subtype)
if (subtype == Subtypes::OnePadding) return UString("Empty (0xFF)"); if (subtype == Subtypes::OnePadding) return UString("Empty (0xFF)");
if (subtype == Subtypes::DataPadding) return UString("Non-empty"); if (subtype == Subtypes::DataPadding) return UString("Non-empty");
break; break;
case Types::Volume: case Types::Volume:
if (subtype == Subtypes::UnknownVolume) return UString("Unknown"); if (subtype == Subtypes::UnknownVolume) return UString("Unknown");
if (subtype == Subtypes::Ffs2Volume) return UString("FFSv2"); if (subtype == Subtypes::Ffs2Volume) return UString("FFSv2");
if (subtype == Subtypes::Ffs3Volume) return UString("FFSv3"); if (subtype == Subtypes::Ffs3Volume) return UString("FFSv3");
if (subtype == Subtypes::NvramVolume) return UString("NVRAM"); if (subtype == Subtypes::NvramVolume) return UString("NVRAM");
if (subtype == Subtypes::MicrocodeVolume) return UString("Microcode"); if (subtype == Subtypes::MicrocodeVolume) return UString("Microcode");
break; break;
case Types::Capsule: case Types::Capsule:
if (subtype == Subtypes::AptioSignedCapsule) return UString("Aptio signed"); if (subtype == Subtypes::AptioSignedCapsule) return UString("Aptio signed");
if (subtype == Subtypes::AptioUnsignedCapsule) return UString("Aptio unsigned"); if (subtype == Subtypes::AptioUnsignedCapsule) return UString("Aptio unsigned");
if (subtype == Subtypes::UefiCapsule) return UString("UEFI 2.0"); if (subtype == Subtypes::UefiCapsule) return UString("UEFI 2.0");
@ -146,7 +146,7 @@ UString itemSubtypeToUString(const UINT8 type, const UINT8 subtype)
if (subtype == Subtypes::IntelMicrocode) return UString("Intel"); if (subtype == Subtypes::IntelMicrocode) return UString("Intel");
if (subtype == Subtypes::AmdMicrocode) return UString("AMD"); if (subtype == Subtypes::AmdMicrocode) return UString("AMD");
break; break;
// ME-specific // ME-specific
case Types::FptEntry: case Types::FptEntry:
if (subtype == Subtypes::ValidFptEntry) return UString("Valid"); if (subtype == Subtypes::ValidFptEntry) return UString("Valid");
if (subtype == Subtypes::InvalidFptEntry) return UString("Invalid"); if (subtype == Subtypes::InvalidFptEntry) return UString("Invalid");

View file

@ -181,7 +181,7 @@ namespace Subtypes {
DataFptPartition, DataFptPartition,
GlutFptPartition GlutFptPartition
}; };
enum CpdPartitionSubtypes { enum CpdPartitionSubtypes {
ManifestCpdPartition = 230, ManifestCpdPartition = 230,
MetadataCpdPartition, MetadataCpdPartition,

View file

@ -64,7 +64,7 @@ public:
} }
UByteArray left(int32_t len) const { return d.substr(0, len); } UByteArray left(int32_t len) const { return d.substr(0, len); }
UByteArray right(int32_t len) const { return d.substr(d.size() - 1 - len, len); } UByteArray right(int32_t len) const { return d.substr(d.size() - len, len); }
UByteArray mid(int32_t pos, int32_t len = -1) const { return d.substr(pos, len); } UByteArray mid(int32_t pos, int32_t len = -1) const { return d.substr(pos, len); }
UByteArray & operator=(const UByteArray & ba) { d = ba.d; return *this; } UByteArray & operator=(const UByteArray & ba) { d = ba.d; return *this; }
@ -77,12 +77,11 @@ public:
for (int32_t i = 0; i < size(); i++) { for (int32_t i = 0; i < size(); i++) {
uint8_t low = d[i] & 0x0F; uint8_t low = d[i] & 0x0F;
uint8_t high = (d[i] & 0xF0) >> 4; uint8_t high = (d[i] & 0xF0) >> 4;
low += (low < 10 ? '0' : 'a'); low += (low < 10 ? '0' : 'a' - 10);
high += (high < 10 ? '0' : 'a'); high += (high < 10 ? '0' : 'a' - 10);
hex[2*i] = low; hex[2*i] = high;
hex[2*i + 1] = high; hex[2*i + 1] = low;
} }
std::reverse(hex.begin(), hex.end());
return UByteArray(hex); return UByteArray(hex);
} }

44
common/uinttypes.h Normal file
View file

@ -0,0 +1,44 @@
/* uinttypes.h
Copyright (c) 2021, 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 UINTTYPES_H
#define UINTTYPES_H
// A workaround for compilers not supporting c++11 and c11
// for using PRIX64.
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#if QT_VERSION_MAJOR >= 6
# define PRIdQ __PRI_64_LENGTH_MODIFIER__ "d"
# define PRIiQ __PRI_64_LENGTH_MODIFIER__ "i"
# define PRIoQ __PRI_64_LENGTH_MODIFIER__ "o"
# define PRIuQ __PRI_64_LENGTH_MODIFIER__ "u"
# define PRIxQ __PRI_64_LENGTH_MODIFIER__ "x"
# define PRIXQ __PRI_64_LENGTH_MODIFIER__ "X"
#else
# define PRIdQ "d"
# define PRIiQ "i"
# define PRIoQ "o"
# define PRIuQ "u"
# define PRIxQ "x"
# define PRIXQ "X"
#endif
#if defined(__clang__) || defined(__GNUC__)
#define ATTRIBUTE_FORMAT_(t,f,a) __attribute__((format(t, f, a)))
#else
#define ATTRIBUTE_FORMAT_(t,f,a)
#endif
#endif // UINTTYPES_H

View file

@ -14,7 +14,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <stdarg.h> #include <stdarg.h>
#if defined(QT_CORE_LIB) #if defined(QT_CORE_LIB)
UString usprintf(const char* fmt, ...) UString usprintf(const char* fmt, ...)
{ {
UString msg; UString msg;
va_list vl; va_list vl;

View file

@ -24,8 +24,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "bstrlib/bstrwrap.h" #include "bstrlib/bstrwrap.h"
#define UString CBString #define UString CBString
#endif // QT_CORE_LIB #endif // QT_CORE_LIB
#include "uinttypes.h"
UString usprintf(const char* fmt, ...); UString usprintf(const char* fmt, ...) ATTRIBUTE_FORMAT_(printf, 1, 2);
UString urepeated(char c, int len); UString urepeated(char c, int len);
#endif // USTRING_H #endif // USTRING_H

View file

@ -95,23 +95,39 @@ UString uniqueItemName(const UModelIndex & index)
+ (subtypeString.length() ? ('_' + subtypeString) : UString()) + (subtypeString.length() ? ('_' + subtypeString) : UString())
+ '_' + name; + '_' + name;
fixFileName(name, true);
return name;
}
// Makes the name usable as a file name
void fixFileName(UString &name, bool replaceSpaces)
{
// Replace some symbols with underscores for compatibility // Replace some symbols with underscores for compatibility
const char table[] = { const char table[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, // ASCII control characters, banned in Windows, hard to work with in *nix
'/', // Banned in *nix and Windows '/', // Banned in *nix and Windows
'<', '>', ':', '\"', '\\', '|', '?', '*', // Banned in Windows '<', '>', ':', '\"', '\\', '|', '?', '*', // Banned in Windows
' ' // Provides better readability
}; };
int nameLength = (int)name.length(); // Note: Qt uses int for whatever reason. int nameLength = (int)name.length(); // Note: Qt uses int for whatever reason.
for (int i = 0; i < nameLength; i++) { for (int i = 0; i < nameLength; i++) {
if (
name[i] < (char)0x20 || // ASCII control characters, banned in Windows, hard to work with in *nix
name[i] > (char)0x7f || // high ASCII characters
(replaceSpaces && name[i] == ' ') // Provides better readability
) {
name[i] = '_';
continue;
}
for (size_t j = 0; j < sizeof(table); j++) { for (size_t j = 0; j < sizeof(table); j++) {
if (name[i] == table[j]) { if (name[i] == table[j]) {
name[i] = '_'; name[i] = '_';
break;
} }
} }
} }
if (!nameLength) {
return name; name = "_";
}
} }
// Returns text representation of error code // Returns text representation of error code
@ -168,7 +184,7 @@ UString errorCodeToUString(USTATUS errorCode)
case U_INVALID_CAPSULE: return UString("Invalid capsule"); case U_INVALID_CAPSULE: return UString("Invalid capsule");
case U_STORES_NOT_FOUND: return UString("Stores not found"); case U_STORES_NOT_FOUND: return UString("Stores not found");
case U_INVALID_STORE_SIZE: return UString("Invalid store size"); case U_INVALID_STORE_SIZE: return UString("Invalid store size");
default: return usprintf("Unknown error %02X", errorCode); default: return usprintf("Unknown error %02lX", errorCode);
} }
} }

View file

@ -29,6 +29,9 @@ UString visibleAsciiOrHex(UINT8* bytes, UINT32 length);
// Returns unique name for tree item // Returns unique name for tree item
UString uniqueItemName(const UModelIndex & index); UString uniqueItemName(const UModelIndex & index);
// Makes the name usable as a file name
void fixFileName(UString &name, bool replaceSpaces);
// Converts error code to UString // Converts error code to UString
UString errorCodeToUString(USTATUS errorCode); UString errorCodeToUString(USTATUS errorCode);
@ -63,9 +66,9 @@ INTN findPattern(const UINT8 *pattern, const UINT8 *patternMask, UINTN patternSi
// Safely dereferences misaligned pointers // Safely dereferences misaligned pointers
template <typename T> template <typename T>
inline T readUnaligned(const T *v) { inline T readUnaligned(const T *v) {
T tmp; T tmp;
memcpy(&tmp, v, sizeof(T)); memcpy(&tmp, v, sizeof(T));
return tmp; return tmp;
} }
#endif // UTILITY_H #endif // UTILITY_H