Compare commits

..

No commits in common. "main" and "v1.6.0" have entirely different histories.
main ... v1.6.0

129 changed files with 1276 additions and 4321 deletions

View file

@ -1,39 +1,23 @@
# FreeBSD build with multiple versions
freebsd_versions_task:
name: FreeBSD $FREEBSD_VERSION make build
freebsd_instance:
image_family: $FREEBSD_IMAGE
matrix:
- env:
FREEBSD_VERSION: "13.5"
FREEBSD_IMAGE: freebsd-13-5
- env:
FREEBSD_VERSION: "14.3"
FREEBSD_IMAGE: freebsd-14-3
install_script:
- pkg install -y git gmake flex bison python3 py312-setuptools swig libyaml pkgconf
build_script:
- gmake
check_script:
- gmake check
env:
CIRRUS_CLONE_DEPTH: 1
# FreeBSD meson builds with multiple versions
freebsd_meson_versions_task:
name: FreeBSD $FREEBSD_VERSION meson build
freebsd_12_task:
freebsd_instance:
image_family: $FREEBSD_IMAGE
matrix:
- env:
FREEBSD_VERSION: "13.5"
FREEBSD_IMAGE: freebsd-13-5
- env:
FREEBSD_VERSION: "14.3"
FREEBSD_IMAGE: freebsd-14-3
image: freebsd-12-1-release-amd64
install_script:
- pkg install -y git meson ninja flex bison python3 py312-setuptools swig libyaml pkgconf
setup_script:
- meson setup -D python=enabled -D yaml=enabled build
pkg install -y bison gmake pkgconf
build_script:
- meson compile -C build
gmake
test_script:
- if ! meson test -C build; then cat build/meson-logs/testlog.txt; false; fi
gmake check
linux_gcc_task:
container:
image: gcc:latest
install_script:
- apt-get update
- apt-get -y install bison flex
build_script:
- make
test_script:
- make check

View file

@ -1,135 +0,0 @@
# SPDX-License-Identifier: GPL-2.0
#
# clang-format configuration file. Intended for clang-format >= 11.
#
# For more information, see:
#
# Documentation/dev-tools/clang-format.rst
# https://clang.llvm.org/docs/ClangFormat.html
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
#
---
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: false
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: true
AfterNamespace: true
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
BreakBeforeInheritanceComma: false
BreakBeforeTernaryOperators: false
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeComma
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: false
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 8
ContinuationIndentWidth: 8
Cpp11BracedListStyle: false
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: false
# Taken from:
# git grep -h '^#define [^[:space:]]*for_each[^[:space:]]*(' \
# | sed "s,^#define \([^[:space:]]*for_each[^[:space:]]*\)(.*$, - '\1'," \
# | LC_ALL=C sort -u
ForEachMacros:
- 'fdt_for_each_property_offset'
- 'fdt_for_each_subnode'
- 'for_each_child'
- 'for_each_child_withdel'
- 'for_each_label'
- 'for_each_label_withdel'
- 'for_each_marker'
- 'for_each_marker_of_type'
- 'for_each_property'
- 'for_each_property_withdel'
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '.*'
Priority: 1
IncludeIsMainRegex: '(Test)?$'
IndentCaseLabels: false
IndentGotoLabels: false
IndentPPDirectives: None
IndentWidth: 8
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 8
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: true
# Taken from git's rules
PenaltyBreakAssignment: 10
PenaltyBreakBeforeFirstCallParameter: 30
PenaltyBreakComment: 10
PenaltyBreakFirstLessLess: 0
PenaltyBreakString: 10
PenaltyExcessCharacter: 100
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
ReflowComments: false
SortIncludes: false
SortUsingDeclarations: false
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatementsExceptForEachMacros
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: false
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp03
TabWidth: 8
UseTab: Always
...

View file

@ -28,6 +28,3 @@ indent_size = 4
[meson.build]
indent_style = space
indent_size = 2
[*.lds]
indent_style = tab

View file

@ -1,114 +0,0 @@
---
name: Build test
'on':
push:
branches:
- main
- ci
pull_request:
branches:
- main
# ensure that the workflow is only triggered once per PR, subsequent pushes to the PR will cancel
# and restart the workflow. See https://docs.github.com/en/actions/using-jobs/using-concurrency
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
build-make:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
os: [ "alpine", "archlinux", "fedora", "ubuntu" ]
container:
image: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Dependencies
run: |
./scripts/install-deps.sh
- name: Build
run: |
make
- name: Run check
run: |
make check
build-meson:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
os: [ "alpine", "archlinux", "fedora", "ubuntu" ]
container:
image: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Dependencies
run: |
./scripts/install-deps.sh
- name: Setup
run: meson setup -D python=enabled -D yaml=enabled build
- name: Build
run: meson compile -C build
- name: Run check
run: if ! meson test -C build; then cat build/meson-logs/testlog.txt; false; fi
build-windows:
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
include:
- { sys: mingw32 }
- { sys: mingw64 }
- { sys: ucrt64 }
- { sys: clang64 }
name: ${{ matrix.sys }}
defaults:
run:
shell: msys2 {0}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup MSYS2
uses: msys2/setup-msys2@v2
with:
msystem: ${{matrix.sys}}
update: true
install: >-
git
flex
bison
pacboy: >-
toolchain:p
meson:p
ninja:p
libyaml:p
swig:p
python-setuptools-scm:p
- name: '🚧 Build'
run: |
meson setup -Dtools=true -Dtests=false build
meson compile -C build

11
.gitignore vendored
View file

@ -3,13 +3,11 @@
*.a
*.patch
*.so
*.so.*
*~
*.bak
*.tab.[ch]
lex.yy.c
*.lex.c
.*.swp
/dtc
/fdtdump
/convert-dtsv0
@ -19,12 +17,3 @@ lex.yy.c
/fdtoverlay
/patches
/.pc
# cscope files
cscope.*
ncscope.*
.eggs/
build/
dist/
*.egg-info/

View file

@ -1,65 +0,0 @@
stages:
- build
variables:
GIT_DEPTH: 1
workflow:
rules:
- if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "main"
- if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "ci"
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
# Linux builds with make
.build-make-template: &build-make-template
stage: build
before_script:
- ./scripts/install-deps.sh
script:
- make
- make check
interruptible: true
build-make-alpine:
<<: *build-make-template
image: alpine:latest
build-make-archlinux:
<<: *build-make-template
image: archlinux:latest
build-make-fedora:
<<: *build-make-template
image: fedora:latest
build-make-ubuntu:
<<: *build-make-template
image: ubuntu:latest
# Linux builds with meson
.build-meson-template: &build-meson-template
stage: build
before_script:
- ./scripts/install-deps.sh
script:
- meson setup -D python=enabled -D yaml=enabled build
- meson compile -C build
- if ! meson test -C build; then cat build/meson-logs/testlog.txt; false; fi
interruptible: true
build-meson-alpine:
<<: *build-meson-template
image: alpine:latest
build-meson-archlinux:
<<: *build-meson-template
image: archlinux:latest
build-meson-fedora:
<<: *build-meson-template
image: fedora:latest
build-meson-ubuntu:
<<: *build-meson-template
image: ubuntu:latest

65
.travis.yml Normal file
View file

@ -0,0 +1,65 @@
language: c
# Coverity Scan uploads
env:
global:
# COVERITY_SCAN_TOKEN (dgibson/dtc)
- secure: "vlHvXe618//IM9LQaKzqsrUbjs7ng0L9UCST4kJbJnFQDXvVe5JiSmJGd4ef7mm0NUv5bMRl2W3xCiu6BYAu/NvU3tMNHoLG+JgCJs0+wLJXbWOwji/NmH7olqgJG+CmpaCMXjARF6+nrTnBYHJL6cYyf4KVoV4B0I/hLUW91+s="
matrix:
include:
- addons:
apt:
packages:
- swig
- python-dev
- valgrind
- libyaml-0-2
coverity_scan:
project:
name: dtc
description: Device Tree Compiler
notification_email: david@gibson.dropbear.id.au
build_command: make
branch_pattern: coverity_scan
script:
- make
- make check && make checkm
# Check it builds properly without optional packages:
# python, valgrind, libyaml
- script:
- make
- make check
- arch: arm64
addons:
apt_packages:
- swig
- python-dev
- valgrind
- libyaml-0-2
script:
- make
- make check checkm
- arch: ppc64le
addons:
apt_packages:
- swig
- python-dev
- libyaml-0-2
script:
- make
- make check
- arch: s390x
addons:
apt_packages:
- swig
- python-dev
- valgrind
- libyaml-0-2
script:
- make
- make check checkm

View file

