1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Verified Boot for Embedded (VBE) command
4 *
5 * Copyright 2022 Google LLC
6 * Written by Simon Glass <sjg@chromium.org>
7 */
8
9#include <common.h>
10#include <bloblist.h>
11#include <bootmeth.h>
12#include <bootstd.h>
13#include <command.h>
14#include <spl.h>
15#include <vbe.h>
16
17static int do_vbe_list(struct cmd_tbl *cmdtp, int flag, int argc,
18		       char *const argv[])
19{
20	vbe_list();
21
22	return 0;
23}
24
25static int do_vbe_select(struct cmd_tbl *cmdtp, int flag, int argc,
26			 char *const argv[])
27{
28	struct bootstd_priv *std;
29	struct udevice *dev;
30	int ret;
31
32	ret = bootstd_get_priv(&std);
33	if (ret)
34		return CMD_RET_FAILURE;
35	if (argc < 2) {
36		std->vbe_bootmeth = NULL;
37		return 0;
38	}
39	if (vbe_find_by_any(argv[1], &dev))
40		return CMD_RET_FAILURE;
41
42	std->vbe_bootmeth = dev;
43
44	return 0;
45}
46
47static int do_vbe_info(struct cmd_tbl *cmdtp, int flag, int argc,
48		       char *const argv[])
49{
50	struct bootstd_priv *std;
51	char buf[256];
52	int ret, len;
53
54	ret = bootstd_get_priv(&std);
55	if (ret)
56		return CMD_RET_FAILURE;
57	if (!std->vbe_bootmeth) {
58		printf("No VBE bootmeth selected\n");
59		return CMD_RET_FAILURE;
60	}
61	ret = bootmeth_get_state_desc(std->vbe_bootmeth, buf, sizeof(buf));
62	if (ret) {
63		printf("Failed (err=%d)\n", ret);
64		return CMD_RET_FAILURE;
65	}
66	len = strnlen(buf, sizeof(buf));
67	if (len >= sizeof(buf)) {
68		printf("Buffer overflow\n");
69		return CMD_RET_FAILURE;
70	}
71
72	puts(buf);
73	if (buf[len] != '\n')
74		putc('\n');
75
76	return 0;
77}
78
79static int do_vbe_state(struct cmd_tbl *cmdtp, int flag, int argc,
80			char *const argv[])
81{
82	struct vbe_handoff *handoff = NULL;
83	int i;
84
85	if (IS_ENABLED(CONFIG_BLOBLIST)) {
86		handoff = bloblist_find(BLOBLISTT_VBE,
87					sizeof(struct vbe_handoff));
88	}
89	if (!handoff) {
90		printf("No VBE state\n");
91		return CMD_RET_FAILURE;
92	}
93
94	printf("Phases:");
95	for (i = PHASE_NONE; i < PHASE_COUNT; i++) {
96		if (handoff->phases & (1 << i))
97			printf(" %s", spl_phase_name(i));
98
99	}
100	if (!handoff->phases)
101		printf(" (none)");
102	printf("\n");
103
104	return 0;
105}
106
107U_BOOT_LONGHELP(vbe,
108	"list   - list VBE bootmeths\n"
109	"vbe select - select a VBE bootmeth by sequence or name\n"
110	"vbe info   - show information about a VBE bootmeth\n"
111	"vbe state  - show VBE state");
112
113U_BOOT_CMD_WITH_SUBCMDS(vbe, "Verified Boot for Embedded", vbe_help_text,
114	U_BOOT_SUBCMD_MKENT(list, 1, 1, do_vbe_list),
115	U_BOOT_SUBCMD_MKENT(select, 2, 1, do_vbe_select),
116	U_BOOT_SUBCMD_MKENT(state, 2, 1, do_vbe_state),
117	U_BOOT_SUBCMD_MKENT(info, 2, 1, do_vbe_info));
118