diff options
author | Simon Glass <sjg@chromium.org> | 2023-01-17 20:48:04 +0300 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2023-01-24 02:11:41 +0300 |
commit | 5143a41e10da67fe9542a42e947b6a375f0a08d6 (patch) | |
tree | d2154456d206f3ff036a37fb189dfba42e899029 /boot | |
parent | 0c1f4a9fb13a54780f550d6e5bc4cd37a58f879e (diff) | |
download | u-boot-5143a41e10da67fe9542a42e947b6a375f0a08d6.tar.xz |
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 <sjg@chromium.org>
Diffstat (limited to 'boot')
-rw-r--r-- | boot/bootmeth_script.c | 93 |
1 files changed, 80 insertions, 13 deletions
diff --git a/boot/bootmeth_script.c b/boot/bootmeth_script.c index 7050e45add..a14c750ff6 100644 --- a/boot/bootmeth_script.c +++ b/boot/bootmeth_script.c @@ -19,18 +19,14 @@ #include <image.h> #include <malloc.h> #include <mapmem.h> +#include <net.h> #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, }; |