Merge https://source.denx.de/u-boot/custodians/u-boot-x86
authorTom Rini <trini@konsulko.com>
Mon, 17 Jul 2023 14:38:28 +0000 (10:38 -0400)
committerTom Rini <trini@konsulko.com>
Mon, 17 Jul 2023 14:38:28 +0000 (10:38 -0400)
- bootstd: Add a bootmeth for ChromiumOS on x86
- x86: Use qemu-x86_64 to boot EFI installers

95 files changed:
arch/sandbox/include/asm/global_data.h
arch/x86/cpu/i386/interrupt.c
arch/x86/cpu/intel_common/mrc.c
arch/x86/cpu/ivybridge/sdram.c
arch/x86/cpu/mtrr.c
arch/x86/cpu/qemu/Kconfig
arch/x86/cpu/start64.S
arch/x86/dts/chromebook_link.dts
arch/x86/include/asm/global_data.h
arch/x86/include/asm/mtrr.h
arch/x86/include/asm/u-boot-x86.h
arch/x86/include/asm/zimage.h
arch/x86/lib/Makefile
arch/x86/lib/bdinfo.c
arch/x86/lib/bios.c
arch/x86/lib/bootm.c
arch/x86/lib/mrccache.c
arch/x86/lib/spl.c
arch/x86/lib/tables.c
arch/x86/lib/zimage.c
board/google/Kconfig
board/sandbox/sandbox.c
boot/Kconfig
boot/Makefile
boot/bootflow.c
boot/bootmeth-uclass.c
boot/bootmeth_cros.c [new file with mode: 0644]
boot/bootmeth_qfw.c
cmd/Kconfig
cmd/acpi.c
cmd/bdinfo.c
cmd/bootflow.c
cmd/part.c
cmd/qfw.c
cmd/x86/mtrr.c
common/bloblist.c
common/board_f.c
common/board_r.c
common/log.c
common/log_console.c
configs/chromebook_coral_defconfig
configs/coreboot_defconfig
configs/qemu-x86_64_defconfig
configs/qemu-x86_defconfig
configs/tools-only_defconfig
disk/part.c
doc/usage/cmd/acpi.rst
doc/usage/cmd/bootflow.rst
doc/usage/cmd/mtrr.rst [new file with mode: 0644]
doc/usage/cmd/part.rst
doc/usage/cmd/qfw.rst
doc/usage/index.rst
drivers/Kconfig
drivers/Makefile
drivers/bios_emulator/Kconfig [new file with mode: 0644]
drivers/bios_emulator/biosemui.h
drivers/bios_emulator/x86emu/sys.c
drivers/gpio/intel_ich6_gpio.c
drivers/misc/qfw.c
drivers/mmc/mmc_bootdev.c
drivers/nvme/nvme.c
drivers/pch/pch9.c
drivers/pci/Kconfig
drivers/pci/pci-uclass.c
drivers/pci/pci_rom.c
drivers/scsi/scsi_bootdev.c
drivers/usb/host/usb_bootdev.c
drivers/video/Kconfig
drivers/video/Makefile
drivers/video/bochs.c [new file with mode: 0644]
drivers/video/bochs.h [new file with mode: 0644]
fs/fat/fat.c
fs/fat/fat_write.c
fs/sandbox/host_bootdev.c
include/asm-generic/global_data.h
include/bloblist.h
include/bootdev.h
include/bootflow.h
include/configs/conga-qeval20-qa3-e3845.h
include/configs/dfi-bt700.h
include/configs/minnowmax.h
include/configs/qemu-x86.h
include/configs/som-db5800-som-6867.h
include/configs/theadorable-x86-common.h
include/configs/x86-chromebook.h
include/env_callback.h
include/part.h
include/video.h
lib/efi_loader/efi_acpi.c
lib/uuid.c
net/eth_bootdev.c
test/boot/bootflow.c
test/cmd/bdinfo.c
test/dm/acpi.c
test/test-main.c

index f4ce72d..f0ab3ba 100644 (file)
 struct arch_global_data {
        uint8_t         *ram_buf;       /* emulated RAM buffer */
        void            *text_base;     /* pointer to base of text region */
+       ulong table_start;              /* Start address of x86 tables */
+       ulong table_end;                /* End address of x86 tables */
+       ulong table_start_high;         /* Start address of high x86 tables */
+       ulong table_end_high;           /* End address of high x86 tables */
 };
 
 #include <asm-generic/global_data.h>
index fae2544..f3f3527 100644 (file)
@@ -266,6 +266,10 @@ int interrupt_init(void)
        struct udevice *dev;
        int ret;
 
+       /*
+        * When running as an EFI application we are not in control of
+        * interrupts and should leave them alone.
+        */
        if (!ll_boot_init())
                return 0;
 
@@ -274,11 +278,6 @@ int interrupt_init(void)
        if (ret && ret != -ENODEV)
                return ret;
 
-       /*
-        * When running as an EFI application we are not in control of
-        * interrupts and should leave them alone.
-        */
-#ifndef CONFIG_EFI_APP
        /* Just in case... */
        disable_interrupts();
 
@@ -294,14 +293,8 @@ int interrupt_init(void)
        /* Initialize core interrupt and exception functionality of CPU */
        cpu_init_interrupts();
 
-       /*
-        * It is now safe to enable interrupts.
-        *
-        * TODO(sjg@chromium.org): But we don't handle these correctly when
-        * booted from EFI.
-        */
+       /* It is now safe to enable interrupts */
        enable_interrupts();
-#endif
 
        return 0;
 }
index 69405d7..56cc253 100644 (file)
@@ -3,6 +3,8 @@
  * Copyright (c) 2016 Google, Inc
  */
 
+#define LOG_CATEGORY   UCLASS_RAM
+
 #include <common.h>
 #include <dm.h>
 #include <init.h>
@@ -144,12 +146,10 @@ int mrc_locate_spd(struct udevice *dev, int size, const void **spd_datap)
 
        ret = gpio_request_list_by_name(dev, "board-id-gpios", desc,
                                        ARRAY_SIZE(desc), GPIOD_IS_IN);
-       if (ret < 0) {
-               debug("%s: gpio ret=%d\n", __func__, ret);
-               return ret;
-       }
+       if (ret < 0)
+               return log_msg_ret("gpio", ret);
        spd_index = dm_gpio_get_values_as_int(desc, ret);
-       debug("spd index %d\n", spd_index);
+       log_debug("spd index %d\n", spd_index);
 
        node = fdt_first_subnode(blob, dev_of_offset(dev));
        if (node < 0)
index 1a0ec43..0718aef 100644 (file)
@@ -9,6 +9,8 @@
  * Copyright (C) 2011 Google Inc.
  */
 
+#define LOG_CATEGORY   UCLASS_RAM
+
 #include <common.h>
 #include <dm.h>
 #include <errno.h>
@@ -213,7 +215,7 @@ static int copy_spd(struct udevice *dev, struct pei_data *peid)
 
        ret = mrc_locate_spd(dev, sizeof(peid->spd_data[0]), &data);
        if (ret) {
-               debug("%s: Could not locate SPD (ret=%d)\n", __func__, ret);
+               log_debug("Could not locate SPD (err=%d)\n", ret);
                return ret;
        }
 
index e69dfb5..d57fcfa 100644 (file)
 
 DECLARE_GLOBAL_DATA_PTR;
 
+static const char *const mtrr_type_name[MTRR_TYPE_COUNT] = {
+       "Uncacheable",
+       "Combine",
+       "2",
+       "3",
+       "Through",
+       "Protect",
+       "Back",
+};
+
 /* Prepare to adjust MTRRs */
 void mtrr_open(struct mtrr_state *state, bool do_caches)
 {
@@ -320,3 +330,54 @@ int mtrr_set(int cpu_select, int reg, u64 base, u64 mask)
 
        return mtrr_start_op(cpu_select, &oper);
 }
+
+static void read_mtrrs_(void *arg)
+{
+       struct mtrr_info *info = arg;
+
+       mtrr_read_all(info);
+}
+
+int mtrr_list(int reg_count, int cpu_select)
+{
+       struct mtrr_info info;
+       int ret;
+       int i;
+
+       printf("Reg Valid Write-type   %-16s %-16s %-16s\n", "Base   ||",
+              "Mask   ||", "Size   ||");
+       memset(&info, '\0', sizeof(info));
+       ret = mp_run_on_cpus(cpu_select, read_mtrrs_, &info);
+       if (ret)
+               return log_msg_ret("run", ret);
+       for (i = 0; i < reg_count; i++) {
+               const char *type = "Invalid";
+               u64 base, mask, size;
+               bool valid;
+
+               base = info.mtrr[i].base;
+               mask = info.mtrr[i].mask;
+               size = ~mask & ((1ULL << CONFIG_CPU_ADDR_BITS) - 1);
+               size |= (1 << 12) - 1;
+               size += 1;
+               valid = mask & MTRR_PHYS_MASK_VALID;
+               type = mtrr_type_name[base & MTRR_BASE_TYPE_MASK];
+               printf("%d   %-5s %-12s %016llx %016llx %016llx\n", i,
+                      valid ? "Y" : "N", type, base & ~MTRR_BASE_TYPE_MASK,
+                      mask & ~MTRR_PHYS_MASK_VALID, size);
+       }
+
+       return 0;
+}
+
+int mtrr_get_type_by_name(const char *typename)
+{
+       int i;
+
+       for (i = 0; i < MTRR_TYPE_COUNT; i++) {
+               if (*typename == *mtrr_type_name[i])
+                       return i;
+       }
+
+       return -EINVAL;
+};
index f8f2f64..aa329b0 100644 (file)
@@ -12,7 +12,7 @@ config QEMU
        imply SYS_NS16550
        imply USB
        imply USB_EHCI_HCD
-       imply VIDEO_VESA
+       imply VIDEO_BOCHS
 
 if QEMU
 
index 7be8347..78e894d 100644 (file)
@@ -26,3 +26,22 @@ _start:
 
        /* Should not return here */
        jmp     .
+
+.globl board_init_f_r_trampoline64
+.type board_init_f_r_trampoline64, @function
+board_init_f_r_trampoline64:
+       /*
+        * SDRAM has been initialised, U-Boot code has been copied into
+        * RAM, BSS has been cleared and relocation adjustments have been
+        * made. It is now time to jump into the in-RAM copy of U-Boot
+        *
+        * %eax = Address of top of new stack
+        */
+
+       /* Stack grows down from top of SDRAM */
+       movq    %rsi, %rsp
+
+       /* New gd is in rdi */
+
+       /* Re-enter U-Boot by calling board_init_f_r() */
+       call    board_init_f_r
index 36956f4..c904b7d 100644 (file)
                                                00 00 00 00 00 00 00 00];
                                        };
                                micron_4Gb_1600_1.35v_x16 {
+                                       bootph-all;
                                        reg = <2>;
                                        data = [92 11 0b 03 04 19 02 02
                                                03 11 01 08 0a 00 fe 00
index 22d103d..ea58259 100644 (file)
@@ -123,6 +123,10 @@ struct arch_global_data {
 #endif
        void *itss_priv;                /* Private ITSS data pointer */
        ulong coreboot_table;           /* Address of coreboot table */
+       ulong table_start;              /* Start address of x86 tables */
+       ulong table_end;                /* End address of x86 tables */
+       ulong table_start_high;         /* Start address of high x86 tables */
+       ulong table_end_high;           /* End address of high x86 tables */
 };
 
 #endif
index ca2edc7..2e995f5 100644 (file)
@@ -190,6 +190,26 @@ int mtrr_set(int cpu_select, int reg, u64 base, u64 mask);
  */
 int mtrr_get_var_count(void);
 
+/**
+ * mtrr_list() - List the MTRRs
+ *
+ * Shows a list of all the MTRRs including their values
+ *
+ * @reg_count: Number of registers to show. You can use mtrr_get_var_count() for
+ * this
+ * @cpu_select: CPU to use. Use MP_SELECT_BSP for the boot CPU
+ * Returns: 0 if OK, -ve if the CPU was not found
+ */
+int mtrr_list(int reg_count, int cpu_select);
+
+/**
+ * mtrr_get_type_by_name() - Get the type of an MTRR given its type name
+ *
+ * @typename: Name to check
+ * Returns: MTRR type (MTRR_TYPE_...) or -EINVAL if invalid
+ */
+int mtrr_get_type_by_name(const char *typename);
+
 #endif
 
 #if ((CONFIG_XIP_ROM_SIZE & (CONFIG_XIP_ROM_SIZE - 1)) != 0)
index 8f38c2d..02a8b0f 100644 (file)
@@ -102,8 +102,31 @@ int video_bios_init(void);
  */
 int fsp_save_s3_stack(void);
 
-void   board_init_f_r_trampoline(ulong) __attribute__ ((noreturn));
-void   board_init_f_r(void) __attribute__ ((noreturn));
+/**
+ * board_init_f_r_trampoline() - jump to relocated address with new stack
+ *
+ * @sp: New stack pointer to use
+ */
+void __noreturn board_init_f_r_trampoline(ulong sp);
+
+/**
+ * board_init_f_r() - jump to relocated U-Boot
+ *
+ * This is used to jump from pre-relocation to post-relocation U-Boot. It
+ * enables the cache and jump to the new location.
+ */
+void __noreturn board_init_f_r(void);
+
+/*
+ * board_init_f_r_trampoline64() - jump to relocated address with new stack
+ *
+ * This is the 64-bit version
+ *
+ * @new_gd: New global_data pointer to use
+ * @sp: New stack pointer to pass on to board_init_r()
+ */
+void __noreturn board_init_f_r_trampoline64(struct global_data *new_gd,
+                                           ulong sp);
 
 int arch_misc_init(void);
 
index 000b38e..9ad74dc 100644 (file)
@@ -72,4 +72,31 @@ int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot,
  */
 void zimage_dump(struct boot_params *base_ptr);
 
+/**
+ * zboot_start() - Boot a zimage
+ *
+ * Boot a zimage, given the component parts
+ *
+ * @addr: Address where the bzImage is moved before booting, either
+ *     BZIMAGE_LOAD_ADDR or ZIMAGE_LOAD_ADDR
+ * @base: Pointer to the boot parameters, typically at address
+ *     DEFAULT_SETUP_BASE
+ * @initrd: Address of the initial ramdisk, or 0 if none
+ * @initrd_size: Size of the initial ramdisk, or 0 if none
+ * @cmdline: Command line to use for booting
+ * Return: -EFAULT on error (normally it does not return)
+ */
+int zboot_start(ulong addr, ulong size, ulong initrd, ulong initrd_size,
+               ulong base, char *cmdline);
+
+/*
+ * zimage_get_kernel_version() - Get the version string from a kernel
+ *
+ * @params: boot_params pointer
+ * @kernel_base: base address of kernel
+ * Return: Kernel version as a NUL-terminated string
+ */
+const char *zimage_get_kernel_version(struct boot_params *params,
+                                     void *kernel_base);
+
 #endif
index b0612ae..90a7618 100644 (file)
@@ -4,16 +4,17 @@
 # Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 
 obj-y  += bdinfo.o
-ifndef CONFIG_X86_64
-ifndef CONFIG_TPL_BUILD
+
+ifndef CONFIG_$(SPL_TPL_)X86_64
 obj-y += bios.o
 obj-y += bios_asm.o
 obj-y += bios_interrupts.o
 endif
-endif
+
 ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_X86_32BIT_INIT) += string.o
 endif
+
 ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_CMD_BOOTM) += bootm.o
 endif
index 1539007..1240584 100644 (file)
@@ -22,6 +22,11 @@ void arch_print_bdinfo(void)
        bdinfo_print_num_l("vendor", gd->arch.x86_vendor);
        bdinfo_print_str(" name", cpu_vendor_name(gd->arch.x86_vendor));
        bdinfo_print_num_l("model", gd->arch.x86_model);
+       bdinfo_print_num_l("phys_addr in bits", cpu_phys_address_size());
+       bdinfo_print_num_l("table start", gd->arch.table_start);
+       bdinfo_print_num_l("table end", gd->arch.table_end);
+       bdinfo_print_num_l(" high start", gd->arch.table_start_high);
+       bdinfo_print_num_l(" high end", gd->arch.table_end_high);
 
        if (IS_ENABLED(CONFIG_EFI_STUB))
                efi_show_bdinfo();
index 94349ba..e29cae7 100644 (file)
@@ -23,7 +23,7 @@
 static int (*int_handler[256])(void);
 
 /* to have a common register file for interrupt handlers */
-#ifndef CONFIG_BIOSEMU
+#if !CONFIG_IS_ENABLED(BIOSEMU)
 X86EMU_sysEnv _X86EMU_env;
 #endif
 
@@ -78,7 +78,7 @@ static int int_exception_handler(void)
        };
        struct eregs *regs = &reg_info;
 
-       debug("Oops, exception %d while executing option rom\n", regs->vector);
+       log_err("Exception %d while executing option rom\n", regs->vector);
        cpu_hlt();
 
        return 0;
index 61cb7bc..3196f9d 100644 (file)
@@ -258,7 +258,7 @@ static ulong get_sp(void)
        ulong ret;
 
 #if CONFIG_IS_ENABLED(X86_64)
-       ret = gd->start_addr_sp;
+       asm("mov %%rsp, %0" : "=r"(ret) : );
 #else
        asm("mov %%esp, %0" : "=r"(ret) : );
 #endif
index 2f6f688..6494b8d 100644 (file)
@@ -6,6 +6,8 @@
  * Copyright (C) 2015 Bin Meng <bmeng.cn@gmail.com>
  */
 
+#define LOG_CATEGORY   UCLASS_RAM
+
 #include <common.h>
 #include <dm.h>
 #include <errno.h>
@@ -197,8 +199,8 @@ static void mrccache_setup(struct mrc_output *mrc, void *data)
        cache->signature = MRC_DATA_SIGNATURE;
        cache->data_size = mrc->len;
        checksum = compute_ip_checksum(mrc->buf, cache->data_size);
-       debug("Saving %d bytes for MRC output data, checksum %04x\n",
-             cache->data_size, checksum);
+       log_debug("Saving %d bytes for MRC output data, checksum %04x\n",
+                 cache->data_size, checksum);
        cache->checksum = checksum;
        cache->reserved = 0;
        memcpy(cache->data, mrc->buf, cache->data_size);
index ca1645f..b6812bb 100644 (file)
@@ -3,6 +3,8 @@
  * Copyright (c) 2016 Google, Inc
  */
 
+#define LOG_CATEGORY   LOGC_BOOT
+
 #include <common.h>
 #include <cpu_func.h>
 #include <debug_uart.h>
 #include <malloc.h>
 #include <spl.h>
 #include <syscon.h>
+#include <vesa.h>
 #include <asm/cpu.h>
 #include <asm/cpu_common.h>
 #include <asm/fsp2/fsp_api.h>
 #include <asm/global_data.h>
+#include <asm/mp.h>
 #include <asm/mrccache.h>
 #include <asm/mtrr.h>
 #include <asm/pci.h>
