diff options
Diffstat (limited to 'drivers/mtd/spi/sf_bootdev.c')
-rw-r--r-- | drivers/mtd/spi/sf_bootdev.c | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/drivers/mtd/spi/sf_bootdev.c b/drivers/mtd/spi/sf_bootdev.c new file mode 100644 index 0000000000..d6b47b11ce --- /dev/null +++ b/drivers/mtd/spi/sf_bootdev.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Read a bootflow from SPI flash + * + * Copyright 2022 Google LLC + */ + +#include <common.h> +#include <bootdev.h> +#include <bootflow.h> +#include <bootmeth.h> +#include <dm.h> +#include <env.h> +#include <malloc.h> +#include <spi_flash.h> + +static int sf_get_bootflow(struct udevice *dev, struct bootflow_iter *iter, + struct bootflow *bflow) +{ + struct udevice *sf = dev_get_parent(dev); + uint size; + char *buf; + int ret; + + /* We only support the whole device, not partitions */ + if (iter->part) + return log_msg_ret("max", -ESHUTDOWN); + + size = env_get_hex("script_size_f", 0); + if (!size) + return log_msg_ret("sz", -EINVAL); + + buf = malloc(size + 1); + if (!buf) + return log_msg_ret("buf", -ENOMEM); + + ret = spi_flash_read_dm(sf, env_get_hex("script_offset_f", 0), + size, buf); + if (ret) + return log_msg_ret("cmd", -EINVAL); + bflow->state = BOOTFLOWST_MEDIA; + + ret = bootmeth_set_bootflow(bflow->method, bflow, buf, size); + if (ret) { + free(buf); + return log_msg_ret("method", ret); + } + + return 0; +} + +static int sf_bootdev_bind(struct udevice *dev) +{ + struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev); + + ucp->prio = BOOTDEVP_4_SCAN_FAST; + + return 0; +} + +struct bootdev_ops sf_bootdev_ops = { + .get_bootflow = sf_get_bootflow, +}; + +static const struct udevice_id sf_bootdev_ids[] = { + { .compatible = "u-boot,bootdev-sf" }, + { } +}; + +U_BOOT_DRIVER(sf_bootdev) = { + .name = "sf_bootdev", + .id = UCLASS_BOOTDEV, + .ops = &sf_bootdev_ops, + .bind = sf_bootdev_bind, + .of_match = sf_bootdev_ids, +}; + +BOOTDEV_HUNTER(sf_bootdev_hunter) = { + .prio = BOOTDEVP_4_SCAN_FAST, + .uclass = UCLASS_SPI_FLASH, + .drv = DM_DRIVER_REF(sf_bootdev), +}; |