// SPDX-License-Identifier: GPL-2.0+
/*
 * cmd_mbr.c -- MBR (Master Boot Record) handling command
 *
 * Copyright (C) 2020 Samsung Electronics
 * author: Marek Szyprowski <m.szyprowski@samsung.com>
 *
 * based on the gpt command.
 */

#include <blk.h>
#include <command.h>
#include <env.h>
#include <malloc.h>
#include <part.h>
#include <vsprintf.h>

/**
 * extract_val() - Extract a value from the key=value pair list
 * @str: pointer to string with key=values pairs
 * @key: pointer to the key to search for
 *
 * The list of parameters is come separated, only a value for
 * the given key is returend.
 *
 * Function allocates memory for the value, remember to free!
 *
 * Return: Pointer to allocated string with the value.
 */
static char *extract_val(const char *str, const char *key)
{
	char *v, *k;
	char *s, *strcopy;
	char *new = NULL;

	strcopy = strdup(str);
	if (strcopy == NULL)
		return NULL;

	s = strcopy;
	while (s) {
		v = strsep(&s, ",");
		if (!v)
			break;
		k = strsep(&v, "=");
		if (!k)
			break;
		if  (strcmp(k, key) == 0) {
			new = strdup(v);
			break;
		}
	}

	free(strcopy);

	return new;
}

/**
 * found_key() - Search for a key without a value in the parameter list
 * @str: pointer to string with key
 * @key: pointer to the key to search for
 *
 * The list of parameters is come separated.
 *
 * Return: True if key has been found.
 */
static bool found_key(const char *str, const char *key)
{
	char *k;
	char *s, *strcopy;
	bool result = false;

	strcopy = strdup(str);
	if (!strcopy)
		return NULL;

	s = strcopy;
	while (s) {
		k = strsep(&s, ",");
		if (!k)
			break;
		if  (strcmp(k, key) == 0) {
			result = true;
			break;
		}
	}

	free(strcopy);

	return result;
}

static int str_to_partitions(const char *str_part, int blksz,
	unsigned long *disk_uuid, struct disk_partition **partitions,
	int *parts_count)
{
	char *tok, *str, *s;
	int i;
	char *val, *p;
	int p_count;
	struct disk_partition *parts;
	int errno = 0;
	uint64_t size_ll, start_ll;

	if (str_part == NULL)
		return -1;

	str = strdup(str_part);
	if (str == NULL)
		return -ENOMEM;

	/* extract disk guid */
	s = str;
	val = extract_val(str, "uuid_disk");
	if (val) {
		val = strsep(&val, ";");
		p = val;
		*disk_uuid = ustrtoull(p, &p, 0);
		free(val);
		/* Move s to first partition */
		strsep(&s, ";");
	}
	if (s == NULL) {
		printf("Error: is the partitions string NULL-terminated?\n");
		return -EINVAL;
	}

	/* remove the optional semicolon at the end of the string */
	i = strlen(s) - 1;
	if (s[i] == ';')
		s[i] = '\0';

	/* calculate expected number of partitions */
	p_count = 1;
	p = s;
	while (*p) {
		if (*p++ == ';')
			p_count++;
	}

	/* allocate memory for partitions */
	parts = calloc(sizeof(struct disk_partition), p_count);
	if (parts == NULL)
		return -ENOMEM;

	/* retrieve partitions data from string */
	for (i = 0; i < p_count; i++) {
		tok = strsep(&s, ";");

		if (tok == NULL)
			break;

		/* size */
		val = extract_val(tok, "size");
		if (!val) { /* 'size' is mandatory */
			errno = -4;
			goto err;
		}
		p = val;
		if ((strcmp(p, "-") == 0)) {
			/* auto extend the size */
			parts[i].size = 0;
		} else {
			size_ll = ustrtoull(p, &p, 0);
			parts[i].size = size_ll / blksz;
		}
		free(val);

		/* start address */
		val = extract_val(tok, "start");
		if (val) { /* start address is optional */
			p = val;
			start_ll = ustrtoull(p, &p, 0);
			parts[i].start = start_ll / blksz;
			free(val);
		}

		/* system id */
		val = extract_val(tok, "id");
		if (!val) { /* '' is mandatory */
			errno = -4;
			goto err;
		}
		p = val;
		parts[i].sys_ind = ustrtoul(p, &p, 0);
		free(val);

		/* bootable */
		if (found_key(tok, "bootable"))
			parts[i].bootable = PART_BOOTABLE;
	}

	*parts_count = p_count;
	*partitions = parts;
	free(str);

	return 0;
err:
	free(str);
	free(parts);

	return errno;
}

