aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ata/ahci.c6
-rw-r--r--drivers/block/ide.c86
-rw-r--r--drivers/core/dump.c65
-rw-r--r--drivers/mmc/mmc-uclass.c2
-rw-r--r--drivers/mmc/mmc_bootdev.c33
-rw-r--r--drivers/mmc/sandbox_mmc.c2
-rw-r--r--drivers/mtd/spi/Kconfig8
-rw-r--r--drivers/mtd/spi/Makefile1
-rw-r--r--drivers/mtd/spi/sf-uclass.c11
-rw-r--r--drivers/mtd/spi/sf_bootdev.c82
-rw-r--r--drivers/nvme/nvme-uclass.c54
-rw-r--r--drivers/nvme/nvme.c5
-rw-r--r--drivers/scsi/Makefile7
-rw-r--r--drivers/scsi/scsi.c32
-rw-r--r--drivers/scsi/scsi_bootdev.c62
-rw-r--r--drivers/usb/host/usb-uclass.c2
-rw-r--r--drivers/usb/host/usb_bootdev.c38
-rw-r--r--drivers/virtio/virtio-uclass.c62
-rw-r--r--drivers/virtio/virtio_sandbox.c16
19 files changed, 449 insertions, 125 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index de6131f1d9..272c48b8e5 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -675,6 +675,12 @@ static int ata_scsiop_inquiry(struct ahci_uc_priv *uc_priv,
/* Read id from sata */
port = pccb->target;
+ /* If this port number is not valid, give up */
+ if (!(uc_priv->port_map & (1 << port))) {
+ debug("Port %x not valid in map %x\n", port, uc_priv->port_map);
+ return -ENODEV;
+ }
+
if (ahci_device_data_io(uc_priv, port, (u8 *)&fis, sizeof(fis),
(u8 *)tmpid, ATA_ID_WORDS * 2, 0)) {
debug("scsi_ahci: SCSI inquiry command failure.\n");
diff --git a/drivers/block/ide.c b/drivers/block/ide.c
index eaa58d859c..1ad9b6c126 100644
--- a/drivers/block/ide.c
+++ b/drivers/block/ide.c
@@ -9,6 +9,7 @@
#include <common.h>
#include <ata.h>
#include <blk.h>
+#include <bootdev.h>
#include <dm.h>
#include <ide.h>
#include <log.h>
@@ -443,9 +444,6 @@ static void atapi_inquiry(struct blk_desc *dev_desc)
device = dev_desc->devnum;
dev_desc->type = DEV_TYPE_UNKNOWN; /* not yet valid */
-#ifndef CONFIG_BLK
- dev_desc->block_read = atapi_read;
-#endif
memset(ccb, 0, sizeof(ccb));
memset(iobuf, 0, sizeof(iobuf));
@@ -692,6 +690,7 @@ __weak unsigned char ide_inb(int dev, int port)
void ide_init(void)
{
+ struct udevice *dev;
unsigned char c;
int i, bus;
@@ -759,29 +758,14 @@ void ide_init(void)
ide_dev_desc[i].log2blksz =
LOG2_INVALID(typeof(ide_dev_desc[i].log2blksz));
ide_dev_desc[i].lba = 0;
-#ifndef CONFIG_BLK
- ide_dev_desc[i].block_read = ide_read;
- ide_dev_desc[i].block_write = ide_write;
-#endif
if (!ide_bus_ok[IDE_BUS(i)])
continue;
ide_ident(&ide_dev_desc[i]);
dev_print(&ide_dev_desc[i]);
-
-#ifndef CONFIG_BLK
- if ((ide_dev_desc[i].lba > 0) && (ide_dev_desc[i].blksz > 0)) {
- /* initialize partition type */
- part_init(&ide_dev_desc[i]);
- }
-#endif
}
schedule();
-#ifdef CONFIG_BLK
- struct udevice *dev;
-
uclass_first_device(UCLASS_IDE, &dev);
-#endif
}
__weak void ide_input_swap_data(int dev, ulong *sect_buf, int words)
@@ -830,17 +814,10 @@ __weak void ide_input_data(int dev, ulong *sect_buf, int words)
}
}
-#ifdef CONFIG_BLK
ulong ide_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
void *buffer)
-#else
-ulong ide_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt,
- void *buffer)
-#endif
{
-#ifdef CONFIG_BLK
struct blk_desc *block_dev = dev_get_uclass_plat(dev);
-#endif
int device = block_dev->devnum;
ulong n = 0;
unsigned char c;
@@ -957,17 +934,10 @@ IDE_READ_E:
return n;
}
-#ifdef CONFIG_BLK
ulong ide_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
const void *buffer)
-#else
-ulong ide_write(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt,
- const void *buffer)
-#endif
{
-#ifdef CONFIG_BLK
struct blk_desc *block_dev = dev_get_uclass_plat(dev);
-#endif
int device = block_dev->devnum;
ulong n = 0;
unsigned char c;
@@ -1056,7 +1026,6 @@ int ide_device_present(int dev)
}
#endif
-#ifdef CONFIG_BLK
static int ide_blk_probe(struct udevice *udev)
{
struct blk_desc *desc = dev_get_uclass_plat(udev);
@@ -1087,6 +1056,45 @@ U_BOOT_DRIVER(ide_blk) = {
.probe = ide_blk_probe,
};
+static int ide_bootdev_bind(struct udevice *dev)
+{
+ struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev);
+
+ ucp->prio = BOOTDEVP_5_SCAN_SLOW;
+
+ return 0;
+}
+
+static int ide_bootdev_hunt(struct bootdev_hunter *info, bool show)
+{
+ ide_init();
+
+ return 0;
+}
+
+struct bootdev_ops ide_bootdev_ops = {
+};
+
+static const struct udevice_id ide_bootdev_ids[] = {
+ { .compatible = "u-boot,bootdev-ide" },
+ { }
+};
+
+U_BOOT_DRIVER(ide_bootdev) = {
+ .name = "ide_bootdev",
+ .id = UCLASS_BOOTDEV,
+ .ops = &ide_bootdev_ops,
+ .bind = ide_bootdev_bind,
+ .of_match = ide_bootdev_ids,
+};
+
+BOOTDEV_HUNTER(ide_bootdev_hunter) = {
+ .prio = BOOTDEVP_5_SCAN_SLOW,
+ .uclass = UCLASS_IDE,
+ .hunt = ide_bootdev_hunt,
+ .drv = DM_DRIVER_REF(ide_bootdev),
+};
+
static int ide_probe(struct udevice *udev)
{
struct udevice *blk_dev;
@@ -1118,6 +1126,10 @@ static int ide_probe(struct udevice *udev)
ret = blk_probe_or_unbind(blk_dev);
if (ret)
return ret;
+
+ ret = bootdev_setup_for_dev(udev, "ide_bootdev");
+ if (ret)
+ return log_msg_ret("bootdev", ret);
}
}
@@ -1141,11 +1153,3 @@ UCLASS_DRIVER(ide) = {
.name = "ide",
.id = UCLASS_IDE,
};
-#else
-U_BOOT_LEGACY_BLK(ide) = {
- .uclass_idname = "ide",
- .uclass_id = UCLASS_IDE,
- .max_devs = CONFIG_SYS_IDE_MAXDEVICE,
- .desc = ide_dev_desc,
-};
-#endif
diff --git a/drivers/core/dump.c b/drivers/core/dump.c
index 1c1f7e4d30..0c7d2ec4d0 100644
--- a/drivers/core/dump.c
+++ b/drivers/core/dump.c
@@ -5,12 +5,34 @@
#include <common.h>
#include <dm.h>
+#include <malloc.h>
#include <mapmem.h>
+#include <sort.h>
#include <dm/root.h>
#include <dm/util.h>
#include <dm/uclass-internal.h>
-static void show_devices(struct udevice *dev, int depth, int last_flag)
+/**
+ * struct sort_info - information used for sorting
+ *
+ * @dev: List of devices
+ * @alloced: Maximum number of devices in @dev
+ */
+struct sort_info {
+ struct udevice **dev;
+ int size;
+};
+
+static int h_cmp_uclass_id(const void *d1, const void *d2)
+{
+ const struct udevice *const *dev1 = d1;
+ const struct udevice *const *dev2 = d2;
+
+ return device_get_uclass_id(*dev1) - device_get_uclass_id(*dev2);
+}
+
+static void show_devices(struct udevice *dev, int depth, int last_flag,
+ struct udevice **devs)
{
int i, is_last;
struct udevice *child;
@@ -39,21 +61,52 @@ static void show_devices(struct udevice *dev, int depth, int last_flag)
printf("%s\n", dev->name);
- device_foreach_child(child, dev) {
- is_last = list_is_last(&child->sibling_node, &dev->child_head);
- show_devices(child, depth + 1, (last_flag << 1) | is_last);
+ if (devs) {
+ int count;
+ int i;
+
+ count = 0;
+ device_foreach_child(child, dev)
+ devs[count++] = child;
+ qsort(devs, count, sizeof(struct udevice *), h_cmp_uclass_id);
+
+ for (i = 0; i < count; i++) {
+ show_devices(devs[i], depth + 1,
+ (last_flag << 1) | (i == count - 1),
+ devs + count);
+ }
+ } else {
+ device_foreach_child(child, dev) {
+ is_last = list_is_last(&child->sibling_node,
+ &dev->child_head);
+ show_devices(child, depth + 1,
+ (last_flag << 1) | is_last, NULL);
+ }
}
}
-void dm_dump_tree(void)
+void dm_dump_tree(bool sort)
{
struct udevice *root;
root = dm_root();
if (root) {
+ int dev_count, uclasses;
+ struct udevice **devs = NULL;
+
+ dm_get_stats(&dev_count, &uclasses);
+
printf(" Class Index Probed Driver Name\n");
printf("-----------------------------------------------------------\n");
- show_devices(root, -1, 0);
+ if (sort) {
+ devs = calloc(dev_count, sizeof(struct udevice *));
+ if (!devs) {
+ printf("(out of memory)\n");
+ return;
+ }
+ }
+ show_devices(root, -1, 0, devs);
+ free(devs);
}
}
diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
index 759a6b728c..01d9b0201f 100644
--- a/drivers/mmc/mmc-uclass.c
+++ b/drivers/mmc/mmc-uclass.c
@@ -421,7 +421,7 @@ int mmc_bind(struct udevice *dev, struct mmc *mmc, const struct mmc_config *cfg)
mmc->cfg = cfg;
mmc->priv = dev;
- ret = bootdev_setup_for_dev(dev, "mmc_bootdev");
+ ret = bootdev_setup_sibling_blk(bdev, "mmc_bootdev");
if (ret)
return log_msg_ret("bootdev", ret);
diff --git a/drivers/mmc/mmc_bootdev.c b/drivers/mmc/mmc_bootdev.c
index b4f41fb3a6..b57b8a6227 100644
--- a/drivers/mmc/mmc_bootdev.c
+++ b/drivers/mmc/mmc_bootdev.c
@@ -11,41 +11,16 @@
#include <dm.h>
#include <mmc.h>
-static int mmc_get_bootflow(struct udevice *dev, struct bootflow_iter *iter,
- struct bootflow *bflow)
-{
- struct udevice *mmc_dev = dev_get_parent(dev);
- struct udevice *blk;
- int ret;
-
- ret = mmc_get_blk(mmc_dev, &blk);
- /*
- * If there is no media, indicate that no more partitions should be
- * checked
- */
- if (ret == -EOPNOTSUPP)
- ret = -ESHUTDOWN;
- if (ret)
- return log_msg_ret("blk", ret);
- assert(blk);
- ret = bootdev_find_in_blk(dev, blk, iter, bflow);
- if (ret)
- return log_msg_ret("find", ret);
-
- return 0;
-}
-
static int mmc_bootdev_bind(struct udevice *dev)
{
struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev);
- ucp->prio = BOOTDEVP_0_INTERNAL_FAST;
+ ucp->prio = BOOTDEVP_2_INTERNAL_FAST;
return 0;
}
struct bootdev_ops mmc_bootdev_ops = {
- .get_bootflow = mmc_get_bootflow,
};
static const struct udevice_id mmc_bootdev_ids[] = {
@@ -60,3 +35,9 @@ U_BOOT_DRIVER(mmc_bootdev) = {
.bind = mmc_bootdev_bind,
.of_match = mmc_bootdev_ids,
};
+
+BOOTDEV_HUNTER(mmc_bootdev_hunter) = {
+ .prio = BOOTDEVP_2_INTERNAL_FAST,
+ .uclass = UCLASS_MMC,
+ .drv = DM_DRIVER_REF(mmc_bootdev),
+};
diff --git a/drivers/mmc/sandbox_mmc.c b/drivers/mmc/sandbox_mmc.c
index ba79a5565c..0ba7940a4d 100644
--- a/drivers/mmc/sandbox_mmc.c
+++ b/drivers/mmc/sandbox_mmc.c
@@ -183,7 +183,7 @@ static int sandbox_mmc_probe(struct udevice *dev)
priv->csize = 0;
priv->size = (priv->csize + 1) * SIZE_MULTIPLE; /* 1 MiB */
- priv->buf = malloc(priv->size);
+ priv->buf = calloc(1, priv->size);
if (!priv->buf) {
log_err("%s: Not enough memory (%x bytes)\n",
dev->name, priv->size);
diff --git a/drivers/mtd/spi/Kconfig b/drivers/mtd/spi/Kconfig
index 7b858a3a91..a9617c6c58 100644
--- a/drivers/mtd/spi/Kconfig
+++ b/drivers/mtd/spi/Kconfig
@@ -80,6 +80,14 @@ config SF_DEFAULT_SPEED
if SPI_FLASH
+config BOOTDEV_SPI_FLASH
+ bool "SPI Flash bootdev support"
+ help
+ Enable a boot device for SPI flash. This allows reading a script
+ from SPI flash so that it can be used to boot an Operating System.
+
+ If unsure, say N
+
config SPI_FLASH_SFDP_SUPPORT
bool "SFDP table parsing support for SPI NOR flashes"
depends on !SPI_FLASH_BAR
diff --git a/drivers/mtd/spi/Makefile b/drivers/mtd/spi/Makefile
index 99cc418552..409395382f 100644
--- a/drivers/mtd/spi/Makefile
+++ b/drivers/mtd/spi/Makefile
@@ -21,3 +21,4 @@ obj-$(CONFIG_SPI_FLASH) += spi-nor.o
obj-$(CONFIG_SPI_FLASH_DATAFLASH) += sf_dataflash.o
obj-$(CONFIG_$(SPL_TPL_)SPI_FLASH_MTD) += sf_mtd.o
obj-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o
+obj-$(CONFIG_$(SPL_TPL_)BOOTDEV_SPI_FLASH) += sf_bootdev.o
diff --git a/drivers/mtd/spi/sf-uclass.c b/drivers/mtd/spi/sf-uclass.c
index e6e650ef8c..df1f75390c 100644
--- a/drivers/mtd/spi/sf-uclass.c
+++ b/drivers/mtd/spi/sf-uclass.c
@@ -6,6 +6,7 @@
#define LOG_CATEGORY UCLASS_SPI_FLASH
#include <common.h>
+#include <bootdev.h>
#include <dm.h>
#include <log.h>
#include <malloc.h>
@@ -13,6 +14,7 @@
#include <spi_flash.h>
#include <asm/global_data.h>
#include <dm/device-internal.h>
+#include <test/test.h>
#include "sf_internal.h"
DECLARE_GLOBAL_DATA_PTR;
@@ -86,6 +88,14 @@ int spi_flash_probe_bus_cs(unsigned int busnum, unsigned int cs,
static int spi_flash_post_bind(struct udevice *dev)
{
+ int ret;
+
+ if (CONFIG_IS_ENABLED(BOOTDEV_SPI_FLASH) && test_sf_bootdev_enabled()) {
+ ret = bootdev_setup_for_dev(dev, "sf_bootdev");
+ if (ret)
+ return log_msg_ret("bd", ret);
+ }
+
#if defined(CONFIG_NEEDS_MANUAL_RELOC)
struct dm_spi_flash_ops *ops = sf_get_ops(dev);
static int reloc_done;
@@ -101,6 +111,7 @@ static int spi_flash_post_bind(struct udevice *dev)
reloc_done++;
}
#endif
+
return 0;
}
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),
+};
diff --git a/drivers/nvme/nvme-uclass.c b/drivers/nvme/nvme-uclass.c
index 239a92abba..f3af6a27b6 100644
--- a/drivers/nvme/nvme-uclass.c
+++ b/drivers/nvme/nvme-uclass.c
@@ -7,9 +7,63 @@
#define LOG_CATEGORY UCLASS_NVME
#include <common.h>
+#include <bootdev.h>
#include <dm.h>
+#include <init.h>
+#include <log.h>
+#include <nvme.h>
+
+static int nvme_bootdev_bind(struct udevice *dev)
+{
+ struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev);
+
+ ucp->prio = BOOTDEVP_4_SCAN_FAST;
+
+ return 0;
+}
+
+static int nvme_bootdev_hunt(struct bootdev_hunter *info, bool show)
+{
+ int ret;
+
+ /* init PCI first since this is often used to provide NVMe */
+ if (IS_ENABLED(CONFIG_PCI)) {
+ ret = pci_init();
+ if (ret)
+ log_warning("Failed to init PCI (%dE)\n", ret);
+ }
+
+ ret = nvme_scan_namespace();
+ if (ret)
+ return log_msg_ret("scan", ret);
+
+ return 0;
+}
UCLASS_DRIVER(nvme) = {
.name = "nvme",
.id = UCLASS_NVME,
};
+
+struct bootdev_ops nvme_bootdev_ops = {
+};
+
+static const struct udevice_id nvme_bootdev_ids[] = {
+ { .compatible = "u-boot,bootdev-nvme" },
+ { }
+};
+
+U_BOOT_DRIVER(nvme_bootdev) = {
+ .name = "nvme_bootdev",
+ .id = UCLASS_BOOTDEV,
+ .ops = &nvme_bootdev_ops,
+ .bind = nvme_bootdev_bind,
+ .of_match = nvme_bootdev_ids,
+};
+
+BOOTDEV_HUNTER(nvme_bootdev_hunter) = {
+ .prio = BOOTDEVP_4_SCAN_FAST,
+ .uclass = UCLASS_NVME,
+ .hunt = nvme_bootdev_hunt,
+ .drv = DM_DRIVER_REF(nvme_bootdev),
+};
diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c
index 6d0d3f3ca2..74e7a5b011 100644
--- a/drivers/nvme/nvme.c
+++ b/drivers/nvme/nvme.c
@@ -6,6 +6,7 @@
#include <common.h>
#include <blk.h>
+#include <bootdev.h>
#include <cpu_func.h>
#include <dm.h>
#include <errno.h>
@@ -893,6 +894,10 @@ int nvme_init(struct udevice *udev)
if (ret)
goto free_id;
+ ret = bootdev_setup_sibling_blk(ns_udev, "nvme_bootdev");
+ if (ret)
+ return log_msg_ret("bootdev", ret);
+
ret = blk_probe_or_unbind(ns_udev);
if (ret)
goto free_id;
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index d1b40c6140..d8d6de5909 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -6,6 +6,13 @@
ifndef CONFIG_SPL_BUILD
obj-$(CONFIG_DM_SCSI) += scsi-uclass.o
obj-$(CONFIG_SCSI) += scsi.o
+
+ifdef CONFIG_SCSI
+ifdef CONFIG_DM_SCSI
+obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += scsi_bootdev.o
+endif
+endif
+
endif
ifdef CONFIG_SPL_BUILD
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index a020a7da23..6caeb3fcdd 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -4,8 +4,11 @@
* Denis Peter, MPL AG Switzerland
*/
+#define LOG_CATEGORY UCLASS_SCSI
+
#include <common.h>
#include <blk.h>
+#include <bootdev.h>
#include <bootstage.h>
#include <dm.h>
#include <env.h>
@@ -558,7 +561,7 @@ static int do_scsi_scan_one(struct udevice *dev, int id, int lun, bool verbose)
struct udevice *bdev;
struct blk_desc bd;
struct blk_desc *bdesc;
- char str[10];
+ char str[10], *name;
/*
* detect the scsi driver to get information about its geometry (block
@@ -574,12 +577,16 @@ static int do_scsi_scan_one(struct udevice *dev, int id, int lun, bool verbose)
* block devices created
*/
snprintf(str, sizeof(str), "id%dlun%d", id, lun);
- ret = blk_create_devicef(dev, "scsi_blk", str, UCLASS_SCSI, -1,
+ name = strdup(str);
+ if (!name)
+ return log_msg_ret("nam", -ENOMEM);
+ ret = blk_create_devicef(dev, "scsi_blk", name, UCLASS_SCSI, -1,
bd.blksz, bd.lba, &bdev);
if (ret) {
debug("Can't create device\n");
return ret;
}
+ device_set_name_alloced(bdev);
bdesc = dev_get_uclass_plat(bdev);
bdesc->target = id;
@@ -598,7 +605,11 @@ static int do_scsi_scan_one(struct udevice *dev, int id, int lun, bool verbose)
ret = blk_probe_or_unbind(bdev);
if (ret < 0)
/* TODO: undo create */
- return ret;
+ return log_msg_ret("pro", ret);
+
+ ret = bootdev_setup_sibling_blk(bdev, "scsi_bootdev");
+ if (ret)
+ return log_msg_ret("bd", ret);
if (verbose) {
printf(" Device %d: ", bdesc->devnum);
@@ -638,12 +649,23 @@ int scsi_scan(bool verbose)
if (verbose)
printf("scanning bus for devices...\n");
- blk_unbind_all(UCLASS_SCSI);
-
ret = uclass_get(UCLASS_SCSI, &uc);
if (ret)
return ret;
+ /* remove all children of the SCSI devices */
+ uclass_foreach_dev(dev, uc) {
+ log_debug("unbind %s\n", dev->name);
+ ret = device_chld_remove(dev, NULL, DM_REMOVE_NORMAL);
+ if (!ret)
+ ret = device_chld_unbind(dev, NULL);
+ if (ret) {
+ if (verbose)
+ printf("unable to unbind devices (%dE)\n", ret);
+ return log_msg_ret("unb", ret);
+ }
+ }
+
uclass_foreach_dev(dev, uc) {
ret = scsi_scan_dev(dev, verbose);
if (ret)
diff --git a/drivers/scsi/scsi_bootdev.c b/drivers/scsi/scsi_bootdev.c
new file mode 100644
index 0000000000..991013fe1e
--- /dev/null
+++ b/drivers/scsi/scsi_bootdev.c
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Bootdevice for USB
+ *
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <bootdev.h>
+#include <dm.h>
+#include <init.h>
+#include <scsi.h>
+
+static int scsi_bootdev_bind(struct udevice *dev)
+{
+ struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev);
+
+ ucp->prio = BOOTDEVP_4_SCAN_FAST;
+
+ return 0;
+}
+
+static int scsi_bootdev_hunt(struct bootdev_hunter *info, bool show)
+{
+ int ret;
+
+ if (IS_ENABLED(CONFIG_PCI)) {
+ ret = pci_init();
+ if (ret)
+ return log_msg_ret("pci", ret);
+ }
+
+ ret = scsi_scan(true);
+ if (ret)
+ return log_msg_ret("scs", ret);
+
+ return 0;
+}
+
+struct bootdev_ops scsi_bootdev_ops = {
+};
+
+static const struct udevice_id scsi_bootdev_ids[] = {
+ { .compatible = "u-boot,bootdev-scsi" },
+ { }
+};
+
+U_BOOT_DRIVER(scsi_bootdev) = {
+ .name = "scsi_bootdev",
+ .id = UCLASS_BOOTDEV,
+ .ops = &scsi_bootdev_ops,
+ .bind = scsi_bootdev_bind,
+ .of_match = scsi_bootdev_ids,
+};
+
+BOOTDEV_HUNTER(scsi_bootdev_hunter) = {
+ .prio = BOOTDEVP_4_SCAN_FAST,
+ .uclass = UCLASS_SCSI,
+ .hunt = scsi_bootdev_hunt,
+ .drv = DM_DRIVER_REF(scsi_bootdev),
+};
diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c
index 93c318c3d1..28f7ca9654 100644
--- a/drivers/usb/host/usb-uclass.c
+++ b/drivers/usb/host/usb-uclass.c
@@ -563,6 +563,8 @@ static int usb_find_and_bind_driver(struct udevice *parent,
if (!str)
return -ENOMEM;
ret = device_bind_driver(parent, "usb_dev_generic_drv", str, devp);
+ if (!ret)
+ device_set_name_alloced(*devp);
error:
debug("%s: No match found: %d\n", __func__, ret);
diff --git a/drivers/usb/host/usb_bootdev.c b/drivers/usb/host/usb_bootdev.c
index b85f699933..32919f9928 100644
--- a/drivers/usb/host/usb_bootdev.c
+++ b/drivers/usb/host/usb_bootdev.c
@@ -11,40 +11,21 @@
#include <dm.h>
#include <usb.h>
-static int usb_get_bootflow(struct udevice *dev, struct bootflow_iter *iter,
- struct bootflow *bflow)
-{
- struct udevice *blk;
- int ret;
-
- ret = bootdev_get_sibling_blk(dev, &blk);
- /*
- * If there is no media, indicate that no more partitions should be
- * checked
- */
- if (ret == -EOPNOTSUPP)
- ret = -ESHUTDOWN;
- if (ret)
- return log_msg_ret("blk", ret);
- assert(blk);
- ret = bootdev_find_in_blk(dev, blk, iter, bflow);
- if (ret)
- return log_msg_ret("find", ret);
-
- return 0;
-}
-
static int usb_bootdev_bind(struct udevice *dev)
{
struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev);
- ucp->prio = BOOTDEVP_3_SCAN_SLOW;
+ ucp->prio = BOOTDEVP_5_SCAN_SLOW;
return 0;
}
+static int usb_bootdev_hunt(struct bootdev_hunter *info, bool show)
+{
+ return usb_init();
+}
+
struct bootdev_ops usb_bootdev_ops = {
- .get_bootflow = usb_get_bootflow,
};
static const struct udevice_id usb_bootdev_ids[] = {
@@ -59,3 +40,10 @@ U_BOOT_DRIVER(usb_bootdev) = {
.bind = usb_bootdev_bind,
.of_match = usb_bootdev_ids,
};
+
+BOOTDEV_HUNTER(usb_bootdev_hunter) = {
+ .prio = BOOTDEVP_5_SCAN_SLOW,
+ .uclass = UCLASS_USB,
+ .hunt = usb_bootdev_hunt,
+ .drv = DM_DRIVER_REF(usb_bootdev),
+};
diff --git a/drivers/virtio/virtio-uclass.c b/drivers/virtio/virtio-uclass.c
index da4f2f26a6..91af412ec1 100644
--- a/drivers/virtio/virtio-uclass.c
+++ b/drivers/virtio/virtio-uclass.c
@@ -18,6 +18,7 @@
#define LOG_CATEGORY UCLASS_VIRTIO
#include <common.h>
+#include <bootdev.h>
#include <dm.h>
#include <log.h>
#include <malloc.h>
@@ -163,7 +164,7 @@ int virtio_finalize_features(struct udevice *vdev)
return ret;
if (!(status & VIRTIO_CONFIG_S_FEATURES_OK)) {
debug("(%s): device refuses features %x\n", vdev->name, status);
- return -ENODEV;
+ return -EINVAL;
}
return 0;
@@ -214,6 +215,7 @@ static int virtio_uclass_post_probe(struct udevice *udev)
struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
char dev_name[30], *str;
struct udevice *vdev;
+ const char *name;
int ret;
if (uc_priv->device >= VIRTIO_ID_MAX_NUM) {
@@ -222,20 +224,19 @@ static int virtio_uclass_post_probe(struct udevice *udev)
return 0;
}
- if (!virtio_drv_name[uc_priv->device]) {
+ name = virtio_drv_name[uc_priv->device];
+ if (!name) {
debug("(%s): underlying virtio device driver unavailable\n",
udev->name);
return 0;
}
- snprintf(dev_name, sizeof(dev_name), "%s#%d",
- virtio_drv_name[uc_priv->device], dev_seq(udev));
+ snprintf(dev_name, sizeof(dev_name), "%s#%d", name, dev_seq(udev));
str = strdup(dev_name);
if (!str)
return -ENOMEM;
- ret = device_bind_driver(udev, virtio_drv_name[uc_priv->device],
- str, &vdev);
+ ret = device_bind_driver(udev, name, str, &vdev);
if (ret == -ENOENT) {
debug("(%s): no driver configured\n", udev->name);
return 0;
@@ -246,6 +247,12 @@ static int virtio_uclass_post_probe(struct udevice *udev)
}
device_set_name_alloced(vdev);
+ if (uc_priv->device == VIRTIO_ID_BLOCK) {
+ ret = bootdev_setup_for_dev(udev, name);
+ if (ret)
+ return log_msg_ret("bootdev", ret);
+ }
+
INIT_LIST_HEAD(&uc_priv->vqs);
return 0;
@@ -349,6 +356,26 @@ static int virtio_uclass_child_post_probe(struct udevice *vdev)
return 0;
}
+static int virtio_bootdev_bind(struct udevice *dev)
+{
+ struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev);
+
+ ucp->prio = BOOTDEVP_4_SCAN_FAST;
+
+ return 0;
+}
+
+static int virtio_bootdev_hunt(struct bootdev_hunter *info, bool show)
+{
+ int ret;
+
+ ret = uclass_probe_all(UCLASS_VIRTIO);
+ if (ret && ret != -ENOENT)
+ return log_msg_ret("vir", ret);
+
+ return 0;
+}
+
UCLASS_DRIVER(virtio) = {
.name = "virtio",
.id = UCLASS_VIRTIO,
@@ -360,3 +387,26 @@ UCLASS_DRIVER(virtio) = {
.child_post_probe = virtio_uclass_child_post_probe,
.per_device_auto = sizeof(struct virtio_dev_priv),
};
+
+struct bootdev_ops virtio_bootdev_ops = {
+};
+
+static const struct udevice_id virtio_bootdev_ids[] = {
+ { .compatible = "u-boot,bootdev-virtio" },
+ { }
+};
+
+U_BOOT_DRIVER(virtio_bootdev) = {
+ .name = "virtio_bootdev",
+ .id = UCLASS_BOOTDEV,
+ .ops = &virtio_bootdev_ops,
+ .bind = virtio_bootdev_bind,
+ .of_match = virtio_bootdev_ids,
+};
+
+BOOTDEV_HUNTER(virtio_bootdev_hunter) = {
+ .prio = BOOTDEVP_4_SCAN_FAST,
+ .uclass = UCLASS_VIRTIO,
+ .hunt = virtio_bootdev_hunt,
+ .drv = DM_DRIVER_REF(virtio_bootdev),
+};
diff --git a/drivers/virtio/virtio_sandbox.c b/drivers/virtio/virtio_sandbox.c
index 5484ae3a1a..b34f1d6045 100644
--- a/drivers/virtio/virtio_sandbox.c
+++ b/drivers/virtio/virtio_sandbox.c
@@ -161,24 +161,13 @@ static int virtio_sandbox_probe(struct udevice *udev)
/* fake some information for testing */
priv->device_features = BIT_ULL(VIRTIO_F_VERSION_1);
- uc_priv->device = VIRTIO_ID_RNG;
+ uc_priv->device = dev_read_u32_default(udev, "virtio-type",
+ VIRTIO_ID_RNG);
uc_priv->vendor = ('u' << 24) | ('b' << 16) | ('o' << 8) | 't';
return 0;
}
-/* check virtio device driver's remove routine was called to reset the device */
-static int virtio_sandbox_child_post_remove(struct udevice *vdev)
-{
- u8 status;
-
- virtio_get_status(vdev, &status);
- if (status)
- panic("virtio device was not reset\n");
-
- return 0;
-}
-
static const struct dm_virtio_ops virtio_sandbox1_ops = {
.get_config = virtio_sandbox_get_config,
.set_config = virtio_sandbox_set_config,
@@ -203,7 +192,6 @@ U_BOOT_DRIVER(virtio_sandbox1) = {
.of_match = virtio_sandbox1_ids,
.ops = &virtio_sandbox1_ops,
.probe = virtio_sandbox_probe,
- .child_post_remove = virtio_sandbox_child_post_remove,
.priv_auto = sizeof(struct virtio_sandbox_priv),
};