Rockbox open source high quality audio player as a Music Player Daemon
mpris rockbox mpd libadwaita audio rust zig deno
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

sbtools: now generate a db file along with with elf/rsrc files

Now always generate a "make.db" file which aims at being the exact
representation of the file, ie running sbtoelf and elftosb using
the generated command file should produce the exact same file
(except for the random paddings). We still miss the support
for some option parsing to achieve that though.

Change-Id: Ib7d6b241f7855fd35225df8ab8e0711f69d9ee5a

+315 -9
+1 -1
utils/imxtools/sbtools/Makefile
··· 10 10 %.o: %.c 11 11 $(CC) $(CFLAGS) -c -o $@ $< 12 12 13 - sbtoelf: sbtoelf.o crc.o crypto.o aes128.o sha1.o xorcrypt.o elf.o misc.o sb.o sb1.o 13 + sbtoelf: sbtoelf.o crc.o crypto.o aes128.o sha1.o xorcrypt.o dbparser.o elf.o misc.o sb.o sb1.o 14 14 $(LD) -o $@ $^ $(LDFLAGS) 15 15 16 16 elftosb: elftosb.o crc.o crypto.o aes128.o sha1.o elf.o dbparser.o misc.o sb.o
+226
utils/imxtools/sbtools/dbparser.c
··· 316 316 } 317 317 #endif 318 318 319 + struct cmd_option_t *db_add_opt(struct cmd_option_t **opt, const char *identifier, bool is_str) 320 + { 321 + while(*opt) 322 + opt = &(*opt)->next; 323 + *opt = xmalloc(sizeof(struct cmd_option_t)); 324 + memset(*opt, 0, sizeof(struct cmd_option_t)); 325 + (*opt)->name = strdup(identifier); 326 + (*opt)->is_string = is_str; 327 + return *opt; 328 + } 329 + 330 + void db_add_str_opt(struct cmd_option_t **opt, const char *name, const char *value) 331 + { 332 + db_add_opt(opt, name, true)->str = strdup(value); 333 + } 334 + 335 + void db_add_int_opt(struct cmd_option_t **opt, const char *name, uint32_t value) 336 + { 337 + db_add_opt(opt, name, false)->val = value; 338 + } 339 + 340 + static struct cmd_source_t *db_add_src(struct cmd_source_t **src, const char *identifier, bool is_extern) 341 + { 342 + while(*src) 343 + src = &(*src)->next; 344 + *src = xmalloc(sizeof(struct cmd_source_t)); 345 + memset(*src, 0, sizeof(struct cmd_source_t)); 346 + (*src)->identifier = strdup(identifier); 347 + (*src)->is_extern = is_extern; 348 + return *src; 349 + } 350 + 351 + void db_add_source(struct cmd_file_t *cmd_file, const char *identifier, const char *filename) 352 + { 353 + db_add_src(&cmd_file->source_list, identifier, false)->filename = strdup(filename); 354 + } 355 + 356 + void db_add_extern_source(struct cmd_file_t *cmd_file, const char *identifier, int extern_nr) 357 + { 358 + db_add_src(&cmd_file->source_list, identifier, false)->extern_nr = extern_nr; 359 + } 360 + 361 + static struct cmd_inst_t *db_add_inst(struct cmd_inst_t **list, enum cmd_inst_type_t type, 362 + uint32_t argument) 363 + { 364 + while(*list) 365 + list = &(*list)->next; 366 + *list = xmalloc(sizeof(struct cmd_inst_t)); 367 + memset(*list, 0, sizeof(struct cmd_inst_t)); 368 + (*list)->type = type; 369 + (*list)->argument = argument; 370 + return *list; 371 + } 372 + 373 + void db_add_inst_id(struct cmd_section_t *cmd_section, enum cmd_inst_type_t type, 374 + const char *identifier, uint32_t argument) 375 + { 376 + db_add_inst(&cmd_section->inst_list, type, argument)->identifier = strdup(identifier); 377 + } 378 + 379 + void db_add_inst_addr(struct cmd_section_t *cmd_section, enum cmd_inst_type_t type, 380 + uint32_t addr, uint32_t argument) 381 + { 382 + db_add_inst(&cmd_section->inst_list, type, argument)->addr = addr; 383 + } 384 + 385 + struct cmd_section_t *db_add_section(struct cmd_file_t *cmd_file, uint32_t identifier, bool data) 386 + { 387 + struct cmd_section_t **prev = &cmd_file->section_list; 388 + while(*prev) 389 + prev = &(*prev)->next; 390 + *prev = xmalloc(sizeof(struct cmd_section_t)); 391 + memset(*prev, 0, sizeof(struct cmd_section_t)); 392 + (*prev)->identifier = identifier; 393 + (*prev)->is_data = data; 394 + return *prev; 395 + } 396 + 319 397 struct cmd_source_t *db_find_source_by_id(struct cmd_file_t *cmd_file, const char *id) 320 398 { 321 399 struct cmd_source_t *src = cmd_file->source_list; ··· 379 457 return ver->major != INVALID_SB_SUBVERSION && 380 458 ver->minor != INVALID_SB_SUBVERSION && 381 459 ver->revision != INVALID_SB_SUBVERSION; 460 + } 461 + 462 + static bool db_generate_sb_subversion(uint16_t subver, char *str) 463 + { 464 + str[0] = '0' + ((subver >> 8) & 0xf); 465 + str[1] = '0' + ((subver >> 4) & 0xf); 466 + str[2] = '0' + (subver & 0xf); 467 + return true; 468 + } 469 + 470 + bool db_generate_sb_version(struct sb_version_t *ver, char *str, int size) 471 + { 472 + if(size < 12) 473 + return false; 474 + str[3] = '.'; 475 + str[7] = '.'; 476 + str[11] = 0; 477 + return db_generate_sb_subversion(ver->major, str) && 478 + db_generate_sb_subversion(ver->minor, str + 4) && 479 + db_generate_sb_subversion(ver->revision, str + 8); 382 480 } 383 481 384 482 #undef parse_error ··· 813 911 free(opt_list); 814 912 opt_list = next; 815 913 } 914 + } 915 + 916 + static bool db_generate_options(FILE *f, const char *secname, struct cmd_option_t *list) 917 + { 918 + fprintf(f, "%s\n", secname); 919 + fprintf(f, "{\n"); 920 + while(list) 921 + { 922 + fprintf(f, " %s = ", list->name); 923 + if(list->is_string) 924 + fprintf(f, "\"%s\";\n", list->str); // FIXME handle escape 925 + else 926 + fprintf(f, "0x%x;\n", list->val); 927 + list = list->next; 928 + } 929 + fprintf(f, "}\n"); 930 + return true; 931 + } 932 + 933 + static bool db_generate_section_options(FILE *f, struct cmd_option_t *list) 934 + { 935 + bool first = true; 936 + while(list) 937 + { 938 + fprintf(f, "%c %s = ", first ? ';' : ',', list->name); 939 + if(list->is_string) 940 + fprintf(f, "\"%s\"", list->str); // FIXME handle escape 941 + else 942 + fprintf(f, "0x%x", list->val); 943 + first = false; 944 + list = list->next; 945 + } 946 + return true; 947 + } 948 + 949 + static bool db_generate_sources(FILE *f, struct cmd_source_t *list) 950 + { 951 + fprintf(f, "sources\n"), 952 + fprintf(f, "{\n"); 953 + while(list) 954 + { 955 + fprintf(f, " %s = ", list->identifier); 956 + if(list->is_extern) 957 + fprintf(f, "extern(%d);\n", list->extern_nr); 958 + else 959 + fprintf(f, "\"%s\";\n", list->filename); // FIXME handle escape 960 + list = list->next; 961 + } 962 + fprintf(f, "}\n"); 963 + return true; 964 + } 965 + 966 + static bool db_generate_section(FILE *f, struct cmd_section_t *section) 967 + { 968 + fprintf(f, "section(%#x", section->identifier); 969 + db_generate_section_options(f, section->opt_list); 970 + if(section->is_data) 971 + { 972 + fprintf(f, ") <= %s;\n", section->source_id); 973 + return true; 974 + } 975 + fprintf(f, ")\n{\n"); 976 + struct cmd_inst_t *inst = section->inst_list; 977 + while(inst) 978 + { 979 + fprintf(f, " "); 980 + switch(inst->type) 981 + { 982 + case CMD_LOAD: 983 + fprintf(f, "load %s;\n", inst->identifier); 984 + break; 985 + case CMD_LOAD_AT: 986 + fprintf(f, "load %s > %#x;\n", inst->identifier, inst->addr); 987 + break; 988 + case CMD_CALL: 989 + fprintf(f, "call %s(%#x);\n", inst->identifier, inst->argument); 990 + break; 991 + case CMD_CALL_AT: 992 + fprintf(f, "call %#x(%#x);\n", inst->addr, inst->argument); 993 + break; 994 + case CMD_JUMP: 995 + fprintf(f, "jump %s(%#x);\n", inst->identifier, inst->argument); 996 + break; 997 + case CMD_JUMP_AT: 998 + fprintf(f, "jump %#x(%#x);\n", inst->addr, inst->argument); 999 + break; 1000 + case CMD_MODE: 1001 + fprintf(f, "mode %#x;\n", inst->argument); 1002 + break; 1003 + default: 1004 + bug("die"); 1005 + } 1006 + inst = inst->next; 1007 + } 1008 + fprintf(f, "}\n"); 1009 + return true; 1010 + } 1011 + 1012 + static bool db_generate_sections(FILE *f, struct cmd_section_t *section) 1013 + { 1014 + while(section) 1015 + if(!db_generate_section(f, section)) 1016 + return false; 1017 + else 1018 + section = section->next; 1019 + return true; 1020 + } 1021 + 1022 + bool db_generate_file(struct cmd_file_t *file, const char *filename, void *user, db_color_printf printf) 1023 + { 1024 + FILE *f = fopen(filename, "w"); 1025 + if(f == NULL) 1026 + return printf(user, true, GREY, "Cannot open '%s' for writing: %m\n", filename), false; 1027 + if(!db_generate_options(f, "constants", file->constant_list)) 1028 + goto Lerr; 1029 + if(!db_generate_options(f, "options", file->opt_list)) 1030 + goto Lerr; 1031 + if(!db_generate_sources(f, file->source_list)) 1032 + goto Lerr; 1033 + if(!db_generate_sections(f, file->section_list)) 1034 + goto Lerr; 1035 + 1036 + fclose(f); 1037 + return true; 1038 + 1039 + Lerr: 1040 + fclose(f); 1041 + return false; 816 1042 } 817 1043 818 1044 void db_free(struct cmd_file_t *file)
+17
utils/imxtools/sbtools/dbparser.h
··· 107 107 struct cmd_section_t *section_list; 108 108 }; 109 109 110 + typedef void (*db_color_printf)(void *u, bool err, color_t c, const char *f, ...); 111 + 110 112 struct cmd_source_t *db_find_source_by_id(struct cmd_file_t *cmd_file, const char *id); 111 113 struct cmd_option_t *db_find_option_by_id(struct cmd_option_t *opt, const char *name); 112 114 bool db_parse_sb_version(struct sb_version_t *ver, char *str); 115 + bool db_generate_sb_version(struct sb_version_t *ver, char *str, int size); 113 116 void db_generate_default_sb_version(struct sb_version_t *ver); 114 117 struct cmd_file_t *db_parse_file(const char *file); 118 + /* NOTE: db_add_{str_opt,int_opt,source,extern_source} add at the beginning of the list */ 119 + void db_add_str_opt(struct cmd_option_t **opt, const char *name, const char *str); 120 + void db_add_int_opt(struct cmd_option_t **opt, const char *name, uint32_t value); 121 + void db_add_source(struct cmd_file_t *cmd_file, const char *identifier, const char *filename); 122 + void db_add_inst_id(struct cmd_section_t *cmd_section, enum cmd_inst_type_t type, 123 + const char *identifier, uint32_t argument); 124 + void db_add_inst_addr(struct cmd_section_t *cmd_section, enum cmd_inst_type_t type, 125 + uint32_t addr, uint32_t argument); 126 + struct cmd_section_t *db_add_section(struct cmd_file_t *cmd_file, uint32_t identifier, bool data); 127 + void db_add_extern_source(struct cmd_file_t *cmd_file, const char *identifier, int extern_nr); 128 + bool db_generate_file(struct cmd_file_t *file, const char *filename, void *user, db_color_printf printf); 115 129 void db_free_option_list(struct cmd_option_t *opt_list); 116 130 void db_free(struct cmd_file_t *file); 131 + 132 + /* standard implementation: user is unused*/ 133 + void db_std_printf(void *user, bool error, color_t c, const char *fmt, ...); 117 134 118 135 #endif /* __DBPARSER__ */
+22 -1
utils/imxtools/sbtools/sb.c
··· 237 237 if(sb->minor_version >= 1) 238 238 memcpy(&sb_hdr->rand_pad0[2], "sgtl", 4); 239 239 240 - sb_hdr->timestamp = generate_timestamp(); 240 + if(sb->override_timestamp) 241 + sb_hdr->timestamp = sb->timestamp; 242 + else 243 + sb_hdr->timestamp = generate_timestamp(); 241 244 sb_hdr->product_ver = sb->product_ver; 242 245 fix_version(&sb_hdr->product_ver); 243 246 sb_hdr->component_ver = sb->component_ver; ··· 789 792 struct tm *time = gmtime(&seconds); 790 793 printf(GREEN, " Creation date/time = "); 791 794 printf(YELLOW, "%s", asctime(time)); 795 + sb_file->timestamp = sb_header->timestamp; 792 796 793 797 struct sb_version_t product_ver = sb_header->product_ver; 794 798 fix_version(&product_ver); ··· 1186 1190 char name[5]; 1187 1191 sb_fill_section_name(name, file->first_boot_sec_id); 1188 1192 printf(TEXT, "%08x (%s)\n", file->first_boot_sec_id, name); 1193 + printf(TREE, "+-"); 1194 + printf(HEADER, "Timestamp: "); 1195 + printf(TEXT, "%#llx", file->timestamp); 1196 + { 1197 + uint64_t micros = file->timestamp; 1198 + time_t seconds = (micros / (uint64_t)1000000L); 1199 + struct tm tm_base; 1200 + memset(&tm_base, 0, sizeof(tm_base)); 1201 + /* 2000/1/1 0:00:00 */ 1202 + tm_base.tm_mday = 1; 1203 + tm_base.tm_year = 100; 1204 + seconds += mktime(&tm_base); 1205 + struct tm *time = gmtime(&seconds); 1206 + char *str = asctime(time); 1207 + str[strlen(str) - 1] = 0; 1208 + printf(TEXT2, " (%s)\n", str); 1209 + } 1189 1210 1190 1211 if(file->override_real_key) 1191 1212 {
+3
utils/imxtools/sbtools/sb.h
··· 204 204 /* override crypto IV, use with caution ! Use NULL to generate it */ 205 205 bool override_crypto_iv; 206 206 uint8_t crypto_iv[16]; 207 + /* override timestamp */ 208 + bool override_timestamp; 209 + uint64_t timestamp; /* In microseconds since 2000/1/1 00:00:00 */ 207 210 208 211 int nr_sections; 209 212 uint16_t drive_tag;
+46 -7
utils/imxtools/sbtools/sbtoelf.c
··· 43 43 #include "sb.h" 44 44 #include "sb1.h" 45 45 #include "misc.h" 46 + #include "dbparser.h" 46 47 47 48 /* all blocks are sized as a multiple of 0x1ff */ 48 49 #define PAD_TO_BOUNDARY(x) (((x) + 0x1ff) & ~0x1ff) ··· 61 62 static char *g_out_prefix; 62 63 static bool g_elf_simplify = true; 63 64 64 - static void extract_elf_section(struct elf_params_t *elf, int count, uint32_t id) 65 + static void extract_elf_section(struct elf_params_t *elf, int count, uint32_t id, 66 + struct cmd_file_t *cmd_file, struct cmd_section_t *section, bool is_call, uint32_t arg) 65 67 { 66 68 char name[5]; 69 + char fileid[16]; 67 70 char *filename = xmalloc(strlen(g_out_prefix) + 32); 68 71 sb_fill_section_name(name, id); 72 + sb_fill_section_name(fileid, id); 73 + sprintf(fileid + strlen(fileid), "%d", count); 69 74 sprintf(filename, "%s%s.%d.elf", g_out_prefix, name, count); 75 + db_add_source(cmd_file, fileid, filename + strlen(g_out_prefix)); 76 + db_add_inst_id(section, CMD_LOAD, fileid, 0); 77 + if(elf_get_start_addr(elf, NULL)) 78 + db_add_inst_id(section, is_call ? CMD_CALL : CMD_JUMP, fileid, arg); 79 + 70 80 if(g_debug) 71 81 printf("Write boot section %s to %s\n", name, filename); 72 82 ··· 81 91 fclose(fd); 82 92 } 83 93 84 - static void extract_sb_section(struct sb_section_t *sec) 94 + static void extract_sb_section(struct sb_section_t *sec, struct cmd_file_t *cmd_file) 85 95 { 96 + struct cmd_section_t *db_sec = db_add_section(cmd_file, sec->identifier, sec->is_data); 97 + db_add_int_opt(&db_sec->opt_list, "alignment", sec->alignment); 98 + db_add_int_opt(&db_sec->opt_list, "cleartext", sec->is_cleartext); 99 + 86 100 if(sec->is_data) 87 101 { 88 102 char sec_name[5]; 89 103 char *filename = xmalloc(strlen(g_out_prefix) + 32); 90 104 sb_fill_section_name(sec_name, sec->identifier); 91 105 sprintf(filename, "%s%s.bin", g_out_prefix, sec_name); 106 + db_add_source(cmd_file, sec_name, filename + strlen(g_out_prefix)); 107 + db_sec->source_id = strdup(sec_name); 108 + 92 109 FILE *fd = fopen(filename, "wb"); 93 110 if(fd == NULL) 94 111 bugp("Cannot open %s for writing\n", filename); ··· 116 133 switch(inst->inst) 117 134 { 118 135 case SB_INST_LOAD: 119 - sprintf(secname, ".text%d", text_idx++); 136 + sprintf(secname, ".text%d", text_idx); 120 137 elf_add_load_section(&elf, inst->addr, inst->size, inst->data, secname); 121 138 break; 122 139 case SB_INST_FILL: ··· 126 143 case SB_INST_CALL: 127 144 case SB_INST_JUMP: 128 145 elf_set_start_addr(&elf, inst->addr); 129 - extract_elf_section(&elf, elf_count++, sec->identifier); 146 + extract_elf_section(&elf, elf_count++, sec->identifier, cmd_file, db_sec, 147 + inst->inst == SB_INST_CALL, inst->argument); 130 148 elf_release(&elf); 131 149 elf_init(&elf); 132 150 bss_idx = text_idx = 0; ··· 138 156 } 139 157 140 158 if(!elf_is_empty(&elf)) 141 - extract_elf_section(&elf, elf_count, sec->identifier); 159 + extract_elf_section(&elf, elf_count, sec->identifier, cmd_file, db_sec, false, 0); 142 160 elf_release(&elf); 143 161 } 144 162 145 163 static void extract_sb_file(struct sb_file_t *file) 146 164 { 165 + char buffer[64]; 166 + struct cmd_file_t *cmd_file = xmalloc(sizeof(struct cmd_file_t)); 167 + memset(cmd_file, 0, sizeof(struct cmd_file_t)); 168 + db_generate_sb_version(&file->product_ver, buffer, sizeof(buffer)); 169 + db_add_str_opt(&cmd_file->opt_list, "productVersion", buffer); 170 + db_generate_sb_version(&file->component_ver, buffer, sizeof(buffer)); 171 + db_add_str_opt(&cmd_file->opt_list, "componentVersion", buffer); 172 + db_add_int_opt(&cmd_file->opt_list, "driveTag", file->drive_tag); 173 + db_add_int_opt(&cmd_file->opt_list, "flags", file->flags); 174 + db_add_int_opt(&cmd_file->opt_list, "timestampLow", file->timestamp & 0xffffffff); 175 + db_add_int_opt(&cmd_file->opt_list, "timestampHigh", file->timestamp >> 32); 176 + db_add_int_opt(&cmd_file->opt_list, "sbMinorVersion", file->minor_version); 177 + 147 178 for(int i = 0; i < file->nr_sections; i++) 148 - extract_sb_section(&file->sections[i]); 179 + extract_sb_section(&file->sections[i], cmd_file); 180 + 181 + char *filename = xmalloc(strlen(g_out_prefix) + 32); 182 + sprintf(filename, "%smake.db", g_out_prefix); 183 + if(g_debug) 184 + printf("Write command file to %s\n", filename); 185 + db_generate_file(cmd_file, filename, NULL, generic_std_printf); 186 + db_free(cmd_file); 149 187 } 150 188 151 189 static void extract_elf(struct elf_params_t *elf, int count) 152 190 { 153 191 char *filename = xmalloc(strlen(g_out_prefix) + 32); 154 - sprintf(filename, "%s.%d.elf", g_out_prefix, count); 192 + sprintf(filename, "%s%d.elf", g_out_prefix, count); 155 193 if(g_debug) 156 194 printf("Write boot content to %s\n", filename); 157 195 ··· 375 413 * garbage */ 376 414 file->override_real_key = false; 377 415 file->override_crypto_iv = false; 416 + file->override_timestamp = true; 378 417 sb_write_file(file, loopback, 0, generic_std_printf); 379 418 } 380 419 sb_free(file);