aboutsummaryrefslogtreecommitdiff
path: root/drivers/block
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2022-10-29 19:47:16 -0600
committerSimon Glass <sjg@chromium.org>2022-11-07 16:24:30 -0700
commit10aae1145c910857053343a2f3e841b38eb77bd0 (patch)
tree03732fb4af770582d9d75dee1619962f62b7333d /drivers/block
parent9bd1aa8af2ed3efde28250987806aaeb12837c66 (diff)
downloadu-boot-10aae1145c910857053343a2f3e841b38eb77bd0.zip
u-boot-10aae1145c910857053343a2f3e841b38eb77bd0.tar.gz
u-boot-10aae1145c910857053343a2f3e841b38eb77bd0.tar.bz2
dm: sandbox: Create a block driver
Create a block driver for the new HOST uclass. This handles attaching and detaching host files. For now the uclass is not used but this will be plumbed in with future patches. Signed-off-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/Makefile2
-rw-r--r--drivers/block/host_dev.c142
2 files changed, 143 insertions, 1 deletions
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index 7f25912..f12447d 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -12,7 +12,7 @@ endif
ifndef CONFIG_SPL_BUILD
obj-$(CONFIG_IDE) += ide.o
endif
-obj-$(CONFIG_SANDBOX) += sandbox.o host-uclass.o
+obj-$(CONFIG_SANDBOX) += sandbox.o host-uclass.o host_dev.o
obj-$(CONFIG_$(SPL_TPL_)BLOCK_CACHE) += blkcache.o
obj-$(CONFIG_EFI_MEDIA) += efi-media-uclass.o
diff --git a/drivers/block/host_dev.c b/drivers/block/host_dev.c
new file mode 100644
index 0000000..5885fc3
--- /dev/null
+++ b/drivers/block/host_dev.c
@@ -0,0 +1,142 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Driver for sandbox host interface, used to access files on the host which
+ * contain partitions and filesystem
+ *
+ * Copyright 2022 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#define LOG_CATEGORY UCLASS_HOST
+
+#include <common.h>
+#include <blk.h>
+#include <bootdev.h>
+#include <dm.h>
+#include <log.h>
+#include <malloc.h>
+#include <os.h>
+#include <sandbox_host.h>
+#include <dm/device-internal.h>
+
+static int host_sb_attach_file(struct udevice *dev, const char *filename)
+{
+ struct host_sb_plat *plat = dev_get_plat(dev);
+ struct blk_desc *desc;
+ struct udevice *blk;
+ int ret, fd, size;
+ char *fname;
+
+ if (!filename)
+ return -EINVAL;
+
+ if (plat->fd)
+ return log_msg_ret("fd", -EEXIST);
+
+ /* Sanity check that host_sb_bind() has been used */
+ ret = blk_find_from_parent(dev, &blk);
+ if (ret)
+ return ret;
+
+ fd = os_open(filename, OS_O_RDWR);
+ if (fd == -1) {
+ printf("Failed to access host backing file '%s', trying read-only\n",
+ filename);
+ fd = os_open(filename, OS_O_RDONLY);
+ if (fd == -1) {
+ printf("- still failed\n");
+ return log_msg_ret("open", -ENOENT);
+ }
+ }
+
+ fname = strdup(filename);
+ if (!fname) {
+ ret = -ENOMEM;
+ goto err_fname;
+ }
+
+ size = os_filesize(fd);
+ desc = dev_get_uclass_plat(blk);
+ desc->lba = size / desc->blksz;
+
+ /* write this in last, when nothing can go wrong */
+ plat = dev_get_plat(dev);
+ plat->fd = fd;
+ plat->filename = fname;
+
+ return 0;
+
+err_fname:
+ os_close(fd);
+
+ return ret;
+}
+
+int host_sb_detach_file(struct udevice *dev)
+{
+ struct host_sb_plat *plat = dev_get_plat(dev);
+ int ret;
+
+ if (!plat->fd)
+ return log_msg_ret("fd", -ENOENT);
+
+ ret = device_remove(dev, DM_REMOVE_NORMAL);
+ if (ret)
+ return log_msg_ret("rem", ret);
+
+ /* Unbind all children */
+ ret = device_chld_unbind(dev, NULL);
+ if (ret)
+ return log_msg_ret("unb", ret);
+
+ os_close(plat->fd);
+ plat->fd = 0;
+ free(plat->filename);
+ free(plat->label);
+
+ return 0;
+}
+
+static int host_sb_bind(struct udevice *dev)
+{
+ struct udevice *blk, *bdev;
+ struct blk_desc *desc;
+ int ret;
+
+ ret = blk_create_devicef(dev, "sandbox_host_blk", "blk", UCLASS_HOST,
+ dev_seq(dev), 512, 0, &blk);
+ if (ret)
+ return log_msg_ret("blk", ret);
+
+ desc = dev_get_uclass_plat(blk);
+ snprintf(desc->vendor, BLK_VEN_SIZE, "U-Boot");
+ snprintf(desc->product, BLK_PRD_SIZE, "hostfile");
+ snprintf(desc->revision, BLK_REV_SIZE, "1.0");
+
+ if (CONFIG_IS_ENABLED(BOOTSTD)) {
+ ret = bootdev_bind(dev, "host_bootdev", "bootdev", &bdev);
+ if (ret)
+ return log_msg_ret("bd", ret);
+ }
+
+ return 0;
+}
+
+struct host_ops host_sb_ops = {
+ .attach_file = host_sb_attach_file,
+ .detach_file = host_sb_detach_file,
+};
+
+static const struct udevice_id host_ids[] = {
+ { .compatible = "sandbox,host" },
+ { }
+};
+
+U_BOOT_DRIVER(host_sb_drv) = {
+ .name = "host_sb_drv",
+ .id = UCLASS_HOST,
+ .of_match = host_ids,
+ .ops = &host_sb_ops,
+ .bind = host_sb_bind,
+ .plat_auto = sizeof(struct host_sb_plat),
+};