Newer devices use a unified system called UFSC (Unified Firmware and Second-source Configuration). This system replaces the separate legacy FW_CONFIG and SSFC fields with a single, schema-driven 128-bit (4-DWORD) value stored in the CBI.
The primary goals of UFSC are to:
The 128-bit UFSC field is structured as follows:
The CONFIG_CROS_EC_CBI_UFSC_PARSER Kconfig option enables the driver that parses UFSC fields from the devicetree and provides the necessary APIs.
This option is enabled automatically if a devicetree node with the cros-ec,cbi-ufsc compatible is present and enabled. Therefore, you do not need to set this Kconfig option manually in your project's configuration file.
UFSC is configured using a template-based approach in the devicetree. A project overlay includes standard schema files and then defines the specific values for the hardware present on that device. The schema for these nodes is defined in cros-ec,cbi-ufsc.yaml and cros-ec,cbi-ufsc-value.yaml.
The structure of the UFSC bitfield is defined in two template files that should be included by a project's overlay:
zephyr/include/cros/cbi_ufsc_std_schema.dtsi: Defines the standardized fields. Only the fields the EC is interested in are defined.zephyr/include/cros/cbi_ufsc_oem_schema.dtsi: Defines the generic, optional fields for OEM customization. Only the fields the EC is interested in are defined.These files define the field names, start bit, and size for each configuration item.
Example snippet from cbi_ufsc_std_schema.dtsi:
#define UFSC_BIT(dword, bit) ((dword) * 32 + (bit)) / { cbi_ufsc: cbi-ufsc { compatible = "cros-ec,cbi-ufsc"; ufsc_thermal_fan: thermal-fan { enum-name = "UFSC_THERMAL_FAN"; start = <UFSC_BIT(2, 2)>; size = <1>; }; ufsc_base_sensor: base-sensor { enum-name = "UFSC_BASE_SENSOR"; start = <UFSC_BIT(2, 6)>; size = <3>; }; /* ... other standard fields ... */ }; };
A project defines the possible values for each field by creating child nodes within the corresponding field node. These value definitions are typically placed in a project-specific overlay file (e.g., generated_std_ufsc.dtsi for autogenerated values, or oem_ufsc.dtsi for custom values).
Each value node has the following properties:
Example project overlay (project.overlay):
/* Include the standard and OEM schema templates */ #include <cros/cbi_ufsc_std_schema.dtsi> #include <cros/cbi_ufsc_oem_schema.dtsi> /* Include the generated file that defines the values for this project */ #include "generated_std_ufsc.dtsi" /* Optionally include and define OEM custom values */ #include "oem_ufsc.dtsi"
Example value definition (generated_std_ufsc.dtsi):
/* This file is typically auto-generated */ &ufsc_thermal_fan { ufsc_fan_absent: absent { compatible = "cros-ec,cbi-ufsc-value"; status = "okay"; value = <0>; default; }; ufsc_fan_present: present { compatible = "cros-ec,cbi-ufsc-value"; status = "okay"; value = <1>; }; }; &ufsc_base_sensor { ufsc_base_lsm6dso: lsm6dso { compatible = "cros-ec,cbi-ufsc-value"; status = "okay"; value = <0>; }; ufsc_base_bmi160: bmi160 { compatible = "cros-ec,cbi-ufsc-value"; status = "okay"; value = <1>; default; }; };
The firmware interacts with UFSC data through a common driver API, abstracting the bit-level details.
The preferred method is to check for a specific value using cros_cbi_ufsc_check_match(). This is less error-prone and similar to the legacy SSFC API.
#include "cros_cbi.h" if (cros_cbi_ufsc_check_match( CBI_UFSC_VALUE_ID(DT_NODELABEL(ufsc_fan_present)))) { /* Fan is present */ }
The cbi console command and the ectool cbi host command can be used to read UFSC data.
When setting the UFSC value using ectool, the argument provided must be a byte-ordered hex string using little-endian format (least significant byte first).
For example, if the desired UFSC data consists of the following 32-bit words:
0x112233440x556677880x99aabbcc0xddeeff00The command to write this to the UFSC tag (29) is:
ectool cbi set 29 4433221188776655ccbbaa9900ffeedd
To generate a CBI image file containing UFSC data, use the cbi-util tool. There are two ways to provide UFSC data:
--ufsc_hex argument to provide a raw hex string. This aligns with the ectool format.cbi-util create --file cbi.bin --board_version 1 --sku_id 1 --size 256 \ --ufsc_hex 4433221188776655ccbbaa9900ffeedd
--ufsc argument with four comma-separated 32-bit hexadecimal values (DWORD 0 to DWORD 3).cbi-util create --file cbi.bin --board_version 1 --sku_id 1 --size 256 \ --ufsc 0x11223344,0x55667788,0x99aabbcc,0xddeeff00