PageRenderTime 32ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/src/utils/genextbin.c

https://gitlab.com/gstreamer-omap/sysbios-rpmsg
C | 528 lines | 377 code | 72 blank | 79 comment | 68 complexity | 14d8e87096b83c7d5207c534dfbe9565 MD5 | raw file
  1. /*
  2. * Copyright (c) 2011-2012, Texas Instruments Incorporated
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. *
  9. * * Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. *
  12. * * Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. *
  16. * * Neither the name of Texas Instruments Incorporated nor the names of
  17. * its contributors may be used to endorse or promote products derived
  18. * from this software without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  21. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  22. * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  23. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  24. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  25. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  26. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  27. * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  28. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  29. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  30. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. */
  32. /*
  33. * ======== genextbin.c ========
  34. * Version History:
  35. * 1.00 - Original Version
  36. * 1.01 - Updated final signature section length
  37. * 1.02 - Fixed addresses in TOC table
  38. * 1.03 - Updated extended section locations
  39. * 1.04 - Added TOC offset at EOF, Version traces
  40. * 1.05 - Check for presigned input binary, generate an optional output binary
  41. */
  42. #include <stdio.h>
  43. #include <stdlib.h>
  44. #include <unistd.h>
  45. #include <sys/stat.h>
  46. #include <string.h>
  47. #include "rprcfmt.h"
  48. #include "mmudefs.h"
  49. #define RPROC_MAX_MEM_ENTRIES 20
  50. #define RPROC_MAX_FW_SECTIONS 30
  51. #define RPROC_L1_ENTRIES 4096
  52. #define DEBUG_TOC_FILE "sign_toc.log"
  53. #define DEBUG_MMU_FILE "mmu_ttb_dump.log"
  54. #define FW_MMU_BASE_PA 0xB4200000
  55. #define FW_SIGNATURE_BASE_PA (FW_MMU_BASE_PA + 0x80000)
  56. #define VERSION "1.05"
  57. static int check_image(void * data, int size);
  58. static int process_image(FILE *iofp, void * data, int size);
  59. typedef struct {
  60. u64 va;
  61. u64 pa;
  62. u32 len;
  63. } va_pa_entry;
  64. typedef struct {
  65. u32 sect_id;
  66. u32 offset;
  67. u32 sect_pa;
  68. u32 sect_len;
  69. } fw_toc_entry;
  70. va_pa_entry va_pa_table[RPROC_MAX_MEM_ENTRIES];
  71. u32 mmu_l1_table[RPROC_L1_ENTRIES];
  72. static void print_help(void)
  73. {
  74. fprintf(stderr, "\nInvalid arguments!\n"
  75. "Usage: ./genextbin <[-i] <Unsigned input ducati binary>> "
  76. "[<[-o] <Presigned output ducati binary>>]\n"
  77. "Rules: - Output binary file is optional, if not given,\n"
  78. " input binary file will be modified in place.\n"
  79. " - Arguments can be specified in any order as long\n"
  80. " as the corresponding option is specified.\n"
  81. " - All arguments not preceded by an option are \n"
  82. " applied as input binary and output binary in \n"
  83. " that order.\n");
  84. exit(1);
  85. }
  86. /*
  87. * ======== main ========
  88. */
  89. int main(int argc, char * argv[])
  90. {
  91. FILE * ifp;
  92. FILE * ofp;
  93. struct stat st;
  94. char * infile;
  95. char * outfile;
  96. void * data;
  97. int size;
  98. int status = 0;
  99. int i, o;
  100. char *bin_files[] = {NULL, NULL};
  101. int num_files = sizeof(bin_files) / sizeof(bin_files[0]);
  102. printf("#######################################\n");
  103. printf(" GENEXTBIN : %s \n", VERSION);
  104. printf("#######################################\n");
  105. /* Determine args */
  106. while ((o = getopt (argc, argv, ":i:o:")) != -1) {
  107. switch (o) {
  108. case 'i':
  109. bin_files[0] = optarg;
  110. break;
  111. case 'o':
  112. bin_files[1] = optarg;
  113. break;
  114. case ':':
  115. status = -1;
  116. printf("Option -%c requires an operand\n", optopt);
  117. break;
  118. case '?':
  119. status = -1;
  120. printf("Unrecognized option: -%c\n", optopt);
  121. break;
  122. }
  123. }
  124. for (i = 0; optind < argc; optind++) {
  125. while (i < num_files && bin_files[i]) i++;
  126. if (i == num_files) {
  127. print_help();
  128. }
  129. bin_files[i++] = argv[optind];
  130. }
  131. if (status || !bin_files[0] ||
  132. (bin_files[1] && (!strcmp(bin_files[0], bin_files[1])))) {
  133. print_help();
  134. }
  135. printf("Input Binary = %s, Output Binary = %s\n",
  136. bin_files[0], bin_files[1]);
  137. infile = bin_files[0];
  138. if ((ifp = fopen(infile, "a+b")) == NULL) {
  139. fprintf(stderr, "%s: could not open: %s\n", argv[0], infile);
  140. exit(2);
  141. }
  142. fstat(fileno(ifp), &st);
  143. size = st.st_size;
  144. if (!size) {
  145. fprintf(stderr, "%s: %s size is invalid.\n", argv[0], infile);
  146. fclose(ifp);
  147. exit(3);
  148. }
  149. outfile = bin_files[1];
  150. if (outfile && ((ofp = fopen(outfile, "w+b")) == NULL)) {
  151. fprintf(stderr, "%s: could not open: %s\n", argv[0], outfile);
  152. fclose(ifp);
  153. exit(2);
  154. }
  155. printf("Preparing binary: %s of size: 0x%x\n", infile, size);
  156. data = malloc(size);
  157. fread(data, 1, size, ifp);
  158. status = check_image(data, size);
  159. if (status == 0) {
  160. if (outfile) {
  161. fwrite(data, 1, size, ofp);
  162. }
  163. else {
  164. ofp = ifp;
  165. }
  166. status = process_image(ofp, data, size);
  167. }
  168. free(data);
  169. if (outfile) {
  170. fclose(ofp);
  171. }
  172. fclose(ifp);
  173. return status;
  174. }
  175. /*
  176. * ======== add_mem_entry ========
  177. */
  178. static int add_mem_entry(struct rproc_fw_resource *rsc)
  179. {
  180. va_pa_entry *me = va_pa_table;
  181. int i = 0;
  182. int ret = 0;
  183. while (me->va || me->pa || me->len) {
  184. me += 1;
  185. i++;
  186. if (i == RPROC_MAX_MEM_ENTRIES) {
  187. printf(" No more space in VA->PA Table\n");
  188. ret = -1;
  189. break;
  190. }
  191. }
  192. if (!ret) {
  193. me->va = rsc->da;
  194. me->pa = rsc->pa;
  195. me->len = rsc->len;
  196. printf(" Added entry %d: va 0x%.8llx pa 0x%.8llx len 0x%.8x\n",
  197. i, me->va, me->pa, me->len);
  198. }
  199. return ret;
  200. }
  201. /*
  202. * ======== va_to_pa ========
  203. */
  204. static int va_to_pa(u64 va, u64 *pa)
  205. {
  206. int i;
  207. u64 offset;
  208. for (i = 0; va_pa_table[i].len; i++) {
  209. const va_pa_entry *me = &va_pa_table[i];
  210. if (va >= me->va && va < (me->va + me->len)) {
  211. offset = va - me->va;
  212. printf(" %s: matched mem entry no. %d\n", __func__, i);
  213. *pa = me->pa + offset;
  214. return 0;
  215. }
  216. }
  217. return -1;
  218. }
  219. /*
  220. * ======== dump_ttb ========
  221. */
  222. static void dump_ttb(void)
  223. {
  224. FILE * fp;
  225. int i = 0;
  226. if ((fp = fopen(DEBUG_MMU_FILE, "w+b")) == NULL) {
  227. fprintf(stderr, "could not open: "DEBUG_MMU_FILE"\n");
  228. return;
  229. }
  230. fprintf(fp, " VA PA \n");
  231. for (i = 0; i < RPROC_L1_ENTRIES; i++) {
  232. fprintf(fp, "0x%.8x 0x%.8x\n", i << 20, mmu_l1_table[i]);
  233. }
  234. fclose(fp);
  235. }
  236. /*
  237. * ======== create_ttb ========
  238. * TODO: Extend the MMU table generation to be able to do L2 tables as
  239. * well (to provide large page or small page mapping granularity).
  240. */
  241. static void create_ttb(void)
  242. {
  243. int i, j;
  244. va_pa_entry *me = va_pa_table;
  245. u32 va, pa;
  246. u32 va_pa;
  247. u32 size;
  248. u32 mmu_sizes[4] = {MMU_SZ_16M, MMU_SZ_1M, MMU_SZ_64K, MMU_SZ_4K};
  249. u32 index;
  250. while (me->pa && me->len) {
  251. size = me->len;
  252. va = me->va;
  253. pa = me->pa;
  254. printf("Preparing MMU entry for va = 0x%x pa = 0x%x len = 0x%x\n",
  255. va, pa, size);
  256. while (size) {
  257. va_pa = va | pa;
  258. for (i = 0; i < 4; i++) {
  259. if ((size >= mmu_sizes[i]) &&
  260. ((va_pa & (mmu_sizes[i] - 1)) == 0)) {
  261. break;
  262. }
  263. }
  264. if (i == MMU_L1_SSECTION) {
  265. printf(" Programming region as 16M entry: 0x%x for 0x%x\n",
  266. va, pa);
  267. index = ((va & MMU_L1_SECTION_MASK) >> 20);
  268. for (j = 0; j < 16; j++) {
  269. mmu_l1_table[index + j] = (pa & MMU_L1_SSECTION_MASK) |
  270. MMU_L1_SSECTION_FLAGS;
  271. }
  272. }
  273. else if (i == MMU_L1_SECTION) {
  274. printf(" Programming region as 1M entry: 0x%x for 0x%x\n",
  275. va, pa);
  276. index = ((va & MMU_L1_SECTION_MASK) >> 20);
  277. mmu_l1_table[index] = (pa & MMU_L1_SECTION_MASK) |
  278. MMU_L1_SECTION_FLAGS;
  279. }
  280. else if (i == MMU_L2_LPAGE || i == MMU_L2_SPAGE) {
  281. printf(" Invalid memory entry. All entries should either be "
  282. " a 16M or 1M entry only\n");
  283. }
  284. size -= mmu_sizes[i];
  285. va += mmu_sizes[i];
  286. pa += mmu_sizes[i];
  287. }
  288. me += 1;
  289. }
  290. dump_ttb();
  291. }
  292. /*
  293. * ======== process_resources ========
  294. */
  295. static void process_resources(struct rproc_fw_section * s)
  296. {
  297. struct rproc_fw_resource * res = (struct rproc_fw_resource * )s->content;
  298. int i;
  299. printf("processing resource table... len: 0x%x\n",
  300. sizeof(struct rproc_fw_resource));
  301. for (i = 0; i < s->len / sizeof(struct rproc_fw_resource); i++) {
  302. printf("resource: %d, da: 0x%.8llx, pa: 0x%.8llx, len: 0x%.8x, name: %s\n",
  303. res[i].type, res[i].da, res[i].pa, res[i].len, res[i].name);
  304. switch(res[i].type) {
  305. case RSC_DEVMEM:
  306. case RSC_CARVEOUT:
  307. if (res[i].pa) {
  308. add_mem_entry(&res[i]);
  309. }
  310. else {
  311. printf(" Entry with undefined PA (to be assigned!)\n");
  312. }
  313. break;
  314. default:
  315. printf(" Nothing to do for this resource\n");
  316. break;
  317. }
  318. }
  319. printf("resource table processed...\n");
  320. }
  321. /*
  322. * ======== check_image ========
  323. */
  324. static int check_image(void * data, int size)
  325. {
  326. struct rproc_fw_header *hdr;
  327. struct rproc_fw_section *s;
  328. int f_offset = 0;
  329. printf("\nChecking header....");
  330. hdr = (struct rproc_fw_header *)data;
  331. /* check that magic is what we expect */
  332. if (memcmp(hdr->magic, RPROC_FW_MAGIC, sizeof(hdr->magic))) {
  333. fprintf(stderr, "invalid magic number: %.4s\n", hdr->magic);
  334. return -1;
  335. }
  336. printf("done.\n");
  337. printf("Checking sections....");
  338. /* get the first section */
  339. s = (struct rproc_fw_section *)(hdr->header + hdr->header_len);
  340. f_offset += (u8 *)s - (u8 *)data;
  341. /* check all the sections for processed sections */
  342. while ((u8 *)s < (u8 *)(data + size)) {
  343. f_offset += (u8 *)s->content - (u8 *)s;
  344. if (s->type == FW_MMU || s->type == FW_SIGNATURE) {
  345. printf("binary is already processed!!\n");
  346. return -2;
  347. }
  348. f_offset += s->len;
  349. s = ((void *)s->content) + s->len;
  350. }
  351. printf("done.\n");
  352. return 0;
  353. }
  354. /*
  355. * ======== process_image ========
  356. */
  357. static int process_image(FILE * iofp, void * data, int size)
  358. {
  359. struct rproc_fw_header *hdr;
  360. struct rproc_fw_section *s;
  361. int f_offset = 0;
  362. int sectno = 0;
  363. u64 pa;
  364. fw_toc_entry fw_toc_table[RPROC_MAX_FW_SECTIONS];
  365. u32 toc_table_length = 0;
  366. u32 toc_offset = 0;
  367. struct rproc_fw_section fw_new_section;
  368. FILE *dfp;
  369. if ((dfp = fopen(DEBUG_TOC_FILE, "w+b")) == NULL) {
  370. fprintf(stderr, "could not open: "DEBUG_TOC_FILE"\n");
  371. return -1;
  372. }
  373. memset(mmu_l1_table, 0, sizeof(mmu_l1_table));
  374. memset(fw_toc_table, 0, sizeof(fw_toc_table));
  375. printf("\nProcessing header...\n");
  376. hdr = (struct rproc_fw_header *)data;
  377. /* check that magic is what we expect */
  378. if (memcmp(hdr->magic, RPROC_FW_MAGIC, sizeof(hdr->magic))) {
  379. fprintf(stderr, "invalid magic number: %.4s\n", hdr->magic);
  380. return -1;
  381. }
  382. /* baseimage information */
  383. printf("magic number %.4s\n", hdr->magic);
  384. printf("header version %d\n", hdr->version);
  385. printf("header size %d\n", hdr->header_len);
  386. printf("header data\n%s\n", hdr->header);
  387. /* get the first section */
  388. s = (struct rproc_fw_section *)(hdr->header + hdr->header_len);
  389. printf("Processing sections....\n");
  390. f_offset += (u8 *)s - (u8 *)data;
  391. while ((u8 *)s < (u8 *)(data + size)) {
  392. f_offset += (u8 *)s->content - (u8 *)s;
  393. printf("section: %d, offset:0x%x address: 0x%llx, size: 0x%x\n",
  394. s->type, f_offset, s->da, s->len);
  395. if (s->type == FW_RESOURCE) {
  396. process_resources(s);
  397. }
  398. if (!va_to_pa(s->da, &pa)) {
  399. fw_toc_table[sectno].sect_id = sectno + 1;
  400. fw_toc_table[sectno].offset = f_offset;
  401. fw_toc_table[sectno].sect_pa = (u32)pa;
  402. fw_toc_table[sectno].sect_len = s->len;
  403. toc_table_length += sizeof(fw_toc_entry);
  404. fprintf(dfp, "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n", ++sectno, f_offset,
  405. (u32)pa, s->len);
  406. }
  407. else {
  408. printf(" Ignoring this section for now! PA to be assigned!!\n");
  409. }
  410. f_offset += s->len;
  411. s = ((void *)s->content) + s->len;
  412. }
  413. printf("sections processed...\n");
  414. printf("\nCurrent position of files = 0x%lx 0x%lx\n", ftell(iofp),
  415. ftell(dfp));
  416. printf("TOC regular sections size = 0x%x\n", toc_table_length);
  417. /* create and append the MMU L1 Page Table section to the binary */
  418. create_ttb();
  419. fw_new_section.type = FW_MMU;
  420. /* this address located right after text section, but before data section */
  421. fw_new_section.da = FW_MMU_BASE_PA;
  422. fw_new_section.len = sizeof(mmu_l1_table);
  423. fwrite(&fw_new_section, 1, 16, iofp);
  424. f_offset += 16; /* for the new fw_section header */
  425. fwrite(&mmu_l1_table, 1, sizeof(mmu_l1_table), iofp);
  426. /* add the MMU section to TOC */
  427. fw_toc_table[sectno].sect_id = sectno + 1;
  428. fw_toc_table[sectno].offset = f_offset;
  429. fw_toc_table[sectno].sect_pa = (u32)fw_new_section.da;
  430. fw_toc_table[sectno].sect_len = fw_new_section.len;
  431. toc_table_length += sizeof(fw_toc_entry);
  432. fprintf(dfp, "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n", ++sectno, f_offset,
  433. (u32)fw_new_section.da, fw_new_section.len);
  434. /* add the end of section marker to TOC */
  435. fw_toc_table[sectno].sect_id = sectno + 1;
  436. fw_toc_table[sectno].offset = -1;
  437. fw_toc_table[sectno].sect_pa = -1;
  438. fw_toc_table[sectno].sect_len = -1;
  439. toc_table_length += sizeof(fw_toc_entry);
  440. fprintf(dfp, "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n", ++sectno, -1, -1, -1);
  441. /* append the FW section TOC for signing tool to the binary */
  442. fw_new_section.type = FW_SIGNATURE;
  443. fw_new_section.da = FW_SIGNATURE_BASE_PA;
  444. fw_new_section.len = toc_table_length + 0x148;
  445. fwrite(&fw_new_section, 1, 16, iofp);
  446. fwrite(fw_toc_table, 1, toc_table_length, iofp);
  447. toc_offset = ftell(iofp) - toc_table_length;
  448. printf("\nCurrent position of files = 0x%lx 0x%lx\n", ftell(iofp),
  449. ftell(dfp));
  450. fwrite(&toc_offset, 1, 4, iofp);
  451. printf("Total TOC size = 0x%x\n", toc_table_length);
  452. printf("TOC Offset = 0x%x\n", toc_offset);
  453. fprintf(dfp, "TOC Offset = 0x%.8x\n", toc_offset);
  454. fclose(dfp);
  455. return 0;
  456. }