libfdt.i 11 KB

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