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