// SPDX-License-Identifier: GPL-2.0+
/*
 * Bootmethod for extlinux boot using PXE (network boot)
 *
 * Copyright 2021 Google LLC
 * Written by Simon Glass <sjg@chromium.org>
 */

#define LOG_CATEGORY UCLASS_BOOTSTD

#include <bootdev.h>
#include <bootflow.h>
#include <bootmeth.h>
#include <command.h>
#include <dm.h>
#include <extlinux.h>
#include <fs.h>
#include <log.h>
#include <malloc.h>
#include <mapmem.h>
#include <mmc.h>
#include <net.h>
#include <pxe_utils.h>

static int extlinux_pxe_getfile(struct pxe_context *ctx, const char *file_path,
				char *file_addr, ulong *sizep)
{
	struct extlinux_info *info = ctx->userdata;
	ulong addr;
	int ret;

	addr = simple_strtoul(file_addr, NULL, 16);

	/* Allow up to 1GB */
	*sizep = 1 << 30;
	ret = bootmeth_read_file(info->dev, info->bflow, file_path, addr,
				 sizep);
	if (ret)
		return log_msg_ret("read", ret);

	return 0;
}

static int extlinux_pxe_check(struct udevice *dev, struct bootflow_iter *iter)
{
	int ret;

	/* This only works on network devices */
	ret = bootflow_iter_check_net(iter);
	if (ret)
		return log_msg_ret("net", ret);

	if (iter->method_flags & BOOTFLOW_METHF_DHCP_ONLY)
		return log_msg_ret("dhcp", -ENOTSUPP);

	return 0;
}

static int extlinux_pxe_read_bootflow(struct udevice *dev,
				      struct bootflow *bflow)
{
	const char *addr_str;
	char fname[200];
	char *bootdir;
	ulong addr;
	ulong size;
	char *buf;
	int ret;

	addr_str = env_get("pxefile_addr_r");
	if (!addr_str)
		return log_msg_ret("pxeb", -EPERM);
	addr = simple_strtoul(addr_str, NULL, 16);

	log_debug("calling pxe_get()\n");
	ret = pxe_get(addr, &bootdir, &size, false);
	log_debug("pxe_get() returned %d\n", ret);
	if (ret)
		return log_msg_ret("pxeb", ret);
	bflow->size = size;

	/* Use the directory of the dhcp bootdir as our subdir, if provided */
	if (bootdir) {
		const char *last_slash;
		int path_len;

		last_slash = strrchr(bootdir, '/');
		if (last_slash) {
			path_len = (last_slash - bootdir) + 1;
			bflow->subdir = malloc(path_len + 1);
			memcpy(bflow->subdir, bootdir, path_len);
			bflow->subdir[path_len] = '\0';
		}
	}
	snprintf(fname, sizeof(fname), "%s%s",
		 bflow->subdir ? bflow->subdir : "", EXTLINUX_FNAME);

	bflow->fname = strdup(fname);
	if (!bflow->fname)
		return log_msg_ret("name", -ENOMEM);

	bflow->state = BOOTFLOWST_READY;

	/* Allocate the buffer, including the \0 byte added by get_pxe_file() */
	buf = malloc(size + 1);
	if (!buf)
		return log_msg_ret("buf", -ENOMEM);
	memcpy(buf, map_sysmem(addr, 0), size + 1);
	bflow->buf = buf;

	return 0;
}

static int extlinux_pxe_read_file(struct udevice *dev, struct bootflow *bflow,
				  const char *file_path, ulong addr,
				  ulong *sizep)
{
	char *tftp_argv[] = {"tftp", NULL, NULL, NULL};
	struct pxe_context *ctx = dev_get_priv(dev);
	char file_addr[17];
	ulong size;
	int ret;

	sprintf(file_addr, "%lx", addr);
	tftp_argv[1] = file_addr;
	tftp_argv[2] = (void *)file_path;

	if (do_tftpb(ctx->cmdtp, 0, 3, tftp_argv))
		return -ENOENT;
	ret = pxe_get_file_size(&size);
	if (ret)
		return log_msg_ret("tftp", ret);
	if (size > *sizep)
		return log_msg_ret("spc", -ENOSPC);
	*sizep = size;

	return 0;
}

static int extlinux_pxe_boot(struct udevice *dev, struct bootflow *bflow)
{
	struct pxe_context *ctx = dev_get_priv(dev);
	struct cmd_tbl cmdtp = {};	/* dummy */
	struct extlinux_info info;
	ulong addr;
	int ret;

	addr = map_to_sysmem(bflow->buf);
	info.dev = dev;
	info.bflow = bflow;
	info.cmdtp = &cmdtp;
	ret = pxe_setup_ctx(ctx, &cmdtp, extlinux_pxe_getfile, &info, false,
			    bflow->subdir, false);
	if (ret)
		return log_msg_ret("ctx", -EINVAL);

	ret = pxe_process(ctx, addr, false);
	if (ret)
		return log_msg_ret("bread", -EINVAL);

	return 0;
}

static int extlinux_bootmeth_pxe_bind(struct udevice *dev)
{
	struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev);

	plat->desc = IS_ENABLED(CONFIG_BOOTSTD_FULL) ?
		"PXE boot from a network device" : "PXE";

	return 0;
}

static struct bootmeth_ops extlinux_bootmeth_pxe_ops = {
	.check		= extlinux_pxe_check,
	.read_bootflow	= extlinux_pxe_read_bootflow,
	.read_file	= extlinux_pxe_read_file,
	.boot		= extlinux_pxe_boot,
};

static const struct udevice_id extlinux_bootmeth_pxe_ids[] = {
	{ .compatible = "u-boot,extlinux-pxe" },
	{ }
};

U_BOOT_DRIVER(bootmeth_zpxe) = {
	.name		= "bootmeth_pxe",
	.id		= UCLASS_BOOTMETH,
	.of_match	= extlinux_bootmeth_pxe_ids,
	.ops		= &extlinux_bootmeth_pxe_ops,
	.bind		= extlinux_bootmeth_pxe_bind,
	.priv_auto	= sizeof(struct pxe_context),
};
