commit 047062a2f005cb2382e7ab336c79e084f4dc6567 from: Aleksey Ryndin date: Thu Mar 07 10:01:50 2024 UTC Dump and validate eGON.BT0 image header commit - 1f373332ee43b7a9c5af2a4a97a736ab63073c96 commit + 047062a2f005cb2382e7ab336c79e084f4dc6567 blob - 553f50f8707eccbfe3c691978635429358441118 blob + 04e7a99f6764824e1494ae9bc5c2eefef0084bff --- tools/img_eGON.BT0/img_eGON.BT0.cc +++ tools/img_eGON.BT0/img_eGON.BT0.cc @@ -6,10 +6,14 @@ #include #include #include +#include +#include namespace { + + /** Non-copiable objects */ struct NonCopiable { @@ -33,6 +37,12 @@ class UniqueFd : public NonCopiable (private) }; +char printable(char ch) +{ + return std::isprint(ch) ? ch : '.'; +} + + struct CommandLineArguments { const char *m_image_file_path{nullptr}; @@ -80,18 +90,25 @@ parse_command_line( } -char printable(char ch) +namespace header { - return ch ? (std::isprint(ch) ? ch : '?') : ' '; -} +constexpr auto MAGIC_LENGTH{8}; +const std::array MAGIC{'e', 'G', 'O', 'N', '.', 'B', 'T', '0'}; + +constexpr auto SPL_SIGNATURE_LENGTH{3}; +const std::array SPL_SIGNATURE{'S', 'P', 'L'}; + +constexpr uint8_t SPL_VERSION_0_2 = 0x02; + struct Header { uint32_t m_jump_instruction; - uint8_t m_magic[8]; + uint8_t m_magic[MAGIC_LENGTH]; uint32_t m_checksum; uint32_t m_length; - uint8_t m_spl_signature[4]; + uint8_t m_spl_signature[SPL_SIGNATURE_LENGTH]; + uint8_t m_spl_version; uint32_t m_zero18; uint32_t m_zero1C; uint32_t m_name_offset; @@ -100,37 +117,51 @@ struct Header { uint8_t m_strings[52]; }; +constexpr uint32_t JUMP_INSTRUCTION{0xea000000 | ((sizeof(Header) / 4) - 2)}; -bool run(int argc, char *argv[]) -{ - CommandLineArguments args; - if (!parse_command_line(argc, argv, args)) - { - usage(argv[0]); - return false; - } - const UniqueFd image_file{open(args.m_image_file_path, O_RDONLY)}; +bool validate_and_dump(const char *image_file_path) +{ + const UniqueFd image_file{open(image_file_path, O_RDONLY)}; if (!image_file) { const auto error{errno}; - std::cerr << "Open file \"" << args.m_image_file_path << "\" failed. " + std::cerr << "Open file \"" << image_file_path << "\" failed. " << "Error code (" << std::dec << error << "): " << strerror(error) << std::endl; return false; } Header header{}; - if (read(image_file.get(), &header, sizeof(header)) == -1) + const auto readed{read(image_file.get(), &header, sizeof(header))}; + if (readed != sizeof(header)) { const auto error{errno}; - std::cerr << "Read file \"" << args.m_image_file_path << "\" failed. " - << "Error code (" << std::dec << error << "): " << strerror(error) << std::endl; + std::cerr << "Read file \"" << image_file_path << "\" failed. "; + if (readed == -1) + std::cerr << "Error code (" << std::dec << error << "): " + << strerror(error) << std::endl; + else + std::cerr << "Probably the file is too small"; return false; } + bool ret_value = true; + + std::cout << std::endl << "# Header (size=0x" << std::hex << sizeof(header) + << "," << std::dec << sizeof(header) << ")" << std::endl << std::endl; + std::cout << "+0x00 Jump instruction : 0x" << std::hex << std::setw(8) << std::setfill('0') << header.m_jump_instruction << std::endl; + if (header.m_jump_instruction == JUMP_INSTRUCTION) + { + std::cout << " (v) OK" << std::endl; + } + else + { + std::cout << " (x) Unexpected" << std::endl; + ret_value = false; + } std::cout << "+0x04 Magic :"; for (const auto ch : header.m_magic) @@ -142,6 +173,16 @@ bool run(int argc, char *argv[]) std::cout << printable(ch); std::cout << std::endl; + if (std::equal(MAGIC.cbegin(), MAGIC.cend(), &header.m_magic[0])) + { + std::cout << " (v) OK" << std::endl; + } + else + { + std::cout << " (x) Unexpected" << std::endl; + ret_value = false; + } + std::cout << "+0x0C Checksum : 0x" << std::hex << std::setw(8) << std::setfill('0') << header.m_checksum << std::endl; @@ -149,7 +190,17 @@ bool run(int argc, char *argv[]) std::cout << "+0x10 Length : 0x" << std::hex << std::setw(8) << std::setfill('0') << header.m_length << ", " << std::dec << header.m_length << std::endl; + if ((header.m_length & 511) == 0) + { + std::cout << " (v) OK" << std::endl; + } + else + { + std::cout << " (x) Unexpected" << std::endl; + ret_value = false; + } + std::cout << "+0x14 SPL signature :"; for (const auto ch : header.m_spl_signature) std::cout << " 0x" << std::hex << std::setw(2) << std::setfill('0') @@ -160,6 +211,30 @@ bool run(int argc, char *argv[]) std::cout << printable(ch); std::cout << std::endl; + if (std::equal(SPL_SIGNATURE.cbegin(), SPL_SIGNATURE.cend(), &header.m_spl_signature[0])) + { + std::cout << " (v) OK" << std::endl; + } + else + { + std::cout << " (x) Unexpected" << std::endl; + ret_value = false; + } + + std::cout << "+0x17 SPL version : 0x" + << std::hex << std::setw(2) << std::setfill('0') << uint32_t(header.m_spl_version) + << ", " << std::dec << uint32_t(header.m_spl_version) << std::endl; + + if (header.m_spl_version == SPL_VERSION_0_2) + { + std::cout << " (v) OK, v0.2" << std::endl; + } + else + { + std::cout << " (x) Unexpected" << std::endl; + ret_value = false; + } + std::cout << "+0x18 : 0x" << std::hex << std::setw(8) << std::setfill('0') << header.m_zero18 << std::endl; @@ -197,13 +272,22 @@ bool run(int argc, char *argv[]) std::cout << printable(ch); std::cout << std::endl; - return true; + return ret_value; } +} // namespace header + + +bool run(const CommandLineArguments &args) +{ + return header::validate_and_dump(args.m_image_file_path); } +} + + extern "C" int main( @@ -211,5 +295,11 @@ main( /* in */ char *argv[] ) { - return run(argc, argv) ? 0 : 1; + CommandLineArguments args; + if (!parse_command_line(argc, argv, args)) + { + usage(argv[0]); + return 1; + } + return run(args) ? 0 : 1; }