#include <omap4/omap4_rom.h>
#include "protocol.h"
-#define WITH_MEMORY_TEST 0
-#define WITH_FLASH_BOOT 0
-#define WITH_SIGNATURE_CHECK 0
-
#define min(a,b) ( ((a) < (b)) ? (a) : (b) )
-#if WITH_MEMORY_TEST
-void memtest(void *x, unsigned count) {
- unsigned *w = x;
- unsigned n;
- count /= 4;
-
- printf("memtest write - %d\n",count);
- for (n = 0; n < count; n++) {
- unsigned chk = 0xa5a5a5a5 ^ n;
- w[n] = chk;
- }
- printf("memtest read\n");
- for (n = 0; n < count; n++) {
- unsigned chk = 0xa5a5a5a5 ^ n;
- if (w[n] != chk) {
- printf("ERROR @ %x (%x != %x)\n",
- (unsigned) (w+n), w[n], chk);
- return;
- }
- }
- printf("OK!\n");
-}
-#endif
-
struct usb usb;
unsigned cfg_machine_type = 2791;
-#if 0
-static void dump(unsigned char *address, unsigned len, char *text)
-{
- unsigned i, j, l;
-
- printf("\n\n%s\n", text);
-
- l = len % 16;
- if (l)
- l = len + 16 - l;
- else
- l = len;
-
- for (i = 0; i < l; i += 16) {
-
- printf("%08X: ", address + i);
-
- for (j = i; j < i + 16; j ++ ) {
- if (j < l)
- printf("%02X ", address[j]);
- else
- printf(" ");
- if (j == i + 8)
- printf ("-");
- }
-
- printf(" | ");
-
- for (j = i; j < i + 16; j ++ ) {
- if (j < l)
- printf("%c", address[j] >= 32 ? address[j] : '.');
- else
- printf(" ");
- if (j == i + 8)
- printf ("-");
- }
-
- printf("\n");
- }
-}
-#endif
-
-#if WITH_SIGNATURE_CHECK
-unsigned call_trusted(unsigned appid, unsigned procid, unsigned flag, void *args);
-
-int verify(void *data, unsigned len, void *signature, unsigned rights) {
- struct {
- unsigned count;
- void *data;
- unsigned len;
- void *signature;
- unsigned rights;
- } args;
- args.count = 4;
- args.data = data;
- args.len = len;
- args.signature = signature;
- args.rights = rights;
- return call_trusted(12, 0, 0, &args);
-}
-#endif
-
-#if WITH_FLASH_BOOT
-int load_image(unsigned device, unsigned start, unsigned count, void *data)
-{
- int (*rom_get_mem_driver)(struct mem_driver **io, u32 type);
- struct mem_driver *io = 0;
- struct mem_device local_md_device, *md = 0;
- struct read_desc rd;
- u16 options;
- u32 base;
- int z;
-
- if (get_omap_rev() >= OMAP_4460_ES1_DOT_0)
- base = PUBLIC_API_BASE_4460;
- else
- base = PUBLIC_API_BASE_4430;
-
- rom_get_mem_driver = API(base + PUBLIC_GET_DRIVER_MEM_OFFSET);
- z = rom_get_mem_driver(&io, device);
- if (z)
- return -1;
-
- md = &local_md_device;
- memset(md, 0, sizeof(struct mem_device));
- options = 0; // 1 = init phoenix pmic?
- md->initialized = 0;
- md->device_type = device;
- md->xip_device = 0;
- md->search_size = 0;
- md->base_address = 0;
- md->hs_toc_mask = 0;
- md->gp_toc_mask = 0;
- md->boot_options = &options;
- md->device_data = (void*) 0x80000000;
- memset(md->device_data, 0, 2500);
-
- z = io->init(md);
- if (z)
- return -1;
-
- rd.sector_start = start;
- rd.sector_count = count;
- rd.destination = data;
- z = io->read(md, &rd);
-
- return 0;
-}
-
-int load_from_mmc(unsigned device, unsigned *len)
-{
- load_image(device, 512, 512, (void*) CONFIG_ADDR_DOWNLOAD);
- *len = 256 * 1024;
- return 0;
-}
-#endif
-
int load_from_usb(unsigned *_len, unsigned *_addr)
{
u32 len, addr, msg;
return 0;
}
-void aboot(unsigned *info)
+static void __attribute__((noreturn))
+boot_image(unsigned machtype, unsigned image, unsigned len)
{
-#if WITH_FLASH_BOOT
- unsigned bootdevice;
-#endif
+ void (*entry)(unsigned, unsigned, unsigned);
+
+ printf("jumping to 0x%x...\n", image);
+ entry = (void*)image;
+ entry(0, cfg_machine_type, CONFIG_ADDR_ATAGS);
+ for (;;);
+}
+
+void __attribute__((noreturn))
+aboot(unsigned *info) {
unsigned n, len, addr = CONFIG_ADDR_DOWNLOAD;
board_mux_init();
serial_puts("\n[ aboot second-stage loader ]\n\n");
- printf("MSV=%08x\n",*((unsigned*) 0x4A00213C));
-
-#if WITH_MEMORY_TEST
- printf("Memory test, pass 1");
- memtest(0x82000000, 8*1024*1024);
- printf("Memory test, pass 2");
- memtest(0xA0208000, 8*1024*1024);
-#endif
-
- printf("Memory test complete\n");
-#if !WITH_FLASH_BOOT
n = load_from_usb(&len, &addr);
-#else
- if (info) {
- bootdevice = info[2] & 0xFF;
- } else {
- bootdevice = 0x45;
- }
-
- switch (bootdevice) {
- case 0x45: /* USB */
- serial_puts("boot device: USB\n\n");
- n = load_from_usb(&len);
- break;
- case 0x05:
- case 0x06:
- serial_puts("boot device: MMC\n\n");
- n = load_from_mmc(bootdevice, &len);
- break;
- default:
- serial_puts("boot device: unknown\n");
- for (;;) ;
- }
-#endif
printf("load complete\n");
if (n) {
serial_puts("*** IO ERROR ***\n");
} else {
-#if WITH_SIGNATURE_CHECK
- void *data = (void*) (addr);
- void *sign = (void*) (addr + len - 280);
- if ((len < 281) || (len > (32*1024*1024)))
- goto fail_verify;
- len -= 280;
-
- n = verify(data, len, sign, 2);
- if (n != 0) {
- fail_verify:
- serial_puts("*** SIGNATURE VERIFICATION FAILED ***\n");
- for (;;) ;
- }
-#endif
printf("starting!\n");
boot_image(cfg_machine_type, addr, len);
serial_puts("*** BOOT FAILED ***\n");
+++ /dev/null
-/*
- * Copyright (C) 2011 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 <aboot/aboot.h>
-#include <aboot/bootimg.h>
-
-static void boot_image_android(unsigned machtype, unsigned image, unsigned len)
-{
- void (*entry)(unsigned, unsigned, unsigned);
- struct boot_img_hdr *hdr = (void*) image;
- unsigned psize, pmask, kactual;
- unsigned *tag = (void*) CONFIG_ADDR_ATAGS;
-
- if (len < sizeof(*hdr))
- return;
-
- psize = hdr->page_size;
- pmask = hdr->page_size - 1;
-
- if ((psize != 1024) && (psize != 2048) && (psize != 4096))
- return;
-
- if (len < psize)
- return;
-
- kactual = (hdr->kernel_size + pmask) & (~pmask);
-
- /* CORE */
- *tag++ = 2;
- *tag++ = 0x54410001;
-
- if (hdr->ramdisk_size) {
- *tag++ = 4;
- *tag++ = 0x54420005;
- *tag++ = image + psize + kactual;
- *tag++ = hdr->ramdisk_size;
- }
-
- if (hdr->cmdline && hdr->cmdline[0]) {
- /* include terminating 0 and word align */
- unsigned n = (strlen((void*) hdr->cmdline) + 4) & (~3);
- *tag++ = (n / 4) + 2;
- *tag++ = 0x54410009;
- memcpy(tag, hdr->cmdline, n);
- tag += (n / 4);
- }
-
- /* END */
- *tag++ = 0;
- *tag++ = 0;
-
- /* need to move the kernel away from the ramdisk-in-bootimg
- * otherwise the ramdisk gets clobbered before it can be
- * uncompressed.
- */
- memcpy((void*) CONFIG_ADDR_KERNEL, (void *)image + psize, kactual);
- entry = (void*) CONFIG_ADDR_KERNEL;
-
- printf("kernel: 0x%x (%d bytes)\n",
- CONFIG_ADDR_KERNEL, hdr->kernel_size);
- printf("ramdisk: 0x%x (%d bytes)\n",
- image + psize + kactual, hdr->ramdisk_size);
- printf("atags: 0x%x\n", CONFIG_ADDR_ATAGS);
- printf("cmdline: %s\n", hdr->cmdline);
- printf("machtype: %d\n", machtype);
-
- serial_puts("\nbooting...\n");
- entry(0, machtype, CONFIG_ADDR_ATAGS);
-
- serial_puts("\nreturned from kernel?\n");
- for (;;) ;
-}
-
-static void __attribute__((noreturn)) boot_image_binary(unsigned machtype, unsigned image, unsigned len)
-{
- void (*entry)(unsigned, unsigned, unsigned);
-
- printf("jumping to 0x%x...\n", image);
- entry = (void*)image;
- entry(0, cfg_machine_type, CONFIG_ADDR_ATAGS);
- for (;;);
-}
-
-void boot_image(unsigned machtype, unsigned image, unsigned len)
-{
- unsigned n;
- char *x = (void*) image;
-
- /* is it android image ? */
- for (n = 0; n < 8; n++)
- if (x[n] != "ANDROID!"[n])
- break;
- if (n == 8)
- return boot_image_android(machtype, image, len);
-
- /* may be, is it uImage ? */
-
- /* .... */
-
- /* no, plain binary */
- boot_image_binary(machtype, image, len);
-
- return /* :) */;
-}
* SUCH DAMAGE.
*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
#include <sys/stat.h>
-#include <stdint.h>
+
+#include <assert.h>
#include <inttypes.h>
#include <fcntl.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <libelf.h>
+#include <libusb.h>
+
+/* XXX - make this work! */
+#if 0
+#include <armv7/include/dev/omap/omap44xx_boot_dev.h>
+#endif
// #include "usb.h"
-#include <usb-linux.h>
+//#include <usb-linux.h>
+#include <omap4/boot.h>
#include <protocol.h>
#define min(a,b) (((a) < (b)) ? (a): (b))
-static int print_error(int r)
-{
- fprintf(stderr, "failed: %s\n", strerror(r));
- return r;
+void
+fail(const char *fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ exit(EXIT_FAILURE);
}
-#define CHECK_ERROR(r) do { if (r) { return print_error((r)); } } while(0)
+static void
+fail_usb(const char *str, int e) {
+ fprintf(stderr, "%s: %s\n", str, libusb_strerror(e));
+ exit(EXIT_FAILURE);
+}
+
+static void
+fail_errno(const char *fmt, ...) {
+ char s[1024];
-#define USBBOOT_MAX_CHUNKS 20
+ va_list ap;
+ va_start(ap, fmt);
+ vsnprintf(s, 1024, fmt, ap);
+ va_end(ap);
+
+ perror(s);
+ exit(EXIT_FAILURE);
+}
+
+static void
+fail_elf(const char *s) {
+ fprintf(stderr, "%s: %s\n", s, elf_errmsg(elf_errno()));
+ exit(EXIT_FAILURE);
+}
struct usb_load_chunk {
- uint32_t address;
- void *data;
- unsigned size;
+ uint32_t address;
+ void *data;
+ unsigned size;
};
-int usb_boot(usb_handle usb, struct usb_load_chunk *chunks)
-{
- uint32_t msg_boot = 0xF0030002;
- uint32_t msg_getid = 0xF0030003;
- uint32_t msg;
- uint8_t id[81];
- int i;
- int r;
-
-#define OFF_CHIP 0x04
-#define OFF_ID 0x0F
-#define OFF_MPKH 0x26
- memset(id, 0xee, 81);
- fprintf(stderr,"reading ASIC ID\n");
- r = linux_usb_write(usb, &msg_getid, sizeof(msg_getid));
- CHECK_ERROR(r);
-
- r = linux_usb_read(usb, id, sizeof(id));
- CHECK_ERROR(r);
-
- 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 2ndstage to target... %08x\n",msg_boot);
- r = linux_usb_write(usb, &msg_boot, sizeof(msg_boot));
- CHECK_ERROR(r);
- usleep(1);
- r = linux_usb_write(usb, &chunks[0].size, sizeof(chunks[0].size));
- CHECK_ERROR(r);
- usleep(1);
- r = linux_usb_write(usb, chunks[0].data, chunks[0].size);
- CHECK_ERROR(r);
-
- // sleep to make stuff work
- sleep(2);
-
- msg = 0;
- fprintf(stderr,"waiting for 2ndstage response...\n");
- r = linux_usb_read(usb, &msg, sizeof(msg));
- CHECK_ERROR(r);
-
- fprintf(stderr, "response is %x\n", msg);
- if (msg != ABOOT_IS_READY) {
- fprintf(stderr,"unexpected 2ndstage response\n");
- return -1;
- }
-
- sleep(1);
-
- for (i = 1; chunks[i].address; i ++) {
-
- if (i != 1)
- printf("\n");
-
- fprintf(stderr, "sending size = %d, ", chunks[i].size);
- r = linux_usb_write(usb, &chunks[i].size, sizeof(chunks[i].size));
- CHECK_ERROR(r);
-
- fprintf(stderr, "sending address = 0x%08X, ", chunks[i].address);
- r = linux_usb_write(usb, &chunks[i].address, sizeof(chunks[i].address));
- CHECK_ERROR(r);
-
- fprintf(stderr, "sending image ");
- for (;;) {
- r = linux_usb_write(usb, chunks[i].data, min(chunks[i].size, CHUNK_SIZE));
- CHECK_ERROR(r);
- if (chunks[i].size < CHUNK_SIZE)
- break;
- chunks[i].data += CHUNK_SIZE;
- chunks[i].size -= CHUNK_SIZE;
- usleep(1);
- }
- CHECK_ERROR(r);
-
- sleep(1);
- }
-
- fprintf(stderr, "\nstarting chunk at 0x%"PRIx32"\n", chunks[1].address);
- msg = ABOOT_NO_MORE_DATA;
- r = linux_usb_write(usb, &msg, sizeof(msg));
- CHECK_ERROR(r);
-
- return 0;
+extern unsigned char aboot_data[];
+extern unsigned aboot_size;
+
+static void
+usb_write(struct libusb_device_handle *usbdev, void *data, int len) {
+ while(len > 0) {
+ int transferred;
+ int r= libusb_bulk_transfer(usbdev, OMAP44xx_bulk_out,
+ data, min(len, CHUNK_SIZE),
+ &transferred, 0);
+ if(r < 0) fail_usb("libusb_bulk_transfer", r);
+
+ assert(transferred <= len);
+ len-= transferred;
+ data+= transferred;
+ }
}
+static void
+usb_read(struct libusb_device_handle *usbdev, void *data, int len) {
+ while(len > 0) {
+ int transferred;
+ int r= libusb_bulk_transfer(usbdev, OMAP44xx_bulk_in,
+ data, min(len, CHUNK_SIZE),
+ &transferred, 0);
+ if(r < 0) fail_usb("libusb_bulk_transfer", r);
+
+ assert(transferred <= len);
+ len-= transferred;
+ data+= transferred;
+ }
+}
-void *load_file(const char *file, unsigned *sz)
-{
- void *data;
- struct stat s;
- int fd;
-
- fd = open(file, O_RDONLY);
- if (fd < 0)
- goto fail;
-
- 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:
- fprintf(stderr, "Cannot read file '%s'\n", file);
- if (fd >= 0)
- close(fd);
- return 0;
+void
+send_word(libusb_device_handle *usb, uint32_t msg) {
+ usb_write(usb, &msg, sizeof(msg));
}
-extern unsigned char aboot_data[];
-extern unsigned aboot_size;
+int
+usb_boot(libusb_device_handle *usb, void *image_data,
+ size_t image_size, uint32_t load_address) {
+ uint32_t msg;
+
+ fprintf(stderr,"Reading ASIC ID\n");
+ send_word(usb, OMAP44xx_bootmsg_getid);
+
+ struct omap44xx_id id;
+ usb_read(usb, &id, sizeof(id));
+
+ assert(id.items == 5);
+ assert(id.id.subblock_id = 0x01);
+ assert(id.checksum.subblock_id = 0x15);
+
+ printf("Chip reports itself to be an OMAP%02x%02x\n",
+ id.id.device[0], id.id.device[1]);
+
+ if(id.id.ch == OMAP44xx_ch_enabled)
+ printf("Configuration header (CH) loading enabled.\n");
+ else if(id.id.ch == OMAP44xx_ch_disabled)
+ printf("Configuration header (CH) loading disabled.\n");
+ else
+ printf("Unrecognised or corrupted CH setting: %02x\n", id.id.ch);
+
+ printf("ROM revision %02x\n", id.id.rom_revision);
+ printf("ROM CRC: %02x%02x%02x%02x\n",
+ id.checksum.rom_crc[0], id.checksum.rom_crc[1],
+ id.checksum.rom_crc[2], id.checksum.rom_crc[3]);
+
+ printf("Sending second stage bootloader... \n");
+ send_word(usb, OMAP44xx_bootmsg_periphboot);
+ usleep(1);
+ send_word(usb, aboot_size);
+ usleep(1);
+ usb_write(usb, aboot_data, aboot_size);
+
+ // sleep to make stuff work
+ sleep(1);
+
+ msg = 0;
+ printf("Waiting for second stage response...\n");
+ usb_read(usb, &msg, sizeof(msg));
+
+ printf("Response is \"%x\"\n", msg);
+ if (msg != ABOOT_IS_READY) fail("Unexpected second stage response\n");
+
+ usleep(500);
+
+ printf("Sending size = %zu, ", image_size);
+ send_word(usb, image_size);
+
+ printf("Sending address = 0x%08X, ", load_address);
+ send_word(usb, load_address);
+
+ struct timespec start, end;
+ printf("Sending image... ");
+ fflush(stdout);
+ if(clock_gettime(CLOCK_REALTIME, &start)) fail_errno("clock_gettime");
+ usb_write(usb, image_data, image_size);
+ if(clock_gettime(CLOCK_REALTIME, &end)) fail_errno("clock_gettime");
+ printf("done.\n");
+
+ double tstart= start.tv_sec + start.tv_nsec * 1e-9;
+ double tend= end.tv_sec + end.tv_nsec * 1e-9;
+ double elapsed= tend - tstart;
+
+ printf("Transferred %zuB in %.2fs at %.2fMB/s\n",
+ image_size, elapsed, (image_size / elapsed) / 1024 / 1024);
+
+ sleep(1);
+
+ printf("Starting chunk at 0x%"PRIx32"\n", load_address);
+ send_word(usb, ABOOT_NO_MORE_DATA);
+
+ return 0;
+}
+
+void *
+load_file(const char *file, size_t *sz, uint32_t *load_address) {
+ int fd= open(file, O_RDONLY);
+ if(fd < 0) fail_errno("open");
+
+ struct stat stat;
+ if(fstat(fd, &stat)) fail_errno("fstat");
+ size_t elfsize= stat.st_size;
+
+ void *elfdata= malloc(elfsize);
+ if(!elfdata) fail_errno("malloc");
+
+ /* Read the raw file data. */
+ {
+ size_t to_read= elfsize;
+ do {
+ size_t bytes_read= read(fd, elfdata, to_read);
+ if(bytes_read < 0) fail_errno("read");
+ assert(bytes_read <= to_read);
+ to_read -= bytes_read;
+ } while(to_read > 0);
+ }
+
+ Elf *elf= elf_memory(elfdata, elfsize);
+ if(!elf) fail_elf("elf_begin");
+
+ const char *elf_ident= elf_getident(elf, NULL);
+ if(!elf_ident) fail_elf("elf_getident");
+
+ if(elf_ident[EI_CLASS] != ELFCLASS32 ||
+ elf_ident[EI_DATA] != ELFDATA2LSB) {
+ fail("Not a 32-bit little-endian image.\n");
+ }
+
+ Elf32_Ehdr *ehdr= elf32_getehdr(elf);
+ if(!ehdr) fail_elf("elf32_getehdr");
+
+ if(ehdr->e_type != ET_EXEC) fail("Not an executable.\n");
+ if(ehdr->e_machine != EM_ARM) fail("Not an ARM binary.\n");
+
+ if(ehdr->e_phnum == 0) fail("No loadable segment.\n");
+ if(ehdr->e_phnum > 1) fail("More than one loadable segment.\n");
+
+ Elf32_Phdr *phdr= elf32_getphdr(elf);
+ if(!phdr) fail_elf("elf32_getphdr");
+
+ printf("Loadable segment at offset %08x, size %u\n",
+ phdr->p_offset, phdr->p_filesz);
+ printf("Load address %08x, loaded size %u\n",
+ phdr->p_vaddr, phdr->p_memsz);
+
+ void *image_base= elfdata + phdr->p_offset;
+ *sz= phdr->p_filesz;
+ *load_address= phdr->p_vaddr;
+
+ if(elf_end(elf)) fail_elf("elf_end");
+
+ return image_base;
+}
int main(int argc, char **argv)
{
- usb_handle usb;
- int once = 1, i;
- int r;
- struct usb_load_chunk chunks[USBBOOT_MAX_CHUNKS], *current;
- char *p;
- char *aboot_cmdline = "--aboot=";
- int aboot_cmdline_sz = strlen(aboot_cmdline);
-
- memset(chunks, 0, sizeof(chunks));
-
- chunks[ 0 ].data = aboot_data;
- chunks[ 0 ].size = aboot_size;
-
- if (argc < 2) {
- fprintf(stderr,"usage: usbboot [ <2ndstage> ] <image>\n");
- return 0;
- }
-
- for (i = 1, current = chunks + 1;
- i < argc && current - chunks < USBBOOT_MAX_CHUNKS;
- i ++) {
-
- /* check if argument is 2nd stage bootloader name */
- if (strcmp(argv[i], "-a") == 0) {
- chunks[0].data = load_file(argv[i + 1], &chunks[0].size);
- i++;
- if (chunks[0].data == NULL)
- break;
- continue;
- }
-
- if (strncmp(argv[i], aboot_cmdline, aboot_cmdline_sz) == 0) {
- chunks[0].data = load_file(argv[i] + aboot_cmdline_sz, &chunks[0].size);
- if (chunks[0].data == NULL)
- break;
- continue;
- }
-
- p = strchr(argv[i], '=');
- if (p == NULL)
- p = strchr(argv[i], ':');
- if (p == NULL) {
- current->address = 0x82000000;
- fprintf(stderr, "Warning: using %x for '%s'\n", current->address, argv[i]);
- p = argv[i];
- }
- else {
- *p = '\0';
- current->address = strtoul(argv[i], NULL, 0);
- p++; /* skip the ':' or '=' */
- }
- current->data = load_file(p, ¤t->size);
- if (current->data == NULL)
- break;
- current ++;
- }
-
- r = linux_usb_init();
- CHECK_ERROR(r);
-
- for (i = 0; i < USBBOOT_MAX_CHUNKS; i ++) {
- if (i && !chunks[i].address)
- break;
- printf("Chunk %d:\n", i);
- printf("\taddress = 0x%08X\n", chunks[i].address);
- printf("\tdata = %p\n", chunks[i].data);
- printf("\tsize = %d\n", chunks[i].size);
- }
-
- for (;;) {
- r = linux_usb_open(0x0451, 0xd010, &usb);
- if (r == 0 && usb) {
- r = usb_boot(usb, chunks);
- linux_usb_close(usb);
- break;
- }
- if (once) {
- once = 0;
- fprintf(stderr,"waiting for OMAP44xx device...\n");
- }
- usleep(250);
- }
-
- linux_usb_fini();
-
- return r;
+ struct libusb_context *usb;
+ struct libusb_device_handle *usbdev;
+ void *image_data;
+ size_t image_size;
+ uint32_t load_address;
+ int r;
+
+ if(elf_version(EV_CURRENT) == EV_NONE)
+ fail("ELF library version out of date");;
+
+ if (argc < 2)fail("usage: %s <image>\n", argv[0]);
+ image_data= load_file(argv[1], &image_size, &load_address);
+
+ r = libusb_init(&usb);
+ if(r) fail_usb("libusb_init", r);
+ libusb_set_debug(usb, LIBUSB_LOG_LEVEL_WARNING);
+
+ int once= 1;
+ for (;;) {
+ usbdev= libusb_open_device_with_vid_pid(usb,
+ OMAP44xx_vid, OMAP44xx_pid);
+ if(usbdev) {
+ r= libusb_reset_device(usbdev);
+ if(r) fail_usb("libusb_reset_device", r);
+
+ r= libusb_set_auto_detach_kernel_driver(usbdev, 1);
+ if(r) fail_usb("libusb_detach_kernel_driver", r);
+
+ r = libusb_set_configuration(usbdev, 1);
+ if(r) fail_usb("libusb_set_configuration", r);
+
+ r = libusb_claim_interface(usbdev, 0);
+ if(r) fail_usb("libusb_claim_interface", r);
+
+ struct libusb_device *dev= libusb_get_device(usbdev);
+ int speed= libusb_get_device_speed(dev);
+ if(speed < 0) fail_usb("libusb_get_device_speed", speed);
+ printf("Connected at ");
+ switch(speed) {
+ case LIBUSB_SPEED_LOW:
+ printf("1.5Mb/s\n");
+ break;
+ case LIBUSB_SPEED_FULL:
+ printf("12Mb/s.\n");
+ break;
+ case LIBUSB_SPEED_HIGH:
+ printf("480Mb/s.\n");
+ break;
+ case LIBUSB_SPEED_SUPER:
+ printf("5000Mb/s.\n");
+ break;
+ default:
+ printf("unknown speed.\n");
+ break;
+ }
+ }
+
+ if (r == 0 && usbdev) {
+ r = usb_boot(usbdev, image_data, image_size, load_address);
+ libusb_release_interface(usbdev, 0);
+ libusb_close(usbdev);
+ break;
+ }
+
+ if (once) {
+ once = 0;
+ fprintf(stderr,"Waiting for OMAP44xx device...\n");
+ }
+
+ usleep(250);
+ }
+
+ libusb_exit(usb);
+
+ return r;
}