1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2012, Google Inc. All rights reserved.
4  */
5 
6 #include <bootstage.h>
7 #include <command.h>
8 #include <vsprintf.h>
9 #include <linux/string.h>
10 
do_bootstage_report(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])11 static int do_bootstage_report(struct cmd_tbl *cmdtp, int flag, int argc,
12 			       char *const argv[])
13 {
14 	bootstage_report();
15 
16 	return 0;
17 }
18 
19 #if IS_ENABLED(CONFIG_BOOTSTAGE_STASH)
get_base_size(int argc,char * const argv[],ulong * basep,ulong * sizep)20 static int get_base_size(int argc, char *const argv[], ulong *basep,
21 			 ulong *sizep)
22 {
23 	char *endp;
24 
25 	*basep = CONFIG_BOOTSTAGE_STASH_ADDR;
26 	*sizep = CONFIG_BOOTSTAGE_STASH_SIZE;
27 	if (argc < 2)
28 		return 0;
29 	*basep = hextoul(argv[1], &endp);
30 	if (*argv[1] == 0 || *endp != 0)
31 		return -1;
32 	if (argc == 2)
33 		return 0;
34 	*sizep = hextoul(argv[2], &endp);
35 	if (*argv[2] == 0 || *endp != 0)
36 		return -1;
37 
38 	return 0;
39 }
40 
do_bootstage_stash(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])41 static int do_bootstage_stash(struct cmd_tbl *cmdtp, int flag, int argc,
42 			      char *const argv[])
43 {
44 	ulong base, size;
45 	int ret;
46 
47 	if (get_base_size(argc, argv, &base, &size))
48 		return CMD_RET_USAGE;
49 	if (base == -1UL) {
50 		printf("No bootstage stash area defined\n");
51 		return 1;
52 	}
53 
54 	if (0 == strcmp(argv[0], "stash"))
55 		ret = bootstage_stash((void *)base, size);
56 	else
57 		ret = bootstage_unstash((void *)base, size);
58 	if (ret)
59 		return 1;
60 
61 	return 0;
62 }
63 #endif
64 
65 static struct cmd_tbl cmd_bootstage_sub[] = {
66 	U_BOOT_CMD_MKENT(report, 2, 1, do_bootstage_report, "", ""),
67 #if IS_ENABLED(CONFIG_BOOTSTAGE_STASH)
68 	U_BOOT_CMD_MKENT(stash, 4, 0, do_bootstage_stash, "", ""),
69 	U_BOOT_CMD_MKENT(unstash, 4, 0, do_bootstage_stash, "", ""),
70 #endif
71 };
72 
73 /*
74  * Process a bootstage sub-command
75  */
do_boostage(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])76 static int do_boostage(struct cmd_tbl *cmdtp, int flag, int argc,
77 		       char *const argv[])
78 {
79 	struct cmd_tbl *c;
80 
81 	/* Strip off leading 'bootstage' command argument */
82 	argc--;
83 	argv++;
84 
85 	c = find_cmd_tbl(argv[0], cmd_bootstage_sub,
86 			 ARRAY_SIZE(cmd_bootstage_sub));
87 
88 	if (c)
89 		return c->cmd(cmdtp, flag, argc, argv);
90 	else
91 		return CMD_RET_USAGE;
92 }
93 
94 U_BOOT_CMD(bootstage, 4, 1, do_boostage,
95 	"Boot stage command",
96 	" - check boot progress and timing\n"
97 	"report                      - Print a report\n"
98 #if IS_ENABLED(CONFIG_BOOTSTAGE_STASH)
99 	"stash [<start> [<size>]]    - Stash data into memory\n"
100 	"unstash [<start> [<size>]]  - Unstash data from memory\n"
101 #endif
102 );
103