mirror of
https://github.com/LongSoft/UEFITool.git
synced 2025-05-09 13:52:01 -04:00
Add Apple SysF/Diag parser
This commit is contained in:
parent
2d6eaa917f
commit
4e600eb986
17 changed files with 597 additions and 154 deletions
|
@ -35,6 +35,7 @@ SET(PROJECT_SOURCES
|
||||||
../common/bstrlib/bstrlib.c
|
../common/bstrlib/bstrlib.c
|
||||||
../common/bstrlib/bstrwrap.cpp
|
../common/bstrlib/bstrwrap.cpp
|
||||||
../common/generated/ami_nvar.cpp
|
../common/generated/ami_nvar.cpp
|
||||||
|
../common/generated/apple_sysf.cpp
|
||||||
../common/generated/edk2_vss.cpp
|
../common/generated/edk2_vss.cpp
|
||||||
../common/generated/edk2_vss2.cpp
|
../common/generated/edk2_vss2.cpp
|
||||||
../common/generated/edk2_ftw.cpp
|
../common/generated/edk2_ftw.cpp
|
||||||
|
|
|
@ -32,6 +32,7 @@ SET(PROJECT_SOURCES
|
||||||
../common/bstrlib/bstrlib.c
|
../common/bstrlib/bstrlib.c
|
||||||
../common/bstrlib/bstrwrap.cpp
|
../common/bstrlib/bstrwrap.cpp
|
||||||
../common/generated/ami_nvar.cpp
|
../common/generated/ami_nvar.cpp
|
||||||
|
../common/generated/apple_sysf.cpp
|
||||||
../common/generated/edk2_vss.cpp
|
../common/generated/edk2_vss.cpp
|
||||||
../common/generated/edk2_vss2.cpp
|
../common/generated/edk2_vss2.cpp
|
||||||
../common/generated/edk2_ftw.cpp
|
../common/generated/edk2_ftw.cpp
|
||||||
|
|
|
@ -68,6 +68,7 @@ SET(PROJECT_SOURCES
|
||||||
../common/digest/sha512.c
|
../common/digest/sha512.c
|
||||||
../common/digest/sm3.c
|
../common/digest/sm3.c
|
||||||
../common/generated/ami_nvar.cpp
|
../common/generated/ami_nvar.cpp
|
||||||
|
../common/generated/apple_sysf.cpp
|
||||||
../common/generated/edk2_vss.cpp
|
../common/generated/edk2_vss.cpp
|
||||||
../common/generated/edk2_vss2.cpp
|
../common/generated/edk2_vss2.cpp
|
||||||
../common/generated/edk2_ftw.cpp
|
../common/generated/edk2_ftw.cpp
|
||||||
|
|
|
@ -466,7 +466,7 @@ void QHexView::checkState() {
|
||||||
|
|
||||||
int doclines = static_cast<int>(this->lines()),
|
int doclines = static_cast<int>(this->lines()),
|
||||||
vislines = this->visibleLines(true);
|
vislines = this->visibleLines(true);
|
||||||
qint64 vscrollmax = doclines - vislines;
|
qint64 vscrollmax = doclines - vislines + 1; // UEFITool: ensure the very last line is visible on macOS
|
||||||
if(doclines >= vislines)
|
if(doclines >= vislines)
|
||||||
vscrollmax++;
|
vscrollmax++;
|
||||||
|
|
||||||
|
|
|
@ -245,7 +245,7 @@ void UEFITool::populateUi(const QModelIndex ¤t)
|
||||||
|| type == Types::SlicData
|
|| type == Types::SlicData
|
||||||
|| type == Types::NvarEntry
|
|| type == Types::NvarEntry
|
||||||
|| type == Types::VssEntry
|
|| type == Types::VssEntry
|
||||||
|| type == Types::FsysEntry
|
|| type == Types::SysFEntry
|
||||||
|| type == Types::EvsaEntry
|
|| type == Types::EvsaEntry
|
||||||
|| type == Types::FlashMapEntry
|
|| type == Types::FlashMapEntry
|
||||||
|| type == Types::IfwiHeader
|
|| type == Types::IfwiHeader
|
||||||
|
@ -263,7 +263,7 @@ void UEFITool::populateUi(const QModelIndex ¤t)
|
||||||
ui->menuStoreActions->setEnabled(type == Types::VssStore
|
ui->menuStoreActions->setEnabled(type == Types::VssStore
|
||||||
|| type == Types::Vss2Store
|
|| type == Types::Vss2Store
|
||||||
|| type == Types::FdcStore
|
|| type == Types::FdcStore
|
||||||
|| type == Types::FsysStore
|
|| type == Types::SysFStore
|
||||||
|| type == Types::EvsaStore
|
|| type == Types::EvsaStore
|
||||||
|| type == Types::FtwStore
|
|| type == Types::FtwStore
|
||||||
|| type == Types::FlashMapStore
|
|| type == Types::FlashMapStore
|
||||||
|
@ -907,7 +907,7 @@ void UEFITool::contextMenuEvent(QContextMenuEvent* event)
|
||||||
case Types::VssStore:
|
case Types::VssStore:
|
||||||
case Types::Vss2Store:
|
case Types::Vss2Store:
|
||||||
case Types::FdcStore:
|
case Types::FdcStore:
|
||||||
case Types::FsysStore:
|
case Types::SysFStore:
|
||||||
case Types::EvsaStore:
|
case Types::EvsaStore:
|
||||||
case Types::FtwStore:
|
case Types::FtwStore:
|
||||||
case Types::FlashMapStore:
|
case Types::FlashMapStore:
|
||||||
|
|
|
@ -51,6 +51,11 @@ HEADERS += uefitool.h \
|
||||||
../common/digest/sha2.h \
|
../common/digest/sha2.h \
|
||||||
../common/digest/sm3.h \
|
../common/digest/sm3.h \
|
||||||
../common/generated/ami_nvar.h \
|
../common/generated/ami_nvar.h \
|
||||||
|
../common/generated/apple_sysf.h \
|
||||||
|
../common/generated/edk2_vss.h \
|
||||||
|
../common/generated/edk2_vss2.h \
|
||||||
|
../common/generated/edk2_ftw.h \
|
||||||
|
../common/generated/insyde_fdc.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 \
|
||||||
|
@ -118,6 +123,11 @@ SOURCES += uefitool_main.cpp \
|
||||||
../common/digest/sha512.c \
|
../common/digest/sha512.c \
|
||||||
../common/digest/sm3.c \
|
../common/digest/sm3.c \
|
||||||
../common/generated/ami_nvar.cpp \
|
../common/generated/ami_nvar.cpp \
|
||||||
|
../common/generated/apple_sysf.cpp \
|
||||||
|
../common/generated/edk2_vss.cpp \
|
||||||
|
../common/generated/edk2_vss2.cpp \
|
||||||
|
../common/generated/edk2_ftw.cpp \
|
||||||
|
../common/generated/insyde_fdc.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 \
|
||||||
|
|
115
common/generated/apple_sysf.cpp
Normal file
115
common/generated/apple_sysf.cpp
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
|
||||||
|
|
||||||
|
#include "apple_sysf.h"
|
||||||
|
#include "../kaitai/exceptions.h"
|
||||||
|
|
||||||
|
apple_sysf_t::apple_sysf_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, apple_sysf_t* p__root) : kaitai::kstruct(p__io) {
|
||||||
|
m__parent = p__parent;
|
||||||
|
m__root = this; (void)p__root;
|
||||||
|
m_body = nullptr;
|
||||||
|
m__io__raw_body = nullptr;
|
||||||
|
f_len_sysf_store_header = false;
|
||||||
|
_read();
|
||||||
|
}
|
||||||
|
|
||||||
|
void apple_sysf_t::_read() {
|
||||||
|
m_signature = m__io->read_u4le();
|
||||||
|
{
|
||||||
|
uint32_t _ = signature();
|
||||||
|
if (!( ((_ == 1937339206) || (_ == 1684627783)) )) {
|
||||||
|
throw kaitai::validation_expr_error<uint32_t>(signature(), _io(), std::string("/seq/0"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_unknown = m__io->read_u1();
|
||||||
|
m_unknown1 = m__io->read_u4le();
|
||||||
|
m_sysf_size = m__io->read_u2le();
|
||||||
|
m__raw_body = m__io->read_bytes(((sysf_size() - len_sysf_store_header()) - 4));
|
||||||
|
m__io__raw_body = std::unique_ptr<kaitai::kstream>(new kaitai::kstream(m__raw_body));
|
||||||
|
m_body = std::unique_ptr<sysf_store_body_t>(new sysf_store_body_t(m__io__raw_body.get(), this, m__root));
|
||||||
|
m_crc = m__io->read_u4le();
|
||||||
|
}
|
||||||
|
|
||||||
|
apple_sysf_t::~apple_sysf_t() {
|
||||||
|
_clean_up();
|
||||||
|
}
|
||||||
|
|
||||||
|
void apple_sysf_t::_clean_up() {
|
||||||
|
}
|
||||||
|
|
||||||
|
apple_sysf_t::sysf_store_body_t::sysf_store_body_t(kaitai::kstream* p__io, apple_sysf_t* p__parent, apple_sysf_t* p__root) : kaitai::kstruct(p__io) {
|
||||||
|
m__parent = p__parent;
|
||||||
|
m__root = p__root;
|
||||||
|
m_variables = nullptr;
|
||||||
|
m_zeroes = nullptr;
|
||||||
|
_read();
|
||||||
|
}
|
||||||
|
|
||||||
|
void apple_sysf_t::sysf_store_body_t::_read() {
|
||||||
|
m_variables = std::unique_ptr<std::vector<std::unique_ptr<sysf_variable_t>>>(new std::vector<std::unique_ptr<sysf_variable_t>>());
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
sysf_variable_t* _;
|
||||||
|
do {
|
||||||
|
_ = new sysf_variable_t(m__io, this, m__root);
|
||||||
|
m_variables->push_back(std::move(std::unique_ptr<sysf_variable_t>(_)));
|
||||||
|
i++;
|
||||||
|
} while (!( (( ((_->len_name() == 3) && (_->name() == (std::string("EOF")))) ) || (_io()->is_eof())) ));
|
||||||
|
}
|
||||||
|
m_zeroes = std::unique_ptr<std::vector<uint8_t>>(new std::vector<uint8_t>());
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
while (!m__io->is_eof()) {
|
||||||
|
m_zeroes->push_back(std::move(m__io->read_u1()));
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apple_sysf_t::sysf_store_body_t::~sysf_store_body_t() {
|
||||||
|
_clean_up();
|
||||||
|
}
|
||||||
|
|
||||||
|
void apple_sysf_t::sysf_store_body_t::_clean_up() {
|
||||||
|
}
|
||||||
|
|
||||||
|
apple_sysf_t::sysf_variable_t::sysf_variable_t(kaitai::kstream* p__io, apple_sysf_t::sysf_store_body_t* p__parent, apple_sysf_t* p__root) : kaitai::kstruct(p__io) {
|
||||||
|
m__parent = p__parent;
|
||||||
|
m__root = p__root;
|
||||||
|
_read();
|
||||||
|
}
|
||||||
|
|
||||||
|
void apple_sysf_t::sysf_variable_t::_read() {
|
||||||
|
m_len_name = m__io->read_bits_int_le(7);
|
||||||
|
m_invalid_flag = m__io->read_bits_int_le(1);
|
||||||
|
m__io->align_to_byte();
|
||||||
|
m_name = kaitai::kstream::bytes_to_str(kaitai::kstream::bytes_terminate(m__io->read_bytes(len_name()), 0, false), std::string("ascii"));
|
||||||
|
n_len_data = true;
|
||||||
|
if (name() != std::string("EOF")) {
|
||||||
|
n_len_data = false;
|
||||||
|
m_len_data = m__io->read_u2le();
|
||||||
|
}
|
||||||
|
n_data = true;
|
||||||
|
if (name() != std::string("EOF")) {
|
||||||
|
n_data = false;
|
||||||
|
m_data = m__io->read_bytes(len_data());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apple_sysf_t::sysf_variable_t::~sysf_variable_t() {
|
||||||
|
_clean_up();
|
||||||
|
}
|
||||||
|
|
||||||
|
void apple_sysf_t::sysf_variable_t::_clean_up() {
|
||||||
|
if (!n_len_data) {
|
||||||
|
}
|
||||||
|
if (!n_data) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int8_t apple_sysf_t::len_sysf_store_header() {
|
||||||
|
if (f_len_sysf_store_header)
|
||||||
|
return m_len_sysf_store_header;
|
||||||
|
m_len_sysf_store_header = 11;
|
||||||
|
f_len_sysf_store_header = true;
|
||||||
|
return m_len_sysf_store_header;
|
||||||
|
}
|
129
common/generated/apple_sysf.h
Normal file
129
common/generated/apple_sysf.h
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// 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 <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#if KAITAI_STRUCT_VERSION < 9000L
|
||||||
|
#error "Incompatible Kaitai Struct C++/STL API: version 0.9 or later is required"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class apple_sysf_t : public kaitai::kstruct {
|
||||||
|
|
||||||
|
public:
|
||||||
|
class sysf_store_body_t;
|
||||||
|
class sysf_variable_t;
|
||||||
|
|
||||||
|
apple_sysf_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = nullptr, apple_sysf_t* p__root = nullptr);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _read();
|
||||||
|
void _clean_up();
|
||||||
|
|
||||||
|
public:
|
||||||
|
~apple_sysf_t();
|
||||||
|
|
||||||
|
class sysf_store_body_t : public kaitai::kstruct {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
sysf_store_body_t(kaitai::kstream* p__io, apple_sysf_t* p__parent = nullptr, apple_sysf_t* p__root = nullptr);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _read();
|
||||||
|
void _clean_up();
|
||||||
|
|
||||||
|
public:
|
||||||
|
~sysf_store_body_t();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<std::vector<std::unique_ptr<sysf_variable_t>>> m_variables;
|
||||||
|
std::unique_ptr<std::vector<uint8_t>> m_zeroes;
|
||||||
|
apple_sysf_t* m__root;
|
||||||
|
apple_sysf_t* m__parent;
|
||||||
|
|
||||||
|
public:
|
||||||
|
std::vector<std::unique_ptr<sysf_variable_t>>* variables() const { return m_variables.get(); }
|
||||||
|
std::vector<uint8_t>* zeroes() const { return m_zeroes.get(); }
|
||||||
|
apple_sysf_t* _root() const { return m__root; }
|
||||||
|
apple_sysf_t* _parent() const { return m__parent; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class sysf_variable_t : public kaitai::kstruct {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
sysf_variable_t(kaitai::kstream* p__io, apple_sysf_t::sysf_store_body_t* p__parent = nullptr, apple_sysf_t* p__root = nullptr);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _read();
|
||||||
|
void _clean_up();
|
||||||
|
|
||||||
|
public:
|
||||||
|
~sysf_variable_t();
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint64_t m_len_name;
|
||||||
|
bool m_invalid_flag;
|
||||||
|
std::string m_name;
|
||||||
|
uint16_t m_len_data;
|
||||||
|
bool n_len_data;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool _is_null_len_data() { len_data(); return n_len_data; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_data;
|
||||||
|
bool n_data;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool _is_null_data() { data(); return n_data; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
apple_sysf_t* m__root;
|
||||||
|
apple_sysf_t::sysf_store_body_t* m__parent;
|
||||||
|
|
||||||
|
public:
|
||||||
|
uint64_t len_name() const { return m_len_name; }
|
||||||
|
bool invalid_flag() const { return m_invalid_flag; }
|
||||||
|
std::string name() const { return m_name; }
|
||||||
|
uint16_t len_data() const { return m_len_data; }
|
||||||
|
std::string data() const { return m_data; }
|
||||||
|
apple_sysf_t* _root() const { return m__root; }
|
||||||
|
apple_sysf_t::sysf_store_body_t* _parent() const { return m__parent; }
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool f_len_sysf_store_header;
|
||||||
|
int8_t m_len_sysf_store_header;
|
||||||
|
|
||||||
|
public:
|
||||||
|
int8_t len_sysf_store_header();
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32_t m_signature;
|
||||||
|
uint8_t m_unknown;
|
||||||
|
uint32_t m_unknown1;
|
||||||
|
uint16_t m_sysf_size;
|
||||||
|
std::unique_ptr<sysf_store_body_t> m_body;
|
||||||
|
uint32_t m_crc;
|
||||||
|
apple_sysf_t* m__root;
|
||||||
|
kaitai::kstruct* m__parent;
|
||||||
|
std::string m__raw_body;
|
||||||
|
std::unique_ptr<kaitai::kstream> m__io__raw_body;
|
||||||
|
|
||||||
|
public:
|
||||||
|
uint32_t signature() const { return m_signature; }
|
||||||
|
uint8_t unknown() const { return m_unknown; }
|
||||||
|
uint32_t unknown1() const { return m_unknown1; }
|
||||||
|
uint16_t sysf_size() const { return m_sysf_size; }
|
||||||
|
sysf_store_body_t* body() const { return m_body.get(); }
|
||||||
|
uint32_t crc() const { return m_crc; }
|
||||||
|
apple_sysf_t* _root() const { return m__root; }
|
||||||
|
kaitai::kstruct* _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.get(); }
|
||||||
|
};
|
60
common/ksy/apple_fsys.ksy
Normal file
60
common/ksy/apple_fsys.ksy
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
meta:
|
||||||
|
id: apple_sysf
|
||||||
|
title: Apple system variable store
|
||||||
|
application: Apple MacEFI-based UEFI firmware
|
||||||
|
file-extension: sysf
|
||||||
|
tags:
|
||||||
|
- firmware
|
||||||
|
license: CC0-1.0
|
||||||
|
ks-version: 0.9
|
||||||
|
endian: le
|
||||||
|
|
||||||
|
seq:
|
||||||
|
- id: signature
|
||||||
|
type: u4
|
||||||
|
valid:
|
||||||
|
expr: _ == 0x73797346 or _ == 0x64696147 # Fsys/Gaid
|
||||||
|
- id: unknown
|
||||||
|
type: u1
|
||||||
|
- id: unknown1
|
||||||
|
type: u4
|
||||||
|
- id: sysf_size
|
||||||
|
type: u2
|
||||||
|
- id: body
|
||||||
|
type: sysf_store_body
|
||||||
|
size: sysf_size - len_sysf_store_header - sizeof<u4>
|
||||||
|
- id: crc
|
||||||
|
type: u4
|
||||||
|
|
||||||
|
instances:
|
||||||
|
len_sysf_store_header:
|
||||||
|
value: 11
|
||||||
|
|
||||||
|
types:
|
||||||
|
sysf_store_body:
|
||||||
|
seq:
|
||||||
|
- id: variables
|
||||||
|
type: sysf_variable
|
||||||
|
repeat: until
|
||||||
|
repeat-until: (_.len_name == 3 and _.name == "EOF") or _io.eof
|
||||||
|
- id: zeroes
|
||||||
|
type: u1
|
||||||
|
repeat: eos
|
||||||
|
|
||||||
|
sysf_variable:
|
||||||
|
seq:
|
||||||
|
- id: len_name
|
||||||
|
type: b7le
|
||||||
|
- id: invalid_flag
|
||||||
|
type: b1le
|
||||||
|
- id: name
|
||||||
|
type: strz
|
||||||
|
encoding: ascii
|
||||||
|
size: len_name
|
||||||
|
- id: len_data
|
||||||
|
type: u2
|
||||||
|
if: name != "EOF"
|
||||||
|
- id: data
|
||||||
|
size: len_data
|
||||||
|
if: name != "EOF"
|
||||||
|
|
|
@ -33,6 +33,11 @@ uefitoolcommon = static_library('uefitoolcommon',
|
||||||
'utility.cpp',
|
'utility.cpp',
|
||||||
'ustring.cpp',
|
'ustring.cpp',
|
||||||
'generated/ami_nvar.cpp',
|
'generated/ami_nvar.cpp',
|
||||||
|
'generated/apple_sysf.cpp',
|
||||||
|
'generated/edk2_vss.cpp',
|
||||||
|
'generated/edk2_vss2.cpp',
|
||||||
|
'generated/edk2_ftw.cpp',
|
||||||
|
'generated/insyde_fdc.cpp',
|
||||||
'generated/intel_acbp_v1.cpp',
|
'generated/intel_acbp_v1.cpp',
|
||||||
'generated/intel_acbp_v2.cpp',
|
'generated/intel_acbp_v2.cpp',
|
||||||
'generated/intel_keym_v1.cpp',
|
'generated/intel_keym_v1.cpp',
|
||||||
|
|
|
@ -70,8 +70,8 @@ extern const UByteArray NVRAM_ADDITIONAL_STORE_VOLUME_GUID; // 00504624-8A59-4EE
|
||||||
#define NVRAM_VSS_STORE_SIGNATURE 0x53535624 // $VSS
|
#define NVRAM_VSS_STORE_SIGNATURE 0x53535624 // $VSS
|
||||||
#define NVRAM_APPLE_SVS_STORE_SIGNATURE 0x53565324 // $SVS
|
#define NVRAM_APPLE_SVS_STORE_SIGNATURE 0x53565324 // $SVS
|
||||||
#define NVRAM_APPLE_NSS_STORE_SIGNATURE 0x53534E24 // $NSS
|
#define NVRAM_APPLE_NSS_STORE_SIGNATURE 0x53534E24 // $NSS
|
||||||
#define NVRAM_APPLE_FSYS_STORE_SIGNATURE 0x73797346 // Fsys
|
#define NVRAM_APPLE_SYSF_STORE_SIGNATURE 0x73797346 // Fsys
|
||||||
#define NVRAM_APPLE_GAID_STORE_SIGNATURE 0x64696147 // Gaid
|
#define NVRAM_APPLE_DIAG_STORE_SIGNATURE 0x64696147 // Gaid
|
||||||
#define NVRAM_VSS_VARIABLE_START_ID 0x55AA
|
#define NVRAM_VSS_VARIABLE_START_ID 0x55AA
|
||||||
|
|
||||||
// Variable store header flags
|
// Variable store header flags
|
||||||
|
@ -229,15 +229,15 @@ typedef struct EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64_ {
|
||||||
} EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64;
|
} EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Apple Fsys store
|
// Apple System Flags store
|
||||||
//
|
//
|
||||||
|
|
||||||
typedef struct APPLE_FSYS_STORE_HEADER_ {
|
typedef struct APPLE_SYSF_STORE_HEADER_ {
|
||||||
UINT32 Signature; // Fsys or Gaid signature
|
UINT32 Signature; // Fsys or Gaid signature
|
||||||
UINT8 Unknown0; // Still unknown
|
UINT8 Unknown0; // Still unknown
|
||||||
UINT32 Unknown1; // Still unknown
|
UINT32 Unknown1; // Still unknown
|
||||||
UINT16 Size; // Size of variable store
|
UINT16 Size; // Size of variable store
|
||||||
} APPLE_FSYS_STORE_HEADER;
|
} APPLE_SYSF_STORE_HEADER;
|
||||||
|
|
||||||
// Apple Fsys entry format
|
// Apple Fsys entry format
|
||||||
// UINT8 NameLength;
|
// UINT8 NameLength;
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "umemstream.h"
|
#include "umemstream.h"
|
||||||
#include "kaitai/kaitaistream.h"
|
#include "kaitai/kaitaistream.h"
|
||||||
#include "generated/ami_nvar.h"
|
#include "generated/ami_nvar.h"
|
||||||
|
#include "generated/apple_sysf.h"
|
||||||
#include "generated/edk2_vss.h"
|
#include "generated/edk2_vss.h"
|
||||||
#include "generated/edk2_vss2.h"
|
#include "generated/edk2_vss2.h"
|
||||||
#include "generated/edk2_ftw.h"
|
#include "generated/edk2_ftw.h"
|
||||||
|
@ -72,7 +73,7 @@ USTATUS NvramParser::parseNvarStore(const UModelIndex & index)
|
||||||
// Get info
|
// Get info
|
||||||
UString info = usprintf("Full size: %Xh (%u)", (UINT32)padding.size(), (UINT32)padding.size());
|
UString info = usprintf("Full size: %Xh (%u)", (UINT32)padding.size(), (UINT32)padding.size());
|
||||||
|
|
||||||
if ((UINT32)padding.count(0xFF) == unparsedSize) { // Free space
|
if ((UINT32)padding.count('\'xFF') == unparsedSize) { // Free space
|
||||||
// Add tree item
|
// Add tree item
|
||||||
model->addItem(localOffset + entry->offset(), Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), padding, UByteArray(), Fixed, index);
|
model->addItem(localOffset + entry->offset(), Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), padding, UByteArray(), Fixed, index);
|
||||||
}
|
}
|
||||||
|
@ -312,7 +313,6 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32
|
||||||
for (UINT32 storeOffset = 0;
|
for (UINT32 storeOffset = 0;
|
||||||
storeOffset < volumeBodySize;
|
storeOffset < volumeBodySize;
|
||||||
storeOffset++) {
|
storeOffset++) {
|
||||||
bool storeFound = false;
|
|
||||||
// VSS
|
// VSS
|
||||||
try {
|
try {
|
||||||
if (volumeBodySize - storeOffset < sizeof(VSS_VARIABLE_STORE_HEADER)) {
|
if (volumeBodySize - storeOffset < sizeof(VSS_VARIABLE_STORE_HEADER)) {
|
||||||
|
@ -375,18 +375,18 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32
|
||||||
// Add header tree item
|
// Add header tree item
|
||||||
UModelIndex headerIndex = model->addItem(localOffset + storeOffset, Types::VssStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, index);
|
UModelIndex headerIndex = model->addItem(localOffset + storeOffset, Types::VssStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, index);
|
||||||
|
|
||||||
|
// Add variables
|
||||||
UINT32 vssVariableOffset = storeOffset + parsed.len_vss_store_header();
|
UINT32 vssVariableOffset = storeOffset + parsed.len_vss_store_header();
|
||||||
for (const auto & variable : *parsed.body()->variables()) {
|
for (const auto & variable : *parsed.body()->variables()) {
|
||||||
UINT8 subtype;
|
UINT8 subtype;
|
||||||
UString text;
|
UString text;
|
||||||
info.clear();
|
|
||||||
name.clear();
|
|
||||||
|
|
||||||
// This is thew terminating entry, needs special processing
|
// This is the terminating entry, needs special processing
|
||||||
if (variable->_is_null_signature_last()) {
|
if (variable->_is_null_signature_last()) {
|
||||||
// Add free space or padding after all variables, if needed
|
// Add free space or padding after all variables, if needed
|
||||||
if (vssVariableOffset < storeSize) {
|
UINT32 freeSpaceOffset = vssVariableOffset - storeOffset;
|
||||||
UByteArray freeSpace = vss.mid(vssVariableOffset, storeSize - vssVariableOffset);
|
if (freeSpaceOffset < storeSize) {
|
||||||
|
UByteArray freeSpace = vss.mid(freeSpaceOffset, storeSize - freeSpaceOffset);
|
||||||
// Add info
|
// Add info
|
||||||
info = usprintf("Full size: %Xh (%u)", (UINT32)freeSpace.size(), (UINT32)freeSpace.size());
|
info = usprintf("Full size: %Xh (%u)", (UINT32)freeSpace.size(), (UINT32)freeSpace.size());
|
||||||
|
|
||||||
|
@ -493,9 +493,9 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32
|
||||||
vssVariableOffset += variableSize;
|
vssVariableOffset += variableSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
storeFound = true;
|
storeOffset += storeSize - 1;
|
||||||
storeOffset += storeSize;
|
previousStoreEndOffset = storeOffset + 1;
|
||||||
previousStoreEndOffset = storeOffset;
|
continue;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
// Parsing failed, try something else
|
// Parsing failed, try something else
|
||||||
}
|
}
|
||||||
|
@ -513,7 +513,7 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32
|
||||||
VSS2_VARIABLE_STORE_HEADER* vss2Header = (VSS2_VARIABLE_STORE_HEADER*)vss2.data();
|
VSS2_VARIABLE_STORE_HEADER* vss2Header = (VSS2_VARIABLE_STORE_HEADER*)vss2.data();
|
||||||
UByteArray guid = UByteArray((const char*)&vss2Header->Signature, sizeof(EFI_GUID));
|
UByteArray guid = UByteArray((const char*)&vss2Header->Signature, sizeof(EFI_GUID));
|
||||||
bool fdcHeaderSizeOverrideRequired = (fdcStoreSizeOverride > 0 && guid == NVRAM_FDC_STORE_GUID && vss2Header->Size == 0xFFFFFFFF);
|
bool fdcHeaderSizeOverrideRequired = (fdcStoreSizeOverride > 0 && guid == NVRAM_FDC_STORE_GUID && vss2Header->Size == 0xFFFFFFFF);
|
||||||
if (fdcStoreSizeOverride) {
|
if (fdcHeaderSizeOverrideRequired) {
|
||||||
originalStoreSize = vss2Header->Size;
|
originalStoreSize = vss2Header->Size;
|
||||||
vss2Header->Size = fdcStoreSizeOverride;
|
vss2Header->Size = fdcStoreSizeOverride;
|
||||||
}
|
}
|
||||||
|
@ -522,7 +522,7 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32
|
||||||
edk2_vss2_t parsed(&ks);
|
edk2_vss2_t parsed(&ks);
|
||||||
UINT32 storeSize = parsed.vss2_size();
|
UINT32 storeSize = parsed.vss2_size();
|
||||||
// Restore original store size, if needed
|
// Restore original store size, if needed
|
||||||
if (fdcStoreSizeOverride) {
|
if (fdcHeaderSizeOverrideRequired) {
|
||||||
vss2Header->Size = originalStoreSize;
|
vss2Header->Size = originalStoreSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -563,18 +563,18 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32
|
||||||
// Add header tree item
|
// Add header tree item
|
||||||
UModelIndex headerIndex = model->addItem(localOffset + storeOffset, Types::Vss2Store, 0, name, UString(), info, header, body, UByteArray(), Fixed, index);
|
UModelIndex headerIndex = model->addItem(localOffset + storeOffset, Types::Vss2Store, 0, name, UString(), info, header, body, UByteArray(), Fixed, index);
|
||||||
|
|
||||||
|
// Add variables
|
||||||
UINT32 vss2VariableOffset = storeOffset + parsed.len_vss2_store_header();
|
UINT32 vss2VariableOffset = storeOffset + parsed.len_vss2_store_header();
|
||||||
for (const auto & variable : *parsed.body()->variables()) {
|
for (const auto & variable : *parsed.body()->variables()) {
|
||||||
UINT8 subtype;
|
UINT8 subtype;
|
||||||
UString text;
|
UString text;
|
||||||
info.clear();
|
|
||||||
name.clear();
|
|
||||||
|
|
||||||
// This is thew terminating entry, needs special processing
|
// This is the terminating entry, needs special processing
|
||||||
if (variable->_is_null_signature_last()) {
|
if (variable->_is_null_signature_last()) {
|
||||||
// Add free space or padding after all variables, if needed
|
// Add free space or padding after all variables, if needed
|
||||||
if (vss2VariableOffset < storeSize) {
|
UINT32 freeSpaceOffset = vss2VariableOffset - storeOffset;
|
||||||
UByteArray freeSpace = vss2.mid(vss2VariableOffset, storeSize - vss2VariableOffset);
|
if (freeSpaceOffset < storeSize) {
|
||||||
|
UByteArray freeSpace = vss2.mid(freeSpaceOffset, storeSize - freeSpaceOffset);
|
||||||
// Add info
|
// Add info
|
||||||
info = usprintf("Full size: %Xh (%u)", (UINT32)freeSpace.size(), (UINT32)freeSpace.size());
|
info = usprintf("Full size: %Xh (%u)", (UINT32)freeSpace.size(), (UINT32)freeSpace.size());
|
||||||
|
|
||||||
|
@ -651,140 +651,247 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32
|
||||||
vss2VariableOffset += variableSize;
|
vss2VariableOffset += variableSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
storeFound = true;
|
storeOffset += storeSize - 1;
|
||||||
storeOffset += storeSize;
|
previousStoreEndOffset = storeOffset + 1;
|
||||||
previousStoreEndOffset = storeOffset;
|
continue;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
// Parsing failed, try something else
|
// Parsing failed, try something else
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do not try any other parsers if we are here for FDC store parsing
|
// Do not try any other parsers if we are here for FDC store parsing
|
||||||
if (fdcStoreSizeOverride == 0) {
|
if (fdcStoreSizeOverride != 0) {
|
||||||
// FTW
|
continue;
|
||||||
try {
|
}
|
||||||
if (volumeBodySize - storeOffset < sizeof(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32)) {
|
// FTW
|
||||||
// No need to parse further, the rest of the volume is too small
|
try {
|
||||||
throw 0;
|
if (volumeBodySize - storeOffset < sizeof(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32)) {
|
||||||
}
|
// No need to parse further, the rest of the volume is too small
|
||||||
|
throw 0;
|
||||||
|
}
|
||||||
|
|
||||||
UByteArray ftw = volumeBody.mid(storeOffset);
|
UByteArray ftw = volumeBody.mid(storeOffset);
|
||||||
umemstream is(ftw.constData(), ftw.size());
|
umemstream is(ftw.constData(), ftw.size());
|
||||||
kaitai::kstream ks(&is);
|
kaitai::kstream ks(&is);
|
||||||
edk2_ftw_t parsed(&ks);
|
edk2_ftw_t parsed(&ks);
|
||||||
UINT64 storeSize;
|
UINT64 storeSize;
|
||||||
UINT64 headerSize;
|
UINT64 headerSize;
|
||||||
UINT32 calculatedCrc;
|
UINT32 calculatedCrc;
|
||||||
UByteArray header;
|
UByteArray header;
|
||||||
if (parsed._is_null_len_write_queue_64()) {
|
if (parsed._is_null_len_write_queue_64()) {
|
||||||
headerSize = parsed.len_ftw_store_header_32();
|
headerSize = parsed.len_ftw_store_header_32();
|
||||||
storeSize = headerSize + parsed.len_write_queue_32();
|
storeSize = headerSize + parsed.len_write_queue_32();
|
||||||
header = ftw.left(headerSize);
|
header = ftw.left(headerSize);
|
||||||
|
|
||||||
// Check block header checksum
|
// Check block header checksum
|
||||||
UByteArray crcHeader = header;
|
UByteArray crcHeader = header;
|
||||||
EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32* crcFtwBlockHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32*)crcHeader.data();
|
EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32* crcFtwBlockHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32*)crcHeader.data();
|
||||||
crcFtwBlockHeader->Crc = emptyByte ? 0xFFFFFFFF : 0;
|
crcFtwBlockHeader->Crc = emptyByte ? 0xFFFFFFFF : 0;
|
||||||
crcFtwBlockHeader->State = emptyByte ? 0xFF : 0;
|
crcFtwBlockHeader->State = emptyByte ? 0xFF : 0;
|
||||||
calculatedCrc = (UINT32)crc32(0, (const UINT8*)crcFtwBlockHeader, (UINT32)headerSize);
|
calculatedCrc = (UINT32)crc32(0, (const UINT8*)crcFtwBlockHeader, (UINT32)headerSize);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
headerSize = parsed.len_ftw_store_header_64();
|
||||||
|
storeSize = headerSize + parsed.len_write_queue_32() + (((UINT64)parsed.len_write_queue_64()) << 32);
|
||||||
|
header = ftw.left(headerSize);
|
||||||
|
|
||||||
|
// Check block header checksum
|
||||||
|
UByteArray crcHeader = header;
|
||||||
|
EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64* crcFtwBlockHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64*)crcHeader.data();
|
||||||
|
crcFtwBlockHeader->Crc = emptyByte ? 0xFFFFFFFF : 0;
|
||||||
|
crcFtwBlockHeader->State = emptyByte ? 0xFF : 0;
|
||||||
|
calculatedCrc = (UINT32)crc32(0, (const UINT8*)crcFtwBlockHeader, (UINT32)headerSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FTW store at current offset parsed correctly
|
||||||
|
// Check if we need to add a padding before it
|
||||||
|
if (!outerPadding.isEmpty()) {
|
||||||
|
UString info = usprintf("Full size: %Xh (%u)", (UINT32)outerPadding.size(), (UINT32)outerPadding.size());
|
||||||
|
model->addItem(previousStoreEndOffset, Types::Padding, getPaddingType(outerPadding), UString("Padding"), UString(), info, UByteArray(), outerPadding, UByteArray(), Fixed, index);
|
||||||
|
outerPadding.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct header and body
|
||||||
|
UByteArray body = ftw.mid(header.size(), storeSize - header.size());
|
||||||
|
|
||||||
|
// Add info
|
||||||
|
const EFI_GUID* guid = (const EFI_GUID*)header.constData();
|
||||||
|
UString name = UString("FTW store");
|
||||||
|
UString info = UString("Signature: ") + guidToUString(*guid, false);
|
||||||
|
info += usprintf("\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nState: %02Xh\nHeader CRC32: %08Xh",
|
||||||
|
(UINT32)storeSize, (UINT32)storeSize,
|
||||||
|
(UINT32)header.size(), (UINT32)header.size(),
|
||||||
|
(UINT32)body.size(), (UINT32)body.size(),
|
||||||
|
parsed.state(),
|
||||||
|
parsed.crc()) + (parsed.crc() != calculatedCrc ? usprintf(", invalid, should be %08Xh", calculatedCrc) : UString(", valid"));
|
||||||
|
|
||||||
|
// Add header tree item
|
||||||
|
model->addItem(localOffset + storeOffset, Types::FtwStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, index);
|
||||||
|
|
||||||
|
storeOffset += storeSize - 1;
|
||||||
|
previousStoreEndOffset = storeOffset + 1;
|
||||||
|
continue;
|
||||||
|
} catch (...) {
|
||||||
|
// Parsing failed, try something else
|
||||||
|
}
|
||||||
|
// Insyde FDC
|
||||||
|
try {
|
||||||
|
if (volumeBodySize - storeOffset < sizeof(FDC_VOLUME_HEADER)) {
|
||||||
|
// No need to parse further, the rest of the volume is too small
|
||||||
|
throw 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
UByteArray fdc = volumeBody.mid(storeOffset);
|
||||||
|
umemstream is(fdc.constData(), fdc.size());
|
||||||
|
kaitai::kstream ks(&is);
|
||||||
|
insyde_fdc_t parsed(&ks);
|
||||||
|
UINT32 storeSize = parsed.fdc_size();
|
||||||
|
|
||||||
|
// FDC store at current offset parsed correctly
|
||||||
|
// Check if we need to add a padding before it
|
||||||
|
if (!outerPadding.isEmpty()) {
|
||||||
|
UString info = usprintf("Full size: %Xh (%u)", (UINT32)outerPadding.size(), (UINT32)outerPadding.size());
|
||||||
|
model->addItem(previousStoreEndOffset, Types::Padding, getPaddingType(outerPadding), UString("Padding"), UString(), info, UByteArray(), outerPadding, UByteArray(), Fixed, index);
|
||||||
|
outerPadding.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct header and body
|
||||||
|
UByteArray header = fdc.left(parsed.len_fdc_store_header());
|
||||||
|
UByteArray body = fdc.mid(header.size(),storeSize - header.size());
|
||||||
|
|
||||||
|
// Add info
|
||||||
|
UString name = UString("FDC store");
|
||||||
|
UString info = usprintf("Signature: _FDC\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)",
|
||||||
|
storeSize, storeSize,
|
||||||
|
(UINT32)header.size(), (UINT32)header.size(),
|
||||||
|
(UINT32)body.size(), (UINT32)body.size());
|
||||||
|
|
||||||
|
// Add header tree item
|
||||||
|
UModelIndex headerIndex = model->addItem(localOffset + storeOffset, Types::FdcStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, index);
|
||||||
|
|
||||||
|
// Parse FDC body as normal VSS/VSS2 storage with size override
|
||||||
|
parseNvramVolumeBody(headerIndex, (UINT32)body.size());
|
||||||
|
|
||||||
|
storeOffset += storeSize - 1;
|
||||||
|
previousStoreEndOffset = storeOffset + 1;
|
||||||
|
continue;
|
||||||
|
} catch (...) {
|
||||||
|
// Parsing failed, try something else
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apple SysF
|
||||||
|
try {
|
||||||
|
if (volumeBodySize - storeOffset < sizeof(APPLE_SYSF_STORE_HEADER)) {
|
||||||
|
// No need to parse further, the rest of the volume is too small
|
||||||
|
throw 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
UByteArray sysf = volumeBody.mid(storeOffset);
|
||||||
|
umemstream is(sysf.constData(), sysf.size());
|
||||||
|
kaitai::kstream ks(&is);
|
||||||
|
apple_sysf_t parsed(&ks);
|
||||||
|
UINT32 storeSize = parsed.sysf_size();
|
||||||
|
|
||||||
|
// Apple SysF store at current offset parsed correctly
|
||||||
|
// Check if we need to add a padding before it
|
||||||
|
if (!outerPadding.isEmpty()) {
|
||||||
|
UString info = usprintf("Full size: %Xh (%u)", (UINT32)outerPadding.size(), (UINT32)outerPadding.size());
|
||||||
|
model->addItem(previousStoreEndOffset, Types::Padding, getPaddingType(outerPadding), UString("Padding"), UString(), info, UByteArray(), outerPadding, UByteArray(), Fixed, index);
|
||||||
|
outerPadding.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct header and body
|
||||||
|
UByteArray header = sysf.left(parsed.len_sysf_store_header());
|
||||||
|
UByteArray body = sysf.mid(header.size(), storeSize - header.size());
|
||||||
|
|
||||||
|
// Check store checksum
|
||||||
|
UINT32 calculatedCrc = (UINT32)crc32(0, (const UINT8*)sysf.constData(), storeSize - sizeof(UINT32));
|
||||||
|
|
||||||
|
// Add info
|
||||||
|
UString name;
|
||||||
|
UString info;
|
||||||
|
if (parsed.signature() == NVRAM_APPLE_SYSF_STORE_SIGNATURE) {
|
||||||
|
name = UString("SysF store");
|
||||||
|
info = UString("Signature: Fsys\n");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
name = UString("Diag store");
|
||||||
|
info = UString("Signature: Gaid\n");
|
||||||
|
}
|
||||||
|
info += usprintf("Full size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nUnknown: %02Xh\nUnknown1: %08Xh\nCRC32: %08Xh",
|
||||||
|
storeSize, storeSize,
|
||||||
|
(UINT32)header.size(), (UINT32)header.size(),
|
||||||
|
(UINT32)body.size(), (UINT32)body.size(),
|
||||||
|
parsed.unknown(),
|
||||||
|
parsed.unknown1(),
|
||||||
|
parsed.crc()) + (parsed.crc() != calculatedCrc ? usprintf(", invalid, should be %08Xh", calculatedCrc) : UString(", valid"));
|
||||||
|
|
||||||
|
// Add header tree item
|
||||||
|
UModelIndex headerIndex = model->addItem(localOffset + storeOffset, Types::SysFStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, index);
|
||||||
|
|
||||||
|
// Add variables
|
||||||
|
UINT32 sysfVariableOffset = storeOffset + parsed.len_sysf_store_header();
|
||||||
|
for (const auto & variable : *parsed.body()->variables()) {
|
||||||
|
UINT8 subtype;
|
||||||
|
|
||||||
|
if (variable->invalid_flag()) {
|
||||||
|
subtype = Subtypes::InvalidSysFEntry;
|
||||||
|
name = UString("Invalid");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
headerSize = parsed.len_ftw_store_header_64();
|
subtype = Subtypes::NormalSysFEntry;
|
||||||
storeSize = headerSize + parsed.len_write_queue_32() + (((UINT64)parsed.len_write_queue_64()) << 32);
|
name = usprintf("%s", variable->name().c_str());
|
||||||
header = ftw.left(headerSize);
|
|
||||||
|
|
||||||
// Check block header checksum
|
|
||||||
UByteArray crcHeader = header;
|
|
||||||
EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64* crcFtwBlockHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64*)crcHeader.data();
|
|
||||||
crcFtwBlockHeader->Crc = emptyByte ? 0xFFFFFFFF : 0;
|
|
||||||
crcFtwBlockHeader->State = emptyByte ? 0xFF : 0;
|
|
||||||
calculatedCrc = (UINT32)crc32(0, (const UINT8*)crcFtwBlockHeader, (UINT32)headerSize);
|
|
||||||
}
|
}
|
||||||
|
if (variable->len_name() == 3 && variable->name() == "EOF") {
|
||||||
// FTW store at current offset parsed correctly
|
header = volumeBody.mid(sysfVariableOffset, 4);
|
||||||
// Check if we need to add a padding before it
|
|
||||||
if (!outerPadding.isEmpty()) {
|
|
||||||
UString info = usprintf("Full size: %Xh (%u)", (UINT32)outerPadding.size(), (UINT32)outerPadding.size());
|
|
||||||
model->addItem(previousStoreEndOffset, Types::Padding, getPaddingType(outerPadding), UString("Padding"), UString(), info, UByteArray(), outerPadding, UByteArray(), Fixed, index);
|
|
||||||
outerPadding.clear();
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
// Construct header and body
|
header = volumeBody.mid(sysfVariableOffset, sizeof(UINT8) + (UINT32)variable->len_name() + sizeof(UINT16));
|
||||||
UByteArray body = ftw.mid(header.size(), storeSize - header.size());
|
body = volumeBody.mid(sysfVariableOffset + header.size(), (UINT32)variable->len_data());
|
||||||
|
}
|
||||||
// Add info
|
// Add generic info
|
||||||
const EFI_GUID* guid = (const EFI_GUID*)header.constData();
|
UINT32 variableSize = (UINT32)header.size() + (UINT32)body.size();
|
||||||
UString name = UString("FTW store");
|
info = usprintf("Full size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\n",
|
||||||
UString info = UString("Signature: ") + guidToUString(*guid, false);
|
variableSize, variableSize,
|
||||||
info += usprintf("\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nState: %02Xh\nHeader CRC32: %08Xh",
|
|
||||||
(UINT32)storeSize, (UINT32)storeSize,
|
|
||||||
(UINT32)header.size(), (UINT32)header.size(),
|
(UINT32)header.size(), (UINT32)header.size(),
|
||||||
(UINT32)body.size(), (UINT32)body.size(),
|
(UINT32)body.size(), (UINT32)body.size());
|
||||||
parsed.state(),
|
|
||||||
parsed.crc()) + (parsed.crc() != calculatedCrc ? usprintf(", invalid, should be %08Xh", calculatedCrc) : UString(", valid"));
|
|
||||||
|
|
||||||
// Add header tree item
|
// Add tree item
|
||||||
UModelIndex headerIndex = model->addItem(localOffset + storeOffset, Types::FtwStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, index);
|
model->addItem(sysfVariableOffset, Types::SysFEntry, subtype, name, UString(), info, header, body, UByteArray(), Fixed, headerIndex);
|
||||||
|
|
||||||
storeFound = true;
|
sysfVariableOffset += variableSize;
|
||||||
storeOffset += storeSize;
|
|
||||||
previousStoreEndOffset = storeOffset;
|
|
||||||
} catch (...) {
|
|
||||||
// Parsing failed, try something else
|
|
||||||
}
|
}
|
||||||
// Insyde FDC
|
|
||||||
try {
|
|
||||||
if (volumeBodySize - storeOffset < sizeof(FDC_VOLUME_HEADER)) {
|
|
||||||
// No need to parse further, the rest of the volume is too small
|
|
||||||
throw 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
UByteArray fdc = volumeBody.mid(storeOffset);
|
|
||||||
umemstream is(fdc.constData(), fdc.size());
|
|
||||||
kaitai::kstream ks(&is);
|
|
||||||
insyde_fdc_t parsed(&ks);
|
|
||||||
UINT32 storeSize = parsed.fdc_size();
|
|
||||||
|
|
||||||
// FDC store at current offset parsed correctly
|
|
||||||
// Check if we need to add a padding before it
|
|
||||||
if (!outerPadding.isEmpty()) {
|
|
||||||
UString info = usprintf("Full size: %Xh (%u)", (UINT32)outerPadding.size(), (UINT32)outerPadding.size());
|
|
||||||
model->addItem(previousStoreEndOffset, Types::Padding, getPaddingType(outerPadding), UString("Padding"), UString(), info, UByteArray(), outerPadding, UByteArray(), Fixed, index);
|
|
||||||
outerPadding.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Construct header and body
|
|
||||||
UByteArray header = fdc.left(parsed.len_fdc_store_header());
|
|
||||||
UByteArray body = fdc.mid(header.size(),storeSize - header.size());
|
|
||||||
|
|
||||||
|
// Add free space or padding after all variables, if needed
|
||||||
|
UINT32 freeSpaceOffset = sysfVariableOffset - storeOffset;
|
||||||
|
if (freeSpaceOffset < storeSize) {
|
||||||
|
UByteArray freeSpace = sysf.mid(freeSpaceOffset, storeSize - freeSpaceOffset);
|
||||||
// Add info
|
// Add info
|
||||||
UString name = UString("FDC store");
|
info = usprintf("Full size: %Xh (%u)", (UINT32)freeSpace.size(), (UINT32)freeSpace.size());
|
||||||
UString info = usprintf("Signature: _FDC\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)",
|
|
||||||
storeSize, storeSize,
|
|
||||||
(UINT32)header.size(), (UINT32)header.size(),
|
|
||||||
(UINT32)body.size(), (UINT32)body.size());
|
|
||||||
|
|
||||||
// Add header tree item
|
// Check that remaining unparsed bytes are actually zeroes
|
||||||
UModelIndex headerIndex = model->addItem(localOffset + storeOffset, Types::FdcStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, index);
|
if (freeSpace.count('\x00') == freeSpace.size() - 4) { // Free space, 4 last bytes are always CRC32
|
||||||
|
// Add tree item
|
||||||
// Parse FDC body as normal VSS/VSS2 storage with size override
|
model->addItem(sysfVariableOffset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), freeSpace, UByteArray(), Fixed, headerIndex);
|
||||||
parseNvramVolumeBody(headerIndex, (UINT32)body.size());
|
}
|
||||||
|
else {
|
||||||
storeFound = true;
|
// Add tree item
|
||||||
storeOffset += storeSize;
|
model->addItem(sysfVariableOffset, Types::Padding, getPaddingType(freeSpace), UString("Padding"), UString(), info, UByteArray(), freeSpace, UByteArray(), Fixed, headerIndex);
|
||||||
previousStoreEndOffset = storeOffset;
|
}
|
||||||
} catch (...) {
|
|
||||||
// Parsing failed, try something else
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apple Fsys/Gaid
|
storeOffset += storeSize - 1;
|
||||||
|
previousStoreEndOffset = storeOffset + 1;
|
||||||
// Phoenix EVSA
|
continue;
|
||||||
// Phoenix FlashMap
|
} catch (...) {
|
||||||
// Phoenix CMDB
|
// Parsing failed, try something else
|
||||||
// Phoenix SLIC Pubkey/Marker
|
|
||||||
// Intel uCode
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Phoenix EVSA
|
||||||
|
// Phoenix FlashMap
|
||||||
|
// Phoenix CMDB
|
||||||
|
// Phoenix SLIC Pubkey/Marker
|
||||||
|
// Intel uCode
|
||||||
|
|
||||||
// Padding
|
// Padding
|
||||||
if (storeOffset < volumeBodySize) {
|
if (storeOffset < volumeBodySize) {
|
||||||
outerPadding += volumeBody[storeOffset];
|
outerPadding += volumeBody[storeOffset];
|
||||||
|
@ -795,8 +902,16 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32
|
||||||
if (!outerPadding.isEmpty()) {
|
if (!outerPadding.isEmpty()) {
|
||||||
// Add info
|
// Add info
|
||||||
UString info = usprintf("Full size: %Xh (%u)", (UINT32)outerPadding.size(), (UINT32)outerPadding.size());
|
UString info = usprintf("Full size: %Xh (%u)", (UINT32)outerPadding.size(), (UINT32)outerPadding.size());
|
||||||
// Add tree item
|
|
||||||
model->addItem(localOffset + previousStoreEndOffset, Types::Padding, getPaddingType(outerPadding), UString("Padding"), UString(), info, UByteArray(), outerPadding, UByteArray(), Fixed, index);
|
// Check that remaining unparsed bytes are actually empty
|
||||||
|
if (outerPadding.count(emptyByte) == outerPadding.size()) {
|
||||||
|
// Add tree item
|
||||||
|
model->addItem(localOffset + previousStoreEndOffset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), outerPadding, UByteArray(), Fixed, index);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Add tree item
|
||||||
|
model->addItem(localOffset + previousStoreEndOffset, Types::Padding, getPaddingType(outerPadding), UString("Padding"), UString(), info, UByteArray(), outerPadding, UByteArray(), Fixed, index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return U_SUCCESS;
|
return U_SUCCESS;
|
||||||
|
|
|
@ -55,14 +55,14 @@ UString itemTypeToUString(const UINT8 type)
|
||||||
case Types::Vss2Store: return UString("VSS2 store");
|
case Types::Vss2Store: return UString("VSS2 store");
|
||||||
case Types::FtwStore: return UString("FTW store");
|
case Types::FtwStore: return UString("FTW store");
|
||||||
case Types::FdcStore: return UString("FDC store");
|
case Types::FdcStore: return UString("FDC store");
|
||||||
case Types::FsysStore: return UString("Fsys store");
|
case Types::SysFStore: return UString("SysF store");
|
||||||
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::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::SysFEntry: return UString("SysF entry");
|
||||||
case Types::EvsaEntry: return UString("EVSA entry");
|
case Types::EvsaEntry: return UString("EVSA entry");
|
||||||
case Types::FlashMapEntry: return UString("FlashMap entry");
|
case Types::FlashMapEntry: return UString("FlashMap entry");
|
||||||
case Types::Microcode: return UString("Microcode");
|
case Types::Microcode: return UString("Microcode");
|
||||||
|
@ -128,9 +128,9 @@ UString itemSubtypeToUString(const UINT8 type, const UINT8 subtype)
|
||||||
else if (subtype == Subtypes::AuthVssEntry) return UString("Auth");
|
else if (subtype == Subtypes::AuthVssEntry) return UString("Auth");
|
||||||
else if (subtype == Subtypes::IntelVssEntry) return UString("Intel");
|
else if (subtype == Subtypes::IntelVssEntry) return UString("Intel");
|
||||||
break;
|
break;
|
||||||
case Types::FsysEntry:
|
case Types::SysFEntry:
|
||||||
if (subtype == Subtypes::InvalidFsysEntry) return UString("Invalid");
|
if (subtype == Subtypes::InvalidSysFEntry) return UString("Invalid");
|
||||||
else if (subtype == Subtypes::NormalFsysEntry) return UString("Normal");
|
else if (subtype == Subtypes::NormalSysFEntry) return UString("Normal");
|
||||||
break;
|
break;
|
||||||
case Types::EvsaEntry:
|
case Types::EvsaEntry:
|
||||||
if (subtype == Subtypes::InvalidEvsaEntry) return UString("Invalid");
|
if (subtype == Subtypes::InvalidEvsaEntry) return UString("Invalid");
|
||||||
|
|
|
@ -47,14 +47,14 @@ namespace Types {
|
||||||
Vss2Store,
|
Vss2Store,
|
||||||
FtwStore,
|
FtwStore,
|
||||||
FdcStore,
|
FdcStore,
|
||||||
FsysStore,
|
SysFStore,
|
||||||
EvsaStore,
|
EvsaStore,
|
||||||
FlashMapStore,
|
FlashMapStore,
|
||||||
CmdbStore,
|
CmdbStore,
|
||||||
NvarGuidStore,
|
NvarGuidStore,
|
||||||
NvarEntry,
|
NvarEntry,
|
||||||
VssEntry,
|
VssEntry,
|
||||||
FsysEntry,
|
SysFEntry,
|
||||||
EvsaEntry,
|
EvsaEntry,
|
||||||
FlashMapEntry,
|
FlashMapEntry,
|
||||||
Microcode,
|
Microcode,
|
||||||
|
@ -138,9 +138,9 @@ namespace Subtypes {
|
||||||
IntelVssEntry,
|
IntelVssEntry,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum FsysEntrySubtypes {
|
enum SysFEntrySubtypes {
|
||||||
InvalidFsysEntry = 150,
|
InvalidSysFEntry = 150,
|
||||||
NormalFsysEntry,
|
NormalSysFEntry,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum EvsaEntrySubtypes {
|
enum EvsaEntrySubtypes {
|
||||||
|
|
|
@ -69,6 +69,7 @@ public:
|
||||||
|
|
||||||
UByteArray & operator=(const UByteArray & ba) { d = ba.d; return *this; }
|
UByteArray & operator=(const UByteArray & ba) { d = ba.d; return *this; }
|
||||||
UByteArray & operator+=(const UByteArray & ba) { d += ba.d; return *this; }
|
UByteArray & operator+=(const UByteArray & ba) { d += ba.d; return *this; }
|
||||||
|
UByteArray & operator+=(const char c) { d += c; return *this; }
|
||||||
bool operator== (const UByteArray & ba) const { return d == ba.d; }
|
bool operator== (const UByteArray & ba) const { return d == ba.d; }
|
||||||
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); }
|
inline void swap(UByteArray &other) { std::swap(d, other.d); }
|
||||||
|
|
|
@ -81,7 +81,7 @@ UString uniqueItemName(const UModelIndex & index)
|
||||||
switch (model->type(index)) {
|
switch (model->type(index)) {
|
||||||
case Types::NvarEntry:
|
case Types::NvarEntry:
|
||||||
case Types::VssEntry:
|
case Types::VssEntry:
|
||||||
case Types::FsysEntry:
|
case Types::SysFEntry:
|
||||||
case Types::EvsaEntry:
|
case Types::EvsaEntry:
|
||||||
case Types::FlashMapEntry:
|
case Types::FlashMapEntry:
|
||||||
case Types::File:
|
case Types::File:
|
||||||
|
|
|
@ -32,6 +32,11 @@ SET(PROJECT_SOURCES
|
||||||
../common/Tiano/EfiTianoDecompress.c
|
../common/Tiano/EfiTianoDecompress.c
|
||||||
../common/ustring.cpp
|
../common/ustring.cpp
|
||||||
../common/generated/ami_nvar.cpp
|
../common/generated/ami_nvar.cpp
|
||||||
|
../common/generated/apple_sysf.cpp
|
||||||
|
../common/generated/edk2_vss.cpp
|
||||||
|
../common/generated/edk2_vss2.cpp
|
||||||
|
../common/generated/edk2_ftw.cpp
|
||||||
|
../common/generated/insyde_fdc.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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue