u-boot/lib/fwu_updates/fwu_gpt.c
Sughosh Ganu 7d6e2c54b7 FWU: Add helper functions for accessing FWU metadata
Add weak functions for getting the update index value and dfu
alternate number needed for FWU Multi Bank update
functionality.

The current implementation for getting the update index value is for
platforms with 2 banks. If a platform supports more than 2 banks, it
can implement it's own function. The function to get the dfu alternate
number has been added for platforms with GPT partitioned storage
devices. Platforms with other storage partition scheme need to
implement their own function.

Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
Acked-by: Etienne Carriere <etienne.carriere@linaro.org>
Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
2022-10-31 14:47:32 -04:00

123 lines
2.6 KiB
C

// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2022, Linaro Limited
*/
#include <blk.h>
#include <dfu.h>
#include <efi.h>
#include <efi_loader.h>
#include <fwu.h>
#include <log.h>
#include <part.h>
#include <linux/errno.h>
static int get_gpt_dfu_identifier(struct blk_desc *desc, efi_guid_t *image_guid)
{
int i;
struct disk_partition info;
efi_guid_t unique_part_guid;
for (i = 1; i < MAX_SEARCH_PARTITIONS; i++) {
if (part_get_info(desc, i, &info))
continue;
uuid_str_to_bin(info.uuid, unique_part_guid.b,
UUID_STR_FORMAT_GUID);
if (!guidcmp(&unique_part_guid, image_guid))
return i;
}
log_err("No partition found with image_guid %pUs\n", image_guid);
return -ENOENT;
}
static int fwu_alt_num_for_dfu_dev(struct dfu_entity *dfu, int dev_num,
int part, unsigned char dfu_dev,
u8 *alt_num)
{
int ret;
switch(dfu_dev) {
case DFU_DEV_MMC:
if (dfu->layout == DFU_RAW_ADDR &&
dfu->data.mmc.dev_num == dev_num &&
dfu->data.mmc.part == part) {
*alt_num = dfu->alt;
ret = 0;
} else {
ret = -ENOENT;
}
break;
default:
ret = -ENOENT;
}
return ret;
}
static int fwu_gpt_get_alt_num(struct blk_desc *desc, efi_guid_t *image_guid,
u8 *alt_num, unsigned char dfu_dev)
{
int ret = -1;
int i, part, dev_num;
struct dfu_entity *dfu;
dev_num = desc->devnum;
part = get_gpt_dfu_identifier(desc, image_guid);
if (part < 0)
return -ENOENT;
ret = dfu_init_env_entities(NULL, NULL);
if (ret)
goto out;
i = 0;
while (true) {
dfu = dfu_get_entity(i++);
if (!dfu) {
ret = -ENOENT;
break;
}
if (dfu->dev_type != dfu_dev)
continue;
ret = fwu_alt_num_for_dfu_dev(dfu, dev_num, part, dfu_dev,
alt_num);
if (!ret)
break;
}
out:
dfu_free_entities();
return ret;
}
/**
* fwu_plat_get_alt_num() - Get the DFU alt number
* @dev: FWU metadata device
* @image_guid: GUID value of the image for which the alt num is to
* be obtained
* @alt_num: The DFU alt number for the image that is to be updated
*
* Get the DFU alt number for the image that is to be updated. The
* image is identified with the image_guid parameter that is passed
* to the function.
*
* Note: This is a weak function and platforms can override this with
* their own implementation for obtaining the alt number value.
*
* Return: 0 if OK, -ve on error
*
*/
__weak int fwu_plat_get_alt_num(struct udevice *dev, efi_guid_t *image_guid,
u8 *alt_num)
{
struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev);
return fwu_gpt_get_alt_num(dev_get_uclass_plat(priv->blk_dev),
image_guid, alt_num, DFU_DEV_MMC);
}