diff mbox

[U-Boot,2/4] dfu: generic backend parts

Message ID 1320832343-21369-3-git-send-email-andrzej.p@samsung.com
State Superseded
Headers show

Commit Message

Andrzej Pietrasiewicz Nov. 9, 2011, 9:52 a.m. UTC
Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 Makefile                 |    1 +
 drivers/usb/dfu/Makefile |   33 ++++++++++++
 drivers/usb/dfu/dfu.c    |  109 ++++++++++++++++++++++++++++++++++++++++
 drivers/usb/dfu/fat.c    |   77 ++++++++++++++++++++++++++++
 drivers/usb/dfu/mmc.c    |  124 ++++++++++++++++++++++++++++++++++++++++++++++
 include/dfu_backend.h    |   71 ++++++++++++++++++++++++++
 include/mbr.h            |   49 ++++++++++++++++++
 7 files changed, 464 insertions(+), 0 deletions(-)
 create mode 100644 drivers/usb/dfu/Makefile
 create mode 100644 drivers/usb/dfu/dfu.c
 create mode 100644 drivers/usb/dfu/fat.c
 create mode 100644 drivers/usb/dfu/mmc.c
 create mode 100644 include/dfu_backend.h
 create mode 100644 include/mbr.h

Comments

Mike Frysinger Jan. 8, 2012, 5:13 a.m. UTC | #1
On Wednesday 09 November 2011 04:52:21 Andrzej Pietrasiewicz wrote:
> --- /dev/null
> +++ b/drivers/usb/dfu/Makefile
>
> +ifdef CONFIG_MMC
> +COBJS-y += mmc.o
> +endif
> +
> +ifdef CONFIG_CMD_FAT
> +COBJS-y += fat.o
> +endif

COBJS-$(CONFIG_XXX) += foo.o

> --- /dev/null
> +++ b/drivers/usb/dfu/fat.c
> @@ -0,0 +1,77 @@
> +#include <common.h>
> +#include <fat.h>
> +#include <dfu_backend.h>

missing intro comment block

> +inline int set_fat_part_num(int pnum)

there seems to be a lot of funcs in this file and others that have misplaced 
"inline" markings

> --- /dev/null
> +++ b/include/dfu_backend.h
>
> +extern void board_dfu_init(void);
> +extern int board_dfu_cleanup(void);
> +extern int usb_gadget_handle_interrupts(void);
> +
> +extern int read_mmc(void *buf, unsigned int len, unsigned long from);
> +extern int write_mmc(void *buf, unsigned int len, unsigned long from);
> +
> +extern block_dev_desc_t *set_fat_dev(block_dev_desc_t *d);
> +extern int set_fat_part_num(int pnum);
> +extern const char *set_fat_filename(const char *fn);
> +extern int read_fat(void *buf, unsigned int len, unsigned long from);
> +extern int write_fat(void *buf, unsigned int len, unsigned long from);
> +
> +extern int read_mbr(struct mmc *mmc, struct mbr_part_data *pd, int
> *extended_lba, int mmc_mbr_dev); +
> +extern int read_block(void *ctx, unsigned int n, void *buf);
> +extern int write_block(void *ctx, unsigned int n, void *buf);
> +extern int generic_prepare(void *ctx, u8 mode);
> +extern int generic_finish(void *ctx, u8 mode);

API needs to be namespaced here with like "dfu_" prefixes

> --- /dev/null
> +++ b/include/mbr.h

file needs protection against multiple inclusion

> +void set_mbr_dev(int dev);
> +void set_mbr_info(char *ramaddr, unsigned int len, unsigned int reserved);
> +void set_mbr_table(unsigned int start_addr, int parts,
> +		unsigned int *blocks, unsigned int *part_offset);
> +int get_mbr_table(unsigned int *part_offset);

seems like you declare funcs here that aren't actually defined ...
-mike
Andrzej Pietrasiewicz Jan. 9, 2012, 7:50 a.m. UTC | #2
Hello Mike,

