diff options
author | Tom Rini <trini@konsulko.com> | 2018-08-09 11:10:41 -0400 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2018-08-09 11:10:41 -0400 |
commit | b243f41f12d63d35234b25949319837e318ff9e0 (patch) | |
tree | f1161e19e75eba5acf78341006609df07a4ac482 /scripts/dtc/pylibfdt | |
parent | 9d17682a57bcc290a2584d81a47537aa0b6b17c1 (diff) | |
parent | 41d7535cba42cd88f3b04f8fbd4409e5a479076f (diff) |
Merge git://git.denx.de/u-boot-dm
Diffstat (limited to 'scripts/dtc/pylibfdt')
-rw-r--r-- | scripts/dtc/pylibfdt/libfdt.i_shipped | 464 |
1 files changed, 239 insertions, 225 deletions
diff --git a/scripts/dtc/pylibfdt/libfdt.i_shipped b/scripts/dtc/pylibfdt/libfdt.i_shipped index e180ee9308..0f17c5879e 100644 --- a/scripts/dtc/pylibfdt/libfdt.i_shipped +++ b/scripts/dtc/pylibfdt/libfdt.i_shipped @@ -18,7 +18,8 @@ * a struct called fdt_property. That struct causes swig to create a class in * libfdt.py called fdt_property(), which confuses things. */ -static int _fdt_property(void *fdt, const char *name, const char *val, int len) +static int fdt_property_stub(void *fdt, const char *name, const char *val, + int len) { return fdt_property(fdt, name, val, len); } @@ -54,6 +55,7 @@ import struct # Pass this as the 'quiet' parameter to return -ENOTFOUND on NOTFOUND errors, # instead of raising an exception. QUIET_NOTFOUND = (NOTFOUND,) +QUIET_NOSPACE = (NOSPACE,) class FdtException(Exception): @@ -119,23 +121,18 @@ def check_err_null(val, quiet=()): raise FdtException(val) return val +class FdtRo(object): + """Class for a read-only device-tree -class Fdt: - """Device tree class, supporting all operations - - The Fdt object is created is created from a device tree binary file, - e.g. with something like: + This is a base class used by FdtRw (read-write access) and FdtSw + (sequential-write access). It implements read-only access to the + device tree. - fdt = Fdt(open("filename.dtb").read()) - - Operations can then be performed using the methods in this class. Each - method xxx(args...) corresponds to a libfdt function fdt_xxx(fdt, args...). + Here are the three classes and when you should use them: - All methods raise an FdtException if an error occurs. To avoid this - behaviour a 'quiet' parameter is provided for some functions. This - defaults to empty, but you can pass a list of errors that you expect. - If one of these errors occurs, the function will return an error number - (e.g. -NOTFOUND). + FdtRo - read-only access to an existing FDT + FdtRw - read-write access to an existing FDT (most common case) + FdtSw - for creating a new FDT, as well as allowing read-only access """ def __init__(self, data): self._fdt = bytearray(data) @@ -157,12 +154,14 @@ class Fdt: Args: nodeoffset: Node offset of previous node - depth: On input, the depth of the node at nodeoffset. On output, the - depth of the returned node + depth: The depth of the node at nodeoffset. This is used to + calculate the depth of the returned node quiet: Errors to ignore (empty to raise on all errors) Returns: - The offset of the next node, if any + Typle: + Offset of the next node, if any, else a -ve error + Depth of the returned node, if any, else undefined Raises: FdtException if no more nodes found or other error occurs @@ -205,7 +204,7 @@ class Fdt: Returns: Magic word """ - return fdt_magic(self._fdt) & 0xffffffff + return fdt_magic(self._fdt) def totalsize(self): """Return the total size of the device tree @@ -213,7 +212,7 @@ class Fdt: Returns: Total tree size in bytes """ - return check_err(fdt_totalsize(self._fdt)) + return fdt_totalsize(self._fdt) def off_dt_struct(self): """Return the start of the device-tree struct area @@ -221,7 +220,7 @@ class Fdt: Returns: Start offset of struct area """ - return check_err(fdt_off_dt_struct(self._fdt)) + return fdt_off_dt_struct(self._fdt) def off_dt_strings(self): """Return the start of the device-tree string area @@ -229,7 +228,7 @@ class Fdt: Returns: Start offset of string area """ - return check_err(fdt_off_dt_strings(self._fdt)) + return fdt_off_dt_strings(self._fdt) def off_mem_rsvmap(self): """Return the start of the memory reserve map @@ -237,7 +236,7 @@ class Fdt: Returns: Start offset of memory reserve map """ - return check_err(fdt_off_mem_rsvmap(self._fdt)) + return fdt_off_mem_rsvmap(self._fdt) def version(self): """Return the version of the device tree @@ -245,7 +244,7 @@ class Fdt: Returns: Version number of the device tree """ - return check_err(fdt_version(self._fdt)) + return fdt_version(self._fdt) def last_comp_version(self): """Return the last compatible version of the device tree @@ -253,7 +252,7 @@ class Fdt: Returns: Last compatible version number of the device tree """ - return check_err(fdt_last_comp_version(self._fdt)) + return fdt_last_comp_version(self._fdt) def boot_cpuid_phys(self): """Return the physical boot CPU ID @@ -261,7 +260,7 @@ class Fdt: Returns: Physical boot CPU ID """ - return check_err(fdt_boot_cpuid_phys(self._fdt)) + return fdt_boot_cpuid_phys(self._fdt) def size_dt_strings(self): """Return the start of the device-tree string area @@ -269,7 +268,7 @@ class Fdt: Returns: Start offset of string area """ - return check_err(fdt_size_dt_strings(self._fdt)) + return fdt_size_dt_strings(self._fdt) def size_dt_struct(self): """Return the start of the device-tree struct area @@ -277,7 +276,7 @@ class Fdt: Returns: Start offset of struct area """ - return check_err(fdt_size_dt_struct(self._fdt)) + return fdt_size_dt_struct(self._fdt) def num_mem_rsv(self, quiet=()): """Return the number of memory reserve-map records @@ -398,26 +397,90 @@ class Fdt: return pdata return Property(pdata[0], pdata[1]) - def get_property(self, nodeoffset, prop_name, quiet=()): - """Obtains a property by name + def getprop(self, nodeoffset, prop_name, quiet=()): + """Get a property from a node Args: - nodeoffset: Offset to the node to check + nodeoffset: Node offset containing property to get prop_name: Name of property to get quiet: Errors to ignore (empty to raise on all errors) Returns: - Property object, or None if not found + Value of property as a Property object (which can be used as a + bytearray/string), or -ve error number. On failure, returns an + integer error Raises: - FdtException on error (e.g. invalid prop_offset or device - tree format) + FdtError if any error occurs (e.g. the property is not found) """ - pdata = check_err_null( - fdt_get_property(self._fdt, nodeoffset, prop_name), quiet) + pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name), + quiet) if isinstance(pdata, (int)): return pdata - return Property(pdata[0], pdata[1]) + return Property(prop_name, bytearray(pdata[0])) + + def get_phandle(self, nodeoffset): + """Get the phandle of a node + + Args: + nodeoffset: Node offset to check + + Returns: + phandle of node, or 0 if the node has no phandle or another error + occurs + """ + return fdt_get_phandle(self._fdt, nodeoffset) + + def parent_offset(self, nodeoffset, quiet=()): + """Get the offset of a node's parent + + Args: + nodeoffset: Node offset to check + quiet: Errors to ignore (empty to raise on all errors) + + Returns: + The offset of the parent node, if any + + Raises: + FdtException if no parent found or other error occurs + """ + return check_err(fdt_parent_offset(self._fdt, nodeoffset), quiet) + + def node_offset_by_phandle(self, phandle, quiet=()): + """Get the offset of a node with the given phandle + + Args: + phandle: Phandle to search for + quiet: Errors to ignore (empty to raise on all errors) + + Returns: + The offset of node with that phandle, if any + + Raises: + FdtException if no node found or other error occurs + """ + return check_err(fdt_node_offset_by_phandle(self._fdt, phandle), quiet) + + +class Fdt(FdtRo): + """Device tree class, supporting all operations + + The Fdt object is created is created from a device tree binary file, + e.g. with something like: + + fdt = Fdt(open("filename.dtb").read()) + + Operations can then be performed using the methods in this class. Each + method xxx(args...) corresponds to a libfdt function fdt_xxx(fdt, args...). + + All methods raise an FdtException if an error occurs. To avoid this + behaviour a 'quiet' parameter is provided for some functions. This + defaults to empty, but you can pass a list of errors that you expect. + If one of these errors occurs, the function will return an error number + (e.g. -NOTFOUND). + """ + def __init__(self, data): + FdtRo.__init__(self, data) @staticmethod def create_empty_tree(size, quiet=()): @@ -435,18 +498,18 @@ class Fdt: return err return Fdt(data) - def open_into(self, size, quiet=()): + def resize(self, size, quiet=()): """Move the device tree into a larger or smaller space This creates a new device tree of size @size and moves the existing device tree contents over to that. It can be used to create more space - in a device tree. + in a device tree. Note that the Fdt object remains the same, but it + now has a new bytearray holding the contents. Args: size: Required new size of device tree in bytes """ fdt = bytearray(size) - fdt[:len(self._fdt)] = self._fdt err = check_err(fdt_open_into(self._fdt, fdt, size), quiet) if err: return err @@ -460,6 +523,9 @@ class Fdt: Args: quiet: Errors to ignore (empty to raise on all errors) + Returns: + Error code, or 0 if OK + Raises: FdtException if any error occurs """ @@ -469,79 +535,12 @@ class Fdt: del self._fdt[self.totalsize():] return err - def getprop(self, nodeoffset, prop_name, quiet=()): - """Get a property from a node - - Args: - nodeoffset: Node offset containing property to get - prop_name: Name of property to get - quiet: Errors to ignore (empty to raise on all errors) - - Returns: - Value of property as a string, or -ve error number - - Raises: - FdtError if any error occurs (e.g. the property is not found) - """ - pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name), - quiet) - if isinstance(pdata, (int)): - return pdata - return str(pdata[0]) - - def getprop_obj(self, nodeoffset, prop_name, quiet=()): - """Get a property from a node as a Property object - - Args: - nodeoffset: Node offset containing property to get - prop_name: Name of property to get - quiet: Errors to ignore (empty to raise on all errors) - - Returns: - Property object, or None if not found - - Raises: - FdtError if any error occurs (e.g. the property is not found) - """ - pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name), - quiet) - if isinstance(pdata, (int)): - return None - return Property(prop_name, bytearray(pdata[0])) - - def get_phandle(self, nodeoffset): - """Get the phandle of a node - - Args: - nodeoffset: Node offset to check - - Returns: - phandle of node, or 0 if the node has no phandle or another error - occurs - """ - return fdt_get_phandle(self._fdt, nodeoffset) - - def parent_offset(self, nodeoffset, quiet=()): - """Get the offset of a node's parent - - Args: - nodeoffset: Node offset to check - quiet: Errors to ignore (empty to raise on all errors) - - Returns: - The offset of the parent node, if any - - Raises: - FdtException if no parent found or other error occurs - """ - return check_err(fdt_parent_offset(self._fdt, nodeoffset), quiet) - def set_name(self, nodeoffset, name, quiet=()): """Set the name of a node Args: nodeoffset: Node offset of node to update - name: New node name + name: New node name (string without \0) Returns: Error code, or 0 if OK @@ -549,6 +548,8 @@ class Fdt: Raises: FdtException if no parent found or other error occurs """ + if chr(0) in name: + raise ValueError('Property contains embedded nul characters') return check_err(fdt_set_name(self._fdt, nodeoffset, name), quiet) def setprop(self, nodeoffset, prop_name, val, quiet=()): @@ -613,7 +614,8 @@ class Fdt: Args: nodeoffset: Node offset containing the property to create/update prop_name: Name of property - val: Value to write (string without nul terminator) + val: Value to write (string without nul terminator). Unicode is + supposed by encoding to UTF-8 quiet: Errors to ignore (empty to raise on all errors) Returns: @@ -622,7 +624,7 @@ class Fdt: Raises: FdtException if no parent found or other error occurs """ - val += '\0' + val = val.encode('utf-8') + '\0' return check_err(fdt_setprop(self._fdt, nodeoffset, prop_name, val, len(val)), quiet) @@ -638,21 +640,6 @@ class Fdt: """ return check_err(fdt_delprop(self._fdt, nodeoffset, prop_name)) - def node_offset_by_phandle(self, phandle, quiet=()): - """Get the offset of a node with the given phandle - - Args: - phandle: Phandle to search for - quiet: Errors to ignore (empty to raise on all errors) - - Returns: - The offset of node with that phandle, if any - - Raises: - FdtException if no node found or other error occurs - """ - return check_err(fdt_node_offset_by_phandle(self._fdt, phandle), quiet) - def del_node(self, nodeoffset): """Delete a node @@ -696,16 +683,20 @@ class Property(bytearray): return self.as_cell('q') def as_str(self): - return self[:-1] + """Unicode is supported by decoding from UTF-8""" + if self[-1] != 0: + raise ValueError('Property lacks nul termination') + if 0 in self[:-1]: + raise ValueError('Property contains embedded nul characters') + return self[:-1].decode('utf-8') -class FdtSw(object): +class FdtSw(FdtRo): """Software interface to create a device tree from scratch The methods in this class work by adding to an existing 'partial' device tree buffer of a fixed size created by instantiating this class. When the - tree is complete, call finish() to complete the device tree so that it can - be used. + tree is complete, call as_fdt() to obtain a device tree ready to be used. Similarly with nodes, a new node is started with begin_node() and finished with end_node(). @@ -713,58 +704,87 @@ class FdtSw(object): The context manager functions can be used to make this a bit easier: # First create the device tree with a node and property: - with FdtSw(small_size) as sw: - with sw.AddNode('node'): - sw.property_u32('reg', 2) - fdt = sw.AsFdt() + sw = FdtSw() + with sw.add_node('node'): + sw.property_u32('reg', 2) + fdt = sw.as_fdt() # Now we can use it as a real device tree fdt.setprop_u32(0, 'reg', 3) + + The size hint provides a starting size for the space to be used by the + device tree. This will be increased automatically as needed as new items + are added to the tree. """ - def __init__(self, size, quiet=()): - fdtrw = bytearray(size) - err = check_err(fdt_create(fdtrw, size)) - if err: - return err - self._fdtrw = fdtrw + INC_SIZE = 1024 # Expand size by this much when out of space - def __enter__(self): - """Contact manager to use to create a device tree via software""" - return self + def __init__(self, size_hint=None): + """Create a new FdtSw object - def __exit__(self, type, value, traceback): - check_err(fdt_finish(self._fdtrw)) + Args: + size_hint: A hint as to the initial size to use + + Raises: + ValueError if size_hint is negative - def AsFdt(self): + Returns: + FdtSw object on success, else integer error code (if not raising) + """ + if not size_hint: + size_hint = self.INC_SIZE + fdtsw = bytearray(size_hint) + err = check_err(fdt_create(fdtsw, size_hint)) + if err: + return err + self._fdt = fdtsw + + def as_fdt(self): """Convert a FdtSw into an Fdt so it can be accessed as normal - Note that finish() must be called before this function will work. If - you are using the context manager (see 'with' code in the FdtSw class - comment) then this will happen automatically. + Creates a new Fdt object from the work-in-progress device tree. This + does not call fdt_finish() on the current object, so it is possible to + add more nodes/properties and call as_fdt() again to get an updated + tree. Returns: Fdt object allowing access to the newly created device tree """ - return Fdt(self._fdtrw) + fdtsw = bytearray(self._fdt) + check_err(fdt_finish(fdtsw)) + return Fdt(fdtsw) - def resize(self, size, quiet=()): + def check_space(self, val): + """Check if we need to add more space to the FDT + + This should be called with the error code from an operation. If this is + -NOSPACE then the FDT will be expanded to have more space, and True will + be returned, indicating that the operation needs to be tried again. + + Args: + val: Return value from the operation that was attempted + + Returns: + True if the operation must be retried, else False + """ + if check_err(val, QUIET_NOSPACE) < 0: + self.resize(len(self._fdt) + self.INC_SIZE) + return True + return False + + def resize(self, size): """Resize the buffer to accommodate a larger tree Args: size: New size of tree - quiet: Errors to ignore (empty to raise on all errors) Raises: - FdtException if no node found or other error occurs + FdtException on any error """ fdt = bytearray(size) - fdt[:len(self._fdtrw)] = self._fdtrw - err = check_err(fdt_resize(self._fdtrw, fdt, size), quiet) - if err: - return err - self._fdtrw = fdt + err = check_err(fdt_resize(self._fdt, fdt, size)) + self._fdt = fdt - def add_reservemap_entry(self, addr, size, quiet=()): + def add_reservemap_entry(self, addr, size): """Add a new memory reserve map entry Once finished adding, you must call finish_reservemap(). @@ -772,26 +792,24 @@ class FdtSw(object): Args: addr: 64-bit start address size: 64-bit size - quiet: Errors to ignore (empty to raise on all errors) Raises: - FdtException if no node found or other error occurs + FdtException on any error """ - return check_err(fdt_add_reservemap_entry(self._fdtrw, addr, size), - quiet) + while self.check_space(fdt_add_reservemap_entry(self._fdt, addr, + size)): + pass - def finish_reservemap(self, quiet=()): + def finish_reservemap(self): """Indicate that there are no more reserve map entries to add - Args: - quiet: Errors to ignore (empty to raise on all errors) - Raises: - FdtException if no node found or other error occurs + FdtException on any error """ - return check_err(fdt_finish_reservemap(self._fdtrw), quiet) + while self.check_space(fdt_finish_reservemap(self._fdt)): + pass - def begin_node(self, name, quiet=()): + def begin_node(self, name): """Begin a new node Use this before adding properties to the node. Then call end_node() to @@ -800,14 +818,14 @@ class FdtSw(object): Args: name: Name of node to begin - quiet: Errors to ignore (empty to raise on all errors) Raises: - FdtException if no node found or other error occurs + FdtException on any error """ - return check_err(fdt_begin_node(self._fdtrw, name), quiet) + while self.check_space(fdt_begin_node(self._fdt, name)): + pass - def property_string(self, name, string, quiet=()): + def property_string(self, name, string): """Add a property with a string value The string will be nul-terminated when written to the device tree @@ -815,14 +833,14 @@ class FdtSw(object): Args: name: Name of property to add string: String value of property - quiet: Errors to ignore (empty to raise on all errors) Raises: - FdtException if no node found or other error occurs + FdtException on any error """ - return check_err(fdt_property_string(self._fdtrw, name, string), quiet) + while self.check_space(fdt_property_string(self._fdt, name, string)): + pass - def property_u32(self, name, val, quiet=()): + def property_u32(self, name, val): """Add a property with a 32-bit value Write a single-cell value to the device tree @@ -830,14 +848,14 @@ class FdtSw(object): Args: name: Name of property to add val: Value of property - quiet: Errors to ignore (empty to raise on all errors) Raises: - FdtException if no node found or other error occurs + FdtException on any error """ - return check_err(fdt_property_u32(self._fdtrw, name, val), quiet) + while self.check_space(fdt_property_u32(self._fdt, name, val)): + pass - def property_u64(self, name, val, quiet=()): + def property_u64(self, name, val): """Add a property with a 64-bit value Write a double-cell value to the device tree in big-endian format @@ -845,14 +863,14 @@ class FdtSw(object): Args: name: Name of property to add val: Value of property - quiet: Errors to ignore (empty to raise on all errors) Raises: - FdtException if no node found or other error occurs + FdtException on any error """ - return check_err(fdt_property_u64(self._fdtrw, name, val), quiet) + while self.check_space(fdt_property_u64(self._fdt, name, val)): + pass - def property_cell(self, name, val, quiet=()): + def property_cell(self, name, val): """Add a property with a single-cell value Write a single-cell value to the device tree @@ -863,11 +881,12 @@ class FdtSw(object): quiet: Errors to ignore (empty to raise on all errors) Raises: - FdtException if no node found or other error occurs + FdtException on any error """ - return check_err(fdt_property_cell(self._fdtrw, name, val), quiet) + while self.check_space(fdt_property_cell(self._fdt, name, val)): + pass - def property(self, name, val, quiet=()): + def property(self, name, val): """Add a property Write a new property with the given value to the device tree. The value @@ -879,11 +898,13 @@ class FdtSw(object): quiet: Errors to ignore (empty to raise on all errors) Raises: - FdtException if no node found or other error occurs + FdtException on any error """ - return check_err(_fdt_property(self._fdtrw, name, val, len(val)), quiet) + while self.check_space(fdt_property_stub(self._fdt, name, val, + len(val))): + pass - def end_node(self, quiet=()): + def end_node(self): """End a node Use this after adding properties to a node to close it off. You can also @@ -893,24 +914,12 @@ class FdtSw(object): quiet: Errors to ignore (empty to raise on all errors) Raises: - FdtException if no node found or other error occurs - """ - return check_err(fdt_end_node(self._fdtrw), quiet) - - def finish(self, quiet=()): - """Finish writing the device tree - - This closes off the device tree ready for use - - Args: - quiet: Errors to ignore (empty to raise on all errors) - - Raises: - FdtException if no node found or other error occurs + FdtException on any error """ - return check_err(fdt_finish(self._fdtrw), quiet) + while self.check_space(fdt_end_node(self._fdt)): + pass - def AddNode(self, name): + def add_node(self, name): """Create a new context for adding a node When used in a 'with' clause this starts a new node and finishes it @@ -919,7 +928,7 @@ class FdtSw(object): Args: name: Name of node to add """ - return NodeAdder(self._fdtrw, name) + return NodeAdder(self, name) class NodeAdder(): @@ -927,26 +936,30 @@ class NodeAdder(): This allows you to add nodes in a more natural way: - with fdtsw.AddNode('name'): + with fdtsw.add_node('name'): fdtsw.property_string('test', 'value') The node is automatically completed with a call to end_node() when the context exits. """ - def __init__(self, fdt, name): - self._fdt = fdt + def __init__(self, fdtsw, name): + self._fdt = fdtsw self._name = name def __enter__(self): - check_err(fdt_begin_node(self._fdt, self._name)) + self._fdt.begin_node(self._name) def __exit__(self, type, value, traceback): - check_err(fdt_end_node(self._fdt)) + self._fdt.end_node() %} %rename(fdt_property) fdt_property_func; -typedef int fdt32_t; +/* + * fdt32_t is a big-endian 32-bit value defined to uint32_t in libfdt_env.h + * so use the same type here. + */ +typedef uint32_t fdt32_t; %include "libfdt/fdt.h" @@ -1039,16 +1052,17 @@ typedef int fdt32_t; %warnfilter(302) fdt_property; /* These are macros in the header so have to be redefined here */ -int fdt_magic(const void *fdt); -int fdt_totalsize(const void *fdt); -int fdt_off_dt_struct(const void *fdt); -int fdt_off_dt_strings(const void *fdt); -int fdt_off_mem_rsvmap(const void *fdt); -int fdt_version(const void *fdt); -int fdt_last_comp_version(const void *fdt); -int fdt_boot_cpuid_phys(const void *fdt); -int fdt_size_dt_strings(const void *fdt); -int fdt_size_dt_struct(const void *fdt); +uint32_t fdt_magic(const void *fdt); +uint32_t fdt_totalsize(const void *fdt); +uint32_t fdt_off_dt_struct(const void *fdt); +uint32_t fdt_off_dt_strings(const void *fdt); +uint32_t fdt_off_mem_rsvmap(const void *fdt); +uint32_t fdt_version(const void *fdt); +uint32_t fdt_last_comp_version(const void *fdt); +uint32_t fdt_boot_cpuid_phys(const void *fdt); +uint32_t fdt_size_dt_strings(const void *fdt); +uint32_t fdt_size_dt_struct(const void *fdt); + int fdt_property_string(void *fdt, const char *name, const char *val); int fdt_property_cell(void *fdt, const char *name, uint32_t val); @@ -1056,6 +1070,6 @@ int fdt_property_cell(void *fdt, const char *name, uint32_t val); * This function has a stub since the name fdt_property is used for both a * function and a struct, which confuses SWIG. */ -int _fdt_property(void *fdt, const char *name, const char *val, int len); +int fdt_property_stub(void *fdt, const char *name, const char *val, int len); %include <../libfdt/libfdt.h> |