diff options
author | Simon Glass <sjg@chromium.org> | 2022-10-29 19:47:15 -0600 |
---|---|---|
committer | Simon Glass <sjg@chromium.org> | 2022-11-07 16:24:30 -0700 |
commit | 9bd1aa8af2ed3efde28250987806aaeb12837c66 (patch) | |
tree | 3733c428484dcbb7801594dbd076d9860985ed5c /drivers/block | |
parent | 41e751091d7cb1a71ac13ab037e0fcf4fcee67e3 (diff) | |
download | u-boot-9bd1aa8af2ed3efde28250987806aaeb12837c66.zip u-boot-9bd1aa8af2ed3efde28250987806aaeb12837c66.tar.gz u-boot-9bd1aa8af2ed3efde28250987806aaeb12837c66.tar.bz2 |
dm: sandbox: Create a new HOST uclass
Sandbox supports block devices which can access files on the host machine.
At present there is no uclass for this. The devices are attached to the
root devic. The block-device type is therefore set to UCLASS_ROOT which
is confusing.
Block devices should be attached to a 'media' device instead, something
which handles access to the actual media and provides the block driver
for the block device.
Create a new uclass to handle this. It supports two operations, to attach
and detach a file on the host machine.
For now this is not fully plumbed in.
Signed-off-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/Makefile | 2 | ||||
-rw-r--r-- | drivers/block/host-uclass.c | 176 |
2 files changed, 177 insertions, 1 deletions
diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 19d9317..7f25912 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 +obj-$(CONFIG_SANDBOX) += sandbox.o host-uclass.o obj-$(CONFIG_$(SPL_TPL_)BLOCK_CACHE) += blkcache.o obj-$(CONFIG_EFI_MEDIA) += efi-media-uclass.o diff --git a/drivers/block/host-uclass.c b/drivers/block/host-uclass.c new file mode 100644 index 0000000..6460d96 --- /dev/null +++ b/drivers/block/host-uclass.c @@ -0,0 +1,176 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Uclass 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 <dm.h> +#include <malloc.h> +#include <sandbox_host.h> +#include <dm/device-internal.h> +#include <dm/lists.h> +#include <dm/uclass-internal.h> + +DECLARE_GLOBAL_DATA_PTR; + +/** + * struct host_priv - information kept by the host uclass + * + * @cur_dev: Currently selected host device, or NULL if none + */ +struct host_priv { + struct udevice *cur_dev; +}; + +int host_create_device(const char *label, bool removable, struct udevice **devp) +{ + char dev_name[30], *str, *label_new; + struct host_sb_plat *plat; + struct udevice *dev, *blk; + int ret; + + /* unbind any existing device with this label */ + dev = host_find_by_label(label); + if (dev) { + ret = host_detach_file(dev); + if (ret) + return log_msg_ret("det", ret); + + ret = device_unbind(dev); + if (ret) + return log_msg_ret("unb", ret); + } + + snprintf(dev_name, sizeof(dev_name), "host-%s", label); + str = strdup(dev_name); + if (!str) + return -ENOMEM; + + label_new = strdup(label); + if (!label_new) { + ret = -ENOMEM; + goto no_label; + } + + ret = device_bind_driver(gd->dm_root, "host_sb_drv", str, &dev); + if (ret) + goto no_dev; + device_set_name_alloced(dev); + + if (!blk_find_from_parent(dev, &blk)) { + struct blk_desc *desc = dev_get_uclass_plat(blk); + + desc->removable = removable; + } + + plat = dev_get_plat(dev); + plat->label = label_new; + *devp = dev; + + return 0; + +no_dev: + free(label_new); +no_label: + free(str); + + return ret; +} + +int host_attach_file(struct udevice *dev, const char *filename) +{ + struct host_ops *ops = host_get_ops(dev); + + if (!ops->attach_file) + return -ENOSYS; + + return ops->attach_file(dev, filename); +} + +int host_create_attach_file(const char *label, const char *filename, + bool removable, struct udevice **devp) +{ + struct udevice *dev; + int ret; + + ret = host_create_device(label, removable, &dev); + if (ret) + return log_msg_ret("cre", ret); + + ret = host_attach_file(dev, filename); + if (ret) { + device_unbind(dev); + return log_msg_ret("att", ret); + } + *devp = dev; + + return 0; +} + +int host_detach_file(struct udevice *dev) +{ + struct host_ops *ops = host_get_ops(dev); + + if (!ops->detach_file) + return -ENOSYS; + + if (dev == host_get_cur_dev()) + host_set_cur_dev(NULL); + + return ops->detach_file(dev); +} + +struct udevice *host_find_by_label(const char *label) +{ + struct udevice *dev; + struct uclass *uc; + + uclass_id_foreach_dev(UCLASS_HOST, dev, uc) { + struct host_sb_plat *plat = dev_get_plat(dev); + + if (plat->label && !strcmp(label, plat->label)) + return dev; + } + + return NULL; +} + +struct udevice *host_get_cur_dev(void) +{ + struct uclass *uc = uclass_find(UCLASS_HOST); + + if (uc) { + struct host_priv *priv = uclass_get_priv(uc); + + return priv->cur_dev; + } + + return NULL; +} + +void host_set_cur_dev(struct udevice *dev) +{ + struct uclass *uc = uclass_find(UCLASS_HOST); + + if (uc) { + struct host_priv *priv = uclass_get_priv(uc); + + priv->cur_dev = dev; + } +} + +UCLASS_DRIVER(host) = { + .id = UCLASS_HOST, + .name = "host", +#if CONFIG_IS_ENABLED(OF_REAL) + .post_bind = dm_scan_fdt_dev, +#endif + .priv_auto = sizeof(struct host_priv), +}; |