From c876d3bbefe0dc00c27ca0c12d29da5874946962 Mon Sep 17 00:00:00 2001 From: Dominik Riebeling Date: Wed, 15 Dec 2021 21:04:28 +0100 Subject: rbutil: Merge rbutil with utils folder. rbutil uses several components from the utils folder, and can be considered part of utils too. Having it in a separate folder is an arbitrary split that doesn't help anymore these days, so merge them. This also allows other utils to easily use libtools.make without the need to navigate to a different folder. Change-Id: I3fc2f4de19e3e776553efb5dea5f779dfec0dc21 --- utils/mks5lboot/main.c | 296 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 296 insertions(+) create mode 100644 utils/mks5lboot/main.c (limited to 'utils/mks5lboot/main.c') diff --git a/utils/mks5lboot/main.c b/utils/mks5lboot/main.c new file mode 100644 index 0000000000..31e16eca82 --- /dev/null +++ b/utils/mks5lboot/main.c @@ -0,0 +1,296 @@ +/*************************************************************************** + * __________ __ ___. + * 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 +#include +#include +#include +#include +#include +#include + +#include "mks5lboot.h" + +/* Win32 compatibility */ +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +#ifdef WIN32 +#include +#define sleep_ms(ms) Sleep(ms) +#else +#include +static void sleep_ms(unsigned int ms) +{ + struct timespec req; + req.tv_sec = ms / 1000; + req.tv_nsec = (ms % 1000) * 1000000; + nanosleep(&req, NULL); +} +#endif + +#define DEFAULT_LOOP_PERIOD 1 /* seconds */ + +#define _ERR(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) + _ERR("Could not open %s for writing", outfile); + + if (write(fd, buf, bufsize) != bufsize) + _ERR("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) + _ERR("Could not open %s for reading", infile); + + if (fstat(fd, &s) < 0) + _ERR("Checking size of input file %s", infile); + + *bufsize = s.st_size; + + buf = malloc(*bufsize); + if (buf == NULL) + _ERR("Could not allocate memory for %s", infile); + + if (read(fd, buf, *bufsize) != *bufsize) + _ERR("Could not read file %s", infile); + + return buf; + +error: + return NULL; +} + +static void usage(void) +{ + fprintf(stderr, + "Usage:\n" + " mks5lboot --bl-inst [-p ] [--single]\n" + " --bl-uninst [-p ]\n" + " --dfuscan [--loop []] [-p ]\n" + " --dfusend [-p ]\n" + " --dfureset [--loop []] [-p ]\n" + " --mkdfu-inst [--single]\n" + " --mkdfu-uninst \n" + " --mkdfu-raw \n" + "\n" + "Commands:\n" + " --bl-inst Install file 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 to the device.\n" + " --dfureset reset DFU USB device bus.\n" + "\n" + " --mkdfu-inst Build a DFU image containing an installer for\n" + " , save it as .\n" + " --mkdfu-uninst Build a DFU image containing an uninstaler for\n" + " devices, save it as .\n" + " --mkdfu-raw Build a DFU image containing raw executable\n" + " code, save it ass . \n" + " is the code you want to run, it is loaded at\n" + " address 0x%08x and executed.\n" + "\n" + " is the rockbox bootloader that you want to\n" + " install (previously scrambled with tools/scramble utility).\n" + "\n" + " 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 Use a specific (Product Id) USB device,\n" + " if this option is ommited then it uses the\n" + " first USB DFU device found.\n" + " -l, --loop Run the command every seconds, default\n" + " period ( 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, +#if defined(WIN32) && defined(USE_LIBUSBAPI) + "mks5lboot Version " VERSION " (libusb)\n" +#else + "mks5lboot Version " VERSION "\n" +#endif + "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); +} -- cgit v1.2.3