Fact-checked by Grok 2 weeks ago

Devicetree

The Devicetree is a data structure and language for describing hardware in computer systems, providing a standardized way for operating systems to receive details about hardware components at boot time rather than relying on hardcoded configurations. It represents hardware topology through a hierarchical tree of nodes and properties, where nodes correspond to devices or buses and properties define attributes such as addresses, interrupts, and compatible drivers. This approach enables flexible, data-driven hardware initialization, decoupling device drivers from specific board layouts and supporting extensibility for new hardware via bindings that specify conventions for data representation. Originating from the standard in the 1990s for platforms like PowerPC and , the Devicetree was formalized to facilitate firmware communication with operating systems. In the , its adoption began in 2005 with PowerPC support, introducing the Flattened Device Tree (FDT) format—a compact, binary representation passed directly to the kernel during . Today, it is integral to on multiple architectures, including , , and x86, where it handles platform identification, runtime configuration, and device population for embedded and server systems. The specification, maintained by the Devicetree Project, reached version 0.4 in June 2023, emphasizing best practices for compatibility and evolution.

Introduction

Definition and Purpose

The Devicetree is a tree-structured used to describe the components of a computer system, such as central processing units (CPUs), memory regions, buses, and peripherals, in a manner that avoids hardcoding these details directly into software. This representation organizes information hierarchically through nodes and properties, allowing firmware to convey a complete, runtime-readable description of the system's physical configuration to the operating system kernel during . By providing this abstracted description, Devicetree enables systems to operate without relying on platform-specific code embedded in the kernel, promoting flexibility across diverse architectures. The primary purpose of Devicetree is to facilitate portable and hardware-agnostic boot processes, where the firmware passes the device description to the OS , which then uses it to initialize drivers and allocate resources dynamically. This approach is particularly valuable for and systems where hardware cannot always be fully probed at runtime, ensuring that non-discoverable aspects—like mappings or device addresses—are explicitly defined. In practice, Devicetree supports the selection of appropriate device drivers through compatible strings in properties, allowing the kernel to match hardware variants without extensive reconfiguration. Key benefits of Devicetree include reducing bloat by minimizing the need for architecture-specific initialization code, enabling dynamic discovery and configuration, and supporting multi-platform deployments with a single . For instance, it allows broad compatibility across architectures like , PowerPC, and , where varying layouts can be accommodated through standardized descriptions rather than compiled-in assumptions. This data-driven model not only streamlines development for diverse systems but also enhances maintainability by centralizing details outside the . Devicetree evolved from the (OF) mechanism originally developed for PowerPC systems, where it served as a structured way to represent hardware in firmware environments, and has since been generalized into a standalone specification. Today, its modern standards are maintained by the Devicetree.org project, a community-driven initiative established around 2017 to oversee the evolution and release of the Devicetree Specification, with the current version (v0.4) published in 2023.

History and Development

The Devicetree originated in the 1990s as part of , a standardized developed under IEEE 1275 and initially created by as OpenBoot. Published in 1994, IEEE 1275 defined a Forth-based scripting environment for hardware initialization and probing on systems like and PowerPC platforms. and Apple adopted for their PowerPC-based systems, including Apple's and 's RS/6000 servers, where it enabled dynamic hardware discovery without hard-coded platform specifics. This approach laid the foundation for Devicetree by representing hardware topology in a tree-like passed from to the operating system. Devicetree was adopted into the around 2005 during a major refactoring of PowerPC support to unify 32-bit and 64-bit architectures, making it mandatory for all PowerPC platforms to supply a flattened device tree at boot. By 2012, with the release of Linux kernel 3.3, Devicetree expanded to architectures, replacing board-specific files with a standardized to support the growing diversity of ARM-based embedded devices. This shift reduced kernel bloat and improved portability across hardware variants. Formalization efforts began with the ePAPR (Embedded PowerPC Architecture Platform Requirements) standard in 2008, jointly developed by Power.org and to define Devicetree usage for embedded PowerPC and systems, including boot protocols and binding conventions. These guidelines evolved into the independent Devicetree Specification, with version 0.1 released by Devicetree.org in 2017 to provide a vendor-neutral reference beyond Linux-specific implementations. Recent developments include architecture support integrated into the starting in 2017 with version 4.15, leveraging Devicetree for hardware description in this open instruction set. In 2021, 5.15 introduced enhancements for hybrid systems combining and Devicetree, such as unified firmware node handling via the fwnode to enable on servers while retaining Devicetree for peripherals. Since 2020, the kernel has incorporated YAML-based for Devicetree bindings, improving validation and documentation of hardware properties through json-schema tools. Key contributors include maintainers Frank Rowand, who has led Devicetree improvements and testing since 2015, and Pantelis Antoniou, who pioneered overlay support for dynamic reconfiguration in kernel 3.19. This transition from ad-hoc to standardized bindings has been driven by community efforts to ensure consistency across architectures.

Formats

Device Tree Source (DTS)

