Provide a way to pass the 'fake go' flag from the bootflow flag through to the PXE implementation, so that a request for a fake go (via 'bootflow boot -f') is handled correctly in the bootmeth and when booting. Add a little more debugging of this in PXE. Signed-off-by: Simon Glass <sjg@chromium.org>
145 lines
3.1 KiB
C
145 lines
3.1 KiB
C
// SPDX-License-Identifier: GPL-2.0+
|
|
/*
|
|
* Common functions for extlinux and PXE
|
|
*
|
|
* Copyright 2024 Collabora
|
|
* Written by Martyn Welch <martyn.welch@collabora.com>
|
|
*/
|
|
|
|
#define LOG_CATEGORY UCLASS_BOOTSTD
|
|
|
|
#include <dm.h>
|
|
#include <extlinux.h>
|
|
#include <mapmem.h>
|
|
#include <linux/string.h>
|
|
|
|
enum extlinux_option_type {
|
|
EO_FALLBACK,
|
|
EO_INVALID
|
|
};
|
|
|
|
struct extlinux_option {
|
|
char *name;
|
|
enum extlinux_option_type option;
|
|
};
|
|
|
|
static const struct extlinux_option options[] = {
|
|
{"fallback", EO_FALLBACK},
|
|
{NULL, EO_INVALID}
|
|
};
|
|
|
|
static enum extlinux_option_type extlinux_get_option(const char *option)
|
|
{
|
|
int i = 0;
|
|
|
|
while (options[i].name) {
|
|
if (!strcmp(options[i].name, option))
|
|
return options[i].option;
|
|
|
|
i++;
|
|
}
|
|
|
|
return EO_INVALID;
|
|
};
|
|
|
|
int extlinux_set_property(struct udevice *dev, const char *property,
|
|
const char *value)
|
|
{
|
|
struct extlinux_plat *plat;
|
|
static enum extlinux_option_type option;
|
|
|
|
plat = dev_get_plat(dev);
|
|
|
|
option = extlinux_get_option(property);
|
|
if (option == EO_INVALID) {
|
|
printf("Invalid option\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
switch (option) {
|
|
case EO_FALLBACK:
|
|
if (!strcmp(value, "1")) {
|
|
plat->use_fallback = true;
|
|
} else if (!strcmp(value, "0")) {
|
|
plat->use_fallback = false;
|
|
} else {
|
|
printf("Unexpected value '%s'\n", value);
|
|
return -EINVAL;
|
|
}
|
|
break;
|
|
default:
|
|
printf("Unrecognised property '%s'\n", property);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int extlinux_setup(struct udevice *dev, struct bootflow *bflow,
|
|
pxe_getfile_func getfile, bool allow_abs_path,
|
|
const char *bootfile, struct pxe_context *ctx)
|
|
{
|
|
struct extlinux_plat *plat = dev_get_plat(dev);
|
|
int ret;
|
|
|
|
plat->info.dev = dev;
|
|
plat->info.bflow = bflow;
|
|
|
|
ret = pxe_setup_ctx(ctx, getfile, &plat->info, allow_abs_path, bootfile,
|
|
false, plat->use_fallback, bflow);
|
|
if (ret)
|
|
return log_msg_ret("ctx", ret);
|
|
log_debug("bootfl flags %x\n", bflow->flags);
|
|
if (bflow->flags & BOOTFLOWF_FAKE_GO)
|
|
ctx->fake_go = true;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int extlinux_boot(struct udevice *dev, struct bootflow *bflow,
|
|
pxe_getfile_func getfile, bool allow_abs_path,
|
|
const char *bootfile, bool restart)
|
|
{
|
|
struct extlinux_plat *plat = dev_get_plat(dev);
|
|
ulong addr;
|
|
int ret;
|
|
|
|
/* if we have already selected a label, just boot it */
|
|
if (plat->ctx.label) {
|
|
plat->ctx.fake_go = bflow->flags & BOOTFLOWF_FAKE_GO;
|
|
ret = pxe_do_boot(&plat->ctx);
|
|
} else {
|
|
ret = extlinux_setup(dev, bflow, getfile, allow_abs_path,
|
|
bootfile, &plat->ctx);
|
|
if (ret)
|
|
return log_msg_ret("elb", ret);
|
|
plat->ctx.restart = restart;
|
|
addr = map_to_sysmem(bflow->buf);
|
|
ret = pxe_process(&plat->ctx, addr, false);
|
|
}
|
|
if (ret)
|
|
return log_msg_ret("elb", -EFAULT);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int extlinux_read_all(struct udevice *dev, struct bootflow *bflow,
|
|
pxe_getfile_func getfile, bool allow_abs_path,
|
|
const char *bootfile)
|
|
{
|
|
struct extlinux_plat *plat = dev_get_plat(dev);
|
|
ulong addr;
|
|
int ret;
|
|
|
|
ret = extlinux_setup(dev, bflow, getfile, allow_abs_path, bootfile,
|
|
&plat->ctx);
|
|
if (ret)
|
|
return log_msg_ret("era", ret);
|
|
addr = map_to_sysmem(bflow->buf);
|
|
ret = pxe_probe(&plat->ctx, addr, false);
|
|
if (ret)
|
|
return log_msg_ret("elb", -EFAULT);
|
|
|
|
return 0;
|
|
}
|