Commit Diff


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 <string.h>
 #include <fcntl.h>
 #include <errno.h>
+#include <sys/stat.h>
 
+#include <cstddef>
 #include <iostream>
 #include <iomanip>
 #include <memory>
 #include <array>
 #include <algorithm>
 #include <vector>
+#include <string>
 
 
 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<uint8_t> 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<Header *>(&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<const uint32_t *>(&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);
 }