diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 6 | ||||
-rw-r--r-- | src/boot.c | 112 | ||||
-rw-r--r-- | src/boot.h | 43 | ||||
-rw-r--r-- | src/omap-usb-boot.c | 308 | ||||
-rw-r--r-- | src/omap-usb-boot.h | 61 | ||||
-rw-r--r-- | src/omap3.c | 77 | ||||
-rw-r--r-- | src/omap3.h | 51 | ||||
-rw-r--r-- | src/omap4.c | 79 | ||||
-rw-r--r-- | src/omap4.h | 66 | ||||
-rw-r--r-- | src/omap5.c | 79 | ||||
-rw-r--r-- | src/omap5.h | 64 | ||||
-rw-r--r-- | src/usb.c | 239 | ||||
-rw-r--r-- | src/usb.h | 61 |
13 files changed, 1246 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..07c901e --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,6 @@ +bin_PROGRAMS = omap-usb-boot + +omap_usb_boot_SOURCES = omap-usb-boot.c omap-usb-boot.h omap3.c omap3.h \ + omap4.c omap4.h omap5.c omap5.h boot.c boot.h usb.c usb.h + +MAINTAINERCLEANFILES = Makefile.in diff --git a/src/boot.c b/src/boot.c new file mode 100644 index 0000000..9181d5e --- /dev/null +++ b/src/boot.c @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2016 Paul Kocialkowski <contact@paulk.fr> + * + * 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 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> + +#include "omap-usb-boot.h" +#include "boot.h" +#include "usb.h" + +int boot_peripheral(struct context *context, size_t length) +{ + uint32_t command; + int rc; + + if (context == NULL) + return -1; + + command = htole32(BOOT_PERIPHERAL); + + rc = usb_send(context, &command, sizeof(command)); + if (rc < 0) + return -1; + + command = htole32((uint32_t) length); + + rc = usb_send(context, &command, sizeof(command)); + if (rc < 0) + return -1; + + return 0; +} + +int boot_asic_id(struct context *context) +{ + int rc; + + if (context == NULL || context->description == NULL) + return -1; + + if (context->description->boot_asic_id != NULL) { + rc = context->description->boot_asic_id(context); + if (rc < 0) + return -1; + } + + return 0; +} + +int boot_device(struct context *context, uint8_t value) +{ + uint32_t command; + int rc; + + if (context == NULL) + return -1; + + command = htole32(BOOT_DEVICE | (value << 8)); + + rc = usb_send(context, &command, sizeof(command)); + if (rc < 0) + return -1; + + return 0; +} + +int boot_next(struct context *context) +{ + uint32_t command; + int rc; + + if (context == NULL) + return -1; + + command = htole32(BOOT_NEXT); + + rc = usb_send(context, &command, sizeof(command)); + if (rc < 0) + return -1; + + return 0; +} + +int boot_memory(struct context *context) +{ + uint32_t command; + int rc; + + if (context == NULL) + return -1; + + command = htole32(BOOT_MEMORY); + + rc = usb_send(context, &command, sizeof(command)); + if (rc < 0) + return -1; + + return 0; +} diff --git a/src/boot.h b/src/boot.h new file mode 100644 index 0000000..4fba848 --- /dev/null +++ b/src/boot.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2016 Paul Kocialkowski <contact@paulk.fr> + * + * 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 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _BOOT_H_ +#define _BOOT_H_ + +#include "omap-usb-boot.h" + +/* + * Values + */ + +#define BOOT_PERIPHERAL 0xf0030002 +#define BOOT_ASIC_ID 0xf0030003 +#define BOOT_DEVICE 0xf0030006 +#define BOOT_NEXT 0xffffffff +#define BOOT_MEMORY 0xdeadbeef + +/* + * Functions + */ + +int boot_peripheral(struct context *context, size_t length); +int boot_asic_id(struct context *context); +int boot_device(struct context *context, uint8_t value); +int boot_next(struct context *context); +int boot_memory(struct context *context); + +#endif diff --git a/src/omap-usb-boot.c b/src/omap-usb-boot.c new file mode 100644 index 0000000..ad49b02 --- /dev/null +++ b/src/omap-usb-boot.c @@ -0,0 +1,308 @@ +/* + * Copyright (C) 2016 Paul Kocialkowski <contact@paulk.fr> + * + * 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 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include "omap-usb-boot.h" +#include "boot.h" +#include "omap3.h" +#include "omap4.h" +#include "omap5.h" +#include "usb.h" + +static struct omap_description *omap_descriptions[] = { + &omap3_description, + &omap4_description, + &omap5_description +}; + +static size_t omap_descriptions_count = sizeof(omap_descriptions) / sizeof(struct omap_description *); + +static int usage_print(void) +{ + size_t i; + size_t j; + + printf("Usage: omap-usb-boot [OPTIONS] [OPERATION]\n\n" + "Options:\n" + " -h help\n" + " -v verbose\n" + " -w wait for device\n\n" + "Operations:\n" + " next skip to the next booting device\n" + " memory skip to the first memory booting device\n" + " boot [device] boot from device\n" + " load [filename] load and execute a file\n\n" + "Devices:\n"); + + for (i = 0; i < omap_descriptions_count; i++) { + printf(" %s: ", omap_descriptions[i]->name); + + for (j = 0; j < omap_descriptions[i]->boot_devices_count; j++) + printf("%s%c", omap_descriptions[i]->boot_devices[j].name, (j == (omap_descriptions[i]->boot_devices_count - 1)) ? '\n' : ' '); + } +} + +static int arguments_parse(struct context *context, int argc, char *argv[]) +{ + int i; + + if (context == NULL || argc < 2) + return -1; + + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "next") == 0) { + if (context->operation) + return -1; + + context->operation = 'n'; + } else if (strcmp(argv[i], "memory") == 0) { + if (context->operation) + return -1; + + context->operation = 'm'; + } else if (strcmp(argv[i], "boot") == 0) { + if (context->operation || argc <= i) + return -1; + + context->operation = 'b'; + context->device = argv[++i]; + } else if (strcmp(argv[i], "load") == 0) { + if (context->operation || argc <= i) + return -1; + + context->operation = 'l'; + context->filename = argv[++i]; + } else if (strcmp(argv[i], "-h") == 0) { + if (context->operation) + return -1; + + context->operation = 'h'; + } else if (strcmp(argv[i], "-v") == 0) { + context->verbose = 1; + } else if (strcmp(argv[i], "-w") == 0) { + context->wait = 1; + } else { + return -1; + } + } + + if (!context->operation) + return -1; + + return 0; +} + +static int boot(struct context *context) +{ + uint8_t value; + size_t i; + int rc; + + if (context == NULL || context->description == NULL || context->device == NULL) + return -1; + + for (i = 0; i < context->description->boot_devices_count; i++) { + if (strcmp(context->description->boot_devices[i].name, context->device) == 0) { + value = context->description->boot_devices[i].value; + break; + } + } + + if (i == context->description->boot_devices_count) { + fprintf(stderr, "Booting device %s not found\n", context->device); + return -1; + } + + rc = boot_device(context, value); + if (rc < 0) + return -1; + + return 0; +} + +static int load(struct context *context) +{ + void *buffer = NULL; + size_t length; + size_t count; + size_t chunk; + uint8_t *p; + size_t i; + struct stat st; + int fd = -1; + int rc; + + if (context == NULL || context->filename == NULL) + return -1; + + rc = stat(context->filename, &st); + if (rc < 0) { + fprintf(stderr, "Stating file failed\n"); + goto error; + } + + length = st.st_size; + + fd = open(context->filename, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "Opening file failed\n"); + goto error; + } + + if (context->verbose) + printf("Loading data with length %d bytes\n", (int) length); + + buffer = calloc(1, USB_SEND_CHUNK); + + rc = boot_peripheral(context, length); + if (rc < 0) + goto error; + + count = 0; + + while (count < length) { + chunk = (length - count) < USB_SEND_CHUNK ? (length - count) : USB_SEND_CHUNK; + + p = (uint8_t *) buffer; + i = 0; + + while (i < chunk) { + rc = read(fd, p, chunk - i); + if (rc <= 0) + goto error; + + i += rc; + p += rc; + } + + rc = usb_send(context, buffer, chunk); + if (rc < 0) + goto error; + + count += chunk; + } + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + if (buffer != NULL) + free(buffer); + + if (fd >= 0) + close(fd); + + return rc; +} + +int main(int argc, char *argv[]) +{ + struct context context = { 0 }; + int rc; + + rc = arguments_parse(&context, argc, argv); + if (rc < 0) { + usage_print(); + return -1; + } + + if (context.operation == 'h') { + usage_print(); + return 0; + } + + printf("Finding and opening USB device\n"); + + rc = usb_open(&context, omap_descriptions, omap_descriptions_count); + if (rc < 0) + goto error; + + rc = boot_asic_id(&context); + if (rc < 0) { + fprintf(stderr, "Getting ASIC ID failed\n"); + return -1; + } + + switch (context.operation) { + case 'n': + printf("Skipping to next booting device...\n"); + + rc = boot_next(&context); + if (rc < 0) { + fprintf(stderr, "Skipping to next booting device failed\n"); + return -1; + } + + break; + case 'm': + printf("Skipping to next memory booting device...\n"); + + rc = boot_memory(&context); + if (rc < 0) { + fprintf(stderr, "Skipping to next memory booting device failed\n"); + return -1; + } + + break; + case 'b': + printf("Booting from device %s...\n", context.device); + + rc = boot(&context); + if (rc < 0) { + fprintf(stderr, "Booting from device failed\n"); + goto error; + } + + break; + case 'l': + printf("Loading and executing %s...\n", context.filename); + + rc = load(&context); + if (rc < 0) { + fprintf(stderr, "Loading and executing failed\n"); + goto error; + } + + break; + default: + goto error; + } + + printf("Done!\n"); + + rc = 0; + goto complete; + +error: + rc = 1; + +complete: + usb_close(&context); + + return rc; +} diff --git a/src/omap-usb-boot.h b/src/omap-usb-boot.h new file mode 100644 index 0000000..700a8ce --- /dev/null +++ b/src/omap-usb-boot.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2016 Paul Kocialkowski <contact@paulk.fr> + * + * 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 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _OMAP_USB_LOADER_H_ +#define _OMAP_USB_LOADER_H_ + +#include <stdint.h> +#include <sys/types.h> +#include <libusb.h> + +/* + * Structures + */ + +struct usb_device_id; +struct context; + +struct omap_boot_device { + char *name; + uint8_t value; +}; + +struct omap_description { + char *name; + + struct usb_device_id *usb_device_ids; + size_t usb_device_ids_count; + + struct omap_boot_device *boot_devices; + size_t boot_devices_count; + + int (*boot_asic_id)(struct context *context); +}; + +struct context { + struct libusb_device_handle *usb_handle; + int verbose; + int wait; + char operation; + + char *device; + char *filename; + + struct omap_description *description; +}; + +#endif diff --git a/src/omap3.c b/src/omap3.c new file mode 100644 index 0000000..98e3855 --- /dev/null +++ b/src/omap3.c @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2016 Paul Kocialkowski <contact@paulk.fr> + * + * 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 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <endian.h> + +#include "omap-usb-boot.h" +#include "boot.h" +#include "usb.h" +#include "omap3.h" + +struct usb_device_id omap3_usb_device_ids[] = { + { USB_VENDOR_TI, USB_DEVICE_OMAP34XX }, + { USB_VENDOR_TI, USB_DEVICE_OMAP36XX } +}; + +struct omap_boot_device omap3_boot_devices[] = { + { "void", 0x00 }, + { "xip", 0x01 }, + { "nand", 0x02 }, + { "onenand", 0x03 }, + { "doc", 0x04 }, + { "mmc2", 0x05 }, + { "mmc1", 0x06 }, + { "xipwait", 0x07 }, + { "mmc2hybrid", 0x08 }, + { "uart", 0x10 }, + { "usb", 0x11 } +}; + +int omap3_boot_asic_id(struct context *context) +{ + struct omap3_asic_id asic_id; + uint32_t command; + int rc; + + if (context == NULL) + return -1; + + rc = usb_recv(context, &asic_id, sizeof(asic_id)); + if (rc < 0) { + command = htole32(BOOT_ASIC_ID); + + rc = usb_send(context, &command, sizeof(command)); + if (rc < 0) + return -1; + + rc = usb_recv(context, &asic_id, sizeof(asic_id)); + if (rc < 0) + return -1; + } + + return 0; +} + +struct omap_description omap3_description = { + .name = "omap3", + .usb_device_ids = omap3_usb_device_ids, + .usb_device_ids_count = sizeof(omap3_usb_device_ids) / sizeof(struct usb_device_id), + .boot_devices = omap3_boot_devices, + .boot_devices_count = sizeof(omap3_boot_devices) / sizeof(struct omap_boot_device), + .boot_asic_id = omap3_boot_asic_id +}; diff --git a/src/omap3.h b/src/omap3.h new file mode 100644 index 0000000..219822a --- /dev/null +++ b/src/omap3.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2016 Paul Kocialkowski <contact@paulk.fr> + * + * 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 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _OMAP3_H_ +#define _OMAP3_H_ + +#include <stdint.h> + +#include "omap-usb-boot.h" + +/* + * Values + */ + +#define USB_DEVICE_OMAP34XX 0xd009 +#define USB_DEVICE_OMAP36XX 0xd00e + +/* + * Structures + */ + +struct omap3_asic_id { + uint8_t count; + uint8_t device_id[7]; + uint32_t reserved; + uint8_t id[23]; + uint8_t reserved_id[23]; + uint8_t crc[11]; +} __attribute__((__packed__)); + +/* + * Globals + */ + +extern struct omap_description omap3_description; + +#endif diff --git a/src/omap4.c b/src/omap4.c new file mode 100644 index 0000000..629bb3a --- /dev/null +++ b/src/omap4.c @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2016 Paul Kocialkowski <contact@paulk.fr> + * + * 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 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <endian.h> + +#include "omap-usb-boot.h" +#include "boot.h" +#include "usb.h" +#include "omap4.h" + +struct usb_device_id omap4_usb_device_ids[] = { + { USB_VENDOR_TI, USB_DEVICE_OMAP4430 }, + { USB_VENDOR_TI, USB_DEVICE_OMAP4460 } +}; + +struct omap_boot_device omap4_boot_devices[] = { + { "void", 0x00 }, + { "xip", 0x01 }, + { "xipwait", 0x02 }, + { "nand", 0x03 }, + { "onenand", 0x04 }, + { "mmc1", 0x05 }, + { "mmc2(1)", 0x06 }, + { "mmc2(2)", 0x07 }, + { "uart", 0x43 }, + { "usb1", 0x45 }, + { "usbulpi", 0x46 }, + { "usb2", 0x47 } +}; + +int omap4_boot_asic_id(struct context *context) +{ + struct omap4_asic_id asic_id; + uint32_t command; + int rc; + + if (context == NULL) + return -1; + + command = htole32(BOOT_ASIC_ID); + + rc = usb_send(context, &command, sizeof(command)); + if (rc < 0) + return -1; + + rc = usb_recv(context, &asic_id, sizeof(asic_id)); + if (rc < 0) + return -1; + + if (context->verbose) + printf("ASIC device id: %04x, %s device\n", be16toh(asic_id.device_id.device), asic_id.crc.gp_blank == 0 ? "GP" : "HS"); + + return 0; +} + +struct omap_description omap4_description = { + .name = "omap4", + .usb_device_ids = omap4_usb_device_ids, + .usb_device_ids_count = sizeof(omap4_usb_device_ids) / sizeof(struct usb_device_id), + .boot_devices = omap4_boot_devices, + .boot_devices_count = sizeof(omap4_boot_devices) / sizeof(struct omap_boot_device), + .boot_asic_id = omap4_boot_asic_id +}; diff --git a/src/omap4.h b/src/omap4.h new file mode 100644 index 0000000..070fc40 --- /dev/null +++ b/src/omap4.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2016 Paul Kocialkowski <contact@paulk.fr> + * + * 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 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _OMAP4_H_ +#define _OMAP4_H_ + +#include <stdint.h> + +#include "omap-usb-boot.h" + +/* + * Values + */ + +#define USB_DEVICE_OMAP4430 0xd00f +#define USB_DEVICE_OMAP4460 0xd010 + +/* + * Structures + */ + +struct omap4_asic_id_device_id { + uint8_t subblock_id; + uint8_t subblock_size; + uint8_t fixed; + uint16_t device; + uint8_t ch; + uint8_t rom_revision; +} __attribute__((__packed__)); + +struct omap4_asic_id_crc { + uint8_t subblock_id; + uint8_t subblock_size; + uint8_t fixed; + uint32_t crc; + uint32_t gp_blank; +} __attribute__((__packed__)); + +struct omap4_asic_id { + uint8_t count; + struct omap4_asic_id_device_id device_id; + uint8_t reserved[62]; + struct omap4_asic_id_crc crc; +} __attribute__((__packed__)); + +/* + * Globals + */ + +extern struct omap_description omap4_description; + +#endif diff --git a/src/omap5.c b/src/omap5.c new file mode 100644 index 0000000..1879c35 --- /dev/null +++ b/src/omap5.c @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2016 Paul Kocialkowski <contact@paulk.fr> + * + * 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 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <endian.h> + +#include "omap-usb-boot.h" +#include "boot.h" +#include "usb.h" +#include "omap5.h" + +struct usb_device_id omap5_usb_device_ids[] = { + { USB_VENDOR_TI, USB_DEVICE_OMAP5430 }, + { USB_VENDOR_TI, USB_DEVICE_AM572X } +}; + +struct omap_boot_device omap5_boot_devices[] = { + { "xip", 0x01 }, + { "xipwait", 0x02 }, + { "nand", 0x03 }, + { "onenand", 0x04 }, + { "sdcard", 0x05 }, + { "emmcboot", 0x06 }, + { "emmc", 0x07 }, + { "sata", 0x09 }, + { "qspi1", 0x0a }, + { "qspi4", 0x0b }, + { "uart", 0x43 }, + { "usb", 0x45 } +}; + +int omap5_boot_asic_id(struct context *context) +{ + struct omap5_asic_id asic_id; + uint32_t command; + int rc; + + if (context == NULL) + return -1; + + command = htole32(BOOT_ASIC_ID); + + rc = usb_send(context, &command, sizeof(command)); + if (rc < 0) + return -1; + + rc = usb_recv(context, &asic_id, sizeof(asic_id)); + if (rc < 0) + return -1; + + if (context->verbose) + printf("ASIC device id: %04x, %s device\n", be16toh(asic_id.device_id.device), asic_id.crc.gp_blank == 0 ? "GP" : "HS"); + + return 0; +} + +struct omap_description omap5_description = { + .name = "omap5", + .usb_device_ids = omap5_usb_device_ids, + .usb_device_ids_count = sizeof(omap5_usb_device_ids) / sizeof(struct usb_device_id), + .boot_devices = omap5_boot_devices, + .boot_devices_count = sizeof(omap5_boot_devices) / sizeof(struct omap_boot_device), + .boot_asic_id = omap5_boot_asic_id +}; diff --git a/src/omap5.h b/src/omap5.h new file mode 100644 index 0000000..498ea18 --- /dev/null +++ b/src/omap5.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2016 Paul Kocialkowski <contact@paulk.fr> + * + * 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 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _OMAP5_H_ +#define _OMAP5_H_ + +#include "omap-usb-boot.h" + +/* + * Values + */ + +#define USB_DEVICE_OMAP5430 0xd011 +#define USB_DEVICE_AM572X 0xd013 + +/* + * Structures + */ + +struct omap5_asic_id_device_id { + uint8_t subblock_id; + uint8_t subblock_size; + uint8_t fixed; + uint16_t device; + uint8_t ch; + uint8_t rom_revision; +} __attribute__((__packed__)); + +struct omap5_asic_id_crc { + uint8_t subblock_id; + uint8_t subblock_size; + uint8_t fixed; + uint32_t crc; + uint32_t gp_blank; +} __attribute__((__packed__)); + +struct omap5_asic_id { + uint8_t count; + struct omap5_asic_id_device_id device_id; + uint8_t reserved[62]; + struct omap5_asic_id_crc crc; +} __attribute__((__packed__)); + +/* + * Globals + */ + +extern struct omap_description omap5_description; + +#endif diff --git a/src/usb.c b/src/usb.c new file mode 100644 index 0000000..747d80c --- /dev/null +++ b/src/usb.c @@ -0,0 +1,239 @@ +/* + * Copyright (C) 2016 Paul Kocialkowski <contact@paulk.fr> + * + * 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 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <stdint.h> +#include <unistd.h> +#include <sys/types.h> +#include <libusb.h> + +#include "omap-usb-boot.h" +#include "usb.h" + +int usb_open(struct context *context, struct omap_description **descriptions, size_t descriptions_count) +{ + struct libusb_device **list = NULL; + struct libusb_device_handle *handle = NULL; + struct libusb_device_descriptor descriptor; + int configuration; + char device_name[32]; + size_t count; + size_t i; + size_t j; + size_t k; + int rc; + + if (context == NULL) + return -1; + + rc = libusb_init(NULL); + if (rc < 0) { + fprintf(stderr, "Initializing USB failed\n"); + return -1; + } + + do { + rc = libusb_get_device_list(NULL, &list); + if (rc < 0) { + fprintf(stderr, "Getting USB device list failed\n"); + goto error; + } + + count = (size_t) rc; + + for (i = 0; i < count; i++) { + rc = libusb_get_device_descriptor(list[i], &descriptor); + if (rc < 0) { + fprintf(stderr, "Getting USB device descriptor failed\n"); + goto error; + } + + for (j = 0; j < descriptions_count; j++) { + for (k = 0; k < descriptions[j]->usb_device_ids_count; k++) { + if (descriptions[j]->usb_device_ids[k].vendor_id == descriptor.idVendor && descriptions[j]->usb_device_ids[k].product_id == descriptor.idProduct) { + rc = libusb_open(list[i], &handle); + if (rc < 0) { + fprintf(stderr, "Opening USB device failed\n"); + fprintf(stderr, "\nYou may not have the rights to do this\n"); + goto error; + } + + rc = libusb_get_string_descriptor_ascii(handle, descriptor.iProduct, device_name, sizeof(device_name)); + if (rc < 0) { + fprintf(stderr, "Getting USB product string descriptor failed\n"); + goto error; + } + + if (context->verbose) + printf("Found and opened %s USB device: %s\n", descriptions[j]->name, device_name); + + context->description = descriptions[j]; + + goto usb_configure; + } + } + } + } + + usleep(300000); + } while (context->wait); + +usb_configure: + if (handle == NULL) { + fprintf(stderr, "Finding USB device failed\n"); + goto error; + } + + libusb_free_device_list(list, 1); + list = NULL; + + rc = libusb_get_configuration(handle, &configuration); + if (rc < 0) { + fprintf(stderr, "Getting USB configuration failed\n"); + goto error; + } + + if (configuration != USB_CONFIGURATION) { + rc = libusb_set_configuration(handle, USB_CONFIGURATION); + if (rc < 0) { + fprintf(stderr, "Setting USB configuration failed\n"); + goto error; + } + } + + rc = libusb_claim_interface(handle, USB_INTERFACE); + if (rc < 0) { + fprintf(stderr, "Claiming USB interface failed\n"); + goto error; + } + + context->usb_handle = handle; + + rc = 0; + goto complete; + +error: + rc = -1; + + if (list != NULL) + libusb_free_device_list(list, 1); + + if (handle != NULL) + libusb_close(handle); + + libusb_exit(NULL); + +complete: + return rc; +} + +void usb_close(struct context *context) +{ + if (context == NULL) + return; + + if (context->usb_handle != NULL) { + libusb_release_interface(context->usb_handle, USB_INTERFACE); + libusb_close(context->usb_handle); + + context->usb_handle = NULL; + + libusb_exit(NULL); + } +} + +int usb_send(struct context *context, const void *data, size_t size) +{ + size_t count; + size_t chunk; + uint8_t *p; + int transferred; + int rc; + + if (context == NULL) + return -1; + + count = 0; + p = (uint8_t *) data; + + while (count < size) { + chunk = (size - count) < USB_SEND_CHUNK ? (size - count) : USB_SEND_CHUNK; + + rc = libusb_bulk_transfer(context->usb_handle, USB_ENDPOINT_OUT, p, chunk, &transferred, USB_TIMEOUT); + if (rc < 0 || transferred <= 0) { + fprintf(stderr, "Bulk USB transfer failed\n"); + return -1; + } + + count += transferred; + p += transferred; + } + + return 0; +} + +int usb_recv(struct context *context, void *data, size_t size) +{ + size_t count; + size_t chunk; + uint8_t *p; + int transferred; + int rc; + + if (context == NULL) + return -1; + + count = 0; + p = (uint8_t *) data; + + while (count < size) { + chunk = (size - count) < USB_RECV_CHUNK ? (size - count) : USB_RECV_CHUNK; + + rc = libusb_bulk_transfer(context->usb_handle, USB_ENDPOINT_IN, p, chunk, &transferred, USB_TIMEOUT); + if (rc < 0 || transferred <= 0) { + fprintf(stderr, "Bulk USB transfer failed\n"); + return -1; + } + + count += transferred; + p += transferred; + } + + return 0; +} + +int usb_recv_available(struct context *context, void *data, size_t size) +{ + size_t chunk; + int transferred; + int rc; + + if (context == NULL) + return -1; + + chunk = size < USB_RECV_CHUNK ? size : USB_RECV_CHUNK; + + rc = libusb_bulk_transfer(context->usb_handle, USB_ENDPOINT_IN, data, chunk, &transferred, USB_TIMEOUT); +printf("%d %d\n", rc, transferred); + if (rc < 0 || transferred <= 0) { + fprintf(stderr, "Bulk USB transfer failed\n"); + return -1; + } + + return transferred; +} diff --git a/src/usb.h b/src/usb.h new file mode 100644 index 0000000..48be159 --- /dev/null +++ b/src/usb.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2016 Paul Kocialkowski <contact@paulk.fr> + * + * 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 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _USB_H_ +#define _USB_H_ + +#include <stdint.h> +#include <sys/types.h> + +#include "omap-usb-boot.h" + +/* + * Values + */ + +#define USB_VENDOR_TI 0x0451 + +#define USB_CONFIGURATION 1 +#define USB_INTERFACE 0 + +#define USB_ENDPOINT_OUT 0x01 +#define USB_ENDPOINT_IN 0x81 + +#define USB_TIMEOUT 100 +#define USB_SEND_CHUNK 512 +#define USB_RECV_CHUNK 512 + +/* + * Structures + */ + +struct usb_device_id { + uint16_t vendor_id; + uint16_t product_id; +}; + +/* + * Functions + */ + +int usb_open(struct context *context, struct omap_description **descriptions, size_t descriptions_count); +void usb_close(struct context *context); +int usb_send(struct context *context, const void *data, size_t size); +int usb_recv(struct context *context, void *data, size_t size); +int usb_recv_available(struct context *context, void *data, size_t size); + +#endif |