blob: 493cbdc3694abe8b2eef242416d8ac6efea997f3 [file] [log] [blame]
Simon Glassfdacd502025-01-15 18:27:03 -07001/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Verified Boot for Embedded (VBE) common functions
4 *
5 * Copyright 2024 Google LLC
6 * Written by Simon Glass <sjg@chromium.org>
7 */
8
9#ifndef __VBE_COMMON_H
10#define __VBE_COMMON_H
11
Simon Glassc2213082025-01-26 11:43:29 -070012#include <dm/ofnode_decl.h>
13#include <linux/bitops.h>
Simon Glassfdacd502025-01-15 18:27:03 -070014#include <linux/types.h>
15
Simon Glassedd22362025-01-15 18:27:22 -070016struct spl_image_info;
Simon Glassfdacd502025-01-15 18:27:03 -070017struct udevice;
18
Simon Glassedd22362025-01-15 18:27:22 -070019/*
20 * Controls whether we use a full bootmeth driver with VBE in this phase, or
21 * just access the information directly.
22 *
23 * For now VBE-simple uses the full bootmeth, but VBE-abrec does not, to reduce
24 * code size
25 */
26#define USE_BOOTMETH CONFIG_IS_ENABLED(BOOTMETH_VBE_SIMPLE)
27
Simon Glassfdacd502025-01-15 18:27:03 -070028enum {
29 MAX_VERSION_LEN = 256,
30
31 NVD_HDR_VER_SHIFT = 0,
32 NVD_HDR_VER_MASK = 0xf,
33 NVD_HDR_SIZE_SHIFT = 4,
34 NVD_HDR_SIZE_MASK = 0xf << NVD_HDR_SIZE_SHIFT,
35
36 /* Firmware key-version is in the top 16 bits of fw_ver */
37 FWVER_KEY_SHIFT = 16,
38 FWVER_FW_MASK = 0xffff,
39
40 NVD_HDR_VER_CUR = 1, /* current version */
41};
42
43/**
Simon Glassc2213082025-01-26 11:43:29 -070044 * enum vbe_try_result - result of trying a firmware pick
45 *
46 * @VBETR_UNKNOWN: Unknown / invalid result
47 * @VBETR_TRYING: Firmware pick is being tried
48 * @VBETR_OK: Firmware pick is OK and can be used from now on
49 * @VBETR_BAD: Firmware pick is bad and should be removed
50 */
51enum vbe_try_result {
52 VBETR_UNKNOWN,
53 VBETR_TRYING,
54 VBETR_OK,
55 VBETR_BAD,
56};
57
58/**
59 * enum vbe_flags - flags controlling operation
60 *
61 * @VBEF_TRY_COUNT_MASK: mask for the 'try count' value
62 * @VBEF_TRY_B: Try the B slot
63 * @VBEF_RECOVERY: Use recovery slot
64 */
65enum vbe_flags {
66 VBEF_TRY_COUNT_MASK = 0x3,
67 VBEF_TRY_B = BIT(2),
68 VBEF_RECOVERY = BIT(3),
69
70 VBEF_RESULT_SHIFT = 4,
71 VBEF_RESULT_MASK = 3 << VBEF_RESULT_SHIFT,
72
73 VBEF_PICK_SHIFT = 6,
74 VBEF_PICK_MASK = 3 << VBEF_PICK_SHIFT,
75};
76
77/**
Simon Glassfdacd502025-01-15 18:27:03 -070078 * struct vbe_nvdata - basic storage format for non-volatile data
79 *
80 * This is used for all VBE methods
81 *
82 * @crc8: crc8 for the entire record except @crc8 field itself
83 * @hdr: header size and version (NVD_HDR_...)
84 * @spare1: unused, must be 0
85 * @fw_vernum: version and key version (FWVER_...)
86 * @flags: Flags controlling operation (enum vbe_flags)
87 */
88struct vbe_nvdata {
89 u8 crc8;
90 u8 hdr;
91 u16 spare1;
92 u32 fw_vernum;
93 u32 flags;
94 u8 spare2[0x34];
95};
96
Simon Glass15d320d2025-01-15 18:27:07 -070097/**
98 * vbe_get_blk() - Obtain the block device to use for VBE
99 *
100 * Decodes the string to produce a block device
101 *
102 * @storage: String indicating the device to use, e.g. "mmc1"
103 * @blkp: Returns associated block device, on success
104 * Return 0 if OK, -ENODEV if @storage does not end with a number, -E2BIG if
105 * the device name is more than 15 characters, -ENXIO if the block device could
106 * not be found
107 */
108int vbe_get_blk(const char *storage, struct udevice **blkp);
109
Simon Glass9846e5f2025-01-15 18:27:08 -0700110/**
111 * vbe_read_version() - Read version-string from a block device
112 *
113 * Reads the VBE version-string from a device. This function reads a single
114 * block from the device, so the string cannot be larger than that. It uses a
115 * temporary buffer for the read, then copies in up to @size bytes
116 *
117 * @blk: Device to read from
118 * @offset: Offset to read, in bytes
119 * @version: Place to put the string
120 * @max_size: Maximum size of @version
121 * Return: 0 if OK, -E2BIG if @max_size > block size, -EBADF if the offset is
122 * not block-aligned, -EIO if an I/O error occurred
123 */
124int vbe_read_version(struct udevice *blk, ulong offset, char *version,
125 int max_size);
126
Simon Glass72424b82025-01-15 18:27:09 -0700127/**
128 * vbe_read_nvdata() - Read non-volatile data from a block device
129 *
130 * Reads the VBE nvdata from a device. This function reads a single block from
131 * the device, so the nvdata cannot be larger than that.
132 *
133 * @blk: Device to read from
134 * @offset: Offset to read, in bytes
135 * @size: Number of bytes to read
136 * @buf: Buffer to hold the data
137 * Return: 0 if OK, -E2BIG if @size > block size, -EBADF if the offset is not
138 * block-aligned, -EIO if an I/O error occurred, -EPERM if the header version is
139 * incorrect, the header size is invalid or the data fails its CRC check
140 */
141int vbe_read_nvdata(struct udevice *blk, ulong offset, ulong size, u8 *buf);
142
Simon Glass988f16a2025-01-15 18:27:10 -0700143/**
144 * vbe_read_fit() - Read an image from a FIT
145 *
146 * This handles most of the VBE logic for reading from a FIT. It reads the FIT
147 * metadata, decides which image to load and loads it to a suitable address,
148 * ready for jumping to the next phase of VBE.
149 *
150 * This supports transition from VPL to SPL as well as SPL to U-Boot proper. For
151 * now, TPL->VPL is not supported.
152 *
153 * Both embedded and external data are supported for the FIT
154 *
155 * @blk: Block device containing FIT
156 * @area_offset: Byte offset of the VBE area in @blk containing the FIT
157 * @area_size: Size of the VBE area
Simon Glassedd22362025-01-15 18:27:22 -0700158 * @image: SPL image to fill in with details of the loaded image, or NULL
Simon Glass988f16a2025-01-15 18:27:10 -0700159 * @load_addrp: If non-null, returns the address where the image was loaded
160 * @lenp: If non-null, returns the size of the image loaded, in bytes
161 * @namep: If non-null, returns the name of the FIT-image node that was loaded
162 * (allocated by this function)
163 * Return: 0 if OK, -EINVAL if the area does not contain an FDT (the underlying
164 * format for FIT), -E2BIG if the FIT extends past @area_size, -ENOMEM if there
165 * was not space to allocate the image-node name, other error if a read error
166 * occurred (see blk_read()), or something went wrong with the actually
167 * FIT-parsing (see fit_image_load()).
168 */
169int vbe_read_fit(struct udevice *blk, ulong area_offset, ulong area_size,
Simon Glassedd22362025-01-15 18:27:22 -0700170 struct spl_image_info *image, ulong *load_addrp, ulong *lenp,
171 char **namep);
Simon Glass988f16a2025-01-15 18:27:10 -0700172
Simon Glassc2213082025-01-26 11:43:29 -0700173/**
174 * vbe_get_node() - Get the node containing the VBE settings
175 *
176 * Return: VBE node (typically "/bootstd/firmware0")
177 */
178ofnode vbe_get_node(void);
179
Simon Glassfdacd502025-01-15 18:27:03 -0700180#endif /* __VBE_ABREC_H */