From: Sughosh Ganu <sughosh.g...@linaro.org> Add helper functions needed for accessing the FWU metadata which contains information on the updatable images.
Signed-off-by: Sughosh Ganu <sughosh.g...@linaro.org> Signed-off-by: Jassi Brar <jaswinder.si...@linaro.org> --- include/fwu.h | 27 ++++++ lib/fwu_updates/Makefile | 1 + lib/fwu_updates/fwu_mtd.c | 172 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 200 insertions(+) create mode 100644 lib/fwu_updates/fwu_mtd.c diff --git a/include/fwu.h b/include/fwu.h index ea25aca2cd..2edfa72caf 100644 --- a/include/fwu.h +++ b/include/fwu.h @@ -8,6 +8,7 @@ #include <blk.h> #include <efi.h> +#include <mtd.h> #include <linux/types.h> @@ -251,4 +252,30 @@ u8 fwu_empty_capsule_checks_pass(void); */ int fwu_trial_state_ctr_start(void); +/** + * fwu_gen_alt_info_from_mtd() - Parse dfu_alt_info from metadata in mtd + * @buf: Buffer into which the dfu_alt_info is filled + * @len: Maximum charaters that can be written in buf + * @mtd: Pointer to underlying MTD device + * + * Parse dfu_alt_info from metadata in mtd. Used for setting the env. + * + * Return: 0 if OK, -ve on error + * + */ +int fwu_gen_alt_info_from_mtd(char *buf, size_t len, struct mtd_info *mtd); + +/** + * fwu_mtd_get_alt_num() - Mapping of fwu_plat_get_alt_num for MTD device + * @image_guid: Image GUID for which DFU alt number needs to be retrieved + * @alt_num: Pointer to the alt_num + * @mtd_dev: Name of mtd device instance + * + * To map fwu_plat_get_alt_num onto mtd based metadata implementation. + * + * Return: 0 if OK, -ve on error + * + */ +int fwu_mtd_get_alt_num(efi_guid_t *image_id, u8 *alt_num, const char *mtd_dev); + #endif /* _FWU_H_ */ diff --git a/lib/fwu_updates/Makefile b/lib/fwu_updates/Makefile index 1993088e5b..c9e3c06b48 100644 --- a/lib/fwu_updates/Makefile +++ b/lib/fwu_updates/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_FWU_MULTI_BANK_UPDATE) += fwu.o obj-$(CONFIG_FWU_MDATA_GPT_BLK) += fwu_gpt.o +obj-$(CONFIG_FWU_MDATA_MTD) += fwu_mtd.o diff --git a/lib/fwu_updates/fwu_mtd.c b/lib/fwu_updates/fwu_mtd.c new file mode 100644 index 0000000000..1895b8fab3 --- /dev/null +++ b/lib/fwu_updates/fwu_mtd.c @@ -0,0 +1,172 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2023, Linaro Limited + */ + +#include <dm.h> +#include <dfu.h> +#include <fwu.h> +#include <fwu_mdata.h> +#include <log.h> +#include <malloc.h> +#include <mtd.h> +#include <uuid.h> +#include <vsprintf.h> + +#include <dm/ofnode.h> + +int fwu_mtd_get_alt_num(efi_guid_t *image_id, u8 *alt_num, + const char *mtd_dev) +{ + int i, nalt; + int ret = -1; + struct mtd_info *mtd; + struct dfu_entity *dfu; + ofnode node, parts_node; + fdt_addr_t offset, size; + char uuidbuf[UUID_STR_LEN + 1]; + + mtd_probe_devices(); + mtd = get_mtd_device_nm(mtd_dev); + + /* Find partition node under given MTD device. */ + parts_node = ofnode_by_compatible(mtd_get_ofnode(mtd), + "fixed-partitions"); + + uuid_bin_to_str(image_id->b, uuidbuf, UUID_STR_FORMAT_STD); + node = ofnode_by_prop_value(parts_node, "uuid", uuidbuf, + sizeof(uuidbuf)); + if (!ofnode_valid(node)) { + log_warning("Warning: Failed to find partition by image UUID\n"); + return -ENOENT; + } + + offset = ofnode_get_addr_size_index_notrans(node, 0, &size); + if (offset == FDT_ADDR_T_NONE || !size) + return -ENOENT; + + dfu_init_env_entities(NULL, NULL); + + nalt = 0; + list_for_each_entry(dfu, &dfu_list, list) + nalt++; + + if (!nalt) { + log_warning("No entities in dfu_alt_info\n"); + dfu_free_entities(); + return -ENOENT; + } + + for (i = 0; i < nalt; i++) { + dfu = dfu_get_entity(i); + + /* Only MTD RAW access */ + if (!dfu || dfu->dev_type != DFU_DEV_MTD || + dfu->layout != DFU_RAW_ADDR || + dfu->data.mtd.start != offset || + dfu->data.mtd.size != size) + continue; + + *alt_num = dfu->alt; + ret = 0; + break; + } + + dfu_free_entities(); + + return ret; +} + +static int gen_image_alt_info(char *buf, size_t len, int sidx, + struct fwu_image_entry *img, struct mtd_info *mtd) +{ + int i; + const char *suuid; + ofnode node, parts_node; + char uuidbuf[UUID_STR_LEN + 1]; + char *p = buf, *end = buf + len; + + /* Find partition node under given MTD device. */ + parts_node = ofnode_by_compatible(mtd_get_ofnode(mtd), + "fixed-partitions"); + if (!ofnode_valid(parts_node)) + return -ENOENT; + + /* Check the media UUID if exist. */ + suuid = ofnode_read_string(parts_node, "uuid"); + if (suuid) { + log_debug("Got location uuid %s\n", suuid); + uuid_bin_to_str(img->location_uuid.b, uuidbuf, UUID_STR_FORMAT_STD); + if (strcasecmp(suuid, uuidbuf)) + log_warning("Warning: Location UUID does not match!\n"); + } + + p += snprintf(p, end - p, "mtd %s", mtd->name); + if (end < p) { + log_err("%s:%d Run out of buffer\n", __func__, __LINE__); + return -E2BIG; + } + + /* + * List the image banks in the FWU mdata and search the corresponding + * partition based on partition's uuid. + */ + for (i = 0; i < CONFIG_FWU_NUM_BANKS; i++) { + struct fwu_image_bank_info *bank; + fdt_addr_t offset, size; + + /* Query a partition by image UUID */ + bank = &img->img_bank_info[i]; + uuid_bin_to_str(bank->image_uuid.b, uuidbuf, UUID_STR_FORMAT_STD); + node = ofnode_by_prop_value(parts_node, "uuid", uuidbuf, + sizeof(uuidbuf)); + if (!ofnode_valid(node)) { + log_err("Failed to find partition by image UUID\n"); + break; + } + + offset = ofnode_get_addr_size_index_notrans(node, 0, &size); + if (offset == FDT_ADDR_T_NONE || !size) + break; + + p += snprintf(p, end - p, "%sbank%d raw %lx %lx", + i == 0 ? "=" : ";", i, (unsigned long)offset, + (unsigned long)size); + if (end < p) { + log_err("%s:%d Run out of buffer\n", __func__, __LINE__); + return -E2BIG; + } + } + + if (i == CONFIG_FWU_NUM_BANKS) + return 0; + + return -ENOENT; +} + +int fwu_gen_alt_info_from_mtd(char *buf, size_t len, struct mtd_info *mtd) +{ + struct fwu_mdata mdata; + int i, l, ret; + + ret = fwu_get_mdata(&mdata); + if (ret < 0) { + log_debug("Failed to get the FWU mdata.\n"); + return ret; + } + + for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) { + ret = gen_image_alt_info(buf, len, i * CONFIG_FWU_NUM_BANKS, + &mdata.img_entry[i], mtd); + if (ret) + break; + l = strlen(buf); + /* Replace the last ';' with '&' if there is another image. */ + if (i != CONFIG_FWU_NUM_IMAGES_PER_BANK - 1 && l) + buf[l - 1] = '&'; + len -= l; + buf += l; + } + + return ret; +} -- 2.34.1