]> Git Repo - u-boot.git/blob - lib/efi_driver/efi_block_device.c
blk: Switch over to using uclass IDs
[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  * EFI attributes of the udevice handled by this driver.
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  * 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  * 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  * Create a block device for a handle
112  *
113  * @handle:     handle
114  * @interface:  block io protocol
115  * Return:      0 = success
116  */
117 static int efi_bl_bind(efi_handle_t handle, void *interface)
118 {
119         struct udevice *bdev, *parent = dm_root();
120         int ret, devnum;
121         char *name;
122         struct efi_object *obj = efi_search_obj(handle);
123         struct efi_block_io *io = interface;
124         struct efi_blk_plat *plat;
125
126         EFI_PRINT("%s: handle %p, interface %p\n", __func__, handle, io);
127
128         if (!obj)
129                 return -ENOENT;
130
131         devnum = blk_find_max_devnum(UCLASS_EFI_LOADER);
132         if (devnum == -ENODEV)
133                 devnum = 0;
134         else if (devnum < 0)
135                 return devnum;
136
137         name = calloc(1, 18); /* strlen("efiblk#2147483648") + 1 */
138         if (!name)
139                 return -ENOMEM;
140         sprintf(name, "efiblk#%d", devnum);
141
142         /* Create driver model udevice for the EFI block io device */
143         ret = blk_create_device(parent, "efi_blk", name, UCLASS_EFI_LOADER,
144                                 devnum, io->media->block_size,
145                                 (lbaint_t)io->media->last_block, &bdev);
146         if (ret)
147                 return ret;
148         if (!bdev)
149                 return -ENOENT;
150         /* Set the DM_FLAG_NAME_ALLOCED flag to avoid a memory leak */
151         device_set_name_alloced(bdev);
152
153         plat = dev_get_plat(bdev);
154         plat->handle = handle;
155         plat->io = interface;
156
157         /*
158          * FIXME: necessary because we won't do almost nothing in
159          * efi_disk_create() when called from device_probe().
160          */
161         if (efi_link_dev(handle, bdev))
162                 /* FIXME: cleanup for bdev */
163                 return ret;
164
165         ret = device_probe(bdev);
166         if (ret)
167                 return ret;
168         EFI_PRINT("%s: block device '%s' created\n", __func__, bdev->name);
169
170         return 0;
171 }
172
173 /* Block device driver operators */
174 static const struct blk_ops efi_blk_ops = {
175         .read   = efi_bl_read,
176         .write  = efi_bl_write,
177 };
178
179 /* Identify as block device driver */
180 U_BOOT_DRIVER(efi_blk) = {
181         .name                   = "efi_blk",
182         .id                     = UCLASS_BLK,
183         .ops                    = &efi_blk_ops,
184         .plat_auto      = sizeof(struct efi_blk_plat),
185 };
186
187 /* EFI driver operators */
188 static const struct efi_driver_ops driver_ops = {
189         .protocol       = &efi_block_io_guid,
190         .child_protocol = &efi_block_io_guid,
191         .bind           = efi_bl_bind,
192 };
193
194 /* Identify as EFI driver */
195 U_BOOT_DRIVER(efi_block) = {
196         .name           = "EFI block driver",
197         .id             = UCLASS_EFI_LOADER,
198         .ops            = &driver_ops,
199 };
This page took 0.039552 seconds and 4 git commands to generate.