summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2023-07-17 17:38:28 +0300
committerTom Rini <trini@konsulko.com>2023-07-17 17:38:28 +0300
commit13aa090b87a0fbdfe690011669b9fdb96bb1ccc7 (patch)
tree69af16bc8ecc4b6e8106a750e31e51d7ec078828
parentaa817dfcaf158dda71358d02181bf52c30dbe4c6 (diff)
parentb8956425d525c3c25fd218f252f89a5e44df6a9f (diff)
downloadu-boot-13aa090b87a0fbdfe690011669b9fdb96bb1ccc7.tar.xz
Merge https://source.denx.de/u-boot/custodians/u-boot-x86
- bootstd: Add a bootmeth for ChromiumOS on x86 - x86: Use qemu-x86_64 to boot EFI installers
-rw-r--r--arch/sandbox/include/asm/global_data.h4
-rw-r--r--arch/x86/cpu/i386/interrupt.c17
-rw-r--r--arch/x86/cpu/intel_common/mrc.c10
-rw-r--r--arch/x86/cpu/ivybridge/sdram.c4
-rw-r--r--arch/x86/cpu/mtrr.c61
-rw-r--r--arch/x86/cpu/qemu/Kconfig2
-rw-r--r--arch/x86/cpu/start64.S19
-rw-r--r--arch/x86/dts/chromebook_link.dts1
-rw-r--r--arch/x86/include/asm/global_data.h4
-rw-r--r--arch/x86/include/asm/mtrr.h20
-rw-r--r--arch/x86/include/asm/u-boot-x86.h27
-rw-r--r--arch/x86/include/asm/zimage.h27
-rw-r--r--arch/x86/lib/Makefile7
-rw-r--r--arch/x86/lib/bdinfo.c5
-rw-r--r--arch/x86/lib/bios.c4
-rw-r--r--arch/x86/lib/bootm.c2
-rw-r--r--arch/x86/lib/mrccache.c6
-rw-r--r--arch/x86/lib/spl.c68
-rw-r--r--arch/x86/lib/tables.c46
-rw-r--r--arch/x86/lib/zimage.c93
-rw-r--r--board/google/Kconfig7
-rw-r--r--board/sandbox/sandbox.c22
-rw-r--r--boot/Kconfig11
-rw-r--r--boot/Makefile1
-rw-r--r--boot/bootflow.c339
-rw-r--r--boot/bootmeth-uclass.c2
-rw-r--r--boot/bootmeth_cros.c212
-rw-r--r--boot/bootmeth_qfw.c2
-rw-r--r--cmd/Kconfig8
-rw-r--r--cmd/acpi.c24
-rw-r--r--cmd/bdinfo.c27
-rw-r--r--cmd/bootflow.c87
-rw-r--r--cmd/part.c34
-rw-r--r--cmd/qfw.c2
-rw-r--r--cmd/x86/mtrr.c60
-rw-r--r--common/bloblist.c1
-rw-r--r--common/board_f.c12
-rw-r--r--common/board_r.c7
-rw-r--r--common/log.c2
-rw-r--r--common/log_console.c10
-rw-r--r--configs/chromebook_coral_defconfig10
-rw-r--r--configs/coreboot_defconfig14
-rw-r--r--configs/qemu-x86_64_defconfig21
-rw-r--r--configs/qemu-x86_defconfig5
-rw-r--r--configs/tools-only_defconfig1
-rw-r--r--disk/part.c16
-rw-r--r--doc/usage/cmd/acpi.rst29
-rw-r--r--doc/usage/cmd/bootflow.rst100
-rw-r--r--doc/usage/cmd/mtrr.rst151
-rw-r--r--doc/usage/cmd/part.rst74
-rw-r--r--doc/usage/cmd/qfw.rst27
-rw-r--r--doc/usage/index.rst1
-rw-r--r--drivers/Kconfig2
-rw-r--r--drivers/Makefile2
-rw-r--r--drivers/bios_emulator/Kconfig10
-rw-r--r--drivers/bios_emulator/biosemui.h18
-rw-r--r--drivers/bios_emulator/x86emu/sys.c1
-rw-r--r--drivers/gpio/intel_ich6_gpio.c5
-rw-r--r--drivers/misc/qfw.c13
-rw-r--r--drivers/mmc/mmc_bootdev.c2
-rw-r--r--drivers/nvme/nvme.c36
-rw-r--r--drivers/pch/pch9.c6
-rw-r--r--drivers/pci/Kconfig5
-rw-r--r--drivers/pci/pci-uclass.c10
-rw-r--r--drivers/pci/pci_rom.c119
-rw-r--r--drivers/scsi/scsi_bootdev.c2
-rw-r--r--drivers/usb/host/usb_bootdev.c2
-rw-r--r--drivers/video/Kconfig30
-rw-r--r--drivers/video/Makefile1
-rw-r--r--drivers/video/bochs.c123
-rw-r--r--drivers/video/bochs.h36
-rw-r--r--fs/fat/fat.c20
-rw-r--r--fs/fat/fat_write.c14
-rw-r--r--fs/sandbox/host_bootdev.c2
-rw-r--r--include/asm-generic/global_data.h13
-rw-r--r--include/bloblist.h1
-rw-r--r--include/bootdev.h2
-rw-r--r--include/bootflow.h100
-rw-r--r--include/configs/conga-qeval20-qa3-e3845.h2
-rw-r--r--include/configs/dfi-bt700.h2
-rw-r--r--include/configs/minnowmax.h2
-rw-r--r--include/configs/qemu-x86.h8
-rw-r--r--include/configs/som-db5800-som-6867.h2
-rw-r--r--include/configs/theadorable-x86-common.h2
-rw-r--r--include/configs/x86-chromebook.h2
-rw-r--r--include/env_callback.h6
-rw-r--r--include/part.h9
-rw-r--r--include/video.h24
-rw-r--r--lib/efi_loader/efi_acpi.c33
-rw-r--r--lib/uuid.c2
-rw-r--r--net/eth_bootdev.c2
-rw-r--r--test/boot/bootflow.c263
-rw-r--r--test/cmd/bdinfo.c21
-rw-r--r--test/dm/acpi.c38
-rw-r--r--test/test-main.c3
95 files changed, 2424 insertions, 318 deletions
diff --git a/arch/sandbox/include/asm/global_data.h b/arch/sandbox/include/asm/global_data.h
index f4ce72d566..f0ab3ba5c1 100644
--- a/arch/sandbox/include/asm/global_data.h
+++ b/arch/sandbox/include/asm/global_data.h
@@ -13,6 +13,10 @@
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>
diff --git a/arch/x86/cpu/i386/interrupt.c b/arch/x86/cpu/i386/interrupt.c
index fae2544c45..f3f3527237 100644
--- a/arch/x86/cpu/i386/interrupt.c
+++ b/arch/x86/cpu/i386/interrupt.c
@@ -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;
}
diff --git a/arch/x86/cpu/intel_common/mrc.c b/arch/x86/cpu/intel_common/mrc.c
index 69405d740b..56cc253831 100644
--- a/arch/x86/cpu/intel_common/mrc.c
+++ b/arch/x86/cpu/intel_common/mrc.c
@@ -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)
diff --git a/arch/x86/cpu/ivybridge/sdram.c b/arch/x86/cpu/ivybridge/sdram.c
index 1a0ec433e6..0718aefbb1 100644
--- a/arch/x86/cpu/ivybridge/sdram.c
+++ b/arch/x86/cpu/ivybridge/sdram.c
@@ -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;
}
diff --git a/arch/x86/cpu/mtrr.c b/arch/x86/cpu/mtrr.c
index e69dfb552b..d57fcface0 100644
--- a/arch/x86/cpu/mtrr.c
+++ b/arch/x86/cpu/mtrr.c
@@ -30,6 +30,16 @@
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;
+};
diff --git a/arch/x86/cpu/qemu/Kconfig b/arch/x86/cpu/qemu/Kconfig
index f8f2f64730..aa329b0dab 100644
--- a/arch/x86/cpu/qemu/Kconfig
+++ b/arch/x86/cpu/qemu/Kconfig
@@ -12,7 +12,7 @@ config QEMU
imply SYS_NS16550
imply USB
imply USB_EHCI_HCD
- imply VIDEO_VESA
+ imply VIDEO_BOCHS
if QEMU
diff --git a/arch/x86/cpu/start64.S b/arch/x86/cpu/start64.S
index 7be834788b..78e894d2a2 100644
--- a/arch/x86/cpu/start64.S
+++ b/arch/x86/cpu/start64.S
@@ -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
diff --git a/arch/x86/dts/chromebook_link.dts b/arch/x86/dts/chromebook_link.dts
index 36956f40bd..c904b7d0b6 100644
--- a/arch/x86/dts/chromebook_link.dts
+++ b/arch/x86/dts/chromebook_link.dts
@@ -314,6 +314,7 @@
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
diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h
index 22d103df4e..ea58259ad7 100644
--- a/arch/x86/include/asm/global_data.h
+++ b/arch/x86/include/asm/global_data.h
@@ -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
diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h
index ca2edc7878..2e995f5406 100644
--- a/arch/x86/include/asm/mtrr.h
+++ b/arch/x86/include/asm/mtrr.h
@@ -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)
diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h
index 8f38c2d1c6..02a8b0f152 100644
--- a/arch/x86/include/asm/u-boot-x86.h
+++ b/arch/x86/include/asm/u-boot-x86.h
@@ -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);
diff --git a/arch/x86/include/asm/zimage.h b/arch/x86/include/asm/zimage.h
index 000b38ea89..9ad74dc0b9 100644
--- a/arch/x86/include/asm/zimage.h
+++ b/arch/x86/include/asm/zimage.h
@@ -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
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index b0612ae6dd..90a7618ecf 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -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
diff --git a/arch/x86/lib/bdinfo.c b/arch/x86/lib/bdinfo.c
index 15390070fe..124058442c 100644
--- a/arch/x86/lib/bdinfo.c
+++ b/arch/x86/lib/bdinfo.c
@@ -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();
diff --git a/arch/x86/lib/bios.c b/arch/x86/lib/bios.c
index 94349ba807..e29cae78e5 100644
--- a/arch/x86/lib/bios.c
+++ b/arch/x86/lib/bios.c
@@ -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;
diff --git a/arch/x86/lib/bootm.c b/arch/x86/lib/bootm.c
index 61cb7bc611..3196f9ddc2 100644
--- a/arch/x86/lib/bootm.c
+++ b/arch/x86/lib/bootm.c
@@ -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
diff --git a/arch/x86/lib/mrccache.c b/arch/x86/lib/mrccache.c
index 2f6f688000..6494b8d263 100644
--- a/arch/x86/lib/mrccache.c
+++ b/arch/x86/lib/mrccache.c
@@ -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);
diff --git a/arch/x86/lib/spl.c b/arch/x86/lib/spl.c
index ca1645f9d6..b6812bb8ca 100644
--- a/arch/x86/lib/spl.c
+++ b/arch/x86/lib/spl.c
@@ -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>
@@ -15,10 +17,12 @@
#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);
+ }
}
diff --git a/arch/x86/lib/tables.c b/arch/x86/lib/tables.c
index ea834a5035..67bc0a72ae 100644
--- a/arch/x86/lib/tables.c
+++ b/arch/x86/lib/tables.c
@@ -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;
diff --git a/arch/x86/lib/zimage.c b/arch/x86/lib/zimage.c
index e5ea5129c1..062e3d3e31 100644
--- a/arch/x86/lib/zimage.c
+++ b/arch/x86/lib/zimage.c
@@ -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);
diff --git a/board/google/Kconfig b/board/google/Kconfig
index a0f1a60976..e4f9b5b68a 100644
--- a/board/google/Kconfig
+++ b/board/google/Kconfig
@@ -4,13 +4,6 @@
if VENDOR_GOOGLE
-config BIOSEMU
- bool
- select X86EMU_RAW_IO
-
-config X86EMU_RAW_IO
- bool
-
choice
prompt "Mainboard model"
optional
diff --git a/board/sandbox/sandbox.c b/board/sandbox/sandbox.c
index c7b6cb78ff..9d58860451 100644
--- a/board/sandbox/sandbox.c
+++ b/board/sandbox/sandbox.c
@@ -11,16 +11,18 @@
#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
diff --git a/boot/Kconfig b/boot/Kconfig
index c8b8f36d83..b424265df8 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -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
diff --git a/boot/Makefile b/boot/Makefile
index f828f870a3..10f0157223 100644
--- a/boot/Makefile
+++ b/boot/Makefile
@@ -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
diff --git a/boot/bootflow.c b/boot/bootflow.c
index 8f2cb876bb..81b5829d5b 100644
--- a/boot/bootflow.c
+++ b/boot/bootflow.c
@@ -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;
+}
diff --git a/boot/bootmeth-uclass.c b/boot/bootmeth-uclass.c
index 701ee8ad1c..eeded08dd4 100644
--- a/boot/bootmeth-uclass.c
+++ b/boot/bootmeth-uclass.c
@@ -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
index 0000000000..aa19ae097f
--- /dev/null
+++ b/boot/bootmeth_cros.c
@@ -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,
+};
diff --git a/boot/bootmeth_qfw.c b/boot/bootmeth_qfw.c
index ecd4b082fd..8ebbc3ebcd 100644
--- a/boot/bootmeth_qfw.c
+++ b/boot/bootmeth_qfw.c
@@ -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;
}
diff --git a/cmd/Kconfig b/cmd/Kconfig
index fd76972eaa..ecfd575237 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -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
diff --git a/cmd/acpi.c b/cmd/acpi.c
index e70913e40b..ede9c8c7dc 100644
--- a/cmd/acpi.c
+++ b/cmd/acpi.c
@@ -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));
diff --git a/cmd/bdinfo.c b/cmd/bdinfo.c
index 365357ca54..1fe13ca13a 100644
--- a/cmd/bdinfo.c
+++ b/cmd/bdinfo.c
@@ -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();
diff --git a/cmd/bootflow.c b/cmd/bootflow.c
index 5c61286a2a..c0aa4f84fe 100644
--- a/cmd/bootflow.c
+++ b/cmd/bootflow.c
@@ -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
);
diff --git a/cmd/part.c b/cmd/part.c
index 28f2b7ff9b..0ce190005d 100644
--- a/cmd/part.c
+++ b/cmd/part.c
@@ -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"
);
diff --git a/cmd/qfw.c b/cmd/qfw.c
index ae3c6a7a84..d6ecfa60d5 100644
--- 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;
diff --git a/cmd/x86/mtrr.c b/cmd/x86/mtrr.c
index b1691d8b65..6ad7a123a4 100644
--- a/cmd/x86/mtrr.c
+++ b/cmd/x86/mtrr.c
@@ -10,71 +10,19 @@
#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) : "",
diff --git a/common/bloblist.c b/common/bloblist.c
index 0d63b6e881..2144b10e1d 100644
--- a/common/bloblist.c
+++ b/common/bloblist.c
@@ -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 */
};
diff --git a/common/board_f.c b/common/board_f.c
index 334d04af19..e5969ec9a2 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -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,
diff --git a/common/board_r.c b/common/board_r.c
index d798c00a80..4aaa894031 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -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;
}
diff --git a/common/log.c b/common/log.c
index 6f02a25c59..b2de57fcb3 100644
--- a/common/log.c
+++ b/common/log.c
@@ -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) {
diff --git a/common/log_console.c b/common/log_console.c
index f1dcc04b97..bb091ce21a 100644
--- a/common/log_console.c
+++ b/common/log_console.c
@@ -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);
diff --git a/configs/chromebook_coral_defconfig b/configs/chromebook_coral_defconfig
index f5995f2200..fe61153b93 100644
--- a/configs/chromebook_coral_defconfig
+++ b/configs/chromebook_coral_defconfig
@@ -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
diff --git a/configs/coreboot_defconfig b/configs/coreboot_defconfig
index 0f3512d23c..fc93561002 100644
--- a/configs/coreboot_defconfig
+++ b/configs/coreboot_defconfig
@@ -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
diff --git a/configs/qemu-x86_64_defconfig b/configs/qemu-x86_64_defconfig
index 6a539a859e..4a15c51671 100644
--- a/configs/qemu-x86_64_defconfig
+++ b/configs/qemu-x86_64_defconfig
@@ -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
diff --git a/configs/qemu-x86_defconfig b/configs/qemu-x86_defconfig
index a7c37b8b0e..95a6ff9ae7 100644
--- a/configs/qemu-x86_defconfig
+++ b/configs/qemu-x86_defconfig
@@ -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
diff --git a/configs/tools-only_defconfig b/configs/tools-only_defconfig
index 2bc3bd9e91..3f588ea69b 100644
--- a/configs/tools-only_defconfig
+++ b/configs/tools-only_defconfig
@@ -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"
diff --git a/disk/part.c b/disk/part.c
index 35300df590..1d2117ab71 100644
--- a/disk/part.c
+++ b/disk/part.c
@@ -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;
diff --git a/doc/usage/cmd/acpi.rst b/doc/usage/cmd/acpi.rst
index 14bafc8e35..6b9b8949f3 100644
--- a/doc/usage/cmd/acpi.rst
+++ b/doc/usage/cmd/acpi.rst
@@ -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
diff --git a/doc/usage/cmd/bootflow.rst b/doc/usage/cmd/bootflow.rst
index 8590efca21..a8af1f8f60 100644
--- a/doc/usage/cmd/bootflow.rst
+++ b/doc/usage/cmd/bootflow.rst
@@ -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
index 0000000000..531153bb3e
--- /dev/null
+++ b/doc/usage/cmd/mtrr.rst
@@ -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
+ =>
diff --git a/doc/usage/cmd/part.rst b/doc/usage/cmd/part.rst
index 8d2a280391..8a594aaff2 100644
--- a/doc/usage/cmd/part.rst
+++ b/doc/usage/cmd/part.rst
@@ -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
------------
diff --git a/doc/usage/cmd/qfw.rst b/doc/usage/cmd/qfw.rst
index cc0e27c277..ec13e0967a 100644
--- a/doc/usage/cmd/qfw.rst
+++ b/doc/usage/cmd/qfw.rst
@@ -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:
diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index f2ffd2787a..072db53614 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -76,6 +76,7 @@ Shell commands
cmd/md
cmd/mmc
cmd/mtest
+ cmd/mtrr
cmd/panic
cmd/part
cmd/pause
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 75937fbb6d..a25f6ae02f 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -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"
diff --git a/drivers/Makefile b/drivers/Makefile
index 78dcf62f76..3bc6d279d7 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -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
index 0000000000..3660576772
--- /dev/null
+++ b/drivers/bios_emulator/Kconfig
@@ -0,0 +1,10 @@
+config BIOSEMU
+ bool
+ select X86EMU_RAW_IO
+
+config SPL_BIOSEMU
+ bool
+ select X86EMU_RAW_IO
+
+config X86EMU_RAW_IO
+ bool
diff --git a/drivers/bios_emulator/biosemui.h b/drivers/bios_emulator/biosemui.h
index 7853015c1e..954cd88315 100644
--- a/drivers/bios_emulator/biosemui.h
+++ b/drivers/bios_emulator/biosemui.h
@@ -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 --------------------------*/
diff --git a/drivers/bios_emulator/x86emu/sys.c b/drivers/bios_emulator/x86emu/sys.c
index c2db1213fe..882a8a34cc 100644
--- a/drivers/bios_emulator/x86emu/sys.c
+++ b/drivers/bios_emulator/x86emu/sys.c
@@ -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];
diff --git a/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c
index 63a07b9592..2ed0d0bea9 100644
--- a/drivers/gpio/intel_ich6_gpio.c
+++ b/drivers/gpio/intel_ich6_gpio.c
@@ -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;
}
diff --git a/drivers/misc/qfw.c b/drivers/misc/qfw.c
index 9ef95caa89..7c01bf23d5 100644
--- a/drivers/misc/qfw.c
+++ b/drivers/misc/qfw.c
@@ -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;
}
diff --git a/drivers/mmc/mmc_bootdev.c b/drivers/mmc/mmc_bootdev.c
index b57b8a6227..55ecead2dd 100644
--- a/drivers/mmc/mmc_bootdev.c
+++ b/drivers/mmc/mmc_bootdev.c
@@ -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>
diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c
index 74e7a5b011..a7add66ab4 100644
--- a/drivers/nvme/nvme.c
+++ b/drivers/nvme/nvme.c
@@ -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);
diff --git a/drivers/pch/pch9.c b/drivers/pch/pch9.c
index 3bd011518b..3137eb2c28 100644
--- a/drivers/pch/pch9.c
+++ b/drivers/pch/pch9.c
@@ -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;
}
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 84a2ae951f..aca439d921 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -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
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c
index 8d27e40338..632c1a63cf 100644
--- a/drivers/pci/pci-uclass.c
+++ b/drivers/pci/pci-uclass.c
@@ -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;
diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c
index f0dfe63149..438583aa01 100644
--- a/drivers/pci/pci_rom.c
+++ b/drivers/pci/pci_rom.c
@@ -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;
}
diff --git a/drivers/scsi/scsi_bootdev.c b/drivers/scsi/scsi_bootdev.c
index 991013fe1e..218221fa30 100644
--- a/drivers/scsi/scsi_bootdev.c
+++ b/drivers/scsi/scsi_bootdev.c
@@ -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>
diff --git a/drivers/usb/host/usb_bootdev.c b/drivers/usb/host/usb_bootdev.c
index 06e8f61aa1..7fa1c601df 100644
--- a/drivers/usb/host/usb_bootdev.c
+++ b/drivers/usb/host/usb_bootdev.c
@@ -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>
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index b209cb7169..b8147f280c 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -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
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index d710c1f2ef..d13af9f3b1 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -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
index 0000000000..2136b51193
--- /dev/null
+++ b/drivers/video/bochs.c
@@ -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
index 0000000000..4c8ec83a55
--- /dev/null
+++ b/drivers/video/bochs.h
@@ -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
diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index 2da93dae3c..d1476aa433 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -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;
}
diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c
index 413fc432eb..e2a9913f80 100644
--- a/fs/fat/fat_write.c
+++ b/fs/fat/fat_write.c
@@ -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;
}
diff --git a/fs/sandbox/host_bootdev.c b/fs/sandbox/host_bootdev.c
index 0d12ee4ef7..3ef5362760 100644
--- a/fs/sandbox/host_bootdev.c
+++ b/fs/sandbox/host_bootdev.c
@@ -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>
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index a1e1b9d640..8fc205ded1 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -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
*
diff --git a/include/bloblist.h b/include/bloblist.h
index 2a2f1700eb..7ea72c6bd4 100644
--- a/include/bloblist.h
+++ b/include/bloblist.h
@@ -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
diff --git a/include/bootdev.h b/include/bootdev.h
index e72ef3650f..1533adfe50 100644
--- a/include/bootdev.h
+++ b/include/bootdev.h
@@ -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
diff --git a/include/bootflow.h b/include/bootflow.h
index f20f575030..4152577afb 100644
--- a/include/bootflow.h
+++ b/include/bootflow.h
@@ -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
diff --git a/include/configs/conga-qeval20-qa3-e3845.h b/include/configs/conga-qeval20-qa3-e3845.h
index 60617e6fec..03c364f29f 100644
--- a/include/configs/conga-qeval20-qa3-e3845.h
+++ b/include/configs/conga-qeval20-qa3-e3845.h
@@ -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" \
diff --git a/include/configs/dfi-bt700.h b/include/configs/dfi-bt700.h
index 05389a435b..be095e28a1 100644
--- a/include/configs/dfi-bt700.h
+++ b/include/configs/dfi-bt700.h
@@ -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" \
diff --git a/include/configs/minnowmax.h b/include/configs/minnowmax.h
index 4a12c2f72c..842672d557 100644
--- a/include/configs/minnowmax.h
+++ b/include/configs/minnowmax.h
@@ -17,6 +17,4 @@
"stderr=vidconsole,serial\0" \
"usb_pgood_delay=40\0"
-#define VIDEO_IO_OFFSET 0
-
#endif /* __CONFIG_H */
diff --git a/include/configs/qemu-x86.h b/include/configs/qemu-x86.h
index 33263a46a4..3e5235291a 100644
--- a/include/configs/qemu-x86.h
+++ b/include/configs/qemu-x86.h
@@ -12,14 +12,6 @@
#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" \
diff --git a/include/configs/som-db5800-som-6867.h b/include/configs/som-db5800-som-6867.h
index b2e7aa1514..5f7eabd3fc 100644
--- a/include/configs/som-db5800-som-6867.h
+++ b/include/configs/som-db5800-som-6867.h
@@ -16,6 +16,4 @@
"stdout=serial,vidconsole\0" \
"stderr=serial,vidconsole\0"
-#define VIDEO_IO_OFFSET 0
-
#endif /* __CONFIG_H */
diff --git a/include/configs/theadorable-x86-common.h b/include/configs/theadorable-x86-common.h
index b23b878307..46aef23821 100644
--- a/include/configs/theadorable-x86-common.h
+++ b/include/configs/theadorable-x86-common.h
@@ -15,8 +15,6 @@
"stdout=serial\0" \
"stderr=serial\0"
-#define VIDEO_IO_OFFSET 0
-
/* Environment settings */
#undef CFG_EXTRA_ENV_SETTINGS
diff --git a/include/configs/x86-chromebook.h b/include/configs/x86-chromebook.h
index 98abb00927..6bf90c7de4 100644
--- a/include/configs/x86-chromebook.h
+++ b/include/configs/x86-chromebook.h
@@ -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"
diff --git a/include/env_callback.h b/include/env_callback.h
index a9a14f2a84..23bc650c16 100644
--- a/include/env_callback.h
+++ b/include/env_callback.h
@@ -60,8 +60,10 @@
#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
diff --git a/include/part.h b/include/part.h
index be75c73549..3b1b539869 100644
--- a/include/part.h
+++ b/include/part.h
@@ -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; }
diff --git a/include/video.h b/include/video.h
index e98d0f9c89..9729fa348a 100644
--- a/include/video.h
+++ b/include/video.h
@@ -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,
diff --git a/lib/efi_loader/efi_acpi.c b/lib/efi_loader/efi_acpi.c
index 2ddc3502b5..f755af76f8 100644
--- a/lib/efi_loader/efi_acpi.c
+++ b/lib/efi_loader/efi_acpi.c
@@ -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);
}
diff --git a/lib/uuid.c b/lib/uuid.c
index 96e1af3c8b..ab30fbf915 100644
--- a/lib/uuid.c
+++ b/lib/uuid.c
@@ -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 },
diff --git a/net/eth_bootdev.c b/net/eth_bootdev.c
index f7b4196f78..869adf8cbb 100644
--- a/net/eth_bootdev.c
+++ b/net/eth_bootdev.c
@@ -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>
diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c
index 2b5f87d7f0..8a4e090e9b 100644
--- a/test/boot/bootflow.c
+++ b/test/boot/bootflow.c
@@ -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);
diff --git a/test/cmd/bdinfo.c b/test/cmd/bdinfo.c
index cddf1a46d4..8c09281cac 100644
--- a/test/cmd/bdinfo.c
+++ b/test/cmd/bdinfo.c
@@ -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;
diff --git a/test/dm/acpi.c b/test/dm/acpi.c
index 818f71572c..77eb524b59 100644
--- a/test/dm/acpi.c
+++ b/test/dm/acpi.c
@@ -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);
diff --git a/test/test-main.c b/test/test-main.c
index 2a3b2ba364..778bf0a18a 100644
--- a/test/test-main.c
+++ b/test/test-main.c
@@ -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)) &&