Line | Count | Source |
1 | | // 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 | | |
24 | | DECLARE_GLOBAL_DATA_PTR; |
25 | | |
26 | 0 | #define LINE_WIDTH 40 |
27 | | #define BLUE "\033[34m" |
28 | | #define YELLOW "\033[33m" |
29 | | #define BOLD "\033[1m" |
30 | 0 | #define RESET "\033[0m" |
31 | | static 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 | | |
59 | | enum 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 | 0 | #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 | | |
89 | | static int do_ufetch(struct cmd_tbl *cmdtp, int flag, int argc, |
90 | | char *const argv[]) |
91 | 0 | { |
92 | 0 | int num_lines = max((size_t)LAST_LINE + 1, ARRAY_SIZE(logo_lines)); |
93 | 0 | const char *model, *compatible; |
94 | 0 | char *ipaddr; |
95 | 0 | int n_cmds, n_cpus = 0, compatlen; |
96 | 0 | size_t size = 0; |
97 | 0 | ofnode np; |
98 | 0 | bool skip_ascii = false; |
99 | |
|
100 | 0 | if (argc > 1 && strcmp(argv[1], "-n") == 0) { |
101 | 0 | skip_ascii = true; |
102 | 0 | num_lines = LAST_LINE; |
103 | 0 | } |
104 | |
|
105 | 0 | for (int line = 0; line < num_lines; line++) { |
106 | 0 | if (!skip_ascii) { |
107 | 0 | if (line < ARRAY_SIZE(logo_lines)) |
108 | 0 | printf("%s ", logo_lines[line]); |
109 | 0 | else |
110 | 0 | printf("%*c ", LINE_WIDTH, ' '); |
111 | 0 | } |
112 | 0 | switch (line) { |
113 | 0 | case FIRST: |
114 | 0 | compatible = ofnode_read_string(ofnode_root(), "compatible"); |
115 | 0 | if (!compatible) |
116 | 0 | compatible = "unknown"; |
117 | 0 | printf(RESET "%s\n", compatible); |
118 | 0 | compatlen = strlen(compatible); |
119 | 0 | break; |
120 | 0 | case SECOND: |
121 | 0 | for (int j = 0; j < compatlen; j++) |
122 | 0 | putc('-'); |
123 | 0 | putc('\n'); |
124 | 0 | break; |
125 | 0 | case KERNEL: |
126 | 0 | printf("Kernel:" RESET " %s\n", U_BOOT_VERSION); |
127 | 0 | break; |
128 | 0 | case SYSINFO: |
129 | 0 | printf("Config:" RESET " %s_defconfig\n", CONFIG_SYS_CONFIG_NAME); |
130 | 0 | break; |
131 | 0 | case HOST: |
132 | 0 | model = ofnode_read_string(ofnode_root(), "model"); |
133 | 0 | if (model) |
134 | 0 | printf("Host:" RESET " %s\n", model); |
135 | 0 | break; |
136 | 0 | case UPTIME: |
137 | 0 | printf("Uptime:" RESET " %ld seconds\n", get_timer(0) / 1000); |
138 | 0 | break; |
139 | 0 | case IP: |
140 | 0 | ipaddr = env_get("ipaddr"); |
141 | 0 | if (!ipaddr) |
142 | 0 | ipaddr = "none"; |
143 | 0 | printf("IP Address:" RESET " %s", ipaddr); |
144 | 0 | ipaddr = env_get("ipv6addr"); |
145 | 0 | if (ipaddr) |
146 | 0 | printf(", %s\n", ipaddr); |
147 | 0 | else |
148 | 0 | putc('\n'); |
149 | 0 | break; |
150 | 0 | case CMDS: |
151 | 0 | n_cmds = ll_entry_count(struct cmd_tbl, cmd); |
152 | 0 | printf("Commands:" RESET " %d (help)\n", n_cmds); |
153 | 0 | break; |
154 | 0 | case CONSOLES: |
155 | 0 | printf("Consoles:" RESET " %s", env_get("stdout")); |
156 | 0 | if (gd->baudrate) |
157 | 0 | printf(" (%d baud)", gd->baudrate); |
158 | 0 | putc('\n'); |
159 | 0 | break; |
160 | 0 | case FEATURES: |
161 | 0 | printf("Features:" RESET " "); |
162 | 0 | if (IS_ENABLED(CONFIG_NET)) |
163 | 0 | printf("Net"); |
164 | 0 | if (IS_ENABLED(CONFIG_EFI_LOADER)) |
165 | 0 | printf(", EFI"); |
166 | 0 | if (IS_ENABLED(CONFIG_CMD_CAT)) |
167 | 0 | 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 | 0 | printf("\n"); |
179 | 0 | break; |
180 | 0 | case RELOCATION: |
181 | 0 | if (gd->flags & GD_FLG_SKIP_RELOC) |
182 | 0 | printf("Relocated:" RESET " no\n"); |
183 | 0 | else |
184 | 0 | printf("Relocated:" RESET " to %#011lx\n", gd->relocaddr); |
185 | 0 | break; |
186 | 0 | case CORES: |
187 | 0 | ofnode_for_each_subnode(np, ofnode_path("/cpus")) { |
188 | 0 | if (ofnode_name_eq(np, "cpu")) |
189 | 0 | n_cpus++; |
190 | 0 | } |
191 | 0 | printf("CPU: " RESET CONFIG_SYS_ARCH " (%d cores, 1 in use)\n", n_cpus); |
192 | 0 | break; |
193 | 0 | case MEMORY: |
194 | 0 | for (int j = 0; j < CONFIG_NR_DRAM_BANKS && gd->bd->bi_dram[j].size; j++) |
195 | 0 | size += gd->bd->bi_dram[j].size; |
196 | 0 | printf("Memory:" RESET " "); |
197 | 0 | print_size(size, "\n"); |
198 | 0 | break; |
199 | 0 | case STORAGE: |
200 | 0 | default: { |
201 | 0 | #ifdef CONFIG_BLK |
202 | 0 | struct udevice *dev; |
203 | 0 | struct blk_desc *desc; |
204 | 0 | int ret; |
205 | |
|
206 | 0 | ret = uclass_find_device_by_seq(UCLASS_BLK, line - STORAGE, &dev); |
207 | 0 | if (!ret && dev) { |
208 | 0 | desc = dev_get_uclass_plat(dev); |
209 | 0 | size = desc->lba * desc->blksz; |
210 | 0 | printf("%4s %d: " RESET, blk_get_uclass_name(desc->uclass_id), |
211 | 0 | desc->lun); |
212 | 0 | if (size) |
213 | 0 | print_size(size, ""); |
214 | 0 | else |
215 | 0 | printf("No media"); |
216 | 0 | } else if (ret == -ENODEV && (skip_ascii || line > ARRAY_SIZE(logo_lines))) { |
217 | 0 | break; |
218 | 0 | } |
219 | 0 | #endif |
220 | 0 | printf("\n"); |
221 | 0 | } |
222 | 0 | } |
223 | 0 | } |
224 | | |
225 | 0 | printf(RESET "\n\n"); |
226 | |
|
227 | 0 | return 0; |
228 | 0 | } |
229 | | |
230 | | U_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 | | ); |