summaryrefslogtreecommitdiff
path: root/utils/atj2137/atjboottool/fw.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/atj2137/atjboottool/fw.c')
-rw-r--r--utils/atj2137/atjboottool/fw.c213
1 files changed, 213 insertions, 0 deletions
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 @@
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
32struct 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
45struct 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 */
76struct 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
86const uint8_t g_fw_signature_f2[FW_SIG_SIZE] =
87{
88 0x55, 0xaa, 0xf2, 0x0f
89};
90
91const uint8_t g_fw_signature_f0[FW_SIG_SIZE] =
92{
93 0x55, 0xaa, 0xf0, 0x0f
94};
95
96static 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
107int 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
202bool 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}