diff options
-rw-r--r-- | .azure-pipelines.yml | 2 | ||||
-rw-r--r-- | .gitlab-ci.yml | 2 | ||||
-rw-r--r-- | MAINTAINERS | 5 | ||||
-rw-r--r-- | cmd/Kconfig | 7 | ||||
-rw-r--r-- | cmd/Makefile | 1 | ||||
-rw-r--r-- | cmd/ufetch.c | 229 | ||||
-rw-r--r-- | configs/sandbox_defconfig | 1 | ||||
-rw-r--r-- | drivers/gpio/at91_gpio.c | 97 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/atmel/nand-controller.c | 7 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/atmel/pmecc.c | 1 | ||||
-rw-r--r-- | drivers/mtd/ubispl/ubispl.c | 2 | ||||
-rw-r--r-- | lib/tiny-printf.c | 2 | ||||
-rw-r--r-- | test/py/u_boot_console_base.py | 7 |
13 files changed, 348 insertions, 15 deletions
diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml index cc335e5f720..c577a724c82 100644 --- a/.azure-pipelines.yml +++ b/.azure-pipelines.yml @@ -2,7 +2,7 @@ variables: windows_vm: windows-2022 ubuntu_vm: ubuntu-24.04 macos_vm: macOS-14 - ci_runner_image: trini/u-boot-gitlab-ci-runner:jammy-20240808-21Aug2024 + ci_runner_image: trini/u-boot-gitlab-ci-runner:jammy-20240808-03Dec2024 # Add '-u 0' options for Azure pipelines, otherwise we get "permission # denied" error when it tries to "useradd -m -u 1001 vsts_azpcontainer", # since our $(ci_runner_image) user is not root. diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f0113361a3f..57037e243ec 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -12,7 +12,7 @@ default: # Grab our configured image. The source for this is found # in the u-boot tree at tools/docker/Dockerfile -image: ${MIRROR_DOCKER}/trini/u-boot-gitlab-ci-runner:jammy-20240808-21Aug2024 +image: ${MIRROR_DOCKER}/trini/u-boot-gitlab-ci-runner:jammy-20240808-03Dec2024 # We run some tests in different order, to catch some failures quicker. stages: diff --git a/MAINTAINERS b/MAINTAINERS index 8c6c0c2a4bc..ba31f86feb6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1736,6 +1736,11 @@ S: Maintained T: git https://source.denx.de/u-boot/custodians/u-boot-ubi.git F: drivers/mtd/ubi/ +UFETCH +M: Caleb Connolly <caleb.connolly@linaro.org> +S: Maintained +F: cmd/ufetch.c + UFS M: Neil Armstrong <neil.armstrong@linaro.org> M: Bhupesh Sharma <bhupesh.linux@gmail.com> diff --git a/cmd/Kconfig b/cmd/Kconfig index 702adfd287c..4936a70f3ef 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -176,6 +176,13 @@ config CMD_CPU 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 diff --git a/cmd/Makefile b/cmd/Makefile index d1f369deec0..1e6d3128c8c 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -53,6 +53,7 @@ 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 diff --git a/cmd/ufetch.c b/cmd/ufetch.c new file mode 100644 index 00000000000..0b825d7e8c7 --- /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("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" +); diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 8c244c859bc..af56571f0d0 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -52,6 +52,7 @@ CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_STACKPROTECTOR=y CONFIG_ANDROID_AB=y CONFIG_CMD_CPU=y +CONFIG_CMD_UFETCH=y CONFIG_CMD_LICENSE=y CONFIG_CMD_SMBIOS=y CONFIG_CMD_BOOTM_PRE_LOAD=y diff --git a/drivers/gpio/at91_gpio.c b/drivers/gpio/at91_gpio.c index 50a69815907..76fcd3fb930 100644 --- a/drivers/gpio/at91_gpio.c +++ b/drivers/gpio/at91_gpio.c @@ -219,6 +219,44 @@ static bool at91_get_port_output(struct at91_port *at91_port, int offset) val = readl(&at91_port->osr); return val & mask; } + +static bool at91_is_port_gpio(struct at91_port *at91_port, int offset) +{ + u32 mask, val; + + mask = 1 << offset; + val = readl(&at91_port->psr); + return !!(val & mask); +} + +static void at91_set_port_multi_drive(struct at91_port *at91_port, int offset, int is_on) +{ + u32 mask; + + mask = 1 << offset; + if (is_on) + writel(mask, &at91_port->mder); + else + writel(mask, &at91_port->mddr); +} + +static bool at91_get_port_multi_drive(struct at91_port *at91_port, int offset) +{ + u32 mask, val; + + mask = 1 << offset; + val = readl(&at91_port->mdsr); + return !!(val & mask); +} + +static bool at91_get_port_pullup(struct at91_port *at91_port, int offset) +{ + u32 mask, val; + + mask = 1 << offset; + val = readl(&at91_port->pusr); + return !(val & mask); +} #endif static void at91_set_port_input(struct at91_port *at91_port, int offset, @@ -549,13 +587,68 @@ static int at91_gpio_get_function(struct udevice *dev, unsigned offset) { struct at91_port_priv *port = dev_get_priv(dev); - /* GPIOF_FUNC is not implemented yet */ + if (!at91_is_port_gpio(port->regs, offset)) + return GPIOF_FUNC; + if (at91_get_port_output(port->regs, offset)) return GPIOF_OUTPUT; else return GPIOF_INPUT; } +static int at91_gpio_set_flags(struct udevice *dev, unsigned int offset, + ulong flags) +{ + struct at91_port_priv *port = dev_get_priv(dev); + ulong supported_mask; + + supported_mask = GPIOD_OPEN_DRAIN | GPIOD_MASK_DIR | GPIOD_PULL_UP; + if (flags & ~supported_mask) + return -ENOTSUPP; + + if (flags & GPIOD_IS_OUT) { + if (flags & GPIOD_OPEN_DRAIN) + at91_set_port_multi_drive(port->regs, offset, true); + else + at91_set_port_multi_drive(port->regs, offset, false); + + at91_set_port_output(port->regs, offset, flags & GPIOD_IS_OUT_ACTIVE); + + } else if (flags & GPIOD_IS_IN) { + at91_set_port_input(port->regs, offset, false); + } + if (flags & GPIOD_PULL_UP) + at91_set_port_pullup(port->regs, offset, true); + + return 0; +} + +static int at91_gpio_get_flags(struct udevice *dev, unsigned int offset, + ulong *flagsp) +{ + struct at91_port_priv *port = dev_get_priv(dev); + ulong dir_flags = 0; + + if (at91_get_port_output(port->regs, offset)) { + dir_flags |= GPIOD_IS_OUT; + + if (at91_get_port_multi_drive(port->regs, offset)) + dir_flags |= GPIOD_OPEN_DRAIN; + + if (at91_get_port_value(port->regs, offset)) + dir_flags |= GPIOD_IS_OUT_ACTIVE; + } else { + dir_flags |= GPIOD_IS_IN; + } + + if (at91_get_port_pullup(port->regs, offset)) + dir_flags |= GPIOD_PULL_UP; + + *flagsp = dir_flags; + + return 0; +} + static const char *at91_get_bank_name(uint32_t base_addr) { switch (base_addr) { @@ -584,6 +677,8 @@ static const struct dm_gpio_ops gpio_at91_ops = { .get_value = at91_gpio_get_value, .set_value = at91_gpio_set_value, .get_function = at91_gpio_get_function, + .set_flags = at91_gpio_set_flags, + .get_flags = at91_gpio_get_flags, }; static int at91_gpio_probe(struct udevice *dev) diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c index 817fab4ca36..25f187a2eec 100644 --- a/drivers/mtd/nand/raw/atmel/nand-controller.c +++ b/drivers/mtd/nand/raw/atmel/nand-controller.c @@ -2205,7 +2205,6 @@ static const struct udevice_id atmel_nand_controller_of_ids[] = { static int atmel_nand_controller_probe(struct udevice *dev) { const struct atmel_nand_controller_caps *caps; - struct udevice *pmecc_dev; caps = (struct atmel_nand_controller_caps *)dev_get_driver_data(dev); if (!caps) { @@ -2213,12 +2212,6 @@ static int atmel_nand_controller_probe(struct udevice *dev) return -EINVAL; } - /* Probe pmecc driver */ - if (uclass_get_device(UCLASS_MTD, 1, &pmecc_dev)) { - printf("%s: get device fail\n", __func__); - return -EINVAL; - } - return caps->ops->probe(dev, caps); } diff --git a/drivers/mtd/nand/raw/atmel/pmecc.c b/drivers/mtd/nand/raw/atmel/pmecc.c index 51f6bd2e65b..e500a0fe3f8 100644 --- a/drivers/mtd/nand/raw/atmel/pmecc.c +++ b/drivers/mtd/nand/raw/atmel/pmecc.c @@ -913,6 +913,7 @@ struct atmel_pmecc *devm_atmel_pmecc_get(struct udevice *userdev) ret = ofnode_parse_phandle_with_args(userdev->node_, "ecc-engine", NULL, 0, 0, &args); + /* Probe pmecc driver */ ret = uclass_get_device_by_ofnode(UCLASS_MTD, args.node, &pdev); if (ret) return NULL; diff --git a/drivers/mtd/ubispl/ubispl.c b/drivers/mtd/ubispl/ubispl.c index 90a7c4c6f9e..9face5fae15 100644 --- a/drivers/mtd/ubispl/ubispl.c +++ b/drivers/mtd/ubispl/ubispl.c @@ -113,7 +113,7 @@ static int vtbl_check(struct ubi_scan_info *ubi, crc = crc32(UBI_CRC32_INIT, &vtbl[i], UBI_VTBL_RECORD_SIZE_CRC); if (be32_to_cpu(vtbl[i].crc) != crc) { - ubi_err("bad CRC at record %u: %#08x, not %#08x", + ubi_err("bad CRC at record %u: #%08x, not #%08x", i, crc, be32_to_cpu(vtbl[i].crc)); ubi_dump_vtbl_record(&vtbl[i], i); return 1; diff --git a/lib/tiny-printf.c b/lib/tiny-printf.c index cc1dfe61cf7..0503c17341f 100644 --- a/lib/tiny-printf.c +++ b/lib/tiny-printf.c @@ -312,7 +312,7 @@ static int _vprintf(struct printf_info *info, const char *fmt, va_list va) *info->bf = 0; info->bf = p; - while (*info->bf++ && width > 0) + while (width > 0 && info->bf && *info->bf++) width--; while (width-- > 0) info->putc(info, lz ? '0' : ' '); diff --git a/test/py/u_boot_console_base.py b/test/py/u_boot_console_base.py index fa9cd57b04b..7eaceb39d9d 100644 --- a/test/py/u_boot_console_base.py +++ b/test/py/u_boot_console_base.py @@ -342,11 +342,12 @@ class ConsoleBase(object): # indentation. return self.p.before.strip('\r\n') except Timeout as exc: - handle_exception(self.config, self, self.log, exc, 'Lab failure', - True) + handle_exception(self.config, self, self.log, exc, + f"Lab failure: Timeout executing '{cmd}'", True) raise except BootFail as exc: - handle_exception(self.config, self, self.log, exc, 'Boot fail', + handle_exception(self.config, self, self.log, exc, + f"'Boot fail '{cmd}'", True, self.get_spawn_output()) raise finally: |