From ea679de8371e4e74fe4e78fb8df8e5df19efffdc Mon Sep 17 00:00:00 2001 From: Amaury Pouly Date: Fri, 29 Sep 2017 18:22:30 +0200 Subject: atjboottool: put afi and fw code in its own files Change-Id: I16347ebee0f82d5fdf32f5aa8f955c07fe148eba --- utils/atj2137/atjboottool/fw.c | 213 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 utils/atj2137/atjboottool/fw.c (limited to 'utils/atj2137/atjboottool/fw.c') diff --git a/utils/atj2137/atjboottool/fw.c b/utils/atj2137/atjboottool/fw.c new file mode 100644 index 0000000000..07ce4e2f31 --- /dev/null +++ b/utils/atj2137/atjboottool/fw.c @@ -0,0 +1,213 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2017 Amaury Pouly + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include +#include +#include +#include "misc.h" +#include "fw.h" +#include "afi.h" + +#define FW_SIG_SIZE 4 + +#define FW_ENTRIES 240 + +struct fw_entry_t +{ + char name[8]; + char ext[3]; + uint8_t attr; + uint8_t res[2]; + uint16_t version; + uint32_t block_offset; // offset shift by 9 + uint32_t size; + uint32_t unk; + uint32_t checksum; +} __attribute__((packed)); + +struct fw_hdr_t +{ + uint8_t sig[FW_SIG_SIZE]; + uint32_t res[4]; + uint8_t year[2]; + uint8_t month; + uint8_t day; + uint16_t usb_vid; + uint16_t usb_pid; + uint32_t checksum; + char productor[16]; + char str2[16]; + char str3[32]; + char dev_name[32]; + uint8_t res2[8 * 16]; + char usb_name1[8]; + char usb_name2[8]; + char res3[4 * 16 + 1]; + char mtp_name1[33]; + char mtp_name2[33]; + char mtp_ver[33]; + uint16_t mtp_vid; + uint16_t mtp_pid; + char fw_ver[64]; + uint32_t res4[2]; + + struct fw_entry_t entry[FW_ENTRIES]; +} __attribute__((packed)); + +/* the s1fwx source code has a layout but it does not make any sense for firmwares + * found in ATJ2127 for example. In doubt just don't do anything */ +struct fw_hdr_f0_t +{ + uint8_t sig[FW_SIG_SIZE]; + uint8_t res[12]; + uint32_t checksum; + uint8_t res2[492]; + + struct fw_entry_t entry[FW_ENTRIES]; +} __attribute__((packed)); + +const uint8_t g_fw_signature_f2[FW_SIG_SIZE] = +{ + 0x55, 0xaa, 0xf2, 0x0f +}; + +const uint8_t g_fw_signature_f0[FW_SIG_SIZE] = +{ + 0x55, 0xaa, 0xf0, 0x0f +}; + +static void build_filename_fw(char buf[16], struct fw_entry_t *ent) +{ + int pos = 0; + for(int i = 0; i < 8 && ent->name[i] != ' '; i++) + buf[pos++] = ent->name[i]; + buf[pos++] = '.'; + for(int i = 0; i < 3 && ent->ext[i] != ' '; i++) + buf[pos++] = ent->ext[i]; + buf[pos] = 0; +} + +int fw_unpack(uint8_t *buf, size_t size, fw_extract_callback_t unpack_cb) +{ + struct fw_hdr_t *hdr = (void *)buf; + + if(size < sizeof(struct fw_hdr_t)) + { + cprintf(GREY, "File too small\n"); + return 1; + } + cprintf(BLUE, "Header\n"); + cprintf(GREEN, " Signature:"); + for(int i = 0; i < FW_SIG_SIZE; i++) + cprintf(YELLOW, " %02x", hdr->sig[i]); + int variant = 0; + if(memcmp(hdr->sig, g_fw_signature_f2, FW_SIG_SIZE) == 0) + { + variant = 0xf2; + cprintf(RED, " Ok (f2 variant)\n"); + } + else if(memcmp(hdr->sig, g_fw_signature_f0, FW_SIG_SIZE) == 0) + { + variant = 0xf0; + cprintf(RED, " Ok (f0 variant)\n"); + } + else + { + cprintf(RED, " Mismatch\n"); + return 1; + } + + /* both variants have the same header size, only the fields differ */ + if(variant == 0xf2) + { + cprintf_field(" USB VID: ", "0x%x\n", hdr->usb_vid); + cprintf_field(" USB PID: ", "0x%x\n", hdr->usb_pid); + cprintf_field(" Date: ", "%x/%x/%02x%02x\n", hdr->day, hdr->month, hdr->year[0], hdr->year[1]); + cprintf_field(" Checksum: ", "%x\n", hdr->checksum); + cprintf_field(" Productor: ", "%.16s\n", hdr->productor); + cprintf_field(" String 2: ", "%.16s\n", hdr->str2); + cprintf_field(" String 3: ", "%.32s\n", hdr->str3); + cprintf_field(" Device Name: ", "%.32s\n", hdr->dev_name); + cprintf(GREEN, " Unknown:\n"); + for(int i = 0; i < 8; i++) + { + cprintf(YELLOW, " "); + for(int j = 0; j < 16; j++) + cprintf(YELLOW, "%02x ", hdr->res2[i * 16 + j]); + cprintf(YELLOW, "\n"); + } + cprintf_field(" USB Name 1: ", "%.8s\n", hdr->usb_name1); + cprintf_field(" USB Name 2: ", "%.8s\n", hdr->usb_name2); + cprintf_field(" MTP Name 1: ", "%.32s\n", hdr->mtp_name1); + cprintf_field(" MTP Name 2: ", "%.32s\n", hdr->mtp_name2); + cprintf_field(" MTP Version: ", "%.32s\n", hdr->mtp_ver); + + cprintf_field(" MTP VID: ", "0x%x\n", hdr->mtp_vid); + cprintf_field(" MTP PID: ", "0x%x\n", hdr->mtp_pid); + cprintf_field(" FW Version: ", "%.64s\n", hdr->fw_ver); + } + else + { + /* struct fw_hdr_f0_t *hdr_f0 = (void *)hdr; */ + cprintf(GREEN, " Header not dumped because format is unclear.\n"); + } + + cprintf(BLUE, "Entries\n"); + for(int i = 0; i < FW_ENTRIES; i++) + { + if(hdr->entry[i].name[0] == 0) + continue; + struct fw_entry_t *entry = &hdr->entry[i]; + char filename[16]; + build_filename_fw(filename, entry); + cprintf(RED, " %s\n", filename); + cprintf_field(" Attr: ", "%02x\n", entry->attr); + cprintf_field(" Offset: ", "0x%x\n", entry->block_offset << 9); + cprintf_field(" Size: ", "0x%x\n", entry->size); + cprintf_field(" Unknown: ", "%x\n", entry->unk); + cprintf_field(" Checksum: ", "0x%x ", entry->checksum); + uint32_t chk = afi_checksum(buf + (entry->block_offset << 9), entry->size); + if(chk != entry->checksum) + { + cprintf(RED, "Mismatch\n"); + return 1; + } + else + cprintf(RED, "Ok\n"); + int ret = unpack_cb(filename, buf + (entry->block_offset << 9), entry->size); + if(ret != 0) + return ret; + } + + return 0; +} + +bool fw_check(uint8_t *buf, size_t size) +{ + struct fw_hdr_t *hdr = (void *)buf; + + if(size < sizeof(struct fw_hdr_t)) + return false; + if(memcmp(hdr->sig, g_fw_signature_f2, FW_SIG_SIZE) == 0) + return true; + if(memcmp(hdr->sig, g_fw_signature_f0, FW_SIG_SIZE) == 0) + return true; + return false; +} -- cgit v1.2.3