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