@@ -61,6 +65,8 @@ static int set_max_freq(void)
 
 static int x86_spl_init(void)
 {
+       struct udevice *dev;
+
 #ifndef CONFIG_TPL
        /*
         * TODO(sjg@chromium.org): We use this area of RAM for the stack
@@ -74,49 +80,64 @@ static int x86_spl_init(void)
 #endif
        int ret;
 
-       debug("%s starting\n", __func__);
+       log_debug("x86 spl starting\n");
        if (IS_ENABLED(TPL))
                ret = x86_cpu_reinit_f();
        else
                ret = x86_cpu_init_f();
        ret = spl_init();
        if (ret) {
-               debug("%s: spl_init() failed\n", __func__);
+               log_debug("spl_init() failed (err=%d)\n", ret);
                return ret;
        }
        ret = arch_cpu_init();
        if (ret) {
-               debug("%s: arch_cpu_init() failed\n", __func__);
+               log_debug("arch_cpu_init() failed (err=%d)\n", ret);
                return ret;
        }
 #ifndef CONFIG_TPL
        ret = fsp_setup_pinctrl(NULL, NULL);
        if (ret) {
-               debug("%s: fsp_setup_pinctrl() failed\n", __func__);
+               log_debug("fsp_setup_pinctrl() failed (err=%d)\n", ret);
                return ret;
        }
 #endif
-       preloader_console_init();
+       /*
+        * spl_board_init() below sets up the console if enabled. If it isn't,
+        * do it here. We cannot call this twice since it results in a double
+        * banner and CI tests fail.
+        */
+       if (!IS_ENABLED(CONFIG_SPL_BOARD_INIT))
+               preloader_console_init();
 #if !defined(CONFIG_TPL) && !CONFIG_IS_ENABLED(CPU)
        ret = print_cpuinfo();
        if (ret) {
-               debug("%s: print_cpuinfo() failed\n", __func__);
+               log_debug("print_cpuinfo() failed (err=%d)\n", ret);
                return ret;
        }
 #endif
+       /* probe the LPC so we get the GPIO_BASE set up correctly */
+       ret = uclass_first_device_err(UCLASS_LPC, &dev);
+       if (ret && ret != -ENODEV) {
+               log_debug("lpc probe failed\n");
+               return ret;
+       }
+
        ret = dram_init();
        if (ret) {
-               debug("%s: dram_init() failed\n", __func__);
+               log_debug("dram_init() failed (err=%d)\n", ret);
                return ret;
        }
+       log_debug("mrc\n");
        if (IS_ENABLED(CONFIG_ENABLE_MRC_CACHE)) {
                ret = mrccache_spl_save();
                if (ret)
-                       debug("%s: Failed to write to mrccache (err=%d)\n",
-                             __func__, ret);
+                       log_debug("Failed to write to mrccache (err=%d)\n",
+                                 ret);
        }
 
 #ifndef CONFIG_SYS_COREBOOT
+       log_debug("bss\n");
        debug("BSS clear from %lx to %lx len %lx\n", (ulong)&__bss_start,
              (ulong)&__bss_end, (ulong)&__bss_end - (ulong)&__bss_start);
        memset(&__bss_start, 0, (ulong)&__bss_end - (ulong)&__bss_start);
@@ -136,9 +157,29 @@ static int x86_spl_init(void)
         */
        gd->new_gd = (struct global_data *)ptr;
        memcpy(gd->new_gd, gd, sizeof(*gd));
+
+       log_debug("logging\n");
+       /*
+        * Make sure logging is disabled when we switch, since the log system
+        * list head will move
+        */
+       gd->new_gd->flags &= ~GD_FLG_LOG_READY;
        arch_setup_gd(gd->new_gd);
        gd->start_addr_sp = (ulong)ptr;
 
+       /* start up logging again, with the new list-head location */
+       ret = log_init();
+       if (ret) {
+               log_debug("Log setup failed (err=%d)\n", ret);
+               return ret;
+       }
+
+       if (_LOG_DEBUG) {
+               ret = mtrr_list(mtrr_get_var_count(), MP_SELECT_BSP);
+               if (ret)
+                       printf("mtrr_list failed\n");
+       }
+
        /* Cache the SPI flash. Otherwise copying the code to RAM takes ages */
        ret = mtrr_add_request(MTRR_TYPE_WRBACK,
                               (1ULL << 32) - CONFIG_XIP_ROM_SIZE,
@@ -157,6 +198,7 @@ static int x86_spl_init(void)
                debug("Failed to set CPU frequency (err=%d)\n", ret);
 # endif
 #endif
+       log_debug("done\n");
 
        return 0;
 }
@@ -250,4 +292,12 @@ void spl_board_init(void)
 #ifndef CONFIG_TPL
        preloader_console_init();
 #endif
+
+       if (CONFIG_IS_ENABLED(VIDEO)) {
+               struct udevice *dev;
+
+               /* Set up PCI video in SPL if required */
+               uclass_first_device_err(UCLASS_PCI, &dev);
+               uclass_first_device_err(UCLASS_VIDEO, &dev);
+       }
 }
index ea834a5..67bc0a7 100644 (file)
@@ -3,7 +3,7 @@
  * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
  */
 
-#define LOG_CATEGORY LOGC_BOARD
+#define LOG_CATEGORY LOGC_ACPI
 
 #include <common.h>
 #include <bloblist.h>
