Compare commits

..

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

122 changed files with 1198 additions and 3599 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

6
.gitignore vendored
View file

@ -3,7 +3,6 @@
*.a
*.patch
*.so
*.so.*
*~
*.bak
*.tab.[ch]
@ -23,8 +22,3 @@ lex.yy.c
# 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 <loeliger@gmail.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)

111
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 = 1
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,11 +54,7 @@ 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
@ -68,8 +62,6 @@ else
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 +69,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 +98,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,6 +153,29 @@ 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)
@ -186,13 +198,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 +210,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 +226,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 +241,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 +261,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 +274,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,6 +317,9 @@ TESTS_BIN += fdtput
TESTS_BIN += fdtget
TESTS_BIN += fdtdump
TESTS_BIN += fdtoverlay
ifeq ($(NO_PYTHON),0)
TESTS_PYLIBFDT += maybe_pylibfdt
endif
ifneq ($(MAKECMDGOALS),libfdt)
include tests/Makefile.tests
@ -306,7 +331,7 @@ endif
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 +351,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 +377,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 <loeliger@gmail.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

245
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, ...) \
@ -208,7 +207,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 +226,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 +254,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)
@ -313,7 +312,7 @@ ERROR(duplicate_property_names, check_duplicate_property_names, NULL);
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",
@ -387,7 +386,7 @@ 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",
@ -404,7 +403,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 +520,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 +579,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);
@ -718,14 +717,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 '-'");
}
@ -896,7 +892,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)",
@ -1027,7 +1023,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;
@ -1082,11 +1078,10 @@ static void check_i2c_bus_reg(struct check *c, struct dt_info *dti, struct node
/* Ignore I2C_OWN_SLAVE_ADDRESS */
reg &= ~I2C_OWN_SLAVE_ADDRESS;
if (reg & I2C_TEN_BIT_ADDRESS) {
if ((reg & ~I2C_TEN_BIT_ADDRESS) > 0x3ff)
if ((reg & I2C_TEN_BIT_ADDRESS) && ((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)
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);
}
@ -1113,7 +1108,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 +1180,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 +1215,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);
@ -1396,7 +1388,7 @@ static void check_property_phandle_args(struct check *c,
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))) {
FAIL_PROP(c, dti, node, prop,
@ -1408,15 +1400,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 +1450,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 +1462,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);
@ -1584,114 +1573,21 @@ static void check_interrupt_provider(struct check *c,
struct node *node)
{
struct property *prop;
bool irq_provider = node_is_interrupt_provider(node);
if (!node_is_interrupt_provider(node))
return;
prop = get_property(node, "#interrupt-cells");
if (irq_provider && !prop) {
if (!prop)
FAIL(c, dti, node,
"Missing '#interrupt-cells' in interrupt provider");
return;
}
"Missing #interrupt-cells in interrupt provider");
if (!irq_provider && prop) {
prop = get_property(node, "#address-cells");
if (!prop)
FAIL(c, dti, node,
"'#interrupt-cells' found, but node is not an interrupt provider");
return;
}
"Missing #address-cells in interrupt provider");
}
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);
WARNING(interrupt_provider, check_interrupt_provider, NULL);
static void check_interrupts_property(struct check *c,
struct dt_info *dti,
@ -1700,7 +1596,7 @@ 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)
@ -1719,7 +1615,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)
@ -1781,11 +1677,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 +1690,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 +1752,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 +1772,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 +1790,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;
@ -1979,11 +1887,10 @@ static struct check *check_table[] = {
&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 +1910,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 +1931,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 +1958,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++) {

47
data.c
View file

@ -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

@ -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);
@ -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
{

19
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",
@ -199,7 +197,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 +252,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 +282,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)

47
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,11 +51,6 @@ 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;
@ -116,12 +111,6 @@ 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 {
@ -146,22 +135,7 @@ 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);
@ -182,10 +156,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 +234,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);
@ -339,9 +310,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 ||
@ -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)
@ -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);
@ -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;
}
}
@ -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

@ -106,6 +106,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 +115,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),
@ -162,7 +165,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 +191,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;
@ -312,14 +308,14 @@ 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;
}

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

@ -66,9 +66,6 @@ int fdt_check_full(const void *fdt, size_t bufsize)
int len;
name = fdt_get_name(fdt, offset, &len);
if (!name)
return len;
if (*name || len)
return -FDT_ERR_BADSTRUCTURE;
}

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;
@ -224,7 +243,7 @@ static int overlay_update_local_node_references(void *fdto,
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;
@ -233,15 +252,33 @@ static int overlay_update_local_node_references(void *fdto,
}
for (i = 0; i < fixup_len; i++) {
fdt32_t *refp;
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 +344,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 +352,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 +365,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 +404,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 +431,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 +441,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 +480,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 +535,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 +636,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 +779,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 +801,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 +839,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

@ -255,9 +255,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);
@ -484,12 +481,12 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
if (!can_assume(VALID_INPUT)) {
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));
}
@ -525,31 +522,16 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
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);
}
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 +539,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;

View file

@ -124,33 +124,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 +181,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 +200,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 +211,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 +255,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 +273,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 +307,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);

View file

@ -39,7 +39,6 @@ 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])))

View file

