summaryrefslogtreecommitdiff
path: root/src/lib/fw_config.c
diff options
context:
space:
mode:
authorDuncan Laurie <dlaurie@google.com>2020-05-09 19:20:10 -0700
committerDuncan Laurie <dlaurie@chromium.org>2020-06-02 16:40:04 +0000
commit36e6c6f8d2b63428b0829ff615903715766b8c20 (patch)
tree0db66d9ab7addfab097c59037e44c38a8579771d /src/lib/fw_config.c
parent1ebbb165efe71e83fbf19a9ce6c4bf14e2448d81 (diff)
downloadcoreboot-36e6c6f8d2b63428b0829ff615903715766b8c20.tar.xz
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>
Diffstat (limited to 'src/lib/fw_config.c')
-rw-r--r--src/lib/fw_config.c94
1 files changed, 94 insertions, 0 deletions
diff --git a/src/lib/fw_config.c b/src/lib/fw_config.c
new file mode 100644
index 0000000000..e97cfdc72a
--- /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