* [PATCH 0/8] Add support for a generic DT based 2nd stage ARM image @ 2019-08-19 13:38 Sascha Hauer 2019-08-19 13:38 ` [PATCH 1/8] dtc: Update update-dtc-source.sh from Linux Sascha Hauer ` (7 more replies) 0 siblings, 8 replies; 18+ messages in thread From: Sascha Hauer @ 2019-08-19 13:38 UTC (permalink / raw) To: Barebox List This series adds support for a generic DT based 2nd stage ARM image. This image can be enabled in Kconfig for multiimage based ARM builds. The result is an image which can be started just like a Kernel and just like the Kernel it will pick the device tree from r2, so basically a put-it-somewhere-as-a-kernel image. This can help with starting barebox on qemu. Sascha Sascha Hauer (8): dtc: Update update-dtc-source.sh from Linux scripts/dtc: Update to upstream version v1.5.0 pbl: Implement strrchr Compile libfdt for barebox common: return "none" when board unset ARM: Add generic device tree 2nd stage support ARM: i.MX: Do not hang() on unknown SoCs ARM: i.MX: When generic DT image is enabled do not hardcode SoC arch/arm/Kconfig | 11 + arch/arm/cpu/Makefile | 3 + arch/arm/cpu/board-dt-2nd-aarch64.S | 11 + arch/arm/cpu/board-dt-2nd.c | 127 +++++++ arch/arm/mach-imx/imx.c | 2 +- arch/arm/mach-imx/include/mach/generic.h | 9 + common/misc.c | 5 +- images/Makefile | 4 + include/fdt.h | 69 +--- include/linux/libfdt.h | 8 + include/linux/libfdt_env.h | 19 + lib/Kconfig | 3 + lib/Makefile | 10 + lib/fdt.c | 2 + lib/fdt_empty_tree.c | 2 + lib/fdt_ro.c | 2 + lib/fdt_rw.c | 2 + lib/fdt_strerror.c | 2 + lib/fdt_sw.c | 2 + lib/fdt_wip.c | 2 + pbl/string.c | 16 + scripts/dtc/Makefile | 49 +-- scripts/dtc/Makefile.dtc | 4 + scripts/dtc/checks.c | 255 +++++++++++++- scripts/dtc/data.c | 2 +- scripts/dtc/dtc-lexer.l | 4 +- scripts/dtc/dtc-parser.y | 53 ++- scripts/dtc/dtc.c | 22 +- scripts/dtc/dtc.h | 18 +- scripts/dtc/fdtget.c | 383 --------------------- scripts/dtc/flattree.c | 4 +- scripts/dtc/fstree.c | 5 +- scripts/dtc/libfdt/Makefile.libfdt | 15 + scripts/dtc/{ => libfdt}/fdt.c | 0 scripts/dtc/{ => libfdt}/fdt.h | 0 scripts/dtc/{ => libfdt}/fdt_addresses.c | 16 +- scripts/dtc/{ => libfdt}/fdt_empty_tree.c | 0 scripts/dtc/{ => libfdt}/fdt_overlay.c | 0 scripts/dtc/{ => libfdt}/fdt_ro.c | 0 scripts/dtc/{ => libfdt}/fdt_rw.c | 0 scripts/dtc/{ => libfdt}/fdt_strerror.c | 0 scripts/dtc/{ => libfdt}/fdt_sw.c | 0 scripts/dtc/{ => libfdt}/fdt_wip.c | 0 scripts/dtc/{ => libfdt}/libfdt.h | 30 +- scripts/dtc/{ => libfdt}/libfdt_env.h | 0 scripts/dtc/{ => libfdt}/libfdt_internal.h | 0 scripts/dtc/livetree.c | 33 +- scripts/dtc/srcpos.c | 153 +++++++- scripts/dtc/srcpos.h | 14 +- scripts/dtc/treesource.c | 124 ++++--- scripts/dtc/update-dtc-source.sh | 25 +- scripts/dtc/util.c | 60 ++-- scripts/dtc/util.h | 2 + scripts/dtc/version_gen.h | 2 +- scripts/dtc/yamltree.c | 247 +++++++++++++ 55 files changed, 1180 insertions(+), 651 deletions(-) create mode 100644 arch/arm/cpu/board-dt-2nd-aarch64.S create mode 100644 arch/arm/cpu/board-dt-2nd.c create mode 100644 include/linux/libfdt.h create mode 100644 include/linux/libfdt_env.h create mode 100644 lib/fdt.c create mode 100644 lib/fdt_empty_tree.c create mode 100644 lib/fdt_ro.c create mode 100644 lib/fdt_rw.c create mode 100644 lib/fdt_strerror.c create mode 100644 lib/fdt_sw.c create mode 100644 lib/fdt_wip.c delete mode 100644 scripts/dtc/fdtget.c create mode 100644 scripts/dtc/libfdt/Makefile.libfdt rename scripts/dtc/{ => libfdt}/fdt.c (100%) rename scripts/dtc/{ => libfdt}/fdt.h (100%) rename scripts/dtc/{ => libfdt}/fdt_addresses.c (92%) rename scripts/dtc/{ => libfdt}/fdt_empty_tree.c (100%) rename scripts/dtc/{ => libfdt}/fdt_overlay.c (100%) rename scripts/dtc/{ => libfdt}/fdt_ro.c (100%) rename scripts/dtc/{ => libfdt}/fdt_rw.c (100%) rename scripts/dtc/{ => libfdt}/fdt_strerror.c (100%) rename scripts/dtc/{ => libfdt}/fdt_sw.c (100%) rename scripts/dtc/{ => libfdt}/fdt_wip.c (100%) rename scripts/dtc/{ => libfdt}/libfdt.h (99%) rename scripts/dtc/{ => libfdt}/libfdt_env.h (100%) rename scripts/dtc/{ => libfdt}/libfdt_internal.h (100%) create mode 100644 scripts/dtc/yamltree.c -- 2.20.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 1/8] dtc: Update update-dtc-source.sh from Linux 2019-08-19 13:38 [PATCH 0/8] Add support for a generic DT based 2nd stage ARM image Sascha Hauer @ 2019-08-19 13:38 ` Sascha Hauer 2019-08-19 13:48 ` Roland Hieber 2019-08-19 13:38 ` [PATCH 2/8] scripts/dtc: Update to upstream version v1.5.0 Sascha Hauer ` (6 subsequent siblings) 7 siblings, 1 reply; 18+ messages in thread From: Sascha Hauer @ 2019-08-19 13:38 UTC (permalink / raw) To: Barebox List This updates update-dtc-source.sh from Linux-5.3-rc4. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- scripts/dtc/update-dtc-source.sh | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/scripts/dtc/update-dtc-source.sh b/scripts/dtc/update-dtc-source.sh index e29f5af00f..7dd29a0362 100755 --- a/scripts/dtc/update-dtc-source.sh +++ b/scripts/dtc/update-dtc-source.sh @@ -4,14 +4,15 @@ # # This script assumes that the dtc and the linux git trees are in the # same directory. After building dtc in the dtc directory, it copies the -# source files into the scripts/dtc directory in barebox and creates a git -# commit updating them to the new version. +# source files and generated source file(s) into the scripts/dtc directory +# in the kernel and creates a git commit updating them to the new +# version. # -# Usage: from the top level barebox source tree, run: +# Usage: from the top level Linux source tree, run: # $ ./scripts/dtc/update-dtc-source.sh # # The script will change into the dtc tree, build and test dtc, copy the -# relevant files into the barebox tree and create a git commit. The commit +# relevant files into the kernel tree and create a git commit. The commit # message will need to be modified to reflect the version of DTC being # imported # @@ -31,9 +32,9 @@ DTC_UPSTREAM_PATH=`pwd`/../dtc DTC_LINUX_PATH=`pwd`/scripts/dtc DTC_SOURCE="checks.c data.c dtc.c dtc.h flattree.c fstree.c livetree.c srcpos.c \ - srcpos.h treesource.c util.c util.h version_gen.h Makefile.dtc \ - dtc-lexer.l dtc-parser.y fdtget.c" -LIBFDT_SOURCE="fdt.c fdt.h fdt_addresses.c fdt_empty_tree.c \ + srcpos.h treesource.c util.c util.h version_gen.h yamltree.c Makefile.dtc \ + dtc-lexer.l dtc-parser.y" +LIBFDT_SOURCE="Makefile.libfdt fdt.c fdt.h fdt_addresses.c fdt_empty_tree.c \ fdt_overlay.c fdt_ro.c fdt_rw.c fdt_strerror.c fdt_sw.c \ fdt_wip.c libfdt.h libfdt_env.h libfdt_internal.h" @@ -58,13 +59,13 @@ for f in $DTC_SOURCE; do git add ${f} done for f in $LIBFDT_SOURCE; do - cp ${DTC_UPSTREAM_PATH}/libfdt/${f} ${f} - git add ${f} + cp ${DTC_UPSTREAM_PATH}/libfdt/${f} libfdt/${f} + git add libfdt/${f} done -sed -i -- 's/#include <libfdt_env.h>/#include "libfdt_env.h"/g' ./libfdt.h -sed -i -- 's/#include <fdt.h>/#include "fdt.h"/g' ./libfdt.h -git add ./libfdt.h +sed -i -- 's/#include <libfdt_env.h>/#include "libfdt_env.h"/g' ./libfdt/libfdt.h +sed -i -- 's/#include <fdt.h>/#include "fdt.h"/g' ./libfdt/libfdt.h +git add ./libfdt/libfdt.h commit_msg=$(cat << EOF scripts/dtc: Update to upstream version ${dtc_version} -- 2.20.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 1/8] dtc: Update update-dtc-source.sh from Linux 2019-08-19 13:38 ` [PATCH 1/8] dtc: Update update-dtc-source.sh from Linux Sascha Hauer @ 2019-08-19 13:48 ` Roland Hieber 0 siblings, 0 replies; 18+ messages in thread From: Roland Hieber @ 2019-08-19 13:48 UTC (permalink / raw) To: Sascha Hauer; +Cc: Barebox List On Mon, Aug 19, 2019 at 03:38:40PM +0200, Sascha Hauer wrote: > This updates update-dtc-source.sh from Linux-5.3-rc4. > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> > --- > scripts/dtc/update-dtc-source.sh | 25 +++++++++++++------------ > 1 file changed, 13 insertions(+), 12 deletions(-) > > diff --git a/scripts/dtc/update-dtc-source.sh b/scripts/dtc/update-dtc-source.sh > index e29f5af00f..7dd29a0362 100755 > --- a/scripts/dtc/update-dtc-source.sh > +++ b/scripts/dtc/update-dtc-source.sh > @@ -4,14 +4,15 @@ > # > # This script assumes that the dtc and the linux git trees are in the > # same directory. After building dtc in the dtc directory, it copies the > -# source files into the scripts/dtc directory in barebox and creates a git > -# commit updating them to the new version. > +# source files and generated source file(s) into the scripts/dtc directory > +# in the kernel and creates a git commit updating them to the new > +# version. > # > -# Usage: from the top level barebox source tree, run: > +# Usage: from the top level Linux source tree, run: > # $ ./scripts/dtc/update-dtc-source.sh > # > # The script will change into the dtc tree, build and test dtc, copy the > -# relevant files into the barebox tree and create a git commit. The commit > +# relevant files into the kernel tree and create a git commit. The commit > # message will need to be modified to reflect the version of DTC being > # imported > # I don't know if those hunks were changed by accident, but it looks like the previous version made more sense. - Roland > @@ -31,9 +32,9 @@ DTC_UPSTREAM_PATH=`pwd`/../dtc > DTC_LINUX_PATH=`pwd`/scripts/dtc > > DTC_SOURCE="checks.c data.c dtc.c dtc.h flattree.c fstree.c livetree.c srcpos.c \ > - srcpos.h treesource.c util.c util.h version_gen.h Makefile.dtc \ > - dtc-lexer.l dtc-parser.y fdtget.c" > -LIBFDT_SOURCE="fdt.c fdt.h fdt_addresses.c fdt_empty_tree.c \ > + srcpos.h treesource.c util.c util.h version_gen.h yamltree.c Makefile.dtc \ > + dtc-lexer.l dtc-parser.y" > +LIBFDT_SOURCE="Makefile.libfdt fdt.c fdt.h fdt_addresses.c fdt_empty_tree.c \ > fdt_overlay.c fdt_ro.c fdt_rw.c fdt_strerror.c fdt_sw.c \ > fdt_wip.c libfdt.h libfdt_env.h libfdt_internal.h" > > @@ -58,13 +59,13 @@ for f in $DTC_SOURCE; do > git add ${f} > done > for f in $LIBFDT_SOURCE; do > - cp ${DTC_UPSTREAM_PATH}/libfdt/${f} ${f} > - git add ${f} > + cp ${DTC_UPSTREAM_PATH}/libfdt/${f} libfdt/${f} > + git add libfdt/${f} > done > > -sed -i -- 's/#include <libfdt_env.h>/#include "libfdt_env.h"/g' ./libfdt.h > -sed -i -- 's/#include <fdt.h>/#include "fdt.h"/g' ./libfdt.h > -git add ./libfdt.h > +sed -i -- 's/#include <libfdt_env.h>/#include "libfdt_env.h"/g' ./libfdt/libfdt.h > +sed -i -- 's/#include <fdt.h>/#include "fdt.h"/g' ./libfdt/libfdt.h > +git add ./libfdt/libfdt.h > > commit_msg=$(cat << EOF > scripts/dtc: Update to upstream version ${dtc_version} > -- > 2.20.1 > > > _______________________________________________ > barebox mailing list > barebox@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/barebox > -- Roland Hieber | r.hieber@pengutronix.de | Pengutronix e.K. | https://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim | Phone: +49-5121-206917-5086 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 2/8] scripts/dtc: Update to upstream version v1.5.0 2019-08-19 13:38 [PATCH 0/8] Add support for a generic DT based 2nd stage ARM image Sascha Hauer 2019-08-19 13:38 ` [PATCH 1/8] dtc: Update update-dtc-source.sh from Linux Sascha Hauer @ 2019-08-19 13:38 ` Sascha Hauer 2019-08-19 13:52 ` Roland Hieber 2019-08-19 13:38 ` [PATCH 3/8] pbl: Implement strrchr Sascha Hauer ` (5 subsequent siblings) 7 siblings, 1 reply; 18+ messages in thread From: Sascha Hauer @ 2019-08-19 13:38 UTC (permalink / raw) To: Barebox List This adds the following commits from upstream: d37f6b2 Bump version to v1.5.0 a4b1a30 pylibfdt:tests: Extend the way how to find a Python module 625dd8a pylibfdt: Change how passing tests are recognized 3646316 pylibfdt: Test fdt.setprop take bytes on Python 3, add error handling cb0f454 pylibfdt: check_err accepts only integer as a first argument. 4b68c6b pylibfdt: Proper handling of bytes/unicode strings and octal literals 78e113e Use PRIxPTR for printing uintptr_t values ea7a8f6 libfdt: Fix FDT_ERR_NOTFOUND typos in documentation 5aafd7c libfdt: Fix fdt_getprop_by_offset() parameter name in documentation 7cbc550 checks: Add unit address check if node is enabled f267e67 checks: Fix crash with multiple source annotations 3616b9a checks: Use source position information for check failures 2bdbd07 checks: Make each message output atomic a1eff70 util: Add xa{v}sprintf_append functions 82a52ce libfdt: Add a test for fdt_getprop_by_offset() 607b858 PEP8 / Flake8 cleanups for setup.py f9c0a42 Remove broken objdir / srcdir support 5182b5e pylibfdt: Use common PREFIX variable d45bf1f Refine make tests_clean target 99284c4 Refine pylibfdt_clean target a4629cf Refine libfdt_clean target 08380fc tests: Use modern octal literals for Python 8113c00 pylibfdt: Allow switch to Python 3 via environment variable PYTHON 11738cf libfdt: Don't use memcpy to handle unaligned reads on ARM 86a288a checks: Restructure check_msg to decrease indentation 5667e7e annotations: add the annotation functionality 8e20ccf annotations: add positions ca930e2 tests: Don't lose errors from make checkm 43366bb tests: Property count valgrind errors in wrapped tests 5062516 srcpos: Remove srcpos_empty a3143fa Revert "annotations: add positions" 403cc79 checks: Update SPI bus check for 'spi-slave' baa1d2c annotations: add positions ff2ad38 Merge remote-tracking branch 'origin/pr/18' aa7254d libfdt: return correct value if #size-cells property is not present 49903ae use ptrdiff_t modifier for printing pointer differences da2b691 treesource: Fix dts output for phandles in middle of a sequence of ints 8f8b77a tests: Wrap check_align() calls with base_run_test() 522d81d Fix dts output with a REF_PATH marker e45198c Added test cases for target references 0fcffda Merge nodes with local target label references 1e4a092 pylibfdt: Don't have setup.py depend on where it's invoked from ca399b1 pylibfdt: Eliminate run_setup make function 98972f1 pylibfdt: Improved version extraction 7ba2be6 pylibfdt: Don't silence setup.py when V=1 7691f9d pylibfdt: Make SETUP make variable 855b996 pylibfdt: Simpler CFLAGS handling 47cafbe pylibfdt: Link extension module with libfdt rather than rebuilding dd695d6 pylibfdt: Correctly set build output directory 5932752 pylibfdt: We don't need include files from the base directory e84742a checks: fix simple-bus compatible matching 8c59a97 Fix missing labels when emitting dts format d448f9a Revert dts output formatting changes of spaces around brackets c86da84 Add support for YAML encoded output 361b5e7 Make type_marker_length helper public bfbfab0 pylibfdt: Add a means to add and delete notes 9005f41 pylibfdt: Allow delprop() to return errors b94c056 Make valgrind optional fd06c54 tests: Better testing of dtc -I fs mode c3f50c9 tests: Allow dtbs_equal_unordered to ignore mem reserves 0ac9fde dtc: trivial '-I fs -O dts' test 0fd1c8c pylibfdt: fdt_get_mem_rsv returns 2 uint64_t values 04853ca pylibfdt: Don't incorrectly / unnecessarily override uint64_t typemap 9619c86 Kill bogus TYPE_BLOB marker type ac68ff9 parser: add TYPE_STRING marker to path references 90a190e checks: add SPI bus checks 53a1bd5 checks: add I2C bus checks Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- scripts/dtc/Makefile | 49 +-- scripts/dtc/Makefile.dtc | 4 + scripts/dtc/checks.c | 255 +++++++++++++- scripts/dtc/data.c | 2 +- scripts/dtc/dtc-lexer.l | 4 +- scripts/dtc/dtc-parser.y | 53 ++- scripts/dtc/dtc.c | 22 +- scripts/dtc/dtc.h | 18 +- scripts/dtc/fdtget.c | 383 --------------------- scripts/dtc/flattree.c | 4 +- scripts/dtc/fstree.c | 5 +- scripts/dtc/libfdt/Makefile.libfdt | 15 + scripts/dtc/{ => libfdt}/fdt.c | 0 scripts/dtc/{ => libfdt}/fdt.h | 0 scripts/dtc/{ => libfdt}/fdt_addresses.c | 16 +- scripts/dtc/{ => libfdt}/fdt_empty_tree.c | 0 scripts/dtc/{ => libfdt}/fdt_overlay.c | 0 scripts/dtc/{ => libfdt}/fdt_ro.c | 0 scripts/dtc/{ => libfdt}/fdt_rw.c | 0 scripts/dtc/{ => libfdt}/fdt_strerror.c | 0 scripts/dtc/{ => libfdt}/fdt_sw.c | 0 scripts/dtc/{ => libfdt}/fdt_wip.c | 0 scripts/dtc/{ => libfdt}/libfdt.h | 30 +- scripts/dtc/{ => libfdt}/libfdt_env.h | 0 scripts/dtc/{ => libfdt}/libfdt_internal.h | 0 scripts/dtc/livetree.c | 33 +- scripts/dtc/srcpos.c | 153 +++++++- scripts/dtc/srcpos.h | 14 +- scripts/dtc/treesource.c | 124 ++++--- scripts/dtc/util.c | 60 ++-- scripts/dtc/util.h | 2 + scripts/dtc/version_gen.h | 2 +- scripts/dtc/yamltree.c | 247 +++++++++++++ 33 files changed, 926 insertions(+), 569 deletions(-) delete mode 100644 scripts/dtc/fdtget.c create mode 100644 scripts/dtc/libfdt/Makefile.libfdt rename scripts/dtc/{ => libfdt}/fdt.c (100%) rename scripts/dtc/{ => libfdt}/fdt.h (100%) rename scripts/dtc/{ => libfdt}/fdt_addresses.c (92%) rename scripts/dtc/{ => libfdt}/fdt_empty_tree.c (100%) rename scripts/dtc/{ => libfdt}/fdt_overlay.c (100%) rename scripts/dtc/{ => libfdt}/fdt_ro.c (100%) rename scripts/dtc/{ => libfdt}/fdt_rw.c (100%) rename scripts/dtc/{ => libfdt}/fdt_strerror.c (100%) rename scripts/dtc/{ => libfdt}/fdt_sw.c (100%) rename scripts/dtc/{ => libfdt}/fdt_wip.c (100%) rename scripts/dtc/{ => libfdt}/libfdt.h (99%) rename scripts/dtc/{ => libfdt}/libfdt_env.h (100%) rename scripts/dtc/{ => libfdt}/libfdt_internal.h (100%) create mode 100644 scripts/dtc/yamltree.c diff --git a/scripts/dtc/Makefile b/scripts/dtc/Makefile index 1d63476ecc..5f227d8d39 100644 --- a/scripts/dtc/Makefile +++ b/scripts/dtc/Makefile @@ -1,43 +1,30 @@ +# SPDX-License-Identifier: GPL-2.0 # scripts/dtc makefile -hostprogs-y := dtc fdtget +hostprogs-$(CONFIG_DTC) := dtc always := $(hostprogs-y) dtc-objs := dtc.o flattree.o fstree.o data.o livetree.o treesource.o \ srcpos.o checks.o util.o dtc-objs += dtc-lexer.lex.o dtc-parser.tab.o -libfdt-objs = fdt.o fdt_ro.o fdt_strerror.o fdt_wip.o fdt_overlay.o -libfdt-objs += fdt_empty_tree.o fdt_rw.o fdt_sw.o - -fdtget-objs += fdtget.o $(libfdt-objs) util.o - # Source files need to get at the userspace version of libfdt_env.h to compile - -HOSTCFLAGS_DTC := -I$(src) - -HOSTCFLAGS_checks.o := $(HOSTCFLAGS_DTC) -HOSTCFLAGS_data.o := $(HOSTCFLAGS_DTC) -HOSTCFLAGS_dtc.o := $(HOSTCFLAGS_DTC) -HOSTCFLAGS_flattree.o := $(HOSTCFLAGS_DTC) -HOSTCFLAGS_fstree.o := $(HOSTCFLAGS_DTC) -HOSTCFLAGS_livetree.o := $(HOSTCFLAGS_DTC) -HOSTCFLAGS_srcpos.o := $(HOSTCFLAGS_DTC) -HOSTCFLAGS_treesource.o := $(HOSTCFLAGS_DTC) -HOSTCFLAGS_util.o := $(HOSTCFLAGS_DTC) -HOSTCFLAGS_fdtget.o := $(HOSTCFLAGS_DTC) - -HOSTCFLAGS_fdt.o := $(HOSTCFLAGS_DTC) -HOSTCFLAGS_fdt_ro.o := $(HOSTCFLAGS_DTC) -HOSTCFLAGS_fdt_strerror.o := $(HOSTCFLAGS_DTC) -HOSTCFLAGS_fdt_wip.o := $(HOSTCFLAGS_DTC) -HOSTCFLAGS_fdt_empty_tree.o := $(HOSTCFLAGS_DTC) -HOSTCFLAGS_fdt_rw.o := $(HOSTCFLAGS_DTC) -HOSTCFLAGS_fdt_sw.o := $(HOSTCFLAGS_DTC) -HOSTCFLAGS_fdt_overlay.o := $(HOSTCFLAGS_DTC) - -HOSTCFLAGS_dtc-lexer.lex.o := $(HOSTCFLAGS_DTC) -HOSTCFLAGS_dtc-parser.tab.o := $(HOSTCFLAGS_DTC) +HOST_EXTRACFLAGS := -I$(src)/libfdt + +ifeq ($(wildcard /usr/include/yaml.h),) +ifneq ($(CHECK_DTBS),) +$(error dtc needs libyaml for DT schema validation support. \ + Install the necessary libyaml development package.) +endif +HOST_EXTRACFLAGS += -DNO_YAML +else +dtc-objs += yamltree.o +HOSTLDLIBS_dtc := -lyaml +endif + +# Generated files need one more search path to include headers in source tree +HOSTCFLAGS_dtc-lexer.lex.o := -I$(src) +HOSTCFLAGS_dtc-parser.tab.o := -I$(src) # dependencies on generated files need to be listed explicitly $(obj)/dtc-lexer.lex.o: $(obj)/dtc-parser.tab.h diff --git a/scripts/dtc/Makefile.dtc b/scripts/dtc/Makefile.dtc index bece49b355..d4375630a7 100644 --- a/scripts/dtc/Makefile.dtc +++ b/scripts/dtc/Makefile.dtc @@ -14,5 +14,9 @@ DTC_SRCS = \ treesource.c \ util.c +ifneq ($(NO_YAML),1) +DTC_SRCS += yamltree.c +endif + DTC_GEN_SRCS = dtc-lexer.lex.c dtc-parser.tab.c DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o) diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c index a2cc1036c9..c0ed45e1c3 100644 --- a/scripts/dtc/checks.c +++ b/scripts/dtc/checks.c @@ -19,6 +19,7 @@ */ #include "dtc.h" +#include "srcpos.h" #ifdef TRACE_CHECKS #define TRACE(c, ...) \ @@ -78,23 +79,56 @@ static inline void PRINTF(5, 6) check_msg(struct check *c, struct dt_info *dti, const char *fmt, ...) { va_list ap; - va_start(ap, fmt); + char *str = NULL; + struct srcpos *pos = NULL; + char *file_str; + + if (!(c->warn && (quiet < 1)) && !(c->error && (quiet < 2))) + return; + + if (prop && prop->srcpos) + pos = prop->srcpos; + else if (node && node->srcpos) + pos = node->srcpos; + + if (pos) { + file_str = srcpos_string(pos); + xasprintf(&str, "%s", file_str); + free(file_str); + } else if (streq(dti->outname, "-")) { + xasprintf(&str, "<stdout>"); + } else { + xasprintf(&str, "%s", dti->outname); + } - if ((c->warn && (quiet < 1)) - || (c->error && (quiet < 2))) { - fprintf(stderr, "%s: %s (%s): ", - strcmp(dti->outname, "-") ? dti->outname : "<stdout>", + xasprintf_append(&str, ": %s (%s): ", (c->error) ? "ERROR" : "Warning", c->name); - if (node) { - fprintf(stderr, "%s", node->fullpath); - if (prop) - fprintf(stderr, ":%s", prop->name); - fputs(": ", stderr); - } - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); + + if (node) { + if (prop) + xasprintf_append(&str, "%s:%s: ", node->fullpath, prop->name); + else + xasprintf_append(&str, "%s: ", node->fullpath); } + + va_start(ap, fmt); + xavsprintf_append(&str, fmt, ap); va_end(ap); + + xasprintf_append(&str, "\n"); + + if (!prop && pos) { + pos = node->srcpos; + while (pos->next) { + pos = pos->next; + + file_str = srcpos_string(pos); + xasprintf_append(&str, " also defined at %s\n", file_str); + free(file_str); + } + } + + fputs(str, stderr); } #define FAIL(c, dti, node, ...) \ @@ -910,7 +944,7 @@ static bool node_is_compatible(struct node *node, const char *compat) for (str = prop->val.val, end = str + prop->val.len; str < end; str += strnlen(str, end - str) + 1) { - if (strprefixeq(str, end - str, compat)) + if (streq(str, compat)) return true; } return false; @@ -921,7 +955,8 @@ static void check_simple_bus_bridge(struct check *c, struct dt_info *dti, struct if (node_is_compatible(node, "simple-bus")) node->bus = &simple_bus; } -WARNING(simple_bus_bridge, check_simple_bus_bridge, NULL, &addr_size_cells); +WARNING(simple_bus_bridge, check_simple_bus_bridge, NULL, + &addr_size_cells, &compatible_is_string_list); static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct node *node) { @@ -962,6 +997,149 @@ static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct no } WARNING(simple_bus_reg, check_simple_bus_reg, NULL, ®_format, &simple_bus_bridge); +static const struct bus_type i2c_bus = { + .name = "i2c-bus", +}; + +static void check_i2c_bus_bridge(struct check *c, struct dt_info *dti, struct node *node) +{ + if (strprefixeq(node->name, node->basenamelen, "i2c-bus") || + strprefixeq(node->name, node->basenamelen, "i2c-arb")) { + node->bus = &i2c_bus; + } else if (strprefixeq(node->name, node->basenamelen, "i2c")) { + struct node *child; + for_each_child(node, child) { + if (strprefixeq(child->name, node->basenamelen, "i2c-bus")) + return; + } + node->bus = &i2c_bus; + } else + return; + + if (!node->children) + return; + + if (node_addr_cells(node) != 1) + FAIL(c, dti, node, "incorrect #address-cells for I2C bus"); + if (node_size_cells(node) != 0) + FAIL(c, dti, node, "incorrect #size-cells for I2C bus"); + +} +WARNING(i2c_bus_bridge, check_i2c_bus_bridge, NULL, &addr_size_cells); + +static void check_i2c_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]; + uint32_t reg = 0; + int len; + cell_t *cells = NULL; + + if (!node->parent || (node->parent->bus != &i2c_bus)) + return; + + prop = get_property(node, "reg"); + if (prop) + cells = (cell_t *)prop->val.val; + + if (!cells) { + FAIL(c, dti, node, "missing or empty reg property"); + return; + } + + reg = fdt32_to_cpu(*cells); + snprintf(unit_addr, sizeof(unit_addr), "%x", reg); + if (!streq(unitname, unit_addr)) + FAIL(c, dti, node, "I2C bus unit address format error, expected \"%s\"", + unit_addr); + + for (len = prop->val.len; len > 0; len -= 4) { + reg = fdt32_to_cpu(*(cells++)); + if (reg > 0x3ff) + FAIL_PROP(c, dti, node, prop, "I2C address must be less than 10-bits, got \"0x%x\"", + reg); + + } +} +WARNING(i2c_bus_reg, check_i2c_bus_reg, NULL, ®_format, &i2c_bus_bridge); + +static const struct bus_type spi_bus = { + .name = "spi-bus", +}; + +static void check_spi_bus_bridge(struct check *c, struct dt_info *dti, struct node *node) +{ + int spi_addr_cells = 1; + + if (strprefixeq(node->name, node->basenamelen, "spi")) { + node->bus = &spi_bus; + } else { + /* Try to detect SPI buses which don't have proper node name */ + struct node *child; + + if (node_addr_cells(node) != 1 || node_size_cells(node) != 0) + return; + + for_each_child(node, child) { + struct property *prop; + for_each_property(child, prop) { + if (strprefixeq(prop->name, 4, "spi-")) { + node->bus = &spi_bus; + break; + } + } + if (node->bus == &spi_bus) + break; + } + + if (node->bus == &spi_bus && get_property(node, "reg")) + FAIL(c, dti, node, "node name for SPI buses should be 'spi'"); + } + if (node->bus != &spi_bus || !node->children) + return; + + if (get_property(node, "spi-slave")) + spi_addr_cells = 0; + if (node_addr_cells(node) != spi_addr_cells) + FAIL(c, dti, node, "incorrect #address-cells for SPI bus"); + if (node_size_cells(node) != 0) + FAIL(c, dti, node, "incorrect #size-cells for SPI bus"); + +} +WARNING(spi_bus_bridge, check_spi_bus_bridge, NULL, &addr_size_cells); + +static void check_spi_bus_reg(struct check *c, struct dt_info *dti, struct node *node) +{ + struct property *prop; + const char *unitname = get_unitname(node); + char unit_addr[9]; + uint32_t reg = 0; + cell_t *cells = NULL; + + if (!node->parent || (node->parent->bus != &spi_bus)) + return; + + if (get_property(node->parent, "spi-slave")) + return; + + prop = get_property(node, "reg"); + if (prop) + cells = (cell_t *)prop->val.val; + + if (!cells) { + FAIL(c, dti, node, "missing or empty reg property"); + return; + } + + reg = fdt32_to_cpu(*cells); + snprintf(unit_addr, sizeof(unit_addr), "%x", reg); + if (!streq(unitname, unit_addr)) + FAIL(c, dti, node, "SPI bus unit address format error, expected \"%s\"", + unit_addr); +} +WARNING(spi_bus_reg, check_spi_bus_reg, NULL, ®_format, &spi_bus_bridge); + static void check_unit_address_format(struct check *c, struct dt_info *dti, struct node *node) { @@ -1034,8 +1212,24 @@ static void check_avoid_unnecessary_addr_size(struct check *c, struct dt_info *d } WARNING(avoid_unnecessary_addr_size, check_avoid_unnecessary_addr_size, NULL, &avoid_default_addr_size); -static void check_unique_unit_address(struct check *c, struct dt_info *dti, - struct node *node) +static bool node_is_disabled(struct node *node) +{ + struct property *prop; + + prop = get_property(node, "status"); + if (prop) { + char *str = prop->val.val; + if (streq("disabled", str)) + return true; + } + + return false; +} + +static void check_unique_unit_address_common(struct check *c, + struct dt_info *dti, + struct node *node, + bool disable_check) { struct node *childa; @@ -1052,18 +1246,38 @@ static void check_unique_unit_address(struct check *c, struct dt_info *dti, if (!strlen(addr_a)) continue; + if (disable_check && node_is_disabled(childa)) + continue; + for_each_child(node, childb) { const char *addr_b = get_unitname(childb); if (childa == childb) break; + if (disable_check && node_is_disabled(childb)) + continue; + if (streq(addr_a, addr_b)) FAIL(c, dti, childb, "duplicate unit-address (also used in node %s)", childa->fullpath); } } } + +static void check_unique_unit_address(struct check *c, struct dt_info *dti, + struct node *node) +{ + check_unique_unit_address_common(c, dti, node, false); +} WARNING(unique_unit_address, check_unique_unit_address, NULL, &avoid_default_addr_size); +static void check_unique_unit_address_if_enabled(struct check *c, struct dt_info *dti, + struct node *node) +{ + check_unique_unit_address_common(c, dti, node, true); +} +CHECK_ENTRY(unique_unit_address_if_enabled, check_unique_unit_address_if_enabled, + NULL, false, false, &avoid_default_addr_size); + static void check_obsolete_chosen_interrupt_controller(struct check *c, struct dt_info *dti, struct node *node) @@ -1582,9 +1796,16 @@ static struct check *check_table[] = { &simple_bus_bridge, &simple_bus_reg, + &i2c_bus_bridge, + &i2c_bus_reg, + + &spi_bus_bridge, + &spi_bus_reg, + &avoid_default_addr_size, &avoid_unnecessary_addr_size, &unique_unit_address, + &unique_unit_address_if_enabled, &obsolete_chosen_interrupt_controller, &chosen_node_is_root, &chosen_node_bootargs, &chosen_node_stdout_path, diff --git a/scripts/dtc/data.c b/scripts/dtc/data.c index accdfaef66..4a204145cc 100644 --- a/scripts/dtc/data.c +++ b/scripts/dtc/data.c @@ -95,7 +95,7 @@ struct data data_copy_file(FILE *f, size_t maxlen) { struct data d = empty_data; - d = data_add_marker(d, TYPE_BLOB, NULL); + d = data_add_marker(d, TYPE_NONE, NULL); while (!feof(f) && (d.len < maxlen)) { size_t chunksize, ret; diff --git a/scripts/dtc/dtc-lexer.l b/scripts/dtc/dtc-lexer.l index 615b7ec658..06c0409024 100644 --- a/scripts/dtc/dtc-lexer.l +++ b/scripts/dtc/dtc-lexer.l @@ -213,14 +213,14 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...); <*>\&{LABEL} { /* label reference */ DPRINT("Ref: %s\n", yytext+1); yylval.labelref = xstrdup(yytext+1); - return DT_REF; + return DT_LABEL_REF; } <*>"&{/"{PATHCHAR}*\} { /* new-style path reference */ yytext[yyleng-1] = '\0'; DPRINT("Ref: %s\n", yytext+2); yylval.labelref = xstrdup(yytext+2); - return DT_REF; + return DT_PATH_REF; } <BYTESTRING>[0-9a-fA-F]{2} { diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y index 815481a9bb..2ec981e861 100644 --- a/scripts/dtc/dtc-parser.y +++ b/scripts/dtc/dtc-parser.y @@ -70,7 +70,8 @@ extern bool treesource_error; %token <byte> DT_BYTE %token <data> DT_STRING %token <labelref> DT_LABEL -%token <labelref> DT_REF +%token <labelref> DT_LABEL_REF +%token <labelref> DT_PATH_REF %token DT_INCBIN %type <data> propdata @@ -83,6 +84,7 @@ extern bool treesource_error; %type <data> bytestring %type <prop> propdef %type <proplist> proplist +%type <labelref> dt_ref %type <node> devicetree %type <node> nodedef @@ -158,6 +160,8 @@ memreserve: } ; +dt_ref: DT_LABEL_REF | DT_PATH_REF; + devicetree: '/' nodedef { @@ -167,7 +171,7 @@ devicetree: { $$ = merge_nodes($1, $3); } - | DT_REF nodedef + | dt_ref nodedef { /* * We rely on the rule being always: @@ -176,9 +180,12 @@ devicetree: */ if (!($<flags>-1 & DTSF_PLUGIN)) ERROR(&@2, "Label or path %s not found", $1); - $$ = add_orphan_node(name_node(build_node(NULL, NULL), ""), $2, $1); + $$ = add_orphan_node( + name_node(build_node(NULL, NULL, NULL), + ""), + $2, $1); } - | devicetree DT_LABEL DT_REF nodedef + | devicetree DT_LABEL dt_ref nodedef { struct node *target = get_node_by_ref($1, $3); @@ -189,7 +196,7 @@ devicetree: ERROR(&@3, "Label or path %s not found", $3); $$ = $1; } - | devicetree DT_REF nodedef + | devicetree DT_PATH_REF nodedef { /* * We rely on the rule being always: @@ -208,7 +215,26 @@ devicetree: } $$ = $1; } - | devicetree DT_DEL_NODE DT_REF ';' + | devicetree DT_LABEL_REF nodedef + { + struct node *target = get_node_by_ref($1, $2); + + if (target) { + merge_nodes(target, $3); + } else { + /* + * We rely on the rule being always: + * versioninfo plugindecl memreserves devicetree + * so $-1 is what we want (plugindecl) + */ + if ($<flags>-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); @@ -220,7 +246,7 @@ devicetree: $$ = $1; } - | devicetree DT_OMIT_NO_REF DT_REF ';' + | devicetree DT_OMIT_NO_REF dt_ref ';' { struct node *target = get_node_by_ref($1, $3); @@ -237,7 +263,7 @@ devicetree: nodedef: '{' proplist subnodes '}' ';' { - $$ = build_node($2, $3); + $$ = build_node($2, $3, &@$); } ; @@ -255,11 +281,11 @@ proplist: propdef: DT_PROPNODENAME '=' propdata ';' { - $$ = build_property($1, $3); + $$ = build_property($1, $3, &@$); } | DT_PROPNODENAME ';' { - $$ = build_property($1, empty_data); + $$ = build_property($1, empty_data, &@$); } | DT_DEL_PROP DT_PROPNODENAME ';' { @@ -285,8 +311,9 @@ propdata: { $$ = data_merge($1, $3); } - | propdataprefix DT_REF + | propdataprefix dt_ref { + $1 = data_add_marker($1, TYPE_STRING, $2); $$ = data_add_marker($1, REF_PATH, $2); } | propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')' @@ -382,7 +409,7 @@ arrayprefix: $$.data = data_append_integer($1.data, $2, $1.bits); } - | arrayprefix DT_REF + | arrayprefix dt_ref { uint64_t val = ~0ULL >> (64 - $1.bits); @@ -539,7 +566,7 @@ subnode: } | DT_DEL_NODE DT_PROPNODENAME ';' { - $$ = name_node(build_node_delete(), $2); + $$ = name_node(build_node_delete(&@$), $2); } | DT_OMIT_NO_REF subnode { diff --git a/scripts/dtc/dtc.c b/scripts/dtc/dtc.c index c36994e6ea..695e1f789f 100644 --- a/scripts/dtc/dtc.c +++ b/scripts/dtc/dtc.c @@ -35,6 +35,8 @@ 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 */ +int annotate; /* Level of annotation: 1 for input source location + >1 for full input source location. */ static int is_power_of_2(int x) { @@ -60,7 +62,7 @@ static void fill_fullpaths(struct node *tree, const char *prefix) /* Usage related data. */ static const char usage_synopsis[] = "dtc [options] <input file>"; -static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@Ahv"; +static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@AThv"; static struct option const usage_long_opts[] = { {"quiet", no_argument, NULL, 'q'}, {"in-format", a_argument, NULL, 'I'}, @@ -81,6 +83,7 @@ static struct option const usage_long_opts[] = { {"error", a_argument, NULL, 'E'}, {"symbols", no_argument, NULL, '@'}, {"auto-alias", no_argument, NULL, 'A'}, + {"annotate", no_argument, NULL, 'T'}, {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'v'}, {NULL, no_argument, NULL, 0x0}, @@ -95,6 +98,9 @@ static const char * const usage_opts_help[] = { "\n\tOutput formats are:\n" "\t\tdts - device tree source text\n" "\t\tdtb - device tree blob\n" +#ifndef NO_YAML + "\t\tyaml - device tree encoded as YAML\n" +#endif "\t\tasm - assembler source", "\n\tBlob version to produce, defaults to "stringify(DEFAULT_FDT_VERSION)" (for dtb and asm output)", "\n\tOutput dependency file", @@ -114,6 +120,7 @@ static const char * const usage_opts_help[] = { "\n\tEnable/disable errors (prefix with \"no-\")", "\n\tEnable generation of symbols", "\n\tEnable auto-alias of labels", + "\n\tAnnotate output .dts with input source file and line (-T -T for more details)", "\n\tPrint this help and exit", "\n\tPrint version and exit", NULL, @@ -128,6 +135,8 @@ static const char *guess_type_by_name(const char *fname, const char *fallback) return fallback; if (!strcasecmp(s, ".dts")) return "dts"; + if (!strcasecmp(s, ".yaml")) + return "yaml"; if (!strcasecmp(s, ".dtb")) return "dtb"; return fallback; @@ -259,6 +268,9 @@ int main(int argc, char *argv[]) case 'A': auto_label_aliases = 1; break; + case 'T': + annotate++; + break; case 'h': usage(NULL); @@ -297,6 +309,8 @@ int main(int argc, char *argv[]) outform = "dts"; } } + if (annotate && (!streq(inform, "dts") || !streq(outform, "dts"))) + die("--annotate requires -I dts -O dts\n"); if (streq(inform, "dts")) dti = dt_from_source(arg); else if (streq(inform, "fs")) @@ -350,6 +364,12 @@ int main(int argc, char *argv[]) if (streq(outform, "dts")) { dt_to_source(outf, dti); +#ifndef NO_YAML + } else if (streq(outform, "yaml")) { + if (!streq(inform, "dts")) + die("YAML output format requires dts input format\n"); + dt_to_yaml(outf, dti); +#endif } else if (streq(outform, "dtb")) { dt_to_blob(outf, dti, outversion); } else if (streq(outform, "asm")) { diff --git a/scripts/dtc/dtc.h b/scripts/dtc/dtc.h index 303c2a6a73..789e0b1bc0 100644 --- a/scripts/dtc/dtc.h +++ b/scripts/dtc/dtc.h @@ -58,6 +58,7 @@ 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 */ +extern int annotate; /* annotate .dts with input source location */ #define PHANDLE_LEGACY 0x1 #define PHANDLE_EPAPR 0x2 @@ -82,7 +83,6 @@ enum markertype { TYPE_UINT16, TYPE_UINT32, TYPE_UINT64, - TYPE_BLOB, TYPE_STRING, }; extern const char *markername(enum markertype markertype); @@ -109,6 +109,8 @@ struct data { for_each_marker(m) \ if ((m)->type == (t)) +size_t type_marker_length(struct marker *m); + void data_free(struct data d); struct data data_grow_for(struct data d, int xlen); @@ -157,6 +159,7 @@ struct property { struct property *next; struct label *labels; + struct srcpos *srcpos; }; struct node { @@ -176,6 +179,7 @@ struct node { struct label *labels; const struct bus_type *bus; + struct srcpos *srcpos; bool omit_if_unused, is_referenced; }; @@ -204,13 +208,15 @@ struct node { 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(char *name, struct data val, + struct srcpos *srcpos); 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 *build_node(struct property *proplist, struct node *children, + struct srcpos *srcpos); +struct node *build_node_delete(struct srcpos *srcpos); struct node *name_node(struct node *node, char *name); struct node *omit_node_if_unused(struct node *node); struct node *reference_node(struct node *node); @@ -298,6 +304,10 @@ struct dt_info *dt_from_blob(const char *fname); void dt_to_source(FILE *f, struct dt_info *dti); struct dt_info *dt_from_source(const char *f); +/* YAML source */ + +void dt_to_yaml(FILE *f, struct dt_info *dti); + /* FS trees */ struct dt_info *dt_from_fs(const char *dirname); diff --git a/scripts/dtc/fdtget.c b/scripts/dtc/fdtget.c deleted file mode 100644 index a79c3b2aa1..0000000000 --- a/scripts/dtc/fdtget.c +++ /dev/null @@ -1,383 +0,0 @@ -/* - * 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 <pantelis.antoniou@gmail.com> and - * Matthew McClintock <msm@freescale.com> - * - * 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 <assert.h> -#include <ctype.h> -#include <getopt.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <libfdt.h> - -#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_ld((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 size; - const char *s; - int is_string; - - /* 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; - } - - 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 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; - fdt_getprop_by_offset(blob, prop, &name, NULL); - 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 - * @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, NULL); - 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 <options> <dt file> [<node> <property>]...\n" - " fdtget -p <options> <dt file> [<node> ]...\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; -} diff --git a/scripts/dtc/flattree.c b/scripts/dtc/flattree.c index 851ea87dbc..acf04c3066 100644 --- a/scripts/dtc/flattree.c +++ b/scripts/dtc/flattree.c @@ -692,7 +692,7 @@ static struct property *flat_read_property(struct inbuf *dtbuf, val = flat_read_data(dtbuf, proplen); - return build_property(name, val); + return build_property(name, val, NULL); } @@ -750,7 +750,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf, char *flatname; uint32_t val; - node = build_node(NULL, NULL); + node = build_node(NULL, NULL, NULL); flatname = flat_read_string(dtbuf); diff --git a/scripts/dtc/fstree.c b/scripts/dtc/fstree.c index ae7d06c3c4..1e7eeba47f 100644 --- a/scripts/dtc/fstree.c +++ b/scripts/dtc/fstree.c @@ -34,7 +34,7 @@ static struct node *read_fstree(const char *dirname) if (!d) die("Couldn't opendir() \"%s\": %s\n", dirname, strerror(errno)); - tree = build_node(NULL, NULL); + tree = build_node(NULL, NULL, NULL); while ((de = readdir(d)) != NULL) { char *tmpname; @@ -60,7 +60,8 @@ static struct node *read_fstree(const char *dirname) } else { prop = build_property(xstrdup(de->d_name), data_copy_file(pfile, - st.st_size)); + st.st_size), + NULL); add_property(tree, prop); fclose(pfile); } diff --git a/scripts/dtc/libfdt/Makefile.libfdt b/scripts/dtc/libfdt/Makefile.libfdt new file mode 100644 index 0000000000..3af3656df8 --- /dev/null +++ b/scripts/dtc/libfdt/Makefile.libfdt @@ -0,0 +1,15 @@ +# Makefile.libfdt +# +# This is not a complete Makefile of itself. Instead, it is designed to +# be easily embeddable into other systems of Makefiles. +# +LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1 +LIBFDT_INCLUDES = fdt.h libfdt.h libfdt_env.h +LIBFDT_VERSION = version.lds +LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c \ + fdt_addresses.c fdt_overlay.c +LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o) + +libfdt_clean: + @$(VECHO) CLEAN "(libfdt)" + rm -f $(STD_CLEANFILES:%=$(LIBFDT_dir)/%) diff --git a/scripts/dtc/fdt.c b/scripts/dtc/libfdt/fdt.c similarity index 100% rename from scripts/dtc/fdt.c rename to scripts/dtc/libfdt/fdt.c diff --git a/scripts/dtc/fdt.h b/scripts/dtc/libfdt/fdt.h similarity index 100% rename from scripts/dtc/fdt.h rename to scripts/dtc/libfdt/fdt.h diff --git a/scripts/dtc/fdt_addresses.c b/scripts/dtc/libfdt/fdt_addresses.c similarity index 92% rename from scripts/dtc/fdt_addresses.c rename to scripts/dtc/libfdt/fdt_addresses.c index 49537b578d..f13a87dfa0 100644 --- a/scripts/dtc/fdt_addresses.c +++ b/scripts/dtc/libfdt/fdt_addresses.c @@ -64,7 +64,7 @@ static int fdt_cells(const void *fdt, int nodeoffset, const char *name) c = fdt_getprop(fdt, nodeoffset, name, &len); if (!c) - return 2; + return len; if (len != sizeof(*c)) return -FDT_ERR_BADNCELLS; @@ -78,10 +78,20 @@ static int fdt_cells(const void *fdt, int nodeoffset, const char *name) int fdt_address_cells(const void *fdt, int nodeoffset) { - return fdt_cells(fdt, nodeoffset, "#address-cells"); + int val; + + val = fdt_cells(fdt, nodeoffset, "#address-cells"); + if (val == -FDT_ERR_NOTFOUND) + return 2; + return val; } int fdt_size_cells(const void *fdt, int nodeoffset) { - return fdt_cells(fdt, nodeoffset, "#size-cells"); + int val; + + val = fdt_cells(fdt, nodeoffset, "#size-cells"); + if (val == -FDT_ERR_NOTFOUND) + return 1; + return val; } diff --git a/scripts/dtc/fdt_empty_tree.c b/scripts/dtc/libfdt/fdt_empty_tree.c similarity index 100% rename from scripts/dtc/fdt_empty_tree.c rename to scripts/dtc/libfdt/fdt_empty_tree.c diff --git a/scripts/dtc/fdt_overlay.c b/scripts/dtc/libfdt/fdt_overlay.c similarity index 100% rename from scripts/dtc/fdt_overlay.c rename to scripts/dtc/libfdt/fdt_overlay.c diff --git a/scripts/dtc/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c similarity index 100% rename from scripts/dtc/fdt_ro.c rename to scripts/dtc/libfdt/fdt_ro.c diff --git a/scripts/dtc/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c similarity index 100% rename from scripts/dtc/fdt_rw.c rename to scripts/dtc/libfdt/fdt_rw.c diff --git a/scripts/dtc/fdt_strerror.c b/scripts/dtc/libfdt/fdt_strerror.c similarity index 100% rename from scripts/dtc/fdt_strerror.c rename to scripts/dtc/libfdt/fdt_strerror.c diff --git a/scripts/dtc/fdt_sw.c b/scripts/dtc/libfdt/fdt_sw.c similarity index 100% rename from scripts/dtc/fdt_sw.c rename to scripts/dtc/libfdt/fdt_sw.c diff --git a/scripts/dtc/fdt_wip.c b/scripts/dtc/libfdt/fdt_wip.c similarity index 100% rename from scripts/dtc/fdt_wip.c rename to scripts/dtc/libfdt/fdt_wip.c diff --git a/scripts/dtc/libfdt.h b/scripts/dtc/libfdt/libfdt.h similarity index 99% rename from scripts/dtc/libfdt.h rename to scripts/dtc/libfdt/libfdt.h index 2bd151dd35..15eb0fd3c6 100644 --- a/scripts/dtc/libfdt.h +++ b/scripts/dtc/libfdt/libfdt.h @@ -163,18 +163,26 @@ uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset); static inline uint32_t fdt32_ld(const fdt32_t *p) { - fdt32_t v; + const uint8_t *bp = (const uint8_t *)p; - memcpy(&v, p, sizeof(v)); - return fdt32_to_cpu(v); + return ((uint32_t)bp[0] << 24) + | ((uint32_t)bp[1] << 16) + | ((uint32_t)bp[2] << 8) + | bp[3]; } static inline uint64_t fdt64_ld(const fdt64_t *p) { - fdt64_t v; - - memcpy(&v, p, sizeof(v)); - return fdt64_to_cpu(v); + const uint8_t *bp = (const uint8_t *)p; + + return ((uint64_t)bp[0] << 56) + | ((uint64_t)bp[1] << 48) + | ((uint64_t)bp[2] << 40) + | ((uint64_t)bp[3] << 32) + | ((uint64_t)bp[4] << 24) + | ((uint64_t)bp[5] << 16) + | ((uint64_t)bp[6] << 8) + | bp[7]; } /**********************************************************************/ @@ -219,7 +227,7 @@ int fdt_next_subnode(const void *fdt, int offset); * ... * } * - * if ((node < 0) && (node != -FDT_ERR_NOT_FOUND)) { + * if ((node < 0) && (node != -FDT_ERR_NOTFOUND)) { * Error handling * } * @@ -558,7 +566,7 @@ int fdt_next_property_offset(const void *fdt, int offset); * ... * } * - * if ((property < 0) && (property != -FDT_ERR_NOT_FOUND)) { + * if ((property < 0) && (property != -FDT_ERR_NOTFOUND)) { * Error handling * } * @@ -661,7 +669,7 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset, /** * 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 + * @offset: 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 * @@ -1145,7 +1153,7 @@ int fdt_address_cells(const void *fdt, int nodeoffset); * * returns: * 0 <= n < FDT_MAX_NCELLS, on success - * 2, if the node has no #size-cells property + * 1, if the node has no #size-cells property * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid * #size-cells property * -FDT_ERR_BADMAGIC, diff --git a/scripts/dtc/libfdt_env.h b/scripts/dtc/libfdt/libfdt_env.h similarity index 100% rename from scripts/dtc/libfdt_env.h rename to scripts/dtc/libfdt/libfdt_env.h diff --git a/scripts/dtc/libfdt_internal.h b/scripts/dtc/libfdt/libfdt_internal.h similarity index 100% rename from scripts/dtc/libfdt_internal.h rename to scripts/dtc/libfdt/libfdt_internal.h diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c index 4ff0679e00..7a2e6446a1 100644 --- a/scripts/dtc/livetree.c +++ b/scripts/dtc/livetree.c @@ -19,6 +19,7 @@ */ #include "dtc.h" +#include "srcpos.h" /* * Tree building functions @@ -50,7 +51,8 @@ void delete_labels(struct label **labels) label->deleted = 1; } -struct property *build_property(char *name, struct data val) +struct property *build_property(char *name, struct data val, + struct srcpos *srcpos) { struct property *new = xmalloc(sizeof(*new)); @@ -58,6 +60,7 @@ struct property *build_property(char *name, struct data val) new->name = name; new->val = val; + new->srcpos = srcpos_copy(srcpos); return new; } @@ -97,7 +100,8 @@ struct property *reverse_properties(struct property *first) return head; } -struct node *build_node(struct property *proplist, struct node *children) +struct node *build_node(struct property *proplist, struct node *children, + struct srcpos *srcpos) { struct node *new = xmalloc(sizeof(*new)); struct node *child; @@ -106,6 +110,7 @@ struct node *build_node(struct property *proplist, struct node *children) new->proplist = reverse_properties(proplist); new->children = children; + new->srcpos = srcpos_copy(srcpos); for_each_child(new, child) { child->parent = new; @@ -114,13 +119,14 @@ struct node *build_node(struct property *proplist, struct node *children) return new; } -struct node *build_node_delete(void) +struct node *build_node_delete(struct srcpos *srcpos) { struct node *new = xmalloc(sizeof(*new)); memset(new, 0, sizeof(*new)); new->deleted = 1; + new->srcpos = srcpos_copy(srcpos); return new; } @@ -183,6 +189,8 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node) old_prop->val = new_prop->val; old_prop->deleted = 0; + free(old_prop->srcpos); + old_prop->srcpos = new_prop->srcpos; free(new_prop); new_prop = NULL; break; @@ -223,6 +231,8 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node) add_child(old_node, new_child); } + old_node->srcpos = srcpos_extend(old_node->srcpos, new_node->srcpos); + /* The new node contents are now merged into the old node. Free * the new node. */ free(new_node); @@ -241,18 +251,18 @@ struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref) if (ref[0] == '/') { d = data_append_data(d, ref, strlen(ref) + 1); - p = build_property("target-path", d); + p = build_property("target-path", d, NULL); } else { d = data_add_marker(d, REF_PHANDLE, ref); d = data_append_integer(d, 0xffffffff, 32); - p = build_property("target", d); + p = build_property("target", d, NULL); } xasprintf(&name, "fragment@%u", next_orphan_fragment++); name_node(new_node, "__overlay__"); - node = build_node(p, new_node); + node = build_node(p, new_node, NULL); name_node(node, name); add_child(dt, node); @@ -351,7 +361,7 @@ void append_to_property(struct node *node, p->val = d; } else { d = data_append_data(empty_data, data, len); - p = build_property(name, d); + p = build_property(name, d, NULL); add_property(node, p); } } @@ -609,11 +619,11 @@ cell_t get_node_phandle(struct node *root, struct node *node) if (!get_property(node, "linux,phandle") && (phandle_format & PHANDLE_LEGACY)) - add_property(node, build_property("linux,phandle", d)); + add_property(node, build_property("linux,phandle", d, NULL)); if (!get_property(node, "phandle") && (phandle_format & PHANDLE_EPAPR)) - add_property(node, build_property("phandle", d)); + add_property(node, build_property("phandle", d, NULL)); /* If the node *does* have a phandle property, we must * be dealing with a self-referencing phandle, which will be @@ -787,7 +797,7 @@ static struct node *build_and_name_child_node(struct node *parent, char *name) { struct node *node; - node = build_node(NULL, NULL); + node = build_node(NULL, NULL, NULL); name_node(node, xstrdup(name)); add_child(parent, node); @@ -849,7 +859,8 @@ static void generate_label_tree_internal(struct dt_info *dti, /* insert it */ p = build_property(l->label, data_copy_mem(node->fullpath, - strlen(node->fullpath) + 1)); + strlen(node->fullpath) + 1), + NULL); add_property(an, p); } diff --git a/scripts/dtc/srcpos.c b/scripts/dtc/srcpos.c index cb6ed0e3e5..41f83700ee 100644 --- a/scripts/dtc/srcpos.c +++ b/scripts/dtc/srcpos.c @@ -33,6 +33,9 @@ struct search_path { /* This is the list of directories that we search for source files */ static struct search_path *search_path_head, **search_path_tail; +/* Detect infinite include recursion. */ +#define MAX_SRCFILE_DEPTH (100) +static int srcfile_depth; /* = 0 */ static char *get_dirname(const char *path) { @@ -51,11 +54,51 @@ static char *get_dirname(const char *path) FILE *depfile; /* = NULL */ struct srcfile_state *current_srcfile; /* = NULL */ +static char *initial_path; /* = NULL */ +static int initial_pathlen; /* = 0 */ +static bool initial_cpp = true; -/* Detect infinite include recursion. */ -#define MAX_SRCFILE_DEPTH (100) -static int srcfile_depth; /* = 0 */ +static void set_initial_path(char *fname) +{ + int i, len = strlen(fname); + xasprintf(&initial_path, "%s", fname); + initial_pathlen = 0; + for (i = 0; i != len; i++) + if (initial_path[i] == '/') + initial_pathlen++; +} + +static char *shorten_to_initial_path(char *fname) +{ + char *p1, *p2, *prevslash1 = NULL; + int slashes = 0; + + for (p1 = fname, p2 = initial_path; *p1 && *p2; p1++, p2++) { + if (*p1 != *p2) + break; + if (*p1 == '/') { + prevslash1 = p1; + slashes++; + } + } + p1 = prevslash1 + 1; + if (prevslash1) { + int diff = initial_pathlen - slashes, i, j; + int restlen = strlen(fname) - (p1 - fname); + char *res; + + res = xmalloc((3 * diff) + restlen + 1); + for (i = 0, j = 0; i != diff; i++) { + res[j++] = '.'; + res[j++] = '.'; + res[j++] = '/'; + } + strcpy(res + j, p1); + return res; + } + return NULL; +} /** * Try to open a file in a given directory. @@ -157,6 +200,9 @@ void srcfile_push(const char *fname) srcfile->colno = 1; current_srcfile = srcfile; + + if (srcfile_depth == 1) + set_initial_path(srcfile->name); } bool srcfile_pop(void) @@ -197,18 +243,6 @@ void srcfile_add_search_path(const char *dirname) search_path_tail = &node->next; } -/* - * The empty source position. - */ - -struct srcpos srcpos_empty = { - .first_line = 0, - .first_column = 0, - .last_line = 0, - .last_column = 0, - .file = NULL, -}; - void srcpos_update(struct srcpos *pos, const char *text, int len) { int i; @@ -234,13 +268,35 @@ struct srcpos * srcpos_copy(struct srcpos *pos) { struct srcpos *pos_new; + struct srcfile_state *srcfile_state; + + if (!pos) + return NULL; pos_new = xmalloc(sizeof(struct srcpos)); + assert(pos->next == NULL); memcpy(pos_new, pos, sizeof(struct srcpos)); + /* allocate without free */ + srcfile_state = xmalloc(sizeof(struct srcfile_state)); + memcpy(srcfile_state, pos->file, sizeof(struct srcfile_state)); + pos_new->file = srcfile_state; + return pos_new; } +struct srcpos *srcpos_extend(struct srcpos *pos, struct srcpos *newtail) +{ + struct srcpos *p; + + if (!pos) + return newtail; + + for (p = pos; p->next != NULL; p = p->next); + p->next = newtail; + return pos; +} + char * srcpos_string(struct srcpos *pos) { @@ -266,6 +322,68 @@ srcpos_string(struct srcpos *pos) return pos_str; } +static char * +srcpos_string_comment(struct srcpos *pos, bool first_line, int level) +{ + char *pos_str, *fname, *first, *rest; + bool fresh_fname = false; + + if (!pos) { + if (level > 1) { + xasprintf(&pos_str, "<no-file>:<no-line>"); + return pos_str; + } else { + return NULL; + } + } + + if (!pos->file) + fname = "<no-file>"; + else if (!pos->file->name) + fname = "<no-filename>"; + else if (level > 1) + fname = pos->file->name; + else { + fname = shorten_to_initial_path(pos->file->name); + if (fname) + fresh_fname = true; + else + fname = pos->file->name; + } + + if (level > 1) + xasprintf(&first, "%s:%d:%d-%d:%d", fname, + pos->first_line, pos->first_column, + pos->last_line, pos->last_column); + else + xasprintf(&first, "%s:%d", fname, + first_line ? pos->first_line : pos->last_line); + + if (fresh_fname) + free(fname); + + if (pos->next != NULL) { + rest = srcpos_string_comment(pos->next, first_line, level); + xasprintf(&pos_str, "%s, %s", first, rest); + free(first); + free(rest); + } else { + pos_str = first; + } + + return pos_str; +} + +char *srcpos_string_first(struct srcpos *pos, int level) +{ + return srcpos_string_comment(pos, true, level); +} + +char *srcpos_string_last(struct srcpos *pos, int level) +{ + return srcpos_string_comment(pos, false, level); +} + void srcpos_verror(struct srcpos *pos, const char *prefix, const char *fmt, va_list va) { @@ -294,4 +412,9 @@ void srcpos_set_line(char *f, int l) { current_srcfile->name = f; current_srcfile->lineno = l; + + if (initial_cpp) { + initial_cpp = false; + set_initial_path(f); + } } diff --git a/scripts/dtc/srcpos.h b/scripts/dtc/srcpos.h index 9ded12a383..6326a952c4 100644 --- a/scripts/dtc/srcpos.h +++ b/scripts/dtc/srcpos.h @@ -74,6 +74,7 @@ struct srcpos { int last_line; int last_column; struct srcfile_state *file; + struct srcpos *next; }; #define YYLTYPE struct srcpos @@ -93,19 +94,18 @@ struct srcpos { YYRHSLOC(Rhs, 0).last_column; \ (Current).file = YYRHSLOC (Rhs, 0).file; \ } \ + (Current).next = NULL; \ } 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 struct srcpos *srcpos_extend(struct srcpos *new_srcpos, + struct srcpos *old_srcpos); extern char *srcpos_string(struct srcpos *pos); +extern char *srcpos_string_first(struct srcpos *pos, int level); +extern char *srcpos_string_last(struct srcpos *pos, int level); + extern void PRINTF(3, 0) srcpos_verror(struct srcpos *pos, const char *prefix, const char *fmt, va_list va); diff --git a/scripts/dtc/treesource.c b/scripts/dtc/treesource.c index f99544d723..1af36628b7 100644 --- a/scripts/dtc/treesource.c +++ b/scripts/dtc/treesource.c @@ -64,6 +64,10 @@ static bool isstring(char c) static void write_propval_string(FILE *f, const char *s, size_t len) { const char *end = s + len - 1; + + if (!len) + return; + assert(*end == '\0'); fprintf(f, "\""); @@ -118,29 +122,36 @@ static void write_propval_int(FILE *f, const char *p, size_t len, size_t width) for (; p < end; p += width) { switch (width) { case 1: - fprintf(f, " %02"PRIx8, *(const uint8_t*)p); + fprintf(f, "%02"PRIx8, *(const uint8_t*)p); break; case 2: - fprintf(f, " 0x%02"PRIx16, fdt16_to_cpu(*(const fdt16_t*)p)); + fprintf(f, "0x%02"PRIx16, fdt16_to_cpu(*(const fdt16_t*)p)); break; case 4: - fprintf(f, " 0x%02"PRIx32, fdt32_to_cpu(*(const fdt32_t*)p)); + fprintf(f, "0x%02"PRIx32, fdt32_to_cpu(*(const fdt32_t*)p)); break; case 8: - fprintf(f, " 0x%02"PRIx64, fdt64_to_cpu(*(const fdt64_t*)p)); + fprintf(f, "0x%02"PRIx64, fdt64_to_cpu(*(const fdt64_t*)p)); break; } + if (p + width < end) + fputc(' ', f); } } +static bool has_data_type_information(struct marker *m) +{ + return m->type >= TYPE_UINT8; +} + static struct marker *next_type_marker(struct marker *m) { - while (m && (m->type == LABEL || m->type == REF_PHANDLE || m->type == REF_PATH)) + while (m && !has_data_type_information(m)) m = m->next; return m; } -static size_t type_marker_length(struct marker *m) +size_t type_marker_length(struct marker *m) { struct marker *next = next_type_marker(m->next); @@ -157,10 +168,10 @@ static const char *delim_start[] = { [TYPE_STRING] = "", }; static const char *delim_end[] = { - [TYPE_UINT8] = " ]", - [TYPE_UINT16] = " >", - [TYPE_UINT32] = " >", - [TYPE_UINT64] = " >", + [TYPE_UINT8] = "]", + [TYPE_UINT16] = ">", + [TYPE_UINT32] = ">", + [TYPE_UINT64] = ">", [TYPE_STRING] = "", }; @@ -203,13 +214,22 @@ static void write_propval(FILE *f, struct property *prop) struct marker *m = prop->val.markers; struct marker dummy_marker; enum markertype emit_type = TYPE_NONE; + char *srcstr; if (len == 0) { - fprintf(f, ";\n"); + fprintf(f, ";"); + if (annotate) { + srcstr = srcpos_string_first(prop->srcpos, annotate); + if (srcstr) { + fprintf(f, " /* %s */", srcstr); + free(srcstr); + } + } + fprintf(f, "\n"); return; } - fprintf(f, " = "); + fprintf(f, " ="); if (!next_type_marker(m)) { /* data type information missing, need to guess */ @@ -220,32 +240,23 @@ static void write_propval(FILE *f, struct property *prop) m = &dummy_marker; } - struct marker *m_label = prop->val.markers; for_each_marker(m) { - size_t chunk_len; + size_t chunk_len = (m->next ? m->next->offset : len) - m->offset; + size_t data_len = type_marker_length(m) ? : len - m->offset; const char *p = &prop->val.val[m->offset]; - if (m->type < TYPE_UINT8) - continue; - - chunk_len = type_marker_length(m); - if (!chunk_len) - chunk_len = len - m->offset; - - if (emit_type != TYPE_NONE) - fprintf(f, "%s, ", delim_end[emit_type]); - emit_type = m->type; - - for_each_marker_of_type(m_label, LABEL) { - if (m_label->offset > m->offset) - break; - fprintf(f, "%s: ", m_label->ref); - } - - fprintf(f, "%s", delim_start[emit_type]); + if (has_data_type_information(m)) { + emit_type = m->type; + fprintf(f, " %s", delim_start[emit_type]); + } else if (m->type == LABEL) + fprintf(f, " %s:", m->ref); + else if (m->offset) + fputc(' ', f); - if (chunk_len <= 0) + if (emit_type == TYPE_NONE) { + assert(chunk_len == 0); continue; + } switch(emit_type) { case TYPE_UINT16: @@ -263,15 +274,23 @@ static void write_propval(FILE *f, struct property *prop) default: write_propval_int(f, p, chunk_len, 1); } - } - /* Wrap up any labels at the end of the value */ - for_each_marker_of_type(m_label, LABEL) { - assert (m_label->offset == len); - fprintf(f, " %s:", m_label->ref); + if (chunk_len == data_len) { + size_t pos = m->offset + chunk_len; + fprintf(f, pos == len ? "%s" : "%s,", + delim_end[emit_type] ? : ""); + emit_type = TYPE_NONE; + } } - - fprintf(f, "%s;\n", delim_end[emit_type] ? : ""); + fprintf(f, ";"); + if (annotate) { + srcstr = srcpos_string_first(prop->srcpos, annotate); + if (srcstr) { + fprintf(f, " /* %s */", srcstr); + free(srcstr); + } + } + fprintf(f, "\n"); } static void write_tree_source_node(FILE *f, struct node *tree, int level) @@ -279,14 +298,24 @@ static void write_tree_source_node(FILE *f, struct node *tree, int level) struct property *prop; struct node *child; struct label *l; + char *srcstr; 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); + fprintf(f, "%s {", tree->name); else - fprintf(f, "/ {\n"); + fprintf(f, "/ {"); + + if (annotate) { + srcstr = srcpos_string_first(tree->srcpos, annotate); + if (srcstr) { + fprintf(f, " /* %s */", srcstr); + free(srcstr); + } + } + fprintf(f, "\n"); for_each_property(tree, prop) { write_prefix(f, level+1); @@ -300,10 +329,17 @@ static void write_tree_source_node(FILE *f, struct node *tree, int level) write_tree_source_node(f, child, level+1); } write_prefix(f, level); - fprintf(f, "};\n"); + fprintf(f, "};"); + if (annotate) { + srcstr = srcpos_string_last(tree->srcpos, annotate); + if (srcstr) { + fprintf(f, " /* %s */", srcstr); + free(srcstr); + } + } + fprintf(f, "\n"); } - void dt_to_source(FILE *f, struct dt_info *dti) { struct reserve_info *re; diff --git a/scripts/dtc/util.c b/scripts/dtc/util.c index a69b7a1346..9c6fb5f286 100644 --- a/scripts/dtc/util.c +++ b/scripts/dtc/util.c @@ -46,36 +46,54 @@ char *xstrdup(const char *s) return d; } -/* based in part from (3) vsnprintf */ -int xasprintf(char **strp, const char *fmt, ...) +int xavsprintf_append(char **strp, const char *fmt, va_list ap) { - int n, size = 128; /* start with 128 bytes */ + int n, size = 0; /* start with 128 bytes */ char *p; - va_list ap; + va_list ap_copy; - /* initial pointer is NULL making the fist realloc to be malloc */ - p = NULL; - while (1) { - p = xrealloc(p, size); + p = *strp; + if (p) + size = strlen(p); - /* Try to print in the allocated space. */ - va_start(ap, fmt); - n = vsnprintf(p, size, fmt, ap); - va_end(ap); + va_copy(ap_copy, ap); + n = vsnprintf(NULL, 0, fmt, ap_copy) + 1; + va_end(ap_copy); + + p = xrealloc(p, size + n); + + n = vsnprintf(p + size, n, fmt, 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); } +int xasprintf_append(char **strp, const char *fmt, ...) +{ + int n; + va_list ap; + + va_start(ap, fmt); + n = xavsprintf_append(strp, fmt, ap); + va_end(ap); + + return n; +} + +int xasprintf(char **strp, const char *fmt, ...) +{ + int n; + va_list ap; + + *strp = NULL; + + va_start(ap, fmt); + n = xavsprintf_append(strp, fmt, ap); + va_end(ap); + + return n; +} + char *join_path(const char *path, const char *name) { int lenp = strlen(path); diff --git a/scripts/dtc/util.h b/scripts/dtc/util.h index f6cea82741..7658781a62 100644 --- a/scripts/dtc/util.h +++ b/scripts/dtc/util.h @@ -72,6 +72,8 @@ static inline void *xrealloc(void *p, size_t len) extern char *xstrdup(const char *s); extern int PRINTF(2, 3) xasprintf(char **strp, const char *fmt, ...); +extern int PRINTF(2, 3) xasprintf_append(char **strp, const char *fmt, ...); +extern int xavsprintf_append(char **strp, const char *fmt, va_list ap); extern char *join_path(const char *path, const char *name); /** diff --git a/scripts/dtc/version_gen.h b/scripts/dtc/version_gen.h index 2adf65b761..5c04ba938c 100644 --- a/scripts/dtc/version_gen.h +++ b/scripts/dtc/version_gen.h @@ -1 +1 @@ -#define DTC_VERSION "DTC 1.4.7" +#define DTC_VERSION "DTC 1.5.0" diff --git a/scripts/dtc/yamltree.c b/scripts/dtc/yamltree.c new file mode 100644 index 0000000000..a00285a5a9 --- /dev/null +++ b/scripts/dtc/yamltree.c @@ -0,0 +1,247 @@ +/* + * (C) Copyright Linaro, Ltd. 2018 + * (C) Copyright Arm Holdings. 2017 + * (C) Copyright David Gibson <dwg@au1.ibm.com>, 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 <stdlib.h> +#include <yaml.h> +#include "dtc.h" +#include "srcpos.h" + +char *yaml_error_name[] = { + [YAML_NO_ERROR] = "no error", + [YAML_MEMORY_ERROR] = "memory error", + [YAML_READER_ERROR] = "reader error", + [YAML_SCANNER_ERROR] = "scanner error", + [YAML_PARSER_ERROR] = "parser error", + [YAML_COMPOSER_ERROR] = "composer error", + [YAML_WRITER_ERROR] = "writer error", + [YAML_EMITTER_ERROR] = "emitter error", +}; + +#define yaml_emitter_emit_or_die(emitter, event) ( \ +{ \ + if (!yaml_emitter_emit(emitter, event)) \ + die("yaml '%s': %s in %s, line %i\n", \ + yaml_error_name[(emitter)->error], \ + (emitter)->problem, __func__, __LINE__); \ +}) + +static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers, char *data, int len, int width) +{ + yaml_event_t event; + void *tag; + int off, start_offset = markers->offset; + + switch(width) { + case 1: tag = "!u8"; break; + case 2: tag = "!u16"; break; + case 4: tag = "!u32"; break; + case 8: tag = "!u64"; break; + default: + die("Invalid width %i", width); + } + assert(len % width == 0); + + yaml_sequence_start_event_initialize(&event, NULL, + (yaml_char_t *)tag, width == 4, YAML_FLOW_SEQUENCE_STYLE); + yaml_emitter_emit_or_die(emitter, &event); + + for (off = 0; off < len; off += width) { + char buf[32]; + struct marker *m; + bool is_phandle = false; + + switch(width) { + case 1: + sprintf(buf, "0x%"PRIx8, *(uint8_t*)(data + off)); + break; + case 2: + sprintf(buf, "0x%"PRIx16, fdt16_to_cpu(*(fdt16_t*)(data + off))); + break; + case 4: + sprintf(buf, "0x%"PRIx32, fdt32_to_cpu(*(fdt32_t*)(data + off))); + m = markers; + is_phandle = false; + for_each_marker_of_type(m, REF_PHANDLE) { + if (m->offset == (start_offset + off)) { + is_phandle = true; + break; + } + } + break; + case 8: + sprintf(buf, "0x%"PRIx64, fdt64_to_cpu(*(fdt64_t*)(data + off))); + break; + } + + if (is_phandle) + yaml_scalar_event_initialize(&event, NULL, + (yaml_char_t*)"!phandle", (yaml_char_t *)buf, + strlen(buf), 0, 0, YAML_PLAIN_SCALAR_STYLE); + else + yaml_scalar_event_initialize(&event, NULL, + (yaml_char_t*)YAML_INT_TAG, (yaml_char_t *)buf, + strlen(buf), 1, 1, YAML_PLAIN_SCALAR_STYLE); + yaml_emitter_emit_or_die(emitter, &event); + } + + yaml_sequence_end_event_initialize(&event); + yaml_emitter_emit_or_die(emitter, &event); +} + +static void yaml_propval_string(yaml_emitter_t *emitter, char *str, int len) +{ + yaml_event_t event; + int i; + + assert(str[len-1] == '\0'); + + /* Make sure the entire string is in the lower 7-bit ascii range */ + for (i = 0; i < len; i++) + assert(isascii(str[i])); + + yaml_scalar_event_initialize(&event, NULL, + (yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)str, + len-1, 0, 1, YAML_DOUBLE_QUOTED_SCALAR_STYLE); + yaml_emitter_emit_or_die(emitter, &event); +} + +static void yaml_propval(yaml_emitter_t *emitter, struct property *prop) +{ + yaml_event_t event; + int len = prop->val.len; + struct marker *m = prop->val.markers; + + /* Emit the property name */ + yaml_scalar_event_initialize(&event, NULL, + (yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)prop->name, + strlen(prop->name), 1, 1, YAML_PLAIN_SCALAR_STYLE); + yaml_emitter_emit_or_die(emitter, &event); + + /* Boolean properties are easiest to deal with. Length is zero, so just emit 'true' */ + if (len == 0) { + yaml_scalar_event_initialize(&event, NULL, + (yaml_char_t *)YAML_BOOL_TAG, + (yaml_char_t*)"true", + strlen("true"), 1, 0, YAML_PLAIN_SCALAR_STYLE); + yaml_emitter_emit_or_die(emitter, &event); + return; + } + + if (!m) + die("No markers present in property '%s' value\n", prop->name); + + yaml_sequence_start_event_initialize(&event, NULL, + (yaml_char_t *)YAML_SEQ_TAG, 1, YAML_FLOW_SEQUENCE_STYLE); + yaml_emitter_emit_or_die(emitter, &event); + + for_each_marker(m) { + int chunk_len; + char *data = &prop->val.val[m->offset]; + + if (m->type < TYPE_UINT8) + continue; + + chunk_len = type_marker_length(m) ? : len; + assert(chunk_len > 0); + len -= chunk_len; + + switch(m->type) { + case TYPE_UINT16: + yaml_propval_int(emitter, m, data, chunk_len, 2); + break; + case TYPE_UINT32: + yaml_propval_int(emitter, m, data, chunk_len, 4); + break; + case TYPE_UINT64: + yaml_propval_int(emitter, m, data, chunk_len, 8); + break; + case TYPE_STRING: + yaml_propval_string(emitter, data, chunk_len); + break; + default: + yaml_propval_int(emitter, m, data, chunk_len, 1); + break; + } + } + + yaml_sequence_end_event_initialize(&event); + yaml_emitter_emit_or_die(emitter, &event); +} + + +static void yaml_tree(struct node *tree, yaml_emitter_t *emitter) +{ + struct property *prop; + struct node *child; + yaml_event_t event; + + if (tree->deleted) + return; + + yaml_mapping_start_event_initialize(&event, NULL, + (yaml_char_t *)YAML_MAP_TAG, 1, YAML_ANY_MAPPING_STYLE); + yaml_emitter_emit_or_die(emitter, &event); + + for_each_property(tree, prop) + yaml_propval(emitter, prop); + + /* Loop over all the children, emitting them into the map */ + for_each_child(tree, child) { + yaml_scalar_event_initialize(&event, NULL, + (yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)child->name, + strlen(child->name), 1, 0, YAML_PLAIN_SCALAR_STYLE); + yaml_emitter_emit_or_die(emitter, &event); + yaml_tree(child, emitter); + } + + yaml_mapping_end_event_initialize(&event); + yaml_emitter_emit_or_die(emitter, &event); +} + +void dt_to_yaml(FILE *f, struct dt_info *dti) +{ + yaml_emitter_t emitter; + yaml_event_t event; + + yaml_emitter_initialize(&emitter); + yaml_emitter_set_output_file(&emitter, f); + yaml_stream_start_event_initialize(&event, YAML_UTF8_ENCODING); + yaml_emitter_emit_or_die(&emitter, &event); + + yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0); + yaml_emitter_emit_or_die(&emitter, &event); + + yaml_sequence_start_event_initialize(&event, NULL, (yaml_char_t *)YAML_SEQ_TAG, 1, YAML_ANY_SEQUENCE_STYLE); + yaml_emitter_emit_or_die(&emitter, &event); + + yaml_tree(dti->dt, &emitter); + + yaml_sequence_end_event_initialize(&event); + yaml_emitter_emit_or_die(&emitter, &event); + + yaml_document_end_event_initialize(&event, 0); + yaml_emitter_emit_or_die(&emitter, &event); + + yaml_stream_end_event_initialize(&event); + yaml_emitter_emit_or_die(&emitter, &event); + + yaml_emitter_delete(&emitter); +} -- 2.20.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/8] scripts/dtc: Update to upstream version v1.5.0 2019-08-19 13:38 ` [PATCH 2/8] scripts/dtc: Update to upstream version v1.5.0 Sascha Hauer @ 2019-08-19 13:52 ` Roland Hieber 2019-08-19 13:56 ` Sascha Hauer 0 siblings, 1 reply; 18+ messages in thread From: Roland Hieber @ 2019-08-19 13:52 UTC (permalink / raw) To: Sascha Hauer; +Cc: Barebox List On Mon, Aug 19, 2019 at 03:38:41PM +0200, Sascha Hauer wrote: > This adds the following commits from upstream: > > d37f6b2 Bump version to v1.5.0 > a4b1a30 pylibfdt:tests: Extend the way how to find a Python module I'm sorry if this will probably mean a lot of work for you, but sadly those SHA1 hashes are too short to be unique :-( linux (master) $ git show d37f6b2 fatal: ambiguous argument 'd37f6b2': unknown revision or path not in the working tree. Use '--' to separate paths from revisions, like this: 'git <command> [<revision>...] -- [<file>...]' linux (master) $ git show a4b1a30 fatal: ambiguous argument 'a4b1a30': unknown revision or path not in the working tree. Use '--' to separate paths from revisions, like this: 'git <command> [<revision>...] -- [<file>...]' - Roland > 625dd8a pylibfdt: Change how passing tests are recognized > 3646316 pylibfdt: Test fdt.setprop take bytes on Python 3, add error handling > cb0f454 pylibfdt: check_err accepts only integer as a first argument. > 4b68c6b pylibfdt: Proper handling of bytes/unicode strings and octal literals > 78e113e Use PRIxPTR for printing uintptr_t values > ea7a8f6 libfdt: Fix FDT_ERR_NOTFOUND typos in documentation > 5aafd7c libfdt: Fix fdt_getprop_by_offset() parameter name in documentation > 7cbc550 checks: Add unit address check if node is enabled > f267e67 checks: Fix crash with multiple source annotations > 3616b9a checks: Use source position information for check failures > 2bdbd07 checks: Make each message output atomic > a1eff70 util: Add xa{v}sprintf_append functions > 82a52ce libfdt: Add a test for fdt_getprop_by_offset() > 607b858 PEP8 / Flake8 cleanups for setup.py > f9c0a42 Remove broken objdir / srcdir support > 5182b5e pylibfdt: Use common PREFIX variable > d45bf1f Refine make tests_clean target > 99284c4 Refine pylibfdt_clean target > a4629cf Refine libfdt_clean target > 08380fc tests: Use modern octal literals for Python > 8113c00 pylibfdt: Allow switch to Python 3 via environment variable PYTHON > 11738cf libfdt: Don't use memcpy to handle unaligned reads on ARM > 86a288a checks: Restructure check_msg to decrease indentation > 5667e7e annotations: add the annotation functionality > 8e20ccf annotations: add positions > ca930e2 tests: Don't lose errors from make checkm > 43366bb tests: Property count valgrind errors in wrapped tests > 5062516 srcpos: Remove srcpos_empty > a3143fa Revert "annotations: add positions" > 403cc79 checks: Update SPI bus check for 'spi-slave' > baa1d2c annotations: add positions > ff2ad38 Merge remote-tracking branch 'origin/pr/18' > aa7254d libfdt: return correct value if #size-cells property is not present > 49903ae use ptrdiff_t modifier for printing pointer differences > da2b691 treesource: Fix dts output for phandles in middle of a sequence of ints > 8f8b77a tests: Wrap check_align() calls with base_run_test() > 522d81d Fix dts output with a REF_PATH marker > e45198c Added test cases for target references > 0fcffda Merge nodes with local target label references > 1e4a092 pylibfdt: Don't have setup.py depend on where it's invoked from > ca399b1 pylibfdt: Eliminate run_setup make function > 98972f1 pylibfdt: Improved version extraction > 7ba2be6 pylibfdt: Don't silence setup.py when V=1 > 7691f9d pylibfdt: Make SETUP make variable > 855b996 pylibfdt: Simpler CFLAGS handling > 47cafbe pylibfdt: Link extension module with libfdt rather than rebuilding > dd695d6 pylibfdt: Correctly set build output directory > 5932752 pylibfdt: We don't need include files from the base directory > e84742a checks: fix simple-bus compatible matching > 8c59a97 Fix missing labels when emitting dts format > d448f9a Revert dts output formatting changes of spaces around brackets > c86da84 Add support for YAML encoded output > 361b5e7 Make type_marker_length helper public > bfbfab0 pylibfdt: Add a means to add and delete notes > 9005f41 pylibfdt: Allow delprop() to return errors > b94c056 Make valgrind optional > fd06c54 tests: Better testing of dtc -I fs mode > c3f50c9 tests: Allow dtbs_equal_unordered to ignore mem reserves > 0ac9fde dtc: trivial '-I fs -O dts' test > 0fd1c8c pylibfdt: fdt_get_mem_rsv returns 2 uint64_t values > 04853ca pylibfdt: Don't incorrectly / unnecessarily override uint64_t typemap > 9619c86 Kill bogus TYPE_BLOB marker type > ac68ff9 parser: add TYPE_STRING marker to path references > 90a190e checks: add SPI bus checks > 53a1bd5 checks: add I2C bus checks > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> > --- > scripts/dtc/Makefile | 49 +-- > scripts/dtc/Makefile.dtc | 4 + > scripts/dtc/checks.c | 255 +++++++++++++- > scripts/dtc/data.c | 2 +- > scripts/dtc/dtc-lexer.l | 4 +- > scripts/dtc/dtc-parser.y | 53 ++- > scripts/dtc/dtc.c | 22 +- > scripts/dtc/dtc.h | 18 +- > scripts/dtc/fdtget.c | 383 --------------------- > scripts/dtc/flattree.c | 4 +- > scripts/dtc/fstree.c | 5 +- > scripts/dtc/libfdt/Makefile.libfdt | 15 + > scripts/dtc/{ => libfdt}/fdt.c | 0 > scripts/dtc/{ => libfdt}/fdt.h | 0 > scripts/dtc/{ => libfdt}/fdt_addresses.c | 16 +- > scripts/dtc/{ => libfdt}/fdt_empty_tree.c | 0 > scripts/dtc/{ => libfdt}/fdt_overlay.c | 0 > scripts/dtc/{ => libfdt}/fdt_ro.c | 0 > scripts/dtc/{ => libfdt}/fdt_rw.c | 0 > scripts/dtc/{ => libfdt}/fdt_strerror.c | 0 > scripts/dtc/{ => libfdt}/fdt_sw.c | 0 > scripts/dtc/{ => libfdt}/fdt_wip.c | 0 > scripts/dtc/{ => libfdt}/libfdt.h | 30 +- > scripts/dtc/{ => libfdt}/libfdt_env.h | 0 > scripts/dtc/{ => libfdt}/libfdt_internal.h | 0 > scripts/dtc/livetree.c | 33 +- > scripts/dtc/srcpos.c | 153 +++++++- > scripts/dtc/srcpos.h | 14 +- > scripts/dtc/treesource.c | 124 ++++--- > scripts/dtc/util.c | 60 ++-- > scripts/dtc/util.h | 2 + > scripts/dtc/version_gen.h | 2 +- > scripts/dtc/yamltree.c | 247 +++++++++++++ > 33 files changed, 926 insertions(+), 569 deletions(-) > delete mode 100644 scripts/dtc/fdtget.c > create mode 100644 scripts/dtc/libfdt/Makefile.libfdt > rename scripts/dtc/{ => libfdt}/fdt.c (100%) > rename scripts/dtc/{ => libfdt}/fdt.h (100%) > rename scripts/dtc/{ => libfdt}/fdt_addresses.c (92%) > rename scripts/dtc/{ => libfdt}/fdt_empty_tree.c (100%) > rename scripts/dtc/{ => libfdt}/fdt_overlay.c (100%) > rename scripts/dtc/{ => libfdt}/fdt_ro.c (100%) > rename scripts/dtc/{ => libfdt}/fdt_rw.c (100%) > rename scripts/dtc/{ => libfdt}/fdt_strerror.c (100%) > rename scripts/dtc/{ => libfdt}/fdt_sw.c (100%) > rename scripts/dtc/{ => libfdt}/fdt_wip.c (100%) > rename scripts/dtc/{ => libfdt}/libfdt.h (99%) > rename scripts/dtc/{ => libfdt}/libfdt_env.h (100%) > rename scripts/dtc/{ => libfdt}/libfdt_internal.h (100%) > create mode 100644 scripts/dtc/yamltree.c > > diff --git a/scripts/dtc/Makefile b/scripts/dtc/Makefile > index 1d63476ecc..5f227d8d39 100644 > --- a/scripts/dtc/Makefile > +++ b/scripts/dtc/Makefile > @@ -1,43 +1,30 @@ > +# SPDX-License-Identifier: GPL-2.0 > # scripts/dtc makefile > > -hostprogs-y := dtc fdtget > +hostprogs-$(CONFIG_DTC) := dtc > always := $(hostprogs-y) > > dtc-objs := dtc.o flattree.o fstree.o data.o livetree.o treesource.o \ > srcpos.o checks.o util.o > dtc-objs += dtc-lexer.lex.o dtc-parser.tab.o > > -libfdt-objs = fdt.o fdt_ro.o fdt_strerror.o fdt_wip.o fdt_overlay.o > -libfdt-objs += fdt_empty_tree.o fdt_rw.o fdt_sw.o > - > -fdtget-objs += fdtget.o $(libfdt-objs) util.o > - > # Source files need to get at the userspace version of libfdt_env.h to compile > - > -HOSTCFLAGS_DTC := -I$(src) > - > -HOSTCFLAGS_checks.o := $(HOSTCFLAGS_DTC) > -HOSTCFLAGS_data.o := $(HOSTCFLAGS_DTC) > -HOSTCFLAGS_dtc.o := $(HOSTCFLAGS_DTC) > -HOSTCFLAGS_flattree.o := $(HOSTCFLAGS_DTC) > -HOSTCFLAGS_fstree.o := $(HOSTCFLAGS_DTC) > -HOSTCFLAGS_livetree.o := $(HOSTCFLAGS_DTC) > -HOSTCFLAGS_srcpos.o := $(HOSTCFLAGS_DTC) > -HOSTCFLAGS_treesource.o := $(HOSTCFLAGS_DTC) > -HOSTCFLAGS_util.o := $(HOSTCFLAGS_DTC) > -HOSTCFLAGS_fdtget.o := $(HOSTCFLAGS_DTC) > - > -HOSTCFLAGS_fdt.o := $(HOSTCFLAGS_DTC) > -HOSTCFLAGS_fdt_ro.o := $(HOSTCFLAGS_DTC) > -HOSTCFLAGS_fdt_strerror.o := $(HOSTCFLAGS_DTC) > -HOSTCFLAGS_fdt_wip.o := $(HOSTCFLAGS_DTC) > -HOSTCFLAGS_fdt_empty_tree.o := $(HOSTCFLAGS_DTC) > -HOSTCFLAGS_fdt_rw.o := $(HOSTCFLAGS_DTC) > -HOSTCFLAGS_fdt_sw.o := $(HOSTCFLAGS_DTC) > -HOSTCFLAGS_fdt_overlay.o := $(HOSTCFLAGS_DTC) > - > -HOSTCFLAGS_dtc-lexer.lex.o := $(HOSTCFLAGS_DTC) > -HOSTCFLAGS_dtc-parser.tab.o := $(HOSTCFLAGS_DTC) > +HOST_EXTRACFLAGS := -I$(src)/libfdt > + > +ifeq ($(wildcard /usr/include/yaml.h),) > +ifneq ($(CHECK_DTBS),) > +$(error dtc needs libyaml for DT schema validation support. \ > + Install the necessary libyaml development package.) > +endif > +HOST_EXTRACFLAGS += -DNO_YAML > +else > +dtc-objs += yamltree.o > +HOSTLDLIBS_dtc := -lyaml > +endif > + > +# Generated files need one more search path to include headers in source tree > +HOSTCFLAGS_dtc-lexer.lex.o := -I$(src) > +HOSTCFLAGS_dtc-parser.tab.o := -I$(src) > > # dependencies on generated files need to be listed explicitly > $(obj)/dtc-lexer.lex.o: $(obj)/dtc-parser.tab.h > diff --git a/scripts/dtc/Makefile.dtc b/scripts/dtc/Makefile.dtc > index bece49b355..d4375630a7 100644 > --- a/scripts/dtc/Makefile.dtc > +++ b/scripts/dtc/Makefile.dtc > @@ -14,5 +14,9 @@ DTC_SRCS = \ > treesource.c \ > util.c > > +ifneq ($(NO_YAML),1) > +DTC_SRCS += yamltree.c > +endif > + > DTC_GEN_SRCS = dtc-lexer.lex.c dtc-parser.tab.c > DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o) > diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c > index a2cc1036c9..c0ed45e1c3 100644 > --- a/scripts/dtc/checks.c > +++ b/scripts/dtc/checks.c > @@ -19,6 +19,7 @@ > */ > > #include "dtc.h" > +#include "srcpos.h" > > #ifdef TRACE_CHECKS > #define TRACE(c, ...) \ > @@ -78,23 +79,56 @@ static inline void PRINTF(5, 6) check_msg(struct check *c, struct dt_info *dti, > const char *fmt, ...) > { > va_list ap; > - va_start(ap, fmt); > + char *str = NULL; > + struct srcpos *pos = NULL; > + char *file_str; > + > + if (!(c->warn && (quiet < 1)) && !(c->error && (quiet < 2))) > + return; > + > + if (prop && prop->srcpos) > + pos = prop->srcpos; > + else if (node && node->srcpos) > + pos = node->srcpos; > + > + if (pos) { > + file_str = srcpos_string(pos); > + xasprintf(&str, "%s", file_str); > + free(file_str); > + } else if (streq(dti->outname, "-")) { > + xasprintf(&str, "<stdout>"); > + } else { > + xasprintf(&str, "%s", dti->outname); > + } > > - if ((c->warn && (quiet < 1)) > - || (c->error && (quiet < 2))) { > - fprintf(stderr, "%s: %s (%s): ", > - strcmp(dti->outname, "-") ? dti->outname : "<stdout>", > + xasprintf_append(&str, ": %s (%s): ", > (c->error) ? "ERROR" : "Warning", c->name); > - if (node) { > - fprintf(stderr, "%s", node->fullpath); > - if (prop) > - fprintf(stderr, ":%s", prop->name); > - fputs(": ", stderr); > - } > - vfprintf(stderr, fmt, ap); > - fprintf(stderr, "\n"); > + > + if (node) { > + if (prop) > + xasprintf_append(&str, "%s:%s: ", node->fullpath, prop->name); > + else > + xasprintf_append(&str, "%s: ", node->fullpath); > } > + > + va_start(ap, fmt); > + xavsprintf_append(&str, fmt, ap); > va_end(ap); > + > + xasprintf_append(&str, "\n"); > + > + if (!prop && pos) { > + pos = node->srcpos; > + while (pos->next) { > + pos = pos->next; > + > + file_str = srcpos_string(pos); > + xasprintf_append(&str, " also defined at %s\n", file_str); > + free(file_str); > + } > + } > + > + fputs(str, stderr); > } > > #define FAIL(c, dti, node, ...) \ > @@ -910,7 +944,7 @@ static bool node_is_compatible(struct node *node, const char *compat) > > for (str = prop->val.val, end = str + prop->val.len; str < end; > str += strnlen(str, end - str) + 1) { > - if (strprefixeq(str, end - str, compat)) > + if (streq(str, compat)) > return true; > } > return false; > @@ -921,7 +955,8 @@ static void check_simple_bus_bridge(struct check *c, struct dt_info *dti, struct > if (node_is_compatible(node, "simple-bus")) > node->bus = &simple_bus; > } > -WARNING(simple_bus_bridge, check_simple_bus_bridge, NULL, &addr_size_cells); > +WARNING(simple_bus_bridge, check_simple_bus_bridge, NULL, > + &addr_size_cells, &compatible_is_string_list); > > static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct node *node) > { > @@ -962,6 +997,149 @@ static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct no > } > WARNING(simple_bus_reg, check_simple_bus_reg, NULL, ®_format, &simple_bus_bridge); > > +static const struct bus_type i2c_bus = { > + .name = "i2c-bus", > +}; > + > +static void check_i2c_bus_bridge(struct check *c, struct dt_info *dti, struct node *node) > +{ > + if (strprefixeq(node->name, node->basenamelen, "i2c-bus") || > + strprefixeq(node->name, node->basenamelen, "i2c-arb")) { > + node->bus = &i2c_bus; > + } else if (strprefixeq(node->name, node->basenamelen, "i2c")) { > + struct node *child; > + for_each_child(node, child) { > + if (strprefixeq(child->name, node->basenamelen, "i2c-bus")) > + return; > + } > + node->bus = &i2c_bus; > + } else > + return; > + > + if (!node->children) > + return; > + > + if (node_addr_cells(node) != 1) > + FAIL(c, dti, node, "incorrect #address-cells for I2C bus"); > + if (node_size_cells(node) != 0) > + FAIL(c, dti, node, "incorrect #size-cells for I2C bus"); > + > +} > +WARNING(i2c_bus_bridge, check_i2c_bus_bridge, NULL, &addr_size_cells); > + > +static void check_i2c_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]; > + uint32_t reg = 0; > + int len; > + cell_t *cells = NULL; > + > + if (!node->parent || (node->parent->bus != &i2c_bus)) > + return; > + > + prop = get_property(node, "reg"); > + if (prop) > + cells = (cell_t *)prop->val.val; > + > + if (!cells) { > + FAIL(c, dti, node, "missing or empty reg property"); > + return; > + } > + > + reg = fdt32_to_cpu(*cells); > + snprintf(unit_addr, sizeof(unit_addr), "%x", reg); > + if (!streq(unitname, unit_addr)) > + FAIL(c, dti, node, "I2C bus unit address format error, expected \"%s\"", > + unit_addr); > + > + for (len = prop->val.len; len > 0; len -= 4) { > + reg = fdt32_to_cpu(*(cells++)); > + if (reg > 0x3ff) > + FAIL_PROP(c, dti, node, prop, "I2C address must be less than 10-bits, got \"0x%x\"", > + reg); > + > + } > +} > +WARNING(i2c_bus_reg, check_i2c_bus_reg, NULL, ®_format, &i2c_bus_bridge); > + > +static const struct bus_type spi_bus = { > + .name = "spi-bus", > +}; > + > +static void check_spi_bus_bridge(struct check *c, struct dt_info *dti, struct node *node) > +{ > + int spi_addr_cells = 1; > + > + if (strprefixeq(node->name, node->basenamelen, "spi")) { > + node->bus = &spi_bus; > + } else { > + /* Try to detect SPI buses which don't have proper node name */ > + struct node *child; > + > + if (node_addr_cells(node) != 1 || node_size_cells(node) != 0) > + return; > + > + for_each_child(node, child) { > + struct property *prop; > + for_each_property(child, prop) { > + if (strprefixeq(prop->name, 4, "spi-")) { > + node->bus = &spi_bus; > + break; > + } > + } > + if (node->bus == &spi_bus) > + break; > + } > + > + if (node->bus == &spi_bus && get_property(node, "reg")) > + FAIL(c, dti, node, "node name for SPI buses should be 'spi'"); > + } > + if (node->bus != &spi_bus || !node->children) > + return; > + > + if (get_property(node, "spi-slave")) > + spi_addr_cells = 0; > + if (node_addr_cells(node) != spi_addr_cells) > + FAIL(c, dti, node, "incorrect #address-cells for SPI bus"); > + if (node_size_cells(node) != 0) > + FAIL(c, dti, node, "incorrect #size-cells for SPI bus"); > + > +} > +WARNING(spi_bus_bridge, check_spi_bus_bridge, NULL, &addr_size_cells); > + > +static void check_spi_bus_reg(struct check *c, struct dt_info *dti, struct node *node) > +{ > + struct property *prop; > + const char *unitname = get_unitname(node); > + char unit_addr[9]; > + uint32_t reg = 0; > + cell_t *cells = NULL; > + > + if (!node->parent || (node->parent->bus != &spi_bus)) > + return; > + > + if (get_property(node->parent, "spi-slave")) > + return; > + > + prop = get_property(node, "reg"); > + if (prop) > + cells = (cell_t *)prop->val.val; > + > + if (!cells) { > + FAIL(c, dti, node, "missing or empty reg property"); > + return; > + } > + > + reg = fdt32_to_cpu(*cells); > + snprintf(unit_addr, sizeof(unit_addr), "%x", reg); > + if (!streq(unitname, unit_addr)) > + FAIL(c, dti, node, "SPI bus unit address format error, expected \"%s\"", > + unit_addr); > +} > +WARNING(spi_bus_reg, check_spi_bus_reg, NULL, ®_format, &spi_bus_bridge); > + > static void check_unit_address_format(struct check *c, struct dt_info *dti, > struct node *node) > { > @@ -1034,8 +1212,24 @@ static void check_avoid_unnecessary_addr_size(struct check *c, struct dt_info *d > } > WARNING(avoid_unnecessary_addr_size, check_avoid_unnecessary_addr_size, NULL, &avoid_default_addr_size); > > -static void check_unique_unit_address(struct check *c, struct dt_info *dti, > - struct node *node) > +static bool node_is_disabled(struct node *node) > +{ > + struct property *prop; > + > + prop = get_property(node, "status"); > + if (prop) { > + char *str = prop->val.val; > + if (streq("disabled", str)) > + return true; > + } > + > + return false; > +} > + > +static void check_unique_unit_address_common(struct check *c, > + struct dt_info *dti, > + struct node *node, > + bool disable_check) > { > struct node *childa; > > @@ -1052,18 +1246,38 @@ static void check_unique_unit_address(struct check *c, struct dt_info *dti, > if (!strlen(addr_a)) > continue; > > + if (disable_check && node_is_disabled(childa)) > + continue; > + > for_each_child(node, childb) { > const char *addr_b = get_unitname(childb); > if (childa == childb) > break; > > + if (disable_check && node_is_disabled(childb)) > + continue; > + > if (streq(addr_a, addr_b)) > FAIL(c, dti, childb, "duplicate unit-address (also used in node %s)", childa->fullpath); > } > } > } > + > +static void check_unique_unit_address(struct check *c, struct dt_info *dti, > + struct node *node) > +{ > + check_unique_unit_address_common(c, dti, node, false); > +} > WARNING(unique_unit_address, check_unique_unit_address, NULL, &avoid_default_addr_size); > > +static void check_unique_unit_address_if_enabled(struct check *c, struct dt_info *dti, > + struct node *node) > +{ > + check_unique_unit_address_common(c, dti, node, true); > +} > +CHECK_ENTRY(unique_unit_address_if_enabled, check_unique_unit_address_if_enabled, > + NULL, false, false, &avoid_default_addr_size); > + > static void check_obsolete_chosen_interrupt_controller(struct check *c, > struct dt_info *dti, > struct node *node) > @@ -1582,9 +1796,16 @@ static struct check *check_table[] = { > &simple_bus_bridge, > &simple_bus_reg, > > + &i2c_bus_bridge, > + &i2c_bus_reg, > + > + &spi_bus_bridge, > + &spi_bus_reg, > + > &avoid_default_addr_size, > &avoid_unnecessary_addr_size, > &unique_unit_address, > + &unique_unit_address_if_enabled, > &obsolete_chosen_interrupt_controller, > &chosen_node_is_root, &chosen_node_bootargs, &chosen_node_stdout_path, > > diff --git a/scripts/dtc/data.c b/scripts/dtc/data.c > index accdfaef66..4a204145cc 100644 > --- a/scripts/dtc/data.c > +++ b/scripts/dtc/data.c > @@ -95,7 +95,7 @@ struct data data_copy_file(FILE *f, size_t maxlen) > { > struct data d = empty_data; > > - d = data_add_marker(d, TYPE_BLOB, NULL); > + d = data_add_marker(d, TYPE_NONE, NULL); > while (!feof(f) && (d.len < maxlen)) { > size_t chunksize, ret; > > diff --git a/scripts/dtc/dtc-lexer.l b/scripts/dtc/dtc-lexer.l > index 615b7ec658..06c0409024 100644 > --- a/scripts/dtc/dtc-lexer.l > +++ b/scripts/dtc/dtc-lexer.l > @@ -213,14 +213,14 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...); > <*>\&{LABEL} { /* label reference */ > DPRINT("Ref: %s\n", yytext+1); > yylval.labelref = xstrdup(yytext+1); > - return DT_REF; > + return DT_LABEL_REF; > } > > <*>"&{/"{PATHCHAR}*\} { /* new-style path reference */ > yytext[yyleng-1] = '\0'; > DPRINT("Ref: %s\n", yytext+2); > yylval.labelref = xstrdup(yytext+2); > - return DT_REF; > + return DT_PATH_REF; > } > > <BYTESTRING>[0-9a-fA-F]{2} { > diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y > index 815481a9bb..2ec981e861 100644 > --- a/scripts/dtc/dtc-parser.y > +++ b/scripts/dtc/dtc-parser.y > @@ -70,7 +70,8 @@ extern bool treesource_error; > %token <byte> DT_BYTE > %token <data> DT_STRING > %token <labelref> DT_LABEL > -%token <labelref> DT_REF > +%token <labelref> DT_LABEL_REF > +%token <labelref> DT_PATH_REF > %token DT_INCBIN > > %type <data> propdata > @@ -83,6 +84,7 @@ extern bool treesource_error; > %type <data> bytestring > %type <prop> propdef > %type <proplist> proplist > +%type <labelref> dt_ref > > %type <node> devicetree > %type <node> nodedef > @@ -158,6 +160,8 @@ memreserve: > } > ; > > +dt_ref: DT_LABEL_REF | DT_PATH_REF; > + > devicetree: > '/' nodedef > { > @@ -167,7 +171,7 @@ devicetree: > { > $$ = merge_nodes($1, $3); > } > - | DT_REF nodedef > + | dt_ref nodedef > { > /* > * We rely on the rule being always: > @@ -176,9 +180,12 @@ devicetree: > */ > if (!($<flags>-1 & DTSF_PLUGIN)) > ERROR(&@2, "Label or path %s not found", $1); > - $$ = add_orphan_node(name_node(build_node(NULL, NULL), ""), $2, $1); > + $$ = add_orphan_node( > + name_node(build_node(NULL, NULL, NULL), > + ""), > + $2, $1); > } > - | devicetree DT_LABEL DT_REF nodedef > + | devicetree DT_LABEL dt_ref nodedef > { > struct node *target = get_node_by_ref($1, $3); > > @@ -189,7 +196,7 @@ devicetree: > ERROR(&@3, "Label or path %s not found", $3); > $$ = $1; > } > - | devicetree DT_REF nodedef > + | devicetree DT_PATH_REF nodedef > { > /* > * We rely on the rule being always: > @@ -208,7 +215,26 @@ devicetree: > } > $$ = $1; > } > - | devicetree DT_DEL_NODE DT_REF ';' > + | devicetree DT_LABEL_REF nodedef > + { > + struct node *target = get_node_by_ref($1, $2); > + > + if (target) { > + merge_nodes(target, $3); > + } else { > + /* > + * We rely on the rule being always: > + * versioninfo plugindecl memreserves devicetree > + * so $-1 is what we want (plugindecl) > + */ > + if ($<flags>-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); > > @@ -220,7 +246,7 @@ devicetree: > > $$ = $1; > } > - | devicetree DT_OMIT_NO_REF DT_REF ';' > + | devicetree DT_OMIT_NO_REF dt_ref ';' > { > struct node *target = get_node_by_ref($1, $3); > > @@ -237,7 +263,7 @@ devicetree: > nodedef: > '{' proplist subnodes '}' ';' > { > - $$ = build_node($2, $3); > + $$ = build_node($2, $3, &@$); > } > ; > > @@ -255,11 +281,11 @@ proplist: > propdef: > DT_PROPNODENAME '=' propdata ';' > { > - $$ = build_property($1, $3); > + $$ = build_property($1, $3, &@$); > } > | DT_PROPNODENAME ';' > { > - $$ = build_property($1, empty_data); > + $$ = build_property($1, empty_data, &@$); > } > | DT_DEL_PROP DT_PROPNODENAME ';' > { > @@ -285,8 +311,9 @@ propdata: > { > $$ = data_merge($1, $3); > } > - | propdataprefix DT_REF > + | propdataprefix dt_ref > { > + $1 = data_add_marker($1, TYPE_STRING, $2); > $$ = data_add_marker($1, REF_PATH, $2); > } > | propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')' > @@ -382,7 +409,7 @@ arrayprefix: > > $$.data = data_append_integer($1.data, $2, $1.bits); > } > - | arrayprefix DT_REF > + | arrayprefix dt_ref > { > uint64_t val = ~0ULL >> (64 - $1.bits); > > @@ -539,7 +566,7 @@ subnode: > } > | DT_DEL_NODE DT_PROPNODENAME ';' > { > - $$ = name_node(build_node_delete(), $2); > + $$ = name_node(build_node_delete(&@$), $2); > } > | DT_OMIT_NO_REF subnode > { > diff --git a/scripts/dtc/dtc.c b/scripts/dtc/dtc.c > index c36994e6ea..695e1f789f 100644 > --- a/scripts/dtc/dtc.c > +++ b/scripts/dtc/dtc.c > @@ -35,6 +35,8 @@ 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 */ > +int annotate; /* Level of annotation: 1 for input source location > + >1 for full input source location. */ > > static int is_power_of_2(int x) > { > @@ -60,7 +62,7 @@ static void fill_fullpaths(struct node *tree, const char *prefix) > > /* Usage related data. */ > static const char usage_synopsis[] = "dtc [options] <input file>"; > -static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@Ahv"; > +static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@AThv"; > static struct option const usage_long_opts[] = { > {"quiet", no_argument, NULL, 'q'}, > {"in-format", a_argument, NULL, 'I'}, > @@ -81,6 +83,7 @@ static struct option const usage_long_opts[] = { > {"error", a_argument, NULL, 'E'}, > {"symbols", no_argument, NULL, '@'}, > {"auto-alias", no_argument, NULL, 'A'}, > + {"annotate", no_argument, NULL, 'T'}, > {"help", no_argument, NULL, 'h'}, > {"version", no_argument, NULL, 'v'}, > {NULL, no_argument, NULL, 0x0}, > @@ -95,6 +98,9 @@ static const char * const usage_opts_help[] = { > "\n\tOutput formats are:\n" > "\t\tdts - device tree source text\n" > "\t\tdtb - device tree blob\n" > +#ifndef NO_YAML > + "\t\tyaml - device tree encoded as YAML\n" > +#endif > "\t\tasm - assembler source", > "\n\tBlob version to produce, defaults to "stringify(DEFAULT_FDT_VERSION)" (for dtb and asm output)", > "\n\tOutput dependency file", > @@ -114,6 +120,7 @@ static const char * const usage_opts_help[] = { > "\n\tEnable/disable errors (prefix with \"no-\")", > "\n\tEnable generation of symbols", > "\n\tEnable auto-alias of labels", > + "\n\tAnnotate output .dts with input source file and line (-T -T for more details)", > "\n\tPrint this help and exit", > "\n\tPrint version and exit", > NULL, > @@ -128,6 +135,8 @@ static const char *guess_type_by_name(const char *fname, const char *fallback) > return fallback; > if (!strcasecmp(s, ".dts")) > return "dts"; > + if (!strcasecmp(s, ".yaml")) > + return "yaml"; > if (!strcasecmp(s, ".dtb")) > return "dtb"; > return fallback; > @@ -259,6 +268,9 @@ int main(int argc, char *argv[]) > case 'A': > auto_label_aliases = 1; > break; > + case 'T': > + annotate++; > + break; > > case 'h': > usage(NULL); > @@ -297,6 +309,8 @@ int main(int argc, char *argv[]) > outform = "dts"; > } > } > + if (annotate && (!streq(inform, "dts") || !streq(outform, "dts"))) > + die("--annotate requires -I dts -O dts\n"); > if (streq(inform, "dts")) > dti = dt_from_source(arg); > else if (streq(inform, "fs")) > @@ -350,6 +364,12 @@ int main(int argc, char *argv[]) > > if (streq(outform, "dts")) { > dt_to_source(outf, dti); > +#ifndef NO_YAML > + } else if (streq(outform, "yaml")) { > + if (!streq(inform, "dts")) > + die("YAML output format requires dts input format\n"); > + dt_to_yaml(outf, dti); > +#endif > } else if (streq(outform, "dtb")) { > dt_to_blob(outf, dti, outversion); > } else if (streq(outform, "asm")) { > diff --git a/scripts/dtc/dtc.h b/scripts/dtc/dtc.h > index 303c2a6a73..789e0b1bc0 100644 > --- a/scripts/dtc/dtc.h > +++ b/scripts/dtc/dtc.h > @@ -58,6 +58,7 @@ 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 */ > +extern int annotate; /* annotate .dts with input source location */ > > #define PHANDLE_LEGACY 0x1 > #define PHANDLE_EPAPR 0x2 > @@ -82,7 +83,6 @@ enum markertype { > TYPE_UINT16, > TYPE_UINT32, > TYPE_UINT64, > - TYPE_BLOB, > TYPE_STRING, > }; > extern const char *markername(enum markertype markertype); > @@ -109,6 +109,8 @@ struct data { > for_each_marker(m) \ > if ((m)->type == (t)) > > +size_t type_marker_length(struct marker *m); > + > void data_free(struct data d); > > struct data data_grow_for(struct data d, int xlen); > @@ -157,6 +159,7 @@ struct property { > struct property *next; > > struct label *labels; > + struct srcpos *srcpos; > }; > > struct node { > @@ -176,6 +179,7 @@ struct node { > > struct label *labels; > const struct bus_type *bus; > + struct srcpos *srcpos; > > bool omit_if_unused, is_referenced; > }; > @@ -204,13 +208,15 @@ struct node { > 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(char *name, struct data val, > + struct srcpos *srcpos); > 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 *build_node(struct property *proplist, struct node *children, > + struct srcpos *srcpos); > +struct node *build_node_delete(struct srcpos *srcpos); > struct node *name_node(struct node *node, char *name); > struct node *omit_node_if_unused(struct node *node); > struct node *reference_node(struct node *node); > @@ -298,6 +304,10 @@ struct dt_info *dt_from_blob(const char *fname); > void dt_to_source(FILE *f, struct dt_info *dti); > struct dt_info *dt_from_source(const char *f); > > +/* YAML source */ > + > +void dt_to_yaml(FILE *f, struct dt_info *dti); > + > /* FS trees */ > > struct dt_info *dt_from_fs(const char *dirname); > diff --git a/scripts/dtc/fdtget.c b/scripts/dtc/fdtget.c > deleted file mode 100644 > index a79c3b2aa1..0000000000 > --- a/scripts/dtc/fdtget.c > +++ /dev/null > @@ -1,383 +0,0 @@ > -/* > - * 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 <pantelis.antoniou@gmail.com> and > - * Matthew McClintock <msm@freescale.com> > - * > - * 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 <assert.h> > -#include <ctype.h> > -#include <getopt.h> > -#include <stdio.h> > -#include <stdlib.h> > -#include <string.h> > - > -#include <libfdt.h> > - > -#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_ld((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 size; > - const char *s; > - int is_string; > - > - /* 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; > - } > - > - 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 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; > - fdt_getprop_by_offset(blob, prop, &name, NULL); > - 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 > - * @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, NULL); > - 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 <options> <dt file> [<node> <property>]...\n" > - " fdtget -p <options> <dt file> [<node> ]...\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; > -} > diff --git a/scripts/dtc/flattree.c b/scripts/dtc/flattree.c > index 851ea87dbc..acf04c3066 100644 > --- a/scripts/dtc/flattree.c > +++ b/scripts/dtc/flattree.c > @@ -692,7 +692,7 @@ static struct property *flat_read_property(struct inbuf *dtbuf, > > val = flat_read_data(dtbuf, proplen); > > - return build_property(name, val); > + return build_property(name, val, NULL); > } > > > @@ -750,7 +750,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf, > char *flatname; > uint32_t val; > > - node = build_node(NULL, NULL); > + node = build_node(NULL, NULL, NULL); > > flatname = flat_read_string(dtbuf); > > diff --git a/scripts/dtc/fstree.c b/scripts/dtc/fstree.c > index ae7d06c3c4..1e7eeba47f 100644 > --- a/scripts/dtc/fstree.c > +++ b/scripts/dtc/fstree.c > @@ -34,7 +34,7 @@ static struct node *read_fstree(const char *dirname) > if (!d) > die("Couldn't opendir() \"%s\": %s\n", dirname, strerror(errno)); > > - tree = build_node(NULL, NULL); > + tree = build_node(NULL, NULL, NULL); > > while ((de = readdir(d)) != NULL) { > char *tmpname; > @@ -60,7 +60,8 @@ static struct node *read_fstree(const char *dirname) > } else { > prop = build_property(xstrdup(de->d_name), > data_copy_file(pfile, > - st.st_size)); > + st.st_size), > + NULL); > add_property(tree, prop); > fclose(pfile); > } > diff --git a/scripts/dtc/libfdt/Makefile.libfdt b/scripts/dtc/libfdt/Makefile.libfdt > new file mode 100644 > index 0000000000..3af3656df8 > --- /dev/null > +++ b/scripts/dtc/libfdt/Makefile.libfdt > @@ -0,0 +1,15 @@ > +# Makefile.libfdt > +# > +# This is not a complete Makefile of itself. Instead, it is designed to > +# be easily embeddable into other systems of Makefiles. > +# > +LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1 > +LIBFDT_INCLUDES = fdt.h libfdt.h libfdt_env.h > +LIBFDT_VERSION = version.lds > +LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c \ > + fdt_addresses.c fdt_overlay.c > +LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o) > + > +libfdt_clean: > + @$(VECHO) CLEAN "(libfdt)" > + rm -f $(STD_CLEANFILES:%=$(LIBFDT_dir)/%) > diff --git a/scripts/dtc/fdt.c b/scripts/dtc/libfdt/fdt.c > similarity index 100% > rename from scripts/dtc/fdt.c > rename to scripts/dtc/libfdt/fdt.c > diff --git a/scripts/dtc/fdt.h b/scripts/dtc/libfdt/fdt.h > similarity index 100% > rename from scripts/dtc/fdt.h > rename to scripts/dtc/libfdt/fdt.h > diff --git a/scripts/dtc/fdt_addresses.c b/scripts/dtc/libfdt/fdt_addresses.c > similarity index 92% > rename from scripts/dtc/fdt_addresses.c > rename to scripts/dtc/libfdt/fdt_addresses.c > index 49537b578d..f13a87dfa0 100644 > --- a/scripts/dtc/fdt_addresses.c > +++ b/scripts/dtc/libfdt/fdt_addresses.c > @@ -64,7 +64,7 @@ static int fdt_cells(const void *fdt, int nodeoffset, const char *name) > > c = fdt_getprop(fdt, nodeoffset, name, &len); > if (!c) > - return 2; > + return len; > > if (len != sizeof(*c)) > return -FDT_ERR_BADNCELLS; > @@ -78,10 +78,20 @@ static int fdt_cells(const void *fdt, int nodeoffset, const char *name) > > int fdt_address_cells(const void *fdt, int nodeoffset) > { > - return fdt_cells(fdt, nodeoffset, "#address-cells"); > + int val; > + > + val = fdt_cells(fdt, nodeoffset, "#address-cells"); > + if (val == -FDT_ERR_NOTFOUND) > + return 2; > + return val; > } > > int fdt_size_cells(const void *fdt, int nodeoffset) > { > - return fdt_cells(fdt, nodeoffset, "#size-cells"); > + int val; > + > + val = fdt_cells(fdt, nodeoffset, "#size-cells"); > + if (val == -FDT_ERR_NOTFOUND) > + return 1; > + return val; > } > diff --git a/scripts/dtc/fdt_empty_tree.c b/scripts/dtc/libfdt/fdt_empty_tree.c > similarity index 100% > rename from scripts/dtc/fdt_empty_tree.c > rename to scripts/dtc/libfdt/fdt_empty_tree.c > diff --git a/scripts/dtc/fdt_overlay.c b/scripts/dtc/libfdt/fdt_overlay.c > similarity index 100% > rename from scripts/dtc/fdt_overlay.c > rename to scripts/dtc/libfdt/fdt_overlay.c > diff --git a/scripts/dtc/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c > similarity index 100% > rename from scripts/dtc/fdt_ro.c > rename to scripts/dtc/libfdt/fdt_ro.c > diff --git a/scripts/dtc/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c > similarity index 100% > rename from scripts/dtc/fdt_rw.c > rename to scripts/dtc/libfdt/fdt_rw.c > diff --git a/scripts/dtc/fdt_strerror.c b/scripts/dtc/libfdt/fdt_strerror.c > similarity index 100% > rename from scripts/dtc/fdt_strerror.c > rename to scripts/dtc/libfdt/fdt_strerror.c > diff --git a/scripts/dtc/fdt_sw.c b/scripts/dtc/libfdt/fdt_sw.c > similarity index 100% > rename from scripts/dtc/fdt_sw.c > rename to scripts/dtc/libfdt/fdt_sw.c > diff --git a/scripts/dtc/fdt_wip.c b/scripts/dtc/libfdt/fdt_wip.c > similarity index 100% > rename from scripts/dtc/fdt_wip.c > rename to scripts/dtc/libfdt/fdt_wip.c > diff --git a/scripts/dtc/libfdt.h b/scripts/dtc/libfdt/libfdt.h > similarity index 99% > rename from scripts/dtc/libfdt.h > rename to scripts/dtc/libfdt/libfdt.h > index 2bd151dd35..15eb0fd3c6 100644 > --- a/scripts/dtc/libfdt.h > +++ b/scripts/dtc/libfdt/libfdt.h > @@ -163,18 +163,26 @@ uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset); > > static inline uint32_t fdt32_ld(const fdt32_t *p) > { > - fdt32_t v; > + const uint8_t *bp = (const uint8_t *)p; > > - memcpy(&v, p, sizeof(v)); > - return fdt32_to_cpu(v); > + return ((uint32_t)bp[0] << 24) > + | ((uint32_t)bp[1] << 16) > + | ((uint32_t)bp[2] << 8) > + | bp[3]; > } > > static inline uint64_t fdt64_ld(const fdt64_t *p) > { > - fdt64_t v; > - > - memcpy(&v, p, sizeof(v)); > - return fdt64_to_cpu(v); > + const uint8_t *bp = (const uint8_t *)p; > + > + return ((uint64_t)bp[0] << 56) > + | ((uint64_t)bp[1] << 48) > + | ((uint64_t)bp[2] << 40) > + | ((uint64_t)bp[3] << 32) > + | ((uint64_t)bp[4] << 24) > + | ((uint64_t)bp[5] << 16) > + | ((uint64_t)bp[6] << 8) > + | bp[7]; > } > > /**********************************************************************/ > @@ -219,7 +227,7 @@ int fdt_next_subnode(const void *fdt, int offset); > * ... > * } > * > - * if ((node < 0) && (node != -FDT_ERR_NOT_FOUND)) { > + * if ((node < 0) && (node != -FDT_ERR_NOTFOUND)) { > * Error handling > * } > * > @@ -558,7 +566,7 @@ int fdt_next_property_offset(const void *fdt, int offset); > * ... > * } > * > - * if ((property < 0) && (property != -FDT_ERR_NOT_FOUND)) { > + * if ((property < 0) && (property != -FDT_ERR_NOTFOUND)) { > * Error handling > * } > * > @@ -661,7 +669,7 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset, > /** > * 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 > + * @offset: 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 > * > @@ -1145,7 +1153,7 @@ int fdt_address_cells(const void *fdt, int nodeoffset); > * > * returns: > * 0 <= n < FDT_MAX_NCELLS, on success > - * 2, if the node has no #size-cells property > + * 1, if the node has no #size-cells property > * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid > * #size-cells property > * -FDT_ERR_BADMAGIC, > diff --git a/scripts/dtc/libfdt_env.h b/scripts/dtc/libfdt/libfdt_env.h > similarity index 100% > rename from scripts/dtc/libfdt_env.h > rename to scripts/dtc/libfdt/libfdt_env.h > diff --git a/scripts/dtc/libfdt_internal.h b/scripts/dtc/libfdt/libfdt_internal.h > similarity index 100% > rename from scripts/dtc/libfdt_internal.h > rename to scripts/dtc/libfdt/libfdt_internal.h > diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c > index 4ff0679e00..7a2e6446a1 100644 > --- a/scripts/dtc/livetree.c > +++ b/scripts/dtc/livetree.c > @@ -19,6 +19,7 @@ > */ > > #include "dtc.h" > +#include "srcpos.h" > > /* > * Tree building functions > @@ -50,7 +51,8 @@ void delete_labels(struct label **labels) > label->deleted = 1; > } > > -struct property *build_property(char *name, struct data val) > +struct property *build_property(char *name, struct data val, > + struct srcpos *srcpos) > { > struct property *new = xmalloc(sizeof(*new)); > > @@ -58,6 +60,7 @@ struct property *build_property(char *name, struct data val) > > new->name = name; > new->val = val; > + new->srcpos = srcpos_copy(srcpos); > > return new; > } > @@ -97,7 +100,8 @@ struct property *reverse_properties(struct property *first) > return head; > } > > -struct node *build_node(struct property *proplist, struct node *children) > +struct node *build_node(struct property *proplist, struct node *children, > + struct srcpos *srcpos) > { > struct node *new = xmalloc(sizeof(*new)); > struct node *child; > @@ -106,6 +110,7 @@ struct node *build_node(struct property *proplist, struct node *children) > > new->proplist = reverse_properties(proplist); > new->children = children; > + new->srcpos = srcpos_copy(srcpos); > > for_each_child(new, child) { > child->parent = new; > @@ -114,13 +119,14 @@ struct node *build_node(struct property *proplist, struct node *children) > return new; > } > > -struct node *build_node_delete(void) > +struct node *build_node_delete(struct srcpos *srcpos) > { > struct node *new = xmalloc(sizeof(*new)); > > memset(new, 0, sizeof(*new)); > > new->deleted = 1; > + new->srcpos = srcpos_copy(srcpos); > > return new; > } > @@ -183,6 +189,8 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node) > > old_prop->val = new_prop->val; > old_prop->deleted = 0; > + free(old_prop->srcpos); > + old_prop->srcpos = new_prop->srcpos; > free(new_prop); > new_prop = NULL; > break; > @@ -223,6 +231,8 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node) > add_child(old_node, new_child); > } > > + old_node->srcpos = srcpos_extend(old_node->srcpos, new_node->srcpos); > + > /* The new node contents are now merged into the old node. Free > * the new node. */ > free(new_node); > @@ -241,18 +251,18 @@ struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref) > if (ref[0] == '/') { > d = data_append_data(d, ref, strlen(ref) + 1); > > - p = build_property("target-path", d); > + p = build_property("target-path", d, NULL); > } else { > d = data_add_marker(d, REF_PHANDLE, ref); > d = data_append_integer(d, 0xffffffff, 32); > > - p = build_property("target", d); > + p = build_property("target", d, NULL); > } > > xasprintf(&name, "fragment@%u", > next_orphan_fragment++); > name_node(new_node, "__overlay__"); > - node = build_node(p, new_node); > + node = build_node(p, new_node, NULL); > name_node(node, name); > > add_child(dt, node); > @@ -351,7 +361,7 @@ void append_to_property(struct node *node, > p->val = d; > } else { > d = data_append_data(empty_data, data, len); > - p = build_property(name, d); > + p = build_property(name, d, NULL); > add_property(node, p); > } > } > @@ -609,11 +619,11 @@ cell_t get_node_phandle(struct node *root, struct node *node) > > if (!get_property(node, "linux,phandle") > && (phandle_format & PHANDLE_LEGACY)) > - add_property(node, build_property("linux,phandle", d)); > + add_property(node, build_property("linux,phandle", d, NULL)); > > if (!get_property(node, "phandle") > && (phandle_format & PHANDLE_EPAPR)) > - add_property(node, build_property("phandle", d)); > + add_property(node, build_property("phandle", d, NULL)); > > /* If the node *does* have a phandle property, we must > * be dealing with a self-referencing phandle, which will be > @@ -787,7 +797,7 @@ static struct node *build_and_name_child_node(struct node *parent, char *name) > { > struct node *node; > > - node = build_node(NULL, NULL); > + node = build_node(NULL, NULL, NULL); > name_node(node, xstrdup(name)); > add_child(parent, node); > > @@ -849,7 +859,8 @@ static void generate_label_tree_internal(struct dt_info *dti, > /* insert it */ > p = build_property(l->label, > data_copy_mem(node->fullpath, > - strlen(node->fullpath) + 1)); > + strlen(node->fullpath) + 1), > + NULL); > add_property(an, p); > } > > diff --git a/scripts/dtc/srcpos.c b/scripts/dtc/srcpos.c > index cb6ed0e3e5..41f83700ee 100644 > --- a/scripts/dtc/srcpos.c > +++ b/scripts/dtc/srcpos.c > @@ -33,6 +33,9 @@ struct search_path { > /* This is the list of directories that we search for source files */ > static struct search_path *search_path_head, **search_path_tail; > > +/* Detect infinite include recursion. */ > +#define MAX_SRCFILE_DEPTH (100) > +static int srcfile_depth; /* = 0 */ > > static char *get_dirname(const char *path) > { > @@ -51,11 +54,51 @@ static char *get_dirname(const char *path) > > FILE *depfile; /* = NULL */ > struct srcfile_state *current_srcfile; /* = NULL */ > +static char *initial_path; /* = NULL */ > +static int initial_pathlen; /* = 0 */ > +static bool initial_cpp = true; > > -/* Detect infinite include recursion. */ > -#define MAX_SRCFILE_DEPTH (100) > -static int srcfile_depth; /* = 0 */ > +static void set_initial_path(char *fname) > +{ > + int i, len = strlen(fname); > > + xasprintf(&initial_path, "%s", fname); > + initial_pathlen = 0; > + for (i = 0; i != len; i++) > + if (initial_path[i] == '/') > + initial_pathlen++; > +} > + > +static char *shorten_to_initial_path(char *fname) > +{ > + char *p1, *p2, *prevslash1 = NULL; > + int slashes = 0; > + > + for (p1 = fname, p2 = initial_path; *p1 && *p2; p1++, p2++) { > + if (*p1 != *p2) > + break; > + if (*p1 == '/') { > + prevslash1 = p1; > + slashes++; > + } > + } > + p1 = prevslash1 + 1; > + if (prevslash1) { > + int diff = initial_pathlen - slashes, i, j; > + int restlen = strlen(fname) - (p1 - fname); > + char *res; > + > + res = xmalloc((3 * diff) + restlen + 1); > + for (i = 0, j = 0; i != diff; i++) { > + res[j++] = '.'; > + res[j++] = '.'; > + res[j++] = '/'; > + } > + strcpy(res + j, p1); > + return res; > + } > + return NULL; > +} > > /** > * Try to open a file in a given directory. > @@ -157,6 +200,9 @@ void srcfile_push(const char *fname) > srcfile->colno = 1; > > current_srcfile = srcfile; > + > + if (srcfile_depth == 1) > + set_initial_path(srcfile->name); > } > > bool srcfile_pop(void) > @@ -197,18 +243,6 @@ void srcfile_add_search_path(const char *dirname) > search_path_tail = &node->next; > } > > -/* > - * The empty source position. > - */ > - > -struct srcpos srcpos_empty = { > - .first_line = 0, > - .first_column = 0, > - .last_line = 0, > - .last_column = 0, > - .file = NULL, > -}; > - > void srcpos_update(struct srcpos *pos, const char *text, int len) > { > int i; > @@ -234,13 +268,35 @@ struct srcpos * > srcpos_copy(struct srcpos *pos) > { > struct srcpos *pos_new; > + struct srcfile_state *srcfile_state; > + > + if (!pos) > + return NULL; > > pos_new = xmalloc(sizeof(struct srcpos)); > + assert(pos->next == NULL); > memcpy(pos_new, pos, sizeof(struct srcpos)); > > + /* allocate without free */ > + srcfile_state = xmalloc(sizeof(struct srcfile_state)); > + memcpy(srcfile_state, pos->file, sizeof(struct srcfile_state)); > + pos_new->file = srcfile_state; > + > return pos_new; > } > > +struct srcpos *srcpos_extend(struct srcpos *pos, struct srcpos *newtail) > +{ > + struct srcpos *p; > + > + if (!pos) > + return newtail; > + > + for (p = pos; p->next != NULL; p = p->next); > + p->next = newtail; > + return pos; > +} > + > char * > srcpos_string(struct srcpos *pos) > { > @@ -266,6 +322,68 @@ srcpos_string(struct srcpos *pos) > return pos_str; > } > > +static char * > +srcpos_string_comment(struct srcpos *pos, bool first_line, int level) > +{ > + char *pos_str, *fname, *first, *rest; > + bool fresh_fname = false; > + > + if (!pos) { > + if (level > 1) { > + xasprintf(&pos_str, "<no-file>:<no-line>"); > + return pos_str; > + } else { > + return NULL; > + } > + } > + > + if (!pos->file) > + fname = "<no-file>"; > + else if (!pos->file->name) > + fname = "<no-filename>"; > + else if (level > 1) > + fname = pos->file->name; > + else { > + fname = shorten_to_initial_path(pos->file->name); > + if (fname) > + fresh_fname = true; > + else > + fname = pos->file->name; > + } > + > + if (level > 1) > + xasprintf(&first, "%s:%d:%d-%d:%d", fname, > + pos->first_line, pos->first_column, > + pos->last_line, pos->last_column); > + else > + xasprintf(&first, "%s:%d", fname, > + first_line ? pos->first_line : pos->last_line); > + > + if (fresh_fname) > + free(fname); > + > + if (pos->next != NULL) { > + rest = srcpos_string_comment(pos->next, first_line, level); > + xasprintf(&pos_str, "%s, %s", first, rest); > + free(first); > + free(rest); > + } else { > + pos_str = first; > + } > + > + return pos_str; > +} > + > +char *srcpos_string_first(struct srcpos *pos, int level) > +{ > + return srcpos_string_comment(pos, true, level); > +} > + > +char *srcpos_string_last(struct srcpos *pos, int level) > +{ > + return srcpos_string_comment(pos, false, level); > +} > + > void srcpos_verror(struct srcpos *pos, const char *prefix, > const char *fmt, va_list va) > { > @@ -294,4 +412,9 @@ void srcpos_set_line(char *f, int l) > { > current_srcfile->name = f; > current_srcfile->lineno = l; > + > + if (initial_cpp) { > + initial_cpp = false; > + set_initial_path(f); > + } > } > diff --git a/scripts/dtc/srcpos.h b/scripts/dtc/srcpos.h > index 9ded12a383..6326a952c4 100644 > --- a/scripts/dtc/srcpos.h > +++ b/scripts/dtc/srcpos.h > @@ -74,6 +74,7 @@ struct srcpos { > int last_line; > int last_column; > struct srcfile_state *file; > + struct srcpos *next; > }; > > #define YYLTYPE struct srcpos > @@ -93,19 +94,18 @@ struct srcpos { > YYRHSLOC(Rhs, 0).last_column; \ > (Current).file = YYRHSLOC (Rhs, 0).file; \ > } \ > + (Current).next = NULL; \ > } 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 struct srcpos *srcpos_extend(struct srcpos *new_srcpos, > + struct srcpos *old_srcpos); > extern char *srcpos_string(struct srcpos *pos); > +extern char *srcpos_string_first(struct srcpos *pos, int level); > +extern char *srcpos_string_last(struct srcpos *pos, int level); > + > > extern void PRINTF(3, 0) srcpos_verror(struct srcpos *pos, const char *prefix, > const char *fmt, va_list va); > diff --git a/scripts/dtc/treesource.c b/scripts/dtc/treesource.c > index f99544d723..1af36628b7 100644 > --- a/scripts/dtc/treesource.c > +++ b/scripts/dtc/treesource.c > @@ -64,6 +64,10 @@ static bool isstring(char c) > static void write_propval_string(FILE *f, const char *s, size_t len) > { > const char *end = s + len - 1; > + > + if (!len) > + return; > + > assert(*end == '\0'); > > fprintf(f, "\""); > @@ -118,29 +122,36 @@ static void write_propval_int(FILE *f, const char *p, size_t len, size_t width) > for (; p < end; p += width) { > switch (width) { > case 1: > - fprintf(f, " %02"PRIx8, *(const uint8_t*)p); > + fprintf(f, "%02"PRIx8, *(const uint8_t*)p); > break; > case 2: > - fprintf(f, " 0x%02"PRIx16, fdt16_to_cpu(*(const fdt16_t*)p)); > + fprintf(f, "0x%02"PRIx16, fdt16_to_cpu(*(const fdt16_t*)p)); > break; > case 4: > - fprintf(f, " 0x%02"PRIx32, fdt32_to_cpu(*(const fdt32_t*)p)); > + fprintf(f, "0x%02"PRIx32, fdt32_to_cpu(*(const fdt32_t*)p)); > break; > case 8: > - fprintf(f, " 0x%02"PRIx64, fdt64_to_cpu(*(const fdt64_t*)p)); > + fprintf(f, "0x%02"PRIx64, fdt64_to_cpu(*(const fdt64_t*)p)); > break; > } > + if (p + width < end) > + fputc(' ', f); > } > } > > +static bool has_data_type_information(struct marker *m) > +{ > + return m->type >= TYPE_UINT8; > +} > + > static struct marker *next_type_marker(struct marker *m) > { > - while (m && (m->type == LABEL || m->type == REF_PHANDLE || m->type == REF_PATH)) > + while (m && !has_data_type_information(m)) > m = m->next; > return m; > } > > -static size_t type_marker_length(struct marker *m) > +size_t type_marker_length(struct marker *m) > { > struct marker *next = next_type_marker(m->next); > > @@ -157,10 +168,10 @@ static const char *delim_start[] = { > [TYPE_STRING] = "", > }; > static const char *delim_end[] = { > - [TYPE_UINT8] = " ]", > - [TYPE_UINT16] = " >", > - [TYPE_UINT32] = " >", > - [TYPE_UINT64] = " >", > + [TYPE_UINT8] = "]", > + [TYPE_UINT16] = ">", > + [TYPE_UINT32] = ">", > + [TYPE_UINT64] = ">", > [TYPE_STRING] = "", > }; > > @@ -203,13 +214,22 @@ static void write_propval(FILE *f, struct property *prop) > struct marker *m = prop->val.markers; > struct marker dummy_marker; > enum markertype emit_type = TYPE_NONE; > + char *srcstr; > > if (len == 0) { > - fprintf(f, ";\n"); > + fprintf(f, ";"); > + if (annotate) { > + srcstr = srcpos_string_first(prop->srcpos, annotate); > + if (srcstr) { > + fprintf(f, " /* %s */", srcstr); > + free(srcstr); > + } > + } > + fprintf(f, "\n"); > return; > } > > - fprintf(f, " = "); > + fprintf(f, " ="); > > if (!next_type_marker(m)) { > /* data type information missing, need to guess */ > @@ -220,32 +240,23 @@ static void write_propval(FILE *f, struct property *prop) > m = &dummy_marker; > } > > - struct marker *m_label = prop->val.markers; > for_each_marker(m) { > - size_t chunk_len; > + size_t chunk_len = (m->next ? m->next->offset : len) - m->offset; > + size_t data_len = type_marker_length(m) ? : len - m->offset; > const char *p = &prop->val.val[m->offset]; > > - if (m->type < TYPE_UINT8) > - continue; > - > - chunk_len = type_marker_length(m); > - if (!chunk_len) > - chunk_len = len - m->offset; > - > - if (emit_type != TYPE_NONE) > - fprintf(f, "%s, ", delim_end[emit_type]); > - emit_type = m->type; > - > - for_each_marker_of_type(m_label, LABEL) { > - if (m_label->offset > m->offset) > - break; > - fprintf(f, "%s: ", m_label->ref); > - } > - > - fprintf(f, "%s", delim_start[emit_type]); > + if (has_data_type_information(m)) { > + emit_type = m->type; > + fprintf(f, " %s", delim_start[emit_type]); > + } else if (m->type == LABEL) > + fprintf(f, " %s:", m->ref); > + else if (m->offset) > + fputc(' ', f); > > - if (chunk_len <= 0) > + if (emit_type == TYPE_NONE) { > + assert(chunk_len == 0); > continue; > + } > > switch(emit_type) { > case TYPE_UINT16: > @@ -263,15 +274,23 @@ static void write_propval(FILE *f, struct property *prop) > default: > write_propval_int(f, p, chunk_len, 1); > } > - } > > - /* Wrap up any labels at the end of the value */ > - for_each_marker_of_type(m_label, LABEL) { > - assert (m_label->offset == len); > - fprintf(f, " %s:", m_label->ref); > + if (chunk_len == data_len) { > + size_t pos = m->offset + chunk_len; > + fprintf(f, pos == len ? "%s" : "%s,", > + delim_end[emit_type] ? : ""); > + emit_type = TYPE_NONE; > + } > } > - > - fprintf(f, "%s;\n", delim_end[emit_type] ? : ""); > + fprintf(f, ";"); > + if (annotate) { > + srcstr = srcpos_string_first(prop->srcpos, annotate); > + if (srcstr) { > + fprintf(f, " /* %s */", srcstr); > + free(srcstr); > + } > + } > + fprintf(f, "\n"); > } > > static void write_tree_source_node(FILE *f, struct node *tree, int level) > @@ -279,14 +298,24 @@ static void write_tree_source_node(FILE *f, struct node *tree, int level) > struct property *prop; > struct node *child; > struct label *l; > + char *srcstr; > > 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); > + fprintf(f, "%s {", tree->name); > else > - fprintf(f, "/ {\n"); > + fprintf(f, "/ {"); > + > + if (annotate) { > + srcstr = srcpos_string_first(tree->srcpos, annotate); > + if (srcstr) { > + fprintf(f, " /* %s */", srcstr); > + free(srcstr); > + } > + } > + fprintf(f, "\n"); > > for_each_property(tree, prop) { > write_prefix(f, level+1); > @@ -300,10 +329,17 @@ static void write_tree_source_node(FILE *f, struct node *tree, int level) > write_tree_source_node(f, child, level+1); > } > write_prefix(f, level); > - fprintf(f, "};\n"); > + fprintf(f, "};"); > + if (annotate) { > + srcstr = srcpos_string_last(tree->srcpos, annotate); > + if (srcstr) { > + fprintf(f, " /* %s */", srcstr); > + free(srcstr); > + } > + } > + fprintf(f, "\n"); > } > > - > void dt_to_source(FILE *f, struct dt_info *dti) > { > struct reserve_info *re; > diff --git a/scripts/dtc/util.c b/scripts/dtc/util.c > index a69b7a1346..9c6fb5f286 100644 > --- a/scripts/dtc/util.c > +++ b/scripts/dtc/util.c > @@ -46,36 +46,54 @@ char *xstrdup(const char *s) > return d; > } > > -/* based in part from (3) vsnprintf */ > -int xasprintf(char **strp, const char *fmt, ...) > +int xavsprintf_append(char **strp, const char *fmt, va_list ap) > { > - int n, size = 128; /* start with 128 bytes */ > + int n, size = 0; /* start with 128 bytes */ > char *p; > - va_list ap; > + va_list ap_copy; > > - /* initial pointer is NULL making the fist realloc to be malloc */ > - p = NULL; > - while (1) { > - p = xrealloc(p, size); > + p = *strp; > + if (p) > + size = strlen(p); > > - /* Try to print in the allocated space. */ > - va_start(ap, fmt); > - n = vsnprintf(p, size, fmt, ap); > - va_end(ap); > + va_copy(ap_copy, ap); > + n = vsnprintf(NULL, 0, fmt, ap_copy) + 1; > + va_end(ap_copy); > + > + p = xrealloc(p, size + n); > + > + n = vsnprintf(p + size, n, fmt, 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); > } > > +int xasprintf_append(char **strp, const char *fmt, ...) > +{ > + int n; > + va_list ap; > + > + va_start(ap, fmt); > + n = xavsprintf_append(strp, fmt, ap); > + va_end(ap); > + > + return n; > +} > + > +int xasprintf(char **strp, const char *fmt, ...) > +{ > + int n; > + va_list ap; > + > + *strp = NULL; > + > + va_start(ap, fmt); > + n = xavsprintf_append(strp, fmt, ap); > + va_end(ap); > + > + return n; > +} > + > char *join_path(const char *path, const char *name) > { > int lenp = strlen(path); > diff --git a/scripts/dtc/util.h b/scripts/dtc/util.h > index f6cea82741..7658781a62 100644 > --- a/scripts/dtc/util.h > +++ b/scripts/dtc/util.h > @@ -72,6 +72,8 @@ static inline void *xrealloc(void *p, size_t len) > extern char *xstrdup(const char *s); > > extern int PRINTF(2, 3) xasprintf(char **strp, const char *fmt, ...); > +extern int PRINTF(2, 3) xasprintf_append(char **strp, const char *fmt, ...); > +extern int xavsprintf_append(char **strp, const char *fmt, va_list ap); > extern char *join_path(const char *path, const char *name); > > /** > diff --git a/scripts/dtc/version_gen.h b/scripts/dtc/version_gen.h > index 2adf65b761..5c04ba938c 100644 > --- a/scripts/dtc/version_gen.h > +++ b/scripts/dtc/version_gen.h > @@ -1 +1 @@ > -#define DTC_VERSION "DTC 1.4.7" > +#define DTC_VERSION "DTC 1.5.0" > diff --git a/scripts/dtc/yamltree.c b/scripts/dtc/yamltree.c > new file mode 100644 > index 0000000000..a00285a5a9 > --- /dev/null > +++ b/scripts/dtc/yamltree.c > @@ -0,0 +1,247 @@ > +/* > + * (C) Copyright Linaro, Ltd. 2018 > + * (C) Copyright Arm Holdings. 2017 > + * (C) Copyright David Gibson <dwg@au1.ibm.com>, 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 <stdlib.h> > +#include <yaml.h> > +#include "dtc.h" > +#include "srcpos.h" > + > +char *yaml_error_name[] = { > + [YAML_NO_ERROR] = "no error", > + [YAML_MEMORY_ERROR] = "memory error", > + [YAML_READER_ERROR] = "reader error", > + [YAML_SCANNER_ERROR] = "scanner error", > + [YAML_PARSER_ERROR] = "parser error", > + [YAML_COMPOSER_ERROR] = "composer error", > + [YAML_WRITER_ERROR] = "writer error", > + [YAML_EMITTER_ERROR] = "emitter error", > +}; > + > +#define yaml_emitter_emit_or_die(emitter, event) ( \ > +{ \ > + if (!yaml_emitter_emit(emitter, event)) \ > + die("yaml '%s': %s in %s, line %i\n", \ > + yaml_error_name[(emitter)->error], \ > + (emitter)->problem, __func__, __LINE__); \ > +}) > + > +static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers, char *data, int len, int width) > +{ > + yaml_event_t event; > + void *tag; > + int off, start_offset = markers->offset; > + > + switch(width) { > + case 1: tag = "!u8"; break; > + case 2: tag = "!u16"; break; > + case 4: tag = "!u32"; break; > + case 8: tag = "!u64"; break; > + default: > + die("Invalid width %i", width); > + } > + assert(len % width == 0); > + > + yaml_sequence_start_event_initialize(&event, NULL, > + (yaml_char_t *)tag, width == 4, YAML_FLOW_SEQUENCE_STYLE); > + yaml_emitter_emit_or_die(emitter, &event); > + > + for (off = 0; off < len; off += width) { > + char buf[32]; > + struct marker *m; > + bool is_phandle = false; > + > + switch(width) { > + case 1: > + sprintf(buf, "0x%"PRIx8, *(uint8_t*)(data + off)); > + break; > + case 2: > + sprintf(buf, "0x%"PRIx16, fdt16_to_cpu(*(fdt16_t*)(data + off))); > + break; > + case 4: > + sprintf(buf, "0x%"PRIx32, fdt32_to_cpu(*(fdt32_t*)(data + off))); > + m = markers; > + is_phandle = false; > + for_each_marker_of_type(m, REF_PHANDLE) { > + if (m->offset == (start_offset + off)) { > + is_phandle = true; > + break; > + } > + } > + break; > + case 8: > + sprintf(buf, "0x%"PRIx64, fdt64_to_cpu(*(fdt64_t*)(data + off))); > + break; > + } > + > + if (is_phandle) > + yaml_scalar_event_initialize(&event, NULL, > + (yaml_char_t*)"!phandle", (yaml_char_t *)buf, > + strlen(buf), 0, 0, YAML_PLAIN_SCALAR_STYLE); > + else > + yaml_scalar_event_initialize(&event, NULL, > + (yaml_char_t*)YAML_INT_TAG, (yaml_char_t *)buf, > + strlen(buf), 1, 1, YAML_PLAIN_SCALAR_STYLE); > + yaml_emitter_emit_or_die(emitter, &event); > + } > + > + yaml_sequence_end_event_initialize(&event); > + yaml_emitter_emit_or_die(emitter, &event); > +} > + > +static void yaml_propval_string(yaml_emitter_t *emitter, char *str, int len) > +{ > + yaml_event_t event; > + int i; > + > + assert(str[len-1] == '\0'); > + > + /* Make sure the entire string is in the lower 7-bit ascii range */ > + for (i = 0; i < len; i++) > + assert(isascii(str[i])); > + > + yaml_scalar_event_initialize(&event, NULL, > + (yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)str, > + len-1, 0, 1, YAML_DOUBLE_QUOTED_SCALAR_STYLE); > + yaml_emitter_emit_or_die(emitter, &event); > +} > + > +static void yaml_propval(yaml_emitter_t *emitter, struct property *prop) > +{ > + yaml_event_t event; > + int len = prop->val.len; > + struct marker *m = prop->val.markers; > + > + /* Emit the property name */ > + yaml_scalar_event_initialize(&event, NULL, > + (yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)prop->name, > + strlen(prop->name), 1, 1, YAML_PLAIN_SCALAR_STYLE); > + yaml_emitter_emit_or_die(emitter, &event); > + > + /* Boolean properties are easiest to deal with. Length is zero, so just emit 'true' */ > + if (len == 0) { > + yaml_scalar_event_initialize(&event, NULL, > + (yaml_char_t *)YAML_BOOL_TAG, > + (yaml_char_t*)"true", > + strlen("true"), 1, 0, YAML_PLAIN_SCALAR_STYLE); > + yaml_emitter_emit_or_die(emitter, &event); > + return; > + } > + > + if (!m) > + die("No markers present in property '%s' value\n", prop->name); > + > + yaml_sequence_start_event_initialize(&event, NULL, > + (yaml_char_t *)YAML_SEQ_TAG, 1, YAML_FLOW_SEQUENCE_STYLE); > + yaml_emitter_emit_or_die(emitter, &event); > + > + for_each_marker(m) { > + int chunk_len; > + char *data = &prop->val.val[m->offset]; > + > + if (m->type < TYPE_UINT8) > + continue; > + > + chunk_len = type_marker_length(m) ? : len; > + assert(chunk_len > 0); > + len -= chunk_len; > + > + switch(m->type) { > + case TYPE_UINT16: > + yaml_propval_int(emitter, m, data, chunk_len, 2); > + break; > + case TYPE_UINT32: > + yaml_propval_int(emitter, m, data, chunk_len, 4); > + break; > + case TYPE_UINT64: > + yaml_propval_int(emitter, m, data, chunk_len, 8); > + break; > + case TYPE_STRING: > + yaml_propval_string(emitter, data, chunk_len); > + break; > + default: > + yaml_propval_int(emitter, m, data, chunk_len, 1); > + break; > + } > + } > + > + yaml_sequence_end_event_initialize(&event); > + yaml_emitter_emit_or_die(emitter, &event); > +} > + > + > +static void yaml_tree(struct node *tree, yaml_emitter_t *emitter) > +{ > + struct property *prop; > + struct node *child; > + yaml_event_t event; > + > + if (tree->deleted) > + return; > + > + yaml_mapping_start_event_initialize(&event, NULL, > + (yaml_char_t *)YAML_MAP_TAG, 1, YAML_ANY_MAPPING_STYLE); > + yaml_emitter_emit_or_die(emitter, &event); > + > + for_each_property(tree, prop) > + yaml_propval(emitter, prop); > + > + /* Loop over all the children, emitting them into the map */ > + for_each_child(tree, child) { > + yaml_scalar_event_initialize(&event, NULL, > + (yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)child->name, > + strlen(child->name), 1, 0, YAML_PLAIN_SCALAR_STYLE); > + yaml_emitter_emit_or_die(emitter, &event); > + yaml_tree(child, emitter); > + } > + > + yaml_mapping_end_event_initialize(&event); > + yaml_emitter_emit_or_die(emitter, &event); > +} > + > +void dt_to_yaml(FILE *f, struct dt_info *dti) > +{ > + yaml_emitter_t emitter; > + yaml_event_t event; > + > + yaml_emitter_initialize(&emitter); > + yaml_emitter_set_output_file(&emitter, f); > + yaml_stream_start_event_initialize(&event, YAML_UTF8_ENCODING); > + yaml_emitter_emit_or_die(&emitter, &event); > + > + yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0); > + yaml_emitter_emit_or_die(&emitter, &event); > + > + yaml_sequence_start_event_initialize(&event, NULL, (yaml_char_t *)YAML_SEQ_TAG, 1, YAML_ANY_SEQUENCE_STYLE); > + yaml_emitter_emit_or_die(&emitter, &event); > + > + yaml_tree(dti->dt, &emitter); > + > + yaml_sequence_end_event_initialize(&event); > + yaml_emitter_emit_or_die(&emitter, &event); > + > + yaml_document_end_event_initialize(&event, 0); > + yaml_emitter_emit_or_die(&emitter, &event); > + > + yaml_stream_end_event_initialize(&event); > + yaml_emitter_emit_or_die(&emitter, &event); > + > + yaml_emitter_delete(&emitter); > +} > -- > 2.20.1 > > > _______________________________________________ > barebox mailing list > barebox@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/barebox > -- Roland Hieber | r.hieber@pengutronix.de | Pengutronix e.K. | https://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim | Phone: +49-5121-206917-5086 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/8] scripts/dtc: Update to upstream version v1.5.0 2019-08-19 13:52 ` Roland Hieber @ 2019-08-19 13:56 ` Sascha Hauer 2019-08-19 14:09 ` Roland Hieber 0 siblings, 1 reply; 18+ messages in thread From: Sascha Hauer @ 2019-08-19 13:56 UTC (permalink / raw) To: Roland Hieber; +Cc: Barebox List On Mon, Aug 19, 2019 at 03:52:40PM +0200, Roland Hieber wrote: > On Mon, Aug 19, 2019 at 03:38:41PM +0200, Sascha Hauer wrote: > > This adds the following commits from upstream: > > > > d37f6b2 Bump version to v1.5.0 > > a4b1a30 pylibfdt:tests: Extend the way how to find a Python module > > I'm sorry if this will probably mean a lot of work for you, but sadly > those SHA1 hashes are too short to be unique :-( > > linux (master) $ git show d37f6b2 > fatal: ambiguous argument 'd37f6b2': unknown revision or path not in the working tree. > Use '--' to separate paths from revisions, like this: > 'git <command> [<revision>...] -- [<file>...]' These are dtc commits, not Linux kernel commits. Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/8] scripts/dtc: Update to upstream version v1.5.0 2019-08-19 13:56 ` Sascha Hauer @ 2019-08-19 14:09 ` Roland Hieber 2019-09-23 13:39 ` Ahmad Fatoum 0 siblings, 1 reply; 18+ messages in thread From: Roland Hieber @ 2019-08-19 14:09 UTC (permalink / raw) To: Sascha Hauer; +Cc: Barebox List On Mon, Aug 19, 2019 at 03:56:56PM +0200, Sascha Hauer wrote: > On Mon, Aug 19, 2019 at 03:52:40PM +0200, Roland Hieber wrote: > > On Mon, Aug 19, 2019 at 03:38:41PM +0200, Sascha Hauer wrote: > > > This adds the following commits from upstream: > > > > > > d37f6b2 Bump version to v1.5.0 > > > a4b1a30 pylibfdt:tests: Extend the way how to find a Python module > > > > I'm sorry if this will probably mean a lot of work for you, but sadly > > those SHA1 hashes are too short to be unique :-( > > > > linux (master) $ git show d37f6b2 > > fatal: ambiguous argument 'd37f6b2': unknown revision or path not in the working tree. > > Use '--' to separate paths from revisions, like this: > > 'git <command> [<revision>...] -- [<file>...]' > > These are dtc commits, not Linux kernel commits. OK, that explains it. Then the comment should probably mention where upstream lives :-) - Roland -- Roland Hieber | r.hieber@pengutronix.de | Pengutronix e.K. | https://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim | Phone: +49-5121-206917-5086 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/8] scripts/dtc: Update to upstream version v1.5.0 2019-08-19 14:09 ` Roland Hieber @ 2019-09-23 13:39 ` Ahmad Fatoum 0 siblings, 0 replies; 18+ messages in thread From: Ahmad Fatoum @ 2019-09-23 13:39 UTC (permalink / raw) To: Roland Hieber, Sascha Hauer; +Cc: Barebox List On 8/19/19 4:09 PM, Roland Hieber wrote: > On Mon, Aug 19, 2019 at 03:56:56PM +0200, Sascha Hauer wrote: >> On Mon, Aug 19, 2019 at 03:52:40PM +0200, Roland Hieber wrote: >>> On Mon, Aug 19, 2019 at 03:38:41PM +0200, Sascha Hauer wrote: >>>> This adds the following commits from upstream: >>>> >>>> d37f6b2 Bump version to v1.5.0 >>>> a4b1a30 pylibfdt:tests: Extend the way how to find a Python module >>> >>> I'm sorry if this will probably mean a lot of work for you, but sadly >>> those SHA1 hashes are too short to be unique :-( >>> >>> linux (master) $ git show d37f6b2 >>> fatal: ambiguous argument 'd37f6b2': unknown revision or path not in the working tree. >>> Use '--' to separate paths from revisions, like this: >>> 'git <command> [<revision>...] -- [<file>...]' >> >> These are dtc commits, not Linux kernel commits. > > OK, that explains it. Then the comment should probably mention where > upstream lives :-) FYI: Sent out <20190923121018.31574-5-a.fatoum@pengutronix.de> today, which does just that. Cheers Ahmad > > - Roland > -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 3/8] pbl: Implement strrchr 2019-08-19 13:38 [PATCH 0/8] Add support for a generic DT based 2nd stage ARM image Sascha Hauer 2019-08-19 13:38 ` [PATCH 1/8] dtc: Update update-dtc-source.sh from Linux Sascha Hauer 2019-08-19 13:38 ` [PATCH 2/8] scripts/dtc: Update to upstream version v1.5.0 Sascha Hauer @ 2019-08-19 13:38 ` Sascha Hauer 2019-08-19 13:38 ` [PATCH 4/8] Compile libfdt for barebox Sascha Hauer ` (4 subsequent siblings) 7 siblings, 0 replies; 18+ messages in thread From: Sascha Hauer @ 2019-08-19 13:38 UTC (permalink / raw) To: Barebox List strrchr is needed for libfdt. Add support for it to the pbl. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- pbl/string.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/pbl/string.c b/pbl/string.c index 927c92dc05..46bf0b32b3 100644 --- a/pbl/string.c +++ b/pbl/string.c @@ -133,3 +133,19 @@ size_t strnlen(const char * s, size_t count) /* nothing */; return sc - s; } + +/** + * strrchr - Find the last occurrence of a character in a string + * @s: The string to be searched + * @c: The character to search for + */ +char * _strrchr(const char * s, int c) +{ + const char *p = s + strlen(s); + + do { + if (*p == (char)c) + return (char *)p; + } while (--p >= s); + return NULL; +} -- 2.20.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 4/8] Compile libfdt for barebox 2019-08-19 13:38 [PATCH 0/8] Add support for a generic DT based 2nd stage ARM image Sascha Hauer ` (2 preceding siblings ...) 2019-08-19 13:38 ` [PATCH 3/8] pbl: Implement strrchr Sascha Hauer @ 2019-08-19 13:38 ` Sascha Hauer 2019-08-19 13:38 ` [PATCH 5/8] common: return "none" when board unset Sascha Hauer ` (3 subsequent siblings) 7 siblings, 0 replies; 18+ messages in thread From: Sascha Hauer @ 2019-08-19 13:38 UTC (permalink / raw) To: Barebox List libfdt can be useful for very early device tree parsing, so compile it for barobox aswell. This is done the same way as done in the Kernel: we put C files with the same name as in libfdt into lib/ and just include the libfdt files from there. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- include/fdt.h | 69 +------------------------------------- include/linux/libfdt.h | 8 +++++ include/linux/libfdt_env.h | 19 +++++++++++ lib/Kconfig | 3 ++ lib/Makefile | 10 ++++++ lib/fdt.c | 2 ++ lib/fdt_empty_tree.c | 2 ++ lib/fdt_ro.c | 2 ++ lib/fdt_rw.c | 2 ++ lib/fdt_strerror.c | 2 ++ lib/fdt_sw.c | 2 ++ lib/fdt_wip.c | 2 ++ 12 files changed, 55 insertions(+), 68 deletions(-) create mode 100644 include/linux/libfdt.h create mode 100644 include/linux/libfdt_env.h create mode 100644 lib/fdt.c create mode 100644 lib/fdt_empty_tree.c create mode 100644 lib/fdt_ro.c create mode 100644 lib/fdt_rw.c create mode 100644 lib/fdt_strerror.c create mode 100644 lib/fdt_sw.c create mode 100644 lib/fdt_wip.c diff --git a/include/fdt.h b/include/fdt.h index 1ccd4c6734..38a2d27b02 100644 --- a/include/fdt.h +++ b/include/fdt.h @@ -3,73 +3,6 @@ #include <linux/types.h> -#ifndef __ASSEMBLY__ - -#define _B(n) ((unsigned long long)((uint8_t *)&x)[n]) - -#define fdt32_to_cpu(x) be32_to_cpu(x) -#define cpu_to_fdt32(x) cpu_to_be32(x) - -static inline uint64_t fdt64_to_cpu(uint64_t x) -{ - return (_B(0) << 56) | (_B(1) << 48) | (_B(2) << 40) | (_B(3) << 32) - | (_B(4) << 24) | (_B(5) << 16) | (_B(6) << 8) | _B(7); -} -#define cpu_to_fdt64(x) fdt64_to_cpu(x) -#undef _B - -struct fdt_header { - uint32_t magic; /* magic word FDT_MAGIC */ - uint32_t totalsize; /* total size of DT block */ - uint32_t off_dt_struct; /* offset to structure */ - uint32_t off_dt_strings; /* offset to strings */ - uint32_t off_mem_rsvmap; /* offset to memory reserve map */ - uint32_t version; /* format version */ - uint32_t last_comp_version; /* last compatible version */ - - /* version 2 fields below */ - uint32_t boot_cpuid_phys; /* Which physical CPU id we're - booting on */ - /* version 3 fields below */ - uint32_t size_dt_strings; /* size of the strings block */ - - /* version 17 fields below */ - uint32_t size_dt_struct; /* size of the structure block */ -}; - -struct fdt_reserve_entry { - uint64_t address; - uint64_t size; -}; - -struct fdt_node_header { - uint32_t tag; - char name[0]; -}; - -struct fdt_property { - uint32_t tag; - uint32_t len; - uint32_t nameoff; - char data[0]; -}; - -#endif /* !__ASSEMBLY */ - -#define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */ -#define FDT_TAGSIZE sizeof(uint32_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(uint32_t)) -#define FDT_V2_SIZE (FDT_V1_SIZE + sizeof(uint32_t)) -#define FDT_V3_SIZE (FDT_V2_SIZE + sizeof(uint32_t)) -#define FDT_V16_SIZE FDT_V3_SIZE -#define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(uint32_t)) +#include <linux/libfdt.h> #endif /* _FDT_H */ diff --git a/include/linux/libfdt.h b/include/linux/libfdt.h new file mode 100644 index 0000000000..ef2467213b --- /dev/null +++ b/include/linux/libfdt.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _INCLUDE_LIBFDT_H_ +#define _INCLUDE_LIBFDT_H_ + +#include <linux/libfdt_env.h> +#include "../scripts/dtc/libfdt/libfdt.h" + +#endif /* _INCLUDE_LIBFDT_H_ */ diff --git a/include/linux/libfdt_env.h b/include/linux/libfdt_env.h new file mode 100644 index 0000000000..edb0f0c309 --- /dev/null +++ b/include/linux/libfdt_env.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef LIBFDT_ENV_H +#define LIBFDT_ENV_H + +#include <linux/kernel.h> /* For INT_MAX */ +#include <linux/string.h> + +#include <asm/byteorder.h> + +typedef __be16 fdt16_t; +typedef __be32 fdt32_t; +typedef __be64 fdt64_t; + +#define fdt32_to_cpu(x) be32_to_cpu(x) +#define cpu_to_fdt32(x) cpu_to_be32(x) +#define fdt64_to_cpu(x) be64_to_cpu(x) +#define cpu_to_fdt64(x) cpu_to_be64(x) + +#endif /* LIBFDT_ENV_H */ diff --git a/lib/Kconfig b/lib/Kconfig index af178217f8..f75eba9220 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -100,6 +100,9 @@ config FSL_QE_FIRMWARE select CRC32 bool +config LIBFDT + bool + config RATP select CRC_ITU_T bool "RATP protocol support" diff --git a/lib/Makefile b/lib/Makefile index 161d3a756e..a07ceb15ab 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -79,3 +79,13 @@ obj-$(CONFIG_GENERIC_LIB_LSHRDI3) += lshrdi3.o obj-$(CONFIG_GENERIC_LIB_MULDI3) += muldi3.o pbl-$(CONFIG_GENERIC_LIB_ASHLDI3) += ashldi3.o + +libfdt_files = fdt.o fdt_ro.o fdt_wip.o fdt_rw.o fdt_sw.o fdt_strerror.o \ + fdt_empty_tree.o +$(foreach file, $(libfdt_files), \ + $(eval CFLAGS_$(file) = -I $(srctree)/scripts/dtc/libfdt)) +$(foreach file, $(libfdt_files), \ + $(eval CFLAGS_pbl-$(file) = -I $(srctree)/scripts/dtc/libfdt)) + +obj-pbl-$(CONFIG_LIBFDT) += $(libfdt_files) + diff --git a/lib/fdt.c b/lib/fdt.c new file mode 100644 index 0000000000..97f20069fc --- /dev/null +++ b/lib/fdt.c @@ -0,0 +1,2 @@ +#include <linux/libfdt_env.h> +#include "../scripts/dtc/libfdt/fdt.c" diff --git a/lib/fdt_empty_tree.c b/lib/fdt_empty_tree.c new file mode 100644 index 0000000000..5d30c58150 --- /dev/null +++ b/lib/fdt_empty_tree.c @@ -0,0 +1,2 @@ +#include <linux/libfdt_env.h> +#include "../scripts/dtc/libfdt/fdt_empty_tree.c" diff --git a/lib/fdt_ro.c b/lib/fdt_ro.c new file mode 100644 index 0000000000..f73c04ea7b --- /dev/null +++ b/lib/fdt_ro.c @@ -0,0 +1,2 @@ +#include <linux/libfdt_env.h> +#include "../scripts/dtc/libfdt/fdt_ro.c" diff --git a/lib/fdt_rw.c b/lib/fdt_rw.c new file mode 100644 index 0000000000..0c1f0f4a4b --- /dev/null +++ b/lib/fdt_rw.c @@ -0,0 +1,2 @@ +#include <linux/libfdt_env.h> +#include "../scripts/dtc/libfdt/fdt_rw.c" diff --git a/lib/fdt_strerror.c b/lib/fdt_strerror.c new file mode 100644 index 0000000000..8713e3ff47 --- /dev/null +++ b/lib/fdt_strerror.c @@ -0,0 +1,2 @@ +#include <linux/libfdt_env.h> +#include "../scripts/dtc/libfdt/fdt_strerror.c" diff --git a/lib/fdt_sw.c b/lib/fdt_sw.c new file mode 100644 index 0000000000..9ac7e50c76 --- /dev/null +++ b/lib/fdt_sw.c @@ -0,0 +1,2 @@ +#include <linux/libfdt_env.h> +#include "../scripts/dtc/libfdt/fdt_sw.c" diff --git a/lib/fdt_wip.c b/lib/fdt_wip.c new file mode 100644 index 0000000000..45b3fc3d3b --- /dev/null +++ b/lib/fdt_wip.c @@ -0,0 +1,2 @@ +#include <linux/libfdt_env.h> +#include "../scripts/dtc/libfdt/fdt_wip.c" -- 2.20.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 5/8] common: return "none" when board unset 2019-08-19 13:38 [PATCH 0/8] Add support for a generic DT based 2nd stage ARM image Sascha Hauer ` (3 preceding siblings ...) 2019-08-19 13:38 ` [PATCH 4/8] Compile libfdt for barebox Sascha Hauer @ 2019-08-19 13:38 ` Sascha Hauer 2019-08-19 13:38 ` [PATCH 6/8] ARM: Add generic device tree 2nd stage support Sascha Hauer ` (2 subsequent siblings) 7 siblings, 0 replies; 18+ messages in thread From: Sascha Hauer @ 2019-08-19 13:38 UTC (permalink / raw) To: Barebox List Instead of returning NULL when board is not set return "none". Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- common/misc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/common/misc.c b/common/misc.c index 66aba534fc..9b390dc7ba 100644 --- a/common/misc.c +++ b/common/misc.c @@ -150,7 +150,10 @@ EXPORT_SYMBOL(barebox_set_model); const char *barebox_get_model(void) { - return model; + if (model) + return model; + else + return "none"; } EXPORT_SYMBOL(barebox_get_model); -- 2.20.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 6/8] ARM: Add generic device tree 2nd stage support 2019-08-19 13:38 [PATCH 0/8] Add support for a generic DT based 2nd stage ARM image Sascha Hauer ` (4 preceding siblings ...) 2019-08-19 13:38 ` [PATCH 5/8] common: return "none" when board unset Sascha Hauer @ 2019-08-19 13:38 ` Sascha Hauer 2019-11-19 8:26 ` Ahmad Fatoum 2019-08-19 13:38 ` [PATCH 7/8] ARM: i.MX: Do not hang() on unknown SoCs Sascha Hauer 2019-08-19 13:38 ` [PATCH 8/8] ARM: i.MX: When generic DT image is enabled do not hardcode SoC Sascha Hauer 7 siblings, 1 reply; 18+ messages in thread From: Sascha Hauer @ 2019-08-19 13:38 UTC (permalink / raw) To: Barebox List This adds support for building a barebox image that boots with the Linux ARM Kernel booting convention. Support for this image can be enabled in Kconfig. It picks up a device tree passed in r2. This new image helps for example with qemu. It can be started with: qemu-system-aarch64 -m 2G -M virt -kernel images/barebox-dt-2nd.img -cpu cortex-a57 -serial stdio or: qemu-system-arm -m 1G -M sabrelite -kernel images/barebox-dt-2nd.img -nographic -dtb arch/arm/dts/imx6q-sabrelite.dtb Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- arch/arm/Kconfig | 11 +++ arch/arm/cpu/Makefile | 3 + arch/arm/cpu/board-dt-2nd-aarch64.S | 11 +++ arch/arm/cpu/board-dt-2nd.c | 127 ++++++++++++++++++++++++++++ images/Makefile | 4 + 5 files changed, 156 insertions(+) create mode 100644 arch/arm/cpu/board-dt-2nd-aarch64.S create mode 100644 arch/arm/cpu/board-dt-2nd.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index de45bcf82a..cfca459984 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -314,6 +314,17 @@ source "arch/arm/mach-zynq/Kconfig" source "arch/arm/mach-qemu/Kconfig" source "arch/arm/mach-zynqmp/Kconfig" +config BOARD_ARM_GENERIC_DT + select LIBFDT + select ARM_AMBA + bool "Build generic dt image" + +config BOARD_ARM_GENERIC_DT_AARCH64 + bool + depends on CPU_V8 + depends on BOARD_ARM_GENERIC_DT + default y + config ARM_ASM_UNIFIED bool diff --git a/arch/arm/cpu/Makefile b/arch/arm/cpu/Makefile index 9b737f80ef..97e4eb52e3 100644 --- a/arch/arm/cpu/Makefile +++ b/arch/arm/cpu/Makefile @@ -10,6 +10,9 @@ AFLAGS_pbl-hyp.o :=-Wa,-march=armv7-a -Wa,-mcpu=all obj-y += start.o entry.o +pbl-$(CONFIG_BOARD_ARM_GENERIC_DT) += board-dt-2nd.o +pbl-$(CONFIG_BOARD_ARM_GENERIC_DT_AARCH64) += board-dt-2nd-aarch64.o + obj-pbl-y += setupc$(S64).o cache$(S64).o obj-$(CONFIG_BOOTM_OPTEE) += start-kernel-optee.o diff --git a/arch/arm/cpu/board-dt-2nd-aarch64.S b/arch/arm/cpu/board-dt-2nd-aarch64.S new file mode 100644 index 0000000000..0540a1690d --- /dev/null +++ b/arch/arm/cpu/board-dt-2nd-aarch64.S @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#include <linux/linkage.h> +#include <asm/barebox-arm64.h> + +ENTRY_PROC(start_dt_2nd) + adr x1, stack + mov sp, x1 + b dt_2nd_aarch64 +.word 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 +stack: +ENTRY_PROC_END(start_dt_2nd) diff --git a/arch/arm/cpu/board-dt-2nd.c b/arch/arm/cpu/board-dt-2nd.c new file mode 100644 index 0000000000..655c4b02b3 --- /dev/null +++ b/arch/arm/cpu/board-dt-2nd.c @@ -0,0 +1,127 @@ +#include <common.h> +#include <linux/sizes.h> +#include <asm/barebox-arm-head.h> +#include <asm/barebox-arm.h> +#include <io.h> +#include <debug_ll.h> +#include <asm/cache.h> +#include <asm/sections.h> +#include <linux/libfdt.h> + +static void find_mem(void *fdt, unsigned long *membase, + unsigned long *memsize) +{ + const __be32 *nap, *nsp, *reg; + uint32_t na, ns; + uint64_t memsize64, membase64; + int node, size, i; + + /* Make sure FDT blob is sane */ + if (fdt_check_header(fdt) != 0) { + pr_err("Invalid device tree blob\n"); + goto err; + } + + /* Find the #address-cells and #size-cells properties */ + node = fdt_path_offset(fdt, "/"); + if (node < 0) { + pr_err("Cannot find root node\n"); + goto err; + } + + nap = fdt_getprop(fdt, node, "#address-cells", &size); + if (!nap || (size != 4)) { + pr_err("Cannot find #address-cells property"); + goto err; + } + na = fdt32_to_cpu(*nap); + + nsp = fdt_getprop(fdt, node, "#size-cells", &size); + if (!nsp || (size != 4)) { + pr_err("Cannot find #size-cells property"); + goto err; + } + ns = fdt32_to_cpu(*nap); + + /* Find the memory range */ + node = fdt_node_offset_by_prop_value(fdt, -1, "device_type", + "memory", sizeof("memory")); + if (node < 0) { + pr_err("Cannot find memory node\n"); + goto err; + } + + reg = fdt_getprop(fdt, node, "reg", &size); + if (size < (na + ns) * sizeof(u32)) { + pr_err("cannot get memory range\n"); + goto err; + } + + membase64 = 0; + for (i = 0; i < na; i++) + membase64 = (membase64 << 32) | fdt32_to_cpu(*reg++); + + /* get the memsize and truncate it to under 4G on 32 bit machines */ + memsize64 = 0; + for (i = 0; i < ns; i++) + memsize64 = (memsize64 << 32) | fdt32_to_cpu(*reg++); + + *membase = membase64; + *memsize = memsize64; + + return; +err: + pr_err("No memory, cannot continue\n"); + while (1); +} + +#ifdef CONFIG_CPU_V8 + +static noinline void dt_2nd_continue_aarch64(void *fdt) +{ + unsigned long membase, memsize; + + find_mem(fdt, &membase, &memsize); + + barebox_arm_entry(membase, memsize, fdt); +} + +/* called from assembly */ +void dt_2nd_aarch64(void *fdt); + +void dt_2nd_aarch64(void *fdt) +{ + unsigned long image_start = (unsigned long)_text + global_variable_offset(); + + arm_setup_stack(image_start); + + relocate_to_current_adr(); + setup_c(); + + dt_2nd_continue_aarch64(fdt); +} + +#else + +static noinline void dt_2nd_continue(void *fdt) +{ + unsigned long membase, memsize; + + find_mem(fdt, &membase, &memsize); + + barebox_arm_entry(membase, memsize, fdt); +} + +ENTRY_FUNCTION(start_dt_2nd, r0, r1, r2) +{ + unsigned long image_start = (unsigned long)_text + global_variable_offset(); + + arm_setup_stack(image_start); + + relocate_to_current_adr(); + setup_c(); + barrier(); + + dt_2nd_continue((void *)r2); +} +#endif diff --git a/images/Makefile b/images/Makefile index 907986e2d0..dd39f44afb 100644 --- a/images/Makefile +++ b/images/Makefile @@ -164,6 +164,10 @@ include $(srctree)/images/Makefile.at91 include $(srctree)/images/Makefile.zynqmp include $(srctree)/images/Makefile.layerscape +pblb-$(CONFIG_BOARD_ARM_GENERIC_DT) += start_dt_2nd +FILE_barebox-dt-2nd.img = start_dt_2nd.pblb +image-$(CONFIG_BOARD_ARM_GENERIC_DT) += barebox-dt-2nd.img + ifneq ($(pblx-y)$(pblx-),) $(error pblx- has been removed. Please use pblb- instead.) endif -- 2.20.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 6/8] ARM: Add generic device tree 2nd stage support 2019-08-19 13:38 ` [PATCH 6/8] ARM: Add generic device tree 2nd stage support Sascha Hauer @ 2019-11-19 8:26 ` Ahmad Fatoum 2019-11-19 9:41 ` Oleksij Rempel 2019-11-25 7:47 ` Sascha Hauer 0 siblings, 2 replies; 18+ messages in thread From: Ahmad Fatoum @ 2019-11-19 8:26 UTC (permalink / raw) To: barebox, Sascha Hauer Hello Sascha, On 8/19/19 3:38 PM, Sascha Hauer wrote: > +void dt_2nd_aarch64(void *fdt) > +{ > + unsigned long image_start = (unsigned long)_text + global_variable_offset(); > + > + arm_setup_stack(image_start); Shouldn't we rather place the stack somewhere beyond the end of the barebox image instead of assuming that we can access the memory before the start? I am asking because I am testing use of the generic ARM board as default second stage image for the multi-image AT91s. The board specific entry point generates only the PBL, which runs in SRAM to do DRAM setup and chainloads the generic dt barebox from MMC to start of SDRAM and then calls it along with the dtb. It works so far and I like that I now can have the same second stage barebox for all multi-image targets. (And one could even "falcon"-boot that way). What do you think? > +ENTRY_FUNCTION(start_dt_2nd, r0, r1, r2) > +{ > + unsigned long image_start = (unsigned long)_text + global_variable_offset(); > + > + arm_setup_stack(image_start); Ditto. Cheers Ahmad -- Pengutronix e.K. | | Steuerwalder Str. 21 | http://www.pengutronix.de/ | 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 6/8] ARM: Add generic device tree 2nd stage support 2019-11-19 8:26 ` Ahmad Fatoum @ 2019-11-19 9:41 ` Oleksij Rempel 2019-11-19 10:21 ` Ahmad Fatoum 2019-11-25 7:47 ` Sascha Hauer 1 sibling, 1 reply; 18+ messages in thread From: Oleksij Rempel @ 2019-11-19 9:41 UTC (permalink / raw) To: Ahmad Fatoum, barebox, Sascha Hauer [-- Attachment #1.1.1: Type: text/plain, Size: 1286 bytes --] Am 19.11.19 um 09:26 schrieb Ahmad Fatoum: > Hello Sascha, > > On 8/19/19 3:38 PM, Sascha Hauer wrote: >> +void dt_2nd_aarch64(void *fdt) >> +{ >> + unsigned long image_start = (unsigned long)_text + global_variable_offset(); >> + >> + arm_setup_stack(image_start); > > Shouldn't we rather place the stack somewhere beyond the end of the barebox image > instead of assuming that we can access the memory before the start? > > I am asking because I am testing use of the generic ARM board as default > second stage image for the multi-image AT91s. The board specific entry point > generates only the PBL, which runs in SRAM to do DRAM setup and chainloads > the generic dt barebox from MMC to start of SDRAM and then calls it along > with the dtb. Hm.. Is it possible that you can get an exception vector in the star of SDRAM? > It works so far and I like that I now can have the same second stage barebox > for all multi-image targets. (And one could even "falcon"-boot that way). > What do you think?> >> +ENTRY_FUNCTION(start_dt_2nd, r0, r1, r2) >> +{ >> + unsigned long image_start = (unsigned long)_text + global_variable_offset(); >> + >> + arm_setup_stack(image_start); > > > Ditto. > > Cheers > Ahmad > -- Regards, Oleksij [-- Attachment #1.2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 488 bytes --] [-- Attachment #2: Type: text/plain, Size: 149 bytes --] _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 6/8] ARM: Add generic device tree 2nd stage support 2019-11-19 9:41 ` Oleksij Rempel @ 2019-11-19 10:21 ` Ahmad Fatoum 0 siblings, 0 replies; 18+ messages in thread From: Ahmad Fatoum @ 2019-11-19 10:21 UTC (permalink / raw) To: Oleksij Rempel, barebox, Sascha Hauer Hello Oleksij, On 11/19/19 10:41 AM, Oleksij Rempel wrote: > Am 19.11.19 um 09:26 schrieb Ahmad Fatoum: >> I am asking because I am testing use of the generic ARM board as default >> second stage image for the multi-image AT91s. The board specific entry point >> generates only the PBL, which runs in SRAM to do DRAM setup and chainloads >> the generic dt barebox from MMC to start of SDRAM and then calls it along >> with the dtb. > > Hm.. Is it possible that you can get an exception vector in the star of SDRAM? Not when I chainload a barebox PBL. In that case, __barebox_arm_head is the start of SDRAM and when barebox reconfigures the vector table, it will be some bytes after that. The exceptions vectors before barebox configures them are probably 0x0 because the ROM code didn't change it. Why are you asking? Cheers Ahmad -- Pengutronix e.K. | | Steuerwalder Str. 21 | http://www.pengutronix.de/ | 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 6/8] ARM: Add generic device tree 2nd stage support 2019-11-19 8:26 ` Ahmad Fatoum 2019-11-19 9:41 ` Oleksij Rempel @ 2019-11-25 7:47 ` Sascha Hauer 1 sibling, 0 replies; 18+ messages in thread From: Sascha Hauer @ 2019-11-25 7:47 UTC (permalink / raw) To: Ahmad Fatoum; +Cc: barebox On Tue, Nov 19, 2019 at 09:26:58AM +0100, Ahmad Fatoum wrote: > Hello Sascha, > > On 8/19/19 3:38 PM, Sascha Hauer wrote: > > +void dt_2nd_aarch64(void *fdt) > > +{ > > + unsigned long image_start = (unsigned long)_text + global_variable_offset(); > > + > > + arm_setup_stack(image_start); > > Shouldn't we rather place the stack somewhere beyond the end of the barebox image > instead of assuming that we can access the memory before the start? Yes, this should be better. barebox is sometimes loaded directly to the start of SDRAM. Sascha -- Pengutronix e.K. | | Steuerwalder Str. 21 | http://www.pengutronix.de/ | 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 7/8] ARM: i.MX: Do not hang() on unknown SoCs 2019-08-19 13:38 [PATCH 0/8] Add support for a generic DT based 2nd stage ARM image Sascha Hauer ` (5 preceding siblings ...) 2019-08-19 13:38 ` [PATCH 6/8] ARM: Add generic device tree 2nd stage support Sascha Hauer @ 2019-08-19 13:38 ` Sascha Hauer 2019-08-19 13:38 ` [PATCH 8/8] ARM: i.MX: When generic DT image is enabled do not hardcode SoC Sascha Hauer 7 siblings, 0 replies; 18+ messages in thread From: Sascha Hauer @ 2019-08-19 13:38 UTC (permalink / raw) To: Barebox List The generic DT image built with CONFIG_ARCH_IMX has nothing really i.MX specific except that it has support for i.MX features. The DT image could be started with a non i.MX device tree which works as expected. imx_init() panics though when started with a non i.MX device tree. Remove the hang() so that we can just continue. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- arch/arm/mach-imx/imx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-imx/imx.c b/arch/arm/mach-imx/imx.c index 63914d306e..ad9b3c4d3e 100644 --- a/arch/arm/mach-imx/imx.c +++ b/arch/arm/mach-imx/imx.c @@ -95,7 +95,7 @@ static int imx_init(void) if (root) { __imx_cpu_type = imx_soc_from_dt(); if (!__imx_cpu_type) - hang(); + return 0; } if (cpu_is_mx1()) -- 2.20.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 8/8] ARM: i.MX: When generic DT image is enabled do not hardcode SoC 2019-08-19 13:38 [PATCH 0/8] Add support for a generic DT based 2nd stage ARM image Sascha Hauer ` (6 preceding siblings ...) 2019-08-19 13:38 ` [PATCH 7/8] ARM: i.MX: Do not hang() on unknown SoCs Sascha Hauer @ 2019-08-19 13:38 ` Sascha Hauer 7 siblings, 0 replies; 18+ messages in thread From: Sascha Hauer @ 2019-08-19 13:38 UTC (permalink / raw) To: Barebox List When only a single i.MX SoC is selected the cpu_is_mx?() macros expand to static 0 or 1. With the generic DT image enabled it could be though that the SoC is not a i.MX at all, so make sure that with the generic DT image enabled the cpu_is_mx?() macros always compare against __imx_cpu_type Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- arch/arm/mach-imx/include/mach/generic.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm/mach-imx/include/mach/generic.h b/arch/arm/mach-imx/include/mach/generic.h index ac066e3f17..5102c34e4c 100644 --- a/arch/arm/mach-imx/include/mach/generic.h +++ b/arch/arm/mach-imx/include/mach/generic.h @@ -223,6 +223,15 @@ extern unsigned int __imx_cpu_type; # define cpu_is_vf610() (0) #endif +#ifdef CONFIG_BOARD_ARM_GENERIC_DT +# ifdef imx_cpu_type +# undef imx_cpu_type +# define imx_cpu_type __imx_cpu_type +# else +# define imx_cpu_type 0 +# endif +#endif + #define cpu_is_mx23() (0) #define cpu_is_mx28() (0) -- 2.20.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2019-11-25 7:47 UTC | newest] Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2019-08-19 13:38 [PATCH 0/8] Add support for a generic DT based 2nd stage ARM image Sascha Hauer 2019-08-19 13:38 ` [PATCH 1/8] dtc: Update update-dtc-source.sh from Linux Sascha Hauer 2019-08-19 13:48 ` Roland Hieber 2019-08-19 13:38 ` [PATCH 2/8] scripts/dtc: Update to upstream version v1.5.0 Sascha Hauer 2019-08-19 13:52 ` Roland Hieber 2019-08-19 13:56 ` Sascha Hauer 2019-08-19 14:09 ` Roland Hieber 2019-09-23 13:39 ` Ahmad Fatoum 2019-08-19 13:38 ` [PATCH 3/8] pbl: Implement strrchr Sascha Hauer 2019-08-19 13:38 ` [PATCH 4/8] Compile libfdt for barebox Sascha Hauer 2019-08-19 13:38 ` [PATCH 5/8] common: return "none" when board unset Sascha Hauer 2019-08-19 13:38 ` [PATCH 6/8] ARM: Add generic device tree 2nd stage support Sascha Hauer 2019-11-19 8:26 ` Ahmad Fatoum 2019-11-19 9:41 ` Oleksij Rempel 2019-11-19 10:21 ` Ahmad Fatoum 2019-11-25 7:47 ` Sascha Hauer 2019-08-19 13:38 ` [PATCH 7/8] ARM: i.MX: Do not hang() on unknown SoCs Sascha Hauer 2019-08-19 13:38 ` [PATCH 8/8] ARM: i.MX: When generic DT image is enabled do not hardcode SoC Sascha Hauer
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox