summaryrefslogtreecommitdiff
path: root/packages/u-boot/u-boot-mkimage-openmoko-native/uboot-dfu.patch
diff options
context:
space:
mode:
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.patch2081
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)