BlogEventsIndustry Conference

How ChromeOS Uses Zephyr for Dynamic Hardware Selection

By August 5, 2026No Comments
Beyond Static Devicetrees: Implementing Runtime Hardware Dynamism in Zephyr - Wai-Hong Tam & Jason Yuan, Google

Open Source Summit North America 2026 and Embedded Linux Conference brought together the open source community in Minneapolis from May 18–20, 2026.

As part of the Zephyr track, Wai-Hong Tam and Jason Yuan from Google presented “Beyond Static Devicetrees: Implementing Runtime Hardware Dynamism in Zephyr.”

The session explained how the ChromeOS Embedded Controller team supports many hardware variations with a single Zephyr firmware binary.

A single Chromebook reference board can be used across several commercial models. Depending on the supply chain, the same design may use different sensors, USB-C controllers, keyboard layouts and other second-source components.

Beyond Static Devicetrees: Implementing Runtime Hardware Dynamism in Zephyr - Wai-Hong Tam & Jason Yuan, Google

Using Zephyr’s standard build-time configuration for every hardware combination could create dozens of binaries for one board and thousands of firmware images across multiple products. This would make testing, signing, verified boot, firmware updates and release management much harder.

The team therefore set a clear goal: one reference board should use exactly one firmware binary.

Zephyr processes Devicetree information at build time and converts it into static data. This is efficient for embedded systems because it avoids the memory overhead of parsing a live Devicetree blob at runtime. However, it also means that the hardware configuration is normally fixed when the firmware is built.

Rather than changing Zephyr’s device model, the team built a runtime routing layer on top of it.

The firmware includes a superset of the drivers that may be needed by the different hardware variants. This adds approximately 10 to 30 KB of flash, but avoids managing many separate firmware images.

The hardware identity is stored in ChromeOS Board Information, or CBI. Earlier implementations used GPIO straps, ADC voltage sensing and a separate EEPROM. The current approach stores the CBI data in a protected 4 KB erase block within the embedded controller’s internal flash, avoiding additional hardware cost.

The team expanded its earlier second-source configuration into a 128-bit structure called Unified Firmware and Second Source Configuration, or UFSC. The bit fields describe hardware options such as audio codecs, trackpads, keyboard backlights, thermal fans and USB-C components.

The layout of the UFSC data is defined in Devicetree rather than in C headers. Devicetree nodes describe the position and size of each field, while board overlays associate specific values with supported hardware options. This makes Devicetree the source of truth for the UFSC format and reduces the need for hard-coded bit masks.

The talk described two patterns built on this framework.

The first is a policy pattern for simple features such as a keyboard backlight or thermal fan. At boot, the firmware reads the cached UFSC value and determines whether the feature should be enabled or disabled. Because the feature-selection logic is separated from the hardware definition, it can also be tested using Zephyr’s Ztest framework and mocked UFSC matching functions.

The second pattern handles driver selection. A Devicetree node defines a hardware slot, such as USB-C port 0, together with pairs of UFSC values and possible driver nodes. Zephyr’s compile-time macros process these definitions and generate the selection logic during the build.

At boot, the firmware compares the stored UFSC value with the generated table and returns the correct Zephyr device pointer.

The approach uses no dynamic memory allocation and no runtime string parsing. The routing information is compiled into read-only memory, allowing the selection to run in constant time.

Compiling all possible drivers into one image introduces another challenge. By default, Zephyr attempts to initialize every enabled device during boot. If the firmware tries to communicate with an I2C component that is not physically present, retries and timeouts can delay startup.

To avoid this, the team uses Zephyr’s deferred initialization support.

Alternative devices are included in the firmware, but their initialization is skipped during normal boot. After the correct component is selected from the UFSC value, the firmware initializes only the matching driver. This allows the team to support boot-time hardware selection while keeping the existing Zephyr device model.

The second part of the presentation focused on hardware discovery from the host operating system.

Because Zephyr compiles the Devicetree into the embedded-controller firmware, ChromeOS cannot directly access the original hardware descriptions. The embedded controller behaves like a black box from the host’s perspective. Probing every possible I2C address from the host would be unsafe, while maintaining a separate host-side configuration file could easily cause the host and firmware definitions to drift apart.

The team addressed this problem with a Component Manifest.

During the firmware build, a JSON manifest is generated from the same precompiled Devicetree data used to create the embedded-controller binary. The Component Manifest is then packaged with the host operating system.

The manifest lists the components that may be present, together with information such as the I2C port, address, component type and any other relevant properties. At runtime, the host reads the manifest and probes only the listed candidate devices through the embedded controller’s I2C pass-through interface.

When several components use the same driver, the manifest can include expected product or device identifiers taken from the component specifications. This allows the host to determine which specific component is installed.

The Component Manifest is also integrated with UFSC provisioning.

During manufacturing, the host can use the manifest to probe the supported hardware options, determine which components are present, calculate the correct UFSC value and write it into the CBI area.

This avoids a circular dependency in which the correct driver cannot initialize before the UFSC is known, while the UFSC cannot be generated without first identifying the hardware.

Because the Component Manifest and the embedded-controller firmware are generated from the same Devicetree, they remain synchronized.

The talk concluded with three main takeaways.

First, mass production requires flexibility because hardware is not truly static when second-source components are involved.

Second, Zephyr’s Devicetree macros and deferred initialization can be used to create boot-time driver routing without introducing dynamic memory allocation or a runtime Devicetree parser.

Third, hardware discovery can be moved to the host using a Component Manifest, keeping the embedded-controller firmware small while allowing the operating system to verify the installed hardware safely.

Together, these approaches allow the ChromeOS Embedded Controller team to support many hardware variations with one Zephyr firmware binary while preserving Zephyr’s build-time efficiency.

Watch the session here. Check out the OSS NA 2026 playlist here.