static int do_write_mbr(struct blk_desc *dev, const char *str)
{
	unsigned long disk_uuid = 0;
	struct disk_partition *partitions;
	int blksz = dev->blksz;
	int count;

	if (str_to_partitions(str, blksz, &disk_uuid, &partitions, &count)) {
		printf("MBR: failed to setup partitions from \"%s\"\n", str);
		return -1;
	}

	if (layout_mbr_partitions(partitions, count, dev->lba)) {
		printf("MBR: failed to layout partitions on the device\n");
		free(partitions);
		return -1;
	}

	if (write_mbr_partitions(dev, partitions, count, disk_uuid)) {
		printf("MBR: failed to write partitions to the device\n");
		free(partitions);
		return -1;
	}

	return 0;
}

static int do_verify_mbr(struct blk_desc *dev, const char *str)
{
	unsigned long disk_uuid = 0;
	struct disk_partition *partitions;
	int blksz = dev->blksz;
	int count, i, ret = 1;

	if (str_to_partitions(str, blksz, &disk_uuid, &partitions, &count)) {
		printf("MBR: failed to setup partitions from \"%s\"\n", str);
		return -1;
	}

	for (i = 0; i < count; i++) {
		struct disk_partition p;

		if (part_get_info_by_type(dev, i + 1, PART_TYPE_DOS, &p))
			goto fail;

		if ((partitions[i].size && p.size != partitions[i].size) ||
		    (partitions[i].start && p.start != partitions[i].start) ||
		    p.sys_ind != partitions[i].sys_ind)
			goto fail;
	}
	ret = 0;
fail:
	free(partitions);
	return ret;
}

static int do_mbr(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{
	const char *parts = NULL;
	int ret = CMD_RET_SUCCESS;
	int dev = 0;
	char *ep;
	struct blk_desc *blk_dev_desc = NULL;

	if (argc != 4 && argc != 5)
		return CMD_RET_USAGE;

	dev = (int)dectoul(argv[3], &ep);
	if (!ep || ep[0] != '\0') {
		printf("'%s' is not a number\n", argv[3]);
		return CMD_RET_USAGE;
	}
	blk_dev_desc = blk_get_dev(argv[2], dev);
	if (!blk_dev_desc) {
		printf("%s: %s dev %d NOT available\n",
		       __func__, argv[2], dev);
		return CMD_RET_FAILURE;
	}

	if ((strcmp(argv[1], "write") == 0)) {
		parts = (argc == 5) ? argv[4] : env_get("mbr_parts");
		printf("MBR: write ");
		ret = do_write_mbr(blk_dev_desc, parts);
	} else if ((strcmp(argv[1], "verify") == 0)) {
		printf("MBR: verify ");
		parts = (argc == 5) ? argv[4] : env_get("mbr_parts");
		ret = do_verify_mbr(blk_dev_desc, parts);
	} else {
		return CMD_RET_USAGE;
	}

	if (ret) {
		printf("error!\n");
		return CMD_RET_FAILURE;
	}

	printf("success!\n");
	return CMD_RET_SUCCESS;
}

U_BOOT_CMD(mbr, CONFIG_SYS_MAXARGS, 1, do_mbr,
	"MBR (Master Boot Record)",
	"<command> <interface> <dev> <partitions_list>\n"
	" - MBR partition table restoration utility\n"
	" Restore or check partition information on a device connected\n"
	" to the given block interface\n"
	" Example usage:\n"
	" mbr write mmc 0 [\"${mbr_parts}\"]\n"
	" mbr verify mmc 0 [\"${partitions}\"]\n"
);
