diff --git a/UEFIExtract/CMakeLists.txt b/UEFIExtract/CMakeLists.txt index 933300e..2cf3c63 100644 --- a/UEFIExtract/CMakeLists.txt +++ b/UEFIExtract/CMakeLists.txt @@ -35,6 +35,9 @@ SET(PROJECT_SOURCES ../common/bstrlib/bstrlib.c ../common/bstrlib/bstrwrap.cpp ../common/generated/ami_nvar.cpp + ../common/generated/edk2_vss.cpp + ../common/generated/edk2_vss2.cpp + ../common/generated/insyde_fdc.cpp ../common/generated/intel_acbp_v1.cpp ../common/generated/intel_acbp_v2.cpp ../common/generated/intel_keym_v1.cpp diff --git a/UEFIFind/CMakeLists.txt b/UEFIFind/CMakeLists.txt index 4ba4a19..c626d47 100644 --- a/UEFIFind/CMakeLists.txt +++ b/UEFIFind/CMakeLists.txt @@ -32,6 +32,9 @@ SET(PROJECT_SOURCES ../common/bstrlib/bstrlib.c ../common/bstrlib/bstrwrap.cpp ../common/generated/ami_nvar.cpp + ../common/generated/edk2_vss.cpp + ../common/generated/edk2_vss2.cpp + ../common/generated/insyde_fdc.cpp ../common/generated/intel_acbp_v1.cpp ../common/generated/intel_acbp_v2.cpp ../common/generated/intel_keym_v1.cpp diff --git a/UEFITool/CMakeLists.txt b/UEFITool/CMakeLists.txt index 29b3371..b38a1b3 100644 --- a/UEFITool/CMakeLists.txt +++ b/UEFITool/CMakeLists.txt @@ -69,7 +69,8 @@ SET(PROJECT_SOURCES ../common/digest/sm3.c ../common/generated/ami_nvar.cpp ../common/generated/edk2_vss.cpp - ../common/generated/phoenix_vss2.cpp + ../common/generated/edk2_vss2.cpp + ../common/generated/insyde_fdc.cpp ../common/generated/intel_acbp_v1.cpp ../common/generated/intel_acbp_v2.cpp ../common/generated/intel_keym_v1.cpp diff --git a/common/generated/phoenix_vss2.cpp b/common/generated/edk2_vss2.cpp similarity index 80% rename from common/generated/phoenix_vss2.cpp rename to common/generated/edk2_vss2.cpp index 45ec1b1..848d472 100644 --- a/common/generated/phoenix_vss2.cpp +++ b/common/generated/edk2_vss2.cpp @@ -1,9 +1,9 @@ // This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild -#include "phoenix_vss2.h" +#include "edk2_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) { +edk2_vss2_t::edk2_vss2_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, edk2_vss2_t* p__root) : kaitai::kstruct(p__io) { m__parent = p__parent; m__root = this; (void)p__root; m_body = nullptr; @@ -12,11 +12,11 @@ phoenix_vss2_t::phoenix_vss2_t(kaitai::kstream* p__io, kaitai::kstruct* p__paren _read(); } -void phoenix_vss2_t::_read() { +void edk2_vss2_t::_read() { m_signature = m__io->read_u4le(); { uint32_t _ = signature(); - if (!( ((_ == 3721344535UL) || (_ == 2868063352UL)) )) { + if (!( ((_ == 3721344534UL) || (_ == 3721344535UL) || (_ == 2868063352UL)) )) { throw kaitai::validation_expr_error(signature(), _io(), std::string("/seq/0")); } } @@ -36,18 +36,26 @@ void phoenix_vss2_t::_read() { throw kaitai::validation_not_equal_error(std::string("\x75\x32\x64\x41\x98\xB6\xFE\x85\x70\x7F\xFE\x7D", 12), signature_vss2_store(), _io(), std::string("/seq/2")); } } + n_signature_fdc_store = true; + if (signature() == 3721344534UL) { + n_signature_fdc_store = false; + m_signature_fdc_store = m__io->read_bytes(12); + if (!(signature_fdc_store() == std::string("\x75\x32\x64\x41\x98\xB6\xFE\x85\x70\x7F\xFE\x7D", 12))) { + throw kaitai::validation_not_equal_error(std::string("\x75\x32\x64\x41\x98\xB6\xFE\x85\x70\x7F\xFE\x7D", 12), signature_fdc_store(), _io(), std::string("/seq/3")); + } + } m_vss2_size = m__io->read_u4le(); { uint32_t _ = vss2_size(); if (!( ((_ > len_vss2_store_header()) && (_ < 4294967295UL)) )) { - throw kaitai::validation_expr_error(vss2_size(), _io(), std::string("/seq/3")); + throw kaitai::validation_expr_error(vss2_size(), _io(), std::string("/seq/4")); } } m_format = m__io->read_u1(); { uint8_t _ = format(); if (!(_ == 90)) { - throw kaitai::validation_expr_error(format(), _io(), std::string("/seq/4")); + throw kaitai::validation_expr_error(format(), _io(), std::string("/seq/5")); } } m_state = m__io->read_u1(); @@ -58,25 +66,27 @@ void phoenix_vss2_t::_read() { m_body = std::unique_ptr(new vss2_store_body_t(m__io__raw_body.get(), this, m__root)); } -phoenix_vss2_t::~phoenix_vss2_t() { +edk2_vss2_t::~edk2_vss2_t() { _clean_up(); } -void phoenix_vss2_t::_clean_up() { +void edk2_vss2_t::_clean_up() { if (!n_signature_auth_var_key_db) { } if (!n_signature_vss2_store) { } + if (!n_signature_fdc_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) { +edk2_vss2_t::vss2_store_body_t::vss2_store_body_t(kaitai::kstream* p__io, edk2_vss2_t* p__parent, edk2_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() { +void edk2_vss2_t::vss2_store_body_t::_read() { m_variables = std::unique_ptr>>(new std::vector>()); { int i = 0; @@ -89,20 +99,20 @@ void phoenix_vss2_t::vss2_store_body_t::_read() { } } -phoenix_vss2_t::vss2_store_body_t::~vss2_store_body_t() { +edk2_vss2_t::vss2_store_body_t::~vss2_store_body_t() { _clean_up(); } -void phoenix_vss2_t::vss2_store_body_t::_clean_up() { +void edk2_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) { +edk2_vss2_t::vss2_variable_attributes_t::vss2_variable_attributes_t(kaitai::kstream* p__io, edk2_vss2_t::vss2_variable_t* p__parent, edk2_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() { +void edk2_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); @@ -113,14 +123,14 @@ void phoenix_vss2_t::vss2_variable_attributes_t::_read() { m_reserved = m__io->read_bits_int_le(25); } -phoenix_vss2_t::vss2_variable_attributes_t::~vss2_variable_attributes_t() { +edk2_vss2_t::vss2_variable_attributes_t::~vss2_variable_attributes_t() { _clean_up(); } -void phoenix_vss2_t::vss2_variable_attributes_t::_clean_up() { +void edk2_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) { +edk2_vss2_t::vss2_variable_t::vss2_variable_t(kaitai::kstream* p__io, edk2_vss2_t::vss2_store_body_t* p__parent, edk2_vss2_t* p__root) : kaitai::kstruct(p__io) { m__parent = p__parent; m__root = p__root; m_attributes = nullptr; @@ -136,7 +146,7 @@ phoenix_vss2_t::vss2_variable_t::vss2_variable_t(kaitai::kstream* p__io, phoenix _read(); } -void phoenix_vss2_t::vss2_variable_t::_read() { +void edk2_vss2_t::vss2_variable_t::_read() { n_invoke_offset = true; if (offset() >= 0) { n_invoke_offset = false; @@ -246,11 +256,11 @@ void phoenix_vss2_t::vss2_variable_t::_read() { } } -phoenix_vss2_t::vss2_variable_t::~vss2_variable_t() { +edk2_vss2_t::vss2_variable_t::~vss2_variable_t() { _clean_up(); } -void phoenix_vss2_t::vss2_variable_t::_clean_up() { +void edk2_vss2_t::vss2_variable_t::_clean_up() { if (!n_invoke_offset) { } if (!n_signature_last) { @@ -293,7 +303,7 @@ void phoenix_vss2_t::vss2_variable_t::_clean_up() { } } -bool phoenix_vss2_t::vss2_variable_t::is_auth() { +bool edk2_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)) )) ; @@ -301,7 +311,7 @@ bool phoenix_vss2_t::vss2_variable_t::is_auth() { return m_is_auth; } -int8_t phoenix_vss2_t::vss2_variable_t::len_standard_header() { +int8_t edk2_vss2_t::vss2_variable_t::len_standard_header() { if (f_len_standard_header) return m_len_standard_header; m_len_standard_header = 32; @@ -309,7 +319,7 @@ int8_t phoenix_vss2_t::vss2_variable_t::len_standard_header() { return m_len_standard_header; } -int32_t phoenix_vss2_t::vss2_variable_t::end_offset_auth() { +int32_t edk2_vss2_t::vss2_variable_t::end_offset_auth() { if (f_end_offset_auth) return m_end_offset_auth; m_end_offset_auth = (int32_t)_io()->pos(); @@ -317,7 +327,7 @@ int32_t phoenix_vss2_t::vss2_variable_t::end_offset_auth() { return m_end_offset_auth; } -int32_t phoenix_vss2_t::vss2_variable_t::len_alignment_padding() { +int32_t edk2_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())); @@ -325,7 +335,7 @@ int32_t phoenix_vss2_t::vss2_variable_t::len_alignment_padding() { return m_len_alignment_padding; } -int8_t phoenix_vss2_t::vss2_variable_t::len_auth_header() { +int8_t edk2_vss2_t::vss2_variable_t::len_auth_header() { if (f_len_auth_header) return m_len_auth_header; m_len_auth_header = 60; @@ -333,7 +343,7 @@ int8_t phoenix_vss2_t::vss2_variable_t::len_auth_header() { return m_len_auth_header; } -int32_t phoenix_vss2_t::vss2_variable_t::end_offset() { +int32_t edk2_vss2_t::vss2_variable_t::end_offset() { if (f_end_offset) return m_end_offset; m_end_offset = (int32_t)_io()->pos(); @@ -341,7 +351,7 @@ int32_t phoenix_vss2_t::vss2_variable_t::end_offset() { return m_end_offset; } -int32_t phoenix_vss2_t::vss2_variable_t::len_alignment_padding_auth() { +int32_t edk2_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())); @@ -349,7 +359,7 @@ int32_t phoenix_vss2_t::vss2_variable_t::len_alignment_padding_auth() { return m_len_alignment_padding_auth; } -bool phoenix_vss2_t::vss2_variable_t::is_valid() { +bool edk2_vss2_t::vss2_variable_t::is_valid() { if (f_is_valid) return m_is_valid; m_is_valid = ((state() == 127) || (state() == 63)) ; @@ -357,7 +367,7 @@ bool phoenix_vss2_t::vss2_variable_t::is_valid() { return m_is_valid; } -int32_t phoenix_vss2_t::vss2_variable_t::offset() { +int32_t edk2_vss2_t::vss2_variable_t::offset() { if (f_offset) return m_offset; m_offset = (int32_t)_io()->pos(); @@ -365,7 +375,7 @@ int32_t phoenix_vss2_t::vss2_variable_t::offset() { return m_offset; } -int32_t phoenix_vss2_t::len_vss2_store_header() { +int32_t edk2_vss2_t::len_vss2_store_header() { if (f_len_vss2_store_header) return m_len_vss2_store_header; m_len_vss2_store_header = (7 * 4); diff --git a/common/generated/phoenix_vss2.h b/common/generated/edk2_vss2.h similarity index 86% rename from common/generated/phoenix_vss2.h rename to common/generated/edk2_vss2.h index 89c5026..7231385 100644 --- a/common/generated/phoenix_vss2.h +++ b/common/generated/edk2_vss2.h @@ -11,27 +11,27 @@ #error "Incompatible Kaitai Struct C++/STL API: version 0.9 or later is required" #endif -class phoenix_vss2_t : public kaitai::kstruct { +class edk2_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); + edk2_vss2_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = nullptr, edk2_vss2_t* p__root = nullptr); private: void _read(); void _clean_up(); public: - ~phoenix_vss2_t(); + ~edk2_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); + vss2_store_body_t(kaitai::kstream* p__io, edk2_vss2_t* p__parent = nullptr, edk2_vss2_t* p__root = nullptr); private: void _read(); @@ -42,20 +42,20 @@ public: private: std::unique_ptr>> m_variables; - phoenix_vss2_t* m__root; - phoenix_vss2_t* m__parent; + edk2_vss2_t* m__root; + edk2_vss2_t* m__parent; public: std::vector>* variables() const { return m_variables.get(); } - phoenix_vss2_t* _root() const { return m__root; } - phoenix_vss2_t* _parent() const { return m__parent; } + edk2_vss2_t* _root() const { return m__root; } + edk2_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); + vss2_variable_attributes_t(kaitai::kstream* p__io, edk2_vss2_t::vss2_variable_t* p__parent = nullptr, edk2_vss2_t* p__root = nullptr); private: void _read(); @@ -73,8 +73,8 @@ public: 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; + edk2_vss2_t* m__root; + edk2_vss2_t::vss2_variable_t* m__parent; public: bool non_volatile() const { return m_non_volatile; } @@ -85,15 +85,15 @@ public: 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; } + edk2_vss2_t* _root() const { return m__root; } + edk2_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); + vss2_variable_t(kaitai::kstream* p__io, edk2_vss2_t::vss2_store_body_t* p__parent = nullptr, edk2_vss2_t* p__root = nullptr); private: void _read(); @@ -307,8 +307,8 @@ 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; + edk2_vss2_t* m__root; + edk2_vss2_t::vss2_store_body_t* m__parent; public: std::string invoke_offset() const { return m_invoke_offset; } @@ -332,8 +332,8 @@ public: 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; } + edk2_vss2_t* _root() const { return m__root; } + edk2_vss2_t::vss2_store_body_t* _parent() const { return m__parent; } }; private: @@ -358,6 +358,13 @@ private: public: bool _is_null_signature_vss2_store() { signature_vss2_store(); return n_signature_vss2_store; }; +private: + std::string m_signature_fdc_store; + bool n_signature_fdc_store; + +public: + bool _is_null_signature_fdc_store() { signature_fdc_store(); return n_signature_fdc_store; }; + private: uint32_t m_vss2_size; uint8_t m_format; @@ -365,7 +372,7 @@ private: uint16_t m_reserved; uint32_t m_reserved1; std::unique_ptr m_body; - phoenix_vss2_t* m__root; + edk2_vss2_t* m__root; kaitai::kstruct* m__parent; std::string m__raw_body; std::unique_ptr m__io__raw_body; @@ -374,13 +381,14 @@ 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; } + std::string signature_fdc_store() const { return m_signature_fdc_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; } + edk2_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(); } diff --git a/common/generated/insyde_fdc.cpp b/common/generated/insyde_fdc.cpp new file mode 100644 index 0000000..003f157 --- /dev/null +++ b/common/generated/insyde_fdc.cpp @@ -0,0 +1,44 @@ +// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild + +#include "insyde_fdc.h" +#include "../kaitai/exceptions.h" + +insyde_fdc_t::insyde_fdc_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, insyde_fdc_t* p__root) : kaitai::kstruct(p__io) { + m__parent = p__parent; + m__root = this; (void)p__root; + f_len_fdc_store_header = false; + _read(); +} + +void insyde_fdc_t::_read() { + m_signature = m__io->read_u4le(); + { + uint32_t _ = signature(); + if (!(_ == 1128547935)) { + throw kaitai::validation_expr_error(signature(), _io(), std::string("/seq/0")); + } + } + m_fdc_size = m__io->read_u4le(); + { + uint32_t _ = fdc_size(); + if (!( ((_ > len_fdc_store_header()) && (_ < 4294967295UL)) )) { + throw kaitai::validation_expr_error(fdc_size(), _io(), std::string("/seq/1")); + } + } + m_body = m__io->read_bytes((fdc_size() - len_fdc_store_header())); +} + +insyde_fdc_t::~insyde_fdc_t() { + _clean_up(); +} + +void insyde_fdc_t::_clean_up() { +} + +int8_t insyde_fdc_t::len_fdc_store_header() { + if (f_len_fdc_store_header) + return m_len_fdc_store_header; + m_len_fdc_store_header = 80; + f_len_fdc_store_header = true; + return m_len_fdc_store_header; +} diff --git a/common/generated/insyde_fdc.h b/common/generated/insyde_fdc.h new file mode 100644 index 0000000..3e8d8a7 --- /dev/null +++ b/common/generated/insyde_fdc.h @@ -0,0 +1,46 @@ +#pragma once + +// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild + +#include "../kaitai/kaitaistruct.h" +#include +#include + +#if KAITAI_STRUCT_VERSION < 9000L +#error "Incompatible Kaitai Struct C++/STL API: version 0.9 or later is required" +#endif + +class insyde_fdc_t : public kaitai::kstruct { + +public: + + insyde_fdc_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = nullptr, insyde_fdc_t* p__root = nullptr); + +private: + void _read(); + void _clean_up(); + +public: + ~insyde_fdc_t(); + +private: + bool f_len_fdc_store_header; + int8_t m_len_fdc_store_header; + +public: + int8_t len_fdc_store_header(); + +private: + uint32_t m_signature; + uint32_t m_fdc_size; + std::string m_body; + insyde_fdc_t* m__root; + kaitai::kstruct* m__parent; + +public: + uint32_t signature() const { return m_signature; } + uint32_t fdc_size() const { return m_fdc_size; } + std::string body() const { return m_body; } + insyde_fdc_t* _root() const { return m__root; } + kaitai::kstruct* _parent() const { return m__parent; } +}; diff --git a/common/ksy/phoenix_vss2.ksy b/common/ksy/edk2_vss2.ksy similarity index 90% rename from common/ksy/phoenix_vss2.ksy rename to common/ksy/edk2_vss2.ksy index f421ba0..07903ee 100644 --- a/common/ksy/phoenix_vss2.ksy +++ b/common/ksy/edk2_vss2.ksy @@ -1,7 +1,7 @@ meta: - id: phoenix_vss2 - title: Phoenix VSS2 NVRAM variable storage - application: Phoenix SCT-based UEFI firmware + id: edk2_vss2 + title: EDK2 VSS2 NVRAM variable storage + application: EDK2-based UEFI firmware file-extension: vss2 tags: - firmware @@ -13,13 +13,16 @@ seq: - id: signature type: u4 valid: - expr: _ == 0xDDCF3617 or _ == 0xAAF32C78 # Beginning of known store GUIDs for VSS2 + expr: _ == 0xDDCF3616 or _ == 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: signature_fdc_store + contents: [0x75, 0x32, 0x64, 0x41, 0x98, 0xB6, 0xFE, 0x85, 0x70, 0x7F, 0xFE, 0x7D] # DDCF3616-3275-4164-98B6-FE85707FFE7D + if: signature == 0xDDCF3616 - id: vss2_size type: u4 valid: diff --git a/common/ksy/insyde_fdc.ksy b/common/ksy/insyde_fdc.ksy new file mode 100644 index 0000000..038721a --- /dev/null +++ b/common/ksy/insyde_fdc.ksy @@ -0,0 +1,25 @@ +meta: + id: insyde_fdc + title: Insyde Factory Data Copy NVRAM store + application: Insyde-based UEFI firmware + file-extension: fdc + tags: + - firmware + license: CC0-1.0 + ks-version: 0.9 + endian: le + +seq: +- id: signature + type: u4 + valid: + expr: _ == 0x4344465F # _FDC +- id: fdc_size + type: u4 + valid: + expr: _ > len_fdc_store_header and _ < 0xFFFFFFFF +- id: body + size: fdc_size - len_fdc_store_header +instances: + len_fdc_store_header: + value: 0x50 diff --git a/common/nvram.h b/common/nvram.h index 0ab72b1..05323d1 100755 --- a/common/nvram.h +++ b/common/nvram.h @@ -16,6 +16,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #define NVRAM_H #include "basetypes.h" +#include "ffs.h" #include "ubytearray.h" #include "ustring.h" @@ -170,6 +171,7 @@ extern const UByteArray NVRAM_VSS2_AUTH_VAR_KEY_DATABASE_GUID; // AAF32C78-947B- #define NVRAM_VSS2_STORE_GUID_PART1 0xddcf3617 extern const UByteArray NVRAM_VSS2_STORE_GUID; // DDCF3617-3275-4164-98B6-FE85707FFE7D +#define NVRAM_FDC_STORE_GUID_PART1 0xddcf3616 extern const UByteArray NVRAM_FDC_STORE_GUID; // DDCF3616-3275-4164-98B6-FE85707FFE7D // Variable store header @@ -193,9 +195,8 @@ typedef struct VSS2_VARIABLE_STORE_HEADER_ { typedef struct FDC_VOLUME_HEADER_ { UINT32 Signature; //_FDC signature UINT32 Size; // Size of the whole region - //EFI_FIRMWARE_VOLUME_HEADER VolumeHeader; - //EFI_FV_BLOCK_MAP_ENTRY FvBlockMap[2]; - //VSS_VARIABLE_STORE_HEADER VssHeader; + EFI_FIRMWARE_VOLUME_HEADER VolumeHeader; + EFI_FV_BLOCK_MAP_ENTRY FvBlockMap[2]; } FDC_VOLUME_HEADER; // diff --git a/common/nvramparser.cpp b/common/nvramparser.cpp index 5ad586a..6c39c64 100644 --- a/common/nvramparser.cpp +++ b/common/nvramparser.cpp @@ -27,7 +27,8 @@ #include "kaitai/kaitaistream.h" #include "generated/ami_nvar.h" #include "generated/edk2_vss.h" -#include "generated/phoenix_vss2.h" +#include "generated/edk2_vss2.h" +#include "generated/insyde_fdc.h" USTATUS NvramParser::parseNvarStore(const UModelIndex & index) { @@ -283,7 +284,7 @@ processing_done: return U_SUCCESS; } -USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index) +USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 fdcStoreSizeOverride) { // Sanity check if (!index.isValid()) @@ -311,12 +312,30 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index) storeOffset < volumeBodySize; storeOffset++) { bool storeFound = false; - // Try parsing as VSS store + // VSS try { + if (volumeBodySize - storeOffset < sizeof(VSS_VARIABLE_STORE_HEADER)) { + // No need to parse further, the rest of the volume is too small + throw 0; + } + UByteArray vss = volumeBody.mid(storeOffset); + // Check if we are here to parse a special case of FDC store with size override + UINT32 originalStoreSize = 0; + VSS_VARIABLE_STORE_HEADER* vssHeader = (VSS_VARIABLE_STORE_HEADER*)vss.data(); + bool fdcHeaderSizeOverrideRequired = (fdcStoreSizeOverride > 0 && vssHeader->Signature == NVRAM_VSS_STORE_SIGNATURE && vssHeader->Size == 0xFFFFFFFF); + if (fdcHeaderSizeOverrideRequired) { + originalStoreSize = vssHeader->Size; + vssHeader->Size = fdcStoreSizeOverride; + } umemstream is(vss.constData(), vss.size()); kaitai::kstream ks(&is); edk2_vss_t parsed(&ks); + UINT32 storeSize = parsed.vss_size(); + // Restore original store size, if needed + if (fdcHeaderSizeOverrideRequired) { + vssHeader->Size = originalStoreSize; + } // VSS store at current offset parsed correctly // Check if we need to add a padding before it @@ -328,7 +347,7 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index) // Construct header and body UByteArray header = vss.left(parsed.len_vss_store_header()); - UByteArray body = vss.mid(header.size(), parsed.vss_size() - header.size()); + UByteArray body = vss.mid(header.size(), storeSize - header.size()); // Add info UString name; @@ -344,7 +363,7 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index) 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(), + storeSize , storeSize, (UINT32)header.size(), (UINT32)header.size(), (UINT32)body.size(), (UINT32)body.size(), parsed.format(), @@ -365,8 +384,8 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index) // 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); + if (vssVariableOffset < storeSize) { + UByteArray freeSpace = vss.mid(vssVariableOffset, storeSize - vssVariableOffset); // Add info info = usprintf("Full size: %Xh (%u)", (UINT32)freeSpace.size(), (UINT32)freeSpace.size()); @@ -474,7 +493,7 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index) } storeFound = true; - storeOffset += parsed.vss_size(); + storeOffset += storeSize; previousStoreEndOffset = storeOffset; } catch (...) { // Parsing failed, try something else @@ -482,11 +501,30 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index) // VSS2 try { + if (volumeBodySize - storeOffset < sizeof(VSS2_VARIABLE_STORE_HEADER)) { + // No need to parse further, the rest of the volume is too small + throw 0; + } + UByteArray vss2 = volumeBody.mid(storeOffset); + // Check if we are here to parse a special case of FDC store with size override + UINT32 originalStoreSize = 0; + VSS2_VARIABLE_STORE_HEADER* vss2Header = (VSS2_VARIABLE_STORE_HEADER*)vss2.data(); + UByteArray guid = UByteArray((const char*)&vss2Header->Signature, sizeof(EFI_GUID)); + bool fdcHeaderSizeOverrideRequired = (fdcStoreSizeOverride > 0 && guid == NVRAM_FDC_STORE_GUID && vss2Header->Size == 0xFFFFFFFF); + if (fdcStoreSizeOverride) { + originalStoreSize = vss2Header->Size; + vss2Header->Size = fdcStoreSizeOverride; + } umemstream is(vss2.constData(), vss2.size()); kaitai::kstream ks(&is); - phoenix_vss2_t parsed(&ks); - + edk2_vss2_t parsed(&ks); + UINT32 storeSize = parsed.vss2_size(); + // Restore original store size, if needed + if (fdcStoreSizeOverride) { + vss2Header->Size = originalStoreSize; + } + // VSS2 store at current offset parsed correctly // Check if we need to add a padding before it if (!outerPadding.isEmpty()) { @@ -497,7 +535,7 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index) // Construct header and body UByteArray header = vss2.left(parsed.len_vss2_store_header()); - UByteArray body = vss2.mid(header.size(), parsed.vss2_size() - header.size()); + UByteArray body = vss2.mid(header.size(), storeSize - header.size()); // Add info UString name = UString("VSS2 store"); @@ -505,12 +543,15 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index) if (parsed.signature() == NVRAM_VSS2_AUTH_VAR_KEY_DATABASE_GUID_PART1) { info = UString("Signature: AAF32C78-947B-439A-A180-2E144EC37792\n"); } + else if (parsed.signature() == NVRAM_FDC_STORE_GUID_PART1) { + info = UString("Signature: DDCF3616-3275-4164-98B6-FE85707FFE7D\n"); + } else { info = UString("Signature: DDCF3617-3275-4164-98B6-FE85707FFE7D\n"); } info += usprintf("Full size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nFormat: %02Xh\nState: %02Xh\nReserved: %02Xh\nReserved1: %04Xh", - parsed.vss2_size() , parsed.vss2_size(), + storeSize, storeSize, (UINT32)header.size(), (UINT32)header.size(), (UINT32)body.size(), (UINT32)body.size(), parsed.format(), @@ -519,7 +560,7 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index) parsed.reserved1()); // 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::Vss2Store, 0, name, UString(), info, header, body, UByteArray(), Fixed, index); UINT32 vss2VariableOffset = storeOffset + parsed.len_vss2_store_header(); for (const auto & variable : *parsed.body()->variables()) { @@ -531,8 +572,8 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index) // 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 (vss2VariableOffset < parsed.vss2_size()) { - UByteArray freeSpace = vss2.mid(vss2VariableOffset, parsed.vss2_size() - vss2VariableOffset); + if (vss2VariableOffset < storeSize) { + UByteArray freeSpace = vss2.mid(vss2VariableOffset, storeSize - vss2VariableOffset); // Add info info = usprintf("Full size: %Xh (%u)", (UINT32)freeSpace.size(), (UINT32)freeSpace.size()); @@ -610,27 +651,75 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index) } storeFound = true; - storeOffset += parsed.vss2_size(); + storeOffset += storeSize; previousStoreEndOffset = storeOffset; } catch (...) { // Parsing failed, try something else } - // FDC - - // EVSA - - // FTW - - // Apple Fsys/Gaid - - // Phoenix FlashMap - // Phoenix CMDB - // Phoenix SLIC Pubkey/Marker - // Intel uCode - + // Do not try any other parsers if we are here for FDC store parsing + if (fdcStoreSizeOverride == 0) { + // FTW + + // 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 with modified body + UModelIndex headerIndex = model->addItem(localOffset + storeOffset, Types::FdcStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, index); + + // Parse modified FDC body as normal VSS/VSS2 storage + parseNvramVolumeBody(headerIndex, (UINT32)body.size()); + + storeFound = true; + storeOffset += storeSize; + previousStoreEndOffset = storeOffset; + } catch (...) { + // Parsing failed, try something else + } + + + // Apple Fsys/Gaid + + // Phoenix EVSA + // Phoenix FlashMap + // Phoenix CMDB + // Phoenix SLIC Pubkey/Marker + // Intel uCode + } + // Padding - outerPadding.append(volumeBody.at(storeOffset)); + if (storeOffset < volumeBodySize) { + outerPadding += volumeBody[storeOffset]; + } } // Add padding at the very end diff --git a/common/nvramparser.h b/common/nvramparser.h index a53862d..a64e795 100644 --- a/common/nvramparser.h +++ b/common/nvramparser.h @@ -37,7 +37,7 @@ public: void clearMessages() { messagesVector.clear(); } // NVRAM parsing - USTATUS parseNvramVolumeBody(const UModelIndex & index); + USTATUS parseNvramVolumeBody(const UModelIndex & index, const UINT32 fdcStoreSizeOverride = 0); USTATUS parseNvarStore(const UModelIndex & index); private: diff --git a/common/treemodel.h b/common/treemodel.h index 0d6b5ac..b2f9e39 100644 --- a/common/treemodel.h +++ b/common/treemodel.h @@ -194,6 +194,7 @@ public: UByteArray body(const UModelIndex &index) const; bool hasEmptyBody(const UModelIndex &index) const; + void setBody(const UModelIndex &index, const UByteArray &body); UByteArray tail(const UModelIndex &index) const; bool hasEmptyTail(const UModelIndex &index) const; diff --git a/kaitai_regenerate.sh b/kaitai_regenerate.sh index a343810..c97e003 100755 --- a/kaitai_regenerate.sh +++ b/kaitai_regenerate.sh @@ -50,12 +50,12 @@ ${UFIND} common/generated ${UFINDOPT} \ -name 'ami_nvar.cpp' \ -exec sed -i.bak 's/_offset = _io()->pos();/_offset = (int32_t)_io()->pos();/g' {} + || exit 1 -# Suppress type downcast warning in phoenix_vss2.cpp +# Suppress type downcast warning in edk2_vss2.cpp ${UFIND} common/generated ${UFINDOPT} \ - -name 'phoenix_vss2.cpp' \ + -name 'edk2_vss2.cpp' \ -exec sed -i.bak 's/_offset = _io()->pos();/_offset = (int32_t)_io()->pos();/g' {} + || exit 1 ${UFIND} common/generated ${UFINDOPT} \ - -name 'phoenix_vss2.cpp' \ + -name 'edk2_vss2.cpp' \ -exec sed -i.bak 's/_offset_auth = _io()->pos();/_offset_auth = (int32_t)_io()->pos();/g' {} + || exit 1 # Remove backup files