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.
31 #include <efi_driver.h>
32 #include <dm/device-internal.h>
36 * EFI attributes of the udevice handled by this driver.
38 * handle handle of the controller on which this driver is installed
39 * io block io protocol proxied by this driver
41 struct efi_blk_platdata
{
43 struct efi_block_io
*io
;
47 * Read from block device
50 * @blknr first block to be read
51 * @blkcnt number of blocks to read
52 * @buffer output buffer
53 * @return number of blocks transferred
55 static ulong
efi_bl_read(struct udevice
*dev
, lbaint_t blknr
, lbaint_t blkcnt
,
58 struct efi_blk_platdata
*platdata
= dev_get_platdata(dev
);
59 struct efi_block_io
*io
= platdata
->io
;
62 EFI_PRINT("%s: read '%s', from block " LBAFU
", " LBAFU
" blocks\n",
63 __func__
, dev
->name
, blknr
, blkcnt
);
64 ret
= EFI_CALL(io
->read_blocks(
65 io
, io
->media
->media_id
, (u64
)blknr
,
67 (efi_uintn_t
)io
->media
->block_size
, buffer
));
68 EFI_PRINT("%s: r = %u\n", __func__
,
69 (unsigned int)(ret
& ~EFI_ERROR_MASK
));
70 if (ret
!= EFI_SUCCESS
)
76 * Write to block device
79 * @blknr first block to be write
80 * @blkcnt number of blocks to write
81 * @buffer input buffer
82 * @return number of blocks transferred
84 static ulong
efi_bl_write(struct udevice
*dev
, lbaint_t blknr
, lbaint_t blkcnt
,
87 struct efi_blk_platdata
*platdata
= dev_get_platdata(dev
);
88 struct efi_block_io
*io
= platdata
->io
;
91 EFI_PRINT("%s: write '%s', from block " LBAFU
", " LBAFU
" blocks\n",
92 __func__
, dev
->name
, blknr
, blkcnt
);
93 ret
= EFI_CALL(io
->write_blocks(
94 io
, io
->media
->media_id
, (u64
)blknr
,
96 (efi_uintn_t
)io
->media
->block_size
,
98 EFI_PRINT("%s: r = %u\n", __func__
,
99 (unsigned int)(ret
& ~EFI_ERROR_MASK
));
100 if (ret
!= EFI_SUCCESS
)
106 * Create partions for the block device.
108 * @handle EFI handle of the block device
109 * @dev udevice of the block device
111 static int efi_bl_bind_partitions(efi_handle_t handle
, struct udevice
*dev
)
113 struct blk_desc
*desc
;
114 const char *if_typename
;
116 desc
= dev_get_uclass_platdata(dev
);
117 if_typename
= blk_get_if_type_name(desc
->if_type
);
119 return efi_disk_create_partitions(handle
, desc
, if_typename
,
120 desc
->devnum
, dev
->name
);
124 * Create a block device for a handle
127 * @interface block io protocol
128 * @return 0 = success
130 static int efi_bl_bind(efi_handle_t handle
, void *interface
)
132 struct udevice
*bdev
, *parent
= dm_root();
135 struct efi_object
*obj
= efi_search_obj(handle
);
136 struct efi_block_io
*io
= interface
;
138 struct efi_blk_platdata
*platdata
;
140 EFI_PRINT("%s: handle %p, interface %p\n", __func__
, handle
, io
);
145 devnum
= blk_find_max_devnum(IF_TYPE_EFI
);
146 if (devnum
== -ENODEV
)
151 name
= calloc(1, 18); /* strlen("efiblk#2147483648") + 1 */
154 sprintf(name
, "efiblk#%d", devnum
);
156 /* Create driver model udevice for the EFI block io device */
157 ret
= blk_create_device(parent
, "efi_blk", name
, IF_TYPE_EFI
, devnum
,
158 io
->media
->block_size
,
159 (lbaint_t
)io
->media
->last_block
, &bdev
);
164 /* Set the DM_FLAG_NAME_ALLOCED flag to avoid a memory leak */
165 device_set_name_alloced(bdev
);
167 platdata
= dev_get_platdata(bdev
);
168 platdata
->handle
= handle
;
169 platdata
->io
= interface
;
171 ret
= device_probe(bdev
);
174 EFI_PRINT("%s: block device '%s' created\n", __func__
, bdev
->name
);
176 /* Create handles for the partions of the block device */
177 disks
= efi_bl_bind_partitions(handle
, bdev
);
178 EFI_PRINT("Found %d partitions\n", disks
);
183 /* Block device driver operators */
184 static const struct blk_ops efi_blk_ops
= {
186 .write
= efi_bl_write
,
189 /* Identify as block device driver */
190 U_BOOT_DRIVER(efi_blk
) = {
194 .platdata_auto_alloc_size
= sizeof(struct efi_blk_platdata
),
197 /* EFI driver operators */
198 static const struct efi_driver_ops driver_ops
= {
199 .protocol
= &efi_block_io_guid
,
200 .child_protocol
= &efi_block_io_guid
,
204 /* Identify as EFI driver */
205 U_BOOT_DRIVER(efi_block
) = {
206 .name
= "EFI block driver",