On Sunday, January 08, 2012 6:14 AM Mike Frysinger wrote:

> -----Original Message-----
> From: Mike Frysinger [mailto:vapier@gentoo.org]
> Sent: Sunday, January 08, 2012 6:14 AM
> To: u-boot@lists.denx.de
> Cc: Andrzej Pietrasiewicz; Kyungmin Park; Marek Szyprowski
> Subject: Re: [U-Boot] [PATCH 2/4] dfu: generic backend parts
> 

<...>

> 
> COBJS-$(CONFIG_XXX) += foo.o
> 

<...>

> 
> missing intro comment block
> 

<...>

> 
> there seems to be a lot of funcs in this file and others that have
> misplaced "inline" markings
>

<...>
 
> 
> API needs to be namespaced here with like "dfu_" prefixes
> 

<...>

> 
> file needs protection against multiple inclusion
>
 
<...>
 
> seems like you declare funcs here that aren't actually defined ...
> -mike

Thank you for your review. As far as I remember this patch series
was a "quick-and-dirty" attempt at splitting the implementation into
parts so that Stefan Shmidt could continue his work with his own
dfu backends.

However, Wolfgang Denk was not convinced about introducing dfu
support to u-boot the way it was proposed. Are there any new
circumstances?

Andrzej
Mike Frysinger Jan. 9, 2012, 5:26 p.m. UTC | #3
On Monday 09 January 2012 02:50:00 Andrzej Pietrasiewicz wrote:
> However, Wolfgang Denk was not convinced about introducing dfu
> support to u-boot the way it was proposed. Are there any new
> circumstances?

i just had the thread marked unread, so i read it & reviewed for some high 
level details.  that's all.
-mike
Wolfgang Denk March 18, 2012, 6:49 p.m. UTC | #4
Dear Andrzej Pietrasiewicz,

In message <000601cccea3$4a41f750$dec5e5f0$%p@samsung.com> you wrote:
> 
> Thank you for your review. As far as I remember this patch series
> was a "quick-and-dirty" attempt at splitting the implementation into
> parts so that Stefan Shmidt could continue his work with his own
> dfu backends.

Is there any such work goig on?  I haven't seen any updates / fixes
for Mike's review comments.

> However, Wolfgang Denk was not convinced about introducing dfu
> support to u-boot the way it was proposed. Are there any new
> circumstances?

Indeed I would have liked to see a more general approach, and I still
feel it should be possible. But if nobody is picking up this idea, it
is probably better to support the feature with the current implemen-
tation than not at all.

The review comments need to be addressed, though.

Best regards,

Wolfgang Denk
Stefan Schmidt April 3, 2012, 2:56 p.m. UTC | #5
Hello.

On Mon, 2012-01-09 at 08:50, Andrzej Pietrasiewicz wrote:
> 
> Thank you for your review. As far as I remember this patch series
> was a "quick-and-dirty" attempt at splitting the implementation into
> parts so that Stefan Shmidt could continue his work with his own
> dfu backends.

Time run out for me on this project and I'm going to relocate to
another country for new job this months. In short I want have time to
work on this the next months.

Personally I'm still interested in this and may start working on it
when everything else settled down. Can not tell when this is though.
If anyone else wants to pick this up and push it forward that would be
more then welcome. A small patchset with my current state will follow
this mail.

Some words about it. As I don't have hardware which is working with
U-boot mainline and provides a UDC driver for the new gadget framework
I could not directly test your code. Having a DFU implementation for
both the old and the new gadget framework turned out to be more
trouble then expected. I split the nand backend part out, but it
still needs some fixing and especially testing.

For systems with old gadget framework UDC drivers, like the
beagleboard with musb, it might still be wise to use the original
version I posted earlier here for reference.

Lets hope someone, or maybe myself in some months, will pick this up
and finally bring it into mainline.

