mirror of
https://github.com/LongSoft/UEFITool.git
synced 2024-11-22 07:58:22 +08:00
Switch AMI NVAR parser to Kaitai
This commit is contained in:
parent
2d1ebcc11b
commit
7eb565d788
@ -33,6 +33,7 @@ SET(PROJECT_SOURCES
|
|||||||
../common/ustring.cpp
|
../common/ustring.cpp
|
||||||
../common/bstrlib/bstrlib.c
|
../common/bstrlib/bstrlib.c
|
||||||
../common/bstrlib/bstrwrap.cpp
|
../common/bstrlib/bstrwrap.cpp
|
||||||
|
../common/generated/ami_nvar.cpp
|
||||||
../common/generated/intel_acbp_v1.cpp
|
../common/generated/intel_acbp_v1.cpp
|
||||||
../common/generated/intel_acbp_v2.cpp
|
../common/generated/intel_acbp_v2.cpp
|
||||||
../common/generated/intel_keym_v1.cpp
|
../common/generated/intel_keym_v1.cpp
|
||||||
|
@ -30,6 +30,7 @@ SET(PROJECT_SOURCES
|
|||||||
../common/ustring.cpp
|
../common/ustring.cpp
|
||||||
../common/bstrlib/bstrlib.c
|
../common/bstrlib/bstrlib.c
|
||||||
../common/bstrlib/bstrwrap.cpp
|
../common/bstrlib/bstrwrap.cpp
|
||||||
|
../common/generated/ami_nvar.cpp
|
||||||
../common/generated/intel_acbp_v1.cpp
|
../common/generated/intel_acbp_v1.cpp
|
||||||
../common/generated/intel_acbp_v2.cpp
|
../common/generated/intel_acbp_v2.cpp
|
||||||
../common/generated/intel_keym_v1.cpp
|
../common/generated/intel_keym_v1.cpp
|
||||||
|
@ -70,6 +70,7 @@ SET(PROJECT_SOURCES
|
|||||||
../common/digest/sha256.c
|
../common/digest/sha256.c
|
||||||
../common/digest/sha512.c
|
../common/digest/sha512.c
|
||||||
../common/digest/sm3.c
|
../common/digest/sm3.c
|
||||||
|
../common/generated/ami_nvar.cpp
|
||||||
../common/generated/intel_acbp_v1.cpp
|
../common/generated/intel_acbp_v1.cpp
|
||||||
../common/generated/intel_acbp_v2.cpp
|
../common/generated/intel_acbp_v2.cpp
|
||||||
../common/generated/intel_keym_v1.cpp
|
../common/generated/intel_keym_v1.cpp
|
||||||
|
@ -243,6 +243,7 @@ void UEFITool::populateUi(const QModelIndex ¤t)
|
|||||||
|| type == Types::EvsaStore
|
|| type == Types::EvsaStore
|
||||||
|| type == Types::FtwStore
|
|| type == Types::FtwStore
|
||||||
|| type == Types::FlashMapStore
|
|| type == Types::FlashMapStore
|
||||||
|
|| type == Types::NvarGuidStore
|
||||||
|| type == Types::CmdbStore
|
|| type == Types::CmdbStore
|
||||||
|| type == Types::FptStore
|
|| type == Types::FptStore
|
||||||
|| type == Types::BpdtStore
|
|| type == Types::BpdtStore
|
||||||
@ -407,9 +408,8 @@ void UEFITool::goToData()
|
|||||||
|
|
||||||
UByteArray rdata = model->parsingData(index);
|
UByteArray rdata = model->parsingData(index);
|
||||||
const NVAR_ENTRY_PARSING_DATA* pdata = (const NVAR_ENTRY_PARSING_DATA*)rdata.constData();
|
const NVAR_ENTRY_PARSING_DATA* pdata = (const NVAR_ENTRY_PARSING_DATA*)rdata.constData();
|
||||||
UINT32 lastVariableFlag = pdata->emptyByte ? 0xFFFFFF : 0;
|
|
||||||
UINT32 offset = model->offset(index);
|
UINT32 offset = model->offset(index);
|
||||||
if (pdata->next == lastVariableFlag) {
|
if (pdata->next == 0xFFFFFF) {
|
||||||
ui->structureTreeView->scrollTo(index, QAbstractItemView::PositionAtCenter);
|
ui->structureTreeView->scrollTo(index, QAbstractItemView::PositionAtCenter);
|
||||||
ui->structureTreeView->selectionModel()->select(index, QItemSelectionModel::Select | QItemSelectionModel::Rows | QItemSelectionModel::Clear);
|
ui->structureTreeView->selectionModel()->select(index, QItemSelectionModel::Select | QItemSelectionModel::Rows | QItemSelectionModel::Clear);
|
||||||
}
|
}
|
||||||
@ -783,13 +783,7 @@ void UEFITool::showParserMessages()
|
|||||||
|
|
||||||
std::vector<std::pair<QString, QModelIndex> > messages = ffsParser->getMessages();
|
std::vector<std::pair<QString, QModelIndex> > messages = ffsParser->getMessages();
|
||||||
|
|
||||||
#if QT_VERSION_MAJOR < 6
|
for (const auto &msg : messages) {
|
||||||
std::pair<QString, QModelIndex> msg;
|
|
||||||
foreach (msg, messages)
|
|
||||||
#else
|
|
||||||
for (const auto &msg : messages)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
QListWidgetItem* item = new QListWidgetItem(msg.first, NULL, 0);
|
QListWidgetItem* item = new QListWidgetItem(msg.first, NULL, 0);
|
||||||
item->setData(Qt::UserRole, QByteArray((const char*)&msg.second, sizeof(msg.second)));
|
item->setData(Qt::UserRole, QByteArray((const char*)&msg.second, sizeof(msg.second)));
|
||||||
ui->parserMessagesListWidget->addItem(item);
|
ui->parserMessagesListWidget->addItem(item);
|
||||||
@ -807,13 +801,7 @@ void UEFITool::showFinderMessages()
|
|||||||
|
|
||||||
std::vector<std::pair<QString, QModelIndex> > messages = ffsFinder->getMessages();
|
std::vector<std::pair<QString, QModelIndex> > messages = ffsFinder->getMessages();
|
||||||
|
|
||||||
#if QT_VERSION_MAJOR < 6
|
for (const auto &msg : messages) {
|
||||||
std::pair<QString, QModelIndex> msg;
|
|
||||||
foreach (msg, messages)
|
|
||||||
#else
|
|
||||||
for (const auto &msg : messages)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
QListWidgetItem* item = new QListWidgetItem(msg.first, NULL, 0);
|
QListWidgetItem* item = new QListWidgetItem(msg.first, NULL, 0);
|
||||||
item->setData(Qt::UserRole, QByteArray((const char*)&msg.second, sizeof(msg.second)));;
|
item->setData(Qt::UserRole, QByteArray((const char*)&msg.second, sizeof(msg.second)));;
|
||||||
ui->finderMessagesListWidget->addItem(item);
|
ui->finderMessagesListWidget->addItem(item);
|
||||||
@ -832,13 +820,7 @@ void UEFITool::showBuilderMessages()
|
|||||||
|
|
||||||
std::vector<std::pair<QString, QModelIndex> > messages = ffsBuilder->getMessages();
|
std::vector<std::pair<QString, QModelIndex> > messages = ffsBuilder->getMessages();
|
||||||
|
|
||||||
#if QT_VERSION_MAJOR < 6
|
for (const auto &msg : messages) {
|
||||||
std::pair<QString, QModelIndex> msg;
|
|
||||||
foreach (msg, messages)
|
|
||||||
#else
|
|
||||||
for (const auto &msg : messages)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
QListWidgetItem* item = new QListWidgetItem(msg.first, NULL, 0);
|
QListWidgetItem* item = new QListWidgetItem(msg.first, NULL, 0);
|
||||||
item->setData(Qt::UserRole, QByteArray((const char*)&msg.second, sizeof(msg.second)));
|
item->setData(Qt::UserRole, QByteArray((const char*)&msg.second, sizeof(msg.second)));
|
||||||
ui->builderMessagesListWidget->addItem(item);
|
ui->builderMessagesListWidget->addItem(item);
|
||||||
@ -891,8 +873,7 @@ void UEFITool::contextMenuEvent(QContextMenuEvent* event)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (model->type(index))
|
switch (model->type(index)) {
|
||||||
{
|
|
||||||
case Types::Capsule: ui->menuCapsuleActions->exec(event->globalPos()); break;
|
case Types::Capsule: ui->menuCapsuleActions->exec(event->globalPos()); break;
|
||||||
case Types::Image: ui->menuImageActions->exec(event->globalPos()); break;
|
case Types::Image: ui->menuImageActions->exec(event->globalPos()); break;
|
||||||
case Types::Region: ui->menuRegionActions->exec(event->globalPos()); break;
|
case Types::Region: ui->menuRegionActions->exec(event->globalPos()); break;
|
||||||
@ -907,6 +888,7 @@ void UEFITool::contextMenuEvent(QContextMenuEvent* event)
|
|||||||
case Types::EvsaStore:
|
case Types::EvsaStore:
|
||||||
case Types::FtwStore:
|
case Types::FtwStore:
|
||||||
case Types::FlashMapStore:
|
case Types::FlashMapStore:
|
||||||
|
case Types::NvarGuidStore:
|
||||||
case Types::CmdbStore:
|
case Types::CmdbStore:
|
||||||
case Types::FptStore:
|
case Types::FptStore:
|
||||||
case Types::CpdStore:
|
case Types::CpdStore:
|
||||||
|
@ -46,9 +46,11 @@ HEADERS += uefitool.h \
|
|||||||
../common/Tiano/EfiTianoCompress.h \
|
../common/Tiano/EfiTianoCompress.h \
|
||||||
../common/ustring.h \
|
../common/ustring.h \
|
||||||
../common/ubytearray.h \
|
../common/ubytearray.h \
|
||||||
|
../common/umemstream.h \
|
||||||
../common/digest/sha1.h \
|
../common/digest/sha1.h \
|
||||||
../common/digest/sha2.h \
|
../common/digest/sha2.h \
|
||||||
../common/digest/sm3.h \
|
../common/digest/sm3.h \
|
||||||
|
../common/generated/ami_nvar.h \
|
||||||
../common/generated/intel_acbp_v1.h \
|
../common/generated/intel_acbp_v1.h \
|
||||||
../common/generated/intel_acbp_v2.h \
|
../common/generated/intel_acbp_v2.h \
|
||||||
../common/generated/intel_keym_v1.h \
|
../common/generated/intel_keym_v1.h \
|
||||||
@ -103,6 +105,7 @@ SOURCES += uefitool_main.cpp \
|
|||||||
../common/digest/sha256.c \
|
../common/digest/sha256.c \
|
||||||
../common/digest/sha512.c \
|
../common/digest/sha512.c \
|
||||||
../common/digest/sm3.c \
|
../common/digest/sm3.c \
|
||||||
|
../common/generated/ami_nvar.cpp \
|
||||||
../common/generated/intel_acbp_v1.cpp \
|
../common/generated/intel_acbp_v1.cpp \
|
||||||
../common/generated/intel_acbp_v2.cpp \
|
../common/generated/intel_acbp_v2.cpp \
|
||||||
../common/generated/intel_keym_v1.cpp \
|
../common/generated/intel_keym_v1.cpp \
|
||||||
|
@ -18,6 +18,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
// TODO: improve
|
||||||
typedef size_t USTATUS;
|
typedef size_t USTATUS;
|
||||||
#define U_SUCCESS 0
|
#define U_SUCCESS 0
|
||||||
#define U_INVALID_PARAMETER 1
|
#define U_INVALID_PARAMETER 1
|
||||||
@ -76,6 +77,7 @@ typedef size_t USTATUS;
|
|||||||
#define U_PATCH_OFFSET_OUT_OF_BOUNDS 54
|
#define U_PATCH_OFFSET_OUT_OF_BOUNDS 54
|
||||||
#define U_INVALID_SYMBOL 55
|
#define U_INVALID_SYMBOL 55
|
||||||
#define U_ZLIB_DECOMPRESSION_FAILED 56
|
#define U_ZLIB_DECOMPRESSION_FAILED 56
|
||||||
|
#define U_INVALID_STORE 57
|
||||||
|
|
||||||
#define U_INVALID_MANIFEST 251
|
#define U_INVALID_MANIFEST 251
|
||||||
#define U_UNKNOWN_MANIFEST_HEADER_VERSION 252
|
#define U_UNKNOWN_MANIFEST_HEADER_VERSION 252
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
#include "digest/sha2.h"
|
#include "digest/sha2.h"
|
||||||
|
|
||||||
#include <sstream>
|
#include "umemstream.h"
|
||||||
#include "kaitai/kaitaistream.h"
|
#include "kaitai/kaitaistream.h"
|
||||||
#include "generated/intel_acbp_v1.h"
|
#include "generated/intel_acbp_v1.h"
|
||||||
#include "generated/intel_acbp_v2.h"
|
#include "generated/intel_acbp_v2.h"
|
||||||
@ -29,45 +29,6 @@
|
|||||||
#include "generated/intel_keym_v2.h"
|
#include "generated/intel_keym_v2.h"
|
||||||
#include "generated/intel_acm.h"
|
#include "generated/intel_acm.h"
|
||||||
|
|
||||||
// TODO: put into separate H/CPP when we start using Kaitai for other parsers
|
|
||||||
// TODO: this implementation is certainly not a valid replacement to std::stringstream
|
|
||||||
// TODO: because it only supports getting through the buffer once
|
|
||||||
// TODO: however, we already do it this way, so it's enough for practical purposes of this file
|
|
||||||
class membuf : public std::streambuf {
|
|
||||||
public:
|
|
||||||
membuf(const char *p, size_t l) {
|
|
||||||
setg((char*)p, (char*)p, (char*)p + l);
|
|
||||||
}
|
|
||||||
|
|
||||||
pos_type seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which = std::ios_base::in) override
|
|
||||||
{
|
|
||||||
(void)which;
|
|
||||||
if (dir == std::ios_base::cur)
|
|
||||||
gbump((int)off);
|
|
||||||
else if (dir == std::ios_base::end)
|
|
||||||
setg(eback(), egptr() + off, egptr());
|
|
||||||
else if (dir == std::ios_base::beg)
|
|
||||||
setg(eback(), eback() + off, egptr());
|
|
||||||
return gptr() - eback();
|
|
||||||
}
|
|
||||||
|
|
||||||
pos_type seekpos(pos_type sp, std::ios_base::openmode which) override
|
|
||||||
{
|
|
||||||
return seekoff(sp - pos_type(off_type(0)), std::ios_base::beg, which);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class memstream : public std::istream {
|
|
||||||
public:
|
|
||||||
memstream(const char *p, size_t l) : std::istream(&buffer_),
|
|
||||||
buffer_(p, l) {
|
|
||||||
rdbuf(&buffer_);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
membuf buffer_;
|
|
||||||
};
|
|
||||||
|
|
||||||
USTATUS FitParser::parseFit(const UModelIndex & index)
|
USTATUS FitParser::parseFit(const UModelIndex & index)
|
||||||
{
|
{
|
||||||
// Reset parser state
|
// Reset parser state
|
||||||
@ -318,7 +279,7 @@ USTATUS FitParser::parseFitEntryMicrocode(const UByteArray & microcode, const UI
|
|||||||
USTATUS FitParser::parseFitEntryAcm(const UByteArray & acm, const UINT32 localOffset, const UModelIndex & parent, UString & info, UINT32 &realSize)
|
USTATUS FitParser::parseFitEntryAcm(const UByteArray & acm, const UINT32 localOffset, const UModelIndex & parent, UString & info, UINT32 &realSize)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
memstream is(acm.constData(), acm.size());
|
umemstream is(acm.constData(), acm.size());
|
||||||
is.seekg(localOffset, is.beg);
|
is.seekg(localOffset, is.beg);
|
||||||
kaitai::kstream ks(&is);
|
kaitai::kstream ks(&is);
|
||||||
intel_acm_t parsed(&ks);
|
intel_acm_t parsed(&ks);
|
||||||
@ -436,7 +397,7 @@ USTATUS FitParser::parseFitEntryBootGuardKeyManifest(const UByteArray & keyManif
|
|||||||
|
|
||||||
// v1
|
// v1
|
||||||
try {
|
try {
|
||||||
memstream is(keyManifest.constData(), keyManifest.size());
|
umemstream is(keyManifest.constData(), keyManifest.size());
|
||||||
is.seekg(localOffset, is.beg);
|
is.seekg(localOffset, is.beg);
|
||||||
kaitai::kstream ks(&is);
|
kaitai::kstream ks(&is);
|
||||||
intel_keym_v1_t parsed(&ks);
|
intel_keym_v1_t parsed(&ks);
|
||||||
@ -539,7 +500,7 @@ USTATUS FitParser::parseFitEntryBootGuardKeyManifest(const UByteArray & keyManif
|
|||||||
|
|
||||||
// v2
|
// v2
|
||||||
try {
|
try {
|
||||||
memstream is(keyManifest.constData(), keyManifest.size());
|
umemstream is(keyManifest.constData(), keyManifest.size());
|
||||||
is.seekg(localOffset, is.beg);
|
is.seekg(localOffset, is.beg);
|
||||||
kaitai::kstream ks(&is);
|
kaitai::kstream ks(&is);
|
||||||
intel_keym_v2_t parsed(&ks);
|
intel_keym_v2_t parsed(&ks);
|
||||||
@ -671,7 +632,7 @@ USTATUS FitParser::parseFitEntryBootGuardBootPolicy(const UByteArray & bootPolic
|
|||||||
|
|
||||||
// v1
|
// v1
|
||||||
try {
|
try {
|
||||||
memstream is(bootPolicy.constData(), bootPolicy.size());
|
umemstream is(bootPolicy.constData(), bootPolicy.size());
|
||||||
is.seekg(localOffset, is.beg);
|
is.seekg(localOffset, is.beg);
|
||||||
kaitai::kstream ks(&is);
|
kaitai::kstream ks(&is);
|
||||||
intel_acbp_v1_t parsed(&ks);
|
intel_acbp_v1_t parsed(&ks);
|
||||||
@ -935,7 +896,7 @@ USTATUS FitParser::parseFitEntryBootGuardBootPolicy(const UByteArray & bootPolic
|
|||||||
|
|
||||||
// v2
|
// v2
|
||||||
try {
|
try {
|
||||||
memstream is(bootPolicy.constData(), bootPolicy.size());
|
umemstream is(bootPolicy.constData(), bootPolicy.size());
|
||||||
is.seekg(localOffset, is.beg);
|
is.seekg(localOffset, is.beg);
|
||||||
kaitai::kstream ks(&is);
|
kaitai::kstream ks(&is);
|
||||||
intel_acbp_v2_t parsed(&ks); // This already verified the version to be >= 0x20
|
intel_acbp_v2_t parsed(&ks); // This already verified the version to be >= 0x20
|
||||||
|
442
common/generated/ami_nvar.cpp
Normal file
442
common/generated/ami_nvar.cpp
Normal file
@ -0,0 +1,442 @@
|
|||||||
|
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
|
||||||
|
|
||||||
|
#include "ami_nvar.h"
|
||||||
|
#include "../kaitai/exceptions.h"
|
||||||
|
|
||||||
|
ami_nvar_t::ami_nvar_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, ami_nvar_t* p__root) : kaitai::kstruct(p__io) {
|
||||||
|
m__parent = p__parent;
|
||||||
|
m__root = this; (void)p__root;
|
||||||
|
m_entries = 0;
|
||||||
|
|
||||||
|
try {
|
||||||
|
_read();
|
||||||
|
} catch(...) {
|
||||||
|
_clean_up();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ami_nvar_t::_read() {
|
||||||
|
m_entries = new std::vector<nvar_entry_t*>();
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
nvar_entry_t* _;
|
||||||
|
do {
|
||||||
|
_ = new nvar_entry_t(m__io, this, m__root);
|
||||||
|
m_entries->push_back(_);
|
||||||
|
i++;
|
||||||
|
} while (!( ((_->signature_first() != 78) || (_io()->is_eof())) ));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ami_nvar_t::~ami_nvar_t() {
|
||||||
|
_clean_up();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ami_nvar_t::_clean_up() {
|
||||||
|
if (m_entries) {
|
||||||
|
for (std::vector<nvar_entry_t*>::iterator it = m_entries->begin(); it != m_entries->end(); ++it) {
|
||||||
|
delete *it;
|
||||||
|
}
|
||||||
|
delete m_entries; m_entries = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ami_nvar_t::nvar_attributes_t::nvar_attributes_t(kaitai::kstream* p__io, ami_nvar_t::nvar_entry_t* p__parent, ami_nvar_t* p__root) : kaitai::kstruct(p__io) {
|
||||||
|
m__parent = p__parent;
|
||||||
|
m__root = p__root;
|
||||||
|
|
||||||
|
try {
|
||||||
|
_read();
|
||||||
|
} catch(...) {
|
||||||
|
_clean_up();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ami_nvar_t::nvar_attributes_t::_read() {
|
||||||
|
m_valid = m__io->read_bits_int_be(1);
|
||||||
|
m_auth_write = m__io->read_bits_int_be(1);
|
||||||
|
m_hw_error_record = m__io->read_bits_int_be(1);
|
||||||
|
m_extended_header = m__io->read_bits_int_be(1);
|
||||||
|
m_data_only = m__io->read_bits_int_be(1);
|
||||||
|
m_local_guid = m__io->read_bits_int_be(1);
|
||||||
|
m_ascii_name = m__io->read_bits_int_be(1);
|
||||||
|
m_runtime = m__io->read_bits_int_be(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ami_nvar_t::nvar_attributes_t::~nvar_attributes_t() {
|
||||||
|
_clean_up();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ami_nvar_t::nvar_attributes_t::_clean_up() {
|
||||||
|
}
|
||||||
|
|
||||||
|
ami_nvar_t::ucs2_string_t::ucs2_string_t(kaitai::kstream* p__io, ami_nvar_t::nvar_entry_body_t* p__parent, ami_nvar_t* p__root) : kaitai::kstruct(p__io) {
|
||||||
|
m__parent = p__parent;
|
||||||
|
m__root = p__root;
|
||||||
|
m_ucs2_chars = 0;
|
||||||
|
|
||||||
|
try {
|
||||||
|
_read();
|
||||||
|
} catch(...) {
|
||||||
|
_clean_up();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ami_nvar_t::ucs2_string_t::_read() {
|
||||||
|
m_ucs2_chars = new std::vector<uint16_t>();
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
uint16_t _;
|
||||||
|
do {
|
||||||
|
_ = m__io->read_u2le();
|
||||||
|
m_ucs2_chars->push_back(_);
|
||||||
|
i++;
|
||||||
|
} while (!(_ == 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ami_nvar_t::ucs2_string_t::~ucs2_string_t() {
|
||||||
|
_clean_up();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ami_nvar_t::ucs2_string_t::_clean_up() {
|
||||||
|
if (m_ucs2_chars) {
|
||||||
|
delete m_ucs2_chars; m_ucs2_chars = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ami_nvar_t::nvar_extended_attributes_t::nvar_extended_attributes_t(kaitai::kstream* p__io, ami_nvar_t::nvar_entry_body_t* p__parent, ami_nvar_t* p__root) : kaitai::kstruct(p__io) {
|
||||||
|
m__parent = p__parent;
|
||||||
|
m__root = p__root;
|
||||||
|
|
||||||
|
try {
|
||||||
|
_read();
|
||||||
|
} catch(...) {
|
||||||
|
_clean_up();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ami_nvar_t::nvar_extended_attributes_t::_read() {
|
||||||
|
m_reserved_high = m__io->read_bits_int_be(2);
|
||||||
|
m_time_based_auth = m__io->read_bits_int_be(1);
|
||||||
|
m_auth_write = m__io->read_bits_int_be(1);
|
||||||
|
m_reserved_low = m__io->read_bits_int_be(3);
|
||||||
|
m_checksum = m__io->read_bits_int_be(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ami_nvar_t::nvar_extended_attributes_t::~nvar_extended_attributes_t() {
|
||||||
|
_clean_up();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ami_nvar_t::nvar_extended_attributes_t::_clean_up() {
|
||||||
|
}
|
||||||
|
|
||||||
|
ami_nvar_t::nvar_entry_t::nvar_entry_t(kaitai::kstream* p__io, ami_nvar_t* p__parent, ami_nvar_t* p__root) : kaitai::kstruct(p__io) {
|
||||||
|
m__parent = p__parent;
|
||||||
|
m__root = p__root;
|
||||||
|
m_attributes = 0;
|
||||||
|
m_body = 0;
|
||||||
|
m__io__raw_body = 0;
|
||||||
|
f_offset = false;
|
||||||
|
f_end_offset = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
_read();
|
||||||
|
} catch(...) {
|
||||||
|
_clean_up();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ami_nvar_t::nvar_entry_t::_read() {
|
||||||
|
n_invoke_offset = true;
|
||||||
|
if (offset() >= 0) {
|
||||||
|
n_invoke_offset = false;
|
||||||
|
m_invoke_offset = m__io->read_bytes(0);
|
||||||
|
}
|
||||||
|
m_signature_first = m__io->read_u1();
|
||||||
|
n_signature_rest = true;
|
||||||
|
if (signature_first() == 78) {
|
||||||
|
n_signature_rest = false;
|
||||||
|
m_signature_rest = m__io->read_bytes(3);
|
||||||
|
if (!(signature_rest() == std::string("\x56\x41\x52", 3))) {
|
||||||
|
throw kaitai::validation_not_equal_error<std::string>(std::string("\x56\x41\x52", 3), signature_rest(), _io(), std::string("/types/nvar_entry/seq/2"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
n_size = true;
|
||||||
|
if (signature_first() == 78) {
|
||||||
|
n_size = false;
|
||||||
|
m_size = m__io->read_u2le();
|
||||||
|
{
|
||||||
|
uint16_t _ = size();
|
||||||
|
if (!(_ > ((4 + 2) + 4))) {
|
||||||
|
throw kaitai::validation_expr_error<uint16_t>(size(), _io(), std::string("/types/nvar_entry/seq/3"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
n_next = true;
|
||||||
|
if (signature_first() == 78) {
|
||||||
|
n_next = false;
|
||||||
|
m_next = m__io->read_bits_int_le(24);
|
||||||
|
}
|
||||||
|
m__io->align_to_byte();
|
||||||
|
n_attributes = true;
|
||||||
|
if (signature_first() == 78) {
|
||||||
|
n_attributes = false;
|
||||||
|
m_attributes = new nvar_attributes_t(m__io, this, m__root);
|
||||||
|
}
|
||||||
|
n_body = true;
|
||||||
|
if (signature_first() == 78) {
|
||||||
|
n_body = false;
|
||||||
|
m__raw_body = m__io->read_bytes((size() - ((4 + 2) + 4)));
|
||||||
|
m__io__raw_body = new kaitai::kstream(m__raw_body);
|
||||||
|
m_body = new nvar_entry_body_t(m__io__raw_body, this, m__root);
|
||||||
|
}
|
||||||
|
n_invoke_end_offset = true;
|
||||||
|
if ( ((signature_first() == 78) && (end_offset() >= 0)) ) {
|
||||||
|
n_invoke_end_offset = false;
|
||||||
|
m_invoke_end_offset = m__io->read_bytes(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ami_nvar_t::nvar_entry_t::~nvar_entry_t() {
|
||||||
|
_clean_up();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ami_nvar_t::nvar_entry_t::_clean_up() {
|
||||||
|
if (!n_invoke_offset) {
|
||||||
|
}
|
||||||
|
if (!n_signature_rest) {
|
||||||
|
}
|
||||||
|
if (!n_size) {
|
||||||
|
}
|
||||||
|
if (!n_next) {
|
||||||
|
}
|
||||||
|
if (!n_attributes) {
|
||||||
|
if (m_attributes) {
|
||||||
|
delete m_attributes; m_attributes = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!n_body) {
|
||||||
|
if (m__io__raw_body) {
|
||||||
|
delete m__io__raw_body; m__io__raw_body = 0;
|
||||||
|
}
|
||||||
|
if (m_body) {
|
||||||
|
delete m_body; m_body = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!n_invoke_end_offset) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t ami_nvar_t::nvar_entry_t::offset() {
|
||||||
|
if (f_offset)
|
||||||
|
return m_offset;
|
||||||
|
m_offset = _io()->pos();
|
||||||
|
f_offset = true;
|
||||||
|
return m_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t ami_nvar_t::nvar_entry_t::end_offset() {
|
||||||
|
if (f_end_offset)
|
||||||
|
return m_end_offset;
|
||||||
|
m_end_offset = _io()->pos();
|
||||||
|
f_end_offset = true;
|
||||||
|
return m_end_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
ami_nvar_t::nvar_entry_body_t::nvar_entry_body_t(kaitai::kstream* p__io, ami_nvar_t::nvar_entry_t* p__parent, ami_nvar_t* p__root) : kaitai::kstruct(p__io) {
|
||||||
|
m__parent = p__parent;
|
||||||
|
m__root = p__root;
|
||||||
|
m_ucs2_name = 0;
|
||||||
|
m_extended_header_attributes = 0;
|
||||||
|
f_extended_header_attributes = false;
|
||||||
|
f_data_start_offset = false;
|
||||||
|
f_extended_header_size_field = false;
|
||||||
|
f_extended_header_timestamp = false;
|
||||||
|
f_data_size = false;
|
||||||
|
f_extended_header_checksum = false;
|
||||||
|
f_data_end_offset = false;
|
||||||
|
f_extended_header_size = false;
|
||||||
|
f_extended_header_hash = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
_read();
|
||||||
|
} catch(...) {
|
||||||
|
_clean_up();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ami_nvar_t::nvar_entry_body_t::_read() {
|
||||||
|
n_guid_index = true;
|
||||||
|
if ( ((!(_parent()->attributes()->local_guid())) && (!(_parent()->attributes()->data_only())) && (_parent()->attributes()->valid())) ) {
|
||||||
|
n_guid_index = false;
|
||||||
|
m_guid_index = m__io->read_u1();
|
||||||
|
}
|
||||||
|
n_guid = true;
|
||||||
|
if ( ((_parent()->attributes()->local_guid()) && (!(_parent()->attributes()->data_only())) && (_parent()->attributes()->valid())) ) {
|
||||||
|
n_guid = false;
|
||||||
|
m_guid = m__io->read_bytes(16);
|
||||||
|
}
|
||||||
|
n_ascii_name = true;
|
||||||
|
if ( ((_parent()->attributes()->ascii_name()) && (!(_parent()->attributes()->data_only())) && (_parent()->attributes()->valid())) ) {
|
||||||
|
n_ascii_name = false;
|
||||||
|
m_ascii_name = kaitai::kstream::bytes_to_str(m__io->read_bytes_term(0, false, true, true), std::string("ASCII"));
|
||||||
|
}
|
||||||
|
n_ucs2_name = true;
|
||||||
|
if ( ((!(_parent()->attributes()->ascii_name())) && (!(_parent()->attributes()->data_only())) && (_parent()->attributes()->valid())) ) {
|
||||||
|
n_ucs2_name = false;
|
||||||
|
m_ucs2_name = new ucs2_string_t(m__io, this, m__root);
|
||||||
|
}
|
||||||
|
n_invoke_data_start = true;
|
||||||
|
if (data_start_offset() >= 0) {
|
||||||
|
n_invoke_data_start = false;
|
||||||
|
m_invoke_data_start = m__io->read_bytes(0);
|
||||||
|
}
|
||||||
|
m_data = m__io->read_bytes_full();
|
||||||
|
}
|
||||||
|
|
||||||
|
ami_nvar_t::nvar_entry_body_t::~nvar_entry_body_t() {
|
||||||
|
_clean_up();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ami_nvar_t::nvar_entry_body_t::_clean_up() {
|
||||||
|
if (!n_guid_index) {
|
||||||
|
}
|
||||||
|
if (!n_guid) {
|
||||||
|
}
|
||||||
|
if (!n_ascii_name) {
|
||||||
|
}
|
||||||
|
if (!n_ucs2_name) {
|
||||||
|
if (m_ucs2_name) {
|
||||||
|
delete m_ucs2_name; m_ucs2_name = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!n_invoke_data_start) {
|
||||||
|
}
|
||||||
|
if (f_extended_header_attributes && !n_extended_header_attributes) {
|
||||||
|
if (m_extended_header_attributes) {
|
||||||
|
delete m_extended_header_attributes; m_extended_header_attributes = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (f_extended_header_size_field && !n_extended_header_size_field) {
|
||||||
|
}
|
||||||
|
if (f_extended_header_timestamp && !n_extended_header_timestamp) {
|
||||||
|
}
|
||||||
|
if (f_extended_header_checksum && !n_extended_header_checksum) {
|
||||||
|
}
|
||||||
|
if (f_extended_header_hash && !n_extended_header_hash) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ami_nvar_t::nvar_extended_attributes_t* ami_nvar_t::nvar_entry_body_t::extended_header_attributes() {
|
||||||
|
if (f_extended_header_attributes)
|
||||||
|
return m_extended_header_attributes;
|
||||||
|
n_extended_header_attributes = true;
|
||||||
|
if ( ((_parent()->attributes()->valid()) && (_parent()->attributes()->extended_header()) && (extended_header_size() >= (1 + 2))) ) {
|
||||||
|
n_extended_header_attributes = false;
|
||||||
|
std::streampos _pos = m__io->pos();
|
||||||
|
m__io->seek((_io()->pos() - extended_header_size()));
|
||||||
|
m_extended_header_attributes = new nvar_extended_attributes_t(m__io, this, m__root);
|
||||||
|
m__io->seek(_pos);
|
||||||
|
f_extended_header_attributes = true;
|
||||||
|
}
|
||||||
|
return m_extended_header_attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t ami_nvar_t::nvar_entry_body_t::data_start_offset() {
|
||||||
|
if (f_data_start_offset)
|
||||||
|
return m_data_start_offset;
|
||||||
|
m_data_start_offset = _io()->pos();
|
||||||
|
f_data_start_offset = true;
|
||||||
|
return m_data_start_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t ami_nvar_t::nvar_entry_body_t::extended_header_size_field() {
|
||||||
|
if (f_extended_header_size_field)
|
||||||
|
return m_extended_header_size_field;
|
||||||
|
n_extended_header_size_field = true;
|
||||||
|
if ( ((_parent()->attributes()->valid()) && (_parent()->attributes()->extended_header()) && (_parent()->size() > (((4 + 2) + 4) + 2))) ) {
|
||||||
|
n_extended_header_size_field = false;
|
||||||
|
std::streampos _pos = m__io->pos();
|
||||||
|
m__io->seek((_io()->pos() - 2));
|
||||||
|
m_extended_header_size_field = m__io->read_u2le();
|
||||||
|
m__io->seek(_pos);
|
||||||
|
f_extended_header_size_field = true;
|
||||||
|
}
|
||||||
|
return m_extended_header_size_field;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t ami_nvar_t::nvar_entry_body_t::extended_header_timestamp() {
|
||||||
|
if (f_extended_header_timestamp)
|
||||||
|
return m_extended_header_timestamp;
|
||||||
|
n_extended_header_timestamp = true;
|
||||||
|
if ( ((_parent()->attributes()->valid()) && (_parent()->attributes()->extended_header()) && (extended_header_size() >= ((1 + 8) + 2)) && (extended_header_attributes()->time_based_auth())) ) {
|
||||||
|
n_extended_header_timestamp = false;
|
||||||
|
std::streampos _pos = m__io->pos();
|
||||||
|
m__io->seek(((_io()->pos() - extended_header_size()) + 1));
|
||||||
|
m_extended_header_timestamp = m__io->read_u8le();
|
||||||
|
m__io->seek(_pos);
|
||||||
|
f_extended_header_timestamp = true;
|
||||||
|
}
|
||||||
|
return m_extended_header_timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t ami_nvar_t::nvar_entry_body_t::data_size() {
|
||||||
|
if (f_data_size)
|
||||||
|
return m_data_size;
|
||||||
|
m_data_size = ((data_end_offset() - data_start_offset()) - extended_header_size());
|
||||||
|
f_data_size = true;
|
||||||
|
return m_data_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ami_nvar_t::nvar_entry_body_t::extended_header_checksum() {
|
||||||
|
if (f_extended_header_checksum)
|
||||||
|
return m_extended_header_checksum;
|
||||||
|
n_extended_header_checksum = true;
|
||||||
|
if ( ((_parent()->attributes()->valid()) && (_parent()->attributes()->extended_header()) && (extended_header_size() >= ((1 + 1) + 2)) && (extended_header_attributes()->checksum())) ) {
|
||||||
|
n_extended_header_checksum = false;
|
||||||
|
std::streampos _pos = m__io->pos();
|
||||||
|
m__io->seek(((_io()->pos() - 2) - 1));
|
||||||
|
m_extended_header_checksum = m__io->read_u1();
|
||||||
|
m__io->seek(_pos);
|
||||||
|
f_extended_header_checksum = true;
|
||||||
|
}
|
||||||
|
return m_extended_header_checksum;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t ami_nvar_t::nvar_entry_body_t::data_end_offset() {
|
||||||
|
if (f_data_end_offset)
|
||||||
|
return m_data_end_offset;
|
||||||
|
m_data_end_offset = _io()->pos();
|
||||||
|
f_data_end_offset = true;
|
||||||
|
return m_data_end_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t ami_nvar_t::nvar_entry_body_t::extended_header_size() {
|
||||||
|
if (f_extended_header_size)
|
||||||
|
return m_extended_header_size;
|
||||||
|
m_extended_header_size = ((_parent()->attributes()->extended_header()) ? (((extended_header_size_field() >= (1 + 2)) ? (extended_header_size_field()) : (0))) : (0));
|
||||||
|
f_extended_header_size = true;
|
||||||
|
return m_extended_header_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ami_nvar_t::nvar_entry_body_t::extended_header_hash() {
|
||||||
|
if (f_extended_header_hash)
|
||||||
|
return m_extended_header_hash;
|
||||||
|
n_extended_header_hash = true;
|
||||||
|
if ( ((_parent()->attributes()->valid()) && (_parent()->attributes()->extended_header()) && (extended_header_size() >= (((1 + 8) + 32) + 2)) && (extended_header_attributes()->time_based_auth()) && (!(_parent()->attributes()->data_only()))) ) {
|
||||||
|
n_extended_header_hash = false;
|
||||||
|
std::streampos _pos = m__io->pos();
|
||||||
|
m__io->seek((((_io()->pos() - extended_header_size()) + 1) + 8));
|
||||||
|
m_extended_header_hash = m__io->read_bytes(32);
|
||||||
|
m__io->seek(_pos);
|
||||||
|
f_extended_header_hash = true;
|
||||||
|
}
|
||||||
|
return m_extended_header_hash;
|
||||||
|
}
|
398
common/generated/ami_nvar.h
Normal file
398
common/generated/ami_nvar.h
Normal file
@ -0,0 +1,398 @@
|
|||||||
|
#ifndef AMI_NVAR_H_
|
||||||
|
#define AMI_NVAR_H_
|
||||||
|
|
||||||
|
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
|
||||||
|
|
||||||
|
#include "../kaitai/kaitaistruct.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#if KAITAI_STRUCT_VERSION < 9000L
|
||||||
|
#error "Incompatible Kaitai Struct C++/STL API: version 0.9 or later is required"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class ami_nvar_t : public kaitai::kstruct {
|
||||||
|
|
||||||
|
public:
|
||||||
|
class nvar_attributes_t;
|
||||||
|
class ucs2_string_t;
|
||||||
|
class nvar_extended_attributes_t;
|
||||||
|
class nvar_entry_t;
|
||||||
|
class nvar_entry_body_t;
|
||||||
|
|
||||||
|
ami_nvar_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = 0, ami_nvar_t* p__root = 0);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _read();
|
||||||
|
void _clean_up();
|
||||||
|
|
||||||
|
public:
|
||||||
|
~ami_nvar_t();
|
||||||
|
|
||||||
|
class nvar_attributes_t : public kaitai::kstruct {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
nvar_attributes_t(kaitai::kstream* p__io, ami_nvar_t::nvar_entry_t* p__parent = 0, ami_nvar_t* p__root = 0);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _read();
|
||||||
|
void _clean_up();
|
||||||
|
|
||||||
|
public:
|
||||||
|
~nvar_attributes_t();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_valid;
|
||||||
|
bool m_auth_write;
|
||||||
|
bool m_hw_error_record;
|
||||||
|
bool m_extended_header;
|
||||||
|
bool m_data_only;
|
||||||
|
bool m_local_guid;
|
||||||
|
bool m_ascii_name;
|
||||||
|
bool m_runtime;
|
||||||
|
ami_nvar_t* m__root;
|
||||||
|
ami_nvar_t::nvar_entry_t* m__parent;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool valid() const { return m_valid; }
|
||||||
|
bool auth_write() const { return m_auth_write; }
|
||||||
|
bool hw_error_record() const { return m_hw_error_record; }
|
||||||
|
bool extended_header() const { return m_extended_header; }
|
||||||
|
bool data_only() const { return m_data_only; }
|
||||||
|
bool local_guid() const { return m_local_guid; }
|
||||||
|
bool ascii_name() const { return m_ascii_name; }
|
||||||
|
bool runtime() const { return m_runtime; }
|
||||||
|
ami_nvar_t* _root() const { return m__root; }
|
||||||
|
ami_nvar_t::nvar_entry_t* _parent() const { return m__parent; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class ucs2_string_t : public kaitai::kstruct {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
ucs2_string_t(kaitai::kstream* p__io, ami_nvar_t::nvar_entry_body_t* p__parent = 0, ami_nvar_t* p__root = 0);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _read();
|
||||||
|
void _clean_up();
|
||||||
|
|
||||||
|
public:
|
||||||
|
~ucs2_string_t();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<uint16_t>* m_ucs2_chars;
|
||||||
|
ami_nvar_t* m__root;
|
||||||
|
ami_nvar_t::nvar_entry_body_t* m__parent;
|
||||||
|
|
||||||
|
public:
|
||||||
|
std::vector<uint16_t>* ucs2_chars() const { return m_ucs2_chars; }
|
||||||
|
ami_nvar_t* _root() const { return m__root; }
|
||||||
|
ami_nvar_t::nvar_entry_body_t* _parent() const { return m__parent; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class nvar_extended_attributes_t : public kaitai::kstruct {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
nvar_extended_attributes_t(kaitai::kstream* p__io, ami_nvar_t::nvar_entry_body_t* p__parent = 0, ami_nvar_t* p__root = 0);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _read();
|
||||||
|
void _clean_up();
|
||||||
|
|
||||||
|
public:
|
||||||
|
~nvar_extended_attributes_t();
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint64_t m_reserved_high;
|
||||||
|
bool m_time_based_auth;
|
||||||
|
bool m_auth_write;
|
||||||
|
uint64_t m_reserved_low;
|
||||||
|
bool m_checksum;
|
||||||
|
ami_nvar_t* m__root;
|
||||||
|
ami_nvar_t::nvar_entry_body_t* m__parent;
|
||||||
|
|
||||||
|
public:
|
||||||
|
uint64_t reserved_high() const { return m_reserved_high; }
|
||||||
|
bool time_based_auth() const { return m_time_based_auth; }
|
||||||
|
bool auth_write() const { return m_auth_write; }
|
||||||
|
uint64_t reserved_low() const { return m_reserved_low; }
|
||||||
|
bool checksum() const { return m_checksum; }
|
||||||
|
ami_nvar_t* _root() const { return m__root; }
|
||||||
|
ami_nvar_t::nvar_entry_body_t* _parent() const { return m__parent; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class nvar_entry_t : public kaitai::kstruct {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
nvar_entry_t(kaitai::kstream* p__io, ami_nvar_t* p__parent = 0, ami_nvar_t* p__root = 0);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _read();
|
||||||
|
void _clean_up();
|
||||||
|
|
||||||
|
public:
|
||||||
|
~nvar_entry_t();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool f_offset;
|
||||||
|
int32_t m_offset;
|
||||||
|
|
||||||
|
public:
|
||||||
|
int32_t offset();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool f_end_offset;
|
||||||
|
int32_t m_end_offset;
|
||||||
|
|
||||||
|
public:
|
||||||
|
int32_t end_offset();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_invoke_offset;
|
||||||
|
bool n_invoke_offset;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool _is_null_invoke_offset() { invoke_offset(); return n_invoke_offset; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8_t m_signature_first;
|
||||||
|
std::string m_signature_rest;
|
||||||
|
bool n_signature_rest;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool _is_null_signature_rest() { signature_rest(); return n_signature_rest; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint16_t m_size;
|
||||||
|
bool n_size;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool _is_null_size() { size(); return n_size; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint64_t m_next;
|
||||||
|
bool n_next;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool _is_null_next() { next(); return n_next; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
nvar_attributes_t* m_attributes;
|
||||||
|
bool n_attributes;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool _is_null_attributes() { attributes(); return n_attributes; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
nvar_entry_body_t* m_body;
|
||||||
|
bool n_body;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool _is_null_body() { body(); return n_body; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_invoke_end_offset;
|
||||||
|
bool n_invoke_end_offset;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool _is_null_invoke_end_offset() { invoke_end_offset(); return n_invoke_end_offset; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
ami_nvar_t* m__root;
|
||||||
|
ami_nvar_t* m__parent;
|
||||||
|
std::string m__raw_body;
|
||||||
|
bool n__raw_body;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool _is_null__raw_body() { _raw_body(); return n__raw_body; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
kaitai::kstream* m__io__raw_body;
|
||||||
|
|
||||||
|
public:
|
||||||
|
std::string invoke_offset() const { return m_invoke_offset; }
|
||||||
|
uint8_t signature_first() const { return m_signature_first; }
|
||||||
|
std::string signature_rest() const { return m_signature_rest; }
|
||||||
|
uint16_t size() const { return m_size; }
|
||||||
|
uint64_t next() const { return m_next; }
|
||||||
|
nvar_attributes_t* attributes() const { return m_attributes; }
|
||||||
|
nvar_entry_body_t* body() const { return m_body; }
|
||||||
|
std::string invoke_end_offset() const { return m_invoke_end_offset; }
|
||||||
|
ami_nvar_t* _root() const { return m__root; }
|
||||||
|
ami_nvar_t* _parent() const { return m__parent; }
|
||||||
|
std::string _raw_body() const { return m__raw_body; }
|
||||||
|
kaitai::kstream* _io__raw_body() const { return m__io__raw_body; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class nvar_entry_body_t : public kaitai::kstruct {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
nvar_entry_body_t(kaitai::kstream* p__io, ami_nvar_t::nvar_entry_t* p__parent = 0, ami_nvar_t* p__root = 0);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _read();
|
||||||
|
void _clean_up();
|
||||||
|
|
||||||
|
public:
|
||||||
|
~nvar_entry_body_t();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool f_extended_header_attributes;
|
||||||
|
nvar_extended_attributes_t* m_extended_header_attributes;
|
||||||
|
bool n_extended_header_attributes;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool _is_null_extended_header_attributes() { extended_header_attributes(); return n_extended_header_attributes; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
public:
|
||||||
|
nvar_extended_attributes_t* extended_header_attributes();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool f_data_start_offset;
|
||||||
|
int32_t m_data_start_offset;
|
||||||
|
|
||||||
|
public:
|
||||||
|
int32_t data_start_offset();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool f_extended_header_size_field;
|
||||||
|
uint16_t m_extended_header_size_field;
|
||||||
|
bool n_extended_header_size_field;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool _is_null_extended_header_size_field() { extended_header_size_field(); return n_extended_header_size_field; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
public:
|
||||||
|
uint16_t extended_header_size_field();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool f_extended_header_timestamp;
|
||||||
|
uint64_t m_extended_header_timestamp;
|
||||||
|
bool n_extended_header_timestamp;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool _is_null_extended_header_timestamp() { extended_header_timestamp(); return n_extended_header_timestamp; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
public:
|
||||||
|
uint64_t extended_header_timestamp();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool f_data_size;
|
||||||
|
int32_t m_data_size;
|
||||||
|
|
||||||
|
public:
|
||||||
|
int32_t data_size();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool f_extended_header_checksum;
|
||||||
|
uint8_t m_extended_header_checksum;
|
||||||
|
bool n_extended_header_checksum;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool _is_null_extended_header_checksum() { extended_header_checksum(); return n_extended_header_checksum; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
public:
|
||||||
|
uint8_t extended_header_checksum();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool f_data_end_offset;
|
||||||
|
int32_t m_data_end_offset;
|
||||||
|
|
||||||
|
public:
|
||||||
|
int32_t data_end_offset();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool f_extended_header_size;
|
||||||
|
uint16_t m_extended_header_size;
|
||||||
|
|
||||||
|
public:
|
||||||
|
uint16_t extended_header_size();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool f_extended_header_hash;
|
||||||
|
std::string m_extended_header_hash;
|
||||||
|
bool n_extended_header_hash;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool _is_null_extended_header_hash() { extended_header_hash(); return n_extended_header_hash; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
public:
|
||||||
|
std::string extended_header_hash();
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8_t m_guid_index;
|
||||||
|
bool n_guid_index;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool _is_null_guid_index() { guid_index(); return n_guid_index; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_guid;
|
||||||
|
bool n_guid;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool _is_null_guid() { guid(); return n_guid; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_ascii_name;
|
||||||
|
bool n_ascii_name;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool _is_null_ascii_name() { ascii_name(); return n_ascii_name; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
ucs2_string_t* m_ucs2_name;
|
||||||
|
bool n_ucs2_name;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool _is_null_ucs2_name() { ucs2_name(); return n_ucs2_name; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_invoke_data_start;
|
||||||
|
bool n_invoke_data_start;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool _is_null_invoke_data_start() { invoke_data_start(); return n_invoke_data_start; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_data;
|
||||||
|
ami_nvar_t* m__root;
|
||||||
|
ami_nvar_t::nvar_entry_t* m__parent;
|
||||||
|
|
||||||
|
public:
|
||||||
|
uint8_t guid_index() const { return m_guid_index; }
|
||||||
|
std::string guid() const { return m_guid; }
|
||||||
|
std::string ascii_name() const { return m_ascii_name; }
|
||||||
|
ucs2_string_t* ucs2_name() const { return m_ucs2_name; }
|
||||||
|
std::string invoke_data_start() const { return m_invoke_data_start; }
|
||||||
|
std::string data() const { return m_data; }
|
||||||
|
ami_nvar_t* _root() const { return m__root; }
|
||||||
|
ami_nvar_t::nvar_entry_t* _parent() const { return m__parent; }
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<nvar_entry_t*>* m_entries;
|
||||||
|
ami_nvar_t* m__root;
|
||||||
|
kaitai::kstruct* m__parent;
|
||||||
|
|
||||||
|
public:
|
||||||
|
std::vector<nvar_entry_t*>* entries() const { return m_entries; }
|
||||||
|
ami_nvar_t* _root() const { return m__root; }
|
||||||
|
kaitai::kstruct* _parent() const { return m__parent; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // AMI_NVAR_H_
|
162
common/ksy/ami_nvar.ksy
Normal file
162
common/ksy/ami_nvar.ksy
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
meta:
|
||||||
|
id: ami_nvar
|
||||||
|
title: AMI Aptio NVRAM Storage
|
||||||
|
application: AMI Aptio-based UEFI firmware
|
||||||
|
file-extension: nvar
|
||||||
|
tags:
|
||||||
|
- firmware
|
||||||
|
license: CC0-1.0
|
||||||
|
ks-version: 0.9
|
||||||
|
endian: le
|
||||||
|
|
||||||
|
seq:
|
||||||
|
- id: entries
|
||||||
|
type: nvar_entry
|
||||||
|
repeat: until
|
||||||
|
repeat-until: _.signature_first != 0x4e or _io.eof
|
||||||
|
|
||||||
|
types:
|
||||||
|
nvar_entry:
|
||||||
|
seq:
|
||||||
|
- id: invoke_offset
|
||||||
|
size: 0
|
||||||
|
if: offset >= 0
|
||||||
|
- id: signature_first
|
||||||
|
type: u1
|
||||||
|
- id: signature_rest
|
||||||
|
contents: [VAR]
|
||||||
|
if: signature_first == 0x4e
|
||||||
|
- id: size
|
||||||
|
type: u2
|
||||||
|
valid:
|
||||||
|
expr: _ > sizeof<u4> + sizeof<u2> + sizeof<u4>
|
||||||
|
if: signature_first == 0x4e
|
||||||
|
- id: next
|
||||||
|
type: b24le
|
||||||
|
if: signature_first == 0x4e
|
||||||
|
- id: attributes
|
||||||
|
type: nvar_attributes
|
||||||
|
if: signature_first == 0x4e
|
||||||
|
- id: body
|
||||||
|
type: nvar_entry_body
|
||||||
|
size: size - (sizeof<u4> + sizeof<u2> + sizeof<u4>)
|
||||||
|
if: signature_first == 0x4e
|
||||||
|
- id: invoke_end_offset
|
||||||
|
size: 0
|
||||||
|
if: signature_first == 0x4e and end_offset >= 0
|
||||||
|
instances:
|
||||||
|
offset:
|
||||||
|
value: _io.pos
|
||||||
|
end_offset:
|
||||||
|
value: _io.pos
|
||||||
|
|
||||||
|
nvar_attributes:
|
||||||
|
seq:
|
||||||
|
- id: valid
|
||||||
|
type: b1
|
||||||
|
- id: auth_write
|
||||||
|
type: b1
|
||||||
|
- id: hw_error_record
|
||||||
|
type: b1
|
||||||
|
- id: extended_header
|
||||||
|
type: b1
|
||||||
|
- id: data_only
|
||||||
|
type: b1
|
||||||
|
- id: local_guid
|
||||||
|
type: b1
|
||||||
|
- id: ascii_name
|
||||||
|
type: b1
|
||||||
|
- id: runtime
|
||||||
|
type: b1
|
||||||
|
|
||||||
|
nvar_extended_attributes:
|
||||||
|
seq:
|
||||||
|
- id: reserved_high
|
||||||
|
type: b2
|
||||||
|
- id: time_based_auth
|
||||||
|
type: b1
|
||||||
|
- id: auth_write
|
||||||
|
type: b1
|
||||||
|
- id: reserved_low
|
||||||
|
type: b3
|
||||||
|
- id: checksum
|
||||||
|
type: b1
|
||||||
|
|
||||||
|
ucs2_string:
|
||||||
|
seq:
|
||||||
|
- id: ucs2_chars
|
||||||
|
type: u2
|
||||||
|
repeat: until
|
||||||
|
repeat-until: _ == 0
|
||||||
|
|
||||||
|
nvar_entry_body:
|
||||||
|
seq:
|
||||||
|
- id: guid_index
|
||||||
|
type: u1
|
||||||
|
if: (not _parent.attributes.local_guid)
|
||||||
|
and (not _parent.attributes.data_only)
|
||||||
|
and (_parent.attributes.valid)
|
||||||
|
- id: guid
|
||||||
|
size: 16
|
||||||
|
if: (_parent.attributes.local_guid)
|
||||||
|
and (not _parent.attributes.data_only)
|
||||||
|
and (_parent.attributes.valid)
|
||||||
|
- id: ascii_name
|
||||||
|
type: strz
|
||||||
|
encoding: ASCII
|
||||||
|
if: (_parent.attributes.ascii_name)
|
||||||
|
and (not _parent.attributes.data_only)
|
||||||
|
and (_parent.attributes.valid)
|
||||||
|
- id: ucs2_name
|
||||||
|
type: ucs2_string
|
||||||
|
if: (not _parent.attributes.ascii_name)
|
||||||
|
and (not _parent.attributes.data_only)
|
||||||
|
and (_parent.attributes.valid)
|
||||||
|
- id: invoke_data_start
|
||||||
|
size: 0
|
||||||
|
if: data_start_offset >= 0
|
||||||
|
- id: data
|
||||||
|
size-eos: true
|
||||||
|
instances:
|
||||||
|
extended_header_size_field:
|
||||||
|
pos: _io.pos - sizeof<u2>
|
||||||
|
type: u2
|
||||||
|
if: _parent.attributes.valid
|
||||||
|
and _parent.attributes.extended_header
|
||||||
|
and _parent.size > sizeof<u4> + sizeof<u2> + sizeof<u4> + sizeof<u2>
|
||||||
|
extended_header_size:
|
||||||
|
value: '_parent.attributes.extended_header ? (extended_header_size_field >= sizeof<nvar_extended_attributes> + sizeof<u2> ? extended_header_size_field : 0) : 0'
|
||||||
|
extended_header_attributes:
|
||||||
|
pos: _io.pos - extended_header_size
|
||||||
|
type: nvar_extended_attributes
|
||||||
|
if: _parent.attributes.valid
|
||||||
|
and _parent.attributes.extended_header
|
||||||
|
and (extended_header_size >= sizeof<nvar_extended_attributes> + sizeof<u2>)
|
||||||
|
extended_header_timestamp:
|
||||||
|
pos: _io.pos - extended_header_size + sizeof<nvar_extended_attributes>
|
||||||
|
type: u8
|
||||||
|
if: _parent.attributes.valid
|
||||||
|
and _parent.attributes.extended_header
|
||||||
|
and (extended_header_size >= sizeof<nvar_extended_attributes> + sizeof<u8> + sizeof<u2>)
|
||||||
|
and extended_header_attributes.time_based_auth
|
||||||
|
extended_header_hash:
|
||||||
|
pos: _io.pos - extended_header_size + sizeof<nvar_extended_attributes> + sizeof<u8>
|
||||||
|
size: 32
|
||||||
|
if: _parent.attributes.valid
|
||||||
|
and _parent.attributes.extended_header
|
||||||
|
and (extended_header_size >= sizeof<nvar_extended_attributes> + sizeof<u8> + 32 + sizeof<u2>)
|
||||||
|
and extended_header_attributes.time_based_auth
|
||||||
|
and (not _parent.attributes.data_only)
|
||||||
|
extended_header_checksum:
|
||||||
|
pos: _io.pos - sizeof<u2> - sizeof<u1>
|
||||||
|
type: u1
|
||||||
|
if: _parent.attributes.valid
|
||||||
|
and _parent.attributes.extended_header
|
||||||
|
and (extended_header_size >= sizeof<nvar_extended_attributes> + sizeof<u1> + sizeof<u2>)
|
||||||
|
and extended_header_attributes.checksum
|
||||||
|
data_start_offset:
|
||||||
|
value: _io.pos
|
||||||
|
data_end_offset:
|
||||||
|
value: _io.pos
|
||||||
|
data_size:
|
||||||
|
value: (data_end_offset - data_start_offset) - extended_header_size
|
@ -12,356 +12,270 @@
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef U_ENABLE_NVRAM_PARSING_SUPPORT
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "nvramparser.h"
|
#include "nvramparser.h"
|
||||||
#include "parsingdata.h"
|
#include "parsingdata.h"
|
||||||
|
#include "ustring.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
#include "nvram.h"
|
#include "nvram.h"
|
||||||
#include "ffs.h"
|
#include "ffs.h"
|
||||||
#include "intel_microcode.h"
|
#include "intel_microcode.h"
|
||||||
|
|
||||||
#ifdef U_ENABLE_NVRAM_PARSING_SUPPORT
|
#include "umemstream.h"
|
||||||
|
#include "kaitai/kaitaistream.h"
|
||||||
|
#include "generated/ami_nvar.h"
|
||||||
|
|
||||||
USTATUS NvramParser::parseNvarStore(const UModelIndex & index)
|
USTATUS NvramParser::parseNvarStore(const UModelIndex & index)
|
||||||
{
|
{
|
||||||
// Sanity check
|
// Sanity check
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
return U_INVALID_PARAMETER;
|
return U_INVALID_PARAMETER;
|
||||||
|
|
||||||
// Obtain required information from parent file
|
UByteArray nvar = model->body(index);
|
||||||
UINT8 emptyByte = 0xFF;
|
|
||||||
UModelIndex parentFileIndex = model->findParentOfType(index, Types::File);
|
|
||||||
if (parentFileIndex.isValid() && model->hasEmptyParsingData(parentFileIndex) == false) {
|
|
||||||
UByteArray data = model->parsingData(parentFileIndex);
|
|
||||||
const FILE_PARSING_DATA* pdata = (const FILE_PARSING_DATA*)data.constData();
|
|
||||||
emptyByte = readUnaligned(pdata).emptyByte;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get local offset
|
// Nothing to parse in an empty store
|
||||||
UINT32 localOffset = (UINT32)model->header(index).size();
|
if (nvar.isEmpty())
|
||||||
|
return U_SUCCESS;
|
||||||
|
|
||||||
// Get item data
|
try {
|
||||||
const UByteArray data = model->body(index);
|
const UINT32 localOffset = (UINT32)model->header(index).size();
|
||||||
|
umemstream is(nvar.constData(), nvar.size());
|
||||||
|
kaitai::kstream ks(&is);
|
||||||
|
ami_nvar_t parsed(&ks);
|
||||||
|
|
||||||
// Parse all entries
|
UINT16 guidsInStore = 0;
|
||||||
UINT32 offset = 0;
|
UINT32 currentEntryIndex = 0;
|
||||||
UINT32 guidsInStore = 0;
|
for (const auto & entry : *parsed.entries()) {
|
||||||
while (1) {
|
UINT8 subtype = Subtypes::FullNvarEntry;
|
||||||
bool msgUnknownExtDataFormat = false;
|
UString name;
|
||||||
bool msgExtHeaderTooLong = false;
|
UString text;
|
||||||
bool msgExtDataTooShort = false;
|
UString info;
|
||||||
|
UString guid;
|
||||||
|
UByteArray header;
|
||||||
|
UByteArray body;
|
||||||
|
UByteArray tail;
|
||||||
|
|
||||||
bool isInvalid = false;
|
// This is a terminating entry, needs special processing
|
||||||
bool isInvalidLink = false;
|
if (entry->_is_null_signature_rest()) {
|
||||||
bool hasExtendedHeader = false;
|
UINT32 guidAreaSize = guidsInStore * sizeof(EFI_GUID);
|
||||||
bool hasChecksum = false;
|
UINT32 unparsedSize = (UINT32)nvar.size() - entry->offset() - guidAreaSize;
|
||||||
bool hasTimestamp = false;
|
|
||||||
bool hasHash = false;
|
|
||||||
bool hasGuidIndex = false;
|
|
||||||
|
|
||||||
UINT32 guidIndex = 0;
|
// Check if the data left is a free space or a padding
|
||||||
UINT8 storedChecksum = 0;
|
UByteArray padding = nvar.mid(entry->offset(), unparsedSize);
|
||||||
UINT8 calculatedChecksum = 0;
|
|
||||||
UINT32 extendedHeaderSize = 0;
|
|
||||||
UINT8 extendedAttributes = 0;
|
|
||||||
UINT64 timestamp = 0;
|
|
||||||
UByteArray hash;
|
|
||||||
|
|
||||||
UINT8 subtype = Subtypes::FullNvarEntry;
|
// Get info
|
||||||
UString name;
|
UString info = usprintf("Full size: %Xh (%u)", (UINT32)padding.size(), (UINT32)padding.size());
|
||||||
UString guid;
|
|
||||||
UString text;
|
|
||||||
UByteArray header;
|
|
||||||
UByteArray body;
|
|
||||||
UByteArray tail;
|
|
||||||
|
|
||||||
UINT32 guidAreaSize = guidsInStore * sizeof(EFI_GUID);
|
if ((UINT32)padding.count(0xFF) == unparsedSize) { // Free space
|
||||||
UINT32 unparsedSize = (UINT32)data.size() - offset - guidAreaSize;
|
// Add tree item
|
||||||
|
model->addItem(localOffset + entry->offset(), Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), padding, UByteArray(), Fixed, index);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Nothing is parsed yet, but the file is not empty
|
||||||
|
if (entry->offset() == 0) {
|
||||||
|
msg(usprintf("%s: file can't be parsed as NVAR variable store", __FUNCTION__), index);
|
||||||
|
return U_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
// Get entry header
|
// Add tree item
|
||||||
const NVAR_ENTRY_HEADER* entryHeader = (const NVAR_ENTRY_HEADER*)(data.constData() + offset);
|
model->addItem(localOffset + entry->offset(), Types::Padding, getPaddingType(padding), UString("Padding"), UString(), info, UByteArray(), padding, UByteArray(), Fixed, index);
|
||||||
|
}
|
||||||
|
|
||||||
// Check header size and signature
|
// Add GUID store area
|
||||||
if (unparsedSize < sizeof(NVAR_ENTRY_HEADER) ||
|
UByteArray guidArea = nvar.right(guidAreaSize);
|
||||||
entryHeader->Signature != NVRAM_NVAR_ENTRY_SIGNATURE ||
|
// Get info
|
||||||
unparsedSize < entryHeader->Size) {
|
name = UString("GUID store");
|
||||||
// Check if the data left is a free space or a padding
|
info = usprintf("Full size: %Xh (%u)\nGUIDs in store: %u",
|
||||||
UByteArray padding = data.mid(offset, unparsedSize);
|
(UINT32)guidArea.size(), (UINT32)guidArea.size(),
|
||||||
|
guidsInStore);
|
||||||
// Get info
|
|
||||||
UString info = usprintf("Full size: %Xh (%u)", (UINT32)padding.size(), (UINT32)padding.size());
|
|
||||||
|
|
||||||
if ((UINT32)padding.count(emptyByte) == unparsedSize) { // Free space
|
|
||||||
// Add tree item
|
// Add tree item
|
||||||
model->addItem(localOffset + offset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), padding, UByteArray(), Fixed, index);
|
model->addItem((UINT32)(localOffset + entry->offset() + padding.size()), Types::NvarGuidStore, 0, name, UString(), info, UByteArray(), guidArea, UByteArray(), Fixed, index);
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Nothing is parsed yet, but the file is not empty
|
|
||||||
if (!offset) {
|
|
||||||
msg(usprintf("%s: file can't be parsed as NVAR variables store", __FUNCTION__), index);
|
|
||||||
return U_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add tree item
|
return U_SUCCESS;
|
||||||
model->addItem(localOffset + offset, Types::Padding, getPaddingType(padding), UString("Padding"), UString(), info, UByteArray(), padding, UByteArray(), Fixed, index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add GUID store area
|
// This is a normal entry
|
||||||
UByteArray guidArea = data.right(guidAreaSize);
|
const auto entry_body = entry->body();
|
||||||
// Get info
|
|
||||||
name = UString("GUID store");
|
|
||||||
info = usprintf("Full size: %Xh (%u)\nGUIDs in store: %u",
|
|
||||||
(UINT32)guidArea.size(), (UINT32)guidArea.size(),
|
|
||||||
guidsInStore);
|
|
||||||
// Add tree item
|
|
||||||
model->addItem((UINT32)(localOffset + offset + padding.size()), Types::Padding, getPaddingType(guidArea), name, UString(), info, UByteArray(), guidArea, UByteArray(), Fixed, index);
|
|
||||||
|
|
||||||
return U_SUCCESS;
|
// Set default next to predefined last value
|
||||||
}
|
NVAR_ENTRY_PARSING_DATA pdata = {};
|
||||||
|
pdata.emptyByte = 0xFF;
|
||||||
|
pdata.next = 0xFFFFFF;
|
||||||
|
pdata.isValid = TRUE;
|
||||||
|
|
||||||
// Contruct generic header and body
|
// Check for invalid entry
|
||||||
header = data.mid(offset, sizeof(NVAR_ENTRY_HEADER));
|
if (!entry->attributes()->valid()) {
|
||||||
body = data.mid(offset + sizeof(NVAR_ENTRY_HEADER), entryHeader->Size - sizeof(NVAR_ENTRY_HEADER));
|
subtype = Subtypes::InvalidNvarEntry;
|
||||||
|
name = UString("Invalid");
|
||||||
UINT32 lastVariableFlag = emptyByte ? 0xFFFFFF : 0;
|
pdata.isValid = FALSE;
|
||||||
|
goto processing_done;
|
||||||
// Set default next to predefined last value
|
|
||||||
NVAR_ENTRY_PARSING_DATA pdata = {};
|
|
||||||
pdata.emptyByte = emptyByte;
|
|
||||||
pdata.next = lastVariableFlag;
|
|
||||||
|
|
||||||
// Entry is marked as invalid
|
|
||||||
if ((entryHeader->Attributes & NVRAM_NVAR_ENTRY_VALID) == 0) { // Valid attribute is not set
|
|
||||||
isInvalid = true;
|
|
||||||
// Do not parse further
|
|
||||||
goto parsing_done;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add next node information to parsing data
|
|
||||||
if (entryHeader->Next != lastVariableFlag) {
|
|
||||||
subtype = Subtypes::LinkNvarEntry;
|
|
||||||
pdata.next = entryHeader->Next;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Entry with extended header
|
|
||||||
if (entryHeader->Attributes & NVRAM_NVAR_ENTRY_EXT_HEADER) {
|
|
||||||
hasExtendedHeader = true;
|
|
||||||
msgUnknownExtDataFormat = true;
|
|
||||||
|
|
||||||
extendedHeaderSize = readUnaligned((UINT16*)(body.constData() + body.size() - sizeof(UINT16)));
|
|
||||||
if (extendedHeaderSize > (UINT32)body.size()) {
|
|
||||||
msgExtHeaderTooLong = true;
|
|
||||||
isInvalid = true;
|
|
||||||
// Do not parse further
|
|
||||||
goto parsing_done;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extendedAttributes = *(UINT8*)(body.constData() + body.size() - extendedHeaderSize);
|
// Check for link entry
|
||||||
|
if (entry->next() != 0xFFFFFF) {
|
||||||
// Variable with checksum
|
subtype = Subtypes::LinkNvarEntry;
|
||||||
if (extendedAttributes & NVRAM_NVAR_ENTRY_EXT_CHECKSUM) {
|
pdata.next = (UINT32)entry->next();
|
||||||
// Get stored checksum
|
|
||||||
storedChecksum = *(UINT8*)(body.constData() + body.size() - sizeof(UINT16) - sizeof(UINT8));
|
|
||||||
|
|
||||||
// Recalculate checksum for the variable
|
|
||||||
calculatedChecksum = 0;
|
|
||||||
// Include entry data
|
|
||||||
UINT8* start = (UINT8*)(entryHeader + 1);
|
|
||||||
for (UINT8* p = start; p < start + entryHeader->Size - sizeof(NVAR_ENTRY_HEADER); p++) {
|
|
||||||
calculatedChecksum += *p;
|
|
||||||
}
|
|
||||||
// Include entry size and flags
|
|
||||||
start = (UINT8*)&entryHeader->Size;
|
|
||||||
for (UINT8*p = start; p < start + sizeof(UINT16); p++) {
|
|
||||||
calculatedChecksum += *p;
|
|
||||||
}
|
|
||||||
// Include entry attributes
|
|
||||||
calculatedChecksum += entryHeader->Attributes;
|
|
||||||
|
|
||||||
hasChecksum = true;
|
|
||||||
msgUnknownExtDataFormat = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tail = body.mid(body.size() - extendedHeaderSize);
|
// Check for data-only entry (nameless and GUIDless entry or link)
|
||||||
body = body.left(body.size() - extendedHeaderSize);
|
if (entry->attributes()->data_only()) {
|
||||||
|
// Search backwards for a previous entry with a link to this variable
|
||||||
|
UModelIndex prevEntryIndex;
|
||||||
|
if (currentEntryIndex > 0) {
|
||||||
|
for (UINT32 i = currentEntryIndex - 1; i > 0; i--) {
|
||||||
|
const auto previousEntry = parsed.entries()->at(i);
|
||||||
|
|
||||||
// Entry with authenticated write (for SecureBoot)
|
if (previousEntry == entry)
|
||||||
if (entryHeader->Attributes & NVRAM_NVAR_ENTRY_AUTH_WRITE) {
|
break;
|
||||||
if ((entryHeader->Attributes & NVRAM_NVAR_ENTRY_DATA_ONLY)) {// Data only auth. variables has no hash
|
|
||||||
if ((UINT32)tail.size() < sizeof(UINT64)) {
|
|
||||||
msgExtDataTooShort = true;
|
|
||||||
isInvalid = true;
|
|
||||||
// Do not parse further
|
|
||||||
goto parsing_done;
|
|
||||||
}
|
|
||||||
|
|
||||||
timestamp = readUnaligned(tail.constData() + sizeof(UINT8));
|
if (previousEntry->next() + previousEntry->offset() == entry->offset()) { // Previous link is present and valid
|
||||||
hasTimestamp = true;
|
prevEntryIndex = index.model()->index(i, 0, index);
|
||||||
msgUnknownExtDataFormat = false;
|
// Make sure that we are linking to a valid entry
|
||||||
}
|
NVAR_ENTRY_PARSING_DATA pd = readUnaligned((NVAR_ENTRY_PARSING_DATA*)model->parsingData(prevEntryIndex).constData());
|
||||||
else { // Full or link variable have hash
|
if (!pd.isValid) {
|
||||||
if ((UINT32)tail.size() < sizeof(UINT64) + SHA256_HASH_SIZE) {
|
prevEntryIndex = UModelIndex();
|
||||||
msgExtDataTooShort = true;
|
}
|
||||||
isInvalid = true;
|
break;
|
||||||
// Do not parse further
|
}
|
||||||
goto parsing_done;
|
|
||||||
}
|
|
||||||
|
|
||||||
timestamp = readUnaligned((UINT64*)(tail.constData() + sizeof(UINT8)));
|
|
||||||
hash = tail.mid(sizeof(UINT64) + sizeof(UINT8), SHA256_HASH_SIZE);
|
|
||||||
hasTimestamp = true;
|
|
||||||
hasHash = true;
|
|
||||||
msgUnknownExtDataFormat = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Entry is data-only (nameless and GUIDless entry or link)
|
|
||||||
if (entryHeader->Attributes & NVRAM_NVAR_ENTRY_DATA_ONLY) { // Data-only attribute is set
|
|
||||||
isInvalidLink = true;
|
|
||||||
UModelIndex nvarIndex;
|
|
||||||
// Search previously added entries for a link to this variable
|
|
||||||
// WARNING: O(n^2), may be very slow
|
|
||||||
for (int i = model->rowCount(index) - 1; i >= 0; i--) {
|
|
||||||
nvarIndex = index.model()->index(i, 0, index);
|
|
||||||
|
|
||||||
if (model->hasEmptyParsingData(nvarIndex) == false) {
|
|
||||||
UByteArray nvarData = model->parsingData(nvarIndex);
|
|
||||||
const NVAR_ENTRY_PARSING_DATA nvarPdata = readUnaligned((const NVAR_ENTRY_PARSING_DATA*)nvarData.constData());
|
|
||||||
if (nvarPdata.isValid && nvarPdata.next + model->offset(nvarIndex) - localOffset == offset) { // Previous link is present and valid
|
|
||||||
isInvalidLink = false;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
// Check if the link is valid
|
||||||
// Check if the link is valid
|
if (prevEntryIndex.isValid()) {
|
||||||
if (!isInvalidLink) {
|
// Use the name and text of the previous entry
|
||||||
// Use the name and text of the previous link
|
name = model->name(prevEntryIndex);
|
||||||
name = model->name(nvarIndex);
|
text = model->text(prevEntryIndex);
|
||||||
text = model->text(nvarIndex);
|
|
||||||
|
|
||||||
if (entryHeader->Next == lastVariableFlag)
|
if (entry->next() == 0xFFFFFF)
|
||||||
subtype = Subtypes::DataNvarEntry;
|
subtype = Subtypes::DataNvarEntry;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
subtype = Subtypes::InvalidLinkNvarEntry;
|
||||||
|
name = UString("InvalidLink");
|
||||||
|
pdata.isValid = FALSE;
|
||||||
|
}
|
||||||
|
goto processing_done;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do not parse further
|
// Obtain text
|
||||||
goto parsing_done;
|
if (!entry_body->_is_null_ascii_name()) {
|
||||||
}
|
text = entry_body->ascii_name().c_str();
|
||||||
|
|
||||||
// Get entry name
|
|
||||||
{
|
|
||||||
UINT32 nameOffset = (entryHeader->Attributes & NVRAM_NVAR_ENTRY_GUID) ? sizeof(EFI_GUID) : sizeof(UINT8); // GUID can be stored with the variable or in a separate store, so there will only be an index of it
|
|
||||||
CHAR8* namePtr = (CHAR8*)(entryHeader + 1) + nameOffset;
|
|
||||||
UINT32 nameSize = 0;
|
|
||||||
if (entryHeader->Attributes & NVRAM_NVAR_ENTRY_ASCII_NAME) { // Name is stored as ASCII string of CHAR8s
|
|
||||||
text = UString(namePtr);
|
|
||||||
nameSize = (UINT32)(text.length() + 1);
|
|
||||||
}
|
}
|
||||||
else { // Name is stored as UCS2 string of CHAR16s
|
else if (!entry_body->_is_null_ucs2_name()) {
|
||||||
text = uFromUcs2(namePtr);
|
UByteArray temp;
|
||||||
nameSize = (UINT32)((text.length() + 1) * 2);
|
for (const auto & ch : *entry_body->ucs2_name()->ucs2_chars()) {
|
||||||
|
temp += UByteArray((const char*)&ch, sizeof(ch));
|
||||||
|
}
|
||||||
|
text = uFromUcs2(temp.constData());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get entry GUID
|
// Obtain GUID
|
||||||
if (entryHeader->Attributes & NVRAM_NVAR_ENTRY_GUID) { // GUID is strored in the variable itself
|
if (!entry_body->_is_null_guid()) { // GUID is stored in the entry itself
|
||||||
name = guidToUString(readUnaligned((EFI_GUID*)(entryHeader + 1)));
|
const EFI_GUID g = readUnaligned((EFI_GUID*)entry_body->guid().c_str());
|
||||||
guid = guidToUString(readUnaligned((EFI_GUID*)(entryHeader + 1)), false);
|
name = guidToUString(g);
|
||||||
|
guid = guidToUString(g, false);
|
||||||
}
|
}
|
||||||
// GUID is stored in GUID list at the end of the store
|
else { // GUID is stored in GUID store at the end of the NVAR store
|
||||||
else {
|
// Grow the GUID store if needed
|
||||||
guidIndex = *(UINT8*)(entryHeader + 1);
|
if (guidsInStore < entry_body->guid_index() + 1)
|
||||||
if (guidsInStore < guidIndex + 1)
|
guidsInStore = entry_body->guid_index() + 1;
|
||||||
guidsInStore = guidIndex + 1;
|
|
||||||
|
|
||||||
// The list begins at the end of the store and goes backwards
|
// The list begins at the end of the store and goes backwards
|
||||||
const EFI_GUID* guidPtr = (const EFI_GUID*)(data.constData() + data.size()) - 1 - guidIndex;
|
const EFI_GUID g = readUnaligned((EFI_GUID*)(nvar.constData() + nvar.size()) - (entry_body->guid_index() + 1));
|
||||||
name = guidToUString(readUnaligned(guidPtr));
|
name = guidToUString(g);
|
||||||
guid = guidToUString(readUnaligned(guidPtr), false);
|
guid = guidToUString(g, false);
|
||||||
hasGuidIndex = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Include name and GUID into the header and remove them from body
|
processing_done:
|
||||||
header = data.mid(offset, sizeof(NVAR_ENTRY_HEADER) + nameOffset + nameSize);
|
// This feels hacky, but I haven't found a way to ask Kaitai for raw bytes
|
||||||
body = body.mid(nameOffset + nameSize);
|
header = nvar.mid(entry->offset(), sizeof(NVAR_ENTRY_HEADER) + entry_body->data_start_offset());
|
||||||
|
body = nvar.mid(entry->offset() + sizeof(NVAR_ENTRY_HEADER) + entry_body->data_start_offset(), entry_body->data_size());
|
||||||
|
tail = nvar.mid(entry->end_offset() - entry_body->extended_header_size(), entry_body->extended_header_size());
|
||||||
|
|
||||||
|
// Add GUID info for valid entries
|
||||||
|
if (!guid.isEmpty())
|
||||||
|
info += UString("Variable GUID: ") + guid + "\n";
|
||||||
|
|
||||||
|
// Add GUID index information
|
||||||
|
if (!entry_body->_is_null_guid_index())
|
||||||
|
info += usprintf("GUID index: %u\n", entry_body->guid_index());
|
||||||
|
|
||||||
|
// Add header, body and extended data info
|
||||||
|
info += usprintf("Full size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nTail size: %Xh (%u)",
|
||||||
|
entry->size(), entry->size(),
|
||||||
|
(UINT32)header.size(), (UINT32)header.size(),
|
||||||
|
(UINT32)body.size(), (UINT32)body.size(),
|
||||||
|
(UINT32)tail.size(), (UINT32)tail.size());
|
||||||
|
|
||||||
|
// Add attributes info
|
||||||
|
const NVAR_ENTRY_HEADER entryHeader = readUnaligned((NVAR_ENTRY_HEADER*)header.constData());
|
||||||
|
info += usprintf("\nAttributes: %02Xh", entryHeader.Attributes);
|
||||||
|
|
||||||
|
// Translate attributes to text
|
||||||
|
if (entryHeader.Attributes != 0x00 && entryHeader.Attributes != 0xFF)
|
||||||
|
info += UString(" (") + nvarAttributesToUString(entryHeader.Attributes) + UString(")");
|
||||||
|
|
||||||
|
// Add next node info
|
||||||
|
if (entry->next() != 0xFFFFFF)
|
||||||
|
info += usprintf("\nNext node at offset: %Xh", localOffset + entry->offset() + (UINT32)entry->next());
|
||||||
|
|
||||||
|
// Add extended header info
|
||||||
|
if (entry_body->extended_header_size() > 0) {
|
||||||
|
info += usprintf("\nExtended header size: %Xh (%u)",
|
||||||
|
entry_body->extended_header_size(), entry_body->extended_header_size());
|
||||||
|
|
||||||
|
const UINT8 extendedAttributes = *tail.constData();
|
||||||
|
info += usprintf("\nExtended attributes: %02Xh (", extendedAttributes) + nvarExtendedAttributesToUString(extendedAttributes) + UString(")");
|
||||||
|
|
||||||
|
// Add checksum
|
||||||
|
if (!entry_body->_is_null_extended_header_checksum()) {
|
||||||
|
UINT8 calculatedChecksum = 0;
|
||||||
|
UByteArray wholeBody = body + tail;
|
||||||
|
|
||||||
|
// Include entry body
|
||||||
|
UINT8* start = (UINT8*)wholeBody.constData();
|
||||||
|
for (UINT8* p = start; p < start + wholeBody.size(); p++) {
|
||||||
|
calculatedChecksum += *p;
|
||||||
|
}
|
||||||
|
// Include entry size and flags
|
||||||
|
start = (UINT8*)&entryHeader.Size;
|
||||||
|
for (UINT8*p = start; p < start + sizeof(UINT16); p++) {
|
||||||
|
calculatedChecksum += *p;
|
||||||
|
}
|
||||||
|
// Include entry attributes
|
||||||
|
calculatedChecksum += entryHeader.Attributes;
|
||||||
|
info += usprintf("\nChecksum: %02Xh, ", entry_body->extended_header_checksum())
|
||||||
|
+ (calculatedChecksum ? usprintf(", invalid, should be %02Xh", 0x100 - calculatedChecksum) : UString(", valid"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add timestamp
|
||||||
|
if (!entry_body->_is_null_extended_header_timestamp())
|
||||||
|
info += usprintf("\nTimestamp: %" PRIX64 "h", entry_body->extended_header_timestamp());
|
||||||
|
|
||||||
|
// Add hash
|
||||||
|
if (!entry_body->_is_null_extended_header_hash()) {
|
||||||
|
UByteArray hash = UByteArray(entry_body->extended_header_hash().c_str(), entry_body->extended_header_hash().size());
|
||||||
|
info += UString("\nHash: ") + UString(hash.toHex().constData());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add tree item
|
||||||
|
UModelIndex varIndex = model->addItem(localOffset + entry->offset(), Types::NvarEntry, subtype, name, text, info, header, body, tail, Fixed, index);
|
||||||
|
currentEntryIndex++;
|
||||||
|
|
||||||
|
// Set parsing data
|
||||||
|
model->setParsingData(varIndex, UByteArray((const char*)&pdata, sizeof(pdata)));
|
||||||
|
|
||||||
|
// Try parsing the entry data as NVAR storage if it begins with NVAR signature
|
||||||
|
if ((subtype == Subtypes::DataNvarEntry || subtype == Subtypes::FullNvarEntry)
|
||||||
|
&& body.size() >= 4 && readUnaligned((const UINT32*)body.constData()) == NVRAM_NVAR_ENTRY_SIGNATURE)
|
||||||
|
(void)parseNvarStore(varIndex);
|
||||||
}
|
}
|
||||||
parsing_done:
|
}
|
||||||
UString info;
|
catch (...) {
|
||||||
|
msg(usprintf("%s: unable to parse AMI NVAR storage", __FUNCTION__), index);
|
||||||
// Rename invalid entries according to their types
|
return U_INVALID_STORE;
|
||||||
pdata.isValid = TRUE;
|
|
||||||
if (isInvalid) {
|
|
||||||
name = UString("Invalid");
|
|
||||||
subtype = Subtypes::InvalidNvarEntry;
|
|
||||||
pdata.isValid = FALSE;
|
|
||||||
}
|
|
||||||
else if (isInvalidLink) {
|
|
||||||
name = UString("Invalid link");
|
|
||||||
subtype = Subtypes::InvalidLinkNvarEntry;
|
|
||||||
pdata.isValid = FALSE;
|
|
||||||
}
|
|
||||||
else // Add GUID info for valid entries
|
|
||||||
info += UString("Variable GUID: ") + guid + "\n";
|
|
||||||
|
|
||||||
// Add GUID index information
|
|
||||||
if (hasGuidIndex)
|
|
||||||
info += usprintf("GUID index: %u\n", guidIndex);
|
|
||||||
|
|
||||||
// Add header, body and extended data info
|
|
||||||
info += usprintf("Full size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)",
|
|
||||||
entryHeader->Size, entryHeader->Size,
|
|
||||||
(UINT32)header.size(), (UINT32)header.size(),
|
|
||||||
(UINT32)body.size(), (UINT32)body.size());
|
|
||||||
|
|
||||||
// Add attributes info
|
|
||||||
info += usprintf("\nAttributes: %02Xh", entryHeader->Attributes);
|
|
||||||
// Translate attributes to text
|
|
||||||
if (entryHeader->Attributes && entryHeader->Attributes != 0xFF)
|
|
||||||
info += UString(" (") + nvarAttributesToUString(entryHeader->Attributes) + UString(")");
|
|
||||||
|
|
||||||
// Add next node info
|
|
||||||
if (!isInvalid && entryHeader->Next != lastVariableFlag)
|
|
||||||
info += usprintf("\nNext node at offset: %Xh", localOffset + offset + entryHeader->Next);
|
|
||||||
|
|
||||||
// Add extended header info
|
|
||||||
if (hasExtendedHeader) {
|
|
||||||
info += usprintf("\nExtended header size: %Xh (%u)\nExtended attributes: %Xh (",
|
|
||||||
extendedHeaderSize, extendedHeaderSize,
|
|
||||||
extendedAttributes) + nvarExtendedAttributesToUString(extendedAttributes) + UString(")");
|
|
||||||
|
|
||||||
// Add checksum
|
|
||||||
if (hasChecksum)
|
|
||||||
info += usprintf("\nChecksum: %02Xh", storedChecksum) +
|
|
||||||
(calculatedChecksum ? usprintf(", invalid, should be %02Xh", 0x100 - calculatedChecksum) : UString(", valid"));
|
|
||||||
|
|
||||||
// Add timestamp
|
|
||||||
if (hasTimestamp)
|
|
||||||
info += usprintf("\nTimestamp: %" PRIX64 "h", timestamp);
|
|
||||||
|
|
||||||
// Add hash
|
|
||||||
if (hasHash)
|
|
||||||
info += UString("\nHash: ") + UString(hash.toHex().constData());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add tree item
|
|
||||||
UModelIndex varIndex = model->addItem(localOffset + offset, Types::NvarEntry, subtype, name, text, info, header, body, tail, Fixed, index);
|
|
||||||
|
|
||||||
// Set parsing data for created entry
|
|
||||||
model->setParsingData(varIndex, UByteArray((const char*)&pdata, sizeof(pdata)));
|
|
||||||
|
|
||||||
// Show messages
|
|
||||||
if (msgUnknownExtDataFormat) msg(usprintf("%s: unknown extended data format", __FUNCTION__), varIndex);
|
|
||||||
if (msgExtHeaderTooLong) msg(usprintf("%s: extended header size (%Xh) is greater than body size (%Xh)", __FUNCTION__,
|
|
||||||
extendedHeaderSize, (UINT32)body.size()), varIndex);
|
|
||||||
if (msgExtDataTooShort) msg(usprintf("%s: extended header size (%Xh) is too small for timestamp and hash", __FUNCTION__,
|
|
||||||
(UINT32)tail.size()), varIndex);
|
|
||||||
|
|
||||||
// Try parsing the entry data as NVAR storage if it begins with NVAR signature
|
|
||||||
if ((subtype == Subtypes::DataNvarEntry || subtype == Subtypes::FullNvarEntry)
|
|
||||||
&& body.size() >= 4 && readUnaligned((const UINT32*)body.constData()) == NVRAM_NVAR_ENTRY_SIGNATURE)
|
|
||||||
parseNvarStore(varIndex);
|
|
||||||
|
|
||||||
// Move to next exntry
|
|
||||||
offset += entryHeader->Size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return U_SUCCESS;
|
return U_SUCCESS;
|
||||||
|
@ -59,6 +59,7 @@ UString itemTypeToUString(const UINT8 type)
|
|||||||
case Types::EvsaStore: return UString("EVSA store");
|
case Types::EvsaStore: return UString("EVSA store");
|
||||||
case Types::CmdbStore: return UString("CMDB store");
|
case Types::CmdbStore: return UString("CMDB store");
|
||||||
case Types::FlashMapStore: return UString("FlashMap store");
|
case Types::FlashMapStore: return UString("FlashMap store");
|
||||||
|
case Types::NvarGuidStore: return UString("NVAR GUID store");
|
||||||
case Types::NvarEntry: return UString("NVAR entry");
|
case Types::NvarEntry: return UString("NVAR entry");
|
||||||
case Types::VssEntry: return UString("VSS entry");
|
case Types::VssEntry: return UString("VSS entry");
|
||||||
case Types::FsysEntry: return UString("Fsys entry");
|
case Types::FsysEntry: return UString("Fsys entry");
|
||||||
|
@ -51,6 +51,7 @@ namespace Types {
|
|||||||
EvsaStore,
|
EvsaStore,
|
||||||
FlashMapStore,
|
FlashMapStore,
|
||||||
CmdbStore,
|
CmdbStore,
|
||||||
|
NvarGuidStore,
|
||||||
NvarEntry,
|
NvarEntry,
|
||||||
VssEntry,
|
VssEntry,
|
||||||
FsysEntry,
|
FsysEntry,
|
||||||
|
58
common/umemstream.h
Normal file
58
common/umemstream.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/* umemstream.h
|
||||||
|
|
||||||
|
Copyright (c) 2023, 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 UMEMSTREAM_H
|
||||||
|
#define UMEMSTREAM_H
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
// NOTE: this implementation is certainly not a valid replacement to std::stringstream
|
||||||
|
// NOTE: because it only supports getting through the buffer once
|
||||||
|
// NOTE: however, we already do it this way, so it's enough for practical purposes
|
||||||
|
|
||||||
|
class umembuf : public std::streambuf {
|
||||||
|
public:
|
||||||
|
umembuf(const char *p, size_t l) {
|
||||||
|
setg((char*)p, (char*)p, (char*)p + l);
|
||||||
|
}
|
||||||
|
|
||||||
|
pos_type seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which = std::ios_base::in) override
|
||||||
|
{
|
||||||
|
(void)which;
|
||||||
|
if (dir == std::ios_base::cur)
|
||||||
|
gbump((int)off);
|
||||||
|
else if (dir == std::ios_base::end)
|
||||||
|
setg(eback(), egptr() + off, egptr());
|
||||||
|
else if (dir == std::ios_base::beg)
|
||||||
|
setg(eback(), eback() + off, egptr());
|
||||||
|
return gptr() - eback();
|
||||||
|
}
|
||||||
|
|
||||||
|
pos_type seekpos(pos_type sp, std::ios_base::openmode which) override
|
||||||
|
{
|
||||||
|
return seekoff(sp - pos_type(off_type(0)), std::ios_base::beg, which);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class umemstream : public std::istream {
|
||||||
|
public:
|
||||||
|
umemstream(const char *p, size_t l) : std::istream(&buffer_),
|
||||||
|
buffer_(p, l) {
|
||||||
|
rdbuf(&buffer_);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
umembuf buffer_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // UMEMSTREAM_H
|
@ -113,12 +113,10 @@ UString uFromUcs2(const char* str, size_t max_len)
|
|||||||
UString msg;
|
UString msg;
|
||||||
const char *str8 = str;
|
const char *str8 = str;
|
||||||
size_t rest = (max_len == 0) ? SIZE_MAX : max_len;
|
size_t rest = (max_len == 0) ? SIZE_MAX : max_len;
|
||||||
if (max_len == 0) {
|
while (str8[0] && rest) {
|
||||||
while (str8[0] && rest) {
|
msg += str8[0];
|
||||||
msg += str8[0];
|
str8 += 2;
|
||||||
str8 += 2;
|
rest--;
|
||||||
rest--;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
@ -146,6 +146,7 @@ void fixFileName(UString &name, bool replaceSpaces)
|
|||||||
// Returns text representation of error code
|
// Returns text representation of error code
|
||||||
UString errorCodeToUString(USTATUS errorCode)
|
UString errorCodeToUString(USTATUS errorCode)
|
||||||
{
|
{
|
||||||
|
// TODO: improve
|
||||||
switch (errorCode) {
|
switch (errorCode) {
|
||||||
case U_SUCCESS: return UString("Success");
|
case U_SUCCESS: return UString("Success");
|
||||||
case U_NOT_IMPLEMENTED: return UString("Not implemented");
|
case U_NOT_IMPLEMENTED: return UString("Not implemented");
|
||||||
@ -165,7 +166,6 @@ UString errorCodeToUString(USTATUS errorCode)
|
|||||||
case U_VOLUMES_NOT_FOUND: return UString("UEFI volumes not found");
|
case U_VOLUMES_NOT_FOUND: return UString("UEFI volumes not found");
|
||||||
case U_INVALID_VOLUME: return UString("Invalid UEFI volume");
|
case U_INVALID_VOLUME: return UString("Invalid UEFI volume");
|
||||||
case U_VOLUME_REVISION_NOT_SUPPORTED: return UString("Volume revision not supported");
|
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_UNKNOWN_FFS: return UString("Unknown file system");
|
||||||
case U_INVALID_FILE: return UString("Invalid file");
|
case U_INVALID_FILE: return UString("Invalid file");
|
||||||
case U_INVALID_SECTION: return UString("Invalid section");
|
case U_INVALID_SECTION: return UString("Invalid section");
|
||||||
@ -177,26 +177,19 @@ UString errorCodeToUString(USTATUS errorCode)
|
|||||||
case U_UNKNOWN_COMPRESSION_TYPE: return UString("Unknown compression type");
|
case U_UNKNOWN_COMPRESSION_TYPE: return UString("Unknown compression type");
|
||||||
case U_UNKNOWN_EXTRACT_MODE: return UString("Unknown extract mode");
|
case U_UNKNOWN_EXTRACT_MODE: return UString("Unknown extract mode");
|
||||||
case U_UNKNOWN_REPLACE_MODE: return UString("Unknown replace 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_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_PE_OPTIONAL_HEADER_TYPE: return UString("Unknown PE optional header type");
|
||||||
case U_UNKNOWN_RELOCATION_TYPE: return UString("Unknown relocation 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_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_ALREADY_EXIST: return UString("Directory already exists");
|
||||||
case U_DIR_CREATE: return UString("Directory can't be created");
|
case U_DIR_CREATE: return UString("Directory can't be created");
|
||||||
case U_DIR_CHANGE: return UString("Change directory failed");
|
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_DEPEX_PARSE_FAILED: return UString("Dependency expression parsing failed");
|
||||||
case U_TRUNCATED_IMAGE: return UString("Image is truncated");
|
case U_TRUNCATED_IMAGE: return UString("Image is truncated");
|
||||||
case U_INVALID_CAPSULE: return UString("Invalid capsule");
|
case U_INVALID_CAPSULE: return UString("Invalid capsule");
|
||||||
case U_STORES_NOT_FOUND: return UString("Stores not found");
|
case U_STORES_NOT_FOUND: return UString("Stores not found");
|
||||||
case U_INVALID_STORE_SIZE: return UString("Invalid store size");
|
case U_INVALID_STORE_SIZE: return UString("Invalid store size");
|
||||||
|
case U_INVALID_STORE: return UString("Invalid store");
|
||||||
default: return usprintf("Unknown error %02lX", errorCode);
|
default: return usprintf("Unknown error %02lX", errorCode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@ SET(PROJECT_SOURCES
|
|||||||
../common/LZMA/SDK/C/LzmaDec.c
|
../common/LZMA/SDK/C/LzmaDec.c
|
||||||
../common/Tiano/EfiTianoDecompress.c
|
../common/Tiano/EfiTianoDecompress.c
|
||||||
../common/ustring.cpp
|
../common/ustring.cpp
|
||||||
|
../common/generated/ami_nvar.cpp
|
||||||
../common/generated/intel_acbp_v1.cpp
|
../common/generated/intel_acbp_v1.cpp
|
||||||
../common/generated/intel_acbp_v2.cpp
|
../common/generated/intel_acbp_v2.cpp
|
||||||
../common/generated/intel_keym_v1.cpp
|
../common/generated/intel_keym_v1.cpp
|
||||||
@ -86,7 +87,7 @@ ADD_DEFINITIONS(
|
|||||||
ADD_EXECUTABLE(ffsparser_fuzzer ${PROJECT_SOURCES})
|
ADD_EXECUTABLE(ffsparser_fuzzer ${PROJECT_SOURCES})
|
||||||
|
|
||||||
|
|
||||||
IF(USE_AFL_DRIVER)
|
IF(NOT USE_AFL_DRIVER)
|
||||||
TARGET_COMPILE_OPTIONS(ffsparser_fuzzer PRIVATE -O1 -fno-omit-frame-pointer -g -ggdb3 -fsanitize=fuzzer,address,undefined -fsanitize-address-use-after-scope -fno-sanitize-recover=undefined)
|
TARGET_COMPILE_OPTIONS(ffsparser_fuzzer PRIVATE -O1 -fno-omit-frame-pointer -g -ggdb3 -fsanitize=fuzzer,address,undefined -fsanitize-address-use-after-scope -fno-sanitize-recover=undefined)
|
||||||
TARGET_LINK_LIBRARIES(ffsparser_fuzzer PRIVATE -fsanitize=fuzzer,address,undefined)
|
TARGET_LINK_LIBRARIES(ffsparser_fuzzer PRIVATE -fsanitize=fuzzer,address,undefined)
|
||||||
ELSE()
|
ELSE()
|
||||||
|
Loading…
Reference in New Issue
Block a user