blob: 017a74a3016fc6bd664ccfdd24270e2797a14787 [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0+
/*
* Read a bootflow from SPI flash
*
* Copyright 2022 Google LLC
*/
#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),
};