regards
Stefan Schmidt
diff mbox

Patch

diff --git a/Makefile b/Makefile
index bd72286..83ea3d0 100644
--- a/Makefile
+++ b/Makefile
@@ -283,6 +283,7 @@  LIBS += drivers/usb/gadget/libusb_gadget.o
 LIBS += drivers/usb/host/libusb_host.o
 LIBS += drivers/usb/musb/libusb_musb.o
 LIBS += drivers/usb/phy/libusb_phy.o
+LIBS += drivers/usb/dfu/libusb_dfu.o
 LIBS += drivers/video/libvideo.o
 LIBS += drivers/watchdog/libwatchdog.o
 LIBS += common/libcommon.o
diff --git a/drivers/usb/dfu/Makefile b/drivers/usb/dfu/Makefile
new file mode 100644
index 0000000..c2fe049
--- /dev/null
+++ b/drivers/usb/dfu/Makefile
@@ -0,0 +1,33 @@ 
+include $(TOPDIR)/config.mk
+
+LIB	:= $(obj)libusb_dfu.o
+
+# new USB gadget layer dependencies
+COBJS-y += dfu.o
+
+ifdef CONFIG_MMC
+COBJS-y += mmc.o
+endif
+
+ifdef CONFIG_CMD_FAT
+COBJS-y += fat.o
+endif
+
+COBJS	:= $(COBJS-y)
+SRCS	:= $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+
+all:	$(LIB)
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
+
diff --git a/drivers/usb/dfu/dfu.c b/drivers/usb/dfu/dfu.c
new file mode 100644
index 0000000..2f5492d
--- /dev/null
+++ b/drivers/usb/dfu/dfu.c
@@ -0,0 +1,109 @@ 
+#include <common.h>
+#include <dfu_backend.h>
+#include <flash_entity.h>
+
+/*
+ * Adapt transport layer buffer size to storage chunk size
+ *
+ * return < n to indicate no more data to read
+ */
+int read_block(void *ctx, unsigned int n, void *buf)
+{
+	struct flash_entity_ctx *ct = ctx;
+	unsigned int nread = 0;
+
+	if (n == 0)
+		return n;
+
+	while (nread < n) {
+		unsigned int copy;
+
+		if (ct->num_done >= ct->length)
+			break;
+		if (ct->buffered == 0) {
+			ct->read(ct->buf, ct->buf_len,
+				 ct->offset + ct->num_done);
+			ct->buffered = ct->buf_len;
+		}
+		copy = min(n - nread, ct->buffered);
+
+		memcpy(buf + nread, ct->buf + ct->buf_len - ct->buffered, copy);
+		nread += copy;
+		ct->buffered -= copy;
+		ct->num_done += copy;
+	}
+
+	return nread;
+}
+
+/*
+ * Adapt transport layer buffer size to storage chunk size
+ */
+int write_block(void *ctx, unsigned int n, void *buf)
+{
+	struct flash_entity_ctx *ct = ctx;
+	unsigned int nwritten = 0;
+
+	if (n == 0)
+		return n;
+
+	while (nwritten < n) {
+		unsigned int copy;
+
+		if (ct->num_done >= ct->length)
+			break;
+		if (ct->buffered >= ct->buf_len) {
+			ct->write(ct->buf, ct->buf_len,
+				  ct->offset + ct->num_done);
+			ct->buffered = 0;
+			ct->num_done += ct->buf_len;
+			if (ct->num_done >= ct->length)
+				break;
+		}
+		copy = min(n - nwritten, ct->buf_len - ct->buffered);
+
+		memcpy(ct->buf + ct->buffered, buf + nwritten, copy);
+		nwritten += copy;
+		ct->buffered += copy;
+	}
+
+	return nwritten;
+}
+
+/*
+ * Entity-specific prepare and finish
+ */
+static void reset_ctx(struct flash_entity_ctx *ctx)
+{
+	ctx->buffered = 0;
+	ctx->num_done = 0;
+}
+
+int generic_prepare(void *ctx, u8 mode)
+{
+	struct flash_entity_ctx *ct = ctx;
+
+	reset_ctx(ct);
+	memset(ct->buf, 0, ct->buf_len);
+	if (mode == FLASH_WRITE) {
+		if (ct->erase) {
+			printf("Erase entity: %s ", ct->this_entity->name);
+			ct->erase(ct->length, ct->offset);
+		}
+		printf("Write entity: %s ", ct->this_entity->name);
+	} else if (mode == FLASH_READ) {
+		printf("Read entity: %s ", ct->this_entity->name);
+	}
+	return 0;
+}
+
+int generic_finish(void *ctx, u8 mode)
+{
+	struct flash_entity_ctx *ct = ctx;
+
+	if (mode == FLASH_WRITE && ct->buffered > 0)
+		ct->write(ct->buf, ct->buffered, ct->offset + ct->num_done);
+
+	return 0;
+}
+
diff --git a/drivers/usb/dfu/fat.c b/drivers/usb/dfu/fat.c
new file mode 100644
index 0000000..6f0125f
--- /dev/null
+++ b/drivers/usb/dfu/fat.c
@@ -0,0 +1,77 @@ 
+#include <common.h>
+#include <fat.h>
+#include <dfu_backend.h>
+
+static const char *fat_filename;
+static int fat_part_num;
+static block_dev_desc_t *fat_dev;
+
+inline int set_fat_part_num(int pnum)
+{
+	fat_part_num = pnum;
+	
+	return pnum;
+}
+
+inline const char *set_fat_filename(const char *fn)
+{
+	fat_filename = fn;
+
+	return fn;
+}
+
+inline block_dev_desc_t *set_fat_dev(block_dev_desc_t *d)
+{
+	fat_dev = d;
+
+	return d;
+}
+
+int read_fat(void *buf, unsigned int len, unsigned long from)
+{
+	int ret;
+
+	ret = fat_register_device(fat_dev, fat_part_num);
+	if (ret < 0) {
+		printf("error : fat_register_device\n");
+		return 0;
+	}
+	printf("read up to %d B ", MMC_FAT_BLOCK_SZ);
+	return file_fat_read(fat_filename, buf, len);
+}
+
+int write_fat(void *buf, unsigned int len, unsigned long from)
+{
+#ifdef CONFIG_FAT_WRITE
+	int ret;
+
+	ret = fat_register_device(fat_dev, fat_part_num);
+	if (ret < 0) {
+		printf("error : fat_register_divce\n");
+		return 0;
+	}
+
+	printf("write up to %d B ", MMC_FAT_BLOCK_SZ);
+	ret = file_fat_write(fat_filename, buf, len);
+
+	/* format and write again */
+	if (ret == 1) {
+		printf("formatting\n");
+		if (mkfs_vfat(fat_dev, fat_part_num)) {
+			printf("error formatting device\n");
+			return 0;
+		}
+		ret = file_fat_write(fat_filename, buf, len);
+	}
+
+	if (ret < 0) {
+		printf("error : writing %s\n", fat_filename);
+		return 0;
+	}
+#else
+	printf("error : FAT write not supported\n");
+	return 0;
+#endif
+	return len;
+}
+
diff --git a/drivers/usb/dfu/mmc.c b/drivers/usb/dfu/mmc.c
new file mode 100644
index 0000000..221d6ff
--- /dev/null
+++ b/drivers/usb/dfu/mmc.c
@@ -0,0 +1,124 @@ 
+#include <common.h>
+#include <mbr.h>
+#include <mmc.h>
+#include <dfu_backend.h>
+#include <flash_entity.h>
+
+#define SIGNATURE		((unsigned short) 0xAA55)
+#define PARAM_LEN		12
+
+static int read_ebr(struct mmc *mmc, struct mbr_partition *mp,
+		int ebr_next, struct mbr_part_data *pd, int parts,
+		int *extended_lba, int mmc_mbr_dev)
+{
+	struct mbr *ebr;
+	struct mbr_partition *p;
+	char buf[512];
+	int ret, i;
+	int lba = 0;
+
+	if (ebr_next)
+		lba = *extended_lba;
+
+	lba += mp->lba;
+	ret = mmc->block_dev.block_read(mmc_mbr_dev, lba, 1, buf);
+	if (ret != 1)
+		return 0;
+
+	ebr = (struct mbr *) buf;
+
+	if (ebr->signature != SIGNATURE) {
+		printf("Signature error 0x%x\n", ebr->signature);
+		return 0;
+	}
+
+	for (i = 0; i < 2; i++) {
+		p = (struct mbr_partition *) &ebr->parts[i];
+
+		if (i == 0) {
+			lba += p->lba;
+			if (p->partition_type == 0x83) {
+				if (pd) {
+					pd[parts].offset = lba;
+					pd[parts].length = p->nsectors;
+					pd[parts].primary = 0;
+				}
+				parts++;
+			}
+		}
+	}
+
+	if (p->lba && p->partition_type == 0x5)
+		parts = read_ebr(mmc, p, 1, pd, parts, extended_lba, mmc_mbr_dev);
+
+	return parts;
+}
+
+int read_mbr(struct mmc *mmc, struct mbr_part_data *pd, int *extended_lba,
+	     int mmc_mbr_dev)
+{
+	struct mbr_partition *mp;
+	struct mbr *mbr;
+	char buf[512];
+	int ret, i;
+	int parts = 0;
+
+	ret = mmc->block_dev.block_read(mmc_mbr_dev, 0, 1, buf);
+	if (ret != 1)
+		return 0;
+
+	mbr = (struct mbr *) buf;
+
+	if (mbr->signature != SIGNATURE) {
+		printf("Signature error 0x%x\n", mbr->signature);
+		return 0;
+	}
+
+	for (i = 0; i < 4; i++) {
+		mp = (struct mbr_partition *) &mbr->parts[i];
+
+		if (!mp->partition_type)
+			continue;
+
+		if (mp->partition_type == 0x83) {
+			if (pd) {
+				pd[parts].offset = mp->lba;
+				pd[parts].length = mp->nsectors;
+				pd[parts].primary = 1;
+			}
+			parts++;
+		}
+
+		if (mp->lba && mp->partition_type == 0x5) {
+			*extended_lba = mp->lba;
+			parts = read_ebr(mmc, mp, 0, pd, parts, extended_lba, mmc_mbr_dev);
+		}
+	}
+
+	return parts;
+}
+
+static int rw_mmc(void *buf, char *op, unsigned int len, unsigned long from)
+{
+	char ram_addr[PARAM_LEN];
+	char offset[PARAM_LEN];
+	char length[PARAM_LEN];
+	char *argv[] = {"mmc", op, ram_addr, offset, length};
+
+	sprintf(ram_addr, "0x%lx", (unsigned long)buf);
+	sprintf(offset, "0x%lx", from / MMC_SECTOR_SZ); /* guaranteed integer */
+	sprintf(length, "0x%x", (len + MMC_SECTOR_SZ - 1) / MMC_SECTOR_SZ);
+
+	return do_mmcops(NULL, 0, 6, argv);
+}
+
+inline int read_mmc(void *buf, unsigned int len, unsigned long from)
+{
+	return rw_mmc(buf, "read", len, from);
+}
+
+inline int write_mmc(void *buf, unsigned int len, unsigned long from)
+{
+	return rw_mmc(buf, "write", len, from);
+}
+
diff --git a/include/dfu_backend.h b/include/dfu_backend.h
new file mode 100644
index 0000000..8c608d1
--- /dev/null
+++ b/include/dfu_backend.h
@@ -0,0 +1,71 @@ 
+/*
+ * dfu.h - Device Firmware Upgrade
+ *
+ * copyright (c) 2011 samsung electronics
+ * author: andrzej pietrasiewicz <andrzej.p@samsung.com>
+ *
+ * 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
+ */
+
+#ifndef __DFU_BACKEND_H__
+#define __DFU_BACKEND_H__
+
+struct mbr_part_data {
+	unsigned long		offset; /* #sectors from mmc begin */
+	unsigned long		length; /* #sectors in this partition*/
+	u8			primary; /* != 0 if primary, 0 if extended */
+};
+
+typedef int (*rw_op)(void *buf, unsigned int len, unsigned long from);
+typedef int (*erase_op)(unsigned int len, unsigned long from);
+
+struct flash_entity_ctx {
+	unsigned long		offset;	/* offset into the device */
+	unsigned long		length; /* size of the entity */
+	u8			*buf; /* buffer for one chunk */
+	unsigned long		buf_len; /* one chunk length */
+	unsigned int		buffered; /* # available bytes in buf */
+	unsigned int		num_done; /* total bytes handled */
+	rw_op			read; /* chunk read op for this medium */
+	rw_op			write; /* chunk write op for this medium */
+	erase_op		erase; /* erase op for this medium or NULL */
+	struct flash_entity	*this_entity; /* the containing entity */
+	void			*associated; /* related entity, if any */
+};
+
+extern void board_dfu_init(void);
+extern int board_dfu_cleanup(void);
+extern int usb_gadget_handle_interrupts(void);
+
+extern int read_mmc(void *buf, unsigned int len, unsigned long from);
+extern int write_mmc(void *buf, unsigned int len, unsigned long from);
+
+extern block_dev_desc_t *set_fat_dev(block_dev_desc_t *d);
+extern int set_fat_part_num(int pnum);
+extern const char *set_fat_filename(const char *fn);
+extern int read_fat(void *buf, unsigned int len, unsigned long from);
+extern int write_fat(void *buf, unsigned int len, unsigned long from);
+
+extern int read_mbr(struct mmc *mmc, struct mbr_part_data *pd, int *extended_lba, int mmc_mbr_dev);
+
+extern int read_block(void *ctx, unsigned int n, void *buf);
+extern int write_block(void *ctx, unsigned int n, void *buf);
+extern int generic_prepare(void *ctx, u8 mode);
+extern int generic_finish(void *ctx, u8 mode);
+
+#define MMC_SECTOR_SZ		512
+#define MMC_FAT_BLOCK_SZ	(4 * 1024 * 1024)
+
+#endif
diff --git a/include/mbr.h b/include/mbr.h
new file mode 100644
index 0000000..9cbeb2e
--- /dev/null
+++ b/include/mbr.h
@@ -0,0 +1,49 @@ 
+/*
+ * Copyright (C) 2010 Samsung Electrnoics
+ *
+ * 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/compiler.h>
+
+#define MBR_RESERVED_SIZE	0x8000
+#define MBR_START_OFS_BLK	(0x500000 / 512)
+
+struct mbr_partition {
+	char status;
+	char f_chs[3];
+	char partition_type;
+	char l_chs[3];
+	int lba;
+	int nsectors;
+} __packed;
+
+struct mbr {
+	char code_area[440];
+	char disk_signature[4];
+	char nulls[2];
+	struct mbr_partition parts[4];
+	unsigned short signature;
+};
+
+extern unsigned int mbr_offset[16];
+extern unsigned int mbr_parts;
+
+void set_mbr_dev(int dev);
+void set_mbr_info(char *ramaddr, unsigned int len, unsigned int reserved);
+void set_mbr_table(unsigned int start_addr, int parts,
+		unsigned int *blocks, unsigned int *part_offset);
+int get_mbr_table(unsigned int *part_offset);