diff options
author | Amaury Pouly <amaury.pouly@gmail.com> | 2017-09-29 18:22:30 +0200 |
---|---|---|
committer | Amaury Pouly <amaury.pouly@gmail.com> | 2017-09-29 18:22:30 +0200 |
commit | ea679de8371e4e74fe4e78fb8df8e5df19efffdc (patch) | |
tree | c08cf8be057318313a3bcf040395826afe62566b | |
parent | 95c32a505a7bfef2dcac2a975b1f5875f490c405 (diff) | |
download | rockbox-ea679de8371e4e74fe4e78fb8df8e5df19efffdc.tar.gz rockbox-ea679de8371e4e74fe4e78fb8df8e5df19efffdc.zip |
atjboottool: put afi and fw code in its own files
Change-Id: I16347ebee0f82d5fdf32f5aa8f955c07fe148eba
-rw-r--r-- | utils/atj2137/atjboottool/Makefile | 2 | ||||
-rw-r--r-- | utils/atj2137/atjboottool/afi.c | 208 | ||||
-rw-r--r-- | utils/atj2137/atjboottool/afi.h | 8 | ||||
-rw-r--r-- | utils/atj2137/atjboottool/atjboottool.c | 416 | ||||
-rw-r--r-- | utils/atj2137/atjboottool/fw.c | 213 | ||||
-rw-r--r-- | utils/atj2137/atjboottool/fw.h | 34 | ||||
-rw-r--r-- | utils/atj2137/atjboottool/fwu.c | 10 |
7 files changed, 499 insertions, 392 deletions
diff --git a/utils/atj2137/atjboottool/Makefile b/utils/atj2137/atjboottool/Makefile index 31c315d4fd..8d96bcdde0 100644 --- a/utils/atj2137/atjboottool/Makefile +++ b/utils/atj2137/atjboottool/Makefile | |||
@@ -10,7 +10,7 @@ all: $(BINS) | |||
10 | %.o: %.c | 10 | %.o: %.c |
11 | $(CC) $(CFLAGS) -c -o $@ $< | 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 | $(LD) -o $@ $^ $(LDFLAGS) | 14 | $(LD) -o $@ $^ $(LDFLAGS) |
15 | 15 | ||
16 | clean: | 16 | clean: |
diff --git a/utils/atj2137/atjboottool/afi.c b/utils/atj2137/atjboottool/afi.c new file mode 100644 index 0000000000..1ce9d0c01e --- /dev/null +++ b/utils/atj2137/atjboottool/afi.c | |||
@@ -0,0 +1,208 @@ | |||
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 | } | ||
diff --git a/utils/atj2137/atjboottool/afi.h b/utils/atj2137/atjboottool/afi.h index bb264cefdf..6756364d2a 100644 --- a/utils/atj2137/atjboottool/afi.h +++ b/utils/atj2137/atjboottool/afi.h | |||
@@ -23,7 +23,13 @@ | |||
23 | 23 | ||
24 | #include <stdint.h> | 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 | bool afi_check(uint8_t *buf, size_t size); | 33 | bool afi_check(uint8_t *buf, size_t size); |
28 | 34 | ||
29 | #endif /* __AFI_H__ */ | 35 | #endif /* __AFI_H__ */ |
diff --git a/utils/atj2137/atjboottool/atjboottool.c b/utils/atj2137/atjboottool/atjboottool.c index 676fdae199..d0ad1b468b 100644 --- a/utils/atj2137/atjboottool/atjboottool.c +++ b/utils/atj2137/atjboottool/atjboottool.c | |||
@@ -29,6 +29,8 @@ | |||
29 | #include <sys/stat.h> | 29 | #include <sys/stat.h> |
30 | #include "misc.h" | 30 | #include "misc.h" |
31 | #include "fwu.h" | 31 | #include "fwu.h" |
32 | #include "afi.h" | ||
33 | #include "fw.h" | ||
32 | 34 | ||
33 | bool g_debug = false; | 35 | bool g_debug = false; |
34 | char *g_out_prefix = NULL; | 36 | char *g_out_prefix = NULL; |
@@ -89,407 +91,51 @@ static int do_fwu(uint8_t *buf, size_t size, enum fwu_mode_t mode) | |||
89 | } | 91 | } |
90 | } | 92 | } |
91 | 93 | ||
92 | /** | 94 | static int unpack_afi_fw_cb(const char *filename, uint8_t *buf, size_t size) |
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 | { | 95 | { |
153 | 'A', 'F', 'I', 0 | 96 | char *name = malloc(strlen(g_out_prefix) + strlen(filename) + 16); |
154 | }; | 97 | sprintf(name, "%s%s", g_out_prefix, filename); |
155 | 98 | ||
156 | static uint32_t afi_checksum(void *ptr, int size) | 99 | cprintf(GREY, "Unpacking to %s... ", name); |
157 | { | 100 | FILE *f = fopen(name, "wb"); |
158 | uint32_t crc = 0; | 101 | if(f) |
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) | ||
183 | { | ||
184 | struct afi_t *afi = (void *)buf; | ||
185 | |||
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 | ||
198 | { | 102 | { |
199 | cprintf(RED, " Mismatch\n"); | 103 | fwrite(buf, size, 1, f); |
200 | return 1; | 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 | else | 108 | else |
217 | { | 109 | { |
218 | cprintf(RED, " Error (file too small)\n"); | 110 | color(RED); |
111 | perror("Failed"); | ||
219 | return 1; | 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) | 116 | static int do_afi(uint8_t *buf, size_t size) |
272 | { | 117 | { |
273 | struct afi_hdr_t *hdr = (void *)buf; | 118 | build_out_prefix(".fw", "", true); |
274 | 119 | return afi_unpack(buf, size, &unpack_afi_fw_cb); | |
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] = | ||
348 | { | ||
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; | ||
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 | build_out_prefix(".unpack", "", true); | 124 | build_out_prefix(".unpack", "", true); |
429 | 125 | return fw_unpack(buf, size, &unpack_afi_fw_cb); | |
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; | ||
478 | } | 126 | } |
479 | |||
480 | static void usage(void) | 127 | static void usage(void) |
481 | { | 128 | { |
482 | printf("Usage: atjboottool [options] firmware\n"); | 129 | printf("Usage: atjboottool [options] firmware\n"); |
483 | printf("Options:\n"); | 130 | printf("Options:\n"); |
484 | printf(" -o <prefix>\tSet output prefix\n"); | 131 | printf(" -o <path> Set output file or output prefix\n"); |
485 | printf(" -f/--force\tForce to continue on errors\n"); | 132 | printf(" -h/--help Display this message\n"); |
486 | printf(" -?/--help\tDisplay this message\n"); | 133 | printf(" -d/--debug Display debug messages\n"); |
487 | printf(" -d/--debug\tDisplay debug messages\n"); | 134 | printf(" -c/--no-color Disable color output\n"); |
488 | printf(" -c/--no-color\tDisable color output\n"); | 135 | printf(" --fwu Unpack a FWU firmware file\n"); |
489 | printf(" --fwu\tUnpack a FWU firmware file\n"); | 136 | printf(" --afi Unpack a AFI archive file\n"); |
490 | printf(" --afi\tUnpack a AFI archive file\n"); | 137 | printf(" --fw Unpack a FW archive file\n"); |
491 | printf(" --fw\tUnpack a FW archive file\n"); | 138 | printf(" --atj2127 Force ATJ2127 decryption mode\n"); |
492 | printf(" --atj2127\tForce ATJ2127 decryption mode\n"); | ||
493 | printf("The default is to try to guess the format.\n"); | 139 | printf("The default is to try to guess the format.\n"); |
494 | printf("If several formats are specified, all are tried.\n"); | 140 | printf("If several formats are specified, all are tried.\n"); |
495 | printf("If no output prefix is specified, a default one is picked.\n"); | 141 | printf("If no output prefix is specified, a default one is picked.\n"); |
@@ -507,7 +153,7 @@ int main(int argc, char **argv) | |||
507 | { | 153 | { |
508 | static struct option long_options[] = | 154 | static struct option long_options[] = |
509 | { | 155 | { |
510 | {"help", no_argument, 0, '?'}, | 156 | {"help", no_argument, 0, 'h'}, |
511 | {"debug", no_argument, 0, 'd'}, | 157 | {"debug", no_argument, 0, 'd'}, |
512 | {"no-color", no_argument, 0, 'c'}, | 158 | {"no-color", no_argument, 0, 'c'}, |
513 | {"fwu", no_argument, 0, 'u'}, | 159 | {"fwu", no_argument, 0, 'u'}, |
@@ -517,7 +163,7 @@ int main(int argc, char **argv) | |||
517 | {0, 0, 0, 0} | 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 | if(c == -1) | 167 | if(c == -1) |
522 | break; | 168 | break; |
523 | switch(c) | 169 | switch(c) |
@@ -531,7 +177,7 @@ int main(int argc, char **argv) | |||
531 | g_debug = true; | 177 | g_debug = true; |
532 | break; | 178 | break; |
533 | break; | 179 | break; |
534 | case '?': | 180 | case 'h': |
535 | usage(); | 181 | usage(); |
536 | break; | 182 | break; |
537 | case 'o': | 183 | case 'o': |
@@ -591,7 +237,7 @@ int main(int argc, char **argv) | |||
591 | ret = do_fwu(buf, size, fwu_mode); | 237 | ret = do_fwu(buf, size, fwu_mode); |
592 | else if(try_afi || afi_check(buf, size)) | 238 | else if(try_afi || afi_check(buf, size)) |
593 | ret = do_afi(buf, size); | 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 | ret = do_fw(buf, size); | 241 | ret = do_fw(buf, size); |
596 | else | 242 | else |
597 | { | 243 | { |
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 | |||
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 | } | ||
diff --git a/utils/atj2137/atjboottool/fw.h b/utils/atj2137/atjboottool/fw.h new file mode 100644 index 0000000000..95f8087116 --- /dev/null +++ b/utils/atj2137/atjboottool/fw.h | |||
@@ -0,0 +1,34 @@ | |||
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__ */ | ||
diff --git a/utils/atj2137/atjboottool/fwu.c b/utils/atj2137/atjboottool/fwu.c index 843a1cb628..44281af4f4 100644 --- a/utils/atj2137/atjboottool/fwu.c +++ b/utils/atj2137/atjboottool/fwu.c | |||
@@ -149,10 +149,10 @@ static int decode_block_A(uint8_t block[1020]) | |||
149 | } | 149 | } |
150 | for(int i = 20; i < 32; i++) | 150 | for(int i = 20; i < 32; i++) |
151 | key[i] = key[i - 20]; | 151 | key[i] = key[i - 20]; |
152 | 152 | ||
153 | for(int i = 0; i < 992; i++) | 153 | for(int i = 0; i < 992; i++) |
154 | block[i] ^= key[i % 32] ^ g_check_block_A_table[i]; | 154 | block[i] ^= key[i % 32] ^ g_check_block_A_table[i]; |
155 | 155 | ||
156 | return check_block(block - 1, block + 1000, 1001); | 156 | return check_block(block - 1, block + 1000, 1001); |
157 | } | 157 | } |
158 | 158 | ||
@@ -277,7 +277,7 @@ static int process_block_A(uint8_t block[1024]) | |||
277 | g_crypto_info_byte = block[offset - 1]; | 277 | g_crypto_info_byte = block[offset - 1]; |
278 | g_decode_buffer = malloc(g_decode_A_info.size); | 278 | g_decode_buffer = malloc(g_decode_A_info.size); |
279 | g_decode_buffer2 = malloc(g_decode_A_info.size); | 279 | g_decode_buffer2 = malloc(g_decode_A_info.size); |
280 | 280 | ||
281 | memset(g_decode_buffer, 0, g_decode_A_info.size); | 281 | memset(g_decode_buffer, 0, g_decode_A_info.size); |
282 | memset(g_decode_buffer2, 0, g_decode_A_info.size); | 282 | memset(g_decode_buffer2, 0, g_decode_A_info.size); |
283 | 283 | ||
@@ -288,7 +288,7 @@ static int process_block_A(uint8_t block[1024]) | |||
288 | 288 | ||
289 | cprintf_field(" Word: ", "%d ", *(uint16_t *)&g_subblock_A[286]); | 289 | cprintf_field(" Word: ", "%d ", *(uint16_t *)&g_subblock_A[286]); |
290 | check_field(*(uint16_t *)&g_subblock_A[286], 1, "Ok\n", "Mismatch\n"); | 290 | check_field(*(uint16_t *)&g_subblock_A[286], 1, "Ok\n", "Mismatch\n"); |
291 | 291 | ||
292 | return 0; | 292 | return 0; |
293 | } | 293 | } |
294 | 294 | ||
@@ -625,7 +625,7 @@ static int crypto3(uint32_t *a1, ptr_bundle_t *ptrs_alt, ptr_bundle_t *ptrs) | |||
625 | static int crypto4(uint8_t *a1, ptr_bundle_t *ptrs, uint32_t *a3) | 625 | static int crypto4(uint8_t *a1, ptr_bundle_t *ptrs, uint32_t *a3) |
626 | { | 626 | { |
627 | ptr_bundle_t ptrs_others; | 627 | ptr_bundle_t ptrs_others; |
628 | 628 | ||
629 | ptrs_others.ptrA = malloc(g_decode_A_info.size); | 629 | ptrs_others.ptrA = malloc(g_decode_A_info.size); |
630 | ptrs_others.ptrB = malloc(g_decode_A_info.size); | 630 | ptrs_others.ptrB = malloc(g_decode_A_info.size); |
631 | clear_memory(ptrs_others.ptrA, g_decode_A_info.nr_dwords); | 631 | clear_memory(ptrs_others.ptrA, g_decode_A_info.nr_dwords); |