12290Sjjg// SPDX-License-Identifier: GPL-2.0+
23294Salanb/*
32290Sjjg * Copyright (c) 2020 Linaro Limited
42290Sjjg */
52290Sjjg
62290Sjjg#include <common.h>
72290Sjjg#include <dfu.h>
82290Sjjg#include <env.h>
92290Sjjg#include <memalign.h>
102290Sjjg#include <mtd.h>
112290Sjjg
122290Sjjg#define DFU_ALT_BUF_LEN		SZ_1K
132290Sjjg
142290Sjjgstatic void board_get_alt_info(struct mtd_info *mtd, char *buf)
152290Sjjg{
162290Sjjg	struct mtd_info *part;
172290Sjjg	bool first = true;
182290Sjjg	const char *name;
192290Sjjg	int len, partnum = 0;
202290Sjjg
212290Sjjg	name = mtd->name;
222290Sjjg	len = strlen(buf);
232290Sjjg
242290Sjjg	if (buf[0] != '\0')
252290Sjjg		len += snprintf(buf + len, DFU_ALT_BUF_LEN - len, "&");
262290Sjjg	len += snprintf(buf + len, DFU_ALT_BUF_LEN - len,
272290Sjjg			"mtd %s=", name);
283294Salanb
292290Sjjg	list_for_each_entry(part, &mtd->partitions, node) {
302290Sjjg		partnum++;
312290Sjjg		if (!first)
322290Sjjg			len += snprintf(buf + len, DFU_ALT_BUF_LEN - len, ";");
332290Sjjg		first = false;
342290Sjjg
352290Sjjg		len += snprintf(buf + len, DFU_ALT_BUF_LEN - len,
362290Sjjg				"%s part %d",
372290Sjjg				part->name, partnum);
382290Sjjg	}
392290Sjjg}
402290Sjjg
412290Sjjgvoid set_dfu_alt_info(char *interface, char *devstr)
422290Sjjg{
432290Sjjg	struct mtd_info *mtd;
442290Sjjg
452290Sjjg	ALLOC_CACHE_ALIGN_BUFFER(char, buf, DFU_ALT_BUF_LEN);
462290Sjjg
472290Sjjg	if (!IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) &&
482290Sjjg	    env_get("dfu_alt_info"))
492290Sjjg		return;
502290Sjjg
512290Sjjg	memset(buf, 0, DFU_ALT_BUF_LEN);
522290Sjjg
532290Sjjg	/*
542290Sjjg	 * Currently dfu_alt_info is needed on Qemu ARM64 for
552290Sjjg	 * capsule updates
562290Sjjg	*/
572290Sjjg	if (IS_ENABLED(CONFIG_EFI_CAPSULE_FIRMWARE_MANAGEMENT) &&
582290Sjjg	    IS_ENABLED(CONFIG_TARGET_QEMU_ARM_64BIT)) {
592290Sjjg		/* probe all MTD devices */
602290Sjjg		mtd_probe_devices();
612290Sjjg
622290Sjjg		mtd = get_mtd_device_nm("nor0");
632290Sjjg		if (!IS_ERR_OR_NULL(mtd))
642290Sjjg			board_get_alt_info(mtd, buf);
652290Sjjg	}
662290Sjjg
672290Sjjg	env_set("dfu_alt_info", buf);
682290Sjjg	printf("dfu_alt_info set\n");
692290Sjjg}
702290Sjjg