cmd: add a fetch utility

Add a small utility for displaying some information about U-Boot and the
hardware it's running on in a similar fashion to the popular neofetch
tool for Linux [1].

While the output is meant to be useful, it should also be pleasing to
look at and perhaps entertaining. The ufetch command aims to bring this
to U-Boot, featuring a colorful ASCII art version of the U-Boot logo.

[1]: https://en.wikipedia.org/wiki/Neofetch

Reviewed-by: Simon Glass <sjg@chromium.org>
Acked-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Tested-by: Mattijs Korpershoek <mkorpershoek@baylibre.com> # vim3
Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8560-QRD
Acked-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Tested-by: Tony Dinh <mibodhi@gmail.com>
Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
This commit is contained in:
Caleb Connolly 2024-11-15 01:47:29 +01:00 committed by Tom Rini
parent 230284b3e8
commit 86d462c05d
5 changed files with 243 additions and 0 deletions

View file

@ -1736,6 +1736,11 @@ S: Maintained
T: git https://source.denx.de/u-boot/custodians/u-boot-ubi.git T: git https://source.denx.de/u-boot/custodians/u-boot-ubi.git
F: drivers/mtd/ubi/ F: drivers/mtd/ubi/
UFETCH
M: Caleb Connolly <caleb.connolly@linaro.org>
S: Maintained
F: cmd/ufetch.c
UFS UFS
M: Neil Armstrong <neil.armstrong@linaro.org> M: Neil Armstrong <neil.armstrong@linaro.org>
M: Bhupesh Sharma <bhupesh.linux@gmail.com> M: Bhupesh Sharma <bhupesh.linux@gmail.com>

View file

@ -176,6 +176,13 @@ config CMD_CPU
internal name) and clock frequency. Other information may be internal name) and clock frequency. Other information may be
available depending on the CPU driver. available depending on the CPU driver.
config CMD_UFETCH
bool "U-Boot fetch"
depends on BLK
help
Fetch utility for U-Boot (akin to neofetch). Prints information
about U-Boot and the board it is running on in a pleasing format.
config CMD_FWU_METADATA config CMD_FWU_METADATA
bool "fwu metadata read" bool "fwu metadata read"
depends on FWU_MULTI_BANK_UPDATE depends on FWU_MULTI_BANK_UPDATE

View file

@ -53,6 +53,7 @@ obj-$(CONFIG_CMD_CPU) += cpu.o
obj-$(CONFIG_CMD_DATE) += date.o obj-$(CONFIG_CMD_DATE) += date.o
obj-$(CONFIG_CMD_DEMO) += demo.o obj-$(CONFIG_CMD_DEMO) += demo.o
obj-$(CONFIG_CMD_DM) += dm.o obj-$(CONFIG_CMD_DM) += dm.o
obj-$(CONFIG_CMD_UFETCH) += ufetch.o
obj-$(CONFIG_CMD_SOUND) += sound.o obj-$(CONFIG_CMD_SOUND) += sound.o
ifdef CONFIG_POST ifdef CONFIG_POST
obj-$(CONFIG_CMD_DIAG) += diag.o obj-$(CONFIG_CMD_DIAG) += diag.o

229
cmd/ufetch.c Normal file
View file

