Rewrite VSS and VSS2 NVRAM variable parsers in KaitaiStruct

This commit is contained in:
Nikolaj Schlej 2025-02-22 11:19:41 +07:00
parent 2661b8fe4b
commit 489b85fd98
11 changed files with 1430 additions and 40 deletions

View file

@ -69,6 +69,7 @@ SET(PROJECT_SOURCES
../common/digest/sm3.c
../common/generated/ami_nvar.cpp
../common/generated/edk2_vss.cpp
../common/generated/phoenix_vss2.cpp
../common/generated/intel_acbp_v1.cpp
../common/generated/intel_acbp_v2.cpp
../common/generated/intel_keym_v1.cpp

View file

@ -1453,7 +1453,7 @@ USTATUS FfsParser::parseVolumeBody(const UModelIndex & index)
UByteArray volumeBody = model->body(index);
UINT32 volumeHeaderSize = (UINT32)model->header(index).size();
// Parse VSS NVRAM volumes with a dedicated function
// Parse NVRAM volume with a dedicated function
if (model->subtype(index) == Subtypes::NvramVolume) {
return nvramParser->parseNvramVolumeBody(index);
}

View file

@ -8,6 +8,7 @@ edk2_vss_t::edk2_vss_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, edk2_
m__root = this; (void)p__root;
m_body = nullptr;
m__io__raw_body = nullptr;
f_len_vss_store_header = false;
_read();
}
@ -19,11 +20,11 @@ void edk2_vss_t::_read() {
throw kaitai::validation_expr_error<uint32_t>(signature(), _io(), std::string("/seq/0"));
}
}
m_size = m__io->read_u4le();
m_vss_size = m__io->read_u4le();
{
uint32_t _ = size();
if (!(_ > (4 * 4))) {
throw kaitai::validation_expr_error<uint32_t>(size(), _io(), std::string("/seq/1"));
uint32_t _ = vss_size();
if (!( ((_ > len_vss_store_header()) && (_ < 4294967295UL)) )) {
throw kaitai::validation_expr_error<uint32_t>(vss_size(), _io(), std::string("/seq/1"));
}
}
m_format = m__io->read_u1();
@ -36,7 +37,7 @@ void edk2_vss_t::_read() {
m_state = m__io->read_u1();
m_reserved = m__io->read_u2le();
m_reserved1 = m__io->read_u4le();
m__raw_body = m__io->read_bytes((size() - (4 * 4)));
m__raw_body = m__io->read_bytes((vss_size() - len_vss_store_header()));
m__io__raw_body = std::unique_ptr<kaitai::kstream>(new kaitai::kstream(m__raw_body));
m_body = std::unique_ptr<vss_store_body_t>(new vss_store_body_t(m__io__raw_body.get(), this, m__root));
}
@ -104,6 +105,13 @@ edk2_vss_t::vss_variable_t::vss_variable_t(kaitai::kstream* p__io, edk2_vss_t::v
m__parent = p__parent;
m__root = p__root;
m_attributes = nullptr;
f_is_auth = false;
f_len_standard_header = false;
f_is_intel_legacy = false;
f_len_auth_header = false;
f_len_apple_header = false;
f_len_intel_legacy_header = false;
f_is_valid = false;
_read();
}
@ -135,35 +143,105 @@ void edk2_vss_t::vss_variable_t::_read() {
n_attributes = false;
m_attributes = std::unique_ptr<vss_variable_attributes_t>(new vss_variable_attributes_t(m__io, this, m__root));
}
n_len_total = true;
if ( ((signature_first() == 170) && (is_intel_legacy())) ) {
n_len_total = false;
m_len_total = m__io->read_u4le();
{
uint32_t _ = len_total();
if (!(_ >= ((len_intel_legacy_header() + 4) + 1))) {
throw kaitai::validation_expr_error<uint32_t>(len_total(), _io(), std::string("/types/vss_variable/seq/5"));
}
}
}
n_len_name = true;
if (signature_first() == 170) {
if ( ((signature_first() == 170) && (!(is_intel_legacy()))) ) {
n_len_name = false;
m_len_name = m__io->read_u4le();
}
n_len_data = true;
if (signature_first() == 170) {
if ( ((signature_first() == 170) && (!(is_intel_legacy()))) ) {
n_len_data = false;
m_len_data = m__io->read_u4le();
}
n_timestamp = true;
if ( ((signature_first() == 170) && (is_auth())) ) {
n_timestamp = false;
m_timestamp = m__io->read_bytes(16);
}
n_pubkey_index = true;
if ( ((signature_first() == 170) && (is_auth())) ) {
n_pubkey_index = false;
m_pubkey_index = m__io->read_u4le();
}
n_len_name_auth = true;
if ( ((signature_first() == 170) && (is_auth())) ) {
n_len_name_auth = false;
m_len_name_auth = m__io->read_u4le();
{
uint32_t _ = len_name_auth();
if (!( ((_ >= 4) && (kaitai::kstream::mod(_, 2) == 0)) )) {
throw kaitai::validation_expr_error<uint32_t>(len_name_auth(), _io(), std::string("/types/vss_variable/seq/10"));
}
}
}
n_len_data_auth = true;
if ( ((signature_first() == 170) && (is_auth())) ) {
n_len_data_auth = false;
m_len_data_auth = m__io->read_u4le();
{
uint32_t _ = len_data_auth();
if (!(_ > 0)) {
throw kaitai::validation_expr_error<uint32_t>(len_data_auth(), _io(), std::string("/types/vss_variable/seq/11"));
}
}
}
n_vendor_guid = true;
if (signature_first() == 170) {
n_vendor_guid = false;
m_vendor_guid = m__io->read_bytes(16);
}
n_name_auth = true;
if ( ((signature_first() == 170) && (is_auth())) ) {
n_name_auth = false;
m_name_auth = m__io->read_bytes(len_name_auth());
}
n_data_auth = true;
if ( ((signature_first() == 170) && (is_auth())) ) {
n_data_auth = false;
m_data_auth = m__io->read_bytes(len_data_auth());
}
n_apple_data_crc32 = true;
if ( ((signature_first() == 170) && (attributes()->apple_data_checksum())) ) {
if ( ((signature_first() == 170) && (!(is_intel_legacy())) && (!(is_auth())) && (attributes()->apple_data_checksum())) ) {
n_apple_data_crc32 = false;
m_apple_data_crc32 = m__io->read_u4le();
}
n_intel_legacy_data = true;
if ( ((signature_first() == 170) && (is_intel_legacy())) ) {
n_intel_legacy_data = false;
m_intel_legacy_data = m__io->read_bytes((len_total() - len_intel_legacy_header()));
}
n_name = true;
if (signature_first() == 170) {
if ( ((signature_first() == 170) && (!(is_intel_legacy())) && (!(is_auth()))) ) {
n_name = false;
m_name = m__io->read_bytes(len_name());
{
std::string _ = name();
if (!( ((len_name() >= 4) && (kaitai::kstream::mod(len_name(), 2) == 0)) )) {
throw kaitai::validation_expr_error<std::string>(name(), _io(), std::string("/types/vss_variable/seq/17"));
}
}
}
n_data = true;
if (signature_first() == 170) {
if ( ((signature_first() == 170) && (!(is_intel_legacy())) && (!(is_auth()))) ) {
n_data = false;
m_data = m__io->read_bytes(len_data());
{
std::string _ = data();
if (!(len_name() > 0)) {
throw kaitai::validation_expr_error<std::string>(data(), _io(), std::string("/types/vss_variable/seq/18"));
}
}
}
}
@ -180,16 +258,96 @@ void edk2_vss_t::vss_variable_t::_clean_up() {
}
if (!n_attributes) {
}
if (!n_len_total) {
}
if (!n_len_name) {
}
if (!n_len_data) {
}
if (!n_timestamp) {
}
if (!n_pubkey_index) {
}
if (!n_len_name_auth) {
}
if (!n_len_data_auth) {
}
if (!n_vendor_guid) {
}
if (!n_name_auth) {
}
if (!n_data_auth) {
}
if (!n_apple_data_crc32) {
}
if (!n_intel_legacy_data) {
}
if (!n_name) {
}
if (!n_data) {
}
}
bool edk2_vss_t::vss_variable_t::is_auth() {
if (f_is_auth)
return m_is_auth;
m_is_auth = ((state() != 248) && (state() != 252) && ( (( ((attributes()->auth_write()) || (attributes()->time_based_auth()) || (attributes()->append_write())) ) || ( ((len_name() == 0) || (len_data() == 0)) )) )) ;
f_is_auth = true;
return m_is_auth;
}
int8_t edk2_vss_t::vss_variable_t::len_standard_header() {
if (f_len_standard_header)
return m_len_standard_header;
m_len_standard_header = 32;
f_len_standard_header = true;
return m_len_standard_header;
}
bool edk2_vss_t::vss_variable_t::is_intel_legacy() {
if (f_is_intel_legacy)
return m_is_intel_legacy;
m_is_intel_legacy = ((state() == 248) || (state() == 252)) ;
f_is_intel_legacy = true;
return m_is_intel_legacy;
}
int8_t edk2_vss_t::vss_variable_t::len_auth_header() {
if (f_len_auth_header)
return m_len_auth_header;
m_len_auth_header = 60;
f_len_auth_header = true;
return m_len_auth_header;
}
int8_t edk2_vss_t::vss_variable_t::len_apple_header() {
if (f_len_apple_header)
return m_len_apple_header;
m_len_apple_header = 36;
f_len_apple_header = true;
return m_len_apple_header;
}
int8_t edk2_vss_t::vss_variable_t::len_intel_legacy_header() {
if (f_len_intel_legacy_header)
return m_len_intel_legacy_header;
m_len_intel_legacy_header = 28;
f_len_intel_legacy_header = true;
return m_len_intel_legacy_header;
}
bool edk2_vss_t::vss_variable_t::is_valid() {
if (f_is_valid)
return m_is_valid;
m_is_valid = ((state() == 252) || (state() == 127) || (state() == 63)) ;
f_is_valid = true;
return m_is_valid;
}
int8_t edk2_vss_t::len_vss_store_header() {
if (f_len_vss_store_header)
return m_len_vss_store_header;
m_len_vss_store_header = 16;
f_len_vss_store_header = true;
return m_len_vss_store_header;
}

View file

@ -104,6 +104,55 @@ public:
public:
~vss_variable_t();
private:
bool f_is_auth;
bool m_is_auth;
public:
bool is_auth();
private:
bool f_len_standard_header;
int8_t m_len_standard_header;
public:
int8_t len_standard_header();
private:
bool f_is_intel_legacy;
bool m_is_intel_legacy;
public:
bool is_intel_legacy();
private:
bool f_len_auth_header;
int8_t m_len_auth_header;
public:
int8_t len_auth_header();
private:
bool f_len_apple_header;
int8_t m_len_apple_header;
public:
int8_t len_apple_header();
private:
bool f_len_intel_legacy_header;
int8_t m_len_intel_legacy_header;
public:
int8_t len_intel_legacy_header();
private:
bool f_is_valid;
bool m_is_valid;
public:
bool is_valid();
private:
uint8_t m_signature_first;
uint8_t m_signature_last;
@ -133,6 +182,13 @@ public:
public:
bool _is_null_attributes() { attributes(); return n_attributes; };
private:
uint32_t m_len_total;
bool n_len_total;
public:
bool _is_null_len_total() { len_total(); return n_len_total; };
private:
uint32_t m_len_name;
bool n_len_name;
@ -147,6 +203,34 @@ public:
public:
bool _is_null_len_data() { len_data(); return n_len_data; };
private:
std::string m_timestamp;
bool n_timestamp;
public:
bool _is_null_timestamp() { timestamp(); return n_timestamp; };
private:
uint32_t m_pubkey_index;
bool n_pubkey_index;
public:
bool _is_null_pubkey_index() { pubkey_index(); return n_pubkey_index; };
private:
uint32_t m_len_name_auth;
bool n_len_name_auth;
public:
bool _is_null_len_name_auth() { len_name_auth(); return n_len_name_auth; };
private:
uint32_t m_len_data_auth;
bool n_len_data_auth;
public:
bool _is_null_len_data_auth() { len_data_auth(); return n_len_data_auth; };
private:
std::string m_vendor_guid;
bool n_vendor_guid;
@ -154,6 +238,20 @@ public:
public:
bool _is_null_vendor_guid() { vendor_guid(); return n_vendor_guid; };
private:
std::string m_name_auth;
bool n_name_auth;
public:
bool _is_null_name_auth() { name_auth(); return n_name_auth; };
private:
std::string m_data_auth;
bool n_data_auth;
public:
bool _is_null_data_auth() { data_auth(); return n_data_auth; };
private:
uint32_t m_apple_data_crc32;
bool n_apple_data_crc32;
@ -161,6 +259,13 @@ public:
public:
bool _is_null_apple_data_crc32() { apple_data_crc32(); return n_apple_data_crc32; };
private:
std::string m_intel_legacy_data;
bool n_intel_legacy_data;
public:
bool _is_null_intel_legacy_data() { intel_legacy_data(); return n_intel_legacy_data; };
private:
std::string m_name;
bool n_name;
@ -185,19 +290,34 @@ public:
uint8_t state() const { return m_state; }
uint8_t reserved() const { return m_reserved; }
vss_variable_attributes_t* attributes() const { return m_attributes.get(); }
uint32_t len_total() const { return m_len_total; }
uint32_t len_name() const { return m_len_name; }
uint32_t len_data() const { return m_len_data; }
std::string timestamp() const { return m_timestamp; }
uint32_t pubkey_index() const { return m_pubkey_index; }
uint32_t len_name_auth() const { return m_len_name_auth; }
uint32_t len_data_auth() const { return m_len_data_auth; }
std::string vendor_guid() const { return m_vendor_guid; }
std::string name_auth() const { return m_name_auth; }
std::string data_auth() const { return m_data_auth; }
uint32_t apple_data_crc32() const { return m_apple_data_crc32; }
std::string intel_legacy_data() const { return m_intel_legacy_data; }
std::string name() const { return m_name; }
std::string data() const { return m_data; }
edk2_vss_t* _root() const { return m__root; }
edk2_vss_t::vss_store_body_t* _parent() const { return m__parent; }
};
private:
bool f_len_vss_store_header;
int8_t m_len_vss_store_header;
public:
int8_t len_vss_store_header();
private:
uint32_t m_signature;
uint32_t m_size;
uint32_t m_vss_size;
uint8_t m_format;
uint8_t m_state;
uint16_t m_reserved;
@ -210,7 +330,7 @@ private:
public:
uint32_t signature() const { return m_signature; }
uint32_t size() const { return m_size; }
uint32_t vss_size() const { return m_vss_size; }
uint8_t format() const { return m_format; }
uint8_t state() const { return m_state; }
uint16_t reserved() const { return m_reserved; }

View file

@ -0,0 +1,347 @@
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
#include "phoenix_vss2.h"
#include "../kaitai/exceptions.h"
phoenix_vss2_t::phoenix_vss2_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, phoenix_vss2_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_header_size = false;
_read();
}
void phoenix_vss2_t::_read() {
m_signature = m__io->read_u4le();
{
uint32_t _ = signature();
if (!( ((_ == 3721344535UL) || (_ == 2868063352UL)) )) {
throw kaitai::validation_expr_error<uint32_t>(signature(), _io(), std::string("/seq/0"));
}
}
n_signature_auth_var_key_db = true;
if (signature() == 2868063352UL) {
n_signature_auth_var_key_db = false;
m_signature_auth_var_key_db = m__io->read_bytes(12);
if (!(signature_auth_var_key_db() == std::string("\x7B\x94\x9A\x43\xA1\x80\x2E\x14\x4E\xC3\x77\x92", 12))) {
throw kaitai::validation_not_equal_error<std::string>(std::string("\x7B\x94\x9A\x43\xA1\x80\x2E\x14\x4E\xC3\x77\x92", 12), signature_auth_var_key_db(), _io(), std::string("/seq/1"));
}
}
n_signature_vss2_store = true;
if (signature() == 3721344535UL) {
n_signature_vss2_store = false;
m_signature_vss2_store = m__io->read_bytes(12);
if (!(signature_vss2_store() == std::string("\x75\x32\x64\x41\x98\xB6\xFE\x85\x70\x7F\xFE\x7D", 12))) {
throw kaitai::validation_not_equal_error<std::string>(std::string("\x75\x32\x64\x41\x98\xB6\xFE\x85\x70\x7F\xFE\x7D", 12), signature_vss2_store(), _io(), std::string("/seq/2"));
}
}
m_vss2_size = m__io->read_u4le();
{
uint32_t _ = vss2_size();
if (!( ((_ > header_size()) && (_ < 4294967295UL)) )) {
throw kaitai::validation_expr_error<uint32_t>(vss2_size(), _io(), std::string("/seq/3"));
}
}
m_format = m__io->read_u1();
{
uint8_t _ = format();
if (!(_ == 90)) {
throw kaitai::validation_expr_error<uint8_t>(format(), _io(), std::string("/seq/4"));
}
}
m_state = m__io->read_u1();
m_reserved = m__io->read_u2le();
m_reserved1 = m__io->read_u4le();
m__raw_body = m__io->read_bytes((vss2_size() - header_size()));
m__io__raw_body = std::unique_ptr<kaitai::kstream>(new kaitai::kstream(m__raw_body));
m_body = std::unique_ptr<vss2_store_body_t>(new vss2_store_body_t(m__io__raw_body.get(), this, m__root));
}
phoenix_vss2_t::~phoenix_vss2_t() {
_clean_up();
}
void phoenix_vss2_t::_clean_up() {
if (!n_signature_auth_var_key_db) {
}
if (!n_signature_vss2_store) {
}
}
phoenix_vss2_t::vss2_store_body_t::vss2_store_body_t(kaitai::kstream* p__io, phoenix_vss2_t* p__parent, phoenix_vss2_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_variables = nullptr;
_read();
}
void phoenix_vss2_t::vss2_store_body_t::_read() {
m_variables = std::unique_ptr<std::vector<std::unique_ptr<vss2_variable_t>>>(new std::vector<std::unique_ptr<vss2_variable_t>>());
{
int i = 0;
vss2_variable_t* _;
do {
_ = new vss2_variable_t(m__io, this, m__root);
m_variables->push_back(std::move(std::unique_ptr<vss2_variable_t>(_)));
i++;
} while (!( ((_->signature_first() != 170) || (_io()->is_eof())) ));
}
}
phoenix_vss2_t::vss2_store_body_t::~vss2_store_body_t() {
_clean_up();
}
void phoenix_vss2_t::vss2_store_body_t::_clean_up() {
}
phoenix_vss2_t::vss2_variable_attributes_t::vss2_variable_attributes_t(kaitai::kstream* p__io, phoenix_vss2_t::vss2_variable_t* p__parent, phoenix_vss2_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
_read();
}
void phoenix_vss2_t::vss2_variable_attributes_t::_read() {
m_non_volatile = m__io->read_bits_int_le(1);
m_boot_service = m__io->read_bits_int_le(1);
m_runtime = m__io->read_bits_int_le(1);
m_hw_error_record = m__io->read_bits_int_le(1);
m_auth_write = m__io->read_bits_int_le(1);
m_time_based_auth = m__io->read_bits_int_le(1);
m_append_write = m__io->read_bits_int_le(1);
m_reserved = m__io->read_bits_int_le(25);
}
phoenix_vss2_t::vss2_variable_attributes_t::~vss2_variable_attributes_t() {
_clean_up();
}
void phoenix_vss2_t::vss2_variable_attributes_t::_clean_up() {
}
phoenix_vss2_t::vss2_variable_t::vss2_variable_t(kaitai::kstream* p__io, phoenix_vss2_t::vss2_store_body_t* p__parent, phoenix_vss2_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_attributes = nullptr;
f_is_auth = false;
f_end_offset_auth = false;
f_len_alignment_padding = false;
f_end_offset = false;
f_len_alignment_padding_auth = false;
f_offset = false;
_read();
}
void phoenix_vss2_t::vss2_variable_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_last = true;
if (signature_first() == 170) {
n_signature_last = false;
m_signature_last = m__io->read_u1();
{
uint8_t _ = signature_last();
if (!(_ == 85)) {
throw kaitai::validation_expr_error<uint8_t>(signature_last(), _io(), std::string("/types/vss2_variable/seq/2"));
}
}
}
n_state = true;
if (signature_first() == 170) {
n_state = false;
m_state = m__io->read_u1();
}
n_reserved = true;
if (signature_first() == 170) {
n_reserved = false;
m_reserved = m__io->read_u1();
}
n_attributes = true;
if (signature_first() == 170) {
n_attributes = false;
m_attributes = std::unique_ptr<vss2_variable_attributes_t>(new vss2_variable_attributes_t(m__io, this, m__root));
}
n_len_name = true;
if (signature_first() == 170) {
n_len_name = false;
m_len_name = m__io->read_u4le();
}
n_len_data = true;
if (signature_first() == 170) {
n_len_data = false;
m_len_data = m__io->read_u4le();
}
n_timestamp = true;
if ( ((signature_first() == 170) && (is_auth())) ) {
n_timestamp = false;
m_timestamp = m__io->read_bytes(16);
}
n_pubkey_index = true;
if ( ((signature_first() == 170) && (is_auth())) ) {
n_pubkey_index = false;
m_pubkey_index = m__io->read_u4le();
}
n_len_name_auth = true;
if ( ((signature_first() == 170) && (is_auth())) ) {
n_len_name_auth = false;
m_len_name_auth = m__io->read_u4le();
}
n_len_data_auth = true;
if ( ((signature_first() == 170) && (is_auth())) ) {
n_len_data_auth = false;
m_len_data_auth = m__io->read_u4le();
}
n_vendor_guid = true;
if (signature_first() == 170) {
n_vendor_guid = false;
m_vendor_guid = m__io->read_bytes(16);
}
n_name_auth = true;
if ( ((signature_first() == 170) && (is_auth())) ) {
n_name_auth = false;
m_name_auth = m__io->read_bytes(len_name_auth());
}
n_data_auth = true;
if ( ((signature_first() == 170) && (is_auth())) ) {
n_data_auth = false;
m_data_auth = m__io->read_bytes(len_data_auth());
}
n_invoke_end_offset_auth = true;
if ( ((signature_first() == 170) && (is_auth()) && (end_offset_auth() >= 0)) ) {
n_invoke_end_offset_auth = false;
m_invoke_end_offset_auth = m__io->read_bytes(0);
}
n_alignment_padding_auth = true;
if ( ((signature_first() == 170) && (is_auth())) ) {
n_alignment_padding_auth = false;
m_alignment_padding_auth = m__io->read_bytes(len_alignment_padding_auth());
}
n_name = true;
if ( ((signature_first() == 170) && (!(is_auth()))) ) {
n_name = false;
m_name = m__io->read_bytes(len_name());
}
n_data = true;
if ( ((signature_first() == 170) && (!(is_auth()))) ) {
n_data = false;
m_data = m__io->read_bytes(len_data());
}
n_invoke_end_offset = true;
if ( ((signature_first() == 170) && (!(is_auth())) && (end_offset() >= 0)) ) {
n_invoke_end_offset = false;
m_invoke_end_offset = m__io->read_bytes(0);
}
n_alignment_padding = true;
if ( ((signature_first() == 170) && (!(is_auth()))) ) {
n_alignment_padding = false;
m_alignment_padding = m__io->read_bytes(len_alignment_padding());
}
}
phoenix_vss2_t::vss2_variable_t::~vss2_variable_t() {
_clean_up();
}
void phoenix_vss2_t::vss2_variable_t::_clean_up() {
if (!n_invoke_offset) {
}
if (!n_signature_last) {
}
if (!n_state) {
}
if (!n_reserved) {
}
if (!n_attributes) {
}
if (!n_len_name) {
}
if (!n_len_data) {
}
if (!n_timestamp) {
}
if (!n_pubkey_index) {
}
if (!n_len_name_auth) {
}
if (!n_len_data_auth) {
}
if (!n_vendor_guid) {
}
if (!n_name_auth) {
}
if (!n_data_auth) {
}
if (!n_invoke_end_offset_auth) {
}
if (!n_alignment_padding_auth) {
}
if (!n_name) {
}
if (!n_data) {
}
if (!n_invoke_end_offset) {
}
if (!n_alignment_padding) {
}
}
bool phoenix_vss2_t::vss2_variable_t::is_auth() {
if (f_is_auth)
return m_is_auth;
m_is_auth = (( ((attributes()->auth_write()) || (attributes()->time_based_auth()) || (attributes()->append_write())) ) || ( ((len_name() == 0) || (len_data() == 0)) )) ;
f_is_auth = true;
return m_is_auth;
}
int32_t phoenix_vss2_t::vss2_variable_t::end_offset_auth() {
if (f_end_offset_auth)
return m_end_offset_auth;
m_end_offset_auth = _io()->pos();
f_end_offset_auth = true;
return m_end_offset_auth;
}
int32_t phoenix_vss2_t::vss2_variable_t::len_alignment_padding() {
if (f_len_alignment_padding)
return m_len_alignment_padding;
m_len_alignment_padding = ((((end_offset() - offset()) + 3) & ~3) - (end_offset() - offset()));
f_len_alignment_padding = true;
return m_len_alignment_padding;
}
int32_t phoenix_vss2_t::vss2_variable_t::end_offset() {
if (f_end_offset)
return m_end_offset;
m_end_offset = _io()->pos();
f_end_offset = true;
return m_end_offset;
}
int32_t phoenix_vss2_t::vss2_variable_t::len_alignment_padding_auth() {
if (f_len_alignment_padding_auth)
return m_len_alignment_padding_auth;
m_len_alignment_padding_auth = ((((end_offset_auth() - offset()) + 3) & ~3) - (end_offset() - offset()));
f_len_alignment_padding_auth = true;
return m_len_alignment_padding_auth;
}
int32_t phoenix_vss2_t::vss2_variable_t::offset() {
if (f_offset)
return m_offset;
m_offset = _io()->pos();
f_offset = true;
return m_offset;
}
int32_t phoenix_vss2_t::header_size() {
if (f_header_size)
return m_header_size;
m_header_size = (7 * 4);
f_header_size = true;
return m_header_size;
}

View file

@ -0,0 +1,366 @@
#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 phoenix_vss2_t : public kaitai::kstruct {
public:
class vss2_store_body_t;
class vss2_variable_attributes_t;
class vss2_variable_t;
phoenix_vss2_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = nullptr, phoenix_vss2_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~phoenix_vss2_t();
class vss2_store_body_t : public kaitai::kstruct {
public:
vss2_store_body_t(kaitai::kstream* p__io, phoenix_vss2_t* p__parent = nullptr, phoenix_vss2_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~vss2_store_body_t();
private:
std::unique_ptr<std::vector<std::unique_ptr<vss2_variable_t>>> m_variables;
phoenix_vss2_t* m__root;
phoenix_vss2_t* m__parent;
public:
std::vector<std::unique_ptr<vss2_variable_t>>* variables() const { return m_variables.get(); }
phoenix_vss2_t* _root() const { return m__root; }
phoenix_vss2_t* _parent() const { return m__parent; }
};
class vss2_variable_attributes_t : public kaitai::kstruct {
public:
vss2_variable_attributes_t(kaitai::kstream* p__io, phoenix_vss2_t::vss2_variable_t* p__parent = nullptr, phoenix_vss2_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~vss2_variable_attributes_t();
private:
bool m_non_volatile;
bool m_boot_service;
bool m_runtime;
bool m_hw_error_record;
bool m_auth_write;
bool m_time_based_auth;
bool m_append_write;
uint64_t m_reserved;
phoenix_vss2_t* m__root;
phoenix_vss2_t::vss2_variable_t* m__parent;
public:
bool non_volatile() const { return m_non_volatile; }
bool boot_service() const { return m_boot_service; }
bool runtime() const { return m_runtime; }
bool hw_error_record() const { return m_hw_error_record; }
bool auth_write() const { return m_auth_write; }
bool time_based_auth() const { return m_time_based_auth; }
bool append_write() const { return m_append_write; }
uint64_t reserved() const { return m_reserved; }
phoenix_vss2_t* _root() const { return m__root; }
phoenix_vss2_t::vss2_variable_t* _parent() const { return m__parent; }
};
class vss2_variable_t : public kaitai::kstruct {
public:
vss2_variable_t(kaitai::kstream* p__io, phoenix_vss2_t::vss2_store_body_t* p__parent = nullptr, phoenix_vss2_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~vss2_variable_t();
private:
bool f_is_auth;
bool m_is_auth;
public:
bool is_auth();
private:
bool f_end_offset_auth;
int32_t m_end_offset_auth;
public:
int32_t end_offset_auth();
private:
bool f_len_alignment_padding;
int32_t m_len_alignment_padding;
public:
int32_t len_alignment_padding();
private:
bool f_end_offset;
int32_t m_end_offset;
public:
int32_t end_offset();
private:
bool f_len_alignment_padding_auth;
int32_t m_len_alignment_padding_auth;
public:
int32_t len_alignment_padding_auth();
private:
bool f_offset;
int32_t m_offset;
public:
int32_t 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;
uint8_t m_signature_last;
bool n_signature_last;
public:
bool _is_null_signature_last() { signature_last(); return n_signature_last; };
private:
uint8_t m_state;
bool n_state;
public:
bool _is_null_state() { state(); return n_state; };
private:
uint8_t m_reserved;
bool n_reserved;
public:
bool _is_null_reserved() { reserved(); return n_reserved; };
private:
std::unique_ptr<vss2_variable_attributes_t> m_attributes;
bool n_attributes;
public:
bool _is_null_attributes() { attributes(); return n_attributes; };
private:
uint32_t m_len_name;
bool n_len_name;
public:
bool _is_null_len_name() { len_name(); return n_len_name; };
private:
uint32_t m_len_data;
bool n_len_data;
public:
bool _is_null_len_data() { len_data(); return n_len_data; };
private:
std::string m_timestamp;
bool n_timestamp;
public:
bool _is_null_timestamp() { timestamp(); return n_timestamp; };
private:
uint32_t m_pubkey_index;
bool n_pubkey_index;
public:
bool _is_null_pubkey_index() { pubkey_index(); return n_pubkey_index; };
private:
uint32_t m_len_name_auth;
bool n_len_name_auth;
public:
bool _is_null_len_name_auth() { len_name_auth(); return n_len_name_auth; };
private:
uint32_t m_len_data_auth;
bool n_len_data_auth;
public:
bool _is_null_len_data_auth() { len_data_auth(); return n_len_data_auth; };
private:
std::string m_vendor_guid;
bool n_vendor_guid;
public:
bool _is_null_vendor_guid() { vendor_guid(); return n_vendor_guid; };
private:
std::string m_name_auth;
bool n_name_auth;
public:
bool _is_null_name_auth() { name_auth(); return n_name_auth; };
private:
std::string m_data_auth;
bool n_data_auth;
public:
bool _is_null_data_auth() { data_auth(); return n_data_auth; };
private:
std::string m_invoke_end_offset_auth;
bool n_invoke_end_offset_auth;
public:
bool _is_null_invoke_end_offset_auth() { invoke_end_offset_auth(); return n_invoke_end_offset_auth; };
private:
std::string m_alignment_padding_auth;
bool n_alignment_padding_auth;
public:
bool _is_null_alignment_padding_auth() { alignment_padding_auth(); return n_alignment_padding_auth; };
private:
std::string m_name;
bool n_name;
public:
bool _is_null_name() { name(); return n_name; };
private:
std::string m_data;
bool n_data;
public:
bool _is_null_data() { data(); return n_data; };
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:
std::string m_alignment_padding;
bool n_alignment_padding;
public:
bool _is_null_alignment_padding() { alignment_padding(); return n_alignment_padding; };
private:
phoenix_vss2_t* m__root;
phoenix_vss2_t::vss2_store_body_t* m__parent;
public:
std::string invoke_offset() const { return m_invoke_offset; }
uint8_t signature_first() const { return m_signature_first; }
uint8_t signature_last() const { return m_signature_last; }
uint8_t state() const { return m_state; }
uint8_t reserved() const { return m_reserved; }
vss2_variable_attributes_t* attributes() const { return m_attributes.get(); }
uint32_t len_name() const { return m_len_name; }
uint32_t len_data() const { return m_len_data; }
std::string timestamp() const { return m_timestamp; }
uint32_t pubkey_index() const { return m_pubkey_index; }
uint32_t len_name_auth() const { return m_len_name_auth; }
uint32_t len_data_auth() const { return m_len_data_auth; }
std::string vendor_guid() const { return m_vendor_guid; }
std::string name_auth() const { return m_name_auth; }
std::string data_auth() const { return m_data_auth; }
std::string invoke_end_offset_auth() const { return m_invoke_end_offset_auth; }
std::string alignment_padding_auth() const { return m_alignment_padding_auth; }
std::string name() const { return m_name; }
std::string data() const { return m_data; }
std::string invoke_end_offset() const { return m_invoke_end_offset; }
std::string alignment_padding() const { return m_alignment_padding; }
phoenix_vss2_t* _root() const { return m__root; }
phoenix_vss2_t::vss2_store_body_t* _parent() const { return m__parent; }
};
private:
bool f_header_size;
int32_t m_header_size;
public:
int32_t header_size();
private:
uint32_t m_signature;
std::string m_signature_auth_var_key_db;
bool n_signature_auth_var_key_db;
public:
bool _is_null_signature_auth_var_key_db() { signature_auth_var_key_db(); return n_signature_auth_var_key_db; };
private:
std::string m_signature_vss2_store;
bool n_signature_vss2_store;
public:
bool _is_null_signature_vss2_store() { signature_vss2_store(); return n_signature_vss2_store; };
private:
uint32_t m_vss2_size;
uint8_t m_format;
uint8_t m_state;
uint16_t m_reserved;
uint32_t m_reserved1;
std::unique_ptr<vss2_store_body_t> m_body;
phoenix_vss2_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; }
std::string signature_auth_var_key_db() const { return m_signature_auth_var_key_db; }
std::string signature_vss2_store() const { return m_signature_vss2_store; }
uint32_t vss2_size() const { return m_vss2_size; }
uint8_t format() const { return m_format; }
uint8_t state() const { return m_state; }
uint16_t reserved() const { return m_reserved; }
uint32_t reserved1() const { return m_reserved1; }
vss2_store_body_t* body() const { return m_body.get(); }
phoenix_vss2_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(); }
};

View file

@ -1,6 +1,6 @@
meta:
id: edk2_vss
title: EDK2 VSS storage
title: EDK2 VSS NVRAM store
application: EDK2-based UEFI firmware
file-extension: vss
tags:
@ -14,10 +14,10 @@ seq:
type: u4
valid:
expr: _ == 0x53535624 or _ == 0x53565324 or _ == 0x53534E24 # $VSS/$SVS/$NSS
- id: size
- id: vss_size
type: u4
valid:
expr: _ > 4 * sizeof<u4>
expr: _ > len_vss_store_header and _ < 0xFFFFFFFF
- id: format
type: u1
valid:
@ -30,7 +30,10 @@ seq:
type: u4
- id: body
type: vss_store_body
size: size - 4 * sizeof<u4>
size: vss_size - len_vss_store_header
instances:
len_vss_store_header:
value: 16
types:
vss_store_body:
@ -79,22 +82,81 @@ types:
- id: attributes
type: vss_variable_attributes
if: signature_first == 0xAA
#TODO: add Intel legacy total_size variant
# vvv Intel legacy
- id: len_total
type: u4
if: signature_first == 0xAA and is_intel_legacy
valid:
expr: _ >= len_intel_legacy_header + 4 + 1 # Header size + at least one UCS2 character for the name + UCS2 null terminator + at least one byte of data
# ^^^ Intel legacy
# Next 2 fields can be of any value for an authenticated variable due to them being a combined value of MonothonicCounter
- id: len_name
type: u4
if: signature_first == 0xAA
if: signature_first == 0xAA and not is_intel_legacy
- id: len_data
type: u4
if: signature_first == 0xAA
if: signature_first == 0xAA and not is_intel_legacy
# vvv Auth variable
- id: timestamp
size: 16
if: signature_first == 0xAA and is_auth
- id: pubkey_index
type: u4
if: signature_first == 0xAA and is_auth
- id: len_name_auth
type: u4
if: signature_first == 0xAA and is_auth
valid:
expr: (_ >= 4) and (_ % 2 == 0) # UCS2 characters come in byte pairs
- id: len_data_auth
type: u4
if: signature_first == 0xAA and is_auth
valid:
expr: _ > 0
# ^^^ Auth variable
- id: vendor_guid
size: 16
if: signature_first == 0xAA
# vvv Auth variable
- id: name_auth
size: len_name_auth
if: signature_first == 0xAA and is_auth
- id: data_auth
size: len_data_auth
if: signature_first == 0xAA and is_auth
# ^^^ Auth variable
# vvv Apple MacEFI
- id: apple_data_crc32
type: u4
if: signature_first == 0xAA and attributes.apple_data_checksum
if: signature_first == 0xAA and not is_intel_legacy and not is_auth and attributes.apple_data_checksum
# ^^^ Apple MacEFI
# vvv Intel legacy
- id: intel_legacy_data
size: len_total - len_intel_legacy_header
if: signature_first == 0xAA and is_intel_legacy
# ^^^ Intel legacy
- id: name
size: len_name
if: signature_first == 0xAA
if: signature_first == 0xAA and not is_intel_legacy and not is_auth
valid:
expr: (len_name >= 4) and (len_name % 2 == 0)
- id: data
size: len_data
if: signature_first == 0xAA
if: signature_first == 0xAA and not is_intel_legacy and not is_auth
valid:
expr: len_name > 0
instances:
is_valid:
value: state == 0xFC or state == 0x7F or state == 0x3F
is_intel_legacy:
value: (state == 0xF8 or state == 0xFC) # Special states indicating Intel legacy variables
is_auth:
value: state != 0xF8 and state != 0xFC and ((attributes.auth_write or attributes.time_based_auth or attributes.append_write) or (len_name == 0 or len_data == 0))
len_intel_legacy_header:
value: 28
len_auth_header:
value: 60
len_standard_header:
value: 32
len_apple_header:
value: 36

154
common/ksy/phoenix_vss2.ksy Normal file
View file

@ -0,0 +1,154 @@
meta:
id: phoenix_vss2
title: Phoenix VSS2 NVRAM variable storage
application: Phoenix SCT-based UEFI firmware
file-extension: vss2
tags:
- firmware
license: CC0-1.0
ks-version: 0.9
endian: le
seq:
- id: signature
type: u4
valid:
expr: _ == 0xDDCF3617 or _ == 0xAAF32C78 # Beginning of known store GUIDs for VSS2
- id: signature_auth_var_key_db
contents: [0x7B, 0x94, 0x9A, 0x43, 0xA1, 0x80, 0x2E, 0x14, 0x4E, 0xC3, 0x77, 0x92] # AAF32C78-947B-439A-A180-2E144EC37792
if: signature == 0xAAF32C78
- id: signature_vss2_store
contents: [0x75, 0x32, 0x64, 0x41, 0x98, 0xB6, 0xFE, 0x85, 0x70, 0x7F, 0xFE, 0x7D] # DDCF3617-3275-4164-98B6-FE85707FFE7D
if: signature == 0xDDCF3617
- id: vss2_size
type: u4
valid:
expr: _ > header_size and _ < 0xFFFFFFFF
- id: format
type: u1
valid:
expr: _ == 0x5a # Formatted
- id: state
type: u1
- id: reserved
type: u2
- id: reserved1
type: u4
- id: body
type: vss2_store_body
size: vss2_size - header_size
instances:
header_size:
value: 7 * sizeof<u4>
types:
vss2_store_body:
seq:
- id: variables
type: vss2_variable
repeat: until
repeat-until: _.signature_first != 0xAA or _io.eof
vss2_variable_attributes:
seq:
- id: non_volatile
type: b1le
- id: boot_service
type: b1le
- id: runtime
type: b1le
- id: hw_error_record
type: b1le
- id: auth_write
type: b1le
- id: time_based_auth
type: b1le
- id: append_write
type: b1le
- id: reserved
type: b25le
# TODO: check if VSS2 stores can have standard VSS variables
vss2_variable:
seq:
- id: invoke_offset
size: 0
if: offset >= 0
- id: signature_first
type: u1
- id: signature_last
type: u1
valid:
expr: _ == 0x55
if: signature_first == 0xAA
- id: state
type: u1
if: signature_first == 0xAA
- id: reserved
type: u1
if: signature_first == 0xAA
- id: attributes
type: vss2_variable_attributes
if: signature_first == 0xAA
- id: len_name
type: u4
if: signature_first == 0xAA
- id: len_data
type: u4
if: signature_first == 0xAA
# vvv Auth variable
- id: timestamp
size: 16
if: signature_first == 0xAA and is_auth
- id: pubkey_index
type: u4
if: signature_first == 0xAA and is_auth
- id: len_name_auth
type: u4
if: signature_first == 0xAA and is_auth
- id: len_data_auth
type: u4
if: signature_first == 0xAA and is_auth
# ^^^ Auth variable
- id: vendor_guid
size: 16
if: signature_first == 0xAA
# vvv Auth variable
- id: name_auth
size: len_name_auth
if: signature_first == 0xAA and is_auth
- id: data_auth
size: len_data_auth
if: signature_first == 0xAA and is_auth
- id: invoke_end_offset_auth
size: 0
if: signature_first == 0xAA and is_auth and end_offset_auth >= 0
- id: alignment_padding_auth
size: len_alignment_padding_auth
if: signature_first == 0xAA and is_auth
# ^^^ Auth variable
- id: name
size: len_name
if: signature_first == 0xAA and not is_auth
- id: data
size: len_data
if: signature_first == 0xAA and not is_auth
- id: invoke_end_offset
size: 0
if: signature_first == 0xAA and not is_auth and end_offset >= 0
- id: alignment_padding
size: len_alignment_padding
if: signature_first == 0xAA and not is_auth
instances:
offset:
value: _io.pos
end_offset:
value: _io.pos
end_offset_auth:
value: _io.pos
len_alignment_padding:
value: (((end_offset - offset)+3) & ~3) - (end_offset - offset)
len_alignment_padding_auth:
value: (((end_offset_auth - offset)+3) & ~3) - (end_offset - offset)
is_auth:
value: (attributes.auth_write or attributes.time_based_auth or attributes.append_write) or (len_name == 0 or len_data == 0)

View file

@ -27,6 +27,7 @@
#include "kaitai/kaitaistream.h"
#include "generated/ami_nvar.h"
#include "generated/edk2_vss.h"
#include "generated/phoenix_vss2.h"
USTATUS NvramParser::parseNvarStore(const UModelIndex & index)
{
@ -304,35 +305,206 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index)
const UINT32 volumeBodySize = (UINT32)volumeBody.size();
// Iterate over all bytes inside the volume body, trying to parse every next byte offset by one of the known parsers
UByteArray padding;
for (UINT32 offset = 0;
offset < volumeBodySize;
offset++) {
UByteArray outerPadding;
UINT32 previousStoreEndOffset = 0;
for (UINT32 storeOffset = 0;
storeOffset < volumeBodySize;
storeOffset++) {
bool storeFound = false;
// Try parsing as VSS store
try {
UByteArray vss = volumeBody.mid(offset);
UByteArray vss = volumeBody.mid(storeOffset);
umemstream is(vss.constData(), vss.size());
kaitai::kstream ks(&is);
edk2_vss_t parsed(&ks);
// VSS store at current offset parsed correctly
msg(usprintf("%s: VSS store found at offset: %Xh, paddingSize: %Xh", __FUNCTION__, localOffset + offset, (UINT32)padding.size()), index);
// 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 = vss.left(parsed.len_vss_store_header());
UByteArray body = vss.mid(header.size(), parsed.vss_size() - header.size());
// Add info
UString name;
if (parsed.signature() == NVRAM_APPLE_SVS_STORE_SIGNATURE) {
name = UString("SVS store");
}
else if (parsed.signature() == NVRAM_APPLE_NSS_STORE_SIGNATURE) {
name = UString("NSS store");
}
else {
name = UString("VSS store");
}
UString info = usprintf("Signature: %Xh (", parsed.signature()) + fourCC(parsed.signature()) + UString(")\n");
info += usprintf("Full size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nFormat: %02Xh\nState: %02Xh\nReserved: %02Xh\nReserved1: %04Xh",
parsed.vss_size() , parsed.vss_size(),
(UINT32)header.size(), (UINT32)header.size(),
(UINT32)body.size(), (UINT32)body.size(),
parsed.format(),
parsed.state(),
parsed.reserved(),
parsed.reserved1());
// Add header tree item
UModelIndex headerIndex = model->addItem(localOffset + storeOffset, Types::VssStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, index);
UINT32 vssVariableOffset = storeOffset + parsed.len_vss_store_header();
for (const auto & variable : *parsed.body()->variables()) {
UINT8 subtype;
UString text;
info.clear();
name.clear();
// This is thew terminating entry, needs special processing
if (variable->_is_null_signature_last()) {
// Add free space or padding after all variables, if needed
if (vssVariableOffset < parsed.vss_size()) {
UByteArray freeSpace = vss.mid(vssVariableOffset, parsed.vss_size() - vssVariableOffset);
// Add info
info = usprintf("Full size: %Xh (%u)", (UINT32)freeSpace.size(), (UINT32)freeSpace.size());
// Check that remaining unparsed bytes are actually empty
if (freeSpace.count(emptyByte) == freeSpace.size()) { // Free space
// Add tree item
model->addItem(vssVariableOffset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), freeSpace, UByteArray(), Fixed, headerIndex);
}
else {
// Add tree item
model->addItem(vssVariableOffset, Types::Padding, getPaddingType(freeSpace), UString("Padding"), UString(), info, UByteArray(), freeSpace, UByteArray(), Fixed, headerIndex);
}
}
break;
}
// This is a normal entry
UINT32 variableSize;
if (variable->is_intel_legacy()) {
subtype = Subtypes::IntelVssEntry;
// Needs some additional parsing of variable->intel_legacy_data to separate the name from the value
text = uFromUcs2(variable->intel_legacy_data().c_str());
UINT32 textLengthInBytes = (UINT32)text.length()*2+2;
header = vss.mid(vssVariableOffset, variable->len_intel_legacy_header() + textLengthInBytes);
body = vss.mid(vssVariableOffset + header.size(), variable->len_total() - variable->len_intel_legacy_header() - textLengthInBytes);
variableSize = (UINT32)(header.size() + body.size());
const EFI_GUID variableGuid = readUnaligned((const EFI_GUID*)(variable->vendor_guid().c_str()));
name = guidToUString(variableGuid);
info += UString("Variable GUID: ") + guidToUString(variableGuid, false) + "\n";
}
else if (variable->is_auth()) {
subtype = Subtypes::AuthVssEntry;
header = vss.mid(vssVariableOffset, variable->len_auth_header() + variable->len_name_auth());
body = vss.mid(vssVariableOffset + header.size(), variable->len_data_auth());
variableSize = (UINT32)(header.size() + body.size());
const EFI_GUID variableGuid = readUnaligned((const EFI_GUID*)(variable->vendor_guid().c_str()));
name = guidToUString(variableGuid);
text = uFromUcs2(variable->name_auth().c_str());
info += UString("Variable GUID: ") + guidToUString(variableGuid, false) + "\n";
}
else if (!variable->_is_null_apple_data_crc32()) {
subtype = Subtypes::AppleVssEntry;
header = vss.mid(vssVariableOffset, variable->len_apple_header() + variable->len_name());
body = vss.mid(vssVariableOffset + header.size(), variable->len_data());
variableSize = (UINT32)(header.size() + body.size());
const EFI_GUID variableGuid = readUnaligned((const EFI_GUID*)(variable->vendor_guid().c_str()));
name = guidToUString(variableGuid);
text = uFromUcs2(variable->name().c_str());
info += UString("Variable GUID: ") + guidToUString(variableGuid, false) + "\n";
}
else {
subtype = Subtypes::StandardVssEntry;
header = vss.mid(vssVariableOffset, variable->len_standard_header() + variable->len_name());
body = vss.mid(vssVariableOffset + header.size(), variable->len_data());
variableSize = (UINT32)(header.size() + body.size());
const EFI_GUID variableGuid = readUnaligned((const EFI_GUID*)(variable->vendor_guid().c_str()));
name = guidToUString(variableGuid);
text = uFromUcs2(variable->name().c_str());
info += UString("Variable GUID: ") + guidToUString(variableGuid, false) + "\n";
}
// Override variable type to Invalid if needed
if (!variable->is_valid()) {
subtype = Subtypes::InvalidVssEntry;
name = UString("Invalid");
text.clear();
}
const UINT32 variableAttributes = variable->attributes()->non_volatile()
+ (variable->attributes()->boot_service() << 1)
+ (variable->attributes()->runtime() << 2)
+ (variable->attributes()->hw_error_record() << 3)
+ (variable->attributes()->auth_write() << 4)
+ (variable->attributes()->time_based_auth() << 5)
+ (variable->attributes()->append_write() << 6)
+ (variable->attributes()->apple_data_checksum() << 31);
// Add generic info
info += usprintf("Full size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nState: %02Xh\nReserved: %02X\nAttributes: %08Xh (",
variableSize, variableSize,
(UINT32)header.size(), (UINT32)header.size(),
(UINT32)body.size(), (UINT32)body.size(),
variable->state(),
variable->reserved(),
variableAttributes) + vssAttributesToUString(variableAttributes) + UString(")");
// Add specific info
if (variable->is_auth()) {
UINT64 monotonicCounter = (UINT64)variable->len_name() + ((UINT64)variable->len_data() << 32);
info += usprintf("\nMonotonic counter: %" PRIX64 "h\nTimestamp: ", monotonicCounter) + efiTimeToUString(*(const EFI_TIME*)variable->timestamp().c_str())
+ usprintf("\nPubKey index: %u", variable->pubkey_index());
}
else if (!variable->_is_null_apple_data_crc32()) {
// Calculate CRC32 of the variable data
UINT32 calculatedCrc32 = (UINT32)crc32(0, (const UINT8*)body.constData(), (uInt)body.size());
info += usprintf("\nData checksum: %08Xh", variable->apple_data_crc32()) +
(variable->apple_data_crc32() != calculatedCrc32 ? usprintf(", invalid, should be %08Xh", calculatedCrc32) : UString(", valid"));
}
// Add tree item
model->addItem(vssVariableOffset, Types::VssEntry, subtype, name, text, info, header, body, UByteArray(), Fixed, headerIndex);
vssVariableOffset += variableSize;
}
storeFound = true;
padding.clear();
offset += parsed.size() - 1;
storeOffset += parsed.vss_size();
previousStoreEndOffset = storeOffset;
} catch (...) {
// Parsing failed try something else
// Parsing failed, try something else
}
//TODO: all other kinds of stores
// if (!storeFound && ...)
// VSS2
// This byte had not been parsed as anything
if (!storeFound)
padding += volumeBody.at(offset);
// FDC
// EVSA
// FTW
// Apple Fsys/Gaid
// Phoenix FlashMap
// Phoenix CMDB
// Phoenix SLIC Pubkey/Marker
// Intel uCode
// Padding
outerPadding += volumeBody.at(storeOffset);
}
// Add padding at the very end
if (!outerPadding.isEmpty()) {
// Add info
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);
}
return U_SUCCESS;

