dfu: add DFU virtual backend

Add a virtual DFU backend to allow board specific read and write
(for OTP update for example).

Acked-by: Lukasz Majewski <lukma@denx.de>
Signed-off-by: Patrick Delaunay <patrick.delaunay@st.com>
This commit is contained in:
Patrick Delaunay 2019-10-14 09:28:06 +02:00 committed by Marek Vasut
parent d5640f700d
commit ec44cace4b
6 changed files with 114 additions and 2 deletions

View File

@ -22,11 +22,18 @@ Overview:
- RAM - RAM
- SF (serial flash) - SF (serial flash)
- MTD (all MTD device: NAND, SPI-NOR, SPI-NAND,...) - MTD (all MTD device: NAND, SPI-NOR, SPI-NAND,...)
- virtual
These DFU backends are also used by These DFU backends are also used by
- the dfutftp (see README.dfutftp) - the dfutftp (see README.dfutftp)
- the thordown command (cmd/thordown.c and gadget/f_thor.c) - the thordown command (cmd/thordown.c and gadget/f_thor.c)
The "virtual" backend is a generic DFU backend to support a board specific
target (for example OTP), only based on the weak functions:
- dfu_write_medium_virt
- dfu_get_medium_size_virt
- dfu_read_medium_virt
Configuration Options: Configuration Options:
CONFIG_DFU CONFIG_DFU
CONFIG_DFU_OVER_USB CONFIG_DFU_OVER_USB
@ -36,6 +43,7 @@ Configuration Options:
CONFIG_DFU_RAM CONFIG_DFU_RAM
CONFIG_DFU_SF CONFIG_DFU_SF
CONFIG_DFU_SF_PART CONFIG_DFU_SF_PART
CONFIG_DFU_VIRTUAL
CONFIG_CMD_DFU CONFIG_CMD_DFU
Environment variables: Environment variables:
@ -117,6 +125,11 @@ Commands:
with <partid> is the MTD partition index with <partid> is the MTD partition index
"virt"
cmd: dfu 0 virt <dev>
each element in "dfu_alt_info" =
<name>
<interface> and <dev> are absent: <interface> and <dev> are absent:
the dfu command to use multiple devices the dfu command to use multiple devices
cmd: dfu 0 list cmd: dfu 0 list
@ -128,7 +141,7 @@ Commands:
ram <dev>=<alt1>;....;<altN> ram <dev>=<alt1>;....;<altN>
sf <dev>=<alt1>;....;<altN> sf <dev>=<alt1>;....;<altN>
mtd <dev>=<alt1>;....;<altN> mtd <dev>=<alt1>;....;<altN>
virt <dev>=<alt1>;....;<altN>
Host tools: Host tools:
When U-Boot runs the dfu stack, the DFU host tools can be used When U-Boot runs the dfu stack, the DFU host tools can be used
@ -230,3 +243,20 @@ Usage:
dev: MTD alt: 1 name: u-boot layout: RAW_ADDR dev: MTD alt: 1 name: u-boot layout: RAW_ADDR
dev: MTD alt: 2 name: u-boot-env layout: RAW_ADDR dev: MTD alt: 2 name: u-boot-env layout: RAW_ADDR
dev: MTD alt: 3 name: UBI layout: RAW_ADDR dev: MTD alt: 3 name: UBI layout: RAW_ADDR
Example 3: firmware located in SD Card (mmc) and virtual partition on
OTP and PMIC not volatile memory
- alternate 1 (alt=1) for scard
- alternate 2 (alt=2) for OTP (virtual)
- alternate 3 (alt=3) for PMIC NVM (virtual)
U-Boot> env set dfu_alt_info \
"mmc 0=sdcard raw 0 0x100000&"\
"virt 0=otp" \
"virt 1=pmic"
U-Boot> dfu 0 list
DFU alt settings list:
dev: eMMC alt: 0 name: sdcard layout: RAW_ADDR
dev: VIRT alt: 1 name: otp layout: RAW_ADDR
dev: VIRT alt: 2 name: pmic layout: RAW_ADDR

View File

@ -60,5 +60,12 @@ config DFU_MTD
help help
This option enables using DFU to read and write to on any MTD device. This option enables using DFU to read and write to on any MTD device.
config DFU_VIRT
bool "VIRTUAL flash back end for DFU"
help
This option enables using DFU to read and write to VIRTUAL device
used at board level to manage specific behavior
(OTP update for example).
endif endif
endmenu endmenu

View File

@ -10,3 +10,4 @@ obj-$(CONFIG_$(SPL_)DFU_NAND) += dfu_nand.o
obj-$(CONFIG_$(SPL_)DFU_RAM) += dfu_ram.o obj-$(CONFIG_$(SPL_)DFU_RAM) += dfu_ram.o
obj-$(CONFIG_$(SPL_)DFU_SF) += dfu_sf.o obj-$(CONFIG_$(SPL_)DFU_SF) += dfu_sf.o
obj-$(CONFIG_$(SPL_)DFU_TFTP) += dfu_tftp.o obj-$(CONFIG_$(SPL_)DFU_TFTP) += dfu_tftp.o
obj-$(CONFIG_$(SPL_)DFU_VIRT) += dfu_virt.o

