1 /* SPDX-License-Identifier: GPL-2.0-only */
6 #include <console/console.h>
7 #include <device/device.h>
8 #include <ec/google/chromeec/ec.h>
12 #include <drivers/vpd/vpd.h>
14 uint64_t fw_config_get(void)
16 static uint64_t fw_config_value
;
17 static bool fw_config_value_initialized
;
19 /* Nothing to prepare if setup is already done. */
20 if (fw_config_value_initialized
)
21 return fw_config_value
;
22 fw_config_value_initialized
= true;
23 fw_config_value
= UNDEFINED_FW_CONFIG
;
25 /* Read the value from EC CBI. */
26 if (CONFIG(FW_CONFIG_SOURCE_CHROMEEC_CBI
)) {
27 if (google_chromeec_cbi_get_fw_config(&fw_config_value
))
28 printk(BIOS_WARNING
, "%s: Could not get fw_config from CBI\n",
31 printk(BIOS_INFO
, "FW_CONFIG value from CBI is 0x%" PRIx64
"\n",
35 /* Look in CBFS to allow override of value. */
36 if (CONFIG(FW_CONFIG_SOURCE_CBFS
) && fw_config_value
== UNDEFINED_FW_CONFIG
) {
37 if (cbfs_load(CONFIG_CBFS_PREFIX
"/fw_config", &fw_config_value
,
38 sizeof(fw_config_value
)) != sizeof(fw_config_value
))
39 printk(BIOS_WARNING
, "%s: Could not get fw_config from CBFS\n",
42 printk(BIOS_INFO
, "FW_CONFIG value from CBFS is 0x%" PRIx64
"\n",
46 if (CONFIG(FW_CONFIG_SOURCE_VPD
) && fw_config_value
== UNDEFINED_FW_CONFIG
) {
48 if (vpd_get_int("fw_config", VPD_RW_THEN_RO
, &vpd_value
)) {
49 fw_config_value
= vpd_value
;
50 printk(BIOS_INFO
, "FW_CONFIG value from VPD is 0x%" PRIx64
"\n",
53 printk(BIOS_WARNING
, "%s: Could not get fw_config from vpd\n",
57 return fw_config_value
;
60 uint64_t fw_config_get_field(const struct fw_config_field
*field
)
62 /* If fw_config is not provisioned, then there is nothing to get. */
63 if (!fw_config_is_provisioned())
64 return UNDEFINED_FW_CONFIG
;
66 int shift
= __ffs64(field
->mask
);
67 const uint64_t value
= (fw_config_get() & field
->mask
) >> shift
;
69 printk(BIOS_INFO
, "fw_config get field name=%s, mask=0x%" PRIx64
", shift=%d, value=0x%"
70 PRIx64
"\n", field
->field_name
, field
->mask
, shift
, value
);
75 bool fw_config_probe(const struct fw_config
*match
)
77 /* If fw_config is not provisioned, then there is nothing to match. */
78 if (!fw_config_is_provisioned())
81 /* Compare to system value. */
82 if ((fw_config_get() & match
->mask
) == match
->value
) {
83 if (match
->field_name
&& match
->option_name
)
84 printk(BIOS_INFO
, "fw_config match found: %s=%s\n", match
->field_name
,
87 printk(BIOS_INFO
, "fw_config match found: mask=0x%" PRIx64
" value=0x%"
89 match
->mask
, match
->value
);
96 bool fw_config_probe_dev(const struct device
*dev
, const struct fw_config
**matching_probe
)
98 const struct fw_config
*probe
;
101 *matching_probe
= NULL
;
103 /* If the device does not have a probe list, then probing is not required. */
104 if (!dev
->probe_list
)
107 /* If the device wants to be enabled during unprovisioned fw_config */
108 if (!fw_config_is_provisioned() && dev
->enable_on_unprovisioned_fw_config
)
111 for (probe
= dev
->probe_list
; probe
&& probe
->mask
!= 0; probe
++) {
112 if (!fw_config_probe(probe
))
116 *matching_probe
= probe
;
126 * The maximum number of fw_config fields is limited by the 64-bit mask that is used to
129 #define MAX_CACHE_ELEMENTS (8 * sizeof(uint64_t))
131 static const struct fw_config
*cached_configs
[MAX_CACHE_ELEMENTS
];
133 static size_t probe_index(uint64_t mask
)
136 return __ffs64(mask
);
139 const struct fw_config
*fw_config_get_found(uint64_t field_mask
)
141 const struct fw_config
*config
;
142 config
= cached_configs
[probe_index(field_mask
)];
143 if (config
&& config
->mask
== field_mask
)
149 void fw_config_for_each_found(void (*cb
)(const struct fw_config
*config
, void *arg
), void *arg
)
153 for (i
= 0; i
< MAX_CACHE_ELEMENTS
; ++i
)
154 if (cached_configs
[i
])
155 cb(cached_configs
[i
], arg
);
158 static void fw_config_init(void *unused
)
162 for (dev
= all_devices
; dev
; dev
= dev
->next
) {
163 const struct fw_config
*probe
;
165 if (!fw_config_probe_dev(dev
, &probe
)) {
166 printk(BIOS_INFO
, "%s disabled by fw_config\n", dev_path(dev
));
172 cached_configs
[probe_index(probe
->mask
)] = probe
;
175 BOOT_STATE_INIT_ENTRY(BS_DEV_INIT_CHIPS
, BS_ON_ENTRY
, fw_config_init
, NULL
);