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 
do_vbe_list(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])17 static 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 
do_vbe_select(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])25 static 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 
do_vbe_info(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])47 static 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 
do_vbe_state(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])79 static 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 
107 #ifdef CONFIG_SYS_LONGHELP
108 static char vbe_help_text[] =
109 	"list   - list VBE bootmeths\n"
110 	"vbe select - select a VBE bootmeth by sequence or name\n"
111 	"vbe info   - show information about a VBE bootmeth\n"
112 	"vbe state  - show VBE state";
113 #endif
114 
115 U_BOOT_CMD_WITH_SUBCMDS(vbe, "Verified Boot for Embedded", vbe_help_text,
116 	U_BOOT_SUBCMD_MKENT(list, 1, 1, do_vbe_list),
117 	U_BOOT_SUBCMD_MKENT(select, 2, 1, do_vbe_select),
118 	U_BOOT_SUBCMD_MKENT(state, 2, 1, do_vbe_state),
119 	U_BOOT_SUBCMD_MKENT(info, 2, 1, do_vbe_info));
120