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