- x86: various improvements made in getting Chromium OS verified boot
  running on top of coreboot, booting into U-Boot.
This commit is contained in:
Tom Rini
2021-07-15 11:06:24 -04:00
22 changed files with 221 additions and 40 deletions

View File

@@ -1,4 +1,4 @@
if TARGET_COREBOOT if VENDOR_COREBOOT
config SYS_COREBOOT config SYS_COREBOOT
bool bool

View File

@@ -423,7 +423,7 @@ static void setup_mtrr(void)
u64 mtrr_cap; u64 mtrr_cap;
/* Configure fixed range MTRRs for some legacy regions */ /* Configure fixed range MTRRs for some legacy regions */
if (!gd->arch.has_mtrr) if (!gd->arch.has_mtrr || !ll_boot_init())
return; return;
mtrr_cap = native_read_msr(MTRR_CAP_MSR); mtrr_cap = native_read_msr(MTRR_CAP_MSR);

View File

@@ -10,7 +10,7 @@
/include/ "rtc.dtsi" /include/ "rtc.dtsi"
/include/ "tsc_timer.dtsi" /include/ "tsc_timer.dtsi"
#ifdef CONFIG_CHROMEOS_VBOOT #if defined(CONFIG_CHROMEOS_VBOOT) && defined(CONFIG_ROM_SIZE)
#include "chromeos-x86.dtsi" #include "chromeos-x86.dtsi"
#include "flashmap-x86-ro.dtsi" #include "flashmap-x86-ro.dtsi"
#include "flashmap-16mb-rw.dtsi" #include "flashmap-16mb-rw.dtsi"

View File

@@ -11,7 +11,7 @@
#include "smbios.dtsi" #include "smbios.dtsi"
#ifdef CONFIG_CHROMEOS_VBOOT #if defined(CONFIG_CHROMEOS_VBOOT) && defined(CONFIG_ROM_SIZE)
#include "chromeos-x86.dtsi" #include "chromeos-x86.dtsi"
#include "flashmap-x86-ro.dtsi" #include "flashmap-x86-ro.dtsi"
#include "flashmap-8mb-rw.dtsi" #include "flashmap-8mb-rw.dtsi"

View File

