libfdt.i_shipped 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. /* SPDX-License-Identifier: GPL-2.0+ OR BSD-2-Clause */
  2. /*
  3. * pylibfdt - Flat Device Tree manipulation in Python
  4. * Copyright (C) 2017 Google, Inc.
  5. * Written by Simon Glass <sjg@chromium.org>
  6. */
  7. %module libfdt
  8. %include <stdint.i>
  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 subnode_offset(self, parentoffset, name, quiet=()):
  104. """Get the offset of a named subnode
  105. Args:
  106. parentoffset: Offset of the parent node to check
  107. name: Name of the required subnode, e.g. 'subnode@1'
  108. quiet: Errors to ignore (empty to raise on all errors)
  109. Returns:
  110. The node offset of the found node, if any
  111. Raises
  112. FdtException if there is no node with that name, or other error
  113. """
  114. return check_err(fdt_subnode_offset(self._fdt, parentoffset, name),
  115. quiet)
  116. def path_offset(self, path, quiet=()):
  117. """Get the offset for a given path
  118. Args:
  119. path: Path to the required node, e.g. '/node@3/subnode@1'
  120. quiet: Errors to ignore (empty to raise on all errors)
  121. Returns:
  122. Node offset
  123. Raises
  124. FdtException if the path is not valid or not found
  125. """
  126. return check_err(fdt_path_offset(self._fdt, path), quiet)
  127. def first_property_offset(self, nodeoffset, quiet=()):
  128. """Get the offset of the first property in a node offset
  129. Args:
  130. nodeoffset: Offset to the node to check
  131. quiet: Errors to ignore (empty to raise on all errors)
  132. Returns:
  133. Offset of the first property
  134. Raises
  135. FdtException if the associated node has no properties, or some
  136. other error occurred
  137. """
  138. return check_err(fdt_first_property_offset(self._fdt, nodeoffset),
  139. quiet)
  140. def next_property_offset(self, prop_offset, quiet=()):
  141. """Get the next property in a node
  142. Args:
  143. prop_offset: Offset of the previous property
  144. quiet: Errors to ignore (empty to raise on all errors)
  145. Returns:
  146. Offset of the next property
  147. Raises:
  148. FdtException if the associated node has no more properties, or
  149. some other error occurred
  150. """
  151. return check_err(fdt_next_property_offset(self._fdt, prop_offset),
  152. quiet)
  153. def get_name(self, nodeoffset):
  154. """Get the name of a node
  155. Args:
  156. nodeoffset: Offset of node to check
  157. Returns:
  158. Node name
  159. Raises:
  160. FdtException on error (e.g. nodeoffset is invalid)
  161. """
  162. return check_err_null(fdt_get_name(self._fdt, nodeoffset))[0]
  163. def get_property_by_offset(self, prop_offset, quiet=()):
  164. """Obtains a property that can be examined
  165. Args:
  166. prop_offset: Offset of property (e.g. from first_property_offset())
  167. quiet: Errors to ignore (empty to raise on all errors)
  168. Returns:
  169. Property object, or None if not found
  170. Raises:
  171. FdtException on error (e.g. invalid prop_offset or device
  172. tree format)
  173. """
  174. pdata = check_err_null(
  175. fdt_get_property_by_offset(self._fdt, prop_offset), quiet)
  176. if isinstance(pdata, (int)):
  177. return pdata
  178. return Property(pdata[0], pdata[1])
  179. def first_subnode(self, nodeoffset, quiet=()):
  180. """Find the first subnode of a parent node
  181. Args:
  182. nodeoffset: Node offset of parent node
  183. quiet: Errors to ignore (empty to raise on all errors)
  184. Returns:
  185. The offset of the first subnode, if any
  186. Raises:
  187. FdtException if no subnode found or other error occurs
  188. """
  189. return check_err(fdt_first_subnode(self._fdt, nodeoffset), quiet)
  190. def next_subnode(self, nodeoffset, quiet=()):
  191. """Find the next subnode
  192. Args:
  193. nodeoffset: Node offset of previous subnode
  194. quiet: Errors to ignore (empty to raise on all errors)
  195. Returns:
  196. The offset of the next subnode, if any
  197. Raises:
  198. FdtException if no more subnode found or other error occurs
  199. """
  200. return check_err(fdt_next_subnode(self._fdt, nodeoffset), quiet)
  201. def totalsize(self):
  202. """Return the total size of the device tree
  203. Returns:
  204. Total tree size in bytes
  205. """
  206. return check_err(fdt_totalsize(self._fdt))
  207. def off_dt_struct(self):
  208. """Return the start of the device tree struct area
  209. Returns:
  210. Start offset of struct area
  211. """
  212. return check_err(fdt_off_dt_struct(self._fdt))
  213. def pack(self, quiet=()):
  214. """Pack the device tree to remove unused space
  215. This adjusts the tree in place.
  216. Args:
  217. quiet: Errors to ignore (empty to raise on all errors)
  218. Raises:
  219. FdtException if any error occurs
  220. """
  221. return check_err(fdt_pack(self._fdt), quiet)
  222. def delprop(self, nodeoffset, prop_name):
  223. """Delete a property from a node
  224. Args:
  225. nodeoffset: Node offset containing property to delete
  226. prop_name: Name of property to delete
  227. Raises:
  228. FdtError if the property does not exist, or another error occurs
  229. """
  230. return check_err(fdt_delprop(self._fdt, nodeoffset, prop_name))
  231. def getprop(self, nodeoffset, prop_name, quiet=()):
  232. """Get a property from a node
  233. Args:
  234. nodeoffset: Node offset containing property to get
  235. prop_name: Name of property to get
  236. quiet: Errors to ignore (empty to raise on all errors)
  237. Returns:
  238. Value of property as a bytearray, or -ve error number
  239. Raises:
  240. FdtError if any error occurs (e.g. the property is not found)
  241. """
  242. pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name),
  243. quiet)
  244. if isinstance(pdata, (int)):
  245. return pdata
  246. return bytearray(pdata[0])
  247. def get_phandle(self, nodeoffset):
  248. """Get the phandle of a node
  249. Args:
  250. nodeoffset: Node offset to check
  251. Returns:
  252. phandle of node, or 0 if the node has no phandle or another error
  253. occurs
  254. """
  255. return fdt_get_phandle(self._fdt, nodeoffset)
  256. def parent_offset(self, nodeoffset, quiet=()):
  257. """Get the offset of a node's parent
  258. Args:
  259. nodeoffset: Node offset to check
  260. quiet: Errors to ignore (empty to raise on all errors)
  261. Returns:
  262. The offset of the parent node, if any
  263. Raises:
  264. FdtException if no parent found or other error occurs
  265. """
  266. return check_err(fdt_parent_offset(self._fdt, nodeoffset), quiet)
  267. def node_offset_by_phandle(self, phandle, quiet=()):
  268. """Get the offset of a node with the given phandle
  269. Args:
  270. phandle: Phandle to search for
  271. quiet: Errors to ignore (empty to raise on all errors)
  272. Returns:
  273. The offset of node with that phandle, if any
  274. Raises:
  275. FdtException if no node found or other error occurs
  276. """
  277. return check_err(fdt_node_offset_by_phandle(self._fdt, phandle), quiet)
  278. class Property:
  279. """Holds a device tree property name and value.
  280. This holds a copy of a property taken from the device tree. It does not
  281. reference the device tree, so if anything changes in the device tree,
  282. a Property object will remain valid.
  283. Properties:
  284. name: Property name
  285. value: Proper value as a bytearray
  286. """
  287. def __init__(self, name, value):
  288. self.name = name
  289. self.value = value
  290. %}
  291. %rename(fdt_property) fdt_property_func;
  292. typedef int fdt32_t;
  293. %include "libfdt/fdt.h"
  294. %include "typemaps.i"
  295. /* Most functions don't change the device tree, so use a const void * */
  296. %typemap(in) (const void *)(const void *fdt) {
  297. if (!PyByteArray_Check($input)) {
  298. SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname"
  299. "', argument " "$argnum"" of type '" "$type""'");
  300. }
  301. $1 = (void *)PyByteArray_AsString($input);
  302. fdt = $1;
  303. fdt = fdt; /* avoid unused variable warning */
  304. }
  305. /* Some functions do change the device tree, so use void * */
  306. %typemap(in) (void *)(const void *fdt) {
  307. if (!PyByteArray_Check($input)) {
  308. SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname"
  309. "', argument " "$argnum"" of type '" "$type""'");
  310. }
  311. $1 = PyByteArray_AsString($input);
  312. fdt = $1;
  313. fdt = fdt; /* avoid unused variable warning */
  314. }
  315. %typemap(out) (struct fdt_property *) {
  316. PyObject *buff;
  317. if ($1) {
  318. resultobj = PyString_FromString(
  319. fdt_string(fdt1, fdt32_to_cpu($1->nameoff)));
  320. buff = PyByteArray_FromStringAndSize(
  321. (const char *)($1 + 1), fdt32_to_cpu($1->len));
  322. resultobj = SWIG_Python_AppendOutput(resultobj, buff);
  323. }
  324. }
  325. %apply int *OUTPUT { int *lenp };
  326. /* typemap used for fdt_getprop() */
  327. %typemap(out) (const void *) {
  328. if (!$1)
  329. $result = Py_None;
  330. else
  331. $result = Py_BuildValue("s#", $1, *arg4);
  332. }
  333. /* We have both struct fdt_property and a function fdt_property() */
  334. %warnfilter(302) fdt_property;
  335. /* These are macros in the header so have to be redefined here */
  336. int fdt_magic(const void *fdt);
  337. int fdt_totalsize(const void *fdt);
  338. int fdt_off_dt_struct(const void *fdt);
  339. int fdt_off_dt_strings(const void *fdt);
  340. int fdt_off_mem_rsvmap(const void *fdt);
  341. int fdt_version(const void *fdt);
  342. int fdt_last_comp_version(const void *fdt);
  343. int fdt_boot_cpuid_phys(const void *fdt);
  344. int fdt_size_dt_strings(const void *fdt);
  345. int fdt_size_dt_struct(const void *fdt);
  346. %include <../libfdt/libfdt.h>