Files
u-boot/boot/ext_pxe_common.c
Simon Glass aaf889390f boot: Support a fake go with pxe
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>
2025-09-22 11:23:05 -06:00

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;
}