// 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 <stdio.h>

#include <dm/ofnode.h>

static struct fwu_mtd_image_info *mtd_img_by_uuid(const char *uuidbuf)
{
	int num_images;
	struct fwu_mdata_mtd_priv *mtd_priv = dev_get_priv(fwu_get_dev());
	struct fwu_mtd_image_info *image_info = mtd_priv->fwu_mtd_images;

	if (!image_info)
		return NULL;

	num_images = CONFIG_FWU_NUM_BANKS *
		CONFIG_FWU_NUM_IMAGES_PER_BANK;

	for (int i = 0; i < num_images; i++)
		if (!strcmp(uuidbuf, image_info[i].uuidbuf))
			return &image_info[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 = list_count_nodes(&dfu_list);
	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,
			      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_guid.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)
{
	int i, l, ret;
	struct fwu_data *data = fwu_get_data();
	struct fwu_image_entry *img_entry;

	for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) {
		img_entry = &data->fwu_images[i];
		ret = gen_image_alt_info(buf, len, img_entry, 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;
}
