Index: vendor/dtc/dist/Documentation/manual.txt =================================================================== --- vendor/dtc/dist/Documentation/manual.txt (revision 327892) +++ vendor/dtc/dist/Documentation/manual.txt (revision 327893) @@ -1,677 +1,695 @@ Device Tree Compiler Manual =========================== I - "dtc", the device tree compiler 1) Obtaining Sources 1.1) Submitting Patches 2) Description 3) Command Line 4) Source File 4.1) Overview 4.2) Properties 4.3) Labels and References II - The DT block format 1) Header 2) Device tree generalities 3) Device tree "structure" block 4) Device tree "strings" block III - libfdt IV - Utility Tools 1) convert-dtsv0 -- Conversion to Version 1 1) fdtdump I - "dtc", the device tree compiler =================================== 1) Sources Source code for the Device Tree Compiler can be found at git.kernel.org. The upstream repository is here: git://git.kernel.org/pub/scm/utils/dtc/dtc.git https://git.kernel.org/pub/scm/utils/dtc/dtc.git The gitweb interface for the upstream respository is: https://git.kernel.org/cgit/utils/dtc/dtc.git/ 1.1) Submitting Patches Patches should be sent to the maintainers: David Gibson Jon Loeliger and CCed to . 2) Description The Device Tree Compiler, dtc, takes as input a device-tree in a given format and outputs a device-tree in another format. Typically, the input format is "dts", a human readable source format, and creates a "dtb", or binary format as output. The currently supported Input Formats are: - "dtb": "blob" format. A flattened device-tree block with header in one binary blob. - "dts": "source" format. A text file containing a "source" for a device-tree. - "fs" format. A representation equivalent to the output of /proc/device-tree where nodes are directories and properties are files. The currently supported Output Formats are: - "dtb": "blob" format - "dts": "source" format - "asm": assembly language file. A file that can be sourced by gas to generate a device-tree "blob". That file can then simply be added to your Makefile. Additionally, the assembly file exports some symbols that can be used. 3) Command Line The syntax of the dtc command line is: dtc [options] [] Options: The name of the input source file. If no or "-" is given, stdin is used. -b Set the physical boot cpu. -f Force. Try to produce output even if the input tree has errors. -h Emit a brief usage and help message. -I The source input format, as listed above. -o The name of the generated output file. Use "-" for stdout. -O The generated output format, as listed above. -d Generate a dependency file during compilation. -q Quiet: -q suppress warnings, -qq errors, -qqq all -R Make space for reserve map entries Relevant for dtb and asm output only. -@ Generates a __symbols__ node at the root node of the resulting blob for any node labels used, and for any local references using phandles it also generates a __local_fixups__ node that tracks them. When using the /plugin/ tag all unresolved label references to be tracked in the __fixups__ node, making dynamic resolution possible. -A Generate automatically aliases for all node labels. This is similar to the -@ option (the __symbols__ node contain identical information) but the semantics are slightly different since no phandles are automatically generated for labeled nodes. -S Ensure the blob at least long, adding additional space if needed. -v Print DTC version and exit. -V Generate output conforming to the given . By default the most recent version is generated. Relevant for dtb and asm output only. The defines what version of the "blob" format will be generated. Supported versions are 1, 2, 3, 16 and 17. The default is always the most recent version and is likely the highest number. Additionally, dtc performs various sanity checks on the tree. 4) Device Tree Source file 4.1) Overview Here is a very rough overview of the layout of a DTS source file: sourcefile: versioninfo plugindecl list_of_memreserve devicetree memreserve: label 'memreserve' ADDR ADDR ';' | label 'memreserve' ADDR '-' ADDR ';' devicetree: '/' nodedef versioninfo: '/' 'dts-v1' '/' ';' plugindecl: '/' 'plugin' '/' ';' | /* empty */ nodedef: '{' list_of_property list_of_subnode '}' ';' property: label PROPNAME '=' propdata ';' propdata: STRING | '<' list_of_cells '>' | '[' list_of_bytes ']' subnode: label nodename nodedef That structure forms a hierarchical layout of nodes and properties rooted at an initial node as: / { } Both classic C style and C++ style comments are supported. Source files may be directly included using the syntax: /include/ "filename" 4.2) Properties Properties are named, possibly labeled, values. Each value is one of: - A null-teminated C-like string, - A numeric value fitting in 32 bits, - A list of 32-bit values - A byte sequence Here are some example property definitions: - A property containing a 0 terminated string property1 = "string_value"; - A property containing a numerical 32-bit hexadecimal value property2 = <1234abcd>; - A property containing 3 numerical 32-bit hexadecimal values property3 = <12345678 12345678 deadbeef>; - A property whose content is an arbitrary array of bytes property4 = [0a 0b 0c 0d de ea ad be ef]; Node may contain sub-nodes to obtain a hierarchical structure. For example: - A child node named "childnode" whose unit name is "childnode at address". It in turn has a string property called "childprop". childnode@addresss { childprop = "hello\n"; }; By default, all numeric values are hexadecimal. Alternate bases may be specified using a prefix "d#" for decimal, "b#" for binary, and "o#" for octal. Strings support common escape sequences from C: "\n", "\t", "\r", "\(octal value)", "\x(hex value)". 4.3) Labels and References Labels may be applied to nodes or properties. Labels appear before a node name, and are referenced using an ampersand: &label. Absolute node path names are also allowed in node references. In this exmaple, a node is labled "mpic" and then referenced: mpic: interrupt-controller@40000 { ... }; ethernet-phy@3 { interrupt-parent = <&mpic>; ... }; And used in properties, lables may appear before or after any value: randomnode { prop: string = data: "mystring\n" data_end: ; ... }; II - The DT block format ======================== This chapter defines the format of the flattened device-tree passed to the kernel. The actual content of the device tree are described in the kernel documentation in the file linux-2.6/Documentation/powerpc/booting-without-of.txt You can find example of code manipulating that format within the kernel. For example, the file: including arch/powerpc/kernel/prom_init.c will generate a flattened device-tree from the Open Firmware representation. Other utilities such as fs2dt, which is part of the kexec tools, will generate one from a filesystem representation. Some bootloaders such as U-Boot provide a bit more support by using the libfdt code. For booting the kernel, the device tree block has to be in main memory. It has to be accessible in both real mode and virtual mode with no mapping other than main memory. If you are writing a simple flash bootloader, it should copy the block to RAM before passing it to the kernel. 1) Header --------- The kernel is entered with r3 pointing to an area of memory that is roughly described in include/asm-powerpc/prom.h by the structure boot_param_header: struct boot_param_header { u32 magic; /* magic word OF_DT_HEADER */ u32 totalsize; /* total size of DT block */ u32 off_dt_struct; /* offset to structure */ u32 off_dt_strings; /* offset to strings */ u32 off_mem_rsvmap; /* offset to memory reserve map */ u32 version; /* format version */ u32 last_comp_version; /* last compatible version */ /* version 2 fields below */ u32 boot_cpuid_phys; /* Which physical CPU id we're booting on */ /* version 3 fields below */ u32 size_dt_strings; /* size of the strings block */ /* version 17 fields below */ u32 size_dt_struct; /* size of the DT structure block */ }; Along with the constants: /* Definitions used by the flattened device tree */ #define OF_DT_HEADER 0xd00dfeed /* 4: version, 4: total size */ #define OF_DT_BEGIN_NODE 0x1 /* Start node: full name */ #define OF_DT_END_NODE 0x2 /* End node */ #define OF_DT_PROP 0x3 /* Property: name off, size, content */ #define OF_DT_END 0x9 All values in this header are in big endian format, the various fields in this header are defined more precisely below. All "offset" values are in bytes from the start of the header; that is from the value of r3. - magic This is a magic value that "marks" the beginning of the device-tree block header. It contains the value 0xd00dfeed and is defined by the constant OF_DT_HEADER - totalsize This is the total size of the DT block including the header. The "DT" block should enclose all data structures defined in this chapter (who are pointed to by offsets in this header). That is, the device-tree structure, strings, and the memory reserve map. - off_dt_struct This is an offset from the beginning of the header to the start of the "structure" part the device tree. (see 2) device tree) - off_dt_strings This is an offset from the beginning of the header to the start of the "strings" part of the device-tree - off_mem_rsvmap This is an offset from the beginning of the header to the start of the reserved memory map. This map is a list of pairs of 64- bit integers. Each pair is a physical address and a size. The list is terminated by an entry of size 0. This map provides the kernel with a list of physical memory areas that are "reserved" and thus not to be used for memory allocations, especially during early initialization. The kernel needs to allocate memory during boot for things like un-flattening the device-tree, allocating an MMU hash table, etc... Those allocations must be done in such a way to avoid overriding critical things like, on Open Firmware capable machines, the RTAS instance, or on some pSeries, the TCE tables used for the iommu. Typically, the reserve map should contain _at least_ this DT block itself (header,total_size). If you are passing an initrd to the kernel, you should reserve it as well. You do not need to reserve the kernel image itself. The map should be 64-bit aligned. - version This is the version of this structure. Version 1 stops here. Version 2 adds an additional field boot_cpuid_phys. Version 3 adds the size of the strings block, allowing the kernel to reallocate it easily at boot and free up the unused flattened structure after expansion. Version 16 introduces a new more "compact" format for the tree itself that is however not backward compatible. Version 17 adds an additional field, size_dt_struct, allowing it to be reallocated or moved more easily (this is particularly useful for bootloaders which need to make adjustments to a device tree based on probed information). You should always generate a structure of the highest version defined at the time of your implementation. Currently that is version 17, unless you explicitly aim at being backward compatible. - last_comp_version Last compatible version. This indicates down to what version of the DT block you are backward compatible. For example, version 2 is backward compatible with version 1 (that is, a kernel build for version 1 will be able to boot with a version 2 format). You should put a 1 in this field if you generate a device tree of version 1 to 3, or 16 if you generate a tree of version 16 or 17 using the new unit name format. - boot_cpuid_phys This field only exist on version 2 headers. It indicate which physical CPU ID is calling the kernel entry point. This is used, among others, by kexec. If you are on an SMP system, this value should match the content of the "reg" property of the CPU node in the device-tree corresponding to the CPU calling the kernel entry point (see further chapters for more informations on the required device-tree contents) - size_dt_strings This field only exists on version 3 and later headers. It gives the size of the "strings" section of the device tree (which starts at the offset given by off_dt_strings). - size_dt_struct This field only exists on version 17 and later headers. It gives the size of the "structure" section of the device tree (which starts at the offset given by off_dt_struct). So the typical layout of a DT block (though the various parts don't need to be in that order) looks like this (addresses go from top to bottom): ------------------------------ r3 -> | struct boot_param_header | ------------------------------ | (alignment gap) (*) | ------------------------------ | memory reserve map | ------------------------------ | (alignment gap) | ------------------------------ | | | device-tree structure | | | ------------------------------ | (alignment gap) | ------------------------------ | | | device-tree strings | | | -----> ------------------------------ | | --- (r3 + totalsize) (*) The alignment gaps are not necessarily present; their presence and size are dependent on the various alignment requirements of the individual data blocks. 2) Device tree generalities --------------------------- This device-tree itself is separated in two different blocks, a structure block and a strings block. Both need to be aligned to a 4 byte boundary. First, let's quickly describe the device-tree concept before detailing the storage format. This chapter does _not_ describe the detail of the required types of nodes & properties for the kernel, this is done later in chapter III. The device-tree layout is strongly inherited from the definition of the Open Firmware IEEE 1275 device-tree. It's basically a tree of nodes, each node having two or more named properties. A property can have a value or not. It is a tree, so each node has one and only one parent except for the root node who has no parent. A node has 2 names. The actual node name is generally contained in a property of type "name" in the node property list whose value is a zero terminated string and is mandatory for version 1 to 3 of the format definition (as it is in Open Firmware). Version 16 makes it optional as it can generate it from the unit name defined below. There is also a "unit name" that is used to differentiate nodes with the same name at the same level, it is usually made of the node names, the "@" sign, and a "unit address", which definition is specific to the bus type the node sits on. The unit name doesn't exist as a property per-se but is included in the device-tree structure. It is typically used to represent "path" in the device-tree. More details about the actual format of these will be below. The kernel powerpc generic code does not make any formal use of the unit address (though some board support code may do) so the only real requirement here for the unit address is to ensure uniqueness of the node unit name at a given level of the tree. Nodes with no notion of address and no possible sibling of the same name (like /memory or /cpus) may omit the unit address in the context of this specification, or use the "@0" default unit address. The unit name is used to define a node "full path", which is the concatenation of all parent node unit names separated with "/". The root node doesn't have a defined name, and isn't required to have a name property either if you are using version 3 or earlier of the format. It also has no unit address (no @ symbol followed by a unit address). The root node unit name is thus an empty string. The full path to the root node is "/". Every node which actually represents an actual device (that is, a node which isn't only a virtual "container" for more nodes, like "/cpus" is) is also required to have a "device_type" property indicating the type of node . Finally, every node that can be referenced from a property in another node is required to have a "linux,phandle" property. Real open firmware implementations provide a unique "phandle" value for every node that the "prom_init()" trampoline code turns into "linux,phandle" properties. However, this is made optional if the flattened device tree is used directly. An example of a node referencing another node via "phandle" is when laying out the interrupt tree which will be described in a further version of this document. This "linux, phandle" property is a 32-bit value that uniquely identifies a node. You are free to use whatever values or system of values, internal pointers, or whatever to generate these, the only requirement is that every node for which you provide that property has a unique value for it. Here is an example of a simple device-tree. In this example, an "o" designates a node followed by the node unit name. Properties are presented with their name followed by their content. "content" represents an ASCII string (zero terminated) value, while represents a 32-bit hexadecimal value. The various nodes in this example will be discussed in a later chapter. At this point, it is only meant to give you a idea of what a device-tree looks like. I have purposefully kept the "name" and "linux,phandle" properties which aren't necessary in order to give you a better idea of what the tree looks like in practice. / o device-tree |- name = "device-tree" |- model = "MyBoardName" |- compatible = "MyBoardFamilyName" |- #address-cells = <2> |- #size-cells = <2> |- linux,phandle = <0> | o cpus | | - name = "cpus" | | - linux,phandle = <1> | | - #address-cells = <1> | | - #size-cells = <0> | | | o PowerPC,970@0 | |- name = "PowerPC,970" | |- device_type = "cpu" | |- reg = <0> | |- clock-frequency = <5f5e1000> | |- 64-bit | |- linux,phandle = <2> | o memory@0 | |- name = "memory" | |- device_type = "memory" | |- reg = <00000000 00000000 00000000 20000000> | |- linux,phandle = <3> | o chosen |- name = "chosen" |- bootargs = "root=/dev/sda2" |- linux,phandle = <4> This tree is almost a minimal tree. It pretty much contains the minimal set of required nodes and properties to boot a linux kernel; that is, some basic model informations at the root, the CPUs, and the physical memory layout. It also includes misc information passed through /chosen, like in this example, the platform type (mandatory) and the kernel command line arguments (optional). The /cpus/PowerPC,970@0/64-bit property is an example of a property without a value. All other properties have a value. The significance of the #address-cells and #size-cells properties will be explained in chapter IV which defines precisely the required nodes and properties and their content. 3) Device tree "structure" block The structure of the device tree is a linearized tree structure. The "OF_DT_BEGIN_NODE" token starts a new node, and the "OF_DT_END_NODE" ends that node definition. Child nodes are simply defined before "OF_DT_END_NODE" (that is nodes within the node). A 'token' is a 32 bit value. The tree has to be "finished" with a OF_DT_END token Here's the basic structure of a single node: * token OF_DT_BEGIN_NODE (that is 0x00000001) * for version 1 to 3, this is the node full path as a zero terminated string, starting with "/". For version 16 and later, this is the node unit name only (or an empty string for the root node) * [align gap to next 4 bytes boundary] * for each property: * token OF_DT_PROP (that is 0x00000003) * 32-bit value of property value size in bytes (or 0 if no value) * 32-bit value of offset in string block of property name * property value data if any * [align gap to next 4 bytes boundary] * [child nodes if any] * token OF_DT_END_NODE (that is 0x00000002) So the node content can be summarized as a start token, a full path, a list of properties, a list of child nodes, and an end token. Every child node is a full node structure itself as defined above. NOTE: The above definition requires that all property definitions for a particular node MUST precede any subnode definitions for that node. Although the structure would not be ambiguous if properties and subnodes were intermingled, the kernel parser requires that the properties come first (up until at least 2.6.22). Any tools manipulating a flattened tree must take care to preserve this constraint. 4) Device tree "strings" block In order to save space, property names, which are generally redundant, are stored separately in the "strings" block. This block is simply the whole bunch of zero terminated strings for all property names concatenated together. The device-tree property definitions in the structure block will contain offset values from the beginning of the strings block. III - libfdt ============ This library should be merged into dtc proper. This library should likely be worked into U-Boot and the kernel. IV - Utility Tools ================== 1) convert-dtsv0 -- Conversion to Version 1 convert-dtsv0 is a small utility program which converts (DTS) Device Tree Source from the obsolete version 0 to version 1. Version 1 DTS files are marked by line "/dts-v1/;" at the top of the file. The syntax of the convert-dtsv0 command line is: convert-dtsv0 [] Each file passed will be converted to the new /dts-v1/ version by creating a new file with a "v1" appended the filename. Comments, empty lines, etc. are preserved. 2) fdtdump -- Flat Device Tree dumping utility The fdtdump program prints a readable version of a flat device tree file. The syntax of the fdtdump command line is: - fdtdump + fdtdump [options] + +Where options are: + -d,--debug Dump debug information while decoding the file + -s,--scan Scan for an embedded fdt in given file + +3) fdtoverlay -- Flat Device Tree overlay applicator + +The fdtoverlay applies an arbitrary number of FDT overlays to a base FDT blob +to a given output file. + +The syntax of the fdtoverlay command line is: + + fdtoverlay -i -o [ ...] + +Where options are: + -i, --input Input base DT blob + -o, --output Output DT blob + -v, --verbose Verbose message output Index: vendor/dtc/dist/Makefile =================================================================== --- vendor/dtc/dist/Makefile (revision 327892) +++ vendor/dtc/dist/Makefile (revision 327893) @@ -1,300 +1,354 @@ # # Device Tree Compiler # # # Version information will be constructed in this order: # EXTRAVERSION might be "-rc", for example. # LOCAL_VERSION is likely from command line. # CONFIG_LOCALVERSION from some future config system. # VERSION = 1 PATCHLEVEL = 4 -SUBLEVEL = 3 +SUBLEVEL = 6 EXTRAVERSION = LOCAL_VERSION = CONFIG_LOCALVERSION = CPPFLAGS = -I libfdt -I . WARNINGS = -Wall -Wpointer-arith -Wcast-qual -Wnested-externs \ -Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls -Wshadow -CFLAGS = -g -Os -fPIC -Werror $(WARNINGS) +CFLAGS = -g -Os $(SHAREDLIB_CFLAGS) -Werror $(WARNINGS) BISON = bison LEX = flex +SWIG = swig +PKG_CONFIG ?= pkg-config INSTALL = /usr/bin/install DESTDIR = PREFIX = $(HOME) BINDIR = $(PREFIX)/bin LIBDIR = $(PREFIX)/lib INCLUDEDIR = $(PREFIX)/include HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \ - sed -e 's/\(cygwin\).*/cygwin/') + sed -e 's/\(cygwin\|msys\).*/\1/') ifeq ($(HOSTOS),darwin) -SHAREDLIB_EXT=dylib -SHAREDLIB_LINK_OPTIONS=-dynamiclib -Wl,-install_name -Wl, +SHAREDLIB_EXT = dylib +SHAREDLIB_CFLAGS = -fPIC +SHAREDLIB_LDFLAGS = -fPIC -dynamiclib -Wl,-install_name -Wl, +else ifeq ($(HOSTOS),$(filter $(HOSTOS),msys cygwin)) +SHAREDLIB_EXT = so +SHAREDLIB_CFLAGS = +SHAREDLIB_LDFLAGS = -shared -Wl,--version-script=$(LIBFDT_version) -Wl,-soname, else -SHAREDLIB_EXT=so -SHAREDLIB_LINK_OPTIONS=-shared -Wl,--version-script=$(LIBFDT_version) -Wl,-soname, +SHAREDLIB_EXT = so +SHAREDLIB_CFLAGS = -fPIC +SHAREDLIB_LDFLAGS = -fPIC -shared -Wl,--version-script=$(LIBFDT_version) -Wl,-soname, endif # # Overall rules # ifdef V VECHO = : else VECHO = echo " " ARFLAGS = rc .SILENT: endif NODEPTARGETS = clean ifeq ($(MAKECMDGOALS),) DEPTARGETS = all else DEPTARGETS = $(filter-out $(NODEPTARGETS),$(MAKECMDGOALS)) endif # # Rules for versioning # DTC_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) VERSION_FILE = version_gen.h CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ else if [ -x /bin/bash ]; then echo /bin/bash; \ else echo sh; fi ; fi) nullstring := space := $(nullstring) # end of line localver_config = $(subst $(space),, $(string) \ $(patsubst "%",%,$(CONFIG_LOCALVERSION))) localver_cmd = $(subst $(space),, $(string) \ $(patsubst "%",%,$(LOCALVERSION))) localver_scm = $(shell $(CONFIG_SHELL) ./scripts/setlocalversion) localver_full = $(localver_config)$(localver_cmd)$(localver_scm) dtc_version = $(DTC_VERSION)$(localver_full) # Contents of the generated version file. define filechk_version (echo "#define DTC_VERSION \"DTC $(dtc_version)\""; ) endef define filechk set -e; \ echo ' CHK $@'; \ mkdir -p $(dir $@); \ $(filechk_$(1)) < $< > $@.tmp; \ if [ -r $@ ] && cmp -s $@ $@.tmp; then \ rm -f $@.tmp; \ else \ echo ' UPD $@'; \ mv -f $@.tmp $@; \ fi; endef include Makefile.convert-dtsv0 include Makefile.dtc include Makefile.utils BIN += convert-dtsv0 BIN += dtc BIN += fdtdump BIN += fdtget BIN += fdtput +BIN += fdtoverlay SCRIPTS = dtdiff all: $(BIN) libfdt +# We need both Python and swig to build pylibfdt. +.PHONY: maybe_pylibfdt +maybe_pylibfdt: FORCE + if $(PKG_CONFIG) --cflags python2 >/dev/null 2>&1; then \ + if which swig >/dev/null 2>&1; then \ + can_build=yes; \ + fi; \ + fi; \ + if [ "$$can_build" = "yes" ]; then \ + $(MAKE) pylibfdt; \ + else \ + echo "## Skipping pylibfdt (install python dev and swig to build)"; \ + fi +ifeq ($(NO_PYTHON),) +all: maybe_pylibfdt +endif + + ifneq ($(DEPTARGETS),) -include $(DTC_OBJS:%.o=%.d) -include $(CONVERT_OBJS:%.o=%.d) -include $(FDTDUMP_OBJS:%.o=%.d) -include $(FDTGET_OBJS:%.o=%.d) -include $(FDTPUT_OBJS:%.o=%.d) +-include $(FDTOVERLAY_OBJS:%.o=%.d) endif # # Rules for libfdt # LIBFDT_objdir = libfdt LIBFDT_srcdir = libfdt LIBFDT_archive = $(LIBFDT_objdir)/libfdt.a LIBFDT_lib = $(LIBFDT_objdir)/libfdt-$(DTC_VERSION).$(SHAREDLIB_EXT) LIBFDT_include = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_INCLUDES)) LIBFDT_version = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_VERSION)) include $(LIBFDT_srcdir)/Makefile.libfdt .PHONY: libfdt libfdt: $(LIBFDT_archive) $(LIBFDT_lib) $(LIBFDT_archive): $(addprefix $(LIBFDT_objdir)/,$(LIBFDT_OBJS)) $(LIBFDT_lib): $(addprefix $(LIBFDT_objdir)/,$(LIBFDT_OBJS)) libfdt_clean: @$(VECHO) CLEAN "(libfdt)" rm -f $(addprefix $(LIBFDT_objdir)/,$(STD_CLEANFILES)) rm -f $(LIBFDT_objdir)/*.so ifneq ($(DEPTARGETS),) -include $(LIBFDT_OBJS:%.o=$(LIBFDT_objdir)/%.d) endif # This stops make from generating the lex and bison output during # auto-dependency computation, but throwing them away as an # intermediate target and building them again "for real" .SECONDARY: $(DTC_GEN_SRCS) $(CONVERT_GEN_SRCS) install-bin: all $(SCRIPTS) @$(VECHO) INSTALL-BIN $(INSTALL) -d $(DESTDIR)$(BINDIR) $(INSTALL) $(BIN) $(SCRIPTS) $(DESTDIR)$(BINDIR) install-lib: all @$(VECHO) INSTALL-LIB $(INSTALL) -d $(DESTDIR)$(LIBDIR) $(INSTALL) $(LIBFDT_lib) $(DESTDIR)$(LIBDIR) ln -sf $(notdir $(LIBFDT_lib)) $(DESTDIR)$(LIBDIR)/$(LIBFDT_soname) ln -sf $(LIBFDT_soname) $(DESTDIR)$(LIBDIR)/libfdt.$(SHAREDLIB_EXT) $(INSTALL) -m 644 $(LIBFDT_archive) $(DESTDIR)$(LIBDIR) install-includes: @$(VECHO) INSTALL-INC $(INSTALL) -d $(DESTDIR)$(INCLUDEDIR) $(INSTALL) -m 644 $(LIBFDT_include) $(DESTDIR)$(INCLUDEDIR) install: install-bin install-lib install-includes +ifeq ($(NO_PYTHON),) +install: install_pylibfdt +endif + $(VERSION_FILE): Makefile FORCE $(call filechk,version) dtc: $(DTC_OBJS) convert-dtsv0: $(CONVERT_OBJS) @$(VECHO) LD $@ $(LINK.c) -o $@ $^ fdtdump: $(FDTDUMP_OBJS) fdtget: $(FDTGET_OBJS) $(LIBFDT_archive) fdtput: $(FDTPUT_OBJS) $(LIBFDT_archive) +fdtoverlay: $(FDTOVERLAY_OBJS) $(LIBFDT_archive) + dist: git archive --format=tar --prefix=dtc-$(dtc_version)/ HEAD \ > ../dtc-$(dtc_version).tar cat ../dtc-$(dtc_version).tar | \ gzip -9 > ../dtc-$(dtc_version).tar.gz + # +# Rules for pylibfdt +# +PYLIBFDT_srcdir = pylibfdt +PYLIBFDT_objdir = pylibfdt + +include $(PYLIBFDT_srcdir)/Makefile.pylibfdt + +.PHONY: pylibfdt +pylibfdt: $(PYLIBFDT_objdir)/_libfdt.so + +pylibfdt_clean: + @$(VECHO) CLEAN "(pylibfdt)" + rm -f $(addprefix $(PYLIBFDT_objdir)/,$(PYLIBFDT_cleanfiles)) + +# # Release signing and uploading # This is for maintainer convenience, don't try this at home. # ifeq ($(MAINTAINER),y) GPG = gpg2 KUP = kup KUPDIR = /pub/software/utils/dtc kup: dist $(GPG) --detach-sign --armor -o ../dtc-$(dtc_version).tar.sign \ ../dtc-$(dtc_version).tar $(KUP) put ../dtc-$(dtc_version).tar.gz ../dtc-$(dtc_version).tar.sign \ $(KUPDIR)/dtc-$(dtc_version).tar.gz endif tags: FORCE rm -f tags find . \( -name tests -type d -prune \) -o \ \( ! -name '*.tab.[ch]' ! -name '*.lex.c' \ -name '*.[chly]' -type f -print \) | xargs ctags -a # # Testsuite rules # TESTS_PREFIX=tests/ TESTS_BIN += dtc TESTS_BIN += convert-dtsv0 TESTS_BIN += fdtput TESTS_BIN += fdtget TESTS_BIN += fdtdump +TESTS_BIN += fdtoverlay +ifeq ($(NO_PYTHON),) +TESTS_PYLIBFDT += maybe_pylibfdt +endif include tests/Makefile.tests # # Clean rules # STD_CLEANFILES = *~ *.o *.$(SHAREDLIB_EXT) *.d *.a *.i *.s core a.out vgcore.* \ *.tab.[ch] *.lex.c *.output -clean: libfdt_clean tests_clean +clean: libfdt_clean pylibfdt_clean tests_clean @$(VECHO) CLEAN rm -f $(STD_CLEANFILES) rm -f $(VERSION_FILE) rm -f $(BIN) rm -f dtc-*.tar dtc-*.tar.sign dtc-*.tar.asc # # Generic compile rules # %: %.o @$(VECHO) LD $@ $(LINK.c) -o $@ $^ %.o: %.c @$(VECHO) CC $@ $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $< %.o: %.S @$(VECHO) AS $@ $(CC) $(CPPFLAGS) $(AFLAGS) -D__ASSEMBLY__ -o $@ -c $< %.d: %.c @$(VECHO) DEP $< $(CC) $(CPPFLAGS) -MM -MG -MT "$*.o $@" $< > $@ %.d: %.S @$(VECHO) DEP $< $(CC) $(CPPFLAGS) -MM -MG -MT "$*.o $@" $< > $@ %.i: %.c @$(VECHO) CPP $@ $(CC) $(CPPFLAGS) -E $< > $@ %.s: %.c @$(VECHO) CC -S $@ $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -S $< %.a: @$(VECHO) AR $@ $(AR) $(ARFLAGS) $@ $^ $(LIBFDT_lib): @$(VECHO) LD $@ - $(CC) $(LDFLAGS) -fPIC $(SHAREDLIB_LINK_OPTIONS)$(LIBFDT_soname) -o $(LIBFDT_lib) $^ + $(CC) $(LDFLAGS) $(SHAREDLIB_LDFLAGS)$(LIBFDT_soname) -o $(LIBFDT_lib) $^ %.lex.c: %.l @$(VECHO) LEX $@ $(LEX) -o$@ $< %.tab.c %.tab.h %.output: %.y @$(VECHO) BISON $@ $(BISON) -d $< FORCE: Index: vendor/dtc/dist/Makefile.utils =================================================================== --- vendor/dtc/dist/Makefile.utils (revision 327892) +++ vendor/dtc/dist/Makefile.utils (revision 327893) @@ -1,24 +1,30 @@ # # This is not a complete Makefile of itself. Instead, it is designed to # be easily embeddable into other systems of Makefiles. # FDTDUMP_SRCS = \ fdtdump.c \ util.c FDTDUMP_OBJS = $(FDTDUMP_SRCS:%.c=%.o) FDTGET_SRCS = \ fdtget.c \ util.c FDTGET_OBJS = $(FDTGET_SRCS:%.c=%.o) FDTPUT_SRCS = \ fdtput.c \ util.c FDTPUT_OBJS = $(FDTPUT_SRCS:%.c=%.o) + +FDTOVERLAY_SRCS = \ + fdtoverlay.c \ + util.c + +FDTOVERLAY_OBJS = $(FDTOVERLAY_SRCS:%.c=%.o) Index: vendor/dtc/dist/README =================================================================== --- vendor/dtc/dist/README (revision 327892) +++ vendor/dtc/dist/README (revision 327893) @@ -1,16 +1,93 @@ The source tree contains the Device Tree Compiler (dtc) toolchain for working with device tree source and binary files and also libfdt, a utility library for reading and manipulating the binary format. DTC and LIBFDT are maintained by: David Gibson Jon Loeliger + +Python library +-------------- + +A Python library is also available. To build this you will need to install +swig and Python development files. On Debian distributions: + + sudo apt-get install swig python-dev + +The library provides an Fdt class which you can use like this: + +$ PYTHONPATH=../pylibfdt python +>>> import libfdt +>>> fdt = libfdt.Fdt(open('test_tree1.dtb').read()) +>>> node = fdt.path_offset('/subnode@1') +>>> print node +124 +>>> prop_offset = fdt.first_property_offset(node) +>>> prop = fdt.get_property_by_offset(prop_offset) +>>> print '%s=%r' % (prop.name, prop.value) +compatible=bytearray(b'subnode1\x00') +>>> print '%s=%s' % (prop.name, prop.value) +compatible=subnode1 +>>> node2 = fdt.path_offset('/') +>>> print fdt.getprop(node2, 'compatible') +test_tree1 + +You will find tests in tests/pylibfdt_tests.py showing how to use each +method. Help is available using the Python help command, e.g.: + + $ cd pylibfdt + $ python -c "import libfdt; help(libfdt)" + +If you add new features, please check code coverage: + + $ sudo apt-get install python-pip python-pytest + $ sudo pip install coverage + $ cd tests + $ coverage run pylibfdt_tests.py + $ coverage html + # Open 'htmlcov/index.html' in your browser + + +To install the library via the normal setup.py method, use: + + ./pylibfdt/setup.py [--prefix=/path/to/install_dir] + +If --prefix is not provided, the default prefix is used, typically '/usr' +or '/usr/local'. See Python's distutils documentation for details. You can +also install via the Makefile if you like, but the above is more common. + +To install both libfdt and pylibfdt you can use: + + make install [SETUP_PREFIX=/path/to/install_dir] \ + [PREFIX=/path/to/install_dir] + +To disable building the python library, even if swig and Python are available, +use: + + make NO_PYTHON=1 + + +More work remains to support all of libfdt, including access to numeric +values. + + +Tests +----- + +Test files are kept in the tests/ directory. Use 'make check' to build and run +all tests. + +If you want to adjust a test file, be aware that tree_tree1.dts is compiled +and checked against a binary tree from assembler macros in trees.S. So +if you change that file you must change tree.S also. + + Mailing list ------------ The following list is for discussion about dtc and libfdt implementation mailto:devicetree-compiler@vger.kernel.org Core device tree bindings are discussed on the devicetree-spec list: mailto:devicetree-spec@vger.kernel.org Index: vendor/dtc/dist/checks.c =================================================================== --- vendor/dtc/dist/checks.c (revision 327892) +++ vendor/dtc/dist/checks.c (revision 327893) @@ -1,849 +1,1518 @@ /* * (C) Copyright David Gibson , IBM Corporation. 2007. * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ #include "dtc.h" #ifdef TRACE_CHECKS #define TRACE(c, ...) \ do { \ fprintf(stderr, "=== %s: ", (c)->name); \ fprintf(stderr, __VA_ARGS__); \ fprintf(stderr, "\n"); \ } while (0) #else #define TRACE(c, fmt, ...) do { } while (0) #endif enum checkstatus { UNCHECKED = 0, PREREQ, PASSED, FAILED, }; struct check; typedef void (*check_fn)(struct check *c, struct dt_info *dti, struct node *node); struct check { const char *name; check_fn fn; void *data; bool warn, error; enum checkstatus status; bool inprogress; int num_prereqs; struct check **prereq; }; -#define CHECK_ENTRY(_nm, _fn, _d, _w, _e, ...) \ - static struct check *_nm##_prereqs[] = { __VA_ARGS__ }; \ - static struct check _nm = { \ - .name = #_nm, \ - .fn = (_fn), \ - .data = (_d), \ - .warn = (_w), \ - .error = (_e), \ +#define CHECK_ENTRY(nm_, fn_, d_, w_, e_, ...) \ + static struct check *nm_##_prereqs[] = { __VA_ARGS__ }; \ + static struct check nm_ = { \ + .name = #nm_, \ + .fn = (fn_), \ + .data = (d_), \ + .warn = (w_), \ + .error = (e_), \ .status = UNCHECKED, \ - .num_prereqs = ARRAY_SIZE(_nm##_prereqs), \ - .prereq = _nm##_prereqs, \ + .num_prereqs = ARRAY_SIZE(nm_##_prereqs), \ + .prereq = nm_##_prereqs, \ }; -#define WARNING(_nm, _fn, _d, ...) \ - CHECK_ENTRY(_nm, _fn, _d, true, false, __VA_ARGS__) -#define ERROR(_nm, _fn, _d, ...) \ - CHECK_ENTRY(_nm, _fn, _d, false, true, __VA_ARGS__) -#define CHECK(_nm, _fn, _d, ...) \ - CHECK_ENTRY(_nm, _fn, _d, false, false, __VA_ARGS__) +#define WARNING(nm_, fn_, d_, ...) \ + CHECK_ENTRY(nm_, fn_, d_, true, false, __VA_ARGS__) +#define ERROR(nm_, fn_, d_, ...) \ + CHECK_ENTRY(nm_, fn_, d_, false, true, __VA_ARGS__) +#define CHECK(nm_, fn_, d_, ...) \ + CHECK_ENTRY(nm_, fn_, d_, false, false, __VA_ARGS__) -#ifdef __GNUC__ -static inline void check_msg(struct check *c, struct dt_info *dti, - const char *fmt, ...) __attribute__((format (printf, 3, 4))); -#endif -static inline void check_msg(struct check *c, struct dt_info *dti, - const char *fmt, ...) +static inline void PRINTF(3, 4) check_msg(struct check *c, struct dt_info *dti, + const char *fmt, ...) { va_list ap; va_start(ap, fmt); if ((c->warn && (quiet < 1)) || (c->error && (quiet < 2))) { fprintf(stderr, "%s: %s (%s): ", strcmp(dti->outname, "-") ? dti->outname : "", (c->error) ? "ERROR" : "Warning", c->name); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); } va_end(ap); } #define FAIL(c, dti, ...) \ do { \ TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \ (c)->status = FAILED; \ check_msg((c), dti, __VA_ARGS__); \ } while (0) static void check_nodes_props(struct check *c, struct dt_info *dti, struct node *node) { struct node *child; TRACE(c, "%s", node->fullpath); if (c->fn) c->fn(c, dti, node); for_each_child(node, child) check_nodes_props(c, dti, child); } static bool run_check(struct check *c, struct dt_info *dti) { struct node *dt = dti->dt; bool error = false; int i; assert(!c->inprogress); if (c->status != UNCHECKED) goto out; c->inprogress = true; for (i = 0; i < c->num_prereqs; i++) { struct check *prq = c->prereq[i]; error = error || run_check(prq, dti); if (prq->status != PASSED) { c->status = PREREQ; check_msg(c, dti, "Failed prerequisite '%s'", c->prereq[i]->name); } } if (c->status != UNCHECKED) goto out; check_nodes_props(c, dti, dt); if (c->status == UNCHECKED) c->status = PASSED; TRACE(c, "\tCompleted, status %d", c->status); out: c->inprogress = false; if ((c->status != PASSED) && (c->error)) error = true; return error; } /* * Utility check functions */ /* A check which always fails, for testing purposes only */ static inline void check_always_fail(struct check *c, struct dt_info *dti, struct node *node) { FAIL(c, dti, "always_fail check"); } CHECK(always_fail, check_always_fail, NULL); static void check_is_string(struct check *c, struct dt_info *dti, struct node *node) { struct property *prop; char *propname = c->data; prop = get_property(node, propname); if (!prop) return; /* Not present, assumed ok */ if (!data_is_one_string(prop->val)) FAIL(c, dti, "\"%s\" property in %s is not a string", propname, node->fullpath); } #define WARNING_IF_NOT_STRING(nm, propname) \ WARNING(nm, check_is_string, (propname)) #define ERROR_IF_NOT_STRING(nm, propname) \ ERROR(nm, check_is_string, (propname)) +static void check_is_string_list(struct check *c, struct dt_info *dti, + struct node *node) +{ + int rem, l; + struct property *prop; + char *propname = c->data; + char *str; + + prop = get_property(node, propname); + if (!prop) + return; /* Not present, assumed ok */ + + str = prop->val.val; + rem = prop->val.len; + while (rem > 0) { + l = strnlen(str, rem); + if (l == rem) { + FAIL(c, dti, "\"%s\" property in %s is not a string list", + propname, node->fullpath); + break; + } + rem -= l + 1; + str += l + 1; + } +} +#define WARNING_IF_NOT_STRING_LIST(nm, propname) \ + WARNING(nm, check_is_string_list, (propname)) +#define ERROR_IF_NOT_STRING_LIST(nm, propname) \ + ERROR(nm, check_is_string_list, (propname)) + static void check_is_cell(struct check *c, struct dt_info *dti, struct node *node) { struct property *prop; char *propname = c->data; prop = get_property(node, propname); if (!prop) return; /* Not present, assumed ok */ if (prop->val.len != sizeof(cell_t)) FAIL(c, dti, "\"%s\" property in %s is not a single cell", propname, node->fullpath); } #define WARNING_IF_NOT_CELL(nm, propname) \ WARNING(nm, check_is_cell, (propname)) #define ERROR_IF_NOT_CELL(nm, propname) \ ERROR(nm, check_is_cell, (propname)) /* * Structural check functions */ static void check_duplicate_node_names(struct check *c, struct dt_info *dti, struct node *node) { struct node *child, *child2; for_each_child(node, child) for (child2 = child->next_sibling; child2; child2 = child2->next_sibling) if (streq(child->name, child2->name)) FAIL(c, dti, "Duplicate node name %s", child->fullpath); } ERROR(duplicate_node_names, check_duplicate_node_names, NULL); static void check_duplicate_property_names(struct check *c, struct dt_info *dti, struct node *node) { struct property *prop, *prop2; for_each_property(node, prop) { for (prop2 = prop->next; prop2; prop2 = prop2->next) { if (prop2->deleted) continue; if (streq(prop->name, prop2->name)) FAIL(c, dti, "Duplicate property name %s in %s", prop->name, node->fullpath); } } } ERROR(duplicate_property_names, check_duplicate_property_names, NULL); #define LOWERCASE "abcdefghijklmnopqrstuvwxyz" #define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ" #define DIGITS "0123456789" #define PROPNODECHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-" #define PROPNODECHARSSTRICT LOWERCASE UPPERCASE DIGITS ",-" static void check_node_name_chars(struct check *c, struct dt_info *dti, struct node *node) { int n = strspn(node->name, c->data); if (n < strlen(node->name)) FAIL(c, dti, "Bad character '%c' in node %s", node->name[n], node->fullpath); } ERROR(node_name_chars, check_node_name_chars, PROPNODECHARS "@"); static void check_node_name_chars_strict(struct check *c, struct dt_info *dti, struct node *node) { int n = strspn(node->name, c->data); if (n < node->basenamelen) FAIL(c, dti, "Character '%c' not recommended in node %s", node->name[n], node->fullpath); } CHECK(node_name_chars_strict, check_node_name_chars_strict, PROPNODECHARSSTRICT); static void check_node_name_format(struct check *c, struct dt_info *dti, struct node *node) { if (strchr(get_unitname(node), '@')) FAIL(c, dti, "Node %s has multiple '@' characters in name", node->fullpath); } ERROR(node_name_format, check_node_name_format, NULL, &node_name_chars); static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti, struct node *node) { const char *unitname = get_unitname(node); struct property *prop = get_property(node, "reg"); if (!prop) { prop = get_property(node, "ranges"); if (prop && !prop->val.len) prop = NULL; } if (prop) { if (!unitname[0]) FAIL(c, dti, "Node %s has a reg or ranges property, but no unit name", node->fullpath); } else { if (unitname[0]) FAIL(c, dti, "Node %s has a unit name, but no reg property", node->fullpath); } } WARNING(unit_address_vs_reg, check_unit_address_vs_reg, NULL); static void check_property_name_chars(struct check *c, struct dt_info *dti, struct node *node) { struct property *prop; for_each_property(node, prop) { int n = strspn(prop->name, c->data); if (n < strlen(prop->name)) FAIL(c, dti, "Bad character '%c' in property name \"%s\", node %s", prop->name[n], prop->name, node->fullpath); } } ERROR(property_name_chars, check_property_name_chars, PROPNODECHARS); static void check_property_name_chars_strict(struct check *c, struct dt_info *dti, struct node *node) { struct property *prop; for_each_property(node, prop) { const char *name = prop->name; int n = strspn(name, c->data); if (n == strlen(prop->name)) continue; /* Certain names are whitelisted */ if (streq(name, "device_type")) continue; /* * # is only allowed at the beginning of property names not counting * the vendor prefix. */ if (name[n] == '#' && ((n == 0) || (name[n-1] == ','))) { name += n + 1; n = strspn(name, c->data); } if (n < strlen(name)) FAIL(c, dti, "Character '%c' not recommended in property name \"%s\", node %s", name[n], prop->name, node->fullpath); } } CHECK(property_name_chars_strict, check_property_name_chars_strict, PROPNODECHARSSTRICT); #define DESCLABEL_FMT "%s%s%s%s%s" #define DESCLABEL_ARGS(node,prop,mark) \ ((mark) ? "value of " : ""), \ ((prop) ? "'" : ""), \ ((prop) ? (prop)->name : ""), \ ((prop) ? "' in " : ""), (node)->fullpath static void check_duplicate_label(struct check *c, struct dt_info *dti, const char *label, struct node *node, struct property *prop, struct marker *mark) { struct node *dt = dti->dt; struct node *othernode = NULL; struct property *otherprop = NULL; struct marker *othermark = NULL; othernode = get_node_by_label(dt, label); if (!othernode) otherprop = get_property_by_label(dt, label, &othernode); if (!othernode) othermark = get_marker_label(dt, label, &othernode, &otherprop); if (!othernode) return; if ((othernode != node) || (otherprop != prop) || (othermark != mark)) FAIL(c, dti, "Duplicate label '%s' on " DESCLABEL_FMT " and " DESCLABEL_FMT, label, DESCLABEL_ARGS(node, prop, mark), DESCLABEL_ARGS(othernode, otherprop, othermark)); } static void check_duplicate_label_node(struct check *c, struct dt_info *dti, struct node *node) { struct label *l; struct property *prop; for_each_label(node->labels, l) check_duplicate_label(c, dti, l->label, node, NULL, NULL); for_each_property(node, prop) { struct marker *m = prop->val.markers; for_each_label(prop->labels, l) check_duplicate_label(c, dti, l->label, node, prop, NULL); for_each_marker_of_type(m, LABEL) check_duplicate_label(c, dti, m->ref, node, prop, m); } } ERROR(duplicate_label, check_duplicate_label_node, NULL); static cell_t check_phandle_prop(struct check *c, struct dt_info *dti, struct node *node, const char *propname) { struct node *root = dti->dt; struct property *prop; struct marker *m; cell_t phandle; prop = get_property(node, propname); if (!prop) return 0; if (prop->val.len != sizeof(cell_t)) { FAIL(c, dti, "%s has bad length (%d) %s property", node->fullpath, prop->val.len, prop->name); return 0; } m = prop->val.markers; for_each_marker_of_type(m, REF_PHANDLE) { assert(m->offset == 0); if (node != get_node_by_ref(root, m->ref)) /* "Set this node's phandle equal to some * other node's phandle". That's nonsensical * by construction. */ { FAIL(c, dti, "%s in %s is a reference to another node", prop->name, node->fullpath); } /* But setting this node's phandle equal to its own * phandle is allowed - that means allocate a unique * phandle for this node, even if it's not otherwise * referenced. The value will be filled in later, so * we treat it as having no phandle data for now. */ return 0; } phandle = propval_cell(prop); if ((phandle == 0) || (phandle == -1)) { FAIL(c, dti, "%s has bad value (0x%x) in %s property", node->fullpath, phandle, prop->name); return 0; } return phandle; } static void check_explicit_phandles(struct check *c, struct dt_info *dti, struct node *node) { struct node *root = dti->dt; struct node *other; cell_t phandle, linux_phandle; /* Nothing should have assigned phandles yet */ assert(!node->phandle); phandle = check_phandle_prop(c, dti, node, "phandle"); linux_phandle = check_phandle_prop(c, dti, node, "linux,phandle"); if (!phandle && !linux_phandle) /* No valid phandles; nothing further to check */ return; if (linux_phandle && phandle && (phandle != linux_phandle)) FAIL(c, dti, "%s has mismatching 'phandle' and 'linux,phandle'" " properties", node->fullpath); if (linux_phandle && !phandle) phandle = linux_phandle; other = get_node_by_phandle(root, phandle); if (other && (other != node)) { FAIL(c, dti, "%s has duplicated phandle 0x%x (seen before at %s)", node->fullpath, phandle, other->fullpath); return; } node->phandle = phandle; } ERROR(explicit_phandles, check_explicit_phandles, NULL); static void check_name_properties(struct check *c, struct dt_info *dti, struct node *node) { struct property **pp, *prop = NULL; for (pp = &node->proplist; *pp; pp = &((*pp)->next)) if (streq((*pp)->name, "name")) { prop = *pp; break; } if (!prop) return; /* No name property, that's fine */ if ((prop->val.len != node->basenamelen+1) || (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) { FAIL(c, dti, "\"name\" property in %s is incorrect (\"%s\" instead" " of base node name)", node->fullpath, prop->val.val); } else { /* The name property is correct, and therefore redundant. * Delete it */ *pp = prop->next; free(prop->name); data_free(prop->val); free(prop); } } ERROR_IF_NOT_STRING(name_is_string, "name"); ERROR(name_properties, check_name_properties, NULL, &name_is_string); /* * Reference fixup functions */ static void fixup_phandle_references(struct check *c, struct dt_info *dti, struct node *node) { struct node *dt = dti->dt; struct property *prop; for_each_property(node, prop) { struct marker *m = prop->val.markers; struct node *refnode; cell_t phandle; for_each_marker_of_type(m, REF_PHANDLE) { assert(m->offset + sizeof(cell_t) <= prop->val.len); refnode = get_node_by_ref(dt, m->ref); if (! refnode) { if (!(dti->dtsflags & DTSF_PLUGIN)) FAIL(c, dti, "Reference to non-existent node or " "label \"%s\"\n", m->ref); else /* mark the entry as unresolved */ - *((cell_t *)(prop->val.val + m->offset)) = + *((fdt32_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(0xffffffff); continue; } phandle = get_node_phandle(dt, refnode); - *((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle); + *((fdt32_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle); } } } ERROR(phandle_references, fixup_phandle_references, NULL, &duplicate_node_names, &explicit_phandles); static void fixup_path_references(struct check *c, struct dt_info *dti, struct node *node) { struct node *dt = dti->dt; struct property *prop; for_each_property(node, prop) { struct marker *m = prop->val.markers; struct node *refnode; char *path; for_each_marker_of_type(m, REF_PATH) { assert(m->offset <= prop->val.len); refnode = get_node_by_ref(dt, m->ref); if (!refnode) { FAIL(c, dti, "Reference to non-existent node or label \"%s\"\n", m->ref); continue; } path = refnode->fullpath; prop->val = data_insert_at_marker(prop->val, m, path, strlen(path) + 1); } } } ERROR(path_references, fixup_path_references, NULL, &duplicate_node_names); /* * Semantic checks */ WARNING_IF_NOT_CELL(address_cells_is_cell, "#address-cells"); WARNING_IF_NOT_CELL(size_cells_is_cell, "#size-cells"); WARNING_IF_NOT_CELL(interrupt_cells_is_cell, "#interrupt-cells"); WARNING_IF_NOT_STRING(device_type_is_string, "device_type"); WARNING_IF_NOT_STRING(model_is_string, "model"); WARNING_IF_NOT_STRING(status_is_string, "status"); +WARNING_IF_NOT_STRING(label_is_string, "label"); +WARNING_IF_NOT_STRING_LIST(compatible_is_string_list, "compatible"); + +static void check_names_is_string_list(struct check *c, struct dt_info *dti, + struct node *node) +{ + struct property *prop; + + for_each_property(node, prop) { + const char *s = strrchr(prop->name, '-'); + if (!s || !streq(s, "-names")) + continue; + + c->data = prop->name; + check_is_string_list(c, dti, node); + } +} +WARNING(names_is_string_list, check_names_is_string_list, NULL); + +static void check_alias_paths(struct check *c, struct dt_info *dti, + struct node *node) +{ + struct property *prop; + + if (!streq(node->name, "aliases")) + return; + + for_each_property(node, prop) { + if (!prop->val.val || !get_node_by_path(dti->dt, prop->val.val)) { + FAIL(c, dti, "aliases property '%s' is not a valid node (%s)", + prop->name, prop->val.val); + continue; + } + if (strspn(prop->name, LOWERCASE DIGITS "-") != strlen(prop->name)) + FAIL(c, dti, "aliases property name '%s' is not valid", + prop->name); + + } +} +WARNING(alias_paths, check_alias_paths, NULL); + static void fixup_addr_size_cells(struct check *c, struct dt_info *dti, struct node *node) { struct property *prop; node->addr_cells = -1; node->size_cells = -1; prop = get_property(node, "#address-cells"); if (prop) node->addr_cells = propval_cell(prop); prop = get_property(node, "#size-cells"); if (prop) node->size_cells = propval_cell(prop); } WARNING(addr_size_cells, fixup_addr_size_cells, NULL, &address_cells_is_cell, &size_cells_is_cell); #define node_addr_cells(n) \ (((n)->addr_cells == -1) ? 2 : (n)->addr_cells) #define node_size_cells(n) \ (((n)->size_cells == -1) ? 1 : (n)->size_cells) static void check_reg_format(struct check *c, struct dt_info *dti, struct node *node) { struct property *prop; int addr_cells, size_cells, entrylen; prop = get_property(node, "reg"); if (!prop) return; /* No "reg", that's fine */ if (!node->parent) { FAIL(c, dti, "Root node has a \"reg\" property"); return; } if (prop->val.len == 0) FAIL(c, dti, "\"reg\" property in %s is empty", node->fullpath); addr_cells = node_addr_cells(node->parent); size_cells = node_size_cells(node->parent); entrylen = (addr_cells + size_cells) * sizeof(cell_t); if (!entrylen || (prop->val.len % entrylen) != 0) FAIL(c, dti, "\"reg\" property in %s has invalid length (%d bytes) " "(#address-cells == %d, #size-cells == %d)", node->fullpath, prop->val.len, addr_cells, size_cells); } WARNING(reg_format, check_reg_format, NULL, &addr_size_cells); static void check_ranges_format(struct check *c, struct dt_info *dti, struct node *node) { struct property *prop; int c_addr_cells, p_addr_cells, c_size_cells, p_size_cells, entrylen; prop = get_property(node, "ranges"); if (!prop) return; if (!node->parent) { FAIL(c, dti, "Root node has a \"ranges\" property"); return; } p_addr_cells = node_addr_cells(node->parent); p_size_cells = node_size_cells(node->parent); c_addr_cells = node_addr_cells(node); c_size_cells = node_size_cells(node); entrylen = (p_addr_cells + c_addr_cells + c_size_cells) * sizeof(cell_t); if (prop->val.len == 0) { if (p_addr_cells != c_addr_cells) FAIL(c, dti, "%s has empty \"ranges\" property but its " "#address-cells (%d) differs from %s (%d)", node->fullpath, c_addr_cells, node->parent->fullpath, p_addr_cells); if (p_size_cells != c_size_cells) FAIL(c, dti, "%s has empty \"ranges\" property but its " "#size-cells (%d) differs from %s (%d)", node->fullpath, c_size_cells, node->parent->fullpath, p_size_cells); } else if ((prop->val.len % entrylen) != 0) { FAIL(c, dti, "\"ranges\" property in %s has invalid length (%d bytes) " "(parent #address-cells == %d, child #address-cells == %d, " "#size-cells == %d)", node->fullpath, prop->val.len, p_addr_cells, c_addr_cells, c_size_cells); } } WARNING(ranges_format, check_ranges_format, NULL, &addr_size_cells); +static const struct bus_type pci_bus = { + .name = "PCI", +}; + +static void check_pci_bridge(struct check *c, struct dt_info *dti, struct node *node) +{ + struct property *prop; + cell_t *cells; + + prop = get_property(node, "device_type"); + if (!prop || !streq(prop->val.val, "pci")) + return; + + node->bus = &pci_bus; + + if (!strprefixeq(node->name, node->basenamelen, "pci") && + !strprefixeq(node->name, node->basenamelen, "pcie")) + FAIL(c, dti, "Node %s node name is not \"pci\" or \"pcie\"", + node->fullpath); + + prop = get_property(node, "ranges"); + if (!prop) + FAIL(c, dti, "Node %s missing ranges for PCI bridge (or not a bridge)", + node->fullpath); + + if (node_addr_cells(node) != 3) + FAIL(c, dti, "Node %s incorrect #address-cells for PCI bridge", + node->fullpath); + if (node_size_cells(node) != 2) + FAIL(c, dti, "Node %s incorrect #size-cells for PCI bridge", + node->fullpath); + + prop = get_property(node, "bus-range"); + if (!prop) { + FAIL(c, dti, "Node %s missing bus-range for PCI bridge", + node->fullpath); + return; + } + if (prop->val.len != (sizeof(cell_t) * 2)) { + FAIL(c, dti, "Node %s bus-range must be 2 cells", + node->fullpath); + return; + } + cells = (cell_t *)prop->val.val; + if (fdt32_to_cpu(cells[0]) > fdt32_to_cpu(cells[1])) + FAIL(c, dti, "Node %s bus-range 1st cell must be less than or equal to 2nd cell", + node->fullpath); + if (fdt32_to_cpu(cells[1]) > 0xff) + FAIL(c, dti, "Node %s bus-range maximum bus number must be less than 256", + node->fullpath); +} +WARNING(pci_bridge, check_pci_bridge, NULL, + &device_type_is_string, &addr_size_cells); + +static void check_pci_device_bus_num(struct check *c, struct dt_info *dti, struct node *node) +{ + struct property *prop; + unsigned int bus_num, min_bus, max_bus; + cell_t *cells; + + if (!node->parent || (node->parent->bus != &pci_bus)) + return; + + prop = get_property(node, "reg"); + if (!prop) + return; + + cells = (cell_t *)prop->val.val; + bus_num = (fdt32_to_cpu(cells[0]) & 0x00ff0000) >> 16; + + prop = get_property(node->parent, "bus-range"); + if (!prop) { + min_bus = max_bus = 0; + } else { + cells = (cell_t *)prop->val.val; + min_bus = fdt32_to_cpu(cells[0]); + max_bus = fdt32_to_cpu(cells[0]); + } + if ((bus_num < min_bus) || (bus_num > max_bus)) + FAIL(c, dti, "Node %s PCI bus number %d out of range, expected (%d - %d)", + node->fullpath, bus_num, min_bus, max_bus); +} +WARNING(pci_device_bus_num, check_pci_device_bus_num, NULL, ®_format, &pci_bridge); + +static void check_pci_device_reg(struct check *c, struct dt_info *dti, struct node *node) +{ + struct property *prop; + const char *unitname = get_unitname(node); + char unit_addr[5]; + unsigned int dev, func, reg; + cell_t *cells; + + if (!node->parent || (node->parent->bus != &pci_bus)) + return; + + prop = get_property(node, "reg"); + if (!prop) { + FAIL(c, dti, "Node %s missing PCI reg property", node->fullpath); + return; + } + + cells = (cell_t *)prop->val.val; + if (cells[1] || cells[2]) + FAIL(c, dti, "Node %s PCI reg config space address cells 2 and 3 must be 0", + node->fullpath); + + reg = fdt32_to_cpu(cells[0]); + dev = (reg & 0xf800) >> 11; + func = (reg & 0x700) >> 8; + + if (reg & 0xff000000) + FAIL(c, dti, "Node %s PCI reg address is not configuration space", + node->fullpath); + if (reg & 0x000000ff) + FAIL(c, dti, "Node %s PCI reg config space address register number must be 0", + node->fullpath); + + if (func == 0) { + snprintf(unit_addr, sizeof(unit_addr), "%x", dev); + if (streq(unitname, unit_addr)) + return; + } + + snprintf(unit_addr, sizeof(unit_addr), "%x,%x", dev, func); + if (streq(unitname, unit_addr)) + return; + + FAIL(c, dti, "Node %s PCI unit address format error, expected \"%s\"", + node->fullpath, unit_addr); +} +WARNING(pci_device_reg, check_pci_device_reg, NULL, ®_format, &pci_bridge); + +static const struct bus_type simple_bus = { + .name = "simple-bus", +}; + +static bool node_is_compatible(struct node *node, const char *compat) +{ + struct property *prop; + const char *str, *end; + + prop = get_property(node, "compatible"); + if (!prop) + return false; + + for (str = prop->val.val, end = str + prop->val.len; str < end; + str += strnlen(str, end - str) + 1) { + if (strprefixeq(str, end - str, compat)) + return true; + } + return false; +} + +static void check_simple_bus_bridge(struct check *c, struct dt_info *dti, struct node *node) +{ + if (node_is_compatible(node, "simple-bus")) + node->bus = &simple_bus; +} +WARNING(simple_bus_bridge, check_simple_bus_bridge, NULL, &addr_size_cells); + +static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct node *node) +{ + struct property *prop; + const char *unitname = get_unitname(node); + char unit_addr[17]; + unsigned int size; + uint64_t reg = 0; + cell_t *cells = NULL; + + if (!node->parent || (node->parent->bus != &simple_bus)) + return; + + prop = get_property(node, "reg"); + if (prop) + cells = (cell_t *)prop->val.val; + else { + prop = get_property(node, "ranges"); + if (prop && prop->val.len) + /* skip of child address */ + cells = ((cell_t *)prop->val.val) + node_addr_cells(node); + } + + if (!cells) { + if (node->parent->parent && !(node->bus == &simple_bus)) + FAIL(c, dti, "Node %s missing or empty reg/ranges property", node->fullpath); + return; + } + + size = node_addr_cells(node->parent); + while (size--) + reg = (reg << 32) | fdt32_to_cpu(*(cells++)); + + snprintf(unit_addr, sizeof(unit_addr), "%"PRIx64, reg); + if (!streq(unitname, unit_addr)) + FAIL(c, dti, "Node %s simple-bus unit address format error, expected \"%s\"", + node->fullpath, unit_addr); +} +WARNING(simple_bus_reg, check_simple_bus_reg, NULL, ®_format, &simple_bus_bridge); + +static void check_unit_address_format(struct check *c, struct dt_info *dti, + struct node *node) +{ + const char *unitname = get_unitname(node); + + if (node->parent && node->parent->bus) + return; + + if (!unitname[0]) + return; + + if (!strncmp(unitname, "0x", 2)) { + FAIL(c, dti, "Node %s unit name should not have leading \"0x\"", + node->fullpath); + /* skip over 0x for next test */ + unitname += 2; + } + if (unitname[0] == '0' && isxdigit(unitname[1])) + FAIL(c, dti, "Node %s unit name should not have leading 0s", + node->fullpath); +} +WARNING(unit_address_format, check_unit_address_format, NULL, + &node_name_format, &pci_bridge, &simple_bus_bridge); + /* * Style checks */ static void check_avoid_default_addr_size(struct check *c, struct dt_info *dti, struct node *node) { struct property *reg, *ranges; if (!node->parent) return; /* Ignore root node */ reg = get_property(node, "reg"); ranges = get_property(node, "ranges"); if (!reg && !ranges) return; if (node->parent->addr_cells == -1) FAIL(c, dti, "Relying on default #address-cells value for %s", node->fullpath); if (node->parent->size_cells == -1) FAIL(c, dti, "Relying on default #size-cells value for %s", node->fullpath); } WARNING(avoid_default_addr_size, check_avoid_default_addr_size, NULL, &addr_size_cells); +static void check_avoid_unnecessary_addr_size(struct check *c, struct dt_info *dti, + struct node *node) +{ + struct property *prop; + struct node *child; + bool has_reg = false; + + if (!node->parent || node->addr_cells < 0 || node->size_cells < 0) + return; + + if (get_property(node, "ranges") || !node->children) + return; + + for_each_child(node, child) { + prop = get_property(child, "reg"); + if (prop) + has_reg = true; + } + + if (!has_reg) + FAIL(c, dti, "unnecessary #address-cells/#size-cells without \"ranges\" or child \"reg\" property in %s", + node->fullpath); +} +WARNING(avoid_unnecessary_addr_size, check_avoid_unnecessary_addr_size, NULL, &avoid_default_addr_size); + static void check_obsolete_chosen_interrupt_controller(struct check *c, struct dt_info *dti, struct node *node) { struct node *dt = dti->dt; struct node *chosen; struct property *prop; if (node != dt) return; chosen = get_node_by_path(dt, "/chosen"); if (!chosen) return; prop = get_property(chosen, "interrupt-controller"); if (prop) FAIL(c, dti, "/chosen has obsolete \"interrupt-controller\" " "property"); } WARNING(obsolete_chosen_interrupt_controller, check_obsolete_chosen_interrupt_controller, NULL); +static void check_chosen_node_is_root(struct check *c, struct dt_info *dti, + struct node *node) +{ + if (!streq(node->name, "chosen")) + return; + + if (node->parent != dti->dt) + FAIL(c, dti, "chosen node '%s' must be at root node", + node->fullpath); +} +WARNING(chosen_node_is_root, check_chosen_node_is_root, NULL); + +static void check_chosen_node_bootargs(struct check *c, struct dt_info *dti, + struct node *node) +{ + struct property *prop; + + if (!streq(node->name, "chosen")) + return; + + prop = get_property(node, "bootargs"); + if (!prop) + return; + + c->data = prop->name; + check_is_string(c, dti, node); +} +WARNING(chosen_node_bootargs, check_chosen_node_bootargs, NULL); + +static void check_chosen_node_stdout_path(struct check *c, struct dt_info *dti, + struct node *node) +{ + struct property *prop; + + if (!streq(node->name, "chosen")) + return; + + prop = get_property(node, "stdout-path"); + if (!prop) { + prop = get_property(node, "linux,stdout-path"); + if (!prop) + return; + FAIL(c, dti, "Use 'stdout-path' instead of 'linux,stdout-path'"); + } + + c->data = prop->name; + check_is_string(c, dti, node); +} +WARNING(chosen_node_stdout_path, check_chosen_node_stdout_path, NULL); + +struct provider { + const char *prop_name; + const char *cell_name; + bool optional; +}; + +static void check_property_phandle_args(struct check *c, + struct dt_info *dti, + struct node *node, + struct property *prop, + const struct provider *provider) +{ + struct node *root = dti->dt; + int cell, cellsize = 0; + + if (prop->val.len % sizeof(cell_t)) { + FAIL(c, dti, "property '%s' size (%d) is invalid, expected multiple of %zu in node %s", + prop->name, prop->val.len, sizeof(cell_t), node->fullpath); + return; + } + + for (cell = 0; cell < prop->val.len / sizeof(cell_t); cell += cellsize + 1) { + struct node *provider_node; + struct property *cellprop; + int phandle; + + phandle = propval_cell_n(prop, cell); + /* + * Some bindings use a cell value 0 or -1 to skip over optional + * entries when each index position has a specific definition. + */ + if (phandle == 0 || phandle == -1) { + /* Give up if this is an overlay with external references */ + if (dti->dtsflags & DTSF_PLUGIN) + break; + + cellsize = 0; + continue; + } + + /* If we have markers, verify the current cell is a phandle */ + if (prop->val.markers) { + struct marker *m = prop->val.markers; + for_each_marker_of_type(m, REF_PHANDLE) { + if (m->offset == (cell * sizeof(cell_t))) + break; + } + if (!m) + FAIL(c, dti, "Property '%s', cell %d is not a phandle reference in %s", + prop->name, cell, node->fullpath); + } + + provider_node = get_node_by_phandle(root, phandle); + if (!provider_node) { + FAIL(c, dti, "Could not get phandle node for %s:%s(cell %d)", + node->fullpath, prop->name, cell); + break; + } + + cellprop = get_property(provider_node, provider->cell_name); + if (cellprop) { + cellsize = propval_cell(cellprop); + } else if (provider->optional) { + cellsize = 0; + } else { + FAIL(c, dti, "Missing property '%s' in node %s or bad phandle (referred from %s:%s[%d])", + provider->cell_name, + provider_node->fullpath, + node->fullpath, prop->name, cell); + break; + } + + if (prop->val.len < ((cell + cellsize + 1) * sizeof(cell_t))) { + FAIL(c, dti, "%s property size (%d) too small for cell size %d in %s", + prop->name, prop->val.len, cellsize, node->fullpath); + } + } +} + +static void check_provider_cells_property(struct check *c, + struct dt_info *dti, + struct node *node) +{ + struct provider *provider = c->data; + struct property *prop; + + prop = get_property(node, provider->prop_name); + if (!prop) + return; + + check_property_phandle_args(c, dti, node, prop, provider); +} +#define WARNING_PROPERTY_PHANDLE_CELLS(nm, propname, cells_name, ...) \ + static struct provider nm##_provider = { (propname), (cells_name), __VA_ARGS__ }; \ + WARNING(nm##_property, check_provider_cells_property, &nm##_provider, &phandle_references); + +WARNING_PROPERTY_PHANDLE_CELLS(clocks, "clocks", "#clock-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(cooling_device, "cooling-device", "#cooling-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(dmas, "dmas", "#dma-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(hwlocks, "hwlocks", "#hwlock-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(interrupts_extended, "interrupts-extended", "#interrupt-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(io_channels, "io-channels", "#io-channel-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(iommus, "iommus", "#iommu-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(mboxes, "mboxes", "#mbox-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(msi_parent, "msi-parent", "#msi-cells", true); +WARNING_PROPERTY_PHANDLE_CELLS(mux_controls, "mux-controls", "#mux-control-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(phys, "phys", "#phy-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(power_domains, "power-domains", "#power-domain-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(pwms, "pwms", "#pwm-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(resets, "resets", "#reset-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(sound_dai, "sound-dai", "#sound-dai-cells"); +WARNING_PROPERTY_PHANDLE_CELLS(thermal_sensors, "thermal-sensors", "#thermal-sensor-cells"); + +static bool prop_is_gpio(struct property *prop) +{ + char *str; + + /* + * *-gpios and *-gpio can appear in property names, + * so skip over any false matches (only one known ATM) + */ + if (strstr(prop->name, "nr-gpio")) + return false; + + str = strrchr(prop->name, '-'); + if (str) + str++; + else + str = prop->name; + if (!(streq(str, "gpios") || streq(str, "gpio"))) + return false; + + return true; +} + +static void check_gpios_property(struct check *c, + struct dt_info *dti, + struct node *node) +{ + struct property *prop; + + /* Skip GPIO hog nodes which have 'gpios' property */ + if (get_property(node, "gpio-hog")) + return; + + for_each_property(node, prop) { + struct provider provider; + + if (!prop_is_gpio(prop)) + continue; + + provider.prop_name = prop->name; + provider.cell_name = "#gpio-cells"; + provider.optional = false; + check_property_phandle_args(c, dti, node, prop, &provider); + } + +} +WARNING(gpios_property, check_gpios_property, NULL, &phandle_references); + +static void check_deprecated_gpio_property(struct check *c, + struct dt_info *dti, + struct node *node) +{ + struct property *prop; + + for_each_property(node, prop) { + char *str; + + if (!prop_is_gpio(prop)) + continue; + + str = strstr(prop->name, "gpio"); + if (!streq(str, "gpio")) + continue; + + FAIL(c, dti, "'[*-]gpio' is deprecated, use '[*-]gpios' instead for %s:%s", + node->fullpath, prop->name); + } + +} +CHECK(deprecated_gpio_property, check_deprecated_gpio_property, NULL); + +static bool node_is_interrupt_provider(struct node *node) +{ + struct property *prop; + + prop = get_property(node, "interrupt-controller"); + if (prop) + return true; + + prop = get_property(node, "interrupt-map"); + if (prop) + return true; + + return false; +} +static void check_interrupts_property(struct check *c, + struct dt_info *dti, + struct node *node) +{ + struct node *root = dti->dt; + struct node *irq_node = NULL, *parent = node; + struct property *irq_prop, *prop = NULL; + int irq_cells, phandle; + + irq_prop = get_property(node, "interrupts"); + if (!irq_prop) + return; + + if (irq_prop->val.len % sizeof(cell_t)) + FAIL(c, dti, "property '%s' size (%d) is invalid, expected multiple of %zu in node %s", + irq_prop->name, irq_prop->val.len, sizeof(cell_t), + node->fullpath); + + while (parent && !prop) { + if (parent != node && node_is_interrupt_provider(parent)) { + irq_node = parent; + break; + } + + prop = get_property(parent, "interrupt-parent"); + if (prop) { + phandle = propval_cell(prop); + /* Give up if this is an overlay with external references */ + if ((phandle == 0 || phandle == -1) && + (dti->dtsflags & DTSF_PLUGIN)) + return; + + irq_node = get_node_by_phandle(root, phandle); + if (!irq_node) { + FAIL(c, dti, "Bad interrupt-parent phandle for %s", + node->fullpath); + return; + } + if (!node_is_interrupt_provider(irq_node)) + FAIL(c, dti, + "Missing interrupt-controller or interrupt-map property in %s", + irq_node->fullpath); + + break; + } + + parent = parent->parent; + } + + if (!irq_node) { + FAIL(c, dti, "Missing interrupt-parent for %s", node->fullpath); + return; + } + + prop = get_property(irq_node, "#interrupt-cells"); + if (!prop) { + FAIL(c, dti, "Missing #interrupt-cells in interrupt-parent %s", + irq_node->fullpath); + return; + } + + irq_cells = propval_cell(prop); + if (irq_prop->val.len % (irq_cells * sizeof(cell_t))) { + FAIL(c, dti, + "interrupts size is (%d), expected multiple of %d in %s", + irq_prop->val.len, (int)(irq_cells * sizeof(cell_t)), + node->fullpath); + } +} +WARNING(interrupts_property, check_interrupts_property, &phandle_references); + static struct check *check_table[] = { &duplicate_node_names, &duplicate_property_names, &node_name_chars, &node_name_format, &property_name_chars, &name_is_string, &name_properties, &duplicate_label, &explicit_phandles, &phandle_references, &path_references, &address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell, &device_type_is_string, &model_is_string, &status_is_string, + &label_is_string, + &compatible_is_string_list, &names_is_string_list, + &property_name_chars_strict, &node_name_chars_strict, &addr_size_cells, ®_format, &ranges_format, &unit_address_vs_reg, + &unit_address_format, + &pci_bridge, + &pci_device_reg, + &pci_device_bus_num, + + &simple_bus_bridge, + &simple_bus_reg, + &avoid_default_addr_size, + &avoid_unnecessary_addr_size, &obsolete_chosen_interrupt_controller, + &chosen_node_is_root, &chosen_node_bootargs, &chosen_node_stdout_path, + + &clocks_property, + &cooling_device_property, + &dmas_property, + &hwlocks_property, + &interrupts_extended_property, + &io_channels_property, + &iommus_property, + &mboxes_property, + &msi_parent_property, + &mux_controls_property, + &phys_property, + &power_domains_property, + &pwms_property, + &resets_property, + &sound_dai_property, + &thermal_sensors_property, + + &deprecated_gpio_property, + &gpios_property, + &interrupts_property, + + &alias_paths, &always_fail, }; static void enable_warning_error(struct check *c, bool warn, bool error) { int i; /* Raising level, also raise it for prereqs */ if ((warn && !c->warn) || (error && !c->error)) for (i = 0; i < c->num_prereqs; i++) enable_warning_error(c->prereq[i], warn, error); c->warn = c->warn || warn; c->error = c->error || error; } static void disable_warning_error(struct check *c, bool warn, bool error) { int i; /* Lowering level, also lower it for things this is the prereq * for */ if ((warn && c->warn) || (error && c->error)) { for (i = 0; i < ARRAY_SIZE(check_table); i++) { struct check *cc = check_table[i]; int j; for (j = 0; j < cc->num_prereqs; j++) if (cc->prereq[j] == c) disable_warning_error(cc, warn, error); } } c->warn = c->warn && !warn; c->error = c->error && !error; } void parse_checks_option(bool warn, bool error, const char *arg) { int i; const char *name = arg; bool enable = true; if ((strncmp(arg, "no-", 3) == 0) || (strncmp(arg, "no_", 3) == 0)) { name = arg + 3; enable = false; } for (i = 0; i < ARRAY_SIZE(check_table); i++) { struct check *c = check_table[i]; if (streq(c->name, name)) { if (enable) enable_warning_error(c, warn, error); else disable_warning_error(c, warn, error); return; } } die("Unrecognized check name \"%s\"\n", name); } void process_checks(bool force, struct dt_info *dti) { int i; int error = 0; for (i = 0; i < ARRAY_SIZE(check_table); i++) { struct check *c = check_table[i]; if (c->warn || c->error) error = error || run_check(c, dti); } if (error) { if (!force) { fprintf(stderr, "ERROR: Input tree has errors, aborting " "(use -f to force output)\n"); exit(2); } else if (quiet < 3) { fprintf(stderr, "Warning: Input tree has errors, " "output forced\n"); } } } Index: vendor/dtc/dist/convert-dtsv0-lexer.l =================================================================== --- vendor/dtc/dist/convert-dtsv0-lexer.l (revision 327892) +++ vendor/dtc/dist/convert-dtsv0-lexer.l (revision 327893) @@ -1,249 +1,249 @@ /* * (C) Copyright David Gibson , IBM Corporation. 2005, 2008. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ %option noyywrap nounput noinput never-interactive %x BYTESTRING %x PROPNODENAME PROPNODECHAR [a-zA-Z0-9,._+*#?@-] PATHCHAR ({PROPNODECHAR}|[/]) LABEL [a-zA-Z_][a-zA-Z0-9_]* STRING \"([^\\"]|\\.)*\" WS [[:space:]] COMMENT "/*"([^*]|\*+[^*/])*\*+"/" LINECOMMENT "//".*\n GAP ({WS}|{COMMENT}|{LINECOMMENT})* %{ #include #include #include #include #include #include #include "srcpos.h" #include "util.h" static int v1_tagged; /* = 0 */ static int cbase = 16; static int saw_hyphen; /* = 0 */ static unsigned long long last_val; static char *last_name; /* = NULL */ -const struct { +static const struct { const char *pattern; int obase, width; } guess_table[] = { { "*-frequency", 10, 0 }, { "num-*", 10, 0 }, { "#*-cells", 10, 0 }, { "*cache-line-size", 10, 0 }, { "*cache-block-size", 10, 0 }, { "*cache-size", 10, 0 }, { "*cache-sets", 10, 0 }, { "cell-index", 10, 0 }, { "bank-width", 10, 0 }, { "*-fifo-size", 10, 0 }, { "*-frame-size", 10, 0 }, { "*-channel", 10, 0 }, { "current-speed", 10, 0 }, { "phy-map", 16, 8 }, { "dcr-reg", 16, 3 }, { "reg", 16, 8 }, { "ranges", 16, 8}, }; %} %% <*>"/include/"{GAP}{STRING} ECHO; <*>\"([^\\"]|\\.)*\" ECHO; <*>"/dts-v1/" { die("Input dts file is already version 1\n"); } <*>"/memreserve/" { if (!v1_tagged) { fprintf(yyout, "/dts-v1/;\n\n"); v1_tagged = 1; } ECHO; BEGIN(INITIAL); } <*>{LABEL}: ECHO; [bodh]# { if (*yytext == 'b') cbase = 2; else if (*yytext == 'o') cbase = 8; else if (*yytext == 'd') cbase = 10; else cbase = 16; } [0-9a-fA-F]+ { unsigned long long val; int obase = 16, width = 0; int i; val = strtoull(yytext, NULL, cbase); if (saw_hyphen) val = val - last_val + 1; if (last_name) { for (i = 0; i < ARRAY_SIZE(guess_table); i++) if (fnmatch(guess_table[i].pattern, last_name, 0) == 0) { obase = guess_table[i].obase; width = guess_table[i].width; } } else { obase = 16; width = 16; } if (cbase != 16) obase = cbase; switch (obase) { case 2: case 16: fprintf(yyout, "0x%0*llx", width, val); break; case 8: fprintf(yyout, "0%0*llo", width, val); break; case 10: fprintf(yyout, "%*llu", width, val); break; } cbase = 16; last_val = val; saw_hyphen = 0; } \&{LABEL} ECHO; "&{/"{PATHCHAR}+\} ECHO; "&/"{PATHCHAR}+ fprintf(yyout, "&{/%s}", yytext + 2); [0-9a-fA-F]{2} ECHO; "]" { ECHO; BEGIN(INITIAL); } {PROPNODECHAR}+ { ECHO; last_name = xstrdup(yytext); BEGIN(INITIAL); } <*>{GAP} ECHO; <*>- { /* Hack to convert old style memreserves */ saw_hyphen = 1; fprintf(yyout, " "); } <*>. { if (!v1_tagged) { fprintf(yyout, "/dts-v1/;\n\n"); v1_tagged = 1; } ECHO; if (yytext[0] == '[') { BEGIN(BYTESTRING); } if ((yytext[0] == '{') || (yytext[0] == ';')) { BEGIN(PROPNODENAME); } } %% /* Usage related data. */ static const char usage_synopsis[] = "convert-dtsv0 [options] ..."; static const char usage_short_opts[] = "" USAGE_COMMON_SHORT_OPTS; static struct option const usage_long_opts[] = { USAGE_COMMON_LONG_OPTS }; static const char * const usage_opts_help[] = { USAGE_COMMON_OPTS_HELP }; static void convert_file(const char *fname) { const char suffix[] = "v1"; int len = strlen(fname); char *newname; newname = xmalloc(len + sizeof(suffix)); memcpy(newname, fname, len); memcpy(newname + len, suffix, sizeof(suffix)); yyin = fopen(fname, "r"); if (!yyin) die("Couldn't open input file %s: %s\n", fname, strerror(errno)); yyout = fopen(newname, "w"); if (!yyout) die("Couldn't open output file %s: %s\n", newname, strerror(errno)); while(yylex()) ; free(newname); } int main(int argc, char *argv[]) { int opt; int i; while ((opt = util_getopt_long()) != EOF) { switch (opt) { case_USAGE_COMMON_FLAGS } } if (argc < 2) usage("missing filename"); for (i = 1; i < argc; i++) { fprintf(stderr, "Converting %s from dts v0 to dts v1\n", argv[i]); convert_file(argv[i]); } exit(0); } Index: vendor/dtc/dist/data.c =================================================================== --- vendor/dtc/dist/data.c (revision 327892) +++ vendor/dtc/dist/data.c (revision 327893) @@ -1,269 +1,269 @@ /* * (C) Copyright David Gibson , IBM Corporation. 2005. * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ #include "dtc.h" void data_free(struct data d) { struct marker *m, *nm; m = d.markers; while (m) { nm = m->next; free(m->ref); free(m); m = nm; } if (d.val) free(d.val); } struct data data_grow_for(struct data d, int xlen) { struct data nd; int newsize; if (xlen == 0) return d; nd = d; newsize = xlen; while ((d.len + xlen) > newsize) newsize *= 2; nd.val = xrealloc(d.val, newsize); return nd; } struct data data_copy_mem(const char *mem, int len) { struct data d; d = data_grow_for(empty_data, len); d.len = len; memcpy(d.val, mem, len); return d; } struct data data_copy_escape_string(const char *s, int len) { int i = 0; struct data d; char *q; d = data_grow_for(empty_data, len + 1); q = d.val; while (i < len) { char c = s[i++]; if (c == '\\') c = get_escape_char(s, &i); q[d.len++] = c; } q[d.len++] = '\0'; return d; } struct data data_copy_file(FILE *f, size_t maxlen) { struct data d = empty_data; while (!feof(f) && (d.len < maxlen)) { size_t chunksize, ret; if (maxlen == -1) chunksize = 4096; else chunksize = maxlen - d.len; d = data_grow_for(d, chunksize); ret = fread(d.val + d.len, 1, chunksize, f); if (ferror(f)) die("Error reading file into data: %s", strerror(errno)); if (d.len + ret < d.len) die("Overflow reading file into data\n"); d.len += ret; } return d; } struct data data_append_data(struct data d, const void *p, int len) { d = data_grow_for(d, len); memcpy(d.val + d.len, p, len); d.len += len; return d; } struct data data_insert_at_marker(struct data d, struct marker *m, const void *p, int len) { d = data_grow_for(d, len); memmove(d.val + m->offset + len, d.val + m->offset, d.len - m->offset); memcpy(d.val + m->offset, p, len); d.len += len; /* Adjust all markers after the one we're inserting at */ m = m->next; for_each_marker(m) m->offset += len; return d; } static struct data data_append_markers(struct data d, struct marker *m) { struct marker **mp = &d.markers; /* Find the end of the markerlist */ while (*mp) mp = &((*mp)->next); *mp = m; return d; } struct data data_merge(struct data d1, struct data d2) { struct data d; struct marker *m2 = d2.markers; d = data_append_markers(data_append_data(d1, d2.val, d2.len), m2); /* Adjust for the length of d1 */ for_each_marker(m2) m2->offset += d1.len; d2.markers = NULL; /* So data_free() doesn't clobber them */ data_free(d2); return d; } struct data data_append_integer(struct data d, uint64_t value, int bits) { uint8_t value_8; - uint16_t value_16; - uint32_t value_32; - uint64_t value_64; + fdt16_t value_16; + fdt32_t value_32; + fdt64_t value_64; switch (bits) { case 8: value_8 = value; return data_append_data(d, &value_8, 1); case 16: value_16 = cpu_to_fdt16(value); return data_append_data(d, &value_16, 2); case 32: value_32 = cpu_to_fdt32(value); return data_append_data(d, &value_32, 4); case 64: value_64 = cpu_to_fdt64(value); return data_append_data(d, &value_64, 8); default: die("Invalid literal size (%d)\n", bits); } } -struct data data_append_re(struct data d, const struct fdt_reserve_entry *re) +struct data data_append_re(struct data d, uint64_t address, uint64_t size) { - struct fdt_reserve_entry bere; + struct fdt_reserve_entry re; - bere.address = cpu_to_fdt64(re->address); - bere.size = cpu_to_fdt64(re->size); + re.address = cpu_to_fdt64(address); + re.size = cpu_to_fdt64(size); - return data_append_data(d, &bere, sizeof(bere)); + return data_append_data(d, &re, sizeof(re)); } struct data data_append_cell(struct data d, cell_t word) { return data_append_integer(d, word, sizeof(word) * 8); } struct data data_append_addr(struct data d, uint64_t addr) { return data_append_integer(d, addr, sizeof(addr) * 8); } struct data data_append_byte(struct data d, uint8_t byte) { return data_append_data(d, &byte, 1); } struct data data_append_zeroes(struct data d, int len) { d = data_grow_for(d, len); memset(d.val + d.len, 0, len); d.len += len; return d; } struct data data_append_align(struct data d, int align) { int newlen = ALIGN(d.len, align); return data_append_zeroes(d, newlen - d.len); } struct data data_add_marker(struct data d, enum markertype type, char *ref) { struct marker *m; m = xmalloc(sizeof(*m)); m->offset = d.len; m->type = type; m->ref = ref; m->next = NULL; return data_append_markers(d, m); } bool data_is_one_string(struct data d) { int i; int len = d.len; if (len == 0) return false; for (i = 0; i < len-1; i++) if (d.val[i] == '\0') return false; if (d.val[len-1] != '\0') return false; return true; } Index: vendor/dtc/dist/dtc-lexer.l =================================================================== --- vendor/dtc/dist/dtc-lexer.l (revision 327892) +++ vendor/dtc/dist/dtc-lexer.l (revision 327893) @@ -1,311 +1,306 @@ /* * (C) Copyright David Gibson , IBM Corporation. 2005. * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ %option noyywrap nounput noinput never-interactive %x BYTESTRING %x PROPNODENAME %s V1 PROPNODECHAR [a-zA-Z0-9,._+*#?@-] PATHCHAR ({PROPNODECHAR}|[/]) LABEL [a-zA-Z_][a-zA-Z0-9_]* STRING \"([^\\"]|\\.)*\" CHAR_LITERAL '([^']|\\')*' WS [[:space:]] COMMENT "/*"([^*]|\*+[^*/])*\*+"/" LINECOMMENT "//".*\n %{ #include "dtc.h" #include "srcpos.h" #include "dtc-parser.tab.h" YYLTYPE yylloc; extern bool treesource_error; /* CAUTION: this will stop working if we ever use yyless() or yyunput() */ #define YY_USER_ACTION \ { \ srcpos_update(&yylloc, yytext, yyleng); \ } /*#define LEXDEBUG 1*/ #ifdef LEXDEBUG #define DPRINT(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__) #else #define DPRINT(fmt, ...) do { } while (0) #endif static int dts_version = 1; #define BEGIN_DEFAULT() DPRINT("\n"); \ BEGIN(V1); \ static void push_input_file(const char *filename); static bool pop_input_file(void); -#ifdef __GNUC__ -static void lexical_error(const char *fmt, ...) - __attribute__((format (printf, 1, 2))); -#else -static void lexical_error(const char *fmt, ...); -#endif +static void PRINTF(1, 2) lexical_error(const char *fmt, ...); %} %% <*>"/include/"{WS}*{STRING} { char *name = strchr(yytext, '\"') + 1; yytext[yyleng-1] = '\0'; push_input_file(name); } <*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)? { char *line, *fnstart, *fnend; struct data fn; /* skip text before line # */ line = yytext; while (!isdigit((unsigned char)*line)) line++; /* regexp ensures that first and list " * in the whole yytext are those at * beginning and end of the filename string */ fnstart = memchr(yytext, '"', yyleng); for (fnend = yytext + yyleng - 1; *fnend != '"'; fnend--) ; assert(fnstart && fnend && (fnend > fnstart)); fn = data_copy_escape_string(fnstart + 1, fnend - fnstart - 1); /* Don't allow nuls in filenames */ if (memchr(fn.val, '\0', fn.len - 1)) lexical_error("nul in line number directive"); /* -1 since #line is the number of the next line */ srcpos_set_line(xstrdup(fn.val), atoi(line) - 1); data_free(fn); } <*><> { if (!pop_input_file()) { yyterminate(); } } <*>{STRING} { DPRINT("String: %s\n", yytext); yylval.data = data_copy_escape_string(yytext+1, yyleng-2); return DT_STRING; } <*>"/dts-v1/" { DPRINT("Keyword: /dts-v1/\n"); dts_version = 1; BEGIN_DEFAULT(); return DT_V1; } <*>"/plugin/" { DPRINT("Keyword: /plugin/\n"); return DT_PLUGIN; } <*>"/memreserve/" { DPRINT("Keyword: /memreserve/\n"); BEGIN_DEFAULT(); return DT_MEMRESERVE; } <*>"/bits/" { DPRINT("Keyword: /bits/\n"); BEGIN_DEFAULT(); return DT_BITS; } <*>"/delete-property/" { DPRINT("Keyword: /delete-property/\n"); DPRINT("\n"); BEGIN(PROPNODENAME); return DT_DEL_PROP; } <*>"/delete-node/" { DPRINT("Keyword: /delete-node/\n"); DPRINT("\n"); BEGIN(PROPNODENAME); return DT_DEL_NODE; } <*>{LABEL}: { DPRINT("Label: %s\n", yytext); yylval.labelref = xstrdup(yytext); yylval.labelref[yyleng-1] = '\0'; return DT_LABEL; } ([0-9]+|0[xX][0-9a-fA-F]+)(U|L|UL|LL|ULL)? { char *e; DPRINT("Integer Literal: '%s'\n", yytext); errno = 0; yylval.integer = strtoull(yytext, &e, 0); if (*e && e[strspn(e, "UL")]) { lexical_error("Bad integer literal '%s'", yytext); } if (errno == ERANGE) lexical_error("Integer literal '%s' out of range", yytext); else /* ERANGE is the only strtoull error triggerable * by strings matching the pattern */ assert(errno == 0); return DT_LITERAL; } <*>{CHAR_LITERAL} { struct data d; DPRINT("Character literal: %s\n", yytext); d = data_copy_escape_string(yytext+1, yyleng-2); if (d.len == 1) { lexical_error("Empty character literal"); yylval.integer = 0; } else { yylval.integer = (unsigned char)d.val[0]; if (d.len > 2) lexical_error("Character literal has %d" " characters instead of 1", d.len - 1); } data_free(d); return DT_CHAR_LITERAL; } <*>\&{LABEL} { /* label reference */ DPRINT("Ref: %s\n", yytext+1); yylval.labelref = xstrdup(yytext+1); return DT_REF; } <*>"&{/"{PATHCHAR}*\} { /* new-style path reference */ yytext[yyleng-1] = '\0'; DPRINT("Ref: %s\n", yytext+2); yylval.labelref = xstrdup(yytext+2); return DT_REF; } [0-9a-fA-F]{2} { yylval.byte = strtol(yytext, NULL, 16); DPRINT("Byte: %02x\n", (int)yylval.byte); return DT_BYTE; } "]" { DPRINT("/BYTESTRING\n"); BEGIN_DEFAULT(); return ']'; } \\?{PROPNODECHAR}+ { DPRINT("PropNodeName: %s\n", yytext); yylval.propnodename = xstrdup((yytext[0] == '\\') ? yytext + 1 : yytext); BEGIN_DEFAULT(); return DT_PROPNODENAME; } "/incbin/" { DPRINT("Binary Include\n"); return DT_INCBIN; } <*>{WS}+ /* eat whitespace */ <*>{COMMENT}+ /* eat C-style comments */ <*>{LINECOMMENT}+ /* eat C++-style comments */ <*>"<<" { return DT_LSHIFT; }; <*>">>" { return DT_RSHIFT; }; <*>"<=" { return DT_LE; }; <*>">=" { return DT_GE; }; <*>"==" { return DT_EQ; }; <*>"!=" { return DT_NE; }; <*>"&&" { return DT_AND; }; <*>"||" { return DT_OR; }; <*>. { DPRINT("Char: %c (\\x%02x)\n", yytext[0], (unsigned)yytext[0]); if (yytext[0] == '[') { DPRINT("\n"); BEGIN(BYTESTRING); } if ((yytext[0] == '{') || (yytext[0] == ';')) { DPRINT("\n"); BEGIN(PROPNODENAME); } return yytext[0]; } %% static void push_input_file(const char *filename) { assert(filename); srcfile_push(filename); yyin = current_srcfile->f; yypush_buffer_state(yy_create_buffer(yyin, YY_BUF_SIZE)); } static bool pop_input_file(void) { if (srcfile_pop() == 0) return false; yypop_buffer_state(); yyin = current_srcfile->f; return true; } static void lexical_error(const char *fmt, ...) { va_list ap; va_start(ap, fmt); srcpos_verror(&yylloc, "Lexical error", fmt, ap); va_end(ap); treesource_error = true; } Index: vendor/dtc/dist/dtc-parser.y =================================================================== --- vendor/dtc/dist/dtc-parser.y (revision 327892) +++ vendor/dtc/dist/dtc-parser.y (revision 327893) @@ -1,519 +1,538 @@ /* * (C) Copyright David Gibson , IBM Corporation. 2005. * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ %{ #include #include #include "dtc.h" #include "srcpos.h" extern int yylex(void); extern void yyerror(char const *s); #define ERROR(loc, ...) \ do { \ srcpos_error((loc), "Error", __VA_ARGS__); \ treesource_error = true; \ } while (0) extern struct dt_info *parser_output; extern bool treesource_error; %} %union { char *propnodename; char *labelref; uint8_t byte; struct data data; struct { struct data data; int bits; } array; struct property *prop; struct property *proplist; struct node *node; struct node *nodelist; struct reserve_info *re; uint64_t integer; unsigned int flags; } %token DT_V1 %token DT_PLUGIN %token DT_MEMRESERVE %token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR %token DT_BITS %token DT_DEL_PROP %token DT_DEL_NODE %token DT_PROPNODENAME %token DT_LITERAL %token DT_CHAR_LITERAL %token DT_BYTE %token DT_STRING %token DT_LABEL %token DT_REF %token DT_INCBIN %type propdata %type propdataprefix %type header %type headers %type memreserve %type memreserves %type arrayprefix %type bytestring %type propdef %type proplist %type devicetree %type nodedef %type subnode %type subnodes %type integer_prim %type integer_unary %type integer_mul %type integer_add %type integer_shift %type integer_rela %type integer_eq %type integer_bitand %type integer_bitxor %type integer_bitor %type integer_and %type integer_or %type integer_trinary %type integer_expr %% sourcefile: headers memreserves devicetree { parser_output = build_dt_info($1, $2, $3, guess_boot_cpuid($3)); } ; header: DT_V1 ';' { $$ = DTSF_V1; } | DT_V1 ';' DT_PLUGIN ';' { $$ = DTSF_V1 | DTSF_PLUGIN; } ; headers: header | header headers { if ($2 != $1) ERROR(&@2, "Header flags don't match earlier ones"); $$ = $1; } ; memreserves: /* empty */ { $$ = NULL; } | memreserve memreserves { $$ = chain_reserve_entry($1, $2); } ; memreserve: DT_MEMRESERVE integer_prim integer_prim ';' { $$ = build_reserve_entry($2, $3); } | DT_LABEL memreserve { add_label(&$2->labels, $1); $$ = $2; } ; devicetree: '/' nodedef { $$ = name_node($2, ""); } | devicetree '/' nodedef { $$ = merge_nodes($1, $3); } - + | DT_REF nodedef + { + /* + * We rely on the rule being always: + * versioninfo plugindecl memreserves devicetree + * so $-1 is what we want (plugindecl) + */ + if (!($-1 & DTSF_PLUGIN)) + ERROR(&@2, "Label or path %s not found", $1); + $$ = add_orphan_node(name_node(build_node(NULL, NULL), ""), $2, $1); + } | devicetree DT_LABEL DT_REF nodedef { struct node *target = get_node_by_ref($1, $3); if (target) { add_label(&target->labels, $2); merge_nodes(target, $4); } else ERROR(&@3, "Label or path %s not found", $3); $$ = $1; } | devicetree DT_REF nodedef { struct node *target = get_node_by_ref($1, $2); - if (target) + if (target) { merge_nodes(target, $3); - else - ERROR(&@2, "Label or path %s not found", $2); + } else { + /* + * We rely on the rule being always: + * versioninfo plugindecl memreserves devicetree + * so $-1 is what we want (plugindecl) + */ + if ($-1 & DTSF_PLUGIN) + add_orphan_node($1, $3, $2); + else + ERROR(&@2, "Label or path %s not found", $2); + } $$ = $1; } | devicetree DT_DEL_NODE DT_REF ';' { struct node *target = get_node_by_ref($1, $3); if (target) delete_node(target); else ERROR(&@3, "Label or path %s not found", $3); $$ = $1; } ; nodedef: '{' proplist subnodes '}' ';' { $$ = build_node($2, $3); } ; proplist: /* empty */ { $$ = NULL; } | proplist propdef { $$ = chain_property($2, $1); } ; propdef: DT_PROPNODENAME '=' propdata ';' { $$ = build_property($1, $3); } | DT_PROPNODENAME ';' { $$ = build_property($1, empty_data); } | DT_DEL_PROP DT_PROPNODENAME ';' { $$ = build_property_delete($2); } | DT_LABEL propdef { add_label(&$2->labels, $1); $$ = $2; } ; propdata: propdataprefix DT_STRING { $$ = data_merge($1, $2); } | propdataprefix arrayprefix '>' { $$ = data_merge($1, $2.data); } | propdataprefix '[' bytestring ']' { $$ = data_merge($1, $3); } | propdataprefix DT_REF { $$ = data_add_marker($1, REF_PATH, $2); } | propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')' { FILE *f = srcfile_relative_open($4.val, NULL); struct data d; if ($6 != 0) if (fseek(f, $6, SEEK_SET) != 0) die("Couldn't seek to offset %llu in \"%s\": %s", (unsigned long long)$6, $4.val, strerror(errno)); d = data_copy_file(f, $8); $$ = data_merge($1, d); fclose(f); } | propdataprefix DT_INCBIN '(' DT_STRING ')' { FILE *f = srcfile_relative_open($4.val, NULL); struct data d = empty_data; d = data_copy_file(f, -1); $$ = data_merge($1, d); fclose(f); } | propdata DT_LABEL { $$ = data_add_marker($1, LABEL, $2); } ; propdataprefix: /* empty */ { $$ = empty_data; } | propdata ',' { $$ = $1; } | propdataprefix DT_LABEL { $$ = data_add_marker($1, LABEL, $2); } ; arrayprefix: DT_BITS DT_LITERAL '<' { unsigned long long bits; bits = $2; if ((bits != 8) && (bits != 16) && (bits != 32) && (bits != 64)) { ERROR(&@2, "Array elements must be" " 8, 16, 32 or 64-bits"); bits = 32; } $$.data = empty_data; $$.bits = bits; } | '<' { $$.data = empty_data; $$.bits = 32; } | arrayprefix integer_prim { if ($1.bits < 64) { uint64_t mask = (1ULL << $1.bits) - 1; /* * Bits above mask must either be all zero * (positive within range of mask) or all one * (negative and sign-extended). The second * condition is true if when we set all bits * within the mask to one (i.e. | in the * mask), all bits are one. */ if (($2 > mask) && (($2 | mask) != -1ULL)) ERROR(&@2, "Value out of range for" " %d-bit array element", $1.bits); } $$.data = data_append_integer($1.data, $2, $1.bits); } | arrayprefix DT_REF { uint64_t val = ~0ULL >> (64 - $1.bits); if ($1.bits == 32) $1.data = data_add_marker($1.data, REF_PHANDLE, $2); else ERROR(&@2, "References are only allowed in " "arrays with 32-bit elements."); $$.data = data_append_integer($1.data, val, $1.bits); } | arrayprefix DT_LABEL { $$.data = data_add_marker($1.data, LABEL, $2); } ; integer_prim: DT_LITERAL | DT_CHAR_LITERAL | '(' integer_expr ')' { $$ = $2; } ; integer_expr: integer_trinary ; integer_trinary: integer_or | integer_or '?' integer_expr ':' integer_trinary { $$ = $1 ? $3 : $5; } ; integer_or: integer_and | integer_or DT_OR integer_and { $$ = $1 || $3; } ; integer_and: integer_bitor | integer_and DT_AND integer_bitor { $$ = $1 && $3; } ; integer_bitor: integer_bitxor | integer_bitor '|' integer_bitxor { $$ = $1 | $3; } ; integer_bitxor: integer_bitand | integer_bitxor '^' integer_bitand { $$ = $1 ^ $3; } ; integer_bitand: integer_eq | integer_bitand '&' integer_eq { $$ = $1 & $3; } ; integer_eq: integer_rela | integer_eq DT_EQ integer_rela { $$ = $1 == $3; } | integer_eq DT_NE integer_rela { $$ = $1 != $3; } ; integer_rela: integer_shift | integer_rela '<' integer_shift { $$ = $1 < $3; } | integer_rela '>' integer_shift { $$ = $1 > $3; } | integer_rela DT_LE integer_shift { $$ = $1 <= $3; } | integer_rela DT_GE integer_shift { $$ = $1 >= $3; } ; integer_shift: integer_shift DT_LSHIFT integer_add { $$ = $1 << $3; } | integer_shift DT_RSHIFT integer_add { $$ = $1 >> $3; } | integer_add ; integer_add: integer_add '+' integer_mul { $$ = $1 + $3; } | integer_add '-' integer_mul { $$ = $1 - $3; } | integer_mul ; integer_mul: integer_mul '*' integer_unary { $$ = $1 * $3; } | integer_mul '/' integer_unary { if ($3 != 0) { $$ = $1 / $3; } else { ERROR(&@$, "Division by zero"); $$ = 0; } } | integer_mul '%' integer_unary { if ($3 != 0) { $$ = $1 % $3; } else { ERROR(&@$, "Division by zero"); $$ = 0; } } | integer_unary ; integer_unary: integer_prim | '-' integer_unary { $$ = -$2; } | '~' integer_unary { $$ = ~$2; } | '!' integer_unary { $$ = !$2; } ; bytestring: /* empty */ { $$ = empty_data; } | bytestring DT_BYTE { $$ = data_append_byte($1, $2); } | bytestring DT_LABEL { $$ = data_add_marker($1, LABEL, $2); } ; subnodes: /* empty */ { $$ = NULL; } | subnode subnodes { $$ = chain_node($1, $2); } | subnode propdef { ERROR(&@2, "Properties must precede subnodes"); YYERROR; } ; subnode: DT_PROPNODENAME nodedef { $$ = name_node($2, $1); } | DT_DEL_NODE DT_PROPNODENAME ';' { $$ = name_node(build_node_delete(), $2); } | DT_LABEL subnode { add_label(&$2->labels, $1); $$ = $2; } ; %% void yyerror(char const *s) { ERROR(&yylloc, "%s", s); } Index: vendor/dtc/dist/dtc.c =================================================================== --- vendor/dtc/dist/dtc.c (revision 327892) +++ vendor/dtc/dist/dtc.c (revision 327893) @@ -1,366 +1,364 @@ /* * (C) Copyright David Gibson , IBM Corporation. 2005. * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ #include #include "dtc.h" #include "srcpos.h" /* * Command line options */ int quiet; /* Level of quietness */ int reservenum; /* Number of memory reservation slots */ int minsize; /* Minimum blob size */ int padsize; /* Additional padding to blob */ int alignsize; /* Additional padding to blob accroding to the alignsize */ -int phandle_format = PHANDLE_BOTH; /* Use linux,phandle or phandle properties */ +int phandle_format = PHANDLE_EPAPR; /* Use linux,phandle or phandle properties */ int generate_symbols; /* enable symbols & fixup support */ int generate_fixups; /* suppress generation of fixups on symbol support */ int auto_label_aliases; /* auto generate labels -> aliases */ static int is_power_of_2(int x) { return (x > 0) && ((x & (x - 1)) == 0); } static void fill_fullpaths(struct node *tree, const char *prefix) { struct node *child; const char *unit; tree->fullpath = join_path(prefix, tree->name); unit = strchr(tree->name, '@'); if (unit) tree->basenamelen = unit - tree->name; else tree->basenamelen = strlen(tree->name); for_each_child(tree, child) fill_fullpaths(child, tree->fullpath); } /* Usage related data. */ -#define FDT_VERSION(version) _FDT_VERSION(version) -#define _FDT_VERSION(version) #version static const char usage_synopsis[] = "dtc [options] "; static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@Ahv"; static struct option const usage_long_opts[] = { {"quiet", no_argument, NULL, 'q'}, {"in-format", a_argument, NULL, 'I'}, {"out", a_argument, NULL, 'o'}, {"out-format", a_argument, NULL, 'O'}, {"out-version", a_argument, NULL, 'V'}, {"out-dependency", a_argument, NULL, 'd'}, {"reserve", a_argument, NULL, 'R'}, {"space", a_argument, NULL, 'S'}, {"pad", a_argument, NULL, 'p'}, {"align", a_argument, NULL, 'a'}, {"boot-cpu", a_argument, NULL, 'b'}, {"force", no_argument, NULL, 'f'}, {"include", a_argument, NULL, 'i'}, {"sort", no_argument, NULL, 's'}, {"phandle", a_argument, NULL, 'H'}, {"warning", a_argument, NULL, 'W'}, {"error", a_argument, NULL, 'E'}, {"symbols", no_argument, NULL, '@'}, {"auto-alias", no_argument, NULL, 'A'}, {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'v'}, {NULL, no_argument, NULL, 0x0}, }; static const char * const usage_opts_help[] = { "\n\tQuiet: -q suppress warnings, -qq errors, -qqq all", "\n\tInput formats are:\n" "\t\tdts - device tree source text\n" "\t\tdtb - device tree blob\n" "\t\tfs - /proc/device-tree style directory", "\n\tOutput file", "\n\tOutput formats are:\n" "\t\tdts - device tree source text\n" "\t\tdtb - device tree blob\n" "\t\tasm - assembler source", - "\n\tBlob version to produce, defaults to "FDT_VERSION(DEFAULT_FDT_VERSION)" (for dtb and asm output)", + "\n\tBlob version to produce, defaults to "stringify(DEFAULT_FDT_VERSION)" (for dtb and asm output)", "\n\tOutput dependency file", "\n\tMake space for reserve map entries (for dtb and asm output)", "\n\tMake the blob at least long (extra space)", "\n\tAdd padding to the blob of long (extra space)", "\n\tMake the blob align to the (extra space)", "\n\tSet the physical boot cpu", "\n\tTry to produce output even if the input tree has errors", "\n\tAdd a path to search for include files", "\n\tSort nodes and properties before outputting (useful for comparing trees)", "\n\tValid phandle formats are:\n" "\t\tlegacy - \"linux,phandle\" properties only\n" "\t\tepapr - \"phandle\" properties only\n" "\t\tboth - Both \"linux,phandle\" and \"phandle\" properties", "\n\tEnable/disable warnings (prefix with \"no-\")", "\n\tEnable/disable errors (prefix with \"no-\")", "\n\tEnable generation of symbols", "\n\tEnable auto-alias of labels", "\n\tPrint this help and exit", "\n\tPrint version and exit", NULL, }; static const char *guess_type_by_name(const char *fname, const char *fallback) { const char *s; s = strrchr(fname, '.'); if (s == NULL) return fallback; if (!strcasecmp(s, ".dts")) return "dts"; if (!strcasecmp(s, ".dtb")) return "dtb"; return fallback; } static const char *guess_input_format(const char *fname, const char *fallback) { struct stat statbuf; - uint32_t magic; + fdt32_t magic; FILE *f; if (stat(fname, &statbuf) != 0) return fallback; if (S_ISDIR(statbuf.st_mode)) return "fs"; if (!S_ISREG(statbuf.st_mode)) return fallback; f = fopen(fname, "r"); if (f == NULL) return fallback; if (fread(&magic, 4, 1, f) != 1) { fclose(f); return fallback; } fclose(f); - magic = fdt32_to_cpu(magic); - if (magic == FDT_MAGIC) + if (fdt32_to_cpu(magic) == FDT_MAGIC) return "dtb"; return guess_type_by_name(fname, fallback); } int main(int argc, char *argv[]) { struct dt_info *dti; const char *inform = NULL; const char *outform = NULL; const char *outname = "-"; const char *depname = NULL; bool force = false, sort = false; const char *arg; int opt; FILE *outf = NULL; int outversion = DEFAULT_FDT_VERSION; long long cmdline_boot_cpuid = -1; quiet = 0; reservenum = 0; minsize = 0; padsize = 0; alignsize = 0; while ((opt = util_getopt_long()) != EOF) { switch (opt) { case 'I': inform = optarg; break; case 'O': outform = optarg; break; case 'o': outname = optarg; break; case 'V': outversion = strtol(optarg, NULL, 0); break; case 'd': depname = optarg; break; case 'R': reservenum = strtol(optarg, NULL, 0); break; case 'S': minsize = strtol(optarg, NULL, 0); break; case 'p': padsize = strtol(optarg, NULL, 0); break; case 'a': alignsize = strtol(optarg, NULL, 0); if (!is_power_of_2(alignsize)) die("Invalid argument \"%d\" to -a option\n", alignsize); break; case 'f': force = true; break; case 'q': quiet++; break; case 'b': cmdline_boot_cpuid = strtoll(optarg, NULL, 0); break; case 'i': srcfile_add_search_path(optarg); break; case 'v': util_version(); case 'H': if (streq(optarg, "legacy")) phandle_format = PHANDLE_LEGACY; else if (streq(optarg, "epapr")) phandle_format = PHANDLE_EPAPR; else if (streq(optarg, "both")) phandle_format = PHANDLE_BOTH; else die("Invalid argument \"%s\" to -H option\n", optarg); break; case 's': sort = true; break; case 'W': parse_checks_option(true, false, optarg); break; case 'E': parse_checks_option(false, true, optarg); break; case '@': generate_symbols = 1; break; case 'A': auto_label_aliases = 1; break; case 'h': usage(NULL); default: usage("unknown option"); } } if (argc > (optind+1)) usage("missing files"); else if (argc < (optind+1)) arg = "-"; else arg = argv[optind]; /* minsize and padsize are mutually exclusive */ if (minsize && padsize) die("Can't set both -p and -S\n"); if (depname) { depfile = fopen(depname, "w"); if (!depfile) die("Couldn't open dependency file %s: %s\n", depname, strerror(errno)); fprintf(depfile, "%s:", outname); } if (inform == NULL) inform = guess_input_format(arg, "dts"); if (outform == NULL) { outform = guess_type_by_name(outname, NULL); if (outform == NULL) { if (streq(inform, "dts")) outform = "dtb"; else outform = "dts"; } } if (streq(inform, "dts")) dti = dt_from_source(arg); else if (streq(inform, "fs")) dti = dt_from_fs(arg); else if(streq(inform, "dtb")) dti = dt_from_blob(arg); else die("Unknown input format \"%s\"\n", inform); dti->outname = outname; if (depfile) { fputc('\n', depfile); fclose(depfile); } if (cmdline_boot_cpuid != -1) dti->boot_cpuid_phys = cmdline_boot_cpuid; fill_fullpaths(dti->dt, ""); - process_checks(force, dti); /* on a plugin, generate by default */ if (dti->dtsflags & DTSF_PLUGIN) { generate_fixups = 1; } + + process_checks(force, dti); if (auto_label_aliases) generate_label_tree(dti, "aliases", false); if (generate_symbols) generate_label_tree(dti, "__symbols__", true); if (generate_fixups) { generate_fixups_tree(dti, "__fixups__"); generate_local_fixups_tree(dti, "__local_fixups__"); } if (sort) sort_tree(dti); if (streq(outname, "-")) { outf = stdout; } else { outf = fopen(outname, "wb"); if (! outf) die("Couldn't open output file %s: %s\n", outname, strerror(errno)); } if (streq(outform, "dts")) { dt_to_source(outf, dti); } else if (streq(outform, "dtb")) { dt_to_blob(outf, dti, outversion); } else if (streq(outform, "asm")) { dt_to_asm(outf, dti, outversion); } else if (streq(outform, "null")) { /* do nothing */ } else { die("Unknown output format \"%s\"\n", outform); } exit(0); } Index: vendor/dtc/dist/dtc.h =================================================================== --- vendor/dtc/dist/dtc.h (revision 327892) +++ vendor/dtc/dist/dtc.h (revision 327893) @@ -1,285 +1,293 @@ -#ifndef _DTC_H -#define _DTC_H +#ifndef DTC_H +#define DTC_H /* * (C) Copyright David Gibson , IBM Corporation. 2005. * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ #include #include #include #include #include #include #include #include #include #include +#include #include #include #include "util.h" #ifdef DEBUG #define debug(...) printf(__VA_ARGS__) #else #define debug(...) #endif - #define DEFAULT_FDT_VERSION 17 /* * Command line options */ extern int quiet; /* Level of quietness */ extern int reservenum; /* Number of memory reservation slots */ extern int minsize; /* Minimum blob size */ extern int padsize; /* Additional padding to blob */ extern int alignsize; /* Additional padding to blob accroding to the alignsize */ extern int phandle_format; /* Use linux,phandle or phandle properties */ extern int generate_symbols; /* generate symbols for nodes with labels */ extern int generate_fixups; /* generate fixups */ extern int auto_label_aliases; /* auto generate labels -> aliases */ #define PHANDLE_LEGACY 0x1 #define PHANDLE_EPAPR 0x2 #define PHANDLE_BOTH 0x3 typedef uint32_t cell_t; #define streq(a, b) (strcmp((a), (b)) == 0) -#define strneq(a, b, n) (strncmp((a), (b), (n)) == 0) +#define strstarts(s, prefix) (strncmp((s), (prefix), strlen(prefix)) == 0) +#define strprefixeq(a, n, b) (strlen(b) == (n) && (memcmp(a, b, n) == 0)) #define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) /* Data blobs */ enum markertype { REF_PHANDLE, REF_PATH, LABEL, }; struct marker { enum markertype type; int offset; char *ref; struct marker *next; }; struct data { int len; char *val; struct marker *markers; }; #define empty_data ((struct data){ 0 /* all .members = 0 or NULL */ }) #define for_each_marker(m) \ for (; (m); (m) = (m)->next) #define for_each_marker_of_type(m, t) \ for_each_marker(m) \ if ((m)->type == (t)) void data_free(struct data d); struct data data_grow_for(struct data d, int xlen); struct data data_copy_mem(const char *mem, int len); struct data data_copy_escape_string(const char *s, int len); struct data data_copy_file(FILE *f, size_t len); struct data data_append_data(struct data d, const void *p, int len); struct data data_insert_at_marker(struct data d, struct marker *m, const void *p, int len); struct data data_merge(struct data d1, struct data d2); struct data data_append_cell(struct data d, cell_t word); struct data data_append_integer(struct data d, uint64_t word, int bits); -struct data data_append_re(struct data d, const struct fdt_reserve_entry *re); +struct data data_append_re(struct data d, uint64_t address, uint64_t size); struct data data_append_addr(struct data d, uint64_t addr); struct data data_append_byte(struct data d, uint8_t byte); struct data data_append_zeroes(struct data d, int len); struct data data_append_align(struct data d, int align); struct data data_add_marker(struct data d, enum markertype type, char *ref); bool data_is_one_string(struct data d); /* DT constraints */ #define MAX_PROPNAME_LEN 31 #define MAX_NODENAME_LEN 31 /* Live trees */ struct label { bool deleted; char *label; struct label *next; }; +struct bus_type { + const char *name; +}; + struct property { bool deleted; char *name; struct data val; struct property *next; struct label *labels; }; struct node { bool deleted; char *name; struct property *proplist; struct node *children; struct node *parent; struct node *next_sibling; char *fullpath; int basenamelen; cell_t phandle; int addr_cells, size_cells; struct label *labels; + const struct bus_type *bus; }; #define for_each_label_withdel(l0, l) \ for ((l) = (l0); (l); (l) = (l)->next) #define for_each_label(l0, l) \ for_each_label_withdel(l0, l) \ if (!(l)->deleted) #define for_each_property_withdel(n, p) \ for ((p) = (n)->proplist; (p); (p) = (p)->next) #define for_each_property(n, p) \ for_each_property_withdel(n, p) \ if (!(p)->deleted) #define for_each_child_withdel(n, c) \ for ((c) = (n)->children; (c); (c) = (c)->next_sibling) #define for_each_child(n, c) \ for_each_child_withdel(n, c) \ if (!(c)->deleted) void add_label(struct label **labels, char *label); void delete_labels(struct label **labels); struct property *build_property(char *name, struct data val); struct property *build_property_delete(char *name); struct property *chain_property(struct property *first, struct property *list); struct property *reverse_properties(struct property *first); struct node *build_node(struct property *proplist, struct node *children); struct node *build_node_delete(void); struct node *name_node(struct node *node, char *name); struct node *chain_node(struct node *first, struct node *list); struct node *merge_nodes(struct node *old_node, struct node *new_node); +struct node *add_orphan_node(struct node *old_node, struct node *new_node, char *ref); void add_property(struct node *node, struct property *prop); void delete_property_by_name(struct node *node, char *name); void delete_property(struct property *prop); void add_child(struct node *parent, struct node *child); void delete_node_by_name(struct node *parent, char *name); void delete_node(struct node *node); void append_to_property(struct node *node, char *name, const void *data, int len); const char *get_unitname(struct node *node); struct property *get_property(struct node *node, const char *propname); cell_t propval_cell(struct property *prop); +cell_t propval_cell_n(struct property *prop, int n); struct property *get_property_by_label(struct node *tree, const char *label, struct node **node); struct marker *get_marker_label(struct node *tree, const char *label, struct node **node, struct property **prop); struct node *get_subnode(struct node *node, const char *nodename); struct node *get_node_by_path(struct node *tree, const char *path); struct node *get_node_by_label(struct node *tree, const char *label); struct node *get_node_by_phandle(struct node *tree, cell_t phandle); struct node *get_node_by_ref(struct node *tree, const char *ref); cell_t get_node_phandle(struct node *root, struct node *node); uint32_t guess_boot_cpuid(struct node *tree); /* Boot info (tree plus memreserve information */ struct reserve_info { - struct fdt_reserve_entry re; + uint64_t address, size; struct reserve_info *next; struct label *labels; }; struct reserve_info *build_reserve_entry(uint64_t start, uint64_t len); struct reserve_info *chain_reserve_entry(struct reserve_info *first, struct reserve_info *list); struct reserve_info *add_reserve_entry(struct reserve_info *list, struct reserve_info *new); struct dt_info { unsigned int dtsflags; struct reserve_info *reservelist; uint32_t boot_cpuid_phys; struct node *dt; /* the device tree */ const char *outname; /* filename being written to, "-" for stdout */ }; /* DTS version flags definitions */ #define DTSF_V1 0x0001 /* /dts-v1/ */ #define DTSF_PLUGIN 0x0002 /* /plugin/ */ struct dt_info *build_dt_info(unsigned int dtsflags, struct reserve_info *reservelist, struct node *tree, uint32_t boot_cpuid_phys); void sort_tree(struct dt_info *dti); void generate_label_tree(struct dt_info *dti, char *name, bool allocph); void generate_fixups_tree(struct dt_info *dti, char *name); void generate_local_fixups_tree(struct dt_info *dti, char *name); /* Checks */ void parse_checks_option(bool warn, bool error, const char *arg); void process_checks(bool force, struct dt_info *dti); /* Flattened trees */ void dt_to_blob(FILE *f, struct dt_info *dti, int version); void dt_to_asm(FILE *f, struct dt_info *dti, int version); struct dt_info *dt_from_blob(const char *fname); /* Tree source */ void dt_to_source(FILE *f, struct dt_info *dti); struct dt_info *dt_from_source(const char *f); /* FS trees */ struct dt_info *dt_from_fs(const char *dirname); -#endif /* _DTC_H */ +#endif /* DTC_H */ Index: vendor/dtc/dist/fdtdump.c =================================================================== --- vendor/dtc/dist/fdtdump.c (revision 327892) +++ vendor/dtc/dist/fdtdump.c (revision 327893) @@ -1,240 +1,245 @@ /* * fdtdump.c - Contributed by Pantelis Antoniou */ #include #include #include #include #include #include #include #include #include #include "util.h" #define FDT_MAGIC_SIZE 4 #define MAX_VERSION 17 #define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1)) #define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a)))) -#define GET_CELL(p) (p += 4, *((const uint32_t *)(p-4))) +#define GET_CELL(p) (p += 4, *((const fdt32_t *)(p-4))) static const char *tagname(uint32_t tag) { static const char * const names[] = { #define TN(t) [t] = #t TN(FDT_BEGIN_NODE), TN(FDT_END_NODE), TN(FDT_PROP), TN(FDT_NOP), TN(FDT_END), #undef TN }; if (tag < ARRAY_SIZE(names)) if (names[tag]) return names[tag]; return "FDT_???"; } #define dumpf(fmt, args...) \ do { if (debug) printf("// " fmt, ## args); } while (0) static void dump_blob(void *blob, bool debug) { uintptr_t blob_off = (uintptr_t)blob; struct fdt_header *bph = blob; uint32_t off_mem_rsvmap = fdt32_to_cpu(bph->off_mem_rsvmap); uint32_t off_dt = fdt32_to_cpu(bph->off_dt_struct); uint32_t off_str = fdt32_to_cpu(bph->off_dt_strings); struct fdt_reserve_entry *p_rsvmap = (struct fdt_reserve_entry *)((char *)blob + off_mem_rsvmap); const char *p_struct = (const char *)blob + off_dt; const char *p_strings = (const char *)blob + off_str; uint32_t version = fdt32_to_cpu(bph->version); uint32_t totalsize = fdt32_to_cpu(bph->totalsize); uint32_t tag; const char *p, *s, *t; int depth, sz, shift; int i; uint64_t addr, size; depth = 0; shift = 4; printf("/dts-v1/;\n"); printf("// magic:\t\t0x%x\n", fdt32_to_cpu(bph->magic)); printf("// totalsize:\t\t0x%x (%d)\n", totalsize, totalsize); printf("// off_dt_struct:\t0x%x\n", off_dt); printf("// off_dt_strings:\t0x%x\n", off_str); printf("// off_mem_rsvmap:\t0x%x\n", off_mem_rsvmap); printf("// version:\t\t%d\n", version); printf("// last_comp_version:\t%d\n", fdt32_to_cpu(bph->last_comp_version)); if (version >= 2) printf("// boot_cpuid_phys:\t0x%x\n", fdt32_to_cpu(bph->boot_cpuid_phys)); if (version >= 3) printf("// size_dt_strings:\t0x%x\n", fdt32_to_cpu(bph->size_dt_strings)); if (version >= 17) printf("// size_dt_struct:\t0x%x\n", fdt32_to_cpu(bph->size_dt_struct)); printf("\n"); for (i = 0; ; i++) { addr = fdt64_to_cpu(p_rsvmap[i].address); size = fdt64_to_cpu(p_rsvmap[i].size); if (addr == 0 && size == 0) break; printf("/memreserve/ %#llx %#llx;\n", (unsigned long long)addr, (unsigned long long)size); } p = p_struct; while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) { dumpf("%04zx: tag: 0x%08x (%s)\n", (uintptr_t)p - blob_off - 4, tag, tagname(tag)); if (tag == FDT_BEGIN_NODE) { s = p; p = PALIGN(p + strlen(s) + 1, 4); if (*s == '\0') s = "/"; printf("%*s%s {\n", depth * shift, "", s); depth++; continue; } if (tag == FDT_END_NODE) { depth--; printf("%*s};\n", depth * shift, ""); continue; } if (tag == FDT_NOP) { printf("%*s// [NOP]\n", depth * shift, ""); continue; } if (tag != FDT_PROP) { fprintf(stderr, "%*s ** Unknown tag 0x%08x\n", depth * shift, "", tag); break; } sz = fdt32_to_cpu(GET_CELL(p)); s = p_strings + fdt32_to_cpu(GET_CELL(p)); if (version < 16 && sz >= 8) p = PALIGN(p, 8); t = p; p = PALIGN(p + sz, 4); dumpf("%04zx: string: %s\n", (uintptr_t)s - blob_off, s); dumpf("%04zx: value\n", (uintptr_t)t - blob_off); printf("%*s%s", depth * shift, "", s); utilfdt_print_data(t, sz); printf(";\n"); } } /* Usage related data. */ static const char usage_synopsis[] = "fdtdump [options] "; static const char usage_short_opts[] = "ds" USAGE_COMMON_SHORT_OPTS; static struct option const usage_long_opts[] = { {"debug", no_argument, NULL, 'd'}, {"scan", no_argument, NULL, 's'}, USAGE_COMMON_LONG_OPTS }; static const char * const usage_opts_help[] = { "Dump debug information while decoding the file", "Scan for an embedded fdt in file", USAGE_COMMON_OPTS_HELP }; static bool valid_header(char *p, off_t len) { if (len < sizeof(struct fdt_header) || fdt_magic(p) != FDT_MAGIC || fdt_version(p) > MAX_VERSION || - fdt_last_comp_version(p) >= MAX_VERSION || + fdt_last_comp_version(p) > MAX_VERSION || fdt_totalsize(p) >= len || fdt_off_dt_struct(p) >= len || fdt_off_dt_strings(p) >= len) return 0; else return 1; } int main(int argc, char *argv[]) { int opt; const char *file; char *buf; bool debug = false; bool scan = false; off_t len; + fprintf(stderr, "\n" +"**** fdtdump is a low-level debugging tool, not meant for general use.\n" +"**** If you want to decompile a dtb, you probably want\n" +"**** dtc -I dtb -O dts \n\n" + ); while ((opt = util_getopt_long()) != EOF) { switch (opt) { case_USAGE_COMMON_FLAGS case 'd': debug = true; break; case 's': scan = true; break; } } if (optind != argc - 1) usage("missing input filename"); file = argv[optind]; buf = utilfdt_read_len(file, &len); if (!buf) die("could not read: %s\n", file); /* try and locate an embedded fdt in a bigger blob */ if (scan) { unsigned char smagic[FDT_MAGIC_SIZE]; char *p = buf; char *endp = buf + len; fdt_set_magic(smagic, FDT_MAGIC); /* poor man's memmem */ while ((endp - p) >= FDT_MAGIC_SIZE) { p = memchr(p, smagic[0], endp - p - FDT_MAGIC_SIZE); if (!p) break; if (fdt_magic(p) == FDT_MAGIC) { /* try and validate the main struct */ off_t this_len = endp - p; if (valid_header(p, this_len)) break; if (debug) printf("%s: skipping fdt magic at offset %#zx\n", file, p - buf); } ++p; } if (!p || endp - p < sizeof(struct fdt_header)) die("%s: could not locate fdt magic\n", file); printf("%s: found fdt at offset %#zx\n", file, p - buf); buf = p; } else if (!valid_header(buf, len)) die("%s: header is not valid\n", file); dump_blob(buf, debug); return 0; } Index: vendor/dtc/dist/fdtget.c =================================================================== --- vendor/dtc/dist/fdtget.c (revision 327892) +++ vendor/dtc/dist/fdtget.c (revision 327893) @@ -1,366 +1,385 @@ /* * Copyright (c) 2011 The Chromium OS Authors. All rights reserved. * * Portions from U-Boot cmd_fdt.c (C) Copyright 2007 * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com * Based on code written by: * Pantelis Antoniou and * Matthew McClintock * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ #include #include #include #include #include #include #include #include "util.h" enum display_mode { MODE_SHOW_VALUE, /* show values for node properties */ MODE_LIST_PROPS, /* list the properties for a node */ MODE_LIST_SUBNODES, /* list the subnodes of a node */ }; /* Holds information which controls our output and options */ struct display_info { int type; /* data type (s/i/u/x or 0 for default) */ int size; /* data size (1/2/4) */ enum display_mode mode; /* display mode that we are using */ const char *default_val; /* default value if node/property not found */ }; static void report_error(const char *where, int err) { fprintf(stderr, "Error at '%s': %s\n", where, fdt_strerror(err)); } /** + * Shows a list of cells in the requested format + * + * @param disp Display information / options + * @param data Data to display + * @param len Maximum length of buffer + * @param size Data size to use for display (e.g. 4 for 32-bit) + * @return 0 if ok, -1 on error + */ +static int show_cell_list(struct display_info *disp, const char *data, int len, + int size) +{ + const uint8_t *p = (const uint8_t *)data; + char fmt[3]; + int value; + int i; + + fmt[0] = '%'; + fmt[1] = disp->type ? disp->type : 'd'; + fmt[2] = '\0'; + for (i = 0; i < len; i += size, p += size) { + if (i) + printf(" "); + value = size == 4 ? fdt32_to_cpu(*(const fdt32_t *)p) : + size == 2 ? (*p << 8) | p[1] : *p; + printf(fmt, value); + } + + return 0; +} + +/** * Displays data of a given length according to selected options * * If a specific data type is provided in disp, then this is used. Otherwise * we try to guess the data type / size from the contents. * * @param disp Display information / options * @param data Data to display * @param len Maximum length of buffer * @return 0 if ok, -1 if data does not match format */ static int show_data(struct display_info *disp, const char *data, int len) { - int i, size; - const uint8_t *p = (const uint8_t *)data; + int size; const char *s; - int value; int is_string; - char fmt[3]; /* no data, don't print */ if (len == 0) return 0; is_string = (disp->type) == 's' || (!disp->type && util_is_printable_string(data, len)); if (is_string) { if (data[len - 1] != '\0') { fprintf(stderr, "Unterminated string\n"); return -1; } for (s = data; s - data < len; s += strlen(s) + 1) { if (s != data) printf(" "); printf("%s", (const char *)s); } return 0; } size = disp->size; if (size == -1) { size = (len % 4) == 0 ? 4 : 1; } else if (len % size) { fprintf(stderr, "Property length must be a multiple of " "selected data size\n"); return -1; } - fmt[0] = '%'; - fmt[1] = disp->type ? disp->type : 'd'; - fmt[2] = '\0'; - for (i = 0; i < len; i += size, p += size) { - if (i) - printf(" "); - value = size == 4 ? fdt32_to_cpu(*(const uint32_t *)p) : - size == 2 ? (*p << 8) | p[1] : *p; - printf(fmt, value); - } - return 0; + + return show_cell_list(disp, data, len, size); } /** * List all properties in a node, one per line. * * @param blob FDT blob * @param node Node to display * @return 0 if ok, or FDT_ERR... if not. */ static int list_properties(const void *blob, int node) { const struct fdt_property *data; const char *name; int prop; prop = fdt_first_property_offset(blob, node); do { /* Stop silently when there are no more properties */ if (prop < 0) return prop == -FDT_ERR_NOTFOUND ? 0 : prop; data = fdt_get_property_by_offset(blob, prop, NULL); name = fdt_string(blob, fdt32_to_cpu(data->nameoff)); if (name) puts(name); prop = fdt_next_property_offset(blob, prop); } while (1); } #define MAX_LEVEL 32 /* how deeply nested we will go */ /** * List all subnodes in a node, one per line * * @param blob FDT blob * @param node Node to display * @return 0 if ok, or FDT_ERR... if not. */ static int list_subnodes(const void *blob, int node) { int nextoffset; /* next node offset from libfdt */ uint32_t tag; /* current tag */ int level = 0; /* keep track of nesting level */ const char *pathp; int depth = 1; /* the assumed depth of this node */ while (level >= 0) { tag = fdt_next_tag(blob, node, &nextoffset); switch (tag) { case FDT_BEGIN_NODE: pathp = fdt_get_name(blob, node, NULL); if (level <= depth) { if (pathp == NULL) pathp = "/* NULL pointer error */"; if (*pathp == '\0') pathp = "/"; /* root is nameless */ if (level == 1) puts(pathp); } level++; if (level >= MAX_LEVEL) { printf("Nested too deep, aborting.\n"); return 1; } break; case FDT_END_NODE: level--; if (level == 0) level = -1; /* exit the loop */ break; case FDT_END: return 1; case FDT_PROP: break; default: if (level <= depth) printf("Unknown tag 0x%08X\n", tag); return 1; } node = nextoffset; } return 0; } /** * Show the data for a given node (and perhaps property) according to the * display option provided. * * @param blob FDT blob * @param disp Display information / options * @param node Node to display * @param property Name of property to display, or NULL if none * @return 0 if ok, -ve on error */ static int show_data_for_item(const void *blob, struct display_info *disp, int node, const char *property) { const void *value = NULL; int len, err = 0; switch (disp->mode) { case MODE_LIST_PROPS: err = list_properties(blob, node); break; case MODE_LIST_SUBNODES: err = list_subnodes(blob, node); break; default: assert(property); value = fdt_getprop(blob, node, property, &len); if (value) { if (show_data(disp, value, len)) err = -1; else printf("\n"); } else if (disp->default_val) { puts(disp->default_val); } else { report_error(property, len); err = -1; } break; } return err; } /** * Run the main fdtget operation, given a filename and valid arguments * * @param disp Display information / options * @param filename Filename of blob file * @param arg List of arguments to process * @param arg_count Number of arguments - * @param return 0 if ok, -ve on error + * @return 0 if ok, -ve on error */ static int do_fdtget(struct display_info *disp, const char *filename, char **arg, int arg_count, int args_per_step) { char *blob; const char *prop; int i, node; blob = utilfdt_read(filename); if (!blob) return -1; for (i = 0; i + args_per_step <= arg_count; i += args_per_step) { node = fdt_path_offset(blob, arg[i]); if (node < 0) { if (disp->default_val) { puts(disp->default_val); continue; } else { report_error(arg[i], node); free(blob); return -1; } } prop = args_per_step == 1 ? NULL : arg[i + 1]; if (show_data_for_item(blob, disp, node, prop)) { free(blob); return -1; } } free(blob); return 0; } /* Usage related data. */ static const char usage_synopsis[] = "read values from device tree\n" " fdtget
[ ]...\n" " fdtget -p
[ ]...\n" "\n" "Each value is printed on a new line.\n" USAGE_TYPE_MSG; static const char usage_short_opts[] = "t:pld:" USAGE_COMMON_SHORT_OPTS; static struct option const usage_long_opts[] = { {"type", a_argument, NULL, 't'}, {"properties", no_argument, NULL, 'p'}, {"list", no_argument, NULL, 'l'}, {"default", a_argument, NULL, 'd'}, USAGE_COMMON_LONG_OPTS, }; static const char * const usage_opts_help[] = { "Type of data", "List properties for each node", "List subnodes for each node", "Default value to display when the property is missing", USAGE_COMMON_OPTS_HELP }; int main(int argc, char *argv[]) { int opt; char *filename = NULL; struct display_info disp; int args_per_step = 2; /* set defaults */ memset(&disp, '\0', sizeof(disp)); disp.size = -1; disp.mode = MODE_SHOW_VALUE; while ((opt = util_getopt_long()) != EOF) { switch (opt) { case_USAGE_COMMON_FLAGS case 't': if (utilfdt_decode_type(optarg, &disp.type, &disp.size)) usage("invalid type string"); break; case 'p': disp.mode = MODE_LIST_PROPS; args_per_step = 1; break; case 'l': disp.mode = MODE_LIST_SUBNODES; args_per_step = 1; break; case 'd': disp.default_val = optarg; break; } } if (optind < argc) filename = argv[optind++]; if (!filename) usage("missing filename"); argv += optind; argc -= optind; /* Allow no arguments, and silently succeed */ if (!argc) return 0; /* Check for node, property arguments */ if (args_per_step == 2 && (argc % 2)) usage("must have an even number of arguments"); if (do_fdtget(&disp, filename, argv, argc, args_per_step)) return 1; return 0; } Index: vendor/dtc/dist/fdtoverlay.c =================================================================== --- vendor/dtc/dist/fdtoverlay.c (nonexistent) +++ vendor/dtc/dist/fdtoverlay.c (revision 327893) @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2017 Konsulko Group Inc. All rights reserved. + * + * Author: + * Pantelis Antoniou + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "util.h" + +/* Usage related data. */ +static const char usage_synopsis[] = + "apply a number of overlays to a base blob\n" + " fdtoverlay [ []]\n" + "\n" + USAGE_TYPE_MSG; +static const char usage_short_opts[] = "i:o:v" USAGE_COMMON_SHORT_OPTS; +static struct option const usage_long_opts[] = { + {"input", required_argument, NULL, 'i'}, + {"output", required_argument, NULL, 'o'}, + {"verbose", no_argument, NULL, 'v'}, + USAGE_COMMON_LONG_OPTS, +}; +static const char * const usage_opts_help[] = { + "Input base DT blob", + "Output DT blob", + "Verbose messages", + USAGE_COMMON_OPTS_HELP +}; + +int verbose = 0; + +static int do_fdtoverlay(const char *input_filename, + const char *output_filename, + int argc, char *argv[]) +{ + char *blob = NULL; + char **ovblob = NULL; + off_t blob_len, ov_len, total_len; + int i, ret = -1; + + blob = utilfdt_read_len(input_filename, &blob_len); + if (!blob) { + fprintf(stderr, "\nFailed to read base blob %s\n", + input_filename); + goto out_err; + } + if (fdt_totalsize(blob) > blob_len) { + fprintf(stderr, + "\nBase blob is incomplete (%lu / %" PRIu32 " bytes read)\n", + (unsigned long)blob_len, fdt_totalsize(blob)); + goto out_err; + } + ret = 0; + + /* allocate blob pointer array */ + ovblob = malloc(sizeof(*ovblob) * argc); + memset(ovblob, 0, sizeof(*ovblob) * argc); + + /* read and keep track of the overlay blobs */ + total_len = 0; + for (i = 0; i < argc; i++) { + ovblob[i] = utilfdt_read_len(argv[i], &ov_len); + if (!ovblob[i]) { + fprintf(stderr, "\nFailed to read overlay %s\n", + argv[i]); + goto out_err; + } + total_len += ov_len; + } + + /* grow the blob to worst case */ + blob_len = fdt_totalsize(blob) + total_len; + blob = xrealloc(blob, blob_len); + fdt_open_into(blob, blob, blob_len); + + /* apply the overlays in sequence */ + for (i = 0; i < argc; i++) { + ret = fdt_overlay_apply(blob, ovblob[i]); + if (ret) { + fprintf(stderr, "\nFailed to apply %s (%d)\n", + argv[i], ret); + goto out_err; + } + } + + fdt_pack(blob); + ret = utilfdt_write(output_filename, blob); + if (ret) + fprintf(stderr, "\nFailed to write output blob %s\n", + output_filename); + +out_err: + if (ovblob) { + for (i = 0; i < argc; i++) { + if (ovblob[i]) + free(ovblob[i]); + } + free(ovblob); + } + free(blob); + + return ret; +} + +int main(int argc, char *argv[]) +{ + int opt, i; + char *input_filename = NULL; + char *output_filename = NULL; + + while ((opt = util_getopt_long()) != EOF) { + switch (opt) { + case_USAGE_COMMON_FLAGS + + case 'i': + input_filename = optarg; + break; + case 'o': + output_filename = optarg; + break; + case 'v': + verbose = 1; + break; + } + } + + if (!input_filename) + usage("missing input file"); + + if (!output_filename) + usage("missing output file"); + + argv += optind; + argc -= optind; + + if (argc <= 0) + usage("missing overlay file(s)"); + + if (verbose) { + printf("input = %s\n", input_filename); + printf("output = %s\n", output_filename); + for (i = 0; i < argc; i++) + printf("overlay[%d] = %s\n", i, argv[i]); + } + + if (do_fdtoverlay(input_filename, output_filename, argc, argv)) + return 1; + + return 0; +} Property changes on: vendor/dtc/dist/fdtoverlay.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/dtc/dist/fdtput.c =================================================================== --- vendor/dtc/dist/fdtput.c (revision 327892) +++ vendor/dtc/dist/fdtput.c (revision 327893) @@ -1,480 +1,480 @@ /* * Copyright (c) 2011 The Chromium OS Authors. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ #include #include #include #include #include #include #include #include "util.h" /* These are the operations we support */ enum oper_type { OPER_WRITE_PROP, /* Write a property in a node */ OPER_CREATE_NODE, /* Create a new node */ OPER_REMOVE_NODE, /* Delete a node */ OPER_DELETE_PROP, /* Delete a property in a node */ }; struct display_info { enum oper_type oper; /* operation to perform */ int type; /* data type (s/i/u/x or 0 for default) */ int size; /* data size (1/2/4) */ int verbose; /* verbose output */ int auto_path; /* automatically create all path components */ }; /** * Report an error with a particular node. * * @param name Node name to report error on * @param namelen Length of node name, or -1 to use entire string * @param err Error number to report (-FDT_ERR_...) */ static void report_error(const char *name, int namelen, int err) { if (namelen == -1) namelen = strlen(name); fprintf(stderr, "Error at '%1.*s': %s\n", namelen, name, fdt_strerror(err)); } /** * Encode a series of arguments in a property value. * * @param disp Display information / options * @param arg List of arguments from command line * @param arg_count Number of arguments (may be 0) * @param valuep Returns buffer containing value - * @param *value_len Returns length of value encoded + * @param value_len Returns length of value encoded */ static int encode_value(struct display_info *disp, char **arg, int arg_count, char **valuep, int *value_len) { char *value = NULL; /* holding area for value */ int value_size = 0; /* size of holding area */ char *ptr; /* pointer to current value position */ int len; /* length of this cell/string/byte */ int ival; int upto; /* the number of bytes we have written to buf */ char fmt[3]; upto = 0; if (disp->verbose) fprintf(stderr, "Decoding value:\n"); fmt[0] = '%'; fmt[1] = disp->type ? disp->type : 'd'; fmt[2] = '\0'; for (; arg_count > 0; arg++, arg_count--, upto += len) { /* assume integer unless told otherwise */ if (disp->type == 's') len = strlen(*arg) + 1; else len = disp->size == -1 ? 4 : disp->size; /* enlarge our value buffer by a suitable margin if needed */ if (upto + len > value_size) { value_size = (upto + len) + 500; value = xrealloc(value, value_size); } ptr = value + upto; if (disp->type == 's') { memcpy(ptr, *arg, len); if (disp->verbose) fprintf(stderr, "\tstring: '%s'\n", ptr); } else { - int *iptr = (int *)ptr; + fdt32_t *iptr = (fdt32_t *)ptr; sscanf(*arg, fmt, &ival); if (len == 4) *iptr = cpu_to_fdt32(ival); else *ptr = (uint8_t)ival; if (disp->verbose) { fprintf(stderr, "\t%s: %d\n", disp->size == 1 ? "byte" : disp->size == 2 ? "short" : "int", ival); } } } *value_len = upto; *valuep = value; if (disp->verbose) fprintf(stderr, "Value size %d\n", upto); return 0; } #define ALIGN(x) (((x) + (FDT_TAGSIZE) - 1) & ~((FDT_TAGSIZE) - 1)) -static char *_realloc_fdt(char *fdt, int delta) +static char *realloc_fdt(char *fdt, int delta) { int new_sz = fdt_totalsize(fdt) + delta; fdt = xrealloc(fdt, new_sz); fdt_open_into(fdt, fdt, new_sz); return fdt; } static char *realloc_node(char *fdt, const char *name) { int delta; /* FDT_BEGIN_NODE, node name in off_struct and FDT_END_NODE */ delta = sizeof(struct fdt_node_header) + ALIGN(strlen(name) + 1) + FDT_TAGSIZE; - return _realloc_fdt(fdt, delta); + return realloc_fdt(fdt, delta); } static char *realloc_property(char *fdt, int nodeoffset, const char *name, int newlen) { int delta = 0; int oldlen = 0; if (!fdt_get_property(fdt, nodeoffset, name, &oldlen)) /* strings + property header */ delta = sizeof(struct fdt_property) + strlen(name) + 1; if (newlen > oldlen) /* actual value in off_struct */ delta += ALIGN(newlen) - ALIGN(oldlen); - return _realloc_fdt(fdt, delta); + return realloc_fdt(fdt, delta); } static int store_key_value(char **blob, const char *node_name, const char *property, const char *buf, int len) { int node; int err; node = fdt_path_offset(*blob, node_name); if (node < 0) { report_error(node_name, -1, node); return -1; } err = fdt_setprop(*blob, node, property, buf, len); if (err == -FDT_ERR_NOSPACE) { *blob = realloc_property(*blob, node, property, len); err = fdt_setprop(*blob, node, property, buf, len); } if (err) { report_error(property, -1, err); return -1; } return 0; } /** * Create paths as needed for all components of a path * * Any components of the path that do not exist are created. Errors are * reported. * * @param blob FDT blob to write into * @param in_path Path to process * @return 0 if ok, -1 on error */ static int create_paths(char **blob, const char *in_path) { const char *path = in_path; const char *sep; int node, offset = 0; /* skip leading '/' */ while (*path == '/') path++; for (sep = path; *sep; path = sep + 1, offset = node) { /* equivalent to strchrnul(), but it requires _GNU_SOURCE */ sep = strchr(path, '/'); if (!sep) sep = path + strlen(path); node = fdt_subnode_offset_namelen(*blob, offset, path, sep - path); if (node == -FDT_ERR_NOTFOUND) { *blob = realloc_node(*blob, path); node = fdt_add_subnode_namelen(*blob, offset, path, sep - path); } if (node < 0) { report_error(path, sep - path, node); return -1; } } return 0; } /** * Create a new node in the fdt. * * This will overwrite the node_name string. Any error is reported. * * TODO: Perhaps create fdt_path_offset_namelen() so we don't need to do this. * * @param blob FDT blob to write into * @param node_name Name of node to create * @return new node offset if found, or -1 on failure */ static int create_node(char **blob, const char *node_name) { int node = 0; char *p; p = strrchr(node_name, '/'); if (!p) { report_error(node_name, -1, -FDT_ERR_BADPATH); return -1; } *p = '\0'; *blob = realloc_node(*blob, p + 1); if (p > node_name) { node = fdt_path_offset(*blob, node_name); if (node < 0) { report_error(node_name, -1, node); return -1; } } node = fdt_add_subnode(*blob, node, p + 1); if (node < 0) { report_error(p + 1, -1, node); return -1; } return 0; } /** * Delete a property of a node in the fdt. * * @param blob FDT blob to write into * @param node_name Path to node containing the property to delete * @param prop_name Name of property to delete * @return 0 on success, or -1 on failure */ static int delete_prop(char *blob, const char *node_name, const char *prop_name) { int node = 0; node = fdt_path_offset(blob, node_name); if (node < 0) { report_error(node_name, -1, node); return -1; } node = fdt_delprop(blob, node, prop_name); if (node < 0) { report_error(node_name, -1, node); return -1; } return 0; } /** * Delete a node in the fdt. * * @param blob FDT blob to write into * @param node_name Name of node to delete * @return 0 on success, or -1 on failure */ static int delete_node(char *blob, const char *node_name) { int node = 0; node = fdt_path_offset(blob, node_name); if (node < 0) { report_error(node_name, -1, node); return -1; } node = fdt_del_node(blob, node); if (node < 0) { report_error(node_name, -1, node); return -1; } return 0; } static int do_fdtput(struct display_info *disp, const char *filename, char **arg, int arg_count) { char *value = NULL; char *blob; char *node; int len, ret = 0; blob = utilfdt_read(filename); if (!blob) return -1; switch (disp->oper) { case OPER_WRITE_PROP: /* * Convert the arguments into a single binary value, then * store them into the property. */ assert(arg_count >= 2); if (disp->auto_path && create_paths(&blob, *arg)) return -1; if (encode_value(disp, arg + 2, arg_count - 2, &value, &len) || store_key_value(&blob, *arg, arg[1], value, len)) ret = -1; break; case OPER_CREATE_NODE: for (; ret >= 0 && arg_count--; arg++) { if (disp->auto_path) ret = create_paths(&blob, *arg); else ret = create_node(&blob, *arg); } break; case OPER_REMOVE_NODE: for (; ret >= 0 && arg_count--; arg++) ret = delete_node(blob, *arg); break; case OPER_DELETE_PROP: node = *arg; for (arg++; ret >= 0 && arg_count-- > 1; arg++) ret = delete_prop(blob, node, *arg); break; } if (ret >= 0) { fdt_pack(blob); ret = utilfdt_write(filename, blob); } free(blob); if (value) { free(value); } return ret; } /* Usage related data. */ static const char usage_synopsis[] = "write a property value to a device tree\n" " fdtput
[...]\n" " fdtput -c
[...]\n" " fdtput -r
[...]\n" " fdtput -d
[...]\n" "\n" "The command line arguments are joined together into a single value.\n" USAGE_TYPE_MSG; static const char usage_short_opts[] = "crdpt:v" USAGE_COMMON_SHORT_OPTS; static struct option const usage_long_opts[] = { {"create", no_argument, NULL, 'c'}, {"remove", no_argument, NULL, 'r'}, {"delete", no_argument, NULL, 'd'}, {"auto-path", no_argument, NULL, 'p'}, {"type", a_argument, NULL, 't'}, {"verbose", no_argument, NULL, 'v'}, USAGE_COMMON_LONG_OPTS, }; static const char * const usage_opts_help[] = { "Create nodes if they don't already exist", "Delete nodes (and any subnodes) if they already exist", "Delete properties if they already exist", "Automatically create nodes as needed for the node path", "Type of data", "Display each value decoded from command line", USAGE_COMMON_OPTS_HELP }; int main(int argc, char *argv[]) { int opt; struct display_info disp; char *filename = NULL; memset(&disp, '\0', sizeof(disp)); disp.size = -1; disp.oper = OPER_WRITE_PROP; while ((opt = util_getopt_long()) != EOF) { /* * TODO: add options to: * - rename node * - pack fdt before writing * - set amount of free space when writing */ switch (opt) { case_USAGE_COMMON_FLAGS case 'c': disp.oper = OPER_CREATE_NODE; break; case 'r': disp.oper = OPER_REMOVE_NODE; break; case 'd': disp.oper = OPER_DELETE_PROP; break; case 'p': disp.auto_path = 1; break; case 't': if (utilfdt_decode_type(optarg, &disp.type, &disp.size)) usage("Invalid type string"); break; case 'v': disp.verbose = 1; break; } } if (optind < argc) filename = argv[optind++]; if (!filename) usage("missing filename"); argv += optind; argc -= optind; if (disp.oper == OPER_WRITE_PROP) { if (argc < 1) usage("missing node"); if (argc < 2) usage("missing property"); } if (disp.oper == OPER_DELETE_PROP) if (argc < 1) usage("missing node"); if (do_fdtput(&disp, filename, argv, argc)) return 1; return 0; } Index: vendor/dtc/dist/flattree.c =================================================================== --- vendor/dtc/dist/flattree.c (revision 327892) +++ vendor/dtc/dist/flattree.c (revision 327893) @@ -1,946 +1,940 @@ /* * (C) Copyright David Gibson , IBM Corporation. 2005. * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ #include "dtc.h" #include "srcpos.h" #define FTF_FULLPATH 0x1 #define FTF_VARALIGN 0x2 #define FTF_NAMEPROPS 0x4 #define FTF_BOOTCPUID 0x8 #define FTF_STRTABSIZE 0x10 #define FTF_STRUCTSIZE 0x20 #define FTF_NOPS 0x40 static struct version_info { int version; int last_comp_version; int hdr_size; int flags; } version_table[] = { {1, 1, FDT_V1_SIZE, FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS}, {2, 1, FDT_V2_SIZE, FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS|FTF_BOOTCPUID}, {3, 1, FDT_V3_SIZE, FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS|FTF_BOOTCPUID|FTF_STRTABSIZE}, {16, 16, FDT_V3_SIZE, FTF_BOOTCPUID|FTF_STRTABSIZE|FTF_NOPS}, {17, 16, FDT_V17_SIZE, FTF_BOOTCPUID|FTF_STRTABSIZE|FTF_STRUCTSIZE|FTF_NOPS}, }; struct emitter { void (*cell)(void *, cell_t); - void (*string)(void *, char *, int); + void (*string)(void *, const char *, int); void (*align)(void *, int); void (*data)(void *, struct data); void (*beginnode)(void *, struct label *labels); void (*endnode)(void *, struct label *labels); void (*property)(void *, struct label *labels); }; static void bin_emit_cell(void *e, cell_t val) { struct data *dtbuf = e; *dtbuf = data_append_cell(*dtbuf, val); } -static void bin_emit_string(void *e, char *str, int len) +static void bin_emit_string(void *e, const char *str, int len) { struct data *dtbuf = e; if (len == 0) len = strlen(str); *dtbuf = data_append_data(*dtbuf, str, len); *dtbuf = data_append_byte(*dtbuf, '\0'); } static void bin_emit_align(void *e, int a) { struct data *dtbuf = e; *dtbuf = data_append_align(*dtbuf, a); } static void bin_emit_data(void *e, struct data d) { struct data *dtbuf = e; *dtbuf = data_append_data(*dtbuf, d.val, d.len); } static void bin_emit_beginnode(void *e, struct label *labels) { bin_emit_cell(e, FDT_BEGIN_NODE); } static void bin_emit_endnode(void *e, struct label *labels) { bin_emit_cell(e, FDT_END_NODE); } static void bin_emit_property(void *e, struct label *labels) { bin_emit_cell(e, FDT_PROP); } static struct emitter bin_emitter = { .cell = bin_emit_cell, .string = bin_emit_string, .align = bin_emit_align, .data = bin_emit_data, .beginnode = bin_emit_beginnode, .endnode = bin_emit_endnode, .property = bin_emit_property, }; static void emit_label(FILE *f, const char *prefix, const char *label) { fprintf(f, "\t.globl\t%s_%s\n", prefix, label); fprintf(f, "%s_%s:\n", prefix, label); fprintf(f, "_%s_%s:\n", prefix, label); } static void emit_offset_label(FILE *f, const char *label, int offset) { fprintf(f, "\t.globl\t%s\n", label); fprintf(f, "%s\t= . + %d\n", label, offset); } #define ASM_EMIT_BELONG(f, fmt, ...) \ { \ fprintf((f), "\t.byte\t((" fmt ") >> 24) & 0xff\n", __VA_ARGS__); \ fprintf((f), "\t.byte\t((" fmt ") >> 16) & 0xff\n", __VA_ARGS__); \ fprintf((f), "\t.byte\t((" fmt ") >> 8) & 0xff\n", __VA_ARGS__); \ fprintf((f), "\t.byte\t(" fmt ") & 0xff\n", __VA_ARGS__); \ } static void asm_emit_cell(void *e, cell_t val) { FILE *f = e; fprintf(f, "\t.byte 0x%02x; .byte 0x%02x; .byte 0x%02x; .byte 0x%02x\n", (val >> 24) & 0xff, (val >> 16) & 0xff, (val >> 8) & 0xff, val & 0xff); } -static void asm_emit_string(void *e, char *str, int len) +static void asm_emit_string(void *e, const char *str, int len) { FILE *f = e; - char c = 0; - if (len != 0) { - /* XXX: ewww */ - c = str[len]; - str[len] = '\0'; - } - - fprintf(f, "\t.string\t\"%s\"\n", str); - - if (len != 0) { - str[len] = c; - } + if (len != 0) + fprintf(f, "\t.string\t\"%.*s\"\n", len, str); + else + fprintf(f, "\t.string\t\"%s\"\n", str); } static void asm_emit_align(void *e, int a) { FILE *f = e; fprintf(f, "\t.balign\t%d, 0\n", a); } static void asm_emit_data(void *e, struct data d) { FILE *f = e; int off = 0; struct marker *m = d.markers; for_each_marker_of_type(m, LABEL) emit_offset_label(f, m->ref, m->offset); while ((d.len - off) >= sizeof(uint32_t)) { - asm_emit_cell(e, fdt32_to_cpu(*((uint32_t *)(d.val+off)))); + asm_emit_cell(e, fdt32_to_cpu(*((fdt32_t *)(d.val+off)))); off += sizeof(uint32_t); } while ((d.len - off) >= 1) { fprintf(f, "\t.byte\t0x%hhx\n", d.val[off]); off += 1; } assert(off == d.len); } static void asm_emit_beginnode(void *e, struct label *labels) { FILE *f = e; struct label *l; for_each_label(labels, l) { fprintf(f, "\t.globl\t%s\n", l->label); fprintf(f, "%s:\n", l->label); } fprintf(f, "\t/* FDT_BEGIN_NODE */\n"); asm_emit_cell(e, FDT_BEGIN_NODE); } static void asm_emit_endnode(void *e, struct label *labels) { FILE *f = e; struct label *l; fprintf(f, "\t/* FDT_END_NODE */\n"); asm_emit_cell(e, FDT_END_NODE); for_each_label(labels, l) { fprintf(f, "\t.globl\t%s_end\n", l->label); fprintf(f, "%s_end:\n", l->label); } } static void asm_emit_property(void *e, struct label *labels) { FILE *f = e; struct label *l; for_each_label(labels, l) { fprintf(f, "\t.globl\t%s\n", l->label); fprintf(f, "%s:\n", l->label); } fprintf(f, "\t/* FDT_PROP */\n"); asm_emit_cell(e, FDT_PROP); } static struct emitter asm_emitter = { .cell = asm_emit_cell, .string = asm_emit_string, .align = asm_emit_align, .data = asm_emit_data, .beginnode = asm_emit_beginnode, .endnode = asm_emit_endnode, .property = asm_emit_property, }; static int stringtable_insert(struct data *d, const char *str) { int i; /* FIXME: do this more efficiently? */ for (i = 0; i < d->len; i++) { if (streq(str, d->val + i)) return i; } *d = data_append_data(*d, str, strlen(str)+1); return i; } static void flatten_tree(struct node *tree, struct emitter *emit, void *etarget, struct data *strbuf, struct version_info *vi) { struct property *prop; struct node *child; bool seen_name_prop = false; if (tree->deleted) return; emit->beginnode(etarget, tree->labels); if (vi->flags & FTF_FULLPATH) emit->string(etarget, tree->fullpath, 0); else emit->string(etarget, tree->name, 0); emit->align(etarget, sizeof(cell_t)); for_each_property(tree, prop) { int nameoff; if (streq(prop->name, "name")) seen_name_prop = true; nameoff = stringtable_insert(strbuf, prop->name); emit->property(etarget, prop->labels); emit->cell(etarget, prop->val.len); emit->cell(etarget, nameoff); if ((vi->flags & FTF_VARALIGN) && (prop->val.len >= 8)) emit->align(etarget, 8); emit->data(etarget, prop->val); emit->align(etarget, sizeof(cell_t)); } if ((vi->flags & FTF_NAMEPROPS) && !seen_name_prop) { emit->property(etarget, NULL); emit->cell(etarget, tree->basenamelen+1); emit->cell(etarget, stringtable_insert(strbuf, "name")); if ((vi->flags & FTF_VARALIGN) && ((tree->basenamelen+1) >= 8)) emit->align(etarget, 8); emit->string(etarget, tree->name, tree->basenamelen); emit->align(etarget, sizeof(cell_t)); } for_each_child(tree, child) { flatten_tree(child, emit, etarget, strbuf, vi); } emit->endnode(etarget, tree->labels); } static struct data flatten_reserve_list(struct reserve_info *reservelist, struct version_info *vi) { struct reserve_info *re; struct data d = empty_data; - static struct fdt_reserve_entry null_re = {0,0}; int j; for (re = reservelist; re; re = re->next) { - d = data_append_re(d, &re->re); + d = data_append_re(d, re->address, re->size); } /* * Add additional reserved slots if the user asked for them. */ for (j = 0; j < reservenum; j++) { - d = data_append_re(d, &null_re); + d = data_append_re(d, 0, 0); } return d; } static void make_fdt_header(struct fdt_header *fdt, struct version_info *vi, int reservesize, int dtsize, int strsize, int boot_cpuid_phys) { int reserve_off; reservesize += sizeof(struct fdt_reserve_entry); memset(fdt, 0xff, sizeof(*fdt)); fdt->magic = cpu_to_fdt32(FDT_MAGIC); fdt->version = cpu_to_fdt32(vi->version); fdt->last_comp_version = cpu_to_fdt32(vi->last_comp_version); /* Reserve map should be doubleword aligned */ reserve_off = ALIGN(vi->hdr_size, 8); fdt->off_mem_rsvmap = cpu_to_fdt32(reserve_off); fdt->off_dt_struct = cpu_to_fdt32(reserve_off + reservesize); fdt->off_dt_strings = cpu_to_fdt32(reserve_off + reservesize + dtsize); fdt->totalsize = cpu_to_fdt32(reserve_off + reservesize + dtsize + strsize); if (vi->flags & FTF_BOOTCPUID) fdt->boot_cpuid_phys = cpu_to_fdt32(boot_cpuid_phys); if (vi->flags & FTF_STRTABSIZE) fdt->size_dt_strings = cpu_to_fdt32(strsize); if (vi->flags & FTF_STRUCTSIZE) fdt->size_dt_struct = cpu_to_fdt32(dtsize); } void dt_to_blob(FILE *f, struct dt_info *dti, int version) { struct version_info *vi = NULL; int i; struct data blob = empty_data; struct data reservebuf = empty_data; struct data dtbuf = empty_data; struct data strbuf = empty_data; struct fdt_header fdt; int padlen = 0; for (i = 0; i < ARRAY_SIZE(version_table); i++) { if (version_table[i].version == version) vi = &version_table[i]; } if (!vi) die("Unknown device tree blob version %d\n", version); flatten_tree(dti->dt, &bin_emitter, &dtbuf, &strbuf, vi); bin_emit_cell(&dtbuf, FDT_END); reservebuf = flatten_reserve_list(dti->reservelist, vi); /* Make header */ make_fdt_header(&fdt, vi, reservebuf.len, dtbuf.len, strbuf.len, dti->boot_cpuid_phys); /* * If the user asked for more space than is used, adjust the totalsize. */ if (minsize > 0) { padlen = minsize - fdt32_to_cpu(fdt.totalsize); if (padlen < 0) { padlen = 0; if (quiet < 1) fprintf(stderr, "Warning: blob size %d >= minimum size %d\n", fdt32_to_cpu(fdt.totalsize), minsize); } } if (padsize > 0) padlen = padsize; if (alignsize > 0) padlen = ALIGN(fdt32_to_cpu(fdt.totalsize) + padlen, alignsize) - fdt32_to_cpu(fdt.totalsize); if (padlen > 0) { int tsize = fdt32_to_cpu(fdt.totalsize); tsize += padlen; fdt.totalsize = cpu_to_fdt32(tsize); } /* * Assemble the blob: start with the header, add with alignment * the reserve buffer, add the reserve map terminating zeroes, * the device tree itself, and finally the strings. */ blob = data_append_data(blob, &fdt, vi->hdr_size); blob = data_append_align(blob, 8); blob = data_merge(blob, reservebuf); blob = data_append_zeroes(blob, sizeof(struct fdt_reserve_entry)); blob = data_merge(blob, dtbuf); blob = data_merge(blob, strbuf); /* * If the user asked for more space than is used, pad out the blob. */ if (padlen > 0) blob = data_append_zeroes(blob, padlen); if (fwrite(blob.val, blob.len, 1, f) != 1) { if (ferror(f)) die("Error writing device tree blob: %s\n", strerror(errno)); else die("Short write on device tree blob\n"); } /* * data_merge() frees the right-hand element so only the blob * remains to be freed. */ data_free(blob); } static void dump_stringtable_asm(FILE *f, struct data strbuf) { const char *p; int len; p = strbuf.val; while (p < (strbuf.val + strbuf.len)) { len = strlen(p); fprintf(f, "\t.string \"%s\"\n", p); p += len+1; } } void dt_to_asm(FILE *f, struct dt_info *dti, int version) { struct version_info *vi = NULL; int i; struct data strbuf = empty_data; struct reserve_info *re; const char *symprefix = "dt"; for (i = 0; i < ARRAY_SIZE(version_table); i++) { if (version_table[i].version == version) vi = &version_table[i]; } if (!vi) die("Unknown device tree blob version %d\n", version); fprintf(f, "/* autogenerated by dtc, do not edit */\n\n"); emit_label(f, symprefix, "blob_start"); emit_label(f, symprefix, "header"); fprintf(f, "\t/* magic */\n"); asm_emit_cell(f, FDT_MAGIC); fprintf(f, "\t/* totalsize */\n"); ASM_EMIT_BELONG(f, "_%s_blob_abs_end - _%s_blob_start", symprefix, symprefix); fprintf(f, "\t/* off_dt_struct */\n"); ASM_EMIT_BELONG(f, "_%s_struct_start - _%s_blob_start", symprefix, symprefix); fprintf(f, "\t/* off_dt_strings */\n"); ASM_EMIT_BELONG(f, "_%s_strings_start - _%s_blob_start", symprefix, symprefix); fprintf(f, "\t/* off_mem_rsvmap */\n"); ASM_EMIT_BELONG(f, "_%s_reserve_map - _%s_blob_start", symprefix, symprefix); fprintf(f, "\t/* version */\n"); asm_emit_cell(f, vi->version); fprintf(f, "\t/* last_comp_version */\n"); asm_emit_cell(f, vi->last_comp_version); if (vi->flags & FTF_BOOTCPUID) { fprintf(f, "\t/* boot_cpuid_phys */\n"); asm_emit_cell(f, dti->boot_cpuid_phys); } if (vi->flags & FTF_STRTABSIZE) { fprintf(f, "\t/* size_dt_strings */\n"); ASM_EMIT_BELONG(f, "_%s_strings_end - _%s_strings_start", symprefix, symprefix); } if (vi->flags & FTF_STRUCTSIZE) { fprintf(f, "\t/* size_dt_struct */\n"); ASM_EMIT_BELONG(f, "_%s_struct_end - _%s_struct_start", symprefix, symprefix); } /* * Reserve map entries. * Align the reserve map to a doubleword boundary. * Each entry is an (address, size) pair of u64 values. * Always supply a zero-sized temination entry. */ asm_emit_align(f, 8); emit_label(f, symprefix, "reserve_map"); fprintf(f, "/* Memory reserve map from source file */\n"); /* * Use .long on high and low halfs of u64s to avoid .quad * as it appears .quad isn't available in some assemblers. */ for (re = dti->reservelist; re; re = re->next) { struct label *l; for_each_label(re->labels, l) { fprintf(f, "\t.globl\t%s\n", l->label); fprintf(f, "%s:\n", l->label); } - ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.address >> 32)); + ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->address >> 32)); ASM_EMIT_BELONG(f, "0x%08x", - (unsigned int)(re->re.address & 0xffffffff)); - ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.size >> 32)); - ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.size & 0xffffffff)); + (unsigned int)(re->address & 0xffffffff)); + ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->size >> 32)); + ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->size & 0xffffffff)); } for (i = 0; i < reservenum; i++) { fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n"); } fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n"); emit_label(f, symprefix, "struct_start"); flatten_tree(dti->dt, &asm_emitter, f, &strbuf, vi); fprintf(f, "\t/* FDT_END */\n"); asm_emit_cell(f, FDT_END); emit_label(f, symprefix, "struct_end"); emit_label(f, symprefix, "strings_start"); dump_stringtable_asm(f, strbuf); emit_label(f, symprefix, "strings_end"); emit_label(f, symprefix, "blob_end"); /* * If the user asked for more space than is used, pad it out. */ if (minsize > 0) { fprintf(f, "\t.space\t%d - (_%s_blob_end - _%s_blob_start), 0\n", minsize, symprefix, symprefix); } if (padsize > 0) { fprintf(f, "\t.space\t%d, 0\n", padsize); } if (alignsize > 0) asm_emit_align(f, alignsize); emit_label(f, symprefix, "blob_abs_end"); data_free(strbuf); } struct inbuf { char *base, *limit, *ptr; }; static void inbuf_init(struct inbuf *inb, void *base, void *limit) { inb->base = base; inb->limit = limit; inb->ptr = inb->base; } static void flat_read_chunk(struct inbuf *inb, void *p, int len) { if ((inb->ptr + len) > inb->limit) die("Premature end of data parsing flat device tree\n"); memcpy(p, inb->ptr, len); inb->ptr += len; } static uint32_t flat_read_word(struct inbuf *inb) { - uint32_t val; + fdt32_t val; assert(((inb->ptr - inb->base) % sizeof(val)) == 0); flat_read_chunk(inb, &val, sizeof(val)); return fdt32_to_cpu(val); } static void flat_realign(struct inbuf *inb, int align) { int off = inb->ptr - inb->base; inb->ptr = inb->base + ALIGN(off, align); if (inb->ptr > inb->limit) die("Premature end of data parsing flat device tree\n"); } static char *flat_read_string(struct inbuf *inb) { int len = 0; const char *p = inb->ptr; char *str; do { if (p >= inb->limit) die("Premature end of data parsing flat device tree\n"); len++; } while ((*p++) != '\0'); str = xstrdup(inb->ptr); inb->ptr += len; flat_realign(inb, sizeof(uint32_t)); return str; } static struct data flat_read_data(struct inbuf *inb, int len) { struct data d = empty_data; if (len == 0) return empty_data; d = data_grow_for(d, len); d.len = len; flat_read_chunk(inb, d.val, len); flat_realign(inb, sizeof(uint32_t)); return d; } static char *flat_read_stringtable(struct inbuf *inb, int offset) { const char *p; p = inb->base + offset; while (1) { if (p >= inb->limit || p < inb->base) die("String offset %d overruns string table\n", offset); if (*p == '\0') break; p++; } return xstrdup(inb->base + offset); } static struct property *flat_read_property(struct inbuf *dtbuf, struct inbuf *strbuf, int flags) { uint32_t proplen, stroff; char *name; struct data val; proplen = flat_read_word(dtbuf); stroff = flat_read_word(dtbuf); name = flat_read_stringtable(strbuf, stroff); if ((flags & FTF_VARALIGN) && (proplen >= 8)) flat_realign(dtbuf, 8); val = flat_read_data(dtbuf, proplen); return build_property(name, val); } static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb) { struct reserve_info *reservelist = NULL; struct reserve_info *new; struct fdt_reserve_entry re; /* * Each entry is a pair of u64 (addr, size) values for 4 cell_t's. * List terminates at an entry with size equal to zero. * * First pass, count entries. */ while (1) { + uint64_t address, size; + flat_read_chunk(inb, &re, sizeof(re)); - re.address = fdt64_to_cpu(re.address); - re.size = fdt64_to_cpu(re.size); - if (re.size == 0) + address = fdt64_to_cpu(re.address); + size = fdt64_to_cpu(re.size); + if (size == 0) break; - new = build_reserve_entry(re.address, re.size); + new = build_reserve_entry(address, size); reservelist = add_reserve_entry(reservelist, new); } return reservelist; } static char *nodename_from_path(const char *ppath, const char *cpath) { int plen; plen = strlen(ppath); - if (!strneq(ppath, cpath, plen)) + if (!strstarts(cpath, ppath)) die("Path \"%s\" is not valid as a child of \"%s\"\n", cpath, ppath); /* root node is a special case */ if (!streq(ppath, "/")) plen++; return xstrdup(cpath + plen); } static struct node *unflatten_tree(struct inbuf *dtbuf, struct inbuf *strbuf, const char *parent_flatname, int flags) { struct node *node; char *flatname; uint32_t val; node = build_node(NULL, NULL); flatname = flat_read_string(dtbuf); if (flags & FTF_FULLPATH) node->name = nodename_from_path(parent_flatname, flatname); else node->name = flatname; do { struct property *prop; struct node *child; val = flat_read_word(dtbuf); switch (val) { case FDT_PROP: if (node->children) fprintf(stderr, "Warning: Flat tree input has " "subnodes preceding a property.\n"); prop = flat_read_property(dtbuf, strbuf, flags); add_property(node, prop); break; case FDT_BEGIN_NODE: child = unflatten_tree(dtbuf,strbuf, flatname, flags); add_child(node, child); break; case FDT_END_NODE: break; case FDT_END: die("Premature FDT_END in device tree blob\n"); break; case FDT_NOP: if (!(flags & FTF_NOPS)) fprintf(stderr, "Warning: NOP tag found in flat tree" " version <16\n"); /* Ignore */ break; default: die("Invalid opcode word %08x in device tree blob\n", val); } } while (val != FDT_END_NODE); if (node->name != flatname) { free(flatname); } return node; } struct dt_info *dt_from_blob(const char *fname) { FILE *f; + fdt32_t magic_buf, totalsize_buf; uint32_t magic, totalsize, version, size_dt, boot_cpuid_phys; uint32_t off_dt, off_str, off_mem_rsvmap; int rc; char *blob; struct fdt_header *fdt; char *p; struct inbuf dtbuf, strbuf; struct inbuf memresvbuf; int sizeleft; struct reserve_info *reservelist; struct node *tree; uint32_t val; int flags = 0; f = srcfile_relative_open(fname, NULL); - rc = fread(&magic, sizeof(magic), 1, f); + rc = fread(&magic_buf, sizeof(magic_buf), 1, f); if (ferror(f)) die("Error reading DT blob magic number: %s\n", strerror(errno)); if (rc < 1) { if (feof(f)) die("EOF reading DT blob magic number\n"); else die("Mysterious short read reading magic number\n"); } - magic = fdt32_to_cpu(magic); + magic = fdt32_to_cpu(magic_buf); if (magic != FDT_MAGIC) die("Blob has incorrect magic number\n"); - rc = fread(&totalsize, sizeof(totalsize), 1, f); + rc = fread(&totalsize_buf, sizeof(totalsize_buf), 1, f); if (ferror(f)) die("Error reading DT blob size: %s\n", strerror(errno)); if (rc < 1) { if (feof(f)) die("EOF reading DT blob size\n"); else die("Mysterious short read reading blob size\n"); } - totalsize = fdt32_to_cpu(totalsize); + totalsize = fdt32_to_cpu(totalsize_buf); if (totalsize < FDT_V1_SIZE) die("DT blob size (%d) is too small\n", totalsize); blob = xmalloc(totalsize); fdt = (struct fdt_header *)blob; fdt->magic = cpu_to_fdt32(magic); fdt->totalsize = cpu_to_fdt32(totalsize); sizeleft = totalsize - sizeof(magic) - sizeof(totalsize); p = blob + sizeof(magic) + sizeof(totalsize); while (sizeleft) { if (feof(f)) die("EOF before reading %d bytes of DT blob\n", totalsize); rc = fread(p, 1, sizeleft, f); if (ferror(f)) die("Error reading DT blob: %s\n", strerror(errno)); sizeleft -= rc; p += rc; } off_dt = fdt32_to_cpu(fdt->off_dt_struct); off_str = fdt32_to_cpu(fdt->off_dt_strings); off_mem_rsvmap = fdt32_to_cpu(fdt->off_mem_rsvmap); version = fdt32_to_cpu(fdt->version); boot_cpuid_phys = fdt32_to_cpu(fdt->boot_cpuid_phys); if (off_mem_rsvmap >= totalsize) die("Mem Reserve structure offset exceeds total size\n"); if (off_dt >= totalsize) die("DT structure offset exceeds total size\n"); if (off_str > totalsize) die("String table offset exceeds total size\n"); if (version >= 3) { uint32_t size_str = fdt32_to_cpu(fdt->size_dt_strings); if ((off_str+size_str < off_str) || (off_str+size_str > totalsize)) die("String table extends past total size\n"); inbuf_init(&strbuf, blob + off_str, blob + off_str + size_str); } else { inbuf_init(&strbuf, blob + off_str, blob + totalsize); } if (version >= 17) { size_dt = fdt32_to_cpu(fdt->size_dt_struct); if ((off_dt+size_dt < off_dt) || (off_dt+size_dt > totalsize)) die("Structure block extends past total size\n"); } if (version < 16) { flags |= FTF_FULLPATH | FTF_NAMEPROPS | FTF_VARALIGN; } else { flags |= FTF_NOPS; } inbuf_init(&memresvbuf, blob + off_mem_rsvmap, blob + totalsize); inbuf_init(&dtbuf, blob + off_dt, blob + totalsize); reservelist = flat_read_mem_reserve(&memresvbuf); val = flat_read_word(&dtbuf); if (val != FDT_BEGIN_NODE) die("Device tree blob doesn't begin with FDT_BEGIN_NODE (begins with 0x%08x)\n", val); tree = unflatten_tree(&dtbuf, &strbuf, "", flags); val = flat_read_word(&dtbuf); if (val != FDT_END) die("Device tree blob doesn't end with FDT_END\n"); free(blob); fclose(f); return build_dt_info(DTSF_V1, reservelist, tree, boot_cpuid_phys); } Index: vendor/dtc/dist/libfdt/fdt.c =================================================================== --- vendor/dtc/dist/libfdt/fdt.c (revision 327892) +++ vendor/dtc/dist/libfdt/fdt.c (revision 327893) @@ -1,251 +1,251 @@ /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. * * libfdt is dual licensed: you can use it either under the terms of * the GPL, or the BSD license, at your option. * * a) This library is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301 USA * * Alternatively, * * b) Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * 1. Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "libfdt_env.h" #include #include #include "libfdt_internal.h" int fdt_check_header(const void *fdt) { if (fdt_magic(fdt) == FDT_MAGIC) { /* Complete tree */ if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) return -FDT_ERR_BADVERSION; if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) return -FDT_ERR_BADVERSION; } else if (fdt_magic(fdt) == FDT_SW_MAGIC) { /* Unfinished sequential-write blob */ if (fdt_size_dt_struct(fdt) == 0) return -FDT_ERR_BADSTATE; } else { return -FDT_ERR_BADMAGIC; } return 0; } const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) { unsigned absoffset = offset + fdt_off_dt_struct(fdt); if ((absoffset < offset) || ((absoffset + len) < absoffset) || (absoffset + len) > fdt_totalsize(fdt)) return NULL; if (fdt_version(fdt) >= 0x11) if (((offset + len) < offset) || ((offset + len) > fdt_size_dt_struct(fdt))) return NULL; - return _fdt_offset_ptr(fdt, offset); + return fdt_offset_ptr_(fdt, offset); } uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) { const fdt32_t *tagp, *lenp; uint32_t tag; int offset = startoffset; const char *p; *nextoffset = -FDT_ERR_TRUNCATED; tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE); if (!tagp) return FDT_END; /* premature end */ tag = fdt32_to_cpu(*tagp); offset += FDT_TAGSIZE; *nextoffset = -FDT_ERR_BADSTRUCTURE; switch (tag) { case FDT_BEGIN_NODE: /* skip name */ do { p = fdt_offset_ptr(fdt, offset++, 1); } while (p && (*p != '\0')); if (!p) return FDT_END; /* premature end */ break; case FDT_PROP: lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp)); if (!lenp) return FDT_END; /* premature end */ /* skip-name offset, length and value */ offset += sizeof(struct fdt_property) - FDT_TAGSIZE + fdt32_to_cpu(*lenp); break; case FDT_END: case FDT_END_NODE: case FDT_NOP: break; default: return FDT_END; } if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset)) return FDT_END; /* premature end */ *nextoffset = FDT_TAGALIGN(offset); return tag; } -int _fdt_check_node_offset(const void *fdt, int offset) +int fdt_check_node_offset_(const void *fdt, int offset) { if ((offset < 0) || (offset % FDT_TAGSIZE) || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE)) return -FDT_ERR_BADOFFSET; return offset; } -int _fdt_check_prop_offset(const void *fdt, int offset) +int fdt_check_prop_offset_(const void *fdt, int offset) { if ((offset < 0) || (offset % FDT_TAGSIZE) || (fdt_next_tag(fdt, offset, &offset) != FDT_PROP)) return -FDT_ERR_BADOFFSET; return offset; } int fdt_next_node(const void *fdt, int offset, int *depth) { int nextoffset = 0; uint32_t tag; if (offset >= 0) - if ((nextoffset = _fdt_check_node_offset(fdt, offset)) < 0) + if ((nextoffset = fdt_check_node_offset_(fdt, offset)) < 0) return nextoffset; do { offset = nextoffset; tag = fdt_next_tag(fdt, offset, &nextoffset); switch (tag) { case FDT_PROP: case FDT_NOP: break; case FDT_BEGIN_NODE: if (depth) (*depth)++; break; case FDT_END_NODE: if (depth && ((--(*depth)) < 0)) return nextoffset; break; case FDT_END: if ((nextoffset >= 0) || ((nextoffset == -FDT_ERR_TRUNCATED) && !depth)) return -FDT_ERR_NOTFOUND; else return nextoffset; } } while (tag != FDT_BEGIN_NODE); return offset; } int fdt_first_subnode(const void *fdt, int offset) { int depth = 0; offset = fdt_next_node(fdt, offset, &depth); if (offset < 0 || depth != 1) return -FDT_ERR_NOTFOUND; return offset; } int fdt_next_subnode(const void *fdt, int offset) { int depth = 1; /* * With respect to the parent, the depth of the next subnode will be * the same as the last. */ do { offset = fdt_next_node(fdt, offset, &depth); if (offset < 0 || depth < 1) return -FDT_ERR_NOTFOUND; } while (depth > 1); return offset; } -const char *_fdt_find_string(const char *strtab, int tabsize, const char *s) +const char *fdt_find_string_(const char *strtab, int tabsize, const char *s) { int len = strlen(s) + 1; const char *last = strtab + tabsize - len; const char *p; for (p = strtab; p <= last; p++) if (memcmp(p, s, len) == 0) return p; return NULL; } int fdt_move(const void *fdt, void *buf, int bufsize) { FDT_CHECK_HEADER(fdt); if (fdt_totalsize(fdt) > bufsize) return -FDT_ERR_NOSPACE; memmove(buf, fdt, fdt_totalsize(fdt)); return 0; } Index: vendor/dtc/dist/libfdt/fdt.h =================================================================== --- vendor/dtc/dist/libfdt/fdt.h (revision 327892) +++ vendor/dtc/dist/libfdt/fdt.h (revision 327893) @@ -1,111 +1,111 @@ -#ifndef _FDT_H -#define _FDT_H +#ifndef FDT_H +#define FDT_H /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. * Copyright 2012 Kim Phillips, Freescale Semiconductor. * * libfdt is dual licensed: you can use it either under the terms of * the GPL, or the BSD license, at your option. * * a) This library is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301 USA * * Alternatively, * * b) Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * 1. Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __ASSEMBLY__ struct fdt_header { fdt32_t magic; /* magic word FDT_MAGIC */ fdt32_t totalsize; /* total size of DT block */ fdt32_t off_dt_struct; /* offset to structure */ fdt32_t off_dt_strings; /* offset to strings */ fdt32_t off_mem_rsvmap; /* offset to memory reserve map */ fdt32_t version; /* format version */ fdt32_t last_comp_version; /* last compatible version */ /* version 2 fields below */ fdt32_t boot_cpuid_phys; /* Which physical CPU id we're booting on */ /* version 3 fields below */ fdt32_t size_dt_strings; /* size of the strings block */ /* version 17 fields below */ fdt32_t size_dt_struct; /* size of the structure block */ }; struct fdt_reserve_entry { fdt64_t address; fdt64_t size; }; struct fdt_node_header { fdt32_t tag; char name[0]; }; struct fdt_property { fdt32_t tag; fdt32_t len; fdt32_t nameoff; char data[0]; }; #endif /* !__ASSEMBLY */ #define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */ #define FDT_TAGSIZE sizeof(fdt32_t) #define FDT_BEGIN_NODE 0x1 /* Start node: full name */ #define FDT_END_NODE 0x2 /* End node */ #define FDT_PROP 0x3 /* Property: name off, size, content */ #define FDT_NOP 0x4 /* nop */ #define FDT_END 0x9 #define FDT_V1_SIZE (7*sizeof(fdt32_t)) #define FDT_V2_SIZE (FDT_V1_SIZE + sizeof(fdt32_t)) #define FDT_V3_SIZE (FDT_V2_SIZE + sizeof(fdt32_t)) #define FDT_V16_SIZE FDT_V3_SIZE #define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(fdt32_t)) -#endif /* _FDT_H */ +#endif /* FDT_H */ Index: vendor/dtc/dist/libfdt/fdt_empty_tree.c =================================================================== --- vendor/dtc/dist/libfdt/fdt_empty_tree.c (revision 327892) +++ vendor/dtc/dist/libfdt/fdt_empty_tree.c (revision 327893) @@ -1,84 +1,83 @@ /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2012 David Gibson, IBM Corporation. * * libfdt is dual licensed: you can use it either under the terms of * the GPL, or the BSD license, at your option. * * a) This library is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301 USA * * Alternatively, * * b) Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * 1. Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "libfdt_env.h" #include #include #include "libfdt_internal.h" int fdt_create_empty_tree(void *buf, int bufsize) { int err; err = fdt_create(buf, bufsize); if (err) return err; err = fdt_finish_reservemap(buf); if (err) return err; err = fdt_begin_node(buf, ""); if (err) return err; err = fdt_end_node(buf); if (err) return err; err = fdt_finish(buf); if (err) return err; return fdt_open_into(buf, buf, bufsize); } - Index: vendor/dtc/dist/libfdt/fdt_overlay.c =================================================================== --- vendor/dtc/dist/libfdt/fdt_overlay.c (revision 327892) +++ vendor/dtc/dist/libfdt/fdt_overlay.c (revision 327893) @@ -1,676 +1,861 @@ #include "libfdt_env.h" #include #include #include "libfdt_internal.h" /** * overlay_get_target_phandle - retrieves the target phandle of a fragment * @fdto: pointer to the device tree overlay blob * @fragment: node offset of the fragment in the overlay * * overlay_get_target_phandle() retrieves the target phandle of an * overlay fragment when that fragment uses a phandle (target * property) instead of a path (target-path property). * * returns: * the phandle pointed by the target property * 0, if the phandle was not found * -1, if the phandle was malformed */ static uint32_t overlay_get_target_phandle(const void *fdto, int fragment) { - const uint32_t *val; + const fdt32_t *val; int len; val = fdt_getprop(fdto, fragment, "target", &len); if (!val) return 0; - if ((len != sizeof(*val)) || (*val == (uint32_t)-1)) + if ((len != sizeof(*val)) || (fdt32_to_cpu(*val) == (uint32_t)-1)) return (uint32_t)-1; return fdt32_to_cpu(*val); } /** * overlay_get_target - retrieves the offset of a fragment's target * @fdt: Base device tree blob * @fdto: Device tree overlay blob * @fragment: node offset of the fragment in the overlay + * @pathp: pointer which receives the path of the target (or NULL) * * overlay_get_target() retrieves the target offset in the base * device tree of a fragment, no matter how the actual targetting is * done (through a phandle or a path) * * returns: * the targetted node offset in the base device tree * Negative error code on error */ static int overlay_get_target(const void *fdt, const void *fdto, - int fragment) + int fragment, char const **pathp) { uint32_t phandle; - const char *path; - int path_len; + const char *path = NULL; + int path_len = 0, ret; /* Try first to do a phandle based lookup */ phandle = overlay_get_target_phandle(fdto, fragment); if (phandle == (uint32_t)-1) return -FDT_ERR_BADPHANDLE; - if (phandle) - return fdt_node_offset_by_phandle(fdt, phandle); + /* no phandle, try path */ + if (!phandle) { + /* And then a path based lookup */ + path = fdt_getprop(fdto, fragment, "target-path", &path_len); + if (path) + ret = fdt_path_offset(fdt, path); + else + ret = path_len; + } else + ret = fdt_node_offset_by_phandle(fdt, phandle); - /* And then a path based lookup */ - path = fdt_getprop(fdto, fragment, "target-path", &path_len); - if (!path) { - /* - * If we haven't found either a target or a - * target-path property in a node that contains a - * __overlay__ subnode (we wouldn't be called - * otherwise), consider it a improperly written - * overlay - */ - if (path_len == -FDT_ERR_NOTFOUND) - return -FDT_ERR_BADOVERLAY; + /* + * If we haven't found either a target or a + * target-path property in a node that contains a + * __overlay__ subnode (we wouldn't be called + * otherwise), consider it a improperly written + * overlay + */ + if (ret < 0 && path_len == -FDT_ERR_NOTFOUND) + ret = -FDT_ERR_BADOVERLAY; - return path_len; - } + /* return on error */ + if (ret < 0) + return ret; - return fdt_path_offset(fdt, path); + /* return pointer to path (if available) */ + if (pathp) + *pathp = path ? path : NULL; + + return ret; } /** * overlay_phandle_add_offset - Increases a phandle by an offset * @fdt: Base device tree blob * @node: Device tree overlay blob * @name: Name of the property to modify (phandle or linux,phandle) * @delta: offset to apply * * overlay_phandle_add_offset() increments a node phandle by a given * offset. * * returns: * 0 on success. * Negative error code on error */ static int overlay_phandle_add_offset(void *fdt, int node, const char *name, uint32_t delta) { - const uint32_t *val; + const fdt32_t *val; uint32_t adj_val; int len; val = fdt_getprop(fdt, node, name, &len); if (!val) return len; if (len != sizeof(*val)) return -FDT_ERR_BADPHANDLE; adj_val = fdt32_to_cpu(*val); if ((adj_val + delta) < adj_val) return -FDT_ERR_NOPHANDLES; adj_val += delta; if (adj_val == (uint32_t)-1) return -FDT_ERR_NOPHANDLES; return fdt_setprop_inplace_u32(fdt, node, name, adj_val); } /** * overlay_adjust_node_phandles - Offsets the phandles of a node * @fdto: Device tree overlay blob * @node: Offset of the node we want to adjust * @delta: Offset to shift the phandles of * * overlay_adjust_node_phandles() adds a constant to all the phandles * of a given node. This is mainly use as part of the overlay * application process, when we want to update all the overlay * phandles to not conflict with the overlays of the base device tree. * * returns: * 0 on success * Negative error code on failure */ static int overlay_adjust_node_phandles(void *fdto, int node, uint32_t delta) { int child; int ret; ret = overlay_phandle_add_offset(fdto, node, "phandle", delta); if (ret && ret != -FDT_ERR_NOTFOUND) return ret; ret = overlay_phandle_add_offset(fdto, node, "linux,phandle", delta); if (ret && ret != -FDT_ERR_NOTFOUND) return ret; fdt_for_each_subnode(child, fdto, node) { ret = overlay_adjust_node_phandles(fdto, child, delta); if (ret) return ret; } return 0; } /** * overlay_adjust_local_phandles - Adjust the phandles of a whole overlay * @fdto: Device tree overlay blob * @delta: Offset to shift the phandles of * * overlay_adjust_local_phandles() adds a constant to all the * phandles of an overlay. This is mainly use as part of the overlay * application process, when we want to update all the overlay * phandles to not conflict with the overlays of the base device tree. * * returns: * 0 on success * Negative error code on failure */ static int overlay_adjust_local_phandles(void *fdto, uint32_t delta) { /* * Start adjusting the phandles from the overlay root */ return overlay_adjust_node_phandles(fdto, 0, delta); } /** * overlay_update_local_node_references - Adjust the overlay references * @fdto: Device tree overlay blob * @tree_node: Node offset of the node to operate on * @fixup_node: Node offset of the matching local fixups node * @delta: Offset to shift the phandles of * * overlay_update_local_nodes_references() update the phandles * pointing to a node within the device tree overlay by adding a * constant delta. * * This is mainly used as part of a device tree application process, * where you want the device tree overlays phandles to not conflict * with the ones from the base device tree before merging them. * * returns: * 0 on success * Negative error code on failure */ static int overlay_update_local_node_references(void *fdto, int tree_node, int fixup_node, uint32_t delta) { int fixup_prop; int fixup_child; int ret; fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) { - const uint32_t *fixup_val; + const fdt32_t *fixup_val; const char *tree_val; const char *name; int fixup_len; int tree_len; int i; fixup_val = fdt_getprop_by_offset(fdto, fixup_prop, &name, &fixup_len); if (!fixup_val) return fixup_len; if (fixup_len % sizeof(uint32_t)) return -FDT_ERR_BADOVERLAY; tree_val = fdt_getprop(fdto, tree_node, name, &tree_len); if (!tree_val) { if (tree_len == -FDT_ERR_NOTFOUND) return -FDT_ERR_BADOVERLAY; return tree_len; } for (i = 0; i < (fixup_len / sizeof(uint32_t)); i++) { - uint32_t adj_val, poffset; + fdt32_t adj_val; + uint32_t poffset; poffset = fdt32_to_cpu(fixup_val[i]); /* * phandles to fixup can be unaligned. * * Use a memcpy for the architectures that do * not support unaligned accesses. */ memcpy(&adj_val, tree_val + poffset, sizeof(adj_val)); - adj_val = fdt32_to_cpu(adj_val); - adj_val += delta; - adj_val = cpu_to_fdt32(adj_val); + adj_val = cpu_to_fdt32(fdt32_to_cpu(adj_val) + delta); ret = fdt_setprop_inplace_namelen_partial(fdto, tree_node, name, strlen(name), poffset, &adj_val, sizeof(adj_val)); if (ret == -FDT_ERR_NOSPACE) return -FDT_ERR_BADOVERLAY; if (ret) return ret; } } fdt_for_each_subnode(fixup_child, fdto, fixup_node) { const char *fixup_child_name = fdt_get_name(fdto, fixup_child, NULL); int tree_child; tree_child = fdt_subnode_offset(fdto, tree_node, fixup_child_name); - if (ret == -FDT_ERR_NOTFOUND) + if (tree_child == -FDT_ERR_NOTFOUND) return -FDT_ERR_BADOVERLAY; if (tree_child < 0) return tree_child; ret = overlay_update_local_node_references(fdto, tree_child, fixup_child, delta); if (ret) return ret; } return 0; } /** * overlay_update_local_references - Adjust the overlay references * @fdto: Device tree overlay blob * @delta: Offset to shift the phandles of * * overlay_update_local_references() update all the phandles pointing * to a node within the device tree overlay by adding a constant * delta to not conflict with the base overlay. * * This is mainly used as part of a device tree application process, * where you want the device tree overlays phandles to not conflict * with the ones from the base device tree before merging them. * * returns: * 0 on success * Negative error code on failure */ static int overlay_update_local_references(void *fdto, uint32_t delta) { int fixups; fixups = fdt_path_offset(fdto, "/__local_fixups__"); if (fixups < 0) { /* There's no local phandles to adjust, bail out */ if (fixups == -FDT_ERR_NOTFOUND) return 0; return fixups; } /* * Update our local references from the root of the tree */ return overlay_update_local_node_references(fdto, 0, fixups, delta); } /** * overlay_fixup_one_phandle - Set an overlay phandle to the base one * @fdt: Base Device Tree blob * @fdto: Device tree overlay blob * @symbols_off: Node offset of the symbols node in the base device tree * @path: Path to a node holding a phandle in the overlay * @path_len: number of path characters to consider * @name: Name of the property holding the phandle reference in the overlay * @name_len: number of name characters to consider * @poffset: Offset within the overlay property where the phandle is stored * @label: Label of the node referenced by the phandle * * overlay_fixup_one_phandle() resolves an overlay phandle pointing to * a node in the base device tree. * * This is part of the device tree overlay application process, when * you want all the phandles in the overlay to point to the actual * base dt nodes. * * returns: * 0 on success * Negative error code on failure */ static int overlay_fixup_one_phandle(void *fdt, void *fdto, int symbols_off, const char *path, uint32_t path_len, const char *name, uint32_t name_len, int poffset, const char *label) { const char *symbol_path; uint32_t phandle; + fdt32_t phandle_prop; int symbol_off, fixup_off; int prop_len; if (symbols_off < 0) return symbols_off; symbol_path = fdt_getprop(fdt, symbols_off, label, &prop_len); if (!symbol_path) return prop_len; symbol_off = fdt_path_offset(fdt, symbol_path); if (symbol_off < 0) return symbol_off; phandle = fdt_get_phandle(fdt, symbol_off); if (!phandle) return -FDT_ERR_NOTFOUND; fixup_off = fdt_path_offset_namelen(fdto, path, path_len); if (fixup_off == -FDT_ERR_NOTFOUND) return -FDT_ERR_BADOVERLAY; if (fixup_off < 0) return fixup_off; - phandle = cpu_to_fdt32(phandle); + phandle_prop = cpu_to_fdt32(phandle); return fdt_setprop_inplace_namelen_partial(fdto, fixup_off, name, name_len, poffset, - &phandle, sizeof(phandle)); + &phandle_prop, + sizeof(phandle_prop)); }; /** * overlay_fixup_phandle - Set an overlay phandle to the base one * @fdt: Base Device Tree blob * @fdto: Device tree overlay blob * @symbols_off: Node offset of the symbols node in the base device tree * @property: Property offset in the overlay holding the list of fixups * * overlay_fixup_phandle() resolves all the overlay phandles pointed * to in a __fixups__ property, and updates them to match the phandles * in use in the base device tree. * * This is part of the device tree overlay application process, when * you want all the phandles in the overlay to point to the actual * base dt nodes. * * returns: * 0 on success * Negative error code on failure */ static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off, int property) { const char *value; const char *label; int len; value = fdt_getprop_by_offset(fdto, property, &label, &len); if (!value) { if (len == -FDT_ERR_NOTFOUND) return -FDT_ERR_INTERNAL; return len; } do { const char *path, *name, *fixup_end; const char *fixup_str = value; uint32_t path_len, name_len; uint32_t fixup_len; char *sep, *endptr; int poffset, ret; fixup_end = memchr(value, '\0', len); if (!fixup_end) return -FDT_ERR_BADOVERLAY; fixup_len = fixup_end - fixup_str; len -= fixup_len + 1; value += fixup_len + 1; path = fixup_str; sep = memchr(fixup_str, ':', fixup_len); if (!sep || *sep != ':') return -FDT_ERR_BADOVERLAY; path_len = sep - path; if (path_len == (fixup_len - 1)) return -FDT_ERR_BADOVERLAY; fixup_len -= path_len + 1; name = sep + 1; sep = memchr(name, ':', fixup_len); if (!sep || *sep != ':') return -FDT_ERR_BADOVERLAY; name_len = sep - name; if (!name_len) return -FDT_ERR_BADOVERLAY; poffset = strtoul(sep + 1, &endptr, 10); if ((*endptr != '\0') || (endptr <= (sep + 1))) return -FDT_ERR_BADOVERLAY; ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off, path, path_len, name, name_len, poffset, label); if (ret) return ret; } while (len > 0); return 0; } /** * overlay_fixup_phandles - Resolve the overlay phandles to the base * device tree * @fdt: Base Device Tree blob * @fdto: Device tree overlay blob * * overlay_fixup_phandles() resolves all the overlay phandles pointing * to nodes in the base device tree. * * This is one of the steps of the device tree overlay application * process, when you want all the phandles in the overlay to point to * the actual base dt nodes. * * returns: * 0 on success * Negative error code on failure */ static int overlay_fixup_phandles(void *fdt, void *fdto) { int fixups_off, symbols_off; int property; /* We can have overlays without any fixups */ fixups_off = fdt_path_offset(fdto, "/__fixups__"); if (fixups_off == -FDT_ERR_NOTFOUND) return 0; /* nothing to do */ if (fixups_off < 0) return fixups_off; /* And base DTs without symbols */ symbols_off = fdt_path_offset(fdt, "/__symbols__"); if ((symbols_off < 0 && (symbols_off != -FDT_ERR_NOTFOUND))) return symbols_off; fdt_for_each_property_offset(property, fdto, fixups_off) { int ret; ret = overlay_fixup_phandle(fdt, fdto, symbols_off, property); if (ret) return ret; } return 0; } /** * overlay_apply_node - Merges a node into the base device tree * @fdt: Base Device Tree blob * @target: Node offset in the base device tree to apply the fragment to * @fdto: Device tree overlay blob * @node: Node offset in the overlay holding the changes to merge * * overlay_apply_node() merges a node into a target base device tree * node pointed. * * This is part of the final step in the device tree overlay * application process, when all the phandles have been adjusted and * resolved and you just have to merge overlay into the base device * tree. * * returns: * 0 on success * Negative error code on failure */ static int overlay_apply_node(void *fdt, int target, void *fdto, int node) { int property; int subnode; fdt_for_each_property_offset(property, fdto, node) { const char *name; const void *prop; int prop_len; int ret; prop = fdt_getprop_by_offset(fdto, property, &name, &prop_len); if (prop_len == -FDT_ERR_NOTFOUND) return -FDT_ERR_INTERNAL; if (prop_len < 0) return prop_len; ret = fdt_setprop(fdt, target, name, prop, prop_len); if (ret) return ret; } fdt_for_each_subnode(subnode, fdto, node) { const char *name = fdt_get_name(fdto, subnode, NULL); int nnode; int ret; nnode = fdt_add_subnode(fdt, target, name); if (nnode == -FDT_ERR_EXISTS) { nnode = fdt_subnode_offset(fdt, target, name); if (nnode == -FDT_ERR_NOTFOUND) return -FDT_ERR_INTERNAL; } if (nnode < 0) return nnode; ret = overlay_apply_node(fdt, nnode, fdto, subnode); if (ret) return ret; } return 0; } /** * overlay_merge - Merge an overlay into its base device tree * @fdt: Base Device Tree blob * @fdto: Device tree overlay blob * * overlay_merge() merges an overlay into its base device tree. * - * This is the final step in the device tree overlay application + * This is the next to last step in the device tree overlay application * process, when all the phandles have been adjusted and resolved and * you just have to merge overlay into the base device tree. * * returns: * 0 on success * Negative error code on failure */ static int overlay_merge(void *fdt, void *fdto) { int fragment; fdt_for_each_subnode(fragment, fdto, 0) { int overlay; int target; int ret; /* * Each fragments will have an __overlay__ node. If * they don't, it's not supposed to be merged */ overlay = fdt_subnode_offset(fdto, fragment, "__overlay__"); if (overlay == -FDT_ERR_NOTFOUND) continue; if (overlay < 0) return overlay; - target = overlay_get_target(fdt, fdto, fragment); + target = overlay_get_target(fdt, fdto, fragment, NULL); if (target < 0) return target; ret = overlay_apply_node(fdt, target, fdto, overlay); if (ret) return ret; } return 0; } +static int get_path_len(const void *fdt, int nodeoffset) +{ + int len = 0, namelen; + const char *name; + + FDT_CHECK_HEADER(fdt); + + for (;;) { + name = fdt_get_name(fdt, nodeoffset, &namelen); + if (!name) + return namelen; + + /* root? we're done */ + if (namelen == 0) + break; + + nodeoffset = fdt_parent_offset(fdt, nodeoffset); + if (nodeoffset < 0) + return nodeoffset; + len += namelen + 1; + } + + /* in case of root pretend it's "/" */ + if (len == 0) + len++; + return len; +} + +/** + * overlay_symbol_update - Update the symbols of base tree after a merge + * @fdt: Base Device Tree blob + * @fdto: Device tree overlay blob + * + * overlay_symbol_update() updates the symbols of the base tree with the + * symbols of the applied overlay + * + * This is the last step in the device tree overlay application + * process, allowing the reference of overlay symbols by subsequent + * overlay operations. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_symbol_update(void *fdt, void *fdto) +{ + int root_sym, ov_sym, prop, path_len, fragment, target; + int len, frag_name_len, ret, rel_path_len; + const char *s, *e; + const char *path; + const char *name; + const char *frag_name; + const char *rel_path; + const char *target_path; + char *buf; + void *p; + + ov_sym = fdt_subnode_offset(fdto, 0, "__symbols__"); + + /* if no overlay symbols exist no problem */ + if (ov_sym < 0) + return 0; + + root_sym = fdt_subnode_offset(fdt, 0, "__symbols__"); + + /* it no root symbols exist we should create them */ + if (root_sym == -FDT_ERR_NOTFOUND) + root_sym = fdt_add_subnode(fdt, 0, "__symbols__"); + + /* any error is fatal now */ + if (root_sym < 0) + return root_sym; + + /* iterate over each overlay symbol */ + fdt_for_each_property_offset(prop, fdto, ov_sym) { + path = fdt_getprop_by_offset(fdto, prop, &name, &path_len); + if (!path) + return path_len; + + /* verify it's a string property (terminated by a single \0) */ + if (path_len < 1 || memchr(path, '\0', path_len) != &path[path_len - 1]) + return -FDT_ERR_BADVALUE; + + /* keep end marker to avoid strlen() */ + e = path + path_len; + + /* format: //__overlay__/ */ + + if (*path != '/') + return -FDT_ERR_BADVALUE; + + /* get fragment name first */ + s = strchr(path + 1, '/'); + if (!s) + return -FDT_ERR_BADOVERLAY; + + frag_name = path + 1; + frag_name_len = s - path - 1; + + /* verify format; safe since "s" lies in \0 terminated prop */ + len = sizeof("/__overlay__/") - 1; + if ((e - s) < len || memcmp(s, "/__overlay__/", len)) + return -FDT_ERR_BADOVERLAY; + + rel_path = s + len; + rel_path_len = e - rel_path; + + /* find the fragment index in which the symbol lies */ + ret = fdt_subnode_offset_namelen(fdto, 0, frag_name, + frag_name_len); + /* not found? */ + if (ret < 0) + return -FDT_ERR_BADOVERLAY; + fragment = ret; + + /* an __overlay__ subnode must exist */ + ret = fdt_subnode_offset(fdto, fragment, "__overlay__"); + if (ret < 0) + return -FDT_ERR_BADOVERLAY; + + /* get the target of the fragment */ + ret = overlay_get_target(fdt, fdto, fragment, &target_path); + if (ret < 0) + return ret; + target = ret; + + /* if we have a target path use */ + if (!target_path) { + ret = get_path_len(fdt, target); + if (ret < 0) + return ret; + len = ret; + } else { + len = strlen(target_path); + } + + ret = fdt_setprop_placeholder(fdt, root_sym, name, + len + (len > 1) + rel_path_len + 1, &p); + if (ret < 0) + return ret; + + if (!target_path) { + /* again in case setprop_placeholder changed it */ + ret = overlay_get_target(fdt, fdto, fragment, &target_path); + if (ret < 0) + return ret; + target = ret; + } + + buf = p; + if (len > 1) { /* target is not root */ + if (!target_path) { + ret = fdt_get_path(fdt, target, buf, len + 1); + if (ret < 0) + return ret; + } else + memcpy(buf, target_path, len + 1); + + } else + len--; + + buf[len] = '/'; + memcpy(buf + len + 1, rel_path, rel_path_len); + buf[len + 1 + rel_path_len] = '\0'; + } + + return 0; +} + int fdt_overlay_apply(void *fdt, void *fdto) { uint32_t delta = fdt_get_max_phandle(fdt); int ret; FDT_CHECK_HEADER(fdt); FDT_CHECK_HEADER(fdto); ret = overlay_adjust_local_phandles(fdto, delta); if (ret) goto err; ret = overlay_update_local_references(fdto, delta); if (ret) goto err; ret = overlay_fixup_phandles(fdt, fdto); if (ret) goto err; ret = overlay_merge(fdt, fdto); + if (ret) + goto err; + + ret = overlay_symbol_update(fdt, fdto); if (ret) goto err; /* * The overlay has been damaged, erase its magic. */ fdt_set_magic(fdto, ~0); return 0; err: /* * The overlay might have been damaged, erase its magic. */ fdt_set_magic(fdto, ~0); /* * The base device tree might have been damaged, erase its * magic. */ fdt_set_magic(fdt, ~0); return ret; } Index: vendor/dtc/dist/libfdt/fdt_ro.c =================================================================== --- vendor/dtc/dist/libfdt/fdt_ro.c (revision 327892) +++ vendor/dtc/dist/libfdt/fdt_ro.c (revision 327893) @@ -1,703 +1,703 @@ /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. * * libfdt is dual licensed: you can use it either under the terms of * the GPL, or the BSD license, at your option. * * a) This library is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301 USA * * Alternatively, * * b) Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * 1. Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "libfdt_env.h" #include #include #include "libfdt_internal.h" -static int _fdt_nodename_eq(const void *fdt, int offset, +static int fdt_nodename_eq_(const void *fdt, int offset, const char *s, int len) { const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1); - if (! p) + if (!p) /* short match */ return 0; if (memcmp(p, s, len) != 0) return 0; if (p[len] == '\0') return 1; else if (!memchr(s, '@', len) && (p[len] == '@')) return 1; else return 0; } const char *fdt_string(const void *fdt, int stroffset) { return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset; } -static int _fdt_string_eq(const void *fdt, int stroffset, +static int fdt_string_eq_(const void *fdt, int stroffset, const char *s, int len) { const char *p = fdt_string(fdt, stroffset); return (strlen(p) == len) && (memcmp(p, s, len) == 0); } uint32_t fdt_get_max_phandle(const void *fdt) { uint32_t max_phandle = 0; int offset; for (offset = fdt_next_node(fdt, -1, NULL);; offset = fdt_next_node(fdt, offset, NULL)) { uint32_t phandle; if (offset == -FDT_ERR_NOTFOUND) return max_phandle; if (offset < 0) return (uint32_t)-1; phandle = fdt_get_phandle(fdt, offset); if (phandle == (uint32_t)-1) continue; if (phandle > max_phandle) max_phandle = phandle; } return 0; } int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) { FDT_CHECK_HEADER(fdt); - *address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address); - *size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size); + *address = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->address); + *size = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->size); return 0; } int fdt_num_mem_rsv(const void *fdt) { int i = 0; - while (fdt64_to_cpu(_fdt_mem_rsv(fdt, i)->size) != 0) + while (fdt64_to_cpu(fdt_mem_rsv_(fdt, i)->size) != 0) i++; return i; } -static int _nextprop(const void *fdt, int offset) +static int nextprop_(const void *fdt, int offset) { uint32_t tag; int nextoffset; do { tag = fdt_next_tag(fdt, offset, &nextoffset); switch (tag) { case FDT_END: if (nextoffset >= 0) return -FDT_ERR_BADSTRUCTURE; else return nextoffset; case FDT_PROP: return offset; } offset = nextoffset; } while (tag == FDT_NOP); return -FDT_ERR_NOTFOUND; } int fdt_subnode_offset_namelen(const void *fdt, int offset, const char *name, int namelen) { int depth; FDT_CHECK_HEADER(fdt); for (depth = 0; (offset >= 0) && (depth >= 0); offset = fdt_next_node(fdt, offset, &depth)) if ((depth == 1) - && _fdt_nodename_eq(fdt, offset, name, namelen)) + && fdt_nodename_eq_(fdt, offset, name, namelen)) return offset; if (depth < 0) return -FDT_ERR_NOTFOUND; return offset; /* error */ } int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name) { return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name)); } int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen) { const char *end = path + namelen; const char *p = path; int offset = 0; FDT_CHECK_HEADER(fdt); /* see if we have an alias */ if (*path != '/') { const char *q = memchr(path, '/', end - p); if (!q) q = end; p = fdt_get_alias_namelen(fdt, p, q - p); if (!p) return -FDT_ERR_BADPATH; offset = fdt_path_offset(fdt, p); p = q; } while (p < end) { const char *q; while (*p == '/') { p++; if (p == end) return offset; } q = memchr(p, '/', end - p); if (! q) q = end; offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p); if (offset < 0) return offset; p = q; } return offset; } int fdt_path_offset(const void *fdt, const char *path) { return fdt_path_offset_namelen(fdt, path, strlen(path)); } const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) { - const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset); + const struct fdt_node_header *nh = fdt_offset_ptr_(fdt, nodeoffset); int err; if (((err = fdt_check_header(fdt)) != 0) - || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0)) + || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0)) goto fail; if (len) *len = strlen(nh->name); return nh->name; fail: if (len) *len = err; return NULL; } int fdt_first_property_offset(const void *fdt, int nodeoffset) { int offset; - if ((offset = _fdt_check_node_offset(fdt, nodeoffset)) < 0) + if ((offset = fdt_check_node_offset_(fdt, nodeoffset)) < 0) return offset; - return _nextprop(fdt, offset); + return nextprop_(fdt, offset); } int fdt_next_property_offset(const void *fdt, int offset) { - if ((offset = _fdt_check_prop_offset(fdt, offset)) < 0) + if ((offset = fdt_check_prop_offset_(fdt, offset)) < 0) return offset; - return _nextprop(fdt, offset); + return nextprop_(fdt, offset); } const struct fdt_property *fdt_get_property_by_offset(const void *fdt, int offset, int *lenp) { int err; const struct fdt_property *prop; - if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) { + if ((err = fdt_check_prop_offset_(fdt, offset)) < 0) { if (lenp) *lenp = err; return NULL; } - prop = _fdt_offset_ptr(fdt, offset); + prop = fdt_offset_ptr_(fdt, offset); if (lenp) *lenp = fdt32_to_cpu(prop->len); return prop; } const struct fdt_property *fdt_get_property_namelen(const void *fdt, int offset, const char *name, int namelen, int *lenp) { for (offset = fdt_first_property_offset(fdt, offset); (offset >= 0); (offset = fdt_next_property_offset(fdt, offset))) { const struct fdt_property *prop; if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) { offset = -FDT_ERR_INTERNAL; break; } - if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff), + if (fdt_string_eq_(fdt, fdt32_to_cpu(prop->nameoff), name, namelen)) return prop; } if (lenp) *lenp = offset; return NULL; } const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset, const char *name, int *lenp) { return fdt_get_property_namelen(fdt, nodeoffset, name, strlen(name), lenp); } const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, const char *name, int namelen, int *lenp) { const struct fdt_property *prop; prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp); - if (! prop) + if (!prop) return NULL; return prop->data; } const void *fdt_getprop_by_offset(const void *fdt, int offset, const char **namep, int *lenp) { const struct fdt_property *prop; prop = fdt_get_property_by_offset(fdt, offset, lenp); if (!prop) return NULL; if (namep) *namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff)); return prop->data; } const void *fdt_getprop(const void *fdt, int nodeoffset, const char *name, int *lenp) { return fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), lenp); } uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) { const fdt32_t *php; int len; /* FIXME: This is a bit sub-optimal, since we potentially scan * over all the properties twice. */ php = fdt_getprop(fdt, nodeoffset, "phandle", &len); if (!php || (len != sizeof(*php))) { php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len); if (!php || (len != sizeof(*php))) return 0; } return fdt32_to_cpu(*php); } const char *fdt_get_alias_namelen(const void *fdt, const char *name, int namelen) { int aliasoffset; aliasoffset = fdt_path_offset(fdt, "/aliases"); if (aliasoffset < 0) return NULL; return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL); } const char *fdt_get_alias(const void *fdt, const char *name) { return fdt_get_alias_namelen(fdt, name, strlen(name)); } int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) { int pdepth = 0, p = 0; int offset, depth, namelen; const char *name; FDT_CHECK_HEADER(fdt); if (buflen < 2) return -FDT_ERR_NOSPACE; for (offset = 0, depth = 0; (offset >= 0) && (offset <= nodeoffset); offset = fdt_next_node(fdt, offset, &depth)) { while (pdepth > depth) { do { p--; } while (buf[p-1] != '/'); pdepth--; } if (pdepth >= depth) { name = fdt_get_name(fdt, offset, &namelen); if (!name) return namelen; if ((p + namelen + 1) <= buflen) { memcpy(buf + p, name, namelen); p += namelen; buf[p++] = '/'; pdepth++; } } if (offset == nodeoffset) { if (pdepth < (depth + 1)) return -FDT_ERR_NOSPACE; if (p > 1) /* special case so that root path is "/", not "" */ p--; buf[p] = '\0'; return 0; } } if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) return -FDT_ERR_BADOFFSET; else if (offset == -FDT_ERR_BADOFFSET) return -FDT_ERR_BADSTRUCTURE; return offset; /* error from fdt_next_node() */ } int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, int supernodedepth, int *nodedepth) { int offset, depth; int supernodeoffset = -FDT_ERR_INTERNAL; FDT_CHECK_HEADER(fdt); if (supernodedepth < 0) return -FDT_ERR_NOTFOUND; for (offset = 0, depth = 0; (offset >= 0) && (offset <= nodeoffset); offset = fdt_next_node(fdt, offset, &depth)) { if (depth == supernodedepth) supernodeoffset = offset; if (offset == nodeoffset) { if (nodedepth) *nodedepth = depth; if (supernodedepth > depth) return -FDT_ERR_NOTFOUND; else return supernodeoffset; } } if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) return -FDT_ERR_BADOFFSET; else if (offset == -FDT_ERR_BADOFFSET) return -FDT_ERR_BADSTRUCTURE; return offset; /* error from fdt_next_node() */ } int fdt_node_depth(const void *fdt, int nodeoffset) { int nodedepth; int err; err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth); if (err) return (err < 0) ? err : -FDT_ERR_INTERNAL; return nodedepth; } int fdt_parent_offset(const void *fdt, int nodeoffset) { int nodedepth = fdt_node_depth(fdt, nodeoffset); if (nodedepth < 0) return nodedepth; return fdt_supernode_atdepth_offset(fdt, nodeoffset, nodedepth - 1, NULL); } int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, const char *propname, const void *propval, int proplen) { int offset; const void *val; int len; FDT_CHECK_HEADER(fdt); /* FIXME: The algorithm here is pretty horrible: we scan each * property of a node in fdt_getprop(), then if that didn't * find what we want, we scan over them again making our way * to the next node. Still it's the easiest to implement * approach; performance can come later. */ for (offset = fdt_next_node(fdt, startoffset, NULL); offset >= 0; offset = fdt_next_node(fdt, offset, NULL)) { val = fdt_getprop(fdt, offset, propname, &len); if (val && (len == proplen) && (memcmp(val, propval, len) == 0)) return offset; } return offset; /* error from fdt_next_node() */ } int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) { int offset; if ((phandle == 0) || (phandle == -1)) return -FDT_ERR_BADPHANDLE; FDT_CHECK_HEADER(fdt); /* FIXME: The algorithm here is pretty horrible: we * potentially scan each property of a node in * fdt_get_phandle(), then if that didn't find what * we want, we scan over them again making our way to the next * node. Still it's the easiest to implement approach; * performance can come later. */ for (offset = fdt_next_node(fdt, -1, NULL); offset >= 0; offset = fdt_next_node(fdt, offset, NULL)) { if (fdt_get_phandle(fdt, offset) == phandle) return offset; } return offset; /* error from fdt_next_node() */ } int fdt_stringlist_contains(const char *strlist, int listlen, const char *str) { int len = strlen(str); const char *p; while (listlen >= len) { if (memcmp(str, strlist, len+1) == 0) return 1; p = memchr(strlist, '\0', listlen); if (!p) return 0; /* malformed strlist.. */ listlen -= (p-strlist) + 1; strlist = p + 1; } return 0; } int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property) { const char *list, *end; int length, count = 0; list = fdt_getprop(fdt, nodeoffset, property, &length); if (!list) return length; end = list + length; while (list < end) { length = strnlen(list, end - list) + 1; /* Abort if the last string isn't properly NUL-terminated. */ if (list + length > end) return -FDT_ERR_BADVALUE; list += length; count++; } return count; } int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property, const char *string) { int length, len, idx = 0; const char *list, *end; list = fdt_getprop(fdt, nodeoffset, property, &length); if (!list) return length; len = strlen(string) + 1; end = list + length; while (list < end) { length = strnlen(list, end - list) + 1; /* Abort if the last string isn't properly NUL-terminated. */ if (list + length > end) return -FDT_ERR_BADVALUE; if (length == len && memcmp(list, string, length) == 0) return idx; list += length; idx++; } return -FDT_ERR_NOTFOUND; } const char *fdt_stringlist_get(const void *fdt, int nodeoffset, const char *property, int idx, int *lenp) { const char *list, *end; int length; list = fdt_getprop(fdt, nodeoffset, property, &length); if (!list) { if (lenp) *lenp = length; return NULL; } end = list + length; while (list < end) { length = strnlen(list, end - list) + 1; /* Abort if the last string isn't properly NUL-terminated. */ if (list + length > end) { if (lenp) *lenp = -FDT_ERR_BADVALUE; return NULL; } if (idx == 0) { if (lenp) *lenp = length - 1; return list; } list += length; idx--; } if (lenp) *lenp = -FDT_ERR_NOTFOUND; return NULL; } int fdt_node_check_compatible(const void *fdt, int nodeoffset, const char *compatible) { const void *prop; int len; prop = fdt_getprop(fdt, nodeoffset, "compatible", &len); if (!prop) return len; return !fdt_stringlist_contains(prop, len, compatible); } int fdt_node_offset_by_compatible(const void *fdt, int startoffset, const char *compatible) { int offset, err; FDT_CHECK_HEADER(fdt); /* FIXME: The algorithm here is pretty horrible: we scan each * property of a node in fdt_node_check_compatible(), then if * that didn't find what we want, we scan over them again * making our way to the next node. Still it's the easiest to * implement approach; performance can come later. */ for (offset = fdt_next_node(fdt, startoffset, NULL); offset >= 0; offset = fdt_next_node(fdt, offset, NULL)) { err = fdt_node_check_compatible(fdt, offset, compatible); if ((err < 0) && (err != -FDT_ERR_NOTFOUND)) return err; else if (err == 0) return offset; } return offset; /* error from fdt_next_node() */ } Index: vendor/dtc/dist/libfdt/fdt_rw.c =================================================================== --- vendor/dtc/dist/libfdt/fdt_rw.c (revision 327892) +++ vendor/dtc/dist/libfdt/fdt_rw.c (revision 327893) @@ -1,491 +1,505 @@ /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. * * libfdt is dual licensed: you can use it either under the terms of * the GPL, or the BSD license, at your option. * * a) This library is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301 USA * * Alternatively, * * b) Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * 1. Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "libfdt_env.h" #include #include #include "libfdt_internal.h" -static int _fdt_blocks_misordered(const void *fdt, - int mem_rsv_size, int struct_size) +static int fdt_blocks_misordered_(const void *fdt, + int mem_rsv_size, int struct_size) { return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8)) || (fdt_off_dt_struct(fdt) < (fdt_off_mem_rsvmap(fdt) + mem_rsv_size)) || (fdt_off_dt_strings(fdt) < (fdt_off_dt_struct(fdt) + struct_size)) || (fdt_totalsize(fdt) < (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt))); } -static int _fdt_rw_check_header(void *fdt) +static int fdt_rw_check_header_(void *fdt) { FDT_CHECK_HEADER(fdt); if (fdt_version(fdt) < 17) return -FDT_ERR_BADVERSION; - if (_fdt_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry), + if (fdt_blocks_misordered_(fdt, sizeof(struct fdt_reserve_entry), fdt_size_dt_struct(fdt))) return -FDT_ERR_BADLAYOUT; if (fdt_version(fdt) > 17) fdt_set_version(fdt, 17); return 0; } #define FDT_RW_CHECK_HEADER(fdt) \ { \ - int __err; \ - if ((__err = _fdt_rw_check_header(fdt)) != 0) \ - return __err; \ + int err_; \ + if ((err_ = fdt_rw_check_header_(fdt)) != 0) \ + return err_; \ } -static inline int _fdt_data_size(void *fdt) +static inline int fdt_data_size_(void *fdt) { return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); } -static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen) +static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen) { char *p = splicepoint; - char *end = (char *)fdt + _fdt_data_size(fdt); + char *end = (char *)fdt + fdt_data_size_(fdt); if (((p + oldlen) < p) || ((p + oldlen) > end)) return -FDT_ERR_BADOFFSET; if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt)) return -FDT_ERR_BADOFFSET; if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt))) return -FDT_ERR_NOSPACE; memmove(p + newlen, p + oldlen, end - p - oldlen); return 0; } -static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p, +static int fdt_splice_mem_rsv_(void *fdt, struct fdt_reserve_entry *p, int oldn, int newn) { int delta = (newn - oldn) * sizeof(*p); int err; - err = _fdt_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p)); + err = fdt_splice_(fdt, p, oldn * sizeof(*p), newn * sizeof(*p)); if (err) return err; fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta); fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta); return 0; } -static int _fdt_splice_struct(void *fdt, void *p, +static int fdt_splice_struct_(void *fdt, void *p, int oldlen, int newlen) { int delta = newlen - oldlen; int err; - if ((err = _fdt_splice(fdt, p, oldlen, newlen))) + if ((err = fdt_splice_(fdt, p, oldlen, newlen))) return err; fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta); fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta); return 0; } -static int _fdt_splice_string(void *fdt, int newlen) +static int fdt_splice_string_(void *fdt, int newlen) { void *p = (char *)fdt + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); int err; - if ((err = _fdt_splice(fdt, p, 0, newlen))) + if ((err = fdt_splice_(fdt, p, 0, newlen))) return err; fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen); return 0; } -static int _fdt_find_add_string(void *fdt, const char *s) +static int fdt_find_add_string_(void *fdt, const char *s) { char *strtab = (char *)fdt + fdt_off_dt_strings(fdt); const char *p; char *new; int len = strlen(s) + 1; int err; - p = _fdt_find_string(strtab, fdt_size_dt_strings(fdt), s); + p = fdt_find_string_(strtab, fdt_size_dt_strings(fdt), s); if (p) /* found it */ return (p - strtab); new = strtab + fdt_size_dt_strings(fdt); - err = _fdt_splice_string(fdt, len); + err = fdt_splice_string_(fdt, len); if (err) return err; memcpy(new, s, len); return (new - strtab); } int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size) { struct fdt_reserve_entry *re; int err; FDT_RW_CHECK_HEADER(fdt); - re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt)); - err = _fdt_splice_mem_rsv(fdt, re, 0, 1); + re = fdt_mem_rsv_w_(fdt, fdt_num_mem_rsv(fdt)); + err = fdt_splice_mem_rsv_(fdt, re, 0, 1); if (err) return err; re->address = cpu_to_fdt64(address); re->size = cpu_to_fdt64(size); return 0; } int fdt_del_mem_rsv(void *fdt, int n) { - struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n); + struct fdt_reserve_entry *re = fdt_mem_rsv_w_(fdt, n); FDT_RW_CHECK_HEADER(fdt); if (n >= fdt_num_mem_rsv(fdt)) return -FDT_ERR_NOTFOUND; - return _fdt_splice_mem_rsv(fdt, re, 1, 0); + return fdt_splice_mem_rsv_(fdt, re, 1, 0); } -static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name, +static int fdt_resize_property_(void *fdt, int nodeoffset, const char *name, int len, struct fdt_property **prop) { int oldlen; int err; *prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); - if (! (*prop)) + if (!*prop) return oldlen; - if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen), + if ((err = fdt_splice_struct_(fdt, (*prop)->data, FDT_TAGALIGN(oldlen), FDT_TAGALIGN(len)))) return err; (*prop)->len = cpu_to_fdt32(len); return 0; } -static int _fdt_add_property(void *fdt, int nodeoffset, const char *name, +static int fdt_add_property_(void *fdt, int nodeoffset, const char *name, int len, struct fdt_property **prop) { int proplen; int nextoffset; int namestroff; int err; - if ((nextoffset = _fdt_check_node_offset(fdt, nodeoffset)) < 0) + if ((nextoffset = fdt_check_node_offset_(fdt, nodeoffset)) < 0) return nextoffset; - namestroff = _fdt_find_add_string(fdt, name); + namestroff = fdt_find_add_string_(fdt, name); if (namestroff < 0) return namestroff; - *prop = _fdt_offset_ptr_w(fdt, nextoffset); + *prop = fdt_offset_ptr_w_(fdt, nextoffset); proplen = sizeof(**prop) + FDT_TAGALIGN(len); - err = _fdt_splice_struct(fdt, *prop, 0, proplen); + err = fdt_splice_struct_(fdt, *prop, 0, proplen); if (err) return err; (*prop)->tag = cpu_to_fdt32(FDT_PROP); (*prop)->nameoff = cpu_to_fdt32(namestroff); (*prop)->len = cpu_to_fdt32(len); return 0; } int fdt_set_name(void *fdt, int nodeoffset, const char *name) { char *namep; int oldlen, newlen; int err; FDT_RW_CHECK_HEADER(fdt); namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen); if (!namep) return oldlen; newlen = strlen(name); - err = _fdt_splice_struct(fdt, namep, FDT_TAGALIGN(oldlen+1), + err = fdt_splice_struct_(fdt, namep, FDT_TAGALIGN(oldlen+1), FDT_TAGALIGN(newlen+1)); if (err) return err; memcpy(namep, name, newlen+1); return 0; } -int fdt_setprop(void *fdt, int nodeoffset, const char *name, - const void *val, int len) +int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name, + int len, void **prop_data) { struct fdt_property *prop; int err; FDT_RW_CHECK_HEADER(fdt); - err = _fdt_resize_property(fdt, nodeoffset, name, len, &prop); + err = fdt_resize_property_(fdt, nodeoffset, name, len, &prop); if (err == -FDT_ERR_NOTFOUND) - err = _fdt_add_property(fdt, nodeoffset, name, len, &prop); + err = fdt_add_property_(fdt, nodeoffset, name, len, &prop); if (err) return err; + *prop_data = prop->data; + return 0; +} + +int fdt_setprop(void *fdt, int nodeoffset, const char *name, + const void *val, int len) +{ + void *prop_data; + int err; + + err = fdt_setprop_placeholder(fdt, nodeoffset, name, len, &prop_data); + if (err) + return err; + if (len) - memcpy(prop->data, val, len); + memcpy(prop_data, val, len); return 0; } int fdt_appendprop(void *fdt, int nodeoffset, const char *name, const void *val, int len) { struct fdt_property *prop; int err, oldlen, newlen; FDT_RW_CHECK_HEADER(fdt); prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); if (prop) { newlen = len + oldlen; - err = _fdt_splice_struct(fdt, prop->data, + err = fdt_splice_struct_(fdt, prop->data, FDT_TAGALIGN(oldlen), FDT_TAGALIGN(newlen)); if (err) return err; prop->len = cpu_to_fdt32(newlen); memcpy(prop->data + oldlen, val, len); } else { - err = _fdt_add_property(fdt, nodeoffset, name, len, &prop); + err = fdt_add_property_(fdt, nodeoffset, name, len, &prop); if (err) return err; memcpy(prop->data, val, len); } return 0; } int fdt_delprop(void *fdt, int nodeoffset, const char *name) { struct fdt_property *prop; int len, proplen; FDT_RW_CHECK_HEADER(fdt); prop = fdt_get_property_w(fdt, nodeoffset, name, &len); - if (! prop) + if (!prop) return len; proplen = sizeof(*prop) + FDT_TAGALIGN(len); - return _fdt_splice_struct(fdt, prop, proplen, 0); + return fdt_splice_struct_(fdt, prop, proplen, 0); } int fdt_add_subnode_namelen(void *fdt, int parentoffset, const char *name, int namelen) { struct fdt_node_header *nh; int offset, nextoffset; int nodelen; int err; uint32_t tag; fdt32_t *endtag; FDT_RW_CHECK_HEADER(fdt); offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen); if (offset >= 0) return -FDT_ERR_EXISTS; else if (offset != -FDT_ERR_NOTFOUND) return offset; /* Try to place the new node after the parent's properties */ fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */ do { offset = nextoffset; tag = fdt_next_tag(fdt, offset, &nextoffset); } while ((tag == FDT_PROP) || (tag == FDT_NOP)); - nh = _fdt_offset_ptr_w(fdt, offset); + nh = fdt_offset_ptr_w_(fdt, offset); nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE; - err = _fdt_splice_struct(fdt, nh, 0, nodelen); + err = fdt_splice_struct_(fdt, nh, 0, nodelen); if (err) return err; nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); memset(nh->name, 0, FDT_TAGALIGN(namelen+1)); memcpy(nh->name, name, namelen); endtag = (fdt32_t *)((char *)nh + nodelen - FDT_TAGSIZE); *endtag = cpu_to_fdt32(FDT_END_NODE); return offset; } int fdt_add_subnode(void *fdt, int parentoffset, const char *name) { return fdt_add_subnode_namelen(fdt, parentoffset, name, strlen(name)); } int fdt_del_node(void *fdt, int nodeoffset) { int endoffset; FDT_RW_CHECK_HEADER(fdt); - endoffset = _fdt_node_end_offset(fdt, nodeoffset); + endoffset = fdt_node_end_offset_(fdt, nodeoffset); if (endoffset < 0) return endoffset; - return _fdt_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset), + return fdt_splice_struct_(fdt, fdt_offset_ptr_w_(fdt, nodeoffset), endoffset - nodeoffset, 0); } -static void _fdt_packblocks(const char *old, char *new, +static void fdt_packblocks_(const char *old, char *new, int mem_rsv_size, int struct_size) { int mem_rsv_off, struct_off, strings_off; mem_rsv_off = FDT_ALIGN(sizeof(struct fdt_header), 8); struct_off = mem_rsv_off + mem_rsv_size; strings_off = struct_off + struct_size; memmove(new + mem_rsv_off, old + fdt_off_mem_rsvmap(old), mem_rsv_size); fdt_set_off_mem_rsvmap(new, mem_rsv_off); memmove(new + struct_off, old + fdt_off_dt_struct(old), struct_size); fdt_set_off_dt_struct(new, struct_off); fdt_set_size_dt_struct(new, struct_size); memmove(new + strings_off, old + fdt_off_dt_strings(old), fdt_size_dt_strings(old)); fdt_set_off_dt_strings(new, strings_off); fdt_set_size_dt_strings(new, fdt_size_dt_strings(old)); } int fdt_open_into(const void *fdt, void *buf, int bufsize) { int err; int mem_rsv_size, struct_size; int newsize; const char *fdtstart = fdt; const char *fdtend = fdtstart + fdt_totalsize(fdt); char *tmp; FDT_CHECK_HEADER(fdt); mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) * sizeof(struct fdt_reserve_entry); if (fdt_version(fdt) >= 17) { struct_size = fdt_size_dt_struct(fdt); } else { struct_size = 0; while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END) ; if (struct_size < 0) return struct_size; } - if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) { + if (!fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) { /* no further work necessary */ err = fdt_move(fdt, buf, bufsize); if (err) return err; fdt_set_version(buf, 17); fdt_set_size_dt_struct(buf, struct_size); fdt_set_totalsize(buf, bufsize); return 0; } /* Need to reorder */ newsize = FDT_ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size + struct_size + fdt_size_dt_strings(fdt); if (bufsize < newsize) return -FDT_ERR_NOSPACE; /* First attempt to build converted tree at beginning of buffer */ tmp = buf; /* But if that overlaps with the old tree... */ if (((tmp + newsize) > fdtstart) && (tmp < fdtend)) { /* Try right after the old tree instead */ tmp = (char *)(uintptr_t)fdtend; if ((tmp + newsize) > ((char *)buf + bufsize)) return -FDT_ERR_NOSPACE; } - _fdt_packblocks(fdt, tmp, mem_rsv_size, struct_size); + fdt_packblocks_(fdt, tmp, mem_rsv_size, struct_size); memmove(buf, tmp, newsize); fdt_set_magic(buf, FDT_MAGIC); fdt_set_totalsize(buf, bufsize); fdt_set_version(buf, 17); fdt_set_last_comp_version(buf, 16); fdt_set_boot_cpuid_phys(buf, fdt_boot_cpuid_phys(fdt)); return 0; } int fdt_pack(void *fdt) { int mem_rsv_size; FDT_RW_CHECK_HEADER(fdt); mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) * sizeof(struct fdt_reserve_entry); - _fdt_packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt)); - fdt_set_totalsize(fdt, _fdt_data_size(fdt)); + fdt_packblocks_(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt)); + fdt_set_totalsize(fdt, fdt_data_size_(fdt)); return 0; } Index: vendor/dtc/dist/libfdt/fdt_sw.c =================================================================== --- vendor/dtc/dist/libfdt/fdt_sw.c (revision 327892) +++ vendor/dtc/dist/libfdt/fdt_sw.c (revision 327893) @@ -1,288 +1,300 @@ /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. * * libfdt is dual licensed: you can use it either under the terms of * the GPL, or the BSD license, at your option. * * a) This library is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301 USA * * Alternatively, * * b) Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * 1. Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "libfdt_env.h" #include #include #include "libfdt_internal.h" -static int _fdt_sw_check_header(void *fdt) +static int fdt_sw_check_header_(void *fdt) { if (fdt_magic(fdt) != FDT_SW_MAGIC) return -FDT_ERR_BADMAGIC; /* FIXME: should check more details about the header state */ return 0; } #define FDT_SW_CHECK_HEADER(fdt) \ { \ int err; \ - if ((err = _fdt_sw_check_header(fdt)) != 0) \ + if ((err = fdt_sw_check_header_(fdt)) != 0) \ return err; \ } -static void *_fdt_grab_space(void *fdt, size_t len) +static void *fdt_grab_space_(void *fdt, size_t len) { int offset = fdt_size_dt_struct(fdt); int spaceleft; spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt) - fdt_size_dt_strings(fdt); if ((offset + len < offset) || (offset + len > spaceleft)) return NULL; fdt_set_size_dt_struct(fdt, offset + len); - return _fdt_offset_ptr_w(fdt, offset); + return fdt_offset_ptr_w_(fdt, offset); } int fdt_create(void *buf, int bufsize) { void *fdt = buf; if (bufsize < sizeof(struct fdt_header)) return -FDT_ERR_NOSPACE; memset(buf, 0, bufsize); fdt_set_magic(fdt, FDT_SW_MAGIC); fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION); fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION); fdt_set_totalsize(fdt, bufsize); fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header), sizeof(struct fdt_reserve_entry))); fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt)); fdt_set_off_dt_strings(fdt, bufsize); return 0; } int fdt_resize(void *fdt, void *buf, int bufsize) { size_t headsize, tailsize; char *oldtail, *newtail; FDT_SW_CHECK_HEADER(fdt); headsize = fdt_off_dt_struct(fdt); tailsize = fdt_size_dt_strings(fdt); if ((headsize + tailsize) > bufsize) return -FDT_ERR_NOSPACE; oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize; newtail = (char *)buf + bufsize - tailsize; /* Two cases to avoid clobbering data if the old and new * buffers partially overlap */ if (buf <= fdt) { memmove(buf, fdt, headsize); memmove(newtail, oldtail, tailsize); } else { memmove(newtail, oldtail, tailsize); memmove(buf, fdt, headsize); } fdt_set_off_dt_strings(buf, bufsize); fdt_set_totalsize(buf, bufsize); return 0; } int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size) { struct fdt_reserve_entry *re; int offset; FDT_SW_CHECK_HEADER(fdt); if (fdt_size_dt_struct(fdt)) return -FDT_ERR_BADSTATE; offset = fdt_off_dt_struct(fdt); if ((offset + sizeof(*re)) > fdt_totalsize(fdt)) return -FDT_ERR_NOSPACE; re = (struct fdt_reserve_entry *)((char *)fdt + offset); re->address = cpu_to_fdt64(addr); re->size = cpu_to_fdt64(size); fdt_set_off_dt_struct(fdt, offset + sizeof(*re)); return 0; } int fdt_finish_reservemap(void *fdt) { return fdt_add_reservemap_entry(fdt, 0, 0); } int fdt_begin_node(void *fdt, const char *name) { struct fdt_node_header *nh; int namelen = strlen(name) + 1; FDT_SW_CHECK_HEADER(fdt); - nh = _fdt_grab_space(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen)); + nh = fdt_grab_space_(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen)); if (! nh) return -FDT_ERR_NOSPACE; nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); memcpy(nh->name, name, namelen); return 0; } int fdt_end_node(void *fdt) { fdt32_t *en; FDT_SW_CHECK_HEADER(fdt); - en = _fdt_grab_space(fdt, FDT_TAGSIZE); + en = fdt_grab_space_(fdt, FDT_TAGSIZE); if (! en) return -FDT_ERR_NOSPACE; *en = cpu_to_fdt32(FDT_END_NODE); return 0; } -static int _fdt_find_add_string(void *fdt, const char *s) +static int fdt_find_add_string_(void *fdt, const char *s) { char *strtab = (char *)fdt + fdt_totalsize(fdt); const char *p; int strtabsize = fdt_size_dt_strings(fdt); int len = strlen(s) + 1; int struct_top, offset; - p = _fdt_find_string(strtab - strtabsize, strtabsize, s); + p = fdt_find_string_(strtab - strtabsize, strtabsize, s); if (p) return p - strtab; /* Add it */ offset = -strtabsize - len; struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); if (fdt_totalsize(fdt) + offset < struct_top) return 0; /* no more room :( */ memcpy(strtab + offset, s, len); fdt_set_size_dt_strings(fdt, strtabsize + len); return offset; } -int fdt_property(void *fdt, const char *name, const void *val, int len) +int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp) { struct fdt_property *prop; int nameoff; FDT_SW_CHECK_HEADER(fdt); - nameoff = _fdt_find_add_string(fdt, name); + nameoff = fdt_find_add_string_(fdt, name); if (nameoff == 0) return -FDT_ERR_NOSPACE; - prop = _fdt_grab_space(fdt, sizeof(*prop) + FDT_TAGALIGN(len)); + prop = fdt_grab_space_(fdt, sizeof(*prop) + FDT_TAGALIGN(len)); if (! prop) return -FDT_ERR_NOSPACE; prop->tag = cpu_to_fdt32(FDT_PROP); prop->nameoff = cpu_to_fdt32(nameoff); prop->len = cpu_to_fdt32(len); - memcpy(prop->data, val, len); + *valp = prop->data; return 0; } +int fdt_property(void *fdt, const char *name, const void *val, int len) +{ + void *ptr; + int ret; + + ret = fdt_property_placeholder(fdt, name, len, &ptr); + if (ret) + return ret; + memcpy(ptr, val, len); + return 0; +} + int fdt_finish(void *fdt) { char *p = (char *)fdt; fdt32_t *end; int oldstroffset, newstroffset; uint32_t tag; int offset, nextoffset; FDT_SW_CHECK_HEADER(fdt); /* Add terminator */ - end = _fdt_grab_space(fdt, sizeof(*end)); + end = fdt_grab_space_(fdt, sizeof(*end)); if (! end) return -FDT_ERR_NOSPACE; *end = cpu_to_fdt32(FDT_END); /* Relocate the string table */ oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt); newstroffset = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt)); fdt_set_off_dt_strings(fdt, newstroffset); /* Walk the structure, correcting string offsets */ offset = 0; while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) { if (tag == FDT_PROP) { struct fdt_property *prop = - _fdt_offset_ptr_w(fdt, offset); + fdt_offset_ptr_w_(fdt, offset); int nameoff; nameoff = fdt32_to_cpu(prop->nameoff); nameoff += fdt_size_dt_strings(fdt); prop->nameoff = cpu_to_fdt32(nameoff); } offset = nextoffset; } if (nextoffset < 0) return nextoffset; /* Finally, adjust the header */ fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt)); fdt_set_magic(fdt, FDT_MAGIC); return 0; } Index: vendor/dtc/dist/libfdt/fdt_wip.c =================================================================== --- vendor/dtc/dist/libfdt/fdt_wip.c (revision 327892) +++ vendor/dtc/dist/libfdt/fdt_wip.c (revision 327893) @@ -1,139 +1,139 @@ /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. * * libfdt is dual licensed: you can use it either under the terms of * the GPL, or the BSD license, at your option. * * a) This library is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301 USA * * Alternatively, * * b) Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * 1. Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "libfdt_env.h" #include #include #include "libfdt_internal.h" int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset, const char *name, int namelen, uint32_t idx, const void *val, int len) { void *propval; int proplen; propval = fdt_getprop_namelen_w(fdt, nodeoffset, name, namelen, &proplen); if (!propval) return proplen; if (proplen < (len + idx)) return -FDT_ERR_NOSPACE; memcpy((char *)propval + idx, val, len); return 0; } int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, const void *val, int len) { const void *propval; int proplen; propval = fdt_getprop(fdt, nodeoffset, name, &proplen); - if (! propval) + if (!propval) return proplen; if (proplen != len) return -FDT_ERR_NOSPACE; return fdt_setprop_inplace_namelen_partial(fdt, nodeoffset, name, strlen(name), 0, val, len); } -static void _fdt_nop_region(void *start, int len) +static void fdt_nop_region_(void *start, int len) { fdt32_t *p; for (p = start; (char *)p < ((char *)start + len); p++) *p = cpu_to_fdt32(FDT_NOP); } int fdt_nop_property(void *fdt, int nodeoffset, const char *name) { struct fdt_property *prop; int len; prop = fdt_get_property_w(fdt, nodeoffset, name, &len); - if (! prop) + if (!prop) return len; - _fdt_nop_region(prop, len + sizeof(*prop)); + fdt_nop_region_(prop, len + sizeof(*prop)); return 0; } -int _fdt_node_end_offset(void *fdt, int offset) +int fdt_node_end_offset_(void *fdt, int offset) { int depth = 0; while ((offset >= 0) && (depth >= 0)) offset = fdt_next_node(fdt, offset, &depth); return offset; } int fdt_nop_node(void *fdt, int nodeoffset) { int endoffset; - endoffset = _fdt_node_end_offset(fdt, nodeoffset); + endoffset = fdt_node_end_offset_(fdt, nodeoffset); if (endoffset < 0) return endoffset; - _fdt_nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0), + fdt_nop_region_(fdt_offset_ptr_w(fdt, nodeoffset, 0), endoffset - nodeoffset); return 0; } Index: vendor/dtc/dist/libfdt/libfdt.h =================================================================== --- vendor/dtc/dist/libfdt/libfdt.h (revision 327892) +++ vendor/dtc/dist/libfdt/libfdt.h (revision 327893) @@ -1,1833 +1,1899 @@ -#ifndef _LIBFDT_H -#define _LIBFDT_H +#ifndef LIBFDT_H +#define LIBFDT_H /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. * * libfdt is dual licensed: you can use it either under the terms of * the GPL, or the BSD license, at your option. * * a) This library is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301 USA * * Alternatively, * * b) Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * 1. Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #define FDT_FIRST_SUPPORTED_VERSION 0x10 #define FDT_LAST_SUPPORTED_VERSION 0x11 /* Error codes: informative error codes */ #define FDT_ERR_NOTFOUND 1 /* FDT_ERR_NOTFOUND: The requested node or property does not exist */ #define FDT_ERR_EXISTS 2 /* FDT_ERR_EXISTS: Attempted to create a node or property which * already exists */ #define FDT_ERR_NOSPACE 3 /* FDT_ERR_NOSPACE: Operation needed to expand the device * tree, but its buffer did not have sufficient space to * contain the expanded tree. Use fdt_open_into() to move the * device tree to a buffer with more space. */ /* Error codes: codes for bad parameters */ #define FDT_ERR_BADOFFSET 4 /* FDT_ERR_BADOFFSET: Function was passed a structure block * offset which is out-of-bounds, or which points to an * unsuitable part of the structure for the operation. */ #define FDT_ERR_BADPATH 5 /* FDT_ERR_BADPATH: Function was passed a badly formatted path * (e.g. missing a leading / for a function which requires an * absolute path) */ #define FDT_ERR_BADPHANDLE 6 /* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle. * This can be caused either by an invalid phandle property * length, or the phandle value was either 0 or -1, which are * not permitted. */ #define FDT_ERR_BADSTATE 7 /* FDT_ERR_BADSTATE: Function was passed an incomplete device * tree created by the sequential-write functions, which is * not sufficiently complete for the requested operation. */ /* Error codes: codes for bad device tree blobs */ #define FDT_ERR_TRUNCATED 8 /* FDT_ERR_TRUNCATED: Structure block of the given device tree * ends without an FDT_END tag. */ #define FDT_ERR_BADMAGIC 9 /* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a * device tree at all - it is missing the flattened device * tree magic number. */ #define FDT_ERR_BADVERSION 10 /* FDT_ERR_BADVERSION: Given device tree has a version which * can't be handled by the requested operation. For * read-write functions, this may mean that fdt_open_into() is * required to convert the tree to the expected version. */ #define FDT_ERR_BADSTRUCTURE 11 /* FDT_ERR_BADSTRUCTURE: Given device tree has a corrupt * structure block or other serious error (e.g. misnested * nodes, or subnodes preceding properties). */ #define FDT_ERR_BADLAYOUT 12 /* FDT_ERR_BADLAYOUT: For read-write functions, the given * device tree has it's sub-blocks in an order that the * function can't handle (memory reserve map, then structure, * then strings). Use fdt_open_into() to reorganize the tree * into a form suitable for the read-write operations. */ /* "Can't happen" error indicating a bug in libfdt */ #define FDT_ERR_INTERNAL 13 /* FDT_ERR_INTERNAL: libfdt has failed an internal assertion. * Should never be returned, if it is, it indicates a bug in * libfdt itself. */ /* Errors in device tree content */ #define FDT_ERR_BADNCELLS 14 /* FDT_ERR_BADNCELLS: Device tree has a #address-cells, #size-cells * or similar property with a bad format or value */ #define FDT_ERR_BADVALUE 15 /* FDT_ERR_BADVALUE: Device tree has a property with an unexpected * value. For example: a property expected to contain a string list * is not NUL-terminated within the length of its value. */ #define FDT_ERR_BADOVERLAY 16 /* FDT_ERR_BADOVERLAY: The device tree overlay, while * correctly structured, cannot be applied due to some * unexpected or missing value, property or node. */ #define FDT_ERR_NOPHANDLES 17 /* FDT_ERR_NOPHANDLES: The device tree doesn't have any * phandle available anymore without causing an overflow */ #define FDT_ERR_MAX 17 /**********************************************************************/ /* Low-level functions (you probably don't need these) */ /**********************************************************************/ +#ifndef SWIG /* This function is not useful in Python */ const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen); +#endif static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen) { return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen); } uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset); /**********************************************************************/ /* Traversal functions */ /**********************************************************************/ int fdt_next_node(const void *fdt, int offset, int *depth); /** * fdt_first_subnode() - get offset of first direct subnode * * @fdt: FDT blob * @offset: Offset of node to check * @return offset of first subnode, or -FDT_ERR_NOTFOUND if there is none */ int fdt_first_subnode(const void *fdt, int offset); /** * fdt_next_subnode() - get offset of next direct subnode * * After first calling fdt_first_subnode(), call this function repeatedly to * get direct subnodes of a parent node. * * @fdt: FDT blob * @offset: Offset of previous subnode * @return offset of next subnode, or -FDT_ERR_NOTFOUND if there are no more * subnodes */ int fdt_next_subnode(const void *fdt, int offset); /** * fdt_for_each_subnode - iterate over all subnodes of a parent * * @node: child node (int, lvalue) * @fdt: FDT blob (const void *) * @parent: parent node (int) * * This is actually a wrapper around a for loop and would be used like so: * * fdt_for_each_subnode(node, fdt, parent) { * Use node * ... * } * * if ((node < 0) && (node != -FDT_ERR_NOT_FOUND)) { * Error handling * } * * Note that this is implemented as a macro and @node is used as * iterator in the loop. The parent variable be constant or even a * literal. * */ #define fdt_for_each_subnode(node, fdt, parent) \ for (node = fdt_first_subnode(fdt, parent); \ node >= 0; \ node = fdt_next_subnode(fdt, node)) /**********************************************************************/ /* General functions */ /**********************************************************************/ - #define fdt_get_header(fdt, field) \ (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field)) #define fdt_magic(fdt) (fdt_get_header(fdt, magic)) #define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize)) #define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct)) #define fdt_off_dt_strings(fdt) (fdt_get_header(fdt, off_dt_strings)) #define fdt_off_mem_rsvmap(fdt) (fdt_get_header(fdt, off_mem_rsvmap)) #define fdt_version(fdt) (fdt_get_header(fdt, version)) #define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version)) #define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys)) #define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings)) #define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct)) -#define __fdt_set_hdr(name) \ +#define fdt_set_hdr_(name) \ static inline void fdt_set_##name(void *fdt, uint32_t val) \ { \ struct fdt_header *fdth = (struct fdt_header *)fdt; \ fdth->name = cpu_to_fdt32(val); \ } -__fdt_set_hdr(magic); -__fdt_set_hdr(totalsize); -__fdt_set_hdr(off_dt_struct); -__fdt_set_hdr(off_dt_strings); -__fdt_set_hdr(off_mem_rsvmap); -__fdt_set_hdr(version); -__fdt_set_hdr(last_comp_version); -__fdt_set_hdr(boot_cpuid_phys); -__fdt_set_hdr(size_dt_strings); -__fdt_set_hdr(size_dt_struct); -#undef __fdt_set_hdr +fdt_set_hdr_(magic); +fdt_set_hdr_(totalsize); +fdt_set_hdr_(off_dt_struct); +fdt_set_hdr_(off_dt_strings); +fdt_set_hdr_(off_mem_rsvmap); +fdt_set_hdr_(version); +fdt_set_hdr_(last_comp_version); +fdt_set_hdr_(boot_cpuid_phys); +fdt_set_hdr_(size_dt_strings); +fdt_set_hdr_(size_dt_struct); +#undef fdt_set_hdr_ /** * fdt_check_header - sanity check a device tree or possible device tree * @fdt: pointer to data which might be a flattened device tree * * fdt_check_header() checks that the given buffer contains what * appears to be a flattened device tree with sane information in its * header. * * returns: * 0, if the buffer appears to contain a valid device tree * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, standard meanings, as above */ int fdt_check_header(const void *fdt); /** * fdt_move - move a device tree around in memory * @fdt: pointer to the device tree to move * @buf: pointer to memory where the device is to be moved * @bufsize: size of the memory space at buf * * fdt_move() relocates, if possible, the device tree blob located at * fdt to the buffer at buf of size bufsize. The buffer may overlap * with the existing device tree blob at fdt. Therefore, * fdt_move(fdt, fdt, fdt_totalsize(fdt)) * should always succeed. * * returns: * 0, on success * -FDT_ERR_NOSPACE, bufsize is insufficient to contain the device tree * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, standard meanings */ int fdt_move(const void *fdt, void *buf, int bufsize); /**********************************************************************/ /* Read-only functions */ /**********************************************************************/ /** * fdt_string - retrieve a string from the strings block of a device tree * @fdt: pointer to the device tree blob * @stroffset: offset of the string within the strings block (native endian) * * fdt_string() retrieves a pointer to a single string from the * strings block of the device tree blob at fdt. * * returns: * a pointer to the string, on success * NULL, if stroffset is out of bounds */ const char *fdt_string(const void *fdt, int stroffset); /** * fdt_get_max_phandle - retrieves the highest phandle in a tree * @fdt: pointer to the device tree blob * * fdt_get_max_phandle retrieves the highest phandle in the given * device tree. This will ignore badly formatted phandles, or phandles * with a value of 0 or -1. * * returns: * the highest phandle on success * 0, if no phandle was found in the device tree * -1, if an error occurred */ uint32_t fdt_get_max_phandle(const void *fdt); /** * fdt_num_mem_rsv - retrieve the number of memory reserve map entries * @fdt: pointer to the device tree blob * * Returns the number of entries in the device tree blob's memory * reservation map. This does not include the terminating 0,0 entry * or any other (0,0) entries reserved for expansion. * * returns: * the number of entries */ int fdt_num_mem_rsv(const void *fdt); /** * fdt_get_mem_rsv - retrieve one memory reserve map entry * @fdt: pointer to the device tree blob * @address, @size: pointers to 64-bit variables * * On success, *address and *size will contain the address and size of * the n-th reserve map entry from the device tree blob, in * native-endian format. * * returns: * 0, on success * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, standard meanings */ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size); /** * fdt_subnode_offset_namelen - find a subnode based on substring * @fdt: pointer to the device tree blob * @parentoffset: structure block offset of a node * @name: name of the subnode to locate * @namelen: number of characters of name to consider * * Identical to fdt_subnode_offset(), but only examine the first * namelen characters of name for matching the subnode name. This is * useful for finding subnodes based on a portion of a larger string, * such as a full path. */ +#ifndef SWIG /* Not available in Python */ int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, const char *name, int namelen); +#endif /** * fdt_subnode_offset - find a subnode of a given node * @fdt: pointer to the device tree blob * @parentoffset: structure block offset of a node * @name: name of the subnode to locate * * fdt_subnode_offset() finds a subnode of the node at structure block * offset parentoffset with the given name. name may include a unit * address, in which case fdt_subnode_offset() will find the subnode * with that unit address, or the unit address may be omitted, in * which case fdt_subnode_offset() will find an arbitrary subnode * whose name excluding unit address matches the given name. * * returns: * structure block offset of the requested subnode (>=0), on success * -FDT_ERR_NOTFOUND, if the requested subnode does not exist * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE * tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings. */ int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name); /** * fdt_path_offset_namelen - find a tree node by its full path * @fdt: pointer to the device tree blob * @path: full path of the node to locate * @namelen: number of characters of path to consider * * Identical to fdt_path_offset(), but only consider the first namelen * characters of path as the path name. */ +#ifndef SWIG /* Not available in Python */ int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen); +#endif /** * fdt_path_offset - find a tree node by its full path * @fdt: pointer to the device tree blob * @path: full path of the node to locate * * fdt_path_offset() finds a node of a given path in the device tree. * Each path component may omit the unit address portion, but the * results of this are undefined if any such path component is * ambiguous (that is if there are multiple nodes at the relevant * level matching the given component, differentiated only by unit * address). * * returns: * structure block offset of the node with the requested path (>=0), on * success * -FDT_ERR_BADPATH, given path does not begin with '/' or is invalid * -FDT_ERR_NOTFOUND, if the requested node does not exist * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings. */ int fdt_path_offset(const void *fdt, const char *path); /** * fdt_get_name - retrieve the name of a given node * @fdt: pointer to the device tree blob * @nodeoffset: structure block offset of the starting node * @lenp: pointer to an integer variable (will be overwritten) or NULL * * fdt_get_name() retrieves the name (including unit address) of the * device tree node at structure block offset nodeoffset. If lenp is * non-NULL, the length of this name is also returned, in the integer * pointed to by lenp. * * returns: * pointer to the node's name, on success * If lenp is non-NULL, *lenp contains the length of that name * (>=0) * NULL, on error * if lenp is non-NULL *lenp contains an error code (<0): * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE * tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, standard meanings */ const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp); /** * fdt_first_property_offset - find the offset of a node's first property * @fdt: pointer to the device tree blob * @nodeoffset: structure block offset of a node * * fdt_first_property_offset() finds the first property of the node at * the given structure block offset. * * returns: * structure block offset of the property (>=0), on success * -FDT_ERR_NOTFOUND, if the requested node has no properties * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_BEGIN_NODE tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings. */ int fdt_first_property_offset(const void *fdt, int nodeoffset); /** * fdt_next_property_offset - step through a node's properties * @fdt: pointer to the device tree blob * @offset: structure block offset of a property * * fdt_next_property_offset() finds the property immediately after the * one at the given structure block offset. This will be a property * of the same node as the given property. * * returns: * structure block offset of the next property (>=0), on success * -FDT_ERR_NOTFOUND, if the given property is the last in its node * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_PROP tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings. */ int fdt_next_property_offset(const void *fdt, int offset); /** * fdt_for_each_property_offset - iterate over all properties of a node * * @property_offset: property offset (int, lvalue) * @fdt: FDT blob (const void *) * @node: node offset (int) * * This is actually a wrapper around a for loop and would be used like so: * * fdt_for_each_property_offset(property, fdt, node) { * Use property * ... * } * * if ((property < 0) && (property != -FDT_ERR_NOT_FOUND)) { * Error handling * } * * Note that this is implemented as a macro and property is used as * iterator in the loop. The node variable can be constant or even a * literal. */ #define fdt_for_each_property_offset(property, fdt, node) \ for (property = fdt_first_property_offset(fdt, node); \ property >= 0; \ property = fdt_next_property_offset(fdt, property)) /** * fdt_get_property_by_offset - retrieve the property at a given offset * @fdt: pointer to the device tree blob * @offset: offset of the property to retrieve * @lenp: pointer to an integer variable (will be overwritten) or NULL * * fdt_get_property_by_offset() retrieves a pointer to the * fdt_property structure within the device tree blob at the given * offset. If lenp is non-NULL, the length of the property value is * also returned, in the integer pointed to by lenp. * * returns: * pointer to the structure representing the property * if lenp is non-NULL, *lenp contains the length of the property * value (>=0) * NULL, on error * if lenp is non-NULL, *lenp contains an error code (<0): * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings */ const struct fdt_property *fdt_get_property_by_offset(const void *fdt, int offset, int *lenp); /** * fdt_get_property_namelen - find a property based on substring * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to find * @name: name of the property to find * @namelen: number of characters of name to consider * @lenp: pointer to an integer variable (will be overwritten) or NULL * * Identical to fdt_get_property(), but only examine the first namelen * characters of name for matching the property name. */ +#ifndef SWIG /* Not available in Python */ const struct fdt_property *fdt_get_property_namelen(const void *fdt, int nodeoffset, const char *name, int namelen, int *lenp); +#endif /** * fdt_get_property - find a given property in a given node * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to find * @name: name of the property to find * @lenp: pointer to an integer variable (will be overwritten) or NULL * * fdt_get_property() retrieves a pointer to the fdt_property * structure within the device tree blob corresponding to the property * named 'name' of the node at offset nodeoffset. If lenp is * non-NULL, the length of the property value is also returned, in the * integer pointed to by lenp. * * returns: * pointer to the structure representing the property * if lenp is non-NULL, *lenp contains the length of the property * value (>=0) * NULL, on error * if lenp is non-NULL, *lenp contains an error code (<0): * -FDT_ERR_NOTFOUND, node does not have named property * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE * tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings */ const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset, const char *name, int *lenp); static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset, const char *name, int *lenp) { return (struct fdt_property *)(uintptr_t) fdt_get_property(fdt, nodeoffset, name, lenp); } /** * fdt_getprop_by_offset - retrieve the value of a property at a given offset * @fdt: pointer to the device tree blob * @ffset: offset of the property to read * @namep: pointer to a string variable (will be overwritten) or NULL * @lenp: pointer to an integer variable (will be overwritten) or NULL * * fdt_getprop_by_offset() retrieves a pointer to the value of the * property at structure block offset 'offset' (this will be a pointer * to within the device blob itself, not a copy of the value). If * lenp is non-NULL, the length of the property value is also * returned, in the integer pointed to by lenp. If namep is non-NULL, * the property's namne will also be returned in the char * pointed to * by namep (this will be a pointer to within the device tree's string * block, not a new copy of the name). * * returns: * pointer to the property's value * if lenp is non-NULL, *lenp contains the length of the property * value (>=0) * if namep is non-NULL *namep contiains a pointer to the property * name. * NULL, on error * if lenp is non-NULL, *lenp contains an error code (<0): * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings */ +#ifndef SWIG /* This function is not useful in Python */ const void *fdt_getprop_by_offset(const void *fdt, int offset, const char **namep, int *lenp); +#endif /** * fdt_getprop_namelen - get property value based on substring * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to find * @name: name of the property to find * @namelen: number of characters of name to consider * @lenp: pointer to an integer variable (will be overwritten) or NULL * * Identical to fdt_getprop(), but only examine the first namelen * characters of name for matching the property name. */ +#ifndef SWIG /* Not available in Python */ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, const char *name, int namelen, int *lenp); static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset, const char *name, int namelen, int *lenp) { return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name, namelen, lenp); } +#endif /** * fdt_getprop - retrieve the value of a given property * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to find * @name: name of the property to find * @lenp: pointer to an integer variable (will be overwritten) or NULL * * fdt_getprop() retrieves a pointer to the value of the property * named 'name' of the node at offset nodeoffset (this will be a * pointer to within the device blob itself, not a copy of the value). * If lenp is non-NULL, the length of the property value is also * returned, in the integer pointed to by lenp. * * returns: * pointer to the property's value * if lenp is non-NULL, *lenp contains the length of the property * value (>=0) * NULL, on error * if lenp is non-NULL, *lenp contains an error code (<0): * -FDT_ERR_NOTFOUND, node does not have named property * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE * tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings */ const void *fdt_getprop(const void *fdt, int nodeoffset, const char *name, int *lenp); static inline void *fdt_getprop_w(void *fdt, int nodeoffset, const char *name, int *lenp) { return (void *)(uintptr_t)fdt_getprop(fdt, nodeoffset, name, lenp); } /** * fdt_get_phandle - retrieve the phandle of a given node * @fdt: pointer to the device tree blob * @nodeoffset: structure block offset of the node * * fdt_get_phandle() retrieves the phandle of the device tree node at * structure block offset nodeoffset. * * returns: * the phandle of the node at nodeoffset, on success (!= 0, != -1) * 0, if the node has no phandle, or another error occurs */ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset); /** * fdt_get_alias_namelen - get alias based on substring * @fdt: pointer to the device tree blob * @name: name of the alias th look up * @namelen: number of characters of name to consider * * Identical to fdt_get_alias(), but only examine the first namelen * characters of name for matching the alias name. */ +#ifndef SWIG /* Not available in Python */ const char *fdt_get_alias_namelen(const void *fdt, const char *name, int namelen); +#endif /** * fdt_get_alias - retrieve the path referenced by a given alias * @fdt: pointer to the device tree blob * @name: name of the alias th look up * * fdt_get_alias() retrieves the value of a given alias. That is, the * value of the property named 'name' in the node /aliases. * * returns: * a pointer to the expansion of the alias named 'name', if it exists * NULL, if the given alias or the /aliases node does not exist */ const char *fdt_get_alias(const void *fdt, const char *name); /** * fdt_get_path - determine the full path of a node * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose path to find * @buf: character buffer to contain the returned path (will be overwritten) * @buflen: size of the character buffer at buf * * fdt_get_path() computes the full path of the node at offset * nodeoffset, and records that path in the buffer at buf. * * NOTE: This function is expensive, as it must scan the device tree * structure from the start to nodeoffset. * * returns: * 0, on success * buf contains the absolute path of the node at * nodeoffset, as a NUL-terminated string. * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag * -FDT_ERR_NOSPACE, the path of the given node is longer than (bufsize-1) * characters and will not fit in the given buffer. * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, standard meanings */ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen); /** * fdt_supernode_atdepth_offset - find a specific ancestor of a node * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose parent to find * @supernodedepth: depth of the ancestor to find * @nodedepth: pointer to an integer variable (will be overwritten) or NULL * * fdt_supernode_atdepth_offset() finds an ancestor of the given node * at a specific depth from the root (where the root itself has depth * 0, its immediate subnodes depth 1 and so forth). So * fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, NULL); * will always return 0, the offset of the root node. If the node at * nodeoffset has depth D, then: * fdt_supernode_atdepth_offset(fdt, nodeoffset, D, NULL); * will return nodeoffset itself. * * NOTE: This function is expensive, as it must scan the device tree * structure from the start to nodeoffset. * * returns: * structure block offset of the node at node offset's ancestor * of depth supernodedepth (>=0), on success * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag * -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of * nodeoffset * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, standard meanings */ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, int supernodedepth, int *nodedepth); /** * fdt_node_depth - find the depth of a given node * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose parent to find * * fdt_node_depth() finds the depth of a given node. The root node * has depth 0, its immediate subnodes depth 1 and so forth. * * NOTE: This function is expensive, as it must scan the device tree * structure from the start to nodeoffset. * * returns: * depth of the node at nodeoffset (>=0), on success * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, standard meanings */ int fdt_node_depth(const void *fdt, int nodeoffset); /** * fdt_parent_offset - find the parent of a given node * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose parent to find * * fdt_parent_offset() locates the parent node of a given node (that * is, it finds the offset of the node which contains the node at * nodeoffset as a subnode). * * NOTE: This function is expensive, as it must scan the device tree * structure from the start to nodeoffset, *twice*. * * returns: * structure block offset of the parent of the node at nodeoffset * (>=0), on success * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, standard meanings */ int fdt_parent_offset(const void *fdt, int nodeoffset); /** * fdt_node_offset_by_prop_value - find nodes with a given property value * @fdt: pointer to the device tree blob * @startoffset: only find nodes after this offset * @propname: property name to check * @propval: property value to search for * @proplen: length of the value in propval * * fdt_node_offset_by_prop_value() returns the offset of the first * node after startoffset, which has a property named propname whose * value is of length proplen and has value equal to propval; or if * startoffset is -1, the very first such node in the tree. * * To iterate through all nodes matching the criterion, the following * idiom can be used: * offset = fdt_node_offset_by_prop_value(fdt, -1, propname, * propval, proplen); * while (offset != -FDT_ERR_NOTFOUND) { * // other code here * offset = fdt_node_offset_by_prop_value(fdt, offset, propname, * propval, proplen); * } * * Note the -1 in the first call to the function, if 0 is used here * instead, the function will never locate the root node, even if it * matches the criterion. * * returns: * structure block offset of the located node (>= 0, >startoffset), * on success * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the * tree after startoffset * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, standard meanings */ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, const char *propname, const void *propval, int proplen); /** * fdt_node_offset_by_phandle - find the node with a given phandle * @fdt: pointer to the device tree blob * @phandle: phandle value * * fdt_node_offset_by_phandle() returns the offset of the node * which has the given phandle value. If there is more than one node * in the tree with the given phandle (an invalid tree), results are * undefined. * * returns: * structure block offset of the located node (>= 0), on success * -FDT_ERR_NOTFOUND, no node with that phandle exists * -FDT_ERR_BADPHANDLE, given phandle value was invalid (0 or -1) * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, standard meanings */ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle); /** * fdt_node_check_compatible: check a node's compatible property * @fdt: pointer to the device tree blob * @nodeoffset: offset of a tree node * @compatible: string to match against * * * fdt_node_check_compatible() returns 0 if the given node contains a * 'compatible' property with the given string as one of its elements, * it returns non-zero otherwise, or on error. * * returns: * 0, if the node has a 'compatible' property listing the given string * 1, if the node has a 'compatible' property, but it does not list * the given string * -FDT_ERR_NOTFOUND, if the given node has no 'compatible' property * -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, standard meanings */ int fdt_node_check_compatible(const void *fdt, int nodeoffset, const char *compatible); /** * fdt_node_offset_by_compatible - find nodes with a given 'compatible' value * @fdt: pointer to the device tree blob * @startoffset: only find nodes after this offset * @compatible: 'compatible' string to match against * * fdt_node_offset_by_compatible() returns the offset of the first * node after startoffset, which has a 'compatible' property which * lists the given compatible string; or if startoffset is -1, the * very first such node in the tree. * * To iterate through all nodes matching the criterion, the following * idiom can be used: * offset = fdt_node_offset_by_compatible(fdt, -1, compatible); * while (offset != -FDT_ERR_NOTFOUND) { * // other code here * offset = fdt_node_offset_by_compatible(fdt, offset, compatible); * } * * Note the -1 in the first call to the function, if 0 is used here * instead, the function will never locate the root node, even if it * matches the criterion. * * returns: * structure block offset of the located node (>= 0, >startoffset), * on success * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the * tree after startoffset * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, standard meanings */ int fdt_node_offset_by_compatible(const void *fdt, int startoffset, const char *compatible); /** * fdt_stringlist_contains - check a string list property for a string * @strlist: Property containing a list of strings to check * @listlen: Length of property * @str: String to search for * * This is a utility function provided for convenience. The list contains * one or more strings, each terminated by \0, as is found in a device tree * "compatible" property. * * @return: 1 if the string is found in the list, 0 not found, or invalid list */ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str); /** * fdt_stringlist_count - count the number of strings in a string list * @fdt: pointer to the device tree blob * @nodeoffset: offset of a tree node * @property: name of the property containing the string list * @return: * the number of strings in the given property * -FDT_ERR_BADVALUE if the property value is not NUL-terminated * -FDT_ERR_NOTFOUND if the property does not exist */ int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property); /** * fdt_stringlist_search - find a string in a string list and return its index * @fdt: pointer to the device tree blob * @nodeoffset: offset of a tree node * @property: name of the property containing the string list * @string: string to look up in the string list * * Note that it is possible for this function to succeed on property values * that are not NUL-terminated. That's because the function will stop after * finding the first occurrence of @string. This can for example happen with * small-valued cell properties, such as #address-cells, when searching for * the empty string. * * @return: * the index of the string in the list of strings * -FDT_ERR_BADVALUE if the property value is not NUL-terminated * -FDT_ERR_NOTFOUND if the property does not exist or does not contain * the given string */ int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property, const char *string); /** * fdt_stringlist_get() - obtain the string at a given index in a string list * @fdt: pointer to the device tree blob * @nodeoffset: offset of a tree node * @property: name of the property containing the string list * @index: index of the string to return * @lenp: return location for the string length or an error code on failure * * Note that this will successfully extract strings from properties with * non-NUL-terminated values. For example on small-valued cell properties * this function will return the empty string. * * If non-NULL, the length of the string (on success) or a negative error-code * (on failure) will be stored in the integer pointer to by lenp. * * @return: * A pointer to the string at the given index in the string list or NULL on * failure. On success the length of the string will be stored in the memory * location pointed to by the lenp parameter, if non-NULL. On failure one of * the following negative error codes will be returned in the lenp parameter * (if non-NULL): * -FDT_ERR_BADVALUE if the property value is not NUL-terminated * -FDT_ERR_NOTFOUND if the property does not exist */ const char *fdt_stringlist_get(const void *fdt, int nodeoffset, const char *property, int index, int *lenp); /**********************************************************************/ /* Read-only functions (addressing related) */ /**********************************************************************/ /** * FDT_MAX_NCELLS - maximum value for #address-cells and #size-cells * * This is the maximum value for #address-cells, #size-cells and * similar properties that will be processed by libfdt. IEE1275 * requires that OF implementations handle values up to 4. * Implementations may support larger values, but in practice higher * values aren't used. */ #define FDT_MAX_NCELLS 4 /** * fdt_address_cells - retrieve address size for a bus represented in the tree * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node to find the address size for * * When the node has a valid #address-cells property, returns its value. * * returns: * 0 <= n < FDT_MAX_NCELLS, on success * 2, if the node has no #address-cells property * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid * #address-cells property * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings */ int fdt_address_cells(const void *fdt, int nodeoffset); /** * fdt_size_cells - retrieve address range size for a bus represented in the * tree * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node to find the address range size for * * When the node has a valid #size-cells property, returns its value. * * returns: * 0 <= n < FDT_MAX_NCELLS, on success * 2, if the node has no #address-cells property * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid * #size-cells property * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings */ int fdt_size_cells(const void *fdt, int nodeoffset); /**********************************************************************/ /* Write-in-place functions */ /**********************************************************************/ /** * fdt_setprop_inplace_namelen_partial - change a property's value, * but not its size * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to change * @name: name of the property to change * @namelen: number of characters of name to consider * @idx: index of the property to change in the array * @val: pointer to data to replace the property value with * @len: length of the property value * * Identical to fdt_setprop_inplace(), but modifies the given property * starting from the given index, and using only the first characters * of the name. It is useful when you want to manipulate only one value of * an array and you have a string that doesn't end with \0. */ +#ifndef SWIG /* Not available in Python */ int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset, const char *name, int namelen, uint32_t idx, const void *val, int len); +#endif /** * fdt_setprop_inplace - change a property's value, but not its size * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to change * @name: name of the property to change * @val: pointer to data to replace the property value with * @len: length of the property value * * fdt_setprop_inplace() replaces the value of a given property with * the data in val, of length len. This function cannot change the * size of a property, and so will only work if len is equal to the * current length of the property. * * This function will alter only the bytes in the blob which contain * the given property value, and will not alter or move any other part * of the tree. * * returns: * 0, on success * -FDT_ERR_NOSPACE, if len is not equal to the property's current length * -FDT_ERR_NOTFOUND, node does not have the named property * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings */ +#ifndef SWIG /* Not available in Python */ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, const void *val, int len); +#endif /** * fdt_setprop_inplace_u32 - change the value of a 32-bit integer property * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to change * @name: name of the property to change * @val: 32-bit integer value to replace the property with * * fdt_setprop_inplace_u32() replaces the value of a given property * with the 32-bit integer value in val, converting val to big-endian * if necessary. This function cannot change the size of a property, * and so will only work if the property already exists and has length * 4. * * This function will alter only the bytes in the blob which contain * the given property value, and will not alter or move any other part * of the tree. * * returns: * 0, on success * -FDT_ERR_NOSPACE, if the property's length is not equal to 4 * -FDT_ERR_NOTFOUND, node does not have the named property * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings */ static inline int fdt_setprop_inplace_u32(void *fdt, int nodeoffset, const char *name, uint32_t val) { fdt32_t tmp = cpu_to_fdt32(val); return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp)); } /** * fdt_setprop_inplace_u64 - change the value of a 64-bit integer property * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to change * @name: name of the property to change * @val: 64-bit integer value to replace the property with * * fdt_setprop_inplace_u64() replaces the value of a given property * with the 64-bit integer value in val, converting val to big-endian * if necessary. This function cannot change the size of a property, * and so will only work if the property already exists and has length * 8. * * This function will alter only the bytes in the blob which contain * the given property value, and will not alter or move any other part * of the tree. * * returns: * 0, on success * -FDT_ERR_NOSPACE, if the property's length is not equal to 8 * -FDT_ERR_NOTFOUND, node does not have the named property * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings */ static inline int fdt_setprop_inplace_u64(void *fdt, int nodeoffset, const char *name, uint64_t val) { fdt64_t tmp = cpu_to_fdt64(val); return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp)); } /** * fdt_setprop_inplace_cell - change the value of a single-cell property * * This is an alternative name for fdt_setprop_inplace_u32() */ static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset, const char *name, uint32_t val) { return fdt_setprop_inplace_u32(fdt, nodeoffset, name, val); } /** * fdt_nop_property - replace a property with nop tags * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to nop * @name: name of the property to nop * * fdt_nop_property() will replace a given property's representation * in the blob with FDT_NOP tags, effectively removing it from the * tree. * * This function will alter only the bytes in the blob which contain * the property, and will not alter or move any other part of the * tree. * * returns: * 0, on success * -FDT_ERR_NOTFOUND, node does not have the named property * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings */ int fdt_nop_property(void *fdt, int nodeoffset, const char *name); /** * fdt_nop_node - replace a node (subtree) with nop tags * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node to nop * * fdt_nop_node() will replace a given node's representation in the * blob, including all its subnodes, if any, with FDT_NOP tags, * effectively removing it from the tree. * * This function will alter only the bytes in the blob which contain * the node and its properties and subnodes, and will not alter or * move any other part of the tree. * * returns: * 0, on success * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings */ int fdt_nop_node(void *fdt, int nodeoffset); /**********************************************************************/ /* Sequential write functions */ /**********************************************************************/ int fdt_create(void *buf, int bufsize); int fdt_resize(void *fdt, void *buf, int bufsize); int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size); int fdt_finish_reservemap(void *fdt); int fdt_begin_node(void *fdt, const char *name); int fdt_property(void *fdt, const char *name, const void *val, int len); static inline int fdt_property_u32(void *fdt, const char *name, uint32_t val) { fdt32_t tmp = cpu_to_fdt32(val); return fdt_property(fdt, name, &tmp, sizeof(tmp)); } static inline int fdt_property_u64(void *fdt, const char *name, uint64_t val) { fdt64_t tmp = cpu_to_fdt64(val); return fdt_property(fdt, name, &tmp, sizeof(tmp)); } static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val) { return fdt_property_u32(fdt, name, val); } + +/** + * fdt_property_placeholder - add a new property and return a ptr to its value + * + * @fdt: pointer to the device tree blob + * @name: name of property to add + * @len: length of property value in bytes + * @valp: returns a pointer to where where the value should be placed + * + * returns: + * 0, on success + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_NOSPACE, standard meanings + */ +int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp); + #define fdt_property_string(fdt, name, str) \ fdt_property(fdt, name, str, strlen(str)+1) int fdt_end_node(void *fdt); int fdt_finish(void *fdt); /**********************************************************************/ /* Read-write functions */ /**********************************************************************/ int fdt_create_empty_tree(void *buf, int bufsize); int fdt_open_into(const void *fdt, void *buf, int bufsize); int fdt_pack(void *fdt); /** * fdt_add_mem_rsv - add one memory reserve map entry * @fdt: pointer to the device tree blob * @address, @size: 64-bit values (native endian) * * Adds a reserve map entry to the given blob reserving a region at * address address of length size. * * This function will insert data into the reserve map and will * therefore change the indexes of some entries in the table. * * returns: * 0, on success * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to * contain the new reservation entry * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_BADLAYOUT, * -FDT_ERR_TRUNCATED, standard meanings */ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size); /** * fdt_del_mem_rsv - remove a memory reserve map entry * @fdt: pointer to the device tree blob * @n: entry to remove * * fdt_del_mem_rsv() removes the n-th memory reserve map entry from * the blob. * * This function will delete data from the reservation table and will * therefore change the indexes of some entries in the table. * * returns: * 0, on success * -FDT_ERR_NOTFOUND, there is no entry of the given index (i.e. there * are less than n+1 reserve map entries) * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_BADLAYOUT, * -FDT_ERR_TRUNCATED, standard meanings */ int fdt_del_mem_rsv(void *fdt, int n); /** * fdt_set_name - change the name of a given node * @fdt: pointer to the device tree blob * @nodeoffset: structure block offset of a node * @name: name to give the node * * fdt_set_name() replaces the name (including unit address, if any) * of the given node with the given string. NOTE: this function can't * efficiently check if the new name is unique amongst the given * node's siblings; results are undefined if this function is invoked * with a name equal to one of the given node's siblings. * * This function may insert or delete data from the blob, and will * therefore change the offsets of some existing nodes. * * returns: * 0, on success * -FDT_ERR_NOSPACE, there is insufficient free space in the blob * to contain the new name * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, standard meanings */ int fdt_set_name(void *fdt, int nodeoffset, const char *name); /** * fdt_setprop - create or change a property * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to change * @name: name of the property to change * @val: pointer to data to set the property value to * @len: length of the property value * * fdt_setprop() sets the value of the named property in the given * node to the given value and length, creating the property if it * does not already exist. * * This function may insert or delete data from the blob, and will * therefore change the offsets of some existing nodes. * * returns: * 0, on success * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to * contain the new property value * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADLAYOUT, * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_BADLAYOUT, * -FDT_ERR_TRUNCATED, standard meanings */ int fdt_setprop(void *fdt, int nodeoffset, const char *name, const void *val, int len); /** + * fdt_setprop_placeholder - allocate space for a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @len: length of the property value + * @prop_data: return pointer to property data + * + * fdt_setprop_placeholer() allocates the named property in the given node. + * If the property exists it is resized. In either case a pointer to the + * property data is returned. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name, + int len, void **prop_data); + +/** * fdt_setprop_u32 - set a property to a 32-bit integer * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to change * @name: name of the property to change * @val: 32-bit integer value for the property (native endian) * * fdt_setprop_u32() sets the value of the named property in the given * node to the given 32-bit integer value (converting to big-endian if * necessary), or creates a new property with that value if it does * not already exist. * * This function may insert or delete data from the blob, and will * therefore change the offsets of some existing nodes. * * returns: * 0, on success * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to * contain the new property value * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADLAYOUT, * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_BADLAYOUT, * -FDT_ERR_TRUNCATED, standard meanings */ static inline int fdt_setprop_u32(void *fdt, int nodeoffset, const char *name, uint32_t val) { fdt32_t tmp = cpu_to_fdt32(val); return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); } /** * fdt_setprop_u64 - set a property to a 64-bit integer * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to change * @name: name of the property to change * @val: 64-bit integer value for the property (native endian) * * fdt_setprop_u64() sets the value of the named property in the given * node to the given 64-bit integer value (converting to big-endian if * necessary), or creates a new property with that value if it does * not already exist. * * This function may insert or delete data from the blob, and will * therefore change the offsets of some existing nodes. * * returns: * 0, on success * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to * contain the new property value * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADLAYOUT, * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_BADLAYOUT, * -FDT_ERR_TRUNCATED, standard meanings */ static inline int fdt_setprop_u64(void *fdt, int nodeoffset, const char *name, uint64_t val) { fdt64_t tmp = cpu_to_fdt64(val); return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); } /** * fdt_setprop_cell - set a property to a single cell value * * This is an alternative name for fdt_setprop_u32() */ static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name, uint32_t val) { return fdt_setprop_u32(fdt, nodeoffset, name, val); } /** * fdt_setprop_string - set a property to a string value * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to change * @name: name of the property to change * @str: string value for the property * * fdt_setprop_string() sets the value of the named property in the * given node to the given string value (using the length of the * string to determine the new length of the property), or creates a * new property with that value if it does not already exist. * * This function may insert or delete data from the blob, and will * therefore change the offsets of some existing nodes. * * returns: * 0, on success * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to * contain the new property value * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADLAYOUT, * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_BADLAYOUT, * -FDT_ERR_TRUNCATED, standard meanings */ #define fdt_setprop_string(fdt, nodeoffset, name, str) \ fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) /** * fdt_setprop_empty - set a property to an empty value * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to change * @name: name of the property to change * * fdt_setprop_empty() sets the value of the named property in the * given node to an empty (zero length) value, or creates a new empty * property if it does not already exist. * * This function may insert or delete data from the blob, and will * therefore change the offsets of some existing nodes. * * returns: * 0, on success * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to * contain the new property value * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADLAYOUT, * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_BADLAYOUT, * -FDT_ERR_TRUNCATED, standard meanings */ #define fdt_setprop_empty(fdt, nodeoffset, name) \ fdt_setprop((fdt), (nodeoffset), (name), NULL, 0) /** * fdt_appendprop - append to or create a property * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to change * @name: name of the property to append to * @val: pointer to data to append to the property value * @len: length of the data to append to the property value * * fdt_appendprop() appends the value to the named property in the * given node, creating the property if it does not already exist. * * This function may insert data into the blob, and will therefore * change the offsets of some existing nodes. * * returns: * 0, on success * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to * contain the new property value * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADLAYOUT, * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_BADLAYOUT, * -FDT_ERR_TRUNCATED, standard meanings */ int fdt_appendprop(void *fdt, int nodeoffset, const char *name, const void *val, int len); /** * fdt_appendprop_u32 - append a 32-bit integer value to a property * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to change * @name: name of the property to change * @val: 32-bit integer value to append to the property (native endian) * * fdt_appendprop_u32() appends the given 32-bit integer value * (converting to big-endian if necessary) to the value of the named * property in the given node, or creates a new property with that * value if it does not already exist. * * This function may insert data into the blob, and will therefore * change the offsets of some existing nodes. * * returns: * 0, on success * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to * contain the new property value * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADLAYOUT, * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_BADLAYOUT, * -FDT_ERR_TRUNCATED, standard meanings */ static inline int fdt_appendprop_u32(void *fdt, int nodeoffset, const char *name, uint32_t val) { fdt32_t tmp = cpu_to_fdt32(val); return fdt_appendprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); } /** * fdt_appendprop_u64 - append a 64-bit integer value to a property * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to change * @name: name of the property to change * @val: 64-bit integer value to append to the property (native endian) * * fdt_appendprop_u64() appends the given 64-bit integer value * (converting to big-endian if necessary) to the value of the named * property in the given node, or creates a new property with that * value if it does not already exist. * * This function may insert data into the blob, and will therefore * change the offsets of some existing nodes. * * returns: * 0, on success * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to * contain the new property value * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADLAYOUT, * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_BADLAYOUT, * -FDT_ERR_TRUNCATED, standard meanings */ static inline int fdt_appendprop_u64(void *fdt, int nodeoffset, const char *name, uint64_t val) { fdt64_t tmp = cpu_to_fdt64(val); return fdt_appendprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); } /** * fdt_appendprop_cell - append a single cell value to a property * * This is an alternative name for fdt_appendprop_u32() */ static inline int fdt_appendprop_cell(void *fdt, int nodeoffset, const char *name, uint32_t val) { return fdt_appendprop_u32(fdt, nodeoffset, name, val); } /** * fdt_appendprop_string - append a string to a property * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to change * @name: name of the property to change * @str: string value to append to the property * * fdt_appendprop_string() appends the given string to the value of * the named property in the given node, or creates a new property * with that value if it does not already exist. * * This function may insert data into the blob, and will therefore * change the offsets of some existing nodes. * * returns: * 0, on success * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to * contain the new property value * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADLAYOUT, * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_BADLAYOUT, * -FDT_ERR_TRUNCATED, standard meanings */ #define fdt_appendprop_string(fdt, nodeoffset, name, str) \ fdt_appendprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) /** * fdt_delprop - delete a property * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to nop * @name: name of the property to nop * * fdt_del_property() will delete the given property. * * This function will delete data from the blob, and will therefore * change the offsets of some existing nodes. * * returns: * 0, on success * -FDT_ERR_NOTFOUND, node does not have the named property * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADLAYOUT, * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings */ int fdt_delprop(void *fdt, int nodeoffset, const char *name); /** * fdt_add_subnode_namelen - creates a new node based on substring * @fdt: pointer to the device tree blob * @parentoffset: structure block offset of a node * @name: name of the subnode to locate * @namelen: number of characters of name to consider * * Identical to fdt_add_subnode(), but use only the first namelen * characters of name as the name of the new node. This is useful for * creating subnodes based on a portion of a larger string, such as a * full path. */ +#ifndef SWIG /* Not available in Python */ int fdt_add_subnode_namelen(void *fdt, int parentoffset, const char *name, int namelen); +#endif /** * fdt_add_subnode - creates a new node * @fdt: pointer to the device tree blob * @parentoffset: structure block offset of a node * @name: name of the subnode to locate * * fdt_add_subnode() creates a new node as a subnode of the node at * structure block offset parentoffset, with the given name (which * should include the unit address, if any). * * This function will insert data into the blob, and will therefore * change the offsets of some existing nodes. * returns: * structure block offset of the created nodeequested subnode (>=0), on * success * -FDT_ERR_NOTFOUND, if the requested subnode does not exist * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE * tag * -FDT_ERR_EXISTS, if the node at parentoffset already has a subnode of * the given name * -FDT_ERR_NOSPACE, if there is insufficient free space in the * blob to contain the new node * -FDT_ERR_NOSPACE * -FDT_ERR_BADLAYOUT * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings. */ int fdt_add_subnode(void *fdt, int parentoffset, const char *name); /** * fdt_del_node - delete a node (subtree) * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node to nop * * fdt_del_node() will remove the given node, including all its * subnodes if any, from the blob. * * This function will delete data from the blob, and will therefore * change the offsets of some existing nodes. * * returns: * 0, on success * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADLAYOUT, * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings */ int fdt_del_node(void *fdt, int nodeoffset); /** * fdt_overlay_apply - Applies a DT overlay on a base DT * @fdt: pointer to the base device tree blob * @fdto: pointer to the device tree overlay blob * * fdt_overlay_apply() will apply the given device tree overlay on the * given base device tree. * * Expect the base device tree to be modified, even if the function * returns an error. * * returns: * 0, on success * -FDT_ERR_NOSPACE, there's not enough space in the base device tree * -FDT_ERR_NOTFOUND, the overlay points to some inexistant nodes or * properties in the base DT * -FDT_ERR_BADPHANDLE, * -FDT_ERR_BADOVERLAY, * -FDT_ERR_NOPHANDLES, * -FDT_ERR_INTERNAL, * -FDT_ERR_BADLAYOUT, * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADOFFSET, * -FDT_ERR_BADPATH, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_BADSTATE, * -FDT_ERR_TRUNCATED, standard meanings */ int fdt_overlay_apply(void *fdt, void *fdto); /**********************************************************************/ /* Debugging / informational functions */ /**********************************************************************/ const char *fdt_strerror(int errval); -#endif /* _LIBFDT_H */ +#endif /* LIBFDT_H */ Index: vendor/dtc/dist/libfdt/libfdt_env.h =================================================================== --- vendor/dtc/dist/libfdt/libfdt_env.h (revision 327892) +++ vendor/dtc/dist/libfdt/libfdt_env.h (revision 327893) @@ -1,112 +1,139 @@ -#ifndef _LIBFDT_ENV_H -#define _LIBFDT_ENV_H +#ifndef LIBFDT_ENV_H +#define LIBFDT_ENV_H /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. * Copyright 2012 Kim Phillips, Freescale Semiconductor. * * libfdt is dual licensed: you can use it either under the terms of * the GPL, or the BSD license, at your option. * * a) This library is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301 USA * * Alternatively, * * b) Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * 1. Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #ifdef __CHECKER__ -#define __force __attribute__((force)) -#define __bitwise __attribute__((bitwise)) +#define FDT_FORCE __attribute__((force)) +#define FDT_BITWISE __attribute__((bitwise)) #else -#define __force -#define __bitwise +#define FDT_FORCE +#define FDT_BITWISE #endif -typedef uint16_t __bitwise fdt16_t; -typedef uint32_t __bitwise fdt32_t; -typedef uint64_t __bitwise fdt64_t; +typedef uint16_t FDT_BITWISE fdt16_t; +typedef uint32_t FDT_BITWISE fdt32_t; +typedef uint64_t FDT_BITWISE fdt64_t; #define EXTRACT_BYTE(x, n) ((unsigned long long)((uint8_t *)&x)[n]) #define CPU_TO_FDT16(x) ((EXTRACT_BYTE(x, 0) << 8) | EXTRACT_BYTE(x, 1)) #define CPU_TO_FDT32(x) ((EXTRACT_BYTE(x, 0) << 24) | (EXTRACT_BYTE(x, 1) << 16) | \ (EXTRACT_BYTE(x, 2) << 8) | EXTRACT_BYTE(x, 3)) #define CPU_TO_FDT64(x) ((EXTRACT_BYTE(x, 0) << 56) | (EXTRACT_BYTE(x, 1) << 48) | \ (EXTRACT_BYTE(x, 2) << 40) | (EXTRACT_BYTE(x, 3) << 32) | \ (EXTRACT_BYTE(x, 4) << 24) | (EXTRACT_BYTE(x, 5) << 16) | \ (EXTRACT_BYTE(x, 6) << 8) | EXTRACT_BYTE(x, 7)) static inline uint16_t fdt16_to_cpu(fdt16_t x) { - return (__force uint16_t)CPU_TO_FDT16(x); + return (FDT_FORCE uint16_t)CPU_TO_FDT16(x); } static inline fdt16_t cpu_to_fdt16(uint16_t x) { - return (__force fdt16_t)CPU_TO_FDT16(x); + return (FDT_FORCE fdt16_t)CPU_TO_FDT16(x); } static inline uint32_t fdt32_to_cpu(fdt32_t x) { - return (__force uint32_t)CPU_TO_FDT32(x); + return (FDT_FORCE uint32_t)CPU_TO_FDT32(x); } static inline fdt32_t cpu_to_fdt32(uint32_t x) { - return (__force fdt32_t)CPU_TO_FDT32(x); + return (FDT_FORCE fdt32_t)CPU_TO_FDT32(x); } static inline uint64_t fdt64_to_cpu(fdt64_t x) { - return (__force uint64_t)CPU_TO_FDT64(x); + return (FDT_FORCE uint64_t)CPU_TO_FDT64(x); } static inline fdt64_t cpu_to_fdt64(uint64_t x) { - return (__force fdt64_t)CPU_TO_FDT64(x); + return (FDT_FORCE fdt64_t)CPU_TO_FDT64(x); } #undef CPU_TO_FDT64 #undef CPU_TO_FDT32 #undef CPU_TO_FDT16 #undef EXTRACT_BYTE -#endif /* _LIBFDT_ENV_H */ +#ifdef __APPLE__ +#include + +/* strnlen() is not available on Mac OS < 10.7 */ +# if !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED < \ + MAC_OS_X_VERSION_10_7) + +#define strnlen fdt_strnlen + +/* + * fdt_strnlen: returns the length of a string or max_count - which ever is + * smallest. + * Input 1 string: the string whose size is to be determined + * Input 2 max_count: the maximum value returned by this function + * Output: length of the string or max_count (the smallest of the two) + */ +static inline size_t fdt_strnlen(const char *string, size_t max_count) +{ + const char *p = memchr(string, 0, max_count); + return p ? p - string : max_count; +} + +#endif /* !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED < + MAC_OS_X_VERSION_10_7) */ + +#endif /* __APPLE__ */ + +#endif /* LIBFDT_ENV_H */ Index: vendor/dtc/dist/libfdt/libfdt_internal.h =================================================================== --- vendor/dtc/dist/libfdt/libfdt_internal.h (revision 327892) +++ vendor/dtc/dist/libfdt/libfdt_internal.h (revision 327893) @@ -1,95 +1,95 @@ -#ifndef _LIBFDT_INTERNAL_H -#define _LIBFDT_INTERNAL_H +#ifndef LIBFDT_INTERNAL_H +#define LIBFDT_INTERNAL_H /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. * * libfdt is dual licensed: you can use it either under the terms of * the GPL, or the BSD license, at your option. * * a) This library is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301 USA * * Alternatively, * * b) Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * 1. Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) #define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE)) #define FDT_CHECK_HEADER(fdt) \ { \ - int __err; \ - if ((__err = fdt_check_header(fdt)) != 0) \ - return __err; \ + int err_; \ + if ((err_ = fdt_check_header(fdt)) != 0) \ + return err_; \ } -int _fdt_check_node_offset(const void *fdt, int offset); -int _fdt_check_prop_offset(const void *fdt, int offset); -const char *_fdt_find_string(const char *strtab, int tabsize, const char *s); -int _fdt_node_end_offset(void *fdt, int nodeoffset); +int fdt_check_node_offset_(const void *fdt, int offset); +int fdt_check_prop_offset_(const void *fdt, int offset); +const char *fdt_find_string_(const char *strtab, int tabsize, const char *s); +int fdt_node_end_offset_(void *fdt, int nodeoffset); -static inline const void *_fdt_offset_ptr(const void *fdt, int offset) +static inline const void *fdt_offset_ptr_(const void *fdt, int offset) { return (const char *)fdt + fdt_off_dt_struct(fdt) + offset; } -static inline void *_fdt_offset_ptr_w(void *fdt, int offset) +static inline void *fdt_offset_ptr_w_(void *fdt, int offset) { - return (void *)(uintptr_t)_fdt_offset_ptr(fdt, offset); + return (void *)(uintptr_t)fdt_offset_ptr_(fdt, offset); } -static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n) +static inline const struct fdt_reserve_entry *fdt_mem_rsv_(const void *fdt, int n) { const struct fdt_reserve_entry *rsv_table = (const struct fdt_reserve_entry *) ((const char *)fdt + fdt_off_mem_rsvmap(fdt)); return rsv_table + n; } -static inline struct fdt_reserve_entry *_fdt_mem_rsv_w(void *fdt, int n) +static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n) { - return (void *)(uintptr_t)_fdt_mem_rsv(fdt, n); + return (void *)(uintptr_t)fdt_mem_rsv_(fdt, n); } #define FDT_SW_MAGIC (~FDT_MAGIC) -#endif /* _LIBFDT_INTERNAL_H */ +#endif /* LIBFDT_INTERNAL_H */ Index: vendor/dtc/dist/libfdt/version.lds =================================================================== --- vendor/dtc/dist/libfdt/version.lds (revision 327892) +++ vendor/dtc/dist/libfdt/version.lds (revision 327893) @@ -1,68 +1,71 @@ LIBFDT_1.2 { global: fdt_next_node; fdt_check_header; fdt_move; fdt_string; fdt_num_mem_rsv; fdt_get_mem_rsv; fdt_subnode_offset_namelen; fdt_subnode_offset; fdt_path_offset_namelen; fdt_path_offset; fdt_get_name; fdt_get_property_namelen; fdt_get_property; fdt_getprop_namelen; fdt_getprop; fdt_get_phandle; fdt_get_alias_namelen; fdt_get_alias; fdt_get_path; fdt_supernode_atdepth_offset; fdt_node_depth; fdt_parent_offset; fdt_node_offset_by_prop_value; fdt_node_offset_by_phandle; fdt_node_check_compatible; fdt_node_offset_by_compatible; fdt_setprop_inplace; fdt_nop_property; fdt_nop_node; fdt_create; fdt_add_reservemap_entry; fdt_finish_reservemap; fdt_begin_node; fdt_property; fdt_end_node; fdt_finish; fdt_open_into; fdt_pack; fdt_add_mem_rsv; fdt_del_mem_rsv; fdt_set_name; fdt_setprop; fdt_delprop; fdt_add_subnode_namelen; fdt_add_subnode; fdt_del_node; fdt_strerror; fdt_offset_ptr; fdt_next_tag; fdt_appendprop; fdt_create_empty_tree; fdt_first_property_offset; fdt_get_property_by_offset; fdt_getprop_by_offset; fdt_next_property_offset; fdt_first_subnode; fdt_next_subnode; fdt_address_cells; fdt_size_cells; fdt_stringlist_contains; + fdt_stringlist_count; + fdt_stringlist_search; + fdt_stringlist_get; fdt_resize; fdt_overlay_apply; local: *; }; Index: vendor/dtc/dist/livetree.c =================================================================== --- vendor/dtc/dist/livetree.c (revision 327892) +++ vendor/dtc/dist/livetree.c (revision 327893) @@ -1,980 +1,1013 @@ /* * (C) Copyright David Gibson , IBM Corporation. 2005. * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ #include "dtc.h" /* * Tree building functions */ void add_label(struct label **labels, char *label) { struct label *new; /* Make sure the label isn't already there */ for_each_label_withdel(*labels, new) if (streq(new->label, label)) { new->deleted = 0; return; } new = xmalloc(sizeof(*new)); memset(new, 0, sizeof(*new)); new->label = label; new->next = *labels; *labels = new; } void delete_labels(struct label **labels) { struct label *label; for_each_label(*labels, label) label->deleted = 1; } struct property *build_property(char *name, struct data val) { struct property *new = xmalloc(sizeof(*new)); memset(new, 0, sizeof(*new)); new->name = name; new->val = val; return new; } struct property *build_property_delete(char *name) { struct property *new = xmalloc(sizeof(*new)); memset(new, 0, sizeof(*new)); new->name = name; new->deleted = 1; return new; } struct property *chain_property(struct property *first, struct property *list) { assert(first->next == NULL); first->next = list; return first; } struct property *reverse_properties(struct property *first) { struct property *p = first; struct property *head = NULL; struct property *next; while (p) { next = p->next; p->next = head; head = p; p = next; } return head; } struct node *build_node(struct property *proplist, struct node *children) { struct node *new = xmalloc(sizeof(*new)); struct node *child; memset(new, 0, sizeof(*new)); new->proplist = reverse_properties(proplist); new->children = children; for_each_child(new, child) { child->parent = new; } return new; } struct node *build_node_delete(void) { struct node *new = xmalloc(sizeof(*new)); memset(new, 0, sizeof(*new)); new->deleted = 1; return new; } struct node *name_node(struct node *node, char *name) { assert(node->name == NULL); node->name = name; return node; } struct node *merge_nodes(struct node *old_node, struct node *new_node) { struct property *new_prop, *old_prop; struct node *new_child, *old_child; struct label *l; old_node->deleted = 0; /* Add new node labels to old node */ for_each_label_withdel(new_node->labels, l) add_label(&old_node->labels, l->label); /* Move properties from the new node to the old node. If there * is a collision, replace the old value with the new */ while (new_node->proplist) { /* Pop the property off the list */ new_prop = new_node->proplist; new_node->proplist = new_prop->next; new_prop->next = NULL; if (new_prop->deleted) { delete_property_by_name(old_node, new_prop->name); free(new_prop); continue; } /* Look for a collision, set new value if there is */ for_each_property_withdel(old_node, old_prop) { if (streq(old_prop->name, new_prop->name)) { /* Add new labels to old property */ for_each_label_withdel(new_prop->labels, l) add_label(&old_prop->labels, l->label); old_prop->val = new_prop->val; old_prop->deleted = 0; free(new_prop); new_prop = NULL; break; } } /* if no collision occurred, add property to the old node. */ if (new_prop) add_property(old_node, new_prop); } /* Move the override child nodes into the primary node. If * there is a collision, then merge the nodes. */ while (new_node->children) { /* Pop the child node off the list */ new_child = new_node->children; new_node->children = new_child->next_sibling; new_child->parent = NULL; new_child->next_sibling = NULL; if (new_child->deleted) { delete_node_by_name(old_node, new_child->name); free(new_child); continue; } /* Search for a collision. Merge if there is */ for_each_child_withdel(old_node, old_child) { if (streq(old_child->name, new_child->name)) { merge_nodes(old_child, new_child); new_child = NULL; break; } } /* if no collision occurred, add child to the old node. */ if (new_child) add_child(old_node, new_child); } /* The new node contents are now merged into the old node. Free * the new node. */ free(new_node); return old_node; } +struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref) +{ + static unsigned int next_orphan_fragment = 0; + struct node *node; + struct property *p; + struct data d = empty_data; + char *name; + + d = data_add_marker(d, REF_PHANDLE, ref); + d = data_append_integer(d, 0xffffffff, 32); + + p = build_property("target", d); + + xasprintf(&name, "fragment@%u", + next_orphan_fragment++); + name_node(new_node, "__overlay__"); + node = build_node(p, new_node); + name_node(node, name); + + add_child(dt, node); + return dt; +} + struct node *chain_node(struct node *first, struct node *list) { assert(first->next_sibling == NULL); first->next_sibling = list; return first; } void add_property(struct node *node, struct property *prop) { struct property **p; prop->next = NULL; p = &node->proplist; while (*p) p = &((*p)->next); *p = prop; } void delete_property_by_name(struct node *node, char *name) { struct property *prop = node->proplist; while (prop) { if (streq(prop->name, name)) { delete_property(prop); return; } prop = prop->next; } } void delete_property(struct property *prop) { prop->deleted = 1; delete_labels(&prop->labels); } void add_child(struct node *parent, struct node *child) { struct node **p; child->next_sibling = NULL; child->parent = parent; p = &parent->children; while (*p) p = &((*p)->next_sibling); *p = child; } void delete_node_by_name(struct node *parent, char *name) { struct node *node = parent->children; while (node) { if (streq(node->name, name)) { delete_node(node); return; } node = node->next_sibling; } } void delete_node(struct node *node) { struct property *prop; struct node *child; node->deleted = 1; for_each_child(node, child) delete_node(child); for_each_property(node, prop) delete_property(prop); delete_labels(&node->labels); } void append_to_property(struct node *node, char *name, const void *data, int len) { struct data d; struct property *p; p = get_property(node, name); if (p) { d = data_append_data(p->val, data, len); p->val = d; } else { d = data_append_data(empty_data, data, len); p = build_property(name, d); add_property(node, p); } } struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size) { struct reserve_info *new = xmalloc(sizeof(*new)); memset(new, 0, sizeof(*new)); - new->re.address = address; - new->re.size = size; + new->address = address; + new->size = size; return new; } struct reserve_info *chain_reserve_entry(struct reserve_info *first, struct reserve_info *list) { assert(first->next == NULL); first->next = list; return first; } struct reserve_info *add_reserve_entry(struct reserve_info *list, struct reserve_info *new) { struct reserve_info *last; new->next = NULL; if (! list) return new; for (last = list; last->next; last = last->next) ; last->next = new; return list; } struct dt_info *build_dt_info(unsigned int dtsflags, struct reserve_info *reservelist, struct node *tree, uint32_t boot_cpuid_phys) { struct dt_info *dti; dti = xmalloc(sizeof(*dti)); dti->dtsflags = dtsflags; dti->reservelist = reservelist; dti->dt = tree; dti->boot_cpuid_phys = boot_cpuid_phys; return dti; } /* * Tree accessor functions */ const char *get_unitname(struct node *node) { if (node->name[node->basenamelen] == '\0') return ""; else return node->name + node->basenamelen + 1; } struct property *get_property(struct node *node, const char *propname) { struct property *prop; for_each_property(node, prop) if (streq(prop->name, propname)) return prop; return NULL; } cell_t propval_cell(struct property *prop) { assert(prop->val.len == sizeof(cell_t)); - return fdt32_to_cpu(*((cell_t *)prop->val.val)); + return fdt32_to_cpu(*((fdt32_t *)prop->val.val)); } +cell_t propval_cell_n(struct property *prop, int n) +{ + assert(prop->val.len / sizeof(cell_t) >= n); + return fdt32_to_cpu(*((fdt32_t *)prop->val.val + n)); +} + struct property *get_property_by_label(struct node *tree, const char *label, struct node **node) { struct property *prop; struct node *c; *node = tree; for_each_property(tree, prop) { struct label *l; for_each_label(prop->labels, l) if (streq(l->label, label)) return prop; } for_each_child(tree, c) { prop = get_property_by_label(c, label, node); if (prop) return prop; } *node = NULL; return NULL; } struct marker *get_marker_label(struct node *tree, const char *label, struct node **node, struct property **prop) { struct marker *m; struct property *p; struct node *c; *node = tree; for_each_property(tree, p) { *prop = p; m = p->val.markers; for_each_marker_of_type(m, LABEL) if (streq(m->ref, label)) return m; } for_each_child(tree, c) { m = get_marker_label(c, label, node, prop); if (m) return m; } *prop = NULL; *node = NULL; return NULL; } struct node *get_subnode(struct node *node, const char *nodename) { struct node *child; for_each_child(node, child) if (streq(child->name, nodename)) return child; return NULL; } struct node *get_node_by_path(struct node *tree, const char *path) { const char *p; struct node *child; if (!path || ! (*path)) { if (tree->deleted) return NULL; return tree; } while (path[0] == '/') path++; p = strchr(path, '/'); for_each_child(tree, child) { - if (p && strneq(path, child->name, p-path)) + if (p && (strlen(child->name) == p-path) && + strprefixeq(path, p - path, child->name)) return get_node_by_path(child, p+1); else if (!p && streq(path, child->name)) return child; } return NULL; } struct node *get_node_by_label(struct node *tree, const char *label) { struct node *child, *node; struct label *l; assert(label && (strlen(label) > 0)); for_each_label(tree->labels, l) if (streq(l->label, label)) return tree; for_each_child(tree, child) { node = get_node_by_label(child, label); if (node) return node; } return NULL; } struct node *get_node_by_phandle(struct node *tree, cell_t phandle) { struct node *child, *node; - assert((phandle != 0) && (phandle != -1)); + if ((phandle == 0) || (phandle == -1)) { + assert(generate_fixups); + return NULL; + } if (tree->phandle == phandle) { if (tree->deleted) return NULL; return tree; } for_each_child(tree, child) { node = get_node_by_phandle(child, phandle); if (node) return node; } return NULL; } struct node *get_node_by_ref(struct node *tree, const char *ref) { if (streq(ref, "/")) return tree; else if (ref[0] == '/') return get_node_by_path(tree, ref); else return get_node_by_label(tree, ref); } cell_t get_node_phandle(struct node *root, struct node *node) { static cell_t phandle = 1; /* FIXME: ick, static local */ if ((node->phandle != 0) && (node->phandle != -1)) return node->phandle; while (get_node_by_phandle(root, phandle)) phandle++; node->phandle = phandle; if (!get_property(node, "linux,phandle") && (phandle_format & PHANDLE_LEGACY)) add_property(node, build_property("linux,phandle", data_append_cell(empty_data, phandle))); if (!get_property(node, "phandle") && (phandle_format & PHANDLE_EPAPR)) add_property(node, build_property("phandle", data_append_cell(empty_data, phandle))); /* If the node *does* have a phandle property, we must * be dealing with a self-referencing phandle, which will be * fixed up momentarily in the caller */ return node->phandle; } uint32_t guess_boot_cpuid(struct node *tree) { struct node *cpus, *bootcpu; struct property *reg; cpus = get_node_by_path(tree, "/cpus"); if (!cpus) return 0; bootcpu = cpus->children; if (!bootcpu) return 0; reg = get_property(bootcpu, "reg"); if (!reg || (reg->val.len != sizeof(uint32_t))) return 0; /* FIXME: Sanity check node? */ return propval_cell(reg); } static int cmp_reserve_info(const void *ax, const void *bx) { const struct reserve_info *a, *b; a = *((const struct reserve_info * const *)ax); b = *((const struct reserve_info * const *)bx); - if (a->re.address < b->re.address) + if (a->address < b->address) return -1; - else if (a->re.address > b->re.address) + else if (a->address > b->address) return 1; - else if (a->re.size < b->re.size) + else if (a->size < b->size) return -1; - else if (a->re.size > b->re.size) + else if (a->size > b->size) return 1; else return 0; } static void sort_reserve_entries(struct dt_info *dti) { struct reserve_info *ri, **tbl; int n = 0, i = 0; for (ri = dti->reservelist; ri; ri = ri->next) n++; if (n == 0) return; tbl = xmalloc(n * sizeof(*tbl)); for (ri = dti->reservelist; ri; ri = ri->next) tbl[i++] = ri; qsort(tbl, n, sizeof(*tbl), cmp_reserve_info); dti->reservelist = tbl[0]; for (i = 0; i < (n-1); i++) tbl[i]->next = tbl[i+1]; tbl[n-1]->next = NULL; free(tbl); } static int cmp_prop(const void *ax, const void *bx) { const struct property *a, *b; a = *((const struct property * const *)ax); b = *((const struct property * const *)bx); return strcmp(a->name, b->name); } static void sort_properties(struct node *node) { int n = 0, i = 0; struct property *prop, **tbl; for_each_property_withdel(node, prop) n++; if (n == 0) return; tbl = xmalloc(n * sizeof(*tbl)); for_each_property_withdel(node, prop) tbl[i++] = prop; qsort(tbl, n, sizeof(*tbl), cmp_prop); node->proplist = tbl[0]; for (i = 0; i < (n-1); i++) tbl[i]->next = tbl[i+1]; tbl[n-1]->next = NULL; free(tbl); } static int cmp_subnode(const void *ax, const void *bx) { const struct node *a, *b; a = *((const struct node * const *)ax); b = *((const struct node * const *)bx); return strcmp(a->name, b->name); } static void sort_subnodes(struct node *node) { int n = 0, i = 0; struct node *subnode, **tbl; for_each_child_withdel(node, subnode) n++; if (n == 0) return; tbl = xmalloc(n * sizeof(*tbl)); for_each_child_withdel(node, subnode) tbl[i++] = subnode; qsort(tbl, n, sizeof(*tbl), cmp_subnode); node->children = tbl[0]; for (i = 0; i < (n-1); i++) tbl[i]->next_sibling = tbl[i+1]; tbl[n-1]->next_sibling = NULL; free(tbl); } static void sort_node(struct node *node) { struct node *c; sort_properties(node); sort_subnodes(node); for_each_child_withdel(node, c) sort_node(c); } void sort_tree(struct dt_info *dti) { sort_reserve_entries(dti); sort_node(dti->dt); } /* utility helper to avoid code duplication */ static struct node *build_and_name_child_node(struct node *parent, char *name) { struct node *node; node = build_node(NULL, NULL); name_node(node, xstrdup(name)); add_child(parent, node); return node; } static struct node *build_root_node(struct node *dt, char *name) { struct node *an; an = get_subnode(dt, name); if (!an) an = build_and_name_child_node(dt, name); if (!an) die("Could not build root node /%s\n", name); return an; } static bool any_label_tree(struct dt_info *dti, struct node *node) { struct node *c; if (node->labels) return true; for_each_child(node, c) if (any_label_tree(dti, c)) return true; return false; } static void generate_label_tree_internal(struct dt_info *dti, struct node *an, struct node *node, bool allocph) { struct node *dt = dti->dt; struct node *c; struct property *p; struct label *l; /* if there are labels */ if (node->labels) { /* now add the label in the node */ for_each_label(node->labels, l) { /* check whether the label already exists */ p = get_property(an, l->label); if (p) { fprintf(stderr, "WARNING: label %s already" " exists in /%s", l->label, an->name); continue; } /* insert it */ p = build_property(l->label, data_copy_mem(node->fullpath, strlen(node->fullpath) + 1)); add_property(an, p); } /* force allocation of a phandle for this node */ if (allocph) (void)get_node_phandle(dt, node); } for_each_child(node, c) generate_label_tree_internal(dti, an, c, allocph); } static bool any_fixup_tree(struct dt_info *dti, struct node *node) { struct node *c; struct property *prop; struct marker *m; for_each_property(node, prop) { m = prop->val.markers; for_each_marker_of_type(m, REF_PHANDLE) { if (!get_node_by_ref(dti->dt, m->ref)) return true; } } for_each_child(node, c) { if (any_fixup_tree(dti, c)) return true; } return false; } static void add_fixup_entry(struct dt_info *dti, struct node *fn, struct node *node, struct property *prop, struct marker *m) { char *entry; /* m->ref can only be a REF_PHANDLE, but check anyway */ assert(m->type == REF_PHANDLE); /* there shouldn't be any ':' in the arguments */ if (strchr(node->fullpath, ':') || strchr(prop->name, ':')) die("arguments should not contain ':'\n"); xasprintf(&entry, "%s:%s:%u", node->fullpath, prop->name, m->offset); append_to_property(fn, m->ref, entry, strlen(entry) + 1); free(entry); } static void generate_fixups_tree_internal(struct dt_info *dti, struct node *fn, struct node *node) { struct node *dt = dti->dt; struct node *c; struct property *prop; struct marker *m; struct node *refnode; for_each_property(node, prop) { m = prop->val.markers; for_each_marker_of_type(m, REF_PHANDLE) { refnode = get_node_by_ref(dt, m->ref); if (!refnode) add_fixup_entry(dti, fn, node, prop, m); } } for_each_child(node, c) generate_fixups_tree_internal(dti, fn, c); } static bool any_local_fixup_tree(struct dt_info *dti, struct node *node) { struct node *c; struct property *prop; struct marker *m; for_each_property(node, prop) { m = prop->val.markers; for_each_marker_of_type(m, REF_PHANDLE) { if (get_node_by_ref(dti->dt, m->ref)) return true; } } for_each_child(node, c) { if (any_local_fixup_tree(dti, c)) return true; } return false; } static void add_local_fixup_entry(struct dt_info *dti, struct node *lfn, struct node *node, struct property *prop, struct marker *m, struct node *refnode) { struct node *wn, *nwn; /* local fixup node, walk node, new */ - uint32_t value_32; + fdt32_t value_32; char **compp; int i, depth; /* walk back retreiving depth */ depth = 0; for (wn = node; wn; wn = wn->parent) depth++; /* allocate name array */ compp = xmalloc(sizeof(*compp) * depth); /* store names in the array */ for (wn = node, i = depth - 1; wn; wn = wn->parent, i--) compp[i] = wn->name; /* walk the path components creating nodes if they don't exist */ for (wn = lfn, i = 1; i < depth; i++, wn = nwn) { /* if no node exists, create it */ nwn = get_subnode(wn, compp[i]); if (!nwn) nwn = build_and_name_child_node(wn, compp[i]); } free(compp); value_32 = cpu_to_fdt32(m->offset); append_to_property(wn, prop->name, &value_32, sizeof(value_32)); } static void generate_local_fixups_tree_internal(struct dt_info *dti, struct node *lfn, struct node *node) { struct node *dt = dti->dt; struct node *c; struct property *prop; struct marker *m; struct node *refnode; for_each_property(node, prop) { m = prop->val.markers; for_each_marker_of_type(m, REF_PHANDLE) { refnode = get_node_by_ref(dt, m->ref); if (refnode) add_local_fixup_entry(dti, lfn, node, prop, m, refnode); } } for_each_child(node, c) generate_local_fixups_tree_internal(dti, lfn, c); } void generate_label_tree(struct dt_info *dti, char *name, bool allocph) { if (!any_label_tree(dti, dti->dt)) return; generate_label_tree_internal(dti, build_root_node(dti->dt, name), dti->dt, allocph); } void generate_fixups_tree(struct dt_info *dti, char *name) { if (!any_fixup_tree(dti, dti->dt)) return; generate_fixups_tree_internal(dti, build_root_node(dti->dt, name), dti->dt); } void generate_local_fixups_tree(struct dt_info *dti, char *name) { if (!any_local_fixup_tree(dti, dti->dt)) return; generate_local_fixups_tree_internal(dti, build_root_node(dti->dt, name), dti->dt); } Index: vendor/dtc/dist/pylibfdt/Makefile.pylibfdt =================================================================== --- vendor/dtc/dist/pylibfdt/Makefile.pylibfdt (nonexistent) +++ vendor/dtc/dist/pylibfdt/Makefile.pylibfdt (revision 327893) @@ -0,0 +1,24 @@ +# Makefile.pylibfdt +# + +PYLIBFDT_srcs = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_SRCS)) \ + $(PYLIBFDT_srcdir)/libfdt.i +PYMODULE = $(PYLIBFDT_objdir)/_libfdt.so + +define run_setup + SOURCES="$(1)" CPPFLAGS="$(CPPFLAGS)" OBJDIR="$(PYLIBFDT_objdir)" + VERSION="$(dtc_version)" + $(PYLIBFDT_objdir)/setup.py --quiet $(2) +endef + +$(PYMODULE): $(PYLIBFDT_srcs) + @$(VECHO) PYMOD $@ + $(call run_setup, $^, build_ext --inplace) + mv _libfdt.so $@ + +install_pylibfdt: $(PYMODULE) + $(VECHO) INSTALL-PYLIB; \ + $(call run_setup, $(PYLIBFDT_srcs), \ + install $(if $(SETUP_PREFIX),--prefix=$(SETUP_PREFIX))) + +PYLIBFDT_cleanfiles = libfdt_wrap.c libfdt.py libfdt.pyc _libfdt.so Property changes on: vendor/dtc/dist/pylibfdt/Makefile.pylibfdt ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/dtc/dist/pylibfdt/libfdt.i =================================================================== --- vendor/dtc/dist/pylibfdt/libfdt.i (nonexistent) +++ vendor/dtc/dist/pylibfdt/libfdt.i (revision 327893) @@ -0,0 +1,493 @@ +/* + * pylibfdt - Flat Device Tree manipulation in Python + * Copyright (C) 2017 Google, Inc. + * Written by Simon Glass + * + * libfdt is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * + * a) This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * Alternatively, + * + * b) Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +%module libfdt + +%include + +%{ +#define SWIG_FILE_WITH_INIT +#include "libfdt.h" +%} + +%pythoncode %{ + +import struct + +# Error codes, corresponding to FDT_ERR_... in libfdt.h +(NOTFOUND, + EXISTS, + NOSPACE, + BADOFFSET, + BADPATH, + BADPHANDLE, + BADSTATE, + TRUNCATED, + BADMAGIC, + BADVERSION, + BADSTRUCTURE, + BADLAYOUT, + INTERNAL, + BADNCELLS, + BADVALUE, + BADOVERLAY, + NOPHANDLES) = QUIET_ALL = range(1, 18) +# QUIET_ALL can be passed as the 'quiet' parameter to avoid exceptions +# altogether. All # functions passed this value will return an error instead +# of raising an exception. + +# Pass this as the 'quiet' parameter to return -ENOTFOUND on NOTFOUND errors, +# instead of raising an exception. +QUIET_NOTFOUND = (NOTFOUND,) + + +class FdtException(Exception): + """An exception caused by an error such as one of the codes above""" + def __init__(self, err): + self.err = err + + def __str__(self): + return 'pylibfdt error %d: %s' % (self.err, fdt_strerror(self.err)) + +def strerror(fdt_err): + """Get the string for an error number + + Args: + fdt_err: Error number (-ve) + + Returns: + String containing the associated error + """ + return fdt_strerror(fdt_err) + +def check_err(val, quiet=()): + """Raise an error if the return value is -ve + + This is used to check for errors returned by libfdt C functions. + + Args: + val: Return value from a libfdt function + quiet: Errors to ignore (empty to raise on all errors) + + Returns: + val if val >= 0 + + Raises + FdtException if val < 0 + """ + if val < 0: + if -val not in quiet: + raise FdtException(val) + return val + +def check_err_null(val, quiet=()): + """Raise an error if the return value is NULL + + This is used to check for a NULL return value from certain libfdt C + functions + + Args: + val: Return value from a libfdt function + quiet: Errors to ignore (empty to raise on all errors) + + Returns: + val if val is a list, None if not + + Raises + FdtException if val indicates an error was reported and the error + is not in @quiet. + """ + # Normally a list is returned which contains the data and its length. + # If we get just an integer error code, it means the function failed. + if not isinstance(val, list): + if -val not in quiet: + raise FdtException(val) + return val + +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: + + 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): + self._fdt = bytearray(data) + check_err(fdt_check_header(self._fdt)); + + def subnode_offset(self, parentoffset, name, quiet=()): + """Get the offset of a named subnode + + Args: + parentoffset: Offset of the parent node to check + name: Name of the required subnode, e.g. 'subnode@1' + quiet: Errors to ignore (empty to raise on all errors) + + Returns: + The node offset of the found node, if any + + Raises + FdtException if there is no node with that name, or other error + """ + return check_err(fdt_subnode_offset(self._fdt, parentoffset, name), + quiet) + + def path_offset(self, path, quiet=()): + """Get the offset for a given path + + Args: + path: Path to the required node, e.g. '/node@3/subnode@1' + quiet: Errors to ignore (empty to raise on all errors) + + Returns: + Node offset + + Raises + FdtException if the path is not valid or not found + """ + return check_err(fdt_path_offset(self._fdt, path), quiet) + + def first_property_offset(self, nodeoffset, quiet=()): + """Get the offset of the first property in a node offset + + Args: + nodeoffset: Offset to the node to check + quiet: Errors to ignore (empty to raise on all errors) + + Returns: + Offset of the first property + + Raises + FdtException if the associated node has no properties, or some + other error occurred + """ + return check_err(fdt_first_property_offset(self._fdt, nodeoffset), + quiet) + + def next_property_offset(self, prop_offset, quiet=()): + """Get the next property in a node + + Args: + prop_offset: Offset of the previous property + quiet: Errors to ignore (empty to raise on all errors) + + Returns: + Offset of the next property + + Raises: + FdtException if the associated node has no more properties, or + some other error occurred + """ + return check_err(fdt_next_property_offset(self._fdt, prop_offset), + quiet) + + def get_name(self, nodeoffset): + """Get the name of a node + + Args: + nodeoffset: Offset of node to check + + Returns: + Node name + + Raises: + FdtException on error (e.g. nodeoffset is invalid) + """ + return check_err_null(fdt_get_name(self._fdt, nodeoffset))[0] + + def get_property_by_offset(self, prop_offset, quiet=()): + """Obtains a property that can be examined + + Args: + prop_offset: Offset of property (e.g. from first_property_offset()) + quiet: Errors to ignore (empty to raise on all errors) + + Returns: + Property object, or None if not found + + Raises: + FdtException on error (e.g. invalid prop_offset or device + tree format) + """ + pdata = check_err_null( + fdt_get_property_by_offset(self._fdt, prop_offset), quiet) + if isinstance(pdata, (int)): + return pdata + return Property(pdata[0], pdata[1]) + + def first_subnode(self, nodeoffset, quiet=()): + """Find the first subnode of a parent node + + Args: + nodeoffset: Node offset of parent node + quiet: Errors to ignore (empty to raise on all errors) + + Returns: + The offset of the first subnode, if any + + Raises: + FdtException if no subnode found or other error occurs + """ + return check_err(fdt_first_subnode(self._fdt, nodeoffset), quiet) + + def next_subnode(self, nodeoffset, quiet=()): + """Find the next subnode + + Args: + nodeoffset: Node offset of previous subnode + quiet: Errors to ignore (empty to raise on all errors) + + Returns: + The offset of the next subnode, if any + + Raises: + FdtException if no more subnode found or other error occurs + """ + return check_err(fdt_next_subnode(self._fdt, nodeoffset), quiet) + + def totalsize(self): + """Return the total size of the device tree + + Returns: + Total tree size in bytes + """ + return check_err(fdt_totalsize(self._fdt)) + + def off_dt_struct(self): + """Return the start of the device tree struct area + + Returns: + Start offset of struct area + """ + return check_err(fdt_off_dt_struct(self._fdt)) + + def pack(self, quiet=()): + """Pack the device tree to remove unused space + + This adjusts the tree in place. + + Args: + quiet: Errors to ignore (empty to raise on all errors) + + Raises: + FdtException if any error occurs + """ + return check_err(fdt_pack(self._fdt), quiet) + + def delprop(self, nodeoffset, prop_name): + """Delete a property from a node + + Args: + nodeoffset: Node offset containing property to delete + prop_name: Name of property to delete + + Raises: + FdtError if the property does not exist, or another error occurs + """ + return check_err(fdt_delprop(self._fdt, nodeoffset, prop_name)) + + 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 bytearray, 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 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 Property: + """Holds a device tree property name and value. + + This holds a copy of a property taken from the device tree. It does not + reference the device tree, so if anything changes in the device tree, + a Property object will remain valid. + + Properties: + name: Property name + value: Proper value as a bytearray + """ + def __init__(self, name, value): + self.name = name + self.value = value +%} + +%rename(fdt_property) fdt_property_func; + +typedef int fdt32_t; + +%include "libfdt/fdt.h" + +%include "typemaps.i" + +/* Most functions don't change the device tree, so use a const void * */ +%typemap(in) (const void *)(const void *fdt) { + if (!PyByteArray_Check($input)) { + SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname" + "', argument " "$argnum"" of type '" "$type""'"); + } + $1 = (void *)PyByteArray_AsString($input); + fdt = $1; + fdt = fdt; /* avoid unused variable warning */ +} + +/* Some functions do change the device tree, so use void * */ +%typemap(in) (void *)(const void *fdt) { + if (!PyByteArray_Check($input)) { + SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname" + "', argument " "$argnum"" of type '" "$type""'"); + } + $1 = PyByteArray_AsString($input); + fdt = $1; + fdt = fdt; /* avoid unused variable warning */ +} + +%typemap(out) (struct fdt_property *) { + PyObject *buff; + + if ($1) { + resultobj = PyString_FromString( + fdt_string(fdt1, fdt32_to_cpu($1->nameoff))); + buff = PyByteArray_FromStringAndSize( + (const char *)($1 + 1), fdt32_to_cpu($1->len)); + resultobj = SWIG_Python_AppendOutput(resultobj, buff); + } +} + +%apply int *OUTPUT { int *lenp }; + +/* typemap used for fdt_getprop() */ +%typemap(out) (const void *) { + if (!$1) + $result = Py_None; + else + $result = Py_BuildValue("s#", $1, *arg4); +} + +/* We have both struct fdt_property and a function fdt_property() */ +%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); + +%include <../libfdt/libfdt.h> Index: vendor/dtc/dist/pylibfdt/setup.py =================================================================== --- vendor/dtc/dist/pylibfdt/setup.py (nonexistent) +++ vendor/dtc/dist/pylibfdt/setup.py (revision 327893) @@ -0,0 +1,121 @@ +#!/usr/bin/env python2 + +""" +setup.py file for SWIG libfdt +Copyright (C) 2017 Google, Inc. +Written by Simon Glass + +Files to be built into the extension are provided in SOURCES +C flags to use are provided in CPPFLAGS +Object file directory is provided in OBJDIR +Version is provided in VERSION + +If these variables are not given they are parsed from the Makefiles. This +allows this script to be run stand-alone, e.g.: + + ./pylibfdt/setup.py install [--prefix=...] +""" + +from distutils.core import setup, Extension +import os +import re +import sys + +# Decodes a Makefile assignment line into key and value (and plus for +=) +RE_KEY_VALUE = re.compile('(?P\w+) *(?P[+])?= *(?P.*)$') + + +def ParseMakefile(fname): + """Parse a Makefile to obtain its variables. + + This collects variable assigments of the form: + + VAR = value + VAR += more + + It does not pick out := assignments, as these are not needed here. It does + handle line continuation. + + Returns a dict: + key: Variable name (e.g. 'VAR') + value: Variable value (e.g. 'value more') + """ + makevars = {} + with open(fname) as fd: + prev_text = '' # Continuation text from previous line(s) + for line in fd.read().splitlines(): + if line and line[-1] == '\\': # Deal with line continuation + prev_text += line[:-1] + continue + elif prev_text: + line = prev_text + line + prev_text = '' # Continuation is now used up + m = RE_KEY_VALUE.match(line) + if m: + value = m.group('value') or '' + key = m.group('key') + + # Appending to a variable inserts a space beforehand + if 'plus' in m.groupdict() and key in makevars: + makevars[key] += ' ' + value + else: + makevars[key] = value + return makevars + +def GetEnvFromMakefiles(): + """Scan the Makefiles to obtain the settings we need. + + This assumes that this script is being run from the top-level directory, + not the pylibfdt directory. + + Returns: + Tuple with: + List of swig options + Version string + List of files to build + List of extra C preprocessor flags needed + Object directory to use (always '') + """ + basedir = os.path.dirname(os.path.dirname(os.path.abspath(sys.argv[0]))) + swig_opts = ['-I%s' % basedir] + makevars = ParseMakefile(os.path.join(basedir, 'Makefile')) + version = '%s.%s.%s' % (makevars['VERSION'], makevars['PATCHLEVEL'], + makevars['SUBLEVEL']) + makevars = ParseMakefile(os.path.join(basedir, 'libfdt', 'Makefile.libfdt')) + files = makevars['LIBFDT_SRCS'].split() + files = [os.path.join(basedir, 'libfdt', fname) for fname in files] + files.append('pylibfdt/libfdt.i') + cflags = ['-I%s' % basedir, '-I%s/libfdt' % basedir] + objdir = '' + return swig_opts, version, files, cflags, objdir + + +progname = sys.argv[0] +files = os.environ.get('SOURCES', '').split() +cflags = os.environ.get('CPPFLAGS', '').split() +objdir = os.environ.get('OBJDIR') +version = os.environ.get('VERSION') +swig_opts = [] + +# If we were called directly rather than through our Makefile (which is often +# the case with Python module installation), read the settings from the +# Makefile. +if not all((version, files, cflags, objdir)): + swig_opts, version, files, cflags, objdir = GetEnvFromMakefiles() + +libfdt_module = Extension( + '_libfdt', + sources = files, + extra_compile_args = cflags, + swig_opts = swig_opts, +) + +setup( + name='libfdt', + version= version, + author='Simon Glass ', + description='Python binding for libfdt', + ext_modules=[libfdt_module], + package_dir={'': objdir}, + py_modules=['pylibfdt/libfdt'], +) Property changes on: vendor/dtc/dist/pylibfdt/setup.py ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/dtc/dist/srcpos.h =================================================================== --- vendor/dtc/dist/srcpos.h (revision 327892) +++ vendor/dtc/dist/srcpos.h (revision 327893) @@ -1,118 +1,117 @@ /* * Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ -#ifndef _SRCPOS_H_ -#define _SRCPOS_H_ +#ifndef SRCPOS_H +#define SRCPOS_H #include #include +#include "util.h" struct srcfile_state { FILE *f; char *name; char *dir; int lineno, colno; struct srcfile_state *prev; }; extern FILE *depfile; /* = NULL */ extern struct srcfile_state *current_srcfile; /* = NULL */ /** * Open a source file. * * If the source file is a relative pathname, then it is searched for in the * current directory (the directory of the last source file read) and after * that in the search path. * * We work through the search path in order from the first path specified to * the last. * * If the file is not found, then this function does not return, but calls * die(). * * @param fname Filename to search * @param fullnamep If non-NULL, it is set to the allocated filename of the * file that was opened. The caller is then responsible * for freeing the pointer. * @return pointer to opened FILE */ FILE *srcfile_relative_open(const char *fname, char **fullnamep); void srcfile_push(const char *fname); bool srcfile_pop(void); /** * Add a new directory to the search path for input files * * The new path is added at the end of the list. * * @param dirname Directory to add */ void srcfile_add_search_path(const char *dirname); struct srcpos { int first_line; int first_column; int last_line; int last_column; struct srcfile_state *file; }; #define YYLTYPE struct srcpos #define YYLLOC_DEFAULT(Current, Rhs, N) \ do { \ if (N) { \ (Current).first_line = YYRHSLOC(Rhs, 1).first_line; \ (Current).first_column = YYRHSLOC(Rhs, 1).first_column; \ (Current).last_line = YYRHSLOC(Rhs, N).last_line; \ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ (Current).file = YYRHSLOC(Rhs, N).file; \ } else { \ (Current).first_line = (Current).last_line = \ YYRHSLOC(Rhs, 0).last_line; \ (Current).first_column = (Current).last_column = \ YYRHSLOC(Rhs, 0).last_column; \ (Current).file = YYRHSLOC (Rhs, 0).file; \ } \ } while (0) /* * Fictional source position used for IR nodes that are * created without otherwise knowing a true source position. * For example,constant definitions from the command line. */ extern struct srcpos srcpos_empty; extern void srcpos_update(struct srcpos *pos, const char *text, int len); extern struct srcpos *srcpos_copy(struct srcpos *pos); extern char *srcpos_string(struct srcpos *pos); -extern void srcpos_verror(struct srcpos *pos, const char *prefix, - const char *fmt, va_list va) - __attribute__((format(printf, 3, 0))); -extern void srcpos_error(struct srcpos *pos, const char *prefix, - const char *fmt, ...) - __attribute__((format(printf, 3, 4))); +extern void PRINTF(3, 0) srcpos_verror(struct srcpos *pos, const char *prefix, + const char *fmt, va_list va); +extern void PRINTF(3, 4) srcpos_error(struct srcpos *pos, const char *prefix, + const char *fmt, ...); extern void srcpos_set_line(char *f, int l); -#endif /* _SRCPOS_H_ */ +#endif /* SRCPOS_H */ Index: vendor/dtc/dist/tests/Makefile.tests =================================================================== --- vendor/dtc/dist/tests/Makefile.tests (revision 327892) +++ vendor/dtc/dist/tests/Makefile.tests (revision 327893) @@ -1,87 +1,87 @@ LIB_TESTS_L = get_mem_rsv \ root_node find_property subnode_offset path_offset \ get_name getprop get_phandle \ get_path supernode_atdepth_offset parent_offset \ node_offset_by_prop_value node_offset_by_phandle \ node_check_compatible node_offset_by_compatible \ get_alias \ char_literal \ sized_cells \ notfound \ addr_size_cells \ stringlist \ setprop_inplace nop_property nop_node \ sw_tree1 \ move_and_save mangle-layout nopulate \ open_pack rw_tree1 set_name setprop del_property del_node \ appendprop1 appendprop2 propname_escapes \ string_escapes references path-references phandle_format \ boot-cpuid incbin \ extra-terminating-null \ dtbs_equal_ordered \ dtb_reverse dtbs_equal_unordered \ add_subnode_with_nops path_offset_aliases \ utilfdt_test \ integer-expressions \ property_iterate \ subnode_iterate \ overlay overlay_bad_fixup \ check_path LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%) LIBTREE_TESTS_L = truncated_property LIBTREE_TESTS = $(LIBTREE_TESTS_L:%=$(TESTS_PREFIX)%) DL_LIB_TESTS_L = asm_tree_dump value-labels DL_LIB_TESTS = $(DL_LIB_TESTS_L:%=$(TESTS_PREFIX)%) TESTS = $(LIB_TESTS) $(LIBTREE_TESTS) $(DL_LIB_TESTS) TESTS_TREES_L = test_tree1.dtb TESTS_TREES = $(TESTS_TREES_L:%=$(TESTS_PREFIX)%) TESTS_TARGETS = $(TESTS) $(TESTS_TREES) TESTS_DEPFILES = $(TESTS:%=%.d) \ $(addprefix $(TESTS_PREFIX),testutils.d trees.d dumptrees.d) TESTS_CLEANFILES_L = *.output vglog.* vgcore.* *.dtb *.test.dts *.dtsv1 tmp.* TESTS_CLEANFILES_L += dumptrees TESTS_CLEANFILES = $(TESTS) $(TESTS_CLEANFILES_L:%=$(TESTS_PREFIX)%) .PHONY: tests tests: $(TESTS) $(TESTS_TREES) $(LIB_TESTS): %: $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_archive) $(DL_LIB_TESTS): %: %.o $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_archive) @$(VECHO) LD [libdl] $@ $(LINK.c) -o $@ $^ -ldl $(LIBTREE_TESTS): %: $(TESTS_PREFIX)testutils.o $(TESTS_PREFIX)trees.o \ util.o $(LIBFDT_archive) $(TESTS_PREFIX)dumptrees: $(TESTS_PREFIX)trees.o $(TESTS_TREES): $(TESTS_PREFIX)dumptrees @$(VECHO) DUMPTREES cd $(TESTS_PREFIX); ./dumptrees >/dev/null tests_clean: @$(VECHO) CLEAN "(tests)" rm -f $(STD_CLEANFILES:%=$(TESTS_PREFIX)%) rm -f $(TESTS_CLEANFILES) -check: tests ${TESTS_BIN} +check: tests ${TESTS_BIN} $(TESTS_PYLIBFDT) cd $(TESTS_PREFIX); ./run_tests.sh -checkm: tests ${TESTS_BIN} +checkm: tests ${TESTS_BIN} $(TESTS_PYLIBFDT) cd $(TESTS_PREFIX); ./run_tests.sh -m 2>&1 | tee vglog.$$$$ -checkv: tests ${TESTS_BIN} +checkv: tests ${TESTS_BIN} $(TESTS_PYLIBFDT) cd $(TESTS_PREFIX); ./run_tests.sh -v ifneq ($(DEPTARGETS),) -include $(TESTS_DEPFILES) endif Index: vendor/dtc/dist/tests/bad-chosen.dts =================================================================== --- vendor/dtc/dist/tests/bad-chosen.dts (nonexistent) +++ vendor/dtc/dist/tests/bad-chosen.dts (revision 327893) @@ -0,0 +1,10 @@ +/dts-v1/; + +/ { + node2 { + chosen { + bootargs = <0xdeadbeef>; + stdout-path = <1>; + }; + }; +}; Property changes on: vendor/dtc/dist/tests/bad-chosen.dts ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/dtc/dist/tests/bad-gpio.dts =================================================================== --- vendor/dtc/dist/tests/bad-gpio.dts (nonexistent) +++ vendor/dtc/dist/tests/bad-gpio.dts (revision 327893) @@ -0,0 +1,13 @@ +/dts-v1/; + +/ { + gpio: gpio-controller { + #gpio-cells = <3>; + }; + + node { + nr-gpios = <1>; + foo-gpios = <&gpio>; + bar-gpio = <&gpio 1 2 3>; + }; +}; Property changes on: vendor/dtc/dist/tests/bad-gpio.dts ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/dtc/dist/tests/bad-interrupt-cells.dts =================================================================== --- vendor/dtc/dist/tests/bad-interrupt-cells.dts (nonexistent) +++ vendor/dtc/dist/tests/bad-interrupt-cells.dts (revision 327893) @@ -0,0 +1,12 @@ +/dts-v1/; + +/ { + interrupt-parent = <&intc>; + intc: interrupt-controller { + #interrupt-cells = <3>; + }; + + node { + interrupts = <1>; + }; +}; Property changes on: vendor/dtc/dist/tests/bad-interrupt-cells.dts ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/dtc/dist/tests/bad-phandle-cells.dts =================================================================== --- vendor/dtc/dist/tests/bad-phandle-cells.dts (nonexistent) +++ vendor/dtc/dist/tests/bad-phandle-cells.dts (revision 327893) @@ -0,0 +1,11 @@ +/dts-v1/; + +/ { + intc: interrupt-controller { + #interrupt-cells = <3>; + }; + + node { + interrupts-extended = <&intc>; + }; +}; Property changes on: vendor/dtc/dist/tests/bad-phandle-cells.dts ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/dtc/dist/tests/bad-string-props.dts =================================================================== --- vendor/dtc/dist/tests/bad-string-props.dts (revision 327892) +++ vendor/dtc/dist/tests/bad-string-props.dts (revision 327893) @@ -1,7 +1,14 @@ /dts-v1/; / { device_type = <0xdeadbeef>; model = <0xdeadbeef>; status = <0xdeadbeef>; + label = <0xdeadbeef>; + + foobar-names = "foo", <1>; + + node { + compatible = "good", <0xdeadbeef>; + }; }; Index: vendor/dtc/dist/tests/char_literal.c =================================================================== --- vendor/dtc/dist/tests/char_literal.c (revision 327892) +++ vendor/dtc/dist/tests/char_literal.c (revision 327893) @@ -1,49 +1,49 @@ /* * libfdt - Flat Device Tree manipulation * Testcase for character literals in dtc * Copyright (C) 2006 David Gibson, IBM Corporation. * Copyright (C) 2011 The Chromium Authors. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include "tests.h" #include "testdata.h" int main(int argc, char *argv[]) { void *fdt; - uint32_t expected_cells[5]; + fdt32_t expected_cells[5]; expected_cells[0] = cpu_to_fdt32((unsigned char)TEST_CHAR1); expected_cells[1] = cpu_to_fdt32((unsigned char)TEST_CHAR2); expected_cells[2] = cpu_to_fdt32((unsigned char)TEST_CHAR3); expected_cells[3] = cpu_to_fdt32((unsigned char)TEST_CHAR4); expected_cells[4] = cpu_to_fdt32((unsigned char)TEST_CHAR5); test_init(argc, argv); fdt = load_blob_arg(argc, argv); check_getprop(fdt, 0, "char-literal-cells", sizeof(expected_cells), expected_cells); PASS(); } Index: vendor/dtc/dist/tests/dtbs_equal_ordered.c =================================================================== --- vendor/dtc/dist/tests/dtbs_equal_ordered.c (revision 327892) +++ vendor/dtc/dist/tests/dtbs_equal_ordered.c (revision 327893) @@ -1,173 +1,173 @@ /* * libfdt - Flat Device Tree manipulation * Tests if two given dtbs are structurally equal (including order) * Copyright (C) 2007 David Gibson, IBM Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include "tests.h" #include "testdata.h" -int notequal; /* = 0 */ +static int notequal; /* = 0 */ #define MISMATCH(fmt, ...) \ do { \ if (notequal) \ PASS(); \ else \ FAIL(fmt, ##__VA_ARGS__); \ } while (0) #define MATCH() \ do { \ if (!notequal) \ PASS(); \ else \ FAIL("Trees match which shouldn't"); \ } while (0) #define CHECK(code) \ { \ err = (code); \ if (err) \ FAIL(#code ": %s", fdt_strerror(err)); \ } static void compare_mem_rsv(const void *fdt1, const void *fdt2) { int i; uint64_t addr1, size1, addr2, size2; int err; if (fdt_num_mem_rsv(fdt1) != fdt_num_mem_rsv(fdt2)) MISMATCH("Trees have different number of reserve entries"); for (i = 0; i < fdt_num_mem_rsv(fdt1); i++) { CHECK(fdt_get_mem_rsv(fdt1, i, &addr1, &size1)); CHECK(fdt_get_mem_rsv(fdt2, i, &addr2, &size2)); if ((addr1 != addr2) || (size1 != size2)) MISMATCH("Mismatch in reserve entry %d: " "(0x%llx, 0x%llx) != (0x%llx, 0x%llx)", i, (unsigned long long)addr1, (unsigned long long)size1, (unsigned long long)addr2, (unsigned long long)size2); } } static void compare_structure(const void *fdt1, const void *fdt2) { int nextoffset1 = 0, nextoffset2 = 0; int offset1, offset2; uint32_t tag1, tag2; const char *name1, *name2; int err; const struct fdt_property *prop1, *prop2; int len1, len2; while (1) { do { offset1 = nextoffset1; tag1 = fdt_next_tag(fdt1, offset1, &nextoffset1); } while (tag1 == FDT_NOP); do { offset2 = nextoffset2; tag2 = fdt_next_tag(fdt2, offset2, &nextoffset2); } while (tag2 == FDT_NOP); if (tag1 != tag2) MISMATCH("Tag mismatch (%d != %d) at (%d, %d)", tag1, tag2, offset1, offset2); switch (tag1) { case FDT_BEGIN_NODE: name1 = fdt_get_name(fdt1, offset1, &err); if (!name1) FAIL("fdt_get_name(fdt1, %d, ..): %s", offset1, fdt_strerror(err)); name2 = fdt_get_name(fdt2, offset2, NULL); if (!name2) FAIL("fdt_get_name(fdt2, %d, ..): %s", offset2, fdt_strerror(err)); if (!streq(name1, name2)) MISMATCH("Name mismatch (\"%s\" != \"%s\") at (%d, %d)", name1, name2, offset1, offset2); break; case FDT_PROP: prop1 = fdt_offset_ptr(fdt1, offset1, sizeof(*prop1)); if (!prop1) FAIL("Could get fdt1 property at %d", offset1); prop2 = fdt_offset_ptr(fdt2, offset2, sizeof(*prop2)); if (!prop2) FAIL("Could get fdt2 property at %d", offset2); name1 = fdt_string(fdt1, fdt32_to_cpu(prop1->nameoff)); name2 = fdt_string(fdt2, fdt32_to_cpu(prop2->nameoff)); if (!streq(name1, name2)) MISMATCH("Property name mismatch \"%s\" != \"%s\" " "at (%d, %d)", name1, name2, offset1, offset2); len1 = fdt32_to_cpu(prop1->len); len2 = fdt32_to_cpu(prop2->len); if (len1 != len2) MISMATCH("Property length mismatch %u != %u " "at (%d, %d)", len1, len2, offset1, offset2); if (memcmp(prop1->data, prop2->data, len1) != 0) MISMATCH("Property value mismatch at (%d, %d)", offset1, offset2); break; case FDT_END: return; } } } int main(int argc, char *argv[]) { void *fdt1, *fdt2; uint32_t cpuid1, cpuid2; test_init(argc, argv); if ((argc != 3) && ((argc != 4) || !streq(argv[1], "-n"))) CONFIG("Usage: %s [-n] ", argv[0]); if (argc == 4) notequal = 1; fdt1 = load_blob(argv[argc-2]); fdt2 = load_blob(argv[argc-1]); compare_mem_rsv(fdt1, fdt2); compare_structure(fdt1, fdt2); cpuid1 = fdt_boot_cpuid_phys(fdt1); cpuid2 = fdt_boot_cpuid_phys(fdt2); if (cpuid1 != cpuid2) MISMATCH("boot_cpuid_phys mismatch 0x%x != 0x%x", cpuid1, cpuid2); MATCH(); } Index: vendor/dtc/dist/tests/dtbs_equal_unordered.c =================================================================== --- vendor/dtc/dist/tests/dtbs_equal_unordered.c (revision 327892) +++ vendor/dtc/dist/tests/dtbs_equal_unordered.c (revision 327893) @@ -1,223 +1,223 @@ /* * libfdt - Flat Device Tree manipulation * Tests if two given dtbs are structurally equal (including order) * Copyright (C) 2007 David Gibson, IBM Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include "tests.h" #include "testdata.h" -int notequal; /* = 0 */ +static int notequal; /* = 0 */ #define MISMATCH(fmt, ...) \ do { \ if (notequal) \ PASS(); \ else \ FAIL(fmt, ##__VA_ARGS__); \ } while (0) #define MATCH() \ do { \ if (!notequal) \ PASS(); \ else \ FAIL("Trees match which shouldn't"); \ } while (0) #define CHECK(code) \ { \ err = (code); \ if (err) \ FAIL(#code ": %s", fdt_strerror(err)); \ } static int mem_rsv_cmp(const void *p1, const void *p2) { const struct fdt_reserve_entry *re1 = p1; const struct fdt_reserve_entry *re2 = p2; - if (re1->address < re2->address) + if (fdt64_to_cpu(re1->address) < fdt64_to_cpu(re2->address)) return -1; - else if (re1->address > re2->address) + else if (fdt64_to_cpu(re1->address) > fdt64_to_cpu(re2->address)) return 1; - if (re1->size < re2->size) + if (fdt64_to_cpu(re1->size) < fdt64_to_cpu(re2->size)) return -1; - else if (re1->size > re2->size) + else if (fdt64_to_cpu(re1->size) > fdt64_to_cpu(re2->size)) return 1; return 0; } static void compare_mem_rsv(void *fdt1, void *fdt2) { int i; uint64_t addr1, size1, addr2, size2; int err; if (fdt_num_mem_rsv(fdt1) != fdt_num_mem_rsv(fdt2)) MISMATCH("Trees have different number of reserve entries"); qsort((char *)fdt1 + fdt_off_mem_rsvmap(fdt1), fdt_num_mem_rsv(fdt1), sizeof(struct fdt_reserve_entry), mem_rsv_cmp); qsort((char *)fdt2 + fdt_off_mem_rsvmap(fdt2), fdt_num_mem_rsv(fdt2), sizeof(struct fdt_reserve_entry), mem_rsv_cmp); for (i = 0; i < fdt_num_mem_rsv(fdt1); i++) { CHECK(fdt_get_mem_rsv(fdt1, i, &addr1, &size1)); CHECK(fdt_get_mem_rsv(fdt2, i, &addr2, &size2)); if ((addr1 != addr2) || (size1 != size2)) MISMATCH("Mismatch in reserve entry %d: " "(0x%llx, 0x%llx) != (0x%llx, 0x%llx)", i, (unsigned long long)addr1, (unsigned long long)size1, (unsigned long long)addr2, (unsigned long long)size2); } } static void compare_properties(const void *fdt1, int offset1, const void *fdt2, int offset2) { int offset = offset1; /* Check the properties */ for (offset = fdt_first_property_offset(fdt1, offset1); offset >= 0; offset = fdt_next_property_offset(fdt1, offset)) { const char *name; int len1, len2; const void *data1, *data2; int i; data1 = fdt_getprop_by_offset(fdt1, offset, &name, &len1); if (!data1) FAIL("fdt_getprop_by_offset(): %s\n", fdt_strerror(len1)); verbose_printf("Property '%s'\n", name); data2 = fdt_getprop(fdt2, offset2, name, &len2); if (!data2) { if (len2 == -FDT_ERR_NOTFOUND) MISMATCH("Property '%s' missing\n", name); else FAIL("fdt_get_property(): %s\n", fdt_strerror(len2)); } verbose_printf("len1=%d data1=", len1); for (i = 0; i < len1; i++) verbose_printf(" %02x", ((const char *)data1)[i]); verbose_printf("\nlen2=%d data2=", len2); for (i = 0; i < len1; i++) verbose_printf(" %02x", ((const char *)data2)[i]); verbose_printf("\n"); if (len1 != len2) MISMATCH("Property '%s' mismatched length %d vs. %d\n", name, len1, len2); else if (memcmp(data1, data2, len1) != 0) MISMATCH("Property '%s' mismatched value\n", name); } } static void compare_node(const void *fdt1, int offset1, const void *fdt2, int offset2); static void compare_subnodes(const void *fdt1, int offset1, const void *fdt2, int offset2, int recurse) { int coffset1, coffset2, depth; for (depth = 0, coffset1 = offset1; (coffset1 >= 0) && (depth >= 0); coffset1 = fdt_next_node(fdt1, coffset1, &depth)) if (depth == 1) { const char *name = fdt_get_name(fdt1, coffset1, NULL); verbose_printf("Subnode %s\n", name); coffset2 = fdt_subnode_offset(fdt2, offset2, name); if (coffset2 == -FDT_ERR_NOTFOUND) MISMATCH("Subnode %s missing\n", name); else if (coffset2 < 0) FAIL("fdt_subnode_offset(): %s\n", fdt_strerror(coffset2)); if (recurse) compare_node(fdt1, coffset1, fdt2, coffset2); } } static void compare_node(const void *fdt1, int offset1, const void *fdt2, int offset2) { int err; char path1[PATH_MAX], path2[PATH_MAX]; CHECK(fdt_get_path(fdt1, offset1, path1, sizeof(path1))); CHECK(fdt_get_path(fdt2, offset2, path2, sizeof(path2))); if (!streq(path1, path2)) TEST_BUG("Path mismatch %s vs. %s\n", path1, path2); verbose_printf("Checking %s\n", path1); compare_properties(fdt1, offset1, fdt2, offset2); compare_properties(fdt2, offset2, fdt1, offset1); compare_subnodes(fdt1, offset1, fdt2, offset2, 1); compare_subnodes(fdt2, offset2, fdt1, offset1, 0); } int main(int argc, char *argv[]) { void *fdt1, *fdt2; uint32_t cpuid1, cpuid2; test_init(argc, argv); if ((argc != 3) && ((argc != 4) || !streq(argv[1], "-n"))) CONFIG("Usage: %s [-n] ", argv[0]); if (argc == 4) notequal = 1; fdt1 = load_blob(argv[argc-2]); fdt2 = load_blob(argv[argc-1]); compare_mem_rsv(fdt1, fdt2); compare_node(fdt1, 0, fdt2, 0); cpuid1 = fdt_boot_cpuid_phys(fdt1); cpuid2 = fdt_boot_cpuid_phys(fdt2); if (cpuid1 != cpuid2) MISMATCH("boot_cpuid_phys mismatch 0x%x != 0x%x", cpuid1, cpuid2); MATCH(); } Index: vendor/dtc/dist/tests/dumptrees.c =================================================================== --- vendor/dtc/dist/tests/dumptrees.c (revision 327892) +++ vendor/dtc/dist/tests/dumptrees.c (revision 327893) @@ -1,70 +1,70 @@ /* * dumptrees - utility for libfdt testing * * (C) Copyright David Gibson , IBM Corporation. 2006. * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ #include #include #include #include #include #include #include "testdata.h" -struct { +static struct { void *blob; const char *filename; } trees[] = { -#define TREE(name) { &_##name, #name ".dtb" } +#define TREE(name) { &name, #name ".dtb" } TREE(test_tree1), TREE(bad_node_char), TREE(bad_node_format), TREE(bad_prop_char), TREE(ovf_size_strings), }; #define NUM_TREES (sizeof(trees) / sizeof(trees[0])) int main(int argc, char *argv[]) { int i; for (i = 0; i < NUM_TREES; i++) { void *blob = trees[i].blob; const char *filename = trees[i].filename; int size; int fd; int ret; size = fdt_totalsize(blob); printf("Tree \"%s\", %d bytes\n", filename, size); fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd < 0) perror("open()"); ret = write(fd, blob, size); if (ret != size) perror("write()"); close(fd); } exit(0); } Index: vendor/dtc/dist/tests/fdtoverlay-runtest.sh =================================================================== --- vendor/dtc/dist/tests/fdtoverlay-runtest.sh (nonexistent) +++ vendor/dtc/dist/tests/fdtoverlay-runtest.sh (revision 327893) @@ -0,0 +1,40 @@ +#! /bin/sh + +# Run script for fdtoverlay tests +# We run fdtoverlay to generate a target device tree, thn fdtget to check it + +# Usage +# fdtoverlay-runtest.sh name expected_output dtb_file node property flags value + +. ./tests.sh + +LOG=tmp.log.$$ +EXPECT=tmp.expect.$$ +rm -f $LOG $EXPECT +trap "rm -f $LOG $EXPECT" 0 + +expect="$1" +echo $expect >$EXPECT +node="$2" +property="$3" +flags="$4" +basedtb="$5" +targetdtb="$6" +shift 6 +overlays="$@" + +# First run fdtoverlay +verbose_run_check $VALGRIND "$FDTOVERLAY" -i "$basedtb" -o "$targetdtb" $overlays + +# Now fdtget to read the value +verbose_run_log_check "$LOG" $VALGRIND "$DTGET" "$targetdtb" "$node" "$property" $flags + +if cmp $EXPECT $LOG >/dev/null; then + PASS +else + if [ -z "$QUIET_TEST" ]; then + echo "EXPECTED :-:" + cat $EXPECT + fi + FAIL "Results differ from expected" +fi Property changes on: vendor/dtc/dist/tests/fdtoverlay-runtest.sh ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/dtc/dist/tests/include7.dts =================================================================== --- vendor/dtc/dist/tests/include7.dts (revision 327892) +++ vendor/dtc/dist/tests/include7.dts (revision 327893) @@ -1,13 +1,14 @@ subnode@1 { compatible = "subnode1"; reg = <1>; prop-int = [deadbeef]; subsubnode { compatible = "subsubnode1", "subsubnode"; + placeholder = "this is a placeholder string", "string2"; prop-int = <0xdeadbeef>; }; ss1 { }; }; Index: vendor/dtc/dist/tests/integer-expressions.c =================================================================== --- vendor/dtc/dist/tests/integer-expressions.c (revision 327892) +++ vendor/dtc/dist/tests/integer-expressions.c (revision 327893) @@ -1,116 +1,116 @@ /* * Testcase for dtc expression support * * Copyright (C) 2008 David Gibson, IBM Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include "tests.h" #include "testdata.h" -struct test_expr { +static struct test_expr { const char *expr; uint32_t result; } expr_table[] = { #define TE(expr) { #expr, (expr) } TE(0xdeadbeef), TE(-0x21524111), TE(1+1), TE(2*3), TE(4/2), TE(10/3), TE(19%4), TE(1 << 13), TE(0x1000 >> 4), TE(3*2+1), TE(3*(2+1)), TE(1+2*3), TE((1+2)*3), TE(1 < 2), TE(2 < 1), TE(1 < 1), TE(1 <= 2), TE(2 <= 1), TE(1 <= 1), TE(1 > 2), TE(2 > 1), TE(1 > 1), TE(1 >= 2), TE(2 >= 1), TE(1 >= 1), TE(1 == 1), TE(1 == 2), TE(1 != 1), TE(1 != 2), TE(0xabcdabcd & 0xffff0000), TE(0xdead4110 ^ 0xf0f0f0f0), TE(0xabcd0000 | 0x0000abcd), TE(~0x21524110), TE(~~0xdeadbeef), TE(0 && 0), TE(17 && 0), TE(0 && 17), TE(17 && 17), TE(0 || 0), TE(17 || 0), TE(0 || 17), TE(17 || 17), TE(!0), TE(!1), TE(!17), TE(!!0), TE(!!17), TE(0 ? 17 : 39), TE(1 ? 17 : 39), TE(17 ? 0xdeadbeef : 0xabcd1234), TE(11 * 257 * 1321517ULL), TE(123456790 - 4/2 + 17%4), }; #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) int main(int argc, char *argv[]) { void *fdt; - const uint32_t *res; + const fdt32_t *res; int reslen; int i; test_init(argc, argv); if ((argc == 3) && (strcmp(argv[1], "-g") == 0)) { FILE *f = fopen(argv[2], "w"); if (!f) FAIL("Couldn't open \"%s\" for output: %s\n", argv[2], strerror(errno)); fprintf(f, "/dts-v1/;\n"); fprintf(f, "/ {\n"); fprintf(f, "\texpressions = <\n"); for (i = 0; i < ARRAY_SIZE(expr_table); i++) fprintf(f, "\t\t(%s)\n", expr_table[i].expr); fprintf(f, "\t>;\n"); fprintf(f, "};\n"); fclose(f); } else { fdt = load_blob_arg(argc, argv); res = fdt_getprop(fdt, 0, "expressions", &reslen); if (!res) FAIL("Error retreiving expression results: %s\n", fdt_strerror(reslen)); if (reslen != (ARRAY_SIZE(expr_table) * sizeof(uint32_t))) FAIL("Unexpected length of results %d instead of %zd\n", reslen, ARRAY_SIZE(expr_table) * sizeof(uint32_t)); for (i = 0; i < ARRAY_SIZE(expr_table); i++) if (fdt32_to_cpu(res[i]) != expr_table[i].result) FAIL("Incorrect result for expression \"%s\"," " 0x%x instead of 0x%x\n", expr_table[i].expr, fdt32_to_cpu(res[i]), expr_table[i].result); } PASS(); } Index: vendor/dtc/dist/tests/node_check_compatible.c =================================================================== --- vendor/dtc/dist/tests/node_check_compatible.c (revision 327892) +++ vendor/dtc/dist/tests/node_check_compatible.c (revision 327893) @@ -1,62 +1,81 @@ /* * libfdt - Flat Device Tree manipulation * Testcase for fdt_node_check_compatible() * Copyright (C) 2006 David Gibson, IBM Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include "tests.h" #include "testdata.h" static void check_compatible(const void *fdt, const char *path, const char *compat) { int offset, err; offset = fdt_path_offset(fdt, path); if (offset < 0) FAIL("fdt_path_offset(%s): %s", path, fdt_strerror(offset)); err = fdt_node_check_compatible(fdt, offset, compat); if (err < 0) FAIL("fdt_node_check_compatible(%s): %s", path, fdt_strerror(err)); if (err != 0) FAIL("%s is not compatible with \"%s\"", path, compat); } +static void check_not_compatible(const void *fdt, const char *path, + const char *compat) +{ + int offset, err; + + offset = fdt_path_offset(fdt, path); + if (offset < 0) + FAIL("fdt_path_offset(%s): %s", path, fdt_strerror(offset)); + + err = fdt_node_check_compatible(fdt, offset, compat); + if (err < 0) + FAIL("fdt_node_check_compatible(%s): %s", path, + fdt_strerror(err)); + if (err == 0) + FAIL("%s is incorrectly compatible with \"%s\"", path, compat); +} + int main(int argc, char *argv[]) { void *fdt; test_init(argc, argv); fdt = load_blob_arg(argc, argv); check_compatible(fdt, "/", "test_tree1"); check_compatible(fdt, "/subnode@1/subsubnode", "subsubnode1"); check_compatible(fdt, "/subnode@1/subsubnode", "subsubnode"); + check_not_compatible(fdt, "/subnode@1/subsubnode", "subsubnode2"); check_compatible(fdt, "/subnode@2/subsubnode", "subsubnode2"); check_compatible(fdt, "/subnode@2/subsubnode", "subsubnode"); + check_not_compatible(fdt, "/subnode@2/subsubnode", "subsubnode1"); PASS(); } Index: vendor/dtc/dist/tests/node_offset_by_prop_value.c =================================================================== --- vendor/dtc/dist/tests/node_offset_by_prop_value.c (revision 327892) +++ vendor/dtc/dist/tests/node_offset_by_prop_value.c (revision 327893) @@ -1,110 +1,110 @@ /* * libfdt - Flat Device Tree manipulation * Testcase for fdt_path_offset() * Copyright (C) 2006 David Gibson, IBM Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include "tests.h" #include "testdata.h" static void vcheck_search(void *fdt, const char *propname, const void *propval, int proplen, va_list ap) { int offset = -1, target; do { target = va_arg(ap, int); verbose_printf("Searching (target = %d): %d ->", target, offset); offset = fdt_node_offset_by_prop_value(fdt, offset, propname, propval, proplen); verbose_printf("%d\n", offset); if (offset != target) FAIL("fdt_node_offset_by_prop_value() returns %d " "instead of %d", offset, target); } while (target >= 0); } static void check_search(void *fdt, const char *propname, const void *propval, int proplen, ...) { va_list ap; va_start(ap, proplen); vcheck_search(fdt, propname, propval, proplen, ap); va_end(ap); } static void check_search_str(void *fdt, const char *propname, const char *propval, ...) { va_list ap; va_start(ap, propval); vcheck_search(fdt, propname, propval, strlen(propval)+1, ap); va_end(ap); } #define check_search_cell(fdt, propname, propval, ...) \ { \ - uint32_t val = cpu_to_fdt32(propval); \ + fdt32_t val = cpu_to_fdt32(propval); \ check_search((fdt), (propname), &val, sizeof(val), \ ##__VA_ARGS__); \ } int main(int argc, char *argv[]) { void *fdt; int subnode1_offset, subnode2_offset; int subsubnode1_offset, subsubnode2_offset; test_init(argc, argv); fdt = load_blob_arg(argc, argv); subnode1_offset = fdt_path_offset(fdt, "/subnode@1"); subnode2_offset = fdt_path_offset(fdt, "/subnode@2"); subsubnode1_offset = fdt_path_offset(fdt, "/subnode@1/subsubnode"); subsubnode2_offset = fdt_path_offset(fdt, "/subnode@2/subsubnode@0"); if ((subnode1_offset < 0) || (subnode2_offset < 0) || (subsubnode1_offset < 0) || (subsubnode2_offset < 0)) FAIL("Can't find required nodes"); check_search_cell(fdt, "prop-int", TEST_VALUE_1, 0, subnode1_offset, subsubnode1_offset, -FDT_ERR_NOTFOUND); check_search_cell(fdt, "prop-int", TEST_VALUE_2, subnode2_offset, subsubnode2_offset, -FDT_ERR_NOTFOUND); check_search_str(fdt, "prop-str", TEST_STRING_1, 0, -FDT_ERR_NOTFOUND); check_search_str(fdt, "prop-str", "no such string", -FDT_ERR_NOTFOUND); check_search_cell(fdt, "prop-int", TEST_VALUE_1+1, -FDT_ERR_NOTFOUND); check_search(fdt, "no-such-prop", NULL, 0, -FDT_ERR_NOTFOUND); PASS(); } Index: vendor/dtc/dist/tests/nopulate.c =================================================================== --- vendor/dtc/dist/tests/nopulate.c (revision 327892) +++ vendor/dtc/dist/tests/nopulate.c (revision 327893) @@ -1,105 +1,105 @@ /* * libfdt - Flat Device Tree manipulation * Testcase/tool for rearranging blocks of a dtb * Copyright (C) 2006 David Gibson, IBM Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include "tests.h" #include "testdata.h" static int nopulate_struct(char *buf, const char *fdt) { int offset, nextoffset = 0; uint32_t tag; char *p; p = buf; do { offset = nextoffset; tag = fdt_next_tag(fdt, offset, &nextoffset); memcpy(p, (const char *)fdt + fdt_off_dt_struct(fdt) + offset, nextoffset - offset); p += nextoffset - offset; - *((uint32_t *)p) = cpu_to_fdt32(FDT_NOP); + *((fdt32_t *)p) = cpu_to_fdt32(FDT_NOP); p += FDT_TAGSIZE; } while (tag != FDT_END); return p - buf; } int main(int argc, char *argv[]) { char *fdt, *fdt2, *buf; int newsize, struct_start, struct_end_old, struct_end_new, delta; const char *inname; char outname[PATH_MAX]; test_init(argc, argv); if (argc != 2) CONFIG("Usage: %s ", argv[0]); inname = argv[1]; fdt = load_blob(argv[1]); sprintf(outname, "noppy.%s", inname); if (fdt_version(fdt) < 17) FAIL("Can't deal with version <17"); buf = xmalloc(2 * fdt_size_dt_struct(fdt)); newsize = nopulate_struct(buf, fdt); verbose_printf("Nopulated structure block has new size %d\n", newsize); /* Replace old strcutre block with the new */ fdt2 = xmalloc(fdt_totalsize(fdt) + newsize); struct_start = fdt_off_dt_struct(fdt); delta = newsize - fdt_size_dt_struct(fdt); struct_end_old = struct_start + fdt_size_dt_struct(fdt); struct_end_new = struct_start + newsize; memcpy(fdt2, fdt, struct_start); memcpy(fdt2 + struct_start, buf, newsize); memcpy(fdt2 + struct_end_new, fdt + struct_end_old, fdt_totalsize(fdt) - struct_end_old); fdt_set_totalsize(fdt2, fdt_totalsize(fdt) + delta); fdt_set_size_dt_struct(fdt2, newsize); if (fdt_off_mem_rsvmap(fdt) > struct_start) fdt_set_off_mem_rsvmap(fdt2, fdt_off_mem_rsvmap(fdt) + delta); if (fdt_off_dt_strings(fdt) > struct_start) fdt_set_off_dt_strings(fdt2, fdt_off_dt_strings(fdt) + delta); save_blob(outname, fdt2); PASS(); } Index: vendor/dtc/dist/tests/path-references.c =================================================================== --- vendor/dtc/dist/tests/path-references.c (revision 327892) +++ vendor/dtc/dist/tests/path-references.c (revision 327893) @@ -1,98 +1,108 @@ /* * libfdt - Flat Device Tree manipulation * Testcase for string references in dtc * Copyright (C) 2006 David Gibson, IBM Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include "tests.h" #include "testdata.h" static void check_ref(const void *fdt, int node, const char *checkpath) { const char *p; int len; p = fdt_getprop(fdt, node, "ref", &len); if (!p) FAIL("fdt_getprop(%d, \"ref\"): %s", node, fdt_strerror(len)); if (!streq(p, checkpath)) FAIL("'ref' in node at %d has value \"%s\" instead of \"%s\"", node, p, checkpath); p = fdt_getprop(fdt, node, "lref", &len); if (!p) FAIL("fdt_getprop(%d, \"lref\"): %s", node, fdt_strerror(len)); if (!streq(p, checkpath)) FAIL("'lref' in node at %d has value \"%s\" instead of \"%s\"", node, p, checkpath); } static void check_rref(const void *fdt) { const char *p; int len; /* Check reference to root node */ p = fdt_getprop(fdt, 0, "rref", &len); if (!p) FAIL("fdt_getprop(0, \"rref\"): %s", fdt_strerror(len)); if (!streq(p, "/")) FAIL("'rref' in root node has value \"%s\" instead of \"/\"", p); } int main(int argc, char *argv[]) { void *fdt; const char *p; int len, multilen; - int n1, n2; + int n1, n2, n3, n4; test_init(argc, argv); fdt = load_blob_arg(argc, argv); n1 = fdt_path_offset(fdt, "/node1"); if (n1 < 0) FAIL("fdt_path_offset(/node1): %s", fdt_strerror(n1)); n2 = fdt_path_offset(fdt, "/node2"); if (n2 < 0) FAIL("fdt_path_offset(/node2): %s", fdt_strerror(n2)); check_ref(fdt, n1, "/node2"); check_ref(fdt, n2, "/node1"); /* Check multiple reference */ multilen = strlen("/node1") + strlen("/node2") + 2; p = fdt_getprop(fdt, 0, "multiref", &len); if (!p) FAIL("fdt_getprop(0, \"multiref\"): %s", fdt_strerror(len)); if (len != multilen) FAIL("multiref has wrong length, %d instead of %d", len, multilen); if ((!streq(p, "/node1") || !streq(p + strlen("/node1") + 1, "/node2"))) FAIL("multiref has wrong value"); + + /* Check reference to nested nodes with common prefix */ + n3 = fdt_path_offset(fdt, "/foo/baz"); + if (n3 < 0) + FAIL("fdt_path_offset(/foo/baz): %s", fdt_strerror(n3)); + n4 = fdt_path_offset(fdt, "/foobar/baz"); + if (n4 < 0) + FAIL("fdt_path_offset(/foobar/baz): %s", fdt_strerror(n4)); + check_ref(fdt, n3, "/foobar/baz"); + check_ref(fdt, n4, "/foo/baz"); check_rref(fdt); PASS(); } Index: vendor/dtc/dist/tests/path-references.dts =================================================================== --- vendor/dtc/dist/tests/path-references.dts (revision 327892) +++ vendor/dtc/dist/tests/path-references.dts (revision 327893) @@ -1,15 +1,28 @@ /dts-v1/; / { rref = &{/}; /* Check multiple references case */ multiref = &n1 , &n2; n1: node1 { ref = &{/node2}; /* reference precedes target */ lref = &n2; }; n2: node2 { ref = &{/node1}; /* reference after target */ lref = &n1; }; + /* Check references to nested nodes with common prefix */ + foobar { + n3: baz { + ref = &{/foo/baz}; + lref = &n4; + }; + }; + foo { + n4: baz { + ref = &{/foobar/baz}; + lref = &n3; + }; + }; }; Index: vendor/dtc/dist/tests/pci-bridge-bad1.dts =================================================================== --- vendor/dtc/dist/tests/pci-bridge-bad1.dts (nonexistent) +++ vendor/dtc/dist/tests/pci-bridge-bad1.dts (revision 327893) @@ -0,0 +1,16 @@ +/dts-v1/; + +/ { + compatible = "example,pci-bridge-ok"; + #address-cells = < 2 >; + #size-cells = < 2 >; + abadname@0 { + device_type = "pci"; + compatible = "example,pci-bridge"; + #address-cells = < 3 >; + #size-cells = < 2 >; + reg = <0 0 0 0x1000>; + bus-range = <0 0xff>; + ranges = <0 0 0 0 0 0 0x10000>; + }; +}; Property changes on: vendor/dtc/dist/tests/pci-bridge-bad1.dts ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/dtc/dist/tests/pci-bridge-bad2.dts =================================================================== --- vendor/dtc/dist/tests/pci-bridge-bad2.dts (nonexistent) +++ vendor/dtc/dist/tests/pci-bridge-bad2.dts (revision 327893) @@ -0,0 +1,16 @@ +/dts-v1/; + +/ { + compatible = "example,pci-bridge-ok"; + #address-cells = < 2 >; + #size-cells = < 2 >; + p@0 { + device_type = "pci"; + compatible = "example,pci-bridge"; + #address-cells = < 3 >; + #size-cells = < 2 >; + reg = <0 0 0 0x1000>; + bus-range = <0 0xff>; + ranges = <0 0 0 0 0 0 0x10000>; + }; +}; Property changes on: vendor/dtc/dist/tests/pci-bridge-bad2.dts ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/dtc/dist/tests/pci-bridge-ok.dts =================================================================== --- vendor/dtc/dist/tests/pci-bridge-ok.dts (nonexistent) +++ vendor/dtc/dist/tests/pci-bridge-ok.dts (revision 327893) @@ -0,0 +1,25 @@ +/dts-v1/; + +/ { + compatible = "example,pci-bridge-ok"; + #address-cells = < 2 >; + #size-cells = < 2 >; + pci@0 { + device_type = "pci"; + compatible = "example,pci-bridge"; + #address-cells = < 3 >; + #size-cells = < 2 >; + reg = <0 0 0 0x1000>; + bus-range = <0 0xff>; + ranges = <0 0 0 0 0 0 0x10000>; + }; + pcie@10000000000 { + device_type = "pci"; + compatible = "example,pcie-bridge"; + #address-cells = < 3 >; + #size-cells = < 2 >; + reg = <0x10 0x00000000 0 0x1000>; + bus-range = <0 0xff>; + ranges = <0 0 0 0 0 0 0x10000>; + }; +}; Property changes on: vendor/dtc/dist/tests/pci-bridge-ok.dts ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/dtc/dist/tests/property_iterate.c =================================================================== --- vendor/dtc/dist/tests/property_iterate.c (revision 327892) +++ vendor/dtc/dist/tests/property_iterate.c (revision 327893) @@ -1,97 +1,97 @@ /* * libfdt - Flat Device Tree manipulation * Tests that fdt_next_subnode() works as expected * * Copyright (C) 2013 Google, Inc * * Copyright (C) 2007 David Gibson, IBM Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include "tests.h" #include "testdata.h" static void test_node(void *fdt, int parent_offset) { - fdt32_t properties; + uint32_t properties; const fdt32_t *prop; int offset, property; int count; int len; /* * This property indicates the number of properties in our * test node to expect */ prop = fdt_getprop(fdt, parent_offset, "test-properties", &len); if (!prop || len != sizeof(fdt32_t)) { FAIL("Missing/invalid test-properties property at '%s'", fdt_get_name(fdt, parent_offset, NULL)); } - properties = cpu_to_fdt32(*prop); + properties = fdt32_to_cpu(*prop); count = 0; offset = fdt_first_subnode(fdt, parent_offset); if (offset < 0) FAIL("Missing test node\n"); fdt_for_each_property_offset(property, fdt, offset) count++; if (count != properties) { FAIL("Node '%s': Expected %d properties, got %d\n", fdt_get_name(fdt, parent_offset, NULL), properties, count); } } static void check_fdt_next_subnode(void *fdt) { int offset; int count = 0; fdt_for_each_subnode(offset, fdt, 0) { test_node(fdt, offset); count++; } if (count != 2) FAIL("Expected %d tests, got %d\n", 2, count); } int main(int argc, char *argv[]) { void *fdt; test_init(argc, argv); if (argc != 2) CONFIG("Usage: %s ", argv[0]); fdt = load_blob(argv[1]); if (!fdt) FAIL("No device tree available"); check_fdt_next_subnode(fdt); PASS(); } Index: vendor/dtc/dist/tests/pylibfdt_tests.py =================================================================== --- vendor/dtc/dist/tests/pylibfdt_tests.py (nonexistent) +++ vendor/dtc/dist/tests/pylibfdt_tests.py (revision 327893) @@ -0,0 +1,334 @@ +# pylibfdt - Tests for Flat Device Tree manipulation in Python +# Copyright (C) 2017 Google, Inc. +# Written by Simon Glass +# +# libfdt is dual licensed: you can use it either under the terms of +# the GPL, or the BSD license, at your option. +# +# a) This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this library; if not, write to the Free +# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, +# MA 02110-1301 USA +# +# Alternatively, +# +# b) Redistribution and use in source and binary forms, with or +# without modification, are permitted provided that the following +# conditions are met: +# +# 1. Redistributions of source code must retain the above +# copyright notice, this list of conditions and the following +# disclaimer. +# 2. Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials +# provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +import sys +import types +import unittest + +sys.path.insert(0, '../pylibfdt') +import libfdt +from libfdt import FdtException, QUIET_NOTFOUND, QUIET_ALL + +def get_err(err_code): + """Convert an error code into an error message + + Args: + err_code: Error code value (FDT_ERR_...) + + Returns: + String error code + """ + return 'pylibfdt error %d: %s' % (-err_code, libfdt.strerror(-err_code)) + +def _ReadFdt(fname): + """Read a device tree file into an Fdt object, ready for use + + Args: + fname: Filename to read from + + Returns: + Fdt bytearray suitable for passing to libfdt functions + """ + return libfdt.Fdt(open(fname).read()) + +class PyLibfdtTests(unittest.TestCase): + """Test class for pylibfdt + + Properties: + fdt: Device tree file used for testing + """ + + def setUp(self): + """Read in the device tree we use for testing""" + self.fdt = _ReadFdt('test_tree1.dtb') + + def GetPropList(self, node_path): + """Read a list of properties from a node + + Args: + node_path: Full path to node, e.g. '/subnode@1/subsubnode' + + Returns: + List of property names for that node, e.g. ['compatible', 'reg'] + """ + prop_list = [] + node = self.fdt.path_offset(node_path) + poffset = self.fdt.first_property_offset(node, QUIET_NOTFOUND) + while poffset > 0: + prop = self.fdt.get_property_by_offset(poffset) + prop_list.append(prop.name) + poffset = self.fdt.next_property_offset(poffset, QUIET_NOTFOUND) + return prop_list + + def testImport(self): + """Check that we can import the library correctly""" + self.assertEquals(type(libfdt), types.ModuleType) + + def testBadFdt(self): + """Check that a filename provided accidentally is not accepted""" + with self.assertRaises(FdtException) as e: + fdt = libfdt.Fdt('a string') + self.assertEquals(e.exception.err, -libfdt.BADMAGIC) + + def testSubnodeOffset(self): + """check that we can locate a subnode by name""" + node1 = self.fdt.path_offset('/subnode@1') + self.assertEquals(self.fdt.subnode_offset(0, 'subnode@1'), node1) + + with self.assertRaises(FdtException) as e: + self.fdt.subnode_offset(0, 'missing') + self.assertEquals(e.exception.err, -libfdt.NOTFOUND) + + node2 = self.fdt.path_offset('/subnode@1/subsubnode') + self.assertEquals(self.fdt.subnode_offset(node1, 'subsubnode'), node2) + + def testPathOffset(self): + """Check that we can find the offset of a node""" + self.assertEquals(self.fdt.path_offset('/'), 0) + self.assertTrue(self.fdt.path_offset('/subnode@1') > 0) + with self.assertRaises(FdtException) as e: + self.fdt.path_offset('/wibble') + self.assertEquals(e.exception.err, -libfdt.NOTFOUND) + self.assertEquals(self.fdt.path_offset('/wibble', QUIET_NOTFOUND), + -libfdt.NOTFOUND) + + def testPropertyOffset(self): + """Walk through all the properties in the root node""" + offset = self.fdt.first_property_offset(0) + self.assertTrue(offset > 0) + for i in range(5): + next_offset = self.fdt.next_property_offset(offset) + self.assertTrue(next_offset > offset) + offset = next_offset + self.assertEquals(self.fdt.next_property_offset(offset, QUIET_NOTFOUND), + -libfdt.NOTFOUND) + + def testPropertyOffsetExceptions(self): + """Check that exceptions are raised as expected""" + with self.assertRaises(FdtException) as e: + self.fdt.first_property_offset(107) + self.assertEquals(e.exception.err, -libfdt.BADOFFSET) + + # Quieten the NOTFOUND exception and check that a BADOFFSET + # exception is still raised. + with self.assertRaises(FdtException) as e: + self.fdt.first_property_offset(107, QUIET_NOTFOUND) + self.assertEquals(e.exception.err, -libfdt.BADOFFSET) + with self.assertRaises(FdtException) as e: + self.fdt.next_property_offset(107, QUIET_NOTFOUND) + self.assertEquals(e.exception.err, -libfdt.BADOFFSET) + + # Check that NOTFOUND can be quietened. + node = self.fdt.path_offset('/subnode@1/ss1') + self.assertEquals(self.fdt.first_property_offset(node, QUIET_NOTFOUND), + -libfdt.NOTFOUND) + with self.assertRaises(FdtException) as e: + self.fdt.first_property_offset(node) + self.assertEquals(e.exception.err, -libfdt.NOTFOUND) + + def testGetName(self): + """Check that we can get the name of a node""" + self.assertEquals(self.fdt.get_name(0), '') + node = self.fdt.path_offset('/subnode@1/subsubnode') + self.assertEquals(self.fdt.get_name(node), 'subsubnode') + + with self.assertRaises(FdtException) as e: + self.fdt.get_name(-2) + self.assertEquals(e.exception.err, -libfdt.BADOFFSET) + + def testGetPropertyByOffset(self): + """Check that we can read the name and contents of a property""" + root = 0 + poffset = self.fdt.first_property_offset(root) + prop = self.fdt.get_property_by_offset(poffset) + self.assertEquals(prop.name, 'compatible') + self.assertEquals(prop.value, 'test_tree1\0') + + with self.assertRaises(FdtException) as e: + self.fdt.get_property_by_offset(-2) + self.assertEquals(e.exception.err, -libfdt.BADOFFSET) + self.assertEquals( + -libfdt.BADOFFSET, + self.fdt.get_property_by_offset(-2, [libfdt.BADOFFSET])) + + def testGetProp(self): + """Check that we can read the contents of a property by name""" + root = self.fdt.path_offset('/') + value = self.fdt.getprop(root, "compatible") + self.assertEquals(value, 'test_tree1\0') + self.assertEquals(-libfdt.NOTFOUND, self.fdt.getprop(root, 'missing', + QUIET_NOTFOUND)) + + with self.assertRaises(FdtException) as e: + self.fdt.getprop(root, 'missing') + self.assertEquals(e.exception.err, -libfdt.NOTFOUND) + + node = self.fdt.path_offset('/subnode@1/subsubnode') + value = self.fdt.getprop(node, "compatible") + self.assertEquals(value, 'subsubnode1\0subsubnode\0') + + def testStrError(self): + """Check that we can get an error string""" + self.assertEquals(libfdt.strerror(-libfdt.NOTFOUND), + 'FDT_ERR_NOTFOUND') + + def testFirstNextSubnodeOffset(self): + """Check that we can walk through subnodes""" + node_list = [] + node = self.fdt.first_subnode(0, QUIET_NOTFOUND) + while node >= 0: + node_list.append(self.fdt.get_name(node)) + node = self.fdt.next_subnode(node, QUIET_NOTFOUND) + self.assertEquals(node_list, ['subnode@1', 'subnode@2']) + + def testFirstNextSubnodeOffsetExceptions(self): + """Check except handling for first/next subnode functions""" + node = self.fdt.path_offset('/subnode@1/subsubnode', QUIET_NOTFOUND) + self.assertEquals(self.fdt.first_subnode(node, QUIET_NOTFOUND), + -libfdt.NOTFOUND) + with self.assertRaises(FdtException) as e: + self.fdt.first_subnode(node) + self.assertEquals(e.exception.err, -libfdt.NOTFOUND) + + node = self.fdt.path_offset('/subnode@1/ss1', QUIET_NOTFOUND) + self.assertEquals(self.fdt.next_subnode(node, QUIET_NOTFOUND), + -libfdt.NOTFOUND) + with self.assertRaises(FdtException) as e: + self.fdt.next_subnode(node) + self.assertEquals(e.exception.err, -libfdt.NOTFOUND) + + def testDeleteProperty(self): + """Test that we can delete a property""" + node_name = '/subnode@1' + self.assertEquals(self.GetPropList(node_name), + ['compatible', 'reg', 'prop-int']) + node = self.fdt.path_offset('/%s' % node_name) + self.assertEquals(self.fdt.delprop(node, 'reg'), 0) + self.assertEquals(self.GetPropList(node_name), + ['compatible', 'prop-int']) + + def testHeader(self): + """Test that we can access the header values""" + self.assertEquals(self.fdt.totalsize(), len(self.fdt._fdt)) + self.assertEquals(self.fdt.off_dt_struct(), 88) + + def testPack(self): + """Test that we can pack the tree after deleting something""" + orig_size = self.fdt.totalsize() + node = self.fdt.path_offset('/subnode@2', QUIET_NOTFOUND) + self.assertEquals(self.fdt.delprop(node, 'prop-int'), 0) + self.assertEquals(orig_size, self.fdt.totalsize()) + self.assertEquals(self.fdt.pack(), 0) + self.assertTrue(self.fdt.totalsize() < orig_size) + + def testBadPropertyOffset(self): + """Test that bad property offsets are detected""" + with self.assertRaises(FdtException) as e: + self.fdt.get_property_by_offset(13) + self.assertEquals(e.exception.err, -libfdt.BADOFFSET) + with self.assertRaises(FdtException) as e: + self.fdt.first_property_offset(3) + self.assertEquals(e.exception.err, -libfdt.BADOFFSET) + with self.assertRaises(FdtException) as e: + self.fdt.next_property_offset(3) + self.assertEquals(e.exception.err, -libfdt.BADOFFSET) + + def testBadPathOffset(self): + """Test that bad path names are detected""" + with self.assertRaisesRegexp(FdtException, get_err(libfdt.BADPATH)): + self.fdt.path_offset('not-present') + + def testQuietAll(self): + """Check that exceptions can be masked by QUIET_ALL""" + self.assertEquals(-libfdt.NOTFOUND, + self.fdt.path_offset('/missing', QUIET_ALL)) + self.assertEquals(-libfdt.BADOFFSET, + self.fdt.get_property_by_offset(13, QUIET_ALL)) + self.assertEquals(-libfdt.BADPATH, + self.fdt.path_offset('missing', QUIET_ALL)) + + def testIntegers(self): + """Check that integers can be passed and returned""" + self.assertEquals(0, libfdt.fdt_get_phandle(self.fdt._fdt, 0)) + node2 = self.fdt.path_offset('/subnode@2') + self.assertEquals(0x2000, libfdt.fdt_get_phandle(self.fdt._fdt, node2)) + + def testGetPhandle(self): + """Test for the get_phandle() method""" + self.assertEquals(0, self.fdt.get_phandle(0)) + node2 = self.fdt.path_offset('/subnode@2') + self.assertEquals(0x2000, self.fdt.get_phandle(node2)) + + def testParentOffset(self): + """Test for the parent_offset() method""" + self.assertEquals(-libfdt.NOTFOUND, + self.fdt.parent_offset(0, QUIET_NOTFOUND)) + with self.assertRaises(FdtException) as e: + self.fdt.parent_offset(0) + self.assertEquals(e.exception.err, -libfdt.NOTFOUND) + + node1 = self.fdt.path_offset('/subnode@2') + self.assertEquals(0, self.fdt.parent_offset(node1)) + node2 = self.fdt.path_offset('/subnode@2/subsubnode@0') + self.assertEquals(node1, self.fdt.parent_offset(node2)) + + def testNodeOffsetByPhandle(self): + """Test for the node_offset_by_phandle() method""" + self.assertEquals(-libfdt.NOTFOUND, + self.fdt.node_offset_by_phandle(1, QUIET_NOTFOUND)) + node1 = self.fdt.path_offset('/subnode@2') + self.assertEquals(node1, self.fdt.node_offset_by_phandle(0x2000)) + node2 = self.fdt.path_offset('/subnode@2/subsubnode@0') + self.assertEquals(node2, self.fdt.node_offset_by_phandle(0x2001)) + + +if __name__ == "__main__": + unittest.main() Property changes on: vendor/dtc/dist/tests/pylibfdt_tests.py ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/dtc/dist/tests/references.c =================================================================== --- vendor/dtc/dist/tests/references.c (revision 327892) +++ vendor/dtc/dist/tests/references.c (revision 327893) @@ -1,127 +1,127 @@ /* * libfdt - Flat Device Tree manipulation * Testcase for phandle references in dtc * Copyright (C) 2006 David Gibson, IBM Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include "tests.h" #include "testdata.h" static void check_ref(const void *fdt, int node, uint32_t checkref) { - const uint32_t *p; + const fdt32_t *p; uint32_t ref; int len; p = fdt_getprop(fdt, node, "ref", &len); if (!p) FAIL("fdt_getprop(%d, \"ref\"): %s", node, fdt_strerror(len)); if (len != sizeof(*p)) FAIL("'ref' in node at %d has wrong size (%d instead of %zd)", node, len, sizeof(*p)); ref = fdt32_to_cpu(*p); if (ref != checkref) FAIL("'ref' in node at %d has value 0x%x instead of 0x%x", node, ref, checkref); p = fdt_getprop(fdt, node, "lref", &len); if (!p) FAIL("fdt_getprop(%d, \"lref\"): %s", node, fdt_strerror(len)); if (len != sizeof(*p)) FAIL("'lref' in node at %d has wrong size (%d instead of %zd)", node, len, sizeof(*p)); ref = fdt32_to_cpu(*p); if (ref != checkref) FAIL("'lref' in node at %d has value 0x%x instead of 0x%x", node, ref, checkref); } static void check_rref(const void *fdt) { - const uint32_t *p; + const fdt32_t *p; uint32_t ref; int len; p = fdt_getprop(fdt, 0, "rref", &len); if (!p) FAIL("fdt_getprop(0, \"rref\"): %s", fdt_strerror(len)); if (len != sizeof(*p)) FAIL("'rref' in root node has wrong size (%d instead of %zd)", len, sizeof(*p)); ref = fdt32_to_cpu(*p); if (ref != fdt_get_phandle(fdt, 0)) FAIL("'rref' in root node has value 0x%x instead of 0x0", ref); } int main(int argc, char *argv[]) { void *fdt; int n1, n2, n3, n4, n5; uint32_t h1, h2, h4, h5; test_init(argc, argv); fdt = load_blob_arg(argc, argv); n1 = fdt_path_offset(fdt, "/node1"); if (n1 < 0) FAIL("fdt_path_offset(/node1): %s", fdt_strerror(n1)); n2 = fdt_path_offset(fdt, "/node2"); if (n2 < 0) FAIL("fdt_path_offset(/node2): %s", fdt_strerror(n2)); n3 = fdt_path_offset(fdt, "/node3"); if (n3 < 0) FAIL("fdt_path_offset(/node3): %s", fdt_strerror(n3)); n4 = fdt_path_offset(fdt, "/node4"); if (n4 < 0) FAIL("fdt_path_offset(/node4): %s", fdt_strerror(n4)); n5 = fdt_path_offset(fdt, "/node5"); if (n5 < 0) FAIL("fdt_path_offset(/node5): %s", fdt_strerror(n5)); h1 = fdt_get_phandle(fdt, n1); h2 = fdt_get_phandle(fdt, n2); h4 = fdt_get_phandle(fdt, n4); h5 = fdt_get_phandle(fdt, n5); if (h1 != 0x2000) FAIL("/node1 has wrong phandle, 0x%x instead of 0x%x", h1, 0x2000); if (h2 != 0x1) FAIL("/node2 has wrong phandle, 0x%x instead of 0x%x", h2, 0x1); if ((h4 == 0x2000) || (h4 == 0x1) || (h4 == 0)) FAIL("/node4 has bad phandle, 0x%x", h4); if ((h5 == 0) || (h5 == -1)) FAIL("/node5 has bad phandle, 0x%x", h5); if ((h5 == h4) || (h5 == h2) || (h5 == h1)) FAIL("/node5 has duplicate phandle, 0x%x", h5); check_ref(fdt, n1, h2); check_ref(fdt, n2, h1); check_ref(fdt, n3, h4); check_rref(fdt); PASS(); } Index: vendor/dtc/dist/tests/run_tests.sh =================================================================== --- vendor/dtc/dist/tests/run_tests.sh (revision 327892) +++ vendor/dtc/dist/tests/run_tests.sh (revision 327893) @@ -1,832 +1,925 @@ #! /bin/sh . ./tests.sh if [ -z "$CC" ]; then CC=gcc fi +# stat differs between platforms +if [ -z "$STATSZ" ]; then + STATSZ="stat -c %s" +fi + export QUIET_TEST=1 STOP_ON_FAIL=0 export VALGRIND= VGCODE=126 tot_tests=0 tot_pass=0 tot_fail=0 tot_config=0 tot_vg=0 tot_strange=0 base_run_test() { tot_tests=$((tot_tests + 1)) if VALGRIND="$VALGRIND" "$@"; then tot_pass=$((tot_pass + 1)) else ret="$?" if [ "$STOP_ON_FAIL" -eq 1 ]; then exit 1 fi if [ "$ret" -eq 1 ]; then tot_config=$((tot_config + 1)) elif [ "$ret" -eq 2 ]; then tot_fail=$((tot_fail + 1)) elif [ "$ret" -eq $VGCODE ]; then tot_vg=$((tot_vg + 1)) else tot_strange=$((tot_strange + 1)) fi fi } shorten_echo () { limit=32 printf "$1" shift for x; do if [ ${#x} -le $limit ]; then printf " $x" else short=$(echo "$x" | head -c$limit) printf " \"$short\"...<${#x} bytes>" fi done } run_test () { printf "$*: " if [ -n "$VALGRIND" -a -f $1.supp ]; then VGSUPP="--suppressions=$1.supp" fi base_run_test $VALGRIND $VGSUPP "./$@" } run_sh_test () { printf "$*: " base_run_test sh "$@" } wrap_test () { ( if verbose_run "$@"; then PASS else ret="$?" if [ "$ret" -gt 127 ]; then signame=$(kill -l $((ret - 128))) FAIL "Killed by SIG$signame" else FAIL "Returned error code $ret" fi fi ) } run_wrap_test () { shorten_echo "$@: " base_run_test wrap_test "$@" } wrap_error () { ( if verbose_run "$@"; then FAIL "Expected non-zero return code" else ret="$?" if [ "$ret" -gt 127 ]; then signame=$(kill -l $((ret - 128))) FAIL "Killed by SIG$signame" else PASS fi fi ) } run_wrap_error_test () { shorten_echo "$@" printf " {!= 0}: " base_run_test wrap_error "$@" } # $1: dtb file # $2: align base check_align () { shorten_echo "check_align $@: " - local size=$(stat -c %s "$1") + local size=$($STATSZ "$1") local align="$2" ( if [ $(($size % $align)) -eq 0 ] ;then PASS else FAIL "Output size $size is not $align-byte aligned" fi ) } run_dtc_test () { printf "dtc $*: " base_run_test wrap_test $VALGRIND $DTC "$@" } asm_to_so () { $CC -shared -o $1.test.so data.S $1.test.s } asm_to_so_test () { run_wrap_test asm_to_so "$@" } run_fdtget_test () { expect="$1" shift printf "fdtget-runtest.sh %s $*: " "$(echo $expect)" base_run_test sh fdtget-runtest.sh "$expect" "$@" } run_fdtput_test () { expect="$1" shift shorten_echo fdtput-runtest.sh "$expect" "$@" printf ": " base_run_test sh fdtput-runtest.sh "$expect" "$@" } run_fdtdump_test() { file="$1" shorten_echo fdtdump-runtest.sh "$file" printf ": " - base_run_test sh fdtdump-runtest.sh "$file" + base_run_test sh fdtdump-runtest.sh "$file" 2>/dev/null } +run_fdtoverlay_test() { + expect="$1" + shift + shorten_echo fdtoverlay-runtest.sh "$expect" "$@" + printf ": " + base_run_test sh fdtoverlay-runtest.sh "$expect" "$@" +} + BAD_FIXUP_TREES="bad_index \ empty \ empty_index \ index_trailing \ path_empty_prop \ path_only \ path_only_sep \ path_prop" # Test to exercise libfdt overlay application without dtc's overlay support libfdt_overlay_tests () { # First test a doctored overlay which requires only local fixups run_dtc_test -I dts -O dtb -o overlay_base_no_symbols.test.dtb overlay_base.dts run_test check_path overlay_base_no_symbols.test.dtb not-exists "/__symbols__" run_test check_path overlay_base_no_symbols.test.dtb not-exists "/__fixups__" run_test check_path overlay_base_no_symbols.test.dtb not-exists "/__local_fixups__" run_dtc_test -I dts -O dtb -o overlay_overlay_no_fixups.test.dtb overlay_overlay_no_fixups.dts run_test check_path overlay_overlay_no_fixups.test.dtb not-exists "/__symbols__" run_test check_path overlay_overlay_no_fixups.test.dtb not-exists "/__fixups__" run_test check_path overlay_overlay_no_fixups.test.dtb exists "/__local_fixups__" run_test overlay overlay_base_no_symbols.test.dtb overlay_overlay_no_fixups.test.dtb # Then test with manually constructed fixups run_dtc_test -I dts -O dtb -o overlay_base_manual_symbols.test.dtb overlay_base_manual_symbols.dts run_test check_path overlay_base_manual_symbols.test.dtb exists "/__symbols__" run_test check_path overlay_base_manual_symbols.test.dtb not-exists "/__fixups__" run_test check_path overlay_base_manual_symbols.test.dtb not-exists "/__local_fixups__" run_dtc_test -I dts -O dtb -o overlay_overlay_manual_fixups.test.dtb overlay_overlay_manual_fixups.dts run_test check_path overlay_overlay_manual_fixups.test.dtb not-exists "/__symbols__" run_test check_path overlay_overlay_manual_fixups.test.dtb exists "/__fixups__" run_test check_path overlay_overlay_manual_fixups.test.dtb exists "/__local_fixups__" run_test overlay overlay_base_manual_symbols.test.dtb overlay_overlay_manual_fixups.test.dtb + # test simplified plugin syntax + run_dtc_test -@ -I dts -O dtb -o overlay_overlay_simple.dtb overlay_overlay_simple.dts + + # verify non-generation of local fixups + run_test check_path overlay_overlay_simple.dtb not-exists "/__local_fixups__" + # Bad fixup tests for test in $BAD_FIXUP_TREES; do tree="overlay_bad_fixup_$test" run_dtc_test -I dts -O dtb -o $tree.test.dtb $tree.dts run_test overlay_bad_fixup overlay_base_no_symbols.test.dtb $tree.test.dtb done } # Tests to exercise dtc's overlay generation support dtc_overlay_tests () { # Overlay tests for dtc run_dtc_test -@ -I dts -O dtb -o overlay_base.test.dtb overlay_base.dts run_test check_path overlay_base.test.dtb exists "/__symbols__" run_test check_path overlay_base.test.dtb not-exists "/__fixups__" run_test check_path overlay_base.test.dtb not-exists "/__local_fixups__" run_dtc_test -I dts -O dtb -o overlay_overlay.test.dtb overlay_overlay.dts run_test check_path overlay_overlay.test.dtb not-exists "/__symbols__" run_test check_path overlay_overlay.test.dtb exists "/__fixups__" run_test check_path overlay_overlay.test.dtb exists "/__local_fixups__" run_test overlay overlay_base.test.dtb overlay_overlay.test.dtb # test plugin source to dtb and back run_dtc_test -I dtb -O dts -o overlay_overlay_decompile.test.dts overlay_overlay.test.dtb run_dtc_test -I dts -O dtb -o overlay_overlay_decompile.test.dtb overlay_overlay_decompile.test.dts run_test dtbs_equal_ordered overlay_overlay.test.dtb overlay_overlay_decompile.test.dtb # Test generation of aliases insted of symbols run_dtc_test -A -I dts -O dtb -o overlay_base_with_aliases.dtb overlay_base.dts run_test check_path overlay_base_with_aliases.dtb exists "/aliases" run_test check_path overlay_base_with_aliases.dtb not-exists "/__symbols__" run_test check_path overlay_base_with_aliases.dtb not-exists "/__fixups__" run_test check_path overlay_base_with_aliases.dtb not-exists "/__local_fixups__" } tree1_tests () { TREE=$1 # Read-only tests run_test get_mem_rsv $TREE run_test root_node $TREE run_test find_property $TREE run_test subnode_offset $TREE run_test path_offset $TREE run_test get_name $TREE run_test getprop $TREE run_test get_phandle $TREE run_test get_path $TREE run_test supernode_atdepth_offset $TREE run_test parent_offset $TREE run_test node_offset_by_prop_value $TREE run_test node_offset_by_phandle $TREE run_test node_check_compatible $TREE run_test node_offset_by_compatible $TREE run_test notfound $TREE # Write-in-place tests run_test setprop_inplace $TREE run_test nop_property $TREE run_test nop_node $TREE } tree1_tests_rw () { TREE=$1 # Read-write tests run_test set_name $TREE run_test setprop $TREE run_test del_property $TREE run_test del_node $TREE } check_tests () { tree="$1" shift run_sh_test dtc-checkfails.sh "$@" -- -I dts -O dtb $tree run_dtc_test -I dts -O dtb -o $tree.test.dtb -f $tree run_sh_test dtc-checkfails.sh "$@" -- -I dtb -O dtb $tree.test.dtb } ALL_LAYOUTS="mts mst tms tsm smt stm" libfdt_tests () { tree1_tests test_tree1.dtb run_dtc_test -I dts -O dtb -o addresses.test.dtb addresses.dts run_test addr_size_cells addresses.test.dtb run_dtc_test -I dts -O dtb -o stringlist.test.dtb stringlist.dts run_test stringlist stringlist.test.dtb # Sequential write tests run_test sw_tree1 tree1_tests sw_tree1.test.dtb tree1_tests unfinished_tree1.test.dtb run_test dtbs_equal_ordered test_tree1.dtb sw_tree1.test.dtb # Resizing tests for mode in resize realloc; do run_test sw_tree1 $mode tree1_tests sw_tree1.test.dtb tree1_tests unfinished_tree1.test.dtb run_test dtbs_equal_ordered test_tree1.dtb sw_tree1.test.dtb done # fdt_move tests for tree in test_tree1.dtb sw_tree1.test.dtb unfinished_tree1.test.dtb; do rm -f moved.$tree shunted.$tree deshunted.$tree run_test move_and_save $tree run_test dtbs_equal_ordered $tree moved.$tree run_test dtbs_equal_ordered $tree shunted.$tree run_test dtbs_equal_ordered $tree deshunted.$tree done # v16 and alternate layout tests for tree in test_tree1.dtb; do for version in 17 16; do for layout in $ALL_LAYOUTS; do run_test mangle-layout $tree $version $layout tree1_tests v$version.$layout.$tree run_test dtbs_equal_ordered $tree v$version.$layout.$tree done done done # Read-write tests for basetree in test_tree1.dtb; do for version in 17 16; do for layout in $ALL_LAYOUTS; do tree=v$version.$layout.$basetree rm -f opened.$tree repacked.$tree run_test open_pack $tree tree1_tests opened.$tree tree1_tests repacked.$tree tree1_tests_rw $tree tree1_tests_rw opened.$tree tree1_tests_rw repacked.$tree done done done run_test rw_tree1 tree1_tests rw_tree1.test.dtb tree1_tests_rw rw_tree1.test.dtb run_test appendprop1 run_test appendprop2 appendprop1.test.dtb run_dtc_test -I dts -O dtb -o appendprop.test.dtb appendprop.dts run_test dtbs_equal_ordered appendprop2.test.dtb appendprop.test.dtb libfdt_overlay_tests for basetree in test_tree1.dtb sw_tree1.test.dtb rw_tree1.test.dtb; do run_test nopulate $basetree run_test dtbs_equal_ordered $basetree noppy.$basetree tree1_tests noppy.$basetree tree1_tests_rw noppy.$basetree done run_dtc_test -I dts -O dtb -o subnode_iterate.dtb subnode_iterate.dts run_test subnode_iterate subnode_iterate.dtb run_dtc_test -I dts -O dtb -o property_iterate.dtb property_iterate.dts run_test property_iterate property_iterate.dtb # Tests for behaviour on various sorts of corrupted trees run_test truncated_property # Check aliases support in fdt_path_offset run_dtc_test -I dts -O dtb -o aliases.dtb aliases.dts run_test get_alias aliases.dtb run_test path_offset_aliases aliases.dtb # Specific bug tests run_test add_subnode_with_nops run_dtc_test -I dts -O dts -o sourceoutput.test.dts sourceoutput.dts run_dtc_test -I dts -O dtb -o sourceoutput.test.dtb sourceoutput.dts run_dtc_test -I dts -O dtb -o sourceoutput.test.dts.test.dtb sourceoutput.test.dts run_test dtbs_equal_ordered sourceoutput.test.dtb sourceoutput.test.dts.test.dtb run_dtc_test -I dts -O dtb -o embedded_nul.test.dtb embedded_nul.dts run_dtc_test -I dts -O dtb -o embedded_nul_equiv.test.dtb embedded_nul_equiv.dts run_test dtbs_equal_ordered embedded_nul.test.dtb embedded_nul_equiv.test.dtb run_dtc_test -I dts -O dtb bad-size-cells.dts run_wrap_error_test $DTC division-by-zero.dts run_wrap_error_test $DTC bad-octal-literal.dts run_dtc_test -I dts -O dtb nul-in-escape.dts run_wrap_error_test $DTC nul-in-line-info1.dts run_wrap_error_test $DTC nul-in-line-info2.dts run_wrap_error_test $DTC -I dtb -O dts -o /dev/null ovf_size_strings.dtb } dtc_tests () { run_dtc_test -I dts -O dtb -o dtc_tree1.test.dtb test_tree1.dts tree1_tests dtc_tree1.test.dtb tree1_tests_rw dtc_tree1.test.dtb run_test dtbs_equal_ordered dtc_tree1.test.dtb test_tree1.dtb run_dtc_test -I dts -O dtb -o dtc_escapes.test.dtb propname_escapes.dts run_test propname_escapes dtc_escapes.test.dtb run_dtc_test -I dts -O dtb -o line_directives.test.dtb line_directives.dts run_dtc_test -I dts -O dtb -o dtc_escapes.test.dtb escapes.dts run_test string_escapes dtc_escapes.test.dtb run_dtc_test -I dts -O dtb -o dtc_char_literal.test.dtb char_literal.dts run_test char_literal dtc_char_literal.test.dtb run_dtc_test -I dts -O dtb -o dtc_sized_cells.test.dtb sized_cells.dts run_test sized_cells dtc_sized_cells.test.dtb run_dtc_test -I dts -O dtb -o dtc_extra-terminating-null.test.dtb extra-terminating-null.dts run_test extra-terminating-null dtc_extra-terminating-null.test.dtb run_dtc_test -I dts -O dtb -o dtc_references.test.dtb references.dts run_test references dtc_references.test.dtb run_dtc_test -I dts -O dtb -o dtc_path-references.test.dtb path-references.dts run_test path-references dtc_path-references.test.dtb - run_test phandle_format dtc_references.test.dtb both + run_test phandle_format dtc_references.test.dtb epapr for f in legacy epapr both; do run_dtc_test -I dts -O dtb -H $f -o dtc_references.test.$f.dtb references.dts run_test phandle_format dtc_references.test.$f.dtb $f done run_dtc_test -I dts -O dtb -o multilabel.test.dtb multilabel.dts run_test references multilabel.test.dtb run_dtc_test -I dts -O dtb -o label_repeated.test.dtb label_repeated.dts run_dtc_test -I dts -O dtb -o dtc_comments.test.dtb comments.dts run_dtc_test -I dts -O dtb -o dtc_comments-cmp.test.dtb comments-cmp.dts run_test dtbs_equal_ordered dtc_comments.test.dtb dtc_comments-cmp.test.dtb # Check /include/ directive run_dtc_test -I dts -O dtb -o includes.test.dtb include0.dts run_test dtbs_equal_ordered includes.test.dtb test_tree1.dtb # Check /incbin/ directive run_dtc_test -I dts -O dtb -o incbin.test.dtb incbin.dts run_test incbin incbin.test.dtb # Check boot_cpuid_phys handling run_dtc_test -I dts -O dtb -o boot_cpuid.test.dtb boot-cpuid.dts run_test boot-cpuid boot_cpuid.test.dtb 16 run_dtc_test -I dts -O dtb -b 17 -o boot_cpuid_17.test.dtb boot-cpuid.dts run_test boot-cpuid boot_cpuid_17.test.dtb 17 run_dtc_test -I dtb -O dtb -o preserve_boot_cpuid.test.dtb boot_cpuid.test.dtb run_test boot-cpuid preserve_boot_cpuid.test.dtb 16 run_test dtbs_equal_ordered preserve_boot_cpuid.test.dtb boot_cpuid.test.dtb run_dtc_test -I dtb -O dtb -o preserve_boot_cpuid_17.test.dtb boot_cpuid_17.test.dtb run_test boot-cpuid preserve_boot_cpuid_17.test.dtb 17 run_test dtbs_equal_ordered preserve_boot_cpuid_17.test.dtb boot_cpuid_17.test.dtb run_dtc_test -I dtb -O dtb -b17 -o override17_boot_cpuid.test.dtb boot_cpuid.test.dtb run_test boot-cpuid override17_boot_cpuid.test.dtb 17 run_dtc_test -I dtb -O dtb -b0 -o override0_boot_cpuid_17.test.dtb boot_cpuid_17.test.dtb run_test boot-cpuid override0_boot_cpuid_17.test.dtb 0 # Check -Oasm mode for tree in test_tree1.dts escapes.dts references.dts path-references.dts \ comments.dts aliases.dts include0.dts incbin.dts \ value-labels.dts ; do run_dtc_test -I dts -O asm -o oasm_$tree.test.s $tree asm_to_so_test oasm_$tree run_dtc_test -I dts -O dtb -o $tree.test.dtb $tree run_test asm_tree_dump ./oasm_$tree.test.so oasm_$tree.test.dtb run_wrap_test cmp oasm_$tree.test.dtb $tree.test.dtb done run_test value-labels ./oasm_value-labels.dts.test.so # Check -Odts mode preserve all dtb information for tree in test_tree1.dtb dtc_tree1.test.dtb dtc_escapes.test.dtb \ dtc_extra-terminating-null.test.dtb dtc_references.test.dtb; do run_dtc_test -I dtb -O dts -o odts_$tree.test.dts $tree run_dtc_test -I dts -O dtb -o odts_$tree.test.dtb odts_$tree.test.dts run_test dtbs_equal_ordered $tree odts_$tree.test.dtb done # Check version conversions for tree in test_tree1.dtb ; do for aver in 1 2 3 16 17; do atree="ov${aver}_$tree.test.dtb" run_dtc_test -I dtb -O dtb -V$aver -o $atree $tree for bver in 16 17; do btree="ov${bver}_$atree" run_dtc_test -I dtb -O dtb -V$bver -o $btree $atree run_test dtbs_equal_ordered $btree $tree done done done # Check merge/overlay functionality run_dtc_test -I dts -O dtb -o dtc_tree1_merge.test.dtb test_tree1_merge.dts tree1_tests dtc_tree1_merge.test.dtb test_tree1.dtb run_dtc_test -I dts -O dtb -o dtc_tree1_merge_labelled.test.dtb test_tree1_merge_labelled.dts tree1_tests dtc_tree1_merge_labelled.test.dtb test_tree1.dtb run_dtc_test -I dts -O dtb -o dtc_tree1_label_noderef.test.dtb test_tree1_label_noderef.dts run_test dtbs_equal_unordered dtc_tree1_label_noderef.test.dtb test_tree1.dtb run_dtc_test -I dts -O dtb -o multilabel_merge.test.dtb multilabel_merge.dts run_test references multilabel.test.dtb run_test dtbs_equal_ordered multilabel.test.dtb multilabel_merge.test.dtb run_dtc_test -I dts -O dtb -o dtc_tree1_merge_path.test.dtb test_tree1_merge_path.dts tree1_tests dtc_tree1_merge_path.test.dtb test_tree1.dtb run_wrap_error_test $DTC -I dts -O dtb -o /dev/null test_label_ref.dts # Check prop/node delete functionality run_dtc_test -I dts -O dtb -o dtc_tree1_delete.test.dtb test_tree1_delete.dts tree1_tests dtc_tree1_delete.test.dtb run_dtc_test -I dts -O dts -o delete_reinstate_multilabel.dts.test.dts delete_reinstate_multilabel.dts run_wrap_test cmp delete_reinstate_multilabel.dts.test.dts delete_reinstate_multilabel_ref.dts # Check some checks check_tests dup-nodename.dts duplicate_node_names check_tests dup-propname.dts duplicate_property_names check_tests dup-phandle.dts explicit_phandles check_tests zero-phandle.dts explicit_phandles check_tests minusone-phandle.dts explicit_phandles run_sh_test dtc-checkfails.sh phandle_references -- -I dts -O dtb nonexist-node-ref.dts run_sh_test dtc-checkfails.sh phandle_references -- -I dts -O dtb nonexist-label-ref.dts run_sh_test dtc-fatal.sh -I dts -O dtb nonexist-node-ref2.dts check_tests bad-name-property.dts name_properties check_tests bad-ncells.dts address_cells_is_cell size_cells_is_cell interrupt_cells_is_cell - check_tests bad-string-props.dts device_type_is_string model_is_string status_is_string + check_tests bad-string-props.dts device_type_is_string model_is_string status_is_string label_is_string compatible_is_string_list names_is_string_list + check_tests bad-chosen.dts chosen_node_is_root + check_tests bad-chosen.dts chosen_node_bootargs + check_tests bad-chosen.dts chosen_node_stdout_path check_tests bad-reg-ranges.dts reg_format ranges_format check_tests bad-empty-ranges.dts ranges_format check_tests reg-ranges-root.dts reg_format ranges_format check_tests default-addr-size.dts avoid_default_addr_size check_tests obsolete-chosen-interrupt-controller.dts obsolete_chosen_interrupt_controller check_tests reg-without-unit-addr.dts unit_address_vs_reg check_tests unit-addr-without-reg.dts unit_address_vs_reg + check_tests unit-addr-leading-0x.dts unit_address_format + check_tests unit-addr-leading-0s.dts unit_address_format + check_tests bad-phandle-cells.dts interrupts_extended_property + check_tests bad-gpio.dts gpios_property + run_sh_test dtc-checkfails.sh deprecated_gpio_property -- -Wdeprecated_gpio_property -I dts -O dtb bad-gpio.dts + check_tests bad-interrupt-cells.dts interrupts_property run_sh_test dtc-checkfails.sh node_name_chars -- -I dtb -O dtb bad_node_char.dtb run_sh_test dtc-checkfails.sh node_name_format -- -I dtb -O dtb bad_node_format.dtb run_sh_test dtc-checkfails.sh prop_name_chars -- -I dtb -O dtb bad_prop_char.dtb run_sh_test dtc-checkfails.sh duplicate_label -- -I dts -O dtb reuse-label1.dts run_sh_test dtc-checkfails.sh duplicate_label -- -I dts -O dtb reuse-label2.dts run_sh_test dtc-checkfails.sh duplicate_label -- -I dts -O dtb reuse-label3.dts run_sh_test dtc-checkfails.sh duplicate_label -- -I dts -O dtb reuse-label4.dts run_sh_test dtc-checkfails.sh duplicate_label -- -I dts -O dtb reuse-label5.dts run_sh_test dtc-checkfails.sh duplicate_label -- -I dts -O dtb reuse-label6.dts run_test check_path test_tree1.dtb exists "/subnode@1" run_test check_path test_tree1.dtb not-exists "/subnode@10" + check_tests pci-bridge-ok.dts -n pci_bridge + check_tests pci-bridge-bad1.dts pci_bridge + check_tests pci-bridge-bad2.dts pci_bridge + # Check warning options run_sh_test dtc-checkfails.sh address_cells_is_cell interrupt_cells_is_cell -n size_cells_is_cell -- -Wno_size_cells_is_cell -I dts -O dtb bad-ncells.dts run_sh_test dtc-fails.sh -n test-warn-output.test.dtb -I dts -O dtb bad-ncells.dts run_sh_test dtc-fails.sh test-error-output.test.dtb -I dts -O dtb bad-ncells.dts -Esize_cells_is_cell run_sh_test dtc-checkfails.sh always_fail -- -Walways_fail -I dts -O dtb test_tree1.dts run_sh_test dtc-checkfails.sh -n always_fail -- -Walways_fail -Wno_always_fail -I dts -O dtb test_tree1.dts run_sh_test dtc-fails.sh test-negation-1.test.dtb -Ealways_fail -I dts -O dtb test_tree1.dts run_sh_test dtc-fails.sh -n test-negation-2.test.dtb -Ealways_fail -Eno_always_fail -I dts -O dtb test_tree1.dts run_sh_test dtc-fails.sh test-negation-3.test.dtb -Ealways_fail -Wno_always_fail -I dts -O dtb test_tree1.dts run_sh_test dtc-fails.sh -n test-negation-4.test.dtb -Esize_cells_is_cell -Eno_size_cells_is_cell -I dts -O dtb bad-ncells.dts run_sh_test dtc-checkfails.sh size_cells_is_cell -- -Esize_cells_is_cell -Eno_size_cells_is_cell -I dts -O dtb bad-ncells.dts # Check for proper behaviour reading from stdin run_dtc_test -I dts -O dtb -o stdin_dtc_tree1.test.dtb - < test_tree1.dts run_wrap_test cmp stdin_dtc_tree1.test.dtb dtc_tree1.test.dtb run_dtc_test -I dtb -O dts -o stdin_odts_test_tree1.dtb.test.dts - < test_tree1.dtb run_wrap_test cmp stdin_odts_test_tree1.dtb.test.dts odts_test_tree1.dtb.test.dts # Check integer expresisons run_test integer-expressions -g integer-expressions.test.dts run_dtc_test -I dts -O dtb -o integer-expressions.test.dtb integer-expressions.test.dts run_test integer-expressions integer-expressions.test.dtb # Check for graceful failure in some error conditions run_sh_test dtc-fatal.sh -I dts -O dtb nosuchfile.dts run_sh_test dtc-fatal.sh -I dtb -O dtb nosuchfile.dtb run_sh_test dtc-fatal.sh -I fs -O dtb nosuchfile # Dependencies run_dtc_test -I dts -O dtb -o dependencies.test.dtb -d dependencies.test.d dependencies.dts run_wrap_test cmp dependencies.test.d dependencies.cmp # Search paths run_wrap_error_test $DTC -I dts -O dtb -o search_paths.dtb search_paths.dts run_dtc_test -i search_dir -I dts -O dtb -o search_paths.dtb \ search_paths.dts run_wrap_error_test $DTC -i search_dir_b -I dts -O dtb \ -o search_paths_b.dtb search_paths_b.dts run_dtc_test -i search_dir_b -i search_dir -I dts -O dtb \ -o search_paths_b.dtb search_paths_b.dts run_dtc_test -I dts -O dtb -o search_paths_subdir.dtb \ search_dir_b/search_paths_subdir.dts # Check -a option for align in 2 4 8 16 32 64; do # -p -a run_dtc_test -O dtb -p 1000 -a $align -o align0.dtb subnode_iterate.dts check_align align0.dtb $align # -S -a run_dtc_test -O dtb -S 1999 -a $align -o align1.dtb subnode_iterate.dts check_align align1.dtb $align done # Tests for overlay/plugin generation dtc_overlay_tests } cmp_tests () { basetree="$1" shift wrongtrees="$@" run_test dtb_reverse $basetree # First dtbs_equal_ordered run_test dtbs_equal_ordered $basetree $basetree run_test dtbs_equal_ordered -n $basetree $basetree.reversed.test.dtb for tree in $wrongtrees; do run_test dtbs_equal_ordered -n $basetree $tree done # now unordered run_test dtbs_equal_unordered $basetree $basetree run_test dtbs_equal_unordered $basetree $basetree.reversed.test.dtb run_test dtbs_equal_unordered $basetree.reversed.test.dtb $basetree for tree in $wrongtrees; do run_test dtbs_equal_unordered -n $basetree $tree done # now dtc --sort run_dtc_test -I dtb -O dtb -s -o $basetree.sorted.test.dtb $basetree run_test dtbs_equal_unordered $basetree $basetree.sorted.test.dtb run_dtc_test -I dtb -O dtb -s -o $basetree.reversed.sorted.test.dtb $basetree.reversed.test.dtb run_test dtbs_equal_unordered $basetree.reversed.test.dtb $basetree.reversed.sorted.test.dtb run_test dtbs_equal_ordered $basetree.sorted.test.dtb $basetree.reversed.sorted.test.dtb } dtbs_equal_tests () { WRONG_TREE1="" for x in 1 2 3 4 5 6 7 8 9; do run_dtc_test -I dts -O dtb -o test_tree1_wrong$x.test.dtb test_tree1_wrong$x.dts WRONG_TREE1="$WRONG_TREE1 test_tree1_wrong$x.test.dtb" done cmp_tests test_tree1.dtb $WRONG_TREE1 } fdtget_tests () { dts=label01.dts dtb=$dts.fdtget.test.dtb run_dtc_test -O dtb -o $dtb $dts # run_fdtget_test [] run_fdtget_test "MyBoardName" $dtb / model run_fdtget_test "MyBoardName MyBoardFamilyName" $dtb / compatible run_fdtget_test "77 121 66 111 \ 97 114 100 78 97 109 101 0 77 121 66 111 97 114 100 70 97 109 105 \ 108 121 78 97 109 101 0" -t bu $dtb / compatible run_fdtget_test "MyBoardName MyBoardFamilyName" -t s $dtb / compatible run_fdtget_test 32768 $dtb /cpus/PowerPC,970@1 d-cache-size run_fdtget_test 8000 -tx $dtb /cpus/PowerPC,970@1 d-cache-size run_fdtget_test "61 62 63 0" -tbx $dtb /randomnode tricky1 run_fdtget_test "a b c d de ea ad be ef" -tbx $dtb /randomnode blob # Here the property size is not a multiple of 4 bytes, so it should fail run_wrap_error_test $DTGET -tlx $dtb /randomnode mixed run_fdtget_test "6162 6300 1234 0 a 0 b 0 c" -thx $dtb /randomnode mixed run_fdtget_test "61 62 63 0 12 34 0 0 0 a 0 0 0 b 0 0 0 c" \ -thhx $dtb /randomnode mixed run_wrap_error_test $DTGET -ts $dtb /randomnode doctor-who # Test multiple arguments run_fdtget_test "MyBoardName\nmemory" -ts $dtb / model /memory device_type # Test defaults run_wrap_error_test $DTGET -tx $dtb /randomnode doctor-who run_fdtget_test "" -tx \ -d "" $dtb /randomnode doctor-who run_fdtget_test "" -tx -d "" $dtb /memory doctor-who } fdtput_tests () { dts=label01.dts dtb=$dts.fdtput.test.dtb text=lorem.txt # Allow just enough space for $text - run_dtc_test -O dtb -p $(stat -c %s $text) -o $dtb $dts + run_dtc_test -O dtb -p $($STATSZ $text) -o $dtb $dts # run_fdtput_test run_fdtput_test "a_model" $dtb / model -ts "a_model" run_fdtput_test "board1 board2" $dtb / compatible -ts board1 board2 run_fdtput_test "board1 board2" $dtb / compatible -ts "board1 board2" run_fdtput_test "32768" $dtb /cpus/PowerPC,970@1 d-cache-size "" "32768" run_fdtput_test "8001" $dtb /cpus/PowerPC,970@1 d-cache-size -tx 0x8001 run_fdtput_test "2 3 12" $dtb /randomnode tricky1 -tbi "02 003 12" run_fdtput_test "a b c ea ad be ef" $dtb /randomnode blob \ -tbx "a b c ea ad be ef" run_fdtput_test "a0b0c0d deeaae ef000000" $dtb /randomnode blob \ -tx "a0b0c0d deeaae ef000000" run_fdtput_test "$(cat $text)" $dtb /randomnode blob -ts "$(cat $text)" # Test expansion of the blob when insufficient room for property run_fdtput_test "$(cat $text $text)" $dtb /randomnode blob -ts "$(cat $text $text)" # Start again with a fresh dtb - run_dtc_test -O dtb -p $(stat -c %s $text) -o $dtb $dts + run_dtc_test -O dtb -p $($STATSZ $text) -o $dtb $dts # Node creation run_wrap_error_test $DTPUT $dtb -c /baldrick sod run_wrap_test $DTPUT $dtb -c /chosen/son /chosen/daughter run_fdtput_test "eva" $dtb /chosen/daughter name "" -ts "eva" run_fdtput_test "adam" $dtb /chosen/son name "" -ts "adam" # Not allowed to create an existing node run_wrap_error_test $DTPUT $dtb -c /chosen run_wrap_error_test $DTPUT $dtb -c /chosen/son # Automatic node creation run_wrap_test $DTPUT $dtb -cp /blackadder/the-second/turnip \ /blackadder/the-second/potato run_fdtput_test 1000 $dtb /blackadder/the-second/turnip cost "" 1000 run_fdtput_test "fine wine" $dtb /blackadder/the-second/potato drink \ "-ts" "fine wine" run_wrap_test $DTPUT $dtb -p /you/are/drunk/sir/winston slurp -ts twice # Test expansion of the blob when insufficent room for a new node run_wrap_test $DTPUT $dtb -cp "$(cat $text $text)/longish" # Allowed to create an existing node with -p run_wrap_test $DTPUT $dtb -cp /chosen run_wrap_test $DTPUT $dtb -cp /chosen/son # Start again with a fresh dtb - run_dtc_test -O dtb -p $(stat -c %s $text) -o $dtb $dts + run_dtc_test -O dtb -p $($STATSZ $text) -o $dtb $dts # Node delete run_wrap_test $DTPUT $dtb -c /chosen/node1 /chosen/node2 /chosen/node3 run_fdtget_test "node3\nnode2\nnode1" $dtb -l /chosen run_wrap_test $DTPUT $dtb -r /chosen/node1 /chosen/node2 run_fdtget_test "node3" $dtb -l /chosen # Delete the non-existent node run_wrap_error_test $DTPUT $dtb -r /non-existent/node # Property delete run_fdtput_test "eva" $dtb /chosen/ name "" -ts "eva" run_fdtput_test "016" $dtb /chosen/ age "" -ts "016" run_fdtget_test "age\nname\nbootargs\nlinux,platform" $dtb -p /chosen run_wrap_test $DTPUT $dtb -d /chosen/ name age run_fdtget_test "bootargs\nlinux,platform" $dtb -p /chosen # Delete the non-existent property run_wrap_error_test $DTPUT $dtb -d /chosen non-existent-prop # TODO: Add tests for verbose mode? } utilfdt_tests () { run_test utilfdt_test } fdtdump_tests () { run_fdtdump_test fdtdump.dts } +fdtoverlay_tests() { + base=overlay_base.dts + basedtb=overlay_base.fdoverlay.test.dtb + overlay=overlay_overlay_manual_fixups.dts + overlaydtb=overlay_overlay_manual_fixups.fdoverlay.test.dtb + targetdtb=target.fdoverlay.test.dtb + + run_dtc_test -@ -I dts -O dtb -o $basedtb $base + run_dtc_test -@ -I dts -O dtb -o $overlaydtb $overlay + + # test that the new property is installed + run_fdtoverlay_test foobar "/test-node" "test-str-property" "-ts" ${basedtb} ${targetdtb} ${overlaydtb} + + stacked_base=stacked_overlay_base.dts + stacked_basedtb=stacked_overlay_base.fdtoverlay.test.dtb + stacked_bar=stacked_overlay_bar.dts + stacked_bardtb=stacked_overlay_bar.fdtoverlay.test.dtb + stacked_baz=stacked_overlay_baz.dts + stacked_bazdtb=stacked_overlay_baz.fdtoverlay.test.dtb + stacked_targetdtb=stacked_overlay_target.fdtoverlay.test.dtb + + run_dtc_test -@ -I dts -O dtb -o $stacked_basedtb $stacked_base + run_dtc_test -@ -I dts -O dtb -o $stacked_bardtb $stacked_bar + run_dtc_test -@ -I dts -O dtb -o $stacked_bazdtb $stacked_baz + + # test that baz correctly inserted the property + run_fdtoverlay_test baz "/foonode/barnode/baznode" "baz-property" "-ts" ${stacked_basedtb} ${stacked_targetdtb} ${stacked_bardtb} ${stacked_bazdtb} +} + +pylibfdt_tests () { + TMP=/tmp/tests.stderr.$$ + python pylibfdt_tests.py -v 2> $TMP + + # Use the 'ok' message meaning the test passed, 'ERROR' meaning it failed + # and the summary line for total tests (e.g. 'Ran 17 tests in 0.002s'). + # We could add pass + fail to get total tests, but this provides a useful + # sanity check. + pass_count=$(grep "\.\.\. ok$" $TMP | wc -l) + fail_count=$(grep "^ERROR: " $TMP | wc -l) + total_tests=$(sed -n 's/^Ran \([0-9]*\) tests.*$/\1/p' $TMP) + cat $TMP + rm $TMP + + # Extract the test results and add them to our totals + tot_fail=$((tot_fail + $fail_count)) + tot_pass=$((tot_pass + $pass_count)) + tot_tests=$((tot_tests + $total_tests)) +} + while getopts "vt:me" ARG ; do case $ARG in "v") unset QUIET_TEST ;; "t") TESTSETS=$OPTARG ;; "m") VALGRIND="valgrind --tool=memcheck -q --error-exitcode=$VGCODE" ;; "e") STOP_ON_FAIL=1 ;; esac done if [ -z "$TESTSETS" ]; then - TESTSETS="libfdt utilfdt dtc dtbs_equal fdtget fdtput fdtdump" + TESTSETS="libfdt utilfdt dtc dtbs_equal fdtget fdtput fdtdump fdtoverlay" + + # Test pylibfdt if the libfdt Python module is available. + if [ -f ../pylibfdt/_libfdt.so ]; then + TESTSETS="$TESTSETS pylibfdt" + fi fi # Make sure we don't have stale blobs lying around rm -f *.test.dtb *.test.dts for set in $TESTSETS; do case $set in "libfdt") libfdt_tests ;; "utilfdt") utilfdt_tests ;; "dtc") dtc_tests ;; "dtbs_equal") dtbs_equal_tests ;; "fdtget") fdtget_tests ;; "fdtput") fdtput_tests ;; "fdtdump") fdtdump_tests ;; + "pylibfdt") + pylibfdt_tests + ;; + "fdtoverlay") + fdtoverlay_tests + ;; esac done echo "********** TEST SUMMARY" echo "* Total testcases: $tot_tests" echo "* PASS: $tot_pass" echo "* FAIL: $tot_fail" echo "* Bad configuration: $tot_config" if [ -n "$VALGRIND" ]; then echo "* valgrind errors: $tot_vg" fi echo "* Strange test result: $tot_strange" echo "**********" +[ "$tot_tests" -eq "$tot_pass" ] || exit 1 Index: vendor/dtc/dist/tests/sized_cells.c =================================================================== --- vendor/dtc/dist/tests/sized_cells.c (revision 327892) +++ vendor/dtc/dist/tests/sized_cells.c (revision 327893) @@ -1,83 +1,83 @@ /* * libfdt - Flat Device Tree manipulation * Testcase for variable sized cells in dtc * Copyright (C) 2006 David Gibson, IBM Corporation. * Copyright (C) 2011 The Chromium Authors. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include "tests.h" #include "testdata.h" static void check_compare_properties(void *fdt, char const *name_one, char const *name_two) { const void *propval; int proplen; propval = fdt_getprop(fdt, 0, name_one, &proplen); if (!propval) FAIL("fdt_getprop(\"%s\"): %s", name_one, fdt_strerror(proplen)); check_getprop(fdt, 0, name_two, proplen, propval); } int main(int argc, char *argv[]) { void *fdt; uint8_t expected_8[6] = {TEST_CHAR1, TEST_CHAR2, TEST_CHAR3, TEST_CHAR4, TEST_CHAR5, TEST_VALUE_1 >> 24}; - uint16_t expected_16[6]; - uint32_t expected_32[6]; - uint64_t expected_64[6]; + fdt16_t expected_16[6]; + fdt32_t expected_32[6]; + fdt64_t expected_64[6]; int i; for (i = 0; i < 5; ++i) { expected_16[i] = cpu_to_fdt16(expected_8[i]); expected_32[i] = cpu_to_fdt32(expected_8[i]); expected_64[i] = cpu_to_fdt64(expected_8[i]); } expected_16[5] = cpu_to_fdt16(TEST_VALUE_1 >> 16); expected_32[5] = cpu_to_fdt32(TEST_VALUE_1); expected_64[5] = cpu_to_fdt64(TEST_ADDR_1); test_init(argc, argv); fdt = load_blob_arg(argc, argv); check_getprop(fdt, 0, "cells-8b", sizeof(expected_8), expected_8); check_getprop(fdt, 0, "cells-16b", sizeof(expected_16), expected_16); check_getprop(fdt, 0, "cells-32b", sizeof(expected_32), expected_32); check_getprop(fdt, 0, "cells-64b", sizeof(expected_64), expected_64); check_compare_properties(fdt, "cells-one-16b", "cells-one-32b"); PASS(); } Index: vendor/dtc/dist/tests/stacked_overlay_bar.dts =================================================================== --- vendor/dtc/dist/tests/stacked_overlay_bar.dts (nonexistent) +++ vendor/dtc/dist/tests/stacked_overlay_bar.dts (revision 327893) @@ -0,0 +1,13 @@ +/dts-v1/; +/plugin/; +/ { + fragment@1 { + target = <&foo>; + __overlay__ { + overlay-1-property; + bar: barnode { + bar-property = "bar"; + }; + }; + }; +}; Property changes on: vendor/dtc/dist/tests/stacked_overlay_bar.dts ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/dtc/dist/tests/stacked_overlay_base.dts =================================================================== --- vendor/dtc/dist/tests/stacked_overlay_base.dts (nonexistent) +++ vendor/dtc/dist/tests/stacked_overlay_base.dts (revision 327893) @@ -0,0 +1,6 @@ +/dts-v1/; +/ { + foo: foonode { + foo-property = "foo"; + }; +}; Property changes on: vendor/dtc/dist/tests/stacked_overlay_base.dts ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/dtc/dist/tests/stacked_overlay_baz.dts =================================================================== --- vendor/dtc/dist/tests/stacked_overlay_baz.dts (nonexistent) +++ vendor/dtc/dist/tests/stacked_overlay_baz.dts (revision 327893) @@ -0,0 +1,13 @@ +/dts-v1/; +/plugin/; +/ { + fragment@1 { + target = <&bar>; + __overlay__ { + overlay-2-property; + baz: baznode { + baz-property = "baz"; + }; + }; + }; +}; Property changes on: vendor/dtc/dist/tests/stacked_overlay_baz.dts ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/dtc/dist/tests/stringlist.c =================================================================== --- vendor/dtc/dist/tests/stringlist.c (revision 327892) +++ vendor/dtc/dist/tests/stringlist.c (revision 327893) @@ -1,154 +1,155 @@ /* * libfdt - Flat Device Tree manipulation * Testcase for string handling * Copyright (C) 2015 NVIDIA Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include "tests.h" #include "testdata.h" static void check_expected_failure(const void *fdt, const char *path, const char *property) { int offset, err; offset = fdt_path_offset(fdt, "/"); if (offset < 0) FAIL("Couldn't find path %s", path); err = fdt_stringlist_count(fdt, offset, "#address-cells"); if (err != -FDT_ERR_BADVALUE) FAIL("unexpectedly succeeded in parsing #address-cells\n"); err = fdt_stringlist_search(fdt, offset, "#address-cells", "foo"); if (err != -FDT_ERR_BADVALUE) FAIL("found string in #address-cells: %d\n", err); /* * Note that the #address-cells property contains a small 32-bit * unsigned integer, hence some bytes will be zero, and searching for * the empty string will succeed. * * The reason for this oddity is that the function will exit when the * first occurrence of the string is found, but in order to determine * that the property does not contain a valid string list it would * need to process the whole value. */ err = fdt_stringlist_search(fdt, offset, "#address-cells", ""); if (err != 0) FAIL("empty string not found in #address-cells: %d\n", err); /* - * fdt_get_string() can successfully extract strings from non-string - * properties. This is because it doesn't necessarily parse the whole - * property value, which would be necessary for it to determine if a - * valid string or string list is present. + * fdt_getprop_string() can successfully extract strings from + * non-string properties. This is because it doesn't + * necessarily parse the whole property value, which would be + * necessary for it to determine if a valid string or string + * list is present. */ } static void check_string_count(const void *fdt, const char *path, const char *property, int count) { int offset, err; offset = fdt_path_offset(fdt, path); if (offset < 0) FAIL("Couldn't find path %s", path); err = fdt_stringlist_count(fdt, offset, property); if (err < 0) FAIL("Couldn't count strings in property %s of node %s: %d\n", property, path, err); if (err != count) FAIL("String count for property %s of node %s is %d instead of %d\n", path, property, err, count); } static void check_string_index(const void *fdt, const char *path, const char *property, const char *string, int idx) { int offset, err; offset = fdt_path_offset(fdt, path); if (offset < 0) FAIL("Couldn't find path %s", path); err = fdt_stringlist_search(fdt, offset, property, string); if (err != idx) FAIL("Index of %s in property %s of node %s is %d, expected %d\n", string, property, path, err, idx); } static void check_string(const void *fdt, const char *path, const char *property, int idx, const char *string) { const char *result; int offset, len; offset = fdt_path_offset(fdt, path); if (offset < 0) FAIL("Couldn't find path %s", path); result = fdt_stringlist_get(fdt, offset, property, idx, &len); if (!result) FAIL("Couldn't extract string %d from property %s of node %s: %d\n", idx, property, path, len); if (strcmp(string, result) != 0) FAIL("String %d in property %s of node %s is %s, expected %s\n", idx, property, path, result, string); } int main(int argc, char *argv[]) { void *fdt; if (argc != 2) CONFIG("Usage: %s \n", argv[0]); test_init(argc, argv); fdt = load_blob(argv[1]); check_expected_failure(fdt, "/", "#address-cells"); check_expected_failure(fdt, "/", "#size-cells"); check_string_count(fdt, "/", "compatible", 1); check_string_count(fdt, "/device", "compatible", 2); check_string_count(fdt, "/device", "big-endian", 0); check_string_index(fdt, "/", "compatible", "test-strings", 0); check_string_index(fdt, "/device", "compatible", "foo", 0); check_string_index(fdt, "/device", "compatible", "bar", 1); check_string_index(fdt, "/device", "big-endian", "baz", -1); check_string(fdt, "/", "compatible", 0, "test-strings"); check_string(fdt, "/device", "compatible", 0, "foo"); check_string(fdt, "/device", "compatible", 1, "bar"); PASS(); } Index: vendor/dtc/dist/tests/subnode_iterate.c =================================================================== --- vendor/dtc/dist/tests/subnode_iterate.c (revision 327892) +++ vendor/dtc/dist/tests/subnode_iterate.c (revision 327893) @@ -1,90 +1,90 @@ /* * libfdt - Flat Device Tree manipulation * Tests that fdt_next_subnode() works as expected * * Copyright (C) 2013 Google, Inc * * Copyright (C) 2007 David Gibson, IBM Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include "tests.h" #include "testdata.h" static void test_node(void *fdt, int parent_offset) { - fdt32_t subnodes; + uint32_t subnodes; const fdt32_t *prop; int offset; int count; int len; /* This property indicates the number of subnodes to expect */ prop = fdt_getprop(fdt, parent_offset, "subnodes", &len); if (!prop || len != sizeof(fdt32_t)) { FAIL("Missing/invalid subnodes property at '%s'", fdt_get_name(fdt, parent_offset, NULL)); } - subnodes = cpu_to_fdt32(*prop); + subnodes = fdt32_to_cpu(*prop); count = 0; fdt_for_each_subnode(offset, fdt, parent_offset) count++; if (count != subnodes) { FAIL("Node '%s': Expected %d subnodes, got %d\n", fdt_get_name(fdt, parent_offset, NULL), subnodes, count); } } static void check_fdt_next_subnode(void *fdt) { int offset; int count = 0; fdt_for_each_subnode(offset, fdt, 0) { test_node(fdt, offset); count++; } if (count != 2) FAIL("Expected %d tests, got %d\n", 2, count); } int main(int argc, char *argv[]) { void *fdt; test_init(argc, argv); if (argc != 2) CONFIG("Usage: %s ", argv[0]); fdt = load_blob(argv[1]); if (!fdt) FAIL("No device tree available"); check_fdt_next_subnode(fdt); PASS(); } Index: vendor/dtc/dist/tests/sw_tree1.c =================================================================== --- vendor/dtc/dist/tests/sw_tree1.c (revision 327892) +++ vendor/dtc/dist/tests/sw_tree1.c (revision 327893) @@ -1,174 +1,181 @@ /* * libfdt - Flat Device Tree manipulation * Testcase for fdt_nop_node() * Copyright (C) 2006 David Gibson, IBM Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include "tests.h" #include "testdata.h" #define SPACE 65536 static enum { FIXED = 0, RESIZE, REALLOC, } alloc_mode; static void realloc_fdt(void **fdt, size_t *size, bool created) { switch (alloc_mode) { case FIXED: if (!(*fdt)) - fdt = xmalloc(*size); + *fdt = xmalloc(*size); else FAIL("Ran out of space"); return; case RESIZE: if (!(*fdt)) { - fdt = xmalloc(SPACE); + *fdt = xmalloc(SPACE); } else if (*size < SPACE) { *size += 1; fdt_resize(*fdt, *fdt, *size); } else { FAIL("Ran out of space"); } return; case REALLOC: *size += 1; *fdt = xrealloc(*fdt, *size); if (created) fdt_resize(*fdt, *fdt, *size); return; default: CONFIG("Bad allocation mode"); } } #define CHECK(code) \ do { \ err = (code); \ if (err == -FDT_ERR_NOSPACE) \ realloc_fdt(&fdt, &size, created); \ else if (err) \ FAIL(#code ": %s", fdt_strerror(err)); \ } while (err != 0) int main(int argc, char *argv[]) { void *fdt = NULL; size_t size; int err; bool created = false; + void *place; + const char place_str[] = "this is a placeholder string\0string2"; + int place_len = sizeof(place_str); test_init(argc, argv); if (argc == 1) { alloc_mode = FIXED; size = SPACE; } else if (argc == 2) { if (streq(argv[1], "resize")) { alloc_mode = REALLOC; size = 0; } else if (streq(argv[1], "realloc")) { alloc_mode = REALLOC; size = 0; } else { char *endp; size = strtoul(argv[1], &endp, 0); if (*endp == '\0') alloc_mode = FIXED; else CONFIG("Bad allocation mode \"%s\" specified", argv[1]); } + } else { + CONFIG("sw_tree1 []"); } fdt = xmalloc(size); CHECK(fdt_create(fdt, size)); created = true; CHECK(fdt_add_reservemap_entry(fdt, TEST_ADDR_1, TEST_SIZE_1)); CHECK(fdt_add_reservemap_entry(fdt, TEST_ADDR_2, TEST_SIZE_2)); CHECK(fdt_finish_reservemap(fdt)); CHECK(fdt_begin_node(fdt, "")); CHECK(fdt_property_string(fdt, "compatible", "test_tree1")); CHECK(fdt_property_u32(fdt, "prop-int", TEST_VALUE_1)); CHECK(fdt_property_u64(fdt, "prop-int64", TEST_VALUE64_1)); CHECK(fdt_property_string(fdt, "prop-str", TEST_STRING_1)); CHECK(fdt_property_u32(fdt, "#address-cells", 1)); CHECK(fdt_property_u32(fdt, "#size-cells", 0)); CHECK(fdt_begin_node(fdt, "subnode@1")); CHECK(fdt_property_string(fdt, "compatible", "subnode1")); CHECK(fdt_property_u32(fdt, "reg", 1)); CHECK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_1)); CHECK(fdt_begin_node(fdt, "subsubnode")); CHECK(fdt_property(fdt, "compatible", "subsubnode1\0subsubnode", 23)); + CHECK(fdt_property_placeholder(fdt, "placeholder", place_len, &place)); + memcpy(place, place_str, place_len); CHECK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_1)); CHECK(fdt_end_node(fdt)); CHECK(fdt_begin_node(fdt, "ss1")); CHECK(fdt_end_node(fdt)); CHECK(fdt_end_node(fdt)); CHECK(fdt_begin_node(fdt, "subnode@2")); CHECK(fdt_property_u32(fdt, "reg", 2)); CHECK(fdt_property_cell(fdt, "linux,phandle", PHANDLE_1)); CHECK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_2)); CHECK(fdt_property_u32(fdt, "#address-cells", 1)); CHECK(fdt_property_u32(fdt, "#size-cells", 0)); CHECK(fdt_begin_node(fdt, "subsubnode@0")); CHECK(fdt_property_u32(fdt, "reg", 0)); CHECK(fdt_property_cell(fdt, "phandle", PHANDLE_2)); CHECK(fdt_property(fdt, "compatible", "subsubnode2\0subsubnode", 23)); CHECK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_2)); CHECK(fdt_end_node(fdt)); CHECK(fdt_begin_node(fdt, "ss2")); CHECK(fdt_end_node(fdt)); CHECK(fdt_end_node(fdt)); CHECK(fdt_end_node(fdt)); save_blob("unfinished_tree1.test.dtb", fdt); CHECK(fdt_finish(fdt)); verbose_printf("Completed tree, totalsize = %d\n", fdt_totalsize(fdt)); save_blob("sw_tree1.test.dtb", fdt); PASS(); } Index: vendor/dtc/dist/tests/test_tree1.dts =================================================================== --- vendor/dtc/dist/tests/test_tree1.dts (revision 327892) +++ vendor/dtc/dist/tests/test_tree1.dts (revision 327893) @@ -1,45 +1,46 @@ /dts-v1/; /memreserve/ 0xdeadbeef00000000 0x100000; /memreserve/ 123456789 010000; / { compatible = "test_tree1"; prop-int = <0xdeadbeef>; prop-int64 = /bits/ 64 <0xdeadbeef01abcdef>; prop-str = "hello world"; #address-cells = <1>; #size-cells = <0>; subnode@1 { compatible = "subnode1"; reg = <1>; prop-int = [deadbeef]; subsubnode { compatible = "subsubnode1", "subsubnode"; + placeholder = "this is a placeholder string", "string2"; prop-int = <0xdeadbeef>; }; ss1 { }; }; subnode@2 { reg = <2>; linux,phandle = <0x2000>; prop-int = <123456789>; #address-cells = <1>; #size-cells = <0>; ssn0: subsubnode@0 { reg = <0>; phandle = <0x2001>; compatible = "subsubnode2", "subsubnode"; prop-int = <0726746425>; }; ss2 { }; }; }; Index: vendor/dtc/dist/tests/test_tree1_label_noderef.dts =================================================================== --- vendor/dtc/dist/tests/test_tree1_label_noderef.dts (revision 327892) +++ vendor/dtc/dist/tests/test_tree1_label_noderef.dts (revision 327893) @@ -1,55 +1,56 @@ /dts-v1/; /memreserve/ 0xdeadbeef00000000 0x100000; /memreserve/ 123456789 010000; / { compatible = "test_tree1"; prop-int = <0xdeadbeef>; prop-int64 = /bits/ 64 <0xdeadbeef01abcdef>; prop-str = "hello world"; #address-cells = <1>; #size-cells = <0>; subnode@1 { compatible = "subnode1"; reg = <1>; prop-int = [deadbeef]; subsubnode { compatible = "subsubnode1", "subsubnode"; + placeholder = "this is a placeholder string", "string2"; prop-int = <0xdeadbeef>; }; ss1 { }; }; subnode@2 { reg = <2>; linux,phandle = <0x2000>; prop-int = <123456789>; #address-cells = <1>; #size-cells = <0>; ssn0: subsubnode@0 { phandle = <0x2001>; prop-int = <0xbad>; }; ss2 { }; }; }; /* Add label to a noderef */ ssn1: &ssn0 { reg = <0>; prop-int = <123456789>; }; /* Use the new label for merging */ &ssn1 { prop-int = <0726746425>; compatible = "subsubnode2", "subsubnode"; }; Index: vendor/dtc/dist/tests/testdata.h =================================================================== --- vendor/dtc/dist/tests/testdata.h (revision 327892) +++ vendor/dtc/dist/tests/testdata.h (revision 327893) @@ -1,40 +1,50 @@ #ifdef __ASSEMBLY__ #define ASM_CONST_LL(x) (x) #else #define ASM_CONST_LL(x) (x##ULL) #endif -#define TEST_ADDR_1 ASM_CONST_LL(0xdeadbeef00000000) -#define TEST_SIZE_1 ASM_CONST_LL(0x100000) -#define TEST_ADDR_2 ASM_CONST_LL(123456789) -#define TEST_SIZE_2 ASM_CONST_LL(010000) +#define TEST_ADDR_1H ASM_CONST_LL(0xdeadbeef) +#define TEST_ADDR_1L ASM_CONST_LL(0x00000000) +#define TEST_ADDR_1 ((TEST_ADDR_1H << 32) | TEST_ADDR_1L) +#define TEST_SIZE_1H ASM_CONST_LL(0x00000000) +#define TEST_SIZE_1L ASM_CONST_LL(0x00100000) +#define TEST_SIZE_1 ((TEST_SIZE_1H << 32) | TEST_SIZE_1L) +#define TEST_ADDR_2H ASM_CONST_LL(0) +#define TEST_ADDR_2L ASM_CONST_LL(123456789) +#define TEST_ADDR_2 ((TEST_ADDR_2H << 32) | TEST_ADDR_2L) +#define TEST_SIZE_2H ASM_CONST_LL(0) +#define TEST_SIZE_2L ASM_CONST_LL(010000) +#define TEST_SIZE_2 ((TEST_SIZE_2H << 32) | TEST_SIZE_2L) #define TEST_VALUE_1 0xdeadbeef #define TEST_VALUE_2 123456789 -#define TEST_VALUE64_1 ASM_CONST_LL(0xdeadbeef01abcdef) +#define TEST_VALUE64_1H ASM_CONST_LL(0xdeadbeef) +#define TEST_VALUE64_1L ASM_CONST_LL(0x01abcdef) +#define TEST_VALUE64_1 ((TEST_VALUE64_1H << 32) | TEST_VALUE64_1L) #define PHANDLE_1 0x2000 #define PHANDLE_2 0x2001 #define TEST_STRING_1 "hello world" #define TEST_STRING_2 "nastystring: \a\b\t\n\v\f\r\\\"" #define TEST_STRING_3 "\xde\xad\xbe\xef" #define TEST_STRING_4_PARTIAL "foobar" #define TEST_STRING_4_RESULT "testfoobar" #define TEST_CHAR1 '\r' #define TEST_CHAR2 'b' #define TEST_CHAR3 '\0' #define TEST_CHAR4 '\'' #define TEST_CHAR5 '\xff' #ifndef __ASSEMBLY__ -extern struct fdt_header _test_tree1; -extern struct fdt_header _truncated_property; -extern struct fdt_header _bad_node_char; -extern struct fdt_header _bad_node_format; -extern struct fdt_header _bad_prop_char; -extern struct fdt_header _ovf_size_strings; +extern struct fdt_header test_tree1; +extern struct fdt_header truncated_property; +extern struct fdt_header bad_node_char; +extern struct fdt_header bad_node_format; +extern struct fdt_header bad_prop_char; +extern struct fdt_header ovf_size_strings; #endif /* ! __ASSEMBLY */ Index: vendor/dtc/dist/tests/tests.h =================================================================== --- vendor/dtc/dist/tests/tests.h (revision 327892) +++ vendor/dtc/dist/tests/tests.h (revision 327893) @@ -1,129 +1,129 @@ -#ifndef _TESTS_H -#define _TESTS_H +#ifndef TESTS_H +#define TESTS_H /* * libfdt - Flat Device Tree manipulation * Testcase definitions * Copyright (C) 2006 David Gibson, IBM Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #define DEBUG /* Test return codes */ #define RC_PASS 0 #define RC_CONFIG 1 #define RC_FAIL 2 #define RC_BUG 99 extern int verbose_test; extern char *test_name; void test_init(int argc, char *argv[]); #define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) #define PALIGN(p, a) ((void *)ALIGN((unsigned long)(p), (a))) #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #define streq(s1, s2) (strcmp((s1),(s2)) == 0) /* Each test case must define this function */ void cleanup(void); #define verbose_printf(...) \ if (verbose_test) { \ printf(__VA_ARGS__); \ fflush(stdout); \ } #define ERR "ERR: " #define ERROR(fmt, args...) fprintf(stderr, ERR fmt, ## args) #define PASS() \ do { \ cleanup(); \ printf("PASS\n"); \ exit(RC_PASS); \ } while (0) #define PASS_INCONCLUSIVE() \ do { \ cleanup(); \ printf("PASS (inconclusive)\n"); \ exit(RC_PASS); \ } while (0) #define IRRELEVANT() \ do { \ cleanup(); \ printf("PASS (irrelevant)\n"); \ exit(RC_PASS); \ } while (0) /* Look out, gcc extension below... */ #define FAIL(fmt, ...) \ do { \ cleanup(); \ printf("FAIL\t" fmt "\n", ##__VA_ARGS__); \ exit(RC_FAIL); \ } while (0) #define CONFIG(fmt, ...) \ do { \ cleanup(); \ printf("Bad configuration: " fmt "\n", ##__VA_ARGS__); \ exit(RC_CONFIG); \ } while (0) #define TEST_BUG(fmt, ...) \ do { \ cleanup(); \ printf("BUG in testsuite: " fmt "\n", ##__VA_ARGS__); \ exit(RC_BUG); \ } while (0) void check_mem_rsv(void *fdt, int n, uint64_t addr, uint64_t size); void check_property(void *fdt, int nodeoffset, const char *name, int len, const void *val); #define check_property_cell(fdt, nodeoffset, name, val) \ ({ \ - uint32_t x = cpu_to_fdt32(val); \ + fdt32_t x = cpu_to_fdt32(val); \ check_property(fdt, nodeoffset, name, sizeof(x), &x); \ }) const void *check_getprop(void *fdt, int nodeoffset, const char *name, int len, const void *val); #define check_getprop_cell(fdt, nodeoffset, name, val) \ ({ \ - uint32_t x = cpu_to_fdt32(val); \ + fdt32_t x = cpu_to_fdt32(val); \ check_getprop(fdt, nodeoffset, name, sizeof(x), &x); \ }) #define check_getprop_64(fdt, nodeoffset, name, val) \ ({ \ - uint64_t x = cpu_to_fdt64(val); \ + fdt64_t x = cpu_to_fdt64(val); \ check_getprop(fdt, nodeoffset, name, sizeof(x), &x); \ }) #define check_getprop_string(fdt, nodeoffset, name, s) \ check_getprop((fdt), (nodeoffset), (name), strlen(s)+1, (s)) int nodename_eq(const char *s1, const char *s2); void *load_blob(const char *filename); void *load_blob_arg(int argc, char *argv[]); void save_blob(const char *filename, void *blob); void *open_blob_rw(void *blob); #include "util.h" -#endif /* _TESTS_H */ +#endif /* TESTS_H */ Index: vendor/dtc/dist/tests/tests.sh =================================================================== --- vendor/dtc/dist/tests/tests.sh (revision 327892) +++ vendor/dtc/dist/tests/tests.sh (revision 327893) @@ -1,62 +1,63 @@ # Common functions for shell testcases PASS () { echo "PASS" exit 0 } FAIL () { echo "FAIL" "$@" exit 2 } FAIL_IF_SIGNAL () { ret="$1" if [ "$ret" -gt 127 ]; then signame=$(kill -l $((ret - 128))) FAIL "Killed by SIG$signame" fi } DTC=../dtc DTGET=../fdtget DTPUT=../fdtput FDTDUMP=../fdtdump +FDTOVERLAY=../fdtoverlay verbose_run () { if [ -z "$QUIET_TEST" ]; then "$@" else "$@" > /dev/null 2> /dev/null fi } verbose_run_check () { verbose_run "$@" ret="$?" FAIL_IF_SIGNAL $ret if [ $ret != 0 ]; then FAIL "Returned error code $ret" fi } verbose_run_log () { LOG="$1" shift "$@" > "$LOG" 2>&1 ret=$? if [ -z "$QUIET_TEST" ]; then cat "$LOG" >&2 fi return $ret } verbose_run_log_check () { verbose_run_log "$@" ret="$?" FAIL_IF_SIGNAL $ret if [ $ret != 0 ]; then FAIL "Returned error code $ret" fi } Index: vendor/dtc/dist/tests/trees.S =================================================================== --- vendor/dtc/dist/tests/trees.S (revision 327892) +++ vendor/dtc/dist/tests/trees.S (revision 327893) @@ -1,242 +1,235 @@ #include #include "testdata.h" #define FDTLONG(val) \ .byte ((val) >> 24) & 0xff ; \ .byte ((val) >> 16) & 0xff ; \ .byte ((val) >> 8) & 0xff ; \ .byte (val) & 0xff ; -#define FDTQUAD(val) \ - .byte ((val) >> 56) & 0xff ; \ - .byte ((val) >> 48) & 0xff ; \ - .byte ((val) >> 40) & 0xff ; \ - .byte ((val) >> 32) & 0xff ; \ - .byte ((val) >> 24) & 0xff ; \ - .byte ((val) >> 16) & 0xff ; \ - .byte ((val) >> 8) & 0xff ; \ - .byte (val) & 0xff ; - #define TREE_HDR(tree) \ .balign 8 ; \ - .globl _##tree ; \ -_##tree: \ + .globl tree ; \ tree: \ FDTLONG(FDT_MAGIC) ; \ FDTLONG(tree##_end - tree) ; \ FDTLONG(tree##_struct - tree) ; \ FDTLONG(tree##_strings - tree) ; \ FDTLONG(tree##_rsvmap - tree) ; \ FDTLONG(0x11) ; \ FDTLONG(0x10) ; \ FDTLONG(0) ; \ FDTLONG(tree##_strings_end - tree##_strings) ; \ FDTLONG(tree##_struct_end - tree##_struct) ; -#define RSVMAP_ENTRY(addr, len) \ - FDTQUAD(addr) ; \ - FDTQUAD(len) ; \ +#define RSVMAP_ENTRY(addrh, addrl, lenh, lenl) \ + FDTLONG(addrh) ; \ + FDTLONG(addrl) ; \ + FDTLONG(lenh) ; \ + FDTLONG(lenl) #define EMPTY_RSVMAP(tree) \ .balign 8 ; \ tree##_rsvmap: ; \ - RSVMAP_ENTRY(0, 0) \ + RSVMAP_ENTRY(0, 0, 0, 0) \ tree##_rsvmap_end: ; #define PROPHDR(tree, name, len) \ FDTLONG(FDT_PROP) ; \ FDTLONG(len) ; \ FDTLONG(tree##_##name - tree##_strings) ; #define PROP_INT(tree, name, val) \ PROPHDR(tree, name, 4) \ FDTLONG(val) ; -#define PROP_INT64(tree, name, val) \ +#define PROP_INT64(tree, name, valh, vall) \ PROPHDR(tree, name, 8) \ - FDTQUAD(val) ; + FDTLONG(valh) ; \ + FDTLONG(vall) ; #define PROP_STR(tree, name, str) \ PROPHDR(tree, name, 55f - 54f) \ 54: \ .string str ; \ 55: \ .balign 4 ; #define BEGIN_NODE(name) \ FDTLONG(FDT_BEGIN_NODE) ; \ .string name ; \ .balign 4 ; #define END_NODE \ FDTLONG(FDT_END_NODE) ; #define STRING(tree, name, str) \ tree##_##name: ; \ .string str ; .data TREE_HDR(test_tree1) .balign 8 test_tree1_rsvmap: - RSVMAP_ENTRY(TEST_ADDR_1, TEST_SIZE_1) - RSVMAP_ENTRY(TEST_ADDR_2, TEST_SIZE_2) - RSVMAP_ENTRY(0, 0) + RSVMAP_ENTRY(TEST_ADDR_1H, TEST_ADDR_1L, TEST_SIZE_1H, TEST_SIZE_1L) + RSVMAP_ENTRY(TEST_ADDR_2H, TEST_ADDR_2L, TEST_SIZE_2H, TEST_SIZE_2L) + RSVMAP_ENTRY(0, 0, 0, 0) test_tree1_rsvmap_end: test_tree1_struct: BEGIN_NODE("") PROP_STR(test_tree1, compatible, "test_tree1") PROP_INT(test_tree1, prop_int, TEST_VALUE_1) - PROP_INT64(test_tree1, prop_int64, TEST_VALUE64_1) + PROP_INT64(test_tree1, prop_int64, TEST_VALUE64_1H, TEST_VALUE64_1L) PROP_STR(test_tree1, prop_str, TEST_STRING_1) PROP_INT(test_tree1, address_cells, 1) PROP_INT(test_tree1, size_cells, 0) BEGIN_NODE("subnode@1") PROP_STR(test_tree1, compatible, "subnode1") PROP_INT(test_tree1, reg, 1) PROP_INT(test_tree1, prop_int, TEST_VALUE_1) BEGIN_NODE("subsubnode") PROP_STR(test_tree1, compatible, "subsubnode1\0subsubnode") + PROP_STR(test_tree1, placeholder, "this is a placeholder string\0string2") PROP_INT(test_tree1, prop_int, TEST_VALUE_1) END_NODE BEGIN_NODE("ss1") END_NODE END_NODE BEGIN_NODE("subnode@2") PROP_INT(test_tree1, reg, 2) PROP_INT(test_tree1, linux_phandle, PHANDLE_1) PROP_INT(test_tree1, prop_int, TEST_VALUE_2) PROP_INT(test_tree1, address_cells, 1) PROP_INT(test_tree1, size_cells, 0) BEGIN_NODE("subsubnode@0") PROP_INT(test_tree1, reg, 0) PROP_INT(test_tree1, phandle, PHANDLE_2) PROP_STR(test_tree1, compatible, "subsubnode2\0subsubnode") PROP_INT(test_tree1, prop_int, TEST_VALUE_2) END_NODE BEGIN_NODE("ss2") END_NODE END_NODE END_NODE FDTLONG(FDT_END) test_tree1_struct_end: test_tree1_strings: STRING(test_tree1, compatible, "compatible") STRING(test_tree1, prop_int, "prop-int") STRING(test_tree1, prop_int64, "prop-int64") STRING(test_tree1, prop_str, "prop-str") STRING(test_tree1, linux_phandle, "linux,phandle") STRING(test_tree1, phandle, "phandle") STRING(test_tree1, reg, "reg") + STRING(test_tree1, placeholder, "placeholder") STRING(test_tree1, address_cells, "#address-cells") STRING(test_tree1, size_cells, "#size-cells") test_tree1_strings_end: test_tree1_end: TREE_HDR(truncated_property) EMPTY_RSVMAP(truncated_property) truncated_property_struct: BEGIN_NODE("") PROPHDR(truncated_property, prop_truncated, 4) /* Oops, no actual property data here */ truncated_property_struct_end: truncated_property_strings: STRING(truncated_property, prop_truncated, "truncated") truncated_property_strings_end: truncated_property_end: TREE_HDR(bad_node_char) EMPTY_RSVMAP(bad_node_char) bad_node_char_struct: BEGIN_NODE("") BEGIN_NODE("sub$node") END_NODE END_NODE FDTLONG(FDT_END) bad_node_char_struct_end: bad_node_char_strings: bad_node_char_strings_end: bad_node_char_end: TREE_HDR(bad_node_format) EMPTY_RSVMAP(bad_node_format) bad_node_format_struct: BEGIN_NODE("") BEGIN_NODE("subnode@1@2") END_NODE END_NODE FDTLONG(FDT_END) bad_node_format_struct_end: bad_node_format_strings: bad_node_format_strings_end: bad_node_format_end: TREE_HDR(bad_prop_char) EMPTY_RSVMAP(bad_prop_char) bad_prop_char_struct: BEGIN_NODE("") PROP_INT(bad_prop_char, prop, TEST_VALUE_1) END_NODE FDTLONG(FDT_END) bad_prop_char_struct_end: bad_prop_char_strings: STRING(bad_prop_char, prop, "prop$erty") bad_prop_char_strings_end: bad_prop_char_end: /* overflow_size_strings */ .balign 8 - .globl _ovf_size_strings -_ovf_size_strings: + .globl ovf_size_strings ovf_size_strings: FDTLONG(FDT_MAGIC) FDTLONG(ovf_size_strings_end - ovf_size_strings) FDTLONG(ovf_size_strings_struct - ovf_size_strings) FDTLONG(ovf_size_strings_strings - ovf_size_strings) FDTLONG(ovf_size_strings_rsvmap - ovf_size_strings) FDTLONG(0x11) FDTLONG(0x10) FDTLONG(0) FDTLONG(0xffffffff) FDTLONG(ovf_size_strings_struct_end - ovf_size_strings_struct) EMPTY_RSVMAP(ovf_size_strings) ovf_size_strings_struct: BEGIN_NODE("") PROP_INT(ovf_size_strings, bad_string, 0) END_NODE FDTLONG(FDT_END) ovf_size_strings_struct_end: ovf_size_strings_strings: STRING(ovf_size_strings, x, "x") ovf_size_strings_bad_string = ovf_size_strings_strings + 0x10000000 ovf_size_strings_strings_end: ovf_size_strings_end: Index: vendor/dtc/dist/tests/truncated_property.c =================================================================== --- vendor/dtc/dist/tests/truncated_property.c (revision 327892) +++ vendor/dtc/dist/tests/truncated_property.c (revision 327893) @@ -1,47 +1,47 @@ /* * libfdt - Flat Device Tree manipulation * Testcase for misbehaviour on a truncated property * Copyright (C) 2006 David Gibson, IBM Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include "tests.h" #include "testdata.h" int main(int argc, char *argv[]) { - void *fdt = &_truncated_property; + void *fdt = &truncated_property; const void *prop; int len; test_init(argc, argv); prop = fdt_getprop(fdt, 0, "truncated", &len); if (prop) FAIL("fdt_getprop() succeeded on truncated property"); if (len != -FDT_ERR_BADSTRUCTURE) FAIL("fdt_getprop() failed with \"%s\" instead of \"%s\"", fdt_strerror(len), fdt_strerror(-FDT_ERR_BADSTRUCTURE)); PASS(); } Index: vendor/dtc/dist/tests/unit-addr-leading-0s.dts =================================================================== --- vendor/dtc/dist/tests/unit-addr-leading-0s.dts (nonexistent) +++ vendor/dtc/dist/tests/unit-addr-leading-0s.dts (revision 327893) @@ -0,0 +1,12 @@ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + bus { + node@001 { + reg = <1 0>; + }; + }; +}; Property changes on: vendor/dtc/dist/tests/unit-addr-leading-0s.dts ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/dtc/dist/tests/unit-addr-leading-0x.dts =================================================================== --- vendor/dtc/dist/tests/unit-addr-leading-0x.dts (nonexistent) +++ vendor/dtc/dist/tests/unit-addr-leading-0x.dts (revision 327893) @@ -0,0 +1,12 @@ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + bus { + node@0x1 { + reg = <1 0>; + }; + }; +}; Property changes on: vendor/dtc/dist/tests/unit-addr-leading-0x.dts ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/dtc/dist/tests/value-labels.c =================================================================== --- vendor/dtc/dist/tests/value-labels.c (revision 327892) +++ vendor/dtc/dist/tests/value-labels.c (revision 327893) @@ -1,127 +1,127 @@ /* * libfdt - Flat Device Tree manipulation * Test labels within values * Copyright (C) 2008 David Gibson, IBM Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include "tests.h" #include "testdata.h" struct val_label { const char *labelname; int propoff; }; -struct val_label labels1[] = { +static struct val_label labels1[] = { { "start1", 0 }, { "mid1", 2 }, { "end1", -1 }, }; -struct val_label labels2[] = { +static struct val_label labels2[] = { { "start2", 0 }, { "innerstart2", 0 }, { "innermid2", 4 }, { "innerend2", -1 }, { "end2", -1 }, }; -struct val_label labels3[] = { +static struct val_label labels3[] = { { "start3", 0 }, { "innerstart3", 0 }, { "innermid3", 1 }, { "innerend3", -1 }, { "end3", -1 }, }; static void check_prop_labels(void *sohandle, void *fdt, const char *name, const struct val_label* labels, int n) { const struct fdt_property *prop; const char *p; int len; int i; prop = fdt_get_property(fdt, 0, name, &len); if (!prop) FAIL("Couldn't locate property \"%s\"", name); p = dlsym(sohandle, name); if (!p) FAIL("Couldn't locate label symbol \"%s\"", name); if (p != (const char *)prop) FAIL("Label \"%s\" does not point to correct property", name); for (i = 0; i < n; i++) { int off = labels[i].propoff; if (off == -1) off = len; p = dlsym(sohandle, labels[i].labelname); if (!p) FAIL("Couldn't locate label symbol \"%s\"", name); if ((p - prop->data) != off) FAIL("Label \"%s\" points to offset %ld instead of %d" "in property \"%s\"", labels[i].labelname, (long)(p - prop->data), off, name); } } int main(int argc, char *argv[]) { void *sohandle; void *fdt; int err; test_init(argc, argv); if (argc != 2) CONFIG("Usage: %s ", argv[0]); sohandle = dlopen(argv[1], RTLD_NOW); if (!sohandle) FAIL("Couldn't dlopen() %s", argv[1]); fdt = dlsym(sohandle, "dt_blob_start"); if (!fdt) FAIL("Couldn't locate \"dt_blob_start\" symbol in %s", argv[1]); err = fdt_check_header(fdt); if (err != 0) FAIL("%s contains invalid tree: %s", argv[1], fdt_strerror(err)); check_prop_labels(sohandle, fdt, "prop1", labels1, ARRAY_SIZE(labels1)); check_prop_labels(sohandle, fdt, "prop2", labels2, ARRAY_SIZE(labels2)); check_prop_labels(sohandle, fdt, "prop3", labels3, ARRAY_SIZE(labels3)); PASS(); } Index: vendor/dtc/dist/treesource.c =================================================================== --- vendor/dtc/dist/treesource.c (revision 327892) +++ vendor/dtc/dist/treesource.c (revision 327893) @@ -1,284 +1,284 @@ /* * (C) Copyright David Gibson , IBM Corporation. 2005. * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ #include "dtc.h" #include "srcpos.h" extern FILE *yyin; extern int yyparse(void); extern YYLTYPE yylloc; struct dt_info *parser_output; bool treesource_error; struct dt_info *dt_from_source(const char *fname) { parser_output = NULL; treesource_error = false; srcfile_push(fname); yyin = current_srcfile->f; yylloc.file = current_srcfile; if (yyparse() != 0) die("Unable to parse input tree\n"); if (treesource_error) die("Syntax error parsing input tree\n"); return parser_output; } static void write_prefix(FILE *f, int level) { int i; for (i = 0; i < level; i++) fputc('\t', f); } static bool isstring(char c) { return (isprint((unsigned char)c) || (c == '\0') || strchr("\a\b\t\n\v\f\r", c)); } static void write_propval_string(FILE *f, struct data val) { const char *str = val.val; int i; struct marker *m = val.markers; assert(str[val.len-1] == '\0'); while (m && (m->offset == 0)) { if (m->type == LABEL) fprintf(f, "%s: ", m->ref); m = m->next; } fprintf(f, "\""); for (i = 0; i < (val.len-1); i++) { char c = str[i]; switch (c) { case '\a': fprintf(f, "\\a"); break; case '\b': fprintf(f, "\\b"); break; case '\t': fprintf(f, "\\t"); break; case '\n': fprintf(f, "\\n"); break; case '\v': fprintf(f, "\\v"); break; case '\f': fprintf(f, "\\f"); break; case '\r': fprintf(f, "\\r"); break; case '\\': fprintf(f, "\\\\"); break; case '\"': fprintf(f, "\\\""); break; case '\0': fprintf(f, "\", "); while (m && (m->offset <= (i + 1))) { if (m->type == LABEL) { assert(m->offset == (i+1)); fprintf(f, "%s: ", m->ref); } m = m->next; } fprintf(f, "\""); break; default: if (isprint((unsigned char)c)) fprintf(f, "%c", c); else fprintf(f, "\\x%02hhx", c); } } fprintf(f, "\""); /* Wrap up any labels at the end of the value */ for_each_marker_of_type(m, LABEL) { assert (m->offset == val.len); fprintf(f, " %s:", m->ref); } } static void write_propval_cells(FILE *f, struct data val) { void *propend = val.val + val.len; - cell_t *cp = (cell_t *)val.val; + fdt32_t *cp = (fdt32_t *)val.val; struct marker *m = val.markers; fprintf(f, "<"); for (;;) { while (m && (m->offset <= ((char *)cp - val.val))) { if (m->type == LABEL) { assert(m->offset == ((char *)cp - val.val)); fprintf(f, "%s: ", m->ref); } m = m->next; } fprintf(f, "0x%x", fdt32_to_cpu(*cp++)); if ((void *)cp >= propend) break; fprintf(f, " "); } /* Wrap up any labels at the end of the value */ for_each_marker_of_type(m, LABEL) { assert (m->offset == val.len); fprintf(f, " %s:", m->ref); } fprintf(f, ">"); } static void write_propval_bytes(FILE *f, struct data val) { void *propend = val.val + val.len; const char *bp = val.val; struct marker *m = val.markers; fprintf(f, "["); for (;;) { while (m && (m->offset == (bp-val.val))) { if (m->type == LABEL) fprintf(f, "%s: ", m->ref); m = m->next; } fprintf(f, "%02hhx", (unsigned char)(*bp++)); if ((const void *)bp >= propend) break; fprintf(f, " "); } /* Wrap up any labels at the end of the value */ for_each_marker_of_type(m, LABEL) { assert (m->offset == val.len); fprintf(f, " %s:", m->ref); } fprintf(f, "]"); } static void write_propval(FILE *f, struct property *prop) { int len = prop->val.len; const char *p = prop->val.val; struct marker *m = prop->val.markers; int nnotstring = 0, nnul = 0; int nnotstringlbl = 0, nnotcelllbl = 0; int i; if (len == 0) { fprintf(f, ";\n"); return; } for (i = 0; i < len; i++) { if (! isstring(p[i])) nnotstring++; if (p[i] == '\0') nnul++; } for_each_marker_of_type(m, LABEL) { if ((m->offset > 0) && (prop->val.val[m->offset - 1] != '\0')) nnotstringlbl++; if ((m->offset % sizeof(cell_t)) != 0) nnotcelllbl++; } fprintf(f, " = "); if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul)) && (nnotstringlbl == 0)) { write_propval_string(f, prop->val); } else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) { write_propval_cells(f, prop->val); } else { write_propval_bytes(f, prop->val); } fprintf(f, ";\n"); } static void write_tree_source_node(FILE *f, struct node *tree, int level) { struct property *prop; struct node *child; struct label *l; write_prefix(f, level); for_each_label(tree->labels, l) fprintf(f, "%s: ", l->label); if (tree->name && (*tree->name)) fprintf(f, "%s {\n", tree->name); else fprintf(f, "/ {\n"); for_each_property(tree, prop) { write_prefix(f, level+1); for_each_label(prop->labels, l) fprintf(f, "%s: ", l->label); fprintf(f, "%s", prop->name); write_propval(f, prop); } for_each_child(tree, child) { fprintf(f, "\n"); write_tree_source_node(f, child, level+1); } write_prefix(f, level); fprintf(f, "};\n"); } void dt_to_source(FILE *f, struct dt_info *dti) { struct reserve_info *re; fprintf(f, "/dts-v1/;\n\n"); for (re = dti->reservelist; re; re = re->next) { struct label *l; for_each_label(re->labels, l) fprintf(f, "%s: ", l->label); fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n", - (unsigned long long)re->re.address, - (unsigned long long)re->re.size); + (unsigned long long)re->address, + (unsigned long long)re->size); } write_tree_source_node(f, dti->dt, 0); } Index: vendor/dtc/dist/util.c =================================================================== --- vendor/dtc/dist/util.c (revision 327892) +++ vendor/dtc/dist/util.c (revision 327893) @@ -1,473 +1,474 @@ /* * Copyright 2011 The Chromium Authors, All Rights Reserved. * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc. * * util_is_printable_string contributed by * Pantelis Antoniou * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ #include #include #include #include #include #include #include #include #include #include "libfdt.h" #include "util.h" #include "version_gen.h" char *xstrdup(const char *s) { int len = strlen(s) + 1; char *d = xmalloc(len); memcpy(d, s, len); return d; } /* based in part from (3) vsnprintf */ int xasprintf(char **strp, const char *fmt, ...) { int n, size = 128; /* start with 128 bytes */ char *p; va_list ap; /* initial pointer is NULL making the fist realloc to be malloc */ p = NULL; while (1) { p = xrealloc(p, size); /* Try to print in the allocated space. */ va_start(ap, fmt); n = vsnprintf(p, size, fmt, ap); va_end(ap); /* If that worked, return the string. */ if (n > -1 && n < size) break; /* Else try again with more space. */ if (n > -1) /* glibc 2.1 */ size = n + 1; /* precisely what is needed */ else /* glibc 2.0 */ size *= 2; /* twice the old size */ } *strp = p; return strlen(p); } char *join_path(const char *path, const char *name) { int lenp = strlen(path); int lenn = strlen(name); int len; int needslash = 1; char *str; len = lenp + lenn + 2; if ((lenp > 0) && (path[lenp-1] == '/')) { needslash = 0; len--; } str = xmalloc(len); memcpy(str, path, lenp); if (needslash) { str[lenp] = '/'; lenp++; } memcpy(str+lenp, name, lenn+1); return str; } bool util_is_printable_string(const void *data, int len) { const char *s = data; const char *ss, *se; /* zero length is not */ if (len == 0) return 0; /* must terminate with zero */ if (s[len - 1] != '\0') return 0; se = s + len; while (s < se) { ss = s; while (s < se && *s && isprint((unsigned char)*s)) s++; /* not zero, or not done yet */ if (*s != '\0' || s == ss) return 0; s++; } return 1; } /* * Parse a octal encoded character starting at index i in string s. The * resulting character will be returned and the index i will be updated to * point at the character directly after the end of the encoding, this may be * the '\0' terminator of the string. */ static char get_oct_char(const char *s, int *i) { char x[4]; char *endx; long val; x[3] = '\0'; strncpy(x, s + *i, 3); val = strtol(x, &endx, 8); assert(endx > x); (*i) += endx - x; return val; } /* * Parse a hexadecimal encoded character starting at index i in string s. The * resulting character will be returned and the index i will be updated to * point at the character directly after the end of the encoding, this may be * the '\0' terminator of the string. */ static char get_hex_char(const char *s, int *i) { char x[3]; char *endx; long val; x[2] = '\0'; strncpy(x, s + *i, 2); val = strtol(x, &endx, 16); if (!(endx > x)) die("\\x used with no following hex digits\n"); (*i) += endx - x; return val; } char get_escape_char(const char *s, int *i) { char c = s[*i]; int j = *i + 1; char val; switch (c) { case 'a': val = '\a'; break; case 'b': val = '\b'; break; case 't': val = '\t'; break; case 'n': val = '\n'; break; case 'v': val = '\v'; break; case 'f': val = '\f'; break; case 'r': val = '\r'; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': j--; /* need to re-read the first digit as * part of the octal value */ val = get_oct_char(s, &j); break; case 'x': val = get_hex_char(s, &j); break; default: val = c; } (*i) = j; return val; } int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len) { int fd = 0; /* assume stdin */ char *buf = NULL; off_t bufsize = 1024, offset = 0; int ret = 0; *buffp = NULL; if (strcmp(filename, "-") != 0) { fd = open(filename, O_RDONLY); if (fd < 0) return errno; } /* Loop until we have read everything */ buf = xmalloc(bufsize); do { /* Expand the buffer to hold the next chunk */ if (offset == bufsize) { bufsize *= 2; buf = xrealloc(buf, bufsize); } ret = read(fd, &buf[offset], bufsize - offset); if (ret < 0) { ret = errno; break; } offset += ret; } while (ret != 0); /* Clean up, including closing stdin; return errno on error */ close(fd); if (ret) free(buf); else *buffp = buf; *len = bufsize; return ret; } int utilfdt_read_err(const char *filename, char **buffp) { off_t len; return utilfdt_read_err_len(filename, buffp, &len); } char *utilfdt_read_len(const char *filename, off_t *len) { char *buff; int ret = utilfdt_read_err_len(filename, &buff, len); if (ret) { fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename, strerror(ret)); return NULL; } /* Successful read */ return buff; } char *utilfdt_read(const char *filename) { off_t len; return utilfdt_read_len(filename, &len); } int utilfdt_write_err(const char *filename, const void *blob) { int fd = 1; /* assume stdout */ int totalsize; int offset; int ret = 0; const char *ptr = blob; if (strcmp(filename, "-") != 0) { fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd < 0) return errno; } totalsize = fdt_totalsize(blob); offset = 0; while (offset < totalsize) { ret = write(fd, ptr + offset, totalsize - offset); if (ret < 0) { ret = -errno; break; } offset += ret; } /* Close the file/stdin; return errno on error */ if (fd != 1) close(fd); return ret < 0 ? -ret : 0; } int utilfdt_write(const char *filename, const void *blob) { int ret = utilfdt_write_err(filename, blob); if (ret) { fprintf(stderr, "Couldn't write blob to '%s': %s\n", filename, strerror(ret)); } return ret ? -1 : 0; } int utilfdt_decode_type(const char *fmt, int *type, int *size) { int qualifier = 0; if (!*fmt) return -1; /* get the conversion qualifier */ *size = -1; if (strchr("hlLb", *fmt)) { qualifier = *fmt++; if (qualifier == *fmt) { switch (*fmt++) { /* TODO: case 'l': qualifier = 'L'; break;*/ case 'h': qualifier = 'b'; break; } } } /* we should now have a type */ if ((*fmt == '\0') || !strchr("iuxs", *fmt)) return -1; /* convert qualifier (bhL) to byte size */ if (*fmt != 's') *size = qualifier == 'b' ? 1 : qualifier == 'h' ? 2 : qualifier == 'l' ? 4 : -1; *type = *fmt++; /* that should be it! */ if (*fmt) return -1; return 0; } void utilfdt_print_data(const char *data, int len) { int i; const char *s; /* no data, don't print */ if (len == 0) return; if (util_is_printable_string(data, len)) { printf(" = "); s = data; do { printf("\"%s\"", s); s += strlen(s) + 1; if (s < data + len) printf(", "); } while (s < data + len); } else if ((len % 4) == 0) { - const uint32_t *cell = (const uint32_t *)data; + const fdt32_t *cell = (const fdt32_t *)data; printf(" = <"); for (i = 0, len /= 4; i < len; i++) printf("0x%08x%s", fdt32_to_cpu(cell[i]), i < (len - 1) ? " " : ""); printf(">"); } else { const unsigned char *p = (const unsigned char *)data; printf(" = ["); for (i = 0; i < len; i++) printf("%02x%s", *p++, i < len - 1 ? " " : ""); printf("]"); } } -void util_version(void) +void NORETURN util_version(void) { printf("Version: %s\n", DTC_VERSION); exit(0); } -void util_usage(const char *errmsg, const char *synopsis, - const char *short_opts, struct option const long_opts[], - const char * const opts_help[]) +void NORETURN util_usage(const char *errmsg, const char *synopsis, + const char *short_opts, + struct option const long_opts[], + const char * const opts_help[]) { FILE *fp = errmsg ? stderr : stdout; const char a_arg[] = ""; size_t a_arg_len = strlen(a_arg) + 1; size_t i; int optlen; fprintf(fp, "Usage: %s\n" "\n" "Options: -[%s]\n", synopsis, short_opts); /* prescan the --long opt length to auto-align */ optlen = 0; for (i = 0; long_opts[i].name; ++i) { /* +1 is for space between --opt and help text */ int l = strlen(long_opts[i].name) + 1; if (long_opts[i].has_arg == a_argument) l += a_arg_len; if (optlen < l) optlen = l; } for (i = 0; long_opts[i].name; ++i) { /* helps when adding new applets or options */ assert(opts_help[i] != NULL); /* first output the short flag if it has one */ if (long_opts[i].val > '~') fprintf(fp, " "); else fprintf(fp, " -%c, ", long_opts[i].val); /* then the long flag */ if (long_opts[i].has_arg == no_argument) fprintf(fp, "--%-*s", optlen, long_opts[i].name); else fprintf(fp, "--%s %s%*s", long_opts[i].name, a_arg, (int)(optlen - strlen(long_opts[i].name) - a_arg_len), ""); /* finally the help text */ fprintf(fp, "%s\n", opts_help[i]); } if (errmsg) { fprintf(fp, "\nError: %s\n", errmsg); exit(EXIT_FAILURE); } else exit(EXIT_SUCCESS); } Index: vendor/dtc/dist/util.h =================================================================== --- vendor/dtc/dist/util.h (revision 327892) +++ vendor/dtc/dist/util.h (revision 327893) @@ -1,265 +1,266 @@ -#ifndef _UTIL_H -#define _UTIL_H +#ifndef UTIL_H +#define UTIL_H #include #include #include /* * Copyright 2011 The Chromium Authors, All Rights Reserved. * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) - #ifdef __GNUC__ -static inline void -__attribute__((noreturn)) __attribute__((format (printf, 1, 2))) -die(const char *str, ...) +#define PRINTF(i, j) __attribute__((format (printf, i, j))) +#define NORETURN __attribute__((noreturn)) #else -static inline void die(const char *str, ...) +#define PRINTF(i, j) +#define NORETURN #endif + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +#define stringify(s) stringify_(s) +#define stringify_(s) #s + +static inline void NORETURN PRINTF(1, 2) die(const char *str, ...) { va_list ap; va_start(ap, str); fprintf(stderr, "FATAL ERROR: "); vfprintf(stderr, str, ap); va_end(ap); exit(1); } static inline void *xmalloc(size_t len) { void *new = malloc(len); if (!new) die("malloc() failed\n"); return new; } static inline void *xrealloc(void *p, size_t len) { void *new = realloc(p, len); if (!new) die("realloc() failed (len=%zd)\n", len); return new; } extern char *xstrdup(const char *s); -#ifdef __GNUC__ -extern int __attribute__((format (printf, 2, 3))) -xasprintf(char **strp, const char *fmt, ...); -#else -extern int xasprintf(char **strp, const char *fmt, ...); -#endif +extern int PRINTF(2, 3) xasprintf(char **strp, const char *fmt, ...); extern char *join_path(const char *path, const char *name); /** * Check a property of a given length to see if it is all printable and * has a valid terminator. The property can contain either a single string, * or multiple strings each of non-zero length. * * @param data The string to check * @param len The string length including terminator * @return 1 if a valid printable string, 0 if not */ bool util_is_printable_string(const void *data, int len); /* * Parse an escaped character starting at index i in string s. The resulting * character will be returned and the index i will be updated to point at the * character directly after the end of the encoding, this may be the '\0' * terminator of the string. */ char get_escape_char(const char *s, int *i); /** * Read a device tree file into a buffer. This will report any errors on * stderr. * * @param filename The filename to read, or - for stdin * @return Pointer to allocated buffer containing fdt, or NULL on error */ char *utilfdt_read(const char *filename); /** * Like utilfdt_read(), but also passes back the size of the file read. * * @param len If non-NULL, the amount of data we managed to read */ char *utilfdt_read_len(const char *filename, off_t *len); /** * Read a device tree file into a buffer. Does not report errors, but only * returns them. The value returned can be passed to strerror() to obtain * an error message for the user. * * @param filename The filename to read, or - for stdin * @param buffp Returns pointer to buffer containing fdt * @return 0 if ok, else an errno value representing the error */ int utilfdt_read_err(const char *filename, char **buffp); /** * Like utilfdt_read_err(), but also passes back the size of the file read. * * @param len If non-NULL, the amount of data we managed to read */ int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len); /** * Write a device tree buffer to a file. This will report any errors on * stderr. * * @param filename The filename to write, or - for stdout * @param blob Poiner to buffer containing fdt * @return 0 if ok, -1 on error */ int utilfdt_write(const char *filename, const void *blob); /** * Write a device tree buffer to a file. Does not report errors, but only * returns them. The value returned can be passed to strerror() to obtain * an error message for the user. * * @param filename The filename to write, or - for stdout * @param blob Poiner to buffer containing fdt * @return 0 if ok, else an errno value representing the error */ int utilfdt_write_err(const char *filename, const void *blob); /** * Decode a data type string. The purpose of this string * * The string consists of an optional character followed by the type: * Modifier characters: * hh or b 1 byte * h 2 byte * l 4 byte, default * * Type character: * s string * i signed integer * u unsigned integer * x hex * * TODO: Implement ll modifier (8 bytes) * TODO: Implement o type (octal) * * @param fmt Format string to process * @param type Returns type found(s/d/u/x), or 0 if none * @param size Returns size found(1,2,4,8) or 4 if none * @return 0 if ok, -1 on error (no type given, or other invalid format) */ int utilfdt_decode_type(const char *fmt, int *type, int *size); /* * This is a usage message fragment for the -t option. It is the format * supported by utilfdt_decode_type. */ #define USAGE_TYPE_MSG \ "\ts=string, i=int, u=unsigned, x=hex\n" \ "\tOptional modifier prefix:\n" \ "\t\thh or b=byte, h=2 byte, l=4 byte (default)"; /** * Print property data in a readable format to stdout * * Properties that look like strings will be printed as strings. Otherwise * the data will be displayed either as cells (if len is a multiple of 4 * bytes) or bytes. * * If len is 0 then this function does nothing. * * @param data Pointers to property data * @param len Length of property data */ void utilfdt_print_data(const char *data, int len); /** * Show source version and exit */ -void util_version(void) __attribute__((noreturn)); +void NORETURN util_version(void); /** * Show usage and exit * * This helps standardize the output of various utils. You most likely want * to use the usage() helper below rather than call this. * * @param errmsg If non-NULL, an error message to display * @param synopsis The initial example usage text (and possible examples) * @param short_opts The string of short options * @param long_opts The structure of long options * @param opts_help An array of help strings (should align with long_opts) */ -void util_usage(const char *errmsg, const char *synopsis, - const char *short_opts, struct option const long_opts[], - const char * const opts_help[]) __attribute__((noreturn)); +void NORETURN util_usage(const char *errmsg, const char *synopsis, + const char *short_opts, + struct option const long_opts[], + const char * const opts_help[]); /** * Show usage and exit * * If you name all your usage variables with usage_xxx, then you can call this * help macro rather than expanding all arguments yourself. * * @param errmsg If non-NULL, an error message to display */ #define usage(errmsg) \ util_usage(errmsg, usage_synopsis, usage_short_opts, \ usage_long_opts, usage_opts_help) /** * Call getopt_long() with standard options * * Since all util code runs getopt in the same way, provide a helper. */ #define util_getopt_long() getopt_long(argc, argv, usage_short_opts, \ usage_long_opts, NULL) /* Helper for aligning long_opts array */ #define a_argument required_argument /* Helper for usage_short_opts string constant */ #define USAGE_COMMON_SHORT_OPTS "hV" /* Helper for usage_long_opts option array */ #define USAGE_COMMON_LONG_OPTS \ {"help", no_argument, NULL, 'h'}, \ {"version", no_argument, NULL, 'V'}, \ {NULL, no_argument, NULL, 0x0} /* Helper for usage_opts_help array */ #define USAGE_COMMON_OPTS_HELP \ "Print this help and exit", \ "Print version and exit", \ NULL /* Helper for getopt case statements */ #define case_USAGE_COMMON_FLAGS \ case 'h': usage(NULL); \ case 'V': util_version(); \ case '?': usage("unknown option"); -#endif /* _UTIL_H */ +#endif /* UTIL_H */