| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- // 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>
- struct fwu_mtd_image_info
- fwu_mtd_images[CONFIG_FWU_NUM_BANKS * CONFIG_FWU_NUM_IMAGES_PER_BANK];
- static struct fwu_mtd_image_info *mtd_img_by_uuid(const char *uuidbuf)
- {
- int num_images = ARRAY_SIZE(fwu_mtd_images);
- for (int i = 0; i < num_images; i++)
- if (!strcmp(uuidbuf, fwu_mtd_images[i].uuidbuf))
- return &fwu_mtd_images[i];
- return NULL;
- }
- int fwu_mtd_get_alt_num(efi_guid_t *image_id, u8 *alt_num,
- const char *mtd_dev)
- {
- struct fwu_mtd_image_info *mtd_img_info;
- char uuidbuf[UUID_STR_LEN + 1];
- fdt_addr_t offset, size = 0;
- struct dfu_entity *dfu;
- int i, nalt, ret;
- mtd_probe_devices();
- uuid_bin_to_str(image_id->b, uuidbuf, UUID_STR_FORMAT_STD);
- mtd_img_info = mtd_img_by_uuid(uuidbuf);
- if (!mtd_img_info) {
- log_err("%s: Not found partition for image %s\n", __func__, uuidbuf);
- return -ENOENT;
- }
- offset = mtd_img_info->start;
- size = mtd_img_info->size;
- ret = dfu_init_env_entities(NULL, NULL);
- if (ret)
- return -ENOENT;
- 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;
- }
- ret = -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();
- log_debug("%s: %s -> %d\n", __func__, uuidbuf, *alt_num);
- return ret;
- }
- /**
- * fwu_plat_get_alt_num() - Get the DFU Alt Num for the image from the platform
- * @dev: FWU device
- * @image_id: Image GUID for which DFU alt number needs to be retrieved
- * @alt_num: Pointer to the alt_num
- *
- * Get the DFU alt number from the platform for the image specified by the
- * image GUID.
- *
- * 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_id,
- u8 *alt_num)
- {
- return fwu_mtd_get_alt_num(image_id, alt_num, "nor1");
- }
- static int gen_image_alt_info(char *buf, size_t len, int sidx,
- struct fwu_image_entry *img, struct mtd_info *mtd)
- {
- char *p = buf, *end = buf + len;
- int i;
- 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_mtd_image_info *mtd_img_info;
- struct fwu_image_bank_info *bank;
- char uuidbuf[UUID_STR_LEN + 1];
- u32 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);
- mtd_img_info = mtd_img_by_uuid(uuidbuf);
- if (!mtd_img_info) {
- log_err("%s: Not found partition for image %s\n", __func__, uuidbuf);
- break;
- }
- offset = mtd_img_info->start;
- size = mtd_img_info->size;
- p += snprintf(p, end - p, "%sbank%d raw %x %x",
- i == 0 ? "=" : ";", i, offset, 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_err("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] = '&';
- buf++;
- }
- len -= l;
- buf += l;
- }
- return ret;
- }
|