diff options
Diffstat (limited to 'arch/x86')
28 files changed, 1122 insertions, 489 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 5b089af..970bdff 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1047,4 +1047,25 @@ config INTEL_GMA_SWSMISCI endif # INTEL_SOC +config COREBOOT_SYSINFO + bool "Support reading coreboot sysinfo" + default y if SYS_COREBOOT + help + Select this option to read the coreboot sysinfo table on start-up, + if present. This is written by coreboot before it exits and provides + various pieces of information about the running system, including + display, memory and build information. It is stored in + struct sysinfo_t after parsing by get_coreboot_info(). + +config SPL_COREBOOT_SYSINFO + bool "Support reading coreboot sysinfo" + depends on SPL + default y if COREBOOT_SYSINFO + help + Select this option to read the coreboot sysinfo table in SPL, + if present. This is written by coreboot before it exits and provides + various pieces of information about the running system, including + display, memory and build information. It is stored in + struct sysinfo_t after parsing by get_coreboot_info(). + endmenu diff --git a/arch/x86/cpu/apollolake/cpu.c b/arch/x86/cpu/apollolake/cpu.c index fbc016d..647c9df 100644 --- a/arch/x86/cpu/apollolake/cpu.c +++ b/arch/x86/cpu/apollolake/cpu.c @@ -19,6 +19,7 @@ #include <asm/arch/iomap.h> #include <dm/acpi.h> +#ifdef CONFIG_ACPIGEN #define CSTATE_RES(address_space, width, offset, address) \ { \ .space_id = address_space, \ @@ -57,11 +58,6 @@ static struct acpi_cstate cstate_map[] = { }, }; -static int apl_get_info(const struct udevice *dev, struct cpu_info *info) -{ - return cpu_intel_get_info(info, INTEL_BCLK_MHZ); -} - static int acpi_cpu_fill_ssdt(const struct udevice *dev, struct acpi_ctx *ctx) { uint core_id = dev_seq(dev); @@ -89,6 +85,12 @@ static int acpi_cpu_fill_ssdt(const struct udevice *dev, struct acpi_ctx *ctx) return 0; } +#endif /* CONFIG_ACPIGEN */ + +static int apl_get_info(const struct udevice *dev, struct cpu_info *info) +{ + return cpu_intel_get_info(info, INTEL_BCLK_MHZ); +} static void update_fixed_mtrrs(void) { @@ -170,9 +172,11 @@ static int cpu_apl_probe(struct udevice *dev) return 0; } +#ifdef CONFIG_ACPIGEN struct acpi_ops apl_cpu_acpi_ops = { .fill_ssdt = acpi_cpu_fill_ssdt, }; +#endif static const struct cpu_ops cpu_x86_apl_ops = { .get_desc = cpu_x86_get_desc, diff --git a/arch/x86/cpu/apollolake/cpu_common.c b/arch/x86/cpu/apollolake/cpu_common.c index 63f6999..5d7d26b 100644 --- a/arch/x86/cpu/apollolake/cpu_common.c +++ b/arch/x86/cpu/apollolake/cpu_common.c @@ -7,11 +7,17 @@ #include <dm.h> #include <log.h> #include <asm/cpu_common.h> +#include <asm/io.h> #include <asm/msr.h> +#include <asm/pci.h> #include <asm/arch/cpu.h> #include <asm/arch/iomap.h> +#include <asm/arch/uart.h> #include <power/acpi_pmc.h> +/* Define this here to avoid referencing any drivers for the debug UART 1 */ +#define PCH_DEV_P2SB PCI_BDF(0, 0x0d, 0) + void cpu_flush_l1d_to_l2(void) { struct msr_t msr; @@ -40,3 +46,57 @@ void enable_pm_timer_emulation(const struct udevice *pmc) debug("PM timer %x %x\n", msr.hi, msr.lo); msr_write(MSR_EMULATE_PM_TIMER, msr); } + +static void pch_uart_init(void) +{ + /* + * Set up the pinmux so that the UART rx/tx signals are connected + * outside the SoC. + * + * There are about 500 lines of code required to program the GPIO + * configuration for the UARTs. But it boils down to four writes, and + * for the debug UART we want the minimum possible amount of code before + * the UART is running. So just add the magic writes here. See + * apl_hostbridge_early_init_pinctrl() for the full horror. + */ + if (PCI_FUNC(PCH_DEV_UART) == 1) { + writel(0x40000402, 0xd0c50650); + writel(0x3c47, 0xd0c50654); + writel(0x40000400, 0xd0c50658); + writel(0x3c48, 0xd0c5065c); + } else { /* UART2 */ + writel(0x40000402, 0xd0c50670); + writel(0x3c4b, 0xd0c50674); + writel(0x40000400, 0xd0c50678); + writel(0x3c4c, 0xd0c5067c); + } + +#ifdef CONFIG_DEBUG_UART + apl_uart_init(PCH_DEV_UART, CONFIG_DEBUG_UART_BASE); +#endif +} + +static void p2sb_enable_bar(ulong bar) +{ + /* Enable PCR Base address in PCH */ + pci_x86_write_config(PCH_DEV_P2SB, PCI_BASE_ADDRESS_0, bar, + PCI_SIZE_32); + pci_x86_write_config(PCH_DEV_P2SB, PCI_BASE_ADDRESS_1, 0, PCI_SIZE_32); + + /* Enable P2SB MSE */ + pci_x86_write_config(PCH_DEV_P2SB, PCI_COMMAND, + PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY, + PCI_SIZE_8); +} + +/* + * board_debug_uart_init() - Init the debug UART ready for use + * + * This is the minimum init needed to get the UART running. It avoids any + * drivers or complex code, so that the UART is running as soon as possible. + */ +void board_debug_uart_init(void) +{ + p2sb_enable_bar(IOMAP_P2SB_BAR); + pch_uart_init(); +} diff --git a/arch/x86/cpu/apollolake/cpu_spl.c b/arch/x86/cpu/apollolake/cpu_spl.c index 9a18476..8f48457 100644 --- a/arch/x86/cpu/apollolake/cpu_spl.c +++ b/arch/x86/cpu/apollolake/cpu_spl.c @@ -31,68 +31,10 @@ #include <asm/arch/lpc.h> #include <asm/arch/pch.h> #include <asm/arch/systemagent.h> -#include <asm/arch/uart.h> #include <asm/fsp2/fsp_api.h> #include <linux/sizes.h> #include <power/acpi_pmc.h> -/* Define this here to avoid referencing any drivers for the debug UART 1 */ -#define PCH_DEV_P2SB PCI_BDF(0, 0x0d, 0) - -static void pch_uart_init(void) -{ - /* - * Set up the pinmux so that the UART rx/tx signals are connected - * outside the SoC. - * - * There are about 500 lines of code required to program the GPIO - * configuration for the UARTs. But it boils down to four writes, and - * for the debug UART we want the minimum possible amount of code before - * the UART is running. So just add the magic writes here. See - * apl_hostbridge_early_init_pinctrl() for the full horror. - */ - if (PCI_FUNC(PCH_DEV_UART) == 1) { - writel(0x40000402, 0xd0c50650); - writel(0x3c47, 0xd0c50654); - writel(0x40000400, 0xd0c50658); - writel(0x3c48, 0xd0c5065c); - } else { /* UART2 */ - writel(0x40000402, 0xd0c50670); - writel(0x3c4b, 0xd0c50674); - writel(0x40000400, 0xd0c50678); - writel(0x3c4c, 0xd0c5067c); - } - -#ifdef CONFIG_DEBUG_UART - apl_uart_init(PCH_DEV_UART, CONFIG_DEBUG_UART_BASE); -#endif -} - -static void p2sb_enable_bar(ulong bar) -{ - /* Enable PCR Base address in PCH */ - pci_x86_write_config(PCH_DEV_P2SB, PCI_BASE_ADDRESS_0, bar, - PCI_SIZE_32); - pci_x86_write_config(PCH_DEV_P2SB, PCI_BASE_ADDRESS_1, 0, PCI_SIZE_32); - - /* Enable P2SB MSE */ - pci_x86_write_config(PCH_DEV_P2SB, PCI_COMMAND, - PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY, - PCI_SIZE_8); -} - -/* - * board_debug_uart_init() - Init the debug UART ready for use - * - * This is the minimum init needed to get the UART running. It avoids any - * drivers or complex code, so that the UART is running as soon as possible. - */ -void board_debug_uart_init(void) -{ - p2sb_enable_bar(IOMAP_P2SB_BAR); - pch_uart_init(); -} - static int fast_spi_cache_bios_region(void) { uint map_size, offset; diff --git a/arch/x86/cpu/coreboot/Makefile b/arch/x86/cpu/coreboot/Makefile index 605f903..a6cdb9a 100644 --- a/arch/x86/cpu/coreboot/Makefile +++ b/arch/x86/cpu/coreboot/Makefile @@ -20,5 +20,4 @@ else obj-y += sdram.o endif obj-y += coreboot.o -obj-y += tables.o obj-y += timestamp.o diff --git a/arch/x86/cpu/coreboot/coreboot.c b/arch/x86/cpu/coreboot/coreboot.c index 15c3ad8..69cf8f4 100644 --- a/arch/x86/cpu/coreboot/coreboot.c +++ b/arch/x86/cpu/coreboot/coreboot.c @@ -14,7 +14,7 @@ #include <asm/io.h> #include <asm/msr.h> #include <asm/mtrr.h> -#include <asm/arch/sysinfo.h> +#include <asm/cb_sysinfo.h> #include <asm/arch/timestamp.h> DECLARE_GLOBAL_DATA_PTR; diff --git a/arch/x86/cpu/coreboot/sdram.c b/arch/x86/cpu/coreboot/sdram.c index a2e47d1..4a256ba 100644 --- a/arch/x86/cpu/coreboot/sdram.c +++ b/arch/x86/cpu/coreboot/sdram.c @@ -8,7 +8,7 @@ #include <common.h> #include <init.h> #include <asm/e820.h> -#include <asm/arch/sysinfo.h> +#include <asm/cb_sysinfo.h> #include <asm/global_data.h> DECLARE_GLOBAL_DATA_PTR; @@ -16,32 +16,7 @@ DECLARE_GLOBAL_DATA_PTR; unsigned int install_e820_map(unsigned int max_entries, struct e820_entry *entries) { - unsigned int num_entries; - int i; - - num_entries = min((unsigned int)lib_sysinfo.n_memranges, max_entries); - if (num_entries < lib_sysinfo.n_memranges) { - printf("Warning: Limiting e820 map to %d entries.\n", - num_entries); - } - for (i = 0; i < num_entries; i++) { - struct memrange *memrange = &lib_sysinfo.memrange[i]; - - entries[i].addr = memrange->base; - entries[i].size = memrange->size; - - /* - * coreboot has some extensions (type 6 & 16) to the E820 types. - * When we detect this, mark it as E820_RESERVED. - */ - if (memrange->type == CB_MEM_VENDOR_RSVD || - memrange->type == CB_MEM_TABLE) - entries[i].type = E820_RESERVED; - else - entries[i].type = memrange->type; - } - - return num_entries; + return cb_install_e820_map(max_entries, entries); } /* diff --git a/arch/x86/cpu/coreboot/tables.c b/arch/x86/cpu/coreboot/tables.c deleted file mode 100644 index c52741a..0000000 --- a/arch/x86/cpu/coreboot/tables.c +++ /dev/null @@ -1,255 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -/* - * This file is part of the libpayload project. - * - * Copyright (C) 2008 Advanced Micro Devices, Inc. - * Copyright (C) 2009 coresystems GmbH - */ - -#include <common.h> -#include <net.h> -#include <asm/arch/sysinfo.h> -#include <asm/global_data.h> - -DECLARE_GLOBAL_DATA_PTR; - -/* - * This needs to be in the .data section so that it's copied over during - * relocation. By default it's put in the .bss section which is simply filled - * with zeroes when transitioning from "ROM", which is really RAM, to other - * RAM. - */ -struct sysinfo_t lib_sysinfo __attribute__((section(".data"))); - -/* - * Some of this is x86 specific, and the rest of it is generic. Right now, - * since we only support x86, we'll avoid trying to make lots of infrastructure - * we don't need. If in the future, we want to use coreboot on some other - * architecture, then take out the generic parsing code and move it elsewhere. - */ - -/* === Parsing code === */ -/* This is the generic parsing code. */ - -static void cb_parse_memory(unsigned char *ptr, struct sysinfo_t *info) -{ - struct cb_memory *mem = (struct cb_memory *)ptr; - int count = MEM_RANGE_COUNT(mem); - int i; - - if (count > SYSINFO_MAX_MEM_RANGES) - count = SYSINFO_MAX_MEM_RANGES; - - info->n_memranges = 0; - - for (i = 0; i < count; i++) { - struct cb_memory_range *range = - (struct cb_memory_range *)MEM_RANGE_PTR(mem, i); - - info->memrange[info->n_memranges].base = - UNPACK_CB64(range->start); - - info->memrange[info->n_memranges].size = - UNPACK_CB64(range->size); - - info->memrange[info->n_memranges].type = range->type; - - info->n_memranges++; - } -} - -static void cb_parse_serial(unsigned char *ptr, struct sysinfo_t *info) -{ - struct cb_serial *ser = (struct cb_serial *)ptr; - info->serial = ser; -} - -static void cb_parse_vbnv(unsigned char *ptr, struct sysinfo_t *info) -{ - struct cb_vbnv *vbnv = (struct cb_vbnv *)ptr; - - info->vbnv_start = vbnv->vbnv_start; - info->vbnv_size = vbnv->vbnv_size; -} - -static void cb_parse_cbmem_entry(unsigned char *ptr, struct sysinfo_t *info) -{ - struct cb_cbmem_entry *entry = (struct cb_cbmem_entry *)ptr; - - if (entry->id != CBMEM_ID_SMBIOS) - return; - - info->smbios_start = entry->address; - info->smbios_size = entry->entry_size; -} - -static void cb_parse_gpios(unsigned char *ptr, struct sysinfo_t *info) -{ - int i; - struct cb_gpios *gpios = (struct cb_gpios *)ptr; - - info->num_gpios = (gpios->count < SYSINFO_MAX_GPIOS) ? - (gpios->count) : SYSINFO_MAX_GPIOS; - - for (i = 0; i < info->num_gpios; i++) - info->gpios[i] = gpios->gpios[i]; -} - -static void cb_parse_vdat(unsigned char *ptr, struct sysinfo_t *info) -{ - struct cb_vdat *vdat = (struct cb_vdat *) ptr; - - info->vdat_addr = vdat->vdat_addr; - info->vdat_size = vdat->vdat_size; -} - -static void cb_parse_tstamp(unsigned char *ptr, struct sysinfo_t *info) -{ - info->tstamp_table = ((struct cb_cbmem_tab *)ptr)->cbmem_tab; -} - -static void cb_parse_cbmem_cons(unsigned char *ptr, struct sysinfo_t *info) -{ - info->cbmem_cons = ((struct cb_cbmem_tab *)ptr)->cbmem_tab; -} - -static void cb_parse_framebuffer(unsigned char *ptr, struct sysinfo_t *info) -{ - info->framebuffer = (struct cb_framebuffer *)ptr; -} - -static void cb_parse_string(unsigned char *ptr, char **info) -{ - *info = (char *)((struct cb_string *)ptr)->string; -} - -__weak void cb_parse_unhandled(u32 tag, unsigned char *ptr) -{ -} - -static int cb_parse_header(void *addr, int len, struct sysinfo_t *info) -{ - unsigned char *ptr = addr; - struct cb_header *header; - int i; - - header = (struct cb_header *)ptr; - if (!header->table_bytes) - return 0; - - /* Make sure the checksums match. */ - if (!ip_checksum_ok(header, sizeof(*header))) - return -1; - - if (compute_ip_checksum(ptr + sizeof(*header), header->table_bytes) != - header->table_checksum) - return -1; - - /* Now, walk the tables. */ - ptr += header->header_bytes; - - /* Inintialize some fields to sentinel values. */ - info->vbnv_start = info->vbnv_size = (uint32_t)(-1); - - for (i = 0; i < header->table_entries; i++) { - struct cb_record *rec = (struct cb_record *)ptr; - - /* We only care about a few tags here (maybe more later). */ - switch (rec->tag) { - case CB_TAG_FORWARD: - return cb_parse_header( - (void *)(unsigned long) - ((struct cb_forward *)rec)->forward, - len, info); - continue; - case CB_TAG_MEMORY: - cb_parse_memory(ptr, info); - break; - case CB_TAG_SERIAL: - cb_parse_serial(ptr, info); - break; - case CB_TAG_VERSION: - cb_parse_string(ptr, &info->version); - break; - case CB_TAG_EXTRA_VERSION: - cb_parse_string(ptr, &info->extra_version); - break; - case CB_TAG_BUILD: - cb_parse_string(ptr, &info->build); - break; - case CB_TAG_COMPILE_TIME: - cb_parse_string(ptr, &info->compile_time); - break; - case CB_TAG_COMPILE_BY: - cb_parse_string(ptr, &info->compile_by); - break; - case CB_TAG_COMPILE_HOST: - cb_parse_string(ptr, &info->compile_host); - break; - case CB_TAG_COMPILE_DOMAIN: - cb_parse_string(ptr, &info->compile_domain); - break; - case CB_TAG_COMPILER: - cb_parse_string(ptr, &info->compiler); - break; - case CB_TAG_LINKER: - cb_parse_string(ptr, &info->linker); - break; - case CB_TAG_ASSEMBLER: - cb_parse_string(ptr, &info->assembler); - break; - /* - * FIXME we should warn on serial if coreboot set up a - * framebuffer buf the payload does not know about it. - */ - case CB_TAG_FRAMEBUFFER: - cb_parse_framebuffer(ptr, info); - break; - case CB_TAG_GPIO: - cb_parse_gpios(ptr, info); - break; - case CB_TAG_VDAT: - cb_parse_vdat(ptr, info); - break; - case CB_TAG_TIMESTAMPS: - cb_parse_tstamp(ptr, info); - break; - case CB_TAG_CBMEM_CONSOLE: - cb_parse_cbmem_cons(ptr, info); - break; - case CB_TAG_VBNV: - cb_parse_vbnv(ptr, info); - break; - case CB_TAG_CBMEM_ENTRY: - cb_parse_cbmem_entry(ptr, info); - break; - default: - cb_parse_unhandled(rec->tag, ptr); - break; - } - - ptr += rec->size; - } - - return 1; -} - -/* == Architecture specific == */ -/* This is the x86 specific stuff. */ - -int get_coreboot_info(struct sysinfo_t *info) -{ - long addr; - int ret; - - addr = locate_coreboot_table(); - if (addr < 0) - return addr; - ret = cb_parse_header((void *)addr, 0x1000, info); - if (!ret) - return -ENOENT; - gd->arch.coreboot_table = addr; - gd->flags |= GD_FLG_SKIP_LL_INIT; - - return 0; -} diff --git a/arch/x86/cpu/coreboot/timestamp.c b/arch/x86/cpu/coreboot/timestamp.c index 0162597..7f133ce 100644 --- a/arch/x86/cpu/coreboot/timestamp.c +++ b/arch/x86/cpu/coreboot/timestamp.c @@ -8,21 +8,9 @@ #include <common.h> #include <bootstage.h> #include <asm/arch/timestamp.h> -#include <asm/arch/sysinfo.h> +#include <asm/cb_sysinfo.h> #include <linux/compiler.h> -struct timestamp_entry { - uint32_t entry_id; - uint64_t entry_stamp; -} __packed; - -struct timestamp_table { - uint64_t base_time; - uint32_t max_entries; - uint32_t num_entries; - struct timestamp_entry entries[0]; /* Variable number of entries */ -} __packed; - static struct timestamp_table *ts_table __attribute__((section(".data"))); void timestamp_init(void) diff --git a/arch/x86/cpu/start_from_spl.S b/arch/x86/cpu/start_from_spl.S index 905c825..abfd4ab 100644 --- a/arch/x86/cpu/start_from_spl.S +++ b/arch/x86/cpu/start_from_spl.S @@ -43,6 +43,10 @@ use_existing_stack: call board_init_f_init_reserve +#ifdef CONFIG_DEBUG_UART + call debug_uart_init +#endif + call x86_cpu_reinit_f xorl %eax, %eax call board_init_f diff --git a/arch/x86/dts/chromebook_coral.dts b/arch/x86/dts/chromebook_coral.dts index d109a38..c8cb4e2 100644 --- a/arch/x86/dts/chromebook_coral.dts +++ b/arch/x86/dts/chromebook_coral.dts @@ -47,6 +47,7 @@ i2c5 = &i2c_5; i2c6 = &i2c_6; i2c7 = &i2c_7; + mmc0 = &emmc; mmc1 = &sdmmc; }; @@ -55,6 +56,17 @@ recovery-gpios = <&gpio_nw (-1) GPIO_ACTIVE_LOW>; write-protect-gpios = <&gpio_nw GPIO_75 GPIO_ACTIVE_HIGH>; phase-enforce-gpios = <&gpio_n GPIO_10 GPIO_ACTIVE_HIGH>; + memconfig-gpios = <&gpio_nw GPIO_101 GPIO_ACTIVE_HIGH + &gpio_nw GPIO_102 GPIO_ACTIVE_HIGH + &gpio_n GPIO_38 GPIO_ACTIVE_HIGH + &gpio_n GPIO_45 GPIO_ACTIVE_HIGH>; + + /* + * This is used for reef only: + * + * skuconfig-gpios = <&gpio_nw GPIO_16 GPIO_ACTIVE_HIGH + * &gpio_nw GPIO_17 GPIO_ACTIVE_HIGH>; + */ smbios { /* Type 1 table */ system { @@ -148,6 +160,11 @@ #interrupt-cells = <2>; }; + coreboot-video { + /* This will only activate when booted from coreboot */ + compatible = "coreboot-fb"; + }; + keyboard { intel,duplicate-por; }; @@ -571,7 +588,7 @@ sdmmc: sdmmc@1b,0 { reg = <0x0000d800 0 0 0 0>; compatible = "intel,apl-sd"; - cd-gpios = <&gpio_n GPIO_177 GPIO_ACTIVE_LOW>; + cd-gpios = <&gpio_sw GPIO_177 GPIO_ACTIVE_LOW>; acpi,name = "SDCD"; }; diff --git a/arch/x86/include/asm/arch-apollolake/uart.h b/arch/x86/include/asm/arch-apollolake/uart.h index 38335b0..c3ca171 100644 --- a/arch/x86/include/asm/arch-apollolake/uart.h +++ b/arch/x86/include/asm/arch-apollolake/uart.h @@ -6,6 +6,7 @@ #ifndef _ASM_ARCH_UART_H #define _ASM_ARCH_UART_H +#include <dt-structs.h> #include <ns16550.h> /** diff --git a/arch/x86/include/asm/arch-coreboot/sysinfo.h b/arch/x86/include/asm/arch-coreboot/sysinfo.h deleted file mode 100644 index 419ec52..0000000 --- a/arch/x86/include/asm/arch-coreboot/sysinfo.h +++ /dev/null @@ -1,62 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * This file is part of the libpayload project. - * - * Copyright (C) 2008 Advanced Micro Devices, Inc. - */ - -#ifndef _COREBOOT_SYSINFO_H -#define _COREBOOT_SYSINFO_H - -#include <asm/coreboot_tables.h> - -/* Maximum number of memory range definitions */ -#define SYSINFO_MAX_MEM_RANGES 32 -/* Allow a maximum of 8 GPIOs */ -#define SYSINFO_MAX_GPIOS 8 - -struct sysinfo_t { - int n_memranges; - struct memrange { - unsigned long long base; - unsigned long long size; - unsigned int type; - } memrange[SYSINFO_MAX_MEM_RANGES]; - - u32 cmos_range_start; - u32 cmos_range_end; - u32 cmos_checksum_location; - u32 vbnv_start; - u32 vbnv_size; - - char *version; - char *extra_version; - char *build; - char *compile_time; - char *compile_by; - char *compile_host; - char *compile_domain; - char *compiler; - char *linker; - char *assembler; - - struct cb_framebuffer *framebuffer; - - int num_gpios; - struct cb_gpio gpios[SYSINFO_MAX_GPIOS]; - - void *vdat_addr; - u32 vdat_size; - void *tstamp_table; - void *cbmem_cons; - u64 smbios_start; - u32 smbios_size; - - struct cb_serial *serial; -}; - -extern struct sysinfo_t lib_sysinfo; - -int get_coreboot_info(struct sysinfo_t *info); - -#endif diff --git a/arch/x86/include/asm/arch-coreboot/timestamp.h b/arch/x86/include/asm/arch-coreboot/timestamp.h index 85d42c0..531526b 100644 --- a/arch/x86/include/asm/arch-coreboot/timestamp.h +++ b/arch/x86/include/asm/arch-coreboot/timestamp.h @@ -8,30 +8,7 @@ #ifndef __COREBOOT_TIMESTAMP_H__ #define __COREBOOT_TIMESTAMP_H__ -enum timestamp_id { - /* coreboot specific timestamp IDs */ - TS_START_ROMSTAGE = 1, - TS_BEFORE_INITRAM = 2, - TS_AFTER_INITRAM = 3, - TS_END_ROMSTAGE = 4, - TS_START_COPYRAM = 8, - TS_END_COPYRAM = 9, - TS_START_RAMSTAGE = 10, - TS_DEVICE_ENUMERATE = 30, - TS_DEVICE_CONFIGURE = 40, - TS_DEVICE_ENABLE = 50, - TS_DEVICE_INITIALIZE = 60, - TS_DEVICE_DONE = 70, - TS_CBMEM_POST = 75, - TS_WRITE_TABLES = 80, - TS_LOAD_PAYLOAD = 90, - TS_ACPI_WAKE_JUMP = 98, - TS_SELFBOOT_JUMP = 99, - - /* U-Boot entry IDs start at 1000 */ - TS_U_BOOT_INITTED = 1000, /* This is where u-boot starts */ - TS_U_BOOT_START_KERNEL = 1100, /* Right before jumping to kernel. */ -}; +#include <asm/cb_sysinfo.h> void timestamp_init(void); void timestamp_add(enum timestamp_id id, uint64_t ts_time); diff --git a/arch/x86/include/asm/cb_sysinfo.h b/arch/x86/include/asm/cb_sysinfo.h new file mode 100644 index 0000000..675eef6 --- /dev/null +++ b/arch/x86/include/asm/cb_sysinfo.h @@ -0,0 +1,220 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + */ + +#ifndef _COREBOOT_SYSINFO_H +#define _COREBOOT_SYSINFO_H + +#include <asm/coreboot_tables.h> + +/* Maximum number of memory range definitions */ +#define SYSINFO_MAX_MEM_RANGES 32 +/* Allow a maximum of 8 GPIOs */ +#define SYSINFO_MAX_GPIOS 8 +/* Up to 10 MAC addresses */ +#define SYSINFO_MAX_MACS 10 + +/** + * struct sysinfo_t - Information passed to U-Boot from coreboot + * + * Coreboot passes on a lot of information using a list of individual data + * structures identified by a numeric tag. These are parsed in U-Boot to produce + * this struct. Some of the pointers here point back to the tagged data + * structure, since it is assumed to remain around while U-Boot is running. + * + * The 'cbsysinfo' command can display this information. + * + * @cpu_khz: CPU frequence in KHz (e.g. 1100000) + * @serial: Pointer to the serial information, NULL if none + * @ser_ioport: Not actually provided by a tag and not used on modern hardware, + * which typicaally uses a memory-mapped port + * @ser_base: Not used at all, but present to match up with the coreboot data + * structure + * @n_memranges: Number of memory ranges + * @memrange: List of memory ranges: + * @base: Base address of range + * @size: Size of range in bytes + * @type: Type of range (CB_MEM_RAM, etc.) + * @option_table: Provides a pointer to the CMOS RAM options table, which + * indicates which options are available. The header is followed by a list + * of struct cb_cmos_entries records, so that an option can be found from + * its name. This is not used in U-Boot. NULL if not present + * @cmos_range_start: Start bit of the CMOS checksum range (in fact this must + * be a multiple of 8) + * @cmos_range_end: End bit of the CMOS checksum range (multiple of 8). This is + * the inclusive end. + * @cmos_checksum_location: Location of checksum, multiplied by 8. This is the + * byte offset into the CMOS RAM of the first checksum byte. The second one + * follows immediately. The checksum is a simple 16-bit sum of all the + * bytes from offset cmos_range_start / 8 to cmos_range_end / 8, inclusive, + * in big-endian format (so sum >> 8 is stored in the first byte). + * @vbnv_start: Start offset of CMOS RAM used for Chromium OS verified boot + * (typically 0x34) + * @vbnv_size: Number of bytes used by Chromium OS verified boot (typically + * 0x10) + * @extra_version: Extra version information, typically "" + * @build: Build date, e.g. "Wed Nov 18 02:51:58 UTC 2020" + * @compile_time: Compilation time, e.g. "02:51:58" + * @compile_by: Who compiled coreboot (never set?) + * @compile_host: Name of the machine that compiled coreboot (never set?) + * @compile_domain: Domain name of the machine that compiled coreboot (never + * set?) + * @compiler: Name of the compiler used to build coreboot (never set?) + * @linker: Name of the linker used to build coreboot (never set?) + * @assembler: Name of the assembler used to build coreboot (never set?) + * @cb_version: Coreboot version string, e.g. v1.9308_26_0.0.22-2599-g232f22c75d + * @framebuffer: Address of framebuffer tag, or NULL if none. See + * struct cb_framebuffer for the definition + * @num_gpios: Number of verified-boot GPIOs + * @gpios: List of GPIOs: + * @port: GPIO number, or 0xffffffff if not a GPIO + * @polarity: CB_GPIO_ACTIVE_LOW or CB_GPIO_ACTIVE_HIGH + * @value: Value of GPIO (0 or 1) + * @name: Name of GPIO + * + * A typical list is: + * id: port polarity val name + * 0: - active-high 1 write protect + * 1: - active-high 0 recovery + * 2: - active-high 1 lid + * 3: - active-high 0 power + * 4: - active-high 0 oprom + * 5: 29 active-high 0 EC in RW + * + * @num_macs: Number of MAC addresses + * @macs: List of MAC addresses + * @serialno: Serial number, or NULL (never set?) + * @mbtable: Address of the multiboot table, or NULL. This is a + * struct multiboot_header, not used in U-Boot + * @header: Address of header, if there is a CB_TAG_FORWARD, else NULL + * @mainboard: Pointer to mainboard info or NULL. Typically the vendor is + * "Google" and the part number is "" + * @vboot_handoff: Pointer to Chromium OS verified boot hand-off information. + * This is struct vboot_handoff, providing access to internal information + * generated by coreboot when this is being used + * @vboot_handoff_size: Size of hand-off information (typically 0xc0c) + * @vdat_addr: Pointer to Chromium OS verified boot data, which uses + * struct chromeos_acpi. It sits in the Intel Global NVS struct, after the + * first 0x100 bytes + * @vdat_size: Size of this data, typically 0xf00 + * @smbios_start: Address of SMBIOS tables + * @smbios_size: Size of SMBIOS tables (e.g. 0x800) + * @x86_rom_var_mtrr_index: MTRR number used for ROM caching. Not used in U-Boot + * @tstamp_table: Pointer to timestamp_table, struct timestamp_table + * @cbmem_cons: Pointer to the console dump, struct cbmem_console. This provides + * access to the console output generated by coreboot, typically about 64KB + * and mostly PCI enumeration info + * @mrc_cache: Pointer to memory-reference-code cache, typically NULL + * acpi_gnvs: @Pointer to Intel Global NVS struct, see struct acpi_global_nvs + * @board_id: Board ID indicating the board variant, typically 0xffffffff + * @ram_code: RAM code indicating the SDRAM type, typically 0xffffffff + * @wifi_calibration: WiFi calibration info, NULL if none + * @ramoops_buffer: Address of kernel Ramoops buffer + * @ramoops_buffer_size: Sizeof of Ramoops buffer, typically 1MB + * @spi_flash: Information about SPI flash: + * @size: Size in bytes, e.g. 16MB + * @sector_size; Sector size of flash device, e.g. 4KB + * @erase_cmd: Command used to erase flash, or 0 if not used + * @fmap_offset: SPI-flash offset of the flash map (FMAP) table. This has a + * __FMAP__ header. It provides information about the different top-level + * sections in the SPI flash, e.g. 0x204000 + * @cbfs_offset: SPI-flash offset of the Coreboot Filesystem (CBFS) used for + * read-only data, e.g. 0x205000. This is typically called 'COREBOOT' in + * the flash map. It holds various coreboot binaries as well as + * video-configuration files and graphics data for the Chromium OS + * verified boot user interface. + * @cbfs_size: Size of CBFS, e.g. 0x17b000 + * @boot_media_size; Size of boot media (i.e. SPI flash), e.g. 16MB + * @mtc_start; Start of MTC region (Nvidia private data), 0 if not used. See + * https://chromium.googlesource.com/chromiumos/third_party/coreboot/+/chromeos-2013.04/src/soc/nvidia/tegra210/mtc.c + * @mtc_size: Size of MTC region + * @chromeos_vpd: Chromium OS Vital Product Data region, typically NULL, meaning + * not used + */ +struct sysinfo_t { + unsigned int cpu_khz; + struct cb_serial *serial; + unsigned short ser_ioport; + unsigned long ser_base; // for mmapped serial + + int n_memranges; + + struct memrange { + unsigned long long base; + unsigned long long size; + unsigned int type; + } memrange[SYSINFO_MAX_MEM_RANGES]; + + struct cb_cmos_option_table *option_table; + u32 cmos_range_start; + u32 cmos_range_end; + u32 cmos_checksum_location; + u32 vbnv_start; + u32 vbnv_size; + + char *version; + char *extra_version; + char *build; + char *compile_time; + char *compile_by; + char *compile_host; + char *compile_domain; + char *compiler; + char *linker; + char *assembler; + + char *cb_version; + + struct cb_framebuffer *framebuffer; + + int num_gpios; + struct cb_gpio gpios[SYSINFO_MAX_GPIOS]; + int num_macs; + struct mac_address macs[SYSINFO_MAX_MACS]; + char *serialno; + + unsigned long *mbtable; /** Pointer to the multiboot table */ + + struct cb_header *header; + struct cb_mainboard *mainboard; + + void *vboot_handoff; + u32 vboot_handoff_size; + void *vdat_addr; + u32 vdat_size; + u64 smbios_start; + u32 smbios_size; + + int x86_rom_var_mtrr_index; + + void *tstamp_table; + void *cbmem_cons; + void *mrc_cache; + void *acpi_gnvs; + u32 board_id; + u32 ram_code; + void *wifi_calibration; + u64 ramoops_buffer; + u32 ramoops_buffer_size; + struct { + u32 size; + u32 sector_size; + u32 erase_cmd; + } spi_flash; + u64 fmap_offset; + u64 cbfs_offset; + u64 cbfs_size; + u64 boot_media_size; + u64 mtc_start; + u32 mtc_size; + void *chromeos_vpd; +}; + +extern struct sysinfo_t lib_sysinfo; + +int get_coreboot_info(struct sysinfo_t *info); + +#endif diff --git a/arch/x86/include/asm/coreboot_tables.h b/arch/x86/include/asm/coreboot_tables.h index 7e15767..a74654b 100644 --- a/arch/x86/include/asm/coreboot_tables.h +++ b/arch/x86/include/asm/coreboot_tables.h @@ -8,6 +8,106 @@ #ifndef _COREBOOT_TABLES_H #define _COREBOOT_TABLES_H +struct timestamp_entry { + u32 entry_id; + u64 entry_stamp; +} __packed; + +struct timestamp_table { + u64 base_time; + u16 max_entries; + u16 tick_freq_mhz; + u32 num_entries; + struct timestamp_entry entries[0]; /* Variable number of entries */ +} __packed; + +enum timestamp_id { + /* coreboot-specific timestamp IDs */ + TS_START_ROMSTAGE = 1, + TS_BEFORE_INITRAM = 2, + TS_AFTER_INITRAM = 3, + TS_END_ROMSTAGE = 4, + TS_START_VBOOT = 5, + TS_END_VBOOT = 6, + TS_START_COPYRAM = 8, + TS_END_COPYRAM = 9, + TS_START_RAMSTAGE = 10, + TS_START_BOOTBLOCK = 11, + TS_END_BOOTBLOCK = 12, + TS_START_COPYROM = 13, + TS_END_COPYROM = 14, + TS_START_ULZMA = 15, + TS_END_ULZMA = 16, + TS_START_ULZ4F = 17, + TS_END_ULZ4F = 18, + TS_DEVICE_ENUMERATE = 30, + TS_DEVICE_CONFIGURE = 40, + TS_DEVICE_ENABLE = 50, + TS_DEVICE_INITIALIZE = 60, + TS_DEVICE_DONE = 70, + TS_CBMEM_POST = 75, + TS_WRITE_TABLES = 80, + TS_FINALIZE_CHIPS = 85, + TS_LOAD_PAYLOAD = 90, + TS_ACPI_WAKE_JUMP = 98, + TS_SELFBOOT_JUMP = 99, + + /* 500+ reserved for vendorcode extensions (500-600: google/chromeos) */ + TS_START_COPYVER = 501, + TS_END_COPYVER = 502, + TS_START_TPMINIT = 503, + TS_END_TPMINIT = 504, + TS_START_VERIFY_SLOT = 505, + TS_END_VERIFY_SLOT = 506, + TS_START_HASH_BODY = 507, + TS_DONE_LOADING = 508, + TS_DONE_HASHING = 509, + TS_END_HASH_BODY = 510, + TS_START_COPYVPD = 550, + TS_END_COPYVPD_RO = 551, + TS_END_COPYVPD_RW = 552, + + /* 940-950 reserved for vendorcode extensions (940-950: Intel ME) */ + TS_ME_INFORM_DRAM_WAIT = 940, + TS_ME_INFORM_DRAM_DONE = 941, + + /* 950+ reserved for vendorcode extensions (950-999: intel/fsp) */ + TS_FSP_MEMORY_INIT_START = 950, + TS_FSP_MEMORY_INIT_END = 951, + TS_FSP_TEMP_RAM_EXIT_START = 952, + TS_FSP_TEMP_RAM_EXIT_END = 953, + TS_FSP_SILICON_INIT_START = 954, + TS_FSP_SILICON_INIT_END = 955, + TS_FSP_BEFORE_ENUMERATE = 956, + TS_FSP_AFTER_ENUMERATE = 957, + TS_FSP_BEFORE_FINALIZE = 958, + TS_FSP_AFTER_FINALIZE = 959, + TS_FSP_BEFORE_END_OF_FIRMWARE = 960, + TS_FSP_AFTER_END_OF_FIRMWARE = 961, + + /* 1000+ reserved for payloads (1000-1200: ChromeOS depthcharge) */ + + /* U-Boot entry IDs start at 1000 */ + TS_U_BOOT_INITTED = 1000, /* This is where U-Boot starts */ + + TS_RO_PARAMS_INIT = 1001, + TS_RO_VB_INIT = 1002, + TS_RO_VB_SELECT_FIRMWARE = 1003, + TS_RO_VB_SELECT_AND_LOAD_KERNEL = 1004, + + TS_RW_VB_SELECT_AND_LOAD_KERNEL = 1010, + + TS_VB_SELECT_AND_LOAD_KERNEL = 1020, + TS_VB_EC_VBOOT_DONE = 1030, + TS_VB_STORAGE_INIT_DONE = 1040, + TS_VB_READ_KERNEL_DONE = 1050, + TS_VB_VBOOT_DONE = 1100, + + TS_START_KERNEL = 1101, + TS_KERNEL_DECOMPRESSION = 1102, + TS_U_BOOT_START_KERNEL = 1100, /* Right before jumping to kernel */ +}; + struct memory_area; struct cbuint64 { @@ -162,13 +262,14 @@ struct cb_framebuffer { }; #define CB_TAG_GPIO 0x0013 -#define GPIO_MAX_NAME_LENGTH 16 - +#define CB_GPIO_ACTIVE_LOW 0 +#define CB_GPIO_ACTIVE_HIGH 1 +#define CB_GPIO_MAX_NAME_LENGTH 16 struct cb_gpio { u32 port; u32 polarity; u32 value; - u8 name[GPIO_MAX_NAME_LENGTH]; + u8 name[CB_GPIO_MAX_NAME_LENGTH]; }; struct cb_gpios { @@ -181,61 +282,158 @@ struct cb_gpios { #define CB_TAG_FDT 0x0014 struct cb_fdt { - uint32_t tag; - uint32_t size; /* size of the entire entry */ + u32 tag; + u32 size; /* size of the entire entry */ /* the actual FDT gets placed here */ }; #define CB_TAG_VDAT 0x0015 struct cb_vdat { - uint32_t tag; - uint32_t size; /* size of the entire entry */ + u32 tag; + u32 size; /* size of the entire entry */ void *vdat_addr; - uint32_t vdat_size; + u32 vdat_size; }; #define CB_TAG_TIMESTAMPS 0x0016 #define CB_TAG_CBMEM_CONSOLE 0x0017 + +struct cbmem_console { + u32 size; + u32 cursor; + char body[0]; +} __packed; + #define CB_TAG_MRC_CACHE 0x0018 struct cb_cbmem_tab { - uint32_t tag; - uint32_t size; - void *cbmem_tab; + u32 tag; + u32 size; + u64 cbmem_tab; }; #define CB_TAG_VBNV 0x0019 struct cb_vbnv { - uint32_t tag; - uint32_t size; - uint32_t vbnv_start; - uint32_t vbnv_size; + u32 tag; + u32 size; + u32 vbnv_start; + u32 vbnv_size; +}; + +#define CB_TAG_VBOOT_HANDOFF 0x0020 + +#define CB_TAG_X86_ROM_MTRR 0x0021 +struct cb_x86_rom_mtrr { + u32 tag; + u32 size; + /* + * The variable range MTRR index covering the ROM. If one wants to + * enable caching the ROM, the variable MTRR needs to be set to + * write-protect. To disable the caching after enabling set the + * type to uncacheable + */ + u32 index; +}; + +#define CB_TAG_DMA 0x0022 +#define CB_TAG_RAM_OOPS 0x0023 +#define CB_TAG_ACPI_GNVS 0x0024 + +#define CB_TAG_BOARD_ID 0x0025 +struct cb_board_id { + u32 tag; + u32 size; + /* Board ID as retrieved from the board revision GPIOs. */ + u32 board_id; +}; + +#define CB_TAG_MAC_ADDRS 0x0026 +struct mac_address { + u8 mac_addr[6]; + u8 pad[2]; /* Pad it to 8 bytes to keep it simple. */ +}; + +struct cb_macs { + u32 tag; + u32 size; + u32 count; + struct mac_address mac_addrs[0]; +}; + +#define CB_TAG_WIFI_CALIBRATION 0x0027 + +#define CB_TAG_RAM_CODE 0x0028 +struct cb_ram_code { + u32 tag; + u32 size; + u32 ram_code; +}; + +#define CB_TAG_SPI_FLASH 0x0029 +struct cb_spi_flash { + u32 tag; + u32 size; + u32 flash_size; + u32 sector_size; + u32 erase_cmd; +}; + +#define CB_TAG_MTC 0x002b +#define CB_TAG_VPD 0x002c +struct lb_range { + u32 tag; + u32 size; + u64 range_start; + u32 range_size; +}; + +#define CB_TAG_BOOT_MEDIA_PARAMS 0x0030 +struct cb_boot_media_params { + u32 tag; + u32 size; + /* offsets are relative to start of boot media */ + u64 fmap_offset; + u64 cbfs_offset; + u64 cbfs_size; + u64 boot_media_size; }; -#define CB_TAG_CBMEM_ENTRY 0x0031 -#define CBMEM_ID_SMBIOS 0x534d4254 +#define CB_TAG_CBMEM_ENTRY 0x0031 +#define CBMEM_ID_SMBIOS 0x534d4254 struct cb_cbmem_entry { - uint32_t tag; - uint32_t size; - uint64_t address; - uint32_t entry_size; - uint32_t id; + u32 tag; + u32 size; + u64 address; + u32 entry_size; + u32 id; +}; + +#define CB_TAG_TSC_INFO 0x0032 +struct cb_tsc_info { + u32 tag; + u32 size; + + u32 freq_khz; }; +#define CB_TAG_SERIALNO 0x002a +#define CB_MAX_SERIALNO_LENGTH 32 + #define CB_TAG_CMOS_OPTION_TABLE 0x00c8 struct cb_cmos_option_table { u32 tag; u32 size; u32 header_length; + /* entries follow after this header */ }; #define CB_TAG_OPTION 0x00c9 -#define CMOS_MAX_NAME_LENGTH 32 +#define CB_CMOS_MAX_NAME_LENGTH 32 struct cb_cmos_entries { u32 tag; @@ -244,34 +442,33 @@ struct cb_cmos_entries { u32 length; u32 config; u32 config_id; - u8 name[CMOS_MAX_NAME_LENGTH]; + u8 name[CB_CMOS_MAX_NAME_LENGTH]; }; #define CB_TAG_OPTION_ENUM 0x00ca -#define CMOS_MAX_TEXT_LENGTH 32 - +#define CB_CMOS_MAX_TEXT_LENGTH 32 struct cb_cmos_enums { u32 tag; u32 size; u32 config_id; u32 value; - u8 text[CMOS_MAX_TEXT_LENGTH]; + u8 text[CB_CMOS_MAX_TEXT_LENGTH]; }; #define CB_TAG_OPTION_DEFAULTS 0x00cb -#define CMOS_IMAGE_BUFFER_SIZE 128 +#define CB_CMOS_IMAGE_BUFFER_SIZE 128 struct cb_cmos_defaults { u32 tag; u32 size; u32 name_length; - u8 name[CMOS_MAX_NAME_LENGTH]; - u8 default_set[CMOS_IMAGE_BUFFER_SIZE]; + u8 name[CB_CMOS_MAX_NAME_LENGTH]; + u8 default_set[CB_CMOS_IMAGE_BUFFER_SIZE]; }; #define CB_TAG_OPTION_CHECKSUM 0x00cc -#define CHECKSUM_NONE 0 -#define CHECKSUM_PCBIOS 1 +#define CB_CHECKSUM_NONE 0 +#define CB_CHECKSUM_PCBIOS 1 struct cb_cmos_checksum { u32 tag; diff --git a/arch/x86/include/asm/e820.h b/arch/x86/include/asm/e820.h index a66c0d2..850a0a7 100644 --- a/arch/x86/include/asm/e820.h +++ b/arch/x86/include/asm/e820.h @@ -22,9 +22,23 @@ struct e820_entry { #define ISA_START_ADDRESS 0xa0000 #define ISA_END_ADDRESS 0x100000 -/* Implementation defined function to install an e820 map */ +/* Implementation-defined function to install an e820 map */ unsigned int install_e820_map(unsigned int max_entries, struct e820_entry *); + +/** + * cb_install_e820_map() - Install e820 map provided by coreboot sysinfo + * + * This should be used when booting from coreboot, since in that case the + * memory areas are provided by coreboot in its sysinfo. + * + * @max_entries: Maximum number of entries to write + * @entries: Place to put entires + * @return number of entries written + */ +unsigned int cb_install_e820_map(unsigned int max_entries, + struct e820_entry *entries); + #endif /* __ASSEMBLY__ */ #endif /* _ASM_X86_E820_H */ diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index 1bcbb49..65d9b3b 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -15,6 +15,7 @@ ifndef CONFIG_SPL_BUILD obj-$(CONFIG_CMD_BOOTM) += bootm.o endif obj-y += cmd_boot.o +obj-$(CONFIG_$(SPL_)COREBOOT_SYSINFO) += coreboot/ obj-$(CONFIG_SEABIOS) += coreboot_table.o obj-y += early_cmos.o obj-y += e820.o diff --git a/arch/x86/lib/bootm.c b/arch/x86/lib/bootm.c index aa5f0bf..733dd71 100644 --- a/arch/x86/lib/bootm.c +++ b/arch/x86/lib/bootm.c @@ -36,7 +36,7 @@ void bootm_announce_and_cleanup(void) printf("\nStarting kernel ...\n\n"); #ifdef CONFIG_SYS_COREBOOT - timestamp_add_now(TS_U_BOOT_START_KERNEL); + timestamp_add_now(TS_START_KERNEL); #endif bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel"); #if CONFIG_IS_ENABLED(BOOTSTAGE_REPORT) diff --git a/arch/x86/lib/coreboot/Makefile b/arch/x86/lib/coreboot/Makefile new file mode 100644 index 0000000..cb0ae1d --- /dev/null +++ b/arch/x86/lib/coreboot/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright 2021 Google LLC +# + +obj-y += cb_sysinfo.o +obj-y += cb_support.o diff --git a/arch/x86/lib/coreboot/cb_support.c b/arch/x86/lib/coreboot/cb_support.c new file mode 100644 index 0000000..ebb45cd --- /dev/null +++ b/arch/x86/lib/coreboot/cb_support.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Support for booting from coreboot + * + * Copyright 2021 Google LLC + */ + +#include <common.h> +#include <asm/cb_sysinfo.h> +#include <asm/e820.h> + +unsigned int cb_install_e820_map(unsigned int max_entries, + struct e820_entry *entries) +{ + unsigned int num_entries; + int i; + + num_entries = min((unsigned int)lib_sysinfo.n_memranges, max_entries); + if (num_entries < lib_sysinfo.n_memranges) { + printf("Warning: Limiting e820 map to %d entries\n", + num_entries); + } + for (i = 0; i < num_entries; i++) { + struct memrange *memrange = &lib_sysinfo.memrange[i]; + + entries[i].addr = memrange->base; + entries[i].size = memrange->size; + + /* + * coreboot has some extensions (type 6 & 16) to the E820 types. + * When we detect this, mark it as E820_RESERVED. + */ + if (memrange->type == CB_MEM_VENDOR_RSVD || + memrange->type == CB_MEM_TABLE) + entries[i].type = E820_RESERVED; + else + entries[i].type = memrange->type; + } + + return num_entries; +} diff --git a/arch/x86/lib/coreboot/cb_sysinfo.c b/arch/x86/lib/coreboot/cb_sysinfo.c new file mode 100644 index 0000000..e2c65bf --- /dev/null +++ b/arch/x86/lib/coreboot/cb_sysinfo.c @@ -0,0 +1,468 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * Copyright (C) 2009 coresystems GmbH + */ + +#include <common.h> +#include <asm/cb_sysinfo.h> +#include <init.h> +#include <mapmem.h> +#include <net.h> +#include <asm/global_data.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* + * This needs to be in the .data section so that it's copied over during + * relocation. By default it's put in the .bss section which is simply filled + * with zeroes when transitioning from "ROM", which is really RAM, to other + * RAM. + */ +struct sysinfo_t lib_sysinfo __attribute__((section(".data"))); + +/* + * Some of this is x86 specific, and the rest of it is generic. Right now, + * since we only support x86, we'll avoid trying to make lots of infrastructure + * we don't need. If in the future, we want to use coreboot on some other + * architecture, then take out the generic parsing code and move it elsewhere. + */ + +/* === Parsing code === */ +/* This is the generic parsing code */ + +static void cb_parse_memory(unsigned char *ptr, struct sysinfo_t *info) +{ + struct cb_memory *mem = (struct cb_memory *)ptr; + int count = MEM_RANGE_COUNT(mem); + int i; + + if (count > SYSINFO_MAX_MEM_RANGES) + count = SYSINFO_MAX_MEM_RANGES; + + info->n_memranges = 0; + + for (i = 0; i < count; i++) { + struct cb_memory_range *range = + (struct cb_memory_range *)MEM_RANGE_PTR(mem, i); + + info->memrange[info->n_memranges].base = + UNPACK_CB64(range->start); + + info->memrange[info->n_memranges].size = + UNPACK_CB64(range->size); + + info->memrange[info->n_memranges].type = range->type; + + info->n_memranges++; + } +} + +static void cb_parse_serial(unsigned char *ptr, struct sysinfo_t *info) +{ + struct cb_serial *ser = (struct cb_serial *)ptr; + + info->serial = ser; +} + +static void cb_parse_vboot_handoff(unsigned char *ptr, struct sysinfo_t *info) +{ + struct lb_range *vbho = (struct lb_range *)ptr; + + info->vboot_handoff = (void *)(uintptr_t)vbho->range_start; + info->vboot_handoff_size = vbho->range_size; +} + +static void cb_parse_vbnv(unsigned char *ptr, struct sysinfo_t *info) +{ + struct lb_range *vbnv = (struct lb_range *)ptr; + + info->vbnv_start = vbnv->range_start; + info->vbnv_size = vbnv->range_size; +} + +static void cb_parse_cbmem_entry(unsigned char *ptr, struct sysinfo_t *info) +{ + struct cb_cbmem_entry *entry = (struct cb_cbmem_entry *)ptr; + + if (entry->id != CBMEM_ID_SMBIOS) + return; + + info->smbios_start = entry->address; + info->smbios_size = entry->entry_size; +} + +static void cb_parse_gpios(unsigned char *ptr, struct sysinfo_t *info) +{ + int i; + struct cb_gpios *gpios = (struct cb_gpios *)ptr; + + info->num_gpios = (gpios->count < SYSINFO_MAX_GPIOS) ? + (gpios->count) : SYSINFO_MAX_GPIOS; + + for (i = 0; i < info->num_gpios; i++) + info->gpios[i] = gpios->gpios[i]; +} + +static void cb_parse_vdat(unsigned char *ptr, struct sysinfo_t *info) +{ + struct lb_range *vdat = (struct lb_range *)ptr; + + info->vdat_addr = map_sysmem(vdat->range_start, vdat->range_size); + info->vdat_size = vdat->range_size; +} + +static void cb_parse_mac_addresses(unsigned char *ptr, + struct sysinfo_t *info) +{ + struct cb_macs *macs = (struct cb_macs *)ptr; + int i; + + info->num_macs = (macs->count < ARRAY_SIZE(info->macs)) ? + macs->count : ARRAY_SIZE(info->macs); + + for (i = 0; i < info->num_macs; i++) + info->macs[i] = macs->mac_addrs[i]; +} + +static void cb_parse_tstamp(void *ptr, struct sysinfo_t *info) +{ + struct cb_cbmem_tab *const cbmem = ptr; + + info->tstamp_table = map_sysmem(cbmem->cbmem_tab, 0); +} + +static void cb_parse_cbmem_cons(void *ptr, struct sysinfo_t *info) +{ + struct cb_cbmem_tab *const cbmem = ptr; + + info->cbmem_cons = map_sysmem(cbmem->cbmem_tab, 0); +} + +static void cb_parse_acpi_gnvs(unsigned char *ptr, struct sysinfo_t *info) +{ + struct cb_cbmem_tab *const cbmem = (struct cb_cbmem_tab *)ptr; + + info->acpi_gnvs = map_sysmem(cbmem->cbmem_tab, 0); +} + +static void cb_parse_board_id(unsigned char *ptr, struct sysinfo_t *info) +{ + struct cb_board_id *const cbbid = (struct cb_board_id *)ptr; + + info->board_id = cbbid->board_id; +} + +static void cb_parse_ram_code(unsigned char *ptr, struct sysinfo_t *info) +{ + struct cb_ram_code *const ram_code = (struct cb_ram_code *)ptr; + + info->ram_code = ram_code->ram_code; +} + +static void cb_parse_optiontable(void *ptr, struct sysinfo_t *info) +{ + /* ptr points to a coreboot table entry and is already virtual */ + info->option_table = ptr; +} + +static void cb_parse_checksum(void *ptr, struct sysinfo_t *info) +{ + struct cb_cmos_checksum *cmos_cksum = ptr; + + info->cmos_range_start = cmos_cksum->range_start; + info->cmos_range_end = cmos_cksum->range_end; + info->cmos_checksum_location = cmos_cksum->location; +} + +static void cb_parse_framebuffer(void *ptr, struct sysinfo_t *info) +{ + /* ptr points to a coreboot table entry and is already virtual */ + info->framebuffer = ptr; +} + +static void cb_parse_string(unsigned char *ptr, char **info) +{ + *info = (char *)((struct cb_string *)ptr)->string; +} + +static void cb_parse_wifi_calibration(void *ptr, struct sysinfo_t *info) +{ + struct cb_cbmem_tab *const cbmem = (struct cb_cbmem_tab *)ptr; + + info->wifi_calibration = map_sysmem(cbmem->cbmem_tab, 0); +} + +static void cb_parse_ramoops(void *ptr, struct sysinfo_t *info) +{ + struct lb_range *ramoops = (struct lb_range *)ptr; + + info->ramoops_buffer = ramoops->range_start; + info->ramoops_buffer_size = ramoops->range_size; +} + +static void cb_parse_mtc(void *ptr, struct sysinfo_t *info) +{ + struct lb_range *mtc = (struct lb_range *)ptr; + + info->mtc_start = mtc->range_start; + info->mtc_size = mtc->range_size; +} + +static void cb_parse_spi_flash(void *ptr, struct sysinfo_t *info) +{ + struct cb_spi_flash *flash = (struct cb_spi_flash *)ptr; + + info->spi_flash.size = flash->flash_size; + info->spi_flash.sector_size = flash->sector_size; + info->spi_flash.erase_cmd = flash->erase_cmd; +} + +static void cb_parse_boot_media_params(unsigned char *ptr, + struct sysinfo_t *info) +{ + struct cb_boot_media_params *const bmp = + (struct cb_boot_media_params *)ptr; + + info->fmap_offset = bmp->fmap_offset; + info->cbfs_offset = bmp->cbfs_offset; + info->cbfs_size = bmp->cbfs_size; + info->boot_media_size = bmp->boot_media_size; +} + +static void cb_parse_vpd(void *ptr, struct sysinfo_t *info) +{ + struct cb_cbmem_tab *const cbmem = (struct cb_cbmem_tab *)ptr; + + info->chromeos_vpd = map_sysmem(cbmem->cbmem_tab, 0); +} + +static void cb_parse_tsc_info(void *ptr, struct sysinfo_t *info) +{ + const struct cb_tsc_info *tsc_info = ptr; + + if (tsc_info->freq_khz == 0) + return; + + /* Honor the TSC frequency passed to the payload */ + info->cpu_khz = tsc_info->freq_khz; +} + +static void cb_parse_x86_rom_var_mtrr(void *ptr, struct sysinfo_t *info) +{ + struct cb_x86_rom_mtrr *rom_mtrr = ptr; + + info->x86_rom_var_mtrr_index = rom_mtrr->index; +} + +static void cb_parse_mrc_cache(void *ptr, struct sysinfo_t *info) +{ + struct cb_cbmem_tab *const cbmem = (struct cb_cbmem_tab *)ptr; + + info->mrc_cache = map_sysmem(cbmem->cbmem_tab, 0); +} + +__weak void cb_parse_unhandled(u32 tag, unsigned char *ptr) +{ +} + +static int cb_parse_header(void *addr, int len, struct sysinfo_t *info) +{ + unsigned char *ptr = addr; + struct cb_header *header; + int i; + + header = (struct cb_header *)ptr; + if (!header->table_bytes) + return 0; + + /* Make sure the checksums match */ + if (!ip_checksum_ok(header, sizeof(*header))) + return -1; + + if (compute_ip_checksum(ptr + sizeof(*header), header->table_bytes) != + header->table_checksum) + return -1; + + info->header = header; + + /* + * Board straps represented by numerical values are small numbers. + * Preset them to an invalid value in case the firmware does not + * supply the info. + */ + info->board_id = ~0; + info->ram_code = ~0; + + /* Now, walk the tables */ + ptr += header->header_bytes; + + /* Inintialize some fields to sentinel values */ + info->vbnv_start = info->vbnv_size = (uint32_t)(-1); + + for (i = 0; i < header->table_entries; i++) { + struct cb_record *rec = (struct cb_record *)ptr; + + /* We only care about a few tags here (maybe more later) */ + switch (rec->tag) { + case CB_TAG_FORWARD: + return cb_parse_header( + (void *)(unsigned long) + ((struct cb_forward *)rec)->forward, + len, info); + continue; + case CB_TAG_MEMORY: + cb_parse_memory(ptr, info); + break; + case CB_TAG_SERIAL: + cb_parse_serial(ptr, info); + break; + case CB_TAG_VERSION: + cb_parse_string(ptr, &info->cb_version); + break; + case CB_TAG_EXTRA_VERSION: + cb_parse_string(ptr, &info->extra_version); + break; + case CB_TAG_BUILD: + cb_parse_string(ptr, &info->build); + break; + case CB_TAG_COMPILE_TIME: + cb_parse_string(ptr, &info->compile_time); + break; + case CB_TAG_COMPILE_BY: + cb_parse_string(ptr, &info->compile_by); + break; + case CB_TAG_COMPILE_HOST: + cb_parse_string(ptr, &info->compile_host); + break; + case CB_TAG_COMPILE_DOMAIN: + cb_parse_string(ptr, &info->compile_domain); + break; + case CB_TAG_COMPILER: + cb_parse_string(ptr, &info->compiler); + break; + case CB_TAG_LINKER: + cb_parse_string(ptr, &info->linker); + break; + case CB_TAG_ASSEMBLER: + cb_parse_string(ptr, &info->assembler); + break; + case CB_TAG_CMOS_OPTION_TABLE: + cb_parse_optiontable(ptr, info); + break; + case CB_TAG_OPTION_CHECKSUM: + cb_parse_checksum(ptr, info); + break; + /* + * FIXME we should warn on serial if coreboot set up a + * framebuffer buf the payload does not know about it. + */ + case CB_TAG_FRAMEBUFFER: + cb_parse_framebuffer(ptr, info); + break; + case CB_TAG_MAINBOARD: + info->mainboard = (struct cb_mainboard *)ptr; + break; + case CB_TAG_GPIO: + cb_parse_gpios(ptr, info); + break; + case CB_TAG_VDAT: + cb_parse_vdat(ptr, info); + break; + case CB_TAG_VBNV: + cb_parse_vbnv(ptr, info); + break; + case CB_TAG_VBOOT_HANDOFF: + cb_parse_vboot_handoff(ptr, info); + break; + case CB_TAG_MAC_ADDRS: + cb_parse_mac_addresses(ptr, info); + break; + case CB_TAG_SERIALNO: + cb_parse_string(ptr, &info->serialno); + break; + case CB_TAG_TIMESTAMPS: + cb_parse_tstamp(ptr, info); + break; + case CB_TAG_CBMEM_CONSOLE: + cb_parse_cbmem_cons(ptr, info); + break; + case CB_TAG_ACPI_GNVS: + cb_parse_acpi_gnvs(ptr, info); + break; + case CB_TAG_CBMEM_ENTRY: + cb_parse_cbmem_entry(ptr, info); + break; + case CB_TAG_BOARD_ID: + cb_parse_board_id(ptr, info); + break; + case CB_TAG_RAM_CODE: + cb_parse_ram_code(ptr, info); + break; + case CB_TAG_WIFI_CALIBRATION: + cb_parse_wifi_calibration(ptr, info); + break; + case CB_TAG_RAM_OOPS: + cb_parse_ramoops(ptr, info); + break; + case CB_TAG_SPI_FLASH: + cb_parse_spi_flash(ptr, info); + break; + case CB_TAG_MTC: + cb_parse_mtc(ptr, info); + break; + case CB_TAG_BOOT_MEDIA_PARAMS: + cb_parse_boot_media_params(ptr, info); + break; + case CB_TAG_TSC_INFO: + cb_parse_tsc_info(ptr, info); + break; + case CB_TAG_VPD: + cb_parse_vpd(ptr, info); + break; + case CB_TAG_X86_ROM_MTRR: + cb_parse_x86_rom_var_mtrr(rec, info); + break; + case CB_TAG_MRC_CACHE: + cb_parse_mrc_cache(rec, info); + break; + default: + cb_parse_unhandled(rec->tag, ptr); + break; + } + + ptr += rec->size; + } + + return 1; +} + +/* == Architecture specific == */ +/* This is the x86 specific stuff */ + +int get_coreboot_info(struct sysinfo_t *info) +{ + long addr; + int ret; + + addr = locate_coreboot_table(); + if (addr < 0) + return addr; + ret = cb_parse_header((void *)addr, 0x1000, info); + if (!ret) + return -ENOENT; + gd->arch.coreboot_table = addr; + gd->flags |= GD_FLG_SKIP_LL_INIT; + + return 0; +} + +const struct sysinfo_t *cb_get_sysinfo(void) +{ + if (!ll_boot_init()) + return &lib_sysinfo; + + return NULL; +} diff --git a/arch/x86/lib/fsp/fsp_graphics.c b/arch/x86/lib/fsp/fsp_graphics.c index cc909e0..02fd05c 100644 --- a/arch/x86/lib/fsp/fsp_graphics.c +++ b/arch/x86/lib/fsp/fsp_graphics.c @@ -87,7 +87,7 @@ static int fsp_video_probe(struct udevice *dev) int ret; if (!ll_boot_init()) - return 0; + return -ENODEV; printf("Video: "); diff --git a/arch/x86/lib/fsp2/fsp_init.c b/arch/x86/lib/fsp2/fsp_init.c index 85cae54..5afdce1 100644 --- a/arch/x86/lib/fsp2/fsp_init.c +++ b/arch/x86/lib/fsp2/fsp_init.c @@ -84,7 +84,8 @@ static int get_cbfs_fsp(enum fsp_type_t type, ulong map_base, struct cbfs_priv *cbfs; int ret; - ret = cbfs_init_mem(map_base + cbfs_base, &cbfs); + ret = cbfs_init_mem(map_base + cbfs_base, CBFS_SIZE_UNKNOWN, true, + &cbfs); if (ret) return ret; if (!ret) { diff --git a/arch/x86/lib/fsp2/fsp_support.c b/arch/x86/lib/fsp2/fsp_support.c index 503f97d..b2c7658 100644 --- a/arch/x86/lib/fsp2/fsp_support.c +++ b/arch/x86/lib/fsp2/fsp_support.c @@ -6,6 +6,7 @@ #include <common.h> #include <dm.h> +#include <init.h> #include <log.h> #include <spi_flash.h> #include <asm/fsp/fsp_support.h> @@ -114,6 +115,9 @@ u32 fsp_notify(struct fsp_header *fsp_hdr, u32 phase) struct fsp_notify_params *params_ptr; u32 status; + if (!ll_boot_init()) + return 0; + if (!fsp_hdr) fsp_hdr = gd->arch.fsp_s_hdr; diff --git a/arch/x86/lib/init_helpers.c b/arch/x86/lib/init_helpers.c index 066dc40..67401b9 100644 --- a/arch/x86/lib/init_helpers.c +++ b/arch/x86/lib/init_helpers.c @@ -18,6 +18,9 @@ int init_cache_f_r(void) IS_ENABLED(CONFIG_FSP_VERSION2); int ret; + if (!ll_boot_init()) + return 0; + do_mtrr &= !IS_ENABLED(CONFIG_FSP_VERSION1) && !IS_ENABLED(CONFIG_SYS_SLIMBOOTLOADER); @@ -31,9 +34,6 @@ int init_cache_f_r(void) return ret; } - if (!ll_boot_init()) - return 0; - /* Initialise the CPU cache(s) */ return init_cache(); } diff --git a/arch/x86/lib/spl.c b/arch/x86/lib/spl.c index 1bae1f4..b18c1cd 100644 --- a/arch/x86/lib/spl.c +++ b/arch/x86/lib/spl.c @@ -96,7 +96,7 @@ static int x86_spl_init(void) } #endif preloader_console_init(); -#ifndef CONFIG_TPL +#if !defined(CONFIG_TPL) && !CONFIG_IS_ENABLED(CPU) ret = print_cpuinfo(); if (ret) { debug("%s: print_cpuinfo() failed\n", __func__); diff --git a/arch/x86/lib/zimage.c b/arch/x86/lib/zimage.c index 602788e..90fc8a4 100644 --- a/arch/x86/lib/zimage.c +++ b/arch/x86/lib/zimage.c @@ -18,6 +18,7 @@ #include <bootm.h> #include <command.h> #include <env.h> +#include <init.h> #include <irq_func.h> #include <log.h> #include <malloc.h> @@ -28,6 +29,7 @@ #include <asm/byteorder.h> #include <asm/bootm.h> #include <asm/bootparam.h> +#include <asm/global_data.h> #ifdef CONFIG_SYS_COREBOOT #include <asm/arch/timestamp.h> #endif @@ -35,6 +37,8 @@ #include <linux/ctype.h> #include <linux/libfdt.h> +DECLARE_GLOBAL_DATA_PTR; + /* * Memory lay-out: * @@ -309,8 +313,13 @@ int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot, int bootproto = get_boot_protocol(hdr, false); log_debug("Setup E820 entries\n"); - setup_base->e820_entries = install_e820_map( - ARRAY_SIZE(setup_base->e820_map), setup_base->e820_map); + if (ll_boot_init()) { + setup_base->e820_entries = install_e820_map( + ARRAY_SIZE(setup_base->e820_map), setup_base->e820_map); + } else if (IS_ENABLED(CONFIG_COREBOOT_SYSINFO)) { + setup_base->e820_entries = cb_install_e820_map( + ARRAY_SIZE(setup_base->e820_map), setup_base->e820_map); + } if (bootproto == 0x0100) { setup_base->screen_info.cl_magic = COMMAND_LINE_MAGIC; |