1 // SPDX-License-Identifier: GPL-2.0+
5 * Copyright (c) 2017 Heinrich Schuchardt
7 * The EFI uclass creates a handle for this driver and installs the
8 * driver binding protocol on it.
10 * The EFI block driver binds to controllers implementing the block io
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.
17 * The read and write functions of the EFI block driver delegate calls to the
18 * controller that it is bound to.
20 * A usage example is as following:
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.
25 * Now the EFI block driver installs the partitions with the simple file
28 * iPXE uses the simple file protocol to load Grub or the Linux Kernel.
34 #include <efi_driver.h>
36 #include <dm/device-internal.h>
41 * struct efi_blk_plat - attributes of a block device
43 * @handle: handle of the controller on which this driver is installed
44 * @io: block io protocol proxied by this driver
48 struct efi_block_io *io;
52 * efi_bl_read() - read from block device
55 * @blknr: first block to be read
56 * @blkcnt: number of blocks to read
57 * @buffer: output buffer
58 * Return: number of blocks transferred
60 static ulong efi_bl_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
63 struct efi_blk_plat *plat = dev_get_plat(dev);
64 struct efi_block_io *io = plat->io;
67 EFI_PRINT("%s: read '%s', from block " LBAFU ", " LBAFU " blocks\n",
68 __func__, dev->name, blknr, blkcnt);
69 ret = EFI_CALL(io->read_blocks(
70 io, io->media->media_id, (u64)blknr,
72 (efi_uintn_t)io->media->block_size, buffer));
73 EFI_PRINT("%s: r = %u\n", __func__,
74 (unsigned int)(ret & ~EFI_ERROR_MASK));
75 if (ret != EFI_SUCCESS)
81 * efi_bl_write() - write to block device
84 * @blknr: first block to be write
85 * @blkcnt: number of blocks to write
86 * @buffer: input buffer
87 * Return: number of blocks transferred
89 static ulong efi_bl_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
92 struct efi_blk_plat *plat = dev_get_plat(dev);
93 struct efi_block_io *io = plat->io;
96 EFI_PRINT("%s: write '%s', from block " LBAFU ", " LBAFU " blocks\n",
97 __func__, dev->name, blknr, blkcnt);
98 ret = EFI_CALL(io->write_blocks(
99 io, io->media->media_id, (u64)blknr,
100 (efi_uintn_t)blkcnt *
101 (efi_uintn_t)io->media->block_size,
103 EFI_PRINT("%s: r = %u\n", __func__,
104 (unsigned int)(ret & ~EFI_ERROR_MASK));
105 if (ret != EFI_SUCCESS)
111 * efi_bl_create_block_device() - create a block device for a handle
114 * @interface: block io protocol
115 * Return: status code
118 efi_bl_create_block_device(efi_handle_t handle, void *interface)
120 struct udevice *bdev = NULL, *parent = dm_root();
124 struct efi_block_io *io = interface;
125 struct efi_blk_plat *plat;
127 devnum = blk_next_free_devnum(UCLASS_EFI_LOADER);
129 return EFI_OUT_OF_RESOURCES;
131 name = calloc(1, 18); /* strlen("efiblk#2147483648") + 1 */
133 return EFI_OUT_OF_RESOURCES;
134 sprintf(name, "efiblk#%d", devnum);
136 /* Create driver model udevice for the EFI block io device */
137 if (blk_create_device(parent, "efi_blk", name, UCLASS_EFI_LOADER,
138 devnum, io->media->block_size,
139 (lbaint_t)io->media->last_block, &bdev)) {
140 ret = EFI_OUT_OF_RESOURCES;
144 /* Set the DM_FLAG_NAME_ALLOCED flag to avoid a memory leak */
145 device_set_name_alloced(bdev);
147 plat = dev_get_plat(bdev);
148 plat->handle = handle;
149 plat->io = interface;
151 if (efi_link_dev(handle, bdev)) {
152 ret = EFI_OUT_OF_RESOURCES;
156 if (device_probe(bdev)) {
157 ret = EFI_DEVICE_ERROR;
160 EFI_PRINT("%s: block device '%s' created\n", __func__, bdev->name);
165 efi_unlink_dev(handle);
173 * efi_bl_bind() - bind to a block io protocol
175 * @this: driver binding protocol
177 * @interface: block io protocol
178 * Return: status code
180 static efi_status_t efi_bl_bind(
181 struct efi_driver_binding_extended_protocol *this,
182 efi_handle_t handle, void *interface)
184 efi_status_t ret = EFI_SUCCESS;
185 struct efi_object *obj = efi_search_obj(handle);
187 EFI_PRINT("%s: handle %p, interface %p\n", __func__, handle, interface);
189 if (!obj || !interface)
190 return EFI_INVALID_PARAMETER;
193 ret = efi_bl_create_block_device(handle, interface);
199 * efi_bl_init() - initialize block device driver
201 * @this: extended driver binding protocol
204 efi_bl_init(struct efi_driver_binding_extended_protocol *this)
208 ret = event_register("efi_disk add", EVT_DM_POST_PROBE,
209 efi_disk_probe, this);
211 log_err("Event registration for efi_disk add failed\n");
212 return EFI_OUT_OF_RESOURCES;
215 ret = event_register("efi_disk del", EVT_DM_PRE_REMOVE,
216 efi_disk_remove, this);
218 log_err("Event registration for efi_disk del failed\n");
219 return EFI_OUT_OF_RESOURCES;
225 /* Block device driver operators */
226 static const struct blk_ops efi_blk_ops = {
228 .write = efi_bl_write,
231 /* Identify as block device driver */
232 U_BOOT_DRIVER(efi_blk) = {
236 .plat_auto = sizeof(struct efi_blk_plat),
239 /* EFI driver operators */
240 static const struct efi_driver_ops driver_ops = {
241 .protocol = &efi_block_io_guid,
242 .child_protocol = &efi_block_io_guid,
247 /* Identify as EFI driver */
248 U_BOOT_DRIVER(efi_block) = {
249 .name = "EFI block driver",
250 .id = UCLASS_EFI_LOADER,