Duncan Laurie has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
fw_config: Add firmware configuration interface
This change introduces a new top-level interface for interacting with a bitmask providing firmware configuration information.
This is motivated by Chromebook mainboards that need to support multiple different configurations at runtime with the same BIOS. In these devices the Embedded Controller provides a bitmask that can be broken down into different fields and each field can be broken down into different options.
The firmware configuration interface is intended to be easily adapted by device drivers and mainboards and lead to less code duplication for new mainboards that make use of this feature by providing common functions and integration into devicetree.cb.
BUG=b:147462631 TEST=this provides a new interface that is tested in subsequent commits
Change-Id: I1e889c235a81545e2ec0e3a34dfa750ac828a330 Signed-off-by: Duncan Laurie dlaurie@google.com --- A Documentation/lib/fw_config.md M Documentation/lib/index.md A src/include/fw_config.h M src/lib/Kconfig M src/lib/Makefile.inc A src/lib/fw_config.c 6 files changed, 742 insertions(+), 1 deletion(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/09/41209/1
diff --git a/Documentation/lib/fw_config.md b/Documentation/lib/fw_config.md new file mode 100644 index 0000000..6f769d6 --- /dev/null +++ b/Documentation/lib/fw_config.md @@ -0,0 +1,406 @@ +# Firmware Configuration Interface in coreboot + +## Motivation + +The firmware configuration interface in coreboot is designed to support a wide variety of +configuration options in that are dictated by the hardware at runtime. This allows a single +BIOS image to be used across a wide variety of devices which may have key differences but are +otherwise similar enough to be a variant of the same baseboard. + +The initial implementation is designed to take advantage of a bitmask returned by the Embedded +Controller on Google Chrome OS devices which allows the manufacturer to use the same firmware +image across multiple devices by selecting various options at runtime. A different +implementation could use a file in CBFS or a hard coded value in Kconfig for different images +to make the selected configuration options static. + +This firmware configuration interface differs from the CMOS option interface in that this +bitmask value is not intended as a user-configurable setting as the configuration values must +match the actual hardware. In the case where a user was to swap their hardware this value +would need to be updated or overridden. + +## Device Presence + +One common example of why a firmware configuration interface is important is determining if a +device is present in the system. With some bus topologies and hardware mechanisms it is +possible to probe and enumerate this at runtime: + +- PCI is a self-discoverable bus and is very easy to handle. +- I2C devices can often be probed with a combination of bus and address. +- The use of GPIOs with external strap to ground or different voltages can be used to detect +presence of a device. + +However there are several cases where this is insufficient: + +- I2C peripherals that require different drivers but have the same bus address cannot be +uniquely identified at runtime. +- A mainboard may be designed with multiple daughter board combinations which contain devices +and configurations that cannot be detected. +- While presence detect GPIOs are a convenient way for a single device presence, they are +unable to distinguish between different devices so it can require a large number of GPIOs to +support relatively few options. + +This presence detection can impact different stages of boot: + +### ACPI + +Devices that are not present should not provide an ACPI device indicating that they are +present or the operating system may not be able to handle it correctly. + +The ACPI devices are largely driven by chips defined in the mainboard `devicetree.cb` and +the variant overridetree.cb. This means it is important to be able to specify when a device +is present or not directly in `devicetree.cb` itself. Otherwise each mainboard needs custom +code to parse the tree and disable unused devices. + +### GPIO + +GPIOs with multiple functions may need to be configured correctly depending on the attached +device. Given the wide variety of GPIO configuration possibilities it is not feasible to +specify all combinations directly in `devicetree.cb` and it is best left to code provided by +the mainboard. + +### FSP UPD + +Enabling and disabling devices may require altering FSP UPD values that are provided to the +various stages of FSP. These options are also not easy to specify multiple times for +different configurations in `devicetree.cb` and can be provided by the mainboard as code. + +## Firmware Configuration Interface + +The firmware configuration interface consists of two inputs: + +1. The table of fields and options that represent the board-specific bitmask. +2. The bitmask of selected options for a particular hardware combination. + +Both of these are provided by the mainboard itself because it is the source of truth for the +possible combinations of SoC and devices. + +### Mainboard Table + +To use the firmware configuration interface the mainboard provides a table defining the fields +within the bitmask and what each of the various options are within each field. + +The list of fields is terminated by an empty field where `field.name == NULL`. + +### Field List + +The table provides a `struct fw_config_field` for each field within the bitmask and contains +the name of that field as well as the starting offset and the mask of bits to be included. + +Each field also contains a list of `struct fw_config_option` which is terminated by an empty +entry where `option.name == NULL`. + +```c +/** + * struct fw_config_field - Descriptor for field within firmware configuration bitmask. + * @name: Name of this field. + * @mask: Mask value that indicates which bits are in this field. + * @shift: Offset within the 32-bit value where this field starts. + * @option: List of field options. + */ +struct fw_config_field { + const char *name; + uint32_t mask; + size_t shift; + struct fw_config_option option[FW_CONFIG_OPTION_MAX]; +}; +``` + +### Option List + +Each field can contain multiple `struct fw_config_option` definitions, and one should be +provided for each possible field option. Options must be unique and there is no provision in +this design for multiple options that have the same value or name. + +Each field option in the list consists of a name and the expected field value, as well as a +callback function. This callback will be executed at boot if the option matches the value of +the field returned by the mainboard. + +```c +/** + * struct fw_config_option - Descriptor for option within a field. + * @name: Name of this field option. + * @value: Value of this option. + * @callback: Function callback for when this option is selected. + */ +struct fw_config_option { + const char *name; + uint32_t value; + fw_config_option_cb *callback; +}; +``` + +Helper macros are provided which make it easier to write the firmware configuration table and +allow the fields to be specified on one line. + + FW_CONFIG_FIELD(name, mask, shift) + FW_CONFIG_OPTION(name, value) + FW_CONFIG_OPTION_CB(name, value, callback) + +### Probe List + +The probe list provides a set of field and option names to match against the mainboard table +and value. Each entry specifies the name of the field within the firmware configuration +bitmask and the name of the option within that field that should be checked. + +This list allows for a driver probe to check for multiple matches, either multiple options +from the same field or from different fields. + +An array of these structures is typically provided in a driver chip configuration structure +and filled out by the mainboard in `devicetree.cb`. + +```c +/** + * struct fw_config_probe - Descriptor for a firmware configuration probe match. + * @field: Name of the field to match. + * @option: Name of the option within the field to match. + */ +struct fw_config_probe { + const char *field; + const char *option; +}; +``` + +A helper macro is provided to make it easier to add matches for driver probing. Note that +with this macro the name strings should not be enclosed in quotes, in order to allow this to +be easily used in `devicetree.cb`: + + FW_CONFIG_MATCH(field_name, option_name) + +### Interface Library + +In addition to the structures there are some defined library functions that are intended for +use by drivers and mainboards. + +#### Match Field and Option + +This function searches the mainboard table for a matching field and option name. It takes +a single field and option name to search for and returns a boolean value that indicates +whether the field and option was found in the table. + +This is intended for mainboards that may need to to additional processing outside of the +automated probing and callback interface. For example during romstage it may be necessary +to check if a given field and option is enabled and adjust a parameter to FSP-M. + +```c +/** + * fw_config_match() - Check provided field and option name against mainboard table. + * @field_name: Name of the field that this option belongs to. + * @option_name: Name of the option within the field to find. + * + * Return %true if option is a match, %false if option does not match. + */ +bool fw_config_match(const char *field_name, const char *option_name); +``` + +#### Probe Device + +This interface is used by device drivers to probe a list of field and option names where any +match in the list is considered a successful probe. A device declared in `devicetree.cb` may +be considered present by more than one option, and any entry in the list is considered a +positive match. + +```c +/** + * fw_config_probe() - Check each field and option against match_list. + * @match_list: List of fw_config field and option names to check. + * + * Return %true if match is found, %false if match is not found. + */ +bool fw_config_probe(const struct fw_config_probe *match_list); +``` + +## Mainboard Integration + +There are several requirements that the mainboard is expected to provide for the firmware +configuration interface. + +### Configuration Table + +The mainboard must provide a function that returns the table of fields and options as well as +the current firmware configuration value. + +The table itself can be declared as a static structure in the mainboard code. Here we show a +boolean 1-bit field for `FEATURE` which is at bit offset 0 and can be set to either `ENABLE` +or `DISABLE`. + +```c +static const struct fw_config_field mainboard_fw_config[] = { + { + FW_CONFIG_FIELD("FEATURE", 0x1, 0), + .option = { + FW_CONFIG_OPTION("DISABLE", 0), + FW_CONFIG_OPTION("ENABLE", 1), + } + }, + { } +}; +``` + +### Configuration Value + +The actual selection of firmware configuration options is done based on a 32-bit mask that +is provided by the mainboard. This value can be read from a variety of different sources: + +- Chrome OS boards typically retrieve the firmware configuration value from the Embedded +Controller via a mailbox function. +- The value could be hard coded in Kconfig or in the source directly. +- The value could be provided in CBFS and added to the image after building. +- The value could be stored directly in flash or CMOS. + +In this example the value is read from the Chrome OS Embedded Controller and provided together +with the pointer to the mainboard firmware configuration table. + +```c +size_t mainboard_get_fw_config(const struct fw_config_field **table, uint32_t *config) +{ + if (google_chromeec_cbi_get_fw_config(config) < 0) { + printk(BIOS_ERR, "Could not get fw_config from EC\n"); + return 0; + } + + *table = mainboard_fw_config; + return ARRAY_SIZE(mainboard_fw_config); +} +``` + +### Option Callbacks + +The table of fields and values can optionally contain a callback function for each defined +option. This allows the mainboard to do special configuration to support the particular +selected option. + +During boot the table of fields is compared against the mainboard provided bitmask and +callbacks will be executed for the option that matches within each field. This happens before +the device driver enable stage to allow the mainboard to alter the device tree if needed. + +Continuing with the previous example if the value returned by the mainboard at boot has +`bit 0 == 0` then the `FEATURE` field option will be set to `DISABLE` and the provided callback +`feature_disable_cb()` will be executed. If the field value is 1 then the field option will +be set to `ENABLE` and the provided callback `feature_enable_cb()` will be executed. + +```c +static void feature_disable_cb(const struct fw_config_option *option) +{ + const struct pad_config disable_pads[] = { + PAD_NC(GPP_S0, NONE), + PAD_NC(GPP_S1, NONE), + }; + gpio_configure_pads(disable_pads, ARRAY_SIZE(disable_pads)); +} + +static void feature_enable_cb(const struct fw_config_option *option) +{ + const struct pad_config enable_pads[] = { + PAD_CFG_NF(GPP_S0, NONE, DEEP, NF1), + PAD_CFG_NF(GPP_S1, NONE, DEEP, NF1), + }; + gpio_configure_pads(enable_pads, ARRAY_SIZE(enable_pads)); +} + +static const struct fw_config_field mainboard_fw_config[] = { + { + FW_CONFIG_FIELD("FEATURE", 0x1, 0), + .option = { + FW_CONFIG_OPTION_CB("DISABLE", 0, feature_disable_cb), + FW_CONFIG_OPTION_CB("ENABLE", 1, feature_enable_cb), + } + }, + { } +}; +``` + +### Device Driver Probing + +When a device driver supports the firmware configuration interface the probe matches can be +specified directly in `devicetree.cb` together with the driver. This relies on an array of +`struct fw_config_probe` to allow multiple matches to be specified. This is a convenient +way to disable drivers for hardware that does not exist in the system, preventing the system +from allocating resources or generating ACPI code for that device. + +This `devicetree.cb` example is based on the table provided in previous examples. If the +`FEATURE` field is set to `ENABLE` then this match will be true and the device will be +considered present. If the field was set to `DISABLE` then the device would be disabled in +the driver by clearing the `enabled` flag in the device structure, and it would not execute +any callback. + +``` +device pci 15.0 on + chip drivers/i2c/generic + register "desc" = ""Example Probed Device"" + register "fw_config_probe" = "true" + register "fw_config" = "{ FW_CONFIG_MATCH(FEATURE, ENABLE) }" + device i2c ff on end + end +end +``` + +## Driver Integration + +Driver support for firmware configuration needs only a few changes: + +1) Add an array of `struct fw_config_probe` to the chip configuration in `chip.h`, along with +an enable flag to make it clear that this probing is expected. +2) Call `fw_config_probe()` from the drivers `chip.enable_dev()` function and supply the list +of matches to check from `devicetree.cb` as an argument. +3) Disable the device if the probe returns false. + +### Example: Driver Chip Configuration + +```c +struct drivers_example_config { + bool fw_config_probe; + struct fw_config_probe fw_config[FW_CONFIG_PROBE_MAX]; +}; +``` + +### Example: Driver Enable Function + +```c +static void drivers_example_enable(struct device *dev) +{ + struct drivers_example_config *config = dev->chip_info; + + if (config->fw_config_probe && !fw_config_probe(config->fw_config)) + dev->enabled = 0; +} +struct chip_operations drivers_example_ops = { + CHIP_NAME("Example Driver") + .enable_dev = drivers_example_enable +}; +``` + +## Other Uses + +The device driver probing and callback interface allow for seamless integration with the +mainboard, but both are designed for ramstage and there are other situations where code may +need to probe or check the value of a field in romstage or other points in ramstage. For +this reason it is also possible to use the firmware configuration interface directly. + +This example has a mainboard check if a feature is disabled and set an FSP UPD before memory +training. This example expects that the default value of this option is set to `true` in +`devicetree.cb` and this code is disabling that feature before FSP is executed. + +```c +void mainboard_memory_init_params(FSPM_UPD *mupd) +{ + if (fw_config_match("FEATURE", "DISABLE")) + mupd->ExampleFeature = false; +} +``` + +### Modifying the Firmware Configuration + +The actual implementation of retrieving the firmware configuration value is left up to the +individual mainboard. If the value comes from Kconfig it is easy to adjust in the local +config file. If it comes from CBFS it could be updated after building the image. + +Google Chrome OS devices support an Embedded Controller interface for reading and writing the +firmware configuration value, along with other board-specific information. It is not typically +necessary to adjust this value, but it is possible *(after disabling write protection)* by using +the `ectool` command in a Chrome OS environment. + +For more information on the firmware configuration field on Chrome OS devices see the Chromium +documentation for [Firmware Config][1] and [Board Info][2]. + +[1]: http://chromium.googlesource.com/chromiumos/docs/+/master/design_docs/firmwa... +[2]: http://chromium.googlesource.com/chromiumos/docs/+/master/design_docs/cros_b... diff --git a/Documentation/lib/index.md b/Documentation/lib/index.md index 99b8061..d64b4e9 100644 --- a/Documentation/lib/index.md +++ b/Documentation/lib/index.md @@ -3,7 +3,7 @@ This section contains documentation about coreboot internal technical information and libraries.
-## Structure and layout - [Flashmap and Flashmap Descriptor](flashmap.md) - [ABI data consumption](abi-data-consumption.md) - [Timestamps](timestamp.md) +- [Firmware Configuration Interface](fw_config.md) diff --git a/src/include/fw_config.h b/src/include/fw_config.h new file mode 100644 index 0000000..a2780e5 --- /dev/null +++ b/src/include/fw_config.h @@ -0,0 +1,149 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* This file is part of the coreboot project. */ + +#ifndef __FW_CONFIG__ +#define __FW_CONFIG__ + +#include <stdint.h> +#include <types.h> + +/** + * enum fw_config_max - Limits on firmware configuration structures. + * @FW_CONFIG_PROBE_MAX: Default limit of probe entries for a driver. + * @FW_CONFIG_OPTION_MAX: Limit on the number of options within a field. + */ +enum fw_config_max { + FW_CONFIG_PROBE_MAX = 8, + FW_CONFIG_OPTION_MAX = 32 +}; + +/** + * fw_config_option_cb() - Callback for option to do extra work. + * @option: Option that was discovered. + */ +struct fw_config_option; +typedef void fw_config_option_cb(const struct fw_config_option *option); + +/** + * struct fw_config_option - Descriptor for option within a field. + * @name: Name of this field option. + * @value: Value of this option. + * @callback: Function callback for when this option is selected. + */ +struct fw_config_option { + const char *name; + uint32_t value; + fw_config_option_cb *callback; +}; + +/** + * struct fw_config_field - Descriptor for field within firmware configuration bitmask. + * @name: Name of this field. + * @mask: Mask value that indicates which bits are in this field. + * @shift: Offset within the 32-bit value where this field starts. + * @option: List of field options. + */ +struct fw_config_field { + const char *name; + uint32_t mask; + size_t shift; + struct fw_config_option option[FW_CONFIG_OPTION_MAX]; +}; + +/** + * struct fw_config_probe - Descriptor for a firmware configuration probe match. + * @field: Name of the field to match. + * @option: Name of the option within the field to match. + */ +struct fw_config_probe { + const char *field; + const char *option; +}; + +/** + * FW_CONFIG_FIELD() - Helper macro for defining a field. + * @__name: Name of this field. + * @__mask: Bitmask for extracting this field. + * @__shift: Bit offset where this field starts. + */ +#define FW_CONFIG_FIELD(__name, __mask, __shift) \ + .name = (__name), \ + .mask = (__mask), \ + .shift = (__shift) + +/** + * FW_CONFIG_OPTION_CB() - Helper macro for defining a field option with a callback. + * @__name; Name of the field option. + * @__value: Value for this option after field shift and mask are applied. + * @__callback: Function to be called if the field is set to this option. + */ +#define FW_CONFIG_OPTION_CB(__name, __value, __callback) { \ + .name = (__name), \ + .value = (__value), \ + .callback = (__callback) \ +} + +/** + * FW_CONFIG_OPTION() - Helper macro for defining a field option without a callback. + * @__name; Name of the field option. + * @__value: Value for this option after field shift and mask are applied. + */ +#define FW_CONFIG_OPTION(__name, __value) FW_CONFIG_OPTION_CB(__name, __value, NULL) + +/** + * FW_CONFIG_MATCH() - Helper macro for defining a field and option to match against. + * @__field: Name of the field to match. + * @__option: Name of the field option to match. + */ +#define FW_CONFIG_MATCH(__field, __option) { \ + .field = #__field, \ + .option = #__option, \ +} + +/** + * mainboard_get_fw_config() - Get table of fields and config value from mainboard. + * This is defined as a weak function in lib/fw_config.c + * and can be overridden by the mainboard. + * @table: Pointer to list of fields that is provided by the mainboard. The list is + * terminated by an empty entry where the field name is NULL. + * @config: Pointer to 32-bit integer of mainboard firmware configuration value. + * + * Return number of entries in mainboard_table, zero if table is not found. + */ +size_t mainboard_get_fw_config(const struct fw_config_field **table, uint32_t *config); + +#if CONFIG(FW_CONFIG) + +/** + * fw_config_match() - Check provided field and option name against mainboard table. + * @field_name: Name of the field that this option belongs to. + * @option_name: Name of the option within the field to find. + * + * Return %true if option is a match, %false if option does not match. + */ +bool fw_config_match(const char *field_name, const char *option_name); + +/** + * fw_config_probe() - Check each field and option against match_list. + * @match_list: List of fw_config field and option names to check. + * + * Return %true if match is found, %false if match is not found. + */ +bool fw_config_probe(const struct fw_config_probe *match_list); + +#else /* CONFIG(FW_CONFIG) */ + +static inline bool fw_config_match(const char *field_name, const char *option_name) +{ + /* Always return true when probing with disabled fw_config. */ + return true; +} +static inline bool fw_config_probe(const struct fw_config_probe *match_list) +{ + /* Always return true when probing with disabled fw_config. */ + return true; +} + +#endif /* CONFIG(FW_CONFIG) */ + +#endif /* __FW_CONFIG__ */ diff --git a/src/lib/Kconfig b/src/lib/Kconfig index dd9974a..78a1eb8 100644 --- a/src/lib/Kconfig +++ b/src/lib/Kconfig @@ -75,3 +75,11 @@ If your platform really doesn't want to use an FMAP cache (e.g. due to space constraints), you can select this to disable warnings and save a bit more code. + +config FW_CONFIG + bool + default n + help + Enable support for probing devices with fw_config. This is a simple + bitmask broken into fields and options which can be provided by an + Embedded Controller or CBFS. diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc index c03aea1..126ad0d 100644 --- a/src/lib/Makefile.inc +++ b/src/lib/Makefile.inc @@ -67,6 +67,7 @@ $(eval rmodules_$(arch)-y += rmodule.ld))
romstage-y += fmap.c +romstage-$(CONFIG_FW_CONFIG) += fw_config.c romstage-y += delay.c romstage-y += cbfs.c romstage-$(CONFIG_COMPRESS_RAMSTAGE) += lzma.c lzmadecode.c @@ -106,6 +107,7 @@ ramstage-y += coreboot_table.c ramstage-y += bootmem.c ramstage-y += fmap.c +ramstage-$(CONFIG_FW_CONFIG) += fw_config.c ramstage-y += memchr.c ramstage-y += memcmp.c ramstage-y += malloc.c diff --git a/src/lib/fw_config.c b/src/lib/fw_config.c new file mode 100644 index 0000000..4364728 --- /dev/null +++ b/src/lib/fw_config.c @@ -0,0 +1,176 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* This file is part of the coreboot project. */ + +#include <bootstate.h> +#include <commonlib/helpers.h> +#include <console/console.h> +#include <fw_config.h> +#include <stdint.h> +#include <string.h> +#include <types.h> + +MAYBE_STATIC_BSS const struct fw_config_field *mainboard_table; +MAYBE_STATIC_BSS uint32_t mainboard_config; + +__weak size_t mainboard_get_fw_config(const struct fw_config_field **table, uint32_t *config) +{ + return 0; +} + +/** + * fw_config_prepare() - Check and set up mainboard table and config value. + * + * Return %false if mainboard does not provide table, otherwise %true. + */ +static bool fw_config_prepare(void) +{ + if (!mainboard_table) { + /* Get mainboard table and config value. */ + if (!mainboard_get_fw_config(&mainboard_table, &mainboard_config)) { + printk(BIOS_WARNING, + "%s: Mainboard did not provide firmware configuration table.\n", + __func__); + return false; + } + } + return true; +} + +/** + * fw_config_check_option() - Check this option against the mainboard config. + * @field: Field that this option belongs to. + * @option: Option that should be checked. + * + * Return %true if option matches, %false if it does not. + */ +static inline bool fw_config_check_option(const struct fw_config_field *field, + const struct fw_config_option *option) +{ + return option->value == ((mainboard_config >> field->shift) & field->mask); +} + +/** + * fw_config_find_option() - Find matching option in the provided field. + * @field: The field to search. + * @option_name: The name of the option to look for. + * + * Return pointer to option that is found, NULL if no match is found. + */ +static const struct fw_config_option * +fw_config_find_option(const struct fw_config_field *field, const char *option_name) +{ + size_t entry; + + for (entry = 0; entry < FW_CONFIG_OPTION_MAX; entry++) { + const struct fw_config_option *option = &field->option[entry]; + + /* Stop at the first undefined option in the list. */ + if (!option || !option->name) + break; + + /* Check this option name to see if it matches. */ + if (strncmp(option->name, option_name, strlen(option->name)) == 0) + return option; + } + return NULL; +} + +/** + * fw_config_find_field() - Find matching field in the mainboard table. + * @field_name: The name of the field to look for. + * + * Return pointer to field that is found, NULL if no match is found or no table is defined. + */ +static const struct fw_config_field *fw_config_find_field(const char *field_name) +{ + const struct fw_config_field *field; + + if (!fw_config_prepare()) + return NULL; + + /* Look for matching field name first. */ + for (field = mainboard_table; field && field->name; field++) { + if (strncmp(field->name, field_name, strlen(field->name)) == 0) + return field; + } + return NULL; +} + +bool fw_config_match(const char *field_name, const char *option_name) +{ + const struct fw_config_field *field; + const struct fw_config_option *option; + + /* Always return true when probing with missing fw_config. */ + if (!fw_config_prepare()) + return true; + + /* Find the field that matches probed field name. */ + field = fw_config_find_field(field_name); + if (!field) + return false; + + /* Find the option in this field that matches probed option name. */ + option = fw_config_find_option(field, option_name); + if (option && fw_config_check_option(field, option)) { + printk(BIOS_INFO, "%s: match found for %s:%s\n", __func__, + field_name, option_name); + return true; + } + + return false; +} + +bool fw_config_probe(const struct fw_config_probe *match_list) +{ + size_t entry; + + /* Always return true when probing with missing fw_config. */ + if (!fw_config_prepare()) + return true; + + /* Check each entry in the probe list provided by the caller. */ + for (entry = 0; entry < FW_CONFIG_PROBE_MAX; entry++) { + const struct fw_config_probe *match = &match_list[entry]; + + /* Stop at the first undefined match in the list. */ + if (!match || !match->option) + break; + + /* Check for a match with this option. */ + if (fw_config_match(match->field, match->option)) + return true; + } + + return false; +} + +/** + * fw_config_run_callbacks() - Find matching options and execute provided callbacks. + * Callbacks are executed before device enable functions are called. + */ +static void fw_config_run_callbacks(void *unused) +{ + const struct fw_config_field *field; + + if (!fw_config_prepare()) + return; + + /* Go through each field and find which option is selected. */ + for (field = mainboard_table; field && field->name; field++) { + size_t entry; + + for (entry = 0; entry < FW_CONFIG_OPTION_MAX; entry++) { + const struct fw_config_option *option = &field->option[entry]; + + /* Stop at the first undefined option in the list. */ + if (!option || !option->name) + break; + + /* Call provided callback if option is selected. */ + if (option->callback && fw_config_check_option(field, option)) + option->callback(option); + } + } +} +BOOT_STATE_INIT_ENTRY(BS_DEV_ENABLE, BS_ON_ENTRY, fw_config_run_callbacks, NULL);
Duncan Laurie has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 1:
I try to avoid introducing new top-level interfaces if possible, but to do probing it really needs integration in both drivers and mainboards and it seemed that src/lib was the best location.
I decided to follow the naming that was used when defining this interface in the EC and the factory process so it would be clear when working with coreboot what it affects. That said 'firmware configuration' is a pretty generic term and there may be other opinions on how to name it.
The first board to use this interface is volteer, but it will get added for other new boards soon.
Hello Furquan Shaikh, Patrick Georgi, Martin Roth, Caveh Jalali, Stefan Reinauer, Tim Wawrzynczak, Jett Rink, Aaron Durbin,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/41209
to look at the new patch set (#2).
Change subject: fw_config: Add firmware configuration interface ......................................................................
fw_config: Add firmware configuration interface
This change introduces a new top-level interface for interacting with a bitmask providing firmware configuration information.
This is motivated by Chromebook mainboards that need to support multiple different configurations at runtime with the same BIOS. In these devices the Embedded Controller provides a bitmask that can be broken down into different fields and each field can then be broken down into different options.
The firmware configuration interface is intended to be easily adapted by device drivers and mainboards and lead to less code duplication for new mainboards that make use of this feature by providing common functions and integration into devicetree.cb.
BUG=b:147462631 TEST=this provides a new interface that is tested in subsequent commits
Change-Id: I1e889c235a81545e2ec0e3a34dfa750ac828a330 Signed-off-by: Duncan Laurie dlaurie@google.com --- A Documentation/lib/fw_config.md M Documentation/lib/index.md A src/include/fw_config.h M src/lib/Kconfig M src/lib/Makefile.inc A src/lib/fw_config.c 6 files changed, 742 insertions(+), 1 deletion(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/09/41209/2
Julius Werner has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 2:
(1 comment)
https://review.coreboot.org/c/coreboot/+/41209/2/src/include/fw_config.h File src/include/fw_config.h:
https://review.coreboot.org/c/coreboot/+/41209/2/src/include/fw_config.h@9 PS2, Line 9: I'm a bit worried about the overall binary size added by these tables to (potentially) every stage. We already have a pretty unfortunate situation with devicetree.cb sometimes taking up near half of the available bootblock space on some boards, and this looks like it may end up causing similar pain. If this is supposed to be our new, be-all/end-all query interface for any kind of firmware-relevant SKU differences, it may very well be possible that you need to check one of those differences in the bootblock, another one in romstage, etc... you end up linking the whole table *and* all the option callbacks into each of those stages (which might not even compile for some of them). That's particularly unfortunate because the bootblock may not even care about all those fields -- it might only want to query one particular one, and it would be great if we could come up with some clever macros that reduce that check down to a single mask-and-compare without having to build in information about all the other fields.
I think you should be able to condense almost all of this down to compile-time constants so each stage can avoid linking in anything other than what it actually really uses. Consider if you made every supporting board provide a <board/fw_config_fields.h> header (similar to how including the <soc/...> headers works) which is then included here. In that header you would write stuff like:
FW_CONFIG_DEFINE_FIELD(DB, 3, 0) FW_CONFIG_DEFINE_FIELD(THERMAL, 7, 4) FW_CONFIG_DEFINE_FIELD(AUDIO, 10, 8, NONE, MAX98357_ALC5682I_I2S, MAX98373_ALC5682I_I2S, MAX98373_ALC5682_SNDW) ...etc...
FW_CONFIG_DEFINE_FIELD() would be a variadic macro (like the stuff in <base3.h> or <device/mmio.h>) that would auto-generate the following definitions for each field:
#define FW_CONFIG_FIELD_AUDIO_LOW 8 #define FW_CONFIG_FIELD_AUDIO_HIGH 10 #define FW_CONFIG_FIELD_AUDIO_MASK ((1 << (1 + 10 - 8)) - 1) #define FW_CONFIG_FIELD_AUDIO_OPTION_NONE 0 #define FW_CONFIG_FIELD_AUDIO_OPTION_MAX98357_ALC5682I_I2S 1 #define FW_CONFIG_FIELD_AUDIO_OPTION_MAX98373_ALC5682I_I2S 2 #define FW_CONFIG_FIELD_AUDIO_OPTION_MAX98373_ALC5682I_SNDW 3
FW_CONFIG_MATCH() could use token pasting so that FW_CONFIG_MATCH(AUDIO, MAX98357_ALC5682I_I2S) results in FW_CONFIG_FIELD_AUDIO_LOW, FW_CONFIG_FIELD_AUDIO_MASK and FW_CONFIG_FIELD_AUDIO_OPTION_MAX98357_ALC5682I_I2S being stored in the devicetree structure, so you can have basically the same nice, readable syntax in devicetree.cb.
If you want to check an option at runtime, fw_config_match() would have to turn into a macro (which would then clash with the devicetree one, so maybe call it FW_CONFIG_CHECK(field, option) or something). The space-constrained bootblock code would say
if (FW_CONFIG_CHECK(AUDIO, MAX98357_ALC5682I_I2S))
and that would be replaced to
if ((fw_config_get() >> FW_CONFIG_FIELD_AUDIO_LOW) & FW_CONFIG_FIELD_AUDIO_MASK == FW_CONFIG_FIELD_AUDIO_OPTION_MAX98357_ALC5682I_I2S)
so you still have pretty syntax, but it compiles down to ~3 instructions. (For checking values from the devicetree there could be a similar macro to make that easier. For convenient handling it might be nice to package the offset/mask pair or the offset/mask/option tuple into typedeffed structures so it is easier to pass them around.)
For the run callbacks thing, well... wouldn't it be simpler (and probably smaller in binary) to just have a bunch of switch statements? Your volteer/fw_config.c could just have a
void mainboard_handle_fw_config(void) { switch (FW_CONFIG_FIELD_VALUE(AUDIO)) { case FW_CONFIG_FIELD_AUDIO_OPTION_NONE: gpio_pads_stuff(); case FW_CONFIG_FIELD_AUDIO_OPTION_MAX98357_ALC5682I_I2S: other_gpio_pads_stuff(); ...etc... }
switch (...next field that needs special handling...) { ... }
Then either make a boot state hook right there or make a central one that calls mainboard_handle_fw_config() as a well-known function name the mainboard must provide.
If you really want a table approach, you could still do it with that approach as something like
struct fw_config_callbacks[] = { FW_CONFIG_CALLBACK(AUDIO, NONE, audio_db_none_cb), FW_CONFIG_CALLBACK(AUDIO, MAX98357_ALC5682I_I2S, audio_db_i2s_cb), ...etc... }
with FW_CONFIG_CALLBACK unpacking it into low offset, mask, match value and callback pointer. That should still be quite a bit smaller than reserving space for 32 options per field, and it would only have to be linked into ramstage where it is used.
Duncan Laurie has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 2:
(1 comment)
https://review.coreboot.org/c/coreboot/+/41209/2/src/include/fw_config.h File src/include/fw_config.h:
https://review.coreboot.org/c/coreboot/+/41209/2/src/include/fw_config.h@9 PS2, Line 9: I did initially pursue a macro based implementation. It had a number of positives like you've noted but also a number of negatives:
- mainboards themselves can't include code to static.c currently (had to hack sconfig and it was not clean; furquan says I should be able to add a chip.h in mainboard but I had issues when I tried that) this could be fixed of course. - I want a string for each field and option for console output anyway - lots of macro expansion which usually generates complaints in reviews
The string approach was very flexible and it didn't seem like a significant size hit (32 options per field is a bit extreme and could be lowered) because the real target is ramstage, but I do agree it is more than we might want in bootblock on some systems.
At the end of the day I'd like for the table itself to be generated from our own database of these fields and options, so maybe it doesn't need to be in code form directly.
I did try to build off the cmos.layout format/parser in order to take advantage of having this in a separate file. But that is tightly bound to the nvramtool and not very flexible.
I also considered extending the sconfig/devicetree to support defining the table directly in devicetree and have sconfig generate the underlying macros. It should be possible to add more tokens to devicetree parsing and do something like:
fw_config mainboard/google/volteer field AUDIO 8 10 option NONE 0 end option MAX98357_ALC5682I_I2S 1 end option MAX98373_ALC5682I_I2S 2 end option MAX98373_ALC5682_SNDW 3 end end end (or similar)
And then sconfig would generate all the #defines that go together with the accessor macros that you noted above.
I'll do some more investigation here tomorrow...
Julius Werner has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 2:
(1 comment)
https://review.coreboot.org/c/coreboot/+/41209/2/src/include/fw_config.h File src/include/fw_config.h:
https://review.coreboot.org/c/coreboot/+/41209/2/src/include/fw_config.h@9 PS2, Line 9:
mainboards themselves can't include code to static.c currently
I'd be curious why that is, what was the exact problem? I thought static.c is treated like any other stage source file once it is generated.
I want a string for each field and option for console output anyway
It's possible to have the generation macro spit out a #define FW_CONFIG_FIELD_AUDIO_NAME "AUDIO" as well, of course (and same for options).
lots of macro expansion which usually generates complaints in reviews
Well... it's a matter of opinion I guess, but in my mind macros are fine as long as it's an isolated API that only really needs to be written and carefully reviewed once and then rarely touched in the internals again, the external interface is clearly documented and easy to understand (even if not everyone understands the internals), and there's a sufficient benefit coming from it that you can't really get with other methods. We have other big complicated macro APIs like that in coreboot already... for example memlayout, or the SET32_BITFIELDS() we added to <device/mmio.h> recently (which I hope takes off because while the internals of how it works are confusing, it is very simple to understand how to use it and it makes code working on hardware registers a lot safer, more readable and easier to follow).
I for one would definitely complain a lot more about leaving binary size on the table ;) (for something that is supposed to be so universal and should work and be used across all platforms with all their different needs and constraints). Even if you apply very careful struct packing to your solution to make it as tight as possible, I think the fundamental issue remains that if one stage only needs to check a single field it shouldn't have to link in info about everything else.
Auto-generating the table from somewhere else also sounds fine but I think that's a pretty orthogonal issue to how it is represented in C. You could auto-generate macros or you could auto-generate structs. But at least if you don't want to auto-generate it I think we can definitely find ways to make a header file with macro definitions just as compact and readable as a struct initializer.
Duncan Laurie has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 2:
(1 comment)
https://review.coreboot.org/c/coreboot/+/41209/2/src/include/fw_config.h File src/include/fw_config.h:
https://review.coreboot.org/c/coreboot/+/41209/2/src/include/fw_config.h@9 PS2, Line 9:
mainboards themselves can't include code to static.c currently
I'd be curious why that is, what was the exact problem? I thought static.c is treated like any other stage source file once it is generated.
It is because static.c is entirely generated and the only #includes come from other chips. (except mainboard because it is special) So if you try to provide something from the mainboard itself it has to be included indirectly from another chip.
Just an annoyance, I had a hack to sconfig that allowed an 'include ...' token but that was messy as well, mostly because sconfig is just messy by default.
It's possible to have the generation macro spit out a #define FW_CONFIG_FIELD_AUDIO_NAME "AUDIO" as well, of course (and same for options).
Sure but that takes up space just like a string in a table.
Auto-generating the table from somewhere else also sounds fine but I think that's a pretty orthogonal issue to how it is represented in C. You could auto-generate macros or you could auto-generate structs. But at least if you don't want to auto-generate it I think we can definitely find ways to make a header file with macro definitions just as compact and readable as a struct initializer.
It solves some of the problems that I had with macros, so it isn't necessarily orthogonal if it results in the solution that people prefer.
Duncan Laurie has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 2:
(1 comment)
https://review.coreboot.org/c/coreboot/+/41209/2/src/include/fw_config.h File src/include/fw_config.h:
https://review.coreboot.org/c/coreboot/+/41209/2/src/include/fw_config.h@9 PS2, Line 9:
mainboards themselves can't include code to static.c currently
I'd be curious why that is, what was the exact problem? I thought static.c is treated like any other stage source file once it is generated.
It is because static.c is entirely generated and the only #includes come from other chips. (except mainboard because it is special) So if you try to provide something from the mainboard itself it has to be included indirectly from another chip.
I did manage to get this to work with a chip.h in the mainboard directory with one small change to sconfig. Not needed now but this wasn't as bad as it seemed.
The devicetree approach is actually looking good after some more work with sconfig today, I appreciate the pushback and forcing me to re-evaluate because I like how it integrates now.
This also makes it easy for variants to add new fields and new options to existing fields in overridetree.cb.
It will take a few days to get everything else done and update the docs.
Duncan Laurie has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 2:
(1 comment)
This change is ready for review.
https://review.coreboot.org/c/coreboot/+/41209/2/src/include/fw_config.h File src/include/fw_config.h:
https://review.coreboot.org/c/coreboot/+/41209/2/src/include/fw_config.h@9 PS2, Line 9:
So if you try to provide something from the mainboard itself it has to be included indirectly from another chip.
Right, but you have to include <fw_config.h> anyway (for the macros), right? That's what I'm saying, just add #include <board/fw_config.h> here (to <fw_config.h>), add an -I $(src)/mainboard/$(MAINBOARDDIR)/include to the toplevel Makefile.inc (or to the mainboard-specific Makefile.inc), and put your board-specific file in src/mainboard/google/volteer/include/board/fw_config.h. Then if any devicetree driver uses fw_config it will #include <fw_config.h> from its <chip.h>, that will chain include <board/fw_config.h> and that should provide all the definitions to static.c. (You can also have that mainboard-specific header pull in a variant-specific header if you want, of course.)
That is what I said, you have to chain include it which is pretty ugly. Not that it is impossible.
Yes, but again only for the stuff that stage is actually using (and probably still considerably less, since many of your strings are smaller than the size of the (potentially) 64-bit pointer pointing to them).
Not if you want to print any debug, you don't know what options are selected so you don't know what strings you need.
Duncan Laurie has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 2:
(1 comment)
This change is ready for review.
https://review.coreboot.org/c/coreboot/+/41209/2/src/include/fw_config.h File src/include/fw_config.h:
https://review.coreboot.org/c/coreboot/+/41209/2/src/include/fw_config.h@9 PS2, Line 9:
That is what I said, you have to chain include it which is pretty ugly. Not that it is impossible.
I don't know, isn't that normal practice whenever you have a generic API that needs to pull in platform-specific definitions? <device/mmio.h> pulls in different <arch/io.h> to get an architecture-specific definition for read32(). <gpio.h> pulls in different <soc/gpio.h> to get a SoC-specific definition for gpio_t. Not sure how this would be any worse.
I would rather not reach back into the mainboard. ACPI has a bad habit of it and I've been trying to remove those.
I only found one case of non-mainboard code pulling a header directly from a mainboard and it was an older AMD platform. maybe I'm missing more instances.
Duncan Laurie has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 3:
I need to actually update the doc, for now just removed the irrelevant parts. The real work moved to sconfig in the next commit.
I am using a compound literal for the function argument as it sure does make it easy for the caller.
Duncan Laurie has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 3:
(8 comments)
This change is ready for review.
https://review.coreboot.org/c/coreboot/+/41209/3/src/include/fw_config.h File src/include/fw_config.h:
https://review.coreboot.org/c/coreboot/+/41209/3/src/include/fw_config.h@19 PS3, Line 19: #define FW_CONFIG(__field, __option) &(const struct fw_config) { \
Macros with complex values should be enclosed in parentheses
Ack
https://review.coreboot.org/c/coreboot/+/41209/3/src/lib/Kconfig File src/lib/Kconfig:
https://review.coreboot.org/c/coreboot/+/41209/3/src/lib/Kconfig@86 PS3, Line 86: bool
I assume we want these to show up in menuconfig? Then they need prompt text.
Initially I was thinking just selected at the mainboard level since it defaulted to trying cbfs first, but I'll expose these to menuconfig since I'm adding separate enables.
https://review.coreboot.org/c/coreboot/+/41209/3/src/lib/Kconfig@94 PS3, Line 94: default "fw_config"
Should depends on FW_CONFIG (to hide in menuconfig when disabled).
Done
https://review.coreboot.org/c/coreboot/+/41209/3/src/lib/Makefile.inc File src/lib/Makefile.inc:
https://review.coreboot.org/c/coreboot/+/41209/3/src/lib/Makefile.inc@69 PS3, Line 69: romstage-$(CONFIG_FW_CONFIG) += fw_config.c
nit: why not all stages right away?
I'll add to bootblock and verstage.
https://review.coreboot.org/c/coreboot/+/41209/3/src/lib/fw_config.c File src/lib/fw_config.c:
https://review.coreboot.org/c/coreboot/+/41209/3/src/lib/fw_config.c@22 PS3, Line 22: if (cbfs_boot_locate(&file, CONFIG_FW_CONFIG_CBFS_FILE, &matchraw))
I think you can just use cbfs_boot_load_file() for all of this.
ah yes that is the shortcut I was looking for, all the examples I was looking at were doing it the long way.
https://review.coreboot.org/c/coreboot/+/41209/3/src/lib/fw_config.c@44 PS3, Line 44: if (fw_config_value)
Are these really guaranteed to always be non-zero? What if you just pick the first option for everyt […]
I can add a separate "initialized" flag to prevent reading every time if the value is zero.
https://review.coreboot.org/c/coreboot/+/41209/3/src/lib/fw_config.c@48 PS3, Line 48: if (fw_config_prepare_cbfs())
This would be a problem if we wanted to use it in early bootblock code (at least on Arm). […]
I have been going back and forth on this, it doesn't necessarily make sense to probe CBFS by default anyway if you don't need to.
https://review.coreboot.org/c/coreboot/+/41209/3/src/lib/fw_config.c@52 PS3, Line 52: if (CONFIG(EC_GOOGLE_CHROMEEC)) {
Shouldn't this be a separate Kconfig? Not all devices using CHROMEEC use a CBI, and not all of those […]
In theory they wouldn't enable CONFIG_FW_CONFIG without needing it, but it does make sense for both of these to be behind a kconfig.
Patrick Rudolph has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 3: Code-Review+1
Hello build bot (Jenkins), Furquan Shaikh, Patrick Georgi, Martin Roth, Caveh Jalali, Stefan Reinauer, Tim Wawrzynczak, Jett Rink, Patrick Rudolph, Aaron Durbin,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/41209
to look at the new patch set (#4).
Change subject: fw_config: Add firmware configuration interface ......................................................................
fw_config: Add firmware configuration interface
This change introduces a new top-level interface for interacting with a bitmask providing firmware configuration information.
This is motivated by Chromebook mainboards that need to support multiple different configurations at runtime with the same BIOS. In these devices the Embedded Controller provides a bitmask that can be broken down into different fields and each field can then be broken down into different options.
The firmware configuration value could also be stored in CBFS and this interface will look in CBFS first to allow the Embedded Controller value to be overridden.
The firmware configuration interface is intended to easily integrate into devicetree.cb and lead to less code duplication for new mainboards that make use of this feature.
BUG=b:147462631 TEST=this provides a new interface that is tested in subsequent commits
Change-Id: I1e889c235a81545e2ec0e3a34dfa750ac828a330 Signed-off-by: Duncan Laurie dlaurie@google.com --- A Documentation/lib/fw_config.md M Documentation/lib/index.md M src/Kconfig M src/include/device/device.h A src/include/fw_config.h M src/lib/Makefile.inc A src/lib/fw_config.c 7 files changed, 532 insertions(+), 1 deletion(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/09/41209/4
Duncan Laurie has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 4:
(2 comments)
https://review.coreboot.org/c/coreboot/+/41209/4/src/include/fw_config.h File src/include/fw_config.h:
https://review.coreboot.org/c/coreboot/+/41209/4/src/include/fw_config.h@9 PS4, Line 9: #include <static.h> there is an odd build dependency issue where sometimes the sconfig step doesn't happen at the start and static.h doesn't exist. I don't see it upstream but it happens every time when building with portage.
https://review.coreboot.org/c/coreboot/+/41209/3/src/lib/Kconfig File src/lib/Kconfig:
https://review.coreboot.org/c/coreboot/+/41209/3/src/lib/Kconfig@86 PS3, Line 86: bool
Initially I was thinking just selected at the mainboard level since it defaulted to trying cbfs firs […]
had to move to src/Kconfig because src/lib/Kconfig can't have prompts..
HAOUAS Elyes has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 4:
(7 comments)
https://review.coreboot.org/c/coreboot/+/41209/4/src/include/fw_config.h File src/include/fw_config.h:
https://review.coreboot.org/c/coreboot/+/41209/4/src/include/fw_config.h@2 PS4, Line 2: /* This file is part of the coreboot project. * please remove
https://review.coreboot.org/c/coreboot/+/41209/4/src/include/fw_config.h@8 PS4, Line 8: #include <types.h> this is not used.
https://review.coreboot.org/c/coreboot/+/41209/4/src/include/fw_config.h@9 PS4, Line 9: #include <static.h>
there is an odd build dependency issue where sometimes the sconfig step doesn't happen at the start […]
maybe <device/device.h> is missing in one of you files ? (or <smbios.h>)
in any case, "#include <static.h>" is not used here :)
https://review.coreboot.org/c/coreboot/+/41209/4/src/lib/fw_config.c File src/lib/fw_config.c:
https://review.coreboot.org/c/coreboot/+/41209/4/src/lib/fw_config.c@2 PS4, Line 2: /* This file is part of the coreboot project. */ please remove
https://review.coreboot.org/c/coreboot/+/41209/4/src/lib/fw_config.c@6 PS4, Line 6: #include <cbfs.h> not used?
(please check the other includes)
https://review.coreboot.org/c/coreboot/+/41209/4/src/lib/fw_config.c@11 PS4, Line 11: #include <string.h> not used
https://review.coreboot.org/c/coreboot/+/41209/4/src/lib/fw_config.c@12 PS4, Line 12: #include <types.h> not used?
Duncan Laurie has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 4:
(7 comments)
https://review.coreboot.org/c/coreboot/+/41209/4/src/include/fw_config.h File src/include/fw_config.h:
https://review.coreboot.org/c/coreboot/+/41209/4/src/include/fw_config.h@2 PS4, Line 2: /* This file is part of the coreboot project. *
please remove
Done
https://review.coreboot.org/c/coreboot/+/41209/4/src/include/fw_config.h@8 PS4, Line 8: #include <types.h>
this is not used.
swapped with stdbool.h
https://review.coreboot.org/c/coreboot/+/41209/4/src/include/fw_config.h@9 PS4, Line 9: #include <static.h>
maybe <device/device.h> is missing in one of you files ? […]
this file is pretty much useless without static.h so I was trying to avoid having to include both every time, but I can move it to all the mainboards.
the dependency issue is at build time though, I need to figure out how to get make to run sconfig first every time.
https://review.coreboot.org/c/coreboot/+/41209/4/src/lib/fw_config.c File src/lib/fw_config.c:
https://review.coreboot.org/c/coreboot/+/41209/4/src/lib/fw_config.c@2 PS4, Line 2: /* This file is part of the coreboot project. */
please remove
Done
https://review.coreboot.org/c/coreboot/+/41209/4/src/lib/fw_config.c@6 PS4, Line 6: #include <cbfs.h>
not used? […]
needed for cbfs_boot_load_file() but some of the others were now stale after this was rewritten so they have been culled.
https://review.coreboot.org/c/coreboot/+/41209/4/src/lib/fw_config.c@11 PS4, Line 11: #include <string.h>
not used
Done
https://review.coreboot.org/c/coreboot/+/41209/4/src/lib/fw_config.c@12 PS4, Line 12: #include <types.h>
not used?
this is what was bringing in bool, but I guess I could include stdbool.h directly.
Duncan Laurie has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 4:
(2 comments)
https://review.coreboot.org/c/coreboot/+/41209/2/src/include/fw_config.h File src/include/fw_config.h:
https://review.coreboot.org/c/coreboot/+/41209/2/src/include/fw_config.h@9 PS2, Line 9:
I'm a bit worried about the overall binary size added by these tables to (potentially) every stage. […]
Ack
https://review.coreboot.org/c/coreboot/+/41209/2/src/include/fw_config.h@9 PS2, Line 9:
That is what I said, you have to chain include it which is pretty ugly. […]
Ack
Hello build bot (Jenkins), Furquan Shaikh, Patrick Georgi, Martin Roth, Caveh Jalali, Stefan Reinauer, Tim Wawrzynczak, Jett Rink, Patrick Rudolph, Aaron Durbin,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/41209
to look at the new patch set (#5).
Change subject: fw_config: Add firmware configuration interface ......................................................................
fw_config: Add firmware configuration interface
This change introduces a new top-level interface for interacting with a bitmask providing firmware configuration information.
This is motivated by Chromebook mainboards that need to support multiple different configurations at runtime with the same BIOS. In these devices the Embedded Controller provides a bitmask that can be broken down into different fields and each field can then be broken down into different options.
The firmware configuration value could also be stored in CBFS and this interface will look in CBFS first to allow the Embedded Controller value to be overridden.
The firmware configuration interface is intended to easily integrate into devicetree.cb and lead to less code duplication for new mainboards that make use of this feature.
BUG=b:147462631 TEST=this provides a new interface that is tested in subsequent commits
Change-Id: I1e889c235a81545e2ec0e3a34dfa750ac828a330 Signed-off-by: Duncan Laurie dlaurie@google.com --- A Documentation/lib/fw_config.md M Documentation/lib/index.md M src/Kconfig M src/include/device/device.h A src/include/fw_config.h M src/lib/Makefile.inc A src/lib/fw_config.c 7 files changed, 526 insertions(+), 1 deletion(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/09/41209/5
Jett Rink has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 5:
(3 comments)
Overall LGTM
https://review.coreboot.org/c/coreboot/+/41209/5/Documentation/lib/fw_config... File Documentation/lib/fw_config.md:
https://review.coreboot.org/c/coreboot/+/41209/5/Documentation/lib/fw_config... PS5, Line 10: The initial implementation is designed to take advantage of a bitmask returned by the Embedded : Controller on Google Chrome OS devices which allows the manufacturer to use the same firmware : image across multiple devices by selecting various options at runtime. Link to https://chromium.googlesource.com/chromiumos/docs/+/master/design_docs/firmw... ?
https://review.coreboot.org/c/coreboot/+/41209/5/src/include/fw_config.h File src/include/fw_config.h:
https://review.coreboot.org/c/coreboot/+/41209/5/src/include/fw_config.h@17 PS5, Line 17: const char *field_name; : const char *option_name; if we don't change matching logic, then we should document that these fields are required to be non-null for a match to take place regardless of mask and value
(I do think we shouldn't make that a requirement though)
https://review.coreboot.org/c/coreboot/+/41209/5/src/lib/fw_config.c File src/lib/fw_config.c:
https://review.coreboot.org/c/coreboot/+/41209/5/src/lib/fw_config.c@67 PS5, Line 67: match->field_name && match->option_name If the debug string aren't present, shouldn't we still match (but not print out as much in the probe_one function)?
Duncan Laurie has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 5:
(1 comment)
https://review.coreboot.org/c/coreboot/+/41209/5/src/lib/fw_config.c File src/lib/fw_config.c:
https://review.coreboot.org/c/coreboot/+/41209/5/src/lib/fw_config.c@67 PS5, Line 67: match->field_name && match->option_name
If the debug string aren't present, shouldn't we still match (but not print out as much in the probe […]
I could key off "mask=0" and make that an invalid probe instead of needing the pointers to be a list terminator.
Jett Rink has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 5:
(1 comment)
https://review.coreboot.org/c/coreboot/+/41209/5/src/lib/fw_config.c File src/lib/fw_config.c:
https://review.coreboot.org/c/coreboot/+/41209/5/src/lib/fw_config.c@67 PS5, Line 67: match->field_name && match->option_name
I could key off "mask=0" and make that an invalid probe instead of needing the pointers to be a list […]
Ah, I like the mask==0 better; that makes more sense to me.
Duncan Laurie has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 5:
(3 comments)
https://review.coreboot.org/c/coreboot/+/41209/5/Documentation/lib/fw_config... File Documentation/lib/fw_config.md:
https://review.coreboot.org/c/coreboot/+/41209/5/Documentation/lib/fw_config... PS5, Line 10: The initial implementation is designed to take advantage of a bitmask returned by the Embedded : Controller on Google Chrome OS devices which allows the manufacturer to use the same firmware : image across multiple devices by selecting various options at runtime.
Link to https://chromium.googlesource.com/chromiumos/docs/+/master/design_docs/firmw... […]
Done
https://review.coreboot.org/c/coreboot/+/41209/5/src/include/fw_config.h File src/include/fw_config.h:
https://review.coreboot.org/c/coreboot/+/41209/5/src/include/fw_config.h@17 PS5, Line 17: const char *field_name; : const char *option_name;
if we don't change matching logic, then we should document that these fields are required to be non- […]
Ack
https://review.coreboot.org/c/coreboot/+/41209/5/src/lib/fw_config.c File src/lib/fw_config.c:
https://review.coreboot.org/c/coreboot/+/41209/5/src/lib/fw_config.c@67 PS5, Line 67: match->field_name && match->option_name
Ah, I like the mask==0 better; that makes more sense to me.
Ack
Hello build bot (Jenkins), Furquan Shaikh, Patrick Georgi, Martin Roth, Caveh Jalali, Stefan Reinauer, Tim Wawrzynczak, Jett Rink, Patrick Rudolph, Aaron Durbin,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/41209
to look at the new patch set (#6).
Change subject: fw_config: Add firmware configuration interface ......................................................................
fw_config: Add firmware configuration interface
This change introduces a new top-level interface for interacting with a bitmask providing firmware configuration information.
This is motivated by Chromebook mainboards that need to support multiple different configurations at runtime with the same BIOS. In these devices the Embedded Controller provides a bitmask that can be broken down into different fields and each field can then be broken down into different options.
The firmware configuration value could also be stored in CBFS and this interface will look in CBFS first to allow the Embedded Controller value to be overridden.
The firmware configuration interface is intended to easily integrate into devicetree.cb and lead to less code duplication for new mainboards that make use of this feature.
BUG=b:147462631 TEST=this provides a new interface that is tested in subsequent commits
Change-Id: I1e889c235a81545e2ec0e3a34dfa750ac828a330 Signed-off-by: Duncan Laurie dlaurie@google.com --- A Documentation/lib/fw_config.md M Documentation/lib/index.md M src/Kconfig M src/include/device/device.h A src/include/fw_config.h M src/lib/Makefile.inc A src/lib/fw_config.c 7 files changed, 529 insertions(+), 1 deletion(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/09/41209/6
Jett Rink has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 6: Code-Review+1
LGTM (don't have +2 rights still)
Julius Werner has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 7:
(5 comments)
https://review.coreboot.org/c/coreboot/+/41209/7/src/include/fw_config.h File src/include/fw_config.h:
https://review.coreboot.org/c/coreboot/+/41209/7/src/include/fw_config.h@43 PS7, Line 43: * @match_list: List of field and options to check. Should clarify that this needs to be terminated by an empty entry. In general maybe avoid the term 'list' (which probably makes most people think of linked lists) and call them zero-terminated arrays or something.
I'm a bit worried that people may call fw_config_probe(FW_CONFIG(...)) and not notice their error, and depending on stack layout it may even sometimes work and not be immediately obvious. Is there something we can do with the naming to make that less likely? Maybe change fw_config_probe_one() to something else like fw_config_check() so that it's clearer which one is for manual checking and which one is for devicetree probing? Maybe even rename the other one to fw_config_devicetree_probe() and make it take the whole struct device instead? Or maybe change FW_CONFIG() to FW_CONFIG_ONE() and add a variadic FW_CONFIG(field, option, option...) to build match lists when needed? Not sure what the best solution is.
https://review.coreboot.org/c/coreboot/+/41209/4/src/include/fw_config.h File src/include/fw_config.h:
https://review.coreboot.org/c/coreboot/+/41209/4/src/include/fw_config.h@9 PS4, Line 9: #include <static.h>
this file is pretty much useless without static. […]
FWIW I'd prefer to keep the include in here. It makes sense logically that when you include <fw_config.h> you have access to all the FW_CONFIG_... definitions, and the fact that they're actually in <static.h> is an implementation detail that will confuse a lot of people.
I think the only way to solve your build issue is to make the build of every single .c file depend on sconfig (which is a bit unfortunate because it prevents some build parallelization, but there's no way for make to add a dependency to only those files which have a certain #include). You can do that by adding $(DEVICETREE_STATIC_C) to <stage>-c-deps for all stages, like it's already done for $(OPTION_TABLE_H). (Technically you want $(DEVICETREE_STATIC_H), not $(DEVICETREE_STATIC_C), but the rule to create both is for $(DEVICETREE_STATIC_C). Also, it might be nice to change the part that makes use of $(class)-$(type)-deps in the toplevel Makefile to allow the use of generic-$(type)-deps, like we already have for generic-$(type)-ccopts, so we don't always have to add these things to every stage explicitly.)
https://review.coreboot.org/c/coreboot/+/41209/7/src/lib/fw_config.c File src/lib/fw_config.c:
https://review.coreboot.org/c/coreboot/+/41209/7/src/lib/fw_config.c@11 PS7, Line 11: MAYBE_STATIC_BSS bool fw_config_value_initialized; Actually, this doesn't work. The point of MAYBE_STATIC_BSS is to either add the 'static' keyword or not, so the variable is either put in the data segment (if possible) or on the stack (if not). But that only works for locals, not globals. Could probably rewrite this so fw_config_prepare() becomes uint32_t fw_config_get() or something and both of these are locals in there.
Also, all variables declared like that should be explicitly initialized to 0/NULL/false (otherwise, if the 'static' keyword wasn't there, the initial value would be undefined.)
(Also, I'm not sure about all these x86 details but I think these might be deprecated anyway? See CB:37055. Maybe they just forgot to clean this up...)
https://review.coreboot.org/c/coreboot/+/41209/7/src/lib/fw_config.c@27 PS7, Line 27: CONFIG_FW_CONFIG_SOURCE_CBFS_FILE Should this be prefixed with CONFIG_CBFS_PREFIX? (I'm not sure if the whole normal/fallback thing still works at all, but if it does it would probably be appropriate to use it for this as well.)
Also, is there really a point in making this name user-selectable? We don't allow people to change the name "romstage" in Kconfig either. Maybe just using fw_config as a well-known name is good enough?
https://review.coreboot.org/c/coreboot/+/41209/7/src/lib/fw_config.c@33 PS7, Line 33: } Your documentation says CBFS can override CBI (at least that's how I understood it), but the way this is written CBI actually overrides CBFS right now. Would either need to return here on success or swap the order or something.
Duncan Laurie has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 7:
(4 comments)
https://review.coreboot.org/c/coreboot/+/41209/7/src/include/fw_config.h File src/include/fw_config.h:
https://review.coreboot.org/c/coreboot/+/41209/7/src/include/fw_config.h@43 PS7, Line 43: * @match_list: List of field and options to check.
Should clarify that this needs to be terminated by an empty entry. […]
Sure I will make this more clear, I think the devicetree probing one could pass a struct device instead pretty easily.
https://review.coreboot.org/c/coreboot/+/41209/7/src/lib/fw_config.c File src/lib/fw_config.c:
https://review.coreboot.org/c/coreboot/+/41209/7/src/lib/fw_config.c@11 PS7, Line 11: MAYBE_STATIC_BSS bool fw_config_value_initialized;
Actually, this doesn't work. […]
Hm yes this was supposed to be in a function and it isn't really a migrated global but I had not seen Kyosti's patch to remove MAYBE_STATIC_BSS entirely.
https://review.coreboot.org/c/coreboot/+/41209/7/src/lib/fw_config.c@27 PS7, Line 27: CONFIG_FW_CONFIG_SOURCE_CBFS_FILE
Should this be prefixed with CONFIG_CBFS_PREFIX? (I'm not sure if the whole normal/fallback thing st […]
I guess with CONFIG_CBFS_PREFIX it would be more than flexible enough without needing to also specify the name.
https://review.coreboot.org/c/coreboot/+/41209/7/src/lib/fw_config.c@33 PS7, Line 33: }
Your documentation says CBFS can override CBI (at least that's how I understood it), but the way thi […]
that is what I get for reworking things too many times, this function used to return early here.
Duncan Laurie has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 7:
(1 comment)
https://review.coreboot.org/c/coreboot/+/41209/4/src/include/fw_config.h File src/include/fw_config.h:
https://review.coreboot.org/c/coreboot/+/41209/4/src/include/fw_config.h@9 PS4, Line 9: #include <static.h>
FWIW I'd prefer to keep the include in here. […]
Ya I thought I could get away with just ramstage-c-deps but it does seem like I need to add to all of them. I'll see how much make I can touch without breaking things.
Duncan Laurie has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 7:
(1 comment)
https://review.coreboot.org/c/coreboot/+/41209/4/src/include/fw_config.h File src/include/fw_config.h:
https://review.coreboot.org/c/coreboot/+/41209/4/src/include/fw_config.h@9 PS4, Line 9: #include <static.h>
Ya I thought I could get away with just ramstage-c-deps but it does seem like I need to add to all o […]
er that is I thought I could use ramstage-c-deps when I was only building in ramstage when testing. now fw_config is in more stages anyway so obviously not enough.
Hello build bot (Jenkins), Furquan Shaikh, Patrick Georgi, Martin Roth, Caveh Jalali, Stefan Reinauer, Tim Wawrzynczak, Jett Rink, Patrick Rudolph, Aaron Durbin,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/41209
to look at the new patch set (#8).
Change subject: fw_config: Add firmware configuration interface ......................................................................
fw_config: Add firmware configuration interface
This change introduces a new top-level interface for interacting with a bitmask providing firmware configuration information.
This is motivated by Chromebook mainboards that need to support multiple different configurations at runtime with the same BIOS. In these devices the Embedded Controller provides a bitmask that can be broken down into different fields and each field can then be broken down into different options.
The firmware configuration value could also be stored in CBFS and this interface will look in CBFS first to allow the Embedded Controller value to be overridden.
The firmware configuration interface is intended to easily integrate into devicetree.cb and lead to less code duplication for new mainboards that make use of this feature.
BUG=b:147462631 TEST=this provides a new interface that is tested in subsequent commits
Change-Id: I1e889c235a81545e2ec0e3a34dfa750ac828a330 Signed-off-by: Duncan Laurie dlaurie@google.com --- A Documentation/lib/fw_config.md M Documentation/lib/index.md M src/Kconfig M src/include/device/device.h A src/include/fw_config.h M src/lib/Makefile.inc A src/lib/fw_config.c 7 files changed, 520 insertions(+), 1 deletion(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/09/41209/8
Duncan Laurie has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 8:
(2 comments)
https://review.coreboot.org/c/coreboot/+/41209/4/src/include/fw_config.h File src/include/fw_config.h:
https://review.coreboot.org/c/coreboot/+/41209/4/src/include/fw_config.h@9 PS4, Line 9: #include <static.h>
er that is I thought I could use ramstage-c-deps when I was only building in ramstage when testing. […]
I went with the cheap fix because make is only making my head hurt.
https://review.coreboot.org/c/coreboot/+/41209/8/src/lib/fw_config.c File src/lib/fw_config.c:
https://review.coreboot.org/c/coreboot/+/41209/8/src/lib/fw_config.c@18 PS8, Line 18: static uint32_t fw_config_value; : static bool fw_config_value_initialized; I added some debug in the different stages to make sure this was working as expected. it gets re-read once every stage.
Julius Werner has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 8: Code-Review+2
Kyösti Mälkki has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 9:
(1 comment)
I did not really review the work here, I just wanted to leave a general (possibly unrelated) comment that linking static.c into SMM is IMHO a bad idea since the copy of devicetree there does not reflect any modifications ramstage could have made.
https://review.coreboot.org/c/coreboot/+/41209/7/src/lib/fw_config.c File src/lib/fw_config.c:
https://review.coreboot.org/c/coreboot/+/41209/7/src/lib/fw_config.c@11 PS7, Line 11: MAYBE_STATIC_BSS bool fw_config_value_initialized;
Hm yes this was supposed to be in a function and it isn't really a migrated global but I had not see […]
Leave comments in CB:40535 please.
Duncan Laurie has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 9:
Patch Set 9:
(1 comment)
I did not really review the work here, I just wanted to leave a general (possibly unrelated) comment that linking static.c into SMM is IMHO a bad idea since the copy of devicetree there does not reflect any modifications ramstage could have made.
Only static.h might end up included indirectly in smm and it just contains some #define. I did add a build dependency on smm code, but just to ensure that an indirect include of static.h wouldn't fail to compile.
Kyösti Mälkki has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 9:
Patch Set 9:
Patch Set 9:
(1 comment)
I did not really review the work here, I just wanted to leave a general (possibly unrelated) comment that linking static.c into SMM is IMHO a bad idea since the copy of devicetree there does not reflect any modifications ramstage could have made.
Only static.h might end up included indirectly in smm and it just contains some #define. I did add a build dependency on smm code, but just to ensure that an indirect include of static.h wouldn't fail to compile.
It is not touched with your work, but currently we do have this: Makefile.inc:smm-y+=$(DEVICETREE_STATIC_C)
With mutable configuration bits in ramstage, SMM will not have correct runtime information.
Caveh Jalali has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 13:
(3 comments)
https://review.coreboot.org/c/coreboot/+/41209/13/src/include/fw_config.h File src/include/fw_config.h:
https://review.coreboot.org/c/coreboot/+/41209/13/src/include/fw_config.h@41 PS13, Line 41: fw_config_probe does this function need to be exposed?
https://review.coreboot.org/c/coreboot/+/41209/13/src/lib/fw_config.c File src/lib/fw_config.c:
https://review.coreboot.org/c/coreboot/+/41209/13/src/lib/fw_config.c@32 PS13, Line 32: /* Look in CBFS to allow override of value. */ should we still query the EC if we have an override?
https://review.coreboot.org/c/coreboot/+/41209/13/src/lib/fw_config.c@70 PS13, Line 70: match this is an invariant... or better be :)
Duncan Laurie has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 13:
(3 comments)
https://review.coreboot.org/c/coreboot/+/41209/13/src/include/fw_config.h File src/include/fw_config.h:
https://review.coreboot.org/c/coreboot/+/41209/13/src/include/fw_config.h@41 PS13, Line 41: fw_config_probe
does this function need to be exposed?
this lets code outside the device enumeration step make a probe check. mostly used by mainboards.
https://review.coreboot.org/c/coreboot/+/41209/13/src/lib/fw_config.c File src/lib/fw_config.c:
https://review.coreboot.org/c/coreboot/+/41209/13/src/lib/fw_config.c@32 PS13, Line 32: /* Look in CBFS to allow override of value. */
should we still query the EC if we have an override?
Ack
https://review.coreboot.org/c/coreboot/+/41209/13/src/lib/fw_config.c@70 PS13, Line 70: match
this is an invariant... […]
since the list is auto-generated by sconfig it is probably a reasonable assumption that the list is properly terminated.
Hello build bot (Jenkins), Furquan Shaikh, Patrick Georgi, Martin Roth, Caveh Jalali, Stefan Reinauer, Tim Wawrzynczak, Julius Werner, Jett Rink, Patrick Rudolph, Aaron Durbin,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/41209
to look at the new patch set (#14).
Change subject: fw_config: Add firmware configuration interface ......................................................................
fw_config: Add firmware configuration interface
This change introduces a new top-level interface for interacting with a bitmask providing firmware configuration information.
This is motivated by Chromebook mainboards that need to support multiple different configurations at runtime with the same BIOS. In these devices the Embedded Controller provides a bitmask that can be broken down into different fields and each field can then be broken down into different options.
The firmware configuration value could also be stored in CBFS and this interface will look in CBFS first to allow the Embedded Controller value to be overridden.
The firmware configuration interface is intended to easily integrate into devicetree.cb and lead to less code duplication for new mainboards that make use of this feature.
BUG=b:147462631 TEST=this provides a new interface that is tested in subsequent commits
Change-Id: I1e889c235a81545e2ec0e3a34dfa750ac828a330 Signed-off-by: Duncan Laurie dlaurie@google.com --- A Documentation/lib/fw_config.md M Documentation/lib/index.md M src/Kconfig M src/include/device/device.h A src/include/fw_config.h M src/lib/Makefile.inc A src/lib/fw_config.c 7 files changed, 525 insertions(+), 1 deletion(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/09/41209/14
Hello build bot (Jenkins), Furquan Shaikh, Patrick Georgi, Martin Roth, Caveh Jalali, Stefan Reinauer, Tim Wawrzynczak, Julius Werner, Jett Rink, Patrick Rudolph, Aaron Durbin,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/41209
to look at the new patch set (#16).
Change subject: fw_config: Add firmware configuration interface ......................................................................
fw_config: Add firmware configuration interface
This change introduces a new top-level interface for interacting with a bitmask providing firmware configuration information.
This is motivated by Chromebook mainboards that need to support multiple different configurations at runtime with the same BIOS. In these devices the Embedded Controller provides a bitmask that can be broken down into different fields and each field can then be broken down into different options.
The firmware configuration value could also be stored in CBFS and this interface will look in CBFS first to allow the Embedded Controller value to be overridden.
The firmware configuration interface is intended to easily integrate into devicetree.cb and lead to less code duplication for new mainboards that make use of this feature.
BUG=b:147462631 TEST=this provides a new interface that is tested in subsequent commits
Change-Id: I1e889c235a81545e2ec0e3a34dfa750ac828a330 Signed-off-by: Duncan Laurie dlaurie@google.com --- A Documentation/lib/fw_config.md M Documentation/lib/index.md M src/Kconfig M src/include/device/device.h A src/include/fw_config.h M src/lib/Makefile.inc A src/lib/fw_config.c 7 files changed, 519 insertions(+), 1 deletion(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/09/41209/16
Furquan Shaikh has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 16:
(3 comments)
https://review.coreboot.org/c/coreboot/+/41209/15/Documentation/lib/fw_confi... File Documentation/lib/fw_config.md:
https://review.coreboot.org/c/coreboot/+/41209/15/Documentation/lib/fw_confi... PS15, Line 8: to be a variant of the same baseboard nit: to use the same coreboot build target.
variants in coreboot are associated with separate build targets.
https://review.coreboot.org/c/coreboot/+/41209/15/src/include/device/device.... File src/include/device/device.h:
https://review.coreboot.org/c/coreboot/+/41209/15/src/include/device/device.... PS15, Line 153: probe_list Should this be guarded by CONFIG(FW_CONFIG) to ensure that it doesn't get added unless mainboard wants to use this?
https://review.coreboot.org/c/coreboot/+/41209/15/src/lib/fw_config.c File src/lib/fw_config.c:
https://review.coreboot.org/c/coreboot/+/41209/15/src/lib/fw_config.c@33 PS15, Line 33: } I know it's not likely that fw_config_value would be partially initialized if cbfs_boot_load_file() failed, but should we set it to 0 here in case FW_CONFIG_SOURCE_CBFS is the only option selected by mainboard.
Duncan Laurie has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 16:
(3 comments)
https://review.coreboot.org/c/coreboot/+/41209/15/Documentation/lib/fw_confi... File Documentation/lib/fw_config.md:
https://review.coreboot.org/c/coreboot/+/41209/15/Documentation/lib/fw_confi... PS15, Line 8: to be a variant of the same baseboard
nit: to use the same coreboot build target. […]
Done
https://review.coreboot.org/c/coreboot/+/41209/15/src/include/device/device.... File src/include/device/device.h:
https://review.coreboot.org/c/coreboot/+/41209/15/src/include/device/device.... PS15, Line 153: probe_list
Should this be guarded by CONFIG(FW_CONFIG) to ensure that it doesn't get added unless mainboard wan […]
With the change to the way probing is done I was able to put this back in !DEVTREE_EARLY but I'd rather not add more #ifdef in here.
https://review.coreboot.org/c/coreboot/+/41209/15/src/lib/fw_config.c File src/lib/fw_config.c:
https://review.coreboot.org/c/coreboot/+/41209/15/src/lib/fw_config.c@33 PS15, Line 33: }
I know it's not likely that fw_config_value would be partially initialized if cbfs_boot_load_file() […]
Done
Furquan Shaikh has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 16:
(1 comment)
https://review.coreboot.org/c/coreboot/+/41209/15/src/include/device/device.... File src/include/device/device.h:
https://review.coreboot.org/c/coreboot/+/41209/15/src/include/device/device.... PS15, Line 153: probe_list
With the change to the way probing is done I was able to put this back in !DEVTREE_EARLY but I'd ra […]
Ack.
Hello build bot (Jenkins), Furquan Shaikh, Patrick Georgi, Martin Roth, Caveh Jalali, Stefan Reinauer, Tim Wawrzynczak, Julius Werner, Jett Rink, Patrick Rudolph, Aaron Durbin,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/41209
to look at the new patch set (#17).
Change subject: fw_config: Add firmware configuration interface ......................................................................
fw_config: Add firmware configuration interface
This change introduces a new top-level interface for interacting with a bitmask providing firmware configuration information.
This is motivated by Chromebook mainboards that need to support multiple different configurations at runtime with the same BIOS. In these devices the Embedded Controller provides a bitmask that can be broken down into different fields and each field can then be broken down into different options.
The firmware configuration value could also be stored in CBFS and this interface will look in CBFS first to allow the Embedded Controller value to be overridden.
The firmware configuration interface is intended to easily integrate into devicetree.cb and lead to less code duplication for new mainboards that make use of this feature.
BUG=b:147462631 TEST=this provides a new interface that is tested in subsequent commits
Change-Id: I1e889c235a81545e2ec0e3a34dfa750ac828a330 Signed-off-by: Duncan Laurie dlaurie@google.com --- A Documentation/lib/fw_config.md M Documentation/lib/index.md M src/Kconfig M src/include/device/device.h A src/include/fw_config.h M src/lib/Makefile.inc A src/lib/fw_config.c 7 files changed, 528 insertions(+), 1 deletion(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/09/41209/17
Duncan Laurie has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 17:
(1 comment)
https://review.coreboot.org/c/coreboot/+/41209/17/src/lib/fw_config.c File src/lib/fw_config.c:
https://review.coreboot.org/c/coreboot/+/41209/17/src/lib/fw_config.c@68 PS17, Line 68: #if ENV_RAMSTAGE I had to use #if here because all_devices is const in other stages so the compiler complains about trying to set dev->enabled to 0 even if that code is wrapped in if(CONFIG(ENV_RAMSTAGE))
Furquan Shaikh has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 17:
(1 comment)
https://review.coreboot.org/c/coreboot/+/41209/17/src/lib/fw_config.c File src/lib/fw_config.c:
https://review.coreboot.org/c/coreboot/+/41209/17/src/lib/fw_config.c@77 PS17, Line 77: if (!fw_config_probe(probe)) { This logic seems different than before. It expects all probes provided by a device to match. Isn't it an OR instead of an AND?
Duncan Laurie has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 17:
(1 comment)
https://review.coreboot.org/c/coreboot/+/41209/17/src/lib/fw_config.c File src/lib/fw_config.c:
https://review.coreboot.org/c/coreboot/+/41209/17/src/lib/fw_config.c@77 PS17, Line 77: if (!fw_config_probe(probe)) {
This logic seems different than before. It expects all probes provided by a device to match. […]
hm I think I uploaded the wrong branch here, I had fixed this in the tree I intended to upload. too many outstanding branches with different states..
Hello build bot (Jenkins), Furquan Shaikh, Patrick Georgi, Martin Roth, Caveh Jalali, Stefan Reinauer, Tim Wawrzynczak, Julius Werner, Jett Rink, Patrick Rudolph, Aaron Durbin,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/41209
to look at the new patch set (#18).
Change subject: fw_config: Add firmware configuration interface ......................................................................
fw_config: Add firmware configuration interface
This change introduces a new top-level interface for interacting with a bitmask providing firmware configuration information.
This is motivated by Chromebook mainboards that need to support multiple different configurations at runtime with the same BIOS. In these devices the Embedded Controller provides a bitmask that can be broken down into different fields and each field can then be broken down into different options.
The firmware configuration value could also be stored in CBFS and this interface will look in CBFS first to allow the Embedded Controller value to be overridden.
The firmware configuration interface is intended to easily integrate into devicetree.cb and lead to less code duplication for new mainboards that make use of this feature.
BUG=b:147462631 TEST=this provides a new interface that is tested in subsequent commits
Change-Id: I1e889c235a81545e2ec0e3a34dfa750ac828a330 Signed-off-by: Duncan Laurie dlaurie@google.com --- A Documentation/lib/fw_config.md M Documentation/lib/index.md M src/Kconfig M src/include/device/device.h A src/include/fw_config.h M src/lib/Makefile.inc A src/lib/fw_config.c 7 files changed, 537 insertions(+), 1 deletion(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/09/41209/18
Furquan Shaikh has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
Patch Set 18: Code-Review+2
Duncan Laurie has submitted this change. ( https://review.coreboot.org/c/coreboot/+/41209 )
Change subject: fw_config: Add firmware configuration interface ......................................................................
fw_config: Add firmware configuration interface
This change introduces a new top-level interface for interacting with a bitmask providing firmware configuration information.
This is motivated by Chromebook mainboards that need to support multiple different configurations at runtime with the same BIOS. In these devices the Embedded Controller provides a bitmask that can be broken down into different fields and each field can then be broken down into different options.
The firmware configuration value could also be stored in CBFS and this interface will look in CBFS first to allow the Embedded Controller value to be overridden.
The firmware configuration interface is intended to easily integrate into devicetree.cb and lead to less code duplication for new mainboards that make use of this feature.
BUG=b:147462631 TEST=this provides a new interface that is tested in subsequent commits
Change-Id: I1e889c235a81545e2ec0e3a34dfa750ac828a330 Signed-off-by: Duncan Laurie dlaurie@google.com Reviewed-on: https://review.coreboot.org/c/coreboot/+/41209 Tested-by: build bot (Jenkins) no-reply@coreboot.org Reviewed-by: Furquan Shaikh furquan@google.com --- A Documentation/lib/fw_config.md M Documentation/lib/index.md M src/Kconfig M src/include/device/device.h A src/include/fw_config.h M src/lib/Makefile.inc A src/lib/fw_config.c 7 files changed, 537 insertions(+), 1 deletion(-)
Approvals: build bot (Jenkins): Verified Furquan Shaikh: Looks good to me, approved
diff --git a/Documentation/lib/fw_config.md b/Documentation/lib/fw_config.md new file mode 100644 index 0000000..63a56dc --- /dev/null +++ b/Documentation/lib/fw_config.md @@ -0,0 +1,353 @@ +# Firmware Configuration Interface in coreboot + +## Motivation + +The firmware configuration interface in coreboot is designed to support a wide variety of +configuration options in that are dictated by the hardware at runtime. This allows a single +BIOS image to be used across a wide variety of devices which may have key differences but are +otherwise similar enough to use the same coreboot build target. + +The initial implementation is designed to take advantage of a bitmask returned by the Embedded +Controller on Google Chrome OS devices which allows the manufacturer to use the same firmware +image across multiple devices by selecting various options at runtime. See the Chromium OS +[Firmware Config][1] documentation for more information. + +This firmware configuration interface differs from the CMOS option interface in that this +bitmask value is not intended as a user-configurable setting as the configuration values must +match the actual hardware. In the case where a user was to swap their hardware this value +would need to be updated or overridden. + +## Device Presence + +One common example of why a firmware configuration interface is important is determining if a +device is present in the system. With some bus topologies and hardware mechanisms it is +possible to probe and enumerate this at runtime: + +- PCI is a self-discoverable bus and is very easy to handle. +- I2C devices can often be probed with a combination of bus and address. +- The use of GPIOs with external strap to ground or different voltages can be used to detect +presence of a device. + +However there are several cases where this is insufficient: + +- I2C peripherals that require different drivers but have the same bus address cannot be +uniquely identified at runtime. +- A mainboard may be designed with multiple daughter board combinations which contain devices +and configurations that cannot be detected. +- While presence detect GPIOs are a convenient way for a single device presence, they are +unable to distinguish between different devices so it can require a large number of GPIOs to +support relatively few options. + +This presence detection can impact different stages of boot: + +### ACPI + +Devices that are not present should not provide an ACPI device indicating that they are +present or the operating system may not be able to handle it correctly. + +The ACPI devices are largely driven by chips defined in the mainboard `devicetree.cb` and +the variant overridetree.cb. This means it is important to be able to specify when a device +is present or not directly in `devicetree.cb` itself. Otherwise each mainboard needs custom +code to parse the tree and disable unused devices. + +### GPIO + +GPIOs with multiple functions may need to be configured correctly depending on the attached +device. Given the wide variety of GPIO configuration possibilities it is not feasible to +specify all combinations directly in `devicetree.cb` and it is best left to code provided by +the mainboard. + +### FSP UPD + +Enabling and disabling devices may require altering FSP UPD values that are provided to the +various stages of FSP. These options are also not easy to specify multiple times for +different configurations in `devicetree.cb` and can be provided by the mainboard as code. + +## Firmware Configuration Interface + +The firmware configuration interface can be enabled by selecting `CONFIG_FW_CONFIG` and also +providing a source for the value by defining an additional Kconfig option defined below. + +If the firmware configuration interface is disabled via Kconfig then all probe attempts will +return true. + +## Firmware Configuration Value + +The 32bit value used as the firmware configuration bitmask is meant to be determined at runtime +but could also be defined at compile time if needed. + +There are two supported sources for providing this information to coreboot. + +### CBFS + +The value can be provided with a 32bit raw value in CBFS that is read by coreboot. The value +can be set at build time but also adjusted in an existing image with `cbfstool`. + +To enable this select the `CONFIG_FW_CONFIG_CBFS` option in the build configuration and add a +raw 32bit value to CBFS with the name of the current prefix at `CONFIG_FW_PREFIX/fw_config`. + +When `fw_config_probe_device()` or `fw_config_probe()` is called it will look for the specified +file in CBFS use the value it contains when matching fields and options. + +### Embedded Controller + +Google Chrome OS devices support an Embedded Controller interface for reading and writing the +firmware configuration value, along with other board-specific information. It is possible for +coreboot to read this value at boot on systems that support this feature. + +This option is selected by default for the mainboards that use it with +`CONFIG_FW_CONFIG_CHROME_EC_CBI` and it is not typically necessary to adjust the value. It is +possible by enabling the CBFS source and coreboot will look in CBFS first for a valid value +before asking the embedded controller. + +It is also possible to adjust the value in the embedded controller *(after disabling write +protection)* with the `ectool` command in a Chrome OS environment. + +For more information on the firmware configuration field on Chrome OS devices see the Chromium +documentation for [Firmware Config][1] and [Board Info][2]. + +[1]: http://chromium.googlesource.com/chromiumos/docs/+/master/design_docs/firmwa... +[2]: http://chromium.googlesource.com/chromiumos/docs/+/master/design_docs/cros_b... + +## Firmware Configuration Table + +The firmware configuration table itself is defined in the mainboard `devicetree.cb` with +special tokens for defining fields and options. + +The table itself is enclosed in a `fw_config` token and terminated with `end` and it contains +a mix of field and option definitions. + +Each field is defined by providing the field name and the start and end bit marking the exact +location in the bitmask. Field names must be at least three characters long in order to +satisfy the sconfig parser requirements and they must be unique with non-overlapping masks. + + field <name> <start-bit> <end-bit> [option...] end + +For single-bit fields only one number is needed: + + field <name> <bit> [option...] end + +Each `field` definition starts a new block that can be composed of zero or more field options, +and it is terminated with `end`. + +Inside the field block the options can be defined by providing the option name and the field +value that this option represents when the bit offsets are used to apply a mask and shift. +Option names must also be at least three characters for the sconfig parser. + + option <name> <value> + +It is possible for there to be multiple `fw_config` blocks and for subsequent `field` blocks +to add additional `option` definitions to the existing field. These subsequent definitions +should not provide the field bitmask as it has already been defined earlier in the file and +this is just matching an existing field by name. + + field <name> [option...] end + +This allows a baseboard to define the major fields and options in `devicetree.cb` and a board +variant to add specific options to fields in or define new fields in the unused bitmask in +`overridetree.cb`. + +It is not possible to redefine a field mask or override the value of an existing option this +way, only to add new options to a field or new fields to the table. + +### Firmware Configuration Table Example + +In this example a baseboard defines a simple boolean feature that is enabled or disabled +depending on the value of bit 0, and a field at bits 1-2 that indicates which daughter board +is attached. + +The baseboard itself defines one daughter board and the variant adds two more possibilities. +This way each variant can support multiple possible daughter boards in addition to the one +that was defined by the baseboard. + +#### devicetree.cb + + fw_config + field FEATURE 0 + option DISABLED 0 + option ENABLED 1 + end + field DAUGHTER_BOARD 1 2 + option NONE 0 + option REFERENCE_DB 1 + end + end + +#### overridetree.cb + + fw_config + field DAUGHTER_BOARD + option VARIANT_DB_ONE 2 + option VARIANT_DB_TWO 3 + end + end + +The result of this table defined in `devicetree.cb` is a list of constants that can be used +to check if fields match the firmware configuration options determined at runtime with a +simple check of the field mask and the option value. + +#### static.h + +```c +/* field: FEATURE */ +#define FW_CONFIG_FIELD_FEATURE_NAME "FEATURE" +#define FW_CONFIG_FIELD_FEATURE_MASK 0x00000001 +#define FW_CONFIG_FIELD_FEATURE_OPTION_DISABLED_NAME "DISABLED" +#define FW_CONFIG_FIELD_FEATURE_OPTION_DISABLED_VALUE 0x00000000 +#define FW_CONFIG_FIELD_FEATURE_OPTION_ENABLED_NAME "ENABLED" +#define FW_CONFIG_FIELD_FEATURE_OPTION_ENABLED_VALUE 0x00000001 + +/* field: DAUGHTER_BOARD */ +#define FW_CONFIG_FIELD_DAUGHTER_BOARD_NAME "DAUGHTER_BOARD" +#define FW_CONFIG_FIELD_DAUGHTER_BOARD_MASK 0x00000006 +#define FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_NONE_NAME "NONE" +#define FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_NONE_VALUE 0x00000000 +#define FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_REFERENCE_DB_NAME "REFERENCE_DB" +#define FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_REFERENCE_DB_VALUE 0x00000002 +#define FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_ONE_NAME "VARIANT_DB_ONE" +#define FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_ONE_VALUE 0x00000004 +#define FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_TWO_NAME "VARIANT_DB_TWO" +#define FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_TWO_VALUE 0x00000006 +``` + +## Device Probing + +One use of the firmware configuration interface in devicetree is to allow device probing to be +specified directly with the devices themselves. A new `probe` token is introduced to allow a +device to be probed by field and option name. Multiple `probe` entries may be present for +each device and any successful probe will consider the device to be present. + +### Probing Example + +Continuing with the previous example this device would be considered present if the field +`DAUGHTER_BOARD` was set to either `VARIANT_DB_ONE` or `VARIANT_DB_TWO`: + +#### overridetree.cb + + chip drivers/generic/example + device generic 0 on + probe DAUGHTER_BOARD VARIANT_DB_ONE + probe DAUGHTER_BOARD VARIANT_DB_TWO + end + end + +If the field were set to any other option, including `NONE` and `REFERENCE_DB` and any +undefined value then the device would be disabled. + +### Probe Overrides + +When a device is declared with a probe in the baseboard `devicetree.cb` and the same device +is also present in the `overridetree.cb` then the probing information from the baseboard +is discarded and the override device must provide all necessary probing information. + +In this example a device is listed in the baseboard with `DAUGHTER_BOARD` field probing for +`REFERENCE_DB` as a field option, It is also defined as an override device with the field +probing for the `VARIANT_DB_ONE` option instead. + +In this case only the probe listed in the override is checked and a field option of +`REFERENCE_DB` will not mark this device present. If both options are desired then the +override device must list both. This allows an override device to remove a probe entry that +was defined in the baseboard. + +#### devicetree.cb + + chip drivers/generic/example + device generic 0 on + probe DAUGHTER_BOARD REFERENCE_DB + end + end + +#### overridetree.cb + + chip drivers/generic/example + device generic 0 on + probe DAUGHTER_BOARD VARIANT_DB_ONE + end + end + +### Automatic Device Probing + +At boot time the firmware configuration interface will walk the device tree and apply any +probe entries that were defined in `devicetree.cb`. This probing takes effect before the +`BS_DEV_ENUMERATE` step during the boot state machine in ramstage. + +Devices that have a probe list but do do not find a match are disabled by setting +`dev->enabled = 0` but the chip `enable_dev()` and device `enable()` handlers will still +be executed to allow any device disable code to execute. + +The result of this probe definition is to provide an array of structures describing each +field and option to check. + +#### fw_config.h + +```c +/** + * struct fw_config - Firmware configuration field and option. + * @field_name: Name of the field that this option belongs to. + * @option_name: Name of the option within this field. + * @mask: Bitmask of the field. + * @value: Value of the option within the mask. + */ +struct fw_config { + const char *field_name; + const char *option_name; + uint32_t mask; + uint32_t value; +}; +``` + +#### static.c + +```c +STORAGE struct fw_config __devN_probe_list[] = { + { + .field_name = FW_CONFIG_FIELD_DAUGHTER_BOARD_NAME, + .option_name = FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_ONE_NAME, + .mask = FW_CONFIG_FIELD_DAUGHTER_BOARD_MASK, + .value = FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_ONE_VALUE + }, + { + .field_name = FW_CONFIG_FIELD_DAUGHTER_BOARD_NAME, + .option_name = FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_TWO_NAME, + .mask = FW_CONFIG_FIELD_DAUGHTER_BOARD_MASK, + .value = FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_TWO_VALUE + }, + { } +}; +``` + +### Runtime Probing + +The device driver probing allows for seamless integration with the mainboard but it is only +effective in ramstage and for specific devices declared in devicetree.cb. There are other +situations where code may need to probe or check the value of a field in romstage or at other +points in ramstage. For this reason it is also possible to use the firmware configuration +interface directly. + +```c +/** + * fw_config_probe() - Check if field and option matches. + * @match: Structure containing field and option to probe. + * + * Return %true if match is found, %false if match is not found. + */ +bool fw_config_probe(const struct fw_config *match); +``` + +The argument provided to this function can be created from a macro for easy use: + + FW_CONFIG(field, option) + +This example has a mainboard check if a feature is disabled and set an FSP UPD before memory +training. This example expects that the default value of this `register` is set to `true` in +`devicetree.cb` and this code is disabling that feature before FSP is executed. + +```c +#include <fw_config.h> + +void mainboard_memory_init_params(FSPM_UPD *mupd) +{ + if (fw_config_probe_one(FW_CONFIG(FEATURE, DISABLED)) + mupd->ExampleFeature = false; +} +``` diff --git a/Documentation/lib/index.md b/Documentation/lib/index.md index 99b8061..d64b4e9 100644 --- a/Documentation/lib/index.md +++ b/Documentation/lib/index.md @@ -3,7 +3,7 @@ This section contains documentation about coreboot internal technical information and libraries.
-## Structure and layout - [Flashmap and Flashmap Descriptor](flashmap.md) - [ABI data consumption](abi-data-consumption.md) - [Timestamps](timestamp.md) +- [Firmware Configuration Interface](fw_config.md) diff --git a/src/Kconfig b/src/Kconfig index 2a2a144..b96d51f 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -323,6 +323,33 @@ The path and filename of the file to use as graphical bootsplash screen. The file format has to be jpg.
+config FW_CONFIG + bool "Firmware Configuration Probing" + default n + help + Enable support for probing devices with fw_config. This is a simple + bitmask broken into fields and options for probing. + +config FW_CONFIG_SOURCE_CBFS + bool "Obtain Firmware Configuration value from CBFS" + depends on FW_CONFIG + default n + help + With this option enabled coreboot will look for the 32bit firmware + configuration value in CBFS at the selected prefix with the file name + "fw_config". This option will override other sources and allow the + local image to preempt the mainboard selected source. + +config FW_CONFIG_SOURCE_CHROMEEC_CBI + bool "Obtain Firmware Configuration value from Google Chrome EC CBI" + depends on FW_CONFIG && EC_GOOGLE_CHROMEEC + default n + help + This option tells coreboot to read the firmware configuration value + from the Google Chrome Embedded Controller CBI interface. This source + is not tried if FW_CONFIG_SOURCE_CBFS is enabled and the value was + found in CBFS. + config HAVE_RAMPAYLOAD bool
diff --git a/src/include/device/device.h b/src/include/device/device.h index 46efbfe..082dcbb 100644 --- a/src/include/device/device.h +++ b/src/include/device/device.h @@ -8,6 +8,7 @@ #include <smbios.h> #include <types.h>
+struct fw_config; struct device; struct pci_operations; struct i2c_bus_operations; @@ -147,6 +148,9 @@ #endif #endif DEVTREE_CONST void *chip_info; + + /* Zero-terminated array of fields and options to probe. */ + DEVTREE_CONST struct fw_config *probe_list; };
/** diff --git a/src/include/fw_config.h b/src/include/fw_config.h new file mode 100644 index 0000000..d41afd6 --- /dev/null +++ b/src/include/fw_config.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __FW_CONFIG__ +#define __FW_CONFIG__ + +#include <device/device.h> +#include <static.h> /* Provides fw_config definitions from devicetree.cb */ +#include <stdbool.h> +#include <stdint.h> + +/** + * struct fw_config - Firmware configuration field and option. + * @field_name: Name of the field that this option belongs to. + * @option_name: Name of the option within this field. + * @mask: Bitmask of the field. + * @value: Value of the option within the mask. + */ +struct fw_config { + const char *field_name; + const char *option_name; + uint32_t mask; + uint32_t value; +}; + +/* Generate a pointer to a compound literal of the fw_config structure. */ +#define FW_CONFIG(__field, __option) (&(const struct fw_config) { \ + .field_name = FW_CONFIG_FIELD_##__field##_NAME, \ + .option_name = FW_CONFIG_FIELD_##__field##_OPTION_##__option##_NAME, \ + .mask = FW_CONFIG_FIELD_##__field##_MASK, \ + .value = FW_CONFIG_FIELD_##__field##_OPTION_##__option##_VALUE \ +}) + +#if CONFIG(FW_CONFIG) + +/** + * fw_config_probe() - Check if field and option matches. + * @match: Structure containing field and option to probe. + * + * Return %true if match is found, %false if match is not found. + */ +bool fw_config_probe(const struct fw_config *match); + +#else + +static inline bool fw_config_probe(const struct fw_config *match) +{ + /* Always return true when probing with disabled fw_config. */ + return true; +} + +#endif /* CONFIG(FW_CONFIG) */ + +#endif /* __FW_CONFIG__ */ diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc index 6511c0c..e0003bd 100644 --- a/src/lib/Makefile.inc +++ b/src/lib/Makefile.inc @@ -159,6 +159,11 @@ verstage-y += hexdump.c smm-y += hexdump.c
+bootblock-$(CONFIG_FW_CONFIG) += fw_config.c +verstage-$(CONFIG_FW_CONFIG) += fw_config.c +romstage-$(CONFIG_FW_CONFIG) += fw_config.c +ramstage-$(CONFIG_FW_CONFIG) += fw_config.c + bootblock-$(CONFIG_ESPI_DEBUG) += espi_debug.c verstage-$(CONFIG_ESPI_DEBUG) += espi_debug.c romstage-$(CONFIG_ESPI_DEBUG) += espi_debug.c diff --git a/src/lib/fw_config.c b/src/lib/fw_config.c new file mode 100644 index 0000000..e97cfdc --- /dev/null +++ b/src/lib/fw_config.c @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <bootstate.h> +#include <cbfs.h> +#include <console/console.h> +#include <device/device.h> +#include <ec/google/chromeec/ec.h> +#include <fw_config.h> +#include <stdbool.h> +#include <stdint.h> + +/** + * fw_config_get() - Provide firmware configuration value. + * + * Return 32bit firmware configuration value determined for the system. + */ +static uint32_t fw_config_get(void) +{ + static uint32_t fw_config_value; + static bool fw_config_value_initialized; + + /* Nothing to prepare if setup is already done. */ + if (fw_config_value_initialized) + return fw_config_value; + fw_config_value_initialized = true; + + /* Look in CBFS to allow override of value. */ + if (CONFIG(FW_CONFIG_SOURCE_CBFS)) { + if (cbfs_boot_load_file(CONFIG_CBFS_PREFIX "/fw_config", + &fw_config_value, sizeof(fw_config_value), + CBFS_TYPE_RAW) != sizeof(fw_config_value)) { + printk(BIOS_WARNING, "%s: Could not get fw_config from CBFS\n", + __func__); + fw_config_value = 0; + } else { + printk(BIOS_INFO, "FW_CONFIG value from CBFS is 0x%08x\n", + fw_config_value); + return fw_config_value; + } + } + + /* Read the value from EC CBI. */ + if (CONFIG(FW_CONFIG_SOURCE_CHROMEEC_CBI)) { + if (google_chromeec_cbi_get_fw_config(&fw_config_value)) + printk(BIOS_WARNING, "%s: Could not get fw_config from EC\n", __func__); + } + + printk(BIOS_INFO, "FW_CONFIG value is 0x%08x\n", fw_config_value); + return fw_config_value; +} + +bool fw_config_probe(const struct fw_config *match) +{ + /* Compare to system value. */ + if ((fw_config_get() & match->mask) == match->value) { + if (match->field_name && match->option_name) + printk(BIOS_INFO, "fw_config match found: %s=%s\n", match->field_name, + match->option_name); + else + printk(BIOS_INFO, "fw_config match found: mask=0x%08x value=0x%08x\n", + match->mask, match->value); + return true; + } + + return false; +} + +#if ENV_RAMSTAGE +static void fw_config_init(void *unused) +{ + struct device *dev; + + for (dev = all_devices; dev; dev = dev->next) { + const struct fw_config *probe; + bool match = false; + + if (!dev->probe_list) + continue; + + for (probe = dev->probe_list; probe && probe->mask != 0; probe++) { + if (fw_config_probe(probe)) { + match = true; + break; + } + } + + if (!match) { + printk(BIOS_INFO, "%s disabled by fw_config\n", dev_path(dev)); + dev->enabled = 0; + } + } +} +BOOT_STATE_INIT_ENTRY(BS_DEV_ENUMERATE, BS_ON_ENTRY, fw_config_init, NULL); +#endif