blob: 9d25ecbf37ff6ed87138d593821f5b45ebca11bc [file] [log] [blame]
Simon Glassd8063dc2021-12-04 08:56:32 -07001// 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
17struct 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 */
30static 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 */
58static 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 */
78static const struct blk_ops efi_blk_ops = {
79 .read = efi_bl_read,
80 .write = efi_bl_write,
81};
82
83U_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
90static 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", IF_TYPE_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
110U_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};