pax_global_header00006660000000000000000000000064116603751250014520gustar00rootroot0000000000000052 comment=27d77171a1b9f0caa60bd8aa310381bacaadf054 linaro-boot-utils-0.1/000077500000000000000000000000001166037512500147435ustar00rootroot00000000000000linaro-boot-utils-0.1/.gitignore000066400000000000000000000000151166037512500167270ustar00rootroot00000000000000local.mk out linaro-boot-utils-0.1/Makefile000066400000000000000000000005471166037512500164110ustar00rootroot00000000000000CFLAGS = -g -O2 -Wall prog = usbboot all: $(prog) install: all install -d $(DESTDIR)/usr/bin install $(prog) $(DESTDIR)/usr/bin %.o: %.c $(CC) $(CFLAGS) -c $< -o $@ -MD -MT $@ -MF $(@:%o=%d) objs = usbboot.o usb_linux.o $(prog): $(objs) $(CC) $(CFLAGS) -o $@ $(objs) clean: rm -rf $(prog) $(objs) $(deps) deps = $(objs:%o=%d) -include $(deps) linaro-boot-utils-0.1/usb.h000066400000000000000000000042411166037512500157060ustar00rootroot00000000000000/* * Copyright (C) 2008 The Android Open Source Project * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef _USB_H_ #define _USB_H_ typedef struct usb_handle usb_handle; typedef struct usb_ifc_info usb_ifc_info; struct usb_ifc_info { /* from device descriptor */ unsigned short dev_vendor; unsigned short dev_product; unsigned char dev_class; unsigned char dev_subclass; unsigned char dev_protocol; unsigned char ifc_class; unsigned char ifc_subclass; unsigned char ifc_protocol; unsigned char has_bulk_in; unsigned char has_bulk_out; unsigned char writable; char serial_number[256]; }; typedef int (*ifc_match_func)(usb_ifc_info *ifc); usb_handle *usb_open(ifc_match_func callback); int usb_close(usb_handle *h); int usb_read(usb_handle *h, void *_data, int len); int usb_write(usb_handle *h, const void *_data, int len); #endif linaro-boot-utils-0.1/usb_linux.c000066400000000000000000000172161166037512500171260ustar00rootroot00000000000000/* * Copyright (C) 2008 The Android Open Source Project * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "usb.h" #define MAX_RETRIES 5 /*#define TRACE_USB*/ #ifdef TRACE_USB #define DBG(x...) fprintf(stderr, x) #else #define DBG(x...) #endif struct usb_handle { char fname[64]; int desc; unsigned char ep_in; unsigned char ep_out; }; static inline int badname(const char *name) { while (*name) { if (!isdigit(*name++)) return 1; } return 0; } static int check(void *_desc, int len, unsigned type, int size) { unsigned char *desc = _desc; if (len < size) return -1; if (desc[0] < size) return -1; if (desc[0] > len) return -1; if (desc[1] != type) return -1; return 0; } static int filter_usb_device(int fd, char *ptr, int len, int writable, ifc_match_func callback, int *ept_in_id, int *ept_out_id, int *ifc_id) { struct usb_device_descriptor *dev; struct usb_config_descriptor *cfg; struct usb_interface_descriptor *ifc; struct usb_endpoint_descriptor *ept; struct usb_ifc_info info; int in, out; unsigned i; unsigned e; if (check(ptr, len, USB_DT_DEVICE, USB_DT_DEVICE_SIZE)) return -1; dev = (void *)ptr; len -= dev->bLength; ptr += dev->bLength; if (check(ptr, len, USB_DT_CONFIG, USB_DT_CONFIG_SIZE)) return -1; cfg = (void *)ptr; len -= cfg->bLength; ptr += cfg->bLength; info.dev_vendor = dev->idVendor; info.dev_product = dev->idProduct; info.dev_class = dev->bDeviceClass; info.dev_subclass = dev->bDeviceSubClass; info.dev_protocol = dev->bDeviceProtocol; info.writable = writable; for (i = 0; i < cfg->bNumInterfaces; i++) { if (check(ptr, len, USB_DT_INTERFACE, USB_DT_INTERFACE_SIZE)) return -1; ifc = (void *)ptr; len -= ifc->bLength; ptr += ifc->bLength; in = -1; out = -1; info.ifc_class = ifc->bInterfaceClass; info.ifc_subclass = ifc->bInterfaceSubClass; info.ifc_protocol = ifc->bInterfaceProtocol; for (e = 0; e < ifc->bNumEndpoints; e++) { if (check (ptr, len, USB_DT_ENDPOINT, USB_DT_ENDPOINT_SIZE)) return -1; ept = (void *)ptr; len -= ept->bLength; ptr += ept->bLength; if ((ept->bmAttributes & 0x03) != 0x02) continue; if (ept->bEndpointAddress & 0x80) { in = ept->bEndpointAddress; } else { out = ept->bEndpointAddress; } } info.has_bulk_in = (in != -1); info.has_bulk_out = (out != -1); if (callback(&info) == 0) { *ept_in_id = in; *ept_out_id = out; *ifc_id = ifc->bInterfaceNumber; return 0; } } return -1; } static void scanning(char *str) { #ifdef TRACE_USB DBG("scanning %s\n", str); #else fprintf(stdout, "scanning %24s\r", str); #endif } static usb_handle *find_usb_device(const char *base, ifc_match_func callback) { usb_handle *usb = 0; char busname[64], devname[64]; char desc[1024]; int n, in, out, ifc; DIR *busdir, *devdir; struct dirent *de; int fd; int writable; busdir = opendir(base); if (busdir == 0) return 0; while ((de = readdir(busdir)) && (usb == 0)) { if (badname(de->d_name)) continue; sprintf(busname, "%s/%s", base, de->d_name); devdir = opendir(busname); if (devdir == 0) continue; scanning(busname); while ((de = readdir(devdir)) && (usb == 0)) { if (badname(de->d_name)) continue; sprintf(devname, "%s/%s", busname, de->d_name); scanning(devname); writable = 1; if ((fd = open(devname, O_RDWR)) < 0) { /* * TODO: Check if we have read-only access, so we * can give a helpful diagnostic like "adb devices" does. */ writable = 0; if ((fd = open(devname, O_RDONLY)) < 0) { continue; } } n = read(fd, desc, sizeof(desc)); if (filter_usb_device(fd, desc, n, writable, callback, &in, &out, &ifc) == 0) { usb = calloc(1, sizeof(usb_handle)); strcpy(usb->fname, devname); usb->ep_in = in; usb->ep_out = out; usb->desc = fd; n = ioctl(fd, USBDEVFS_CLAIMINTERFACE, &ifc); if (n != 0) { close(fd); free(usb); usb = 0; continue; } } else { close(fd); } } closedir(devdir); } closedir(busdir); #ifndef TRACE_USB if (usb) fprintf(stdout, "\n"); #endif return usb; } int usb_write(usb_handle * h, const void *_data, int len) { unsigned char *data = (unsigned char *)_data; unsigned count = 0; struct usbdevfs_bulktransfer bulk; int n; if (h->ep_out == 0) { return -1; } if (len == 0) { bulk.ep = h->ep_out; bulk.len = 0; bulk.data = data; bulk.timeout = 0; n = ioctl(h->desc, USBDEVFS_BULK, &bulk); if (n != 0) { fprintf(stderr, "ERROR: n = %d, errno = %d (%s)\n", n, errno, strerror(errno)); return -1; } return 0; } while (len > 0) { int xfer; xfer = (len > 4096) ? 4096 : len; bulk.ep = h->ep_out; bulk.len = xfer; bulk.data = data; bulk.timeout = 0; n = ioctl(h->desc, USBDEVFS_BULK, &bulk); if (n != xfer) { DBG("ERROR: n = %d, errno = %d (%s)\n", n, errno, strerror(errno)); return -1; } count += xfer; len -= xfer; data += xfer; } return count; } int usb_read(usb_handle * h, void *_data, int len) { unsigned char *data = (unsigned char *)_data; unsigned count = 0; struct usbdevfs_bulktransfer bulk; int n, retry; if (h->ep_in == 0) { return -1; } while (len > 0) { int xfer = (len > 4096) ? 4096 : len; bulk.ep = h->ep_in; bulk.len = xfer; bulk.data = data; bulk.timeout = 0; retry = 0; do { DBG("[ usb read %d fd = %d], fname=%s\n", xfer, h->desc, h->fname); n = ioctl(h->desc, USBDEVFS_BULK, &bulk); DBG("[ usb read %d ] = %d, fname=%s, Retry %d \n", xfer, n, h->fname, retry); if (n < 0) { DBG("ERROR: n = %d, errno = %d (%s)\n", n, errno, strerror(errno)); if (++retry > MAX_RETRIES) return -1; sleep(1); } } while (n < 0); count += n; len -= n; data += n; if (n < xfer) { break; } } return count; } int usb_close(usb_handle * h) { int fd; fd = h->desc; h->desc = -1; if (fd >= 0) { close(fd); DBG("[ usb closed %d ]\n", fd); } return 0; } usb_handle *usb_open(ifc_match_func callback) { return find_usb_device("/dev/bus/usb", callback); } linaro-boot-utils-0.1/usbboot.c000066400000000000000000000127651166037512500165770ustar00rootroot00000000000000/* * Copyright (C) 2010 The Android Open Source Project * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "usb.h" int usb_boot(usb_handle * usb, void *data1, unsigned sz1, void *data2, unsigned sz2) { if (data1) { uint32_t msg_boot = 0xF0030002; uint32_t msg_getid = 0xF0030003; uint32_t msg_size = sz1; uint8_t id[81]; int i; #define OFF_CHIP 0x04 #define OFF_ID 0x0F #define OFF_MPKH 0x26 memset(id, 0xee, 81); fprintf(stderr, "reading ASIC ID\n"); usb_write(usb, &msg_getid, sizeof(msg_getid)); usb_read(usb, id, sizeof(id)); fprintf(stderr, "CHIP: %02x%02x\n", id[OFF_CHIP + 0], id[OFF_CHIP + 1]); fprintf(stderr, "IDEN: "); for (i = 0; i < 20; i++) fprintf(stderr, "%02x", id[OFF_ID + i]); fprintf(stderr, "\nMPKH: "); for (i = 0; i < 32; i++) fprintf(stderr, "%02x", id[OFF_MPKH + i]); fprintf(stderr, "\nCRC0: %02x%02x%02x%02x\n", id[73], id[74], id[75], id[76]); fprintf(stderr, "CRC1: %02x%02x%02x%02x\n", id[77], id[78], id[79], id[80]); fprintf(stderr, "sending u-boot-spl to target... %08x\n", msg_boot); sleep(1); usb_write(usb, &msg_boot, sizeof(msg_boot)); sleep(1); usb_write(usb, &msg_size, sizeof(msg_size)); sleep(1); usb_write(usb, data1, sz1); } if (data2) { char command[64]; char response[64]; long rsz; sleep(1); fprintf(stderr, "sending download command to u-boot-spl\n"); sprintf(command, "download:%08x", sz2); usb_write(usb, command, sizeof(command)); fprintf(stderr, "waiting for \"DATA\" response to download: command\n"); usb_read(usb, response, sizeof(response)); if (strncmp("DATA", response, 4)) { fprintf(stderr, "unexpected response\"%s\"\n", response); return -1; } rsz = strtol(response + 4, 0, 16); if (rsz != sz2) { fprintf(stderr, "bad returned size\"%s\"\n", response); return -1; } sleep(1); fprintf(stderr, "transferring %d bytes of data\n", sz2); usb_write(usb, data2, sz2); fprintf(stderr, "write finished, waiting for \"OKAY\"\n"); usb_read(usb, response, sizeof(response)); if (strncmp("OKAY", response, 4) == 0) { fprintf(stderr, "data transfer successful\n"); } else { fprintf(stderr, "unexpected response to data xfer\"%s\"\n", response); return -1; } } return 0; } int match_omap4_bootloader(usb_ifc_info * ifc) { if (ifc->dev_vendor != 0x0451) return -1; if ((ifc->dev_product != 0xd010) && (ifc->dev_product != 0xd00f)) return -1; return 0; } /* * same as above for now */ int match_u_boot_spl(usb_ifc_info * ifc) { if (ifc->dev_vendor != 0x0525) return -1; if (ifc->dev_product != 0xFFFF) return -1; return 0; } void *load_file(const char *file, unsigned *sz) { void *data; struct stat s; int fd; fd = open(file, O_RDONLY); if (fd < 0) return 0; if (fstat(fd, &s)) goto fail; data = malloc(s.st_size); if (!data) goto fail; if (read(fd, data, s.st_size) != s.st_size) { free(data); goto fail; } close(fd); *sz = s.st_size; return data; fail: close(fd); return 0; } extern unsigned char aboot_data[]; extern unsigned aboot_size; int main(int argc, char **argv) { void *data[2]; unsigned sz[2]; usb_handle *usb; int i; int once = 1; if (argc < 3) { fprintf(stderr, "usage: usbboot u-boot-spl.bin u-boot.bin\n"); return 0; } for (i = 0; i < 2; i++) { data[i] = load_file(argv[i + 1], sz + i); if (data[i] == 0) { fprintf(stderr, "cannot load '%s'\n", argv[i + 1]); return -1; } } /* * First talk to the omap4 mask rom boot loader */ for (;;) { usb = usb_open(match_omap4_bootloader); if (usb) { usb_boot(usb, data[0], sz[0], 0, 0); break; } if (once) { once = 0; fprintf(stderr, "waiting for OMAP44xx device...\n"); } usleep(2500); } usb_close(usb); /* * Second talk to u-boot-spl usb boot loader * this is a new connection since there is no * hand off between the mask rom usb code and * u-boot-spl */ once = 1; for (;;) { usb = usb_open(match_u_boot_spl); if (usb) return usb_boot(usb, 0, 0, data[1], sz[1]); if (once) { once = 0; fprintf(stderr, "waiting for U-Boot-spl bootloader...\n"); } usleep(2500); } return -1; }