[PATCH v4 00/16] x86: Various minor enhancements for coreboot

This series includes some patches generated while getting U-Boot to boot more nicely on Brya, an Adler Lake Chromebook.
This includes: - show the ACPI tables with 'acpi list' - get the UART to work even if coreboot doesn't enable it - show unimplemented sysinfo tags - fix for keyboard not working - fix for trying to set up PCI regions when the info is not available - fix for looking at inaccessible memory to find the sysinfo table
Changes in v4: - Split out patch to enable bus mastering - Drop unnecessary CONFIG options - Drop patch to allow locating UARTs by device ID
Changes in v3: - Don't enable ACPI by default except on x86 and sandbox - Avoid a build error with the ASL compiler - Disable for coreboot64 since ACPI is not available
Changes in v2: - Don't show an invalid CPU number on error - Update commit message with more detail - Update code comment to mention that addresses <1KB are ignored - Flush the buffer instead of skipping the reset - Add new patch to create a new Kconfig for ACPI - Add new patch to move acpi-table-finding functions into the library - Use tab instead of space in header file - Refactor two patches into one - Add new patch to allow locating the UART from ACPI tables - Expand commit message to explain this is for the debug UART - Update the defconfig instead - Drop patch 'usb: Quieten a debug message' since it was fixed elsewhere - Drop patch 'x86: coreboot: Use a memory-mapped UART' (not needed) - Add new patch to enable ms command
Simon Glass (16): mtrr: Don't show an invalid CPU number x86: Adjust search range for sysinfo table input: Flush the keyboard buffer before resetting it acpi: Create a new Kconfig for ACPI acpi: Move the table-finding functions into the libary x86: coreboot: Collect the address of the ACPI tables x86: Allow locating the UART from ACPI tables pci: coreboot: Don't read regions when booting x86: coreboot: Use a memory-mapped UART x86: coreboot: Document how to enable the debug UART x86: coreboot: Scan PCI after relocation x86: coreboot: Log function names and line numbers x86: coreboot: Show unimplemented sysinfo tags nvme: Enable PCI bus mastering x86: nvme: coreboot: Enable NVMe coreboot: Enable ms command
arch/Kconfig | 2 + arch/x86/cpu/cpu.c | 4 +- arch/x86/include/asm/cb_sysinfo.h | 8 ++ arch/x86/include/asm/coreboot_tables.h | 2 + arch/x86/lib/coreboot/cb_sysinfo.c | 13 +++ cmd/Kconfig | 2 +- cmd/acpi.c | 44 ++-------- cmd/x86/cbsysinfo.c | 9 ++ cmd/x86/mtrr.c | 3 +- configs/coreboot64_defconfig | 1 - configs/coreboot_defconfig | 8 +- doc/board/coreboot/coreboot.rst | 29 +++++++ drivers/core/Kconfig | 1 + drivers/input/i8042.c | 19 +++++ drivers/nvme/nvme_pci.c | 5 ++ drivers/pci/pci-uclass.c | 4 + drivers/serial/Kconfig | 10 +++ drivers/serial/serial_coreboot.c | 114 +++++++++++++++++++++++-- include/acpi/acpi_table.h | 8 ++ include/asm-generic/global_data.h | 4 +- lib/Kconfig | 10 ++- lib/Makefile | 2 +- lib/acpi/Makefile | 6 ++ lib/acpi/acpi.c | 45 ++++++++++ 24 files changed, 296 insertions(+), 57 deletions(-) create mode 100644 lib/acpi/acpi.c

