From 865328c3147b013021b1e48641ca11cef96f88cd Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 17 Jan 2023 10:47:54 -0700 Subject: bootstd: Rename bootdev checkers These functions return 0 if the check passes, so the names are somewhat confusing. Rename them. Signed-off-by: Simon Glass --- boot/bootmeth_script.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'boot/bootmeth_script.c') diff --git a/boot/bootmeth_script.c b/boot/bootmeth_script.c index c7061eb998f..3a3907d75b7 100644 --- a/boot/bootmeth_script.c +++ b/boot/bootmeth_script.c @@ -28,7 +28,7 @@ static int script_check(struct udevice *dev, struct bootflow_iter *iter) int ret; /* This only works on block devices */ - ret = bootflow_iter_uses_blk_dev(iter); + ret = bootflow_iter_check_blk(iter); if (ret) return log_msg_ret("blk", ret); -- cgit v1.2.3 From 25365879029d06b17b29010547e7a992901f51c0 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 17 Jan 2023 10:47:58 -0700 Subject: bootstd: Set the distro_bootpart env var with scripts This environment variable is supposed to be set so that the script knows which partition holds the script. Set it before invoking the script. Signed-off-by: Simon Glass --- boot/bootmeth_script.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'boot/bootmeth_script.c') diff --git a/boot/bootmeth_script.c b/boot/bootmeth_script.c index 3a3907d75b7..7050e45addb 100644 --- a/boot/bootmeth_script.c +++ b/boot/bootmeth_script.c @@ -125,6 +125,8 @@ static int script_boot(struct udevice *dev, struct bootflow *bflow) ret = env_set("devtype", blk_get_devtype(bflow->blk)); if (!ret) ret = env_set_hex("devnum", desc->devnum); + if (!ret) + ret = env_set_hex("distro_bootpart", bflow->part); if (!ret) ret = env_set("prefix", bflow->subdir); if (!ret && IS_ENABLED(CONFIG_ARCH_SUNXI) && @@ -135,6 +137,7 @@ static int script_boot(struct udevice *dev, struct bootflow *bflow) log_debug("devtype: %s\n", env_get("devtype")); log_debug("devnum: %s\n", env_get("devnum")); + log_debug("distro_bootpart: %s\n", env_get("distro_bootpart")); log_debug("prefix: %s\n", env_get("prefix")); log_debug("mmc_bootdev: %s\n", env_get("mmc_bootdev")); -- cgit v1.2.3 From 5143a41e10da67fe9542a42e947b6a375f0a08d6 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 17 Jan 2023 10:48:04 -0700 Subject: bootstd: Support reading a script from network or SPI flash At present this bootmeth only supports a block device and the sandbox host filesystem. Add support for obtaining the script from a network device. Also implement the set_bootflow() method so that it is easy for other bootdevs (such as enabling SPI flash to support scripts). Signed-off-by: Simon Glass --- boot/bootmeth_script.c | 93 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 80 insertions(+), 13 deletions(-) (limited to 'boot/bootmeth_script.c') diff --git a/boot/bootmeth_script.c b/boot/bootmeth_script.c index 7050e45addb..a14c750ff61 100644 --- a/boot/bootmeth_script.c +++ b/boot/bootmeth_script.c @@ -19,18 +19,14 @@ #include #include #include +#include #define SCRIPT_FNAME1 "boot.scr.uimg" #define SCRIPT_FNAME2 "boot.scr" static int script_check(struct udevice *dev, struct bootflow_iter *iter) { - int ret; - - /* This only works on block devices */ - ret = bootflow_iter_check_blk(iter); - if (ret) - return log_msg_ret("blk", ret); + /* This works on block devices, network devices and SPI Flash */ return 0; } @@ -65,11 +61,11 @@ static int script_fill_info(struct bootflow *bflow) return 0; } -static int script_read_bootflow(struct udevice *dev, struct bootflow *bflow) +static int script_read_bootflow_file(struct udevice *bootstd, + struct bootflow *bflow) { struct blk_desc *desc = NULL; const char *const *prefixes; - struct udevice *bootstd; const char *prefix; int ret, i; @@ -77,12 +73,12 @@ static int script_read_bootflow(struct udevice *dev, struct bootflow *bflow) if (ret) return log_msg_ret("std", ret); - /* We require a partition table */ - if (!bflow->part) - return -ENOENT; - - if (bflow->blk) + if (bflow->blk) { + /* We require a partition table */ + if (!bflow->part) + return -ENOENT; desc = dev_get_uclass_plat(bflow->blk); + } prefixes = bootstd_get_prefixes(bootstd); i = 0; @@ -116,6 +112,76 @@ static int script_read_bootflow(struct udevice *dev, struct bootflow *bflow) return 0; } +static int script_read_bootflow_net(struct bootflow *bflow) +{ + const char *addr_str; + int size, ret; + char *fname; + ulong addr; + + /* figure out the load address */ + addr_str = env_get("scriptaddr"); + addr = addr_str ? hextoul(addr_str, NULL) : image_load_addr; + + fname = env_get("boot_script_dhcp"); + if (!fname) + return log_msg_ret("dhc", -EINVAL); + + ret = dhcp_run(addr, fname, true); + if (ret) + return log_msg_ret("dhc", ret); + + size = env_get_hex("filesize", 0); + if (!size) + return log_msg_ret("sz", -EINVAL); + + bflow->buf = malloc(size + 1); + if (!bflow->buf) + return log_msg_ret("buf", -ENOMEM); + memcpy(bflow->buf, map_sysmem(addr, size), size); + bflow->buf[size] = '\0'; + bflow->size = size; + bflow->state = BOOTFLOWST_READY; + + return 0; +} + +static int script_read_bootflow(struct udevice *dev, struct bootflow *bflow) +{ + const struct udevice *media = dev_get_parent(bflow->dev); + struct udevice *bootstd; + int ret; + + ret = uclass_first_device_err(UCLASS_BOOTSTD, &bootstd); + if (ret) + return log_msg_ret("std", ret); + + if (IS_ENABLED(CONFIG_CMD_DHCP) && + device_get_uclass_id(media) == UCLASS_ETH) { + /* we only support reading from one device, so ignore 'dev' */ + ret = script_read_bootflow_net(bflow); + if (ret) + return log_msg_ret("net", ret); + } else { + ret = script_read_bootflow_file(bootstd, bflow); + if (ret) + return log_msg_ret("blk", ret); + } + + return 0; +} + +static int script_set_bootflow(struct udevice *dev, struct bootflow *bflow, + char *buf, int size) +{ + buf[size] = '\0'; + bflow->buf = buf; + bflow->size = size; + bflow->state = BOOTFLOWST_READY; + + return 0; +} + static int script_boot(struct udevice *dev, struct bootflow *bflow) { struct blk_desc *desc = dev_get_uclass_plat(bflow->blk); @@ -162,6 +228,7 @@ static int script_bootmeth_bind(struct udevice *dev) static struct bootmeth_ops script_bootmeth_ops = { .check = script_check, .read_bootflow = script_read_bootflow, + .set_bootflow = script_set_bootflow, .read_file = bootmeth_common_read_file, .boot = script_boot, }; -- cgit v1.2.3 From d9f48579dced9c897e718a8b0b84d56ac564a486 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 17 Jan 2023 10:48:05 -0700 Subject: bootstd: Treat DHCP and PXE as bootdev labels These are associated with the ethernet boot device but do not match its uclass name, so handle them as special cases. Provide a way to pass flags through with the bootdev so that we know how to process it. The flags are checked by the bootmeths, to ensure that only the selected bootmeth is used. While these both use the network device, they work quite differently. It is common to run only one of these, or to run PXE before DHCP. Provide bootflow flags to control which methods are used. Check these in the two bootmeths so that only the chosen one is used. Signed-off-by: Simon Glass --- boot/bootmeth_script.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'boot/bootmeth_script.c') diff --git a/boot/bootmeth_script.c b/boot/bootmeth_script.c index a14c750ff61..225eb18ee6c 100644 --- a/boot/bootmeth_script.c +++ b/boot/bootmeth_script.c @@ -27,6 +27,8 @@ static int script_check(struct udevice *dev, struct bootflow_iter *iter) { /* This works on block devices, network devices and SPI Flash */ + if (iter->method_flags & BOOTFLOW_METHF_PXE_ONLY) + return log_msg_ret("pxe", -ENOTSUPP); return 0; } -- cgit v1.2.3