libfdt.i 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. /*
  2. * pylibfdt - Flat Device Tree manipulation in Python
  3. * Copyright (C) 2017 Google, Inc.
  4. * Written by Simon Glass <sjg@chromium.org>
  5. *
  6. * SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause
  7. */
  8. %module libfdt
  9. %include <stdint.i>
  10. %{
  11. #define SWIG_FILE_WITH_INIT
  12. #include "libfdt.h"
  13. %}
  14. %pythoncode %{
  15. import struct
  16. # Error codes, corresponding to FDT_ERR_... in libfdt.h
  17. (NOTFOUND,
  18. EXISTS,
  19. NOSPACE,
  20. BADOFFSET,
  21. BADPATH,
  22. BADPHANDLE,
  23. BADSTATE,
  24. TRUNCATED,
  25. BADMAGIC,
  26. BADVERSION,
  27. BADSTRUCTURE,
  28. BADLAYOUT,
  29. INTERNAL,
  30. BADNCELLS,
  31. BADVALUE,
  32. BADOVERLAY,
  33. NOPHANDLES) = QUIET_ALL = range(1, 18)
  34. # QUIET_ALL can be passed as the 'quiet' parameter to avoid exceptions
  35. # altogether. All # functions passed this value will return an error instead
  36. # of raising an exception.
  37. # Pass this as the 'quiet' parameter to return -ENOTFOUND on NOTFOUND errors,
  38. # instead of raising an exception.
  39. QUIET_NOTFOUND = (NOTFOUND,)
  40. class FdtException(Exception):
  41. """An exception caused by an error such as one of the codes above"""
  42. def __init__(self, err):
  43. self.err = err
  44. def __str__(self):
  45. return 'pylibfdt error %d: %s' % (self.err, fdt_strerror(self.err))
  46. def strerror(fdt_err):
  47. """Get the string for an error number
  48. Args:
  49. fdt_err: Error number (-ve)
  50. Returns:
  51. String containing the associated error
  52. """
  53. return fdt_strerror(fdt_err)
  54. def check_err(val, quiet=()):
  55. """Raise an error if the return value is -ve
  56. This is used to check for errors returned by libfdt C functions.
  57. Args:
  58. val: Return value from a libfdt function
  59. quiet: Errors to ignore (empty to raise on all errors)
  60. Returns:
  61. val if val >= 0
  62. Raises
  63. FdtException if val < 0
  64. """
  65. if val < 0:
  66. if -val not in quiet:
  67. raise FdtException(val)
  68. return val
  69. def check_err_null(val, quiet=()):
  70. """Raise an error if the return value is NULL
  71. This is used to check for a NULL return value from certain libfdt C
  72. functions
  73. Args:
  74. val: Return value from a libfdt function
  75. quiet: Errors to ignore (empty to raise on all errors)
  76. Returns:
  77. val if val is a list, None if not
  78. Raises
  79. FdtException if val indicates an error was reported and the error
  80. is not in @quiet.
  81. """
  82. # Normally a list is returned which contains the data and its length.
  83. # If we get just an integer error code, it means the function failed.
  84. if not isinstance(val, list):
  85. if -val not in quiet:
  86. raise FdtException(val)
  87. return val
  88. class Fdt:
  89. """Device tree class, supporting all operations
  90. The Fdt object is created is created from a device tree binary file,
  91. e.g. with something like:
  92. fdt = Fdt(open("filename.dtb").read())
  93. Operations can then be performed using the methods in this class. Each
  94. method xxx(args...) corresponds to a libfdt function fdt_xxx(fdt, args...).
  95. All methods raise an FdtException if an error occurs. To avoid this
  96. behaviour a 'quiet' parameter is provided for some functions. This
  97. defaults to empty, but you can pass a list of errors that you expect.
  98. If one of these errors occurs, the function will return an error number
  99. (e.g. -NOTFOUND).
  100. """
  101. def __init__(self, data):
  102. self._fdt = bytearray(data)
  103. check_err(fdt_check_header(self._fdt));
  104. def path_offset(self, path, quiet=()):
  105. """Get the offset for a given path
  106. Args:
  107. path: Path to the required node, e.g. '/node@3/subnode@1'
  108. quiet: Errors to ignore (empty to raise on all errors)
  109. Returns:
  110. Node offset
  111. Raises
  112. FdtException if the path is not valid or not found
  113. """
  114. return check_err(fdt_path_offset(self._fdt, path), quiet)
  115. def first_property_offset(self, nodeoffset, quiet=()):
  116. """Get the offset of the first property in a node offset
  117. Args:
  118. nodeoffset: Offset to the node to check
  119. quiet: Errors to ignore (empty to raise on all errors)
  120. Returns:
  121. Offset of the first property
  122. Raises
  123. FdtException if the associated node has no properties, or some
  124. other error occurred
  125. """
  126. return check_err(fdt_first_property_offset(self._fdt, nodeoffset),
  127. quiet)
  128. def next_property_offset(self, prop_offset, quiet=()):
  129. """Get the next property in a node
  130. Args:
  131. prop_offset: Offset of the previous property
  132. quiet: Errors to ignore (empty to raise on all errors)
  133. Returns:
  134. Offset of the next property
  135. Raises:
  136. FdtException if the associated node has no more properties, or
  137. some other error occurred
  138. """
  139. return check_err(fdt_next_property_offset(self._fdt, prop_offset),
  140. quiet)
  141. def get_name(self, nodeoffset):
  142. """Get the name of a node
  143. Args:
  144. nodeoffset: Offset of node to check
  145. Returns:
  146. Node name
  147. Raises:
  148. FdtException on error (e.g. nodeoffset is invalid)
  149. """
  150. return check_err_null(fdt_get_name(self._fdt, nodeoffset))[0]
  151. def get_property_by_offset(self, prop_offset, quiet=()):
  152. """Obtains a property that can be examined
  153. Args:
  154. prop_offset: Offset of property (e.g. from first_property_offset())
  155. quiet: Errors to ignore (empty to raise on all errors)
  156. Returns:
  157. Property object, or None if not found
  158. Raises:
  159. FdtException on error (e.g. invalid prop_offset or device
  160. tree format)
  161. """
  162. pdata = check_err_null(
  163. fdt_get_property_by_offset(self._fdt, prop_offset), quiet)
  164. if isinstance(pdata, (int)):
  165. return pdata
  166. return Property(pdata[0], pdata[1])
  167. def first_subnode(self, nodeoffset, quiet=()):
  168. """Find the first subnode of a parent node
  169. Args:
  170. nodeoffset: Node offset of parent node
  171. quiet: Errors to ignore (empty to raise on all errors)
  172. Returns:
  173. The offset of the first subnode, if any
  174. Raises:
  175. FdtException if no subnode found or other error occurs
  176. """
  177. return check_err(fdt_first_subnode(self._fdt, nodeoffset), quiet)
  178. def next_subnode(self, nodeoffset, quiet=()):
  179. """Find the next subnode
  180. Args:
  181. nodeoffset: Node offset of previous subnode
  182. quiet: Errors to ignore (empty to raise on all errors)
  183. Returns:
  184. The offset of the next subnode, if any
  185. Raises:
  186. FdtException if no more subnode found or other error occurs
  187. """
  188. return check_err(fdt_next_subnode(self._fdt, nodeoffset), quiet)
  189. def totalsize(self):
  190. """Return the total size of the device tree
  191. Returns:
  192. Total tree size in bytes
  193. """
  194. return check_err(fdt_totalsize(self._fdt))
  195. def off_dt_struct(self):
  196. """Return the start of the device tree struct area
  197. Returns:
  198. Start offset of struct area
  199. """
  200. return check_err(fdt_off_dt_struct(self._fdt))
  201. def pack(self, quiet=()):
  202. """Pack the device tree to remove unused space
  203. This adjusts the tree in place.
  204. Args:
  205. quiet: Errors to ignore (empty to raise on all errors)
  206. Raises:
  207. FdtException if any error occurs
  208. """
  209. return check_err(fdt_pack(self._fdt), quiet)
  210. def delprop(self, nodeoffset, prop_name):
  211. """Delete a property from a node
  212. Args:
  213. nodeoffset: Node offset containing property to delete
  214. prop_name: Name of property to delete
  215. Raises:
  216. FdtError if the property does not exist, or another error occurs
  217. """
  218. return check_err(fdt_delprop(self._fdt, nodeoffset, prop_name))
  219. def getprop(self, nodeoffset, prop_name, quiet=()):
  220. """Get a property from a node
  221. Args:
  222. nodeoffset: Node offset containing property to get
  223. prop_name: Name of property to get
  224. quiet: Errors to ignore (empty to raise on all errors)
  225. Returns:
  226. Value of property as a bytearray, or -ve error number
  227. Raises:
  228. FdtError if any error occurs (e.g. the property is not found)
  229. """
  230. pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name),
  231. quiet)
  232. if isinstance(pdata, (int)):
  233. return pdata
  234. return bytearray(pdata[0])
  235. class Property:
  236. """Holds a device tree property name and value.
  237. This holds a copy of a property taken from the device tree. It does not
  238. reference the device tree, so if anything changes in the device tree,
  239. a Property object will remain valid.
  240. Properties:
  241. name: Property name
  242. value: Proper value as a bytearray
  243. """
  244. def __init__(self, name, value):
  245. self.name = name
  246. self.value = value
  247. %}
  248. %rename(fdt_property) fdt_property_func;
  249. typedef int fdt32_t;
  250. %include "libfdt/fdt.h"
  251. %include "typemaps.i"
  252. /* Most functions don't change the device tree, so use a const void * */
  253. %typemap(in) (const void *)(const void *fdt) {
  254. if (!PyByteArray_Check($input)) {
  255. SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname"
  256. "', argument " "$argnum"" of type '" "$type""'");
  257. }
  258. $1 = (void *)PyByteArray_AsString($input);
  259. fdt = $1;
  260. fdt = fdt; /* avoid unused variable warning */
  261. }
  262. /* Some functions do change the device tree, so use void * */
  263. %typemap(in) (void *)(const void *fdt) {
  264. if (!PyByteArray_Check($input)) {
  265. SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname"
  266. "', argument " "$argnum"" of type '" "$type""'");
  267. }
  268. $1 = PyByteArray_AsString($input);
  269. fdt = $1;
  270. fdt = fdt; /* avoid unused variable warning */
  271. }
  272. %typemap(out) (struct fdt_property *) {
  273. PyObject *buff;
  274. if ($1) {
  275. resultobj = PyString_FromString(
  276. fdt_string(fdt1, fdt32_to_cpu($1->nameoff)));
  277. buff = PyByteArray_FromStringAndSize(
  278. (const char *)($1 + 1), fdt32_to_cpu($1->len));
  279. resultobj = SWIG_Python_AppendOutput(resultobj, buff);
  280. }
  281. }
  282. %apply int *OUTPUT { int *lenp };
  283. /* typemap used for fdt_getprop() */
  284. %typemap(out) (const void *) {
  285. if (!$1)
  286. $result = Py_None;
  287. else
  288. $result = Py_BuildValue("s#", $1, *arg4);
  289. }
  290. /* We have both struct fdt_property and a function fdt_property() */
  291. %warnfilter(302) fdt_property;
  292. /* These are macros in the header so have to be redefined here */
  293. int fdt_magic(const void *fdt);
  294. int fdt_totalsize(const void *fdt);
  295. int fdt_off_dt_struct(const void *fdt);
  296. int fdt_off_dt_strings(const void *fdt);
  297. int fdt_off_mem_rsvmap(const void *fdt);
  298. int fdt_version(const void *fdt);
  299. int fdt_last_comp_version(const void *fdt);
  300. int fdt_boot_cpuid_phys(const void *fdt);
  301. int fdt_size_dt_strings(const void *fdt);
  302. int fdt_size_dt_struct(const void *fdt);
  303. %include <../libfdt/libfdt.h>