fdt_fallback.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  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).items():
  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. def DeleteProp(self, prop_name):
  62. """Delete a property of a node
  63. The property is deleted using fdtput.
  64. Args:
  65. prop_name: Name of the property to delete
  66. Raises:
  67. CommandError if the property does not exist
  68. """
  69. args = [self._fdt._fname, '-d', self.path, prop_name]
  70. command.Output('fdtput', *args)
  71. del self.props[prop_name]
  72. class FdtFallback(Fdt):
  73. """Provides simple access to a flat device tree blob using fdtget/fdtput
  74. Properties:
  75. See superclass
  76. """
  77. def __init__(self, fname):
  78. Fdt.__init__(self, fname)
  79. if self._fname:
  80. self._fname = fdt_util.EnsureCompiled(self._fname)
  81. def GetSubNodes(self, node):
  82. """Returns a list of sub-nodes of a given node
  83. Args:
  84. node: Node name to return children from
  85. Returns:
  86. List of children in the node (each a string node name)
  87. Raises:
  88. CmdError: if the node does not exist.
  89. """
  90. out = command.Output('fdtget', self._fname, '-l', node)
  91. return out.strip().splitlines()
  92. def GetProps(self, node):
  93. """Get all properties from a node
  94. Args:
  95. node: full path to node name to look in
  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. props_dict[prop] = self.GetProp(node, name)
  109. return props_dict
  110. def GetProp(self, node, prop, default=None, typespec=None):
  111. """Get a property from a device tree.
  112. This looks up the given node and property, and returns the value as a
  113. string,
  114. If the node or property does not exist, this will return the default
  115. value.
  116. Args:
  117. node: Full path to node to look up.
  118. prop: Property name to look up.
  119. default: Default value to return if nothing is present in the fdt,
  120. or None to raise in this case. This will be converted to a
  121. string.
  122. typespec: Type character to use (None for default, 's' for string)
  123. Returns:
  124. string containing the property value.
  125. Raises:
  126. CmdError: if the property does not exist and no default is provided.
  127. """
  128. args = [self._fname, node, prop, '-t', 'bx']
  129. if default is not None:
  130. args += ['-d', str(default)]
  131. if typespec is not None:
  132. args += ['-t', typespec]
  133. out = command.Output('fdtget', *args)
  134. return out.strip()
  135. @classmethod
  136. def Node(self, fdt, offset, name, path):
  137. """Create a new node
  138. This is used by Fdt.Scan() to create a new node using the correct
  139. class.
  140. Args:
  141. fdt: Fdt object
  142. offset: Offset of node
  143. name: Node name
  144. path: Full path to node
  145. """
  146. node = Node(fdt, offset, name, path)
  147. return node