summaryrefslogtreecommitdiff
path: root/tools/dtoc/fdt.py
blob: 329d03cc6b743e7f1af13d5cfb84375f1715a989 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#!/usr/bin/python
#
# Copyright (C) 2016 Google, Inc
# Written by Simon Glass <sjg@chromium.org>
#
# SPDX-License-Identifier:      GPL-2.0+
#

import struct
import sys

import fdt_util

# This deals with a device tree, presenting it as an assortment of Node and
# Prop objects, representing nodes and properties, respectively. This file
# contains the base classes and defines the high-level API. Most of the
# implementation is in the FdtFallback and FdtNormal subclasses. See
# fdt_select.py for how to create an Fdt object.

# A list of types we support
(TYPE_BYTE, TYPE_INT, TYPE_STRING, TYPE_BOOL) = range(4)

def CheckErr(errnum, msg):
    if errnum:
        raise ValueError('Error %d: %s: %s' %
            (errnum, libfdt.fdt_strerror(errnum), msg))

class PropBase:
    """A device tree property

    Properties:
        name: Property name (as per the device tree)
        value: Property value as a string of bytes, or a list of strings of
            bytes
        type: Value type
    """
    def __init__(self, node, offset, name):
        self._node = node
        self._offset = offset
        self.name = name
        self.value = None

    def BytesToValue(self, bytes):
        """Converts a string of bytes into a type and value

        Args:
            A string containing bytes

        Return:
            A tuple:
                Type of data
                Data, either a single element or a list of elements. Each element
                is one of:
                    TYPE_STRING: string value from the property
                    TYPE_INT: a byte-swapped integer stored as a 4-byte string
                    TYPE_BYTE: a byte stored as a single-byte string
        """
        size = len(bytes)
        strings = bytes.split('\0')
        is_string = True
        count = len(strings) - 1
        if count > 0 and not strings[-1]:
            for string in strings[:-1]:
                if not string:
                    is_string = False
                    break
                for ch in string:
                    if ch < ' ' or ch > '~':
                        is_string = False
                        break
        else:
            is_string = False
        if is_string:
            if count == 1:
                return TYPE_STRING, strings[0]
            else:
                return TYPE_STRING, strings[:-1]
        if size % 4:
            if size == 1:
                return TYPE_BYTE, bytes[0]
            else:
                return TYPE_BYTE, list(bytes)
        val = []
        for i in range(0, size, 4):
            val.append(bytes[i:i + 4])
        if size == 4:
            return TYPE_INT, val[0]
        else:
            return TYPE_INT, val

    def GetEmpty(self, type):
        """Get an empty / zero value of the given type

        Returns:
            A single value of the given type
        """
        if type == TYPE_BYTE:
            return chr(0)
        elif type == TYPE_INT:
            return struct.pack('<I', 0);
        elif type == TYPE_STRING:
            return ''
        else:
            return True

class NodeBase:
    """A device tree node

    Properties:
        offset: Integer offset in the device tree
        name: Device tree node tname
        path: Full path to node, along with the node name itself
        _fdt: Device tree object
        subnodes: A list of subnodes for this node, each a Node object
        props: A dict of properties for this node, each a Prop object.
            Keyed by property name
    """
    def __init__(self, fdt, offset, name, path):
        self._fdt = fdt
        self._offset = offset
        self.name = name
        self.path = path
        self.subnodes = []
        self.props = {}

class Fdt:
    """Provides simple access to a flat device tree blob.

    Properties:
      fname: Filename of fdt
      _root: Root of device tree (a Node object)
    """
    def __init__(self, fname):
        self._fname = fname