Merge pull request #57 from LongSoft/LessQt

Integrate LessQt changes
This commit is contained in:
Nikolaj Schlej 2016-07-09 10:17:32 +02:00 committed by GitHub
commit bb8e4a9746
69 changed files with 21646 additions and 3151 deletions

49
UEFIDump/CMakeLists.txt Normal file
View File

@ -0,0 +1,49 @@
PROJECT(UEFIDump)
SET(PROJECT_SOURCES
uefidump_main.cpp
uefidump.cpp
../common/types.cpp
../common/descriptor.cpp
../common/ffs.cpp
../common/nvram.cpp
../common/ffsparser.cpp
../common/ffsreport.cpp
../common/fitparser.cpp
../common/peimage.cpp
../common/treeitem.cpp
../common/treemodel.cpp
../common/utility.cpp
../common/LZMA/LzmaDecompress.c
../common/LZMA/SDK/C/LzmaDec.c
../common/Tiano/EfiTianoDecompress.c
../common/ustring.cpp
../bstrlib/bstrlib.c
../bstrlib/bstrwrap.cpp
)
SET(PROJECT_HEADERS
uefidump.h
../common/basetypes.h
../common/descriptor.h
../common/gbe.h
../common/me.h
../common/ffs.h
../common/nvram.h
../common/ffsparser.h
../common/ffsreport.h
../common/fitparser.h
../common/peimage.h
../common/types.h
../common/treeitem.h
../common/treemodel.h
../common/utility.h
../common/LZMA/LzmaDecompress.h
../common/Tiano/EfiTianoDecompress.h
../common/ubytearray.h
../common/ustring.h
../bstrlib/bstrlib.h
../bstrlib/bstrwrap.h
)
ADD_EXECUTABLE(UEFIDump ${PROJECT_SOURCES} ${PROJECT_HEADERS})

220
UEFIDump/uefidump.cpp Normal file
View File

@ -0,0 +1,220 @@
/* ffsdumper.cpp
Copyright (c) 2015, Nikolaj Schlej. All rights reserved.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*/
#include "uefidump.h"
#include "../common/ffs.h"
#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <sys/stat.h>
#ifdef WIN32
#include <direct.h>
bool isExistOnFs(const UString & path) {
struct _stat buf;
return (_stat((const char*)path.toLocal8Bit(), &buf) == 0);
}
bool makeDirectory(const UString & dir) {
return (_mkdir((const char*)dir.toLocal8Bit()) == 0);
}
bool changeDirectory(const UString & dir) {
return (_chdir((const char*)dir.toLocal8Bit()) == 0);
}
#else
#include <unistd.h>
bool isExistOnFs(const UString & path) {
struct stat buf;
return (stat((const char*)path.toLocal8Bit(), &buf) == 0);
}
bool makeDirectory(const UString & dir) {
return (mkdir((const char*)dir.toLocal8Bit(), ACCESSPERMS) == 0);
}
bool changeDirectory(const UString & dir) {
return (chdir((const char*)dir.toLocal8Bit()) == 0);
}
#endif
USTATUS UEFIDumper::dump(const UByteArray & buffer, const UString & inPath, const UString & guid)
{
UString path = UString(inPath) + UString(".dump");
UString reportPath = UString(inPath) + UString(".report.txt");
if (initialized) {
// Check if called with a different buffer as before
if (buffer != currentBuffer) {
// Reinitalize if so
initialized = false;
}
}
if (!initialized) {
// Fill currentBuffer
currentBuffer = buffer;
// Parse FFS structure
USTATUS result = ffsParser.parse(buffer);
if (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;
}
// Get last VTF
UModelIndex lastVtf = ffsParser.getLastVtf();
if (lastVtf.isValid()) {
// Create fitParser
FitParser fitParser(&model);
// Find and parse FIT table
result = fitParser.parse(model.index(0, 0), lastVtf);
if (U_SUCCESS == result) {
// Show fitParser's messages
std::vector<std::pair<UString, UModelIndex> > fitMessages = fitParser.getMessages();
for (size_t i = 0; i < fitMessages.size(); i++) {
std::cout << (const char*)fitMessages[i].first.toLocal8Bit() << std::endl;
}
// Show FIT table
std::vector<std::vector<UString> > fitTable = fitParser.getFitTable();
if (fitTable.size()) {
std::cout << "-------------------------------------------------------------------" << std::endl;
std::cout << " Address | Size | Ver | Type | CS " << std::endl;
std::cout << "-------------------------------------------------------------------" << std::endl;
for (size_t i = 0; i < fitTable.size(); i++) {
std::cout << (const char*)fitTable[i][0].toLocal8Bit() << " | "
<< (const char*)fitTable[i][1].toLocal8Bit() << " | "
<< (const char*)fitTable[i][2].toLocal8Bit() << " | "
<< (const char*)fitTable[i][3].toLocal8Bit() << " | "
<< (const char*)fitTable[i][4].toLocal8Bit() << std::endl;
}
}
}
}
// Create ffsReport
FfsReport ffsReport(&model);
std::vector<UString> report = ffsReport.generate();
if (report.size()) {
std::ofstream ofs;
ofs.open(reportPath, std::ofstream::out);
for (size_t i = 0; i < report.size(); i++) {
ofs << (const char*)report[i].toLocal8Bit() << std::endl;
}
ofs.close();
}
initialized = true;
}
// Check for dump directory existence
if (isExistOnFs(path))
return U_DIR_ALREADY_EXIST;
// Create dump directory and cd to it
if (!makeDirectory(path))
return U_DIR_CREATE;
if (!changeDirectory(path))
return U_DIR_CHANGE;
dumped = false;
UINT8 result = recursiveDump(model.index(0,0));
if (result)
return result;
else if (!dumped)
return U_ITEM_NOT_FOUND;
return U_SUCCESS;
}
USTATUS UEFIDumper::recursiveDump(const UModelIndex & index)
{
if (!index.isValid())
return U_INVALID_PARAMETER;
//UByteArray itemHeader = model.header(index);
//UByteArray fileHeader = model.header(model.findParentOfType(index, Types::File));
//if (guid.length() == 0 ||
// (itemHeader.size() >= sizeof (EFI_GUID) && guidToUString(*(const EFI_GUID*)itemHeader.constData()) == guid) ||
// (fileHeader.size() >= sizeof(EFI_GUID) && guidToUString(*(const EFI_GUID*)fileHeader.constData()) == guid)) {
// Construct file name
UString orgName = uniqueItemName(index);
UString name = orgName;
bool nameFound = false;
for (int i = 1; i < 1000; ++i) {
if (!isExistOnFs(name + UString("_info.txt"))) {
nameFound = true;
break;
}
name = orgName + UString("_") + usprintf("%03d", i);
}
if (!nameFound)
return U_INVALID_PARAMETER; //TODO: replace with proper errorCode
// Add header and body only for leaf sections
if (model.rowCount(index) == 0) {
// Header
UByteArray data = model.header(index);
if (!data.isEmpty()) {
std::ofstream file;
std::string str = std::string((const char*)name) + std::string("_header.bin");
file.open(str, std::ios::out | std::ios::binary);
file.write(data.constData(), data.size());
file.close();
}
// Body
data = model.body(index);
if (!data.isEmpty()) {
std::ofstream file;
std::string str = std::string((const char*)name) + std::string("_body.bin");
file.open(str, std::ios::out | std::ios::binary);
file.write(data.constData(), data.size());
file.close();
}
}
// Info
UString info = "Type: " + itemTypeToUString(model.type(index)) + "\n" +
"Subtype: " + itemSubtypeToUString(model.type(index), model.subtype(index)) + "\n";
if (model.text(index).length() > 0)
info += "Text: " + model.text(index) + "\n";
info += model.info(index) + "\n";
std::ofstream file;
std::string str = std::string((const char*)name) + std::string("_info.txt");
file.open(str, std::ios::out);
file.write((const char*)info, info.length());
file.close();
dumped = true;
//}
// Process child items
UINT8 result;
for (int i = 0; i < model.rowCount(index); i++) {
result = recursiveDump(index.child(i, 0));
if (result)
return result;
}
return U_SUCCESS;
}

46
UEFIDump/uefidump.h Normal file
View File

@ -0,0 +1,46 @@
/* uefidump.h
Copyright (c) 2016, 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 UEFIDUMP_H
#define UEFIDUMP_H
#include "../common/basetypes.h"
#include "../common/ustring.h"
#include "../common/treemodel.h"
#include "../common/ffsparser.h"
#include "../common/ffsreport.h"
#include "../common/fitparser.h"
class UEFIDumper
{
public:
explicit UEFIDumper() : model(), ffsParser(&model), ffsReport(&model), fitParser(&model), currentBuffer(), initialized(false), dumped(false) {}
~UEFIDumper() {}
USTATUS dump(const UByteArray & buffer, const UString & path, const UString & guid = UString());
private:
USTATUS recursiveDump(const UModelIndex & root);
TreeModel model;
FfsParser ffsParser;
FfsReport ffsReport;
FitParser fitParser;
UByteArray currentBuffer;
bool initialized;
bool dumped;
};
#endif

View File

@ -0,0 +1,42 @@
/* uefidump_main.cpp
Copyright (c) 2016, Nikolaj Schlej. All rights reserved.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*/
#include <iostream>
#include <fstream>
#include "uefidump.h"
int main(int argc, char *argv[])
{
if (argc > 32) {
std::cout << "Too many arguments" << std::endl;
return 1;
}
if (argc > 1) {
std::ifstream inputFile;
inputFile.open(argv[1], std::ios::in | std::ios::binary);
std::vector<char> buffer(std::istreambuf_iterator<char>(inputFile),
(std::istreambuf_iterator<char>()));
inputFile.close();
UEFIDumper uefidumper;
return (uefidumper.dump(buffer, UString(argv[1])) != U_SUCCESS);
}
else {
std::cout << "UEFIDump 0.1.0" << std::endl << std::endl
<< "Usage: UEFIDump imagefile" << std::endl;
return 1;
}
return 1;
}

View File

@ -22,81 +22,83 @@ FfsDumper::~FfsDumper()
{
}
STATUS FfsDumper::dump(const QModelIndex & root, const QString & path, const bool dumpAll, const QString & guid)
USTATUS FfsDumper::dump(const UModelIndex & root, const UString & path, const bool dumpAll, const UString & guid)
{
dumped = false;
UINT8 result = recursiveDump(root, path, dumpAll, guid);
if (result)
return result;
else if (!dumped)
return ERR_ITEM_NOT_FOUND;
return ERR_SUCCESS;
return U_ITEM_NOT_FOUND;
return U_SUCCESS;
}
STATUS FfsDumper::recursiveDump(const QModelIndex & index, const QString & path, const bool dumpAll, const QString & guid)
USTATUS FfsDumper::recursiveDump(const UModelIndex & index, const UString & path, const bool dumpAll, const UString & guid)
{
if (!index.isValid())
return ERR_INVALID_PARAMETER;
return U_INVALID_PARAMETER;
QDir dir;
if (guid.isEmpty() ||
guidToQString(*(const EFI_GUID*)model->header(index).constData()) == guid ||
guidToQString(*(const EFI_GUID*)model->header(model->findParentOfType(index, Types::File)).constData()) == guid) {
guidToUString(*(const EFI_GUID*)model->header(index).constData()) == guid ||
guidToUString(*(const EFI_GUID*)model->header(model->findParentOfType(index, Types::File)).constData()) == guid) {
if (dir.cd(path))
return ERR_DIR_ALREADY_EXIST;
if (dir.cd(QString(path)))
return U_DIR_ALREADY_EXIST;
if (!dir.mkpath(path))
return ERR_DIR_CREATE;
if (!dir.mkpath(QString(path)))
return U_DIR_CREATE;
QFile file;
if (dumpAll || model->rowCount(index) == 0) { // Dump if leaf item or dumpAll is true
if (!model->header(index).isEmpty()) {
file.setFileName(QObject::tr("%1/header.bin").arg(path));
file.setFileName(QString(path) + UString("/header.bin"));
if (!file.open(QFile::WriteOnly))
return ERR_FILE_OPEN;
return U_FILE_OPEN;
file.write(model->header(index));
QByteArray ba(model->header(index).constData(), model->header(index).size());
file.write(ba);
file.close();
}
if (!model->body(index).isEmpty()) {
file.setFileName(QObject::tr("%1/body.bin").arg(path));
file.setFileName(QString(path) + UString("/body.bin"));
if (!file.open(QFile::WriteOnly))
return ERR_FILE_OPEN;
return U_FILE_OPEN;
file.write(model->body(index));
QByteArray ba(model->body(index).constData(), model->body(index).size());
file.write(ba);
file.close();
}
}
// Always dump info
QString info = QObject::tr("Type: %1\nSubtype: %2\n%3%4\n")
.arg(itemTypeToQString(model->type(index)))
.arg(itemSubtypeToQString(model->type(index), model->subtype(index)))
.arg(model->text(index).isEmpty() ? QObject::tr("") : QObject::tr("Text: %1\n").arg(model->text(index)))
.arg(model->info(index));
file.setFileName(QObject::tr("%1/info.txt").arg(path));
UString info = UString("Type: ") + itemTypeToUString(model->type(index)) + UString("\n")
+ UString("Subtype: ") + itemSubtypeToUString(model->type(index), model->subtype(index)) + UString("\n")
+ (model->text(index).isEmpty() ? UString("") : UString("Text: ") + model->text(index) + UString("\n"))
+ model->info(index) + UString("\n");
file.setFileName(QString(path) + UString("/info.txt"));
if (!file.open(QFile::Text | QFile::WriteOnly))
return ERR_FILE_OPEN;
return U_FILE_OPEN;
file.write(info.toLatin1());
file.write(info.toLocal8Bit());
file.close();
dumped = true;
}
UINT8 result;
for (int i = 0; i < model->rowCount(index); i++) {
QModelIndex childIndex = index.child(i, 0);
UModelIndex childIndex = index.child(i, 0);
bool useText = FALSE;
if (model->type(childIndex) != Types::Volume)
useText = !model->text(childIndex).isEmpty();
QString childPath = QString("%1/%2 %3").arg(path).arg(i).arg(useText ? model->text(childIndex) : model->name(childIndex));
UString childPath = path + usprintf("/%u ", i) + (useText ? model->text(childIndex) : model->name(childIndex));
result = recursiveDump(childIndex, childPath, dumpAll, guid);
if (result)
return result;
}
return ERR_SUCCESS;
return U_SUCCESS;
}

View File

@ -14,12 +14,10 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#ifndef FFSDUMPER_H
#define FFSDUMPER_H
#include <QObject>
#include <QDir>
#include <QByteArray>
#include <QString>
#include <QModelIndex>
#include <QDir>
#include "../common/ubytearray.h"
#include "../common/ustring.h"
#include "../common/basetypes.h"
#include "../common/treemodel.h"
#include "../common/ffs.h"
@ -30,10 +28,10 @@ public:
explicit FfsDumper(TreeModel * treeModel);
~FfsDumper();
STATUS dump(const QModelIndex & root, const QString & path, const bool dumpAll = false, const QString & guid = QString());
USTATUS dump(const UModelIndex & root, const UString & path, const bool dumpAll = false, const UString & guid = UString());
private:
STATUS recursiveDump(const QModelIndex & root, const QString & path, const bool dumpAll, const QString & guid);
USTATUS recursiveDump(const UModelIndex & root, const UString & path, const bool dumpAll, const UString & guid);
TreeModel* model;
bool dumped;
};

View File

@ -6,7 +6,8 @@ TEMPLATE = app
CONFIG += console
CONFIG -= app_bundle
SOURCES += uefiextract_main.cpp \
SOURCES += \
uefiextract_main.cpp \
ffsdumper.cpp \
../common/types.cpp \
../common/descriptor.cpp \
@ -22,8 +23,10 @@ SOURCES += uefiextract_main.cpp \
../common/LZMA/LzmaDecompress.c \
../common/LZMA/SDK/C/LzmaDec.c \
../common/Tiano/EfiTianoDecompress.c \
../common/ustring.cpp
HEADERS += ffsdumper.h \
HEADERS += \
ffsdumper.h \
../common/basetypes.h \
../common/descriptor.h \
../common/gbe.h \
@ -39,5 +42,7 @@ HEADERS += ffsdumper.h \
../common/treemodel.h \
../common/utility.h \
../common/LZMA/LzmaDecompress.h \
../common/Tiano/EfiTianoDecompress.h
../common/Tiano/EfiTianoDecompress.h \
../common/ubytearray.h \
../common/ustring.h

View File