@@ -54,6 +54,10 @@ static struct table_info table_list[] = {
 #ifdef CONFIG_GENERATE_MP_TABLE
        { "mp", write_mp_table, },
 #endif
+       /*
+        * tables which can go in the bloblist must be last in this list, so
+        * that the calculation of gd->table_end works properly
+        */
 #ifdef CONFIG_GENERATE_ACPI_TABLE
        { "acpi", write_acpi_tables, BLOBLISTT_ACPI_TABLES, 0x10000, 0x1000},
 #endif
@@ -78,33 +82,42 @@ void table_fill_string(char *dest, const char *src, size_t n, char pad)
 
 int write_tables(void)
 {
-       u32 rom_table_start;
-       u32 rom_table_end;
        u32 high_table, table_size;
        struct memory_area cfg_tables[ARRAY_SIZE(table_list) + 1];
+       bool use_high = false;
+       u32 rom_addr;
        int i;
 
-       rom_table_start = ROM_TABLE_ADDR;
+       gd->arch.table_start = ROM_TABLE_ADDR;
+       rom_addr = gd->arch.table_start;
 
-       debug("Writing tables to %x:\n", rom_table_start);
+       debug("Writing tables to %x:\n", rom_addr);
        for (i = 0; i < ARRAY_SIZE(table_list); i++) {
                const struct table_info *table = &table_list[i];
                int size = table->size ? : CONFIG_ROM_TABLE_SIZE;
+               u32 rom_table_end;
 
                if (IS_ENABLED(CONFIG_BLOBLIST_TABLES) && table->tag) {
-                       rom_table_start = (ulong)bloblist_add(table->tag, size,
-                                                             table->align);
-                       if (!rom_table_start)
+                       if (!gd->arch.table_end)
+                               gd->arch.table_end = rom_addr;
+                       rom_addr = (ulong)bloblist_add(table->tag, size,
+                                                      table->align);
+                       if (!rom_addr)
                                return log_msg_ret("bloblist", -ENOBUFS);
+
+                       /* the bloblist is always in high memory */
+                       use_high = true;
+                       if (!gd->arch.table_start_high)
+                               gd->arch.table_start_high = rom_addr;
                }
-               rom_table_end = table->write(rom_table_start);
+               rom_table_end = table->write(rom_addr);
                if (!rom_table_end) {
                        log_err("Can't create configuration table %d\n", i);
                        return -EINTR;
                }
 
                if (IS_ENABLED(CONFIG_SEABIOS)) {
-                       table_size = rom_table_end - rom_table_start;
+                       table_size = rom_table_end - rom_addr;
                        high_table = (u32)(ulong)high_table_malloc(table_size);
                        if (high_table) {
                                if (!table->write(high_table)) {
@@ -123,15 +136,20 @@ int write_tables(void)
                }
 
                debug("- wrote '%s' to %x, end %x\n", table->name,
-                     rom_table_start, rom_table_end);
-               if (rom_table_end - rom_table_start > size) {
+                     rom_addr, rom_table_end);
+               if (rom_table_end - rom_addr > size) {
                        log_err("Out of space for configuration tables: need %x, have %x\n",
-                               rom_table_end - rom_table_start, size);
+                               rom_table_end - rom_addr, size);
                        return log_msg_ret("bloblist", -ENOSPC);
                }
-               rom_table_start = rom_table_end;
+               rom_addr = rom_table_end;
        }
 
+       if (use_high)
+               gd->arch.table_end_high = rom_addr;
+       else
+               gd->arch.table_end = rom_addr;
+
        if (IS_ENABLED(CONFIG_SEABIOS)) {
                /* make sure the last item is zero */
                cfg_tables[i].size = 0;
index e5ea512..062e3d3 100644 (file)
@@ -22,6 +22,7 @@
 #include <irq_func.h>
 #include <log.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <acpi/acpi_table.h>
 #include <asm/io.h>
 #include <asm/ptrace.h>
@@ -180,7 +181,7 @@ static int setup_device_tree(struct setup_header *hdr, const void *fdt_blob)
        return 0;
 }
 
-static const char *get_kernel_version(struct boot_params *params,
+const char *zimage_get_kernel_version(struct boot_params *params,
                                      void *kernel_base)
 {
        struct setup_header *hdr = &params->hdr;
@@ -188,10 +189,14 @@ static const char *get_kernel_version(struct boot_params *params,
        const char *s, *end;
 
        bootproto = get_boot_protocol(hdr, false);
+       log_debug("bootproto %x, hdr->setup_sects %x\n", bootproto,
+                 hdr->setup_sects);
        if (bootproto < 0x0200 || hdr->setup_sects < 15)
                return NULL;
 
        /* sanity-check the kernel version in case it is missing */
+       log_debug("hdr->kernel_version %x, str at %p\n", hdr->kernel_version,
+                 kernel_base + hdr->kernel_version + 0x200);
        for (s = kernel_base + hdr->kernel_version + 0x200, end = s + 0x100; *s;
             s++) {
                if (!isprint(*s))
@@ -238,7 +243,7 @@ struct boot_params *load_zimage(char *image, unsigned long kernel_size,
        log_debug("Using boot protocol version %x.%02x\n",
                  (bootproto & 0xff00) >> 8, bootproto & 0xff);
 
-       version = get_kernel_version(params, image);
+       version = zimage_get_kernel_version(params, image);
        if (version)
                printf("Linux kernel version %s\n", version);
        else
@@ -442,8 +447,7 @@ static int do_zboot_start(struct cmd_tbl *cmdtp, int flag, int argc,
        return 0;
 }
 
-static int do_zboot_load(struct cmd_tbl *cmdtp, int flag, int argc,
-                        char *const argv[])
+static int zboot_load(void)
 {
        struct boot_params *base_ptr;
 
@@ -460,31 +464,51 @@ static int do_zboot_load(struct cmd_tbl *cmdtp, int flag, int argc,
                                       &state.load_address);
                if (!base_ptr) {
                        puts("## Kernel loading failed ...\n");
-                       return CMD_RET_FAILURE;
+                       return -EINVAL;
                }
        }
        state.base_ptr = base_ptr;
-       if (env_set_hex("zbootbase", (ulong)base_ptr) ||
+
+       return 0;
+}
+
+static int do_zboot_load(struct cmd_tbl *cmdtp, int flag, int argc,
+                        char *const argv[])
+{
+       if (zboot_load())
+               return CMD_RET_FAILURE;
+
+       if (env_set_hex("zbootbase", map_to_sysmem(state.base_ptr)) ||
            env_set_hex("zbootaddr", state.load_address))
                return CMD_RET_FAILURE;
 
        return 0;
 }
 
+static int zboot_setup(void)
+{
+       struct boot_params *base_ptr = state.base_ptr;
+       int ret;
+
+       ret = setup_zimage(base_ptr, (char *)base_ptr + COMMAND_LINE_OFFSET,
+                          0, state.initrd_addr, state.initrd_size,
+                          (ulong)state.cmdline);
+       if (ret)
+               return -EINVAL;
+
+       return 0;
+}
+
 static int do_zboot_setup(struct cmd_tbl *cmdtp, int flag, int argc,
                          char *const argv[])
 {
        struct boot_params *base_ptr = state.base_ptr;
-       int ret;
 
        if (!base_ptr) {
                printf("base is not set: use 'zboot load' first\n");
                return CMD_RET_FAILURE;
        }
-       ret = setup_zimage(base_ptr, (char *)base_ptr + COMMAND_LINE_OFFSET,
-                          0, state.initrd_addr, state.initrd_size,
-                          (ulong)state.cmdline);
-       if (ret) {
+       if (zboot_setup()) {
                puts("Setting up boot parameters failed ...\n");
                return CMD_RET_FAILURE;
        }
@@ -501,8 +525,7 @@ static int do_zboot_info(struct cmd_tbl *cmdtp, int flag, int argc,
        return 0;
 }
 
-static int do_zboot_go(struct cmd_tbl *cmdtp, int flag, int argc,
-                      char *const argv[])
+static int zboot_go(void)
 {
        struct boot_params *params = state.base_ptr;
        struct setup_header *hdr = &params->hdr;
@@ -522,11 +545,52 @@ static int do_zboot_go(struct cmd_tbl *cmdtp, int flag, int argc,
 
        /* we assume that the kernel is in place */
        ret = boot_linux_kernel((ulong)state.base_ptr, entry, image_64bit);
+
+       return ret;
+}
+
+static int do_zboot_go(struct cmd_tbl *cmdtp, int flag, int argc,
+                      char *const argv[])
+{
+       int ret;
+
+       ret = zboot_go();
        printf("Kernel returned! (err=%d)\n", ret);
 
        return CMD_RET_FAILURE;
 }
 
+int zboot_start(ulong addr, ulong size, ulong initrd, ulong initrd_size,
+               ulong base, char *cmdline)
+{
+       int ret;
+
+       memset(&state, '\0', sizeof(state));
+
+       if (base) {
+               state.base_ptr = map_sysmem(base, 0);
+               state.load_address = addr;
+       } else {
+               state.bzimage_addr = addr;
+       }
+       state.bzimage_size = size;
+       state.initrd_addr = initrd;
+       state.initrd_size = initrd_size;
+       state.cmdline = cmdline;
+
+       ret = zboot_load();
+       if (ret)
+               return log_msg_ret("ld", ret);
+       ret = zboot_setup();
+       if (ret)
+               return log_msg_ret("set", ret);
+       ret = zboot_go();
+       if (ret)
+               return log_msg_ret("set", ret);
+
+       return -EFAULT;
+}
+
 static void print_num(const char *name, ulong value)
 {
        printf("%-20s: %lx\n", name, value);
@@ -668,7 +732,8 @@ void zimage_dump(struct boot_params *base_ptr)
        print_num("Real mode switch", hdr->realmode_swtch);
        print_num("Start sys seg", hdr->start_sys_seg);
        print_num("Kernel version", hdr->kernel_version);
-       version = get_kernel_version(base_ptr, (void *)state.bzimage_addr);
+       version = zimage_get_kernel_version(base_ptr,
+                                           (void *)state.bzimage_addr);
        if (version)
                printf("   @%p: %s\n", version, version);
        print_num("Type of loader", hdr->type_of_loader);
index a0f1a60..e4f9b5b 100644 (file)
@@ -4,13 +4,6 @@
 
 if VENDOR_GOOGLE
 
-config BIOSEMU
-       bool
-       select X86EMU_RAW_IO
-
-config X86EMU_RAW_IO
-       bool
-
 choice
        prompt "Mainboard model"
        optional
index c7b6cb7..9d58860 100644 (file)
 #include <efi.h>
 #include <efi_loader.h>
 #include <env_internal.h>
+#include <extension_board.h>
 #include <init.h>
 #include <led.h>
+#include <malloc.h>
+#include <mapmem.h>
 #include <os.h>
+#include <acpi/acpi_table.h>
 #include <asm/global_data.h>
 #include <asm/test.h>
 #include <asm/u-boot-sandbox.h>
 #include <linux/kernel.h>
-#include <malloc.h>
-
-#include <extension_board.h>
+#include <linux/sizes.h>
 
 /*
  * Pointer to initial global data area
@@ -154,6 +156,8 @@ int extension_board_scan(struct list_head *extension_list)
 int board_late_init(void)
 {
        struct udevice *dev;
+       ulong addr, end;
+       void *ptr;
        int ret;
 
        ret = uclass_first_device_err(UCLASS_CROS_EC, &dev);
@@ -166,6 +170,18 @@ int board_late_init(void)
                panic("Cannot init cros-ec device");
                return -1;
        }
+
+       if (IS_ENABLED(CONFIG_GENERATE_ACPI_TABLE)) {
+               /* Reserve 64K for ACPI tables, aligned to a 4K boundary */
+               ptr = memalign(SZ_4K, SZ_64K);
+               addr = map_to_sysmem(ptr);
+
+               /* Generate ACPI tables */
+               end = write_acpi_tables(addr);
+               gd->arch.table_start = addr;
+               gd->arch.table_end = addr;
+       }
+
        return 0;
 }
 #endif
index c8b8f36..b424265 100644 (file)
@@ -463,6 +463,17 @@ config BOOTMETH_GLOBAL
          EFI bootmgr, since they take full control over which bootdevs are
          selected to boot.
 
+config BOOTMETH_CROS
+       bool "Bootdev support for Chromium OS"
+       depends on X86 || SANDBOX
+       default y
+       help
+         Enables support for booting Chromium OS using bootdevs. This uses the
+         kernel A slot and obtains the kernel command line from the parameters
+         provided there.
+
+         Note that only x86 devices are supported at present.
+
 config BOOTMETH_EXTLINUX
        bool "Bootdev support for extlinux boot"
        select PXE_UTILS
index f828f87..10f0157 100644 (file)
@@ -27,6 +27,7 @@ obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootstd-uclass.o
 obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_EXTLINUX) += bootmeth_extlinux.o
 obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_EXTLINUX_PXE) += bootmeth_pxe.o
 obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_EFILOADER) += bootmeth_efi.o
+obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_CROS) += bootmeth_cros.o
 obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_SANDBOX) += bootmeth_sandbox.o
 obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_SCRIPT) += bootmeth_script.o
 ifdef CONFIG_$(SPL_TPL_)BOOTSTD_FULL
index 8f2cb87..81b5829 100644 (file)
@@ -12,7 +12,9 @@
 #include <bootmeth.h>
 #include <bootstd.h>
 #include <dm.h>
+#include <env_internal.h>
 #include <malloc.h>
+#include <serial.h>
 #include <dm/device-internal.h>
 #include <dm/uclass-internal.h>
 
@@ -315,14 +317,14 @@ static int bootflow_check(struct bootflow_iter *iter, struct bootflow *bflow)
 
        /* If we got a valid bootflow, return it */
        if (!ret) {
-               log_debug("Bootdevice '%s' part %d method '%s': Found bootflow\n",
+               log_debug("Bootdev '%s' part %d method '%s': Found bootflow\n",
                          dev->name, iter->part, iter->method->name);
                return 0;
        }
 
        /* Unless there is nothing more to try, move to the next device */
        else if (ret != BF_NO_MORE_PARTS && ret != -ENOSYS) {
-               log_debug("Bootdevice '%s' part %d method '%s': Error %d\n",
+               log_debug("Bootdev '%s' part %d method '%s': Error %d\n",
                          dev->name, iter->part, iter->method->name, ret);
                /*
                 * For 'all' we return all bootflows, even
@@ -552,3 +554,336 @@ int bootflow_iter_check_system(const struct bootflow_iter *iter)
 
        return -ENOTSUPP;
 }
+
+/**
+ * bootflow_cmdline_set() - Set the command line for a bootflow
+ *
+ * @value: New command-line string
+ * Returns 0 if OK, -ENOENT if no current bootflow, -ENOMEM if out of memory
+ */
+int bootflow_cmdline_set(struct bootflow *bflow, const char *value)
+{
+       char *cmdline = NULL;
+
+       if (value) {
+               cmdline = strdup(value);
+               if (!cmdline)
+                       return -ENOMEM;
+       }
+
+       free(bflow->cmdline);
+       bflow->cmdline = cmdline;
+
+       return 0;
+}
+
+#ifdef CONFIG_BOOTSTD_FULL
+/**
+ * on_bootargs() - Update the cmdline of a bootflow
+ */
+static int on_bootargs(const char *name, const char *value, enum env_op op,
+                      int flags)
+{
+       struct bootstd_priv *std;
+       struct bootflow *bflow;
+       int ret;
+
+       ret = bootstd_get_priv(&std);
+       if (ret)
+               return 0;
+       bflow = std->cur_bootflow;
+       if (!bflow)
+               return 0;
+
+       switch (op) {
+       case env_op_create:
+       case env_op_overwrite:
+               ret = bootflow_cmdline_set(bflow, value);
+               if (ret && ret != ENOENT)
+                       return 1;
+               return 0;
+       case env_op_delete:
+               bootflow_cmdline_set(bflow, NULL);
+               fallthrough;
+       default:
+               return 0;
+       }
+}
+U_BOOT_ENV_CALLBACK(bootargs, on_bootargs);
+#endif
+
+/**
+ * copy_in() - Copy a string into a cmdline buffer
+ *
+ * @buf: Buffer to copy into
+ * @end: End of buffer (pointer to char after the end)
+ * @arg: String to copy from
+ * @len: Number of chars to copy from @arg (note that this is not usually the
+ * sane as strlen(arg) since the string may contain following arguments)
+ * @new_val: Value to put after arg, or BOOTFLOWCL_EMPTY to use an empty value
+ * with no '=' sign
+ * Returns: Number of chars written to @buf
+ */
+static int copy_in(char *buf, char *end, const char *arg, int len,
+                  const char *new_val)
+{
+       char *to = buf;
+
+       /* copy the arg name */
+       if (to + len >= end)
+               return -E2BIG;
+       memcpy(to, arg, len);
+       to += len;
+
+       if (new_val == BOOTFLOWCL_EMPTY) {
+               /* no value */
+       } else {
+               bool need_quote = strchr(new_val, ' ');
+               len = strlen(new_val);
+
+               /* need space for value, equals sign and maybe two quotes */
+               if (to + 1 + (need_quote ? 2 : 0) + len >= end)
+                       return -E2BIG;
+               *to++ = '=';
+               if (need_quote)
+                       *to++ = '"';
+               memcpy(to, new_val, len);
+               to += len;
+               if (need_quote)
+                       *to++ = '"';
+       }
+
+       return to - buf;
+}
+
+int cmdline_set_arg(char *buf, int maxlen, const char *cmdline,
+                   const char *set_arg, const char *new_val, int *posp)
+{
+       bool found_arg = false;
+       const char *from;
+       char *to, *end;
+       int set_arg_len;
+       char empty = '\0';
+       int ret;
+
+       from = cmdline ?: &empty;
+
+       /* check if the value has quotes inside */
+       if (new_val && new_val != BOOTFLOWCL_EMPTY && strchr(new_val, '"'))
+               return -EBADF;
+
+       set_arg_len = strlen(set_arg);
+       for (to = buf, end = buf + maxlen; *from;) {
+               const char *val, *arg_end, *val_end, *p;
+               bool in_quote;
+
+               if (to >= end)
+                       return -E2BIG;
+               while (*from == ' ')
+                       from++;
+               if (!*from)
+                       break;
+
+               /* find the end of this arg */
+               val = NULL;
+               arg_end = NULL;
+               val_end = NULL;
+               in_quote = false;
+               for (p = from;; p++) {
+                       if (in_quote) {
+                               if (!*p)
+                                       return -EINVAL;
+                               if (*p == '"')
+                                       in_quote = false;
+                               continue;
+                       }
+                       if (*p == '=') {
+                               arg_end = p;
+                               val = p + 1;
+                       } else if (*p == '"') {
+                               in_quote = true;
+                       } else if (!*p || *p == ' ') {
+                               val_end = p;
+                               if (!arg_end)
+                                       arg_end = p;
+                               break;
+                       }
+               }
+               /*
+                * At this point val_end points to the end of the value, or the
+                * last char after the arg name, if there is no label.
+                * arg_end is the char after the arg name
+                * val points to the value, or NULL if there is none
+                * char after the value.
+                *
+                *        fred=1234
+                *        ^   ^^   ^
+                *      from  ||   |
+                *           / \    \
+                *    arg_end  val   val_end
+                */
+               log_debug("from %s arg_end %ld val %ld val_end %ld\n", from,
+                         (long)(arg_end - from), (long)(val - from),
+                         (long)(val_end - from));
+
+               if (to != buf) {
+                       if (to >= end)
+                               return -E2BIG;
+                       *to++ = ' ';
+               }
+
+               /* if this is the target arg, update it */
+               if (!strncmp(from, set_arg, arg_end - from)) {
+                       if (!buf) {
+                               bool has_quote = val_end[-1] == '"';
+
+                               /*
+                                * exclude any start/end quotes from
+                                * calculations
+                                */
+                               if (!val)
+                                       val = val_end;
+                               *posp = val - cmdline + has_quote;
+                               return val_end - val - 2 * has_quote;
+                       }
+                       found_arg = true;
+                       if (!new_val) {
+                               /* delete this arg */
+                               from = val_end + (*val_end == ' ');
+                               log_debug("delete from: %s\n", from);
+                               if (to != buf)
+                                       to--; /* drop the space we added */
+                               continue;
+                       }
+
+                       ret = copy_in(to, end, from, arg_end - from, new_val);
+                       if (ret < 0)
+                               return ret;
+                       to += ret;
+
+               /* if not the target arg, copy it unchanged */
+               } else if (to) {
+                       int len;
+
+                       len = val_end - from;
+                       if (to + len >= end)
+                               return -E2BIG;
+                       memcpy(to, from, len);
+                       to += len;
+               }
+               from = val_end;
+       }
+
+       /* If we didn't find the arg, add it */
+       if (!found_arg) {
+               /* trying to delete something that is not there */
+               if (!new_val || !buf)
+                       return -ENOENT;
+               if (to >= end)
+                       return -E2BIG;
+
+               /* add a space to separate it from the previous arg */
+               if (to != buf && to[-1] != ' ')
+                       *to++ = ' ';
+               ret = copy_in(to, end, set_arg, set_arg_len, new_val);
+               log_debug("ret=%d, to: %s buf: %s\n", ret, to, buf);
+               if (ret < 0)
+                       return ret;
+               to += ret;
+       }
+
+       /* delete any trailing space */
+       if (to > buf && to[-1] == ' ')
+               to--;
+
+       if (to >= end)
+               return -E2BIG;
+       *to++ = '\0';
+
+       return to - buf;
+}
+
+int bootflow_cmdline_set_arg(struct bootflow *bflow, const char *set_arg,
+                            const char *new_val, bool set_env)
+{
+       char buf[2048];
+       char *cmd = NULL;
+       int ret;
+
+       ret = cmdline_set_arg(buf, sizeof(buf), bflow->cmdline, set_arg,
+                             new_val, NULL);
+       if (ret < 0)
+               return ret;
+
+       ret = bootflow_cmdline_set(bflow, buf);
+       if (*buf) {
+               cmd = strdup(buf);
+               if (!cmd)
+                       return -ENOMEM;
+       }
+       free(bflow->cmdline);
+       bflow->cmdline = cmd;
+
+       if (set_env) {
+               ret = env_set("bootargs", bflow->cmdline);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+int cmdline_get_arg(const char *cmdline, const char *arg, int *posp)
+{
+       int ret;
+
+       ret = cmdline_set_arg(NULL, 1, cmdline, arg, NULL, posp);
+
+       return ret;
+}
+
+int bootflow_cmdline_get_arg(struct bootflow *bflow, const char *arg,
+                            const char **val)
+{
+       int ret;
+       int pos;
+
+       ret = cmdline_get_arg(bflow->cmdline, arg, &pos);
+       if (ret < 0)
+               return ret;
+       *val = bflow->cmdline + pos;
+
+       return ret;
+}
+
+int bootflow_cmdline_auto(struct bootflow *bflow, const char *arg)
+{
+       struct serial_device_info info;
+       char buf[50];
+       int ret;
+
+       ret = serial_getinfo(gd->cur_serial_dev, &info);
+       if (ret)
+               return ret;
+
+       *buf = '\0';
+       if (!strcmp("earlycon", arg)) {
+               snprintf(buf, sizeof(buf),
+                        "uart8250,mmio32,%#lx,%dn8", info.addr,
+                        info.baudrate);
+       } else if (!strcmp("console", arg)) {
+               snprintf(buf, sizeof(buf),
+                        "ttyS0,%dn8", info.baudrate);
+       }
+
+       if (!*buf) {
+               printf("Unknown param '%s\n", arg);
+               return -ENOENT;
+       }
+
+       ret = bootflow_cmdline_set_arg(bflow, arg, buf, true);
+       if (ret)
+               return ret;
+
+       return 0;
+}
index 701ee8a..eeded08 100644 (file)
@@ -395,7 +395,7 @@ int bootmeth_common_read_file(struct udevice *dev, struct bootflow *bflow,
 /**
  * on_bootmeths() - Update the bootmeth order
  *
- * This will check for a valid baudrate and only apply it if valid.
+ * This will check for a valid list of bootmeths and only apply it if valid.
  */
 static int on_bootmeths(const char *name, const char *value, enum env_op op,
                        int flags)
diff --git a/boot/bootmeth_cros.c b/boot/bootmeth_cros.c
new file mode 100644 (file)
index 0000000..aa19ae0
--- /dev/null
@@ -0,0 +1,212 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Bootmethod for ChromiumOS
+ *
+ * Copyright 2023 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#define LOG_CATEGORY UCLASS_BOOTSTD
+
+#include <common.h>
+#include <blk.h>
+#include <bootdev.h>
+#include <bootflow.h>
+#include <bootmeth.h>
+#include <dm.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <part.h>
+#ifdef CONFIG_X86
+#include <asm/zimage.h>
+#endif
+#include <linux/sizes.h>
+
+enum {
+       /* Offsets in the kernel-partition header */
+       KERN_START      = 0x4f0,
+       KERN_SIZE       = 0x518,
+
+       SETUP_OFFSET    = 0x1000,       /* bytes before base */
+       CMDLINE_OFFSET  = 0x2000,       /* bytes before base */
+       OFFSET_BASE     = 0x100000,     /* assumed kernel load-address */
+};
+
+static int cros_check(struct udevice *dev, struct bootflow_iter *iter)
+{
+       /* This only works on block and network devices */
+       if (bootflow_iter_check_blk(iter))
+               return log_msg_ret("blk", -ENOTSUPP);
+
+       return 0;
+}
+
+static int copy_cmdline(const char *from, const char *uuid, char **bufp)
+{
+       const int maxlen = 2048;
+       char buf[maxlen];
+       char *cmd, *to, *end;
+       int len;
+
+       /* Allow space for cmdline + UUID */
+       len = strnlen(from, sizeof(buf));
+       if (len >= maxlen)
+               return -E2BIG;
+
+       log_debug("uuid %d %s\n", uuid ? (int)strlen(uuid) : 0, uuid);
+       for (to = buf, end = buf + maxlen - UUID_STR_LEN - 1; *from; from++) {
+               if (to >= end)
+                       return -E2BIG;
+               if (from[0] == '%' && from[1] == 'U' && uuid &&
+                   strlen(uuid) == UUID_STR_LEN) {
+                       strcpy(to, uuid);
+                       to += UUID_STR_LEN;
+                       from++;
+               } else {
+                       *to++ = *from;
+               }
+       }
+       *to = '\0';
+       len = to - buf;
+       cmd = strdup(buf);
+       if (!cmd)
+               return -ENOMEM;
+       free(*bufp);
+       *bufp = cmd;
+
+       return 0;
+}
+
+static int cros_read_bootflow(struct udevice *dev, struct bootflow *bflow)
+{
+       struct blk_desc *desc = dev_get_uclass_plat(bflow->blk);
+       ulong base, start, size, setup, cmdline, num_blks, kern_base;
+       struct disk_partition info;
+       const char *uuid = NULL;
+       void *buf, *hdr;
+       int ret;
+
+       log_debug("starting, part=%d\n", bflow->part);
+
+       /* We consider the whole disk, not any one partition */
+       if (bflow->part)
+               return log_msg_ret("max", -ENOENT);
+
+       /* Check partition 2 */
+       ret = part_get_info(desc, 2, &info);
+       if (ret)
+               return log_msg_ret("part", ret);
+
+       /* Make a buffer for the header information */
+       num_blks = SZ_4K >> desc->log2blksz;
+       log_debug("Reading header, blk=%s, start=%lx, blocks=%lx\n",
+                 bflow->blk->name, (ulong)info.start, num_blks);
+       hdr = memalign(SZ_1K, SZ_4K);
+       if (!hdr)
+               return log_msg_ret("hdr", -ENOMEM);
+       ret = blk_read(bflow->blk, info.start, num_blks, hdr);
+       if (ret != num_blks)
+               return log_msg_ret("inf", ret);
+
+       if (memcmp("CHROMEOS", hdr, 8))
+               return -ENOENT;
+
+       log_info("Header at %lx\n", (ulong)map_to_sysmem(hdr));
+       start = *(u32 *)(hdr + KERN_START);
+       size = ALIGN(*(u32 *)(hdr + KERN_SIZE), desc->blksz);
+       log_debug("Reading start %lx size %lx\n", start, size);
+       bflow->size = size;
+
+       buf = memalign(SZ_1K, size);
+       if (!buf)
+               return log_msg_ret("buf", -ENOMEM);
+       num_blks = size >> desc->log2blksz;
+       log_debug("Reading data, blk=%s, start=%lx, blocks=%lx\n",
+                 bflow->blk->name, (ulong)info.start, num_blks);
+       ret = blk_read(bflow->blk, (ulong)info.start + 0x80, num_blks, buf);
+       if (ret != num_blks)
+               return log_msg_ret("inf", ret);
+       base = map_to_sysmem(buf);
+
+       setup = base + start - OFFSET_BASE - SETUP_OFFSET;
+       cmdline = base + start - OFFSET_BASE - CMDLINE_OFFSET;
+       kern_base = base + start - OFFSET_BASE + SZ_16K;
+       log_debug("base %lx setup %lx, cmdline %lx, kern_base %lx\n", base,
+                 setup, cmdline, kern_base);
+
+#ifdef CONFIG_X86
+       const char *version;
+
+       version = zimage_get_kernel_version(map_sysmem(setup, 0),
+                                           map_sysmem(kern_base, 0));
+       log_debug("version %s\n", version);
+       if (version)
+               bflow->name = strdup(version);
+#endif
+       if (!bflow->name)
+               bflow->name = strdup("ChromeOS");
+       if (!bflow->name)
+               return log_msg_ret("nam", -ENOMEM);
+       bflow->os_name = strdup("ChromeOS");
+       if (!bflow->os_name)
+               return log_msg_ret("os", -ENOMEM);
+
+#if CONFIG_IS_ENABLED(PARTITION_UUIDS)
+       uuid = info.uuid;
+#endif
+       ret = copy_cmdline(map_sysmem(cmdline, 0), uuid, &bflow->cmdline);
+       if (ret)
+               return log_msg_ret("cmd", ret);
+
+       bflow->state = BOOTFLOWST_READY;
+       bflow->buf = buf;
+       bflow->x86_setup = map_sysmem(setup, 0);
+
+       return 0;
+}
+
+static int cros_read_file(struct udevice *dev, struct bootflow *bflow,
+                        const char *file_path, ulong addr, ulong *sizep)
+{
+       return -ENOSYS;
+}
+
+static int cros_boot(struct udevice *dev, struct bootflow *bflow)
+{
+#ifdef CONFIG_X86
+       zboot_start(map_to_sysmem(bflow->buf), bflow->size, 0, 0,
+                   map_to_sysmem(bflow->x86_setup),
+                   bflow->cmdline);
+#endif
+
+       return log_msg_ret("go", -EFAULT);
+}
+
+static int cros_bootmeth_bind(struct udevice *dev)
+{
+       struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev);
+
+       plat->desc = "ChromiumOS boot";
+
+       return 0;
+}
+
+static struct bootmeth_ops cros_bootmeth_ops = {
+       .check          = cros_check,
+       .read_bootflow  = cros_read_bootflow,
+       .read_file      = cros_read_file,
+       .boot           = cros_boot,
+};
+
+static const struct udevice_id cros_bootmeth_ids[] = {
+       { .compatible = "u-boot,cros" },
+       { }
+};
+
+U_BOOT_DRIVER(bootmeth_cros) = {
+       .name           = "bootmeth_cros",
+       .id             = UCLASS_BOOTMETH,
+       .of_match       = cros_bootmeth_ids,
+       .ops            = &cros_bootmeth_ops,
+       .bind           = cros_bootmeth_bind,
+};
index ecd4b08..8ebbc3e 100644 (file)
@@ -76,7 +76,7 @@ static int qfw_bootmeth_bind(struct udevice *dev)
 {
        struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev);
 
-       plat->desc = "Sandbox boot for testing";
+       plat->desc = "QEMU boot using firmware interface";
 
        return 0;
 }
index fd76972..ecfd575 100644 (file)
@@ -135,6 +135,14 @@ config CMD_BDI
        help
          Print board info
 
+config CMD_BDINFO_EXTRA
+       bool "bdinfo extra features"
+       default y if SANDBOX || X86
+       help
+         Show additional information about the board. This uses a little more
+         code space but provides more options, particularly those useful for
+         bringup, development and debugging.
+
 config CMD_CONFIG
        bool "config"
        default SANDBOX
index e70913e..ede9c8c 100644 (file)
@@ -118,6 +118,22 @@ static int do_acpi_list(struct cmd_tbl *cmdtp, int flag, int argc,
        return 0;
 }
 
+static int do_acpi_set(struct cmd_tbl *cmdtp, int flag, int argc,
+                      char *const argv[])
+{
+       ulong val;
+
+       if (argc < 2) {
+               printf("ACPI pointer: %lx\n", gd_acpi_start());
+       } else {
+               val = hextoul(argv[1], NULL);
+               printf("Setting ACPI pointer to %lx\n", val);
+               gd_set_acpi_start(val);
+       }
+
+       return 0;
+}
+
 static int do_acpi_items(struct cmd_tbl *cmdtp, int flag, int argc,
                         char *const argv[])
 {
@@ -157,12 +173,14 @@ static int do_acpi_dump(struct cmd_tbl *cmdtp, int flag, int argc,
 
 #ifdef CONFIG_SYS_LONGHELP
 static char acpi_help_text[] =
-       "list - list ACPI tables\n"
-       "acpi items [-d]  - List/dump each piece of ACPI data from devices\n"
-       "acpi dump <name> - Dump ACPI table";
+       "list  - list ACPI tables\n"
+       "acpi items [-d]   - List/dump each piece of ACPI data from devices\n"
+       "acpi set [<addr>] - Set or show address of ACPI tables\n"
+       "acpi dump <name>  - Dump ACPI table";
 #endif
 
 U_BOOT_CMD_WITH_SUBCMDS(acpi, "ACPI tables", acpi_help_text,
        U_BOOT_SUBCMD_MKENT(list, 1, 1, do_acpi_list),
        U_BOOT_SUBCMD_MKENT(items, 2, 1, do_acpi_items),
+       U_BOOT_SUBCMD_MKENT(set, 2, 1, do_acpi_set),
        U_BOOT_SUBCMD_MKENT(dump, 2, 1, do_acpi_dump));
index 365357c..1fe13ca 100644 (file)
@@ -13,6 +13,7 @@
 #include <lmb.h>
 #include <mapmem.h>
 #include <net.h>
+#include <serial.h>
 #include <video.h>
 #include <vsprintf.h>
 #include <asm/cache.h>
@@ -113,6 +114,25 @@ static void show_video_info(void)
        }
 }
 
+static void print_serial(struct udevice *dev)
+{
+       struct serial_device_info info;
+       int ret;
+
+       if (!dev || !IS_ENABLED(CONFIG_DM_SERIAL))
+               return;
+
+       ret = serial_getinfo(dev, &info);
+       if (ret)
+               return;
+
+       bdinfo_print_num_l("serial addr", info.addr);
+       bdinfo_print_num_l(" width", info.reg_width);
+       bdinfo_print_num_l(" shift", info.reg_shift);
+       bdinfo_print_num_l(" offset", info.reg_offset);
+       bdinfo_print_num_l(" clock", info.clock);
+}
+
 int do_bdinfo(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
        struct bd_info *bd = gd->bd;
@@ -151,6 +171,13 @@ int do_bdinfo(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
                if (IS_ENABLED(CONFIG_OF_REAL))
                        printf("devicetree  = %s\n", fdtdec_get_srcname());
        }
+       print_serial(gd->cur_serial_dev);
+
+       if (IS_ENABLED(CONFIG_CMD_BDINFO_EXTRA)) {
+               bdinfo_print_num_ll("stack ptr", (ulong)&bd);
+               bdinfo_print_num_ll("ram_top ptr", (ulong)gd->ram_top);
+               bdinfo_print_num_l("malloc base", gd_malloc_start());
+       }
 
        arch_print_bdinfo();
 
index 5c61286..c0aa4f8 100644 (file)
@@ -288,6 +288,12 @@ static int do_bootflow_select(struct cmd_tbl *cmdtp, int flag, int argc,
                return CMD_RET_FAILURE;
        }
        std->cur_bootflow = found;
+       if (IS_ENABLED(CONFIG_BOOTSTD_FULL)) {
+               if (env_set("bootargs", found->cmdline)) {
+                       printf("Cannot set bootargs\n");
+                       return CMD_RET_FAILURE;
+               }
+       }
 
        return 0;
 }
@@ -324,6 +330,14 @@ static int do_bootflow_info(struct cmd_tbl *cmdtp, int flag, int argc,
        printf("Buffer:    %lx\n", (ulong)map_to_sysmem(bflow->buf));
        printf("Size:      %x (%d bytes)\n", bflow->size, bflow->size);
        printf("OS:        %s\n", bflow->os_name ? bflow->os_name : "(none)");
+       printf("Cmdline:   ");
+       if (bflow->cmdline)
+               puts(bflow->cmdline);
+       else
+               puts("(none)");
+       putc('\n');
+       if (bflow->x86_setup)
+               printf("X86 setup: %p\n", bflow->x86_setup);
        printf("Logo:      %s\n", bflow->logo ?
               simple_xtoa((ulong)map_to_sysmem(bflow->logo)) : "(none)");
        if (bflow->logo) {
@@ -417,6 +431,75 @@ static int do_bootflow_menu(struct cmd_tbl *cmdtp, int flag, int argc,
 
        return 0;
 }
+
+static int do_bootflow_cmdline(struct cmd_tbl *cmdtp, int flag, int argc,
+                              char *const argv[])
+{
+       struct bootstd_priv *std;
+       struct bootflow *bflow;
+       const char *op, *arg, *val = NULL;
+       int ret;
+
+       if (argc < 3)
+               return CMD_RET_USAGE;
+
+       ret = bootstd_get_priv(&std);
+       if (ret)
+               return CMD_RET_FAILURE;
+
+       bflow = std->cur_bootflow;
+       if (!bflow) {
+               printf("No bootflow selected\n");
+               return CMD_RET_FAILURE;
+       }
+
+       op = argv[1];
+       arg = argv[2];
+       if (*op == 's') {
+               if (argc < 4)
+                       return CMD_RET_USAGE;
+               val = argv[3];
+       }
+
+       switch (*op) {
+       case 'c':       /* clear */
+               val = "";
+               fallthrough;
+       case 's':       /* set */
+       case 'd':       /* delete */
+               ret = bootflow_cmdline_set_arg(bflow, arg, val, true);
+               break;
+       case 'g':       /* get */
+               ret = bootflow_cmdline_get_arg(bflow, arg, &val);
+               if (ret >= 0)
+                       printf("%.*s\n", ret, val);
+               break;
+       case 'a':       /* auto */
+               ret = bootflow_cmdline_auto(bflow, arg);
+               break;
+       }
+       switch (ret) {
+       case -E2BIG:
+               printf("Argument too long\n");
+               break;
+       case -ENOENT:
+               printf("Argument not found\n");
+               break;
+       case -EINVAL:
+               printf("Mismatched quotes\n");
+               break;
+       case -EBADF:
+               printf("Value must be quoted\n");
+               break;
+       default:
+               if (ret < 0)
+                       printf("Unknown error: %dE\n", ret);
+       }
+       if (ret < 0)
+               return CMD_RET_FAILURE;
+
+       return 0;
+}
 #endif /* CONFIG_CMD_BOOTFLOW_FULL */
 
 #ifdef CONFIG_SYS_LONGHELP
@@ -427,7 +510,8 @@ static char bootflow_help_text[] =
        "bootflow select [<num>|<name>] - select a bootflow\n"
        "bootflow info [-d]             - show info on current bootflow (-d dump bootflow)\n"
        "bootflow boot                  - boot current bootflow (or first available if none selected)\n"
-       "bootflow menu [-t]             - show a menu of available bootflows";
+       "bootflow menu [-t]             - show a menu of available bootflows\n"
+       "bootflow cmdline [set|get|clear|delete|auto] <param> [<value>] - update cmdline";
 #else
        "scan - boot first available bootflow\n";
 #endif
@@ -441,5 +525,6 @@ U_BOOT_CMD_WITH_SUBCMDS(bootflow, "Boot flows", bootflow_help_text,
        U_BOOT_SUBCMD_MKENT(info, 2, 1, do_bootflow_info),
        U_BOOT_SUBCMD_MKENT(boot, 1, 1, do_bootflow_boot),
        U_BOOT_SUBCMD_MKENT(menu, 2, 1, do_bootflow_menu),
+       U_BOOT_SUBCMD_MKENT(cmdline, 4, 1, do_bootflow_cmdline),
 #endif
 );
index 28f2b7f..0ce1900 100644 (file)
@@ -182,6 +182,36 @@ static int do_part_number(int argc, char *const argv[])
        return do_part_info(argc, argv, CMD_PART_INFO_NUMBER);
 }
 
+static int do_part_set(int argc, char *const argv[])
+{
+       const char *devname, *partstr, *typestr;
+       struct blk_desc *desc;
+       int dev;
+
+       if (argc < 3)
+               return CMD_RET_USAGE;
+
+       /* Look up the device */
+       devname = argv[0];
+       partstr = argv[1];
+       typestr = argv[2];
+       dev = blk_get_device_by_str(devname, partstr, &desc);
+       if (dev < 0) {
+               printf("** Bad device specification %s %s **\n", devname,
+                      partstr);
+               return CMD_RET_FAILURE;
+       }
+
+       desc->part_type = part_get_type_by_name(typestr);
+       if (!desc->part_type) {
+               printf("Unknown partition type '%s'\n", typestr);
+               return CMD_RET_FAILURE;
+       }
+       part_print(desc);
+
+       return 0;
+}
+
 #ifdef CONFIG_PARTITION_TYPE_GUID
 static int do_part_type(int argc, char *const argv[])
 {
@@ -245,6 +275,8 @@ static int do_part(struct cmd_tbl *cmdtp, int flag, int argc,
                return do_part_number(argc - 2, argv + 2);
        else if (!strcmp(argv[1], "types"))
                return do_part_types(argc - 2, argv + 2);
+       else if (!strcmp(argv[1], "set"))
+               return do_part_set(argc - 2, argv + 2);
 #ifdef CONFIG_PARTITION_TYPE_GUID
        else if (!strcmp(argv[1], "type"))
                return do_part_type(argc - 2, argv + 2);
@@ -279,6 +311,8 @@ U_BOOT_CMD(
 #endif
        "part type <interface> <dev>:<part> <varname>\n"
        "    - set environment variable to partition type\n"
+       "part set <interface> <dev> type\n"
+       "    - set partition type for a device\n"
        "part types\n"
        "    - list supported partition table types"
 );
index ae3c6a7..d6ecfa6 100644 (file)
--- a/cmd/qfw.c
+++ b/cmd/qfw.c
@@ -26,7 +26,7 @@ static int qemu_fwcfg_cmd_list_firmware(void)
        for (file = qfw_file_iter_init(qfw_dev, &iter);
             !qfw_file_iter_end(&iter);
             file = qfw_file_iter_next(&iter)) {
-               printf("%-56s\n", file->cfg.name);
+               printf("%08lx %-56s\n", file->addr, file->cfg.name);
        }
 
        return 0;
index b1691d8..6ad7a12 100644 (file)
 #include <asm/mp.h>
 #include <asm/mtrr.h>
 
-static const char *const mtrr_type_name[MTRR_TYPE_COUNT] = {
-       "Uncacheable",
-       "Combine",
-       "2",
-       "3",
-       "Through",
-       "Protect",
-       "Back",
-};
-
-static void read_mtrrs(void *arg)
-{
-       struct mtrr_info *info = arg;
-
-       mtrr_read_all(info);
-}
-
-static int do_mtrr_list(int reg_count, int cpu_select)
-{
-       struct mtrr_info info;
-       int ret;
-       int i;
-
-       printf("Reg Valid Write-type   %-16s %-16s %-16s\n", "Base   ||",
-              "Mask   ||", "Size   ||");
-       memset(&info, '\0', sizeof(info));
-       ret = mp_run_on_cpus(cpu_select, read_mtrrs, &info);
-       if (ret)
-               return log_msg_ret("run", ret);
-       for (i = 0; i < reg_count; i++) {
-               const char *type = "Invalid";
-               uint64_t base, mask, size;
-               bool valid;
-
-               base = info.mtrr[i].base;
-               mask = info.mtrr[i].mask;
-               size = ~mask & ((1ULL << CONFIG_CPU_ADDR_BITS) - 1);
-               size |= (1 << 12) - 1;
-               size += 1;
-               valid = mask & MTRR_PHYS_MASK_VALID;
-               type = mtrr_type_name[base & MTRR_BASE_TYPE_MASK];
-               printf("%d   %-5s %-12s %016llx %016llx %016llx\n", i,
-                      valid ? "Y" : "N", type, base & ~MTRR_BASE_TYPE_MASK,
-                      mask & ~MTRR_PHYS_MASK_VALID, size);
-       }
-
-       return 0;
-}
-
 static int do_mtrr_set(int cpu_select, uint reg, int argc, char *const argv[])
 {
        const char *typename = argv[0];
        uint32_t start, size;
        uint64_t base, mask;
-       int i, type = -1;
+       int type = -1;
        bool valid;
        int ret;
 
        if (argc < 3)
                return CMD_RET_USAGE;
-       for (i = 0; i < MTRR_TYPE_COUNT; i++) {
-               if (*typename == *mtrr_type_name[i])
-                       type = i;
-       }
-       if (type == -1) {
+       type = mtrr_get_type_by_name(typename);
+       if (type < 0) {
                printf("Invalid type name %s\n", typename);
                return CMD_RET_USAGE;
        }
@@ -146,7 +94,7 @@ static int do_mtrr(struct cmd_tbl *cmdtp, int flag, int argc,
                        if (!first)
                                printf("\n");
                        printf("CPU %d:\n", i);
-                       ret = do_mtrr_list(reg_count, i);
+                       ret = mtrr_list(reg_count, i);
                        if (ret) {
                                printf("Failed to read CPU %s (err=%d)\n",
                                       i < MP_SELECT_ALL ? simple_itoa(i) : "",
index 0d63b6e..2144b10 100644 (file)
@@ -51,6 +51,7 @@ static struct tag_name {
 
        /* BLOBLISTT_PROJECT_AREA */
        { BLOBLISTT_U_BOOT_SPL_HANDOFF, "SPL hand-off" },
+       { BLOBLISTT_U_BOOT_VIDEO, "SPL video handoff" },
 
        /* BLOBLISTT_VENDOR_AREA */
 };
index 334d04a..e5969ec 100644 (file)
@@ -729,8 +729,7 @@ static int fix_fdt(void)
 #endif
 
 /* ARM calls relocate_code from its crt0.S */
-#if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX) && \
-               !CONFIG_IS_ENABLED(X86_64)
+#if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX)
 
 static int jump_to_copy(void)
 {
@@ -752,7 +751,11 @@ static int jump_to_copy(void)
         * (CPU cache)
         */
        arch_setup_gd(gd->new_gd);
-       board_init_f_r_trampoline(gd->start_addr_sp);
+# if CONFIG_IS_ENABLED(X86_64)
+               board_init_f_r_trampoline64(gd->new_gd, gd->start_addr_sp);
+# else
+               board_init_f_r_trampoline(gd->start_addr_sp);
+# endif
 #else
        relocate_code(gd->start_addr_sp, gd->new_gd, gd->relocaddr);
 #endif
@@ -967,8 +970,7 @@ static const init_fnc_t init_sequence_f[] = {
         * watchdog device is not serviced is as small as possible.
         */
        cyclic_unregister_all,
-#if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX) && \
-               !CONFIG_IS_ENABLED(X86_64)
+#if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX)
        jump_to_copy,
 #endif
        NULL,
index d798c00..4aaa894 100644 (file)
@@ -196,7 +196,7 @@ static int initr_barrier(void)
 
 static int initr_malloc(void)
 {
-       ulong malloc_start;
+       ulong start;
 
 #if CONFIG_VAL(SYS_MALLOC_F_LEN)
        debug("Pre-reloc malloc() used %#lx bytes (%ld KB)\n", gd->malloc_ptr,
@@ -207,8 +207,9 @@ static int initr_malloc(void)
         * This value MUST match the value of gd->start_addr_sp in board_f.c:
         * reserve_noncached().
         */
-       malloc_start = gd->relocaddr - TOTAL_MALLOC_LEN;
-       mem_malloc_init((ulong)map_sysmem(malloc_start, TOTAL_MALLOC_LEN),
+       start = gd->relocaddr - TOTAL_MALLOC_LEN;
+       gd_set_malloc_start(start);
+       mem_malloc_init((ulong)map_sysmem(start, TOTAL_MALLOC_LEN),
                        TOTAL_MALLOC_LEN);
        return 0;
 }
index 6f02a25..b2de57f 100644 (file)
@@ -437,7 +437,7 @@ int log_init(void)
        /*
         * We cannot add runtime data to the driver since it is likely stored
         * in rodata. Instead, set up a 'device' corresponding to each driver.
-        * We only support having a single device.
+        * We only support having a single device for each driver.
         */
        INIT_LIST_HEAD((struct list_head *)&gd->log_head);
        while (drv < end) {
index f1dcc04..bb091ce 100644 (file)
@@ -37,8 +37,14 @@ static int log_console_emit(struct log_device *ldev, struct log_rec *rec)
                        printf("%s:", rec->file);
                if (fmt & BIT(LOGF_LINE))
                        printf("%d-", rec->line);
-               if (fmt & BIT(LOGF_FUNC))
-                       printf("%*s()", CONFIG_LOGF_FUNC_PAD, rec->func);
+               if (fmt & BIT(LOGF_FUNC)) {
+                       if (CONFIG_IS_ENABLED(USE_TINY_PRINTF)) {
+                               printf("%s()", rec->func);
+                       } else {
+                               printf("%*s()", CONFIG_LOGF_FUNC_PAD,
+                                      rec->func);
+                       }
+               }
        }
        if (fmt & BIT(LOGF_MSG))
                printf("%s%s", add_space ? " " : "", rec->msg);
index f5995f2..fe61153 100644 (file)
@@ -1,5 +1,6 @@
 CONFIG_X86=y
 CONFIG_TEXT_BASE=0x1110000
+CONFIG_SYS_MALLOC_LEN=0x2000000
 CONFIG_SYS_MALLOC_F_LEN=0x3d00
 CONFIG_NR_DRAM_BANKS=8
 CONFIG_MAX_CPUS=8
@@ -22,6 +23,7 @@ CONFIG_X86_OFFSET_U_BOOT=0xffd00000
 CONFIG_X86_OFFSET_SPL=0xffe80000
 CONFIG_INTEL_ACPIGEN=y
 CONFIG_INTEL_GENERIC_WIFI=y
+CONFIG_BOOTSTD_FULL=y
 CONFIG_SYS_MONITOR_BASE=0x01110000
 CONFIG_CHROMEOS=y
 CONFIG_BOOTSTAGE=y
@@ -33,8 +35,10 @@ CONFIG_BOOTSTAGE_STASH=y
 CONFIG_USE_BOOTARGS=y
 CONFIG_BOOTARGS_SUBST=y
 CONFIG_USE_BOOTCOMMAND=y
-CONFIG_BOOTCOMMAND="tpm init; tpm startup TPM2_SU_CLEAR; read mmc 0:2 100000 0 80; setexpr loader *001004f0; setexpr size *00100518; setexpr blocks $size / 200; read mmc 0:2 100000 80 $blocks; setexpr setup $loader - 1000; setexpr cmdline_ptr $loader - 2000; setexpr.s cmdline *$cmdline_ptr; setexpr cmdline gsub %U \\\\${uuid}; if part uuid mmc 0:2 uuid; then zboot start 100000 0 0 0 $setup cmdline; zboot load; zboot setup; zboot dump; zboot go;fi"
+CONFIG_BOOTCOMMAND="tpm init; tpm startup TPM2_SU_CLEAR; bootflow scan -lb"
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
+CONFIG_LOG=y
+CONFIG_LOGF_FUNC=y
 CONFIG_DISPLAY_BOARDINFO_LATE=y
 CONFIG_LAST_STAGE_INIT=y
 CONFIG_BLOBLIST=y
@@ -52,9 +56,11 @@ CONFIG_SPL_POWER=y
 CONFIG_TPL_SYS_MALLOC_SIMPLE=y
 CONFIG_TPL_POWER=y
 CONFIG_HUSH_PARSER=y
-CONFIG_SYS_PBSIZE=532
+CONFIG_SYS_CBSIZE=1024
+CONFIG_SYS_PBSIZE=1024
 CONFIG_CMD_CPU=y
 CONFIG_CMD_PMC=y
+CONFIG_CMD_MEM_SEARCH=y
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_PART=y
index 0f3512d..fc93561 100644 (file)
@@ -1,5 +1,6 @@
 CONFIG_X86=y
 CONFIG_TEXT_BASE=0x1110000
+CONFIG_SYS_MALLOC_LEN=0x2000000
 CONFIG_NR_DRAM_BANKS=8
 CONFIG_ENV_SIZE=0x1000
 CONFIG_DEFAULT_DEVICE_TREE="coreboot"
@@ -8,12 +9,11 @@ CONFIG_VENDOR_COREBOOT=y
 CONFIG_TARGET_COREBOOT=y
 CONFIG_FIT=y
 CONFIG_FIT_SIGNATURE=y
+CONFIG_BOOTSTD_FULL=y
 CONFIG_SYS_MONITOR_BASE=0x01110000
 CONFIG_SHOW_BOOT_PROGRESS=y
 CONFIG_USE_BOOTARGS=y
 CONFIG_BOOTARGS="root=/dev/sdb3 init=/sbin/init rootwait ro"
-CONFIG_USE_BOOTCOMMAND=y
-CONFIG_BOOTCOMMAND="ext2load scsi 0:3 01000000 /boot/vmlinuz; zboot 01000000"
 CONFIG_PRE_CONSOLE_BUFFER=y
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_LOG=y
@@ -23,9 +23,6 @@ CONFIG_DISPLAY_BOARDINFO_LATE=y
 CONFIG_LAST_STAGE_INIT=y
 CONFIG_PCI_INIT_R=y
 CONFIG_HUSH_PARSER=y
-CONFIG_SYS_PBSIZE=532
-CONFIG_CMD_MEM_SEARCH=y
-CONFIG_CMD_IDE=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_PART=y
 CONFIG_CMD_USB=y
@@ -52,13 +49,6 @@ CONFIG_USE_ROOTPATH=y
 CONFIG_REGMAP=y
 CONFIG_SYSCON=y
 # CONFIG_ACPIGEN is not set
-CONFIG_SYS_IDE_MAXDEVICE=4
-CONFIG_SYS_ATA_DATA_OFFSET=0
-CONFIG_SYS_ATA_REG_OFFSET=0
-CONFIG_SYS_ATA_ALT_OFFSET=0
-CONFIG_ATAPI=y
-CONFIG_LBA48=y
-CONFIG_SYS_64BIT_LBA=y
 CONFIG_NVME_PCI=y
 # CONFIG_PCI_PNP is not set
 CONFIG_SOUND=y
index 6a539a8..4a15c51 100644 (file)
@@ -6,30 +6,39 @@ CONFIG_ENV_SIZE=0x40000
 CONFIG_MAX_CPUS=2
 CONFIG_SPL_DM_SPI=y
 CONFIG_DEFAULT_DEVICE_TREE="qemu-x86_i440fx"
-CONFIG_SPL_TEXT_BASE=0xfffd0000
+CONFIG_SPL_TEXT_BASE=0xfffd8000
+CONFIG_SPL_SYS_MALLOC_F_LEN=0x2000
 CONFIG_DEBUG_UART_BASE=0x3f8
 CONFIG_DEBUG_UART_CLOCK=1843200
 CONFIG_X86_RUN_64BIT=y
 CONFIG_TARGET_QEMU_X86_64=y
 CONFIG_DEBUG_UART=y
+# CONFIG_HAVE_MICROCODE is not set
 CONFIG_SMP=y
 CONFIG_GENERATE_PIRQ_TABLE=y
 CONFIG_GENERATE_MP_TABLE=y
 CONFIG_X86_OFFSET_U_BOOT=0xfff00000
 CONFIG_FIT=y
 CONFIG_SPL_LOAD_FIT=y
+CONFIG_BOOTSTD_FULL=y
 CONFIG_SYS_MONITOR_BASE=0x01110000
-CONFIG_DISTRO_DEFAULTS=y
+CONFIG_BOOTSTD_DEFAULTS=y
 CONFIG_BOOTSTAGE=y
 CONFIG_BOOTSTAGE_REPORT=y
 CONFIG_SHOW_BOOT_PROGRESS=y
 CONFIG_USE_BOOTARGS=y
 CONFIG_BOOTARGS="root=/dev/sdb3 init=/sbin/init rootwait ro"
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
+CONFIG_LOG=y
+CONFIG_LOGF_FUNC=y
+CONFIG_SPL_LOG=y
 CONFIG_DISPLAY_BOARDINFO_LATE=y
 CONFIG_LAST_STAGE_INIT=y
 CONFIG_PCI_INIT_R=y
+CONFIG_BLOBLIST=y
+CONFIG_BLOBLIST_ADDR=0x10000
 CONFIG_SPL_NO_BSS_LIMIT=y
+CONFIG_SPL_BOARD_INIT=y
 CONFIG_SPL_SYS_MALLOC_SIMPLE=y
 CONFIG_SPL_CPU=y
 CONFIG_SPL_ENV_SUPPORT=y
@@ -42,11 +51,13 @@ CONFIG_SYS_PBSIZE=532
 CONFIG_CMD_CPU=y
 CONFIG_CMD_BOOTEFI_SELFTEST=y
 CONFIG_CMD_NVEDIT_EFI=y
+CONFIG_CMD_MEM_SEARCH=y
 CONFIG_CMD_IDE=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_BOOTP_BOOTFILESIZE=y
+CONFIG_CMD_EFIDEBUG=y
 CONFIG_CMD_TIME=y
 CONFIG_CMD_QFW=y
 CONFIG_CMD_BOOTSTAGE=y
@@ -68,13 +79,13 @@ CONFIG_LBA48=y
 CONFIG_SYS_64BIT_LBA=y
 CONFIG_CPU=y
 CONFIG_NVME_PCI=y
+CONFIG_SPL_PCI_PNP=y
 CONFIG_SPL_DM_RTC=y
 CONFIG_SYS_NS16550_PORT_MAPPED=y
 CONFIG_SPI=y
 CONFIG_USB_KEYBOARD=y
-CONFIG_FRAMEBUFFER_SET_VESA_MODE=y
-CONFIG_FRAMEBUFFER_VESA_MODE_USER=y
-CONFIG_FRAMEBUFFER_VESA_MODE=0x144
 CONFIG_CONSOLE_SCROLL_LINES=5
+CONFIG_FAT_BLK_XLATE=y
+# CONFIG_SPL_USE_TINY_PRINTF is not set
 CONFIG_GENERATE_ACPI_TABLE=y
 # CONFIG_GZIP is not set
index a7c37b8..95a6ff9 100644 (file)
@@ -9,7 +9,7 @@ CONFIG_SMP=y
 CONFIG_GENERATE_PIRQ_TABLE=y
 CONFIG_GENERATE_MP_TABLE=y
 CONFIG_FIT=y
-CONFIG_DISTRO_DEFAULTS=y
+CONFIG_BOOTSTD_DEFAULTS=y
 CONFIG_BOOTSTAGE=y
 CONFIG_BOOTSTAGE_REPORT=y
 CONFIG_SHOW_BOOT_PROGRESS=y
@@ -53,9 +53,6 @@ CONFIG_NVME_PCI=y
 CONFIG_SYS_NS16550_PORT_MAPPED=y
 CONFIG_SPI=y
 CONFIG_USB_KEYBOARD=y
-CONFIG_FRAMEBUFFER_SET_VESA_MODE=y
-CONFIG_FRAMEBUFFER_VESA_MODE_USER=y
-CONFIG_FRAMEBUFFER_VESA_MODE=0x144
 CONFIG_CONSOLE_SCROLL_LINES=5
 CONFIG_GENERATE_ACPI_TABLE=y
 # CONFIG_GZIP is not set
index 2bc3bd9..3f588ea 100644 (file)
@@ -10,6 +10,7 @@ CONFIG_FIT=y
 CONFIG_TIMESTAMP=y
 CONFIG_FIT_SIGNATURE=y
 # CONFIG_BOOTSTD_FULL is not set
+# CONFIG_BOOTMETH_CROS is not set
 # CONFIG_BOOTMETH_VBE is not set
 CONFIG_USE_BOOTCOMMAND=y
 CONFIG_BOOTCOMMAND="run distro_bootcmd"
index 35300df..1d2117a 100644 (file)
@@ -54,6 +54,22 @@ static struct part_driver *part_driver_lookup_type(struct blk_desc *dev_desc)
        return NULL;
 }
 
+int part_get_type_by_name(const char *name)
+{
+       struct part_driver *drv =
+               ll_entry_start(struct part_driver, part_driver);
+       const int n_ents = ll_entry_count(struct part_driver, part_driver);
+       struct part_driver *entry;
+
+       for (entry = drv; entry != drv + n_ents; entry++) {
+               if (!strcasecmp(name, entry->name))
+                       return entry->part_type;
+       }
+
+       /* Not found */
+       return PART_TYPE_UNKNOWN;
+}
+
 static struct blk_desc *get_dev_hwpart(const char *ifname, int dev, int hwpart)
 {
        struct blk_desc *dev_desc;
index 14bafc8..6b9b894 100644 (file)
@@ -11,12 +11,14 @@ Synopis
     acpi list
     acpi items [-d]
     acpi dump <name>
+    acpi set <address>
 
 Description
 -----------
 
-The *acpi* command is used to dump the ACPI tables generated by U-Boot for passing
-to the operating systems.
+The *acpi* command is used to dump the ACPI tables generated by U-Boot for
+passing to the operating systems. It allows manually setting the address to take
+a look at existing ACPI tables.
 
 ACPI tables can be generated by various output functions and even devices can
 output material to include in the Differentiated System Description Table (DSDT)
@@ -231,5 +233,28 @@ Example
     00000000: 44 53 44 54 ea 32 00 00 02 eb 55 2d 42 4f 4f 54  DSDT.2....U-BOOT
     00000010: 55 2d 42 4f 4f 54 42 4c 25 07 11 20 49 4e 54 4c  U-BOOTBL%.. INTL
 
+This shows searching for tables in a known area of memory, then setting the
+pointer::
+
+    => acpi list
+    No ACPI tables present
+    => ms.s bff00000 80000 "RSD PTR"
+    bff75000: 52 53 44 20 50 54 52 20 cf 42 4f 43 48 53 20 00  RSD PTR .BOCHS .
+    1 match
+    => acpi set bff75000
+    Setting ACPI pointer to bff75000
+    => acpi list
+    Name      Base   Size  Detail
+    ----  --------  -----  ------
+    RSDP  bff75000      0  v00 BOCHS
+    RSDT  bff76a63     38  v01 BOCHS  BXPC     1 BXPC 1
+    FACP  bff768ff     74  v01 BOCHS  BXPC     1 BXPC 1
+    DSDT  bff75080   187f  v01 BOCHS  BXPC     1 BXPC 1
+    FACS  bff75040     40
+    APIC  bff76973     90  v01 BOCHS  BXPC     1 BXPC 1
+    HPET  bff76a03     38  v01 BOCHS  BXPC     1 BXPC 1
+    WAET  bff76a3b     28  v01 BOCHS  BXPC     1 BXPC 1
+    SSDT  bff95040     c5  v02 COREv4 COREBOOT 2a CORE 20221020
+
 
 .. _`ACPI specification`: https://uefi.org/sites/default/files/resources/ACPI_6_3_final_Jan30.pdf
index 8590efc..a8af1f8 100644 (file)
@@ -13,7 +13,7 @@ Synopis
     bootflow select [<num|name>]
     bootflow info [-d]
     bootflow boot
-
+    bootflow cmdline [set|get|clear|delete|auto] <param> [<value>]
 
 Description
 -----------
@@ -198,6 +198,36 @@ bootflow boot
 This boots the current bootflow.
 
 
+bootflow cmdline
+~~~~~~~~~~~~~~~~
+
+Some bootmeths can obtain the OS command line since it is stored with the OS.
+In that case, you can use `bootflow cmdline` to adjust this. The command line
+is assumed to be in the format used by Linux, i.e. a space-separated set of
+parameters with optional values, e.g. "noinitrd console=/dev/tty0".
+
+To change or add a parameter, use::
+
+    bootflow cmdline set <param> <value>
+
+To clear a parameter value to empty you can use "" for the value, or use::
+
+    bootflow cmdline clear <param>
+
+To delete a parameter entirely, use::
+
+    bootflow cmdline delete <param>
+
+Automatic parameters are available in a very few cases. You can use these to
+add parmeters where the value is known by U-Boot. For example::
+
+    bootflow cmdline auto earlycon
+    bootflow cmdline auto console
+
+can be used to set the early console (or console) to a suitable value so that
+output appears on the serial port. This is only supported by the 16550 serial
+driver so far.
+
 Example
 -------
 
@@ -258,7 +288,6 @@ displayed and booted::
     Name:      mmc@7e202000.bootdev.part_2
     Device:    mmc@7e202000.bootdev
     Block dev: mmc@7e202000.blk
-    Sequence:  1
     Method:    distro
     State:     ready
     Partition: 2
@@ -266,6 +295,10 @@ displayed and booted::
     Filename:  extlinux/extlinux.conf
     Buffer:    3db7ae88
     Size:      232 (562 bytes)
+    OS:        Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl)
+    Cmdline:   (none)
+    Logo:      (none)
+    FDT:       <NULL>
     Error:     0
     U-Boot> bootflow boot
     ** Booting bootflow 'smsc95xx_eth.bootdev.0'
@@ -427,6 +460,69 @@ Here is am example using the -e flag to see all errors::
     (21 bootflows, 2 valid)
     U-Boot>
 
+Here is an example of booting ChromeOS, adjusting the console beforehand. Note that
+the cmdline is word-wrapped here and some parts of the command line are elided::
+
+    => bootfl list
+    Showing all bootflows
+    Seq  Method       State   Uclass    Part  Name                      Filename
+    ---  -----------  ------  --------  ----  ------------------------  ----------------
+    0  cros         ready   nvme         0  5.10.153-20434-g98da1eb2c <NULL>
+    1  efi          ready   nvme         c  nvme#0.blk#1.bootdev.part efi/boot/bootia32.efi
+    2  efi          ready   usb_mass_    2  usb_mass_storage.lun0.boo efi/boot/bootia32.efi
+    ---  -----------  ------  --------  ----  ------------------------  ----------------
+    (3 bootflows, 3 valid)
+    => bootfl sel 0
+    => bootfl inf
+    Name:      5.10.153-20434-g98da1eb2cf9d (chrome-bot@chromeos-release-builder-us-central1-b-x32-12-xijx) #1 SMP PREEMPT Tue Jan 24 19:38:23 PST 2023
+    Device:    nvme#0.blk#1.bootdev
+    Block dev: nvme#0.blk#1
+    Method:    cros
+    State:     ready
+    Partition: 0
+    Subdir:    (none)
+    Filename:  <NULL>
+    Buffer:    737a1400
+    Size:      c47000 (12873728 bytes)
+    OS:        ChromeOS
+    Cmdline:   console= loglevel=7 init=/sbin/init cros_secure drm.trace=0x106
+        root=/dev/dm-0 rootwait ro dm_verity.error_behavior=3
+        dm_verity.max_bios=-1 dm_verity.dev_wait=1
+        dm="1 vroot none ro 1,0 6348800
+          verity payload=PARTUUID=799c935b-ae62-d143-8493-816fa936eef7/PARTNROFF=1
+          hashtree=PARTUUID=799c935b-ae62-d143-8493-816fa936eef7/PARTNROFF=1
+          hashstart=6348800 alg=sha256
+          root_hexdigest=78cc462cd45aecbcd49ca476587b4dee59aa1b00ba5ece58e2c29ec9acd914ab
+          salt=8dec4dc80a75dd834a9b3175c674405e15b16a253fdfe05c79394ae5fd76f66a"
+        noinitrd vt.global_cursor_default=0
+        kern_guid=799c935b-ae62-d143-8493-816fa936eef7 add_efi_memmap boot=local
+        noresume noswap i915.modeset=1 ramoops.ecc=1 tpm_tis.force=0
+        intel_pmc_core.warn_on_s0ix_failures=1 i915.enable_guc=3 i915.enable_dc=4
+        xdomain=0 swiotlb=65536 intel_iommu=on i915.enable_psr=1
+        usb-storage.quirks=13fe:6500:u
+    X86 setup: 742e3400
+    Logo:      (none)
+    FDT:       <NULL>
+    Error:     0
+    => bootflow cmdline auto earlycon
+    => bootflow cmd auto console
+    => print bootargs
+    bootargs=console=ttyS0,115200n8 loglevel=7 ...
+        usb-storage.quirks=13fe:6500:u earlycon=uart8250,mmio32,0xfe03e000,115200n8
+    => bootflow cmd del console
+    => print bootargs
+    bootargs=loglevel=7 ... earlycon=uart8250,mmio32,0xfe03e000,115200n8
+    => bootfl boot
+    ** Booting bootflow '5.10.153-20434-g98da1eb2cf9d (chrome-bot@chromeos-release-builder-us-central1-b-x32-12-xijx) #1 SMP PREEMPT Tue Jan 24 19:38:23 PST 2023' with cros
+    Kernel command line: "loglevel=7 ... earlycon=uart8250,mmio32,0xfe03e000,115200n8"
+
+    Starting kernel ...
+
+    [    0.000000] Linux version 5.10.153-20434-g98da1eb2cf9d (chrome-bot@chromeos-release-builder-us-central1-b-x32-12-xijx) (Chromium OS 15.0_pre465103_p20220825-r4 clang version 15.0.0 (/var/tmp/portage/sys-devel/llvm-15.0_pre465103_p20220825-r4/work/llvm-15.0_pre465103_p20220825/clang db1978b67431ca3462ad8935bf662c15750b8252), LLD 15.0.0) #1 SMP PREEMPT Tue Jan 24 19:38:23 PST 2023
+    [    0.000000] Command line: loglevel=7 ... usb-storage.quirks=13fe:6500:u earlycon=uart8250,mmio32,0xfe03e000,115200n8
+    [    0.000000] x86/split lock detection: warning about user-space split_locks
+
+
 
 Return value
 ------------
diff --git a/doc/usage/cmd/mtrr.rst b/doc/usage/cmd/mtrr.rst
new file mode 100644 (file)
index 0000000..531153b
--- /dev/null
@@ -0,0 +1,151 @@
+.. SPDX-License-Identifier: GPL-2.0+:
+
+mtrr command
+============
+
+Synopis
+-------
+
+    mtrr [list]
+    mtrr set <reg> <type> <start> <size>
+    mtrr disable <reg>
+    mtrr enable
+
+
+Description
+-----------
+
+The *mtrr* command is used to dump the Memory Type Range Registers (MTRRs) on
+an x86 machine. These register control cache behaviour in selected memory
+ranges.
+
+Note that the number of registers can vary between CPUs.
+
+
+mtrr [list]
+~~~~~~~~~~~
+
+List the MTRRs. The table shows the following information:
+
+Reg
+    Register number (the first is register 0)
+
+Valid
+    Shows Y if the register is valid (has bit 11 set), N if not
+
+Write-type
+    Shows the behaviour when writing to the memory region. The types are
+    abbreviated to fit a reasonable line length. Valid types shown below.
+
+    ======  ==============  ====================================================
+    Value   Type            Meaning
+    ======  ==============  ====================================================
+    0       Uncacheable     Skip cache and write directly to memory
+    1       Combine         Multiple writes can be combined into one transaction
+    4       Through         Update cache and also write to memory
+    5       Protect         Writes are prohibited
+    6       Back            Update cache but don't write to memory
+    ======  ==============  ====================================================
+
+Base
+    Base memory address from which the register controls behaviour
+
+Mask
+    Mask value, which also indicates the size
+
+Size
+    Length of memory region within which the register controls behaviour
+
+
+mtrr set
+~~~~~~~~
+
+This sets the value of a particular MTRR. Parameters are:
+
+reg
+    Register number to set, with 0 being the first
+
+type
+    Access type to set. See Write-type above for valid types. This uses the name
+    rather than its numeric value.
+
+start
+    Base memory address from which the register should control behaviour
+
+size
+    Length of memory region within which the register controls behaviour
+
+
+mtrr disable
+~~~~~~~~~~~~
+
+This disables a particular register, by clearing its `valid` bit (11).
+
+
+mtrr enable
+~~~~~~~~~~~
+
+This enables a particular register, by setting its `valid` bit (11).
+
+
+Example
+-------
+
+This shows disabling and enabling an MTRR, as well as setting its type::
+
+    => mtrr
+    CPU 0:
+    Reg Valid Write-type   Base   ||        Mask   ||        Size   ||
+    0   Y     Back         0000000000000000 0000000f80000000 0000000080000000
+    1   Y     Back         0000000080000000 0000000fe0000000 0000000020000000
+    2   Y     Back         00000000a0000000 0000000ff0000000 0000000010000000
+    3   Y     Uncacheable  00000000ad000000 0000000fff000000 0000000001000000
+    4   Y     Uncacheable  00000000ae000000 0000000ffe000000 0000000002000000
+    5   Y     Combine      00000000d0000000 0000000ff0000000 0000000010000000
+    6   N     Uncacheable  0000000000000000 0000000000000000 0000001000000000
+    7   N     Uncacheable  0000000000000000 0000000000000000 0000001000000000
+    8   N     Uncacheable  0000000000000000 0000000000000000 0000001000000000
+    9   N     Uncacheable  0000000000000000 0000000000000000 0000001000000000
+    => mtrr d 5
+    => mtrr
+    CPU 0:
+    Reg Valid Write-type   Base   ||        Mask   ||        Size   ||
+    0   Y     Back         0000000000000000 0000000f80000000 0000000080000000
+    1   Y     Back         0000000080000000 0000000fe0000000 0000000020000000
+    2   Y     Back         00000000a0000000 0000000ff0000000 0000000010000000
+    3   Y     Uncacheable  00000000ad000000 0000000fff000000 0000000001000000
+    4   Y     Uncacheable  00000000ae000000 0000000ffe000000 0000000002000000
+    5   N     Combine      00000000d0000000 0000000ff0000000 0000000010000000
+    6   N     Uncacheable  0000000000000000 0000000000000000 0000001000000000
+    7   N     Uncacheable  0000000000000000 0000000000000000 0000001000000000
+    8   N     Uncacheable  0000000000000000 0000000000000000 0000001000000000
+    9   N     Uncacheable  0000000000000000 0000000000000000 0000001000000000
+    => mtrr e 5
+    => mtrr
+    CPU 0:
+    Reg Valid Write-type   Base   ||        Mask   ||        Size   ||
+    0   Y     Back         0000000000000000 0000000f80000000 0000000080000000
+    1   Y     Back         0000000080000000 0000000fe0000000 0000000020000000
+    2   Y     Back         00000000a0000000 0000000ff0000000 0000000010000000
+    3   Y     Uncacheable  00000000ad000000 0000000fff000000 0000000001000000
+    4   Y     Uncacheable  00000000ae000000 0000000ffe000000 0000000002000000
+    5   Y     Combine      00000000d0000000 0000000ff0000000 0000000010000000
+    6   N     Uncacheable  0000000000000000 0000000000000000 0000001000000000
+    7   N     Uncacheable  0000000000000000 0000000000000000 0000001000000000
+    8   N     Uncacheable  0000000000000000 0000000000000000 0000001000000000
+    9   N     Uncacheable  0000000000000000 0000000000000000 0000001000000000
+    => mtrr set 5 Uncacheable d0000000 10000000
+    => mtrr
+    CPU 0:
+    Reg Valid Write-type   Base   ||        Mask   ||        Size   ||
+    0   Y     Back         0000000000000000 0000000f80000000 0000000080000000
+    1   Y     Back         0000000080000000 0000000fe0000000 0000000020000000
+    2   Y     Back         00000000a0000000 0000000ff0000000 0000000010000000
+    3   Y     Uncacheable  00000000ad000000 0000000fff000000 0000000001000000
+    4   Y     Uncacheable  00000000ae000000 0000000ffe000000 0000000002000000
+    5   Y     Uncacheable  00000000d0000000 0000000ff0000000 0000000010000000
+    6   N     Uncacheable  0000000000000000 0000000000000000 0000001000000000
+    7   N     Uncacheable  0000000000000000 0000000000000000 0000001000000000
+    8   N     Uncacheable  0000000000000000 0000000000000000 0000001000000000
+    9   N     Uncacheable  0000000000000000 0000000000000000 0000001000000000
+    =>
index 8d2a280..8a594aa 100644 (file)
@@ -13,6 +13,7 @@ Synopis
     part start <interface> <dev> <part> <varname>
     part size <interface> <dev> <part> <varname>
     part number <interface> <dev> <part> <varname>
+    part set <interface> <dev> <part> <type>
     part type <interface> <dev>:<part> [varname]
     part types
 
@@ -82,6 +83,18 @@ part must be specified as partition name.
     varname
         a variable to store the current partition number value into
 
+The 'part set' command sets the type of a partition. This is useful when
+autodetection fails or does not do the correct thing:
+
+    interface
+        interface for accessing the block device (mmc, sata, scsi, usb, ....)
+    dev
+        device number
+    part
+        partition number
+    type
+        partition type to use (see 'part types') to check available types
+
 The 'part type' command prints or sets an environment variable to the partition type UUID.
 
     interface
@@ -147,6 +160,67 @@ Examples
     => part types
     Supported partition tables: EFI, AMIGA, DOS, ISO, MAC
 
+This shows looking at a device with multiple partition tables::
+
+    => virtio scan
+    => part list virtio 0
+
+    Partition Map for VirtIO device 0  --   Partition Type: EFI
+
+    Part       Start LBA       End LBA         Name
+            Attributes
+            Type GUID
+            Partition GUID
+    1  0x00000040      0x0092b093      "ISO9660"
+            attrs:     0x1000000000000001
+            type:      ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
+            guid:      a0891d7e-b930-4513-94d8-f629dbd637b2
+    2  0x0092b094      0x0092d7e7      "Appended2"
+            attrs:     0x0000000000000000
+            type:      c12a7328-f81f-11d2-ba4b-00a0c93ec93b
+            guid:      a0891d7e-b930-4513-94db-f629dbd637b2
+    3  0x0092d7e8      0x0092da3f      "Gap1"
+            attrs:     0x1000000000000001
+            type:      ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
+            guid:      a0891d7e-b930-4513-94da-f629dbd637b2
+    => ls virtio 0:3
+    => part types
+    Supported partition tables: EFI, DOS, ISO
+    => part set virtio 0 dos
+
+    Partition Map for VirtIO device 0  --   Partition Type: DOS
+
+    Part       Start Sector    Num Sectors     UUID            Type
+    1  1               9624191         00000000-01     ee
+    => part set virtio 0 iso
+
+    Partition Map for VirtIO device 0  --   Partition Type: ISO
+
+    Part   Start     Sect x Size Type
+    1     3020        4    512 U-Boot
+    2  9613460    10068    512 U-Boot
+    => part set virtio 0 efi
+
+    Partition Map for VirtIO device 0  --   Partition Type: EFI
+
+    Part       Start LBA       End LBA         Name
+            Attributes
+            Type GUID
+            Partition GUID
+    1  0x00000040      0x0092b093      "ISO9660"
+            attrs:     0x1000000000000001
+            type:      ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
+            guid:      a0891d7e-b930-4513-94d8-f629dbd637b2
+    2  0x0092b094      0x0092d7e7      "Appended2"
+            attrs:     0x0000000000000000
+            type:      c12a7328-f81f-11d2-ba4b-00a0c93ec93b
+            guid:      a0891d7e-b930-4513-94db-f629dbd637b2
+    3  0x0092d7e8      0x0092da3f      "Gap1"
+            attrs:     0x1000000000000001
+            type:      ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
+            guid:      a0891d7e-b930-4513-94da-f629dbd637b2
+    =>
+
 Return value
 ------------
 
index cc0e27c..ec13e09 100644 (file)
@@ -41,18 +41,21 @@ QEMU firmware files are listed via the *qfw list* command:
 ::
 
     => qfw list
-    etc/boot-fail-wait
-    etc/smbios/smbios-tables
-    etc/smbios/smbios-anchor
-    etc/e820
-    genroms/kvmvapic.bin
-    genroms/linuxboot.bin
-    etc/system-states
-    etc/acpi/tables
-    etc/table-loader
-    etc/tpm/log
-    etc/acpi/rsdp
-    bootorder
+    00000000 bios-geometry
+    00000000 bootorder
+    000f0060 etc/acpi/rsdp
+    bed14040 etc/acpi/tables
+    00000000 etc/boot-fail-wait
+    00000000 etc/e820
+    00000000 etc/smbios/smbios-anchor
+    00000000 etc/smbios/smbios-tables
+    00000000 etc/system-states
+    00000000 etc/table-loader
+    00000000 etc/tpm/log
+    00000000 genroms/kvmvapic.bin
+
+Where an address is shown, it indicates where the data is available for
+inspection, e.g. using the :doc:`md`.
 
 The available CPUs can be shown via the *qfw cpus* command:
 
index f2ffd27..072db53 100644 (file)
@@ -76,6 +76,7 @@ Shell commands
    cmd/md
    cmd/mmc
    cmd/mtest
+   cmd/mtrr
    cmd/panic
    cmd/part
    cmd/pause
index 75937fb..a25f6ae 100644 (file)
@@ -10,6 +10,8 @@ source "drivers/ata/Kconfig"
 
 source "drivers/axi/Kconfig"
 
+source "drivers/bios_emulator/Kconfig"
+
 source "drivers/bus/Kconfig"
 
 source "drivers/block/Kconfig"
index 78dcf62..3bc6d27 100644 (file)
@@ -1,5 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0+
 
+obj-$(CONFIG_$(SPL_TPL_)BIOSEMU) += bios_emulator/
 obj-$(CONFIG_$(SPL_TPL_)BLK) += block/
 obj-$(CONFIG_$(SPL_TPL_)BOOTCOUNT_LIMIT) += bootcount/
 obj-$(CONFIG_$(SPL_TPL_)BUTTON) += button/
@@ -80,7 +81,6 @@ ifeq ($(CONFIG_SPL_BUILD)$(CONFIG_TPL_BUILD),)
 obj-y += adc/
 obj-y += ata/
 obj-$(CONFIG_DM_DEMO) += demo/
-obj-$(CONFIG_BIOSEMU) += bios_emulator/
 obj-y += block/
 obj-y += cache/
 obj-$(CONFIG_CPU) += cpu/
diff --git a/drivers/bios_emulator/Kconfig b/drivers/bios_emulator/Kconfig
new file mode 100644 (file)
index 0000000..3660576
--- /dev/null
@@ -0,0 +1,10 @@
+config BIOSEMU
+       bool
+       select X86EMU_RAW_IO
+
+config SPL_BIOSEMU
+       bool
+       select X86EMU_RAW_IO
+
+config X86EMU_RAW_IO
+       bool
index 7853015..954cd88 100644 (file)
@@ -128,19 +128,19 @@ typedef struct {
        u32 finalVal;
 } BE_portInfo;
 
-#define PM_inpb(port)  inb(port+VIDEO_IO_OFFSET)
-#define PM_inpw(port)  inw(port+VIDEO_IO_OFFSET)
-#define PM_inpd(port)  inl(port+VIDEO_IO_OFFSET)
-#define PM_outpb(port,val)     outb(val,port+VIDEO_IO_OFFSET)
-#define PM_outpw(port,val)     outw(val,port+VIDEO_IO_OFFSET)
-#define PM_outpd(port,val)     outl(val,port+VIDEO_IO_OFFSET)
+#define PM_inpb(port)  inb(port)
+#define PM_inpw(port)  inw(port)
+#define PM_inpd(port)  inl(port)
+#define PM_outpb(port, val)    outb(val, port)
+#define PM_outpw(port, val)    outw(val, port)
+#define PM_outpd(port, val)    outl(val, port)
 
 #define LOG_inpb(port) PM_inpb(port)
 #define LOG_inpw(port) PM_inpw(port)
 #define LOG_inpd(port) PM_inpd(port)
-#define LOG_outpb(port,val)    PM_outpb(port,val)
-#define LOG_outpw(port,val)    PM_outpw(port,val)
-#define LOG_outpd(port,val)    PM_outpd(port,val)
+#define LOG_outpb(port, val)   PM_outpb(port, val)
+#define LOG_outpw(port, val)   PM_outpw(port, val)
+#define LOG_outpd(port, val)   PM_outpd(port, val)
 
 /*-------------------------- Function Prototypes --------------------------*/
 
index c2db121..882a8a3 100644 (file)
@@ -44,6 +44,7 @@
 
 /*------------------------- Global Variables ------------------------------*/
 
+/* Note: bios.c defines this if the emulator is not enabled */
 X86EMU_sysEnv _X86EMU_env;     /* Global emulator machine state */
 X86EMU_intrFuncs _X86EMU_intrTab[256];
 
index 63a07b9..2ed0d0b 100644 (file)
@@ -26,6 +26,8 @@
  * reserved or subject to arcane restrictions.
  */
 
+#define LOG_CATEGORY   UCLASS_GPIO
+
 #include <common.h>
 #include <dm.h>
 #include <errno.h>
@@ -155,8 +157,7 @@ static int ich6_gpio_request(struct udevice *dev, unsigned offset,
         */
        tmplong = inl(bank->use_sel);
        if (!(tmplong & (1UL << offset))) {
-               debug("%s: gpio %d is reserved for internal use\n", __func__,
-                     offset);
+               log_debug("gpio %d is reserved for internal use\n", offset);
                return -EPERM;
        }
 
index 9ef95ca..7c01bf2 100644 (file)
@@ -18,6 +18,7 @@
 #include <dm.h>
 #include <misc.h>
 #include <tables_csum.h>
+#include <asm/acpi_table.h>
 
 #if defined(CONFIG_GENERATE_ACPI_TABLE) && !defined(CONFIG_SANDBOX)
 /*
@@ -64,6 +65,11 @@ static int bios_linker_allocate(struct udevice *dev,
                        printf("error: allocating resource\n");
                        return -ENOMEM;
                }
+               if (aligned_addr < gd->arch.table_start_high)
+                       gd->arch.table_start_high = aligned_addr;
+               if (aligned_addr + size > gd->arch.table_end_high)
+                       gd->arch.table_end_high = aligned_addr + size;
+
        } else if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG) {
                aligned_addr = ALIGN(*addr, align);
        } else {
@@ -188,6 +194,10 @@ ulong write_acpi_tables(ulong addr)
                return addr;
        }
 
+       /* QFW always puts tables at high addresses */
+       gd->arch.table_start_high = (ulong)table_loader;
+       gd->arch.table_end_high = (ulong)table_loader;
+
        qfw_read_entry(dev, be16_to_cpu(file->cfg.select), size, table_loader);
 
        for (i = 0; i < (size / sizeof(*entry)); i++) {
@@ -227,6 +237,9 @@ out:
        }
 
        free(table_loader);
+
+       gd_set_acpi_start(acpi_get_rsdp_addr());
+
        return addr;
 }
 
index b57b8a6..55ecead 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * Bootdevice for MMC
+ * Bootdev for MMC
  *
  * Copyright 2021 Google LLC
  * Written by Simon Glass <sjg@chromium.org>
index 74e7a5b..a7add66 100644 (file)
@@ -578,17 +578,22 @@ static int nvme_set_queue_count(struct nvme_dev *dev, int count)
        return min(result & 0xffff, result >> 16) + 1;
 }
 
-static void nvme_create_io_queues(struct nvme_dev *dev)
+static int nvme_create_io_queues(struct nvme_dev *dev)
 {
        unsigned int i;
+       int ret;
 
        for (i = dev->queue_count; i <= dev->max_qid; i++)
                if (!nvme_alloc_queue(dev, i, dev->q_depth))
-                       break;
+                       return log_msg_ret("all", -ENOMEM);
 
-       for (i = dev->online_queues; i <= dev->queue_count - 1; i++)
-               if (nvme_create_queue(dev->queues[i], i))
-                       break;
+       for (i = dev->online_queues; i <= dev->queue_count - 1; i++) {
+               ret = nvme_create_queue(dev->queues[i], i);
+               if (ret)
+                       return log_msg_ret("cre", ret);
+       }
+
+       return 0;
 }
 
 static int nvme_setup_io_queues(struct nvme_dev *dev)
@@ -598,14 +603,18 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
 
        nr_io_queues = 1;
        result = nvme_set_queue_count(dev, nr_io_queues);
-       if (result <= 0)
+       if (result <= 0) {
+               log_debug("Cannot set queue count (err=%dE)\n", result);
                return result;
+       }
 
        dev->max_qid = nr_io_queues;
 
        /* Free previously allocated queues */
        nvme_free_queues(dev, nr_io_queues + 1);
-       nvme_create_io_queues(dev);
+       result = nvme_create_io_queues(dev);
+       if (result)
+               return result;
 
        return 0;
 }
@@ -683,8 +692,11 @@ int nvme_scan_namespace(void)
 
        uclass_foreach_dev(dev, uc) {
                ret = device_probe(dev);
-               if (ret)
+               if (ret) {
+                       log_err("Failed to probe '%s': err=%dE\n", dev->name,
+                               ret);
                        return ret;
+               }
        }
 
        return 0;
@@ -842,8 +854,10 @@ int nvme_init(struct udevice *udev)
        ndev->dbs = ((void __iomem *)ndev->bar) + 4096;
 
        ret = nvme_configure_admin_queue(ndev);
-       if (ret)
+       if (ret) {
+               log_debug("Unable to configure admin queue (err=%dE)\n", ret);
                goto free_queue;
+       }
 
        /* Allocate after the page size is known */
        ndev->prp_pool = memalign(ndev->page_size, MAX_PRP_POOL);
@@ -855,8 +869,10 @@ int nvme_init(struct udevice *udev)
        ndev->prp_entry_num = MAX_PRP_POOL >> 3;
 
        ret = nvme_setup_io_queues(ndev);
-       if (ret)
+       if (ret) {
+               log_debug("Unable to setup I/O queues(err=%dE)\n", ret);
                goto free_queue;
+       }
 
        nvme_get_info_from_identify(ndev);
 
index 3bd0115..3137eb2 100644 (file)
@@ -3,6 +3,8 @@
  * Copyright (C) 2014 Google, Inc
  */
 
+#define LOG_CATEGORY   UCLASS_PCH
+
 #include <common.h>
 #include <dm.h>
 #include <log.h>
@@ -38,7 +40,7 @@ static int pch9_get_gpio_base(struct udevice *dev, u32 *gbasep)
         */
        dm_pci_read_config32(dev, GPIO_BASE, &base);
        if (base == 0x00000000 || base == 0xffffffff) {
-               debug("%s: unexpected BASE value\n", __func__);
+               log_debug("unexpected BASE value\n");
                return -ENODEV;
        }
 
@@ -59,7 +61,7 @@ static int pch9_get_io_base(struct udevice *dev, u32 *iobasep)
 
        dm_pci_read_config32(dev, IO_BASE, &base);
        if (base == 0x00000000 || base == 0xffffffff) {
-               debug("%s: unexpected BASE value\n", __func__);
+               log_debug("unexpected BASE value\n");
                return -ENODEV;
        }
 
index 84a2ae9..aca439d 100644 (file)
@@ -44,8 +44,13 @@ config SPL_PCI_PNP
        bool "Enable Plug & Play support for PCI"
        help
          Enable PCI memory and I/O space resource allocation and assignment.
+
          This is required to auto configure the enumerated devices.
 
+         This is normally not done in SPL, but can be enabled if devices must
+         be set up in the SPL phase. Often it is enough to manually configure
+         one device, so this option can be disabled.
+
 config PCI_REGION_MULTI_ENTRY
        bool "Enable Multiple entries of region type MEMORY in ranges for PCI"
        help
index 8d27e40..632c1a6 100644 (file)
@@ -13,6 +13,7 @@
 #include <log.h>
 #include <malloc.h>
 #include <pci.h>
+#include <spl.h>
 #include <asm/global_data.h>
 #include <asm/io.h>
 #include <dm/device-internal.h>
@@ -722,6 +723,9 @@ static bool pci_need_device_pre_reloc(struct udevice *bus, uint vendor,
        u32 vendev;
        int index;
 
+       if (spl_phase() == PHASE_SPL && CONFIG_IS_ENABLED(PCI_PNP))
+               return true;
+
        for (index = 0;
             !dev_read_u32_index(bus, "u-boot,pci-pre-reloc", index,
                                 &vendev);
@@ -793,7 +797,9 @@ static int pci_find_and_bind_driver(struct udevice *parent,
                         * space is pretty limited (ie: using Cache As RAM).
                         */
                        if (!(gd->flags & GD_FLG_RELOC) &&
-                           !(drv->flags & DM_FLAG_PRE_RELOC))
+                           !(drv->flags & DM_FLAG_PRE_RELOC) &&
+                           (!CONFIG_IS_ENABLED(PCI_PNP) ||
+                            spl_phase() != PHASE_SPL))
                                return log_msg_ret("pre", -EPERM);
 
                        /*
@@ -918,6 +924,8 @@ int pci_bind_bus_devices(struct udevice *bus)
                        }
                        ret = pci_find_and_bind_driver(bus, &find_id, bdf,
                                                       &dev);
+               } else {
+                       debug("device: %s\n", dev->name);
                }
                if (ret == -EPERM)
                        continue;
index f0dfe63..438583a 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <common.h>
 #include <bios_emul.h>
+#include <bloblist.h>
 #include <bootstage.h>
 #include <dm.h>
 #include <errno.h>
@@ -34,6 +35,7 @@
 #include <malloc.h>
 #include <pci.h>
 #include <pci_rom.h>
+#include <spl.h>
 #include <vesa.h>
 #include <video.h>
 #include <acpi/acpi_s3.h>
@@ -91,6 +93,7 @@ static int pci_rom_probe(struct udevice *dev, struct pci_rom_header **hdrp)
                debug("%s: rom_address=%x\n", __func__, rom_address);
                return -ENOENT;
        }
+       rom_address &= PCI_ROM_ADDRESS_MASK;
 
        /* Enable expansion ROM address decoding. */
        dm_pci_write_config32(dev, PCI_ROM_ADDRESS,
@@ -254,14 +257,16 @@ int dm_pci_run_vga_bios(struct udevice *dev, int (*int15_handler)(void),
 
        ret = pci_rom_probe(dev, &rom);
        if (ret)
-               return ret;
+               return log_msg_ret("pro", ret);
 
        ret = pci_rom_load(rom, &ram, &alloced);
-       if (ret)
+       if (ret) {
+               ret = log_msg_ret("ld", ret);
                goto err;
+       }
 
        if (!board_should_run_oprom(dev)) {
-               ret = -ENXIO;
+               ret = log_msg_ret("run", -ENXIO);
                goto err;
        }
 
@@ -269,7 +274,7 @@ int dm_pci_run_vga_bios(struct udevice *dev, int (*int15_handler)(void),
                defined(CONFIG_FRAMEBUFFER_VESA_MODE)
        vesa_mode = CONFIG_FRAMEBUFFER_VESA_MODE;
 #endif
-       debug("Selected vesa mode %#x\n", vesa_mode);
+       debug("Selected vesa mode 0x%x\n", vesa_mode);
 
        if (exec_method & PCI_ROM_USE_NATIVE) {
 #ifdef CONFIG_X86
@@ -296,27 +301,31 @@ int dm_pci_run_vga_bios(struct udevice *dev, int (*int15_handler)(void),
        }
 
        if (emulate) {
-#ifdef CONFIG_BIOSEMU
-               BE_VGAInfo *info;
-
-               ret = biosemu_setup(dev, &info);
-               if (ret)
-                       goto err;
-               biosemu_set_interrupt_handler(0x15, int15_handler);
-               ret = biosemu_run(dev, (uchar *)ram, 1 << 16, info,
-                                 true, vesa_mode, &mode_info);
-               if (ret)
-                       goto err;
-#endif
+               if (CONFIG_IS_ENABLED(BIOSEMU)) {
+                       BE_VGAInfo *info;
+
+                       log_debug("Running video BIOS with emulator...");
+                       ret = biosemu_setup(dev, &info);
+                       if (ret)
+                               goto err;
+                       biosemu_set_interrupt_handler(0x15, int15_handler);
+                       ret = biosemu_run(dev, (uchar *)ram, 1 << 16, info,
+                                         true, vesa_mode, &mode_info);
+                       log_debug("done\n");
+                       if (ret)
+                               goto err;
+               }
        } else {
 #if defined(CONFIG_X86) && (CONFIG_IS_ENABLED(X86_32BIT_INIT) || CONFIG_TPL)
+               log_debug("Running video BIOS...");
                bios_set_interrupt_handler(0x15, int15_handler);
 
                bios_run_on_x86(dev, (unsigned long)ram, vesa_mode,
                                &mode_info);
+               log_debug("done\n");
 #endif
        }
-       debug("Final vesa mode %#x\n", mode_info.video_mode);
+       debug("Final vesa mode %x\n", mode_info.video_mode);
        ret = 0;
 
 err:
@@ -368,34 +377,68 @@ int vesa_setup_video(struct udevice *dev, int (*int15_handler)(void))
                printf("Not available (previous bootloader prevents it)\n");
                return -EPERM;
        }
-       bootstage_start(BOOTSTAGE_ID_ACCUM_LCD, "vesa display");
-       ret = dm_pci_run_vga_bios(dev, int15_handler, PCI_ROM_USE_NATIVE |
-                                       PCI_ROM_ALLOW_FALLBACK);
-       bootstage_accum(BOOTSTAGE_ID_ACCUM_LCD);
-       if (ret) {
-               debug("failed to run video BIOS: %d\n", ret);
-               return ret;
-       }
 
-       ret = vesa_setup_video_priv(&mode_info.vesa,
-                                   mode_info.vesa.phys_base_ptr, uc_priv,
-                                   plat);
-       if (ret) {
-               if (ret == -ENFILE) {
-                       /*
-                        * See video-uclass.c for how to set up reserved memory
-                        * in your video driver
-                        */
-                       log_err("CONFIG_VIDEO_COPY enabled but driver '%s' set up no reserved memory\n",
-                               dev->driver->name);
+       /* In U-Boot proper, collect the information added by SPL (see below) */
+       if (IS_ENABLED(CONFIG_SPL_VIDEO) && spl_phase() > PHASE_SPL &&
+           CONFIG_IS_ENABLED(BLOBLIST)) {
+               struct video_handoff *ho;
+
+               ho = bloblist_find(BLOBLISTT_U_BOOT_VIDEO, sizeof(*ho));
+               if (!ho)
+                       return log_msg_ret("blf", -ENOENT);
+               plat->base = ho->fb;
+               plat->size = ho->size;
+               uc_priv->xsize = ho->xsize;
+               uc_priv->ysize = ho->ysize;
+               uc_priv->line_length = ho->line_length;
+               uc_priv->bpix = ho->bpix;
+       } else {
+               bootstage_start(BOOTSTAGE_ID_ACCUM_LCD, "vesa display");
+               ret = dm_pci_run_vga_bios(dev, int15_handler,
+                                         PCI_ROM_USE_NATIVE |
+                                         PCI_ROM_ALLOW_FALLBACK);
+               bootstage_accum(BOOTSTAGE_ID_ACCUM_LCD);
+               if (ret) {
+                       debug("failed to run video BIOS: %d\n", ret);
+                       return ret;
                }
 
-               debug("No video mode configured\n");
-               return ret;
+               ret = vesa_setup_video_priv(&mode_info.vesa,
+                                           mode_info.vesa.phys_base_ptr,
+                                           uc_priv, plat);
+               if (ret) {
+                       if (ret == -ENFILE) {
+                               /*
+                                * See video-uclass.c for how to set up reserved
+                                * memory in your video driver
+                                */
+                               log_err("CONFIG_VIDEO_COPY enabled but driver '%s' set up no reserved memory\n",
+                                       dev->driver->name);
+                       }
+
+                       debug("No video mode configured\n");
+                       return ret;
+               }
        }
 
        printf("Video: %dx%dx%d\n", uc_priv->xsize, uc_priv->ysize,
               mode_info.vesa.bits_per_pixel);
 
+       /* In SPL, store the information for use by U-Boot proper */
+       if (spl_phase() == PHASE_SPL && CONFIG_IS_ENABLED(BLOBLIST)) {
+               struct video_handoff *ho;
+
+               ho = bloblist_add(BLOBLISTT_U_BOOT_VIDEO, sizeof(*ho), 0);
+               if (!ho)
+                       return log_msg_ret("blc", -ENOMEM);
+
+               ho->fb = plat->base;
+               ho->size = plat->size;
+               ho->xsize = uc_priv->xsize;
+               ho->ysize = uc_priv->ysize;
+               ho->line_length = uc_priv->line_length;
+               ho->bpix = uc_priv->bpix;
+       }
+
        return 0;
 }
index 991013f..218221f 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * Bootdevice for USB
+ * Bootdev for SCSI
  *
  * Copyright 2021 Google LLC
  * Written by Simon Glass <sjg@chromium.org>
index 06e8f61..7fa1c60 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * Bootdevice for USB
+ * Bootdev for USB
  *
  * Copyright 2021 Google LLC
  * Written by Simon Glass <sjg@chromium.org>
index b209cb7..b8147f2 100644 (file)
@@ -278,6 +278,36 @@ config VIDCONSOLE_AS_NAME
          possible to update the environment, the breakage may be confusing for
          users. This option will be removed around the end of 2020.
 
+config VIDEO_BOCHS
+       bool "Enable Bochs video emulation for QEMU"
+       depends on X86
+       help
+         Enable this to use the Bochs video support provided in the QEMU
+         emulator. This appears as a PCI device which U-Boot can set up to
+         provide a frame buffer.
+
+if VIDEO_BOCHS
+
+config VIDEO_BOCHS_SIZE_X
+       int "Width of display (X resolution)"
+       default 1280
+       help
+         Sets the width of the display.
+
+         These two options control the size of the display set up by QEMU.
+         Typical sizes are 1024 x 768 or 1280 x 1024.
+
+config VIDEO_BOCHS_SIZE_Y
+       int "High of display (Y resolution)"
+       default 1024
+       help
+         Sets the height of the display.
+
+         These two options control the size of the display set up by QEMU.
+         Typical sizes are 1024 x 768 or 1280 x 1024.
+
+endif
+
 config VIDEO_COREBOOT
        bool "Enable coreboot framebuffer driver support"
        depends on X86
index d710c1f..d13af9f 100644 (file)
@@ -45,6 +45,7 @@ obj-$(CONFIG_OSD) += video_osd-uclass.o
 obj-$(CONFIG_SANDBOX_OSD) += sandbox_osd.o
 obj-$(CONFIG_VIDEO_ARM_MALIDP) += mali_dp.o
 obj-$(CONFIG_VIDEO_BCM2835) += bcm2835.o
+obj-$(CONFIG_VIDEO_BOCHS) += bochs.o
 obj-$(CONFIG_VIDEO_BROADWELL_IGD) += broadwell_igd.o
 obj-$(CONFIG_VIDEO_COREBOOT) += coreboot.o
 obj-$(CONFIG_VIDEO_DW_HDMI) += dw_hdmi.o
diff --git a/drivers/video/bochs.c b/drivers/video/bochs.c
new file mode 100644 (file)
index 0000000..2136b51
--- /dev/null
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Modified from coreboot bochs.c
+ */
+
+#define LOG_CATEGORY   UCLASS_VIDEO
+
+#include <common.h>
+#include <dm.h>
+#include <log.h>
+#include <pci.h>
+#include <video.h>
+#include <asm/io.h>
+#include <asm/mtrr.h>
+#include <linux/sizes.h>
+#include "bochs.h"
+
+static int xsize = CONFIG_VIDEO_BOCHS_SIZE_X;
+static int ysize = CONFIG_VIDEO_BOCHS_SIZE_Y;
+
+static void bochs_write(void *mmio, int index, int val)
+{
+       writew(val, mmio + MMIO_BASE + index * 2);
+}
+
+static int bochs_read(void *mmio, int index)
+{
+       return readw(mmio + MMIO_BASE + index * 2);
+}
+
+static void bochs_vga_write(int index, uint8_t val)
+{
+       outb(val, VGA_INDEX);
+}
+
+static int bochs_init_fb(struct udevice *dev)
+{
+       struct video_uc_plat *plat = dev_get_uclass_plat(dev);
+       struct video_priv *uc_priv = dev_get_uclass_priv(dev);
+       ulong fb;
+       void *mmio;
+       int id, mem;
+
+       log_debug("probing %s at PCI %x\n", dev->name, dm_pci_get_bdf(dev));
+       fb = dm_pci_read_bar32(dev, 0);
+       if (!fb)
+               return log_msg_ret("fb", -EIO);
+
+       /* MMIO bar supported since qemu 3.0+ */
+       mmio = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_2, 0, 0, PCI_REGION_TYPE,
+                             PCI_REGION_MEM);
+
+       if (!mmio)
+               return log_msg_ret("map", -EIO);
+
+       /* bochs dispi detection */
+       id = bochs_read(mmio, INDEX_ID);
+       if ((id & 0xfff0) != ID0) {
+               log_debug("ID mismatch\n");
+               return -EPROTONOSUPPORT;
+       }
+       mem = bochs_read(mmio, INDEX_VIDEO_MEMORY_64K) * SZ_64K;
+       log_debug("QEMU VGA: bochs @ %p: %d MiB FB at %lx\n", mmio, mem / SZ_1M,
+                 fb);
+
+       uc_priv->xsize = xsize;
+       uc_priv->ysize = ysize;
+       uc_priv->bpix = VIDEO_BPP32;
+
+       /* setup video mode */
+       bochs_write(mmio, INDEX_ENABLE,  0);
+       bochs_write(mmio, INDEX_BANK,  0);
+       bochs_write(mmio, INDEX_BPP, VNBITS(uc_priv->bpix));
+       bochs_write(mmio, INDEX_XRES, xsize);
+       bochs_write(mmio, INDEX_YRES, ysize);
+       bochs_write(mmio, INDEX_VIRT_WIDTH, xsize);
+       bochs_write(mmio, INDEX_VIRT_HEIGHT, ysize);
+       bochs_write(mmio, INDEX_X_OFFSET, 0);
+       bochs_write(mmio, INDEX_Y_OFFSET, 0);
+       bochs_write(mmio, INDEX_ENABLE, ENABLED | LFB_ENABLED);
+
+       bochs_vga_write(0, 0x20);       /* disable blanking */
+
+       plat->base = fb;
+
+       return 0;
+}
+
+static int bochs_video_probe(struct udevice *dev)
+{
+       int ret;
+
+       ret = bochs_init_fb(dev);
+       if (ret)
+               return log_ret(ret);
+
+       return 0;
+}
+
+static int bochs_video_bind(struct udevice *dev)
+{
+       struct video_uc_plat *uc_plat = dev_get_uclass_plat(dev);
+
+       /* Set the maximum supported resolution */
+       uc_plat->size = 2560 * 1600 * 4;
+       log_debug("%s: Frame buffer size %x\n", __func__, uc_plat->size);
+
+       return 0;
+}
+
+U_BOOT_DRIVER(bochs_video) = {
+       .name   = "bochs_video",
+       .id     = UCLASS_VIDEO,
+       .bind   = bochs_video_bind,
+       .probe  = bochs_video_probe,
+};
+
+static struct pci_device_id bochs_video_supported[] = {
+       { PCI_DEVICE(0x1234, 0x1111) },
+       { },
+};
+
+U_BOOT_PCI_DEVICE(bochs_video, bochs_video_supported);
diff --git a/drivers/video/bochs.h b/drivers/video/bochs.h
new file mode 100644 (file)
index 0000000..4c8ec83
--- /dev/null
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Modified from coreboot bochs.c
+ */
+
+#ifndef __BOCHS_H
+#define __BOCHS_H
+
+#define VGA_INDEX      0x3c0
+
+#define IOPORT_INDEX   0x01ce
+#define IOPORT_DATA    0x01cf
+
+enum {
+       INDEX_ID,
+       INDEX_XRES,
+       INDEX_YRES,
+       INDEX_BPP,
+       INDEX_ENABLE,
+       INDEX_BANK,
+       INDEX_VIRT_WIDTH,
+       INDEX_VIRT_HEIGHT,
+       INDEX_X_OFFSET,
+       INDEX_Y_OFFSET,
+       INDEX_VIDEO_MEMORY_64K
+};
+
+#define ID0            0xb0c0
+
+#define ENABLED                BIT(0)
+#define LFB_ENABLED    BIT(6)
+#define NOCLEARMEM     BIT(7)
+
+#define MMIO_BASE      0x500
+
+#endif
index 2da93da..d1476aa 100644 (file)
@@ -8,6 +8,8 @@
  * 2003-03-10 - kharris@nexus-tech.net - ported to uboot
  */
 
+#define LOG_CATEGORY   LOGC_FS
+
 #include <common.h>
 #include <blk.h>
 #include <config.h>
@@ -97,8 +99,8 @@ int fat_register_device(struct blk_desc *dev_desc, int part_no)
        /* Read the partition table, if present */
        if (part_get_info(dev_desc, part_no, &info)) {
                if (part_no != 0) {
-                       printf("** Partition %d not valid on device %d **\n",
-                                       part_no, dev_desc->devnum);
+                       log_err("Partition %d invalid on device %d\n", part_no,
+                               dev_desc->devnum);
                        return -1;
                }
 
@@ -168,7 +170,7 @@ static __u32 get_fatent(fsdata *mydata, __u32 entry)
        __u32 ret = 0x00;
 
        if (CHECK_CLUST(entry, mydata->fatsize)) {
-               printf("Error: Invalid FAT entry: 0x%08x\n", entry);
+               log_err("Invalid FAT entry: %#08x\n", entry);
                return ret;
        }
 
@@ -586,19 +588,19 @@ static int get_fs_info(fsdata *mydata)
        mydata->sect_size = (bs.sector_size[1] << 8) + bs.sector_size[0];
        mydata->clust_size = bs.cluster_size;
        if (mydata->sect_size != cur_part_info.blksz) {
-               printf("Error: FAT sector size mismatch (fs=%hu, dev=%lu)\n",
-                               mydata->sect_size, cur_part_info.blksz);
+               log_err("FAT sector size mismatch (fs=%u, dev=%lu)\n",
+                       mydata->sect_size, cur_part_info.blksz);
                return -1;
        }
        if (mydata->clust_size == 0) {
-               printf("Error: FAT cluster size not set\n");
+               log_err("FAT cluster size not set\n");
                return -1;
        }
        if ((unsigned int)mydata->clust_size * mydata->sect_size >
            MAX_CLUSTSIZE) {
-               printf("Error: FAT cluster size too big (cs=%u, max=%u)\n",
-                      (unsigned int)mydata->clust_size * mydata->sect_size,
-                      MAX_CLUSTSIZE);
+               log_err("FAT cluster size too big (cs=%u, max=%u)\n",
+                       (uint)mydata->clust_size * mydata->sect_size,
+                       MAX_CLUSTSIZE);
                return -1;
        }
 
index 413fc43..e2a9913 100644 (file)
@@ -1571,8 +1571,9 @@ int fat_unlink(const char *filename)
        char *filename_copy, *dirname, *basename;
 
        filename_copy = strdup(filename);
-       if (!filename_copy) {
-               printf("Error: allocating memory\n");
+       itr = malloc_cache_aligned(sizeof(fat_itr));
+       if (!itr || !filename_copy) {
+               printf("Error: out of memory\n");
                ret = -ENOMEM;
                goto exit;
        }
@@ -1584,13 +1585,6 @@ int fat_unlink(const char *filename)
                goto exit;
        }
 
-       itr = malloc_cache_aligned(sizeof(fat_itr));
-       if (!itr) {
-               printf("Error: allocating memory\n");
-               ret = -ENOMEM;
-               goto exit;
-       }
-
        ret = fat_itr_root(itr, &fsdata);
        if (ret)
                goto exit;
@@ -1605,7 +1599,7 @@ int fat_unlink(const char *filename)
        }
 
        if (!find_directory_entry(itr, basename)) {
-               printf("%s: doesn't exist\n", basename);
+               log_err("%s: doesn't exist (%d)\n", basename, -ENOENT);
                ret = -ENOENT;
                goto exit;
        }
index 0d12ee4..3ef5362 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * Bootdevice for MMC
+ * Bootdev for sandbox host
  *
  * Copyright 2021 Google LLC
  * Written by Simon Glass <sjg@chromium.org>
index a1e1b9d..8fc205d 100644 (file)
@@ -301,6 +301,12 @@ struct global_data {
         * @timebase_l: low 32 bits of timer
         */
        unsigned int timebase_l;
+       /**
+        * @malloc_start: start of malloc() region
+        */
+#if CONFIG_IS_ENABLED(CMD_BDINFO_EXTRA)
+       unsigned long malloc_start;
+#endif
 #if CONFIG_VAL(SYS_MALLOC_F_LEN)
        /**
         * @malloc_base: base address of early malloc()
@@ -560,6 +566,13 @@ static_assert(sizeof(struct global_data) == GD_SIZE);
 #define gd_event_state()       NULL
 #endif
 
+#if CONFIG_IS_ENABLED(CMD_BDINFO_EXTRA)
+#define gd_malloc_start()              gd->malloc_start
+#define gd_set_malloc_start(_val)      gd->malloc_start = (_val)
+#else
+#define gd_malloc_start()      0
+#define gd_set_malloc_start(val)
+#endif
 /**
  * enum gd_flags - global data flags
  *
index 2a2f170..7ea72c6 100644 (file)
@@ -113,6 +113,7 @@ enum bloblist_tag_t {
        BLOBLISTT_PROJECT_AREA = 0x8000,
        BLOBLISTT_U_BOOT_SPL_HANDOFF = 0x8000, /* Hand-off info from SPL */
        BLOBLISTT_VBE           = 0x8001,       /* VBE per-phase state */
+       BLOBLISTT_U_BOOT_VIDEO = 0x8002, /* Video information from SPL */
 
        /*
         * Vendor-specific tags are permitted here. Projects can be open source
index e72ef36..1533adf 100644 (file)
@@ -200,7 +200,7 @@ void bootdev_clear_bootflows(struct udevice *dev);
  * All fields in @bflow must be set up. Note that @bflow->dev is used to add the
  * bootflow to that device.
  *
- * @dev: Bootdevice device to add to
+ * @dev: Bootdev device to add to
  * @bflow: Bootflow to add. Note that fields within bflow must be allocated
  *     since this function takes over ownership of these. This functions makes
  *     a copy of @bflow itself (without allocating its fields again), so the
index f20f575..4152577 100644 (file)
@@ -58,7 +58,7 @@ enum bootflow_flags_t {
  *
  * @bm_node: Points to siblings in the same bootdev
  * @glob_node: Points to siblings in the global list (all bootdev)
- * @dev: Bootdevice device which produced this bootflow
+ * @dev: Bootdev device which produced this bootflow
  * @blk: Block device which contains this bootflow, NULL if this is a network
  *     device or sandbox 'host' device
  * @part: Partition number (0 for whole device)
@@ -81,6 +81,8 @@ enum bootflow_flags_t {
  * @fdt_size: Size of FDT file
  * @fdt_addr: Address of loaded fdt
  * @flags: Flags for the bootflow (see enum bootflow_flags_t)
+ * @cmdline: OS command line, or NULL if not known (allocated)
+ * @x86_setup: Pointer to x86 setup block inside @buf, NULL if not present
  */
 struct bootflow {
        struct list_head bm_node;
@@ -104,6 +106,8 @@ struct bootflow {
        int fdt_size;
        ulong fdt_addr;
        int flags;
+       char *cmdline;
+       char *x86_setup;
 };
 
 /**
@@ -440,4 +444,98 @@ int bootflow_menu_apply_theme(struct expo *exp, ofnode node);
 int bootflow_menu_run(struct bootstd_priv *std, bool text_mode,
                      struct bootflow **bflowp);
 
+#define BOOTFLOWCL_EMPTY       ((void *)1)
+
+/**
+ * cmdline_set_arg() - Update or read an argument in a cmdline string
+ *
+ * Handles updating a single arg in a cmdline string, returning it in a supplied
+ * buffer; also reading an arg from a cmdline string
+ *
+ * When updating, consecutive spaces are squashed as are spaces at the start and
+ * end.
+ *
+ * @buf: Working buffer to use (initial contents are ignored). Use NULL when
+ * reading
+ * @maxlen: Length of working buffer. Use 0 when reading
+ * @cmdline: Command line to update, in the form:
+ *
+ *     fred mary= jane=123 john="has spaces"
+ *
+ * @set_arg: Argument to set or read (may or may not exist)
+ * @new_val: Value for the new argument. May not include quotes (") but may
+ * include embedded spaces, in which case it will be quoted when added to the
+ * command line. Use NULL to delete the argument from @cmdline, BOOTFLOWCL_EMPTY
+ * to set it to an empty value (no '=' sign after arg), "" to add an '=' sign
+ * but with an empty value. Use NULL when reading.
+ * @posp: Ignored when setting an argument; when getting an argument, returns
+ * the start position of its value in @cmdline, after the first quote, if any
+ *
+ * Return:
+ * For updating:
+ *     length of new buffer (including \0 terminator) on success, -ENOENT if
+ *     @new_val is NULL and @set_arg does not exist in @from, -EINVAL if a
+ *     quoted arg-value in @from is not terminated with a quote, -EBADF if
+ *     @new_val has spaces but does not start and end with quotes (or it has
+ *     quotes in the middle of the string), -E2BIG if @maxlen is too small
+ * For reading:
+ *     length of arg value (excluding quotes), -ENOENT if not found
+ */
+int cmdline_set_arg(char *buf, int maxlen, const char *cmdline,
+                   const char *set_arg, const char *new_val, int *posp);
+
+/**
+ * bootflow_cmdline_set_arg() - Set a single argument for a bootflow
+ *
+ * Update the allocated cmdline and set the bootargs variable
+ *
+ * @bflow: Bootflow to update
+ * @arg: Argument to update (e.g. "console")
+ * @val: Value to set (e.g. "ttyS2") or NULL to delete the argument if present,
+ * "" to set it to an empty value (e.g. "console=") and BOOTFLOWCL_EMPTY to add
+ * it without any value ("initrd")
+ * @set_env: true to set the "bootargs" environment variable too
+ *
+ * Return: 0 if OK, -ENOMEM if out of memory
+ */
+int bootflow_cmdline_set_arg(struct bootflow *bflow, const char *arg,
+                            const char *val, bool set_env);
+
+/**
+ * cmdline_get_arg() - Read an argument from a cmdline
+ *
+ * @cmdline: Command line to read, in the form:
+ *
+ *     fred mary= jane=123 john="has spaces"
+ * @arg: Argument to read (may or may not exist)
+ * @posp: Returns position of argument (after any leading quote) if present
+ * Return: Length of argument value excluding quotes if found, -ENOENT if not
+ * found
+ */
+int cmdline_get_arg(const char *cmdline, const char *arg, int *posp);
+
+/**
+ * bootflow_cmdline_get_arg() - Read an argument from a cmdline
+ *
+ * @bootflow: Bootflow to read from
+ * @arg: Argument to read (may or may not exist)
+ * @valp: Returns a pointer to the argument (after any leading quote) if present
+ * Return: Length of argument value excluding quotes if found, -ENOENT if not
+ * found
+ */
+int bootflow_cmdline_get_arg(struct bootflow *bflow, const char *arg,
+                            const char **val);
+
+/**
+ * bootflow_cmdline_auto() - Automatically set a value for a known argument
+ *
+ * This handles a small number of known arguments, for Linux in particular. It
+ * adds suitable kernel parameters automatically, e.g. to enable the console.
+ *
+ * @bflow: Bootflow to update
+ * @arg: Name of argument to set (e.g. "earlycon" or "console")
+ * Return: 0 if OK -ve on error
+ */
+int bootflow_cmdline_auto(struct bootflow *bflow, const char *arg);
+
 #endif
index 60617e6..03c364f 100644 (file)
@@ -16,8 +16,6 @@
                                        "stdout=serial\0" \
                                        "stderr=serial\0"
 
-#define VIDEO_IO_OFFSET                                0
-
 #undef CFG_EXTRA_ENV_SETTINGS
 #define CFG_EXTRA_ENV_SETTINGS                         \
        "kernel-ver=4.4.0-22\0"                                 \
index 05389a4..be095e2 100644 (file)
@@ -20,8 +20,6 @@
                                        "stdout=serial\0" \
                                        "stderr=serial\0"
 
-#define VIDEO_IO_OFFSET                                0
-
 #undef CFG_EXTRA_ENV_SETTINGS
 #define CFG_EXTRA_ENV_SETTINGS                         \
        "kernel-ver=4.4.0-24\0"                                 \
index 4a12c2f..842672d 100644 (file)
@@ -17,6 +17,4 @@
                                        "stderr=vidconsole,serial\0" \
                                        "usb_pgood_delay=40\0"
 
-#define VIDEO_IO_OFFSET                                0
-
 #endif /* __CONFIG_H */
index 33263a4..3e52352 100644 (file)
 
 #include <linux/sizes.h>
 
-#define BOOT_TARGET_DEVICES(func) \
-       func(USB, usb, 0) \
-       func(SCSI, scsi, 0) \
-       func(VIRTIO, virtio, 0) \
-       func(IDE, ide, 0) \
-       func(DHCP, dhcp, na)
-
-#include <config_distro_bootcmd.h>
 #include <configs/x86-common.h>
 
 #define CFG_STD_DEVICES_SETTINGS       "stdin=serial,i8042-kbd\0" \
index b2e7aa1..5f7eabd 100644 (file)
@@ -16,6 +16,4 @@
                                        "stdout=serial,vidconsole\0" \
                                        "stderr=serial,vidconsole\0"
 
-#define VIDEO_IO_OFFSET                                0
-
 #endif /* __CONFIG_H */
index b23b878..46aef23 100644 (file)
@@ -15,8 +15,6 @@
                                        "stdout=serial\0" \
                                        "stderr=serial\0"
 
-#define VIDEO_IO_OFFSET                                0
-
 /* Environment settings */
 
 #undef CFG_EXTRA_ENV_SETTINGS
index 98abb00..6bf90c7 100644 (file)
@@ -10,8 +10,6 @@
 #define CFG_X86_REFCODE_ADDR                   0xffea0000
 #define CFG_X86_REFCODE_RUN_ADDR               0
 
-#define VIDEO_IO_OFFSET                                0
-
 #define CFG_STD_DEVICES_SETTINGS       "stdin=usbkbd,i8042-kbd,serial\0" \
                                        "stdout=vidconsole,serial\0" \
                                        "stderr=vidconsole,serial\0"
index a9a14f2..23bc650 100644 (file)
 #define NET6_CALLBACKS
 #endif
 
-#ifdef CONFIG_BOOTSTD
-#define BOOTSTD_CALLBACK       "bootmeths:bootmeths,"
+#ifdef CONFIG_BOOTSTD_FULL
+#define BOOTSTD_CALLBACK \
+       "bootmeths:bootmeths," \
+       "bootargs:bootargs,"
 #else
 #define BOOTSTD_CALLBACK
 #endif
index be75c73..3b1b539 100644 (file)
@@ -598,6 +598,15 @@ static inline struct part_driver *part_driver_get_first(void)
        return ll_entry_start(struct part_driver, part_driver);
 }
 
+/**
+ * part_get_type_by_name() - Get partition type by name
+ *
+ * @name: Name of partition type to look up (not case-sensitive)
+ * Returns: Corresponding partition type (PART_TYPE_...) or PART_TYPE_UNKNOWN if
+ * not known
+ */
+int part_get_type_by_name(const char *name);
+
 #else
 static inline int part_driver_get_count(void)
 { return 0; }
index e98d0f9..9729fa3 100644 (file)
@@ -134,6 +134,30 @@ struct video_ops {
 
 #define video_get_ops(dev)        ((struct video_ops *)(dev)->driver->ops)
 
+/**
+ * struct video_handoff - video information passed from SPL
+ *
+ * This is used when video is set up by SPL, to provide the details to U-Boot
+ * proper.
+ *
+ * @fb: Base address of frame buffer, 0 if not yet known
+ * @size: Frame-buffer size, in bytes
+ * @xsize:     Number of pixel columns (e.g. 1366)
+ * @ysize:     Number of pixels rows (e.g.. 768)
+ * @line_length:       Length of each frame buffer line, in bytes. This can be
+ *             set by the driver, but if not, the uclass will set it after
+ *             probing
+ * @bpix:      Encoded bits per pixel (enum video_log2_bpp)
+ */
+struct video_handoff {
+       u64 fb;
+       u32 size;
+       u16 xsize;
+       u16 ysize;
+       u32 line_length;
+       u8 bpix;
+};
+
 /** enum colour_idx - the 16 colors supported by consoles */
 enum colour_idx {
        VID_BLACK = 0,
index 2ddc350..f755af7 100644 (file)
@@ -10,6 +10,9 @@
 #include <log.h>
 #include <mapmem.h>
 #include <acpi/acpi_table.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
 
 static const efi_guid_t acpi_guid = EFI_ACPI_TABLE_GUID;
 
@@ -20,26 +23,28 @@ static const efi_guid_t acpi_guid = EFI_ACPI_TABLE_GUID;
  */
 efi_status_t efi_acpi_register(void)
 {
-       /* Map within the low 32 bits, to allow for 32bit ACPI tables */
-       u64 acpi = U32_MAX;
+       ulong addr, start, end;
        efi_status_t ret;
-       ulong addr;
 
-       /* Reserve 64kiB page for ACPI */
-       ret = efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS,
-                                EFI_ACPI_RECLAIM_MEMORY, 16, &acpi);
+       /* Mark space used for tables */
+       start = ALIGN_DOWN(gd->arch.table_start, EFI_PAGE_MASK);
+       end = ALIGN(gd->arch.table_end, EFI_PAGE_MASK);
+       ret = efi_add_memory_map(start, end - start, EFI_ACPI_RECLAIM_MEMORY);
        if (ret != EFI_SUCCESS)
                return ret;
+       if (gd->arch.table_start_high) {
+               start = ALIGN_DOWN(gd->arch.table_start_high, EFI_PAGE_MASK);
+               end = ALIGN(gd->arch.table_end_high, EFI_PAGE_MASK);
+               ret = efi_add_memory_map(start, end - start,
+                                        EFI_ACPI_RECLAIM_MEMORY);
+               if (ret != EFI_SUCCESS)
+                       return ret;
+       }
 
-       /*
-        * Generate ACPI tables - we know that efi_allocate_pages() returns
-        * a 4k-aligned address, so it is safe to assume that
-        * write_acpi_tables() will write the table at that address.
-        */
-       addr = map_to_sysmem((void *)(ulong)acpi);
-       write_acpi_tables(addr);
+       addr = gd_acpi_start();
+       printf("EFI using ACPI tables at %lx\n", addr);
 
        /* And expose them to our EFI payload */
        return efi_install_configuration_table(&acpi_guid,
-                                              (void *)(uintptr_t)acpi);
+                                              (void *)(ulong)addr);
 }
index 96e1af3..ab30fbf 100644 (file)
@@ -255,7 +255,7 @@ static const struct {
                EFI_CERT_TYPE_PKCS7_GUID,
        },
 #endif
-#ifdef CONFIG_EFI
+#if defined(CONFIG_CMD_EFIDEBUG) || defined(CONFIG_EFI)
        { "EFI_LZMA_COMPRESSED", EFI_LZMA_COMPRESSED },
        { "EFI_DXE_SERVICES", EFI_DXE_SERVICES },
        { "EFI_HOB_LIST", EFI_HOB_LIST },
index f7b4196..869adf8 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * Bootdevice for ethernet (uses PXE)
+ * Bootdev for ethernet (uses PXE)
  *
  * Copyright 2021 Google LLC
  * Written by Simon Glass <sjg@chromium.org>
index 2b5f87d..8a4e090 100644 (file)
@@ -226,6 +226,7 @@ static int bootflow_cmd_info(struct unit_test_state *uts)
        ut_assert_nextlinen("Buffer:    ");
        ut_assert_nextline("Size:      253 (595 bytes)");
        ut_assert_nextline("OS:        Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl)");
+       ut_assert_nextline("Cmdline:   (none)");
        ut_assert_nextline("Logo:      (none)");
        ut_assert_nextline("FDT:       <NULL>");
        ut_assert_nextline("Error:     0");
@@ -682,3 +683,265 @@ static int bootflow_menu_theme(struct unit_test_state *uts)
        return 0;
 }
 BOOTSTD_TEST(bootflow_menu_theme, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/**
+ * check_arg() - Check both the normal case and the buffer-overflow case
+ *
+ * @uts: Unit-test state
+ * @expect_ret: Expected return value (i.e. buffer length)
+ * @expect_str: String expected to be returned
+ * @buf: Buffer to use
+ * @from: Original cmdline to update
+ * @arg: Argument to update (e.g. "console")
+ * @val: Value to set (e.g. "ttyS2") or NULL to delete the argument if present,
+ * "" to set it to an empty value (e.g. "console=") and BOOTFLOWCL_EMPTY to add
+ * it without any value ("initrd")
+ */
+static int check_arg(struct unit_test_state *uts, int expect_ret,
+                    const char *expect_str, char *buf, const char *from,
+                    const char *arg, const char *val)
+{
+       /* check for writing outside the reported bounds */
+       buf[expect_ret] = '[';
+       ut_asserteq(expect_ret,
+                   cmdline_set_arg(buf, expect_ret, from, arg, val, NULL));
+       ut_asserteq_str(expect_str, buf);
+       ut_asserteq('[', buf[expect_ret]);
+
+       /* do the test again but with one less byte in the buffer */
+       ut_asserteq(-E2BIG, cmdline_set_arg(buf, expect_ret - 1, from, arg,
+                                           val, NULL));
+
+       return 0;
+}
+
+/* Test of bootflow_cmdline_set_arg() */
+static int test_bootflow_cmdline_set(struct unit_test_state *uts)
+{
+       char buf[50];
+       const int size = sizeof(buf);
+
+       /*
+        * note that buffer-overflow tests are immediately each test case, just
+        * top keep the code together
+        */
+
+       /* add an arg that doesn't already exist, starting from empty */
+       ut_asserteq(-ENOENT, cmdline_set_arg(buf, size, NULL, "me", NULL,
+                                            NULL));
+
+       ut_assertok(check_arg(uts, 3, "me", buf, NULL, "me", BOOTFLOWCL_EMPTY));
+       ut_assertok(check_arg(uts, 4, "me=", buf, NULL, "me", ""));
+       ut_assertok(check_arg(uts, 8, "me=fred", buf, NULL, "me", "fred"));
+
+       /* add an arg that doesn't already exist, starting from non-empty */
+       ut_assertok(check_arg(uts, 11, "arg=123 me", buf, "arg=123", "me",
+                             BOOTFLOWCL_EMPTY));
+       ut_assertok(check_arg(uts, 12, "arg=123 me=", buf, "arg=123", "me",
+                             ""));
+       ut_assertok(check_arg(uts, 16, "arg=123 me=fred", buf, "arg=123", "me",
+                             "fred"));
+
+       /* update an arg at the start */
+       ut_assertok(check_arg(uts, 1, "", buf, "arg=123", "arg", NULL));
+       ut_assertok(check_arg(uts, 4, "arg", buf, "arg=123", "arg",
+                             BOOTFLOWCL_EMPTY));
+       ut_assertok(check_arg(uts, 5, "arg=", buf, "arg=123", "arg", ""));
+       ut_assertok(check_arg(uts, 6, "arg=1", buf, "arg=123", "arg", "1"));
+       ut_assertok(check_arg(uts, 9, "arg=1234", buf, "arg=123", "arg",
+                             "1234"));
+
+       /* update an arg at the end */
+       ut_assertok(check_arg(uts, 5, "mary", buf, "mary arg=123", "arg",
+                             NULL));
+       ut_assertok(check_arg(uts, 9, "mary arg", buf, "mary arg=123", "arg",
+                             BOOTFLOWCL_EMPTY));
+       ut_assertok(check_arg(uts, 10, "mary arg=", buf, "mary arg=123", "arg",
+                             ""));
+       ut_assertok(check_arg(uts, 11, "mary arg=1", buf, "mary arg=123", "arg",
+                             "1"));
+       ut_assertok(check_arg(uts, 14, "mary arg=1234", buf, "mary arg=123",
+                             "arg", "1234"));
+
+       /* update an arg in the middle */
+       ut_assertok(check_arg(uts, 16, "mary=abc john=2", buf,
+                             "mary=abc arg=123 john=2", "arg", NULL));
+       ut_assertok(check_arg(uts, 20, "mary=abc arg john=2", buf,
+                             "mary=abc arg=123 john=2", "arg",
+                             BOOTFLOWCL_EMPTY));
+       ut_assertok(check_arg(uts, 21, "mary=abc arg= john=2", buf,
+                             "mary=abc arg=123 john=2", "arg", ""));
+       ut_assertok(check_arg(uts, 22, "mary=abc arg=1 john=2", buf,
+                             "mary=abc arg=123 john=2", "arg", "1"));
+       ut_assertok(check_arg(uts, 25, "mary=abc arg=1234 john=2", buf,
+                             "mary=abc arg=123 john=2", "arg", "1234"));
+
+       /* handle existing args with quotes */
+       ut_assertok(check_arg(uts, 16, "mary=\"abc\" john", buf,
+                             "mary=\"abc\" arg=123 john", "arg", NULL));
+
+       /* handle existing args with quoted spaces */
+       ut_assertok(check_arg(uts, 20, "mary=\"abc def\" john", buf,
+                             "mary=\"abc def\" arg=123 john", "arg", NULL));
+
+       ut_assertok(check_arg(uts, 34, "mary=\"abc def\" arg=123 john def=4",
+                             buf, "mary=\"abc def\" arg=123 john", "def",
+                             "4"));
+
+       /* quote at the start */
+       ut_asserteq(-EBADF, cmdline_set_arg(buf, size,
+                                           "mary=\"abc def\" arg=\"123 456\"",
+                                           "arg", "\"4 5 6", NULL));
+
+       /* quote at the end */
+       ut_asserteq(-EBADF, cmdline_set_arg(buf, size,
+                                           "mary=\"abc def\" arg=\"123 456\"",
+                                           "arg", "4 5 6\"", NULL));
+
+       /* quote in the middle */
+       ut_asserteq(-EBADF, cmdline_set_arg(buf, size,
+                                           "mary=\"abc def\" arg=\"123 456\"",
+                                           "arg", "\"4 \"5 6\"", NULL));
+
+       /* handle updating a quoted arg */
+       ut_assertok(check_arg(uts, 27, "mary=\"abc def\" arg=\"4 5 6\"", buf,
+                             "mary=\"abc def\" arg=\"123 456\"", "arg",
+                             "4 5 6"));
+
+       /* changing a quoted arg to a non-quoted arg */
+       ut_assertok(check_arg(uts, 23, "mary=\"abc def\" arg=789", buf,
+                             "mary=\"abc def\" arg=\"123 456\"", "arg",
+                             "789"));
+
+       /* changing a non-quoted arg to a quoted arg */
+       ut_assertok(check_arg(uts, 29, "mary=\"abc def\" arg=\"456 789\"", buf,
+                             "mary=\"abc def\" arg=123", "arg", "456 789"));
+
+       /* handling of spaces */
+       ut_assertok(check_arg(uts, 8, "arg=123", buf, " ", "arg", "123"));
+       ut_assertok(check_arg(uts, 8, "arg=123", buf, "   ", "arg", "123"));
+       ut_assertok(check_arg(uts, 13, "john arg=123", buf, " john  ", "arg",
+                             "123"));
+       ut_assertok(check_arg(uts, 13, "john arg=123", buf, " john  arg=123  ",
+                             "arg", "123"));
+       ut_assertok(check_arg(uts, 18, "john arg=123 mary", buf,
+                             " john  arg=123 mary ", "arg", "123"));
+
+       /* unchanged arg */
+       ut_assertok(check_arg(uts, 3, "me", buf, "me", "me", BOOTFLOWCL_EMPTY));
+
+       /* arg which starts with the same name */
+       ut_assertok(check_arg(uts, 28, "mary=abc johnathon=2 john=3", buf,
+                             "mary=abc johnathon=2 john=1", "john", "3"));
+
+       return 0;
+}
+BOOTSTD_TEST(test_bootflow_cmdline_set, 0);
+
+/* Test of bootflow_cmdline_set_arg() */
+static int bootflow_set_arg(struct unit_test_state *uts)
+{
+       struct bootflow s_bflow, *bflow = &s_bflow;
+       ulong mem_start;
+
+       ut_assertok(env_set("bootargs", NULL));
+
+       mem_start = ut_check_delta(0);
+
+       /* Do a simple sanity check. Rely on bootflow_cmdline() for the rest */
+       bflow->cmdline = NULL;
+       ut_assertok(bootflow_cmdline_set_arg(bflow, "fred", "123", false));
+       ut_asserteq_str(bflow->cmdline, "fred=123");
+
+       ut_assertok(bootflow_cmdline_set_arg(bflow, "mary", "and here", false));
+       ut_asserteq_str(bflow->cmdline, "fred=123 mary=\"and here\"");
+
+       ut_assertok(bootflow_cmdline_set_arg(bflow, "mary", NULL, false));
+       ut_asserteq_str(bflow->cmdline, "fred=123");
+       ut_assertok(bootflow_cmdline_set_arg(bflow, "fred", NULL, false));
+       ut_asserteq_ptr(bflow->cmdline, NULL);
+
+       ut_asserteq(0, ut_check_delta(mem_start));
+
+       ut_assertok(bootflow_cmdline_set_arg(bflow, "mary", "here", true));
+       ut_asserteq_str("mary=here", env_get("bootargs"));
+       ut_assertok(env_set("bootargs", NULL));
+
+       return 0;
+}
+BOOTSTD_TEST(bootflow_set_arg, 0);
+
+/* Test of bootflow_cmdline_get_arg() */
+static int bootflow_cmdline_get(struct unit_test_state *uts)
+{
+       int pos;
+
+       /* empty string */
+       ut_asserteq(-ENOENT, cmdline_get_arg("", "fred", &pos));
+
+       /* arg with empty value */
+       ut_asserteq(0, cmdline_get_arg("fred= mary", "fred", &pos));
+       ut_asserteq(5, pos);
+
+       /* arg with a value */
+       ut_asserteq(2, cmdline_get_arg("fred=23", "fred", &pos));
+       ut_asserteq(5, pos);
+
+       /* arg with a value */
+       ut_asserteq(3, cmdline_get_arg("mary=1 fred=234", "fred", &pos));
+       ut_asserteq(12, pos);
+
+       /* arg with a value, after quoted arg */
+       ut_asserteq(3, cmdline_get_arg("mary=\"1 2\" fred=234", "fred", &pos));
+       ut_asserteq(16, pos);
+
+       /* arg in the middle */
+       ut_asserteq(0, cmdline_get_arg("mary=\"1 2\" fred john=23", "fred",
+                                      &pos));
+       ut_asserteq(15, pos);
+
+       /* quoted arg */
+       ut_asserteq(3, cmdline_get_arg("mary=\"1 2\" fred=\"3 4\" john=23",
+                                      "fred", &pos));
+       ut_asserteq(17, pos);
+
+       /* args starting with the same prefix */
+       ut_asserteq(1, cmdline_get_arg("mary=abc johnathon=3 john=1", "john",
+                                      &pos));
+       ut_asserteq(26, pos);
+
+       return 0;
+}
+BOOTSTD_TEST(bootflow_cmdline_get, 0);
+
+static int bootflow_cmdline(struct unit_test_state *uts)
+{
+       ut_assertok(run_command("bootflow scan mmc", 0));
+       ut_assertok(run_command("bootflow sel 0", 0));
+       console_record_reset_enable();
+
+       ut_asserteq(1, run_command("bootflow cmdline get fred", 0));
+       ut_assert_nextline("Argument not found");
+       ut_assert_console_end();
+
+       ut_asserteq(0, run_command("bootflow cmdline set fred 123", 0));
+       ut_asserteq(0, run_command("bootflow cmdline get fred", 0));
+       ut_assert_nextline("123");
+
+       ut_asserteq(0, run_command("bootflow cmdline set mary abc", 0));
+       ut_asserteq(0, run_command("bootflow cmdline get mary", 0));
+       ut_assert_nextline("abc");
+
+       ut_asserteq(0, run_command("bootflow cmdline delete fred", 0));
+       ut_asserteq(1, run_command("bootflow cmdline get fred", 0));
+       ut_assert_nextline("Argument not found");
+
+       ut_asserteq(0, run_command("bootflow cmdline clear mary", 0));
+       ut_asserteq(0, run_command("bootflow cmdline get mary", 0));
+       ut_assert_nextline_empty();
+
+       ut_assert_console_end();
+
+       return 0;
+}
+BOOTSTD_TEST(bootflow_cmdline, 0);
index cddf1a4..8c09281 100644 (file)
@@ -16,6 +16,7 @@
 #include <env.h>
 #include <lmb.h>
 #include <net.h>
+#include <serial.h>
 #include <video.h>
 #include <vsprintf.h>
 #include <asm/cache.h>
@@ -191,6 +192,26 @@ static int bdinfo_test_move(struct unit_test_state *uts)
                        ut_assert_nextline("devicetree  = %s", fdtdec_get_srcname());
        }
 
+       if (IS_ENABLED(CONFIG_DM_SERIAL)) {
+               struct serial_device_info info;
+
+               ut_assertnonnull(gd->cur_serial_dev);
+               ut_assertok(serial_getinfo(gd->cur_serial_dev, &info));
+
+               ut_assertok(test_num_l(uts, "serial addr", info.addr));
+               ut_assertok(test_num_l(uts, " width", info.reg_width));
+               ut_assertok(test_num_l(uts, " shift", info.reg_shift));
+               ut_assertok(test_num_l(uts, " offset", info.reg_offset));
+               ut_assertok(test_num_l(uts, " clock", info.clock));
+       }
+
+       if (IS_ENABLED(CONFIG_CMD_BDINFO_EXTRA)) {
+               ut_assert_nextlinen("stack ptr");
+               ut_assertok(test_num_ll(uts, "ram_top ptr",
+                                       (unsigned long long)gd->ram_top));
+               ut_assertok(test_num_l(uts, "malloc base", gd_malloc_start()));
+       }
+
        ut_assertok(ut_check_console_end(uts));
 
        return 0;
index 818f715..77eb524 100644 (file)
@@ -609,3 +609,41 @@ static int dm_test_acpi_cmd_items(struct unit_test_state *uts)
        return 0;
 }
 DM_TEST(dm_test_acpi_cmd_items, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+
+/* Test 'acpi set' command */
+static int dm_test_acpi_cmd_set(struct unit_test_state *uts)
+{
+       struct acpi_ctx ctx;
+       ulong addr;
+       void *buf;
+
+       gd_set_acpi_start(0);
+
+       console_record_reset();
+       ut_asserteq(0, gd_acpi_start());
+       ut_assertok(run_command("acpi set", 0));
+       ut_assert_nextline("ACPI pointer: 0");
+
+       buf = memalign(16, BUF_SIZE);
+       ut_assertnonnull(buf);
+       addr = map_to_sysmem(buf);
+       ut_assertok(setup_ctx_and_base_tables(uts, &ctx, addr));
+
+       ut_assertok(acpi_write_dev_tables(&ctx));
+
+       ut_assertok(run_command("acpi set", 0));
+       ut_assert_nextline("ACPI pointer: %lx", addr);
+
+       ut_assertok(run_command("acpi set 0", 0));
+       ut_assert_nextline("Setting ACPI pointer to 0");
+       ut_asserteq(0, gd_acpi_start());
+
+       ut_assertok(run_commandf("acpi set %lx", addr));
+       ut_assert_nextline("Setting ACPI pointer to %lx", addr);
+       ut_asserteq(addr, gd_acpi_start());
+
+       ut_assert_console_end();
+
+       return 0;
+}
+DM_TEST(dm_test_acpi_cmd_set, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
index 2a3b2ba..778bf0a 100644 (file)
@@ -476,7 +476,8 @@ static int ut_run_test_live_flat(struct unit_test_state *uts,
         *   (for sandbox we handle this by copying the tree, but not for other
         *    boards)
         */
-       if (!(test->flags & UT_TESTF_LIVE_TREE) &&
+       if ((test->flags & UT_TESTF_SCAN_FDT) &&
+           !(test->flags & UT_TESTF_LIVE_TREE) &&
            (CONFIG_IS_ENABLED(OFNODE_MULTI_TREE) ||
             !(test->flags & UT_TESTF_OTHER_FDT)) &&
            (!runs || ut_test_run_on_flattree(test)) &&