mirror of
https://github.com/LongSoft/UEFITool.git
synced 2024-11-25 17:38:22 +08:00
commit
bb8e4a9746
49
UEFIDump/CMakeLists.txt
Normal file
49
UEFIDump/CMakeLists.txt
Normal 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
220
UEFIDump/uefidump.cpp
Normal 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
46
UEFIDump/uefidump.h
Normal 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
|
42
UEFIDump/uefidump_main.cpp
Normal file
42
UEFIDump/uefidump_main.cpp
Normal 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;
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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 ¤t)
|
||||
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
|
||||
|
@ -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
28
bstrlib/LICENSE
Normal 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
34
bstrlib/README.md
Normal 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
82
bstrlib/bsafe.c
Normal 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
43
bstrlib/bsafe.h
Normal 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
3689
bstrlib/bstest.c
Normal file
File diff suppressed because it is too large
Load Diff
1161
bstrlib/bstraux.c
Normal file
1161
bstrlib/bstraux.c
Normal file
File diff suppressed because it is too large
Load Diff
115
bstrlib/bstraux.h
Normal file
115
bstrlib/bstraux.h
Normal 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
3153
bstrlib/bstrlib.c
Normal file
File diff suppressed because it is too large
Load Diff
316
bstrlib/bstrlib.h
Normal file
316
bstrlib/bstrlib.h
Normal 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
3512
bstrlib/bstrlib.txt
Normal file
File diff suppressed because it is too large
Load Diff
1721
bstrlib/bstrwrap.cpp
Normal file
1721
bstrlib/bstrwrap.cpp
Normal file
File diff suppressed because it is too large
Load Diff
449
bstrlib/bstrwrap.h
Normal file
449
bstrlib/bstrwrap.h
Normal 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
274
bstrlib/buniutil.c
Normal 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
37
bstrlib/buniutil.h
Normal 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
339
bstrlib/gpl.txt
Normal 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
172
bstrlib/porting.txt
Normal 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
217
bstrlib/security.txt
Normal 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
1725
bstrlib/test.cpp
Normal file
File diff suppressed because it is too large
Load Diff
423
bstrlib/testaux.c
Normal file
423
bstrlib/testaux.c
Normal 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\">"), "<"Hello, you, me, & world">");
|
||||
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
249
bstrlib/utf8util.c
Normal 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
62
bstrlib/utf8util.h
Normal 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 */
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
104
common/ffs.cpp
104
common/ffs.cpp
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
64
common/ffs.h
64
common/ffs.h
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
};
|
||||
|
||||
|
2516
common/ffsparser.cpp
2516
common/ffsparser.cpp
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
};
|
||||
|
||||
|
@ -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_ {
|
||||
|
@ -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;
|
||||
}
|
@ -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));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
129
common/nvram.cpp
129
common/nvram.cpp
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
//
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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
|
||||
//
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
@ -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
|
||||
|
200
common/types.cpp
200
common/types.cpp
@ -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");
|
||||
}
|
@ -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
86
common/ubytearray.h
Normal 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
94
common/ustring.cpp
Normal 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
30
common/ustring.h
Normal 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
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user