mirror of
https://github.com/Rockbox/rockbox.git
synced 2026-04-11 16:37:45 -04:00
Remove Meizu M3/M6SL/M6SP and Samsung YP-S3 ports
These targets haven't seen any changes since 2008-09 have bitrotted to the point they don't compile anymore. With only internal NAND flash for storage which doesn't seem to have ever been accessible from Rockbox, they've never been usable and there's probably not much point keeping them around any more. Change-Id: I2fc63da20682b439126672065ae013044cb2d1c4
This commit is contained in:
parent
19fe7a4915
commit
1a33d7990a
60 changed files with 38 additions and 5990 deletions
|
|
@ -1,11 +0,0 @@
|
|||
CFLAGS = -W -Wall
|
||||
LDFLAGS = -lusb
|
||||
|
||||
all: meizu_dfu
|
||||
|
||||
meizu_dfu: meizu_dfu.c
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f meizu_dfu
|
||||
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
Meizu DFU tool for Linux
|
||||
|
||||
This tool can restore the firmware on M3, M6 SP, M6 TP and M6 SL.
|
||||
It can also run a single provided file from RAM.
|
||||
|
||||
Notes:
|
||||
1. SST39VF800.dfu is taken from the official dfu tool provided by Meizu.
|
||||
2. updateNAND_BE_070831.dfu is taken from the unofficial dfu tool for M6 SL.
|
||||
3. To compile, just run `make'.
|
||||
|
|
@ -1,441 +0,0 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2008 by William Poetra Yoga Hadisoeseno and Frank Gevaerts
|
||||
*
|
||||
* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <libgen.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <usb.h>
|
||||
|
||||
#define bswap_16(value) \
|
||||
((((value) & 0xff) << 8) | ((value) >> 8))
|
||||
|
||||
#define bswap_32(value) \
|
||||
(((uint32_t)bswap_16((uint16_t)((value) & 0xffff)) << 16) | \
|
||||
(uint32_t)bswap_16((uint16_t)((value) >> 16)))
|
||||
|
||||
#define host_to_le32(_x) bswap_32(htonl(_x))
|
||||
#define host_to_le16(_x) bswap_16(htons(_x))
|
||||
|
||||
void usage()
|
||||
{
|
||||
fprintf(stderr, "usage: meizu_dfu m3 [SST39VF800.dfu] <M3.EBN>\n");
|
||||
fprintf(stderr, " meizu_dfu m6 [SST39VF800.dfu] <M6.EBN>\n");
|
||||
fprintf(stderr, " meizu_dfu m6sl [updateNAND_BE_070831.dfu] <M6SL.EBN>\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uint32_t crc32(char *data, int len, uint32_t poly, uint32_t init)
|
||||
{
|
||||
uint32_t crc_table[256];
|
||||
uint32_t crc, t;
|
||||
int i, j;
|
||||
|
||||
// generate the table
|
||||
for (i = 0; i < 256; ++i) {
|
||||
t = i;
|
||||
for (j = 0; j < 8; ++j)
|
||||
if (t & 1)
|
||||
t = (t >> 1) ^ poly;
|
||||
else
|
||||
t >>= 1;
|
||||
crc_table[i] = t;
|
||||
}
|
||||
|
||||
// calculate the crc
|
||||
crc = init;
|
||||
for (i = 0; i < len; ++i)
|
||||
crc = (crc >> 8) ^ crc_table[(crc^data[i]) & 0xff];
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
char *data;
|
||||
int len;
|
||||
} image_data_t;
|
||||
|
||||
typedef struct {
|
||||
int delay;
|
||||
int pre_off;
|
||||
uint32_t pre_sig;
|
||||
uint16_t suf_dev;
|
||||
uint16_t suf_prod;
|
||||
uint16_t suf_ven;
|
||||
uint16_t suf_dfu;
|
||||
char suf_sig[3];
|
||||
uint8_t suf_len;
|
||||
} image_attr_t;
|
||||
|
||||
#define BLOCK_SIZE 2048
|
||||
#define DFU_TIMEOUT 0xa000
|
||||
#define DFU_CRC_POLY 0xedb88320
|
||||
#define DFU_INIT_CRC 0xffffffff
|
||||
|
||||
#define USB_VID_SAMSUNG 0x0419
|
||||
#define USB_PID_M6SL 0x0145
|
||||
#define USB_PID_M3_M6 0x0141
|
||||
|
||||
void init_img(image_data_t *img, const char *filename, image_attr_t *attr)
|
||||
{
|
||||
int fd, len, i, readlen;
|
||||
struct stat statbuf;
|
||||
char buf[BLOCK_SIZE];
|
||||
uint32_t dfu_crc;
|
||||
uint32_t le_len;
|
||||
|
||||
printf("Reading %s...", filename);
|
||||
|
||||
if (stat(filename, &statbuf) < 0) {
|
||||
printf("\nCould not stat file, exiting.\n");
|
||||
exit(1);
|
||||
}
|
||||
len = statbuf.st_size;
|
||||
|
||||
img->name = basename(strdup(filename));
|
||||
img->data = malloc(len + 16);
|
||||
img->len = len + 16;
|
||||
|
||||
fd = open(filename, O_RDONLY);
|
||||
for (i = 0; i < len; i += BLOCK_SIZE) {
|
||||
readlen = ((len - i) < BLOCK_SIZE) ? (len - i) : BLOCK_SIZE;
|
||||
read(fd, buf, readlen);
|
||||
memcpy(img->data + i, buf, readlen);
|
||||
}
|
||||
close(fd);
|
||||
|
||||
le_len = host_to_le32(img->len);
|
||||
// patch the data size in after the signature
|
||||
memcpy(img->data + attr->pre_off + 4, &le_len, 4);
|
||||
|
||||
/* convert to little endian */
|
||||
attr->suf_dev = host_to_le16(attr->suf_dev);
|
||||
attr->suf_prod = host_to_le16(attr->suf_prod);
|
||||
attr->suf_ven = host_to_le16(attr->suf_ven);
|
||||
attr->suf_dfu = host_to_le16(attr->suf_dfu);
|
||||
|
||||
// append the suffix (excluding the checksum)
|
||||
memcpy(img->data + len, &attr->suf_dev, 2);
|
||||
memcpy(img->data + len + 2, &attr->suf_prod, 2);
|
||||
memcpy(img->data + len + 4, &attr->suf_ven, 2);
|
||||
memcpy(img->data + len + 6, &attr->suf_dfu, 2);
|
||||
memcpy(img->data + len + 8, &attr->suf_sig, 3);
|
||||
memcpy(img->data + len + 11, &attr->suf_len, 1);
|
||||
|
||||
dfu_crc = host_to_le32(crc32(img->data, len + 12, DFU_CRC_POLY, DFU_INIT_CRC));
|
||||
memcpy(img->data + len + 12, &dfu_crc, 4);
|
||||
|
||||
#if 0
|
||||
FILE *f = fopen(img->name, "w");
|
||||
fwrite(img->data, len + 16, 1, f);
|
||||
fclose(f);
|
||||
#endif
|
||||
|
||||
printf("OK\n");
|
||||
}
|
||||
|
||||
usb_dev_handle *usb_dev_open(uint16_t dfu_vid, uint16_t dfu_pid)
|
||||
{
|
||||
struct usb_bus *bus;
|
||||
struct usb_device *dev;
|
||||
usb_dev_handle *device;
|
||||
|
||||
printf("USB initialization...");
|
||||
|
||||
usb_init();
|
||||
usb_find_busses();
|
||||
usb_find_devices();
|
||||
|
||||
for (bus = usb_get_busses(); bus != NULL; bus = bus->next)
|
||||
for (dev = bus->devices; dev != NULL; dev = dev->next)
|
||||
if (dev->descriptor.idVendor == dfu_vid
|
||||
&& dev->descriptor.idProduct == dfu_pid)
|
||||
goto found;
|
||||
|
||||
printf("\nNo device found, exiting.\n");
|
||||
exit(1);
|
||||
|
||||
found:
|
||||
printf(" Device found.\n");
|
||||
device = usb_open(dev);
|
||||
usb_claim_interface(device, 0);
|
||||
return device;
|
||||
}
|
||||
|
||||
void usb_mimic_windows(usb_dev_handle *device)
|
||||
{
|
||||
char data[1024];
|
||||
|
||||
usb_control_msg(device, 0x80, 0x06, 0x0100, 0x0000, data, 0x0012, DFU_TIMEOUT);
|
||||
usb_control_msg(device, 0x80, 0x06, 0x0200, 0x0000, data, 0x0009, DFU_TIMEOUT);
|
||||
usb_control_msg(device, 0x80, 0x06, 0x0200, 0x0000, data, 0x001b, DFU_TIMEOUT);
|
||||
usb_control_msg(device, 0x80, 0x06, 0x0100, 0x0000, data, 0x0040, DFU_TIMEOUT);
|
||||
usb_control_msg(device, 0x80, 0x06, 0x0100, 0x0000, data, 0x0012, DFU_TIMEOUT);
|
||||
usb_control_msg(device, 0x80, 0x06, 0x0200, 0x0000, data, 0x0009, DFU_TIMEOUT);
|
||||
usb_control_msg(device, 0x80, 0x06, 0x0300, 0x0000, data, 0x00ff, DFU_TIMEOUT);
|
||||
usb_control_msg(device, 0x80, 0x06, 0x0303, 0x0409, data, 0x00ff, DFU_TIMEOUT);
|
||||
usb_control_msg(device, 0x80, 0x06, 0x0200, 0x0000, data, 0x00ff, DFU_TIMEOUT);
|
||||
usb_control_msg(device, 0x80, 0x06, 0x0300, 0x0000, data, 0x00ff, DFU_TIMEOUT);
|
||||
usb_control_msg(device, 0x80, 0x06, 0x0302, 0x0409, data, 0x00ff, DFU_TIMEOUT);
|
||||
usb_control_msg(device, 0x80, 0x06, 0x0300, 0x0000, data, 0x00ff, DFU_TIMEOUT);
|
||||
usb_control_msg(device, 0x80, 0x06, 0x0302, 0x0409, data, 0x00ff, DFU_TIMEOUT);
|
||||
usb_control_msg(device, 0x80, 0x06, 0x0100, 0x0000, data, 0x0012, DFU_TIMEOUT);
|
||||
usb_control_msg(device, 0x80, 0x06, 0x0200, 0x0000, data, 0x0209, DFU_TIMEOUT);
|
||||
}
|
||||
|
||||
void usb_dev_close(usb_dev_handle *device)
|
||||
{
|
||||
printf("Releasing interface...");
|
||||
|
||||
usb_release_interface(device, 0);
|
||||
|
||||
printf(" OK\n");
|
||||
}
|
||||
|
||||
enum DFU_REQUEST {
|
||||
DFU_DETACH = 0,
|
||||
DFU_DOWNLOAD,
|
||||
DFU_UPLOAD,
|
||||
DFU_GETSTATUS,
|
||||
DFU_CLRSTATUS,
|
||||
DFU_GETSTATE,
|
||||
DFU_ABORT
|
||||
};
|
||||
|
||||
void get_cpu(usb_dev_handle *device)
|
||||
{
|
||||
char data[64];
|
||||
int req_out_if = USB_ENDPOINT_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
|
||||
int len;
|
||||
|
||||
printf("GET CPU");
|
||||
|
||||
// check for "S5L8700 Rev.1"
|
||||
len = usb_control_msg(device, req_out_if, 0xff, 0x0002, 0, data, 0x003f, DFU_TIMEOUT);
|
||||
if (len < 0) {
|
||||
printf("\nError trying to get CPU model, exiting.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memset(data + len, 0, 64 - len);
|
||||
printf(", got: %s\n", data);
|
||||
}
|
||||
|
||||
void send_file(usb_dev_handle *device, image_data_t *img)
|
||||
{
|
||||
char dfu_ret[6];
|
||||
char *data;
|
||||
int req_out_if = USB_ENDPOINT_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
|
||||
int req_in_if = USB_ENDPOINT_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
|
||||
int len, idx, writelen, i;
|
||||
|
||||
printf("Sending %s... ", img->name);
|
||||
|
||||
len = img->len;
|
||||
data = img->data;
|
||||
|
||||
// loop for the file
|
||||
for (i = 0, idx = 0; i < len; i += BLOCK_SIZE, ++idx) {
|
||||
writelen = ((len - i) < BLOCK_SIZE) ? (len - i) : BLOCK_SIZE;
|
||||
usb_control_msg(device, req_out_if, DFU_DOWNLOAD, idx, 0, data + i, writelen, DFU_TIMEOUT);
|
||||
dfu_ret[4] = 0x00;
|
||||
while (dfu_ret[4] != 0x05)
|
||||
usb_control_msg(device, req_in_if, DFU_GETSTATUS, 0, 0, dfu_ret, 6, DFU_TIMEOUT);
|
||||
printf("#");
|
||||
}
|
||||
|
||||
usb_control_msg(device, req_out_if, DFU_DOWNLOAD, idx, 0, NULL, 0, DFU_TIMEOUT);
|
||||
dfu_ret[4] = 0x00;
|
||||
while (dfu_ret[4] != 0x07)
|
||||
usb_control_msg(device, req_in_if, DFU_GETSTATUS, 0, 0, dfu_ret, 6, DFU_TIMEOUT);
|
||||
|
||||
printf(" OK\n");
|
||||
}
|
||||
|
||||
void clear_status(usb_dev_handle *device)
|
||||
{
|
||||
char dfu_ret[6];
|
||||
int usb_in_if = USB_ENDPOINT_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
|
||||
int usb_out_if = USB_ENDPOINT_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
|
||||
|
||||
printf("Clearing status...");
|
||||
|
||||
dfu_ret[4] = 0x00;
|
||||
while (dfu_ret[4] != 0x08)
|
||||
usb_control_msg(device, usb_in_if, DFU_GETSTATUS, 0, 0, dfu_ret, 6, DFU_TIMEOUT);
|
||||
usb_control_msg(device, usb_out_if, DFU_CLRSTATUS, 0, 0, NULL, 0, DFU_TIMEOUT);
|
||||
|
||||
printf(" OK\n");
|
||||
}
|
||||
|
||||
void dfu_detach(usb_dev_handle *device)
|
||||
{
|
||||
char usb_ret[4];
|
||||
int usb_in_oth = USB_ENDPOINT_IN | USB_TYPE_CLASS | USB_RECIP_OTHER;
|
||||
int usb_out_oth = USB_ENDPOINT_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER;
|
||||
|
||||
printf("Detaching...");
|
||||
|
||||
usb_control_msg(device, usb_in_oth, DFU_DETACH, 0x0000, 3, usb_ret, 4, DFU_TIMEOUT);
|
||||
usb_control_msg(device, usb_out_oth, DFU_DOWNLOAD, 0x0010, 3, NULL, 0, DFU_TIMEOUT);
|
||||
usb_control_msg(device, usb_in_oth, DFU_DETACH, 0x0000, 3, usb_ret, 4, DFU_TIMEOUT);
|
||||
usb_control_msg(device, usb_in_oth, DFU_DETACH, 0x0000, 3, usb_ret, 4, DFU_TIMEOUT);
|
||||
usb_control_msg(device, usb_in_oth, DFU_DETACH, 0x0000, 3, usb_ret, 4, DFU_TIMEOUT);
|
||||
usb_control_msg(device, usb_in_oth, DFU_DETACH, 0x0000, 3, usb_ret, 4, DFU_TIMEOUT);
|
||||
usb_control_msg(device, usb_in_oth, DFU_DETACH, 0x0000, 3, usb_ret, 4, DFU_TIMEOUT);
|
||||
|
||||
printf(" OK\n");
|
||||
}
|
||||
|
||||
void dfu_m3_m6(char *file1, char *file2)
|
||||
{
|
||||
image_data_t img1, img2;
|
||||
image_attr_t attr1, attr2;
|
||||
usb_dev_handle *device;
|
||||
|
||||
attr1.delay = 1000;
|
||||
attr1.pre_off = 0x20;
|
||||
attr1.pre_sig = 0x44465543;
|
||||
attr1.suf_dev = 0x0100;
|
||||
attr1.suf_prod = 0x0140;
|
||||
attr1.suf_ven = 0x0419;
|
||||
attr1.suf_dfu = 0x0100;
|
||||
memcpy(attr1.suf_sig, "RON", 3);
|
||||
attr1.suf_len = 0x10;
|
||||
|
||||
init_img(&img1, file1, &attr1);
|
||||
|
||||
if (file2) {
|
||||
attr2.delay = 1000;
|
||||
attr2.pre_off = 0x20;
|
||||
attr2.pre_sig = 0x44465543;
|
||||
attr2.suf_dev = 0x0100;
|
||||
attr2.suf_prod = 0x0140;
|
||||
attr2.suf_ven = 0x0419;
|
||||
attr2.suf_dfu = 0x0100;
|
||||
memcpy(attr2.suf_sig, "UFD", 3);
|
||||
attr2.suf_len = 0x10;
|
||||
|
||||
init_img(&img2, file2, &attr2);
|
||||
}
|
||||
|
||||
device = usb_dev_open(USB_VID_SAMSUNG, USB_PID_M3_M6);
|
||||
// usb_mimic_windows();
|
||||
get_cpu(device);
|
||||
get_cpu(device);
|
||||
send_file(device, &img1);
|
||||
|
||||
if (file2) {
|
||||
printf("Wait a sec (literally)...");
|
||||
sleep(1);
|
||||
printf(" OK\n");
|
||||
|
||||
clear_status(device);
|
||||
get_cpu(device);
|
||||
send_file(device, &img2);
|
||||
dfu_detach(device);
|
||||
}
|
||||
|
||||
usb_dev_close(device);
|
||||
}
|
||||
|
||||
void dfu_m6sl(char *file1, char *file2)
|
||||
{
|
||||
image_data_t img1, img2;
|
||||
image_attr_t attr1, attr2;
|
||||
usb_dev_handle *device;
|
||||
|
||||
attr1.delay = 1000;
|
||||
attr1.pre_off = 0x20;
|
||||
attr1.pre_sig = 0x44465543;
|
||||
attr1.suf_dev = 0x0100;
|
||||
attr1.suf_prod = 0x0140;
|
||||
attr1.suf_ven = 0x0419;
|
||||
attr1.suf_dfu = 0x0100;
|
||||
memcpy(attr1.suf_sig, "UFD", 3);
|
||||
attr1.suf_len = 0x10;
|
||||
|
||||
init_img(&img1, file1, &attr1);
|
||||
|
||||
if (file2) {
|
||||
attr2.delay = 1000;
|
||||
attr2.pre_off = 0x20;
|
||||
attr2.pre_sig = 0x44465543;
|
||||
attr2.suf_dev = 0x0100;
|
||||
attr2.suf_prod = 0x0140;
|
||||
attr2.suf_ven = 0x0419;
|
||||
attr2.suf_dfu = 0x0100;
|
||||
memcpy(attr2.suf_sig, "UFD", 3);
|
||||
attr2.suf_len = 0x10;
|
||||
|
||||
init_img(&img2, file2, &attr2);
|
||||
}
|
||||
|
||||
device = usb_dev_open(USB_VID_SAMSUNG, USB_PID_M6SL);
|
||||
get_cpu(device);
|
||||
get_cpu(device);
|
||||
send_file(device, &img1);
|
||||
|
||||
if (file2) {
|
||||
printf("Wait a sec (literally)...");
|
||||
sleep(1);
|
||||
printf(" OK\n");
|
||||
usb_dev_close(device);
|
||||
|
||||
device = usb_dev_open(USB_VID_SAMSUNG, USB_PID_M6SL);
|
||||
get_cpu(device);
|
||||
get_cpu(device);
|
||||
send_file(device, &img2);
|
||||
dfu_detach(device);
|
||||
}
|
||||
|
||||
usb_dev_close(device);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc < 3 || argc > 4)
|
||||
usage();
|
||||
|
||||
setvbuf(stdout, NULL, _IONBF, 0);
|
||||
|
||||
char *second_file = (argc == 4) ? argv[3] : NULL;
|
||||
|
||||
if (!strcmp(argv[1], "m3"))
|
||||
dfu_m3_m6(argv[2], second_file);
|
||||
else if (!strcmp(argv[1], "m6"))
|
||||
dfu_m3_m6(argv[2], second_file);
|
||||
else if (!strcmp(argv[1], "m6sl"))
|
||||
dfu_m6sl(argv[2], second_file);
|
||||
else
|
||||
usage();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -589,33 +589,6 @@ lyreproto1
|
|||
record : no
|
||||
}
|
||||
|
||||
meizum3
|
||||
{
|
||||
name : Meizu M3
|
||||
screen : 176 x 132 @ rgb
|
||||
remote : no
|
||||
fm : yes
|
||||
record : no
|
||||
}
|
||||
|
||||
meizum6sl
|
||||
{
|
||||
name : Meizu M6SL
|
||||
screen : 320 x 240 @ rgb
|
||||
remote : no
|
||||
fm : yes
|
||||
record : no
|
||||
}
|
||||
|
||||
meizum6sp
|
||||
{
|
||||
name : Meizu M6SP
|
||||
screen : 240 x 320 @ rgb
|
||||
remote : no
|
||||
fm : yes
|
||||
record : no
|
||||
}
|
||||
|
||||
mini2440
|
||||
{
|
||||
name : Mini 2440
|
||||
|
|
@ -688,15 +661,6 @@ samsungypr0
|
|||
record : no
|
||||
}
|
||||
|
||||
samsungyps3
|
||||
{
|
||||
name : Samsung YP-S3
|
||||
screen : 176 x 220 @ rgb
|
||||
remote : no
|
||||
fm : yes
|
||||
record : no
|
||||
}
|
||||
|
||||
sansac100
|
||||
{
|
||||
name : SanDisk Sansa c100
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue