1 // SPDX-License-Identifier: GPL-2.0+
3 * Verified Boot for Embedded (VBE) 'simple' method
5 * Copyright 2022 Google LLC
6 * Written by Simon Glass <sjg@chromium.org>
9 #define LOG_CATEGORY LOGC_BOOT
19 #include <dm/device-internal.h>
20 #include <dm/ofnode.h>
21 #include "vbe_simple.h"
23 static int simple_read_nvdata(const struct simple_priv
*priv
,
24 struct udevice
*blk
, struct simple_state
*state
)
26 ALLOC_CACHE_ALIGN_BUFFER(u8
, buf
, MMC_MAX_BLOCK_LEN
);
27 const struct vbe_nvdata
*nvd
;
30 ret
= vbe_read_nvdata(blk
, priv
->area_start
+ priv
->state_offset
,
31 priv
->state_size
, buf
);
33 return log_msg_ret("nv", ret
);
35 nvd
= (struct vbe_nvdata
*)buf
;
36 state
->fw_vernum
= nvd
->fw_vernum
;
38 log_debug("version=%s\n", state
->fw_version
);
43 int vbe_simple_read_state(struct udevice
*dev
, struct simple_state
*state
)
45 struct simple_priv
*priv
= dev_get_priv(dev
);
49 ret
= vbe_get_blk(priv
->storage
, &blk
);
51 return log_msg_ret("blk", ret
);
53 ret
= vbe_read_version(blk
, priv
->area_start
+ priv
->version_offset
,
54 state
->fw_version
, MAX_VERSION_LEN
);
56 return log_msg_ret("ver", ret
);
58 ret
= simple_read_nvdata(priv
, blk
, state
);
60 return log_msg_ret("nvd", ret
);
65 static int vbe_simple_get_state_desc(struct udevice
*dev
, char *buf
,
68 struct simple_state state
;
71 ret
= vbe_simple_read_state(dev
, &state
);
73 return log_msg_ret("read", ret
);
77 snprintf(buf
, maxsize
, "Version: %s\nVernum: %x/%x", state
.fw_version
,
78 state
.fw_vernum
>> FWVER_KEY_SHIFT
,
79 state
.fw_vernum
& FWVER_FW_MASK
);
84 static int vbe_simple_read_bootflow(struct udevice
*dev
, struct bootflow
*bflow
)
88 if (CONFIG_IS_ENABLED(BOOTMETH_VBE_SIMPLE_FW
)) {
89 if (vbe_phase() == VBE_PHASE_FIRMWARE
) {
90 ret
= vbe_simple_read_bootflow_fw(dev
, bflow
);
92 return log_msg_ret("fw", ret
);
100 static int vbe_simple_read_file(struct udevice
*dev
, struct bootflow
*bflow
,
101 const char *file_path
, ulong addr
,
102 enum bootflow_img_t type
, ulong
*sizep
)
106 if (vbe_phase() == VBE_PHASE_OS
) {
107 ret
= bootmeth_common_read_file(dev
, bflow
, file_path
, addr
,
110 return log_msg_ret("os", ret
);
113 /* To be implemented */
117 static struct bootmeth_ops bootmeth_vbe_simple_ops
= {
118 .get_state_desc
= vbe_simple_get_state_desc
,
119 .read_bootflow
= vbe_simple_read_bootflow
,
120 .read_file
= vbe_simple_read_file
,
123 static int bootmeth_vbe_simple_probe(struct udevice
*dev
)
125 struct simple_priv
*priv
= dev_get_priv(dev
);
127 memset(priv
, '\0', sizeof(*priv
));
128 if (dev_read_u32(dev
, "area-start", &priv
->area_start
) ||
129 dev_read_u32(dev
, "area-size", &priv
->area_size
) ||
130 dev_read_u32(dev
, "version-offset", &priv
->version_offset
) ||
131 dev_read_u32(dev
, "version-size", &priv
->version_size
) ||
132 dev_read_u32(dev
, "state-offset", &priv
->state_offset
) ||
133 dev_read_u32(dev
, "state-size", &priv
->state_size
))
134 return log_msg_ret("read", -EINVAL
);
135 dev_read_u32(dev
, "skip-offset", &priv
->skip_offset
);
136 priv
->storage
= strdup(dev_read_string(dev
, "storage"));
138 return log_msg_ret("str", -EINVAL
);
143 static int bootmeth_vbe_simple_bind(struct udevice
*dev
)
145 struct bootmeth_uc_plat
*plat
= dev_get_uclass_plat(dev
);
147 plat
->desc
= IS_ENABLED(CONFIG_BOOTSTD_FULL
) ?
148 "VBE simple" : "vbe-simple";
149 plat
->flags
= BOOTMETHF_GLOBAL
;
154 #if CONFIG_IS_ENABLED(OF_REAL)
155 static const struct udevice_id generic_simple_vbe_simple_ids
[] = {
156 { .compatible
= "fwupd,vbe-simple" },
161 U_BOOT_DRIVER(vbe_simple
) = {
162 .name
= "vbe_simple",
163 .id
= UCLASS_BOOTMETH
,
164 .of_match
= of_match_ptr(generic_simple_vbe_simple_ids
),
165 .ops
= &bootmeth_vbe_simple_ops
,
166 .bind
= bootmeth_vbe_simple_bind
,
167 .probe
= bootmeth_vbe_simple_probe
,
168 .flags
= DM_FLAG_PRE_RELOC
,
169 .priv_auto
= sizeof(struct simple_priv
),