Merge patch series "FWU: Add support for FWU metadata version 2"

Sughosh Ganu <sughosh.ganu@linaro.org> says:

The following patch series adds support for version 2 of the FWU
metadata. The version 2 metadata structure is defined in the latest
revision of the FWU specification [1].

The earlier versions of these patches were migrating to a version 2
only support in U-Boot, similar to TF-A. However, based on feedback
from ST [2], this series has been updated to support both versions. A
platform would still be needed to enable one of the two versions of
metadata through a config symbol.

TF-A has code which reads the FWU metadata and boots the platform from
the active partition. TF-A has decided to migrate the FWU code to a
version 2 only support. These changes have been merged in upstream
TF-A.

These changes have been tested on the ST DK2 board, which uses the GPT
based partitioning scheme. Both V1 and V2 metadata versions have been
tested on the DK2 board.

These changes need to be tested on platforms with MTD partitioned
storage devices.
This commit is contained in:
Tom Rini
2024-05-24 13:42:07 -06:00
21 changed files with 1153 additions and 217 deletions

View File

@@ -19,7 +19,8 @@
*
* Return: 0 if OK, -ve on error
*/
int fwu_read_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool primary)
int fwu_read_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool primary,
uint32_t size)
{
const struct fwu_mdata_ops *ops = device_get_ops(dev);
@@ -28,7 +29,7 @@ int fwu_read_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool primary)
return -ENOSYS;
}
return ops->read_mdata(dev, mdata, primary);
return ops->read_mdata(dev, mdata, primary, size);
}
/**
@@ -36,7 +37,8 @@ int fwu_read_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool primary)
*
* Return: 0 if OK, -ve on error
*/
int fwu_write_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool primary)
int fwu_write_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool primary,
uint32_t size)
{
const struct fwu_mdata_ops *ops = device_get_ops(dev);
@@ -45,7 +47,7 @@ int fwu_write_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool primary)
return -ENOSYS;
}
return ops->write_mdata(dev, mdata, primary);
return ops->write_mdata(dev, mdata, primary, size);
}
UCLASS_DRIVER(fwu_mdata) = {

View File

@@ -81,15 +81,14 @@ static int gpt_get_mdata_disk_part(struct blk_desc *desc,
return -ENOENT;
}
static int gpt_read_write_mdata(struct blk_desc *desc,
struct fwu_mdata *mdata,
u8 access, u32 part_num)
static int gpt_read_write_mdata(struct blk_desc *desc, struct fwu_mdata *mdata,
u8 access, u32 part_num, u32 size)
{
int ret;
u32 len, blk_start, blkcnt;
struct disk_partition info;
ALLOC_CACHE_ALIGN_BUFFER_PAD(struct fwu_mdata, mdata_aligned, 1,
ALLOC_CACHE_ALIGN_BUFFER_PAD(u8, mdata_aligned, size,
desc->blksz);
if (!mdata)
@@ -101,7 +100,7 @@ static int gpt_read_write_mdata(struct blk_desc *desc,
return -ENOENT;
}
len = sizeof(*mdata);
len = size;
blkcnt = BLOCK_CNT(len, desc);
if (blkcnt > info.size) {
log_debug("Block count exceeds FWU metadata partition size\n");
@@ -114,7 +113,7 @@ static int gpt_read_write_mdata(struct blk_desc *desc,
log_debug("Error reading FWU metadata from the device\n");
return -EIO;
}
memcpy(mdata, mdata_aligned, sizeof(struct fwu_mdata));
memcpy(mdata, mdata_aligned, size);
} else {
if (blk_dwrite(desc, blk_start, blkcnt, mdata) != blkcnt) {
log_debug("Error writing FWU metadata to the device\n");
@@ -164,7 +163,7 @@ static int fwu_mdata_gpt_blk_probe(struct udevice *dev)
}
static int fwu_gpt_read_mdata(struct udevice *dev, struct fwu_mdata *mdata,
bool primary)
bool primary, u32 size)
{
struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev);
struct blk_desc *desc = dev_get_uclass_plat(priv->blk_dev);
@@ -177,11 +176,13 @@ static int fwu_gpt_read_mdata(struct udevice *dev, struct fwu_mdata *mdata,
}
return gpt_read_write_mdata(desc, mdata, MDATA_READ,
primary ? g_mdata_part[0] : g_mdata_part[1]);
primary ?
g_mdata_part[0] : g_mdata_part[1],
size);
}
static int fwu_gpt_write_mdata(struct udevice *dev, struct fwu_mdata *mdata,
bool primary)
bool primary, u32 size)
{
struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev);
struct blk_desc *desc = dev_get_uclass_plat(priv->blk_dev);
@@ -194,7 +195,9 @@ static int fwu_gpt_write_mdata(struct udevice *dev, struct fwu_mdata *mdata,
}
return gpt_read_write_mdata(desc, mdata, MDATA_WRITE,
primary ? g_mdata_part[0] : g_mdata_part[1]);
primary ?
g_mdata_part[0] : g_mdata_part[1],
size);
}
static const struct fwu_mdata_ops fwu_gpt_blk_ops = {

View File

@@ -12,22 +12,11 @@
#include <linux/errno.h>
#include <linux/types.h>
/* Internal helper structure to move data around */
struct fwu_mdata_mtd_priv {
struct mtd_info *mtd;
char pri_label[50];
char sec_label[50];
u32 pri_offset;
u32 sec_offset;
};
enum fwu_mtd_op {
FWU_MTD_READ,
FWU_MTD_WRITE,
};
extern struct fwu_mtd_image_info fwu_mtd_images[];
static bool mtd_is_aligned_with_block_size(struct mtd_info *mtd, u64 size)
{
return !do_div(size, mtd->erasesize);
@@ -97,22 +86,24 @@ lock:
return ret;
}
static int fwu_mtd_read_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool primary)
static int fwu_mtd_read_mdata(struct udevice *dev, struct fwu_mdata *mdata,
bool primary, u32 size)
{
struct fwu_mdata_mtd_priv *mtd_priv = dev_get_priv(dev);
struct mtd_info *mtd = mtd_priv->mtd;
u32 offs = primary ? mtd_priv->pri_offset : mtd_priv->sec_offset;
return mtd_io_data(mtd, offs, sizeof(struct fwu_mdata), mdata, FWU_MTD_READ);
return mtd_io_data(mtd, offs, size, mdata, FWU_MTD_READ);
}
static int fwu_mtd_write_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool primary)
static int fwu_mtd_write_mdata(struct udevice *dev, struct fwu_mdata *mdata,
bool primary, u32 size)
{
struct fwu_mdata_mtd_priv *mtd_priv = dev_get_priv(dev);
struct mtd_info *mtd = mtd_priv->mtd;
u32 offs = primary ? mtd_priv->pri_offset : mtd_priv->sec_offset;
return mtd_io_data(mtd, offs, sizeof(struct fwu_mdata), mdata, FWU_MTD_WRITE);
return mtd_io_data(mtd, offs, size, mdata, FWU_MTD_WRITE);
}
static int flash_partition_offset(struct udevice *dev, const char *part_name, fdt_addr_t *offset)
@@ -132,7 +123,7 @@ static int flash_partition_offset(struct udevice *dev, const char *part_name, fd
return (int)size;
}
static int fwu_mdata_mtd_of_to_plat(struct udevice *dev)
static int get_fwu_mdata_dev(struct udevice *dev)
{
struct fwu_mdata_mtd_priv *mtd_priv = dev_get_priv(dev);
const fdt32_t *phandle_p = NULL;
@@ -142,8 +133,6 @@ static int fwu_mdata_mtd_of_to_plat(struct udevice *dev)
fdt_addr_t offset;
int ret, size;
u32 phandle;
ofnode bank;
int off_img;
/* Find the FWU mdata storage device */
phandle_p = ofnode_get_property(dev_ofnode(dev),
@@ -197,8 +186,28 @@ static int fwu_mdata_mtd_of_to_plat(struct udevice *dev)
return ret;
mtd_priv->sec_offset = offset;
off_img = 0;
return 0;
}
static int fwu_mtd_image_info_populate(struct udevice *dev, u8 nbanks,
u16 nimages)
{
struct fwu_mtd_image_info *mtd_images;
struct fwu_mdata_mtd_priv *mtd_priv = dev_get_priv(dev);
struct udevice *mtd_dev = mtd_priv->mtd->dev;
fdt_addr_t offset;
ofnode bank;
int off_img;
u32 total_images;
total_images = nbanks * nimages;
mtd_priv->fwu_mtd_images = malloc(sizeof(struct fwu_mtd_image_info) *
total_images);
if (!mtd_priv->fwu_mtd_images)
return -ENOMEM;
off_img = 0;
mtd_images = mtd_priv->fwu_mtd_images;
ofnode_for_each_subnode(bank, dev_ofnode(dev)) {
int bank_num, bank_offset, bank_size;
const char *bank_name;
@@ -217,8 +226,7 @@ static int fwu_mdata_mtd_of_to_plat(struct udevice *dev)
int image_num, image_offset, image_size;
const char *uuid;
if (off_img == CONFIG_FWU_NUM_BANKS *
CONFIG_FWU_NUM_IMAGES_PER_BANK) {
if (off_img == total_images) {
log_err("DT provides more images than configured!\n");
break;
}
@@ -228,11 +236,11 @@ static int fwu_mdata_mtd_of_to_plat(struct udevice *dev)
ofnode_read_u32(image, "offset", &image_offset);
ofnode_read_u32(image, "size", &image_size);
fwu_mtd_images[off_img].start = bank_offset + image_offset;
fwu_mtd_images[off_img].size = image_size;
fwu_mtd_images[off_img].bank_num = bank_num;
fwu_mtd_images[off_img].image_num = image_num;
strcpy(fwu_mtd_images[off_img].uuidbuf, uuid);
mtd_images[off_img].start = bank_offset + image_offset;
mtd_images[off_img].size = image_size;
mtd_images[off_img].bank_num = bank_num;
mtd_images[off_img].image_num = image_num;
strcpy(mtd_images[off_img].uuidbuf, uuid);
log_debug("\tImage%d: %s @0x%x\n\n",
image_num, uuid, bank_offset + image_offset);
off_img++;
@@ -244,8 +252,21 @@ static int fwu_mdata_mtd_of_to_plat(struct udevice *dev)
static int fwu_mdata_mtd_probe(struct udevice *dev)
{
/* Ensure the metadata can be read. */
return fwu_get_mdata(NULL);
u8 nbanks;
u16 nimages;
int ret;
ret = get_fwu_mdata_dev(dev);
if (ret)
return ret;
nbanks = CONFIG_FWU_NUM_BANKS;
nimages = CONFIG_FWU_NUM_IMAGES_PER_BANK;
ret = fwu_mtd_image_info_populate(dev, nbanks, nimages);
if (ret)
return ret;
return 0;
}
static struct fwu_mdata_ops fwu_mtd_ops = {
@@ -264,6 +285,5 @@ U_BOOT_DRIVER(fwu_mdata_mtd) = {
.of_match = fwu_mdata_ids,
.ops = &fwu_mtd_ops,
.probe = fwu_mdata_mtd_probe,
.of_to_plat = fwu_mdata_mtd_of_to_plat,
.priv_auto = sizeof(struct fwu_mdata_mtd_priv),
};