⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uboot-dfu.patch

📁 Uboot常用的移植patches, 方便定制移植到s3c2440
💻 PATCH
📖 第 1 页 / 共 4 页
字号:
Index: u-boot/drivers/usb/usbdcore_ep0.c===================================================================--- u-boot.orig/drivers/usb/usbdcore_ep0.c+++ u-boot/drivers/usb/usbdcore_ep0.c@@ -51,10 +51,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@@ -273,7 +278,24 @@ 	case USB_DESCRIPTOR_TYPE_ENDPOINT: 		serial_printf("USB_DESCRIPTOR_TYPE_ENDPOINT - error not implemented\n"); 		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 */ 		{ 			serial_printf("USB_DESCRIPTOR_TYPE_HID - error not implemented\n"); 			return -1;	/* unsupported at this time */@@ -301,6 +323,7 @@ 				     max); #endif 		}+#endif /* CONFIG_USBD_DFU */ 		break; 	case USB_DESCRIPTOR_TYPE_REPORT: 		{@@ -403,6 +426,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){@@ -590,7 +631,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/usb/usbdfu.c===================================================================--- /dev/null+++ u-boot/drivers/usb/usbdfu.c@@ -0,0 +1,1050 @@+/*+ * (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 "../serial/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 - ds->part->offset);+	debug("Erasing tail of 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) {+		printf("Error erasing tail\n");+	    	dev->dfu_state = DFU_STATE_dfuERROR;+		dev->dfu_status = DFU_STATUS_errERASE;+		return RET_STALL;+	}++	ds->off += ds->erase_opts.length; /* 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 && !strcmp(ds->part->name, "rootfs"))+				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)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -