Commit 3def0cf238e0df9736a4ce8fb54c1eb561a56ddd
1 parent
5c890238c4
Exists in
smarc_8mq_lf_v2020.04
and in
13 other branches
libfdt: Bring in proposed pylibfdt changes
This provides various patches sent to the devicetree-compiler mailing list to enhance the Python bindings. A final version of this patch may be created once upstreaming is complete, but if it takes too long, this can act as a placeholder. New pylibfdt features: - Support for most remaining, relevant libfdt functions - Support for sequential-write functions Changes are applied to existing U-Boot tools as needed. Signed-off-by: Simon Glass <sjg@chromium.org>
Showing 5 changed files with 663 additions and 71 deletions Side-by-side Diff
scripts/dtc/libfdt/libfdt.h
... | ... | @@ -1313,10 +1313,13 @@ |
1313 | 1313 | fdt64_t tmp = cpu_to_fdt64(val); |
1314 | 1314 | return fdt_property(fdt, name, &tmp, sizeof(tmp)); |
1315 | 1315 | } |
1316 | + | |
1317 | +#ifndef SWIG /* Not available in Python */ | |
1316 | 1318 | static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val) |
1317 | 1319 | { |
1318 | 1320 | return fdt_property_u32(fdt, name, val); |
1319 | 1321 | } |
1322 | +#endif | |
1320 | 1323 | |
1321 | 1324 | /** |
1322 | 1325 | * fdt_property_placeholder - add a new property and return a ptr to its value |
scripts/dtc/pylibfdt/libfdt.i_shipped
... | ... | @@ -12,6 +12,17 @@ |
12 | 12 | %{ |
13 | 13 | #define SWIG_FILE_WITH_INIT |
14 | 14 | #include "libfdt.h" |
15 | + | |
16 | +/* | |
17 | + * We rename this function here to avoid problems with swig, since we also have | |
18 | + * a struct called fdt_property. That struct causes swig to create a class in | |
19 | + * libfdt.py called fdt_property(), which confuses things. | |
20 | + */ | |
21 | +static int _fdt_property(void *fdt, const char *name, const char *val, int len) | |
22 | +{ | |
23 | + return fdt_property(fdt, name, val, len); | |
24 | +} | |
25 | + | |
15 | 26 | %} |
16 | 27 | |
17 | 28 | %pythoncode %{ |
... | ... | @@ -108,6 +119,7 @@ |
108 | 119 | raise FdtException(val) |
109 | 120 | return val |
110 | 121 | |
122 | + | |
111 | 123 | class Fdt: |
112 | 124 | """Device tree class, supporting all operations |
113 | 125 | |
... | ... | @@ -129,6 +141,163 @@ |
129 | 141 | self._fdt = bytearray(data) |
130 | 142 | check_err(fdt_check_header(self._fdt)); |
131 | 143 | |
144 | + def as_bytearray(self): | |
145 | + """Get the device tree contents as a bytearray | |
146 | + | |
147 | + This can be passed directly to libfdt functions that access a | |
148 | + const void * for the device tree. | |
149 | + | |
150 | + Returns: | |
151 | + bytearray containing the device tree | |
152 | + """ | |
153 | + return bytearray(self._fdt) | |
154 | + | |
155 | + def next_node(self, nodeoffset, depth, quiet=()): | |
156 | + """Find the next subnode | |
157 | + | |
158 | + Args: | |
159 | + nodeoffset: Node offset of previous node | |
160 | + depth: On input, the depth of the node at nodeoffset. On output, the | |
161 | + depth of the returned node | |
162 | + quiet: Errors to ignore (empty to raise on all errors) | |
163 | + | |
164 | + Returns: | |
165 | + The offset of the next node, if any | |
166 | + | |
167 | + Raises: | |
168 | + FdtException if no more nodes found or other error occurs | |
169 | + """ | |
170 | + return check_err(fdt_next_node(self._fdt, nodeoffset, depth), quiet) | |
171 | + | |
172 | + def first_subnode(self, nodeoffset, quiet=()): | |
173 | + """Find the first subnode of a parent node | |
174 | + | |
175 | + Args: | |
176 | + nodeoffset: Node offset of parent node | |
177 | + quiet: Errors to ignore (empty to raise on all errors) | |
178 | + | |
179 | + Returns: | |
180 | + The offset of the first subnode, if any | |
181 | + | |
182 | + Raises: | |
183 | + FdtException if no subnodes found or other error occurs | |
184 | + """ | |
185 | + return check_err(fdt_first_subnode(self._fdt, nodeoffset), quiet) | |
186 | + | |
187 | + def next_subnode(self, nodeoffset, quiet=()): | |
188 | + """Find the next subnode | |
189 | + | |
190 | + Args: | |
191 | + nodeoffset: Node offset of previous subnode | |
192 | + quiet: Errors to ignore (empty to raise on all errors) | |
193 | + | |
194 | + Returns: | |
195 | + The offset of the next subnode, if any | |
196 | + | |
197 | + Raises: | |
198 | + FdtException if no more subnodes found or other error occurs | |
199 | + """ | |
200 | + return check_err(fdt_next_subnode(self._fdt, nodeoffset), quiet) | |
201 | + | |
202 | + def magic(self): | |
203 | + """Return the magic word from the header | |
204 | + | |
205 | + Returns: | |
206 | + Magic word | |
207 | + """ | |
208 | + return fdt_magic(self._fdt) & 0xffffffff | |
209 | + | |
210 | + def totalsize(self): | |
211 | + """Return the total size of the device tree | |
212 | + | |
213 | + Returns: | |
214 | + Total tree size in bytes | |
215 | + """ | |
216 | + return check_err(fdt_totalsize(self._fdt)) | |
217 | + | |
218 | + def off_dt_struct(self): | |
219 | + """Return the start of the device-tree struct area | |
220 | + | |
221 | + Returns: | |
222 | + Start offset of struct area | |
223 | + """ | |
224 | + return check_err(fdt_off_dt_struct(self._fdt)) | |
225 | + | |
226 | + def off_dt_strings(self): | |
227 | + """Return the start of the device-tree string area | |
228 | + | |
229 | + Returns: | |
230 | + Start offset of string area | |
231 | + """ | |
232 | + return check_err(fdt_off_dt_strings(self._fdt)) | |
233 | + | |
234 | + def off_mem_rsvmap(self): | |
235 | + """Return the start of the memory reserve map | |
236 | + | |
237 | + Returns: | |
238 | + Start offset of memory reserve map | |
239 | + """ | |
240 | + return check_err(fdt_off_mem_rsvmap(self._fdt)) | |
241 | + | |
242 | + def version(self): | |
243 | + """Return the version of the device tree | |
244 | + | |
245 | + Returns: | |
246 | + Version number of the device tree | |
247 | + """ | |
248 | + return check_err(fdt_version(self._fdt)) | |
249 | + | |
250 | + def last_comp_version(self): | |
251 | + """Return the last compatible version of the device tree | |
252 | + | |
253 | + Returns: | |
254 | + Last compatible version number of the device tree | |
255 | + """ | |
256 | + return check_err(fdt_last_comp_version(self._fdt)) | |
257 | + | |
258 | + def boot_cpuid_phys(self): | |
259 | + """Return the physical boot CPU ID | |
260 | + | |
261 | + Returns: | |
262 | + Physical boot CPU ID | |
263 | + """ | |
264 | + return check_err(fdt_boot_cpuid_phys(self._fdt)) | |
265 | + | |
266 | + def size_dt_strings(self): | |
267 | + """Return the start of the device-tree string area | |
268 | + | |
269 | + Returns: | |
270 | + Start offset of string area | |
271 | + """ | |
272 | + return check_err(fdt_size_dt_strings(self._fdt)) | |
273 | + | |
274 | + def size_dt_struct(self): | |
275 | + """Return the start of the device-tree struct area | |
276 | + | |
277 | + Returns: | |
278 | + Start offset of struct area | |
279 | + """ | |
280 | + return check_err(fdt_size_dt_struct(self._fdt)) | |
281 | + | |
282 | + def num_mem_rsv(self, quiet=()): | |
283 | + """Return the number of memory reserve-map records | |
284 | + | |
285 | + Returns: | |
286 | + Number of memory reserve-map records | |
287 | + """ | |
288 | + return check_err(fdt_num_mem_rsv(self._fdt), quiet) | |
289 | + | |
290 | + def get_mem_rsv(self, index, quiet=()): | |
291 | + """Return the indexed memory reserve-map record | |
292 | + | |
293 | + Args: | |
294 | + index: Record to return (0=first) | |
295 | + | |
296 | + Returns: | |
297 | + Number of memory reserve-map records | |
298 | + """ | |
299 | + return check_err(fdt_get_mem_rsv(self._fdt, index), quiet) | |
300 | + | |
132 | 301 | def subnode_offset(self, parentoffset, name, quiet=()): |
133 | 302 | """Get the offset of a named subnode |
134 | 303 | |
... | ... | @@ -161,6 +330,20 @@ |
161 | 330 | """ |
162 | 331 | return check_err(fdt_path_offset(self._fdt, path), quiet) |
163 | 332 | |
333 | + def get_name(self, nodeoffset): | |
334 | + """Get the name of a node | |
335 | + | |
336 | + Args: | |
337 | + nodeoffset: Offset of node to check | |
338 | + | |
339 | + Returns: | |
340 | + Node name | |
341 | + | |
342 | + Raises: | |
343 | + FdtException on error (e.g. nodeoffset is invalid) | |
344 | + """ | |
345 | + return check_err_null(fdt_get_name(self._fdt, nodeoffset))[0] | |
346 | + | |
164 | 347 | def first_property_offset(self, nodeoffset, quiet=()): |
165 | 348 | """Get the offset of the first property in a node offset |
166 | 349 | |
... | ... | @@ -195,20 +378,6 @@ |
195 | 378 | return check_err(fdt_next_property_offset(self._fdt, prop_offset), |
196 | 379 | quiet) |
197 | 380 | |
198 | - def get_name(self, nodeoffset): | |
199 | - """Get the name of a node | |
200 | - | |
201 | - Args: | |
202 | - nodeoffset: Offset of node to check | |
203 | - | |
204 | - Returns: | |
205 | - Node name | |
206 | - | |
207 | - Raises: | |
208 | - FdtException on error (e.g. nodeoffset is invalid) | |
209 | - """ | |
210 | - return check_err_null(fdt_get_name(self._fdt, nodeoffset))[0] | |
211 | - | |
212 | 381 | def get_property_by_offset(self, prop_offset, quiet=()): |
213 | 382 | """Obtains a property that can be examined |
214 | 383 | |
215 | 384 | |
216 | 385 | |
217 | 386 | |
218 | 387 | |
219 | 388 | |
220 | 389 | |
221 | 390 | |
222 | 391 | |
... | ... | @@ -229,52 +398,39 @@ |
229 | 398 | return pdata |
230 | 399 | return Property(pdata[0], pdata[1]) |
231 | 400 | |
232 | - def first_subnode(self, nodeoffset, quiet=()): | |
233 | - """Find the first subnode of a parent node | |
401 | + @staticmethod | |
402 | + def create_empty_tree(size, quiet=()): | |
403 | + """Create an empty device tree ready for use | |
234 | 404 | |
235 | 405 | Args: |
236 | - nodeoffset: Node offset of parent node | |
237 | - quiet: Errors to ignore (empty to raise on all errors) | |
406 | + size: Size of device tree in bytes | |
238 | 407 | |
239 | 408 | Returns: |
240 | - The offset of the first subnode, if any | |
241 | - | |
242 | - Raises: | |
243 | - FdtException if no subnode found or other error occurs | |
409 | + Fdt object containing the device tree | |
244 | 410 | """ |
245 | - return check_err(fdt_first_subnode(self._fdt, nodeoffset), quiet) | |
411 | + data = bytearray(size) | |
412 | + err = check_err(fdt_create_empty_tree(data, size), quiet) | |
413 | + if err: | |
414 | + return err | |
415 | + return Fdt(data) | |
246 | 416 | |
247 | - def next_subnode(self, nodeoffset, quiet=()): | |
248 | - """Find the next subnode | |
417 | + def open_into(self, size, quiet=()): | |
418 | + """Move the device tree into a larger or smaller space | |
249 | 419 | |
250 | - Args: | |
251 | - nodeoffset: Node offset of previous subnode | |
252 | - quiet: Errors to ignore (empty to raise on all errors) | |
420 | + This creates a new device tree of size @size and moves the existing | |
421 | + device tree contents over to that. It can be used to create more space | |
422 | + in a device tree. | |
253 | 423 | |
254 | - Returns: | |
255 | - The offset of the next subnode, if any | |
256 | - | |
257 | - Raises: | |
258 | - FdtException if no more subnode found or other error occurs | |
424 | + Args: | |
425 | + size: Required new size of device tree in bytes | |
259 | 426 | """ |
260 | - return check_err(fdt_next_subnode(self._fdt, nodeoffset), quiet) | |
427 | + fdt = bytearray(size) | |
428 | + fdt[:len(self._fdt)] = self._fdt | |
429 | + err = check_err(fdt_open_into(self._fdt, fdt, size), quiet) | |
430 | + if err: | |
431 | + return err | |
432 | + self._fdt = fdt | |
261 | 433 | |
262 | - def totalsize(self): | |
263 | - """Return the total size of the device tree | |
264 | - | |
265 | - Returns: | |
266 | - Total tree size in bytes | |
267 | - """ | |
268 | - return check_err(fdt_totalsize(self._fdt)) | |
269 | - | |
270 | - def off_dt_struct(self): | |
271 | - """Return the start of the device tree struct area | |
272 | - | |
273 | - Returns: | |
274 | - Start offset of struct area | |
275 | - """ | |
276 | - return check_err(fdt_off_dt_struct(self._fdt)) | |
277 | - | |
278 | 434 | def pack(self, quiet=()): |
279 | 435 | """Pack the device tree to remove unused space |
280 | 436 | |
281 | 437 | |
282 | 438 | |
283 | 439 | |
284 | 440 | |
285 | 441 | |
... | ... | @@ -288,20 +444,28 @@ |
288 | 444 | """ |
289 | 445 | return check_err(fdt_pack(self._fdt), quiet) |
290 | 446 | |
291 | - def delprop(self, nodeoffset, prop_name): | |
292 | - """Delete a property from a node | |
447 | + def getprop(self, nodeoffset, prop_name, quiet=()): | |
448 | + """Get a property from a node | |
293 | 449 | |
294 | 450 | Args: |
295 | - nodeoffset: Node offset containing property to delete | |
296 | - prop_name: Name of property to delete | |
451 | + nodeoffset: Node offset containing property to get | |
452 | + prop_name: Name of property to get | |
453 | + quiet: Errors to ignore (empty to raise on all errors) | |
297 | 454 | |
455 | + Returns: | |
456 | + Value of property as a string, or -ve error number | |
457 | + | |
298 | 458 | Raises: |
299 | - FdtError if the property does not exist, or another error occurs | |
459 | + FdtError if any error occurs (e.g. the property is not found) | |
300 | 460 | """ |
301 | - return check_err(fdt_delprop(self._fdt, nodeoffset, prop_name)) | |
461 | + pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name), | |
462 | + quiet) | |
463 | + if isinstance(pdata, (int)): | |
464 | + return pdata | |
465 | + return str(pdata[0]) | |
302 | 466 | |
303 | - def getprop(self, nodeoffset, prop_name, quiet=()): | |
304 | - """Get a property from a node | |
467 | + def getprop_obj(self, nodeoffset, prop_name, quiet=()): | |
468 | + """Get a property from a node as a Property object | |
305 | 469 | |
306 | 470 | Args: |
307 | 471 | nodeoffset: Node offset containing property to get |
... | ... | @@ -309,7 +473,7 @@ |
309 | 473 | quiet: Errors to ignore (empty to raise on all errors) |
310 | 474 | |
311 | 475 | Returns: |
312 | - Value of property as a bytearray, or -ve error number | |
476 | + Property object, or None if not found | |
313 | 477 | |
314 | 478 | Raises: |
315 | 479 | FdtError if any error occurs (e.g. the property is not found) |
... | ... | @@ -317,8 +481,8 @@ |
317 | 481 | pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name), |
318 | 482 | quiet) |
319 | 483 | if isinstance(pdata, (int)): |
320 | - return pdata | |
321 | - return bytearray(pdata[0]) | |
484 | + return None | |
485 | + return Property(prop_name, bytearray(pdata[0])) | |
322 | 486 | |
323 | 487 | def get_phandle(self, nodeoffset): |
324 | 488 | """Get the phandle of a node |
... | ... | @@ -347,6 +511,108 @@ |
347 | 511 | """ |
348 | 512 | return check_err(fdt_parent_offset(self._fdt, nodeoffset), quiet) |
349 | 513 | |
514 | + def set_name(self, nodeoffset, name, quiet=()): | |
515 | + """Set the name of a node | |
516 | + | |
517 | + Args: | |
518 | + nodeoffset: Node offset of node to update | |
519 | + name: New node name | |
520 | + | |
521 | + Returns: | |
522 | + Error code, or 0 if OK | |
523 | + | |
524 | + Raises: | |
525 | + FdtException if no parent found or other error occurs | |
526 | + """ | |
527 | + return check_err(fdt_set_name(self._fdt, nodeoffset, name), quiet) | |
528 | + | |
529 | + def setprop(self, nodeoffset, prop_name, val, quiet=()): | |
530 | + """Set the value of a property | |
531 | + | |
532 | + Args: | |
533 | + nodeoffset: Node offset containing the property to create/update | |
534 | + prop_name: Name of property | |
535 | + val: Value to write (string or bytearray) | |
536 | + quiet: Errors to ignore (empty to raise on all errors) | |
537 | + | |
538 | + Returns: | |
539 | + Error code, or 0 if OK | |
540 | + | |
541 | + Raises: | |
542 | + FdtException if no parent found or other error occurs | |
543 | + """ | |
544 | + return check_err(fdt_setprop(self._fdt, nodeoffset, prop_name, val, | |
545 | + len(val)), quiet) | |
546 | + | |
547 | + def setprop_u32(self, nodeoffset, prop_name, val, quiet=()): | |
548 | + """Set the value of a property | |
549 | + | |
550 | + Args: | |
551 | + nodeoffset: Node offset containing the property to create/update | |
552 | + prop_name: Name of property | |
553 | + val: Value to write (integer) | |
554 | + quiet: Errors to ignore (empty to raise on all errors) | |
555 | + | |
556 | + Returns: | |
557 | + Error code, or 0 if OK | |
558 | + | |
559 | + Raises: | |
560 | + FdtException if no parent found or other error occurs | |
561 | + """ | |
562 | + return check_err(fdt_setprop_u32(self._fdt, nodeoffset, prop_name, val), | |
563 | + quiet) | |
564 | + | |
565 | + def setprop_u64(self, nodeoffset, prop_name, val, quiet=()): | |
566 | + """Set the value of a property | |
567 | + | |
568 | + Args: | |
569 | + nodeoffset: Node offset containing the property to create/update | |
570 | + prop_name: Name of property | |
571 | + val: Value to write (integer) | |
572 | + quiet: Errors to ignore (empty to raise on all errors) | |
573 | + | |
574 | + Returns: | |
575 | + Error code, or 0 if OK | |
576 | + | |
577 | + Raises: | |
578 | + FdtException if no parent found or other error occurs | |
579 | + """ | |
580 | + return check_err(fdt_setprop_u64(self._fdt, nodeoffset, prop_name, val), | |
581 | + quiet) | |
582 | + | |
583 | + def setprop_str(self, nodeoffset, prop_name, val, quiet=()): | |
584 | + """Set the string value of a property | |
585 | + | |
586 | + The property is set to the string, with a nul terminator added | |
587 | + | |
588 | + Args: | |
589 | + nodeoffset: Node offset containing the property to create/update | |
590 | + prop_name: Name of property | |
591 | + val: Value to write (string without nul terminator) | |
592 | + quiet: Errors to ignore (empty to raise on all errors) | |
593 | + | |
594 | + Returns: | |
595 | + Error code, or 0 if OK | |
596 | + | |
597 | + Raises: | |
598 | + FdtException if no parent found or other error occurs | |
599 | + """ | |
600 | + val += '\0' | |
601 | + return check_err(fdt_setprop(self._fdt, nodeoffset, prop_name, | |
602 | + val, len(val)), quiet) | |
603 | + | |
604 | + def delprop(self, nodeoffset, prop_name): | |
605 | + """Delete a property from a node | |
606 | + | |
607 | + Args: | |
608 | + nodeoffset: Node offset containing property to delete | |
609 | + prop_name: Name of property to delete | |
610 | + | |
611 | + Raises: | |
612 | + FdtError if the property does not exist, or another error occurs | |
613 | + """ | |
614 | + return check_err(fdt_delprop(self._fdt, nodeoffset, prop_name)) | |
615 | + | |
350 | 616 | def node_offset_by_phandle(self, phandle, quiet=()): |
351 | 617 | """Get the offset of a node with the given phandle |
352 | 618 | |
... | ... | @@ -362,7 +628,8 @@ |
362 | 628 | """ |
363 | 629 | return check_err(fdt_node_offset_by_phandle(self._fdt, phandle), quiet) |
364 | 630 | |
365 | -class Property: | |
631 | + | |
632 | +class Property(bytearray): | |
366 | 633 | """Holds a device tree property name and value. |
367 | 634 | |
368 | 635 | This holds a copy of a property taken from the device tree. It does not |
369 | 636 | |
370 | 637 | |
... | ... | @@ -371,11 +638,274 @@ |
371 | 638 | |
372 | 639 | Properties: |
373 | 640 | name: Property name |
374 | - value: Proper value as a bytearray | |
641 | + value: Property value as a bytearray | |
375 | 642 | """ |
376 | 643 | def __init__(self, name, value): |
644 | + bytearray.__init__(self, value) | |
377 | 645 | self.name = name |
378 | - self.value = value | |
646 | + | |
647 | + def as_cell(self, fmt): | |
648 | + return struct.unpack('>' + fmt, self)[0] | |
649 | + | |
650 | + def as_uint32(self): | |
651 | + return self.as_cell('L') | |
652 | + | |
653 | + def as_int32(self): | |
654 | + return self.as_cell('l') | |
655 | + | |
656 | + def as_uint64(self): | |
657 | + return self.as_cell('Q') | |
658 | + | |
659 | + def as_int64(self): | |
660 | + return self.as_cell('q') | |
661 | + | |
662 | + def as_str(self): | |
663 | + return self[:-1] | |
664 | + | |
665 | + | |
666 | +class FdtSw(object): | |
667 | + """Software interface to create a device tree from scratch | |
668 | + | |
669 | + The methods in this class work by adding to an existing 'partial' device | |
670 | + tree buffer of a fixed size created by instantiating this class. When the | |
671 | + tree is complete, call finish() to complete the device tree so that it can | |
672 | + be used. | |
673 | + | |
674 | + Similarly with nodes, a new node is started with begin_node() and finished | |
675 | + with end_node(). | |
676 | + | |
677 | + The context manager functions can be used to make this a bit easier: | |
678 | + | |
679 | + # First create the device tree with a node and property: | |
680 | + with FdtSw(small_size) as sw: | |
681 | + with sw.AddNode('node'): | |
682 | + sw.property_u32('reg', 2) | |
683 | + fdt = sw.AsFdt() | |
684 | + | |
685 | + # Now we can use it as a real device tree | |
686 | + fdt.setprop_u32(0, 'reg', 3) | |
687 | + """ | |
688 | + def __init__(self, size, quiet=()): | |
689 | + fdtrw = bytearray(size) | |
690 | + err = check_err(fdt_create(fdtrw, size)) | |
691 | + if err: | |
692 | + return err | |
693 | + self._fdtrw = fdtrw | |
694 | + | |
695 | + def __enter__(self): | |
696 | + """Contact manager to use to create a device tree via software""" | |
697 | + return self | |
698 | + | |
699 | + def __exit__(self, type, value, traceback): | |
700 | + check_err(fdt_finish(self._fdtrw)) | |
701 | + | |
702 | + def AsFdt(self): | |
703 | + """Convert a FdtSw into an Fdt so it can be accessed as normal | |
704 | + | |
705 | + Note that finish() must be called before this function will work. If | |
706 | + you are using the context manager (see 'with' code in the FdtSw class | |
707 | + comment) then this will happen automatically. | |
708 | + | |
709 | + Returns: | |
710 | + Fdt object allowing access to the newly created device tree | |
711 | + """ | |
712 | + return Fdt(self._fdtrw) | |
713 | + | |
714 | + def resize(self, size, quiet=()): | |
715 | + """Resize the buffer to accommodate a larger tree | |
716 | + | |
717 | + Args: | |
718 | + size: New size of tree | |
719 | + quiet: Errors to ignore (empty to raise on all errors) | |
720 | + | |
721 | + Raises: | |
722 | + FdtException if no node found or other error occurs | |
723 | + """ | |
724 | + fdt = bytearray(size) | |
725 | + fdt[:len(self._fdtrw)] = self._fdtrw | |
726 | + err = check_err(fdt_resize(self._fdtrw, fdt, size), quiet) | |
727 | + if err: | |
728 | + return err | |
729 | + self._fdtrw = fdt | |
730 | + | |
731 | + def add_reservemap_entry(self, addr, size, quiet=()): | |
732 | + """Add a new memory reserve map entry | |
733 | + | |
734 | + Once finished adding, you must call finish_reservemap(). | |
735 | + | |
736 | + Args: | |
737 | + addr: 64-bit start address | |
738 | + size: 64-bit size | |
739 | + quiet: Errors to ignore (empty to raise on all errors) | |
740 | + | |
741 | + Raises: | |
742 | + FdtException if no node found or other error occurs | |
743 | + """ | |
744 | + return check_err(fdt_add_reservemap_entry(self._fdtrw, addr, size), | |
745 | + quiet) | |
746 | + | |
747 | + def finish_reservemap(self, quiet=()): | |
748 | + """Indicate that there are no more reserve map entries to add | |
749 | + | |
750 | + Args: | |
751 | + quiet: Errors to ignore (empty to raise on all errors) | |
752 | + | |
753 | + Raises: | |
754 | + FdtException if no node found or other error occurs | |
755 | + """ | |
756 | + return check_err(fdt_finish_reservemap(self._fdtrw), quiet) | |
757 | + | |
758 | + def begin_node(self, name, quiet=()): | |
759 | + """Begin a new node | |
760 | + | |
761 | + Use this before adding properties to the node. Then call end_node() to | |
762 | + finish it. You can also use the context manager as shown in the FdtSw | |
763 | + class comment. | |
764 | + | |
765 | + Args: | |
766 | + name: Name of node to begin | |
767 | + quiet: Errors to ignore (empty to raise on all errors) | |
768 | + | |
769 | + Raises: | |
770 | + FdtException if no node found or other error occurs | |
771 | + """ | |
772 | + return check_err(fdt_begin_node(self._fdtrw, name), quiet) | |
773 | + | |
774 | + def property_string(self, name, string, quiet=()): | |
775 | + """Add a property with a string value | |
776 | + | |
777 | + The string will be nul-terminated when written to the device tree | |
778 | + | |
779 | + Args: | |
780 | + name: Name of property to add | |
781 | + string: String value of property | |
782 | + quiet: Errors to ignore (empty to raise on all errors) | |
783 | + | |
784 | + Raises: | |
785 | + FdtException if no node found or other error occurs | |
786 | + """ | |
787 | + return check_err(fdt_property_string(self._fdtrw, name, string), quiet) | |
788 | + | |
789 | + def property_u32(self, name, val, quiet=()): | |
790 | + """Add a property with a 32-bit value | |
791 | + | |
792 | + Write a single-cell value to the device tree | |
793 | + | |
794 | + Args: | |
795 | + name: Name of property to add | |
796 | + val: Value of property | |
797 | + quiet: Errors to ignore (empty to raise on all errors) | |
798 | + | |
799 | + Raises: | |
800 | + FdtException if no node found or other error occurs | |
801 | + """ | |
802 | + return check_err(fdt_property_u32(self._fdtrw, name, val), quiet) | |
803 | + | |
804 | + def property_u64(self, name, val, quiet=()): | |
805 | + """Add a property with a 64-bit value | |
806 | + | |
807 | + Write a double-cell value to the device tree in big-endian format | |
808 | + | |
809 | + Args: | |
810 | + name: Name of property to add | |
811 | + val: Value of property | |
812 | + quiet: Errors to ignore (empty to raise on all errors) | |
813 | + | |
814 | + Raises: | |
815 | + FdtException if no node found or other error occurs | |
816 | + """ | |
817 | + return check_err(fdt_property_u64(self._fdtrw, name, val), quiet) | |
818 | + | |
819 | + def property_cell(self, name, val, quiet=()): | |
820 | + """Add a property with a single-cell value | |
821 | + | |
822 | + Write a single-cell value to the device tree | |
823 | + | |
824 | + Args: | |
825 | + name: Name of property to add | |
826 | + val: Value of property | |
827 | + quiet: Errors to ignore (empty to raise on all errors) | |
828 | + | |
829 | + Raises: | |
830 | + FdtException if no node found or other error occurs | |
831 | + """ | |
832 | + return check_err(fdt_property_cell(self._fdtrw, name, val), quiet) | |
833 | + | |
834 | + def property(self, name, val, quiet=()): | |
835 | + """Add a property | |
836 | + | |
837 | + Write a new property with the given value to the device tree. The value | |
838 | + is taken as is and is not nul-terminated | |
839 | + | |
840 | + Args: | |
841 | + name: Name of property to add | |
842 | + val: Value of property | |
843 | + quiet: Errors to ignore (empty to raise on all errors) | |
844 | + | |
845 | + Raises: | |
846 | + FdtException if no node found or other error occurs | |
847 | + """ | |
848 | + return check_err(_fdt_property(self._fdtrw, name, val, len(val)), quiet) | |
849 | + | |
850 | + def end_node(self, quiet=()): | |
851 | + """End a node | |
852 | + | |
853 | + Use this after adding properties to a node to close it off. You can also | |
854 | + use the context manager as shown in the FdtSw class comment. | |
855 | + | |
856 | + Args: | |
857 | + quiet: Errors to ignore (empty to raise on all errors) | |
858 | + | |
859 | + Raises: | |
860 | + FdtException if no node found or other error occurs | |
861 | + """ | |
862 | + return check_err(fdt_end_node(self._fdtrw), quiet) | |
863 | + | |
864 | + def finish(self, quiet=()): | |
865 | + """Finish writing the device tree | |
866 | + | |
867 | + This closes off the device tree ready for use | |
868 | + | |
869 | + Args: | |
870 | + quiet: Errors to ignore (empty to raise on all errors) | |
871 | + | |
872 | + Raises: | |
873 | + FdtException if no node found or other error occurs | |
874 | + """ | |
875 | + return check_err(fdt_finish(self._fdtrw), quiet) | |
876 | + | |
877 | + def AddNode(self, name): | |
878 | + """Create a new context for adding a node | |
879 | + | |
880 | + When used in a 'with' clause this starts a new node and finishes it | |
881 | + afterward. | |
882 | + | |
883 | + Args: | |
884 | + name: Name of node to add | |
885 | + """ | |
886 | + return NodeAdder(self._fdtrw, name) | |
887 | + | |
888 | + | |
889 | +class NodeAdder(): | |
890 | + """Class to provide a node context | |
891 | + | |
892 | + This allows you to add nodes in a more natural way: | |
893 | + | |
894 | + with fdtsw.AddNode('name'): | |
895 | + fdtsw.property_string('test', 'value') | |
896 | + | |
897 | + The node is automatically completed with a call to end_node() when the | |
898 | + context exits. | |
899 | + """ | |
900 | + def __init__(self, fdt, name): | |
901 | + self._fdt = fdt | |
902 | + self._name = name | |
903 | + | |
904 | + def __enter__(self): | |
905 | + check_err(fdt_begin_node(self._fdt, self._name)) | |
906 | + | |
907 | + def __exit__(self, type, value, traceback): | |
908 | + check_err(fdt_end_node(self._fdt)) | |
379 | 909 | %} |
380 | 910 | |
381 | 911 | %rename(fdt_property) fdt_property_func; |
... | ... | @@ -408,6 +938,7 @@ |
408 | 938 | fdt = fdt; /* avoid unused variable warning */ |
409 | 939 | } |
410 | 940 | |
941 | +/* typemap used for fdt_get_property_by_offset() */ | |
411 | 942 | %typemap(out) (struct fdt_property *) { |
412 | 943 | PyObject *buff; |
413 | 944 | |
... | ... | @@ -430,6 +961,44 @@ |
430 | 961 | $result = Py_BuildValue("s#", $1, *arg4); |
431 | 962 | } |
432 | 963 | |
964 | +/* typemap used for fdt_setprop() */ | |
965 | +%typemap(in) (const void *val) { | |
966 | + $1 = PyString_AsString($input); /* char *str */ | |
967 | +} | |
968 | + | |
969 | +/* typemap used for fdt_add_reservemap_entry() */ | |
970 | +%typemap(in) uint64_t { | |
971 | + $1 = PyLong_AsUnsignedLong($input); | |
972 | +} | |
973 | + | |
974 | +/* typemaps used for fdt_next_node() */ | |
975 | +%typemap(in, numinputs=1) int *depth (int depth) { | |
976 | + depth = (int) PyInt_AsLong($input); | |
977 | + $1 = &depth; | |
978 | +} | |
979 | + | |
980 | +%typemap(argout) int *depth { | |
981 | + PyObject *val = Py_BuildValue("i", *arg$argnum); | |
982 | + resultobj = SWIG_Python_AppendOutput(resultobj, val); | |
983 | +} | |
984 | + | |
985 | +%apply int *depth { int *depth }; | |
986 | + | |
987 | +/* typemaps for fdt_get_mem_rsv */ | |
988 | +%typemap(in, numinputs=0) uint64_t * (uint64_t temp) { | |
989 | + $1 = &temp; | |
990 | +} | |
991 | + | |
992 | +%typemap(argout) uint64_t * { | |
993 | + PyObject *val = PyLong_FromUnsignedLong(*arg$argnum); | |
994 | + if (!result) { | |
995 | + if (PyTuple_GET_SIZE(resultobj) == 0) | |
996 | + resultobj = val; | |
997 | + else | |
998 | + resultobj = SWIG_Python_AppendOutput(resultobj, val); | |
999 | + } | |
1000 | +} | |
1001 | + | |
433 | 1002 | /* We have both struct fdt_property and a function fdt_property() */ |
434 | 1003 | %warnfilter(302) fdt_property; |
435 | 1004 | |
... | ... | @@ -444,6 +1013,14 @@ |
444 | 1013 | int fdt_boot_cpuid_phys(const void *fdt); |
445 | 1014 | int fdt_size_dt_strings(const void *fdt); |
446 | 1015 | int fdt_size_dt_struct(const void *fdt); |
1016 | +int fdt_property_string(void *fdt, const char *name, const char *val); | |
1017 | +int fdt_property_cell(void *fdt, const char *name, uint32_t val); | |
1018 | + | |
1019 | +/* | |
1020 | + * This function has a stub since the name fdt_property is used for both a | |
1021 | + * function and a struct, which confuses SWIG. | |
1022 | + */ | |
1023 | +int _fdt_property(void *fdt, const char *name, const char *val, int len); | |
447 | 1024 | |
448 | 1025 | %include <../libfdt/libfdt.h> |
tools/dtoc/dtoc.py
... | ... | @@ -36,14 +36,26 @@ |
36 | 36 | |
37 | 37 | import dtb_platdata |
38 | 38 | |
39 | -def run_tests(): | |
40 | - """Run all the test we have for dtoc""" | |
39 | +def run_tests(args): | |
40 | + """Run all the test we have for dtoc | |
41 | + | |
42 | + Args: | |
43 | + args: List of positional args provided to binman. This can hold a test | |
44 | + name to execute (as in 'binman -t testSections', for example) | |
45 | + """ | |
41 | 46 | import test_dtoc |
42 | 47 | |
43 | 48 | result = unittest.TestResult() |
44 | 49 | sys.argv = [sys.argv[0]] |
50 | + test_name = args and args[0] or None | |
45 | 51 | for module in (test_dtoc.TestDtoc,): |
46 | - suite = unittest.TestLoader().loadTestsFromTestCase(module) | |
52 | + if test_name: | |
53 | + try: | |
54 | + suite = unittest.TestLoader().loadTestsFromName(test_name, module) | |
55 | + except AttributeError: | |
56 | + continue | |
57 | + else: | |
58 | + suite = unittest.TestLoader().loadTestsFromTestCase(module) | |
47 | 59 | suite.run(result) |
48 | 60 | |
49 | 61 | print result |
... | ... | @@ -68,7 +80,7 @@ |
68 | 80 | |
69 | 81 | # Run our meagre tests |
70 | 82 | if options.test: |
71 | - run_tests() | |
83 | + run_tests(args) | |
72 | 84 | |
73 | 85 | else: |
74 | 86 | dtb_platdata.run_steps(args, options.dtb_file, options.include_disabled, |
tools/dtoc/fdt.py
... | ... | @@ -234,7 +234,6 @@ |
234 | 234 | be updated. |
235 | 235 | """ |
236 | 236 | if self._offset != my_offset: |
237 | - #print '%s: %d -> %d\n' % (self.path, self._offset, my_offset) | |
238 | 237 | self._offset = my_offset |
239 | 238 | offset = libfdt.fdt_first_subnode(self._fdt.GetFdt(), self._offset) |
240 | 239 | for subnode in self.subnodes: |
... | ... | @@ -359,7 +358,7 @@ |
359 | 358 | poffset = libfdt.fdt_first_property_offset(self._fdt, node._offset) |
360 | 359 | while poffset >= 0: |
361 | 360 | p = self._fdt_obj.get_property_by_offset(poffset) |
362 | - prop = Prop(node, poffset, p.name, p.value) | |
361 | + prop = Prop(node, poffset, p.name, p) | |
363 | 362 | props_dict[prop.name] = prop |
364 | 363 | |
365 | 364 | poffset = libfdt.fdt_next_property_offset(self._fdt, poffset) |
tools/dtoc/test_dtoc.py