diff --git a/UEFIExtract/CMakeLists.txt b/UEFIExtract/CMakeLists.txt index b1f0533..f2cd5fc 100644 --- a/UEFIExtract/CMakeLists.txt +++ b/UEFIExtract/CMakeLists.txt @@ -41,6 +41,8 @@ SET(PROJECT_SOURCES ../common/generated/edk2_ftw.cpp ../common/generated/insyde_fdc.cpp ../common/generated/insyde_fdm.cpp + ../common/generated/ms_slic_marker.cpp + ../common/generated/ms_slic_pubkey.cpp ../common/generated/phoenix_flm.cpp ../common/generated/phoenix_evsa.cpp ../common/generated/intel_acbp_v1.cpp diff --git a/UEFIFind/CMakeLists.txt b/UEFIFind/CMakeLists.txt index e27a5eb..c66c04c 100644 --- a/UEFIFind/CMakeLists.txt +++ b/UEFIFind/CMakeLists.txt @@ -38,6 +38,8 @@ SET(PROJECT_SOURCES ../common/generated/edk2_ftw.cpp ../common/generated/insyde_fdc.cpp ../common/generated/insyde_fdm.cpp + ../common/generated/ms_slic_marker.cpp + ../common/generated/ms_slic_pubkey.cpp ../common/generated/phoenix_flm.cpp ../common/generated/phoenix_evsa.cpp ../common/generated/intel_acbp_v1.cpp diff --git a/UEFITool/CMakeLists.txt b/UEFITool/CMakeLists.txt index 9ba54df..eee9153 100644 --- a/UEFITool/CMakeLists.txt +++ b/UEFITool/CMakeLists.txt @@ -74,6 +74,8 @@ SET(PROJECT_SOURCES ../common/generated/edk2_ftw.cpp ../common/generated/insyde_fdc.cpp ../common/generated/insyde_fdm.cpp + ../common/generated/ms_slic_marker.cpp + ../common/generated/ms_slic_pubkey.cpp ../common/generated/phoenix_evsa.cpp ../common/generated/phoenix_flm.cpp ../common/generated/intel_acbp_v1.cpp diff --git a/UEFITool/uefitool.pro b/UEFITool/uefitool.pro index 6de5332..a3ea8c9 100644 --- a/UEFITool/uefitool.pro +++ b/UEFITool/uefitool.pro @@ -57,6 +57,8 @@ HEADERS += uefitool.h \ ../common/generated/edk2_ftw.h \ ../common/generated/insyde_fdc.h \ ../common/generated/insyde_fdm.h \ + ../common/generated/ms_slic_marker.h \ + ../common/generated/ms_slic_pubkey.h \ ../common/generated/phoenix_flm.h \ ../common/generated/phoenix_evsa.h \ ../common/generated/intel_acbp_v1.h \ @@ -132,6 +134,8 @@ SOURCES += uefitool_main.cpp \ ../common/generated/edk2_ftw.cpp \ ../common/generated/insyde_fdc.cpp \ ../common/generated/insyde_fdm.cpp \ + ../common/generated/ms_slic_marker.cpp \ + ../common/generated/ms_slic_pubkey.cpp \ ../common/generated/phoenix_flm.cpp \ ../common/generated/phoenix_evsa.cpp \ ../common/generated/intel_acbp_v1.cpp \ diff --git a/common/ffsparser.cpp b/common/ffsparser.cpp index 3706036..0be22c2 100644 --- a/common/ffsparser.cpp +++ b/common/ffsparser.cpp @@ -992,7 +992,7 @@ USTATUS FfsParser::parseRawArea(const UModelIndex & index) } // Add board IDs - if (parsed.revision() == 3) { + if (!parsed._is_null_board_ids()) { info += usprintf("\nRegion index: %Xh\nBoardId Count: %u", parsed.board_ids()->region_index(), parsed.board_ids()->num_board_ids()); diff --git a/common/generated/apple_sysf.cpp b/common/generated/apple_sysf.cpp index 84a0678..580d84e 100644 --- a/common/generated/apple_sysf.cpp +++ b/common/generated/apple_sysf.cpp @@ -1,7 +1,6 @@ // 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; @@ -14,12 +13,6 @@ apple_sysf_t::apple_sysf_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, a void apple_sysf_t::_read() { m_signature = m__io->read_u4le(); - { - uint32_t _ = signature(); - if (!( ((_ == 1937339206) || (_ == 1684627783)) )) { - throw kaitai::validation_expr_error(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(); diff --git a/common/generated/edk2_ftw.cpp b/common/generated/edk2_ftw.cpp index e50c598..60aa199 100644 --- a/common/generated/edk2_ftw.cpp +++ b/common/generated/edk2_ftw.cpp @@ -1,7 +1,6 @@ // This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild #include "edk2_ftw.h" -#include "../kaitai/exceptions.h" edk2_ftw_t::edk2_ftw_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, edk2_ftw_t* p__root) : kaitai::kstruct(p__io) { m__parent = p__parent; @@ -13,12 +12,6 @@ edk2_ftw_t::edk2_ftw_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, edk2_ void edk2_ftw_t::_read() { m_signature = m__io->read_bytes(16); - { - std::string _ = signature(); - if (!( ((_ == std::string("\x8D\x2B\xF1\xFF\x96\x76\x8B\x4C\xA9\x85\x27\x47\x07\x5B\x4F\x50", 16)) || (_ == std::string("\x2B\x29\x58\x9E\x68\x7C\x7D\x49\x0A\xCE\x65\x00\xFD\x9F\x1B\x95", 16)) || (_ == std::string("\x2B\x29\x58\x9E\x68\x7C\x7D\x49\xA0\xCE\x65\x00\xFD\x9F\x1B\x95", 16))) )) { - throw kaitai::validation_expr_error(signature(), _io(), std::string("/seq/0")); - } - } m_crc = m__io->read_u4le(); m_state = m__io->read_u1(); m_reserved = m__io->read_bytes(3); diff --git a/common/generated/edk2_vss.cpp b/common/generated/edk2_vss.cpp index 9c5ecac..6a5eced 100644 --- a/common/generated/edk2_vss.cpp +++ b/common/generated/edk2_vss.cpp @@ -14,12 +14,6 @@ edk2_vss_t::edk2_vss_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, edk2_ void edk2_vss_t::_read() { m_signature = m__io->read_u4le(); - { - uint32_t _ = signature(); - if (!( ((_ == 1397970468) || (_ == 1398166308) || (_ == 1397968420)) )) { - throw kaitai::validation_expr_error(signature(), _io(), std::string("/seq/0")); - } - } m_vss_size = m__io->read_u4le(); { uint32_t _ = vss_size(); @@ -28,12 +22,6 @@ void edk2_vss_t::_read() { } } m_format = m__io->read_u1(); - { - uint8_t _ = format(); - if (!(_ == 90)) { - throw kaitai::validation_expr_error(format(), _io(), std::string("/seq/2")); - } - } m_state = m__io->read_u1(); m_reserved = m__io->read_u2le(); m_reserved1 = m__io->read_u4le(); diff --git a/common/generated/edk2_vss2.cpp b/common/generated/edk2_vss2.cpp index b9ffd83..7e2e3f5 100644 --- a/common/generated/edk2_vss2.cpp +++ b/common/generated/edk2_vss2.cpp @@ -13,51 +13,15 @@ edk2_vss2_t::edk2_vss2_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, edk } void edk2_vss2_t::_read() { - m_signature = m__io->read_u4le(); - { - uint32_t _ = signature(); - if (!( ((_ == 3721344534UL) || (_ == 3721344535UL) || (_ == 2868063352UL)) )) { - throw kaitai::validation_expr_error(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("\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("\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_signature = m__io->read_bytes(16); m_vss2_size = m__io->read_u4le(); { uint32_t _ = vss2_size(); if (!( ((_ > static_cast(len_vss2_store_header())) && (_ < 4294967295UL)) )) { - throw kaitai::validation_expr_error(vss2_size(), _io(), std::string("/seq/4")); + throw kaitai::validation_expr_error(vss2_size(), _io(), std::string("/seq/1")); } } m_format = m__io->read_u1(); - { - uint8_t _ = format(); - if (!(_ == 90)) { - throw kaitai::validation_expr_error(format(), _io(), std::string("/seq/5")); - } - } m_state = m__io->read_u1(); m_reserved = m__io->read_u2le(); m_reserved1 = m__io->read_u4le(); @@ -71,12 +35,6 @@ edk2_vss2_t::~edk2_vss2_t() { } void edk2_vss2_t::_clean_up() { - if (!n_signature_auth_var_key_db) { - } - if (!n_signature_vss2_store) { - } - if (!n_signature_fdc_store) { - } } 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) { diff --git a/common/generated/edk2_vss2.h b/common/generated/edk2_vss2.h index 7231385..3053a8e 100644 --- a/common/generated/edk2_vss2.h +++ b/common/generated/edk2_vss2.h @@ -344,28 +344,7 @@ public: int32_t len_vss2_store_header(); 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: - 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: + std::string m_signature; uint32_t m_vss2_size; uint8_t m_format; uint8_t m_state; @@ -378,10 +357,7 @@ private: std::unique_ptr 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; } - std::string signature_fdc_store() const { return m_signature_fdc_store; } + std::string signature() const { return m_signature; } uint32_t vss2_size() const { return m_vss2_size; } uint8_t format() const { return m_format; } uint8_t state() const { return m_state; } diff --git a/common/generated/insyde_fdc.cpp b/common/generated/insyde_fdc.cpp index 2312547..7a3080e 100644 --- a/common/generated/insyde_fdc.cpp +++ b/common/generated/insyde_fdc.cpp @@ -12,12 +12,6 @@ insyde_fdc_t::insyde_fdc_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, i 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(); diff --git a/common/generated/insyde_fdm.cpp b/common/generated/insyde_fdm.cpp index ebef703..4306965 100644 --- a/common/generated/insyde_fdm.cpp +++ b/common/generated/insyde_fdm.cpp @@ -24,6 +24,9 @@ void insyde_fdm_t::_read() { m_entry_size = m__io->read_u4le(); m_entry_format = m__io->read_u1(); m_revision = m__io->read_u1(); + if (!( ((revision() == 1) || (revision() == 2) || (revision() == 3)) )) { + throw kaitai::validation_not_any_of_error(revision(), _io(), std::string("/seq/5")); + } m_num_extensions = m__io->read_u1(); m_checksum = m__io->read_u1(); m_fd_base_address = m__io->read_u8le(); @@ -35,7 +38,7 @@ void insyde_fdm_t::_read() { m_extensions = std::unique_ptr(new fdm_extensions_t(m__io__raw_extensions.get(), this, m__root)); } n_board_ids = true; - if (revision() == 3) { + if ( ((revision() == 3) && (extensions()->extensions()->at(1)->count() > 0)) ) { n_board_ids = false; m_board_ids = std::unique_ptr(new fdm_board_ids_t(m__io, this, m__root)); } diff --git a/common/generated/ms_slic_marker.cpp b/common/generated/ms_slic_marker.cpp new file mode 100644 index 0000000..ad7aa00 --- /dev/null +++ b/common/generated/ms_slic_marker.cpp @@ -0,0 +1,28 @@ +// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild + +#include "ms_slic_marker.h" + +ms_slic_marker_t::ms_slic_marker_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, ms_slic_marker_t* p__root) : kaitai::kstruct(p__io) { + m__parent = p__parent; + m__root = this; (void)p__root; + _read(); +} + +void ms_slic_marker_t::_read() { + m_type = m__io->read_u4le(); + m_len_marker = m__io->read_u4le(); + m_version = m__io->read_u4le(); + m_oem_id = m__io->read_bytes(6); + m_oem_table_id = m__io->read_bytes(8); + m_windows_flag = m__io->read_u8le(); + m_slic_version = m__io->read_u4le(); + m_reserved = m__io->read_bytes(16); + m_signature = m__io->read_bytes(128); +} + +ms_slic_marker_t::~ms_slic_marker_t() { + _clean_up(); +} + +void ms_slic_marker_t::_clean_up() { +} diff --git a/common/generated/ms_slic_marker.h b/common/generated/ms_slic_marker.h new file mode 100644 index 0000000..a5935dc --- /dev/null +++ b/common/generated/ms_slic_marker.h @@ -0,0 +1,51 @@ +#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 ms_slic_marker_t : public kaitai::kstruct { + +public: + + ms_slic_marker_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = nullptr, ms_slic_marker_t* p__root = nullptr); + +private: + void _read(); + void _clean_up(); + +public: + ~ms_slic_marker_t(); + +private: + uint32_t m_type; + uint32_t m_len_marker; + uint32_t m_version; + std::string m_oem_id; + std::string m_oem_table_id; + uint64_t m_windows_flag; + uint32_t m_slic_version; + std::string m_reserved; + std::string m_signature; + ms_slic_marker_t* m__root; + kaitai::kstruct* m__parent; + +public: + uint32_t type() const { return m_type; } + uint32_t len_marker() const { return m_len_marker; } + uint32_t version() const { return m_version; } + std::string oem_id() const { return m_oem_id; } + std::string oem_table_id() const { return m_oem_table_id; } + uint64_t windows_flag() const { return m_windows_flag; } + uint32_t slic_version() const { return m_slic_version; } + std::string reserved() const { return m_reserved; } + std::string signature() const { return m_signature; } + ms_slic_marker_t* _root() const { return m__root; } + kaitai::kstruct* _parent() const { return m__parent; } +}; diff --git a/common/generated/ms_slic_pubkey.cpp b/common/generated/ms_slic_pubkey.cpp new file mode 100644 index 0000000..bfe2fb9 --- /dev/null +++ b/common/generated/ms_slic_pubkey.cpp @@ -0,0 +1,29 @@ +// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild + +#include "ms_slic_pubkey.h" + +ms_slic_pubkey_t::ms_slic_pubkey_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, ms_slic_pubkey_t* p__root) : kaitai::kstruct(p__io) { + m__parent = p__parent; + m__root = this; (void)p__root; + _read(); +} + +void ms_slic_pubkey_t::_read() { + m_type = m__io->read_u4le(); + m_len_pubkey = m__io->read_u4le(); + m_key_type = m__io->read_u1(); + m_version = m__io->read_u1(); + m_reserved = m__io->read_u2le(); + m_algorithm = m__io->read_u4le(); + m_magic = m__io->read_u4le(); + m_bit_length = m__io->read_u4le(); + m_exponent = m__io->read_u4le(); + m_modulus = m__io->read_bytes(128); +} + +ms_slic_pubkey_t::~ms_slic_pubkey_t() { + _clean_up(); +} + +void ms_slic_pubkey_t::_clean_up() { +} diff --git a/common/generated/ms_slic_pubkey.h b/common/generated/ms_slic_pubkey.h new file mode 100644 index 0000000..75e7361 --- /dev/null +++ b/common/generated/ms_slic_pubkey.h @@ -0,0 +1,53 @@ +#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 ms_slic_pubkey_t : public kaitai::kstruct { + +public: + + ms_slic_pubkey_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = nullptr, ms_slic_pubkey_t* p__root = nullptr); + +private: + void _read(); + void _clean_up(); + +public: + ~ms_slic_pubkey_t(); + +private: + uint32_t m_type; + uint32_t m_len_pubkey; + uint8_t m_key_type; + uint8_t m_version; + uint16_t m_reserved; + uint32_t m_algorithm; + uint32_t m_magic; + uint32_t m_bit_length; + uint32_t m_exponent; + std::string m_modulus; + ms_slic_pubkey_t* m__root; + kaitai::kstruct* m__parent; + +public: + uint32_t type() const { return m_type; } + uint32_t len_pubkey() const { return m_len_pubkey; } + uint8_t key_type() const { return m_key_type; } + uint8_t version() const { return m_version; } + uint16_t reserved() const { return m_reserved; } + uint32_t algorithm() const { return m_algorithm; } + uint32_t magic() const { return m_magic; } + uint32_t bit_length() const { return m_bit_length; } + uint32_t exponent() const { return m_exponent; } + std::string modulus() const { return m_modulus; } + ms_slic_pubkey_t* _root() const { return m__root; } + kaitai::kstruct* _parent() const { return m__parent; } +}; diff --git a/common/generated/phoenix_evsa.cpp b/common/generated/phoenix_evsa.cpp index 1315663..c586711 100644 --- a/common/generated/phoenix_evsa.cpp +++ b/common/generated/phoenix_evsa.cpp @@ -13,18 +13,9 @@ phoenix_evsa_t::phoenix_evsa_t(kaitai::kstream* p__io, kaitai::kstruct* p__paren void phoenix_evsa_t::_read() { m_type = m__io->read_u1(); - if (!(type() == 236)) { - throw kaitai::validation_not_equal_error(236, type(), _io(), std::string("/seq/0")); - } m_checksum = m__io->read_u1(); m_len_evsa_store_header = m__io->read_u2le(); - if (!(len_evsa_store_header() == 20)) { - throw kaitai::validation_not_equal_error(20, len_evsa_store_header(), _io(), std::string("/seq/2")); - } m_signature = m__io->read_u4le(); - if (!(signature() == 1095980613)) { - throw kaitai::validation_not_equal_error(1095980613, signature(), _io(), std::string("/seq/3")); - } m_attributes = m__io->read_u4le(); m_len_evsa_store = m__io->read_u4le(); m_reserved = m__io->read_u4le(); diff --git a/common/generated/phoenix_flm.cpp b/common/generated/phoenix_flm.cpp index c1d9228..babbbb3 100644 --- a/common/generated/phoenix_flm.cpp +++ b/common/generated/phoenix_flm.cpp @@ -1,14 +1,11 @@ // This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild #include "phoenix_flm.h" -#include "../kaitai/exceptions.h" phoenix_flm_t::phoenix_flm_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, phoenix_flm_t* p__root) : kaitai::kstruct(p__io) { m__parent = p__parent; m__root = this; (void)p__root; m_entries = nullptr; - m_free_space = nullptr; - f_len_flm_store = false; f_len_flm_store_header = false; f_len_flm_entry = false; _read(); @@ -16,27 +13,13 @@ phoenix_flm_t::phoenix_flm_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, void phoenix_flm_t::_read() { m_signature = m__io->read_bytes(10); - if (!(signature() == std::string("\x5F\x46\x4C\x41\x53\x48\x5F\x4D\x41\x50", 10))) { - throw kaitai::validation_not_equal_error(std::string("\x5F\x46\x4C\x41\x53\x48\x5F\x4D\x41\x50", 10), signature(), _io(), std::string("/seq/0")); - } m_num_entries = m__io->read_u2le(); - { - uint16_t _ = num_entries(); - if (!(_ <= 113)) { - throw kaitai::validation_expr_error(num_entries(), _io(), std::string("/seq/1")); - } - } m_reserved = m__io->read_u4le(); m_entries = std::unique_ptr>>(new std::vector>()); const int l_entries = num_entries(); for (int i = 0; i < l_entries; i++) { m_entries->push_back(std::move(std::unique_ptr(new flm_entry_t(m__io, this, m__root)))); } - m_free_space = std::unique_ptr>(new std::vector()); - const int l_free_space = ((len_flm_store() - len_flm_store_header()) - (len_flm_entry() * num_entries())); - for (int i = 0; i < l_free_space; i++) { - m_free_space->push_back(std::move(m__io->read_u1())); - } } phoenix_flm_t::~phoenix_flm_t() { @@ -68,14 +51,6 @@ phoenix_flm_t::flm_entry_t::~flm_entry_t() { void phoenix_flm_t::flm_entry_t::_clean_up() { } -int32_t phoenix_flm_t::len_flm_store() { - if (f_len_flm_store) - return m_len_flm_store; - m_len_flm_store = 4096; - f_len_flm_store = true; - return m_len_flm_store; -} - int8_t phoenix_flm_t::len_flm_store_header() { if (f_len_flm_store_header) return m_len_flm_store_header; diff --git a/common/generated/phoenix_flm.h b/common/generated/phoenix_flm.h index a42b9c6..2faeba3 100644 --- a/common/generated/phoenix_flm.h +++ b/common/generated/phoenix_flm.h @@ -59,13 +59,6 @@ public: phoenix_flm_t* _parent() const { return m__parent; } }; -private: - bool f_len_flm_store; - int32_t m_len_flm_store; - -public: - int32_t len_flm_store(); - private: bool f_len_flm_store_header; int8_t m_len_flm_store_header; @@ -85,7 +78,6 @@ private: uint16_t m_num_entries; uint32_t m_reserved; std::unique_ptr>> m_entries; - std::unique_ptr> m_free_space; phoenix_flm_t* m__root; kaitai::kstruct* m__parent; @@ -94,7 +86,6 @@ public: uint16_t num_entries() const { return m_num_entries; } uint32_t reserved() const { return m_reserved; } std::vector>* entries() const { return m_entries.get(); } - std::vector* free_space() const { return m_free_space.get(); } phoenix_flm_t* _root() const { return m__root; } kaitai::kstruct* _parent() const { return m__parent; } }; diff --git a/common/ksy/apple_fsys.ksy b/common/ksy/apple_sysf.ksy similarity index 89% rename from common/ksy/apple_fsys.ksy rename to common/ksy/apple_sysf.ksy index 934c74e..4b6bb4f 100644 --- a/common/ksy/apple_fsys.ksy +++ b/common/ksy/apple_sysf.ksy @@ -1,6 +1,6 @@ meta: id: apple_sysf - title: Apple system variable store + title: Apple System Flags store application: Apple MacEFI-based UEFI firmware file-extension: sysf tags: @@ -12,8 +12,6 @@ meta: seq: - id: signature type: u4 - valid: - expr: _ == 0x73797346 or _ == 0x64696147 # Fsys/Gaid - id: unknown type: u1 - id: unknown1 diff --git a/common/ksy/edk2_ftw.ksy b/common/ksy/edk2_ftw.ksy index 1c23200..bed3013 100644 --- a/common/ksy/edk2_ftw.ksy +++ b/common/ksy/edk2_ftw.ksy @@ -12,10 +12,6 @@ meta: seq: - id: signature size: 16 - valid: - expr: _ == [0x8D, 0x2B, 0xF1, 0xFF, 0x96, 0x76, 0x8B, 0x4C, 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50] - or _ == [0x2B, 0x29, 0x58, 0x9E, 0x68, 0x7C, 0x7D, 0x49, 0x0A, 0xCE, 0x65, 0x00, 0xFD, 0x9F, 0x1B, 0x95] - or _ == [0x2B, 0x29, 0x58, 0x9E, 0x68, 0x7C, 0x7D, 0x49, 0xA0, 0xCE, 0x65, 0x00, 0xFD, 0x9F, 0x1B, 0x95] - id: crc type: u4 - id: state diff --git a/common/ksy/edk2_vss.ksy b/common/ksy/edk2_vss.ksy index a36c5df..8c6b5fd 100644 --- a/common/ksy/edk2_vss.ksy +++ b/common/ksy/edk2_vss.ksy @@ -12,16 +12,12 @@ meta: seq: - id: signature type: u4 - valid: - expr: _ == 0x53535624 or _ == 0x53565324 or _ == 0x53534E24 # $VSS/$SVS/$NSS - id: vss_size type: u4 valid: expr: _ > len_vss_store_header.as and _ < 0xFFFFFFFF - id: format type: u1 - valid: - expr: _ == 0x5a # Formatted - id: state type: u1 - id: reserved diff --git a/common/ksy/edk2_vss2.ksy b/common/ksy/edk2_vss2.ksy index 5cc9a11..bd4d149 100644 --- a/common/ksy/edk2_vss2.ksy +++ b/common/ksy/edk2_vss2.ksy @@ -11,26 +11,13 @@ meta: seq: - id: signature - type: u4 - valid: - 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 + size: 16 - id: vss2_size type: u4 valid: expr: _ > len_vss2_store_header.as and _ < 0xFFFFFFFF - id: format type: u1 - valid: - expr: _ == 0x5a # Formatted - id: state type: u1 - id: reserved diff --git a/common/ksy/insyde_fdc.ksy b/common/ksy/insyde_fdc.ksy index 1d6ec93..2bfb0f7 100644 --- a/common/ksy/insyde_fdc.ksy +++ b/common/ksy/insyde_fdc.ksy @@ -12,8 +12,6 @@ meta: seq: - id: signature type: u4 - valid: - expr: _ == 0x4344465F # _FDC - id: fdc_size type: u4 valid: diff --git a/common/ksy/insyde_fdm.ksy b/common/ksy/insyde_fdm.ksy index 406704f..168f6ee 100644 --- a/common/ksy/insyde_fdm.ksy +++ b/common/ksy/insyde_fdm.ksy @@ -1,6 +1,6 @@ meta: id: insyde_fdm - title: Insyde Flash Device + title: Insyde Flash Device Map application: Insyde-based UEFI firmware file-extension: fdm tags: @@ -23,6 +23,8 @@ seq: type: u1 - id: revision type: u1 + valid: + any-of: [1, 2, 3] - id: num_extensions type: u1 - id: checksum @@ -35,7 +37,7 @@ seq: if: revision == 3 - id: board_ids type: fdm_board_ids - if: revision == 3 + if: revision == 3 and extensions.extensions[1].count > 0 - id: entries type: fdm_entries size: store_size - data_offset diff --git a/common/ksy/ms_slic_marker.ksy b/common/ksy/ms_slic_marker.ksy new file mode 100644 index 0000000..0ea0de1 --- /dev/null +++ b/common/ksy/ms_slic_marker.ksy @@ -0,0 +1,30 @@ +meta: + id: ms_slic_marker + title: Microsoft SLIC Marker + application: Phoenix-based UEFI firmware + file-extension: slmr + tags: + - firmware + license: CC0-1.0 + ks-version: 0.9 + endian: le + +seq: +- id: type + type: u4 +- id: len_marker + type: u4 +- id: version + type: u4 +- id: oem_id + size: 6 +- id: oem_table_id + size: 8 +- id: windows_flag + type: u8 +- id: slic_version + type: u4 +- id: reserved + size: 16 +- id: signature + size: 128 diff --git a/common/ksy/ms_slic_pubkey.ksy b/common/ksy/ms_slic_pubkey.ksy new file mode 100644 index 0000000..3c042ae --- /dev/null +++ b/common/ksy/ms_slic_pubkey.ksy @@ -0,0 +1,32 @@ +meta: + id: ms_slic_pubkey + title: Microsoft SLIC Public Key + application: Phoenix-based UEFI firmware + file-extension: slpk + tags: + - firmware + license: CC0-1.0 + ks-version: 0.9 + endian: le + +seq: +- id: type + type: u4 +- id: len_pubkey + type: u4 +- id: key_type + type: u1 +- id: version + type: u1 +- id: reserved + type: u2 +- id: algorithm + type: u4 +- id: magic + type: u4 +- id: bit_length + type: u4 +- id: exponent + type: u4 +- id: modulus + size: 128 diff --git a/common/ksy/phoenix_evsa.ksy b/common/ksy/phoenix_evsa.ksy index 2264b17..11135d1 100644 --- a/common/ksy/phoenix_evsa.ksy +++ b/common/ksy/phoenix_evsa.ksy @@ -12,15 +12,12 @@ meta: seq: - id: type type: u1 - valid: 0xEC - id: checksum type: u1 - id: len_evsa_store_header type: u2 - valid: 20 - id: signature type: u4 - valid: 0x41535645 #EVSA - id: attributes type: u4 - id: len_evsa_store diff --git a/common/ksy/phoenix_flm.ksy b/common/ksy/phoenix_flm.ksy index d46acee..a1148c4 100644 --- a/common/ksy/phoenix_flm.ksy +++ b/common/ksy/phoenix_flm.ksy @@ -1,6 +1,6 @@ meta: id: phoenix_flm - title: Phoenix flash map + title: Phoenix Flash Map application: Phoenix-based UEFI firmware file-extension: flm tags: @@ -11,25 +11,17 @@ meta: seq: - id: signature - contents: [0x5F, 0x46, 0x4C, 0x41, 0x53, 0x48, 0x5F, 0x4D, 0x41, 0x50] # _FLASH_MAP + size: 10 - id: num_entries type: u2 - valid: - expr: _ <= 113 # Needs to fit into the last 0x1000 bytes of the NVRAM volume - id: reserved type: u4 - id: entries type: flm_entry repeat: expr repeat-expr: num_entries -- id: free_space - type: u1 - repeat: expr - repeat-expr: len_flm_store - len_flm_store_header - len_flm_entry * num_entries instances: - len_flm_store: - value: 0x1000 len_flm_store_header: value: 16 len_flm_entry: @@ -50,5 +42,4 @@ types: type: u4 - id: offset type: u4 - - + diff --git a/common/meson.build b/common/meson.build index 13ed9fc..f4b2d98 100644 --- a/common/meson.build +++ b/common/meson.build @@ -39,6 +39,8 @@ uefitoolcommon = static_library('uefitoolcommon', 'generated/edk2_ftw.cpp', 'generated/insyde_fdc.cpp', 'generated/insyde_fdm.cpp', + 'generated/ms_slic_marker.cpp', + 'generated/ms_slic_pubkey.cpp', 'generated/phoenix_flm.cpp', 'generated/phoenix_evsa.cpp', 'generated/intel_acbp_v1.cpp', diff --git a/common/nvram.h b/common/nvram.h index 0d82e62..c7ff85d 100755 --- a/common/nvram.h +++ b/common/nvram.h @@ -70,8 +70,6 @@ extern const UByteArray NVRAM_ADDITIONAL_STORE_VOLUME_GUID; // 00504624-8A59-4EE #define NVRAM_VSS_STORE_SIGNATURE 0x53535624 // $VSS #define NVRAM_APPLE_SVS_STORE_SIGNATURE 0x53565324 // $SVS #define NVRAM_APPLE_NSS_STORE_SIGNATURE 0x53534E24 // $NSS -#define NVRAM_APPLE_SYSF_STORE_SIGNATURE 0x73797346 // Fsys -#define NVRAM_APPLE_DIAG_STORE_SIGNATURE 0x64696147 // Gaid #define NVRAM_VSS_VARIABLE_START_ID 0x55AA // Variable store header flags @@ -86,12 +84,12 @@ extern const UByteArray NVRAM_ADDITIONAL_STORE_VOLUME_GUID; // 00504624-8A59-4EE // Variable store header typedef struct VSS_VARIABLE_STORE_HEADER_ { - UINT32 Signature; // $VSS signature - UINT32 Size; // Size of variable store, including store header - UINT8 Format; // Store format state - UINT8 State; // Store health state - UINT16 Unknown; // Used in Apple $SVS varstores - UINT32 : 32; + UINT32 Signature; // Signature + UINT32 Size; // Size of variable store, including store header + UINT8 Format; // Store format state + UINT8 State; // Store health state + UINT16 Reserved; // Used in Apple $SVS varstores + UINT32 Reserved1; // Reserved } VSS_VARIABLE_STORE_HEADER; // Normal variable header @@ -142,12 +140,12 @@ typedef struct VSS_AUTH_VARIABLE_HEADER_ { } VSS_AUTH_VARIABLE_HEADER; // VSS variable states -#define NVRAM_VSS_VARIABLE_IN_DELETED_TRANSITION 0xfe // Variable is in obsolete transistion -#define NVRAM_VSS_VARIABLE_DELETED 0xfd // Variable is obsolete -#define NVRAM_VSS_VARIABLE_HEADER_VALID 0x7f // Variable has valid header -#define NVRAM_VSS_VARIABLE_ADDED 0x3f // Variable has been completely added -#define NVRAM_VSS_INTEL_VARIABLE_VALID 0xfc // Intel special variable valid -#define NVRAM_VSS_INTEL_VARIABLE_INVALID 0xf8 // Intel special variable invalid +#define NVRAM_VSS_VARIABLE_IN_DELETED_TRANSITION 0xfe // Variable is in obsolete transistion +#define NVRAM_VSS_VARIABLE_DELETED 0xfd // Variable is obsolete +#define NVRAM_VSS_VARIABLE_HEADER_VALID 0x7f // Variable has valid header +#define NVRAM_VSS_VARIABLE_ADDED 0x3f // Variable has been completely added +#define NVRAM_VSS_INTEL_VARIABLE_VALID 0xfc // Intel special variable valid +#define NVRAM_VSS_INTEL_VARIABLE_INVALID 0xf8 // Intel special variable invalid // VSS variable attributes #define NVRAM_VSS_VARIABLE_NON_VOLATILE 0x00000001 @@ -165,13 +163,8 @@ extern UString vssAttributesToUString(const UINT32 attributes); // // VSS2 variables // -#define NVRAM_VSS2_AUTH_VAR_KEY_DATABASE_GUID_PART1 0xaaf32c78 extern const UByteArray NVRAM_VSS2_AUTH_VAR_KEY_DATABASE_GUID; // AAF32C78-947B-439A-A180-2E144EC37792 - -#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 @@ -180,24 +173,23 @@ typedef struct VSS2_VARIABLE_STORE_HEADER_ { UINT32 Size; // Size of variable store, including store header UINT8 Format; // Store format state UINT8 State; // Store health state - UINT16 Unknown; - UINT32 : 32; + UINT16 Reserved; + UINT32 Reserved1; } VSS2_VARIABLE_STORE_HEADER; // VSS2 entries are 4-bytes aligned in VSS2 stores // -// _FDC region +// Insyde Factory Data Copy store // +#define INSYDE_FDC_STORE_SIGNATURE 0x4344465F -#define NVRAM_FDC_VOLUME_SIGNATURE 0x4344465F - -typedef struct FDC_VOLUME_HEADER_ { +typedef struct INSYDE_FDC_STORE_HEADER_ { UINT32 Signature; //_FDC signature UINT32 Size; // Size of the whole region EFI_FIRMWARE_VOLUME_HEADER VolumeHeader; EFI_FV_BLOCK_MAP_ENTRY FvBlockMap[2]; -} FDC_VOLUME_HEADER; +} INSYDE_FDC_STORE_HEADER; // // FTW block @@ -207,11 +199,8 @@ typedef struct FDC_VOLUME_HEADER_ { extern const UByteArray EDKII_WORKING_BLOCK_SIGNATURE_GUID; // 9E58292B-7C68-497D-0ACE-6500FD9F1B95 extern const UByteArray VSS2_WORKING_BLOCK_SIGNATURE_GUID; // 9E58292B-7C68-497D-A0CE-6500FD9F1B95 -#define NVRAM_MAIN_STORE_VOLUME_GUID_DATA1 0xFFF12B8D -#define EDKII_WORKING_BLOCK_SIGNATURE_GUID_DATA1 0x9E58292B - typedef struct EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32_ { - EFI_GUID Signature; // NVRAM_MAIN_STORE_VOLUME_GUID + EFI_GUID Signature; UINT32 Crc; // Crc32 of the header with empty Crc and State fields UINT8 State; UINT8 Reserved[3]; @@ -220,7 +209,7 @@ typedef struct EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32_ { } EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32; typedef struct EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64_ { - EFI_GUID Signature; // NVRAM_MAIN_STORE_VOLUME_GUID or EDKII_WORKING_BLOCK_SIGNATURE_GUID + EFI_GUID Signature; UINT32 Crc; // Crc32 of the header with empty Crc and State fields UINT8 State; UINT8 Reserved[3]; @@ -231,15 +220,16 @@ typedef struct EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64_ { // // Apple System Flags store // - +#define NVRAM_APPLE_SYSF_STORE_SIGNATURE 0x73797346 // Fsys +#define NVRAM_APPLE_DIAG_STORE_SIGNATURE 0x64696147 // Gaid typedef struct APPLE_SYSF_STORE_HEADER_ { UINT32 Signature; // Fsys or Gaid signature - UINT8 Unknown0; // Still unknown + UINT8 Unknown; // Still unknown UINT32 Unknown1; // Still unknown UINT16 Size; // Size of variable store } APPLE_SYSF_STORE_HEADER; -// Apple Fsys entry format +// Apple SysF entry format // UINT8 NameLength; // CHAR8 Name[]; // UINT16 DataLength; @@ -322,12 +312,8 @@ extern UString evsaAttributesToUString(const UINT32 attributes); // // Phoenix SCT Flash Map // - -#define NVRAM_PHOENIX_FLASH_MAP_SIGNATURE_PART1 0x414C465F #define NVRAM_PHOENIX_FLASH_MAP_SIGNATURE_LENGTH 10 - -// _FLASH_MAP -extern const UByteArray NVRAM_PHOENIX_FLASH_MAP_SIGNATURE; +extern const UByteArray NVRAM_PHOENIX_FLASH_MAP_SIGNATURE; // _FLASH_MAP typedef struct PHOENIX_FLASH_MAP_HEADER_ { UINT8 Signature[10]; // _FLASH_MAP signature @@ -396,10 +382,9 @@ typedef struct OEM_ACTIVATION_MARKER_ { UINT8 Signature[128]; } OEM_ACTIVATION_MARKER; -#define OEM_ACTIVATION_MARKER_TYPE 0x00000001 -#define OEM_ACTIVATION_MARKER_WINDOWS_FLAG_PART1 0x444E4957 -#define OEM_ACTIVATION_MARKER_WINDOWS_FLAG 0x2053574F444E4957UL -#define OEM_ACTIVATION_MARKER_RESERVED_BYTE 0x00 +#define OEM_ACTIVATION_MARKER_TYPE 0x00000001 +#define OEM_ACTIVATION_MARKER_WINDOWS_FLAG 0x2053574F444E4957UL // WINDOWS +#define OEM_ACTIVATION_MARKER_RESERVED_BYTE 0x00 // // Phoenix CMDB, no londer used, requires no parsing diff --git a/common/nvramparser.cpp b/common/nvramparser.cpp index 638b282..f04d431 100644 --- a/common/nvramparser.cpp +++ b/common/nvramparser.cpp @@ -31,9 +31,15 @@ #include "generated/edk2_vss2.h" #include "generated/edk2_ftw.h" #include "generated/insyde_fdc.h" +#include "generated/ms_slic_pubkey.h" +#include "generated/ms_slic_marker.h" #include "generated/phoenix_flm.h" #include "generated/phoenix_evsa.h" +#ifndef MIN +#define MIN(x, y) (((x) < (y)) ? (x) : (y)) +#endif + USTATUS NvramParser::parseNvarStore(const UModelIndex & index) { // Sanity check @@ -289,7 +295,6 @@ processing_done: } } catch (...) { - msg(usprintf("%s: unable to parse AMI NVAR storage", __FUNCTION__), index); return U_INVALID_STORE; } @@ -330,24 +335,40 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 try { if (volumeBodySize - storeOffset < sizeof(VSS_VARIABLE_STORE_HEADER)) { // No need to parse further, the rest of the volume is too small - throw 0; + goto not_vss; } - UByteArray vss = volumeBody.mid(storeOffset); + // Perform initial sanity check + const VSS_VARIABLE_STORE_HEADER* storeHeader = (const VSS_VARIABLE_STORE_HEADER*)(volumeBody.constData() + storeOffset); + if ((storeHeader->Signature != NVRAM_VSS_STORE_SIGNATURE + && storeHeader->Signature != NVRAM_APPLE_SVS_STORE_SIGNATURE + && storeHeader->Signature != NVRAM_APPLE_NSS_STORE_SIGNATURE) + || storeHeader->Format != NVRAM_VSS_VARIABLE_STORE_FORMATTED) { + // No need to parse further, not a VSS store + goto not_vss; + } + UINT32 storeSize = MIN(volumeBodySize - storeOffset, storeHeader->Size); //TODO: consider this check to become hard bail as it was before + + // This copy is required for possible FDC workaround + UByteArray vss = volumeBody.mid(storeOffset, storeSize); + // 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); + bool fdcHeaderSizeOverrideRequired = (fdcStoreSizeOverride > 0 && storeHeader->Signature == NVRAM_VSS_STORE_SIGNATURE && storeHeader->Size == 0xFFFFFFFF); if (fdcHeaderSizeOverrideRequired) { + VSS_VARIABLE_STORE_HEADER* vssHeader = (VSS_VARIABLE_STORE_HEADER*)vss.data(); originalStoreSize = vssHeader->Size; vssHeader->Size = fdcStoreSizeOverride; } + + // Try parsing VSS store candidate 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) { + VSS_VARIABLE_STORE_HEADER* vssHeader = (VSS_VARIABLE_STORE_HEADER*)vss.data(); vssHeader->Size = originalStoreSize; } @@ -355,7 +376,7 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 // 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); + model->addItem(localOffset + previousStoreEndOffset, Types::Padding, getPaddingType(outerPadding), UString("Padding"), UString(), info, UByteArray(), outerPadding, UByteArray(), Fixed, index); outerPadding.clear(); } @@ -365,16 +386,16 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 // Add info if (parsed.signature() == NVRAM_APPLE_SVS_STORE_SIGNATURE) { - name = UString("SVS store"); + name = UString("Apple SVS store"); } else if (parsed.signature() == NVRAM_APPLE_NSS_STORE_SIGNATURE) { - name = UString("NSS store"); + name = UString("Apple NSS store"); } else { name = UString("VSS store"); } - info = usprintf("Signature: %Xh (", parsed.signature()) + fourCC(parsed.signature()) + UString(")\n"); + 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", storeSize , storeSize, (UINT32)header.size(), (UINT32)header.size(), @@ -388,26 +409,26 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 UModelIndex headerIndex = model->addItem(localOffset + storeOffset, Types::VssStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, index); // Add variables - UINT32 vssVariableOffset = parsed.len_vss_store_header(); + UINT32 entryOffset = parsed.len_vss_store_header(); for (const auto & variable : *parsed.body()->variables()) { UINT8 subtype; // This is the terminating entry, needs special processing if (variable->_is_null_signature_last()) { // Add free space or padding after all variables, if needed - if (vssVariableOffset < storeSize) { - UByteArray freeSpace = vss.mid(vssVariableOffset, storeSize - vssVariableOffset); + if (entryOffset < storeSize) { + UByteArray freeSpace = vss.mid(entryOffset, storeSize - entryOffset); // 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); + model->addItem(entryOffset, 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); + model->addItem(entryOffset, Types::Padding, getPaddingType(freeSpace), UString("Padding"), UString(), info, UByteArray(), freeSpace, UByteArray(), Fixed, headerIndex); } } break; @@ -420,8 +441,8 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 // 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); + header = vss.mid(entryOffset, variable->len_intel_legacy_header() + textLengthInBytes); + body = vss.mid(entryOffset + 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); @@ -429,8 +450,8 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 } else if (variable->is_auth()) { // Authenticated 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()); + header = vss.mid(entryOffset, variable->len_auth_header() + variable->len_name_auth()); + body = vss.mid(entryOffset + 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); @@ -439,8 +460,8 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 } else if (!variable->_is_null_apple_data_crc32()) { // Apple CRC32 subtype = Subtypes::AppleVssEntry; - header = vss.mid(vssVariableOffset, variable->len_apple_header() + variable->len_name()); - body = vss.mid(vssVariableOffset + header.size(), variable->len_data()); + header = vss.mid(entryOffset, variable->len_apple_header() + variable->len_name()); + body = vss.mid(entryOffset + 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); @@ -449,8 +470,8 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 } else { // Standard subtype = Subtypes::StandardVssEntry; - header = vss.mid(vssVariableOffset, variable->len_standard_header() + variable->len_name()); - body = vss.mid(vssVariableOffset + header.size(), variable->len_data()); + header = vss.mid(entryOffset, variable->len_standard_header() + variable->len_name()); + body = vss.mid(entryOffset + 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); @@ -458,7 +479,7 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 info = UString("Variable GUID: ") + guidToUString(variableGuid, false) + "\n"; } - // Override variable type to Invalid if needed + // Override variable type to Invalid, if needed if (!variable->is_valid()) { subtype = Subtypes::InvalidVssEntry; name = UString("Invalid"); @@ -499,9 +520,9 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 } // Add tree item - model->addItem(vssVariableOffset, Types::VssEntry, subtype, name, text, info, header, body, UByteArray(), Fixed, headerIndex); + model->addItem(entryOffset, Types::VssEntry, subtype, name, text, info, header, body, UByteArray(), Fixed, headerIndex); - vssVariableOffset += variableSize; + entryOffset += variableSize; } storeOffset += storeSize - 1; @@ -510,33 +531,47 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 } catch (...) { // Parsing failed, try something else } - +not_vss: // 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; + goto not_vss2; } - UByteArray vss2 = volumeBody.mid(storeOffset); + // Perform initial sanity check + const VSS2_VARIABLE_STORE_HEADER* storeHeader = (const VSS2_VARIABLE_STORE_HEADER*)(volumeBody.constData() + storeOffset); + UByteArray guid = UByteArray((const char*)&storeHeader->Signature, sizeof(EFI_GUID)); + + if ((guid != NVRAM_VSS2_AUTH_VAR_KEY_DATABASE_GUID + && guid != NVRAM_VSS2_STORE_GUID + && guid != NVRAM_FDC_STORE_GUID) + || storeHeader->Format != NVRAM_VSS_VARIABLE_STORE_FORMATTED) { + // No need to parse further, not a VSS2 store + goto not_vss2; + } + UINT32 storeSize = MIN(volumeBodySize - storeOffset, storeHeader->Size); + + // This copy is required for possible FDC workaround + UByteArray vss2 = volumeBody.mid(storeOffset, storeSize); // 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); + bool fdcHeaderSizeOverrideRequired = (fdcStoreSizeOverride > 0 && guid == NVRAM_FDC_STORE_GUID && storeHeader->Size == 0xFFFFFFFF); if (fdcHeaderSizeOverrideRequired) { + VSS2_VARIABLE_STORE_HEADER* vss2Header = (VSS2_VARIABLE_STORE_HEADER*)vss2.data(); originalStoreSize = vss2Header->Size; vss2Header->Size = fdcStoreSizeOverride; } + // Try parsing VSS store candidate umemstream is(vss2.constData(), vss2.size()); kaitai::kstream ks(&is); edk2_vss2_t parsed(&ks); - UINT32 storeSize = parsed.vss2_size(); // Restore original store size, if needed if (fdcHeaderSizeOverrideRequired) { + VSS2_VARIABLE_STORE_HEADER* vss2Header = (VSS2_VARIABLE_STORE_HEADER*)vss2.data(); vss2Header->Size = originalStoreSize; } @@ -544,7 +579,7 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 // Check if we need to add a padding before it if (!outerPadding.isEmpty()) { 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); + model->addItem(localOffset + previousStoreEndOffset, Types::Padding, getPaddingType(outerPadding), UString("Padding"), UString(), info, UByteArray(), outerPadding, UByteArray(), Fixed, index); outerPadding.clear(); } @@ -554,10 +589,10 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 // Add info name = UString("VSS2 store"); - if (parsed.signature() == NVRAM_VSS2_AUTH_VAR_KEY_DATABASE_GUID_PART1) { + if (guid == NVRAM_VSS2_AUTH_VAR_KEY_DATABASE_GUID) { info = UString("Signature: AAF32C78-947B-439A-A180-2E144EC37792\n"); } - else if (parsed.signature() == NVRAM_FDC_STORE_GUID_PART1) { + else if (guid == NVRAM_FDC_STORE_GUID) { info = UString("Signature: DDCF3616-3275-4164-98B6-FE85707FFE7D\n"); } else { @@ -577,26 +612,26 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 UModelIndex headerIndex = model->addItem(localOffset + storeOffset, Types::Vss2Store, 0, name, UString(), info, header, body, UByteArray(), Fixed, index); // Add variables - UINT32 vss2VariableOffset = parsed.len_vss2_store_header(); + UINT32 entryOffset = parsed.len_vss2_store_header(); for (const auto & variable : *parsed.body()->variables()) { UINT8 subtype; // This is the terminating entry, needs special processing if (variable->_is_null_signature_last()) { // Add free space or padding after all variables, if needed - if (vss2VariableOffset < storeSize) { - UByteArray freeSpace = vss2.mid(vss2VariableOffset, storeSize - vss2VariableOffset); + if (entryOffset < storeSize) { + UByteArray freeSpace = vss2.mid(entryOffset, storeSize - entryOffset); // 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(vss2VariableOffset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), freeSpace, UByteArray(), Fixed, headerIndex); + model->addItem(entryOffset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), freeSpace, UByteArray(), Fixed, headerIndex); } else { // Add tree item - model->addItem(vss2VariableOffset, Types::Padding, getPaddingType(freeSpace), UString("Padding"), UString(), info, UByteArray(), freeSpace, UByteArray(), Fixed, headerIndex); + model->addItem(entryOffset, Types::Padding, getPaddingType(freeSpace), UString("Padding"), UString(), info, UByteArray(), freeSpace, UByteArray(), Fixed, headerIndex); } } break; @@ -607,8 +642,8 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 UINT32 alignmentSize; if (variable->is_auth()) { // Authenticated subtype = Subtypes::AuthVssEntry; - header = vss2.mid(vss2VariableOffset, variable->len_auth_header() + variable->len_name_auth()); - body = vss2.mid(vss2VariableOffset + header.size(), variable->len_data_auth()); + header = vss2.mid(entryOffset, variable->len_auth_header() + variable->len_name_auth()); + body = vss2.mid(entryOffset + header.size(), variable->len_data_auth()); variableSize = (UINT32)(header.size() + body.size()); alignmentSize = variable->len_alignment_padding_auth(); const EFI_GUID variableGuid = readUnaligned((const EFI_GUID*)(variable->vendor_guid().c_str())); @@ -618,8 +653,8 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 } else { // Standard subtype = Subtypes::StandardVssEntry; - header = vss2.mid(vss2VariableOffset, variable->len_standard_header() + variable->len_name()); - body = vss2.mid(vss2VariableOffset + header.size(), variable->len_data()); + header = vss2.mid(entryOffset, variable->len_standard_header() + variable->len_name()); + body = vss2.mid(entryOffset + header.size(), variable->len_data()); variableSize = (UINT32)(header.size() + body.size()); alignmentSize = variable->len_alignment_padding(); const EFI_GUID variableGuid = readUnaligned((const EFI_GUID*)(variable->vendor_guid().c_str())); @@ -661,9 +696,9 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 } // Add tree item - model->addItem(vss2VariableOffset, Types::VssEntry, subtype, name, text, info, header, body, UByteArray(), Fixed, headerIndex); + model->addItem(entryOffset, Types::VssEntry, subtype, name, text, info, header, body, UByteArray(), Fixed, headerIndex); - vss2VariableOffset += (variableSize + alignmentSize); + entryOffset += (variableSize + alignmentSize); } storeOffset += storeSize - 1; @@ -672,7 +707,7 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 } catch (...) { // Parsing failed, try something else } - +not_vss2: // Do not try any other parsers if we are here for FDC store parsing if (fdcStoreSizeOverride != 0) { continue; @@ -682,20 +717,43 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 try { 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; + goto not_ftw; } - - UByteArray ftw = volumeBody.mid(storeOffset); - umemstream is(ftw.constData(), ftw.size()); + // Perform initial sanity check + const EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32* storeHeader = (const EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32*)(volumeBody.constData() + storeOffset); + UByteArray guid = UByteArray((const char*)&storeHeader->Signature, sizeof(EFI_GUID)); + if (guid != NVRAM_MAIN_STORE_VOLUME_GUID + && guid != EDKII_WORKING_BLOCK_SIGNATURE_GUID + && guid != VSS2_WORKING_BLOCK_SIGNATURE_GUID) { + // No need to parse further, not a FTW store + goto not_ftw; + } + // Determine store size + UINT32 storeSize; + if (storeHeader->WriteQueueSize % 0x10 == 4) { + storeSize = sizeof(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32) + storeHeader->WriteQueueSize; + } + else if (storeHeader->WriteQueueSize % 0x10 == 0) { + const EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64* storeHeader64 = (const EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64*)(volumeBody.constData() + storeOffset); + storeSize = (UINT32)(sizeof(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64) + storeHeader64->WriteQueueSize); + } + else { + // No need to parse further, unknown FTW store size + msg(usprintf("%s: can not determine FTW store size for candidate at base %08Xh", __FUNCTION__, model->base(index) + localOffset + storeOffset), index); + goto not_ftw; + } + storeSize = MIN(volumeBodySize - storeOffset, storeSize); + + umemstream is(volumeBody.constData() + storeOffset, storeSize); kaitai::kstream ks(&is); edk2_ftw_t parsed(&ks); - UINT64 storeSize; - UINT64 headerSize; + + // Construct header and calculate header checksum + UINT32 headerSize; UINT32 calculatedCrc; if (parsed._is_null_len_write_queue_64()) { - headerSize = parsed.len_ftw_store_header_32(); - storeSize = headerSize + parsed.len_write_queue_32(); - header = ftw.left(headerSize); + headerSize = sizeof(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32); + header = volumeBody.mid(storeOffset, headerSize); // Check block header checksum UByteArray crcHeader = header; @@ -705,9 +763,8 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 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); + headerSize = sizeof(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64); + header = volumeBody.mid(storeOffset, headerSize); // Check block header checksum UByteArray crcHeader = header; @@ -721,17 +778,16 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 // 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); + model->addItem(localOffset + previousStoreEndOffset, Types::Padding, getPaddingType(outerPadding), UString("Padding"), UString(), info, UByteArray(), outerPadding, UByteArray(), Fixed, index); outerPadding.clear(); } - // Construct header and body - body = ftw.mid(header.size(), storeSize - header.size()); + // Construct body + body = volumeBody.mid(storeOffset + header.size(), storeSize - header.size()); // Add info - const EFI_GUID* guid = (const EFI_GUID*)header.constData(); name = UString("FTW store"); - info = UString("Signature: ") + guidToUString(*guid, false); + info = UString("Signature: ") + guidToUString(*(const EFI_GUID*)guid.constData(), 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(), @@ -748,34 +804,39 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 } catch (...) { // Parsing failed, try something else } - +not_ftw: // Insyde FDC try { - if (volumeBodySize - storeOffset < sizeof(FDC_VOLUME_HEADER)) { + if (volumeBodySize - storeOffset < sizeof(INSYDE_FDC_STORE_HEADER)) { // No need to parse further, the rest of the volume is too small - throw 0; + goto not_fdc; } + // Perform initial sanity check + const INSYDE_FDC_STORE_HEADER* storeHeader = (const INSYDE_FDC_STORE_HEADER*)(volumeBody.constData() + storeOffset); + if (storeHeader->Signature != INSYDE_FDC_STORE_SIGNATURE) { + // No need to parse further, not a FDC store + goto not_fdc; + } + UINT32 storeSize = MIN(volumeBodySize - storeOffset, storeHeader->Size); - UByteArray fdc = volumeBody.mid(storeOffset); - umemstream is(fdc.constData(), fdc.size()); + umemstream is(volumeBody.constData() + storeOffset, storeSize); kaitai::kstream ks(&is); insyde_fdc_t parsed(&ks); - UINT32 storeSize = parsed.fdc_size(); - // FDC store at current offset parsed correctly + // Insyde 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); + model->addItem(localOffset + previousStoreEndOffset, Types::Padding, getPaddingType(outerPadding), UString("Padding"), UString(), info, UByteArray(), outerPadding, UByteArray(), Fixed, index); outerPadding.clear(); } // Construct header and body - header = fdc.left(parsed.len_fdc_store_header()); - body = fdc.mid(header.size(),storeSize - header.size()); + header = volumeBody.mid(storeOffset, sizeof(INSYDE_FDC_STORE_HEADER)); + body = volumeBody.mid(storeOffset + header.size(), storeSize - header.size()); // Add info - name = UString("FDC store"); + name = UString("Insyde FDC store"); info = usprintf("Signature: _FDC\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)", storeSize, storeSize, (UINT32)header.size(), (UINT32)header.size(), @@ -793,42 +854,48 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 } catch (...) { // Parsing failed, try something else } - +not_fdc: // 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; + goto not_sysf; } + // Perform initial sanity check + const APPLE_SYSF_STORE_HEADER* storeHeader = (const APPLE_SYSF_STORE_HEADER*)(volumeBody.constData() + storeOffset); + if (storeHeader->Signature != NVRAM_APPLE_SYSF_STORE_SIGNATURE + && storeHeader->Signature != NVRAM_APPLE_DIAG_STORE_SIGNATURE) { + // No need to parse further, not a SysF/Diag store + goto not_sysf; + } + UINT32 storeSize = MIN(volumeBodySize - storeOffset, storeHeader->Size); - UByteArray sysf = volumeBody.mid(storeOffset); - umemstream is(sysf.constData(), sysf.size()); + umemstream is(volumeBody.constData() + storeOffset, storeSize); kaitai::kstream ks(&is); apple_sysf_t parsed(&ks); - UINT32 storeSize = parsed.sysf_size(); - // Apple SysF store at current offset parsed correctly + // Apple SysF/Diag store at current offset parsed correctly // Check if we need to add a padding before it if (!outerPadding.isEmpty()) { 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); + model->addItem(localOffset + previousStoreEndOffset, Types::Padding, getPaddingType(outerPadding), UString("Padding"), UString(), info, UByteArray(), outerPadding, UByteArray(), Fixed, index); outerPadding.clear(); } // Construct header and body - header = sysf.left(parsed.len_sysf_store_header()); - body = sysf.mid(header.size(), storeSize - header.size()); + header = volumeBody.mid(storeOffset, sizeof(APPLE_SYSF_STORE_HEADER)); + body = volumeBody.mid(storeOffset + header.size(), storeSize - header.size()); // Check store checksum - UINT32 calculatedCrc = (UINT32)crc32(0, (const UINT8*)sysf.constData(), storeSize - sizeof(UINT32)); + UINT32 calculatedCrc = (UINT32)crc32(0, (const UINT8*)(volumeBody.constData() + storeOffset), storeSize - sizeof(UINT32)); // Add info - if (parsed.signature() == NVRAM_APPLE_SYSF_STORE_SIGNATURE) { - name = UString("SysF store"); + if (storeHeader->Signature == NVRAM_APPLE_SYSF_STORE_SIGNATURE) { + name = UString("Apple SysF store"); info = UString("Signature: Fsys\n"); } else { - name = UString("Diag store"); + name = UString("Apple 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", @@ -843,7 +910,7 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 UModelIndex headerIndex = model->addItem(localOffset + storeOffset, Types::SysFStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, index); // Add variables - UINT32 sysfVariableOffset = parsed.len_sysf_store_header(); + UINT32 entryOffset = sizeof(APPLE_SYSF_STORE_HEADER); for (const auto & variable : *parsed.body()->variables()) { UINT8 subtype; @@ -857,11 +924,11 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 } if (variable->len_name() == 3 && variable->name() == "EOF") { - header = sysf.mid(sysfVariableOffset, 4); + header = volumeBody.mid(storeOffset + entryOffset, 4); } else { - header = sysf.mid(sysfVariableOffset, sizeof(UINT8) + (UINT32)variable->len_name() + sizeof(UINT16)); - body = sysf.mid(sysfVariableOffset + header.size(), (UINT32)variable->len_data()); + header = volumeBody.mid(storeOffset + entryOffset, sizeof(UINT8) + (UINT32)variable->len_name() + sizeof(UINT16)); + body = volumeBody.mid(storeOffset + entryOffset + header.size(), (UINT32)variable->len_data()); } // Add generic info UINT32 variableSize = (UINT32)header.size() + (UINT32)body.size(); @@ -871,25 +938,25 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 (UINT32)body.size(), (UINT32)body.size()); // Add tree item - model->addItem(sysfVariableOffset, Types::SysFEntry, subtype, name, UString(), info, header, body, UByteArray(), Fixed, headerIndex); + model->addItem(entryOffset, Types::SysFEntry, subtype, name, UString(), info, header, body, UByteArray(), Fixed, headerIndex); - sysfVariableOffset += variableSize; + entryOffset += variableSize; } // Add free space or padding after all variables, if needed - if (sysfVariableOffset < storeSize) { - UByteArray freeSpace = sysf.mid(sysfVariableOffset, storeSize - sysfVariableOffset); + if (entryOffset < storeSize) { + UByteArray freeSpace = volumeBody.mid(storeOffset + entryOffset, storeSize - entryOffset); // Add info info = usprintf("Full size: %Xh (%u)", (UINT32)freeSpace.size(), (UINT32)freeSpace.size()); // Check that remaining unparsed bytes are actually zeroes if (freeSpace.count('\x00') == freeSpace.size() - 4) { // Free space, 4 last bytes are always CRC32 // Add tree item - model->addItem(sysfVariableOffset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), freeSpace, UByteArray(), Fixed, headerIndex); + model->addItem(entryOffset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), freeSpace, UByteArray(), Fixed, headerIndex); } else { // Add tree item - model->addItem(sysfVariableOffset, Types::Padding, getPaddingType(freeSpace), UString("Padding"), UString(), info, UByteArray(), freeSpace, UByteArray(), Fixed, headerIndex); + model->addItem(entryOffset, Types::Padding, getPaddingType(freeSpace), UString("Padding"), UString(), info, UByteArray(), freeSpace, UByteArray(), Fixed, headerIndex); } } @@ -899,34 +966,40 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 } catch (...) { // Parsing failed, try something else } - - // Phoenix SCT FlashMap +not_sysf: + // Phoenix Flash Map try { - if (volumeBodySize - storeOffset < NVRAM_PHOENIX_FLASH_MAP_TOTAL_SIZE) { + if (volumeBodySize - storeOffset < sizeof(PHOENIX_FLASH_MAP_HEADER)) { // No need to parse further, the rest of the volume is too small - throw 0; + goto not_flm; } + // Perform initial sanity check + const PHOENIX_FLASH_MAP_HEADER* storeHeader = (const PHOENIX_FLASH_MAP_HEADER*)(volumeBody.constData() + storeOffset); + if (UByteArray((const char*)storeHeader->Signature, NVRAM_PHOENIX_FLASH_MAP_SIGNATURE_LENGTH) != NVRAM_PHOENIX_FLASH_MAP_SIGNATURE + || storeHeader->NumEntries > 113) { + // No need to parse further, not a Phoenix Flash Map + goto not_flm; + } + UINT32 storeSize = sizeof(PHOENIX_FLASH_MAP_HEADER) + storeHeader->NumEntries * sizeof(PHOENIX_FLASH_MAP_ENTRY); - UByteArray flm = volumeBody.mid(storeOffset); - umemstream is(flm.constData(), flm.size()); + umemstream is(volumeBody.constData() + storeOffset, storeSize); kaitai::kstream ks(&is); phoenix_flm_t parsed(&ks); - UINT32 storeSize = parsed.len_flm_store(); // Phoenix FlashMap store at current offset parsed correctly // Check if we need to add a padding before it if (!outerPadding.isEmpty()) { 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); + model->addItem(localOffset + previousStoreEndOffset, Types::Padding, getPaddingType(outerPadding), UString("Padding"), UString(), info, UByteArray(), outerPadding, UByteArray(), Fixed, index); outerPadding.clear(); } // Construct header and body - header = flm.left(parsed.len_flm_store_header()); - body = flm.mid(header.size(), storeSize - header.size()); + header = volumeBody.left(storeOffset + sizeof(PHOENIX_FLASH_MAP_HEADER)); + body = volumeBody.mid(storeOffset + header.size(), storeSize - header.size()); // Add info - name = UString("Phoenix SCT FlashMap"); + name = UString("Phoenix SCT flash map"); info = usprintf("Signature: _FLASH_MAP\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nEntries: %u\nReserved: %08Xh", storeSize, storeSize, (UINT32)header.size(), (UINT32)header.size(), @@ -938,7 +1011,7 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 UModelIndex headerIndex = model->addItem(localOffset + storeOffset, Types::PhoenixFlashMapStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, index); // Add entries - UINT32 entryOffset = parsed.len_flm_store_header(); + UINT32 entryOffset = sizeof(PHOENIX_FLASH_MAP_HEADER); for (const auto & entry : *parsed.entries()) { UINT8 subtype; @@ -955,7 +1028,7 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 const EFI_GUID guid = readUnaligned((const EFI_GUID*)entry->guid().c_str()); name = guidToUString(guid); text = phoenixFlashMapGuidToUString(guid); - header = flm.mid(entryOffset, parsed.len_flm_entry()); + header = volumeBody.mid(storeOffset + entryOffset, sizeof(PHOENIX_FLASH_MAP_ENTRY)); // Add info UINT32 entrySize = (UINT32)header.size(); @@ -974,63 +1047,50 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 entryOffset += entrySize; } - // Add free space, if needed - UByteArray freeSpace; - for (const auto & byte : *parsed.free_space()) { - freeSpace += (const char)byte; - } - if (freeSpace.size() > 0) { - // Add info - info = usprintf("Full size: %Xh (%u)", (UINT32)freeSpace.size(), (UINT32)freeSpace.size()); - - // Check that remaining unparsed bytes are actually zeroes - if (freeSpace.count(emptyByte) == freeSpace.size()) { // Free space - // Add tree item - model->addItem(entryOffset, Types::FreeSpace, 0, UString("Free space"), UString(), info, UByteArray(), freeSpace, UByteArray(), Fixed, headerIndex); - } - else { - // Add tree item - model->addItem(entryOffset, Types::Padding, getPaddingType(freeSpace), UString("Padding"), UString(), info, UByteArray(), freeSpace, UByteArray(), Fixed, headerIndex); - } - } - storeOffset += storeSize - 1; previousStoreEndOffset = storeOffset + 1; continue; } catch (...) { // Parsing failed, try something else } - - // Phoenix EVSA +not_flm: + // Phoenix EVSA store try { if (volumeBodySize - storeOffset < sizeof(EVSA_STORE_ENTRY)) { // No need to parse further, the rest of the volume is too small - throw 0; + goto not_evsa; } + // Perform initial sanity check + const EVSA_STORE_ENTRY* storeHeader = (const EVSA_STORE_ENTRY*)(volumeBody.constData() + storeOffset); + if (storeHeader->Signature != NVRAM_EVSA_STORE_SIGNATURE + || storeHeader->Header.Type != NVRAM_EVSA_ENTRY_TYPE_STORE + || storeHeader->Header.Size != sizeof(EVSA_STORE_ENTRY)) { + // No need to parse further, not a EVSA store + goto not_evsa; + } + UINT32 storeSize = MIN(volumeBodySize - storeOffset, storeHeader->StoreSize); - UByteArray evsa = volumeBody.mid(storeOffset); - umemstream is(evsa.constData(), evsa.size()); + umemstream is(volumeBody.constData() + storeOffset, storeSize); kaitai::kstream ks(&is); phoenix_evsa_t parsed(&ks); - UINT32 storeSize = parsed.len_evsa_store(); // Phoenix EVSA store at current offset parsed correctly // Check if we need to add a padding before it if (!outerPadding.isEmpty()) { 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); + model->addItem(localOffset + previousStoreEndOffset, Types::Padding, getPaddingType(outerPadding), UString("Padding"), UString(), info, UByteArray(), outerPadding, UByteArray(), Fixed, index); outerPadding.clear(); } // Construct header and body - header = evsa.left(parsed.len_evsa_store_header()); - body = evsa.mid(header.size(), storeSize - header.size()); + header = volumeBody.mid(storeOffset, sizeof(EVSA_STORE_ENTRY)); + body = volumeBody.mid(storeOffset + header.size(), storeSize - header.size()); - const EVSA_STORE_ENTRY* evsaStoreHeader = (const EVSA_STORE_ENTRY*)header.constData(); - UINT8 calculated = calculateChecksum8(((const UINT8*)evsaStoreHeader) + 2, evsaStoreHeader->Header.Size - 2); + // Calculate header checksum + UINT8 calculated = calculateChecksum8(((const UINT8*)storeHeader) + 2, storeHeader->Header.Size - 2); // Add info - name = UString("EVSA Store"); + name = UString("Phoenix EVSA store"); info = usprintf("Signature: EVSA\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: %Xh (%u)\nAttributes: %08Xh\nReserved: %08Xh\nChecksum: %02Xh", storeSize, storeSize, (UINT32)header.size(), (UINT32)header.size(), @@ -1055,7 +1115,7 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 if (entry->_is_null_checksum()) { // Add free space or padding after all variables, if needed if (entryOffset < storeSize) { - UByteArray freeSpace = evsa.mid(entryOffset, storeSize - entryOffset); + UByteArray freeSpace = volumeBody.mid(storeOffset + entryOffset, storeSize - entryOffset); // Add info info = usprintf("Full size: %Xh (%u)", (UINT32)freeSpace.size(), (UINT32)freeSpace.size()); @@ -1072,14 +1132,14 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 break; } - const EVSA_ENTRY_HEADER* entryHeader = (const EVSA_ENTRY_HEADER*)(evsa.constData() + entryOffset); + const EVSA_ENTRY_HEADER* entryHeader = (const EVSA_ENTRY_HEADER*)(volumeBody.constData() + storeOffset + entryOffset); calculated = calculateChecksum8(((const UINT8*)entryHeader) + 2, entryHeader->Size - 2); // GUID entry if (entry->entry_type() == NVRAM_EVSA_ENTRY_TYPE_GUID1 || entry->entry_type() == NVRAM_EVSA_ENTRY_TYPE_GUID2) { const phoenix_evsa_t::evsa_guid_t* guidEntry = (const phoenix_evsa_t::evsa_guid_t*)(entry->body()); - header = evsa.mid(entryOffset, sizeof(EVSA_GUID_ENTRY)); - body = evsa.mid(entryOffset + sizeof(EVSA_GUID_ENTRY), entry->len_evsa_entry() - header.size()); + header = volumeBody.mid(storeOffset + entryOffset, sizeof(EVSA_GUID_ENTRY)); + body = volumeBody.mid(storeOffset + entryOffset + sizeof(EVSA_GUID_ENTRY), entry->len_evsa_entry() - header.size()); entrySize = (UINT32)(header.size() + body.size()); EFI_GUID guid = *(const EFI_GUID*)(guidEntry->guid().c_str()); name = guidToUString(guid); @@ -1098,8 +1158,8 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 // Name entry else if (entry->entry_type() == NVRAM_EVSA_ENTRY_TYPE_NAME1 || entry->entry_type() == NVRAM_EVSA_ENTRY_TYPE_NAME2) { const phoenix_evsa_t::evsa_name_t* nameEntry = (const phoenix_evsa_t::evsa_name_t*)(entry->body()); - header = evsa.mid(entryOffset, sizeof(EVSA_NAME_ENTRY)); - body = evsa.mid(entryOffset + sizeof(EVSA_NAME_ENTRY), entry->len_evsa_entry() - header.size()); + header = volumeBody.mid(storeOffset + entryOffset, sizeof(EVSA_NAME_ENTRY)); + body = volumeBody.mid(storeOffset + entryOffset + sizeof(EVSA_NAME_ENTRY), entry->len_evsa_entry() - header.size()); entrySize = (UINT32)(header.size() + body.size()); name = uFromUcs2(body.constData()); info = UString("Name: ") + name @@ -1120,12 +1180,12 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 || entry->entry_type() == NVRAM_EVSA_ENTRY_TYPE_DATA_INVALID) { phoenix_evsa_t::evsa_data_t* dataEntry = (phoenix_evsa_t::evsa_data_t*)(entry->body()); if (dataEntry->_is_null_len_data_ext()) { - header = evsa.mid(entryOffset, sizeof(EVSA_DATA_ENTRY)); - body = evsa.mid(entryOffset + sizeof(EVSA_DATA_ENTRY), entry->len_evsa_entry() - header.size()); + header = volumeBody.mid(storeOffset + entryOffset, sizeof(EVSA_DATA_ENTRY)); + body = volumeBody.mid(storeOffset + entryOffset + sizeof(EVSA_DATA_ENTRY), entry->len_evsa_entry() - header.size()); } else { - header = evsa.mid(entryOffset, sizeof(EVSA_DATA_ENTRY_EXTENDED)); - body = evsa.mid(entryOffset + sizeof(EVSA_DATA_ENTRY_EXTENDED), dataEntry->len_data_ext()); + header = volumeBody.mid(storeOffset + entryOffset, sizeof(EVSA_DATA_ENTRY_EXTENDED)); + body = volumeBody.mid(storeOffset + entryOffset + sizeof(EVSA_DATA_ENTRY_EXTENDED), dataEntry->len_data_ext()); } entrySize = (UINT32)(header.size() + body.size()); name = UString("Data"); @@ -1216,37 +1276,42 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 } catch (...) { // Parsing failed, try something else } - - // Phoenix CMDB + not_evsa: + // Phoenix CMDB store try { if (volumeBodySize - storeOffset < NVRAM_PHOENIX_CMDB_SIZE) { // No need to parse further, the rest of the volume is too small - throw 0; + goto not_cmdb; + } + // Perform initial sanity check + const PHOENIX_CMDB_HEADER* storeHeader = (const PHOENIX_CMDB_HEADER*)(volumeBody.constData() + storeOffset); + if (storeHeader->Signature != NVRAM_PHOENIX_CMDB_HEADER_SIGNATURE) { + // No need to parse further, not a Phoenix CMDB store + goto not_cmdb; } - UINT32 storeSize = NVRAM_PHOENIX_CMDB_SIZE; - UByteArray cmdb = volumeBody.mid(storeOffset, storeSize); - // Get store header - const PHOENIX_CMDB_HEADER* cmdbHeader = (const PHOENIX_CMDB_HEADER*)cmdb.constData(); - - if (cmdbHeader->Signature != NVRAM_PHOENIX_CMDB_HEADER_SIGNATURE) { - throw 0; + // CMDB store at current offset parsed correctly + // Check if we need to add a padding before it + if (!outerPadding.isEmpty()) { + info = usprintf("Full size: %Xh (%u)", (UINT32)outerPadding.size(), (UINT32)outerPadding.size()); + model->addItem(localOffset + previousStoreEndOffset, Types::Padding, getPaddingType(outerPadding), UString("Padding"), UString(), info, UByteArray(), outerPadding, UByteArray(), Fixed, index); + outerPadding.clear(); } // Construct header and body - header = cmdb.left(cmdbHeader->TotalSize); - body = cmdb.mid(cmdbHeader->TotalSize, storeSize - cmdbHeader->TotalSize); + header = volumeBody.mid(storeOffset, storeHeader->TotalSize); + body = volumeBody.mid(storeOffset + header.size(), storeSize - header.size()); // Add info - name = UString("CMDB store"); + name = UString("Phoenix CMDB store"); info = usprintf("Signature: CMDB\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 tree item - model->addItem(storeOffset, Types::CmdbStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, index); + model->addItem(localOffset + storeOffset, Types::CmdbStore, 0, name, UString(), info, header, body, UByteArray(), Fixed, index); storeOffset += storeSize - 1; previousStoreEndOffset = storeOffset + 1; @@ -1254,43 +1319,162 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 } catch (...) { // Parsing failed, try something else } - - // Phoenix SLIC Pubkey - - // Phoenix SLIC Marker - +not_cmdb: + // SLIC PubKey + try { + if (volumeBodySize - storeOffset < sizeof(OEM_ACTIVATION_PUBKEY)) { + // No need to parse further, the rest of the volume is too small + goto not_pubkey; + } + // Perform initial sanity check + const OEM_ACTIVATION_PUBKEY* storeHeader = (const OEM_ACTIVATION_PUBKEY*)(volumeBody.constData() + storeOffset); + if (storeHeader->Magic != OEM_ACTIVATION_PUBKEY_MAGIC + || storeHeader->Type != OEM_ACTIVATION_PUBKEY_TYPE + || storeHeader->Size != sizeof(OEM_ACTIVATION_PUBKEY)) { + // No need to parse further, not a SLIC PubKey + goto not_pubkey; + } + UINT32 storeSize = sizeof(OEM_ACTIVATION_PUBKEY); + + umemstream is(volumeBody.constData() + storeOffset, storeSize); + kaitai::kstream ks(&is); + ms_slic_pubkey_t parsed(&ks); + + // SLIC PubKey at current offset parsed correctly + // Check if we need to add a padding before it + if (!outerPadding.isEmpty()) { + info = usprintf("Full size: %Xh (%u)", (UINT32)outerPadding.size(), (UINT32)outerPadding.size()); + model->addItem(localOffset + previousStoreEndOffset, Types::Padding, getPaddingType(outerPadding), UString("Padding"), UString(), info, UByteArray(), outerPadding, UByteArray(), Fixed, index); + outerPadding.clear(); + } + + // Construct header + header = volumeBody.mid(storeOffset, storeSize); + + // Add info + name = UString("SLIC pubkey"); + info = usprintf("Type: 0h\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: 0h (0)\n" + "Key type: %02Xh\nVersion: %02Xh\nAlgorithm: %08Xh\nMagic: RSA1\nBit length: %08Xh\nExponent: %08Xh", + parsed.len_pubkey(), parsed.len_pubkey(), + parsed.len_pubkey(), parsed.len_pubkey(), + parsed.key_type(), + parsed.version(), + parsed.algorithm(), + parsed.bit_length(), + parsed.exponent()); + + // Add tree item + model->addItem(localOffset + storeOffset, Types::SlicData, Subtypes::PubkeySlicData, name, UString(), info, header, UByteArray(), UByteArray(), Fixed, index); + + storeOffset += storeSize - 1; + previousStoreEndOffset = storeOffset + 1; + continue; + } catch (...) { + // Parsing failed, try something else + } +not_pubkey: + // SLIC marker + try { + if (volumeBodySize - storeOffset < sizeof(OEM_ACTIVATION_MARKER)) { + // No need to parse further, the rest of the volume is too small + goto not_marker; + } + // Perform initial sanity check + const OEM_ACTIVATION_MARKER* storeHeader = (const OEM_ACTIVATION_MARKER*)(volumeBody.constData() + storeOffset); + if (storeHeader->WindowsFlag != OEM_ACTIVATION_MARKER_WINDOWS_FLAG + || storeHeader->Type != OEM_ACTIVATION_MARKER_TYPE + || storeHeader->Size != sizeof(OEM_ACTIVATION_MARKER)) { + // No need to parse further, not a SLIC marker + goto not_marker; + } + // Check reserved bytes + for (UINT8 i = 0; i < sizeof(storeHeader->Reserved); i++) { + if (storeHeader->Reserved[i] != OEM_ACTIVATION_MARKER_RESERVED_BYTE) { + // No need to parse further, not a SLIC marker + goto not_marker; + } + } + UINT32 storeSize = sizeof(OEM_ACTIVATION_MARKER); + + umemstream is(volumeBody.constData() + storeOffset, storeSize); + kaitai::kstream ks(&is); + ms_slic_marker_t parsed(&ks); + + // SLIC marker at current offset parsed correctly + // Check if we need to add a padding before it + if (!outerPadding.isEmpty()) { + info = usprintf("Full size: %Xh (%u)", (UINT32)outerPadding.size(), (UINT32)outerPadding.size()); + model->addItem(localOffset + previousStoreEndOffset, Types::Padding, getPaddingType(outerPadding), UString("Padding"), UString(), info, UByteArray(), outerPadding, UByteArray(), Fixed, index); + outerPadding.clear(); + } + + // Construct header + header = volumeBody.mid(storeOffset, storeSize); + + // Add info + name = UString("SLIC marker"); + info = usprintf("Type: 1h\nFull size: %Xh (%u)\nHeader size: %Xh (%u)\nBody size: 0h (0)\n" + "Version: %08Xh\nOEM ID: %s\nOEM table ID: %s\nWindows flag: WINDOWS \nSLIC version: %08Xh", + parsed.len_marker(), parsed.len_marker(), + parsed.len_marker(), parsed.len_marker(), + parsed.version(), + parsed.oem_id().c_str(), + parsed.oem_table_id().c_str(), + parsed.slic_version()); + + // Add tree item + model->addItem(localOffset + storeOffset, Types::SlicData, Subtypes::MarkerSlicData, name, UString(), info, header, UByteArray(), UByteArray(), Fixed, index); + + storeOffset += storeSize - 1; + previousStoreEndOffset = storeOffset + 1; + continue; + } catch (...) { + // Parsing failed, try something else + } +not_marker: // Intel uCode try { // Check data size if (volumeBodySize - storeOffset < sizeof(INTEL_MICROCODE_HEADER)) { - throw 0; + goto not_ucode; } const UINT32 currentUint32 = readUnaligned((const UINT32*)(volumeBody.constData() + storeOffset)); - if (currentUint32 != INTEL_MICROCODE_HEADER_VERSION_1) { - throw 0; + goto not_ucode; } // Check microcode header candidate const INTEL_MICROCODE_HEADER* ucodeHeader = (const INTEL_MICROCODE_HEADER*)(volumeBody.constData() + storeOffset); if (FALSE == ffsParser->microcodeHeaderValid(ucodeHeader)) { - throw 0; + goto not_ucode; } - // Check size candidate + // Check candidate size if (ucodeHeader->TotalSize == 0) { - throw 0; + goto not_ucode; + } + + // We still have enough data left to fit the whole TotalSize + UINT32 storeSize = ucodeHeader->TotalSize; + if (volumeBodySize - storeOffset < storeSize) { + goto not_ucode; } // All checks passed, microcode found + // Check if we need to add a padding before it + if (!outerPadding.isEmpty()) { + info = usprintf("Full size: %Xh (%u)", (UINT32)outerPadding.size(), (UINT32)outerPadding.size()); + model->addItem(localOffset + previousStoreEndOffset, Types::Padding, getPaddingType(outerPadding), UString("Padding"), UString(), info, UByteArray(), outerPadding, UByteArray(), Fixed, index); + outerPadding.clear(); + } + + // Parse microcode header UByteArray ucode = volumeBody.mid(storeOffset); UModelIndex ucodeIndex; - if (U_SUCCESS != ffsParser->parseIntelMicrocodeHeader(ucode, storeOffset, index, ucodeIndex)) { - throw 0; + if (U_SUCCESS != ffsParser->parseIntelMicrocodeHeader(ucode, localOffset + storeOffset, index, ucodeIndex)) { + goto not_ucode; } - - UINT32 storeSize = ucodeHeader->TotalSize; storeOffset += storeSize - 1; previousStoreEndOffset = storeOffset + 1; @@ -1298,25 +1482,25 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 } catch (...) { // Parsing failed, try something else } - +not_ucode: // FFS volume try { // Check data size if (volumeBodySize - storeOffset < sizeof(EFI_FIRMWARE_VOLUME_HEADER)) { - throw 0; + goto not_ffs_volume; } // Check volume header candidate const EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (const EFI_FIRMWARE_VOLUME_HEADER*)(volumeBody.constData() + storeOffset); if (volumeHeader->Signature != EFI_FV_SIGNATURE) { - throw 0; + goto not_ffs_volume; } // All checks passed, volume found UByteArray volume = volumeBody.mid(storeOffset); UModelIndex volumeIndex; - if (U_SUCCESS != ffsParser->parseVolumeHeader(volume, storeOffset, index, volumeIndex)) { - throw 0; + if (U_SUCCESS != ffsParser->parseVolumeHeader(volume, localOffset + storeOffset, index, volumeIndex)) { + goto not_ffs_volume; } (VOID)ffsParser->parseVolumeBody(volumeIndex); @@ -1328,13 +1512,13 @@ USTATUS NvramParser::parseNvramVolumeBody(const UModelIndex & index,const UINT32 } catch (...) { // Parsing failed, try something else } - +not_ffs_volume: // Padding if (storeOffset < volumeBodySize) { outerPadding += volumeBody[storeOffset]; } } - + // Add padding at the very end if (!outerPadding.isEmpty()) { // Add info diff --git a/common/treemodel.h b/common/treemodel.h index b2f9e39..0d6b5ac 100644 --- a/common/treemodel.h +++ b/common/treemodel.h @@ -194,7 +194,6 @@ 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/fuzzing/CMakeLists.txt b/fuzzing/CMakeLists.txt index 37c3882..b05b1ac 100644 --- a/fuzzing/CMakeLists.txt +++ b/fuzzing/CMakeLists.txt @@ -38,6 +38,8 @@ SET(PROJECT_SOURCES ../common/generated/edk2_ftw.cpp ../common/generated/insyde_fdc.cpp ../common/generated/insyde_fdm.cpp + ../common/generated/ms_slic_marker.cpp + ../common/generated/ms_slic_pubkey.cpp ../common/generated/phoenix_flm.cpp ../common/generated/phoenix_evsa.cpp ../common/generated/intel_acbp_v1.cpp