jh7110_uboot_spl.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. #define _GNU_SOURCE
  2. #include <sys/types.h>
  3. #include <sys/stat.h>
  4. #include <fcntl.h>
  5. #include <getopt.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <stdint.h>
  9. #include <string.h>
  10. #include <stdbool.h>
  11. #include <unistd.h>
  12. #include <endian.h>
  13. #include <errno.h>
  14. #include <limits.h>
  15. #define NOSIZE ((size_t)-1)
  16. extern uint32_t crc32(uint32_t iv, uint32_t sv, const void *data, size_t n);
  17. extern uint32_t crc32_final(uint32_t iv);
  18. /* all uint32_t ends up little endian in output header */
  19. struct __attribute__((__packed__)) ubootsplhdr {
  20. uint32_t sofs; /* offset of spl header: 64+256+256 = 0x240 */
  21. uint32_t bofs; /* SBL_BAK_OFFSET: Offset of backup SBL from Flash info start (from input_sbl_normal.cfg) */
  22. uint8_t zro2[636];
  23. uint32_t vers; /* version: shall be 0x01010101
  24. * (from https://doc-en.rvspace.org/VisionFive2/SWTRM/VisionFive2_SW_TRM/create_spl.html) */
  25. uint32_t fsiz; /* u-boot-spl.bin size in bytes */
  26. uint32_t res1; /* Offset from HDR to SPL_IMAGE, 0x400 (00 04 00 00) currently */
  27. uint32_t crcs; /* CRC32 of u-boot-spl.bin */
  28. uint8_t zro3[364];
  29. };
  30. struct hdr_conf_t {
  31. const char name[PATH_MAX];
  32. uint32_t vers;
  33. uint32_t bofs;
  34. bool creat_hdr_flag;
  35. };
  36. static struct ubootsplhdr ubsplhdr;
  37. static struct hdr_conf_t g_hdr_conf;
  38. static char ubootspl[131072-sizeof(struct ubootsplhdr)+1];
  39. static char outpath[PATH_MAX];
  40. #define DEFVERSID 0x01010101
  41. #define DEFBACKUP 0x200000U
  42. static void xerror(int errnoval, const char *s)
  43. {
  44. if (errnoval) perror(s);
  45. else fprintf(stderr, "%s\n", s);
  46. exit(2);
  47. }
  48. static void usage(void)
  49. {
  50. const char help[] = {
  51. "\n StarFive spl tool\n\n"
  52. "usage:\n"
  53. "-c, --creat-splhdr creat spl hdr\n"
  54. "-a, --spl-bak-addr set backup SPL addr(default: 0x200000)\n"
  55. "-v, --version set version (default: 0x01010101)\n"
  56. "-f, --file input file name(spl/img)\n"
  57. "-h, --help show this information\n"
  58. };
  59. puts(help);
  60. }
  61. static int parse_args(int argc, char **argv)
  62. {
  63. uint32_t v;
  64. enum {
  65. OPTION_CREAD_HDR = 1,
  66. OPTION_SBL_BAK_OFFSET,
  67. OPTION_VERSION,
  68. OPTION_FILENAME,
  69. OPTION_HELP,
  70. };
  71. static struct option long_options[] =
  72. {
  73. {"creat-splhdr" , no_argument, NULL, OPTION_CREAD_HDR},
  74. {"spl-bak-addr" , required_argument, NULL, OPTION_SBL_BAK_OFFSET},
  75. {"version", required_argument, NULL, OPTION_VERSION},
  76. {"file", required_argument, NULL, OPTION_FILENAME},
  77. {"help", no_argument, NULL, OPTION_HELP},
  78. {0, 0, 0, 0}
  79. };
  80. while (1)
  81. {
  82. /* getopt_long stores the option index here. */
  83. int option_index = 0;
  84. int c = getopt_long(argc, argv, "cio:v:f:h", long_options, &option_index);
  85. /* Detect the end of the options. */
  86. if (c == -1)
  87. break;
  88. switch (c) {
  89. case 0:
  90. /* If this option set a flag, do nothing else now. */
  91. if (long_options[option_index].flag != 0)
  92. break;
  93. case 'c':
  94. case OPTION_CREAD_HDR:
  95. g_hdr_conf.creat_hdr_flag = true;
  96. break;
  97. case 'a':
  98. case OPTION_SBL_BAK_OFFSET:
  99. v = (uint32_t)strtoul(optarg, NULL, 16);
  100. v = htole32(v);
  101. g_hdr_conf.bofs = v;
  102. break;
  103. case 'v':
  104. case OPTION_VERSION:
  105. v = (uint32_t)strtoul(optarg, NULL, 16);
  106. v = htole32(v);
  107. g_hdr_conf.vers = v;
  108. break;
  109. case 'f':
  110. case OPTION_FILENAME:
  111. strcpy((char*)g_hdr_conf.name, optarg);
  112. break;
  113. case 'h':
  114. case OPTION_HELP:
  115. usage();
  116. break;
  117. default:
  118. usage();
  119. break;
  120. }
  121. }
  122. return 0;
  123. }
  124. int spl_creat_hdr(struct hdr_conf_t *conf)
  125. {
  126. int fd;
  127. uint32_t v;
  128. size_t sz;
  129. if (!conf->creat_hdr_flag)
  130. return 0;
  131. ubsplhdr.sofs = htole32(0x240U);
  132. ubsplhdr.res1 = htole32(0x400U);
  133. ubsplhdr.bofs = conf->bofs ? conf->bofs : htole32(DEFBACKUP);
  134. ubsplhdr.vers = conf->vers ? conf->vers : htole32(DEFVERSID);
  135. printf("ubsplhdr.sofs:%#x, ubsplhdr.bofs:%#x, ubsplhdr.vers:%#x name:%s\n",
  136. ubsplhdr.sofs, ubsplhdr.bofs, ubsplhdr.vers, conf->name);
  137. fd = open(conf->name, O_RDONLY);
  138. if (fd == -1) xerror(errno, conf->name);
  139. sz = (size_t)read(fd, ubootspl, sizeof(ubootspl));
  140. if (sz == NOSIZE) xerror(errno, conf->name);
  141. if (sz >= (sizeof(ubootspl)))
  142. xerror(0, "File too large! Please rebuild your SPL with -Os. Maximum allowed size is 130048 bytes.");
  143. v = htole32((uint32_t)sz);
  144. ubsplhdr.fsiz = v;
  145. close(fd);
  146. snprintf(outpath, sizeof(outpath), "%s.normal.out", conf->name);
  147. fd = creat(outpath, 0666);
  148. if (fd == -1) xerror(errno, outpath);
  149. v = crc32(~0U, 0x04c11db7U, ubootspl, sz);
  150. v = crc32_final(v);
  151. v = htole32(v);
  152. ubsplhdr.crcs = v;
  153. write(fd, &ubsplhdr, sizeof(struct ubootsplhdr));
  154. write(fd, ubootspl, sz);
  155. close(fd);
  156. printf("SPL written to %s successfully.\n", outpath);
  157. return 0;
  158. }
  159. int main(int argc, char **argv)
  160. {
  161. parse_args(argc, argv);
  162. spl_creat_hdr(&g_hdr_conf);
  163. }