@@ -215,6 +215,22 @@ struct sysinfo_t {
extern struct sysinfo_t lib_sysinfo; extern struct sysinfo_t lib_sysinfo;
/**
* get_coreboot_info() - parse the coreboot sysinfo table
*
* Parses the coreboot table if found, setting the GD_FLG_SKIP_LL_INIT flag if
* so.
*
* @info: Place to put the parsed information
* @return 0 if OK, -ENOENT if no table found
*/
int get_coreboot_info(struct sysinfo_t *info); int get_coreboot_info(struct sysinfo_t *info);
/**
* cb_get_sysinfo() - get a pointer to the parsed coreboot sysinfo
*
* @return pointer to sysinfo, or NULL if not available
*/
const struct sysinfo_t *cb_get_sysinfo(void);
#endif #endif

View File

@@ -10,18 +10,22 @@
#include <asm/atomic.h> #include <asm/atomic.h>
#include <asm/cache.h> #include <asm/cache.h>
#include <linux/bitops.h>
struct udevice; struct udevice;
enum { enum {
/* Indicates that the function should run on all CPUs */ /*
MP_SELECT_ALL = -1, * Indicates that the function should run on all CPUs. We use a large
* number, above the number of real CPUs we expect to find.
*/
MP_SELECT_ALL = BIT(16),
/* Run on boot CPUs */ /* Run on boot CPUs */
MP_SELECT_BSP = -2, MP_SELECT_BSP,
/* Run on non-boot CPUs */ /* Run on non-boot CPUs */
MP_SELECT_APS = -3, MP_SELECT_APS,
}; };
typedef int (*mp_callback_t)(struct udevice *cpu, void *arg); typedef int (*mp_callback_t)(struct udevice *cpu, void *arg);

View File

@@ -18,10 +18,20 @@ int init_cache_f_r(void)
IS_ENABLED(CONFIG_FSP_VERSION2); IS_ENABLED(CONFIG_FSP_VERSION2);
int ret; int ret;
if (!ll_boot_init()) /*
return 0; * Supported configurations:
*
do_mtrr &= !IS_ENABLED(CONFIG_FSP_VERSION1) && * booting from slimbootloader - in that case the MTRRs are already set
* up
* booting with FSPv1 - MTRRs are already set up
* booting with FSPv2 - MTRRs must be set here
* booting from coreboot - in this case there is no SPL, so we set up
* the MTRRs here
* Note: if there is an SPL, then it has already set up MTRRs so we
* don't need to do that here
*/
do_mtrr &= !IS_ENABLED(CONFIG_SPL) &&
!IS_ENABLED(CONFIG_FSP_VERSION1) &&
!IS_ENABLED(CONFIG_SYS_SLIMBOOTLOADER); !IS_ENABLED(CONFIG_SYS_SLIMBOOTLOADER);
if (do_mtrr) { if (do_mtrr) {

View File

@@ -313,12 +313,12 @@ int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot,
int bootproto = get_boot_protocol(hdr, false); int bootproto = get_boot_protocol(hdr, false);
log_debug("Setup E820 entries\n"); log_debug("Setup E820 entries\n");
if (ll_boot_init()) { if (IS_ENABLED(CONFIG_COREBOOT_SYSINFO)) {
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( setup_base->e820_entries = cb_install_e820_map(
ARRAY_SIZE(setup_base->e820_map), setup_base->e820_map); ARRAY_SIZE(setup_base->e820_map), setup_base->e820_map);
} else {
setup_base->e820_entries = install_e820_map(
ARRAY_SIZE(setup_base->e820_map), setup_base->e820_map);
} }
if (bootproto == 0x0100) { if (bootproto == 0x0100) {

View File

@@ -1,4 +1,4 @@
if TARGET_COREBOOT if VENDOR_COREBOOT
config SYS_BOARD config SYS_BOARD
default "coreboot" default "coreboot"
@@ -9,9 +9,6 @@ config SYS_VENDOR
config SYS_SOC config SYS_SOC
default "coreboot" default "coreboot"
config SYS_CONFIG_NAME
default "coreboot"
config SYS_TEXT_BASE config SYS_TEXT_BASE
default 0x01110000 default 0x01110000
@@ -31,4 +28,11 @@ config SYS_CAR_SIZE
help help
This option specifies the board specific Cache-As-RAM (CAR) size. This option specifies the board specific Cache-As-RAM (CAR) size.
endif # CONFIG_VENDOR_COREBOOT
if TARGET_COREBOOT
config SYS_CONFIG_NAME
default "coreboot"
endif endif

View File

@@ -37,6 +37,7 @@ int show_board_info(void)
goto fallback; goto fallback;
const char *bios_ver = smbios_string(bios, t0->bios_ver); const char *bios_ver = smbios_string(bios, t0->bios_ver);
const char *bios_date = smbios_string(bios, t0->bios_release_date);
const char *model = smbios_string(system, t1->product_name); const char *model = smbios_string(system, t1->product_name);
const char *manufacturer = smbios_string(system, t1->manufacturer); const char *manufacturer = smbios_string(system, t1->manufacturer);
@@ -46,6 +47,8 @@ int show_board_info(void)
printf("Vendor: %s\n", manufacturer); printf("Vendor: %s\n", manufacturer);
printf("Model: %s\n", model); printf("Model: %s\n", model);
printf("BIOS Version: %s\n", bios_ver); printf("BIOS Version: %s\n", bios_ver);
if (bios_date)
printf("BIOS date: %s\n", bios_date);
return 0; return 0;

View File

@@ -10,17 +10,21 @@
#include <command.h> #include <command.h>
#include <cros_ec.h> #include <cros_ec.h>
#include <dm.h> #include <dm.h>
#include <init.h>
#include <log.h> #include <log.h>
#include <sysinfo.h> #include <sysinfo.h>
#include <acpi/acpigen.h> #include <acpi/acpigen.h>
#include <asm-generic/gpio.h> #include <asm-generic/gpio.h>
#include <asm/acpi_nhlt.h> #include <asm/acpi_nhlt.h>
#include <asm/cb_sysinfo.h>
#include <asm/intel_gnvs.h> #include <asm/intel_gnvs.h>
#include <asm/intel_pinctrl.h> #include <asm/intel_pinctrl.h>
#include <dm/acpi.h> #include <dm/acpi.h>
#include <linux/delay.h> #include <linux/delay.h>
#include "variant_gpio.h" #include "variant_gpio.h"
DECLARE_GLOBAL_DATA_PTR;
struct cros_gpio_info { struct cros_gpio_info {
const char *linux_name; const char *linux_name;
enum cros_gpio_t type; enum cros_gpio_t type;
@@ -28,6 +32,30 @@ struct cros_gpio_info {
int flags; int flags;
}; };
int misc_init_f(void)
{
if (!ll_boot_init()) {
printf("Running as secondary loader");
if (gd->arch.coreboot_table) {
int ret;
printf(" (found coreboot table at %lx)",
gd->arch.coreboot_table);
ret = get_coreboot_info(&lib_sysinfo);
if (ret) {
printf("\nFailed to parse coreboot tables (err=%d)\n",
ret);
return ret;
}
}
printf("\n");
}
return 0;
}
int arch_misc_init(void) int arch_misc_init(void)
{ {
return 0; return 0;

View File

@@ -50,3 +50,24 @@ works by using a 32-bit SPL binary to switch to 64-bit for running U-Boot. It
can be useful for running UEFI applications, for example. can be useful for running UEFI applications, for example.
This has only been lightly tested. This has only been lightly tested.
Memory map
----------
========== ==================================================================
Address Region at that address
========== ==================================================================
ffffffff Top of ROM (and last byte of 32-bit address space)
7a9fd000 Typical top of memory available to U-Boot
(use cbsysinfo to see where memory range 'table' starts)
10000000 Memory reserved by coreboot for mapping PCI devices
(typical size 2151000, includes framebuffer)
1920000 CONFIG_SYS_CAR_ADDR, fake Cache-as-RAM memory, used during startup
1110000 CONFIG_SYS_TEXT_BASE (start address of U-Boot code, before reloc)
110000 CONFIG_BLOBLIST_ADDR (before being relocated)
100000 CONFIG_PRE_CON_BUF_ADDR
f0000 ACPI tables set up by U-Boot
(typically redirects to 7ab10030 or similar)
500 Location of coreboot sysinfo table, used during startup
========== ==================================================================

View File

@@ -6,11 +6,15 @@
Running U-Boot with Chromium OS verified boot Running U-Boot with Chromium OS verified boot
============================================= =============================================
Note: Once you use the source below you can obtain extra documentation with
'make htmldocs'. See the 'Internal Documentation' link, under
'Chromium OS-specific doc'.
To obtain:: To obtain::
git clone https://github.com/sjg20/u-boot.git git clone https://github.com/sjg20/u-boot.git
cd u-boot cd u-boot
git checkout cros-master git checkout cros-2021.04
cd .. cd ..
git clone https://chromium.googlesource.com/chromiumos/platform/vboot_reference git clone https://chromium.googlesource.com/chromiumos/platform/vboot_reference
@@ -169,7 +173,8 @@ detect problems that affect the flow or particular vboot features.
U-Boot without Chromium OS verified boot U-Boot without Chromium OS verified boot
---------------------------------------- ----------------------------------------
The following script can be used to boot a Chrome OS image on coral:: The following script can be used to boot a Chrome OS image on coral. It is
defined as the boot command in mainline::
# Read the image header and obtain the address of the kernel # Read the image header and obtain the address of the kernel
# The offset 4f0 is defined by verified boot and may change for other # The offset 4f0 is defined by verified boot and may change for other
@@ -195,10 +200,4 @@ The following script can be used to boot a Chrome OS image on coral::
zboot go zboot go
TO DO
-----
Get the full ACPI tables working with Coral
7 October 2018 7 October 2018

View File

@@ -20,6 +20,10 @@ For PCI devices the following optional property is available:
output to be lost. This should not generally be used in production code, output to be lost. This should not generally be used in production code,
although it is often harmless. although it is often harmless.
- u-boot,pci-pre-reloc : List of vendor/device IDs to bind before relocation, even
if they are not bridges. This is useful if the device is needed (e.g. a
UART). The format is 0xvvvvdddd where d is the device ID and v is the
vendor ID.
Example: Example:
@@ -32,7 +36,8 @@ pci {
0x42000000 0x0 0xb0000000 0xb0000000 0 0x10000000 0x42000000 0x0 0xb0000000 0xb0000000 0 0x10000000
0x01000000 0x0 0x1000 0x1000 0 0xefff>; 0x01000000 0x0 0x1000 0x1000 0 0xefff>;
u-boot,skip-auto-config-until-reloc; u-boot,skip-auto-config-until-reloc;
u-boot,pci-pre-reloc = <
PCI_VENDEV(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_APL_UART2)>;
serial: serial@18,2 { serial: serial@18,2 {
reg = <0x0200c210 0 0 0 0>; reg = <0x0200c210 0 0 0 0>;

View File

@@ -21,6 +21,7 @@
#if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP) #if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP)
#include <asm/fsp/fsp_support.h> #include <asm/fsp/fsp_support.h>
#endif #endif
#include <dt-bindings/pci/pci.h>
#include <linux/delay.h> #include <linux/delay.h>
#include "pci_internal.h" #include "pci_internal.h"
@@ -164,7 +165,7 @@ int dm_pci_bus_find_bdf(pci_dev_t bdf, struct udevice **devp)
} }
static int pci_device_matches_ids(struct udevice *dev, static int pci_device_matches_ids(struct udevice *dev,
struct pci_device_id *ids) const struct pci_device_id *ids)
{ {
struct pci_child_plat *pplat; struct pci_child_plat *pplat;
int i; int i;
@@ -181,7 +182,7 @@ static int pci_device_matches_ids(struct udevice *dev,
return -EINVAL; return -EINVAL;
} }
int pci_bus_find_devices(struct udevice *bus, struct pci_device_id *ids, int pci_bus_find_devices(struct udevice *bus, const struct pci_device_id *ids,
int *indexp, struct udevice **devp) int *indexp, struct udevice **devp)
{ {
struct udevice *dev; struct udevice *dev;
@@ -201,7 +202,7 @@ int pci_bus_find_devices(struct udevice *bus, struct pci_device_id *ids,
return -ENODEV; return -ENODEV;
} }
int pci_find_device_id(struct pci_device_id *ids, int index, int pci_find_device_id(const struct pci_device_id *ids, int index,
struct udevice **devp) struct udevice **devp)
{ {
struct udevice *bus; struct udevice *bus;
@@ -681,6 +682,34 @@ static bool pci_match_one_id(const struct pci_device_id *id,
return false; return false;
} }
/**
* pci_need_device_pre_reloc() - Check if a device should be bound
*
* This checks a list of vendor/device-ID values indicating devices that should
* be bound before relocation.
*
* @bus: Bus to check
* @vendor: Vendor ID to check
* @device: Device ID to check
* @return true if the vendor/device is in the list, false if not
*/
static bool pci_need_device_pre_reloc(struct udevice *bus, uint vendor,
uint device)
{
u32 vendev;
int index;
for (index = 0;
!dev_read_u32_index(bus, "u-boot,pci-pre-reloc", index,
&vendev);
index++) {
if (vendev == PCI_VENDEV(vendor, device))
return true;
}
return false;
}
/** /**
* pci_find_and_bind_driver() - Find and bind the right PCI driver * pci_find_and_bind_driver() - Find and bind the right PCI driver
* *
@@ -769,7 +798,9 @@ static int pci_find_and_bind_driver(struct udevice *parent,
* precious memory space as on some platforms as that space is pretty * precious memory space as on some platforms as that space is pretty
* limited (ie: using Cache As RAM). * limited (ie: using Cache As RAM).
*/ */
if (!(gd->flags & GD_FLG_RELOC) && !bridge) if (!(gd->flags & GD_FLG_RELOC) && !bridge &&
!pci_need_device_pre_reloc(parent, find_id->vendor,
find_id->device))
return log_msg_ret("notbr", -EPERM); return log_msg_ret("notbr", -EPERM);
/* Bind a generic driver so that the device can be used */ /* Bind a generic driver so that the device can be used */

View File

@@ -114,7 +114,7 @@ static bool ich9_can_do_33mhz(struct udevice *dev)
struct ich_spi_priv *priv = dev_get_priv(dev); struct ich_spi_priv *priv = dev_get_priv(dev);
u32 fdod, speed; u32 fdod, speed;
if (!CONFIG_IS_ENABLED(PCI)) if (!CONFIG_IS_ENABLED(PCI) || !priv->pch)
return false; return false;
/* Observe SPI Descriptor Component Section 0 */ /* Observe SPI Descriptor Component Section 0 */
dm_pci_write_config32(priv->pch, 0xb0, 0x1000); dm_pci_write_config32(priv->pch, 0xb0, 0x1000);
@@ -632,7 +632,7 @@ static int ich_spi_get_basics(struct udevice *bus, bool can_probe,
if (device_get_uclass_id(pch) != UCLASS_PCH) { if (device_get_uclass_id(pch) != UCLASS_PCH) {
uclass_first_device(UCLASS_PCH, &pch); uclass_first_device(UCLASS_PCH, &pch);
if (!pch) if (!pch)
return log_msg_ret("uclass", -EPROTOTYPE); ; /* ignore this error since we don't need it */
} }
} }

View File

@@ -18,8 +18,6 @@
#include <acpi/acpi_device.h> #include <acpi/acpi_device.h>
#include <asm/gpio.h> #include <asm/gpio.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/arch/iomap.h>
#include <asm/arch/pm.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <dm/acpi.h> #include <dm/acpi.h>

View File

@@ -0,0 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* This header provides common constants for PCI bindings.
*/
#ifndef _DT_BINDINGS_PCI_PCI_H
#define _DT_BINDINGS_PCI_PCI_H
/* Encode a vendor and device ID into a single cell */
#define PCI_VENDEV(v, d) (((v) << 16) | (d))
#endif /* _DT_BINDINGS_PCI_PCI_H */

View File

@@ -578,7 +578,6 @@ typedef int pci_dev_t;
#define PCI_MASK_BUS(bdf) ((bdf) & 0xffff) #define PCI_MASK_BUS(bdf) ((bdf) & 0xffff)
#define PCI_ADD_BUS(bus, devfn) (((bus) << 16) | (devfn)) #define PCI_ADD_BUS(bus, devfn) (((bus) << 16) | (devfn))
#define PCI_BDF(b, d, f) ((b) << 16 | PCI_DEVFN(d, f)) #define PCI_BDF(b, d, f) ((b) << 16 | PCI_DEVFN(d, f))
#define PCI_VENDEV(v, d) (((v) << 16) | (d))
#define PCI_ANY_ID (~0) #define PCI_ANY_ID (~0)
/* Convert from Linux format to U-Boot format */ /* Convert from Linux format to U-Boot format */
@@ -1064,7 +1063,7 @@ int pci_get_ff(enum pci_size_t size);
* @devp: Returns matching device if found * @devp: Returns matching device if found
* @return 0 if found, -ENODEV if not * @return 0 if found, -ENODEV if not
*/ */
int pci_bus_find_devices(struct udevice *bus, struct pci_device_id *ids, int pci_bus_find_devices(struct udevice *bus, const struct pci_device_id *ids,
int *indexp, struct udevice **devp); int *indexp, struct udevice **devp);
/** /**
@@ -1076,7 +1075,7 @@ int pci_bus_find_devices(struct udevice *bus, struct pci_device_id *ids,
* @devp: Returns matching device if found * @devp: Returns matching device if found
* @return 0 if found, -ENODEV if not * @return 0 if found, -ENODEV if not
*/ */
int pci_find_device_id(struct pci_device_id *ids, int index, int pci_find_device_id(const struct pci_device_id *ids, int index,
struct udevice **devp); struct udevice **devp);
/** /**

View File

@@ -749,6 +749,15 @@ class DtbPlatdata():
break break
if node.parent and node.parent.parent: if node.parent and node.parent.parent:
if node.parent not in self._valid_nodes:
# This might indicate that the parent node is not in the
# SPL/TPL devicetree but the child is. For example if we are
# dealing with of-platdata in TPL, the parent has a
# u-boot,dm-tpl tag but the child has u-boot,dm-pre-reloc. In
# this case the child node exists in TPL but the parent does
# not.
raise ValueError("Node '%s' requires parent node '%s' but it is not in the valid list" %
(node.path, node.parent.path))
self.buf('\t.parent\t\t= DM_DEVICE_REF(%s),\n' % self.buf('\t.parent\t\t= DM_DEVICE_REF(%s),\n' %
node.parent.var_name) node.parent.var_name)
if priv_name: if priv_name:

View File

@@ -0,0 +1,32 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Test device tree file for dtoc
*
* Copyright 2017 Google, Inc
*/
/dts-v1/;
/ {
#address-cells = <1>;
#size-cells = <1>;
i2c@0 {
compatible = "sandbox,i2c";
u-boot,dm-tpl;
#address-cells = <1>;
#size-cells = <0>;
spl-test {
u-boot,dm-pre-reloc;
compatible = "sandbox,spl-test";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
pmic@9 {
compatible = "sandbox,pmic";
u-boot,dm-pre-reloc;
reg = <9>;
low-power;
};
};
};
};

View File

@@ -1830,3 +1830,13 @@ U_BOOT_DRVINFO(spl_test2) = {
dtb_file = get_dtb_file('dtoc_test_single_reg.dts') dtb_file = get_dtb_file('dtoc_test_single_reg.dts')
output = tools.GetOutputFilename('output') output = tools.GetOutputFilename('output')
self.run_test(['struct'], dtb_file, output) self.run_test(['struct'], dtb_file, output)
def test_missing_parent(self):
"""Test detection of a parent node with no properties"""
dtb_file = get_dtb_file('dtoc_test_noparent.dts', capture_stderr=True)
output = tools.GetOutputFilename('output')
with self.assertRaises(ValueError) as exc:
self.run_test(['device'], dtb_file, output, instantiate=True)
self.assertIn("Node '/i2c@0/spl-test/pmic@9' requires parent node "
"'/i2c@0/spl-test' but it is not in the valid list",
str(exc.exception))