"Das U-Boot" Source Tree
at master 184 lines 3.6 kB view raw
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Uclass for sandbox host interface, used to access files on the host which 4 * contain partitions and filesystem 5 * 6 * Copyright 2022 Google LLC 7 * Written by Simon Glass <sjg@chromium.org> 8 */ 9 10#define LOG_CATEGORY UCLASS_HOST 11 12#include <blk.h> 13#include <dm.h> 14#include <malloc.h> 15#include <part.h> 16#include <sandbox_host.h> 17#include <dm/device-internal.h> 18#include <dm/lists.h> 19#include <dm/uclass-internal.h> 20 21DECLARE_GLOBAL_DATA_PTR; 22 23/** 24 * struct host_priv - information kept by the host uclass 25 * 26 * @cur_dev: Currently selected host device, or NULL if none 27 */ 28struct host_priv { 29 struct udevice *cur_dev; 30}; 31 32int host_create_device(const char *label, bool removable, unsigned long blksz, 33 struct udevice **devp) 34{ 35 char dev_name[30], *str, *label_new; 36 struct host_sb_plat *plat; 37 struct udevice *dev, *blk; 38 int ret; 39 40 /* unbind any existing device with this label */ 41 dev = host_find_by_label(label); 42 if (dev) { 43 ret = host_detach_file(dev); 44 if (ret) 45 return log_msg_ret("det", ret); 46 47 ret = device_unbind(dev); 48 if (ret) 49 return log_msg_ret("unb", ret); 50 } 51 52 snprintf(dev_name, sizeof(dev_name), "host-%s", label); 53 str = strdup(dev_name); 54 if (!str) 55 return -ENOMEM; 56 57 label_new = strdup(label); 58 if (!label_new) { 59 ret = -ENOMEM; 60 goto no_label; 61 } 62 63 ret = device_bind_driver(gd->dm_root, "host_sb_drv", str, &dev); 64 if (ret) 65 goto no_dev; 66 device_set_name_alloced(dev); 67 68 if (!blk_find_from_parent(dev, &blk)) { 69 struct blk_desc *desc = dev_get_uclass_plat(blk); 70 71 desc->removable = removable; 72 73 /* update blk device's block size with the provided one */ 74 if (blksz != desc->blksz) { 75 desc->blksz = blksz; 76 desc->log2blksz = LOG2(desc->blksz); 77 } 78 } 79 80 plat = dev_get_plat(dev); 81 plat->label = label_new; 82 *devp = dev; 83 84 return 0; 85 86no_dev: 87 free(label_new); 88no_label: 89 free(str); 90 91 return ret; 92} 93 94int host_attach_file(struct udevice *dev, const char *filename) 95{ 96 struct host_ops *ops = host_get_ops(dev); 97 98 if (!ops->attach_file) 99 return -ENOSYS; 100 101 return ops->attach_file(dev, filename); 102} 103 104int host_create_attach_file(const char *label, const char *filename, 105 bool removable, unsigned long blksz, 106 struct udevice **devp) 107{ 108 struct udevice *dev; 109 int ret; 110 111 ret = host_create_device(label, removable, blksz, &dev); 112 if (ret) 113 return log_msg_ret("cre", ret); 114 115 ret = host_attach_file(dev, filename); 116 if (ret) { 117 device_unbind(dev); 118 return log_msg_ret("att", ret); 119 } 120 *devp = dev; 121 122 return 0; 123} 124 125int host_detach_file(struct udevice *dev) 126{ 127 struct host_ops *ops = host_get_ops(dev); 128 129 if (!ops->detach_file) 130 return -ENOSYS; 131 132 if (dev == host_get_cur_dev()) 133 host_set_cur_dev(NULL); 134 135 return ops->detach_file(dev); 136} 137 138struct udevice *host_find_by_label(const char *label) 139{ 140 struct udevice *dev; 141 struct uclass *uc; 142 143 uclass_id_foreach_dev(UCLASS_HOST, dev, uc) { 144 struct host_sb_plat *plat = dev_get_plat(dev); 145 146 if (plat->label && !strcmp(label, plat->label)) 147 return dev; 148 } 149 150 return NULL; 151} 152 153struct udevice *host_get_cur_dev(void) 154{ 155 struct uclass *uc = uclass_find(UCLASS_HOST); 156 157 if (uc) { 158 struct host_priv *priv = uclass_get_priv(uc); 159 160 return priv->cur_dev; 161 } 162 163 return NULL; 164} 165 166void host_set_cur_dev(struct udevice *dev) 167{ 168 struct uclass *uc = uclass_find(UCLASS_HOST); 169 170 if (uc) { 171 struct host_priv *priv = uclass_get_priv(uc); 172 173 priv->cur_dev = dev; 174 } 175} 176 177UCLASS_DRIVER(host) = { 178 .id = UCLASS_HOST, 179 .name = "host", 180#if CONFIG_IS_ENABLED(OF_REAL) 181 .post_bind = dm_scan_fdt_dev, 182#endif 183 .priv_auto = sizeof(struct host_priv), 184};