Prepare v2023.10
[platform/kernel/u-boot.git] / lib / efi_driver / efi_block_device.c
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 #include <common.h>
32 #include <blk.h>
33 #include <dm.h>
34 #include <efi_driver.h>
35 #include <malloc.h>
36 #include <dm/device-internal.h>
37 #include <dm/root.h>
38 #include <dm/tag.h>
39
40 /**
41  * struct efi_blk_plat - attributes of a block device
42  *
43  * @handle:     handle of the controller on which this driver is installed
44  * @io:         block io protocol proxied by this driver
45  */
46 struct efi_blk_plat {
47         efi_handle_t            handle;
48         struct efi_block_io     *io;
49 };
50
51 /**
52  * efi_bl_read() - read from block device
53  *
54  * @dev:        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
59  */
60 static ulong efi_bl_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
61                          void *buffer)
62 {
63         struct efi_blk_plat *plat = dev_get_plat(dev);
64         struct efi_block_io *io = plat->io;
65         efi_status_t ret;
66
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,
71                                 (efi_uintn_t)blkcnt *
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)
76                 return 0;
77         return blkcnt;
78 }
79
80 /**
81  * efi_bl_write() - write to block device
82  *
83  * @dev:        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
88  */
89 static ulong efi_bl_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
90                           const void *buffer)
91 {
92         struct efi_blk_plat *plat = dev_get_plat(dev);
93         struct efi_block_io *io = plat->io;
94         efi_status_t ret;
95
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,
102                                 (void *)buffer));
103         EFI_PRINT("%s: r = %u\n", __func__,
104                   (unsigned int)(ret & ~EFI_ERROR_MASK));
105         if (ret != EFI_SUCCESS)
106                 return 0;
107         return blkcnt;
108 }
109
110 /**
111  * efi_bl_create_block_device() - create a block device for a handle
112  *
113  * @handle:     handle
114  * @interface:  block io protocol
115  * Return:      status code
116  */
117 static efi_status_t
118 efi_bl_create_block_device(efi_handle_t handle, void *interface)
119 {
120         struct udevice *bdev = NULL, *parent = dm_root();
121         efi_status_t ret;
122         int devnum;
123         char *name;
124         struct efi_block_io *io = interface;
125         struct efi_blk_plat *plat;
126
127         devnum = blk_next_free_devnum(UCLASS_EFI_LOADER);
128         if (devnum < 0)
129                 return EFI_OUT_OF_RESOURCES;
130
131         name = calloc(1, 18); /* strlen("efiblk#2147483648") + 1 */
132         if (!name)
133                 return EFI_OUT_OF_RESOURCES;
134         sprintf(name, "efiblk#%d", devnum);
135
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;
141                 free(name);
142                 goto err;
143         }
144         /* Set the DM_FLAG_NAME_ALLOCED flag to avoid a memory leak */
145         device_set_name_alloced(bdev);
146
147         plat = dev_get_plat(bdev);
148         plat->handle = handle;
149         plat->io = interface;
150
151         if (efi_link_dev(handle, bdev)) {
152                 ret = EFI_OUT_OF_RESOURCES;
153                 goto err;
154         }
155
156         if (device_probe(bdev)) {
157                 ret = EFI_DEVICE_ERROR;
158                 goto err;
159         }
160         EFI_PRINT("%s: block device '%s' created\n", __func__, bdev->name);
161
162         return EFI_SUCCESS;
163
164 err:
165         efi_unlink_dev(handle);
166         if (bdev)
167                 device_unbind(bdev);
168
169         return ret;
170 }
171
172 /**
173  * efi_bl_bind() - bind to a block io protocol
174  *
175  * @this:       driver binding protocol
176  * @handle:     handle
177  * @interface:  block io protocol
178  * Return:      status code
179  */
180 static efi_status_t efi_bl_bind(
181                         struct efi_driver_binding_extended_protocol *this,
182                         efi_handle_t handle, void *interface)
183 {
184         efi_status_t ret = EFI_SUCCESS;
185         struct efi_object *obj = efi_search_obj(handle);
186
187         EFI_PRINT("%s: handle %p, interface %p\n", __func__, handle, interface);
188
189         if (!obj || !interface)
190                 return EFI_INVALID_PARAMETER;
191
192         if (!handle->dev)
193                 ret = efi_bl_create_block_device(handle, interface);
194
195         return ret;
196 }
197
198 /**
199  * efi_bl_init() - initialize block device driver
200  *
201  * @this:       extended driver binding protocol
202  */
203 static efi_status_t
204 efi_bl_init(struct efi_driver_binding_extended_protocol *this)
205 {
206         int ret;
207
208         ret = event_register("efi_disk add", EVT_DM_POST_PROBE,
209                              efi_disk_probe, this);
210         if (ret) {
211                 log_err("Event registration for efi_disk add failed\n");
212                 return EFI_OUT_OF_RESOURCES;
213         }
214
215         ret = event_register("efi_disk del", EVT_DM_PRE_REMOVE,
216                              efi_disk_remove, this);
217         if (ret) {
218                 log_err("Event registration for efi_disk del failed\n");
219                 return EFI_OUT_OF_RESOURCES;
220         }
221
222         return EFI_SUCCESS;
223 }
224
225 /* Block device driver operators */
226 static const struct blk_ops efi_blk_ops = {
227         .read   = efi_bl_read,
228         .write  = efi_bl_write,
229 };
230
231 /* Identify as block device driver */
232 U_BOOT_DRIVER(efi_blk) = {
233         .name           = "efi_blk",
234         .id             = UCLASS_BLK,
235         .ops            = &efi_blk_ops,
236         .plat_auto      = sizeof(struct efi_blk_plat),
237 };
238
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,
243         .init           = efi_bl_init,
244         .bind           = efi_bl_bind,
245 };
246
247 /* Identify as EFI driver */
248 U_BOOT_DRIVER(efi_block) = {
249         .name           = "EFI block driver",
250         .id             = UCLASS_EFI_LOADER,
251         .ops            = &driver_ops,
252 };