Am 14. November 2024 21:08:44 MEZ schrieb Caleb Connolly 
<[email protected]>:
>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 <[email protected]>
>Acked-by: Ilias Apalodimas <[email protected]>
>Tested-by: Mattijs Korpershoek <[email protected]> # vim3
>Tested-by: Neil Armstrong <[email protected]> # on SM8560-QRD
>Signed-off-by: Caleb Connolly <[email protected]>


Acked-by: Heinrich Schuchardt <[email protected]>

>---
>For additional background/context see v1 thread.
>
>I've enabled this for sandbox so it at least gets build-tested in CI as
>Simon originally suggested in v1.
>
>Changes since v2:
> * Fix building on 32-bit ARM
> * Enable for sandbox to avoid build regressions
> * Remove unused Devices line
> * Use blk_get_uclass_name()
> * Add TODO/ideas comment
> * Avoid printing blank lines at the end when running with -n
> * V2: 
> https://lore.kernel.org/u-boot/[email protected]
>
>Changes since v1:
> * Rework storage info to be more dynamic
> * use print_size() helper everywhere
> * manually walk RAM banks to report memory size correctly
> * minor formatting changes and fixes
> * MAINTAINERS entry
> * V1: 
> https://lore.kernel.org/u-boot/[email protected]
>---
> MAINTAINERS               |   5 +
> cmd/Kconfig               |   7 ++
> cmd/Makefile              |   1 +
> cmd/ufetch.c              | 229 ++++++++++++++++++++++++++++++++++++++
> configs/sandbox_defconfig |   1 +
> 5 files changed, 243 insertions(+)
> create mode 100644 cmd/ufetch.c
>
>diff --git a/MAINTAINERS b/MAINTAINERS
>index 0399ed1dbf64..1d81bdecc7c3 100644
>--- a/MAINTAINERS
>+++ b/MAINTAINERS
>@@ -1732,8 +1732,13 @@ M:      Heiko Schocher <[email protected]>
> S:    Maintained
> T:    git https://source.denx.de/u-boot/custodians/u-boot-ubi.git
> F:    drivers/mtd/ubi/
> 
>+UFETCH
>+M:    Caleb Connolly <[email protected]>
>+S:    Maintained
>+F:    cmd/ufetch.c
>+
> UFS
> M:    Neil Armstrong <[email protected]>
> M:    Bhupesh Sharma <[email protected]>
> M:    Neha Malcom Francis <[email protected]>
>diff --git a/cmd/Kconfig b/cmd/Kconfig
>index 636833646f6e..253fbdfe1dd1 100644
>--- a/cmd/Kconfig
>+++ b/cmd/Kconfig
>@@ -175,8 +175,15 @@ config CMD_CPU
>         number of CPUs, type (e.g. manufacturer, architecture, product or
>         internal name) and clock frequency. Other information may be
>         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
>       bool "fwu metadata read"
>       depends on FWU_MULTI_BANK_UPDATE
>       help
>diff --git a/cmd/Makefile b/cmd/Makefile
>index d1f369deec0a..1e6d3128c8ca 100644
>--- a/cmd/Makefile
>+++ b/cmd/Makefile
>@@ -52,8 +52,9 @@ obj-$(CONFIG_CMD_CONSOLE) += console.o
> obj-$(CONFIG_CMD_CPU) += cpu.o
> obj-$(CONFIG_CMD_DATE) += date.o
> obj-$(CONFIG_CMD_DEMO) += demo.o
> obj-$(CONFIG_CMD_DM) += dm.o
>+obj-$(CONFIG_CMD_UFETCH) += ufetch.o
> obj-$(CONFIG_CMD_SOUND) += sound.o
> ifdef CONFIG_POST
> obj-$(CONFIG_CMD_DIAG) += diag.o
> endif
>diff --git a/cmd/ufetch.c b/cmd/ufetch.c
>new file mode 100644
>index 000000000000..61bf264d2afb
>--- /dev/null
>+++ b/cmd/ufetch.c
>@@ -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("ipvaddr");
>+                      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"
>+);
>diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
>index d111858082d5..fb2b5ff54f4a 100644
>--- a/configs/sandbox_defconfig
>+++ b/configs/sandbox_defconfig
>@@ -50,8 +50,9 @@ CONFIG_LOG_DEFAULT_LEVEL=6
> CONFIG_LOGF_FUNC=y
> CONFIG_DISPLAY_BOARDINFO_LATE=y
> CONFIG_STACKPROTECTOR=y
> CONFIG_CMD_CPU=y
>+CONFIG_CMD_UFETCH=y
> CONFIG_CMD_LICENSE=y
> CONFIG_CMD_SMBIOS=y
> CONFIG_CMD_BOOTM_PRE_LOAD=y
> CONFIG_CMD_BOOTZ=y

Reply via email to