fdt_util.py 5.9 KB
Newer Older
1
#!/usr/bin/python
2
# SPDX-License-Identifier: GPL-2.0+
3 4 5 6 7
#
# Copyright (C) 2016 Google, Inc
# Written by Simon Glass <sjg@chromium.org>
#

8 9 10
# Utility functions for reading from a device tree. Once the upstream pylibfdt
# implementation advances far enough, we should be able to drop these.

11
import os
12
import struct
13
import sys
14 15
import tempfile

S
Simon Glass 已提交
16 17
from patman import command
from patman import tools
18 19 20 21 22 23 24 25 26 27

def fdt32_to_cpu(val):
    """Convert a device tree cell to an integer

    Args:
        Value to convert (4-character string representing the cell value)

    Return:
        A native-endian integer value
    """
S
Simon Glass 已提交
28
    return struct.unpack('>I', val)[0]
29

30 31 32 33 34 35 36
def fdt_cells_to_cpu(val, cells):
    """Convert one or two cells to a long integer

    Args:
        Value to convert (array of one or more 4-character strings)

    Return:
S
Simon Glass 已提交
37
        A native-endian integer value
38
    """
39 40
    if not cells:
        return 0
S
Simon Glass 已提交
41
    out = int(fdt32_to_cpu(val[0]))
42 43 44 45
    if cells == 2:
        out = out << 32 | fdt32_to_cpu(val[1])
    return out

46
def EnsureCompiled(fname, tmpdir=None, capture_stderr=False):
47 48 49 50 51
    """Compile an fdt .dts source file into a .dtb binary blob if needed.

    Args:
        fname: Filename (if .dts it will be compiled). It not it will be
            left alone
52 53
        tmpdir: Temporary directory for output files, or None to use the
            tools-module output directory
54 55 56 57 58 59 60 61

    Returns:
        Filename of resulting .dtb file
    """
    _, ext = os.path.splitext(fname)
    if ext != '.dts':
        return fname

62 63 64 65 66 67
    if tmpdir:
        dts_input = os.path.join(tmpdir, 'source.dts')
        dtb_output = os.path.join(tmpdir, 'source.dtb')
    else:
        dts_input = tools.GetOutputFilename('source.dts')
        dtb_output = tools.GetOutputFilename('source.dtb')
68 69 70 71 72 73 74 75 76 77 78 79 80 81

    search_paths = [os.path.join(os.getcwd(), 'include')]
    root, _ = os.path.splitext(fname)
    args = ['-E', '-P', '-x', 'assembler-with-cpp', '-D__ASSEMBLY__']
    args += ['-Ulinux']
    for path in search_paths:
        args.extend(['-I', path])
    args += ['-o', dts_input, fname]
    command.Run('cc', *args)

    # If we don't have a directory, put it in the tools tempdir
    search_list = []
    for path in search_paths:
        search_list.extend(['-i', path])
82 83
    args = ['-I', 'dts', '-o', dtb_output, '-O', 'dtb',
            '-W', 'no-unit_address_vs_reg']
84 85
    args.extend(search_list)
    args.append(dts_input)
86
    dtc = os.environ.get('DTC') or 'dtc'
87
    command.Run(dtc, *args, capture_stderr=capture_stderr)
88
    return dtb_output
89 90

def GetInt(node, propname, default=None):
91 92 93 94 95 96 97 98 99 100
    """Get an integer from a property

    Args:
        node: Node object to read from
        propname: property name to read
        default: Default value to use if the node/property do not exist

    Returns:
        Integer value read, or default if none
    """
101 102 103
    prop = node.props.get(propname)
    if not prop:
        return default
104 105
    if isinstance(prop.value, list):
        raise ValueError("Node '%s' property '%s' has list value: expecting "
106
                         "a single integer" % (node.name, propname))
107
    value = fdt32_to_cpu(prop.value)
108 109 110
    return value

def GetString(node, propname, default=None):
111 112 113 114 115 116 117 118 119 120
    """Get a string from a property

    Args:
        node: Node object to read from
        propname: property name to read
        default: Default value to use if the node/property do not exist

    Returns:
        String value read, or default if none
    """
121 122 123 124
    prop = node.props.get(propname)
    if not prop:
        return default
    value = prop.value
125 126
    if isinstance(value, list):
        raise ValueError("Node '%s' property '%s' has list value: expecting "
127 128 129 130
                         "a single string" % (node.name, propname))
    return value

def GetBool(node, propname, default=False):
131 132 133 134 135 136 137 138 139 140 141
    """Get an boolean from a property

    Args:
        node: Node object to read from
        propname: property name to read
        default: Default value to use if the node/property do not exist

    Returns:
        Boolean value read, or default if none (if you set this to True the
            function will always return True)
    """
142 143 144
    if propname in node.props:
        return True
    return default
145

146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
def GetByte(node, propname, default=None):
    """Get an byte from a property

    Args:
        node: Node object to read from
        propname: property name to read
        default: Default value to use if the node/property do not exist

    Returns:
        Byte value read, or default if none
    """
    prop = node.props.get(propname)
    if not prop:
        return default
    value = prop.value
    if isinstance(value, list):
        raise ValueError("Node '%s' property '%s' has list value: expecting "
                         "a single byte" % (node.name, propname))
    if len(value) != 1:
        raise ValueError("Node '%s' property '%s' has length %d, expecting %d" %
                         (node.name, propname, len(value), 1))
    return ord(value[0])

169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
def GetPhandleList(node, propname):
    """Get a list of phandles from a property

    Args:
        node: Node object to read from
        propname: property name to read

    Returns:
        List of phandles read, each an integer
    """
    prop = node.props.get(propname)
    if not prop:
        return None
    value = prop.value
    if not isinstance(value, list):
        value = [value]
    return [fdt32_to_cpu(v) for v in value]

187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
def GetDatatype(node, propname, datatype):
    """Get a value of a given type from a property

    Args:
        node: Node object to read from
        propname: property name to read
        datatype: Type to read (str or int)

    Returns:
        value read, or None if none

    Raises:
        ValueError if datatype is not str or int
    """
    if datatype == str:
        return GetString(node, propname)
    elif datatype == int:
        return GetInt(node, propname)
    raise ValueError("fdt_util internal error: Unknown data type '%s'" %
                     datatype)