]> git.sur5r.net Git - u-boot/commitdiff
dfu: ram support
authorAfzal Mohammed <afzal.mohd.ma@gmail.com>
Tue, 17 Sep 2013 19:45:24 +0000 (01:15 +0530)
committerMarek Vasut <marex@denx.de>
Tue, 24 Sep 2013 15:51:35 +0000 (17:51 +0200)
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.

Signed-off-by: Afzal Mohammed <afzal.mohd.ma@gmail.com>
Cc: Heiko Schocher <hs@denx.de>
Cc: Marek Vasut <marex@denx.de>
Cc: Lukasz Majewski <l.majewski@samsung.com>
Cc: Pantelis Antoniou <panto@antoniou-consulting.com>
Cc: Gerhard Sittig <gsi@denx.de>
Acked-by: Marek Vasut <marex@denx.de>
Acked-by: Lukasz Majewski <l.majewski@samsung.com>
Acked-by: Heiko Schocher <hs@denx.de>
README
drivers/dfu/Makefile
drivers/dfu/dfu.c
drivers/dfu/dfu_ram.c [new file with mode: 0644]
include/dfu.h

diff --git a/README b/README
index 20ba6502481728cfd81d7b8224f3d36c9851bd5e..cab649dedd98f3b2c49216c7fb690243710c327d 100644 (file)
--- a/README
+++ b/README
@@ -1409,6 +1409,12 @@ The following options need to be configured:
                CONFIG_DFU_NAND
                This enables support for exposing NAND devices via DFU.
 
+               CONFIG_DFU_RAM
+               This enables support for exposing RAM via DFU.
+               Note: DFU spec refer to non-volatile memory usage, but
+               allow usages beyond the scope of spec - here RAM usage,
+               one that would help mostly the developer.
+
                CONFIG_SYS_DFU_DATA_BUF_SIZE
                Dfu transfer uses a buffer before writing data to the
                raw storage device. Make the size (in bytes) of this buffer
index fca370ae04c05f24730b200f38f446b004eb4ec0..de9e44e1ef1c5635febf33f091362c5d5f792f65 100644 (file)
@@ -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))
index 689f5dbdedad673c48734d7abe798d8800471d25..56b21c78abc68676710eb90f003bb26bead26ea4 100644 (file)
@@ -348,6 +348,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);
@@ -397,14 +400,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 (file)
index 0000000..335a8e1
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * (C) Copyright 2013
+ * Afzal Mohammed <afzal.mohd.ma@gmail.com>
+ *
+ * Reference: dfu_mmc.c
+ * Copyright (C) 2012 Samsung Electronics
+ * author: Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <errno.h>
+#include <dfu.h>
+
+static int dfu_transfer_medium_ram(enum dfu_op op, struct dfu_entity *dfu,
+                                  u64 offset, void *buf, long *len)
+{
+       if (dfu->layout != DFU_RAM_ADDR) {
+               error("unsupported layout: %s\n", dfu_get_layout(dfu->layout));
+               return  -EINVAL;
+       }
+
+       if (offset > dfu->data.ram.size) {
+               error("request exceeds allowed area\n");
+               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")) {
+               error("unsupported device: %s\n", st);
+               return -ENODEV;
+       }
+
+       dfu->layout = DFU_RAM_ADDR;
+       dfu->data.ram.start = (void *)simple_strtoul(s, &s, 16);
+       s++;
+       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;
+}
index 6a3e253b1df56abaeb1b313fbf8184394d41c6df..6f4bba455b131016c1d5c0de213106101002e85a 100644 (file)
@@ -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,
 };
 
 enum dfu_op {
@@ -56,6 +58,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;
@@ -81,6 +88,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,
@@ -143,4 +151,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_ */