@ -0,0 +1,229 @@
// SPDX-License-Identifier: GPL-2.0
/* Small "fetch" utility for U-Boot */
#ifdef CONFIG_ARM64
#include <asm/system.h>
#endif
#include <dm/device.h>
#include <dm/uclass-internal.h>
#include <display_options.h>
#include <mmc.h>
#include <time.h>
#include <asm/global_data.h>
#include <cli.h>
#include <command.h>
#include <dm/ofnode.h>
#include <env.h>
#include <rand.h>
#include <vsprintf.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <version.h>
DECLARE_GLOBAL_DATA_PTR;
#define LINE_WIDTH 40
#define BLUE "\033[38;5;4m"
#define YELLOW "\033[38;5;11m"
#define BOLD "\033[1m"
#define RESET "\033[0m"
static const char * const logo_lines[] = {
BLUE BOLD " ......::...... ",
BLUE BOLD " ...::::::::::::::::::... ",
BLUE BOLD " ..::::::::::::::::::::::::::.. ",
BLUE BOLD " .::::.:::::::::::::::...::::.::::. ",
BLUE BOLD " .::::::::::::::::::::..::::::::::::::. ",
BLUE BOLD " .::.:::::::::::::::::::" YELLOW "=*%#*" BLUE "::::::::::.::. ",
BLUE BOLD " .:::::::::::::::::....." YELLOW "*%%*-" BLUE ":....::::::::::. ",
BLUE BOLD " .:.:::...:::::::::.:-" YELLOW "===##*---==-" BLUE "::::::::::.:. ",
BLUE BOLD " .::::..::::........" YELLOW "-***#****###****-" BLUE "...::::::.:. ",
BLUE BOLD " ::.:.-" YELLOW "+***+=" BLUE "::-" YELLOW "=+**#%%%%%%%%%%%%###*= " BLUE "-::...::::. ",
BLUE BOLD ".:.::-" YELLOW "*****###%%%%%%%%%%%%%%%%%%%%%%%%%%#*=" BLUE ":..:::: ",
BLUE BOLD ".::" YELLOW "##" BLUE ":" YELLOW "***#%%%%%%#####%%%%%%%####%%%%%####%%%*" BLUE "-.::. ",
BLUE BOLD ":.:" YELLOW "#%" BLUE "::" YELLOW "*%%%%%%%#*****##%%%#*****##%%##*****#%%+" BLUE ".::.",
BLUE BOLD ".::" YELLOW "**==#%%%%%%%##****#%%%%##****#%%%%#****###%%" BLUE ":.. ",
BLUE BOLD "..:" YELLOW "#%" BLUE "::" YELLOW "*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#%%%%%+ " BLUE ".:.",
BLUE BOLD " ::" YELLOW "##" BLUE ":" YELLOW "+**#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%* " BLUE "-.:: ",
BLUE BOLD " ..::-" YELLOW "#****#%#%%%%%%%%%%%%%%%%%%%%%%%%%%#*=" BLUE "-..::. ",
BLUE BOLD " ...:=" YELLOW "*****=" BLUE "::-" YELLOW "=+**###%%%%%%%%###**+= " BLUE "--:...::: ",
BLUE BOLD " .::.::--:........::::::--::::::......::::::. ",
BLUE BOLD " .::.....::::::::::...........:::::::::.::. ",
BLUE BOLD " .::::::::::::::::::::::::::::::::::::. ",
BLUE BOLD " .::::.::::::::::::::::::::::.::::. ",
BLUE BOLD " ..::::::::::::::::::::::::::.. ",
BLUE BOLD " ...::::::::::::::::::... ",
BLUE BOLD " ......::...... ",
};
enum output_lines {
FIRST,
SECOND,
KERNEL,
SYSINFO,
HOST,
UPTIME,
IP,
CMDS,
CONSOLES,
FEATURES,
RELOCATION,
CORES,
MEMORY,
STORAGE,
/* Up to 10 storage devices... Should be enough for anyone right? */
_LAST_LINE = (STORAGE + 10),
#define LAST_LINE (_LAST_LINE - 1UL)
};
/*
* TODO/ideas:
* - Refactor to not use a for loop
* - Handle multiple network interfaces
* - Include stats about number of bound/probed devices
* - Show U-Boot's size and malloc usage, fdt size, etc.
*/
static int do_ufetch(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
int num_lines = max(LAST_LINE + 1, ARRAY_SIZE(logo_lines));
const char *model, *compatible;
char *ipaddr;
int n_cmds, n_cpus = 0, ret, compatlen;
size_t size;
ofnode np;
struct udevice *dev;
struct blk_desc *desc;
bool skip_ascii = false;
if (argc > 1 && strcmp(argv[1], "-n") == 0) {
skip_ascii = true;
num_lines = LAST_LINE;
}
for (int line = 0; line < num_lines; line++) {
if (!skip_ascii) {
if (line < ARRAY_SIZE(logo_lines))
printf("%s ", logo_lines[line]);
else
printf("%*c ", LINE_WIDTH, ' ');
}
switch (line) {
case FIRST:
compatible = ofnode_read_string(ofnode_root(), "compatible");
if (!compatible)
compatible = "unknown";
printf(RESET "%s\n", compatible);
compatlen = strlen(compatible);
break;
case SECOND:
for (int j = 0; j < compatlen; j++)
putc('-');
putc('\n');
break;
case KERNEL:
printf("Kernel:" RESET " %s\n", U_BOOT_VERSION);
break;
case SYSINFO:
printf("Config:" RESET " %s_defconfig\n", CONFIG_SYS_CONFIG_NAME);
break;
case HOST:
model = ofnode_read_string(ofnode_root(), "model");
if (model)
printf("Host:" RESET " %s\n", model);
break;
case UPTIME:
printf("Uptime:" RESET " %ld seconds\n", get_timer(0) / 1000);
break;
case IP:
ipaddr = env_get("ipaddr");
if (!ipaddr)
ipaddr = "none";
printf("IP Address:" RESET " %s", ipaddr);
ipaddr = env_get("ipv6addr");
if (ipaddr)
printf(", %s\n", ipaddr);
else
putc('\n');
break;
case CMDS:
n_cmds = ll_entry_count(struct cmd_tbl, cmd);
printf("Commands:" RESET " %d (help)\n", n_cmds);
break;
case CONSOLES:
printf("Consoles:" RESET " %s", env_get("stdout"));
if (gd->baudrate)
printf(" (%d baud)", gd->baudrate);
putc('\n');
break;
case FEATURES:
printf("Features:" RESET " ");
if (IS_ENABLED(CONFIG_NET))
printf("Net");
if (IS_ENABLED(CONFIG_EFI_LOADER))
printf(", EFI");
if (IS_ENABLED(CONFIG_CMD_CAT))
printf(", cat :3");
#ifdef CONFIG_ARM64
switch (current_el()) {
case 2:
printf(", VMs");
break;
case 3:
printf(", full control!");
break;
}
#endif
printf("\n");
break;
case RELOCATION:
if (gd->flags & GD_FLG_SKIP_RELOC)
printf("Relocated:" RESET " no\n");
else
printf("Relocated:" RESET " to %#011lx\n", gd->relocaddr);
break;
case CORES:
ofnode_for_each_subnode(np, ofnode_path("/cpus")) {
if (ofnode_name_eq(np, "cpu"))
n_cpus++;
}
printf("CPU:" RESET " %d (1 in use)\n", n_cpus);
break;
case MEMORY:
for (int j = 0; j < CONFIG_NR_DRAM_BANKS && gd->bd->bi_dram[j].size; j++)
size += gd->bd->bi_dram[j].size;
printf("Memory:" RESET " ");
print_size(size, "\n");
break;
case STORAGE:
default:
ret = uclass_find_device_by_seq(UCLASS_BLK, line - STORAGE, &dev);
if (!ret && dev) {
desc = dev_get_uclass_plat(dev);
size = desc->lba * desc->blksz;
printf("%4s %d: " RESET, blk_get_uclass_name(desc->uclass_id),
desc->lun);
if (size)
print_size(size, "");
else
printf("No media");
} else if (ret == -ENODEV && (skip_ascii || line > ARRAY_SIZE(logo_lines))) {
break;
}
printf("\n");
}
}
printf(RESET "\n\n");
return 0;
}
U_BOOT_CMD(ufetch, 2, 1, do_ufetch,
"U-Boot fetch utility",
"Print information about your device.\n"
" -n Don't print the ASCII logo"
);

View file

@ -52,6 +52,7 @@ CONFIG_DISPLAY_BOARDINFO_LATE=y
CONFIG_STACKPROTECTOR=y CONFIG_STACKPROTECTOR=y
CONFIG_ANDROID_AB=y CONFIG_ANDROID_AB=y
CONFIG_CMD_CPU=y CONFIG_CMD_CPU=y
CONFIG_CMD_UFETCH=y
CONFIG_CMD_LICENSE=y CONFIG_CMD_LICENSE=y
CONFIG_CMD_SMBIOS=y CONFIG_CMD_SMBIOS=y
CONFIG_CMD_BOOTM_PRE_LOAD=y CONFIG_CMD_BOOTM_PRE_LOAD=y