1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Block driver for EFI devices
4 * This supports a media driver of UCLASS_EFI with a child UCLASS_BLK
5 * It allows block-level access to EFI devices made available via EFI boot
6 * services
7 *
8 * Copyright 2021 Google LLC
9 */
10
11 #include <common.h>
12 #include <blk.h>
13 #include <dm.h>
14 #include <efi.h>
15 #include <efi_api.h>
16
17 struct efi_block_plat {
18 struct efi_block_io *blkio;
19 };
20
21 /**
22 * Read from block device
23 *
24 * @dev: device
25 * @blknr: first block to be read
26 * @blkcnt: number of blocks to read
27 * @buffer: output buffer
28 * Return: number of blocks transferred
29 */
efi_bl_read(struct udevice * dev,lbaint_t blknr,lbaint_t blkcnt,void * buffer)30 static ulong efi_bl_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
31 void *buffer)
32 {
33 struct efi_block_plat *plat = dev_get_plat(dev);
34 struct efi_block_io *io = plat->blkio;
35 efi_status_t ret;
36
37 log_debug("read buf=%p, block=%lx, count=%lx: ", buffer, (ulong)blknr,
38 (ulong)blkcnt);
39 ret = io->read_blocks(io, io->media->media_id, blknr,
40 blkcnt * io->media->block_size, buffer);
41 log_debug("ret=%lx (dec %ld)\n", ret & ~EFI_ERROR_MASK,
42 ret & ~EFI_ERROR_MASK);
43 if (ret)
44 return 0;
45
46 return blkcnt;
47 }
48
49 /**
50 * Write to block device
51 *
52 * @dev: device
53 * @blknr: first block to be write
54 * @blkcnt: number of blocks to write
55 * @buffer: input buffer
56 * Return: number of blocks transferred
57 */
efi_bl_write(struct udevice * dev,lbaint_t blknr,lbaint_t blkcnt,const void * buffer)58 static ulong efi_bl_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
59 const void *buffer)
60 {
61 struct efi_block_plat *plat = dev_get_plat(dev);
62 struct efi_block_io *io = plat->blkio;
63 efi_status_t ret;
64
65 log_debug("write buf=%p, block=%lx, count=%lx: ", buffer, (ulong)blknr,
66 (ulong)blkcnt);
67 ret = io->write_blocks(io, io->media->media_id, blknr,
68 blkcnt * io->media->block_size, (void *)buffer);
69 log_debug("ret=%lx (dec %ld)\n", ret & ~EFI_ERROR_MASK,
70 ret & ~EFI_ERROR_MASK);
71 if (ret)
72 return 0;
73
74 return blkcnt;
75 }
76
77 /* Block device driver operators */
78 static const struct blk_ops efi_blk_ops = {
79 .read = efi_bl_read,
80 .write = efi_bl_write,
81 };
82
83 U_BOOT_DRIVER(efi_block) = {
84 .name = "efi_block",
85 .id = UCLASS_BLK,
86 .ops = &efi_blk_ops,
87 .plat_auto = sizeof(struct efi_block_plat),
88 };
89
efi_media_bind(struct udevice * dev)90 static int efi_media_bind(struct udevice *dev)
91 {
92 struct efi_media_plat *plat = dev_get_plat(dev);
93 struct efi_block_plat *blk_plat;
94 struct udevice *blk;
95 int ret;
96
97 ret = blk_create_devicef(dev, "efi_block", "blk", UCLASS_EFI_MEDIA,
98 dev_seq(dev), plat->blkio->media->block_size,
99 plat->blkio->media->last_block, &blk);
100 if (ret) {
101 debug("Cannot create block device\n");
102 return ret;
103 }
104 blk_plat = dev_get_plat(blk);
105 blk_plat->blkio = plat->blkio;
106
107 return 0;
108 }
109
110 U_BOOT_DRIVER(efi_media) = {
111 .name = "efi_media",
112 .id = UCLASS_EFI_MEDIA,
113 .bind = efi_media_bind,
114 .plat_auto = sizeof(struct efi_media_plat),
115 };
116