summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrank Gevaerts <frank@gevaerts.be>2008-08-29 18:53:52 +0000
committerFrank Gevaerts <frank@gevaerts.be>2008-08-29 18:53:52 +0000
commite645cede2b8521c3c0205a0bfcd49ea23fef46f1 (patch)
treead583b785cf9c044bbe74b8081259b0964aa6d6e
parent26e0a9766da3cf375483d40f988813276bda3741 (diff)
downloadrockbox-e645cede2b8521c3c0205a0bfcd49ea23fef46f1.tar.gz
rockbox-e645cede2b8521c3c0205a0bfcd49ea23fef46f1.zip
add Meizu M3, M6 TP, M6 SP and M6 SL dfu firmware recovery tool
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@18360 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--utils/meizu_dfu/Makefile10
-rw-r--r--utils/meizu_dfu/README10
-rw-r--r--utils/meizu_dfu/meizu_dfu.c394
3 files changed, 414 insertions, 0 deletions
diff --git a/utils/meizu_dfu/Makefile b/utils/meizu_dfu/Makefile
new file mode 100644
index 0000000000..6b368fa21b
--- /dev/null
+++ b/utils/meizu_dfu/Makefile
@@ -0,0 +1,10 @@
1
2all: meizu_dfu
3
4meizu_dfu: meizu_dfu.c
5 gcc -o meizu_dfu meizu_dfu.c -lusb
6
7.PHONY: clean
8clean:
9 rm -f meizu_dfu
10
diff --git a/utils/meizu_dfu/README b/utils/meizu_dfu/README
new file mode 100644
index 0000000000..027e82d890
--- /dev/null
+++ b/utils/meizu_dfu/README
@@ -0,0 +1,10 @@
1
2Meizu DFU tool for Linux
3
4This tool can restore the firmware on M3, M6 SP, M6 TP and M6 SL.
5
6Notes:
71. SST39VF800.dfu is taken from the official dfu tool provided by Meizu.
82. updateNAND_BE_070831.dfu is taken from the unofficial dfu tool for M6 SL.
93. To compile, just run `make'.
10
diff --git a/utils/meizu_dfu/meizu_dfu.c b/utils/meizu_dfu/meizu_dfu.c
new file mode 100644
index 0000000000..67a5065384
--- /dev/null
+++ b/utils/meizu_dfu/meizu_dfu.c
@@ -0,0 +1,394 @@
1/*
2 Copyright 2008 William Poetra Yoga Hadisoeseno <williampoetra@gmail.com>
3 Frank Gevaerts <frank@gevaerts.be>
4 This file is licensed under GPL v2.
5*/
6
7#include <stdio.h>
8#include <stdlib.h>
9#include <stdint.h>
10#include <string.h>
11#include <sys/types.h>
12#include <sys/stat.h>
13#include <fcntl.h>
14#include <unistd.h>
15#include <libgen.h>
16
17#include <usb.h>
18
19void usage()
20{
21 fprintf(stderr, "usage: meizu_dfu m3 <SST39VF800.dfu> <M3.EBN>\n");
22 fprintf(stderr, " meizu_dfu m6 <SST39VF800.dfu> <M6.EBN>\n");
23 fprintf(stderr, " meizu_dfu m6sl <updateNAND_BE_070831.dfu> <M6SL.EBN>\n");
24 exit(1);
25}
26
27uint32_t crc32(char *data, int len, uint32_t poly, uint32_t init)
28{
29 uint32_t crc_table[256];
30 uint32_t crc, t;
31 int i, j;
32
33 // generate the table
34 for (i = 0; i < 256; ++i) {
35 t = i;
36 for (j = 0; j < 8; ++j)
37 if (t & 1)
38 t = (t >> 1) ^ poly;
39 else
40 t >>= 1;
41 crc_table[i] = t;
42 }
43
44 // calculate the crc
45 crc = init;
46 for (i = 0; i < len; ++i)
47 crc = (crc >> 8) ^ crc_table[(crc^data[i]) & 0xff];
48
49 return crc;
50}
51
52#define BLOCK_SIZE 2048
53
54typedef struct {
55 char *name;
56 char *data;
57 int len;
58} image_data_t;
59
60typedef struct {
61 int delay;
62 int pre_off;
63 uint32_t pre_sig;
64 uint16_t suf_dev;
65 uint16_t suf_prod;
66 uint16_t suf_ven;
67 uint16_t suf_dfu;
68 char suf_sig[3];
69 uint8_t suf_len;
70} image_attr_t;
71
72#define DFU_CRC_POLY 0xedb88320
73#define DFU_INIT_CRC 0xffffffff
74
75void init_img(image_data_t *img, const char *filename, image_attr_t *attr)
76{
77 int fd, len, i, readlen;
78 struct stat statbuf;
79 char buf[BLOCK_SIZE];
80 uint32_t dfu_crc;
81
82 printf("Reading %s...", filename);
83
84 stat(filename, &statbuf);
85 len = statbuf.st_size;
86
87 img->name = basename(strdup(filename));
88 img->data = malloc(len + 16);
89 img->len = len + 16;
90
91 fd = open(filename, O_RDONLY);
92 for (i = 0; i < len; i += BLOCK_SIZE) {
93 readlen = ((len - i) < BLOCK_SIZE) ? (len - i) : BLOCK_SIZE;
94 read(fd, buf, readlen);
95 memcpy(img->data + i, buf, readlen);
96 }
97 close(fd);
98
99 // patch the data size in after the signature
100 memcpy(img->data + attr->pre_off + 4, &img->len, 4);
101
102 // append the suffix (excluding the checksum)
103 memcpy(img->data + len, &attr->suf_dev, 2);
104 memcpy(img->data + len + 2, &attr->suf_prod, 2);
105 memcpy(img->data + len + 4, &attr->suf_ven, 2);
106 memcpy(img->data + len + 6, &attr->suf_dfu, 2);
107 memcpy(img->data + len + 8, &attr->suf_sig, 3);
108 memcpy(img->data + len + 11, &attr->suf_len, 1);
109
110 dfu_crc = crc32(img->data, len + 12, DFU_CRC_POLY, DFU_INIT_CRC);
111 memcpy(img->data + len + 12, &dfu_crc, 4);
112
113#if 0
114 FILE *f = fopen(img->name, "w");
115 fwrite(img->data, len + 16, 1, f);
116 fclose(f);
117#endif
118
119 printf("OK\n");
120}
121
122#define DFU_VEN 0x0419
123#define DFU_DEV 0x0141
124usb_dev_handle *device;
125int timeout = 0xa0000;
126
127void usb_dev_open()
128{
129 struct usb_bus *bus;
130 struct usb_device *dev;
131
132 printf("USB initialization...");
133 fflush(stdout);
134
135 usb_init();
136 usb_find_busses();
137 usb_find_devices();
138
139 for (bus = usb_get_busses(); bus != NULL; bus = bus->next)
140 for (dev = bus->devices; dev != NULL; dev = dev->next)
141 if (dev->descriptor.idVendor == DFU_VEN
142 || dev->descriptor.idProduct == DFU_DEV)
143 goto found;
144
145 printf("\nNo device found, exiting.\n");
146 exit(1);
147
148found:
149 printf(" Device found.\n");
150 device = usb_open(dev);
151 usb_claim_interface(device, 0);
152}
153
154void usb_mimic_windows()
155{
156 char data[1024];
157
158 usb_control_msg(device, 0x80, 0x06, 0x0100, 0x0000, data, 0x0012, timeout);
159 usb_control_msg(device, 0x80, 0x06, 0x0200, 0x0000, data, 0x0009, timeout);
160 usb_control_msg(device, 0x80, 0x06, 0x0200, 0x0000, data, 0x001b, timeout);
161 usb_control_msg(device, 0x80, 0x06, 0x0100, 0x0000, data, 0x0040, timeout);
162 usb_control_msg(device, 0x80, 0x06, 0x0100, 0x0000, data, 0x0012, timeout);
163 usb_control_msg(device, 0x80, 0x06, 0x0200, 0x0000, data, 0x0009, timeout);
164 usb_control_msg(device, 0x80, 0x06, 0x0300, 0x0000, data, 0x00ff, timeout);
165 usb_control_msg(device, 0x80, 0x06, 0x0303, 0x0409, data, 0x00ff, timeout);
166 usb_control_msg(device, 0x80, 0x06, 0x0200, 0x0000, data, 0x00ff, timeout);
167 usb_control_msg(device, 0x80, 0x06, 0x0300, 0x0000, data, 0x00ff, timeout);
168 usb_control_msg(device, 0x80, 0x06, 0x0302, 0x0409, data, 0x00ff, timeout);
169 usb_control_msg(device, 0x80, 0x06, 0x0300, 0x0000, data, 0x00ff, timeout);
170 usb_control_msg(device, 0x80, 0x06, 0x0302, 0x0409, data, 0x00ff, timeout);
171 usb_control_msg(device, 0x80, 0x06, 0x0100, 0x0000, data, 0x0012, timeout);
172 usb_control_msg(device, 0x80, 0x06, 0x0200, 0x0000, data, 0x0209, timeout);
173}
174
175void usb_dev_close()
176{
177 printf("Releasing interface...");
178 fflush(stdout);
179
180 usb_release_interface(device, 0);
181
182 printf(" OK\n");
183}
184
185#define DFU_DETACH 0
186#define DFU_DOWNLOAD 1
187#define DFU_UPLOAD 2
188#define DFU_GETSTATUS 3
189#define DFU_CLRSTATUS 4
190#define DFU_GETSTATE 5
191#define DFU_ABORT 6
192
193void get_cpu()
194{
195 char data[64];
196 int req_out_if = USB_ENDPOINT_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
197 int len;
198
199 printf("GET CPU");
200 fflush(stdout);
201
202 // check for "S5L8700 Rev.1"
203 len = usb_control_msg(device, req_out_if, 0xff, 0x0002, 0, data, 0x003f, timeout);
204 if (len < 0) {
205 printf("\nError trying to get CPU model, exiting.\n");
206 exit(1);
207 }
208
209 memset(data + len, 0, 64 - len);
210 printf(", got: %s\n", data);
211}
212
213void send_file(image_data_t *img)
214{
215 char dfu_ret[6];
216 char *data;
217 int req_out_if = USB_ENDPOINT_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
218 int req_in_if = USB_ENDPOINT_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
219 int len, idx, writelen, i;
220
221 printf("Sending %s... ", img->name);
222 fflush(stdout);
223
224 len = img->len;
225 data = img->data;
226
227 // loop for the file
228 for (i = 0, idx = 0; i < len; i += BLOCK_SIZE, ++idx) {
229 writelen = ((len - i) < BLOCK_SIZE) ? (len - i) : BLOCK_SIZE;
230 usb_control_msg(device, req_out_if, DFU_DOWNLOAD, idx, 0, data + i, writelen, timeout);
231 dfu_ret[4] = 0x00;
232 while (dfu_ret[4] != 0x05)
233 usb_control_msg(device, req_in_if, DFU_GETSTATUS, 0, 0, dfu_ret, 6, timeout);
234 printf("#");
235 fflush(stdout);
236 }
237
238 usb_control_msg(device, req_out_if, DFU_DOWNLOAD, idx, 0, NULL, 0, timeout);
239 dfu_ret[4] = 0x00;
240 while (dfu_ret[4] != 0x07)
241 usb_control_msg(device, req_in_if, DFU_GETSTATUS, 0, 0, dfu_ret, 6, timeout);
242
243 printf(" OK\n");
244 fflush(stdout);
245}
246
247void clear_status()
248{
249 char dfu_ret[6];
250 int usb_in_if = USB_ENDPOINT_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
251 int usb_out_if = USB_ENDPOINT_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
252
253 printf("Clearing status...");
254 fflush(stdout);
255
256 dfu_ret[4] = 0x00;
257 while (dfu_ret[4] != 0x08)
258 usb_control_msg(device, usb_in_if, DFU_GETSTATUS, 0, 0, dfu_ret, 6, timeout);
259 usb_control_msg(device, usb_out_if, DFU_CLRSTATUS, 0, 0, NULL, 0, timeout);
260
261 printf(" OK\n");
262}
263
264void dfu_detach()
265{
266 char usb_ret[4];
267 int usb_in_oth = USB_ENDPOINT_IN | USB_TYPE_CLASS | USB_RECIP_OTHER;
268 int usb_out_oth = USB_ENDPOINT_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER;
269
270 printf("Detaching...");
271 fflush(stdout);
272
273 usb_control_msg(device, usb_in_oth, DFU_DETACH, 0x0000, 3, usb_ret, 4, timeout);
274 usb_control_msg(device, usb_out_oth, DFU_DOWNLOAD, 0x0010, 3, NULL, 0, timeout);
275 usb_control_msg(device, usb_in_oth, DFU_DETACH, 0x0000, 3, usb_ret, 4, timeout);
276 usb_control_msg(device, usb_in_oth, DFU_DETACH, 0x0000, 3, usb_ret, 4, timeout);
277 usb_control_msg(device, usb_in_oth, DFU_DETACH, 0x0000, 3, usb_ret, 4, timeout);
278 usb_control_msg(device, usb_in_oth, DFU_DETACH, 0x0000, 3, usb_ret, 4, timeout);
279 usb_control_msg(device, usb_in_oth, DFU_DETACH, 0x0000, 3, usb_ret, 4, timeout);
280
281 printf(" OK\n");
282}
283
284void dfu_m3_m6(char *file1, char *file2)
285{
286 image_data_t img1, img2;
287 image_attr_t attr1, attr2;
288
289 attr1.delay = 1000;
290 attr1.pre_off = 0x20;
291 attr1.pre_sig = 0x44465543;
292 attr1.suf_dev = 0x0100;
293 attr1.suf_prod = 0x0140;
294 attr1.suf_ven = 0x0419;
295 attr1.suf_dfu = 0x0100;
296 memcpy(attr1.suf_sig, "RON", 3);
297 attr1.suf_len = 0x10;
298
299 attr2.delay = 1000;
300 attr2.pre_off = 0x20;
301 attr2.pre_sig = 0x44465543;
302 attr2.suf_dev = 0x0100;
303 attr2.suf_prod = 0x0140;
304 attr2.suf_ven = 0x0419;
305 attr2.suf_dfu = 0x0100;
306 memcpy(attr2.suf_sig, "UFD", 3);
307 attr2.suf_len = 0x10;
308
309 init_img(&img1, file1, &attr1);
310 init_img(&img2, file2, &attr2);
311
312 usb_dev_open();
313// usb_mimic_windows();
314 get_cpu();
315 get_cpu();
316 send_file(&img1);
317
318 printf("Wait a sec (literally)...");
319 fflush(stdout);
320 sleep(1);
321 printf(" OK\n");
322
323 clear_status();
324 get_cpu();
325 send_file(&img2);
326 dfu_detach();
327 usb_dev_close();
328}
329
330void dfu_m6sl(char *file1, char *file2)
331{
332 image_data_t img1, img2;
333 image_attr_t attr1, attr2;
334
335 attr1.delay = 1000;
336 attr1.pre_off = 0x20;
337 attr1.pre_sig = 0x44465543;
338 attr1.suf_dev = 0x0100;
339 attr1.suf_prod = 0x0140;
340 attr1.suf_ven = 0x0419;
341 attr1.suf_dfu = 0x0100;
342 memcpy(attr1.suf_sig, "UFD", 3);
343 attr1.suf_len = 0x10;
344
345 attr2.delay = 1000;
346 attr2.pre_off = 0x20;
347 attr2.pre_sig = 0x44465543;
348 attr2.suf_dev = 0x0100;
349 attr2.suf_prod = 0x0140;
350 attr2.suf_ven = 0x0419;
351 attr2.suf_dfu = 0x0100;
352 memcpy(attr2.suf_sig, "UFD", 3);
353 attr2.suf_len = 0x10;
354
355 init_img(&img1, file1, &attr1);
356 init_img(&img2, file2, &attr2);
357
358 usb_dev_open();
359 get_cpu();
360 get_cpu();
361 send_file(&img1);
362
363 printf("Wait a sec (literally)...");
364 fflush(stdout);
365 sleep(1);
366 printf(" OK\n");
367 usb_dev_close();
368
369 usb_dev_open();
370 get_cpu();
371 get_cpu();
372 send_file(&img2);
373 dfu_detach();
374 usb_dev_close();
375}
376
377
378int main(int argc, char **argv)
379{
380 if (argc != 4)
381 usage();
382
383 if (!strcmp(argv[1], "m3"))
384 dfu_m3_m6(argv[2], argv[3]);
385 else if (!strcmp(argv[1], "m6"))
386 dfu_m3_m6(argv[2], argv[3]);
387 else if (!strcmp(argv[1], "m6sl"))
388 dfu_m6sl(argv[2], argv[3]);
389 else
390 usage();
391
392 return 0;
393}
394