/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id$ * * Copyright (C) 2015 by Amaury Pouly * * 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 2 * of the License, or (at your option) any later version. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/ #include #include #include #include #include #include #include #define VR_GET_CPU_INFO 0 #define VR_SET_DATA_ADDRESS 1 #define VR_SET_DATA_LENGTH 2 #define VR_FLUSH_CACHES 3 #define VR_PROGRAM_START1 4 #define VR_PROGRAM_START2 5 bool g_verbose = false; int jz_cpuinfo(libusb_device_handle *dev) { if(g_verbose) printf("Get CPU Info...\n"); uint8_t cpuinfo[9]; int ret = libusb_control_transfer(dev, LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, VR_GET_CPU_INFO, 0, 0, cpuinfo, 8, 1000); if(ret != 8) { printf("Cannot get CPU info: %d\n", ret); return ret; } cpuinfo[8] = 0; printf("CPU Info: %s\n", cpuinfo); return 0; } int jz_set_addr(libusb_device_handle *dev, unsigned long addr) { if(g_verbose) printf("Set address to 0x%lx...\n", addr); int ret = libusb_control_transfer(dev, LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, VR_SET_DATA_ADDRESS, addr >> 16, addr & 0xffff, NULL, 0, 1000); if(ret != 0) printf("Cannot set address: %d\n", ret); return ret; } int jz_set_length(libusb_device_handle *dev, unsigned long length) { if(g_verbose) printf("Set length to 0x%lx...\n", length); int ret = libusb_control_transfer(dev, LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, VR_SET_DATA_LENGTH, length >> 16, length & 0xffff, NULL, 0, 1000); if(ret != 0) printf("Cannot set length: %d\n", ret); return ret; } int jz_start1(libusb_device_handle *dev, unsigned long addr) { if(g_verbose) printf("Start 1 at 0x%lx...\n", addr); int ret = libusb_control_transfer(dev, LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, VR_PROGRAM_START1, addr >> 16, addr & 0xffff, NULL, 0, 1000); if(ret != 0) printf("Cannot start1: %d\n", ret); return ret; } int jz_start2(libusb_device_handle *dev, unsigned long addr) { if(g_verbose) printf("Start 2 at 0x%lx...\n", addr); int ret = libusb_control_transfer(dev, LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, VR_PROGRAM_START2, addr >> 16, addr & 0xffff, NULL, 0, 1000); if(ret != 0) printf("Cannot start2: %d\n", ret); return ret; } int jz_flush_caches(libusb_device_handle *dev) { if(g_verbose) printf("Flush caches...\n"); int ret = libusb_control_transfer(dev, LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, VR_FLUSH_CACHES, 0, 0, NULL, 0, 1000); if(ret != 0) printf("Cannot flush caches: %d\n", ret); return ret; } int jz_upload(libusb_device_handle *dev, const char *file, unsigned long length) { if(g_verbose) printf("Upload %lu bytes...\n", length); void *data = malloc(length); int xfered; int ret = libusb_bulk_transfer(dev, LIBUSB_ENDPOINT_IN | 1, data, length, &xfered, 10000); if(ret != 0) printf("Cannot upload data from device: %d\n", ret); if(ret == 0 && xfered != length) { printf("Device did not send all the data\n"); ret = -1; } if(ret == 0) { FILE *f = fopen(file, "wb"); if(f != NULL) { if(fwrite(data, length, 1, f) != 1) { printf("Cannot write file\n"); ret = -3; } fclose(f); } else { printf("Cannot open file for writing\n"); ret = -2; } } free(data); return ret; } int jz_download(libusb_device_handle *dev, const char *file) { FILE *f = fopen(file, "rb"); if(f == NULL) { printf("Cannot open file for reading\n"); return -1; } fseek(f, 0, SEEK_END); size_t length = ftell(f); fseek(f, 0, SEEK_SET); if(g_verbose) printf("Download %lu bytes..\n", length); void *data = malloc(length); if(fread(data, length, 1, f) != 1) { printf("Cannot read file\n"); free(data); fclose(f); return -1; } fclose(f); int xfered; int ret = libusb_bulk_transfer(dev, LIBUSB_ENDPOINT_OUT | 1, data, length, &xfered, 1000); if(ret != 0) printf("Cannot download data from device: %d\n", ret); if(ret == 0 && xfered != length) { printf("Device did not receive all the data\n"); ret = -1; } free(data); return ret; } int renumerate(libusb_device_handle **dev) { if(g_verbose) printf("Look for device again...\n"); libusb_close(*dev); *dev = libusb_open_device_with_vid_pid(NULL, 0x601a, 0x4760); if(dev == NULL) { printf("Cannot open device\n"); return -1; } return 0; } int jz_stage1(libusb_device_handle *dev, unsigned long addr, const char *file) { int ret = jz_set_addr(dev, addr); if(ret != 0) return ret; ret = jz_download(dev, file); if(ret != 0) return ret; return jz_start1(dev, addr); } void usage() { printf("Usage: usbboot [options]\n"); printf("\n"); printf("Basic options:\n"); printf(" --stage1 Upload first stage program (<=16Kio)\n"); printf(" --s1-addr Change first stage address (default is 0x80000000)\n"); printf(" --stage2 Upload second stage program to SDRAM\n"); printf(" --s2-addr Change second stage address (default is 0x80000000)\n"); printf(" --ram Setup SDRAM for , see list below\n"); printf("\n"); printf("Advanced options:\n"); printf(" --addr Set address for next operation\n"); printf(" --length Set length for next operation\n"); printf(" --download Download data in file to the device (use file length)\n"); printf(" --upload Upload data from the device to the file\n"); printf(" --cpuinfo Print CPU info\n"); printf(" --flush-caches Flush CPU caches\n"); printf(" --start1 Execute first stage from I-cache\n"); printf(" --start2 Execute second stage\n"); printf(" --wait