{"id":10106,"library":"pylibfdt","title":"Python FDT Bindings","description":"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.","status":"active","version":"1.7.2.post1","language":"en","source_language":"en","source_url":"https://github.com/dtb-stuff/pylibfdt","tags":["device-tree","fdt","libfdt","dtb","hardware","embedded"],"install":[{"cmd":"pip install pylibfdt","lang":"bash","label":"Install pylibfdt"}],"dependencies":[],"imports":[{"symbol":"Fdt","correct":"from pylibfdt import Fdt"}],"quickstart":{"code":"from pylibfdt import Fdt\nimport os\n\n# For demonstration, create a dummy DTB file if it doesn't exist\n# In a real scenario, you'd load an existing .dtb file\ndummy_dtb_path = \"example.dtb\"\nif not os.path.exists(dummy_dtb_path):\n    # This is a very minimal valid DTB structure (version 16, no nodes)\n    # Actual DTBs are much more complex. This only serves to avoid FdtException on a non-existent file.\n    # A true example would require external tools to generate a valid DTB.\n    # For real use, ensure 'example.dtb' is a valid DTB created by dtc.\n    try:\n        # Attempt to create a placeholder or indicate requirement for a real DTB\n        # Cannot easily generate a valid DTB from scratch within Python for quickstart.\n        # Assume a valid 'test.dtb' exists for proper execution.\n        print(f\"Please ensure a valid DTB file named '{dummy_dtb_path}' exists for a meaningful quickstart.\")\n        # For strict runnable, we will use a byte literal that is a minimal valid FDT header.\n        # This will load, but won't have any actual nodes or properties.\n        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'\n        fdt = Fdt(dtb=minimal_fdt_bytes)\n        print(\"Loaded minimal FDT from bytes.\")\n\n    except Exception as e:\n        print(f\"Could not create dummy DTB or load minimal FDT bytes: {e}\")\n        print(\"Skipping quickstart example as no valid DTB could be loaded.\")\n        exit()\nelse:\n    try:\n        fdt = Fdt(filename=dummy_dtb_path)\n        print(f\"Loaded FDT from file: {dummy_dtb_path}\")\n    except Exception as e:\n        print(f\"Error loading {dummy_dtb_path}: {e}\")\n        print(\"Skipping quickstart example due to DTB loading error.\")\n        exit()\n\n# Get the root node\nroot_node = fdt.get_node('/')\nif root_node:\n    print(f\"Root node name: {root_node.name}\")\n\n    # Walk the tree (if there are any nodes in the loaded FDT)\n    print(\"\\nWalking FDT nodes:\")\n    found_nodes = False\n    for node in fdt.walk():\n        print(f\"  Node: {node.name} (path: {node.path})\")\n        for prop in node.properties:\n            # Property values can be bytes, strings, or integers\n            value = prop.value\n            if isinstance(value, bytes):\n                try:\n                    value = value.decode('utf-8').strip('\\x00') # Try decoding if it's a string\n                except UnicodeDecodeError:\n                    pass # Keep as bytes if not a valid utf-8 string\n            print(f\"    Property: {prop.name} = {value}\")\n        found_nodes = True\n    if not found_nodes:\n        print(\"  No nodes found in the FDT (might be a minimal FDT header).\")\nelse:\n    print(\"Could not get root node.\")\n\n# Example of getting a specific node and property (if they exist)\n# This assumes a more complex DTB than the minimal header.\n# For a real DTB, you might look for '/chosen' or '/aliases'\nchosen_node = fdt.get_node('/chosen')\nif chosen_node:\n    print(f\"\\nFound node: {chosen_node.path}\")\n    bootargs_prop = chosen_node.get_property('bootargs')\n    if bootargs_prop:\n        print(f\"  Bootargs: {bootargs_prop.value.decode('utf-8')}\")\n    else:\n        print(\"  'bootargs' property not found in /chosen.\")\nelse:\n    print(\"Node '/chosen' not found (this is common for minimal DTBs).\")","lang":"python","description":"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."},"warnings":[{"fix":"Always check `isinstance(prop.value, bytes)` and decode/process accordingly. Example: `prop.value.decode('utf-8').strip('\\x00')`.","message":"Property values accessed via `prop.value` can be of type `bytes`, `int`, or `str` depending on the property definition in the DTB. You often need to explicitly `decode('utf-8')` byte values if expecting a string, and handle `strip('\\x00')` for null-terminated strings.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Always include `if node:` or `if prop:` checks before using the returned object. Example: `node = fdt.get_node('/path'); if node: print(node.name)`.","message":"Methods like `fdt.get_node()` and `node.get_property()` return `None` if the requested node or property does not exist. Failing to check for `None` before attempting to access attributes (e.g., `node.name`, `prop.value`) will result in an `AttributeError`.","severity":"gotcha","affected_versions":"All versions"},{"fix":"On Debian/Ubuntu: `sudo apt-get install libfdt-dev`. On Fedora: `sudo dnf install libfdt-devel`. Consult your OS package manager for `libfdt-dev` or similar.","message":"When installing `pylibfdt` from source (e.g., if no wheel is available for your platform/Python version), you will need the `libfdt` C library development headers installed on your system. This is a common requirement for Python bindings to C libraries.","severity":"gotcha","affected_versions":"All versions (when compiling from source)"}],"env_vars":null,"last_verified":"2026-04-17T00:00:00.000Z","next_check":"2026-07-16T00:00:00.000Z","problems":[{"fix":"Ensure `pylibfdt` is installed in your active environment: `pip install pylibfdt`.","cause":"`pylibfdt` is not installed, or the current Python environment does not have it installed.","error":"ImportError: cannot import name 'Fdt' from 'pylibfdt'"},{"fix":"Verify that the input file path is correct and points to a properly formatted `.dtb` file, usually generated by the Device Tree Compiler (`dtc`). If providing bytes, ensure they represent a valid DTB.","cause":"The file or bytes provided to `Fdt()` is not a valid Device Tree Blob (DTB) and does not start with the expected magic number (`0xd00dfeed`).","error":"pylibfdt.FdtException: Fdt file magic missing"},{"fix":"Always check if the property object is not `None` before attempting to access its attributes. Example: `prop = node.get_property('some_name'); if prop: print(prop.value)`.","cause":"You attempted to access `.value` on a property object that was `None`. This typically happens when `node.get_property('some_name')` returned `None` because the property does not exist for that node.","error":"AttributeError: 'NoneType' object has no attribute 'value'"}]}