Merge tag 'efi-2019-10-rc1-2' of https://gitlab.denx.de/u-boot/custodians/u-boot-efi
[oweals/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 <efi_driver.h>
32 #include <dm/device-internal.h>
33 #include <dm/root.h>
34
35 /*
36  * EFI attributes of the udevice handled by this driver.
37  *
38  * handle       handle of the controller on which this driver is installed
39  * io           block io protocol proxied by this driver
40  */
41 struct efi_blk_platdata {
42         efi_handle_t            handle;
43         struct efi_block_io     *io;
44 };
45
46 /**
47  * Read from block device
48  *
49  * @dev:        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
54  */
55 static ulong efi_bl_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
56                          void *buffer)
57 {
58         struct efi_blk_platdata *platdata = dev_get_platdata(dev);
59         struct efi_block_io *io = platdata->io;
60         efi_status_t ret;
61
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,
66                                 (efi_uintn_t)blkcnt *
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)
71                 return 0;
72         return blkcnt;
73 }
74
75 /**
76  * Write to block device
77  *
78  * @dev:        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
83  */
84 static ulong efi_bl_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
85                           const void *buffer)
86 {
87         struct efi_blk_platdata *platdata = dev_get_platdata(dev);
88         struct efi_block_io *io = platdata->io;
89         efi_status_t ret;
90
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,
95                                 (efi_uintn_t)blkcnt *
96                                 (efi_uintn_t)io->media->block_size,
97                                 (void *)buffer));
98         EFI_PRINT("%s: r = %u\n", __func__,
99                   (unsigned int)(ret & ~EFI_ERROR_MASK));
100         if (ret != EFI_SUCCESS)
101                 return 0;
102         return blkcnt;
103 }
104
105 /**
106  * Create partions for the block device.
107  *
108  * @handle:     EFI handle of the block device
109  * @dev:        udevice of the block device
110  * Return:      number of partitions created
111  */
112 static int efi_bl_bind_partitions(efi_handle_t handle, struct udevice *dev)
113 {
114         struct blk_desc *desc;
115         const char *if_typename;
116
117         desc = dev_get_uclass_platdata(dev);
118         if_typename = blk_get_if_type_name(desc->if_type);
119
120         return efi_disk_create_partitions(handle, desc, if_typename,
121                                           desc->devnum, dev->name);
122 }
123
124 /**
125  * Create a block device for a handle
126  *
127  * @handle:     handle
128  * @interface:  block io protocol
129  * Return:      0 = success
130  */
131 static int efi_bl_bind(efi_handle_t handle, void *interface)
132 {
133         struct udevice *bdev, *parent = dm_root();
134         int ret, devnum;
135         char *name;
136         struct efi_object *obj = efi_search_obj(handle);
137         struct efi_block_io *io = interface;
138         int disks;
139         struct efi_blk_platdata *platdata;
140
141         EFI_PRINT("%s: handle %p, interface %p\n", __func__, handle, io);
142
143         if (!obj)
144                 return -ENOENT;
145
146         devnum = blk_find_max_devnum(IF_TYPE_EFI);
147         if (devnum == -ENODEV)
148                 devnum = 0;
149         else if (devnum < 0)
150                 return devnum;
151
152         name = calloc(1, 18); /* strlen("efiblk#2147483648") + 1 */
153         if (!name)
154                 return -ENOMEM;
155         sprintf(name, "efiblk#%d", devnum);
156
157         /* Create driver model udevice for the EFI block io device */
158         ret = blk_create_device(parent, "efi_blk", name, IF_TYPE_EFI, devnum,
159                                 io->media->block_size,
160                                 (lbaint_t)io->media->last_block, &bdev);
161         if (ret)
162                 return ret;
163         if (!bdev)
164                 return -ENOENT;
165         /* Set the DM_FLAG_NAME_ALLOCED flag to avoid a memory leak */
166         device_set_name_alloced(bdev);
167
168         platdata = dev_get_platdata(bdev);
169         platdata->handle = handle;
170         platdata->io = interface;
171
172         ret = device_probe(bdev);
173         if (ret)
174                 return ret;
175         EFI_PRINT("%s: block device '%s' created\n", __func__, bdev->name);
176
177         /* Create handles for the partions of the block device */
178         disks = efi_bl_bind_partitions(handle, bdev);
179         EFI_PRINT("Found %d partitions\n", disks);
180
181         return 0;
182 }
183
184 /* Block device driver operators */
185 static const struct blk_ops efi_blk_ops = {
186         .read   = efi_bl_read,
187         .write  = efi_bl_write,
188 };
189
190 /* Identify as block device driver */
191 U_BOOT_DRIVER(efi_blk) = {
192         .name                   = "efi_blk",
193         .id                     = UCLASS_BLK,
194         .ops                    = &efi_blk_ops,
195         .platdata_auto_alloc_size = sizeof(struct efi_blk_platdata),
196 };
197
198 /* EFI driver operators */
199 static const struct efi_driver_ops driver_ops = {
200         .protocol       = &efi_block_io_guid,
201         .child_protocol = &efi_block_io_guid,
202         .bind           = efi_bl_bind,
203 };
204
205 /* Identify as EFI driver */
206 U_BOOT_DRIVER(efi_block) = {
207         .name           = "EFI block driver",
208         .id             = UCLASS_EFI,
209         .ops            = &driver_ops,
210 };