#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 */
+ if (iter->method_flags & BOOTFLOW_METHF_PXE_ONLY)
+ return log_msg_ret("pxe", -ENOTSUPP);
return 0;
}
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;
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;
if (!bflow->subdir)
return log_msg_ret("prefix", -ENOMEM);
- ret = bootmeth_alloc_file(bflow, 0x10000, 1);
+ ret = bootmeth_alloc_file(bflow, 0x10000, ARCH_DMA_MINALIGN);
if (ret)
return log_msg_ret("read", ret);
return 0;
}
-static int script_boot(struct udevice *dev, struct bootflow *bflow)
+static int script_read_bootflow_net(struct bootflow *bflow)
{
- struct blk_desc *desc = dev_get_uclass_plat(bflow->blk);
+ 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 = env_set("devtype", blk_get_devtype(bflow->blk));
+ 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);
+ ulong addr;
+ int ret = 0;
+
+ if (desc->uclass_id == UCLASS_USB) {
+ ret = env_set("devtype", "usb");
+ } else {
+ /* If the uclass is AHCI, but the driver is ATA
+ * (not scsi), set devtype to sata
+ */
+ if (IS_ENABLED(CONFIG_SATA) &&
+ desc->uclass_id == UCLASS_AHCI)
+ ret = env_set("devtype", "sata");
+ else
+ ret = env_set("devtype", blk_get_devtype(bflow->blk));
+ }
if (!ret)
ret = env_set_hex("devnum", desc->devnum);
if (!ret)
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,
};
{ }
};
-U_BOOT_DRIVER(bootmeth_script) = {
+/* Put an number before 'script' to provide a default ordering */
+U_BOOT_DRIVER(bootmeth_2script) = {
.name = "bootmeth_script",
.id = UCLASS_BOOTMETH,
.of_match = script_bootmeth_ids,