View file

@ -369,8 +369,6 @@ USTATUS decompress(const UByteArray & compressedData, const UINT8 compressionTyp
}
}
// 8bit sum calculation routine
UINT8 calculateSum8(const UINT8* buffer, UINT32 bufferSize)
{
@ -573,3 +571,12 @@ USTATUS zlibDecompress(const UByteArray& input, UByteArray& output)
inflateEnd(&stream);
return ret == Z_STREAM_END ? U_SUCCESS : U_ZLIB_DECOMPRESSION_FAILED;
}
UString fourCC(const UINT32 value)
{
const UINT8 byte0 = (const UINT8)(value & 0xFF);
const UINT8 byte1 = (const UINT8)((value & 0xFF00) >> 8);
const UINT8 byte2 = (const UINT8)((value & 0xFF0000) >> 16);
const UINT8 byte3 = (const UINT8)((value & 0xFF000000) >> 24);
return usprintf("%c%c%c%c", byte0, byte1, byte2, byte3);
}

View file

@ -23,6 +23,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "treemodel.h"
#include "parsingdata.h"
// Returns text representation of 4CC value
UString fourCC(const UINT32 value);
// Returns bytes as string when all bytes are ascii visible, hex representation otherwise
UString visibleAsciiOrHex(UINT8* bytes, UINT32 length);