diff options
Diffstat (limited to 'lib/fwu_updates/fwu_gpt.c')
-rw-r--r-- | lib/fwu_updates/fwu_gpt.c | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/lib/fwu_updates/fwu_gpt.c b/lib/fwu_updates/fwu_gpt.c new file mode 100644 index 00000000000..21a573c9342 --- /dev/null +++ b/lib/fwu_updates/fwu_gpt.c @@ -0,0 +1,123 @@ +// 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); +} |