aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Kocialkowski2016-02-23 23:06:07 +0100
committerPaul Kocialkowski2016-02-24 11:22:04 +0100
commit15ea4dcaecdf2e65a79d78a3fd4fd500addfc7cc (patch)
tree8e444f793402ce42f269e1c436e36659fbb6b8d9 /src
omap-usb-boot: Tool to communicate with OMAP devices bootroms via USB
Signed-off-by: Paul Kocialkowski <contact@paulk.fr>
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am6
-rw-r--r--src/boot.c112
-rw-r--r--src/boot.h43
-rw-r--r--src/omap-usb-boot.c308
-rw-r--r--src/omap-usb-boot.h61
-rw-r--r--src/omap3.c77
-rw-r--r--src/omap3.h51
-rw-r--r--src/omap4.c79
-rw-r--r--src/omap4.h66
-rw-r--r--src/omap5.c79
-rw-r--r--src/omap5.h64
-rw-r--r--src/usb.c239
-rw-r--r--src/usb.h61
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