@ -1,79 +0,0 @@
# Contributing to dtc or libfdt
There are two ways to submit changes for dtc or libfdt:
* Post patches directly to the
[devicetree-compiler](mailto:devicetree-compiler@vger.kernel.org)
mailing list.
* Submit pull requests via
[Github](https://github.com/dgibson/dtc/pulls)
## Adding a new function to libfdt.h
The shared library uses `libfdt/version.lds` to list the exported
functions, so add your new function there. Check that your function
works with pylibfdt. If it cannot be supported, put the declaration in
`libfdt.h` behind `#ifndef SWIG` so that swig ignores it.
## Tests
Test files are kept in the `tests/` directory. Use `make check` to build and run
all tests.
If you want to adjust a test file, be aware that `tree_tree1.dts` is compiled
and checked against a binary tree from assembler macros in `trees.S`. So
if you change that file you must change `tree.S` also.
## Developer's Certificate of Origin
Like many other projects, dtc and libfdt have adopted the "Developer's
Certificate of Origin" (Signed-off-by) process created by the Linux
kernel community to improve tracking of who did what. Here's how it
works (this is a very slight modification of the description from
`Documentation/process/submitting-patches.rst` in the kernel tree):
The sign-off is a simple line at the end of the explanation for the
patch, which certifies that you wrote it or otherwise have the right
to pass it on as an open-source patch. The rules are pretty simple:
if you can certify the below:
Developer's Certificate of Origin 1.1
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the open source license
indicated in the file; or
(b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that
work with modifications, whether created in whole or in part
by me, under the same open source license (unless I am
permitted to submit under a different license), as indicated
in the file; or
(c) The contribution was provided directly to me by some other
person who certified (a), (b) or (c) and I have not modified
it.
(d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.
then you just add a line saying::
Signed-off-by: Random J Developer <random@developer.example.org>
using your real name (sorry, no pseudonyms or anonymous
contributions.) This will be done for you automatically if you use
`git commit -s`. Reverts should also include "Signed-off-by". `git
revert -s` does that for you.
Any further SoBs (Signed-off-by:'s) following the author's SoB are
from people handling and transporting the patch, but were not involved
in its development. SoB chains should reflect the **real** route a
patch took as it was propagated to the maintainers, with the first SoB
entry signalling primary authorship of a single author.

View file

@ -6,7 +6,7 @@ the hardware capabilities. This is insufficient for platforms
that need to dynamically insert Device Tree fragments into the
live tree.
This document explains the Device Tree object format and
This document explains the the Device Tree object format and
modifications made to the Device Tree compiler, which make it possible.
1. Simplified Problem Definition
@ -35,7 +35,7 @@ We have a number of peripherals that after probing (using some undefined method)
should result in different Device Tree configuration.
We cannot boot with this static tree because due to the configuration of the
foo platform there exist multiple conflicting peripherals DT fragments.
foo platform there exist multiple conficting peripherals DT fragments.
So for the bar peripheral we would have this:

View file

@ -43,8 +43,9 @@ The gitweb interface for the upstream repository is:
1.1) Submitting Patches
Patches should be sent to the maintainer:
Patches should be sent to the maintainers:
David Gibson <david@gibson.dropbear.id.au>
Jon Loeliger <jdl@jdl.com>
and CCed to <devicetree-compiler@vger.kernel.org>.
2) Description
@ -122,24 +123,12 @@ Options:
Relevant for dtb and asm output only.
-@
Generates a __symbols__ node at the root node. This node contains a
property for each label. The property's name is the label name and the
value is the path of the labeled node.
Generates a __symbols__ node at the root node of the resulting blob
for any node labels used, and for any local references using phandles
it also generates a __local_fixups__ node that tracks them.
-L
Possibly generates a __local_fixups__ and a __fixups__ node at the root node.
For each property that contains a phandle reference using a locally
defined phandle, the __local_fixups__ node contains a property (at path
/__local_fixups__/$a if $a is the path of the node). Its value is a list
of offsets that are phandle values. If there are no such properties, no
__local_fixups__ node is generated.
For each undefined label used in at least one reference, the __fixups__
node contains a property. Its name is the label name, its value is a
list of locations where the label is used in a reference in the format
"path:property:offset". If there is no undefined label, no __fixups__
nodes is generated.
Enabled by default for compiling overlays (i.e. dts files with a
/plugin/ tag).
When using the /plugin/ tag all unresolved label references to
be tracked in the __fixups__ node, making dynamic resolution possible.
-A
Generate automatically aliases for all node labels. This is similar to
@ -723,7 +712,7 @@ The syntax of the fdtget command is:
where options are:
<type> s=string, i=int, u=unsigned, x=hex, r=raw
<type> s=string, i=int, u=unsigned, x=hex
Optional modifier prefix:
hh or b=byte, h=2 byte, l=4 byte (default)

118
Makefile
View file

@ -3,17 +3,16 @@
# Device Tree Compiler
#
$(warning WARNING: Building dtc using make is deprecated, in favour of using Meson (https://mesonbuild.com))
$(warning )
$(warning Use `meson setup builddir/ && meson compile -C builddir/` to build, `meson test -C builddir/` to test, or `meson configure` to see build options.)
#
# Version information will be constructed in this order:
# DTC_VERSION release version as MAJOR.MINOR.PATCH
# EXTRAVERSION might be "-rc", for example.
# LOCAL_VERSION is likely from command line.
# CONFIG_LOCALVERSION from some future config system.
#
DTC_VERSION = $(shell cat VERSION.txt)
VERSION = 1
PATCHLEVEL = 6
SUBLEVEL = 0
EXTRAVERSION =
LOCAL_VERSION =
CONFIG_LOCALVERSION =
@ -22,20 +21,17 @@ CONFIG_LOCALVERSION =
ASSUME_MASK ?= 0
CPPFLAGS = -I libfdt -I . -DFDT_ASSUME_MASK=$(ASSUME_MASK)
WARNINGS = -Wall -Wpointer-arith -Wcast-qual -Wnested-externs -Wsign-compare \
-Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls -Wshadow \
-Wwrite-strings
ifeq ($(shell $(CC) --version | grep -q gcc && echo gcc),gcc)
WARNINGS += -Wsuggest-attribute=format
endif
WARNINGS = -Wall -Wpointer-arith -Wcast-qual -Wnested-externs \
-Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls -Wshadow
CFLAGS = -g -Os $(SHAREDLIB_CFLAGS) -Werror $(WARNINGS) $(EXTRA_CFLAGS)
BISON = bison
LEX = flex
SWIG = swig
PKG_CONFIG ?= pkg-config
PYTHON ?= python3
INSTALL = install
INSTALL = /usr/bin/install
INSTALL_PROGRAM = $(INSTALL)
INSTALL_LIB = $(INSTALL)
INSTALL_DATA = $(INSTALL) -m 644
@ -49,6 +45,8 @@ INCLUDEDIR = $(PREFIX)/include
HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \
sed -e 's/\(cygwin\|msys\).*/\1/')
NO_PYTHON ?= 0
NO_VALGRIND := $(shell $(PKG_CONFIG) --exists valgrind; echo $$?)
ifeq ($(NO_VALGRIND),1)
CPPFLAGS += -DNO_VALGRIND
@ -56,20 +54,13 @@ else
CFLAGS += $(shell $(PKG_CONFIG) --cflags valgrind)
endif
# libyaml before version 0.2.3 expects non-const string parameters. Supporting
# both variants would require either cpp magic or passing
# -Wno-error=discarded-qualifiers to the compiler. For the sake of simplicity
# just support libyaml >= 0.2.3.
NO_YAML := $(shell $(PKG_CONFIG) --atleast-version 0.2.3 yaml-0.1; echo $$?)
NO_YAML := $(shell $(PKG_CONFIG) --exists yaml-0.1; echo $$?)
ifeq ($(NO_YAML),1)
CFLAGS += -DNO_YAML
else
LDLIBS_dtc += $(shell $(PKG_CONFIG) --libs yaml-0.1)
CFLAGS += $(shell $(PKG_CONFIG) --cflags yaml-0.1)
endif
HAS_VERSION_SCRIPT := $(shell echo 'int main(){}' | $(CC) -Wl,--version-script=/dev/null -x c - -o /dev/null 2>/dev/null && echo y)
ifeq ($(HOSTOS),darwin)
SHAREDLIB_EXT = dylib
SHAREDLIB_CFLAGS = -fPIC
@ -77,15 +68,11 @@ SHAREDLIB_LDFLAGS = -fPIC -dynamiclib -Wl,-install_name -Wl,
else ifeq ($(HOSTOS),$(filter $(HOSTOS),msys cygwin))
SHAREDLIB_EXT = so
SHAREDLIB_CFLAGS =
SHAREDLIB_LDFLAGS = -shared -Wl,-soname,
SHAREDLIB_LDFLAGS = -shared -Wl,--version-script=$(LIBFDT_version) -Wl,-soname,
else
SHAREDLIB_EXT = so
SHAREDLIB_CFLAGS = -fPIC
SHAREDLIB_LDFLAGS = -fPIC -shared -Wl,-soname,
endif
ifeq ($(HAS_VERSION_SCRIPT),y)
SHAREDLIB_LDFLAGS += -Wl,--version-script=$(LIBFDT_version)
SHAREDLIB_LDFLAGS = -fPIC -shared -Wl,--version-script=$(LIBFDT_version) -Wl,-soname,
endif
#
@ -110,6 +97,7 @@ endif
# Rules for versioning
#
DTC_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
VERSION_FILE = version_gen.h
CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
@ -164,8 +152,30 @@ SCRIPTS = dtdiff
all: $(BIN) libfdt
# We need both Python and swig to build/install pylibfdt.
# This builds the given make ${target} if those deps are found.
check_python_deps = \
if $(PKG_CONFIG) --cflags $(PYTHON) >/dev/null 2>&1; then \
if which swig >/dev/null 2>&1; then \
can_build=yes; \
fi; \
fi; \
if [ "$${can_build}" = "yes" ]; then \
$(MAKE) $${target}; \
else \
echo "\#\# Skipping pylibfdt (install python dev and swig to build)"; \
fi ;
.PHONY: maybe_pylibfdt
maybe_pylibfdt: FORCE
target=pylibfdt; $(check_python_deps)
ifeq ($(NO_PYTHON),0)
all: maybe_pylibfdt
endif
ifneq ($(DEPTARGETS),)
ifneq ($(MAKECMDGOALS),libfdt)
-include $(DTC_OBJS:%.o=%.d)
-include $(CONVERT_OBJS:%.o=%.d)
-include $(FDTDUMP_OBJS:%.o=%.d)
@ -173,7 +183,6 @@ ifneq ($(MAKECMDGOALS),libfdt)
-include $(FDTPUT_OBJS:%.o=%.d)
-include $(FDTOVERLAY_OBJS:%.o=%.d)
endif
endif
@ -186,13 +195,6 @@ LIBFDT_lib = $(LIBFDT_dir)/$(LIBFDT_LIB)
LIBFDT_include = $(addprefix $(LIBFDT_dir)/,$(LIBFDT_INCLUDES))
LIBFDT_version = $(addprefix $(LIBFDT_dir)/,$(LIBFDT_VERSION))
ifeq ($(STATIC_BUILD),1)
CFLAGS += -static
LIBFDT_dep = $(LIBFDT_archive)
else
LIBFDT_dep = $(LIBFDT_lib)
endif
include $(LIBFDT_dir)/Makefile.libfdt
.PHONY: libfdt
@ -205,7 +207,6 @@ $(LIBFDT_lib): $(addprefix $(LIBFDT_dir)/,$(LIBFDT_OBJS)) $(LIBFDT_version)
$(CC) $(LDFLAGS) $(SHAREDLIB_LDFLAGS)$(LIBFDT_soname) -o $(LIBFDT_lib) \
$(addprefix $(LIBFDT_dir)/,$(LIBFDT_OBJS))
ln -sf $(LIBFDT_LIB) $(LIBFDT_dir)/$(LIBFDT_soname)
ln -sf $(LIBFDT_soname) $(LIBFDT_dir)/$(LIBFDT_so)
ifneq ($(DEPTARGETS),)
-include $(LIBFDT_OBJS:%.o=$(LIBFDT_dir)/%.d)
@ -222,7 +223,7 @@ install-bin: all $(SCRIPTS)
$(INSTALL_PROGRAM) $(BIN) $(DESTDIR)$(BINDIR)
$(INSTALL_SCRIPT) $(SCRIPTS) $(DESTDIR)$(BINDIR)
install-lib: libfdt
install-lib: all
@$(VECHO) INSTALL-LIB
$(INSTALL) -d $(DESTDIR)$(LIBDIR)
$(INSTALL_LIB) $(LIBFDT_lib) $(DESTDIR)$(LIBDIR)
@ -237,6 +238,14 @@ install-includes:
install: install-bin install-lib install-includes
.PHONY: maybe_install_pylibfdt
maybe_install_pylibfdt: FORCE
target=install_pylibfdt; $(check_python_deps)
ifeq ($(NO_PYTHON),0)
install: maybe_install_pylibfdt
endif
$(VERSION_FILE): Makefile FORCE
$(call filechk,version)
@ -249,11 +258,11 @@ convert-dtsv0: $(CONVERT_OBJS)
fdtdump: $(FDTDUMP_OBJS)
fdtget: $(FDTGET_OBJS) $(LIBFDT_dep)
fdtget: $(FDTGET_OBJS) $(LIBFDT_lib)
fdtput: $(FDTPUT_OBJS) $(LIBFDT_dep)
fdtput: $(FDTPUT_OBJS) $(LIBFDT_lib)
fdtoverlay: $(FDTOVERLAY_OBJS) $(LIBFDT_dep)
fdtoverlay: $(FDTOVERLAY_OBJS) $(LIBFDT_lib)
dist:
git archive --format=tar --prefix=dtc-$(dtc_version)/ HEAD \
@ -262,6 +271,16 @@ dist:
gzip -9 > ../dtc-$(dtc_version).tar.gz
#
# Rules for pylibfdt
#
PYLIBFDT_dir = pylibfdt
include $(PYLIBFDT_dir)/Makefile.pylibfdt
.PHONY: pylibfdt
pylibfdt: $(PYLIBFDT_dir)/_libfdt.so
#
# Release signing and uploading
# This is for maintainer convenience, don't try this at home.
@ -295,18 +314,19 @@ TESTS_BIN += fdtput
TESTS_BIN += fdtget
TESTS_BIN += fdtdump
TESTS_BIN += fdtoverlay
ifneq ($(MAKECMDGOALS),libfdt)
include tests/Makefile.tests
ifeq ($(NO_PYTHON),0)
TESTS_PYLIBFDT += maybe_pylibfdt
endif
include tests/Makefile.tests
#
# Clean rules
#
STD_CLEANFILES = *~ *.o *.$(SHAREDLIB_EXT) *.d *.a *.i *.s core a.out vgcore.* \
*.tab.[ch] *.lex.c *.output
clean: libfdt_clean tests_clean
clean: libfdt_clean pylibfdt_clean tests_clean
@$(VECHO) CLEAN
rm -f $(STD_CLEANFILES)
rm -f $(VERSION_FILE)
@ -326,7 +346,7 @@ clean: libfdt_clean tests_clean
%.o: %.S
@$(VECHO) AS $@
$(CC) $(CPPFLAGS) $(AFLAGS) -o $@ -c $<
$(CC) $(CPPFLAGS) $(AFLAGS) -D__ASSEMBLY__ -o $@ -c $<
%.d: %.c
@$(VECHO) DEP $<
@ -352,12 +372,8 @@ clean: libfdt_clean tests_clean
@$(VECHO) LEX $@
$(LEX) -o$@ $<
%.tab.c %.tab.h: %.y
%.tab.c %.tab.h %.output: %.y
@$(VECHO) BISON $@
$(BISON) -b $(basename $(basename $@)) -d $<
FORCE:
ifeq ($(MAKE_RESTARTS),10)
$(error "Make re-executed itself $(MAKE_RESTARTS) times. Infinite recursion?")
endif

91
README Normal file
View file

@ -0,0 +1,91 @@
The source tree contains the Device Tree Compiler (dtc) toolchain for
working with device tree source and binary files and also libfdt, a
utility library for reading and manipulating the binary format.
DTC and LIBFDT are maintained by:
David Gibson <david@gibson.dropbear.id.au>
Jon Loeliger <jdl@jdl.com>
Python library
--------------
A Python library is also available. To build this you will need to install
swig and Python development files. On Debian distributions:
sudo apt-get install swig python3-dev
The library provides an Fdt class which you can use like this:
$ PYTHONPATH=../pylibfdt python3
>>> import libfdt
>>> fdt = libfdt.Fdt(open('test_tree1.dtb', mode='rb').read())
>>> node = fdt.path_offset('/subnode@1')
>>> print(node)
124
>>> prop_offset = fdt.first_property_offset(node)
>>> prop = fdt.get_property_by_offset(prop_offset)
>>> print('%s=%s' % (prop.name, prop.as_str()))
compatible=subnode1
>>> node2 = fdt.path_offset('/')
>>> print(fdt.getprop(node2, 'compatible').as_str())
test_tree1
You will find tests in tests/pylibfdt_tests.py showing how to use each
method. Help is available using the Python help command, e.g.:
$ cd pylibfdt
$ python3 -c "import libfdt; help(libfdt)"
If you add new features, please check code coverage:
$ sudo apt-get install python3-coverage
$ cd tests
# It's just 'coverage' on most other distributions
$ python3-coverage run pylibfdt_tests.py
$ python3-coverage html
# Open 'htmlcov/index.html' in your browser
To install the library via the normal setup.py method, use:
./pylibfdt/setup.py install [--prefix=/path/to/install_dir]
If --prefix is not provided, the default prefix is used, typically '/usr'
or '/usr/local'. See Python's distutils documentation for details. You can
also install via the Makefile if you like, but the above is more common.
To install both libfdt and pylibfdt you can use:
make install [SETUP_PREFIX=/path/to/install_dir] \
[PREFIX=/path/to/install_dir]
To disable building the python library, even if swig and Python are available,
use:
make NO_PYTHON=1
More work remains to support all of libfdt, including access to numeric
values.
Tests
-----
Test files are kept in the tests/ directory. Use 'make check' to build and run
all tests.
If you want to adjust a test file, be aware that tree_tree1.dts is compiled
and checked against a binary tree from assembler macros in trees.S. So
if you change that file you must change tree.S also.
Mailing list
------------
The following list is for discussion about dtc and libfdt implementation
mailto:devicetree-compiler@vger.kernel.org
Core device tree bindings are discussed on the devicetree-spec list:
mailto:devicetree-spec@vger.kernel.org

View file

@ -28,7 +28,7 @@ tools. Allowing libfdt to be used under the terms of the BSD license
makes that it easier for vendors or authors of such software to do so.
This does mean that libfdt code could be "stolen" - say, included in a
proprietary firmware and extended without contributing those extensions
proprietary fimware and extended without contributing those extensions
back to the libfdt mainline. While I hope that doesn't happen, I
believe the goal of allowing libfdt to be widely used is more
important than avoiding that. libfdt is quite small, and hardly

100
README.md
View file

@ -1,100 +0,0 @@
# Device Tree Compiler and libfdt
The source tree contains the Device Tree Compiler (dtc) toolchain for
working with device tree source and binary files and also libfdt, a
utility library for reading and manipulating the binary format.
dtc and libfdt are maintained by:
* [David Gibson `<david@gibson.dropbear.id.au>`](mailto:david@gibson.dropbear.id.au)
## Python library
A Python library wrapping libfdt is also available. To build this you
will need to install `swig` and Python development files. On Debian
distributions:
```
$ sudo apt-get install swig python3-dev
```
The library provides an `Fdt` class which you can use like this:
```
$ PYTHONPATH=../pylibfdt python3
>>> import libfdt
>>> fdt = libfdt.Fdt(open('test_tree1.dtb', mode='rb').read())
>>> node = fdt.path_offset('/subnode@1')
>>> print(node)
124
>>> prop_offset = fdt.first_property_offset(node)
>>> prop = fdt.get_property_by_offset(prop_offset)
>>> print('%s=%s' % (prop.name, prop.as_str()))
compatible=subnode1
>>> node2 = fdt.path_offset('/')
>>> print(fdt.getprop(node2, 'compatible').as_str())
test_tree1
```
You will find tests in `tests/pylibfdt_tests.py` showing how to use each
method. Help is available using the Python help command, e.g.:
```
$ cd pylibfdt
$ python3 -c "import libfdt; help(libfdt)"
```
If you add new features, please check code coverage:
```
$ sudo apt-get install python3-coverage
$ cd tests
# It's just 'coverage' on most other distributions
$ python3-coverage run pylibfdt_tests.py
$ python3-coverage html
# Open 'htmlcov/index.html' in your browser
```
The library can be installed with pip from a local source tree:
```
$ pip install . [--user|--prefix=/path/to/install_dir]
```
Or directly from a remote git repo:
```
$ pip install git+git://git.kernel.org/pub/scm/utils/dtc/dtc.git@main
```
The install depends on libfdt shared library being installed on the
host system first. Generally, using `--user` or `--prefix` is not
necessary and pip will use the default location for the Python
installation which varies if the user is root or not.
You can also install everything via make if you like, but pip is
recommended.
To install both libfdt and pylibfdt you can use:
```
$ make install [PREFIX=/path/to/install_dir]
```
To disable building the python library, even if swig and Python are available,
use:
```
$ make NO_PYTHON=1
```
More work remains to support all of libfdt, including access to numeric
values.
## Mailing lists
* The [devicetree-compiler](mailto:devicetree-compiler@vger.kernel.org)
list is for discussion about dtc and libfdt implementation.
* Core device tree bindings are discussed on the
[devicetree-spec](mailto:devicetree-spec@vger.kernel.org) list.

View file

@ -1 +0,0 @@
1.7.2

366
checks.c
View file

@ -31,7 +31,7 @@ typedef void (*check_fn)(struct check *c, struct dt_info *dti, struct node *node
struct check {
const char *name;
check_fn fn;
const void *data;
void *data;
bool warn, error;
enum checkstatus status;
bool inprogress;
@ -114,7 +114,6 @@ static inline void PRINTF(5, 6) check_msg(struct check *c, struct dt_info *dti,
}
fputs(str, stderr);
free(str);
}
#define FAIL(c, dti, node, ...) \
@ -144,14 +143,6 @@ static void check_nodes_props(struct check *c, struct dt_info *dti, struct node
check_nodes_props(c, dti, child);
}
static bool is_multiple_of(int multiple, int divisor)
{
if (divisor == 0)
return multiple == 0;
else
return (multiple % divisor) == 0;
}
static bool run_check(struct check *c, struct dt_info *dti)
{
struct node *dt = dti->dt;
@ -208,7 +199,7 @@ static void check_is_string(struct check *c, struct dt_info *dti,
struct node *node)
{
struct property *prop;
const char *propname = c->data;
char *propname = c->data;
prop = get_property(node, propname);
if (!prop)
@ -227,7 +218,7 @@ static void check_is_string_list(struct check *c, struct dt_info *dti,
{
int rem, l;
struct property *prop;
const char *propname = c->data;
char *propname = c->data;
char *str;
prop = get_property(node, propname);
@ -255,7 +246,7 @@ static void check_is_cell(struct check *c, struct dt_info *dti,
struct node *node)
{
struct property *prop;
const char *propname = c->data;
char *propname = c->data;
prop = get_property(node, propname);
if (!prop)
@ -306,20 +297,19 @@ ERROR(duplicate_property_names, check_duplicate_property_names, NULL);
#define LOWERCASE "abcdefghijklmnopqrstuvwxyz"
#define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
#define DIGITS "0123456789"
#define NODECHARS LOWERCASE UPPERCASE DIGITS ",._+-@"
#define PROPCHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-"
#define PROPNODECHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-"
#define PROPNODECHARSSTRICT LOWERCASE UPPERCASE DIGITS ",-"
static void check_node_name_chars(struct check *c, struct dt_info *dti,
struct node *node)
{
size_t n = strspn(node->name, c->data);
int n = strspn(node->name, c->data);
if (n < strlen(node->name))
FAIL(c, dti, node, "Bad character '%c' in node name",
node->name[n]);
}
ERROR(node_name_chars, check_node_name_chars, NODECHARS);
ERROR(node_name_chars, check_node_name_chars, PROPNODECHARS "@");
static void check_node_name_chars_strict(struct check *c, struct dt_info *dti,
struct node *node)
@ -340,20 +330,6 @@ static void check_node_name_format(struct check *c, struct dt_info *dti,
}
ERROR(node_name_format, check_node_name_format, NULL, &node_name_chars);
static void check_node_name_vs_property_name(struct check *c,
struct dt_info *dti,
struct node *node)
{
if (!node->parent)
return;
if (get_property(node->parent, node->name)) {
FAIL(c, dti, node, "node name and property name conflict");
}
}
WARNING(node_name_vs_property_name, check_node_name_vs_property_name,
NULL, &node_name_chars);
static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti,
struct node *node)
{
@ -376,7 +352,7 @@ static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti,
FAIL(c, dti, node, "node has a reg or ranges property, but no unit name");
} else {
if (unitname[0])
FAIL(c, dti, node, "node has a unit name, but no reg or ranges property");
FAIL(c, dti, node, "node has a unit name, but no reg property");
}
}
WARNING(unit_address_vs_reg, check_unit_address_vs_reg, NULL);
@ -387,14 +363,14 @@ static void check_property_name_chars(struct check *c, struct dt_info *dti,
struct property *prop;
for_each_property(node, prop) {
size_t n = strspn(prop->name, c->data);
int n = strspn(prop->name, c->data);
if (n < strlen(prop->name))
FAIL_PROP(c, dti, node, prop, "Bad character '%c' in property name",
prop->name[n]);
}
}
ERROR(property_name_chars, check_property_name_chars, PROPCHARS);
ERROR(property_name_chars, check_property_name_chars, PROPNODECHARS);
static void check_property_name_chars_strict(struct check *c,
struct dt_info *dti,
@ -404,7 +380,7 @@ static void check_property_name_chars_strict(struct check *c,
for_each_property(node, prop) {
const char *name = prop->name;
size_t n = strspn(name, c->data);
int n = strspn(name, c->data);
if (n == strlen(prop->name))
continue;
@ -521,7 +497,7 @@ static cell_t check_phandle_prop(struct check *c, struct dt_info *dti,
phandle = propval_cell(prop);
if (!phandle_is_valid(phandle)) {
if ((phandle == 0) || (phandle == -1)) {
FAIL_PROP(c, dti, node, prop, "bad value (0x%x) in %s property",
phandle, prop->name);
return 0;
@ -580,7 +556,7 @@ static void check_name_properties(struct check *c, struct dt_info *dti,
if (!prop)
return; /* No name property, that's fine */
if ((prop->val.len != node->basenamelen + 1U)
if ((prop->val.len != node->basenamelen+1)
|| (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) {
FAIL(c, dti, node, "\"name\" property is incorrect (\"%s\" instead"
" of base node name)", prop->val.val);
@ -681,6 +657,7 @@ ERROR(omit_unused_nodes, fixup_omit_unused_nodes, NULL, &phandle_references, &pa
*/
WARNING_IF_NOT_CELL(address_cells_is_cell, "#address-cells");
WARNING_IF_NOT_CELL(size_cells_is_cell, "#size-cells");
WARNING_IF_NOT_CELL(interrupt_cells_is_cell, "#interrupt-cells");
WARNING_IF_NOT_STRING(device_type_is_string, "device_type");
WARNING_IF_NOT_STRING(model_is_string, "model");
@ -695,7 +672,8 @@ static void check_names_is_string_list(struct check *c, struct dt_info *dti,
struct property *prop;
for_each_property(node, prop) {
if (!strends(prop->name, "-names"))
const char *s = strrchr(prop->name, '-');
if (!s || !streq(s, "-names"))
continue;
c->data = prop->name;
@ -718,14 +696,11 @@ static void check_alias_paths(struct check *c, struct dt_info *dti,
continue;
}
/* This check does not work for overlays with external paths */
if (!(dti->dtsflags & DTSF_PLUGIN) &&
(!prop->val.val || !get_node_by_path(dti->dt, prop->val.val))) {
if (!prop->val.val || !get_node_by_path(dti->dt, prop->val.val)) {
FAIL_PROP(c, dti, node, prop, "aliases property is not a valid node (%s)",
prop->val.val);
continue;
}
if (strspn(prop->name, LOWERCASE DIGITS "-") != strlen(prop->name))
FAIL(c, dti, node, "aliases property name must include only lowercase and '-'");
}
@ -778,7 +753,7 @@ static void check_reg_format(struct check *c, struct dt_info *dti,
size_cells = node_size_cells(node->parent);
entrylen = (addr_cells + size_cells) * sizeof(cell_t);
if (!is_multiple_of(prop->val.len, entrylen))
if (!entrylen || (prop->val.len % entrylen) != 0)
FAIL_PROP(c, dti, node, prop, "property has invalid length (%d bytes) "
"(#address-cells == %d, #size-cells == %d)",
prop->val.len, addr_cells, size_cells);
@ -819,7 +794,7 @@ static void check_ranges_format(struct check *c, struct dt_info *dti,
"#size-cells (%d) differs from %s (%d)",
ranges, c_size_cells, node->parent->fullpath,
p_size_cells);
} else if (!is_multiple_of(prop->val.len, entrylen)) {
} else if ((prop->val.len % entrylen) != 0) {
FAIL_PROP(c, dti, node, prop, "\"%s\" property has invalid length (%d bytes) "
"(parent #address-cells == %d, child #address-cells == %d, "
"#size-cells == %d)", ranges, prop->val.len,
@ -896,7 +871,7 @@ static void check_pci_device_bus_num(struct check *c, struct dt_info *dti, struc
} else {
cells = (cell_t *)prop->val.val;
min_bus = fdt32_to_cpu(cells[0]);
max_bus = fdt32_to_cpu(cells[1]);
max_bus = fdt32_to_cpu(cells[0]);
}
if ((bus_num < min_bus) || (bus_num > max_bus))
FAIL_PROP(c, dti, node, prop, "PCI bus number %d out of range, expected (%d - %d)",
@ -916,8 +891,10 @@ static void check_pci_device_reg(struct check *c, struct dt_info *dti, struct no
return;
prop = get_property(node, "reg");
if (!prop)
if (!prop) {
FAIL(c, dti, node, "missing PCI reg property");
return;
}
cells = (cell_t *)prop->val.val;
if (cells[1] || cells[2])
@ -1027,7 +1004,7 @@ static void check_i2c_bus_bridge(struct check *c, struct dt_info *dti, struct no
} else if (strprefixeq(node->name, node->basenamelen, "i2c")) {
struct node *child;
for_each_child(node, child) {
if (strprefixeq(child->name, child->basenamelen, "i2c-bus"))
if (strprefixeq(child->name, node->basenamelen, "i2c-bus"))
return;
}
node->bus = &i2c_bus;
@ -1045,9 +1022,6 @@ static void check_i2c_bus_bridge(struct check *c, struct dt_info *dti, struct no
}
WARNING(i2c_bus_bridge, check_i2c_bus_bridge, NULL, &addr_size_cells);
#define I2C_OWN_SLAVE_ADDRESS (1U << 30)
#define I2C_TEN_BIT_ADDRESS (1U << 31)
static void check_i2c_bus_reg(struct check *c, struct dt_info *dti, struct node *node)
{
struct property *prop;
@ -1070,8 +1044,6 @@ static void check_i2c_bus_reg(struct check *c, struct dt_info *dti, struct node
}
reg = fdt32_to_cpu(*cells);
/* Ignore I2C_OWN_SLAVE_ADDRESS */
reg &= ~I2C_OWN_SLAVE_ADDRESS;
snprintf(unit_addr, sizeof(unit_addr), "%x", reg);
if (!streq(unitname, unit_addr))
FAIL(c, dti, node, "I2C bus unit address format error, expected \"%s\"",
@ -1079,16 +1051,10 @@ static void check_i2c_bus_reg(struct check *c, struct dt_info *dti, struct node
for (len = prop->val.len; len > 0; len -= 4) {
reg = fdt32_to_cpu(*(cells++));
/* Ignore I2C_OWN_SLAVE_ADDRESS */
reg &= ~I2C_OWN_SLAVE_ADDRESS;
if (reg > 0x3ff)
FAIL_PROP(c, dti, node, prop, "I2C address must be less than 10-bits, got \"0x%x\"",
reg);
if (reg & I2C_TEN_BIT_ADDRESS) {
if ((reg & ~I2C_TEN_BIT_ADDRESS) > 0x3ff)
FAIL_PROP(c, dti, node, prop, "I2C address must be less than 10-bits, got \"0x%x\"",
reg);
} else if (reg > 0x7f)
FAIL_PROP(c, dti, node, prop, "I2C address must be less than 7-bits, got \"0x%x\". Set I2C_TEN_BIT_ADDRESS for 10 bit addresses or fix the property",
reg);
}
}
WARNING(i2c_bus_reg, check_i2c_bus_reg, NULL, &reg_format, &i2c_bus_bridge);
@ -1113,7 +1079,7 @@ static void check_spi_bus_bridge(struct check *c, struct dt_info *dti, struct no
for_each_child(node, child) {
struct property *prop;
for_each_property(child, prop) {
if (strstarts(prop->name, "spi-")) {
if (strprefixeq(prop->name, 4, "spi-")) {
node->bus = &spi_bus;
break;
}
@ -1185,7 +1151,7 @@ static void check_unit_address_format(struct check *c, struct dt_info *dti,
/* skip over 0x for next test */
unitname += 2;
}
if (unitname[0] == '0' && isxdigit((unsigned char)unitname[1]))
if (unitname[0] == '0' && isxdigit(unitname[1]))
FAIL(c, dti, node, "unit name should not have leading 0s");
}
WARNING(unit_address_format, check_unit_address_format, NULL,
@ -1220,27 +1186,24 @@ WARNING(avoid_default_addr_size, check_avoid_default_addr_size, NULL,
static void check_avoid_unnecessary_addr_size(struct check *c, struct dt_info *dti,
struct node *node)
{
struct property *prop;
struct node *child;
bool has_reg = false;
if (!node->parent || node->addr_cells < 0 || node->size_cells < 0)
return;
if (get_property(node, "ranges") || get_property(node, "dma-ranges") || !node->children)
if (get_property(node, "ranges") || !node->children)
return;
for_each_child(node, child) {
/*
* Even if the child devices' address space is not mapped into
* the parent bus (no 'ranges' property on node), children can
* still have registers on a local bus, or map local addresses
* to another subordinate address space. The properties on the
* child nodes then make #address-cells/#size-cells necessary:
*/
if (get_property(child, "reg") || get_property(child, "ranges"))
return;
prop = get_property(child, "reg");
if (prop)
has_reg = true;
}
FAIL(c, dti, node, "unnecessary #address-cells/#size-cells without \"ranges\", \"dma-ranges\" or child \"reg\" or \"ranges\" property");
if (!has_reg)
FAIL(c, dti, node, "unnecessary #address-cells/#size-cells without \"ranges\" or child \"reg\" property");
}
WARNING(avoid_unnecessary_addr_size, check_avoid_unnecessary_addr_size, NULL, &avoid_default_addr_size);
@ -1390,15 +1353,15 @@ struct provider {
};
static void check_property_phandle_args(struct check *c,
struct dt_info *dti,
struct node *node,
struct property *prop,
const struct provider *provider)
struct dt_info *dti,
struct node *node,
struct property *prop,
const struct provider *provider)
{
struct node *root = dti->dt;
unsigned int cell, cellsize = 0;
int cell, cellsize = 0;
if (!is_multiple_of(prop->val.len, sizeof(cell_t))) {
if (prop->val.len % sizeof(cell_t)) {
FAIL_PROP(c, dti, node, prop,
"property size (%d) is invalid, expected multiple of %zu",
prop->val.len, sizeof(cell_t));
@ -1408,15 +1371,14 @@ static void check_property_phandle_args(struct check *c,
for (cell = 0; cell < prop->val.len / sizeof(cell_t); cell += cellsize + 1) {
struct node *provider_node;
struct property *cellprop;
cell_t phandle;
unsigned int expected;
int phandle;
phandle = propval_cell_n(prop, cell);
/*
* Some bindings use a cell value 0 or -1 to skip over optional
* entries when each index position has a specific definition.
*/
if (!phandle_is_valid(phandle)) {
if (phandle == 0 || phandle == -1) {
/* Give up if this is an overlay with external references */
if (dti->dtsflags & DTSF_PLUGIN)
break;
@ -1459,12 +1421,10 @@ static void check_property_phandle_args(struct check *c,
break;
}
expected = (cell + cellsize + 1) * sizeof(cell_t);
if ((expected <= cell) || prop->val.len < expected) {
if (prop->val.len < ((cell + cellsize + 1) * sizeof(cell_t))) {
FAIL_PROP(c, dti, node, prop,
"property size (%d) too small for cell size %u",
"property size (%d) too small for cell size %d",
prop->val.len, cellsize);
break;
}
}
}
@ -1473,7 +1433,7 @@ static void check_provider_cells_property(struct check *c,
struct dt_info *dti,
struct node *node)
{
const struct provider *provider = c->data;
struct provider *provider = c->data;
struct property *prop;
prop = get_property(node, provider->prop_name);
@ -1484,8 +1444,7 @@ static void check_provider_cells_property(struct check *c,
}
#define WARNING_PROPERTY_PHANDLE_CELLS(nm, propname, cells_name, ...) \
static struct provider nm##_provider = { (propname), (cells_name), __VA_ARGS__ }; \
WARNING_IF_NOT_CELL(nm##_is_cell, cells_name); \
WARNING(nm##_property, check_provider_cells_property, &nm##_provider, &nm##_is_cell, &phandle_references);
WARNING(nm##_property, check_provider_cells_property, &nm##_provider, &phandle_references);
WARNING_PROPERTY_PHANDLE_CELLS(clocks, "clocks", "#clock-cells");
WARNING_PROPERTY_PHANDLE_CELLS(cooling_device, "cooling-device", "#cooling-cells");
@ -1506,17 +1465,24 @@ WARNING_PROPERTY_PHANDLE_CELLS(thermal_sensors, "thermal-sensors", "#thermal-sen
static bool prop_is_gpio(struct property *prop)
{
char *str;
/*
* *-gpios and *-gpio can appear in property names,
* so skip over any false matches (only one known ATM)
*/
if (strends(prop->name, ",nr-gpios"))
if (strstr(prop->name, "nr-gpio"))
return false;
return strends(prop->name, "-gpios") ||
streq(prop->name, "gpios") ||
strends(prop->name, "-gpio") ||
streq(prop->name, "gpio");
str = strrchr(prop->name, '-');
if (str)
str++;
else
str = prop->name;
if (!(streq(str, "gpios") || streq(str, "gpio")))
return false;
return true;
}
static void check_gpios_property(struct check *c,
@ -1551,10 +1517,13 @@ static void check_deprecated_gpio_property(struct check *c,
struct property *prop;
for_each_property(node, prop) {
char *str;
if (!prop_is_gpio(prop))
continue;
if (!strends(prop->name, "gpio"))
str = strstr(prop->name, "gpio");
if (!streq(str, "gpio"))
continue;
FAIL_PROP(c, dti, node, prop,
@ -1578,121 +1547,6 @@ static bool node_is_interrupt_provider(struct node *node)
return false;
}
static void check_interrupt_provider(struct check *c,
struct dt_info *dti,
struct node *node)
{
struct property *prop;
bool irq_provider = node_is_interrupt_provider(node);
prop = get_property(node, "#interrupt-cells");
if (irq_provider && !prop) {
FAIL(c, dti, node,
"Missing '#interrupt-cells' in interrupt provider");
return;
}
if (!irq_provider && prop) {
FAIL(c, dti, node,
"'#interrupt-cells' found, but node is not an interrupt provider");
return;
}
}
WARNING(interrupt_provider, check_interrupt_provider, NULL, &interrupts_extended_is_cell);
static void check_interrupt_map(struct check *c,
struct dt_info *dti,
struct node *node)
{
struct node *root = dti->dt;
struct property *prop, *irq_map_prop;
size_t cellsize, cell, map_cells;
irq_map_prop = get_property(node, "interrupt-map");
if (!irq_map_prop)
return;
if (node->addr_cells < 0) {
FAIL(c, dti, node,
"Missing '#address-cells' in interrupt-map provider");
return;
}
cellsize = node_addr_cells(node);
cellsize += propval_cell(get_property(node, "#interrupt-cells"));
prop = get_property(node, "interrupt-map-mask");
if (prop && (prop->val.len != (cellsize * sizeof(cell_t))))
FAIL_PROP(c, dti, node, prop,
"property size (%d) is invalid, expected %zu",
prop->val.len, cellsize * sizeof(cell_t));
if (!is_multiple_of(irq_map_prop->val.len, sizeof(cell_t))) {
FAIL_PROP(c, dti, node, irq_map_prop,
"property size (%d) is invalid, expected multiple of %zu",
irq_map_prop->val.len, sizeof(cell_t));
return;
}
map_cells = irq_map_prop->val.len / sizeof(cell_t);
for (cell = 0; cell < map_cells; ) {
struct node *provider_node;
struct property *cellprop;
int phandle;
size_t parent_cellsize;
if ((cell + cellsize) >= map_cells) {
FAIL_PROP(c, dti, node, irq_map_prop,
"property size (%d) too small, expected > %zu",
irq_map_prop->val.len, (cell + cellsize) * sizeof(cell_t));
break;
}
cell += cellsize;
phandle = propval_cell_n(irq_map_prop, cell);
if (!phandle_is_valid(phandle)) {
/* Give up if this is an overlay with external references */
if (!(dti->dtsflags & DTSF_PLUGIN))
FAIL_PROP(c, dti, node, irq_map_prop,
"Cell %zu is not a phandle(%d)",
cell, phandle);
break;
}
provider_node = get_node_by_phandle(root, phandle);
if (!provider_node) {
FAIL_PROP(c, dti, node, irq_map_prop,
"Could not get phandle(%d) node for (cell %zu)",
phandle, cell);
break;
}
cellprop = get_property(provider_node, "#interrupt-cells");
if (cellprop) {
parent_cellsize = propval_cell(cellprop);
} else {
FAIL(c, dti, node, "Missing property '#interrupt-cells' in node %s or bad phandle (referred from interrupt-map[%zu])",
provider_node->fullpath, cell);
break;
}
cellprop = get_property(provider_node, "#address-cells");
if (cellprop)
parent_cellsize += propval_cell(cellprop);
else
FAIL_PROP(c, dti, node, irq_map_prop,
"Missing property '#address-cells' in node %s, using 0 as fallback",
provider_node->fullpath);
cell += 1 + parent_cellsize;
if (cell > map_cells)
FAIL_PROP(c, dti, node, irq_map_prop,
"property size (%d) mismatch, expected %zu",
irq_map_prop->val.len, cell * sizeof(cell_t));
}
}
WARNING(interrupt_map, check_interrupt_map, NULL, &phandle_references, &addr_size_cells, &interrupt_provider);
static void check_interrupts_property(struct check *c,
struct dt_info *dti,
struct node *node)
@ -1700,13 +1554,13 @@ static void check_interrupts_property(struct check *c,
struct node *root = dti->dt;
struct node *irq_node = NULL, *parent = node;
struct property *irq_prop, *prop = NULL;
cell_t irq_cells, phandle;
int irq_cells, phandle;
irq_prop = get_property(node, "interrupts");
if (!irq_prop)
return;
if (!is_multiple_of(irq_prop->val.len, sizeof(cell_t)))
if (irq_prop->val.len % sizeof(cell_t))
FAIL_PROP(c, dti, node, irq_prop, "size (%d) is invalid, expected multiple of %zu",
irq_prop->val.len, sizeof(cell_t));
@ -1719,7 +1573,7 @@ static void check_interrupts_property(struct check *c,
prop = get_property(parent, "interrupt-parent");
if (prop) {
phandle = propval_cell(prop);
if (!phandle_is_valid(phandle)) {
if ((phandle == 0) || (phandle == -1)) {
/* Give up if this is an overlay with
* external references */
if (dti->dtsflags & DTSF_PLUGIN)
@ -1750,12 +1604,12 @@ static void check_interrupts_property(struct check *c,
prop = get_property(irq_node, "#interrupt-cells");
if (!prop) {
/* We warn about that already in another test. */
FAIL(c, dti, irq_node, "Missing #interrupt-cells in interrupt-parent");
return;
}
irq_cells = propval_cell(prop);
if (!is_multiple_of(irq_prop->val.len, irq_cells * sizeof(cell_t))) {
if (irq_prop->val.len % (irq_cells * sizeof(cell_t))) {
FAIL_PROP(c, dti, node, prop,
"size is (%d), expected multiple of %d",
irq_prop->val.len, (int)(irq_cells * sizeof(cell_t)));
@ -1781,11 +1635,6 @@ static void check_graph_nodes(struct check *c, struct dt_info *dti,
get_property(child, "remote-endpoint")))
continue;
/* The root node cannot be a port */
if (!node->parent) {
FAIL(c, dti, node, "root node contains endpoint node '%s', potentially misplaced remote-endpoint property", child->name);
continue;
}
node->bus = &graph_port_bus;
/* The parent of 'port' nodes can be either 'ports' or a device */
@ -1799,6 +1648,31 @@ static void check_graph_nodes(struct check *c, struct dt_info *dti,
}
WARNING(graph_nodes, check_graph_nodes, NULL);
static void check_graph_child_address(struct check *c, struct dt_info *dti,
struct node *node)
{
int cnt = 0;
struct node *child;
if (node->bus != &graph_ports_bus && node->bus != &graph_port_bus)
return;
for_each_child(node, child) {
struct property *prop = get_property(child, "reg");
/* No error if we have any non-zero unit address */
if (prop && propval_cell(prop) != 0)
return;
cnt++;
}
if (cnt == 1 && node->addr_cells != -1)
FAIL(c, dti, node, "graph node has single child node '%s', #address-cells/#size-cells are not necessary",
node->children->name);
}
WARNING(graph_child_address, check_graph_child_address, NULL, &graph_nodes);
static void check_graph_reg(struct check *c, struct dt_info *dti,
struct node *node)
{
@ -1836,21 +1710,17 @@ static void check_graph_port(struct check *c, struct dt_info *dti,
if (node->bus != &graph_port_bus)
return;
check_graph_reg(c, dti, node);
/* skip checks below for overlays */
if (dti->dtsflags & DTSF_PLUGIN)
return;
if (!strprefixeq(node->name, node->basenamelen, "port"))
FAIL(c, dti, node, "graph port node name should be 'port'");
check_graph_reg(c, dti, node);
}
WARNING(graph_port, check_graph_port, NULL, &graph_nodes);
static struct node *get_remote_endpoint(struct check *c, struct dt_info *dti,
struct node *endpoint)
{
cell_t phandle;
int phandle;
struct node *node;
struct property *prop;
@ -1860,7 +1730,7 @@ static struct node *get_remote_endpoint(struct check *c, struct dt_info *dti,
phandle = propval_cell(prop);
/* Give up if this is an overlay with external references */
if (!phandle_is_valid(phandle))
if (phandle == 0 || phandle == -1)
return NULL;
node = get_node_by_phandle(dti->dt, phandle);
@ -1878,15 +1748,11 @@ static void check_graph_endpoint(struct check *c, struct dt_info *dti,
if (!node->parent || node->parent->bus != &graph_port_bus)
return;
check_graph_reg(c, dti, node);
/* skip checks below for overlays */
if (dti->dtsflags & DTSF_PLUGIN)
return;
if (!strprefixeq(node->name, node->basenamelen, "endpoint"))
FAIL(c, dti, node, "graph endpoint node name should be 'endpoint'");
check_graph_reg(c, dti, node);
remote_node = get_remote_endpoint(c, dti, node);
if (!remote_node)
return;
@ -1900,7 +1766,7 @@ WARNING(graph_endpoint, check_graph_endpoint, NULL, &graph_nodes);
static struct check *check_table[] = {
&duplicate_node_names, &duplicate_property_names,
&node_name_chars, &node_name_format, &property_name_chars,
&name_is_string, &name_properties, &node_name_vs_property_name,
&name_is_string, &name_properties,
&duplicate_label,
@ -1908,7 +1774,7 @@ static struct check *check_table[] = {
&phandle_references, &path_references,
&omit_unused_nodes,
&address_cells_is_cell, &size_cells_is_cell,
&address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell,
&device_type_is_string, &model_is_string, &status_is_string,
&label_is_string,
@ -1943,47 +1809,29 @@ static struct check *check_table[] = {
&chosen_node_is_root, &chosen_node_bootargs, &chosen_node_stdout_path,
&clocks_property,
&clocks_is_cell,
&cooling_device_property,
&cooling_device_is_cell,
&dmas_property,
&dmas_is_cell,
&hwlocks_property,
&hwlocks_is_cell,
&interrupts_extended_property,
&interrupts_extended_is_cell,
&io_channels_property,
&io_channels_is_cell,
&iommus_property,
&iommus_is_cell,
&mboxes_property,
&mboxes_is_cell,
&msi_parent_property,
&msi_parent_is_cell,
&mux_controls_property,
&mux_controls_is_cell,
&phys_property,
&phys_is_cell,
&power_domains_property,
&power_domains_is_cell,
&pwms_property,
&pwms_is_cell,
&resets_property,
&resets_is_cell,
&sound_dai_property,
&sound_dai_is_cell,
&thermal_sensors_property,
&thermal_sensors_is_cell,
&deprecated_gpio_property,
&gpios_property,
&interrupts_property,
&interrupt_provider,
&interrupt_map,
&alias_paths,
&graph_nodes, &graph_port, &graph_endpoint,
&graph_nodes, &graph_child_address, &graph_port, &graph_endpoint,
&always_fail,
};
@ -2003,7 +1851,7 @@ static void enable_warning_error(struct check *c, bool warn, bool error)
static void disable_warning_error(struct check *c, bool warn, bool error)
{
unsigned int i;
int i;
/* Lowering level, also lower it for things this is the prereq
* for */
@ -2024,7 +1872,7 @@ static void disable_warning_error(struct check *c, bool warn, bool error)
void parse_checks_option(bool warn, bool error, const char *arg)
{
unsigned int i;
int i;
const char *name = arg;
bool enable = true;
@ -2051,7 +1899,7 @@ void parse_checks_option(bool warn, bool error, const char *arg)
void process_checks(bool force, struct dt_info *dti)
{
unsigned int i;
int i;
int error = 0;
for (i = 0; i < ARRAY_SIZE(check_table); i++) {

View file

@ -94,7 +94,7 @@ static const struct {
<INITIAL>[0-9a-fA-F]+ {
unsigned long long val;
int obase = 16, width = 0;
unsigned int i;
int i;
val = strtoull(yytext, NULL, cbase);

53
data.c
View file

@ -21,10 +21,10 @@ void data_free(struct data d)
free(d.val);
}
struct data data_grow_for(struct data d, unsigned int xlen)
struct data data_grow_for(struct data d, int xlen)
{
struct data nd;
unsigned int newsize;
int newsize;
if (xlen == 0)
return d;
@ -84,7 +84,7 @@ struct data data_copy_file(FILE *f, size_t maxlen)
while (!feof(f) && (d.len < maxlen)) {
size_t chunksize, ret;
if (maxlen == (size_t)-1)
if (maxlen == -1)
chunksize = 4096;
else
chunksize = maxlen - d.len;
@ -228,7 +228,11 @@ struct data data_add_marker(struct data d, enum markertype type, char *ref)
{
struct marker *m;
m = alloc_marker(d.len, type, ref);
m = xmalloc(sizeof(*m));
m->offset = d.len;
m->type = type;
m->ref = ref;
m->next = NULL;
return data_append_markers(d, m);
}
@ -250,44 +254,3 @@ bool data_is_one_string(struct data d)
return true;
}
struct data data_insert_data(struct data d, struct marker *m, struct data old)
{
unsigned int offset = m->offset;
struct marker *next = m->next;
struct marker *marker;
struct data new_data;
char *ref;
new_data = data_insert_at_marker(d, m, old.val, old.len);
/* Copy all markers from old value */
marker = old.markers;
for_each_marker(marker) {
ref = NULL;
if (marker->ref)
ref = xstrdup(marker->ref);
m->next = alloc_marker(marker->offset + offset, marker->type,
ref);
m = m->next;
}
m->next = next;
return new_data;
}
struct marker *alloc_marker(unsigned int offset, enum markertype type,
char *ref)
{
struct marker *m;
m = xmalloc(sizeof(*m));
m->offset = offset;
m->type = type;
m->ref = ref;
m->next = NULL;
return m;
}

View file

@ -57,7 +57,7 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
push_input_file(name);
}
<*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)* {
<*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)? {
char *line, *fnstart, *fnend;
struct data fn;
/* skip text before line # */
@ -151,21 +151,6 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
return DT_LABEL;
}
<V1>{LABEL} {
/* Missed includes or macro definitions while
* preprocessing can lead to unexpected identifiers in
* the input. Report a slightly more informative error
* in this case */
lexical_error("Unexpected '%s'", yytext);
/* Treat it as a literal which often generates further
* useful error messages */
yylval.integer = 0;
return DT_LITERAL;
}
<V1>([0-9]+|0[xX][0-9a-fA-F]+)(U|L|UL|LL|ULL)? {
char *e;
DPRINT("Integer Literal: '%s'\n", yytext);
@ -215,7 +200,7 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
return DT_LABEL_REF;
}
<*>"&{"{PATHCHAR}*\} { /* new-style path reference */
<*>"&{/"{PATHCHAR}*\} { /* new-style path reference */
yytext[yyleng-1] = '\0';
DPRINT("Ref: %s\n", yytext+2);
yylval.labelref = xstrdup(yytext+2);

View file

@ -23,12 +23,6 @@ extern void yyerror(char const *s);
extern struct dt_info *parser_output;
extern bool treesource_error;
static bool is_ref_relative(const char *ref)
{
return ref[0] != '/' && strchr(&ref[1], '/');
}
%}
%union {
@ -175,8 +169,6 @@ devicetree:
*/
if (!($<flags>-1 & DTSF_PLUGIN))
ERROR(&@2, "Label or path %s not found", $1);
else if (is_ref_relative($1))
ERROR(&@2, "Label-relative reference %s not supported in plugin", $1);
$$ = add_orphan_node(
name_node(build_node(NULL, NULL, NULL),
""),
@ -186,9 +178,6 @@ devicetree:
{
struct node *target = get_node_by_ref($1, $3);
if (($<flags>-1 & DTSF_PLUGIN) && is_ref_relative($3))
ERROR(&@2, "Label-relative reference %s not supported in plugin", $3);
if (target) {
add_label(&target->labels, $2);
merge_nodes(target, $4);
@ -204,8 +193,6 @@ devicetree:
* so $-1 is what we want (plugindecl)
*/
if ($<flags>-1 & DTSF_PLUGIN) {
if (is_ref_relative($2))
ERROR(&@2, "Label-relative reference %s not supported in plugin", $2);
add_orphan_node($1, $3, $2);
} else {
struct node *target = get_node_by_ref($1, $2);
@ -284,17 +271,14 @@ propdef:
DT_PROPNODENAME '=' propdata ';'
{
$$ = build_property($1, $3, &@$);
free($1);
}
| DT_PROPNODENAME ';'
{
$$ = build_property($1, empty_data, &@$);
free($1);
}
| DT_DEL_PROP DT_PROPNODENAME ';'
{
$$ = build_property_delete($2);
free($2);
}
| DT_LABEL propdef
{
@ -407,14 +391,9 @@ arrayprefix:
* within the mask to one (i.e. | in the
* mask), all bits are one.
*/
if (($2 > mask) && (($2 | mask) != -1ULL)) {
char *loc = srcpos_string(&@2);
fprintf(stderr,
"WARNING: %s: Value 0x%016" PRIx64
" truncated to 0x%0*" PRIx64 "\n",
loc, $2, $1.bits / 4, ($2 & mask));
free(loc);
}
if (($2 > mask) && (($2 | mask) != -1ULL))
ERROR(&@2, "Value out of range for"
" %d-bit array element", $1.bits);
}
$$.data = data_append_integer($1.data, $2, $1.bits);
@ -497,8 +476,8 @@ integer_rela:
;
integer_shift:
integer_shift DT_LSHIFT integer_add { $$ = ($3 < 64) ? ($1 << $3) : 0; }
| integer_shift DT_RSHIFT integer_add { $$ = ($3 < 64) ? ($1 >> $3) : 0; }
integer_shift DT_LSHIFT integer_add { $$ = $1 << $3; }
| integer_shift DT_RSHIFT integer_add { $$ = $1 >> $3; }
| integer_add
;
@ -573,12 +552,10 @@ subnode:
DT_PROPNODENAME nodedef
{
$$ = name_node($2, $1);
free($1);
}
| DT_DEL_NODE DT_PROPNODENAME ';'
{
$$ = name_node(build_node_delete(&@$), $2);
free($2);
}
| DT_OMIT_NO_REF subnode
{

21
dtc.c
View file

@ -12,10 +12,10 @@
* Command line options
*/
int quiet; /* Level of quietness */
unsigned int reservenum;/* Number of memory reservation slots */
int reservenum; /* Number of memory reservation slots */
int minsize; /* Minimum blob size */
int padsize; /* Additional padding to blob */
int alignsize; /* Additional padding to blob according to the alignsize */
int alignsize; /* Additional padding to blob accroding to the alignsize */
int phandle_format = PHANDLE_EPAPR; /* Use linux,phandle or phandle properties */
int generate_symbols; /* enable symbols & fixup support */
int generate_fixups; /* suppress generation of fixups on symbol support */
@ -47,7 +47,7 @@ static void fill_fullpaths(struct node *tree, const char *prefix)
/* Usage related data. */
static const char usage_synopsis[] = "dtc [options] <input file>";
static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@LAThv";
static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@AThv";
static struct option const usage_long_opts[] = {
{"quiet", no_argument, NULL, 'q'},
{"in-format", a_argument, NULL, 'I'},
@ -67,7 +67,6 @@ static struct option const usage_long_opts[] = {
{"warning", a_argument, NULL, 'W'},
{"error", a_argument, NULL, 'E'},
{"symbols", no_argument, NULL, '@'},
{"local-fixups", no_argument, NULL, 'L'},
{"auto-alias", no_argument, NULL, 'A'},
{"annotate", no_argument, NULL, 'T'},
{"help", no_argument, NULL, 'h'},
@ -105,7 +104,6 @@ static const char * const usage_opts_help[] = {
"\n\tEnable/disable warnings (prefix with \"no-\")",
"\n\tEnable/disable errors (prefix with \"no-\")",
"\n\tEnable generation of symbols",
"\n\tPossibly generates a __local_fixups__ and a __fixups__ node at the root node",
"\n\tEnable auto-alias of labels",
"\n\tAnnotate output .dts with input source file and line (-T -T for more details)",
"\n\tPrint this help and exit",
@ -124,8 +122,6 @@ static const char *guess_type_by_name(const char *fname, const char *fallback)
return "dts";
if (!strcasecmp(s, ".yaml"))
return "yaml";
if (!strcasecmp(s, ".dtbo"))
return "dtb";
if (!strcasecmp(s, ".dtb"))
return "dtb";
return fallback;
@ -199,7 +195,7 @@ int main(int argc, char *argv[])
depname = optarg;
break;
case 'R':
reservenum = strtoul(optarg, NULL, 0);
reservenum = strtol(optarg, NULL, 0);
break;
case 'S':
minsize = strtol(optarg, NULL, 0);
@ -254,11 +250,6 @@ int main(int argc, char *argv[])
case '@':
generate_symbols = 1;
break;
case 'L':
generate_fixups = 1;
break;
case 'A':
auto_label_aliases = 1;
break;
@ -289,9 +280,7 @@ int main(int argc, char *argv[])
if (!depfile)
die("Couldn't open dependency file %s: %s\n", depname,
strerror(errno));
fprint_path_escaped(depfile, outname);
fputc(':', depfile);
fprintf(depfile, "%s:", outname);
}
if (inform == NULL)

96
dtc.h
View file

@ -35,10 +35,10 @@
* Command line options
*/
extern int quiet; /* Level of quietness */
extern unsigned int reservenum; /* Number of memory reservation slots */
extern int reservenum; /* Number of memory reservation slots */
extern int minsize; /* Minimum blob size */
extern int padsize; /* Additional padding to blob */
extern int alignsize; /* Additional padding to blob according to the alignsize */
extern int alignsize; /* Additional padding to blob accroding to the alignsize */
extern int phandle_format; /* Use linux,phandle or phandle properties */
extern int generate_symbols; /* generate symbols for nodes with labels */
extern int generate_fixups; /* generate fixups */
@ -51,56 +51,10 @@ extern int annotate; /* annotate .dts with input source location */
typedef uint32_t cell_t;
static inline bool phandle_is_valid(cell_t phandle)
{
return phandle != 0 && phandle != ~0U;
}
static inline uint16_t dtb_ld16(const void *p)
{
const uint8_t *bp = (const uint8_t *)p;
return ((uint16_t)bp[0] << 8)
| bp[1];
}
static inline uint32_t dtb_ld32(const void *p)
{
const uint8_t *bp = (const uint8_t *)p;
return ((uint32_t)bp[0] << 24)
| ((uint32_t)bp[1] << 16)
| ((uint32_t)bp[2] << 8)
| bp[3];
}
static inline uint64_t dtb_ld64(const void *p)
{
const uint8_t *bp = (const uint8_t *)p;
return ((uint64_t)bp[0] << 56)
| ((uint64_t)bp[1] << 48)
| ((uint64_t)bp[2] << 40)
| ((uint64_t)bp[3] << 32)
| ((uint64_t)bp[4] << 24)
| ((uint64_t)bp[5] << 16)
| ((uint64_t)bp[6] << 8)
| bp[7];
}
#define streq(a, b) (strcmp((a), (b)) == 0)
#define strstarts(s, prefix) (strncmp((s), (prefix), strlen(prefix)) == 0)
#define strprefixeq(a, n, b) (strlen(b) == (n) && (memcmp(a, b, n) == 0))
static inline bool strends(const char *str, const char *suffix)
{
unsigned int len, suffix_len;
len = strlen(str);
suffix_len = strlen(suffix);
if (len < suffix_len)
return false;
return streq(str + len - suffix_len, suffix);
}
#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
@ -116,23 +70,17 @@ enum markertype {
TYPE_UINT64,
TYPE_STRING,
};
static inline bool is_type_marker(enum markertype type)
{
return type >= TYPE_UINT8;
}
extern const char *markername(enum markertype markertype);
struct marker {
enum markertype type;
unsigned int offset;
int offset;
char *ref;
struct marker *next;
};
struct data {
unsigned int len;
int len;
char *val;
struct marker *markers;
};
@ -146,26 +94,11 @@ struct data {
for_each_marker(m) \
if ((m)->type == (t))
static inline struct marker *next_type_marker(struct marker *m)
{
for_each_marker(m)
if (is_type_marker(m->type))
break;
return m;
}
static inline size_t type_marker_length(struct marker *m)
{
struct marker *next = next_type_marker(m->next);
if (next)
return next->offset - m->offset;
return 0;
}
size_t type_marker_length(struct marker *m);
void data_free(struct data d);
struct data data_grow_for(struct data d, unsigned int xlen);
struct data data_grow_for(struct data d, int xlen);
struct data data_copy_mem(const char *mem, int len);
struct data data_copy_escape_string(const char *s, int len);
@ -182,10 +115,7 @@ struct data data_append_addr(struct data d, uint64_t addr);
struct data data_append_byte(struct data d, uint8_t byte);
struct data data_append_zeroes(struct data d, int len);
struct data data_append_align(struct data d, int align);
struct data data_insert_data(struct data d, struct marker *m, struct data old);
struct marker *alloc_marker(unsigned int offset, enum markertype type,
char *ref);
struct data data_add_marker(struct data d, enum markertype type, char *ref);
bool data_is_one_string(struct data d);
@ -263,16 +193,16 @@ struct node {
void add_label(struct label **labels, char *label);
void delete_labels(struct label **labels);
struct property *build_property(const char *name, struct data val,
struct property *build_property(char *name, struct data val,
struct srcpos *srcpos);
struct property *build_property_delete(const char *name);
struct property *build_property_delete(char *name);
struct property *chain_property(struct property *first, struct property *list);
struct property *reverse_properties(struct property *first);
struct node *build_node(struct property *proplist, struct node *children,
struct srcpos *srcpos);
struct node *build_node_delete(struct srcpos *srcpos);
struct node *name_node(struct node *node, const char *name);
struct node *name_node(struct node *node, char *name);
struct node *omit_node_if_unused(struct node *node);
struct node *reference_node(struct node *node);
struct node *chain_node(struct node *first, struct node *list);
@ -292,7 +222,7 @@ void append_to_property(struct node *node,
const char *get_unitname(struct node *node);
struct property *get_property(struct node *node, const char *propname);
cell_t propval_cell(struct property *prop);
cell_t propval_cell_n(struct property *prop, unsigned int n);
cell_t propval_cell_n(struct property *prop, int n);
struct property *get_property_by_label(struct node *tree, const char *label,
struct node **node);
struct marker *get_marker_label(struct node *tree, const char *label,
@ -339,9 +269,9 @@ struct dt_info *build_dt_info(unsigned int dtsflags,
struct reserve_info *reservelist,
struct node *tree, uint32_t boot_cpuid_phys);
void sort_tree(struct dt_info *dti);
void generate_label_tree(struct dt_info *dti, const char *name, bool allocph);
void generate_fixups_tree(struct dt_info *dti, const char *name);
void generate_local_fixups_tree(struct dt_info *dti, const char *name);
void generate_label_tree(struct dt_info *dti, char *name, bool allocph);
void generate_fixups_tree(struct dt_info *dti, char *name);
void generate_local_fixups_tree(struct dt_info *dti, char *name);
/* Checks */

2
dtdiff
View file

@ -17,7 +17,7 @@ source_and_sort () {
*.dts)
IFORMAT=dts
;;
*.dtb|*.dtbo)
*.dtb)
IFORMAT=dtb
;;
esac

View file

@ -18,10 +18,10 @@
#include "util.h"
#define FDT_MAGIC_SIZE 4
#define MAX_VERSION 17U
#define MAX_VERSION 17
#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
#define PALIGN(p, a) ((void *)(ALIGN((uintptr_t)(p), (a))))
#define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a))))
#define GET_CELL(p) (p += 4, *((const fdt32_t *)(p-4)))
static const char *tagname(uint32_t tag)
@ -163,7 +163,7 @@ static const char * const usage_opts_help[] = {
USAGE_COMMON_OPTS_HELP
};
static bool valid_header(char *p, size_t len)
static bool valid_header(char *p, off_t len)
{
if (len < sizeof(struct fdt_header) ||
fdt_magic(p) != FDT_MAGIC ||
@ -217,7 +217,7 @@ int main(int argc, char *argv[])
char *p = buf;
char *endp = buf + len;
fdt32_st(smagic, FDT_MAGIC);
fdt_set_magic(smagic, FDT_MAGIC);
/* poor man's memmem */
while ((endp - p) >= FDT_MAGIC_SIZE) {
@ -235,7 +235,7 @@ int main(int argc, char *argv[])
}
++p;
}
if (!p || (size_t)(endp - p) < sizeof(struct fdt_header))
if (!p || endp - p < sizeof(struct fdt_header))
die("%s: could not locate fdt magic\n", file);
printf("%s: found fdt at offset %#tx\n", file, p - buf);
buf = p;

View file

@ -62,14 +62,8 @@ static int show_cell_list(struct display_info *disp, const char *data, int len,
for (i = 0; i < len; i += size, p += size) {
if (i)
printf(" ");
switch (size) {
case 4: value = fdt32_ld((const fdt32_t *)p); break;
case 2: value = fdt16_ld((const fdt16_t *)p); break;
case 1:
default:
value = *p;
break;
}
value = size == 4 ? fdt32_ld((const fdt32_t *)p) :
size == 2 ? (*p << 8) | p[1] : *p;
printf(fmt, value);
}
@ -97,11 +91,6 @@ static int show_data(struct display_info *disp, const char *data, int len)
if (len == 0)
return 0;
if (disp->type == 'r') {
fwrite(data, 1, len, stdout);
return 0;
}
is_string = (disp->type) == 's' ||
(!disp->type && util_is_printable_string(data, len));
if (is_string) {

View file

@ -23,7 +23,9 @@
/* Usage related data. */
static const char usage_synopsis[] =
"apply a number of overlays to a base blob\n"
" fdtoverlay <options> [<overlay.dtbo> [<overlay.dtbo>]]";
" fdtoverlay <options> [<overlay.dtbo> [<overlay.dtbo>]]\n"
"\n"
USAGE_TYPE_MSG;
static const char usage_short_opts[] = "i:o:v" USAGE_COMMON_SHORT_OPTS;
static struct option const usage_long_opts[] = {
{"input", required_argument, NULL, 'i'},
@ -46,10 +48,9 @@ static void *apply_one(char *base, const char *overlay, size_t *buf_len,
char *tmp = NULL;
char *tmpo;
int ret;
bool has_symbols;
/*
* We take copies first, because a failed apply can trash
* We take a copies first, because a a failed apply can trash
* both the base blob and the overlay
*/
tmpo = xmalloc(fdt_totalsize(overlay));
@ -63,8 +64,6 @@ static void *apply_one(char *base, const char *overlay, size_t *buf_len,
fdt_strerror(ret));
goto fail;
}
ret = fdt_path_offset(tmp, "/__symbols__");
has_symbols = ret >= 0;
memcpy(tmpo, overlay, fdt_totalsize(overlay));
@ -77,11 +76,6 @@ static void *apply_one(char *base, const char *overlay, size_t *buf_len,
if (ret) {
fprintf(stderr, "\nFailed to apply '%s': %s\n",
name, fdt_strerror(ret));
if (!has_symbols) {
fprintf(stderr,
"base blob does not have a '/__symbols__' node, "
"make sure you have compiled the base blob with '-@' option\n");
}
goto fail;
}

View file

@ -9,7 +9,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <libfdt.h>
@ -65,12 +64,16 @@ static int encode_value(struct display_info *disp, char **arg, int arg_count,
int len; /* length of this cell/string/byte */
int ival;
int upto; /* the number of bytes we have written to buf */
char fmt[3];
upto = 0;
if (disp->verbose)
fprintf(stderr, "Decoding value:\n");
fmt[0] = '%';
fmt[1] = disp->type ? disp->type : 'd';
fmt[2] = '\0';
for (; arg_count > 0; arg++, arg_count--, upto += len) {
/* assume integer unless told otherwise */
if (disp->type == 's')
@ -91,34 +94,7 @@ static int encode_value(struct display_info *disp, char **arg, int arg_count,
fprintf(stderr, "\tstring: '%s'\n", ptr);
} else {
fdt32_t *iptr = (fdt32_t *)ptr;
char *endptr;
errno = 0;
switch (disp->type) {
case 'x':
ival = strtoul(*arg, &endptr, 16);
break;
case 'o':
ival = strtoul(*arg, &endptr, 8);
break;
case 'i':
ival = strtol(*arg, &endptr, 0);
break;
case 'u':
ival = strtoul(*arg, &endptr, 0);
break;
default: /* 0 or 'd' */
ival = strtol(*arg, &endptr, 10);
}
if (*endptr != '\0' || errno) {
if (disp->verbose) {
fprintf(stderr,
"Couldn't parse \"%s\" as an integer\n",
*arg);
}
return -1;
}
sscanf(*arg, fmt, &ival);
if (len == 4)
*iptr = cpu_to_fdt32(ival);
else
@ -413,8 +389,8 @@ static struct option const usage_long_opts[] = {
USAGE_COMMON_LONG_OPTS,
};
static const char * const usage_opts_help[] = {
"Create nodes",
"Delete nodes (and any subnodes)",
"Create nodes if they don't already exist",
"Delete nodes (and any subnodes) if they already exist",
"Delete properties if they already exist",
"Automatically create nodes as needed for the node path",
"Type of data",
@ -457,8 +433,6 @@ int main(int argc, char *argv[])
if (utilfdt_decode_type(optarg, &disp.type,
&disp.size))
usage("Invalid type string");
if (disp.type == 'r')
usage("Unsupported raw data type");
break;
case 'v':

View file

@ -124,8 +124,7 @@ static void asm_emit_cell(void *e, cell_t val)
{
FILE *f = e;
fprintf(f, "\t.byte\t0x%02x\n" "\t.byte\t0x%02x\n"
"\t.byte\t0x%02x\n" "\t.byte\t0x%02x\n",
fprintf(f, "\t.byte 0x%02x; .byte 0x%02x; .byte 0x%02x; .byte 0x%02x\n",
(val >> 24) & 0xff, (val >> 16) & 0xff,
(val >> 8) & 0xff, val & 0xff);
}
@ -135,9 +134,9 @@ static void asm_emit_string(void *e, const char *str, int len)
FILE *f = e;
if (len != 0)
fprintf(f, "\t.asciz\t\"%.*s\"\n", len, str);
fprintf(f, "\t.string\t\"%.*s\"\n", len, str);
else
fprintf(f, "\t.asciz\t\"%s\"\n", str);
fprintf(f, "\t.string\t\"%s\"\n", str);
}
static void asm_emit_align(void *e, int a)
@ -150,14 +149,14 @@ static void asm_emit_align(void *e, int a)
static void asm_emit_data(void *e, struct data d)
{
FILE *f = e;
unsigned int off = 0;
int off = 0;
struct marker *m = d.markers;
for_each_marker_of_type(m, LABEL)
emit_offset_label(f, m->ref, m->offset);
while ((d.len - off) >= sizeof(uint32_t)) {
asm_emit_cell(e, dtb_ld32(d.val + off));
asm_emit_cell(e, fdt32_to_cpu(*((fdt32_t *)(d.val+off))));
off += sizeof(uint32_t);
}
@ -220,7 +219,7 @@ static struct emitter asm_emitter = {
static int stringtable_insert(struct data *d, const char *str)
{
unsigned int i;
int i;
/* FIXME: do this more efficiently? */
@ -296,7 +295,7 @@ static struct data flatten_reserve_list(struct reserve_info *reservelist,
{
struct reserve_info *re;
struct data d = empty_data;
unsigned int j;
int j;
for (re = reservelist; re; re = re->next) {
d = data_append_re(d, re->address, re->size);
@ -346,7 +345,7 @@ static void make_fdt_header(struct fdt_header *fdt,
void dt_to_blob(FILE *f, struct dt_info *dti, int version)
{
struct version_info *vi = NULL;
unsigned int i;
int i;
struct data blob = empty_data;
struct data reservebuf = empty_data;
struct data dtbuf = empty_data;
@ -439,7 +438,7 @@ static void dump_stringtable_asm(FILE *f, struct data strbuf)
while (p < (strbuf.val + strbuf.len)) {
len = strlen(p);
fprintf(f, "\t.asciz \"%s\"\n", p);
fprintf(f, "\t.string \"%s\"\n", p);
p += len+1;
}
}
@ -447,7 +446,7 @@ static void dump_stringtable_asm(FILE *f, struct data strbuf)
void dt_to_asm(FILE *f, struct dt_info *dti, int version)
{
struct version_info *vi = NULL;
unsigned int i;
int i;
struct data strbuf = empty_data;
struct reserve_info *re;
const char *symprefix = "dt";
@ -503,7 +502,7 @@ void dt_to_asm(FILE *f, struct dt_info *dti, int version)
* Reserve map entries.
* Align the reserve map to a doubleword boundary.
* Each entry is an (address, size) pair of u64 values.
* Always supply a zero-sized termination entry.
* Always supply a zero-sized temination entry.
*/
asm_emit_align(f, 8);
emit_label(f, symprefix, "reserve_map");
@ -604,11 +603,11 @@ static void flat_realign(struct inbuf *inb, int align)
die("Premature end of data parsing flat device tree\n");
}
static const char *flat_read_string(struct inbuf *inb)
static char *flat_read_string(struct inbuf *inb)
{
int len = 0;
const char *p = inb->ptr;
const char *str;
char *str;
do {
if (p >= inb->limit)
@ -616,7 +615,7 @@ static const char *flat_read_string(struct inbuf *inb)
len++;
} while ((*p++) != '\0');
str = inb->ptr;
str = xstrdup(inb->ptr);
inb->ptr += len;
@ -711,7 +710,7 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb)
}
static const char *nodename_from_path(const char *ppath, const char *cpath)
static char *nodename_from_path(const char *ppath, const char *cpath)
{
int plen;
@ -725,7 +724,7 @@ static const char *nodename_from_path(const char *ppath, const char *cpath)
if (!streq(ppath, "/"))
plen++;
return cpath + plen;
return xstrdup(cpath + plen);
}
static struct node *unflatten_tree(struct inbuf *dtbuf,
@ -733,7 +732,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,
const char *parent_flatname, int flags)
{
struct node *node;
const char *flatname;
char *flatname;
uint32_t val;
node = build_node(NULL, NULL, NULL);
@ -741,10 +740,9 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,
flatname = flat_read_string(dtbuf);
if (flags & FTF_FULLPATH)
node->name = xstrdup(nodename_from_path(parent_flatname,
flatname));
node->name = nodename_from_path(parent_flatname, flatname);
else
node->name = xstrdup(flatname);
node->name = flatname;
do {
struct property *prop;
@ -786,6 +784,10 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,
}
} while (val != FDT_END_NODE);
if (node->name != flatname) {
free(flatname);
}
return node;
}

View file

@ -43,7 +43,7 @@ static struct node *read_fstree(const char *dirname)
"WARNING: Cannot open %s: %s\n",
tmpname, strerror(errno));
} else {
prop = build_property(de->d_name,
prop = build_property(xstrdup(de->d_name),
data_copy_file(pfile,
st.st_size),
NULL);

View file

@ -4,19 +4,15 @@
# This is not a complete Makefile of itself. Instead, it is designed to
# be easily embeddable into other systems of Makefiles.
#
LIBFDT_so = libfdt.$(SHAREDLIB_EXT)
LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1
LIBFDT_INCLUDES = fdt.h libfdt.h libfdt_env.h
LIBFDT_VERSION = version.lds
LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c \
fdt_addresses.c fdt_overlay.c fdt_check.c
LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
LIBFDT_LIB = libfdt.$(SHAREDLIB_EXT).$(DTC_VERSION)
LIBFDT_LIB = libfdt-$(DTC_VERSION).$(SHAREDLIB_EXT)
libfdt_clean:
@$(VECHO) CLEAN "(libfdt)"
rm -f $(STD_CLEANFILES:%=$(LIBFDT_dir)/%)
rm -f $(LIBFDT_dir)/$(LIBFDT_so)
rm -f $(LIBFDT_dir)/$(LIBFDT_soname)
rm -f $(LIBFDT_dir)/$(LIBFDT_LIB)

View file

@ -1,2 +1,3 @@
- Tree traversal functions
- Graft function
- Complete libfdt.h documenting comments

View file

@ -22,10 +22,6 @@ int32_t fdt_ro_probe_(const void *fdt)
if (can_assume(VALID_DTB))
return totalsize;
/* The device tree must be at an 8-byte aligned address */
if ((uintptr_t)fdt & 7)
return -FDT_ERR_ALIGNMENT;
if (fdt_magic(fdt) == FDT_MAGIC) {
/* Complete tree */
if (!can_assume(LATEST)) {
@ -90,10 +86,6 @@ int fdt_check_header(const void *fdt)
{
size_t hdrsize;
/* The device tree must be at an 8-byte aligned address */
if ((uintptr_t)fdt & 7)
return -FDT_ERR_ALIGNMENT;
if (fdt_magic(fdt) != FDT_MAGIC)
return -FDT_ERR_BADMAGIC;
if (!can_assume(LATEST)) {
@ -106,6 +98,7 @@ int fdt_check_header(const void *fdt)
}
hdrsize = fdt_header_size(fdt);
if (!can_assume(VALID_DTB)) {
if ((fdt_totalsize(fdt) < hdrsize)
|| (fdt_totalsize(fdt) > INT_MAX))
return -FDT_ERR_TRUNCATED;
@ -114,7 +107,9 @@ int fdt_check_header(const void *fdt)
if (!check_off_(hdrsize, fdt_totalsize(fdt),
fdt_off_mem_rsvmap(fdt)))
return -FDT_ERR_TRUNCATED;
}
if (!can_assume(VALID_DTB)) {
/* Bounds check structure block */
if (!can_assume(LATEST) && fdt_version(fdt) < 17) {
if (!check_off_(hdrsize, fdt_totalsize(fdt),
@ -139,20 +134,16 @@ int fdt_check_header(const void *fdt)
const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
{
unsigned int uoffset = offset;
unsigned int absoffset = offset + fdt_off_dt_struct(fdt);
if (offset < 0)
return NULL;
unsigned absoffset = offset + fdt_off_dt_struct(fdt);
if (!can_assume(VALID_INPUT))
if ((absoffset < uoffset)
if ((absoffset < offset)
|| ((absoffset + len) < absoffset)
|| (absoffset + len) > fdt_totalsize(fdt))
return NULL;
if (can_assume(LATEST) || fdt_version(fdt) >= 0x11)
if (((uoffset + len) < uoffset)
if (((offset + len) < offset)
|| ((offset + len) > fdt_size_dt_struct(fdt)))
return NULL;
@ -162,7 +153,7 @@ const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
{
const fdt32_t *tagp, *lenp;
uint32_t tag, len, sum;
uint32_t tag;
int offset = startoffset;
const char *p;
@ -188,19 +179,12 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
if (!can_assume(VALID_DTB) && !lenp)
return FDT_END; /* premature end */
len = fdt32_to_cpu(*lenp);
sum = len + offset;
if (!can_assume(VALID_DTB) &&
(INT_MAX <= sum || sum < (uint32_t) offset))
return FDT_END; /* premature end */
/* skip-name offset, length and value */
offset += sizeof(struct fdt_property) - FDT_TAGSIZE + len;
offset += sizeof(struct fdt_property) - FDT_TAGSIZE
+ fdt32_to_cpu(*lenp);
if (!can_assume(LATEST) &&
fdt_version(fdt) < 0x10 && len >= 8 &&
((offset - len) % 8) != 0)
fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 &&
((offset - fdt32_to_cpu(*lenp)) % 8) != 0)
offset += 4;
break;
@ -222,11 +206,10 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
int fdt_check_node_offset_(const void *fdt, int offset)
{
if (!can_assume(VALID_INPUT)
&& ((offset < 0) || (offset % FDT_TAGSIZE)))
return -FDT_ERR_BADOFFSET;
if (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE)
if (can_assume(VALID_INPUT))
return offset;
if ((offset < 0) || (offset % FDT_TAGSIZE)
|| (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE))
return -FDT_ERR_BADOFFSET;
return offset;
@ -234,11 +217,8 @@ int fdt_check_node_offset_(const void *fdt, int offset)
int fdt_check_prop_offset_(const void *fdt, int offset)
{
if (!can_assume(VALID_INPUT)
&& ((offset < 0) || (offset % FDT_TAGSIZE)))
return -FDT_ERR_BADOFFSET;
if (fdt_next_tag(fdt, offset, &offset) != FDT_PROP)
if ((offset < 0) || (offset % FDT_TAGSIZE)
|| (fdt_next_tag(fdt, offset, &offset) != FDT_PROP))
return -FDT_ERR_BADOFFSET;
return offset;
@ -312,26 +292,23 @@ int fdt_next_subnode(const void *fdt, int offset)
return offset;
}
const char *fdt_find_string_len_(const char *strtab, int tabsize, const char *s,
int slen)
const char *fdt_find_string_(const char *strtab, int tabsize, const char *s)
{
const char *last = strtab + tabsize - (slen + 1);
int len = strlen(s) + 1;
const char *last = strtab + tabsize - len;
const char *p;
for (p = strtab; p <= last; p++)
if (memcmp(p, s, slen) == 0 && p[slen] == '\0')
if (memcmp(p, s, len) == 0)
return p;
return NULL;
}
int fdt_move(const void *fdt, void *buf, int bufsize)
{
if (!can_assume(VALID_INPUT) && bufsize < 0)
return -FDT_ERR_NOSPACE;
FDT_RO_PROBE(fdt);
if (fdt_totalsize(fdt) > (unsigned int)bufsize)
if (fdt_totalsize(fdt) > bufsize)
return -FDT_ERR_NOSPACE;
memmove(buf, fdt, fdt_totalsize(fdt));

View file

@ -7,7 +7,7 @@
* Copyright 2012 Kim Phillips, Freescale Semiconductor.
*/
#ifndef __ASSEMBLER__
#ifndef __ASSEMBLY__
struct fdt_header {
fdt32_t magic; /* magic word FDT_MAGIC */
@ -35,17 +35,17 @@ struct fdt_reserve_entry {
struct fdt_node_header {
fdt32_t tag;
char name[];
char name[0];
};
struct fdt_property {
fdt32_t tag;
fdt32_t len;
fdt32_t nameoff;
char data[];
char data[0];
};
#endif /* !__ASSEMBLER__ */
#endif /* !__ASSEMBLY */
#define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */
#define FDT_TAGSIZE sizeof(fdt32_t)

View file

@ -73,7 +73,7 @@ int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset,
/* check validity of address */
prop = data;
if (addr_cells == 1) {
if ((addr > UINT32_MAX) || (((uint64_t) UINT32_MAX + 1 - addr) < size))
if ((addr > UINT32_MAX) || ((UINT32_MAX + 1 - addr) < size))
return -FDT_ERR_BADVALUE;
fdt32_st(prop, (uint32_t)addr);

View file

@ -19,12 +19,9 @@ int fdt_check_full(const void *fdt, size_t bufsize)
unsigned int depth = 0;
const void *prop;
const char *propname;
bool expect_end = false;
if (bufsize < FDT_V1_SIZE)
return -FDT_ERR_TRUNCATED;
if (bufsize < fdt_header_size(fdt))
return -FDT_ERR_TRUNCATED;
err = fdt_check_header(fdt);
if (err != 0)
return err;
@ -42,10 +39,6 @@ int fdt_check_full(const void *fdt, size_t bufsize)
if (nextoffset < 0)
return nextoffset;
/* If we see two root nodes, something is wrong */
if (expect_end && tag != FDT_END)
return -FDT_ERR_BADSTRUCTURE;
switch (tag) {
case FDT_NOP:
break;
@ -59,27 +52,12 @@ int fdt_check_full(const void *fdt, size_t bufsize)
depth++;
if (depth > INT_MAX)
return -FDT_ERR_BADSTRUCTURE;
/* The root node must have an empty name */
if (depth == 1) {
const char *name;
int len;
name = fdt_get_name(fdt, offset, &len);
if (!name)
return len;
if (*name || len)
return -FDT_ERR_BADSTRUCTURE;
}
break;
case FDT_END_NODE:
if (depth == 0)
return -FDT_ERR_BADSTRUCTURE;
depth--;
if (depth == 0)
expect_end = true;
break;
case FDT_PROP:

View file

@ -40,22 +40,37 @@ static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
return fdt32_to_cpu(*val);
}
int fdt_overlay_target_offset(const void *fdt, const void *fdto,
int fragment_offset, char const **pathp)
/**
* overlay_get_target - retrieves the offset of a fragment's target
* @fdt: Base device tree blob
* @fdto: Device tree overlay blob
* @fragment: node offset of the fragment in the overlay
* @pathp: pointer which receives the path of the target (or NULL)
*
* overlay_get_target() retrieves the target offset in the base
* device tree of a fragment, no matter how the actual targeting is
* done (through a phandle or a path)
*
* returns:
* the targeted node offset in the base device tree
* Negative error code on error
*/
static int overlay_get_target(const void *fdt, const void *fdto,
int fragment, char const **pathp)
{
uint32_t phandle;
const char *path = NULL;
int path_len = 0, ret;
/* Try first to do a phandle based lookup */
phandle = overlay_get_target_phandle(fdto, fragment_offset);
phandle = overlay_get_target_phandle(fdto, fragment);
if (phandle == (uint32_t)-1)
return -FDT_ERR_BADPHANDLE;
/* no phandle, try path */
if (!phandle) {
/* And then a path based lookup */
path = fdt_getprop(fdto, fragment_offset, "target-path", &path_len);
path = fdt_getprop(fdto, fragment, "target-path", &path_len);
if (path)
ret = fdt_path_offset(fdt, path);
else
@ -101,22 +116,26 @@ int fdt_overlay_target_offset(const void *fdt, const void *fdto,
static int overlay_phandle_add_offset(void *fdt, int node,
const char *name, uint32_t delta)
{
fdt32_t *valp, val;
const fdt32_t *val;
uint32_t adj_val;
int len;
valp = fdt_getprop_w(fdt, node, name, &len);
if (!valp)
val = fdt_getprop(fdt, node, name, &len);
if (!val)
return len;
if (len != sizeof(val))
if (len != sizeof(*val))
return -FDT_ERR_BADPHANDLE;
val = fdt32_ld(valp);
if (val + delta < val || val + delta == (uint32_t)-1)
adj_val = fdt32_to_cpu(*val);
if ((adj_val + delta) < adj_val)
return -FDT_ERR_NOPHANDLES;
fdt32_st(valp, val + delta);
return 0;
adj_val += delta;
if (adj_val == (uint32_t)-1)
return -FDT_ERR_NOPHANDLES;
return fdt_setprop_inplace_u32(fdt, node, name, adj_val);
}
/**
@ -209,8 +228,8 @@ static int overlay_update_local_node_references(void *fdto,
fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {
const fdt32_t *fixup_val;
const char *tree_val;
const char *name;
char *tree_val;
int fixup_len;
int tree_len;
int i;
@ -222,9 +241,8 @@ static int overlay_update_local_node_references(void *fdto,
if (fixup_len % sizeof(uint32_t))
return -FDT_ERR_BADOVERLAY;
fixup_len /= sizeof(uint32_t);
tree_val = fdt_getprop_w(fdto, tree_node, name, &tree_len);
tree_val = fdt_getprop(fdto, tree_node, name, &tree_len);
if (!tree_val) {
if (tree_len == -FDT_ERR_NOTFOUND)
return -FDT_ERR_BADOVERLAY;
@ -232,16 +250,34 @@ static int overlay_update_local_node_references(void *fdto,
return tree_len;
}
for (i = 0; i < fixup_len; i++) {
fdt32_t *refp;
for (i = 0; i < (fixup_len / sizeof(uint32_t)); i++) {
fdt32_t adj_val;
uint32_t poffset;
refp = (fdt32_t *)(tree_val + fdt32_ld_(fixup_val + i));
poffset = fdt32_to_cpu(fixup_val[i]);
/*
* phandles to fixup can be unaligned, so use
* fdt32_{ld,st}() to read/write them.
* phandles to fixup can be unaligned.
*
* Use a memcpy for the architectures that do
* not support unaligned accesses.
*/
fdt32_st(refp, fdt32_ld(refp) + delta);
memcpy(&adj_val, tree_val + poffset, sizeof(adj_val));
adj_val = cpu_to_fdt32(fdt32_to_cpu(adj_val) + delta);
ret = fdt_setprop_inplace_namelen_partial(fdto,
tree_node,
name,
strlen(name),
poffset,
&adj_val,
sizeof(adj_val));
if (ret == -FDT_ERR_NOSPACE)
return -FDT_ERR_BADOVERLAY;
if (ret)
return ret;
}
}
@ -307,6 +343,7 @@ static int overlay_update_local_references(void *fdto, uint32_t delta)
/**
* overlay_fixup_one_phandle - Set an overlay phandle to the base one
* @fdt: Base Device Tree blob
* @fdto: Device tree overlay blob
* @symbols_off: Node offset of the symbols node in the base device tree
* @path: Path to a node holding a phandle in the overlay
@ -314,7 +351,7 @@ static int overlay_update_local_references(void *fdto, uint32_t delta)
* @name: Name of the property holding the phandle reference in the overlay
* @name_len: number of name characters to consider
* @poffset: Offset within the overlay property where the phandle is stored
* @phandle: Phandle referencing the node
* @label: Label of the node referenced by the phandle
*
* overlay_fixup_one_phandle() resolves an overlay phandle pointing to
* a node in the base device tree.
@ -327,17 +364,34 @@ static int overlay_update_local_references(void *fdto, uint32_t delta)
* 0 on success
* Negative error code on failure
*/
static int overlay_fixup_one_phandle(void *fdto, int symbols_off,
static int overlay_fixup_one_phandle(void *fdt, void *fdto,
int symbols_off,
const char *path, uint32_t path_len,
const char *name, uint32_t name_len,
int poffset, uint32_t phandle)
int poffset, const char *label)
{
const char *symbol_path;
uint32_t phandle;
fdt32_t phandle_prop;
int fixup_off;
int symbol_off, fixup_off;
int prop_len;
if (symbols_off < 0)
return symbols_off;
symbol_path = fdt_getprop(fdt, symbols_off, label,
&prop_len);
if (!symbol_path)
return prop_len;
symbol_off = fdt_path_offset(fdt, symbol_path);
if (symbol_off < 0)
return symbol_off;
phandle = fdt_get_phandle(fdt, symbol_off);
if (!phandle)
return -FDT_ERR_NOTFOUND;
fixup_off = fdt_path_offset_namelen(fdto, path, path_len);
if (fixup_off == -FDT_ERR_NOTFOUND)
return -FDT_ERR_BADOVERLAY;
@ -349,7 +403,7 @@ static int overlay_fixup_one_phandle(void *fdto, int symbols_off,
name, name_len, poffset,
&phandle_prop,
sizeof(phandle_prop));
}
};
/**
* overlay_fixup_phandle - Set an overlay phandle to the base one
@ -376,10 +430,6 @@ static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
const char *value;
const char *label;
int len;
const char *symbol_path;
int prop_len;
int symbol_off;
uint32_t phandle;
value = fdt_getprop_by_offset(fdto, property,
&label, &len);
@ -390,18 +440,6 @@ static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
return len;
}
symbol_path = fdt_getprop(fdt, symbols_off, label, &prop_len);
if (!symbol_path)
return prop_len;
symbol_off = fdt_path_offset(fdt, symbol_path);
if (symbol_off < 0)
return symbol_off;
phandle = fdt_get_phandle(fdt, symbol_off);
if (!phandle)
return -FDT_ERR_NOTFOUND;
do {
const char *path, *name, *fixup_end;
const char *fixup_str = value;
@ -441,9 +479,9 @@ static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
if ((*endptr != '\0') || (endptr <= (sep + 1)))
return -FDT_ERR_BADOVERLAY;
ret = overlay_fixup_one_phandle(fdto, symbols_off,
ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off,
path, path_len, name, name_len,
poffset, phandle);
poffset, label);
if (ret)
return ret;
} while (len > 0);
@ -496,255 +534,6 @@ static int overlay_fixup_phandles(void *fdt, void *fdto)
return 0;
}
/**
* overlay_adjust_local_conflicting_phandle: Changes a phandle value
* @fdto: Device tree overlay
* @node: The node the phandle is set for
* @fdt_phandle: The new value for the phandle
*
* returns:
* 0 on success
* Negative error code on failure
*/
static int overlay_adjust_local_conflicting_phandle(void *fdto, int node,
uint32_t fdt_phandle)
{
const fdt32_t *php;
int len, ret;
php = fdt_getprop(fdto, node, "phandle", &len);
if (php && len == sizeof(*php)) {
ret = fdt_setprop_inplace_u32(fdto, node, "phandle", fdt_phandle);
if (ret)
return ret;
}
php = fdt_getprop(fdto, node, "linux,phandle", &len);
if (php && len == sizeof(*php)) {
ret = fdt_setprop_inplace_u32(fdto, node, "linux,phandle", fdt_phandle);
if (ret)
return ret;
}
return 0;
}
/**
* overlay_update_node_conflicting_references - Recursively replace phandle values
* @fdto: Device tree overlay blob
* @tree_node: Node to recurse into
* @fixup_node: Node offset of the matching local fixups node
* @fdt_phandle: Value to replace phandles with
* @fdto_phandle: Value to be replaced
*
* Replaces all phandles with value @fdto_phandle by @fdt_phandle.
*
* returns:
* 0 on success
* Negative error code on failure
*/
static int overlay_update_node_conflicting_references(void *fdto, int tree_node,
int fixup_node,
uint32_t fdt_phandle,
uint32_t fdto_phandle)
{
int fixup_prop;
int fixup_child;
int ret;
fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {
const fdt32_t *fixup_val;
const char *name;
char *tree_val;
int fixup_len;
int tree_len;
int i;
fixup_val = fdt_getprop_by_offset(fdto, fixup_prop,
&name, &fixup_len);
if (!fixup_val)
return fixup_len;
if (fixup_len % sizeof(uint32_t))
return -FDT_ERR_BADOVERLAY;
fixup_len /= sizeof(uint32_t);
tree_val = fdt_getprop_w(fdto, tree_node, name, &tree_len);
if (!tree_val) {
if (tree_len == -FDT_ERR_NOTFOUND)
return -FDT_ERR_BADOVERLAY;
return tree_len;
}
for (i = 0; i < fixup_len; i++) {
fdt32_t *refp;
uint32_t valp;
refp = (fdt32_t *)(tree_val + fdt32_ld_(fixup_val + i));
valp = fdt32_ld(refp);
if (valp == fdto_phandle)
fdt32_st(refp, fdt_phandle);
}
}
fdt_for_each_subnode(fixup_child, fdto, fixup_node) {
const char *fixup_child_name = fdt_get_name(fdto, fixup_child, NULL);
int tree_child;
tree_child = fdt_subnode_offset(fdto, tree_node, fixup_child_name);
if (tree_child == -FDT_ERR_NOTFOUND)
return -FDT_ERR_BADOVERLAY;
if (tree_child < 0)
return tree_child;
ret = overlay_update_node_conflicting_references(fdto, tree_child,
fixup_child,
fdt_phandle,
fdto_phandle);
if (ret)
return ret;
}
return 0;
}
/**
* overlay_update_local_conflicting_references - Recursively replace phandle values
* @fdto: Device tree overlay blob
* @fdt_phandle: Value to replace phandles with
* @fdto_phandle: Value to be replaced
*
* Replaces all phandles with value @fdto_phandle by @fdt_phandle.
*
* returns:
* 0 on success
* Negative error code on failure
*/
static int overlay_update_local_conflicting_references(void *fdto,
uint32_t fdt_phandle,
uint32_t fdto_phandle)
{
int fixups;
fixups = fdt_path_offset(fdto, "/__local_fixups__");
if (fixups == -FDT_ERR_NOTFOUND)
return 0;
if (fixups < 0)
return fixups;
return overlay_update_node_conflicting_references(fdto, 0, fixups,
fdt_phandle,
fdto_phandle);
}
/**
* overlay_prevent_phandle_overwrite_node - Helper function for overlay_prevent_phandle_overwrite
* @fdt: Base Device tree blob
* @fdtnode: Node in fdt that is checked for an overwrite
* @fdto: Device tree overlay blob
* @fdtonode: Node in fdto matching @fdtnode
*
* returns:
* 0 on success
* Negative error code on failure
*/
static int overlay_prevent_phandle_overwrite_node(void *fdt, int fdtnode,
void *fdto, int fdtonode)
{
uint32_t fdt_phandle, fdto_phandle;
int fdtochild;
fdt_phandle = fdt_get_phandle(fdt, fdtnode);
fdto_phandle = fdt_get_phandle(fdto, fdtonode);
if (fdt_phandle && fdto_phandle) {
int ret;
ret = overlay_adjust_local_conflicting_phandle(fdto, fdtonode,
fdt_phandle);
if (ret)
return ret;
ret = overlay_update_local_conflicting_references(fdto,
fdt_phandle,
fdto_phandle);
if (ret)
return ret;
}
fdt_for_each_subnode(fdtochild, fdto, fdtonode) {
const char *name = fdt_get_name(fdto, fdtochild, NULL);
int fdtchild;
int ret;
fdtchild = fdt_subnode_offset(fdt, fdtnode, name);
if (fdtchild == -FDT_ERR_NOTFOUND)
/*
* no further overwrites possible here as this node is
* new
*/
continue;
ret = overlay_prevent_phandle_overwrite_node(fdt, fdtchild,
fdto, fdtochild);
if (ret)
return ret;
}
return 0;
}
/**
* overlay_prevent_phandle_overwrite - Fixes overlay phandles to not overwrite base phandles
* @fdt: Base Device Tree blob
* @fdto: Device tree overlay blob
*
* Checks recursively if applying fdto overwrites phandle values in the base
* dtb. When such a phandle is found, the fdto is changed to use the fdt's
* phandle value to not break references in the base.
*
* returns:
* 0 on success
* Negative error code on failure
*/
static int overlay_prevent_phandle_overwrite(void *fdt, void *fdto)
{
int fragment;
fdt_for_each_subnode(fragment, fdto, 0) {
int overlay;
int target;
int ret;
overlay = fdt_subnode_offset(fdto, fragment, "__overlay__");
if (overlay == -FDT_ERR_NOTFOUND)
continue;
if (overlay < 0)
return overlay;
target = fdt_overlay_target_offset(fdt, fdto, fragment, NULL);
if (target == -FDT_ERR_NOTFOUND)
/*
* The subtree doesn't exist in the base, so nothing
* will be overwritten.
*/
continue;
else if (target < 0)
return target;
ret = overlay_prevent_phandle_overwrite_node(fdt, target,
fdto, overlay);
if (ret)
return ret;
}
return 0;
}
/**
* overlay_apply_node - Merges a node into the base device tree
* @fdt: Base Device Tree blob
@ -846,7 +635,7 @@ static int overlay_merge(void *fdt, void *fdto)
if (overlay < 0)
return overlay;
target = fdt_overlay_target_offset(fdt, fdto, fragment, NULL);
target = overlay_get_target(fdt, fdto, fragment, NULL);
if (target < 0)
return target;
@ -989,7 +778,7 @@ static int overlay_symbol_update(void *fdt, void *fdto)
return -FDT_ERR_BADOVERLAY;
/* get the target of the fragment */
ret = fdt_overlay_target_offset(fdt, fdto, fragment, &target_path);
ret = overlay_get_target(fdt, fdto, fragment, &target_path);
if (ret < 0)
return ret;
target = ret;
@ -1011,7 +800,7 @@ static int overlay_symbol_update(void *fdt, void *fdto)
if (!target_path) {
/* again in case setprop_placeholder changed it */
ret = fdt_overlay_target_offset(fdt, fdto, fragment, &target_path);
ret = overlay_get_target(fdt, fdto, fragment, &target_path);
if (ret < 0)
return ret;
target = ret;
@ -1049,26 +838,18 @@ int fdt_overlay_apply(void *fdt, void *fdto)
if (ret)
goto err;
/* Increase all phandles in the fdto by delta */
ret = overlay_adjust_local_phandles(fdto, delta);
if (ret)
goto err;
/* Adapt the phandle values in fdto to the above increase */
ret = overlay_update_local_references(fdto, delta);
if (ret)
goto err;
/* Update fdto's phandles using symbols from fdt */
ret = overlay_fixup_phandles(fdt, fdto);
if (ret)
goto err;
/* Don't overwrite phandles in fdt */
ret = overlay_prevent_phandle_overwrite(fdt, fdto);
if (ret)
goto err;
ret = overlay_merge(fdt, fdto);
if (ret)
goto err;

View file

@ -53,7 +53,7 @@ const char *fdt_get_string(const void *fdt, int stroffset, int *lenp)
err = -FDT_ERR_BADOFFSET;
absoffset = stroffset + fdt_off_dt_strings(fdt);
if (absoffset >= (unsigned)totalsize)
if (absoffset >= totalsize)
goto fail;
len = totalsize - absoffset;
@ -61,19 +61,17 @@ const char *fdt_get_string(const void *fdt, int stroffset, int *lenp)
if (stroffset < 0)
goto fail;
if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
if ((unsigned)stroffset >= fdt_size_dt_strings(fdt))
if (stroffset >= fdt_size_dt_strings(fdt))
goto fail;
if ((fdt_size_dt_strings(fdt) - stroffset) < len)
len = fdt_size_dt_strings(fdt) - stroffset;
}
} else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
unsigned int sw_stroffset = -stroffset;
if ((stroffset >= 0) ||
(sw_stroffset > fdt_size_dt_strings(fdt)))
if ((stroffset >= 0)
|| (stroffset < -fdt_size_dt_strings(fdt)))
goto fail;
if (sw_stroffset < len)
len = sw_stroffset;
if ((-stroffset) < len)
len = -stroffset;
} else {
err = -FDT_ERR_INTERNAL;
goto fail;
@ -159,8 +157,8 @@ int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n)
{
unsigned int offset = n * sizeof(struct fdt_reserve_entry);
unsigned int absoffset = fdt_off_mem_rsvmap(fdt) + offset;
int offset = n * sizeof(struct fdt_reserve_entry);
int absoffset = fdt_off_mem_rsvmap(fdt) + offset;
if (!can_assume(VALID_INPUT)) {
if (absoffset < fdt_off_mem_rsvmap(fdt))
@ -181,8 +179,8 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
if (!can_assume(VALID_INPUT) && !re)
return -FDT_ERR_BADOFFSET;
*address = fdt64_ld_(&re->address);
*size = fdt64_ld_(&re->size);
*address = fdt64_ld(&re->address);
*size = fdt64_ld(&re->size);
return 0;
}
@ -192,7 +190,7 @@ int fdt_num_mem_rsv(const void *fdt)
const struct fdt_reserve_entry *re;
for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) {
if (fdt64_ld_(&re->size) == 0)
if (fdt64_ld(&re->size) == 0)
return i;
}
return -FDT_ERR_TRUNCATED;
@ -255,9 +253,6 @@ int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen)
FDT_RO_PROBE(fdt);
if (!can_assume(VALID_INPUT) && namelen <= 0)
return -FDT_ERR_BADPATH;
/* see if we have an alias */
if (*path != '/') {
const char *q = memchr(path, '/', end - p);
@ -373,7 +368,7 @@ static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt,
prop = fdt_offset_ptr_(fdt, offset);
if (lenp)
*lenp = fdt32_ld_(&prop->len);
*lenp = fdt32_ld(&prop->len);
return prop;
}
@ -411,7 +406,7 @@ static const struct fdt_property *fdt_get_property_namelen_(const void *fdt,
offset = -FDT_ERR_INTERNAL;
break;
}
if (fdt_string_eq_(fdt, fdt32_ld_(&prop->nameoff),
if (fdt_string_eq_(fdt, fdt32_ld(&prop->nameoff),
name, namelen)) {
if (poffset)
*poffset = offset;
@ -464,7 +459,7 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
/* Handle realignment */
if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
(poffset + sizeof(*prop)) % 8 && fdt32_ld_(&prop->len) >= 8)
(poffset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
return prop->data + 4;
return prop->data;
}
@ -482,22 +477,22 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
int namelen;
if (!can_assume(VALID_INPUT)) {
name = fdt_get_string(fdt, fdt32_ld_(&prop->nameoff),
name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff),
&namelen);
*namep = name;
if (!name) {
if (lenp)
*lenp = namelen;
return NULL;
}
*namep = name;
} else {
*namep = fdt_string(fdt, fdt32_ld_(&prop->nameoff));
*namep = fdt_string(fdt, fdt32_ld(&prop->nameoff));
}
}
/* Handle realignment */
if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
(offset + sizeof(*prop)) % 8 && fdt32_ld_(&prop->len) >= 8)
(offset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
return prop->data + 4;
return prop->data;
}
@ -522,34 +517,19 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
return 0;
}
return fdt32_ld_(php);
}
static const void *fdt_path_getprop_namelen(const void *fdt, const char *path,
const char *propname, int propnamelen,
int *lenp)
{
int offset = fdt_path_offset(fdt, path);
if (offset < 0)
return NULL;
return fdt_getprop_namelen(fdt, offset, propname, propnamelen, lenp);
return fdt32_ld(php);
}
const char *fdt_get_alias_namelen(const void *fdt,
const char *name, int namelen)
{
int len;
const char *alias;
int aliasoffset;
alias = fdt_path_getprop_namelen(fdt, "/aliases", name, namelen, &len);
if (!can_assume(VALID_DTB) &&
!(alias && len > 0 && alias[len - 1] == '\0' && *alias == '/'))
aliasoffset = fdt_path_offset(fdt, "/aliases");
if (aliasoffset < 0)
return NULL;
return alias;
return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL);
}
const char *fdt_get_alias(const void *fdt, const char *name)
@ -557,17 +537,6 @@ const char *fdt_get_alias(const void *fdt, const char *name)
return fdt_get_alias_namelen(fdt, name, strlen(name));
}
const char *fdt_get_symbol_namelen(const void *fdt,
const char *name, int namelen)
{
return fdt_path_getprop_namelen(fdt, "/__symbols__", name, namelen, NULL);
}
const char *fdt_get_symbol(const void *fdt, const char *name)
{
return fdt_get_symbol_namelen(fdt, name, strlen(name));
}
int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
{
int pdepth = 0, p = 0;
@ -711,7 +680,7 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
{
int offset;
if ((phandle == 0) || (phandle == ~0U))
if ((phandle == 0) || (phandle == -1))
return -FDT_ERR_BADPHANDLE;
FDT_RO_PROBE(fdt);

View file

@ -46,7 +46,7 @@ static int fdt_rw_probe_(void *fdt)
return err_; \
}
static inline unsigned int fdt_data_size_(void *fdt)
static inline int fdt_data_size_(void *fdt)
{
return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
}
@ -54,16 +54,15 @@ static inline unsigned int fdt_data_size_(void *fdt)
static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen)
{
char *p = splicepoint;
unsigned int dsize = fdt_data_size_(fdt);
size_t soff = p - (char *)fdt;
char *end = (char *)fdt + fdt_data_size_(fdt);
if ((oldlen < 0) || (soff + oldlen < soff) || (soff + oldlen > dsize))
if (((p + oldlen) < p) || ((p + oldlen) > end))
return -FDT_ERR_BADOFFSET;
if ((p < (char *)fdt) || (dsize + newlen < (unsigned)oldlen))
if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt))
return -FDT_ERR_BADOFFSET;
if (dsize - oldlen + newlen > fdt_totalsize(fdt))
if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt)))
return -FDT_ERR_NOSPACE;
memmove(p + newlen, p + oldlen, ((char *)fdt + dsize) - (p + oldlen));
memmove(p + newlen, p + oldlen, end - p - oldlen);
return 0;
}
@ -124,33 +123,31 @@ static int fdt_splice_string_(void *fdt, int newlen)
* allocated. Ignored if can_assume(NO_ROLLBACK)
* @return offset of string in the string table (whether found or added)
*/
static int fdt_find_add_string_(void *fdt, const char *s, int slen,
int *allocated)
static int fdt_find_add_string_(void *fdt, const char *s, int *allocated)
{
char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
const char *p;
char *new;
int len = strlen(s) + 1;
int err;
if (!can_assume(NO_ROLLBACK))
*allocated = 0;
p = fdt_find_string_len_(strtab, fdt_size_dt_strings(fdt), s, slen);
p = fdt_find_string_(strtab, fdt_size_dt_strings(fdt), s);
if (p)
/* found it */
return (p - strtab);
new = strtab + fdt_size_dt_strings(fdt);
err = fdt_splice_string_(fdt, slen + 1);
err = fdt_splice_string_(fdt, len);
if (err)
return err;
if (!can_assume(NO_ROLLBACK))
*allocated = 1;
memcpy(new, s, slen);
new[slen] = '\0';
memcpy(new, s, len);
return (new - strtab);
}
@ -183,15 +180,13 @@ int fdt_del_mem_rsv(void *fdt, int n)
return fdt_splice_mem_rsv_(fdt, re, 1, 0);
}
static int fdt_resize_property_(void *fdt, int nodeoffset,
const char *name, int namelen,
static int fdt_resize_property_(void *fdt, int nodeoffset, const char *name,
int len, struct fdt_property **prop)
{
int oldlen;
int err;
*prop = fdt_get_property_namelen_w(fdt, nodeoffset, name, namelen,
&oldlen);
*prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
if (!*prop)
return oldlen;
@ -204,7 +199,7 @@ static int fdt_resize_property_(void *fdt, int nodeoffset,
}
static int fdt_add_property_(void *fdt, int nodeoffset, const char *name,
int namelen, int len, struct fdt_property **prop)
int len, struct fdt_property **prop)
{
int proplen;
int nextoffset;
@ -215,7 +210,7 @@ static int fdt_add_property_(void *fdt, int nodeoffset, const char *name,
if ((nextoffset = fdt_check_node_offset_(fdt, nodeoffset)) < 0)
return nextoffset;
namestroff = fdt_find_add_string_(fdt, name, namelen, &allocated);
namestroff = fdt_find_add_string_(fdt, name, &allocated);
if (namestroff < 0)
return namestroff;
@ -259,18 +254,17 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name)
return 0;
}
int fdt_setprop_placeholder_namelen(void *fdt, int nodeoffset, const char *name,
int namelen, int len, void **prop_data)
int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name,
int len, void **prop_data)
{
struct fdt_property *prop;
int err;
FDT_RW_PROBE(fdt);
err = fdt_resize_property_(fdt, nodeoffset, name, namelen, len, &prop);
err = fdt_resize_property_(fdt, nodeoffset, name, len, &prop);
if (err == -FDT_ERR_NOTFOUND)
err = fdt_add_property_(fdt, nodeoffset, name, namelen, len,
&prop);
err = fdt_add_property_(fdt, nodeoffset, name, len, &prop);
if (err)
return err;
@ -278,14 +272,13 @@ int fdt_setprop_placeholder_namelen(void *fdt, int nodeoffset, const char *name,
return 0;
}
int fdt_setprop_namelen(void *fdt, int nodeoffset, const char *name,
int namelen, const void *val, int len)
int fdt_setprop(void *fdt, int nodeoffset, const char *name,
const void *val, int len)
{
void *prop_data;
int err;
err = fdt_setprop_placeholder_namelen(fdt, nodeoffset, name, namelen,
len, &prop_data);
err = fdt_setprop_placeholder(fdt, nodeoffset, name, len, &prop_data);
if (err)
return err;
@ -313,8 +306,7 @@ int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
prop->len = cpu_to_fdt32(newlen);
memcpy(prop->data + oldlen, val, len);
} else {
err = fdt_add_property_(fdt, nodeoffset, name, strlen(name),
len, &prop);
err = fdt_add_property_(fdt, nodeoffset, name, len, &prop);
if (err)
return err;
memcpy(prop->data, val, len);
@ -356,10 +348,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
return offset;
/* Try to place the new node after the parent's properties */
tag = fdt_next_tag(fdt, parentoffset, &nextoffset);
/* the fdt_subnode_offset_namelen() should ensure this never hits */
if (!can_assume(LIBFDT_FLAWLESS) && (tag != FDT_BEGIN_NODE))
return -FDT_ERR_INTERNAL;
fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */
do {
offset = nextoffset;
tag = fdt_next_tag(fdt, offset, &nextoffset);
@ -401,9 +390,7 @@ int fdt_del_node(void *fdt, int nodeoffset)
}
static void fdt_packblocks_(const char *old, char *new,
int mem_rsv_size,
int struct_size,
int strings_size)
int mem_rsv_size, int struct_size)
{
int mem_rsv_off, struct_off, strings_off;
@ -418,7 +405,8 @@ static void fdt_packblocks_(const char *old, char *new,
fdt_set_off_dt_struct(new, struct_off);
fdt_set_size_dt_struct(new, struct_size);
memmove(new + strings_off, old + fdt_off_dt_strings(old), strings_size);
memmove(new + strings_off, old + fdt_off_dt_strings(old),
fdt_size_dt_strings(old));
fdt_set_off_dt_strings(new, strings_off);
fdt_set_size_dt_strings(new, fdt_size_dt_strings(old));
}
@ -439,17 +427,15 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
struct_size = fdt_size_dt_struct(fdt);
} else if (fdt_version(fdt) == 16) {
} else {
struct_size = 0;
while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END)
;
if (struct_size < 0)
return struct_size;
} else {
return -FDT_ERR_BADVERSION;
}
if (can_assume(LIBFDT_ORDER) ||
if (can_assume(LIBFDT_ORDER) |
!fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) {
/* no further work necessary */
err = fdt_move(fdt, buf, bufsize);
@ -478,8 +464,7 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
return -FDT_ERR_NOSPACE;
}
fdt_packblocks_(fdt, tmp, mem_rsv_size, struct_size,
fdt_size_dt_strings(fdt));
fdt_packblocks_(fdt, tmp, mem_rsv_size, struct_size);
memmove(buf, tmp, newsize);
fdt_set_magic(buf, FDT_MAGIC);
@ -499,8 +484,7 @@ int fdt_pack(void *fdt)
mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
* sizeof(struct fdt_reserve_entry);
fdt_packblocks_(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt),
fdt_size_dt_strings(fdt));
fdt_packblocks_(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt));
fdt_set_totalsize(fdt, fdt_data_size_(fdt));
return 0;

View file

@ -39,9 +39,8 @@ static struct fdt_errtabent fdt_errtable[] = {
FDT_ERRTABENT(FDT_ERR_BADOVERLAY),
FDT_ERRTABENT(FDT_ERR_NOPHANDLES),
FDT_ERRTABENT(FDT_ERR_BADFLAGS),
FDT_ERRTABENT(FDT_ERR_ALIGNMENT),
};
#define FDT_ERRTABSIZE ((int)(sizeof(fdt_errtable) / sizeof(fdt_errtable[0])))
#define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))
const char *fdt_strerror(int errval)
{
@ -49,7 +48,7 @@ const char *fdt_strerror(int errval)
return "<valid offset/length>";
else if (errval == 0)
return "<no error>";
else if (-errval < FDT_ERRTABSIZE) {
else if (errval > -FDT_ERRTABSIZE) {
const char *s = fdt_errtable[-errval].str;
if (s)

View file

@ -32,7 +32,7 @@ static int fdt_sw_probe_(void *fdt)
/* 'memrsv' state: Initial state after fdt_create()
*
* Allowed functions:
* fdt_add_reservemap_entry()
* fdt_add_reservmap_entry()
* fdt_finish_reservemap() [moves to 'struct' state]
*/
static int fdt_sw_probe_memrsv_(void *fdt)
@ -93,8 +93,8 @@ static inline uint32_t sw_flags(void *fdt)
static void *fdt_grab_space_(void *fdt, size_t len)
{
unsigned int offset = fdt_size_dt_struct(fdt);
unsigned int spaceleft;
int offset = fdt_size_dt_struct(fdt);
int spaceleft;
spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt)
- fdt_size_dt_strings(fdt);
@ -108,8 +108,8 @@ static void *fdt_grab_space_(void *fdt, size_t len)
int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags)
{
const int hdrsize = FDT_ALIGN(sizeof(struct fdt_header),
sizeof(struct fdt_reserve_entry));
const size_t hdrsize = FDT_ALIGN(sizeof(struct fdt_header),
sizeof(struct fdt_reserve_entry));
void *fdt = buf;
if (bufsize < hdrsize)
@ -152,9 +152,6 @@ int fdt_resize(void *fdt, void *buf, int bufsize)
FDT_SW_PROBE(fdt);
if (bufsize < 0)
return -FDT_ERR_NOSPACE;
headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
tailsize = fdt_size_dt_strings(fdt);
@ -162,7 +159,7 @@ int fdt_resize(void *fdt, void *buf, int bufsize)
headsize + tailsize > fdt_totalsize(fdt))
return -FDT_ERR_INTERNAL;
if ((headsize + tailsize) > (unsigned)bufsize)
if ((headsize + tailsize) > bufsize)
return -FDT_ERR_NOSPACE;
oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize;
@ -250,18 +247,18 @@ int fdt_end_node(void *fdt)
static int fdt_add_string_(void *fdt, const char *s)
{
char *strtab = (char *)fdt + fdt_totalsize(fdt);
unsigned int strtabsize = fdt_size_dt_strings(fdt);
unsigned int len = strlen(s) + 1;
unsigned int struct_top, offset;
int strtabsize = fdt_size_dt_strings(fdt);
int len = strlen(s) + 1;
int struct_top, offset;
offset = strtabsize + len;
offset = -strtabsize - len;
struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
if (fdt_totalsize(fdt) - offset < struct_top)
if (fdt_totalsize(fdt) + offset < struct_top)
return 0; /* no more room :( */
memcpy(strtab - offset, s, len);
memcpy(strtab + offset, s, len);
fdt_set_size_dt_strings(fdt, strtabsize + len);
return -offset;
return offset;
}
/* Must only be used to roll back in case of error */
@ -377,7 +374,7 @@ int fdt_finish(void *fdt)
fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
/* And fix up fields that were keeping intermediate state. */
fdt_set_last_comp_version(fdt, FDT_LAST_COMPATIBLE_VERSION);
fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
fdt_set_magic(fdt, FDT_MAGIC);
return 0;

View file

@ -23,7 +23,7 @@ int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
if (!propval)
return proplen;
if ((unsigned)proplen < (len + idx))
if (proplen < (len + idx))
return -FDT_ERR_NOSPACE;
memcpy((char *)propval + idx, val, len);

File diff suppressed because it is too large Load diff

View file

@ -66,4 +66,31 @@ static inline fdt64_t cpu_to_fdt64(uint64_t x)
#undef CPU_TO_FDT16
#undef EXTRACT_BYTE
#ifdef __APPLE__
#include <AvailabilityMacros.h>
/* strnlen() is not available on Mac OS < 10.7 */
# if !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED < \
MAC_OS_X_VERSION_10_7)
#define strnlen fdt_strnlen
/*
* fdt_strnlen: returns the length of a string or max_count - which ever is
* smallest.
* Input 1 string: the string whose size is to be determined
* Input 2 max_count: the maximum value returned by this function
* Output: length of the string or max_count (the smallest of the two)
*/
static inline size_t fdt_strnlen(const char *string, size_t max_count)
{
const char *p = memchr(string, 0, max_count);
return p ? p - string : max_count;
}
#endif /* !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED <
MAC_OS_X_VERSION_10_7) */
#endif /* __APPLE__ */
#endif /* LIBFDT_ENV_H */

View file

@ -20,15 +20,7 @@ int32_t fdt_ro_probe_(const void *fdt);
int fdt_check_node_offset_(const void *fdt, int offset);
int fdt_check_prop_offset_(const void *fdt, int offset);
const char *fdt_find_string_len_(const char *strtab, int tabsize, const char *s,
int s_len);
static inline const char *fdt_find_string_(const char *strtab, int tabsize,
const char *s)
{
return fdt_find_string_len_(strtab, tabsize, s, strlen(s));
}
const char *fdt_find_string_(const char *strtab, int tabsize, const char *s);
int fdt_node_end_offset_(void *fdt, int nodeoffset);
static inline const void *fdt_offset_ptr_(const void *fdt, int offset)
@ -54,25 +46,6 @@ static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n)
return (void *)(uintptr_t)fdt_mem_rsv_(fdt, n);
}
/*
* Internal helpers to access structural elements of the device tree
* blob (rather than for example reading integers from within property
* values). We assume that we are either given a naturally aligned
* address for the platform or if we are not, we are on a platform
* where unaligned memory reads will be handled in a graceful manner.
* If not the external helpers fdtXX_ld() from libfdt.h can be used
* instead.
*/
static inline uint32_t fdt32_ld_(const fdt32_t *p)
{
return fdt32_to_cpu(*p);
}
static inline uint64_t fdt64_ld_(const fdt64_t *p)
{
return fdt64_to_cpu(*p);
}
#define FDT_SW_MAGIC (~FDT_MAGIC)
/**********************************************************************/

View file

@ -1,63 +0,0 @@
version_script = '-Wl,--version-script=@0@'.format(meson.current_source_dir() / 'version.lds')
if not cc.has_link_argument(version_script)
version_script = []
endif
sources = files(
'fdt.c',
'fdt_addresses.c',
'fdt_check.c',
'fdt_empty_tree.c',
'fdt_overlay.c',
'fdt_ro.c',
'fdt_rw.c',
'fdt_strerror.c',
'fdt_sw.c',
'fdt_wip.c',
)
link_args = []
if cc.has_link_argument('-Wl,--no-undefined')
link_args += '-Wl,--no-undefined'
else
# -undefined error is the equivalent of --no-undefined for the macOS linker,
# but -undefined would also be understood as a valid argument for GNU ld!
link_args += cc.get_supported_link_arguments('-Wl,-undefined,error')
endif
link_args += version_script
libfdt = library(
'fdt', sources,
version: meson.project_version(),
link_args: link_args,
link_depends: 'version.lds',
install: get_option('default_library') != 'static' or not wheel_only,
)
libfdt_inc = include_directories('.')
libfdt_dep = declare_dependency(
include_directories: libfdt_inc,
link_with: libfdt,
)
meson.override_dependency('libfdt', libfdt_dep)
if not wheel_only
install_headers(
files(
'fdt.h',
'libfdt.h',
'libfdt_env.h',
)
)
pkgconfig = import('pkgconfig')
pkgconfig.generate(
libraries: libfdt,
version: meson.project_version(),
filebase: 'libfdt',
name: 'libfdt',
description: 'Flat Device Tree manipulation',
)
endif

View file

@ -1,43 +0,0 @@
{
"bomFormat": "CycloneDX",
"specVersion": "1.6",
"version": 1,
"metadata": {
"authors": [
{
"name": "@VCS_SBOM_AUTHORS@"
}
]
},
"components": [
{
"type": "library",
"bom-ref": "pkg:github/dgibson/libfdt@@VCS_TAG@",
"cpe": "cpe:2.3:a:dgibson:libfdt:@VCS_TAG@:*:*:*:*:*:*:*",
"name": "libfdt",
"version": "@VCS_VERSION@",
"description": "Utility library for reading and manipulating the FDT binary format",
"supplier": {
"name": "libfdt developers"
},
"licenses": [
{
"license": {
"id": "BSD-2-Clause"
}
},
{
"license": {
"id": "GPL-2.0-or-later"
}
}
],
"externalReferences": [
{
"type": "vcs",
"url": "https://github.com/dgibson/dtc"
}
]
}
]
}

View file

@ -20,7 +20,7 @@ LIBFDT_1.2 {
fdt_get_alias_namelen;
fdt_get_alias;
fdt_get_path;
fdt_header_size;
fdt_header_size;
fdt_supernode_atdepth_offset;
fdt_node_depth;
fdt_parent_offset;
@ -43,7 +43,6 @@ LIBFDT_1.2 {
fdt_add_mem_rsv;
fdt_del_mem_rsv;
fdt_set_name;
fdt_setprop_namelen;
fdt_setprop;
fdt_delprop;
fdt_add_subnode_namelen;
@ -72,16 +71,12 @@ LIBFDT_1.2 {
fdt_find_max_phandle;
fdt_generate_phandle;
fdt_check_full;
fdt_setprop_placeholder_namelen;
fdt_setprop_placeholder;
fdt_property_placeholder;
fdt_header_size_;
fdt_appendprop_addrrange;
fdt_setprop_inplace_namelen_partial;
fdt_create_with_flags;
fdt_overlay_target_offset;
fdt_get_symbol;
fdt_get_symbol_namelen;
local:
*;
};

View file

@ -36,27 +36,27 @@ void delete_labels(struct label **labels)
label->deleted = 1;
}
struct property *build_property(const char *name, struct data val,
struct property *build_property(char *name, struct data val,
struct srcpos *srcpos)
{
struct property *new = xmalloc(sizeof(*new));
memset(new, 0, sizeof(*new));
new->name = xstrdup(name);
new->name = name;
new->val = val;
new->srcpos = srcpos_copy(srcpos);
return new;
}
struct property *build_property_delete(const char *name)
struct property *build_property_delete(char *name)
{
struct property *new = xmalloc(sizeof(*new));
memset(new, 0, sizeof(*new));
new->name = xstrdup(name);
new->name = name;
new->deleted = 1;
return new;
@ -116,11 +116,11 @@ struct node *build_node_delete(struct srcpos *srcpos)
return new;
}
struct node *name_node(struct node *node, const char *name)
struct node *name_node(struct node *node, char *name)
{
assert(node->name == NULL);
node->name = xstrdup(name);
node->name = name;
return node;
}
@ -174,7 +174,7 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
old_prop->val = new_prop->val;
old_prop->deleted = 0;
srcpos_free(old_prop->srcpos);
free(old_prop->srcpos);
old_prop->srcpos = new_prop->srcpos;
free(new_prop);
new_prop = NULL;
@ -250,7 +250,6 @@ struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref)
name_node(new_node, "__overlay__");
node = build_node(p, new_node, NULL);
name_node(node, name);
free(name);
add_child(dt, node);
return dt;
@ -340,73 +339,20 @@ void append_to_property(struct node *node,
char *name, const void *data, int len,
enum markertype type)
{
struct property *p;
p = get_property(node, name);
if (!p) {
p = build_property(name, empty_data, NULL);
add_property(node, p);
}
p->val = data_add_marker(p->val, type, name);
p->val = data_append_data(p->val, data, len);
}
static int append_unique_str_to_property(struct node *node,
char *name, const char *data, int len)
{
struct data d;
struct property *p;
p = get_property(node, name);
if (p) {
const char *s;
if (p->val.len && p->val.val[p->val.len - 1] != '\0')
/* The current content doesn't look like a string */
return -1;
for (s = p->val.val; s < p->val.val + p->val.len; s = strchr(s, '\0') + 1) {
if (strcmp(data, s) == 0)
/* data already contained in node.name */
return 0;
}
d = data_add_marker(p->val, type, name);
d = data_append_data(d, data, len);
p->val = d;
} else {
p = build_property(name, empty_data, NULL);
d = data_add_marker(empty_data, type, name);
d = data_append_data(d, data, len);
p = build_property(name, d, NULL);
add_property(node, p);
}
p->val = data_add_marker(p->val, TYPE_STRING, name);
p->val = data_append_data(p->val, data, len);
return 0;
}
static int append_unique_u32_to_property(struct node *node, char *name, fdt32_t value)
{
struct property *p;
p = get_property(node, name);
if (p) {
const fdt32_t *v, *val_end = (const fdt32_t *)p->val.val + p->val.len / 4;
if (p->val.len % 4 != 0)
/* The current content doesn't look like a u32 array */
return -1;
for (v = (const void *)p->val.val; v < val_end; v++) {
if (*v == value)
/* value already contained */
return 0;
}
} else {
p = build_property(name, empty_data, NULL);
add_property(node, p);
}
p->val = data_add_marker(p->val, TYPE_UINT32, name);
p->val = data_append_data(p->val, &value, 4);
return 0;
}
struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
@ -492,9 +438,9 @@ cell_t propval_cell(struct property *prop)
return fdt32_to_cpu(*((fdt32_t *)prop->val.val));
}
cell_t propval_cell_n(struct property *prop, unsigned int n)
cell_t propval_cell_n(struct property *prop, int n)
{
assert(prop->val.len / sizeof(cell_t) > n);
assert(prop->val.len / sizeof(cell_t) >= n);
return fdt32_to_cpu(*((fdt32_t *)prop->val.val + n));
}
@ -557,7 +503,7 @@ struct node *get_subnode(struct node *node, const char *nodename)
struct node *child;
for_each_child(node, child)
if (streq(child->name, nodename) && !child->deleted)
if (streq(child->name, nodename))
return child;
return NULL;
@ -580,7 +526,7 @@ struct node *get_node_by_path(struct node *tree, const char *path)
p = strchr(path, '/');
for_each_child(tree, child) {
if (p && strprefixeq(path, (size_t)(p - path), child->name))
if (p && strprefixeq(path, p - path, child->name))
return get_node_by_path(child, p+1);
else if (!p && streq(path, child->name))
return child;
@ -613,7 +559,7 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
{
struct node *child, *node;
if (!phandle_is_valid(phandle)) {
if ((phandle == 0) || (phandle == -1)) {
assert(generate_fixups);
return NULL;
}
@ -635,62 +581,20 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
struct node *get_node_by_ref(struct node *tree, const char *ref)
{
struct node *target = tree;
const char *label = NULL, *path = NULL;
if (streq(ref, "/"))
return tree;
if (ref[0] == '/')
path = ref;
else if (ref[0] == '/')
return get_node_by_path(tree, ref);
else
label = ref;
if (label) {
const char *slash = strchr(label, '/');
char *buf = NULL;
if (slash) {
buf = xstrndup(label, slash - label);
label = buf;
path = slash + 1;
}
target = get_node_by_label(tree, label);
free(buf);
if (!target)
return NULL;
}
if (path)
target = get_node_by_path(target, path);
return target;
}
static void add_phandle_property(struct node *node,
const char *name, int format)
{
struct data d;
if (!(phandle_format & format))
return;
if (get_property(node, name))
return;
d = data_add_marker(empty_data, TYPE_UINT32, NULL);
d = data_append_cell(d, node->phandle);
add_property(node, build_property(name, d, NULL));
return get_node_by_label(tree, ref);
}
cell_t get_node_phandle(struct node *root, struct node *node)
{
static cell_t phandle = 1; /* FIXME: ick, static local */
struct data d = empty_data;
if (phandle_is_valid(node->phandle))
if ((node->phandle != 0) && (node->phandle != -1))
return node->phandle;
while (get_node_by_phandle(root, phandle))
@ -698,8 +602,16 @@ cell_t get_node_phandle(struct node *root, struct node *node)
node->phandle = phandle;
add_phandle_property(node, "linux,phandle", PHANDLE_LEGACY);
add_phandle_property(node, "phandle", PHANDLE_EPAPR);
d = data_add_marker(d, TYPE_UINT32, NULL);
d = data_append_cell(d, phandle);
if (!get_property(node, "linux,phandle")
&& (phandle_format & PHANDLE_LEGACY))
add_property(node, build_property("linux,phandle", d, NULL));
if (!get_property(node, "phandle")
&& (phandle_format & PHANDLE_EPAPR))
add_property(node, build_property("phandle", d, NULL));
/* If the node *does* have a phandle property, we must
* be dealing with a self-referencing phandle, which will be
@ -869,18 +781,18 @@ void sort_tree(struct dt_info *dti)
}
/* utility helper to avoid code duplication */
static struct node *build_and_name_child_node(struct node *parent, const char *name)
static struct node *build_and_name_child_node(struct node *parent, char *name)
{
struct node *node;
node = build_node(NULL, NULL, NULL);
name_node(node, name);
name_node(node, xstrdup(name));
add_child(parent, node);
return node;
}
static struct node *build_root_node(struct node *dt, const char *name)
static struct node *build_root_node(struct node *dt, char *name)
{
struct node *an;
@ -971,61 +883,47 @@ static bool any_fixup_tree(struct dt_info *dti, struct node *node)
return false;
}
static int add_fixup_entry(struct dt_info *dti, struct node *fn,
struct node *node, struct property *prop,
struct marker *m)
static void add_fixup_entry(struct dt_info *dti, struct node *fn,
struct node *node, struct property *prop,
struct marker *m)
{
char *entry;
int ret;
/* m->ref can only be a REF_PHANDLE, but check anyway */
assert(m->type == REF_PHANDLE);
/* The format only permits fixups for references to label, not
* references to path */
if (strchr(m->ref, '/'))
die("Can't generate fixup for reference to path &{%s}\n",
m->ref);
/* there shouldn't be any ':' in the arguments */
if (strchr(node->fullpath, ':') || strchr(prop->name, ':'))
die("arguments should not contain ':'\n");
xasprintf(&entry, "%s:%s:%u",
node->fullpath, prop->name, m->offset);
ret = append_unique_str_to_property(fn, m->ref, entry, strlen(entry) + 1);
append_to_property(fn, m->ref, entry, strlen(entry) + 1, TYPE_STRING);
free(entry);
return ret;
}
static int generate_fixups_tree_internal(struct dt_info *dti,
struct node *fn,
struct node *node)
static void generate_fixups_tree_internal(struct dt_info *dti,
struct node *fn,
struct node *node)
{
struct node *dt = dti->dt;
struct node *c;
struct property *prop;
struct marker *m;
struct node *refnode;
int ret = 0;
for_each_property(node, prop) {
m = prop->val.markers;
for_each_marker_of_type(m, REF_PHANDLE) {
refnode = get_node_by_ref(dt, m->ref);
if (!refnode)
if (add_fixup_entry(dti, fn, node, prop, m))
ret = -1;
add_fixup_entry(dti, fn, node, prop, m);
}
}
for_each_child(node, c)
if (generate_fixups_tree_internal(dti, fn, c))
ret = -1;
return ret;
generate_fixups_tree_internal(dti, fn, c);
}
static bool any_local_fixup_tree(struct dt_info *dti, struct node *node)
@ -1050,7 +948,7 @@ static bool any_local_fixup_tree(struct dt_info *dti, struct node *node)
return false;
}
static int add_local_fixup_entry(struct dt_info *dti,
static void add_local_fixup_entry(struct dt_info *dti,
struct node *lfn, struct node *node,
struct property *prop, struct marker *m,
struct node *refnode)
@ -1075,44 +973,41 @@ static int add_local_fixup_entry(struct dt_info *dti,
/* walk the path components creating nodes if they don't exist */
for (wn = lfn, i = 1; i < depth; i++, wn = nwn) {
/* if no node exists, create it */
nwn = build_root_node(wn, compp[i]);
nwn = get_subnode(wn, compp[i]);
if (!nwn)
nwn = build_and_name_child_node(wn, compp[i]);
}
free(compp);
value_32 = cpu_to_fdt32(m->offset);
return append_unique_u32_to_property(wn, prop->name, value_32);
append_to_property(wn, prop->name, &value_32, sizeof(value_32), TYPE_UINT32);
}
static int generate_local_fixups_tree_internal(struct dt_info *dti,
struct node *lfn,
struct node *node)
static void generate_local_fixups_tree_internal(struct dt_info *dti,
struct node *lfn,
struct node *node)
{
struct node *dt = dti->dt;
struct node *c;
struct property *prop;
struct marker *m;
struct node *refnode;
int ret = 0;
for_each_property(node, prop) {
m = prop->val.markers;
for_each_marker_of_type(m, REF_PHANDLE) {
refnode = get_node_by_ref(dt, m->ref);
if (refnode)
if (add_local_fixup_entry(dti, lfn, node, prop, m, refnode))
ret = -1;
add_local_fixup_entry(dti, lfn, node, prop, m, refnode);
}
}
for_each_child(node, c)
if (generate_local_fixups_tree_internal(dti, lfn, c))
ret = -1;
return ret;
generate_local_fixups_tree_internal(dti, lfn, c);
}
void generate_label_tree(struct dt_info *dti, const char *name, bool allocph)
void generate_label_tree(struct dt_info *dti, char *name, bool allocph)
{
if (!any_label_tree(dti, dti->dt))
return;
@ -1120,22 +1015,18 @@ void generate_label_tree(struct dt_info *dti, const char *name, bool allocph)
dti->dt, allocph);
}
void generate_fixups_tree(struct dt_info *dti, const char *name)
void generate_fixups_tree(struct dt_info *dti, char *name)
{
if (!any_fixup_tree(dti, dti->dt))
return;
if (generate_fixups_tree_internal(dti, build_root_node(dti->dt, name), dti->dt))
fprintf(stderr,
"Warning: Preexisting data in %s malformed, some content could not be added.\n",
name);
generate_fixups_tree_internal(dti, build_root_node(dti->dt, name),
dti->dt);
}
void generate_local_fixups_tree(struct dt_info *dti, const char *name)
void generate_local_fixups_tree(struct dt_info *dti, char *name)
{
if (!any_local_fixup_tree(dti, dti->dt))
return;
if (generate_local_fixups_tree_internal(dti, build_root_node(dti->dt, name), dti->dt))
fprintf(stderr,
"Warning: Preexisting data in %s malformed, some content could not be added.\n",
name);
generate_local_fixups_tree_internal(dti, build_root_node(dti->dt, name),
dti->dt);
}

View file

@ -1,131 +0,0 @@
project('dtc', 'c',
version: files('VERSION.txt'),
license: ['GPL2+', 'BSD-2'],
default_options: ['werror=true', 'default_library=both'],
meson_version: '>=0.57.0'
)
cc = meson.get_compiler('c')
add_project_arguments(
cc.get_supported_arguments([
'-Wpointer-arith',
'-Wcast-qual',
'-Wnested-externs',
'-Wstrict-prototypes',
'-Wmissing-prototypes',
'-Wredundant-decls',
'-Wshadow',
'-Wsuggest-attribute=format',
'-Wwrite-strings',
]),
language: 'c'
)
add_project_arguments(
'-DFDT_ASSUME_MASK=' + get_option('assume-mask').to_string(),
language: 'c'
)
yamltree = 'yamltree.c'
yaml = dependency('yaml-0.1', version: '>=0.2.3', required: get_option('yaml'))
if not yaml.found()
add_project_arguments('-DNO_YAML', language: 'c')
yamltree = []
endif
valgrind = dependency('valgrind', required: get_option('valgrind'))
if not valgrind.found()
add_project_arguments('-DNO_VALGRIND', language: 'c')
endif
py = import('python')
py = py.find_installation(required: get_option('python'))
swig = find_program('swig', required: get_option('python'))
pylibfdt_enabled = not meson.is_cross_build() and py.found() and swig.found() ? true : false
wheel_only = get_option('wheel-only')
version_gen_h = vcs_tag(
command: ['git', 'describe', '--dirty=+'],
input: 'version_gen.h.in',
output: 'version_gen.h',
)
subdir('libfdt')
dtc_tools = []
util_dep = declare_dependency(
sources: ['util.c', version_gen_h],
include_directories: '.',
dependencies: libfdt_dep
)
if get_option('tools') and not wheel_only
flex = find_program('flex', required: true)
bison = find_program('bison', required: true)
lgen = generator(
flex,
output: '@PLAINNAME@.lex.c',
arguments: ['-o', '@OUTPUT@', '@INPUT@'],
)
pgen = generator(
bison,
output: ['@BASENAME@.tab.c', '@BASENAME@.tab.h'],
arguments: ['@INPUT@', '--defines=@OUTPUT1@', '--output=@OUTPUT0@'],
)
if cc.check_header('fnmatch.h')
dtc_tools += executable(
'convert-dtsv0',
[
lgen.process('convert-dtsv0-lexer.l'),
'srcpos.c',
],
dependencies: util_dep,
install: true,
)
endif
dtc_tools += executable(
'dtc',
[
lgen.process('dtc-lexer.l'),
pgen.process('dtc-parser.y'),
'checks.c',
'data.c',
'dtc.c',
'flattree.c',
'fstree.c',
'livetree.c',
'srcpos.c',
'treesource.c',
yamltree,
],
dependencies: [util_dep, yaml],
install: true,
)
foreach e: ['fdtdump', 'fdtget', 'fdtput', 'fdtoverlay']
dtc_tools += executable(e, files(e + '.c'), dependencies: util_dep, install: true)
endforeach
install_data(
'dtdiff',
install_dir: get_option('bindir'),
install_mode: 'rwxr-xr-x',
)
endif
foreach e: dtc_tools
meson.override_find_program(e.name(), e)
endforeach
if pylibfdt_enabled
subdir('pylibfdt')
endif
if get_option('tests')
subdir('tests')
endif

View file

@ -1,14 +0,0 @@
option('tools', type: 'boolean', value: true,
description: 'Build tools')
option('assume-mask', type: 'integer', value: 0,
description: 'Control the assumptions made (e.g. risking security issues) in the code.')
option('yaml', type: 'feature', value: 'auto',
description: 'YAML support')
option('valgrind', type: 'feature', value: 'auto',
description: 'Valgrind support')
option('python', type: 'feature', value: 'auto',
description: 'Build pylibfdt Python library')
option('tests', type: 'boolean', value: true,
description: 'Build tests')
option('wheel-only', type: 'boolean', value: false,
description: 'building from meson-python')

View file

@ -0,0 +1,30 @@
# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
# Makefile.pylibfdt
#
PYLIBFDT_srcs = $(PYLIBFDT_dir)/libfdt.i
PYMODULE = $(PYLIBFDT_dir)/_libfdt.so
PYLIBFDT_CLEANFILES_L = libfdt_wrap.c libfdt.py *.pyc *.so
PYLIBFDT_CLEANFILES = $(PYLIBFDT_CLEANFILES_L:%=$(PYLIBFDT_dir)/%)
PYLIBFDT_CLEANDIRS_L = build __pycache__
PYLIBFDT_CLEANDIRS = $(PYLIBFDT_CLEANDIRS_L:%=$(PYLIBFDT_dir)/%)
SETUP = $(PYLIBFDT_dir)/setup.py
SETUPFLAGS =
ifndef V
SETUPFLAGS += --quiet
endif
$(PYMODULE): $(PYLIBFDT_srcs) $(LIBFDT_archive) $(SETUP) $(VERSION_FILE)
@$(VECHO) PYMOD $@
$(PYTHON) $(SETUP) $(SETUPFLAGS) build_ext --build-lib=../$(PYLIBFDT_dir)
install_pylibfdt: $(PYMODULE)
@$(VECHO) INSTALL-PYLIB
$(PYTHON) $(SETUP) $(SETUPFLAGS) install --prefix=$(PREFIX)
pylibfdt_clean:
@$(VECHO) CLEAN "(pylibfdt)"
rm -f $(PYLIBFDT_CLEANFILES)
rm -rf $(PYLIBFDT_CLEANDIRS)

View file

@ -114,14 +114,11 @@ def check_err_null(val, quiet=()):
FdtException if val indicates an error was reported and the error
is not in @quiet.
"""
# Compatibility for SWIG v4.2 and earlier. SWIG 4.2 would drop the first
# item from the list if it was None, returning only the second item.
# Normally a list is returned which contains the data and its length.
# If we get just an integer error code, it means the function failed.
if not isinstance(val, list):
val = [None, val]
if val[0] is None:
if -val[1] not in quiet:
raise FdtException(val[1])
if -val not in quiet:
raise FdtException(val)
return val
class FdtRo(object):
@ -162,7 +159,7 @@ class FdtRo(object):
quiet: Errors to ignore (empty to raise on all errors)
Returns:
Tuple:
Typle:
Offset of the next node, if any, else a -ve error
Depth of the returned node, if any, else undefined
@ -298,9 +295,7 @@ class FdtRo(object):
Returns:
Number of memory reserve-map records
"""
val = fdt_get_mem_rsv(self._fdt, index)
check_err(val[0], quiet)
return val[1:]
return check_err(fdt_get_mem_rsv(self._fdt, index), quiet)
def subnode_offset(self, parentoffset, name, quiet=()):
"""Get the offset of a named subnode
@ -398,8 +393,8 @@ class FdtRo(object):
"""
pdata = check_err_null(
fdt_get_property_by_offset(self._fdt, prop_offset), quiet)
if pdata[0] is None:
return pdata[1]
if isinstance(pdata, (int)):
return pdata
return Property(pdata[0], pdata[1])
def getprop(self, nodeoffset, prop_name, quiet=()):
@ -420,39 +415,10 @@ class FdtRo(object):
"""
pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name),
quiet)
if pdata[0] is None:
return pdata[1]
if isinstance(pdata, (int)):
return pdata
return Property(prop_name, bytearray(pdata[0]))
def hasprop(self, nodeoffset, prop_name, quiet=()):
"""Check if a node has a property
This can be used to check boolean properties
Args:
nodeoffset: Node offset containing property to check
prop_name: Name of property to check
quiet: Errors to ignore (empty to raise on all errors). Note that
NOTFOUND is added internally by this function so need not be
provided
Returns:
True if the property exists in the node, else False. If an error
other than -NOTFOUND is returned by fdt_getprop() then the error
is return (-ve integer)
Raises:
FdtError if any error occurs other than NOTFOUND (e.g. the
nodeoffset is invalid)
"""
pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name),
quiet + (NOTFOUND,))
if pdata[0] is None:
if pdata[1] == -NOTFOUND:
return False
return pdata[1]
return True
def get_phandle(self, nodeoffset):
"""Get the phandle of a node
@ -477,29 +443,6 @@ class FdtRo(object):
"""
return fdt_get_alias(self._fdt, name)
def get_path(self, nodeoffset, size_hint=1024, quiet=()):
"""Get the full path of a node
Args:
nodeoffset: Node offset to check
size_hint: Hint for size of returned string
Returns:
Full path to the node
Raises:
FdtException if an error occurs
"""
while True:
ret, path = fdt_get_path(self._fdt, nodeoffset, size_hint)
if ret == -NOSPACE:
size_hint *= 2
continue
err = check_err(ret, quiet)
if err:
return err
return path
def parent_offset(self, nodeoffset, quiet=()):
"""Get the offset of a node's parent
@ -639,32 +582,6 @@ class Fdt(FdtRo):
return check_err(fdt_setprop(self._fdt, nodeoffset, prop_name, val,
len(val)), quiet)
def setprop_bool(self, nodeoffset, prop_name, val, quiet=()):
"""Set the boolean value of a property
Either:
adds the property if not already present; or
deletes the property if present
Args:
nodeoffset: Node offset containing the property to create/delete
prop_name: Name of property
val: Boolean value to write (i.e. True or False)
quiet: Errors to ignore (empty to raise on all errors)
Returns:
Error code, or 0 if OK
Raises:
FdtException if no parent found or other error occurs
"""
exists = self.hasprop(nodeoffset, prop_name, quiet)
if val != exists:
if val:
return self.setprop(nodeoffset, prop_name, b'', quiet=quiet)
else:
return self.delprop(nodeoffset, prop_name, quiet=quiet)
def setprop_u32(self, nodeoffset, prop_name, val, quiet=()):
"""Set the value of a property
@ -799,21 +716,6 @@ class Property(bytearray):
def as_int64(self):
return self.as_cell('q')
def as_list(self, fmt):
return list(map(lambda x: x[0], struct.iter_unpack('>' + fmt, self)))
def as_uint32_list(self):
return self.as_list('L')
def as_int32_list(self):
return self.as_list('l')
def as_uint64_list(self):
return self.as_list('Q')
def as_int64_list(self):
return self.as_list('q')
def as_str(self):
"""Unicode is supported by decoding from UTF-8"""
if self[-1] != 0:
@ -822,13 +724,6 @@ class Property(bytearray):
raise ValueError('Property contains embedded nul characters')
return self[:-1].decode('utf-8')
def as_stringlist(self):
"""Unicode is supported by decoding from UTF-8"""
if self[-1] != 0:
raise ValueError('Property lacks nul termination')
parts = self[:-1].split(b'\x00')
return list(map(lambda x: x.decode('utf-8'), parts))
class FdtSw(FdtRo):
"""Software interface to create a device tree from scratch
@ -1096,9 +991,6 @@ class NodeAdder():
%rename(fdt_property) fdt_property_func;
%immutable fdt_property::data;
%immutable fdt_node_header::name;
/*
* fdt32_t is a big-endian 32-bit value defined to uint32_t in libfdt_env.h
* so use the same type here.
@ -1117,7 +1009,7 @@ typedef uint32_t fdt32_t;
}
$1 = (void *)PyByteArray_AsString($input);
fdt = $1;
(void)fdt; /* avoid unused variable warning */
fdt = fdt; /* avoid unused variable warning */
}
/* Some functions do change the device tree, so use void * */
@ -1128,7 +1020,7 @@ typedef uint32_t fdt32_t;
}
$1 = PyByteArray_AsString($input);
fdt = $1;
(void)fdt; /* avoid unused variable warning */
fdt = fdt; /* avoid unused variable warning */
}
/* typemap used for fdt_get_property_by_offset() */
@ -1140,7 +1032,7 @@ typedef uint32_t fdt32_t;
fdt_string(fdt1, fdt32_to_cpu($1->nameoff)));
buff = PyByteArray_FromStringAndSize(
(const char *)($1 + 1), fdt32_to_cpu($1->len));
resultobj = SWIG_AppendOutput(resultobj, buff);
resultobj = SWIG_Python_AppendOutput(resultobj, buff);
}
}
@ -1148,16 +1040,14 @@ typedef uint32_t fdt32_t;
/* typemap used for fdt_getprop() */
%typemap(out) (const void *) {
if (!$1) {
if (!$1)
$result = Py_None;
Py_INCREF($result);
} else {
else
%#if PY_VERSION_HEX >= 0x03000000
$result = Py_BuildValue("y#", $1, (Py_ssize_t)*arg4);
$result = Py_BuildValue("y#", $1, *arg4);
%#else
$result = Py_BuildValue("s#", $1, (Py_ssize_t)*arg4);
$result = Py_BuildValue("s#", $1, *arg4);
%#endif
}
}
/* typemap used for fdt_setprop() */
@ -1181,7 +1071,7 @@ typedef uint32_t fdt32_t;
%typemap(argout) int *depth {
PyObject *val = Py_BuildValue("i", *arg$argnum);
resultobj = SWIG_AppendOutput(resultobj, val);
resultobj = SWIG_Python_AppendOutput(resultobj, val);
}
%apply int *depth { int *depth };
@ -1193,14 +1083,14 @@ typedef uint32_t fdt32_t;
%typemap(argout) uint64_t * {
PyObject *val = PyLong_FromUnsignedLongLong(*arg$argnum);
resultobj = SWIG_AppendOutput(resultobj, val);
if (!result) {
if (PyTuple_GET_SIZE(resultobj) == 0)
resultobj = val;
else
resultobj = SWIG_Python_AppendOutput(resultobj, val);
}
}
%include "cstring.i"
%cstring_output_maxsize(char *buf, int buflen);
int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen);
/* We have both struct fdt_property and a function fdt_property() */
%warnfilter(302) fdt_property;

View file

@ -1,21 +0,0 @@
libfdt_c = custom_target(
'swig',
input: 'libfdt.i',
output: ['libfdt.c', 'libfdt.py'],
install: true,
install_dir: [false, py.get_install_dir(pure: false)],
command: [swig, '-python', '-I'+meson.current_source_dir() / '../libfdt', '-o', '@OUTPUT0@', '@INPUT@']
)
nowarn_gen = cc.get_supported_arguments(
'-Wno-cast-qual',
'-Wno-missing-prototypes',
'-Wno-redundant-decls',
)
pylibfdt = py.extension_module(
'_libfdt',
libfdt_c,
c_args: ['-DPY_SSIZE_T_CLEAN'] + nowarn_gen,
dependencies: [libfdt_dep, py.dependency()],
install: true,
)

48
pylibfdt/setup.py Executable file
View file

@ -0,0 +1,48 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
# While Python 3 is the default, it's also possible to invoke
# this setup.py script with Python 2.
"""
setup.py file for SWIG libfdt
Copyright (C) 2017 Google, Inc.
Written by Simon Glass <sjg@chromium.org>
"""
from distutils.core import setup, Extension
import os
import re
import sys
VERSION_PATTERN = '^#define DTC_VERSION "DTC ([^"]*)"$'
def get_version():
version_file = "../version_gen.h"
f = open(version_file, 'rt')
m = re.match(VERSION_PATTERN, f.readline())
return m.group(1)
setupdir = os.path.dirname(os.path.abspath(sys.argv[0]))
os.chdir(setupdir)
libfdt_module = Extension(
'_libfdt',
sources=['libfdt.i'],
include_dirs=['../libfdt'],
libraries=['fdt'],
library_dirs=['../libfdt'],
swig_opts=['-I../libfdt'],
)
setup(
name='libfdt',
version=get_version(),
author='Simon Glass <sjg@chromium.org>',
description='Python binding for libfdt',
ext_modules=[libfdt_module],
py_modules=['libfdt'],
)

View file

@ -1,33 +0,0 @@
[build-system]
build-backend = 'mesonpy'
requires = ['meson-python']
[project]
name = 'libfdt'
authors = [
{name = 'Simon Glass', email = 'sjg@chromium.org'},
]
classifiers = [
'Programming Language :: Python :: 3',
'License :: OSI Approved :: BSD License',
'License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)',
'Operating System :: OS Independent',
]
description = 'Python binding for libfdt'
readme = 'README.md'
requires-python = '>=3.8'
dynamic = ['version']
[project.urls]
'homepage' = 'https://git.kernel.org/pub/scm/utils/dtc/dtc.git'
# These arguments are applied only when building a redistributable binary wheel
# for uploading to PyPI. We don't want to install libraries (or headers /
# pkgconfig files / executables) that clash with system C installs, so we
# disable everything other than the python bindings themselves, and build the
# python C-API extension using static linkage to avoid juggling "libdir" /
# LD_LIBRARY_PATH / RPATH around. When building both the C library and the
# python bindings for a distro, `meson setup` will still default to shared
# libraries.
[tool.meson-python.args]
setup = ['-Ddefault_library=static', '-Dwheel-only=true']

View file

@ -1,32 +0,0 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later
if [ -f /etc/os-release ]
then
. /etc/os-release
else
echo "ERROR: OS name is not provided."
exit 1
fi
if [ "$NAME" = "Arch Linux" ]
then
pacman -Syu --needed --noconfirm bison diffutils flex gcc git libyaml \
make meson pkgconf python python-setuptools-scm swig
elif [ "$NAME" = "Alpine Linux" ]
then
apk add build-base bison flex git yaml yaml-dev python3-dev \
meson py3-setuptools_scm swig
elif [ "$NAME" = "Fedora Linux" ]
then
dnf install -y bison diffutils flex gcc git libyaml libyaml-devel \
make meson python3-devel python3-setuptools swig
elif [ "$NAME" = "Ubuntu" ]
then
apt update
apt install -yq build-essential bison flex git libyaml-dev pkg-config \
meson python3-dev python3-setuptools python3-setuptools-scm swig
else
echo "ERROR: OS name is not provided."
exit 1
fi

View file

@ -3,9 +3,7 @@
* Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc.
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stdio.h>
@ -22,7 +20,7 @@ struct search_path {
static struct search_path *search_path_head, **search_path_tail;
/* Detect infinite include recursion. */
#define MAX_SRCFILE_DEPTH (200)
#define MAX_SRCFILE_DEPTH (100)
static int srcfile_depth; /* = 0 */
static char *get_dirname(const char *path)
@ -88,26 +86,6 @@ static char *shorten_to_initial_path(char *fname)
return NULL;
}
/**
* Returns true if the given path is an absolute one.
*
* On Windows, it either needs to begin with a forward slash or with a drive
* letter (e.g. "C:").
* On all other operating systems, it must begin with a forward slash to be
* considered an absolute path.
*/
static bool is_absolute_path(const char *path)
{
#ifdef WIN32
return (
path[0] == '/' ||
(((path[0] >= 'A' && path[0] <= 'Z') || (path[0] >= 'a' && path[0] <= 'z')) && path[1] == ':')
);
#else
return (path[0] == '/');
#endif
}
/**
* Try to open a file in a given directory.
*
@ -123,7 +101,7 @@ static char *try_open(const char *dirname, const char *fname, FILE **fp)
{
char *fullname;
if (!dirname || is_absolute_path(fname))
if (!dirname || fname[0] == '/')
fullname = xstrdup(fname);
else
fullname = join_path(dirname, fname);
@ -180,10 +158,8 @@ FILE *srcfile_relative_open(const char *fname, char **fullnamep)
strerror(errno));
}
if (depfile) {
fputc(' ', depfile);
fprint_path_escaped(depfile, fullname);
}
if (depfile)
fprintf(depfile, " %s", fullname);
if (fullnamep)
*fullnamep = fullname;
@ -307,17 +283,6 @@ struct srcpos *srcpos_extend(struct srcpos *pos, struct srcpos *newtail)
return pos;
}
void srcpos_free(struct srcpos *pos)
{
struct srcpos *p_next;
while (pos) {
p_next = pos->next;
free(pos);
pos = p_next;
}
}
char *
srcpos_string(struct srcpos *pos)
{
@ -346,8 +311,8 @@ srcpos_string(struct srcpos *pos)
static char *
srcpos_string_comment(struct srcpos *pos, bool first_line, int level)
{
char *pos_str, *fresh_fname = NULL, *first, *rest;
const char *fname;
char *pos_str, *fname, *first, *rest;
bool fresh_fname = false;
if (!pos) {
if (level > 1) {
@ -365,9 +330,9 @@ srcpos_string_comment(struct srcpos *pos, bool first_line, int level)
else if (level > 1)
fname = pos->file->name;
else {
fresh_fname = shorten_to_initial_path(pos->file->name);
if (fresh_fname)
fname = fresh_fname;
fname = shorten_to_initial_path(pos->file->name);
if (fname)
fresh_fname = true;
else
fname = pos->file->name;
}
@ -381,7 +346,7 @@ srcpos_string_comment(struct srcpos *pos, bool first_line, int level)
first_line ? pos->first_line : pos->last_line);
if (fresh_fname)
free(fresh_fname);
free(fname);
if (pos->next != NULL) {
rest = srcpos_string_comment(pos->next, first_line, level);

View file

@ -88,7 +88,6 @@ extern void srcpos_update(struct srcpos *pos, const char *text, int len);
extern struct srcpos *srcpos_copy(struct srcpos *pos);
extern struct srcpos *srcpos_extend(struct srcpos *new_srcpos,
struct srcpos *old_srcpos);
extern void srcpos_free(struct srcpos *pos);
extern char *srcpos_string(struct srcpos *pos);
extern char *srcpos_string_first(struct srcpos *pos, int level);
extern char *srcpos_string_last(struct srcpos *pos, int level);

2
tests/.gitignore vendored
View file

@ -54,7 +54,6 @@ tmp.*
/property_iterate
/propname_escapes
/references
/relref_merge
/root_node
/rw_tree1
/rw_oom
@ -74,4 +73,3 @@ tmp.*
/truncated_memrsv
/utilfdt_test
/value-labels
/get_next_tag_invalid_prop_len

View file

@ -4,7 +4,7 @@ LIB_TESTS_L = get_mem_rsv \
get_path supernode_atdepth_offset parent_offset \
node_offset_by_prop_value node_offset_by_phandle \
node_check_compatible node_offset_by_compatible \
get_alias get_next_tag_invalid_prop_len \
get_alias \
char_literal \
sized_cells \
notfound \
@ -18,7 +18,7 @@ LIB_TESTS_L = get_mem_rsv \
open_pack rw_tree1 rw_oom set_name setprop del_property del_node \
appendprop1 appendprop2 propname_escapes \
string_escapes references path-references phandle_format \
boot-cpuid incbin relref_merge \
boot-cpuid incbin \
extra-terminating-null \
dtbs_equal_ordered \
dtb_reverse dtbs_equal_unordered \
@ -33,19 +33,14 @@ LIB_TESTS_L = get_mem_rsv \
LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%)
LIBTREE_TESTS_L = truncated_property truncated_string truncated_memrsv
LIBTREE_TESTS = $(LIBTREE_TESTS_L:%=$(TESTS_PREFIX)%)
ifneq ($(STATIC_BUILD),1)
DL_LIB_TESTS_L = asm_tree_dump value-labels
DL_LIB_TESTS = $(DL_LIB_TESTS_L:%=$(TESTS_PREFIX)%)
endif
DL_LIB_TESTS_L = asm_tree_dump value-labels
DL_LIB_TESTS = $(DL_LIB_TESTS_L:%=$(TESTS_PREFIX)%)
TESTS = $(LIB_TESTS) $(LIBTREE_TESTS) $(DL_LIB_TESTS)
TESTS_TREES_L = test_tree1.dtb bad_node_char.dtb bad_node_format.dtb \
bad_prop_char.dtb ovf_size_strings.dtb truncated_property.dtb \
truncated_string.dtb truncated_memrsv.dtb two_roots.dtb named_root.dtb
TESTS_TREES_L = test_tree1.dtb
TESTS_TREES = $(TESTS_TREES_L:%=$(TESTS_PREFIX)%)
TESTS_TARGETS = $(TESTS) $(TESTS_TREES)
@ -63,17 +58,17 @@ TESTS_CLEANDIRS = $(TESTS_CLEANDIRS_L:%=$(TESTS_PREFIX)%)
.PHONY: tests
tests: $(TESTS) $(TESTS_TREES)
$(LIB_TESTS): %: $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_dep)
$(LIB_TESTS): %: $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_lib)
# Not necessary on all platforms; allow -ldl to be excluded instead of forcing
# other platforms to patch it out.
LIBDL = -ldl
$(DL_LIB_TESTS): %: %.o $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_dep)
$(DL_LIB_TESTS): %: %.o $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_lib)
@$(VECHO) LD [libdl] $@
$(LINK.c) -o $@ $^ $(LIBDL)
$(LIBTREE_TESTS): %: $(TESTS_PREFIX)testutils.o $(TESTS_PREFIX)trees.o \
util.o $(LIBFDT_dep)
util.o $(LIBFDT_lib)
$(TESTS_PREFIX)dumptrees: $(TESTS_PREFIX)trees.o

View file

@ -5,10 +5,6 @@
#size-cells = <0>;
aliases {
empty = "";
loop = "loop";
nonull = [626164];
relative = "s1/subsubnode";
s1 = &sub1;
ss1 = &subsub1;
sss1 = &subsubsub1;

View file

@ -36,7 +36,6 @@ int main(int argc, char *argv[])
buf = xmalloc(SPACE);
CHECK(fdt_open_into(fdt, buf, SPACE));
free(fdt);
fdt = buf;
CHECK(fdt_appendprop(fdt, 0, "prop-bytes", bytes, sizeof(bytes)));

View file

@ -36,7 +36,7 @@ int main(int argc, char *argv[])
err = fdt_open_into(fdt, buf, 0x1000);
if (err)
FAIL("fdt_open_into(): %s", fdt_strerror(err));
free(fdt);
fdt = buf;
/* Set up */

View file

@ -1,22 +0,0 @@
/dts-v1/;
/ {
bar: bar {
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
bar_con: endpoint {
remote-endpoint = <&foo_con>;
};
};
};
};
foo {
port {
foo_con: endpoint {
remote-endpoint = <&bar_con>;
};
};
};
};

View file

@ -1,36 +0,0 @@
/dts-v1/;
/ {
bar: bar {
ports {
#address-cells = <1>;
#size-cells = <1>; // should always be 0
port@1 {
reg = <1 2>; // should always contain only a single cell
bar_con: endpoint {
remote-endpoint = <&foo_con>;
};
};
port@2 {
reg = <2>;
bar_con2: endpoint {
remote-endpoint = <&foo_con2>;
};
};
};
};
foo {
port {
#address-cells = <1>;
#size-cells = <1>; // should always be 0
foo_con: endpoint@1 {
reg = <1 2>; // should always contain only a single cell
remote-endpoint = <&bar_con>;
};
foo_con2: endpoint@2 {
reg = <2>;
remote-endpoint = <&bar_con2>;
};
};
};
};

View file

@ -1,7 +0,0 @@
/dts-v1/;
/ {
foo {
remote-endpoint = <0xdeadbeef>;
};
};

View file

@ -1,2 +0,0 @@
/dts-v1/;
/ { endpoint {}; };

View file

@ -1,14 +0,0 @@
/dts-v1/;
/ {
bar: bar {
port {
bar_con: endpoint {
remote-endpoint = <&foo_con>;
};
};
};
foo_con: endpoint {
remote-endpoint = <&bar_con>;
};
};

View file

@ -1,19 +0,0 @@
/dts-v1/;
/ {
bar: bar {
port {
bar_con: endpoint {
remote-endpoint = <&foo_con>;
};
};
};
foo {
remote-endpoint = <&bar_con>; // misplaced remote-endpoint property
port {
foo_con: endpoint {
};
};
};
};

View file

@ -1,7 +0,0 @@
/dts-v1/;
/ {
intc: interrupt-controller {
interrupt-controller;
};
};

View file

@ -1,20 +0,0 @@
/dts-v1/;
/ {
interrupt-parent = <&intc>;
intc: interrupt-controller {
#interrupt-cells = <3>;
interrupt-controller;
};
node {
#address-cells = <0>;
#interrupt-cells = <1>;
interrupt-map = <1 &intc 1 2 3>;
interrupt-map-mask = <0 0>;
child {
interrupts = <1>;
};
};
};

View file

@ -1,17 +0,0 @@
/dts-v1/;
/ {
interrupt-parent = <&intc>;
intc: interrupt-controller {
};
node {
#address-cells = <0>;
#interrupt-cells = <1>;
interrupt-map = <1 &intc 1 2 3>;
child {
interrupts = <1>;
};
};
};

View file

@ -1,19 +0,0 @@
/dts-v1/;
/ {
interrupt-parent = <&intc>;
intc: interrupt-controller {
#interrupt-cells = <3>;
interrupt-controller;
};
node {
/* Missing #address-cells = <0>; */
#interrupt-cells = <1>;
interrupt-map = <1 &intc 1 2 3>;
child {
interrupts = <1>;
};
};
};

View file

@ -32,7 +32,7 @@ _dt_reserve_map:
dt_struct_start:
_dt_struct_start:
.long OF_DT_BEGIN_NODE
.asciz ""
.string ""
.balign 4
.long OF_DT_PROP
.long 0xa
@ -58,7 +58,7 @@ _dt_struct_start:
.long 0x2
.balign 4
.long OF_DT_BEGIN_NODE
.asciz "memory@0"
.string "memory@0"
.balign 4
.long OF_DT_PROP
.long 0x7
@ -77,7 +77,7 @@ _dt_struct_start:
.balign 4
.long OF_DT_END_NODE
.long OF_DT_BEGIN_NODE
.asciz "cpus"
.string "cpus"
.balign 4
.long OF_DT_PROP
.long 0x4
@ -151,22 +151,22 @@ _dt_struct_end:
.globl dt_strings_start
dt_strings_start:
_dt_strings_start:
.asciz "model"
.asciz "compatible"
.asciz "#address-cells"
.asciz "#size-cells"
.asciz "device_type"
.asciz "reg"
.asciz "d10"
.asciz "d23"
.asciz "b101"
.asciz "o17"
.asciz "hd00d"
.asciz "stuff"
.asciz "bad-d-1"
.asciz "bad-d-2"
.asciz "bad-o-1"
.asciz "bad-o-2"
.string "model"
.string "compatible"
.string "#address-cells"
.string "#size-cells"
.string "device_type"
.string "reg"
.string "d10"
.string "d23"
.string "b101"
.string "o17"
.string "hd00d"
.string "stuff"
.string "bad-d-1"
.string "bad-d-2"
.string "bad-o-1"
.string "bad-o-2"
.globl dt_strings_end
dt_strings_end:
_dt_strings_end:

View file

@ -1,7 +0,0 @@
/dts-v1/;
/ {
prop1 = < 0 >;
prop2 = < 0xffffffff >;
prop3 = < 0 >;
};

View file

@ -1,7 +0,0 @@
/dts-v1/;
/ {
prop1 = < (-0xffffffff - 1) >;
prop2 = < (-0xffffffff - 2) >;
prop3 = < ((-0xffffffff - 1) * 2) >;
};

View file

@ -32,7 +32,6 @@ static void *open_dt(char *path)
* Resize our DTs to 4k so that we have room to operate on
*/
CHECK(fdt_open_into(dt, copy, FDT_COPY_SIZE));
free(dt);
return copy;
}

View file

@ -25,7 +25,7 @@
prop7;
/* yet
* another
* multiline
* multline
* comment
*/
prop8;

View file

@ -18,16 +18,15 @@
int main(int argc, char *argv[])
{
void *fdt, *blob;
void *fdt;
int subnode1_offset, subnode2_offset, subsubnode2_offset;
int err;
int oldsize, delsize, newsize;
test_init(argc, argv);
blob = load_blob_arg(argc, argv);
fdt = load_blob_arg(argc, argv);
fdt = open_blob_rw(blob);
free(blob);
fdt = open_blob_rw(fdt);
oldsize = fdt_totalsize(fdt);

View file

@ -18,17 +18,16 @@
int main(int argc, char *argv[])
{
void *fdt, *blob;
void *fdt;
const uint32_t *intp;
const char *strp;
int err, lenerr;
int oldsize, delsize, newsize;
test_init(argc, argv);
blob = load_blob_arg(argc, argv);
fdt = load_blob_arg(argc, argv);
fdt = open_blob_rw(blob);
free(blob);
fdt = open_blob_rw(fdt);
oldsize = fdt_totalsize(fdt);
@ -74,6 +73,5 @@ int main(int argc, char *argv[])
if (newsize >= oldsize)
FAIL("Tree failed to shrink after deletions");
free(fdt);
PASS();
}

View file

@ -24,15 +24,13 @@ static struct {
TREE(ovf_size_strings),
TREE(truncated_property), TREE(truncated_string),
TREE(truncated_memrsv),
TREE(two_roots),
TREE(named_root)
};
#define NUM_TREES (sizeof(trees) / sizeof(trees[0]))
int main(int argc, char *argv[])
{
unsigned int i;
int i;
if (argc != 2) {
fprintf(stderr, "Missing output directory argument\n");

View file

@ -9,7 +9,7 @@ rm -f $LOG $EXPECT
trap "rm -f $LOG $EXPECT" 0
expect="$1"
printf "$expect\n" > $EXPECT
printf '%b\n' "$expect" > $EXPECT
shift
verbose_run_log_check "$LOG" $VALGRIND $DTGET "$@"

View file

@ -1,6 +0,0 @@
/dts-v1/;
/plugin/;
/ {
prop = < &{/path/to/node} >;
};

View file

@ -54,7 +54,7 @@ static void mkfile(const char *name, void *data, size_t len)
rc = write(fd, data, len);
if (rc < 0)
FAIL("write(\"%s\"): %s", name, strerror(errno));
if ((unsigned)rc != len)
if (rc != len)
FAIL("write(\"%s\"): short write", name);
rc = close(fd);

View file

@ -21,16 +21,9 @@ static void check_alias(void *fdt, const char *path, const char *alias)
aliaspath = fdt_get_alias(fdt, alias);
if (!path && !aliaspath)
return;
if (!aliaspath)
if (path && !aliaspath)
FAIL("fdt_get_alias(%s) failed\n", alias);
if (!path)
FAIL("fdt_get_alias(%s) returned %s instead of NULL",
alias, aliaspath);
if (strcmp(aliaspath, path) != 0)
FAIL("fdt_get_alias(%s) returned %s instead of %s\n",
alias, aliaspath, path);
@ -43,14 +36,9 @@ int main(int argc, char *argv[])
test_init(argc, argv);
fdt = load_blob_arg(argc, argv);
check_alias(fdt, NULL, "empty");
check_alias(fdt, NULL, "nonull");
check_alias(fdt, NULL, "relative");
check_alias(fdt, "/subnode@1", "s1");
check_alias(fdt, "/subnode@1/subsubnode", "ss1");
check_alias(fdt, "/subnode@1/subsubnode/subsubsubnode", "sss1");
check_alias(fdt, NULL, "loop"); // Might trigger a stack overflow
PASS();
}

View file

@ -34,14 +34,12 @@ static void check_name(void *fdt, const char *path)
offset, getname, len);
if (!getname)
FAIL("fdt_get_name(%d): %s", offset, fdt_strerror(len));
if (len < 0)
FAIL("negative name length (%d) for returned node name\n", len);
if (strcmp(getname, checkname) != 0)
FAIL("fdt_get_name(%s) returned \"%s\" instead of \"%s\"",
path, getname, checkname);
if ((unsigned)len != strlen(getname))
if (len != strlen(getname))
FAIL("fdt_get_name(%s) returned length %d instead of %zd",
path, len, strlen(getname));

View file

@ -1,100 +0,0 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_next_tag()
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <libfdt.h>
#include "tests.h"
#include "testdata.h"
#define FDT_SIZE 65536
#define CHECK_ERR(err) \
({ if (err) \
FAIL("%s: %d: %s", __FILE__, __LINE__, fdt_strerror(err)); \
})
static void fdt_next_tag_test(bool fdt_finished)
{
struct fdt_property *prp;
void *fdt;
int nextoff = 0, offset, err;
uint32_t tag;
fdt = malloc(FDT_SIZE);
if (!fdt)
FAIL("Can't allocate memory");
err = fdt_create(fdt, FDT_SIZE);
CHECK_ERR(err);
err = fdt_finish_reservemap(fdt);
CHECK_ERR(err);
/* Create a root node and add two properties */
err = fdt_begin_node(fdt, "");
CHECK_ERR(err);
err = fdt_property_u32(fdt, "prop-int-32", 0x1234);
CHECK_ERR(err);
err = fdt_property_u32(fdt, "prop2-int-32", 0x4321);
CHECK_ERR(err);
err = fdt_end_node(fdt);
CHECK_ERR(err);
if (fdt_finished) {
/* Call fdt_finish to set the correct fdt state. */
err = fdt_finish(fdt);
CHECK_ERR(err);
}
offset = fdt_first_property_offset(fdt, 0);
if (offset <= 0)
FAIL("Invalid offset %x, expected value greater than 0, finished=%d\n",
offset, fdt_finished);
/* Normal case */
tag = fdt_next_tag(fdt, offset, &nextoff);
if (tag != FDT_PROP)
FAIL("Invalid tag %x, expected FDT_PROP, finished=%d\n",
tag, fdt_finished);
if (nextoff <= 0)
FAIL("Invalid nextoff %d, expected value greater than 0, finished=%d",
nextoff, fdt_finished);
/* Get a writable ptr to the first property and corrupt the length */
prp = fdt_get_property_by_offset_w(fdt, offset, NULL);
if (!prp)
FAIL("Bad property pointer, finished=%d", fdt_finished);
/* int overflow case */
prp->len = cpu_to_fdt32(0xFFFFFFFA);
tag = fdt_next_tag(fdt, offset, &nextoff);
if (tag != FDT_END)
FAIL("Invalid tag %x, expected premature FDT_END, finished=%d",
tag, fdt_finished);
if (nextoff != -FDT_ERR_BADSTRUCTURE)
FAIL("Invalid nextoff, expected error -FDT_ERR_BADSTRUCTURE, finished=%d",
fdt_finished);
/* negative offset case */
prp->len = cpu_to_fdt32(0x7FFFFFFA);
tag = fdt_next_tag(fdt, offset, &nextoff);
if (tag != FDT_END)
FAIL("Invalid tag %x, expected premature FDT_END, finished=%d",
tag, fdt_finished);
if (nextoff != -FDT_ERR_BADSTRUCTURE)
FAIL("Invalid nextoff, expected -FDT_ERR_BADSTRUCTURE, finished=%d",
fdt_finished);
free(fdt);
}
int main(int argc, char *argv[])
{
test_init(argc, argv);
fdt_next_tag_test(false);
fdt_next_tag_test(true);
PASS();
}

View file

@ -1,12 +0,0 @@
/dts-v1/;
/ {
gpio: gpio-controller {
#gpio-cells = <3>;
};
node {
foo,nr-gpios = <1>;
foo-gpios = <&gpio 1 2 3>;
};
};

View file

@ -59,7 +59,7 @@ int main(int argc, char *argv[])
void *fdt;
const fdt32_t *res;
int reslen;
unsigned int i;
int i;
test_init(argc, argv);

View file

@ -1,163 +0,0 @@
trees = static_library('trees', files('trees.S'),
build_by_default: false,
include_directories: libfdt_inc)
dumptrees = executable('dumptrees', files('dumptrees.c'),
build_by_default: false,
link_with: trees, dependencies: libfdt_dep)
dumptrees_dtb = custom_target(
'dumptrees',
command: [dumptrees, meson.current_build_dir()],
output: [
'test_tree1.dtb',
'bad_node_char.dtb',
'bad_node_format.dtb',
'bad_prop_char.dtb',
'ovf_size_strings.dtb',
'truncated_property.dtb',
'truncated_string.dtb',
'truncated_memrsv.dtb',
]
)
testutil_dep = declare_dependency(sources: ['testutils.c'], link_with: trees)
tests = [
'add_subnode_with_nops',
'addr_size_cells',
'addr_size_cells2',
'appendprop1',
'appendprop2',
'appendprop_addrrange',
'boot-cpuid',
'char_literal',
'check_full',
'check_header',
'check_path',
'del_node',
'del_property',
'dtb_reverse',
'dtbs_equal_ordered',
'dtbs_equal_unordered',
'extra-terminating-null',
'find_property',
'fs_tree1',
'get_alias',
'get_mem_rsv',
'get_name',
'get_path',
'get_phandle',
'get_prop_offset',
'get_next_tag_invalid_prop_len',
'getprop',
'incbin',
'integer-expressions',
'mangle-layout',
'move_and_save',
'node_check_compatible',
'node_offset_by_compatible',
'node_offset_by_phandle',
'node_offset_by_prop_value',
'nop_node',
'nop_property',
'nopulate',
'notfound',
'open_pack',
'overlay',
'overlay_bad_fixup',
'parent_offset',
'path-references',
'path_offset',
'path_offset_aliases',
'phandle_format',
'property_iterate',
'propname_escapes',
'references',
'relref_merge',
'root_node',
'rw_oom',
'rw_tree1',
'set_name',
'setprop',
'setprop_inplace',
'sized_cells',
'string_escapes',
'stringlist',
'subnode_iterate',
'subnode_offset',
'supernode_atdepth_offset',
'sw_states',
'sw_tree1',
'utilfdt_test',
]
tests += [
'truncated_memrsv',
'truncated_property',
'truncated_string',
]
test_deps = [testutil_dep, util_dep, libfdt_dep]
dl = cc.find_library('dl', required: false)
if dl.found()
tests += [
'asm_tree_dump',
'value-labels',
]
test_deps += [dl]
endif
tests_exe = []
foreach t: tests
tests_exe += executable(t, files(t + '.c'), dependencies: test_deps, build_by_default: false)
endforeach
run_tests = find_program('run_tests.sh')
env = []
if not py.found()
env += 'NO_PYTHON=1'
else
env += [
'PYTHON=' + py.full_path(),
'PYTHONPATH=' + meson.project_source_root() / 'pylibfdt',
'NO_PYTHON=0',
]
endif
if not yaml.found()
env += 'NO_YAML=1'
else
env += 'NO_YAML=0'
endif
run_test_types = [
'libfdt',
'utilfdt',
'dtc',
'dtbs_equal',
'fdtget',
'fdtput',
'fdtdump',
'fdtoverlay'
]
run_test_deps = [
dtc_tools, dumptrees_dtb, tests_exe
]
if pylibfdt_enabled
run_test_types += 'pylibfdt'
run_test_deps += pylibfdt
endif
foreach test_type : run_test_types
test(
test_type,
run_tests,
args: ['-t', test_type],
is_parallel: false,
workdir: meson.current_build_dir(),
depends: run_test_deps,
env: env,
timeout: 1800, # mostly for valgrind
)
endforeach

View file

@ -43,8 +43,7 @@ static int nopulate_struct(char *buf, const char *fdt)
int main(int argc, char *argv[])
{
char *fdt, *fdt2, *buf;
int newsize, struct_end_old, struct_end_new, delta;
unsigned int struct_start;
int newsize, struct_start, struct_end_old, struct_end_new, delta;
const char *inname;
char outname[PATH_MAX];
@ -65,7 +64,7 @@ int main(int argc, char *argv[])
verbose_printf("Nopulated structure block has new size %d\n", newsize);
/* Replace old structure block with the new */
/* Replace old strcutre block with the new */
fdt2 = xmalloc(fdt_totalsize(fdt) + newsize);

View file

@ -35,11 +35,7 @@ static int fdt_getprop_u32_by_poffset(void *fdt, const char *path,
return node_off;
val = fdt_getprop(fdt, node_off, name, &len);
if (val && len < 0)
FAIL("fdt_getprop() returns negative length");
if (!val && len < 0)
return len;
if (!val || ((unsigned)len < (sizeof(uint32_t) * (poffset + 1))))
if (!val || (len < (sizeof(uint32_t) * (poffset + 1))))
return -FDT_ERR_NOTFOUND;
*out = fdt32_to_cpu(*(val + poffset));
@ -186,7 +182,6 @@ static void *open_dt(char *path)
* Resize our DTs to 4k so that we have room to operate on
*/
CHECK(fdt_open_into(dt, copy, FDT_COPY_SIZE));
free(dt);
return copy;
}

View file

@ -1,21 +0,0 @@
/*
* Copyright (c) 2024 Uwe Kleine-König
*
* SPDX-License-Identifier: GPL-2.0+
*/
/dts-v1/;
/ {
node_a: a {
value = <17>;
};
node_b: b {
a = <&node_a>;
};
node_d: d {
b = <&node_b>;
};
};

View file

@ -46,7 +46,3 @@
new-sub-test-property;
};
};
&{/new-local-node} {
another-new-property;
};

View file

@ -72,14 +72,6 @@
};
};
fragment@7 {
target-path = "/new-local-node";
__overlay__ {
another-new-property;
};
};
__local_fixups__ {
fragment@5 {
__overlay__ {

View file

@ -48,7 +48,7 @@
};
};
fragment@4 {
fragment@5 {
target = <&test>;
__overlay__ {
@ -58,7 +58,7 @@
};
};
fragment@5 {
fragment@6 {
target = <&test>;
__overlay__ {
@ -66,7 +66,7 @@
};
};
fragment@6 {
fragment@7 {
target = <&test>;
__overlay__ {
@ -74,7 +74,7 @@
};
};
fragment@7 {
fragment@8 {
target = <&test>;
__overlay__ {

View file

@ -1,34 +0,0 @@
/*
* Copyright (c) 2024 Uwe Kleine-König
*
* SPDX-License-Identifier: GPL-2.0+
*/
/dts-v1/;
/plugin/;
&{/} {
/*
* /b already has a label "node_b" in the base dts, also b is already
* referenced in the base, so both the base's b and this b have a
* phandle value.
*/
node_b2: b {
value = <42>;
d = <&node_d>;
};
node_c: c {
value = <23>;
b = <&node_b2>;
};
d {
a = <&node_a>;
c = <&node_c>;
};
};
&node_a {
value = <32>;
};

View file

@ -53,7 +53,7 @@ int main(int argc, char *argv[])
void *fdt;
const char *p;
int len, multilen;
int n1, n2, n3, n4, n5;
int n1, n2, n3, n4;
test_init(argc, argv);
fdt = load_blob_arg(argc, argv);
@ -89,12 +89,6 @@ int main(int argc, char *argv[])
check_ref(fdt, n3, "/foobar/baz");
check_ref(fdt, n4, "/foo/baz");
n5 = fdt_path_offset(fdt, "/bar/baz");
if (n5 < 0)
FAIL("fdt_path_offset(/bar/baz): %s", fdt_strerror(n5));
check_ref(fdt, n5, "/bar/baz");
check_rref(fdt);
PASS();

View file

@ -25,13 +25,4 @@
lref = &n3;
};
};
n5: bar {
baz {
};
};
};
n6: &{n5/baz} {
ref = &{n6/};
lref = &{n5/baz};
};

View file

@ -41,25 +41,22 @@ static int check_subnode(void *fdt, int parent, const char *name)
return offset;
}
static void check_path_offset(void *fdt, const char *path, int offset)
static void check_path_offset(void *fdt, char *path, int offset)
{
int rc;
verbose_printf("Checking offset of \"%s\" is %d...\n", path, offset);
rc = fdt_path_offset(fdt, path);
if (rc == offset)
return;
if (rc < 0)
FAIL("fdt_path_offset(\"%s\") failed: %s",
path, fdt_strerror(rc));
else
if (rc != offset)
FAIL("fdt_path_offset(\"%s\") returned incorrect offset"
" %d instead of %d", path, rc, offset);
}
static void check_path_offset_namelen(void *fdt, const char *path, int namelen,
static void check_path_offset_namelen(void *fdt, char *path, int namelen,
int offset)
{
int rc;
@ -105,7 +102,6 @@ int main(int argc, char *argv[])
check_path_offset(fdt, "/subnode@2/subsubnode", subsubnode2_offset2);
/* Test paths with extraneous separators */
check_path_offset(fdt, "", -FDT_ERR_BADPATH);
check_path_offset(fdt, "//", 0);
check_path_offset(fdt, "///", 0);
check_path_offset(fdt, "//subnode@1", subnode1_offset);
@ -114,8 +110,6 @@ int main(int argc, char *argv[])
check_path_offset(fdt, "/subnode@2////subsubnode", subsubnode2_offset2);
/* Test fdt_path_offset_namelen() */
check_path_offset_namelen(fdt, "/subnode@1", -1, -FDT_ERR_BADPATH);
check_path_offset_namelen(fdt, "/subnode@1", 0, -FDT_ERR_BADPATH);
check_path_offset_namelen(fdt, "/subnode@1", 1, 0);
check_path_offset_namelen(fdt, "/subnode@1/subsubnode", 10, subnode1_offset);
check_path_offset_namelen(fdt, "/subnode@1/subsubnode", 11, subnode1_offset);

Some files were not shown because too many files have changed in this diff Show more