mkbootimg.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. /* tools/mkbootimg/mkbootimg.c
  2. **
  3. ** Copyright 2007, The Android Open Source Project
  4. ** Copyright 2013, Sony Mobile Communications
  5. **
  6. ** Licensed under the Apache License, Version 2.0 (the "License");
  7. ** you may not use this file except in compliance with the License.
  8. ** You may obtain a copy of the License at
  9. **
  10. ** http://www.apache.org/licenses/LICENSE-2.0
  11. **
  12. ** Unless required by applicable law or agreed to in writing, software
  13. ** distributed under the License is distributed on an "AS IS" BASIS,
  14. ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. ** See the License for the specific language governing permissions and
  16. ** limitations under the License.
  17. **
  18. ** June 2014, Ketut Putu Kumajaya
  19. ** Modified for Samsung Exynos DTBH, based on mkqcdtbootimg from Sony
  20. */
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <unistd.h>
  25. #include <fcntl.h>
  26. #include <errno.h>
  27. #include <limits.h>
  28. #include <sys/types.h>
  29. #include <arpa/inet.h>
  30. #include <assert.h>
  31. #include <dirent.h>
  32. #include <err.h>
  33. #include <stdint.h>
  34. #include <dtbimg.h>
  35. #include <openssl/sha.h>
  36. #include "bootimg.h"
  37. static void *load_file(const char *fn, unsigned *_sz)
  38. {
  39. char *data;
  40. int sz;
  41. int fd;
  42. data = 0;
  43. fd = open(fn, O_RDONLY);
  44. if(fd < 0) return 0;
  45. sz = lseek(fd, 0, SEEK_END);
  46. if(sz < 0) goto oops;
  47. if(lseek(fd, 0, SEEK_SET) != 0) goto oops;
  48. data = (char*) malloc(sz);
  49. if(data == 0) goto oops;
  50. if(read(fd, data, sz) != sz) goto oops;
  51. close(fd);
  52. if(_sz) *_sz = sz;
  53. return data;
  54. oops:
  55. close(fd);
  56. if(data != 0) free(data);
  57. return 0;
  58. }
  59. int usage(void)
  60. {
  61. fprintf(stderr,"usage: mkbootimg\n"
  62. " --kernel <filename>\n"
  63. " --ramdisk <filename>\n"
  64. " [ --second <2ndbootloader-filename> ]\n"
  65. " [ --cmdline <kernel-commandline> ]\n"
  66. " [ --board <boardname> ]\n"
  67. " [ --base <address> ]\n"
  68. " [ --pagesize <pagesize> ]\n"
  69. " [ --ramdisk_offset <address> ]\n"
  70. " [ --dt_dir <dtb path> ]\n"
  71. " [ --dt <filename> ]\n"
  72. " [ --signature <filename> ]\n"
  73. " -o|--output <filename>\n"
  74. );
  75. return 1;
  76. }
  77. static unsigned char padding[131072] = { 0, };
  78. int write_padding(int fd, unsigned pagesize, unsigned itemsize)
  79. {
  80. unsigned pagemask = pagesize - 1;
  81. unsigned count;
  82. if((itemsize & pagemask) == 0) {
  83. return 0;
  84. }
  85. count = pagesize - (itemsize & pagemask);
  86. if(write(fd, padding, count) != count) {
  87. return -1;
  88. } else {
  89. return 0;
  90. }
  91. }
  92. int main(int argc, char **argv)
  93. {
  94. boot_img_hdr hdr;
  95. char *kernel_fn = 0;
  96. void *kernel_data = 0;
  97. char *ramdisk_fn = 0;
  98. void *ramdisk_data = 0;
  99. char *second_fn = 0;
  100. void *second_data = 0;
  101. char *cmdline = "";
  102. char *bootimg = 0;
  103. char *board = "";
  104. char *dt_dir = 0;
  105. char *dt_fn = 0;
  106. void *dt_data = 0;
  107. char *sig_fn = 0;
  108. void *sig_data = 0;
  109. unsigned pagesize = 2048;
  110. int fd;
  111. SHA_CTX ctx;
  112. uint8_t sha[SHA_DIGEST_LENGTH];
  113. unsigned base = 0x10000000;
  114. unsigned kernel_offset = 0x00008000;
  115. unsigned ramdisk_offset = 0x01000000;
  116. unsigned second_offset = 0x00f00000;
  117. unsigned tags_offset = 0x00000100;
  118. argc--;
  119. argv++;
  120. memset(&hdr, 0, sizeof(hdr));
  121. while(argc > 0){
  122. char *arg = argv[0];
  123. char *val = argv[1];
  124. if(argc < 2) {
  125. return usage();
  126. }
  127. argc -= 2;
  128. argv += 2;
  129. if(!strcmp(arg, "--output") || !strcmp(arg, "-o")) {
  130. bootimg = val;
  131. } else if(!strcmp(arg, "--kernel")) {
  132. kernel_fn = val;
  133. } else if(!strcmp(arg, "--ramdisk")) {
  134. ramdisk_fn = val;
  135. } else if(!strcmp(arg, "--second")) {
  136. second_fn = val;
  137. } else if(!strcmp(arg, "--cmdline")) {
  138. cmdline = val;
  139. } else if(!strcmp(arg, "--base")) {
  140. base = strtoul(val, 0, 16);
  141. } else if(!strcmp(arg, "--kernel_offset")) {
  142. kernel_offset = strtoul(val, 0, 16);
  143. } else if(!strcmp(arg, "--ramdisk_offset")) {
  144. ramdisk_offset = strtoul(val, 0, 16);
  145. } else if(!strcmp(arg, "--second_offset")) {
  146. second_offset = strtoul(val, 0, 16);
  147. } else if(!strcmp(arg, "--tags_offset")) {
  148. tags_offset = strtoul(val, 0, 16);
  149. } else if(!strcmp(arg, "--board")) {
  150. board = val;
  151. } else if(!strcmp(arg,"--pagesize")) {
  152. pagesize = strtoul(val, 0, 10);
  153. if ((pagesize != 2048) && (pagesize != 4096) && (pagesize != 8192) && (pagesize != 16384) && (pagesize != 32768) && (pagesize != 65536) && (pagesize != 131072)) {
  154. fprintf(stderr,"error: unsupported page size %d\n", pagesize);
  155. return -1;
  156. }
  157. } else if (!strcmp(arg, "--dt_dir")) {
  158. dt_dir = val;
  159. } else if(!strcmp(arg, "--dt")) {
  160. dt_fn = val;
  161. } else if(!strcmp(arg, "--signature")) {
  162. sig_fn = val;
  163. } else {
  164. return usage();
  165. }
  166. }
  167. hdr.page_size = pagesize;
  168. hdr.kernel_addr = base + kernel_offset;
  169. hdr.ramdisk_addr = base + ramdisk_offset;
  170. hdr.second_addr = base + second_offset;
  171. hdr.tags_addr = base + tags_offset;
  172. if (dt_dir && dt_fn) {
  173. fprintf(stderr,"error: don't use both --dt_dir and --dt option\n");
  174. return usage();
  175. }
  176. if(bootimg == 0) {
  177. fprintf(stderr,"error: no output filename specified\n");
  178. return usage();
  179. }
  180. if(kernel_fn == 0) {
  181. fprintf(stderr,"error: no kernel image specified\n");
  182. return usage();
  183. }
  184. if(ramdisk_fn == 0) {
  185. fprintf(stderr,"error: no ramdisk image specified\n");
  186. return usage();
  187. }
  188. if(strlen(board) >= BOOT_NAME_SIZE) {
  189. fprintf(stderr,"error: board name too large\n");
  190. return usage();
  191. }
  192. strcpy(hdr.name, board);
  193. memcpy(hdr.magic, BOOT_MAGIC, BOOT_MAGIC_SIZE);
  194. if(strlen(cmdline) > (BOOT_ARGS_SIZE - 1)) {
  195. fprintf(stderr,"error: kernel commandline too large\n");
  196. return 1;
  197. }
  198. strcpy((char*)hdr.cmdline, cmdline);
  199. kernel_data = load_file(kernel_fn, &hdr.kernel_size);
  200. if(kernel_data == 0) {
  201. fprintf(stderr,"error: could not load kernel '%s'\n", kernel_fn);
  202. return 1;
  203. }
  204. if(!strcmp(ramdisk_fn,"NONE")) {
  205. ramdisk_data = 0;
  206. hdr.ramdisk_size = 0;
  207. } else {
  208. ramdisk_data = load_file(ramdisk_fn, &hdr.ramdisk_size);
  209. if(ramdisk_data == 0) {
  210. fprintf(stderr,"error: could not load ramdisk '%s'\n", ramdisk_fn);
  211. return 1;
  212. }
  213. }
  214. if(second_fn) {
  215. second_data = load_file(second_fn, &hdr.second_size);
  216. if(second_data == 0) {
  217. fprintf(stderr,"error: could not load secondstage '%s'\n", second_fn);
  218. return 1;
  219. }
  220. }
  221. if (dt_dir) {
  222. dt_data = load_dtbh_block(dt_dir, pagesize, &hdr.dt_size);
  223. if (dt_data == 0) {
  224. fprintf(stderr, "error: could not load device tree blobs '%s'\n", dt_dir);
  225. return 1;
  226. }
  227. }
  228. if(dt_fn) {
  229. dt_data = load_file(dt_fn, &hdr.dt_size);
  230. if (dt_data == 0) {
  231. fprintf(stderr,"error: could not load device tree image '%s'\n", dt_fn);
  232. return 1;
  233. }
  234. }
  235. if(sig_fn) {
  236. sig_data = load_file(sig_fn, 0);
  237. if (sig_data == 0) {
  238. fprintf(stderr,"error: could not load signature '%s'\n", sig_fn);
  239. return 1;
  240. }
  241. }
  242. /* put a hash of the contents in the header so boot images can be
  243. * differentiated based on their first 2k.
  244. */
  245. SHA1_Init(&ctx);
  246. SHA1_Update(&ctx, kernel_data, hdr.kernel_size);
  247. SHA1_Update(&ctx, &hdr.kernel_size, sizeof(hdr.kernel_size));
  248. SHA1_Update(&ctx, ramdisk_data, hdr.ramdisk_size);
  249. SHA1_Update(&ctx, &hdr.ramdisk_size, sizeof(hdr.ramdisk_size));
  250. SHA1_Update(&ctx, second_data, hdr.second_size);
  251. SHA1_Update(&ctx, &hdr.second_size, sizeof(hdr.second_size));
  252. if(dt_data) {
  253. SHA1_Update(&ctx, dt_data, hdr.dt_size);
  254. SHA1_Update(&ctx, &hdr.dt_size, sizeof(hdr.dt_size));
  255. }
  256. SHA1_Final(sha, &ctx);
  257. memcpy(hdr.id, sha,
  258. SHA_DIGEST_LENGTH > sizeof(hdr.id) ? sizeof(hdr.id) : SHA_DIGEST_LENGTH);
  259. fd = open(bootimg, O_CREAT | O_TRUNC | O_WRONLY, 0644);
  260. if(fd < 0) {
  261. fprintf(stderr,"error: could not create '%s'\n", bootimg);
  262. return 1;
  263. }
  264. if(write(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) goto fail;
  265. if(write_padding(fd, pagesize, sizeof(hdr))) goto fail;
  266. if(write(fd, kernel_data, hdr.kernel_size) != hdr.kernel_size) goto fail;
  267. if(write_padding(fd, pagesize, hdr.kernel_size)) goto fail;
  268. if(write(fd, ramdisk_data, hdr.ramdisk_size) != hdr.ramdisk_size) goto fail;
  269. if(write_padding(fd, pagesize, hdr.ramdisk_size)) goto fail;
  270. if(second_data) {
  271. if(write(fd, second_data, hdr.second_size) != hdr.second_size) goto fail;
  272. if(write_padding(fd, pagesize, hdr.ramdisk_size)) goto fail;
  273. }
  274. if(dt_data) {
  275. if(write(fd, dt_data, hdr.dt_size) != hdr.dt_size) goto fail;
  276. if(write_padding(fd, pagesize, hdr.dt_size)) goto fail;
  277. }
  278. if(sig_data) {
  279. if(write(fd, sig_data, 256) != 256) goto fail;
  280. }
  281. return 0;
  282. fail:
  283. unlink(bootimg);
  284. close(fd);
  285. fprintf(stderr,"error: failed writing '%s': %s\n", bootimg,
  286. strerror(errno));
  287. return 1;
  288. }