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 * EFI attributes of the udevice handled by this driver.
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 * 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 * 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 * Create a block device for a handle
114 * @interface: block io protocol
115 * Return: 0 = success
117 static int efi_bl_bind(efi_handle_t handle, void *interface)
119 struct udevice *bdev, *parent = dm_root();
122 struct efi_object *obj = efi_search_obj(handle);
123 struct efi_block_io *io = interface;
124 struct efi_blk_plat *plat;
126 EFI_PRINT("%s: handle %p, interface %p\n", __func__, handle, io);
131 devnum = blk_find_max_devnum(UCLASS_EFI_LOADER);
132 if (devnum == -ENODEV)
137 name = calloc(1, 18); /* strlen("efiblk#2147483648") + 1 */
140 sprintf(name, "efiblk#%d", devnum);
142 /* Create driver model udevice for the EFI block io device */
143 ret = blk_create_device(parent, "efi_blk", name, UCLASS_EFI_LOADER,
144 devnum, io->media->block_size,
145 (lbaint_t)io->media->last_block, &bdev);
150 /* Set the DM_FLAG_NAME_ALLOCED flag to avoid a memory leak */
151 device_set_name_alloced(bdev);
153 plat = dev_get_plat(bdev);
154 plat->handle = handle;
155 plat->io = interface;
158 * FIXME: necessary because we won't do almost nothing in
159 * efi_disk_create() when called from device_probe().
161 if (efi_link_dev(handle, bdev))
162 /* FIXME: cleanup for bdev */
165 ret = device_probe(bdev);
168 EFI_PRINT("%s: block device '%s' created\n", __func__, bdev->name);
173 /* Block device driver operators */
174 static const struct blk_ops efi_blk_ops = {
176 .write = efi_bl_write,
179 /* Identify as block device driver */
180 U_BOOT_DRIVER(efi_blk) = {
184 .plat_auto = sizeof(struct efi_blk_plat),
187 /* EFI driver operators */
188 static const struct efi_driver_ops driver_ops = {
189 .protocol = &efi_block_io_guid,
190 .child_protocol = &efi_block_io_guid,
194 /* Identify as EFI driver */
195 U_BOOT_DRIVER(efi_block) = {
196 .name = "EFI block driver",
197 .id = UCLASS_EFI_LOADER,