diff options
| author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2012-10-30 03:09:18 -0400 |
|---|---|---|
| committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2012-10-30 03:09:18 -0400 |
| commit | 68fe0f0a6dcd2ac1ace5da3647a6d1cf0f4d2fea (patch) | |
| tree | 69d855c2e46d42ef8f23680cf3a1e6ff38de9ef4 /scripts | |
| parent | 88fd449e734a4264347e12b8ff74ccb33a9b9a35 (diff) | |
| parent | 8f0d8163b50e01f398b14bcd4dc039ac5ab18d64 (diff) | |
Merge tag 'v3.7-rc3' into for-linus to sync up with recent USB changes
Diffstat (limited to 'scripts')
72 files changed, 6643 insertions, 936 deletions
diff --git a/scripts/.gitignore b/scripts/.gitignore index 65f362d931b5..fb070fa1038f 100644 --- a/scripts/.gitignore +++ b/scripts/.gitignore | |||
| @@ -10,3 +10,4 @@ ihex2fw | |||
| 10 | recordmcount | 10 | recordmcount |
| 11 | docproc | 11 | docproc |
| 12 | sortextable | 12 | sortextable |
| 13 | asn1_compiler | ||
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include index 6a3ee981931d..978416dd31ca 100644 --- a/scripts/Kbuild.include +++ b/scripts/Kbuild.include | |||
| @@ -98,24 +98,24 @@ try-run = $(shell set -e; \ | |||
| 98 | # Usage: cflags-y += $(call as-option,-Wa$(comma)-isa=foo,) | 98 | # Usage: cflags-y += $(call as-option,-Wa$(comma)-isa=foo,) |
| 99 | 99 | ||
| 100 | as-option = $(call try-run,\ | 100 | as-option = $(call try-run,\ |
| 101 | $(CC) $(KBUILD_CFLAGS) $(1) -c -xassembler /dev/null -o "$$TMP",$(1),$(2)) | 101 | $(CC) $(KBUILD_CFLAGS) $(1) -c -x assembler /dev/null -o "$$TMP",$(1),$(2)) |
| 102 | 102 | ||
| 103 | # as-instr | 103 | # as-instr |
| 104 | # Usage: cflags-y += $(call as-instr,instr,option1,option2) | 104 | # Usage: cflags-y += $(call as-instr,instr,option1,option2) |
| 105 | 105 | ||
| 106 | as-instr = $(call try-run,\ | 106 | as-instr = $(call try-run,\ |
| 107 | printf "%b\n" "$(1)" | $(CC) $(KBUILD_AFLAGS) -c -xassembler -o "$$TMP" -,$(2),$(3)) | 107 | printf "%b\n" "$(1)" | $(CC) $(KBUILD_AFLAGS) -c -x assembler -o "$$TMP" -,$(2),$(3)) |
| 108 | 108 | ||
| 109 | # cc-option | 109 | # cc-option |
| 110 | # Usage: cflags-y += $(call cc-option,-march=winchip-c6,-march=i586) | 110 | # Usage: cflags-y += $(call cc-option,-march=winchip-c6,-march=i586) |
| 111 | 111 | ||
| 112 | cc-option = $(call try-run,\ | 112 | cc-option = $(call try-run,\ |
| 113 | $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -xc /dev/null -o "$$TMP",$(1),$(2)) | 113 | $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",$(1),$(2)) |
| 114 | 114 | ||
| 115 | # cc-option-yn | 115 | # cc-option-yn |
| 116 | # Usage: flag := $(call cc-option-yn,-march=winchip-c6) | 116 | # Usage: flag := $(call cc-option-yn,-march=winchip-c6) |
| 117 | cc-option-yn = $(call try-run,\ | 117 | cc-option-yn = $(call try-run,\ |
| 118 | $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -xc /dev/null -o "$$TMP",y,n) | 118 | $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",y,n) |
| 119 | 119 | ||
| 120 | # cc-option-align | 120 | # cc-option-align |
| 121 | # Prefix align with either -falign or -malign | 121 | # Prefix align with either -falign or -malign |
| @@ -125,7 +125,7 @@ cc-option-align = $(subst -functions=0,,\ | |||
| 125 | # cc-disable-warning | 125 | # cc-disable-warning |
| 126 | # Usage: cflags-y += $(call cc-disable-warning,unused-but-set-variable) | 126 | # Usage: cflags-y += $(call cc-disable-warning,unused-but-set-variable) |
| 127 | cc-disable-warning = $(call try-run,\ | 127 | cc-disable-warning = $(call try-run,\ |
| 128 | $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -W$(strip $(1)) -c -xc /dev/null -o "$$TMP",-Wno-$(strip $(1))) | 128 | $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -W$(strip $(1)) -c -x c /dev/null -o "$$TMP",-Wno-$(strip $(1))) |
| 129 | 129 | ||
| 130 | # cc-version | 130 | # cc-version |
| 131 | # Usage gcc-ver := $(call cc-version) | 131 | # Usage gcc-ver := $(call cc-version) |
| @@ -143,7 +143,7 @@ cc-ifversion = $(shell [ $(call cc-version, $(CC)) $(1) $(2) ] && echo $(3)) | |||
| 143 | # cc-ldoption | 143 | # cc-ldoption |
| 144 | # Usage: ldflags += $(call cc-ldoption, -Wl$(comma)--hash-style=both) | 144 | # Usage: ldflags += $(call cc-ldoption, -Wl$(comma)--hash-style=both) |
| 145 | cc-ldoption = $(call try-run,\ | 145 | cc-ldoption = $(call try-run,\ |
| 146 | $(CC) $(1) -nostdlib -xc /dev/null -o "$$TMP",$(1),$(2)) | 146 | $(CC) $(1) -nostdlib -x c /dev/null -o "$$TMP",$(1),$(2)) |
| 147 | 147 | ||
| 148 | # ld-option | 148 | # ld-option |
| 149 | # Usage: LDFLAGS += $(call ld-option, -X) | 149 | # Usage: LDFLAGS += $(call ld-option, -X) |
| @@ -209,7 +209,7 @@ endif | |||
| 209 | # >$< substitution to preserve $ when reloading .cmd file | 209 | # >$< substitution to preserve $ when reloading .cmd file |
| 210 | # note: when using inline perl scripts [perl -e '...$$t=1;...'] | 210 | # note: when using inline perl scripts [perl -e '...$$t=1;...'] |
| 211 | # in $(cmd_xxx) double $$ your perl vars | 211 | # in $(cmd_xxx) double $$ your perl vars |
| 212 | make-cmd = $(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1))))) | 212 | make-cmd = $(subst \\,\\\\,$(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1)))))) |
| 213 | 213 | ||
| 214 | # Find any prerequisites that is newer than target or that does not exist. | 214 | # Find any prerequisites that is newer than target or that does not exist. |
| 215 | # PHONY targets skipped in both cases. | 215 | # PHONY targets skipped in both cases. |
diff --git a/scripts/Makefile b/scripts/Makefile index a55b0067758a..01e7adb838d9 100644 --- a/scripts/Makefile +++ b/scripts/Makefile | |||
| @@ -16,8 +16,10 @@ hostprogs-$(CONFIG_VT) += conmakehash | |||
| 16 | hostprogs-$(CONFIG_IKCONFIG) += bin2c | 16 | hostprogs-$(CONFIG_IKCONFIG) += bin2c |
| 17 | hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount | 17 | hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount |
| 18 | hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable | 18 | hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable |
| 19 | hostprogs-$(CONFIG_ASN1) += asn1_compiler | ||
| 19 | 20 | ||
| 20 | HOSTCFLAGS_sortextable.o = -I$(srctree)/tools/include | 21 | HOSTCFLAGS_sortextable.o = -I$(srctree)/tools/include |
| 22 | HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include | ||
| 21 | 23 | ||
| 22 | always := $(hostprogs-y) $(hostprogs-m) | 24 | always := $(hostprogs-y) $(hostprogs-m) |
| 23 | 25 | ||
diff --git a/scripts/Makefile.asm-generic b/scripts/Makefile.asm-generic index 40caf3c26cd5..d17e0ea911ed 100644 --- a/scripts/Makefile.asm-generic +++ b/scripts/Makefile.asm-generic | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | # and for each file listed in this file with generic-y creates | 5 | # and for each file listed in this file with generic-y creates |
| 6 | # a small wrapper file in $(obj) (arch/$(SRCARCH)/include/generated/asm) | 6 | # a small wrapper file in $(obj) (arch/$(SRCARCH)/include/generated/asm) |
| 7 | 7 | ||
| 8 | kbuild-file := $(srctree)/arch/$(SRCARCH)/include/asm/Kbuild | 8 | kbuild-file := $(srctree)/arch/$(SRCARCH)/include/$(src)/Kbuild |
| 9 | -include $(kbuild-file) | 9 | -include $(kbuild-file) |
| 10 | 10 | ||
| 11 | include scripts/Kbuild.include | 11 | include scripts/Kbuild.include |
diff --git a/scripts/Makefile.build b/scripts/Makefile.build index ff1720d28d0c..0e801c3cdaf8 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build | |||
| @@ -354,6 +354,17 @@ quiet_cmd_cpp_lds_S = LDS $@ | |||
| 354 | $(obj)/%.lds: $(src)/%.lds.S FORCE | 354 | $(obj)/%.lds: $(src)/%.lds.S FORCE |
| 355 | $(call if_changed_dep,cpp_lds_S) | 355 | $(call if_changed_dep,cpp_lds_S) |
| 356 | 356 | ||
| 357 | # ASN.1 grammar | ||
| 358 | # --------------------------------------------------------------------------- | ||
| 359 | quiet_cmd_asn1_compiler = ASN.1 $@ | ||
| 360 | cmd_asn1_compiler = $(objtree)/scripts/asn1_compiler $< \ | ||
| 361 | $(subst .h,.c,$@) $(subst .c,.h,$@) | ||
| 362 | |||
| 363 | .PRECIOUS: $(objtree)/$(obj)/%-asn1.c $(objtree)/$(obj)/%-asn1.h | ||
| 364 | |||
| 365 | $(obj)/%-asn1.c $(obj)/%-asn1.h: $(src)/%.asn1 $(objtree)/scripts/asn1_compiler | ||
| 366 | $(call cmd,asn1_compiler) | ||
| 367 | |||
| 357 | # Build the compiled-in targets | 368 | # Build the compiled-in targets |
| 358 | # --------------------------------------------------------------------------- | 369 | # --------------------------------------------------------------------------- |
| 359 | 370 | ||
diff --git a/scripts/Makefile.fwinst b/scripts/Makefile.fwinst index c3f69ae275d1..4d908d16c035 100644 --- a/scripts/Makefile.fwinst +++ b/scripts/Makefile.fwinst | |||
| @@ -27,7 +27,7 @@ endif | |||
| 27 | installed-mod-fw := $(addprefix $(INSTALL_FW_PATH)/,$(mod-fw)) | 27 | installed-mod-fw := $(addprefix $(INSTALL_FW_PATH)/,$(mod-fw)) |
| 28 | 28 | ||
| 29 | installed-fw := $(addprefix $(INSTALL_FW_PATH)/,$(fw-shipped-all)) | 29 | installed-fw := $(addprefix $(INSTALL_FW_PATH)/,$(fw-shipped-all)) |
| 30 | installed-fw-dirs := $(sort $(dir $(installed-fw))) $(INSTALL_FW_PATH)/. | 30 | installed-fw-dirs := $(sort $(dir $(installed-fw))) $(INSTALL_FW_PATH)/./ |
| 31 | 31 | ||
| 32 | # Workaround for make < 3.81, where .SECONDEXPANSION doesn't work. | 32 | # Workaround for make < 3.81, where .SECONDEXPANSION doesn't work. |
| 33 | PHONY += $(INSTALL_FW_PATH)/$$(%) install-all-dirs | 33 | PHONY += $(INSTALL_FW_PATH)/$$(%) install-all-dirs |
| @@ -42,7 +42,7 @@ quiet_cmd_install = INSTALL $(subst $(srctree)/,,$@) | |||
| 42 | $(installed-fw-dirs): | 42 | $(installed-fw-dirs): |
| 43 | $(call cmd,mkdir) | 43 | $(call cmd,mkdir) |
| 44 | 44 | ||
| 45 | $(installed-fw): $(INSTALL_FW_PATH)/%: $(obj)/% | $$(dir $(INSTALL_FW_PATH)/%) | 45 | $(installed-fw): $(INSTALL_FW_PATH)/%: $(obj)/% | $(INSTALL_FW_PATH)/$$(dir %) |
| 46 | $(call cmd,install) | 46 | $(call cmd,install) |
| 47 | 47 | ||
| 48 | PHONY += __fw_install __fw_modinst FORCE | 48 | PHONY += __fw_install __fw_modinst FORCE |
diff --git a/scripts/Makefile.headersinst b/scripts/Makefile.headersinst index d3bae5e7b601..06ba4a70bd4d 100644 --- a/scripts/Makefile.headersinst +++ b/scripts/Makefile.headersinst | |||
| @@ -3,13 +3,12 @@ | |||
| 3 | # | 3 | # |
| 4 | # header-y - list files to be installed. They are preprocessed | 4 | # header-y - list files to be installed. They are preprocessed |
| 5 | # to remove __KERNEL__ section of the file | 5 | # to remove __KERNEL__ section of the file |
| 6 | # objhdr-y - Same as header-y but for generated files | 6 | # genhdr-y - Same as header-y but in a generated/ directory |
| 7 | # genhdr-y - Same as objhdr-y but in a generated/ directory | ||
| 8 | # | 7 | # |
| 9 | # ========================================================================== | 8 | # ========================================================================== |
| 10 | 9 | ||
| 11 | # called may set destination dir (when installing to asm/) | 10 | # called may set destination dir (when installing to asm/) |
| 12 | _dst := $(if $(dst),$(dst),$(obj)) | 11 | _dst := $(or $(destination-y),$(dst),$(obj)) |
| 13 | 12 | ||
| 14 | # generated header directory | 13 | # generated header directory |
| 15 | gen := $(if $(gen),$(gen),$(subst include/,include/generated/,$(obj))) | 14 | gen := $(if $(gen),$(gen),$(subst include/,include/generated/,$(obj))) |
| @@ -17,49 +16,64 @@ gen := $(if $(gen),$(gen),$(subst include/,include/generated/,$(obj))) | |||
| 17 | kbuild-file := $(srctree)/$(obj)/Kbuild | 16 | kbuild-file := $(srctree)/$(obj)/Kbuild |
| 18 | include $(kbuild-file) | 17 | include $(kbuild-file) |
| 19 | 18 | ||
| 20 | _dst := $(if $(destination-y),$(destination-y),$(_dst)) | 19 | old-kbuild-file := $(srctree)/$(subst uapi/,,$(obj))/Kbuild |
| 20 | ifneq ($(wildcard $(old-kbuild-file)),) | ||
| 21 | include $(old-kbuild-file) | ||
| 22 | endif | ||
| 21 | 23 | ||
| 22 | include scripts/Kbuild.include | 24 | include scripts/Kbuild.include |
| 23 | 25 | ||
| 24 | install := $(INSTALL_HDR_PATH)/$(_dst) | 26 | installdir := $(INSTALL_HDR_PATH)/$(subst uapi/,,$(_dst)) |
| 25 | 27 | ||
| 26 | header-y := $(sort $(header-y)) | 28 | header-y := $(sort $(header-y)) |
| 27 | subdirs := $(patsubst %/,%,$(filter %/, $(header-y))) | 29 | subdirs := $(patsubst %/,%,$(filter %/, $(header-y))) |
| 28 | header-y := $(filter-out %/, $(header-y)) | 30 | header-y := $(filter-out %/, $(header-y)) |
| 29 | 31 | ||
| 30 | # files used to track state of install/check | 32 | # files used to track state of install/check |
| 31 | install-file := $(install)/.install | 33 | install-file := $(installdir)/.install |
| 32 | check-file := $(install)/.check | 34 | check-file := $(installdir)/.check |
| 33 | 35 | ||
| 34 | # generic-y list all files an architecture uses from asm-generic | 36 | # generic-y list all files an architecture uses from asm-generic |
| 35 | # Use this to build a list of headers which require a wrapper | 37 | # Use this to build a list of headers which require a wrapper |
| 36 | wrapper-files := $(filter $(header-y), $(generic-y)) | 38 | wrapper-files := $(filter $(header-y), $(generic-y)) |
| 37 | 39 | ||
| 40 | srcdir := $(srctree)/$(obj) | ||
| 41 | gendir := $(objtree)/$(gen) | ||
| 42 | |||
| 43 | oldsrcdir := $(srctree)/$(subst /uapi,,$(obj)) | ||
| 44 | |||
| 38 | # all headers files for this dir | 45 | # all headers files for this dir |
| 39 | header-y := $(filter-out $(generic-y), $(header-y)) | 46 | header-y := $(filter-out $(generic-y), $(header-y)) |
| 40 | all-files := $(header-y) $(objhdr-y) $(genhdr-y) $(wrapper-files) | 47 | all-files := $(header-y) $(genhdr-y) $(wrapper-files) |
| 41 | input-files := $(addprefix $(srctree)/$(obj)/,$(header-y)) \ | 48 | output-files := $(addprefix $(installdir)/, $(all-files)) |
| 42 | $(addprefix $(objtree)/$(obj)/,$(objhdr-y)) \ | 49 | |
| 43 | $(addprefix $(objtree)/$(gen)/,$(genhdr-y)) | 50 | input-files := $(foreach hdr, $(header-y), \ |
| 44 | output-files := $(addprefix $(install)/, $(all-files)) | 51 | $(or \ |
| 52 | $(wildcard $(srcdir)/$(hdr)), \ | ||
| 53 | $(wildcard $(oldsrcdir)/$(hdr)), \ | ||
| 54 | $(error Missing UAPI file $(srcdir)/$(hdr)) \ | ||
| 55 | )) \ | ||
| 56 | $(foreach hdr, $(genhdr-y), \ | ||
| 57 | $(or \ | ||
| 58 | $(wildcard $(gendir)/$(hdr)), \ | ||
| 59 | $(error Missing generated UAPI file $(gendir)/$(hdr)) \ | ||
| 60 | )) | ||
| 45 | 61 | ||
| 46 | # Work out what needs to be removed | 62 | # Work out what needs to be removed |
| 47 | oldheaders := $(patsubst $(install)/%,%,$(wildcard $(install)/*.h)) | 63 | oldheaders := $(patsubst $(installdir)/%,%,$(wildcard $(installdir)/*.h)) |
| 48 | unwanted := $(filter-out $(all-files),$(oldheaders)) | 64 | unwanted := $(filter-out $(all-files),$(oldheaders)) |
| 49 | 65 | ||
| 50 | # Prefix unwanted with full paths to $(INSTALL_HDR_PATH) | 66 | # Prefix unwanted with full paths to $(INSTALL_HDR_PATH) |
| 51 | unwanted-file := $(addprefix $(install)/, $(unwanted)) | 67 | unwanted-file := $(addprefix $(installdir)/, $(unwanted)) |
| 52 | 68 | ||
| 53 | printdir = $(patsubst $(INSTALL_HDR_PATH)/%/,%,$(dir $@)) | 69 | printdir = $(patsubst $(INSTALL_HDR_PATH)/%/,%,$(dir $@)) |
| 54 | 70 | ||
| 55 | quiet_cmd_install = INSTALL $(printdir) ($(words $(all-files))\ | 71 | quiet_cmd_install = INSTALL $(printdir) ($(words $(all-files))\ |
| 56 | file$(if $(word 2, $(all-files)),s)) | 72 | file$(if $(word 2, $(all-files)),s)) |
| 57 | cmd_install = \ | 73 | cmd_install = \ |
| 58 | $(PERL) $< $(srctree)/$(obj) $(install) $(SRCARCH) $(header-y); \ | 74 | $(PERL) $< $(installdir) $(SRCARCH) $(input-files); \ |
| 59 | $(PERL) $< $(objtree)/$(obj) $(install) $(SRCARCH) $(objhdr-y); \ | ||
| 60 | $(PERL) $< $(objtree)/$(gen) $(install) $(SRCARCH) $(genhdr-y); \ | ||
| 61 | for F in $(wrapper-files); do \ | 75 | for F in $(wrapper-files); do \ |
| 62 | echo "\#include <asm-generic/$$F>" > $(install)/$$F; \ | 76 | echo "\#include <asm-generic/$$F>" > $(installdir)/$$F; \ |
| 63 | done; \ | 77 | done; \ |
| 64 | touch $@ | 78 | touch $@ |
| 65 | 79 | ||
| @@ -70,7 +84,7 @@ quiet_cmd_check = CHECK $(printdir) ($(words $(all-files)) files) | |||
| 70 | # Headers list can be pretty long, xargs helps to avoid | 84 | # Headers list can be pretty long, xargs helps to avoid |
| 71 | # the "Argument list too long" error. | 85 | # the "Argument list too long" error. |
| 72 | cmd_check = for f in $(all-files); do \ | 86 | cmd_check = for f in $(all-files); do \ |
| 73 | echo "$(install)/$${f}"; done \ | 87 | echo "$(installdir)/$${f}"; done \ |
| 74 | | xargs \ | 88 | | xargs \ |
| 75 | $(PERL) $< $(INSTALL_HDR_PATH)/include $(SRCARCH); \ | 89 | $(PERL) $< $(INSTALL_HDR_PATH)/include $(SRCARCH); \ |
| 76 | touch $@ | 90 | touch $@ |
diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst index efa5d940e632..dda4b2b61927 100644 --- a/scripts/Makefile.modinst +++ b/scripts/Makefile.modinst | |||
| @@ -9,7 +9,7 @@ include scripts/Kbuild.include | |||
| 9 | 9 | ||
| 10 | # | 10 | # |
| 11 | 11 | ||
| 12 | __modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod))) | 12 | __modules := $(sort $(shell grep -h '\.ko$$' /dev/null $(wildcard $(MODVERDIR)/*.mod))) |
| 13 | modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o))) | 13 | modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o))) |
| 14 | 14 | ||
| 15 | PHONY += $(modules) | 15 | PHONY += $(modules) |
| @@ -17,7 +17,7 @@ __modinst: $(modules) | |||
| 17 | @: | 17 | @: |
| 18 | 18 | ||
| 19 | quiet_cmd_modules_install = INSTALL $@ | 19 | quiet_cmd_modules_install = INSTALL $@ |
| 20 | cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@) | 20 | cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@) ; $(mod_sign_cmd) $(2)/$(notdir $@) |
| 21 | 21 | ||
| 22 | # Modules built outside the kernel source tree go into extra by default | 22 | # Modules built outside the kernel source tree go into extra by default |
| 23 | INSTALL_MOD_DIR ?= extra | 23 | INSTALL_MOD_DIR ?= extra |
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost index 08dce14f2dc8..a1cb0222ebe6 100644 --- a/scripts/Makefile.modpost +++ b/scripts/Makefile.modpost | |||
| @@ -60,7 +60,7 @@ kernelsymfile := $(objtree)/Module.symvers | |||
| 60 | modulesymfile := $(firstword $(KBUILD_EXTMOD))/Module.symvers | 60 | modulesymfile := $(firstword $(KBUILD_EXTMOD))/Module.symvers |
| 61 | 61 | ||
| 62 | # Step 1), find all modules listed in $(MODVERDIR)/ | 62 | # Step 1), find all modules listed in $(MODVERDIR)/ |
| 63 | __modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod))) | 63 | __modules := $(sort $(shell grep -h '\.ko$$' /dev/null $(wildcard $(MODVERDIR)/*.mod))) |
| 64 | modules := $(patsubst %.o,%.ko, $(wildcard $(__modules:.ko=.o))) | 64 | modules := $(patsubst %.o,%.ko, $(wildcard $(__modules:.ko=.o))) |
| 65 | 65 | ||
| 66 | # Stop after building .o files if NOFINAL is set. Makes compile tests quicker | 66 | # Stop after building .o files if NOFINAL is set. Makes compile tests quicker |
diff --git a/scripts/asn1_compiler.c b/scripts/asn1_compiler.c new file mode 100644 index 000000000000..db0e5cd34c70 --- /dev/null +++ b/scripts/asn1_compiler.c | |||
| @@ -0,0 +1,1545 @@ | |||
| 1 | /* Simplified ASN.1 notation parser | ||
| 2 | * | ||
| 3 | * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public Licence | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the Licence, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <stdarg.h> | ||
| 13 | #include <stdio.h> | ||
| 14 | #include <stdlib.h> | ||
| 15 | #include <stdint.h> | ||
| 16 | #include <string.h> | ||
| 17 | #include <ctype.h> | ||
| 18 | #include <unistd.h> | ||
| 19 | #include <fcntl.h> | ||
| 20 | #include <sys/stat.h> | ||
| 21 | #include <linux/asn1_ber_bytecode.h> | ||
| 22 | |||
| 23 | enum token_type { | ||
| 24 | DIRECTIVE_ABSENT, | ||
| 25 | DIRECTIVE_ALL, | ||
| 26 | DIRECTIVE_ANY, | ||
| 27 | DIRECTIVE_APPLICATION, | ||
| 28 | DIRECTIVE_AUTOMATIC, | ||
| 29 | DIRECTIVE_BEGIN, | ||
| 30 | DIRECTIVE_BIT, | ||
| 31 | DIRECTIVE_BMPString, | ||
| 32 | DIRECTIVE_BOOLEAN, | ||
| 33 | DIRECTIVE_BY, | ||
| 34 | DIRECTIVE_CHARACTER, | ||
| 35 | DIRECTIVE_CHOICE, | ||
| 36 | DIRECTIVE_CLASS, | ||
| 37 | DIRECTIVE_COMPONENT, | ||
| 38 | DIRECTIVE_COMPONENTS, | ||
| 39 | DIRECTIVE_CONSTRAINED, | ||
| 40 | DIRECTIVE_CONTAINING, | ||
| 41 | DIRECTIVE_DEFAULT, | ||
| 42 | DIRECTIVE_DEFINED, | ||
| 43 | DIRECTIVE_DEFINITIONS, | ||
| 44 | DIRECTIVE_EMBEDDED, | ||
| 45 | DIRECTIVE_ENCODED, | ||
| 46 | DIRECTIVE_ENCODING_CONTROL, | ||
| 47 | DIRECTIVE_END, | ||
| 48 | DIRECTIVE_ENUMERATED, | ||
| 49 | DIRECTIVE_EXCEPT, | ||
| 50 | DIRECTIVE_EXPLICIT, | ||
| 51 | DIRECTIVE_EXPORTS, | ||
| 52 | DIRECTIVE_EXTENSIBILITY, | ||
| 53 | DIRECTIVE_EXTERNAL, | ||
| 54 | DIRECTIVE_FALSE, | ||
| 55 | DIRECTIVE_FROM, | ||
| 56 | DIRECTIVE_GeneralString, | ||
| 57 | DIRECTIVE_GeneralizedTime, | ||
| 58 | DIRECTIVE_GraphicString, | ||
| 59 | DIRECTIVE_IA5String, | ||
| 60 | DIRECTIVE_IDENTIFIER, | ||
| 61 | DIRECTIVE_IMPLICIT, | ||
| 62 | DIRECTIVE_IMPLIED, | ||
| 63 | DIRECTIVE_IMPORTS, | ||
| 64 | DIRECTIVE_INCLUDES, | ||
| 65 | DIRECTIVE_INSTANCE, | ||
| 66 | DIRECTIVE_INSTRUCTIONS, | ||
| 67 | DIRECTIVE_INTEGER, | ||
| 68 | DIRECTIVE_INTERSECTION, | ||
| 69 | DIRECTIVE_ISO646String, | ||
| 70 | DIRECTIVE_MAX, | ||
| 71 | DIRECTIVE_MIN, | ||
| 72 | DIRECTIVE_MINUS_INFINITY, | ||
| 73 | DIRECTIVE_NULL, | ||
| 74 | DIRECTIVE_NumericString, | ||
| 75 | DIRECTIVE_OBJECT, | ||
| 76 | DIRECTIVE_OCTET, | ||
| 77 | DIRECTIVE_OF, | ||
| 78 | DIRECTIVE_OPTIONAL, | ||
| 79 | DIRECTIVE_ObjectDescriptor, | ||
| 80 | DIRECTIVE_PATTERN, | ||
| 81 | DIRECTIVE_PDV, | ||
| 82 | DIRECTIVE_PLUS_INFINITY, | ||
| 83 | DIRECTIVE_PRESENT, | ||
| 84 | DIRECTIVE_PRIVATE, | ||
| 85 | DIRECTIVE_PrintableString, | ||
| 86 | DIRECTIVE_REAL, | ||
| 87 | DIRECTIVE_RELATIVE_OID, | ||
| 88 | DIRECTIVE_SEQUENCE, | ||
| 89 | DIRECTIVE_SET, | ||
| 90 | DIRECTIVE_SIZE, | ||
| 91 | DIRECTIVE_STRING, | ||
| 92 | DIRECTIVE_SYNTAX, | ||
| 93 | DIRECTIVE_T61String, | ||
| 94 | DIRECTIVE_TAGS, | ||
| 95 | DIRECTIVE_TRUE, | ||
| 96 | DIRECTIVE_TeletexString, | ||
| 97 | DIRECTIVE_UNION, | ||
| 98 | DIRECTIVE_UNIQUE, | ||
| 99 | DIRECTIVE_UNIVERSAL, | ||
| 100 | DIRECTIVE_UTCTime, | ||
| 101 | DIRECTIVE_UTF8String, | ||
| 102 | DIRECTIVE_UniversalString, | ||
| 103 | DIRECTIVE_VideotexString, | ||
| 104 | DIRECTIVE_VisibleString, | ||
| 105 | DIRECTIVE_WITH, | ||
| 106 | NR__DIRECTIVES, | ||
| 107 | TOKEN_ASSIGNMENT = NR__DIRECTIVES, | ||
| 108 | TOKEN_OPEN_CURLY, | ||
| 109 | TOKEN_CLOSE_CURLY, | ||
| 110 | TOKEN_OPEN_SQUARE, | ||
| 111 | TOKEN_CLOSE_SQUARE, | ||
| 112 | TOKEN_OPEN_ACTION, | ||
| 113 | TOKEN_CLOSE_ACTION, | ||
| 114 | TOKEN_COMMA, | ||
| 115 | TOKEN_NUMBER, | ||
| 116 | TOKEN_TYPE_NAME, | ||
| 117 | TOKEN_ELEMENT_NAME, | ||
| 118 | NR__TOKENS | ||
| 119 | }; | ||
| 120 | |||
| 121 | static const unsigned char token_to_tag[NR__TOKENS] = { | ||
| 122 | /* EOC goes first */ | ||
| 123 | [DIRECTIVE_BOOLEAN] = ASN1_BOOL, | ||
| 124 | [DIRECTIVE_INTEGER] = ASN1_INT, | ||
| 125 | [DIRECTIVE_BIT] = ASN1_BTS, | ||
| 126 | [DIRECTIVE_OCTET] = ASN1_OTS, | ||
| 127 | [DIRECTIVE_NULL] = ASN1_NULL, | ||
| 128 | [DIRECTIVE_OBJECT] = ASN1_OID, | ||
| 129 | [DIRECTIVE_ObjectDescriptor] = ASN1_ODE, | ||
| 130 | [DIRECTIVE_EXTERNAL] = ASN1_EXT, | ||
| 131 | [DIRECTIVE_REAL] = ASN1_REAL, | ||
| 132 | [DIRECTIVE_ENUMERATED] = ASN1_ENUM, | ||
| 133 | [DIRECTIVE_EMBEDDED] = 0, | ||
| 134 | [DIRECTIVE_UTF8String] = ASN1_UTF8STR, | ||
| 135 | [DIRECTIVE_RELATIVE_OID] = ASN1_RELOID, | ||
| 136 | /* 14 */ | ||
| 137 | /* 15 */ | ||
| 138 | [DIRECTIVE_SEQUENCE] = ASN1_SEQ, | ||
| 139 | [DIRECTIVE_SET] = ASN1_SET, | ||
| 140 | [DIRECTIVE_NumericString] = ASN1_NUMSTR, | ||
| 141 | [DIRECTIVE_PrintableString] = ASN1_PRNSTR, | ||
| 142 | [DIRECTIVE_T61String] = ASN1_TEXSTR, | ||
| 143 | [DIRECTIVE_TeletexString] = ASN1_TEXSTR, | ||
| 144 | [DIRECTIVE_VideotexString] = ASN1_VIDSTR, | ||
| 145 | [DIRECTIVE_IA5String] = ASN1_IA5STR, | ||
| 146 | [DIRECTIVE_UTCTime] = ASN1_UNITIM, | ||
| 147 | [DIRECTIVE_GeneralizedTime] = ASN1_GENTIM, | ||
| 148 | [DIRECTIVE_GraphicString] = ASN1_GRASTR, | ||
| 149 | [DIRECTIVE_VisibleString] = ASN1_VISSTR, | ||
| 150 | [DIRECTIVE_GeneralString] = ASN1_GENSTR, | ||
| 151 | [DIRECTIVE_UniversalString] = ASN1_UNITIM, | ||
| 152 | [DIRECTIVE_CHARACTER] = ASN1_CHRSTR, | ||
| 153 | [DIRECTIVE_BMPString] = ASN1_BMPSTR, | ||
| 154 | }; | ||
| 155 | |||
| 156 | static const char asn1_classes[4][5] = { | ||
| 157 | [ASN1_UNIV] = "UNIV", | ||
| 158 | [ASN1_APPL] = "APPL", | ||
| 159 | [ASN1_CONT] = "CONT", | ||
| 160 | [ASN1_PRIV] = "PRIV" | ||
| 161 | }; | ||
| 162 | |||
| 163 | static const char asn1_methods[2][5] = { | ||
| 164 | [ASN1_UNIV] = "PRIM", | ||
| 165 | [ASN1_APPL] = "CONS" | ||
| 166 | }; | ||
| 167 | |||
| 168 | static const char *const asn1_universal_tags[32] = { | ||
| 169 | "EOC", | ||
| 170 | "BOOL", | ||
| 171 | "INT", | ||
| 172 | "BTS", | ||
| 173 | "OTS", | ||
| 174 | "NULL", | ||
| 175 | "OID", | ||
| 176 | "ODE", | ||
| 177 | "EXT", | ||
| 178 | "REAL", | ||
| 179 | "ENUM", | ||
| 180 | "EPDV", | ||
| 181 | "UTF8STR", | ||
| 182 | "RELOID", | ||
| 183 | NULL, /* 14 */ | ||
| 184 | NULL, /* 15 */ | ||
| 185 | "SEQ", | ||
| 186 | "SET", | ||
| 187 | "NUMSTR", | ||
| 188 | "PRNSTR", | ||
| 189 | "TEXSTR", | ||
| 190 | "VIDSTR", | ||
| 191 | "IA5STR", | ||
| 192 | "UNITIM", | ||
| 193 | "GENTIM", | ||
| 194 | "GRASTR", | ||
| 195 | "VISSTR", | ||
| 196 | "GENSTR", | ||
| 197 | "UNISTR", | ||
| 198 | "CHRSTR", | ||
| 199 | "BMPSTR", | ||
| 200 | NULL /* 31 */ | ||
| 201 | }; | ||
| 202 | |||
| 203 | static const char *filename; | ||
| 204 | static const char *grammar_name; | ||
| 205 | static const char *outputname; | ||
| 206 | static const char *headername; | ||
| 207 | |||
| 208 | static const char *const directives[NR__DIRECTIVES] = { | ||
| 209 | #define _(X) [DIRECTIVE_##X] = #X | ||
| 210 | _(ABSENT), | ||
| 211 | _(ALL), | ||
| 212 | _(ANY), | ||
| 213 | _(APPLICATION), | ||
| 214 | _(AUTOMATIC), | ||
| 215 | _(BEGIN), | ||
| 216 | _(BIT), | ||
| 217 | _(BMPString), | ||
| 218 | _(BOOLEAN), | ||
| 219 | _(BY), | ||
| 220 | _(CHARACTER), | ||
| 221 | _(CHOICE), | ||
| 222 | _(CLASS), | ||
| 223 | _(COMPONENT), | ||
| 224 | _(COMPONENTS), | ||
| 225 | _(CONSTRAINED), | ||
| 226 | _(CONTAINING), | ||
| 227 | _(DEFAULT), | ||
| 228 | _(DEFINED), | ||
| 229 | _(DEFINITIONS), | ||
| 230 | _(EMBEDDED), | ||
| 231 | _(ENCODED), | ||
| 232 | [DIRECTIVE_ENCODING_CONTROL] = "ENCODING-CONTROL", | ||
| 233 | _(END), | ||
| 234 | _(ENUMERATED), | ||
| 235 | _(EXCEPT), | ||
| 236 | _(EXPLICIT), | ||
| 237 | _(EXPORTS), | ||
| 238 | _(EXTENSIBILITY), | ||
| 239 | _(EXTERNAL), | ||
| 240 | _(FALSE), | ||
| 241 | _(FROM), | ||
| 242 | _(GeneralString), | ||
| 243 | _(GeneralizedTime), | ||
| 244 | _(GraphicString), | ||
| 245 | _(IA5String), | ||
| 246 | _(IDENTIFIER), | ||
| 247 | _(IMPLICIT), | ||
| 248 | _(IMPLIED), | ||
| 249 | _(IMPORTS), | ||
| 250 | _(INCLUDES), | ||
| 251 | _(INSTANCE), | ||
| 252 | _(INSTRUCTIONS), | ||
| 253 | _(INTEGER), | ||
| 254 | _(INTERSECTION), | ||
| 255 | _(ISO646String), | ||
| 256 | _(MAX), | ||
| 257 | _(MIN), | ||
| 258 | [DIRECTIVE_MINUS_INFINITY] = "MINUS-INFINITY", | ||
| 259 | [DIRECTIVE_NULL] = "NULL", | ||
| 260 | _(NumericString), | ||
| 261 | _(OBJECT), | ||
| 262 | _(OCTET), | ||
| 263 | _(OF), | ||
| 264 | _(OPTIONAL), | ||
| 265 | _(ObjectDescriptor), | ||
| 266 | _(PATTERN), | ||
| 267 | _(PDV), | ||
| 268 | [DIRECTIVE_PLUS_INFINITY] = "PLUS-INFINITY", | ||
| 269 | _(PRESENT), | ||
| 270 | _(PRIVATE), | ||
| 271 | _(PrintableString), | ||
| 272 | _(REAL), | ||
| 273 | [DIRECTIVE_RELATIVE_OID] = "RELATIVE-OID", | ||
| 274 | _(SEQUENCE), | ||
| 275 | _(SET), | ||
| 276 | _(SIZE), | ||
| 277 | _(STRING), | ||
| 278 | _(SYNTAX), | ||
| 279 | _(T61String), | ||
| 280 | _(TAGS), | ||
| 281 | _(TRUE), | ||
| 282 | _(TeletexString), | ||
| 283 | _(UNION), | ||
| 284 | _(UNIQUE), | ||
| 285 | _(UNIVERSAL), | ||
| 286 | _(UTCTime), | ||
| 287 | _(UTF8String), | ||
| 288 | _(UniversalString), | ||
| 289 | _(VideotexString), | ||
| 290 | _(VisibleString), | ||
| 291 | _(WITH) | ||
| 292 | }; | ||
| 293 | |||
| 294 | struct action { | ||
| 295 | struct action *next; | ||
| 296 | unsigned char index; | ||
| 297 | char name[]; | ||
| 298 | }; | ||
| 299 | |||
| 300 | static struct action *action_list; | ||
| 301 | static unsigned nr_actions; | ||
| 302 | |||
| 303 | struct token { | ||
| 304 | unsigned short line; | ||
| 305 | enum token_type token_type : 8; | ||
| 306 | unsigned char size; | ||
| 307 | struct action *action; | ||
| 308 | const char *value; | ||
| 309 | struct type *type; | ||
| 310 | }; | ||
| 311 | |||
| 312 | static struct token *token_list; | ||
| 313 | static unsigned nr_tokens; | ||
| 314 | |||
| 315 | static int directive_compare(const void *_key, const void *_pdir) | ||
| 316 | { | ||
| 317 | const struct token *token = _key; | ||
| 318 | const char *const *pdir = _pdir, *dir = *pdir; | ||
| 319 | size_t dlen, clen; | ||
| 320 | int val; | ||
| 321 | |||
| 322 | dlen = strlen(dir); | ||
| 323 | clen = (dlen < token->size) ? dlen : token->size; | ||
| 324 | |||
| 325 | //printf("cmp(%*.*s,%s) = ", | ||
| 326 | // (int)token->size, (int)token->size, token->value, | ||
| 327 | // dir); | ||
| 328 | |||
| 329 | val = memcmp(token->value, dir, clen); | ||
| 330 | if (val != 0) { | ||
| 331 | //printf("%d [cmp]\n", val); | ||
| 332 | return val; | ||
| 333 | } | ||
| 334 | |||
| 335 | if (dlen == token->size) { | ||
| 336 | //printf("0\n"); | ||
| 337 | return 0; | ||
| 338 | } | ||
| 339 | //printf("%d\n", (int)dlen - (int)token->size); | ||
| 340 | return dlen - token->size; /* shorter -> negative */ | ||
| 341 | } | ||
| 342 | |||
| 343 | /* | ||
| 344 | * Tokenise an ASN.1 grammar | ||
| 345 | */ | ||
| 346 | static void tokenise(char *buffer, char *end) | ||
| 347 | { | ||
| 348 | struct token *tokens; | ||
| 349 | char *line, *nl, *p, *q; | ||
| 350 | unsigned tix, lineno; | ||
| 351 | |||
| 352 | /* Assume we're going to have half as many tokens as we have | ||
| 353 | * characters | ||
| 354 | */ | ||
| 355 | token_list = tokens = calloc((end - buffer) / 2, sizeof(struct token)); | ||
| 356 | if (!tokens) { | ||
| 357 | perror(NULL); | ||
| 358 | exit(1); | ||
| 359 | } | ||
| 360 | tix = 0; | ||
| 361 | |||
| 362 | lineno = 0; | ||
| 363 | while (buffer < end) { | ||
| 364 | /* First of all, break out a line */ | ||
| 365 | lineno++; | ||
| 366 | line = buffer; | ||
| 367 | nl = memchr(line, '\n', end - buffer); | ||
| 368 | if (!nl) { | ||
| 369 | buffer = nl = end; | ||
| 370 | } else { | ||
| 371 | buffer = nl + 1; | ||
| 372 | *nl = '\0'; | ||
| 373 | } | ||
| 374 | |||
| 375 | /* Remove "--" comments */ | ||
| 376 | p = line; | ||
| 377 | next_comment: | ||
| 378 | while ((p = memchr(p, '-', nl - p))) { | ||
| 379 | if (p[1] == '-') { | ||
| 380 | /* Found a comment; see if there's a terminator */ | ||
| 381 | q = p + 2; | ||
| 382 | while ((q = memchr(q, '-', nl - q))) { | ||
| 383 | if (q[1] == '-') { | ||
| 384 | /* There is - excise the comment */ | ||
| 385 | q += 2; | ||
| 386 | memmove(p, q, nl - q); | ||
| 387 | goto next_comment; | ||
| 388 | } | ||
| 389 | q++; | ||
| 390 | } | ||
| 391 | *p = '\0'; | ||
| 392 | nl = p; | ||
| 393 | break; | ||
| 394 | } else { | ||
| 395 | p++; | ||
| 396 | } | ||
| 397 | } | ||
| 398 | |||
| 399 | p = line; | ||
| 400 | while (p < nl) { | ||
| 401 | /* Skip white space */ | ||
| 402 | while (p < nl && isspace(*p)) | ||
| 403 | *(p++) = 0; | ||
| 404 | if (p >= nl) | ||
| 405 | break; | ||
| 406 | |||
| 407 | tokens[tix].line = lineno; | ||
| 408 | tokens[tix].value = p; | ||
| 409 | |||
| 410 | /* Handle string tokens */ | ||
| 411 | if (isalpha(*p)) { | ||
| 412 | const char **dir; | ||
| 413 | |||
| 414 | /* Can be a directive, type name or element | ||
| 415 | * name. Find the end of the name. | ||
| 416 | */ | ||
| 417 | q = p + 1; | ||
| 418 | while (q < nl && (isalnum(*q) || *q == '-' || *q == '_')) | ||
| 419 | q++; | ||
| 420 | tokens[tix].size = q - p; | ||
| 421 | p = q; | ||
| 422 | |||
| 423 | /* If it begins with a lowercase letter then | ||
| 424 | * it's an element name | ||
| 425 | */ | ||
| 426 | if (islower(tokens[tix].value[0])) { | ||
| 427 | tokens[tix++].token_type = TOKEN_ELEMENT_NAME; | ||
| 428 | continue; | ||
| 429 | } | ||
| 430 | |||
| 431 | /* Otherwise we need to search the directive | ||
| 432 | * table | ||
| 433 | */ | ||
| 434 | dir = bsearch(&tokens[tix], directives, | ||
| 435 | sizeof(directives) / sizeof(directives[1]), | ||
| 436 | sizeof(directives[1]), | ||
| 437 | directive_compare); | ||
| 438 | if (dir) { | ||
| 439 | tokens[tix++].token_type = dir - directives; | ||
| 440 | continue; | ||
| 441 | } | ||
| 442 | |||
| 443 | tokens[tix++].token_type = TOKEN_TYPE_NAME; | ||
| 444 | continue; | ||
| 445 | } | ||
| 446 | |||
| 447 | /* Handle numbers */ | ||
| 448 | if (isdigit(*p)) { | ||
| 449 | /* Find the end of the number */ | ||
| 450 | q = p + 1; | ||
| 451 | while (q < nl && (isdigit(*q))) | ||
| 452 | q++; | ||
| 453 | tokens[tix].size = q - p; | ||
| 454 | p = q; | ||
| 455 | tokens[tix++].token_type = TOKEN_NUMBER; | ||
| 456 | continue; | ||
| 457 | } | ||
| 458 | |||
| 459 | if (nl - p >= 3) { | ||
| 460 | if (memcmp(p, "::=", 3) == 0) { | ||
| 461 | p += 3; | ||
| 462 | tokens[tix].size = 3; | ||
| 463 | tokens[tix++].token_type = TOKEN_ASSIGNMENT; | ||
| 464 | continue; | ||
| 465 | } | ||
| 466 | } | ||
| 467 | |||
| 468 | if (nl - p >= 2) { | ||
| 469 | if (memcmp(p, "({", 2) == 0) { | ||
| 470 | p += 2; | ||
| 471 | tokens[tix].size = 2; | ||
| 472 | tokens[tix++].token_type = TOKEN_OPEN_ACTION; | ||
| 473 | continue; | ||
| 474 | } | ||
| 475 | if (memcmp(p, "})", 2) == 0) { | ||
| 476 | p += 2; | ||
| 477 | tokens[tix].size = 2; | ||
| 478 | tokens[tix++].token_type = TOKEN_CLOSE_ACTION; | ||
| 479 | continue; | ||
| 480 | } | ||
| 481 | } | ||
| 482 | |||
| 483 | if (nl - p >= 1) { | ||
| 484 | tokens[tix].size = 1; | ||
| 485 | switch (*p) { | ||
| 486 | case '{': | ||
| 487 | p += 1; | ||
| 488 | tokens[tix++].token_type = TOKEN_OPEN_CURLY; | ||
| 489 | continue; | ||
| 490 | case '}': | ||
| 491 | p += 1; | ||
| 492 | tokens[tix++].token_type = TOKEN_CLOSE_CURLY; | ||
| 493 | continue; | ||
| 494 | case '[': | ||
| 495 | p += 1; | ||
| 496 | tokens[tix++].token_type = TOKEN_OPEN_SQUARE; | ||
| 497 | continue; | ||
| 498 | case ']': | ||
| 499 | p += 1; | ||
| 500 | tokens[tix++].token_type = TOKEN_CLOSE_SQUARE; | ||
| 501 | continue; | ||
| 502 | case ',': | ||
| 503 | p += 1; | ||
| 504 | tokens[tix++].token_type = TOKEN_COMMA; | ||
| 505 | continue; | ||
| 506 | default: | ||
| 507 | break; | ||
| 508 | } | ||
| 509 | } | ||
| 510 | |||
| 511 | fprintf(stderr, "%s:%u: Unknown character in grammar: '%c'\n", | ||
| 512 | filename, lineno, *p); | ||
| 513 | exit(1); | ||
| 514 | } | ||
| 515 | } | ||
| 516 | |||
| 517 | nr_tokens = tix; | ||
| 518 | printf("Extracted %u tokens\n", nr_tokens); | ||
| 519 | |||
| 520 | #if 0 | ||
| 521 | { | ||
| 522 | int n; | ||
| 523 | for (n = 0; n < nr_tokens; n++) | ||
| 524 | printf("Token %3u: '%*.*s'\n", | ||
| 525 | n, | ||
| 526 | (int)token_list[n].size, (int)token_list[n].size, | ||
| 527 | token_list[n].value); | ||
| 528 | } | ||
| 529 | #endif | ||
| 530 | } | ||
| 531 | |||
| 532 | static void build_type_list(void); | ||
| 533 | static void parse(void); | ||
| 534 | static void render(FILE *out, FILE *hdr); | ||
| 535 | |||
| 536 | /* | ||
| 537 | * | ||
| 538 | */ | ||
| 539 | int main(int argc, char **argv) | ||
| 540 | { | ||
| 541 | struct stat st; | ||
| 542 | ssize_t readlen; | ||
| 543 | FILE *out, *hdr; | ||
| 544 | char *buffer, *p; | ||
| 545 | int fd; | ||
| 546 | |||
| 547 | if (argc != 4) { | ||
| 548 | fprintf(stderr, "Format: %s <grammar-file> <c-file> <hdr-file>\n", | ||
| 549 | argv[0]); | ||
| 550 | exit(2); | ||
| 551 | } | ||
| 552 | |||
| 553 | filename = argv[1]; | ||
| 554 | outputname = argv[2]; | ||
| 555 | headername = argv[3]; | ||
| 556 | |||
| 557 | fd = open(filename, O_RDONLY); | ||
| 558 | if (fd < 0) { | ||
| 559 | perror(filename); | ||
| 560 | exit(1); | ||
| 561 | } | ||
| 562 | |||
| 563 | if (fstat(fd, &st) < 0) { | ||
| 564 | perror(filename); | ||
| 565 | exit(1); | ||
| 566 | } | ||
| 567 | |||
| 568 | if (!(buffer = malloc(st.st_size + 1))) { | ||
| 569 | perror(NULL); | ||
| 570 | exit(1); | ||
| 571 | } | ||
| 572 | |||
| 573 | if ((readlen = read(fd, buffer, st.st_size)) < 0) { | ||
| 574 | perror(filename); | ||
| 575 | exit(1); | ||
| 576 | } | ||
| 577 | |||
| 578 | if (close(fd) < 0) { | ||
| 579 | perror(filename); | ||
| 580 | exit(1); | ||
| 581 | } | ||
| 582 | |||
| 583 | if (readlen != st.st_size) { | ||
| 584 | fprintf(stderr, "%s: Short read\n", filename); | ||
| 585 | exit(1); | ||
| 586 | } | ||
| 587 | |||
| 588 | p = strrchr(argv[1], '/'); | ||
| 589 | p = p ? p + 1 : argv[1]; | ||
| 590 | grammar_name = strdup(p); | ||
| 591 | if (!p) { | ||
| 592 | perror(NULL); | ||
| 593 | exit(1); | ||
| 594 | } | ||
| 595 | p = strchr(grammar_name, '.'); | ||
| 596 | if (p) | ||
| 597 | *p = '\0'; | ||
| 598 | |||
| 599 | buffer[readlen] = 0; | ||
| 600 | tokenise(buffer, buffer + readlen); | ||
| 601 | build_type_list(); | ||
| 602 | parse(); | ||
| 603 | |||
| 604 | out = fopen(outputname, "w"); | ||
| 605 | if (!out) { | ||
| 606 | perror(outputname); | ||
| 607 | exit(1); | ||
| 608 | } | ||
| 609 | |||
| 610 | hdr = fopen(headername, "w"); | ||
| 611 | if (!out) { | ||
| 612 | perror(headername); | ||
| 613 | exit(1); | ||
| 614 | } | ||
| 615 | |||
| 616 | render(out, hdr); | ||
| 617 | |||
| 618 | if (fclose(out) < 0) { | ||
| 619 | perror(outputname); | ||
| 620 | exit(1); | ||
| 621 | } | ||
| 622 | |||
| 623 | if (fclose(hdr) < 0) { | ||
| 624 | perror(headername); | ||
| 625 | exit(1); | ||
| 626 | } | ||
| 627 | |||
| 628 | return 0; | ||
| 629 | } | ||
| 630 | |||
| 631 | enum compound { | ||
| 632 | NOT_COMPOUND, | ||
| 633 | SET, | ||
| 634 | SET_OF, | ||
| 635 | SEQUENCE, | ||
| 636 | SEQUENCE_OF, | ||
| 637 | CHOICE, | ||
| 638 | ANY, | ||
| 639 | TYPE_REF, | ||
| 640 | TAG_OVERRIDE | ||
| 641 | }; | ||
| 642 | |||
| 643 | struct element { | ||
| 644 | struct type *type_def; | ||
| 645 | struct token *name; | ||
| 646 | struct token *type; | ||
| 647 | struct action *action; | ||
| 648 | struct element *children; | ||
| 649 | struct element *next; | ||
| 650 | struct element *render_next; | ||
| 651 | struct element *list_next; | ||
| 652 | uint8_t n_elements; | ||
| 653 | enum compound compound : 8; | ||
| 654 | enum asn1_class class : 8; | ||
| 655 | enum asn1_method method : 8; | ||
| 656 | uint8_t tag; | ||
| 657 | unsigned entry_index; | ||
| 658 | unsigned flags; | ||
| 659 | #define ELEMENT_IMPLICIT 0x0001 | ||
| 660 | #define ELEMENT_EXPLICIT 0x0002 | ||
| 661 | #define ELEMENT_MARKED 0x0004 | ||
| 662 | #define ELEMENT_RENDERED 0x0008 | ||
| 663 | #define ELEMENT_SKIPPABLE 0x0010 | ||
| 664 | #define ELEMENT_CONDITIONAL 0x0020 | ||
| 665 | }; | ||
| 666 | |||
| 667 | struct type { | ||
| 668 | struct token *name; | ||
| 669 | struct token *def; | ||
| 670 | struct element *element; | ||
| 671 | unsigned ref_count; | ||
| 672 | unsigned flags; | ||
| 673 | #define TYPE_STOP_MARKER 0x0001 | ||
| 674 | #define TYPE_BEGIN 0x0002 | ||
| 675 | }; | ||
| 676 | |||
| 677 | static struct type *type_list; | ||
| 678 | static struct type **type_index; | ||
| 679 | static unsigned nr_types; | ||
| 680 | |||
| 681 | static int type_index_compare(const void *_a, const void *_b) | ||
| 682 | { | ||
| 683 | const struct type *const *a = _a, *const *b = _b; | ||
| 684 | |||
| 685 | if ((*a)->name->size != (*b)->name->size) | ||
| 686 | return (*a)->name->size - (*b)->name->size; | ||
| 687 | else | ||
| 688 | return memcmp((*a)->name->value, (*b)->name->value, | ||
| 689 | (*a)->name->size); | ||
| 690 | } | ||
| 691 | |||
| 692 | static int type_finder(const void *_key, const void *_ti) | ||
| 693 | { | ||
| 694 | const struct token *token = _key; | ||
| 695 | const struct type *const *ti = _ti; | ||
| 696 | const struct type *type = *ti; | ||
| 697 | |||
| 698 | if (token->size != type->name->size) | ||
| 699 | return token->size - type->name->size; | ||
| 700 | else | ||
| 701 | return memcmp(token->value, type->name->value, | ||
| 702 | token->size); | ||
| 703 | } | ||
| 704 | |||
| 705 | /* | ||
| 706 | * Build up a list of types and a sorted index to that list. | ||
| 707 | */ | ||
| 708 | static void build_type_list(void) | ||
| 709 | { | ||
| 710 | struct type *types; | ||
| 711 | unsigned nr, t, n; | ||
| 712 | |||
| 713 | nr = 0; | ||
| 714 | for (n = 0; n < nr_tokens - 1; n++) | ||
| 715 | if (token_list[n + 0].token_type == TOKEN_TYPE_NAME && | ||
| 716 | token_list[n + 1].token_type == TOKEN_ASSIGNMENT) | ||
| 717 | nr++; | ||
| 718 | |||
| 719 | if (nr == 0) { | ||
| 720 | fprintf(stderr, "%s: No defined types\n", filename); | ||
| 721 | exit(1); | ||
| 722 | } | ||
| 723 | |||
| 724 | nr_types = nr; | ||
| 725 | types = type_list = calloc(nr + 1, sizeof(type_list[0])); | ||
| 726 | if (!type_list) { | ||
| 727 | perror(NULL); | ||
| 728 | exit(1); | ||
| 729 | } | ||
| 730 | type_index = calloc(nr, sizeof(type_index[0])); | ||
| 731 | if (!type_index) { | ||
| 732 | perror(NULL); | ||
| 733 | exit(1); | ||
| 734 | } | ||
| 735 | |||
| 736 | t = 0; | ||
| 737 | types[t].flags |= TYPE_BEGIN; | ||
| 738 | for (n = 0; n < nr_tokens - 1; n++) { | ||
| 739 | if (token_list[n + 0].token_type == TOKEN_TYPE_NAME && | ||
| 740 | token_list[n + 1].token_type == TOKEN_ASSIGNMENT) { | ||
| 741 | types[t].name = &token_list[n]; | ||
| 742 | type_index[t] = &types[t]; | ||
| 743 | t++; | ||
| 744 | } | ||
| 745 | } | ||
| 746 | types[t].name = &token_list[n + 1]; | ||
| 747 | types[t].flags |= TYPE_STOP_MARKER; | ||
| 748 | |||
| 749 | qsort(type_index, nr, sizeof(type_index[0]), type_index_compare); | ||
| 750 | |||
| 751 | printf("Extracted %u types\n", nr_types); | ||
| 752 | #if 0 | ||
| 753 | for (n = 0; n < nr_types; n++) { | ||
| 754 | struct type *type = type_index[n]; | ||
| 755 | printf("- %*.*s\n", | ||
| 756 | (int)type->name->size, | ||
| 757 | (int)type->name->size, | ||
| 758 | type->name->value); | ||
| 759 | } | ||
| 760 | #endif | ||
| 761 | } | ||
| 762 | |||
| 763 | static struct element *parse_type(struct token **_cursor, struct token *stop, | ||
| 764 | struct token *name); | ||
| 765 | |||
| 766 | /* | ||
| 767 | * Parse the token stream | ||
| 768 | */ | ||
| 769 | static void parse(void) | ||
| 770 | { | ||
| 771 | struct token *cursor; | ||
| 772 | struct type *type; | ||
| 773 | |||
| 774 | /* Parse one type definition statement at a time */ | ||
| 775 | type = type_list; | ||
| 776 | do { | ||
| 777 | cursor = type->name; | ||
| 778 | |||
| 779 | if (cursor[0].token_type != TOKEN_TYPE_NAME || | ||
| 780 | cursor[1].token_type != TOKEN_ASSIGNMENT) | ||
| 781 | abort(); | ||
| 782 | cursor += 2; | ||
| 783 | |||
| 784 | type->element = parse_type(&cursor, type[1].name, NULL); | ||
| 785 | type->element->type_def = type; | ||
| 786 | |||
| 787 | if (cursor != type[1].name) { | ||
| 788 | fprintf(stderr, "%s:%d: Parse error at token '%*.*s'\n", | ||
| 789 | filename, cursor->line, | ||
| 790 | (int)cursor->size, (int)cursor->size, cursor->value); | ||
| 791 | exit(1); | ||
| 792 | } | ||
| 793 | |||
| 794 | } while (type++, !(type->flags & TYPE_STOP_MARKER)); | ||
| 795 | |||
| 796 | printf("Extracted %u actions\n", nr_actions); | ||
| 797 | } | ||
| 798 | |||
| 799 | static struct element *element_list; | ||
| 800 | |||
| 801 | static struct element *alloc_elem(struct token *type) | ||
| 802 | { | ||
| 803 | struct element *e = calloc(1, sizeof(*e)); | ||
| 804 | if (!e) { | ||
| 805 | perror(NULL); | ||
| 806 | exit(1); | ||
| 807 | } | ||
| 808 | e->list_next = element_list; | ||
| 809 | element_list = e; | ||
| 810 | return e; | ||
| 811 | } | ||
| 812 | |||
| 813 | static struct element *parse_compound(struct token **_cursor, struct token *end, | ||
| 814 | int alternates); | ||
| 815 | |||
| 816 | /* | ||
| 817 | * Parse one type definition statement | ||
| 818 | */ | ||
| 819 | static struct element *parse_type(struct token **_cursor, struct token *end, | ||
| 820 | struct token *name) | ||
| 821 | { | ||
| 822 | struct element *top, *element; | ||
| 823 | struct action *action, **ppaction; | ||
| 824 | struct token *cursor = *_cursor; | ||
| 825 | struct type **ref; | ||
| 826 | char *p; | ||
| 827 | int labelled = 0, implicit = 0; | ||
| 828 | |||
| 829 | top = element = alloc_elem(cursor); | ||
| 830 | element->class = ASN1_UNIV; | ||
| 831 | element->method = ASN1_PRIM; | ||
| 832 | element->tag = token_to_tag[cursor->token_type]; | ||
| 833 | element->name = name; | ||
| 834 | |||
| 835 | /* Extract the tag value if one given */ | ||
| 836 | if (cursor->token_type == TOKEN_OPEN_SQUARE) { | ||
| 837 | cursor++; | ||
| 838 | if (cursor >= end) | ||
| 839 | goto overrun_error; | ||
| 840 | switch (cursor->token_type) { | ||
| 841 | case DIRECTIVE_UNIVERSAL: | ||
| 842 | element->class = ASN1_UNIV; | ||
| 843 | cursor++; | ||
| 844 | break; | ||
| 845 | case DIRECTIVE_APPLICATION: | ||
| 846 | element->class = ASN1_APPL; | ||
| 847 | cursor++; | ||
| 848 | break; | ||
| 849 | case TOKEN_NUMBER: | ||
| 850 | element->class = ASN1_CONT; | ||
| 851 | break; | ||
| 852 | case DIRECTIVE_PRIVATE: | ||
| 853 | element->class = ASN1_PRIV; | ||
| 854 | cursor++; | ||
| 855 | break; | ||
| 856 | default: | ||
| 857 | fprintf(stderr, "%s:%d: Unrecognised tag class token '%*.*s'\n", | ||
| 858 | filename, cursor->line, | ||
| 859 | (int)cursor->size, (int)cursor->size, cursor->value); | ||
| 860 | exit(1); | ||
| 861 | } | ||
| 862 | |||
| 863 | if (cursor >= end) | ||
| 864 | goto overrun_error; | ||
| 865 | if (cursor->token_type != TOKEN_NUMBER) { | ||
| 866 | fprintf(stderr, "%s:%d: Missing tag number '%*.*s'\n", | ||
| 867 | filename, cursor->line, | ||
| 868 | (int)cursor->size, (int)cursor->size, cursor->value); | ||
| 869 | exit(1); | ||
| 870 | } | ||
| 871 | |||
| 872 | element->tag &= ~0x1f; | ||
| 873 | element->tag |= strtoul(cursor->value, &p, 10); | ||
| 874 | if (p - cursor->value != cursor->size) | ||
| 875 | abort(); | ||
| 876 | cursor++; | ||
| 877 | |||
| 878 | if (cursor >= end) | ||
| 879 | goto overrun_error; | ||
| 880 | if (cursor->token_type != TOKEN_CLOSE_SQUARE) { | ||
| 881 | fprintf(stderr, "%s:%d: Missing closing square bracket '%*.*s'\n", | ||
| 882 | filename, cursor->line, | ||
| 883 | (int)cursor->size, (int)cursor->size, cursor->value); | ||
| 884 | exit(1); | ||
| 885 | } | ||
| 886 | cursor++; | ||
| 887 | if (cursor >= end) | ||
| 888 | goto overrun_error; | ||
| 889 | labelled = 1; | ||
| 890 | } | ||
| 891 | |||
| 892 | /* Handle implicit and explicit markers */ | ||
| 893 | if (cursor->token_type == DIRECTIVE_IMPLICIT) { | ||
| 894 | element->flags |= ELEMENT_IMPLICIT; | ||
| 895 | implicit = 1; | ||
| 896 | cursor++; | ||
| 897 | if (cursor >= end) | ||
| 898 | goto overrun_error; | ||
| 899 | } else if (cursor->token_type == DIRECTIVE_EXPLICIT) { | ||
| 900 | element->flags |= ELEMENT_EXPLICIT; | ||
| 901 | cursor++; | ||
| 902 | if (cursor >= end) | ||
| 903 | goto overrun_error; | ||
| 904 | } | ||
| 905 | |||
| 906 | if (labelled) { | ||
| 907 | if (!implicit) | ||
| 908 | element->method |= ASN1_CONS; | ||
| 909 | element->compound = implicit ? TAG_OVERRIDE : SEQUENCE; | ||
| 910 | element->children = alloc_elem(cursor); | ||
| 911 | element = element->children; | ||
| 912 | element->class = ASN1_UNIV; | ||
| 913 | element->method = ASN1_PRIM; | ||
| 914 | element->tag = token_to_tag[cursor->token_type]; | ||
| 915 | element->name = name; | ||
| 916 | } | ||
| 917 | |||
| 918 | /* Extract the type we're expecting here */ | ||
| 919 | element->type = cursor; | ||
| 920 | switch (cursor->token_type) { | ||
| 921 | case DIRECTIVE_ANY: | ||
| 922 | element->compound = ANY; | ||
| 923 | cursor++; | ||
| 924 | break; | ||
| 925 | |||
| 926 | case DIRECTIVE_NULL: | ||
| 927 | case DIRECTIVE_BOOLEAN: | ||
| 928 | case DIRECTIVE_ENUMERATED: | ||
| 929 | case DIRECTIVE_INTEGER: | ||
| 930 | element->compound = NOT_COMPOUND; | ||
| 931 | cursor++; | ||
| 932 | break; | ||
| 933 | |||
| 934 | case DIRECTIVE_EXTERNAL: | ||
| 935 | element->method = ASN1_CONS; | ||
| 936 | |||
| 937 | case DIRECTIVE_BMPString: | ||
| 938 | case DIRECTIVE_GeneralString: | ||
| 939 | case DIRECTIVE_GraphicString: | ||
| 940 | case DIRECTIVE_IA5String: | ||
| 941 | case DIRECTIVE_ISO646String: | ||
| 942 | case DIRECTIVE_NumericString: | ||
| 943 | case DIRECTIVE_PrintableString: | ||
| 944 | case DIRECTIVE_T61String: | ||
| 945 | case DIRECTIVE_TeletexString: | ||
| 946 | case DIRECTIVE_UniversalString: | ||
| 947 | case DIRECTIVE_UTF8String: | ||
| 948 | case DIRECTIVE_VideotexString: | ||
| 949 | case DIRECTIVE_VisibleString: | ||
| 950 | case DIRECTIVE_ObjectDescriptor: | ||
| 951 | case DIRECTIVE_GeneralizedTime: | ||
| 952 | case DIRECTIVE_UTCTime: | ||
| 953 | element->compound = NOT_COMPOUND; | ||
| 954 | cursor++; | ||
| 955 | break; | ||
| 956 | |||
| 957 | case DIRECTIVE_BIT: | ||
| 958 | case DIRECTIVE_OCTET: | ||
| 959 | element->compound = NOT_COMPOUND; | ||
| 960 | cursor++; | ||
| 961 | if (cursor >= end) | ||
| 962 | goto overrun_error; | ||
| 963 | if (cursor->token_type != DIRECTIVE_STRING) | ||
| 964 | goto parse_error; | ||
| 965 | cursor++; | ||
| 966 | break; | ||
| 967 | |||
| 968 | case DIRECTIVE_OBJECT: | ||
| 969 | element->compound = NOT_COMPOUND; | ||
| 970 | cursor++; | ||
| 971 | if (cursor >= end) | ||
| 972 | goto overrun_error; | ||
| 973 | if (cursor->token_type != DIRECTIVE_IDENTIFIER) | ||
| 974 | goto parse_error; | ||
| 975 | cursor++; | ||
| 976 | break; | ||
| 977 | |||
| 978 | case TOKEN_TYPE_NAME: | ||
| 979 | element->compound = TYPE_REF; | ||
| 980 | ref = bsearch(cursor, type_index, nr_types, sizeof(type_index[0]), | ||
| 981 | type_finder); | ||
| 982 | if (!ref) { | ||
| 983 | fprintf(stderr, "%s:%d: Type '%*.*s' undefined\n", | ||
| 984 | filename, cursor->line, | ||
| 985 | (int)cursor->size, (int)cursor->size, cursor->value); | ||
| 986 | exit(1); | ||
| 987 | } | ||
| 988 | cursor->type = *ref; | ||
| 989 | (*ref)->ref_count++; | ||
| 990 | cursor++; | ||
| 991 | break; | ||
| 992 | |||
| 993 | case DIRECTIVE_CHOICE: | ||
| 994 | element->compound = CHOICE; | ||
| 995 | cursor++; | ||
| 996 | element->children = parse_compound(&cursor, end, 1); | ||
| 997 | break; | ||
| 998 | |||
| 999 | case DIRECTIVE_SEQUENCE: | ||
| 1000 | element->compound = SEQUENCE; | ||
| 1001 | element->method = ASN1_CONS; | ||
| 1002 | cursor++; | ||
| 1003 | if (cursor >= end) | ||
| 1004 | goto overrun_error; | ||
| 1005 | if (cursor->token_type == DIRECTIVE_OF) { | ||
| 1006 | element->compound = SEQUENCE_OF; | ||
| 1007 | cursor++; | ||
| 1008 | if (cursor >= end) | ||
| 1009 | goto overrun_error; | ||
| 1010 | element->children = parse_type(&cursor, end, NULL); | ||
| 1011 | } else { | ||
| 1012 | element->children = parse_compound(&cursor, end, 0); | ||
| 1013 | } | ||
| 1014 | break; | ||
| 1015 | |||
| 1016 | case DIRECTIVE_SET: | ||
| 1017 | element->compound = SET; | ||
| 1018 | element->method = ASN1_CONS; | ||
| 1019 | cursor++; | ||
| 1020 | if (cursor >= end) | ||
| 1021 | goto overrun_error; | ||
| 1022 | if (cursor->token_type == DIRECTIVE_OF) { | ||
| 1023 | element->compound = SET_OF; | ||
| 1024 | cursor++; | ||
| 1025 | if (cursor >= end) | ||
| 1026 | goto parse_error; | ||
| 1027 | element->children = parse_type(&cursor, end, NULL); | ||
| 1028 | } else { | ||
| 1029 | element->children = parse_compound(&cursor, end, 1); | ||
| 1030 | } | ||
| 1031 | break; | ||
| 1032 | |||
| 1033 | default: | ||
| 1034 | fprintf(stderr, "%s:%d: Token '%*.*s' does not introduce a type\n", | ||
| 1035 | filename, cursor->line, | ||
| 1036 | (int)cursor->size, (int)cursor->size, cursor->value); | ||
| 1037 | exit(1); | ||
| 1038 | } | ||
| 1039 | |||
| 1040 | /* Handle elements that are optional */ | ||
| 1041 | if (cursor < end && (cursor->token_type == DIRECTIVE_OPTIONAL || | ||
| 1042 | cursor->token_type == DIRECTIVE_DEFAULT) | ||
| 1043 | ) { | ||
| 1044 | cursor++; | ||
| 1045 | top->flags |= ELEMENT_SKIPPABLE; | ||
| 1046 | } | ||
| 1047 | |||
| 1048 | if (cursor < end && cursor->token_type == TOKEN_OPEN_ACTION) { | ||
| 1049 | cursor++; | ||
| 1050 | if (cursor >= end) | ||
| 1051 | goto overrun_error; | ||
| 1052 | if (cursor->token_type != TOKEN_ELEMENT_NAME) { | ||
| 1053 | fprintf(stderr, "%s:%d: Token '%*.*s' is not an action function name\n", | ||
| 1054 | filename, cursor->line, | ||
| 1055 | (int)cursor->size, (int)cursor->size, cursor->value); | ||
| 1056 | exit(1); | ||
| 1057 | } | ||
| 1058 | |||
| 1059 | action = malloc(sizeof(struct action) + cursor->size + 1); | ||
| 1060 | if (!action) { | ||
| 1061 | perror(NULL); | ||
| 1062 | exit(1); | ||
| 1063 | } | ||
| 1064 | action->index = 0; | ||
| 1065 | memcpy(action->name, cursor->value, cursor->size); | ||
| 1066 | action->name[cursor->size] = 0; | ||
| 1067 | |||
| 1068 | for (ppaction = &action_list; | ||
| 1069 | *ppaction; | ||
| 1070 | ppaction = &(*ppaction)->next | ||
| 1071 | ) { | ||
| 1072 | int cmp = strcmp(action->name, (*ppaction)->name); | ||
| 1073 | if (cmp == 0) { | ||
| 1074 | free(action); | ||
| 1075 | action = *ppaction; | ||
| 1076 | goto found; | ||
| 1077 | } | ||
| 1078 | if (cmp < 0) { | ||
| 1079 | action->next = *ppaction; | ||
| 1080 | *ppaction = action; | ||
| 1081 | nr_actions++; | ||
| 1082 | goto found; | ||
| 1083 | } | ||
| 1084 | } | ||
| 1085 | action->next = NULL; | ||
| 1086 | *ppaction = action; | ||
| 1087 | nr_actions++; | ||
| 1088 | found: | ||
| 1089 | |||
| 1090 | element->action = action; | ||
| 1091 | cursor->action = action; | ||
| 1092 | cursor++; | ||
| 1093 | if (cursor >= end) | ||
| 1094 | goto overrun_error; | ||
| 1095 | if (cursor->token_type != TOKEN_CLOSE_ACTION) { | ||
| 1096 | fprintf(stderr, "%s:%d: Missing close action, got '%*.*s'\n", | ||
| 1097 | filename, cursor->line, | ||
| 1098 | (int)cursor->size, (int)cursor->size, cursor->value); | ||
| 1099 | exit(1); | ||
| 1100 | } | ||
| 1101 | cursor++; | ||
| 1102 | } | ||
| 1103 | |||
| 1104 | *_cursor = cursor; | ||
| 1105 | return top; | ||
| 1106 | |||
| 1107 | parse_error: | ||
| 1108 | fprintf(stderr, "%s:%d: Unexpected token '%*.*s'\n", | ||
| 1109 | filename, cursor->line, | ||
| 1110 | (int)cursor->size, (int)cursor->size, cursor->value); | ||
| 1111 | exit(1); | ||
| 1112 | |||
| 1113 | overrun_error: | ||
| 1114 | fprintf(stderr, "%s: Unexpectedly hit EOF\n", filename); | ||
| 1115 | exit(1); | ||
| 1116 | } | ||
| 1117 | |||
| 1118 | /* | ||
| 1119 | * Parse a compound type list | ||
| 1120 | */ | ||
| 1121 | static struct element *parse_compound(struct token **_cursor, struct token *end, | ||
| 1122 | int alternates) | ||
| 1123 | { | ||
| 1124 | struct element *children, **child_p = &children, *element; | ||
| 1125 | struct token *cursor = *_cursor, *name; | ||
| 1126 | |||
| 1127 | if (cursor->token_type != TOKEN_OPEN_CURLY) { | ||
| 1128 | fprintf(stderr, "%s:%d: Expected compound to start with brace not '%*.*s'\n", | ||
| 1129 | filename, cursor->line, | ||
| 1130 | (int)cursor->size, (int)cursor->size, cursor->value); | ||
| 1131 | exit(1); | ||
| 1132 | } | ||
| 1133 | cursor++; | ||
| 1134 | if (cursor >= end) | ||
| 1135 | goto overrun_error; | ||
| 1136 | |||
| 1137 | if (cursor->token_type == TOKEN_OPEN_CURLY) { | ||
| 1138 | fprintf(stderr, "%s:%d: Empty compound\n", | ||
| 1139 | filename, cursor->line); | ||
| 1140 | exit(1); | ||
| 1141 | } | ||
| 1142 | |||
| 1143 | for (;;) { | ||
| 1144 | name = NULL; | ||
| 1145 | if (cursor->token_type == TOKEN_ELEMENT_NAME) { | ||
| 1146 | name = cursor; | ||
| 1147 | cursor++; | ||
| 1148 | if (cursor >= end) | ||
| 1149 | goto overrun_error; | ||
| 1150 | } | ||
| 1151 | |||
| 1152 | element = parse_type(&cursor, end, name); | ||
| 1153 | if (alternates) | ||
| 1154 | element->flags |= ELEMENT_SKIPPABLE | ELEMENT_CONDITIONAL; | ||
| 1155 | |||
| 1156 | *child_p = element; | ||
| 1157 | child_p = &element->next; | ||
| 1158 | |||
| 1159 | if (cursor >= end) | ||
| 1160 | goto overrun_error; | ||
| 1161 | if (cursor->token_type != TOKEN_COMMA) | ||
| 1162 | break; | ||
| 1163 | cursor++; | ||
| 1164 | if (cursor >= end) | ||
| 1165 | goto overrun_error; | ||
| 1166 | } | ||
| 1167 | |||
| 1168 | children->flags &= ~ELEMENT_CONDITIONAL; | ||
| 1169 | |||
| 1170 | if (cursor->token_type != TOKEN_CLOSE_CURLY) { | ||
| 1171 | fprintf(stderr, "%s:%d: Expected compound closure, got '%*.*s'\n", | ||
| 1172 | filename, cursor->line, | ||
| 1173 | (int)cursor->size, (int)cursor->size, cursor->value); | ||
| 1174 | exit(1); | ||
| 1175 | } | ||
| 1176 | cursor++; | ||
| 1177 | |||
| 1178 | *_cursor = cursor; | ||
| 1179 | return children; | ||
| 1180 | |||
| 1181 | overrun_error: | ||
| 1182 | fprintf(stderr, "%s: Unexpectedly hit EOF\n", filename); | ||
| 1183 | exit(1); | ||
| 1184 | } | ||
| 1185 | |||
| 1186 | static void render_element(FILE *out, struct element *e, struct element *tag); | ||
| 1187 | static void render_out_of_line_list(FILE *out); | ||
| 1188 | |||
| 1189 | static int nr_entries; | ||
| 1190 | static int render_depth = 1; | ||
| 1191 | static struct element *render_list, **render_list_p = &render_list; | ||
| 1192 | |||
| 1193 | __attribute__((format(printf, 2, 3))) | ||
| 1194 | static void render_opcode(FILE *out, const char *fmt, ...) | ||
| 1195 | { | ||
| 1196 | va_list va; | ||
| 1197 | |||
| 1198 | if (out) { | ||
| 1199 | fprintf(out, "\t[%4d] =%*s", nr_entries, render_depth, ""); | ||
| 1200 | va_start(va, fmt); | ||
| 1201 | vfprintf(out, fmt, va); | ||
| 1202 | va_end(va); | ||
| 1203 | } | ||
| 1204 | nr_entries++; | ||
| 1205 | } | ||
| 1206 | |||
| 1207 | __attribute__((format(printf, 2, 3))) | ||
| 1208 | static void render_more(FILE *out, const char *fmt, ...) | ||
| 1209 | { | ||
| 1210 | va_list va; | ||
| 1211 | |||
| 1212 | if (out) { | ||
| 1213 | va_start(va, fmt); | ||
| 1214 | vfprintf(out, fmt, va); | ||
| 1215 | va_end(va); | ||
| 1216 | } | ||
| 1217 | } | ||
| 1218 | |||
| 1219 | /* | ||
| 1220 | * Render the grammar into a state machine definition. | ||
| 1221 | */ | ||
| 1222 | static void render(FILE *out, FILE *hdr) | ||
| 1223 | { | ||
| 1224 | struct element *e; | ||
| 1225 | struct action *action; | ||
| 1226 | struct type *root; | ||
| 1227 | int index; | ||
| 1228 | |||
| 1229 | fprintf(hdr, "/*\n"); | ||
| 1230 | fprintf(hdr, " * Automatically generated by asn1_compiler. Do not edit\n"); | ||
| 1231 | fprintf(hdr, " *\n"); | ||
| 1232 | fprintf(hdr, " * ASN.1 parser for %s\n", grammar_name); | ||
| 1233 | fprintf(hdr, " */\n"); | ||
| 1234 | fprintf(hdr, "#include <linux/asn1_decoder.h>\n"); | ||
| 1235 | fprintf(hdr, "\n"); | ||
| 1236 | fprintf(hdr, "extern const struct asn1_decoder %s_decoder;\n", grammar_name); | ||
| 1237 | if (ferror(hdr)) { | ||
| 1238 | perror(headername); | ||
| 1239 | exit(1); | ||
| 1240 | } | ||
| 1241 | |||
| 1242 | fprintf(out, "/*\n"); | ||
| 1243 | fprintf(out, " * Automatically generated by asn1_compiler. Do not edit\n"); | ||
| 1244 | fprintf(out, " *\n"); | ||
| 1245 | fprintf(out, " * ASN.1 parser for %s\n", grammar_name); | ||
| 1246 | fprintf(out, " */\n"); | ||
| 1247 | fprintf(out, "#include <linux/asn1_ber_bytecode.h>\n"); | ||
| 1248 | fprintf(out, "#include \"%s-asn1.h\"\n", grammar_name); | ||
| 1249 | fprintf(out, "\n"); | ||
| 1250 | if (ferror(out)) { | ||
| 1251 | perror(outputname); | ||
| 1252 | exit(1); | ||
| 1253 | } | ||
| 1254 | |||
| 1255 | /* Tabulate the action functions we might have to call */ | ||
| 1256 | fprintf(hdr, "\n"); | ||
| 1257 | index = 0; | ||
| 1258 | for (action = action_list; action; action = action->next) { | ||
| 1259 | action->index = index++; | ||
| 1260 | fprintf(hdr, | ||
| 1261 | "extern int %s(void *, size_t, unsigned char," | ||
| 1262 | " const void *, size_t);\n", | ||
| 1263 | action->name); | ||
| 1264 | } | ||
| 1265 | fprintf(hdr, "\n"); | ||
| 1266 | |||
| 1267 | fprintf(out, "enum %s_actions {\n", grammar_name); | ||
| 1268 | for (action = action_list; action; action = action->next) | ||
| 1269 | fprintf(out, "\tACT_%s = %u,\n", | ||
| 1270 | action->name, action->index); | ||
| 1271 | fprintf(out, "\tNR__%s_actions = %u\n", grammar_name, nr_actions); | ||
| 1272 | fprintf(out, "};\n"); | ||
| 1273 | |||
| 1274 | fprintf(out, "\n"); | ||
| 1275 | fprintf(out, "static const asn1_action_t %s_action_table[NR__%s_actions] = {\n", | ||
| 1276 | grammar_name, grammar_name); | ||
| 1277 | for (action = action_list; action; action = action->next) | ||
| 1278 | fprintf(out, "\t[%4u] = %s,\n", action->index, action->name); | ||
| 1279 | fprintf(out, "};\n"); | ||
| 1280 | |||
| 1281 | if (ferror(out)) { | ||
| 1282 | perror(outputname); | ||
| 1283 | exit(1); | ||
| 1284 | } | ||
| 1285 | |||
| 1286 | /* We do two passes - the first one calculates all the offsets */ | ||
| 1287 | printf("Pass 1\n"); | ||
| 1288 | nr_entries = 0; | ||
| 1289 | root = &type_list[0]; | ||
| 1290 | render_element(NULL, root->element, NULL); | ||
| 1291 | render_opcode(NULL, "ASN1_OP_COMPLETE,\n"); | ||
| 1292 | render_out_of_line_list(NULL); | ||
| 1293 | |||
| 1294 | for (e = element_list; e; e = e->list_next) | ||
| 1295 | e->flags &= ~ELEMENT_RENDERED; | ||
| 1296 | |||
| 1297 | /* And then we actually render */ | ||
| 1298 | printf("Pass 2\n"); | ||
| 1299 | fprintf(out, "\n"); | ||
| 1300 | fprintf(out, "static const unsigned char %s_machine[] = {\n", | ||
| 1301 | grammar_name); | ||
| 1302 | |||
| 1303 | nr_entries = 0; | ||
| 1304 | root = &type_list[0]; | ||
| 1305 | render_element(out, root->element, NULL); | ||
| 1306 | render_opcode(out, "ASN1_OP_COMPLETE,\n"); | ||
| 1307 | render_out_of_line_list(out); | ||
| 1308 | |||
| 1309 | fprintf(out, "};\n"); | ||
| 1310 | |||
| 1311 | fprintf(out, "\n"); | ||
| 1312 | fprintf(out, "const struct asn1_decoder %s_decoder = {\n", grammar_name); | ||
| 1313 | fprintf(out, "\t.machine = %s_machine,\n", grammar_name); | ||
| 1314 | fprintf(out, "\t.machlen = sizeof(%s_machine),\n", grammar_name); | ||
| 1315 | fprintf(out, "\t.actions = %s_action_table,\n", grammar_name); | ||
| 1316 | fprintf(out, "};\n"); | ||
| 1317 | } | ||
| 1318 | |||
| 1319 | /* | ||
| 1320 | * Render the out-of-line elements | ||
| 1321 | */ | ||
| 1322 | static void render_out_of_line_list(FILE *out) | ||
| 1323 | { | ||
| 1324 | struct element *e, *ce; | ||
| 1325 | const char *act; | ||
| 1326 | int entry; | ||
| 1327 | |||
| 1328 | while ((e = render_list)) { | ||
| 1329 | render_list = e->render_next; | ||
| 1330 | if (!render_list) | ||
| 1331 | render_list_p = &render_list; | ||
| 1332 | |||
| 1333 | render_more(out, "\n"); | ||
| 1334 | e->entry_index = entry = nr_entries; | ||
| 1335 | render_depth++; | ||
| 1336 | for (ce = e->children; ce; ce = ce->next) | ||
| 1337 | render_element(out, ce, NULL); | ||
| 1338 | render_depth--; | ||
| 1339 | |||
| 1340 | act = e->action ? "_ACT" : ""; | ||
| 1341 | switch (e->compound) { | ||
| 1342 | case SEQUENCE: | ||
| 1343 | render_opcode(out, "ASN1_OP_END_SEQ%s,\n", act); | ||
| 1344 | break; | ||
| 1345 | case SEQUENCE_OF: | ||
| 1346 | render_opcode(out, "ASN1_OP_END_SEQ_OF%s,\n", act); | ||
| 1347 | render_opcode(out, "_jump_target(%u),\n", entry); | ||
| 1348 | break; | ||
| 1349 | case SET: | ||
| 1350 | render_opcode(out, "ASN1_OP_END_SET%s,\n", act); | ||
| 1351 | break; | ||
| 1352 | case SET_OF: | ||
| 1353 | render_opcode(out, "ASN1_OP_END_SET_OF%s,\n", act); | ||
| 1354 | render_opcode(out, "_jump_target(%u),\n", entry); | ||
| 1355 | break; | ||
| 1356 | } | ||
| 1357 | if (e->action) | ||
| 1358 | render_opcode(out, "_action(ACT_%s),\n", | ||
| 1359 | e->action->name); | ||
| 1360 | render_opcode(out, "ASN1_OP_RETURN,\n"); | ||
| 1361 | } | ||
| 1362 | } | ||
| 1363 | |||
| 1364 | /* | ||
| 1365 | * Render an element. | ||
| 1366 | */ | ||
| 1367 | static void render_element(FILE *out, struct element *e, struct element *tag) | ||
| 1368 | { | ||
| 1369 | struct element *ec; | ||
| 1370 | const char *cond, *act; | ||
| 1371 | int entry, skippable = 0, outofline = 0; | ||
| 1372 | |||
| 1373 | if (e->flags & ELEMENT_SKIPPABLE || | ||
| 1374 | (tag && tag->flags & ELEMENT_SKIPPABLE)) | ||
| 1375 | skippable = 1; | ||
| 1376 | |||
| 1377 | if ((e->type_def && e->type_def->ref_count > 1) || | ||
| 1378 | skippable) | ||
| 1379 | outofline = 1; | ||
| 1380 | |||
| 1381 | if (e->type_def && out) { | ||
| 1382 | render_more(out, "\t// %*.*s\n", | ||
| 1383 | (int)e->type_def->name->size, (int)e->type_def->name->size, | ||
| 1384 | e->type_def->name->value); | ||
| 1385 | } | ||
| 1386 | |||
| 1387 | /* Render the operation */ | ||
| 1388 | cond = (e->flags & ELEMENT_CONDITIONAL || | ||
| 1389 | (tag && tag->flags & ELEMENT_CONDITIONAL)) ? "COND_" : ""; | ||
| 1390 | act = e->action ? "_ACT" : ""; | ||
| 1391 | switch (e->compound) { | ||
| 1392 | case ANY: | ||
| 1393 | render_opcode(out, "ASN1_OP_%sMATCH_ANY%s,", cond, act); | ||
| 1394 | if (e->name) | ||
| 1395 | render_more(out, "\t\t// %*.*s", | ||
| 1396 | (int)e->name->size, (int)e->name->size, | ||
| 1397 | e->name->value); | ||
| 1398 | render_more(out, "\n"); | ||
| 1399 | goto dont_render_tag; | ||
| 1400 | |||
| 1401 | case TAG_OVERRIDE: | ||
| 1402 | render_element(out, e->children, e); | ||
| 1403 | return; | ||
| 1404 | |||
| 1405 | case SEQUENCE: | ||
| 1406 | case SEQUENCE_OF: | ||
| 1407 | case SET: | ||
| 1408 | case SET_OF: | ||
| 1409 | render_opcode(out, "ASN1_OP_%sMATCH%s%s,", | ||
| 1410 | cond, | ||
| 1411 | outofline ? "_JUMP" : "", | ||
| 1412 | skippable ? "_OR_SKIP" : ""); | ||
| 1413 | break; | ||
| 1414 | |||
| 1415 | case CHOICE: | ||
| 1416 | goto dont_render_tag; | ||
| 1417 | |||
| 1418 | case TYPE_REF: | ||
| 1419 | if (e->class == ASN1_UNIV && e->method == ASN1_PRIM && e->tag == 0) | ||
| 1420 | goto dont_render_tag; | ||
| 1421 | default: | ||
| 1422 | render_opcode(out, "ASN1_OP_%sMATCH%s%s,", | ||
| 1423 | cond, act, | ||
| 1424 | skippable ? "_OR_SKIP" : ""); | ||
| 1425 | break; | ||
| 1426 | } | ||
| 1427 | |||
| 1428 | if (e->name) | ||
| 1429 | render_more(out, "\t\t// %*.*s", | ||
| 1430 | (int)e->name->size, (int)e->name->size, | ||
| 1431 | e->name->value); | ||
| 1432 | render_more(out, "\n"); | ||
| 1433 | |||
| 1434 | /* Render the tag */ | ||
| 1435 | if (!tag) | ||
| 1436 | tag = e; | ||
| 1437 | if (tag->class == ASN1_UNIV && | ||
| 1438 | tag->tag != 14 && | ||
| 1439 | tag->tag != 15 && | ||
| 1440 | tag->tag != 31) | ||
| 1441 | render_opcode(out, "_tag(%s, %s, %s),\n", | ||
| 1442 | asn1_classes[tag->class], | ||
| 1443 | asn1_methods[tag->method | e->method], | ||
| 1444 | asn1_universal_tags[tag->tag]); | ||
| 1445 | else | ||
| 1446 | render_opcode(out, "_tagn(%s, %s, %2u),\n", | ||
| 1447 | asn1_classes[tag->class], | ||
| 1448 | asn1_methods[tag->method | e->method], | ||
| 1449 | tag->tag); | ||
| 1450 | tag = NULL; | ||
| 1451 | dont_render_tag: | ||
| 1452 | |||
| 1453 | /* Deal with compound types */ | ||
| 1454 | switch (e->compound) { | ||
| 1455 | case TYPE_REF: | ||
| 1456 | render_element(out, e->type->type->element, tag); | ||
| 1457 | if (e->action) | ||
| 1458 | render_opcode(out, "ASN1_OP_ACT,\n"); | ||
| 1459 | break; | ||
| 1460 | |||
| 1461 | case SEQUENCE: | ||
| 1462 | if (outofline) { | ||
| 1463 | /* Render out-of-line for multiple use or | ||
| 1464 | * skipability */ | ||
| 1465 | render_opcode(out, "_jump_target(%u),", e->entry_index); | ||
| 1466 | if (e->type_def && e->type_def->name) | ||
| 1467 | render_more(out, "\t\t// --> %*.*s", | ||
| 1468 | (int)e->type_def->name->size, | ||
| 1469 | (int)e->type_def->name->size, | ||
| 1470 | e->type_def->name->value); | ||
| 1471 | render_more(out, "\n"); | ||
| 1472 | if (!(e->flags & ELEMENT_RENDERED)) { | ||
| 1473 | e->flags |= ELEMENT_RENDERED; | ||
| 1474 | *render_list_p = e; | ||
| 1475 | render_list_p = &e->render_next; | ||
| 1476 | } | ||
| 1477 | return; | ||
| 1478 | } else { | ||
| 1479 | /* Render inline for single use */ | ||
| 1480 | render_depth++; | ||
| 1481 | for (ec = e->children; ec; ec = ec->next) | ||
| 1482 | render_element(out, ec, NULL); | ||
| 1483 | render_depth--; | ||
| 1484 | render_opcode(out, "ASN1_OP_END_SEQ%s,\n", act); | ||
| 1485 | } | ||
| 1486 | break; | ||
| 1487 | |||
| 1488 | case SEQUENCE_OF: | ||
| 1489 | case SET_OF: | ||
| 1490 | if (outofline) { | ||
| 1491 | /* Render out-of-line for multiple use or | ||
| 1492 | * skipability */ | ||
| 1493 | render_opcode(out, "_jump_target(%u),", e->entry_index); | ||
| 1494 | if (e->type_def && e->type_def->name) | ||
| 1495 | render_more(out, "\t\t// --> %*.*s", | ||
| 1496 | (int)e->type_def->name->size, | ||
| 1497 | (int)e->type_def->name->size, | ||
| 1498 | e->type_def->name->value); | ||
| 1499 | render_more(out, "\n"); | ||
| 1500 | if (!(e->flags & ELEMENT_RENDERED)) { | ||
| 1501 | e->flags |= ELEMENT_RENDERED; | ||
| 1502 | *render_list_p = e; | ||
| 1503 | render_list_p = &e->render_next; | ||
| 1504 | } | ||
| 1505 | return; | ||
| 1506 | } else { | ||
| 1507 | /* Render inline for single use */ | ||
| 1508 | entry = nr_entries; | ||
| 1509 | render_depth++; | ||
| 1510 | render_element(out, e->children, NULL); | ||
| 1511 | render_depth--; | ||
| 1512 | if (e->compound == SEQUENCE_OF) | ||
| 1513 | render_opcode(out, "ASN1_OP_END_SEQ_OF%s,\n", act); | ||
| 1514 | else | ||
| 1515 | render_opcode(out, "ASN1_OP_END_SET_OF%s,\n", act); | ||
| 1516 | render_opcode(out, "_jump_target(%u),\n", entry); | ||
| 1517 | } | ||
| 1518 | break; | ||
| 1519 | |||
| 1520 | case SET: | ||
| 1521 | /* I can't think of a nice way to do SET support without having | ||
| 1522 | * a stack of bitmasks to make sure no element is repeated. | ||
| 1523 | * The bitmask has also to be checked that no non-optional | ||
| 1524 | * elements are left out whilst not preventing optional | ||
| 1525 | * elements from being left out. | ||
| 1526 | */ | ||
| 1527 | fprintf(stderr, "The ASN.1 SET type is not currently supported.\n"); | ||
| 1528 | exit(1); | ||
| 1529 | |||
| 1530 | case CHOICE: | ||
| 1531 | for (ec = e->children; ec; ec = ec->next) | ||
| 1532 | render_element(out, ec, NULL); | ||
| 1533 | if (!skippable) | ||
| 1534 | render_opcode(out, "ASN1_OP_COND_FAIL,\n"); | ||
| 1535 | if (e->action) | ||
| 1536 | render_opcode(out, "ASN1_OP_ACT,\n"); | ||
| 1537 | break; | ||
| 1538 | |||
| 1539 | default: | ||
| 1540 | break; | ||
| 1541 | } | ||
| 1542 | |||
| 1543 | if (e->action) | ||
| 1544 | render_opcode(out, "_action(ACT_%s),\n", e->action->name); | ||
| 1545 | } | ||
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index ca05ba217f5f..21a9f5de0a21 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl | |||
| @@ -421,7 +421,7 @@ sub top_of_kernel_tree { | |||
| 421 | } | 421 | } |
| 422 | } | 422 | } |
| 423 | return 1; | 423 | return 1; |
| 424 | } | 424 | } |
| 425 | 425 | ||
| 426 | sub parse_email { | 426 | sub parse_email { |
| 427 | my ($formatted_email) = @_; | 427 | my ($formatted_email) = @_; |
| @@ -1386,6 +1386,8 @@ sub process { | |||
| 1386 | my $in_header_lines = 1; | 1386 | my $in_header_lines = 1; |
| 1387 | my $in_commit_log = 0; #Scanning lines before patch | 1387 | my $in_commit_log = 0; #Scanning lines before patch |
| 1388 | 1388 | ||
| 1389 | my $non_utf8_charset = 0; | ||
| 1390 | |||
| 1389 | our @report = (); | 1391 | our @report = (); |
| 1390 | our $cnt_lines = 0; | 1392 | our $cnt_lines = 0; |
| 1391 | our $cnt_error = 0; | 1393 | our $cnt_error = 0; |
| @@ -1686,10 +1688,17 @@ sub process { | |||
| 1686 | $in_commit_log = 1; | 1688 | $in_commit_log = 1; |
| 1687 | } | 1689 | } |
| 1688 | 1690 | ||
| 1689 | # Still not yet in a patch, check for any UTF-8 | 1691 | # Check if there is UTF-8 in a commit log when a mail header has explicitly |
| 1690 | if ($in_commit_log && $realfile =~ /^$/ && | 1692 | # declined it, i.e defined some charset where it is missing. |
| 1693 | if ($in_header_lines && | ||
| 1694 | $rawline =~ /^Content-Type:.+charset="(.+)".*$/ && | ||
| 1695 | $1 !~ /utf-8/i) { | ||
| 1696 | $non_utf8_charset = 1; | ||
| 1697 | } | ||
| 1698 | |||
| 1699 | if ($in_commit_log && $non_utf8_charset && $realfile =~ /^$/ && | ||
| 1691 | $rawline =~ /$NON_ASCII_UTF8/) { | 1700 | $rawline =~ /$NON_ASCII_UTF8/) { |
| 1692 | CHK("UTF8_BEFORE_PATCH", | 1701 | WARN("UTF8_BEFORE_PATCH", |
| 1693 | "8-bit UTF-8 used in possible commit log\n" . $herecurr); | 1702 | "8-bit UTF-8 used in possible commit log\n" . $herecurr); |
| 1694 | } | 1703 | } |
| 1695 | 1704 | ||
| @@ -1873,6 +1882,20 @@ sub process { | |||
| 1873 | "No space is necessary after a cast\n" . $hereprev); | 1882 | "No space is necessary after a cast\n" . $hereprev); |
| 1874 | } | 1883 | } |
| 1875 | 1884 | ||
| 1885 | if ($realfile =~ m@^(drivers/net/|net/)@ && | ||
| 1886 | $rawline =~ /^\+[ \t]*\/\*[ \t]*$/ && | ||
| 1887 | $prevrawline =~ /^\+[ \t]*$/) { | ||
| 1888 | WARN("NETWORKING_BLOCK_COMMENT_STYLE", | ||
| 1889 | "networking block comments don't use an empty /* line, use /* Comment...\n" . $hereprev); | ||
| 1890 | } | ||
| 1891 | |||
| 1892 | if ($realfile =~ m@^(drivers/net/|net/)@ && | ||
| 1893 | $rawline !~ m@^\+[ \t]*(\/\*|\*\/)@ && | ||
| 1894 | $rawline =~ m@^\+[ \t]*.+\*\/[ \t]*$@) { | ||
| 1895 | WARN("NETWORKING_BLOCK_COMMENT_STYLE", | ||
| 1896 | "networking block comments put the trailing */ on a separate line\n" . $herecurr); | ||
| 1897 | } | ||
| 1898 | |||
| 1876 | # check for spaces at the beginning of a line. | 1899 | # check for spaces at the beginning of a line. |
| 1877 | # Exceptions: | 1900 | # Exceptions: |
| 1878 | # 1) within comments | 1901 | # 1) within comments |
| @@ -2390,8 +2413,10 @@ sub process { | |||
| 2390 | my $orig = $1; | 2413 | my $orig = $1; |
| 2391 | my $level = lc($orig); | 2414 | my $level = lc($orig); |
| 2392 | $level = "warn" if ($level eq "warning"); | 2415 | $level = "warn" if ($level eq "warning"); |
| 2416 | my $level2 = $level; | ||
| 2417 | $level2 = "dbg" if ($level eq "debug"); | ||
| 2393 | WARN("PREFER_PR_LEVEL", | 2418 | WARN("PREFER_PR_LEVEL", |
| 2394 | "Prefer pr_$level(... to printk(KERN_$1, ...\n" . $herecurr); | 2419 | "Prefer netdev_$level2(netdev, ... then dev_$level2(dev, ... then pr_$level(... to printk(KERN_$orig ...\n" . $herecurr); |
| 2395 | } | 2420 | } |
| 2396 | 2421 | ||
| 2397 | if ($line =~ /\bpr_warning\s*\(/) { | 2422 | if ($line =~ /\bpr_warning\s*\(/) { |
| @@ -2947,7 +2972,7 @@ sub process { | |||
| 2947 | my $exceptions = qr{ | 2972 | my $exceptions = qr{ |
| 2948 | $Declare| | 2973 | $Declare| |
| 2949 | module_param_named| | 2974 | module_param_named| |
| 2950 | MODULE_PARAM_DESC| | 2975 | MODULE_PARM_DESC| |
| 2951 | DECLARE_PER_CPU| | 2976 | DECLARE_PER_CPU| |
| 2952 | DEFINE_PER_CPU| | 2977 | DEFINE_PER_CPU| |
| 2953 | __typeof__\(| | 2978 | __typeof__\(| |
diff --git a/scripts/checksyscalls.sh b/scripts/checksyscalls.sh index d24810fc6af6..fd8fa9aa7c4e 100755 --- a/scripts/checksyscalls.sh +++ b/scripts/checksyscalls.sh | |||
| @@ -200,7 +200,7 @@ EOF | |||
| 200 | syscall_list() { | 200 | syscall_list() { |
| 201 | grep '^[0-9]' "$1" | sort -n | ( | 201 | grep '^[0-9]' "$1" | sort -n | ( |
| 202 | while read nr abi name entry ; do | 202 | while read nr abi name entry ; do |
| 203 | echo <<EOF | 203 | cat <<EOF |
| 204 | #if !defined(__NR_${name}) && !defined(__IGNORE_${name}) | 204 | #if !defined(__NR_${name}) && !defined(__IGNORE_${name}) |
| 205 | #warning syscall ${name} not implemented | 205 | #warning syscall ${name} not implemented |
| 206 | #endif | 206 | #endif |
diff --git a/scripts/coccicheck b/scripts/coccicheck index 823e972149e5..1a49d1c7ecfe 100755 --- a/scripts/coccicheck +++ b/scripts/coccicheck | |||
| @@ -95,6 +95,9 @@ coccinelle () { | |||
| 95 | $SPATCH -D report $FLAGS -sp_file $COCCI $OPT $OPTIONS -no_show_diff || \ | 95 | $SPATCH -D report $FLAGS -sp_file $COCCI $OPT $OPTIONS -no_show_diff || \ |
| 96 | $SPATCH -D context $FLAGS -sp_file $COCCI $OPT $OPTIONS || \ | 96 | $SPATCH -D context $FLAGS -sp_file $COCCI $OPT $OPTIONS || \ |
| 97 | $SPATCH -D org $FLAGS -sp_file $COCCI $OPT $OPTIONS -no_show_diff || exit 1 | 97 | $SPATCH -D org $FLAGS -sp_file $COCCI $OPT $OPTIONS -no_show_diff || exit 1 |
| 98 | elif [ "$MODE" = "rep+ctxt" ] ; then | ||
| 99 | $SPATCH -D report $FLAGS -sp_file $COCCI $OPT $OPTIONS -no_show_diff && \ | ||
| 100 | $SPATCH -D context $FLAGS -sp_file $COCCI $OPT $OPTIONS || exit 1 | ||
| 98 | else | 101 | else |
| 99 | $SPATCH -D $MODE $FLAGS -sp_file $COCCI $OPT $OPTIONS || exit 1 | 102 | $SPATCH -D $MODE $FLAGS -sp_file $COCCI $OPT $OPTIONS || exit 1 |
| 100 | fi | 103 | fi |
diff --git a/scripts/coccinelle/api/memdup_user.cocci b/scripts/coccinelle/api/memdup_user.cocci index 2efac289fd59..2b131a8a1306 100644 --- a/scripts/coccinelle/api/memdup_user.cocci +++ b/scripts/coccinelle/api/memdup_user.cocci | |||
| @@ -51,10 +51,10 @@ statement S1,S2; | |||
| 51 | p << r.p; | 51 | p << r.p; |
| 52 | @@ | 52 | @@ |
| 53 | 53 | ||
| 54 | coccilib.org.print_todo(p[0], "WARNING opportunity for memdep_user") | 54 | coccilib.org.print_todo(p[0], "WARNING opportunity for memdup_user") |
| 55 | 55 | ||
| 56 | @script:python depends on report@ | 56 | @script:python depends on report@ |
| 57 | p << r.p; | 57 | p << r.p; |
| 58 | @@ | 58 | @@ |
| 59 | 59 | ||
| 60 | coccilib.report.print_report(p[0], "WARNING opportunity for memdep_user") | 60 | coccilib.report.print_report(p[0], "WARNING opportunity for memdup_user") |
diff --git a/scripts/coccinelle/api/ptr_ret.cocci b/scripts/coccinelle/api/ptr_ret.cocci index cbfd08c7d8c7..15f076fdecbe 100644 --- a/scripts/coccinelle/api/ptr_ret.cocci +++ b/scripts/coccinelle/api/ptr_ret.cocci | |||
| @@ -30,6 +30,13 @@ expression ptr; | |||
| 30 | - if (IS_ERR(ptr)) return PTR_ERR(ptr); return 0; | 30 | - if (IS_ERR(ptr)) return PTR_ERR(ptr); return 0; |
| 31 | + return PTR_RET(ptr); | 31 | + return PTR_RET(ptr); |
| 32 | 32 | ||
| 33 | @depends on patch@ | ||
| 34 | expression ptr; | ||
| 35 | @@ | ||
| 36 | |||
| 37 | - (IS_ERR(ptr) ? PTR_ERR(ptr) : 0) | ||
| 38 | + PTR_RET(ptr) | ||
| 39 | |||
| 33 | @r1 depends on !patch@ | 40 | @r1 depends on !patch@ |
| 34 | expression ptr; | 41 | expression ptr; |
| 35 | position p1; | 42 | position p1; |
| @@ -44,6 +51,13 @@ position p2; | |||
| 44 | 51 | ||
| 45 | * if@p2 (IS_ERR(ptr)) return PTR_ERR(ptr); return 0; | 52 | * if@p2 (IS_ERR(ptr)) return PTR_ERR(ptr); return 0; |
| 46 | 53 | ||
| 54 | @r3 depends on !patch@ | ||
| 55 | expression ptr; | ||
| 56 | position p3; | ||
| 57 | @@ | ||
| 58 | |||
| 59 | * IS_ERR@p3(ptr) ? PTR_ERR(ptr) : 0 | ||
| 60 | |||
| 47 | @script:python depends on org@ | 61 | @script:python depends on org@ |
| 48 | p << r1.p1; | 62 | p << r1.p1; |
| 49 | @@ | 63 | @@ |
| @@ -57,6 +71,12 @@ p << r2.p2; | |||
| 57 | 71 | ||
| 58 | coccilib.org.print_todo(p[0], "WARNING: PTR_RET can be used") | 72 | coccilib.org.print_todo(p[0], "WARNING: PTR_RET can be used") |
| 59 | 73 | ||
| 74 | @script:python depends on org@ | ||
| 75 | p << r3.p3; | ||
| 76 | @@ | ||
| 77 | |||
| 78 | coccilib.org.print_todo(p[0], "WARNING: PTR_RET can be used") | ||
| 79 | |||
| 60 | @script:python depends on report@ | 80 | @script:python depends on report@ |
| 61 | p << r1.p1; | 81 | p << r1.p1; |
| 62 | @@ | 82 | @@ |
| @@ -68,3 +88,9 @@ p << r2.p2; | |||
| 68 | @@ | 88 | @@ |
| 69 | 89 | ||
| 70 | coccilib.report.print_report(p[0], "WARNING: PTR_RET can be used") | 90 | coccilib.report.print_report(p[0], "WARNING: PTR_RET can be used") |
| 91 | |||
| 92 | @script:python depends on report@ | ||
| 93 | p << r3.p3; | ||
| 94 | @@ | ||
| 95 | |||
| 96 | coccilib.report.print_report(p[0], "WARNING: PTR_RET can be used") | ||
diff --git a/scripts/coccinelle/tests/odd_ptr_err.cocci b/scripts/coccinelle/tests/odd_ptr_err.cocci new file mode 100644 index 000000000000..e8dd8a6b28a2 --- /dev/null +++ b/scripts/coccinelle/tests/odd_ptr_err.cocci | |||
| @@ -0,0 +1,65 @@ | |||
| 1 | /// PTR_ERR should access the value just tested by IS_ERR | ||
| 2 | //# There can be false positives in the patch case, where it is the call | ||
| 3 | //# IS_ERR that is wrong. | ||
| 4 | /// | ||
| 5 | // Confidence: High | ||
| 6 | // Copyright: (C) 2012 Julia Lawall, INRIA. GPLv2. | ||
| 7 | // Copyright: (C) 2012 Gilles Muller, INRIA. GPLv2. | ||
| 8 | // URL: http://coccinelle.lip6.fr/ | ||
| 9 | // Comments: | ||
| 10 | // Options: -no_includes -include_headers | ||
| 11 | |||
| 12 | virtual patch | ||
| 13 | virtual context | ||
| 14 | virtual org | ||
| 15 | virtual report | ||
| 16 | |||
| 17 | @depends on patch@ | ||
| 18 | expression e,e1; | ||
| 19 | @@ | ||
| 20 | |||
| 21 | ( | ||
| 22 | if (IS_ERR(e)) { ... PTR_ERR(e) ... } | ||
| 23 | | | ||
| 24 | if (IS_ERR(e=e1)) { ... PTR_ERR(e) ... } | ||
| 25 | | | ||
| 26 | if (IS_ERR(e)) | ||
| 27 | { ... | ||
| 28 | PTR_ERR( | ||
| 29 | - e1 | ||
| 30 | + e | ||
| 31 | ) | ||
| 32 | ... } | ||
| 33 | ) | ||
| 34 | |||
| 35 | @r depends on !patch@ | ||
| 36 | expression e,e1; | ||
| 37 | position p1,p2; | ||
| 38 | @@ | ||
| 39 | |||
| 40 | ( | ||
| 41 | if (IS_ERR(e)) { ... PTR_ERR(e) ... } | ||
| 42 | | | ||
| 43 | if (IS_ERR(e=e1)) { ... PTR_ERR(e) ... } | ||
| 44 | | | ||
| 45 | *if (IS_ERR@p1(e)) | ||
| 46 | { ... | ||
| 47 | * PTR_ERR@p2(e1) | ||
| 48 | ... } | ||
| 49 | ) | ||
| 50 | |||
| 51 | @script:python depends on org@ | ||
| 52 | p1 << r.p1; | ||
| 53 | p2 << r.p2; | ||
| 54 | @@ | ||
| 55 | |||
| 56 | cocci.print_main("inconsistent IS_ERR and PTR_ERR",p1) | ||
| 57 | cocci.print_secs("PTR_ERR",p2) | ||
| 58 | |||
| 59 | @script:python depends on report@ | ||
| 60 | p1 << r.p1; | ||
| 61 | p2 << r.p2; | ||
| 62 | @@ | ||
| 63 | |||
| 64 | msg = "inconsistent IS_ERR and PTR_ERR, PTR_ERR on line %s" % (p2[0].line) | ||
| 65 | coccilib.report.print_report(p1[0],msg) | ||
diff --git a/scripts/dtc/Makefile.dtc b/scripts/dtc/Makefile.dtc index 6ddf9ecac669..bece49b35535 100644 --- a/scripts/dtc/Makefile.dtc +++ b/scripts/dtc/Makefile.dtc | |||
| @@ -3,7 +3,16 @@ | |||
| 3 | # This is not a complete Makefile of itself. Instead, it is designed to | 3 | # This is not a complete Makefile of itself. Instead, it is designed to |
| 4 | # be easily embeddable into other systems of Makefiles. | 4 | # be easily embeddable into other systems of Makefiles. |
| 5 | # | 5 | # |
| 6 | DTC_SRCS = dtc.c flattree.c fstree.c data.c livetree.c treesource.c srcpos.c \ | 6 | DTC_SRCS = \ |
| 7 | checks.c | 7 | checks.c \ |
| 8 | data.c \ | ||
| 9 | dtc.c \ | ||
| 10 | flattree.c \ | ||
| 11 | fstree.c \ | ||
| 12 | livetree.c \ | ||
| 13 | srcpos.c \ | ||
| 14 | treesource.c \ | ||
| 15 | util.c | ||
| 16 | |||
| 8 | DTC_GEN_SRCS = dtc-lexer.lex.c dtc-parser.tab.c | 17 | DTC_GEN_SRCS = dtc-lexer.lex.c dtc-parser.tab.c |
| 9 | DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o) | 18 | DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o) |
diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c index a662a0044798..ee96a2519eff 100644 --- a/scripts/dtc/checks.c +++ b/scripts/dtc/checks.c | |||
| @@ -31,12 +31,6 @@ | |||
| 31 | #define TRACE(c, fmt, ...) do { } while (0) | 31 | #define TRACE(c, fmt, ...) do { } while (0) |
| 32 | #endif | 32 | #endif |
| 33 | 33 | ||
| 34 | enum checklevel { | ||
| 35 | IGNORE = 0, | ||
| 36 | WARN = 1, | ||
| 37 | ERROR = 2, | ||
| 38 | }; | ||
| 39 | |||
| 40 | enum checkstatus { | 34 | enum checkstatus { |
| 41 | UNCHECKED = 0, | 35 | UNCHECKED = 0, |
| 42 | PREREQ, | 36 | PREREQ, |
| @@ -57,14 +51,14 @@ struct check { | |||
| 57 | node_check_fn node_fn; | 51 | node_check_fn node_fn; |
| 58 | prop_check_fn prop_fn; | 52 | prop_check_fn prop_fn; |
| 59 | void *data; | 53 | void *data; |
| 60 | enum checklevel level; | 54 | bool warn, error; |
| 61 | enum checkstatus status; | 55 | enum checkstatus status; |
| 62 | int inprogress; | 56 | int inprogress; |
| 63 | int num_prereqs; | 57 | int num_prereqs; |
| 64 | struct check **prereq; | 58 | struct check **prereq; |
| 65 | }; | 59 | }; |
| 66 | 60 | ||
| 67 | #define CHECK(nm, tfn, nfn, pfn, d, lvl, ...) \ | 61 | #define CHECK_ENTRY(nm, tfn, nfn, pfn, d, w, e, ...) \ |
| 68 | static struct check *nm##_prereqs[] = { __VA_ARGS__ }; \ | 62 | static struct check *nm##_prereqs[] = { __VA_ARGS__ }; \ |
| 69 | static struct check nm = { \ | 63 | static struct check nm = { \ |
| 70 | .name = #nm, \ | 64 | .name = #nm, \ |
| @@ -72,20 +66,37 @@ struct check { | |||
| 72 | .node_fn = (nfn), \ | 66 | .node_fn = (nfn), \ |
| 73 | .prop_fn = (pfn), \ | 67 | .prop_fn = (pfn), \ |
| 74 | .data = (d), \ | 68 | .data = (d), \ |
| 75 | .level = (lvl), \ | 69 | .warn = (w), \ |
| 70 | .error = (e), \ | ||
| 76 | .status = UNCHECKED, \ | 71 | .status = UNCHECKED, \ |
| 77 | .num_prereqs = ARRAY_SIZE(nm##_prereqs), \ | 72 | .num_prereqs = ARRAY_SIZE(nm##_prereqs), \ |
| 78 | .prereq = nm##_prereqs, \ | 73 | .prereq = nm##_prereqs, \ |
| 79 | }; | 74 | }; |
| 80 | 75 | #define WARNING(nm, tfn, nfn, pfn, d, ...) \ | |
| 81 | #define TREE_CHECK(nm, d, lvl, ...) \ | 76 | CHECK_ENTRY(nm, tfn, nfn, pfn, d, true, false, __VA_ARGS__) |
| 82 | CHECK(nm, check_##nm, NULL, NULL, d, lvl, __VA_ARGS__) | 77 | #define ERROR(nm, tfn, nfn, pfn, d, ...) \ |
| 83 | #define NODE_CHECK(nm, d, lvl, ...) \ | 78 | CHECK_ENTRY(nm, tfn, nfn, pfn, d, false, true, __VA_ARGS__) |
| 84 | CHECK(nm, NULL, check_##nm, NULL, d, lvl, __VA_ARGS__) | 79 | #define CHECK(nm, tfn, nfn, pfn, d, ...) \ |
| 85 | #define PROP_CHECK(nm, d, lvl, ...) \ | 80 | CHECK_ENTRY(nm, tfn, nfn, pfn, d, false, false, __VA_ARGS__) |
| 86 | CHECK(nm, NULL, NULL, check_##nm, d, lvl, __VA_ARGS__) | 81 | |
| 87 | #define BATCH_CHECK(nm, lvl, ...) \ | 82 | #define TREE_WARNING(nm, d, ...) \ |
| 88 | CHECK(nm, NULL, NULL, NULL, NULL, lvl, __VA_ARGS__) | 83 | WARNING(nm, check_##nm, NULL, NULL, d, __VA_ARGS__) |
| 84 | #define TREE_ERROR(nm, d, ...) \ | ||
| 85 | ERROR(nm, check_##nm, NULL, NULL, d, __VA_ARGS__) | ||
| 86 | #define TREE_CHECK(nm, d, ...) \ | ||
| 87 | CHECK(nm, check_##nm, NULL, NULL, d, __VA_ARGS__) | ||
| 88 | #define NODE_WARNING(nm, d, ...) \ | ||
| 89 | WARNING(nm, NULL, check_##nm, NULL, d, __VA_ARGS__) | ||
| 90 | #define NODE_ERROR(nm, d, ...) \ | ||
| 91 | ERROR(nm, NULL, check_##nm, NULL, d, __VA_ARGS__) | ||
| 92 | #define NODE_CHECK(nm, d, ...) \ | ||
| 93 | CHECK(nm, NULL, check_##nm, NULL, d, __VA_ARGS__) | ||
| 94 | #define PROP_WARNING(nm, d, ...) \ | ||
| 95 | WARNING(nm, NULL, NULL, check_##nm, d, __VA_ARGS__) | ||
| 96 | #define PROP_ERROR(nm, d, ...) \ | ||
| 97 | ERROR(nm, NULL, NULL, check_##nm, d, __VA_ARGS__) | ||
| 98 | #define PROP_CHECK(nm, d, ...) \ | ||
| 99 | CHECK(nm, NULL, NULL, check_##nm, d, __VA_ARGS__) | ||
| 89 | 100 | ||
| 90 | #ifdef __GNUC__ | 101 | #ifdef __GNUC__ |
| 91 | static inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3))); | 102 | static inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3))); |
| @@ -95,13 +106,13 @@ static inline void check_msg(struct check *c, const char *fmt, ...) | |||
| 95 | va_list ap; | 106 | va_list ap; |
| 96 | va_start(ap, fmt); | 107 | va_start(ap, fmt); |
| 97 | 108 | ||
| 98 | if ((c->level < WARN) || (c->level <= quiet)) | 109 | if ((c->warn && (quiet < 1)) |
| 99 | return; /* Suppress message */ | 110 | || (c->error && (quiet < 2))) { |
| 100 | 111 | fprintf(stderr, "%s (%s): ", | |
| 101 | fprintf(stderr, "%s (%s): ", | 112 | (c->error) ? "ERROR" : "Warning", c->name); |
| 102 | (c->level == ERROR) ? "ERROR" : "Warning", c->name); | 113 | vfprintf(stderr, fmt, ap); |
| 103 | vfprintf(stderr, fmt, ap); | 114 | fprintf(stderr, "\n"); |
| 104 | fprintf(stderr, "\n"); | 115 | } |
| 105 | } | 116 | } |
| 106 | 117 | ||
| 107 | #define FAIL(c, ...) \ | 118 | #define FAIL(c, ...) \ |
| @@ -167,7 +178,7 @@ static int run_check(struct check *c, struct node *dt) | |||
| 167 | 178 | ||
| 168 | out: | 179 | out: |
| 169 | c->inprogress = 0; | 180 | c->inprogress = 0; |
| 170 | if ((c->status != PASSED) && (c->level == ERROR)) | 181 | if ((c->status != PASSED) && (c->error)) |
| 171 | error = 1; | 182 | error = 1; |
| 172 | return error; | 183 | return error; |
| 173 | } | 184 | } |
| @@ -176,6 +187,13 @@ out: | |||
| 176 | * Utility check functions | 187 | * Utility check functions |
| 177 | */ | 188 | */ |
| 178 | 189 | ||
| 190 | /* A check which always fails, for testing purposes only */ | ||
| 191 | static inline void check_always_fail(struct check *c, struct node *dt) | ||
| 192 | { | ||
| 193 | FAIL(c, "always_fail check"); | ||
| 194 | } | ||
| 195 | TREE_CHECK(always_fail, NULL); | ||
| 196 | |||
| 179 | static void check_is_string(struct check *c, struct node *root, | 197 | static void check_is_string(struct check *c, struct node *root, |
| 180 | struct node *node) | 198 | struct node *node) |
| 181 | { | 199 | { |
| @@ -190,8 +208,10 @@ static void check_is_string(struct check *c, struct node *root, | |||
| 190 | FAIL(c, "\"%s\" property in %s is not a string", | 208 | FAIL(c, "\"%s\" property in %s is not a string", |
| 191 | propname, node->fullpath); | 209 | propname, node->fullpath); |
| 192 | } | 210 | } |
| 193 | #define CHECK_IS_STRING(nm, propname, lvl) \ | 211 | #define WARNING_IF_NOT_STRING(nm, propname) \ |
| 194 | CHECK(nm, NULL, check_is_string, NULL, (propname), (lvl)) | 212 | WARNING(nm, NULL, check_is_string, NULL, (propname)) |
| 213 | #define ERROR_IF_NOT_STRING(nm, propname) \ | ||
| 214 | ERROR(nm, NULL, check_is_string, NULL, (propname)) | ||
| 195 | 215 | ||
| 196 | static void check_is_cell(struct check *c, struct node *root, | 216 | static void check_is_cell(struct check *c, struct node *root, |
| 197 | struct node *node) | 217 | struct node *node) |
| @@ -207,8 +227,10 @@ static void check_is_cell(struct check *c, struct node *root, | |||
| 207 | FAIL(c, "\"%s\" property in %s is not a single cell", | 227 | FAIL(c, "\"%s\" property in %s is not a single cell", |
| 208 | propname, node->fullpath); | 228 | propname, node->fullpath); |
| 209 | } | 229 | } |
| 210 | #define CHECK_IS_CELL(nm, propname, lvl) \ | 230 | #define WARNING_IF_NOT_CELL(nm, propname) \ |
| 211 | CHECK(nm, NULL, check_is_cell, NULL, (propname), (lvl)) | 231 | WARNING(nm, NULL, check_is_cell, NULL, (propname)) |
| 232 | #define ERROR_IF_NOT_CELL(nm, propname) \ | ||
| 233 | ERROR(nm, NULL, check_is_cell, NULL, (propname)) | ||
| 212 | 234 | ||
| 213 | /* | 235 | /* |
| 214 | * Structural check functions | 236 | * Structural check functions |
| @@ -227,20 +249,24 @@ static void check_duplicate_node_names(struct check *c, struct node *dt, | |||
| 227 | FAIL(c, "Duplicate node name %s", | 249 | FAIL(c, "Duplicate node name %s", |
| 228 | child->fullpath); | 250 | child->fullpath); |
| 229 | } | 251 | } |
| 230 | NODE_CHECK(duplicate_node_names, NULL, ERROR); | 252 | NODE_ERROR(duplicate_node_names, NULL); |
| 231 | 253 | ||
| 232 | static void check_duplicate_property_names(struct check *c, struct node *dt, | 254 | static void check_duplicate_property_names(struct check *c, struct node *dt, |
| 233 | struct node *node) | 255 | struct node *node) |
| 234 | { | 256 | { |
| 235 | struct property *prop, *prop2; | 257 | struct property *prop, *prop2; |
| 236 | 258 | ||
| 237 | for_each_property(node, prop) | 259 | for_each_property(node, prop) { |
| 238 | for (prop2 = prop->next; prop2; prop2 = prop2->next) | 260 | for (prop2 = prop->next; prop2; prop2 = prop2->next) { |
| 261 | if (prop2->deleted) | ||
| 262 | continue; | ||
| 239 | if (streq(prop->name, prop2->name)) | 263 | if (streq(prop->name, prop2->name)) |
| 240 | FAIL(c, "Duplicate property name %s in %s", | 264 | FAIL(c, "Duplicate property name %s in %s", |
| 241 | prop->name, node->fullpath); | 265 | prop->name, node->fullpath); |
| 266 | } | ||
| 267 | } | ||
| 242 | } | 268 | } |
| 243 | NODE_CHECK(duplicate_property_names, NULL, ERROR); | 269 | NODE_ERROR(duplicate_property_names, NULL); |
| 244 | 270 | ||
| 245 | #define LOWERCASE "abcdefghijklmnopqrstuvwxyz" | 271 | #define LOWERCASE "abcdefghijklmnopqrstuvwxyz" |
| 246 | #define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ" | 272 | #define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ" |
| @@ -256,7 +282,7 @@ static void check_node_name_chars(struct check *c, struct node *dt, | |||
| 256 | FAIL(c, "Bad character '%c' in node %s", | 282 | FAIL(c, "Bad character '%c' in node %s", |
| 257 | node->name[n], node->fullpath); | 283 | node->name[n], node->fullpath); |
| 258 | } | 284 | } |
| 259 | NODE_CHECK(node_name_chars, PROPNODECHARS "@", ERROR); | 285 | NODE_ERROR(node_name_chars, PROPNODECHARS "@"); |
| 260 | 286 | ||
| 261 | static void check_node_name_format(struct check *c, struct node *dt, | 287 | static void check_node_name_format(struct check *c, struct node *dt, |
| 262 | struct node *node) | 288 | struct node *node) |
| @@ -265,7 +291,7 @@ static void check_node_name_format(struct check *c, struct node *dt, | |||
| 265 | FAIL(c, "Node %s has multiple '@' characters in name", | 291 | FAIL(c, "Node %s has multiple '@' characters in name", |
| 266 | node->fullpath); | 292 | node->fullpath); |
| 267 | } | 293 | } |
| 268 | NODE_CHECK(node_name_format, NULL, ERROR, &node_name_chars); | 294 | NODE_ERROR(node_name_format, NULL, &node_name_chars); |
| 269 | 295 | ||
| 270 | static void check_property_name_chars(struct check *c, struct node *dt, | 296 | static void check_property_name_chars(struct check *c, struct node *dt, |
| 271 | struct node *node, struct property *prop) | 297 | struct node *node, struct property *prop) |
| @@ -276,7 +302,7 @@ static void check_property_name_chars(struct check *c, struct node *dt, | |||
| 276 | FAIL(c, "Bad character '%c' in property name \"%s\", node %s", | 302 | FAIL(c, "Bad character '%c' in property name \"%s\", node %s", |
| 277 | prop->name[n], prop->name, node->fullpath); | 303 | prop->name[n], prop->name, node->fullpath); |
| 278 | } | 304 | } |
| 279 | PROP_CHECK(property_name_chars, PROPNODECHARS, ERROR); | 305 | PROP_ERROR(property_name_chars, PROPNODECHARS); |
| 280 | 306 | ||
| 281 | #define DESCLABEL_FMT "%s%s%s%s%s" | 307 | #define DESCLABEL_FMT "%s%s%s%s%s" |
| 282 | #define DESCLABEL_ARGS(node,prop,mark) \ | 308 | #define DESCLABEL_ARGS(node,prop,mark) \ |
| @@ -331,8 +357,8 @@ static void check_duplicate_label_prop(struct check *c, struct node *dt, | |||
| 331 | for_each_marker_of_type(m, LABEL) | 357 | for_each_marker_of_type(m, LABEL) |
| 332 | check_duplicate_label(c, dt, m->ref, node, prop, m); | 358 | check_duplicate_label(c, dt, m->ref, node, prop, m); |
| 333 | } | 359 | } |
| 334 | CHECK(duplicate_label, NULL, check_duplicate_label_node, | 360 | ERROR(duplicate_label, NULL, check_duplicate_label_node, |
| 335 | check_duplicate_label_prop, NULL, ERROR); | 361 | check_duplicate_label_prop, NULL); |
| 336 | 362 | ||
| 337 | static void check_explicit_phandles(struct check *c, struct node *root, | 363 | static void check_explicit_phandles(struct check *c, struct node *root, |
| 338 | struct node *node, struct property *prop) | 364 | struct node *node, struct property *prop) |
| @@ -391,7 +417,7 @@ static void check_explicit_phandles(struct check *c, struct node *root, | |||
| 391 | 417 | ||
| 392 | node->phandle = phandle; | 418 | node->phandle = phandle; |
| 393 | } | 419 | } |
| 394 | PROP_CHECK(explicit_phandles, NULL, ERROR); | 420 | PROP_ERROR(explicit_phandles, NULL); |
| 395 | 421 | ||
| 396 | static void check_name_properties(struct check *c, struct node *root, | 422 | static void check_name_properties(struct check *c, struct node *root, |
| 397 | struct node *node) | 423 | struct node *node) |
| @@ -420,8 +446,8 @@ static void check_name_properties(struct check *c, struct node *root, | |||
| 420 | free(prop); | 446 | free(prop); |
| 421 | } | 447 | } |
| 422 | } | 448 | } |
| 423 | CHECK_IS_STRING(name_is_string, "name", ERROR); | 449 | ERROR_IF_NOT_STRING(name_is_string, "name"); |
| 424 | NODE_CHECK(name_properties, NULL, ERROR, &name_is_string); | 450 | NODE_ERROR(name_properties, NULL, &name_is_string); |
| 425 | 451 | ||
| 426 | /* | 452 | /* |
| 427 | * Reference fixup functions | 453 | * Reference fixup functions |
| @@ -448,7 +474,7 @@ static void fixup_phandle_references(struct check *c, struct node *dt, | |||
| 448 | *((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle); | 474 | *((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle); |
| 449 | } | 475 | } |
| 450 | } | 476 | } |
| 451 | CHECK(phandle_references, NULL, NULL, fixup_phandle_references, NULL, ERROR, | 477 | ERROR(phandle_references, NULL, NULL, fixup_phandle_references, NULL, |
| 452 | &duplicate_node_names, &explicit_phandles); | 478 | &duplicate_node_names, &explicit_phandles); |
| 453 | 479 | ||
| 454 | static void fixup_path_references(struct check *c, struct node *dt, | 480 | static void fixup_path_references(struct check *c, struct node *dt, |
| @@ -473,19 +499,19 @@ static void fixup_path_references(struct check *c, struct node *dt, | |||
| 473 | strlen(path) + 1); | 499 | strlen(path) + 1); |
| 474 | } | 500 | } |
| 475 | } | 501 | } |
| 476 | CHECK(path_references, NULL, NULL, fixup_path_references, NULL, ERROR, | 502 | ERROR(path_references, NULL, NULL, fixup_path_references, NULL, |
| 477 | &duplicate_node_names); | 503 | &duplicate_node_names); |
| 478 | 504 | ||
| 479 | /* | 505 | /* |
| 480 | * Semantic checks | 506 | * Semantic checks |
| 481 | */ | 507 | */ |
| 482 | CHECK_IS_CELL(address_cells_is_cell, "#address-cells", WARN); | 508 | WARNING_IF_NOT_CELL(address_cells_is_cell, "#address-cells"); |
| 483 | CHECK_IS_CELL(size_cells_is_cell, "#size-cells", WARN); | 509 | WARNING_IF_NOT_CELL(size_cells_is_cell, "#size-cells"); |
| 484 | CHECK_IS_CELL(interrupt_cells_is_cell, "#interrupt-cells", WARN); | 510 | WARNING_IF_NOT_CELL(interrupt_cells_is_cell, "#interrupt-cells"); |
| 485 | 511 | ||
| 486 | CHECK_IS_STRING(device_type_is_string, "device_type", WARN); | 512 | WARNING_IF_NOT_STRING(device_type_is_string, "device_type"); |
| 487 | CHECK_IS_STRING(model_is_string, "model", WARN); | 513 | WARNING_IF_NOT_STRING(model_is_string, "model"); |
| 488 | CHECK_IS_STRING(status_is_string, "status", WARN); | 514 | WARNING_IF_NOT_STRING(status_is_string, "status"); |
| 489 | 515 | ||
| 490 | static void fixup_addr_size_cells(struct check *c, struct node *dt, | 516 | static void fixup_addr_size_cells(struct check *c, struct node *dt, |
| 491 | struct node *node) | 517 | struct node *node) |
| @@ -503,8 +529,8 @@ static void fixup_addr_size_cells(struct check *c, struct node *dt, | |||
| 503 | if (prop) | 529 | if (prop) |
| 504 | node->size_cells = propval_cell(prop); | 530 | node->size_cells = propval_cell(prop); |
| 505 | } | 531 | } |
| 506 | CHECK(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL, WARN, | 532 | WARNING(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL, |
| 507 | &address_cells_is_cell, &size_cells_is_cell); | 533 | &address_cells_is_cell, &size_cells_is_cell); |
| 508 | 534 | ||
| 509 | #define node_addr_cells(n) \ | 535 | #define node_addr_cells(n) \ |
| 510 | (((n)->addr_cells == -1) ? 2 : (n)->addr_cells) | 536 | (((n)->addr_cells == -1) ? 2 : (n)->addr_cells) |
| @@ -538,7 +564,7 @@ static void check_reg_format(struct check *c, struct node *dt, | |||
| 538 | "(#address-cells == %d, #size-cells == %d)", | 564 | "(#address-cells == %d, #size-cells == %d)", |
| 539 | node->fullpath, prop->val.len, addr_cells, size_cells); | 565 | node->fullpath, prop->val.len, addr_cells, size_cells); |
| 540 | } | 566 | } |
| 541 | NODE_CHECK(reg_format, NULL, WARN, &addr_size_cells); | 567 | NODE_WARNING(reg_format, NULL, &addr_size_cells); |
| 542 | 568 | ||
| 543 | static void check_ranges_format(struct check *c, struct node *dt, | 569 | static void check_ranges_format(struct check *c, struct node *dt, |
| 544 | struct node *node) | 570 | struct node *node) |
| @@ -579,7 +605,7 @@ static void check_ranges_format(struct check *c, struct node *dt, | |||
| 579 | p_addr_cells, c_addr_cells, c_size_cells); | 605 | p_addr_cells, c_addr_cells, c_size_cells); |
| 580 | } | 606 | } |
| 581 | } | 607 | } |
| 582 | NODE_CHECK(ranges_format, NULL, WARN, &addr_size_cells); | 608 | NODE_WARNING(ranges_format, NULL, &addr_size_cells); |
| 583 | 609 | ||
| 584 | /* | 610 | /* |
| 585 | * Style checks | 611 | * Style checks |
| @@ -606,7 +632,7 @@ static void check_avoid_default_addr_size(struct check *c, struct node *dt, | |||
| 606 | FAIL(c, "Relying on default #size-cells value for %s", | 632 | FAIL(c, "Relying on default #size-cells value for %s", |
| 607 | node->fullpath); | 633 | node->fullpath); |
| 608 | } | 634 | } |
| 609 | NODE_CHECK(avoid_default_addr_size, NULL, WARN, &addr_size_cells); | 635 | NODE_WARNING(avoid_default_addr_size, NULL, &addr_size_cells); |
| 610 | 636 | ||
| 611 | static void check_obsolete_chosen_interrupt_controller(struct check *c, | 637 | static void check_obsolete_chosen_interrupt_controller(struct check *c, |
| 612 | struct node *dt) | 638 | struct node *dt) |
| @@ -623,7 +649,7 @@ static void check_obsolete_chosen_interrupt_controller(struct check *c, | |||
| 623 | FAIL(c, "/chosen has obsolete \"interrupt-controller\" " | 649 | FAIL(c, "/chosen has obsolete \"interrupt-controller\" " |
| 624 | "property"); | 650 | "property"); |
| 625 | } | 651 | } |
| 626 | TREE_CHECK(obsolete_chosen_interrupt_controller, NULL, WARN); | 652 | TREE_WARNING(obsolete_chosen_interrupt_controller, NULL); |
| 627 | 653 | ||
| 628 | static struct check *check_table[] = { | 654 | static struct check *check_table[] = { |
| 629 | &duplicate_node_names, &duplicate_property_names, | 655 | &duplicate_node_names, &duplicate_property_names, |
| @@ -642,8 +668,71 @@ static struct check *check_table[] = { | |||
| 642 | 668 | ||
| 643 | &avoid_default_addr_size, | 669 | &avoid_default_addr_size, |
| 644 | &obsolete_chosen_interrupt_controller, | 670 | &obsolete_chosen_interrupt_controller, |
| 671 | |||
| 672 | &always_fail, | ||
| 645 | }; | 673 | }; |
| 646 | 674 | ||
| 675 | static void enable_warning_error(struct check *c, bool warn, bool error) | ||
| 676 | { | ||
| 677 | int i; | ||
| 678 | |||
| 679 | /* Raising level, also raise it for prereqs */ | ||
| 680 | if ((warn && !c->warn) || (error && !c->error)) | ||
| 681 | for (i = 0; i < c->num_prereqs; i++) | ||
| 682 | enable_warning_error(c->prereq[i], warn, error); | ||
| 683 | |||
| 684 | c->warn = c->warn || warn; | ||
| 685 | c->error = c->error || error; | ||
| 686 | } | ||
| 687 | |||
| 688 | static void disable_warning_error(struct check *c, bool warn, bool error) | ||
| 689 | { | ||
| 690 | int i; | ||
| 691 | |||
| 692 | /* Lowering level, also lower it for things this is the prereq | ||
| 693 | * for */ | ||
| 694 | if ((warn && c->warn) || (error && c->error)) { | ||
| 695 | for (i = 0; i < ARRAY_SIZE(check_table); i++) { | ||
| 696 | struct check *cc = check_table[i]; | ||
| 697 | int j; | ||
| 698 | |||
| 699 | for (j = 0; j < cc->num_prereqs; j++) | ||
| 700 | if (cc->prereq[j] == c) | ||
| 701 | disable_warning_error(cc, warn, error); | ||
| 702 | } | ||
| 703 | } | ||
| 704 | |||
| 705 | c->warn = c->warn && !warn; | ||
| 706 | c->error = c->error && !error; | ||
| 707 | } | ||
| 708 | |||
| 709 | void parse_checks_option(bool warn, bool error, const char *optarg) | ||
| 710 | { | ||
| 711 | int i; | ||
| 712 | const char *name = optarg; | ||
| 713 | bool enable = true; | ||
| 714 | |||
| 715 | if ((strncmp(optarg, "no-", 3) == 0) | ||
| 716 | || (strncmp(optarg, "no_", 3) == 0)) { | ||
| 717 | name = optarg + 3; | ||
| 718 | enable = false; | ||
| 719 | } | ||
| 720 | |||
| 721 | for (i = 0; i < ARRAY_SIZE(check_table); i++) { | ||
| 722 | struct check *c = check_table[i]; | ||
| 723 | |||
| 724 | if (streq(c->name, name)) { | ||
| 725 | if (enable) | ||
| 726 | enable_warning_error(c, warn, error); | ||
| 727 | else | ||
| 728 | disable_warning_error(c, warn, error); | ||
| 729 | return; | ||
| 730 | } | ||
| 731 | } | ||
| 732 | |||
| 733 | die("Unrecognized check name \"%s\"\n", name); | ||
| 734 | } | ||
| 735 | |||
| 647 | void process_checks(int force, struct boot_info *bi) | 736 | void process_checks(int force, struct boot_info *bi) |
| 648 | { | 737 | { |
| 649 | struct node *dt = bi->dt; | 738 | struct node *dt = bi->dt; |
| @@ -653,7 +742,7 @@ void process_checks(int force, struct boot_info *bi) | |||
| 653 | for (i = 0; i < ARRAY_SIZE(check_table); i++) { | 742 | for (i = 0; i < ARRAY_SIZE(check_table); i++) { |
| 654 | struct check *c = check_table[i]; | 743 | struct check *c = check_table[i]; |
| 655 | 744 | ||
| 656 | if (c->level != IGNORE) | 745 | if (c->warn || c->error) |
| 657 | error = error || run_check(c, dt); | 746 | error = error || run_check(c, dt); |
| 658 | } | 747 | } |
| 659 | 748 | ||
diff --git a/scripts/dtc/data.c b/scripts/dtc/data.c index fe555e819bf8..4a40c5b92474 100644 --- a/scripts/dtc/data.c +++ b/scripts/dtc/data.c | |||
| @@ -68,40 +68,6 @@ struct data data_copy_mem(const char *mem, int len) | |||
| 68 | return d; | 68 | return d; |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | static char get_oct_char(const char *s, int *i) | ||
| 72 | { | ||
| 73 | char x[4]; | ||
| 74 | char *endx; | ||
| 75 | long val; | ||
| 76 | |||
| 77 | x[3] = '\0'; | ||
| 78 | strncpy(x, s + *i, 3); | ||
| 79 | |||
| 80 | val = strtol(x, &endx, 8); | ||
| 81 | |||
| 82 | assert(endx > x); | ||
| 83 | |||
| 84 | (*i) += endx - x; | ||
| 85 | return val; | ||
| 86 | } | ||
| 87 | |||
| 88 | static char get_hex_char(const char *s, int *i) | ||
| 89 | { | ||
| 90 | char x[3]; | ||
| 91 | char *endx; | ||
| 92 | long val; | ||
| 93 | |||
| 94 | x[2] = '\0'; | ||
| 95 | strncpy(x, s + *i, 2); | ||
| 96 | |||
| 97 | val = strtol(x, &endx, 16); | ||
| 98 | if (!(endx > x)) | ||
| 99 | die("\\x used with no following hex digits\n"); | ||
| 100 | |||
| 101 | (*i) += endx - x; | ||
| 102 | return val; | ||
| 103 | } | ||
| 104 | |||
| 105 | struct data data_copy_escape_string(const char *s, int len) | 71 | struct data data_copy_escape_string(const char *s, int len) |
| 106 | { | 72 | { |
| 107 | int i = 0; | 73 | int i = 0; |
| @@ -114,53 +80,10 @@ struct data data_copy_escape_string(const char *s, int len) | |||
| 114 | while (i < len) { | 80 | while (i < len) { |
| 115 | char c = s[i++]; | 81 | char c = s[i++]; |
| 116 | 82 | ||
| 117 | if (c != '\\') { | 83 | if (c == '\\') |
| 118 | q[d.len++] = c; | 84 | c = get_escape_char(s, &i); |
| 119 | continue; | 85 | |
| 120 | } | 86 | q[d.len++] = c; |
| 121 | |||
| 122 | c = s[i++]; | ||
| 123 | assert(c); | ||
| 124 | switch (c) { | ||
| 125 | case 'a': | ||
| 126 | q[d.len++] = '\a'; | ||
| 127 | break; | ||
| 128 | case 'b': | ||
| 129 | q[d.len++] = '\b'; | ||
| 130 | break; | ||
| 131 | case 't': | ||
| 132 | q[d.len++] = '\t'; | ||
| 133 | break; | ||
| 134 | case 'n': | ||
| 135 | q[d.len++] = '\n'; | ||
| 136 | break; | ||
| 137 | case 'v': | ||
| 138 | q[d.len++] = '\v'; | ||
| 139 | break; | ||
| 140 | case 'f': | ||
| 141 | q[d.len++] = '\f'; | ||
| 142 | break; | ||
| 143 | case 'r': | ||
| 144 | q[d.len++] = '\r'; | ||
| 145 | break; | ||
| 146 | case '0': | ||
| 147 | case '1': | ||
| 148 | case '2': | ||
| 149 | case '3': | ||
| 150 | case '4': | ||
| 151 | case '5': | ||
| 152 | case '6': | ||
| 153 | case '7': | ||
| 154 | i--; /* need to re-read the first digit as | ||
| 155 | * part of the octal value */ | ||
| 156 | q[d.len++] = get_oct_char(s, &i); | ||
| 157 | break; | ||
| 158 | case 'x': | ||
| 159 | q[d.len++] = get_hex_char(s, &i); | ||
| 160 | break; | ||
| 161 | default: | ||
| 162 | q[d.len++] = c; | ||
| 163 | } | ||
| 164 | } | 87 | } |
| 165 | 88 | ||
| 166 | q[d.len++] = '\0'; | 89 | q[d.len++] = '\0'; |
| @@ -245,11 +168,33 @@ struct data data_merge(struct data d1, struct data d2) | |||
| 245 | return d; | 168 | return d; |
| 246 | } | 169 | } |
| 247 | 170 | ||
| 248 | struct data data_append_cell(struct data d, cell_t word) | 171 | struct data data_append_integer(struct data d, uint64_t value, int bits) |
| 249 | { | 172 | { |
| 250 | cell_t beword = cpu_to_fdt32(word); | 173 | uint8_t value_8; |
| 251 | 174 | uint16_t value_16; | |
| 252 | return data_append_data(d, &beword, sizeof(beword)); | 175 | uint32_t value_32; |
| 176 | uint64_t value_64; | ||
| 177 | |||
| 178 | switch (bits) { | ||
| 179 | case 8: | ||
| 180 | value_8 = value; | ||
| 181 | return data_append_data(d, &value_8, 1); | ||
| 182 | |||
| 183 | case 16: | ||
| 184 | value_16 = cpu_to_fdt16(value); | ||
| 185 | return data_append_data(d, &value_16, 2); | ||
| 186 | |||
| 187 | case 32: | ||
| 188 | value_32 = cpu_to_fdt32(value); | ||
| 189 | return data_append_data(d, &value_32, 4); | ||
| 190 | |||
| 191 | case 64: | ||
| 192 | value_64 = cpu_to_fdt64(value); | ||
| 193 | return data_append_data(d, &value_64, 8); | ||
| 194 | |||
| 195 | default: | ||
| 196 | die("Invalid literal size (%d)\n", bits); | ||
| 197 | } | ||
| 253 | } | 198 | } |
| 254 | 199 | ||
| 255 | struct data data_append_re(struct data d, const struct fdt_reserve_entry *re) | 200 | struct data data_append_re(struct data d, const struct fdt_reserve_entry *re) |
| @@ -262,11 +207,14 @@ struct data data_append_re(struct data d, const struct fdt_reserve_entry *re) | |||
| 262 | return data_append_data(d, &bere, sizeof(bere)); | 207 | return data_append_data(d, &bere, sizeof(bere)); |
| 263 | } | 208 | } |
| 264 | 209 | ||
| 265 | struct data data_append_addr(struct data d, uint64_t addr) | 210 | struct data data_append_cell(struct data d, cell_t word) |
| 266 | { | 211 | { |
| 267 | uint64_t beaddr = cpu_to_fdt64(addr); | 212 | return data_append_integer(d, word, sizeof(word) * 8); |
| 213 | } | ||
| 268 | 214 | ||
| 269 | return data_append_data(d, &beaddr, sizeof(beaddr)); | 215 | struct data data_append_addr(struct data d, uint64_t addr) |
| 216 | { | ||
| 217 | return data_append_integer(d, addr, sizeof(addr) * 8); | ||
| 270 | } | 218 | } |
| 271 | 219 | ||
| 272 | struct data data_append_byte(struct data d, uint8_t byte) | 220 | struct data data_append_byte(struct data d, uint8_t byte) |
diff --git a/scripts/dtc/dtc-lexer.l b/scripts/dtc/dtc-lexer.l index e866ea5166ac..254d5af88956 100644 --- a/scripts/dtc/dtc-lexer.l +++ b/scripts/dtc/dtc-lexer.l | |||
| @@ -29,6 +29,7 @@ PROPNODECHAR [a-zA-Z0-9,._+*#?@-] | |||
| 29 | PATHCHAR ({PROPNODECHAR}|[/]) | 29 | PATHCHAR ({PROPNODECHAR}|[/]) |
| 30 | LABEL [a-zA-Z_][a-zA-Z0-9_]* | 30 | LABEL [a-zA-Z_][a-zA-Z0-9_]* |
| 31 | STRING \"([^\\"]|\\.)*\" | 31 | STRING \"([^\\"]|\\.)*\" |
| 32 | CHAR_LITERAL '([^']|\\')*' | ||
| 32 | WS [[:space:]] | 33 | WS [[:space:]] |
| 33 | COMMENT "/*"([^*]|\*+[^*/])*\*+"/" | 34 | COMMENT "/*"([^*]|\*+[^*/])*\*+"/" |
| 34 | LINECOMMENT "//".*\n | 35 | LINECOMMENT "//".*\n |
| @@ -70,6 +71,27 @@ static int pop_input_file(void); | |||
| 70 | push_input_file(name); | 71 | push_input_file(name); |
| 71 | } | 72 | } |
| 72 | 73 | ||
| 74 | <*>^"#"(line)?{WS}+[0-9]+{WS}+{STRING}({WS}+[0-9]+)? { | ||
| 75 | char *line, *tmp, *fn; | ||
| 76 | /* skip text before line # */ | ||
| 77 | line = yytext; | ||
| 78 | while (!isdigit(*line)) | ||
| 79 | line++; | ||
| 80 | /* skip digits in line # */ | ||
| 81 | tmp = line; | ||
| 82 | while (!isspace(*tmp)) | ||
| 83 | tmp++; | ||
| 84 | /* "NULL"-terminate line # */ | ||
| 85 | *tmp = '\0'; | ||
| 86 | /* start of filename */ | ||
| 87 | fn = strchr(tmp + 1, '"') + 1; | ||
| 88 | /* strip trailing " from filename */ | ||
| 89 | tmp = strchr(fn, '"'); | ||
| 90 | *tmp = 0; | ||
| 91 | /* -1 since #line is the number of the next line */ | ||
| 92 | srcpos_set_line(xstrdup(fn), atoi(line) - 1); | ||
| 93 | } | ||
| 94 | |||
| 73 | <*><<EOF>> { | 95 | <*><<EOF>> { |
| 74 | if (!pop_input_file()) { | 96 | if (!pop_input_file()) { |
| 75 | yyterminate(); | 97 | yyterminate(); |
| @@ -96,6 +118,26 @@ static int pop_input_file(void); | |||
| 96 | return DT_MEMRESERVE; | 118 | return DT_MEMRESERVE; |
| 97 | } | 119 | } |
| 98 | 120 | ||
| 121 | <*>"/bits/" { | ||
| 122 | DPRINT("Keyword: /bits/\n"); | ||
| 123 | BEGIN_DEFAULT(); | ||
| 124 | return DT_BITS; | ||
| 125 | } | ||
| 126 | |||
| 127 | <*>"/delete-property/" { | ||
| 128 | DPRINT("Keyword: /delete-property/\n"); | ||
| 129 | DPRINT("<PROPNODENAME>\n"); | ||
| 130 | BEGIN(PROPNODENAME); | ||
| 131 | return DT_DEL_PROP; | ||
| 132 | } | ||
| 133 | |||
| 134 | <*>"/delete-node/" { | ||
| 135 | DPRINT("Keyword: /delete-node/\n"); | ||
| 136 | DPRINT("<PROPNODENAME>\n"); | ||
| 137 | BEGIN(PROPNODENAME); | ||
| 138 | return DT_DEL_NODE; | ||
| 139 | } | ||
| 140 | |||
| 99 | <*>{LABEL}: { | 141 | <*>{LABEL}: { |
| 100 | DPRINT("Label: %s\n", yytext); | 142 | DPRINT("Label: %s\n", yytext); |
| 101 | yylval.labelref = xstrdup(yytext); | 143 | yylval.labelref = xstrdup(yytext); |
| @@ -103,12 +145,19 @@ static int pop_input_file(void); | |||
| 103 | return DT_LABEL; | 145 | return DT_LABEL; |
| 104 | } | 146 | } |
| 105 | 147 | ||
| 106 | <V1>[0-9]+|0[xX][0-9a-fA-F]+ { | 148 | <V1>([0-9]+|0[xX][0-9a-fA-F]+)(U|L|UL|LL|ULL)? { |
| 107 | yylval.literal = xstrdup(yytext); | 149 | yylval.literal = xstrdup(yytext); |
| 108 | DPRINT("Literal: '%s'\n", yylval.literal); | 150 | DPRINT("Literal: '%s'\n", yylval.literal); |
| 109 | return DT_LITERAL; | 151 | return DT_LITERAL; |
| 110 | } | 152 | } |
| 111 | 153 | ||
| 154 | <*>{CHAR_LITERAL} { | ||
| 155 | yytext[yyleng-1] = '\0'; | ||
| 156 | yylval.literal = xstrdup(yytext+1); | ||
| 157 | DPRINT("Character literal: %s\n", yylval.literal); | ||
| 158 | return DT_CHAR_LITERAL; | ||
| 159 | } | ||
| 160 | |||
| 112 | <*>\&{LABEL} { /* label reference */ | 161 | <*>\&{LABEL} { /* label reference */ |
| 113 | DPRINT("Ref: %s\n", yytext+1); | 162 | DPRINT("Ref: %s\n", yytext+1); |
| 114 | yylval.labelref = xstrdup(yytext+1); | 163 | yylval.labelref = xstrdup(yytext+1); |
| @@ -134,9 +183,10 @@ static int pop_input_file(void); | |||
| 134 | return ']'; | 183 | return ']'; |
| 135 | } | 184 | } |
| 136 | 185 | ||
| 137 | <PROPNODENAME>{PROPNODECHAR}+ { | 186 | <PROPNODENAME>\\?{PROPNODECHAR}+ { |
| 138 | DPRINT("PropNodeName: %s\n", yytext); | 187 | DPRINT("PropNodeName: %s\n", yytext); |
| 139 | yylval.propnodename = xstrdup(yytext); | 188 | yylval.propnodename = xstrdup((yytext[0] == '\\') ? |
| 189 | yytext + 1 : yytext); | ||
| 140 | BEGIN_DEFAULT(); | 190 | BEGIN_DEFAULT(); |
| 141 | return DT_PROPNODENAME; | 191 | return DT_PROPNODENAME; |
| 142 | } | 192 | } |
| @@ -150,6 +200,15 @@ static int pop_input_file(void); | |||
| 150 | <*>{COMMENT}+ /* eat C-style comments */ | 200 | <*>{COMMENT}+ /* eat C-style comments */ |
| 151 | <*>{LINECOMMENT}+ /* eat C++-style comments */ | 201 | <*>{LINECOMMENT}+ /* eat C++-style comments */ |
| 152 | 202 | ||
| 203 | <*>"<<" { return DT_LSHIFT; }; | ||
| 204 | <*>">>" { return DT_RSHIFT; }; | ||
| 205 | <*>"<=" { return DT_LE; }; | ||
| 206 | <*>">=" { return DT_GE; }; | ||
| 207 | <*>"==" { return DT_EQ; }; | ||
| 208 | <*>"!=" { return DT_NE; }; | ||
| 209 | <*>"&&" { return DT_AND; }; | ||
| 210 | <*>"||" { return DT_OR; }; | ||
| 211 | |||
| 153 | <*>. { | 212 | <*>. { |
| 154 | DPRINT("Char: %c (\\x%02x)\n", yytext[0], | 213 | DPRINT("Char: %c (\\x%02x)\n", yytext[0], |
| 155 | (unsigned)yytext[0]); | 214 | (unsigned)yytext[0]); |
diff --git a/scripts/dtc/dtc-lexer.lex.c_shipped b/scripts/dtc/dtc-lexer.lex.c_shipped index 8bbe12817050..a6c5fcdfc032 100644 --- a/scripts/dtc/dtc-lexer.lex.c_shipped +++ b/scripts/dtc/dtc-lexer.lex.c_shipped | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | #line 2 "dtc-lexer.lex.c" | ||
| 1 | 2 | ||
| 2 | #line 3 "scripts/dtc/dtc-lexer.lex.c_shipped" | 3 | #line 4 "dtc-lexer.lex.c" |
| 3 | 4 | ||
| 4 | #define YY_INT_ALIGNED short int | 5 | #define YY_INT_ALIGNED short int |
| 5 | 6 | ||
| @@ -53,7 +54,6 @@ typedef int flex_int32_t; | |||
| 53 | typedef unsigned char flex_uint8_t; | 54 | typedef unsigned char flex_uint8_t; |
| 54 | typedef unsigned short int flex_uint16_t; | 55 | typedef unsigned short int flex_uint16_t; |
| 55 | typedef unsigned int flex_uint32_t; | 56 | typedef unsigned int flex_uint32_t; |
| 56 | #endif /* ! C99 */ | ||
| 57 | 57 | ||
| 58 | /* Limits of integral types. */ | 58 | /* Limits of integral types. */ |
| 59 | #ifndef INT8_MIN | 59 | #ifndef INT8_MIN |
| @@ -84,6 +84,8 @@ typedef unsigned int flex_uint32_t; | |||
| 84 | #define UINT32_MAX (4294967295U) | 84 | #define UINT32_MAX (4294967295U) |
| 85 | #endif | 85 | #endif |
| 86 | 86 | ||
| 87 | #endif /* ! C99 */ | ||
| 88 | |||
| 87 | #endif /* ! FLEXINT_H */ | 89 | #endif /* ! FLEXINT_H */ |
| 88 | 90 | ||
| 89 | #ifdef __cplusplus | 91 | #ifdef __cplusplus |
| @@ -140,7 +142,15 @@ typedef unsigned int flex_uint32_t; | |||
| 140 | 142 | ||
| 141 | /* Size of default input buffer. */ | 143 | /* Size of default input buffer. */ |
| 142 | #ifndef YY_BUF_SIZE | 144 | #ifndef YY_BUF_SIZE |
| 145 | #ifdef __ia64__ | ||
| 146 | /* On IA-64, the buffer size is 16k, not 8k. | ||
| 147 | * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. | ||
| 148 | * Ditto for the __ia64__ case accordingly. | ||
| 149 | */ | ||
| 150 | #define YY_BUF_SIZE 32768 | ||
| 151 | #else | ||
| 143 | #define YY_BUF_SIZE 16384 | 152 | #define YY_BUF_SIZE 16384 |
| 153 | #endif /* __ia64__ */ | ||
| 144 | #endif | 154 | #endif |
| 145 | 155 | ||
| 146 | /* The state buf must be large enough to hold one state per character in the main buffer. | 156 | /* The state buf must be large enough to hold one state per character in the main buffer. |
| @@ -362,8 +372,8 @@ static void yy_fatal_error (yyconst char msg[] ); | |||
| 362 | *yy_cp = '\0'; \ | 372 | *yy_cp = '\0'; \ |
| 363 | (yy_c_buf_p) = yy_cp; | 373 | (yy_c_buf_p) = yy_cp; |
| 364 | 374 | ||
| 365 | #define YY_NUM_RULES 17 | 375 | #define YY_NUM_RULES 30 |
| 366 | #define YY_END_OF_BUFFER 18 | 376 | #define YY_END_OF_BUFFER 31 |
| 367 | /* This struct is not used in this scanner, | 377 | /* This struct is not used in this scanner, |
| 368 | but its presence is necessary. */ | 378 | but its presence is necessary. */ |
| 369 | struct yy_trans_info | 379 | struct yy_trans_info |
| @@ -371,19 +381,25 @@ struct yy_trans_info | |||
| 371 | flex_int32_t yy_verify; | 381 | flex_int32_t yy_verify; |
| 372 | flex_int32_t yy_nxt; | 382 | flex_int32_t yy_nxt; |
| 373 | }; | 383 | }; |
| 374 | static yyconst flex_int16_t yy_accept[94] = | 384 | static yyconst flex_int16_t yy_accept[161] = |
| 375 | { 0, | 385 | { 0, |
| 376 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 386 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 377 | 18, 16, 13, 13, 16, 16, 16, 16, 16, 16, | 387 | 31, 29, 18, 18, 29, 29, 29, 29, 29, 29, |
| 378 | 16, 10, 11, 11, 6, 6, 13, 0, 2, 0, | 388 | 29, 29, 29, 29, 29, 29, 29, 29, 15, 16, |
| 379 | 7, 0, 0, 0, 0, 0, 0, 0, 5, 0, | 389 | 16, 29, 16, 10, 10, 18, 26, 0, 3, 0, |
| 380 | 9, 9, 11, 11, 6, 0, 7, 0, 0, 0, | 390 | 27, 12, 0, 0, 11, 0, 0, 0, 0, 0, |
| 381 | 0, 15, 0, 0, 0, 0, 6, 0, 14, 0, | 391 | 0, 0, 21, 23, 25, 24, 22, 0, 9, 28, |
| 382 | 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, | 392 | 0, 0, 0, 14, 14, 16, 16, 16, 10, 10, |
| 383 | 0, 0, 0, 0, 0, 0, 0, 0, 3, 12, | 393 | 10, 0, 12, 0, 11, 0, 0, 0, 20, 0, |
| 384 | 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, | 394 | 0, 0, 0, 0, 0, 0, 0, 16, 10, 10, |
| 385 | 0, 4, 0 | 395 | 10, 0, 19, 0, 0, 0, 0, 0, 0, 0, |
| 386 | 396 | ||
| 397 | 0, 0, 16, 13, 0, 0, 0, 0, 0, 0, | ||
| 398 | 0, 0, 0, 16, 6, 0, 0, 0, 0, 0, | ||
| 399 | 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 400 | 4, 17, 0, 0, 2, 0, 0, 0, 0, 0, | ||
| 401 | 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, | ||
| 402 | 0, 0, 5, 8, 0, 0, 0, 0, 7, 0 | ||
| 387 | } ; | 403 | } ; |
| 388 | 404 | ||
| 389 | static yyconst flex_int32_t yy_ec[256] = | 405 | static yyconst flex_int32_t yy_ec[256] = |
| @@ -391,17 +407,17 @@ static yyconst flex_int32_t yy_ec[256] = | |||
| 391 | 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, | 407 | 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, |
| 392 | 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, | 408 | 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, |
| 393 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | 409 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| 394 | 1, 2, 1, 4, 5, 1, 1, 6, 1, 1, | 410 | 1, 2, 4, 5, 6, 1, 1, 7, 8, 1, |
| 395 | 1, 7, 5, 5, 8, 5, 9, 10, 11, 12, | 411 | 1, 9, 10, 10, 11, 10, 12, 13, 14, 15, |
| 396 | 12, 12, 12, 12, 12, 12, 12, 13, 1, 1, | 412 | 15, 15, 15, 15, 15, 15, 15, 16, 1, 17, |
| 397 | 1, 1, 5, 5, 14, 14, 14, 14, 14, 14, | 413 | 18, 19, 10, 10, 20, 20, 20, 20, 20, 20, |
| 398 | 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, | 414 | 21, 21, 21, 21, 21, 22, 21, 21, 21, 21, |
| 399 | 15, 15, 15, 15, 15, 15, 15, 16, 15, 15, | 415 | 21, 21, 21, 21, 23, 21, 21, 24, 21, 21, |
| 400 | 1, 17, 18, 1, 15, 1, 14, 19, 20, 21, | 416 | 1, 25, 26, 1, 21, 1, 20, 27, 28, 29, |
| 401 | 417 | ||
| 402 | 22, 14, 15, 15, 23, 15, 15, 24, 25, 26, | 418 | 30, 20, 21, 21, 31, 21, 21, 32, 33, 34, |
| 403 | 15, 15, 15, 27, 28, 29, 30, 31, 15, 16, | 419 | 35, 36, 21, 37, 38, 39, 40, 41, 21, 24, |
| 404 | 15, 15, 32, 1, 33, 1, 1, 1, 1, 1, | 420 | 42, 21, 43, 44, 45, 1, 1, 1, 1, 1, |
| 405 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | 421 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| 406 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | 422 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| 407 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | 423 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| @@ -418,112 +434,163 @@ static yyconst flex_int32_t yy_ec[256] = | |||
| 418 | 1, 1, 1, 1, 1 | 434 | 1, 1, 1, 1, 1 |
| 419 | } ; | 435 | } ; |
| 420 | 436 | ||
| 421 | static yyconst flex_int32_t yy_meta[34] = | 437 | static yyconst flex_int32_t yy_meta[46] = |
| 422 | { 0, | 438 | { 0, |
| 423 | 1, 1, 1, 1, 2, 1, 2, 2, 3, 4, | 439 | 1, 1, 1, 1, 1, 2, 3, 1, 2, 2, |
| 424 | 4, 4, 5, 6, 7, 7, 1, 1, 6, 6, | 440 | 2, 4, 5, 5, 5, 6, 1, 1, 1, 7, |
| 425 | 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, | 441 | 8, 8, 8, 8, 1, 1, 7, 7, 7, 7, |
| 426 | 7, 8, 1 | 442 | 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, |
| 443 | 8, 8, 3, 1, 1 | ||
| 427 | } ; | 444 | } ; |
| 428 | 445 | ||
| 429 | static yyconst flex_int16_t yy_base[106] = | 446 | static yyconst flex_int16_t yy_base[175] = |
| 430 | { 0, | 447 | { 0, |
| 431 | 0, 0, 237, 236, 25, 0, 47, 0, 30, 71, | 448 | 0, 388, 381, 40, 41, 386, 71, 385, 34, 44, |
| 432 | 244, 247, 82, 84, 84, 211, 95, 229, 218, 0, | 449 | 390, 395, 60, 62, 371, 112, 111, 111, 111, 104, |
| 433 | 111, 247, 0, 84, 83, 95, 106, 86, 247, 237, | 450 | 370, 106, 371, 342, 124, 119, 0, 144, 395, 0, |
| 434 | 0, 230, 231, 234, 207, 209, 212, 220, 247, 206, | 451 | 123, 0, 159, 153, 165, 167, 395, 130, 395, 382, |
| 435 | 247, 218, 0, 106, 116, 0, 0, 0, 223, 89, | 452 | 395, 0, 372, 122, 395, 157, 374, 379, 350, 21, |
| 436 | 226, 219, 199, 206, 200, 204, 0, 190, 213, 212, | 453 | 346, 349, 395, 395, 395, 395, 395, 362, 395, 395, |
| 437 | 202, 91, 178, 161, 247, 172, 144, 150, 140, 130, | 454 | 181, 346, 342, 395, 359, 0, 191, 343, 190, 351, |
| 438 | 140, 124, 128, 120, 138, 137, 123, 122, 247, 247, | 455 | 350, 0, 0, 0, 173, 362, 177, 367, 357, 329, |
| 439 | 134, 114, 132, 86, 135, 125, 90, 136, 247, 97, | 456 | 335, 328, 337, 331, 206, 329, 334, 327, 395, 338, |
| 440 | 29, 247, 247, 153, 156, 161, 165, 170, 176, 180, | 457 | 170, 314, 346, 345, 318, 325, 343, 158, 316, 212, |
| 441 | 458 | ||
| 442 | 187, 195, 200, 205, 212 | 459 | 322, 319, 320, 395, 340, 336, 308, 305, 314, 304, |
| 460 | 295, 138, 208, 220, 395, 292, 305, 265, 264, 254, | ||
| 461 | 201, 222, 285, 275, 273, 270, 236, 235, 225, 115, | ||
| 462 | 395, 395, 252, 216, 216, 217, 214, 230, 209, 220, | ||
| 463 | 213, 239, 211, 217, 216, 209, 229, 395, 240, 225, | ||
| 464 | 206, 169, 395, 395, 116, 106, 99, 54, 395, 395, | ||
| 465 | 254, 260, 268, 272, 276, 282, 289, 293, 301, 309, | ||
| 466 | 313, 319, 327, 335 | ||
| 443 | } ; | 467 | } ; |
| 444 | 468 | ||
| 445 | static yyconst flex_int16_t yy_def[106] = | 469 | static yyconst flex_int16_t yy_def[175] = |
| 446 | { 0, | 470 | { 0, |
| 447 | 93, 1, 1, 1, 1, 5, 93, 7, 1, 1, | 471 | 160, 1, 1, 1, 1, 5, 160, 7, 1, 1, |
| 448 | 93, 93, 93, 93, 94, 95, 93, 96, 17, 97, | 472 | 160, 160, 160, 160, 160, 161, 162, 163, 160, 160, |
| 449 | 96, 93, 98, 99, 93, 93, 93, 94, 93, 94, | 473 | 160, 160, 164, 160, 160, 160, 165, 164, 160, 166, |
| 450 | 100, 93, 101, 102, 93, 93, 93, 96, 93, 93, | 474 | 167, 166, 166, 160, 160, 160, 160, 161, 160, 161, |
| 451 | 93, 96, 98, 99, 93, 103, 100, 104, 101, 101, | 475 | 160, 168, 160, 163, 160, 163, 169, 170, 160, 160, |
| 452 | 102, 93, 93, 93, 93, 93, 103, 104, 93, 93, | 476 | 160, 160, 160, 160, 160, 160, 160, 164, 160, 160, |
| 453 | 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, | 477 | 160, 160, 160, 160, 164, 166, 167, 166, 160, 160, |
| 454 | 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, | 478 | 160, 171, 168, 172, 163, 169, 169, 170, 160, 160, |
| 455 | 93, 93, 93, 93, 93, 105, 93, 105, 93, 105, | 479 | 160, 160, 160, 160, 160, 160, 160, 166, 160, 160, |
| 456 | 93, 93, 0, 93, 93, 93, 93, 93, 93, 93, | 480 | 171, 172, 160, 160, 160, 160, 160, 160, 160, 160, |
| 457 | 481 | ||
| 458 | 93, 93, 93, 93, 93 | 482 | 160, 160, 166, 160, 160, 160, 160, 160, 160, 160, |
| 483 | 160, 173, 160, 166, 160, 160, 160, 160, 160, 160, | ||
| 484 | 173, 160, 173, 160, 160, 160, 160, 160, 160, 160, | ||
| 485 | 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, | ||
| 486 | 160, 160, 174, 160, 160, 160, 174, 160, 174, 160, | ||
| 487 | 160, 160, 160, 160, 160, 160, 160, 160, 160, 0, | ||
| 488 | 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, | ||
| 489 | 160, 160, 160, 160 | ||
| 459 | } ; | 490 | } ; |
| 460 | 491 | ||
| 461 | static yyconst flex_int16_t yy_nxt[281] = | 492 | static yyconst flex_int16_t yy_nxt[441] = |
| 462 | { 0, | 493 | { 0, |
| 463 | 12, 13, 14, 15, 12, 16, 12, 12, 17, 12, | 494 | 12, 13, 14, 15, 16, 12, 17, 18, 12, 12, |
| 464 | 12, 12, 12, 18, 18, 18, 12, 12, 18, 18, | 495 | 12, 19, 12, 12, 12, 12, 20, 21, 22, 23, |
| 465 | 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, | 496 | 23, 23, 23, 23, 12, 12, 23, 23, 23, 23, |
| 466 | 18, 12, 12, 19, 20, 20, 20, 92, 21, 25, | 497 | 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, |
| 467 | 26, 26, 22, 21, 21, 21, 21, 12, 13, 14, | 498 | 23, 23, 12, 24, 12, 25, 34, 35, 35, 25, |
| 468 | 15, 23, 16, 23, 23, 19, 23, 23, 23, 12, | 499 | 81, 26, 26, 27, 27, 27, 34, 35, 35, 82, |
| 469 | 24, 24, 24, 12, 12, 24, 24, 24, 24, 24, | 500 | 28, 36, 36, 36, 36, 159, 29, 28, 28, 28, |
| 470 | 24, 24, 24, 24, 24, 24, 24, 24, 12, 12, | 501 | 28, 12, 13, 14, 15, 16, 30, 17, 18, 30, |
| 471 | 25, 26, 26, 27, 27, 27, 27, 29, 43, 29, | 502 | 30, 30, 26, 30, 30, 30, 12, 20, 21, 22, |
| 472 | 43, 43, 45, 45, 45, 50, 39, 59, 46, 93, | 503 | 31, 31, 31, 31, 31, 32, 12, 31, 31, 31, |
| 473 | 504 | ||
| 474 | 30, 33, 30, 34, 45, 45, 45, 27, 27, 68, | 505 | 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, |
| 475 | 43, 91, 43, 43, 69, 35, 87, 36, 39, 37, | 506 | 31, 31, 31, 12, 24, 12, 39, 41, 45, 47, |
| 476 | 42, 42, 42, 39, 42, 45, 45, 45, 89, 42, | 507 | 53, 54, 48, 56, 57, 61, 61, 47, 66, 45, |
| 477 | 42, 42, 42, 85, 85, 86, 85, 85, 86, 89, | 508 | 48, 66, 66, 66, 39, 46, 40, 49, 59, 50, |
| 478 | 84, 90, 83, 82, 81, 80, 79, 78, 77, 76, | 509 | 158, 51, 122, 52, 157, 49, 46, 50, 136, 63, |
| 479 | 75, 74, 90, 28, 28, 28, 28, 28, 28, 28, | 510 | 137, 52, 156, 43, 40, 62, 65, 65, 65, 59, |
| 480 | 28, 31, 31, 31, 38, 38, 38, 38, 41, 73, | 511 | 61, 61, 123, 65, 75, 69, 69, 69, 36, 36, |
| 481 | 41, 43, 72, 43, 71, 43, 43, 44, 33, 44, | 512 | 65, 65, 65, 65, 70, 71, 72, 69, 69, 69, |
| 482 | 44, 44, 44, 47, 69, 47, 47, 49, 49, 49, | 513 | 45, 46, 61, 61, 109, 77, 70, 71, 93, 110, |
| 483 | 49, 49, 49, 49, 49, 51, 51, 51, 51, 51, | 514 | 68, 70, 71, 85, 85, 85, 66, 46, 155, 66, |
| 484 | 515 | ||
| 485 | 51, 51, 51, 57, 70, 57, 58, 58, 58, 67, | 516 | 66, 66, 69, 69, 69, 122, 59, 100, 100, 61, |
| 486 | 58, 58, 88, 88, 88, 88, 88, 88, 88, 88, | 517 | 61, 70, 71, 100, 100, 148, 112, 154, 85, 85, |
| 487 | 34, 66, 65, 64, 63, 62, 61, 60, 52, 50, | 518 | 85, 61, 61, 129, 129, 123, 129, 129, 135, 135, |
| 488 | 39, 56, 39, 55, 54, 53, 52, 50, 48, 93, | 519 | 135, 142, 142, 148, 143, 149, 153, 135, 135, 135, |
| 489 | 40, 39, 32, 93, 19, 19, 11, 93, 93, 93, | 520 | 142, 142, 160, 143, 152, 151, 150, 146, 145, 144, |
| 490 | 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, | 521 | 141, 140, 139, 149, 38, 38, 38, 38, 38, 38, |
| 491 | 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, | 522 | 38, 38, 42, 138, 134, 133, 42, 42, 44, 44, |
| 492 | 93, 93, 93, 93, 93, 93, 93, 93, 93, 93 | 523 | 44, 44, 44, 44, 44, 44, 58, 58, 58, 58, |
| 524 | 64, 132, 64, 66, 131, 130, 66, 160, 66, 66, | ||
| 525 | 67, 128, 127, 67, 67, 67, 67, 73, 126, 73, | ||
| 526 | |||
| 527 | 73, 76, 76, 76, 76, 76, 76, 76, 76, 78, | ||
| 528 | 78, 78, 78, 78, 78, 78, 78, 91, 125, 91, | ||
| 529 | 92, 124, 92, 92, 120, 92, 92, 121, 121, 121, | ||
| 530 | 121, 121, 121, 121, 121, 147, 147, 147, 147, 147, | ||
| 531 | 147, 147, 147, 119, 118, 117, 116, 115, 47, 114, | ||
| 532 | 110, 113, 111, 108, 107, 106, 48, 105, 104, 89, | ||
| 533 | 103, 102, 101, 99, 98, 97, 96, 95, 94, 79, | ||
| 534 | 77, 90, 89, 88, 59, 87, 86, 59, 84, 83, | ||
| 535 | 80, 79, 77, 74, 160, 60, 59, 55, 37, 160, | ||
| 536 | 33, 25, 26, 25, 11, 160, 160, 160, 160, 160, | ||
| 537 | |||
| 538 | 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, | ||
| 539 | 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, | ||
| 540 | 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, | ||
| 541 | 160, 160, 160, 160, 160, 160, 160, 160, 160, 160 | ||
| 493 | } ; | 542 | } ; |
| 494 | 543 | ||
| 495 | static yyconst flex_int16_t yy_chk[281] = | 544 | static yyconst flex_int16_t yy_chk[441] = |
| 496 | { 0, | 545 | { 0, |
| 497 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | 546 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| 498 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | 547 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| 499 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | 548 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| 500 | 1, 1, 1, 5, 5, 5, 5, 91, 5, 9, | 549 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| 501 | 9, 9, 5, 5, 5, 5, 5, 7, 7, 7, | 550 | 1, 1, 1, 1, 1, 4, 9, 9, 9, 10, |
| 551 | 50, 4, 5, 5, 5, 5, 10, 10, 10, 50, | ||
| 552 | 5, 13, 13, 14, 14, 158, 5, 5, 5, 5, | ||
| 553 | 5, 7, 7, 7, 7, 7, 7, 7, 7, 7, | ||
| 502 | 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, | 554 | 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, |
| 503 | 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, | 555 | 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, |
| 556 | |||
| 504 | 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, | 557 | 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, |
| 505 | 10, 10, 10, 13, 13, 14, 14, 15, 24, 28, | 558 | 7, 7, 7, 7, 7, 7, 16, 17, 18, 19, |
| 506 | 24, 24, 25, 25, 25, 50, 24, 50, 25, 90, | 559 | 20, 20, 19, 22, 22, 25, 25, 26, 31, 44, |
| 507 | 560 | 26, 31, 31, 31, 38, 18, 16, 19, 31, 19, | |
| 508 | 15, 17, 28, 17, 26, 26, 26, 27, 27, 62, | 561 | 157, 19, 112, 19, 156, 26, 44, 26, 130, 26, |
| 509 | 44, 87, 44, 44, 62, 17, 84, 17, 44, 17, | 562 | 130, 26, 155, 17, 38, 25, 28, 28, 28, 28, |
| 510 | 21, 21, 21, 21, 21, 45, 45, 45, 86, 21, | 563 | 33, 33, 112, 28, 46, 34, 34, 34, 36, 36, |
| 511 | 21, 21, 21, 83, 83, 83, 85, 85, 85, 88, | 564 | 28, 28, 28, 28, 34, 34, 34, 35, 35, 35, |
| 512 | 82, 86, 81, 78, 77, 76, 75, 74, 73, 72, | 565 | 75, 46, 61, 61, 98, 77, 35, 35, 77, 98, |
| 513 | 71, 70, 88, 94, 94, 94, 94, 94, 94, 94, | 566 | 33, 91, 91, 61, 61, 61, 67, 75, 152, 67, |
| 514 | 94, 95, 95, 95, 96, 96, 96, 96, 97, 69, | 567 | |
| 515 | 97, 98, 68, 98, 67, 98, 98, 99, 66, 99, | 568 | 67, 67, 69, 69, 69, 121, 67, 85, 85, 113, |
| 516 | 99, 99, 99, 100, 64, 100, 100, 101, 101, 101, | 569 | 113, 69, 69, 100, 100, 143, 100, 151, 85, 85, |
| 517 | 101, 101, 101, 101, 101, 102, 102, 102, 102, 102, | 570 | 85, 114, 114, 122, 122, 121, 129, 129, 135, 135, |
| 518 | 571 | 135, 138, 138, 147, 138, 143, 150, 129, 129, 129, | |
| 519 | 102, 102, 102, 103, 63, 103, 104, 104, 104, 61, | 572 | 142, 142, 149, 142, 146, 145, 144, 141, 140, 139, |
| 520 | 104, 104, 105, 105, 105, 105, 105, 105, 105, 105, | 573 | 137, 136, 134, 147, 161, 161, 161, 161, 161, 161, |
| 521 | 60, 59, 58, 56, 55, 54, 53, 52, 51, 49, | 574 | 161, 161, 162, 133, 128, 127, 162, 162, 163, 163, |
| 522 | 42, 40, 38, 37, 36, 35, 34, 33, 32, 30, | 575 | 163, 163, 163, 163, 163, 163, 164, 164, 164, 164, |
| 523 | 19, 18, 16, 11, 4, 3, 93, 93, 93, 93, | 576 | 165, 126, 165, 166, 125, 124, 166, 123, 166, 166, |
| 524 | 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, | 577 | 167, 120, 119, 167, 167, 167, 167, 168, 118, 168, |
| 525 | 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, | 578 | |
| 526 | 93, 93, 93, 93, 93, 93, 93, 93, 93, 93 | 579 | 168, 169, 169, 169, 169, 169, 169, 169, 169, 170, |
| 580 | 170, 170, 170, 170, 170, 170, 170, 171, 117, 171, | ||
| 581 | 172, 116, 172, 172, 111, 172, 172, 173, 173, 173, | ||
| 582 | 173, 173, 173, 173, 173, 174, 174, 174, 174, 174, | ||
| 583 | 174, 174, 174, 110, 109, 108, 107, 106, 105, 103, | ||
| 584 | 102, 101, 99, 97, 96, 95, 94, 93, 92, 90, | ||
| 585 | 88, 87, 86, 84, 83, 82, 81, 80, 79, 78, | ||
| 586 | 76, 71, 70, 68, 65, 63, 62, 58, 52, 51, | ||
| 587 | 49, 48, 47, 43, 40, 24, 23, 21, 15, 11, | ||
| 588 | 8, 6, 3, 2, 160, 160, 160, 160, 160, 160, | ||
| 589 | |||
| 590 | 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, | ||
| 591 | 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, | ||
| 592 | 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, | ||
| 593 | 160, 160, 160, 160, 160, 160, 160, 160, 160, 160 | ||
| 527 | } ; | 594 | } ; |
| 528 | 595 | ||
| 529 | static yy_state_type yy_last_accepting_state; | 596 | static yy_state_type yy_last_accepting_state; |
| @@ -540,6 +607,7 @@ int yy_flex_debug = 0; | |||
| 540 | #define YY_MORE_ADJ 0 | 607 | #define YY_MORE_ADJ 0 |
| 541 | #define YY_RESTORE_YY_MORE_OFFSET | 608 | #define YY_RESTORE_YY_MORE_OFFSET |
| 542 | char *yytext; | 609 | char *yytext; |
| 610 | #line 1 "dtc-lexer.l" | ||
| 543 | /* | 611 | /* |
| 544 | * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005. | 612 | * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005. |
| 545 | * | 613 | * |
| @@ -561,6 +629,10 @@ char *yytext; | |||
| 561 | */ | 629 | */ |
| 562 | #define YY_NO_INPUT 1 | 630 | #define YY_NO_INPUT 1 |
| 563 | 631 | ||
| 632 | |||
| 633 | |||
| 634 | |||
| 635 | #line 38 "dtc-lexer.l" | ||
| 564 | #include "dtc.h" | 636 | #include "dtc.h" |
| 565 | #include "srcpos.h" | 637 | #include "srcpos.h" |
| 566 | #include "dtc-parser.tab.h" | 638 | #include "dtc-parser.tab.h" |
| @@ -588,6 +660,7 @@ static int dts_version = 1; | |||
| 588 | 660 | ||
| 589 | static void push_input_file(const char *filename); | 661 | static void push_input_file(const char *filename); |
| 590 | static int pop_input_file(void); | 662 | static int pop_input_file(void); |
| 663 | #line 664 "dtc-lexer.lex.c" | ||
| 591 | 664 | ||
| 592 | #define INITIAL 0 | 665 | #define INITIAL 0 |
| 593 | #define INCLUDE 1 | 666 | #define INCLUDE 1 |
| @@ -670,7 +743,12 @@ static int input (void ); | |||
| 670 | 743 | ||
| 671 | /* Amount of stuff to slurp up with each read. */ | 744 | /* Amount of stuff to slurp up with each read. */ |
| 672 | #ifndef YY_READ_BUF_SIZE | 745 | #ifndef YY_READ_BUF_SIZE |
| 746 | #ifdef __ia64__ | ||
| 747 | /* On IA-64, the buffer size is 16k, not 8k */ | ||
| 748 | #define YY_READ_BUF_SIZE 16384 | ||
| 749 | #else | ||
| 673 | #define YY_READ_BUF_SIZE 8192 | 750 | #define YY_READ_BUF_SIZE 8192 |
| 751 | #endif /* __ia64__ */ | ||
| 674 | #endif | 752 | #endif |
| 675 | 753 | ||
| 676 | /* Copy whatever the last rule matched to the standard output. */ | 754 | /* Copy whatever the last rule matched to the standard output. */ |
| @@ -689,7 +767,7 @@ static int input (void ); | |||
| 689 | if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ | 767 | if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ |
| 690 | { \ | 768 | { \ |
| 691 | int c = '*'; \ | 769 | int c = '*'; \ |
| 692 | unsigned n; \ | 770 | size_t n; \ |
| 693 | for ( n = 0; n < max_size && \ | 771 | for ( n = 0; n < max_size && \ |
| 694 | (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ | 772 | (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ |
| 695 | buf[n] = (char) c; \ | 773 | buf[n] = (char) c; \ |
| @@ -761,6 +839,9 @@ extern int yylex (void); | |||
| 761 | #endif | 839 | #endif |
| 762 | 840 | ||
| 763 | #define YY_RULE_SETUP \ | 841 | #define YY_RULE_SETUP \ |
| 842 | if ( yyleng > 0 ) \ | ||
| 843 | YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \ | ||
| 844 | (yytext[yyleng - 1] == '\n'); \ | ||
| 764 | YY_USER_ACTION | 845 | YY_USER_ACTION |
| 765 | 846 | ||
| 766 | /** The main scanner function which does all the work. | 847 | /** The main scanner function which does all the work. |
| @@ -771,6 +852,10 @@ YY_DECL | |||
| 771 | register char *yy_cp, *yy_bp; | 852 | register char *yy_cp, *yy_bp; |
| 772 | register int yy_act; | 853 | register int yy_act; |
| 773 | 854 | ||
| 855 | #line 67 "dtc-lexer.l" | ||
| 856 | |||
| 857 | #line 858 "dtc-lexer.lex.c" | ||
| 858 | |||
| 774 | if ( !(yy_init) ) | 859 | if ( !(yy_init) ) |
| 775 | { | 860 | { |
| 776 | (yy_init) = 1; | 861 | (yy_init) = 1; |
| @@ -810,6 +895,7 @@ YY_DECL | |||
| 810 | yy_bp = yy_cp; | 895 | yy_bp = yy_cp; |
| 811 | 896 | ||
| 812 | yy_current_state = (yy_start); | 897 | yy_current_state = (yy_start); |
| 898 | yy_current_state += YY_AT_BOL(); | ||
| 813 | yy_match: | 899 | yy_match: |
| 814 | do | 900 | do |
| 815 | { | 901 | { |
| @@ -822,13 +908,13 @@ yy_match: | |||
| 822 | while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) | 908 | while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) |
| 823 | { | 909 | { |
| 824 | yy_current_state = (int) yy_def[yy_current_state]; | 910 | yy_current_state = (int) yy_def[yy_current_state]; |
| 825 | if ( yy_current_state >= 94 ) | 911 | if ( yy_current_state >= 161 ) |
| 826 | yy_c = yy_meta[(unsigned int) yy_c]; | 912 | yy_c = yy_meta[(unsigned int) yy_c]; |
| 827 | } | 913 | } |
| 828 | yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; | 914 | yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; |
| 829 | ++yy_cp; | 915 | ++yy_cp; |
| 830 | } | 916 | } |
| 831 | while ( yy_current_state != 93 ); | 917 | while ( yy_current_state != 160 ); |
| 832 | yy_cp = (yy_last_accepting_cpos); | 918 | yy_cp = (yy_last_accepting_cpos); |
| 833 | yy_current_state = (yy_last_accepting_state); | 919 | yy_current_state = (yy_last_accepting_state); |
| 834 | 920 | ||
| @@ -851,26 +937,54 @@ do_action: /* This label is used only to access EOF actions. */ | |||
| 851 | case 1: | 937 | case 1: |
| 852 | /* rule 1 can match eol */ | 938 | /* rule 1 can match eol */ |
| 853 | YY_RULE_SETUP | 939 | YY_RULE_SETUP |
| 940 | #line 68 "dtc-lexer.l" | ||
| 854 | { | 941 | { |
| 855 | char *name = strchr(yytext, '\"') + 1; | 942 | char *name = strchr(yytext, '\"') + 1; |
| 856 | yytext[yyleng-1] = '\0'; | 943 | yytext[yyleng-1] = '\0'; |
| 857 | push_input_file(name); | 944 | push_input_file(name); |
| 858 | } | 945 | } |
| 859 | YY_BREAK | 946 | YY_BREAK |
| 947 | case 2: | ||
| 948 | /* rule 2 can match eol */ | ||
| 949 | YY_RULE_SETUP | ||
| 950 | #line 74 "dtc-lexer.l" | ||
| 951 | { | ||
| 952 | char *line, *tmp, *fn; | ||
| 953 | /* skip text before line # */ | ||
| 954 | line = yytext; | ||
| 955 | while (!isdigit(*line)) | ||
| 956 | line++; | ||
| 957 | /* skip digits in line # */ | ||
| 958 | tmp = line; | ||
| 959 | while (!isspace(*tmp)) | ||
| 960 | tmp++; | ||
| 961 | /* "NULL"-terminate line # */ | ||
| 962 | *tmp = '\0'; | ||
| 963 | /* start of filename */ | ||
| 964 | fn = strchr(tmp + 1, '"') + 1; | ||
| 965 | /* strip trailing " from filename */ | ||
| 966 | tmp = strchr(fn, '"'); | ||
| 967 | *tmp = 0; | ||
| 968 | /* -1 since #line is the number of the next line */ | ||
| 969 | srcpos_set_line(xstrdup(fn), atoi(line) - 1); | ||
| 970 | } | ||
| 971 | YY_BREAK | ||
| 860 | case YY_STATE_EOF(INITIAL): | 972 | case YY_STATE_EOF(INITIAL): |
| 861 | case YY_STATE_EOF(INCLUDE): | 973 | case YY_STATE_EOF(INCLUDE): |
| 862 | case YY_STATE_EOF(BYTESTRING): | 974 | case YY_STATE_EOF(BYTESTRING): |
| 863 | case YY_STATE_EOF(PROPNODENAME): | 975 | case YY_STATE_EOF(PROPNODENAME): |
| 864 | case YY_STATE_EOF(V1): | 976 | case YY_STATE_EOF(V1): |
| 977 | #line 95 "dtc-lexer.l" | ||
| 865 | { | 978 | { |
| 866 | if (!pop_input_file()) { | 979 | if (!pop_input_file()) { |
| 867 | yyterminate(); | 980 | yyterminate(); |
| 868 | } | 981 | } |
| 869 | } | 982 | } |
| 870 | YY_BREAK | 983 | YY_BREAK |
| 871 | case 2: | 984 | case 3: |
| 872 | /* rule 2 can match eol */ | 985 | /* rule 3 can match eol */ |
| 873 | YY_RULE_SETUP | 986 | YY_RULE_SETUP |
| 987 | #line 101 "dtc-lexer.l" | ||
| 874 | { | 988 | { |
| 875 | DPRINT("String: %s\n", yytext); | 989 | DPRINT("String: %s\n", yytext); |
| 876 | yylval.data = data_copy_escape_string(yytext+1, | 990 | yylval.data = data_copy_escape_string(yytext+1, |
| @@ -878,8 +992,9 @@ YY_RULE_SETUP | |||
| 878 | return DT_STRING; | 992 | return DT_STRING; |
| 879 | } | 993 | } |
| 880 | YY_BREAK | 994 | YY_BREAK |
| 881 | case 3: | 995 | case 4: |
| 882 | YY_RULE_SETUP | 996 | YY_RULE_SETUP |
| 997 | #line 108 "dtc-lexer.l" | ||
| 883 | { | 998 | { |
| 884 | DPRINT("Keyword: /dts-v1/\n"); | 999 | DPRINT("Keyword: /dts-v1/\n"); |
| 885 | dts_version = 1; | 1000 | dts_version = 1; |
| @@ -887,16 +1002,47 @@ YY_RULE_SETUP | |||
| 887 | return DT_V1; | 1002 | return DT_V1; |
| 888 | } | 1003 | } |
| 889 | YY_BREAK | 1004 | YY_BREAK |
| 890 | case 4: | 1005 | case 5: |
| 891 | YY_RULE_SETUP | 1006 | YY_RULE_SETUP |
| 1007 | #line 115 "dtc-lexer.l" | ||
| 892 | { | 1008 | { |
| 893 | DPRINT("Keyword: /memreserve/\n"); | 1009 | DPRINT("Keyword: /memreserve/\n"); |
| 894 | BEGIN_DEFAULT(); | 1010 | BEGIN_DEFAULT(); |
| 895 | return DT_MEMRESERVE; | 1011 | return DT_MEMRESERVE; |
| 896 | } | 1012 | } |
| 897 | YY_BREAK | 1013 | YY_BREAK |
| 898 | case 5: | 1014 | case 6: |
| 1015 | YY_RULE_SETUP | ||
| 1016 | #line 121 "dtc-lexer.l" | ||
| 1017 | { | ||
| 1018 | DPRINT("Keyword: /bits/\n"); | ||
| 1019 | BEGIN_DEFAULT(); | ||
| 1020 | return DT_BITS; | ||
| 1021 | } | ||
| 1022 | YY_BREAK | ||
| 1023 | case 7: | ||
| 899 | YY_RULE_SETUP | 1024 | YY_RULE_SETUP |
| 1025 | #line 127 "dtc-lexer.l" | ||
| 1026 | { | ||
| 1027 | DPRINT("Keyword: /delete-property/\n"); | ||
| 1028 | DPRINT("<PROPNODENAME>\n"); | ||
| 1029 | BEGIN(PROPNODENAME); | ||
| 1030 | return DT_DEL_PROP; | ||
| 1031 | } | ||
| 1032 | YY_BREAK | ||
| 1033 | case 8: | ||
| 1034 | YY_RULE_SETUP | ||
| 1035 | #line 134 "dtc-lexer.l" | ||
| 1036 | { | ||
| 1037 | DPRINT("Keyword: /delete-node/\n"); | ||
| 1038 | DPRINT("<PROPNODENAME>\n"); | ||
| 1039 | BEGIN(PROPNODENAME); | ||
| 1040 | return DT_DEL_NODE; | ||
| 1041 | } | ||
| 1042 | YY_BREAK | ||
| 1043 | case 9: | ||
| 1044 | YY_RULE_SETUP | ||
| 1045 | #line 141 "dtc-lexer.l" | ||
| 900 | { | 1046 | { |
| 901 | DPRINT("Label: %s\n", yytext); | 1047 | DPRINT("Label: %s\n", yytext); |
| 902 | yylval.labelref = xstrdup(yytext); | 1048 | yylval.labelref = xstrdup(yytext); |
| @@ -904,24 +1050,38 @@ YY_RULE_SETUP | |||
| 904 | return DT_LABEL; | 1050 | return DT_LABEL; |
| 905 | } | 1051 | } |
| 906 | YY_BREAK | 1052 | YY_BREAK |
| 907 | case 6: | 1053 | case 10: |
| 908 | YY_RULE_SETUP | 1054 | YY_RULE_SETUP |
| 1055 | #line 148 "dtc-lexer.l" | ||
| 909 | { | 1056 | { |
| 910 | yylval.literal = xstrdup(yytext); | 1057 | yylval.literal = xstrdup(yytext); |
| 911 | DPRINT("Literal: '%s'\n", yylval.literal); | 1058 | DPRINT("Literal: '%s'\n", yylval.literal); |
| 912 | return DT_LITERAL; | 1059 | return DT_LITERAL; |
| 913 | } | 1060 | } |
| 914 | YY_BREAK | 1061 | YY_BREAK |
| 915 | case 7: | 1062 | case 11: |
| 1063 | /* rule 11 can match eol */ | ||
| 1064 | YY_RULE_SETUP | ||
| 1065 | #line 154 "dtc-lexer.l" | ||
| 1066 | { | ||
| 1067 | yytext[yyleng-1] = '\0'; | ||
| 1068 | yylval.literal = xstrdup(yytext+1); | ||
| 1069 | DPRINT("Character literal: %s\n", yylval.literal); | ||
| 1070 | return DT_CHAR_LITERAL; | ||
| 1071 | } | ||
| 1072 | YY_BREAK | ||
| 1073 | case 12: | ||
| 916 | YY_RULE_SETUP | 1074 | YY_RULE_SETUP |
| 1075 | #line 161 "dtc-lexer.l" | ||
| 917 | { /* label reference */ | 1076 | { /* label reference */ |
| 918 | DPRINT("Ref: %s\n", yytext+1); | 1077 | DPRINT("Ref: %s\n", yytext+1); |
| 919 | yylval.labelref = xstrdup(yytext+1); | 1078 | yylval.labelref = xstrdup(yytext+1); |
| 920 | return DT_REF; | 1079 | return DT_REF; |
| 921 | } | 1080 | } |
| 922 | YY_BREAK | 1081 | YY_BREAK |
| 923 | case 8: | 1082 | case 13: |
| 924 | YY_RULE_SETUP | 1083 | YY_RULE_SETUP |
| 1084 | #line 167 "dtc-lexer.l" | ||
| 925 | { /* new-style path reference */ | 1085 | { /* new-style path reference */ |
| 926 | yytext[yyleng-1] = '\0'; | 1086 | yytext[yyleng-1] = '\0'; |
| 927 | DPRINT("Ref: %s\n", yytext+2); | 1087 | DPRINT("Ref: %s\n", yytext+2); |
| @@ -929,55 +1089,104 @@ YY_RULE_SETUP | |||
| 929 | return DT_REF; | 1089 | return DT_REF; |
| 930 | } | 1090 | } |
| 931 | YY_BREAK | 1091 | YY_BREAK |
| 932 | case 9: | 1092 | case 14: |
| 933 | YY_RULE_SETUP | 1093 | YY_RULE_SETUP |
| 1094 | #line 174 "dtc-lexer.l" | ||
| 934 | { | 1095 | { |
| 935 | yylval.byte = strtol(yytext, NULL, 16); | 1096 | yylval.byte = strtol(yytext, NULL, 16); |
| 936 | DPRINT("Byte: %02x\n", (int)yylval.byte); | 1097 | DPRINT("Byte: %02x\n", (int)yylval.byte); |
| 937 | return DT_BYTE; | 1098 | return DT_BYTE; |
| 938 | } | 1099 | } |
| 939 | YY_BREAK | 1100 | YY_BREAK |
| 940 | case 10: | 1101 | case 15: |
| 941 | YY_RULE_SETUP | 1102 | YY_RULE_SETUP |
| 1103 | #line 180 "dtc-lexer.l" | ||
| 942 | { | 1104 | { |
| 943 | DPRINT("/BYTESTRING\n"); | 1105 | DPRINT("/BYTESTRING\n"); |
| 944 | BEGIN_DEFAULT(); | 1106 | BEGIN_DEFAULT(); |
| 945 | return ']'; | 1107 | return ']'; |
| 946 | } | 1108 | } |
| 947 | YY_BREAK | 1109 | YY_BREAK |
| 948 | case 11: | 1110 | case 16: |
| 949 | YY_RULE_SETUP | 1111 | YY_RULE_SETUP |
| 1112 | #line 186 "dtc-lexer.l" | ||
| 950 | { | 1113 | { |
| 951 | DPRINT("PropNodeName: %s\n", yytext); | 1114 | DPRINT("PropNodeName: %s\n", yytext); |
| 952 | yylval.propnodename = xstrdup(yytext); | 1115 | yylval.propnodename = xstrdup((yytext[0] == '\\') ? |
| 1116 | yytext + 1 : yytext); | ||
| 953 | BEGIN_DEFAULT(); | 1117 | BEGIN_DEFAULT(); |
| 954 | return DT_PROPNODENAME; | 1118 | return DT_PROPNODENAME; |
| 955 | } | 1119 | } |
| 956 | YY_BREAK | 1120 | YY_BREAK |
| 957 | case 12: | 1121 | case 17: |
| 958 | YY_RULE_SETUP | 1122 | YY_RULE_SETUP |
| 1123 | #line 194 "dtc-lexer.l" | ||
| 959 | { | 1124 | { |
| 960 | DPRINT("Binary Include\n"); | 1125 | DPRINT("Binary Include\n"); |
| 961 | return DT_INCBIN; | 1126 | return DT_INCBIN; |
| 962 | } | 1127 | } |
| 963 | YY_BREAK | 1128 | YY_BREAK |
| 964 | case 13: | 1129 | case 18: |
| 965 | /* rule 13 can match eol */ | 1130 | /* rule 18 can match eol */ |
| 966 | YY_RULE_SETUP | 1131 | YY_RULE_SETUP |
| 1132 | #line 199 "dtc-lexer.l" | ||
| 967 | /* eat whitespace */ | 1133 | /* eat whitespace */ |
| 968 | YY_BREAK | 1134 | YY_BREAK |
| 969 | case 14: | 1135 | case 19: |
| 970 | /* rule 14 can match eol */ | 1136 | /* rule 19 can match eol */ |
| 971 | YY_RULE_SETUP | 1137 | YY_RULE_SETUP |
| 1138 | #line 200 "dtc-lexer.l" | ||
| 972 | /* eat C-style comments */ | 1139 | /* eat C-style comments */ |
| 973 | YY_BREAK | 1140 | YY_BREAK |
| 974 | case 15: | 1141 | case 20: |
| 975 | /* rule 15 can match eol */ | 1142 | /* rule 20 can match eol */ |
| 976 | YY_RULE_SETUP | 1143 | YY_RULE_SETUP |
| 1144 | #line 201 "dtc-lexer.l" | ||
| 977 | /* eat C++-style comments */ | 1145 | /* eat C++-style comments */ |
| 978 | YY_BREAK | 1146 | YY_BREAK |
| 979 | case 16: | 1147 | case 21: |
| 980 | YY_RULE_SETUP | 1148 | YY_RULE_SETUP |
| 1149 | #line 203 "dtc-lexer.l" | ||
| 1150 | { return DT_LSHIFT; }; | ||
| 1151 | YY_BREAK | ||
| 1152 | case 22: | ||
| 1153 | YY_RULE_SETUP | ||
| 1154 | #line 204 "dtc-lexer.l" | ||
| 1155 | { return DT_RSHIFT; }; | ||
| 1156 | YY_BREAK | ||
| 1157 | case 23: | ||
| 1158 | YY_RULE_SETUP | ||
| 1159 | #line 205 "dtc-lexer.l" | ||
| 1160 | { return DT_LE; }; | ||
| 1161 | YY_BREAK | ||
| 1162 | case 24: | ||
| 1163 | YY_RULE_SETUP | ||
| 1164 | #line 206 "dtc-lexer.l" | ||
| 1165 | { return DT_GE; }; | ||
| 1166 | YY_BREAK | ||
| 1167 | case 25: | ||
| 1168 | YY_RULE_SETUP | ||
| 1169 | #line 207 "dtc-lexer.l" | ||
| 1170 | { return DT_EQ; }; | ||
| 1171 | YY_BREAK | ||
| 1172 | case 26: | ||
| 1173 | YY_RULE_SETUP | ||
| 1174 | #line 208 "dtc-lexer.l" | ||
| 1175 | { return DT_NE; }; | ||
| 1176 | YY_BREAK | ||
| 1177 | case 27: | ||
| 1178 | YY_RULE_SETUP | ||
| 1179 | #line 209 "dtc-lexer.l" | ||
| 1180 | { return DT_AND; }; | ||
| 1181 | YY_BREAK | ||
| 1182 | case 28: | ||
| 1183 | YY_RULE_SETUP | ||
| 1184 | #line 210 "dtc-lexer.l" | ||
| 1185 | { return DT_OR; }; | ||
| 1186 | YY_BREAK | ||
| 1187 | case 29: | ||
| 1188 | YY_RULE_SETUP | ||
| 1189 | #line 212 "dtc-lexer.l" | ||
| 981 | { | 1190 | { |
| 982 | DPRINT("Char: %c (\\x%02x)\n", yytext[0], | 1191 | DPRINT("Char: %c (\\x%02x)\n", yytext[0], |
| 983 | (unsigned)yytext[0]); | 1192 | (unsigned)yytext[0]); |
| @@ -993,10 +1202,12 @@ YY_RULE_SETUP | |||
| 993 | return yytext[0]; | 1202 | return yytext[0]; |
| 994 | } | 1203 | } |
| 995 | YY_BREAK | 1204 | YY_BREAK |
| 996 | case 17: | 1205 | case 30: |
| 997 | YY_RULE_SETUP | 1206 | YY_RULE_SETUP |
| 1207 | #line 227 "dtc-lexer.l" | ||
| 998 | ECHO; | 1208 | ECHO; |
| 999 | YY_BREAK | 1209 | YY_BREAK |
| 1210 | #line 1211 "dtc-lexer.lex.c" | ||
| 1000 | 1211 | ||
| 1001 | case YY_END_OF_BUFFER: | 1212 | case YY_END_OF_BUFFER: |
| 1002 | { | 1213 | { |
| @@ -1275,6 +1486,7 @@ static int yy_get_next_buffer (void) | |||
| 1275 | register char *yy_cp; | 1486 | register char *yy_cp; |
| 1276 | 1487 | ||
| 1277 | yy_current_state = (yy_start); | 1488 | yy_current_state = (yy_start); |
| 1489 | yy_current_state += YY_AT_BOL(); | ||
| 1278 | 1490 | ||
| 1279 | for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) | 1491 | for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) |
| 1280 | { | 1492 | { |
| @@ -1287,7 +1499,7 @@ static int yy_get_next_buffer (void) | |||
| 1287 | while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) | 1499 | while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) |
| 1288 | { | 1500 | { |
| 1289 | yy_current_state = (int) yy_def[yy_current_state]; | 1501 | yy_current_state = (int) yy_def[yy_current_state]; |
| 1290 | if ( yy_current_state >= 94 ) | 1502 | if ( yy_current_state >= 161 ) |
| 1291 | yy_c = yy_meta[(unsigned int) yy_c]; | 1503 | yy_c = yy_meta[(unsigned int) yy_c]; |
| 1292 | } | 1504 | } |
| 1293 | yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; | 1505 | yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; |
| @@ -1315,11 +1527,11 @@ static int yy_get_next_buffer (void) | |||
| 1315 | while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) | 1527 | while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) |
| 1316 | { | 1528 | { |
| 1317 | yy_current_state = (int) yy_def[yy_current_state]; | 1529 | yy_current_state = (int) yy_def[yy_current_state]; |
| 1318 | if ( yy_current_state >= 94 ) | 1530 | if ( yy_current_state >= 161 ) |
| 1319 | yy_c = yy_meta[(unsigned int) yy_c]; | 1531 | yy_c = yy_meta[(unsigned int) yy_c]; |
| 1320 | } | 1532 | } |
| 1321 | yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; | 1533 | yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; |
| 1322 | yy_is_jam = (yy_current_state == 93); | 1534 | yy_is_jam = (yy_current_state == 160); |
| 1323 | 1535 | ||
| 1324 | return yy_is_jam ? 0 : yy_current_state; | 1536 | return yy_is_jam ? 0 : yy_current_state; |
| 1325 | } | 1537 | } |
| @@ -1394,6 +1606,8 @@ static int yy_get_next_buffer (void) | |||
| 1394 | *(yy_c_buf_p) = '\0'; /* preserve yytext */ | 1606 | *(yy_c_buf_p) = '\0'; /* preserve yytext */ |
| 1395 | (yy_hold_char) = *++(yy_c_buf_p); | 1607 | (yy_hold_char) = *++(yy_c_buf_p); |
| 1396 | 1608 | ||
| 1609 | YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n'); | ||
| 1610 | |||
| 1397 | return c; | 1611 | return c; |
| 1398 | } | 1612 | } |
| 1399 | #endif /* ifndef YY_NO_INPUT */ | 1613 | #endif /* ifndef YY_NO_INPUT */ |
| @@ -1712,8 +1926,8 @@ YY_BUFFER_STATE yy_scan_string (yyconst char * yystr ) | |||
| 1712 | 1926 | ||
| 1713 | /** Setup the input buffer state to scan the given bytes. The next call to yylex() will | 1927 | /** Setup the input buffer state to scan the given bytes. The next call to yylex() will |
| 1714 | * scan from a @e copy of @a bytes. | 1928 | * scan from a @e copy of @a bytes. |
| 1715 | * @param bytes the byte buffer to scan | 1929 | * @param yybytes the byte buffer to scan |
| 1716 | * @param len the number of bytes in the buffer pointed to by @a bytes. | 1930 | * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. |
| 1717 | * | 1931 | * |
| 1718 | * @return the newly allocated buffer state object. | 1932 | * @return the newly allocated buffer state object. |
| 1719 | */ | 1933 | */ |
| @@ -1952,6 +2166,10 @@ void yyfree (void * ptr ) | |||
| 1952 | 2166 | ||
| 1953 | #define YYTABLES_NAME "yytables" | 2167 | #define YYTABLES_NAME "yytables" |
| 1954 | 2168 | ||
| 2169 | #line 227 "dtc-lexer.l" | ||
| 2170 | |||
| 2171 | |||
| 2172 | |||
| 1955 | static void push_input_file(const char *filename) | 2173 | static void push_input_file(const char *filename) |
| 1956 | { | 2174 | { |
| 1957 | assert(filename); | 2175 | assert(filename); |
| @@ -1963,6 +2181,7 @@ static void push_input_file(const char *filename) | |||
| 1963 | yypush_buffer_state(yy_create_buffer(yyin,YY_BUF_SIZE)); | 2181 | yypush_buffer_state(yy_create_buffer(yyin,YY_BUF_SIZE)); |
| 1964 | } | 2182 | } |
| 1965 | 2183 | ||
| 2184 | |||
| 1966 | static int pop_input_file(void) | 2185 | static int pop_input_file(void) |
| 1967 | { | 2186 | { |
| 1968 | if (srcfile_pop() == 0) | 2187 | if (srcfile_pop() == 0) |
diff --git a/scripts/dtc/dtc-parser.tab.c_shipped b/scripts/dtc/dtc-parser.tab.c_shipped index b05921e1e848..4af55900a15b 100644 --- a/scripts/dtc/dtc-parser.tab.c_shipped +++ b/scripts/dtc/dtc-parser.tab.c_shipped | |||
| @@ -1,9 +1,10 @@ | |||
| 1 | /* A Bison parser, made by GNU Bison 2.4.3. */ | 1 | |
| 2 | /* A Bison parser, made by GNU Bison 2.4.1. */ | ||
| 2 | 3 | ||
| 3 | /* Skeleton implementation for Bison's Yacc-like parsers in C | 4 | /* Skeleton implementation for Bison's Yacc-like parsers in C |
| 4 | 5 | ||
| 5 | Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006, | 6 | Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 |
| 6 | 2009, 2010 Free Software Foundation, Inc. | 7 | Free Software Foundation, Inc. |
| 7 | 8 | ||
| 8 | This program is free software: you can redistribute it and/or modify | 9 | This program is free software: you can redistribute it and/or modify |
| 9 | it under the terms of the GNU General Public License as published by | 10 | it under the terms of the GNU General Public License as published by |
| @@ -45,7 +46,7 @@ | |||
| 45 | #define YYBISON 1 | 46 | #define YYBISON 1 |
| 46 | 47 | ||
| 47 | /* Bison version. */ | 48 | /* Bison version. */ |
| 48 | #define YYBISON_VERSION "2.4.3" | 49 | #define YYBISON_VERSION "2.4.1" |
| 49 | 50 | ||
| 50 | /* Skeleton name. */ | 51 | /* Skeleton name. */ |
| 51 | #define YYSKELETON_NAME "yacc.c" | 52 | #define YYSKELETON_NAME "yacc.c" |
| @@ -66,6 +67,8 @@ | |||
| 66 | 67 | ||
| 67 | /* Copy the first part of user declarations. */ | 68 | /* Copy the first part of user declarations. */ |
| 68 | 69 | ||
| 70 | /* Line 189 of yacc.c */ | ||
| 71 | #line 21 "dtc-parser.y" | ||
| 69 | 72 | ||
| 70 | #include <stdio.h> | 73 | #include <stdio.h> |
| 71 | 74 | ||
| @@ -82,12 +85,15 @@ extern struct boot_info *the_boot_info; | |||
| 82 | extern int treesource_error; | 85 | extern int treesource_error; |
| 83 | 86 | ||
| 84 | static unsigned long long eval_literal(const char *s, int base, int bits); | 87 | static unsigned long long eval_literal(const char *s, int base, int bits); |
| 88 | static unsigned char eval_char_literal(const char *s); | ||
| 85 | 89 | ||
| 86 | 90 | ||
| 91 | /* Line 189 of yacc.c */ | ||
| 92 | #line 93 "dtc-parser.tab.c" | ||
| 87 | 93 | ||
| 88 | /* Enabling traces. */ | 94 | /* Enabling traces. */ |
| 89 | #ifndef YYDEBUG | 95 | #ifndef YYDEBUG |
| 90 | # define YYDEBUG 1 | 96 | # define YYDEBUG 0 |
| 91 | #endif | 97 | #endif |
| 92 | 98 | ||
| 93 | /* Enabling verbose error messages. */ | 99 | /* Enabling verbose error messages. */ |
| @@ -112,14 +118,26 @@ static unsigned long long eval_literal(const char *s, int base, int bits); | |||
| 112 | enum yytokentype { | 118 | enum yytokentype { |
| 113 | DT_V1 = 258, | 119 | DT_V1 = 258, |
| 114 | DT_MEMRESERVE = 259, | 120 | DT_MEMRESERVE = 259, |
| 115 | DT_PROPNODENAME = 260, | 121 | DT_LSHIFT = 260, |
| 116 | DT_LITERAL = 261, | 122 | DT_RSHIFT = 261, |
| 117 | DT_BASE = 262, | 123 | DT_LE = 262, |
| 118 | DT_BYTE = 263, | 124 | DT_GE = 263, |
| 119 | DT_STRING = 264, | 125 | DT_EQ = 264, |
| 120 | DT_LABEL = 265, | 126 | DT_NE = 265, |
| 121 | DT_REF = 266, | 127 | DT_AND = 266, |
| 122 | DT_INCBIN = 267 | 128 | DT_OR = 267, |
| 129 | DT_BITS = 268, | ||
| 130 | DT_DEL_PROP = 269, | ||
| 131 | DT_DEL_NODE = 270, | ||
| 132 | DT_PROPNODENAME = 271, | ||
| 133 | DT_LITERAL = 272, | ||
| 134 | DT_CHAR_LITERAL = 273, | ||
| 135 | DT_BASE = 274, | ||
| 136 | DT_BYTE = 275, | ||
| 137 | DT_STRING = 276, | ||
| 138 | DT_LABEL = 277, | ||
| 139 | DT_REF = 278, | ||
| 140 | DT_INCBIN = 279 | ||
| 123 | }; | 141 | }; |
| 124 | #endif | 142 | #endif |
| 125 | 143 | ||
| @@ -129,6 +147,8 @@ static unsigned long long eval_literal(const char *s, int base, int bits); | |||
| 129 | typedef union YYSTYPE | 147 | typedef union YYSTYPE |
| 130 | { | 148 | { |
| 131 | 149 | ||
| 150 | /* Line 214 of yacc.c */ | ||
| 151 | #line 40 "dtc-parser.y" | ||
| 132 | 152 | ||
| 133 | char *propnodename; | 153 | char *propnodename; |
| 134 | char *literal; | 154 | char *literal; |
| @@ -137,16 +157,22 @@ typedef union YYSTYPE | |||
| 137 | uint8_t byte; | 157 | uint8_t byte; |
| 138 | struct data data; | 158 | struct data data; |
| 139 | 159 | ||
| 140 | uint64_t addr; | 160 | struct { |
| 141 | cell_t cell; | 161 | struct data data; |
| 162 | int bits; | ||
| 163 | } array; | ||
| 164 | |||
| 142 | struct property *prop; | 165 | struct property *prop; |
| 143 | struct property *proplist; | 166 | struct property *proplist; |
| 144 | struct node *node; | 167 | struct node *node; |
| 145 | struct node *nodelist; | 168 | struct node *nodelist; |
| 146 | struct reserve_info *re; | 169 | struct reserve_info *re; |
| 170 | uint64_t integer; | ||
| 147 | 171 | ||
| 148 | 172 | ||
| 149 | 173 | ||
| 174 | /* Line 214 of yacc.c */ | ||
| 175 | #line 176 "dtc-parser.tab.c" | ||
| 150 | } YYSTYPE; | 176 | } YYSTYPE; |
| 151 | # define YYSTYPE_IS_TRIVIAL 1 | 177 | # define YYSTYPE_IS_TRIVIAL 1 |
| 152 | # define yystype YYSTYPE /* obsolescent; will be withdrawn */ | 178 | # define yystype YYSTYPE /* obsolescent; will be withdrawn */ |
| @@ -157,6 +183,8 @@ typedef union YYSTYPE | |||
| 157 | /* Copy the second part of user declarations. */ | 183 | /* Copy the second part of user declarations. */ |
| 158 | 184 | ||
| 159 | 185 | ||
| 186 | /* Line 264 of yacc.c */ | ||
| 187 | #line 188 "dtc-parser.tab.c" | ||
| 160 | 188 | ||
| 161 | #ifdef short | 189 | #ifdef short |
| 162 | # undef short | 190 | # undef short |
| @@ -206,7 +234,7 @@ typedef short int yytype_int16; | |||
| 206 | #define YYSIZE_MAXIMUM ((YYSIZE_T) -1) | 234 | #define YYSIZE_MAXIMUM ((YYSIZE_T) -1) |
| 207 | 235 | ||
| 208 | #ifndef YY_ | 236 | #ifndef YY_ |
| 209 | # if defined YYENABLE_NLS && YYENABLE_NLS | 237 | # if YYENABLE_NLS |
| 210 | # if ENABLE_NLS | 238 | # if ENABLE_NLS |
| 211 | # include <libintl.h> /* INFRINGES ON USER NAME SPACE */ | 239 | # include <libintl.h> /* INFRINGES ON USER NAME SPACE */ |
| 212 | # define YY_(msgid) dgettext ("bison-runtime", msgid) | 240 | # define YY_(msgid) dgettext ("bison-runtime", msgid) |
| @@ -371,20 +399,20 @@ union yyalloc | |||
| 371 | /* YYFINAL -- State number of the termination state. */ | 399 | /* YYFINAL -- State number of the termination state. */ |
| 372 | #define YYFINAL 4 | 400 | #define YYFINAL 4 |
| 373 | /* YYLAST -- Last index in YYTABLE. */ | 401 | /* YYLAST -- Last index in YYTABLE. */ |
| 374 | #define YYLAST 56 | 402 | #define YYLAST 133 |
| 375 | 403 | ||
| 376 | /* YYNTOKENS -- Number of terminals. */ | 404 | /* YYNTOKENS -- Number of terminals. */ |
| 377 | #define YYNTOKENS 25 | 405 | #define YYNTOKENS 48 |
| 378 | /* YYNNTS -- Number of nonterminals. */ | 406 | /* YYNNTS -- Number of nonterminals. */ |
| 379 | #define YYNNTS 16 | 407 | #define YYNNTS 28 |
| 380 | /* YYNRULES -- Number of rules. */ | 408 | /* YYNRULES -- Number of rules. */ |
| 381 | #define YYNRULES 39 | 409 | #define YYNRULES 79 |
| 382 | /* YYNRULES -- Number of states. */ | 410 | /* YYNRULES -- Number of states. */ |
| 383 | #define YYNSTATES 67 | 411 | #define YYNSTATES 141 |
| 384 | 412 | ||
| 385 | /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ | 413 | /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ |
| 386 | #define YYUNDEFTOK 2 | 414 | #define YYUNDEFTOK 2 |
| 387 | #define YYMAXUTOK 267 | 415 | #define YYMAXUTOK 279 |
| 388 | 416 | ||
| 389 | #define YYTRANSLATE(YYX) \ | 417 | #define YYTRANSLATE(YYX) \ |
| 390 | ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) | 418 | ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) |
| @@ -395,16 +423,16 @@ static const yytype_uint8 yytranslate[] = | |||
| 395 | 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, | 423 | 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 396 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, | 424 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 397 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, | 425 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 398 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, | 426 | 2, 2, 2, 47, 2, 2, 2, 45, 41, 2, |
| 399 | 22, 24, 2, 2, 23, 2, 2, 14, 2, 2, | 427 | 33, 35, 44, 42, 34, 43, 2, 26, 2, 2, |
| 400 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 13, | 428 | 2, 2, 2, 2, 2, 2, 2, 2, 38, 25, |
| 401 | 18, 17, 19, 2, 2, 2, 2, 2, 2, 2, | 429 | 36, 29, 30, 37, 2, 2, 2, 2, 2, 2, |
| 402 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, | 430 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 403 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, | 431 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 404 | 2, 20, 2, 21, 2, 2, 2, 2, 2, 2, | 432 | 2, 31, 2, 32, 40, 2, 2, 2, 2, 2, |
| 405 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, | 433 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 406 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, | 434 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 407 | 2, 2, 2, 15, 2, 16, 2, 2, 2, 2, | 435 | 2, 2, 2, 27, 39, 28, 46, 2, 2, 2, |
| 408 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, | 436 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 409 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, | 437 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 410 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, | 438 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| @@ -418,45 +446,68 @@ static const yytype_uint8 yytranslate[] = | |||
| 418 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, | 446 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 419 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, | 447 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 420 | 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, | 448 | 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, |
| 421 | 5, 6, 7, 8, 9, 10, 11, 12 | 449 | 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, |
| 450 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 | ||
| 422 | }; | 451 | }; |
| 423 | 452 | ||
| 424 | #if YYDEBUG | 453 | #if YYDEBUG |
| 425 | /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in | 454 | /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in |
| 426 | YYRHS. */ | 455 | YYRHS. */ |
| 427 | static const yytype_uint8 yyprhs[] = | 456 | static const yytype_uint16 yyprhs[] = |
| 428 | { | 457 | { |
| 429 | 0, 0, 3, 8, 9, 12, 17, 20, 22, 25, | 458 | 0, 0, 3, 8, 9, 12, 17, 20, 23, 27, |
| 430 | 29, 33, 39, 40, 43, 48, 51, 54, 57, 62, | 459 | 31, 36, 42, 43, 46, 51, 54, 58, 61, 64, |
| 431 | 67, 70, 80, 86, 89, 90, 93, 96, 97, 100, | 460 | 68, 73, 76, 86, 92, 95, 96, 99, 102, 106, |
| 432 | 103, 106, 108, 109, 112, 115, 116, 119, 122, 125 | 461 | 108, 111, 114, 117, 119, 121, 125, 127, 129, 135, |
| 462 | 137, 141, 143, 147, 149, 153, 155, 159, 161, 165, | ||
| 463 | 167, 171, 175, 177, 181, 185, 189, 193, 197, 201, | ||
| 464 | 203, 207, 211, 213, 217, 221, 225, 227, 229, 232, | ||
| 465 | 235, 238, 239, 242, 245, 246, 249, 252, 255, 259 | ||
| 433 | }; | 466 | }; |
| 434 | 467 | ||
| 435 | /* YYRHS -- A `-1'-separated list of the rules' RHS. */ | 468 | /* YYRHS -- A `-1'-separated list of the rules' RHS. */ |
| 436 | static const yytype_int8 yyrhs[] = | 469 | static const yytype_int8 yyrhs[] = |
| 437 | { | 470 | { |
| 438 | 26, 0, -1, 3, 13, 27, 30, -1, -1, 28, | 471 | 49, 0, -1, 3, 25, 50, 52, -1, -1, 51, |
| 439 | 27, -1, 4, 29, 29, 13, -1, 10, 28, -1, | 472 | 50, -1, 4, 59, 59, 25, -1, 22, 51, -1, |
| 440 | 6, -1, 14, 31, -1, 30, 14, 31, -1, 30, | 473 | 26, 53, -1, 52, 26, 53, -1, 52, 23, 53, |
| 441 | 11, 31, -1, 15, 32, 39, 16, 13, -1, -1, | 474 | -1, 52, 15, 23, 25, -1, 27, 54, 74, 28, |
| 442 | 32, 33, -1, 5, 17, 34, 13, -1, 5, 13, | 475 | 25, -1, -1, 54, 55, -1, 16, 29, 56, 25, |
| 443 | -1, 10, 33, -1, 35, 9, -1, 35, 18, 36, | 476 | -1, 16, 25, -1, 14, 16, 25, -1, 22, 55, |
| 444 | 19, -1, 35, 20, 38, 21, -1, 35, 11, -1, | 477 | -1, 57, 21, -1, 57, 58, 30, -1, 57, 31, |
| 445 | 35, 12, 22, 9, 23, 29, 23, 29, 24, -1, | 478 | 73, 32, -1, 57, 23, -1, 57, 24, 33, 21, |
| 446 | 35, 12, 22, 9, 24, -1, 34, 10, -1, -1, | 479 | 34, 59, 34, 59, 35, -1, 57, 24, 33, 21, |
| 447 | 34, 23, -1, 35, 10, -1, -1, 36, 37, -1, | 480 | 35, -1, 56, 22, -1, -1, 56, 34, -1, 57, |
| 448 | 36, 11, -1, 36, 10, -1, 6, -1, -1, 38, | 481 | 22, -1, 13, 17, 36, -1, 36, -1, 58, 59, |
| 449 | 8, -1, 38, 10, -1, -1, 40, 39, -1, 40, | 482 | -1, 58, 23, -1, 58, 22, -1, 17, -1, 18, |
| 450 | 33, -1, 5, 31, -1, 10, 40, -1 | 483 | -1, 33, 60, 35, -1, 61, -1, 62, -1, 62, |
| 484 | 37, 60, 38, 61, -1, 63, -1, 62, 12, 63, | ||
| 485 | -1, 64, -1, 63, 11, 64, -1, 65, -1, 64, | ||
| 486 | 39, 65, -1, 66, -1, 65, 40, 66, -1, 67, | ||
| 487 | -1, 66, 41, 67, -1, 68, -1, 67, 9, 68, | ||
| 488 | -1, 67, 10, 68, -1, 69, -1, 68, 36, 69, | ||
| 489 | -1, 68, 30, 69, -1, 68, 7, 69, -1, 68, | ||
| 490 | 8, 69, -1, 69, 5, 70, -1, 69, 6, 70, | ||
| 491 | -1, 70, -1, 70, 42, 71, -1, 70, 43, 71, | ||
| 492 | -1, 71, -1, 71, 44, 72, -1, 71, 26, 72, | ||
| 493 | -1, 71, 45, 72, -1, 72, -1, 59, -1, 43, | ||
| 494 | 72, -1, 46, 72, -1, 47, 72, -1, -1, 73, | ||
| 495 | 20, -1, 73, 22, -1, -1, 75, 74, -1, 75, | ||
| 496 | 55, -1, 16, 53, -1, 15, 16, 25, -1, 22, | ||
| 497 | 75, -1 | ||
| 451 | }; | 498 | }; |
| 452 | 499 | ||
| 453 | /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ | 500 | /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ |
| 454 | static const yytype_uint16 yyrline[] = | 501 | static const yytype_uint16 yyrline[] = |
| 455 | { | 502 | { |
| 456 | 0, 86, 86, 95, 98, 105, 109, 117, 124, 128, | 503 | 0, 109, 109, 118, 121, 128, 132, 140, 144, 148, |
| 457 | 132, 145, 153, 156, 163, 167, 171, 179, 183, 187, | 504 | 158, 172, 180, 183, 190, 194, 198, 202, 210, 214, |
| 458 | 191, 195, 212, 222, 230, 233, 237, 245, 248, 252, | 505 | 218, 222, 226, 243, 253, 261, 264, 268, 275, 290, |
| 459 | 257, 264, 272, 275, 279, 287, 290, 294, 302, 306 | 506 | 295, 315, 329, 336, 340, 344, 351, 355, 356, 360, |
| 507 | 361, 365, 366, 370, 371, 375, 376, 380, 381, 385, | ||
| 508 | 386, 387, 391, 392, 393, 394, 395, 399, 400, 401, | ||
| 509 | 405, 406, 407, 411, 412, 413, 414, 418, 419, 420, | ||
| 510 | 421, 426, 429, 433, 441, 444, 448, 456, 460, 464 | ||
| 460 | }; | 511 | }; |
| 461 | #endif | 512 | #endif |
| 462 | 513 | ||
| @@ -465,13 +516,19 @@ static const yytype_uint16 yyrline[] = | |||
| 465 | First, the terminals, then, starting at YYNTOKENS, nonterminals. */ | 516 | First, the terminals, then, starting at YYNTOKENS, nonterminals. */ |
| 466 | static const char *const yytname[] = | 517 | static const char *const yytname[] = |
| 467 | { | 518 | { |
| 468 | "$end", "error", "$undefined", "DT_V1", "DT_MEMRESERVE", | 519 | "$end", "error", "$undefined", "DT_V1", "DT_MEMRESERVE", "DT_LSHIFT", |
| 469 | "DT_PROPNODENAME", "DT_LITERAL", "DT_BASE", "DT_BYTE", "DT_STRING", | 520 | "DT_RSHIFT", "DT_LE", "DT_GE", "DT_EQ", "DT_NE", "DT_AND", "DT_OR", |
| 470 | "DT_LABEL", "DT_REF", "DT_INCBIN", "';'", "'/'", "'{'", "'}'", "'='", | 521 | "DT_BITS", "DT_DEL_PROP", "DT_DEL_NODE", "DT_PROPNODENAME", "DT_LITERAL", |
| 471 | "'<'", "'>'", "'['", "']'", "'('", "','", "')'", "$accept", "sourcefile", | 522 | "DT_CHAR_LITERAL", "DT_BASE", "DT_BYTE", "DT_STRING", "DT_LABEL", |
| 472 | "memreserves", "memreserve", "addr", "devicetree", "nodedef", "proplist", | 523 | "DT_REF", "DT_INCBIN", "';'", "'/'", "'{'", "'}'", "'='", "'>'", "'['", |
| 473 | "propdef", "propdata", "propdataprefix", "celllist", "cellval", | 524 | "']'", "'('", "','", "')'", "'<'", "'?'", "':'", "'|'", "'^'", "'&'", |
| 474 | "bytestring", "subnodes", "subnode", 0 | 525 | "'+'", "'-'", "'*'", "'%'", "'~'", "'!'", "$accept", "sourcefile", |
| 526 | "memreserves", "memreserve", "devicetree", "nodedef", "proplist", | ||
| 527 | "propdef", "propdata", "propdataprefix", "arrayprefix", "integer_prim", | ||
| 528 | "integer_expr", "integer_trinary", "integer_or", "integer_and", | ||
| 529 | "integer_bitor", "integer_bitxor", "integer_bitand", "integer_eq", | ||
| 530 | "integer_rela", "integer_shift", "integer_add", "integer_mul", | ||
| 531 | "integer_unary", "bytestring", "subnodes", "subnode", 0 | ||
| 475 | }; | 532 | }; |
| 476 | #endif | 533 | #endif |
| 477 | 534 | ||
| @@ -481,27 +538,37 @@ static const char *const yytname[] = | |||
| 481 | static const yytype_uint16 yytoknum[] = | 538 | static const yytype_uint16 yytoknum[] = |
| 482 | { | 539 | { |
| 483 | 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, | 540 | 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, |
| 484 | 265, 266, 267, 59, 47, 123, 125, 61, 60, 62, | 541 | 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, |
| 485 | 91, 93, 40, 44, 41 | 542 | 275, 276, 277, 278, 279, 59, 47, 123, 125, 61, |
| 543 | 62, 91, 93, 40, 44, 41, 60, 63, 58, 124, | ||
| 544 | 94, 38, 43, 45, 42, 37, 126, 33 | ||
| 486 | }; | 545 | }; |
| 487 | # endif | 546 | # endif |
| 488 | 547 | ||
| 489 | /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ | 548 | /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ |
| 490 | static const yytype_uint8 yyr1[] = | 549 | static const yytype_uint8 yyr1[] = |
| 491 | { | 550 | { |
| 492 | 0, 25, 26, 27, 27, 28, 28, 29, 30, 30, | 551 | 0, 48, 49, 50, 50, 51, 51, 52, 52, 52, |
| 493 | 30, 31, 32, 32, 33, 33, 33, 34, 34, 34, | 552 | 52, 53, 54, 54, 55, 55, 55, 55, 56, 56, |
| 494 | 34, 34, 34, 34, 35, 35, 35, 36, 36, 36, | 553 | 56, 56, 56, 56, 56, 57, 57, 57, 58, 58, |
| 495 | 36, 37, 38, 38, 38, 39, 39, 39, 40, 40 | 554 | 58, 58, 58, 59, 59, 59, 60, 61, 61, 62, |
| 555 | 62, 63, 63, 64, 64, 65, 65, 66, 66, 67, | ||
| 556 | 67, 67, 68, 68, 68, 68, 68, 69, 69, 69, | ||
| 557 | 70, 70, 70, 71, 71, 71, 71, 72, 72, 72, | ||
| 558 | 72, 73, 73, 73, 74, 74, 74, 75, 75, 75 | ||
| 496 | }; | 559 | }; |
| 497 | 560 | ||
| 498 | /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ | 561 | /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ |
| 499 | static const yytype_uint8 yyr2[] = | 562 | static const yytype_uint8 yyr2[] = |
| 500 | { | 563 | { |
| 501 | 0, 2, 4, 0, 2, 4, 2, 1, 2, 3, | 564 | 0, 2, 4, 0, 2, 4, 2, 2, 3, 3, |
| 502 | 3, 5, 0, 2, 4, 2, 2, 2, 4, 4, | 565 | 4, 5, 0, 2, 4, 2, 3, 2, 2, 3, |
| 503 | 2, 9, 5, 2, 0, 2, 2, 0, 2, 2, | 566 | 4, 2, 9, 5, 2, 0, 2, 2, 3, 1, |
| 504 | 2, 1, 0, 2, 2, 0, 2, 2, 2, 2 | 567 | 2, 2, 2, 1, 1, 3, 1, 1, 5, 1, |
| 568 | 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, | ||
| 569 | 3, 3, 1, 3, 3, 3, 3, 3, 3, 1, | ||
| 570 | 3, 3, 1, 3, 3, 3, 1, 1, 2, 2, | ||
| 571 | 2, 0, 2, 2, 0, 2, 2, 2, 3, 2 | ||
| 505 | }; | 572 | }; |
| 506 | 573 | ||
| 507 | /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state | 574 | /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state |
| @@ -509,41 +576,59 @@ static const yytype_uint8 yyr2[] = | |||
| 509 | means the default is an error. */ | 576 | means the default is an error. */ |
| 510 | static const yytype_uint8 yydefact[] = | 577 | static const yytype_uint8 yydefact[] = |
| 511 | { | 578 | { |
| 512 | 0, 0, 0, 3, 1, 0, 0, 0, 3, 7, | 579 | 0, 0, 0, 3, 1, 0, 0, 0, 3, 33, |
| 513 | 0, 6, 0, 2, 4, 0, 12, 8, 0, 0, | 580 | 34, 0, 0, 6, 0, 2, 4, 0, 0, 0, |
| 514 | 5, 35, 10, 9, 0, 0, 13, 0, 35, 15, | 581 | 67, 0, 36, 37, 39, 41, 43, 45, 47, 49, |
| 515 | 24, 38, 16, 39, 0, 37, 36, 0, 0, 11, | 582 | 52, 59, 62, 66, 0, 12, 7, 0, 0, 0, |
| 516 | 23, 14, 25, 17, 26, 20, 0, 27, 32, 0, | 583 | 68, 69, 70, 35, 0, 0, 0, 0, 0, 0, |
| 517 | 0, 0, 0, 31, 30, 29, 18, 28, 33, 34, | 584 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 518 | 19, 0, 22, 0, 0, 0, 21 | 585 | 0, 0, 0, 5, 74, 0, 9, 8, 40, 0, |
| 586 | 42, 44, 46, 48, 50, 51, 55, 56, 54, 53, | ||
| 587 | 57, 58, 60, 61, 64, 63, 65, 0, 0, 0, | ||
| 588 | 0, 13, 0, 74, 10, 0, 0, 0, 15, 25, | ||
| 589 | 77, 17, 79, 0, 76, 75, 38, 16, 78, 0, | ||
| 590 | 0, 11, 24, 14, 26, 0, 18, 27, 21, 0, | ||
| 591 | 71, 29, 0, 0, 0, 0, 32, 31, 19, 30, | ||
| 592 | 28, 0, 72, 73, 20, 0, 23, 0, 0, 0, | ||
| 593 | 22 | ||
| 519 | }; | 594 | }; |
| 520 | 595 | ||
| 521 | /* YYDEFGOTO[NTERM-NUM]. */ | 596 | /* YYDEFGOTO[NTERM-NUM]. */ |
| 522 | static const yytype_int8 yydefgoto[] = | 597 | static const yytype_int8 yydefgoto[] = |
| 523 | { | 598 | { |
| 524 | -1, 2, 7, 8, 10, 13, 17, 21, 26, 37, | 599 | -1, 2, 7, 8, 15, 36, 64, 91, 109, 110, |
| 525 | 38, 50, 57, 51, 27, 28 | 600 | 122, 20, 21, 22, 23, 24, 25, 26, 27, 28, |
| 601 | 29, 30, 31, 32, 33, 125, 92, 93 | ||
| 526 | }; | 602 | }; |
| 527 | 603 | ||
| 528 | /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing | 604 | /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing |
| 529 | STATE-NUM. */ | 605 | STATE-NUM. */ |
| 530 | #define YYPACT_NINF -12 | 606 | #define YYPACT_NINF -78 |
| 531 | static const yytype_int8 yypact[] = | 607 | static const yytype_int8 yypact[] = |
| 532 | { | 608 | { |
| 533 | 10, -11, 18, -1, -12, 22, -1, 15, -1, -12, | 609 | 22, 11, 51, 10, -78, 23, 10, 2, 10, -78, |
| 534 | 22, -12, 20, 1, -12, 17, -12, -12, 20, 20, | 610 | -78, -9, 23, -78, 30, 38, -78, -9, -9, -9, |
| 535 | -12, 6, -12, -12, 21, 6, -12, 23, 6, -12, | 611 | -78, 35, -78, -6, 52, 29, 48, 49, 33, 3, |
| 536 | -12, -12, -12, -12, 28, -12, -12, -6, 13, -12, | 612 | 71, 36, 0, -78, 64, -78, -78, 68, 30, 30, |
| 537 | -12, -12, -12, -12, -12, -12, 24, -12, -12, 33, | 613 | -78, -78, -78, -78, -9, -9, -9, -9, -9, -9, |
| 538 | -5, 0, -4, -12, -12, -12, -12, -12, -12, -12, | 614 | -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, |
| 539 | -12, 22, -12, 25, 22, 19, -12 | 615 | -9, -9, -9, -78, 44, 67, -78, -78, 52, 55, |
| 616 | 29, 48, 49, 33, 3, 3, 71, 71, 71, 71, | ||
| 617 | 36, 36, 0, 0, -78, -78, -78, 78, 79, 42, | ||
| 618 | 44, -78, 69, 44, -78, -9, 73, 74, -78, -78, | ||
| 619 | -78, -78, -78, 75, -78, -78, -78, -78, -78, -7, | ||
| 620 | -1, -78, -78, -78, -78, 84, -78, -78, -78, 63, | ||
| 621 | -78, -78, 32, 66, 82, -3, -78, -78, -78, -78, | ||
| 622 | -78, 46, -78, -78, -78, 23, -78, 70, 23, 72, | ||
| 623 | -78 | ||
| 540 | }; | 624 | }; |
| 541 | 625 | ||
| 542 | /* YYPGOTO[NTERM-NUM]. */ | 626 | /* YYPGOTO[NTERM-NUM]. */ |
| 543 | static const yytype_int8 yypgoto[] = | 627 | static const yytype_int8 yypgoto[] = |
| 544 | { | 628 | { |
| 545 | -12, -12, 36, 39, -10, -12, 8, -12, 12, -12, | 629 | -78, -78, 97, 100, -78, -37, -78, -77, -78, -78, |
| 546 | -12, -12, -12, -12, 27, 31 | 630 | -78, -5, 65, 13, -78, 76, 77, 62, 80, 83, |
| 631 | 34, 20, 26, 28, -14, -78, 18, 24 | ||
| 547 | }; | 632 | }; |
| 548 | 633 | ||
| 549 | /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If | 634 | /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If |
| @@ -553,35 +638,59 @@ static const yytype_int8 yypgoto[] = | |||
| 553 | #define YYTABLE_NINF -1 | 638 | #define YYTABLE_NINF -1 |
| 554 | static const yytype_uint8 yytable[] = | 639 | static const yytype_uint8 yytable[] = |
| 555 | { | 640 | { |
| 556 | 15, 53, 3, 5, 40, 54, 55, 41, 58, 6, | 641 | 12, 66, 67, 40, 41, 42, 44, 34, 9, 10, |
| 557 | 59, 24, 18, 1, 56, 19, 25, 42, 4, 61, | 642 | 52, 53, 115, 101, 5, 112, 104, 132, 113, 133, |
| 558 | 62, 60, 43, 44, 45, 46, 22, 23, 9, 12, | 643 | 116, 117, 118, 119, 11, 1, 60, 114, 14, 134, |
| 559 | 20, 47, 31, 48, 29, 16, 16, 32, 30, 34, | 644 | 120, 45, 6, 54, 17, 121, 3, 18, 19, 55, |
| 560 | 35, 39, 52, 66, 14, 11, 49, 0, 64, 0, | 645 | 9, 10, 50, 51, 61, 62, 84, 85, 86, 9, |
| 561 | 0, 63, 0, 0, 65, 36, 33 | 646 | 10, 4, 100, 37, 126, 127, 11, 35, 87, 88, |
| 647 | 89, 38, 128, 46, 39, 11, 90, 98, 47, 35, | ||
| 648 | 43, 99, 76, 77, 78, 79, 56, 57, 58, 59, | ||
| 649 | 135, 136, 80, 81, 74, 75, 82, 83, 48, 63, | ||
| 650 | 49, 65, 94, 95, 96, 97, 124, 103, 107, 108, | ||
| 651 | 111, 123, 130, 131, 138, 16, 13, 140, 106, 71, | ||
| 652 | 69, 105, 0, 0, 102, 0, 0, 129, 0, 0, | ||
| 653 | 68, 0, 0, 70, 0, 0, 0, 0, 72, 0, | ||
| 654 | 137, 0, 73, 139 | ||
| 562 | }; | 655 | }; |
| 563 | 656 | ||
| 564 | static const yytype_int8 yycheck[] = | 657 | static const yytype_int16 yycheck[] = |
| 565 | { | 658 | { |
| 566 | 10, 6, 13, 4, 10, 10, 11, 13, 8, 10, | 659 | 5, 38, 39, 17, 18, 19, 12, 12, 17, 18, |
| 567 | 10, 5, 11, 3, 19, 14, 10, 23, 0, 23, | 660 | 7, 8, 13, 90, 4, 22, 93, 20, 25, 22, |
| 568 | 24, 21, 9, 10, 11, 12, 18, 19, 6, 14, | 661 | 21, 22, 23, 24, 33, 3, 26, 34, 26, 32, |
| 569 | 13, 18, 24, 20, 13, 15, 15, 25, 17, 16, | 662 | 31, 37, 22, 30, 43, 36, 25, 46, 47, 36, |
| 570 | 28, 13, 9, 24, 8, 6, 22, -1, 23, -1, | 663 | 17, 18, 9, 10, 44, 45, 60, 61, 62, 17, |
| 571 | -1, 61, -1, -1, 64, 28, 25 | 664 | 18, 0, 89, 15, 22, 23, 33, 27, 14, 15, |
| 665 | 16, 23, 30, 11, 26, 33, 22, 25, 39, 27, | ||
| 666 | 35, 29, 52, 53, 54, 55, 5, 6, 42, 43, | ||
| 667 | 34, 35, 56, 57, 50, 51, 58, 59, 40, 25, | ||
| 668 | 41, 23, 25, 38, 16, 16, 33, 28, 25, 25, | ||
| 669 | 25, 17, 36, 21, 34, 8, 6, 35, 95, 47, | ||
| 670 | 45, 93, -1, -1, 90, -1, -1, 122, -1, -1, | ||
| 671 | 44, -1, -1, 46, -1, -1, -1, -1, 48, -1, | ||
| 672 | 135, -1, 49, 138 | ||
| 572 | }; | 673 | }; |
| 573 | 674 | ||
| 574 | /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing | 675 | /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing |
| 575 | symbol of state STATE-NUM. */ | 676 | symbol of state STATE-NUM. */ |
| 576 | static const yytype_uint8 yystos[] = | 677 | static const yytype_uint8 yystos[] = |
| 577 | { | 678 | { |
| 578 | 0, 3, 26, 13, 0, 4, 10, 27, 28, 6, | 679 | 0, 3, 49, 25, 0, 4, 22, 50, 51, 17, |
| 579 | 29, 28, 14, 30, 27, 29, 15, 31, 11, 14, | 680 | 18, 33, 59, 51, 26, 52, 50, 43, 46, 47, |
| 580 | 13, 32, 31, 31, 5, 10, 33, 39, 40, 13, | 681 | 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, |
| 581 | 17, 31, 33, 40, 16, 33, 39, 34, 35, 13, | 682 | 69, 70, 71, 72, 59, 27, 53, 15, 23, 26, |
| 582 | 10, 13, 23, 9, 10, 11, 12, 18, 20, 22, | 683 | 72, 72, 72, 35, 12, 37, 11, 39, 40, 41, |
| 583 | 36, 38, 9, 6, 10, 11, 19, 37, 8, 10, | 684 | 9, 10, 7, 8, 30, 36, 5, 6, 42, 43, |
| 584 | 21, 23, 24, 29, 23, 29, 24 | 685 | 26, 44, 45, 25, 54, 23, 53, 53, 63, 60, |
| 686 | 64, 65, 66, 67, 68, 68, 69, 69, 69, 69, | ||
| 687 | 70, 70, 71, 71, 72, 72, 72, 14, 15, 16, | ||
| 688 | 22, 55, 74, 75, 25, 38, 16, 16, 25, 29, | ||
| 689 | 53, 55, 75, 28, 55, 74, 61, 25, 25, 56, | ||
| 690 | 57, 25, 22, 25, 34, 13, 21, 22, 23, 24, | ||
| 691 | 31, 36, 58, 17, 33, 73, 22, 23, 30, 59, | ||
| 692 | 36, 21, 20, 22, 32, 34, 35, 59, 34, 59, | ||
| 693 | 35 | ||
| 585 | }; | 694 | }; |
| 586 | 695 | ||
| 587 | #define yyerrok (yyerrstatus = 0) | 696 | #define yyerrok (yyerrstatus = 0) |
| @@ -596,18 +705,9 @@ static const yytype_uint8 yystos[] = | |||
| 596 | 705 | ||
| 597 | /* Like YYERROR except do call yyerror. This remains here temporarily | 706 | /* Like YYERROR except do call yyerror. This remains here temporarily |
| 598 | to ease the transition to the new meaning of YYERROR, for GCC. | 707 | to ease the transition to the new meaning of YYERROR, for GCC. |
| 599 | Once GCC version 2 has supplanted version 1, this can go. However, | 708 | Once GCC version 2 has supplanted version 1, this can go. */ |
| 600 | YYFAIL appears to be in use. Nevertheless, it is formally deprecated | ||
| 601 | in Bison 2.4.2's NEWS entry, where a plan to phase it out is | ||
| 602 | discussed. */ | ||
| 603 | 709 | ||
| 604 | #define YYFAIL goto yyerrlab | 710 | #define YYFAIL goto yyerrlab |
| 605 | #if defined YYFAIL | ||
| 606 | /* This is here to suppress warnings from the GCC cpp's | ||
| 607 | -Wunused-macros. Normally we don't worry about that warning, but | ||
| 608 | some users do, and we want to make it easy for users to remove | ||
| 609 | YYFAIL uses, which will produce warnings from Bison 2.5. */ | ||
| 610 | #endif | ||
| 611 | 711 | ||
| 612 | #define YYRECOVERING() (!!yyerrstatus) | 712 | #define YYRECOVERING() (!!yyerrstatus) |
| 613 | 713 | ||
| @@ -664,7 +764,7 @@ while (YYID (0)) | |||
| 664 | we won't break user code: when these are the locations we know. */ | 764 | we won't break user code: when these are the locations we know. */ |
| 665 | 765 | ||
| 666 | #ifndef YY_LOCATION_PRINT | 766 | #ifndef YY_LOCATION_PRINT |
| 667 | # if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL | 767 | # if YYLTYPE_IS_TRIVIAL |
| 668 | # define YY_LOCATION_PRINT(File, Loc) \ | 768 | # define YY_LOCATION_PRINT(File, Loc) \ |
| 669 | fprintf (File, "%d.%d-%d.%d", \ | 769 | fprintf (File, "%d.%d-%d.%d", \ |
| 670 | (Loc).first_line, (Loc).first_column, \ | 770 | (Loc).first_line, (Loc).first_column, \ |
| @@ -1403,6 +1503,8 @@ yyreduce: | |||
| 1403 | { | 1503 | { |
| 1404 | case 2: | 1504 | case 2: |
| 1405 | 1505 | ||
| 1506 | /* Line 1455 of yacc.c */ | ||
| 1507 | #line 110 "dtc-parser.y" | ||
| 1406 | { | 1508 | { |
| 1407 | the_boot_info = build_boot_info((yyvsp[(3) - (4)].re), (yyvsp[(4) - (4)].node), | 1509 | the_boot_info = build_boot_info((yyvsp[(3) - (4)].re), (yyvsp[(4) - (4)].node), |
| 1408 | guess_boot_cpuid((yyvsp[(4) - (4)].node))); | 1510 | guess_boot_cpuid((yyvsp[(4) - (4)].node))); |
| @@ -1411,6 +1513,8 @@ yyreduce: | |||
| 1411 | 1513 | ||
| 1412 | case 3: | 1514 | case 3: |
| 1413 | 1515 | ||
| 1516 | /* Line 1455 of yacc.c */ | ||
| 1517 | #line 118 "dtc-parser.y" | ||
| 1414 | { | 1518 | { |
| 1415 | (yyval.re) = NULL; | 1519 | (yyval.re) = NULL; |
| 1416 | ;} | 1520 | ;} |
| @@ -1418,6 +1522,8 @@ yyreduce: | |||
| 1418 | 1522 | ||
| 1419 | case 4: | 1523 | case 4: |
| 1420 | 1524 | ||
| 1525 | /* Line 1455 of yacc.c */ | ||
| 1526 | #line 122 "dtc-parser.y" | ||
| 1421 | { | 1527 | { |
| 1422 | (yyval.re) = chain_reserve_entry((yyvsp[(1) - (2)].re), (yyvsp[(2) - (2)].re)); | 1528 | (yyval.re) = chain_reserve_entry((yyvsp[(1) - (2)].re), (yyvsp[(2) - (2)].re)); |
| 1423 | ;} | 1529 | ;} |
| @@ -1425,13 +1531,17 @@ yyreduce: | |||
| 1425 | 1531 | ||
| 1426 | case 5: | 1532 | case 5: |
| 1427 | 1533 | ||
| 1534 | /* Line 1455 of yacc.c */ | ||
| 1535 | #line 129 "dtc-parser.y" | ||
| 1428 | { | 1536 | { |
| 1429 | (yyval.re) = build_reserve_entry((yyvsp[(2) - (4)].addr), (yyvsp[(3) - (4)].addr)); | 1537 | (yyval.re) = build_reserve_entry((yyvsp[(2) - (4)].integer), (yyvsp[(3) - (4)].integer)); |
| 1430 | ;} | 1538 | ;} |
| 1431 | break; | 1539 | break; |
| 1432 | 1540 | ||
| 1433 | case 6: | 1541 | case 6: |
| 1434 | 1542 | ||
| 1543 | /* Line 1455 of yacc.c */ | ||
| 1544 | #line 133 "dtc-parser.y" | ||
| 1435 | { | 1545 | { |
| 1436 | add_label(&(yyvsp[(2) - (2)].re)->labels, (yyvsp[(1) - (2)].labelref)); | 1546 | add_label(&(yyvsp[(2) - (2)].re)->labels, (yyvsp[(1) - (2)].labelref)); |
| 1437 | (yyval.re) = (yyvsp[(2) - (2)].re); | 1547 | (yyval.re) = (yyvsp[(2) - (2)].re); |
| @@ -1440,40 +1550,57 @@ yyreduce: | |||
| 1440 | 1550 | ||
| 1441 | case 7: | 1551 | case 7: |
| 1442 | 1552 | ||
| 1553 | /* Line 1455 of yacc.c */ | ||
| 1554 | #line 141 "dtc-parser.y" | ||
| 1443 | { | 1555 | { |
| 1444 | (yyval.addr) = eval_literal((yyvsp[(1) - (1)].literal), 0, 64); | 1556 | (yyval.node) = name_node((yyvsp[(2) - (2)].node), ""); |
| 1445 | ;} | 1557 | ;} |
| 1446 | break; | 1558 | break; |
| 1447 | 1559 | ||
| 1448 | case 8: | 1560 | case 8: |
| 1449 | 1561 | ||
| 1562 | /* Line 1455 of yacc.c */ | ||
| 1563 | #line 145 "dtc-parser.y" | ||
| 1450 | { | 1564 | { |
| 1451 | (yyval.node) = name_node((yyvsp[(2) - (2)].node), ""); | 1565 | (yyval.node) = merge_nodes((yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); |
| 1452 | ;} | 1566 | ;} |
| 1453 | break; | 1567 | break; |
| 1454 | 1568 | ||
| 1455 | case 9: | 1569 | case 9: |
| 1456 | 1570 | ||
| 1571 | /* Line 1455 of yacc.c */ | ||
| 1572 | #line 149 "dtc-parser.y" | ||
| 1457 | { | 1573 | { |
| 1458 | (yyval.node) = merge_nodes((yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); | 1574 | struct node *target = get_node_by_ref((yyvsp[(1) - (3)].node), (yyvsp[(2) - (3)].labelref)); |
| 1575 | |||
| 1576 | if (target) | ||
| 1577 | merge_nodes(target, (yyvsp[(3) - (3)].node)); | ||
| 1578 | else | ||
| 1579 | print_error("label or path, '%s', not found", (yyvsp[(2) - (3)].labelref)); | ||
| 1580 | (yyval.node) = (yyvsp[(1) - (3)].node); | ||
| 1459 | ;} | 1581 | ;} |
| 1460 | break; | 1582 | break; |
| 1461 | 1583 | ||
| 1462 | case 10: | 1584 | case 10: |
| 1463 | 1585 | ||
| 1586 | /* Line 1455 of yacc.c */ | ||
| 1587 | #line 159 "dtc-parser.y" | ||
| 1464 | { | 1588 | { |
| 1465 | struct node *target = get_node_by_ref((yyvsp[(1) - (3)].node), (yyvsp[(2) - (3)].labelref)); | 1589 | struct node *target = get_node_by_ref((yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].labelref)); |
| 1466 | 1590 | ||
| 1467 | if (target) | 1591 | if (!target) |
| 1468 | merge_nodes(target, (yyvsp[(3) - (3)].node)); | 1592 | print_error("label or path, '%s', not found", (yyvsp[(3) - (4)].labelref)); |
| 1469 | else | 1593 | else |
| 1470 | print_error("label or path, '%s', not found", (yyvsp[(2) - (3)].labelref)); | 1594 | delete_node(target); |
| 1471 | (yyval.node) = (yyvsp[(1) - (3)].node); | 1595 | |
| 1596 | (yyval.node) = (yyvsp[(1) - (4)].node); | ||
| 1472 | ;} | 1597 | ;} |
| 1473 | break; | 1598 | break; |
| 1474 | 1599 | ||
| 1475 | case 11: | 1600 | case 11: |
| 1476 | 1601 | ||
| 1602 | /* Line 1455 of yacc.c */ | ||
| 1603 | #line 173 "dtc-parser.y" | ||
| 1477 | { | 1604 | { |
| 1478 | (yyval.node) = build_node((yyvsp[(2) - (5)].proplist), (yyvsp[(3) - (5)].nodelist)); | 1605 | (yyval.node) = build_node((yyvsp[(2) - (5)].proplist), (yyvsp[(3) - (5)].nodelist)); |
| 1479 | ;} | 1606 | ;} |
| @@ -1481,6 +1608,8 @@ yyreduce: | |||
| 1481 | 1608 | ||
| 1482 | case 12: | 1609 | case 12: |
| 1483 | 1610 | ||
| 1611 | /* Line 1455 of yacc.c */ | ||
| 1612 | #line 180 "dtc-parser.y" | ||
| 1484 | { | 1613 | { |
| 1485 | (yyval.proplist) = NULL; | 1614 | (yyval.proplist) = NULL; |
| 1486 | ;} | 1615 | ;} |
| @@ -1488,6 +1617,8 @@ yyreduce: | |||
| 1488 | 1617 | ||
| 1489 | case 13: | 1618 | case 13: |
| 1490 | 1619 | ||
| 1620 | /* Line 1455 of yacc.c */ | ||
| 1621 | #line 184 "dtc-parser.y" | ||
| 1491 | { | 1622 | { |
| 1492 | (yyval.proplist) = chain_property((yyvsp[(2) - (2)].prop), (yyvsp[(1) - (2)].proplist)); | 1623 | (yyval.proplist) = chain_property((yyvsp[(2) - (2)].prop), (yyvsp[(1) - (2)].proplist)); |
| 1493 | ;} | 1624 | ;} |
| @@ -1495,6 +1626,8 @@ yyreduce: | |||
| 1495 | 1626 | ||
| 1496 | case 14: | 1627 | case 14: |
| 1497 | 1628 | ||
| 1629 | /* Line 1455 of yacc.c */ | ||
| 1630 | #line 191 "dtc-parser.y" | ||
| 1498 | { | 1631 | { |
| 1499 | (yyval.prop) = build_property((yyvsp[(1) - (4)].propnodename), (yyvsp[(3) - (4)].data)); | 1632 | (yyval.prop) = build_property((yyvsp[(1) - (4)].propnodename), (yyvsp[(3) - (4)].data)); |
| 1500 | ;} | 1633 | ;} |
| @@ -1502,6 +1635,8 @@ yyreduce: | |||
| 1502 | 1635 | ||
| 1503 | case 15: | 1636 | case 15: |
| 1504 | 1637 | ||
| 1638 | /* Line 1455 of yacc.c */ | ||
| 1639 | #line 195 "dtc-parser.y" | ||
| 1505 | { | 1640 | { |
| 1506 | (yyval.prop) = build_property((yyvsp[(1) - (2)].propnodename), empty_data); | 1641 | (yyval.prop) = build_property((yyvsp[(1) - (2)].propnodename), empty_data); |
| 1507 | ;} | 1642 | ;} |
| @@ -1509,62 +1644,85 @@ yyreduce: | |||
| 1509 | 1644 | ||
| 1510 | case 16: | 1645 | case 16: |
| 1511 | 1646 | ||
| 1647 | /* Line 1455 of yacc.c */ | ||
| 1648 | #line 199 "dtc-parser.y" | ||
| 1512 | { | 1649 | { |
| 1513 | add_label(&(yyvsp[(2) - (2)].prop)->labels, (yyvsp[(1) - (2)].labelref)); | 1650 | (yyval.prop) = build_property_delete((yyvsp[(2) - (3)].propnodename)); |
| 1514 | (yyval.prop) = (yyvsp[(2) - (2)].prop); | ||
| 1515 | ;} | 1651 | ;} |
| 1516 | break; | 1652 | break; |
| 1517 | 1653 | ||
| 1518 | case 17: | 1654 | case 17: |
| 1519 | 1655 | ||
| 1656 | /* Line 1455 of yacc.c */ | ||
| 1657 | #line 203 "dtc-parser.y" | ||
| 1520 | { | 1658 | { |
| 1521 | (yyval.data) = data_merge((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].data)); | 1659 | add_label(&(yyvsp[(2) - (2)].prop)->labels, (yyvsp[(1) - (2)].labelref)); |
| 1660 | (yyval.prop) = (yyvsp[(2) - (2)].prop); | ||
| 1522 | ;} | 1661 | ;} |
| 1523 | break; | 1662 | break; |
| 1524 | 1663 | ||
| 1525 | case 18: | 1664 | case 18: |
| 1526 | 1665 | ||
| 1666 | /* Line 1455 of yacc.c */ | ||
| 1667 | #line 211 "dtc-parser.y" | ||
| 1527 | { | 1668 | { |
| 1528 | (yyval.data) = data_merge((yyvsp[(1) - (4)].data), (yyvsp[(3) - (4)].data)); | 1669 | (yyval.data) = data_merge((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].data)); |
| 1529 | ;} | 1670 | ;} |
| 1530 | break; | 1671 | break; |
| 1531 | 1672 | ||
| 1532 | case 19: | 1673 | case 19: |
| 1533 | 1674 | ||
| 1675 | /* Line 1455 of yacc.c */ | ||
| 1676 | #line 215 "dtc-parser.y" | ||
| 1534 | { | 1677 | { |
| 1535 | (yyval.data) = data_merge((yyvsp[(1) - (4)].data), (yyvsp[(3) - (4)].data)); | 1678 | (yyval.data) = data_merge((yyvsp[(1) - (3)].data), (yyvsp[(2) - (3)].array).data); |
| 1536 | ;} | 1679 | ;} |
| 1537 | break; | 1680 | break; |
| 1538 | 1681 | ||
| 1539 | case 20: | 1682 | case 20: |
| 1540 | 1683 | ||
| 1684 | /* Line 1455 of yacc.c */ | ||
| 1685 | #line 219 "dtc-parser.y" | ||
| 1541 | { | 1686 | { |
| 1542 | (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), REF_PATH, (yyvsp[(2) - (2)].labelref)); | 1687 | (yyval.data) = data_merge((yyvsp[(1) - (4)].data), (yyvsp[(3) - (4)].data)); |
| 1543 | ;} | 1688 | ;} |
| 1544 | break; | 1689 | break; |
| 1545 | 1690 | ||
| 1546 | case 21: | 1691 | case 21: |
| 1547 | 1692 | ||
| 1693 | /* Line 1455 of yacc.c */ | ||
| 1694 | #line 223 "dtc-parser.y" | ||
| 1695 | { | ||
| 1696 | (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), REF_PATH, (yyvsp[(2) - (2)].labelref)); | ||
| 1697 | ;} | ||
| 1698 | break; | ||
| 1699 | |||
| 1700 | case 22: | ||
| 1701 | |||
| 1702 | /* Line 1455 of yacc.c */ | ||
| 1703 | #line 227 "dtc-parser.y" | ||
| 1548 | { | 1704 | { |
| 1549 | FILE *f = srcfile_relative_open((yyvsp[(4) - (9)].data).val, NULL); | 1705 | FILE *f = srcfile_relative_open((yyvsp[(4) - (9)].data).val, NULL); |
| 1550 | struct data d; | 1706 | struct data d; |
| 1551 | 1707 | ||
| 1552 | if ((yyvsp[(6) - (9)].addr) != 0) | 1708 | if ((yyvsp[(6) - (9)].integer) != 0) |
| 1553 | if (fseek(f, (yyvsp[(6) - (9)].addr), SEEK_SET) != 0) | 1709 | if (fseek(f, (yyvsp[(6) - (9)].integer), SEEK_SET) != 0) |
| 1554 | print_error("Couldn't seek to offset %llu in \"%s\": %s", | 1710 | print_error("Couldn't seek to offset %llu in \"%s\": %s", |
| 1555 | (unsigned long long)(yyvsp[(6) - (9)].addr), | 1711 | (unsigned long long)(yyvsp[(6) - (9)].integer), |
| 1556 | (yyvsp[(4) - (9)].data).val, | 1712 | (yyvsp[(4) - (9)].data).val, |
| 1557 | strerror(errno)); | 1713 | strerror(errno)); |
| 1558 | 1714 | ||
| 1559 | d = data_copy_file(f, (yyvsp[(8) - (9)].addr)); | 1715 | d = data_copy_file(f, (yyvsp[(8) - (9)].integer)); |
| 1560 | 1716 | ||
| 1561 | (yyval.data) = data_merge((yyvsp[(1) - (9)].data), d); | 1717 | (yyval.data) = data_merge((yyvsp[(1) - (9)].data), d); |
| 1562 | fclose(f); | 1718 | fclose(f); |
| 1563 | ;} | 1719 | ;} |
| 1564 | break; | 1720 | break; |
| 1565 | 1721 | ||
| 1566 | case 22: | 1722 | case 23: |
| 1567 | 1723 | ||
| 1724 | /* Line 1455 of yacc.c */ | ||
| 1725 | #line 244 "dtc-parser.y" | ||
| 1568 | { | 1726 | { |
| 1569 | FILE *f = srcfile_relative_open((yyvsp[(4) - (5)].data).val, NULL); | 1727 | FILE *f = srcfile_relative_open((yyvsp[(4) - (5)].data).val, NULL); |
| 1570 | struct data d = empty_data; | 1728 | struct data d = empty_data; |
| @@ -1576,122 +1734,383 @@ yyreduce: | |||
| 1576 | ;} | 1734 | ;} |
| 1577 | break; | 1735 | break; |
| 1578 | 1736 | ||
| 1579 | case 23: | ||
| 1580 | |||
| 1581 | { | ||
| 1582 | (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref)); | ||
| 1583 | ;} | ||
| 1584 | break; | ||
| 1585 | |||
| 1586 | case 24: | 1737 | case 24: |
| 1587 | 1738 | ||
| 1739 | /* Line 1455 of yacc.c */ | ||
| 1740 | #line 254 "dtc-parser.y" | ||
| 1588 | { | 1741 | { |
| 1589 | (yyval.data) = empty_data; | 1742 | (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref)); |
| 1590 | ;} | 1743 | ;} |
| 1591 | break; | 1744 | break; |
| 1592 | 1745 | ||
| 1593 | case 25: | 1746 | case 25: |
| 1594 | 1747 | ||
| 1748 | /* Line 1455 of yacc.c */ | ||
| 1749 | #line 261 "dtc-parser.y" | ||
| 1595 | { | 1750 | { |
| 1596 | (yyval.data) = (yyvsp[(1) - (2)].data); | 1751 | (yyval.data) = empty_data; |
| 1597 | ;} | 1752 | ;} |
| 1598 | break; | 1753 | break; |
| 1599 | 1754 | ||
| 1600 | case 26: | 1755 | case 26: |
| 1601 | 1756 | ||
| 1757 | /* Line 1455 of yacc.c */ | ||
| 1758 | #line 265 "dtc-parser.y" | ||
| 1602 | { | 1759 | { |
| 1603 | (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref)); | 1760 | (yyval.data) = (yyvsp[(1) - (2)].data); |
| 1604 | ;} | 1761 | ;} |
| 1605 | break; | 1762 | break; |
| 1606 | 1763 | ||
| 1607 | case 27: | 1764 | case 27: |
| 1608 | 1765 | ||
| 1766 | /* Line 1455 of yacc.c */ | ||
| 1767 | #line 269 "dtc-parser.y" | ||
| 1609 | { | 1768 | { |
| 1610 | (yyval.data) = empty_data; | 1769 | (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref)); |
| 1611 | ;} | 1770 | ;} |
| 1612 | break; | 1771 | break; |
| 1613 | 1772 | ||
| 1614 | case 28: | 1773 | case 28: |
| 1615 | 1774 | ||
| 1775 | /* Line 1455 of yacc.c */ | ||
| 1776 | #line 276 "dtc-parser.y" | ||
| 1616 | { | 1777 | { |
| 1617 | (yyval.data) = data_append_cell((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].cell)); | 1778 | (yyval.array).data = empty_data; |
| 1779 | (yyval.array).bits = eval_literal((yyvsp[(2) - (3)].literal), 0, 7); | ||
| 1780 | |||
| 1781 | if (((yyval.array).bits != 8) && | ||
| 1782 | ((yyval.array).bits != 16) && | ||
| 1783 | ((yyval.array).bits != 32) && | ||
| 1784 | ((yyval.array).bits != 64)) | ||
| 1785 | { | ||
| 1786 | print_error("Only 8, 16, 32 and 64-bit elements" | ||
| 1787 | " are currently supported"); | ||
| 1788 | (yyval.array).bits = 32; | ||
| 1789 | } | ||
| 1618 | ;} | 1790 | ;} |
| 1619 | break; | 1791 | break; |
| 1620 | 1792 | ||
| 1621 | case 29: | 1793 | case 29: |
| 1622 | 1794 | ||
| 1795 | /* Line 1455 of yacc.c */ | ||
| 1796 | #line 291 "dtc-parser.y" | ||
| 1623 | { | 1797 | { |
| 1624 | (yyval.data) = data_append_cell(data_add_marker((yyvsp[(1) - (2)].data), REF_PHANDLE, | 1798 | (yyval.array).data = empty_data; |
| 1625 | (yyvsp[(2) - (2)].labelref)), -1); | 1799 | (yyval.array).bits = 32; |
| 1626 | ;} | 1800 | ;} |
| 1627 | break; | 1801 | break; |
| 1628 | 1802 | ||
| 1629 | case 30: | 1803 | case 30: |
| 1630 | 1804 | ||
| 1805 | /* Line 1455 of yacc.c */ | ||
| 1806 | #line 296 "dtc-parser.y" | ||
| 1631 | { | 1807 | { |
| 1632 | (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref)); | 1808 | if ((yyvsp[(1) - (2)].array).bits < 64) { |
| 1809 | uint64_t mask = (1ULL << (yyvsp[(1) - (2)].array).bits) - 1; | ||
| 1810 | /* | ||
| 1811 | * Bits above mask must either be all zero | ||
| 1812 | * (positive within range of mask) or all one | ||
| 1813 | * (negative and sign-extended). The second | ||
| 1814 | * condition is true if when we set all bits | ||
| 1815 | * within the mask to one (i.e. | in the | ||
| 1816 | * mask), all bits are one. | ||
| 1817 | */ | ||
| 1818 | if (((yyvsp[(2) - (2)].integer) > mask) && (((yyvsp[(2) - (2)].integer) | mask) != -1ULL)) | ||
| 1819 | print_error( | ||
| 1820 | "integer value out of range " | ||
| 1821 | "%016lx (%d bits)", (yyvsp[(1) - (2)].array).bits); | ||
| 1822 | } | ||
| 1823 | |||
| 1824 | (yyval.array).data = data_append_integer((yyvsp[(1) - (2)].array).data, (yyvsp[(2) - (2)].integer), (yyvsp[(1) - (2)].array).bits); | ||
| 1633 | ;} | 1825 | ;} |
| 1634 | break; | 1826 | break; |
| 1635 | 1827 | ||
| 1636 | case 31: | 1828 | case 31: |
| 1637 | 1829 | ||
| 1830 | /* Line 1455 of yacc.c */ | ||
| 1831 | #line 316 "dtc-parser.y" | ||
| 1638 | { | 1832 | { |
| 1639 | (yyval.cell) = eval_literal((yyvsp[(1) - (1)].literal), 0, 32); | 1833 | uint64_t val = ~0ULL >> (64 - (yyvsp[(1) - (2)].array).bits); |
| 1834 | |||
| 1835 | if ((yyvsp[(1) - (2)].array).bits == 32) | ||
| 1836 | (yyvsp[(1) - (2)].array).data = data_add_marker((yyvsp[(1) - (2)].array).data, | ||
| 1837 | REF_PHANDLE, | ||
| 1838 | (yyvsp[(2) - (2)].labelref)); | ||
| 1839 | else | ||
| 1840 | print_error("References are only allowed in " | ||
| 1841 | "arrays with 32-bit elements."); | ||
| 1842 | |||
| 1843 | (yyval.array).data = data_append_integer((yyvsp[(1) - (2)].array).data, val, (yyvsp[(1) - (2)].array).bits); | ||
| 1640 | ;} | 1844 | ;} |
| 1641 | break; | 1845 | break; |
| 1642 | 1846 | ||
| 1643 | case 32: | 1847 | case 32: |
| 1644 | 1848 | ||
| 1849 | /* Line 1455 of yacc.c */ | ||
| 1850 | #line 330 "dtc-parser.y" | ||
| 1645 | { | 1851 | { |
| 1646 | (yyval.data) = empty_data; | 1852 | (yyval.array).data = data_add_marker((yyvsp[(1) - (2)].array).data, LABEL, (yyvsp[(2) - (2)].labelref)); |
| 1647 | ;} | 1853 | ;} |
| 1648 | break; | 1854 | break; |
| 1649 | 1855 | ||
| 1650 | case 33: | 1856 | case 33: |
| 1651 | 1857 | ||
| 1858 | /* Line 1455 of yacc.c */ | ||
| 1859 | #line 337 "dtc-parser.y" | ||
| 1652 | { | 1860 | { |
| 1653 | (yyval.data) = data_append_byte((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].byte)); | 1861 | (yyval.integer) = eval_literal((yyvsp[(1) - (1)].literal), 0, 64); |
| 1654 | ;} | 1862 | ;} |
| 1655 | break; | 1863 | break; |
| 1656 | 1864 | ||
| 1657 | case 34: | 1865 | case 34: |
| 1658 | 1866 | ||
| 1867 | /* Line 1455 of yacc.c */ | ||
| 1868 | #line 341 "dtc-parser.y" | ||
| 1659 | { | 1869 | { |
| 1660 | (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref)); | 1870 | (yyval.integer) = eval_char_literal((yyvsp[(1) - (1)].literal)); |
| 1661 | ;} | 1871 | ;} |
| 1662 | break; | 1872 | break; |
| 1663 | 1873 | ||
| 1664 | case 35: | 1874 | case 35: |
| 1665 | 1875 | ||
| 1876 | /* Line 1455 of yacc.c */ | ||
| 1877 | #line 345 "dtc-parser.y" | ||
| 1878 | { | ||
| 1879 | (yyval.integer) = (yyvsp[(2) - (3)].integer); | ||
| 1880 | ;} | ||
| 1881 | break; | ||
| 1882 | |||
| 1883 | case 38: | ||
| 1884 | |||
| 1885 | /* Line 1455 of yacc.c */ | ||
| 1886 | #line 356 "dtc-parser.y" | ||
| 1887 | { (yyval.integer) = (yyvsp[(1) - (5)].integer) ? (yyvsp[(3) - (5)].integer) : (yyvsp[(5) - (5)].integer); ;} | ||
| 1888 | break; | ||
| 1889 | |||
| 1890 | case 40: | ||
| 1891 | |||
| 1892 | /* Line 1455 of yacc.c */ | ||
| 1893 | #line 361 "dtc-parser.y" | ||
| 1894 | { (yyval.integer) = (yyvsp[(1) - (3)].integer) || (yyvsp[(3) - (3)].integer); ;} | ||
| 1895 | break; | ||
| 1896 | |||
| 1897 | case 42: | ||
| 1898 | |||
| 1899 | /* Line 1455 of yacc.c */ | ||
| 1900 | #line 366 "dtc-parser.y" | ||
| 1901 | { (yyval.integer) = (yyvsp[(1) - (3)].integer) && (yyvsp[(3) - (3)].integer); ;} | ||
| 1902 | break; | ||
| 1903 | |||
| 1904 | case 44: | ||
| 1905 | |||
| 1906 | /* Line 1455 of yacc.c */ | ||
| 1907 | #line 371 "dtc-parser.y" | ||
| 1908 | { (yyval.integer) = (yyvsp[(1) - (3)].integer) | (yyvsp[(3) - (3)].integer); ;} | ||
| 1909 | break; | ||
| 1910 | |||
| 1911 | case 46: | ||
| 1912 | |||
| 1913 | /* Line 1455 of yacc.c */ | ||
| 1914 | #line 376 "dtc-parser.y" | ||
| 1915 | { (yyval.integer) = (yyvsp[(1) - (3)].integer) ^ (yyvsp[(3) - (3)].integer); ;} | ||
| 1916 | break; | ||
| 1917 | |||
| 1918 | case 48: | ||
| 1919 | |||
| 1920 | /* Line 1455 of yacc.c */ | ||
| 1921 | #line 381 "dtc-parser.y" | ||
| 1922 | { (yyval.integer) = (yyvsp[(1) - (3)].integer) & (yyvsp[(3) - (3)].integer); ;} | ||
| 1923 | break; | ||
| 1924 | |||
| 1925 | case 50: | ||
| 1926 | |||
| 1927 | /* Line 1455 of yacc.c */ | ||
| 1928 | #line 386 "dtc-parser.y" | ||
| 1929 | { (yyval.integer) = (yyvsp[(1) - (3)].integer) == (yyvsp[(3) - (3)].integer); ;} | ||
| 1930 | break; | ||
| 1931 | |||
| 1932 | case 51: | ||
| 1933 | |||
| 1934 | /* Line 1455 of yacc.c */ | ||
| 1935 | #line 387 "dtc-parser.y" | ||
| 1936 | { (yyval.integer) = (yyvsp[(1) - (3)].integer) != (yyvsp[(3) - (3)].integer); ;} | ||
| 1937 | break; | ||
| 1938 | |||
| 1939 | case 53: | ||
| 1940 | |||
| 1941 | /* Line 1455 of yacc.c */ | ||
| 1942 | #line 392 "dtc-parser.y" | ||
| 1943 | { (yyval.integer) = (yyvsp[(1) - (3)].integer) < (yyvsp[(3) - (3)].integer); ;} | ||
| 1944 | break; | ||
| 1945 | |||
| 1946 | case 54: | ||
| 1947 | |||
| 1948 | /* Line 1455 of yacc.c */ | ||
| 1949 | #line 393 "dtc-parser.y" | ||
| 1950 | { (yyval.integer) = (yyvsp[(1) - (3)].integer) > (yyvsp[(3) - (3)].integer); ;} | ||
| 1951 | break; | ||
| 1952 | |||
| 1953 | case 55: | ||
| 1954 | |||
| 1955 | /* Line 1455 of yacc.c */ | ||
| 1956 | #line 394 "dtc-parser.y" | ||
| 1957 | { (yyval.integer) = (yyvsp[(1) - (3)].integer) <= (yyvsp[(3) - (3)].integer); ;} | ||
| 1958 | break; | ||
| 1959 | |||
| 1960 | case 56: | ||
| 1961 | |||
| 1962 | /* Line 1455 of yacc.c */ | ||
| 1963 | #line 395 "dtc-parser.y" | ||
| 1964 | { (yyval.integer) = (yyvsp[(1) - (3)].integer) >= (yyvsp[(3) - (3)].integer); ;} | ||
| 1965 | break; | ||
| 1966 | |||
| 1967 | case 57: | ||
| 1968 | |||
| 1969 | /* Line 1455 of yacc.c */ | ||
| 1970 | #line 399 "dtc-parser.y" | ||
| 1971 | { (yyval.integer) = (yyvsp[(1) - (3)].integer) << (yyvsp[(3) - (3)].integer); ;} | ||
| 1972 | break; | ||
| 1973 | |||
| 1974 | case 58: | ||
| 1975 | |||
| 1976 | /* Line 1455 of yacc.c */ | ||
| 1977 | #line 400 "dtc-parser.y" | ||
| 1978 | { (yyval.integer) = (yyvsp[(1) - (3)].integer) >> (yyvsp[(3) - (3)].integer); ;} | ||
| 1979 | break; | ||
| 1980 | |||
| 1981 | case 60: | ||
| 1982 | |||
| 1983 | /* Line 1455 of yacc.c */ | ||
| 1984 | #line 405 "dtc-parser.y" | ||
| 1985 | { (yyval.integer) = (yyvsp[(1) - (3)].integer) + (yyvsp[(3) - (3)].integer); ;} | ||
| 1986 | break; | ||
| 1987 | |||
| 1988 | case 61: | ||
| 1989 | |||
| 1990 | /* Line 1455 of yacc.c */ | ||
| 1991 | #line 406 "dtc-parser.y" | ||
| 1992 | { (yyval.integer) = (yyvsp[(1) - (3)].integer) - (yyvsp[(3) - (3)].integer); ;} | ||
| 1993 | break; | ||
| 1994 | |||
| 1995 | case 63: | ||
| 1996 | |||
| 1997 | /* Line 1455 of yacc.c */ | ||
| 1998 | #line 411 "dtc-parser.y" | ||
| 1999 | { (yyval.integer) = (yyvsp[(1) - (3)].integer) * (yyvsp[(3) - (3)].integer); ;} | ||
| 2000 | break; | ||
| 2001 | |||
| 2002 | case 64: | ||
| 2003 | |||
| 2004 | /* Line 1455 of yacc.c */ | ||
| 2005 | #line 412 "dtc-parser.y" | ||
| 2006 | { (yyval.integer) = (yyvsp[(1) - (3)].integer) / (yyvsp[(3) - (3)].integer); ;} | ||
| 2007 | break; | ||
| 2008 | |||
| 2009 | case 65: | ||
| 2010 | |||
| 2011 | /* Line 1455 of yacc.c */ | ||
| 2012 | #line 413 "dtc-parser.y" | ||
| 2013 | { (yyval.integer) = (yyvsp[(1) - (3)].integer) % (yyvsp[(3) - (3)].integer); ;} | ||
| 2014 | break; | ||
| 2015 | |||
| 2016 | case 68: | ||
| 2017 | |||
| 2018 | /* Line 1455 of yacc.c */ | ||
| 2019 | #line 419 "dtc-parser.y" | ||
| 2020 | { (yyval.integer) = -(yyvsp[(2) - (2)].integer); ;} | ||
| 2021 | break; | ||
| 2022 | |||
| 2023 | case 69: | ||
| 2024 | |||
| 2025 | /* Line 1455 of yacc.c */ | ||
| 2026 | #line 420 "dtc-parser.y" | ||
| 2027 | { (yyval.integer) = ~(yyvsp[(2) - (2)].integer); ;} | ||
| 2028 | break; | ||
| 2029 | |||
| 2030 | case 70: | ||
| 2031 | |||
| 2032 | /* Line 1455 of yacc.c */ | ||
| 2033 | #line 421 "dtc-parser.y" | ||
| 2034 | { (yyval.integer) = !(yyvsp[(2) - (2)].integer); ;} | ||
| 2035 | break; | ||
| 2036 | |||
| 2037 | case 71: | ||
| 2038 | |||
| 2039 | /* Line 1455 of yacc.c */ | ||
| 2040 | #line 426 "dtc-parser.y" | ||
| 2041 | { | ||
| 2042 | (yyval.data) = empty_data; | ||
| 2043 | ;} | ||
| 2044 | break; | ||
| 2045 | |||
| 2046 | case 72: | ||
| 2047 | |||
| 2048 | /* Line 1455 of yacc.c */ | ||
| 2049 | #line 430 "dtc-parser.y" | ||
| 2050 | { | ||
| 2051 | (yyval.data) = data_append_byte((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].byte)); | ||
| 2052 | ;} | ||
| 2053 | break; | ||
| 2054 | |||
| 2055 | case 73: | ||
| 2056 | |||
| 2057 | /* Line 1455 of yacc.c */ | ||
| 2058 | #line 434 "dtc-parser.y" | ||
| 2059 | { | ||
| 2060 | (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref)); | ||
| 2061 | ;} | ||
| 2062 | break; | ||
| 2063 | |||
| 2064 | case 74: | ||
| 2065 | |||
| 2066 | /* Line 1455 of yacc.c */ | ||
| 2067 | #line 441 "dtc-parser.y" | ||
| 1666 | { | 2068 | { |
| 1667 | (yyval.nodelist) = NULL; | 2069 | (yyval.nodelist) = NULL; |
| 1668 | ;} | 2070 | ;} |
| 1669 | break; | 2071 | break; |
| 1670 | 2072 | ||
| 1671 | case 36: | 2073 | case 75: |
| 1672 | 2074 | ||
| 2075 | /* Line 1455 of yacc.c */ | ||
| 2076 | #line 445 "dtc-parser.y" | ||
| 1673 | { | 2077 | { |
| 1674 | (yyval.nodelist) = chain_node((yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].nodelist)); | 2078 | (yyval.nodelist) = chain_node((yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].nodelist)); |
| 1675 | ;} | 2079 | ;} |
| 1676 | break; | 2080 | break; |
| 1677 | 2081 | ||
| 1678 | case 37: | 2082 | case 76: |
| 1679 | 2083 | ||
| 2084 | /* Line 1455 of yacc.c */ | ||
| 2085 | #line 449 "dtc-parser.y" | ||
| 1680 | { | 2086 | { |
| 1681 | print_error("syntax error: properties must precede subnodes"); | 2087 | print_error("syntax error: properties must precede subnodes"); |
| 1682 | YYERROR; | 2088 | YYERROR; |
| 1683 | ;} | 2089 | ;} |
| 1684 | break; | 2090 | break; |
| 1685 | 2091 | ||
| 1686 | case 38: | 2092 | case 77: |
| 1687 | 2093 | ||
| 2094 | /* Line 1455 of yacc.c */ | ||
| 2095 | #line 457 "dtc-parser.y" | ||
| 1688 | { | 2096 | { |
| 1689 | (yyval.node) = name_node((yyvsp[(2) - (2)].node), (yyvsp[(1) - (2)].propnodename)); | 2097 | (yyval.node) = name_node((yyvsp[(2) - (2)].node), (yyvsp[(1) - (2)].propnodename)); |
| 1690 | ;} | 2098 | ;} |
| 1691 | break; | 2099 | break; |
| 1692 | 2100 | ||
| 1693 | case 39: | 2101 | case 78: |
| 2102 | |||
| 2103 | /* Line 1455 of yacc.c */ | ||
| 2104 | #line 461 "dtc-parser.y" | ||
| 2105 | { | ||
| 2106 | (yyval.node) = name_node(build_node_delete(), (yyvsp[(2) - (3)].propnodename)); | ||
| 2107 | ;} | ||
| 2108 | break; | ||
| 2109 | |||
| 2110 | case 79: | ||
| 1694 | 2111 | ||
| 2112 | /* Line 1455 of yacc.c */ | ||
| 2113 | #line 465 "dtc-parser.y" | ||
| 1695 | { | 2114 | { |
| 1696 | add_label(&(yyvsp[(2) - (2)].node)->labels, (yyvsp[(1) - (2)].labelref)); | 2115 | add_label(&(yyvsp[(2) - (2)].node)->labels, (yyvsp[(1) - (2)].labelref)); |
| 1697 | (yyval.node) = (yyvsp[(2) - (2)].node); | 2116 | (yyval.node) = (yyvsp[(2) - (2)].node); |
| @@ -1700,6 +2119,8 @@ yyreduce: | |||
| 1700 | 2119 | ||
| 1701 | 2120 | ||
| 1702 | 2121 | ||
| 2122 | /* Line 1455 of yacc.c */ | ||
| 2123 | #line 2124 "dtc-parser.tab.c" | ||
| 1703 | default: break; | 2124 | default: break; |
| 1704 | } | 2125 | } |
| 1705 | YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); | 2126 | YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); |
| @@ -1910,6 +2331,8 @@ yyreturn: | |||
| 1910 | 2331 | ||
| 1911 | 2332 | ||
| 1912 | 2333 | ||
| 2334 | /* Line 1675 of yacc.c */ | ||
| 2335 | #line 471 "dtc-parser.y" | ||
| 1913 | 2336 | ||
| 1914 | 2337 | ||
| 1915 | void print_error(char const *fmt, ...) | 2338 | void print_error(char const *fmt, ...) |
| @@ -1934,9 +2357,12 @@ static unsigned long long eval_literal(const char *s, int base, int bits) | |||
| 1934 | 2357 | ||
| 1935 | errno = 0; | 2358 | errno = 0; |
| 1936 | val = strtoull(s, &e, base); | 2359 | val = strtoull(s, &e, base); |
| 1937 | if (*e) | 2360 | if (*e) { |
| 1938 | print_error("bad characters in literal"); | 2361 | size_t uls = strspn(e, "UL"); |
| 1939 | else if ((errno == ERANGE) | 2362 | if (e[uls]) |
| 2363 | print_error("bad characters in literal"); | ||
| 2364 | } | ||
| 2365 | if ((errno == ERANGE) | ||
| 1940 | || ((bits < 64) && (val >= (1ULL << bits)))) | 2366 | || ((bits < 64) && (val >= (1ULL << bits)))) |
| 1941 | print_error("literal out of range"); | 2367 | print_error("literal out of range"); |
| 1942 | else if (errno != 0) | 2368 | else if (errno != 0) |
| @@ -1944,3 +2370,29 @@ static unsigned long long eval_literal(const char *s, int base, int bits) | |||
| 1944 | return val; | 2370 | return val; |
| 1945 | } | 2371 | } |
| 1946 | 2372 | ||
| 2373 | static unsigned char eval_char_literal(const char *s) | ||
| 2374 | { | ||
| 2375 | int i = 1; | ||
| 2376 | char c = s[0]; | ||
| 2377 | |||
| 2378 | if (c == '\0') | ||
| 2379 | { | ||
| 2380 | print_error("empty character literal"); | ||
| 2381 | return 0; | ||
| 2382 | } | ||
| 2383 | |||
| 2384 | /* | ||
| 2385 | * If the first character in the character literal is a \ then process | ||
| 2386 | * the remaining characters as an escape encoding. If the first | ||
| 2387 | * character is neither an escape or a terminator it should be the only | ||
| 2388 | * character in the literal and will be returned. | ||
| 2389 | */ | ||
| 2390 | if (c == '\\') | ||
| 2391 | c = get_escape_char(s, &i); | ||
| 2392 | |||
| 2393 | if (s[i] != '\0') | ||
| 2394 | print_error("malformed character literal"); | ||
| 2395 | |||
| 2396 | return c; | ||
| 2397 | } | ||
| 2398 | |||
diff --git a/scripts/dtc/dtc-parser.tab.h_shipped b/scripts/dtc/dtc-parser.tab.h_shipped index 4ee682bb7d33..9d2dce41211f 100644 --- a/scripts/dtc/dtc-parser.tab.h_shipped +++ b/scripts/dtc/dtc-parser.tab.h_shipped | |||
| @@ -1,9 +1,10 @@ | |||
| 1 | /* A Bison parser, made by GNU Bison 2.4.3. */ | 1 | |
| 2 | /* A Bison parser, made by GNU Bison 2.4.1. */ | ||
| 2 | 3 | ||
| 3 | /* Skeleton interface for Bison's Yacc-like parsers in C | 4 | /* Skeleton interface for Bison's Yacc-like parsers in C |
| 4 | 5 | ||
| 5 | Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006, | 6 | Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 |
| 6 | 2009, 2010 Free Software Foundation, Inc. | 7 | Free Software Foundation, Inc. |
| 7 | 8 | ||
| 8 | This program is free software: you can redistribute it and/or modify | 9 | This program is free software: you can redistribute it and/or modify |
| 9 | it under the terms of the GNU General Public License as published by | 10 | it under the terms of the GNU General Public License as published by |
| @@ -40,14 +41,26 @@ | |||
| 40 | enum yytokentype { | 41 | enum yytokentype { |
| 41 | DT_V1 = 258, | 42 | DT_V1 = 258, |
| 42 | DT_MEMRESERVE = 259, | 43 | DT_MEMRESERVE = 259, |
| 43 | DT_PROPNODENAME = 260, | 44 | DT_LSHIFT = 260, |
| 44 | DT_LITERAL = 261, | 45 | DT_RSHIFT = 261, |
| 45 | DT_BASE = 262, | 46 | DT_LE = 262, |
| 46 | DT_BYTE = 263, | 47 | DT_GE = 263, |
| 47 | DT_STRING = 264, | 48 | DT_EQ = 264, |
| 48 | DT_LABEL = 265, | 49 | DT_NE = 265, |
| 49 | DT_REF = 266, | 50 | DT_AND = 266, |
| 50 | DT_INCBIN = 267 | 51 | DT_OR = 267, |
| 52 | DT_BITS = 268, | ||
| 53 | DT_DEL_PROP = 269, | ||
| 54 | DT_DEL_NODE = 270, | ||
| 55 | DT_PROPNODENAME = 271, | ||
| 56 | DT_LITERAL = 272, | ||
| 57 | DT_CHAR_LITERAL = 273, | ||
| 58 | DT_BASE = 274, | ||
| 59 | DT_BYTE = 275, | ||
| 60 | DT_STRING = 276, | ||
| 61 | DT_LABEL = 277, | ||
| 62 | DT_REF = 278, | ||
| 63 | DT_INCBIN = 279 | ||
| 51 | }; | 64 | }; |
| 52 | #endif | 65 | #endif |
| 53 | 66 | ||
| @@ -57,6 +70,8 @@ | |||
| 57 | typedef union YYSTYPE | 70 | typedef union YYSTYPE |
| 58 | { | 71 | { |
| 59 | 72 | ||
| 73 | /* Line 1676 of yacc.c */ | ||
| 74 | #line 40 "dtc-parser.y" | ||
| 60 | 75 | ||
| 61 | char *propnodename; | 76 | char *propnodename; |
| 62 | char *literal; | 77 | char *literal; |
| @@ -65,16 +80,22 @@ typedef union YYSTYPE | |||
| 65 | uint8_t byte; | 80 | uint8_t byte; |
| 66 | struct data data; | 81 | struct data data; |
| 67 | 82 | ||
| 68 | uint64_t addr; | 83 | struct { |
| 69 | cell_t cell; | 84 | struct data data; |
| 85 | int bits; | ||
| 86 | } array; | ||
| 87 | |||
| 70 | struct property *prop; | 88 | struct property *prop; |
| 71 | struct property *proplist; | 89 | struct property *proplist; |
| 72 | struct node *node; | 90 | struct node *node; |
| 73 | struct node *nodelist; | 91 | struct node *nodelist; |
| 74 | struct reserve_info *re; | 92 | struct reserve_info *re; |
| 93 | uint64_t integer; | ||
| 75 | 94 | ||
| 76 | 95 | ||
| 77 | 96 | ||
| 97 | /* Line 1676 of yacc.c */ | ||
| 98 | #line 99 "dtc-parser.tab.h" | ||
| 78 | } YYSTYPE; | 99 | } YYSTYPE; |
| 79 | # define YYSTYPE_IS_TRIVIAL 1 | 100 | # define YYSTYPE_IS_TRIVIAL 1 |
| 80 | # define yystype YYSTYPE /* obsolescent; will be withdrawn */ | 101 | # define yystype YYSTYPE /* obsolescent; will be withdrawn */ |
diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y index 5e84a67fc1d2..f412460f94d7 100644 --- a/scripts/dtc/dtc-parser.y +++ b/scripts/dtc/dtc-parser.y | |||
| @@ -34,6 +34,7 @@ extern struct boot_info *the_boot_info; | |||
| 34 | extern int treesource_error; | 34 | extern int treesource_error; |
| 35 | 35 | ||
| 36 | static unsigned long long eval_literal(const char *s, int base, int bits); | 36 | static unsigned long long eval_literal(const char *s, int base, int bits); |
| 37 | static unsigned char eval_char_literal(const char *s); | ||
| 37 | %} | 38 | %} |
| 38 | 39 | ||
| 39 | %union { | 40 | %union { |
| @@ -44,19 +45,28 @@ static unsigned long long eval_literal(const char *s, int base, int bits); | |||
| 44 | uint8_t byte; | 45 | uint8_t byte; |
| 45 | struct data data; | 46 | struct data data; |
| 46 | 47 | ||
| 47 | uint64_t addr; | 48 | struct { |
| 48 | cell_t cell; | 49 | struct data data; |
| 50 | int bits; | ||
| 51 | } array; | ||
| 52 | |||
| 49 | struct property *prop; | 53 | struct property *prop; |
| 50 | struct property *proplist; | 54 | struct property *proplist; |
| 51 | struct node *node; | 55 | struct node *node; |
| 52 | struct node *nodelist; | 56 | struct node *nodelist; |
| 53 | struct reserve_info *re; | 57 | struct reserve_info *re; |
| 58 | uint64_t integer; | ||
| 54 | } | 59 | } |
| 55 | 60 | ||
| 56 | %token DT_V1 | 61 | %token DT_V1 |
| 57 | %token DT_MEMRESERVE | 62 | %token DT_MEMRESERVE |
| 63 | %token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR | ||
| 64 | %token DT_BITS | ||
| 65 | %token DT_DEL_PROP | ||
| 66 | %token DT_DEL_NODE | ||
| 58 | %token <propnodename> DT_PROPNODENAME | 67 | %token <propnodename> DT_PROPNODENAME |
| 59 | %token <literal> DT_LITERAL | 68 | %token <literal> DT_LITERAL |
| 69 | %token <literal> DT_CHAR_LITERAL | ||
| 60 | %token <cbase> DT_BASE | 70 | %token <cbase> DT_BASE |
| 61 | %token <byte> DT_BYTE | 71 | %token <byte> DT_BYTE |
| 62 | %token <data> DT_STRING | 72 | %token <data> DT_STRING |
| @@ -68,9 +78,7 @@ static unsigned long long eval_literal(const char *s, int base, int bits); | |||
| 68 | %type <data> propdataprefix | 78 | %type <data> propdataprefix |
| 69 | %type <re> memreserve | 79 | %type <re> memreserve |
| 70 | %type <re> memreserves | 80 | %type <re> memreserves |
| 71 | %type <addr> addr | 81 | %type <array> arrayprefix |
| 72 | %type <data> celllist | ||
| 73 | %type <cell> cellval | ||
| 74 | %type <data> bytestring | 82 | %type <data> bytestring |
| 75 | %type <prop> propdef | 83 | %type <prop> propdef |
| 76 | %type <proplist> proplist | 84 | %type <proplist> proplist |
| @@ -80,6 +88,21 @@ static unsigned long long eval_literal(const char *s, int base, int bits); | |||
| 80 | %type <node> subnode | 88 | %type <node> subnode |
| 81 | %type <nodelist> subnodes | 89 | %type <nodelist> subnodes |
| 82 | 90 | ||
| 91 | %type <integer> integer_prim | ||
| 92 | %type <integer> integer_unary | ||
| 93 | %type <integer> integer_mul | ||
| 94 | %type <integer> integer_add | ||
| 95 | %type <integer> integer_shift | ||
| 96 | %type <integer> integer_rela | ||
| 97 | %type <integer> integer_eq | ||
| 98 | %type <integer> integer_bitand | ||
| 99 | %type <integer> integer_bitxor | ||
| 100 | %type <integer> integer_bitor | ||
| 101 | %type <integer> integer_and | ||
| 102 | %type <integer> integer_or | ||
| 103 | %type <integer> integer_trinary | ||
| 104 | %type <integer> integer_expr | ||
| 105 | |||
| 83 | %% | 106 | %% |
| 84 | 107 | ||
| 85 | sourcefile: | 108 | sourcefile: |
| @@ -102,7 +125,7 @@ memreserves: | |||
| 102 | ; | 125 | ; |
| 103 | 126 | ||
| 104 | memreserve: | 127 | memreserve: |
| 105 | DT_MEMRESERVE addr addr ';' | 128 | DT_MEMRESERVE integer_prim integer_prim ';' |
| 106 | { | 129 | { |
| 107 | $$ = build_reserve_entry($2, $3); | 130 | $$ = build_reserve_entry($2, $3); |
| 108 | } | 131 | } |
| @@ -113,13 +136,6 @@ memreserve: | |||
| 113 | } | 136 | } |
| 114 | ; | 137 | ; |
| 115 | 138 | ||
| 116 | addr: | ||
| 117 | DT_LITERAL | ||
| 118 | { | ||
| 119 | $$ = eval_literal($1, 0, 64); | ||
| 120 | } | ||
| 121 | ; | ||
| 122 | |||
| 123 | devicetree: | 139 | devicetree: |
| 124 | '/' nodedef | 140 | '/' nodedef |
| 125 | { | 141 | { |
| @@ -139,6 +155,17 @@ devicetree: | |||
| 139 | print_error("label or path, '%s', not found", $2); | 155 | print_error("label or path, '%s', not found", $2); |
| 140 | $$ = $1; | 156 | $$ = $1; |
| 141 | } | 157 | } |
| 158 | | devicetree DT_DEL_NODE DT_REF ';' | ||
| 159 | { | ||
| 160 | struct node *target = get_node_by_ref($1, $3); | ||
| 161 | |||
| 162 | if (!target) | ||
| 163 | print_error("label or path, '%s', not found", $3); | ||
| 164 | else | ||
| 165 | delete_node(target); | ||
| 166 | |||
| 167 | $$ = $1; | ||
| 168 | } | ||
| 142 | ; | 169 | ; |
| 143 | 170 | ||
| 144 | nodedef: | 171 | nodedef: |
| @@ -168,6 +195,10 @@ propdef: | |||
| 168 | { | 195 | { |
| 169 | $$ = build_property($1, empty_data); | 196 | $$ = build_property($1, empty_data); |
| 170 | } | 197 | } |
| 198 | | DT_DEL_PROP DT_PROPNODENAME ';' | ||
| 199 | { | ||
| 200 | $$ = build_property_delete($2); | ||
| 201 | } | ||
| 171 | | DT_LABEL propdef | 202 | | DT_LABEL propdef |
| 172 | { | 203 | { |
| 173 | add_label(&$2->labels, $1); | 204 | add_label(&$2->labels, $1); |
| @@ -180,9 +211,9 @@ propdata: | |||
| 180 | { | 211 | { |
| 181 | $$ = data_merge($1, $2); | 212 | $$ = data_merge($1, $2); |
| 182 | } | 213 | } |
| 183 | | propdataprefix '<' celllist '>' | 214 | | propdataprefix arrayprefix '>' |
| 184 | { | 215 | { |
| 185 | $$ = data_merge($1, $3); | 216 | $$ = data_merge($1, $2.data); |
| 186 | } | 217 | } |
| 187 | | propdataprefix '[' bytestring ']' | 218 | | propdataprefix '[' bytestring ']' |
| 188 | { | 219 | { |
| @@ -192,7 +223,7 @@ propdata: | |||
| 192 | { | 223 | { |
| 193 | $$ = data_add_marker($1, REF_PATH, $2); | 224 | $$ = data_add_marker($1, REF_PATH, $2); |
| 194 | } | 225 | } |
| 195 | | propdataprefix DT_INCBIN '(' DT_STRING ',' addr ',' addr ')' | 226 | | propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')' |
| 196 | { | 227 | { |
| 197 | FILE *f = srcfile_relative_open($4.val, NULL); | 228 | FILE *f = srcfile_relative_open($4.val, NULL); |
| 198 | struct data d; | 229 | struct data d; |
| @@ -240,31 +271,154 @@ propdataprefix: | |||
| 240 | } | 271 | } |
| 241 | ; | 272 | ; |
| 242 | 273 | ||
| 243 | celllist: | 274 | arrayprefix: |
| 244 | /* empty */ | 275 | DT_BITS DT_LITERAL '<' |
| 276 | { | ||
| 277 | $$.data = empty_data; | ||
| 278 | $$.bits = eval_literal($2, 0, 7); | ||
| 279 | |||
| 280 | if (($$.bits != 8) && | ||
| 281 | ($$.bits != 16) && | ||
| 282 | ($$.bits != 32) && | ||
| 283 | ($$.bits != 64)) | ||
| 284 | { | ||
| 285 | print_error("Only 8, 16, 32 and 64-bit elements" | ||
| 286 | " are currently supported"); | ||
| 287 | $$.bits = 32; | ||
| 288 | } | ||
| 289 | } | ||
| 290 | | '<' | ||
| 291 | { | ||
| 292 | $$.data = empty_data; | ||
| 293 | $$.bits = 32; | ||
| 294 | } | ||
| 295 | | arrayprefix integer_prim | ||
| 296 | { | ||
| 297 | if ($1.bits < 64) { | ||
| 298 | uint64_t mask = (1ULL << $1.bits) - 1; | ||
| 299 | /* | ||
| 300 | * Bits above mask must either be all zero | ||
| 301 | * (positive within range of mask) or all one | ||
| 302 | * (negative and sign-extended). The second | ||
| 303 | * condition is true if when we set all bits | ||
| 304 | * within the mask to one (i.e. | in the | ||
| 305 | * mask), all bits are one. | ||
| 306 | */ | ||
| 307 | if (($2 > mask) && (($2 | mask) != -1ULL)) | ||
| 308 | print_error( | ||
| 309 | "integer value out of range " | ||
| 310 | "%016lx (%d bits)", $1.bits); | ||
| 311 | } | ||
| 312 | |||
| 313 | $$.data = data_append_integer($1.data, $2, $1.bits); | ||
| 314 | } | ||
| 315 | | arrayprefix DT_REF | ||
| 316 | { | ||
| 317 | uint64_t val = ~0ULL >> (64 - $1.bits); | ||
| 318 | |||
| 319 | if ($1.bits == 32) | ||
| 320 | $1.data = data_add_marker($1.data, | ||
| 321 | REF_PHANDLE, | ||
| 322 | $2); | ||
| 323 | else | ||
| 324 | print_error("References are only allowed in " | ||
| 325 | "arrays with 32-bit elements."); | ||
| 326 | |||
| 327 | $$.data = data_append_integer($1.data, val, $1.bits); | ||
| 328 | } | ||
| 329 | | arrayprefix DT_LABEL | ||
| 245 | { | 330 | { |
| 246 | $$ = empty_data; | 331 | $$.data = data_add_marker($1.data, LABEL, $2); |
| 247 | } | 332 | } |
| 248 | | celllist cellval | 333 | ; |
| 334 | |||
| 335 | integer_prim: | ||
| 336 | DT_LITERAL | ||
| 249 | { | 337 | { |
| 250 | $$ = data_append_cell($1, $2); | 338 | $$ = eval_literal($1, 0, 64); |
| 251 | } | 339 | } |
| 252 | | celllist DT_REF | 340 | | DT_CHAR_LITERAL |
| 253 | { | 341 | { |
| 254 | $$ = data_append_cell(data_add_marker($1, REF_PHANDLE, | 342 | $$ = eval_char_literal($1); |
| 255 | $2), -1); | ||
| 256 | } | 343 | } |
| 257 | | celllist DT_LABEL | 344 | | '(' integer_expr ')' |
| 258 | { | 345 | { |
| 259 | $$ = data_add_marker($1, LABEL, $2); | 346 | $$ = $2; |
| 260 | } | 347 | } |
| 261 | ; | 348 | ; |
| 262 | 349 | ||
| 263 | cellval: | 350 | integer_expr: |
| 264 | DT_LITERAL | 351 | integer_trinary |
| 265 | { | 352 | ; |
| 266 | $$ = eval_literal($1, 0, 32); | 353 | |
| 267 | } | 354 | integer_trinary: |
| 355 | integer_or | ||
| 356 | | integer_or '?' integer_expr ':' integer_trinary { $$ = $1 ? $3 : $5; } | ||
| 357 | ; | ||
| 358 | |||
| 359 | integer_or: | ||
| 360 | integer_and | ||
| 361 | | integer_or DT_OR integer_and { $$ = $1 || $3; } | ||
| 362 | ; | ||
| 363 | |||
| 364 | integer_and: | ||
| 365 | integer_bitor | ||
| 366 | | integer_and DT_AND integer_bitor { $$ = $1 && $3; } | ||
| 367 | ; | ||
| 368 | |||
| 369 | integer_bitor: | ||
| 370 | integer_bitxor | ||
| 371 | | integer_bitor '|' integer_bitxor { $$ = $1 | $3; } | ||
| 372 | ; | ||
| 373 | |||
| 374 | integer_bitxor: | ||
| 375 | integer_bitand | ||
| 376 | | integer_bitxor '^' integer_bitand { $$ = $1 ^ $3; } | ||
| 377 | ; | ||
| 378 | |||
| 379 | integer_bitand: | ||
| 380 | integer_eq | ||
| 381 | | integer_bitand '&' integer_eq { $$ = $1 & $3; } | ||
| 382 | ; | ||
| 383 | |||
| 384 | integer_eq: | ||
| 385 | integer_rela | ||
| 386 | | integer_eq DT_EQ integer_rela { $$ = $1 == $3; } | ||
| 387 | | integer_eq DT_NE integer_rela { $$ = $1 != $3; } | ||
| 388 | ; | ||
| 389 | |||
| 390 | integer_rela: | ||
| 391 | integer_shift | ||
| 392 | | integer_rela '<' integer_shift { $$ = $1 < $3; } | ||
| 393 | | integer_rela '>' integer_shift { $$ = $1 > $3; } | ||
| 394 | | integer_rela DT_LE integer_shift { $$ = $1 <= $3; } | ||
| 395 | | integer_rela DT_GE integer_shift { $$ = $1 >= $3; } | ||
| 396 | ; | ||
| 397 | |||
| 398 | integer_shift: | ||
| 399 | integer_shift DT_LSHIFT integer_add { $$ = $1 << $3; } | ||
| 400 | | integer_shift DT_RSHIFT integer_add { $$ = $1 >> $3; } | ||
| 401 | | integer_add | ||
| 402 | ; | ||
| 403 | |||
| 404 | integer_add: | ||
| 405 | integer_add '+' integer_mul { $$ = $1 + $3; } | ||
| 406 | | integer_add '-' integer_mul { $$ = $1 - $3; } | ||
| 407 | | integer_mul | ||
| 408 | ; | ||
| 409 | |||
| 410 | integer_mul: | ||
| 411 | integer_mul '*' integer_unary { $$ = $1 * $3; } | ||
| 412 | | integer_mul '/' integer_unary { $$ = $1 / $3; } | ||
| 413 | | integer_mul '%' integer_unary { $$ = $1 % $3; } | ||
| 414 | | integer_unary | ||
| 415 | ; | ||
| 416 | |||
| 417 | integer_unary: | ||
| 418 | integer_prim | ||
| 419 | | '-' integer_unary { $$ = -$2; } | ||
| 420 | | '~' integer_unary { $$ = ~$2; } | ||
| 421 | | '!' integer_unary { $$ = !$2; } | ||
| 268 | ; | 422 | ; |
| 269 | 423 | ||
| 270 | bytestring: | 424 | bytestring: |
| @@ -303,6 +457,10 @@ subnode: | |||
| 303 | { | 457 | { |
| 304 | $$ = name_node($2, $1); | 458 | $$ = name_node($2, $1); |
| 305 | } | 459 | } |
| 460 | | DT_DEL_NODE DT_PROPNODENAME ';' | ||
| 461 | { | ||
| 462 | $$ = name_node(build_node_delete(), $2); | ||
| 463 | } | ||
| 306 | | DT_LABEL subnode | 464 | | DT_LABEL subnode |
| 307 | { | 465 | { |
| 308 | add_label(&$2->labels, $1); | 466 | add_label(&$2->labels, $1); |
| @@ -334,12 +492,41 @@ static unsigned long long eval_literal(const char *s, int base, int bits) | |||
| 334 | 492 | ||
| 335 | errno = 0; | 493 | errno = 0; |
| 336 | val = strtoull(s, &e, base); | 494 | val = strtoull(s, &e, base); |
| 337 | if (*e) | 495 | if (*e) { |
| 338 | print_error("bad characters in literal"); | 496 | size_t uls = strspn(e, "UL"); |
| 339 | else if ((errno == ERANGE) | 497 | if (e[uls]) |
| 498 | print_error("bad characters in literal"); | ||
| 499 | } | ||
| 500 | if ((errno == ERANGE) | ||
| 340 | || ((bits < 64) && (val >= (1ULL << bits)))) | 501 | || ((bits < 64) && (val >= (1ULL << bits)))) |
| 341 | print_error("literal out of range"); | 502 | print_error("literal out of range"); |
| 342 | else if (errno != 0) | 503 | else if (errno != 0) |
| 343 | print_error("bad literal"); | 504 | print_error("bad literal"); |
| 344 | return val; | 505 | return val; |
| 345 | } | 506 | } |
| 507 | |||
| 508 | static unsigned char eval_char_literal(const char *s) | ||
| 509 | { | ||
| 510 | int i = 1; | ||
| 511 | char c = s[0]; | ||
| 512 | |||
| 513 | if (c == '\0') | ||
| 514 | { | ||
| 515 | print_error("empty character literal"); | ||
| 516 | return 0; | ||
| 517 | } | ||
| 518 | |||
| 519 | /* | ||
| 520 | * If the first character in the character literal is a \ then process | ||
| 521 | * the remaining characters as an escape encoding. If the first | ||
| 522 | * character is neither an escape or a terminator it should be the only | ||
| 523 | * character in the literal and will be returned. | ||
| 524 | */ | ||
| 525 | if (c == '\\') | ||
| 526 | c = get_escape_char(s, &i); | ||
| 527 | |||
| 528 | if (s[i] != '\0') | ||
| 529 | print_error("malformed character literal"); | ||
| 530 | |||
| 531 | return c; | ||
| 532 | } | ||
diff --git a/scripts/dtc/dtc.c b/scripts/dtc/dtc.c index 2ef5e2e3dd38..a375683c1534 100644 --- a/scripts/dtc/dtc.c +++ b/scripts/dtc/dtc.c | |||
| @@ -82,6 +82,8 @@ static void __attribute__ ((noreturn)) usage(void) | |||
| 82 | fprintf(stderr, "\t\tSet the physical boot cpu\n"); | 82 | fprintf(stderr, "\t\tSet the physical boot cpu\n"); |
| 83 | fprintf(stderr, "\t-f\n"); | 83 | fprintf(stderr, "\t-f\n"); |
| 84 | fprintf(stderr, "\t\tForce - try to produce output even if the input tree has errors\n"); | 84 | fprintf(stderr, "\t\tForce - try to produce output even if the input tree has errors\n"); |
| 85 | fprintf(stderr, "\t-i\n"); | ||
| 86 | fprintf(stderr, "\t\tAdd a path to search for include files\n"); | ||
| 85 | fprintf(stderr, "\t-s\n"); | 87 | fprintf(stderr, "\t-s\n"); |
| 86 | fprintf(stderr, "\t\tSort nodes and properties before outputting (only useful for\n\t\tcomparing trees)\n"); | 88 | fprintf(stderr, "\t\tSort nodes and properties before outputting (only useful for\n\t\tcomparing trees)\n"); |
| 87 | fprintf(stderr, "\t-v\n"); | 89 | fprintf(stderr, "\t-v\n"); |
| @@ -91,6 +93,9 @@ static void __attribute__ ((noreturn)) usage(void) | |||
| 91 | fprintf(stderr, "\t\t\tlegacy - \"linux,phandle\" properties only\n"); | 93 | fprintf(stderr, "\t\t\tlegacy - \"linux,phandle\" properties only\n"); |
| 92 | fprintf(stderr, "\t\t\tepapr - \"phandle\" properties only\n"); | 94 | fprintf(stderr, "\t\t\tepapr - \"phandle\" properties only\n"); |
| 93 | fprintf(stderr, "\t\t\tboth - Both \"linux,phandle\" and \"phandle\" properties\n"); | 95 | fprintf(stderr, "\t\t\tboth - Both \"linux,phandle\" and \"phandle\" properties\n"); |
| 96 | fprintf(stderr, "\t-W [no-]<checkname>\n"); | ||
| 97 | fprintf(stderr, "\t-E [no-]<checkname>\n"); | ||
| 98 | fprintf(stderr, "\t\t\tenable or disable warnings and errors\n"); | ||
| 94 | exit(3); | 99 | exit(3); |
| 95 | } | 100 | } |
| 96 | 101 | ||
| @@ -113,7 +118,7 @@ int main(int argc, char *argv[]) | |||
| 113 | minsize = 0; | 118 | minsize = 0; |
| 114 | padsize = 0; | 119 | padsize = 0; |
| 115 | 120 | ||
| 116 | while ((opt = getopt(argc, argv, "hI:O:o:V:d:R:S:p:fcqb:vH:s")) | 121 | while ((opt = getopt(argc, argv, "hI:O:o:V:d:R:S:p:fqb:i:vH:sW:E:")) |
| 117 | != EOF) { | 122 | != EOF) { |
| 118 | switch (opt) { | 123 | switch (opt) { |
| 119 | case 'I': | 124 | case 'I': |
| @@ -149,6 +154,9 @@ int main(int argc, char *argv[]) | |||
| 149 | case 'b': | 154 | case 'b': |
| 150 | cmdline_boot_cpuid = strtoll(optarg, NULL, 0); | 155 | cmdline_boot_cpuid = strtoll(optarg, NULL, 0); |
| 151 | break; | 156 | break; |
| 157 | case 'i': | ||
| 158 | srcfile_add_search_path(optarg); | ||
| 159 | break; | ||
| 152 | case 'v': | 160 | case 'v': |
| 153 | printf("Version: %s\n", DTC_VERSION); | 161 | printf("Version: %s\n", DTC_VERSION); |
| 154 | exit(0); | 162 | exit(0); |
| @@ -168,6 +176,14 @@ int main(int argc, char *argv[]) | |||
| 168 | sort = 1; | 176 | sort = 1; |
| 169 | break; | 177 | break; |
| 170 | 178 | ||
| 179 | case 'W': | ||
| 180 | parse_checks_option(true, false, optarg); | ||
| 181 | break; | ||
| 182 | |||
| 183 | case 'E': | ||
| 184 | parse_checks_option(false, true, optarg); | ||
| 185 | break; | ||
| 186 | |||
| 171 | case 'h': | 187 | case 'h': |
| 172 | default: | 188 | default: |
| 173 | usage(); | 189 | usage(); |
| @@ -188,9 +204,6 @@ int main(int argc, char *argv[]) | |||
| 188 | if (minsize) | 204 | if (minsize) |
| 189 | fprintf(stderr, "DTC: Use of \"-S\" is deprecated; it will be removed soon, use \"-p\" instead\n"); | 205 | fprintf(stderr, "DTC: Use of \"-S\" is deprecated; it will be removed soon, use \"-p\" instead\n"); |
| 190 | 206 | ||
| 191 | fprintf(stderr, "DTC: %s->%s on file \"%s\"\n", | ||
| 192 | inform, outform, arg); | ||
| 193 | |||
| 194 | if (depname) { | 207 | if (depname) { |
| 195 | depfile = fopen(depname, "w"); | 208 | depfile = fopen(depname, "w"); |
| 196 | if (!depfile) | 209 | if (!depfile) |
diff --git a/scripts/dtc/dtc.h b/scripts/dtc/dtc.h index f37c97eb3dfc..3e42a071070e 100644 --- a/scripts/dtc/dtc.h +++ b/scripts/dtc/dtc.h | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #include <string.h> | 25 | #include <string.h> |
| 26 | #include <stdlib.h> | 26 | #include <stdlib.h> |
| 27 | #include <stdint.h> | 27 | #include <stdint.h> |
| 28 | #include <stdbool.h> | ||
| 28 | #include <stdarg.h> | 29 | #include <stdarg.h> |
| 29 | #include <assert.h> | 30 | #include <assert.h> |
| 30 | #include <ctype.h> | 31 | #include <ctype.h> |
| @@ -109,6 +110,7 @@ struct data data_insert_at_marker(struct data d, struct marker *m, | |||
| 109 | const void *p, int len); | 110 | const void *p, int len); |
| 110 | struct data data_merge(struct data d1, struct data d2); | 111 | struct data data_merge(struct data d1, struct data d2); |
| 111 | struct data data_append_cell(struct data d, cell_t word); | 112 | struct data data_append_cell(struct data d, cell_t word); |
| 113 | struct data data_append_integer(struct data d, uint64_t word, int bits); | ||
| 112 | struct data data_append_re(struct data d, const struct fdt_reserve_entry *re); | 114 | struct data data_append_re(struct data d, const struct fdt_reserve_entry *re); |
| 113 | struct data data_append_addr(struct data d, uint64_t addr); | 115 | struct data data_append_addr(struct data d, uint64_t addr); |
| 114 | struct data data_append_byte(struct data d, uint8_t byte); | 116 | struct data data_append_byte(struct data d, uint8_t byte); |
| @@ -126,11 +128,13 @@ int data_is_one_string(struct data d); | |||
| 126 | 128 | ||
| 127 | /* Live trees */ | 129 | /* Live trees */ |
| 128 | struct label { | 130 | struct label { |
| 131 | int deleted; | ||
| 129 | char *label; | 132 | char *label; |
| 130 | struct label *next; | 133 | struct label *next; |
| 131 | }; | 134 | }; |
| 132 | 135 | ||
| 133 | struct property { | 136 | struct property { |
| 137 | int deleted; | ||
| 134 | char *name; | 138 | char *name; |
| 135 | struct data val; | 139 | struct data val; |
| 136 | 140 | ||
| @@ -140,6 +144,7 @@ struct property { | |||
| 140 | }; | 144 | }; |
| 141 | 145 | ||
| 142 | struct node { | 146 | struct node { |
| 147 | int deleted; | ||
| 143 | char *name; | 148 | char *name; |
| 144 | struct property *proplist; | 149 | struct property *proplist; |
| 145 | struct node *children; | 150 | struct node *children; |
| @@ -156,28 +161,47 @@ struct node { | |||
| 156 | struct label *labels; | 161 | struct label *labels; |
| 157 | }; | 162 | }; |
| 158 | 163 | ||
| 159 | #define for_each_label(l0, l) \ | 164 | #define for_each_label_withdel(l0, l) \ |
| 160 | for ((l) = (l0); (l); (l) = (l)->next) | 165 | for ((l) = (l0); (l); (l) = (l)->next) |
| 161 | 166 | ||
| 162 | #define for_each_property(n, p) \ | 167 | #define for_each_label(l0, l) \ |
| 168 | for_each_label_withdel(l0, l) \ | ||
| 169 | if (!(l)->deleted) | ||
| 170 | |||
| 171 | #define for_each_property_withdel(n, p) \ | ||
| 163 | for ((p) = (n)->proplist; (p); (p) = (p)->next) | 172 | for ((p) = (n)->proplist; (p); (p) = (p)->next) |
| 164 | 173 | ||
| 165 | #define for_each_child(n, c) \ | 174 | #define for_each_property(n, p) \ |
| 175 | for_each_property_withdel(n, p) \ | ||
| 176 | if (!(p)->deleted) | ||
| 177 | |||
| 178 | #define for_each_child_withdel(n, c) \ | ||
| 166 | for ((c) = (n)->children; (c); (c) = (c)->next_sibling) | 179 | for ((c) = (n)->children; (c); (c) = (c)->next_sibling) |
| 167 | 180 | ||
| 181 | #define for_each_child(n, c) \ | ||
| 182 | for_each_child_withdel(n, c) \ | ||
| 183 | if (!(c)->deleted) | ||
| 184 | |||
| 168 | void add_label(struct label **labels, char *label); | 185 | void add_label(struct label **labels, char *label); |
| 186 | void delete_labels(struct label **labels); | ||
| 169 | 187 | ||
| 170 | struct property *build_property(char *name, struct data val); | 188 | struct property *build_property(char *name, struct data val); |
| 189 | struct property *build_property_delete(char *name); | ||
| 171 | struct property *chain_property(struct property *first, struct property *list); | 190 | struct property *chain_property(struct property *first, struct property *list); |
| 172 | struct property *reverse_properties(struct property *first); | 191 | struct property *reverse_properties(struct property *first); |
| 173 | 192 | ||
| 174 | struct node *build_node(struct property *proplist, struct node *children); | 193 | struct node *build_node(struct property *proplist, struct node *children); |
| 194 | struct node *build_node_delete(void); | ||
| 175 | struct node *name_node(struct node *node, char *name); | 195 | struct node *name_node(struct node *node, char *name); |
| 176 | struct node *chain_node(struct node *first, struct node *list); | 196 | struct node *chain_node(struct node *first, struct node *list); |
| 177 | struct node *merge_nodes(struct node *old_node, struct node *new_node); | 197 | struct node *merge_nodes(struct node *old_node, struct node *new_node); |
| 178 | 198 | ||
| 179 | void add_property(struct node *node, struct property *prop); | 199 | void add_property(struct node *node, struct property *prop); |
| 200 | void delete_property_by_name(struct node *node, char *name); | ||
| 201 | void delete_property(struct property *prop); | ||
| 180 | void add_child(struct node *parent, struct node *child); | 202 | void add_child(struct node *parent, struct node *child); |
| 203 | void delete_node_by_name(struct node *parent, char *name); | ||
| 204 | void delete_node(struct node *node); | ||
| 181 | 205 | ||
| 182 | const char *get_unitname(struct node *node); | 206 | const char *get_unitname(struct node *node); |
| 183 | struct property *get_property(struct node *node, const char *propname); | 207 | struct property *get_property(struct node *node, const char *propname); |
| @@ -224,6 +248,7 @@ void sort_tree(struct boot_info *bi); | |||
| 224 | 248 | ||
| 225 | /* Checks */ | 249 | /* Checks */ |
| 226 | 250 | ||
| 251 | void parse_checks_option(bool warn, bool error, const char *optarg); | ||
| 227 | void process_checks(int force, struct boot_info *bi); | 252 | void process_checks(int force, struct boot_info *bi); |
| 228 | 253 | ||
| 229 | /* Flattened trees */ | 254 | /* Flattened trees */ |
diff --git a/scripts/dtc/fdtdump.c b/scripts/dtc/fdtdump.c new file mode 100644 index 000000000000..207a46d64864 --- /dev/null +++ b/scripts/dtc/fdtdump.c | |||
| @@ -0,0 +1,162 @@ | |||
| 1 | /* | ||
| 2 | * fdtdump.c - Contributed by Pantelis Antoniou <pantelis.antoniou AT gmail.com> | ||
| 3 | */ | ||
| 4 | |||
| 5 | #include <stdint.h> | ||
| 6 | #include <stdio.h> | ||
| 7 | #include <stdlib.h> | ||
| 8 | #include <string.h> | ||
| 9 | #include <ctype.h> | ||
| 10 | |||
| 11 | #include <fdt.h> | ||
| 12 | #include <libfdt_env.h> | ||
| 13 | |||
| 14 | #include "util.h" | ||
| 15 | |||
| 16 | #define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1)) | ||
| 17 | #define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a)))) | ||
| 18 | #define GET_CELL(p) (p += 4, *((const uint32_t *)(p-4))) | ||
| 19 | |||
| 20 | static void print_data(const char *data, int len) | ||
| 21 | { | ||
| 22 | int i; | ||
| 23 | const char *p = data; | ||
| 24 | |||
| 25 | /* no data, don't print */ | ||
| 26 | if (len == 0) | ||
| 27 | return; | ||
| 28 | |||
| 29 | if (util_is_printable_string(data, len)) { | ||
| 30 | printf(" = \"%s\"", (const char *)data); | ||
| 31 | } else if ((len % 4) == 0) { | ||
| 32 | printf(" = <"); | ||
| 33 | for (i = 0; i < len; i += 4) | ||
| 34 | printf("0x%08x%s", fdt32_to_cpu(GET_CELL(p)), | ||
| 35 | i < (len - 4) ? " " : ""); | ||
| 36 | printf(">"); | ||
| 37 | } else { | ||
| 38 | printf(" = ["); | ||
| 39 | for (i = 0; i < len; i++) | ||
| 40 | printf("%02x%s", *p++, i < len - 1 ? " " : ""); | ||
| 41 | printf("]"); | ||
| 42 | } | ||
| 43 | } | ||
| 44 | |||
| 45 | static void dump_blob(void *blob) | ||
| 46 | { | ||
| 47 | struct fdt_header *bph = blob; | ||
| 48 | uint32_t off_mem_rsvmap = fdt32_to_cpu(bph->off_mem_rsvmap); | ||
| 49 | uint32_t off_dt = fdt32_to_cpu(bph->off_dt_struct); | ||
| 50 | uint32_t off_str = fdt32_to_cpu(bph->off_dt_strings); | ||
| 51 | struct fdt_reserve_entry *p_rsvmap = | ||
| 52 | (struct fdt_reserve_entry *)((char *)blob + off_mem_rsvmap); | ||
| 53 | const char *p_struct = (const char *)blob + off_dt; | ||
| 54 | const char *p_strings = (const char *)blob + off_str; | ||
| 55 | uint32_t version = fdt32_to_cpu(bph->version); | ||
| 56 | uint32_t totalsize = fdt32_to_cpu(bph->totalsize); | ||
| 57 | uint32_t tag; | ||
| 58 | const char *p, *s, *t; | ||
| 59 | int depth, sz, shift; | ||
| 60 | int i; | ||
| 61 | uint64_t addr, size; | ||
| 62 | |||
| 63 | depth = 0; | ||
| 64 | shift = 4; | ||
| 65 | |||
| 66 | printf("/dts-v1/;\n"); | ||
| 67 | printf("// magic:\t\t0x%x\n", fdt32_to_cpu(bph->magic)); | ||
| 68 | printf("// totalsize:\t\t0x%x (%d)\n", totalsize, totalsize); | ||
| 69 | printf("// off_dt_struct:\t0x%x\n", off_dt); | ||
| 70 | printf("// off_dt_strings:\t0x%x\n", off_str); | ||
| 71 | printf("// off_mem_rsvmap:\t0x%x\n", off_mem_rsvmap); | ||
| 72 | printf("// version:\t\t%d\n", version); | ||
| 73 | printf("// last_comp_version:\t%d\n", | ||
| 74 | fdt32_to_cpu(bph->last_comp_version)); | ||
| 75 | if (version >= 2) | ||
| 76 | printf("// boot_cpuid_phys:\t0x%x\n", | ||
| 77 | fdt32_to_cpu(bph->boot_cpuid_phys)); | ||
| 78 | |||
| 79 | if (version >= 3) | ||
| 80 | printf("// size_dt_strings:\t0x%x\n", | ||
| 81 | fdt32_to_cpu(bph->size_dt_strings)); | ||
| 82 | if (version >= 17) | ||
| 83 | printf("// size_dt_struct:\t0x%x\n", | ||
| 84 | fdt32_to_cpu(bph->size_dt_struct)); | ||
| 85 | printf("\n"); | ||
| 86 | |||
| 87 | for (i = 0; ; i++) { | ||
| 88 | addr = fdt64_to_cpu(p_rsvmap[i].address); | ||
| 89 | size = fdt64_to_cpu(p_rsvmap[i].size); | ||
| 90 | if (addr == 0 && size == 0) | ||
| 91 | break; | ||
| 92 | |||
| 93 | printf("/memreserve/ %llx %llx;\n", | ||
| 94 | (unsigned long long)addr, (unsigned long long)size); | ||
| 95 | } | ||
| 96 | |||
| 97 | p = p_struct; | ||
| 98 | while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) { | ||
| 99 | |||
| 100 | /* printf("tag: 0x%08x (%d)\n", tag, p - p_struct); */ | ||
| 101 | |||
| 102 | if (tag == FDT_BEGIN_NODE) { | ||
| 103 | s = p; | ||
| 104 | p = PALIGN(p + strlen(s) + 1, 4); | ||
| 105 | |||
| 106 | if (*s == '\0') | ||
| 107 | s = "/"; | ||
| 108 | |||
| 109 | printf("%*s%s {\n", depth * shift, "", s); | ||
| 110 | |||
| 111 | depth++; | ||
| 112 | continue; | ||
| 113 | } | ||
| 114 | |||
| 115 | if (tag == FDT_END_NODE) { | ||
| 116 | depth--; | ||
| 117 | |||
| 118 | printf("%*s};\n", depth * shift, ""); | ||
| 119 | continue; | ||
| 120 | } | ||
| 121 | |||
| 122 | if (tag == FDT_NOP) { | ||
| 123 | printf("%*s// [NOP]\n", depth * shift, ""); | ||
| 124 | continue; | ||
| 125 | } | ||
| 126 | |||
| 127 | if (tag != FDT_PROP) { | ||
| 128 | fprintf(stderr, "%*s ** Unknown tag 0x%08x\n", depth * shift, "", tag); | ||
| 129 | break; | ||
| 130 | } | ||
| 131 | sz = fdt32_to_cpu(GET_CELL(p)); | ||
| 132 | s = p_strings + fdt32_to_cpu(GET_CELL(p)); | ||
| 133 | if (version < 16 && sz >= 8) | ||
| 134 | p = PALIGN(p, 8); | ||
| 135 | t = p; | ||
| 136 | |||
| 137 | p = PALIGN(p + sz, 4); | ||
| 138 | |||
| 139 | printf("%*s%s", depth * shift, "", s); | ||
| 140 | print_data(t, sz); | ||
| 141 | printf(";\n"); | ||
| 142 | } | ||
| 143 | } | ||
| 144 | |||
| 145 | |||
| 146 | int main(int argc, char *argv[]) | ||
| 147 | { | ||
| 148 | char *buf; | ||
| 149 | |||
| 150 | if (argc < 2) { | ||
| 151 | fprintf(stderr, "supply input filename\n"); | ||
| 152 | return 5; | ||
| 153 | } | ||
| 154 | |||
| 155 | buf = utilfdt_read(argv[1]); | ||
| 156 | if (buf) | ||
| 157 | dump_blob(buf); | ||
| 158 | else | ||
| 159 | return 10; | ||
| 160 | |||
| 161 | return 0; | ||
| 162 | } | ||
diff --git a/scripts/dtc/fdtget.c b/scripts/dtc/fdtget.c new file mode 100644 index 000000000000..c2fbab2a5476 --- /dev/null +++ b/scripts/dtc/fdtget.c | |||
| @@ -0,0 +1,366 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2011 The Chromium OS Authors. All rights reserved. | ||
| 3 | * | ||
| 4 | * Portions from U-Boot cmd_fdt.c (C) Copyright 2007 | ||
| 5 | * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com | ||
| 6 | * Based on code written by: | ||
| 7 | * Pantelis Antoniou <pantelis.antoniou@gmail.com> and | ||
| 8 | * Matthew McClintock <msm@freescale.com> | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or | ||
| 11 | * modify it under the terms of the GNU General Public License as | ||
| 12 | * published by the Free Software Foundation; either version 2 of | ||
| 13 | * the License, or (at your option) any later version. | ||
| 14 | * | ||
| 15 | * This program is distributed in the hope that it will be useful, | ||
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | * GNU General Public License for more details. | ||
| 19 | * | ||
| 20 | * You should have received a copy of the GNU General Public License | ||
| 21 | * along with this program; if not, write to the Free Software | ||
| 22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | ||
| 23 | * MA 02111-1307 USA | ||
| 24 | */ | ||
| 25 | |||
| 26 | #include <assert.h> | ||
| 27 | #include <ctype.h> | ||
| 28 | #include <getopt.h> | ||
| 29 | #include <stdio.h> | ||
| 30 | #include <stdlib.h> | ||
| 31 | #include <string.h> | ||
| 32 | |||
| 33 | #include <libfdt.h> | ||
| 34 | |||
| 35 | #include "util.h" | ||
| 36 | |||
| 37 | enum display_mode { | ||
| 38 | MODE_SHOW_VALUE, /* show values for node properties */ | ||
| 39 | MODE_LIST_PROPS, /* list the properties for a node */ | ||
| 40 | MODE_LIST_SUBNODES, /* list the subnodes of a node */ | ||
| 41 | }; | ||
| 42 | |||
| 43 | /* Holds information which controls our output and options */ | ||
| 44 | struct display_info { | ||
| 45 | int type; /* data type (s/i/u/x or 0 for default) */ | ||
| 46 | int size; /* data size (1/2/4) */ | ||
| 47 | enum display_mode mode; /* display mode that we are using */ | ||
| 48 | const char *default_val; /* default value if node/property not found */ | ||
| 49 | }; | ||
| 50 | |||
| 51 | static void report_error(const char *where, int err) | ||
| 52 | { | ||
| 53 | fprintf(stderr, "Error at '%s': %s\n", where, fdt_strerror(err)); | ||
| 54 | } | ||
| 55 | |||
| 56 | /** | ||
| 57 | * Displays data of a given length according to selected options | ||
| 58 | * | ||
| 59 | * If a specific data type is provided in disp, then this is used. Otherwise | ||
| 60 | * we try to guess the data type / size from the contents. | ||
| 61 | * | ||
| 62 | * @param disp Display information / options | ||
| 63 | * @param data Data to display | ||
| 64 | * @param len Maximum length of buffer | ||
| 65 | * @return 0 if ok, -1 if data does not match format | ||
| 66 | */ | ||
| 67 | static int show_data(struct display_info *disp, const char *data, int len) | ||
| 68 | { | ||
| 69 | int i, size; | ||
| 70 | const uint8_t *p = (const uint8_t *)data; | ||
| 71 | const char *s; | ||
| 72 | int value; | ||
| 73 | int is_string; | ||
| 74 | char fmt[3]; | ||
| 75 | |||
| 76 | /* no data, don't print */ | ||
| 77 | if (len == 0) | ||
| 78 | return 0; | ||
| 79 | |||
| 80 | is_string = (disp->type) == 's' || | ||
| 81 | (!disp->type && util_is_printable_string(data, len)); | ||
| 82 | if (is_string) { | ||
| 83 | if (data[len - 1] != '\0') { | ||
| 84 | fprintf(stderr, "Unterminated string\n"); | ||
| 85 | return -1; | ||
| 86 | } | ||
| 87 | for (s = data; s - data < len; s += strlen(s) + 1) { | ||
| 88 | if (s != data) | ||
| 89 | printf(" "); | ||
| 90 | printf("%s", (const char *)s); | ||
| 91 | } | ||
| 92 | return 0; | ||
| 93 | } | ||
| 94 | size = disp->size; | ||
| 95 | if (size == -1) { | ||
| 96 | size = (len % 4) == 0 ? 4 : 1; | ||
| 97 | } else if (len % size) { | ||
| 98 | fprintf(stderr, "Property length must be a multiple of " | ||
| 99 | "selected data size\n"); | ||
| 100 | return -1; | ||
| 101 | } | ||
| 102 | fmt[0] = '%'; | ||
| 103 | fmt[1] = disp->type ? disp->type : 'd'; | ||
| 104 | fmt[2] = '\0'; | ||
| 105 | for (i = 0; i < len; i += size, p += size) { | ||
| 106 | if (i) | ||
| 107 | printf(" "); | ||
| 108 | value = size == 4 ? fdt32_to_cpu(*(const uint32_t *)p) : | ||
| 109 | size == 2 ? (*p << 8) | p[1] : *p; | ||
| 110 | printf(fmt, value); | ||
| 111 | } | ||
| 112 | return 0; | ||
| 113 | } | ||
| 114 | |||
| 115 | /** | ||
| 116 | * List all properties in a node, one per line. | ||
| 117 | * | ||
| 118 | * @param blob FDT blob | ||
| 119 | * @param node Node to display | ||
| 120 | * @return 0 if ok, or FDT_ERR... if not. | ||
| 121 | */ | ||
| 122 | static int list_properties(const void *blob, int node) | ||
| 123 | { | ||
| 124 | const struct fdt_property *data; | ||
| 125 | const char *name; | ||
| 126 | int prop; | ||
| 127 | |||
| 128 | prop = fdt_first_property_offset(blob, node); | ||
| 129 | do { | ||
| 130 | /* Stop silently when there are no more properties */ | ||
| 131 | if (prop < 0) | ||
| 132 | return prop == -FDT_ERR_NOTFOUND ? 0 : prop; | ||
| 133 | data = fdt_get_property_by_offset(blob, prop, NULL); | ||
| 134 | name = fdt_string(blob, fdt32_to_cpu(data->nameoff)); | ||
| 135 | if (name) | ||
| 136 | puts(name); | ||
| 137 | prop = fdt_next_property_offset(blob, prop); | ||
| 138 | } while (1); | ||
| 139 | } | ||
| 140 | |||
| 141 | #define MAX_LEVEL 32 /* how deeply nested we will go */ | ||
| 142 | |||
| 143 | /** | ||
| 144 | * List all subnodes in a node, one per line | ||
| 145 | * | ||
| 146 | * @param blob FDT blob | ||
| 147 | * @param node Node to display | ||
| 148 | * @return 0 if ok, or FDT_ERR... if not. | ||
| 149 | */ | ||
| 150 | static int list_subnodes(const void *blob, int node) | ||
| 151 | { | ||
| 152 | int nextoffset; /* next node offset from libfdt */ | ||
| 153 | uint32_t tag; /* current tag */ | ||
| 154 | int level = 0; /* keep track of nesting level */ | ||
| 155 | const char *pathp; | ||
| 156 | int depth = 1; /* the assumed depth of this node */ | ||
| 157 | |||
| 158 | while (level >= 0) { | ||
| 159 | tag = fdt_next_tag(blob, node, &nextoffset); | ||
| 160 | switch (tag) { | ||
| 161 | case FDT_BEGIN_NODE: | ||
| 162 | pathp = fdt_get_name(blob, node, NULL); | ||
| 163 | if (level <= depth) { | ||
| 164 | if (pathp == NULL) | ||
| 165 | pathp = "/* NULL pointer error */"; | ||
| 166 | if (*pathp == '\0') | ||
| 167 | pathp = "/"; /* root is nameless */ | ||
| 168 | if (level == 1) | ||
| 169 | puts(pathp); | ||
| 170 | } | ||
| 171 | level++; | ||
| 172 | if (level >= MAX_LEVEL) { | ||
| 173 | printf("Nested too deep, aborting.\n"); | ||
| 174 | return 1; | ||
| 175 | } | ||
| 176 | break; | ||
| 177 | case FDT_END_NODE: | ||
| 178 | level--; | ||
| 179 | if (level == 0) | ||
| 180 | level = -1; /* exit the loop */ | ||
| 181 | break; | ||
| 182 | case FDT_END: | ||
| 183 | return 1; | ||
| 184 | case FDT_PROP: | ||
| 185 | break; | ||
| 186 | default: | ||
| 187 | if (level <= depth) | ||
| 188 | printf("Unknown tag 0x%08X\n", tag); | ||
| 189 | return 1; | ||
| 190 | } | ||
| 191 | node = nextoffset; | ||
| 192 | } | ||
| 193 | return 0; | ||
| 194 | } | ||
| 195 | |||
| 196 | /** | ||
| 197 | * Show the data for a given node (and perhaps property) according to the | ||
| 198 | * display option provided. | ||
| 199 | * | ||
| 200 | * @param blob FDT blob | ||
| 201 | * @param disp Display information / options | ||
| 202 | * @param node Node to display | ||
| 203 | * @param property Name of property to display, or NULL if none | ||
| 204 | * @return 0 if ok, -ve on error | ||
| 205 | */ | ||
| 206 | static int show_data_for_item(const void *blob, struct display_info *disp, | ||
| 207 | int node, const char *property) | ||
| 208 | { | ||
| 209 | const void *value = NULL; | ||
| 210 | int len, err = 0; | ||
| 211 | |||
| 212 | switch (disp->mode) { | ||
| 213 | case MODE_LIST_PROPS: | ||
| 214 | err = list_properties(blob, node); | ||
| 215 | break; | ||
| 216 | |||
| 217 | case MODE_LIST_SUBNODES: | ||
| 218 | err = list_subnodes(blob, node); | ||
| 219 | break; | ||
| 220 | |||
| 221 | default: | ||
| 222 | assert(property); | ||
| 223 | value = fdt_getprop(blob, node, property, &len); | ||
| 224 | if (value) { | ||
| 225 | if (show_data(disp, value, len)) | ||
| 226 | err = -1; | ||
| 227 | else | ||
| 228 | printf("\n"); | ||
| 229 | } else if (disp->default_val) { | ||
| 230 | puts(disp->default_val); | ||
| 231 | } else { | ||
| 232 | report_error(property, len); | ||
| 233 | err = -1; | ||
| 234 | } | ||
| 235 | break; | ||
| 236 | } | ||
| 237 | |||
| 238 | return err; | ||
| 239 | } | ||
| 240 | |||
| 241 | /** | ||
| 242 | * Run the main fdtget operation, given a filename and valid arguments | ||
| 243 | * | ||
| 244 | * @param disp Display information / options | ||
| 245 | * @param filename Filename of blob file | ||
| 246 | * @param arg List of arguments to process | ||
| 247 | * @param arg_count Number of arguments | ||
| 248 | * @param return 0 if ok, -ve on error | ||
| 249 | */ | ||
| 250 | static int do_fdtget(struct display_info *disp, const char *filename, | ||
| 251 | char **arg, int arg_count, int args_per_step) | ||
| 252 | { | ||
| 253 | char *blob; | ||
| 254 | const char *prop; | ||
| 255 | int i, node; | ||
| 256 | |||
| 257 | blob = utilfdt_read(filename); | ||
| 258 | if (!blob) | ||
| 259 | return -1; | ||
| 260 | |||
| 261 | for (i = 0; i + args_per_step <= arg_count; i += args_per_step) { | ||
| 262 | node = fdt_path_offset(blob, arg[i]); | ||
| 263 | if (node < 0) { | ||
| 264 | if (disp->default_val) { | ||
| 265 | puts(disp->default_val); | ||
| 266 | continue; | ||
| 267 | } else { | ||
| 268 | report_error(arg[i], node); | ||
| 269 | return -1; | ||
| 270 | } | ||
| 271 | } | ||
| 272 | prop = args_per_step == 1 ? NULL : arg[i + 1]; | ||
| 273 | |||
| 274 | if (show_data_for_item(blob, disp, node, prop)) | ||
| 275 | return -1; | ||
| 276 | } | ||
| 277 | return 0; | ||
| 278 | } | ||
| 279 | |||
| 280 | static const char *usage_msg = | ||
| 281 | "fdtget - read values from device tree\n" | ||
| 282 | "\n" | ||
| 283 | "Each value is printed on a new line.\n\n" | ||
| 284 | "Usage:\n" | ||
| 285 | " fdtget <options> <dt file> [<node> <property>]...\n" | ||
| 286 | " fdtget -p <options> <dt file> [<node> ]...\n" | ||
| 287 | "Options:\n" | ||
| 288 | "\t-t <type>\tType of data\n" | ||
| 289 | "\t-p\t\tList properties for each node\n" | ||
| 290 | "\t-l\t\tList subnodes for each node\n" | ||
| 291 | "\t-d\t\tDefault value to display when the property is " | ||
| 292 | "missing\n" | ||
| 293 | "\t-h\t\tPrint this help\n\n" | ||
| 294 | USAGE_TYPE_MSG; | ||
| 295 | |||
| 296 | static void usage(const char *msg) | ||
| 297 | { | ||
| 298 | if (msg) | ||
| 299 | fprintf(stderr, "Error: %s\n\n", msg); | ||
| 300 | |||
| 301 | fprintf(stderr, "%s", usage_msg); | ||
| 302 | exit(2); | ||
| 303 | } | ||
| 304 | |||
| 305 | int main(int argc, char *argv[]) | ||
| 306 | { | ||
| 307 | char *filename = NULL; | ||
| 308 | struct display_info disp; | ||
| 309 | int args_per_step = 2; | ||
| 310 | |||
| 311 | /* set defaults */ | ||
| 312 | memset(&disp, '\0', sizeof(disp)); | ||
| 313 | disp.size = -1; | ||
| 314 | disp.mode = MODE_SHOW_VALUE; | ||
| 315 | for (;;) { | ||
| 316 | int c = getopt(argc, argv, "d:hlpt:"); | ||
| 317 | if (c == -1) | ||
| 318 | break; | ||
| 319 | |||
| 320 | switch (c) { | ||
| 321 | case 'h': | ||
| 322 | case '?': | ||
| 323 | usage(NULL); | ||
| 324 | |||
| 325 | case 't': | ||
| 326 | if (utilfdt_decode_type(optarg, &disp.type, | ||
| 327 | &disp.size)) | ||
| 328 | usage("Invalid type string"); | ||
| 329 | break; | ||
| 330 | |||
| 331 | case 'p': | ||
| 332 | disp.mode = MODE_LIST_PROPS; | ||
| 333 | args_per_step = 1; | ||
| 334 | break; | ||
| 335 | |||
| 336 | case 'l': | ||
| 337 | disp.mode = MODE_LIST_SUBNODES; | ||
| 338 | args_per_step = 1; | ||
| 339 | break; | ||
| 340 | |||
| 341 | case 'd': | ||
| 342 | disp.default_val = optarg; | ||
| 343 | break; | ||
| 344 | } | ||
| 345 | } | ||
| 346 | |||
| 347 | if (optind < argc) | ||
| 348 | filename = argv[optind++]; | ||
| 349 | if (!filename) | ||
| 350 | usage("Missing filename"); | ||
| 351 | |||
| 352 | argv += optind; | ||
| 353 | argc -= optind; | ||
| 354 | |||
| 355 | /* Allow no arguments, and silently succeed */ | ||
| 356 | if (!argc) | ||
| 357 | return 0; | ||
| 358 | |||
| 359 | /* Check for node, property arguments */ | ||
| 360 | if (args_per_step == 2 && (argc % 2)) | ||
| 361 | usage("Must have an even number of arguments"); | ||
| 362 | |||
| 363 | if (do_fdtget(&disp, filename, argv, argc, args_per_step)) | ||
| 364 | return 1; | ||
| 365 | return 0; | ||
| 366 | } | ||
diff --git a/scripts/dtc/fdtput.c b/scripts/dtc/fdtput.c new file mode 100644 index 000000000000..f2197f51930b --- /dev/null +++ b/scripts/dtc/fdtput.c | |||
| @@ -0,0 +1,362 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2011 The Chromium OS Authors. All rights reserved. | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or | ||
| 5 | * modify it under the terms of the GNU General Public License as | ||
| 6 | * published by the Free Software Foundation; either version 2 of | ||
| 7 | * the License, or (at your option) any later version. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope that it will be useful, | ||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | * GNU General Public License for more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU General Public License | ||
| 15 | * along with this program; if not, write to the Free Software | ||
| 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | ||
| 17 | * MA 02111-1307 USA | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <assert.h> | ||
| 21 | #include <ctype.h> | ||
| 22 | #include <getopt.h> | ||
| 23 | #include <stdio.h> | ||
| 24 | #include <stdlib.h> | ||
| 25 | #include <string.h> | ||
| 26 | |||
| 27 | #include <libfdt.h> | ||
| 28 | |||
| 29 | #include "util.h" | ||
| 30 | |||
| 31 | /* These are the operations we support */ | ||
| 32 | enum oper_type { | ||
| 33 | OPER_WRITE_PROP, /* Write a property in a node */ | ||
| 34 | OPER_CREATE_NODE, /* Create a new node */ | ||
| 35 | }; | ||
| 36 | |||
| 37 | struct display_info { | ||
| 38 | enum oper_type oper; /* operation to perform */ | ||
| 39 | int type; /* data type (s/i/u/x or 0 for default) */ | ||
| 40 | int size; /* data size (1/2/4) */ | ||
| 41 | int verbose; /* verbose output */ | ||
| 42 | int auto_path; /* automatically create all path components */ | ||
| 43 | }; | ||
| 44 | |||
| 45 | |||
| 46 | /** | ||
| 47 | * Report an error with a particular node. | ||
| 48 | * | ||
| 49 | * @param name Node name to report error on | ||
| 50 | * @param namelen Length of node name, or -1 to use entire string | ||
| 51 | * @param err Error number to report (-FDT_ERR_...) | ||
| 52 | */ | ||
| 53 | static void report_error(const char *name, int namelen, int err) | ||
| 54 | { | ||
| 55 | if (namelen == -1) | ||
| 56 | namelen = strlen(name); | ||
| 57 | fprintf(stderr, "Error at '%1.*s': %s\n", namelen, name, | ||
| 58 | fdt_strerror(err)); | ||
| 59 | } | ||
| 60 | |||
| 61 | /** | ||
| 62 | * Encode a series of arguments in a property value. | ||
| 63 | * | ||
| 64 | * @param disp Display information / options | ||
| 65 | * @param arg List of arguments from command line | ||
| 66 | * @param arg_count Number of arguments (may be 0) | ||
| 67 | * @param valuep Returns buffer containing value | ||
| 68 | * @param *value_len Returns length of value encoded | ||
| 69 | */ | ||
| 70 | static int encode_value(struct display_info *disp, char **arg, int arg_count, | ||
| 71 | char **valuep, int *value_len) | ||
| 72 | { | ||
| 73 | char *value = NULL; /* holding area for value */ | ||
| 74 | int value_size = 0; /* size of holding area */ | ||
| 75 | char *ptr; /* pointer to current value position */ | ||
| 76 | int len; /* length of this cell/string/byte */ | ||
| 77 | int ival; | ||
| 78 | int upto; /* the number of bytes we have written to buf */ | ||
| 79 | char fmt[3]; | ||
| 80 | |||
| 81 | upto = 0; | ||
| 82 | |||
| 83 | if (disp->verbose) | ||
| 84 | fprintf(stderr, "Decoding value:\n"); | ||
| 85 | |||
| 86 | fmt[0] = '%'; | ||
| 87 | fmt[1] = disp->type ? disp->type : 'd'; | ||
| 88 | fmt[2] = '\0'; | ||
| 89 | for (; arg_count > 0; arg++, arg_count--, upto += len) { | ||
| 90 | /* assume integer unless told otherwise */ | ||
| 91 | if (disp->type == 's') | ||
| 92 | len = strlen(*arg) + 1; | ||
| 93 | else | ||
| 94 | len = disp->size == -1 ? 4 : disp->size; | ||
| 95 | |||
| 96 | /* enlarge our value buffer by a suitable margin if needed */ | ||
| 97 | if (upto + len > value_size) { | ||
| 98 | value_size = (upto + len) + 500; | ||
| 99 | value = realloc(value, value_size); | ||
| 100 | if (!value) { | ||
| 101 | fprintf(stderr, "Out of mmory: cannot alloc " | ||
| 102 | "%d bytes\n", value_size); | ||
| 103 | return -1; | ||
| 104 | } | ||
| 105 | } | ||
| 106 | |||
| 107 | ptr = value + upto; | ||
| 108 | if (disp->type == 's') { | ||
| 109 | memcpy(ptr, *arg, len); | ||
| 110 | if (disp->verbose) | ||
| 111 | fprintf(stderr, "\tstring: '%s'\n", ptr); | ||
| 112 | } else { | ||
| 113 | int *iptr = (int *)ptr; | ||
| 114 | sscanf(*arg, fmt, &ival); | ||
| 115 | if (len == 4) | ||
| 116 | *iptr = cpu_to_fdt32(ival); | ||
| 117 | else | ||
| 118 | *ptr = (uint8_t)ival; | ||
| 119 | if (disp->verbose) { | ||
| 120 | fprintf(stderr, "\t%s: %d\n", | ||
| 121 | disp->size == 1 ? "byte" : | ||
| 122 | disp->size == 2 ? "short" : "int", | ||
| 123 | ival); | ||
| 124 | } | ||
| 125 | } | ||
| 126 | } | ||
| 127 | *value_len = upto; | ||
| 128 | *valuep = value; | ||
| 129 | if (disp->verbose) | ||
| 130 | fprintf(stderr, "Value size %d\n", upto); | ||
| 131 | return 0; | ||
| 132 | } | ||
| 133 | |||
| 134 | static int store_key_value(void *blob, const char *node_name, | ||
| 135 | const char *property, const char *buf, int len) | ||
| 136 | { | ||
| 137 | int node; | ||
| 138 | int err; | ||
| 139 | |||
| 140 | node = fdt_path_offset(blob, node_name); | ||
| 141 | if (node < 0) { | ||
| 142 | report_error(node_name, -1, node); | ||
| 143 | return -1; | ||
| 144 | } | ||
| 145 | |||
| 146 | err = fdt_setprop(blob, node, property, buf, len); | ||
| 147 | if (err) { | ||
| 148 | report_error(property, -1, err); | ||
| 149 | return -1; | ||
| 150 | } | ||
| 151 | return 0; | ||
| 152 | } | ||
| 153 | |||
| 154 | /** | ||
| 155 | * Create paths as needed for all components of a path | ||
| 156 | * | ||
| 157 | * Any components of the path that do not exist are created. Errors are | ||
| 158 | * reported. | ||
| 159 | * | ||
| 160 | * @param blob FDT blob to write into | ||
| 161 | * @param in_path Path to process | ||
| 162 | * @return 0 if ok, -1 on error | ||
| 163 | */ | ||
| 164 | static int create_paths(void *blob, const char *in_path) | ||
| 165 | { | ||
| 166 | const char *path = in_path; | ||
| 167 | const char *sep; | ||
| 168 | int node, offset = 0; | ||
| 169 | |||
| 170 | /* skip leading '/' */ | ||
| 171 | while (*path == '/') | ||
| 172 | path++; | ||
| 173 | |||
| 174 | for (sep = path; *sep; path = sep + 1, offset = node) { | ||
| 175 | /* equivalent to strchrnul(), but it requires _GNU_SOURCE */ | ||
| 176 | sep = strchr(path, '/'); | ||
| 177 | if (!sep) | ||
| 178 | sep = path + strlen(path); | ||
| 179 | |||
| 180 | node = fdt_subnode_offset_namelen(blob, offset, path, | ||
| 181 | sep - path); | ||
| 182 | if (node == -FDT_ERR_NOTFOUND) { | ||
| 183 | node = fdt_add_subnode_namelen(blob, offset, path, | ||
| 184 | sep - path); | ||
| 185 | } | ||
| 186 | if (node < 0) { | ||
| 187 | report_error(path, sep - path, node); | ||
| 188 | return -1; | ||
| 189 | } | ||
| 190 | } | ||
| 191 | |||
| 192 | return 0; | ||
| 193 | } | ||
| 194 | |||
| 195 | /** | ||
| 196 | * Create a new node in the fdt. | ||
| 197 | * | ||
| 198 | * This will overwrite the node_name string. Any error is reported. | ||
| 199 | * | ||
| 200 | * TODO: Perhaps create fdt_path_offset_namelen() so we don't need to do this. | ||
| 201 | * | ||
| 202 | * @param blob FDT blob to write into | ||
| 203 | * @param node_name Name of node to create | ||
| 204 | * @return new node offset if found, or -1 on failure | ||
| 205 | */ | ||
| 206 | static int create_node(void *blob, const char *node_name) | ||
| 207 | { | ||
| 208 | int node = 0; | ||
| 209 | char *p; | ||
| 210 | |||
| 211 | p = strrchr(node_name, '/'); | ||
| 212 | if (!p) { | ||
| 213 | report_error(node_name, -1, -FDT_ERR_BADPATH); | ||
| 214 | return -1; | ||
| 215 | } | ||
| 216 | *p = '\0'; | ||
| 217 | |||
| 218 | if (p > node_name) { | ||
| 219 | node = fdt_path_offset(blob, node_name); | ||
| 220 | if (node < 0) { | ||
| 221 | report_error(node_name, -1, node); | ||
| 222 | return -1; | ||
| 223 | } | ||
| 224 | } | ||
| 225 | |||
| 226 | node = fdt_add_subnode(blob, node, p + 1); | ||
| 227 | if (node < 0) { | ||
| 228 | report_error(p + 1, -1, node); | ||
| 229 | return -1; | ||
| 230 | } | ||
| 231 | |||
| 232 | return 0; | ||
| 233 | } | ||
| 234 | |||
| 235 | static int do_fdtput(struct display_info *disp, const char *filename, | ||
| 236 | char **arg, int arg_count) | ||
| 237 | { | ||
| 238 | char *value; | ||
| 239 | char *blob; | ||
| 240 | int len, ret = 0; | ||
| 241 | |||
| 242 | blob = utilfdt_read(filename); | ||
| 243 | if (!blob) | ||
| 244 | return -1; | ||
| 245 | |||
| 246 | switch (disp->oper) { | ||
| 247 | case OPER_WRITE_PROP: | ||
| 248 | /* | ||
| 249 | * Convert the arguments into a single binary value, then | ||
| 250 | * store them into the property. | ||
| 251 | */ | ||
| 252 | assert(arg_count >= 2); | ||
| 253 | if (disp->auto_path && create_paths(blob, *arg)) | ||
| 254 | return -1; | ||
| 255 | if (encode_value(disp, arg + 2, arg_count - 2, &value, &len) || | ||
| 256 | store_key_value(blob, *arg, arg[1], value, len)) | ||
| 257 | ret = -1; | ||
| 258 | break; | ||
| 259 | case OPER_CREATE_NODE: | ||
| 260 | for (; ret >= 0 && arg_count--; arg++) { | ||
| 261 | if (disp->auto_path) | ||
| 262 | ret = create_paths(blob, *arg); | ||
| 263 | else | ||
| 264 | ret = create_node(blob, *arg); | ||
| 265 | } | ||
| 266 | break; | ||
| 267 | } | ||
| 268 | if (ret >= 0) | ||
| 269 | ret = utilfdt_write(filename, blob); | ||
| 270 | |||
| 271 | free(blob); | ||
| 272 | return ret; | ||
| 273 | } | ||
| 274 | |||
| 275 | static const char *usage_msg = | ||
| 276 | "fdtput - write a property value to a device tree\n" | ||
| 277 | "\n" | ||
| 278 | "The command line arguments are joined together into a single value.\n" | ||
| 279 | "\n" | ||
| 280 | "Usage:\n" | ||
| 281 | " fdtput <options> <dt file> <node> <property> [<value>...]\n" | ||
| 282 | " fdtput -c <options> <dt file> [<node>...]\n" | ||
| 283 | "Options:\n" | ||
| 284 | "\t-c\t\tCreate nodes if they don't already exist\n" | ||
| 285 | "\t-p\t\tAutomatically create nodes as needed for the node path\n" | ||
| 286 | "\t-t <type>\tType of data\n" | ||
| 287 | "\t-v\t\tVerbose: display each value decoded from command line\n" | ||
| 288 | "\t-h\t\tPrint this help\n\n" | ||
| 289 | USAGE_TYPE_MSG; | ||
| 290 | |||
| 291 | static void usage(const char *msg) | ||
| 292 | { | ||
| 293 | if (msg) | ||
| 294 | fprintf(stderr, "Error: %s\n\n", msg); | ||
| 295 | |||
| 296 | fprintf(stderr, "%s", usage_msg); | ||
| 297 | exit(2); | ||
| 298 | } | ||
| 299 | |||
| 300 | int main(int argc, char *argv[]) | ||
| 301 | { | ||
| 302 | struct display_info disp; | ||
| 303 | char *filename = NULL; | ||
| 304 | |||
| 305 | memset(&disp, '\0', sizeof(disp)); | ||
| 306 | disp.size = -1; | ||
| 307 | disp.oper = OPER_WRITE_PROP; | ||
| 308 | for (;;) { | ||
| 309 | int c = getopt(argc, argv, "chpt:v"); | ||
| 310 | if (c == -1) | ||
| 311 | break; | ||
| 312 | |||
| 313 | /* | ||
| 314 | * TODO: add options to: | ||
| 315 | * - delete property | ||
| 316 | * - delete node (optionally recursively) | ||
| 317 | * - rename node | ||
| 318 | * - pack fdt before writing | ||
| 319 | * - set amount of free space when writing | ||
| 320 | * - expand fdt if value doesn't fit | ||
| 321 | */ | ||
| 322 | switch (c) { | ||
| 323 | case 'c': | ||
| 324 | disp.oper = OPER_CREATE_NODE; | ||
| 325 | break; | ||
| 326 | case 'h': | ||
| 327 | case '?': | ||
| 328 | usage(NULL); | ||
| 329 | case 'p': | ||
| 330 | disp.auto_path = 1; | ||
| 331 | break; | ||
| 332 | case 't': | ||
| 333 | if (utilfdt_decode_type(optarg, &disp.type, | ||
| 334 | &disp.size)) | ||
| 335 | usage("Invalid type string"); | ||
| 336 | break; | ||
| 337 | |||
| 338 | case 'v': | ||
| 339 | disp.verbose = 1; | ||
| 340 | break; | ||
| 341 | } | ||
| 342 | } | ||
| 343 | |||
| 344 | if (optind < argc) | ||
| 345 | filename = argv[optind++]; | ||
| 346 | if (!filename) | ||
| 347 | usage("Missing filename"); | ||
| 348 | |||
| 349 | argv += optind; | ||
| 350 | argc -= optind; | ||
| 351 | |||
| 352 | if (disp.oper == OPER_WRITE_PROP) { | ||
| 353 | if (argc < 1) | ||
| 354 | usage("Missing node"); | ||
| 355 | if (argc < 2) | ||
| 356 | usage("Missing property"); | ||
| 357 | } | ||
| 358 | |||
| 359 | if (do_fdtput(&disp, filename, argv, argc)) | ||
| 360 | return 1; | ||
| 361 | return 0; | ||
| 362 | } | ||
diff --git a/scripts/dtc/flattree.c b/scripts/dtc/flattree.c index 28d0b2381df6..665dad7bb465 100644 --- a/scripts/dtc/flattree.c +++ b/scripts/dtc/flattree.c | |||
| @@ -263,6 +263,9 @@ static void flatten_tree(struct node *tree, struct emitter *emit, | |||
| 263 | struct node *child; | 263 | struct node *child; |
| 264 | int seen_name_prop = 0; | 264 | int seen_name_prop = 0; |
| 265 | 265 | ||
| 266 | if (tree->deleted) | ||
| 267 | return; | ||
| 268 | |||
| 266 | emit->beginnode(etarget, tree->labels); | 269 | emit->beginnode(etarget, tree->labels); |
| 267 | 270 | ||
| 268 | if (vi->flags & FTF_FULLPATH) | 271 | if (vi->flags & FTF_FULLPATH) |
diff --git a/scripts/dtc/libfdt/Makefile.libfdt b/scripts/dtc/libfdt/Makefile.libfdt index 6c42acfa21ec..91126c000a1e 100644 --- a/scripts/dtc/libfdt/Makefile.libfdt +++ b/scripts/dtc/libfdt/Makefile.libfdt | |||
| @@ -3,6 +3,8 @@ | |||
| 3 | # This is not a complete Makefile of itself. Instead, it is designed to | 3 | # This is not a complete Makefile of itself. Instead, it is designed to |
| 4 | # be easily embeddable into other systems of Makefiles. | 4 | # be easily embeddable into other systems of Makefiles. |
| 5 | # | 5 | # |
| 6 | LIBFDT_INCLUDES = fdt.h libfdt.h | 6 | LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1 |
| 7 | LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c | 7 | LIBFDT_INCLUDES = fdt.h libfdt.h libfdt_env.h |
| 8 | LIBFDT_VERSION = version.lds | ||
| 9 | LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c | ||
| 8 | LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o) | 10 | LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o) |
diff --git a/scripts/dtc/libfdt/fdt.c b/scripts/dtc/libfdt/fdt.c index 2acaec5923ae..e56833ae9b6f 100644 --- a/scripts/dtc/libfdt/fdt.c +++ b/scripts/dtc/libfdt/fdt.c | |||
| @@ -74,7 +74,7 @@ int fdt_check_header(const void *fdt) | |||
| 74 | return 0; | 74 | return 0; |
| 75 | } | 75 | } |
| 76 | 76 | ||
| 77 | const void *fdt_offset_ptr(const void *fdt, int offset, int len) | 77 | const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) |
| 78 | { | 78 | { |
| 79 | const char *p; | 79 | const char *p; |
| 80 | 80 | ||
| @@ -90,42 +90,53 @@ const void *fdt_offset_ptr(const void *fdt, int offset, int len) | |||
| 90 | return p; | 90 | return p; |
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset) | 93 | uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) |
| 94 | { | 94 | { |
| 95 | const uint32_t *tagp, *lenp; | 95 | const uint32_t *tagp, *lenp; |
| 96 | uint32_t tag; | 96 | uint32_t tag; |
| 97 | int offset = startoffset; | ||
| 97 | const char *p; | 98 | const char *p; |
| 98 | 99 | ||
| 99 | if (offset % FDT_TAGSIZE) | 100 | *nextoffset = -FDT_ERR_TRUNCATED; |
| 100 | return -1; | ||
| 101 | |||
| 102 | tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE); | 101 | tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE); |
| 103 | if (! tagp) | 102 | if (!tagp) |
| 104 | return FDT_END; /* premature end */ | 103 | return FDT_END; /* premature end */ |
| 105 | tag = fdt32_to_cpu(*tagp); | 104 | tag = fdt32_to_cpu(*tagp); |
| 106 | offset += FDT_TAGSIZE; | 105 | offset += FDT_TAGSIZE; |
| 107 | 106 | ||
| 107 | *nextoffset = -FDT_ERR_BADSTRUCTURE; | ||
| 108 | switch (tag) { | 108 | switch (tag) { |
| 109 | case FDT_BEGIN_NODE: | 109 | case FDT_BEGIN_NODE: |
| 110 | /* skip name */ | 110 | /* skip name */ |
| 111 | do { | 111 | do { |
| 112 | p = fdt_offset_ptr(fdt, offset++, 1); | 112 | p = fdt_offset_ptr(fdt, offset++, 1); |
| 113 | } while (p && (*p != '\0')); | 113 | } while (p && (*p != '\0')); |
| 114 | if (! p) | 114 | if (!p) |
| 115 | return FDT_END; | 115 | return FDT_END; /* premature end */ |
| 116 | break; | 116 | break; |
| 117 | |||
| 117 | case FDT_PROP: | 118 | case FDT_PROP: |
| 118 | lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp)); | 119 | lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp)); |
| 119 | if (! lenp) | 120 | if (!lenp) |
| 120 | return FDT_END; | 121 | return FDT_END; /* premature end */ |
| 121 | /* skip name offset, length and value */ | 122 | /* skip-name offset, length and value */ |
| 122 | offset += 2*FDT_TAGSIZE + fdt32_to_cpu(*lenp); | 123 | offset += sizeof(struct fdt_property) - FDT_TAGSIZE |
| 124 | + fdt32_to_cpu(*lenp); | ||
| 125 | break; | ||
| 126 | |||
| 127 | case FDT_END: | ||
| 128 | case FDT_END_NODE: | ||
| 129 | case FDT_NOP: | ||
| 123 | break; | 130 | break; |
| 131 | |||
| 132 | default: | ||
| 133 | return FDT_END; | ||
| 124 | } | 134 | } |
| 125 | 135 | ||
| 126 | if (nextoffset) | 136 | if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset)) |
| 127 | *nextoffset = FDT_TAGALIGN(offset); | 137 | return FDT_END; /* premature end */ |
| 128 | 138 | ||
| 139 | *nextoffset = FDT_TAGALIGN(offset); | ||
| 129 | return tag; | 140 | return tag; |
| 130 | } | 141 | } |
| 131 | 142 | ||
| @@ -138,6 +149,15 @@ int _fdt_check_node_offset(const void *fdt, int offset) | |||
| 138 | return offset; | 149 | return offset; |
| 139 | } | 150 | } |
| 140 | 151 | ||
| 152 | int _fdt_check_prop_offset(const void *fdt, int offset) | ||
| 153 | { | ||
| 154 | if ((offset < 0) || (offset % FDT_TAGSIZE) | ||
| 155 | || (fdt_next_tag(fdt, offset, &offset) != FDT_PROP)) | ||
| 156 | return -FDT_ERR_BADOFFSET; | ||
| 157 | |||
| 158 | return offset; | ||
| 159 | } | ||
| 160 | |||
| 141 | int fdt_next_node(const void *fdt, int offset, int *depth) | 161 | int fdt_next_node(const void *fdt, int offset, int *depth) |
| 142 | { | 162 | { |
| 143 | int nextoffset = 0; | 163 | int nextoffset = 0; |
| @@ -162,15 +182,16 @@ int fdt_next_node(const void *fdt, int offset, int *depth) | |||
| 162 | break; | 182 | break; |
| 163 | 183 | ||
| 164 | case FDT_END_NODE: | 184 | case FDT_END_NODE: |
| 165 | if (depth) | 185 | if (depth && ((--(*depth)) < 0)) |
| 166 | (*depth)--; | 186 | return nextoffset; |
| 167 | break; | 187 | break; |
| 168 | 188 | ||
| 169 | case FDT_END: | 189 | case FDT_END: |
| 170 | return -FDT_ERR_NOTFOUND; | 190 | if ((nextoffset >= 0) |
| 171 | 191 | || ((nextoffset == -FDT_ERR_TRUNCATED) && !depth)) | |
| 172 | default: | 192 | return -FDT_ERR_NOTFOUND; |
| 173 | return -FDT_ERR_BADSTRUCTURE; | 193 | else |
| 194 | return nextoffset; | ||
| 174 | } | 195 | } |
| 175 | } while (tag != FDT_BEGIN_NODE); | 196 | } while (tag != FDT_BEGIN_NODE); |
| 176 | 197 | ||
diff --git a/scripts/dtc/libfdt/fdt_empty_tree.c b/scripts/dtc/libfdt/fdt_empty_tree.c new file mode 100644 index 000000000000..f72d13b1d19c --- /dev/null +++ b/scripts/dtc/libfdt/fdt_empty_tree.c | |||
| @@ -0,0 +1,84 @@ | |||
| 1 | /* | ||
| 2 | * libfdt - Flat Device Tree manipulation | ||
| 3 | * Copyright (C) 2012 David Gibson, IBM Corporation. | ||
| 4 | * | ||
| 5 | * libfdt is dual licensed: you can use it either under the terms of | ||
| 6 | * the GPL, or the BSD license, at your option. | ||
| 7 | * | ||
| 8 | * a) This library is free software; you can redistribute it and/or | ||
| 9 | * modify it under the terms of the GNU General Public License as | ||
| 10 | * published by the Free Software Foundation; either version 2 of the | ||
| 11 | * License, or (at your option) any later version. | ||
| 12 | * | ||
| 13 | * This library is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public | ||
| 19 | * License along with this library; if not, write to the Free | ||
| 20 | * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, | ||
| 21 | * MA 02110-1301 USA | ||
| 22 | * | ||
| 23 | * Alternatively, | ||
| 24 | * | ||
| 25 | * b) Redistribution and use in source and binary forms, with or | ||
| 26 | * without modification, are permitted provided that the following | ||
| 27 | * conditions are met: | ||
| 28 | * | ||
| 29 | * 1. Redistributions of source code must retain the above | ||
| 30 | * copyright notice, this list of conditions and the following | ||
| 31 | * disclaimer. | ||
| 32 | * 2. Redistributions in binary form must reproduce the above | ||
| 33 | * copyright notice, this list of conditions and the following | ||
| 34 | * disclaimer in the documentation and/or other materials | ||
| 35 | * provided with the distribution. | ||
| 36 | * | ||
| 37 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND | ||
| 38 | * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, | ||
| 39 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
| 40 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
| 41 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||
| 42 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
| 43 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
| 44 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
| 45 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
| 46 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
| 47 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||
| 48 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | ||
| 49 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 50 | */ | ||
| 51 | #include "libfdt_env.h" | ||
| 52 | |||
| 53 | #include <fdt.h> | ||
| 54 | #include <libfdt.h> | ||
| 55 | |||
| 56 | #include "libfdt_internal.h" | ||
| 57 | |||
| 58 | int fdt_create_empty_tree(void *buf, int bufsize) | ||
| 59 | { | ||
| 60 | int err; | ||
| 61 | |||
| 62 | err = fdt_create(buf, bufsize); | ||
| 63 | if (err) | ||
| 64 | return err; | ||
| 65 | |||
| 66 | err = fdt_finish_reservemap(buf); | ||
| 67 | if (err) | ||
| 68 | return err; | ||
| 69 | |||
| 70 | err = fdt_begin_node(buf, ""); | ||
| 71 | if (err) | ||
| 72 | return err; | ||
| 73 | |||
| 74 | err = fdt_end_node(buf); | ||
| 75 | if (err) | ||
| 76 | return err; | ||
| 77 | |||
| 78 | err = fdt_finish(buf); | ||
| 79 | if (err) | ||
| 80 | return err; | ||
| 81 | |||
| 82 | return fdt_open_into(buf, buf, bufsize); | ||
| 83 | } | ||
| 84 | |||
diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c index 22e692919ff9..02b6d687537f 100644 --- a/scripts/dtc/libfdt/fdt_ro.c +++ b/scripts/dtc/libfdt/fdt_ro.c | |||
| @@ -80,6 +80,14 @@ const char *fdt_string(const void *fdt, int stroffset) | |||
| 80 | return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset; | 80 | return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset; |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | static int _fdt_string_eq(const void *fdt, int stroffset, | ||
| 84 | const char *s, int len) | ||
| 85 | { | ||
| 86 | const char *p = fdt_string(fdt, stroffset); | ||
| 87 | |||
| 88 | return (strlen(p) == len) && (memcmp(p, s, len) == 0); | ||
| 89 | } | ||
| 90 | |||
| 83 | int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) | 91 | int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) |
| 84 | { | 92 | { |
| 85 | FDT_CHECK_HEADER(fdt); | 93 | FDT_CHECK_HEADER(fdt); |
| @@ -97,6 +105,30 @@ int fdt_num_mem_rsv(const void *fdt) | |||
| 97 | return i; | 105 | return i; |
| 98 | } | 106 | } |
| 99 | 107 | ||
| 108 | static int _nextprop(const void *fdt, int offset) | ||
| 109 | { | ||
| 110 | uint32_t tag; | ||
| 111 | int nextoffset; | ||
| 112 | |||
| 113 | do { | ||
| 114 | tag = fdt_next_tag(fdt, offset, &nextoffset); | ||
| 115 | |||
| 116 | switch (tag) { | ||
| 117 | case FDT_END: | ||
| 118 | if (nextoffset >= 0) | ||
| 119 | return -FDT_ERR_BADSTRUCTURE; | ||
| 120 | else | ||
| 121 | return nextoffset; | ||
| 122 | |||
| 123 | case FDT_PROP: | ||
| 124 | return offset; | ||
| 125 | } | ||
| 126 | offset = nextoffset; | ||
| 127 | } while (tag == FDT_NOP); | ||
| 128 | |||
| 129 | return -FDT_ERR_NOTFOUND; | ||
| 130 | } | ||
| 131 | |||
| 100 | int fdt_subnode_offset_namelen(const void *fdt, int offset, | 132 | int fdt_subnode_offset_namelen(const void *fdt, int offset, |
| 101 | const char *name, int namelen) | 133 | const char *name, int namelen) |
| 102 | { | 134 | { |
| @@ -104,20 +136,16 @@ int fdt_subnode_offset_namelen(const void *fdt, int offset, | |||
| 104 | 136 | ||
| 105 | FDT_CHECK_HEADER(fdt); | 137 | FDT_CHECK_HEADER(fdt); |
| 106 | 138 | ||
| 107 | for (depth = 0, offset = fdt_next_node(fdt, offset, &depth); | 139 | for (depth = 0; |
| 108 | (offset >= 0) && (depth > 0); | 140 | (offset >= 0) && (depth >= 0); |
| 109 | offset = fdt_next_node(fdt, offset, &depth)) { | 141 | offset = fdt_next_node(fdt, offset, &depth)) |
| 110 | if (depth < 0) | 142 | if ((depth == 1) |
| 111 | return -FDT_ERR_NOTFOUND; | 143 | && _fdt_nodename_eq(fdt, offset, name, namelen)) |
| 112 | else if ((depth == 1) | ||
| 113 | && _fdt_nodename_eq(fdt, offset, name, namelen)) | ||
| 114 | return offset; | 144 | return offset; |
| 115 | } | ||
| 116 | 145 | ||
| 117 | if (offset < 0) | 146 | if (depth < 0) |
| 118 | return offset; /* error */ | ||
| 119 | else | ||
| 120 | return -FDT_ERR_NOTFOUND; | 147 | return -FDT_ERR_NOTFOUND; |
| 148 | return offset; /* error */ | ||
| 121 | } | 149 | } |
| 122 | 150 | ||
| 123 | int fdt_subnode_offset(const void *fdt, int parentoffset, | 151 | int fdt_subnode_offset(const void *fdt, int parentoffset, |
| @@ -134,8 +162,20 @@ int fdt_path_offset(const void *fdt, const char *path) | |||
| 134 | 162 | ||
| 135 | FDT_CHECK_HEADER(fdt); | 163 | FDT_CHECK_HEADER(fdt); |
| 136 | 164 | ||
| 137 | if (*path != '/') | 165 | /* see if we have an alias */ |
| 138 | return -FDT_ERR_BADPATH; | 166 | if (*path != '/') { |
| 167 | const char *q = strchr(path, '/'); | ||
| 168 | |||
| 169 | if (!q) | ||
| 170 | q = end; | ||
| 171 | |||
| 172 | p = fdt_get_alias_namelen(fdt, p, q - p); | ||
| 173 | if (!p) | ||
| 174 | return -FDT_ERR_BADPATH; | ||
| 175 | offset = fdt_path_offset(fdt, p); | ||
| 176 | |||
| 177 | p = q; | ||
| 178 | } | ||
| 139 | 179 | ||
| 140 | while (*p) { | 180 | while (*p) { |
| 141 | const char *q; | 181 | const char *q; |
| @@ -178,93 +218,142 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) | |||
| 178 | return NULL; | 218 | return NULL; |
| 179 | } | 219 | } |
| 180 | 220 | ||
| 181 | const struct fdt_property *fdt_get_property(const void *fdt, | 221 | int fdt_first_property_offset(const void *fdt, int nodeoffset) |
| 182 | int nodeoffset, | 222 | { |
| 183 | const char *name, int *lenp) | 223 | int offset; |
| 224 | |||
| 225 | if ((offset = _fdt_check_node_offset(fdt, nodeoffset)) < 0) | ||
| 226 | return offset; | ||
| 227 | |||
| 228 | return _nextprop(fdt, offset); | ||
| 229 | } | ||
| 230 | |||
| 231 | int fdt_next_property_offset(const void *fdt, int offset) | ||
| 232 | { | ||
| 233 | if ((offset = _fdt_check_prop_offset(fdt, offset)) < 0) | ||
| 234 | return offset; | ||
| 235 | |||
| 236 | return _nextprop(fdt, offset); | ||
| 237 | } | ||
| 238 | |||
| 239 | const struct fdt_property *fdt_get_property_by_offset(const void *fdt, | ||
| 240 | int offset, | ||
| 241 | int *lenp) | ||
| 184 | { | 242 | { |
| 185 | uint32_t tag; | ||
| 186 | const struct fdt_property *prop; | ||
| 187 | int namestroff; | ||
| 188 | int offset, nextoffset; | ||
| 189 | int err; | 243 | int err; |
| 244 | const struct fdt_property *prop; | ||
| 190 | 245 | ||
| 191 | if (((err = fdt_check_header(fdt)) != 0) | 246 | if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) { |
| 192 | || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0)) | 247 | if (lenp) |
| 193 | goto fail; | 248 | *lenp = err; |
| 249 | return NULL; | ||
| 250 | } | ||
| 194 | 251 | ||
| 195 | nextoffset = err; | 252 | prop = _fdt_offset_ptr(fdt, offset); |
| 196 | do { | ||
| 197 | offset = nextoffset; | ||
| 198 | 253 | ||
| 199 | tag = fdt_next_tag(fdt, offset, &nextoffset); | 254 | if (lenp) |
| 200 | switch (tag) { | 255 | *lenp = fdt32_to_cpu(prop->len); |
| 201 | case FDT_END: | ||
| 202 | err = -FDT_ERR_TRUNCATED; | ||
| 203 | goto fail; | ||
| 204 | 256 | ||
| 205 | case FDT_BEGIN_NODE: | 257 | return prop; |
| 206 | case FDT_END_NODE: | 258 | } |
| 207 | case FDT_NOP: | ||
| 208 | break; | ||
| 209 | 259 | ||
| 210 | case FDT_PROP: | 260 | const struct fdt_property *fdt_get_property_namelen(const void *fdt, |
| 211 | err = -FDT_ERR_BADSTRUCTURE; | 261 | int offset, |
| 212 | prop = fdt_offset_ptr(fdt, offset, sizeof(*prop)); | 262 | const char *name, |
| 213 | if (! prop) | 263 | int namelen, int *lenp) |
| 214 | goto fail; | 264 | { |
| 215 | namestroff = fdt32_to_cpu(prop->nameoff); | 265 | for (offset = fdt_first_property_offset(fdt, offset); |
| 216 | if (strcmp(fdt_string(fdt, namestroff), name) == 0) { | 266 | (offset >= 0); |
| 217 | /* Found it! */ | 267 | (offset = fdt_next_property_offset(fdt, offset))) { |
| 218 | int len = fdt32_to_cpu(prop->len); | 268 | const struct fdt_property *prop; |
| 219 | prop = fdt_offset_ptr(fdt, offset, | ||
| 220 | sizeof(*prop)+len); | ||
| 221 | if (! prop) | ||
| 222 | goto fail; | ||
| 223 | |||
| 224 | if (lenp) | ||
| 225 | *lenp = len; | ||
| 226 | |||
| 227 | return prop; | ||
| 228 | } | ||
| 229 | break; | ||
| 230 | 269 | ||
| 231 | default: | 270 | if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) { |
| 232 | err = -FDT_ERR_BADSTRUCTURE; | 271 | offset = -FDT_ERR_INTERNAL; |
| 233 | goto fail; | 272 | break; |
| 234 | } | 273 | } |
| 235 | } while ((tag != FDT_BEGIN_NODE) && (tag != FDT_END_NODE)); | 274 | if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff), |
| 275 | name, namelen)) | ||
| 276 | return prop; | ||
| 277 | } | ||
| 236 | 278 | ||
| 237 | err = -FDT_ERR_NOTFOUND; | ||
| 238 | fail: | ||
| 239 | if (lenp) | 279 | if (lenp) |
| 240 | *lenp = err; | 280 | *lenp = offset; |
| 241 | return NULL; | 281 | return NULL; |
| 242 | } | 282 | } |
| 243 | 283 | ||
| 244 | const void *fdt_getprop(const void *fdt, int nodeoffset, | 284 | const struct fdt_property *fdt_get_property(const void *fdt, |
| 245 | const char *name, int *lenp) | 285 | int nodeoffset, |
| 286 | const char *name, int *lenp) | ||
| 287 | { | ||
| 288 | return fdt_get_property_namelen(fdt, nodeoffset, name, | ||
| 289 | strlen(name), lenp); | ||
| 290 | } | ||
| 291 | |||
| 292 | const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, | ||
| 293 | const char *name, int namelen, int *lenp) | ||
| 246 | { | 294 | { |
| 247 | const struct fdt_property *prop; | 295 | const struct fdt_property *prop; |
| 248 | 296 | ||
| 249 | prop = fdt_get_property(fdt, nodeoffset, name, lenp); | 297 | prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp); |
| 250 | if (! prop) | 298 | if (! prop) |
| 251 | return NULL; | 299 | return NULL; |
| 252 | 300 | ||
| 253 | return prop->data; | 301 | return prop->data; |
| 254 | } | 302 | } |
| 255 | 303 | ||
| 304 | const void *fdt_getprop_by_offset(const void *fdt, int offset, | ||
| 305 | const char **namep, int *lenp) | ||
| 306 | { | ||
| 307 | const struct fdt_property *prop; | ||
| 308 | |||
| 309 | prop = fdt_get_property_by_offset(fdt, offset, lenp); | ||
| 310 | if (!prop) | ||
| 311 | return NULL; | ||
| 312 | if (namep) | ||
| 313 | *namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff)); | ||
| 314 | return prop->data; | ||
| 315 | } | ||
| 316 | |||
| 317 | const void *fdt_getprop(const void *fdt, int nodeoffset, | ||
| 318 | const char *name, int *lenp) | ||
| 319 | { | ||
| 320 | return fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), lenp); | ||
| 321 | } | ||
| 322 | |||
| 256 | uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) | 323 | uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) |
| 257 | { | 324 | { |
| 258 | const uint32_t *php; | 325 | const uint32_t *php; |
| 259 | int len; | 326 | int len; |
| 260 | 327 | ||
| 261 | php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len); | 328 | /* FIXME: This is a bit sub-optimal, since we potentially scan |
| 262 | if (!php || (len != sizeof(*php))) | 329 | * over all the properties twice. */ |
| 263 | return 0; | 330 | php = fdt_getprop(fdt, nodeoffset, "phandle", &len); |
| 331 | if (!php || (len != sizeof(*php))) { | ||
| 332 | php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len); | ||
| 333 | if (!php || (len != sizeof(*php))) | ||
| 334 | return 0; | ||
| 335 | } | ||
| 264 | 336 | ||
| 265 | return fdt32_to_cpu(*php); | 337 | return fdt32_to_cpu(*php); |
| 266 | } | 338 | } |
| 267 | 339 | ||
| 340 | const char *fdt_get_alias_namelen(const void *fdt, | ||
| 341 | const char *name, int namelen) | ||
| 342 | { | ||
| 343 | int aliasoffset; | ||
| 344 | |||
| 345 | aliasoffset = fdt_path_offset(fdt, "/aliases"); | ||
| 346 | if (aliasoffset < 0) | ||
| 347 | return NULL; | ||
| 348 | |||
| 349 | return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL); | ||
| 350 | } | ||
| 351 | |||
| 352 | const char *fdt_get_alias(const void *fdt, const char *name) | ||
| 353 | { | ||
| 354 | return fdt_get_alias_namelen(fdt, name, strlen(name)); | ||
| 355 | } | ||
| 356 | |||
| 268 | int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) | 357 | int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) |
| 269 | { | 358 | { |
| 270 | int pdepth = 0, p = 0; | 359 | int pdepth = 0, p = 0; |
| @@ -279,9 +368,6 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) | |||
| 279 | for (offset = 0, depth = 0; | 368 | for (offset = 0, depth = 0; |
| 280 | (offset >= 0) && (offset <= nodeoffset); | 369 | (offset >= 0) && (offset <= nodeoffset); |
| 281 | offset = fdt_next_node(fdt, offset, &depth)) { | 370 | offset = fdt_next_node(fdt, offset, &depth)) { |
| 282 | if (pdepth < depth) | ||
| 283 | continue; /* overflowed buffer */ | ||
| 284 | |||
| 285 | while (pdepth > depth) { | 371 | while (pdepth > depth) { |
| 286 | do { | 372 | do { |
| 287 | p--; | 373 | p--; |
| @@ -289,14 +375,16 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) | |||
| 289 | pdepth--; | 375 | pdepth--; |
| 290 | } | 376 | } |
| 291 | 377 | ||
| 292 | name = fdt_get_name(fdt, offset, &namelen); | 378 | if (pdepth >= depth) { |
| 293 | if (!name) | 379 | name = fdt_get_name(fdt, offset, &namelen); |
| 294 | return namelen; | 380 | if (!name) |
| 295 | if ((p + namelen + 1) <= buflen) { | 381 | return namelen; |
| 296 | memcpy(buf + p, name, namelen); | 382 | if ((p + namelen + 1) <= buflen) { |
| 297 | p += namelen; | 383 | memcpy(buf + p, name, namelen); |
| 298 | buf[p++] = '/'; | 384 | p += namelen; |
| 299 | pdepth++; | 385 | buf[p++] = '/'; |
| 386 | pdepth++; | ||
| 387 | } | ||
| 300 | } | 388 | } |
| 301 | 389 | ||
| 302 | if (offset == nodeoffset) { | 390 | if (offset == nodeoffset) { |
| @@ -306,7 +394,7 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) | |||
| 306 | if (p > 1) /* special case so that root path is "/", not "" */ | 394 | if (p > 1) /* special case so that root path is "/", not "" */ |
| 307 | p--; | 395 | p--; |
| 308 | buf[p] = '\0'; | 396 | buf[p] = '\0'; |
| 309 | return p; | 397 | return 0; |
| 310 | } | 398 | } |
| 311 | } | 399 | } |
| 312 | 400 | ||
| @@ -404,14 +492,31 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, | |||
| 404 | 492 | ||
| 405 | int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) | 493 | int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) |
| 406 | { | 494 | { |
| 495 | int offset; | ||
| 496 | |||
| 407 | if ((phandle == 0) || (phandle == -1)) | 497 | if ((phandle == 0) || (phandle == -1)) |
| 408 | return -FDT_ERR_BADPHANDLE; | 498 | return -FDT_ERR_BADPHANDLE; |
| 409 | phandle = cpu_to_fdt32(phandle); | 499 | |
| 410 | return fdt_node_offset_by_prop_value(fdt, -1, "linux,phandle", | 500 | FDT_CHECK_HEADER(fdt); |
| 411 | &phandle, sizeof(phandle)); | 501 | |
| 502 | /* FIXME: The algorithm here is pretty horrible: we | ||
| 503 | * potentially scan each property of a node in | ||
| 504 | * fdt_get_phandle(), then if that didn't find what | ||
| 505 | * we want, we scan over them again making our way to the next | ||
| 506 | * node. Still it's the easiest to implement approach; | ||
| 507 | * performance can come later. */ | ||
| 508 | for (offset = fdt_next_node(fdt, -1, NULL); | ||
| 509 | offset >= 0; | ||
| 510 | offset = fdt_next_node(fdt, offset, NULL)) { | ||
| 511 | if (fdt_get_phandle(fdt, offset) == phandle) | ||
| 512 | return offset; | ||
| 513 | } | ||
| 514 | |||
| 515 | return offset; /* error from fdt_next_node() */ | ||
| 412 | } | 516 | } |
| 413 | 517 | ||
| 414 | static int _stringlist_contains(const char *strlist, int listlen, const char *str) | 518 | static int _fdt_stringlist_contains(const char *strlist, int listlen, |
| 519 | const char *str) | ||
| 415 | { | 520 | { |
| 416 | int len = strlen(str); | 521 | int len = strlen(str); |
| 417 | const char *p; | 522 | const char *p; |
| @@ -437,7 +542,7 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset, | |||
| 437 | prop = fdt_getprop(fdt, nodeoffset, "compatible", &len); | 542 | prop = fdt_getprop(fdt, nodeoffset, "compatible", &len); |
| 438 | if (!prop) | 543 | if (!prop) |
| 439 | return len; | 544 | return len; |
| 440 | if (_stringlist_contains(prop, len, compatible)) | 545 | if (_fdt_stringlist_contains(prop, len, compatible)) |
| 441 | return 0; | 546 | return 0; |
| 442 | else | 547 | else |
| 443 | return 1; | 548 | return 1; |
diff --git a/scripts/dtc/libfdt/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c index 8e7ec4cb7bcd..24437dfc32b8 100644 --- a/scripts/dtc/libfdt/fdt_rw.c +++ b/scripts/dtc/libfdt/fdt_rw.c | |||
| @@ -289,6 +289,33 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name, | |||
| 289 | return 0; | 289 | return 0; |
| 290 | } | 290 | } |
| 291 | 291 | ||
| 292 | int fdt_appendprop(void *fdt, int nodeoffset, const char *name, | ||
| 293 | const void *val, int len) | ||
| 294 | { | ||
| 295 | struct fdt_property *prop; | ||
| 296 | int err, oldlen, newlen; | ||
| 297 | |||
| 298 | FDT_RW_CHECK_HEADER(fdt); | ||
| 299 | |||
| 300 | prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); | ||
| 301 | if (prop) { | ||
| 302 | newlen = len + oldlen; | ||
| 303 | err = _fdt_splice_struct(fdt, prop->data, | ||
| 304 | FDT_TAGALIGN(oldlen), | ||
| 305 | FDT_TAGALIGN(newlen)); | ||
| 306 | if (err) | ||
| 307 | return err; | ||
| 308 | prop->len = cpu_to_fdt32(newlen); | ||
| 309 | memcpy(prop->data + oldlen, val, len); | ||
| 310 | } else { | ||
| 311 | err = _fdt_add_property(fdt, nodeoffset, name, len, &prop); | ||
| 312 | if (err) | ||
| 313 | return err; | ||
| 314 | memcpy(prop->data, val, len); | ||
| 315 | } | ||
| 316 | return 0; | ||
| 317 | } | ||
| 318 | |||
| 292 | int fdt_delprop(void *fdt, int nodeoffset, const char *name) | 319 | int fdt_delprop(void *fdt, int nodeoffset, const char *name) |
| 293 | { | 320 | { |
| 294 | struct fdt_property *prop; | 321 | struct fdt_property *prop; |
| @@ -406,6 +433,8 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize) | |||
| 406 | struct_size = 0; | 433 | struct_size = 0; |
| 407 | while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END) | 434 | while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END) |
| 408 | ; | 435 | ; |
| 436 | if (struct_size < 0) | ||
| 437 | return struct_size; | ||
| 409 | } | 438 | } |
| 410 | 439 | ||
| 411 | if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) { | 440 | if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) { |
diff --git a/scripts/dtc/libfdt/fdt_sw.c b/scripts/dtc/libfdt/fdt_sw.c index 698329e0ccaf..55ebebf1eb20 100644 --- a/scripts/dtc/libfdt/fdt_sw.c +++ b/scripts/dtc/libfdt/fdt_sw.c | |||
| @@ -70,7 +70,7 @@ static int _fdt_sw_check_header(void *fdt) | |||
| 70 | return err; \ | 70 | return err; \ |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | static void *_fdt_grab_space(void *fdt, int len) | 73 | static void *_fdt_grab_space(void *fdt, size_t len) |
| 74 | { | 74 | { |
| 75 | int offset = fdt_size_dt_struct(fdt); | 75 | int offset = fdt_size_dt_struct(fdt); |
| 76 | int spaceleft; | 76 | int spaceleft; |
| @@ -82,7 +82,7 @@ static void *_fdt_grab_space(void *fdt, int len) | |||
| 82 | return NULL; | 82 | return NULL; |
| 83 | 83 | ||
| 84 | fdt_set_size_dt_struct(fdt, offset + len); | 84 | fdt_set_size_dt_struct(fdt, offset + len); |
| 85 | return fdt_offset_ptr_w(fdt, offset, len); | 85 | return _fdt_offset_ptr_w(fdt, offset); |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | int fdt_create(void *buf, int bufsize) | 88 | int fdt_create(void *buf, int bufsize) |
| @@ -237,18 +237,17 @@ int fdt_finish(void *fdt) | |||
| 237 | while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) { | 237 | while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) { |
| 238 | if (tag == FDT_PROP) { | 238 | if (tag == FDT_PROP) { |
| 239 | struct fdt_property *prop = | 239 | struct fdt_property *prop = |
| 240 | fdt_offset_ptr_w(fdt, offset, sizeof(*prop)); | 240 | _fdt_offset_ptr_w(fdt, offset); |
| 241 | int nameoff; | 241 | int nameoff; |
| 242 | 242 | ||
| 243 | if (! prop) | ||
| 244 | return -FDT_ERR_BADSTRUCTURE; | ||
| 245 | |||
| 246 | nameoff = fdt32_to_cpu(prop->nameoff); | 243 | nameoff = fdt32_to_cpu(prop->nameoff); |
| 247 | nameoff += fdt_size_dt_strings(fdt); | 244 | nameoff += fdt_size_dt_strings(fdt); |
| 248 | prop->nameoff = cpu_to_fdt32(nameoff); | 245 | prop->nameoff = cpu_to_fdt32(nameoff); |
| 249 | } | 246 | } |
| 250 | offset = nextoffset; | 247 | offset = nextoffset; |
| 251 | } | 248 | } |
| 249 | if (nextoffset < 0) | ||
| 250 | return nextoffset; | ||
| 252 | 251 | ||
| 253 | /* Finally, adjust the header */ | 252 | /* Finally, adjust the header */ |
| 254 | fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt)); | 253 | fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt)); |
diff --git a/scripts/dtc/libfdt/fdt_wip.c b/scripts/dtc/libfdt/fdt_wip.c index a4652c6e787e..6025fa1fe8fe 100644 --- a/scripts/dtc/libfdt/fdt_wip.c +++ b/scripts/dtc/libfdt/fdt_wip.c | |||
| @@ -94,41 +94,14 @@ int fdt_nop_property(void *fdt, int nodeoffset, const char *name) | |||
| 94 | return 0; | 94 | return 0; |
| 95 | } | 95 | } |
| 96 | 96 | ||
| 97 | int _fdt_node_end_offset(void *fdt, int nodeoffset) | 97 | int _fdt_node_end_offset(void *fdt, int offset) |
| 98 | { | 98 | { |
| 99 | int level = 0; | 99 | int depth = 0; |
| 100 | uint32_t tag; | 100 | |
| 101 | int offset, nextoffset; | 101 | while ((offset >= 0) && (depth >= 0)) |
| 102 | 102 | offset = fdt_next_node(fdt, offset, &depth); | |
| 103 | tag = fdt_next_tag(fdt, nodeoffset, &nextoffset); | 103 | |
| 104 | if (tag != FDT_BEGIN_NODE) | 104 | return offset; |
| 105 | return -FDT_ERR_BADOFFSET; | ||
| 106 | do { | ||
| 107 | offset = nextoffset; | ||
| 108 | tag = fdt_next_tag(fdt, offset, &nextoffset); | ||
| 109 | |||
| 110 | switch (tag) { | ||
| 111 | case FDT_END: | ||
| 112 | return offset; | ||
| 113 | |||
| 114 | case FDT_BEGIN_NODE: | ||
| 115 | level++; | ||
| 116 | break; | ||
| 117 | |||
| 118 | case FDT_END_NODE: | ||
| 119 | level--; | ||
| 120 | break; | ||
| 121 | |||
| 122 | case FDT_PROP: | ||
| 123 | case FDT_NOP: | ||
| 124 | break; | ||
| 125 | |||
| 126 | default: | ||
| 127 | return -FDT_ERR_BADSTRUCTURE; | ||
| 128 | } | ||
| 129 | } while (level >= 0); | ||
| 130 | |||
| 131 | return nextoffset; | ||
| 132 | } | 105 | } |
| 133 | 106 | ||
| 134 | int fdt_nop_node(void *fdt, int nodeoffset) | 107 | int fdt_nop_node(void *fdt, int nodeoffset) |
diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h index ff6246f000ce..73f49759a5e7 100644 --- a/scripts/dtc/libfdt/libfdt.h +++ b/scripts/dtc/libfdt/libfdt.h | |||
| @@ -61,7 +61,7 @@ | |||
| 61 | #define FDT_ERR_NOTFOUND 1 | 61 | #define FDT_ERR_NOTFOUND 1 |
| 62 | /* FDT_ERR_NOTFOUND: The requested node or property does not exist */ | 62 | /* FDT_ERR_NOTFOUND: The requested node or property does not exist */ |
| 63 | #define FDT_ERR_EXISTS 2 | 63 | #define FDT_ERR_EXISTS 2 |
| 64 | /* FDT_ERR_EXISTS: Attempted to create a node or property which | 64 | /* FDT_ERR_EXISTS: Attemped to create a node or property which |
| 65 | * already exists */ | 65 | * already exists */ |
| 66 | #define FDT_ERR_NOSPACE 3 | 66 | #define FDT_ERR_NOSPACE 3 |
| 67 | /* FDT_ERR_NOSPACE: Operation needed to expand the device | 67 | /* FDT_ERR_NOSPACE: Operation needed to expand the device |
| @@ -122,7 +122,7 @@ | |||
| 122 | /* Low-level functions (you probably don't need these) */ | 122 | /* Low-level functions (you probably don't need these) */ |
| 123 | /**********************************************************************/ | 123 | /**********************************************************************/ |
| 124 | 124 | ||
| 125 | const void *fdt_offset_ptr(const void *fdt, int offset, int checklen); | 125 | const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen); |
| 126 | static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen) | 126 | static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen) |
| 127 | { | 127 | { |
| 128 | return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen); | 128 | return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen); |
| @@ -156,7 +156,7 @@ int fdt_next_node(const void *fdt, int offset, int *depth); | |||
| 156 | #define __fdt_set_hdr(name) \ | 156 | #define __fdt_set_hdr(name) \ |
| 157 | static inline void fdt_set_##name(void *fdt, uint32_t val) \ | 157 | static inline void fdt_set_##name(void *fdt, uint32_t val) \ |
| 158 | { \ | 158 | { \ |
| 159 | struct fdt_header *fdth = fdt; \ | 159 | struct fdt_header *fdth = (struct fdt_header*)fdt; \ |
| 160 | fdth->name = cpu_to_fdt32(val); \ | 160 | fdth->name = cpu_to_fdt32(val); \ |
| 161 | } | 161 | } |
| 162 | __fdt_set_hdr(magic); | 162 | __fdt_set_hdr(magic); |
| @@ -343,6 +343,91 @@ int fdt_path_offset(const void *fdt, const char *path); | |||
| 343 | const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp); | 343 | const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp); |
| 344 | 344 | ||
| 345 | /** | 345 | /** |
| 346 | * fdt_first_property_offset - find the offset of a node's first property | ||
| 347 | * @fdt: pointer to the device tree blob | ||
| 348 | * @nodeoffset: structure block offset of a node | ||
| 349 | * | ||
| 350 | * fdt_first_property_offset() finds the first property of the node at | ||
| 351 | * the given structure block offset. | ||
| 352 | * | ||
| 353 | * returns: | ||
| 354 | * structure block offset of the property (>=0), on success | ||
| 355 | * -FDT_ERR_NOTFOUND, if the requested node has no properties | ||
| 356 | * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_BEGIN_NODE tag | ||
| 357 | * -FDT_ERR_BADMAGIC, | ||
| 358 | * -FDT_ERR_BADVERSION, | ||
| 359 | * -FDT_ERR_BADSTATE, | ||
| 360 | * -FDT_ERR_BADSTRUCTURE, | ||
| 361 | * -FDT_ERR_TRUNCATED, standard meanings. | ||
| 362 | */ | ||
| 363 | int fdt_first_property_offset(const void *fdt, int nodeoffset); | ||
| 364 | |||
| 365 | /** | ||
| 366 | * fdt_next_property_offset - step through a node's properties | ||
| 367 | * @fdt: pointer to the device tree blob | ||
| 368 | * @offset: structure block offset of a property | ||
| 369 | * | ||
| 370 | * fdt_next_property_offset() finds the property immediately after the | ||
| 371 | * one at the given structure block offset. This will be a property | ||
| 372 | * of the same node as the given property. | ||
| 373 | * | ||
| 374 | * returns: | ||
| 375 | * structure block offset of the next property (>=0), on success | ||
| 376 | * -FDT_ERR_NOTFOUND, if the given property is the last in its node | ||
| 377 | * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_PROP tag | ||
| 378 | * -FDT_ERR_BADMAGIC, | ||
| 379 | * -FDT_ERR_BADVERSION, | ||
| 380 | * -FDT_ERR_BADSTATE, | ||
| 381 | * -FDT_ERR_BADSTRUCTURE, | ||
| 382 | * -FDT_ERR_TRUNCATED, standard meanings. | ||
| 383 | */ | ||
| 384 | int fdt_next_property_offset(const void *fdt, int offset); | ||
| 385 | |||
| 386 | /** | ||
| 387 | * fdt_get_property_by_offset - retrieve the property at a given offset | ||
| 388 | * @fdt: pointer to the device tree blob | ||
| 389 | * @offset: offset of the property to retrieve | ||
| 390 | * @lenp: pointer to an integer variable (will be overwritten) or NULL | ||
| 391 | * | ||
| 392 | * fdt_get_property_by_offset() retrieves a pointer to the | ||
| 393 | * fdt_property structure within the device tree blob at the given | ||
| 394 | * offset. If lenp is non-NULL, the length of the property value is | ||
| 395 | * also returned, in the integer pointed to by lenp. | ||
| 396 | * | ||
| 397 | * returns: | ||
| 398 | * pointer to the structure representing the property | ||
| 399 | * if lenp is non-NULL, *lenp contains the length of the property | ||
| 400 | * value (>=0) | ||
| 401 | * NULL, on error | ||
| 402 | * if lenp is non-NULL, *lenp contains an error code (<0): | ||
| 403 | * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag | ||
| 404 | * -FDT_ERR_BADMAGIC, | ||
| 405 | * -FDT_ERR_BADVERSION, | ||
| 406 | * -FDT_ERR_BADSTATE, | ||
| 407 | * -FDT_ERR_BADSTRUCTURE, | ||
| 408 | * -FDT_ERR_TRUNCATED, standard meanings | ||
| 409 | */ | ||
| 410 | const struct fdt_property *fdt_get_property_by_offset(const void *fdt, | ||
| 411 | int offset, | ||
| 412 | int *lenp); | ||
| 413 | |||
| 414 | /** | ||
| 415 | * fdt_get_property_namelen - find a property based on substring | ||
| 416 | * @fdt: pointer to the device tree blob | ||
| 417 | * @nodeoffset: offset of the node whose property to find | ||
| 418 | * @name: name of the property to find | ||
| 419 | * @namelen: number of characters of name to consider | ||
| 420 | * @lenp: pointer to an integer variable (will be overwritten) or NULL | ||
| 421 | * | ||
| 422 | * Identical to fdt_get_property_namelen(), but only examine the first | ||
| 423 | * namelen characters of name for matching the property name. | ||
| 424 | */ | ||
| 425 | const struct fdt_property *fdt_get_property_namelen(const void *fdt, | ||
| 426 | int nodeoffset, | ||
| 427 | const char *name, | ||
| 428 | int namelen, int *lenp); | ||
| 429 | |||
| 430 | /** | ||
| 346 | * fdt_get_property - find a given property in a given node | 431 | * fdt_get_property - find a given property in a given node |
| 347 | * @fdt: pointer to the device tree blob | 432 | * @fdt: pointer to the device tree blob |
| 348 | * @nodeoffset: offset of the node whose property to find | 433 | * @nodeoffset: offset of the node whose property to find |
| @@ -380,6 +465,54 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset, | |||
| 380 | } | 465 | } |
| 381 | 466 | ||
| 382 | /** | 467 | /** |
| 468 | * fdt_getprop_by_offset - retrieve the value of a property at a given offset | ||
| 469 | * @fdt: pointer to the device tree blob | ||
| 470 | * @ffset: offset of the property to read | ||
| 471 | * @namep: pointer to a string variable (will be overwritten) or NULL | ||
| 472 | * @lenp: pointer to an integer variable (will be overwritten) or NULL | ||
| 473 | * | ||
| 474 | * fdt_getprop_by_offset() retrieves a pointer to the value of the | ||
| 475 | * property at structure block offset 'offset' (this will be a pointer | ||
| 476 | * to within the device blob itself, not a copy of the value). If | ||
| 477 | * lenp is non-NULL, the length of the property value is also | ||
| 478 | * returned, in the integer pointed to by lenp. If namep is non-NULL, | ||
| 479 | * the property's namne will also be returned in the char * pointed to | ||
| 480 | * by namep (this will be a pointer to within the device tree's string | ||
| 481 | * block, not a new copy of the name). | ||
| 482 | * | ||
| 483 | * returns: | ||
| 484 | * pointer to the property's value | ||
| 485 | * if lenp is non-NULL, *lenp contains the length of the property | ||
| 486 | * value (>=0) | ||
| 487 | * if namep is non-NULL *namep contiains a pointer to the property | ||
| 488 | * name. | ||
| 489 | * NULL, on error | ||
| 490 | * if lenp is non-NULL, *lenp contains an error code (<0): | ||
| 491 | * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag | ||
| 492 | * -FDT_ERR_BADMAGIC, | ||
| 493 | * -FDT_ERR_BADVERSION, | ||
| 494 | * -FDT_ERR_BADSTATE, | ||
| 495 | * -FDT_ERR_BADSTRUCTURE, | ||
| 496 | * -FDT_ERR_TRUNCATED, standard meanings | ||
| 497 | */ | ||
| 498 | const void *fdt_getprop_by_offset(const void *fdt, int offset, | ||
| 499 | const char **namep, int *lenp); | ||
| 500 | |||
| 501 | /** | ||
| 502 | * fdt_getprop_namelen - get property value based on substring | ||
| 503 | * @fdt: pointer to the device tree blob | ||
| 504 | * @nodeoffset: offset of the node whose property to find | ||
| 505 | * @name: name of the property to find | ||
| 506 | * @namelen: number of characters of name to consider | ||
| 507 | * @lenp: pointer to an integer variable (will be overwritten) or NULL | ||
| 508 | * | ||
| 509 | * Identical to fdt_getprop(), but only examine the first namelen | ||
| 510 | * characters of name for matching the property name. | ||
| 511 | */ | ||
| 512 | const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, | ||
| 513 | const char *name, int namelen, int *lenp); | ||
| 514 | |||
| 515 | /** | ||
| 383 | * fdt_getprop - retrieve the value of a given property | 516 | * fdt_getprop - retrieve the value of a given property |
| 384 | * @fdt: pointer to the device tree blob | 517 | * @fdt: pointer to the device tree blob |
| 385 | * @nodeoffset: offset of the node whose property to find | 518 | * @nodeoffset: offset of the node whose property to find |
| @@ -429,6 +562,32 @@ static inline void *fdt_getprop_w(void *fdt, int nodeoffset, | |||
| 429 | uint32_t fdt_get_phandle(const void *fdt, int nodeoffset); | 562 | uint32_t fdt_get_phandle(const void *fdt, int nodeoffset); |
| 430 | 563 | ||
| 431 | /** | 564 | /** |
| 565 | * fdt_get_alias_namelen - get alias based on substring | ||
| 566 | * @fdt: pointer to the device tree blob | ||
| 567 | * @name: name of the alias th look up | ||
| 568 | * @namelen: number of characters of name to consider | ||
| 569 | * | ||
| 570 | * Identical to fdt_get_alias(), but only examine the first namelen | ||
| 571 | * characters of name for matching the alias name. | ||
| 572 | */ | ||
| 573 | const char *fdt_get_alias_namelen(const void *fdt, | ||
| 574 | const char *name, int namelen); | ||
| 575 | |||
| 576 | /** | ||
| 577 | * fdt_get_alias - retreive the path referenced by a given alias | ||
| 578 | * @fdt: pointer to the device tree blob | ||
| 579 | * @name: name of the alias th look up | ||
| 580 | * | ||
| 581 | * fdt_get_alias() retrieves the value of a given alias. That is, the | ||
| 582 | * value of the property named 'name' in the node /aliases. | ||
| 583 | * | ||
| 584 | * returns: | ||
| 585 | * a pointer to the expansion of the alias named 'name', of it exists | ||
| 586 | * NULL, if the given alias or the /aliases node does not exist | ||
| 587 | */ | ||
| 588 | const char *fdt_get_alias(const void *fdt, const char *name); | ||
| 589 | |||
| 590 | /** | ||
| 432 | * fdt_get_path - determine the full path of a node | 591 | * fdt_get_path - determine the full path of a node |
| 433 | * @fdt: pointer to the device tree blob | 592 | * @fdt: pointer to the device tree blob |
| 434 | * @nodeoffset: offset of the node whose path to find | 593 | * @nodeoffset: offset of the node whose path to find |
| @@ -693,17 +852,17 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, | |||
| 693 | const void *val, int len); | 852 | const void *val, int len); |
| 694 | 853 | ||
| 695 | /** | 854 | /** |
| 696 | * fdt_setprop_inplace_cell - change the value of a single-cell property | 855 | * fdt_setprop_inplace_u32 - change the value of a 32-bit integer property |
| 697 | * @fdt: pointer to the device tree blob | 856 | * @fdt: pointer to the device tree blob |
| 698 | * @nodeoffset: offset of the node whose property to change | 857 | * @nodeoffset: offset of the node whose property to change |
| 699 | * @name: name of the property to change | 858 | * @name: name of the property to change |
| 700 | * @val: cell (32-bit integer) value to replace the property with | 859 | * @val: 32-bit integer value to replace the property with |
| 701 | * | 860 | * |
| 702 | * fdt_setprop_inplace_cell() replaces the value of a given property | 861 | * fdt_setprop_inplace_u32() replaces the value of a given property |
| 703 | * with the 32-bit integer cell value in val, converting val to | 862 | * with the 32-bit integer value in val, converting val to big-endian |
| 704 | * big-endian if necessary. This function cannot change the size of a | 863 | * if necessary. This function cannot change the size of a property, |
| 705 | * property, and so will only work if the property already exists and | 864 | * and so will only work if the property already exists and has length |
| 706 | * has length 4. | 865 | * 4. |
| 707 | * | 866 | * |
| 708 | * This function will alter only the bytes in the blob which contain | 867 | * This function will alter only the bytes in the blob which contain |
| 709 | * the given property value, and will not alter or move any other part | 868 | * the given property value, and will not alter or move any other part |
| @@ -712,7 +871,7 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, | |||
| 712 | * returns: | 871 | * returns: |
| 713 | * 0, on success | 872 | * 0, on success |
| 714 | * -FDT_ERR_NOSPACE, if the property's length is not equal to 4 | 873 | * -FDT_ERR_NOSPACE, if the property's length is not equal to 4 |
| 715 | * -FDT_ERR_NOTFOUND, node does not have the named property | 874 | * -FDT_ERR_NOTFOUND, node does not have the named property |
| 716 | * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag | 875 | * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag |
| 717 | * -FDT_ERR_BADMAGIC, | 876 | * -FDT_ERR_BADMAGIC, |
| 718 | * -FDT_ERR_BADVERSION, | 877 | * -FDT_ERR_BADVERSION, |
| @@ -720,14 +879,60 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, | |||
| 720 | * -FDT_ERR_BADSTRUCTURE, | 879 | * -FDT_ERR_BADSTRUCTURE, |
| 721 | * -FDT_ERR_TRUNCATED, standard meanings | 880 | * -FDT_ERR_TRUNCATED, standard meanings |
| 722 | */ | 881 | */ |
| 723 | static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset, | 882 | static inline int fdt_setprop_inplace_u32(void *fdt, int nodeoffset, |
| 724 | const char *name, uint32_t val) | 883 | const char *name, uint32_t val) |
| 725 | { | 884 | { |
| 726 | val = cpu_to_fdt32(val); | 885 | val = cpu_to_fdt32(val); |
| 727 | return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val)); | 886 | return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val)); |
| 728 | } | 887 | } |
| 729 | 888 | ||
| 730 | /** | 889 | /** |
| 890 | * fdt_setprop_inplace_u64 - change the value of a 64-bit integer property | ||
| 891 | * @fdt: pointer to the device tree blob | ||
| 892 | * @nodeoffset: offset of the node whose property to change | ||
| 893 | * @name: name of the property to change | ||
| 894 | * @val: 64-bit integer value to replace the property with | ||
| 895 | * | ||
| 896 | * fdt_setprop_inplace_u64() replaces the value of a given property | ||
| 897 | * with the 64-bit integer value in val, converting val to big-endian | ||
| 898 | * if necessary. This function cannot change the size of a property, | ||
| 899 | * and so will only work if the property already exists and has length | ||
| 900 | * 8. | ||
| 901 | * | ||
| 902 | * This function will alter only the bytes in the blob which contain | ||
| 903 | * the given property value, and will not alter or move any other part | ||
| 904 | * of the tree. | ||
| 905 | * | ||
| 906 | * returns: | ||
| 907 | * 0, on success | ||
| 908 | * -FDT_ERR_NOSPACE, if the property's length is not equal to 8 | ||
| 909 | * -FDT_ERR_NOTFOUND, node does not have the named property | ||
| 910 | * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag | ||
| 911 | * -FDT_ERR_BADMAGIC, | ||
| 912 | * -FDT_ERR_BADVERSION, | ||
| 913 | * -FDT_ERR_BADSTATE, | ||
| 914 | * -FDT_ERR_BADSTRUCTURE, | ||
| 915 | * -FDT_ERR_TRUNCATED, standard meanings | ||
| 916 | */ | ||
| 917 | static inline int fdt_setprop_inplace_u64(void *fdt, int nodeoffset, | ||
| 918 | const char *name, uint64_t val) | ||
| 919 | { | ||
| 920 | val = cpu_to_fdt64(val); | ||
| 921 | return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val)); | ||
| 922 | } | ||
| 923 | |||
| 924 | /** | ||
| 925 | * fdt_setprop_inplace_cell - change the value of a single-cell property | ||
| 926 | * | ||
| 927 | * This is an alternative name for fdt_setprop_inplace_u32() | ||
| 928 | */ | ||
| 929 | static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset, | ||
| 930 | const char *name, uint32_t val) | ||
| 931 | { | ||
| 932 | return fdt_setprop_inplace_u32(fdt, nodeoffset, name, val); | ||
| 933 | } | ||
| 934 | |||
| 935 | /** | ||
| 731 | * fdt_nop_property - replace a property with nop tags | 936 | * fdt_nop_property - replace a property with nop tags |
| 732 | * @fdt: pointer to the device tree blob | 937 | * @fdt: pointer to the device tree blob |
| 733 | * @nodeoffset: offset of the node whose property to nop | 938 | * @nodeoffset: offset of the node whose property to nop |
| @@ -786,11 +991,20 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size); | |||
| 786 | int fdt_finish_reservemap(void *fdt); | 991 | int fdt_finish_reservemap(void *fdt); |
| 787 | int fdt_begin_node(void *fdt, const char *name); | 992 | int fdt_begin_node(void *fdt, const char *name); |
| 788 | int fdt_property(void *fdt, const char *name, const void *val, int len); | 993 | int fdt_property(void *fdt, const char *name, const void *val, int len); |
| 789 | static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val) | 994 | static inline int fdt_property_u32(void *fdt, const char *name, uint32_t val) |
| 790 | { | 995 | { |
| 791 | val = cpu_to_fdt32(val); | 996 | val = cpu_to_fdt32(val); |
| 792 | return fdt_property(fdt, name, &val, sizeof(val)); | 997 | return fdt_property(fdt, name, &val, sizeof(val)); |
| 793 | } | 998 | } |
| 999 | static inline int fdt_property_u64(void *fdt, const char *name, uint64_t val) | ||
| 1000 | { | ||
| 1001 | val = cpu_to_fdt64(val); | ||
| 1002 | return fdt_property(fdt, name, &val, sizeof(val)); | ||
| 1003 | } | ||
| 1004 | static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val) | ||
| 1005 | { | ||
| 1006 | return fdt_property_u32(fdt, name, val); | ||
| 1007 | } | ||
| 794 | #define fdt_property_string(fdt, name, str) \ | 1008 | #define fdt_property_string(fdt, name, str) \ |
| 795 | fdt_property(fdt, name, str, strlen(str)+1) | 1009 | fdt_property(fdt, name, str, strlen(str)+1) |
| 796 | int fdt_end_node(void *fdt); | 1010 | int fdt_end_node(void *fdt); |
| @@ -800,6 +1014,7 @@ int fdt_finish(void *fdt); | |||
| 800 | /* Read-write functions */ | 1014 | /* Read-write functions */ |
| 801 | /**********************************************************************/ | 1015 | /**********************************************************************/ |
| 802 | 1016 | ||
| 1017 | int fdt_create_empty_tree(void *buf, int bufsize); | ||
| 803 | int fdt_open_into(const void *fdt, void *buf, int bufsize); | 1018 | int fdt_open_into(const void *fdt, void *buf, int bufsize); |
| 804 | int fdt_pack(void *fdt); | 1019 | int fdt_pack(void *fdt); |
| 805 | 1020 | ||
| @@ -909,14 +1124,14 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name, | |||
| 909 | const void *val, int len); | 1124 | const void *val, int len); |
| 910 | 1125 | ||
| 911 | /** | 1126 | /** |
| 912 | * fdt_setprop_cell - set a property to a single cell value | 1127 | * fdt_setprop_u32 - set a property to a 32-bit integer |
| 913 | * @fdt: pointer to the device tree blob | 1128 | * @fdt: pointer to the device tree blob |
| 914 | * @nodeoffset: offset of the node whose property to change | 1129 | * @nodeoffset: offset of the node whose property to change |
| 915 | * @name: name of the property to change | 1130 | * @name: name of the property to change |
| 916 | * @val: 32-bit integer value for the property (native endian) | 1131 | * @val: 32-bit integer value for the property (native endian) |
| 917 | * | 1132 | * |
| 918 | * fdt_setprop_cell() sets the value of the named property in the | 1133 | * fdt_setprop_u32() sets the value of the named property in the given |
| 919 | * given node to the given cell value (converting to big-endian if | 1134 | * node to the given 32-bit integer value (converting to big-endian if |
| 920 | * necessary), or creates a new property with that value if it does | 1135 | * necessary), or creates a new property with that value if it does |
| 921 | * not already exist. | 1136 | * not already exist. |
| 922 | * | 1137 | * |
| @@ -936,14 +1151,60 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name, | |||
| 936 | * -FDT_ERR_BADLAYOUT, | 1151 | * -FDT_ERR_BADLAYOUT, |
| 937 | * -FDT_ERR_TRUNCATED, standard meanings | 1152 | * -FDT_ERR_TRUNCATED, standard meanings |
| 938 | */ | 1153 | */ |
| 939 | static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name, | 1154 | static inline int fdt_setprop_u32(void *fdt, int nodeoffset, const char *name, |
| 940 | uint32_t val) | 1155 | uint32_t val) |
| 941 | { | 1156 | { |
| 942 | val = cpu_to_fdt32(val); | 1157 | val = cpu_to_fdt32(val); |
| 943 | return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val)); | 1158 | return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val)); |
| 944 | } | 1159 | } |
| 945 | 1160 | ||
| 946 | /** | 1161 | /** |
| 1162 | * fdt_setprop_u64 - set a property to a 64-bit integer | ||
| 1163 | * @fdt: pointer to the device tree blob | ||
| 1164 | * @nodeoffset: offset of the node whose property to change | ||
| 1165 | * @name: name of the property to change | ||
| 1166 | * @val: 64-bit integer value for the property (native endian) | ||
| 1167 | * | ||
| 1168 | * fdt_setprop_u64() sets the value of the named property in the given | ||
| 1169 | * node to the given 64-bit integer value (converting to big-endian if | ||
| 1170 | * necessary), or creates a new property with that value if it does | ||
| 1171 | * not already exist. | ||
| 1172 | * | ||
| 1173 | * This function may insert or delete data from the blob, and will | ||
| 1174 | * therefore change the offsets of some existing nodes. | ||
| 1175 | * | ||
| 1176 | * returns: | ||
| 1177 | * 0, on success | ||
| 1178 | * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to | ||
| 1179 | * contain the new property value | ||
| 1180 | * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag | ||
| 1181 | * -FDT_ERR_BADLAYOUT, | ||
| 1182 | * -FDT_ERR_BADMAGIC, | ||
| 1183 | * -FDT_ERR_BADVERSION, | ||
| 1184 | * -FDT_ERR_BADSTATE, | ||
| 1185 | * -FDT_ERR_BADSTRUCTURE, | ||
| 1186 | * -FDT_ERR_BADLAYOUT, | ||
| 1187 | * -FDT_ERR_TRUNCATED, standard meanings | ||
| 1188 | */ | ||
| 1189 | static inline int fdt_setprop_u64(void *fdt, int nodeoffset, const char *name, | ||
| 1190 | uint64_t val) | ||
| 1191 | { | ||
| 1192 | val = cpu_to_fdt64(val); | ||
| 1193 | return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val)); | ||
| 1194 | } | ||
| 1195 | |||
| 1196 | /** | ||
| 1197 | * fdt_setprop_cell - set a property to a single cell value | ||
| 1198 | * | ||
| 1199 | * This is an alternative name for fdt_setprop_u32() | ||
| 1200 | */ | ||
| 1201 | static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name, | ||
| 1202 | uint32_t val) | ||
| 1203 | { | ||
| 1204 | return fdt_setprop_u32(fdt, nodeoffset, name, val); | ||
| 1205 | } | ||
| 1206 | |||
| 1207 | /** | ||
| 947 | * fdt_setprop_string - set a property to a string value | 1208 | * fdt_setprop_string - set a property to a string value |
| 948 | * @fdt: pointer to the device tree blob | 1209 | * @fdt: pointer to the device tree blob |
| 949 | * @nodeoffset: offset of the node whose property to change | 1210 | * @nodeoffset: offset of the node whose property to change |
| @@ -975,6 +1236,147 @@ static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name, | |||
| 975 | fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) | 1236 | fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) |
| 976 | 1237 | ||
| 977 | /** | 1238 | /** |
| 1239 | * fdt_appendprop - append to or create a property | ||
| 1240 | * @fdt: pointer to the device tree blob | ||
| 1241 | * @nodeoffset: offset of the node whose property to change | ||
| 1242 | * @name: name of the property to append to | ||
| 1243 | * @val: pointer to data to append to the property value | ||
| 1244 | * @len: length of the data to append to the property value | ||
| 1245 | * | ||
| 1246 | * fdt_appendprop() appends the value to the named property in the | ||
| 1247 | * given node, creating the property if it does not already exist. | ||
| 1248 | * | ||
| 1249 | * This function may insert data into the blob, and will therefore | ||
| 1250 | * change the offsets of some existing nodes. | ||
| 1251 | * | ||
| 1252 | * returns: | ||
| 1253 | * 0, on success | ||
| 1254 | * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to | ||
| 1255 | * contain the new property value | ||
| 1256 | * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag | ||
| 1257 | * -FDT_ERR_BADLAYOUT, | ||
| 1258 | * -FDT_ERR_BADMAGIC, | ||
| 1259 | * -FDT_ERR_BADVERSION, | ||
| 1260 | * -FDT_ERR_BADSTATE, | ||
| 1261 | * -FDT_ERR_BADSTRUCTURE, | ||
| 1262 | * -FDT_ERR_BADLAYOUT, | ||
| 1263 | * -FDT_ERR_TRUNCATED, standard meanings | ||
| 1264 | */ | ||
| 1265 | int fdt_appendprop(void *fdt, int nodeoffset, const char *name, | ||
| 1266 | const void *val, int len); | ||
| 1267 | |||
| 1268 | /** | ||
| 1269 | * fdt_appendprop_u32 - append a 32-bit integer value to a property | ||
| 1270 | * @fdt: pointer to the device tree blob | ||
| 1271 | * @nodeoffset: offset of the node whose property to change | ||
| 1272 | * @name: name of the property to change | ||
| 1273 | * @val: 32-bit integer value to append to the property (native endian) | ||
| 1274 | * | ||
| 1275 | * fdt_appendprop_u32() appends the given 32-bit integer value | ||
| 1276 | * (converting to big-endian if necessary) to the value of the named | ||
| 1277 | * property in the given node, or creates a new property with that | ||
| 1278 | * value if it does not already exist. | ||
| 1279 | * | ||
| 1280 | * This function may insert data into the blob, and will therefore | ||
| 1281 | * change the offsets of some existing nodes. | ||
| 1282 | * | ||
| 1283 | * returns: | ||
| 1284 | * 0, on success | ||
| 1285 | * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to | ||
| 1286 | * contain the new property value | ||
| 1287 | * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag | ||
| 1288 | * -FDT_ERR_BADLAYOUT, | ||
| 1289 | * -FDT_ERR_BADMAGIC, | ||
| 1290 | * -FDT_ERR_BADVERSION, | ||
| 1291 | * -FDT_ERR_BADSTATE, | ||
| 1292 | * -FDT_ERR_BADSTRUCTURE, | ||
| 1293 | * -FDT_ERR_BADLAYOUT, | ||
| 1294 | * -FDT_ERR_TRUNCATED, standard meanings | ||
| 1295 | */ | ||
| 1296 | static inline int fdt_appendprop_u32(void *fdt, int nodeoffset, | ||
| 1297 | const char *name, uint32_t val) | ||
| 1298 | { | ||
| 1299 | val = cpu_to_fdt32(val); | ||
| 1300 | return fdt_appendprop(fdt, nodeoffset, name, &val, sizeof(val)); | ||
| 1301 | } | ||
| 1302 | |||
| 1303 | /** | ||
| 1304 | * fdt_appendprop_u64 - append a 64-bit integer value to a property | ||
| 1305 | * @fdt: pointer to the device tree blob | ||
| 1306 | * @nodeoffset: offset of the node whose property to change | ||
| 1307 | * @name: name of the property to change | ||
| 1308 | * @val: 64-bit integer value to append to the property (native endian) | ||
| 1309 | * | ||
| 1310 | * fdt_appendprop_u64() appends the given 64-bit integer value | ||
| 1311 | * (converting to big-endian if necessary) to the value of the named | ||
| 1312 | * property in the given node, or creates a new property with that | ||
| 1313 | * value if it does not already exist. | ||
| 1314 | * | ||
| 1315 | * This function may insert data into the blob, and will therefore | ||
| 1316 | * change the offsets of some existing nodes. | ||
| 1317 | * | ||
| 1318 | * returns: | ||
| 1319 | * 0, on success | ||
| 1320 | * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to | ||
| 1321 | * contain the new property value | ||
| 1322 | * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag | ||
| 1323 | * -FDT_ERR_BADLAYOUT, | ||
| 1324 | * -FDT_ERR_BADMAGIC, | ||
| 1325 | * -FDT_ERR_BADVERSION, | ||
| 1326 | * -FDT_ERR_BADSTATE, | ||
| 1327 | * -FDT_ERR_BADSTRUCTURE, | ||
| 1328 | * -FDT_ERR_BADLAYOUT, | ||
| 1329 | * -FDT_ERR_TRUNCATED, standard meanings | ||
| 1330 | */ | ||
| 1331 | static inline int fdt_appendprop_u64(void *fdt, int nodeoffset, | ||
| 1332 | const char *name, uint64_t val) | ||
| 1333 | { | ||
| 1334 | val = cpu_to_fdt64(val); | ||
| 1335 | return fdt_appendprop(fdt, nodeoffset, name, &val, sizeof(val)); | ||
| 1336 | } | ||
| 1337 | |||
| 1338 | /** | ||
| 1339 | * fdt_appendprop_cell - append a single cell value to a property | ||
| 1340 | * | ||
| 1341 | * This is an alternative name for fdt_appendprop_u32() | ||
| 1342 | */ | ||
| 1343 | static inline int fdt_appendprop_cell(void *fdt, int nodeoffset, | ||
| 1344 | const char *name, uint32_t val) | ||
| 1345 | { | ||
| 1346 | return fdt_appendprop_u32(fdt, nodeoffset, name, val); | ||
| 1347 | } | ||
| 1348 | |||
| 1349 | /** | ||
| 1350 | * fdt_appendprop_string - append a string to a property | ||
| 1351 | * @fdt: pointer to the device tree blob | ||
| 1352 | * @nodeoffset: offset of the node whose property to change | ||
| 1353 | * @name: name of the property to change | ||
| 1354 | * @str: string value to append to the property | ||
| 1355 | * | ||
| 1356 | * fdt_appendprop_string() appends the given string to the value of | ||
| 1357 | * the named property in the given node, or creates a new property | ||
| 1358 | * with that value if it does not already exist. | ||
| 1359 | * | ||
| 1360 | * This function may insert data into the blob, and will therefore | ||
| 1361 | * change the offsets of some existing nodes. | ||
| 1362 | * | ||
| 1363 | * returns: | ||
| 1364 | * 0, on success | ||
| 1365 | * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to | ||
| 1366 | * contain the new property value | ||
| 1367 | * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag | ||
| 1368 | * -FDT_ERR_BADLAYOUT, | ||
| 1369 | * -FDT_ERR_BADMAGIC, | ||
| 1370 | * -FDT_ERR_BADVERSION, | ||
| 1371 | * -FDT_ERR_BADSTATE, | ||
| 1372 | * -FDT_ERR_BADSTRUCTURE, | ||
| 1373 | * -FDT_ERR_BADLAYOUT, | ||
| 1374 | * -FDT_ERR_TRUNCATED, standard meanings | ||
| 1375 | */ | ||
| 1376 | #define fdt_appendprop_string(fdt, nodeoffset, name, str) \ | ||
| 1377 | fdt_appendprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) | ||
| 1378 | |||
| 1379 | /** | ||
| 978 | * fdt_delprop - delete a property | 1380 | * fdt_delprop - delete a property |
| 979 | * @fdt: pointer to the device tree blob | 1381 | * @fdt: pointer to the device tree blob |
| 980 | * @nodeoffset: offset of the node whose property to nop | 1382 | * @nodeoffset: offset of the node whose property to nop |
diff --git a/scripts/dtc/libfdt/libfdt_env.h b/scripts/dtc/libfdt/libfdt_env.h index 449bf602daf1..213d7fb81c42 100644 --- a/scripts/dtc/libfdt/libfdt_env.h +++ b/scripts/dtc/libfdt/libfdt_env.h | |||
| @@ -5,19 +5,25 @@ | |||
| 5 | #include <stdint.h> | 5 | #include <stdint.h> |
| 6 | #include <string.h> | 6 | #include <string.h> |
| 7 | 7 | ||
| 8 | #define _B(n) ((unsigned long long)((uint8_t *)&x)[n]) | 8 | #define EXTRACT_BYTE(n) ((unsigned long long)((uint8_t *)&x)[n]) |
| 9 | static inline uint16_t fdt16_to_cpu(uint16_t x) | ||
| 10 | { | ||
| 11 | return (EXTRACT_BYTE(0) << 8) | EXTRACT_BYTE(1); | ||
| 12 | } | ||
| 13 | #define cpu_to_fdt16(x) fdt16_to_cpu(x) | ||
| 14 | |||
| 9 | static inline uint32_t fdt32_to_cpu(uint32_t x) | 15 | static inline uint32_t fdt32_to_cpu(uint32_t x) |
| 10 | { | 16 | { |
| 11 | return (_B(0) << 24) | (_B(1) << 16) | (_B(2) << 8) | _B(3); | 17 | return (EXTRACT_BYTE(0) << 24) | (EXTRACT_BYTE(1) << 16) | (EXTRACT_BYTE(2) << 8) | EXTRACT_BYTE(3); |
| 12 | } | 18 | } |
| 13 | #define cpu_to_fdt32(x) fdt32_to_cpu(x) | 19 | #define cpu_to_fdt32(x) fdt32_to_cpu(x) |
| 14 | 20 | ||
| 15 | static inline uint64_t fdt64_to_cpu(uint64_t x) | 21 | static inline uint64_t fdt64_to_cpu(uint64_t x) |
| 16 | { | 22 | { |
| 17 | return (_B(0) << 56) | (_B(1) << 48) | (_B(2) << 40) | (_B(3) << 32) | 23 | return (EXTRACT_BYTE(0) << 56) | (EXTRACT_BYTE(1) << 48) | (EXTRACT_BYTE(2) << 40) | (EXTRACT_BYTE(3) << 32) |
| 18 | | (_B(4) << 24) | (_B(5) << 16) | (_B(6) << 8) | _B(7); | 24 | | (EXTRACT_BYTE(4) << 24) | (EXTRACT_BYTE(5) << 16) | (EXTRACT_BYTE(6) << 8) | EXTRACT_BYTE(7); |
| 19 | } | 25 | } |
| 20 | #define cpu_to_fdt64(x) fdt64_to_cpu(x) | 26 | #define cpu_to_fdt64(x) fdt64_to_cpu(x) |
| 21 | #undef _B | 27 | #undef EXTRACT_BYTE |
| 22 | 28 | ||
| 23 | #endif /* _LIBFDT_ENV_H */ | 29 | #endif /* _LIBFDT_ENV_H */ |
diff --git a/scripts/dtc/libfdt/libfdt_internal.h b/scripts/dtc/libfdt/libfdt_internal.h index 46eb93e4af5c..381133ba81df 100644 --- a/scripts/dtc/libfdt/libfdt_internal.h +++ b/scripts/dtc/libfdt/libfdt_internal.h | |||
| @@ -62,8 +62,8 @@ | |||
| 62 | return err; \ | 62 | return err; \ |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | uint32_t _fdt_next_tag(const void *fdt, int startoffset, int *nextoffset); | ||
| 66 | int _fdt_check_node_offset(const void *fdt, int offset); | 65 | int _fdt_check_node_offset(const void *fdt, int offset); |
| 66 | int _fdt_check_prop_offset(const void *fdt, int offset); | ||
| 67 | const char *_fdt_find_string(const char *strtab, int tabsize, const char *s); | 67 | const char *_fdt_find_string(const char *strtab, int tabsize, const char *s); |
| 68 | int _fdt_node_end_offset(void *fdt, int nodeoffset); | 68 | int _fdt_node_end_offset(void *fdt, int nodeoffset); |
| 69 | 69 | ||
diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c index 26d0e1e60c0c..b61465fb2f33 100644 --- a/scripts/dtc/livetree.c +++ b/scripts/dtc/livetree.c | |||
| @@ -29,16 +29,27 @@ void add_label(struct label **labels, char *label) | |||
| 29 | struct label *new; | 29 | struct label *new; |
| 30 | 30 | ||
| 31 | /* Make sure the label isn't already there */ | 31 | /* Make sure the label isn't already there */ |
| 32 | for_each_label(*labels, new) | 32 | for_each_label_withdel(*labels, new) |
| 33 | if (streq(new->label, label)) | 33 | if (streq(new->label, label)) { |
| 34 | new->deleted = 0; | ||
| 34 | return; | 35 | return; |
| 36 | } | ||
| 35 | 37 | ||
| 36 | new = xmalloc(sizeof(*new)); | 38 | new = xmalloc(sizeof(*new)); |
| 39 | memset(new, 0, sizeof(*new)); | ||
| 37 | new->label = label; | 40 | new->label = label; |
| 38 | new->next = *labels; | 41 | new->next = *labels; |
| 39 | *labels = new; | 42 | *labels = new; |
| 40 | } | 43 | } |
| 41 | 44 | ||
| 45 | void delete_labels(struct label **labels) | ||
| 46 | { | ||
| 47 | struct label *label; | ||
| 48 | |||
| 49 | for_each_label(*labels, label) | ||
| 50 | label->deleted = 1; | ||
| 51 | } | ||
| 52 | |||
| 42 | struct property *build_property(char *name, struct data val) | 53 | struct property *build_property(char *name, struct data val) |
| 43 | { | 54 | { |
| 44 | struct property *new = xmalloc(sizeof(*new)); | 55 | struct property *new = xmalloc(sizeof(*new)); |
| @@ -51,6 +62,18 @@ struct property *build_property(char *name, struct data val) | |||
| 51 | return new; | 62 | return new; |
| 52 | } | 63 | } |
| 53 | 64 | ||
| 65 | struct property *build_property_delete(char *name) | ||
| 66 | { | ||
| 67 | struct property *new = xmalloc(sizeof(*new)); | ||
| 68 | |||
| 69 | memset(new, 0, sizeof(*new)); | ||
| 70 | |||
| 71 | new->name = name; | ||
| 72 | new->deleted = 1; | ||
| 73 | |||
| 74 | return new; | ||
| 75 | } | ||
| 76 | |||
| 54 | struct property *chain_property(struct property *first, struct property *list) | 77 | struct property *chain_property(struct property *first, struct property *list) |
| 55 | { | 78 | { |
| 56 | assert(first->next == NULL); | 79 | assert(first->next == NULL); |
| @@ -91,6 +114,17 @@ struct node *build_node(struct property *proplist, struct node *children) | |||
| 91 | return new; | 114 | return new; |
| 92 | } | 115 | } |
| 93 | 116 | ||
| 117 | struct node *build_node_delete(void) | ||
| 118 | { | ||
| 119 | struct node *new = xmalloc(sizeof(*new)); | ||
| 120 | |||
| 121 | memset(new, 0, sizeof(*new)); | ||
| 122 | |||
| 123 | new->deleted = 1; | ||
| 124 | |||
| 125 | return new; | ||
| 126 | } | ||
| 127 | |||
| 94 | struct node *name_node(struct node *node, char *name) | 128 | struct node *name_node(struct node *node, char *name) |
| 95 | { | 129 | { |
| 96 | assert(node->name == NULL); | 130 | assert(node->name == NULL); |
| @@ -106,8 +140,10 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node) | |||
| 106 | struct node *new_child, *old_child; | 140 | struct node *new_child, *old_child; |
| 107 | struct label *l; | 141 | struct label *l; |
| 108 | 142 | ||
| 143 | old_node->deleted = 0; | ||
| 144 | |||
| 109 | /* Add new node labels to old node */ | 145 | /* Add new node labels to old node */ |
| 110 | for_each_label(new_node->labels, l) | 146 | for_each_label_withdel(new_node->labels, l) |
| 111 | add_label(&old_node->labels, l->label); | 147 | add_label(&old_node->labels, l->label); |
| 112 | 148 | ||
| 113 | /* Move properties from the new node to the old node. If there | 149 | /* Move properties from the new node to the old node. If there |
| @@ -118,14 +154,21 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node) | |||
| 118 | new_node->proplist = new_prop->next; | 154 | new_node->proplist = new_prop->next; |
| 119 | new_prop->next = NULL; | 155 | new_prop->next = NULL; |
| 120 | 156 | ||
| 157 | if (new_prop->deleted) { | ||
| 158 | delete_property_by_name(old_node, new_prop->name); | ||
| 159 | free(new_prop); | ||
| 160 | continue; | ||
| 161 | } | ||
| 162 | |||
| 121 | /* Look for a collision, set new value if there is */ | 163 | /* Look for a collision, set new value if there is */ |
| 122 | for_each_property(old_node, old_prop) { | 164 | for_each_property_withdel(old_node, old_prop) { |
| 123 | if (streq(old_prop->name, new_prop->name)) { | 165 | if (streq(old_prop->name, new_prop->name)) { |
| 124 | /* Add new labels to old property */ | 166 | /* Add new labels to old property */ |
| 125 | for_each_label(new_prop->labels, l) | 167 | for_each_label_withdel(new_prop->labels, l) |
| 126 | add_label(&old_prop->labels, l->label); | 168 | add_label(&old_prop->labels, l->label); |
| 127 | 169 | ||
| 128 | old_prop->val = new_prop->val; | 170 | old_prop->val = new_prop->val; |
| 171 | old_prop->deleted = 0; | ||
| 129 | free(new_prop); | 172 | free(new_prop); |
| 130 | new_prop = NULL; | 173 | new_prop = NULL; |
| 131 | break; | 174 | break; |
| @@ -146,8 +189,14 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node) | |||
| 146 | new_child->parent = NULL; | 189 | new_child->parent = NULL; |
| 147 | new_child->next_sibling = NULL; | 190 | new_child->next_sibling = NULL; |
| 148 | 191 | ||
| 192 | if (new_child->deleted) { | ||
| 193 | delete_node_by_name(old_node, new_child->name); | ||
| 194 | free(new_child); | ||
| 195 | continue; | ||
| 196 | } | ||
| 197 | |||
| 149 | /* Search for a collision. Merge if there is */ | 198 | /* Search for a collision. Merge if there is */ |
| 150 | for_each_child(old_node, old_child) { | 199 | for_each_child_withdel(old_node, old_child) { |
| 151 | if (streq(old_child->name, new_child->name)) { | 200 | if (streq(old_child->name, new_child->name)) { |
| 152 | merge_nodes(old_child, new_child); | 201 | merge_nodes(old_child, new_child); |
| 153 | new_child = NULL; | 202 | new_child = NULL; |
| @@ -155,7 +204,7 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node) | |||
| 155 | } | 204 | } |
| 156 | } | 205 | } |
| 157 | 206 | ||
| 158 | /* if no collision occurred, add child to the old node. */ | 207 | /* if no collision occured, add child to the old node. */ |
| 159 | if (new_child) | 208 | if (new_child) |
| 160 | add_child(old_node, new_child); | 209 | add_child(old_node, new_child); |
| 161 | } | 210 | } |
| @@ -188,6 +237,25 @@ void add_property(struct node *node, struct property *prop) | |||
| 188 | *p = prop; | 237 | *p = prop; |
| 189 | } | 238 | } |
| 190 | 239 | ||
| 240 | void delete_property_by_name(struct node *node, char *name) | ||
| 241 | { | ||
| 242 | struct property *prop = node->proplist; | ||
| 243 | |||
| 244 | while (prop) { | ||
| 245 | if (!strcmp(prop->name, name)) { | ||
| 246 | delete_property(prop); | ||
| 247 | return; | ||
| 248 | } | ||
| 249 | prop = prop->next; | ||
| 250 | } | ||
| 251 | } | ||
| 252 | |||
| 253 | void delete_property(struct property *prop) | ||
| 254 | { | ||
| 255 | prop->deleted = 1; | ||
| 256 | delete_labels(&prop->labels); | ||
| 257 | } | ||
| 258 | |||
| 191 | void add_child(struct node *parent, struct node *child) | 259 | void add_child(struct node *parent, struct node *child) |
| 192 | { | 260 | { |
| 193 | struct node **p; | 261 | struct node **p; |
| @@ -202,6 +270,32 @@ void add_child(struct node *parent, struct node *child) | |||
| 202 | *p = child; | 270 | *p = child; |
| 203 | } | 271 | } |
| 204 | 272 | ||
| 273 | void delete_node_by_name(struct node *parent, char *name) | ||
| 274 | { | ||
| 275 | struct node *node = parent->children; | ||
| 276 | |||
| 277 | while (node) { | ||
| 278 | if (!strcmp(node->name, name)) { | ||
| 279 | delete_node(node); | ||
| 280 | return; | ||
| 281 | } | ||
| 282 | node = node->next_sibling; | ||
| 283 | } | ||
| 284 | } | ||
| 285 | |||
| 286 | void delete_node(struct node *node) | ||
| 287 | { | ||
| 288 | struct property *prop; | ||
| 289 | struct node *child; | ||
| 290 | |||
| 291 | node->deleted = 1; | ||
| 292 | for_each_child(node, child) | ||
| 293 | delete_node(child); | ||
| 294 | for_each_property(node, prop) | ||
| 295 | delete_property(prop); | ||
| 296 | delete_labels(&node->labels); | ||
| 297 | } | ||
| 298 | |||
| 205 | struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size) | 299 | struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size) |
| 206 | { | 300 | { |
| 207 | struct reserve_info *new = xmalloc(sizeof(*new)); | 301 | struct reserve_info *new = xmalloc(sizeof(*new)); |
| @@ -353,8 +447,11 @@ struct node *get_node_by_path(struct node *tree, const char *path) | |||
| 353 | const char *p; | 447 | const char *p; |
| 354 | struct node *child; | 448 | struct node *child; |
| 355 | 449 | ||
| 356 | if (!path || ! (*path)) | 450 | if (!path || ! (*path)) { |
| 451 | if (tree->deleted) | ||
| 452 | return NULL; | ||
| 357 | return tree; | 453 | return tree; |
| 454 | } | ||
| 358 | 455 | ||
| 359 | while (path[0] == '/') | 456 | while (path[0] == '/') |
| 360 | path++; | 457 | path++; |
| @@ -397,8 +494,11 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle) | |||
| 397 | 494 | ||
| 398 | assert((phandle != 0) && (phandle != -1)); | 495 | assert((phandle != 0) && (phandle != -1)); |
| 399 | 496 | ||
| 400 | if (tree->phandle == phandle) | 497 | if (tree->phandle == phandle) { |
| 498 | if (tree->deleted) | ||
| 499 | return NULL; | ||
| 401 | return tree; | 500 | return tree; |
| 501 | } | ||
| 402 | 502 | ||
| 403 | for_each_child(tree, child) { | 503 | for_each_child(tree, child) { |
| 404 | node = get_node_by_phandle(child, phandle); | 504 | node = get_node_by_phandle(child, phandle); |
| @@ -535,7 +635,7 @@ static void sort_properties(struct node *node) | |||
| 535 | int n = 0, i = 0; | 635 | int n = 0, i = 0; |
| 536 | struct property *prop, **tbl; | 636 | struct property *prop, **tbl; |
| 537 | 637 | ||
| 538 | for_each_property(node, prop) | 638 | for_each_property_withdel(node, prop) |
| 539 | n++; | 639 | n++; |
| 540 | 640 | ||
| 541 | if (n == 0) | 641 | if (n == 0) |
| @@ -543,7 +643,7 @@ static void sort_properties(struct node *node) | |||
| 543 | 643 | ||
| 544 | tbl = xmalloc(n * sizeof(*tbl)); | 644 | tbl = xmalloc(n * sizeof(*tbl)); |
| 545 | 645 | ||
| 546 | for_each_property(node, prop) | 646 | for_each_property_withdel(node, prop) |
| 547 | tbl[i++] = prop; | 647 | tbl[i++] = prop; |
| 548 | 648 | ||
| 549 | qsort(tbl, n, sizeof(*tbl), cmp_prop); | 649 | qsort(tbl, n, sizeof(*tbl), cmp_prop); |
| @@ -571,7 +671,7 @@ static void sort_subnodes(struct node *node) | |||
| 571 | int n = 0, i = 0; | 671 | int n = 0, i = 0; |
| 572 | struct node *subnode, **tbl; | 672 | struct node *subnode, **tbl; |
| 573 | 673 | ||
| 574 | for_each_child(node, subnode) | 674 | for_each_child_withdel(node, subnode) |
| 575 | n++; | 675 | n++; |
| 576 | 676 | ||
| 577 | if (n == 0) | 677 | if (n == 0) |
| @@ -579,7 +679,7 @@ static void sort_subnodes(struct node *node) | |||
| 579 | 679 | ||
| 580 | tbl = xmalloc(n * sizeof(*tbl)); | 680 | tbl = xmalloc(n * sizeof(*tbl)); |
| 581 | 681 | ||
| 582 | for_each_child(node, subnode) | 682 | for_each_child_withdel(node, subnode) |
| 583 | tbl[i++] = subnode; | 683 | tbl[i++] = subnode; |
| 584 | 684 | ||
| 585 | qsort(tbl, n, sizeof(*tbl), cmp_subnode); | 685 | qsort(tbl, n, sizeof(*tbl), cmp_subnode); |
| @@ -598,7 +698,7 @@ static void sort_node(struct node *node) | |||
| 598 | 698 | ||
| 599 | sort_properties(node); | 699 | sort_properties(node); |
| 600 | sort_subnodes(node); | 700 | sort_subnodes(node); |
| 601 | for_each_child(node, c) | 701 | for_each_child_withdel(node, c) |
| 602 | sort_node(c); | 702 | sort_node(c); |
| 603 | } | 703 | } |
| 604 | 704 | ||
diff --git a/scripts/dtc/srcpos.c b/scripts/dtc/srcpos.c index 36a38e9f1a2c..246ab4bc0d9d 100644 --- a/scripts/dtc/srcpos.c +++ b/scripts/dtc/srcpos.c | |||
| @@ -24,6 +24,15 @@ | |||
| 24 | #include "dtc.h" | 24 | #include "dtc.h" |
| 25 | #include "srcpos.h" | 25 | #include "srcpos.h" |
| 26 | 26 | ||
| 27 | /* A node in our list of directories to search for source/include files */ | ||
| 28 | struct search_path { | ||
| 29 | struct search_path *next; /* next node in list, NULL for end */ | ||
| 30 | const char *dirname; /* name of directory to search */ | ||
| 31 | }; | ||
| 32 | |||
| 33 | /* This is the list of directories that we search for source files */ | ||
| 34 | static struct search_path *search_path_head, **search_path_tail; | ||
| 35 | |||
| 27 | 36 | ||
| 28 | static char *dirname(const char *path) | 37 | static char *dirname(const char *path) |
| 29 | { | 38 | { |
| @@ -47,6 +56,64 @@ struct srcfile_state *current_srcfile; /* = NULL */ | |||
| 47 | #define MAX_SRCFILE_DEPTH (100) | 56 | #define MAX_SRCFILE_DEPTH (100) |
| 48 | static int srcfile_depth; /* = 0 */ | 57 | static int srcfile_depth; /* = 0 */ |
| 49 | 58 | ||
| 59 | |||
| 60 | /** | ||
| 61 | * Try to open a file in a given directory. | ||
| 62 | * | ||
| 63 | * If the filename is an absolute path, then dirname is ignored. If it is a | ||
| 64 | * relative path, then we look in that directory for the file. | ||
| 65 | * | ||
| 66 | * @param dirname Directory to look in, or NULL for none | ||
| 67 | * @param fname Filename to look for | ||
| 68 | * @param fp Set to NULL if file did not open | ||
| 69 | * @return allocated filename on success (caller must free), NULL on failure | ||
| 70 | */ | ||
| 71 | static char *try_open(const char *dirname, const char *fname, FILE **fp) | ||
| 72 | { | ||
| 73 | char *fullname; | ||
| 74 | |||
| 75 | if (!dirname || fname[0] == '/') | ||
| 76 | fullname = xstrdup(fname); | ||
| 77 | else | ||
| 78 | fullname = join_path(dirname, fname); | ||
| 79 | |||
| 80 | *fp = fopen(fullname, "r"); | ||
| 81 | if (!*fp) { | ||
| 82 | free(fullname); | ||
| 83 | fullname = NULL; | ||
| 84 | } | ||
| 85 | |||
| 86 | return fullname; | ||
| 87 | } | ||
| 88 | |||
| 89 | /** | ||
| 90 | * Open a file for read access | ||
| 91 | * | ||
| 92 | * If it is a relative filename, we search the full search path for it. | ||
| 93 | * | ||
| 94 | * @param fname Filename to open | ||
| 95 | * @param fp Returns pointer to opened FILE, or NULL on failure | ||
| 96 | * @return pointer to allocated filename, which caller must free | ||
| 97 | */ | ||
| 98 | static char *fopen_any_on_path(const char *fname, FILE **fp) | ||
| 99 | { | ||
| 100 | const char *cur_dir = NULL; | ||
| 101 | struct search_path *node; | ||
| 102 | char *fullname; | ||
| 103 | |||
| 104 | /* Try current directory first */ | ||
| 105 | assert(fp); | ||
| 106 | if (current_srcfile) | ||
| 107 | cur_dir = current_srcfile->dir; | ||
| 108 | fullname = try_open(cur_dir, fname, fp); | ||
| 109 | |||
| 110 | /* Failing that, try each search path in turn */ | ||
| 111 | for (node = search_path_head; !*fp && node; node = node->next) | ||
| 112 | fullname = try_open(node->dirname, fname, fp); | ||
| 113 | |||
| 114 | return fullname; | ||
| 115 | } | ||
| 116 | |||
| 50 | FILE *srcfile_relative_open(const char *fname, char **fullnamep) | 117 | FILE *srcfile_relative_open(const char *fname, char **fullnamep) |
| 51 | { | 118 | { |
| 52 | FILE *f; | 119 | FILE *f; |
| @@ -56,13 +123,7 @@ FILE *srcfile_relative_open(const char *fname, char **fullnamep) | |||
| 56 | f = stdin; | 123 | f = stdin; |
| 57 | fullname = xstrdup("<stdin>"); | 124 | fullname = xstrdup("<stdin>"); |
| 58 | } else { | 125 | } else { |
| 59 | if (!current_srcfile || !current_srcfile->dir | 126 | fullname = fopen_any_on_path(fname, &f); |
| 60 | || (fname[0] == '/')) | ||
| 61 | fullname = xstrdup(fname); | ||
| 62 | else | ||
| 63 | fullname = join_path(current_srcfile->dir, fname); | ||
| 64 | |||
| 65 | f = fopen(fullname, "r"); | ||
| 66 | if (!f) | 127 | if (!f) |
| 67 | die("Couldn't open \"%s\": %s\n", fname, | 128 | die("Couldn't open \"%s\": %s\n", fname, |
| 68 | strerror(errno)); | 129 | strerror(errno)); |
| @@ -119,6 +180,23 @@ int srcfile_pop(void) | |||
| 119 | return current_srcfile ? 1 : 0; | 180 | return current_srcfile ? 1 : 0; |
| 120 | } | 181 | } |
| 121 | 182 | ||
| 183 | void srcfile_add_search_path(const char *dirname) | ||
| 184 | { | ||
| 185 | struct search_path *node; | ||
| 186 | |||
| 187 | /* Create the node */ | ||
| 188 | node = xmalloc(sizeof(*node)); | ||
| 189 | node->next = NULL; | ||
| 190 | node->dirname = xstrdup(dirname); | ||
| 191 | |||
| 192 | /* Add to the end of our list */ | ||
| 193 | if (search_path_tail) | ||
| 194 | *search_path_tail = node; | ||
| 195 | else | ||
| 196 | search_path_head = node; | ||
| 197 | search_path_tail = &node->next; | ||
| 198 | } | ||
| 199 | |||
| 122 | /* | 200 | /* |
| 123 | * The empty source position. | 201 | * The empty source position. |
| 124 | */ | 202 | */ |
| @@ -250,3 +328,9 @@ srcpos_warn(struct srcpos *pos, char const *fmt, ...) | |||
| 250 | 328 | ||
| 251 | va_end(va); | 329 | va_end(va); |
| 252 | } | 330 | } |
| 331 | |||
| 332 | void srcpos_set_line(char *f, int l) | ||
| 333 | { | ||
| 334 | current_srcfile->name = f; | ||
| 335 | current_srcfile->lineno = l; | ||
| 336 | } | ||
diff --git a/scripts/dtc/srcpos.h b/scripts/dtc/srcpos.h index ce980cafe588..93a27123c2e9 100644 --- a/scripts/dtc/srcpos.h +++ b/scripts/dtc/srcpos.h | |||
| @@ -33,10 +33,39 @@ struct srcfile_state { | |||
| 33 | extern FILE *depfile; /* = NULL */ | 33 | extern FILE *depfile; /* = NULL */ |
| 34 | extern struct srcfile_state *current_srcfile; /* = NULL */ | 34 | extern struct srcfile_state *current_srcfile; /* = NULL */ |
| 35 | 35 | ||
| 36 | /** | ||
| 37 | * Open a source file. | ||
| 38 | * | ||
| 39 | * If the source file is a relative pathname, then it is searched for in the | ||
| 40 | * current directory (the directory of the last source file read) and after | ||
| 41 | * that in the search path. | ||
| 42 | * | ||
| 43 | * We work through the search path in order from the first path specified to | ||
| 44 | * the last. | ||
| 45 | * | ||
| 46 | * If the file is not found, then this function does not return, but calls | ||
| 47 | * die(). | ||
| 48 | * | ||
| 49 | * @param fname Filename to search | ||
| 50 | * @param fullnamep If non-NULL, it is set to the allocated filename of the | ||
| 51 | * file that was opened. The caller is then responsible | ||
| 52 | * for freeing the pointer. | ||
| 53 | * @return pointer to opened FILE | ||
| 54 | */ | ||
| 36 | FILE *srcfile_relative_open(const char *fname, char **fullnamep); | 55 | FILE *srcfile_relative_open(const char *fname, char **fullnamep); |
| 56 | |||
| 37 | void srcfile_push(const char *fname); | 57 | void srcfile_push(const char *fname); |
| 38 | int srcfile_pop(void); | 58 | int srcfile_pop(void); |
| 39 | 59 | ||
| 60 | /** | ||
| 61 | * Add a new directory to the search path for input files | ||
| 62 | * | ||
| 63 | * The new path is added at the end of the list. | ||
| 64 | * | ||
| 65 | * @param dirname Directory to add | ||
| 66 | */ | ||
| 67 | void srcfile_add_search_path(const char *dirname); | ||
| 68 | |||
| 40 | struct srcpos { | 69 | struct srcpos { |
| 41 | int first_line; | 70 | int first_line; |
| 42 | int first_column; | 71 | int first_column; |
| @@ -84,4 +113,6 @@ extern void srcpos_error(struct srcpos *pos, char const *, ...) | |||
| 84 | extern void srcpos_warn(struct srcpos *pos, char const *, ...) | 113 | extern void srcpos_warn(struct srcpos *pos, char const *, ...) |
| 85 | __attribute__((format(printf, 2, 3))); | 114 | __attribute__((format(printf, 2, 3))); |
| 86 | 115 | ||
| 116 | extern void srcpos_set_line(char *f, int l); | ||
| 117 | |||
| 87 | #endif /* _SRCPOS_H_ */ | 118 | #endif /* _SRCPOS_H_ */ |
diff --git a/scripts/dtc/treesource.c b/scripts/dtc/treesource.c index c09aafade313..33eeba55fb4d 100644 --- a/scripts/dtc/treesource.c +++ b/scripts/dtc/treesource.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | 23 | ||
| 24 | extern FILE *yyin; | 24 | extern FILE *yyin; |
| 25 | extern int yyparse(void); | 25 | extern int yyparse(void); |
| 26 | extern YYLTYPE yylloc; | ||
| 26 | 27 | ||
| 27 | struct boot_info *the_boot_info; | 28 | struct boot_info *the_boot_info; |
| 28 | int treesource_error; | 29 | int treesource_error; |
| @@ -34,6 +35,7 @@ struct boot_info *dt_from_source(const char *fname) | |||
| 34 | 35 | ||
| 35 | srcfile_push(fname); | 36 | srcfile_push(fname); |
| 36 | yyin = current_srcfile->f; | 37 | yyin = current_srcfile->f; |
| 38 | yylloc.file = current_srcfile; | ||
| 37 | 39 | ||
| 38 | if (yyparse() != 0) | 40 | if (yyparse() != 0) |
| 39 | die("Unable to parse input tree\n"); | 41 | die("Unable to parse input tree\n"); |
diff --git a/scripts/dtc/util.c b/scripts/dtc/util.c index d7ac27d2ae15..2422c34e11df 100644 --- a/scripts/dtc/util.c +++ b/scripts/dtc/util.c | |||
| @@ -1,6 +1,10 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright 2011 The Chromium Authors, All Rights Reserved. | ||
| 2 | * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc. | 3 | * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc. |
| 3 | * | 4 | * |
| 5 | * util_is_printable_string contributed by | ||
| 6 | * Pantelis Antoniou <pantelis.antoniou AT gmail.com> | ||
| 7 | * | ||
| 4 | * This program is free software; you can redistribute it and/or | 8 | * This program is free software; you can redistribute it and/or |
| 5 | * modify it under the terms of the GNU General Public License as | 9 | * modify it under the terms of the GNU General Public License as |
| 6 | * published by the Free Software Foundation; either version 2 of the | 10 | * published by the Free Software Foundation; either version 2 of the |
| @@ -17,11 +21,18 @@ | |||
| 17 | * USA | 21 | * USA |
| 18 | */ | 22 | */ |
| 19 | 23 | ||
| 24 | #include <ctype.h> | ||
| 20 | #include <stdio.h> | 25 | #include <stdio.h> |
| 21 | #include <stdlib.h> | 26 | #include <stdlib.h> |
| 22 | #include <stdarg.h> | 27 | #include <stdarg.h> |
| 23 | #include <string.h> | 28 | #include <string.h> |
| 29 | #include <assert.h> | ||
| 30 | |||
| 31 | #include <errno.h> | ||
| 32 | #include <fcntl.h> | ||
| 33 | #include <unistd.h> | ||
| 24 | 34 | ||
| 35 | #include "libfdt.h" | ||
| 25 | #include "util.h" | 36 | #include "util.h" |
| 26 | 37 | ||
| 27 | char *xstrdup(const char *s) | 38 | char *xstrdup(const char *s) |
| @@ -57,3 +68,264 @@ char *join_path(const char *path, const char *name) | |||
| 57 | memcpy(str+lenp, name, lenn+1); | 68 | memcpy(str+lenp, name, lenn+1); |
| 58 | return str; | 69 | return str; |
| 59 | } | 70 | } |
| 71 | |||
| 72 | int util_is_printable_string(const void *data, int len) | ||
| 73 | { | ||
| 74 | const char *s = data; | ||
| 75 | const char *ss; | ||
| 76 | |||
| 77 | /* zero length is not */ | ||
| 78 | if (len == 0) | ||
| 79 | return 0; | ||
| 80 | |||
| 81 | /* must terminate with zero */ | ||
| 82 | if (s[len - 1] != '\0') | ||
| 83 | return 0; | ||
| 84 | |||
| 85 | ss = s; | ||
| 86 | while (*s && isprint(*s)) | ||
| 87 | s++; | ||
| 88 | |||
| 89 | /* not zero, or not done yet */ | ||
| 90 | if (*s != '\0' || (s + 1 - ss) < len) | ||
| 91 | return 0; | ||
| 92 | |||
| 93 | return 1; | ||
| 94 | } | ||
| 95 | |||
| 96 | /* | ||
| 97 | * Parse a octal encoded character starting at index i in string s. The | ||
| 98 | * resulting character will be returned and the index i will be updated to | ||
| 99 | * point at the character directly after the end of the encoding, this may be | ||
| 100 | * the '\0' terminator of the string. | ||
| 101 | */ | ||
| 102 | static char get_oct_char(const char *s, int *i) | ||
| 103 | { | ||
| 104 | char x[4]; | ||
| 105 | char *endx; | ||
| 106 | long val; | ||
| 107 | |||
| 108 | x[3] = '\0'; | ||
| 109 | strncpy(x, s + *i, 3); | ||
| 110 | |||
| 111 | val = strtol(x, &endx, 8); | ||
| 112 | |||
| 113 | assert(endx > x); | ||
| 114 | |||
| 115 | (*i) += endx - x; | ||
| 116 | return val; | ||
| 117 | } | ||
| 118 | |||
| 119 | /* | ||
| 120 | * Parse a hexadecimal encoded character starting at index i in string s. The | ||
| 121 | * resulting character will be returned and the index i will be updated to | ||
| 122 | * point at the character directly after the end of the encoding, this may be | ||
| 123 | * the '\0' terminator of the string. | ||
| 124 | */ | ||
| 125 | static char get_hex_char(const char *s, int *i) | ||
| 126 | { | ||
| 127 | char x[3]; | ||
| 128 | char *endx; | ||
| 129 | long val; | ||
| 130 | |||
| 131 | x[2] = '\0'; | ||
| 132 | strncpy(x, s + *i, 2); | ||
| 133 | |||
| 134 | val = strtol(x, &endx, 16); | ||
| 135 | if (!(endx > x)) | ||
| 136 | die("\\x used with no following hex digits\n"); | ||
| 137 | |||
| 138 | (*i) += endx - x; | ||
| 139 | return val; | ||
| 140 | } | ||
| 141 | |||
| 142 | char get_escape_char(const char *s, int *i) | ||
| 143 | { | ||
| 144 | char c = s[*i]; | ||
| 145 | int j = *i + 1; | ||
| 146 | char val; | ||
| 147 | |||
| 148 | assert(c); | ||
| 149 | switch (c) { | ||
| 150 | case 'a': | ||
| 151 | val = '\a'; | ||
| 152 | break; | ||
| 153 | case 'b': | ||
| 154 | val = '\b'; | ||
| 155 | break; | ||
| 156 | case 't': | ||
| 157 | val = '\t'; | ||
| 158 | break; | ||
| 159 | case 'n': | ||
| 160 | val = '\n'; | ||
| 161 | break; | ||
| 162 | case 'v': | ||
| 163 | val = '\v'; | ||
| 164 | break; | ||
| 165 | case 'f': | ||
| 166 | val = '\f'; | ||
| 167 | break; | ||
| 168 | case 'r': | ||
| 169 | val = '\r'; | ||
| 170 | break; | ||
| 171 | case '0': | ||
| 172 | case '1': | ||
| 173 | case '2': | ||
| 174 | case '3': | ||
| 175 | case '4': | ||
| 176 | case '5': | ||
| 177 | case '6': | ||
| 178 | case '7': | ||
| 179 | j--; /* need to re-read the first digit as | ||
| 180 | * part of the octal value */ | ||
| 181 | val = get_oct_char(s, &j); | ||
| 182 | break; | ||
| 183 | case 'x': | ||
| 184 | val = get_hex_char(s, &j); | ||
| 185 | break; | ||
| 186 | default: | ||
| 187 | val = c; | ||
| 188 | } | ||
| 189 | |||
| 190 | (*i) = j; | ||
| 191 | return val; | ||
| 192 | } | ||
| 193 | |||
| 194 | int utilfdt_read_err(const char *filename, char **buffp) | ||
| 195 | { | ||
| 196 | int fd = 0; /* assume stdin */ | ||
| 197 | char *buf = NULL; | ||
| 198 | off_t bufsize = 1024, offset = 0; | ||
| 199 | int ret = 0; | ||
| 200 | |||
| 201 | *buffp = NULL; | ||
| 202 | if (strcmp(filename, "-") != 0) { | ||
| 203 | fd = open(filename, O_RDONLY); | ||
| 204 | if (fd < 0) | ||
| 205 | return errno; | ||
| 206 | } | ||
| 207 | |||
| 208 | /* Loop until we have read everything */ | ||
| 209 | buf = malloc(bufsize); | ||
| 210 | do { | ||
| 211 | /* Expand the buffer to hold the next chunk */ | ||
| 212 | if (offset == bufsize) { | ||
| 213 | bufsize *= 2; | ||
| 214 | buf = realloc(buf, bufsize); | ||
| 215 | if (!buf) { | ||
| 216 | ret = ENOMEM; | ||
| 217 | break; | ||
| 218 | } | ||
| 219 | } | ||
| 220 | |||
| 221 | ret = read(fd, &buf[offset], bufsize - offset); | ||
| 222 | if (ret < 0) { | ||
| 223 | ret = errno; | ||
| 224 | break; | ||
| 225 | } | ||
| 226 | offset += ret; | ||
| 227 | } while (ret != 0); | ||
| 228 | |||
| 229 | /* Clean up, including closing stdin; return errno on error */ | ||
| 230 | close(fd); | ||
| 231 | if (ret) | ||
| 232 | free(buf); | ||
| 233 | else | ||
| 234 | *buffp = buf; | ||
| 235 | return ret; | ||
| 236 | } | ||
| 237 | |||
| 238 | char *utilfdt_read(const char *filename) | ||
| 239 | { | ||
| 240 | char *buff; | ||
| 241 | int ret = utilfdt_read_err(filename, &buff); | ||
| 242 | |||
| 243 | if (ret) { | ||
| 244 | fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename, | ||
| 245 | strerror(ret)); | ||
| 246 | return NULL; | ||
| 247 | } | ||
| 248 | /* Successful read */ | ||
| 249 | return buff; | ||
| 250 | } | ||
| 251 | |||
| 252 | int utilfdt_write_err(const char *filename, const void *blob) | ||
| 253 | { | ||
| 254 | int fd = 1; /* assume stdout */ | ||
| 255 | int totalsize; | ||
| 256 | int offset; | ||
| 257 | int ret = 0; | ||
| 258 | const char *ptr = blob; | ||
| 259 | |||
| 260 | if (strcmp(filename, "-") != 0) { | ||
| 261 | fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); | ||
| 262 | if (fd < 0) | ||
| 263 | return errno; | ||
| 264 | } | ||
| 265 | |||
| 266 | totalsize = fdt_totalsize(blob); | ||
| 267 | offset = 0; | ||
| 268 | |||
| 269 | while (offset < totalsize) { | ||
| 270 | ret = write(fd, ptr + offset, totalsize - offset); | ||
| 271 | if (ret < 0) { | ||
| 272 | ret = -errno; | ||
| 273 | break; | ||
| 274 | } | ||
| 275 | offset += ret; | ||
| 276 | } | ||
| 277 | /* Close the file/stdin; return errno on error */ | ||
| 278 | if (fd != 1) | ||
| 279 | close(fd); | ||
| 280 | return ret < 0 ? -ret : 0; | ||
| 281 | } | ||
| 282 | |||
| 283 | |||
| 284 | int utilfdt_write(const char *filename, const void *blob) | ||
| 285 | { | ||
| 286 | int ret = utilfdt_write_err(filename, blob); | ||
| 287 | |||
| 288 | if (ret) { | ||
| 289 | fprintf(stderr, "Couldn't write blob to '%s': %s\n", filename, | ||
| 290 | strerror(ret)); | ||
| 291 | } | ||
| 292 | return ret ? -1 : 0; | ||
| 293 | } | ||
| 294 | |||
| 295 | int utilfdt_decode_type(const char *fmt, int *type, int *size) | ||
| 296 | { | ||
| 297 | int qualifier = 0; | ||
| 298 | |||
| 299 | if (!*fmt) | ||
| 300 | return -1; | ||
| 301 | |||
| 302 | /* get the conversion qualifier */ | ||
| 303 | *size = -1; | ||
| 304 | if (strchr("hlLb", *fmt)) { | ||
| 305 | qualifier = *fmt++; | ||
| 306 | if (qualifier == *fmt) { | ||
| 307 | switch (*fmt++) { | ||
| 308 | /* TODO: case 'l': qualifier = 'L'; break;*/ | ||
| 309 | case 'h': | ||
| 310 | qualifier = 'b'; | ||
| 311 | break; | ||
| 312 | } | ||
| 313 | } | ||
| 314 | } | ||
| 315 | |||
| 316 | /* we should now have a type */ | ||
| 317 | if ((*fmt == '\0') || !strchr("iuxs", *fmt)) | ||
| 318 | return -1; | ||
| 319 | |||
| 320 | /* convert qualifier (bhL) to byte size */ | ||
| 321 | if (*fmt != 's') | ||
| 322 | *size = qualifier == 'b' ? 1 : | ||
| 323 | qualifier == 'h' ? 2 : | ||
| 324 | qualifier == 'l' ? 4 : -1; | ||
| 325 | *type = *fmt++; | ||
| 326 | |||
| 327 | /* that should be it! */ | ||
| 328 | if (*fmt) | ||
| 329 | return -1; | ||
| 330 | return 0; | ||
| 331 | } | ||
diff --git a/scripts/dtc/util.h b/scripts/dtc/util.h index 9cead842c11e..c8eb45d9f04b 100644 --- a/scripts/dtc/util.h +++ b/scripts/dtc/util.h | |||
| @@ -1,7 +1,10 @@ | |||
| 1 | #ifndef _UTIL_H | 1 | #ifndef _UTIL_H |
| 2 | #define _UTIL_H | 2 | #define _UTIL_H |
| 3 | 3 | ||
| 4 | #include <stdarg.h> | ||
| 5 | |||
| 4 | /* | 6 | /* |
| 7 | * Copyright 2011 The Chromium Authors, All Rights Reserved. | ||
| 5 | * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc. | 8 | * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc. |
| 6 | * | 9 | * |
| 7 | * This program is free software; you can redistribute it and/or | 10 | * This program is free software; you can redistribute it and/or |
| @@ -53,4 +56,98 @@ static inline void *xrealloc(void *p, size_t len) | |||
| 53 | extern char *xstrdup(const char *s); | 56 | extern char *xstrdup(const char *s); |
| 54 | extern char *join_path(const char *path, const char *name); | 57 | extern char *join_path(const char *path, const char *name); |
| 55 | 58 | ||
| 59 | /** | ||
| 60 | * Check a string of a given length to see if it is all printable and | ||
| 61 | * has a valid terminator. | ||
| 62 | * | ||
| 63 | * @param data The string to check | ||
| 64 | * @param len The string length including terminator | ||
| 65 | * @return 1 if a valid printable string, 0 if not */ | ||
| 66 | int util_is_printable_string(const void *data, int len); | ||
| 67 | |||
| 68 | /* | ||
| 69 | * Parse an escaped character starting at index i in string s. The resulting | ||
| 70 | * character will be returned and the index i will be updated to point at the | ||
| 71 | * character directly after the end of the encoding, this may be the '\0' | ||
| 72 | * terminator of the string. | ||
| 73 | */ | ||
| 74 | char get_escape_char(const char *s, int *i); | ||
| 75 | |||
| 76 | /** | ||
| 77 | * Read a device tree file into a buffer. This will report any errors on | ||
| 78 | * stderr. | ||
| 79 | * | ||
| 80 | * @param filename The filename to read, or - for stdin | ||
| 81 | * @return Pointer to allocated buffer containing fdt, or NULL on error | ||
| 82 | */ | ||
| 83 | char *utilfdt_read(const char *filename); | ||
| 84 | |||
| 85 | /** | ||
| 86 | * Read a device tree file into a buffer. Does not report errors, but only | ||
| 87 | * returns them. The value returned can be passed to strerror() to obtain | ||
| 88 | * an error message for the user. | ||
| 89 | * | ||
| 90 | * @param filename The filename to read, or - for stdin | ||
| 91 | * @param buffp Returns pointer to buffer containing fdt | ||
| 92 | * @return 0 if ok, else an errno value representing the error | ||
| 93 | */ | ||
| 94 | int utilfdt_read_err(const char *filename, char **buffp); | ||
| 95 | |||
| 96 | |||
| 97 | /** | ||
| 98 | * Write a device tree buffer to a file. This will report any errors on | ||
| 99 | * stderr. | ||
| 100 | * | ||
| 101 | * @param filename The filename to write, or - for stdout | ||
| 102 | * @param blob Poiner to buffer containing fdt | ||
| 103 | * @return 0 if ok, -1 on error | ||
| 104 | */ | ||
| 105 | int utilfdt_write(const char *filename, const void *blob); | ||
| 106 | |||
| 107 | /** | ||
| 108 | * Write a device tree buffer to a file. Does not report errors, but only | ||
| 109 | * returns them. The value returned can be passed to strerror() to obtain | ||
| 110 | * an error message for the user. | ||
| 111 | * | ||
| 112 | * @param filename The filename to write, or - for stdout | ||
| 113 | * @param blob Poiner to buffer containing fdt | ||
| 114 | * @return 0 if ok, else an errno value representing the error | ||
| 115 | */ | ||
| 116 | int utilfdt_write_err(const char *filename, const void *blob); | ||
| 117 | |||
| 118 | /** | ||
| 119 | * Decode a data type string. The purpose of this string | ||
| 120 | * | ||
| 121 | * The string consists of an optional character followed by the type: | ||
| 122 | * Modifier characters: | ||
| 123 | * hh or b 1 byte | ||
| 124 | * h 2 byte | ||
| 125 | * l 4 byte, default | ||
| 126 | * | ||
| 127 | * Type character: | ||
| 128 | * s string | ||
| 129 | * i signed integer | ||
| 130 | * u unsigned integer | ||
| 131 | * x hex | ||
| 132 | * | ||
| 133 | * TODO: Implement ll modifier (8 bytes) | ||
| 134 | * TODO: Implement o type (octal) | ||
| 135 | * | ||
| 136 | * @param fmt Format string to process | ||
| 137 | * @param type Returns type found(s/d/u/x), or 0 if none | ||
| 138 | * @param size Returns size found(1,2,4,8) or 4 if none | ||
| 139 | * @return 0 if ok, -1 on error (no type given, or other invalid format) | ||
| 140 | */ | ||
| 141 | int utilfdt_decode_type(const char *fmt, int *type, int *size); | ||
| 142 | |||
| 143 | /* | ||
| 144 | * This is a usage message fragment for the -t option. It is the format | ||
| 145 | * supported by utilfdt_decode_type. | ||
| 146 | */ | ||
| 147 | |||
| 148 | #define USAGE_TYPE_MSG \ | ||
| 149 | "<type>\ts=string, i=int, u=unsigned, x=hex\n" \ | ||
| 150 | "\tOptional modifier prefix:\n" \ | ||
| 151 | "\t\thh or b=byte, h=2 byte, l=4 byte (default)\n"; | ||
| 152 | |||
| 56 | #endif /* _UTIL_H */ | 153 | #endif /* _UTIL_H */ |
diff --git a/scripts/gcc-version.sh b/scripts/gcc-version.sh index debecb5561c4..7f2126df91f2 100644 --- a/scripts/gcc-version.sh +++ b/scripts/gcc-version.sh | |||
| @@ -22,10 +22,10 @@ if [ ${#compiler} -eq 0 ]; then | |||
| 22 | exit 1 | 22 | exit 1 |
| 23 | fi | 23 | fi |
| 24 | 24 | ||
| 25 | MAJOR=$(echo __GNUC__ | $compiler -E -xc - | tail -n 1) | 25 | MAJOR=$(echo __GNUC__ | $compiler -E -x c - | tail -n 1) |
| 26 | MINOR=$(echo __GNUC_MINOR__ | $compiler -E -xc - | tail -n 1) | 26 | MINOR=$(echo __GNUC_MINOR__ | $compiler -E -x c - | tail -n 1) |
| 27 | if [ "x$with_patchlevel" != "x" ] ; then | 27 | if [ "x$with_patchlevel" != "x" ] ; then |
| 28 | PATCHLEVEL=$(echo __GNUC_PATCHLEVEL__ | $compiler -E -xc - | tail -n 1) | 28 | PATCHLEVEL=$(echo __GNUC_PATCHLEVEL__ | $compiler -E -x c - | tail -n 1) |
| 29 | printf "%02d%02d%02d\\n" $MAJOR $MINOR $PATCHLEVEL | 29 | printf "%02d%02d%02d\\n" $MAJOR $MINOR $PATCHLEVEL |
| 30 | else | 30 | else |
| 31 | printf "%02d%02d\\n" $MAJOR $MINOR | 31 | printf "%02d%02d\\n" $MAJOR $MINOR |
diff --git a/scripts/gcc-x86_32-has-stack-protector.sh b/scripts/gcc-x86_32-has-stack-protector.sh index 29493dc4528d..12dbd0b11ea4 100644 --- a/scripts/gcc-x86_32-has-stack-protector.sh +++ b/scripts/gcc-x86_32-has-stack-protector.sh | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | #!/bin/sh | 1 | #!/bin/sh |
| 2 | 2 | ||
| 3 | echo "int foo(void) { char X[200]; return 3; }" | $* -S -xc -c -O0 -fstack-protector - -o - 2> /dev/null | grep -q "%gs" | 3 | echo "int foo(void) { char X[200]; return 3; }" | $* -S -x c -c -O0 -fstack-protector - -o - 2> /dev/null | grep -q "%gs" |
| 4 | if [ "$?" -eq "0" ] ; then | 4 | if [ "$?" -eq "0" ] ; then |
| 5 | echo y | 5 | echo y |
| 6 | else | 6 | else |
diff --git a/scripts/gcc-x86_64-has-stack-protector.sh b/scripts/gcc-x86_64-has-stack-protector.sh index afaec618b395..973e8c141567 100644 --- a/scripts/gcc-x86_64-has-stack-protector.sh +++ b/scripts/gcc-x86_64-has-stack-protector.sh | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | #!/bin/sh | 1 | #!/bin/sh |
| 2 | 2 | ||
| 3 | echo "int foo(void) { char X[200]; return 3; }" | $* -S -xc -c -O0 -mcmodel=kernel -fstack-protector - -o - 2> /dev/null | grep -q "%gs" | 3 | echo "int foo(void) { char X[200]; return 3; }" | $* -S -x c -c -O0 -mcmodel=kernel -fstack-protector - -o - 2> /dev/null | grep -q "%gs" |
| 4 | if [ "$?" -eq "0" ] ; then | 4 | if [ "$?" -eq "0" ] ; then |
| 5 | echo y | 5 | echo y |
| 6 | else | 6 | else |
diff --git a/scripts/headers_install.pl b/scripts/headers_install.pl index 48462be328bb..239d22d4207b 100644 --- a/scripts/headers_install.pl +++ b/scripts/headers_install.pl | |||
| @@ -4,8 +4,7 @@ | |||
| 4 | # user space and copy the files to their destination. | 4 | # user space and copy the files to their destination. |
| 5 | # | 5 | # |
| 6 | # Usage: headers_install.pl readdir installdir arch [files...] | 6 | # Usage: headers_install.pl readdir installdir arch [files...] |
| 7 | # readdir: dir to open files | 7 | # installdir: dir to install the files to |
| 8 | # installdir: dir to install the files | ||
| 9 | # arch: current architecture | 8 | # arch: current architecture |
| 10 | # arch is used to force a reinstallation when the arch | 9 | # arch is used to force a reinstallation when the arch |
| 11 | # changes because kbuild then detect a command line change. | 10 | # changes because kbuild then detect a command line change. |
| @@ -18,15 +17,18 @@ | |||
| 18 | 17 | ||
| 19 | use strict; | 18 | use strict; |
| 20 | 19 | ||
| 21 | my ($readdir, $installdir, $arch, @files) = @ARGV; | 20 | my ($installdir, $arch, @files) = @ARGV; |
| 22 | 21 | ||
| 23 | my $unifdef = "scripts/unifdef -U__KERNEL__ -D__EXPORTED_HEADERS__"; | 22 | my $unifdef = "scripts/unifdef -U__KERNEL__ -D__EXPORTED_HEADERS__"; |
| 24 | 23 | ||
| 25 | foreach my $file (@files) { | 24 | foreach my $filename (@files) { |
| 25 | my $file = $filename; | ||
| 26 | $file =~ s!^.*/!!; | ||
| 27 | |||
| 26 | my $tmpfile = "$installdir/$file.tmp"; | 28 | my $tmpfile = "$installdir/$file.tmp"; |
| 27 | 29 | ||
| 28 | open(my $in, '<', "$readdir/$file") | 30 | open(my $in, '<', $filename) |
| 29 | or die "$readdir/$file: $!\n"; | 31 | or die "$filename: $!\n"; |
| 30 | open(my $out, '>', $tmpfile) | 32 | open(my $out, '>', $tmpfile) |
| 31 | or die "$tmpfile: $!\n"; | 33 | or die "$tmpfile: $!\n"; |
| 32 | while (my $line = <$in>) { | 34 | while (my $line = <$in>) { |
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile index 77d53999ffb9..3091794e9354 100644 --- a/scripts/kconfig/Makefile +++ b/scripts/kconfig/Makefile | |||
| @@ -76,11 +76,17 @@ PHONY += allnoconfig allyesconfig allmodconfig alldefconfig randconfig | |||
| 76 | allnoconfig allyesconfig allmodconfig alldefconfig randconfig: $(obj)/conf | 76 | allnoconfig allyesconfig allmodconfig alldefconfig randconfig: $(obj)/conf |
| 77 | $< --$@ $(Kconfig) | 77 | $< --$@ $(Kconfig) |
| 78 | 78 | ||
| 79 | PHONY += listnewconfig oldnoconfig savedefconfig defconfig | 79 | PHONY += listnewconfig olddefconfig oldnoconfig savedefconfig defconfig |
| 80 | 80 | ||
| 81 | listnewconfig oldnoconfig: $(obj)/conf | 81 | listnewconfig olddefconfig: $(obj)/conf |
| 82 | $< --$@ $(Kconfig) | 82 | $< --$@ $(Kconfig) |
| 83 | 83 | ||
| 84 | # oldnoconfig is an alias of olddefconfig, because people already are dependent | ||
| 85 | # on its behavior(sets new symbols to their default value but not 'n') with the | ||
| 86 | # counter-intuitive name. | ||
| 87 | oldnoconfig: $(obj)/conf | ||
| 88 | $< --olddefconfig $(Kconfig) | ||
| 89 | |||
| 84 | savedefconfig: $(obj)/conf | 90 | savedefconfig: $(obj)/conf |
| 85 | $< --$@=defconfig $(Kconfig) | 91 | $< --$@=defconfig $(Kconfig) |
| 86 | 92 | ||
| @@ -114,7 +120,7 @@ help: | |||
| 114 | @echo ' alldefconfig - New config with all symbols set to default' | 120 | @echo ' alldefconfig - New config with all symbols set to default' |
| 115 | @echo ' randconfig - New config with random answer to all options' | 121 | @echo ' randconfig - New config with random answer to all options' |
| 116 | @echo ' listnewconfig - List new options' | 122 | @echo ' listnewconfig - List new options' |
| 117 | @echo ' oldnoconfig - Same as silentoldconfig but sets new symbols to their default value' | 123 | @echo ' olddefconfig - Same as silentoldconfig but sets new symbols to their default value' |
| 118 | 124 | ||
| 119 | # lxdialog stuff | 125 | # lxdialog stuff |
| 120 | check-lxdialog := $(srctree)/$(src)/lxdialog/check-lxdialog.sh | 126 | check-lxdialog := $(srctree)/$(src)/lxdialog/check-lxdialog.sh |
diff --git a/scripts/kconfig/check.sh b/scripts/kconfig/check.sh index fa59cbf9d62c..854d9c7c675c 100755 --- a/scripts/kconfig/check.sh +++ b/scripts/kconfig/check.sh | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | #!/bin/sh | 1 | #!/bin/sh |
| 2 | # Needed for systems without gettext | 2 | # Needed for systems without gettext |
| 3 | $* -xc -o /dev/null - > /dev/null 2>&1 << EOF | 3 | $* -x c -o /dev/null - > /dev/null 2>&1 << EOF |
| 4 | #include <libintl.h> | 4 | #include <libintl.h> |
| 5 | int main() | 5 | int main() |
| 6 | { | 6 | { |
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c index 0dc4a2c779b1..4da3b4adfad2 100644 --- a/scripts/kconfig/conf.c +++ b/scripts/kconfig/conf.c | |||
| @@ -32,7 +32,7 @@ enum input_mode { | |||
| 32 | defconfig, | 32 | defconfig, |
| 33 | savedefconfig, | 33 | savedefconfig, |
| 34 | listnewconfig, | 34 | listnewconfig, |
| 35 | oldnoconfig, | 35 | olddefconfig, |
| 36 | } input_mode = oldaskconfig; | 36 | } input_mode = oldaskconfig; |
| 37 | 37 | ||
| 38 | static int indent = 1; | 38 | static int indent = 1; |
| @@ -365,7 +365,7 @@ static void conf(struct menu *menu) | |||
| 365 | case P_MENU: | 365 | case P_MENU: |
| 366 | if ((input_mode == silentoldconfig || | 366 | if ((input_mode == silentoldconfig || |
| 367 | input_mode == listnewconfig || | 367 | input_mode == listnewconfig || |
| 368 | input_mode == oldnoconfig) && | 368 | input_mode == olddefconfig) && |
| 369 | rootEntry != menu) { | 369 | rootEntry != menu) { |
| 370 | check_conf(menu); | 370 | check_conf(menu); |
| 371 | return; | 371 | return; |
| @@ -429,7 +429,7 @@ static void check_conf(struct menu *menu) | |||
| 429 | if (sym->name && !sym_is_choice_value(sym)) { | 429 | if (sym->name && !sym_is_choice_value(sym)) { |
| 430 | printf("%s%s\n", CONFIG_, sym->name); | 430 | printf("%s%s\n", CONFIG_, sym->name); |
| 431 | } | 431 | } |
| 432 | } else if (input_mode != oldnoconfig) { | 432 | } else if (input_mode != olddefconfig) { |
| 433 | if (!conf_cnt++) | 433 | if (!conf_cnt++) |
| 434 | printf(_("*\n* Restart config...\n*\n")); | 434 | printf(_("*\n* Restart config...\n*\n")); |
| 435 | rootEntry = menu_get_parent_menu(menu); | 435 | rootEntry = menu_get_parent_menu(menu); |
| @@ -454,7 +454,13 @@ static struct option long_opts[] = { | |||
| 454 | {"alldefconfig", no_argument, NULL, alldefconfig}, | 454 | {"alldefconfig", no_argument, NULL, alldefconfig}, |
| 455 | {"randconfig", no_argument, NULL, randconfig}, | 455 | {"randconfig", no_argument, NULL, randconfig}, |
| 456 | {"listnewconfig", no_argument, NULL, listnewconfig}, | 456 | {"listnewconfig", no_argument, NULL, listnewconfig}, |
| 457 | {"oldnoconfig", no_argument, NULL, oldnoconfig}, | 457 | {"olddefconfig", no_argument, NULL, olddefconfig}, |
| 458 | /* | ||
| 459 | * oldnoconfig is an alias of olddefconfig, because people already | ||
| 460 | * are dependent on its behavior(sets new symbols to their default | ||
| 461 | * value but not 'n') with the counter-intuitive name. | ||
| 462 | */ | ||
| 463 | {"oldnoconfig", no_argument, NULL, olddefconfig}, | ||
| 458 | {NULL, 0, NULL, 0} | 464 | {NULL, 0, NULL, 0} |
| 459 | }; | 465 | }; |
| 460 | 466 | ||
| @@ -467,7 +473,8 @@ static void conf_usage(const char *progname) | |||
| 467 | printf(" --oldaskconfig Start a new configuration using a line-oriented program\n"); | 473 | printf(" --oldaskconfig Start a new configuration using a line-oriented program\n"); |
| 468 | printf(" --oldconfig Update a configuration using a provided .config as base\n"); | 474 | printf(" --oldconfig Update a configuration using a provided .config as base\n"); |
| 469 | printf(" --silentoldconfig Same as oldconfig, but quietly, additionally update deps\n"); | 475 | printf(" --silentoldconfig Same as oldconfig, but quietly, additionally update deps\n"); |
| 470 | printf(" --oldnoconfig Same as silentoldconfig but set new symbols to no\n"); | 476 | printf(" --olddefconfig Same as silentoldconfig but sets new symbols to their default value\n"); |
| 477 | printf(" --oldnoconfig An alias of olddefconfig\n"); | ||
| 471 | printf(" --defconfig <file> New config with default defined in <file>\n"); | 478 | printf(" --defconfig <file> New config with default defined in <file>\n"); |
| 472 | printf(" --savedefconfig <file> Save the minimal current configuration to <file>\n"); | 479 | printf(" --savedefconfig <file> Save the minimal current configuration to <file>\n"); |
| 473 | printf(" --allnoconfig New config where all options are answered with no\n"); | 480 | printf(" --allnoconfig New config where all options are answered with no\n"); |
| @@ -520,7 +527,7 @@ int main(int ac, char **av) | |||
| 520 | case allmodconfig: | 527 | case allmodconfig: |
| 521 | case alldefconfig: | 528 | case alldefconfig: |
| 522 | case listnewconfig: | 529 | case listnewconfig: |
| 523 | case oldnoconfig: | 530 | case olddefconfig: |
| 524 | break; | 531 | break; |
| 525 | case '?': | 532 | case '?': |
| 526 | conf_usage(progname); | 533 | conf_usage(progname); |
| @@ -565,7 +572,7 @@ int main(int ac, char **av) | |||
| 565 | case oldaskconfig: | 572 | case oldaskconfig: |
| 566 | case oldconfig: | 573 | case oldconfig: |
| 567 | case listnewconfig: | 574 | case listnewconfig: |
| 568 | case oldnoconfig: | 575 | case olddefconfig: |
| 569 | conf_read(NULL); | 576 | conf_read(NULL); |
| 570 | break; | 577 | break; |
| 571 | case allnoconfig: | 578 | case allnoconfig: |
| @@ -645,7 +652,7 @@ int main(int ac, char **av) | |||
| 645 | /* fall through */ | 652 | /* fall through */ |
| 646 | case oldconfig: | 653 | case oldconfig: |
| 647 | case listnewconfig: | 654 | case listnewconfig: |
| 648 | case oldnoconfig: | 655 | case olddefconfig: |
| 649 | case silentoldconfig: | 656 | case silentoldconfig: |
| 650 | /* Update until a loop caused no more changes */ | 657 | /* Update until a loop caused no more changes */ |
| 651 | do { | 658 | do { |
| @@ -653,7 +660,7 @@ int main(int ac, char **av) | |||
| 653 | check_conf(&rootmenu); | 660 | check_conf(&rootmenu); |
| 654 | } while (conf_cnt && | 661 | } while (conf_cnt && |
| 655 | (input_mode != listnewconfig && | 662 | (input_mode != listnewconfig && |
| 656 | input_mode != oldnoconfig)); | 663 | input_mode != olddefconfig)); |
| 657 | break; | 664 | break; |
| 658 | } | 665 | } |
| 659 | 666 | ||
diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h index d4ecce8bc3a6..bd2e09895553 100644 --- a/scripts/kconfig/expr.h +++ b/scripts/kconfig/expr.h | |||
| @@ -12,6 +12,7 @@ extern "C" { | |||
| 12 | 12 | ||
| 13 | #include <assert.h> | 13 | #include <assert.h> |
| 14 | #include <stdio.h> | 14 | #include <stdio.h> |
| 15 | #include <sys/queue.h> | ||
| 15 | #ifndef __cplusplus | 16 | #ifndef __cplusplus |
| 16 | #include <stdbool.h> | 17 | #include <stdbool.h> |
| 17 | #endif | 18 | #endif |
| @@ -173,6 +174,16 @@ struct menu { | |||
| 173 | #define MENU_CHANGED 0x0001 | 174 | #define MENU_CHANGED 0x0001 |
| 174 | #define MENU_ROOT 0x0002 | 175 | #define MENU_ROOT 0x0002 |
| 175 | 176 | ||
| 177 | struct jump_key { | ||
| 178 | CIRCLEQ_ENTRY(jump_key) entries; | ||
| 179 | size_t offset; | ||
| 180 | struct menu *target; | ||
| 181 | int index; | ||
| 182 | }; | ||
| 183 | CIRCLEQ_HEAD(jk_head, jump_key); | ||
| 184 | |||
| 185 | #define JUMP_NB 9 | ||
| 186 | |||
| 176 | extern struct file *file_list; | 187 | extern struct file *file_list; |
| 177 | extern struct file *current_file; | 188 | extern struct file *current_file; |
| 178 | struct file *lookup_file(const char *name); | 189 | struct file *lookup_file(const char *name); |
diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h index 47fe9c340f9a..1d1c08537f1e 100644 --- a/scripts/kconfig/lkc_proto.h +++ b/scripts/kconfig/lkc_proto.h | |||
| @@ -21,8 +21,10 @@ P(menu_get_root_menu,struct menu *,(struct menu *menu)); | |||
| 21 | P(menu_get_parent_menu,struct menu *,(struct menu *menu)); | 21 | P(menu_get_parent_menu,struct menu *,(struct menu *menu)); |
| 22 | P(menu_has_help,bool,(struct menu *menu)); | 22 | P(menu_has_help,bool,(struct menu *menu)); |
| 23 | P(menu_get_help,const char *,(struct menu *menu)); | 23 | P(menu_get_help,const char *,(struct menu *menu)); |
| 24 | P(get_symbol_str, void, (struct gstr *r, struct symbol *sym)); | 24 | P(get_symbol_str, void, (struct gstr *r, struct symbol *sym, struct jk_head |
| 25 | P(get_relations_str, struct gstr, (struct symbol **sym_arr)); | 25 | *head)); |
| 26 | P(get_relations_str, struct gstr, (struct symbol **sym_arr, struct jk_head | ||
| 27 | *head)); | ||
| 26 | P(menu_get_ext_help,void,(struct menu *menu, struct gstr *help)); | 28 | P(menu_get_ext_help,void,(struct menu *menu, struct gstr *help)); |
| 27 | 29 | ||
| 28 | /* symbol.c */ | 30 | /* symbol.c */ |
diff --git a/scripts/kconfig/lxdialog/check-lxdialog.sh b/scripts/kconfig/lxdialog/check-lxdialog.sh index e3b12c010417..c8e8a7154753 100644 --- a/scripts/kconfig/lxdialog/check-lxdialog.sh +++ b/scripts/kconfig/lxdialog/check-lxdialog.sh | |||
| @@ -38,7 +38,7 @@ trap "rm -f $tmp" 0 1 2 3 15 | |||
| 38 | 38 | ||
| 39 | # Check if we can link to ncurses | 39 | # Check if we can link to ncurses |
| 40 | check() { | 40 | check() { |
| 41 | $cc -xc - -o $tmp 2>/dev/null <<'EOF' | 41 | $cc -x c - -o $tmp 2>/dev/null <<'EOF' |
| 42 | #include CURSES_LOC | 42 | #include CURSES_LOC |
| 43 | main() {} | 43 | main() {} |
| 44 | EOF | 44 | EOF |
diff --git a/scripts/kconfig/lxdialog/dialog.h b/scripts/kconfig/lxdialog/dialog.h index b5211fce0d94..ee17a5264d5b 100644 --- a/scripts/kconfig/lxdialog/dialog.h +++ b/scripts/kconfig/lxdialog/dialog.h | |||
| @@ -144,6 +144,7 @@ struct dialog_info { | |||
| 144 | */ | 144 | */ |
| 145 | extern struct dialog_info dlg; | 145 | extern struct dialog_info dlg; |
| 146 | extern char dialog_input_result[]; | 146 | extern char dialog_input_result[]; |
| 147 | extern int saved_x, saved_y; /* Needed in signal handler in mconf.c */ | ||
| 147 | 148 | ||
| 148 | /* | 149 | /* |
| 149 | * Function prototypes | 150 | * Function prototypes |
| @@ -209,7 +210,13 @@ int first_alpha(const char *string, const char *exempt); | |||
| 209 | int dialog_yesno(const char *title, const char *prompt, int height, int width); | 210 | int dialog_yesno(const char *title, const char *prompt, int height, int width); |
| 210 | int dialog_msgbox(const char *title, const char *prompt, int height, | 211 | int dialog_msgbox(const char *title, const char *prompt, int height, |
| 211 | int width, int pause); | 212 | int width, int pause); |
| 212 | int dialog_textbox(const char *title, const char *file, int height, int width); | 213 | |
| 214 | |||
| 215 | typedef void (*update_text_fn)(char *buf, size_t start, size_t end, void | ||
| 216 | *_data); | ||
| 217 | int dialog_textbox(const char *title, char *tbuf, int initial_height, | ||
| 218 | int initial_width, int *keys, int *_vscroll, int *_hscroll, | ||
| 219 | update_text_fn update_text, void *data); | ||
| 213 | int dialog_menu(const char *title, const char *prompt, | 220 | int dialog_menu(const char *title, const char *prompt, |
| 214 | const void *selected, int *s_scroll); | 221 | const void *selected, int *s_scroll); |
| 215 | int dialog_checklist(const char *title, const char *prompt, int height, | 222 | int dialog_checklist(const char *title, const char *prompt, int height, |
diff --git a/scripts/kconfig/lxdialog/textbox.c b/scripts/kconfig/lxdialog/textbox.c index 4e5de60a0c0d..a48bb93e0907 100644 --- a/scripts/kconfig/lxdialog/textbox.c +++ b/scripts/kconfig/lxdialog/textbox.c | |||
| @@ -22,23 +22,25 @@ | |||
| 22 | #include "dialog.h" | 22 | #include "dialog.h" |
| 23 | 23 | ||
| 24 | static void back_lines(int n); | 24 | static void back_lines(int n); |
| 25 | static void print_page(WINDOW * win, int height, int width); | 25 | static void print_page(WINDOW *win, int height, int width, update_text_fn |
| 26 | static void print_line(WINDOW * win, int row, int width); | 26 | update_text, void *data); |
| 27 | static void print_line(WINDOW *win, int row, int width); | ||
| 27 | static char *get_line(void); | 28 | static char *get_line(void); |
| 28 | static void print_position(WINDOW * win); | 29 | static void print_position(WINDOW * win); |
| 29 | 30 | ||
| 30 | static int hscroll; | 31 | static int hscroll; |
| 31 | static int begin_reached, end_reached, page_length; | 32 | static int begin_reached, end_reached, page_length; |
| 32 | static const char *buf; | 33 | static char *buf; |
| 33 | static const char *page; | 34 | static char *page; |
| 34 | 35 | ||
| 35 | /* | 36 | /* |
| 36 | * refresh window content | 37 | * refresh window content |
| 37 | */ | 38 | */ |
| 38 | static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw, | 39 | static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw, |
| 39 | int cur_y, int cur_x) | 40 | int cur_y, int cur_x, update_text_fn update_text, |
| 41 | void *data) | ||
| 40 | { | 42 | { |
| 41 | print_page(box, boxh, boxw); | 43 | print_page(box, boxh, boxw, update_text, data); |
| 42 | print_position(dialog); | 44 | print_position(dialog); |
| 43 | wmove(dialog, cur_y, cur_x); /* Restore cursor position */ | 45 | wmove(dialog, cur_y, cur_x); /* Restore cursor position */ |
| 44 | wrefresh(dialog); | 46 | wrefresh(dialog); |
| @@ -47,14 +49,18 @@ static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw, | |||
| 47 | 49 | ||
| 48 | /* | 50 | /* |
| 49 | * Display text from a file in a dialog box. | 51 | * Display text from a file in a dialog box. |
| 52 | * | ||
| 53 | * keys is a null-terminated array | ||
| 54 | * update_text() may not add or remove any '\n' or '\0' in tbuf | ||
| 50 | */ | 55 | */ |
| 51 | int dialog_textbox(const char *title, const char *tbuf, | 56 | int dialog_textbox(const char *title, char *tbuf, int initial_height, |
| 52 | int initial_height, int initial_width) | 57 | int initial_width, int *keys, int *_vscroll, int *_hscroll, |
| 58 | update_text_fn update_text, void *data) | ||
| 53 | { | 59 | { |
| 54 | int i, x, y, cur_x, cur_y, key = 0; | 60 | int i, x, y, cur_x, cur_y, key = 0; |
| 55 | int height, width, boxh, boxw; | 61 | int height, width, boxh, boxw; |
| 56 | int passed_end; | ||
| 57 | WINDOW *dialog, *box; | 62 | WINDOW *dialog, *box; |
| 63 | bool done = false; | ||
| 58 | 64 | ||
| 59 | begin_reached = 1; | 65 | begin_reached = 1; |
| 60 | end_reached = 0; | 66 | end_reached = 0; |
| @@ -63,6 +69,15 @@ int dialog_textbox(const char *title, const char *tbuf, | |||
| 63 | buf = tbuf; | 69 | buf = tbuf; |
| 64 | page = buf; /* page is pointer to start of page to be displayed */ | 70 | page = buf; /* page is pointer to start of page to be displayed */ |
| 65 | 71 | ||
| 72 | if (_vscroll && *_vscroll) { | ||
| 73 | begin_reached = 0; | ||
| 74 | |||
| 75 | for (i = 0; i < *_vscroll; i++) | ||
| 76 | get_line(); | ||
| 77 | } | ||
| 78 | if (_hscroll) | ||
| 79 | hscroll = *_hscroll; | ||
| 80 | |||
| 66 | do_resize: | 81 | do_resize: |
| 67 | getmaxyx(stdscr, height, width); | 82 | getmaxyx(stdscr, height, width); |
| 68 | if (height < 8 || width < 8) | 83 | if (height < 8 || width < 8) |
| @@ -120,9 +135,10 @@ do_resize: | |||
| 120 | 135 | ||
| 121 | /* Print first page of text */ | 136 | /* Print first page of text */ |
| 122 | attr_clear(box, boxh, boxw, dlg.dialog.atr); | 137 | attr_clear(box, boxh, boxw, dlg.dialog.atr); |
| 123 | refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x); | 138 | refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x, update_text, |
| 139 | data); | ||
| 124 | 140 | ||
| 125 | while ((key != KEY_ESC) && (key != '\n')) { | 141 | while (!done) { |
| 126 | key = wgetch(dialog); | 142 | key = wgetch(dialog); |
| 127 | switch (key) { | 143 | switch (key) { |
| 128 | case 'E': /* Exit */ | 144 | case 'E': /* Exit */ |
| @@ -130,16 +146,17 @@ do_resize: | |||
| 130 | case 'X': | 146 | case 'X': |
| 131 | case 'x': | 147 | case 'x': |
| 132 | case 'q': | 148 | case 'q': |
| 133 | delwin(box); | 149 | case '\n': |
| 134 | delwin(dialog); | 150 | done = true; |
| 135 | return 0; | 151 | break; |
| 136 | case 'g': /* First page */ | 152 | case 'g': /* First page */ |
| 137 | case KEY_HOME: | 153 | case KEY_HOME: |
| 138 | if (!begin_reached) { | 154 | if (!begin_reached) { |
| 139 | begin_reached = 1; | 155 | begin_reached = 1; |
| 140 | page = buf; | 156 | page = buf; |
| 141 | refresh_text_box(dialog, box, boxh, boxw, | 157 | refresh_text_box(dialog, box, boxh, boxw, |
| 142 | cur_y, cur_x); | 158 | cur_y, cur_x, update_text, |
| 159 | data); | ||
| 143 | } | 160 | } |
| 144 | break; | 161 | break; |
| 145 | case 'G': /* Last page */ | 162 | case 'G': /* Last page */ |
| @@ -149,45 +166,18 @@ do_resize: | |||
| 149 | /* point to last char in buf */ | 166 | /* point to last char in buf */ |
| 150 | page = buf + strlen(buf); | 167 | page = buf + strlen(buf); |
| 151 | back_lines(boxh); | 168 | back_lines(boxh); |
| 152 | refresh_text_box(dialog, box, boxh, boxw, | 169 | refresh_text_box(dialog, box, boxh, boxw, cur_y, |
| 153 | cur_y, cur_x); | 170 | cur_x, update_text, data); |
| 154 | break; | 171 | break; |
| 155 | case 'K': /* Previous line */ | 172 | case 'K': /* Previous line */ |
| 156 | case 'k': | 173 | case 'k': |
| 157 | case KEY_UP: | 174 | case KEY_UP: |
| 158 | if (!begin_reached) { | 175 | if (begin_reached) |
| 159 | back_lines(page_length + 1); | 176 | break; |
| 160 | |||
| 161 | /* We don't call print_page() here but use | ||
| 162 | * scrolling to ensure faster screen update. | ||
| 163 | * However, 'end_reached' and 'page_length' | ||
| 164 | * should still be updated, and 'page' should | ||
| 165 | * point to start of next page. This is done | ||
| 166 | * by calling get_line() in the following | ||
| 167 | * 'for' loop. */ | ||
| 168 | scrollok(box, TRUE); | ||
| 169 | wscrl(box, -1); /* Scroll box region down one line */ | ||
| 170 | scrollok(box, FALSE); | ||
| 171 | page_length = 0; | ||
| 172 | passed_end = 0; | ||
| 173 | for (i = 0; i < boxh; i++) { | ||
| 174 | if (!i) { | ||
| 175 | /* print first line of page */ | ||
| 176 | print_line(box, 0, boxw); | ||
| 177 | wnoutrefresh(box); | ||
| 178 | } else | ||
| 179 | /* Called to update 'end_reached' and 'page' */ | ||
| 180 | get_line(); | ||
| 181 | if (!passed_end) | ||
| 182 | page_length++; | ||
| 183 | if (end_reached && !passed_end) | ||
| 184 | passed_end = 1; | ||
| 185 | } | ||
| 186 | 177 | ||
| 187 | print_position(dialog); | 178 | back_lines(page_length + 1); |
| 188 | wmove(dialog, cur_y, cur_x); /* Restore cursor position */ | 179 | refresh_text_box(dialog, box, boxh, boxw, cur_y, |
| 189 | wrefresh(dialog); | 180 | cur_x, update_text, data); |
| 190 | } | ||
| 191 | break; | 181 | break; |
| 192 | case 'B': /* Previous page */ | 182 | case 'B': /* Previous page */ |
| 193 | case 'b': | 183 | case 'b': |
| @@ -196,23 +186,18 @@ do_resize: | |||
| 196 | if (begin_reached) | 186 | if (begin_reached) |
| 197 | break; | 187 | break; |
| 198 | back_lines(page_length + boxh); | 188 | back_lines(page_length + boxh); |
| 199 | refresh_text_box(dialog, box, boxh, boxw, | 189 | refresh_text_box(dialog, box, boxh, boxw, cur_y, |
| 200 | cur_y, cur_x); | 190 | cur_x, update_text, data); |
| 201 | break; | 191 | break; |
| 202 | case 'J': /* Next line */ | 192 | case 'J': /* Next line */ |
| 203 | case 'j': | 193 | case 'j': |
| 204 | case KEY_DOWN: | 194 | case KEY_DOWN: |
| 205 | if (!end_reached) { | 195 | if (end_reached) |
| 206 | begin_reached = 0; | 196 | break; |
| 207 | scrollok(box, TRUE); | 197 | |
| 208 | scroll(box); /* Scroll box region up one line */ | 198 | back_lines(page_length - 1); |
| 209 | scrollok(box, FALSE); | 199 | refresh_text_box(dialog, box, boxh, boxw, cur_y, |
| 210 | print_line(box, boxh - 1, boxw); | 200 | cur_x, update_text, data); |
| 211 | wnoutrefresh(box); | ||
| 212 | print_position(dialog); | ||
| 213 | wmove(dialog, cur_y, cur_x); /* Restore cursor position */ | ||
| 214 | wrefresh(dialog); | ||
| 215 | } | ||
| 216 | break; | 201 | break; |
| 217 | case KEY_NPAGE: /* Next page */ | 202 | case KEY_NPAGE: /* Next page */ |
| 218 | case ' ': | 203 | case ' ': |
| @@ -221,8 +206,8 @@ do_resize: | |||
| 221 | break; | 206 | break; |
| 222 | 207 | ||
| 223 | begin_reached = 0; | 208 | begin_reached = 0; |
| 224 | refresh_text_box(dialog, box, boxh, boxw, | 209 | refresh_text_box(dialog, box, boxh, boxw, cur_y, |
| 225 | cur_y, cur_x); | 210 | cur_x, update_text, data); |
| 226 | break; | 211 | break; |
| 227 | case '0': /* Beginning of line */ | 212 | case '0': /* Beginning of line */ |
| 228 | case 'H': /* Scroll left */ | 213 | case 'H': /* Scroll left */ |
| @@ -237,8 +222,8 @@ do_resize: | |||
| 237 | hscroll--; | 222 | hscroll--; |
| 238 | /* Reprint current page to scroll horizontally */ | 223 | /* Reprint current page to scroll horizontally */ |
| 239 | back_lines(page_length); | 224 | back_lines(page_length); |
| 240 | refresh_text_box(dialog, box, boxh, boxw, | 225 | refresh_text_box(dialog, box, boxh, boxw, cur_y, |
| 241 | cur_y, cur_x); | 226 | cur_x, update_text, data); |
| 242 | break; | 227 | break; |
| 243 | case 'L': /* Scroll right */ | 228 | case 'L': /* Scroll right */ |
| 244 | case 'l': | 229 | case 'l': |
| @@ -248,11 +233,12 @@ do_resize: | |||
| 248 | hscroll++; | 233 | hscroll++; |
| 249 | /* Reprint current page to scroll horizontally */ | 234 | /* Reprint current page to scroll horizontally */ |
| 250 | back_lines(page_length); | 235 | back_lines(page_length); |
| 251 | refresh_text_box(dialog, box, boxh, boxw, | 236 | refresh_text_box(dialog, box, boxh, boxw, cur_y, |
| 252 | cur_y, cur_x); | 237 | cur_x, update_text, data); |
| 253 | break; | 238 | break; |
| 254 | case KEY_ESC: | 239 | case KEY_ESC: |
| 255 | key = on_key_esc(dialog); | 240 | if (on_key_esc(dialog) == KEY_ESC) |
| 241 | done = true; | ||
| 256 | break; | 242 | break; |
| 257 | case KEY_RESIZE: | 243 | case KEY_RESIZE: |
| 258 | back_lines(height); | 244 | back_lines(height); |
| @@ -260,11 +246,31 @@ do_resize: | |||
| 260 | delwin(dialog); | 246 | delwin(dialog); |
| 261 | on_key_resize(); | 247 | on_key_resize(); |
| 262 | goto do_resize; | 248 | goto do_resize; |
| 249 | default: | ||
| 250 | for (i = 0; keys[i]; i++) { | ||
| 251 | if (key == keys[i]) { | ||
| 252 | done = true; | ||
| 253 | break; | ||
| 254 | } | ||
| 255 | } | ||
| 263 | } | 256 | } |
| 264 | } | 257 | } |
| 265 | delwin(box); | 258 | delwin(box); |
| 266 | delwin(dialog); | 259 | delwin(dialog); |
| 267 | return key; /* ESC pressed */ | 260 | if (_vscroll) { |
| 261 | const char *s; | ||
| 262 | |||
| 263 | s = buf; | ||
| 264 | *_vscroll = 0; | ||
| 265 | back_lines(page_length); | ||
| 266 | while (s < page && (s = strchr(s, '\n'))) { | ||
| 267 | (*_vscroll)++; | ||
| 268 | s++; | ||
| 269 | } | ||
| 270 | } | ||
| 271 | if (_hscroll) | ||
| 272 | *_hscroll = hscroll; | ||
| 273 | return key; | ||
| 268 | } | 274 | } |
| 269 | 275 | ||
| 270 | /* | 276 | /* |
| @@ -301,12 +307,23 @@ static void back_lines(int n) | |||
| 301 | } | 307 | } |
| 302 | 308 | ||
| 303 | /* | 309 | /* |
| 304 | * Print a new page of text. Called by dialog_textbox(). | 310 | * Print a new page of text. |
| 305 | */ | 311 | */ |
| 306 | static void print_page(WINDOW * win, int height, int width) | 312 | static void print_page(WINDOW *win, int height, int width, update_text_fn |
| 313 | update_text, void *data) | ||
| 307 | { | 314 | { |
| 308 | int i, passed_end = 0; | 315 | int i, passed_end = 0; |
| 309 | 316 | ||
| 317 | if (update_text) { | ||
| 318 | char *end; | ||
| 319 | |||
| 320 | for (i = 0; i < height; i++) | ||
| 321 | get_line(); | ||
| 322 | end = page; | ||
| 323 | back_lines(height); | ||
| 324 | update_text(buf, page - buf, end - buf, data); | ||
| 325 | } | ||
| 326 | |||
| 310 | page_length = 0; | 327 | page_length = 0; |
| 311 | for (i = 0; i < height; i++) { | 328 | for (i = 0; i < height; i++) { |
| 312 | print_line(win, i, width); | 329 | print_line(win, i, width); |
| @@ -319,7 +336,7 @@ static void print_page(WINDOW * win, int height, int width) | |||
| 319 | } | 336 | } |
| 320 | 337 | ||
| 321 | /* | 338 | /* |
| 322 | * Print a new line of text. Called by dialog_textbox() and print_page(). | 339 | * Print a new line of text. |
| 323 | */ | 340 | */ |
| 324 | static void print_line(WINDOW * win, int row, int width) | 341 | static void print_line(WINDOW * win, int row, int width) |
| 325 | { | 342 | { |
| @@ -357,10 +374,8 @@ static char *get_line(void) | |||
| 357 | end_reached = 0; | 374 | end_reached = 0; |
| 358 | while (*page != '\n') { | 375 | while (*page != '\n') { |
| 359 | if (*page == '\0') { | 376 | if (*page == '\0') { |
| 360 | if (!end_reached) { | 377 | end_reached = 1; |
| 361 | end_reached = 1; | 378 | break; |
| 362 | break; | ||
| 363 | } | ||
| 364 | } else if (i < MAX_LEN) | 379 | } else if (i < MAX_LEN) |
| 365 | line[i++] = *(page++); | 380 | line[i++] = *(page++); |
| 366 | else { | 381 | else { |
| @@ -373,7 +388,7 @@ static char *get_line(void) | |||
| 373 | if (i <= MAX_LEN) | 388 | if (i <= MAX_LEN) |
| 374 | line[i] = '\0'; | 389 | line[i] = '\0'; |
| 375 | if (!end_reached) | 390 | if (!end_reached) |
| 376 | page++; /* move pass '\n' */ | 391 | page++; /* move past '\n' */ |
| 377 | 392 | ||
| 378 | return line; | 393 | return line; |
| 379 | } | 394 | } |
diff --git a/scripts/kconfig/lxdialog/util.c b/scripts/kconfig/lxdialog/util.c index f2375ad7ebc9..109d53117d22 100644 --- a/scripts/kconfig/lxdialog/util.c +++ b/scripts/kconfig/lxdialog/util.c | |||
| @@ -23,6 +23,9 @@ | |||
| 23 | 23 | ||
| 24 | #include "dialog.h" | 24 | #include "dialog.h" |
| 25 | 25 | ||
| 26 | /* Needed in signal handler in mconf.c */ | ||
| 27 | int saved_x, saved_y; | ||
| 28 | |||
| 26 | struct dialog_info dlg; | 29 | struct dialog_info dlg; |
| 27 | 30 | ||
| 28 | static void set_mono_theme(void) | 31 | static void set_mono_theme(void) |
| @@ -273,6 +276,10 @@ int init_dialog(const char *backtitle) | |||
| 273 | int height, width; | 276 | int height, width; |
| 274 | 277 | ||
| 275 | initscr(); /* Init curses */ | 278 | initscr(); /* Init curses */ |
| 279 | |||
| 280 | /* Get current cursor position for signal handler in mconf.c */ | ||
| 281 | getyx(stdscr, saved_y, saved_x); | ||
| 282 | |||
| 276 | getmaxyx(stdscr, height, width); | 283 | getmaxyx(stdscr, height, width); |
| 277 | if (height < 19 || width < 80) { | 284 | if (height < 19 || width < 80) { |
| 278 | endwin(); | 285 | endwin(); |
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c index f584a281bb4c..48f67448af7b 100644 --- a/scripts/kconfig/mconf.c +++ b/scripts/kconfig/mconf.c | |||
| @@ -236,16 +236,19 @@ search_help[] = N_( | |||
| 236 | "Result:\n" | 236 | "Result:\n" |
| 237 | "-----------------------------------------------------------------\n" | 237 | "-----------------------------------------------------------------\n" |
| 238 | "Symbol: FOO [=m]\n" | 238 | "Symbol: FOO [=m]\n" |
| 239 | "Type : tristate\n" | ||
| 239 | "Prompt: Foo bus is used to drive the bar HW\n" | 240 | "Prompt: Foo bus is used to drive the bar HW\n" |
| 240 | "Defined at drivers/pci/Kconfig:47\n" | 241 | " Defined at drivers/pci/Kconfig:47\n" |
| 241 | "Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n" | 242 | " Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n" |
| 242 | "Location:\n" | 243 | " Location:\n" |
| 243 | " -> Bus options (PCI, PCMCIA, EISA, ISA)\n" | 244 | " -> Bus options (PCI, PCMCIA, EISA, ISA)\n" |
| 244 | " -> PCI support (PCI [=y])\n" | 245 | " -> PCI support (PCI [=y])\n" |
| 245 | " -> PCI access mode (<choice> [=y])\n" | 246 | "(1) -> PCI access mode (<choice> [=y])\n" |
| 246 | "Selects: LIBCRC32\n" | 247 | " Selects: LIBCRC32\n" |
| 247 | "Selected by: BAR\n" | 248 | " Selected by: BAR\n" |
| 248 | "-----------------------------------------------------------------\n" | 249 | "-----------------------------------------------------------------\n" |
| 250 | "o The line 'Type:' shows the type of the configuration option for\n" | ||
| 251 | " this symbol (boolean, tristate, string, ...)\n" | ||
| 249 | "o The line 'Prompt:' shows the text used in the menu structure for\n" | 252 | "o The line 'Prompt:' shows the text used in the menu structure for\n" |
| 250 | " this symbol\n" | 253 | " this symbol\n" |
| 251 | "o The 'Defined at' line tell at what file / line number the symbol\n" | 254 | "o The 'Defined at' line tell at what file / line number the symbol\n" |
| @@ -254,8 +257,12 @@ search_help[] = N_( | |||
| 254 | " this symbol to be visible in the menu (selectable)\n" | 257 | " this symbol to be visible in the menu (selectable)\n" |
| 255 | "o The 'Location:' lines tell where in the menu structure this symbol\n" | 258 | "o The 'Location:' lines tell where in the menu structure this symbol\n" |
| 256 | " is located\n" | 259 | " is located\n" |
| 257 | " A location followed by a [=y] indicate that this is a selectable\n" | 260 | " A location followed by a [=y] indicates that this is a\n" |
| 258 | " menu item - and current value is displayed inside brackets.\n" | 261 | " selectable menu item - and the current value is displayed inside\n" |
| 262 | " brackets.\n" | ||
| 263 | " Press the key in the (#) prefix to jump directly to that\n" | ||
| 264 | " location. You will be returned to the current search results\n" | ||
| 265 | " after exiting this new menu.\n" | ||
| 259 | "o The 'Selects:' line tell what symbol will be automatically\n" | 266 | "o The 'Selects:' line tell what symbol will be automatically\n" |
| 260 | " selected if this symbol is selected (y or m)\n" | 267 | " selected if this symbol is selected (y or m)\n" |
| 261 | "o The 'Selected by' line tell what symbol has selected this symbol\n" | 268 | "o The 'Selected by' line tell what symbol has selected this symbol\n" |
| @@ -273,13 +280,15 @@ static struct menu *current_menu; | |||
| 273 | static int child_count; | 280 | static int child_count; |
| 274 | static int single_menu_mode; | 281 | static int single_menu_mode; |
| 275 | static int show_all_options; | 282 | static int show_all_options; |
| 276 | static int saved_x, saved_y; | ||
| 277 | 283 | ||
| 278 | static void conf(struct menu *menu); | 284 | static void conf(struct menu *menu, struct menu *active_menu); |
| 279 | static void conf_choice(struct menu *menu); | 285 | static void conf_choice(struct menu *menu); |
| 280 | static void conf_string(struct menu *menu); | 286 | static void conf_string(struct menu *menu); |
| 281 | static void conf_load(void); | 287 | static void conf_load(void); |
| 282 | static void conf_save(void); | 288 | static void conf_save(void); |
| 289 | static int show_textbox_ext(const char *title, char *text, int r, int c, | ||
| 290 | int *keys, int *vscroll, int *hscroll, | ||
| 291 | update_text_fn update_text, void *data); | ||
| 283 | static void show_textbox(const char *title, const char *text, int r, int c); | 292 | static void show_textbox(const char *title, const char *text, int r, int c); |
| 284 | static void show_helptext(const char *title, const char *text); | 293 | static void show_helptext(const char *title, const char *text); |
| 285 | static void show_help(struct menu *menu); | 294 | static void show_help(struct menu *menu); |
| @@ -302,12 +311,47 @@ static void set_config_filename(const char *config_filename) | |||
| 302 | } | 311 | } |
| 303 | 312 | ||
| 304 | 313 | ||
| 314 | struct search_data { | ||
| 315 | struct jk_head *head; | ||
| 316 | struct menu **targets; | ||
| 317 | int *keys; | ||
| 318 | }; | ||
| 319 | |||
| 320 | static void update_text(char *buf, size_t start, size_t end, void *_data) | ||
| 321 | { | ||
| 322 | struct search_data *data = _data; | ||
| 323 | struct jump_key *pos; | ||
| 324 | int k = 0; | ||
| 325 | |||
| 326 | CIRCLEQ_FOREACH(pos, data->head, entries) { | ||
| 327 | if (pos->offset >= start && pos->offset < end) { | ||
| 328 | char header[4]; | ||
| 329 | |||
| 330 | if (k < JUMP_NB) { | ||
| 331 | int key = '0' + (pos->index % JUMP_NB) + 1; | ||
| 332 | |||
| 333 | sprintf(header, "(%c)", key); | ||
| 334 | data->keys[k] = key; | ||
| 335 | data->targets[k] = pos->target; | ||
| 336 | k++; | ||
| 337 | } else { | ||
| 338 | sprintf(header, " "); | ||
| 339 | } | ||
| 340 | |||
| 341 | memcpy(buf + pos->offset, header, sizeof(header) - 1); | ||
| 342 | } | ||
| 343 | } | ||
| 344 | data->keys[k] = 0; | ||
| 345 | } | ||
| 346 | |||
| 305 | static void search_conf(void) | 347 | static void search_conf(void) |
| 306 | { | 348 | { |
| 307 | struct symbol **sym_arr; | 349 | struct symbol **sym_arr; |
| 308 | struct gstr res; | 350 | struct gstr res; |
| 309 | char *dialog_input; | 351 | char *dialog_input; |
| 310 | int dres; | 352 | int dres, vscroll = 0, hscroll = 0; |
| 353 | bool again; | ||
| 354 | |||
| 311 | again: | 355 | again: |
| 312 | dialog_clear(); | 356 | dialog_clear(); |
| 313 | dres = dialog_inputbox(_("Search Configuration Parameter"), | 357 | dres = dialog_inputbox(_("Search Configuration Parameter"), |
| @@ -330,10 +374,30 @@ again: | |||
| 330 | dialog_input += strlen(CONFIG_); | 374 | dialog_input += strlen(CONFIG_); |
| 331 | 375 | ||
| 332 | sym_arr = sym_re_search(dialog_input); | 376 | sym_arr = sym_re_search(dialog_input); |
| 333 | res = get_relations_str(sym_arr); | 377 | do { |
| 378 | struct jk_head head = CIRCLEQ_HEAD_INITIALIZER(head); | ||
| 379 | struct menu *targets[JUMP_NB]; | ||
| 380 | int keys[JUMP_NB + 1], i; | ||
| 381 | struct search_data data = { | ||
| 382 | .head = &head, | ||
| 383 | .targets = targets, | ||
| 384 | .keys = keys, | ||
| 385 | }; | ||
| 386 | |||
| 387 | res = get_relations_str(sym_arr, &head); | ||
| 388 | dres = show_textbox_ext(_("Search Results"), (char *) | ||
| 389 | str_get(&res), 0, 0, keys, &vscroll, | ||
| 390 | &hscroll, &update_text, (void *) | ||
| 391 | &data); | ||
| 392 | again = false; | ||
| 393 | for (i = 0; i < JUMP_NB && keys[i]; i++) | ||
| 394 | if (dres == keys[i]) { | ||
| 395 | conf(targets[i]->parent, targets[i]); | ||
| 396 | again = true; | ||
| 397 | } | ||
| 398 | str_free(&res); | ||
| 399 | } while (again); | ||
| 334 | free(sym_arr); | 400 | free(sym_arr); |
| 335 | show_textbox(_("Search Results"), str_get(&res), 0, 0); | ||
| 336 | str_free(&res); | ||
| 337 | } | 401 | } |
| 338 | 402 | ||
| 339 | static void build_conf(struct menu *menu) | 403 | static void build_conf(struct menu *menu) |
| @@ -514,12 +578,11 @@ conf_childs: | |||
| 514 | indent -= doint; | 578 | indent -= doint; |
| 515 | } | 579 | } |
| 516 | 580 | ||
| 517 | static void conf(struct menu *menu) | 581 | static void conf(struct menu *menu, struct menu *active_menu) |
| 518 | { | 582 | { |
| 519 | struct menu *submenu; | 583 | struct menu *submenu; |
| 520 | const char *prompt = menu_get_prompt(menu); | 584 | const char *prompt = menu_get_prompt(menu); |
| 521 | struct symbol *sym; | 585 | struct symbol *sym; |
| 522 | struct menu *active_menu = NULL; | ||
| 523 | int res; | 586 | int res; |
| 524 | int s_scroll = 0; | 587 | int s_scroll = 0; |
| 525 | 588 | ||
| @@ -562,13 +625,13 @@ static void conf(struct menu *menu) | |||
| 562 | if (single_menu_mode) | 625 | if (single_menu_mode) |
| 563 | submenu->data = (void *) (long) !submenu->data; | 626 | submenu->data = (void *) (long) !submenu->data; |
| 564 | else | 627 | else |
| 565 | conf(submenu); | 628 | conf(submenu, NULL); |
| 566 | break; | 629 | break; |
| 567 | case 't': | 630 | case 't': |
| 568 | if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes) | 631 | if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes) |
| 569 | conf_choice(submenu); | 632 | conf_choice(submenu); |
| 570 | else if (submenu->prompt->type == P_MENU) | 633 | else if (submenu->prompt->type == P_MENU) |
| 571 | conf(submenu); | 634 | conf(submenu, NULL); |
| 572 | break; | 635 | break; |
| 573 | case 's': | 636 | case 's': |
| 574 | conf_string(submenu); | 637 | conf_string(submenu); |
| @@ -607,7 +670,7 @@ static void conf(struct menu *menu) | |||
| 607 | if (item_is_tag('t')) | 670 | if (item_is_tag('t')) |
| 608 | sym_toggle_tristate_value(sym); | 671 | sym_toggle_tristate_value(sym); |
| 609 | else if (item_is_tag('m')) | 672 | else if (item_is_tag('m')) |
| 610 | conf(submenu); | 673 | conf(submenu, NULL); |
| 611 | break; | 674 | break; |
| 612 | case 7: | 675 | case 7: |
| 613 | search_conf(); | 676 | search_conf(); |
| @@ -619,10 +682,19 @@ static void conf(struct menu *menu) | |||
| 619 | } | 682 | } |
| 620 | } | 683 | } |
| 621 | 684 | ||
| 622 | static void show_textbox(const char *title, const char *text, int r, int c) | 685 | static int show_textbox_ext(const char *title, char *text, int r, int c, int |
| 686 | *keys, int *vscroll, int *hscroll, update_text_fn | ||
| 687 | update_text, void *data) | ||
| 623 | { | 688 | { |
| 624 | dialog_clear(); | 689 | dialog_clear(); |
| 625 | dialog_textbox(title, text, r, c); | 690 | return dialog_textbox(title, text, r, c, keys, vscroll, hscroll, |
| 691 | update_text, data); | ||
| 692 | } | ||
| 693 | |||
| 694 | static void show_textbox(const char *title, const char *text, int r, int c) | ||
| 695 | { | ||
| 696 | show_textbox_ext(title, (char *) text, r, c, (int []) {0}, NULL, NULL, | ||
| 697 | NULL, NULL); | ||
| 626 | } | 698 | } |
| 627 | 699 | ||
| 628 | static void show_helptext(const char *title, const char *text) | 700 | static void show_helptext(const char *title, const char *text) |
| @@ -862,9 +934,6 @@ int main(int ac, char **av) | |||
| 862 | single_menu_mode = 1; | 934 | single_menu_mode = 1; |
| 863 | } | 935 | } |
| 864 | 936 | ||
| 865 | initscr(); | ||
| 866 | |||
| 867 | getyx(stdscr, saved_y, saved_x); | ||
| 868 | if (init_dialog(NULL)) { | 937 | if (init_dialog(NULL)) { |
| 869 | fprintf(stderr, N_("Your display is too small to run Menuconfig!\n")); | 938 | fprintf(stderr, N_("Your display is too small to run Menuconfig!\n")); |
| 870 | fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n")); | 939 | fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n")); |
| @@ -873,7 +942,7 @@ int main(int ac, char **av) | |||
| 873 | 942 | ||
| 874 | set_config_filename(conf_get_configname()); | 943 | set_config_filename(conf_get_configname()); |
| 875 | do { | 944 | do { |
| 876 | conf(&rootmenu); | 945 | conf(&rootmenu, NULL); |
| 877 | res = handle_exit(); | 946 | res = handle_exit(); |
| 878 | } while (res == KEY_ESC); | 947 | } while (res == KEY_ESC); |
| 879 | 948 | ||
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c index 8c2a97e60faf..a3cade659f89 100644 --- a/scripts/kconfig/menu.c +++ b/scripts/kconfig/menu.c | |||
| @@ -507,10 +507,12 @@ const char *menu_get_help(struct menu *menu) | |||
| 507 | return ""; | 507 | return ""; |
| 508 | } | 508 | } |
| 509 | 509 | ||
| 510 | static void get_prompt_str(struct gstr *r, struct property *prop) | 510 | static void get_prompt_str(struct gstr *r, struct property *prop, |
| 511 | struct jk_head *head) | ||
| 511 | { | 512 | { |
| 512 | int i, j; | 513 | int i, j; |
| 513 | struct menu *submenu[8], *menu; | 514 | struct menu *submenu[8], *menu, *location = NULL; |
| 515 | struct jump_key *jump; | ||
| 514 | 516 | ||
| 515 | str_printf(r, _("Prompt: %s\n"), _(prop->text)); | 517 | str_printf(r, _("Prompt: %s\n"), _(prop->text)); |
| 516 | str_printf(r, _(" Defined at %s:%d\n"), prop->menu->file->name, | 518 | str_printf(r, _(" Defined at %s:%d\n"), prop->menu->file->name, |
| @@ -521,13 +523,43 @@ static void get_prompt_str(struct gstr *r, struct property *prop) | |||
| 521 | str_append(r, "\n"); | 523 | str_append(r, "\n"); |
| 522 | } | 524 | } |
| 523 | menu = prop->menu->parent; | 525 | menu = prop->menu->parent; |
| 524 | for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) | 526 | for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) { |
| 527 | bool accessible = menu_is_visible(menu); | ||
| 528 | |||
| 525 | submenu[i++] = menu; | 529 | submenu[i++] = menu; |
| 530 | if (location == NULL && accessible) | ||
| 531 | location = menu; | ||
| 532 | } | ||
| 533 | if (head && location) { | ||
| 534 | jump = malloc(sizeof(struct jump_key)); | ||
| 535 | |||
| 536 | if (menu_is_visible(prop->menu)) { | ||
| 537 | /* | ||
| 538 | * There is not enough room to put the hint at the | ||
| 539 | * beginning of the "Prompt" line. Put the hint on the | ||
| 540 | * last "Location" line even when it would belong on | ||
| 541 | * the former. | ||
| 542 | */ | ||
| 543 | jump->target = prop->menu; | ||
| 544 | } else | ||
| 545 | jump->target = location; | ||
| 546 | |||
| 547 | if (CIRCLEQ_EMPTY(head)) | ||
| 548 | jump->index = 0; | ||
| 549 | else | ||
| 550 | jump->index = CIRCLEQ_LAST(head)->index + 1; | ||
| 551 | |||
| 552 | CIRCLEQ_INSERT_TAIL(head, jump, entries); | ||
| 553 | } | ||
| 554 | |||
| 526 | if (i > 0) { | 555 | if (i > 0) { |
| 527 | str_printf(r, _(" Location:\n")); | 556 | str_printf(r, _(" Location:\n")); |
| 528 | for (j = 4; --i >= 0; j += 2) { | 557 | for (j = 4; --i >= 0; j += 2) { |
| 529 | menu = submenu[i]; | 558 | menu = submenu[i]; |
| 530 | str_printf(r, "%*c-> %s", j, ' ', _(menu_get_prompt(menu))); | 559 | if (head && location && menu == location) |
| 560 | jump->offset = r->len - 1; | ||
| 561 | str_printf(r, "%*c-> %s", j, ' ', | ||
| 562 | _(menu_get_prompt(menu))); | ||
| 531 | if (menu->sym) { | 563 | if (menu->sym) { |
| 532 | str_printf(r, " (%s [=%s])", menu->sym->name ? | 564 | str_printf(r, " (%s [=%s])", menu->sym->name ? |
| 533 | menu->sym->name : _("<choice>"), | 565 | menu->sym->name : _("<choice>"), |
| @@ -538,7 +570,10 @@ static void get_prompt_str(struct gstr *r, struct property *prop) | |||
| 538 | } | 570 | } |
| 539 | } | 571 | } |
| 540 | 572 | ||
| 541 | void get_symbol_str(struct gstr *r, struct symbol *sym) | 573 | /* |
| 574 | * head is optional and may be NULL | ||
| 575 | */ | ||
| 576 | void get_symbol_str(struct gstr *r, struct symbol *sym, struct jk_head *head) | ||
| 542 | { | 577 | { |
| 543 | bool hit; | 578 | bool hit; |
| 544 | struct property *prop; | 579 | struct property *prop; |
| @@ -557,7 +592,7 @@ void get_symbol_str(struct gstr *r, struct symbol *sym) | |||
| 557 | } | 592 | } |
| 558 | } | 593 | } |
| 559 | for_all_prompts(sym, prop) | 594 | for_all_prompts(sym, prop) |
| 560 | get_prompt_str(r, prop); | 595 | get_prompt_str(r, prop, head); |
| 561 | hit = false; | 596 | hit = false; |
| 562 | for_all_properties(sym, prop, P_SELECT) { | 597 | for_all_properties(sym, prop, P_SELECT) { |
| 563 | if (!hit) { | 598 | if (!hit) { |
| @@ -577,14 +612,14 @@ void get_symbol_str(struct gstr *r, struct symbol *sym) | |||
| 577 | str_append(r, "\n\n"); | 612 | str_append(r, "\n\n"); |
| 578 | } | 613 | } |
| 579 | 614 | ||
| 580 | struct gstr get_relations_str(struct symbol **sym_arr) | 615 | struct gstr get_relations_str(struct symbol **sym_arr, struct jk_head *head) |
| 581 | { | 616 | { |
| 582 | struct symbol *sym; | 617 | struct symbol *sym; |
| 583 | struct gstr res = str_new(); | 618 | struct gstr res = str_new(); |
| 584 | int i; | 619 | int i; |
| 585 | 620 | ||
| 586 | for (i = 0; sym_arr && (sym = sym_arr[i]); i++) | 621 | for (i = 0; sym_arr && (sym = sym_arr[i]); i++) |
| 587 | get_symbol_str(&res, sym); | 622 | get_symbol_str(&res, sym, head); |
| 588 | if (!i) | 623 | if (!i) |
| 589 | str_append(&res, _("No matches found.\n")); | 624 | str_append(&res, _("No matches found.\n")); |
| 590 | return res; | 625 | return res; |
| @@ -603,5 +638,5 @@ void menu_get_ext_help(struct menu *menu, struct gstr *help) | |||
| 603 | } | 638 | } |
| 604 | str_printf(help, "%s\n", _(help_text)); | 639 | str_printf(help, "%s\n", _(help_text)); |
| 605 | if (sym) | 640 | if (sym) |
| 606 | get_symbol_str(help, sym); | 641 | get_symbol_str(help, sym, NULL); |
| 607 | } | 642 | } |
diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c index 1704a8562a5d..87d4b15da951 100644 --- a/scripts/kconfig/nconf.c +++ b/scripts/kconfig/nconf.c | |||
| @@ -721,7 +721,7 @@ again: | |||
| 721 | dialog_input += strlen(CONFIG_); | 721 | dialog_input += strlen(CONFIG_); |
| 722 | 722 | ||
| 723 | sym_arr = sym_re_search(dialog_input); | 723 | sym_arr = sym_re_search(dialog_input); |
| 724 | res = get_relations_str(sym_arr); | 724 | res = get_relations_str(sym_arr, NULL); |
| 725 | free(sym_arr); | 725 | free(sym_arr); |
| 726 | show_scroll_win(main_window, | 726 | show_scroll_win(main_window, |
| 727 | _("Search Results"), str_get(&res)); | 727 | _("Search Results"), str_get(&res)); |
diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl index 2fbbbc1ddea0..33689396953a 100644 --- a/scripts/kconfig/streamline_config.pl +++ b/scripts/kconfig/streamline_config.pl | |||
| @@ -100,7 +100,7 @@ my @searchconfigs = ( | |||
| 100 | }, | 100 | }, |
| 101 | ); | 101 | ); |
| 102 | 102 | ||
| 103 | sub find_config { | 103 | sub read_config { |
| 104 | foreach my $conf (@searchconfigs) { | 104 | foreach my $conf (@searchconfigs) { |
| 105 | my $file = $conf->{"file"}; | 105 | my $file = $conf->{"file"}; |
| 106 | 106 | ||
| @@ -115,17 +115,15 @@ sub find_config { | |||
| 115 | 115 | ||
| 116 | print STDERR "using config: '$file'\n"; | 116 | print STDERR "using config: '$file'\n"; |
| 117 | 117 | ||
| 118 | open(CIN, "$exec $file |") || die "Failed to run $exec $file"; | 118 | open(my $infile, '-|', "$exec $file") || die "Failed to run $exec $file"; |
| 119 | return; | 119 | my @x = <$infile>; |
| 120 | close $infile; | ||
| 121 | return @x; | ||
| 120 | } | 122 | } |
| 121 | die "No config file found"; | 123 | die "No config file found"; |
| 122 | } | 124 | } |
| 123 | 125 | ||
| 124 | find_config; | 126 | my @config_file = read_config; |
| 125 | |||
| 126 | # Read in the entire config file into config_file | ||
| 127 | my @config_file = <CIN>; | ||
| 128 | close CIN; | ||
| 129 | 127 | ||
| 130 | # Parse options | 128 | # Parse options |
| 131 | my $localmodconfig = 0; | 129 | my $localmodconfig = 0; |
| @@ -135,7 +133,7 @@ GetOptions("localmodconfig" => \$localmodconfig, | |||
| 135 | "localyesconfig" => \$localyesconfig); | 133 | "localyesconfig" => \$localyesconfig); |
| 136 | 134 | ||
| 137 | # Get the build source and top level Kconfig file (passed in) | 135 | # Get the build source and top level Kconfig file (passed in) |
| 138 | my $ksource = $ARGV[0]; | 136 | my $ksource = ($ARGV[0] ? $ARGV[0] : '.'); |
| 139 | my $kconfig = $ARGV[1]; | 137 | my $kconfig = $ARGV[1]; |
| 140 | my $lsmod_file = $ENV{'LSMOD'}; | 138 | my $lsmod_file = $ENV{'LSMOD'}; |
| 141 | 139 | ||
| @@ -173,8 +171,8 @@ sub read_kconfig { | |||
| 173 | $source =~ s/\$$env/$ENV{$env}/; | 171 | $source =~ s/\$$env/$ENV{$env}/; |
| 174 | } | 172 | } |
| 175 | 173 | ||
| 176 | open(KIN, "$source") || die "Can't open $kconfig"; | 174 | open(my $kinfile, '<', $source) || die "Can't open $kconfig"; |
| 177 | while (<KIN>) { | 175 | while (<$kinfile>) { |
| 178 | chomp; | 176 | chomp; |
| 179 | 177 | ||
| 180 | # Make sure that lines ending with \ continue | 178 | # Make sure that lines ending with \ continue |
| @@ -251,10 +249,10 @@ sub read_kconfig { | |||
| 251 | $state = "NONE"; | 249 | $state = "NONE"; |
| 252 | } | 250 | } |
| 253 | } | 251 | } |
| 254 | close(KIN); | 252 | close($kinfile); |
| 255 | 253 | ||
| 256 | # read in any configs that were found. | 254 | # read in any configs that were found. |
| 257 | foreach $kconfig (@kconfigs) { | 255 | foreach my $kconfig (@kconfigs) { |
| 258 | if (!defined($read_kconfigs{$kconfig})) { | 256 | if (!defined($read_kconfigs{$kconfig})) { |
| 259 | $read_kconfigs{$kconfig} = 1; | 257 | $read_kconfigs{$kconfig} = 1; |
| 260 | read_kconfig($kconfig); | 258 | read_kconfig($kconfig); |
| @@ -295,8 +293,8 @@ foreach my $makefile (@makefiles) { | |||
| 295 | my $line = ""; | 293 | my $line = ""; |
| 296 | my %make_vars; | 294 | my %make_vars; |
| 297 | 295 | ||
| 298 | open(MIN,$makefile) || die "Can't open $makefile"; | 296 | open(my $infile, '<', $makefile) || die "Can't open $makefile"; |
| 299 | while (<MIN>) { | 297 | while (<$infile>) { |
| 300 | # if this line ends with a backslash, continue | 298 | # if this line ends with a backslash, continue |
| 301 | chomp; | 299 | chomp; |
| 302 | if (/^(.*)\\$/) { | 300 | if (/^(.*)\\$/) { |
| @@ -343,10 +341,11 @@ foreach my $makefile (@makefiles) { | |||
| 343 | } | 341 | } |
| 344 | } | 342 | } |
| 345 | } | 343 | } |
| 346 | close(MIN); | 344 | close($infile); |
| 347 | } | 345 | } |
| 348 | 346 | ||
| 349 | my %modules; | 347 | my %modules; |
| 348 | my $linfile; | ||
| 350 | 349 | ||
| 351 | if (defined($lsmod_file)) { | 350 | if (defined($lsmod_file)) { |
| 352 | if ( ! -f $lsmod_file) { | 351 | if ( ! -f $lsmod_file) { |
| @@ -356,13 +355,10 @@ if (defined($lsmod_file)) { | |||
| 356 | die "$lsmod_file not found"; | 355 | die "$lsmod_file not found"; |
| 357 | } | 356 | } |
| 358 | } | 357 | } |
| 359 | if ( -x $lsmod_file) { | 358 | |
| 360 | # the file is executable, run it | 359 | my $otype = ( -x $lsmod_file) ? '-|' : '<'; |
| 361 | open(LIN, "$lsmod_file|"); | 360 | open($linfile, $otype, $lsmod_file); |
| 362 | } else { | 361 | |
| 363 | # Just read the contents | ||
| 364 | open(LIN, "$lsmod_file"); | ||
| 365 | } | ||
| 366 | } else { | 362 | } else { |
| 367 | 363 | ||
| 368 | # see what modules are loaded on this system | 364 | # see what modules are loaded on this system |
| @@ -379,16 +375,16 @@ if (defined($lsmod_file)) { | |||
| 379 | $lsmod = "lsmod"; | 375 | $lsmod = "lsmod"; |
| 380 | } | 376 | } |
| 381 | 377 | ||
| 382 | open(LIN,"$lsmod|") || die "Can not call lsmod with $lsmod"; | 378 | open($linfile, '-|', $lsmod) || die "Can not call lsmod with $lsmod"; |
| 383 | } | 379 | } |
| 384 | 380 | ||
| 385 | while (<LIN>) { | 381 | while (<$linfile>) { |
| 386 | next if (/^Module/); # Skip the first line. | 382 | next if (/^Module/); # Skip the first line. |
| 387 | if (/^(\S+)/) { | 383 | if (/^(\S+)/) { |
| 388 | $modules{$1} = 1; | 384 | $modules{$1} = 1; |
| 389 | } | 385 | } |
| 390 | } | 386 | } |
| 391 | close (LIN); | 387 | close ($linfile); |
| 392 | 388 | ||
| 393 | # add to the configs hash all configs that are needed to enable | 389 | # add to the configs hash all configs that are needed to enable |
| 394 | # a loaded module. This is a direct obj-${CONFIG_FOO} += bar.o | 390 | # a loaded module. This is a direct obj-${CONFIG_FOO} += bar.o |
| @@ -605,6 +601,8 @@ foreach my $line (@config_file) { | |||
| 605 | if (defined($configs{$1})) { | 601 | if (defined($configs{$1})) { |
| 606 | if ($localyesconfig) { | 602 | if ($localyesconfig) { |
| 607 | $setconfigs{$1} = 'y'; | 603 | $setconfigs{$1} = 'y'; |
| 604 | print "$1=y\n"; | ||
| 605 | next; | ||
| 608 | } else { | 606 | } else { |
| 609 | $setconfigs{$1} = $2; | 607 | $setconfigs{$1} = $2; |
| 610 | } | 608 | } |
diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 8fd107a3fac4..46e7aff80d1a 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc | |||
| @@ -6,6 +6,7 @@ use strict; | |||
| 6 | ## Copyright (C) 2000, 1 Tim Waugh <twaugh@redhat.com> ## | 6 | ## Copyright (C) 2000, 1 Tim Waugh <twaugh@redhat.com> ## |
| 7 | ## Copyright (C) 2001 Simon Huggins ## | 7 | ## Copyright (C) 2001 Simon Huggins ## |
| 8 | ## Copyright (C) 2005-2012 Randy Dunlap ## | 8 | ## Copyright (C) 2005-2012 Randy Dunlap ## |
| 9 | ## Copyright (C) 2012 Dan Luedtke ## | ||
| 9 | ## ## | 10 | ## ## |
| 10 | ## #define enhancements by Armin Kuster <akuster@mvista.com> ## | 11 | ## #define enhancements by Armin Kuster <akuster@mvista.com> ## |
| 11 | ## Copyright (c) 2000 MontaVista Software, Inc. ## | 12 | ## Copyright (c) 2000 MontaVista Software, Inc. ## |
| @@ -35,6 +36,8 @@ use strict; | |||
| 35 | # Small fixes (like spaces vs. \s in regex) | 36 | # Small fixes (like spaces vs. \s in regex) |
| 36 | # -- Tim Jansen <tim@tjansen.de> | 37 | # -- Tim Jansen <tim@tjansen.de> |
| 37 | 38 | ||
| 39 | # 25/07/2012 - Added support for HTML5 | ||
| 40 | # -- Dan Luedtke <mail@danrl.de> | ||
| 38 | 41 | ||
| 39 | # | 42 | # |
| 40 | # This will read a 'c' file and scan for embedded comments in the | 43 | # This will read a 'c' file and scan for embedded comments in the |
| @@ -44,12 +47,16 @@ use strict; | |||
| 44 | # Note: This only supports 'c'. | 47 | # Note: This only supports 'c'. |
| 45 | 48 | ||
| 46 | # usage: | 49 | # usage: |
| 47 | # kernel-doc [ -docbook | -html | -text | -man | -list ] [ -no-doc-sections ] | 50 | # kernel-doc [ -docbook | -html | -html5 | -text | -man | -list ] |
| 48 | # [ -function funcname [ -function funcname ...] ] c file(s)s > outputfile | 51 | # [ -no-doc-sections ] |
| 52 | # [ -function funcname [ -function funcname ...] ] | ||
| 53 | # c file(s)s > outputfile | ||
| 49 | # or | 54 | # or |
| 50 | # [ -nofunction funcname [ -function funcname ...] ] c file(s)s > outputfile | 55 | # [ -nofunction funcname [ -function funcname ...] ] |
| 56 | # c file(s)s > outputfile | ||
| 51 | # | 57 | # |
| 52 | # Set output format using one of -docbook -html -text or -man. Default is man. | 58 | # Set output format using one of -docbook -html -html5 -text or -man. |
| 59 | # Default is man. | ||
| 53 | # The -list format is for internal use by docproc. | 60 | # The -list format is for internal use by docproc. |
| 54 | # | 61 | # |
| 55 | # -no-doc-sections | 62 | # -no-doc-sections |
| @@ -182,6 +189,14 @@ my $local_lt = "\\\\\\\\lt:"; | |||
| 182 | my $local_gt = "\\\\\\\\gt:"; | 189 | my $local_gt = "\\\\\\\\gt:"; |
| 183 | my $blankline_html = $local_lt . "p" . $local_gt; # was "<p>" | 190 | my $blankline_html = $local_lt . "p" . $local_gt; # was "<p>" |
| 184 | 191 | ||
| 192 | # html version 5 | ||
| 193 | my %highlights_html5 = ( $type_constant, "<span class=\"const\">\$1</span>", | ||
| 194 | $type_func, "<span class=\"func\">\$1</span>", | ||
| 195 | $type_struct_xml, "<span class=\"struct\">\$1</span>", | ||
| 196 | $type_env, "<span class=\"env\">\$1</span>", | ||
| 197 | $type_param, "<span class=\"param\">\$1</span>" ); | ||
| 198 | my $blankline_html5 = $local_lt . "br /" . $local_gt; | ||
| 199 | |||
| 185 | # XML, docbook format | 200 | # XML, docbook format |
| 186 | my %highlights_xml = ( "([^=])\\\"([^\\\"<]+)\\\"", "\$1<quote>\$2</quote>", | 201 | my %highlights_xml = ( "([^=])\\\"([^\\\"<]+)\\\"", "\$1<quote>\$2</quote>", |
| 187 | $type_constant, "<constant>\$1</constant>", | 202 | $type_constant, "<constant>\$1</constant>", |
| @@ -230,6 +245,7 @@ my $dohighlight = ""; | |||
| 230 | 245 | ||
| 231 | my $verbose = 0; | 246 | my $verbose = 0; |
| 232 | my $output_mode = "man"; | 247 | my $output_mode = "man"; |
| 248 | my $output_preformatted = 0; | ||
| 233 | my $no_doc_sections = 0; | 249 | my $no_doc_sections = 0; |
| 234 | my %highlights = %highlights_man; | 250 | my %highlights = %highlights_man; |
| 235 | my $blankline = $blankline_man; | 251 | my $blankline = $blankline_man; |
| @@ -280,9 +296,10 @@ my $doc_special = "\@\%\$\&"; | |||
| 280 | my $doc_start = '^/\*\*\s*$'; # Allow whitespace at end of comment start. | 296 | my $doc_start = '^/\*\*\s*$'; # Allow whitespace at end of comment start. |
| 281 | my $doc_end = '\*/'; | 297 | my $doc_end = '\*/'; |
| 282 | my $doc_com = '\s*\*\s*'; | 298 | my $doc_com = '\s*\*\s*'; |
| 299 | my $doc_com_body = '\s*\* ?'; | ||
| 283 | my $doc_decl = $doc_com . '(\w+)'; | 300 | my $doc_decl = $doc_com . '(\w+)'; |
| 284 | my $doc_sect = $doc_com . '([' . $doc_special . ']?[\w\s]+):(.*)'; | 301 | my $doc_sect = $doc_com . '([' . $doc_special . ']?[\w\s]+):(.*)'; |
| 285 | my $doc_content = $doc_com . '(.*)'; | 302 | my $doc_content = $doc_com_body . '(.*)'; |
| 286 | my $doc_block = $doc_com . 'DOC:\s*(.*)?'; | 303 | my $doc_block = $doc_com . 'DOC:\s*(.*)?'; |
| 287 | 304 | ||
| 288 | my %constants; | 305 | my %constants; |
| @@ -309,6 +326,10 @@ while ($ARGV[0] =~ m/^-(.*)/) { | |||
| 309 | $output_mode = "html"; | 326 | $output_mode = "html"; |
| 310 | %highlights = %highlights_html; | 327 | %highlights = %highlights_html; |
| 311 | $blankline = $blankline_html; | 328 | $blankline = $blankline_html; |
| 329 | } elsif ($cmd eq "-html5") { | ||
| 330 | $output_mode = "html5"; | ||
| 331 | %highlights = %highlights_html5; | ||
| 332 | $blankline = $blankline_html5; | ||
| 312 | } elsif ($cmd eq "-man") { | 333 | } elsif ($cmd eq "-man") { |
| 313 | $output_mode = "man"; | 334 | $output_mode = "man"; |
| 314 | %highlights = %highlights_man; | 335 | %highlights = %highlights_man; |
| @@ -351,10 +372,11 @@ while ($ARGV[0] =~ m/^-(.*)/) { | |||
| 351 | # continue execution near EOF; | 372 | # continue execution near EOF; |
| 352 | 373 | ||
| 353 | sub usage { | 374 | sub usage { |
| 354 | print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man | -list ]\n"; | 375 | print "Usage: $0 [ -docbook | -html | -html5 | -text | -man | -list ]\n"; |
| 355 | print " [ -no-doc-sections ]\n"; | 376 | print " [ -no-doc-sections ]\n"; |
| 356 | print " [ -function funcname [ -function funcname ...] ]\n"; | 377 | print " [ -function funcname [ -function funcname ...] ]\n"; |
| 357 | print " [ -nofunction funcname [ -nofunction funcname ...] ]\n"; | 378 | print " [ -nofunction funcname [ -nofunction funcname ...] ]\n"; |
| 379 | print " [ -v ]\n"; | ||
| 358 | print " c source file(s) > outputfile\n"; | 380 | print " c source file(s) > outputfile\n"; |
| 359 | print " -v : verbose output, more warnings & other info listed\n"; | 381 | print " -v : verbose output, more warnings & other info listed\n"; |
| 360 | exit 1; | 382 | exit 1; |
| @@ -448,7 +470,8 @@ sub output_highlight { | |||
| 448 | # confess "output_highlight got called with no args?\n"; | 470 | # confess "output_highlight got called with no args?\n"; |
| 449 | # } | 471 | # } |
| 450 | 472 | ||
| 451 | if ($output_mode eq "html" || $output_mode eq "xml") { | 473 | if ($output_mode eq "html" || $output_mode eq "html5" || |
| 474 | $output_mode eq "xml") { | ||
| 452 | $contents = local_unescape($contents); | 475 | $contents = local_unescape($contents); |
| 453 | # convert data read & converted thru xml_escape() into &xyz; format: | 476 | # convert data read & converted thru xml_escape() into &xyz; format: |
| 454 | $contents =~ s/\\\\\\/\&/g; | 477 | $contents =~ s/\\\\\\/\&/g; |
| @@ -458,9 +481,19 @@ sub output_highlight { | |||
| 458 | die $@ if $@; | 481 | die $@ if $@; |
| 459 | # print STDERR "contents af:$contents\n"; | 482 | # print STDERR "contents af:$contents\n"; |
| 460 | 483 | ||
| 484 | # strip whitespaces when generating html5 | ||
| 485 | if ($output_mode eq "html5") { | ||
| 486 | $contents =~ s/^\s+//; | ||
| 487 | $contents =~ s/\s+$//; | ||
| 488 | } | ||
| 461 | foreach $line (split "\n", $contents) { | 489 | foreach $line (split "\n", $contents) { |
| 490 | if (! $output_preformatted) { | ||
| 491 | $line =~ s/^\s*//; | ||
| 492 | } | ||
| 462 | if ($line eq ""){ | 493 | if ($line eq ""){ |
| 463 | print $lineprefix, local_unescape($blankline); | 494 | if (! $output_preformatted) { |
| 495 | print $lineprefix, local_unescape($blankline); | ||
| 496 | } | ||
| 464 | } else { | 497 | } else { |
| 465 | $line =~ s/\\\\\\/\&/g; | 498 | $line =~ s/\\\\\\/\&/g; |
| 466 | if ($output_mode eq "man" && substr($line, 0, 1) eq ".") { | 499 | if ($output_mode eq "man" && substr($line, 0, 1) eq ".") { |
| @@ -473,7 +506,7 @@ sub output_highlight { | |||
| 473 | } | 506 | } |
| 474 | } | 507 | } |
| 475 | 508 | ||
| 476 | #output sections in html | 509 | # output sections in html |
| 477 | sub output_section_html(%) { | 510 | sub output_section_html(%) { |
| 478 | my %args = %{$_[0]}; | 511 | my %args = %{$_[0]}; |
| 479 | my $section; | 512 | my $section; |
| @@ -633,6 +666,239 @@ sub output_blockhead_html(%) { | |||
| 633 | print "<hr>\n"; | 666 | print "<hr>\n"; |
| 634 | } | 667 | } |
| 635 | 668 | ||
| 669 | # output sections in html5 | ||
| 670 | sub output_section_html5(%) { | ||
| 671 | my %args = %{$_[0]}; | ||
| 672 | my $section; | ||
| 673 | |||
| 674 | foreach $section (@{$args{'sectionlist'}}) { | ||
| 675 | print "<section>\n"; | ||
| 676 | print "<h1>$section</h1>\n"; | ||
| 677 | print "<p>\n"; | ||
| 678 | output_highlight($args{'sections'}{$section}); | ||
| 679 | print "</p>\n"; | ||
| 680 | print "</section>\n"; | ||
| 681 | } | ||
| 682 | } | ||
| 683 | |||
| 684 | # output enum in html5 | ||
| 685 | sub output_enum_html5(%) { | ||
| 686 | my %args = %{$_[0]}; | ||
| 687 | my ($parameter); | ||
| 688 | my $count; | ||
| 689 | my $html5id; | ||
| 690 | |||
| 691 | $html5id = $args{'enum'}; | ||
| 692 | $html5id =~ s/[^a-zA-Z0-9\-]+/_/g; | ||
| 693 | print "<article class=\"enum\" id=\"enum:". $html5id . "\">"; | ||
| 694 | print "<h1>enum " . $args{'enum'} . "</h1>\n"; | ||
| 695 | print "<ol class=\"code\">\n"; | ||
| 696 | print "<li>"; | ||
| 697 | print "<span class=\"keyword\">enum</span> "; | ||
| 698 | print "<span class=\"identifier\">" . $args{'enum'} . "</span> {"; | ||
| 699 | print "</li>\n"; | ||
| 700 | $count = 0; | ||
| 701 | foreach $parameter (@{$args{'parameterlist'}}) { | ||
| 702 | print "<li class=\"indent\">"; | ||
| 703 | print "<span class=\"param\">" . $parameter . "</span>"; | ||
| 704 | if ($count != $#{$args{'parameterlist'}}) { | ||
| 705 | $count++; | ||
| 706 | print ","; | ||
| 707 | } | ||
| 708 | print "</li>\n"; | ||
| 709 | } | ||
| 710 | print "<li>};</li>\n"; | ||
| 711 | print "</ol>\n"; | ||
| 712 | |||
| 713 | print "<section>\n"; | ||
| 714 | print "<h1>Constants</h1>\n"; | ||
| 715 | print "<dl>\n"; | ||
| 716 | foreach $parameter (@{$args{'parameterlist'}}) { | ||
| 717 | print "<dt>" . $parameter . "</dt>\n"; | ||
| 718 | print "<dd>"; | ||
| 719 | output_highlight($args{'parameterdescs'}{$parameter}); | ||
| 720 | print "</dd>\n"; | ||
| 721 | } | ||
| 722 | print "</dl>\n"; | ||
| 723 | print "</section>\n"; | ||
| 724 | output_section_html5(@_); | ||
| 725 | print "</article>\n"; | ||
| 726 | } | ||
| 727 | |||
| 728 | # output typedef in html5 | ||
| 729 | sub output_typedef_html5(%) { | ||
| 730 | my %args = %{$_[0]}; | ||
| 731 | my ($parameter); | ||
| 732 | my $count; | ||
| 733 | my $html5id; | ||
| 734 | |||
| 735 | $html5id = $args{'typedef'}; | ||
| 736 | $html5id =~ s/[^a-zA-Z0-9\-]+/_/g; | ||
| 737 | print "<article class=\"typedef\" id=\"typedef:" . $html5id . "\">\n"; | ||
| 738 | print "<h1>typedef " . $args{'typedef'} . "</h1>\n"; | ||
| 739 | |||
| 740 | print "<ol class=\"code\">\n"; | ||
| 741 | print "<li>"; | ||
| 742 | print "<span class=\"keyword\">typedef</span> "; | ||
| 743 | print "<span class=\"identifier\">" . $args{'typedef'} . "</span>"; | ||
| 744 | print "</li>\n"; | ||
| 745 | print "</ol>\n"; | ||
| 746 | output_section_html5(@_); | ||
| 747 | print "</article>\n"; | ||
| 748 | } | ||
| 749 | |||
| 750 | # output struct in html5 | ||
| 751 | sub output_struct_html5(%) { | ||
| 752 | my %args = %{$_[0]}; | ||
| 753 | my ($parameter); | ||
| 754 | my $html5id; | ||
| 755 | |||
| 756 | $html5id = $args{'struct'}; | ||
| 757 | $html5id =~ s/[^a-zA-Z0-9\-]+/_/g; | ||
| 758 | print "<article class=\"struct\" id=\"struct:" . $html5id . "\">\n"; | ||
| 759 | print "<hgroup>\n"; | ||
| 760 | print "<h1>" . $args{'type'} . " " . $args{'struct'} . "</h1>"; | ||
| 761 | print "<h2>". $args{'purpose'} . "</h2>\n"; | ||
| 762 | print "</hgroup>\n"; | ||
| 763 | print "<ol class=\"code\">\n"; | ||
| 764 | print "<li>"; | ||
| 765 | print "<span class=\"type\">" . $args{'type'} . "</span> "; | ||
| 766 | print "<span class=\"identifier\">" . $args{'struct'} . "</span> {"; | ||
| 767 | print "</li>\n"; | ||
| 768 | foreach $parameter (@{$args{'parameterlist'}}) { | ||
| 769 | print "<li class=\"indent\">"; | ||
| 770 | if ($parameter =~ /^#/) { | ||
| 771 | print "<span class=\"param\">" . $parameter ."</span>\n"; | ||
| 772 | print "</li>\n"; | ||
| 773 | next; | ||
| 774 | } | ||
| 775 | my $parameter_name = $parameter; | ||
| 776 | $parameter_name =~ s/\[.*//; | ||
| 777 | |||
| 778 | ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; | ||
| 779 | $type = $args{'parametertypes'}{$parameter}; | ||
| 780 | if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { | ||
| 781 | # pointer-to-function | ||
| 782 | print "<span class=\"type\">$1</span> "; | ||
| 783 | print "<span class=\"param\">$parameter</span>"; | ||
| 784 | print "<span class=\"type\">)</span> "; | ||
| 785 | print "(<span class=\"args\">$2</span>);"; | ||
| 786 | } elsif ($type =~ m/^(.*?)\s*(:.*)/) { | ||
| 787 | # bitfield | ||
| 788 | print "<span class=\"type\">$1</span> "; | ||
| 789 | print "<span class=\"param\">$parameter</span>"; | ||
| 790 | print "<span class=\"bits\">$2</span>;"; | ||
| 791 | } else { | ||
| 792 | print "<span class=\"type\">$type</span> "; | ||
| 793 | print "<span class=\"param\">$parameter</span>;"; | ||
| 794 | } | ||
| 795 | print "</li>\n"; | ||
| 796 | } | ||
| 797 | print "<li>};</li>\n"; | ||
| 798 | print "</ol>\n"; | ||
| 799 | |||
| 800 | print "<section>\n"; | ||
| 801 | print "<h1>Members</h1>\n"; | ||
| 802 | print "<dl>\n"; | ||
| 803 | foreach $parameter (@{$args{'parameterlist'}}) { | ||
| 804 | ($parameter =~ /^#/) && next; | ||
| 805 | |||
| 806 | my $parameter_name = $parameter; | ||
| 807 | $parameter_name =~ s/\[.*//; | ||
| 808 | |||
| 809 | ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; | ||
| 810 | print "<dt>" . $parameter . "</dt>\n"; | ||
| 811 | print "<dd>"; | ||
| 812 | output_highlight($args{'parameterdescs'}{$parameter_name}); | ||
| 813 | print "</dd>\n"; | ||
| 814 | } | ||
| 815 | print "</dl>\n"; | ||
| 816 | print "</section>\n"; | ||
| 817 | output_section_html5(@_); | ||
| 818 | print "</article>\n"; | ||
| 819 | } | ||
| 820 | |||
| 821 | # output function in html5 | ||
| 822 | sub output_function_html5(%) { | ||
| 823 | my %args = %{$_[0]}; | ||
| 824 | my ($parameter, $section); | ||
| 825 | my $count; | ||
| 826 | my $html5id; | ||
| 827 | |||
| 828 | $html5id = $args{'function'}; | ||
| 829 | $html5id =~ s/[^a-zA-Z0-9\-]+/_/g; | ||
| 830 | print "<article class=\"function\" id=\"func:". $html5id . "\">\n"; | ||
| 831 | print "<hgroup>\n"; | ||
| 832 | print "<h1>" . $args{'function'} . "</h1>"; | ||
| 833 | print "<h2>" . $args{'purpose'} . "</h2>\n"; | ||
| 834 | print "</hgroup>\n"; | ||
| 835 | print "<ol class=\"code\">\n"; | ||
| 836 | print "<li>"; | ||
| 837 | print "<span class=\"type\">" . $args{'functiontype'} . "</span> "; | ||
| 838 | print "<span class=\"identifier\">" . $args{'function'} . "</span> ("; | ||
| 839 | print "</li>"; | ||
| 840 | $count = 0; | ||
| 841 | foreach $parameter (@{$args{'parameterlist'}}) { | ||
| 842 | print "<li class=\"indent\">"; | ||
| 843 | $type = $args{'parametertypes'}{$parameter}; | ||
| 844 | if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { | ||
| 845 | # pointer-to-function | ||
| 846 | print "<span class=\"type\">$1</span> "; | ||
| 847 | print "<span class=\"param\">$parameter</span>"; | ||
| 848 | print "<span class=\"type\">)</span> "; | ||
| 849 | print "(<span class=\"args\">$2</span>)"; | ||
| 850 | } else { | ||
| 851 | print "<span class=\"type\">$type</span> "; | ||
| 852 | print "<span class=\"param\">$parameter</span>"; | ||
| 853 | } | ||
| 854 | if ($count != $#{$args{'parameterlist'}}) { | ||
| 855 | $count++; | ||
| 856 | print ","; | ||
| 857 | } | ||
| 858 | print "</li>\n"; | ||
| 859 | } | ||
| 860 | print "<li>)</li>\n"; | ||
| 861 | print "</ol>\n"; | ||
| 862 | |||
| 863 | print "<section>\n"; | ||
| 864 | print "<h1>Arguments</h1>\n"; | ||
| 865 | print "<p>\n"; | ||
| 866 | print "<dl>\n"; | ||
| 867 | foreach $parameter (@{$args{'parameterlist'}}) { | ||
| 868 | my $parameter_name = $parameter; | ||
| 869 | $parameter_name =~ s/\[.*//; | ||
| 870 | |||
| 871 | ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; | ||
| 872 | print "<dt>" . $parameter . "</dt>\n"; | ||
| 873 | print "<dd>"; | ||
| 874 | output_highlight($args{'parameterdescs'}{$parameter_name}); | ||
| 875 | print "</dd>\n"; | ||
| 876 | } | ||
| 877 | print "</dl>\n"; | ||
| 878 | print "</section>\n"; | ||
| 879 | output_section_html5(@_); | ||
| 880 | print "</article>\n"; | ||
| 881 | } | ||
| 882 | |||
| 883 | # output DOC: block header in html5 | ||
| 884 | sub output_blockhead_html5(%) { | ||
| 885 | my %args = %{$_[0]}; | ||
| 886 | my ($parameter, $section); | ||
| 887 | my $count; | ||
| 888 | my $html5id; | ||
| 889 | |||
| 890 | foreach $section (@{$args{'sectionlist'}}) { | ||
| 891 | $html5id = $section; | ||
| 892 | $html5id =~ s/[^a-zA-Z0-9\-]+/_/g; | ||
| 893 | print "<article class=\"doc\" id=\"doc:". $html5id . "\">\n"; | ||
| 894 | print "<h1>$section</h1>\n"; | ||
| 895 | print "<p>\n"; | ||
| 896 | output_highlight($args{'sections'}{$section}); | ||
| 897 | print "</p>\n"; | ||
| 898 | } | ||
| 899 | print "</article>\n"; | ||
| 900 | } | ||
| 901 | |||
| 636 | sub output_section_xml(%) { | 902 | sub output_section_xml(%) { |
| 637 | my %args = %{$_[0]}; | 903 | my %args = %{$_[0]}; |
| 638 | my $section; | 904 | my $section; |
| @@ -643,10 +909,12 @@ sub output_section_xml(%) { | |||
| 643 | print "<title>$section</title>\n"; | 909 | print "<title>$section</title>\n"; |
| 644 | if ($section =~ m/EXAMPLE/i) { | 910 | if ($section =~ m/EXAMPLE/i) { |
| 645 | print "<informalexample><programlisting>\n"; | 911 | print "<informalexample><programlisting>\n"; |
| 912 | $output_preformatted = 1; | ||
| 646 | } else { | 913 | } else { |
| 647 | print "<para>\n"; | 914 | print "<para>\n"; |
| 648 | } | 915 | } |
| 649 | output_highlight($args{'sections'}{$section}); | 916 | output_highlight($args{'sections'}{$section}); |
| 917 | $output_preformatted = 0; | ||
| 650 | if ($section =~ m/EXAMPLE/i) { | 918 | if ($section =~ m/EXAMPLE/i) { |
| 651 | print "</programlisting></informalexample>\n"; | 919 | print "</programlisting></informalexample>\n"; |
| 652 | } else { | 920 | } else { |
| @@ -949,10 +1217,12 @@ sub output_blockhead_xml(%) { | |||
| 949 | } | 1217 | } |
| 950 | if ($section =~ m/EXAMPLE/i) { | 1218 | if ($section =~ m/EXAMPLE/i) { |
| 951 | print "<example><para>\n"; | 1219 | print "<example><para>\n"; |
| 1220 | $output_preformatted = 1; | ||
| 952 | } else { | 1221 | } else { |
| 953 | print "<para>\n"; | 1222 | print "<para>\n"; |
| 954 | } | 1223 | } |
| 955 | output_highlight($args{'sections'}{$section}); | 1224 | output_highlight($args{'sections'}{$section}); |
| 1225 | $output_preformatted = 0; | ||
| 956 | if ($section =~ m/EXAMPLE/i) { | 1226 | if ($section =~ m/EXAMPLE/i) { |
| 957 | print "</para></example>\n"; | 1227 | print "</para></example>\n"; |
| 958 | } else { | 1228 | } else { |
| @@ -1028,10 +1298,12 @@ sub output_function_gnome { | |||
| 1028 | print "<simplesect>\n <title>$section</title>\n"; | 1298 | print "<simplesect>\n <title>$section</title>\n"; |
| 1029 | if ($section =~ m/EXAMPLE/i) { | 1299 | if ($section =~ m/EXAMPLE/i) { |
| 1030 | print "<example><programlisting>\n"; | 1300 | print "<example><programlisting>\n"; |
| 1301 | $output_preformatted = 1; | ||
| 1031 | } else { | 1302 | } else { |
| 1032 | } | 1303 | } |
| 1033 | print "<para>\n"; | 1304 | print "<para>\n"; |
| 1034 | output_highlight($args{'sections'}{$section}); | 1305 | output_highlight($args{'sections'}{$section}); |
| 1306 | $output_preformatted = 0; | ||
| 1035 | print "</para>\n"; | 1307 | print "</para>\n"; |
| 1036 | if ($section =~ m/EXAMPLE/i) { | 1308 | if ($section =~ m/EXAMPLE/i) { |
| 1037 | print "</programlisting></example>\n"; | 1309 | print "</programlisting></example>\n"; |
| @@ -2046,6 +2318,9 @@ sub process_file($) { | |||
| 2046 | 2318 | ||
| 2047 | $section_counter = 0; | 2319 | $section_counter = 0; |
| 2048 | while (<IN>) { | 2320 | while (<IN>) { |
| 2321 | while (s/\\\s*$//) { | ||
| 2322 | $_ .= <IN>; | ||
| 2323 | } | ||
| 2049 | if ($state == 0) { | 2324 | if ($state == 0) { |
| 2050 | if (/$doc_start/o) { | 2325 | if (/$doc_start/o) { |
| 2051 | $state = 1; # next line is always the function name | 2326 | $state = 1; # next line is always the function name |
| @@ -2073,7 +2348,7 @@ sub process_file($) { | |||
| 2073 | $descr= $1; | 2348 | $descr= $1; |
| 2074 | $descr =~ s/^\s*//; | 2349 | $descr =~ s/^\s*//; |
| 2075 | $descr =~ s/\s*$//; | 2350 | $descr =~ s/\s*$//; |
| 2076 | $descr =~ s/\s+/ /; | 2351 | $descr =~ s/\s+/ /g; |
| 2077 | $declaration_purpose = xml_escape($descr); | 2352 | $declaration_purpose = xml_escape($descr); |
| 2078 | $in_purpose = 1; | 2353 | $in_purpose = 1; |
| 2079 | } else { | 2354 | } else { |
| @@ -2165,6 +2440,7 @@ sub process_file($) { | |||
| 2165 | # Continued declaration purpose | 2440 | # Continued declaration purpose |
| 2166 | chomp($declaration_purpose); | 2441 | chomp($declaration_purpose); |
| 2167 | $declaration_purpose .= " " . xml_escape($1); | 2442 | $declaration_purpose .= " " . xml_escape($1); |
| 2443 | $declaration_purpose =~ s/\s+/ /g; | ||
| 2168 | } else { | 2444 | } else { |
| 2169 | $contents .= $1 . "\n"; | 2445 | $contents .= $1 . "\n"; |
| 2170 | } | 2446 | } |
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index 4235a6361fec..b3d907eb93a9 100644 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh | |||
| @@ -74,8 +74,13 @@ kallsyms() | |||
| 74 | info KSYM ${2} | 74 | info KSYM ${2} |
| 75 | local kallsymopt; | 75 | local kallsymopt; |
| 76 | 76 | ||
| 77 | if [ -n "${CONFIG_SYMBOL_PREFIX}" ]; then | ||
| 78 | kallsymopt="${kallsymopt} \ | ||
| 79 | --symbol-prefix=${CONFIG_SYMBOL_PREFIX}" | ||
| 80 | fi | ||
| 81 | |||
| 77 | if [ -n "${CONFIG_KALLSYMS_ALL}" ]; then | 82 | if [ -n "${CONFIG_KALLSYMS_ALL}" ]; then |
| 78 | kallsymopt=--all-symbols | 83 | kallsymopt="${kallsymopt} --all-symbols" |
| 79 | fi | 84 | fi |
| 80 | 85 | ||
| 81 | local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} \ | 86 | local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} \ |
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 7ed6864ef65b..df4fc23dd836 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c | |||
| @@ -966,6 +966,21 @@ static int do_isapnp_entry(const char *filename, | |||
| 966 | } | 966 | } |
| 967 | ADD_TO_DEVTABLE("isapnp", struct isapnp_device_id, do_isapnp_entry); | 967 | ADD_TO_DEVTABLE("isapnp", struct isapnp_device_id, do_isapnp_entry); |
| 968 | 968 | ||
| 969 | /* Looks like: "ipack:fNvNdN". */ | ||
| 970 | static int do_ipack_entry(const char *filename, | ||
| 971 | struct ipack_device_id *id, char *alias) | ||
| 972 | { | ||
| 973 | id->vendor = TO_NATIVE(id->vendor); | ||
| 974 | id->device = TO_NATIVE(id->device); | ||
| 975 | strcpy(alias, "ipack:"); | ||
| 976 | ADD(alias, "f", id->format != IPACK_ANY_FORMAT, id->format); | ||
| 977 | ADD(alias, "v", id->vendor != IPACK_ANY_ID, id->vendor); | ||
| 978 | ADD(alias, "d", id->device != IPACK_ANY_ID, id->device); | ||
| 979 | add_wildcard(alias); | ||
| 980 | return 1; | ||
| 981 | } | ||
| 982 | ADD_TO_DEVTABLE("ipack", struct ipack_device_id, do_ipack_entry); | ||
| 983 | |||
| 969 | /* | 984 | /* |
| 970 | * Append a match expression for a single masked hex digit. | 985 | * Append a match expression for a single masked hex digit. |
| 971 | * outp points to a pointer to the character at which to append. | 986 | * outp points to a pointer to the character at which to append. |
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 68e9f5ed0a6f..0d93856a03f4 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c | |||
| @@ -821,12 +821,15 @@ static const char *section_white_list[] = | |||
| 821 | ".debug*", | 821 | ".debug*", |
| 822 | ".zdebug*", /* Compressed debug sections. */ | 822 | ".zdebug*", /* Compressed debug sections. */ |
| 823 | ".GCC-command-line", /* mn10300 */ | 823 | ".GCC-command-line", /* mn10300 */ |
| 824 | ".GCC.command.line", /* record-gcc-switches, non mn10300 */ | ||
| 824 | ".mdebug*", /* alpha, score, mips etc. */ | 825 | ".mdebug*", /* alpha, score, mips etc. */ |
| 825 | ".pdr", /* alpha, score, mips etc. */ | 826 | ".pdr", /* alpha, score, mips etc. */ |
| 826 | ".stab*", | 827 | ".stab*", |
| 827 | ".note*", | 828 | ".note*", |
| 828 | ".got*", | 829 | ".got*", |
| 829 | ".toc*", | 830 | ".toc*", |
| 831 | ".xt.prop", /* xtensa */ | ||
| 832 | ".xt.lit", /* xtensa */ | ||
| 830 | NULL | 833 | NULL |
| 831 | }; | 834 | }; |
| 832 | 835 | ||
diff --git a/scripts/package/buildtar b/scripts/package/buildtar index 8a7b15598ea9..62d8234f8787 100644 --- a/scripts/package/buildtar +++ b/scripts/package/buildtar | |||
| @@ -28,15 +28,15 @@ case "${1}" in | |||
| 28 | file_ext="" | 28 | file_ext="" |
| 29 | ;; | 29 | ;; |
| 30 | targz-pkg) | 30 | targz-pkg) |
| 31 | compress="gzip -c9" | 31 | compress="gzip" |
| 32 | file_ext=".gz" | 32 | file_ext=".gz" |
| 33 | ;; | 33 | ;; |
| 34 | tarbz2-pkg) | 34 | tarbz2-pkg) |
| 35 | compress="bzip2 -c9" | 35 | compress="bzip2" |
| 36 | file_ext=".bz2" | 36 | file_ext=".bz2" |
| 37 | ;; | 37 | ;; |
| 38 | tarxz-pkg) | 38 | tarxz-pkg) |
| 39 | compress="xz -c9" | 39 | compress="xz" |
| 40 | file_ext=".xz" | 40 | file_ext=".xz" |
| 41 | ;; | 41 | ;; |
| 42 | *) | 42 | *) |
| @@ -109,7 +109,7 @@ esac | |||
| 109 | if tar --owner=root --group=root --help >/dev/null 2>&1; then | 109 | if tar --owner=root --group=root --help >/dev/null 2>&1; then |
| 110 | opts="--owner=root --group=root" | 110 | opts="--owner=root --group=root" |
| 111 | fi | 111 | fi |
| 112 | tar cf - . $opts | ${compress} > "${tarball}${file_ext}" | 112 | tar cf - boot/* lib/* $opts | ${compress} > "${tarball}${file_ext}" |
| 113 | ) | 113 | ) |
| 114 | 114 | ||
| 115 | echo "Tarball successfully created in ${tarball}${file_ext}" | 115 | echo "Tarball successfully created in ${tarball}${file_ext}" |
diff --git a/scripts/recordmcount.h b/scripts/recordmcount.h index 54e35c1e5948..9d1421e63ff8 100644 --- a/scripts/recordmcount.h +++ b/scripts/recordmcount.h | |||
| @@ -261,11 +261,13 @@ static unsigned get_mcountsym(Elf_Sym const *const sym0, | |||
| 261 | &sym0[Elf_r_sym(relp)]; | 261 | &sym0[Elf_r_sym(relp)]; |
| 262 | char const *symname = &str0[w(symp->st_name)]; | 262 | char const *symname = &str0[w(symp->st_name)]; |
| 263 | char const *mcount = gpfx == '_' ? "_mcount" : "mcount"; | 263 | char const *mcount = gpfx == '_' ? "_mcount" : "mcount"; |
| 264 | char const *fentry = "__fentry__"; | ||
| 264 | 265 | ||
| 265 | if (symname[0] == '.') | 266 | if (symname[0] == '.') |
| 266 | ++symname; /* ppc64 hack */ | 267 | ++symname; /* ppc64 hack */ |
| 267 | if (strcmp(mcount, symname) == 0 || | 268 | if (strcmp(mcount, symname) == 0 || |
| 268 | (altmcount && strcmp(altmcount, symname) == 0)) | 269 | (altmcount && strcmp(altmcount, symname) == 0) || |
| 270 | (strcmp(fentry, symname) == 0)) | ||
| 269 | mcountsym = Elf_r_sym(relp); | 271 | mcountsym = Elf_r_sym(relp); |
| 270 | 272 | ||
| 271 | return mcountsym; | 273 | return mcountsym; |
diff --git a/scripts/sign-file b/scripts/sign-file new file mode 100755 index 000000000000..87ca59d36e7e --- /dev/null +++ b/scripts/sign-file | |||
| @@ -0,0 +1,429 @@ | |||
| 1 | #!/usr/bin/perl -w | ||
| 2 | # | ||
| 3 | # Sign a module file using the given key. | ||
| 4 | # | ||
| 5 | # Format: | ||
| 6 | # | ||
| 7 | # ./scripts/sign-file [-v] <key> <x509> <module> [<dest>] | ||
| 8 | # | ||
| 9 | # | ||
| 10 | use strict; | ||
| 11 | use FileHandle; | ||
| 12 | use IPC::Open2; | ||
| 13 | |||
| 14 | my $verbose = 0; | ||
| 15 | if ($#ARGV >= 0 && $ARGV[0] eq "-v") { | ||
| 16 | $verbose = 1; | ||
| 17 | shift; | ||
| 18 | } | ||
| 19 | |||
| 20 | die "Format: ./scripts/sign-file [-v] <key> <x509> <module> [<dest>]\n" | ||
| 21 | if ($#ARGV != 2 && $#ARGV != 3); | ||
| 22 | |||
| 23 | my $private_key = $ARGV[0]; | ||
| 24 | my $x509 = $ARGV[1]; | ||
| 25 | my $module = $ARGV[2]; | ||
| 26 | my $dest = ($#ARGV == 3) ? $ARGV[3] : $ARGV[2] . "~"; | ||
| 27 | |||
| 28 | die "Can't read private key\n" unless (-r $private_key); | ||
| 29 | die "Can't read X.509 certificate\n" unless (-r $x509); | ||
| 30 | die "Can't read module\n" unless (-r $module); | ||
| 31 | |||
| 32 | # | ||
| 33 | # Read the kernel configuration | ||
| 34 | # | ||
| 35 | my %config = ( | ||
| 36 | CONFIG_MODULE_SIG_SHA512 => 1 | ||
| 37 | ); | ||
| 38 | |||
| 39 | if (-r ".config") { | ||
| 40 | open(FD, "<.config") || die ".config"; | ||
| 41 | while (<FD>) { | ||
| 42 | if ($_ =~ /^(CONFIG_.*)=[ym]/) { | ||
| 43 | $config{$1} = 1; | ||
| 44 | } | ||
| 45 | } | ||
| 46 | close(FD); | ||
| 47 | } | ||
| 48 | |||
| 49 | # | ||
| 50 | # Function to read the contents of a file into a variable. | ||
| 51 | # | ||
| 52 | sub read_file($) | ||
| 53 | { | ||
| 54 | my ($file) = @_; | ||
| 55 | my $contents; | ||
| 56 | my $len; | ||
| 57 | |||
| 58 | open(FD, "<$file") || die $file; | ||
| 59 | binmode FD; | ||
| 60 | my @st = stat(FD); | ||
| 61 | die $file if (!@st); | ||
| 62 | $len = read(FD, $contents, $st[7]) || die $file; | ||
| 63 | close(FD) || die $file; | ||
| 64 | die "$file: Wanted length ", $st[7], ", got ", $len, "\n" | ||
| 65 | if ($len != $st[7]); | ||
| 66 | return $contents; | ||
| 67 | } | ||
| 68 | |||
| 69 | ############################################################################### | ||
| 70 | # | ||
| 71 | # First of all, we have to parse the X.509 certificate to find certain details | ||
| 72 | # about it. | ||
| 73 | # | ||
| 74 | # We read the DER-encoded X509 certificate and parse it to extract the Subject | ||
| 75 | # name and Subject Key Identifier. Theis provides the data we need to build | ||
| 76 | # the certificate identifier. | ||
| 77 | # | ||
| 78 | # The signer's name part of the identifier is fabricated from the commonName, | ||
| 79 | # the organizationName or the emailAddress components of the X.509 subject | ||
| 80 | # name. | ||
| 81 | # | ||
| 82 | # The subject key ID is used to select which of that signer's certificates | ||
| 83 | # we're intending to use to sign the module. | ||
| 84 | # | ||
| 85 | ############################################################################### | ||
| 86 | my $x509_certificate = read_file($x509); | ||
| 87 | |||
| 88 | my $UNIV = 0 << 6; | ||
| 89 | my $APPL = 1 << 6; | ||
| 90 | my $CONT = 2 << 6; | ||
| 91 | my $PRIV = 3 << 6; | ||
| 92 | |||
| 93 | my $CONS = 0x20; | ||
| 94 | |||
| 95 | my $BOOLEAN = 0x01; | ||
| 96 | my $INTEGER = 0x02; | ||
| 97 | my $BIT_STRING = 0x03; | ||
| 98 | my $OCTET_STRING = 0x04; | ||
| 99 | my $NULL = 0x05; | ||
| 100 | my $OBJ_ID = 0x06; | ||
| 101 | my $UTF8String = 0x0c; | ||
| 102 | my $SEQUENCE = 0x10; | ||
| 103 | my $SET = 0x11; | ||
| 104 | my $UTCTime = 0x17; | ||
| 105 | my $GeneralizedTime = 0x18; | ||
| 106 | |||
| 107 | my %OIDs = ( | ||
| 108 | pack("CCC", 85, 4, 3) => "commonName", | ||
| 109 | pack("CCC", 85, 4, 6) => "countryName", | ||
| 110 | pack("CCC", 85, 4, 10) => "organizationName", | ||
| 111 | pack("CCC", 85, 4, 11) => "organizationUnitName", | ||
| 112 | pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 1) => "rsaEncryption", | ||
| 113 | pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 5) => "sha1WithRSAEncryption", | ||
| 114 | pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 9, 1) => "emailAddress", | ||
| 115 | pack("CCC", 85, 29, 35) => "authorityKeyIdentifier", | ||
| 116 | pack("CCC", 85, 29, 14) => "subjectKeyIdentifier", | ||
| 117 | pack("CCC", 85, 29, 19) => "basicConstraints" | ||
| 118 | ); | ||
| 119 | |||
| 120 | ############################################################################### | ||
| 121 | # | ||
| 122 | # Extract an ASN.1 element from a string and return information about it. | ||
| 123 | # | ||
| 124 | ############################################################################### | ||
| 125 | sub asn1_extract($$@) | ||
| 126 | { | ||
| 127 | my ($cursor, $expected_tag, $optional) = @_; | ||
| 128 | |||
| 129 | return [ -1 ] | ||
| 130 | if ($cursor->[1] == 0 && $optional); | ||
| 131 | |||
| 132 | die $x509, ": ", $cursor->[0], ": ASN.1 data underrun (elem ", $cursor->[1], ")\n" | ||
| 133 | if ($cursor->[1] < 2); | ||
| 134 | |||
| 135 | my ($tag, $len) = unpack("CC", substr(${$cursor->[2]}, $cursor->[0], 2)); | ||
| 136 | |||
| 137 | if ($expected_tag != -1 && $tag != $expected_tag) { | ||
| 138 | return [ -1 ] | ||
| 139 | if ($optional); | ||
| 140 | die $x509, ": ", $cursor->[0], ": ASN.1 unexpected tag (", $tag, | ||
| 141 | " not ", $expected_tag, ")\n"; | ||
| 142 | } | ||
| 143 | |||
| 144 | $cursor->[0] += 2; | ||
| 145 | $cursor->[1] -= 2; | ||
| 146 | |||
| 147 | die $x509, ": ", $cursor->[0], ": ASN.1 long tag\n" | ||
| 148 | if (($tag & 0x1f) == 0x1f); | ||
| 149 | die $x509, ": ", $cursor->[0], ": ASN.1 indefinite length\n" | ||
| 150 | if ($len == 0x80); | ||
| 151 | |||
| 152 | if ($len > 0x80) { | ||
| 153 | my $l = $len - 0x80; | ||
| 154 | die $x509, ": ", $cursor->[0], ": ASN.1 data underrun (len len $l)\n" | ||
| 155 | if ($cursor->[1] < $l); | ||
| 156 | |||
| 157 | if ($l == 0x1) { | ||
| 158 | $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)); | ||
| 159 | } elsif ($l = 0x2) { | ||
| 160 | $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0], 2)); | ||
| 161 | } elsif ($l = 0x3) { | ||
| 162 | $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)) << 16; | ||
| 163 | $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0] + 1, 2)); | ||
| 164 | } elsif ($l = 0x4) { | ||
| 165 | $len = unpack("N", substr(${$cursor->[2]}, $cursor->[0], 4)); | ||
| 166 | } else { | ||
| 167 | die $x509, ": ", $cursor->[0], ": ASN.1 element too long (", $l, ")\n"; | ||
| 168 | } | ||
| 169 | |||
| 170 | $cursor->[0] += $l; | ||
| 171 | $cursor->[1] -= $l; | ||
| 172 | } | ||
| 173 | |||
| 174 | die $x509, ": ", $cursor->[0], ": ASN.1 data underrun (", $len, ")\n" | ||
| 175 | if ($cursor->[1] < $len); | ||
| 176 | |||
| 177 | my $ret = [ $tag, [ $cursor->[0], $len, $cursor->[2] ] ]; | ||
| 178 | $cursor->[0] += $len; | ||
| 179 | $cursor->[1] -= $len; | ||
| 180 | |||
| 181 | return $ret; | ||
| 182 | } | ||
| 183 | |||
| 184 | ############################################################################### | ||
| 185 | # | ||
| 186 | # Retrieve the data referred to by a cursor | ||
| 187 | # | ||
| 188 | ############################################################################### | ||
| 189 | sub asn1_retrieve($) | ||
| 190 | { | ||
| 191 | my ($cursor) = @_; | ||
| 192 | my ($offset, $len, $data) = @$cursor; | ||
| 193 | return substr($$data, $offset, $len); | ||
| 194 | } | ||
| 195 | |||
| 196 | ############################################################################### | ||
| 197 | # | ||
| 198 | # Roughly parse the X.509 certificate | ||
| 199 | # | ||
| 200 | ############################################################################### | ||
| 201 | my $cursor = [ 0, length($x509_certificate), \$x509_certificate ]; | ||
| 202 | |||
| 203 | my $cert = asn1_extract($cursor, $UNIV | $CONS | $SEQUENCE); | ||
| 204 | my $tbs = asn1_extract($cert->[1], $UNIV | $CONS | $SEQUENCE); | ||
| 205 | my $version = asn1_extract($tbs->[1], $CONT | $CONS | 0, 1); | ||
| 206 | my $serial_number = asn1_extract($tbs->[1], $UNIV | $INTEGER); | ||
| 207 | my $sig_type = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); | ||
| 208 | my $issuer = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); | ||
| 209 | my $validity = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); | ||
| 210 | my $subject = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); | ||
| 211 | my $key = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); | ||
| 212 | my $issuer_uid = asn1_extract($tbs->[1], $CONT | $CONS | 1, 1); | ||
| 213 | my $subject_uid = asn1_extract($tbs->[1], $CONT | $CONS | 2, 1); | ||
| 214 | my $extension_list = asn1_extract($tbs->[1], $CONT | $CONS | 3, 1); | ||
| 215 | |||
| 216 | my $subject_key_id = (); | ||
| 217 | my $authority_key_id = (); | ||
| 218 | |||
| 219 | # | ||
| 220 | # Parse the extension list | ||
| 221 | # | ||
| 222 | if ($extension_list->[0] != -1) { | ||
| 223 | my $extensions = asn1_extract($extension_list->[1], $UNIV | $CONS | $SEQUENCE); | ||
| 224 | |||
| 225 | while ($extensions->[1]->[1] > 0) { | ||
| 226 | my $ext = asn1_extract($extensions->[1], $UNIV | $CONS | $SEQUENCE); | ||
| 227 | my $x_oid = asn1_extract($ext->[1], $UNIV | $OBJ_ID); | ||
| 228 | my $x_crit = asn1_extract($ext->[1], $UNIV | $BOOLEAN, 1); | ||
| 229 | my $x_val = asn1_extract($ext->[1], $UNIV | $OCTET_STRING); | ||
| 230 | |||
| 231 | my $raw_oid = asn1_retrieve($x_oid->[1]); | ||
| 232 | next if (!exists($OIDs{$raw_oid})); | ||
| 233 | my $x_type = $OIDs{$raw_oid}; | ||
| 234 | |||
| 235 | my $raw_value = asn1_retrieve($x_val->[1]); | ||
| 236 | |||
| 237 | if ($x_type eq "subjectKeyIdentifier") { | ||
| 238 | my $vcursor = [ 0, length($raw_value), \$raw_value ]; | ||
| 239 | |||
| 240 | $subject_key_id = asn1_extract($vcursor, $UNIV | $OCTET_STRING); | ||
| 241 | } | ||
| 242 | } | ||
| 243 | } | ||
| 244 | |||
| 245 | ############################################################################### | ||
| 246 | # | ||
| 247 | # Determine what we're going to use as the signer's name. In order of | ||
| 248 | # preference, take one of: commonName, organizationName or emailAddress. | ||
| 249 | # | ||
| 250 | ############################################################################### | ||
| 251 | my $org = ""; | ||
| 252 | my $cn = ""; | ||
| 253 | my $email = ""; | ||
| 254 | |||
| 255 | while ($subject->[1]->[1] > 0) { | ||
| 256 | my $rdn = asn1_extract($subject->[1], $UNIV | $CONS | $SET); | ||
| 257 | my $attr = asn1_extract($rdn->[1], $UNIV | $CONS | $SEQUENCE); | ||
| 258 | my $n_oid = asn1_extract($attr->[1], $UNIV | $OBJ_ID); | ||
| 259 | my $n_val = asn1_extract($attr->[1], -1); | ||
| 260 | |||
| 261 | my $raw_oid = asn1_retrieve($n_oid->[1]); | ||
| 262 | next if (!exists($OIDs{$raw_oid})); | ||
| 263 | my $n_type = $OIDs{$raw_oid}; | ||
| 264 | |||
| 265 | my $raw_value = asn1_retrieve($n_val->[1]); | ||
| 266 | |||
| 267 | if ($n_type eq "organizationName") { | ||
| 268 | $org = $raw_value; | ||
| 269 | } elsif ($n_type eq "commonName") { | ||
| 270 | $cn = $raw_value; | ||
| 271 | } elsif ($n_type eq "emailAddress") { | ||
| 272 | $email = $raw_value; | ||
| 273 | } | ||
| 274 | } | ||
| 275 | |||
| 276 | my $signers_name = $email; | ||
| 277 | |||
| 278 | if ($org && $cn) { | ||
| 279 | # Don't use the organizationName if the commonName repeats it | ||
| 280 | if (length($org) <= length($cn) && | ||
| 281 | substr($cn, 0, length($org)) eq $org) { | ||
| 282 | $signers_name = $cn; | ||
| 283 | goto got_id_name; | ||
| 284 | } | ||
| 285 | |||
| 286 | # Or a signifcant chunk of it | ||
| 287 | if (length($org) >= 7 && | ||
| 288 | length($cn) >= 7 && | ||
| 289 | substr($cn, 0, 7) eq substr($org, 0, 7)) { | ||
| 290 | $signers_name = $cn; | ||
| 291 | goto got_id_name; | ||
| 292 | } | ||
| 293 | |||
| 294 | $signers_name = $org . ": " . $cn; | ||
| 295 | } elsif ($org) { | ||
| 296 | $signers_name = $org; | ||
| 297 | } elsif ($cn) { | ||
| 298 | $signers_name = $cn; | ||
| 299 | } | ||
| 300 | |||
| 301 | got_id_name: | ||
| 302 | |||
| 303 | die $x509, ": ", "X.509: Couldn't find the Subject Key Identifier extension\n" | ||
| 304 | if (!$subject_key_id); | ||
| 305 | |||
| 306 | my $key_identifier = asn1_retrieve($subject_key_id->[1]); | ||
| 307 | |||
| 308 | ############################################################################### | ||
| 309 | # | ||
| 310 | # Create and attach the module signature | ||
| 311 | # | ||
| 312 | ############################################################################### | ||
| 313 | |||
| 314 | # | ||
| 315 | # Signature parameters | ||
| 316 | # | ||
| 317 | my $algo = 1; # Public-key crypto algorithm: RSA | ||
| 318 | my $hash = 0; # Digest algorithm | ||
| 319 | my $id_type = 1; # Identifier type: X.509 | ||
| 320 | |||
| 321 | # | ||
| 322 | # Digest the data | ||
| 323 | # | ||
| 324 | my ($dgst, $prologue) = (); | ||
| 325 | if (exists $config{"CONFIG_MODULE_SIG_SHA1"}) { | ||
| 326 | $prologue = pack("C*", | ||
| 327 | 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, | ||
| 328 | 0x2B, 0x0E, 0x03, 0x02, 0x1A, | ||
| 329 | 0x05, 0x00, 0x04, 0x14); | ||
| 330 | $dgst = "-sha1"; | ||
| 331 | $hash = 2; | ||
| 332 | } elsif (exists $config{"CONFIG_MODULE_SIG_SHA224"}) { | ||
| 333 | $prologue = pack("C*", | ||
| 334 | 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, | ||
| 335 | 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, | ||
| 336 | 0x05, 0x00, 0x04, 0x1C); | ||
| 337 | $dgst = "-sha224"; | ||
| 338 | $hash = 7; | ||
| 339 | } elsif (exists $config{"CONFIG_MODULE_SIG_SHA256"}) { | ||
| 340 | $prologue = pack("C*", | ||
| 341 | 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, | ||
| 342 | 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, | ||
| 343 | 0x05, 0x00, 0x04, 0x20); | ||
| 344 | $dgst = "-sha256"; | ||
| 345 | $hash = 4; | ||
| 346 | } elsif (exists $config{"CONFIG_MODULE_SIG_SHA384"}) { | ||
| 347 | $prologue = pack("C*", | ||
| 348 | 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, | ||
| 349 | 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, | ||
| 350 | 0x05, 0x00, 0x04, 0x30); | ||
| 351 | $dgst = "-sha384"; | ||
| 352 | $hash = 5; | ||
| 353 | } elsif (exists $config{"CONFIG_MODULE_SIG_SHA512"}) { | ||
| 354 | $prologue = pack("C*", | ||
| 355 | 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, | ||
| 356 | 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, | ||
| 357 | 0x05, 0x00, 0x04, 0x40); | ||
| 358 | $dgst = "-sha512"; | ||
| 359 | $hash = 6; | ||
| 360 | } else { | ||
| 361 | die "Can't determine hash algorithm"; | ||
| 362 | } | ||
| 363 | |||
| 364 | # | ||
| 365 | # Generate the digest and read from openssl's stdout | ||
| 366 | # | ||
| 367 | my $digest; | ||
| 368 | $digest = readpipe("openssl dgst $dgst -binary $module") || die "openssl dgst"; | ||
| 369 | |||
| 370 | # | ||
| 371 | # Generate the binary signature, which will be just the integer that comprises | ||
| 372 | # the signature with no metadata attached. | ||
| 373 | # | ||
| 374 | my $pid; | ||
| 375 | $pid = open2(*read_from, *write_to, | ||
| 376 | "openssl rsautl -sign -inkey $private_key -keyform PEM") || | ||
| 377 | die "openssl rsautl"; | ||
| 378 | binmode write_to; | ||
| 379 | print write_to $prologue . $digest || die "pipe to openssl rsautl"; | ||
| 380 | close(write_to) || die "pipe to openssl rsautl"; | ||
| 381 | |||
| 382 | binmode read_from; | ||
| 383 | my $signature; | ||
| 384 | read(read_from, $signature, 4096) || die "pipe from openssl rsautl"; | ||
| 385 | close(read_from) || die "pipe from openssl rsautl"; | ||
| 386 | $signature = pack("n", length($signature)) . $signature, | ||
| 387 | |||
| 388 | waitpid($pid, 0) || die; | ||
| 389 | die "openssl rsautl died: $?" if ($? >> 8); | ||
| 390 | |||
| 391 | # | ||
| 392 | # Build the signed binary | ||
| 393 | # | ||
| 394 | my $unsigned_module = read_file($module); | ||
| 395 | |||
| 396 | my $magic_number = "~Module signature appended~\n"; | ||
| 397 | |||
| 398 | my $info = pack("CCCCCxxxN", | ||
| 399 | $algo, $hash, $id_type, | ||
| 400 | length($signers_name), | ||
| 401 | length($key_identifier), | ||
| 402 | length($signature)); | ||
| 403 | |||
| 404 | if ($verbose) { | ||
| 405 | print "Size of unsigned module: ", length($unsigned_module), "\n"; | ||
| 406 | print "Size of signer's name : ", length($signers_name), "\n"; | ||
| 407 | print "Size of key identifier : ", length($key_identifier), "\n"; | ||
| 408 | print "Size of signature : ", length($signature), "\n"; | ||
| 409 | print "Size of informaton : ", length($info), "\n"; | ||
| 410 | print "Size of magic number : ", length($magic_number), "\n"; | ||
| 411 | print "Signer's name : '", $signers_name, "'\n"; | ||
| 412 | print "Digest : $dgst\n"; | ||
| 413 | } | ||
| 414 | |||
| 415 | open(FD, ">$dest") || die $dest; | ||
| 416 | binmode FD; | ||
| 417 | print FD | ||
| 418 | $unsigned_module, | ||
| 419 | $signers_name, | ||
| 420 | $key_identifier, | ||
| 421 | $signature, | ||
| 422 | $info, | ||
| 423 | $magic_number | ||
| 424 | ; | ||
| 425 | close FD || die $dest; | ||
| 426 | |||
| 427 | if ($#ARGV != 3) { | ||
| 428 | rename($dest, $module) || die $module; | ||
| 429 | } | ||
diff --git a/scripts/sortextable.c b/scripts/sortextable.c index 6acf83449105..f19ddc47304c 100644 --- a/scripts/sortextable.c +++ b/scripts/sortextable.c | |||
| @@ -161,7 +161,7 @@ typedef void (*table_sort_t)(char *, int); | |||
| 161 | #define SORTEXTABLE_64 | 161 | #define SORTEXTABLE_64 |
| 162 | #include "sortextable.h" | 162 | #include "sortextable.h" |
| 163 | 163 | ||
| 164 | static int compare_x86_table(const void *a, const void *b) | 164 | static int compare_relative_table(const void *a, const void *b) |
| 165 | { | 165 | { |
| 166 | int32_t av = (int32_t)r(a); | 166 | int32_t av = (int32_t)r(a); |
| 167 | int32_t bv = (int32_t)r(b); | 167 | int32_t bv = (int32_t)r(b); |
| @@ -173,7 +173,7 @@ static int compare_x86_table(const void *a, const void *b) | |||
| 173 | return 0; | 173 | return 0; |
| 174 | } | 174 | } |
| 175 | 175 | ||
| 176 | static void sort_x86_table(char *extab_image, int image_size) | 176 | static void sort_relative_table(char *extab_image, int image_size) |
| 177 | { | 177 | { |
| 178 | int i; | 178 | int i; |
| 179 | 179 | ||
| @@ -188,7 +188,7 @@ static void sort_x86_table(char *extab_image, int image_size) | |||
| 188 | i += 4; | 188 | i += 4; |
| 189 | } | 189 | } |
| 190 | 190 | ||
| 191 | qsort(extab_image, image_size / 8, 8, compare_x86_table); | 191 | qsort(extab_image, image_size / 8, 8, compare_relative_table); |
| 192 | 192 | ||
| 193 | /* Now denormalize. */ | 193 | /* Now denormalize. */ |
| 194 | i = 0; | 194 | i = 0; |
| @@ -245,9 +245,9 @@ do_file(char const *const fname) | |||
| 245 | break; | 245 | break; |
| 246 | case EM_386: | 246 | case EM_386: |
| 247 | case EM_X86_64: | 247 | case EM_X86_64: |
| 248 | custom_sort = sort_x86_table; | ||
| 249 | break; | ||
| 250 | case EM_S390: | 248 | case EM_S390: |
| 249 | custom_sort = sort_relative_table; | ||
| 250 | break; | ||
| 251 | case EM_MIPS: | 251 | case EM_MIPS: |
| 252 | break; | 252 | break; |
| 253 | } /* end switch */ | 253 | } /* end switch */ |
diff --git a/scripts/tags.sh b/scripts/tags.sh index cff8faad73d1..79fdafb0d263 100755 --- a/scripts/tags.sh +++ b/scripts/tags.sh | |||
| @@ -154,7 +154,9 @@ exuberant() | |||
| 154 | --regex-c++='/__CLEARPAGEFLAG_NOOP\(([^,)]*).*/__ClearPage\1/' \ | 154 | --regex-c++='/__CLEARPAGEFLAG_NOOP\(([^,)]*).*/__ClearPage\1/' \ |
| 155 | --regex-c++='/TESTCLEARFLAG_FALSE\(([^,)]*).*/TestClearPage\1/' \ | 155 | --regex-c++='/TESTCLEARFLAG_FALSE\(([^,)]*).*/TestClearPage\1/' \ |
| 156 | --regex-c++='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/' \ | 156 | --regex-c++='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/' \ |
| 157 | --regex-c++='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/' | 157 | --regex-c++='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/' \ |
| 158 | --regex-c='/PCI_OP_READ\(([a-z]*[a-z]).*[1-4]\)/pci_bus_read_config_\1/' \ | ||
| 159 | --regex-c='/PCI_OP_WRITE\(([a-z]*[a-z]).*[1-4]\)/pci_bus_write_config_\1/' | ||
| 158 | 160 | ||
| 159 | all_kconfigs | xargs $1 -a \ | 161 | all_kconfigs | xargs $1 -a \ |
| 160 | --langdef=kconfig --language-force=kconfig \ | 162 | --langdef=kconfig --language-force=kconfig \ |
| @@ -197,7 +199,9 @@ emacs() | |||
| 197 | --regex='/__CLEARPAGEFLAG_NOOP\(([^,)]*).*/__ClearPage\1/' \ | 199 | --regex='/__CLEARPAGEFLAG_NOOP\(([^,)]*).*/__ClearPage\1/' \ |
| 198 | --regex='/TESTCLEARFLAG_FALSE\(([^,)]*).*/TestClearPage\1/' \ | 200 | --regex='/TESTCLEARFLAG_FALSE\(([^,)]*).*/TestClearPage\1/' \ |
| 199 | --regex='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/' \ | 201 | --regex='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/' \ |
| 200 | --regex='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/' | 202 | --regex='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/' \ |
| 203 | --regex='/PCI_OP_READ\(([a-z]*[a-z]).*[1-4]\)/pci_bus_read_config_\1/' \ | ||
| 204 | --regex='/PCI_OP_WRITE\(([a-z]*[a-z]).*[1-4]\)/pci_bus_write_config_\1/' | ||
| 201 | 205 | ||
| 202 | all_kconfigs | xargs $1 -a \ | 206 | all_kconfigs | xargs $1 -a \ |
| 203 | --regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/\3/' | 207 | --regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/\3/' |
