diff options
Diffstat (limited to 'libdpf/bootload.c')
-rw-r--r-- | libdpf/bootload.c | 634 |
1 files changed, 348 insertions, 286 deletions
diff --git a/libdpf/bootload.c b/libdpf/bootload.c index 2d882cf..342ec2b 100644 --- a/libdpf/bootload.c +++ b/libdpf/bootload.c @@ -5,7 +5,7 @@ // #include "dpf.h" -#include "usbuser.h" // our user defined flash commands +#include "usbuser.h" // our user defined flash commands #include <stdio.h> #include <string.h> #include <unistd.h> @@ -20,360 +20,422 @@ #define BUFSIZE (64 - 6) #define PKTSIZE (64 - 7) -typedef struct { - unsigned char len; - unsigned char chk; - unsigned char jmp[2]; - union { - // Structures for various backends - // The default memory loader: - struct { - unsigned char offset[2]; // XDATA memory dest address - unsigned char buf[BUFSIZE]; // Binary data to write - } loader; - struct { - unsigned char opcode; // SPI operation opcode - unsigned char wnum; // Number of bytes to send (Host -> DPF) - unsigned char rnum; // Number of bytes to recv (DPF -> Host) - unsigned char seq[PKTSIZE]; // SPI cmd sequence - } spi; - } u; +typedef struct +{ + unsigned char len; + unsigned char chk; + unsigned char jmp[2]; + union + { + // Structures for various backends + // The default memory loader: + struct + { + unsigned char offset[2]; // XDATA memory dest address + unsigned char buf[BUFSIZE]; // Binary data to write + } loader; + struct + { + unsigned char opcode; // SPI operation opcode + unsigned char wnum; // Number of bytes to send (Host -> DPF) + unsigned char rnum; // Number of bytes to recv (DPF -> Host) + unsigned char seq[PKTSIZE]; // SPI cmd sequence + } spi; + } u; } UsbMsg; -#define OPCODE_SPISEL 0x01 // assert SELECT +#define OPCODE_SPISEL 0x01 // assert SELECT #define OPCODE_CRYPT0 0x02 #define OPCODE_CRYPT1 0x04 -#define OPCODE_SPIDES 0x10 // assert DESELECT +#define OPCODE_SPIDES 0x10 // assert DESELECT -int validate(UsbMsg *msg) +int +validate (UsbMsg * msg) { - unsigned short c = 0; - unsigned char *b = (unsigned char *) msg; - unsigned short l = msg->len; + unsigned short c = 0; + unsigned char *b = (unsigned char *) msg; + unsigned short l = msg->len; - if (l < 6 || l > 64) return -1; + if (l < 6 || l > 64) + return -1; - while (l--) { - c += *b++; - } + while (l--) + { + c += *b++; + } - msg->chk -= c; + msg->chk -= c; - return 0; + return 0; } -void hexdump(unsigned char *buf, unsigned long n) +void +hexdump (unsigned char *buf, unsigned long n) { - int i = 0; - int c = 0; - - while (i < n) { - printf("%02x ", buf[i]); - c++; - if (c == 16) { c = 0; printf("\n"); } - i++; - } - if (c) - printf("\n"); + int i = 0; + int c = 0; + + while (i < n) + { + printf ("%02x ", buf[i]); + c++; + if (c == 16) + { + c = 0; + printf ("\n"); + } + i++; + } + if (c) + printf ("\n"); } -int transmit(DPFContext *dpf, UsbMsg *m) +int +transmit (DPFContext * dpf, UsbMsg * m) { - int error; - unsigned char *s = (unsigned char *) m; - // hexdump(s, m->len); - error = usb_rawwrite(dpf->dev.udev, s, m->len); - if (error < 0) { - perror("Writing to USB"); - } - return error; + int error; + unsigned char *s = (unsigned char *) m; + // hexdump(s, m->len); + error = usb_rawwrite (dpf->dev.udev, s, m->len); + if (error < 0) + { + perror ("Writing to USB"); + } + return error; } -int spilib_process(DPFContext *h, UsbMsg *umsg, unsigned char *out) +int +spilib_process (DPFContext * h, UsbMsg * umsg, unsigned char *out) { - int error; - umsg->jmp[0] = JMP_SPILIB & 0xff; umsg->jmp[1] = JMP_SPILIB >> 8; - umsg->len = 7 + umsg->u.spi.wnum; - - validate(umsg); - error = transmit(h, umsg); - if (umsg->u.spi.rnum > 0 && error >= 0) { - error = usb_rawread(h->dev.udev, out, 64); - } - if (error < 0) perror("Reading USB"); - else error = 0; - return error; + int error; + umsg->jmp[0] = JMP_SPILIB & 0xff; + umsg->jmp[1] = JMP_SPILIB >> 8; + umsg->len = 7 + umsg->u.spi.wnum; + + validate (umsg); + error = transmit (h, umsg); + if (umsg->u.spi.rnum > 0 && error >= 0) + { + error = usb_rawread (h->dev.udev, out, 64); + } + if (error < 0) + perror ("Reading USB"); + else + error = 0; + return error; } -int go_hid(DPFContext *dpf, ADDR jmpoffset) +int +go_hid (DPFContext * dpf, ADDR jmpoffset) { - UsbMsg umsg; - umsg.jmp[0] = jmpoffset; umsg.jmp[1] = jmpoffset >> 8; - umsg.len = 8; - validate(&umsg); - return transmit(dpf, &umsg); + UsbMsg umsg; + umsg.jmp[0] = jmpoffset; + umsg.jmp[1] = jmpoffset >> 8; + umsg.len = 8; + validate (&umsg); + return transmit (dpf, &umsg); } -int load(DPFContext *dpf, FILE *f, uint16_t jmpoffset) +int +load (DPFContext * dpf, FILE * f, uint16_t jmpoffset) { - int size; - UsbMsg umsg; - - unsigned short offset = jmpoffset - 0x800; - - umsg.jmp[0] = JMP_LOAD & 0xff; umsg.jmp[1] = JMP_LOAD >> 8; - umsg.chk = 0xce; - size = fread(umsg.u.loader.buf, 1, BUFSIZE, f); - if (size < 0) return size; - - while (size > 0) { - umsg.u.loader.offset[0] = offset; - umsg.u.loader.offset[1] = offset >> 8; - umsg.len = sizeof(UsbMsg) - BUFSIZE + size; - offset += size; - validate(&umsg); - transmit(dpf, &umsg); - size = fread(umsg.u.loader.buf, 1, BUFSIZE, f); - } - - // And jump into the code: - if (jmpoffset != 0x0000) { - go_hid(dpf, jmpoffset); - } - return size; + int size; + UsbMsg umsg; + + unsigned short offset = jmpoffset - 0x800; + + umsg.jmp[0] = JMP_LOAD & 0xff; + umsg.jmp[1] = JMP_LOAD >> 8; + umsg.chk = 0xce; + size = fread (umsg.u.loader.buf, 1, BUFSIZE, f); + if (size < 0) + return size; + + while (size > 0) + { + umsg.u.loader.offset[0] = offset; + umsg.u.loader.offset[1] = offset >> 8; + umsg.len = sizeof (UsbMsg) - BUFSIZE + size; + offset += size; + validate (&umsg); + transmit (dpf, &umsg); + size = fread (umsg.u.loader.buf, 1, BUFSIZE, f); + } + + // And jump into the code: + if (jmpoffset != 0x0000) + { + go_hid (dpf, jmpoffset); + } + return size; } + /* Flash stuff, HID wrapped */ static unsigned char s_rbuf[64]; -static -int flash_probe_hid(DPFContext *h, unsigned char *id) +static int +flash_probe_hid (DPFContext * h, unsigned char *id) { - int error; - UsbMsg umsg; - FILE *f; - - // First, load spilib.bin - f = fopen("spilib.bin", "rb"); - - if (!f) { - printf("failed to open flash driver\n"); - return -1; - } - umsg.u.spi.opcode = OPCODE_SPISEL | OPCODE_SPIDES; - - error = load(h, f, 0x0000); // Load, but do not execute - fclose(f); - usleep(500000); - if (error == 0) { - umsg.u.spi.wnum = 1; - umsg.u.spi.rnum = 4; - umsg.u.spi.seq[0] = SPM_RDID; - error = spilib_process(h, &umsg, s_rbuf); - id[0] = s_rbuf[0]; id[1] = s_rbuf[1]; id[2] = s_rbuf[2]; - } - return error; + int error; + UsbMsg umsg; + FILE *f; + + // First, load spilib.bin + f = fopen ("spilib.bin", "rb"); + + if (!f) + { + printf ("failed to open flash driver\n"); + return -1; + } + umsg.u.spi.opcode = OPCODE_SPISEL | OPCODE_SPIDES; + + error = load (h, f, 0x0000); // Load, but do not execute + fclose (f); + usleep (500000); + if (error == 0) + { + umsg.u.spi.wnum = 1; + umsg.u.spi.rnum = 4; + umsg.u.spi.seq[0] = SPM_RDID; + error = spilib_process (h, &umsg, s_rbuf); + id[0] = s_rbuf[0]; + id[1] = s_rbuf[1]; + id[2] = s_rbuf[2]; + } + return error; } -static -int flash_cmd_hid(DPFContext *h, int command, int cmdlen, ADDR addr) +static int +flash_cmd_hid (DPFContext * h, int command, int cmdlen, ADDR addr) { - UsbMsg umsg; - umsg.u.spi.opcode = OPCODE_SPISEL | OPCODE_SPIDES; - umsg.u.spi.wnum = cmdlen; - umsg.u.spi.rnum = 0; - umsg.u.spi.seq[0] = command; - umsg.u.spi.seq[1] = addr >> 16; - umsg.u.spi.seq[2] = addr >> 8; - umsg.u.spi.seq[3] = addr; - - return spilib_process(h, &umsg, 0); + UsbMsg umsg; + umsg.u.spi.opcode = OPCODE_SPISEL | OPCODE_SPIDES; + umsg.u.spi.wnum = cmdlen; + umsg.u.spi.rnum = 0; + umsg.u.spi.seq[0] = command; + umsg.u.spi.seq[1] = addr >> 16; + umsg.u.spi.seq[2] = addr >> 8; + umsg.u.spi.seq[3] = addr; + + return spilib_process (h, &umsg, 0); } -int flash_status_hid(DPFHANDLE h, uint8_t *status) +int +flash_status_hid (DPFHANDLE h, uint8_t * status) { - int error; - UsbMsg umsg; - umsg.u.spi.opcode = OPCODE_SPISEL | OPCODE_SPIDES; - umsg.u.spi.wnum = 1; - umsg.u.spi.rnum = 1; - umsg.u.spi.seq[0] = SPM_RDSR; - - error = spilib_process(h, &umsg, s_rbuf); - *status = s_rbuf[0]; - return error; + int error; + UsbMsg umsg; + umsg.u.spi.opcode = OPCODE_SPISEL | OPCODE_SPIDES; + umsg.u.spi.wnum = 1; + umsg.u.spi.rnum = 1; + umsg.u.spi.seq[0] = SPM_RDSR; + + error = spilib_process (h, &umsg, s_rbuf); + *status = s_rbuf[0]; + return error; } -static -int chunk_read(DPFContext *h, unsigned char *buf, ADDR offset, int len) +static int +chunk_read (DPFContext * h, unsigned char *buf, ADDR offset, int len) { - int error; - UsbMsg umsg; + int error; + UsbMsg umsg; - if (len > PKTSIZE) len = PKTSIZE; + if (len > PKTSIZE) + len = PKTSIZE; - umsg.u.spi.opcode = OPCODE_SPISEL | OPCODE_SPIDES; - umsg.u.spi.wnum = 4; - umsg.u.spi.rnum = PKTSIZE; - umsg.u.spi.seq[0] = SPM_READ; - umsg.u.spi.seq[1] = offset >> 16; - umsg.u.spi.seq[2] = offset >> 8; - umsg.u.spi.seq[3] = offset; + umsg.u.spi.opcode = OPCODE_SPISEL | OPCODE_SPIDES; + umsg.u.spi.wnum = 4; + umsg.u.spi.rnum = PKTSIZE; + umsg.u.spi.seq[0] = SPM_READ; + umsg.u.spi.seq[1] = offset >> 16; + umsg.u.spi.seq[2] = offset >> 8; + umsg.u.spi.seq[3] = offset; - error = spilib_process(h, &umsg, buf); - if (error < 0) return error; + error = spilib_process (h, &umsg, buf); + if (error < 0) + return error; - return len; + return len; } -static -int flash_read_hid(DPFContext *h, unsigned char *buf, ADDR offset, int len) +static int +flash_read_hid (DPFContext * h, unsigned char *buf, ADDR offset, int len) { - int n; - - while (len > 0) { - n = chunk_read(h, buf, offset, len); - if (n < 0) return n; - len -= n; offset += n; buf += n; - } - return 0; + int n; + + while (len > 0) + { + n = chunk_read (h, buf, offset, len); + if (n < 0) + return n; + len -= n; + offset += n; + buf += n; + } + return 0; } -int fill_spimsg(UsbMsg *umsg, const unsigned char *buf, - unsigned short offset, int len) +int +fill_spimsg (UsbMsg * umsg, const unsigned char *buf, + unsigned short offset, int len) { - int n = PKTSIZE - offset; - if (len > n) len = n; - memcpy(&umsg->u.spi.seq[offset], buf, len); - umsg->u.spi.wnum = offset + len; - return len; + int n = PKTSIZE - offset; + if (len > n) + len = n; + memcpy (&umsg->u.spi.seq[offset], buf, len); + umsg->u.spi.wnum = offset + len; + return len; } -static -int flash_writechunk_hid(DPFContext *h, - const unsigned char *buf, ADDR offset, int len) +static int +flash_writechunk_hid (DPFContext * h, + const unsigned char *buf, ADDR offset, int len) { - UsbMsg umsg; - int error; - int n; - - if (len > PAGESIZE) len = PAGESIZE; - - umsg.u.spi.rnum = 0; - umsg.u.spi.seq[0] = SPM_PP; - umsg.u.spi.seq[1] = offset >> 16; - umsg.u.spi.seq[2] = offset >> 8; - umsg.u.spi.seq[3] = offset; - - n = fill_spimsg(&umsg, buf, 4, len); - len -= n; buf += n; offset += n; - - umsg.u.spi.opcode = OPCODE_SPISEL; - error = spilib_process(h, &umsg, 0); - if (error < 0) return error; - - umsg.u.spi.opcode = 0; - while (len > PKTSIZE) { - n = fill_spimsg(&umsg, buf, 0, PKTSIZE); - error = spilib_process(h, &umsg, 0); - if (error < 0) return error; - len -= n; buf += n; offset += n; - } - - umsg.u.spi.opcode = OPCODE_SPIDES; - fill_spimsg(&umsg, buf, 0, len); - error = spilib_process(h, &umsg, 0); - if (error < 0) return error; - - return PAGESIZE; + UsbMsg umsg; + int error; + int n; + + if (len > PAGESIZE) + len = PAGESIZE; + + umsg.u.spi.rnum = 0; + umsg.u.spi.seq[0] = SPM_PP; + umsg.u.spi.seq[1] = offset >> 16; + umsg.u.spi.seq[2] = offset >> 8; + umsg.u.spi.seq[3] = offset; + + n = fill_spimsg (&umsg, buf, 4, len); + len -= n; + buf += n; + offset += n; + + umsg.u.spi.opcode = OPCODE_SPISEL; + error = spilib_process (h, &umsg, 0); + if (error < 0) + return error; + + umsg.u.spi.opcode = 0; + while (len > PKTSIZE) + { + n = fill_spimsg (&umsg, buf, 0, PKTSIZE); + error = spilib_process (h, &umsg, 0); + if (error < 0) + return error; + len -= n; + buf += n; + offset += n; + } + + umsg.u.spi.opcode = OPCODE_SPIDES; + fill_spimsg (&umsg, buf, 0, len); + error = spilib_process (h, &umsg, 0); + if (error < 0) + return error; + + return PAGESIZE; } -int blk_write(DPFContext *h, ADDR dst, const unsigned char *src, - unsigned short len) +int +blk_write (DPFContext * h, ADDR dst, const unsigned char *src, + unsigned short len) { - static UsbMsg umsg; + static UsbMsg umsg; - if (len > BUFSIZE) len = BUFSIZE; + if (len > BUFSIZE) + len = BUFSIZE; - umsg.jmp[0] = JMP_LOAD & 0xff; umsg.jmp[1] = JMP_LOAD >> 8; - memcpy(umsg.u.loader.buf, src, len); - umsg.u.loader.offset[0] = dst; - umsg.u.loader.offset[1] = dst >> 8; - umsg.len = sizeof(UsbMsg) - BUFSIZE + len; + umsg.jmp[0] = JMP_LOAD & 0xff; + umsg.jmp[1] = JMP_LOAD >> 8; + memcpy (umsg.u.loader.buf, src, len); + umsg.u.loader.offset[0] = dst; + umsg.u.loader.offset[1] = dst >> 8; + umsg.len = sizeof (UsbMsg) - BUFSIZE + len; - validate(&umsg); - transmit(h, &umsg); - return len; + validate (&umsg); + transmit (h, &umsg); + return len; } -int mem_write_hid(DPFContext *h, - ADDR dst, const unsigned char *src, unsigned short n) +int +mem_write_hid (DPFContext * h, + ADDR dst, const unsigned char *src, unsigned short n) { - int len; - - while (n > 0) { - len = blk_write(h, dst, src, n); - n -= len; src += len; dst += len; - } - return n; + int len; + + while (n > 0) + { + len = blk_write (h, dst, src, n); + n -= len; + src += len; + dst += len; + } + return n; } -AccessMethods -hid_methods = { - .mem_read = NULL, - .mem_write = mem_write_hid, - .go = go_hid, - .bootstrap = NULL, - .flash_probe = flash_probe_hid, - .flash_cmd = flash_cmd_hid, - .flash_status = flash_status_hid, - .flash_read = flash_read_hid, - .flash_writechunk = flash_writechunk_hid, - .flash_lock = NULL, -}; +AccessMethods hid_methods = +{ +.mem_read = NULL,.mem_write = mem_write_hid,.go = go_hid,.bootstrap = + NULL,.flash_probe = flash_probe_hid,.flash_cmd = + flash_cmd_hid,.flash_status = flash_status_hid,.flash_read = + flash_read_hid,.flash_writechunk = flash_writechunk_hid,.flash_lock = + NULL,}; #ifdef TEST -int main(int argc, char **argv) +int +main (int argc, char **argv) { - FILE *f; - int error; - DPFHANDLE dpf; - uint16_t startaddr = 0x1000; - - if (argc >= 2) { - - f = fopen(argv[1], "rb"); - - if (!f) { - printf("failed to open file\n"); - return -1; - } - if (argc == 3) { - startaddr = strtol(argv[2], NULL, 16); - printf("Starting at %04x\n", startaddr); - } - - error = dpf_open("usb0", &dpf); - if (error < 0) { - printf("Failed to open DPF\n"); - return error; - } - if (dpf->mode == MODE_USBHID) { - error = load(dpf, f, startaddr); - } else { - printf("Not in BOOTLOAD mode! Press Reset and hold MENU\n"); - } - dpf_close(dpf); - } else { - printf("Needs boot image argument\n"); - } - - if (error < 0) { - printf("Error\n"); - } - return error; + FILE *f; + int error; + DPFHANDLE dpf; + uint16_t startaddr = 0x1000; + + if (argc >= 2) + { + + f = fopen (argv[1], "rb"); + + if (!f) + { + printf ("failed to open file\n"); + return -1; + } + if (argc == 3) + { + startaddr = strtol (argv[2], NULL, 16); + printf ("Starting at %04x\n", startaddr); + } + + error = dpf_open ("usb0", &dpf); + if (error < 0) + { + printf ("Failed to open DPF\n"); + return error; + } + if (dpf->mode == MODE_USBHID) + { + error = load (dpf, f, startaddr); + } + else + { + printf ("Not in BOOTLOAD mode! Press Reset and hold MENU\n"); + } + dpf_close (dpf); + } + else + { + printf ("Needs boot image argument\n"); + } + + if (error < 0) + { + printf ("Error\n"); + } + return error; } #endif |