fdt_util.py 5.9 KB

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