xref: /rk3399_rockchip-uboot/tools/dtoc/fdt.py (revision bc1dea3656e55d91f7a3c1339d53fc9def3bbf31)
1a06a34b2SSimon Glass#!/usr/bin/python
2a06a34b2SSimon Glass#
3a06a34b2SSimon Glass# Copyright (C) 2016 Google, Inc
4a06a34b2SSimon Glass# Written by Simon Glass <sjg@chromium.org>
5a06a34b2SSimon Glass#
6a06a34b2SSimon Glass# SPDX-License-Identifier:      GPL-2.0+
7a06a34b2SSimon Glass#
8a06a34b2SSimon Glass
9a06a34b2SSimon Glassimport struct
10a06a34b2SSimon Glassimport sys
11a06a34b2SSimon Glass
12a06a34b2SSimon Glassimport fdt_util
13a06a34b2SSimon Glass
14a06a34b2SSimon Glass# This deals with a device tree, presenting it as an assortment of Node and
15a06a34b2SSimon Glass# Prop objects, representing nodes and properties, respectively. This file
16a06a34b2SSimon Glass# contains the base classes and defines the high-level API. Most of the
17a06a34b2SSimon Glass# implementation is in the FdtFallback and FdtNormal subclasses. See
18a06a34b2SSimon Glass# fdt_select.py for how to create an Fdt object.
19a06a34b2SSimon Glass
20*bc1dea36SSimon Glass# A list of types we support
21*bc1dea36SSimon Glass(TYPE_BYTE, TYPE_INT, TYPE_STRING, TYPE_BOOL) = range(4)
22*bc1dea36SSimon Glass
23a06a34b2SSimon Glassdef CheckErr(errnum, msg):
24a06a34b2SSimon Glass    if errnum:
25a06a34b2SSimon Glass        raise ValueError('Error %d: %s: %s' %
26a06a34b2SSimon Glass            (errnum, libfdt.fdt_strerror(errnum), msg))
27a06a34b2SSimon Glass
28a06a34b2SSimon Glassclass PropBase:
29a06a34b2SSimon Glass    """A device tree property
30a06a34b2SSimon Glass
31a06a34b2SSimon Glass    Properties:
32a06a34b2SSimon Glass        name: Property name (as per the device tree)
33a06a34b2SSimon Glass        value: Property value as a string of bytes, or a list of strings of
34a06a34b2SSimon Glass            bytes
35a06a34b2SSimon Glass        type: Value type
36a06a34b2SSimon Glass    """
37a06a34b2SSimon Glass    def __init__(self, node, offset, name):
38a06a34b2SSimon Glass        self._node = node
39a06a34b2SSimon Glass        self._offset = offset
40a06a34b2SSimon Glass        self.name = name
41a06a34b2SSimon Glass        self.value = None
42a06a34b2SSimon Glass
43*bc1dea36SSimon Glass    def BytesToValue(self, bytes):
44*bc1dea36SSimon Glass        """Converts a string of bytes into a type and value
45*bc1dea36SSimon Glass
46*bc1dea36SSimon Glass        Args:
47*bc1dea36SSimon Glass            A string containing bytes
48*bc1dea36SSimon Glass
49*bc1dea36SSimon Glass        Return:
50*bc1dea36SSimon Glass            A tuple:
51*bc1dea36SSimon Glass                Type of data
52*bc1dea36SSimon Glass                Data, either a single element or a list of elements. Each element
53*bc1dea36SSimon Glass                is one of:
54*bc1dea36SSimon Glass                    TYPE_STRING: string value from the property
55*bc1dea36SSimon Glass                    TYPE_INT: a byte-swapped integer stored as a 4-byte string
56*bc1dea36SSimon Glass                    TYPE_BYTE: a byte stored as a single-byte string
57*bc1dea36SSimon Glass        """
58*bc1dea36SSimon Glass        size = len(bytes)
59*bc1dea36SSimon Glass        strings = bytes.split('\0')
60*bc1dea36SSimon Glass        is_string = True
61*bc1dea36SSimon Glass        count = len(strings) - 1
62*bc1dea36SSimon Glass        if count > 0 and not strings[-1]:
63*bc1dea36SSimon Glass            for string in strings[:-1]:
64*bc1dea36SSimon Glass                if not string:
65*bc1dea36SSimon Glass                    is_string = False
66*bc1dea36SSimon Glass                    break
67*bc1dea36SSimon Glass                for ch in string:
68*bc1dea36SSimon Glass                    if ch < ' ' or ch > '~':
69*bc1dea36SSimon Glass                        is_string = False
70*bc1dea36SSimon Glass                        break
71*bc1dea36SSimon Glass        else:
72*bc1dea36SSimon Glass            is_string = False
73*bc1dea36SSimon Glass        if is_string:
74*bc1dea36SSimon Glass            if count == 1:
75*bc1dea36SSimon Glass                return TYPE_STRING, strings[0]
76*bc1dea36SSimon Glass            else:
77*bc1dea36SSimon Glass                return TYPE_STRING, strings[:-1]
78*bc1dea36SSimon Glass        if size % 4:
79*bc1dea36SSimon Glass            if size == 1:
80*bc1dea36SSimon Glass                return TYPE_BYTE, bytes[0]
81*bc1dea36SSimon Glass            else:
82*bc1dea36SSimon Glass                return TYPE_BYTE, list(bytes)
83*bc1dea36SSimon Glass        val = []
84*bc1dea36SSimon Glass        for i in range(0, size, 4):
85*bc1dea36SSimon Glass            val.append(bytes[i:i + 4])
86*bc1dea36SSimon Glass        if size == 4:
87*bc1dea36SSimon Glass            return TYPE_INT, val[0]
88*bc1dea36SSimon Glass        else:
89*bc1dea36SSimon Glass            return TYPE_INT, val
90*bc1dea36SSimon Glass
91*bc1dea36SSimon Glass    def GetEmpty(self, type):
92*bc1dea36SSimon Glass        """Get an empty / zero value of the given type
93*bc1dea36SSimon Glass
94*bc1dea36SSimon Glass        Returns:
95*bc1dea36SSimon Glass            A single value of the given type
96*bc1dea36SSimon Glass        """
97*bc1dea36SSimon Glass        if type == TYPE_BYTE:
98*bc1dea36SSimon Glass            return chr(0)
99*bc1dea36SSimon Glass        elif type == TYPE_INT:
100*bc1dea36SSimon Glass            return struct.pack('<I', 0);
101*bc1dea36SSimon Glass        elif type == TYPE_STRING:
102*bc1dea36SSimon Glass            return ''
103*bc1dea36SSimon Glass        else:
104*bc1dea36SSimon Glass            return True
105*bc1dea36SSimon Glass
106a06a34b2SSimon Glassclass NodeBase:
107a06a34b2SSimon Glass    """A device tree node
108a06a34b2SSimon Glass
109a06a34b2SSimon Glass    Properties:
110a06a34b2SSimon Glass        offset: Integer offset in the device tree
111a06a34b2SSimon Glass        name: Device tree node tname
112a06a34b2SSimon Glass        path: Full path to node, along with the node name itself
113a06a34b2SSimon Glass        _fdt: Device tree object
114a06a34b2SSimon Glass        subnodes: A list of subnodes for this node, each a Node object
115a06a34b2SSimon Glass        props: A dict of properties for this node, each a Prop object.
116a06a34b2SSimon Glass            Keyed by property name
117a06a34b2SSimon Glass    """
118a06a34b2SSimon Glass    def __init__(self, fdt, offset, name, path):
119a06a34b2SSimon Glass        self._fdt = fdt
120a06a34b2SSimon Glass        self._offset = offset
121a06a34b2SSimon Glass        self.name = name
122a06a34b2SSimon Glass        self.path = path
123a06a34b2SSimon Glass        self.subnodes = []
124a06a34b2SSimon Glass        self.props = {}
125a06a34b2SSimon Glass
126a06a34b2SSimon Glassclass Fdt:
127a06a34b2SSimon Glass    """Provides simple access to a flat device tree blob.
128a06a34b2SSimon Glass
129a06a34b2SSimon Glass    Properties:
130a06a34b2SSimon Glass      fname: Filename of fdt
131a06a34b2SSimon Glass      _root: Root of device tree (a Node object)
132a06a34b2SSimon Glass    """
133a06a34b2SSimon Glass    def __init__(self, fname):
134a06a34b2SSimon Glass        self._fname = fname
135