summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--utils/rknanoutils/rkboottool/elf.c73
-rw-r--r--utils/rknanoutils/rkboottool/elf.h5
-rw-r--r--utils/rknanoutils/rkboottool/rkboottool.c211
3 files changed, 210 insertions, 79 deletions
diff --git a/utils/rknanoutils/rkboottool/elf.c b/utils/rknanoutils/rkboottool/elf.c
index 481ab98dd6..78b29506a2 100644
--- a/utils/rknanoutils/rkboottool/elf.c
+++ b/utils/rknanoutils/rkboottool/elf.c
@@ -21,6 +21,14 @@
21#include "elf.h" 21#include "elf.h"
22#include "misc.h" 22#include "misc.h"
23 23
24static char *strdup(const char *str)
25{
26 int len = strlen(str);
27 char *s = malloc(len + 1);
28 memcpy(s, str, len + 1);
29 return s;
30}
31
24/** 32/**
25 * Definitions 33 * Definitions
26 * taken from elf.h linux header 34 * taken from elf.h linux header
@@ -189,43 +197,55 @@ static struct elf_segment_t *elf_add_segment(struct elf_params_t *params)
189} 197}
190 198
191void elf_add_load_section(struct elf_params_t *params, 199void elf_add_load_section(struct elf_params_t *params,
192 uint32_t load_addr, uint32_t size, const void *section) 200 uint32_t load_addr, uint32_t size, const void *section, const char *name)
193{ 201{
194 struct elf_section_t *sec = elf_add_section(params); 202 struct elf_section_t *sec = elf_add_section(params);
203 char buffer[32];
204 if(name == NULL)
205 {
206 sprintf(buffer, ".text%d", params->unique_index++);
207 name = buffer;
208 }
195 209
196 sec->type = EST_LOAD; 210 sec->type = EST_LOAD;
197 sec->addr = load_addr; 211 sec->addr = load_addr;
198 sec->size = size; 212 sec->size = size;
199 sec->section = xmalloc(size); 213 sec->section = xmalloc(size);
214 sec->name = strdup(name);
200 memcpy(sec->section, section, size); 215 memcpy(sec->section, section, size);
201} 216}
202 217
203void elf_add_fill_section(struct elf_params_t *params, 218void elf_add_fill_section(struct elf_params_t *params,
204 uint32_t fill_addr, uint32_t size, uint32_t pattern) 219 uint32_t fill_addr, uint32_t size, uint32_t pattern)
205{ 220{
221 char buffer[32];
222 sprintf(buffer, ".bss%d", params->unique_index++);
223
206 if(pattern != 0x00) 224 if(pattern != 0x00)
207 { 225 {
208 printf("oops, non-zero filling, ignore fill section\n"); 226 printf("oops, non-zero filling, ignore fill section\n");
209 return; 227 return;
210 } 228 }
211 229
212 struct elf_section_t *sec = elf_add_section(params); 230 struct elf_section_t *sec = elf_add_section(params);
213 231
214 sec->type = EST_FILL; 232 sec->type = EST_FILL;
215 sec->addr = fill_addr; 233 sec->addr = fill_addr;
216 sec->size = size; 234 sec->size = size;
217 sec->pattern = pattern; 235 sec->pattern = pattern;
236 sec->name = strdup(buffer);
218} 237}
219 238
220void elf_write_file(struct elf_params_t *params, elf_write_fn_t write, 239void elf_write_file(struct elf_params_t *params, elf_write_fn_t write,
221 elf_printf_fn_t printf, void *user) 240 elf_printf_fn_t printf, void *user)
222{ 241{
223 (void) printf; 242 (void) printf;
224 243
225 Elf32_Ehdr ehdr; 244 Elf32_Ehdr ehdr;
226 uint32_t phnum = 0; 245 uint32_t phnum = 0;
227 struct elf_section_t *sec = params->first_section; 246 struct elf_section_t *sec = params->first_section;
228 uint32_t offset = 0; 247 uint32_t offset = 0;
248 uint32_t strtbl_size = 1; /* offset 0 is for the NULL name */
229 Elf32_Phdr phdr; 249 Elf32_Phdr phdr;
230 Elf32_Shdr shdr; 250 Elf32_Shdr shdr;
231 memset(&ehdr, 0, EI_NIDENT); 251 memset(&ehdr, 0, EI_NIDENT);
@@ -241,7 +261,9 @@ void elf_write_file(struct elf_params_t *params, elf_write_fn_t write,
241 { 261 {
242 sec->offset = 0; 262 sec->offset = 0;
243 } 263 }
244 264 sec->name_offset = strtbl_size;
265 strtbl_size += strlen(sec->name) + 1;
266
245 phnum++; 267 phnum++;
246 sec = sec->next; 268 sec = sec->next;
247 } 269 }
@@ -275,16 +297,14 @@ void elf_write_file(struct elf_params_t *params, elf_write_fn_t write,
275 297
276 write(user, 0, &ehdr, sizeof ehdr); 298 write(user, 0, &ehdr, sizeof ehdr);
277 299
278 /* allocate enough size to hold any combinaison of .text/.bss in the string table: 300 /* the last name offset gives the size of the section, we need to add a small
279 * - one empty name ("\0") 301 * amount of .shstrtab name */
280 * - at most N names of the form ".textXXXX\0" or ".bssXXXX\0" 302 uint32_t shstrtab_index = strtbl_size;
281 * - one name ".shstrtab\0" */ 303 strtbl_size += strlen(".shstrtab") + 1;
282 char *strtbl_content = malloc(1 + strlen(".shstrtab") + 1 + 304 char *strtbl_content = malloc(strtbl_size);
283 phnum * (strlen(".textXXXX") + 1)); 305 /* create NULL and shstrtab names */
284
285 strtbl_content[0] = '\0'; 306 strtbl_content[0] = '\0';
286 strcpy(&strtbl_content[1], ".shstrtab"); 307 strcpy(&strtbl_content[shstrtab_index], ".shstrtab");
287 uint32_t strtbl_index = 1 + strlen(".shstrtab") + 1;
288 308
289 uint32_t data_offset = ehdr.e_ehsize + ehdr.e_phnum * ehdr.e_phentsize + 309 uint32_t data_offset = ehdr.e_ehsize + ehdr.e_phnum * ehdr.e_phentsize +
290 ehdr.e_shnum * ehdr.e_shentsize; 310 ehdr.e_shnum * ehdr.e_shentsize;
@@ -294,7 +314,8 @@ void elf_write_file(struct elf_params_t *params, elf_write_fn_t write,
294 while(sec) 314 while(sec)
295 { 315 {
296 sec->offset += data_offset; 316 sec->offset += data_offset;
297 317 strcpy(&strtbl_content[sec->name_offset], sec->name);
318
298 phdr.p_type = PT_LOAD; 319 phdr.p_type = PT_LOAD;
299 if(sec->type == EST_LOAD) 320 if(sec->type == EST_LOAD)
300 phdr.p_offset = sec->offset; 321 phdr.p_offset = sec->offset;
@@ -336,21 +357,13 @@ void elf_write_file(struct elf_params_t *params, elf_write_fn_t write,
336 offset += sizeof(Elf32_Shdr); 357 offset += sizeof(Elf32_Shdr);
337 } 358 }
338 359
339 uint32_t text_idx = 0;
340 uint32_t bss_idx = 0;
341 while(sec) 360 while(sec)
342 { 361 {
343 shdr.sh_name = strtbl_index; 362 shdr.sh_name = sec->name_offset;
344 if(sec->type == EST_LOAD) 363 if(sec->type == EST_LOAD)
345 {
346 strtbl_index += 1 + sprintf(&strtbl_content[strtbl_index], ".text%d", text_idx++);
347 shdr.sh_type = SHT_PROGBITS; 364 shdr.sh_type = SHT_PROGBITS;
348 }
349 else 365 else
350 {
351 strtbl_index += 1 + sprintf(&strtbl_content[strtbl_index], ".bss%d", bss_idx++);
352 shdr.sh_type = SHT_NOBITS; 366 shdr.sh_type = SHT_NOBITS;
353 }
354 shdr.sh_flags = SHF_ALLOC | SHF_EXECINSTR; 367 shdr.sh_flags = SHF_ALLOC | SHF_EXECINSTR;
355 shdr.sh_addr = sec->addr; 368 shdr.sh_addr = sec->addr;
356 shdr.sh_offset = sec->offset; 369 shdr.sh_offset = sec->offset;
@@ -367,12 +380,12 @@ void elf_write_file(struct elf_params_t *params, elf_write_fn_t write,
367 } 380 }
368 381
369 { 382 {
370 shdr.sh_name = 1; 383 shdr.sh_name = shstrtab_index;
371 shdr.sh_type = SHT_STRTAB; 384 shdr.sh_type = SHT_STRTAB;
372 shdr.sh_flags = 0; 385 shdr.sh_flags = 0;
373 shdr.sh_addr = 0; 386 shdr.sh_addr = 0;
374 shdr.sh_offset = strtbl_offset + data_offset; 387 shdr.sh_offset = strtbl_offset + data_offset;
375 shdr.sh_size = strtbl_index; 388 shdr.sh_size = strtbl_size;
376 shdr.sh_link = SHN_UNDEF; 389 shdr.sh_link = SHN_UNDEF;
377 shdr.sh_info = 0; 390 shdr.sh_info = 0;
378 shdr.sh_addralign = 1; 391 shdr.sh_addralign = 1;
@@ -391,7 +404,7 @@ void elf_write_file(struct elf_params_t *params, elf_write_fn_t write,
391 sec = sec->next; 404 sec = sec->next;
392 } 405 }
393 406
394 write(user, strtbl_offset + data_offset, strtbl_content, strtbl_index); 407 write(user, strtbl_offset + data_offset, strtbl_content, strtbl_size);
395 free(strtbl_content); 408 free(strtbl_content);
396} 409}
397 410
@@ -399,7 +412,7 @@ bool elf_read_file(struct elf_params_t *params, elf_read_fn_t read,
399 elf_printf_fn_t printf, void *user) 412 elf_printf_fn_t printf, void *user)
400{ 413{
401 #define error_printf(...) ({printf(user, true, __VA_ARGS__); return false;}) 414 #define error_printf(...) ({printf(user, true, __VA_ARGS__); return false;})
402 415
403 /* read header */ 416 /* read header */
404 Elf32_Ehdr ehdr; 417 Elf32_Ehdr ehdr;
405 if(!read(user, 0, &ehdr, sizeof(ehdr))) 418 if(!read(user, 0, &ehdr, sizeof(ehdr)))
@@ -459,7 +472,7 @@ bool elf_read_file(struct elf_params_t *params, elf_read_fn_t read,
459 void *data = xmalloc(shdr.sh_size); 472 void *data = xmalloc(shdr.sh_size);
460 if(!read(user, shdr.sh_offset, data, shdr.sh_size)) 473 if(!read(user, shdr.sh_offset, data, shdr.sh_size))
461 error_printf("error read self section data\n"); 474 error_printf("error read self section data\n");
462 elf_add_load_section(params, shdr.sh_addr, shdr.sh_size, data); 475 elf_add_load_section(params, shdr.sh_addr, shdr.sh_size, data, NULL);
463 free(data); 476 free(data);
464 477
465 if(strtab) 478 if(strtab)
@@ -476,7 +489,6 @@ bool elf_read_file(struct elf_params_t *params, elf_read_fn_t read,
476 if(strtab) 489 if(strtab)
477 printf(user, false, "filter out %s\n", &strtab[shdr.sh_name], shdr.sh_type); 490 printf(user, false, "filter out %s\n", &strtab[shdr.sh_name], shdr.sh_type);
478 } 491 }
479
480 } 492 }
481 free(strtab); 493 free(strtab);
482 /* run through segments */ 494 /* run through segments */
@@ -562,6 +574,7 @@ void elf_release(struct elf_params_t *params)
562 struct elf_section_t *next_sec = sec->next; 574 struct elf_section_t *next_sec = sec->next;
563 if(sec->type == EST_LOAD) 575 if(sec->type == EST_LOAD)
564 free(sec->section); 576 free(sec->section);
577 free(sec->name);
565 free(sec); 578 free(sec);
566 sec = next_sec; 579 sec = next_sec;
567 } 580 }
diff --git a/utils/rknanoutils/rkboottool/elf.h b/utils/rknanoutils/rkboottool/elf.h
index 2166833276..2408e0c588 100644
--- a/utils/rknanoutils/rkboottool/elf.h
+++ b/utils/rknanoutils/rkboottool/elf.h
@@ -42,6 +42,7 @@ struct elf_section_t
42 uint32_t addr; /* virtual address */ 42 uint32_t addr; /* virtual address */
43 uint32_t size; /* virtual size */ 43 uint32_t size; /* virtual size */
44 enum elf_section_type_t type; 44 enum elf_section_type_t type;
45 char *name;
45 /* <union> */ 46 /* <union> */
46 void *section; /* data */ 47 void *section; /* data */
47 uint32_t pattern; /* fill pattern */ 48 uint32_t pattern; /* fill pattern */
@@ -49,6 +50,7 @@ struct elf_section_t
49 struct elf_section_t *next; 50 struct elf_section_t *next;
50 /* Internal to elf_write_file */ 51 /* Internal to elf_write_file */
51 uint32_t offset; 52 uint32_t offset;
53 uint32_t name_offset;
52}; 54};
53 55
54struct elf_segment_t 56struct elf_segment_t
@@ -68,6 +70,7 @@ struct elf_params_t
68 struct elf_section_t *last_section; 70 struct elf_section_t *last_section;
69 struct elf_segment_t *first_segment; 71 struct elf_segment_t *first_segment;
70 struct elf_segment_t *last_segment; 72 struct elf_segment_t *last_segment;
73 int unique_index;
71}; 74};
72 75
73typedef bool (*elf_read_fn_t)(void *user, uint32_t addr, void *buf, size_t count); 76typedef bool (*elf_read_fn_t)(void *user, uint32_t addr, void *buf, size_t count);
@@ -77,7 +80,7 @@ typedef void (*elf_printf_fn_t)(void *user, bool error, const char *fmt, ...);
77 80
78void elf_init(struct elf_params_t *params); 81void elf_init(struct elf_params_t *params);
79void elf_add_load_section(struct elf_params_t *params, 82void elf_add_load_section(struct elf_params_t *params,
80 uint32_t load_addr, uint32_t size, const void *section); 83 uint32_t load_addr, uint32_t size, const void *section, const char *name);
81void elf_add_fill_section(struct elf_params_t *params, 84void elf_add_fill_section(struct elf_params_t *params,
82 uint32_t fill_addr, uint32_t size, uint32_t pattern); 85 uint32_t fill_addr, uint32_t size, uint32_t pattern);
83uint32_t elf_translate_virtual_address(struct elf_params_t *params, uint32_t addr); 86uint32_t elf_translate_virtual_address(struct elf_params_t *params, uint32_t addr);
diff --git a/utils/rknanoutils/rkboottool/rkboottool.c b/utils/rknanoutils/rkboottool/rkboottool.c
index ee9b17e610..763751e41f 100644
--- a/utils/rknanoutils/rkboottool/rkboottool.c
+++ b/utils/rknanoutils/rkboottool/rkboottool.c
@@ -15,6 +15,11 @@ bool g_debug = false;
15typedef uint8_t packed_bcd_uint8_t; 15typedef uint8_t packed_bcd_uint8_t;
16typedef uint16_t packed_bcd_uint16_t; 16typedef uint16_t packed_bcd_uint16_t;
17 17
18/**
19 * RKnanoFW
20 * contains resources and code stages
21 */
22
18struct rknano_date_t 23struct rknano_date_t
19{ 24{
20 packed_bcd_uint16_t year; 25 packed_bcd_uint16_t year;
@@ -176,7 +181,7 @@ static void save_blob(const struct rknano_blob_t *b, void *buf, uint32_t size,
176 } 181 }
177 encode_page(buff_ptr, out_ptr, len); 182 encode_page(buff_ptr, out_ptr, len);
178 } 183 }
179 184
180 if(f) 185 if(f)
181 { 186 {
182 fwrite(ptr, b->size, 1, f); 187 fwrite(ptr, b->size, 1, f);
@@ -276,6 +281,11 @@ static int do_nanofw_image(uint8_t *buf, unsigned long size)
276 return 0; 281 return 0;
277} 282}
278 283
284/**
285 * RKNano stage
286 * contains code and memory mapping
287 */
288
279struct rknano_stage_header_t 289struct rknano_stage_header_t
280{ 290{
281 uint32_t addr; 291 uint32_t addr;
@@ -283,21 +293,28 @@ struct rknano_stage_header_t
283} __attribute__((packed)); 293} __attribute__((packed));
284 294
285/* 295/*
286 * The [code_pa,code_pa+code_sz[ and [data_pa,data_pa+data_sz[ ranges 296 * NOTE this theory has not been tested against actual code, it's still a guess
287 * are consistent: they never overlap and have no gaps and fill the 297 * The firmware is too big to fit in memory so it's split into sections,
288 * entire space. Furthermore they match the code sequences so it's 298 * each section having a "virtual address" and a "physical address".
289 * reasonable to assume these fields are correct. 299 * Except it gets tricky because the RKNano doesn't have a MMU but a MPU,
290 * The other fields are still quite unsure. */ 300 * so most probably the OF divides the memory into regions (8 would match
301 * hardware capabilities), each being able to contain one of the sections
302 * in the OF file. To gracefully handle jumps between sections, my guess is
303 * that the entire OF is linked as a flat image, cut into pieces and
304 * then each code section get relocated except for jump/calls outside of it:
305 * this will trigger an access fault when trying to access another section, which
306 * the OF can trap and then load the corresponding section.
307 */
291 308
292struct rknano_stage_section_t 309struct rknano_stage_section_t
293{ 310{
294 uint32_t code_pa;
295 uint32_t code_va; 311 uint32_t code_va;
312 uint32_t code_pa;
296 uint32_t code_sz; 313 uint32_t code_sz;
297 uint32_t data_pa;
298 uint32_t data_va; 314 uint32_t data_va;
315 uint32_t data_pa;
299 uint32_t data_sz; 316 uint32_t data_sz;
300 uint32_t bss_va; 317 uint32_t bss_pa;
301 uint32_t bss_sz; 318 uint32_t bss_sz;
302} __attribute__((packed)); 319} __attribute__((packed));
303 320
@@ -319,14 +336,14 @@ static void elf_write(void *user, uint32_t addr, const void *buf, size_t count)
319 fwrite(buf, count, 1, f); 336 fwrite(buf, count, 1, f);
320} 337}
321 338
322static void extract_elf_section(struct elf_params_t *elf, int count) 339static void extract_elf_section(struct elf_params_t *elf)
323{ 340{
324 if(g_out_prefix == NULL) 341 if(g_out_prefix == NULL)
325 return; 342 return;
326 char *filename = xmalloc(strlen(g_out_prefix) + 32); 343 char *filename = xmalloc(strlen(g_out_prefix) + 32);
327 sprintf(filename, "%s%d.elf", g_out_prefix, count); 344 sprintf(filename, "%s.elf", g_out_prefix);
328 if(g_debug) 345 if(g_debug)
329 printf("Write entry %d to %s\n", count, filename); 346 printf("Write stage to %s\n", filename);
330 347
331 FILE *fd = fopen(filename, "wb"); 348 FILE *fd = fopen(filename, "wb");
332 free(filename); 349 free(filename);
@@ -337,67 +354,149 @@ static void extract_elf_section(struct elf_params_t *elf, int count)
337 fclose(fd); 354 fclose(fd);
338} 355}
339 356
357struct range_t
358{
359 unsigned long start, size;
360 int section;
361 int type;
362};
363
364int range_cmp(const void *_a, const void *_b)
365{
366 const struct range_t *a = _a, *b = _b;
367 if(a->start == b->start)
368 return a->size - b->size;
369 return a->start - b->start;
370}
371
372#define RANGE_TXT 0
373#define RANGE_DAT 1
374
340static int do_nanostage_image(uint8_t *buf, unsigned long size) 375static int do_nanostage_image(uint8_t *buf, unsigned long size)
341{ 376{
342 if(size < sizeof(struct rknano_stage_section_t)) 377 if(size < sizeof(struct rknano_stage_section_t))
343 return 1; 378 return 1;
344 struct rknano_stage_header_t *hdr = (void *)buf; 379 struct rknano_stage_header_t *hdr = (void *)buf;
380 size_t hdr_size = sizeof(struct rknano_stage_header_t) +
381 hdr->count * sizeof(struct rknano_stage_section_t);
382 if(size < hdr_size)
383 return 1;
345 384
346 cprintf(BLUE, "Header\n"); 385 cprintf(BLUE, "Header\n");
347 cprintf(GREEN, " Base Address: "); 386 cprintf(GREEN, " Base Address: ");
348 cprintf(YELLOW, "%#08x\n", hdr->addr); 387 cprintf(YELLOW, "%#08x\n", hdr->addr);
349 cprintf(GREEN, " Load count: "); 388 cprintf(GREEN, " Section count: ");
350 cprintf(YELLOW, "%d\n", hdr->count); 389 cprintf(YELLOW, "%d\n", hdr->count);
351
352 struct rknano_stage_section_t *sec = (void *)(hdr + 1);
353 390
391 struct rknano_stage_section_t *sec = (void *)(hdr + 1);
392 struct elf_params_t elf;
393 elf_init(&elf);
394 bool error = false;
395 /* track range for overlap */
396 struct range_t *ranges = malloc(sizeof(struct range_t) * 2 * hdr->count);
397 int nr_ranges = 0;
354 for(unsigned i = 0; i < hdr->count; i++, sec++) 398 for(unsigned i = 0; i < hdr->count; i++, sec++)
355 { 399 {
356 cprintf(BLUE, "Section %d\n", i); 400 cprintf(BLUE, "Section %d\n", i);
357 cprintf(GREEN, " Code: "); 401 cprintf(GREEN, " Code: ");
358 cprintf(YELLOW, "0x%08x", sec->code_pa); 402 cprintf(YELLOW, "0x%08x", sec->code_va);
359 cprintf(RED, "-(txt)-"); 403 cprintf(RED, "-(txt)-");
360 cprintf(YELLOW, "0x%08x", sec->code_pa + sec->code_sz); 404 cprintf(YELLOW, "0x%08x", sec->code_va + sec->code_sz);
361 cprintf(BLUE, " |--> "); 405 cprintf(BLUE, " |--> ");
362 cprintf(YELLOW, "0x%08x", sec->code_va); 406 cprintf(YELLOW, "0x%08x", sec->code_pa);
363 cprintf(RED, "-(txt)-"); 407 cprintf(RED, "-(txt)-");
364 cprintf(YELLOW, "0x%08x\n", sec->code_va + sec->code_sz); 408 cprintf(YELLOW, "0x%08x\n", sec->code_pa + sec->code_sz);
409
410 /* add ranges */
411 ranges[nr_ranges].start = sec->code_va;
412 ranges[nr_ranges].size = sec->code_sz;
413 ranges[nr_ranges].section = i;
414 ranges[nr_ranges].type = RANGE_TXT;
415 ranges[nr_ranges + 1].start = sec->data_va;
416 ranges[nr_ranges + 1].size = sec->data_sz;
417 ranges[nr_ranges + 1].section = i;
418 ranges[nr_ranges + 1].type = RANGE_DAT;
419 nr_ranges += 2;
365 420
366 cprintf(GREEN, " Data: "); 421 cprintf(GREEN, " Data: ");
367 cprintf(YELLOW, "0x%08x", sec->data_pa); 422 cprintf(YELLOW, "0x%08x", sec->data_va);
368 cprintf(RED, "-(dat)-"); 423 cprintf(RED, "-(dat)-");
369 cprintf(YELLOW, "0x%08x", sec->data_pa + sec->data_sz); 424 cprintf(YELLOW, "0x%08x", sec->data_va + sec->data_sz);
370 cprintf(BLUE, " |--> "); 425 cprintf(BLUE, " |--> ");
371 cprintf(YELLOW, "0x%08x", sec->data_va); 426 cprintf(YELLOW, "0x%08x", sec->data_pa);
372 cprintf(RED, "-(dat)-"); 427 cprintf(RED, "-(dat)-");
373 cprintf(YELLOW, "0x%08x\n", sec->data_va + sec->data_sz); 428 cprintf(YELLOW, "0x%08x\n", sec->data_pa + sec->data_sz);
374 429
375 cprintf(GREEN, " Data: "); 430 cprintf(GREEN, " Data: ");
376 cprintf(RED, " "); 431 cprintf(RED, " ");
377 cprintf(BLUE, " |--> "); 432 cprintf(BLUE, " |--> ");
378 cprintf(YELLOW, "0x%08x", sec->bss_va); 433 cprintf(YELLOW, "0x%08x", sec->bss_pa);
379 cprintf(RED, "-(bss)-"); 434 cprintf(RED, "-(bss)-");
380 cprintf(YELLOW, "0x%08x\n", sec->bss_va + sec->bss_sz); 435 cprintf(YELLOW, "0x%08x\n", sec->bss_pa + sec->bss_sz);
436
437#define check_range_(start,sz) \
438 ((start) >= hdr_size && (start) + (sz) <= size)
439#define check_range(start,sz) \
440 ((start) >= hdr->addr && check_range_((start) - hdr->addr, sz))
441 /* check ranges */
442 if(sec->code_sz != 0 && !check_range(sec->code_va, sec->code_sz))
443 {
444 cprintf(GREY, "Invalid stage: out of bound code\n");
445 error = true;
446 break;
447 }
448 if(sec->data_sz != 0 && !check_range(sec->data_va, sec->data_sz))
449 {
450 cprintf(GREY, "Invalid stage: out of bound data\n");
451 error = true;
452 break;
453 }
454#undef check_range_
455#undef check_range
381 456
382#if 0 457 char buffer[32];
383 struct rknano_blob_t blob; 458 if(sec->code_sz != 0)
384 blob.offset = sec->code_pa - hdr->addr; 459 {
385 blob.size = sec->code_sz; 460 sprintf(buffer, ".text.%d", i);
386 save_blob(&blob, buf, size, "entry.", i, NO_ENC); 461 elf_add_load_section(&elf, sec->code_va, sec->code_sz,
387#else 462 buf + sec->code_va - hdr->addr, buffer);
388 struct elf_params_t elf; 463 }
389 elf_init(&elf); 464 if(sec->data_sz != 0)
390 elf_add_load_section(&elf, sec->code_va, sec->code_sz, buf + sec->code_pa - hdr->addr); 465 {
391 elf_add_load_section(&elf, sec->data_va, sec->data_sz, buf + sec->data_pa - hdr->addr); 466 sprintf(buffer, ".data.%d", i);
392 elf_add_fill_section(&elf, sec->bss_va, sec->bss_sz, 0); 467 elf_add_load_section(&elf, sec->data_va, sec->data_sz,
393 extract_elf_section(&elf, i); 468 buf + sec->data_va - hdr->addr, buffer);
394 elf_release(&elf); 469 }
395#endif 470 }
471 /* sort ranges and check overlap */
472 qsort(ranges, nr_ranges, sizeof(struct range_t), range_cmp);
473 for(int i = 1; i < nr_ranges; i++)
474 {
475 if(ranges[i - 1].start + ranges[i - 1].size > ranges[i].start)
476 {
477 error = true;
478 static const char *type[] = {"txt", "dat"};
479 cprintf(GREY, "Section overlap: section %d %s intersects section %d %s\n",
480 ranges[i - 1].section, type[ranges[i - 1].type], ranges[i].section,
481 type[ranges[i].type]);
482 break;
483 }
396 } 484 }
485 if(!error)
486 extract_elf_section(&elf);
487 /* FIXME for full information, we could add segments to the ELF file to
488 * keep the mapping, but it's unclear if that would do any good */
489 elf_release(&elf);
490 free(ranges);
397 491
398 return 0; 492 return 0;
399} 493}
400 494
495/**
496 * RKNano BOOT
497 * contains named bootloader stages
498 */
499
401#define MAGIC_BOOT "BOOT" 500#define MAGIC_BOOT "BOOT"
402#define MAGIC_BOOT_SIZE 4 501#define MAGIC_BOOT_SIZE 4
403 502
@@ -428,6 +527,8 @@ struct rknano_boot_header_t
428 uint32_t field_34; 527 uint32_t field_34;
429} __attribute__((packed)); 528} __attribute__((packed));
430 529
530#define BOOT_CHIP_RKNANO 0x30
531
431struct rknano_boot_entry_t 532struct rknano_boot_entry_t
432{ 533{
433 uint8_t entry_size; // unsure 534 uint8_t entry_size; // unsure
@@ -588,7 +689,7 @@ static int do_boot_image(uint8_t *buf, unsigned long size)
588 cprintf(RED, "OK\n"); 689 cprintf(RED, "OK\n");
589 else 690 else
590 cprintf(RED, "Mismatch\n"); 691 cprintf(RED, "Mismatch\n");
591 692
592#define print(str, name) cprintf(GREEN, " "str": ");cprintf(YELLOW, "%#x\n", (unsigned)hdr->name) 693#define print(str, name) cprintf(GREEN, " "str": ");cprintf(YELLOW, "%#x\n", (unsigned)hdr->name)
593#define print_arr(str, name, sz) \ 694#define print_arr(str, name, sz) \
594 cprintf(GREEN, " "str":");for(int i = 0; i < sz; i++)cprintf(YELLOW, " %#x", (unsigned)hdr->name[i]);printf("\n") 695 cprintf(GREEN, " "str":");for(int i = 0; i < sz; i++)cprintf(YELLOW, " %#x", (unsigned)hdr->name[i]);printf("\n")
@@ -602,8 +703,12 @@ static int do_boot_image(uint8_t *buf, unsigned long size)
602 hdr->hour, hdr->minute, hdr->second); 703 hdr->hour, hdr->minute, hdr->second);
603 704
604 cprintf(GREEN, " Chip: "); 705 cprintf(GREEN, " Chip: ");
605 cprintf(YELLOW, "%#x\n", hdr->chip); 706 cprintf(YELLOW, "%#x ", hdr->chip);
606 707 if(hdr->chip == BOOT_CHIP_RKNANO)
708 cprintf(RED, "(RKNANO)\n");
709 else
710 cprintf(RED, "(unknown)\n");
711
607 print_arr("field_2A", field_2B, 9); 712 print_arr("field_2A", field_2B, 9);
608 print("field_34", field_34); 713 print("field_34", field_34);
609 714
@@ -625,10 +730,15 @@ static int do_boot_image(uint8_t *buf, unsigned long size)
625 cprintf(RED, "OK\n"); 730 cprintf(RED, "OK\n");
626 else 731 else
627 cprintf(RED, "Mismatch\n"); 732 cprintf(RED, "Mismatch\n");
628 733
629 return 0; 734 return 0;
630} 735}
631 736
737/**
738 * RKFW
739 * contains bootloader and update
740 */
741
632typedef struct rknano_blob_t rkfw_blob_t; 742typedef struct rknano_blob_t rkfw_blob_t;
633 743
634#define MAGIC_RKFW "RKFW" 744#define MAGIC_RKFW "RKFW"
@@ -637,7 +747,7 @@ typedef struct rknano_blob_t rkfw_blob_t;
637struct rkfw_header_t 747struct rkfw_header_t
638{ 748{
639 char magic[MAGIC_RKFW_SIZE]; 749 char magic[MAGIC_RKFW_SIZE];
640 uint16_t hdr_size; // UNSURE 750 uint16_t hdr_size;
641 uint32_t version; 751 uint32_t version;
642 uint32_t code; 752 uint32_t code;
643 uint16_t year; 753 uint16_t year;
@@ -652,6 +762,8 @@ struct rkfw_header_t
652 uint8_t pad[61]; 762 uint8_t pad[61];
653} __attribute__((packed)); 763} __attribute__((packed));
654 764
765#define RKFW_CHIP_RKNANO 0x30
766
655static int do_rkfw_image(uint8_t *buf, unsigned long size) 767static int do_rkfw_image(uint8_t *buf, unsigned long size)
656{ 768{
657 if(size < sizeof(struct rkfw_header_t)) 769 if(size < sizeof(struct rkfw_header_t))
@@ -686,8 +798,12 @@ static int do_rkfw_image(uint8_t *buf, unsigned long size)
686 hdr->hour, hdr->minute, hdr->second); 798 hdr->hour, hdr->minute, hdr->second);
687 799
688 cprintf(GREEN, " Chip: "); 800 cprintf(GREEN, " Chip: ");
689 cprintf(YELLOW, "%#x\n", hdr->chip); 801 cprintf(YELLOW, "%#x ", hdr->chip);
690 802 if(hdr->chip == RKFW_CHIP_RKNANO)
803 cprintf(RED, "(RKNANO)\n");
804 else
805 cprintf(RED, "(unknown)\n");
806
691 cprintf(GREEN, " Loader: "); 807 cprintf(GREEN, " Loader: ");
692 print_blob_interval(&hdr->loader); 808 print_blob_interval(&hdr->loader);
693 cprintf(OFF, "\n"); 809 cprintf(OFF, "\n");
@@ -852,7 +968,7 @@ int main(int argc, char **argv)
852 perror("Cannot read file"); 968 perror("Cannot read file");
853 return 1; 969 return 1;
854 } 970 }
855 971
856 fclose(fin); 972 fclose(fin);
857 973
858 if(try_nanofw && !do_nanofw_image(buf, size)) 974 if(try_nanofw && !do_nanofw_image(buf, size))
@@ -873,4 +989,3 @@ int main(int argc, char **argv)
873 989
874 return 0; 990 return 0;
875} 991}
876