The Device Tree Source (DTS) is a human-readable, text-based format used to describe hardware configurations in a , employing a syntax reminiscent of . It serves as the editable input for defining device trees before they are compiled into a representation suitable for use by bootloaders and operating systems. The format allows developers to specify nodes representing components and their properties, facilitating without modifying . DTS files typically begin with a version header such as /dts-v1/;, which indicates compatibility with of the format and enables features like enhanced integer representations. The root of the tree is denoted by the node / { ... };, enclosing all top-level and child nodes. For modularity, DTS supports inclusion directives like /include/ "filename.dtsi", where .dtsi files contain reusable snippets for common hardware descriptions, while primary board or files use the .dts extension. Comments in DTS can be added using C-style block comments (/* ... */) for multi-line annotations or C++-style single-line comments (// ...) for brevity. Labels, defined by appending a colon to an identifier (e.g., mylabel:), allow forward or backward references to nodes or properties via the &label syntax, aiding in complex tree definitions without duplicating paths. These elements promote maintainable and readable source files for hardware vendors and kernel developers. Nodes in DTS are declared within curly braces, containing properties as key-value pairs terminated by semicolons. can hold strings (e.g., compatible = "vendor,[device](/page/Device)";), integer arrays in angle brackets (e.g., reg = <0x1000 0x100>;), or byte strings in square brackets. A simple node example might appear as:
serial@1000 {
    compatible = "ns16550a";
    reg = <0x1000 0x100>;
    clock-frequency = <1843200>;
};
This defines a with its region and . Such snippets build hierarchical trees, with nodes nested inside braces. The compilation process involves feeding DTS files into the Device Tree Compiler (dtc), a tool that validates the syntax and generates a compact Device Tree Blob (DTB) binary file for runtime consumption. Since Linux kernel version 3.18, released in late 2014, DTS has supported the creation of overlays—partial tree fragments that can be applied dynamically to a base tree—enhancing flexibility for modular hardware extensions like add-on boards.

Device Tree Blob (DTB)

The Device Tree Blob (DTB) serves as a flattened, representation of the device tree, enabling efficient exchange of hardware description between bootloaders, , and operating system kernels during system initialization. This format eliminates pointers and hierarchical indirections present in the source representation, serializing the tree into a compact, linear byte stream that can be loaded into and parsed at . DTBs are platform-independent, allowing the same to describe across different architectures, provided the underlying conventions are followed. The DTB begins with a fixed-size header that provides metadata for locating and validating the blob's components. Defined by the C structure struct fdt_header, the header consists of 32-bit big-endian integers, starting with a magic number of 0xd00dfeed to identify the format. Key fields include the total size of the DTB in bytes (totalsize), offsets from the header start to the structure block (off_dt_struct), strings block (off_dt_strings), and memory reservation map (off_mem_rsvmap), as well as the DTB version (up to 17 in the current specification, with backwards compatibility to version 16) and the last compatible version (last_comp_version). Additional fields cover the physical boot CPU ID (boot_cpuid_phys) and sizes of the structure and strings blocks. Following the header is the memory reservation block, comprising zero or more 64-bit big-endian pairs of address and size for regions to be reserved from the kernel's usable memory, terminated by a (0, 0) pair and aligned to 8 bytes. The structure block then follows, aligned to 4 bytes, containing tokens such as FDT_BEGIN_NODE (0x00000001) for node starts, FDT_PROP (0x00000003) for properties with length and name offset, FDT_END_NODE (0x00000002), FDT_NOP (0x00000004) for padding or overlay modifications, and FDT_END (0x00000009) to mark the block's conclusion. The strings block, unaligned, stores null-terminated property name strings referenced by offsets in the structure. The flattening process involves an in-order depth-first traversal of the device tree, serializing nodes and properties into this token-based stream without recursive pointers, which ensures the DTB remains self-contained and relocatable. This supports dynamic reservations for scenarios like initrd placement or bootloader-allocated regions, preventing overlap. They require 8-byte alignment when loaded into to maintain portability across big-endian and little-endian platforms, with the entire blob fitting within contiguous physical . Runtime modifications to the DTB, such as applying overlays for modular extensions, occur by inserting FDT_NOP to effectively remove or alter nodes and properties in place, preserving the original structure while enabling updates without recompilation. For portability, the DTB is loaded at a platform-specific 64-bit aligned (often above the 128 boundary from the start of on systems) and passed to the via registers or boot parameters, allowing parsers to validate the header and traverse the blob independently of the source format from which it was compiled.

Structure and Syntax

Nodes and Properties

In the Devicetree, nodes serve as the fundamental hierarchical containers that represent entities within a , forming a that describes the logical organization of devices and components. The root , denoted as "/", acts as the top-level container for all other nodes, with each subsequent potentially containing nodes to reflect parent-child relationships in the , such as a /soc encapsulating system-on-chip peripherals. This acyclic ensures no cycles exist in the tree, maintaining a that supports references like interrupts without loops. Properties within nodes are key-value pairs that provide descriptive about the represented , consisting of a property name followed by a value in a structured format. Property names are limited to 1-31 characters using a defined set (a-z, A-Z, 0-9, _, +, ,, -, .), while values can be empty, unsigned 32-bit or 64-bit integers, , phandles (for cross-referencing other nodes), string lists, or encoded arrays. For instance, may use integer arrays for specifications, such as reg = <0x3000 0x20>; to denote a base address and size, or string lists for , like compatible = "vendor,[device](/page/Device)";. In the Device Tree Source (DTS) format, are declared sequentially within node braces as property-name = value;, preserving their order in the compiled Device Tree Blob (DTB) for efficient parsing. Several standard properties are defined to convey common characteristics across nodes, enhancing . The name is implicitly derived from the node's name in the source, while device_type (a deprecated string property from IEEE 1275 for FCode model description) may appear in legacy contexts but is not recommended for new designs. The status property, typically set to "okay" or "disabled", indicates whether the node represents active hardware. Phandles provide unique 32-bit integer identifiers for cross-references between nodes, assigned via the phandle property or automatically in the DTB. In DTS syntax, the is explicitly constructed using braces to nest child nodes, such as / { subnode@address { ... }; };, where the @address optionally specifies a unit address matching the first entry in the node's reg for addressable devices. , prefixed as label:, can be attached to nodes or properties for reuse, enabling references via &label in phandles or paths, which facilitates modular descriptions without duplication. Upon compilation to DTB, property strings are stored in a shared offset-based string table to optimize space and access efficiency, while integer values and phandles remain as . This structure ensures the Devicetree remains portable and machine-readable across firmware and operating systems.

Compatible Strings and Binding Documents

The compatible property in a Devicetree is an array of strings that specifies the device model and its , enabling software to hardware descriptions to appropriate drivers. It is defined as a list of null-terminated strings, typically in the format "manufacturer,device-variant", ordered from most specific to most to support fallback matching for or drivers. For example, a UART might use compatible = "fsl,imx6q-uart", "fsl,imx21-uart";, where the first attempts to the specific Freescale i.MX6Q variant and falls back to the i.MX21 if no is found. Devicetree binding documents provide standardized specifications for the required or optional for specific classes, ensuring consistent representation across systems. These documents define semantic rules, such as types, values, and relationships, often using examples to illustrate usage; for instance, they may specify clock or phandles for peripherals. Bindings are crucial for validating Devicetree sources against expected interfaces and facilitating . The evolution of binding documents has progressed from informal text-based descriptions in early releases to structured files employing JSON-schema vocabulary for machine-readable validation. This shift began with initial proposals around 2017 and saw schema validation infrastructure added in 4.20 in late 2018, enabling automated checks during builds. By 2019, the use of schemas became the standard for new bindings, with mandatory validation checks enforced for all submissions since 2021 to improve consistency and error detection. These bindings are hosted in the source tree under the Documentation/devicetree/bindings directory. Representative examples include bindings for GPIO controllers, which require the boolean gpio-controller property to indicate the node acts as a GPIO provider, along with #gpio-cells, an integer specifying the number of cells (typically 2: pin number and flags) needed to encode a GPIO specifier in consumer nodes. Similarly, interrupt controller bindings mandate the interrupt-controller property and #interrupt-cells to define the format of interrupt specifiers, such as 3 cells for type, number, and level in ARM GIC bindings, allowing consumers to reference interrupts via phandles. These standards ensure interoperable referencing of hardware resources like pins or IRQs across the tree. In the , the compatible property plays a central role in driver probing by allowing the device model core to iterate through the string array for each and match it against registered drivers' of_match_table. Upon a successful match, the driver's probe function is invoked to initialize the device, with fallbacks ensuring compatibility for evolving hardware descriptions; this process starts from the root and recurses through buses like or I2C.

Usage in Operating Systems

Linux Kernel Integration

In the Linux kernel, the Device Tree Blob (DTB) is passed from firmware or bootloaders to the kernel during the boot process to describe the hardware configuration. On ARM platforms, the bootloader loads the DTB into memory and passes its physical address to the kernel entry point via register r2, while register r0 is set to 0 to indicate Device Tree usage rather than ATAGs. On PowerPC systems, the DTB is typically embedded or provided through a device tree header in the kernel image, processed by the bootwrapper before kernel initialization. This mechanism allows the kernel to receive a flattened binary representation of the hardware tree without requiring platform-specific code for each board. The parses the DTB using the (OF) APIs located in the drivers/of/ subdirectory, which unflattens the binary into an in-memory tree structure via functions like unflatten_device_tree(). Drivers and subsystems then traverse this tree using of_* APIs, such as of_find_node_by_path() for locating nodes and of_property_read_u32() for extracting properties. Platform devices are automatically registered by calling of_platform_populate(), which iterates over compatible nodes and instantiates struct platform_device instances bound to matching drivers based on compatible strings. This integration enables modular driver probing without hardcoding hardware details in the source. Support for dynamic Device Tree updates was introduced through overlays, allowing runtime modifications to the live tree. Since version 4.6 (released in ), overlays can be applied via the configfs interface at /sys//config/device-tree/overlays, where userspace writes a DT overlay blob to apply changes like adding or modifying nodes and properties. The of_overlay subsystem handles these updates internally, using functions like of_overlay_fdt_apply() to merge fragments into the base tree and notify registered drivers of changes. Live property changes are supported through mechanisms like of_overlay, enabling limited reconfiguration without rebooting, though full device instantiation requires compatible bindings. Device Tree integration is primary on architectures since kernel 3.1 (2012), where it became mandatory for new multi-platform s to consolidate board support. PowerPC has used Device Tree since early kernel versions, originating from standards. support was added in kernel 4.15 (2018), providing initial architecture code and Device Tree bindings for CPU and peripherals. Experimental support combining with Device Tree on x86 platforms arrived in kernel 5.18 (2022), allowing hybrid enumeration for certain firmware scenarios. Despite these features, Device Tree has limitations in handling dynamic hardware changes. It lacks native hotplug support, as the tree describes static hardware at boot time and does not automatically detect or enumerate removable devices like or USB peripherals, which rely on bus-specific discovery instead. Driver probe order depends on static compatible bindings and , potentially leading to dependencies that must be resolved manually via phandles or initcall ordering, without runtime reconfiguration for hot-added hardware. Overlays mitigate some rigidity but are unsuitable for frequent or complex hotplug events, where provides more robust dynamic capabilities on supported platforms.

Support in Other OSes

Support for Devicetree in operating systems other than varies in maturity and implementation, often adapting the standard for specific architectures and use cases while addressing compatibility with established mechanisms like . (WoA) provides partial Devicetree support since 2017, primarily through the translation of Device Tree Blob (DTB) files into tables within during . This approach enables on ARM-based systems, but it is limited to specific platforms such as those using processors, where the firmware handles the conversion to ensure compatibility with Windows' -centric model. Apple has historically utilized Devicetree concepts in its and . In early PowerPC-based Macs, —based on the IEEE 1275 —constructed a device tree by probing I/O buses to describe hardware configuration, facilitating boot and device enumeration. For modern ARM-based systems like those with and later chips, the in macOS employs a custom Apple Device Tree (ADT) format, which is inspired by traditional Devicetree structures for hardware probing and description, though it diverges from the standard flattened format to integrate with Apple's proprietary boot process. FreeBSD introduced experimental Devicetree support for in 2010, with initial code committed to its to enable of flattened device trees for hardware resource on embedded systems. This evolved into fuller integration by FreeBSD 13.0 in 2021, particularly for platforms like the , where DTB supports device enumeration and driver binding without relying on platform-specific probing. NetBSD has supported Device Trees since around 2012 for and other embedded architectures, using them to describe hardware in a portable way similar to , aiding in cross-platform compatibility for devices like and . The RTOS fully adopted Devicetree starting with version 1.10 in 2018, incorporating a major overhaul to use Device Tree Source (DTS) files for board configuration in embedded applications. This allows to describe hardware peripherals, pins, and interrupts in a portable manner, enabling cross-platform builds for resource-constrained devices. Overall, Devicetree support in non- OSes remains less mature than in Linux, frequently hybridized with for and dynamic features, which introduces challenges in standardization and boot complexity on diverse hardware.

Usage in Firmware and Bootloaders

Coreboot Implementation

integrates Devicetree to describe hardware configurations on and platforms, generating a Device Tree Blob (DTB) during the firmware build process for passing to payloads such as the or . This DTB provides essential hardware details, including memory regions, peripherals, and bus structures, enabling payloads to initialize devices without proprietary firmware dependencies. On x86 platforms, primarily uses a custom devicetree format for generation, but standard Devicetree support is extended via payloads like U-Boot. Configuration in involves payload-specific Device Tree Source (DTS) files, such as coreboot.dts for U-Boot payloads, which detail mainboard hardware like CPU, memory, and I/O controllers. These DTS files are processed by the compiler during the build, incorporating Kconfig selections to produce a tailored DTB embedded in the . For example, Kconfig options for board variants dynamically adjust node properties, such as GPIO mappings or clock frequencies, ensuring the DTB reflects the selected hardware setup. Coreboot's Devicetree implementation supports a wide range of devices, including Chromebooks from vendors like and , as well as servers from and , where it facilitates hardware initialization across diverse SoCs. Dynamic DTB generation from Kconfig, developed alongside ARM support, allows automated adaptation based on build-time choices, reducing manual configuration efforts. This approach promotes vendor-neutral by standardizing hardware descriptions independent of proprietary blobs. Integration with libpayload enables runtime access to Devicetree data in payloads, using Flattened Device Tree (FDT) helpers to query and modify hardware information post-initialization. For instance, libpayload can parse DTB nodes for resource allocation in custom payloads. RISC-V support was initially added to around 2020, with enhancements including fixes for hardware initialization and DTB handling in version 4.20, released on May 15, 2023. As of October 2025, 25.09 includes further improvements for , such as enhanced crossgcc build system support for precise Devicetree generation targeting specific ISA extensions.

U-Boot and Other Bootloaders

U-Boot, a widely used for embedded systems, relies on the Device Tree to describe hardware configuration during its execution phase and passes a modified Flattened Device Tree Blob (DTB) to the operating system at handoff. This process enables U-Boot to initialize peripherals and adapt to specific board layouts without recompiling the bootloader binary for each variant. The bootloader parses the DTB loaded from storage or generated internally and performs runtime adjustments to ensure compatibility with the target hardware before invoking the kernel. Runtime modification of the DTB in U-Boot is facilitated by the fdt command suite, which supports operations such as inspecting nodes (fdt print), altering properties (fdt set), and resizing the tree (fdt resize) to accommodate additions like boot arguments. These modifications occur prior to handoff, allowing fixes for hardware-specific details, such as adjusting regions or enabling/disabling peripherals based on detected variants. For example, U-Boot can set the command line in the /chosen node using fdt set /chosen bootargs "<arguments>" after resizing, ensuring the receives updated parameters like filesystem location. Device Tree overlays, which enable modular extensions to the base DTB, have been supported in U-Boot since version 2018.07, allowing dynamic application of patches for add-on hardware without altering the core DTB. Overlays are loaded and merged using commands like fdt apply <overlay_address>, commonly for variants differing in peripherals like sensors or displays, and are passed intact to the after merging. In the implementation, environment variables control DTB handling, with fdtfile specifying the DTB filename to load from storage (e.g., via or filesystems) and fdt_addr_r defining the runtime relocation address in for the parsed . These variables are often set during board initialization scripts and persist across boots if saved to non-volatile storage. Board-specific Device Tree Source (DTS) files reside in the U-Boot source tree under arch/<arch>/dts/, where maintainers define nodes and tailored to the , such as pinmux configurations or clock settings to the board. For new boards, providing a DTS file in this directory is required, with U-Boot-specific overrides in companion .dtsi includes to avoid duplicating upstream definitions. Beyond U-Boot, other bootloaders incorporate Device Tree support with varying degrees of integration. GRUB2 offers limited DTB handling for EFI environments, enabling the bootloader to load a separate DTB file and pass it to the via the devicetree=<path> directive in entries, a refined in version 2.04 to treat loaded DTBs similarly to tables for security and compatibility. This support, introduced around 2018, facilitates booting on UEFI-based systems but lacks advanced features like overlays or runtime modifications, relying instead on static DTB selection during configuration generation. Tianocore EDK II, the open-source UEFI firmware implementation, utilizes Device Tree for platform initialization on and architectures, where the DTB is retrieved from the EFI System Configuration Table to enumerate hardware during the boot services phase. This approach allows EDK II to probe devices, configure , and prepare the environment for OS loaders without hardcoded board knowledge, particularly on where DTB provides essential details like CPU topology and interrupt controllers before transitioning to the kernel.

Tools and Development

dtc Compiler

The Device Tree Compiler (dtc) is an open-source toolchain for processing device tree files, primarily compiling human-readable Device Tree Source (DTS) files into compact binary Device Tree Blobs (DTB) suitable for embedding in images or passing to bootloaders on systems. Written , dtc originated as part of the development efforts, with its source maintained in the kernel tree under scripts/dtc and an upstream repository at . Initial development began in May 2005, led by Benjamin Herrenschmidt with contributions from David Gibson, to support flattened device tree formats for PowerPC and other architectures, evolving from concepts to enable portable hardware description across diverse platforms. Dtc supports multiple input and output formats to facilitate , decompilation, and manipulation of trees. The core function compiles DTS to DTB using the command-line options -I dts -O dtb, producing a that adheres to the Devicetree Specification's flattened format for efficient runtime parsing. Conversely, decompilation from DTB to DTS is achieved with -I dtb -O dts, aiding in reverse-engineering or binary trees. Additional output formats include (-O asm) for integration with assemblers like gas, and (-O yaml) primarily for validation purposes rather than direct use in . Key options enhance flexibility and reliability: -f forces output even if input contains errors, -s sorts s and properties alphabetically for deterministic comparisons, and -@ generates a symbols node containing paths, essential for device tree overlays that reference symbols dynamically during application. Dtc performs basic semantic checks during processing, such as verifying node structures and property types, issuing warnings or errors for violations; the -q option suppresses messages, with escalating levels (-qq, -qqq) for finer control. In practice, integrates seamlessly into build systems for operating systems and . Within the , it is invoked automatically during the make dtbs target to compile all architecture-specific DTS files into DTBs linked into the kernel image or provided separately. Bootloaders like U-Boot also embed or build to generate or modify DTBs at runtime, supporting features like overlays for modular hardware . As a standalone , can be built and used independently via make install, aligning versions with kernel releases— for instance, version 1.7.2, released in 2024, provides enhanced error checking for properties like interrupts and GPIO mappings, and is incorporated in kernels from 6.1 onward. Subsequent releases have added features such as improved plugin support and additional validation checks. Despite its robustness, lacks native support for YAML-based validation against binding documents, necessitating external tools for comprehensive compliance checks.

Editing and Validation Tools

Editing and validation tools facilitate the authoring, debugging, and verification of Devicetree source files (.dts) and binaries (.dtb), ensuring hardware descriptions are accurate and compliant with specifications. For editing, the supports reading Devicetree structures directly from a filesystem representation using the -I fs input option, allowing developers to work with live or exported tree data such as that exposed by the . Integrated development environments enhance this ; for instance, extensions like the DeviceTree extension provide , autocompletion, and basic validation for .dts files, improving productivity during manual edits. Similarly, the nRF DeviceTree extension offers a visual editor for graphical of peripherals and pins, particularly useful for hardware. Validation tools focus on schema compliance for bindings and sources. The dtschema Python package, introduced in 2019, enables comprehensive checks of Devicetree files against / schemas derived from kernel binding documents, using the dtbs_check target in the kernel build system to identify structural errors and property mismatches. For YAML-based binding files, yamllint is employed to enforce style and formatting rules, with a dedicated configuration file in the kernel's Documentation/devicetree/bindings directory ensuring consistency in schema authoring. Debugging utilities allow inspection of compiled and runtime Devicetree structures. The tool can decompile a .dtb file back to human-readable .dts format using -I dtb -O dts, aiding in verification of binary outputs. For hex dumps and structured views of flat Device Tree blobs, fdtdump provides a readable textual representation without full decompilation. At runtime in the , the live Device Tree is exposed via /proc/device-tree, a symlink to /sys//devicetree/base/, where userspace tools can query node properties and hierarchies for debugging booted systems. Additional utilities support dynamic modifications, such as Device Tree overlays, which are fragments applied to the base tree to enable runtime hardware reconfiguration; support for applying overlays via configfs was upstreamed in 3.18 in 2014, with scripts like those in the kernel's scripts/ directory facilitating integration. Best practices for Devicetree development emphasize maintaining .dts files under systems like to track hardware description changes across iterations. Automated (CI) pipelines should incorporate validation using dtschema and yamllint for new bindings, ensuring early detection of inconsistencies before upstream submission or deployment.

Examples

Basic Hardware Description

The Devicetree provides a structured way to describe fundamental hardware components such as processors and memory in a minimal system, enabling the operating system to initialize without hard-coded assumptions about the platform. A basic example for a single-core ARM system based on the Cortex-A53 processor illustrates this by focusing on the root node, CPU topology, and primary memory region, omitting peripherals to emphasize core bootstrapping. This approach is particularly useful for simple system-on-chip (SoC) designs where the hardware configuration is straightforward. Consider the following Device Tree Source (DTS) for a minimal ARM system:
/dts-v1/;

{
    model = "Minimal ARM Cortex-A53 System";
    compatible = "simple,arm-system";
    #address-cells = <2>;
    #size-cells = <2>;

    cpus {
        #address-cells = <1>;
        #size-cells = <0>;

        cpu@0 {
            compatible = "arm,cortex-a53";
            device_type = "cpu";
            reg = <0x0>;
            clock-frequency = <1000000000>; /* 1 GHz */
        };
    };

    memory@0 {
        device_type = "memory";
        reg = <0x00000000 0x00000000 0x40000000 0x00000000>; /* 1 GB starting at 0x0 */
    };
};
In this DTS, the root node establishes the overall addressing scheme with #address-cells and #size-cells properties, which define how child nodes interpret address and size values throughout the tree. The cpus node serves as a container for describing CPU topology, with its child cpu@0 node specifying the processor instance via the reg property (indicating CPU ID 0) and the compatible property identifying the Cortex-A53 architecture for driver matching. The clock-frequency property provides the CPU's operating speed in Hz, aiding in performance scaling. Similarly, the memory@0 node maps the physical memory layout using the reg property to denote the base address and size, allowing the kernel to allocate resources correctly without platform-specific code. These nodes collectively convey the system's core hardware layout in a portable, textual format. When compiled into a Device Tree Blob (DTB), this DTS produces a compact representation suitable for boot-time loading. A snippet of the DTB structure begins with a 40-byte header, including the magic number 0xd00dfeed (big-endian), followed by the total size (e.g., 0x00000068 for this minimal case), offset to the structure block (e.g., 0x00000038), offset to the strings block (e.g., 0x00000058), and other fields like 0x00000011 and boot CPU ID 0x00000000. The structure block then encodes the using tokens such as 0x00000001 (FDT_BEGIN_NODE) for the , properties like 0x00000003 (FDT_PROP) for compatible, and terminators like 0x00000004 (FDT_END_NODE). This form is parsed by the or to populate hardware descriptions at runtime. Such a basic Devicetree is ideal for a single-core without peripherals, as seen in early-stage development or platforms like QEMU's machine, where the focus is on initializing the CPU and memory before adding complexity.

Complex Device Configuration

Complex device configurations in Devicetree often involve hierarchical structures describing interconnected peripherals, such as buses with child devices that share resources like via phandles. These setups require precise node definitions to ensure proper address mapping and resource referencing across the tree. For instance, an I2C bus under the system-on-chip () node might host a device, with properties linking it to an interrupt controller. A representative example of a full board description appears in a Device Tree Source (DTS) file for an SoC with an I2C controller at base address 0x7000, enabling a temperature sensor at I2C address 0x48. The structure includes:
/ {
    soc {
        #address-cells = <1>;
        #size-cells = <1>;
        compatible = "vendor,soc";
        ranges;

        i2c@7000 {
            compatible = "vendor,i2c";
            reg = <0x7000 0x1000>;
            #address-cells = <1>;
            #size-cells = <0>;
            status = "okay";

            my-sensor@48 {
                compatible = "ams,as6200";
                reg = <0x48>;
                interrupt-parent = <&gpio1>;
                interrupts = <17 IRQ_TYPE_EDGE_BOTH>;
                vs-supply = <&vs_regulator>;
            };
        };

        gpio1: gpio@6000 {
            compatible = "vendor,gpio";
            reg = <0x6000 0x1000>;
            gpio-controller;
            #gpio-cells = <2>;
            interrupt-controller;
            #interrupt-cells = <2>;
        };
    };
};
Here, the interrupt-parent phandle references the gpio1 node, and the interrupts property specifies the GPIO pin 17 with edge-both triggering, enabling the sensor to signal events to the GPIO controller acting as an source. The #address-cells and #size-cells properties ensure correct interpretation of the reg address for the I2C child, while the ranges property in the SoC node maps child addresses to physical memory. Devicetree overlays provide a mechanism for runtime modifications to the base tree, allowing dynamic enabling or disabling of devices like a USB controller without recompiling the entire DTS. An overlay fragment targets an existing USB node and updates its status:
/dts-v1/;
/plugin/;

/ {
    fragment@0 {
        target-path = "/soc/usb@30000000";
        __overlay__ {
            status = "okay";
            maximum-speed = "high-speed";
        };
    };
};
This fragment applies at boot via the kernel's overlay support, resolving phandles against the live tree and activating the USB controller at address 0x30000000 with high-speed capability. Overlays are particularly useful for modular hardware additions, such as peripherals added post-manufacture. In real-world implementations, such as the 4's DTS, complex configurations integrate GPIO, UART, and bindings within the BCM2711 description. Key excerpts include:
  • GPIO controller: gpio: gpio@7e200000 { compatible = "brcm,bcm2711-gpio", "brcm,bcm2835-gpio"; reg = <0x7e200000 0xb4>; interrupts = <1 25>; gpio-controller; #gpio-cells = <2>; gpio-ranges = <&cmu 0 0 54>, <&cmu 6 54 6>; #gpio-line-names = "ID_SDA", ..., "TXD1", "RXD1", ...; }; This defines 54 GPIO lines with pin support via the clock management unit (CMU).
  • UART: &uart0 { pinctrl-names = "default"; pinctrl-0 = <&uart0_pins>; status = "okay"; }; uart0_pins: uart0-pins { brcm,pins = <14 15>; brcm,function = <4 4>; }; The primary UART (PL011) uses GPIO 14 () and 15 () in alternate function 4.
  • HDMI: &hdmi0 { status = "okay"; }; hdmi0: hdmi@7e900000 { compatible = "brcm,bcm2835-hdmi"; reg = <0x7e900000 0x1000>, <0x7e902000 0x1000>; interrupts = <2 101>, <2 102>; ... }; Dual HDMI ports are enabled, with the first at 0x7e900000 handling audio and video output via interrupt lines 101 and 102.
These bindings interconnect via phandles, such as GPIO pins routed to UART or for signaling. Managing complex configurations presents challenges, particularly with #address-cells and #size-cells properties, which are not inherited from parent nodes and must be explicitly set for each bus to avoid mismatches in child reg interpretations—defaults of 2 and 1 apply only if omitted, potentially causing translation errors in multi-level hierarchies. Resolving phandles in large trees or during overlay application requires dynamic adjustment to prevent conflicts, as the kernel's resolver shifts local phandles by the maximum value in the base tree plus one, ensuring uniqueness but demanding careful validation to maintain reference integrity across thousands of nodes in expansive SoCs.

References

  1. [1]
    Linux and the Devicetree - The Linux Kernel documentation
    This article describes how Linux uses the device tree. An overview of the device tree data format can be found on the device tree usage page at devicetree.org.
  2. [2]
    Specifications - Devicetree.org
    The current Devicetree Specification release is v0.4, released on June 28, 2023. The source document is on GitHub.
  3. [3]
    Devicetree Specification v0.3-dirty documentation - Read the Docs
    A devicetree is a tree data structure with nodes that describe the devices in a system. Each node has property/value pairs that describe the characteristics of ...
  4. [4]
    The Devicetree Project
    The devicetree specification provides a full technical description of the devicetree data format and best practices. Everyone is encouraged to get involved and ...Specifications · Collaborate · Releases · Contact
  5. [5]
  6. [6]
    IEEE 1275-1994 - IEEE SA
    ... Open Firmware services; and debugging tools for hardware, firmware, firmware drivers, and system software. ... Published: 1994-10-28. Working Group Details.
  7. [7]
    IEEE 1275 Open Firmware Home Page - Devicetree.org
    May 10, 2005 · The core specification, IEEE Std 1275-1994: IEEE Standard for Boot Firmware (Initialization Configuration) Firmware: Core Requirements and ...
  8. [8]
    [PDF] ARM support in the Linux kernel - Bootlin
    ▷ At boot time, the kernel parses the Device Tree to instantiate the available devices. ▷ Can also be used by other platform software than Linux: the. U-Boot ...
  9. [9]
    [PDF] Using the device tree to describe embedded hardware
    Jul 23, 2008 · This paper discusses the implications of using a device tree in the context of embedded systems. We'll cover the current state of device ...Missing: ePAPER | Show results with:ePAPER
  10. [10]
    Releases - Devicetree.org
    Specifications. Governance. Overview Releases · Collaborate · FAQ · News & Blogs ... v0.2-pre - Released Friday, December 1, 2017. Pre-Release. v0.1 - Released ...
  11. [11]
    All Aboard, Part 8: The RISC-V Linux Port is Upstream! - SiFive
    The RISC-V Linux port has been accepted into Linus' tree and is slated to release as part of 4.15. While this is a major milestone, we're far from done in ...
  12. [12]
    Linux_5.15 - Linux Kernel Newbies
    Linux 5.15 was released on Sunday, 31 Oct 2021. Summary: This release adds a new NTFS read-write implementation; support for putting all the processes ...
  13. [13]
    Writing Devicetree Bindings in json-schema
    Devicetree bindings use json-schema in YAML, with top-level properties like $id, $schema, title, and properties defining DT properties.Missing: introduction 2020
  14. [14]
    An alternative device-tree source language - LWN.net
    Aug 9, 2017 · One of the kernel's device-tree maintainers, Frank Rowand, replied: Keep in mind one of the reasons Linus says he is very direct is to avoid ...
  15. [15]
    YAML and Devicetree - Konsulko Group
    Oct 21, 2017 · This document attempts to explain the rationale behind using a YAML based data model instead of the standard devicetree source (DTS).
  16. [16]
    6. Devicetree Source (DTS) Format (version 1)
    The Devicetree Source (DTS) format is a textual representation of a devicetree in a form that can be processed by dtc into a binary devicetree in the form ...Missing: UTF- 8
  17. [17]
    Devicetree Sources (DTS) Coding Style
    The Devicetree Specification allows a broad range of characters in node and property names, but this coding style narrows the range down to achieve better code ...
  18. [18]
    [PDF] Using the device tree to describe embedded hardware
    Jul 23, 2008 · The device tree source (.dts) format is used to express device trees ... By keeping the device tree design focused on hardware description.Missing: specification | Show results with:specification
  19. [19]
    Device tree overlays - LWN.net
    Oct 22, 2014 · Pantelis Antoniou started his LinuxCon Europe session on device tree overlays by noting that the device tree concept often draws complaints ...Missing: contributor | Show results with:contributor
  20. [20]
    5. Flattened Devicetree (DTB) Format
    The Devicetree Blob (DTB) format is a flat binary encoding of devicetree data. It used to exchange devicetree data between software programs.
  21. [21]
    Booting ARM Linux - The Linux Kernel documentation
    Setup the device tree¶. The boot loader must load a device tree image (dtb) into system ram at a 64bit aligned address and initialize it with the boot data. The ...
  22. [22]
    Device-tree schemas - LWN.net
    Nov 14, 2018 · The device-tree bindings define how a particular piece of hardware is described in a device tree. Drivers then implement those bindings.Missing: introduction | Show results with:introduction
  23. [23]
    How to specify gpio information for devices in device-tree
    Most controllers are specifying a generic flag bitfield in the last cell, so for these, use the macros defined in include/dt-bindings/gpio/gpio.h whenever ...<|control11|><|separator|>
  24. [24]
    interrupts.txt
    An additional "#interrupt-cells" property defines the number of cells needed to specify a single interrupt. It is the responsibility of the interrupt ...
  25. [25]
    DeviceTree Booting - powerpc - The Linux Kernel Archives
    The main requirement that will be defined in more detail below is the presence of a device-tree whose format is defined after Open Firmware specification.
  26. [26]
    Devicetree Overlay Notes - The Linux Kernel documentation
    This Page. Show Source. English. Chinese (Simplified). Devicetree Overlay Notes ... dts-v1/; / { compatible = "corp,foo"; /* shared resources */ res: res ...Missing: header | Show results with:header
  27. [27]
    [PDF] ARM support in the Linux kernel - Bootlin
    ▷ The Device Tree Source, in text format, gets compiled into a. Device Tree Blob, in binary format, thanks to the Device Tree. Compiler. ▷ Sources are stored in ...
  28. [28]
    Linux_5.18 - Linux Kernel Newbies
    May 26, 2022 · This release includes support for user events, which allow processes to create and write to trace events that are isolated from kernel trace level events.
  29. [29]
    Xen on ARM and the Device Tree vs. ACPI debate
    Dec 3, 2013 · On systems which support both ACPI and DT we will continue to prefer Device Tree. Once ARM hardware platforms that only support ACPI are ...Missing: 2012 PowerPC RISC- 4.15 5.18<|separator|>
  30. [30]
    How Windows on ARM discovers the underlying hardware?
    Mar 16, 2021 · Windows relies on ACPI to auto-discover the hardware. However, for smaller systems (notably ARM architectures), a device tree file needs to be passed to the ...
  31. [31]
    Apple Device Tree (ADT) - Asahi Linux Documentation
    The Apple device tree (ADT) encodes a number of untyped byte arrays (properties) in a hierarchy of nodes. These describe the available hardware.
  32. [32]
    FlattenedDeviceTree - FreeBSD Wiki
    Jun 27, 2022 · The objective of this project is to provide FreeBSD with the ability to use flattened device trees for description of hardware resources of a computer system ...
  33. [33]
    Zephyr Kernel 1.10.0
    Major enhancements with this release include: Initial alpha-quality thread-level memory protection on x86, userspace and memory domains. Major overhaul to the ...
  34. [34]
    ACPI vs. Device Tree: The Linux Approach to Hardware Description
    Feb 2, 2025 · ACPI dominates x86 due to its powerful dynamic configuration & power management capabilities. Device Trees thrive on ARM & RISC-V due to their lightweight, ...
  35. [35]
    Flattened uImage Tree documentation
    Flattened uImage Tree documentation . uImage.FIT is the new format used for uImage payloads developed by U-boot. Supported architectures . aarch32. aarch64.
  36. [36]
    Adding new devices to a device tree - the coreboot documentation
    Coreboot uses a device tree to generate ACPI tables. Devices are declared with optional aliases, and drivers are hooked up via entries in the device tree.Missing: implementation | Show results with:implementation
  37. [37]
    Kconfig in coreboot
    Kconfig is a tool used in coreboot, Linux, and many other projects as the main configuration mechanism. In coreboot, it allows a developer both to select which ...
  38. [38]
    Distributions — coreboot 25.09-63-gfba92daed3 documentation
    Coreboot distributions include hardware like ChromeOS devices, and after-market firmware like Dasharo, Heads, and Libreboot.
  39. [39]
    RISC-V architecture documentation
    This section contains documentation about coreboot on RISC-V architecture. Mode usage All stages run in M mode. Payloads have a choice of managing M mode ...
  40. [40]
    Welcome to the coreboot documentation — coreboot 25.09-63 ...
    Blob policy in the coreboot project . The goal of the coreboot project is to provide a FOSS firmware solution across multiple CPU architectures, such as ARM, ...Payloads · Getting Started · Tutorial · Mainboard-specific...
  41. [41]
    coreboot 24.08 release
    The LeanEFI payload is basically a translator from coreboot to UEFI. It takes the coreboot tables and transforms them into UEFI interfaces. Although it can ...Missing: generate | Show results with:generate
  42. [42]
    404 Not Found
    Insufficient relevant content.
  43. [43]
    Devicetree in U-Boot — Das U-Boot unknown version documentation
    Devicetree in U-Boot . The following holds information on how U-Boot makes use of devicetree for build-time and runtime configuration.Missing: support | Show results with:support
  44. [44]
    fdt command — Das U-Boot unknown version documentation
    The fdt command provides access to flat device tree blobs in memory. It has many subcommands, some of which are not documented here.<|separator|>
  45. [45]
    See how U-Boot modifies your board device tree - Root Commit
    Jul 21, 2025 · Think about the 2GB, 4GB, 8GB and 16GB variants of the Raspberry Pi 5 board. You don't want to have four different DTS files in the kernel ...Decompiling The Dtb · Board Information · Kernel Command Line
  46. [46]
    Device Tree Overlays — Das U-Boot unknown version documentation
    Device tree overlays manipulate symbols from previous device trees, using a different syntax. They can be applied in U-Boot automatically or manually.
  47. [47]
    Using FIT Image and Device Tree Overlays - Developer Help
    Jun 9, 2025 · Since U-boot 2018.07, released with linux4sam_6.0, we have the feature of adding Device Tree overlays to the base Device Tree at boot time, from ...How It Works · Example · Extract Parts Of The Fit...
  48. [48]
    Environment Variables - The U-Boot Documentation
    U-Boot supports user configuration using environment variables which can be made persistent by saving to persistent storage, for example flash memory.
  49. [49]
    Devicetree Control in U-Boot
    The devicetree files and devicetree bindings are maintained as part of the Linux kernel git repository. Traditionally, U-Boot placed copies of devicetree source ...<|control11|><|separator|>
  50. [50]
    GNU GRUB 2: ChangeLog - 2.02 vs. 2.04 changes | Fossies Diffs
    Source code changes report for the member file ChangeLog of the GNU GRUB 2 software package between the versions 2.02 and 2.04.
  51. [51]
    1751307 – Add ability to add devicetree line to grub.cfg on a BLS ...
    Sep 13, 2019 · Add the ability to add GRUB_DEVICETREE to /etc/default/grub and if it's present (and only if) add the equivalent devicetree= line to the grub.cfg kernel ...<|separator|>
  52. [52]
    [PDF] EDK2 UEFI on RISC-V - Fosdem
    "Free and Open RISC Instruction Set Architecture". – Tries to be simple and legacy-free. – Three privilege modes (Machine, Supervisor, User).
  53. [53]
    [PDF] Device trees everywhere - OzLabs
    Feb 13, 2006 · When reading, dtc takes the version from the blob header, and when writing it takes a com- mand line option specifying the desired version.Missing: history | Show results with:history
  54. [54]
  55. [55]
    None
    ### Summary of dtc Manual (https://raw.githubusercontent.com/dgibson/dtc/master/Documentation/manual.txt)
  56. [56]
    dgibson/dtc - Device Tree Compiler and libfdt - GitHub
    The devicetree-compiler list is for discussion about dtc and libfdt implementation. Core device tree bindings are discussed on the devicetree-spec list.
  57. [57]
    Linux Kernel Makefiles
    dtc. Create flattened device tree blob object suitable for linking into vmlinux. Device tree blobs linked into vmlinux are placed in an init section in the ...
  58. [58]
  59. [59]
    DeviceTree - Visual Studio Marketplace
    The extension supports VSCode 1.5.0 and above. How to install. Open the command palette ( Shift-Ctrl-P ) in VSCode; Select Extensions: Install Extensions ...
  60. [60]
    nRF DeviceTree - Visual Studio Marketplace
    nRF DeviceTree extension features the Devicetree Visual Editor, which allows you to edit your devicetree configuration using an intuitive GUI. Devicetree Visual ...
  61. [61]
    devicetree-org/dt-schema - GitHub
    This repository does not contain device specific bindings. Those are currently maintained within the Linux kernel tree alongside Devicetree files (.dts).
  62. [62]
    fdtdump - prints a readable version of a flat device-tree file.
    DESCRIPTION. The fdtdump program prints a readable version of a flat device-tree file. AUTHOR. fdtdump was written by Pantelis Antoniou <pantelis ...Missing: utility | Show results with:utility
  63. [63]
    linux - Is it possible to get the information for a device tree using /sys ...
    Feb 26, 2016 · If you're on a system that booted using a dtb, your device tree should be accessible inside debugfs. You can also try the dtc tools by Pantelis ...
  64. [64]
    DOs and DON'Ts for designing and writing Devicetree bindings
    Board/SoC .dts Files¶ · DO put all MMIO devices under a bus node and not at the top-level. · DO use non-empty 'ranges' to limit the size of child buses/devices.Missing: format | Show results with:format
  65. [65]
    Tips and Tricks for Validating Devicetree sources with the ... - Linaro
    May 18, 2023 · The Devicetree (DT) schema in the Linux kernel can be used to validate and check your Devicetree sources (DTS). This allows the parser to spot mistakes in the ...Missing: introduction 2020
  66. [66]
    lm75.yaml - The Linux Kernel Archives
    ... devicetree.org/schemas/hwmon/lm75.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# title: LM75 hwmon sensor ... interrupts: maxItems: 1 required ...
  67. [67]
    2. The Devicetree
    The #interrupt-cells property is used by the root of an interrupt domain to define the number of <u32> values needed to encode an interrupt specifier. For ...
  68. [68]
    Devicetree Overlay Notes — The Linux Kernel documentation
    No readable text found in the HTML.<|control11|><|separator|>
  69. [69]
    None
    ### Excerpts Showing GPIO, UART, and HDMI Bindings
  70. [70]
    Devicetree Dynamic Resolver Notes
    How the resolver works¶ · Get the maximum device tree phandle value from the live tree + 1. · Adjust all the local phandles of the tree to resolve by that amount.