commit 29b6aefcc50d941aa40b4884b28a3ecc95f2752b from: Aleksey Ryndin date: Mon Mar 11 16:48:40 2024 UTC Append img_eGON.BT0: create new image option commit - 621f0e86e870df27570c60b2d36a870213fa06e3 commit + 29b6aefcc50d941aa40b4884b28a3ecc95f2752b blob - fa81d1fc96717d9898057354443c6ea1450fcc7b blob + 718b1ffbaef1959e058b15834d9403eea4b414d1 --- tools/img_eGON.BT0/img_eGON.BT0.cc +++ tools/img_eGON.BT0/img_eGON.BT0.cc @@ -2,13 +2,16 @@ #include #include #include +#include +#include #include #include #include #include #include #include +#include namespace @@ -47,6 +50,7 @@ char printable(char ch) struct CommandLineArguments { const char *m_image_file_path{nullptr}; + const char *m_bin_file_path{nullptr}; }; @@ -60,7 +64,9 @@ void usage(const char *program) std::cerr << "Usage: " << file_name << " [OPTS]" << std::endl << std::endl; std::cerr << "OPTS may be: " << std::endl; - std::cerr << "\t-f FILE : image file path" << std::endl; + std::cerr << "\t-f IMG_FILE : image file header (required)" << std::endl; + std::cerr << "\t-c BIN_FILE : create IMG_FILE from BIN_FILE"<< std::endl; + std::cerr << "\t if not specified: check and dump IMG_FILE" << std::endl; } @@ -72,11 +78,14 @@ parse_command_line( ) { int ch; - while ((ch = getopt(argc, argv, "f:")) != -1) { + while ((ch = getopt(argc, argv, "f:c:")) != -1) { switch (ch) { case 'f': args.m_image_file_path = optarg; break; + case 'c': + args.m_bin_file_path = optarg; + break; default: std::cerr << "Invalid command line" << std::endl; return false; @@ -113,7 +122,7 @@ struct Header { uint8_t m_spl_signature[SPL_SIGNATURE_LENGTH]; uint8_t m_spl_version; uint32_t m_zero18; - uint32_t m_zero1C; + uint32_t m_zero1c; uint32_t m_name_offset; uint32_t m_zero24; uint32_t m_zero28; @@ -122,7 +131,9 @@ struct Header { constexpr uint32_t JUMP_INSTRUCTION{0xea000000 | ((sizeof(Header) / 4) - 2)}; +const std::string NAME = "sun50i-a64-pinephone-1.2"; + bool validate_and_dump(const char *image_file_path) { const UniqueFd image_file{open(image_file_path, O_RDONLY)}; @@ -135,12 +146,12 @@ bool validate_and_dump(const char *image_file_path) } Header header{}; - const auto readed{read(image_file.get(), &header, sizeof(header))}; - if (readed != sizeof(header)) + const auto read_res{read(image_file.get(), &header, sizeof(header))}; + if (read_res != sizeof(header)) { const auto error{errno}; std::cerr << "Read file \"" << image_file_path << "\" failed. "; - if (readed == -1) + if (read_res == -1) std::cerr << "Error code (" << std::dec << error << "): " << strerror(error) << std::endl; else @@ -279,12 +290,22 @@ bool validate_and_dump(const char *image_file_path) std::cout << "+0x1c : 0x" << std::hex << std::setw(8) << std::setfill('0') - << header.m_zero1C << std::endl; + << header.m_zero1c << std::endl; std::cout << "+0x20 Name offset : 0x" << std::hex << std::setw(8) << std::setfill('0') << header.m_name_offset << ", " << std::dec << header.m_name_offset; std::cout << std::endl; + if (header.m_name_offset >= offsetof(Header, m_name_offset) && + header.m_name_offset < (offsetof(Header, m_name_offset) + sizeof(header.m_strings))) + { + std::cout << " (v) OK" << std::endl; + } + else + { + std::cout << " (x) Unexpected" << std::endl; + ret_value = false; + } std::cout << "+0x24 : 0x" << std::hex << std::setw(8) << std::setfill('0') @@ -314,11 +335,95 @@ bool validate_and_dump(const char *image_file_path) } +bool +create( + const char *from_bin_file_path, + const char *to_image_file_path +) +{ + struct stat bin_file_sb{}; + if (stat(from_bin_file_path, &bin_file_sb) == -1) + { + const auto error{errno}; + std::cerr << "Stat file \"" << from_bin_file_path << "\" failed. " + << "Error code (" << std::dec << error << "): " << strerror(error) << std::endl; + return false; + } + // round up 512 + const uint32_t rounded_size = (uint32_t(bin_file_sb.st_size) + 511) & ~511; + if (bin_file_sb.st_size > rounded_size) + { + std::cerr << "Input binary file \"" << from_bin_file_path << "\" is too large." << std::endl; + return false; + } + + const uint32_t binary_size{uint32_t(sizeof(Header)) + rounded_size}; + std::vector binary; + binary.resize(binary_size); + + const UniqueFd bin_file{open(from_bin_file_path, O_RDONLY)}; + if (!bin_file) + { + const auto error{errno}; + std::cerr << "Open file \"" << from_bin_file_path << "\" failed. " + << "Error code (" << std::dec << error << "): " << strerror(error) << std::endl; + return false; + } + + const auto read_res{read(bin_file.get(), &binary[sizeof(Header)], bin_file_sb.st_size)}; + if (read_res != bin_file_sb.st_size) + { + const auto error{errno}; + std::cerr << "Read file \"" << from_bin_file_path << "\" failed."; + if (read_res == -1) + std::cerr << " Error code (" << std::dec << error << "): " << strerror(error); + std::cerr << std::endl; + return false; + } + + Header &header = *reinterpret_cast
(&binary[0]); + header.m_jump_instruction = JUMP_INSTRUCTION; + std::copy(MAGIC.cbegin(), MAGIC.cend(), &header.m_magic[0]); + header.m_checksum = CHECKSUM_INITIAL; + header.m_length = rounded_size; + std::copy(SPL_SIGNATURE.cbegin(), SPL_SIGNATURE.cend(), &header.m_spl_signature[0]); + header.m_spl_version = SPL_VERSION_0_2; + header.m_name_offset = offsetof(Header, m_strings); + std::copy(NAME.cbegin(), NAME.cend(), &header.m_strings[0]); + + uint32_t checksum = 0; + for (uint32_t i = 0; i < binary_size / sizeof(uint32_t); ++i) + checksum += reinterpret_cast(&binary[0])[i]; + header.m_checksum = checksum; + + const UniqueFd image_file{open(to_image_file_path, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG | S_IROTH)}; + if (!image_file) + { + const auto error{errno}; + std::cerr << "Create file \"" << to_image_file_path << "\" failed. " + << "Error code (" << std::dec << error << "): " << strerror(error) << std::endl; + return false; + } + const auto write_res{write(image_file.get(), &binary[0], binary_size)}; + if (write_res != binary_size) + { + const auto error{errno}; + std::cerr << "Write file \"" << to_image_file_path << "\" failed."; + if (read_res == -1) + std::cerr << " Error code (" << std::dec << error << "): " << strerror(error); + std::cerr << std::endl; + return false; + } + return true; +} + } // namespace header bool run(const CommandLineArguments &args) { + if (args.m_bin_file_path) + return header::create(args.m_bin_file_path, args.m_image_file_path); return header::validate_and_dump(args.m_image_file_path); }