When U-Boot did not do the MP init, we don't get an actual CPU number here. Skip printing it in that case.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
(no changes since v2)
Changes in v2: - Don't show an invalid CPU number on error
cmd/x86/mtrr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/cmd/x86/mtrr.c b/cmd/x86/mtrr.c index b213a942fde..b1691d8b65a 100644 --- a/cmd/x86/mtrr.c +++ b/cmd/x86/mtrr.c @@ -148,7 +148,8 @@ static int do_mtrr(struct cmd_tbl *cmdtp, int flag, int argc, printf("CPU %d:\n", i); ret = do_mtrr_list(reg_count, i); if (ret) { - printf("Failed to read CPU %d (err=%d)\n", i, + printf("Failed to read CPU %s (err=%d)\n", + i < MP_SELECT_ALL ? simple_itoa(i) : "", ret); return CMD_RET_FAILURE; }

Avoid searching starting at 0 since this memory may not be available, e.g. if protection against NULL-pointer access is enabled. The table cannot be there anyway, since the first 1KB of memory was originally used for the interrupt table and coreboot avoids it.
Start at 0x400 instead.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
(no changes since v2)
Changes in v2: - Update commit message with more detail - Update code comment to mention that addresses <1KB are ignored
arch/x86/cpu/cpu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c index 6fe6eaf6c84..dddd281e966 100644 --- a/arch/x86/cpu/cpu.c +++ b/arch/x86/cpu/cpu.c @@ -351,8 +351,8 @@ long locate_coreboot_table(void) { long addr;
- /* We look for LBIO in the first 4K of RAM and again at 960KB */ - addr = detect_coreboot_table_at(0x0, 0x1000); + /* We look for LBIO from addresses 1K-4K and again at 960KB */ + addr = detect_coreboot_table_at(0x400, 0xc00); if (addr < 0) addr = detect_coreboot_table_at(0xf0000, 0x1000);

If U-Boot is not the first-stage bootloader the keyboard may already be set up. Make sure to flush any data before trying to reset it. This avoids a long timeout / hang.
Add some comments and a log category while we are here.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
(no changes since v2)
Changes in v2: - Flush the buffer instead of skipping the reset
drivers/input/i8042.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
diff --git a/drivers/input/i8042.c b/drivers/input/i8042.c index 3563dc98838..e6070ca0152 100644 --- a/drivers/input/i8042.c +++ b/drivers/input/i8042.c @@ -6,6 +6,8 @@
/* i8042.c - Intel 8042 keyboard driver routines */
+#define LOG_CATEGORY UCLASS_KEYBOARD + #include <common.h> #include <dm.h> #include <env.h> @@ -54,6 +56,14 @@ static unsigned char ext_key_map[] = { 0x00 /* map end */ };
+/** + * kbd_input_empty() - Wait until the keyboard is ready for a command + * + * Checks the IBF flag (input buffer full), waiting for it to indicate that + * any previous command has been processed. + * + * Return: true if ready, false if it timed out + */ static int kbd_input_empty(void) { int kbd_timeout = KBD_TIMEOUT * 1000; @@ -64,6 +74,12 @@ static int kbd_input_empty(void) return kbd_timeout != -1; }
+/** + * kbd_output_full() - Wait until the keyboard has data available + * + * Checks the OBF flag (output buffer full), waiting for it to indicate that + * a response to a previous command is available + */ static int kbd_output_full(void) { int kbd_timeout = KBD_TIMEOUT * 1000; @@ -127,6 +143,9 @@ static int kbd_reset(int quirk) { int config;
+ if (!kbd_input_empty()) + goto err; + /* controller self test */ if (kbd_cmd_read(CMD_SELF_TEST) != KBC_TEST_OK) goto err;

We have several Kconfig options for ACPI, but all relate to specific functions, such as generating tables and AML code.
Add a new option which controls including basic ACPI library code, including the lib/acpi directory. This will allow us to add functions which are available even if table generation is not supported.
Adjust the command to avoid a build error when ACPIGEN is not enabled.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
(no changes since v3)
Changes in v3: - Don't enable ACPI by default except on x86 and sandbox
Changes in v2: - Add new patch to create a new Kconfig for ACPI
arch/Kconfig | 2 ++ cmd/Kconfig | 2 +- cmd/acpi.c | 4 ++++ drivers/core/Kconfig | 1 + lib/Kconfig | 10 +++++++++- lib/Makefile | 2 +- lib/acpi/Makefile | 4 ++++ 7 files changed, 22 insertions(+), 3 deletions(-)
diff --git a/arch/Kconfig b/arch/Kconfig index 55b9a5eb8a5..c9a33592252 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -195,6 +195,7 @@ config SANDBOX imply PHYLIB imply DM_MDIO imply DM_MDIO_MUX + imply ACPI imply ACPI_PMC imply ACPI_PMC_SANDBOX imply CMD_PMC @@ -261,6 +262,7 @@ config X86 imply PCH imply PHYSMEM imply RTC_MC146818 + imply ACPI imply ACPIGEN if !QEMU && !EFI_APP imply SYSINFO if GENERATE_SMBIOS_TABLE imply SYSINFO_SMBIOS if GENERATE_SMBIOS_TABLE diff --git a/cmd/Kconfig b/cmd/Kconfig index e45b8847aef..56f5ab02239 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -109,7 +109,7 @@ menu "Info commands"
config CMD_ACPI bool "acpi" - depends on ACPIGEN + depends on ACPI default y help List and dump ACPI tables. ACPI (Advanced Configuration and Power diff --git a/cmd/acpi.c b/cmd/acpi.c index d0fc062ef8c..991b5235e28 100644 --- a/cmd/acpi.c +++ b/cmd/acpi.c @@ -162,6 +162,10 @@ static int do_acpi_items(struct cmd_tbl *cmdtp, int flag, int argc, bool dump_contents;
dump_contents = argc >= 2 && !strcmp("-d", argv[1]); + if (!IS_ENABLED(CONFIG_ACPIGEN)) { + printf("Not supported (enable ACPIGEN)\n"); + return CMD_RET_FAILURE; + } acpi_dump_items(dump_contents ? ACPI_DUMP_CONTENTS : ACPI_DUMP_LIST);
return 0; diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig index 0f755aa702e..f0d848f45d8 100644 --- a/drivers/core/Kconfig +++ b/drivers/core/Kconfig @@ -448,6 +448,7 @@ config OFNODE_MULTI_TREE_MAX
config ACPIGEN bool "Support ACPI table generation in driver model" + depends on ACPI default y if SANDBOX || (GENERATE_ACPI_TABLE && !QEMU) select LIB_UUID help diff --git a/lib/Kconfig b/lib/Kconfig index d8dac09ea84..c8b3ec1ec9c 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -281,9 +281,17 @@ config SUPPORT_ACPI U-Boot can generate these tables and pass them to the Operating System.
+config ACPI + bool "Enable support for ACPI libraries" + depends on SUPPORT_ACPI + help + Provides library functions for dealing with ACPI tables. This does + not necessarily include generation of tables + (see GENERATE_ACPI_TABLE), but allows for tables to be located. + config GENERATE_ACPI_TABLE bool "Generate an ACPI (Advanced Configuration and Power Interface) table" - depends on SUPPORT_ACPI + depends on ACPI select QFW if QEMU help The Advanced Configuration and Power Interface (ACPI) specification diff --git a/lib/Makefile b/lib/Makefile index 10aa7ac0298..8d8ccc8bbc3 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -66,7 +66,7 @@ obj-$(CONFIG_$(SPL_TPL_)CRC8) += crc8.o
obj-y += crypto/
-obj-$(CONFIG_$(SPL_TPL_)GENERATE_ACPI_TABLE) += acpi/ +obj-$(CONFIG_$(SPL_TPL_)ACPI) += acpi/ obj-$(CONFIG_$(SPL_)MD5) += md5.o obj-$(CONFIG_ECDSA) += ecdsa/ obj-$(CONFIG_$(SPL_)RSA) += rsa/ diff --git a/lib/acpi/Makefile b/lib/acpi/Makefile index 956b5a0d726..12337abaecf 100644 --- a/lib/acpi/Makefile +++ b/lib/acpi/Makefile @@ -1,6 +1,8 @@ # SPDX-License-Identifier: GPL-2.0+ #
+ifdef CONFIG_$(SPL_TPL_)GENERATE_ACPI_TABLE + obj-$(CONFIG_$(SPL_)ACPIGEN) += acpigen.o obj-$(CONFIG_$(SPL_)ACPIGEN) += acpi_device.o obj-$(CONFIG_$(SPL_)ACPIGEN) += acpi_dp.o @@ -21,3 +23,5 @@ endif obj-y += facs.o obj-y += ssdt.o endif + +endif # GENERATE_ACPI_TABLE

This is useful for other features. Move the function into library code so it can be used outside just the 'acpi' command.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
(no changes since v3)
Changes in v3: - Avoid a build error with the ASL compiler
Changes in v2: - Add new patch to move acpi-table-finding functions into the library
cmd/acpi.c | 40 +--------------------------------- include/acpi/acpi_table.h | 8 +++++++ lib/acpi/Makefile | 2 ++ lib/acpi/acpi.c | 45 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 56 insertions(+), 39 deletions(-) create mode 100644 lib/acpi/acpi.c
diff --git a/cmd/acpi.c b/cmd/acpi.c index 991b5235e28..e70913e40bf 100644 --- a/cmd/acpi.c +++ b/cmd/acpi.c @@ -36,49 +36,11 @@ static void dump_hdr(struct acpi_table_header *hdr) } }
-/** - * find_table() - Look up an ACPI table - * - * @sig: Signature of table (4 characters, upper case) - * Return: pointer to table header, or NULL if not found - */ -struct acpi_table_header *find_table(const char *sig) -{ - struct acpi_rsdp *rsdp; - struct acpi_rsdt *rsdt; - int len, i, count; - - rsdp = map_sysmem(gd_acpi_start(), 0); - if (!rsdp) - return NULL; - rsdt = map_sysmem(rsdp->rsdt_address, 0); - len = rsdt->header.length - sizeof(rsdt->header); - count = len / sizeof(u32); - for (i = 0; i < count; i++) { - struct acpi_table_header *hdr; - - hdr = map_sysmem(rsdt->entry[i], 0); - if (!memcmp(hdr->signature, sig, ACPI_NAME_LEN)) - return hdr; - if (!memcmp(hdr->signature, "FACP", ACPI_NAME_LEN)) { - struct acpi_fadt *fadt = (struct acpi_fadt *)hdr; - - if (!memcmp(sig, "DSDT", ACPI_NAME_LEN) && fadt->dsdt) - return map_sysmem(fadt->dsdt, 0); - if (!memcmp(sig, "FACS", ACPI_NAME_LEN) && - fadt->firmware_ctrl) - return map_sysmem(fadt->firmware_ctrl, 0); - } - } - - return NULL; -} - static int dump_table_name(const char *sig) { struct acpi_table_header *hdr;
- hdr = find_table(sig); + hdr = acpi_find_table(sig); if (!hdr) return -ENOENT; printf("%.*s @ %08lx\n", ACPI_NAME_LEN, hdr->signature, diff --git a/include/acpi/acpi_table.h b/include/acpi/acpi_table.h index 4030d25c66a..7ed0443c821 100644 --- a/include/acpi/acpi_table.h +++ b/include/acpi/acpi_table.h @@ -923,6 +923,14 @@ int acpi_fill_csrt(struct acpi_ctx *ctx); */ ulong write_acpi_tables(ulong start);
+/** + * acpi_find_table() - Look up an ACPI table + * + * @sig: Signature of table (4 characters, upper case) + * Return: pointer to table header, or NULL if not found + */ +struct acpi_table_header *acpi_find_table(const char *sig); + #endif /* !__ACPI__*/
#include <asm/acpi_table.h> diff --git a/lib/acpi/Makefile b/lib/acpi/Makefile index 12337abaecf..c1c9675b5d2 100644 --- a/lib/acpi/Makefile +++ b/lib/acpi/Makefile @@ -1,6 +1,8 @@ # SPDX-License-Identifier: GPL-2.0+ #
+obj-y += acpi.o + ifdef CONFIG_$(SPL_TPL_)GENERATE_ACPI_TABLE
obj-$(CONFIG_$(SPL_)ACPIGEN) += acpigen.o diff --git a/lib/acpi/acpi.c b/lib/acpi/acpi.c new file mode 100644 index 00000000000..14b15754f49 --- /dev/null +++ b/lib/acpi/acpi.c @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Utility functions for ACPI + * + * Copyright 2023 Google LLC + */ + +#include <common.h> +#include <mapmem.h> +#include <acpi/acpi_table.h> +#include <asm/global_data.h> + +DECLARE_GLOBAL_DATA_PTR; + +struct acpi_table_header *acpi_find_table(const char *sig) +{ + struct acpi_rsdp *rsdp; + struct acpi_rsdt *rsdt; + int len, i, count; + + rsdp = map_sysmem(gd_acpi_start(), 0); + if (!rsdp) + return NULL; + rsdt = map_sysmem(rsdp->rsdt_address, 0); + len = rsdt->header.length - sizeof(rsdt->header); + count = len / sizeof(u32); + for (i = 0; i < count; i++) { + struct acpi_table_header *hdr; + + hdr = map_sysmem(rsdt->entry[i], 0); + if (!memcmp(hdr->signature, sig, ACPI_NAME_LEN)) + return hdr; + if (!memcmp(hdr->signature, "FACP", ACPI_NAME_LEN)) { + struct acpi_fadt *fadt = (struct acpi_fadt *)hdr; + + if (!memcmp(sig, "DSDT", ACPI_NAME_LEN) && fadt->dsdt) + return map_sysmem(fadt->dsdt, 0); + if (!memcmp(sig, "FACS", ACPI_NAME_LEN) && + fadt->firmware_ctrl) + return map_sysmem(fadt->firmware_ctrl, 0); + } + } + + return NULL; +}

At present any ACPI tables created by prior-stage firmware are ignored. It is useful to be able to view these in U-Boot.
Pick this up from the sysinfo tables and display it with the cbsysinfo command. This allows the 'acpi list' command to work when booting from coreboot.
Adjust the global_data condition so that acpi_start is available even if table-generation is disabled.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com
---
(no changes since v2)
Changes in v2: - Use tab instead of space in header file - Refactor two patches into one
arch/x86/include/asm/cb_sysinfo.h | 2 ++ arch/x86/include/asm/coreboot_tables.h | 2 ++ arch/x86/lib/coreboot/cb_sysinfo.c | 11 +++++++++++ cmd/x86/cbsysinfo.c | 1 + include/asm-generic/global_data.h | 4 ++-- 5 files changed, 18 insertions(+), 2 deletions(-)
diff --git a/arch/x86/include/asm/cb_sysinfo.h b/arch/x86/include/asm/cb_sysinfo.h index 0201ac6b03a..6b266149cf6 100644 --- a/arch/x86/include/asm/cb_sysinfo.h +++ b/arch/x86/include/asm/cb_sysinfo.h @@ -133,6 +133,7 @@ * @mtc_size: Size of MTC region * @chromeos_vpd: Chromium OS Vital Product Data region, typically NULL, meaning * not used + * @rsdp: Pointer to ACPI RSDP table */ struct sysinfo_t { unsigned int cpu_khz; @@ -211,6 +212,7 @@ struct sysinfo_t { u64 mtc_start; u32 mtc_size; void *chromeos_vpd; + void *rsdp; };
extern struct sysinfo_t lib_sysinfo; diff --git a/arch/x86/include/asm/coreboot_tables.h b/arch/x86/include/asm/coreboot_tables.h index f131de56a40..4de137fbab9 100644 --- a/arch/x86/include/asm/coreboot_tables.h +++ b/arch/x86/include/asm/coreboot_tables.h @@ -422,6 +422,8 @@ struct cb_tsc_info { #define CB_TAG_SERIALNO 0x002a #define CB_MAX_SERIALNO_LENGTH 32
+#define CB_TAG_ACPI_RSDP 0x0043 + #define CB_TAG_CMOS_OPTION_TABLE 0x00c8
struct cb_cmos_option_table { diff --git a/arch/x86/lib/coreboot/cb_sysinfo.c b/arch/x86/lib/coreboot/cb_sysinfo.c index 748fa4ee53b..a11a2587f66 100644 --- a/arch/x86/lib/coreboot/cb_sysinfo.c +++ b/arch/x86/lib/coreboot/cb_sysinfo.c @@ -264,6 +264,13 @@ static void cb_parse_mrc_cache(void *ptr, struct sysinfo_t *info) info->mrc_cache = map_sysmem(cbmem->cbmem_tab, 0); }
+static void cb_parse_acpi_rsdp(void *ptr, struct sysinfo_t *info) +{ + struct cb_cbmem_tab *const cbmem = (struct cb_cbmem_tab *)ptr; + + info->rsdp = map_sysmem(cbmem->cbmem_tab, 0); +} + __weak void cb_parse_unhandled(u32 tag, unsigned char *ptr) { } @@ -428,6 +435,9 @@ static int cb_parse_header(void *addr, int len, struct sysinfo_t *info) case CB_TAG_MRC_CACHE: cb_parse_mrc_cache(rec, info); break; + case CB_TAG_ACPI_RSDP: + cb_parse_acpi_rsdp(rec, info); + break; default: cb_parse_unhandled(rec->tag, ptr); break; @@ -454,6 +464,7 @@ int get_coreboot_info(struct sysinfo_t *info) if (!ret) return -ENOENT; gd->arch.coreboot_table = addr; + gd_set_acpi_start(map_to_sysmem(info->rsdp)); gd->flags |= GD_FLG_SKIP_LL_INIT;
return 0; diff --git a/cmd/x86/cbsysinfo.c b/cmd/x86/cbsysinfo.c index 34fdaf5b1b1..07570b00c9a 100644 --- a/cmd/x86/cbsysinfo.c +++ b/cmd/x86/cbsysinfo.c @@ -363,6 +363,7 @@ static void show_table(struct sysinfo_t *info, bool verbose) print_hex("MTC size", info->mtc_size);
print_ptr("Chrome OS VPD", info->chromeos_vpd); + print_ptr("RSDP", info->rsdp); }
static int do_cbsysinfo(struct cmd_tbl *cmdtp, int flag, int argc, diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h index 987fb66c17a..422e0cf4720 100644 --- a/include/asm-generic/global_data.h +++ b/include/asm-generic/global_data.h @@ -457,7 +457,7 @@ struct global_data { */ fdt_addr_t translation_offset; #endif -#ifdef CONFIG_GENERATE_ACPI_TABLE +#ifdef CONFIG_ACPI /** * @acpi_ctx: ACPI context pointer */ @@ -536,7 +536,7 @@ static_assert(sizeof(struct global_data) == GD_SIZE); #define gd_dm_priv_base() NULL #endif
-#ifdef CONFIG_GENERATE_ACPI_TABLE +#ifdef CONFIG_ACPI #define gd_acpi_ctx() gd->acpi_ctx #define gd_acpi_start() gd->acpi_start #define gd_set_acpi_start(addr) gd->acpi_start = addr

When coreboot does not pass a UART in its sysinfo struct, there is no easy way to find it out.
Since coreboot does not actually init the serial device when serial is disabled, it is not possible to make it add this information to the sysinfo table.
Add a way to obtain this information from the DBG2 ACPI table, which is normally set up by coreboot.
For now this only supports a memory-mapped 16550-style UART.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
(no changes since v3)
Changes in v3: - Disable for coreboot64 since ACPI is not available
Changes in v2: - Add new patch to allow locating the UART from ACPI tables
drivers/serial/Kconfig | 10 +++ drivers/serial/serial_coreboot.c | 114 ++++++++++++++++++++++++++++--- 2 files changed, 116 insertions(+), 8 deletions(-)
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 7faf6784442..f4767c838f9 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -669,6 +669,16 @@ config COREBOOT_SERIAL a serial console on any platform without needing to change the device tree, etc.
+config COREBOOT_SERIAL_FROM_DBG2 + bool "Obtain UART from ACPI tables" + depends on COREBOOT_SERIAL + default y if !SPL + help + Select this to try to find a DBG2 record in the ACPI tables, in the + event that coreboot does not provide information about the UART in the + normal sysinfo tables. This provides a useful fallback when serial + is not enabled in coreboot. + config CORTINA_UART bool "Cortina UART support" depends on DM_SERIAL diff --git a/drivers/serial/serial_coreboot.c b/drivers/serial/serial_coreboot.c index de09c8681f5..23066e4d054 100644 --- a/drivers/serial/serial_coreboot.c +++ b/drivers/serial/serial_coreboot.c @@ -5,25 +5,123 @@ * Copyright 2019 Google LLC */
+#define LOG_CATGEGORY UCLASS_SERIAL + #include <common.h> #include <dm.h> +#include <log.h> #include <ns16550.h> #include <serial.h> +#include <acpi/acpi_table.h> #include <asm/cb_sysinfo.h>
+DECLARE_GLOBAL_DATA_PTR; + +static int read_dbg2(struct ns16550_plat *plat) +{ + struct acpi_table_header *tab; + struct acpi_dbg2_header *hdr; + struct acpi_dbg2_device *dbg; + struct acpi_gen_regaddr *addr; + u32 *addr_size; + + log_debug("Looking for DBG2 in ACPI tables\n"); + if (!gd->acpi_start) { + log_debug("No ACPI tables\n"); + return -ENOENT; + } + + tab = acpi_find_table("DBG2"); + if (!tab) { + log_debug("No DBG2 table\n"); + return -ENOENT; + } + hdr = container_of(tab, struct acpi_dbg2_header, header); + + /* We only use the first device, but check that there is at least one */ + if (!hdr->devices_count) { + log_debug("No devices\n"); + return -ENOENT; + } + if (hdr->devices_offset >= tab->length) { + log_debug("Invalid offset\n"); + return -EINVAL; + } + dbg = (void *)hdr + hdr->devices_offset; + if (dbg->revision) { + log_debug("Invalid revision %d\n", dbg->revision); + return -EINVAL; + } + if (!dbg->address_count) { + log_debug("No addresses\n"); + return -EINVAL; + } + if (dbg->port_type != ACPI_DBG2_SERIAL_PORT) { + log_debug("Not a serial port\n"); + return -EPROTOTYPE; + } + if (dbg->port_subtype != ACPI_DBG2_16550_COMPATIBLE) { + log_debug("Incompatible serial port\n"); + return -EPROTOTYPE; + } + if (dbg->base_address_offset >= dbg->length || + dbg->address_size_offset >= dbg->length) { + log_debug("Invalid base address/size offsets %d, %d\n", + dbg->base_address_offset, dbg->address_size_offset); + return -EINVAL; + } + addr_size = (void *)dbg + dbg->address_size_offset; + if (!*addr_size) { + log_debug("Zero address size\n"); + return -EINVAL; + } + addr = (void *)dbg + dbg->base_address_offset; + if (addr->space_id != ACPI_ADDRESS_SPACE_MEMORY) { + log_debug("Incompatible space %d\n", addr->space_id); + return -EPROTOTYPE; + } + + plat->base = addr->addrl; + + /* ACPI_ACCESS_SIZE_DWORD_ACCESS is 3; we want 2 */ + plat->reg_shift = addr->access_size - 1; + plat->reg_width = 4; /* coreboot sets bit_width to 0 */ + plat->clock = 1843200; + plat->fcr = UART_FCR_DEFVAL; + plat->flags = 0; + log_debug("Collected UART from ACPI DBG2 table\n"); + + return 0; +} + static int coreboot_of_to_plat(struct udevice *dev) { struct ns16550_plat *plat = dev_get_plat(dev); struct cb_serial *cb_info = lib_sysinfo.serial; + int ret = -ENOENT;
- plat->base = cb_info->baseaddr; - plat->reg_shift = cb_info->regwidth == 4 ? 2 : 0; - plat->reg_width = cb_info->regwidth; - plat->clock = cb_info->input_hertz; - plat->fcr = UART_FCR_DEFVAL; - plat->flags = 0; - if (cb_info->type == CB_SERIAL_TYPE_IO_MAPPED) - plat->flags |= NS16550_FLAG_IO; + if (cb_info) { + plat->base = cb_info->baseaddr; + plat->reg_shift = cb_info->regwidth == 4 ? 2 : 0; + plat->reg_width = cb_info->regwidth; + plat->clock = cb_info->input_hertz; + plat->fcr = UART_FCR_DEFVAL; + plat->flags = 0; + if (cb_info->type == CB_SERIAL_TYPE_IO_MAPPED) + plat->flags |= NS16550_FLAG_IO; + ret = 0; + } else if (IS_ENABLED(CONFIG_COREBOOT_SERIAL_FROM_DBG2)) { + ret = read_dbg2(plat); + } + + if (ret) { + /* + * Returning an error will cause U-Boot to complain that + * there is no UART, which may panic. So stay silent and + * pray that the video console will work. + */ + log_debug("Cannot detect UART\n"); + }
return 0; }

When U-Boot is the second-stage bootloader, PCI is already set up. We cannot read the regions from the device tree. There is no point anyway, since PCI devices have already been allocated according to the regions and it is not safe for U-Boot to make any changes.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com Fixes: f2ebaaa9f38d ("pci: Handle failed calloc in decode_regions()") Tested-by: Christian Gmeiner christian.gmeiner@gmail.com ---
(no changes since v1)
drivers/pci/pci-uclass.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index 9343cfc62a9..8d27e40338c 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -973,6 +973,10 @@ static int decode_regions(struct pci_controller *hose, ofnode parent_node, int len; int i;
+ /* handle booting from coreboot, etc. */ + if (!ll_boot_init()) + return 0; + prop = ofnode_get_property(node, "ranges", &len); if (!prop) { debug("%s: Cannot decode regions\n", __func__);

This is much more common on modern hardware, so default to using it.
This does not affect the normal UART, but does allow the debug UART to work, since it uses serial_out_shift(), etc.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
(no changes since v2)
Changes in v2: - Expand commit message to explain this is for the debug UART - Update the defconfig instead
configs/coreboot64_defconfig | 1 - configs/coreboot_defconfig | 1 - 2 files changed, 2 deletions(-)
diff --git a/configs/coreboot64_defconfig b/configs/coreboot64_defconfig index ec672e59e89..60a1924e9e5 100644 --- a/configs/coreboot64_defconfig +++ b/configs/coreboot64_defconfig @@ -62,7 +62,6 @@ CONFIG_ATAPI=y CONFIG_LBA48=y CONFIG_SYS_64BIT_LBA=y # CONFIG_PCI_PNP is not set -CONFIG_SYS_NS16550_PORT_MAPPED=y CONFIG_SOUND=y CONFIG_SOUND_I8254=y CONFIG_CONSOLE_SCROLL_LINES=5 diff --git a/configs/coreboot_defconfig b/configs/coreboot_defconfig index 4db72899169..fb4d1751108 100644 --- a/configs/coreboot_defconfig +++ b/configs/coreboot_defconfig @@ -56,7 +56,6 @@ CONFIG_ATAPI=y CONFIG_LBA48=y CONFIG_SYS_64BIT_LBA=y # CONFIG_PCI_PNP is not set -CONFIG_SYS_NS16550_PORT_MAPPED=y CONFIG_SOUND=y CONFIG_SOUND_I8254=y CONFIG_CONSOLE_SCROLL_LINES=5

This is not obvious so add a little note about how it works.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
(no changes since v1)
doc/board/coreboot/coreboot.rst | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+)
diff --git a/doc/board/coreboot/coreboot.rst b/doc/board/coreboot/coreboot.rst index 4a5f101cad2..0fe95af56d2 100644 --- a/doc/board/coreboot/coreboot.rst +++ b/doc/board/coreboot/coreboot.rst @@ -71,3 +71,32 @@ Memory map (typically redirects to 7ab10030 or similar) 500 Location of coreboot sysinfo table, used during startup ========== ================================================================== + + +Debug UART +---------- + +It is possible to enable the debug UART with coreboot. To do this, use the +info from the cbsysinfo command to locate the UART base. For example:: + + => cbsysinfo + ... + Serial I/O port: 00000000 + base : 00000000 + pointer : 767b51bc + type : 2 + base : fe03e000 + baud : 0d115200 + regwidth : 4 + input_hz : 0d1843200 + PCI addr : 00000010 + ... + +Here you can see that the UART base is fe03e000, regwidth is 4 (1 << 2) and the +input clock is 1843200. So you can add the following CONFIG options:: + + CONFIG_DEBUG_UART=y + CONFIG_DEBUG_UART_BASE=fe03e000 + CONFIG_DEBUG_UART_CLOCK=1843200 + CONFIG_DEBUG_UART_SHIFT=2 + CONFIG_DEBUG_UART_ANNOUNCE=y

Enable this so that PCI devices can be used correctly without needing to do a manual scan.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
(no changes since v1)
configs/coreboot_defconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/configs/coreboot_defconfig b/configs/coreboot_defconfig index fb4d1751108..1bbb358a022 100644 --- a/configs/coreboot_defconfig +++ b/configs/coreboot_defconfig @@ -18,6 +18,7 @@ CONFIG_PRE_CONSOLE_BUFFER=y CONFIG_SYS_CONSOLE_INFO_QUIET=y 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_IDE=y

Turn these options on to make it easier to debug things.
Also enable dhrystone so we can get some measure of performance.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
(no changes since v1)
configs/coreboot_defconfig | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/configs/coreboot_defconfig b/configs/coreboot_defconfig index 1bbb358a022..3030e5bf93b 100644 --- a/configs/coreboot_defconfig +++ b/configs/coreboot_defconfig @@ -16,6 +16,9 @@ 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 +CONFIG_LOGF_LINE=y +CONFIG_LOGF_FUNC=y CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_LAST_STAGE_INIT=y CONFIG_PCI_INIT_R=y @@ -60,5 +63,6 @@ CONFIG_SYS_64BIT_LBA=y CONFIG_SOUND=y CONFIG_SOUND_I8254=y CONFIG_CONSOLE_SCROLL_LINES=5 +CONFIG_CMD_DHRYSTONE=y # CONFIG_GZIP is not set CONFIG_SMBIOS_PARSER=y

Sometimes coreboot adds new tags that U-Boot does not know about. These are silently ignored, but it is useful to at least know what we are missing.
Add a way to collect this information. For Brya it shows:
Unimpl. 38 41 37 34 42 40
These are:
LB_TAG_PLATFORM_BLOB_VERSION LB_TAG_ACPI_CNVS LB_TAG_FMAP LB_TAG_VBOOT_WORKBUF LB_TAG_TYPE_C_INFO LB_TAG_BOARD_CONFIG
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
(no changes since v1)
arch/x86/include/asm/cb_sysinfo.h | 6 ++++++ arch/x86/lib/coreboot/cb_sysinfo.c | 2 ++ cmd/x86/cbsysinfo.c | 8 ++++++++ 3 files changed, 16 insertions(+)
diff --git a/arch/x86/include/asm/cb_sysinfo.h b/arch/x86/include/asm/cb_sysinfo.h index 6b266149cf6..2c78b22d0d2 100644 --- a/arch/x86/include/asm/cb_sysinfo.h +++ b/arch/x86/include/asm/cb_sysinfo.h @@ -16,6 +16,8 @@ #define SYSINFO_MAX_GPIOS 8 /* Up to 10 MAC addresses */ #define SYSINFO_MAX_MACS 10 +/* Track the first 32 unimplemented tags */ +#define SYSINFO_MAX_UNIMPL 32
/** * struct sysinfo_t - Information passed to U-Boot from coreboot @@ -134,6 +136,8 @@ * @chromeos_vpd: Chromium OS Vital Product Data region, typically NULL, meaning * not used * @rsdp: Pointer to ACPI RSDP table + * @unimpl_count: Number of entries in unimpl_map[] + * @unimpl: List of unimplemented IDs (bottom 8 bits only) */ struct sysinfo_t { unsigned int cpu_khz; @@ -213,6 +217,8 @@ struct sysinfo_t { u32 mtc_size; void *chromeos_vpd; void *rsdp; + u32 unimpl_count; + u8 unimpl[SYSINFO_MAX_UNIMPL]; };
extern struct sysinfo_t lib_sysinfo; diff --git a/arch/x86/lib/coreboot/cb_sysinfo.c b/arch/x86/lib/coreboot/cb_sysinfo.c index a11a2587f66..42cc3a128d9 100644 --- a/arch/x86/lib/coreboot/cb_sysinfo.c +++ b/arch/x86/lib/coreboot/cb_sysinfo.c @@ -439,6 +439,8 @@ static int cb_parse_header(void *addr, int len, struct sysinfo_t *info) cb_parse_acpi_rsdp(rec, info); break; default: + if (info->unimpl_count < SYSINFO_MAX_UNIMPL) + info->unimpl[info->unimpl_count++] = rec->tag; cb_parse_unhandled(rec->tag, ptr); break; } diff --git a/cmd/x86/cbsysinfo.c b/cmd/x86/cbsysinfo.c index 07570b00c9a..2b8d3b0a435 100644 --- a/cmd/x86/cbsysinfo.c +++ b/cmd/x86/cbsysinfo.c @@ -364,6 +364,14 @@ static void show_table(struct sysinfo_t *info, bool verbose)
print_ptr("Chrome OS VPD", info->chromeos_vpd); print_ptr("RSDP", info->rsdp); + printf("%-12s: ", "Unimpl."); + if (info->unimpl_count) { + for (i = 0; i < info->unimpl_count; i++) + printf("%02x ", info->unimpl[i]); + printf("\n"); + } else { + printf("(none)\n"); + } }
static int do_cbsysinfo(struct cmd_tbl *cmdtp, int flag, int argc,

U-Boot sets up devices ready for use, but coreboot does not. Enable this so that NVMe works OK from coreboot.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v4: - Split out patch to enable bus mastering
drivers/nvme/nvme_pci.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/nvme/nvme_pci.c b/drivers/nvme/nvme_pci.c index 36bf9c5ffb7..5bb43d299fc 100644 --- a/drivers/nvme/nvme_pci.c +++ b/drivers/nvme/nvme_pci.c @@ -6,6 +6,7 @@
#include <common.h> #include <dm.h> +#include <init.h> #include <pci.h> #include "nvme.h"
@@ -30,6 +31,10 @@ static int nvme_probe(struct udevice *udev) ndev->instance = trailing_strtol(udev->name); ndev->bar = dm_pci_map_bar(udev, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_TYPE, PCI_REGION_MEM); + + /* Turn on bus-mastering */ + dm_pci_clrset_config16(udev, PCI_COMMAND, 0, PCI_COMMAND_MASTER); + return nvme_init(udev); }

On Fri, May 5, 2023 at 6:55 AM Simon Glass sjg@chromium.org wrote:
U-Boot sets up devices ready for use, but coreboot does not. Enable this so that NVMe works OK from coreboot.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v4:
- Split out patch to enable bus mastering
drivers/nvme/nvme_pci.c | 5 +++++ 1 file changed, 5 insertions(+)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

Enable support for NVMe storage devices. Update the driver to enable the bus master bit, since coreboot does not do that automatically.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v4: - Drop unnecessary CONFIG options - Drop patch to allow locating UARTs by device ID
Changes in v2: - Drop patch 'usb: Quieten a debug message' since it was fixed elsewhere - Drop patch 'x86: coreboot: Use a memory-mapped UART' (not needed)
configs/coreboot_defconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/configs/coreboot_defconfig b/configs/coreboot_defconfig index 3030e5bf93b..f6ffb518042 100644 --- a/configs/coreboot_defconfig +++ b/configs/coreboot_defconfig @@ -59,6 +59,7 @@ 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 CONFIG_SOUND_I8254=y

On Fri, May 5, 2023 at 6:55 AM Simon Glass sjg@chromium.org wrote:
Enable support for NVMe storage devices. Update the driver to enable the bus master bit, since coreboot does not do that automatically.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v4:
- Drop unnecessary CONFIG options
- Drop patch to allow locating UARTs by device ID
Changes in v2:
- Drop patch 'usb: Quieten a debug message' since it was fixed elsewhere
- Drop patch 'x86: coreboot: Use a memory-mapped UART' (not needed)
configs/coreboot_defconfig | 1 + 1 file changed, 1 insertion(+)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

This is useful when looking for tables in memory. Enable it for coreboot.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
(no changes since v2)
Changes in v2: - Add new patch to enable ms command
configs/coreboot_defconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/configs/coreboot_defconfig b/configs/coreboot_defconfig index f6ffb518042..058caf008f9 100644 --- a/configs/coreboot_defconfig +++ b/configs/coreboot_defconfig @@ -24,6 +24,7 @@ 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

On Fri, May 5, 2023 at 6:55 AM Simon Glass sjg@chromium.org wrote:
This series includes some patches generated while getting U-Boot to boot more nicely on Brya, an Adler Lake Chromebook.
This includes:
- show the ACPI tables with 'acpi list'
- get the UART to work even if coreboot doesn't enable it
- show unimplemented sysinfo tags
- fix for keyboard not working
- fix for trying to set up PCI regions when the info is not available
- fix for looking at inaccessible memory to find the sysinfo table
Changes in v4:
- Split out patch to enable bus mastering
- Drop unnecessary CONFIG options
- Drop patch to allow locating UARTs by device ID
Changes in v3:
- Don't enable ACPI by default except on x86 and sandbox
- Avoid a build error with the ASL compiler
- Disable for coreboot64 since ACPI is not available
Changes in v2:
- Don't show an invalid CPU number on error
- Update commit message with more detail
- Update code comment to mention that addresses <1KB are ignored
- Flush the buffer instead of skipping the reset
- Add new patch to create a new Kconfig for ACPI
- Add new patch to move acpi-table-finding functions into the library
- Use tab instead of space in header file
- Refactor two patches into one
- Add new patch to allow locating the UART from ACPI tables
- Expand commit message to explain this is for the debug UART
- Update the defconfig instead
- Drop patch 'usb: Quieten a debug message' since it was fixed elsewhere
- Drop patch 'x86: coreboot: Use a memory-mapped UART' (not needed)
- Add new patch to enable ms command
Simon Glass (16): mtrr: Don't show an invalid CPU number x86: Adjust search range for sysinfo table input: Flush the keyboard buffer before resetting it acpi: Create a new Kconfig for ACPI acpi: Move the table-finding functions into the libary x86: coreboot: Collect the address of the ACPI tables x86: Allow locating the UART from ACPI tables pci: coreboot: Don't read regions when booting x86: coreboot: Use a memory-mapped UART x86: coreboot: Document how to enable the debug UART x86: coreboot: Scan PCI after relocation x86: coreboot: Log function names and line numbers x86: coreboot: Show unimplemented sysinfo tags nvme: Enable PCI bus mastering x86: nvme: coreboot: Enable NVMe coreboot: Enable ms command
series applied to u-boot-x86, thanks!
participants (2)
-
Bin Meng
-
Simon Glass