fdt_fallback.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  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. import command
  9. import fdt
  10. from fdt import Fdt, NodeBase, PropBase
  11. import fdt_util
  12. import sys
  13. # This deals with a device tree, presenting it as a list of Node and Prop
  14. # objects, representing nodes and properties, respectively.
  15. #
  16. # This implementation uses the fdtget tool to access the device tree, so it
  17. # is not very efficient for larger trees. The tool is called once for each
  18. # node and property in the tree.
  19. class Prop(PropBase):
  20. """A device tree property
  21. Properties:
  22. name: Property name (as per the device tree)
  23. value: Property value as a string of bytes, or a list of strings of
  24. bytes
  25. type: Value type
  26. """
  27. def __init__(self, node, name, byte_list_str):
  28. PropBase.__init__(self, node, 0, name)
  29. if not byte_list_str.strip():
  30. self.type = fdt.TYPE_BOOL
  31. return
  32. self.bytes = [chr(int(byte, 16))
  33. for byte in byte_list_str.strip().split(' ')]
  34. self.type, self.value = self.BytesToValue(''.join(self.bytes))
  35. class Node(NodeBase):
  36. """A device tree node
  37. Properties:
  38. name: Device tree node tname
  39. path: Full path to node, along with the node name itself
  40. _fdt: Device tree object
  41. subnodes: A list of subnodes for this node, each a Node object
  42. props: A dict of properties for this node, each a Prop object.
  43. Keyed by property name
  44. """
  45. def __init__(self, fdt, offset, name, path):
  46. NodeBase.__init__(self, fdt, offset, name, path)
  47. def Scan(self):
  48. """Scan a node's properties and subnodes
  49. This fills in the props and subnodes properties, recursively
  50. searching into subnodes so that the entire tree is built.
  51. """
  52. for name, byte_list_str in self._fdt.GetProps(self.path).iteritems():
  53. prop = Prop(self, name, byte_list_str)
  54. self.props[name] = prop
  55. for name in self._fdt.GetSubNodes(self.path):
  56. sep = '' if self.path[-1] == '/' else '/'
  57. path = self.path + sep + name
  58. node = Node(self._fdt, 0, name, path)
  59. self.subnodes.append(node)
  60. node.Scan()
  61. class FdtFallback(Fdt):
  62. """Provides simple access to a flat device tree blob using fdtget/fdtput
  63. Properties:
  64. See superclass
  65. """
  66. def __init__(self, fname):
  67. Fdt.__init__(self, fname)
  68. def Scan(self):
  69. """Scan a device tree, building up a tree of Node objects
  70. This fills in the self._root property
  71. """
  72. self._root = Node(self, 0, '/', '/')
  73. self._root.Scan()
  74. def GetRoot(self):
  75. """Get the root Node of the device tree
  76. Returns:
  77. The root Node object
  78. """
  79. return self._root
  80. def GetSubNodes(self, node):
  81. """Returns a list of sub-nodes of a given node
  82. Args:
  83. node: Node name to return children from
  84. Returns:
  85. List of children in the node (each a string node name)
  86. Raises:
  87. CmdError: if the node does not exist.
  88. """
  89. out = command.Output('fdtget', self._fname, '-l', node)
  90. return out.strip().splitlines()
  91. def GetProps(self, node, convert_dashes=False):
  92. """Get all properties from a node
  93. Args:
  94. node: full path to node name to look in
  95. convert_dashes: True to convert - to _ in node names
  96. Returns:
  97. A dictionary containing all the properties, indexed by node name.
  98. The entries are simply strings - no decoding of lists or numbers
  99. is done.
  100. Raises:
  101. CmdError: if the node does not exist.
  102. """
  103. out = command.Output('fdtget', self._fname, node, '-p')
  104. props = out.strip().splitlines()
  105. props_dict = {}
  106. for prop in props:
  107. name = prop
  108. if convert_dashes:
  109. prop = re.sub('-', '_', prop)
  110. props_dict[prop] = self.GetProp(node, name)
  111. return props_dict
  112. def GetProp(self, node, prop, default=None, typespec=None):
  113. """Get a property from a device tree.
  114. This looks up the given node and property, and returns the value as a
  115. string,
  116. If the node or property does not exist, this will return the default
  117. value.
  118. Args:
  119. node: Full path to node to look up.
  120. prop: Property name to look up.
  121. default: Default value to return if nothing is present in the fdt,
  122. or None to raise in this case. This will be converted to a
  123. string.
  124. typespec: Type character to use (None for default, 's' for string)
  125. Returns:
  126. string containing the property value.
  127. Raises:
  128. CmdError: if the property does not exist and no default is provided.
  129. """
  130. args = [self._fname, node, prop, '-t', 'bx']
  131. if default is not None:
  132. args += ['-d', str(default)]
  133. if typespec is not None:
  134. args += ['-t%s' % typespec]
  135. out = command.Output('fdtget', *args)
  136. return out.strip()
  137. @classmethod
  138. def Node(self, fdt, offset, name, path):
  139. """Create a new node
  140. This is used by Fdt.Scan() to create a new node using the correct
  141. class.
  142. Args:
  143. fdt: Fdt object
  144. offset: Offset of node
  145. name: Node name
  146. path: Full path to node
  147. """
  148. node = Node(fdt, offset, name, path)
  149. return node