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