@ -116,20 +116,6 @@ extern "C" {
/* Low-level functions (you probably don't need these) */
/**********************************************************************/
/**
* fdt_offset_ptr - safely get a byte range within the device tree blob
* @fdt: Pointer to the device tree blob
* @offset: Offset within the blob to the desired byte range
* @checklen: Required length of the byte range
*
* fdt_offset_ptr() returns a pointer to the byte range of length @checklen at
* the given @offset within the device tree blob, after verifying that the byte
* range fits entirely within the blob and does not overflow.
*
* returns:
* pointer to the byte range, on success
* NULL, if the requested range does not fit within the blob
*/
#ifndef SWIG /* This function is not useful in Python */
const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen);
#endif
@ -138,20 +124,6 @@ static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen);
}
/**
* fdt_next_tag - get next tag in the device tree
* @fdt: Pointer to the device tree blob
* @offset: Offset within the blob to start searching
* @nextoffset: Pointer to variable to store the offset of the next tag
*
* fdt_next_tag() returns the tag type of the next tag in the device tree
* blob starting from the given @offset. If @nextoffset is non-NULL, it will
* be set to the offset immediately following the tag.
*
* returns:
* the tag type (FDT_BEGIN_NODE, FDT_END_NODE, FDT_PROP, FDT_NOP, FDT_END),
* FDT_END, if offset is out of bounds
*/
uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
/*
@ -159,13 +131,6 @@ uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
* to work even with unaligned pointers on platforms (such as ARMv5) that don't
* like unaligned loads and stores.
*/
static inline uint16_t fdt16_ld(const fdt16_t *p)
{
const uint8_t *bp = (const uint8_t *)p;
return ((uint16_t)bp[0] << 8) | bp[1];
}
static inline uint32_t fdt32_ld(const fdt32_t *p)
{
const uint8_t *bp = (const uint8_t *)p;
@ -291,16 +256,16 @@ int fdt_next_subnode(const void *fdt, int offset);
struct fdt_header *fdth = (struct fdt_header *)fdt; \
fdth->name = cpu_to_fdt32(val); \
}
fdt_set_hdr_(magic)
fdt_set_hdr_(totalsize)
fdt_set_hdr_(off_dt_struct)
fdt_set_hdr_(off_dt_strings)
fdt_set_hdr_(off_mem_rsvmap)
fdt_set_hdr_(version)
fdt_set_hdr_(last_comp_version)
fdt_set_hdr_(boot_cpuid_phys)
fdt_set_hdr_(size_dt_strings)
fdt_set_hdr_(size_dt_struct)
fdt_set_hdr_(magic);
fdt_set_hdr_(totalsize);
fdt_set_hdr_(off_dt_struct);
fdt_set_hdr_(off_dt_strings);
fdt_set_hdr_(off_mem_rsvmap);
fdt_set_hdr_(version);
fdt_set_hdr_(last_comp_version);
fdt_set_hdr_(boot_cpuid_phys);
fdt_set_hdr_(size_dt_strings);
fdt_set_hdr_(size_dt_struct);
#undef fdt_set_hdr_
/**
@ -313,7 +278,7 @@ size_t fdt_header_size(const void *fdt);
/**
* fdt_header_size_ - internal function to get header size from a version number
* @version: device tree version number
* @version: devicetree version number
*
* Return: size of DTB header in bytes
*/
@ -362,23 +327,6 @@ int fdt_move(const void *fdt, void *buf, int bufsize);
/* Read-only functions */
/**********************************************************************/
/**
* fdt_check_full - check device tree validity
* @fdt: pointer to the device tree blob
* @bufsize: size of the buffer containing the device tree
*
* fdt_check_full() checks that the given buffer contains a valid
* flattened device tree and that the tree structure is internally
* consistent. This is a more thorough check than fdt_check_header().
*
* returns:
* 0, on success
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE,
* -FDT_ERR_BADSTRUCTURE,
* -FDT_ERR_TRUNCATED, standard meanings
*/
int fdt_check_full(const void *fdt, size_t bufsize);
/**
@ -569,35 +517,10 @@ int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen);
* level matching the given component, differentiated only by unit
* address).
*
* If the path is not absolute (i.e. does not begin with '/'), the
* first component is treated as an alias. That is, the property by
* that name is looked up in the /aliases node, and the value of that
* property used in place of that first component.
*
* For example, for this small fragment
*
* / {
* aliases {
* i2c2 = &foo; // RHS compiles to "/soc@0/i2c@30a40000/eeprom@52"
* };
* soc@0 {
* foo: i2c@30a40000 {
* bar: eeprom@52 {
* };
* };
* };
* };
*
* these would be equivalent:
*
* /soc@0/i2c@30a40000/eeprom@52
* i2c2/eeprom@52
*
* returns:
* structure block offset of the node with the requested path (>=0), on
* success
* -FDT_ERR_BADPATH, given path does not begin with '/' and the first
* component is not a valid alias
* -FDT_ERR_BADPATH, given path does not begin with '/' or is invalid
* -FDT_ERR_NOTFOUND, if the requested node does not exist
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
@ -730,13 +653,6 @@ int fdt_next_property_offset(const void *fdt, int offset);
const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
int offset,
int *lenp);
static inline struct fdt_property *fdt_get_property_by_offset_w(void *fdt,
int offset,
int *lenp)
{
return (struct fdt_property *)(uintptr_t)
fdt_get_property_by_offset(fdt, offset, lenp);
}
/**
* fdt_get_property_namelen - find a property based on substring
@ -757,13 +673,6 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt,
int nodeoffset,
const char *name,
int namelen, int *lenp);
static inline struct fdt_property *
fdt_get_property_namelen_w(void *fdt, int nodeoffset, const char *name,
int namelen, int *lenp)
{
return (struct fdt_property *)(uintptr_t)fdt_get_property_namelen(
fdt, nodeoffset, name, namelen, lenp);
}
#endif
/**
@ -816,7 +725,7 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
* to within the device blob itself, not a copy of the value). If
* lenp is non-NULL, the length of the property value is also
* returned, in the integer pointed to by lenp. If namep is non-NULL,
* the property's name will also be returned in the char * pointed to
* the property's namne will also be returned in the char * pointed to
* by namep (this will be a pointer to within the device tree's string
* block, not a new copy of the name).
*
@ -824,7 +733,7 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
* pointer to the property's value
* if lenp is non-NULL, *lenp contains the length of the property
* value (>=0)
* if namep is non-NULL *namep contains a pointer to the property
* if namep is non-NULL *namep contiains a pointer to the property
* name.
* NULL, on error
* if lenp is non-NULL, *lenp contains an error code (<0):
@ -918,7 +827,7 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);
/**
* fdt_get_alias_namelen - get alias based on substring
* @fdt: pointer to the device tree blob
* @name: name of the alias to look up
* @name: name of the alias th look up
* @namelen: number of characters of name to consider
*
* Identical to fdt_get_alias(), but only examine the first @namelen
@ -935,7 +844,7 @@ const char *fdt_get_alias_namelen(const void *fdt,
/**
* fdt_get_alias - retrieve the path referenced by a given alias
* @fdt: pointer to the device tree blob
* @name: name of the alias to look up
* @name: name of the alias th look up
*
* fdt_get_alias() retrieves the value of a given alias. That is, the
* value of the property named @name in the node /aliases.
@ -946,42 +855,6 @@ const char *fdt_get_alias_namelen(const void *fdt,
*/
const char *fdt_get_alias(const void *fdt, const char *name);
/**
* fdt_get_symbol_namelen - get symbol based on substring
* @fdt: pointer to the device tree blob
* @name: name of the symbol to look up
* @namelen: number of characters of name to consider
*
* Identical to fdt_get_symbol(), but only examine the first @namelen
* characters of @name for matching the symbol name.
*
* Return: a pointer to the expansion of the symbol named @name, if it exists,
* NULL otherwise
*/
#ifndef SWIG /* Not available in Python */
const char *fdt_get_symbol_namelen(const void *fdt,
const char *name, int namelen);
#endif
/**
* fdt_get_symbol - retrieve the path referenced by a given symbol
* @fdt: pointer to the device tree blob
* @name: name of the symbol to look up
*
* fdt_get_symbol() retrieves the value of a given symbol. That is,
* the value of the property named @name in the node
* /__symbols__. Such a node exists only for a device tree blob that
* has been compiled with the -@ dtc option. Each property corresponds
* to a label appearing in the device tree source, with the name of
* the property being the label and the value being the full path of
* the node it is attached to.
*
* returns:
* a pointer to the expansion of the symbol named 'name', if it exists
* NULL, if the given symbol or the /__symbols__ node does not exist
*/
const char *fdt_get_symbol(const void *fdt, const char *name);
/**
* fdt_get_path - determine the full path of a node
* @fdt: pointer to the device tree blob
@ -1563,7 +1436,7 @@ int fdt_nop_node(void *fdt, int nodeoffset);
* fdt_create_with_flags() begins the process of creating a new fdt with
* the sequential write interface.
*
* fdt creation process must end with fdt_finish() to produce a valid fdt.
* fdt creation process must end with fdt_finished() to produce a valid fdt.
*
* returns:
* 0, on success
@ -1585,90 +1458,10 @@ int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags);
*/
int fdt_create(void *buf, int bufsize);
/**
* fdt_resize - move and resize a device tree in sequential write state
* @fdt: Pointer to the device tree to resize
* @buf: Buffer where resized tree should be placed
* @bufsize: Size of the buffer at @buf
*
* fdt_resize() moves the device tree blob from @fdt to @buf and
* resizes it to fit in the new buffer size.
*
* returns:
* 0, on success
* -FDT_ERR_NOSPACE, if @bufsize is too small
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE, standard meanings
*/
int fdt_resize(void *fdt, void *buf, int bufsize);
/**
* fdt_add_reservemap_entry - add an entry to the memory reserve map
* @fdt: Pointer to the device tree blob
* @addr: Start address of the reserve map entry
* @size: Size of the reserved region
*
* fdt_add_reservemap_entry() adds a memory reserve map entry to the
* device tree blob during the sequential write process. This function
* can only be called after fdt_create() and before fdt_finish_reservemap().
*
* returns:
* 0, on success
* -FDT_ERR_NOSPACE, if there is insufficient space in the blob
* -FDT_ERR_BADSTATE, if not in the correct sequential write state
*/
int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size);
/**
* fdt_finish_reservemap - complete the memory reserve map
* @fdt: Pointer to the device tree blob
*
* fdt_finish_reservemap() completes the memory reserve map section
* of the device tree blob during sequential write. After calling this
* function, no more reserve map entries can be added and the blob
* moves to the structure creation phase.
*
* returns:
* 0, on success
* -FDT_ERR_BADSTATE, if not in the correct sequential write state
*/
int fdt_finish_reservemap(void *fdt);
/**
* fdt_begin_node - start creation of a new node
* @fdt: Pointer to the device tree blob
* @name: Name of the node to create
*
* fdt_begin_node() starts the creation of a new node with the given
* @name during sequential write. After calling this function, properties
* can be added with fdt_property() and subnodes can be created with
* additional fdt_begin_node() calls. The node must be completed with
* fdt_end_node().
*
* returns:
* 0, on success
* -FDT_ERR_NOSPACE, if there is insufficient space in the blob
* -FDT_ERR_BADSTATE, if not in the correct sequential write state
*/
int fdt_begin_node(void *fdt, const char *name);
/**
* fdt_property - add a property to the current node
* @fdt: Pointer to the device tree blob
* @name: Name of the property to add
* @val: Pointer to the property value
* @len: Length of the property value in bytes
*
* fdt_property() adds a property with the given @name and value to
* the current node during sequential write. This function can only
* be called between fdt_begin_node() and fdt_end_node().
*
* returns:
* 0, on success
* -FDT_ERR_NOSPACE, if there is insufficient space in the blob
* -FDT_ERR_BADSTATE, if not currently within a node
*/
int fdt_property(void *fdt, const char *name, const void *val, int len);
static inline int fdt_property_u32(void *fdt, const char *name, uint32_t val)
{
@ -1694,7 +1487,7 @@ static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
* @fdt: pointer to the device tree blob
* @name: name of property to add
* @len: length of property value in bytes
* @valp: returns a pointer to where the value should be placed
* @valp: returns a pointer to where where the value should be placed
*
* returns:
* 0, on success
@ -1705,94 +1498,15 @@ int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp);
#define fdt_property_string(fdt, name, str) \
fdt_property(fdt, name, str, strlen(str)+1)
/**
* fdt_end_node - complete the current node
* @fdt: Pointer to the device tree blob
*
* fdt_end_node() completes the current node during sequential write. This
* function must be called to close each node started with
* fdt_begin_node(). After calling this function, no more properties or subnodes
* can be added to the node.
*
* returns:
* 0, on success
* -FDT_ERR_BADSTATE, if not currently within a node
*/
int fdt_end_node(void *fdt);
/**
* fdt_finish - complete device tree creation
* @fdt: Pointer to the device tree blob
*
* fdt_finish() completes the device tree creation process started with
* fdt_create(). This function finalizes the device tree blob and makes it ready
* for use. After calling this function, the blob is complete and can be used
* with libfdt read-only and read-write functions, but not with sequential write
* functions.
*
* returns:
* 0, on success
* -FDT_ERR_BADSTATE, if the sequential write process is incomplete
*/
int fdt_finish(void *fdt);
/**********************************************************************/
/* Read-write functions */
/**********************************************************************/
/**
* fdt_create_empty_tree - create an empty device tree
* @buf: Buffer where the empty tree should be created
* @bufsize: Size of the buffer at @buf
*
* fdt_create_empty_tree() creates a minimal empty device tree blob
* in the given buffer. The tree contains only a root node with no
* properties or subnodes.
*
* returns:
* 0, on success
* -FDT_ERR_NOSPACE, if @bufsize is too small for even an empty tree
*/
int fdt_create_empty_tree(void *buf, int bufsize);
/**
* fdt_open_into - move a device tree into a new buffer and make editable
* @fdt: Pointer to the device tree to move
* @buf: Buffer where the editable tree should be placed
* @bufsize: Size of the buffer at @buf
*
* fdt_open_into() moves and reorganizes the device tree blob from @fdt
* into @buf, converting it to a format suitable for read-write operations.
* The new buffer should allow space for modifications.
*
* returns:
* 0, on success
* -FDT_ERR_NOSPACE, if @bufsize is too small
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE,
* -FDT_ERR_BADSTRUCTURE,
* -FDT_ERR_TRUNCATED, standard meanings
*/
int fdt_open_into(const void *fdt, void *buf, int bufsize);
/**
* fdt_pack - pack a device tree blob
* @fdt: Pointer to the device tree blob
*
* fdt_pack() reorganizes the device tree blob to eliminate any free space
* and pack it into the minimum possible size. This is useful after making
* modifications that might have left gaps in the blob.
*
* returns:
* 0, on success
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE,
* -FDT_ERR_BADSTRUCTURE,
* -FDT_ERR_BADLAYOUT, standard meanings
*/
int fdt_pack(void *fdt);
/**
@ -1870,38 +1584,6 @@ int fdt_del_mem_rsv(void *fdt, int n);
*/
int fdt_set_name(void *fdt, int nodeoffset, const char *name);
/**
* fdt_setprop_namelen - create or change a property
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to change
* @name: name of the property to change
* @namelen: length of the name
* @val: pointer to data to set the property value to
* @len: length of the property value
*
* fdt_setprop_namelen() sets the value of the named property in the given
* node to the given value and length, creating the property if it
* does not already exist.
*
* This function may insert or delete data from the blob, and will
* therefore change the offsets of some existing nodes.
*
* returns:
* 0, on success
* -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
* contain the new property value
* -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
* -FDT_ERR_BADLAYOUT,
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE,
* -FDT_ERR_BADSTRUCTURE,
* -FDT_ERR_BADLAYOUT,
* -FDT_ERR_TRUNCATED, standard meanings
*/
int fdt_setprop_namelen(void *fdt, int nodeoffset, const char *name,
int namelen, const void *val, int len);
/**
* fdt_setprop - create or change a property
* @fdt: pointer to the device tree blob
@ -1930,44 +1612,8 @@ int fdt_setprop_namelen(void *fdt, int nodeoffset, const char *name,
* -FDT_ERR_BADLAYOUT,
* -FDT_ERR_TRUNCATED, standard meanings
*/
static inline int fdt_setprop(void *fdt, int nodeoffset, const char *name,
const void *val, int len)
{
return fdt_setprop_namelen(fdt, nodeoffset, name, strlen(name), val,
len);
}
/**
* fdt_setprop_placeholder_namelen - allocate space for a property
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to change
* @name: name of the property to change
* @namelen: length of the name
* @len: length of the property value
* @prop_data: return pointer to property data
*
* fdt_setprop_placeholder_namelen() allocates the named property in the given node.
* If the property exists it is resized. In either case a pointer to the
* property data is returned.
*
* This function may insert or delete data from the blob, and will
* therefore change the offsets of some existing nodes.
*
* returns:
* 0, on success
* -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
* contain the new property value
* -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
* -FDT_ERR_BADLAYOUT,
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE,
* -FDT_ERR_BADSTRUCTURE,
* -FDT_ERR_BADLAYOUT,
* -FDT_ERR_TRUNCATED, standard meanings
*/
int fdt_setprop_placeholder_namelen(void *fdt, int nodeoffset, const char *name,
int namelen, int len, void **prop_data);
int fdt_setprop(void *fdt, int nodeoffset, const char *name,
const void *val, int len);
/**
* fdt_setprop_placeholder - allocate space for a property
@ -1977,7 +1623,7 @@ int fdt_setprop_placeholder_namelen(void *fdt, int nodeoffset, const char *name,
* @len: length of the property value
* @prop_data: return pointer to property data
*
* fdt_setprop_placeholder() allocates the named property in the given node.
* fdt_setprop_placeholer() allocates the named property in the given node.
* If the property exists it is resized. In either case a pointer to the
* property data is returned.
*
@ -1997,13 +1643,8 @@ int fdt_setprop_placeholder_namelen(void *fdt, int nodeoffset, const char *name,
* -FDT_ERR_BADLAYOUT,
* -FDT_ERR_TRUNCATED, standard meanings
*/
static inline int fdt_setprop_placeholder(void *fdt, int nodeoffset,
const char *name, int len,
void **prop_data)
{
return fdt_setprop_placeholder_namelen(fdt, nodeoffset, name,
strlen(name), len, prop_data);
}
int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name,
int len, void **prop_data);
/**
* fdt_setprop_u32 - set a property to a 32-bit integer
@ -2123,38 +1764,6 @@ static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
#define fdt_setprop_string(fdt, nodeoffset, name, str) \
fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
/**
* fdt_setprop_namelen_string - set a property to a string value
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to change
* @name: name of the property to change
* @namelen: number of characters of name to consider
* @str: string value for the property
*
* fdt_setprop_namelen_string() sets the value of the named property in the
* given node to the given string value (using the length of the
* string to determine the new length of the property), or creates a
* new property with that value if it does not already exist.
*
* This function may insert or delete data from the blob, and will
* therefore change the offsets of some existing nodes.
*
* returns:
* 0, on success
* -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
* contain the new property value
* -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
* -FDT_ERR_BADLAYOUT,
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE,
* -FDT_ERR_BADSTRUCTURE,
* -FDT_ERR_BADLAYOUT,
* -FDT_ERR_TRUNCATED, standard meanings
*/
#define fdt_setprop_namelen_string(fdt, nodeoffset, name, namelen, str) \
fdt_setprop_namelen((fdt), (nodeoffset), (name), (namelen), (str), \
strlen(str) + 1)
/**
* fdt_setprop_empty - set a property to an empty value
@ -2345,7 +1954,7 @@ static inline int fdt_appendprop_cell(void *fdt, int nodeoffset,
* address and size) to the value of the named property in the given
* node, or creates a new property with that value if it does not
* already exist.
*
* If "name" is not specified, a default "reg" is used.
* Cell sizes are determined by parent's #address-cells and #size-cells.
*
* This function may insert data into the blob, and will therefore
@ -2375,7 +1984,7 @@ int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset,
* @nodeoffset: offset of the node whose property to nop
* @name: name of the property to nop
*
* fdt_delprop() will delete the given property.
* fdt_del_property() will delete the given property.
*
* This function will delete data from the blob, and will therefore
* change the offsets of some existing nodes.
@ -2427,7 +2036,8 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
* change the offsets of some existing nodes.
*
* returns:
* structure block offset of the created subnode (>=0), on success
* structure block offset of the created nodeequested subnode (>=0), on
* success
* -FDT_ERR_NOTFOUND, if the requested subnode does not exist
* -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE
* tag
@ -2482,7 +2092,7 @@ int fdt_del_node(void *fdt, int nodeoffset);
* returns:
* 0, on success
* -FDT_ERR_NOSPACE, there's not enough space in the base device tree
* -FDT_ERR_NOTFOUND, the overlay points to some nonexistent nodes or
* -FDT_ERR_NOTFOUND, the overlay points to some inexistant nodes or
* properties in the base DT
* -FDT_ERR_BADPHANDLE,
* -FDT_ERR_BADOVERLAY,
@ -2499,38 +2109,10 @@ int fdt_del_node(void *fdt, int nodeoffset);
*/
int fdt_overlay_apply(void *fdt, void *fdto);
/**
* fdt_overlay_target_offset - retrieves the offset of a fragment's target
* @fdt: Base device tree blob
* @fdto: Device tree overlay blob
* @fragment_offset: node offset of the fragment in the overlay
* @pathp: pointer which receives the path of the target (or NULL)
*
* fdt_overlay_target_offset() 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
*/
int fdt_overlay_target_offset(const void *fdt, const void *fdto,
int fragment_offset, char const **pathp);
/**********************************************************************/
/* Debugging / informational functions */
/**********************************************************************/
/**
* fdt_strerror - return string description of error code
* @errval: Error code returned by a libfdt function
*
* fdt_strerror() returns a string description of the error code passed
* in @errval.
*
* returns:
* pointer to a string describing the error code
*/
const char *fdt_strerror(int errval);
#ifdef __cplusplus

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)
@ -55,8 +47,8 @@ static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n)
}
/*
* Internal helpers to access structural elements of the device tree
* blob (rather than for example reading integers from within property
* Internal helpers to access tructural elements of the device tree
* blob (rather than for exaple 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.

View file

@ -16,22 +16,12 @@ sources = files(
'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,
version: '1.6.0',
link_args: ['-Wl,--no-undefined', version_script],
link_depends: 'version.lds',
install: get_option('default_library') != 'static' or not wheel_only,
install: true,
)
libfdt_inc = include_directories('.')
@ -40,24 +30,21 @@ libfdt_dep = declare_dependency(
include_directories: libfdt_inc,
link_with: libfdt,
)
meson.override_dependency('libfdt', libfdt_dep)
if not wheel_only
install_headers(
install_headers(
files(
'fdt.h',
'libfdt.h',
'libfdt_env.h',
)
)
)
pkgconfig = import('pkgconfig')
pkgconfig = import('pkgconfig')
pkgconfig.generate(
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

@ -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)
@ -494,7 +440,7 @@ cell_t propval_cell(struct property *prop)
cell_t propval_cell_n(struct property *prop, unsigned 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,36 +883,27 @@ 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,
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,
static void generate_fixups_tree_internal(struct dt_info *dti,
struct node *fn,
struct node *node)
{
@ -1009,23 +912,18 @@ static int generate_fixups_tree_internal(struct dt_info *dti,
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,16 +973,18 @@ 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,
static void generate_local_fixups_tree_internal(struct dt_info *dti,
struct node *lfn,
struct node *node)
{
@ -1093,26 +993,21 @@ static int generate_local_fixups_tree_internal(struct dt_info *dti,
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,8 +1,7 @@
project('dtc', 'c',
version: files('VERSION.txt'),
version: '1.6.0',
license: ['GPL2+', 'BSD-2'],
default_options: ['werror=true', 'default_library=both'],
meson_version: '>=0.57.0'
default_options: 'werror=true',
)
cc = meson.get_compiler('c')
@ -15,20 +14,25 @@ add_project_arguments(
'-Wstrict-prototypes',
'-Wmissing-prototypes',
'-Wredundant-decls',
'-Wshadow',
'-Wsuggest-attribute=format',
'-Wwrite-strings',
'-Wshadow'
]),
language: 'c'
)
if host_machine.system() == 'windows'
add_project_arguments(
'-D__USE_MINGW_ANSI_STDIO=1',
language: 'c'
)
endif
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'))
yaml = dependency('yaml-0.1', required: get_option('yaml'))
if not yaml.found()
add_project_arguments('-DNO_YAML', language: 'c')
yamltree = []
@ -42,27 +46,23 @@ 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(
if get_option('tools')
flex = find_program('flex', required: true)
bison = find_program('bison', required: true)
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,
@ -77,7 +77,7 @@ if get_option('tools') and not wheel_only
)
if cc.check_header('fnmatch.h')
dtc_tools += executable(
executable(
'convert-dtsv0',
[
lgen.process('convert-dtsv0-lexer.l'),
@ -88,7 +88,7 @@ if get_option('tools') and not wheel_only
)
endif
dtc_tools += executable(
executable(
'dtc',
[
lgen.process('dtc-lexer.l'),
@ -108,24 +108,22 @@ if get_option('tools') and not wheel_only
)
foreach e: ['fdtdump', 'fdtget', 'fdtput', 'fdtoverlay']
dtc_tools += executable(e, files(e + '.c'), dependencies: util_dep, install: true)
executable(e, files(e + '.c'), dependencies: util_dep, install: true)
endforeach
install_data(
'dtdiff',
install_dir: get_option('bindir'),
install_dir: get_option('prefix') / get_option('bindir'),
install_mode: 'rwxr-xr-x',
)
endif
foreach e: dtc_tools
meson.override_find_program(e.name(), e)
endforeach
if pylibfdt_enabled
if not meson.is_cross_build()
if py.found() and swig.found()
subdir('pylibfdt')
endif
endif
if get_option('tests')
if get_option('tools')
subdir('tests')
endif
endif

View file

@ -8,7 +8,3 @@ 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 = --top-builddir .
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.
@ -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 +1,13 @@
libfdt_c = custom_target(
'swig',
setup_py = find_program('setup.py')
setup_py = [setup_py.path(), '--quiet', '--top-builddir', meson.current_build_dir() / '..']
custom_target(
'pylibfdt',
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@']
output: '_libfdt.so',
depends: version_gen_h,
command: [setup_py, 'build_ext', '--build-lib=' + meson.current_build_dir()],
build_by_default: true,
)
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,
)
meson.add_install_script(setup_py, 'install', '--prefix=' + get_option('prefix'), '--root=$DESTDIR')

59
pylibfdt/setup.py Executable file
View file

@ -0,0 +1,59 @@
#!/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_top_builddir():
if '--top-builddir' in sys.argv:
index = sys.argv.index('--top-builddir')
sys.argv.pop(index)
return sys.argv.pop(index)
else:
return os.getcwd()
srcdir = os.path.dirname(os.path.abspath(sys.argv[0]))
top_builddir = get_top_builddir()
def get_version():
version_file = os.path.join(top_builddir, 'version_gen.h')
f = open(version_file, 'rt')
m = re.match(VERSION_PATTERN, f.readline())
return m.group(1)
libfdt_module = Extension(
'_libfdt',
sources=[os.path.join(srcdir, 'libfdt.i')],
include_dirs=[os.path.join(srcdir, '../libfdt')],
libraries=['fdt'],
library_dirs=[os.path.join(top_builddir, 'libfdt')],
swig_opts=['-I' + os.path.join(srcdir, '../libfdt')],
)
setup(
name='libfdt',
version=get_version(),
author='Simon Glass <sjg@chromium.org>',
description='Python binding for libfdt',
ext_modules=[libfdt_module],
package_dir={'': srcdir},
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>
@ -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 \
@ -32,20 +32,17 @@ LIB_TESTS_L = get_mem_rsv \
fs_tree1
LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%)
LIBTREE_TESTS_L = truncated_property truncated_string truncated_memrsv
LIBTREE_TESTS_L = truncated_property truncated_string truncated_memrsv \
two_roots named_root
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 +60,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,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

@ -32,7 +32,7 @@ static struct {
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

@ -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,9 +1,7 @@
trees = static_library('trees', files('trees.S'),
build_by_default: false,
trees = static_library('trees', files('trees.S'), c_args: '-D__ASSEMBLY__',
include_directories: libfdt_inc)
dumptrees = executable('dumptrees', files('dumptrees.c'),
build_by_default: false,
link_with: trees, dependencies: libfdt_dep)
dumptrees_dtb = custom_target(
@ -49,7 +47,6 @@ tests = [
'get_path',
'get_phandle',
'get_prop_offset',
'get_next_tag_invalid_prop_len',
'getprop',
'incbin',
'integer-expressions',
@ -74,7 +71,6 @@ tests = [
'property_iterate',
'propname_escapes',
'references',
'relref_merge',
'root_node',
'rw_oom',
'rw_tree1',
@ -98,20 +94,16 @@ tests += [
'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)
executable(t, files(t + '.c'), dependencies: [testutil_dep, util_dep, libfdt_dep, dl])
endforeach
run_tests = find_program('run_tests.sh')
@ -121,43 +113,19 @@ if not py.found()
env += 'NO_PYTHON=1'
else
env += [
'PYTHON=' + py.full_path(),
'PYTHONPATH=' + meson.project_source_root() / 'pylibfdt',
'NO_PYTHON=0',
'PYTHON=' + py.path(),
'PYTHONPATH=' + meson.source_root() / 'pylibfdt',
]
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,
test(
'run-test',
run_tests,
args: ['-t', test_type],
is_parallel: false,
workdir: meson.current_build_dir(),
depends: run_test_deps,
depends: dumptrees_dtb,
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

@ -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);

View file

@ -1,18 +0,0 @@
/dts-v1/;
/*
* https://github.com/dgibson/dtc/issues/64
*
* Certain dtc versions had a bug where this input caused an infinite
* loop in check_property_phandle_args().
*
*/
/ {
clocks = <&ref &ref>;
ref: poc {
phandle = <1>;
#clock-cells = <0xffffffff>;
};
};

