Python FDT Bindings

1.7.2.post1 · active · verified Fri Apr 17

pylibfdt is a Python binding for the C library `libfdt`, providing functionality to parse, manipulate, and generate Device Tree Blobs (DTBs). It offers a Pythonic interface to access nodes, properties, and iterate through the device tree structure. Currently at version 1.7.2.post1, the library maintains a stable API with infrequent but significant updates, primarily tracking upstream `libfdt` changes.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to load a Device Tree Blob (DTB) from bytes or a file, access its root node, and iterate through all nodes and their properties. It highlights handling different types of property values (bytes, strings) and the importance of checking for `None` when retrieving nodes or properties.

from pylibfdt import Fdt
import os

# For demonstration, create a dummy DTB file if it doesn't exist
# In a real scenario, you'd load an existing .dtb file
dummy_dtb_path = "example.dtb"
if not os.path.exists(dummy_dtb_path):
    # This is a very minimal valid DTB structure (version 16, no nodes)
    # Actual DTBs are much more complex. This only serves to avoid FdtException on a non-existent file.
    # A true example would require external tools to generate a valid DTB.
    # For real use, ensure 'example.dtb' is a valid DTB created by dtc.
    try:
        # Attempt to create a placeholder or indicate requirement for a real DTB
        # Cannot easily generate a valid DTB from scratch within Python for quickstart.
        # Assume a valid 'test.dtb' exists for proper execution.
        print(f"Please ensure a valid DTB file named '{dummy_dtb_path}' exists for a meaningful quickstart.")
        # For strict runnable, we will use a byte literal that is a minimal valid FDT header.
        # This will load, but won't have any actual nodes or properties.
        minimal_fdt_bytes = b'\xd0\x0d\xfe\xed\x00\x00\x00\x01\x00\x00\x00\x28\x00\x00\x00\x30\x00\x00\x00\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
        fdt = Fdt(dtb=minimal_fdt_bytes)
        print("Loaded minimal FDT from bytes.")

    except Exception as e:
        print(f"Could not create dummy DTB or load minimal FDT bytes: {e}")
        print("Skipping quickstart example as no valid DTB could be loaded.")
        exit()
else:
    try:
        fdt = Fdt(filename=dummy_dtb_path)
        print(f"Loaded FDT from file: {dummy_dtb_path}")
    except Exception as e:
        print(f"Error loading {dummy_dtb_path}: {e}")
        print("Skipping quickstart example due to DTB loading error.")
        exit()

# Get the root node
root_node = fdt.get_node('/')
if root_node:
    print(f"Root node name: {root_node.name}")

    # Walk the tree (if there are any nodes in the loaded FDT)
    print("\nWalking FDT nodes:")
    found_nodes = False
    for node in fdt.walk():
        print(f"  Node: {node.name} (path: {node.path})")
        for prop in node.properties:
            # Property values can be bytes, strings, or integers
            value = prop.value
            if isinstance(value, bytes):
                try:
                    value = value.decode('utf-8').strip('\x00') # Try decoding if it's a string
                except UnicodeDecodeError:
                    pass # Keep as bytes if not a valid utf-8 string
            print(f"    Property: {prop.name} = {value}")
        found_nodes = True
    if not found_nodes:
        print("  No nodes found in the FDT (might be a minimal FDT header).")
else:
    print("Could not get root node.")

# Example of getting a specific node and property (if they exist)
# This assumes a more complex DTB than the minimal header.
# For a real DTB, you might look for '/chosen' or '/aliases'
chosen_node = fdt.get_node('/chosen')
if chosen_node:
    print(f"\nFound node: {chosen_node.path}")
    bootargs_prop = chosen_node.get_property('bootargs')
    if bootargs_prop:
        print(f"  Bootargs: {bootargs_prop.value.decode('utf-8')}")
    else:
        print("  'bootargs' property not found in /chosen.")
else:
    print("Node '/chosen' not found (this is common for minimal DTBs).")

view raw JSON →