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