@ -11,11 +11,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*/
#include <QCoreApplication>
#include <QString>
#include <QFileInfo>
#include <iostream>
#include <fstream>
#include <../common/ustring.h>
#include "../common/ffsparser.h"
#include "../common/ffsreport.h"
#include "../common/fitparser.h"
@ -35,61 +35,64 @@ int main(int argc, char *argv[])
if (a.arguments().length() > 1) {
// Check that input file exists
QString path = a.arguments().at(1);
QFileInfo fileInfo(path);
UString path(a.arguments().at(1).toLatin1());
QString qpath = QString(path);
QFileInfo fileInfo(qpath);
if (!fileInfo.exists())
return ERR_FILE_OPEN;
return U_FILE_OPEN;
// Open the input file
QFile inputFile;
inputFile.setFileName(path);
inputFile.setFileName(qpath);
if (!inputFile.open(QFile::ReadOnly))
return ERR_FILE_OPEN;
return U_FILE_OPEN;
// Read and close the file
QByteArray buffer = inputFile.readAll();
QByteArray b = inputFile.readAll();
inputFile.close();
UByteArray buffer(b.constData(), b.size());
// Create model and ffsParser
TreeModel model;
FfsParser ffsParser(&model);
// Parse input buffer
STATUS result = ffsParser.parse(buffer);
USTATUS result = ffsParser.parse(buffer);
if (result)
return result;
// Show ffsParser's messages
std::vector<std::pair<QString, QModelIndex> > messages = ffsParser.getMessages();
std::vector<std::pair<UString, UModelIndex> > messages = ffsParser.getMessages();
for (size_t i = 0; i < messages.size(); i++) {
std::cout << messages[i].first.toLatin1().constData() << std::endl;
std::cout << (const char*)messages[i].first.toLocal8Bit() << std::endl;
}
// Get last VTF
QModelIndex lastVtf = ffsParser.getLastVtf();
UModelIndex lastVtf = ffsParser.getLastVtf();
if (lastVtf.isValid()) {
// Create fitParser
FitParser fitParser(&model);
// Find and parse FIT table
result = fitParser.parse(model.index(0, 0), lastVtf);
if (ERR_SUCCESS == result) {
if (U_SUCCESS == result) {
// Show fitParser's messages
std::vector<std::pair<QString, QModelIndex> > fitMessages = fitParser.getMessages();
std::vector<std::pair<UString, UModelIndex> > fitMessages = fitParser.getMessages();
for (size_t i = 0; i < fitMessages.size(); i++) {
std::cout << fitMessages[i].first.toLatin1().constData() << std::endl;
std::cout << (const char*)fitMessages[i].first.toLocal8Bit() << std::endl;
}
// Show FIT table
std::vector<std::vector<QString> > fitTable = fitParser.getFitTable();
std::vector<std::vector<UString> > fitTable = fitParser.getFitTable();
if (fitTable.size()) {
std::cout << "-------------------------------------------------------------------" << std::endl;
std::cout << " Address | Size | Ver | Type | CS " << std::endl;
std::cout << "-------------------------------------------------------------------" << std::endl;
for (size_t i = 0; i < fitTable.size(); i++) {
std::cout << fitTable[i][0].toLatin1().constData() << " | "
<< fitTable[i][1].toLatin1().constData() << " | "
<< fitTable[i][2].toLatin1().constData() << " | "
<< fitTable[i][3].toLatin1().constData() << " | "
<< fitTable[i][4].toLatin1().constData() << std::endl;
std::cout << (const char*)fitTable[i][0].toLocal8Bit() << " | "
<< (const char*)fitTable[i][1].toLocal8Bit() << " | "
<< (const char*)fitTable[i][2].toLocal8Bit() << " | "
<< (const char*)fitTable[i][3].toLocal8Bit() << " | "
<< (const char*)fitTable[i][4].toLocal8Bit() << std::endl;
}
}
}
@ -97,16 +100,14 @@ int main(int argc, char *argv[])
// Create ffsReport
FfsReport ffsReport(&model);
std::vector<QString> report = ffsReport.generate();
std::vector<UString> report = ffsReport.generate();
if (report.size()) {
QFile file;
file.setFileName(fileInfo.fileName().append(".report.txt"));
if (file.open(QFile::Text | QFile::WriteOnly)) {
for (size_t i = 0; i < report.size(); i++) {
file.write(report[i].toLatin1().append('\n'));
}
file.close();
std::ofstream ofs;
ofs.open("report.txt", std::ofstream::out);
for (size_t i = 0; i < report.size(); i++) {
ofs << (const char*)report[i].toLocal8Bit() << std::endl;
}
ofs.close();
}
// Create ffsDumper
@ -114,18 +115,18 @@ int main(int argc, char *argv[])
// Dump all non-leaf elements
if (a.arguments().length() == 2) {
return (ffsDumper.dump(model.index(0, 0), fileInfo.fileName().append(".dump")) != ERR_SUCCESS);
return (ffsDumper.dump(model.index(0, 0), fileInfo.fileName().append(".dump2").toLatin1().constData()) != U_SUCCESS);
}
else if (a.arguments().length() == 3 && a.arguments().at(2) == QString("all")) { // Dump everything
return (ffsDumper.dump(model.index(0, 0), fileInfo.fileName().append(".dump"), true) != ERR_SUCCESS);
else if (a.arguments().length() == 3 && a.arguments().at(2) == UString("all")) { // Dump everything
return (ffsDumper.dump(model.index(0, 0), fileInfo.fileName().append(".dump2").toLatin1().constData(), true) != U_SUCCESS);
}
else if (a.arguments().length() == 3 && a.arguments().at(2) == QString("none")) { // Skip dumping
else if (a.arguments().length() == 3 && a.arguments().at(2) == UString("none")) { // Skip dumping
return 0;
}
else { // Dump specific files
UINT32 returned = 0;
for (int i = 2; i < a.arguments().length(); i++) {
result = ffsDumper.dump(model.index(0, 0), fileInfo.fileName().append(".dump"), true, a.arguments().at(i));
result = ffsDumper.dump(model.index(0, 0), fileInfo.fileName().append(".dump2").toLatin1().constData(), true, a.arguments().at(i).toLatin1().constData());
if (result)
returned |= (1 << (i - 1));
}
@ -143,4 +144,6 @@ int main(int argc, char *argv[])
<< "Return value is a bit mask where 0 at position N means that file with GUID_N was found and unpacked, 1 otherwise" << std::endl;
return 1;
}
return 0;
}

View File

@ -27,20 +27,20 @@ UEFIFind::~UEFIFind()
model = NULL;
}
STATUS UEFIFind::init(const QString & path)
USTATUS UEFIFind::init(const QString & path)
{
STATUS result;
USTATUS result;
fileInfo = QFileInfo(path);
if (!fileInfo.exists())
return ERR_FILE_OPEN;
return U_FILE_OPEN;
QFile inputFile;
inputFile.setFileName(path);
if (!inputFile.open(QFile::ReadOnly))
return ERR_FILE_OPEN;
return U_FILE_OPEN;
QByteArray buffer = inputFile.readAll();
inputFile.close();
@ -50,42 +50,24 @@ STATUS UEFIFind::init(const QString & path)
return result;
initDone = true;
return ERR_SUCCESS;
return U_SUCCESS;
}
QString UEFIFind::guidToQString(const UINT8* guid)
{
const UINT32 u32 = *(const UINT32*)guid;
const UINT16 u16_1 = *(const UINT16*)(guid + 4);
const UINT16 u16_2 = *(const UINT16*)(guid + 6);
const UINT8 u8_1 = *(const UINT8*)(guid + 8);
const UINT8 u8_2 = *(const UINT8*)(guid + 9);
const UINT8 u8_3 = *(const UINT8*)(guid + 10);
const UINT8 u8_4 = *(const UINT8*)(guid + 11);
const UINT8 u8_5 = *(const UINT8*)(guid + 12);
const UINT8 u8_6 = *(const UINT8*)(guid + 13);
const UINT8 u8_7 = *(const UINT8*)(guid + 14);
const UINT8 u8_8 = *(const UINT8*)(guid + 15);
return QString("%1-%2-%3-%4%5-%6%7%8%9%10%11").hexarg2(u32, 8).hexarg2(u16_1, 4).hexarg2(u16_2, 4).hexarg2(u8_1, 2).hexarg2(u8_2, 2)
.hexarg2(u8_3, 2).hexarg2(u8_4, 2).hexarg2(u8_5, 2).hexarg2(u8_6, 2).hexarg2(u8_7, 2).hexarg2(u8_8, 2);
}
STATUS UEFIFind::find(const UINT8 mode, const bool count, const QString & hexPattern, QString & result)
USTATUS UEFIFind::find(const UINT8 mode, const bool count, const QString & hexPattern, QString & result)
{
QModelIndex root = model->index(0, 0);
std::set<std::pair<QModelIndex, QModelIndex> > files;
result.clear();
STATUS returned = findFileRecursive(root, hexPattern, mode, files);
USTATUS returned = findFileRecursive(root, hexPattern, mode, files);
if (returned)
return returned;
if (count) {
if (!files.empty())
result.append(QString("%1\n").arg(files.size()));
return ERR_SUCCESS;
return U_SUCCESS;
}
for (std::set<std::pair<QModelIndex, QModelIndex> >::const_iterator citer = files.cbegin(); citer != files.cend(); ++citer) {
@ -93,30 +75,30 @@ STATUS UEFIFind::find(const UINT8 mode, const bool count, const QString & hexPat
std::pair<QModelIndex, QModelIndex> indexes = *citer;
if (!model->hasEmptyHeader(indexes.first))
data = model->header(indexes.first).left(16);
result.append(guidToQString((const UINT8*)data.constData()));
result.append(guidToUString(*(const EFI_GUID*)data.constData()));
// Special case of freeform subtype GUID files
if (indexes.second.isValid() && model->subtype(indexes.second) == EFI_SECTION_FREEFORM_SUBTYPE_GUID) {
data = model->header(indexes.second).left(sizeof(EFI_FREEFORM_SUBTYPE_GUID_SECTION));
result.append(" ").append(guidToQString((const UINT8*)data.constData() + sizeof(EFI_COMMON_SECTION_HEADER)));
result.append(" ").append(guidToUString(*(const EFI_GUID*)(data.constData() + sizeof(EFI_COMMON_SECTION_HEADER))));
}
result.append("\n");
}
return ERR_SUCCESS;
return U_SUCCESS;
}
STATUS UEFIFind::findFileRecursive(const QModelIndex index, const QString & hexPattern, const UINT8 mode, std::set<std::pair<QModelIndex, QModelIndex> > & files)
USTATUS UEFIFind::findFileRecursive(const QModelIndex index, const QString & hexPattern, const UINT8 mode, std::set<std::pair<QModelIndex, QModelIndex> > & files)
{
if (!index.isValid())
return ERR_SUCCESS;
return U_SUCCESS;
if (hexPattern.isEmpty())
return ERR_INVALID_PARAMETER;
return U_INVALID_PARAMETER;
// Check for "all substrings" pattern
if (hexPattern.count('.') == hexPattern.length())
return ERR_SUCCESS;
return U_SUCCESS;
bool hasChildren = (model->rowCount(index) > 0);
for (int i = 0; i < model->rowCount(index); i++) {
@ -157,5 +139,5 @@ STATUS UEFIFind::findFileRecursive(const QModelIndex index, const QString & hexP
offset = regexp.indexIn(hexBody, offset + 1);
}
return ERR_SUCCESS;
return U_SUCCESS;
}

View File

@ -34,11 +34,11 @@ public:
explicit UEFIFind();
~UEFIFind();
STATUS init(const QString & path);
STATUS find(const UINT8 mode, const bool count, const QString & hexPattern, QString & result);
USTATUS init(const QString & path);
USTATUS find(const UINT8 mode, const bool count, const QString & hexPattern, QString & result);
private:
STATUS findFileRecursive(const QModelIndex index, const QString & hexPattern, const UINT8 mode, std::set<std::pair<QModelIndex, QModelIndex> > & files);
USTATUS findFileRecursive(const QModelIndex index, const QString & hexPattern, const UINT8 mode, std::set<std::pair<QModelIndex, QModelIndex> > & files);
QString guidToQString(const UINT8* guid);
FfsParser* ffsParser;

View File

@ -20,6 +20,7 @@ SOURCES += uefifind_main.cpp \
../common/LZMA/LzmaDecompress.c \
../common/LZMA/SDK/C/LzmaDec.c \
../common/Tiano/EfiTianoDecompress.c \
../common/ustring.cpp
HEADERS += uefifind.h \
../common/basetypes.h \
@ -35,5 +36,7 @@ HEADERS += uefifind.h \
../common/treemodel.h \
../common/utility.h \
../common/LZMA/LzmaDecompress.h \
../common/Tiano/EfiTianoDecompress.h
../common/Tiano/EfiTianoDecompress.h \
../common/ustring.h \
../common/ubytearray.h

View File

@ -34,7 +34,7 @@ int main(int argc, char *argv[])
else if (a.arguments().at(1) == QString("all"))
mode = SEARCH_MODE_ALL;
else
return ERR_INVALID_PARAMETER;
return U_INVALID_PARAMETER;
// Get result type
bool count;
@ -43,7 +43,7 @@ int main(int argc, char *argv[])
else if (a.arguments().at(2) == QString("count"))
count = true;
else
return ERR_INVALID_PARAMETER;
return U_INVALID_PARAMETER;
// Parse input file
result = w.init(a.arguments().at(4));
@ -58,26 +58,26 @@ int main(int argc, char *argv[])
// Nothing is found
if (found.isEmpty())
return ERR_ITEM_NOT_FOUND;
return U_ITEM_NOT_FOUND;
// Print result
std::cout << found.toStdString();
return ERR_SUCCESS;
return U_SUCCESS;
}
else if (a.arguments().length() == 4) {
// Get search mode
if (a.arguments().at(1) != QString("file"))
return ERR_INVALID_PARAMETER;
return U_INVALID_PARAMETER;
// Open patterns file
QFileInfo fileInfo(a.arguments().at(2));
if (!fileInfo.exists())
return ERR_FILE_OPEN;
return U_FILE_OPEN;
QFile patternsFile;
patternsFile.setFileName(a.arguments().at(2));
if (!patternsFile.open(QFile::ReadOnly))
return ERR_FILE_OPEN;
return U_FILE_OPEN;
// Parse input file
result = w.init(a.arguments().at(3));
@ -143,15 +143,15 @@ int main(int argc, char *argv[])
// Nothing is found
if (!somethingFound)
return ERR_ITEM_NOT_FOUND;
return U_ITEM_NOT_FOUND;
return ERR_SUCCESS;
return U_SUCCESS;
}
else {
std::cout << "UEFIFind 0.10.6" << std::endl << std::endl <<
"Usage: UEFIFind {header | body | all} {list | count} pattern imagefile" << std::endl <<
" or UEFIFind file patternsfile imagefile" << std::endl;
return ERR_INVALID_PARAMETER;
return U_INVALID_PARAMETER;
}
}

View File

@ -13,24 +13,24 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "ffsfinder.h"
STATUS FfsFinder::findHexPattern(const QModelIndex & index, const QByteArray & hexPattern, const UINT8 mode)
USTATUS FfsFinder::findHexPattern(const UModelIndex & index, const UByteArray & hexPattern, const UINT8 mode)
{
if (!index.isValid())
return ERR_SUCCESS;
return U_SUCCESS;
if (hexPattern.isEmpty())
return ERR_INVALID_PARAMETER;
return U_INVALID_PARAMETER;
// Check for "all substrings" pattern
if (hexPattern.count('.') == hexPattern.length())
return ERR_SUCCESS;
return U_SUCCESS;
bool hasChildren = (model->rowCount(index) > 0);
for (int i = 0; i < model->rowCount(index); i++) {
findHexPattern(index.child(i, index.column()), hexPattern, mode);
}
QByteArray data;
UByteArray data;
if (hasChildren) {
if (mode != SEARCH_MODE_BODY)
data = model->header(index);
@ -44,39 +44,37 @@ STATUS FfsFinder::findHexPattern(const QModelIndex & index, const QByteArray & h
data.append(model->header(index)).append(model->body(index));
}
QString hexBody = QString(data.toHex());
QRegExp regexp = QRegExp(QString(hexPattern), Qt::CaseInsensitive);
UString hexBody = UString(data.toHex());
QRegExp regexp = QRegExp(UString(hexPattern), Qt::CaseInsensitive);
INT32 offset = regexp.indexIn(hexBody);
while (offset >= 0) {
if (offset % 2 == 0) {
msg(QObject::tr("Hex pattern \"%1\" found as \"%2\" in %3 at %4-offset %5h")
.arg(QString(hexPattern))
.arg(hexBody.mid(offset, hexPattern.length()).toUpper())
.arg(model->name(index))
.arg(mode == SEARCH_MODE_BODY ? QObject::tr("body") : QObject::tr("header"))
.hexarg(offset / 2),
msg(UString("Hex pattern \"") + UString(hexPattern)
+ UString("\" found as \"") + hexBody.mid(offset, hexPattern.length()).toUpper()
+ UString("\" in ") + model->name(index)
+ usprintf(" at %s-offset %02Xh", mode == SEARCH_MODE_BODY ? "body" : "header", offset / 2),
index);
}
offset = regexp.indexIn(hexBody, offset + 1);
}
return ERR_SUCCESS;
return U_SUCCESS;
}
STATUS FfsFinder::findGuidPattern(const QModelIndex & index, const QByteArray & guidPattern, const UINT8 mode)
USTATUS FfsFinder::findGuidPattern(const UModelIndex & index, const UByteArray & guidPattern, const UINT8 mode)
{
if (guidPattern.isEmpty())
return ERR_INVALID_PARAMETER;
return U_INVALID_PARAMETER;
if (!index.isValid())
return ERR_SUCCESS;
return U_SUCCESS;
bool hasChildren = (model->rowCount(index) > 0);
for (int i = 0; i < model->rowCount(index); i++) {
findGuidPattern(index.child(i, index.column()), guidPattern, mode);
}
QByteArray data;
UByteArray data;
if (hasChildren) {
if (mode != SEARCH_MODE_BODY)
data = model->header(index);
@ -90,12 +88,12 @@ STATUS FfsFinder::findGuidPattern(const QModelIndex & index, const QByteArray &
data.append(model->header(index)).append(model->body(index));
}
QString hexBody = QString(data.toHex());
QList<QByteArray> list = guidPattern.split('-');
UString hexBody = UString(data.toHex());
QList<UByteArray> list = guidPattern.split('-');
if (list.count() != 5)
return ERR_INVALID_PARAMETER;
return U_INVALID_PARAMETER;
QByteArray hexPattern;
UByteArray hexPattern;
// Reverse first GUID block
hexPattern.append(list.at(0).mid(6, 2));
hexPattern.append(list.at(0).mid(4, 2));
@ -112,40 +110,38 @@ STATUS FfsFinder::findGuidPattern(const QModelIndex & index, const QByteArray &
// Check for "all substrings" pattern
if (hexPattern.count('.') == hexPattern.length())
return ERR_SUCCESS;
return U_SUCCESS;
QRegExp regexp(QString(hexPattern), Qt::CaseInsensitive);
QRegExp regexp(UString(hexPattern), Qt::CaseInsensitive);
INT32 offset = regexp.indexIn(hexBody);
while (offset >= 0) {
if (offset % 2 == 0) {
msg(QObject::tr("GUID pattern \"%1\" found as \"%2\" in %3 at %4-offset %5h")
.arg(QString(guidPattern))
.arg(hexBody.mid(offset, hexPattern.length()).toUpper())
.arg(model->name(index))
.arg(mode == SEARCH_MODE_BODY ? QObject::tr("body") : QObject::tr("header"))
.hexarg(offset / 2),
msg(UString("GUID pattern \"") + UString(guidPattern)
+ UString("\" found as \"") + hexBody.mid(offset, hexPattern.length()).toUpper()
+ UString("\" in ") + model->name(index)
+ usprintf(" at %s-offset %02Xh", mode == SEARCH_MODE_BODY ? "body" : "header", offset / 2),
index);
}
offset = regexp.indexIn(hexBody, offset + 1);
}
return ERR_SUCCESS;
return U_SUCCESS;
}
STATUS FfsFinder::findTextPattern(const QModelIndex & index, const QString & pattern, const UINT8 mode, const bool unicode, const Qt::CaseSensitivity caseSensitive)
USTATUS FfsFinder::findTextPattern(const UModelIndex & index, const UString & pattern, const UINT8 mode, const bool unicode, const Qt::CaseSensitivity caseSensitive)
{
if (pattern.isEmpty())
return ERR_INVALID_PARAMETER;
return U_INVALID_PARAMETER;
if (!index.isValid())
return ERR_SUCCESS;
return U_SUCCESS;
bool hasChildren = (model->rowCount(index) > 0);
for (int i = 0; i < model->rowCount(index); i++) {
findTextPattern(index.child(i, index.column()), pattern, mode, unicode, caseSensitive);
}
QByteArray body;
UByteArray body;
if (hasChildren) {
if (mode != SEARCH_MODE_BODY)
body = model->header(index);
@ -159,22 +155,20 @@ STATUS FfsFinder::findTextPattern(const QModelIndex & index, const QString & pat
body.append(model->header(index)).append(model->body(index));
}
QString data;
UString data;
if (unicode)
data = QString::fromUtf16((const ushort*)body.constData(), body.length() / 2);
data = UString::fromUtf16((const ushort*)body.constData(), body.length() / 2);
else
data = QString::fromLatin1((const char*)body.constData(), body.length());
data = UString::fromLatin1((const char*)body.constData(), body.length());
int offset = -1;
while ((offset = data.indexOf(pattern, offset + 1, caseSensitive)) >= 0) {
msg(QObject::tr("%1 text \"%2\" found in %3 at %4-offset %5h")
.arg(unicode ? "Unicode" : "ASCII")
.arg(pattern)
.arg(model->name(index))
.arg(mode == SEARCH_MODE_BODY ? QObject::tr("body") : QObject::tr("header"))
.hexarg(unicode ? offset * 2 : offset),
msg((unicode ? UString("Unicode") : UString("ASCII")) + UString(" text \"") + UString(pattern)
+ UString("\" found in ") + model->name(index)
+ usprintf(" at %s-offset %02Xh", mode == SEARCH_MODE_BODY ? "body" : "header", (unicode ? offset * 2 : offset)),
index);
}
return ERR_SUCCESS;
return U_SUCCESS;
}

View File

@ -15,13 +15,10 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#define FFSFINDER_H
#include <vector>
#include <QObject>
#include <QByteArray>
#include <QString>
#include <QModelIndex>
#include <QRegExp>
#include "../common/ubytearray.h"
#include "../common/ustring.h"
#include "../common/basetypes.h"
#include "../common/treemodel.h"
@ -31,19 +28,19 @@ public:
FfsFinder(const TreeModel * treeModel) : model(treeModel) {}
~FfsFinder() {}
std::vector<std::pair<QString, QModelIndex> > getMessages() const { return messagesVector; }
std::vector<std::pair<UString, UModelIndex> > getMessages() const { return messagesVector; }
void clearMessages() { messagesVector.clear(); }
STATUS findHexPattern(const QModelIndex & index, const QByteArray & hexPattern, const UINT8 mode);
STATUS findGuidPattern(const QModelIndex & index, const QByteArray & guidPattern, const UINT8 mode);
STATUS findTextPattern(const QModelIndex & index, const QString & pattern, const UINT8 mode, const bool unicode, const Qt::CaseSensitivity caseSensitive);
USTATUS findHexPattern(const UModelIndex & index, const UByteArray & hexPattern, const UINT8 mode);
USTATUS findGuidPattern(const UModelIndex & index, const UByteArray & guidPattern, const UINT8 mode);
USTATUS findTextPattern(const UModelIndex & index, const UString & pattern, const UINT8 mode, const bool unicode, const Qt::CaseSensitivity caseSensitive);
private:
const TreeModel* model;
std::vector<std::pair<QString, QModelIndex> > messagesVector;
std::vector<std::pair<UString, UModelIndex> > messagesVector;
void msg(const QString & message, const QModelIndex &index = QModelIndex()) {
messagesVector.push_back(std::pair<QString, QModelIndex>(message, index));
void msg(const UString & message, const UModelIndex &index = UModelIndex()) {
messagesVector.push_back(std::pair<UString, UModelIndex>(message, index));
}
};

View File

@ -17,7 +17,7 @@
UEFITool::UEFITool(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::UEFITool),
version(tr("0.30.0_alpha28"))
version(tr("0.30.0_alpha29"))
{
clipboard = QApplication::clipboard();
@ -211,7 +211,7 @@ bool UEFITool::enableExtractBodyUncompressed(const QModelIndex &current)
if (current.isValid() && model->type(current) == Types::Section &&
(model->subtype(current) == EFI_SECTION_COMPRESSION || model->subtype(current) == EFI_SECTION_GUID_DEFINED)) {
// Get parsing data
PARSING_DATA pdata = parsingDataFromQModelIndex(current);
PARSING_DATA pdata = parsingDataFromUModelIndex(current);
if (model->subtype(current) == EFI_SECTION_COMPRESSION &&
pdata.section.compressed.algorithm != COMPRESSION_ALGORITHM_NONE &&
@ -297,7 +297,7 @@ void UEFITool::goToData()
QModelIndex parent = model->parent(index);
for (int i = index.row(); i < model->rowCount(parent); i++) {
PARSING_DATA pdata = parsingDataFromQModelIndex(index);
PARSING_DATA pdata = parsingDataFromUModelIndex(index);
UINT32 lastVariableFlag = pdata.emptyByte ? 0xFFFFFF : 0;
if (pdata.nvar.next == lastVariableFlag) {
ui->structureTreeView->scrollTo(index, QAbstractItemView::PositionAtCenter);
@ -306,7 +306,7 @@ void UEFITool::goToData()
for (int j = i + 1; j < model->rowCount(parent); j++) {
QModelIndex currentIndex = parent.child(j, 0);
PARSING_DATA currentPdata = parsingDataFromQModelIndex(currentIndex);
PARSING_DATA currentPdata = parsingDataFromUModelIndex(currentIndex);
if (currentPdata.offset == pdata.offset + pdata.nvar.next) {
index = currentIndex;
break;
@ -481,7 +481,7 @@ void UEFITool::replace(const UINT8 mode)
UINT8 result = ffsOps->replace(index, buffer, mode);
if (result) {
QMessageBox::critical(this, tr("Replacing failed"), errorCodeToQString(result), QMessageBox::Ok);
QMessageBox::critical(this, tr("Replacing failed"), errorCodeToUString(result), QMessageBox::Ok);
return;
}
ui->actionSaveImageFile->setEnabled(true);
@ -512,7 +512,7 @@ void UEFITool::extract(const UINT8 mode)
QString name;
UINT8 result = ffsOps->extract(index, name, extracted, mode);
if (result) {
QMessageBox::critical(this, tr("Extraction failed"), errorCodeToQString(result), QMessageBox::Ok);
QMessageBox::critical(this, tr("Extraction failed"), errorCodeToUString(result), QMessageBox::Ok);
return;
}
@ -609,21 +609,21 @@ void UEFITool::extract(const UINT8 mode)
void UEFITool::rebuild()
{
QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex();
UModelIndex index = ui->structureTreeView->selectionModel()->currentIndex();
if (!index.isValid())
return;
if (ERR_SUCCESS == ffsOps->rebuild(index))
if (U_SUCCESS == ffsOps->rebuild(index))
ui->actionSaveImageFile->setEnabled(true);
}
void UEFITool::remove()
{
QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex();
UModelIndex index = ui->structureTreeView->selectionModel()->currentIndex();
if (!index.isValid())
return;
if (ERR_SUCCESS == ffsOps->remove(index))
if (U_SUCCESS == ffsOps->remove(index))
ui->actionSaveImageFile->setEnabled(true);
}
@ -661,10 +661,10 @@ void UEFITool::saveImageFile()
// Create ffsBuilder
delete ffsBuilder;
ffsBuilder = new FfsBuilder(model);
STATUS result = ffsBuilder->build(model->index(0,0), reconstructed);
USTATUS result = ffsBuilder->build(model->index(0,0), reconstructed);
showBuilderMessages();
if (result) {
QMessageBox::critical(this, tr("Image build failed"), errorCodeToQString(result), QMessageBox::Ok);
QMessageBox::critical(this, tr("Image build failed"), errorCodeToUString(result), QMessageBox::Ok);
return;
}
@ -725,7 +725,7 @@ void UEFITool::openImageFile(QString path)
UINT8 result = ffsParser->parse(buffer);
showParserMessages();
if (result) {
QMessageBox::critical(this, tr("Image parsing failed"), errorCodeToQString(result), QMessageBox::Ok);
QMessageBox::critical(this, tr("Image parsing failed"), errorCodeToUString(result), QMessageBox::Ok);
return;
}
else

View File

@ -29,7 +29,8 @@ SOURCES += uefitool_main.cpp \
../common/LZMA/SDK/C/LzmaEnc.c \
../common/Tiano/EfiTianoDecompress.c \
../common/Tiano/EfiTianoCompress.c \
../common/Tiano/EfiTianoCompressLegacy.c
../common/Tiano/EfiTianoCompressLegacy.c \
../common/ustring.cpp \
HEADERS += uefitool.h \
searchdialog.h \
@ -56,7 +57,9 @@ HEADERS += uefitool.h \
../common/LZMA/LzmaCompress.h \
../common/LZMA/LzmaDecompress.h \
../common/Tiano/EfiTianoDecompress.h \
../common/Tiano/EfiTianoCompress.h
../common/Tiano/EfiTianoCompress.h \
../common/ustring.h \
../common/ubytearray.h \
FORMS += uefitool.ui \
searchdialog.ui

28
bstrlib/LICENSE Normal file
View File

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

34
bstrlib/README.md Normal file
View File

@ -0,0 +1,34 @@
The Better String Library
The Better String Library is an abstraction of a string data type which is
superior to the C library char buffer string type, or C++'s std::string.
Among the features achieved are:
- Substantial mitigation of buffer overflow/overrun problems and other
failures that result from erroneous usage of the common C string
library functions
- Significantly simplified string manipulation
- High performance interoperability with other source/libraries which
expect '\0' terminated char buffers
- Improved overall performance of common string operations
- Functional equivalency with other more modern languages
The library is totally stand alone, portable (known to work with gcc/g++,
MSVC++, Intel C++, WATCOM C/C++, Turbo C, Borland C++, IBM's native CC
compiler on Windows, Linux and Mac OS X), high performance, easy to use and
is not part of some other collection of data structures. Even the file I/O
functions are totally abstracted (so that other stream-like mechanisms, like
sockets, can be used.) Nevertheless, it is adequate as a complete
replacement of the C string library for string manipulation in any C program.
The library includes a robust C++ wrapper that uses overloaded operators,
rich constructors, exceptions, stream I/O and STL to make the CBString
struct a natural and powerful string abstraction with more functionality and
higher performance than std::string.
Bstrlib is stable, well tested and suitable for any software production
environment.

82
bstrlib/bsafe.c Normal file
View File

@ -0,0 +1,82 @@
/*
* This source file is part of the bstring string library. This code was
* written by Paul Hsieh in 2002-2015, and is covered by the BSD open source
* license. Refer to the accompanying documentation for details on usage and
* license.
*/
/*
* bsafe.c
*
* This is an optional module that can be used to help enforce a safety
* standard based on pervasive usage of bstrlib. This file is not necessarily
* portable, however, it has been tested to work correctly with Intel's C/C++
* compiler, WATCOM C/C++ v11.x and Microsoft Visual C++.
*/
#include <stdio.h>
#include <stdlib.h>
#include "bsafe.h"
static int bsafeShouldExit = 1;
char * strcpy (char *dst, const char *src);
char * strcat (char *dst, const char *src);
char * strcpy (char *dst, const char *src) {
(void) dst;
(void) src;
fprintf (stderr, "bsafe error: strcpy() is not safe, use bstrcpy instead.\n");
if (bsafeShouldExit) exit (-1);
return NULL;
}
char * strcat (char *dst, const char *src) {
(void) dst;
(void) src;
fprintf (stderr, "bsafe error: strcat() is not safe, use bstrcat instead.\n");
if (bsafeShouldExit) exit (-1);
return NULL;
}
#if !defined (__GNUC__) && (!defined(_MSC_VER) || (_MSC_VER <= 1310))
char * (gets) (char * buf) {
(void) buf;
fprintf (stderr, "bsafe error: gets() is not safe, use bgets.\n");
if (bsafeShouldExit) exit (-1);
return NULL;
}
#endif
char * (strncpy) (char *dst, const char *src, size_t n) {
(void) dst;
(void) src;
(void) n;
fprintf (stderr, "bsafe error: strncpy() is not safe, use bmidstr instead.\n");
if (bsafeShouldExit) exit (-1);
return NULL;
}
char * (strncat) (char *dst, const char *src, size_t n) {
(void) dst;
(void) src;
(void) n;
fprintf (stderr, "bsafe error: strncat() is not safe, use bstrcat then btrunc\n\tor cstr2tbstr, btrunc then bstrcat instead.\n");
if (bsafeShouldExit) exit (-1);
return NULL;
}
char * (strtok) (char *s1, const char *s2) {
(void) s1;
(void) s2;
fprintf (stderr, "bsafe error: strtok() is not safe, use bsplit or bsplits instead.\n");
if (bsafeShouldExit) exit (-1);
return NULL;
}
char * (strdup) (const char *s) {
(void) s;
fprintf (stderr, "bsafe error: strdup() is not safe, use bstrcpy.\n");
if (bsafeShouldExit) exit (-1);
return NULL;
}

43
bstrlib/bsafe.h Normal file
View File

@ -0,0 +1,43 @@
/*
* This source file is part of the bstring string library. This code was
* written by Paul Hsieh in 2002-2004, and is covered by the BSD open source
* license. Refer to the accompanying documentation for details on usage and
* license.
*/
/*
* bsafe.h
*
* This is an optional module that can be used to help enforce a safety
* standard based on pervasive usage of bstrlib. This file is not necessarily
* portable, however, it has been tested to work correctly with Intel's C/C++
* compiler, WATCOM C/C++ v11.x and Microsoft Visual C++.
*/
#ifndef BSTRLIB_BSAFE_INCLUDE
#define BSTRLIB_BSAFE_INCLUDE
#ifdef __cplusplus
extern "C" {
#endif
#if !defined (__GNUC__) && (!defined(_MSC_VER) || (_MSC_VER <= 1310))
/* This is caught in the linker, so its not necessary for gcc. */
extern char * (gets) (char * buf);
#endif
extern char * (strncpy) (char *dst, const char *src, size_t n);
extern char * (strncat) (char *dst, const char *src, size_t n);
extern char * (strtok) (char *s1, const char *s2);
extern char * (strdup) (const char *s);
#undef strcpy
#undef strcat
#define strcpy(a,b) bsafe_strcpy(a,b)
#define strcat(a,b) bsafe_strcat(a,b)
#ifdef __cplusplus
}
#endif
#endif

3689
bstrlib/bstest.c Normal file

File diff suppressed because it is too large Load Diff

1161
bstrlib/bstraux.c Normal file

File diff suppressed because it is too large Load Diff

115
bstrlib/bstraux.h Normal file
View File

@ -0,0 +1,115 @@
/*
* This source file is part of the bstring string library. This code was
* written by Paul Hsieh in 2002-2015, and is covered by the BSD open source
* license and the GPL. Refer to the accompanying documentation for details
* on usage and license.
*/
/*
* bstraux.h
*
* This file is not a necessary part of the core bstring library itself, but
* is just an auxilliary module which includes miscellaneous or trivial
* functions.
*/
#ifndef BSTRAUX_INCLUDE
#define BSTRAUX_INCLUDE
#include <time.h>
#include "bstrlib.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Safety mechanisms */
#define bstrDeclare(b) bstring (b) = NULL;
#define bstrFree(b) {if ((b) != NULL && (b)->slen >= 0 && (b)->mlen >= (b)->slen) { bdestroy (b); (b) = NULL; }}
/* Backward compatibilty with previous versions of Bstrlib */
#if !defined(BSTRLIB_REDUCE_NAMESPACE_POLLUTION)
#define bAssign(a,b) ((bassign)((a), (b)))
#define bSubs(b,pos,len,a,c) ((breplace)((b),(pos),(len),(a),(unsigned char)(c)))
#define bStrchr(b,c) ((bstrchr)((b), (c)))
#define bStrchrFast(b,c) ((bstrchr)((b), (c)))
#define bCatCstr(b,s) ((bcatcstr)((b), (s)))
#define bCatBlk(b,s,len) ((bcatblk)((b),(s),(len)))
#define bCatStatic(b,s) bcatStatic(b,s)
#define bTrunc(b,n) ((btrunc)((b), (n)))
#define bReplaceAll(b,find,repl,pos) ((bfindreplace)((b),(find),(repl),(pos)))
#define bUppercase(b) ((btoupper)(b))
#define bLowercase(b) ((btolower)(b))
#define bCaselessCmp(a,b) ((bstricmp)((a), (b)))
#define bCaselessNCmp(a,b,n) ((bstrnicmp)((a), (b), (n)))
#define bBase64Decode(b) (bBase64DecodeEx ((b), NULL))
#define bUuDecode(b) (bUuDecodeEx ((b), NULL))
#endif
/* Unusual functions */
extern struct bStream * bsFromBstr (const_bstring b);
extern bstring bTail (bstring b, int n);
extern bstring bHead (bstring b, int n);
extern int bSetCstrChar (bstring a, int pos, char c);
extern int bSetChar (bstring b, int pos, char c);
extern int bFill (bstring a, char c, int len);
extern int bReplicate (bstring b, int n);
extern int bReverse (bstring b);
extern int bInsertChrs (bstring b, int pos, int len, unsigned char c, unsigned char fill);
extern bstring bStrfTime (const char * fmt, const struct tm * timeptr);
#define bAscTime(t) (bStrfTime ("%c\n", (t)))
#define bCTime(t) ((t) ? bAscTime (localtime (t)) : NULL)
/* Spacing formatting */
extern int bJustifyLeft (bstring b, int space);
extern int bJustifyRight (bstring b, int width, int space);
extern int bJustifyMargin (bstring b, int width, int space);
extern int bJustifyCenter (bstring b, int width, int space);
/* Esoteric standards specific functions */
extern char * bStr2NetStr (const_bstring b);
extern bstring bNetStr2Bstr (const char * buf);
extern bstring bBase64Encode (const_bstring b);
extern bstring bBase64DecodeEx (const_bstring b, int * boolTruncError);
extern struct bStream * bsUuDecode (struct bStream * sInp, int * badlines);
extern bstring bUuDecodeEx (const_bstring src, int * badlines);
extern bstring bUuEncode (const_bstring src);
extern bstring bYEncode (const_bstring src);
extern bstring bYDecode (const_bstring src);
extern int bSGMLEncode (bstring b);
/* Writable stream */
typedef int (* bNwrite) (const void * buf, size_t elsize, size_t nelem, void * parm);
struct bwriteStream * bwsOpen (bNwrite writeFn, void * parm);
int bwsWriteBstr (struct bwriteStream * stream, const_bstring b);
int bwsWriteBlk (struct bwriteStream * stream, void * blk, int len);
int bwsWriteFlush (struct bwriteStream * stream);
int bwsIsEOF (const struct bwriteStream * stream);
int bwsBuffLength (struct bwriteStream * stream, int sz);
void * bwsClose (struct bwriteStream * stream);
/* Security functions */
#define bSecureDestroy(b) { \
bstring bstr__tmp = (b); \
if (bstr__tmp && bstr__tmp->mlen > 0 && bstr__tmp->data) { \
(void) memset (bstr__tmp->data, 0, (size_t) bstr__tmp->mlen); \
bdestroy (bstr__tmp); \
} \
}
#define bSecureWriteProtect(t) { \
if ((t).mlen >= 0) { \
if ((t).mlen > (t).slen)) { \
(void) memset ((t).data + (t).slen, 0, (size_t) (t).mlen - (t).slen); \
} \
(t).mlen = -1; \
} \
}
extern bstring bSecureInput (int maxlen, int termchar,
bNgetc vgetchar, void * vgcCtx);
#ifdef __cplusplus
}
#endif
#endif

3153
bstrlib/bstrlib.c Normal file

File diff suppressed because it is too large Load Diff

316
bstrlib/bstrlib.h Normal file
View File

@ -0,0 +1,316 @@
/*
* This source file is part of the bstring string library. This code was
* written by Paul Hsieh in 2002-2015, and is covered by the BSD open source
* license and the GPL. Refer to the accompanying documentation for details
* on usage and license.
*/
/*
* bstrlib.h
*
* This file is the interface for the core bstring functions.
*/
#ifndef BSTRLIB_INCLUDE
#define BSTRLIB_INCLUDE
#ifdef __cplusplus
extern "C" {
#endif
#include <stdarg.h>
#include <string.h>
#include <limits.h>
#include <ctype.h>
#if !defined (BSTRLIB_VSNP_OK) && !defined (BSTRLIB_NOVSNP)
# if defined (__TURBOC__) && !defined (__BORLANDC__)
# define BSTRLIB_NOVSNP
# endif
#endif
#define BSTR_ERR (-1)
#define BSTR_OK (0)
#define BSTR_BS_BUFF_LENGTH_GET (0)
typedef struct tagbstring * bstring;
typedef const struct tagbstring * const_bstring;
/* Copy functions */
#define cstr2bstr bfromcstr
extern bstring bfromcstr (const char * str);
extern bstring bfromcstralloc (int mlen, const char * str);
extern bstring bfromcstrrangealloc (int minl, int maxl, const char* str);
extern bstring blk2bstr (const void * blk, int len);
extern char * bstr2cstr (const_bstring s, char z);
extern int bcstrfree (char * s);
extern bstring bstrcpy (const_bstring b1);
extern int bassign (bstring a, const_bstring b);
extern int bassignmidstr (bstring a, const_bstring b, int left, int len);
extern int bassigncstr (bstring a, const char * str);
extern int bassignblk (bstring a, const void * s, int len);
/* Destroy function */
extern int bdestroy (bstring b);
/* Space allocation hinting functions */
extern int balloc (bstring s, int len);
extern int ballocmin (bstring b, int len);
/* Substring extraction */
extern bstring bmidstr (const_bstring b, int left, int len);
/* Various standard manipulations */
extern int bconcat (bstring b0, const_bstring b1);
extern int bconchar (bstring b0, char c);
extern int bcatcstr (bstring b, const char * s);
extern int bcatblk (bstring b, const void * s, int len);
extern int binsert (bstring s1, int pos, const_bstring s2, unsigned char fill);
extern int binsertblk (bstring s1, int pos, const void * s2, int len, unsigned char fill);
extern int binsertch (bstring s1, int pos, int len, unsigned char fill);
extern int breplace (bstring b1, int pos, int len, const_bstring b2, unsigned char fill);
extern int bdelete (bstring s1, int pos, int len);
extern int bsetstr (bstring b0, int pos, const_bstring b1, unsigned char fill);
extern int btrunc (bstring b, int n);
/* Scan/search functions */
extern int bstricmp (const_bstring b0, const_bstring b1);
extern int bstrnicmp (const_bstring b0, const_bstring b1, int n);
extern int biseqcaseless (const_bstring b0, const_bstring b1);
extern int biseqcaselessblk (const_bstring b, const void * blk, int len);
extern int bisstemeqcaselessblk (const_bstring b0, const void * blk, int len);
extern int biseq (const_bstring b0, const_bstring b1);
extern int biseqblk (const_bstring b, const void * blk, int len);
extern int bisstemeqblk (const_bstring b0, const void * blk, int len);
extern int biseqcstr (const_bstring b, const char * s);
extern int biseqcstrcaseless (const_bstring b, const char * s);
extern int bstrcmp (const_bstring b0, const_bstring b1);
extern int bstrncmp (const_bstring b0, const_bstring b1, int n);
extern int binstr (const_bstring s1, int pos, const_bstring s2);
extern int binstrr (const_bstring s1, int pos, const_bstring s2);
extern int binstrcaseless (const_bstring s1, int pos, const_bstring s2);
extern int binstrrcaseless (const_bstring s1, int pos, const_bstring s2);
extern int bstrchrp (const_bstring b, int c, int pos);
extern int bstrrchrp (const_bstring b, int c, int pos);
#define bstrchr(b,c) bstrchrp ((b), (c), 0)
#define bstrrchr(b,c) bstrrchrp ((b), (c), blength(b)-1)
extern int binchr (const_bstring b0, int pos, const_bstring b1);
extern int binchrr (const_bstring b0, int pos, const_bstring b1);
extern int bninchr (const_bstring b0, int pos, const_bstring b1);
extern int bninchrr (const_bstring b0, int pos, const_bstring b1);
extern int bfindreplace (bstring b, const_bstring find, const_bstring repl, int pos);
extern int bfindreplacecaseless (bstring b, const_bstring find, const_bstring repl, int pos);
/* List of string container functions */
struct bstrList {
int qty, mlen;
bstring * entry;
};
extern struct bstrList * bstrListCreate (void);
extern int bstrListDestroy (struct bstrList * sl);
extern int bstrListAlloc (struct bstrList * sl, int msz);
extern int bstrListAllocMin (struct bstrList * sl, int msz);
/* String split and join functions */
extern struct bstrList * bsplit (const_bstring str, unsigned char splitChar);
extern struct bstrList * bsplits (const_bstring str, const_bstring splitStr);
extern struct bstrList * bsplitstr (const_bstring str, const_bstring splitStr);
extern bstring bjoin (const struct bstrList * bl, const_bstring sep);
extern bstring bjoinblk (const struct bstrList * bl, const void * s, int len);
extern int bsplitcb (const_bstring str, unsigned char splitChar, int pos,
int (* cb) (void * parm, int ofs, int len), void * parm);
extern int bsplitscb (const_bstring str, const_bstring splitStr, int pos,
int (* cb) (void * parm, int ofs, int len), void * parm);
extern int bsplitstrcb (const_bstring str, const_bstring splitStr, int pos,
int (* cb) (void * parm, int ofs, int len), void * parm);
/* Miscellaneous functions */
extern int bpattern (bstring b, int len);
extern int btoupper (bstring b);
extern int btolower (bstring b);
extern int bltrimws (bstring b);
extern int brtrimws (bstring b);
extern int btrimws (bstring b);
#if !defined (BSTRLIB_NOVSNP)
extern bstring bformat (const char * fmt, ...);
extern int bformata (bstring b, const char * fmt, ...);
extern int bassignformat (bstring b, const char * fmt, ...);
extern int bvcformata (bstring b, int count, const char * fmt, va_list arglist);
#define bvformata(ret, b, fmt, lastarg) { \
bstring bstrtmp_b = (b); \
const char * bstrtmp_fmt = (fmt); \
int bstrtmp_r = BSTR_ERR, bstrtmp_sz = 16; \
for (;;) { \
va_list bstrtmp_arglist; \
va_start (bstrtmp_arglist, lastarg); \
bstrtmp_r = bvcformata (bstrtmp_b, bstrtmp_sz, bstrtmp_fmt, bstrtmp_arglist); \
va_end (bstrtmp_arglist); \
if (bstrtmp_r >= 0) { /* Everything went ok */ \
bstrtmp_r = BSTR_OK; \
break; \
} else if (-bstrtmp_r <= bstrtmp_sz) { /* A real error? */ \
bstrtmp_r = BSTR_ERR; \
break; \
} \
bstrtmp_sz = -bstrtmp_r; /* Doubled or target size */ \
} \
ret = bstrtmp_r; \
}
#endif
typedef int (*bNgetc) (void *parm);
typedef size_t (* bNread) (void *buff, size_t elsize, size_t nelem, void *parm);
/* Input functions */
extern bstring bgets (bNgetc getcPtr, void * parm, char terminator);
extern bstring bread (bNread readPtr, void * parm);
extern int bgetsa (bstring b, bNgetc getcPtr, void * parm, char terminator);
extern int bassigngets (bstring b, bNgetc getcPtr, void * parm, char terminator);
extern int breada (bstring b, bNread readPtr, void * parm);
/* Stream functions */
extern struct bStream * bsopen (bNread readPtr, void * parm);
extern void * bsclose (struct bStream * s);
extern int bsbufflength (struct bStream * s, int sz);
extern int bsreadln (bstring b, struct bStream * s, char terminator);
extern int bsreadlns (bstring r, struct bStream * s, const_bstring term);
extern int bsread (bstring b, struct bStream * s, int n);
extern int bsreadlna (bstring b, struct bStream * s, char terminator);
extern int bsreadlnsa (bstring r, struct bStream * s, const_bstring term);
extern int bsreada (bstring b, struct bStream * s, int n);
extern int bsunread (struct bStream * s, const_bstring b);
extern int bspeek (bstring r, const struct bStream * s);
extern int bssplitscb (struct bStream * s, const_bstring splitStr,
int (* cb) (void * parm, int ofs, const_bstring entry), void * parm);
extern int bssplitstrcb (struct bStream * s, const_bstring splitStr,
int (* cb) (void * parm, int ofs, const_bstring entry), void * parm);
extern int bseof (const struct bStream * s);
struct tagbstring {
int mlen;
int slen;
unsigned char * data;
};
/* Accessor macros */
#define blengthe(b, e) (((b) == (void *)0 || (b)->slen < 0) ? (int)(e) : ((b)->slen))
#define blength(b) (blengthe ((b), 0))
#define bdataofse(b, o, e) (((b) == (void *)0 || (b)->data == (void*)0) ? (char *)(e) : ((char *)(b)->data) + (o))
#define bdataofs(b, o) (bdataofse ((b), (o), (void *)0))
#define bdatae(b, e) (bdataofse (b, 0, e))
#define bdata(b) (bdataofs (b, 0))
#define bchare(b, p, e) ((((unsigned)(p)) < (unsigned)blength(b)) ? ((b)->data[(p)]) : (e))
#define bchar(b, p) bchare ((b), (p), '\0')
/* Static constant string initialization macro */
#define bsStaticMlen(q,m) {(m), (int) sizeof(q)-1, (unsigned char *) ("" q "")}
#if defined(_MSC_VER)
# define bsStatic(q) bsStaticMlen(q,-32)
#endif
#ifndef bsStatic
# define bsStatic(q) bsStaticMlen(q,-__LINE__)
#endif
/* Static constant block parameter pair */
#define bsStaticBlkParms(q) ((void *)("" q "")), ((int) sizeof(q)-1)
#define bcatStatic(b,s) ((bcatblk)((b), bsStaticBlkParms(s)))
#define bfromStatic(s) ((blk2bstr)(bsStaticBlkParms(s)))
#define bassignStatic(b,s) ((bassignblk)((b), bsStaticBlkParms(s)))
#define binsertStatic(b,p,s,f) ((binsertblk)((b), (p), bsStaticBlkParms(s), (f)))
#define bjoinStatic(b,s) ((bjoinblk)((b), bsStaticBlkParms(s)))
#define biseqStatic(b,s) ((biseqblk)((b), bsStaticBlkParms(s)))
#define bisstemeqStatic(b,s) ((bisstemeqblk)((b), bsStaticBlkParms(s)))
#define biseqcaselessStatic(b,s) ((biseqcaselessblk)((b), bsStaticBlkParms(s)))
#define bisstemeqcaselessStatic(b,s) ((bisstemeqcaselessblk)((b), bsStaticBlkParms(s)))
/* Reference building macros */
#define cstr2tbstr btfromcstr
#define btfromcstr(t,s) { \
(t).data = (unsigned char *) (s); \
(t).slen = ((t).data) ? ((int) (strlen) ((char *)(t).data)) : 0; \
(t).mlen = -1; \
}
#define blk2tbstr(t,s,l) { \
(t).data = (unsigned char *) (s); \
(t).slen = l; \
(t).mlen = -1; \
}
#define btfromblk(t,s,l) blk2tbstr(t,s,l)
#define bmid2tbstr(t,b,p,l) { \
const_bstring bstrtmp_s = (b); \
if (bstrtmp_s && bstrtmp_s->data && bstrtmp_s->slen >= 0) { \
int bstrtmp_left = (p); \
int bstrtmp_len = (l); \
if (bstrtmp_left < 0) { \
bstrtmp_len += bstrtmp_left; \
bstrtmp_left = 0; \
} \
if (bstrtmp_len > bstrtmp_s->slen - bstrtmp_left) \
bstrtmp_len = bstrtmp_s->slen - bstrtmp_left; \
if (bstrtmp_len <= 0) { \
(t).data = (unsigned char *)""; \
(t).slen = 0; \
} else { \
(t).data = bstrtmp_s->data + bstrtmp_left; \
(t).slen = bstrtmp_len; \
} \
} else { \
(t).data = (unsigned char *)""; \
(t).slen = 0; \
} \
(t).mlen = -__LINE__; \
}
#define btfromblkltrimws(t,s,l) { \
int bstrtmp_idx = 0, bstrtmp_len = (l); \
unsigned char * bstrtmp_s = (s); \
if (bstrtmp_s && bstrtmp_len >= 0) { \
for (; bstrtmp_idx < bstrtmp_len; bstrtmp_idx++) { \
if (!isspace (bstrtmp_s[bstrtmp_idx])) break; \
} \
} \
(t).data = bstrtmp_s + bstrtmp_idx; \
(t).slen = bstrtmp_len - bstrtmp_idx; \
(t).mlen = -__LINE__; \
}
#define btfromblkrtrimws(t,s,l) { \
int bstrtmp_len = (l) - 1; \
unsigned char * bstrtmp_s = (s); \
if (bstrtmp_s && bstrtmp_len >= 0) { \
for (; bstrtmp_len >= 0; bstrtmp_len--) { \
if (!isspace (bstrtmp_s[bstrtmp_len])) break; \
} \
} \
(t).data = bstrtmp_s; \
(t).slen = bstrtmp_len + 1; \
(t).mlen = -__LINE__; \
}
#define btfromblktrimws(t,s,l) { \
int bstrtmp_idx = 0, bstrtmp_len = (l) - 1; \
unsigned char * bstrtmp_s = (s); \
if (bstrtmp_s && bstrtmp_len >= 0) { \
for (; bstrtmp_idx <= bstrtmp_len; bstrtmp_idx++) { \
if (!isspace (bstrtmp_s[bstrtmp_idx])) break; \
} \
for (; bstrtmp_len >= bstrtmp_idx; bstrtmp_len--) { \
if (!isspace (bstrtmp_s[bstrtmp_len])) break; \
} \
} \
(t).data = bstrtmp_s + bstrtmp_idx; \
(t).slen = bstrtmp_len + 1 - bstrtmp_idx; \
(t).mlen = -__LINE__; \
}
/* Write protection macros */
#define bwriteprotect(t) { if ((t).mlen >= 0) (t).mlen = -1; }
#define bwriteallow(t) { if ((t).mlen == -1) (t).mlen = (t).slen + ((t).slen == 0); }
#define biswriteprotected(t) ((t).mlen <= 0)
#ifdef __cplusplus
}
#endif
#endif

3512
bstrlib/bstrlib.txt Normal file

File diff suppressed because it is too large Load Diff

1721
bstrlib/bstrwrap.cpp Normal file

File diff suppressed because it is too large Load Diff

449
bstrlib/bstrwrap.h Normal file
View File

@ -0,0 +1,449 @@
/*
* This source file is part of the bstring string library. This code was
* written by Paul Hsieh in 2002-2015, and is covered by the BSD open source
* license and the GPL. Refer to the accompanying documentation for details
* on usage and license.
*/
/*
* bstrwrap.h
*
* This file is the C++ wrapper for the bstring functions.
*/
#ifndef BSTRWRAP_INCLUDE
#define BSTRWRAP_INCLUDE
/////////////////// Configuration defines //////////////////////////////
// WATCOM C/C++ has broken STL and std::iostream support. If you have
// ported over STLport, then you can #define BSTRLIB_CAN_USE_STL to use
// the CBStringList class.
#if defined(__WATCOMC__)
# if !defined (BSTRLIB_CAN_USE_STL) && !defined (BSTRLIB_CANNOT_USE_STL)
# define BSTRLIB_CANNOT_USE_STL
# endif
# if !defined (BSTRLIB_CAN_USE_IOSTREAM) && !defined (BSTRLIB_CANNOT_USE_IOSTREAM)
# define BSTRLIB_CANNOT_USE_IOSTREAM
# endif
#endif
// By default it assumed that STL has been installed and works for your
// compiler. If this is not the case, then #define BSTRLIB_CANNOT_USE_STL
#if !defined (BSTRLIB_CANNOT_USE_STL) && !defined (BSTRLIB_CAN_USE_STL)
#define BSTRLIB_CAN_USE_STL
#endif
// By default it assumed that std::iostream works well with your compiler.
// If this is not the case, then #define BSTRLIB_CAN_USE_IOSTREAM
#if !defined (BSTRLIB_CANNOT_USE_IOSTREAM) && !defined (BSTRLIB_CAN_USE_IOSTREAM)
#define BSTRLIB_CAN_USE_IOSTREAM
#endif
// By default it is assumed that your compiler can deal with and has enabled
// exception handlling. If this is not the case then you will need to
// #define BSTRLIB_DOESNT_THROW_EXCEPTIONS
#if !defined (BSTRLIB_THROWS_EXCEPTIONS) && !defined (BSTRLIB_DOESNT_THROW_EXCEPTIONS)
#define BSTRLIB_THROWS_EXCEPTIONS
#endif
////////////////////////////////////////////////////////////////////////
#include <stdlib.h>
#include "bstrlib.h"
#include "../common/ubytearray.h"
#ifdef __cplusplus
#if defined(BSTRLIB_CAN_USE_STL)
#if defined(__WATCOMC__)
#pragma warning 604 10
#pragma warning 595 10
#pragma warning 594 10
#pragma warning 549 10
#endif
#include <vector>
#include <string>
#if defined(__WATCOMC__)
#pragma warning 604 9
#pragma warning 595 9
#pragma warning 594 9
#endif
#endif
namespace Bstrlib {
#ifdef BSTRLIB_THROWS_EXCEPTIONS
#if defined(BSTRLIB_CAN_USE_STL)
struct CBStringException : public std::exception {
private:
std::string msg;
public:
CBStringException (const std::string inmsg) : msg(inmsg) {}
virtual ~CBStringException () throw () {}
virtual const char *what () const throw () { return msg.c_str(); }
};
#else
struct CBStringException {
private:
char * msg;
int needToFree;
public:
CBStringException (const char * inmsg) : needToFree(0) {
if (inmsg) {
msg = (char *) malloc (1 + strlen (inmsg));
if (NULL == msg) msg = "Out of memory";
else {
strcpy (msg, inmsg);
needToFree = 1;
}
} else {
msg = "NULL exception message";
}
}
virtual ~CBStringException () throw () {
if (needToFree) {
free (msg);
needToFree = 0;
msg = NULL;
}
}
virtual const char *what () const throw () { return msg; }
};
#endif
#define bstringThrow(er) {\
CBStringException bstr__cppwrapper_exception ("CBString::" er "");\
throw bstr__cppwrapper_exception;\
}
#else
#define bstringThrow(er) {}
#endif
struct CBString;
#ifdef _MSC_VER
#pragma warning(disable:4512)
#endif
class CBCharWriteProtected {
friend struct CBString;
private:
const struct tagbstring& s;
unsigned int idx;
CBCharWriteProtected (const struct tagbstring& c, int i) : s(c), idx((unsigned int)i) {
if (idx >= (unsigned) s.slen) {
bstringThrow ("character index out of bounds");
}
}
public:
inline char operator = (char c) {
if (s.mlen <= 0) {
bstringThrow ("Write protection error");
} else {
#ifndef BSTRLIB_THROWS_EXCEPTIONS
if (idx >= (unsigned) s.slen) return '\0';
#endif
s.data[idx] = (unsigned char) c;
}
return (char) s.data[idx];
}
inline unsigned char operator = (unsigned char c) {
if (s.mlen <= 0) {
bstringThrow ("Write protection error");
} else {
#ifndef BSTRLIB_THROWS_EXCEPTIONS
if (idx >= (unsigned) s.slen) return '\0';
#endif
s.data[idx] = c;
}
return s.data[idx];
}
inline operator unsigned char () const {
#ifndef BSTRLIB_THROWS_EXCEPTIONS
if (idx >= (unsigned) s.slen) return (unsigned char) '\0';
#endif
return s.data[idx];
}
};
struct CBString : public tagbstring {
// Constructors
CBString ();
CBString (char c);
CBString (unsigned char c);
CBString (const char *s);
CBString (int len, const char *s);
CBString (const CBString& b);
CBString (const tagbstring& x);
CBString (char c, int len);
CBString (const void * blk, int len);
#if defined(BSTRLIB_CAN_USE_STL)
CBString (const struct CBStringList& l);
CBString (const struct CBStringList& l, const CBString& sep);
CBString (const struct CBStringList& l, char sep);
CBString (const struct CBStringList& l, unsigned char sep);
#endif
// Destructor
#if !defined(BSTRLIB_DONT_USE_VIRTUAL_DESTRUCTOR)
virtual
#endif
~CBString ();
// = operator
const CBString& operator = (char c);
const CBString& operator = (unsigned char c);
const CBString& operator = (const char *s);
const CBString& operator = (const CBString& b);
const CBString& operator = (const tagbstring& x);
// += operator
const CBString& operator += (char c);
const CBString& operator += (unsigned char c);
const CBString& operator += (const char *s);
const CBString& operator += (const CBString& b);
const CBString& operator += (const tagbstring& x);
// *= operator
inline const CBString& operator *= (int count) {
this->repeat (count);
return *this;
}
// + operator
const CBString operator + (char c) const;
const CBString operator + (unsigned char c) const;
const CBString operator + (const unsigned char *s) const;
const CBString operator + (const char *s) const;
const CBString operator + (const CBString& b) const;
const CBString operator + (const tagbstring& x) const;
// * operator
inline const CBString operator * (int count) const {
CBString retval (*this);
retval.repeat (count);
return retval;
}
// Comparison operators
bool operator == (const CBString& b) const;
bool operator == (const char * s) const;
bool operator == (const unsigned char * s) const;
bool operator != (const CBString& b) const;
bool operator != (const char * s) const;
bool operator != (const unsigned char * s) const;
bool operator < (const CBString& b) const;
bool operator < (const char * s) const;
bool operator < (const unsigned char * s) const;
bool operator <= (const CBString& b) const;
bool operator <= (const char * s) const;
bool operator <= (const unsigned char * s) const;
bool operator > (const CBString& b) const;
bool operator > (const char * s) const;
bool operator > (const unsigned char * s) const;
bool operator >= (const CBString& b) const;
bool operator >= (const char * s) const;
bool operator >= (const unsigned char * s) const;
// Casts
inline operator const char* () const { return (const char *)data; }
inline operator const unsigned char* () const { return (const unsigned char *)data; }
operator double () const;
operator float () const;
operator int () const;
operator unsigned int () const;
// Accessors
inline int length () const {return slen;}
inline unsigned char character (int i) const {
if (((unsigned) i) >= (unsigned) slen) {
#ifdef BSTRLIB_THROWS_EXCEPTIONS
bstringThrow ("character idx out of bounds");
#else
return '\0';
#endif
}
return data[i];
}
inline unsigned char operator [] (int i) const { return character(i); }
inline CBCharWriteProtected character (int i) {
return CBCharWriteProtected (*this, i);
}
inline CBCharWriteProtected operator [] (int i) { return character(i); }
// Space allocation hint method.
void alloc (int length);
// Search methods.
int caselessEqual (const CBString& b) const;
int caselessCmp (const CBString& b) const;
int find (const CBString& b, int pos = 0) const;
int find (const char * b, int pos = 0) const;
int caselessfind (const CBString& b, int pos = 0) const;
int caselessfind (const char * b, int pos = 0) const;
int find (char c, int pos = 0) const;
int reversefind (const CBString& b, int pos) const;
int reversefind (const char * b, int pos) const;
int caselessreversefind (const CBString& b, int pos) const;
int caselessreversefind (const char * b, int pos) const;
int reversefind (char c, int pos) const;
int findchr (const CBString& b, int pos = 0) const;
int findchr (const char * s, int pos = 0) const;
int reversefindchr (const CBString& b, int pos) const;
int reversefindchr (const char * s, int pos) const;
int nfindchr (const CBString& b, int pos = 0) const;
int nfindchr (const char * b, int pos = 0) const;
int nreversefindchr (const CBString& b, int pos) const;
int nreversefindchr (const char * b, int pos) const;
// Search and substitute methods.
void findreplace (const CBString& find, const CBString& repl, int pos = 0);
void findreplace (const CBString& find, const char * repl, int pos = 0);
void findreplace (const char * find, const CBString& repl, int pos = 0);
void findreplace (const char * find, const char * repl, int pos = 0);
void findreplacecaseless (const CBString& find, const CBString& repl, int pos = 0);
void findreplacecaseless (const CBString& find, const char * repl, int pos = 0);
void findreplacecaseless (const char * find, const CBString& repl, int pos = 0);
void findreplacecaseless (const char * find, const char * repl, int pos = 0);
// Extraction method.
CBString midstr (int left, int len) const;
// Standard manipulation methods.
void setsubstr (int pos, const CBString& b, unsigned char fill = ' ');
void setsubstr (int pos, const char * b, unsigned char fill = ' ');
void insert (int pos, const CBString& b, unsigned char fill = ' ');
void insert (int pos, const char * b, unsigned char fill = ' ');
void insertchrs (int pos, int len, unsigned char fill = ' ');
void replace (int pos, int len, const CBString& b, unsigned char fill = ' ');
void replace (int pos, int len, const char * s, unsigned char fill = ' ');
void remove (int pos, int len);
void trunc (int len);
// Miscellaneous methods.
void format (const char * fmt, ...);
void formata (const char * fmt, ...);
void fill (int length, unsigned char fill = ' ');
void repeat (int count);
void ltrim (const CBString& b = CBString (bsStaticBlkParms (" \t\v\f\r\n")));
void rtrim (const CBString& b = CBString (bsStaticBlkParms (" \t\v\f\r\n")));
inline void trim (const CBString& b = CBString (bsStaticBlkParms (" \t\v\f\r\n"))) {
rtrim (b);
ltrim (b);
}
void toupper ();
void tolower ();
// Write protection methods.
void writeprotect ();
void writeallow ();
inline bool iswriteprotected () const { return mlen <= 0; }
// Join methods.
#if defined(BSTRLIB_CAN_USE_STL)
void join (const struct CBStringList& l);
void join (const struct CBStringList& l, const CBString& sep);
void join (const struct CBStringList& l, char sep);
void join (const struct CBStringList& l, unsigned char sep);
#endif
// CBStream methods
int gets (bNgetc getcPtr, void * parm, char terminator = '\n');
int read (bNread readPtr, void * parm);
// QString compatibility methods
CBString toLocal8Bit() const { return *this; }
bool isEmpty() const { return slen == 0; }
void clear() { *this = ""; }
CBString left(int len) const { return midstr(0, len); }
CBString mid(int pos, int len) const { return midstr(pos, len); }
static CBString fromUtf16(const unsigned short* str) { // Naive implementation assuming that only ASCII part of UCS2 is used
CBString msg; while (*str) { msg += *(char*)str; str++; } return msg;
}
CBString leftJustified(int length) { if (length > slen) { return *this + CBString(' ', length - slen); } return *this; }
};
extern const CBString operator + (const char *a, const CBString& b);
extern const CBString operator + (const unsigned char *a, const CBString& b);
extern const CBString operator + (char c, const CBString& b);
extern const CBString operator + (unsigned char c, const CBString& b);
extern const CBString operator + (const tagbstring& x, const CBString& b);
inline const CBString operator * (int count, const CBString& b) {
CBString retval (b);
retval.repeat (count);
return retval;
}
#if defined(BSTRLIB_CAN_USE_IOSTREAM)
extern std::ostream& operator << (std::ostream& sout, CBString b);
extern std::istream& operator >> (std::istream& sin, CBString& b);
extern std::istream& getline (std::istream& sin, CBString& b, char terminator='\n');
#endif
struct CBStream {
friend struct CBStringList;
private:
struct bStream * m_s;
public:
CBStream (bNread readPtr, void * parm);
~CBStream ();
int buffLengthSet (int sz);
int buffLengthGet ();
int eof () const;
CBString readLine (char terminator);
CBString readLine (const CBString& terminator);
void readLine (CBString& s, char terminator);
void readLine (CBString& s, const CBString& terminator);
void readLineAppend (CBString& s, char terminator);
void readLineAppend (CBString& s, const CBString& terminator);
CBString read ();
CBString& operator >> (CBString& s);
CBString read (int n);
void read (CBString& s);
void read (CBString& s, int n);
void readAppend (CBString& s);
void readAppend (CBString& s, int n);
void unread (const CBString& s);
inline CBStream& operator << (const CBString& s) {
this->unread (s);
return *this;
}
CBString peek () const;
void peek (CBString& s) const;
void peekAppend (CBString& s) const;
};
#if defined(BSTRLIB_CAN_USE_STL)
struct CBStringList : public std::vector<CBString> {
// split a string into a vector of strings.
void split (const CBString& b, unsigned char splitChar);
void split (const CBString& b, const CBString& s);
void splitstr (const CBString& b, const CBString& s);
void split (const CBStream& b, unsigned char splitChar);
void split (const CBStream& b, const CBString& s);
void splitstr (const CBStream& b, const CBString& s);
};
#endif
} // namespace Bstrlib
#if !defined (BSTRLIB_DONT_ASSUME_NAMESPACE)
using namespace Bstrlib;
#endif
#endif
#endif

274
bstrlib/buniutil.c Normal file
View File

@ -0,0 +1,274 @@
/*
* This source file is part of the bstring string library. This code was
* written by Paul Hsieh in 2002-2015, and is covered by the BSD open source
* license and the GPL. Refer to the accompanying documentation for details
* on usage and license.
*/
/*
* buniutil.c
*
* This file is not necessarily part of the core bstring library itself, but
* is just an implementation of basic utf8 processing for bstrlib. Note that
* this module is dependent upon bstrlib.c and utf8util.c
*/
#include "bstrlib.h"
#include "buniutil.h"
#define UNICODE__CODE_POINT__REPLACEMENT_CHARACTER (0xFFFDL)
/* int buIsUTF8Content (const_bstring bu)
*
* Scan string and return 1 if its entire contents is entirely UTF8 code
* points. Otherwise return 0.
*/
int buIsUTF8Content (const_bstring bu) {
struct utf8Iterator iter;
if (NULL == bdata (bu)) return 0;
for (utf8IteratorInit (&iter, bu->data, bu->slen);
iter.next < iter.slen;) {
if (0 >= utf8IteratorGetNextCodePoint (&iter, -1)) return 0;
}
return 1;
}
/* int buGetBlkUTF16 (cpUcs2* ucs2, int len, cpUcs4 errCh, const_bstring bu,
* int pos)
*
* Convert a string of UTF8 codepoints (bu) skipping the first pos, into a
* sequence of UTF16 encoded code points. Returns the number of UCS2 16-bit
* words written to the output. No more than len words are written to the
* target array ucs2. If any code point in bu is unparsable, it will be
* translated to errCh.
*/
int buGetBlkUTF16 (/* @out */ cpUcs2* ucs2, int len, cpUcs4 errCh, const_bstring bu, int pos) {
struct tagbstring t;
struct utf8Iterator iter;
cpUcs4 ucs4;
int i, j;
if (!isLegalUnicodeCodePoint (errCh)) errCh = UNICODE__CODE_POINT__REPLACEMENT_CHARACTER;
if (NULL == ucs2 || 0 >= len || NULL == bdata (bu) || 0 > pos) return BSTR_ERR;
for (j=0, i=0; j < bu->slen; j++) {
if (0x80 != (0xC0 & bu->data[j])) {
if (i >= pos) break;
i++;
}
}
t.mlen = -1;
t.data = bu->data + j;
t.slen = bu->slen - j;
utf8IteratorInit (&iter, t.data, t.slen);
ucs4 = BSTR_ERR;
for (i=0; 0 < len && iter.next < iter.slen &&
0 <= (ucs4 = utf8IteratorGetNextCodePoint (&iter, errCh)); i++) {
if (ucs4 < 0x10000) {
*ucs2++ = (cpUcs2) ucs4;
len--;
} else {
if (len < 2) {
*ucs2++ = UNICODE__CODE_POINT__REPLACEMENT_CHARACTER;
len--;
} else {
long y = ucs4 - 0x10000;
ucs2[0] = (cpUcs2) (0xD800 | (y >> 10));
ucs2[1] = (cpUcs2) (0xDC00 | (y & 0x03FF));
len -= 2;
ucs2 += 2;
i++;
}
}
}
while (0 < len) {
*ucs2++ = 0;
len--;
}
utf8IteratorUninit (&iter);
if (0 > ucs4) return BSTR_ERR;
return i;
}
/*
Unicode UTF-8
------- -----
U-00000000 - U-0000007F: 0xxxxxxx
U-00000080 - U-000007FF: 110xxxxx 10xxxxxx
U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
UTF-32: U-000000 - U-10FFFF
*/
/* int buAppendBlkUcs4 (bstring b, const cpUcs4* bu, int len, cpUcs4 errCh)
*
* Convert an array of UCS4 code points (bu) to UTF8 codepoints b. Any
* invalid code point is replaced by errCh. If errCh is itself not a
* valid code point, then this translation will halt upon the first error
* and return BSTR_ERR. Otherwise BSTR_OK is returned.
*/
int buAppendBlkUcs4 (bstring b, const cpUcs4* bu, int len, cpUcs4 errCh) {
int i, oldSlen;
if (NULL == bu || NULL == b || 0 > len || 0 > (oldSlen = blengthe (b, -1))) return BSTR_ERR;
if (!isLegalUnicodeCodePoint (errCh)) errCh = ~0;
for (i=0; i < len; i++) {
unsigned char c[6];
cpUcs4 v = bu[i];
if (!isLegalUnicodeCodePoint (v)) {
if (~0 == errCh) {
b->slen = oldSlen;
return BSTR_ERR;
}
v = errCh;
}
if (v < 0x80) {
if (BSTR_OK != bconchar (b, (char) v)) {
b->slen = oldSlen;
return BSTR_ERR;
}
} else if (v < 0x800) {
c[0] = (unsigned char) ( (v >> 6) + 0xc0);
c[1] = (unsigned char) (( v & 0x3f) + 0x80);
if (BSTR_OK != bcatblk (b, c, 2)) {
b->slen = oldSlen;
return BSTR_ERR;
}
} else if (v < 0x10000) {
c[0] = (unsigned char) ( (v >> 12) + 0xe0);
c[1] = (unsigned char) (((v >> 6) & 0x3f) + 0x80);
c[2] = (unsigned char) (( v & 0x3f) + 0x80);
if (BSTR_OK != bcatblk (b, c, 3)) {
b->slen = oldSlen;
return BSTR_ERR;
}
} else
#if 0
if (v < 0x200000)
#endif
{
c[0] = (unsigned char) ( (v >> 18) + 0xf0);
c[1] = (unsigned char) (((v >> 12) & 0x3f) + 0x80);
c[2] = (unsigned char) (((v >> 6) & 0x3f) + 0x80);
c[3] = (unsigned char) (( v & 0x3f) + 0x80);
if (BSTR_OK != bcatblk (b, c, 4)) {
b->slen = oldSlen;
return BSTR_ERR;
}
}
#if 0
else if (v < 0x4000000) {
c[0] = (unsigned char) ( (v >> 24) + 0xf8);
c[1] = (unsigned char) (((v >> 18) & 0x3f) + 0x80);
c[2] = (unsigned char) (((v >> 12) & 0x3f) + 0x80);
c[3] = (unsigned char) (((v >> 6) & 0x3f) + 0x80);
c[4] = (unsigned char) (( v & 0x3f) + 0x80);
if (BSTR_OK != bcatblk (b, c, 5)) {
b->slen = oldSlen;
return BSTR_ERR;
}
} else {
c[0] = (unsigned char) ( (v >> 30) + 0xfc);
c[1] = (unsigned char) (((v >> 24) & 0x3f) + 0x80);
c[2] = (unsigned char) (((v >> 18) & 0x3f) + 0x80);
c[3] = (unsigned char) (((v >> 12) & 0x3f) + 0x80);
c[4] = (unsigned char) (((v >> 6) & 0x3f) + 0x80);
c[5] = (unsigned char) (( v & 0x3f) + 0x80);
if (BSTR_OK != bcatblk (b, c, 6)) {
b->slen = oldSlen;
return BSTR_ERR;
}
}
#endif
}
return BSTR_OK;
}
#define endSwap(cs,mode) ((mode) ? ((((cs) & 0xFF) << 8) | (((cs) >> 8) & 0xFF)) : (cs))
#define TEMP_UCS4_BUFFER_SIZE (64)
/* int buAppendBlkUTF16 (bstring bu, const cpUcs2* utf16, int len,
* cpUcs2* bom, cpUcs4 errCh)
*
* Append an array of UCS2 code points (utf16) to UTF8 codepoints (bu). Any
* invalid code point is replaced by errCh. If errCh is itself not a
* valid code point, then this translation will halt upon the first error
* and return BSTR_ERR. Otherwise BSTR_OK is returned. If a byte order mark
* has been previously read, it may be passed in as bom, otherwise if *bom is
* set to 0, it will be filled in with the BOM as read from the first
* character if it is a BOM.
*/
int buAppendBlkUTF16 (bstring bu, const cpUcs2* utf16, int len, cpUcs2* bom, cpUcs4 errCh) {
cpUcs4 buff[TEMP_UCS4_BUFFER_SIZE];
int cc, i, sm, oldSlen;
if (NULL == bdata(bu) || NULL == utf16 || len < 0) return BSTR_ERR;
if (!isLegalUnicodeCodePoint (errCh)) errCh = ~0;
if (len == 0) return BSTR_OK;
oldSlen = bu->slen;
i = 0;
/* Check for BOM character and select endianess. Also remove the
BOM from the stream, since there is no need for it in a UTF-8 encoding. */
if (bom && (cpUcs2) 0xFFFE == *bom) {
sm = 8;
} else if (bom && (cpUcs2) 0xFEFF == *bom) {
sm = 0;
} else if (utf16[i] == (cpUcs2) 0xFFFE) {
if (bom) *bom = utf16[i];
sm = 8;
i++;
} else if (utf16[i] == (cpUcs2) 0xFEFF) {
if (bom) *bom = utf16[i];
sm = 0;
i++;
} else {
sm = 0; /* Assume local endianness. */
}
cc = 0;
for (;i < len; i++) {
cpUcs4 c, v;
v = endSwap (utf16[i], sm);
if ((v | 0x7FF) == 0xDFFF) { /* Deal with surrogate pairs */
if (v >= 0xDC00 || i >= len) {
ErrMode:;
if (~0 == errCh) {
ErrReturn:;
bu->slen = oldSlen;
return BSTR_ERR;
}
v = errCh;
} else {
i++;
if ((c = endSwap (utf16[i], sm) - 0xDC00) > 0x3FF) goto ErrMode;
v = ((v - 0xD800) << 10) + c + 0x10000;
}
}
buff[cc] = v;
cc++;
if (cc >= TEMP_UCS4_BUFFER_SIZE) {
if (0 > buAppendBlkUcs4 (bu, buff, cc, errCh)) goto ErrReturn;
cc = 0;
}
}
if (cc > 0 && 0 > buAppendBlkUcs4 (bu, buff, cc, errCh)) goto ErrReturn;
return BSTR_OK;
}

37
bstrlib/buniutil.h Normal file
View File

@ -0,0 +1,37 @@
/*
* This source file is part of the bstring string library. This code was
* written by Paul Hsieh in 2002-2015, and is covered by the BSD open source
* license and the GPL. Refer to the accompanying documentation for details
* on usage and license.
*/
/*
* buniutil.h
*
* This file is the interface for the buniutil basic "Unicode for bstrings"
* functions. Note that there are dependencies on bstrlib.h and utf8util.h .
*/
#ifndef BSTRLIB_UNICODE_UTILITIES
#define BSTRLIB_UNICODE_UTILITIES
#include "utf8util.h"
#include "bstrlib.h"
#ifdef __cplusplus
extern "C" {
#endif
extern int buIsUTF8Content (const_bstring bu);
extern int buAppendBlkUcs4 (bstring b, const cpUcs4* bu, int len, cpUcs4 errCh);
/* For those unfortunate enough to be stuck supporting UTF16. */
extern int buGetBlkUTF16 (/* @out */ cpUcs2* ucs2, int len, cpUcs4 errCh, const_bstring bu, int pos);
extern int buAppendBlkUTF16 (bstring bu, const cpUcs2* utf16, int len, cpUcs2* bom, cpUcs4 errCh);
#ifdef __cplusplus
}
#endif
#endif /* BSTRLIB_UNICODE_UTILITIES */

339
bstrlib/gpl.txt Normal file
View File

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

172
bstrlib/porting.txt Normal file
View File

@ -0,0 +1,172 @@
Better String library Porting Guide
-----------------------------------
by Paul Hsieh
The bstring library is an attempt to provide improved string processing
functionality to the C and C++ language. At the heart of the bstring library
is the management of "bstring"s which are a significant improvement over '\0'
terminated char buffers. See the accompanying documenation file bstrlib.txt
for more information.
===============================================================================
Identifying the Compiler
------------------------
Bstrlib has been tested on the following compilers:
Microsoft Visual C++
Watcom C/C++ (32 bit flat)
Intel's C/C++ compiler (on Windows)
The GNU C/C++ compiler (on Windows/Linux on x86 and PPC64)
Borland C++
Turbo C
There are slight differences in these compilers which requires slight
differences in the implementation of Bstrlib. These are accomodated in the
same sources using #ifdef/#if defined() on compiler specific macros. To
port Bstrlib to a new compiler not listed above, it is recommended that the
same strategy be followed. If you are unaware of the compiler specific
identifying preprocessor macro for your compiler you might find it here:
http://predef.sourceforge.net/precomp.html
Note that Intel C/C++ on Windows sets the Microsoft identifier: _MSC_VER.
16-bit vs. 32-bit vs. 64-bit Systems
------------------------------------
Bstrlib has been architected to deal with strings of length between 0 and
INT_MAX (inclusive). Since the values of int are never higher than size_t
there will be no issue here. Note that on most 64-bit systems int is 32-bit.
Dependency on The C-Library
---------------------------
Bstrlib uses the functions memcpy, memmove, malloc, realloc, free and
vsnprintf. Many free standing C compiler implementations that have a mode in
which the C library is not available will typically not include these
functions which will make porting Bstrlib to it onerous. Bstrlib is not
designed for such bare bones compiler environments. This usually includes
compilers that target ROM environments.
Porting Issues
--------------
Bstrlib has been written completely in ANSI/ISO C and ISO C++, however, there
are still a few porting issues. These are described below.
1. The vsnprintf () function.
Unfortunately, the earlier ANSI/ISO C standards did not include this function.
If the compiler of interest does not support this function then the
BSTRLIB_NOVSNP should be defined via something like:
#if !defined (BSTRLIB_VSNP_OK) && !defined (BSTRLIB_NOVSNP)
# if defined (__TURBOC__) || defined (__COMPILERVENDORSPECIFICMACRO__)
# define BSTRLIB_NOVSNP
# endif
#endif
which appears at the top of bstrlib.h. Note that the bformat(a) functions
will not be declared or implemented if the BSTRLIB_NOVSNP macro is set. If
the compiler has renamed vsnprintf() to some other named function, then
search for the definition of the exvsnprintf macro in bstrlib.c file and be
sure its defined appropriately:
#if defined (__COMPILERVENDORSPECIFICMACRO__)
# define exvsnprintf(r,b,n,f,a) {r=__compiler_specific_vsnprintf(b,n,f,a);}
#else
# define exvsnprintf(r,b,n,f,a) {r=vsnprintf(b,n,f,a);}
#endif
Take notice of the return value being captured in the variable r. It is
assumed that r exceeds n if and only if the underlying vsnprintf function has
determined what the true maximal output length would be for output if the
buffer were large enough to hold it. Non-modern implementations must output a
lesser number (the macro can and should be modified to ensure this).
2. Weak C++ compiler.
C++ is a much more complicated language to implement than C. This has lead
to varying quality of compiler implementations. The weaknesses isolated in
the initial ports are inclusion of the Standard Template Library,
std::iostream and exception handling. By default it is assumed that the C++
compiler supports all of these things correctly. If your compiler does not
support one or more of these define the corresponding macro:
BSTRLIB_CANNOT_USE_STL
BSTRLIB_CANNOT_USE_IOSTREAM
BSTRLIB_DOESNT_THROW_EXCEPTIONS
The compiler specific detected macro should be defined at the top of
bstrwrap.h in the Configuration defines section. Note that these disabling
macros can be overrided with the associated enabling macro if a subsequent
version of the compiler gains support. (For example, its possible to rig
up STLport to provide STL support for WATCOM C/C++, so -DBSTRLIB_CAN_USE_STL
can be passed in as a compiler option.)
3. The bsafe module, and reserved words.
The bsafe module is in gross violation of the ANSI/ISO C standard in the
sense that it redefines what could be implemented as reserved words on a
given compiler. The typical problem is that a compiler may inline some of the
functions and thus not be properly overridden by the definitions in the bsafe
module. It is also possible that a compiler may prohibit the redefinitions in
the bsafe module. Compiler specific action will be required to deal with
these situations.
Platform Specific Files
-----------------------
The makefiles for the examples are basically setup of for particular
environments for each platform. In general these makefiles are not portable
and should be constructed as necessary from scratch for each platform.
Testing a port
--------------
To test that a port compiles correctly do the following:
1. Build a sample project that includes the bstrlib, bstraux, bstrwrap, and
bsafe modules.
2. Compile bstest against the bstrlib module.
3. Run bstest and ensure that 0 errors are reported.
4. Compile test against the bstrlib and bstrwrap modules.
5. Run test and ensure that 0 errors are reported.
6. Compile each of the examples (except for the "re" example, which may be
complicated and is not a real test of bstrlib and except for the mfcbench
example which is Windows specific.)
7. Run each of the examples.
The builds must have 0 errors, and should have the absolute minimum number of
warnings (in most cases can be reduced to 0.) The result of execution should
be essentially identical on each platform.
Performance
-----------
Different CPU and compilers have different capabilities in terms of
performance. It is possible for Bstrlib to assume performance
characteristics that a platform doesn't have (since it was primarily
developed on just one platform). The goal of Bstrlib is to provide very good
performance on all platforms regardless of this but without resorting to
extreme measures (such as using assembly language, or non-portable intrinsics
or library extensions.)
There are two performance benchmarks that can be found in the example/
directory. They are: cbench.c and cppbench.cpp. These are variations and
expansions of a benchmark for another string library. They don't cover all
string functionality, but do include the most basic functions which will be
common in most string manipulation kernels.
...............................................................................
Feedback
--------
In all cases, you may email issues found to the primary author of Bstrlib at
the email address: websnarf@users.sourceforge.net
===============================================================================

217
bstrlib/security.txt Normal file
View File

@ -0,0 +1,217 @@
Better String library Security Statement
----------------------------------------
by Paul Hsieh
===============================================================================
Introduction
------------
The Better String library (hereafter referred to as Bstrlib) is an attempt to
provide improved string processing functionality to the C and C++ languages.
At the heart of the Bstrlib is the management of "bstring"s which are a
significant improvement over '\0' terminated char buffers. See the
accompanying documenation file bstrlib.txt for more information.
DISCLAIMER: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Like any software, there is always a possibility of failure due to a flawed
implementation. Nevertheless a good faith effort has been made to minimize
such flaws in Bstrlib. Use of Bstrlib by itself will not make an application
secure or free from implementation failures, however, it is the author's
conviction that use of Bstrlib can greatly facilitate the creation of
software meeting the highest possible standards of security.
Part of the reason why this document has been created, is for the purpose of
security auditing, or the creation of further "Statements on Security" for
software that is created that uses Bstrlib. An auditor may check the claims
below against Bstrlib, and use this as a basis for analysis of software which
uses Bstrlib.
===============================================================================
Statement on Security
---------------------
This is a document intended to give consumers of the Better String Library
who are interested in security an idea of where the Better String Library
stands on various security issues. Any deviation observed in the actual
library itself from the descriptions below should be considered an
implementation error, not a design flaw.
This statement is not an analytical proof of correctness or an outline of one
but rather an assertion similar to a scientific claim or hypothesis. By use,
testing and open independent examination (otherwise known as scientific
falsifiability), the credibility of the claims made below can rise to the
level of an established theory.
Common security issues:
.......................
1. Buffer Overflows
The Bstrlib API allows the programmer a way to deal with strings without
having to deal with the buffers containing them. Ordinary usage of the
Bstrlib API itself makes buffer overflows impossible.
Furthermore, the Bstrlib API has a superset of basic string functionality as
compared to the C library's char * functions, C++'s std::string class and
Microsoft's MFC based CString class. It also has abstracted mechanisms for
dealing with IO. This is important as it gives developers a way of migrating
all their code from a functionality point of view.
2. Memory size overflow/wrap around attack
By design, Bstrlib is impervious to memory size overflow attacks. The
reason is that it detects length overflows and leads to a result error before
the operation attempts to proceed. Attempted conversions of char* strings
which may have lengths greater than INT_MAX are detected and the conversion
is aborted. If the memory to hold the string exceeds the available memory
for it, again, the result is aborted without changing the prior state of the
strings.
3. Constant string protection
Bstrlib implements runtime enforced constant and read-only string semantics.
I.e., bstrings which are declared as constant via the bsStatic() macro cannot
be modified or deallocated directly through the Bstrlib API, and this cannot
be subverted by casting or other type coercion. This is independent of the
use of the const_bstring data type.
The Bstrlib C API uses the type const_bstring to specify bstring parameters
whose contents do not change. Although the C language cannot enforce this,
this is nevertheless guaranteed by the implementation of the Bstrlib library
of C functions. The C++ API enforces the const attribute on CBString types
correctly.
4. Aliased bstring support
Bstrlib detects and supports aliased parameter management throughout the API.
The kind of aliasing that is allowed is the one where pointers of the same
basic type may be pointing to overlapping objects (this is the assumption the
ANSI C99 specification makes.) Each function behaves as if all read-only
parameters were copied to temporaries which are used in their stead before
the function is enacted (it rarely actually does this). No function in the
Bstrlib uses the "restrict" parameter attribute from the ANSI C99
specification.
5. Information leaking
In bstraux.h, using the semantically equivalent macros bSecureDestroy() and
bSecureWriteProtect() in place of bdestroy() and bwriteprotect() respectively
will ensure that stale data does not linger in the heap's free space after
strings have been released back to memory. Created bstrings or CBStrings
are not linked to anything external to themselves, and thus cannot expose
deterministic data leaking. If a bstring is resized, the preimage may exist
as a copy that is released to the heap. Thus for sensitive data, the bstring
should be sufficiently presized before manipulated so that it is not resized.
bSecureInput() has been supplied in bstraux.c, which can be used to obtain
input securely without any risk of leaving any part of the input image in the
heap except for the allocated bstring that is returned.
6. Memory leaking
Bstrlib can be built using memdbg.h enabled via the BSTRLIB_MEMORY_DEBUG
macro. User generated definitions for malloc, realloc and free can then be
supplied which can implement special strategies for memory corruption
detection or memory leaking. Otherwise, bstrlib does not do anything out of
the ordinary to attempt to deal with the standard problem of memory leaking
(i.e., losing references to allocated memory) when programming in the C and
C++ languages. However, it does not compound the problem any more than exists
either, as it doesn't have any intrinsic inescapable leaks in it. Bstrlib
does not preclude the use of automatic garbage collection mechanisms such as
the Boehm garbage collector.
7. Encryption
Bstrlib does not present any built-in encryption mechanism. However, it
supports full binary contents in its data buffers, so any standard block
based encryption mechanism can make direct use of bstrings/CBStrings for
buffer management.
8. Double freeing
Freeing a pointer that is already free is an extremely rare, but nevertheless
a potentially ruthlessly corrupting operation (its possible to cause Win 98 to
reboot, by calling free mulitiple times on already freed data using the WATCOM
CRT.) Bstrlib invalidates the bstring header data before freeing, so that in
many cases a double free will be detected and an error will be reported
(though this behaviour is not guaranteed and should not be relied on).
Using bstrFree pervasively (instead of bdestroy) can lead to somewhat
improved invalid free avoidance (it is completely safe whenever bstring
instances are only stored in unique variables). For example:
struct tagbstring hw = bsStatic ("Hello, world");
bstring cpHw = bstrcpy (&hw);
#ifdef NOT_QUITE_AS_SAFE
bdestroy (cpHw); /* Never fail */
bdestroy (cpHw); /* Error sometimes detected at runtime */
bdestroy (&hw); /* Error detected at run time */
#else
bstrFree (cpHw); /* Never fail */
bstrFree (cpHw); /* Will do nothing */
bstrFree (&hw); /* Will lead to a compile time error */
#endif
9. Resource based denial of service
bSecureInput() has been supplied in bstraux.c. It has an optional upper limit
for input length. But unlike fgets(), it is also easily determined if the
buffer has been truncated early. In this way, a program can set an upper
limit on input sizes while still allowing for implementing context specific
truncation semantics (i.e., does the program consume but dump the extra
input, or does it consume it in later inputs?)
10. Mixing char *'s and bstrings
The bstring and char * representations are not identical. So there is a risk
when converting back and forth that data may lost. Essentially bstrings can
contain '\0' as a valid non-terminating character, while char * strings
cannot and in fact must use the character as a terminator. The risk of data
loss is very low, since:
A) the simple method of only using bstrings in a char * semantically
compatible way is both easy to achieve and pervasively supported.
B) obtaining '\0' content in a string is either deliberate or indicative
of another, likely more serious problem in the code.
C) the library comes with various functions which deal with this issue
(namely: bfromcstr(), bstr2cstr (), and bSetCstrChar ())
Marginal security issues:
.........................
11. 8-bit versus 9-bit portability
Bstrlib uses CHAR_BIT and other limits.h constants to the maximum extent
possible to avoid portability problems. However, Bstrlib has not been tested
on any system that does not represent char as 8-bits. So whether or not it
works on 9-bit systems is an open question. It is recommended that Bstrlib be
carefully auditted by anyone using a system in which CHAR_BIT is not 8.
12. EBCDIC/ASCII/UTF-8 data representation attacks.
Bstrlib uses ctype.h functions to ensure that it remains portable to non-
ASCII systems. It also checks range to make sure it is well defined even for
data that ANSI does not define for the ctype functions.
Obscure issues:
...............
13. Data attributes
There is no support for a Perl-like "taint" attribute, although this is a
fairly straightforward exercise using C++'s type system.

1725
bstrlib/test.cpp Normal file

File diff suppressed because it is too large Load Diff

423
bstrlib/testaux.c Normal file
View File

@ -0,0 +1,423 @@
/*
* This source file is part of the bstring string library. This code was
* written by Paul Hsieh in 2002-2015, and is covered by the BSD open source
* license. Refer to the accompanying documentation for details on usage and
* license.
*/
/*
* testaux.c
*
* This file is the C unit test for the bstraux module of Bstrlib.
*/
#include <stdio.h>
#include "bstrlib.h"
#include "bstraux.h"
static int tWrite (const void * buf, size_t elsize, size_t nelem, void * parm) {
bstring b = (bstring) parm;
size_t i;
if (NULL == b || NULL == buf || 0 == elsize || 0 == nelem)
return -__LINE__;
for (i=0; i < nelem; i++) {
if (0 > bcatblk (b, buf, elsize)) break;
buf = (const void *) (elsize + (const char *) buf);
}
return (int) i;
}
int test0 (void) {
struct bwriteStream * ws;
bstring s;
int ret = 0;
printf ("TEST: struct bwriteStream functions.\n");
ws = bwsOpen ((bNwrite) tWrite, (s = bfromcstr ("")));
bwsBuffLength (ws, 8);
ret += 8 != bwsBuffLength (ws, 0);
bwsWriteBlk (ws, bsStaticBlkParms ("Hello "));
ret += 0 == biseqcstr (s, "");
bwsWriteBlk (ws, bsStaticBlkParms ("World\n"));
ret += 0 == biseqcstr (s, "Hello Wo");
ret += s != bwsClose (ws);
ret += 0 == biseqcstr (s, "Hello World\n");
printf ("\t# failures: %d\n", ret);
return ret;
}
int test1 (void) {
struct tagbstring t = bsStatic ("Hello world");
bstring b, c, d;
int ret = 0;
printf ("TEST: bTail and bHead functions.\n");
b = bTail (&t, 5);
c = bHead (&t, 5);
ret += 0 >= biseqcstr (b, "world");
ret += 0 >= biseqcstr (c, "Hello");
bdestroy (b);
bdestroy (c);
b = bTail (&t, 0);
c = bHead (&t, 0);
ret += 0 >= biseqcstr (b, "");
ret += 0 >= biseqcstr (c, "");
bdestroy (b);
bdestroy (c);
d = bstrcpy (&t);
b = bTail (d, 5);
c = bHead (d, 5);
ret += 0 >= biseqcstr (b, "world");
ret += 0 >= biseqcstr (c, "Hello");
bdestroy (b);
bdestroy (c);
bdestroy (d);
printf ("\t# failures: %d\n", ret);
return ret;
}
int test2 (void) {
struct tagbstring t = bsStatic ("Hello world");
bstring b;
int ret = 0, reto;
printf ("TEST: bSetChar function.\n");
ret += 0 <= bSetChar (&t, 4, ',');
ret += 0 > bSetChar (b = bstrcpy (&t), 4, ',');
ret += 0 >= biseqcstr (b, "Hell, world");
ret += 0 <= bSetChar (b, -1, 'x');
b->slen = 2;
ret += 0 > bSetChar (b, 1, 'i');
ret += 0 >= biseqcstr (b, "Hi");
ret += 0 > bSetChar (b, 2, 's');
ret += 0 >= biseqcstr (b, "His");
ret += 0 > bSetChar (b, 1, '\0');
ret += blength (b) != 3;
ret += bchare (b, 0, '?') != 'H';
ret += bchare (b, 1, '?') != '\0';
ret += bchare (b, 2, '?') != 's';
bdestroy (b);
printf ("\t# failures: %d\n", ret);
reto = ret;
ret = 0;
printf ("TEST: bSetCstrChar function.\n");
ret += 0 <= bSetCstrChar (&t, 4, ',');
ret += 0 > bSetCstrChar (b = bstrcpy (&t), 4, ',');
ret += 0 >= biseqcstr (b, "Hell, world");
ret += 0 <= bSetCstrChar (b, -1, 'x');
b->slen = 2;
ret += 0 > bSetCstrChar (b, 1, 'i');
ret += 0 >= biseqcstr (b, "Hi");
ret += 0 > bSetCstrChar (b, 2, 's');
ret += 0 >= biseqcstr (b, "His");
ret += 0 > bSetCstrChar (b, 1, '\0');
ret += blength (b) != 1;
ret += bchare (b, 0, '?') != 'H';
bdestroy (b);
printf ("\t# failures: %d\n", ret);
return reto + ret;
}
int test3 (void) {
struct tagbstring t = bsStatic ("Hello world");
bstring b;
int ret = 0;
printf ("TEST: bFill function.\n");
ret += 0 <= bFill (&t, 'x', 7);
ret += 0 > bFill (b = bstrcpy (&t), 'x', 7);
ret += 0 >= biseqcstr (b, "xxxxxxx");
ret += 0 <= bFill (b, 'x', -1);
ret += 0 > bFill (b, 'x', 0);
ret += 0 >= biseqcstr (b, "");
bdestroy (b);
printf ("\t# failures: %d\n", ret);
return ret;
}
int test4 (void) {
struct tagbstring t = bsStatic ("foo");
bstring b;
int ret = 0;
printf ("TEST: bReplicate function.\n");
ret += 0 <= bReplicate (&t, 4);
ret += 0 <= bReplicate (b = bstrcpy (&t), -1);
ret += 0 > bReplicate (b, 4);
ret += 0 >= biseqcstr (b, "foofoofoofoo");
ret += 0 > bReplicate (b, 0);
ret += 0 >= biseqcstr (b, "");
bdestroy (b);
printf ("\t# failures: %d\n", ret);
return ret;
}
int test5 (void) {
struct tagbstring t = bsStatic ("Hello world");
bstring b;
int ret = 0;
printf ("TEST: bReverse function.\n");
ret += 0 <= bReverse (&t);
ret += 0 > bReverse (b = bstrcpy (&t));
ret += 0 >= biseqcstr (b, "dlrow olleH");
b->slen = 0;
ret += 0 > bReverse (b);
ret += 0 >= biseqcstr (b, "");
bdestroy (b);
printf ("\t# failures: %d\n", ret);
return ret;
}
int test6 (void) {
struct tagbstring t = bsStatic ("Hello world");
bstring b;
int ret = 0;
printf ("TEST: bInsertChrs function.\n");
ret += 0 <= bInsertChrs (&t, 6, 4, 'x', '?');
ret += 0 > bInsertChrs (b = bstrcpy (&t), 6, 4, 'x', '?');
ret += 0 >= biseqcstr (b, "Hello xxxxworld");
bdestroy (b);
printf ("\t# failures: %d\n", ret);
return ret;
}
int test7 (void) {
struct tagbstring t = bsStatic (" i am ");
bstring b;
int ret = 0;
printf ("TEST: bJustify functions.\n");
ret += 0 <= bJustifyLeft (&t, ' ');
ret += 0 <= bJustifyRight (&t, 8, ' ');
ret += 0 <= bJustifyMargin (&t, 8, ' ');
ret += 0 <= bJustifyCenter (&t, 8, ' ');
ret += 0 > bJustifyLeft (b = bstrcpy (&t), ' ');
ret += 0 >= biseqcstr (b, "i am");
ret += 0 > bJustifyRight (b, 8, ' ');
ret += 0 >= biseqcstr (b, " i am");
ret += 0 > bJustifyMargin (b, 8, ' ');
ret += 0 >= biseqcstr (b, "i am");
ret += 0 > bJustifyCenter (b, 8, ' ');
ret += 0 >= biseqcstr (b, " i am");
bdestroy (b);
printf ("\t# failures: %d\n", ret);
return ret;
}
int test8 (void) {
struct tagbstring t = bsStatic ("Hello world");
bstring b;
char * c;
int ret = 0;
printf ("TEST: NetStr functions.\n");
c = bStr2NetStr (&t);
ret += 0 != strcmp (c, "11:Hello world,");
b = bNetStr2Bstr (c);
ret += 0 >= biseq (b, &t);
bdestroy (b);
bcstrfree (c);
printf ("\t# failures: %d\n", ret);
return ret;
}
int test9 (void) {
struct tagbstring t = bsStatic ("Hello world");
bstring b, c;
int err, ret = 0;
printf ("TEST: Base 64 codec.\n");
b = bBase64Encode (&t);
ret += 0 >= biseqcstr (b, "SGVsbG8gd29ybGQ=");
c = bBase64DecodeEx (b, &err);
ret += 0 != err;
ret += 0 >= biseq (c, &t);
bdestroy (b);
bdestroy (c);
printf ("\t# failures: %d\n", ret);
return ret;
}
int test10 (void) {
struct tagbstring t = bsStatic ("Hello world");
bstring b, c;
int err, ret = 0;
printf ("TEST: UU codec.\n");
b = bUuEncode (&t);
ret += 0 >= biseqcstr (b, "+2&5L;&\\@=V]R;&0`\r\n");
c = bUuDecodeEx (b, &err);
ret += 0 != err;
ret += 0 >= biseq (c, &t);
bdestroy (b);
bdestroy (c);
printf ("\t# failures: %d\n", ret);
return ret;
}
int test11 (void) {
struct tagbstring t = bsStatic ("Hello world");
unsigned char Ytstr[] = {0x72, 0x8f, 0x96, 0x96, 0x99, 0x4a, 0xa1, 0x99, 0x9c, 0x96, 0x8e};
bstring b, c;
int ret = 0;
printf ("TEST: Y codec.\n");
b = bYEncode (&t);
ret += 11 != b->slen;
ret += 0 >= bisstemeqblk (b, Ytstr, 11);
c = bYDecode (b);
ret += 0 >= biseq (c, &t);
bdestroy (b);
bdestroy (c);
printf ("\t# failures: %d\n", ret);
return ret;
}
int test12 (void) {
struct tagbstring t = bsStatic ("Hello world");
struct bStream * s;
bstring b;
int ret = 0;
printf ("TEST: bsFromBstr.\n");
ret = bsread (b = bfromcstr (""), s = bsFromBstr (&t), 6);
ret += 1 != biseqcstr (b, "Hello ");
if (b) b->slen = 0;
ret = bsread (b, s, 6);
ret += 1 != biseqcstr (b, "world");
bdestroy (b);
bsclose (s);
printf ("\t# failures: %d\n", ret);
return ret;
}
struct vfgetc {
int ofs;
bstring base;
};
static int test13_fgetc (void * ctx) {
struct vfgetc * vctx = (struct vfgetc *) ctx;
int c;
if (NULL == vctx || NULL == vctx->base) return EOF;
if (vctx->ofs >= blength (vctx->base)) return EOF;
c = bchare (vctx->base, vctx->ofs, EOF);
vctx->ofs++;
return c;
}
int test13 (void) {
struct tagbstring t0 = bsStatic ("Random String, long enough to cause to reallocing");
struct vfgetc vctx;
bstring b;
int ret = 0;
int i;
printf ("TEST: bSecureInput, bSecureDestroy.\n");
for (i=0; i < 1000; i++) {
unsigned char * h;
vctx.ofs = 0;
vctx.base = &t0;
b = bSecureInput (INT_MAX, '\n', (bNgetc) test13_fgetc, &vctx);
ret += 1 != biseq (b, &t0);
h = b->data;
bSecureDestroy (b);
/* WARNING! Technically undefined code follows (h has been freed): */
ret += (0 == memcmp (h, t0.data, t0.slen));
if (ret) break;
}
printf ("\t# failures: %d\n", ret);
return ret;
}
int test14_aux(bstring b, const char* chkVal) {
int ret = 0;
ret += 0 != bSGMLEncode (b);
ret += 1 != biseqcstr (b, chkVal);
return ret;
}
int test14 (void) {
bstring b;
int ret = 0;
printf ("TEST: bSGMLEncode.\n");
ret += test14_aux (b = bfromStatic ("<\"Hello, you, me, & world\">"), "&lt;&quot;Hello, you, me, &amp; world&quot;&gt;");
printf ("\t# failures: %d\n", ret);
return ret;
}
int main () {
int ret = 0;
printf ("Direct case testing of bstraux functions\n");
ret += test0 ();
ret += test1 ();
ret += test2 ();
ret += test3 ();
ret += test4 ();
ret += test5 ();
ret += test6 ();
ret += test7 ();
ret += test8 ();
ret += test9 ();
ret += test10 ();
ret += test11 ();
ret += test12 ();
ret += test13 ();
ret += test14 ();
printf ("# test failures: %d\n", ret);
return 0;
}

249
bstrlib/utf8util.c Normal file
View File

@ -0,0 +1,249 @@
/*
* This source file is part of the bstring string library. This code was
* written by Paul Hsieh in 2002-2015, and is covered by the BSD open source
* license and the GPL. Refer to the accompanying documentation for details
* on usage and license.
*/
/*
* utf8util.c
*
* This file is not necessarily part of the core bstring library itself, but
* is just an generic module for implementing utf8 utility functions.
*/
#include "utf8util.h"
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
/* Surrogate range is wrong, there is a maximum, the BOM alias is illegal and 0xFFFF is illegal */
#define isLegalUnicodeCodePoint(v) ((((v) < 0xD800L) || ((v) > 0xDFFFL)) && (((unsigned long)(v)) <= 0x0010FFFFL) && (((v)|0x1F0001) != 0x1FFFFFL))
void utf8IteratorInit (struct utf8Iterator* iter, unsigned char* data, int slen) {
if (iter) {
iter->data = data;
iter->slen = (iter->data && slen >= 0) ? slen : -1;
iter->start = -1;
iter->next = (iter->slen >= 0) ? 0 : -1;
iter->error = (iter->slen >= 0) ? 0 : 1;
}
}
void utf8IteratorUninit (struct utf8Iterator* iter) {
if (iter) {
iter->data = NULL;
iter->slen = -1;
iter->start = iter->next = -1;
}
}
int utf8ScanBackwardsForCodePoint (unsigned char* msg, int len, int pos, cpUcs4* out) {
cpUcs4 v1, v2, v3, v4, x;
int ret;
if (NULL == msg || len < 0 || (unsigned) pos >= (unsigned) len) {
return -__LINE__;
}
if (!out) out = &x;
ret = 0;
if (msg[pos] < 0x80) {
*out = msg[pos];
return 0;
} else if (msg[pos] < 0xC0) {
if (0 == pos) return -__LINE__;
ret = -__LINE__;
if (msg[pos-1] >= 0xC1 && msg[pos-1] < 0xF8) {
pos--;
ret = 1;
} else {
if (1 == pos) return -__LINE__;
if ((msg[pos-1] | 0x3F) != 0xBF) return -__LINE__;
if (msg[pos-2] >= 0xE0 && msg[pos-2] < 0xF8) {
pos -= 2;
ret = 2;
} else {
if (2 == pos) return -__LINE__;
if ((msg[pos-2] | 0x3F) != 0xBF) return -__LINE__;
if ((msg[pos-3]|0x07) == 0xF7) {
pos -= 3;
ret = 3;
} else return -__LINE__;
}
}
}
if (msg[pos] < 0xE0) {
if (pos + 1 >= len) return -__LINE__;
v1 = msg[pos] & ~0xE0;
v2 = msg[pos+1] & ~0xC0;
v1 = (v1 << 6) + v2;
if (v1 < 0x80) return -__LINE__;
*out = v1;
return ret;
}
if (msg[pos] < 0xF0) {
if (pos + 2 >= len) return -__LINE__;
v1 = msg[pos] & ~0xF0;
v2 = msg[pos+1] & ~0xC0;
v3 = msg[pos+2] & ~0xC0;
v1 = (v1 << 12) + (v2 << 6) + v3;
if (v1 < 0x800) return -__LINE__;
if (!isLegalUnicodeCodePoint(v1)) return -__LINE__;
*out = v1;
return ret;
}
if (msg[pos] >= 0xF8) return -__LINE__;
if (pos + 3 >= len) return -__LINE__;
v1 = msg[pos] & ~0xF8;
v2 = msg[pos+1] & ~0xC0;
v3 = msg[pos+2] & ~0xC0;
v4 = msg[pos+3] & ~0xC0;
v1 = (v1 << 18) + (v2 << 12) + (v3 << 6) + v4;
if (v1 < 0x10000) return -__LINE__;
if (!isLegalUnicodeCodePoint(v1)) return -__LINE__;
*out = v1;
return ret;
}
/*
Code point UTF-8
---------- -----
U-00000000 - U-0000007F: 0xxxxxxx
U-00000080 - U-000007FF: 110xxxxx 10xxxxxx
U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
*/
/*
* Returns next read code point for iterator.
*
* iter->data + iter->start points at the characters just read.
*
* iter->data + iter->next points at the characters that will be read next.
*
* iter->error is boolean indicating whether or not last read contained an error.
*/
cpUcs4 utf8IteratorGetNextCodePoint (struct utf8Iterator* iter, cpUcs4 errCh) {
unsigned char * chrs;
unsigned char c, d, e;
long v;
int i, ofs;
if (NULL == iter || iter->next < 0) return errCh;
if (iter->next >= iter->slen) {
iter->start = iter->slen;
return errCh;
}
if (NULL == iter->data || iter->next < 0 || utf8IteratorNoMore(iter)) return errCh;
chrs = iter->data + iter->next;
iter->error = 0;
c = chrs[0];
ofs = 0;
if (c < 0xC0 || c > 0xFD) {
if (c >= 0x80) goto ErrMode;
v = c;
ofs = 1;
} else if (c < 0xE0) {
if (iter->next >= iter->slen + 1) goto ErrMode;
v = (c << 6u) - (0x0C0 << 6u);
c = (unsigned char) ((unsigned) chrs[1] - 0x080);
v += c;
if (c >= 0x40 || v < 0x80) goto ErrMode;
ofs = 2;
} else if (c < 0xF0) {
if (iter->next >= iter->slen + 2) goto ErrMode;
v = (c << 12) - (0x0E0 << 12u);
c = (unsigned char) ((unsigned) chrs[1] - 0x080);
d = (unsigned char) ((unsigned) chrs[2] - 0x080);
v += (c << 6u) + d;
if ((c|d) >= 0x40 || v < 0x800 || !isLegalUnicodeCodePoint (v)) goto ErrMode;
ofs = 3;
} else if (c < 0xF8) {
if (iter->next >= iter->slen + 3) goto ErrMode;
v = (c << 18) - (0x0F0 << 18u);
c = (unsigned char) ((unsigned) chrs[1] - 0x080);
d = (unsigned char) ((unsigned) chrs[2] - 0x080);
e = (unsigned char) ((unsigned) chrs[3] - 0x080);
v += (c << 12u) + (d << 6u) + e;
if ((c|d|e) >= 0x40 || v < 0x10000 || !isLegalUnicodeCodePoint (v)) goto ErrMode;
ofs = 4;
} else { /* 5 and 6 byte encodings are invalid */
ErrMode:;
iter->error = 1;
v = errCh;
for (i = iter->next+1; i < iter->slen; i++) if ((iter->data[i] & 0xC0) != 0x80) break;
ofs = i - iter->next;
}
iter->start = iter->next;
iter->next += ofs;
return v;
}
/*
* Returns next read code point for iterator.
*
* iter->data + iter->start points at the characters to be read.
*
* iter->data + iter->next points at the characters that will be read next.
*
* iter->error is boolean indicating whether or not last read contained an error.
*/
cpUcs4 utf8IteratorGetCurrCodePoint (struct utf8Iterator* iter, cpUcs4 errCh) {
unsigned char * chrs;
unsigned char c, d, e;
long v;
if (NULL == iter || iter->next < 0) return errCh;
if (iter->next >= iter->slen) {
iter->start = iter->slen;
return errCh;
}
if (NULL == iter->data || iter->next < 0 || utf8IteratorNoMore(iter)) return errCh;
chrs = iter->data + iter->next;
iter->error = 0;
c = chrs[0];
if (c < 0xC0 || c > 0xFD) {
if (c >= 0x80) goto ErrMode;
v = c;
} else if (c < 0xE0) {
if (iter->next >= iter->slen + 1) goto ErrMode;
v = (c << 6u) - (0x0C0 << 6u);
c = (unsigned char) ((unsigned) chrs[1] - 0x080);
v += c;
if (c >= 0x40 || v < 0x80) goto ErrMode;
} else if (c < 0xF0) {
if (iter->next >= iter->slen + 2) goto ErrMode;
v = (c << 12lu) - (0x0E0 << 12u);
c = (unsigned char) ((unsigned) chrs[1] - 0x080);
d = (unsigned char) ((unsigned) chrs[2] - 0x080);
v += (c << 6u) + d;
if ((c|d) >= 0x40 || v < 0x800 || !isLegalUnicodeCodePoint (v)) goto ErrMode;
} else if (c < 0xF8) {
if (iter->next >= iter->slen + 3) goto ErrMode;
v = (c << 18lu) - (0x0F0 << 18u);
c = (unsigned char) ((unsigned) chrs[1] - 0x080);
d = (unsigned char) ((unsigned) chrs[2] - 0x080);
e = (unsigned char) ((unsigned) chrs[3] - 0x080);
v += (c << 12lu) + (d << 6u) + e;
if ((c|d|e) >= 0x40 || v < 0x10000 || !isLegalUnicodeCodePoint (v)) goto ErrMode;
} else { /* 5 and 6 byte encodings are invalid */
ErrMode:;
iter->error = 1;
v = errCh;
}
return v;
}

62
bstrlib/utf8util.h Normal file
View File

@ -0,0 +1,62 @@
/*
* This source file is part of the bstring string library. This code was
* written by Paul Hsieh in 2002-2015, and is covered by the BSD open source
* license and the GPL. Refer to the accompanying documentation for details
* on usage and license.
*/
/*
* utf8util.h
*
* This file defines the interface to the utf8 utility functions.
*/
#ifndef UTF8_UNICODE_UTILITIES
#define UTF8_UNICODE_UTILITIES
#include <limits.h>
#ifdef __cplusplus
extern "C" {
#endif
#if INT_MAX >= 0x7fffffffUL
typedef int cpUcs4;
#elif LONG_MAX >= 0x7fffffffUL
typedef long cpUcs4;
#else
#error This compiler is not supported
#endif
#if UINT_MAX == 0xFFFF
typedef unsigned int cpUcs2;
#elif USHRT_MAX == 0xFFFF
typedef unsigned short cpUcs2;
#elif UCHAR_MAX == 0xFFFF
typedef unsigned char cpUcs2;
#else
#error This compiler is not supported
#endif
#define isLegalUnicodeCodePoint(v) ((((v) < 0xD800L) || ((v) > 0xDFFFL)) && (((unsigned long)(v)) <= 0x0010FFFFL) && (((v)|0x1F0001) != 0x1FFFFFL))
struct utf8Iterator {
unsigned char* data;
int slen;
int start, next;
int error;
};
#define utf8IteratorNoMore(it) (!(it) || (it)->next >= (it)->slen)
extern void utf8IteratorInit (struct utf8Iterator* iter, unsigned char* data, int slen);
extern void utf8IteratorUninit (struct utf8Iterator* iter);
extern cpUcs4 utf8IteratorGetNextCodePoint (struct utf8Iterator* iter, cpUcs4 errCh);
extern cpUcs4 utf8IteratorGetCurrCodePoint (struct utf8Iterator* iter, cpUcs4 errCh);
extern int utf8ScanBackwardsForCodePoint (unsigned char* msg, int len, int pos, cpUcs4* out);
#ifdef __cplusplus
}
#endif
#endif /* UTF8_UNICODE_UTILITIES */

View File

@ -75,7 +75,7 @@ UINT32 *DestinationSize
if (*DestinationSize < destLen)
{
*DestinationSize = destLen;
return ERR_BUFFER_TOO_SMALL;
return EFI_BUFFER_TOO_SMALL;
}
LzmaEncProps_Init(&props);
@ -101,9 +101,9 @@ UINT32 *DestinationSize
SetEncodedSizeOfBuf((UINT64)SourceSize, Destination);
if (LzmaResult == SZ_OK) {
return ERR_SUCCESS;
return EFI_SUCCESS;
}
else {
return ERR_INVALID_PARAMETER;
return EFI_INVALID_PARAMETER;
}
}

View File

@ -100,7 +100,7 @@ UINT32 *DestinationSize
DecodedSize = GetDecodedSizeOfBuf((UINT8*)Source);
*DestinationSize = (UINT32)DecodedSize;
return ERR_SUCCESS;
return U_SUCCESS;
}
/*
@ -151,9 +151,9 @@ VOID *Destination
);
if (LzmaResult == SZ_OK) {
return ERR_SUCCESS;
return U_SUCCESS;
}
else {
return ERR_INVALID_PARAMETER;
return U_INVALID_PARAMETER;
}
}

View File

@ -17,6 +17,49 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <stdarg.h>
#include <stdint.h>
typedef uint8_t USTATUS;
#define U_SUCCESS 0
#define U_INVALID_PARAMETER 1
#define U_BUFFER_TOO_SMALL 2
#define U_OUT_OF_RESOURCES 3
#define U_OUT_OF_MEMORY 4
#define U_FILE_OPEN 5
#define U_FILE_READ 6
#define U_FILE_WRITE 7
#define U_ITEM_NOT_FOUND 8
#define U_UNKNOWN_ITEM_TYPE 9
#define U_INVALID_FLASH_DESCRIPTOR 10
#define U_INVALID_REGION 11
#define U_EMPTY_REGION 12
#define U_BIOS_REGION_NOT_FOUND 13
#define U_VOLUMES_NOT_FOUND 14
#define U_INVALID_VOLUME 15
#define U_VOLUME_REVISION_NOT_SUPPORTED 16
#define U_COMPLEX_BLOCK_MAP 17
#define U_UNKNOWN_FFS 18
#define U_INVALID_FILE 19
#define U_INVALID_SECTION 20
#define U_UNKNOWN_SECTION 21
#define U_STANDARD_COMPRESSION_FAILED 22
#define U_CUSTOMIZED_COMPRESSION_FAILED 23
#define U_STANDARD_DECOMPRESSION_FAILED 24
#define U_CUSTOMIZED_DECOMPRESSION_FAILED 25
#define U_UNKNOWN_COMPRESSION_TYPE 26
#define U_DEPEX_PARSE_FAILED 27
#define U_UNKNOWN_EXTRACT_MODE 28
#define U_UNKNOWN_REPLACE_MODE 29
#define U_UNKNOWN_IMAGE_TYPE 30
#define U_UNKNOWN_PE_OPTIONAL_HEADER_TYPE 31
#define U_UNKNOWN_RELOCATION_TYPE 32
#define U_DIR_ALREADY_EXIST 33
#define U_DIR_CREATE 34
#define U_DIR_CHANGE 35
#define U_TRUNCATED_IMAGE 36
#define U_INVALID_CAPSULE 37
#define U_STORES_NOT_FOUND 38
#define U_NOT_IMPLEMENTED 0xFF
// UDK porting definitions
typedef uint8_t BOOLEAN;
typedef int8_t INT8;
typedef uint8_t UINT8;
@ -42,56 +85,14 @@ typedef unsigned int UINTN;
#define FALSE ((BOOLEAN)(0==1))
#endif
typedef UINT8 STATUS;
#define ERR_SUCCESS 0
#define ERR_INVALID_PARAMETER 1
#define ERR_BUFFER_TOO_SMALL 2
#define ERR_OUT_OF_RESOURCES 3
#define ERR_OUT_OF_MEMORY 4
#define ERR_FILE_OPEN 5
#define ERR_FILE_READ 6
#define ERR_FILE_WRITE 7
#define ERR_ITEM_NOT_FOUND 8
#define ERR_UNKNOWN_ITEM_TYPE 9
#define ERR_INVALID_FLASH_DESCRIPTOR 10
#define ERR_INVALID_REGION 11
#define ERR_EMPTY_REGION 12
#define ERR_BIOS_REGION_NOT_FOUND 13
#define ERR_VOLUMES_NOT_FOUND 14
#define ERR_INVALID_VOLUME 15
#define ERR_VOLUME_REVISION_NOT_SUPPORTED 16
#define ERR_COMPLEX_BLOCK_MAP 17
#define ERR_UNKNOWN_FFS 18
#define ERR_INVALID_FILE 19
#define ERR_INVALID_SECTION 20
#define ERR_UNKNOWN_SECTION 21
#define ERR_STANDARD_COMPRESSION_FAILED 22
#define ERR_CUSTOMIZED_COMPRESSION_FAILED 23
#define ERR_STANDARD_DECOMPRESSION_FAILED 24
#define ERR_CUSTOMIZED_DECOMPRESSION_FAILED 25
#define ERR_UNKNOWN_COMPRESSION_TYPE 26
#define ERR_DEPEX_PARSE_FAILED 27
#define ERR_UNKNOWN_EXTRACT_MODE 28
#define ERR_UNKNOWN_REPLACE_MODE 29
#define ERR_UNKNOWN_IMAGE_TYPE 30
#define ERR_UNKNOWN_PE_OPTIONAL_HEADER_TYPE 31
#define ERR_UNKNOWN_RELOCATION_TYPE 32
#define ERR_DIR_ALREADY_EXIST 33
#define ERR_DIR_CREATE 34
#define ERR_TRUNCATED_IMAGE 35
#define ERR_INVALID_CAPSULE 36
#define ERR_STORES_NOT_FOUND 37
#define ERR_NOT_IMPLEMENTED 0xFF
// UDK porting definitions
#define IN
#define OUT
#define EFIAPI
#define EFI_STATUS UINTN
#define EFI_SUCCESS ERR_SUCCESS
#define EFI_INVALID_PARAMETER ERR_INVALID_PARAMETER
#define EFI_OUT_OF_RESOURCES ERR_OUT_OF_RESOURCES
#define EFI_BUFFER_TOO_SMALL ERR_BUFFER_TOO_SMALL
#define EFI_SUCCESS U_SUCCESS
#define EFI_INVALID_PARAMETER U_INVALID_PARAMETER
#define EFI_OUT_OF_RESOURCES U_OUT_OF_RESOURCES
#define EFI_BUFFER_TOO_SMALL U_BUFFER_TOO_SMALL
#define EFI_ERROR(X) (X)
// Compression algorithms
@ -162,10 +163,6 @@ typedef struct EFI_TIME_ {
#include <assert.h>
#define ASSERT(x) assert(x)
//Hexarg macros
#define hexarg(X) arg(QString("%1").arg((X),0,16).toUpper())
#define hexarg2(X, Y) arg(QString("%1").arg((X),(Y),16,QLatin1Char('0')).toUpper())
// SHA256 hash size in bytes
#define SHA256_HASH_SIZE 0x20

View File

@ -10,11 +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.
*/
#include <QObject>
#include "ustring.h"
#include "ffs.h"
// This is a workaround for the lack of static std::vector initializer before C++11
const QByteArray FFSv2VolumesInt[] = {
const UByteArray FFSv2VolumesInt[] = {
EFI_FIRMWARE_FILE_SYSTEM_GUID,
EFI_FIRMWARE_FILE_SYSTEM2_GUID,
EFI_APPLE_BOOT_VOLUME_FILE_SYSTEM_GUID,
@ -25,9 +25,9 @@ const QByteArray FFSv2VolumesInt[] = {
};
// This number must be updated if the array above is grown
#define FFSv2VolumesIntSize 7
const std::vector<QByteArray> FFSv2Volumes(FFSv2VolumesInt, FFSv2VolumesInt + FFSv2VolumesIntSize);
const std::vector<UByteArray> FFSv2Volumes(FFSv2VolumesInt, FFSv2VolumesInt + FFSv2VolumesIntSize);
// Luckily, FFSv3Volumes now only has 1 element
const std::vector<QByteArray> FFSv3Volumes(1, EFI_FIRMWARE_FILE_SYSTEM3_GUID);
const std::vector<UByteArray> FFSv3Volumes(1, EFI_FIRMWARE_FILE_SYSTEM3_GUID);
const UINT8 ffsAlignmentTable[] =
{ 0, 4, 7, 9, 10, 12, 15, 16 };
@ -44,66 +44,66 @@ UINT32 uint24ToUint32(const UINT8* ffsSize)
return *(UINT32*)ffsSize & 0x00FFFFFF;
}
QString guidToQString(const EFI_GUID & guid)
UString guidToUString(const EFI_GUID & guid)
{
return QString("%1-%2-%3-%4%5-%6%7%8%9%10%11")
.arg(*(const UINT32*)&guid.Data[0], 8, 16, QChar('0'))
.arg(*(const UINT16*)&guid.Data[4], 4, 16, QChar('0'))
.arg(*(const UINT16*)&guid.Data[6], 4, 16, QChar('0'))
.arg(guid.Data[8], 2, 16, QChar('0'))
.arg(guid.Data[9], 2, 16, QChar('0'))
.arg(guid.Data[10], 2, 16, QChar('0'))
.arg(guid.Data[11], 2, 16, QChar('0'))
.arg(guid.Data[12], 2, 16, QChar('0'))
.arg(guid.Data[13], 2, 16, QChar('0'))
.arg(guid.Data[14], 2, 16, QChar('0'))
.arg(guid.Data[15], 2, 16, QChar('0')).toUpper();
return usprintf("%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
*(const UINT32*)&guid.Data[0],
*(const UINT16*)&guid.Data[4],
*(const UINT16*)&guid.Data[6],
guid.Data[8],
guid.Data[9],
guid.Data[10],
guid.Data[11],
guid.Data[12],
guid.Data[13],
guid.Data[14],
guid.Data[15]);
}
QString fileTypeToQString(const UINT8 type)
UString fileTypeToUString(const UINT8 type)
{
switch (type)
{
case EFI_FV_FILETYPE_RAW: return QObject::tr("Raw");
case EFI_FV_FILETYPE_FREEFORM: return QObject::tr("Freeform");
case EFI_FV_FILETYPE_SECURITY_CORE: return QObject::tr("SEC core");
case EFI_FV_FILETYPE_PEI_CORE: return QObject::tr("PEI core");
case EFI_FV_FILETYPE_DXE_CORE: return QObject::tr("DXE core");
case EFI_FV_FILETYPE_PEIM: return QObject::tr("PEI module");
case EFI_FV_FILETYPE_DRIVER: return QObject::tr("DXE driver");
case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER: return QObject::tr("Combined PEI/DXE");
case EFI_FV_FILETYPE_APPLICATION: return QObject::tr("Application");
case EFI_FV_FILETYPE_SMM: return QObject::tr("SMM module");
case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE: return QObject::tr("Volume image");
case EFI_FV_FILETYPE_COMBINED_SMM_DXE: return QObject::tr("Combined SMM/DXE");
case EFI_FV_FILETYPE_SMM_CORE: return QObject::tr("SMM core");
case EFI_FV_FILETYPE_PAD: return QObject::tr("Pad");
default: return QObject::tr("Unknown");
case EFI_FV_FILETYPE_RAW: return UString("Raw");
case EFI_FV_FILETYPE_FREEFORM: return UString("Freeform");
case EFI_FV_FILETYPE_SECURITY_CORE: return UString("SEC core");
case EFI_FV_FILETYPE_PEI_CORE: return UString("PEI core");
case EFI_FV_FILETYPE_DXE_CORE: return UString("DXE core");
case EFI_FV_FILETYPE_PEIM: return UString("PEI module");
case EFI_FV_FILETYPE_DRIVER: return UString("DXE driver");
case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER: return UString("Combined PEI/DXE");
case EFI_FV_FILETYPE_APPLICATION: return UString("Application");
case EFI_FV_FILETYPE_SMM: return UString("SMM module");
case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE: return UString("Volume image");
case EFI_FV_FILETYPE_COMBINED_SMM_DXE: return UString("Combined SMM/DXE");
case EFI_FV_FILETYPE_SMM_CORE: return UString("SMM core");
case EFI_FV_FILETYPE_PAD: return UString("Pad");
default: return UString("Unknown");
};
}
QString sectionTypeToQString(const UINT8 type)
UString sectionTypeToUString(const UINT8 type)
{
switch (type)
{
case EFI_SECTION_COMPRESSION: return QObject::tr("Compressed");
case EFI_SECTION_GUID_DEFINED: return QObject::tr("GUID defined");
case EFI_SECTION_DISPOSABLE: return QObject::tr("Disposable");
case EFI_SECTION_PE32: return QObject::tr("PE32 image");
case EFI_SECTION_PIC: return QObject::tr("PIC image");
case EFI_SECTION_TE: return QObject::tr("TE image");
case EFI_SECTION_DXE_DEPEX: return QObject::tr("DXE dependency");
case EFI_SECTION_VERSION: return QObject::tr("Version");
case EFI_SECTION_USER_INTERFACE: return QObject::tr("UI");
case EFI_SECTION_COMPATIBILITY16: return QObject::tr("16-bit image");
case EFI_SECTION_FIRMWARE_VOLUME_IMAGE: return QObject::tr("Volume image");
case EFI_SECTION_FREEFORM_SUBTYPE_GUID: return QObject::tr("Freeform subtype GUID");
case EFI_SECTION_RAW: return QObject::tr("Raw");
case EFI_SECTION_PEI_DEPEX: return QObject::tr("PEI dependency");
case EFI_SECTION_SMM_DEPEX: return QObject::tr("SMM dependency");
case INSYDE_SECTION_POSTCODE: return QObject::tr("Insyde postcode");
case PHOENIX_SECTION_POSTCODE: return QObject::tr("Phoenix postcode");
default: return QObject::tr("Unknown");
case EFI_SECTION_COMPRESSION: return UString("Compressed");
case EFI_SECTION_GUID_DEFINED: return UString("GUID defined");
case EFI_SECTION_DISPOSABLE: return UString("Disposable");
case EFI_SECTION_PE32: return UString("PE32 image");
case EFI_SECTION_PIC: return UString("PIC image");
case EFI_SECTION_TE: return UString("TE image");
case EFI_SECTION_DXE_DEPEX: return UString("DXE dependency");
case EFI_SECTION_VERSION: return UString("Version");
case EFI_SECTION_USER_INTERFACE: return UString("UI");
case EFI_SECTION_COMPATIBILITY16: return UString("16-bit image");
case EFI_SECTION_FIRMWARE_VOLUME_IMAGE: return UString("Volume image");
case EFI_SECTION_FREEFORM_SUBTYPE_GUID: return UString("Freeform subtype GUID");
case EFI_SECTION_RAW: return UString("Raw");
case EFI_SECTION_PEI_DEPEX: return UString("PEI dependency");
case EFI_SECTION_SMM_DEPEX: return UString("SMM dependency");
case INSYDE_SECTION_POSTCODE: return UString("Insyde postcode");
case PHOENIX_SECTION_POSTCODE: return UString("Phoenix postcode");
default: return UString("Unknown");
}
}

View File

@ -15,16 +15,16 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <vector>
#include <QByteArray>
#include <QString>
#include "ubytearray.h"
#include "ustring.h"
#include "basetypes.h"
// Make sure we use right packing rules
#pragma pack(push,1)
extern QString guidToQString(const EFI_GUID& guid);
extern QString fileTypeToQString(const UINT8 type);
extern QString sectionTypeToQString(const UINT8 type);
extern UString guidToUString(const EFI_GUID& guid);
extern UString fileTypeToUString(const UINT8 type);
extern UString sectionTypeToUString(const UINT8 type);
//*****************************************************************************
// EFI Capsule
@ -43,19 +43,19 @@ typedef struct EFI_CAPSULE_HEADER_ {
#define EFI_CAPSULE_HEADER_FLAG_POPULATE_SYSTEM_TABLE 0x00020000
// Standard EFI capsule GUID
const QByteArray EFI_CAPSULE_GUID
const UByteArray EFI_CAPSULE_GUID
("\xBD\x86\x66\x3B\x76\x0D\x30\x40\xB7\x0E\xB5\x51\x9E\x2F\xC5\xA0", 16);
// Intel capsule GUID
const QByteArray INTEL_CAPSULE_GUID
const UByteArray INTEL_CAPSULE_GUID
("\xB9\x82\x91\x53\xB5\xAB\x91\x43\xB6\x9A\xE3\xA9\x43\xF7\x2F\xCC", 16);
// Lenovo capsule GUID
const QByteArray LENOVO_CAPSULE_GUID
const UByteArray LENOVO_CAPSULE_GUID
("\xD3\xAF\x0B\xE2\x14\x99\x4F\x4F\x95\x37\x31\x29\xE0\x90\xEB\x3C", 16);
// Another Lenovo capsule GUID
const QByteArray LENOVO2_CAPSULE_GUID
const UByteArray LENOVO2_CAPSULE_GUID
("\x76\xFE\xB5\x25\x43\x82\x5C\x4A\xA9\xBD\x7E\xE3\x24\x61\x98\xB5", 16);
// Toshiba EFI Capsule header
@ -67,7 +67,7 @@ typedef struct TOSHIBA_CAPSULE_HEADER_ {
} TOSHIBA_CAPSULE_HEADER;
// Toshiba capsule GUID
const QByteArray TOSHIBA_CAPSULE_GUID
const UByteArray TOSHIBA_CAPSULE_GUID
("\x62\x70\xE0\x3B\x51\x1D\xD2\x45\x83\x2B\xF0\x93\x25\x7E\xD4\x61", 16);
// AMI Aptio extended capsule header
@ -80,11 +80,11 @@ typedef struct APTIO_CAPSULE_HEADER_ {
} APTIO_CAPSULE_HEADER;
// AMI Aptio signed extended capsule GUID
const QByteArray APTIO_SIGNED_CAPSULE_GUID
const UByteArray APTIO_SIGNED_CAPSULE_GUID
("\x8B\xA6\x3C\x4A\x23\x77\xFB\x48\x80\x3D\x57\x8C\xC1\xFE\xC4\x4D", 16);
// AMI Aptio unsigned extended capsule GUID
const QByteArray APTIO_UNSIGNED_CAPSULE_GUID
const UByteArray APTIO_UNSIGNED_CAPSULE_GUID
("\x90\xBB\xEE\x14\x0A\x89\xDB\x43\xAE\xD1\x5D\x3C\x45\x88\xA4\x18", 16);
//*****************************************************************************
@ -113,38 +113,38 @@ typedef struct EFI_FIRMWARE_VOLUME_HEADER_ {
} EFI_FIRMWARE_VOLUME_HEADER;
// Standard file system GUIDs
const QByteArray EFI_FIRMWARE_FILE_SYSTEM_GUID
const UByteArray EFI_FIRMWARE_FILE_SYSTEM_GUID
("\xD9\x54\x93\x7A\x68\x04\x4A\x44\x81\xCE\x0B\xF6\x17\xD8\x90\xDF", 16);
const QByteArray EFI_FIRMWARE_FILE_SYSTEM2_GUID
const UByteArray EFI_FIRMWARE_FILE_SYSTEM2_GUID
("\x78\xE5\x8C\x8C\x3D\x8A\x1C\x4F\x99\x35\x89\x61\x85\xC3\x2D\xD3", 16);
// Vendor-specific file system GUIDs
const QByteArray EFI_APPLE_BOOT_VOLUME_FILE_SYSTEM_GUID
const UByteArray EFI_APPLE_BOOT_VOLUME_FILE_SYSTEM_GUID
("\xAD\xEE\xAD\x04\xFF\x61\x31\x4D\xB6\xBA\x64\xF8\xBF\x90\x1F\x5A", 16);
const QByteArray EFI_APPLE_BOOT_VOLUME_FILE_SYSTEM2_GUID
const UByteArray EFI_APPLE_BOOT_VOLUME_FILE_SYSTEM2_GUID
("\x8C\x1B\x00\xBD\x71\x6A\x7B\x48\xA1\x4F\x0C\x2A\x2D\xCF\x7A\x5D", 16);
// AD3FFFFF-D28B-44C4-9F13-9EA98A97F9F0 // Intel 1
const QByteArray EFI_INTEL_FILE_SYSTEM_GUID
const UByteArray EFI_INTEL_FILE_SYSTEM_GUID
("\xFF\xFF\x3F\xAD\x8B\xD2\xC4\x44\x9F\x13\x9E\xA9\x8A\x97\xF9\xF0", 16);
// D6A1CD70-4B33-4994-A6EA-375F2CCC5437 // Intel 2
const QByteArray EFI_INTEL_FILE_SYSTEM2_GUID
const UByteArray EFI_INTEL_FILE_SYSTEM2_GUID
("\x70\xCD\xA1\xD6\x33\x4B\x94\x49\xA6\xEA\x37\x5F\x2C\xCC\x54\x37", 16);
// 4F494156-AED6-4D64-A537-B8A5557BCEEC // Sony 1
const QByteArray EFI_SONY_FILE_SYSTEM_GUID
const UByteArray EFI_SONY_FILE_SYSTEM_GUID
("\x56\x41\x49\x4F\xD6\xAE\x64\x4D\xA5\x37\xB8\xA5\x55\x7B\xCE\xEC", 16);
// Vector of volume GUIDs with FFSv2-compatible files
extern const std::vector<QByteArray> FFSv2Volumes;
extern const std::vector<UByteArray> FFSv2Volumes;
const QByteArray EFI_FIRMWARE_FILE_SYSTEM3_GUID // 5473C07A-3DCB-4DCA-BD6F-1E9689E7349A
const UByteArray EFI_FIRMWARE_FILE_SYSTEM3_GUID // 5473C07A-3DCB-4DCA-BD6F-1E9689E7349A
("\x7A\xC0\x73\x54\xCB\x3D\xCA\x4D\xBD\x6F\x1E\x96\x89\xE7\x34\x9A", 16);
// Vector of volume GUIDs with FFSv3-compatible files
extern const std::vector<QByteArray> FFSv3Volumes;
extern const std::vector<UByteArray> FFSv3Volumes;
// Firmware volume signature
const QByteArray EFI_FV_SIGNATURE("_FVH", 4);
const UByteArray EFI_FV_SIGNATURE("_FVH", 4);
#define EFI_FV_SIGNATURE_OFFSET 0x28
// Firmware volume attributes
@ -338,19 +338,19 @@ extern const UINT8 ffsAlignmentTable[];
#define EFI_FILE_HEADER_INVALID 0x20
// PEI apriori file
const QByteArray EFI_PEI_APRIORI_FILE_GUID
const UByteArray EFI_PEI_APRIORI_FILE_GUID
("\x0A\xCC\x45\x1B\x6A\x15\x8A\x42\xAF\x62\x49\x86\x4D\xA0\xE6\xE6", 16);
// DXE apriori file
const QByteArray EFI_DXE_APRIORI_FILE_GUID
const UByteArray EFI_DXE_APRIORI_FILE_GUID
("\xE7\x0E\x51\xFC\xDC\xFF\xD4\x11\xBD\x41\x00\x80\xC7\x3C\x88\x81", 16);
// Volume top file
const QByteArray EFI_FFS_VOLUME_TOP_FILE_GUID
const UByteArray EFI_FFS_VOLUME_TOP_FILE_GUID
("\x2E\x06\xA0\x1B\x79\xC7\x82\x45\x85\x66\x33\x6A\xE8\xF7\x8F\x09", 16);
// Pad file GUID
const QByteArray EFI_FFS_PAD_FILE_GUID
const UByteArray EFI_FFS_PAD_FILE_GUID
("\x85\x65\x53\xE4\x09\x79\x60\x4A\xB5\xC6\xEC\xDE\xA6\xEB\xFB\x54", 16);
// FFS size conversion routines
@ -445,16 +445,16 @@ typedef struct EFI_GUID_DEFINED_SECTION_APPLE_ {
#define EFI_GUIDED_SECTION_AUTH_STATUS_VALID 0x02
// GUIDs of GUID-defined sections
const QByteArray EFI_GUIDED_SECTION_CRC32 // FC1BCDB0-7D31-49AA-936A-A4600D9DD083
const UByteArray EFI_GUIDED_SECTION_CRC32 // FC1BCDB0-7D31-49AA-936A-A4600D9DD083
("\xB0\xCD\x1B\xFC\x31\x7D\xAA\x49\x93\x6A\xA4\x60\x0D\x9D\xD0\x83", 16);
const QByteArray EFI_GUIDED_SECTION_TIANO // A31280AD-481E-41B6-95E8-127F4C984779
const UByteArray EFI_GUIDED_SECTION_TIANO // A31280AD-481E-41B6-95E8-127F4C984779
("\xAD\x80\x12\xA3\x1E\x48\xB6\x41\x95\xE8\x12\x7F\x4C\x98\x47\x79", 16);
const QByteArray EFI_GUIDED_SECTION_LZMA // EE4E5898-3914-4259-9D6E-DC7BD79403CF
const UByteArray EFI_GUIDED_SECTION_LZMA // EE4E5898-3914-4259-9D6E-DC7BD79403CF
("\x98\x58\x4E\xEE\x14\x39\x59\x42\x9D\x6E\xDC\x7B\xD7\x94\x03\xCF", 16);
const QByteArray EFI_FIRMWARE_CONTENTS_SIGNED_GUID // 0F9D89E8-9259-4F76-A5AF-0C89E34023DF
const UByteArray EFI_FIRMWARE_CONTENTS_SIGNED_GUID // 0F9D89E8-9259-4F76-A5AF-0C89E34023DF
("\xE8\x89\x9D\x0F\x59\x92\x76\x4F\xA5\xAF\x0C\x89\xE3\x40\x23\xDF", 16);
//#define WIN_CERT_TYPE_PKCS_SIGNED_DATA 0x0002
@ -474,7 +474,7 @@ typedef struct WIN_CERTIFICATE_UEFI_GUID_ {
} WIN_CERTIFICATE_UEFI_GUID;
// WIN_CERTIFICATE_UEFI_GUID.CertType
const QByteArray EFI_CERT_TYPE_RSA2048_SHA256_GUID
const UByteArray EFI_CERT_TYPE_RSA2048_SHA256_GUID
("\x14\x74\x71\xA7\x16\xC6\x77\x49\x94\x20\x84\x47\x12\xA7\x35\xBF");
// WIN_CERTIFICATE_UEFI_GUID.CertData

View File

@ -12,22 +12,22 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*/
#include "ffsbuilder.h"
STATUS FfsBuilder::erase(const QModelIndex & index, QByteArray & erased)
USTATUS FfsBuilder::erase(const UModelIndex & index, UByteArray & erased)
{
// Sanity check
if (!index.isValid())
return ERR_INVALID_PARAMETER;
return U_INVALID_PARAMETER;
PARSING_DATA pdata = parsingDataFromQModelIndex(index);
PARSING_DATA pdata = parsingDataFromUModelIndex(index);
erased.fill(pdata.emptyByte);
return ERR_SUCCESS;
return U_SUCCESS;
}
STATUS FfsBuilder::build(const QModelIndex & root, QByteArray & image)
USTATUS FfsBuilder::build(const UModelIndex & root, UByteArray & image)
{
// Sanity check
if (!root.isValid())
return ERR_INVALID_PARAMETER;
return U_INVALID_PARAMETER;
if (model->type(root) == Types::Capsule) {
return buildCapsule(root, image);
@ -41,44 +41,44 @@ STATUS FfsBuilder::build(const QModelIndex & root, QByteArray & image)
}
}
return ERR_NOT_IMPLEMENTED;
return U_NOT_IMPLEMENTED;
}
STATUS FfsBuilder::buildCapsule(const QModelIndex & index, QByteArray & capsule)
USTATUS FfsBuilder::buildCapsule(const UModelIndex & index, UByteArray & capsule)
{
// Sanity check
if (!index.isValid())
return ERR_INVALID_PARAMETER;
return U_INVALID_PARAMETER;
// No action required
if (model->action(index) == Actions::NoAction) {
// Use original item data
capsule = model->header(index).append(model->body(index));
return ERR_SUCCESS;
return U_SUCCESS;
}
// Rebuild or Replace
else if (model->action(index) == Actions::Rebuild
|| model->action(index) == Actions::Replace) {
if (model->rowCount(index)) {
// Clear the supplied QByteArray
// Clear the supplied UByteArray
capsule.clear();
// Right now there is only one capsule image element supported
if (model->rowCount(index) != 1) {
msg(QObject::tr("buildCapsule: building of capsules with %1 elements are not supported, original item data is used").arg(model->rowCount(index)), index);
//msg(UString("buildCapsule: building of capsules with %1 elements are not supported, original item data is used").arg(model->rowCount(index)), index);
// Use original item data
capsule = model->header(index).append(model->body(index));
return ERR_SUCCESS;
return U_SUCCESS;
}
// Build image
QModelIndex imageIndex = index.child(0, 0);
QByteArray imageData;
UModelIndex imageIndex = index.child(0, 0);
UByteArray imageData;
// Check image type
if (model->type(imageIndex) == Types::Image) {
STATUS result = ERR_SUCCESS;
USTATUS result = U_SUCCESS;
if (model->subtype(imageIndex) == Subtypes::IntelImage) {
result = buildIntelImage(imageIndex, imageData);
}
@ -86,20 +86,20 @@ STATUS FfsBuilder::buildCapsule(const QModelIndex & index, QByteArray & capsule)
result = buildRawArea(imageIndex, imageData);
}
else {
msg(QObject::tr("buildCapsule: unexpected item of subtype %1 can't be processed, original item data is used").arg(model->subtype(imageIndex)), imageIndex);
//msg(UString("buildCapsule: unexpected item of subtype %1 can't be processed, original item data is used").arg(model->subtype(imageIndex)), imageIndex);
capsule.append(model->header(imageIndex)).append(model->body(imageIndex));
}
// Check build result
if (result) {
msg(QObject::tr("buildCapsule: building of \"%1\" failed with error \"%2\", original item data is used").arg(model->name(imageIndex)).arg(errorCodeToQString(result)), imageIndex);
//msg(UString("buildCapsule: building of \"%1\" failed with error \"%2\", original item data is used").arg(model->name(imageIndex)).arg(errorCodeToUString(result)), imageIndex);
capsule.append(model->header(imageIndex)).append(model->body(imageIndex));
}
else
capsule.append(imageData);
}
else {
msg(QObject::tr("buildCapsule: unexpected item of type %1 can't be processed, original item data is used").arg(model->type(imageIndex)), imageIndex);
//msg(UString("buildCapsule: unexpected item of type %1 can't be processed, original item data is used").arg(model->type(imageIndex)), imageIndex);
capsule.append(model->header(imageIndex)).append(model->body(imageIndex));
}
@ -107,14 +107,14 @@ STATUS FfsBuilder::buildCapsule(const QModelIndex & index, QByteArray & capsule)
UINT32 newSize = capsule.size();
UINT32 oldSize = model->body(index).size();
if (newSize > oldSize) {
msg(QObject::tr("buildCapsule: new capsule body size %1h (%2) is bigger than the original %3h (%4)")
.hexarg(newSize).arg(newSize).hexarg(oldSize).arg(oldSize),index);
return ERR_INVALID_PARAMETER;
//msg(UString("buildCapsule: new capsule body size %1h (%2) is bigger than the original %3h (%4)")
// .hexarg(newSize).arg(newSize).hexarg(oldSize).arg(oldSize),index);
return U_INVALID_PARAMETER;
}
else if (newSize < oldSize) {
msg(QObject::tr("buildCapsule: new capsule body size %1h (%2) is smaller than the original %3h (%4)")
.hexarg(newSize).arg(newSize).hexarg(oldSize).arg(oldSize), index);
return ERR_INVALID_PARAMETER;
//msg(UString("buildCapsule: new capsule body size %1h (%2) is smaller than the original %3h (%4)")
// .hexarg(newSize).arg(newSize).hexarg(oldSize).arg(oldSize), index);
return U_INVALID_PARAMETER;
}
}
else
@ -122,23 +122,23 @@ STATUS FfsBuilder::buildCapsule(const QModelIndex & index, QByteArray & capsule)
// Build successful, append header
capsule = model->header(index).append(capsule);
return ERR_SUCCESS;
return U_SUCCESS;
}
msg(QObject::tr("buildCapsule: unexpected action \"%1\"").arg(actionTypeToQString(model->action(index))), index);
return ERR_NOT_IMPLEMENTED;
//msg(UString("buildCapsule: unexpected action \"%1\"").arg(actionTypeToQString(model->action(index))), index);
return U_NOT_IMPLEMENTED;
}
STATUS FfsBuilder::buildIntelImage(const QModelIndex & index, QByteArray & intelImage)
USTATUS FfsBuilder::buildIntelImage(const UModelIndex & index, UByteArray & intelImage)
{
// Sanity check
if (!index.isValid())
return ERR_SUCCESS;
return U_SUCCESS;
// No action
if (model->action(index) == Actions::NoAction) {
intelImage = model->header(index).append(model->body(index));
return ERR_SUCCESS;
return U_SUCCESS;
}
// Rebuild
@ -150,7 +150,7 @@ STATUS FfsBuilder::buildIntelImage(const QModelIndex & index, QByteArray & intel
// Process other regions
for (int i = 1; i < model->rowCount(index); i++) {
QModelIndex currentRegion = index.child(i, 0);
UModelIndex currentRegion = index.child(i, 0);
// Skip regions with Remove action
if (model->action(currentRegion) == Actions::Remove)
@ -165,15 +165,15 @@ STATUS FfsBuilder::buildIntelImage(const QModelIndex & index, QByteArray & intel
}
// Check region subtype
STATUS result;
QByteArray region;
USTATUS result;
UByteArray region;
UINT8 regionType = model->subtype(currentRegion);
switch (regionType) {
case Subtypes::BiosRegion:
case Subtypes::PdrRegion:
result = buildRawArea(currentRegion, region);
if (result) {
msg(QObject::tr("buildIntelImage: building of %1 region failed with error \"%2\", original item data is used").arg(regionTypeToQString(regionType)).arg(errorCodeToQString(result)), currentRegion);
//msg(UString("buildIntelImage: building of %1 region failed with error \"%2\", original item data is used").arg(regionTypeToQString(regionType)).arg(errorCodeToQString(result)), currentRegion);
region = model->header(currentRegion).append(model->body(currentRegion));
}
break;
@ -188,8 +188,8 @@ STATUS FfsBuilder::buildIntelImage(const QModelIndex & index, QByteArray & intel
region = model->header(currentRegion).append(model->body(currentRegion));
break;
default:
msg(QObject::tr("buildIntelImage: don't know how to build region of unknown type"), index);
return ERR_UNKNOWN_ITEM_TYPE;
msg(UString("buildIntelImage: don't know how to build region of unknown type"), index);
return U_UNKNOWN_ITEM_TYPE;
}
// Append the resulting region
@ -200,48 +200,48 @@ STATUS FfsBuilder::buildIntelImage(const QModelIndex & index, QByteArray & intel
UINT32 newSize = intelImage.size();
UINT32 oldSize = model->body(index).size();
if (newSize > oldSize) {
msg(QObject::tr("buildIntelImage: new image size %1h (%2) is bigger than the original %3h (%4)")
.hexarg(newSize).arg(newSize).hexarg(oldSize).arg(oldSize), index);
return ERR_INVALID_PARAMETER;
//msg(UString("buildIntelImage: new image size %1h (%2) is bigger than the original %3h (%4)")
// .hexarg(newSize).arg(newSize).hexarg(oldSize).arg(oldSize), index);
return U_INVALID_PARAMETER;
}
else if (newSize < oldSize) {
msg(QObject::tr("buildIntelImage: new image size %1h (%2) is smaller than the original %3h (%4)")
.hexarg(newSize).arg(newSize).hexarg(oldSize).arg(oldSize), index);
return ERR_INVALID_PARAMETER;
//msg(UString("buildIntelImage: new image size %1h (%2) is smaller than the original %3h (%4)")
// .hexarg(newSize).arg(newSize).hexarg(oldSize).arg(oldSize), index);
return U_INVALID_PARAMETER;
}
// Reconstruction successful
return ERR_SUCCESS;
return U_SUCCESS;
}
msg(QObject::tr("buildIntelImage: unexpected action \"%1\"").arg(actionTypeToQString(model->action(index))), index);
return ERR_NOT_IMPLEMENTED;
//msg(UString("buildIntelImage: unexpected action \"%1\"").arg(actionTypeToQString(model->action(index))), index);
return U_NOT_IMPLEMENTED;
}
STATUS FfsBuilder::buildRawArea(const QModelIndex & index, QByteArray & rawArea, bool addHeader)
USTATUS FfsBuilder::buildRawArea(const UModelIndex & index, UByteArray & rawArea, bool addHeader)
{
// Sanity check
if (!index.isValid())
return ERR_INVALID_PARAMETER;
return U_INVALID_PARAMETER;
// No action required
if (model->action(index) == Actions::NoAction) {
rawArea = model->header(index).append(model->body(index));
return ERR_SUCCESS;
return U_SUCCESS;
}
// Rebuild or Replace
else if (model->action(index) == Actions::Rebuild
|| model->action(index) == Actions::Replace) {
if (model->rowCount(index)) {
// Clear the supplied QByteArray
// Clear the supplied UByteArray
rawArea.clear();
// Build children
for (int i = 0; i < model->rowCount(index); i++) {
STATUS result = ERR_SUCCESS;
QModelIndex currentChild = index.child(i, 0);
QByteArray currentData;
USTATUS result = U_SUCCESS;
UModelIndex currentChild = index.child(i, 0);
UByteArray currentData;
// Check child type
if (model->type(currentChild) == Types::Volume) {
result = buildVolume(currentChild, currentData);
@ -250,12 +250,12 @@ STATUS FfsBuilder::buildRawArea(const QModelIndex & index, QByteArray & rawArea,
result = buildPadding(currentChild, currentData);
}
else {
msg(QObject::tr("buildRawArea: unexpected item of type %1 can't be processed, original item data is used").arg(model->type(currentChild)), currentChild);
//msg(UString("buildRawArea: unexpected item of type %1 can't be processed, original item data is used").arg(model->type(currentChild)), currentChild);
currentData = model->header(currentChild).append(model->body(currentChild));
}
// Check build result
if (result) {
msg(QObject::tr("buildRawArea: building of %1 failed with error \"%2\", original item data is used").arg(model->name(currentChild)).arg(errorCodeToQString(result)), currentChild);
//msg(UString("buildRawArea: building of %1 failed with error \"%2\", original item data is used").arg(model->name(currentChild)).arg(errorCodeToQString(result)), currentChild);
currentData = model->header(currentChild).append(model->body(currentChild));
}
// Append current data
@ -266,14 +266,14 @@ STATUS FfsBuilder::buildRawArea(const QModelIndex & index, QByteArray & rawArea,
UINT32 newSize = rawArea.size();
UINT32 oldSize = model->body(index).size();
if (newSize > oldSize) {
msg(QObject::tr("buildRawArea: new area size %1h (%2) is bigger than the original %3h (%4)")
.hexarg(newSize).arg(newSize).hexarg(oldSize).arg(oldSize), index);
return ERR_INVALID_PARAMETER;
//msg(UString("buildRawArea: new area size %1h (%2) is bigger than the original %3h (%4)")
// .hexarg(newSize).arg(newSize).hexarg(oldSize).arg(oldSize), index);
return U_INVALID_PARAMETER;
}
else if (newSize < oldSize) {
msg(QObject::tr("buildRawArea: new area size %1h (%2) is smaller than the original %3h (%4)")
.hexarg(newSize).arg(newSize).hexarg(oldSize).arg(oldSize), index);
return ERR_INVALID_PARAMETER;
//msg(UString("buildRawArea: new area size %1h (%2) is smaller than the original %3h (%4)")
// .hexarg(newSize).arg(newSize).hexarg(oldSize).arg(oldSize), index);
return U_INVALID_PARAMETER;
}
}
else
@ -282,95 +282,95 @@ STATUS FfsBuilder::buildRawArea(const QModelIndex & index, QByteArray & rawArea,
// Build successful, add header if needed
if (addHeader)
rawArea = model->header(index).append(rawArea);
return ERR_SUCCESS;
return U_SUCCESS;
}
msg(QObject::tr("buildRawArea: unexpected action \"%1\"").arg(actionTypeToQString(model->action(index))), index);
return ERR_NOT_IMPLEMENTED;
//msg(UString("buildRawArea: unexpected action \"%1\"").arg(actionTypeToQString(model->action(index))), index);
return U_NOT_IMPLEMENTED;
}
STATUS FfsBuilder::buildPadding(const QModelIndex & index, QByteArray & padding)
USTATUS FfsBuilder::buildPadding(const UModelIndex & index, UByteArray & padding)
{
// Sanity check
if (!index.isValid())
return ERR_INVALID_PARAMETER;
return U_INVALID_PARAMETER;
// No action required
if (model->action(index) == Actions::NoAction) {
padding = model->header(index).append(model->body(index));
return ERR_SUCCESS;
return U_SUCCESS;
}
// Erase
else if (model->action(index) == Actions::Erase) {
padding = model->header(index).append(model->body(index));
if(erase(index, padding))
msg(QObject::tr("buildPadding: erase failed, original item data is used"), index);
return ERR_SUCCESS;
msg(UString("buildPadding: erase failed, original item data is used"), index);
return U_SUCCESS;
}
msg(QObject::tr("buildPadding: unexpected action \"%1\"").arg(actionTypeToQString(model->action(index))), index);
return ERR_NOT_IMPLEMENTED;
//msg(UString("buildPadding: unexpected action \"%1\"").arg(actionTypeToUString(model->action(index))), index);
return U_NOT_IMPLEMENTED;
}
STATUS FfsBuilder::buildNonUefiData(const QModelIndex & index, QByteArray & data)
USTATUS FfsBuilder::buildNonUefiData(const UModelIndex & index, UByteArray & data)
{
// Sanity check
if (!index.isValid())
return ERR_INVALID_PARAMETER;
return U_INVALID_PARAMETER;
// No action required
if (model->action(index) == Actions::NoAction) {
data = model->header(index).append(model->body(index));
return ERR_SUCCESS;
return U_SUCCESS;
}
// Erase
else if (model->action(index) == Actions::Erase) {
data = model->header(index).append(model->body(index));
if (erase(index, data))
msg(QObject::tr("buildNonUefiData: erase failed, original item data is used"), index);
return ERR_SUCCESS;
msg(UString("buildNonUefiData: erase failed, original item data is used"), index);
return U_SUCCESS;
}
msg(QObject::tr("buildNonUefiData: unexpected action \"%1\"").arg(actionTypeToQString(model->action(index))), index);
return ERR_NOT_IMPLEMENTED;
//msg(UString("buildNonUefiData: unexpected action \"%1\"").arg(actionTypeToUString(model->action(index))), index);
return U_NOT_IMPLEMENTED;
}
STATUS FfsBuilder::buildFreeSpace(const QModelIndex & index, QByteArray & freeSpace)
USTATUS FfsBuilder::buildFreeSpace(const UModelIndex & index, UByteArray & freeSpace)
{
// Sanity check
if (!index.isValid())
return ERR_INVALID_PARAMETER;
return U_INVALID_PARAMETER;
// No action required
if (model->action(index) == Actions::NoAction) {
freeSpace = model->header(index).append(model->body(index));
return ERR_SUCCESS;
return U_SUCCESS;
}
msg(QObject::tr("buildFreeSpace: unexpected action \"%1\"").arg(actionTypeToQString(model->action(index))), index);
return ERR_NOT_IMPLEMENTED;
//msg(UString("buildFreeSpace: unexpected action \"%1\"").arg(actionTypeToQString(model->action(index))), index);
return U_NOT_IMPLEMENTED;
}
STATUS FfsBuilder::buildVolume(const QModelIndex & index, QByteArray & volume)
USTATUS FfsBuilder::buildVolume(const UModelIndex & index, UByteArray & volume)
{
return ERR_NOT_IMPLEMENTED;
return U_NOT_IMPLEMENTED;
}
STATUS FfsBuilder::buildPadFile(const QModelIndex & index, QByteArray & padFile)
USTATUS FfsBuilder::buildPadFile(const UModelIndex & index, UByteArray & padFile)
{
return ERR_NOT_IMPLEMENTED;
return U_NOT_IMPLEMENTED;
}
STATUS FfsBuilder::buildFile(const QModelIndex & index, QByteArray & file)
USTATUS FfsBuilder::buildFile(const UModelIndex & index, UByteArray & file)
{
return ERR_NOT_IMPLEMENTED;
return U_NOT_IMPLEMENTED;
}
STATUS FfsBuilder::buildSection(const QModelIndex & index, QByteArray & section)
USTATUS FfsBuilder::buildSection(const UModelIndex & index, UByteArray & section)
{
return ERR_NOT_IMPLEMENTED;
return U_NOT_IMPLEMENTED;
}

View File

@ -16,11 +16,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <vector>
#include <QObject>
#include <QByteArray>
#include <QString>
#include <QModelIndex>
#include "ubytearray.h"
#include "ustring.h"
#include "basetypes.h"
#include "treemodel.h"
#include "descriptor.h"
@ -33,31 +30,31 @@ public:
FfsBuilder(const TreeModel * treeModel) : model(treeModel) {}
~FfsBuilder() {}
std::vector<std::pair<QString, QModelIndex> > getMessages() const { return messagesVector; }
std::vector<std::pair<UString, UModelIndex> > getMessages() const { return messagesVector; }
void clearMessages() { messagesVector.clear(); }
STATUS build(const QModelIndex & root, QByteArray & image);
USTATUS build(const UModelIndex & root, UByteArray & image);
private:
const TreeModel* model;
std::vector<std::pair<QString, QModelIndex> > messagesVector;
void msg(const QString & message, const QModelIndex &index = QModelIndex()) {
messagesVector.push_back(std::pair<QString, QModelIndex>(message, index));
std::vector<std::pair<UString, UModelIndex> > messagesVector;
void msg(const UString & message, const UModelIndex &index = UModelIndex()) {
messagesVector.push_back(std::pair<UString, UModelIndex>(message, index));
}
STATUS buildCapsule(const QModelIndex & index, QByteArray & capsule);
STATUS buildIntelImage(const QModelIndex & index, QByteArray & intelImage);
STATUS buildRawArea(const QModelIndex & index, QByteArray & rawArea, bool addHeader = true);
STATUS buildPadding(const QModelIndex & index, QByteArray & padding);
STATUS buildVolume(const QModelIndex & index, QByteArray & volume);
STATUS buildNonUefiData(const QModelIndex & index, QByteArray & data);
STATUS buildFreeSpace(const QModelIndex & index, QByteArray & freeSpace);
STATUS buildPadFile(const QModelIndex & index, QByteArray & padFile);
STATUS buildFile(const QModelIndex & index, QByteArray & file);
STATUS buildSection(const QModelIndex & index, QByteArray & section);
USTATUS buildCapsule(const UModelIndex & index, UByteArray & capsule);
USTATUS buildIntelImage(const UModelIndex & index, UByteArray & intelImage);
USTATUS buildRawArea(const UModelIndex & index, UByteArray & rawArea, bool addHeader = true);
USTATUS buildPadding(const UModelIndex & index, UByteArray & padding);
USTATUS buildVolume(const UModelIndex & index, UByteArray & volume);
USTATUS buildNonUefiData(const UModelIndex & index, UByteArray & data);
USTATUS buildFreeSpace(const UModelIndex & index, UByteArray & freeSpace);
USTATUS buildPadFile(const UModelIndex & index, UByteArray & padFile);
USTATUS buildFile(const UModelIndex & index, UByteArray & file);
USTATUS buildSection(const UModelIndex & index, UByteArray & section);
// Utility functions
STATUS erase(const QModelIndex & index, QByteArray & erased);
USTATUS erase(const UModelIndex & index, UByteArray & erased);
};
#endif // FFSBUILDER_H

View File

@ -13,24 +13,24 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "ffsops.h"
STATUS FfsOperations::extract(const QModelIndex & index, QString & name, QByteArray & extracted, const UINT8 mode)
USTATUS FfsOperations::extract(const UModelIndex & index, UString & name, UByteArray & extracted, const UINT8 mode)
{
// Sanity check
if (!index.isValid())
return ERR_INVALID_PARAMETER;
return U_INVALID_PARAMETER;
// Get data from parsing data
PARSING_DATA pdata = parsingDataFromQModelIndex(index);
PARSING_DATA pdata = parsingDataFromUModelIndex(index);
// Construct a name for extracted data
QString itemName = model->name(index);
QString itemText = model->text(index);
UString itemName = model->name(index);
UString itemText = model->text(index);
// Default name
name = itemName.replace(' ', '_').replace('/', '_').replace('-', '_');
switch (model->type(index)) {
case Types::Volume: if (pdata.volume.hasExtendedHeader) name = guidToQString(pdata.volume.extendedHeaderGuid).replace('-', '_'); break;
case Types::Volume: if (pdata.volume.hasExtendedHeader) name = guidToUString(pdata.volume.extendedHeaderGuid).replace('-', '_'); break;
case Types::NvarEntry:
case Types::VssEntry:
case Types::FsysEntry:
@ -39,11 +39,11 @@ STATUS FfsOperations::extract(const QModelIndex & index, QString & name, QByteAr
case Types::File: name = itemText.isEmpty() ? itemName : itemText.replace(' ', '_').replace('-', '_'); break;
case Types::Section: {
// Get parent file name
QModelIndex fileIndex = model->findParentOfType(index, Types::File);
QString fileText = model->text(fileIndex);
UModelIndex fileIndex = model->findParentOfType(index, Types::File);
UString fileText = model->text(fileIndex);
name = fileText.isEmpty() ? model->name(fileIndex) : fileText.replace(' ', '_').replace('-', '_');
// Append section subtype name
name += QChar('_') + itemName.replace(' ', '_');
name += '_' + itemName.replace(' ', '_');
} break;
}
@ -67,9 +67,9 @@ STATUS FfsOperations::extract(const QModelIndex & index, QString & name, QByteAr
extracted.clear();
// There is no need to redo decompression, we can use child items
for (int i = 0; i < model->rowCount(index); i++) {
QModelIndex childIndex = index.child(i, 0);
UModelIndex childIndex = index.child(i, 0);
// Ensure 4-byte alignment of current section
extracted.append(QByteArray('\x00', ALIGN4((UINT32)extracted.size()) - (UINT32)extracted.size()));
extracted.append(UByteArray('\x00', ALIGN4((UINT32)extracted.size()) - (UINT32)extracted.size()));
// Add current section header, body and tail
extracted.append(model->header(childIndex));
extracted.append(model->body(childIndex));
@ -77,49 +77,49 @@ STATUS FfsOperations::extract(const QModelIndex & index, QString & name, QByteAr
}
}
else
return ERR_UNKNOWN_EXTRACT_MODE;
return U_UNKNOWN_EXTRACT_MODE;
return ERR_SUCCESS;
return U_SUCCESS;
}
STATUS FfsOperations::replace(const QModelIndex & index, const QString & data, const UINT8 mode)
USTATUS FfsOperations::replace(const UModelIndex & index, const UString & data, const UINT8 mode)
{
// Sanity check
if (!index.isValid())
return ERR_INVALID_PARAMETER;
return U_INVALID_PARAMETER;
// Get data from parsing data
//PARSING_DATA pdata = parsingDataFromQModelIndex(index);
if (mode == REPLACE_MODE_AS_IS) {
return ERR_NOT_IMPLEMENTED;
return U_NOT_IMPLEMENTED;
}
else if (mode == REPLACE_MODE_BODY) {
return ERR_NOT_IMPLEMENTED;
return U_NOT_IMPLEMENTED;
}
else
return ERR_UNKNOWN_REPLACE_MODE;
return U_UNKNOWN_REPLACE_MODE;
return ERR_NOT_IMPLEMENTED;
return U_NOT_IMPLEMENTED;
}
STATUS FfsOperations::remove(const QModelIndex & index)
USTATUS FfsOperations::remove(const UModelIndex & index)
{
// Sanity check
if (!index.isValid())
return ERR_INVALID_PARAMETER;
return U_INVALID_PARAMETER;
// Set remove action
model->setAction(index, Actions::Remove);
return ERR_SUCCESS;
return U_SUCCESS;
}
STATUS FfsOperations::rebuild(const QModelIndex & index)
USTATUS FfsOperations::rebuild(const UModelIndex & index)
{
// Sanity check
if (!index.isValid())
return ERR_INVALID_PARAMETER;
return U_INVALID_PARAMETER;
// On insert action, set insert action for children
//if (action == Actions::Insert)
@ -130,10 +130,10 @@ STATUS FfsOperations::rebuild(const QModelIndex & index)
model->setAction(index, Actions::Rebuild);
// Rebuild parent, if it has no action now
QModelIndex parent = index.parent();
UModelIndex parent = index.parent();
if (parent.isValid() && model->type(parent) != Types::Root
&& model->action(parent) == Actions::NoAction)
rebuild(parent);
return ERR_SUCCESS;
return U_SUCCESS;
}

View File

@ -16,11 +16,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <vector>
#include <QObject>
#include <QByteArray>
#include <QString>
#include <QModelIndex>
#include "ubytearray.h"
#include "ustring.h"
#include "basetypes.h"
#include "treemodel.h"
#include "ffs.h"
@ -33,21 +30,21 @@ public:
FfsOperations(TreeModel * treeModel) : model(treeModel) {}
~FfsOperations() {};
std::vector<std::pair<QString, QModelIndex> > getMessages() const { return messagesVector; }
std::vector<std::pair<UString, UModelIndex> > getMessages() const { return messagesVector; }
void clearMessages() { messagesVector.clear(); }
STATUS extract(const QModelIndex & index, QString & name, QByteArray & extracted, const UINT8 mode);
STATUS replace(const QModelIndex & index, const QString & data, const UINT8 mode);
USTATUS extract(const UModelIndex & index, UString & name, UByteArray & extracted, const UINT8 mode);
USTATUS replace(const UModelIndex & index, const UString & data, const UINT8 mode);
STATUS remove(const QModelIndex & index);
STATUS rebuild(const QModelIndex & index);
USTATUS remove(const UModelIndex & index);
USTATUS rebuild(const UModelIndex & index);
private:
TreeModel* model;
std::vector<std::pair<QString, QModelIndex> > messagesVector;
std::vector<std::pair<UString, UModelIndex> > messagesVector;
void msg(const QString & message, const QModelIndex &index = QModelIndex()) {
messagesVector.push_back(std::pair<QString, QModelIndex>(message, index));
void msg(const UString & message, const UModelIndex &index = UModelIndex()) {
messagesVector.push_back(std::pair<UString, UModelIndex>(message, index));
}
};

File diff suppressed because it is too large Load Diff

View File

@ -15,10 +15,8 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <vector>
#include <QObject>
#include <QModelIndex>
#include <QByteArray>
#include "ustring.h"
#include "ubytearray.h"
#include "basetypes.h"
#include "treemodel.h"
#include "utility.h"
@ -43,95 +41,95 @@ public:
~FfsParser() {}
// Returns messages
std::vector<std::pair<QString, QModelIndex> > getMessages() const { return messagesVector; }
std::vector<std::pair<UString, UModelIndex> > getMessages() const { return messagesVector; }
// Clears messages
void clearMessages() { messagesVector.clear(); }
// Firmware image parsing
STATUS parse(const QByteArray &buffer);
USTATUS parse(const UByteArray &buffer);
// Retuns index of the last VTF after parsing is done
const QModelIndex getLastVtf() {return lastVtf;};
const UModelIndex getLastVtf() {return lastVtf;};
private:
TreeModel *model;
std::vector<std::pair<QString, QModelIndex> > messagesVector;
void msg(const QString & message, const QModelIndex &index = QModelIndex()) {
messagesVector.push_back(std::pair<QString, QModelIndex>(message, index));
std::vector<std::pair<UString, UModelIndex> > messagesVector;
void msg(const UString message, const UModelIndex index = UModelIndex()) {
messagesVector.push_back(std::pair<UString, UModelIndex>(message, index));
};
QModelIndex lastVtf;
UModelIndex lastVtf;
UINT32 capsuleOffsetFixup;
STATUS parseRawArea(const QModelIndex & index);
STATUS parseVolumeHeader(const QByteArray & volume, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
STATUS parseVolumeBody(const QModelIndex & index);
STATUS parseFileHeader(const QByteArray & file, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
STATUS parseFileBody(const QModelIndex & index);
STATUS parseSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index, const bool preparse = false);
STATUS parseSectionBody(const QModelIndex & index);
USTATUS parseRawArea(const UModelIndex & index);
USTATUS parseVolumeHeader(const UByteArray & volume, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseVolumeBody(const UModelIndex & index);
USTATUS parseFileHeader(const UByteArray & file, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseFileBody(const UModelIndex & index);
USTATUS parseSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool preparse = false);
USTATUS parseSectionBody(const UModelIndex & index);
STATUS parseIntelImage(const QByteArray & intelImage, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & root);
STATUS parseGbeRegion(const QByteArray & gbe, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
STATUS parseMeRegion(const QByteArray & me, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
STATUS parseBiosRegion(const QByteArray & bios, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
STATUS parsePdrRegion(const QByteArray & pdr, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
STATUS parseGeneralRegion(const UINT8 subtype, const QByteArray & region, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
USTATUS parseIntelImage(const UByteArray & intelImage, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & root);
USTATUS parseGbeRegion(const UByteArray & gbe, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseMeRegion(const UByteArray & me, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseBiosRegion(const UByteArray & bios, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parsePdrRegion(const UByteArray & pdr, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseGeneralRegion(const UINT8 subtype, const UByteArray & region, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index);
STATUS parsePadFileBody(const QModelIndex & index);
STATUS parseVolumeNonUefiData(const QByteArray & data, const UINT32 parentOffset, const QModelIndex & index);
USTATUS parsePadFileBody(const UModelIndex & index);
USTATUS parseVolumeNonUefiData(const UByteArray & data, const UINT32 parentOffset, const UModelIndex & index);
STATUS parseSections(const QByteArray & sections, const QModelIndex & index, const bool preparse = false);
STATUS parseCommonSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index, const bool preparse);
STATUS parseCompressedSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index, const bool preparse);
STATUS parseGuidedSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index, const bool preparse);
STATUS parseFreeformGuidedSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index, const bool preparse);
STATUS parseVersionSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index, const bool preparse);
STATUS parsePostcodeSectionHeader(const QByteArray & section, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index, const bool preparse);
USTATUS parseSections(const UByteArray & sections, const UModelIndex & index, const bool preparse = false);
USTATUS parseCommonSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool preparse);
USTATUS parseCompressedSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool preparse);
USTATUS parseGuidedSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool preparse);
USTATUS parseFreeformGuidedSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool preparse);
USTATUS parseVersionSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool preparse);
USTATUS parsePostcodeSectionHeader(const UByteArray & section, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index, const bool preparse);
STATUS parseCompressedSectionBody(const QModelIndex & index);
STATUS parseGuidedSectionBody(const QModelIndex & index);
STATUS parseVersionSectionBody(const QModelIndex & index);
STATUS parseDepexSectionBody(const QModelIndex & index);
STATUS parseUiSectionBody(const QModelIndex & index);
STATUS parseRawSectionBody(const QModelIndex & index);
STATUS parsePeImageSectionBody(const QModelIndex & index);
STATUS parseTeImageSectionBody(const QModelIndex & index);
USTATUS parseCompressedSectionBody(const UModelIndex & index);
USTATUS parseGuidedSectionBody(const UModelIndex & index);
USTATUS parseVersionSectionBody(const UModelIndex & index);
USTATUS parseDepexSectionBody(const UModelIndex & index);
USTATUS parseUiSectionBody(const UModelIndex & index);
USTATUS parseRawSectionBody(const UModelIndex & index);
USTATUS parsePeImageSectionBody(const UModelIndex & index);
USTATUS parseTeImageSectionBody(const UModelIndex & index);
UINT8 getPaddingType(const QByteArray & padding);
STATUS parseAprioriRawSection(const QByteArray & body, QString & parsed);
STATUS findNextVolume(const QModelIndex & index, const QByteArray & bios, const UINT32 parentOffset, const UINT32 volumeOffset, UINT32 & nextVolumeOffset);
STATUS getVolumeSize(const QByteArray & bios, const UINT32 volumeOffset, UINT32 & volumeSize, UINT32 & bmVolumeSize);
UINT32 getFileSize(const QByteArray & volume, const UINT32 fileOffset, const UINT8 ffsVersion);
UINT32 getSectionSize(const QByteArray & file, const UINT32 sectionOffset, const UINT8 ffsVersion);
UINT8 getPaddingType(const UByteArray & padding);
USTATUS parseAprioriRawSection(const UByteArray & body, UString & parsed);
USTATUS findNextVolume(const UModelIndex & index, const UByteArray & bios, const UINT32 parentOffset, const UINT32 volumeOffset, UINT32 & nextVolumeOffset);
USTATUS getVolumeSize(const UByteArray & bios, const UINT32 volumeOffset, UINT32 & volumeSize, UINT32 & bmVolumeSize);
UINT32 getFileSize(const UByteArray & volume, const UINT32 fileOffset, const UINT8 ffsVersion);
UINT32 getSectionSize(const UByteArray & file, const UINT32 sectionOffset, const UINT8 ffsVersion);
STATUS performFirstPass(const QByteArray & imageFile, QModelIndex & index);
STATUS performSecondPass(const QModelIndex & index);
STATUS addOffsetsRecursive(const QModelIndex & index);
STATUS addMemoryAddressesRecursive(const QModelIndex & index, const UINT32 diff);
USTATUS performFirstPass(const UByteArray & imageFile, UModelIndex & index);
USTATUS performSecondPass(const UModelIndex & index);
USTATUS addOffsetsRecursive(const UModelIndex & index);
USTATUS addMemoryAddressesRecursive(const UModelIndex & index, const UINT32 diff);
// NVRAM parsing
STATUS parseNvramVolumeBody(const QModelIndex & index);
STATUS findNextStore(const QModelIndex & index, const QByteArray & volume, const UINT32 parentOffset, const UINT32 storeOffset, UINT32 & nextStoreOffset);
STATUS getStoreSize(const QByteArray & data, const UINT32 storeOffset, UINT32 & storeSize);
STATUS parseStoreHeader(const QByteArray & store, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
USTATUS parseNvramVolumeBody(const UModelIndex & index);
USTATUS findNextStore(const UModelIndex & index, const UByteArray & volume, const UINT32 parentOffset, const UINT32 storeOffset, UINT32 & nextStoreOffset);
USTATUS getStoreSize(const UByteArray & data, const UINT32 storeOffset, UINT32 & storeSize);
USTATUS parseStoreHeader(const UByteArray & store, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index);
STATUS parseNvarStore(const QModelIndex & index);
STATUS parseVssStoreHeader(const QByteArray & store, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
STATUS parseFtwStoreHeader(const QByteArray & store, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
STATUS parseFdcStoreHeader(const QByteArray & store, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
STATUS parseFsysStoreHeader(const QByteArray & store, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
STATUS parseEvsaStoreHeader(const QByteArray & store, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
STATUS parseFlashMapStoreHeader(const QByteArray & store, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
STATUS parseCmdbStoreHeader(const QByteArray & store, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
STATUS parseSlicPubkeyHeader(const QByteArray & store, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
STATUS parseSlicMarkerHeader(const QByteArray & store, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
STATUS parseIntelMicrocodeHeader(const QByteArray & store, const UINT32 parentOffset, const QModelIndex & parent, QModelIndex & index);
USTATUS parseNvarStore(const UModelIndex & index);
USTATUS parseVssStoreHeader(const UByteArray & store, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseFtwStoreHeader(const UByteArray & store, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseFdcStoreHeader(const UByteArray & store, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseFsysStoreHeader(const UByteArray & store, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseEvsaStoreHeader(const UByteArray & store, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseFlashMapStoreHeader(const UByteArray & store, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseCmdbStoreHeader(const UByteArray & store, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseSlicPubkeyHeader(const UByteArray & store, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseSlicMarkerHeader(const UByteArray & store, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index);
USTATUS parseIntelMicrocodeHeader(const UByteArray & store, const UINT32 parentOffset, const UModelIndex & parent, UModelIndex & index);
STATUS parseVssStoreBody(const QModelIndex & index);
STATUS parseFsysStoreBody(const QModelIndex & index);
STATUS parseEvsaStoreBody(const QModelIndex & index);
STATUS parseFlashMapBody(const QModelIndex & index);
USTATUS parseVssStoreBody(const UModelIndex & index);
USTATUS parseFsysStoreBody(const UModelIndex & index);
USTATUS parseEvsaStoreBody(const UModelIndex & index);
USTATUS parseFlashMapBody(const UModelIndex & index);
};
#endif // FFSPARSER_H

View File

@ -13,53 +13,49 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "ffsreport.h"
std::vector<QString> FfsReport::generate()
std::vector<UString> FfsReport::generate()
{
std::vector<QString> report;
std::vector<UString> report;
// Check model pointer
if (!model) {
report.push_back(QObject::tr("ERROR: Invalid model pointer provided."));
report.push_back(UString("ERROR: Invalid model pointer provided"));
return report;
}
// Check root index to be valid
QModelIndex root = model->index(0,0);
UModelIndex root = model->index(0,0);
if (!root.isValid()) {
report.push_back(QObject::tr("ERROR: Model root index is invalid."));
report.push_back(UString("ERROR: Model root index is invalid"));
return report;
}
// Generate report recursive
report.push_back(QObject::tr(" Type | Subtype | Size | CRC32 | Name "));
STATUS result = generateRecursive(report, root);
report.push_back(UString(" Type | Subtype | Size | CRC32 | Name "));
USTATUS result = generateRecursive(report, root);
if (result) {
report.push_back(QObject::tr("ERROR: generateRecursive returned %1.")
.arg(errorCodeToQString(result)));
report.push_back(UString("ERROR: generateRecursive returned ") + errorCodeToUString(result));
}
return report;
}
STATUS FfsReport::generateRecursive(std::vector<QString> & report, QModelIndex index, UINT32 level)
USTATUS FfsReport::generateRecursive(std::vector<UString> & report, UModelIndex index, UINT32 level)
{
if (!index.isValid())
return ERR_SUCCESS; //Nothing to report for invalid index
return U_SUCCESS; //Nothing to report for invalid index
// Calculate item CRC32
QByteArray data = model->header(index) + model->body(index) + model->tail(index);
UByteArray data = model->header(index) + model->body(index) + model->tail(index);
UINT32 crc = crc32(0, (const UINT8*)data.constData(), data.size());
// Information on current item
QString text = model->text(index);
report.push_back(QObject::tr("%1 | %2 | %3 | %4 | %5 %6 %7")
.arg(itemTypeToQString(model->type(index)), 16, QChar(' '))
.arg(itemSubtypeToQString(model->type(index), model->subtype(index)), 24, QChar(' '))
.hexarg2(data.size(), 8)
.hexarg2(crc, 8)
.arg(' ', level, QChar('-'))
.arg(model->name(index))
.arg(text.isEmpty() ? "" : text.prepend("| "))
UString text = model->text(index);
report.push_back(
UString(" ") + itemTypeToUString(model->type(index)).leftJustified(16)
+ UString("| ") + itemSubtypeToUString(model->type(index), model->subtype(index)).leftJustified(22)
+ usprintf("| %08X | %08X | ", data.size(), crc)
+ UString('-', level) + UString(" ") + model->name(index) + (text.isEmpty() ? UString("") : UString(" | ") + text)
);
// Information on child items
@ -67,5 +63,5 @@ STATUS FfsReport::generateRecursive(std::vector<QString> & report, QModelIndex i
generateRecursive(report, index.child(i,0), level + 1);
}
return ERR_SUCCESS;
return U_SUCCESS;
}

View File

@ -16,11 +16,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <vector>
#include <QObject>
#include <QByteArray>
#include <QString>
#include <QModelIndex>
#include "../common/ubytearray.h"
#include "../common/ustring.h"
#include "basetypes.h"
#include "treemodel.h"
#include "ffs.h"
@ -33,12 +30,12 @@ public:
FfsReport(TreeModel * treeModel) : model(treeModel) {}
~FfsReport() {};
std::vector<QString> generate();
std::vector<UString> generate();
private:
TreeModel* model;
STATUS generateRecursive(std::vector<QString> & report, QModelIndex index, UINT32 level = 0);
USTATUS generateRecursive(std::vector<UString> & report, UModelIndex index, UINT32 level = 0);
};

View File

@ -13,8 +13,8 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#ifndef FIT_H
#define FIT_H
#include <QByteArray>
#include "basetypes.h"
#include "ubytearray.h"
// Make sure we use right packing rules
#pragma pack(push, 1)
@ -37,7 +37,7 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#define FIT_HEADER_VERSION 0x0100
#define FIT_MICROCODE_VERSION 0x0100
const QByteArray FIT_SIGNATURE
const UByteArray FIT_SIGNATURE
("\x5F\x46\x49\x54\x5F\x20\x20\x20", 8);
typedef struct FIT_ENTRY_ {

View File

@ -11,7 +11,7 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*/
#include "fitparser.h"
STATUS FitParser::parse(const QModelIndex & index, const QModelIndex & lastVtfIndex)
USTATUS FitParser::parse(const UModelIndex & index, const UModelIndex & lastVtfIndex)
{
// Check sanity
if (!index.isValid() || !lastVtfIndex.isValid())
@ -21,15 +21,15 @@ STATUS FitParser::parse(const QModelIndex & index, const QModelIndex & lastVtfIn
lastVtf = lastVtfIndex;
// Search for FIT
QModelIndex fitIndex;
UModelIndex fitIndex;
UINT32 fitOffset;
STATUS result = findFitRecursive(index, fitIndex, fitOffset);
USTATUS result = findFitRecursive(index, fitIndex, fitOffset);
if (result)
return result;
// FIT not found
if (!fitIndex.isValid())
return ERR_SUCCESS;
return U_SUCCESS;
// Explicitly set the item as fixed
model->setFixed(index, true);
@ -41,27 +41,27 @@ STATUS FitParser::parse(const QModelIndex & index, const QModelIndex & lastVtfIn
UINT32 fitSize = (fitHeader->Size & 0xFFFFFF) << 4;
if (fitHeader->Type & 0x80) {
// Calculate FIT entry checksum
QByteArray tempFIT = model->body(fitIndex).mid(fitOffset, fitSize);
UByteArray tempFIT = model->body(fitIndex).mid(fitOffset, fitSize);
FIT_ENTRY* tempFitHeader = (FIT_ENTRY*)tempFIT.data();
tempFitHeader->Checksum = 0;
UINT8 calculated = calculateChecksum8((const UINT8*)tempFitHeader, fitSize);
if (calculated != fitHeader->Checksum) {
msg(QObject::tr("Invalid FIT table checksum %1h, should be %2h").hexarg2(fitHeader->Checksum, 2).hexarg2(calculated, 2), fitIndex);
msg(usprintf("Invalid FIT table checksum %02Xh, should be %02Xh", fitHeader->Checksum, calculated), fitIndex);
}
}
// Check fit header type
if ((fitHeader->Type & 0x7F) != FIT_TYPE_HEADER) {
msg(QObject::tr("Invalid FIT header type"), fitIndex);
msg(("Invalid FIT header type"), fitIndex);
}
// Add FIT header to fitTable
std::vector<QString> currentStrings;
currentStrings.push_back(QObject::tr("_FIT_ "));
currentStrings.push_back(QObject::tr("%1").hexarg2(fitSize, 8));
currentStrings.push_back(QObject::tr("%1").hexarg2(fitHeader->Version, 4));
currentStrings.push_back(fitEntryTypeToQString(fitHeader->Type));
currentStrings.push_back(QObject::tr("%1").hexarg2(fitHeader->Checksum, 2));
std::vector<UString> currentStrings;
currentStrings.push_back(UString("_FIT_ "));
currentStrings.push_back(usprintf("%08X", fitSize));
currentStrings.push_back(usprintf("%04X", fitHeader->Version));
currentStrings.push_back(fitEntryTypeToUString(fitHeader->Type));
currentStrings.push_back(usprintf("%02X", fitHeader->Checksum));
fitTable.push_back(currentStrings);
// Process all other entries
@ -73,7 +73,7 @@ STATUS FitParser::parse(const QModelIndex & index, const QModelIndex & lastVtfIn
// Check entry type
switch (currentEntry->Type & 0x7F) {
case FIT_TYPE_HEADER:
msg(QObject::tr("Second FIT header found, the table is damaged"), fitIndex);
msg(UString("Second FIT header found, the table is damaged"), fitIndex);
break;
case FIT_TYPE_EMPTY:
@ -93,52 +93,52 @@ STATUS FitParser::parse(const QModelIndex & index, const QModelIndex & lastVtfIn
}
// Add entry to fitTable
currentStrings.push_back(QObject::tr("%1").hexarg2(currentEntry->Address, 16));
currentStrings.push_back(QObject::tr("%1").hexarg2(currentEntry->Size, 8));
currentStrings.push_back(QObject::tr("%1").hexarg2(currentEntry->Version, 4));
currentStrings.push_back(fitEntryTypeToQString(currentEntry->Type));
currentStrings.push_back(QObject::tr("%1").hexarg2(currentEntry->Checksum, 2));
currentStrings.push_back(usprintf("%016X",currentEntry->Address));
currentStrings.push_back(usprintf("%08X", currentEntry->Size));
currentStrings.push_back(usprintf("%04X", currentEntry->Version));
currentStrings.push_back(fitEntryTypeToUString(currentEntry->Type));
currentStrings.push_back(usprintf("%02X", currentEntry->Checksum));
fitTable.push_back(currentStrings);
}
if (msgModifiedImageMayNotWork)
msg(QObject::tr("Opened image may not work after any modification"));
msg(("Opened image may not work after any modification"));
return ERR_SUCCESS;
return U_SUCCESS;
}
QString FitParser::fitEntryTypeToQString(UINT8 type)
UString FitParser::fitEntryTypeToUString(UINT8 type)
{
switch (type & 0x7F) {
case FIT_TYPE_HEADER: return QObject::tr("Header ");
case FIT_TYPE_MICROCODE: return QObject::tr("Microcode ");
case FIT_TYPE_BIOS_AC_MODULE: return QObject::tr("BIOS ACM ");
case FIT_TYPE_BIOS_INIT_MODULE: return QObject::tr("BIOS Init ");
case FIT_TYPE_TPM_POLICY: return QObject::tr("TPM Policy ");
case FIT_TYPE_BIOS_POLICY_DATA: return QObject::tr("BIOS Policy Data ");
case FIT_TYPE_TXT_CONF_POLICY: return QObject::tr("TXT Configuration Policy");
case FIT_TYPE_AC_KEY_MANIFEST: return QObject::tr("BootGuard Key Manifest ");
case FIT_TYPE_AC_BOOT_POLICY: return QObject::tr("BootGuard Boot Policy ");
case FIT_TYPE_EMPTY: return QObject::tr("Empty ");
default: return QObject::tr("Unknown ");
case FIT_TYPE_HEADER: return ("Header ");
case FIT_TYPE_MICROCODE: return ("Microcode ");
case FIT_TYPE_BIOS_AC_MODULE: return ("BIOS ACM ");
case FIT_TYPE_BIOS_INIT_MODULE: return ("BIOS Init ");
case FIT_TYPE_TPM_POLICY: return ("TPM Policy ");
case FIT_TYPE_BIOS_POLICY_DATA: return ("BIOS Policy Data ");
case FIT_TYPE_TXT_CONF_POLICY: return ("TXT Configuration Policy");
case FIT_TYPE_AC_KEY_MANIFEST: return ("BootGuard Key Manifest ");
case FIT_TYPE_AC_BOOT_POLICY: return ("BootGuard Boot Policy ");
case FIT_TYPE_EMPTY: return ("Empty ");
default: return ("Unknown ");
}
}
STATUS FitParser::findFitRecursive(const QModelIndex & index, QModelIndex & found, UINT32 & fitOffset)
USTATUS FitParser::findFitRecursive(const UModelIndex & index, UModelIndex & found, UINT32 & fitOffset)
{
// Sanity check
if (!index.isValid())
return ERR_SUCCESS;
return U_SUCCESS;
// Process child items
for (int i = 0; i < model->rowCount(index); i++) {
findFitRecursive(index.child(i, 0), found, fitOffset);
if (found.isValid())
return ERR_SUCCESS;
return U_SUCCESS;
}
// Get parsing data for the current item
PARSING_DATA pdata = parsingDataFromQModelIndex(index);
PARSING_DATA pdata = parsingDataFromUModelIndex(index);
// Check for all FIT signatures in item's body
for (INT32 offset = model->body(index).indexOf(FIT_SIGNATURE);
@ -148,16 +148,16 @@ STATUS FitParser::findFitRecursive(const QModelIndex & index, QModelIndex & foun
UINT32 fitAddress = pdata.address + model->header(index).size() + (UINT32)offset;
// Check FIT address to be in the last VTF
QByteArray lastVtfBody = model->body(lastVtf);
UByteArray lastVtfBody = model->body(lastVtf);
if (*(const UINT32*)(lastVtfBody.constData() + lastVtfBody.size() - FIT_POINTER_OFFSET) == fitAddress) {
found = index;
fitOffset = offset;
msg(QObject::tr("Real FIT table found at physical address %1h").hexarg(fitAddress), found);
return ERR_SUCCESS;
msg(usprintf("Real FIT table found at physical address %Xh", fitAddress), found);
return U_SUCCESS;
}
else if (model->rowCount(index) == 0) // Show messages only to leaf items
msg(QObject::tr("FIT table candidate found, but not referenced from the last VTF"), index);
msg(("FIT table candidate found, but not referenced from the last VTF"), index);
}
return ERR_SUCCESS;
return U_SUCCESS;
}

View File

@ -15,10 +15,8 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <vector>
#include <QObject>
#include <QModelIndex>
#include <QByteArray>
#include "ustring.h"
#include "ubytearray.h"
#include "treemodel.h"
#include "utility.h"
#include "parsingdata.h"
@ -36,25 +34,25 @@ public:
~FitParser() {}
// Returns messages
std::vector<std::pair<QString, QModelIndex> > getMessages() const { return messagesVector; };
std::vector<std::pair<UString, UModelIndex> > getMessages() const { return messagesVector; };
// Clears messages
void clearMessages() { messagesVector.clear(); }
STATUS parse(const QModelIndex & index, const QModelIndex & lastVtf);
std::vector<std::vector<QString> > getFitTable() const { return fitTable; }
USTATUS parse(const UModelIndex & index, const UModelIndex & lastVtf);
std::vector<std::vector<UString> > getFitTable() const { return fitTable; }
private:
TreeModel *model;
std::vector<std::pair<QString, QModelIndex> > messagesVector;
QModelIndex lastVtf;
std::vector<std::vector<QString> > fitTable;
std::vector<std::pair<UString, UModelIndex> > messagesVector;
UModelIndex lastVtf;
std::vector<std::vector<UString> > fitTable;
STATUS findFitRecursive(const QModelIndex & index, QModelIndex & found, UINT32 & fitOffset);
QString fitEntryTypeToQString(UINT8 type);
USTATUS findFitRecursive(const UModelIndex & index, UModelIndex & found, UINT32 & fitOffset);
UString fitEntryTypeToUString(UINT8 type);
// Message helper
void msg(const QString & message, const QModelIndex &index = QModelIndex()) {
messagesVector.push_back(std::pair<QString, QModelIndex>(message, index));
void msg(const UString & message, const UModelIndex &index = UModelIndex()) {
messagesVector.push_back(std::pair<UString, UModelIndex>(message, index));
}
};

View File

@ -18,8 +18,8 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
// Make sure we use right packing rules
#pragma pack(push, 1)
const QByteArray ME_VERSION_SIGNATURE("\x24\x4D\x41\x4E", 4); //$MAN
const QByteArray ME_VERSION_SIGNATURE2("\x24\x4D\x4E\x32", 4); //$MN2
const UByteArray ME_VERSION_SIGNATURE("\x24\x4D\x41\x4E", 4); //$MAN
const UByteArray ME_VERSION_SIGNATURE2("\x24\x4D\x4E\x32", 4); //$MN2
typedef struct ME_VERSION_ {
UINT32 signature;

View File

@ -11,100 +11,103 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*/
#include <QObject>
#include "nvram.h"
QString nvarAttributesToQString(const UINT8 attributes)
UString nvarAttributesToUString(const UINT8 attributes)
{
if (attributes == 0x00 || attributes == 0xFF)
return QString();
return UString();
QString str;
if (attributes & NVRAM_NVAR_ENTRY_RUNTIME) str += QObject::tr(", Runtime");
if (attributes & NVRAM_NVAR_ENTRY_ASCII_NAME) str += QObject::tr(", AsciiName");
if (attributes & NVRAM_NVAR_ENTRY_GUID) str += QObject::tr(", Guid");
if (attributes & NVRAM_NVAR_ENTRY_DATA_ONLY) str += QObject::tr(", DataOnly");
if (attributes & NVRAM_NVAR_ENTRY_EXT_HEADER) str += QObject::tr(", ExtHeader");
if (attributes & NVRAM_NVAR_ENTRY_HW_ERROR_RECORD) str += QObject::tr(", HwErrorRecord");
if (attributes & NVRAM_NVAR_ENTRY_AUTH_WRITE) str += QObject::tr(", AuthWrite");
if (attributes & NVRAM_NVAR_ENTRY_VALID) str += QObject::tr(", Valid");
UString str;
if (attributes & NVRAM_NVAR_ENTRY_RUNTIME) str += UString(", Runtime");
if (attributes & NVRAM_NVAR_ENTRY_ASCII_NAME) str += UString(", AsciiName");
if (attributes & NVRAM_NVAR_ENTRY_GUID) str += UString(", Guid");
if (attributes & NVRAM_NVAR_ENTRY_DATA_ONLY) str += UString(", DataOnly");
if (attributes & NVRAM_NVAR_ENTRY_EXT_HEADER) str += UString(", ExtHeader");
if (attributes & NVRAM_NVAR_ENTRY_HW_ERROR_RECORD) str += UString(", HwErrorRecord");
if (attributes & NVRAM_NVAR_ENTRY_AUTH_WRITE) str += UString(", AuthWrite");
if (attributes & NVRAM_NVAR_ENTRY_VALID) str += UString(", Valid");
return str.mid(2); // Remove first comma and space
str.remove(0, 2); // Remove first comma and space
return str;
}
QString nvarExtendedAttributesToQString(const UINT8 attributes)
UString nvarExtendedAttributesToUString(const UINT8 attributes)
{
QString str;
if (attributes & NVRAM_NVAR_ENTRY_EXT_CHECKSUM) str += QObject::tr(", Checksum");
if (attributes & NVRAM_NVAR_ENTRY_EXT_AUTH_WRITE) str += QObject::tr(", AuthWrite");
if (attributes & NVRAM_NVAR_ENTRY_EXT_TIME_BASED) str += QObject::tr(", TimeBasedAuthWrite");
if (attributes & NVRAM_NVAR_ENTRY_EXT_UNKNOWN_MASK) str += QObject::tr(", Unknown");
UString str;
if (attributes & NVRAM_NVAR_ENTRY_EXT_CHECKSUM) str += UString(", Checksum");
if (attributes & NVRAM_NVAR_ENTRY_EXT_AUTH_WRITE) str += UString(", AuthWrite");
if (attributes & NVRAM_NVAR_ENTRY_EXT_TIME_BASED) str += UString(", TimeBasedAuthWrite");
if (attributes & NVRAM_NVAR_ENTRY_EXT_UNKNOWN_MASK) str += UString(", Unknown");
return str.mid(2); // Remove first comma and space
str.remove(0, 2); // Remove first comma and space
return str;
}
extern QString vssAttributesToQString(const UINT32 attributes)
extern UString vssAttributesToUString(const UINT32 attributes)
{
QString str;
if (attributes & NVRAM_VSS_VARIABLE_NON_VOLATILE) str += QObject::tr(", NonVolatile");
if (attributes & NVRAM_VSS_VARIABLE_BOOTSERVICE_ACCESS) str += QObject::tr(", BootService");
if (attributes & NVRAM_VSS_VARIABLE_RUNTIME_ACCESS) str += QObject::tr(", Runtime");
if (attributes & NVRAM_VSS_VARIABLE_HARDWARE_ERROR_RECORD) str += QObject::tr(", HwErrorRecord");
if (attributes & NVRAM_VSS_VARIABLE_AUTHENTICATED_WRITE_ACCESS) str += QObject::tr(", AuthWrite");
if (attributes & NVRAM_VSS_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) str += QObject::tr(", TimeBasedAuthWrite");
if (attributes & NVRAM_VSS_VARIABLE_APPEND_WRITE) str += QObject::tr(", AppendWrite");
if (attributes & NVRAM_VSS_VARIABLE_APPLE_DATA_CHECKSUM) str += QObject::tr(", AppleChecksum");
if (attributes & NVRAM_VSS_VARIABLE_UNKNOWN_MASK) str += QObject::tr(", Unknown");
UString str;
if (attributes & NVRAM_VSS_VARIABLE_NON_VOLATILE) str += UString(", NonVolatile");
if (attributes & NVRAM_VSS_VARIABLE_BOOTSERVICE_ACCESS) str += UString(", BootService");
if (attributes & NVRAM_VSS_VARIABLE_RUNTIME_ACCESS) str += UString(", Runtime");
if (attributes & NVRAM_VSS_VARIABLE_HARDWARE_ERROR_RECORD) str += UString(", HwErrorRecord");
if (attributes & NVRAM_VSS_VARIABLE_AUTHENTICATED_WRITE_ACCESS) str += UString(", AuthWrite");
if (attributes & NVRAM_VSS_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) str += UString(", TimeBasedAuthWrite");
if (attributes & NVRAM_VSS_VARIABLE_APPEND_WRITE) str += UString(", AppendWrite");
if (attributes & NVRAM_VSS_VARIABLE_APPLE_DATA_CHECKSUM) str += UString(", AppleChecksum");
if (attributes & NVRAM_VSS_VARIABLE_UNKNOWN_MASK) str += UString(", Unknown");
return str.mid(2); // Remove first comma and space
str.remove(0, 2); // Remove first comma and space
return str;
}
QString evsaAttributesToQString(const UINT32 attributes)
UString evsaAttributesToUString(const UINT32 attributes)
{
QString str;
if (attributes & NVRAM_EVSA_DATA_NON_VOLATILE) str += QObject::tr(", NonVolatile");
if (attributes & NVRAM_EVSA_DATA_BOOTSERVICE_ACCESS) str += QObject::tr(", BootService");
if (attributes & NVRAM_EVSA_DATA_RUNTIME_ACCESS) str += QObject::tr(", Runtime");
if (attributes & NVRAM_EVSA_DATA_HARDWARE_ERROR_RECORD) str += QObject::tr(", HwErrorRecord");
if (attributes & NVRAM_EVSA_DATA_AUTHENTICATED_WRITE_ACCESS) str += QObject::tr(", AuthWrite");
if (attributes & NVRAM_EVSA_DATA_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) str += QObject::tr(", TimeBasedAuthWrite");
if (attributes & NVRAM_EVSA_DATA_APPEND_WRITE) str += QObject::tr(", AppendWrite");
if (attributes & NVRAM_EVSA_DATA_EXTENDED_HEADER) str += QObject::tr(", ExtendedHeader");
if (attributes & NVRAM_EVSA_DATA_UNKNOWN_MASK) str += QObject::tr(", Unknown");
UString str;
if (attributes & NVRAM_EVSA_DATA_NON_VOLATILE) str += UString(", NonVolatile");
if (attributes & NVRAM_EVSA_DATA_BOOTSERVICE_ACCESS) str += UString(", BootService");
if (attributes & NVRAM_EVSA_DATA_RUNTIME_ACCESS) str += UString(", Runtime");
if (attributes & NVRAM_EVSA_DATA_HARDWARE_ERROR_RECORD) str += UString(", HwErrorRecord");
if (attributes & NVRAM_EVSA_DATA_AUTHENTICATED_WRITE_ACCESS) str += UString(", AuthWrite");
if (attributes & NVRAM_EVSA_DATA_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) str += UString(", TimeBasedAuthWrite");
if (attributes & NVRAM_EVSA_DATA_APPEND_WRITE) str += UString(", AppendWrite");
if (attributes & NVRAM_EVSA_DATA_EXTENDED_HEADER) str += UString(", ExtendedHeader");
if (attributes & NVRAM_EVSA_DATA_UNKNOWN_MASK) str += UString(", Unknown");
return str.mid(2); // Remove first comma and space
str.remove(0, 2); // Remove first comma and space
return str;
}
QString efiTimeToQString(const EFI_TIME & time)
UString efiTimeToUString(const EFI_TIME & time)
{
return QObject::tr("%1-%2-%3T%4:%5:%6.%7")
.arg(time.Year, 4, 10, QLatin1Char('0'))
.arg(time.Month, 2, 10, QLatin1Char('0'))
.arg(time.Day, 2, 10, QLatin1Char('0'))
.arg(time.Hour, 2, 10, QLatin1Char('0'))
.arg(time.Minute, 2, 10, QLatin1Char('0'))
.arg(time.Second, 2, 10, QLatin1Char('0'))
.arg(time.Nanosecond);
return usprintf("%04u-%02u-%02uT%02u:%02u:%02u.%u",
time.Year,
time.Month,
time.Day,
time.Hour,
time.Minute,
time.Second,
time.Nanosecond);
}
QString flashMapGuidToQString(const EFI_GUID & guid)
UString flashMapGuidToUString(const EFI_GUID & guid)
{
const QByteArray baGuid((const char*)&guid, sizeof(EFI_GUID));
if (baGuid == NVRAM_PHOENIX_FLASH_MAP_VOLUME_HEADER) return QObject::tr("Volume header");
if (baGuid == NVRAM_PHOENIX_FLASH_MAP_MICROCODES_GUID) return QObject::tr("Microcodes");
if (baGuid == NVRAM_PHOENIX_FLASH_MAP_CMDB_GUID) return QObject::tr("CMDB");
const UByteArray baGuid((const char*)&guid, sizeof(EFI_GUID));
if (baGuid == NVRAM_PHOENIX_FLASH_MAP_VOLUME_HEADER) return UString("Volume header");
if (baGuid == NVRAM_PHOENIX_FLASH_MAP_MICROCODES_GUID) return UString("Microcodes");
if (baGuid == NVRAM_PHOENIX_FLASH_MAP_CMDB_GUID) return UString("CMDB");
if (baGuid == NVRAM_PHOENIX_FLASH_MAP_PUBKEY1_GUID
|| baGuid == NVRAM_PHOENIX_FLASH_MAP_PUBKEY2_GUID) return QObject::tr("SLIC pubkey");
|| baGuid == NVRAM_PHOENIX_FLASH_MAP_PUBKEY2_GUID) return UString("SLIC pubkey");
if (baGuid == NVRAM_PHOENIX_FLASH_MAP_MARKER1_GUID
|| baGuid == NVRAM_PHOENIX_FLASH_MAP_MARKER2_GUID) return QObject::tr("SLIC marker");
|| baGuid == NVRAM_PHOENIX_FLASH_MAP_MARKER2_GUID) return UString("SLIC marker");
if (baGuid == NVRAM_PHOENIX_FLASH_MAP_EVSA1_GUID
|| baGuid == NVRAM_PHOENIX_FLASH_MAP_EVSA2_GUID
|| baGuid == NVRAM_PHOENIX_FLASH_MAP_EVSA3_GUID
|| baGuid == NVRAM_PHOENIX_FLASH_MAP_EVSA4_GUID
|| baGuid == NVRAM_PHOENIX_FLASH_MAP_EVSA5_GUID
|| baGuid == NVRAM_PHOENIX_FLASH_MAP_EVSA6_GUID
|| baGuid == NVRAM_PHOENIX_FLASH_MAP_EVSA7_GUID) return QObject::tr("EVSA store");
if (baGuid == NVRAM_PHOENIX_FLASH_MAP_SELF_GUID) return QObject::tr("Flash map");
return QString();
|| baGuid == NVRAM_PHOENIX_FLASH_MAP_EVSA7_GUID) return UString("EVSA store");
if (baGuid == NVRAM_PHOENIX_FLASH_MAP_SELF_GUID) return UString("Flash map");
return UString();
}

View File

@ -15,8 +15,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#ifndef NVRAM_H
#define NVRAM_H
#include <QByteArray>
#include <QString>
#include "ubytearray.h"
#include "ustring.h"
#include "basetypes.h"
// Make sure we use right packing rules
@ -27,16 +27,16 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
//
// CEF5B9A3-476D-497F-9FDC-E98143E0422C
const QByteArray NVRAM_NVAR_STORE_FILE_GUID
const UByteArray NVRAM_NVAR_STORE_FILE_GUID
("\xA3\xB9\xF5\xCE\x6D\x47\x7F\x49\x9F\xDC\xE9\x81\x43\xE0\x42\x2C", 16);
// 9221315B-30BB-46B5-813E-1B1BF4712BD3
const QByteArray NVRAM_NVAR_EXTERNAL_DEFAULTS_FILE_GUID
const UByteArray NVRAM_NVAR_EXTERNAL_DEFAULTS_FILE_GUID
("\x5B\x31\x21\x92\xBB\x30\xB5\x46\x81\x3E\x1B\x1B\xF4\x71\x2B\xD3", 16);
extern QString nvarAttributesToQString(const UINT8 attributes);
extern QString nvarExtendedAttributesToQString(const UINT8 attributes);
extern QString efiTimeToQString(const EFI_TIME & time);
extern UString nvarAttributesToUString(const UINT8 attributes);
extern UString nvarExtendedAttributesToUString(const UINT8 attributes);
extern UString efiTimeToUString(const EFI_TIME & time);
typedef struct NVAR_ENTRY_HEADER_ {
UINT32 Signature; // NVAR
@ -68,11 +68,11 @@ typedef struct NVAR_ENTRY_HEADER_ {
//
// FFF12B8D-7696-4C8B-A985-2747075B4F50
const QByteArray NVRAM_MAIN_STORE_VOLUME_GUID
const UByteArray NVRAM_MAIN_STORE_VOLUME_GUID
("\x8D\x2B\xF1\xFF\x96\x76\x8B\x4C\xA9\x85\x27\x47\x07\x5B\x4F\x50", 16);
// 00504624-8A59-4EEB-BD0F-6B36E96128E0
const QByteArray NVRAM_ADDITIONAL_STORE_VOLUME_GUID
const UByteArray NVRAM_ADDITIONAL_STORE_VOLUME_GUID
("\x24\x46\x50\x00\x59\x8A\xEB\x4E\xBD\x0F\x6B\x36\xE9\x61\x28\xE0", 16);
#define NVRAM_VSS_STORE_SIGNATURE 0x53535624 // $VSS
@ -156,7 +156,7 @@ typedef struct VSS_AUTH_VARIABLE_HEADER_ {
#define NVRAM_VSS_VARIABLE_APPLE_DATA_CHECKSUM 0x80000000
#define NVRAM_VSS_VARIABLE_UNKNOWN_MASK 0x7FFFFF80
extern QString vssAttributesToQString(const UINT32 attributes);
extern UString vssAttributesToUString(const UINT32 attributes);
//
// _FDC region
@ -179,7 +179,7 @@ typedef struct FDC_VOLUME_HEADER_ {
#define EFI_FAULT_TOLERANT_WORKING_BLOCK_INVALID 0x2
// 9E58292B-7C68-497D-0ACE6500FD9F1B95
const QByteArray EDKII_WORKING_BLOCK_SIGNATURE_GUID
const UByteArray EDKII_WORKING_BLOCK_SIGNATURE_GUID
("\x2B\x29\x58\x9E\x68\x7C\x7D\x49\x0A\xCE\x65\x00\xFD\x9F\x1B\x95", 16);
#define NVRAM_MAIN_STORE_VOLUME_GUID_DATA1 0xFFF12B8D
@ -292,7 +292,7 @@ typedef struct EVSA_DATA_ENTRY_EXTENDED_ {
//UINT8 Data[];
} EVSA_DATA_ENTRY_EXTENDED;
extern QString evsaAttributesToQString(const UINT32 attributes);
extern UString evsaAttributesToUString(const UINT32 attributes);
//
// Phoenix SCT Flash Map
@ -302,7 +302,7 @@ extern QString evsaAttributesToQString(const UINT32 attributes);
#define NVRAM_PHOENIX_FLASH_MAP_SIGNATURE_LENGTH 10
// _FLASH_MAP
const QByteArray NVRAM_PHOENIX_FLASH_MAP_SIGNATURE
const UByteArray NVRAM_PHOENIX_FLASH_MAP_SIGNATURE
("\x5F\x46\x4C\x41\x53\x48\x5F\x4D\x41\x50", 10);
typedef struct PHOENIX_FLASH_MAP_HEADER_ {
@ -323,66 +323,66 @@ typedef struct PHOENIX_FLASH_MAP_ENTRY_ {
#define NVRAM_PHOENIX_FLASH_MAP_ENTRY_TYPE_VOLUME 0x0000
#define NVRAM_PHOENIX_FLASH_MAP_ENTRY_TYPE_DATA_BLOCK 0x0001
extern QString flashMapGuidToQString(const EFI_GUID & guid);
extern UString flashMapGuidToUString(const EFI_GUID & guid);
// B091E7D2-05A0-4198-94F0-74B7B8C55459
const QByteArray NVRAM_PHOENIX_FLASH_MAP_VOLUME_HEADER
const UByteArray NVRAM_PHOENIX_FLASH_MAP_VOLUME_HEADER
("\xD2\xE7\x91\xB0\xA0\x05\x98\x41\x94\xF0\x74\xB7\xB8\xC5\x54\x59", 16);
// FD3F690E-B4B0-4D68-89DB-19A1A3318F90
const QByteArray NVRAM_PHOENIX_FLASH_MAP_MICROCODES_GUID
const UByteArray NVRAM_PHOENIX_FLASH_MAP_MICROCODES_GUID
("\x0E\x69\x3F\xFD\xB0\xB4\x68\x4D\x89\xDB\x19\xA1\xA3\x31\x8F\x90", 16);
// 46310243-7B03-4132-BE44-2243FACA7CDD
const QByteArray NVRAM_PHOENIX_FLASH_MAP_CMDB_GUID
const UByteArray NVRAM_PHOENIX_FLASH_MAP_CMDB_GUID
("\x43\x02\x31\x46\x03\x7B\x32\x41\xBE\x44\x22\x43\xFA\xCA\x7C\xDD", 16);
// 1B2C4952-D778-4B64-BDA1-15A36F5FA545
const QByteArray NVRAM_PHOENIX_FLASH_MAP_PUBKEY1_GUID
const UByteArray NVRAM_PHOENIX_FLASH_MAP_PUBKEY1_GUID
("\x52\x49\x2C\x1B\x78\xD7\x64\x4B\xBD\xA1\x15\xA3\x6F\x5F\xA5\x45", 16);
// 127C1C4E-9135-46E3-B006-F9808B0559A5
const QByteArray NVRAM_PHOENIX_FLASH_MAP_MARKER1_GUID
const UByteArray NVRAM_PHOENIX_FLASH_MAP_MARKER1_GUID
("\x4E\x1C\x7C\x12\x35\x91\xE3\x46\xB0\x06\xF9\x80\x8B\x05\x59\xA5", 16);
// 7CE75114-8272-45AF-B536-761BD38852CE
const QByteArray NVRAM_PHOENIX_FLASH_MAP_PUBKEY2_GUID
const UByteArray NVRAM_PHOENIX_FLASH_MAP_PUBKEY2_GUID
("\x14\x51\xE7\x7C\x72\x82\xAF\x45\xB5\x36\x76\x1B\xD3\x88\x52\xCE", 16);
// 071A3DBE-CFF4-4B73-83F0-598C13DCFDD5
const QByteArray NVRAM_PHOENIX_FLASH_MAP_MARKER2_GUID
const UByteArray NVRAM_PHOENIX_FLASH_MAP_MARKER2_GUID
("\xBE\x3D\x1A\x07\xF4\xCF\x73\x4B\x83\xF0\x59\x8C\x13\xDC\xFD\xD5", 16);
// FACFB110-7BFD-4EFB-873E-88B6B23B97EA
const QByteArray NVRAM_PHOENIX_FLASH_MAP_EVSA1_GUID
const UByteArray NVRAM_PHOENIX_FLASH_MAP_EVSA1_GUID
("\x10\xB1\xCF\xFA\xFD\x7B\xFB\x4E\x87\x3E\x88\xB6\xB2\x3B\x97\xEA", 16);
// E68DC11A-A5F4-4AC3-AA2E-29E298BFF645
const QByteArray NVRAM_PHOENIX_FLASH_MAP_EVSA2_GUID
const UByteArray NVRAM_PHOENIX_FLASH_MAP_EVSA2_GUID
("\x1A\xC1\x8D\xE6\xF4\xA5\xC3\x4A\xAA\x2E\x29\xE2\x98\xBF\xF6\x45", 16);
// 4B3828AE-0ACE-45B6-8CDB-DAFC28BBF8C5
const QByteArray NVRAM_PHOENIX_FLASH_MAP_EVSA3_GUID
const UByteArray NVRAM_PHOENIX_FLASH_MAP_EVSA3_GUID
("\xAE\x28\x38\x4B\xCE\x0A\xB6\x45\x8C\xDB\xDA\xFC\x28\xBB\xF8\xC5", 16);
// C22E6B8A-8159-49A3-B353-E84B79DF19C0
const QByteArray NVRAM_PHOENIX_FLASH_MAP_EVSA4_GUID
const UByteArray NVRAM_PHOENIX_FLASH_MAP_EVSA4_GUID
("\x8A\x6B\x2E\xC2\x59\x81\xA3\x49\xB3\x53\xE8\x4B\x79\xDF\x19\xC0", 16);
// B6B5FAB9-75C4-4AAE-8314-7FFFA7156EAA
const QByteArray NVRAM_PHOENIX_FLASH_MAP_EVSA5_GUID
const UByteArray NVRAM_PHOENIX_FLASH_MAP_EVSA5_GUID
("\xB9\xFA\xB5\xB6\xC4\x75\xAE\x4A\x83\x14\x7F\xFF\xA7\x15\x6E\xAA", 16);
// 919B9699-8DD0-4376-AA0B-0E54CCA47D8F
const QByteArray NVRAM_PHOENIX_FLASH_MAP_EVSA6_GUID
const UByteArray NVRAM_PHOENIX_FLASH_MAP_EVSA6_GUID
("\x99\x96\x9B\x91\xD0\x8D\x76\x43\xAA\x0B\x0E\x54\xCC\xA4\x7D\x8F", 16);
// 58A90A52-929F-44F8-AC35-A7E1AB18AC91
const QByteArray NVRAM_PHOENIX_FLASH_MAP_EVSA7_GUID
const UByteArray NVRAM_PHOENIX_FLASH_MAP_EVSA7_GUID
("\x52\x0A\xA9\x58\x9F\x92\xF8\x44\xAC\x35\xA7\xE1\xAB\x18\xAC\x91", 16);
// 8CB71915-531F-4AF5-82BF-A09140817BAA
const QByteArray NVRAM_PHOENIX_FLASH_MAP_SELF_GUID
const UByteArray NVRAM_PHOENIX_FLASH_MAP_SELF_GUID
("\x15\x19\xB7\x8C\x1F\x53\xF5\x4A\x82\xBF\xA0\x91\x40\x81\x7B\xAA", 16);
//

View File

@ -11,27 +11,25 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*/
#include <QObject>
#include "peimage.h"
QString machineTypeToQString(UINT16 machineType)
UString machineTypeToUString(UINT16 machineType)
{
switch (machineType) {
case EFI_IMAGE_FILE_MACHINE_AMD64: return QObject::tr("x86-64");
case EFI_IMAGE_FILE_MACHINE_ARM: return QObject::tr("ARM");
case EFI_IMAGE_FILE_MACHINE_ARMNT: return QObject::tr("ARMv7");
case EFI_IMAGE_FILE_MACHINE_APPLE_ARM: return QObject::tr("Apple ARM");
case EFI_IMAGE_FILE_MACHINE_AARCH64: return QObject::tr("AARCH64");
case EFI_IMAGE_FILE_MACHINE_EBC: return QObject::tr("EBC");
case EFI_IMAGE_FILE_MACHINE_I386: return QObject::tr("x86");
case EFI_IMAGE_FILE_MACHINE_IA64: return QObject::tr("IA64");
case EFI_IMAGE_FILE_MACHINE_POWERPC: return QObject::tr("PowerPC");
case EFI_IMAGE_FILE_MACHINE_POWERPCFP: return QObject::tr("PowerPC FP");
case EFI_IMAGE_FILE_MACHINE_THUMB: return QObject::tr("ARM Thumb");
case EFI_IMAGE_FILE_MACHINE_RISCV32: return QObject::tr("RISC-V 32-bit");
case EFI_IMAGE_FILE_MACHINE_RISCV64: return QObject::tr("RISC-V 64-bit");
case EFI_IMAGE_FILE_MACHINE_RISCV128: return QObject::tr("RISC-V 128-bit");
default: return QObject::tr("Unknown %1h").hexarg2(machineType, 4);
case EFI_IMAGE_FILE_MACHINE_AMD64: return UString("x86-64");
case EFI_IMAGE_FILE_MACHINE_ARM: return UString("ARM");
case EFI_IMAGE_FILE_MACHINE_ARMNT: return UString("ARMv7");
case EFI_IMAGE_FILE_MACHINE_APPLE_ARM: return UString("Apple ARM");
case EFI_IMAGE_FILE_MACHINE_AARCH64: return UString("AARCH64");
case EFI_IMAGE_FILE_MACHINE_EBC: return UString("EBC");
case EFI_IMAGE_FILE_MACHINE_I386: return UString("x86");
case EFI_IMAGE_FILE_MACHINE_IA64: return UString("IA64");
case EFI_IMAGE_FILE_MACHINE_POWERPC: return UString("PowerPC");
case EFI_IMAGE_FILE_MACHINE_POWERPCFP: return UString("PowerPC FP");
case EFI_IMAGE_FILE_MACHINE_THUMB: return UString("ARM Thumb");
case EFI_IMAGE_FILE_MACHINE_RISCV32: return UString("RISC-V 32-bit");
case EFI_IMAGE_FILE_MACHINE_RISCV64: return UString("RISC-V 64-bit");
case EFI_IMAGE_FILE_MACHINE_RISCV128: return UString("RISC-V 128-bit");
default: return usprintf("Unknown (%04Xh)", machineType);
}
}

View File

@ -16,10 +16,10 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#ifndef PEIMAGE_H
#define PEIMAGE_H
#include <QString>
#include "ustring.h"
#include "basetypes.h"
extern QString machineTypeToQString(UINT16 machineType);
extern UString machineTypeToUString(UINT16 machineType);
// Make sure we use right packing rules
#pragma pack(push, 1)
@ -49,6 +49,7 @@ extern QString machineTypeToQString(UINT16 machineType);
#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_RISCV128 0x5128 // RISC-V 128-bit
//
// EXE file formats
//
@ -471,6 +472,7 @@ typedef struct {
#define EFI_IMAGE_REL_BASED_RISCV_LO12I 0x0007
#define EFI_IMAGE_REL_BASED_RISCV_LO12S 0x0008
//
// Based relocation format
//

View File

@ -11,14 +11,13 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*/
#include <QObject>
#include "treeitem.h"
#include "types.h"
TreeItem::TreeItem(const UINT8 type, const UINT8 subtype,
const QString & name, const QString & text, const QString & info,
const QByteArray & header, const QByteArray & body, const QByteArray & tail,
const BOOLEAN fixed, const BOOLEAN compressed, const QByteArray & parsingData,
const UString & name, const UString & text, const UString & info,
const UByteArray & header, const UByteArray & body, const UByteArray & tail,
const bool fixed, const bool compressed, const UByteArray & parsingData,
TreeItem *parent) :
itemAction(Actions::NoAction),
itemType(type),
@ -34,50 +33,61 @@ TreeItem::TreeItem(const UINT8 type, const UINT8 subtype,
itemCompressed(compressed),
parentItem(parent)
{
setFixed(fixed);
}
TreeItem::~TreeItem() {
std::list<TreeItem*>::iterator begin = childItems.begin();
while (begin != childItems.end()) {
delete *begin;
++begin;
}
}
UINT8 TreeItem::insertChildBefore(TreeItem *item, TreeItem *newItem)
{
int index = childItems.indexOf(item);
if (index == -1)
return ERR_ITEM_NOT_FOUND;
childItems.insert(index, newItem);
return ERR_SUCCESS;
std::list<TreeItem*>::iterator found = std::find(std::begin(childItems), std::end(childItems), item);
if (found == std::end(childItems))
return U_ITEM_NOT_FOUND;
childItems.insert(found, newItem);
return U_SUCCESS;
}
UINT8 TreeItem::insertChildAfter(TreeItem *item, TreeItem *newItem)
{
int index = childItems.indexOf(item);
if (index == -1)
return ERR_ITEM_NOT_FOUND;
childItems.insert(index + 1, newItem);
return ERR_SUCCESS;
std::list<TreeItem*>::iterator found = std::find(std::begin(childItems), std::end(childItems), item);
if (found == std::end(childItems))
return U_ITEM_NOT_FOUND;
childItems.insert(++found, newItem);
return U_SUCCESS;
}
QVariant TreeItem::data(int column) const
UString TreeItem::data(int column) const
{
switch (column)
{
case 0: // Name
return itemName;
case 1: // Action
return actionTypeToQString(itemAction);
return actionTypeToUString(itemAction);
case 2: // Type
return itemTypeToQString(itemType);
return itemTypeToUString(itemType);
case 3: // Subtype
return itemSubtypeToQString(itemType, itemSubtype);
return itemSubtypeToUString(itemType, itemSubtype);
case 4: // Text
return itemText;
default:
return QVariant();
return UString();
}
}
int TreeItem::row() const
{
if (parentItem)
return parentItem->childItems.indexOf(const_cast<TreeItem*>(this));
if (parentItem) {
std::list<TreeItem*>::const_iterator iter = parentItem->childItems.cbegin();
for (int i = 0; i < (int)parentItem->childItems.size(); ++i, ++iter) {
if (const_cast<TreeItem*>(this) == *iter)
return i;
}
}
return 0;
}

View File

@ -14,39 +14,38 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#ifndef TREEITEM_H
#define TREEITEM_H
#include <QByteArray>
#include <QList>
#include <QString>
#include <QVariant>
#include <list>
#include "ubytearray.h"
#include "ustring.h"
#include "basetypes.h"
class TreeItem
{
public:
TreeItem(const UINT8 type, const UINT8 subtype, const QString &name, const QString &text, const QString &info,
const QByteArray & header, const QByteArray & body, const QByteArray & tail,
const BOOLEAN fixed, const BOOLEAN compressed, const QByteArray & parsingData,
TreeItem(const UINT8 type, const UINT8 subtype, const UString &name, const UString &text, const UString &info,
const UByteArray & header, const UByteArray & body, const UByteArray & tail,
const bool fixed, const bool compressed, const UByteArray & parsingData,
TreeItem *parent = 0);
~TreeItem() { qDeleteAll(childItems); }
~TreeItem(); // Non-trivial implementation in CPP file
// Operations with items
void appendChild(TreeItem *item) { childItems.append(item); }
void prependChild(TreeItem *item) { childItems.prepend(item); };
void appendChild(TreeItem *item) { childItems.push_back(item); }
void prependChild(TreeItem *item) { childItems.push_front(item); };
UINT8 insertChildBefore(TreeItem *item, TreeItem *newItem); // Non-trivial implementation in CPP file
UINT8 insertChildAfter(TreeItem *item, TreeItem *newItem); // Non-trivial implementation in CPP file
// Model support operations
TreeItem *child(int row) { return childItems.value(row, NULL); }
int childCount() const {return childItems.count(); }
TreeItem *child(int row) { return *std::next(childItems.begin(), row); }
int childCount() const {return childItems.size(); }
int columnCount() const { return 5; }
QVariant data(int column) const; // Non-trivial implementation in CPP file
UString data(int column) const; // Non-trivial implementation in CPP file
int row() const; // Non-trivial implementation in CPP file
TreeItem *parent() { return parentItem; }
// Reading operations for item parameters
QString name() const { return itemName; }
void setName(const QString &text) { itemName = text; }
UString name() const { return itemName; }
void setName(const UString &text) { itemName = text; }
UINT8 type() const { return itemType; }
void setType(const UINT8 type) { itemType = type; }
@ -54,47 +53,47 @@ public:
UINT8 subtype() const { return itemSubtype; }
void setSubtype(const UINT8 subtype) { itemSubtype = subtype; }
QString text() const { return itemText; }
void setText(const QString &text) { itemText = text; }
UString text() const { return itemText; }
void setText(const UString &text) { itemText = text; }
QByteArray header() const { return itemHeader; }
UByteArray header() const { return itemHeader; }
bool hasEmptyHeader() const { return itemHeader.isEmpty(); }
QByteArray body() const { return itemBody; };
UByteArray body() const { return itemBody; };
bool hasEmptyBody() const { return itemBody.isEmpty(); }
QByteArray tail() const { return itemTail; };
UByteArray tail() const { return itemTail; };
bool hasEmptyTail() const { return itemTail.isEmpty(); }
QByteArray parsingData() const { return itemParsingData; }
UByteArray parsingData() const { return itemParsingData; }
bool hasEmptyParsingData() const { return itemParsingData.isEmpty(); }
void setParsingData(const QByteArray & data) { itemParsingData = data; }
void setParsingData(const UByteArray & data) { itemParsingData = data; }
QString info() const { return itemInfo; }
void addInfo(const QString &info, const BOOLEAN append) { if (append) itemInfo.append(info); else itemInfo.prepend(info); }
void setInfo(const QString &info) { itemInfo = info; }
UString info() const { return itemInfo; }
void addInfo(const UString &info, const bool append) { if (append) itemInfo += info; else itemInfo = info + itemInfo; }
void setInfo(const UString &info) { itemInfo = info; }
UINT8 action() const {return itemAction; }
void setAction(const UINT8 action) { itemAction = action; }
BOOLEAN fixed() const { return itemFixed; }
bool fixed() const { return itemFixed; }
void setFixed(const bool fixed) { itemFixed = fixed; }
BOOLEAN compressed() const { return itemCompressed; }
bool compressed() const { return itemCompressed; }
void setCompressed(const bool compressed) { itemCompressed = compressed; }
private:
QList<TreeItem*> childItems;
std::list<TreeItem*> childItems;
UINT8 itemAction;
UINT8 itemType;
UINT8 itemSubtype;
QString itemName;
QString itemText;
QString itemInfo;
QByteArray itemHeader;
QByteArray itemBody;
QByteArray itemTail;
QByteArray itemParsingData;
UString itemName;
UString itemText;
UString itemInfo;
UByteArray itemHeader;
UByteArray itemBody;
UByteArray itemTail;
UByteArray itemParsingData;
bool itemFixed;
bool itemCompressed;
TreeItem* parentItem;

View File

@ -14,26 +14,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "treeitem.h"
#include "treemodel.h"
TreeModel::TreeModel(QObject *parent)
: QAbstractItemModel(parent)
{
rootItem = new TreeItem(Types::Root, 0, QString(), QString(), QString(), QByteArray(), QByteArray(), QByteArray(), TRUE, FALSE, QByteArray());
}
TreeModel::~TreeModel()
{
delete rootItem;
}
int TreeModel::columnCount(const QModelIndex &parent) const
{
if (parent.isValid())
return static_cast<TreeItem*>(parent.internalPointer())->columnCount();
else
return rootItem->columnCount();
}
QVariant TreeModel::data(const QModelIndex &index, int role) const
#if defined(QT_CORE_LIB)
QVariant TreeModel::data(const UModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
@ -44,12 +26,12 @@ QVariant TreeModel::data(const QModelIndex &index, int role) const
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
if (role == Qt::DisplayRole)
return item->data(index.column());
return (const char*)item->data(index.column()).toLocal8Bit();
else
return item->info();
return (const char*)item->info().toLocal8Bit();
}
Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const
Qt::ItemFlags TreeModel::flags(const UModelIndex &index) const
{
if (!index.isValid())
return 0;
@ -78,11 +60,58 @@ QVariant TreeModel::headerData(int section, Qt::Orientation orientation,
return QVariant();
}
#else
UString TreeModel::data(const UModelIndex &index, int role) const
{
if (!index.isValid())
return UString();
QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) const
if (role != 0 && role != 0x0100)
return UString();
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
if (role == 0)
return item->data(index.column());
else
return item->info();
}
UString TreeModel::headerData(int section, int orientation,
int role) const
{
if (orientation == 1 && role == 0) {
switch (section)
{
case 0:
return UString("Name");
case 1:
return UString("Action");
case 2:
return UString("Type");
case 3:
return UString("Subtype");
case 4:
return UString("Text");
}
}
return UString();
}
#endif
int TreeModel::columnCount(const UModelIndex &parent) const
{
if (parent.isValid())
return static_cast<TreeItem*>(parent.internalPointer())->columnCount();
else
return rootItem->columnCount();
}
UModelIndex TreeModel::index(int row, int column, const UModelIndex &parent) const
{
if (!hasIndex(row, column, parent))
return QModelIndex();
return UModelIndex();
TreeItem *parentItem;
@ -95,27 +124,27 @@ QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) con
if (childItem)
return createIndex(row, column, childItem);
else
return QModelIndex();
return UModelIndex();
}
QModelIndex TreeModel::parent(const QModelIndex &index) const
UModelIndex TreeModel::parent(const UModelIndex &index) const
{
if (!index.isValid())
return QModelIndex();
return UModelIndex();
TreeItem *childItem = static_cast<TreeItem*>(index.internalPointer());
if (childItem == rootItem)
return QModelIndex();
return UModelIndex();
TreeItem *parentItem = childItem->parent();
if (parentItem == rootItem)
return QModelIndex();
return UModelIndex();
return createIndex(parentItem->row(), 0, parentItem);
}
int TreeModel::rowCount(const QModelIndex &parent) const
int TreeModel::rowCount(const UModelIndex &parent) const
{
TreeItem *parentItem;
if (parent.column() > 0)
@ -129,7 +158,7 @@ int TreeModel::rowCount(const QModelIndex &parent) const
return parentItem->childCount();
}
UINT8 TreeModel::type(const QModelIndex &index) const
UINT8 TreeModel::type(const UModelIndex &index) const
{
if (!index.isValid())
return 0;
@ -137,7 +166,7 @@ UINT8 TreeModel::type(const QModelIndex &index) const
return item->type();
}
UINT8 TreeModel::subtype(const QModelIndex &index) const
UINT8 TreeModel::subtype(const UModelIndex &index) const
{
if (!index.isValid())
return 0;
@ -145,15 +174,15 @@ UINT8 TreeModel::subtype(const QModelIndex &index) const
return item->subtype();
}
QByteArray TreeModel::header(const QModelIndex &index) const
UByteArray TreeModel::header(const UModelIndex &index) const
{
if (!index.isValid())
return QByteArray();
return UByteArray();
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
return item->header();
}
bool TreeModel::hasEmptyHeader(const QModelIndex &index) const
bool TreeModel::hasEmptyHeader(const UModelIndex &index) const
{
if (!index.isValid())
return true;
@ -161,15 +190,15 @@ bool TreeModel::hasEmptyHeader(const QModelIndex &index) const
return item->hasEmptyHeader();
}
QByteArray TreeModel::body(const QModelIndex &index) const
UByteArray TreeModel::body(const UModelIndex &index) const
{
if (!index.isValid())
return QByteArray();
return UByteArray();
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
return item->body();
}
bool TreeModel::hasEmptyBody(const QModelIndex &index) const
bool TreeModel::hasEmptyBody(const UModelIndex &index) const
{
if (!index.isValid())
return true;
@ -177,15 +206,15 @@ bool TreeModel::hasEmptyBody(const QModelIndex &index) const
return item->hasEmptyBody();
}
QByteArray TreeModel::tail(const QModelIndex &index) const
UByteArray TreeModel::tail(const UModelIndex &index) const
{
if (!index.isValid())
return QByteArray();
return UByteArray();
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
return item->tail();
}
bool TreeModel::hasEmptyTail(const QModelIndex &index) const
bool TreeModel::hasEmptyTail(const UModelIndex &index) const
{
if (!index.isValid())
return true;
@ -193,15 +222,15 @@ bool TreeModel::hasEmptyTail(const QModelIndex &index) const
return item->hasEmptyTail();
}
QByteArray TreeModel::parsingData(const QModelIndex &index) const
UByteArray TreeModel::parsingData(const UModelIndex &index) const
{
if (!index.isValid())
return QByteArray();
return UByteArray();
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
return item->parsingData();
}
bool TreeModel::hasEmptyParsingData(const QModelIndex &index) const
bool TreeModel::hasEmptyParsingData(const UModelIndex &index) const
{
if (!index.isValid())
return true;
@ -209,31 +238,31 @@ bool TreeModel::hasEmptyParsingData(const QModelIndex &index) const
return item->hasEmptyParsingData();
}
QString TreeModel::name(const QModelIndex &index) const
UString TreeModel::name(const UModelIndex &index) const
{
if (!index.isValid())
return QString();
return UString();
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
return item->name();
}
QString TreeModel::text(const QModelIndex &index) const
UString TreeModel::text(const UModelIndex &index) const
{
if (!index.isValid())
return QString();
return UString();
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
return item->text();
}
QString TreeModel::info(const QModelIndex &index) const
UString TreeModel::info(const UModelIndex &index) const
{
if (!index.isValid())
return QString();
return UString();
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
return item->info();
}
UINT8 TreeModel::action(const QModelIndex &index) const
UINT8 TreeModel::action(const UModelIndex &index) const
{
if (!index.isValid())
return Actions::NoAction;
@ -241,7 +270,7 @@ UINT8 TreeModel::action(const QModelIndex &index) const
return item->action();
}
bool TreeModel::fixed(const QModelIndex &index) const
bool TreeModel::fixed(const UModelIndex &index) const
{
if (!index.isValid())
return false;
@ -249,7 +278,7 @@ bool TreeModel::fixed(const QModelIndex &index) const
return item->fixed();
}
bool TreeModel::compressed(const QModelIndex &index) const
bool TreeModel::compressed(const UModelIndex &index) const
{
if (!index.isValid())
return false;
@ -257,7 +286,7 @@ bool TreeModel::compressed(const QModelIndex &index) const
return item->compressed();
}
void TreeModel::setFixed(const QModelIndex &index, const bool fixed)
void TreeModel::setFixed(const UModelIndex &index, const bool fixed)
{
if (!index.isValid())
return;
@ -281,7 +310,7 @@ void TreeModel::setFixed(const QModelIndex &index, const bool fixed)
emit dataChanged(index, index);
}
void TreeModel::setCompressed(const QModelIndex &index, const bool compressed)
void TreeModel::setCompressed(const UModelIndex &index, const bool compressed)
{
if (!index.isValid())
return;
@ -293,7 +322,7 @@ void TreeModel::setCompressed(const QModelIndex &index, const bool compressed)
}
void TreeModel::setSubtype(const QModelIndex & index, const UINT8 subtype)
void TreeModel::setSubtype(const UModelIndex & index, const UINT8 subtype)
{
if (!index.isValid())
return;
@ -303,7 +332,7 @@ void TreeModel::setSubtype(const QModelIndex & index, const UINT8 subtype)
emit dataChanged(index, index);
}
void TreeModel::setName(const QModelIndex &index, const QString &data)
void TreeModel::setName(const UModelIndex &index, const UString &data)
{
if (!index.isValid())
return;
@ -313,7 +342,7 @@ void TreeModel::setName(const QModelIndex &index, const QString &data)
emit dataChanged(index, index);
}
void TreeModel::setType(const QModelIndex &index, const UINT8 data)
void TreeModel::setType(const UModelIndex &index, const UINT8 data)
{
if (!index.isValid())
return;
@ -323,7 +352,7 @@ void TreeModel::setType(const QModelIndex &index, const UINT8 data)
emit dataChanged(index, index);
}
void TreeModel::setText(const QModelIndex &index, const QString &data)
void TreeModel::setText(const UModelIndex &index, const UString &data)
{
if (!index.isValid())
return;
@ -333,7 +362,7 @@ void TreeModel::setText(const QModelIndex &index, const QString &data)
emit dataChanged(index, index);
}
void TreeModel::setInfo(const QModelIndex &index, const QString &data)
void TreeModel::setInfo(const UModelIndex &index, const UString &data)
{
if (!index.isValid())
return;
@ -343,17 +372,17 @@ void TreeModel::setInfo(const QModelIndex &index, const QString &data)
emit dataChanged(index, index);
}
void TreeModel::addInfo(const QModelIndex &index, const QString &data, const bool append)
void TreeModel::addInfo(const UModelIndex &index, const UString &data, const bool append)
{
if (!index.isValid())
return;
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
item->addInfo(data, (BOOLEAN)append);
item->addInfo(data, append);
emit dataChanged(index, index);
}
void TreeModel::setAction(const QModelIndex &index, const UINT8 action)
void TreeModel::setAction(const UModelIndex &index, const UINT8 action)
{
if (!index.isValid())
return;
@ -363,7 +392,7 @@ void TreeModel::setAction(const QModelIndex &index, const UINT8 action)
emit dataChanged(index, index);
}
void TreeModel::setParsingData(const QModelIndex &index, const QByteArray &data)
void TreeModel::setParsingData(const UModelIndex &index, const UByteArray &data)
{
if (!index.isValid())
return;
@ -373,11 +402,11 @@ void TreeModel::setParsingData(const QModelIndex &index, const QByteArray &data)
emit dataChanged(this->index(0, 0), index);
}
QModelIndex TreeModel::addItem(const UINT8 type, const UINT8 subtype,
const QString & name, const QString & text, const QString & info,
const QByteArray & header, const QByteArray & body, const QByteArray & tail,
const bool fixed, const QByteArray & parsingData,
const QModelIndex & parent, const UINT8 mode)
UModelIndex TreeModel::addItem(const UINT8 type, const UINT8 subtype,
const UString & name, const UString & text, const UString & info,
const UByteArray & header, const UByteArray & body, const UByteArray & tail,
const bool fixed, const UByteArray & parsingData,
const UModelIndex & parent, const UINT8 mode)
{
TreeItem *item = 0;
TreeItem *parentItem = 0;
@ -418,23 +447,23 @@ QModelIndex TreeModel::addItem(const UINT8 type, const UINT8 subtype,
}
else {
delete newItem;
return QModelIndex();
return UModelIndex();
}
emit layoutChanged();
QModelIndex created = createIndex(newItem->row(), parentColumn, newItem);
UModelIndex created = createIndex(newItem->row(), parentColumn, newItem);
setFixed(created, fixed); // Non-trivial logic requires additional call
return created;
}
QModelIndex TreeModel::findParentOfType(const QModelIndex& index, UINT8 type) const
UModelIndex TreeModel::findParentOfType(const UModelIndex& index, UINT8 type) const
{
if (!index.isValid())
return QModelIndex();
return UModelIndex();
TreeItem *item;
QModelIndex parent = index;
UModelIndex parent = index;
for (item = static_cast<TreeItem*>(parent.internalPointer());
item != NULL && item != rootItem && item->type() != type;
@ -443,5 +472,5 @@ QModelIndex TreeModel::findParentOfType(const QModelIndex& index, UINT8 type) co
if (item != NULL && item != rootItem)
return parent;
return QModelIndex();
return UModelIndex();
}

View File

@ -14,73 +14,165 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#ifndef TREEMODEL_H
#define TREEMODEL_H
#if defined(QT_CORE_LIB)
// Use Qt classes
#include <QAbstractItemModel>
#include <QModelIndex>
#include <QString>
#include <QVariant>
#include <QObject>
#include "ustring.h"
#include "ubytearray.h"
#include "basetypes.h"
#include "types.h"
#include "treeitem.h"
class TreeItem;
#define UModelIndex QModelIndex
#else
// Use own implementation
#include "ustring.h"
#include "ubytearray.h"
#include "basetypes.h"
#include "types.h"
#include "treeitem.h"
class TreeModel;
class UModelIndex
{
friend class TreeModel;
public:
inline UModelIndex() : r(-1), c(-1), i(0), m(0) {}
// compiler-generated copy/move ctors/assignment operators are fine!
inline int row() const { return r; }
inline int column() const { return c; }
inline uint64_t internalId() const { return i; }
inline void *internalPointer() const { return reinterpret_cast<void*>(i); }
inline UModelIndex parent() const;
inline UModelIndex child(int row, int column) const;
inline CBString data(int role) const;
inline const TreeModel *model() const { return m; }
inline bool isValid() const { return (r >= 0) && (c >= 0) && (m != 0); }
inline bool operator==(const UModelIndex &other) const { return (other.r == r) && (other.i == i) && (other.c == c) && (other.m == m); }
inline bool operator!=(const UModelIndex &other) const { return !(*this == other); }
inline bool operator<(const UModelIndex &other) const
{
return r < other.r
|| (r == other.r && (c < other.c
|| (c == other.c && (i < other.i
|| (i == other.i && m < other.m)))));
}
private:
inline UModelIndex(int arow, int acolumn, void *ptr, const TreeModel *amodel)
: r(arow), c(acolumn), i(reinterpret_cast<uint64_t>(ptr)), m(amodel) {}
inline UModelIndex(int arow, int acolumn, uint64_t id, const TreeModel *amodel)
: r(arow), c(acolumn), i(id), m(amodel) {}
int r, c;
uint64_t i;
const TreeModel *m;
};
#endif
#if defined(QT_CORE_LIB)
class TreeModel : public QAbstractItemModel
{
Q_OBJECT
public:
TreeModel(QObject *parent = 0);
~TreeModel();
QVariant data(const QModelIndex &index, int role) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const;
QModelIndex index(int row, int column,
const QModelIndex &parent = QModelIndex()) const;
QModelIndex parent(const QModelIndex &index) const;
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
void setAction(const QModelIndex &index, const UINT8 action);
void setType(const QModelIndex &index, const UINT8 type);
void setSubtype(const QModelIndex &index, const UINT8 subtype);
void setName(const QModelIndex &index, const QString &name);
void setText(const QModelIndex &index, const QString &text);
void setInfo(const QModelIndex &index, const QString &info);
void addInfo(const QModelIndex &index, const QString &info, const bool append = TRUE);
void setParsingData(const QModelIndex &index, const QByteArray &data);
void setFixed(const QModelIndex &index, const bool fixed);
void setCompressed(const QModelIndex &index, const bool compressed);
QString name(const QModelIndex &index) const;
QString text(const QModelIndex &index) const;
QString info(const QModelIndex &index) const;
UINT8 type(const QModelIndex &index) const;
UINT8 subtype(const QModelIndex &index) const;
QByteArray header(const QModelIndex &index) const;
bool hasEmptyHeader(const QModelIndex &index) const;
QByteArray body(const QModelIndex &index) const;
bool hasEmptyBody(const QModelIndex &index) const;
QByteArray tail(const QModelIndex &index) const;
bool hasEmptyTail(const QModelIndex &index) const;
QByteArray parsingData(const QModelIndex &index) const;
bool hasEmptyParsingData(const QModelIndex &index) const;
UINT8 action(const QModelIndex &index) const;
bool fixed(const QModelIndex &index) const;
bool compressed(const QModelIndex &index) const;
QModelIndex addItem(const UINT8 type, const UINT8 subtype,
const QString & name, const QString & text, const QString & info,
const QByteArray & header, const QByteArray & body, const QByteArray & tail,
const bool fixed, const QByteArray & parsingData = QByteArray(),
const QModelIndex & parent = QModelIndex(), const UINT8 mode = CREATE_MODE_APPEND);
QModelIndex findParentOfType(const QModelIndex & index, UINT8 type) const;
private:
TreeItem *rootItem;
public:
QVariant data(const UModelIndex &index, int role) const;
Qt::ItemFlags flags(const UModelIndex &index) const;
QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const;
TreeModel(QObject *parent = 0) : QAbstractItemModel(parent) {
rootItem = new TreeItem(Types::Root, 0, UString(), UString(), UString(), UByteArray(), UByteArray(), UByteArray(), TRUE, FALSE, UByteArray());
}
#else
#define emit
class TreeModel
{
private:
TreeItem *rootItem;
void dataChanged(const UModelIndex &, const UModelIndex &) {}
void layoutAboutToBeChanged() {}
void layoutChanged() {}
public:
UString data(const UModelIndex &index, int role) const;
UString headerData(int section, int orientation, int role = 0) const;
TreeModel() {
rootItem = new TreeItem(Types::Root, 0, UString(), UString(), UString(), UByteArray(), UByteArray(), UByteArray(), TRUE, FALSE, UByteArray());
}
bool hasIndex(int row, int column, const UModelIndex &parent = UModelIndex()) const {
if (row < 0 || column < 0)
return false;
return row < rowCount(parent) && column < columnCount(parent);
}
UModelIndex createIndex(int row, int column, void *data) const { return UModelIndex(row, column, data, this); }
#endif
~TreeModel() {
delete rootItem;
}
UModelIndex index(int row, int column,
const UModelIndex &parent = UModelIndex()) const;
UModelIndex parent(const UModelIndex &index) const;
int rowCount(const UModelIndex &parent = UModelIndex()) const;
int columnCount(const UModelIndex &parent = UModelIndex()) const;
void setAction(const UModelIndex &index, const UINT8 action);
void setType(const UModelIndex &index, const UINT8 type);
void setSubtype(const UModelIndex &index, const UINT8 subtype);
void setName(const UModelIndex &index, const UString &name);
void setText(const UModelIndex &index, const UString &text);
void setInfo(const UModelIndex &index, const UString &info);
void addInfo(const UModelIndex &index, const UString &info, const bool append = TRUE);
void setParsingData(const UModelIndex &index, const UByteArray &data);
void setFixed(const UModelIndex &index, const bool fixed);
void setCompressed(const UModelIndex &index, const bool compressed);
UString name(const UModelIndex &index) const;
UString text(const UModelIndex &index) const;
UString info(const UModelIndex &index) const;
UINT8 type(const UModelIndex &index) const;
UINT8 subtype(const UModelIndex &index) const;
UByteArray header(const UModelIndex &index) const;
bool hasEmptyHeader(const UModelIndex &index) const;
UByteArray body(const UModelIndex &index) const;
bool hasEmptyBody(const UModelIndex &index) const;
UByteArray tail(const UModelIndex &index) const;
bool hasEmptyTail(const UModelIndex &index) const;
UByteArray parsingData(const UModelIndex &index) const;
bool hasEmptyParsingData(const UModelIndex &index) const;
UINT8 action(const UModelIndex &index) const;
bool fixed(const UModelIndex &index) const;
bool compressed(const UModelIndex &index) const;
UModelIndex addItem(const UINT8 type, const UINT8 subtype,
const UString & name, const UString & text, const UString & info,
const UByteArray & header, const UByteArray & body, const UByteArray & tail,
const bool fixed, const UByteArray & parsingData = UByteArray(),
const UModelIndex & parent = UModelIndex(), const UINT8 mode = CREATE_MODE_APPEND);
UModelIndex findParentOfType(const UModelIndex & index, UINT8 type) const;
};
#if defined(QT_CORE_LIB)
// Nothing required here
#else
inline UModelIndex UModelIndex::parent() const { return m ? m->parent(*this) : UModelIndex(); }
inline UModelIndex UModelIndex::child(int row, int column) const { return m ? m->index(row, column, *this) : UModelIndex(); }
inline UString UModelIndex::data(int role) const { return m ? m->data(*this, role) : UString(); }
#endif
#endif // TREEMODEL_H

View File

@ -10,62 +10,60 @@ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*/
#include <QObject>
#include <QString>
#include "ustring.h"
#include "types.h"
#include "ffs.h"
QString regionTypeToQString(const UINT8 type)
{
switch (type)
{
case Subtypes::DescriptorRegion: return QObject::tr("Descriptor");
case Subtypes::BiosRegion: return QObject::tr("BIOS");
case Subtypes::MeRegion: return QObject::tr("ME");
case Subtypes::GbeRegion: return QObject::tr("GbE");
case Subtypes::PdrRegion: return QObject::tr("PDR");
case Subtypes::Reserved1Region: return QObject::tr("Reserved1");
case Subtypes::Reserved2Region: return QObject::tr("Reserved2");
case Subtypes::Reserved3Region: return QObject::tr("Reserved3");
case Subtypes::EcRegion: return QObject::tr("EC");
case Subtypes::Reserved4Region: return QObject::tr("Reserved4");
};
return QObject::tr("Unknown");
}
QString itemTypeToQString(const UINT8 type)
UString regionTypeToUString(const UINT8 type)
{
switch (type) {
case Types::Root: return QObject::tr("Root");
case Types::Image: return QObject::tr("Image");
case Types::Capsule: return QObject::tr("Capsule");
case Types::Region: return QObject::tr("Region");
case Types::Volume: return QObject::tr("Volume");
case Types::Padding: return QObject::tr("Padding");
case Types::File: return QObject::tr("File");
case Types::Section: return QObject::tr("Section");
case Types::FreeSpace: return QObject::tr("Free space");
case Types::VssStore: return QObject::tr("VSS store");
case Types::FtwStore: return QObject::tr("FTW store");
case Types::FdcStore: return QObject::tr("FDC store");
case Types::FsysStore: return QObject::tr("Fsys store");
case Types::EvsaStore: return QObject::tr("EVSA store");
case Types::CmdbStore: return QObject::tr("CMDB store");
case Types::FlashMapStore: return QObject::tr("FlashMap store");
case Types::NvarEntry: return QObject::tr("NVAR entry");
case Types::VssEntry: return QObject::tr("VSS entry");
case Types::FsysEntry: return QObject::tr("Fsys entry");
case Types::EvsaEntry: return QObject::tr("EVSA entry");
case Types::FlashMapEntry: return QObject::tr("FlashMap entry");
case Types::Microcode: return QObject::tr("Microcode");
case Types::SlicData: return QObject::tr("SLIC data");
}
case Subtypes::DescriptorRegion: return UString("Descriptor");
case Subtypes::BiosRegion: return UString("BIOS");
case Subtypes::MeRegion: return UString("ME");
case Subtypes::GbeRegion: return UString("GbE");
case Subtypes::PdrRegion: return UString("PDR");
case Subtypes::Reserved1Region: return UString("Reserved1");
case Subtypes::Reserved2Region: return UString("Reserved2");
case Subtypes::Reserved3Region: return UString("Reserved3");
case Subtypes::EcRegion: return UString("EC");
case Subtypes::Reserved4Region: return UString("Reserved4");
};
return QObject::tr("Unknown");
return UString("Unknown");
}
QString itemSubtypeToQString(const UINT8 type, const UINT8 subtype)
UString itemTypeToUString(const UINT8 type)
{
switch (type) {
case Types::Root: return UString("Root");
case Types::Image: return UString("Image");
case Types::Capsule: return UString("Capsule");
case Types::Region: return UString("Region");
case Types::Volume: return UString("Volume");
case Types::Padding: return UString("Padding");
case Types::File: return UString("File");
case Types::Section: return UString("Section");
case Types::FreeSpace: return UString("Free space");
case Types::VssStore: return UString("VSS store");
case Types::FtwStore: return UString("FTW store");
case Types::FdcStore: return UString("FDC store");
case Types::FsysStore: return UString("Fsys store");
case Types::EvsaStore: return UString("EVSA store");
case Types::CmdbStore: return UString("CMDB store");
case Types::FlashMapStore: return UString("FlashMap store");
case Types::NvarEntry: return UString("NVAR entry");
case Types::VssEntry: return UString("VSS entry");
case Types::FsysEntry: return UString("Fsys entry");
case Types::EvsaEntry: return UString("EVSA entry");
case Types::FlashMapEntry: return UString("FlashMap entry");
case Types::Microcode: return UString("Microcode");
case Types::SlicData: return UString("SLIC data");
}
return UString("Unknown");
}
UString itemSubtypeToUString(const UINT8 type, const UINT8 subtype)
{
switch (type) {
case Types::Root:
@ -78,89 +76,89 @@ QString itemSubtypeToQString(const UINT8 type, const UINT8 subtype)
case Types::FlashMapStore:
case Types::CmdbStore:
case Types::FsysEntry:
case Types::SlicData: return QString();
case Types::SlicData: return UString();
case Types::Image:
if (subtype == Subtypes::IntelImage) return QObject::tr("Intel");
if (subtype == Subtypes::UefiImage) return QObject::tr("UEFI");
if (subtype == Subtypes::IntelImage) return UString("Intel");
if (subtype == Subtypes::UefiImage) return UString("UEFI");
break;
case Types::Padding:
if (subtype == Subtypes::ZeroPadding) return QObject::tr("Empty (0x00)");
if (subtype == Subtypes::OnePadding) return QObject::tr("Empty (0xFF)");
if (subtype == Subtypes::DataPadding) return QObject::tr("Non-empty");
if (subtype == Subtypes::ZeroPadding) return UString("Empty (0x00)");
if (subtype == Subtypes::OnePadding) return UString("Empty (0xFF)");
if (subtype == Subtypes::DataPadding) return UString("Non-empty");
break;
case Types::Volume:
if (subtype == Subtypes::UnknownVolume) return QObject::tr("Unknown");
if (subtype == Subtypes::Ffs2Volume) return QObject::tr("FFSv2");
if (subtype == Subtypes::Ffs3Volume) return QObject::tr("FFSv3");
if (subtype == Subtypes::NvramVolume) return QObject::tr("NVRAM");
if (subtype == Subtypes::UnknownVolume) return UString("Unknown");
if (subtype == Subtypes::Ffs2Volume) return UString("FFSv2");
if (subtype == Subtypes::Ffs3Volume) return UString("FFSv3");
if (subtype == Subtypes::NvramVolume) return UString("NVRAM");
break;
case Types::Capsule:
if (subtype == Subtypes::AptioSignedCapsule) return QObject::tr("Aptio signed");
if (subtype == Subtypes::AptioUnsignedCapsule) return QObject::tr("Aptio unsigned");
if (subtype == Subtypes::UefiCapsule) return QObject::tr("UEFI 2.0");
if (subtype == Subtypes::ToshibaCapsule) return QObject::tr("Toshiba");
if (subtype == Subtypes::AptioSignedCapsule) return UString("Aptio signed");
if (subtype == Subtypes::AptioUnsignedCapsule) return UString("Aptio unsigned");
if (subtype == Subtypes::UefiCapsule) return UString("UEFI 2.0");
if (subtype == Subtypes::ToshibaCapsule) return UString("Toshiba");
break;
case Types::Region: return regionTypeToQString(subtype);
case Types::File: return fileTypeToQString(subtype);
case Types::Section: return sectionTypeToQString(subtype);
case Types::Region: return regionTypeToUString(subtype);
case Types::File: return fileTypeToUString(subtype);
case Types::Section: return sectionTypeToUString(subtype);
case Types::NvarEntry:
if (subtype == Subtypes::InvalidNvarEntry) return QObject::tr("Invalid");
if (subtype == Subtypes::InvalidLinkNvarEntry) return QObject::tr("Invalid link");
if (subtype == Subtypes::LinkNvarEntry) return QObject::tr("Link");
if (subtype == Subtypes::DataNvarEntry) return QObject::tr("Data");
if (subtype == Subtypes::FullNvarEntry) return QObject::tr("Full");
if (subtype == Subtypes::InvalidNvarEntry) return UString("Invalid");
if (subtype == Subtypes::InvalidLinkNvarEntry) return UString("Invalid link");
if (subtype == Subtypes::LinkNvarEntry) return UString("Link");
if (subtype == Subtypes::DataNvarEntry) return UString("Data");
if (subtype == Subtypes::FullNvarEntry) return UString("Full");
break;
case Types::VssEntry:
if (subtype == Subtypes::InvalidVssEntry) return QObject::tr("Invalid");
if (subtype == Subtypes::StandardVssEntry) return QObject::tr("Standard");
if (subtype == Subtypes::AppleVssEntry) return QObject::tr("Apple");
if (subtype == Subtypes::AuthVssEntry) return QObject::tr("Auth");
if (subtype == Subtypes::InvalidVssEntry) return UString("Invalid");
if (subtype == Subtypes::StandardVssEntry) return UString("Standard");
if (subtype == Subtypes::AppleVssEntry) return UString("Apple");
if (subtype == Subtypes::AuthVssEntry) return UString("Auth");
break;
case Types::EvsaEntry:
if (subtype == Subtypes::InvalidEvsaEntry) return QObject::tr("Invalid");
if (subtype == Subtypes::UnknownEvsaEntry) return QObject::tr("Unknown");
if (subtype == Subtypes::GuidEvsaEntry) return QObject::tr("GUID");
if (subtype == Subtypes::NameEvsaEntry) return QObject::tr("Name");
if (subtype == Subtypes::DataEvsaEntry) return QObject::tr("Data");
if (subtype == Subtypes::InvalidEvsaEntry) return UString("Invalid");
if (subtype == Subtypes::UnknownEvsaEntry) return UString("Unknown");
if (subtype == Subtypes::GuidEvsaEntry) return UString("GUID");
if (subtype == Subtypes::NameEvsaEntry) return UString("Name");
if (subtype == Subtypes::DataEvsaEntry) return UString("Data");
break;
case Types::FlashMapEntry:
if (subtype == Subtypes::VolumeFlashMapEntry) return QObject::tr("Volume");
if (subtype == Subtypes::DataFlashMapEntry) return QObject::tr("Data");
if (subtype == Subtypes::VolumeFlashMapEntry) return UString("Volume");
if (subtype == Subtypes::DataFlashMapEntry) return UString("Data");
break;
case Types::Microcode:
if (subtype == Subtypes::IntelMicrocode) return QObject::tr("Intel");
if (subtype == Subtypes::AmdMicrocode) return QObject::tr("AMD");
if (subtype == Subtypes::IntelMicrocode) return UString("Intel");
if (subtype == Subtypes::AmdMicrocode) return UString("AMD");
break;
}
return QObject::tr("Unknown");
return UString("Unknown");
}
QString compressionTypeToQString(const UINT8 algorithm)
UString compressionTypeToUString(const UINT8 algorithm)
{
switch (algorithm) {
case COMPRESSION_ALGORITHM_NONE: return QObject::tr("None");
case COMPRESSION_ALGORITHM_EFI11: return QObject::tr("EFI 1.1");
case COMPRESSION_ALGORITHM_TIANO: return QObject::tr("Tiano");
case COMPRESSION_ALGORITHM_UNDECIDED: return QObject::tr("Undecided Tiano/EFI 1.1");
case COMPRESSION_ALGORITHM_LZMA: return QObject::tr("LZMA");
case COMPRESSION_ALGORITHM_IMLZMA: return QObject::tr("Intel modified LZMA");
case COMPRESSION_ALGORITHM_NONE: return UString("None");
case COMPRESSION_ALGORITHM_EFI11: return UString("EFI 1.1");
case COMPRESSION_ALGORITHM_TIANO: return UString("Tiano");
case COMPRESSION_ALGORITHM_UNDECIDED: return UString("Undecided Tiano/EFI 1.1");
case COMPRESSION_ALGORITHM_LZMA: return UString("LZMA");
case COMPRESSION_ALGORITHM_IMLZMA: return UString("Intel modified LZMA");
}
return QObject::tr("Unknown");
return UString("Unknown");
}
QString actionTypeToQString(const UINT8 action)
UString actionTypeToUString(const UINT8 action)
{
switch (action) {
case Actions::NoAction: return QString();
case Actions::Create: return QObject::tr("Create");
case Actions::Insert: return QObject::tr("Insert");
case Actions::Replace: return QObject::tr("Replace");
case Actions::Remove: return QObject::tr("Remove");
case Actions::Rebuild: return QObject::tr("Rebuild");
case Actions::Rebase: return QObject::tr("Rebase");
case Actions::NoAction: return UString();
case Actions::Create: return UString("Create");
case Actions::Insert: return UString("Insert");
case Actions::Replace: return UString("Replace");
case Actions::Remove: return UString("Remove");
case Actions::Rebuild: return UString("Rebuild");
case Actions::Rebase: return UString("Rebase");
}
return QObject::tr("Unknown");
return UString("Unknown");
}

View File

@ -138,11 +138,11 @@ namespace Subtypes {
};
};
// *ToQString conversion routines
extern QString actionTypeToQString(const UINT8 action);
extern QString itemTypeToQString(const UINT8 type);
extern QString itemSubtypeToQString(const UINT8 type, const UINT8 subtype);
extern QString compressionTypeToQString(const UINT8 algorithm);
extern QString regionTypeToQString(const UINT8 type);
// *ToUString conversion routines
extern UString actionTypeToUString(const UINT8 action);
extern UString itemTypeToUString(const UINT8 type);
extern UString itemSubtypeToUString(const UINT8 type, const UINT8 subtype);
extern UString compressionTypeToUString(const UINT8 algorithm);
extern UString regionTypeToUString(const UINT8 type);
#endif // TYPES_H

86
common/ubytearray.h Normal file
View File

@ -0,0 +1,86 @@
/* ubytearray.h
Copyright (c) 2016, 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 UBYTEARRAY_H
#define UBYTEARRAY_H
#if defined(QT_CORE_LIB)
// Use Qt class, if Qt is available
#include <QByteArray>
#define UByteArray QByteArray
#else
// Use own implementation
#include <stdint.h>
#include <string>
#include <vector>
class UByteArray
{
public:
UByteArray() : d() {}
UByteArray(const UByteArray & ba) : d(ba.d) {}
UByteArray(const std::basic_string<char> & bs) : d(bs) {}
UByteArray(const std::vector<char> & bc) : d(bc.data(), bc.size()) {}
UByteArray(const char* bytes, int32_t size) : d(bytes, size) {}
~UByteArray() {}
bool isEmpty() const { return d.length() == 0; }
char* data() { return &(d.front()); /* Feels dirty, but works for all basic_string implementations I know, is fully OK in C++11 and later*/ }
const char* data() const { return d.c_str(); }
const char* constData() const { return d.c_str(); }
void clear() { d.clear(); }
int32_t size() const { return d.size(); }
int32_t count(char ch) const { return std::count(d.cbegin(), d.cend(), ch); }
char at(uint32_t i) const { return d.at(i); }
char operator[](uint32_t i) const { return d[i]; }
char& operator[](uint32_t i) { return d[i]; }
bool startsWith(const UByteArray & ba) const { return 0 == d.find(ba.d, 0); }
int indexOf(const UByteArray & ba, int from = 0) const { return d.find(ba.d, from); }
int lastIndexOf(const UByteArray & ba, int from = 0) const { return d.rfind(ba.d, from); }
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 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; }
bool operator== (const UByteArray & ba) const { return d == ba.d; }
bool operator!= (const UByteArray & ba) const { return d != ba.d; }
inline void swap(UByteArray &other) { std::swap(d, other.d); }
UByteArray toHex() {
std::basic_string<char> hex(size() * 2, '\x00');
for (int32_t i = 0; i < size(); i++) {
uint8_t low = d[i] & 0x0F;
uint8_t high = (d[i] & 0xF0) >> 4;
low += (low < 10 ? '0' : 'a');
high += (high < 10 ? '0' : 'a');
hex[2*i] = low;
hex[2*i + 1] = high;
}
std::reverse(hex.begin(), hex.end());
return UByteArray(hex);
}
private:
std::basic_string<char> d;
};
inline const UByteArray operator+(const UByteArray &a1, const UByteArray &a2)
{
return UByteArray(a1) += a2;
}
#endif // QT_CORE_LIB
#endif // UBYTEARRAY_H

94
common/ustring.cpp Normal file
View File

@ -0,0 +1,94 @@
/* ustring.cpp
Copyright (c) 2016, Nikolaj Schlej. All rights reserved.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*/
#include "ustring.h"
#include <stdarg.h>
#if defined(QT_CORE_LIB)
UString usprintf(const char* fmt, ...)
{
UString msg;
va_list vl;
va_start(vl, fmt);
msg.vsprintf(fmt, vl);
va_end(vl);
return msg;
};
#else
/* Give WATCOM C/C++, MSVC some latitude for their non-support of vsnprintf */
#if defined(__WATCOMC__) || defined(_MSC_VER)
#define exvsnprintf(r,b,n,f,a) {r = _vsnprintf (b,n,f,a);}
#else
#ifdef BSTRLIB_NOVSNP
/* This is just a hack. If you are using a system without a vsnprintf, it is
not recommended that bformat be used at all. */
#define exvsnprintf(r,b,n,f,a) {vsprintf (b,f,a); r = -1;}
#define START_VSNBUFF (256)
#else
#if defined (__GNUC__) && !defined (__PPC__)
/* Something is making gcc complain about this prototype not being here, so
I've just gone ahead and put it in. */
extern "C" {
extern int vsnprintf(char *buf, size_t count, const char *format, va_list arg);
}
#endif
#define exvsnprintf(r,b,n,f,a) {r = vsnprintf (b,n,f,a);}
#endif
#endif
#ifndef START_VSNBUFF
#define START_VSNBUFF (16)
#endif
UString usprintf(const char* fmt, ...)
{
UString msg;
bstring b;
va_list arglist;
int r, n;
if (fmt == NULL) {
msg = "<NULL>";
}
else {
if ((b = bfromcstr("")) == NULL) {
msg = "<NULL>";
}
else {
if ((n = (int)(2 * (strlen)(fmt))) < START_VSNBUFF) n = START_VSNBUFF;
for (;;) {
if (BSTR_OK != balloc(b, n + 2)) {
b = bformat("<NULL>");
break;
}
va_start(arglist, fmt);
exvsnprintf(r, (char *)b->data, n + 1, fmt, arglist);
va_end(arglist);
b->data[n] = '\0';
b->slen = (int)(strlen)((char *)b->data);
if (b->slen < n) break;
if (r > n) n = r; else n += n;
}
msg = *b;
bdestroy(b);
}
}
return msg;
}
#endif

30
common/ustring.h Normal file
View File

@ -0,0 +1,30 @@
/* ustring.h
Copyright (c) 2016, 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 USTRING_H
#define USTRING_H
#if defined (QT_CORE_LIB)
// Use Qt class, if Qt is available
#include <QString>
#define UString QString
#define findreplace replace
#else
// Use Bstrlib
#define BSTRLIB_DOESNT_THROW_EXCEPTIONS
#include "../bstrlib/bstrwrap.h"
#define UString CBString
#endif // QT_CORE_LIB
UString usprintf(const char* fmt, ...);
#endif // USTRING_H

View File

@ -10,7 +10,7 @@ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*/
#include <QObject>
#include "treemodel.h"
#include "utility.h"
#include "ffs.h"
@ -20,7 +20,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "LZMA/LzmaDecompress.h"
// Returns either new parsing data instance or obtains it from index
PARSING_DATA parsingDataFromQModelIndex(const QModelIndex & index)
PARSING_DATA parsingDataFromUModelIndex(const UModelIndex & index)
{
if (index.isValid()) {
TreeModel* model = (TreeModel*)index.model();
@ -39,64 +39,116 @@ PARSING_DATA parsingDataFromQModelIndex(const QModelIndex & index)
}
// Converts parsing data to byte array
QByteArray parsingDataToQByteArray(const PARSING_DATA & pdata)
UByteArray parsingDataToUByteArray(const PARSING_DATA & pdata)
{
return QByteArray((const char*)&pdata, sizeof(PARSING_DATA));
return UByteArray((const char*)&pdata, sizeof(PARSING_DATA));
}
// Returns unique name string based for tree item
UString uniqueItemName(const UModelIndex & index)
{
// Sanity check
if (!index.isValid())
return UString("Invalid index");
// Get model from index
const TreeModel* model = (const TreeModel*)index.model();
// Get data from parsing data
PARSING_DATA pdata = parsingDataFromUModelIndex(index);
// Construct the name
UString itemName = model->name(index);
UString itemText = model->text(index);
// Default name
UString name = itemName;
switch (model->type(index)) {
case Types::Volume:
if (pdata.volume.hasExtendedHeader) name = guidToUString(pdata.volume.extendedHeaderGuid);
break;
case Types::NvarEntry:
case Types::VssEntry:
case Types::FsysEntry:
case Types::EvsaEntry:
case Types::FlashMapEntry:
case Types::File:
name = itemText.isEmpty() ? itemName : itemName + '_' + itemText;
break;
case Types::Section: {
// Get parent file name
UModelIndex fileIndex = model->findParentOfType(index, Types::File);
UString fileText = model->text(fileIndex);
name = fileText.isEmpty() ? model->name(fileIndex) : model->name(fileIndex) + '_' + fileText;
} break;
}
UString subtypeString = itemSubtypeToUString(model->type(index), model->subtype(index));
name = itemTypeToUString(model->type(index))
+ (subtypeString.length() ? ('_' + subtypeString) : UString())
+ '_' + name;
name.findreplace(' ', '_');
name.findreplace('/', '_');
name.findreplace('-', '_');
return name;
}
// Returns text representation of error code
QString errorCodeToQString(UINT8 errorCode)
UString errorCodeToUString(UINT8 errorCode)
{
switch (errorCode) {
case ERR_SUCCESS: return QObject::tr("Success");
case ERR_NOT_IMPLEMENTED: return QObject::tr("Not implemented");
case ERR_INVALID_PARAMETER: return QObject::tr("Function called with invalid parameter");
case ERR_BUFFER_TOO_SMALL: return QObject::tr("Buffer too small");
case ERR_OUT_OF_RESOURCES: return QObject::tr("Out of resources");
case ERR_OUT_OF_MEMORY: return QObject::tr("Out of memory");
case ERR_FILE_OPEN: return QObject::tr("File can't be opened");
case ERR_FILE_READ: return QObject::tr("File can't be read");
case ERR_FILE_WRITE: return QObject::tr("File can't be written");
case ERR_ITEM_NOT_FOUND: return QObject::tr("Item not found");
case ERR_UNKNOWN_ITEM_TYPE: return QObject::tr("Unknown item type");
case ERR_INVALID_FLASH_DESCRIPTOR: return QObject::tr("Invalid flash descriptor");
case ERR_INVALID_REGION: return QObject::tr("Invalid region");
case ERR_EMPTY_REGION: return QObject::tr("Empty region");
case ERR_BIOS_REGION_NOT_FOUND: return QObject::tr("BIOS region not found");
case ERR_VOLUMES_NOT_FOUND: return QObject::tr("UEFI volumes not found");
case ERR_INVALID_VOLUME: return QObject::tr("Invalid UEFI volume");
case ERR_VOLUME_REVISION_NOT_SUPPORTED: return QObject::tr("Volume revision not supported");
//case ERR_VOLUME_GROW_FAILED: return QObject::tr("Volume grow failed");
case ERR_UNKNOWN_FFS: return QObject::tr("Unknown file system");
case ERR_INVALID_FILE: return QObject::tr("Invalid file");
case ERR_INVALID_SECTION: return QObject::tr("Invalid section");
case ERR_UNKNOWN_SECTION: return QObject::tr("Unknown section");
case ERR_STANDARD_COMPRESSION_FAILED: return QObject::tr("Standard compression failed");
case ERR_CUSTOMIZED_COMPRESSION_FAILED: return QObject::tr("Customized compression failed");
case ERR_STANDARD_DECOMPRESSION_FAILED: return QObject::tr("Standard decompression failed");
case ERR_CUSTOMIZED_DECOMPRESSION_FAILED: return QObject::tr("Customized decompression failed");
case ERR_UNKNOWN_COMPRESSION_TYPE: return QObject::tr("Unknown compression type");
case ERR_UNKNOWN_EXTRACT_MODE: return QObject::tr("Unknown extract mode");
case ERR_UNKNOWN_REPLACE_MODE: return QObject::tr("Unknown replace mode");
//case ERR_UNKNOWN_INSERT_MODE: return QObject::tr("Unknown insert mode");
case ERR_UNKNOWN_IMAGE_TYPE: return QObject::tr("Unknown executable image type");
case ERR_UNKNOWN_PE_OPTIONAL_HEADER_TYPE: return QObject::tr("Unknown PE optional header type");
case ERR_UNKNOWN_RELOCATION_TYPE: return QObject::tr("Unknown relocation type");
//case ERR_GENERIC_CALL_NOT_SUPPORTED: return QObject::tr("Generic call not supported");
//case ERR_VOLUME_BASE_NOT_FOUND: return QObject::tr("Volume base address not found");
//case ERR_PEI_CORE_ENTRY_POINT_NOT_FOUND: return QObject::tr("PEI core entry point not found");
case ERR_COMPLEX_BLOCK_MAP: return QObject::tr("Block map structure too complex for correct analysis");
case ERR_DIR_ALREADY_EXIST: return QObject::tr("Directory already exists");
case ERR_DIR_CREATE: return QObject::tr("Directory can't be created");
//case ERR_UNKNOWN_PATCH_TYPE: return QObject::tr("Unknown patch type");
//case ERR_PATCH_OFFSET_OUT_OF_BOUNDS: return QObject::tr("Patch offset out of bounds");
//case ERR_INVALID_SYMBOL: return QObject::tr("Invalid symbol");
//case ERR_NOTHING_TO_PATCH: return QObject::tr("Nothing to patch");
case ERR_DEPEX_PARSE_FAILED: return QObject::tr("Dependency expression parsing failed");
case ERR_TRUNCATED_IMAGE: return QObject::tr("Image is truncated");
case ERR_INVALID_CAPSULE: return QObject::tr("Invalid capsule");
case ERR_STORES_NOT_FOUND: return QObject::tr("Stores not found");
default: return QObject::tr("Unknown error %1").arg(errorCode);
case U_SUCCESS: return UString("Success");
case U_NOT_IMPLEMENTED: return UString("Not implemented");
case U_INVALID_PARAMETER: return UString("Function called with invalid parameter");
case U_BUFFER_TOO_SMALL: return UString("Buffer too small");
case U_OUT_OF_RESOURCES: return UString("Out of resources");
case U_OUT_OF_MEMORY: return UString("Out of memory");
case U_FILE_OPEN: return UString("File can't be opened");
case U_FILE_READ: return UString("File can't be read");
case U_FILE_WRITE: return UString("File can't be written");
case U_ITEM_NOT_FOUND: return UString("Item not found");
case U_UNKNOWN_ITEM_TYPE: return UString("Unknown item type");
case U_INVALID_FLASH_DESCRIPTOR: return UString("Invalid flash descriptor");
case U_INVALID_REGION: return UString("Invalid region");
case U_EMPTY_REGION: return UString("Empty region");
case U_BIOS_REGION_NOT_FOUND: return UString("BIOS region not found");
case U_VOLUMES_NOT_FOUND: return UString("UEFI volumes not found");
case U_INVALID_VOLUME: return UString("Invalid UEFI volume");
case U_VOLUME_REVISION_NOT_SUPPORTED: return UString("Volume revision not supported");
//case U_VOLUME_GROW_FAILED: return UString("Volume grow failed");
case U_UNKNOWN_FFS: return UString("Unknown file system");
case U_INVALID_FILE: return UString("Invalid file");
case U_INVALID_SECTION: return UString("Invalid section");
case U_UNKNOWN_SECTION: return UString("Unknown section");
case U_STANDARD_COMPRESSION_FAILED: return UString("Standard compression failed");
case U_CUSTOMIZED_COMPRESSION_FAILED: return UString("Customized compression failed");
case U_STANDARD_DECOMPRESSION_FAILED: return UString("Standard decompression failed");
case U_CUSTOMIZED_DECOMPRESSION_FAILED: return UString("Customized decompression failed");
case U_UNKNOWN_COMPRESSION_TYPE: return UString("Unknown compression type");
case U_UNKNOWN_EXTRACT_MODE: return UString("Unknown extract mode");
case U_UNKNOWN_REPLACE_MODE: return UString("Unknown replace mode");
//case U_UNKNOWN_INSERT_MODE: return UString("Unknown insert mode");
case U_UNKNOWN_IMAGE_TYPE: return UString("Unknown executable image type");
case U_UNKNOWN_PE_OPTIONAL_HEADER_TYPE: return UString("Unknown PE optional header type");
case U_UNKNOWN_RELOCATION_TYPE: return UString("Unknown relocation type");
//case U_GENERIC_CALL_NOT_SUPPORTED: return UString("Generic call not supported");
//case U_VOLUME_BASE_NOT_FOUND: return UString("Volume base address not found");
//case U_PEI_CORE_ENTRY_POINT_NOT_FOUND: return UString("PEI core entry point not found");
case U_COMPLEX_BLOCK_MAP: return UString("Block map structure too complex for correct analysis");
case U_DIR_ALREADY_EXIST: return UString("Directory already exists");
case U_DIR_CREATE: return UString("Directory can't be created");
case U_DIR_CHANGE: return UString("Change directory failed");
//case U_UNKNOWN_PATCH_TYPE: return UString("Unknown patch type");
//case U_PATCH_OFFSET_OUT_OF_BOUNDS: return UString("Patch offset out of bounds");
//case U_INVALID_SYMBOL: return UString("Invalid symbol");
//case U_NOTHING_TO_PATCH: return UString("Nothing to patch");
case U_DEPEX_PARSE_FAILED: return UString("Dependency expression parsing failed");
case U_TRUNCATED_IMAGE: return UString("Image is truncated");
case U_INVALID_CAPSULE: return UString("Invalid capsule");
case U_STORES_NOT_FOUND: return UString("Stores not found");
default: return usprintf("Unknown error %02X", errorCode);
}
}
@ -152,7 +204,7 @@ UINT32 crc32(UINT32 initial, const UINT8* buffer, const UINT32 length)
}
// Compression routines
STATUS decompress(const QByteArray & compressedData, UINT8 & algorithm, QByteArray & decompressedData, QByteArray & efiDecompressedData)
USTATUS decompress(const UByteArray & compressedData, UINT8 & algorithm, UByteArray & decompressedData, UByteArray & efiDecompressedData)
{
const UINT8* data;
UINT32 dataSize;
@ -168,7 +220,7 @@ STATUS decompress(const QByteArray & compressedData, UINT8 & algorithm, QByteArr
case EFI_NOT_COMPRESSED:
decompressedData = compressedData;
algorithm = COMPRESSION_ALGORITHM_NONE;
return ERR_SUCCESS;
return U_SUCCESS;
case EFI_STANDARD_COMPRESSION: {
// Set default algorithm to unknown
algorithm = COMPRESSION_ALGORITHM_UNKNOWN;
@ -180,11 +232,11 @@ STATUS decompress(const QByteArray & compressedData, UINT8 & algorithm, QByteArr
// Check header to be valid
header = (const EFI_TIANO_HEADER*)data;
if (header->CompSize + sizeof(EFI_TIANO_HEADER) != dataSize)
return ERR_STANDARD_DECOMPRESSION_FAILED;
return U_STANDARD_DECOMPRESSION_FAILED;
// Get info function is the same for both algorithms
if (ERR_SUCCESS != EfiTianoGetInfo(data, dataSize, &decompressedSize, &scratchSize))
return ERR_STANDARD_DECOMPRESSION_FAILED;
if (U_SUCCESS != EfiTianoGetInfo(data, dataSize, &decompressedSize, &scratchSize))
return U_STANDARD_DECOMPRESSION_FAILED;
// Allocate memory
decompressed = (UINT8*)malloc(decompressedSize);
@ -194,31 +246,31 @@ STATUS decompress(const QByteArray & compressedData, UINT8 & algorithm, QByteArr
if (decompressed) free(decompressed);
if (efiDecompressed) free(efiDecompressed);
if (scratch) free(scratch);
return ERR_STANDARD_DECOMPRESSION_FAILED;
return U_STANDARD_DECOMPRESSION_FAILED;
}
// Decompress section data using both algorithms
STATUS result = ERR_SUCCESS;
USTATUS result = U_SUCCESS;
// Try Tiano
STATUS TianoResult = TianoDecompress(data, dataSize, decompressed, decompressedSize, scratch, scratchSize);
USTATUS TianoResult = TianoDecompress(data, dataSize, decompressed, decompressedSize, scratch, scratchSize);
// Try EFI 1.1
STATUS EfiResult = EfiDecompress(data, dataSize, efiDecompressed, decompressedSize, scratch, scratchSize);
USTATUS EfiResult = EfiDecompress(data, dataSize, efiDecompressed, decompressedSize, scratch, scratchSize);
if (EfiResult == ERR_SUCCESS && TianoResult == ERR_SUCCESS) { // Both decompressions are OK
if (EfiResult == U_SUCCESS && TianoResult == U_SUCCESS) { // Both decompressions are OK
algorithm = COMPRESSION_ALGORITHM_UNDECIDED;
decompressedData = QByteArray((const char*)decompressed, decompressedSize);
efiDecompressedData = QByteArray((const char*)efiDecompressed, decompressedSize);
decompressedData = UByteArray((const char*)decompressed, decompressedSize);
efiDecompressedData = UByteArray((const char*)efiDecompressed, decompressedSize);
}
else if (TianoResult == ERR_SUCCESS) { // Only Tiano is OK
else if (TianoResult == U_SUCCESS) { // Only Tiano is OK
algorithm = COMPRESSION_ALGORITHM_TIANO;
decompressedData = QByteArray((const char*)decompressed, decompressedSize);
decompressedData = UByteArray((const char*)decompressed, decompressedSize);
}
else if (EfiResult == ERR_SUCCESS) { // Only EFI 1.1 is OK
else if (EfiResult == U_SUCCESS) { // Only EFI 1.1 is OK
algorithm = COMPRESSION_ALGORITHM_EFI11;
decompressedData = QByteArray((const char*)efiDecompressed, decompressedSize);
decompressedData = UByteArray((const char*)efiDecompressed, decompressedSize);
}
else { // Both decompressions failed
result = ERR_STANDARD_DECOMPRESSION_FAILED;
result = U_STANDARD_DECOMPRESSION_FAILED;
}
free(decompressed);
@ -235,47 +287,47 @@ STATUS decompress(const QByteArray & compressedData, UINT8 & algorithm, QByteArr
dataSize = compressedData.size();
// Get info
if (ERR_SUCCESS != LzmaGetInfo(data, dataSize, &decompressedSize))
return ERR_CUSTOMIZED_DECOMPRESSION_FAILED;
if (U_SUCCESS != LzmaGetInfo(data, dataSize, &decompressedSize))
return U_CUSTOMIZED_DECOMPRESSION_FAILED;
// Allocate memory
decompressed = (UINT8*)malloc(decompressedSize);
if (!decompressed) {
return ERR_STANDARD_DECOMPRESSION_FAILED;
return U_STANDARD_DECOMPRESSION_FAILED;
}
// Decompress section data
if (ERR_SUCCESS != LzmaDecompress(data, dataSize, decompressed)) {
if (U_SUCCESS != LzmaDecompress(data, dataSize, decompressed)) {
// Intel modified LZMA workaround
// Decompress section data once again
data += sizeof(UINT32);
// Get info again
if (ERR_SUCCESS != LzmaGetInfo(data, dataSize, &decompressedSize)) {
if (U_SUCCESS != LzmaGetInfo(data, dataSize, &decompressedSize)) {
free(decompressed);
return ERR_CUSTOMIZED_DECOMPRESSION_FAILED;
return U_CUSTOMIZED_DECOMPRESSION_FAILED;
}
// Decompress section data again
if (ERR_SUCCESS != LzmaDecompress(data, dataSize, decompressed)) {
if (U_SUCCESS != LzmaDecompress(data, dataSize, decompressed)) {
free(decompressed);
return ERR_CUSTOMIZED_DECOMPRESSION_FAILED;
return U_CUSTOMIZED_DECOMPRESSION_FAILED;
}
else {
algorithm = COMPRESSION_ALGORITHM_IMLZMA;
decompressedData = QByteArray((const char*)decompressed, decompressedSize);
decompressedData = UByteArray((const char*)decompressed, decompressedSize);
}
}
else {
algorithm = COMPRESSION_ALGORITHM_LZMA;
decompressedData = QByteArray((const char*)decompressed, decompressedSize);
decompressedData = UByteArray((const char*)decompressed, decompressedSize);
}
free(decompressed);
return ERR_SUCCESS;
return U_SUCCESS;
default:
algorithm = COMPRESSION_ALGORITHM_UNKNOWN;
return ERR_UNKNOWN_COMPRESSION_TYPE;
return U_UNKNOWN_COMPRESSION_TYPE;
}
}

View File

@ -14,33 +14,36 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#ifndef UTILITY_H
#define UTILITY_H
#include <QString>
#include <QModelIndex>
#include "ustring.h"
#include "treemodel.h"
#include "basetypes.h"
#include "parsingdata.h"
// Returns either new parsing data instance or obtains it from index
PARSING_DATA parsingDataFromQModelIndex(const QModelIndex & index);
PARSING_DATA parsingDataFromUModelIndex(const UModelIndex & index);
// Converts parsing data to byte array
QByteArray parsingDataToQByteArray(const PARSING_DATA & pdata);
UByteArray parsingDataToUByteArray(const PARSING_DATA & pdata);
// Converts error code to QString
extern QString errorCodeToQString(UINT8 errorCode);
// Returns unique name string based for tree item
UString uniqueItemName(const UModelIndex & index);
// Converts error code to UString
UString errorCodeToUString(UINT8 errorCode);
// Decompression routine
extern STATUS decompress(const QByteArray & compressed, UINT8 & algorithm, QByteArray & decompressed, QByteArray & efiDecompressed);
USTATUS decompress(const UByteArray & compressed, UINT8 & algorithm, UByteArray & decompressed, UByteArray & efiDecompressed);
// Compression routine
//STATUS compress(const QByteArray & decompressed, QByteArray & compressed, const UINT8 & algorithm);
//USTATUS compress(const UByteArray & decompressed, UByteArray & compressed, const UINT8 & algorithm);
// CRC32 calculation routine
extern UINT32 crc32(UINT32 initial, const UINT8* buffer, const UINT32 length);
UINT32 crc32(UINT32 initial, const UINT8* buffer, const UINT32 length);
// 8bit checksum calculation routine
extern UINT8 calculateChecksum8(const UINT8* buffer, UINT32 bufferSize);
UINT8 calculateChecksum8(const UINT8* buffer, UINT32 bufferSize);
// 16bit checksum calculation routine
extern UINT16 calculateChecksum16(const UINT16* buffer, UINT32 bufferSize);
UINT16 calculateChecksum16(const UINT16* buffer, UINT32 bufferSize);
#endif // UTILITY_H