blob: ed5a856c7abbe08949b81e0b2f634edd8b390be5 [file] [log] [blame]
Caleb Connolly6f7c8b22024-11-15 01:47:29 +01001// SPDX-License-Identifier: GPL-2.0
2
3/* Small "fetch" utility for U-Boot */
4
5#ifdef CONFIG_ARM64
6#include <asm/system.h>
7#endif
8#include <dm/device.h>
9#include <dm/uclass-internal.h>
10#include <display_options.h>
11#include <mmc.h>
12#include <time.h>
13#include <asm/global_data.h>
14#include <cli.h>
15#include <command.h>
16#include <dm/ofnode.h>
17#include <env.h>
18#include <rand.h>
19#include <vsprintf.h>
20#include <linux/delay.h>
21#include <linux/kernel.h>
22#include <version.h>
23
24DECLARE_GLOBAL_DATA_PTR;
25
26#define LINE_WIDTH 40
27#define BLUE "\033[38;5;4m"
28#define YELLOW "\033[38;5;11m"
29#define BOLD "\033[1m"
30#define RESET "\033[0m"
31static const char * const logo_lines[] = {
32 BLUE BOLD " ......::...... ",
33 BLUE BOLD " ...::::::::::::::::::... ",
34 BLUE BOLD " ..::::::::::::::::::::::::::.. ",
35 BLUE BOLD " .::::.:::::::::::::::...::::.::::. ",
36 BLUE BOLD " .::::::::::::::::::::..::::::::::::::. ",
37 BLUE BOLD " .::.:::::::::::::::::::" YELLOW "=*%#*" BLUE "::::::::::.::. ",
38 BLUE BOLD " .:::::::::::::::::....." YELLOW "*%%*-" BLUE ":....::::::::::. ",
39 BLUE BOLD " .:.:::...:::::::::.:-" YELLOW "===##*---==-" BLUE "::::::::::.:. ",
40 BLUE BOLD " .::::..::::........" YELLOW "-***#****###****-" BLUE "...::::::.:. ",
41 BLUE BOLD " ::.:.-" YELLOW "+***+=" BLUE "::-" YELLOW "=+**#%%%%%%%%%%%%###*= " BLUE "-::...::::. ",
42 BLUE BOLD ".:.::-" YELLOW "*****###%%%%%%%%%%%%%%%%%%%%%%%%%%#*=" BLUE ":..:::: ",
43 BLUE BOLD ".::" YELLOW "##" BLUE ":" YELLOW "***#%%%%%%#####%%%%%%%####%%%%%####%%%*" BLUE "-.::. ",
44 BLUE BOLD ":.:" YELLOW "#%" BLUE "::" YELLOW "*%%%%%%%#*****##%%%#*****##%%##*****#%%+" BLUE ".::.",
45 BLUE BOLD ".::" YELLOW "**==#%%%%%%%##****#%%%%##****#%%%%#****###%%" BLUE ":.. ",
46 BLUE BOLD "..:" YELLOW "#%" BLUE "::" YELLOW "*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#%%%%%+ " BLUE ".:.",
47 BLUE BOLD " ::" YELLOW "##" BLUE ":" YELLOW "+**#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%* " BLUE "-.:: ",
48 BLUE BOLD " ..::-" YELLOW "#****#%#%%%%%%%%%%%%%%%%%%%%%%%%%%#*=" BLUE "-..::. ",
49 BLUE BOLD " ...:=" YELLOW "*****=" BLUE "::-" YELLOW "=+**###%%%%%%%%###**+= " BLUE "--:...::: ",
50 BLUE BOLD " .::.::--:........::::::--::::::......::::::. ",
51 BLUE BOLD " .::.....::::::::::...........:::::::::.::. ",
52 BLUE BOLD " .::::::::::::::::::::::::::::::::::::. ",
53 BLUE BOLD " .::::.::::::::::::::::::::::.::::. ",
54 BLUE BOLD " ..::::::::::::::::::::::::::.. ",
55 BLUE BOLD " ...::::::::::::::::::... ",
56 BLUE BOLD " ......::...... ",
57};
58
59enum output_lines {
60 FIRST,
61 SECOND,
62 KERNEL,
63 SYSINFO,
64 HOST,
65 UPTIME,
66 IP,
67 CMDS,
68 CONSOLES,
69 FEATURES,
70 RELOCATION,
71 CORES,
72 MEMORY,
73 STORAGE,
74
75 /* Up to 10 storage devices... Should be enough for anyone right? */
76 _LAST_LINE = (STORAGE + 10),
77#define LAST_LINE (_LAST_LINE - 1UL)
78};
79
80/*
81 * TODO/ideas:
82 * - Refactor to not use a for loop
83 * - Handle multiple network interfaces
84 * - Include stats about number of bound/probed devices
85 * - Show U-Boot's size and malloc usage, fdt size, etc.
86 */
87
88
89static int do_ufetch(struct cmd_tbl *cmdtp, int flag, int argc,
90 char *const argv[])
91{
J. Neuschäfer3f3d89b2024-12-11 23:25:25 +010092 int num_lines = max((size_t)LAST_LINE + 1, ARRAY_SIZE(logo_lines));
Caleb Connolly6f7c8b22024-11-15 01:47:29 +010093 const char *model, *compatible;
94 char *ipaddr;
J. Neuschäfere1dac492024-12-11 23:25:26 +010095 int n_cmds, n_cpus = 0, compatlen;
Caleb Connolly6f7c8b22024-11-15 01:47:29 +010096 size_t size;
97 ofnode np;
Caleb Connolly6f7c8b22024-11-15 01:47:29 +010098 bool skip_ascii = false;
99
100 if (argc > 1 && strcmp(argv[1], "-n") == 0) {
101 skip_ascii = true;
102 num_lines = LAST_LINE;
103 }
104
105 for (int line = 0; line < num_lines; line++) {
106 if (!skip_ascii) {
107 if (line < ARRAY_SIZE(logo_lines))
108 printf("%s ", logo_lines[line]);
109 else
110 printf("%*c ", LINE_WIDTH, ' ');
111 }
112 switch (line) {
113 case FIRST:
114 compatible = ofnode_read_string(ofnode_root(), "compatible");
115 if (!compatible)
116 compatible = "unknown";
117 printf(RESET "%s\n", compatible);
118 compatlen = strlen(compatible);
119 break;
120 case SECOND:
121 for (int j = 0; j < compatlen; j++)
122 putc('-');
123 putc('\n');
124 break;
125 case KERNEL:
126 printf("Kernel:" RESET " %s\n", U_BOOT_VERSION);
127 break;
128 case SYSINFO:
129 printf("Config:" RESET " %s_defconfig\n", CONFIG_SYS_CONFIG_NAME);
130 break;
131 case HOST:
132 model = ofnode_read_string(ofnode_root(), "model");
133 if (model)
134 printf("Host:" RESET " %s\n", model);
135 break;
136 case UPTIME:
137 printf("Uptime:" RESET " %ld seconds\n", get_timer(0) / 1000);
138 break;
139 case IP:
140 ipaddr = env_get("ipaddr");
141 if (!ipaddr)
142 ipaddr = "none";
143 printf("IP Address:" RESET " %s", ipaddr);
144 ipaddr = env_get("ipv6addr");
145 if (ipaddr)
146 printf(", %s\n", ipaddr);
147 else
148 putc('\n');
149 break;
150 case CMDS:
151 n_cmds = ll_entry_count(struct cmd_tbl, cmd);
152 printf("Commands:" RESET " %d (help)\n", n_cmds);
153 break;
154 case CONSOLES:
155 printf("Consoles:" RESET " %s", env_get("stdout"));
156 if (gd->baudrate)
157 printf(" (%d baud)", gd->baudrate);
158 putc('\n');
159 break;
160 case FEATURES:
161 printf("Features:" RESET " ");
162 if (IS_ENABLED(CONFIG_NET))
163 printf("Net");
164 if (IS_ENABLED(CONFIG_EFI_LOADER))
165 printf(", EFI");
166 if (IS_ENABLED(CONFIG_CMD_CAT))
167 printf(", cat :3");
168#ifdef CONFIG_ARM64
169 switch (current_el()) {
170 case 2:
171 printf(", VMs");
172 break;
173 case 3:
174 printf(", full control!");
175 break;
176 }
177#endif
178 printf("\n");
179 break;
180 case RELOCATION:
181 if (gd->flags & GD_FLG_SKIP_RELOC)
182 printf("Relocated:" RESET " no\n");
183 else
184 printf("Relocated:" RESET " to %#011lx\n", gd->relocaddr);
185 break;
186 case CORES:
187 ofnode_for_each_subnode(np, ofnode_path("/cpus")) {
188 if (ofnode_name_eq(np, "cpu"))
189 n_cpus++;
190 }
J. Neuschäfer158afdb2024-12-11 23:25:27 +0100191 printf("CPU: " RESET CONFIG_SYS_ARCH " (%d cores, 1 in use)\n", n_cpus);
Caleb Connolly6f7c8b22024-11-15 01:47:29 +0100192 break;
193 case MEMORY:
194 for (int j = 0; j < CONFIG_NR_DRAM_BANKS && gd->bd->bi_dram[j].size; j++)
195 size += gd->bd->bi_dram[j].size;
196 printf("Memory:" RESET " ");
197 print_size(size, "\n");
198 break;
199 case STORAGE:
J. Neuschäfere1dac492024-12-11 23:25:26 +0100200 default: {
201#ifdef CONFIG_BLK
202 struct udevice *dev;
203 struct blk_desc *desc;
204 int ret;
205
Caleb Connolly6f7c8b22024-11-15 01:47:29 +0100206 ret = uclass_find_device_by_seq(UCLASS_BLK, line - STORAGE, &dev);
207 if (!ret && dev) {
208 desc = dev_get_uclass_plat(dev);
209 size = desc->lba * desc->blksz;
210 printf("%4s %d: " RESET, blk_get_uclass_name(desc->uclass_id),
211 desc->lun);
212 if (size)
213 print_size(size, "");
214 else
215 printf("No media");
216 } else if (ret == -ENODEV && (skip_ascii || line > ARRAY_SIZE(logo_lines))) {
217 break;
218 }
J. Neuschäfere1dac492024-12-11 23:25:26 +0100219#endif
Caleb Connolly6f7c8b22024-11-15 01:47:29 +0100220 printf("\n");
221 }
J. Neuschäfere1dac492024-12-11 23:25:26 +0100222 }
Caleb Connolly6f7c8b22024-11-15 01:47:29 +0100223 }
224
225 printf(RESET "\n\n");
226
227 return 0;
228}
229
230U_BOOT_CMD(ufetch, 2, 1, do_ufetch,
231 "U-Boot fetch utility",
232 "Print information about your device.\n"
233 " -n Don't print the ASCII logo"
234);