fdt_util.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. #!/usr/bin/python
  2. # SPDX-License-Identifier: GPL-2.0+
  3. #
  4. # Copyright (C) 2016 Google, Inc
  5. # Written by Simon Glass <sjg@chromium.org>
  6. #
  7. # Utility functions for reading from a device tree. Once the upstream pylibfdt
  8. # implementation advances far enough, we should be able to drop these.
  9. import os
  10. import struct
  11. import sys
  12. import tempfile
  13. import command
  14. import tools
  15. VERSION3 = sys.version_info > (3, 0)
  16. def get_plain_bytes(val):
  17. """Handle Python 3 strings"""
  18. if isinstance(val, bytes):
  19. val = val.decode('utf-8')
  20. return val.encode('raw_unicode_escape')
  21. def fdt32_to_cpu(val):
  22. """Convert a device tree cell to an integer
  23. Args:
  24. Value to convert (4-character string representing the cell value)
  25. Return:
  26. A native-endian integer value
  27. """
  28. if VERSION3:
  29. # This code is not reached in Python 2
  30. val = get_plain_bytes(val) # pragma: no cover
  31. return struct.unpack('>I', val)[0]
  32. def fdt_cells_to_cpu(val, cells):
  33. """Convert one or two cells to a long integer
  34. Args:
  35. Value to convert (array of one or more 4-character strings)
  36. Return:
  37. A native-endian long value
  38. """
  39. if not cells:
  40. return 0
  41. out = long(fdt32_to_cpu(val[0]))
  42. if cells == 2:
  43. out = out << 32 | fdt32_to_cpu(val[1])
  44. return out
  45. def EnsureCompiled(fname, capture_stderr=False):
  46. """Compile an fdt .dts source file into a .dtb binary blob if needed.
  47. Args:
  48. fname: Filename (if .dts it will be compiled). It not it will be
  49. left alone
  50. Returns:
  51. Filename of resulting .dtb file
  52. """
  53. _, ext = os.path.splitext(fname)
  54. if ext != '.dts':
  55. return fname
  56. dts_input = tools.GetOutputFilename('source.dts')
  57. dtb_output = tools.GetOutputFilename('source.dtb')
  58. search_paths = [os.path.join(os.getcwd(), 'include')]
  59. root, _ = os.path.splitext(fname)
  60. args = ['-E', '-P', '-x', 'assembler-with-cpp', '-D__ASSEMBLY__']
  61. args += ['-Ulinux']
  62. for path in search_paths:
  63. args.extend(['-I', path])
  64. args += ['-o', dts_input, fname]
  65. command.Run('cc', *args)
  66. # If we don't have a directory, put it in the tools tempdir
  67. search_list = []
  68. for path in search_paths:
  69. search_list.extend(['-i', path])
  70. args = ['-I', 'dts', '-o', dtb_output, '-O', 'dtb',
  71. '-W', 'no-unit_address_vs_reg']
  72. args.extend(search_list)
  73. args.append(dts_input)
  74. dtc = os.environ.get('DTC') or 'dtc'
  75. command.Run(dtc, *args, capture_stderr=capture_stderr)
  76. return dtb_output
  77. def GetInt(node, propname, default=None):
  78. """Get an integer from a property
  79. Args:
  80. node: Node object to read from
  81. propname: property name to read
  82. default: Default value to use if the node/property do not exist
  83. Returns:
  84. Integer value read, or default if none
  85. """
  86. prop = node.props.get(propname)
  87. if not prop:
  88. return default
  89. if isinstance(prop.value, list):
  90. raise ValueError("Node '%s' property '%s' has list value: expecting "
  91. "a single integer" % (node.name, propname))
  92. value = fdt32_to_cpu(prop.value)
  93. return value
  94. def GetString(node, propname, default=None):
  95. """Get a string from a property
  96. Args:
  97. node: Node object to read from
  98. propname: property name to read
  99. default: Default value to use if the node/property do not exist
  100. Returns:
  101. String value read, or default if none
  102. """
  103. prop = node.props.get(propname)
  104. if not prop:
  105. return default
  106. value = prop.value
  107. if isinstance(value, list):
  108. raise ValueError("Node '%s' property '%s' has list value: expecting "
  109. "a single string" % (node.name, propname))
  110. return value
  111. def GetBool(node, propname, default=False):
  112. """Get an boolean from a property
  113. Args:
  114. node: Node object to read from
  115. propname: property name to read
  116. default: Default value to use if the node/property do not exist
  117. Returns:
  118. Boolean value read, or default if none (if you set this to True the
  119. function will always return True)
  120. """
  121. if propname in node.props:
  122. return True
  123. return default
  124. def GetByte(node, propname, default=None):
  125. """Get an byte from a property
  126. Args:
  127. node: Node object to read from
  128. propname: property name to read
  129. default: Default value to use if the node/property do not exist
  130. Returns:
  131. Byte value read, or default if none
  132. """
  133. prop = node.props.get(propname)
  134. if not prop:
  135. return default
  136. value = prop.value
  137. if isinstance(value, list):
  138. raise ValueError("Node '%s' property '%s' has list value: expecting "
  139. "a single byte" % (node.name, propname))
  140. if len(value) != 1:
  141. raise ValueError("Node '%s' property '%s' has length %d, expecting %d" %
  142. (node.name, propname, len(value), 1))
  143. return ord(value[0])
  144. def GetPhandleList(node, propname):
  145. """Get a list of phandles from a property
  146. Args:
  147. node: Node object to read from
  148. propname: property name to read
  149. Returns:
  150. List of phandles read, each an integer
  151. """
  152. prop = node.props.get(propname)
  153. if not prop:
  154. return None
  155. value = prop.value
  156. if not isinstance(value, list):
  157. value = [value]
  158. return [fdt32_to_cpu(v) for v in value]
  159. def GetDatatype(node, propname, datatype):
  160. """Get a value of a given type from a property
  161. Args:
  162. node: Node object to read from
  163. propname: property name to read
  164. datatype: Type to read (str or int)
  165. Returns:
  166. value read, or None if none
  167. Raises:
  168. ValueError if datatype is not str or int
  169. """
  170. if datatype == str:
  171. return GetString(node, propname)
  172. elif datatype == int:
  173. return GetInt(node, propname)
  174. raise ValueError("fdt_util internal error: Unknown data type '%s'" %
  175. datatype)