diff options
Diffstat (limited to 'packages/u-boot/u-boot-mkimage-openmoko-native/uboot-dfu.patch')
-rw-r--r-- | packages/u-boot/u-boot-mkimage-openmoko-native/uboot-dfu.patch | 2081 |
1 files changed, 0 insertions, 2081 deletions
diff --git a/packages/u-boot/u-boot-mkimage-openmoko-native/uboot-dfu.patch b/packages/u-boot/u-boot-mkimage-openmoko-native/uboot-dfu.patch deleted file mode 100644 index ad319c0a26..0000000000 --- a/packages/u-boot/u-boot-mkimage-openmoko-native/uboot-dfu.patch +++ /dev/null @@ -1,2081 +0,0 @@ -Index: u-boot/drivers/usbdcore_ep0.c -=================================================================== ---- u-boot.orig/drivers/usbdcore_ep0.c -+++ u-boot/drivers/usbdcore_ep0.c -@@ -42,10 +42,15 @@ - */ - - #include <common.h> -+DECLARE_GLOBAL_DATA_PTR; - - #if defined(CONFIG_USB_DEVICE) - #include "usbdcore.h" - -+#ifdef CONFIG_USBD_DFU -+#include <usb_dfu.h> -+#endif -+ - #if 0 - #define dbg_ep0(lvl,fmt,args...) serial_printf("[%s] %s:%d: "fmt"\n",__FILE__,__FUNCTION__,__LINE__,##args) - #else -@@ -213,7 +218,7 @@ - urb->buffer = device_descriptor; - urb->actual_length = MIN(sizeof(*device_descriptor), max); - } -- /*dbg_ep0(3, "copied device configuration, actual_length: %x", urb->actual_length); */ -+ dbg_ep0(3, "using device configuration, actual_length: %x", urb->actual_length); - break; - - case USB_DESCRIPTOR_TYPE_CONFIGURATION: -@@ -267,7 +272,24 @@ - return -1; - case USB_DESCRIPTOR_TYPE_ENDPOINT: - return -1; -+ /* This really means "Class Specific Descriptor #1 == USB_DT_DFU */ - case USB_DESCRIPTOR_TYPE_HID: -+#ifdef CONFIG_USBD_DFU -+ { -+ int bNumInterface = -+ le16_to_cpu(urb->device_request.wIndex); -+ -+ /* In runtime mode, we only respond to the DFU INTERFACE, -+ * whereas in DFU mode, we respond for all intrfaces */ -+ if (device->dfu_state != DFU_STATE_appIDLE && -+ device->dfu_state != DFU_STATE_appDETACH || -+ bNumInterface == CONFIG_USBD_DFU_INTERFACE) { -+ urb->buffer = &device->dfu_cfg_desc->func_dfu; -+ urb->actual_length = sizeof(struct usb_dfu_func_descriptor); -+ } else -+ return -1; -+ } -+#else /* CONFIG_USBD_DFU */ - { - return -1; /* unsupported at this time */ - #if 0 -@@ -294,6 +316,7 @@ - max); - #endif - } -+#endif /* CONFIG_USBD_DFU */ - break; - case USB_DESCRIPTOR_TYPE_REPORT: - { -@@ -388,6 +411,24 @@ - le16_to_cpu (request->wLength), - USBD_DEVICE_REQUESTS (request->bRequest)); - -+#ifdef CONFIG_USBD_DFU -+ if ((request->bmRequestType & 0x3f) == USB_TYPE_DFU && -+ (device->dfu_state != DFU_STATE_appIDLE || -+ le16_to_cpu(request->wIndex) == CONFIG_USBD_DFU_INTERFACE)) { -+ int rc = dfu_ep0_handler(urb); -+ switch (rc) { -+ case DFU_EP0_NONE: -+ case DFU_EP0_UNHANDLED: -+ break; -+ case DFU_EP0_ZLP: -+ case DFU_EP0_DATA: -+ return 0; -+ case DFU_EP0_STALL: -+ return -1; -+ } -+ } -+#endif /* CONFIG_USB_DFU */ -+ - /* handle USB Standard Request (c.f. USB Spec table 9-2) */ - if ((request->bmRequestType & USB_REQ_TYPE_MASK) != 0) { - if (device->device_state <= STATE_CONFIGURED) -@@ -570,7 +611,8 @@ - device->interface = le16_to_cpu (request->wIndex); - device->alternate = le16_to_cpu (request->wValue); - /*dbg_ep0(2, "set interface: %d alternate: %d", device->interface, device->alternate); */ -- serial_printf ("DEVICE_SET_INTERFACE.. event?\n"); -+ usbd_device_event_irq(device, DEVICE_SET_INTERFACE, -+ (request->wIndex << 16 | request->wValue)); - return 0; - - case USB_REQ_GET_STATUS: -Index: u-boot/drivers/usbdfu.c -=================================================================== ---- /dev/null -+++ u-boot/drivers/usbdfu.c -@@ -0,0 +1,1069 @@ -+/* -+ * (C) 2007 by Openmoko, Inc. -+ * Author: Harald Welte <laforge@openmoko.org> -+ * -+ * based on existing SAM7DFU code from OpenPCD: -+ * (C) Copyright 2006 by Harald Welte <hwelte@hmw-consulting.de> -+ * -+ * See file CREDITS for list of people who contributed to this -+ * project. -+ * -+ * 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 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, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, -+ * MA 02111-1307 USA -+ * -+ * TODO: -+ * - make NAND support reasonably self-contained and put in apropriate -+ * ifdefs -+ * - add some means of synchronization, i.e. block commandline access -+ * while DFU transfer is in progress, and return to commandline once -+ * we're finished -+ * - add VERIFY support after writing to flash -+ * - sanely free() resources allocated during first uppload/download -+ * request when aborting -+ * - sanely free resources when another alternate interface is selected -+ * -+ * Maybe: -+ * - add something like uImage or some other header that provides CRC -+ * checking? -+ * - make 'dnstate' attached to 'struct usb_device_instance' -+ */ -+ -+#include <config.h> -+#if defined(CONFIG_USBD_DFU) -+ -+#include <common.h> -+DECLARE_GLOBAL_DATA_PTR; -+ -+#include <malloc.h> -+#include <linux/types.h> -+#include <linux/list.h> -+#include <asm/errno.h> -+#include <usbdcore.h> -+#include <usb_dfu.h> -+#include <usb_dfu_descriptors.h> -+#include <usb_dfu_trailer.h> -+ -+#include <nand.h> -+#include <jffs2/load_kernel.h> -+int mtdparts_init(void); -+extern struct list_head devices; -+ -+#include "usbdcore_s3c2410.h" -+#include "usbtty.h" /* for STR_* defs */ -+ -+#define RET_NOTHING 0 -+#define RET_ZLP 1 -+#define RET_STALL 2 -+ -+volatile enum dfu_state *system_dfu_state; /* for 3rd parties */ -+ -+ -+struct dnload_state { -+ nand_info_t *nand; -+ struct part_info *part; -+ unsigned int part_net_size; /* net sizee (excl. bad blocks) of part */ -+ -+ nand_erase_options_t erase_opts; -+ nand_write_options_t write_opts; -+ nand_read_options_t read_opts; -+ -+ unsigned char *ptr; /* pointer to next empty byte in buffer */ -+ unsigned int off; /* offset of current erase page in flash chip */ -+ unsigned char *buf; /* pointer to allocated erase page buffer */ -+ -+ /* unless doing an atomic transfer, we use the static buffer below. -+ * This saves us from having to clean up dynamic allications in the -+ * various error paths of the code. Also, it will always work, no -+ * matter what the memory situation is. */ -+ unsigned char _buf[0x20000]; /* FIXME: depends flash page size */ -+}; -+ -+static struct dnload_state _dnstate; -+ -+static int dfu_trailer_matching(const struct uboot_dfu_trailer *trailer) -+{ -+ if (trailer->magic != UBOOT_DFU_TRAILER_MAGIC || -+ trailer->version != UBOOT_DFU_TRAILER_V1 || -+ trailer->vendor != CONFIG_USBD_VENDORID || -+ (trailer->product != CONFIG_USBD_PRODUCTID_CDCACM && -+ trailer->product != CONFIG_USBD_PRODUCTID_GSERIAL)) -+ return 0; -+#ifdef CONFIG_REVISION_TAG -+ if (trailer->revision != get_board_rev()) -+ return 0; -+#endif -+ -+ return 1; -+} -+ -+static struct part_info *get_partition_nand(int idx) -+{ -+ struct mtd_device *dev; -+ struct part_info *part; -+ struct list_head *pentry; -+ int i; -+ -+ if (mtdparts_init()) -+ return NULL; -+ if (list_empty(&devices)) -+ return NULL; -+ -+ dev = list_entry(devices.next, struct mtd_device, link); -+ i = 0; -+ list_for_each(pentry, &dev->parts) { -+ if (i == idx) { -+ part = list_entry(pentry, struct part_info, link); -+ return part; -+ } -+ i++; -+ } -+ -+ return NULL; -+} -+ -+#define LOAD_ADDR ((unsigned char *)0x32000000) -+ -+static int initialize_ds_nand(struct usb_device_instance *dev, struct dnload_state *ds) -+{ -+ ds->part = get_partition_nand(dev->alternate - 1); -+ if (!ds->part) { -+ printf("DFU: unable to find partition %u\b", dev->alternate-1); -+ dev->dfu_state = DFU_STATE_dfuERROR; -+ dev->dfu_status = DFU_STATUS_errADDRESS; -+ return RET_STALL; -+ } -+ ds->nand = &nand_info[ds->part->dev->id->num]; -+ ds->off = ds->part->offset; -+ ds->part_net_size = nand_net_part_size(ds->part); -+ -+ if (ds->nand->erasesize > sizeof(ds->_buf)) { -+ printf("*** Warning - NAND ERASESIZE bigger than static buffer\n"); -+ ds->buf = malloc(ds->nand->erasesize); -+ if (!ds->buf) { -+ printf("DFU: can't allocate %u bytes\n", ds->nand->erasesize); -+ dev->dfu_state = DFU_STATE_dfuERROR; -+ dev->dfu_status = DFU_STATUS_errADDRESS; -+ return RET_STALL; -+ } -+ } else -+ ds->buf = ds->_buf; -+ -+ ds->ptr = ds->buf; -+ -+ memset(&ds->read_opts, 0, sizeof(ds->read_opts)); -+ -+ memset(&ds->erase_opts, 0, sizeof(ds->erase_opts)); -+ ds->erase_opts.quiet = 1; -+ /* FIXME: do this more dynamic */ -+ if (!strcmp(ds->part->name, "rootfs")) -+ ds->erase_opts.jffs2 = 1; -+ -+ memset(&ds->write_opts, 0, sizeof(ds->write_opts)); -+ ds->write_opts.pad = 1; -+ ds->write_opts.blockalign = 1; -+ ds->write_opts.quiet = 1; -+ -+ debug("initialize_ds_nand(dev=%p, ds=%p): ", dev, ds); -+ debug("nand=%p, ptr=%p, buf=%p, off=0x%x\n", ds->nand, ds->ptr, ds->buf, ds->off); -+ -+ return RET_NOTHING; -+} -+ -+static int erase_flash_verify_nand(struct urb *urb, struct dnload_state *ds, -+ unsigned long erasesize, unsigned long size) -+{ -+ struct usb_device_instance *dev = urb->device; -+ int rc; -+ -+ debug("erase_flash_verify_nand(urb=%p, ds=%p, erase=0x%x size=0x%x)\n", -+ urb, ds, erasesize, size); -+ -+ if (erasesize == ds->nand->erasesize) { -+ /* we're only writing a single block and need to -+ * do bad block skipping / offset adjustments our own */ -+ while (ds->nand->block_isbad(ds->nand, ds->off)) { -+ debug("SKIP_ONE_BLOCK(0x%08x)!!\n", ds->off); -+ ds->off += ds->nand->erasesize; -+ } -+ } -+ -+ /* we have finished one eraseblock, flash it */ -+ ds->erase_opts.offset = ds->off; -+ ds->erase_opts.length = erasesize; -+ debug("Erasing 0x%x bytes @ offset 0x%x (jffs=%u)\n", -+ ds->erase_opts.length, ds->erase_opts.offset, -+ ds->erase_opts.jffs2); -+ rc = nand_erase_opts(ds->nand, &ds->erase_opts); -+ if (rc) { -+ debug("Error erasing\n"); -+ dev->dfu_state = DFU_STATE_dfuERROR; -+ dev->dfu_status = DFU_STATUS_errERASE; -+ return RET_STALL; -+ } -+ -+ ds->write_opts.buffer = ds->buf; -+ ds->write_opts.length = size; -+ ds->write_opts.offset = ds->off; -+ debug("Writing 0x%x bytes @ offset 0x%x\n", size, ds->off); -+ rc = nand_write_opts(ds->nand, &ds->write_opts); -+ if (rc) { -+ debug("Error writing\n"); -+ dev->dfu_state = DFU_STATE_dfuERROR; -+ dev->dfu_status = DFU_STATUS_errWRITE; -+ return RET_STALL; -+ } -+ -+ ds->off += size; -+ ds->ptr = ds->buf; -+ -+ /* FIXME: implement verify! */ -+ return RET_NOTHING; -+} -+ -+static int erase_tail_clean_nand(struct urb *urb, struct dnload_state *ds) -+{ -+ struct usb_device_instance *dev = urb->device; -+ int rc; -+ -+ ds->erase_opts.offset = ds->off; -+ ds->erase_opts.length = ds->part->size-ds->off; -+ debug("Erasing 0x%x bytes @ offset 0x%x (jffs=%u)\n", -+ ds->erase_opts.length, ds->erase_opts.offset, -+ ds->erase_opts.jffs2); -+ rc = nand_erase_opts(ds->nand, &ds->erase_opts); -+ if (rc) { -+ debug("Error erasing\n"); -+ dev->dfu_state = DFU_STATE_dfuERROR; -+ dev->dfu_status = DFU_STATUS_errERASE; -+ return RET_STALL; -+ } -+ -+ ds->off += ds->part->size; /* for consistency */ -+ -+ return RET_NOTHING; -+} -+ -+/* Read the next erase blcok from NAND into buffer */ -+static int read_next_nand(struct urb *urb, struct dnload_state *ds) -+{ -+ struct usb_device_instance *dev = urb->device; -+ int rc; -+ -+ ds->read_opts.buffer = ds->buf; -+ ds->read_opts.length = ds->nand->erasesize; -+ ds->read_opts.offset = ds->off; -+ ds->read_opts.quiet = 1; -+ -+ debug("Reading 0x%x@0x%x to 0x%08p\n", ds->nand->erasesize, -+ ds->off, ds->buf); -+ rc = nand_read_opts(ds->nand, &ds->read_opts); -+ if (rc) { -+ debug("Error reading\n"); -+ dev->dfu_state = DFU_STATE_dfuERROR; -+ dev->dfu_status = DFU_STATUS_errWRITE; -+ return RET_STALL; -+ } -+ ds->off += ds->nand->erasesize; -+ ds->ptr = ds->buf; -+ -+ return RET_NOTHING; -+} -+ -+ -+static int handle_dnload(struct urb *urb, u_int16_t val, u_int16_t len, int first) -+{ -+ struct usb_device_instance *dev = urb->device; -+ struct dnload_state *ds = &_dnstate; -+ unsigned int actual_len = len; -+ unsigned int remain_len; -+ unsigned long size; -+ int rc; -+ -+ debug("download(len=%u, first=%u) ", len, first); -+ -+ if (len > CONFIG_USBD_DFU_XFER_SIZE) { -+ /* Too big. Not that we'd really care, but it's a -+ * DFU protocol violation */ -+ debug("length exceeds flash page size "); -+ dev->dfu_state = DFU_STATE_dfuERROR; -+ dev->dfu_status = DFU_STATUS_errADDRESS; -+ return RET_STALL; -+ } -+ -+ if (first) { -+ /* Make sure that we have a valid mtd partition table */ -+ char *mtdp = getenv("mtdparts"); -+ if (!mtdp) -+ run_command("dynpart", 0); -+ } -+ -+ if (len == 0) { -+ debug("zero-size write -> MANIFEST_SYNC "); -+ dev->dfu_state = DFU_STATE_dfuMANIFEST_SYNC; -+ -+ /* cleanup */ -+ switch (dev->alternate) { -+ char buf[12]; -+ case 0: -+ sprintf(buf, "%lx", ds->ptr - ds->buf); -+ setenv("filesize", buf); -+ ds->ptr = ds->buf; -+ break; -+ case 1: -+ if (ds->ptr > -+ ds->buf + sizeof(struct uboot_dfu_trailer)) { -+ struct uboot_dfu_trailer trailer; -+ dfu_trailer_mirror(&trailer, ds->ptr); -+ if (!dfu_trailer_matching(&trailer)) { -+ printf("DFU TRAILER NOT OK\n"); -+ dev->dfu_state = DFU_STATE_dfuERROR; -+ dev->dfu_status = DFU_STATUS_errTARGET; -+ return RET_STALL; -+ } -+ -+ rc = erase_flash_verify_nand(urb, ds, -+ ds->part->size, -+ ds->part_net_size); -+ /* re-write dynenv marker in OOB */ -+ run_command("dynenv set u-boot_env", 0); -+ } -+ ds->nand = NULL; -+ free(ds->buf); -+ ds->ptr = ds->buf = ds->_buf; -+ break; -+ default: -+ rc = 0; -+ if (ds->ptr > ds->buf) -+ rc = erase_flash_verify_nand(urb, ds, -+ ds->nand->erasesize, -+ ds->nand->erasesize); -+ /* rootfs partition */ -+ if (!rc && dev->alternate == 5) -+ rc = erase_tail_clean_nand(urb, ds); -+ -+ ds->nand = NULL; -+ break; -+ } -+ -+ return RET_ZLP; -+ } -+ -+ if (urb->actual_length != len) { -+ debug("urb->actual_length(%u) != len(%u) ?!? ", -+ urb->actual_length, len); -+ dev->dfu_state = DFU_STATE_dfuERROR; -+ dev->dfu_status = DFU_STATUS_errADDRESS; -+ return RET_STALL; -+ } -+ -+ if (first && ds->buf && ds->buf != ds->_buf && ds->buf != LOAD_ADDR) { -+ free(ds->buf); -+ ds->buf = ds->_buf; -+ } -+ -+ switch (dev->alternate) { -+ case 0: -+ if (first) { -+ printf("Starting DFU DOWNLOAD to RAM (0x%08p)\n", -+ LOAD_ADDR); -+ ds->buf = LOAD_ADDR; -+ ds->ptr = ds->buf; -+ } -+ -+ memcpy(ds->ptr, urb->buffer, len); -+ ds->ptr += len; -+ break; -+ case 1: -+ if (first) { -+ rc = initialize_ds_nand(dev, ds); -+ if (rc) -+ return rc; -+ ds->buf = malloc(ds->part_net_size); -+ if (!ds->buf) { -+ printf("No memory for atomic buffer!!\n"); -+ dev->dfu_state = DFU_STATE_dfuERROR; -+ dev->dfu_status = DFU_STATUS_errUNKNOWN; -+ return RET_STALL; -+ } -+ ds->ptr = ds->buf; -+ printf("Starting Atomic DFU DOWNLOAD to partition '%s'\n", -+ ds->part->name); -+ } -+ -+ remain_len = (ds->buf + ds->part_net_size) - ds->ptr; -+ if (remain_len < len) { -+ len = remain_len; -+ printf("End of write exceeds partition end\n"); -+ dev->dfu_state = DFU_STATE_dfuERROR; -+ dev->dfu_status = DFU_STATUS_errADDRESS; -+ return RET_STALL; -+ } -+ memcpy(ds->ptr, urb->buffer, len); -+ ds->ptr += len; -+ break; -+ default: -+ if (first) { -+ rc = initialize_ds_nand(dev, ds); -+ if (rc) -+ return rc; -+ printf("Starting DFU DOWNLOAD to partition '%s'\n", -+ ds->part->name); -+ } -+ -+ size = ds->nand->erasesize; -+ remain_len = ds->buf + size - ds->ptr; -+ if (remain_len < len) -+ actual_len = remain_len; -+ -+ memcpy(ds->ptr, urb->buffer, actual_len); -+ ds->ptr += actual_len; -+ -+ /* check partition end */ -+ if (ds->off + (ds->ptr - ds->buf) > ds->part->offset + ds->part->size) { -+ printf("End of write exceeds partition end\n"); -+ dev->dfu_state = DFU_STATE_dfuERROR; -+ dev->dfu_status = DFU_STATUS_errADDRESS; -+ return RET_STALL; -+ } -+ -+ if (ds->ptr >= ds->buf + size) { -+ rc = erase_flash_verify_nand(urb, ds, -+ ds->nand->erasesize, -+ ds->nand->erasesize); -+ if (rc) -+ return rc; -+ /* copy remainder of data into buffer */ -+ memcpy(ds->ptr, urb->buffer + actual_len, len - actual_len); -+ ds->ptr += (len - actual_len); -+ } -+ break; -+ } -+ -+ return RET_ZLP; -+} -+ -+static int handle_upload(struct urb *urb, u_int16_t val, u_int16_t len, int first) -+{ -+ struct usb_device_instance *dev = urb->device; -+ struct dnload_state *ds = &_dnstate; -+ unsigned int remain; -+ int rc; -+ -+ debug("upload(val=0x%02x, len=%u, first=%u) ", val, len, first); -+ -+ if (len > CONFIG_USBD_DFU_XFER_SIZE) { -+ /* Too big */ -+ dev->dfu_state = DFU_STATE_dfuERROR; -+ dev->dfu_status = DFU_STATUS_errADDRESS; -+ //udc_ep0_send_stall(); -+ debug("Error: Transfer size > CONFIG_USBD_DFU_XFER_SIZE "); -+ return -EINVAL; -+ } -+ -+ switch (dev->alternate) { -+ case 0: -+ if (first) { -+ printf("Starting DFU Upload of RAM (0x%08p)\n", -+ LOAD_ADDR); -+ ds->ptr = ds->buf; -+ } -+ -+ /* FIXME: end at some more dynamic point */ -+ if (ds->ptr + len > LOAD_ADDR + 0x200000) -+ len = (LOAD_ADDR + 0x200000) - ds->ptr; -+ -+ urb->buffer = ds->ptr; -+ urb->actual_length = len; -+ ds->ptr += len; -+ break; -+ default: -+ if (first) { -+ rc = initialize_ds_nand(dev, ds); -+ if (rc) -+ return -EINVAL; -+ printf("Starting DFU Upload of partition '%s'\n", -+ ds->part->name); -+ rc = read_next_nand(urb, ds); -+ if (rc) -+ return -EINVAL; -+ } -+ -+ if (len > ds->nand->erasesize) { -+ printf("We don't support transfers bigger than %u\n", -+ ds->nand->erasesize); -+ len = ds->nand->erasesize; -+ } -+ -+ remain = ds->nand->erasesize - (ds->ptr - ds->buf); -+ if (len < remain) -+ remain = len; -+ -+ debug("copying %u bytes ", remain); -+ urb->buffer = ds->ptr; -+ ds->ptr += remain; -+ urb->actual_length = remain; -+ -+ if (ds->ptr >= ds->buf + ds->nand->erasesize && -+ ds->off < ds->part->offset + ds->part->size) { -+ rc = read_next_nand(urb, ds); -+ if (rc) -+ return -EINVAL; -+ if (len > remain) { -+ debug("copying another %u bytes ", len - remain); -+ memcpy(urb->buffer + remain, ds->ptr, len - remain); -+ ds->ptr += (len - remain); -+ urb->actual_length += (len - remain); -+ } -+ } -+ break; -+ } -+ -+ debug("returning len=%u\n", len); -+ return len; -+} -+ -+static void handle_getstatus(struct urb *urb, int max) -+{ -+ struct usb_device_instance *dev = urb->device; -+ struct dfu_status *dstat = (struct dfu_status *) urb->buffer; -+ -+ debug("getstatus "); -+ -+ if (!urb->buffer || urb->buffer_length < sizeof(*dstat)) { -+ debug("invalid urb! "); -+ return; -+ } -+ -+ switch (dev->dfu_state) { -+ case DFU_STATE_dfuDNLOAD_SYNC: -+ case DFU_STATE_dfuDNBUSY: -+#if 0 -+ if (fsr & AT91C_MC_PROGE) { -+ debug("errPROG "); -+ dev->dfu_status = DFU_STATUS_errPROG; -+ dev->dfu_state = DFU_STATE_dfuERROR; -+ } else if (fsr & AT91C_MC_LOCKE) { -+ debug("errWRITE "); -+ dev->dfu_status = DFU_STATUS_errWRITE; -+ dev->dfu_state = DFU_STATE_dfuERROR; -+ } else if (fsr & AT91C_MC_FRDY) { -+#endif -+ debug("DNLOAD_IDLE "); -+ dev->dfu_state = DFU_STATE_dfuDNLOAD_IDLE; -+#if 0 -+ } else { -+ debug("DNBUSY "); -+ dev->dfu_state = DFU_STATE_dfuDNBUSY; -+ } -+#endif -+ break; -+ case DFU_STATE_dfuMANIFEST_SYNC: -+ break; -+ default: -+ //return; -+ break; -+ } -+ -+ /* send status response */ -+ dstat->bStatus = dev->dfu_status; -+ dstat->bState = dev->dfu_state; -+ dstat->iString = 0; -+ /* FIXME: set dstat->bwPollTimeout */ -+ urb->actual_length = MIN(sizeof(*dstat), max); -+ -+ /* we don't need to explicitly send data here, will -+ * be done by the original caller! */ -+} -+ -+static void handle_getstate(struct urb *urb, int max) -+{ -+ debug("getstate "); -+ -+ if (!urb->buffer || urb->buffer_length < sizeof(u_int8_t)) { -+ debug("invalid urb! "); -+ return; -+ } -+ -+ urb->buffer[0] = urb->device->dfu_state & 0xff; -+ urb->actual_length = sizeof(u_int8_t); -+} -+ -+#ifndef CONFIG_USBD_PRODUCTID_DFU -+#define CONFIG_USBD_PRODUCTID_DFU CONFIG_USBD_PRODUCTID_CDCACM -+#endif -+ -+static const struct usb_device_descriptor dfu_dev_descriptor = { -+ .bLength = USB_DT_DEVICE_SIZE, -+ .bDescriptorType = USB_DT_DEVICE, -+ .bcdUSB = 0x0100, -+ .bDeviceClass = 0x00, -+ .bDeviceSubClass = 0x00, -+ .bDeviceProtocol = 0x00, -+ .bMaxPacketSize0 = EP0_MAX_PACKET_SIZE, -+ .idVendor = CONFIG_USBD_VENDORID, -+ .idProduct = CONFIG_USBD_PRODUCTID_DFU, -+ .bcdDevice = 0x0000, -+ .iManufacturer = DFU_STR_MANUFACTURER, -+ .iProduct = DFU_STR_PRODUCT, -+ .iSerialNumber = DFU_STR_SERIAL, -+ .bNumConfigurations = 0x01, -+}; -+ -+static const struct _dfu_desc dfu_cfg_descriptor = { -+ .ucfg = { -+ .bLength = USB_DT_CONFIG_SIZE, -+ .bDescriptorType = USB_DT_CONFIG, -+ .wTotalLength = USB_DT_CONFIG_SIZE + -+ DFU_NUM_ALTERNATES * USB_DT_INTERFACE_SIZE + -+ USB_DT_DFU_SIZE, -+ .bNumInterfaces = 5, -+ .bConfigurationValue = 1, -+ .iConfiguration = DFU_STR_CONFIG, -+ .bmAttributes = BMATTRIBUTE_RESERVED, -+ .bMaxPower = 50, -+ }, -+ .uif[0] = { -+ .bLength = USB_DT_INTERFACE_SIZE, -+ .bDescriptorType = USB_DT_INTERFACE, -+ .bInterfaceNumber = 0x00, -+ .bAlternateSetting = 0x00, -+ .bNumEndpoints = 0x00, -+ .bInterfaceClass = 0xfe, -+ .bInterfaceSubClass = 0x01, -+ .bInterfaceProtocol = 0x02, -+ .iInterface = DFU_STR_ALT0, -+ }, -+ .uif[1] = { -+ .bLength = USB_DT_INTERFACE_SIZE, -+ .bDescriptorType = USB_DT_INTERFACE, -+ .bInterfaceNumber = 0x00, -+ .bAlternateSetting = 0x01, -+ .bNumEndpoints = 0x00, -+ .bInterfaceClass = 0xfe, -+ .bInterfaceSubClass = 0x01, -+ .bInterfaceProtocol = 0x02, -+ .iInterface = DFU_STR_ALT1, -+ }, -+ .uif[2] = { -+ .bLength = USB_DT_INTERFACE_SIZE, -+ .bDescriptorType = USB_DT_INTERFACE, -+ .bInterfaceNumber = 0x00, -+ .bAlternateSetting = 0x02, -+ .bNumEndpoints = 0x00, -+ .bInterfaceClass = 0xfe, -+ .bInterfaceSubClass = 0x01, -+ .bInterfaceProtocol = 0x02, -+ .iInterface = DFU_STR_ALT2, -+ }, -+ .uif[3] = { -+ .bLength = USB_DT_INTERFACE_SIZE, -+ .bDescriptorType = USB_DT_INTERFACE, -+ .bInterfaceNumber = 0x00, -+ .bAlternateSetting = 0x03, -+ .bNumEndpoints = 0x00, -+ .bInterfaceClass = 0xfe, -+ .bInterfaceSubClass = 0x01, -+ .bInterfaceProtocol = 0x02, -+ .iInterface = DFU_STR_ALT3, -+ }, -+ .uif[4] = { -+ .bLength = USB_DT_INTERFACE_SIZE, -+ .bDescriptorType = USB_DT_INTERFACE, -+ .bInterfaceNumber = 0x00, -+ .bAlternateSetting = 0x04, -+ .bNumEndpoints = 0x00, -+ .bInterfaceClass = 0xfe, -+ .bInterfaceSubClass = 0x01, -+ .bInterfaceProtocol = 0x02, -+ .iInterface = DFU_STR_ALT4, -+ }, -+ .uif[5] = { -+ .bLength = USB_DT_INTERFACE_SIZE, -+ .bDescriptorType = USB_DT_INTERFACE, -+ .bInterfaceNumber = 0x00, -+ .bAlternateSetting = 0x05, -+ .bNumEndpoints = 0x00, -+ .bInterfaceClass = 0xfe, -+ .bInterfaceSubClass = 0x01, -+ .bInterfaceProtocol = 0x02, -+ .iInterface = DFU_STR_ALT5, -+ }, -+ .func_dfu = DFU_FUNC_DESC, -+}; -+ -+int dfu_ep0_handler(struct urb *urb) -+{ -+ int rc, ret = RET_NOTHING; -+ u_int8_t req = urb->device_request.bRequest; -+ u_int16_t val = urb->device_request.wValue; -+ u_int16_t len = urb->device_request.wLength; -+ struct usb_device_instance *dev = urb->device; -+ -+ debug("dfu_ep0(req=0x%x, val=0x%x, len=%u) old_state = %u ", -+ req, val, len, dev->dfu_state); -+ -+ switch (dev->dfu_state) { -+ case DFU_STATE_appIDLE: -+ switch (req) { -+ case USB_REQ_DFU_GETSTATUS: -+ handle_getstatus(urb, len); -+ break; -+ case USB_REQ_DFU_GETSTATE: -+ handle_getstate(urb, len); -+ break; -+ case USB_REQ_DFU_DETACH: -+ dev->dfu_state = DFU_STATE_appDETACH; -+ ret = RET_ZLP; -+ goto out; -+ break; -+ default: -+ ret = RET_STALL; -+ } -+ break; -+ case DFU_STATE_appDETACH: -+ switch (req) { -+ case USB_REQ_DFU_GETSTATUS: -+ handle_getstatus(urb, len); -+ break; -+ case USB_REQ_DFU_GETSTATE: -+ handle_getstate(urb, len); -+ break; -+ default: -+ dev->dfu_state = DFU_STATE_appIDLE; -+ ret = RET_STALL; -+ goto out; -+ break; -+ } -+ /* FIXME: implement timer to return to appIDLE */ -+ break; -+ case DFU_STATE_dfuIDLE: -+ switch (req) { -+ case USB_REQ_DFU_DNLOAD: -+ if (len == 0) { -+ dev->dfu_state = DFU_STATE_dfuERROR; -+ ret = RET_STALL; -+ goto out; -+ } -+ dev->dfu_state = DFU_STATE_dfuDNLOAD_SYNC; -+ ret = handle_dnload(urb, val, len, 1); -+ break; -+ case USB_REQ_DFU_UPLOAD: -+ dev->dfu_state = DFU_STATE_dfuUPLOAD_IDLE; -+ handle_upload(urb, val, len, 1); -+ break; -+ case USB_REQ_DFU_ABORT: -+ /* no zlp? */ -+ ret = RET_ZLP; -+ break; -+ case USB_REQ_DFU_GETSTATUS: -+ handle_getstatus(urb, len); -+ break; -+ case USB_REQ_DFU_GETSTATE: -+ handle_getstate(urb, len); -+ break; -+ case USB_REQ_DFU_DETACH: -+ /* Proprietary extension: 'detach' from idle mode and -+ * get back to runtime mode in case of USB Reset. As -+ * much as I dislike this, we just can't use every USB -+ * bus reset to switch back to runtime mode, since at -+ * least the Linux USB stack likes to send a number of resets -+ * in a row :( */ -+ dev->dfu_state = DFU_STATE_dfuMANIFEST_WAIT_RST; -+ break; -+ default: -+ dev->dfu_state = DFU_STATE_dfuERROR; -+ ret = RET_STALL; -+ goto out; -+ break; -+ } -+ break; -+ case DFU_STATE_dfuDNLOAD_SYNC: -+ switch (req) { -+ case USB_REQ_DFU_GETSTATUS: -+ handle_getstatus(urb, len); -+ /* FIXME: state transition depending on block completeness */ -+ break; -+ case USB_REQ_DFU_GETSTATE: -+ handle_getstate(urb, len); -+ break; -+ default: -+ dev->dfu_state = DFU_STATE_dfuERROR; -+ ret = RET_STALL; -+ goto out; -+ } -+ break; -+ case DFU_STATE_dfuDNBUSY: -+ switch (req) { -+ case USB_REQ_DFU_GETSTATUS: -+ /* FIXME: only accept getstatus if bwPollTimeout -+ * has elapsed */ -+ handle_getstatus(urb, len); -+ break; -+ default: -+ dev->dfu_state = DFU_STATE_dfuERROR; -+ ret = RET_STALL; -+ goto out; -+ } -+ break; -+ case DFU_STATE_dfuDNLOAD_IDLE: -+ switch (req) { -+ case USB_REQ_DFU_DNLOAD: -+ dev->dfu_state = DFU_STATE_dfuDNLOAD_SYNC; -+ ret = handle_dnload(urb, val, len, 0); -+ break; -+ case USB_REQ_DFU_ABORT: -+ dev->dfu_state = DFU_STATE_dfuIDLE; -+ ret = RET_ZLP; -+ break; -+ case USB_REQ_DFU_GETSTATUS: -+ handle_getstatus(urb, len); -+ break; -+ case USB_REQ_DFU_GETSTATE: -+ handle_getstate(urb, len); -+ break; -+ default: -+ dev->dfu_state = DFU_STATE_dfuERROR; -+ ret = RET_STALL; -+ break; -+ } -+ break; -+ case DFU_STATE_dfuMANIFEST_SYNC: -+ switch (req) { -+ case USB_REQ_DFU_GETSTATUS: -+ /* We're MainfestationTolerant */ -+ dev->dfu_state = DFU_STATE_dfuIDLE; -+ handle_getstatus(urb, len); -+ break; -+ case USB_REQ_DFU_GETSTATE: -+ handle_getstate(urb, len); -+ break; -+ default: -+ dev->dfu_state = DFU_STATE_dfuERROR; -+ ret = RET_STALL; -+ break; -+ } -+ break; -+ case DFU_STATE_dfuMANIFEST: -+ /* we should never go here */ -+ dev->dfu_state = DFU_STATE_dfuERROR; -+ ret = RET_STALL; -+ break; -+ case DFU_STATE_dfuMANIFEST_WAIT_RST: -+ /* we should never go here */ -+ break; -+ case DFU_STATE_dfuUPLOAD_IDLE: -+ switch (req) { -+ case USB_REQ_DFU_UPLOAD: -+ /* state transition if less data then requested */ -+ rc = handle_upload(urb, val, len, 0); -+ if (rc >= 0 && rc < len) -+ dev->dfu_state = DFU_STATE_dfuIDLE; -+ break; -+ case USB_REQ_DFU_ABORT: -+ dev->dfu_state = DFU_STATE_dfuIDLE; -+ /* no zlp? */ -+ ret = RET_ZLP; -+ break; -+ case USB_REQ_DFU_GETSTATUS: -+ handle_getstatus(urb, len); -+ break; -+ case USB_REQ_DFU_GETSTATE: -+ handle_getstate(urb, len); -+ break; -+ default: -+ dev->dfu_state = DFU_STATE_dfuERROR; -+ ret = RET_STALL; -+ break; -+ } -+ break; -+ case DFU_STATE_dfuERROR: -+ switch (req) { -+ case USB_REQ_DFU_GETSTATUS: -+ handle_getstatus(urb, len); -+ break; -+ case USB_REQ_DFU_GETSTATE: -+ handle_getstate(urb, len); -+ break; -+ case USB_REQ_DFU_CLRSTATUS: -+ dev->dfu_state = DFU_STATE_dfuIDLE; -+ dev->dfu_status = DFU_STATUS_OK; -+ /* no zlp? */ -+ ret = RET_ZLP; -+ break; -+ default: -+ dev->dfu_state = DFU_STATE_dfuERROR; -+ ret = RET_STALL; -+ break; -+ } -+ break; -+ default: -+ return DFU_EP0_UNHANDLED; -+ break; -+ } -+ -+out: -+ debug("new_state = %u, ret = %u\n", dev->dfu_state, ret); -+ -+ switch (ret) { -+ case RET_ZLP: -+ //udc_ep0_send_zlp(); -+ urb->actual_length = 0; -+ return DFU_EP0_ZLP; -+ break; -+ case RET_STALL: -+ //udc_ep0_send_stall(); -+ return DFU_EP0_STALL; -+ break; -+ case RET_NOTHING: -+ break; -+ } -+ -+ return DFU_EP0_DATA; -+} -+ -+void str2wide (char *str, u16 * wide); -+static struct usb_string_descriptor *create_usbstring(char *string) -+{ -+ struct usb_string_descriptor *strdesc; -+ int size = sizeof(*strdesc) + strlen(string)*2; -+ -+ if (size > 255) -+ return NULL; -+ -+ strdesc = malloc(size); -+ if (!strdesc) -+ return NULL; -+ -+ strdesc->bLength = size; -+ strdesc->bDescriptorType = USB_DT_STRING; -+ str2wide(string, strdesc->wData); -+ -+ return strdesc; -+} -+ -+ -+static void dfu_init_strings(struct usb_device_instance *dev) -+{ -+ int i; -+ struct usb_string_descriptor *strdesc; -+ -+ strdesc = create_usbstring(CONFIG_DFU_CFG_STR); -+ usb_strings[DFU_STR_CONFIG] = strdesc; -+ -+ for (i = 0; i < DFU_NUM_ALTERNATES; i++) { -+ if (i == 0) { -+ strdesc = create_usbstring(CONFIG_DFU_ALT0_STR); -+ } else { -+ struct part_info *part = get_partition_nand(i-1); -+ -+ if (part) -+ strdesc = create_usbstring(part->name); -+ else -+ strdesc = -+ create_usbstring("undefined partition"); -+ } -+ if (!strdesc) -+ continue; -+ usb_strings[STR_COUNT+i+1] = strdesc; -+ } -+} -+ -+int dfu_init_instance(struct usb_device_instance *dev) -+{ -+ dev->dfu_dev_desc = &dfu_dev_descriptor; -+ dev->dfu_cfg_desc = &dfu_cfg_descriptor; -+ dev->dfu_state = DFU_STATE_appIDLE; -+ dev->dfu_status = DFU_STATUS_OK; -+ -+ if (system_dfu_state) -+ printf("SURPRISE: system_dfu_state is already set\n"); -+ system_dfu_state = &dev->dfu_state; -+ -+ dfu_init_strings(dev); -+ -+ return 0; -+} -+ -+static int stdout_switched; -+ -+/* event handler for usb device state events */ -+void dfu_event(struct usb_device_instance *device, -+ usb_device_event_t event, int data) -+{ -+ char *out; -+ -+ switch (event) { -+ case DEVICE_RESET: -+ switch (device->dfu_state) { -+ case DFU_STATE_appDETACH: -+ device->dfu_state = DFU_STATE_dfuIDLE; -+ out = getenv("stdout"); -+ if (out && !strcmp(out, "usbtty")) { -+ setenv("stdout", "vga"); -+ setenv("stderr", "vga"); -+ stdout_switched = 1; -+ } -+ printf("DFU: Switching to DFU Mode\n"); -+ break; -+ case DFU_STATE_dfuMANIFEST_WAIT_RST: -+ device->dfu_state = DFU_STATE_appIDLE; -+ printf("DFU: Switching back to Runtime mode\n"); -+ if (stdout_switched) { -+ setenv("stdout", "usbtty"); -+ setenv("stderr", "usbtty"); -+ stdout_switched = 0; -+ } -+ break; -+ default: -+ break; -+ } -+ break; -+ case DEVICE_CONFIGURED: -+ case DEVICE_DE_CONFIGURED: -+ debug("SET_CONFIGURATION(%u) ", device->configuration); -+ /* fallthrough */ -+ case DEVICE_SET_INTERFACE: -+ debug("SET_INTERFACE(%u,%u) old_state = %u ", -+ device->interface, device->alternate, -+ device->dfu_state); -+ switch (device->dfu_state) { -+ case DFU_STATE_appIDLE: -+ case DFU_STATE_appDETACH: -+ case DFU_STATE_dfuIDLE: -+ case DFU_STATE_dfuMANIFEST_WAIT_RST: -+ /* do nothing, we're fine */ -+ break; -+ case DFU_STATE_dfuDNLOAD_SYNC: -+ case DFU_STATE_dfuDNBUSY: -+ case DFU_STATE_dfuDNLOAD_IDLE: -+ case DFU_STATE_dfuMANIFEST: -+ device->dfu_state = DFU_STATE_dfuERROR; -+ device->dfu_status = DFU_STATUS_errNOTDONE; -+ /* FIXME: free malloc()ed buffer! */ -+ break; -+ case DFU_STATE_dfuMANIFEST_SYNC: -+ case DFU_STATE_dfuUPLOAD_IDLE: -+ case DFU_STATE_dfuERROR: -+ device->dfu_state = DFU_STATE_dfuERROR; -+ device->dfu_status = DFU_STATUS_errUNKNOWN; -+ break; -+ } -+ debug("new_state = %u\n", device->dfu_state); -+ break; -+ default: -+ break; -+ } -+} -+#endif /* CONFIG_USBD_DFU */ -Index: u-boot/drivers/Makefile -=================================================================== ---- u-boot.orig/drivers/Makefile -+++ u-boot/drivers/Makefile -@@ -47,7 +47,7 @@ - status_led.o sym53c8xx.o systemace.o ahci.o \ - ti_pci1410a.o tigon3.o tsec.o \ - tsi108_eth.o tsi108_i2c.o tsi108_pci.o \ -- usbdcore.o usbdcore_ep0.o usbdcore_omap1510.o usbdcore_s3c2410.o usbtty.o \ -+ usbdcore.o usbdfu.o usbdcore_ep0.o usbdcore_omap1510.o usbdcore_s3c2410.o usbtty.o \ - videomodes.o w83c553f.o \ - ks8695eth.o \ - pcf50606.o \ -Index: u-boot/drivers/usbdcore.c -=================================================================== ---- u-boot.orig/drivers/usbdcore.c -+++ u-boot/drivers/usbdcore.c -@@ -31,6 +31,7 @@ - - #include <malloc.h> - #include "usbdcore.h" -+#include <usb_dfu.h> - - #define MAX_INTERFACES 2 - -@@ -212,6 +213,10 @@ - */ - struct usb_device_descriptor *usbd_device_device_descriptor (struct usb_device_instance *device, int port) - { -+#ifdef CONFIG_USBD_DFU -+ if (device->dfu_state != DFU_STATE_appIDLE) -+ return device->dfu_dev_desc; -+#endif - return (device->device_descriptor); - } - -@@ -232,6 +237,10 @@ - if (!(configuration_instance = usbd_device_configuration_instance (device, port, configuration))) { - return NULL; - } -+#ifdef CONFIG_USBD_DFU -+ if (device->dfu_state != DFU_STATE_appIDLE) -+ return (&device->dfu_cfg_desc->ucfg); -+#endif - return (configuration_instance->configuration_descriptor); - } - -@@ -253,6 +262,13 @@ - if (!(interface_instance = usbd_device_interface_instance (device, port, configuration, interface))) { - return NULL; - } -+#ifdef CONFIG_USBD_DFU -+ if (device->dfu_state != DFU_STATE_appIDLE) { -+ if (alternate < 0 || alternate >= DFU_NUM_ALTERNATES) -+ return NULL; -+ return &device->dfu_cfg_desc->uif[alternate]; -+ } -+#endif - if ((alternate < 0) || (alternate >= interface_instance->alternates)) { - return NULL; - } -@@ -681,4 +697,7 @@ - /* usbdbg("calling device->event"); */ - device->event(device, event, data); - } -+#ifdef CONFIG_USBD_DFU -+ dfu_event(device, event, data); -+#endif - } -Index: u-boot/drivers/usbtty.c -=================================================================== ---- u-boot.orig/drivers/usbtty.c -+++ u-boot/drivers/usbtty.c -@@ -31,6 +31,8 @@ - #include "usbtty.h" - #include "usb_cdc_acm.h" - #include "usbdescriptors.h" -+#include <usb_dfu_descriptors.h> -+#include <usb_dfu.h> - #include <config.h> /* If defined, override Linux identifiers with - * vendor specific ones */ - -@@ -118,7 +120,7 @@ - static unsigned short rx_endpoint = 0; - static unsigned short tx_endpoint = 0; - static unsigned short interface_count = 0; --static struct usb_string_descriptor *usbtty_string_table[STR_COUNT]; -+static struct usb_string_descriptor *usbtty_string_table[NUM_STRINGS]; - - /* USB Descriptor Strings */ - static u8 wstrLang[4] = {4,USB_DT_STRING,0x9,0x4}; -@@ -169,6 +171,10 @@ - struct usb_interface_descriptor data_class_interface; - struct usb_endpoint_descriptor - data_endpoints[NUM_ENDPOINTS-1] __attribute__((packed)); -+#ifdef CONFIG_USBD_DFU -+ struct usb_interface_descriptor uif_dfu; -+ struct usb_dfu_func_descriptor func_dfu; -+#endif - } __attribute__((packed)); - - static struct acm_config_desc acm_configuration_descriptors[NUM_CONFIGS] = { -@@ -179,7 +185,11 @@ - .bDescriptorType = USB_DT_CONFIG, - .wTotalLength = - cpu_to_le16(sizeof(struct acm_config_desc)), -+#ifdef CONFIG_USBD_DFU -+ .bNumInterfaces = NUM_ACM_INTERFACES +1, -+#else - .bNumInterfaces = NUM_ACM_INTERFACES, -+#endif - .bConfigurationValue = 1, - .iConfiguration = STR_CONFIG, - .bmAttributes = -@@ -278,6 +288,11 @@ - .bInterval = 0xFF, - }, - }, -+#ifdef CONFIG_USBD_DFU -+ /* Interface 3 */ -+ .uif_dfu = DFU_RT_IF_DESC, -+ .func_dfu = DFU_FUNC_DESC, -+#endif - }, - }; - -@@ -390,7 +405,7 @@ - void usbtty_poll (void); - - /* utility function for converting char* to wide string used by USB */ --static void str2wide (char *str, u16 * wide) -+void str2wide (char *str, u16 * wide) - { - int i; - for (i = 0; i < strlen (str) && str[i]; i++){ -@@ -652,6 +667,9 @@ - device_instance->bus = bus_instance; - device_instance->configurations = NUM_CONFIGS; - device_instance->configuration_instance_array = config_instance; -+#ifdef CONFIG_USBD_DFU -+ dfu_init_instance(device_instance); -+#endif - - /* initialize bus instance */ - memset (bus_instance, 0, sizeof (struct usb_bus_instance)); -Index: u-boot/include/configs/neo1973_gta01.h -=================================================================== ---- u-boot.orig/include/configs/neo1973_gta01.h -+++ u-boot/include/configs/neo1973_gta01.h -@@ -167,7 +167,7 @@ - */ - #define CONFIG_STACKSIZE (128*1024) /* regular stack */ - #ifdef CONFIG_USE_IRQ --#define CONFIG_STACKSIZE_IRQ (4*1024) /* IRQ stack */ -+#define CONFIG_STACKSIZE_IRQ (8*1024) /* IRQ stack */ - #define CONFIG_STACKSIZE_FIQ (4*1024) /* FIQ stack */ - #endif - -@@ -184,6 +184,10 @@ - #define CONFIG_USBD_MANUFACTURER "Openmoko, Inc" - #define CONFIG_USBD_PRODUCT_NAME "Neo1973 Bootloader " U_BOOT_VERSION - #define CONFIG_EXTRA_ENV_SETTINGS "usbtty=cdc_acm\0" -+#define CONFIG_USBD_DFU 1 -+#define CONFIG_USBD_DFU_XFER_SIZE 4096 /* 0x4000 */ -+#define CONFIG_USBD_DFU_INTERFACE 2 -+ - - /*----------------------------------------------------------------------- - * Physical Memory Map -Index: u-boot/include/usb_dfu.h -=================================================================== ---- /dev/null -+++ u-boot/include/usb_dfu.h -@@ -0,0 +1,99 @@ -+#ifndef _DFU_H -+#define _DFU_H -+ -+/* USB Device Firmware Update Implementation for u-boot -+ * (C) 2007 by Openmoko, Inc. -+ * Author: Harald Welte <laforge@openmoko.org> -+ * -+ * based on: USB Device Firmware Update Implementation for OpenPCD -+ * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de> -+ * -+ * This ought to be compliant to the USB DFU Spec 1.0 as available from -+ * http://www.usb.org/developers/devclass_docs/usbdfu10.pdf -+ * -+ * 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 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, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#include <asm/types.h> -+#include <usbdescriptors.h> -+#include <usb_dfu_descriptors.h> -+#include <config.h> -+ -+/* USB DFU functional descriptor */ -+#define DFU_FUNC_DESC { \ -+ .bLength = USB_DT_DFU_SIZE, \ -+ .bDescriptorType = USB_DT_DFU, \ -+ .bmAttributes = USB_DFU_CAN_UPLOAD | USB_DFU_CAN_DOWNLOAD | USB_DFU_MANIFEST_TOL, \ -+ .wDetachTimeOut = 0xff00, \ -+ .wTransferSize = CONFIG_USBD_DFU_XFER_SIZE, \ -+ .bcdDFUVersion = 0x0100, \ -+} -+ -+/* USB Interface descriptor in Runtime mode */ -+#define DFU_RT_IF_DESC { \ -+ .bLength = USB_DT_INTERFACE_SIZE, \ -+ .bDescriptorType = USB_DT_INTERFACE, \ -+ .bInterfaceNumber = CONFIG_USBD_DFU_INTERFACE, \ -+ .bAlternateSetting = 0x00, \ -+ .bNumEndpoints = 0x00, \ -+ .bInterfaceClass = 0xfe, \ -+ .bInterfaceSubClass = 0x01, \ -+ .bInterfaceProtocol = 0x01, \ -+ .iInterface = DFU_STR_CONFIG, \ -+} -+ -+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) -+ -+#define DFU_NUM_ALTERNATES 6 -+ -+#define DFU_STR_MANUFACTURER STR_MANUFACTURER -+#define DFU_STR_PRODUCT STR_PRODUCT -+#define DFU_STR_SERIAL STR_SERIAL -+#define DFU_STR_CONFIG (STR_COUNT) -+#define DFU_STR_ALT0 (STR_COUNT+1) -+#define DFU_STR_ALT1 (STR_COUNT+2) -+#define DFU_STR_ALT2 (STR_COUNT+3) -+#define DFU_STR_ALT3 (STR_COUNT+4) -+#define DFU_STR_ALT4 (STR_COUNT+5) -+#define DFU_STR_ALT5 (STR_COUNT+6) -+#define DFU_STR_COUNT (STR_COUNT+7) -+ -+#define DFU_NUM_STRINGS (STR_COUNT+8) -+ -+#define CONFIG_DFU_CFG_STR "USB Device Firmware Upgrade" -+#define CONFIG_DFU_ALT0_STR "RAM 0x32000000" -+ -+struct _dfu_desc { -+ struct usb_configuration_descriptor ucfg; -+ struct usb_interface_descriptor uif[DFU_NUM_ALTERNATES]; -+ struct usb_dfu_func_descriptor func_dfu; -+}; -+ -+int dfu_init_instance(struct usb_device_instance *dev); -+ -+#define DFU_EP0_NONE 0 -+#define DFU_EP0_UNHANDLED 1 -+#define DFU_EP0_STALL 2 -+#define DFU_EP0_ZLP 3 -+#define DFU_EP0_DATA 4 -+ -+extern volatile enum dfu_state *system_dfu_state; /* for 3rd parties */ -+ -+int dfu_ep0_handler(struct urb *urb); -+ -+void dfu_event(struct usb_device_instance *device, -+ usb_device_event_t event, int data); -+ -+#endif /* _DFU_H */ -Index: u-boot/include/usb_dfu_descriptors.h -=================================================================== ---- /dev/null -+++ u-boot/include/usb_dfu_descriptors.h -@@ -0,0 +1,94 @@ -+#ifndef _USB_DFU_H -+#define _USB_DFU_H -+/* USB Device Firmware Update Implementation for OpenPCD -+ * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de> -+ * -+ * Protocol definitions for USB DFU -+ * -+ * This ought to be compliant to the USB DFU Spec 1.0 as available from -+ * http://www.usb.org/developers/devclass_docs/usbdfu10.pdf -+ * -+ * 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 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, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#include <linux/types.h> -+ -+#define USB_DT_DFU 0x21 -+ -+struct usb_dfu_func_descriptor { -+ u_int8_t bLength; -+ u_int8_t bDescriptorType; -+ u_int8_t bmAttributes; -+#define USB_DFU_CAN_DOWNLOAD (1 << 0) -+#define USB_DFU_CAN_UPLOAD (1 << 1) -+#define USB_DFU_MANIFEST_TOL (1 << 2) -+#define USB_DFU_WILL_DETACH (1 << 3) -+ u_int16_t wDetachTimeOut; -+ u_int16_t wTransferSize; -+ u_int16_t bcdDFUVersion; -+} __attribute__ ((packed)); -+ -+#define USB_DT_DFU_SIZE 9 -+ -+#define USB_TYPE_DFU (USB_TYPE_CLASS|USB_RECIP_INTERFACE) -+ -+/* DFU class-specific requests (Section 3, DFU Rev 1.1) */ -+#define USB_REQ_DFU_DETACH 0x00 -+#define USB_REQ_DFU_DNLOAD 0x01 -+#define USB_REQ_DFU_UPLOAD 0x02 -+#define USB_REQ_DFU_GETSTATUS 0x03 -+#define USB_REQ_DFU_CLRSTATUS 0x04 -+#define USB_REQ_DFU_GETSTATE 0x05 -+#define USB_REQ_DFU_ABORT 0x06 -+ -+struct dfu_status { -+ u_int8_t bStatus; -+ u_int8_t bwPollTimeout[3]; -+ u_int8_t bState; -+ u_int8_t iString; -+} __attribute__((packed)); -+ -+#define DFU_STATUS_OK 0x00 -+#define DFU_STATUS_errTARGET 0x01 -+#define DFU_STATUS_errFILE 0x02 -+#define DFU_STATUS_errWRITE 0x03 -+#define DFU_STATUS_errERASE 0x04 -+#define DFU_STATUS_errCHECK_ERASED 0x05 -+#define DFU_STATUS_errPROG 0x06 -+#define DFU_STATUS_errVERIFY 0x07 -+#define DFU_STATUS_errADDRESS 0x08 -+#define DFU_STATUS_errNOTDONE 0x09 -+#define DFU_STATUS_errFIRMWARE 0x0a -+#define DFU_STATUS_errVENDOR 0x0b -+#define DFU_STATUS_errUSBR 0x0c -+#define DFU_STATUS_errPOR 0x0d -+#define DFU_STATUS_errUNKNOWN 0x0e -+#define DFU_STATUS_errSTALLEDPKT 0x0f -+ -+enum dfu_state { -+ DFU_STATE_appIDLE = 0, -+ DFU_STATE_appDETACH = 1, -+ DFU_STATE_dfuIDLE = 2, -+ DFU_STATE_dfuDNLOAD_SYNC = 3, -+ DFU_STATE_dfuDNBUSY = 4, -+ DFU_STATE_dfuDNLOAD_IDLE = 5, -+ DFU_STATE_dfuMANIFEST_SYNC = 6, -+ DFU_STATE_dfuMANIFEST = 7, -+ DFU_STATE_dfuMANIFEST_WAIT_RST = 8, -+ DFU_STATE_dfuUPLOAD_IDLE = 9, -+ DFU_STATE_dfuERROR = 10, -+}; -+ -+#endif /* _USB_DFU_H */ -Index: u-boot/include/usbdcore.h -=================================================================== ---- u-boot.orig/include/usbdcore.h -+++ u-boot/include/usbdcore.h -@@ -33,6 +33,7 @@ - - #include <common.h> - #include "usbdescriptors.h" -+#include <usb_dfu_descriptors.h> - - - #define MAX_URBS_QUEUED 5 -@@ -475,7 +476,11 @@ - * function driver to inform it that data has arrived. - */ - -+#ifdef CONFIG_USBD_DFU -+#define URB_BUF_SIZE (128+CONFIG_USBD_DFU_XFER_SIZE) -+#else - #define URB_BUF_SIZE 128 /* in linux we'd malloc this, but in u-boot we prefer static data */ -+#endif - struct urb { - - struct usb_endpoint_instance *endpoint; -@@ -603,6 +608,12 @@ - unsigned long usbd_rxtx_timestamp; - unsigned long usbd_last_rxtx_timestamp; - -+#ifdef CONFIG_USBD_DFU -+ const struct usb_device_descriptor *dfu_dev_desc; -+ const struct _dfu_desc *dfu_cfg_desc; -+ enum dfu_state dfu_state; -+ u_int8_t dfu_status; -+#endif - }; - - /* Bus Interface configuration structure -@@ -632,6 +643,8 @@ - extern char *usbd_device_requests[]; - extern char *usbd_device_descriptors[]; - -+extern struct usb_string_descriptor **usb_strings; -+ - void urb_link_init (urb_link * ul); - void urb_detach (struct urb *urb); - urb_link *first_urb_link (urb_link * hd); -Index: u-boot/drivers/usbtty.h -=================================================================== ---- u-boot.orig/drivers/usbtty.h -+++ u-boot/drivers/usbtty.h -@@ -71,4 +71,10 @@ - #define STR_CTRL_INTERFACE 0x06 - #define STR_COUNT 0x07 - -+#ifdef CONFIG_USBD_DFU -+#define NUM_STRINGS DFU_STR_COUNT -+#else -+#define NUM_STRINGS STR_COUNT -+#endif -+ - #endif -Index: u-boot/include/configs/qt2410.h -=================================================================== ---- u-boot.orig/include/configs/qt2410.h -+++ u-boot/include/configs/qt2410.h -@@ -199,7 +199,8 @@ - #define CONFIG_USBD_PRODUCT_NAME "QT2410 Bootloader " U_BOOT_VERSION - #define CONFIG_EXTRA_ENV_SETTINGS "usbtty=cdc_acm\0" - #define CONFIG_USBD_DFU 1 --#define CONFIG_USBD_DFU_XFER_SIZE 0x4000 -+#define CONFIG_USBD_DFU_XFER_SIZE 4096 -+#define CONFIG_USBD_DFU_INTERFACE 2 - - /*----------------------------------------------------------------------- - * Physical Memory Map -Index: u-boot/tools/Makefile -=================================================================== ---- u-boot.orig/tools/Makefile -+++ u-boot/tools/Makefile -@@ -21,10 +21,10 @@ - # MA 02111-1307 USA - # - --BIN_FILES = img2srec$(SFX) mkimage$(SFX) envcrc$(SFX) gen_eth_addr$(SFX) bmp_logo$(SFX) -+BIN_FILES = img2srec$(SFX) mkimage$(SFX) envcrc$(SFX) gen_eth_addr$(SFX) bmp_logo$(SFX) mkudfu$(SFX) - - OBJ_LINKS = environment.o crc32.o --OBJ_FILES = img2srec.o mkimage.o envcrc.o gen_eth_addr.o bmp_logo.o -+OBJ_FILES = img2srec.o mkimage.o envcrc.o gen_eth_addr.o bmp_logo.o mkudfu.o - - ifeq ($(ARCH),mips) - BIN_FILES += inca-swap-bytes$(SFX) -@@ -137,6 +137,10 @@ - $(CC) $(CFLAGS) $(HOST_LDFLAGS) -o $@ $^ - $(STRIP) $@ - -+$(obj)mkudfu$(SFX): $(obj)mkudfu.o -+ $(CC) $(CFLAGS) $(HOST_LDFLAGS) -o $@ $^ -+ $(STRIP) $@ -+ - $(obj)ncb$(SFX): $(obj)ncb.o - $(CC) $(CFLAGS) $(HOST_LDFLAGS) -o $@ $^ - $(STRIP) $@ -Index: u-boot/tools/mkudfu.c -=================================================================== ---- /dev/null -+++ u-boot/tools/mkudfu.c -@@ -0,0 +1,314 @@ -+/* -+ * USB DFU file trailer tool -+ * (C) Copyright by Openmoko, Inc. -+ * Author: Harald Welte <laforge@openmoko.org> -+ * -+ * based on mkimage.c, copyright information as follows: -+ * -+ * (C) Copyright 2000-2004 -+ * DENX Software Engineering -+ * Wolfgang Denk, wd@denx.de -+ * All rights reserved. -+ * -+ * 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 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, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, -+ * MA 02111-1307 USA -+ */ -+ -+#include <errno.h> -+#include <fcntl.h> -+#include <stdio.h> -+#include <stdlib.h> -+#include <string.h> -+#ifndef __WIN32__ -+#include <netinet/in.h> /* for host / network byte order conversions */ -+#endif -+#include <sys/mman.h> -+#include <sys/stat.h> -+#include <time.h> -+#include <unistd.h> -+ -+#if defined(__BEOS__) || defined(__NetBSD__) || defined(__APPLE__) -+#include <inttypes.h> -+#endif -+ -+#ifdef __WIN32__ -+typedef unsigned int __u32; -+ -+#define SWAP_LONG(x) \ -+ ((__u32)( \ -+ (((__u32)(x) & (__u32)0x000000ffUL) << 24) | \ -+ (((__u32)(x) & (__u32)0x0000ff00UL) << 8) | \ -+ (((__u32)(x) & (__u32)0x00ff0000UL) >> 8) | \ -+ (((__u32)(x) & (__u32)0xff000000UL) >> 24) )) -+typedef unsigned char uint8_t; -+typedef unsigned short uint16_t; -+typedef unsigned int uint32_t; -+ -+#define ntohl(a) SWAP_LONG(a) -+#define htonl(a) SWAP_LONG(a) -+#endif /* __WIN32__ */ -+ -+#ifndef O_BINARY /* should be define'd on __WIN32__ */ -+#define O_BINARY 0 -+#endif -+ -+#include <usb_dfu_trailer.h> -+ -+extern int errno; -+ -+#ifndef MAP_FAILED -+#define MAP_FAILED (-1) -+#endif -+ -+static char *cmdname; -+ -+static char *datafile; -+static char *imagefile; -+ -+ -+static void usage() -+{ -+ fprintf (stderr, "%s - create / display u-boot DFU trailer\n", cmdname); -+ fprintf (stderr, "Usage: %s -l image\n" -+ " -l ==> list image header information\n" -+ " %s -v VID -p PID -r REV -d data_file image\n", -+ cmdname, cmdname); -+ fprintf (stderr, " -v ==> set vendor ID to 'VID'\n" -+ " -p ==> set product ID system to 'PID'\n" -+ " -r ==> set hardware revision to 'REV'\n" -+ " -d ==> use 'data_file' as input file\n" -+ ); -+ exit (EXIT_FAILURE); -+} -+ -+static void print_trailer(struct uboot_dfu_trailer *trailer) -+{ -+ printf("===> DFU Trailer information:\n"); -+ printf("Trailer Vers.: %d\n", trailer->version); -+ printf("Trailer Length: %d\n", trailer->length); -+ printf("VendorID: 0x%04x\n", trailer->vendor); -+ printf("ProductID: 0x%04x\n", trailer->product); -+ printf("HW Revision: 0x%04x\n", trailer->revision); -+} -+ -+static void copy_file (int ifd, const char *datafile, int pad) -+{ -+ int dfd; -+ struct stat sbuf; -+ unsigned char *ptr; -+ int tail; -+ int zero = 0; -+ int offset = 0; -+ int size; -+ -+ if ((dfd = open(datafile, O_RDONLY|O_BINARY)) < 0) { -+ fprintf (stderr, "%s: Can't open %s: %s\n", -+ cmdname, datafile, strerror(errno)); -+ exit (EXIT_FAILURE); -+ } -+ -+ if (fstat(dfd, &sbuf) < 0) { -+ fprintf (stderr, "%s: Can't stat %s: %s\n", -+ cmdname, datafile, strerror(errno)); -+ exit (EXIT_FAILURE); -+ } -+ -+ ptr = (unsigned char *)mmap(0, sbuf.st_size, -+ PROT_READ, MAP_SHARED, dfd, 0); -+ if (ptr == (unsigned char *)MAP_FAILED) { -+ fprintf (stderr, "%s: Can't read %s: %s\n", -+ cmdname, datafile, strerror(errno)); -+ exit (EXIT_FAILURE); -+ } -+ -+ size = sbuf.st_size - offset; -+ if (write(ifd, ptr + offset, size) != size) { -+ fprintf (stderr, "%s: Write error on %s: %s\n", -+ cmdname, imagefile, strerror(errno)); -+ exit (EXIT_FAILURE); -+ } -+ -+ if (pad && ((tail = size % 4) != 0)) { -+ -+ if (write(ifd, (char *)&zero, 4-tail) != 4-tail) { -+ fprintf (stderr, "%s: Write error on %s: %s\n", -+ cmdname, imagefile, strerror(errno)); -+ exit (EXIT_FAILURE); -+ } -+ } -+ -+ (void) munmap((void *)ptr, sbuf.st_size); -+ (void) close (dfd); -+} -+ -+ -+int main(int argc, char **argv) -+{ -+ int ifd; -+ int lflag = 0; -+ struct stat sbuf; -+ u_int16_t opt_vendor, opt_product, opt_revision; -+ struct uboot_dfu_trailer _hdr, _mirror, *hdr = &_hdr; -+ -+ opt_vendor = opt_product = opt_revision = 0; -+ -+ cmdname = *argv; -+ -+ while (--argc > 0 && **++argv == '-') { -+ while (*++*argv) { -+ switch (**argv) { -+ case 'l': -+ lflag = 1; -+ break; -+ case 'v': -+ if (--argc <= 0) -+ usage (); -+ opt_vendor = strtoul(*++argv, NULL, 16); -+ goto NXTARG; -+ case 'p': -+ if (--argc <= 0) -+ usage (); -+ opt_product = strtoul(*++argv, NULL, 16); -+ goto NXTARG; -+ case 'r': -+ if (--argc <= 0) -+ usage (); -+ opt_revision = strtoul(*++argv, NULL, 16); -+ goto NXTARG; -+ case 'd': -+ if (--argc <= 0) -+ usage (); -+ datafile = *++argv; -+ goto NXTARG; -+ case 'h': -+ usage(); -+ break; -+ default: -+ usage(); -+ } -+ } -+NXTARG: ; -+ } -+ -+ if (argc != 1) -+ usage(); -+ -+ imagefile = *argv; -+ -+ if (lflag) -+ ifd = open(imagefile, O_RDONLY|O_BINARY); -+ else -+ ifd = open(imagefile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0666); -+ -+ if (ifd < 0) { -+ fprintf (stderr, "%s: Can't open %s: %s\n", -+ cmdname, imagefile, strerror(errno)); -+ exit (EXIT_FAILURE); -+ } -+ -+ if (lflag) { -+ unsigned char *ptr; -+ /* list header information of existing image */ -+ if (fstat(ifd, &sbuf) < 0) { -+ fprintf (stderr, "%s: Can't stat %s: %s\n", -+ cmdname, imagefile, strerror(errno)); -+ exit (EXIT_FAILURE); -+ } -+ -+ if ((unsigned)sbuf.st_size < sizeof(struct uboot_dfu_trailer)) { -+ fprintf (stderr, -+ "%s: Bad size: \"%s\" is no valid image\n", -+ cmdname, imagefile); -+ exit (EXIT_FAILURE); -+ } -+ -+ ptr = (unsigned char *)mmap(0, sbuf.st_size, -+ PROT_READ, MAP_SHARED, ifd, 0); -+ if ((caddr_t)ptr == (caddr_t)-1) { -+ fprintf (stderr, "%s: Can't read %s: %s\n", -+ cmdname, imagefile, strerror(errno)); -+ exit (EXIT_FAILURE); -+ } -+ -+ dfu_trailer_mirror(hdr, ptr+sbuf.st_size); -+ -+ if (hdr->magic != UBOOT_DFU_TRAILER_MAGIC) { -+ fprintf (stderr, -+ "%s: Bad Magic Number: \"%s\" is no valid image\n", -+ cmdname, imagefile); -+ exit (EXIT_FAILURE); -+ } -+ -+ /* for multi-file images we need the data part, too */ -+ print_trailer(hdr); -+ -+ (void) munmap((void *)ptr, sbuf.st_size); -+ (void) close (ifd); -+ -+ exit (EXIT_SUCCESS); -+ } -+ -+ /* if we're not listing: */ -+ -+ copy_file (ifd, datafile, 0); -+ -+ memset (hdr, 0, sizeof(struct uboot_dfu_trailer)); -+ -+ /* Build new header */ -+ hdr->version = UBOOT_DFU_TRAILER_V1; -+ hdr->magic = UBOOT_DFU_TRAILER_MAGIC; -+ hdr->length = sizeof(struct uboot_dfu_trailer); -+ hdr->vendor = opt_vendor; -+ hdr->product = opt_product; -+ hdr->revision = opt_revision; -+ -+ print_trailer(hdr); -+ dfu_trailer_mirror(&_mirror, (unsigned char *)hdr+sizeof(*hdr)); -+ -+ if (write(ifd, &_mirror, sizeof(struct uboot_dfu_trailer)) -+ != sizeof(struct uboot_dfu_trailer)) { -+ fprintf (stderr, "%s: Write error on %s: %s\n", -+ cmdname, imagefile, strerror(errno)); -+ exit (EXIT_FAILURE); -+ } -+ -+ /* We're a bit of paranoid */ -+#if defined(_POSIX_SYNCHRONIZED_IO) && !defined(__sun__) && !defined(__FreeBSD__) -+ (void) fdatasync (ifd); -+#else -+ (void) fsync (ifd); -+#endif -+ -+ if (fstat(ifd, &sbuf) < 0) { -+ fprintf (stderr, "%s: Can't stat %s: %s\n", -+ cmdname, imagefile, strerror(errno)); -+ exit (EXIT_FAILURE); -+ } -+ -+ /* We're a bit of paranoid */ -+#if defined(_POSIX_SYNCHRONIZED_IO) && !defined(__sun__) && !defined(__FreeBSD__) -+ (void) fdatasync (ifd); -+#else -+ (void) fsync (ifd); -+#endif -+ -+ if (close(ifd)) { -+ fprintf (stderr, "%s: Write error on %s: %s\n", -+ cmdname, imagefile, strerror(errno)); -+ exit (EXIT_FAILURE); -+ } -+ -+ exit (EXIT_SUCCESS); -+} -Index: u-boot/include/usb_dfu_trailer.h -=================================================================== ---- /dev/null -+++ u-boot/include/usb_dfu_trailer.h -@@ -0,0 +1,31 @@ -+#ifndef _USB_DFU_TRAILER_H -+#define _USB_DFU_TRAILER_H -+ -+/* trailer handling for DFU files */ -+ -+#define UBOOT_DFU_TRAILER_V1 1 -+#define UBOOT_DFU_TRAILER_MAGIC 0x19731978 -+struct uboot_dfu_trailer { -+ u_int32_t magic; -+ u_int16_t version; -+ u_int16_t length; -+ u_int16_t vendor; -+ u_int16_t product; -+ u_int32_t revision; -+} __attribute__((packed)); -+ -+/* we mirror the trailer because we want it to be longer in later versions -+ * while keeping backwards compatibility */ -+static inline void dfu_trailer_mirror(struct uboot_dfu_trailer *trailer, -+ unsigned char *eof) -+{ -+ int i; -+ int len = sizeof(struct uboot_dfu_trailer); -+ unsigned char *src = eof - len; -+ unsigned char *dst = (unsigned char *) trailer; -+ -+ for (i = 0; i < len; i++) -+ dst[len-1-i] = src[i]; -+} -+ -+#endif /* _USB_DFU_TRAILER_H */ -Index: u-boot/Makefile -=================================================================== ---- u-boot.orig/Makefile -+++ u-boot/Makefile -@@ -261,6 +261,12 @@ - $(obj)u-boot.bin: $(obj)u-boot - $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@ - -+$(obj)u-boot.udfu: $(obj)u-boot.bin -+ ./tools/mkudfu -v $(CONFIG_USB_DFU_VENDOR) \ -+ -p $(CONFIG_USB_DFU_PRODUCT) \ -+ -r $(CONFIG_USB_DFU_REVISION) \ -+ -d $< $@ -+ - $(obj)u-boot.img: $(obj)u-boot.bin - ./tools/mkimage -A $(ARCH) -T firmware -C none \ - -a $(TEXT_BASE) -e 0 \ -Index: u-boot/board/neo1973/gta01/split_by_variant.sh -=================================================================== ---- u-boot.orig/board/neo1973/gta01/split_by_variant.sh -+++ u-boot/board/neo1973/gta01/split_by_variant.sh -@@ -15,37 +15,44 @@ - echo "$0:: No parameters - using GTA01Bv3 config" - echo "#define CONFIG_ARCH_GTA01B_v3" > $CFGINC - echo "GTA01_BIG_RAM=y" > $CFGTMP -+ echo "CONFIG_USB_DFU_REVISION=0x0230" > $CFGTMP - else - case "$1" in - gta01v4_config) - echo "#define CONFIG_ARCH_GTA01_v4" > $CFGINC - echo "GTA01_BIG_RAM=n" > $CFGTMP -+ echo "CONFIG_USB_DFU_REVISION=0x0140" > $CFGTMP - ;; - - gta01v3_config) - echo "#define CONFIG_ARCH_GTA01_v3" > $CFGINC - echo "GTA01_BIG_RAM=n" > $CFGTMP -+ echo "CONFIG_USB_DFU_REVISION=0x0130" > $CFGTMP - ;; - - gta01bv2_config) - echo "#define CONFIG_ARCH_GTA01B_v2" > $CFGINC - echo "GTA01_BIG_RAM=y" > $CFGTMP -+ echo "CONFIG_USB_DFU_REVISION=0x0220" > $CFGTMP - ;; - - gta01bv3_config) - echo "#define CONFIG_ARCH_GTA01B_v3" > $CFGINC - echo "GTA01_BIG_RAM=y" > $CFGTMP -+ echo "CONFIG_USB_DFU_REVISION=0x0230" > $CFGTMP - ;; - - gta01bv4_config) - echo "#define CONFIG_ARCH_GTA01B_v4" > $CFGINC - echo "GTA01_BIG_RAM=y" > $CFGTMP -+ echo "CONFIG_USB_DFU_REVISION=0x0240" > $CFGTMP - ;; - - *) - echo "$0:: Unrecognised config - using GTA01Bv4 config" - echo "#define CONFIG_ARCH_GTA01B_v4" > $CFGINC - echo "GTA01_BIG_RAM=y" > $CFGTMP -+ echo "CONFIG_USB_DFU_REVISION=0x0240" > $CFGTMP - ;; - - esac -Index: u-boot/board/neo1973/gta01/config.mk -=================================================================== ---- u-boot.orig/board/neo1973/gta01/config.mk -+++ u-boot/board/neo1973/gta01/config.mk -@@ -24,6 +24,9 @@ - # - # download area is 3200'0000 or 3300'0000 - -+CONFIG_USB_DFU_VENDOR=0x1457 -+CONFIG_USB_DFU_PRODUCT=0x5119 -+ - sinclude $(OBJTREE)/board/$(BOARDDIR)/config.tmp - - ifeq ($(GTA01_BIG_RAM),y) |