mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-12-08 12:45:26 -05:00
mks5lboot v1.0 - dualboot installer for s5l8702 targets
A tool to install/uninstall a bootloader into a s5l8702 based device: - iPod Classic 6G - iPod Nano 3G (TODO) See mks5lboot/README for detailed info. Change-Id: I451d2aaff34509ebd356e4660647e5222c5d3409
This commit is contained in:
parent
eefc7c73e2
commit
346423c040
16 changed files with 3226 additions and 0 deletions
287
rbutil/mks5lboot/main.c
Normal file
287
rbutil/mks5lboot/main.c
Normal file
|
|
@ -0,0 +1,287 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id:$
|
||||
*
|
||||
* Copyright (C) 2015 by Cástor Muñoz
|
||||
*
|
||||
* 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 <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "mks5lboot.h"
|
||||
|
||||
/* Win32 compatibility */
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
#define DEFAULT_LOOP_PERIOD 1 /* seconds */
|
||||
|
||||
#define ERROR(format, ...) \
|
||||
do { \
|
||||
snprintf(errstr, errstrsize, "[ERR] "format, __VA_ARGS__); \
|
||||
goto error; \
|
||||
} while(0)
|
||||
|
||||
static int write_file(char *outfile, unsigned char* buf,
|
||||
int bufsize, char* errstr, int errstrsize)
|
||||
{
|
||||
int fd = open(outfile, O_CREAT|O_TRUNC|O_WRONLY|O_BINARY, 0666);
|
||||
if (fd < 0)
|
||||
ERROR("Could not open %s for writing", outfile);
|
||||
|
||||
if (write(fd, buf, bufsize) != bufsize)
|
||||
ERROR("Could not write file %s", outfile);
|
||||
|
||||
return 1;
|
||||
|
||||
error:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned char *read_file(char *infile, int *bufsize,
|
||||
char* errstr, int errstrsize)
|
||||
{
|
||||
unsigned char *buf;
|
||||
int fd;
|
||||
struct stat s;
|
||||
|
||||
fd = open(infile, O_RDONLY|O_BINARY);
|
||||
if (fd < 0)
|
||||
ERROR("Could not open %s for reading", infile);
|
||||
|
||||
if (fstat(fd, &s) < 0)
|
||||
ERROR("Checking size of input file %s", infile);
|
||||
|
||||
*bufsize = s.st_size;
|
||||
|
||||
buf = malloc(*bufsize);
|
||||
if (buf == NULL)
|
||||
ERROR("Could not allocate memory for %s", infile);
|
||||
|
||||
if (read(fd, buf, *bufsize) != *bufsize)
|
||||
ERROR("Could not read file %s", infile);
|
||||
|
||||
return buf;
|
||||
|
||||
error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void sleep_ms(unsigned int ms)
|
||||
{
|
||||
struct timespec req;
|
||||
req.tv_sec = ms / 1000;
|
||||
req.tv_nsec = (ms % 1000) * 1000000;
|
||||
nanosleep(&req, NULL);
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage:\n"
|
||||
" mks5lboot --bl-inst <bootloader.ipod> [-p <pid>] [--single]\n"
|
||||
" --bl-uninst <platform> [-p <pid>]\n"
|
||||
" --dfuscan [--loop [<sec>]] [-p <pid>]\n"
|
||||
" --dfusend <infile.dfu> [-p <pid>]\n"
|
||||
" --dfureset [--loop [<sec>]] [-p <pid>]\n"
|
||||
" --mkdfu-inst <bootloader.ipod> <outfile.dfu> [--single]\n"
|
||||
" --mkdfu-uninst <platform> <outfile.dfu>\n"
|
||||
" --mkdfu-raw <filename.bin> <outfile.dfu>\n"
|
||||
"\n"
|
||||
"Commands:\n"
|
||||
" --bl-inst Install file <bootloader.ipod> into an iPod device\n"
|
||||
" (same as --mkdfu-inst and --dfusend).\n"
|
||||
" --bl-uninst Remove a bootloader from an iPod device (same as\n"
|
||||
" --mkdfu-uninst and --dfusend).\n"
|
||||
"\n"
|
||||
" --dfuscan scan for DFU USB devices and outputs the status.\n"
|
||||
" --dfusend send DFU image <infile.dfu> to the device.\n"
|
||||
" --dfureset reset DFU USB device bus.\n"
|
||||
"\n"
|
||||
" --mkdfu-inst Build a DFU image containing an installer for\n"
|
||||
" <bootloader.ipod>, save it as <outfile.dfu>.\n"
|
||||
" --mkdfu-uninst Build a DFU image containing an uninstaler for\n"
|
||||
" <platform> devices, save it as <outfile.dfu>.\n"
|
||||
" --mkdfu-raw Build a DFU image containing raw executable\n"
|
||||
" code, save it ass <outfile.dfu>. <infile.bin>\n"
|
||||
" is the code you want to run, it is loaded at\n"
|
||||
" address 0x%08x and executed.\n"
|
||||
"\n"
|
||||
" <bootloader.ipod> is the rockbox bootloader that you want to\n"
|
||||
" install (previously scrambled with tools/scramble utility).\n"
|
||||
"\n"
|
||||
" <platform> is the name of the platform (type of device) for\n"
|
||||
" which the DFU uninstaller will be built. Currently supported\n"
|
||||
" platform names are:\n"
|
||||
" ipod6g: iPod Classic 6G\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
" -p, --pid <pid> Use a specific <pid> (Product Id) USB device,\n"
|
||||
" if this option is ommited then it uses the\n"
|
||||
" first USB DFU device found.\n"
|
||||
" -l, --loop <sec> Run the command every <sec> seconds, default\n"
|
||||
" period (<sec> ommited) is %d seconds.\n"
|
||||
" -S, --single Be careful using this option. The bootloader\n"
|
||||
" is installed for single boot, the original\n"
|
||||
" Apple NOR boot is destroyed (if it exists),\n"
|
||||
" and only Rockbox can be used.\n"
|
||||
, DFU_LOADADDR + BIN_OFFSET
|
||||
, DEFAULT_LOOP_PERIOD);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
char *dfuoutfile = NULL;
|
||||
char *dfuinfile = NULL;
|
||||
char *dfu_arg = NULL;
|
||||
int dfu_type = DFU_NONE;
|
||||
int n_cmds = 0;
|
||||
int scan = 0;
|
||||
int pid = 0;
|
||||
int reset = 0;
|
||||
int loop = 0;
|
||||
int single = 0;
|
||||
char errstr[200];
|
||||
unsigned char *dfubuf;
|
||||
int dfusize;
|
||||
|
||||
fprintf(stderr,
|
||||
"mks5lboot Version " VERSION "\n"
|
||||
"This is free software; see the source for copying conditions. There is NO\n"
|
||||
"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
|
||||
"\n");
|
||||
fflush(stderr);
|
||||
|
||||
while (--argc)
|
||||
{
|
||||
argv++;
|
||||
if (!memcmp(*argv, "--bl", 4)) {
|
||||
if (!strcmp(*argv+4, "-inst")) dfu_type = DFU_INST;
|
||||
else if (!strcmp(*argv+4, "-uninst")) dfu_type = DFU_UNINST;
|
||||
else usage();
|
||||
if (!--argc) usage();
|
||||
dfu_arg = *++argv;
|
||||
n_cmds++;
|
||||
}
|
||||
else if (!memcmp(*argv, "--mkdfu", 7)) {
|
||||
if (!strcmp(*argv+7, "-inst")) dfu_type = DFU_INST;
|
||||
else if (!strcmp(*argv+7, "-uninst")) dfu_type = DFU_UNINST;
|
||||
else if (!strcmp(*argv+7, "-raw")) dfu_type = DFU_RAW;
|
||||
else usage();
|
||||
if (!--argc) usage();
|
||||
dfu_arg = *++argv;
|
||||
if (!--argc) usage();
|
||||
dfuoutfile = *++argv;
|
||||
n_cmds++;
|
||||
}
|
||||
else if (!strcmp(*argv, "--dfusend")) {
|
||||
if (!--argc) usage();
|
||||
dfuinfile = *++argv;
|
||||
n_cmds++;
|
||||
}
|
||||
else if (!strcmp(*argv, "--dfuscan")) {
|
||||
scan = 1;
|
||||
n_cmds++;
|
||||
}
|
||||
else if (!strcmp(*argv, "--dfureset")) {
|
||||
scan = 1;
|
||||
reset = 1;
|
||||
n_cmds++;
|
||||
}
|
||||
else if (!strcmp(*argv, "--pid") || !strcmp(*argv, "-p")) {
|
||||
if (!--argc) usage();
|
||||
if (sscanf(*++argv, "%x", &pid) != 1) usage();
|
||||
}
|
||||
else if (!strcmp(*argv, "--loop") || !strcmp (*argv, "-l")) {
|
||||
if (!(argc-1) || *(argv+1)[0] == '-') {
|
||||
loop = DEFAULT_LOOP_PERIOD;
|
||||
}
|
||||
else {
|
||||
if ((sscanf(*++argv, "%d", &loop) != 1) || !loop) usage();
|
||||
argc--;
|
||||
}
|
||||
}
|
||||
else if (!strcmp(*argv, "--single") || !strcmp(*argv, "-S")) {
|
||||
single = 1;
|
||||
}
|
||||
else if (!strcmp(*argv, "--debug")) {
|
||||
ipoddfu_debug(1);
|
||||
}
|
||||
else
|
||||
usage();
|
||||
}
|
||||
|
||||
if (n_cmds != 1)
|
||||
usage();
|
||||
|
||||
if ((dfu_type == DFU_INST) && single)
|
||||
dfu_type = DFU_INST_SINGLE;
|
||||
|
||||
if (scan) {
|
||||
int cnt = 0;
|
||||
while (1) {
|
||||
int state, res;
|
||||
if (loop) printf("[%d] ", cnt);
|
||||
else printf("[INFO] ");
|
||||
printf("DFU %s:\n", reset ? "reset":"scan");
|
||||
res = ipoddfu_scan(pid, &state, reset, errstr, sizeof(errstr));
|
||||
if (res == 0)
|
||||
printf("%s\n", errstr);
|
||||
else
|
||||
printf("[INFO] DFU device state: %d\n", state);
|
||||
if (!loop)
|
||||
exit(!res);
|
||||
fflush(stdout);
|
||||
sleep_ms(loop*1000);
|
||||
cnt += loop;
|
||||
}
|
||||
}
|
||||
|
||||
if (dfuinfile)
|
||||
dfubuf = read_file(dfuinfile, &dfusize, errstr, sizeof(errstr));
|
||||
else
|
||||
dfubuf = mkdfu(dfu_type, dfu_arg, &dfusize, errstr, sizeof(errstr));
|
||||
|
||||
if (!dfubuf)
|
||||
goto error;
|
||||
|
||||
if (dfuoutfile) {
|
||||
if (write_file(dfuoutfile, dfubuf, dfusize, errstr, sizeof(errstr))) {
|
||||
printf("[INFO] Created file %s (%d bytes)\n", dfuoutfile, dfusize);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ipoddfu_send(pid, dfubuf, dfusize, errstr, sizeof(errstr))) {
|
||||
printf("[INFO] DFU image sent successfully (%d bytes)\n", dfusize);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
error:
|
||||
printf("%s\n", errstr);
|
||||
exit(1);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue