/*
 * Copyright (c) 2012, Google Inc.
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include <common.h>
#include <fs.h>
#include <part.h>
#include <sandboxblockdev.h>
#include <asm/errno.h>

static int do_host_load(cmd_tbl_t *cmdtp, int flag, int argc,
			   char * const argv[])
{
	return do_load(cmdtp, flag, argc, argv, FS_TYPE_SANDBOX);
}

static int do_host_ls(cmd_tbl_t *cmdtp, int flag, int argc,
			   char * const argv[])
{
	return do_ls(cmdtp, flag, argc, argv, FS_TYPE_SANDBOX);
}

static int do_host_save(cmd_tbl_t *cmdtp, int flag, int argc,
			   char * const argv[])
{
	return do_save(cmdtp, flag, argc, argv, FS_TYPE_SANDBOX);
}

static int do_host_bind(cmd_tbl_t *cmdtp, int flag, int argc,
			   char * const argv[])
{
	if (argc < 2 || argc > 3)
		return CMD_RET_USAGE;
	char *ep;
	char *dev_str = argv[1];
	char *file = argc >= 3 ? argv[2] : NULL;
	int dev = simple_strtoul(dev_str, &ep, 16);
	if (*ep) {
		printf("** Bad device specification %s **\n", dev_str);
		return CMD_RET_USAGE;
	}
	return host_dev_bind(dev, file);
}

static int do_host_info(cmd_tbl_t *cmdtp, int flag, int argc,
			   char * const argv[])
{
	if (argc < 1 || argc > 2)
		return CMD_RET_USAGE;
	int min_dev = 0;
	int max_dev = CONFIG_HOST_MAX_DEVICES - 1;
	if (argc >= 2) {
		char *ep;
		char *dev_str = argv[1];
		int dev = simple_strtoul(dev_str, &ep, 16);
		if (*ep) {
			printf("** Bad device specification %s **\n", dev_str);
			return CMD_RET_USAGE;
		}
		min_dev = dev;
		max_dev = dev;
	}
	int dev;
	printf("%3s %12s %s\n", "dev", "blocks", "path");
	for (dev = min_dev; dev <= max_dev; dev++) {
		block_dev_desc_t *blk_dev;
		int ret;

		printf("%3d ", dev);
		ret = host_get_dev_err(dev, &blk_dev);
		if (ret) {
			if (ret == -ENOENT)
				puts("Not bound to a backing file\n");
			else if (ret == -ENODEV)
				puts("Invalid host device number\n");

			continue;
		}
		struct host_block_dev *host_dev = blk_dev->priv;
		printf("%12lu %s\n", (unsigned long)blk_dev->lba,
		       host_dev->filename);
	}
	return 0;
}

static cmd_tbl_t cmd_host_sub[] = {
	U_BOOT_CMD_MKENT(load, 7, 0, do_host_load, "", ""),
	U_BOOT_CMD_MKENT(ls, 3, 0, do_host_ls, "", ""),
	U_BOOT_CMD_MKENT(save, 6, 0, do_host_save, "", ""),
	U_BOOT_CMD_MKENT(bind, 3, 0, do_host_bind, "", ""),
	U_BOOT_CMD_MKENT(info, 3, 0, do_host_info, "", ""),
};

static int do_host(cmd_tbl_t *cmdtp, int flag, int argc,
		      char * const argv[])
{
	cmd_tbl_t *c;

	/* Skip past 'host' */
	argc--;
	argv++;

	c = find_cmd_tbl(argv[0], cmd_host_sub,
			 ARRAY_SIZE(cmd_host_sub));

	if (c)
		return c->cmd(cmdtp, flag, argc, argv);
	else
		return CMD_RET_USAGE;
}

U_BOOT_CMD(
	sb,	8,	1,	do_host,
	"Deprecated: use 'host' command instead.", ""
);

U_BOOT_CMD(
	host, 8, 1, do_host,
	"Miscellaneous host commands",
	"load hostfs - <addr> <filename> [<bytes> <offset>]  - "
		"load a file from host\n"
	"host ls hostfs - <filename>                    - list files on host\n"
	"host save hostfs - <addr> <filename> <bytes> [<offset>] - "
		"save a file to host\n"
	"host bind <dev> [<filename>] - bind \"host\" device to file\n"
	"host info [<dev>]            - show device binding & info\n"
	"host commands use the \"hostfs\" device. The \"host\" device is used\n"
	"with standard IO commands such as fatls or ext2load"
);
