[U-Boot] [PATCH RFC] dfu: ram support

Lukasz Majewski l.majewski at samsung.com
Mon Sep 9 08:50:58 CEST 2013


Hi Afzal Mohammed,

> DFU spec mentions it as a method to upgrade firmware (software stored
> in writable non-volatile memory). It also says other potential uses of
> DFU is beyond scope of the spec.
> 
> Here such a beyond the scope use is being attempted - directly pumping
> binary images from host via USB to RAM. This facility is a developer
> centric one in that it gives advantage over upgrading non-volatile
> memory for testing new images every time during development and/or
> testing.
> 
> Directly putting image onto RAM would speed up upgrade process. This
> and convenience was the initial thoughts that led to doing this, speed
> improvement over MMC was only 1 second though - 6 sec on RAM as
> opposed to 7 sec on MMC in beagle bone, perhaps enabling cache and/or
> optimizing DFU framework to avoid multiple copy for ram (if worth)
> may help, and on other platforms and other boot media like NAND maybe
> improvement would be higher.
> 
> And for a platform that doesn't yet have proper DFU suppport for
> non-volatile media's, DFU to RAM can be used.
> 
> Another minor advantage would be to increase life of mmc/nand as it
> would be less used during development/testing.
> 
> usage: <image name> ram <start address> <size>
> eg. kernel ram 0x81000000 0x1000000
> 
> Downloading images to RAM using DFU is not something new, this is
> acheived in openmoko also.
> 
> DFU on RAM can be used for extracting RAM contents to host using dfu
> upload. Perhaps this can be extended to io for squeezing out register
> dump through usb, if it is worth.
> 

Above idea sounds very interesting. 
One minor thing: 
It also would be good to have dfu_alt_info environment properly defined
to have "ram" alt setting for beagle bone. Then we would have at least
one board which supports this new feature.

