A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd

atjboottool: put afi and fw code in its own files

Change-Id: I16347ebee0f82d5fdf32f5aa8f955c07fe148eba

+499 -392
+1 -1
utils/atj2137/atjboottool/Makefile
··· 10 10 %.o: %.c 11 11 $(CC) $(CFLAGS) -c -o $@ $< 12 12 13 - atjboottool: atjboottool.o fwu.o misc.o atj_tables.o 13 + atjboottool: atjboottool.o fwu.o fw.o afi.o misc.o atj_tables.o 14 14 $(LD) -o $@ $^ $(LDFLAGS) 15 15 16 16 clean:
+208
utils/atj2137/atjboottool/afi.c
··· 1 + /*************************************************************************** 2 + * __________ __ ___. 3 + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 + * \/ \/ \/ \/ \/ 8 + * $Id$ 9 + * 10 + * Copyright (C) 2017 Amaury Pouly 11 + * 12 + * This program is free software; you can redistribute it and/or 13 + * modify it under the terms of the GNU General Public License 14 + * as published by the Free Software Foundation; either version 2 15 + * of the License, or (at your option) any later version. 16 + * 17 + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 + * KIND, either express or implied. 19 + * 20 + ****************************************************************************/ 21 + #include <string.h> 22 + #include <stdlib.h> 23 + #include <ctype.h> 24 + #include "misc.h" 25 + #include "afi.h" 26 + 27 + /** part of this work comes from s1mp3/s1fwx */ 28 + 29 + #define AFI_ENTRIES 126 30 + #define AFI_SIG_SIZE 4 31 + 32 + struct afi_hdr_t 33 + { 34 + uint8_t sig[AFI_SIG_SIZE]; 35 + uint16_t vendor_id; 36 + uint16_t product_id; 37 + uint8_t ver_id[2]; 38 + uint8_t ext_ver_id[2]; 39 + uint8_t year[2]; 40 + uint8_t month; 41 + uint8_t day; 42 + uint32_t afi_size; 43 + uint32_t res[3]; 44 + } __attribute__((packed)); 45 + 46 + struct afi_entry_t 47 + { 48 + char name[8]; 49 + char ext[3]; 50 + char type; 51 + uint32_t addr; 52 + uint32_t offset; 53 + uint32_t size; 54 + char desc[4]; 55 + uint32_t checksum; 56 + } __attribute__((packed)); 57 + 58 + struct afi_post_hdr_t 59 + { 60 + uint8_t res[28]; 61 + uint32_t checksum; 62 + } __attribute__((packed)); 63 + 64 + struct afi_t 65 + { 66 + struct afi_hdr_t hdr; 67 + struct afi_entry_t entry[AFI_ENTRIES]; 68 + struct afi_post_hdr_t post; 69 + }; 70 + 71 + #define AFI_ENTRY_BREC 'B' 72 + #define AFI_ENTRY_FWSC 'F' 73 + #define AFI_ENTRY_ADFUS 'A' 74 + #define AFI_ENTRY_FW 'I' 75 + 76 + #define AFI_ENTRY_DLADR_BREC 0x00000006 // 'B' 77 + #define AFI_ENTRY_DLADR_FWSC 0x00020008 // 'F' 78 + #define AFI_ENTRY_DLADR_ADFUS 0x000C0008 // 'A' 79 + #define AFI_ENTRY_DLADR_ADFU 0x00000000 // 'U' 80 + #define AFI_ENTRY_DLADR_FW 0x00000011 // 'I' 81 + 82 + const uint8_t g_afi_signature[AFI_SIG_SIZE] = 83 + { 84 + 'A', 'F', 'I', 0 85 + }; 86 + 87 + uint32_t afi_checksum(void *ptr, size_t size) 88 + { 89 + uint32_t crc = 0; 90 + uint32_t *cp = ptr; 91 + for(; size >= 4; size -= 4) 92 + crc += *cp++; 93 + if(size == 1) 94 + crc += *(uint8_t *)cp; 95 + else if(size == 2) 96 + crc += *(uint16_t *)cp; 97 + else if(size == 3) 98 + crc += *(uint16_t *)cp + ((*(uint8_t *)(cp + 2)) << 16); 99 + return crc; 100 + } 101 + 102 + static void build_filename(char buf[16], struct afi_entry_t *ent) 103 + { 104 + int pos = 0; 105 + for(int i = 0; i < 8 && ent->name[i] != ' '; i++) 106 + buf[pos++] = ent->name[i]; 107 + buf[pos++] = '.'; 108 + for(int i = 0; i < 3 && ent->ext[i] != ' '; i++) 109 + buf[pos++] = ent->ext[i]; 110 + buf[pos] = 0; 111 + } 112 + 113 + int afi_unpack(uint8_t *buf, size_t size, afi_extract_callback_t unpack_cb) 114 + { 115 + struct afi_t *afi = (void *)buf; 116 + 117 + if(size < sizeof(struct afi_t)) 118 + { 119 + cprintf(GREY, "File too small\n"); 120 + return 1; 121 + } 122 + cprintf(BLUE, "Header\n"); 123 + cprintf(GREEN, " Signature:"); 124 + for(int i = 0; i < AFI_SIG_SIZE; i++) 125 + cprintf(YELLOW, " %02x", afi->hdr.sig[i]); 126 + if(memcmp(afi->hdr.sig, g_afi_signature, AFI_SIG_SIZE) == 0) 127 + cprintf(RED, " Ok\n"); 128 + else 129 + { 130 + cprintf(RED, " Mismatch\n"); 131 + return 1; 132 + } 133 + 134 + cprintf_field(" Vendor ID: ", "0x%x\n", afi->hdr.vendor_id); 135 + cprintf_field(" Product ID: ", "0x%x\n", afi->hdr.product_id); 136 + cprintf_field(" Version: ", "%x.%x\n", afi->hdr.ver_id[0], afi->hdr.ver_id[1]); 137 + cprintf_field(" Ext Version: ", "%x.%x\n", afi->hdr.ext_ver_id[0], 138 + afi->hdr.ext_ver_id[1]); 139 + cprintf_field(" Date: ", "%02x/%02x/%02x%02x\n", afi->hdr.day, afi->hdr.month, 140 + afi->hdr.year[0], afi->hdr.year[1]); 141 + 142 + cprintf_field(" AFI size: ", "%d ", afi->hdr.afi_size); 143 + if(afi->hdr.afi_size == size) 144 + cprintf(RED, " Ok\n"); 145 + else if(afi->hdr.afi_size < size) 146 + cprintf(RED, " Ok (file greater than archive)\n"); 147 + else 148 + { 149 + cprintf(RED, " Error (file too small)\n"); 150 + return 1; 151 + } 152 + 153 + cprintf_field(" Reserved: ", "%x %x %x\n", afi->hdr.res[0], 154 + afi->hdr.res[1], afi->hdr.res[2]); 155 + 156 + cprintf(BLUE, "Entries\n"); 157 + for(int i = 0; i < AFI_ENTRIES; i++) 158 + { 159 + if(afi->entry[i].name[0] == 0) 160 + continue; 161 + struct afi_entry_t *entry = &afi->entry[i]; 162 + char filename[16]; 163 + build_filename(filename, entry); 164 + cprintf(RED, " %s\n", filename); 165 + cprintf_field(" Type: ", "%02x", entry->type); 166 + if(isprint(entry->type)) 167 + cprintf(RED, " %c", entry->type); 168 + printf("\n"); 169 + cprintf_field(" Addr: ", "0x%x\n", entry->addr); 170 + cprintf_field(" Offset: ", "0x%x\n", entry->offset); 171 + cprintf_field(" Size: ", "0x%x\n", entry->size); 172 + cprintf_field(" Desc: ", "%.4s\n", entry->desc); 173 + cprintf_field(" Checksum: ", "0x%x ", entry->checksum); 174 + uint32_t chk = afi_checksum(buf + entry->offset, entry->size); 175 + if(chk != entry->checksum) 176 + { 177 + cprintf(RED, "Mismatch\n"); 178 + return 1; 179 + } 180 + else 181 + cprintf(RED, "Ok\n"); 182 + int ret = unpack_cb(filename, buf + entry->offset, entry->size); 183 + if(ret != 0) 184 + return ret; 185 + } 186 + 187 + cprintf(BLUE, "Post Header\n"); 188 + cprintf_field(" Checksum: ", "%x ", afi->post.checksum); 189 + uint32_t chk = afi_checksum(buf, sizeof(struct afi_t) - 4); 190 + if(chk != afi->post.checksum) 191 + { 192 + cprintf(RED, "Mismatch\n"); 193 + return 1; 194 + } 195 + else 196 + cprintf(RED, "Ok\n"); 197 + 198 + return 0; 199 + } 200 + 201 + bool afi_check(uint8_t *buf, size_t size) 202 + { 203 + struct afi_hdr_t *hdr = (void *)buf; 204 + 205 + if(size < sizeof(struct afi_hdr_t)) 206 + return false; 207 + return memcmp(hdr->sig, g_afi_signature, AFI_SIG_SIZE) == 0; 208 + }
+7 -1
utils/atj2137/atjboottool/afi.h
··· 23 23 24 24 #include <stdint.h> 25 25 26 - /* Check if a file looks like a FWU file */ 26 + uint32_t afi_checksum(void *ptr, size_t size); 27 + /* Unpack an AFI file: the callback function will be called once for each file in the archive with 28 + * its name and content. If the callback returns a nonzero value, the function will stop and return 29 + * that value. Returns 0 on success */ 30 + typedef int (*afi_extract_callback_t)(const char *name, uint8_t *buf, size_t size); 31 + int afi_unpack(uint8_t *buf, size_t size, afi_extract_callback_t cb); 32 + /* Check if a file looks like an AFI file */ 27 33 bool afi_check(uint8_t *buf, size_t size); 28 34 29 35 #endif /* __AFI_H__ */
+31 -385
utils/atj2137/atjboottool/atjboottool.c
··· 29 29 #include <sys/stat.h> 30 30 #include "misc.h" 31 31 #include "fwu.h" 32 + #include "afi.h" 33 + #include "fw.h" 32 34 33 35 bool g_debug = false; 34 36 char *g_out_prefix = NULL; ··· 89 91 } 90 92 } 91 93 92 - /** 93 - * AFI 94 - * 95 - * part of this work comes from s1mp3/s1fwx 96 - **/ 97 - 98 - #define AFI_ENTRIES 126 99 - #define AFI_SIG_SIZE 4 100 - 101 - struct afi_hdr_t 102 - { 103 - uint8_t sig[AFI_SIG_SIZE]; 104 - uint16_t vendor_id; 105 - uint16_t product_id; 106 - uint8_t ver_id[2]; 107 - uint8_t ext_ver_id[2]; 108 - uint8_t year[2]; 109 - uint8_t month; 110 - uint8_t day; 111 - uint32_t afi_size; 112 - uint32_t res[3]; 113 - } __attribute__((packed)); 114 - 115 - struct afi_entry_t 116 - { 117 - char name[8]; 118 - char ext[3]; 119 - char type; 120 - uint32_t addr; 121 - uint32_t offset; 122 - uint32_t size; 123 - char desc[4]; 124 - uint32_t checksum; 125 - } __attribute__((packed)); 126 - 127 - struct afi_post_hdr_t 128 - { 129 - uint8_t res[28]; 130 - uint32_t checksum; 131 - } __attribute__((packed)); 132 - 133 - struct afi_t 134 - { 135 - struct afi_hdr_t hdr; 136 - struct afi_entry_t entry[AFI_ENTRIES]; 137 - struct afi_post_hdr_t post; 138 - }; 139 - 140 - #define AFI_ENTRY_BREC 'B' 141 - #define AFI_ENTRY_FWSC 'F' 142 - #define AFI_ENTRY_ADFUS 'A' 143 - #define AFI_ENTRY_FW 'I' 144 - 145 - #define AFI_ENTRY_DLADR_BREC 0x00000006 // 'B' 146 - #define AFI_ENTRY_DLADR_FWSC 0x00020008 // 'F' 147 - #define AFI_ENTRY_DLADR_ADFUS 0x000C0008 // 'A' 148 - #define AFI_ENTRY_DLADR_ADFU 0x00000000 // 'U' 149 - #define AFI_ENTRY_DLADR_FW 0x00000011 // 'I' 150 - 151 - const uint8_t g_afi_signature[AFI_SIG_SIZE] = 152 - { 153 - 'A', 'F', 'I', 0 154 - }; 155 - 156 - static uint32_t afi_checksum(void *ptr, int size) 157 - { 158 - uint32_t crc = 0; 159 - uint32_t *cp = ptr; 160 - for(; size >= 4; size -= 4) 161 - crc += *cp++; 162 - if(size == 1) 163 - crc += *(uint8_t *)cp; 164 - else if(size == 2) 165 - crc += *(uint16_t *)cp; 166 - else if(size == 3) 167 - crc += *(uint16_t *)cp + ((*(uint8_t *)(cp + 2)) << 16); 168 - return crc; 169 - } 170 - 171 - static void build_filename(char buf[16], struct afi_entry_t *ent) 172 - { 173 - int pos = 0; 174 - for(int i = 0; i < 8 && ent->name[i] != ' '; i++) 175 - buf[pos++] = ent->name[i]; 176 - buf[pos++] = '.'; 177 - for(int i = 0; i < 3 && ent->ext[i] != ' '; i++) 178 - buf[pos++] = ent->ext[i]; 179 - buf[pos] = 0; 180 - } 181 - 182 - static int do_afi(uint8_t *buf, int size) 94 + static int unpack_afi_fw_cb(const char *filename, uint8_t *buf, size_t size) 183 95 { 184 - struct afi_t *afi = (void *)buf; 96 + char *name = malloc(strlen(g_out_prefix) + strlen(filename) + 16); 97 + sprintf(name, "%s%s", g_out_prefix, filename); 185 98 186 - if(size < (int)sizeof(struct afi_t)) 187 - { 188 - cprintf(GREY, "File too small\n"); 189 - return 1; 190 - } 191 - cprintf(BLUE, "Header\n"); 192 - cprintf(GREEN, " Signature:"); 193 - for(int i = 0; i < AFI_SIG_SIZE; i++) 194 - cprintf(YELLOW, " %02x", afi->hdr.sig[i]); 195 - if(memcmp(afi->hdr.sig, g_afi_signature, AFI_SIG_SIZE) == 0) 196 - cprintf(RED, " Ok\n"); 197 - else 99 + cprintf(GREY, "Unpacking to %s... ", name); 100 + FILE *f = fopen(name, "wb"); 101 + if(f) 198 102 { 199 - cprintf(RED, " Mismatch\n"); 200 - return 1; 103 + fwrite(buf, size, 1, f); 104 + fclose(f); 105 + cprintf(RED, "Ok\n"); 106 + return 0; 201 107 } 202 - 203 - cprintf_field(" Vendor ID: ", "0x%x\n", afi->hdr.vendor_id); 204 - cprintf_field(" Product ID: ", "0x%x\n", afi->hdr.product_id); 205 - cprintf_field(" Version: ", "%x.%x\n", afi->hdr.ver_id[0], afi->hdr.ver_id[1]); 206 - cprintf_field(" Ext Version: ", "%x.%x\n", afi->hdr.ext_ver_id[0], 207 - afi->hdr.ext_ver_id[1]); 208 - cprintf_field(" Date: ", "%02x/%02x/%02x%02x\n", afi->hdr.day, afi->hdr.month, 209 - afi->hdr.year[0], afi->hdr.year[1]); 210 - 211 - cprintf_field(" AFI size: ", "%d ", afi->hdr.afi_size); 212 - if((int)afi->hdr.afi_size == size) 213 - cprintf(RED, " Ok\n"); 214 - else if((int)afi->hdr.afi_size < size) 215 - cprintf(RED, " Ok (file greater than archive)\n"); 216 108 else 217 109 { 218 - cprintf(RED, " Error (file too small)\n"); 110 + color(RED); 111 + perror("Failed"); 219 112 return 1; 220 113 } 221 - 222 - cprintf_field(" Reserved: ", "%x %x %x\n", afi->hdr.res[0], 223 - afi->hdr.res[1], afi->hdr.res[2]); 224 - 225 - build_out_prefix(".fw", "", true); 226 - 227 - cprintf(BLUE, "Entries\n"); 228 - for(int i = 0; i < AFI_ENTRIES; i++) 229 - { 230 - if(afi->entry[i].name[0] == 0) 231 - continue; 232 - struct afi_entry_t *entry = &afi->entry[i]; 233 - char filename[16]; 234 - build_filename(filename, entry); 235 - cprintf(RED, " %s\n", filename); 236 - cprintf_field(" Type: ", "%02x", entry->type); 237 - if(isprint(entry->type)) 238 - cprintf(RED, " %c", entry->type); 239 - printf("\n"); 240 - cprintf_field(" Addr: ", "0x%x\n", entry->addr); 241 - cprintf_field(" Offset: ", "0x%x\n", entry->offset); 242 - cprintf_field(" Size: ", "0x%x\n", entry->size); 243 - cprintf_field(" Desc: ", "%.4s\n", entry->desc); 244 - cprintf_field(" Checksum: ", "0x%x ", entry->checksum); 245 - uint32_t chk = afi_checksum(buf + entry->offset, entry->size); 246 - cprintf(RED, "%s\n", chk == entry->checksum ? "Ok" : "Mismatch"); 247 - 248 - char *name = malloc(strlen(g_out_prefix) + strlen(filename) + 16); 249 - sprintf(name, "%s%s", g_out_prefix, filename); 250 - 251 - cprintf(GREY, "Unpacking to %s... ", name); 252 - FILE *f = fopen(name, "wb"); 253 - if(f) 254 - { 255 - fwrite(buf + entry->offset, entry->size, 1, f); 256 - fclose(f); 257 - cprintf(RED, "Ok\n"); 258 - } 259 - else 260 - cprintf(RED, "Failed: %m\n"); 261 - } 262 - 263 - cprintf(BLUE, "Post Header\n"); 264 - cprintf_field(" Checksum: ", "%x ", afi->post.checksum); 265 - uint32_t chk = afi_checksum(buf, sizeof(struct afi_t) - 4); 266 - cprintf(RED, "%s\n", chk == afi->post.checksum ? "Ok" : "Mismatch"); 267 - 268 - return 0; 269 114 } 270 115 271 - bool afi_check(uint8_t *buf, int size) 272 - { 273 - struct afi_hdr_t *hdr = (void *)buf; 274 - 275 - if(size < (int)sizeof(struct afi_hdr_t)) 276 - return false; 277 - return memcmp(hdr->sig, g_afi_signature, AFI_SIG_SIZE) == 0; 278 - } 279 - 280 - /** 281 - * FW 282 - **/ 283 - 284 - #define FW_SIG_SIZE 4 285 - 286 - #define FW_ENTRIES 240 287 - 288 - struct fw_entry_t 289 - { 290 - char name[8]; 291 - char ext[3]; 292 - uint8_t attr; 293 - uint8_t res[2]; 294 - uint16_t version; 295 - uint32_t block_offset; // offset shift by 9 296 - uint32_t size; 297 - uint32_t unk; 298 - uint32_t checksum; 299 - } __attribute__((packed)); 300 - 301 - struct fw_hdr_t 302 - { 303 - uint8_t sig[FW_SIG_SIZE]; 304 - uint32_t res[4]; 305 - uint8_t year[2]; 306 - uint8_t month; 307 - uint8_t day; 308 - uint16_t usb_vid; 309 - uint16_t usb_pid; 310 - uint32_t checksum; 311 - char productor[16]; 312 - char str2[16]; 313 - char str3[32]; 314 - char dev_name[32]; 315 - uint8_t res2[8 * 16]; 316 - char usb_name1[8]; 317 - char usb_name2[8]; 318 - char res3[4 * 16 + 1]; 319 - char mtp_name1[33]; 320 - char mtp_name2[33]; 321 - char mtp_ver[33]; 322 - uint16_t mtp_vid; 323 - uint16_t mtp_pid; 324 - char fw_ver[64]; 325 - uint32_t res4[2]; 326 - 327 - struct fw_entry_t entry[FW_ENTRIES]; 328 - } __attribute__((packed)); 329 - 330 - /* the s1fwx source code has a layout but it does not make any sense for firmwares 331 - * found in ATJ2127 for example. In doubt just don't do anything */ 332 - struct fw_hdr_f0_t 333 - { 334 - uint8_t sig[FW_SIG_SIZE]; 335 - uint8_t res[12]; 336 - uint32_t checksum; 337 - uint8_t res2[492]; 338 - 339 - struct fw_entry_t entry[FW_ENTRIES]; 340 - } __attribute__((packed)); 341 - 342 - const uint8_t g_fw_signature_f2[FW_SIG_SIZE] = 343 - { 344 - 0x55, 0xaa, 0xf2, 0x0f 345 - }; 346 - 347 - const uint8_t g_fw_signature_f0[FW_SIG_SIZE] = 116 + static int do_afi(uint8_t *buf, size_t size) 348 117 { 349 - 0x55, 0xaa, 0xf0, 0x0f 350 - }; 351 - 352 - static void build_filename_fw(char buf[16], struct fw_entry_t *ent) 353 - { 354 - int pos = 0; 355 - for(int i = 0; i < 8 && ent->name[i] != ' '; i++) 356 - buf[pos++] = ent->name[i]; 357 - buf[pos++] = '.'; 358 - for(int i = 0; i < 3 && ent->ext[i] != ' '; i++) 359 - buf[pos++] = ent->ext[i]; 360 - buf[pos] = 0; 118 + build_out_prefix(".fw", "", true); 119 + return afi_unpack(buf, size, &unpack_afi_fw_cb); 361 120 } 362 121 363 - static int do_fw(uint8_t *buf, int size) 122 + static int do_fw(uint8_t *buf, size_t size) 364 123 { 365 - struct fw_hdr_t *hdr = (void *)buf; 366 - 367 - if(size < (int)sizeof(struct fw_hdr_t)) 368 - { 369 - cprintf(GREY, "File too small\n"); 370 - return 1; 371 - } 372 - cprintf(BLUE, "Header\n"); 373 - cprintf(GREEN, " Signature:"); 374 - for(int i = 0; i < FW_SIG_SIZE; i++) 375 - cprintf(YELLOW, " %02x", hdr->sig[i]); 376 - int variant = 0; 377 - if(memcmp(hdr->sig, g_fw_signature_f2, FW_SIG_SIZE) == 0) 378 - { 379 - variant = 0xf2; 380 - cprintf(RED, " Ok (f2 variant)\n"); 381 - } 382 - else if(memcmp(hdr->sig, g_fw_signature_f0, FW_SIG_SIZE) == 0) 383 - { 384 - variant = 0xf0; 385 - cprintf(RED, " Ok (f0 variant)\n"); 386 - } 387 - else 388 - { 389 - cprintf(RED, " Mismatch\n"); 390 - return 1; 391 - } 392 - 393 - /* both variants have the same header size, only the fields differ */ 394 - if(variant == 0xf2) 395 - { 396 - cprintf_field(" USB VID: ", "0x%x\n", hdr->usb_vid); 397 - cprintf_field(" USB PID: ", "0x%x\n", hdr->usb_pid); 398 - cprintf_field(" Date: ", "%x/%x/%02x%02x\n", hdr->day, hdr->month, hdr->year[0], hdr->year[1]); 399 - cprintf_field(" Checksum: ", "%x\n", hdr->checksum); 400 - cprintf_field(" Productor: ", "%.16s\n", hdr->productor); 401 - cprintf_field(" String 2: ", "%.16s\n", hdr->str2); 402 - cprintf_field(" String 3: ", "%.32s\n", hdr->str3); 403 - cprintf_field(" Device Name: ", "%.32s\n", hdr->dev_name); 404 - cprintf(GREEN, " Unknown:\n"); 405 - for(int i = 0; i < 8; i++) 406 - { 407 - cprintf(YELLOW, " "); 408 - for(int j = 0; j < 16; j++) 409 - cprintf(YELLOW, "%02x ", hdr->res2[i * 16 + j]); 410 - cprintf(YELLOW, "\n"); 411 - } 412 - cprintf_field(" USB Name 1: ", "%.8s\n", hdr->usb_name1); 413 - cprintf_field(" USB Name 2: ", "%.8s\n", hdr->usb_name2); 414 - cprintf_field(" MTP Name 1: ", "%.32s\n", hdr->mtp_name1); 415 - cprintf_field(" MTP Name 2: ", "%.32s\n", hdr->mtp_name2); 416 - cprintf_field(" MTP Version: ", "%.32s\n", hdr->mtp_ver); 417 - 418 - cprintf_field(" MTP VID: ", "0x%x\n", hdr->mtp_vid); 419 - cprintf_field(" MTP PID: ", "0x%x\n", hdr->mtp_pid); 420 - cprintf_field(" FW Version: ", "%.64s\n", hdr->fw_ver); 421 - } 422 - else 423 - { 424 - /* struct fw_hdr_f0_t *hdr_f0 = (void *)hdr; */ 425 - cprintf(GREEN, " Header not dumped because format is unclear.\n"); 426 - } 427 - 428 124 build_out_prefix(".unpack", "", true); 429 - 430 - cprintf(BLUE, "Entries\n"); 431 - for(int i = 0; i < AFI_ENTRIES; i++) 432 - { 433 - if(hdr->entry[i].name[0] == 0) 434 - continue; 435 - struct fw_entry_t *entry = &hdr->entry[i]; 436 - char filename[16]; 437 - build_filename_fw(filename, entry); 438 - cprintf(RED, " %s\n", filename); 439 - cprintf_field(" Attr: ", "%02x\n", entry->attr); 440 - cprintf_field(" Offset: ", "0x%x\n", entry->block_offset << 9); 441 - cprintf_field(" Size: ", "0x%x\n", entry->size); 442 - cprintf_field(" Unknown: ", "%x\n", entry->unk); 443 - cprintf_field(" Checksum: ", "0x%x ", entry->checksum); 444 - uint32_t chk = afi_checksum(buf + (entry->block_offset << 9), entry->size); 445 - cprintf(RED, "%s\n", chk == entry->checksum ? "Ok" : "Mismatch"); 446 - if(g_out_prefix) 447 - { 448 - char *name = malloc(strlen(g_out_prefix) + strlen(filename) + 16); 449 - sprintf(name, "%s%s", g_out_prefix, filename); 450 - 451 - cprintf(GREY, "Unpacking to %s... ", name); 452 - FILE *f = fopen(name, "wb"); 453 - if(f) 454 - { 455 - fwrite(buf + (entry->block_offset << 9), entry->size, 1, f); 456 - fclose(f); 457 - cprintf(RED, "Ok\n"); 458 - } 459 - else 460 - cprintf(RED, "Failed: %m\n"); 461 - } 462 - } 463 - 464 - return 0; 465 - } 466 - 467 - static bool check_fw(uint8_t *buf, int size) 468 - { 469 - struct fw_hdr_t *hdr = (void *)buf; 470 - 471 - if(size < (int)sizeof(struct fw_hdr_t)) 472 - return false; 473 - if(memcmp(hdr->sig, g_fw_signature_f2, FW_SIG_SIZE) == 0) 474 - return true; 475 - if(memcmp(hdr->sig, g_fw_signature_f0, FW_SIG_SIZE) == 0) 476 - return true; 477 - return false; 125 + return fw_unpack(buf, size, &unpack_afi_fw_cb); 478 126 } 479 - 480 127 static void usage(void) 481 128 { 482 129 printf("Usage: atjboottool [options] firmware\n"); 483 130 printf("Options:\n"); 484 - printf(" -o <prefix>\tSet output prefix\n"); 485 - printf(" -f/--force\tForce to continue on errors\n"); 486 - printf(" -?/--help\tDisplay this message\n"); 487 - printf(" -d/--debug\tDisplay debug messages\n"); 488 - printf(" -c/--no-color\tDisable color output\n"); 489 - printf(" --fwu\tUnpack a FWU firmware file\n"); 490 - printf(" --afi\tUnpack a AFI archive file\n"); 491 - printf(" --fw\tUnpack a FW archive file\n"); 492 - printf(" --atj2127\tForce ATJ2127 decryption mode\n"); 131 + printf(" -o <path> Set output file or output prefix\n"); 132 + printf(" -h/--help Display this message\n"); 133 + printf(" -d/--debug Display debug messages\n"); 134 + printf(" -c/--no-color Disable color output\n"); 135 + printf(" --fwu Unpack a FWU firmware file\n"); 136 + printf(" --afi Unpack a AFI archive file\n"); 137 + printf(" --fw Unpack a FW archive file\n"); 138 + printf(" --atj2127 Force ATJ2127 decryption mode\n"); 493 139 printf("The default is to try to guess the format.\n"); 494 140 printf("If several formats are specified, all are tried.\n"); 495 141 printf("If no output prefix is specified, a default one is picked.\n"); ··· 507 153 { 508 154 static struct option long_options[] = 509 155 { 510 - {"help", no_argument, 0, '?'}, 156 + {"help", no_argument, 0, 'h'}, 511 157 {"debug", no_argument, 0, 'd'}, 512 158 {"no-color", no_argument, 0, 'c'}, 513 159 {"fwu", no_argument, 0, 'u'}, ··· 517 163 {0, 0, 0, 0} 518 164 }; 519 165 520 - int c = getopt_long(argc, argv, "?dcfo:a1", long_options, NULL); 166 + int c = getopt_long(argc, argv, "hdco:a2", long_options, NULL); 521 167 if(c == -1) 522 168 break; 523 169 switch(c) ··· 531 177 g_debug = true; 532 178 break; 533 179 break; 534 - case '?': 180 + case 'h': 535 181 usage(); 536 182 break; 537 183 case 'o': ··· 591 237 ret = do_fwu(buf, size, fwu_mode); 592 238 else if(try_afi || afi_check(buf, size)) 593 239 ret = do_afi(buf, size); 594 - else if(try_fw || check_fw(buf, size)) 240 + else if(try_fw || fw_check(buf, size)) 595 241 ret = do_fw(buf, size); 596 242 else 597 243 {
+213
utils/atj2137/atjboottool/fw.c
··· 1 + /*************************************************************************** 2 + * __________ __ ___. 3 + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 + * \/ \/ \/ \/ \/ 8 + * $Id$ 9 + * 10 + * Copyright (C) 2017 Amaury Pouly 11 + * 12 + * This program is free software; you can redistribute it and/or 13 + * modify it under the terms of the GNU General Public License 14 + * as published by the Free Software Foundation; either version 2 15 + * of the License, or (at your option) any later version. 16 + * 17 + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 + * KIND, either express or implied. 19 + * 20 + ****************************************************************************/ 21 + #include <string.h> 22 + #include <stdlib.h> 23 + #include <ctype.h> 24 + #include "misc.h" 25 + #include "fw.h" 26 + #include "afi.h" 27 + 28 + #define FW_SIG_SIZE 4 29 + 30 + #define FW_ENTRIES 240 31 + 32 + struct fw_entry_t 33 + { 34 + char name[8]; 35 + char ext[3]; 36 + uint8_t attr; 37 + uint8_t res[2]; 38 + uint16_t version; 39 + uint32_t block_offset; // offset shift by 9 40 + uint32_t size; 41 + uint32_t unk; 42 + uint32_t checksum; 43 + } __attribute__((packed)); 44 + 45 + struct fw_hdr_t 46 + { 47 + uint8_t sig[FW_SIG_SIZE]; 48 + uint32_t res[4]; 49 + uint8_t year[2]; 50 + uint8_t month; 51 + uint8_t day; 52 + uint16_t usb_vid; 53 + uint16_t usb_pid; 54 + uint32_t checksum; 55 + char productor[16]; 56 + char str2[16]; 57 + char str3[32]; 58 + char dev_name[32]; 59 + uint8_t res2[8 * 16]; 60 + char usb_name1[8]; 61 + char usb_name2[8]; 62 + char res3[4 * 16 + 1]; 63 + char mtp_name1[33]; 64 + char mtp_name2[33]; 65 + char mtp_ver[33]; 66 + uint16_t mtp_vid; 67 + uint16_t mtp_pid; 68 + char fw_ver[64]; 69 + uint32_t res4[2]; 70 + 71 + struct fw_entry_t entry[FW_ENTRIES]; 72 + } __attribute__((packed)); 73 + 74 + /* the s1fwx source code has a layout but it does not make any sense for firmwares 75 + * found in ATJ2127 for example. In doubt just don't do anything */ 76 + struct fw_hdr_f0_t 77 + { 78 + uint8_t sig[FW_SIG_SIZE]; 79 + uint8_t res[12]; 80 + uint32_t checksum; 81 + uint8_t res2[492]; 82 + 83 + struct fw_entry_t entry[FW_ENTRIES]; 84 + } __attribute__((packed)); 85 + 86 + const uint8_t g_fw_signature_f2[FW_SIG_SIZE] = 87 + { 88 + 0x55, 0xaa, 0xf2, 0x0f 89 + }; 90 + 91 + const uint8_t g_fw_signature_f0[FW_SIG_SIZE] = 92 + { 93 + 0x55, 0xaa, 0xf0, 0x0f 94 + }; 95 + 96 + static void build_filename_fw(char buf[16], struct fw_entry_t *ent) 97 + { 98 + int pos = 0; 99 + for(int i = 0; i < 8 && ent->name[i] != ' '; i++) 100 + buf[pos++] = ent->name[i]; 101 + buf[pos++] = '.'; 102 + for(int i = 0; i < 3 && ent->ext[i] != ' '; i++) 103 + buf[pos++] = ent->ext[i]; 104 + buf[pos] = 0; 105 + } 106 + 107 + int fw_unpack(uint8_t *buf, size_t size, fw_extract_callback_t unpack_cb) 108 + { 109 + struct fw_hdr_t *hdr = (void *)buf; 110 + 111 + if(size < sizeof(struct fw_hdr_t)) 112 + { 113 + cprintf(GREY, "File too small\n"); 114 + return 1; 115 + } 116 + cprintf(BLUE, "Header\n"); 117 + cprintf(GREEN, " Signature:"); 118 + for(int i = 0; i < FW_SIG_SIZE; i++) 119 + cprintf(YELLOW, " %02x", hdr->sig[i]); 120 + int variant = 0; 121 + if(memcmp(hdr->sig, g_fw_signature_f2, FW_SIG_SIZE) == 0) 122 + { 123 + variant = 0xf2; 124 + cprintf(RED, " Ok (f2 variant)\n"); 125 + } 126 + else if(memcmp(hdr->sig, g_fw_signature_f0, FW_SIG_SIZE) == 0) 127 + { 128 + variant = 0xf0; 129 + cprintf(RED, " Ok (f0 variant)\n"); 130 + } 131 + else 132 + { 133 + cprintf(RED, " Mismatch\n"); 134 + return 1; 135 + } 136 + 137 + /* both variants have the same header size, only the fields differ */ 138 + if(variant == 0xf2) 139 + { 140 + cprintf_field(" USB VID: ", "0x%x\n", hdr->usb_vid); 141 + cprintf_field(" USB PID: ", "0x%x\n", hdr->usb_pid); 142 + cprintf_field(" Date: ", "%x/%x/%02x%02x\n", hdr->day, hdr->month, hdr->year[0], hdr->year[1]); 143 + cprintf_field(" Checksum: ", "%x\n", hdr->checksum); 144 + cprintf_field(" Productor: ", "%.16s\n", hdr->productor); 145 + cprintf_field(" String 2: ", "%.16s\n", hdr->str2); 146 + cprintf_field(" String 3: ", "%.32s\n", hdr->str3); 147 + cprintf_field(" Device Name: ", "%.32s\n", hdr->dev_name); 148 + cprintf(GREEN, " Unknown:\n"); 149 + for(int i = 0; i < 8; i++) 150 + { 151 + cprintf(YELLOW, " "); 152 + for(int j = 0; j < 16; j++) 153 + cprintf(YELLOW, "%02x ", hdr->res2[i * 16 + j]); 154 + cprintf(YELLOW, "\n"); 155 + } 156 + cprintf_field(" USB Name 1: ", "%.8s\n", hdr->usb_name1); 157 + cprintf_field(" USB Name 2: ", "%.8s\n", hdr->usb_name2); 158 + cprintf_field(" MTP Name 1: ", "%.32s\n", hdr->mtp_name1); 159 + cprintf_field(" MTP Name 2: ", "%.32s\n", hdr->mtp_name2); 160 + cprintf_field(" MTP Version: ", "%.32s\n", hdr->mtp_ver); 161 + 162 + cprintf_field(" MTP VID: ", "0x%x\n", hdr->mtp_vid); 163 + cprintf_field(" MTP PID: ", "0x%x\n", hdr->mtp_pid); 164 + cprintf_field(" FW Version: ", "%.64s\n", hdr->fw_ver); 165 + } 166 + else 167 + { 168 + /* struct fw_hdr_f0_t *hdr_f0 = (void *)hdr; */ 169 + cprintf(GREEN, " Header not dumped because format is unclear.\n"); 170 + } 171 + 172 + cprintf(BLUE, "Entries\n"); 173 + for(int i = 0; i < FW_ENTRIES; i++) 174 + { 175 + if(hdr->entry[i].name[0] == 0) 176 + continue; 177 + struct fw_entry_t *entry = &hdr->entry[i]; 178 + char filename[16]; 179 + build_filename_fw(filename, entry); 180 + cprintf(RED, " %s\n", filename); 181 + cprintf_field(" Attr: ", "%02x\n", entry->attr); 182 + cprintf_field(" Offset: ", "0x%x\n", entry->block_offset << 9); 183 + cprintf_field(" Size: ", "0x%x\n", entry->size); 184 + cprintf_field(" Unknown: ", "%x\n", entry->unk); 185 + cprintf_field(" Checksum: ", "0x%x ", entry->checksum); 186 + uint32_t chk = afi_checksum(buf + (entry->block_offset << 9), entry->size); 187 + if(chk != entry->checksum) 188 + { 189 + cprintf(RED, "Mismatch\n"); 190 + return 1; 191 + } 192 + else 193 + cprintf(RED, "Ok\n"); 194 + int ret = unpack_cb(filename, buf + (entry->block_offset << 9), entry->size); 195 + if(ret != 0) 196 + return ret; 197 + } 198 + 199 + return 0; 200 + } 201 + 202 + bool fw_check(uint8_t *buf, size_t size) 203 + { 204 + struct fw_hdr_t *hdr = (void *)buf; 205 + 206 + if(size < sizeof(struct fw_hdr_t)) 207 + return false; 208 + if(memcmp(hdr->sig, g_fw_signature_f2, FW_SIG_SIZE) == 0) 209 + return true; 210 + if(memcmp(hdr->sig, g_fw_signature_f0, FW_SIG_SIZE) == 0) 211 + return true; 212 + return false; 213 + }
+34
utils/atj2137/atjboottool/fw.h
··· 1 + /*************************************************************************** 2 + * __________ __ ___. 3 + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 + * \/ \/ \/ \/ \/ 8 + * $Id$ 9 + * 10 + * Copyright (C) 2017 Amaury Pouly 11 + * 12 + * This program is free software; you can redistribute it and/or 13 + * modify it under the terms of the GNU General Public License 14 + * as published by the Free Software Foundation; either version 2 15 + * of the License, or (at your option) any later version. 16 + * 17 + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 + * KIND, either express or implied. 19 + * 20 + ****************************************************************************/ 21 + #ifndef __FW_H__ 22 + #define __FW_H__ 23 + 24 + #include <stdint.h> 25 + 26 + /* Unpack an AFI file: the callback function will be called once for each file in the archive with 27 + * its name and content. If the callback returns a nonzero value, the function will stop and return 28 + * that value. Returns 0 on success */ 29 + typedef int (*fw_extract_callback_t)(const char *name, uint8_t *buf, size_t size); 30 + int fw_unpack(uint8_t *buf, size_t size, fw_extract_callback_t cb); 31 + /* Check if a file looks like an AFI file */ 32 + bool fw_check(uint8_t *buf, size_t size); 33 + 34 + #endif /* __FW_H__ */
+5 -5
utils/atj2137/atjboottool/fwu.c
··· 149 149 } 150 150 for(int i = 20; i < 32; i++) 151 151 key[i] = key[i - 20]; 152 - 152 + 153 153 for(int i = 0; i < 992; i++) 154 154 block[i] ^= key[i % 32] ^ g_check_block_A_table[i]; 155 - 155 + 156 156 return check_block(block - 1, block + 1000, 1001); 157 157 } 158 158 ··· 277 277 g_crypto_info_byte = block[offset - 1]; 278 278 g_decode_buffer = malloc(g_decode_A_info.size); 279 279 g_decode_buffer2 = malloc(g_decode_A_info.size); 280 - 280 + 281 281 memset(g_decode_buffer, 0, g_decode_A_info.size); 282 282 memset(g_decode_buffer2, 0, g_decode_A_info.size); 283 283 ··· 288 288 289 289 cprintf_field(" Word: ", "%d ", *(uint16_t *)&g_subblock_A[286]); 290 290 check_field(*(uint16_t *)&g_subblock_A[286], 1, "Ok\n", "Mismatch\n"); 291 - 291 + 292 292 return 0; 293 293 } 294 294 ··· 625 625 static int crypto4(uint8_t *a1, ptr_bundle_t *ptrs, uint32_t *a3) 626 626 { 627 627 ptr_bundle_t ptrs_others; 628 - 628 + 629 629 ptrs_others.ptrA = malloc(g_decode_A_info.size); 630 630 ptrs_others.ptrB = malloc(g_decode_A_info.size); 631 631 clear_memory(ptrs_others.ptrA, g_decode_A_info.nr_dwords);