summaryrefslogtreecommitdiff
path: root/boot
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2024-10-15 09:18:04 -0600
committerTom Rini <[email protected]>2024-10-15 11:38:44 -0600
commit4378732d5658accd07d2fb245417262a23f578ce (patch)
tree06b50e26d4b1582fb4c00393e83b4ede06537fa6 /boot
parent4f777c2ef20ad294af1d3447baf7dfffb7514ab3 (diff)
parent87980311fbb64369c29d8725fc8fb4fb35ae2f3c (diff)
Merge patch series to add a "fallback" keyword to extlinux.conf parsing
This series from Martyn Welch <[email protected]> adds the ability to have a "fallback" option in extlinux.conf parsing, which can be in turn used in A/B style update mechanisms. Link: https://lore.kernel.org/u-boot/[email protected]/
Diffstat (limited to 'boot')
-rw-r--r--boot/bootmeth-uclass.c25
-rw-r--r--boot/bootmeth_extlinux.c73
-rw-r--r--boot/bootmeth_pxe.c2
-rw-r--r--boot/pxe_utils.c29
4 files changed, 126 insertions, 3 deletions
diff --git a/boot/bootmeth-uclass.c b/boot/bootmeth-uclass.c
index c0abadef97c..5b5fea39b3b 100644
--- a/boot/bootmeth-uclass.c
+++ b/boot/bootmeth-uclass.c
@@ -251,6 +251,31 @@ int bootmeth_set_order(const char *order_str)
return 0;
}
+int bootmeth_set_property(const char *name, const char *property, const char *value)
+{
+ int ret;
+ int len;
+ struct udevice *dev;
+ const struct bootmeth_ops *ops;
+
+ len = strlen(name);
+
+ ret = uclass_find_device_by_namelen(UCLASS_BOOTMETH, name, len,
+ &dev);
+ if (ret) {
+ printf("Unknown bootmeth '%s'\n", name);
+ return ret;
+ }
+
+ ops = bootmeth_get_ops(dev);
+ if (!ops->set_property) {
+ printf("set_property not found\n");
+ return -ENODEV;
+ }
+
+ return ops->set_property(dev, property, value);
+}
+
int bootmeth_setup_fs(struct bootflow *bflow, struct blk_desc *desc)
{
int ret;
diff --git a/boot/bootmeth_extlinux.c b/boot/bootmeth_extlinux.c
index fbb05ef928e..be8fbf4df63 100644
--- a/boot/bootmeth_extlinux.c
+++ b/boot/bootmeth_extlinux.c
@@ -21,6 +21,39 @@
#include <mmc.h>
#include <pxe_utils.h>
+struct extlinux_plat {
+ bool use_fallback;
+};
+
+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 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;
+};
+
static int extlinux_get_state_desc(struct udevice *dev, char *buf, int maxsize)
{
if (IS_ENABLED(CONFIG_SANDBOX)) {
@@ -142,14 +175,18 @@ static int extlinux_boot(struct udevice *dev, struct bootflow *bflow)
struct cmd_tbl cmdtp = {}; /* dummy */
struct pxe_context ctx;
struct extlinux_info info;
+ struct extlinux_plat *plat;
ulong addr;
int ret;
addr = map_to_sysmem(bflow->buf);
info.dev = dev;
info.bflow = bflow;
+
+ plat = dev_get_plat(dev);
+
ret = pxe_setup_ctx(&ctx, &cmdtp, extlinux_getfile, &info, true,
- bflow->fname, false);
+ bflow->fname, false, plat->use_fallback);
if (ret)
return log_msg_ret("ctx", -EINVAL);
@@ -160,6 +197,38 @@ static int extlinux_boot(struct udevice *dev, struct bootflow *bflow)
return 0;
}
+static 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 = 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_bootmeth_bind(struct udevice *dev)
{
struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev);
@@ -176,6 +245,7 @@ static struct bootmeth_ops extlinux_bootmeth_ops = {
.read_bootflow = extlinux_read_bootflow,
.read_file = bootmeth_common_read_file,
.boot = extlinux_boot,
+ .set_property = extlinux_set_property,
};
static const struct udevice_id extlinux_bootmeth_ids[] = {
@@ -190,4 +260,5 @@ U_BOOT_DRIVER(bootmeth_1extlinux) = {
.of_match = extlinux_bootmeth_ids,
.ops = &extlinux_bootmeth_ops,
.bind = extlinux_bootmeth_bind,
+ .plat_auto = sizeof(struct extlinux_plat)
};
diff --git a/boot/bootmeth_pxe.c b/boot/bootmeth_pxe.c
index 03d2589c264..05c6bece2c1 100644
--- a/boot/bootmeth_pxe.c
+++ b/boot/bootmeth_pxe.c
@@ -150,7 +150,7 @@ static int extlinux_pxe_boot(struct udevice *dev, struct bootflow *bflow)
info.bflow = bflow;
info.cmdtp = &cmdtp;
ret = pxe_setup_ctx(ctx, &cmdtp, extlinux_pxe_getfile, &info, false,
- bflow->subdir, false);
+ bflow->subdir, false, false);
if (ret)
return log_msg_ret("ctx", -EINVAL);
diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c
index 4e27842b088..d6a4b2cb859 100644
--- a/boot/pxe_utils.c
+++ b/boot/pxe_utils.c
@@ -781,6 +781,7 @@ enum token_type {
T_IPAPPEND,
T_BACKGROUND,
T_KASLRSEED,
+ T_FALLBACK,
T_INVALID
};
@@ -814,6 +815,7 @@ static const struct token keywords[] = {
{"ipappend", T_IPAPPEND,},
{"background", T_BACKGROUND,},
{"kaslrseed", T_KASLRSEED,},
+ {"fallback", T_FALLBACK,},
{NULL, T_INVALID}
};
@@ -1356,6 +1358,18 @@ static int parse_pxefile_top(struct pxe_context *ctx, char *p, unsigned long bas
break;
+ case T_FALLBACK:
+ err = parse_sliteral(&p, &label_name);
+
+ if (label_name) {
+ if (cfg->fallback_label)
+ free(cfg->fallback_label);
+
+ cfg->fallback_label = label_name;
+ }
+
+ break;
+
case T_INCLUDE:
err = handle_include(ctx, &p,
base + ALIGN(strlen(b), 4), cfg,
@@ -1395,6 +1409,7 @@ void destroy_pxe_menu(struct pxe_menu *cfg)
free(cfg->title);
free(cfg->default_label);
+ free(cfg->fallback_label);
list_for_each_safe(pos, n, &cfg->labels) {
label = list_entry(pos, struct pxe_label, list);
@@ -1421,6 +1436,16 @@ struct pxe_menu *parse_pxefile(struct pxe_context *ctx, unsigned long menucfg)
buf = map_sysmem(menucfg, 0);
r = parse_pxefile_top(ctx, buf, menucfg, cfg, 1);
+
+ if (ctx->use_fallback) {
+ if (cfg->fallback_label) {
+ printf("Setting use of fallback\n");
+ cfg->default_label = cfg->fallback_label;
+ } else {
+ printf("Selected fallback option, but not set\n");
+ }
+ }
+
unmap_sysmem(buf);
if (r < 0) {
destroy_pxe_menu(cfg);
@@ -1571,7 +1596,8 @@ void handle_pxe_menu(struct pxe_context *ctx, struct pxe_menu *cfg)
int pxe_setup_ctx(struct pxe_context *ctx, struct cmd_tbl *cmdtp,
pxe_getfile_func getfile, void *userdata,
- bool allow_abs_path, const char *bootfile, bool use_ipv6)
+ bool allow_abs_path, const char *bootfile, bool use_ipv6,
+ bool use_fallback)
{
const char *last_slash;
size_t path_len = 0;
@@ -1582,6 +1608,7 @@ int pxe_setup_ctx(struct pxe_context *ctx, struct cmd_tbl *cmdtp,
ctx->userdata = userdata;
ctx->allow_abs_path = allow_abs_path;
ctx->use_ipv6 = use_ipv6;
+ ctx->use_fallback = use_fallback;
/* figure out the boot directory, if there is one */
if (bootfile && strlen(bootfile) >= MAX_TFTP_PATH_LEN)