> Signed-off-by: Afzal Mohammed <afzal.mohd.ma at gmail.com>
> Cc: Lukasz Majewski <l.majewski at samsung.com>
> Cc: Pantelis Antoniou <panto at antoniou-consulting.com>
> Cc: Heiko Schocher <hs at denx.de>
> ---
>  drivers/dfu/Makefile  |  1 +
>  drivers/dfu/dfu.c     |  7 +++--
>  drivers/dfu/dfu_ram.c | 82
> +++++++++++++++++++++++++++++++++++++++++++++++++++
> include/dfu.h         | 18 +++++++++++ 4 files changed, 106
> insertions(+), 2 deletions(-) create mode 100644 drivers/dfu/dfu_ram.c
> 
> diff --git a/drivers/dfu/Makefile b/drivers/dfu/Makefile
> index fca370a..de9e44e 100644
> --- a/drivers/dfu/Makefile
> +++ b/drivers/dfu/Makefile
> @@ -12,6 +12,7 @@ LIB	= $(obj)libdfu.o
>  COBJS-$(CONFIG_DFU_FUNCTION) += dfu.o
>  COBJS-$(CONFIG_DFU_MMC) += dfu_mmc.o
>  COBJS-$(CONFIG_DFU_NAND) += dfu_nand.o
> +COBJS-$(CONFIG_DFU_RAM) += dfu_ram.o
>  
>  SRCS    := $(COBJS-y:.o=.c)
>  OBJS	:= $(addprefix $(obj),$(COBJS-y))
> diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c
> index d73d510..7b3d05d 100644
> --- a/drivers/dfu/dfu.c
> +++ b/drivers/dfu/dfu.c
> @@ -325,6 +325,9 @@ static int dfu_fill_entity(struct dfu_entity
> *dfu, char *s, int alt, } else if (strcmp(interface, "nand") == 0) {
>  		if (dfu_fill_entity_nand(dfu, s))
>  			return -1;
> +	} else if (strcmp(interface, "ram") == 0) {
> +		if (dfu_fill_entity_ram(dfu, s))
> +			return -1;
>  	} else {
>  		printf("%s: Device %s not (yet) supported!\n",
>  		       __func__,  interface);
> @@ -374,14 +377,14 @@ int dfu_config_entities(char *env, char
> *interface, int num) 
>  const char *dfu_get_dev_type(enum dfu_device_type t)
>  {
> -	const char *dev_t[] = {NULL, "eMMC", "OneNAND", "NAND" };
> +	const char *dev_t[] = {NULL, "eMMC", "OneNAND", "NAND",
> "RAM" }; return dev_t[t];
>  }
>  
>  const char *dfu_get_layout(enum dfu_layout l)
>  {
>  	const char *dfu_layout[] = {NULL, "RAW_ADDR", "FAT", "EXT2",
> -					   "EXT3", "EXT4" };
> +					   "EXT3", "EXT4",
> "RAM_ADDR" }; return dfu_layout[l];
>  }
>  
> diff --git a/drivers/dfu/dfu_ram.c b/drivers/dfu/dfu_ram.c
> new file mode 100644
> index 0000000..8562495
> --- /dev/null
> +++ b/drivers/dfu/dfu_ram.c
> @@ -0,0 +1,82 @@
> +/*
> + * (C) Copyright 2013
> + * Afzal Mohammed <afzal.mohd.ma at gmail.com>
> + *
> + * Reference: dfu_mmc.c
> + * Copyright (C) 2012 Samsung Electronics
> + * author: Lukasz Majewski <l.majewski at samsung.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <malloc.h>
> +#include <errno.h>
> +#include <dfu.h>
> +
> +enum dfu_ram_op {
> +	DFU_OP_READ = 1,
> +	DFU_OP_WRITE,
> +};

Minor:
Now I've realised that the dfu_nand_op and dfu_mmc_op have the same
defines. Maybe it is a good time to combine this and store it at
dfu.h?

> +
> +static int dfu_transfer_medium_ram(enum dfu_ram_op op, struct
> dfu_entity *dfu,
> +				   u64 offset, void *buf, long *len)
> +{
> +	if (dfu->layout != DFU_RAM_ADDR) {
> +		printf("%s: unsupported layout :%s\n", __func__,
> +			dfu_get_layout(dfu->layout));
> +		return  -EINVAL;
> +	}
> +
> +	if (offset > dfu->data.ram.size) {
> +		printf("%s: request exceeds allowed area\n",
> __func__);
> +		return -EINVAL;
> +	}
> +
> +	if (op == DFU_OP_WRITE)
> +		memcpy(dfu->data.ram.start + offset, buf, *len);
> +	else
> +		memcpy(buf, dfu->data.ram.start + offset, *len);
> +
> +	return 0;
> +}
> +
> +static int dfu_write_medium_ram(struct dfu_entity *dfu, u64 offset,
> +				void *buf, long *len)
> +{
> +	return dfu_transfer_medium_ram(DFU_OP_WRITE, dfu, offset,
> buf, len); +}
> +
> +static int dfu_read_medium_ram(struct dfu_entity *dfu, u64 offset,
> +			       void *buf, long *len)
> +{
> +	if (!*len) {
> +		*len = dfu->data.ram.size;
> +		return 0;
> +	}
> +
> +	return dfu_transfer_medium_ram(DFU_OP_READ, dfu, offset,
> buf, len); +}
> +
> +int dfu_fill_entity_ram(struct dfu_entity *dfu, char *s)
> +{
> +	char *st;
> +
> +	dfu->dev_type = DFU_DEV_RAM;
> +	st = strsep(&s, " ");
> +	if (strcmp(st, "ram")) {
> +		printf("%s: unsupported device: %s\n", __func__, st);
> +		return -ENODEV;
> +	}
> +
> +	dfu->layout = DFU_RAM_ADDR;
> +	dfu->data.ram.start = (void *)simple_strtoul(s, &s, 16);
> +	dfu->data.ram.size = simple_strtoul(++s, &s, 16);
> +
> +	dfu->write_medium = dfu_write_medium_ram;
> +	dfu->read_medium = dfu_read_medium_ram;
> +
> +	dfu->inited = 0;
> +
> +	return 0;
> +}
> diff --git a/include/dfu.h b/include/dfu.h
> index 47b9055..18d288d 100644
> --- a/include/dfu.h
> +++ b/include/dfu.h
> @@ -19,6 +19,7 @@ enum dfu_device_type {
>  	DFU_DEV_MMC = 1,
>  	DFU_DEV_ONENAND,
>  	DFU_DEV_NAND,
> +	DFU_DEV_RAM,
>  };
>  
>  enum dfu_layout {
> @@ -27,6 +28,7 @@ enum dfu_layout {
>  	DFU_FS_EXT2,
>  	DFU_FS_EXT3,
>  	DFU_FS_EXT4,
> +	DFU_RAM_ADDR,
>  };
>  
>  struct mmc_internal_data {
> @@ -51,6 +53,11 @@ struct nand_internal_data {
>  	unsigned int ubi;
>  };
>  
> +struct ram_internal_data {
> +	void		*start;
> +	unsigned int	size;
> +};
> +
>  static inline unsigned int get_mmc_blk_size(int dev)
>  {
>  	return find_mmc_device(dev)->read_bl_len;
> @@ -76,6 +83,7 @@ struct dfu_entity {
>  	union {
>  		struct mmc_internal_data mmc;
>  		struct nand_internal_data nand;
> +		struct ram_internal_data ram;
>  	} data;
>  
>  	int (*read_medium)(struct dfu_entity *dfu,
> @@ -137,4 +145,14 @@ static inline int dfu_fill_entity_nand(struct
> dfu_entity *dfu, char *s) }
>  #endif
>  
> +#ifdef CONFIG_DFU_RAM
> +extern int dfu_fill_entity_ram(struct dfu_entity *dfu, char *s);
> +#else
> +static inline int dfu_fill_entity_ram(struct dfu_entity *dfu, char
> *s) +{
> +	puts("RAM support not available!\n");
> +	return -1;
> +}
> +#endif
> +
>  #endif /* __DFU_ENTITY_H_ */

Despite one minor comment, I like the code and looking forward for a
patch :-).

-- 
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group


More information about the U-Boot mailing list