coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
fw_config.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <assert.h>
4 #include <bootstate.h>
5 #include <cbfs.h>
6 #include <console/console.h>
7 #include <device/device.h>
9 #include <fw_config.h>
10 #include <inttypes.h>
11 #include <lib.h>
12 #include <stdbool.h>
13 #include <stdint.h>
14 #include <drivers/vpd/vpd.h>
15 
17 {
18  static uint64_t fw_config_value;
19  static bool fw_config_value_initialized;
20 
21  /* Nothing to prepare if setup is already done. */
22  if (fw_config_value_initialized)
23  return fw_config_value;
24  fw_config_value_initialized = true;
25  fw_config_value = UNDEFINED_FW_CONFIG;
26 
27  /* Read the value from EC CBI. */
28  if (CONFIG(FW_CONFIG_SOURCE_CHROMEEC_CBI)) {
29  if (google_chromeec_cbi_get_fw_config(&fw_config_value))
30  printk(BIOS_WARNING, "%s: Could not get fw_config from CBI\n",
31  __func__);
32  else
33  printk(BIOS_INFO, "FW_CONFIG value from CBI is 0x%" PRIx64 "\n",
34  fw_config_value);
35  }
36 
37  /* Look in CBFS to allow override of value. */
38  if (CONFIG(FW_CONFIG_SOURCE_CBFS) && fw_config_value == UNDEFINED_FW_CONFIG) {
39  if (cbfs_load(CONFIG_CBFS_PREFIX "/fw_config", &fw_config_value,
40  sizeof(fw_config_value)) != sizeof(fw_config_value))
41  printk(BIOS_WARNING, "%s: Could not get fw_config from CBFS\n",
42  __func__);
43  else
44  printk(BIOS_INFO, "FW_CONFIG value from CBFS is 0x%" PRIx64 "\n",
45  fw_config_value);
46  }
47 
48  if (CONFIG(FW_CONFIG_SOURCE_VPD) && fw_config_value == UNDEFINED_FW_CONFIG) {
49  int vpd_value;
50  if (vpd_get_int("fw_config", VPD_RW_THEN_RO, &vpd_value)) {
51  fw_config_value = vpd_value;
52  printk(BIOS_INFO, "FW_CONFIG value from VPD is 0x%" PRIx64 "\n",
53  fw_config_value);
54  } else
55  printk(BIOS_WARNING, "%s: Could not get fw_config from vpd\n",
56  __func__);
57  }
58 
59  return fw_config_value;
60 }
61 
62 bool fw_config_probe(const struct fw_config *match)
63 {
64  /* If fw_config is not provisioned, then there is nothing to match. */
66  return false;
67 
68  /* Compare to system value. */
69  if ((fw_config_get() & match->mask) == match->value) {
70  if (match->field_name && match->option_name)
71  printk(BIOS_INFO, "fw_config match found: %s=%s\n", match->field_name,
72  match->option_name);
73  else
74  printk(BIOS_INFO, "fw_config match found: mask=0x%" PRIx64 " value=0x%"
75  PRIx64 "\n",
76  match->mask, match->value);
77  return true;
78  }
79 
80  return false;
81 }
82 
84 {
86 }
87 
88 bool fw_config_probe_dev(const struct device *dev, const struct fw_config **matching_probe)
89 {
90  const struct fw_config *probe;
91 
92  if (matching_probe)
93  *matching_probe = NULL;
94 
95  /* If the device does not have a probe list, then probing is not required. */
96  if (!dev->probe_list)
97  return true;
98 
99  for (probe = dev->probe_list; probe && probe->mask != 0; probe++) {
100  if (!fw_config_probe(probe))
101  continue;
102 
103  if (matching_probe)
104  *matching_probe = probe;
105  return true;
106  }
107 
108  return false;
109 }
110 
111 #if ENV_RAMSTAGE
112 
113 /*
114  * The maximum number of fw_config fields is limited by the 64-bit mask that is used to
115  * represent them.
116  */
117 #define MAX_CACHE_ELEMENTS (8 * sizeof(uint64_t))
118 
119 static const struct fw_config *cached_configs[MAX_CACHE_ELEMENTS];
120 
121 static size_t probe_index(uint64_t mask)
122 {
123  assert(mask);
124  return __ffs64(mask);
125 }
126 
127 const struct fw_config *fw_config_get_found(uint64_t field_mask)
128 {
129  const struct fw_config *config;
130  config = cached_configs[probe_index(field_mask)];
131  if (config && config->mask == field_mask)
132  return config;
133 
134  return NULL;
135 }
136 
137 void fw_config_for_each_found(void (*cb)(const struct fw_config *config, void *arg), void *arg)
138 {
139  size_t i;
140 
141  for (i = 0; i < MAX_CACHE_ELEMENTS; ++i)
142  if (cached_configs[i])
143  cb(cached_configs[i], arg);
144 }
145 
146 static void fw_config_init(void *unused)
147 {
148  struct device *dev;
149 
150  for (dev = all_devices; dev; dev = dev->next) {
151  const struct fw_config *probe;
152 
153  if (!fw_config_probe_dev(dev, &probe)) {
154  printk(BIOS_INFO, "%s disabled by fw_config\n", dev_path(dev));
155  dev->enabled = 0;
156  continue;
157  }
158 
159  if (probe)
160  cached_configs[probe_index(probe->mask)] = probe;
161  }
162 }
164 #endif
#define assert(statement)
Definition: assert.h:74
@ BS_DEV_INIT_CHIPS
Definition: bootstate.h:79
@ BS_ON_ENTRY
Definition: bootstate.h:95
static size_t cbfs_load(const char *name, void *buf, size_t size)
Definition: cbfs.h:282
#define printk(level,...)
Definition: stdlib.h:16
DEVTREE_CONST struct device *DEVTREE_CONST all_devices
Linked list of ALL devices.
Definition: device_const.c:13
const char * dev_path(const struct device *dev)
Definition: device_util.c:149
@ VPD_RW_THEN_RO
Definition: vpd.h:14
@ CONFIG
Definition: dsi_common.h:201
int google_chromeec_cbi_get_fw_config(uint64_t *fw_config)
Definition: ec.c:844
#define UNDEFINED_FW_CONFIG
Definition: fw_config.h:11
#define PRIx64
Definition: inttypes.h:37
struct bootblock_arg arg
Definition: decompressor.c:22
uint64_t fw_config_get(void)
fw_config_get() - Provide firmware configuration value.
Definition: fw_config.c:16
bool fw_config_probe_dev(const struct device *dev, const struct fw_config **matching_probe)
Definition: fw_config.c:88
bool fw_config_is_provisioned(void)
Definition: fw_config.c:83
bool fw_config_probe(const struct fw_config *match)
Definition: fw_config.c:62
static int __ffs64(u64 x)
Definition: lib.h:65
#define BIOS_INFO
BIOS_INFO - Expected events.
Definition: loglevel.h:113
#define BIOS_WARNING
BIOS_WARNING - Bad configuration.
Definition: loglevel.h:86
BOOT_STATE_INIT_ENTRY(BS_DEV_ENABLE, BS_ON_ENTRY, fw_config_handle, NULL)
enum board_config config
Definition: memory.c:448
static const int mask[4]
Definition: gpio.c:308
#define NULL
Definition: stddef.h:19
unsigned long long uint64_t
Definition: stdint.h:17
Definition: device.h:107
DEVTREE_CONST struct fw_config * probe_list
Definition: device.h:167
DEVTREE_CONST struct device * next
Definition: device.h:113
unsigned int enabled
Definition: device.h:122
struct fw_config - Firmware configuration field and option.
Definition: fw_config.h:20
uint64_t mask
Definition: fw_config.h:23
const char * field_name
Definition: fw_config.h:21
const char * option_name
Definition: fw_config.h:22
uint64_t value
Definition: fw_config.h:24
bool vpd_get_int(const char *const key, const enum vpd_region region, int *const val)
Definition: vpd.c:284