Merge patch series "test: Minor fixes to test.py"
Simon Glass <sjg@chromium.org> says:
This series collects together the patches from the Labgrid series which
are not related to Labgrid, or at least can be applied independently of
using Labgrid to run the lab.
Link: https://lore.kernel.org/r/20241010002907.19383-1-sjg@chromium.org
diff --git a/boot/bootmeth-uclass.c b/boot/bootmeth-uclass.c
index c0abade..5b5fea3 100644
--- a/boot/bootmeth-uclass.c
+++ b/boot/bootmeth-uclass.c
@@ -251,6 +251,31 @@
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 fbb05ef..be8fbf4 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 @@
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 @@
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 @@
.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 @@
.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 03d2589..05c6bec 100644
--- a/boot/bootmeth_pxe.c
+++ b/boot/bootmeth_pxe.c
@@ -150,7 +150,7 @@
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 4e27842..d6a4b2c 100644
--- a/boot/pxe_utils.c
+++ b/boot/pxe_utils.c
@@ -781,6 +781,7 @@
T_IPAPPEND,
T_BACKGROUND,
T_KASLRSEED,
+ T_FALLBACK,
T_INVALID
};
@@ -814,6 +815,7 @@
{"ipappend", T_IPAPPEND,},
{"background", T_BACKGROUND,},
{"kaslrseed", T_KASLRSEED,},
+ {"fallback", T_FALLBACK,},
{NULL, T_INVALID}
};
@@ -1356,6 +1358,18 @@
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 @@
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 @@
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 @@
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 @@
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)
diff --git a/cmd/bootmeth.c b/cmd/bootmeth.c
index ebf8b7e..2f41fa1 100644
--- a/cmd/bootmeth.c
+++ b/cmd/bootmeth.c
@@ -103,10 +103,31 @@
return 0;
}
+static int do_bootmeth_set(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int ret;
+
+ if (argc < 4) {
+ printf("Required parameters not provided\n");
+ return CMD_RET_FAILURE;
+ }
+
+ ret = bootmeth_set_property(argv[1], argv[2], argv[3]);
+ if (ret) {
+ printf("Failed (err=%d)\n", ret);
+ return CMD_RET_FAILURE;
+ }
+
+ return 0;
+}
+
U_BOOT_LONGHELP(bootmeth,
"list [-a] - list available bootmeths (-a all)\n"
- "bootmeth order [<bd> ...] - select bootmeth order / subset to use");
+ "bootmeth order [<bd> ...] - select bootmeth order / subset to use\n"
+ "bootmeth set <bootmeth> <property> <value> - set optional property");
U_BOOT_CMD_WITH_SUBCMDS(bootmeth, "Boot methods", bootmeth_help_text,
U_BOOT_SUBCMD_MKENT(list, 2, 1, do_bootmeth_list),
- U_BOOT_SUBCMD_MKENT(order, CONFIG_SYS_MAXARGS, 1, do_bootmeth_order));
+ U_BOOT_SUBCMD_MKENT(order, CONFIG_SYS_MAXARGS, 1, do_bootmeth_order),
+ U_BOOT_SUBCMD_MKENT(set, CONFIG_SYS_MAXARGS, 1, do_bootmeth_set));
diff --git a/cmd/pxe.c b/cmd/pxe.c
index ae02c28..982e2b1 100644
--- a/cmd/pxe.c
+++ b/cmd/pxe.c
@@ -138,7 +138,7 @@
int i;
if (pxe_setup_ctx(&ctx, cmdtp, do_get_tftp, NULL, false,
- env_get("bootfile"), use_ipv6))
+ env_get("bootfile"), use_ipv6, false))
return -ENOMEM;
if (IS_ENABLED(CONFIG_BOOTP_PXE_DHCP_OPTION) &&
@@ -288,7 +288,7 @@
}
if (pxe_setup_ctx(&ctx, cmdtp, do_get_tftp, NULL, false,
- env_get("bootfile"), use_ipv6)) {
+ env_get("bootfile"), use_ipv6, false)) {
printf("Out of memory\n");
return CMD_RET_FAILURE;
}
diff --git a/cmd/sysboot.c b/cmd/sysboot.c
index 0ea08fd..8a06078 100644
--- a/cmd/sysboot.c
+++ b/cmd/sysboot.c
@@ -105,7 +105,7 @@
}
if (pxe_setup_ctx(&ctx, cmdtp, sysboot_read_file, &info, true,
- filename, false)) {
+ filename, false, false)) {
printf("Out of memory\n");
return CMD_RET_FAILURE;
}
diff --git a/doc/README.pxe b/doc/README.pxe
index 1722010..af2e64a 100644
--- a/doc/README.pxe
+++ b/doc/README.pxe
@@ -120,6 +120,11 @@
default <label> - the label named here is treated as the default and is
the first label 'pxe boot' attempts to boot.
+fallback <label> - the label named here is treated as a fallback option that
+ may be attempted should it be detected that booting of
+ the default has failed to complete, for example via
+ U-Boot's boot count limit functionality.
+
menu title <string> - sets a title for the menu of labels being displayed.
menu include <path> - use tftp to retrieve the pxe file at <path>, which
diff --git a/doc/develop/bootstd/overview.rst b/doc/develop/bootstd/overview.rst
index c6f0038..a2913cd 100644
--- a/doc/develop/bootstd/overview.rst
+++ b/doc/develop/bootstd/overview.rst
@@ -103,6 +103,12 @@
returns the bootflow, if found. Some of these bootmeths may be very slow, if
they scan a lot of devices.
+The extlinux bootmeth also allows for bootmeth specific configuration to be
+set. A bootmeth that wishes to support this provides the `set_property()`
+method. This allows string properties and values to be passed to the bootmeth.
+It is up to the bootmeth to determine what action to take when this method is
+called.
+
Boot process
------------
@@ -459,8 +465,8 @@
See :doc:`/usage/cmd/bootflow`
`bootmeth`
- Allow listing of available bootmethds and setting the order in which they
- are tried. See :doc:`/usage/cmd/bootmeth`
+ Allow listing of available bootmethds, setting the order in which they are
+ tried and bootmeth specific configuration. See :doc:`/usage/cmd/bootmeth`
.. _BootflowStates:
diff --git a/doc/usage/cmd/bootmeth.rst b/doc/usage/cmd/bootmeth.rst
index c3d2ec1..4f899d9 100644
--- a/doc/usage/cmd/bootmeth.rst
+++ b/doc/usage/cmd/bootmeth.rst
@@ -12,7 +12,8 @@
::
bootmeth list [-a] - list selected bootmeths (-a for all)
- bootmeth order "[<bm> ...]" - select the order of bootmeths\n"
+ bootmeth order "[<bm> ...]" - select the order of bootmeths
+ bootmeth set <bootmeth> <property> <value> - set optional property
Description
@@ -112,3 +113,38 @@
- 4 efi_mgr EFI bootmgr flow
----- --- ------------------ ------------------
(5 bootmeths)
+
+
+bootmeth set
+~~~~~~~~~~~~
+
+Allows setting of bootmeth specific configuration. This allows finer grain
+control over the boot process in specific instances.
+
+
+Supported Configuration Options
+-------------------------------
+
+The following configuration options are currently supported:
+
+======== =================== ====== ===============================
+Property Supported Bootmeths Values Description
+======== =================== ====== ===============================
+fallback extlinux 0 | 1 Enable or disable fallback path
+======== =================== ====== ===============================
+
+
+Bootmeth set Example
+--------------------
+
+With the bootcount functionality enabled, when the bootlimit is reached, the
+`altbootcmd` environment variable lists the command used for booting rather
+than `bootcmd`. We can set the fallback configuration to cause the fallback
+boot option to be preferred, to revert to a previous known working boot option
+after a failed update for example. So if `bootcmd` is set to::
+
+ bootflow scan -lb
+
+We would set "altbootcmd" to::
+
+ bootmeth set extlinux fallback 1; bootflow scan -lb
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index 6f5395c..f5c9868 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -194,27 +194,26 @@
/**
* struct spi_nor_fixups - SPI NOR fixup hooks
- * @default_init: called after default flash parameters init. Used to tweak
- * flash parameters when information provided by the flash_info
- * table is incomplete or wrong.
* @post_bfpt: called after the BFPT table has been parsed
- * @post_sfdp: called after SFDP has been parsed (is also called for SPI NORs
- * that do not support RDSFDP). Typically used to tweak various
- * parameters that could not be extracted by other means (i.e.
- * when information provided by the SFDP/flash_info tables are
- * incomplete or wrong).
+ * @post_sfdp: called after SFDP has been parsed. Typically used to tweak
+ * various parameters that could not be extracted by other means
+ * (i.e. when information provided by the SFDP tables are incomplete
+ * or wrong).
+ * @late_init: used to initialize flash parameters that are not declared in the
+ * JESD216 SFDP standard, or where SFDP tables not defined at all.
*
* Those hooks can be used to tweak the SPI NOR configuration when the SFDP
* table is broken or not available.
*/
struct spi_nor_fixups {
- void (*default_init)(struct spi_nor *nor);
int (*post_bfpt)(struct spi_nor *nor,
const struct sfdp_parameter_header *bfpt_header,
const struct sfdp_bfpt *bfpt,
struct spi_nor_flash_parameter *params);
void (*post_sfdp)(struct spi_nor *nor,
struct spi_nor_flash_parameter *params);
+ void (*late_init)(struct spi_nor *nor,
+ struct spi_nor_flash_parameter *params);
};
#define SPI_NOR_SRST_SLEEP_LEN 200
@@ -3045,13 +3044,12 @@
/**
* spi_nor_post_sfdp_fixups() - Updates the flash's parameters and settings
- * after SFDP has been parsed (is also called for SPI NORs that do not
- * support RDSFDP).
+ * after SFDP has been parsed.
* @nor: pointer to a 'struct spi_nor'
*
* Typically used to tweak various parameters that could not be extracted by
- * other means (i.e. when information provided by the SFDP/flash_info tables
- * are incomplete or wrong).
+ * other means (i.e. when information provided by the SFDP tables are incomplete
+ * or wrong).
*/
static void spi_nor_post_sfdp_fixups(struct spi_nor *nor,
struct spi_nor_flash_parameter *params)
@@ -3060,10 +3058,11 @@
nor->fixups->post_sfdp(nor, params);
}
-static void spi_nor_default_init_fixups(struct spi_nor *nor)
+static void spi_nor_late_init_fixups(struct spi_nor *nor,
+ struct spi_nor_flash_parameter *params)
{
- if (nor->fixups && nor->fixups->default_init)
- nor->fixups->default_init(nor);
+ if (nor->fixups && nor->fixups->late_init)
+ nor->fixups->late_init(nor, params);
}
static int spi_nor_init_params(struct spi_nor *nor,
@@ -3081,6 +3080,7 @@
memset(params, 0, sizeof(*params));
/* Set SPI NOR sizes. */
+ params->writesize = 1;
params->size = info->sector_size * info->n_sectors;
params->page_size = info->page_size;
@@ -3176,8 +3176,6 @@
}
}
- spi_nor_default_init_fixups(nor);
-
/* Override the parameters with data read from SFDP tables. */
nor->addr_width = 0;
nor->mtd.erasesize = 0;
@@ -3193,6 +3191,8 @@
} else {
memcpy(params, &sfdp_params, sizeof(*params));
}
+
+ spi_nor_post_sfdp_fixups(nor, params);
}
#if CONFIG_IS_ENABLED(DM_SPI) && CONFIG_IS_ENABLED(SPI_ADVANCE)
/*
@@ -3250,7 +3250,7 @@
params->page_size <<= 1;
}
#endif
- spi_nor_post_sfdp_fixups(nor, params);
+ spi_nor_late_init_fixups(nor, params);
return 0;
}
@@ -3714,7 +3714,8 @@
return spi_nor_default_setup(nor, info, params);
}
-static void s25fs_s_default_init(struct spi_nor *nor)
+static void s25fs_s_late_init(struct spi_nor *nor,
+ struct spi_nor_flash_parameter *params)
{
nor->setup = s25fs_s_setup;
}
@@ -3764,9 +3765,9 @@
}
static struct spi_nor_fixups s25fs_s_fixups = {
- .default_init = s25fs_s_default_init,
.post_bfpt = s25fs_s_post_bfpt_fixup,
.post_sfdp = s25fs_s_post_sfdp_fixup,
+ .late_init = s25fs_s_late_init,
};
static int s25_s28_mdp_ready(struct spi_nor *nor)
@@ -3850,9 +3851,17 @@
return spi_nor_default_setup(nor, info, params);
}
-static void s25_default_init(struct spi_nor *nor)
+static void s25_late_init(struct spi_nor *nor,
+ struct spi_nor_flash_parameter *params)
{
nor->setup = s25_s28_setup;
+
+ /*
+ * Programming is supported only in 16-byte ECC data unit granularity.
+ * Byte-programming, bit-walking, or multiple program operations to the
+ * same ECC data unit without an erase are not allowed.
+ */
+ params->writesize = 16;
}
static int s25_s28_post_bfpt_fixup(struct spi_nor *nor,
@@ -3931,9 +3940,9 @@
}
static struct spi_nor_fixups s25_fixups = {
- .default_init = s25_default_init,
.post_bfpt = s25_s28_post_bfpt_fixup,
.post_sfdp = s25_post_sfdp_fixup,
+ .late_init = s25_late_init,
};
static int s25fl256l_setup(struct spi_nor *nor, const struct flash_info *info,
@@ -3942,13 +3951,14 @@
return -ENOTSUPP; /* Bank Address Register is not supported */
}
-static void s25fl256l_default_init(struct spi_nor *nor)
+static void s25fl256l_late_init(struct spi_nor *nor,
+ struct spi_nor_flash_parameter *params)
{
nor->setup = s25fl256l_setup;
}
static struct spi_nor_fixups s25fl256l_fixups = {
- .default_init = s25fl256l_default_init,
+ .late_init = s25fl256l_late_init,
};
#endif
@@ -4011,10 +4021,18 @@
return 0;
}
-static void s28hx_t_default_init(struct spi_nor *nor)
+static void s28hx_t_late_init(struct spi_nor *nor,
+ struct spi_nor_flash_parameter *params)
{
nor->octal_dtr_enable = spi_nor_cypress_octal_dtr_enable;
nor->setup = s25_s28_setup;
+
+ /*
+ * Programming is supported only in 16-byte ECC data unit granularity.
+ * Byte-programming, bit-walking, or multiple program operations to the
+ * same ECC data unit without an erase are not allowed.
+ */
+ params->writesize = 16;
}
static void s28hx_t_post_sfdp_fixup(struct spi_nor *nor,
@@ -4049,9 +4067,9 @@
}
static struct spi_nor_fixups s28hx_t_fixups = {
- .default_init = s28hx_t_default_init,
.post_sfdp = s28hx_t_post_sfdp_fixup,
.post_bfpt = s25_s28_post_bfpt_fixup,
+ .late_init = s28hx_t_late_init,
};
#endif /* CONFIG_SPI_FLASH_S28HX_T */
@@ -4103,7 +4121,8 @@
return 0;
}
-static void mt35xu512aba_default_init(struct spi_nor *nor)
+static void mt35xu512aba_late_init(struct spi_nor *nor,
+ struct spi_nor_flash_parameter *params)
{
nor->octal_dtr_enable = spi_nor_micron_octal_dtr_enable;
}
@@ -4132,8 +4151,8 @@
}
static struct spi_nor_fixups mt35xu512aba_fixups = {
- .default_init = mt35xu512aba_default_init,
.post_sfdp = mt35xu512aba_post_sfdp_fixup,
+ .late_init = mt35xu512aba_late_init,
};
#endif /* CONFIG_SPI_FLASH_MT35XU */
@@ -4193,7 +4212,8 @@
return 0;
}
-static void macronix_octal_default_init(struct spi_nor *nor)
+static void macronix_octal_late_init(struct spi_nor *nor,
+ struct spi_nor_flash_parameter *params)
{
nor->octal_dtr_enable = spi_nor_macronix_octal_dtr_enable;
}
@@ -4210,8 +4230,8 @@
}
static struct spi_nor_fixups macronix_octal_fixups = {
- .default_init = macronix_octal_default_init,
.post_sfdp = macronix_octal_post_sfdp_fixup,
+ .late_init = macronix_octal_late_init,
};
#endif /* CONFIG_SPI_FLASH_MACRONIX */
@@ -4422,7 +4442,9 @@
#endif
#if CONFIG_IS_ENABLED(SPI_FLASH_MACRONIX)
- nor->fixups = ¯onix_octal_fixups;
+ if (JEDEC_MFR(nor->info) == SNOR_MFR_MACRONIX &&
+ nor->info->flags & SPI_NOR_OCTAL_DTR_READ)
+ nor->fixups = ¯onix_octal_fixups;
#endif /* SPI_FLASH_MACRONIX */
}
@@ -4499,7 +4521,7 @@
mtd->dev = nor->dev;
mtd->priv = nor;
mtd->type = MTD_NORFLASH;
- mtd->writesize = 1;
+ mtd->writesize = params.writesize;
mtd->flags = MTD_CAP_NORFLASH;
mtd->size = params.size;
mtd->_erase = spi_nor_erase;
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index cf0d702..1045377 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -679,10 +679,8 @@
ubi->bad_peb_limit = get_bad_peb_limit(ubi, max_beb_per1024);
}
- if (ubi->mtd->type == MTD_NORFLASH) {
- ubi_assert(ubi->mtd->writesize == 1);
+ if (ubi->mtd->type == MTD_NORFLASH)
ubi->nor_flash = 1;
- }
ubi->min_io_size = ubi->mtd->writesize;
ubi->hdrs_min_io_size = ubi->mtd->writesize >> ubi->mtd->subpage_sft;
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
index 14be95b..45699b4 100644
--- a/drivers/mtd/ubi/io.c
+++ b/drivers/mtd/ubi/io.c
@@ -563,7 +563,14 @@
return -EROFS;
}
- if (ubi->nor_flash) {
+ /*
+ * If the flash is ECC-ed then we have to erase the ECC block before we
+ * can write to it. But the write is in preparation to an erase in the
+ * first place. This means we cannot zero out EC and VID before the
+ * erase and we just have to hope the flash starts erasing from the
+ * start of the page.
+ */
+ if (ubi->nor_flash && ubi->mtd->writesize == 1) {
err = nor_erase_prepare(ubi, pnum);
if (err)
return err;
diff --git a/include/bootmeth.h b/include/bootmeth.h
index 4d8ca48..a08ebf0 100644
--- a/include/bootmeth.h
+++ b/include/bootmeth.h
@@ -146,6 +146,22 @@
* something changes, other -ve on other error
*/
int (*boot)(struct udevice *dev, struct bootflow *bflow);
+
+ /**
+ * set_property() - set the bootmeth property
+ *
+ * This allows the setting of boot method specific properties to enable
+ * automated finer grain control of the boot process
+ *
+ * @name: String containing the name of the relevant boot method
+ * @property: String containing the name of the property to set
+ * @value: String containing the value to be set for the specified
+ * property
+ * Return: 0 if OK, -ENODEV if an unknown bootmeth or property is
+ * provided, -ENOENT if there are no bootmeth devices
+ */
+ int (*set_property)(struct udevice *dev, const char *property,
+ const char *value);
};
#define bootmeth_get_ops(dev) ((struct bootmeth_ops *)(dev)->driver->ops)
@@ -291,6 +307,21 @@
int bootmeth_set_order(const char *order_str);
/**
+ * bootmeth_set_property() - Set the bootmeth property
+ *
+ * This allows the setting of boot method specific properties to enable
+ * automated finer grain control of the boot process
+ *
+ * @name: String containing the name of the relevant boot method
+ * @property: String containing the name of the property to set
+ * @value: String containing the value to be set for the specified property
+ * Return: 0 if OK, -ENODEV if an unknown bootmeth or property is provided,
+ * -ENOENT if there are no bootmeth devices
+ */
+int bootmeth_set_property(const char *name, const char *property,
+ const char *value);
+
+/**
* bootmeth_setup_fs() - Set up read to read a file
*
* We must redo the setup before each filesystem operation. This function
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index 047e83e..1ae586b 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -457,6 +457,7 @@
struct spi_nor_flash_parameter {
u64 size;
+ u32 writesize;
u32 page_size;
u8 rdsr_dummy;
u8 rdsr_addr_nbytes;
diff --git a/include/pxe_utils.h b/include/pxe_utils.h
index 9f19593..68ac40b 100644
--- a/include/pxe_utils.h
+++ b/include/pxe_utils.h
@@ -62,6 +62,7 @@
*
* title - the name of the menu as given by a 'menu title' line.
* default_label - the name of the default label, if any.
+ * fallback_label - the name of the fallback label, if any.
* bmp - the bmp file name which is displayed in background
* timeout - time in tenths of a second to wait for a user key-press before
* booting the default label.
@@ -73,6 +74,7 @@
struct pxe_menu {
char *title;
char *default_label;
+ char *fallback_label;
char *bmp;
int timeout;
int prompt;
@@ -94,6 +96,8 @@
* allocated
* @pxe_file_size: Size of the PXE file
* @use_ipv6: TRUE : use IPv6 addressing, FALSE : use IPv4 addressing
+ * @use_fallback: TRUE : use "fallback" option as default, FALSE : use
+ * "default" option as default
*/
struct pxe_context {
struct cmd_tbl *cmdtp;
@@ -114,6 +118,7 @@
char *bootdir;
ulong pxe_file_size;
bool use_ipv6;
+ bool use_fallback;
};
/**
@@ -213,12 +218,17 @@
* none
* @use_ipv6: TRUE : use IPv6 addressing
* FALSE : use IPv4 addressing
+ * @use_fallback: TRUE : Use "fallback" option instead of "default" should no
+ * other choice be selected
+ * FALSE : Use "default" option should no other choice be
+ * selected
* Return: 0 if OK, -ENOMEM if out of memory, -E2BIG if bootfile is larger than
* MAX_TFTP_PATH_LEN bytes
*/
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);
/**
* pxe_destroy_ctx() - Destroy a PXE context
diff --git a/test/boot/bootmeth.c b/test/boot/bootmeth.c
index 518d99c..18ae6d7 100644
--- a/test/boot/bootmeth.c
+++ b/test/boot/bootmeth.c
@@ -127,6 +127,53 @@
}
BOOTSTD_TEST(bootmeth_cmd_order_glob, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
+/* Check 'bootmeth set' command */
+static int bootmeth_cmd_set(struct unit_test_state *uts)
+{
+ /* Check we can enable extlinux fallback */
+ console_record_reset_enable();
+ ut_assertok(run_command("bootmeth set extlinux fallback 1", 0));
+ ut_assert_console_end();
+
+ /* Check we can disable extlinux fallback */
+ console_record_reset_enable();
+ ut_assertok(run_command("bootmeth set extlinux fallback 0", 0));
+ ut_assert_console_end();
+
+ /* Check extlinux fallback unexpected value */
+ console_record_reset_enable();
+ ut_asserteq(1, run_command("bootmeth set extlinux fallback fred", 0));
+ ut_assert_nextline("Unexpected value 'fred'");
+ ut_assert_nextline("Failed (err=-22)");
+ ut_assert_console_end();
+
+ /* Check that we need to provide right number of parameters */
+ ut_asserteq(1, run_command("bootmeth set extlinux fallback", 0));
+ ut_assert_nextline("Required parameters not provided");
+ ut_assert_console_end();
+
+ /* Check that we need to provide a valid bootmethod */
+ ut_asserteq(1, run_command("bootmeth set fred fallback 0", 0));
+ ut_assert_nextline("Unknown bootmeth 'fred'");
+ ut_assert_nextline("Failed (err=-19)");
+ ut_assert_console_end();
+
+ /* Check that we need to provide a valid property */
+ ut_asserteq(1, run_command("bootmeth set extlinux fred 0", 0));
+ ut_assert_nextline("Invalid option");
+ ut_assert_nextline("Failed (err=-22)");
+ ut_assert_console_end();
+
+ /* Check that we need to provide a bootmeth that supports properties */
+ ut_asserteq(1, run_command("bootmeth set efi fallback 0", 0));
+ ut_assert_nextline("set_property not found");
+ ut_assert_nextline("Failed (err=-19)");
+ ut_assert_console_end();
+
+ return 0;
+}
+BOOTSTD_TEST(bootmeth_cmd_set, UTF_DM | UTF_SCAN_FDT);
+
/* Check 'bootmeths' env var */
static int bootmeth_env(struct unit_test_state *uts)
{