2 Copyright 2008 William Poetra Yoga Hadisoeseno <williampoetra@gmail.com>
3 Frank Gevaerts <frank@gevaerts.be>
4 This file is licensed under GPL v2.
11 #include <sys/types.h>
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");
27 uint32_t crc32(char *data
, int len
, uint32_t poly
, uint32_t init
)
29 uint32_t crc_table
[256];
34 for (i
= 0; i
< 256; ++i
) {
36 for (j
= 0; j
< 8; ++j
)
46 for (i
= 0; i
< len
; ++i
)
47 crc
= (crc
>> 8) ^ crc_table
[(crc
^data
[i
]) & 0xff];
70 #define BLOCK_SIZE 2048
71 #define DFU_TIMEOUT 0xa000
72 #define DFU_CRC_POLY 0xedb88320
73 #define DFU_INIT_CRC 0xffffffff
75 #define USB_VID_SAMSUNG 0x0419
76 #define USB_PID_M6SL 0x0145
77 #define USB_PID_M3_M6 0x0141
79 void init_img(image_data_t
*img
, const char *filename
, image_attr_t
*attr
)
81 int fd
, len
, i
, readlen
;
86 printf("Reading %s...", filename
);
88 stat(filename
, &statbuf
);
89 len
= statbuf
.st_size
;
91 img
->name
= basename(strdup(filename
));
92 img
->data
= malloc(len
+ 16);
95 fd
= open(filename
, O_RDONLY
);
96 for (i
= 0; i
< len
; i
+= BLOCK_SIZE
) {
97 readlen
= ((len
- i
) < BLOCK_SIZE
) ? (len
- i
) : BLOCK_SIZE
;
98 read(fd
, buf
, readlen
);
99 memcpy(img
->data
+ i
, buf
, readlen
);
103 // patch the data size in after the signature
104 memcpy(img
->data
+ attr
->pre_off
+ 4, &img
->len
, 4);
106 // append the suffix (excluding the checksum)
107 memcpy(img
->data
+ len
, &attr
->suf_dev
, 2);
108 memcpy(img
->data
+ len
+ 2, &attr
->suf_prod
, 2);
109 memcpy(img
->data
+ len
+ 4, &attr
->suf_ven
, 2);
110 memcpy(img
->data
+ len
+ 6, &attr
->suf_dfu
, 2);
111 memcpy(img
->data
+ len
+ 8, &attr
->suf_sig
, 3);
112 memcpy(img
->data
+ len
+ 11, &attr
->suf_len
, 1);
114 dfu_crc
= crc32(img
->data
, len
+ 12, DFU_CRC_POLY
, DFU_INIT_CRC
);
115 memcpy(img
->data
+ len
+ 12, &dfu_crc
, 4);
118 FILE *f
= fopen(img
->name
, "w");
119 fwrite(img
->data
, len
+ 16, 1, f
);
126 usb_dev_handle
*usb_dev_open(uint16_t dfu_vid
, uint16_t dfu_pid
)
129 struct usb_device
*dev
;
130 usb_dev_handle
*device
;
132 printf("USB initialization...");
138 for (bus
= usb_get_busses(); bus
!= NULL
; bus
= bus
->next
)
139 for (dev
= bus
->devices
; dev
!= NULL
; dev
= dev
->next
)
140 if (dev
->descriptor
.idVendor
== dfu_vid
141 && dev
->descriptor
.idProduct
== dfu_pid
)
144 printf("\nNo device found, exiting.\n");
148 printf(" Device found.\n");
149 device
= usb_open(dev
);
150 usb_claim_interface(device
, 0);
154 void usb_mimic_windows(usb_dev_handle
*device
)
158 usb_control_msg(device
, 0x80, 0x06, 0x0100, 0x0000, data
, 0x0012, DFU_TIMEOUT
);
159 usb_control_msg(device
, 0x80, 0x06, 0x0200, 0x0000, data
, 0x0009, DFU_TIMEOUT
);
160 usb_control_msg(device
, 0x80, 0x06, 0x0200, 0x0000, data
, 0x001b, DFU_TIMEOUT
);
161 usb_control_msg(device
, 0x80, 0x06, 0x0100, 0x0000, data
, 0x0040, DFU_TIMEOUT
);
162 usb_control_msg(device
, 0x80, 0x06, 0x0100, 0x0000, data
, 0x0012, DFU_TIMEOUT
);
163 usb_control_msg(device
, 0x80, 0x06, 0x0200, 0x0000, data
, 0x0009, DFU_TIMEOUT
);
164 usb_control_msg(device
, 0x80, 0x06, 0x0300, 0x0000, data
, 0x00ff, DFU_TIMEOUT
);
165 usb_control_msg(device
, 0x80, 0x06, 0x0303, 0x0409, data
, 0x00ff, DFU_TIMEOUT
);
166 usb_control_msg(device
, 0x80, 0x06, 0x0200, 0x0000, data
, 0x00ff, DFU_TIMEOUT
);
167 usb_control_msg(device
, 0x80, 0x06, 0x0300, 0x0000, data
, 0x00ff, DFU_TIMEOUT
);
168 usb_control_msg(device
, 0x80, 0x06, 0x0302, 0x0409, data
, 0x00ff, DFU_TIMEOUT
);
169 usb_control_msg(device
, 0x80, 0x06, 0x0300, 0x0000, data
, 0x00ff, DFU_TIMEOUT
);
170 usb_control_msg(device
, 0x80, 0x06, 0x0302, 0x0409, data
, 0x00ff, DFU_TIMEOUT
);
171 usb_control_msg(device
, 0x80, 0x06, 0x0100, 0x0000, data
, 0x0012, DFU_TIMEOUT
);
172 usb_control_msg(device
, 0x80, 0x06, 0x0200, 0x0000, data
, 0x0209, DFU_TIMEOUT
);
175 void usb_dev_close(usb_dev_handle
*device
)
177 printf("Releasing interface...");
179 usb_release_interface(device
, 0);
194 void get_cpu(usb_dev_handle
*device
)
197 int req_out_if
= USB_ENDPOINT_IN
| USB_TYPE_CLASS
| USB_RECIP_INTERFACE
;
202 // check for "S5L8700 Rev.1"
203 len
= usb_control_msg(device
, req_out_if
, 0xff, 0x0002, 0, data
, 0x003f, DFU_TIMEOUT
);
205 printf("\nError trying to get CPU model, exiting.\n");
209 memset(data
+ len
, 0, 64 - len
);
210 printf(", got: %s\n", data
);
213 void send_file(usb_dev_handle
*device
, image_data_t
*img
)
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
;
221 printf("Sending %s... ", img
->name
);
227 for (i
= 0, idx
= 0; i
< len
; i
+= BLOCK_SIZE
, ++idx
) {
228 writelen
= ((len
- i
) < BLOCK_SIZE
) ? (len
- i
) : BLOCK_SIZE
;
229 usb_control_msg(device
, req_out_if
, DFU_DOWNLOAD
, idx
, 0, data
+ i
, writelen
, DFU_TIMEOUT
);
231 while (dfu_ret
[4] != 0x05)
232 usb_control_msg(device
, req_in_if
, DFU_GETSTATUS
, 0, 0, dfu_ret
, 6, DFU_TIMEOUT
);
236 usb_control_msg(device
, req_out_if
, DFU_DOWNLOAD
, idx
, 0, NULL
, 0, DFU_TIMEOUT
);
238 while (dfu_ret
[4] != 0x07)
239 usb_control_msg(device
, req_in_if
, DFU_GETSTATUS
, 0, 0, dfu_ret
, 6, DFU_TIMEOUT
);
244 void clear_status(usb_dev_handle
*device
)
247 int usb_in_if
= USB_ENDPOINT_IN
| USB_TYPE_CLASS
| USB_RECIP_INTERFACE
;
248 int usb_out_if
= USB_ENDPOINT_OUT
| USB_TYPE_CLASS
| USB_RECIP_INTERFACE
;
250 printf("Clearing status...");
253 while (dfu_ret
[4] != 0x08)
254 usb_control_msg(device
, usb_in_if
, DFU_GETSTATUS
, 0, 0, dfu_ret
, 6, DFU_TIMEOUT
);
255 usb_control_msg(device
, usb_out_if
, DFU_CLRSTATUS
, 0, 0, NULL
, 0, DFU_TIMEOUT
);
260 void dfu_detach(usb_dev_handle
*device
)
263 int usb_in_oth
= USB_ENDPOINT_IN
| USB_TYPE_CLASS
| USB_RECIP_OTHER
;
264 int usb_out_oth
= USB_ENDPOINT_OUT
| USB_TYPE_CLASS
| USB_RECIP_OTHER
;
266 printf("Detaching...");
268 usb_control_msg(device
, usb_in_oth
, DFU_DETACH
, 0x0000, 3, usb_ret
, 4, DFU_TIMEOUT
);
269 usb_control_msg(device
, usb_out_oth
, DFU_DOWNLOAD
, 0x0010, 3, NULL
, 0, DFU_TIMEOUT
);
270 usb_control_msg(device
, usb_in_oth
, DFU_DETACH
, 0x0000, 3, usb_ret
, 4, DFU_TIMEOUT
);
271 usb_control_msg(device
, usb_in_oth
, DFU_DETACH
, 0x0000, 3, usb_ret
, 4, DFU_TIMEOUT
);
272 usb_control_msg(device
, usb_in_oth
, DFU_DETACH
, 0x0000, 3, usb_ret
, 4, DFU_TIMEOUT
);
273 usb_control_msg(device
, usb_in_oth
, DFU_DETACH
, 0x0000, 3, usb_ret
, 4, DFU_TIMEOUT
);
274 usb_control_msg(device
, usb_in_oth
, DFU_DETACH
, 0x0000, 3, usb_ret
, 4, DFU_TIMEOUT
);
279 void dfu_m3_m6(char *file1
, char *file2
)
281 image_data_t img1
, img2
;
282 image_attr_t attr1
, attr2
;
283 usb_dev_handle
*device
;
286 attr1
.pre_off
= 0x20;
287 attr1
.pre_sig
= 0x44465543;
288 attr1
.suf_dev
= 0x0100;
289 attr1
.suf_prod
= 0x0140;
290 attr1
.suf_ven
= 0x0419;
291 attr1
.suf_dfu
= 0x0100;
292 memcpy(attr1
.suf_sig
, "RON", 3);
293 attr1
.suf_len
= 0x10;
296 attr2
.pre_off
= 0x20;
297 attr2
.pre_sig
= 0x44465543;
298 attr2
.suf_dev
= 0x0100;
299 attr2
.suf_prod
= 0x0140;
300 attr2
.suf_ven
= 0x0419;
301 attr2
.suf_dfu
= 0x0100;
302 memcpy(attr2
.suf_sig
, "UFD", 3);
303 attr2
.suf_len
= 0x10;
305 init_img(&img1
, file1
, &attr1
);
306 init_img(&img2
, file2
, &attr2
);
308 device
= usb_dev_open(USB_VID_SAMSUNG
, USB_PID_M3_M6
);
309 // usb_mimic_windows();
312 send_file(device
, &img1
);
314 printf("Wait a sec (literally)...");
318 clear_status(device
);
320 send_file(device
, &img2
);
322 usb_dev_close(device
);
325 void dfu_m6sl(char *file1
, char *file2
)
327 image_data_t img1
, img2
;
328 image_attr_t attr1
, attr2
;
329 usb_dev_handle
*device
;
332 attr1
.pre_off
= 0x20;
333 attr1
.pre_sig
= 0x44465543;
334 attr1
.suf_dev
= 0x0100;
335 attr1
.suf_prod
= 0x0140;
336 attr1
.suf_ven
= 0x0419;
337 attr1
.suf_dfu
= 0x0100;
338 memcpy(attr1
.suf_sig
, "UFD", 3);
339 attr1
.suf_len
= 0x10;
342 attr2
.pre_off
= 0x20;
343 attr2
.pre_sig
= 0x44465543;
344 attr2
.suf_dev
= 0x0100;
345 attr2
.suf_prod
= 0x0140;
346 attr2
.suf_ven
= 0x0419;
347 attr2
.suf_dfu
= 0x0100;
348 memcpy(attr2
.suf_sig
, "UFD", 3);
349 attr2
.suf_len
= 0x10;
351 init_img(&img1
, file1
, &attr1
);
352 init_img(&img2
, file2
, &attr2
);
354 device
= usb_dev_open(USB_VID_SAMSUNG
, USB_PID_M6SL
);
357 send_file(device
, &img1
);
359 printf("Wait a sec (literally)...");
362 usb_dev_close(device
);
364 device
= usb_dev_open(USB_VID_SAMSUNG
, USB_PID_M6SL
);
367 send_file(device
, &img2
);
369 usb_dev_close(device
);
373 int main(int argc
, char **argv
)
378 setvbuf(stdout
, NULL
, _IONBF
, 0);
380 if (!strcmp(argv
[1], "m3"))
381 dfu_m3_m6(argv
[2], argv
[3]);
382 else if (!strcmp(argv
[1], "m6"))
383 dfu_m3_m6(argv
[2], argv
[3]);
384 else if (!strcmp(argv
[1], "m6sl"))
385 dfu_m6sl(argv
[2], argv
[3]);