1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * EFI block driver
4 *
5 * Copyright (c) 2017 Heinrich Schuchardt
6 *
7 * The EFI uclass creates a handle for this driver and installs the
8 * driver binding protocol on it.
9 *
10 * The EFI block driver binds to controllers implementing the block io
11 * protocol.
12 *
13 * When the bind function of the EFI block driver is called it creates a
14 * new U-Boot block device. It installs child handles for all partitions and
15 * installs the simple file protocol on these.
16 *
17 * The read and write functions of the EFI block driver delegate calls to the
18 * controller that it is bound to.
19 *
20 * A usage example is as following:
21 *
22 * U-Boot loads the iPXE snp.efi executable. iPXE connects an iSCSI drive and
23 * exposes a handle with the block IO protocol. It calls ConnectController.
24 *
25 * Now the EFI block driver installs the partitions with the simple file
26 * protocol.
27 *
28 * iPXE uses the simple file protocol to load Grub or the Linux Kernel.
29 */
30
31 #define LOG_CATEGORY LOGC_EFI
32
33 #include <blk.h>
34 #include <dm.h>
35 #include <efi_driver.h>
36 #include <malloc.h>
37 #include <dm/device-internal.h>
38 #include <dm/lists.h>
39 #include <dm/root.h>
40 #include <dm/tag.h>
41 #include <dm/uclass-internal.h>
42
43 /**
44 * struct efi_blk_plat - attributes of a block device
45 *
46 * @handle: handle of the controller on which this driver is installed
47 * @io: block io protocol proxied by this driver
48 */
49 struct efi_blk_plat {
50 efi_handle_t handle;
51 struct efi_block_io *io;
52 };
53
54 /**
55 * efi_bl_read() - read from block device
56 *
57 * @dev: device
58 * @blknr: first block to be read
59 * @blkcnt: number of blocks to read
60 * @buffer: output buffer
61 * Return: number of blocks transferred
62 */
efi_bl_read(struct udevice * dev,lbaint_t blknr,lbaint_t blkcnt,void * buffer)63 static ulong efi_bl_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
64 void *buffer)
65 {
66 struct efi_blk_plat *plat = dev_get_plat(dev);
67 struct efi_block_io *io = plat->io;
68 efi_status_t ret;
69
70 EFI_PRINT("%s: read '%s', from block " LBAFU ", " LBAFU " blocks\n",
71 __func__, dev->name, blknr, blkcnt);
72 ret = EFI_CALL(io->read_blocks(
73 io, io->media->media_id, (u64)blknr,
74 (efi_uintn_t)blkcnt *
75 (efi_uintn_t)io->media->block_size, buffer));
76 EFI_PRINT("%s: r = %u\n", __func__,
77 (unsigned int)(ret & ~EFI_ERROR_MASK));
78 if (ret != EFI_SUCCESS)
79 return 0;
80 return blkcnt;
81 }
82
83 /**
84 * efi_bl_write() - write to block device
85 *
86 * @dev: device
87 * @blknr: first block to be write
88 * @blkcnt: number of blocks to write
89 * @buffer: input buffer
90 * Return: number of blocks transferred
91 */
efi_bl_write(struct udevice * dev,lbaint_t blknr,lbaint_t blkcnt,const void * buffer)92 static ulong efi_bl_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
93 const void *buffer)
94 {
95 struct efi_blk_plat *plat = dev_get_plat(dev);
96 struct efi_block_io *io = plat->io;
97 efi_status_t ret;
98
99 EFI_PRINT("%s: write '%s', from block " LBAFU ", " LBAFU " blocks\n",
100 __func__, dev->name, blknr, blkcnt);
101 ret = EFI_CALL(io->write_blocks(
102 io, io->media->media_id, (u64)blknr,
103 (efi_uintn_t)blkcnt *
104 (efi_uintn_t)io->media->block_size,
105 (void *)buffer));
106 EFI_PRINT("%s: r = %u\n", __func__,
107 (unsigned int)(ret & ~EFI_ERROR_MASK));
108 if (ret != EFI_SUCCESS)
109 return 0;
110 return blkcnt;
111 }
112
113 /**
114 * efi_bl_create_block_device() - create a block device for a handle
115 *
116 * @handle: handle
117 * @interface: block io protocol
118 * Return: status code
119 */
120 static efi_status_t
efi_bl_create_block_device(efi_handle_t handle,void * interface)121 efi_bl_create_block_device(efi_handle_t handle, void *interface)
122 {
123 struct udevice *bdev = NULL, *parent;
124 efi_status_t ret;
125 int r;
126 int devnum;
127 char *name;
128 struct efi_block_io *io = interface;
129 struct efi_blk_plat *plat;
130
131 r = uclass_find_first_device(UCLASS_EFI_LOADER, &parent);
132 if (r)
133 return EFI_OUT_OF_RESOURCES;
134
135 devnum = blk_next_free_devnum(UCLASS_EFI_LOADER);
136 if (devnum < 0)
137 return EFI_OUT_OF_RESOURCES;
138
139 name = calloc(1, 18); /* strlen("efiblk#2147483648") + 1 */
140 if (!name)
141 return EFI_OUT_OF_RESOURCES;
142 sprintf(name, "efiblk#%d", devnum);
143
144 /* Create driver model udevice for the EFI block io device */
145 if (blk_create_devicef(parent, "efi_blk", name, UCLASS_EFI_LOADER,
146 devnum, io->media->block_size,
147 (lbaint_t)io->media->last_block, &bdev)) {
148 ret = EFI_OUT_OF_RESOURCES;
149 free(name);
150 goto err;
151 }
152
153 plat = dev_get_plat(bdev);
154 plat->handle = handle;
155 plat->io = interface;
156
157 if (efi_link_dev(handle, bdev)) {
158 ret = EFI_OUT_OF_RESOURCES;
159 goto err;
160 }
161
162 if (device_probe(bdev)) {
163 ret = EFI_DEVICE_ERROR;
164 goto err;
165 }
166 EFI_PRINT("%s: block device '%s' created\n", __func__, bdev->name);
167
168 return EFI_SUCCESS;
169
170 err:
171 efi_unlink_dev(handle);
172 if (bdev)
173 device_unbind(bdev);
174
175 return ret;
176 }
177
178 /**
179 * efi_bl_bind() - bind to a block io protocol
180 *
181 * @this: driver binding protocol
182 * @handle: handle
183 * @interface: block io protocol
184 * Return: status code
185 */
efi_bl_bind(struct efi_driver_binding_extended_protocol * this,efi_handle_t handle,void * interface)186 static efi_status_t efi_bl_bind(
187 struct efi_driver_binding_extended_protocol *this,
188 efi_handle_t handle, void *interface)
189 {
190 efi_status_t ret = EFI_SUCCESS;
191 struct efi_object *obj = efi_search_obj(handle);
192
193 EFI_PRINT("%s: handle %p, interface %p\n", __func__, handle, interface);
194
195 if (!obj || !interface)
196 return EFI_INVALID_PARAMETER;
197
198 if (!handle->dev)
199 ret = efi_bl_create_block_device(handle, interface);
200
201 return ret;
202 }
203
204 /**
205 * efi_bl_init() - initialize block device driver
206 *
207 * @this: extended driver binding protocol
208 */
209 static efi_status_t
efi_bl_init(struct efi_driver_binding_extended_protocol * this)210 efi_bl_init(struct efi_driver_binding_extended_protocol *this)
211 {
212 int ret;
213
214 ret = event_register("efi_disk add", EVT_DM_POST_PROBE,
215 efi_disk_probe, this);
216 if (ret) {
217 log_err("Event registration for efi_disk add failed\n");
218 return EFI_OUT_OF_RESOURCES;
219 }
220
221 ret = event_register("efi_disk del", EVT_DM_PRE_REMOVE,
222 efi_disk_remove, this);
223 if (ret) {
224 log_err("Event registration for efi_disk del failed\n");
225 return EFI_OUT_OF_RESOURCES;
226 }
227
228 return EFI_SUCCESS;
229 }
230
231 /**
232 * efi_block_device_create() - create parent for EFI block devices
233 *
234 * Create a device that serves as parent for all block devices created via
235 * ConnectController().
236 *
237 * Return: 0 for success
238 */
efi_block_device_create(void)239 static int efi_block_device_create(void)
240 {
241 int ret;
242 struct udevice *dev;
243
244 ret = device_bind_driver(gd->dm_root, "EFI block driver", "efi", &dev);
245
246 return ret;
247 }
248
249 /* Block device driver operators */
250 static const struct blk_ops efi_blk_ops = {
251 .read = efi_bl_read,
252 .write = efi_bl_write,
253 };
254
255 /* Identify as block device driver */
256 U_BOOT_DRIVER(efi_blk) = {
257 .name = "efi_blk",
258 .id = UCLASS_BLK,
259 .ops = &efi_blk_ops,
260 .plat_auto = sizeof(struct efi_blk_plat),
261 };
262
263 /* EFI driver operators */
264 static const struct efi_driver_ops driver_ops = {
265 .protocol = &efi_block_io_guid,
266 .child_protocol = &efi_block_io_guid,
267 .init = efi_bl_init,
268 .bind = efi_bl_bind,
269 };
270
271 /* Identify as EFI driver */
272 U_BOOT_DRIVER(efi_block) = {
273 .name = "EFI block driver",
274 .id = UCLASS_EFI_LOADER,
275 .ops = &driver_ops,
276 };
277
278 EVENT_SPY_SIMPLE(EVT_LAST_STAGE_INIT, efi_block_device_create);
279