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