View File

@ -474,6 +474,9 @@ static int dfu_fill_entity(struct dfu_entity *dfu, char *s, int alt,
} else if (strcmp(interface, "sf") == 0) { } else if (strcmp(interface, "sf") == 0) {
if (dfu_fill_entity_sf(dfu, devstr, s)) if (dfu_fill_entity_sf(dfu, devstr, s))
return -1; return -1;
} else if (strcmp(interface, "virt") == 0) {
if (dfu_fill_entity_virt(dfu, devstr, s))
return -1;
} else { } else {
printf("%s: Device %s not (yet) supported!\n", printf("%s: Device %s not (yet) supported!\n",
__func__, interface); __func__, interface);
@ -569,7 +572,7 @@ int dfu_config_entities(char *env, char *interface, char *devstr)
const char *dfu_get_dev_type(enum dfu_device_type t) const char *dfu_get_dev_type(enum dfu_device_type t)
{ {
const char *const dev_t[] = {NULL, "eMMC", "OneNAND", "NAND", "RAM", const char *const dev_t[] = {NULL, "eMMC", "OneNAND", "NAND", "RAM",
"SF", "MTD"}; "SF", "MTD", "VIRT"};
return dev_t[t]; return dev_t[t];
} }

49
drivers/dfu/dfu_virt.c Normal file
View File

@ -0,0 +1,49 @@
// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
/*
* Copyright (C) 2019, STMicroelectronics - All Rights Reserved
*/
#include <common.h>
#include <dfu.h>
#include <errno.h>
#include <malloc.h>
int __weak dfu_write_medium_virt(struct dfu_entity *dfu, u64 offset,
void *buf, long *len)
{
debug("%s: off=0x%llx, len=0x%x\n", __func__, offset, (u32)*len);
return 0;
}
int __weak dfu_get_medium_size_virt(struct dfu_entity *dfu, u64 *size)
{
*size = 0;
return 0;
}
int __weak dfu_read_medium_virt(struct dfu_entity *dfu, u64 offset,
void *buf, long *len)
{
debug("%s: off=0x%llx, len=0x%x\n", __func__, offset, (u32)*len);
*len = 0;
return 0;
}
int dfu_fill_entity_virt(struct dfu_entity *dfu, char *devstr, char *s)
{
debug("%s: devstr = %s\n", __func__, devstr);
dfu->dev_type = DFU_DEV_VIRT;
dfu->layout = DFU_RAW_ADDR;
dfu->data.virt.dev_num = simple_strtoul(devstr, NULL, 10);
dfu->write_medium = dfu_write_medium_virt;
dfu->get_medium_size = dfu_get_medium_size_virt;
dfu->read_medium = dfu_read_medium_virt;
dfu->inited = 0;
return 0;
}

View File

@ -23,6 +23,7 @@ enum dfu_device_type {
DFU_DEV_RAM, DFU_DEV_RAM,
DFU_DEV_SF, DFU_DEV_SF,
DFU_DEV_MTD, DFU_DEV_MTD,
DFU_DEV_VIRT,
}; };
enum dfu_layout { enum dfu_layout {
@ -92,6 +93,10 @@ struct sf_internal_data {
unsigned int ubi; unsigned int ubi;
}; };
struct virt_internal_data {
int dev_num;
};
#define DFU_NAME_SIZE 32 #define DFU_NAME_SIZE 32
#ifndef CONFIG_SYS_DFU_DATA_BUF_SIZE #ifndef CONFIG_SYS_DFU_DATA_BUF_SIZE
#define CONFIG_SYS_DFU_DATA_BUF_SIZE (1024*1024*8) /* 8 MiB */ #define CONFIG_SYS_DFU_DATA_BUF_SIZE (1024*1024*8) /* 8 MiB */
@ -120,6 +125,7 @@ struct dfu_entity {
struct nand_internal_data nand; struct nand_internal_data nand;
struct ram_internal_data ram; struct ram_internal_data ram;
struct sf_internal_data sf; struct sf_internal_data sf;
struct virt_internal_data virt;
} data; } data;
int (*get_medium_size)(struct dfu_entity *dfu, u64 *size); int (*get_medium_size)(struct dfu_entity *dfu, u64 *size);
@ -272,6 +278,22 @@ static inline int dfu_fill_entity_mtd(struct dfu_entity *dfu, char *devstr,
} }
#endif #endif
#ifdef CONFIG_DFU_VIRT
int dfu_fill_entity_virt(struct dfu_entity *dfu, char *devstr, char *s);
int dfu_write_medium_virt(struct dfu_entity *dfu, u64 offset,
void *buf, long *len);
int dfu_get_medium_size_virt(struct dfu_entity *dfu, u64 *size);
int dfu_read_medium_virt(struct dfu_entity *dfu, u64 offset,
void *buf, long *len);
#else
static inline int dfu_fill_entity_virt(struct dfu_entity *dfu, char *devstr,
char *s)
{
puts("VIRT support not available!\n");
return -1;
}
#endif
/** /**
* dfu_tftp_write - Write TFTP data to DFU medium * dfu_tftp_write - Write TFTP data to DFU medium
* *