View file

@ -45,7 +45,7 @@ int main(int argc, char *argv[])
FAIL("fdt_path_offset(/node4): %s", fdt_strerror(n4));
h4 = fdt_get_phandle(fdt, n4);
if ((h4 == 0) || (h4 == ~0U))
if ((h4 == 0) || (h4 == -1))
FAIL("/node4 has bad phandle 0x%x\n", h4);
if (phandle_format & PHANDLE_LEGACY)

View file

@ -23,7 +23,7 @@ static void test_node(void *fdt, int parent_offset)
uint32_t properties;
const fdt32_t *prop;
int offset, property;
unsigned int count;
int count;
int len;
/*

View file

@ -348,20 +348,6 @@ class PyLibfdtBasicTests(unittest.TestCase):
self.assertEqual("/subnode@1/subsubnode", self.fdt3.get_alias('ss1'))
self.assertEqual("/subnode@1/subsubnode/subsubsubnode", self.fdt3.get_alias('sss1'))
def testGetPath(self):
"""Test for the get_path() method"""
node = self.fdt.path_offset('/subnode@1')
node2 = self.fdt.path_offset('/subnode@1/subsubnode')
self.assertEqual("/subnode@1", self.fdt.get_path(node))
self.assertEqual("/subnode@1/subsubnode", self.fdt.get_path(node2))
self.assertEqual("/subnode@1/subsubnode", self.fdt.get_path(node2, size_hint=1))
with self.assertRaises(FdtException) as e:
self.fdt.get_path(-1)
self.assertEqual(e.exception.err, -libfdt.BADOFFSET)
self.assertEqual(-libfdt.BADOFFSET, self.fdt.get_path(-1, quiet=(libfdt.BADOFFSET,)))
def testParentOffset(self):
"""Test for the parent_offset() method"""
self.assertEqual(-libfdt.NOTFOUND,
@ -396,25 +382,6 @@ class PyLibfdtBasicTests(unittest.TestCase):
self.get_prop("prop-uint64").as_uint64())
self.assertEqual(-2, self.get_prop("prop-int64").as_int64())
def testGetIntListProperties(self):
"""Test that we can access properties as integer lists"""
self.assertEqual([128, -16, -2],
self.get_prop("prop-int32-array").as_int32_list())
self.assertEqual([0x1, 0x98765432, 0xdeadbeef],
self.get_prop("prop-uint32-array").as_uint32_list())
self.assertEqual([0x100000000, -2],
self.get_prop("prop-int64-array").as_int64_list())
self.assertEqual([0x100000000, 0x1],
self.get_prop("prop-uint64-array").as_uint64_list())
def testGetStringlistProperties(self):
"""Test that we can access properties as string list"""
node = self.fdt.path_offset('/subnode@1/subsubnode')
self.assertEqual(["subsubnode1", "subsubnode"],
self.fdt.getprop(node, "compatible").as_stringlist())
self.assertEqual(["this is a placeholder string", "string2"],
self.fdt.getprop(node, "placeholder").as_stringlist())
def testReserveMap(self):
"""Test that we can access the memory reserve map"""
self.assertEqual(2, self.fdt.num_mem_rsv())
@ -496,39 +463,6 @@ class PyLibfdtBasicTests(unittest.TestCase):
self.assertEqual(TEST_STRING_3,
self.fdt.getprop(node, prop).as_str())
def testHasProp(self):
"""Test that we can check if a node has a property"""
node = 0
self.assertFalse(self.fdt2.hasprop(node, 'missing'))
self.assertTrue(self.fdt2.hasprop(node, 'prop-bool'))
# Test a property with a non-empty value
self.assertTrue(self.fdt2.hasprop(node, 'prop-uint64'))
def testSetPropBool(self):
"""Test that we can update and create boolean properties"""
node = 0
prop = 'prop-bool'
# Make some space and then try setting a new boolean property
self.fdt.resize(self.fdt.totalsize() + 50)
self.fdt.hasprop(node, 'missing')
self.fdt.setprop_bool(node, 'missing', True)
self.assertTrue(self.fdt.hasprop(node, 'missing'))
# Trying toggling an existing boolean property. Do each operation twice
# to make sure that the behaviour is correct when setting the property
# to the same value.
self.assertTrue(self.fdt2.hasprop(node, prop))
self.fdt2.setprop_bool(node, prop, False)
self.assertFalse(self.fdt2.hasprop(node, prop))
self.fdt2.setprop_bool(node, prop, False)
self.assertFalse(self.fdt2.hasprop(node, prop))
self.fdt2.setprop_bool(node, prop, True)
self.assertTrue(self.fdt2.hasprop(node, prop))
self.fdt2.setprop_bool(node, prop, True)
self.assertTrue(self.fdt2.hasprop(node, prop))
def testSetName(self):
"""Test that we can update a node name"""
node = self.fdt.path_offset('/subnode@1')

View file

@ -106,7 +106,7 @@ int main(int argc, char *argv[])
if ((h4 == 0x2000) || (h4 == 0x1) || (h4 == 0))
FAIL("/node4 has bad phandle, 0x%x", h4);
if ((h5 == 0) || (h5 == ~0U))
if ((h5 == 0) || (h5 == -1))
FAIL("/node5 has bad phandle, 0x%x", h5);
if ((h5 == h4) || (h5 == h2) || (h5 == h1))
FAIL("/node5 has duplicate phandle, 0x%x", h5);

View file

@ -1,51 +0,0 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for label relative child references in dtc
* Copyright (C) 2006 David Gibson, IBM Corporation.
* Copyright (C) 2020 Ahmad Fatoum, Pengutronix.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <libfdt.h>
#include "tests.h"
#include "testdata.h"
static void check_exist(void *fdt, const char *path)
{
int sn = fdt_path_offset(fdt, path);
if (sn < 0)
FAIL("%s expected but not found: %s", path, fdt_strerror(sn));
}
static void check_doesnt_exist(void *fdt, const char *path)
{
int sn = fdt_path_offset(fdt, path);
if (sn >= 0)
FAIL("%s found but not expected %d", path, sn);
}
int main(int argc, char *argv[])
{
void *fdt;
test_init(argc, argv);
fdt = load_blob_arg(argc, argv);
check_exist(fdt, "/node/subnode1");
check_exist(fdt, "/node/keep-me");
check_doesnt_exist(fdt, "/node/remove-me");
check_doesnt_exist(fdt, "/node2");
check_doesnt_exist(fdt, "/node/subnode3");
check_exist(fdt, "/node/subnode4");
check_exist(fdt, "/node/subnode1/add-me");
PASS();
}

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