1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in 12 * the documentation and/or other materials provided with the 13 * distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29#include <sys/stat.h> 30 31#include <assert.h> 32#include <inttypes.h> 33#include <fcntl.h> 34#include <stdarg.h> 35#include <stdint.h> 36#include <stdio.h> 37#include <stdlib.h> 38#include <string.h> 39#include <time.h> 40#include <unistd.h> 41 42#include <libelf.h> 43#include <libusb.h> 44 45/* XXX - make this work! */ 46#if 0 47#include <armv7/include/dev/omap/omap44xx_boot_dev.h> 48#endif 49 50// #include "usb.h" 51//#include <usb-linux.h> 52#include <omap4/boot.h> 53#include <protocol.h> 54 55#define min(a,b) (((a) < (b)) ? (a): (b)) 56 57void 58fail(const char *fmt, ...) { 59 va_list ap; 60 va_start(ap, fmt); 61 vfprintf(stderr, fmt, ap); 62 va_end(ap); 63 exit(EXIT_FAILURE); 64} 65 66static void 67fail_usb(const char *str, int e) { 68 fprintf(stderr, "%s: %s\n", str, libusb_strerror(e)); 69 exit(EXIT_FAILURE); 70} 71 72static void 73fail_errno(const char *fmt, ...) { 74 char s[1024]; 75 76 va_list ap; 77 va_start(ap, fmt); 78 vsnprintf(s, 1024, fmt, ap); 79 va_end(ap); 80 81 perror(s); 82 exit(EXIT_FAILURE); 83} 84 85static void 86fail_elf(const char *s) { 87 fprintf(stderr, "%s: %s\n", s, elf_errmsg(elf_errno())); 88 exit(EXIT_FAILURE); 89} 90 91struct usb_load_chunk { 92 uint32_t address; 93 void *data; 94 unsigned size; 95}; 96 97extern unsigned char aboot_data[]; 98extern unsigned aboot_size; 99 100static void 101usb_write(struct libusb_device_handle *usbdev, void *data, int len) { 102 while(len > 0) { 103 int transferred; 104 int r= libusb_bulk_transfer(usbdev, OMAP44xx_bulk_out, 105 data, len, &transferred, 0); 106 if(r < 0) fail_usb("libusb_bulk_transfer", r); 107 108 assert(transferred <= len); 109 len-= transferred; 110 data+= transferred; 111 } 112} 113 114static int 115usb_read_nofail(struct libusb_device_handle *usbdev, void *data, int len, 116 int timeout) { 117 while(len > 0) { 118 int transferred; 119 int r= libusb_bulk_transfer(usbdev, OMAP44xx_bulk_in, 120 data, len, &transferred, timeout); 121 if(r < 0) return r; 122 123 assert(transferred <= len); 124 len-= transferred; 125 data+= transferred; 126 } 127 128 return 0; 129} 130 131static void 132usb_read(struct libusb_device_handle *usbdev, void *data, int len) { 133 int r= usb_read_nofail(usbdev, data, len, 0); 134 if(r < 0) fail_usb("libusb_bulk_transfer", r); 135} 136 137void 138send_word(libusb_device_handle *usb, uint32_t msg) { 139 usb_write(usb, &msg, sizeof(msg)); 140} 141 142uint32_t 143read_word(libusb_device_handle *usb) { 144 uint32_t msg; 145 usb_read(usb, &msg, sizeof(msg)); 146 return msg; 147} 148 149#define READ_TIMEOUT 1000 150 151int 152usb_boot(libusb_device_handle *usb, void *image_data, 153 size_t image_size, uint32_t load_address, uint32_t entry_point) { 154 uint32_t msg; 155 156 printf("Reading ASIC ID\n"); 157 send_word(usb, OMAP44xx_bootmsg_getid); 158 159 struct omap44xx_id id; 160 int r= usb_read_nofail(usb, &id, sizeof(id), READ_TIMEOUT); 161 if(r == LIBUSB_ERROR_TIMEOUT) { 162 fail("Timed out while reading ASID ID.\n" 163 "This probably means the Pandaboard has hung in the\n" 164 "ROM bootloader - try a hard reset.\n"); 165 } 166 else if(r < 0) fail_usb("libusb_bulk_transfer", r); 167 168 assert(id.items == 5); 169 assert(id.id.subblock_id == 0x01); 170 assert(id.checksum.subblock_id == 0x15); 171 172 printf("Chip reports itself to be an OMAP%02x%02x\n", 173 id.id.device[0], id.id.device[1]); 174 175 if(id.id.ch == OMAP44xx_ch_enabled) 176 printf("Configuration header (CH) loading enabled.\n"); 177 else if(id.id.ch == OMAP44xx_ch_disabled) 178 printf("Configuration header (CH) loading disabled.\n"); 179 else 180 printf("Unrecognised or corrupted CH setting: %02x\n", id.id.ch); 181 182 printf("ROM revision %02x\n", id.id.rom_revision); 183 printf("ROM CRC: %02x%02x%02x%02x\n", 184 id.checksum.rom_crc[0], id.checksum.rom_crc[1], 185 id.checksum.rom_crc[2], id.checksum.rom_crc[3]); 186 187 printf("Sending second stage bootloader... \n"); 188 send_word(usb, OMAP44xx_bootmsg_periphboot); 189 usleep(1); /* The ROM code is slow. */ 190 send_word(usb, aboot_size); 191 usleep(1); 192 usb_write(usb, aboot_data, aboot_size); 193 194 /* The bootloader takes a while, before it starts handling USB traffic. 195 * If we start talking to it too soon, it'll lock up. 100ms seems to do 196 * the trick. */ 197 usleep(100 * 1000); 198 199 msg = 0; 200 printf("Waiting for second stage response...\n"); 201 usb_read(usb, &msg, sizeof(msg)); 202 203 printf("Response is \"%x\"\n", msg); 204 if (msg != ABOOT_IS_READY) fail("Unexpected second stage response\n"); 205 206 printf("Sending size = %zu\n", image_size); 207 send_word(usb, image_size); 208 209 usleep(1); 210 211 printf("Sending load address = 0x%08x\n", load_address); 212 send_word(usb, load_address); 213 214 usleep(1); 215 216 printf("Sending entry point = 0x%08x\n", entry_point); 217 send_word(usb, entry_point); 218 219 struct timespec start, end; 220 printf("Sending image... "); 221 fflush(stdout); 222 if(clock_gettime(CLOCK_REALTIME, &start)) fail_errno("clock_gettime"); 223 224 /* Send the image in chunks. */ 225 size_t to_send= image_size; 226 void *send_ptr= image_data; 227 size_t chunk= 0; 228 while(to_send > 0) { 229 size_t this_chunk= min(to_send, CHUNK_SIZE); 230 231 /* Write a chunk. */ 232 usb_write(usb, send_ptr, this_chunk); 233 to_send-= this_chunk; 234 send_ptr+= this_chunk; 235 236 /* Wait for the acknowledgement. */ 237 size_t ack_chunk= read_word(usb); 238 if(ack_chunk != chunk) { 239 fail("Chunk synchronisation failed after %zuB\n", 240 image_size - to_send); 241 } 242 chunk++; 243 } 244 245 if(clock_gettime(CLOCK_REALTIME, &end)) fail_errno("clock_gettime"); 246 printf("done.\n"); 247 248 double tstart= start.tv_sec + start.tv_nsec * 1e-9; 249 double tend= end.tv_sec + end.tv_nsec * 1e-9; 250 double elapsed= tend - tstart; 251 252 printf("Transferred %zuB in %.2fs at %.2fMB/s\n", 253 image_size, elapsed, (image_size / elapsed) / 1024 / 1024); 254 255 printf("Starting image at 0x%"PRIx32"\n", load_address); 256 send_word(usb, ABOOT_NO_MORE_DATA); 257 258 return 0; 259} 260 261void * 262load_file(const char *file, size_t *sz, uint32_t *load_address, 263 uint32_t *entry_point) { 264 int fd= open(file, O_RDONLY); 265 if(fd < 0) fail_errno("open"); 266 267 struct stat stat; 268 if(fstat(fd, &stat)) fail_errno("fstat"); 269 size_t elfsize= stat.st_size; 270 271 void *elfdata= malloc(elfsize); 272 if(!elfdata) fail_errno("malloc"); 273 274 /* Read the raw file data. */ 275 { 276 size_t to_read= elfsize; 277 do { 278 size_t bytes_read= read(fd, elfdata, to_read); 279 if(bytes_read < 0) fail_errno("read"); 280 assert(bytes_read <= to_read); 281 to_read -= bytes_read; 282 } while(to_read > 0); 283 } 284 285 Elf *elf= elf_memory(elfdata, elfsize); 286 if(!elf) fail_elf("elf_begin"); 287 288 const char *elf_ident= elf_getident(elf, NULL); 289 if(!elf_ident) fail_elf("elf_getident"); 290 291 if(elf_ident[EI_CLASS] != ELFCLASS32 || 292 elf_ident[EI_DATA] != ELFDATA2LSB) { 293 fail("Not a 32-bit little-endian image.\n"); 294 } 295 296 Elf32_Ehdr *ehdr= elf32_getehdr(elf); 297 if(!ehdr) fail_elf("elf32_getehdr"); 298 299 if(ehdr->e_type != ET_EXEC) fail("Not an executable.\n"); 300 if(ehdr->e_machine != EM_ARM) fail("Not an ARM binary.\n"); 301 302 if(ehdr->e_phnum == 0) fail("No loadable segment.\n"); 303 if(ehdr->e_phnum > 1) fail("More than one loadable segment.\n"); 304 305 Elf32_Phdr *phdr= elf32_getphdr(elf); 306 if(!phdr) fail_elf("elf32_getphdr"); 307 308 printf("Loadable segment at offset %08x, size %u\n", 309 phdr->p_offset, phdr->p_filesz); 310 printf("Load address %08x, loaded size %u\n", 311 phdr->p_vaddr, phdr->p_memsz); 312 printf("Entry point %08x\n", 313 ehdr->e_entry); 314 315 void *image_base= elfdata + phdr->p_offset; 316 *sz= phdr->p_filesz; 317 *load_address= phdr->p_vaddr; 318 *entry_point= ehdr->e_entry; 319 320 if(elf_end(elf)) fail_elf("elf_end"); 321 322 return image_base; 323} 324 325int main(int argc, char **argv) 326{ 327 struct libusb_context *usb; 328 struct libusb_device_handle *usbdev; 329 void *image_data; 330 size_t image_size; 331 uint32_t load_address, entry_point; 332 int r; 333 334 if(elf_version(EV_CURRENT) == EV_NONE) 335 fail("ELF library version out of date");; 336 337 if (argc < 2)fail("usage: %s <image>\n", argv[0]); 338 image_data= load_file(argv[1], &image_size, &load_address, &entry_point); 339 340 r = libusb_init(&usb); 341 if(r) fail_usb("libusb_init", r); 342 libusb_set_debug(usb, LIBUSB_LOG_LEVEL_WARNING); 343 344 int once= 1; 345 for (;;) { 346 usbdev= libusb_open_device_with_vid_pid(usb, 347 OMAP44xx_vid, OMAP44xx_pid); 348 if(usbdev) { 349 r= libusb_reset_device(usbdev); 350 if(r) fail_usb("libusb_reset_device", r); 351 352 r= libusb_set_auto_detach_kernel_driver(usbdev, 1); 353 if(r) fail_usb("libusb_detach_kernel_driver", r); 354 355 r = libusb_set_configuration(usbdev, 1); 356 if(r) fail_usb("libusb_set_configuration", r); 357 358 r = libusb_claim_interface(usbdev, 0); 359 if(r) fail_usb("libusb_claim_interface", r); 360 361 struct libusb_device *dev= libusb_get_device(usbdev); 362 int speed= libusb_get_device_speed(dev); 363 if(speed < 0) fail_usb("libusb_get_device_speed", speed); 364 printf("Connected at "); 365 switch(speed) { 366 case LIBUSB_SPEED_LOW: 367 printf("1.5Mb/s\n"); 368 break; 369 case LIBUSB_SPEED_FULL: 370 printf("12Mb/s.\n"); 371 break; 372 case LIBUSB_SPEED_HIGH: 373 printf("480Mb/s.\n"); 374 break; 375 case LIBUSB_SPEED_SUPER: 376 printf("5000Mb/s.\n"); 377 break; 378 default: 379 printf("unknown speed.\n"); 380 break; 381 } 382 } 383 384 if (r == 0 && usbdev) { 385 r = usb_boot(usbdev, image_data, image_size, load_address, 386 entry_point); 387 libusb_release_interface(usbdev, 0); 388 libusb_close(usbdev); 389 break; 390 } 391 392 if (once) { 393 once = 0; 394 fprintf(stderr,"Waiting for OMAP44xx device...\n"); 395 } 396 397 usleep(1000000); 398 } 399 400 libusb_exit(usb); 401 402 return r; 403} 404