Compare commits

..

No commits in common. "master" and "v1.4.6" have entirely different histories.

210 changed files with 4008 additions and 9868 deletions

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

@ -1,33 +0,0 @@
# EditorConfig is a file format and collection of text editor plugins
# for maintaining consistent coding styles between different editors
# and IDEs. Most popular editors support this either natively or via
# plugin.
#
# Check https://editorconfig.org for details.

root = true

[*]
end_of_line = lf
insert_final_newline = true
charset = utf-8
indent_style = space

[Makefile*]
indent_style = tab
indent_size = 8
file_type_emacs = makefile

[*.[ch]]
indent_style = tab
indent_size = 8

[*.py]
indent_size = 4

[meson.build]
indent_style = space
indent_size = 2

[*.lds]
indent_style = tab

View File

@ -1,113 +0,0 @@
---
name: Build test
'on':
push:
branches:
- main
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

12
.gitignore vendored
View File

@ -3,13 +3,10 @@
*.a
*.patch
*.so
*.so.*
*~
*.bak
*.tab.[ch]
lex.yy.c
*.lex.c
.*.swp
/dtc
/fdtdump
/convert-dtsv0
@ -19,12 +16,3 @@ lex.yy.c
/fdtoverlay
/patches
/.pc

# cscope files
cscope.*
ncscope.*

.eggs/
build/
dist/
*.egg-info/

30
.travis.yml Normal file
View File

@ -0,0 +1,30 @@
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
coverity_scan:
project:
name: dtc
description: Device Tree Compiler
notification_email: david@gibson.dropbear.id.au
build_command: make
branch_pattern: coverity_scan

- addons:
apt:
packages:

script:
- make
- make check

View File

@ -1,32 +0,0 @@
Valid-License-Identifier: BSD-2-Clause
SPDX-URL: https://spdx.org/licenses/BSD-2-Clause.html
Usage-Guide:
To use the BSD 2-clause "Simplified" License put the following SPDX
tag/value pair into a comment according to the placement guidelines in
the licensing rules documentation:
SPDX-License-Identifier: BSD-2-Clause
License-Text:

Copyright (c) <year> <owner> . All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

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

@ -37,14 +37,15 @@ The upstream repository is here:
git://git.kernel.org/pub/scm/utils/dtc/dtc.git
https://git.kernel.org/pub/scm/utils/dtc/dtc.git

The gitweb interface for the upstream repository is:
The gitweb interface for the upstream respository is:

https://git.kernel.org/cgit/utils/dtc/dtc.git/

1.1) Submitting Patches

Patches should be sent to the maintainer:
Patches should be sent to the maintainers:
David Gibson <david@gibson.dropbear.id.au>
Jon Loeliger <jdl@jdl.com>
and CCed to <devicetree-compiler@vger.kernel.org>.

2) Description
@ -77,9 +78,6 @@ The currently supported Output Formats are:
then simply be added to your Makefile. Additionally, the
assembly file exports some symbols that can be used.

- "yaml": DT encoded in YAML format. This representation is an
intermediate format used for validation tools.


3) Command Line

@ -122,24 +120,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
@ -245,7 +231,7 @@ For example:
"childnode at address". It in turn has a string property
called "childprop".

childnode@address {
childnode@addresss {
childprop = "hello\n";
};

@ -264,7 +250,7 @@ Labels may be applied to nodes or properties. Labels appear
before a node name, and are referenced using an ampersand: &label.
Absolute node path names are also allowed in node references.

In this example, a node is labeled "mpic" and then referenced:
In this exmaple, a node is labled "mpic" and then referenced:

mpic: interrupt-controller@40000 {
...
@ -275,7 +261,7 @@ In this example, a node is labeled "mpic" and then referenced:
...
};

And used in properties, labels may appear before or after any value:
And used in properties, lables may appear before or after any value:

randomnode {
prop: string = data: "mystring\n" data_end: ;
@ -429,7 +415,7 @@ value of r3.
among others, by kexec. If you are on an SMP system, this value
should match the content of the "reg" property of the CPU node in
the device-tree corresponding to the CPU calling the kernel entry
point (see further chapters for more information on the required
point (see further chapters for more informations on the required
device-tree contents)

- size_dt_strings
@ -595,7 +581,7 @@ looks like in practice.

This tree is almost a minimal tree. It pretty much contains the
minimal set of required nodes and properties to boot a linux kernel;
that is, some basic model information at the root, the CPUs, and the
that is, some basic model informations at the root, the CPUs, and the
physical memory layout. It also includes misc information passed
through /chosen, like in this example, the platform type (mandatory)
and the kernel command line arguments (optional).
@ -707,67 +693,3 @@ Where options are:
-i, --input Input base DT blob
-o, --output Output DT blob
-v, --verbose Verbose message output

4 ) fdtget -- Read properties from device tree

This command can be used to obtain individual values from the device tree in a
nicely formatted way. You can specify multiple nodes to display (when using -p)
or multiple node/property pairs (when not using -p). For the latter, each
property is displayed on its own line, with a space between each cell within
the property.

The syntax of the fdtget command is:

fdtget <options> <dt file> [<node> <property>]...
fdtget -p <options> <dt file> [<node> ]...

where options are:

<type> s=string, i=int, u=unsigned, x=hex, r=raw
Optional modifier prefix:
hh or b=byte, h=2 byte, l=4 byte (default)

Options: -[t:pld:hV]
-t, --type <arg> Type of data
-p, --properties List properties for each node
-l, --list List subnodes for each node
-d, --default <arg> Default value to display when the property is missing
-h, --help Print this help and exit
-V, --version Print version and exit

If -t is not provided, fdtget will try to figure out the type, trying to detect
strings, string lists and the size of each value in the property. This is
similar to how fdtdump works, and uses the same heuristics.


5 ) fdtput - Write properties to a device tree

The syntax of the fdtput command is:

fdtput <options> <dt file> <node> <property> [<value>...]
fdtput -c <options> <dt file> [<node>...]
fdtput -r <options> <dt file> [<node>...]
fdtput -d <options> <dt file> <node> [<property>...]

Options are:

<type> s=string, i=int, u=unsigned, x=hex
Optional modifier prefix:
hh or b=byte, h=2 byte, l=4 byte (default)

-c, --create Create nodes if they don't already exist
-r, --remove Delete nodes (and any subnodes) if they already exist
-d, --delete Delete properties if they already exist
-p, --auto-path Automatically create nodes as needed for the node path
-t, --type <arg> Type of data
-v, --verbose Display each value decoded from command line
-h, --help Print this help and exit
-V, --version Print version and exit

The option determines which usage is selected and therefore the operation that
is performed. The first usage adds or updates properties; the rest are used to
create/delete nodes and delete properties.

For the first usage, the command line arguments are joined together into a
single value which is written to the property. The -t option is required so
that fdtput knows how to decode its arguments.

41
GPL
View File

@ -1,12 +1,12 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991

Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.

Preamble
Preamble

The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
@ -15,7 +15,7 @@ software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
the GNU Library General Public License instead.) You can apply it to
your programs, too.

When we speak of free software, we are referring to freedom, not
@ -55,8 +55,8 @@ patent must be licensed for everyone's free use or not licensed at all.

The precise terms and conditions for copying, distribution and
modification follow.

GNU GENERAL PUBLIC LICENSE
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

0. This License applies to any program or other work which contains
@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)

These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.

4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
@ -225,7 +225,7 @@ impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
@ -255,7 +255,7 @@ make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.

NO WARRANTY
NO WARRANTY

11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.

END OF TERMS AND CONDITIONS

How to Apply These Terms to Your New Programs
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs

If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
@ -303,16 +303,17 @@ the "copyright" line and a pointer to where the full notice is found.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA


Also add information on how to contact you by electronic and paper mail.

If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:

Gnomovision version 69, Copyright (C) year name of author
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
@ -335,5 +336,5 @@ necessary. Here is a sample; alter the names:
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

170
Makefile
View File

@ -1,42 +1,31 @@
# SPDX-License-Identifier: GPL-2.0-or-later
#
# 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 = 4
SUBLEVEL = 6
EXTRAVERSION =
LOCAL_VERSION =
CONFIG_LOCALVERSION =

# Control the assumptions made (e.g. risking security issues) in the code.
# See libfdt_internal.h for details
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 \
-Wsuggest-attribute=format -Wwrite-strings
CFLAGS = -g -Os $(SHAREDLIB_CFLAGS) -Werror $(WARNINGS) $(EXTRA_CFLAGS)
CPPFLAGS = -I libfdt -I .
WARNINGS = -Wall -Wpointer-arith -Wcast-qual -Wnested-externs \
-Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls -Wshadow
CFLAGS = -g -Os $(SHAREDLIB_CFLAGS) -Werror $(WARNINGS)

BISON = bison
LEX = flex
SWIG = swig
PKG_CONFIG ?= pkg-config

INSTALL = install
INSTALL_PROGRAM = $(INSTALL)
INSTALL_LIB = $(INSTALL)
INSTALL_DATA = $(INSTALL) -m 644
INSTALL_SCRIPT = $(INSTALL)
INSTALL = /usr/bin/install
DESTDIR =
PREFIX = $(HOME)
BINDIR = $(PREFIX)/bin
@ -46,25 +35,6 @@ INCLUDEDIR = $(PREFIX)/include
HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \
sed -e 's/\(cygwin\|msys\).*/\1/')

NO_VALGRIND := $(shell $(PKG_CONFIG) --exists valgrind; echo $$?)
ifeq ($(NO_VALGRIND),1)
CPPFLAGS += -DNO_VALGRIND
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 $$?)
ifeq ($(NO_YAML),1)
CFLAGS += -DNO_YAML
else
LDLIBS_dtc += $(shell $(PKG_CONFIG) --libs yaml-0.1)
CFLAGS += $(shell $(PKG_CONFIG) --cflags yaml-0.1)
endif

ifeq ($(HOSTOS),darwin)
SHAREDLIB_EXT = dylib
SHAREDLIB_CFLAGS = -fPIC
@ -101,6 +71,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; \
@ -155,8 +126,26 @@ SCRIPTS = dtdiff

all: $(BIN) libfdt

# We need both Python and swig to build pylibfdt.
.PHONY: maybe_pylibfdt
maybe_pylibfdt: FORCE
if $(PKG_CONFIG) --cflags python2 >/dev/null 2>&1; then \
if which swig >/dev/null 2>&1; then \
can_build=yes; \
fi; \
fi; \
if [ "$$can_build" = "yes" ]; then \
$(MAKE) pylibfdt; \
else \
echo "## Skipping pylibfdt (install python dev and swig to build)"; \
fi

ifeq ($(NO_PYTHON),)
all: maybe_pylibfdt
endif


ifneq ($(DEPTARGETS),)
ifneq ($(MAKECMDGOALS),libfdt)
-include $(DTC_OBJS:%.o=%.d)
-include $(CONVERT_OBJS:%.o=%.d)
-include $(FDTDUMP_OBJS:%.o=%.d)
@ -164,42 +153,34 @@ ifneq ($(MAKECMDGOALS),libfdt)
-include $(FDTPUT_OBJS:%.o=%.d)
-include $(FDTOVERLAY_OBJS:%.o=%.d)
endif
endif



#
# Rules for libfdt
#
LIBFDT_dir = libfdt
LIBFDT_archive = $(LIBFDT_dir)/libfdt.a
LIBFDT_lib = $(LIBFDT_dir)/$(LIBFDT_LIB)
LIBFDT_include = $(addprefix $(LIBFDT_dir)/,$(LIBFDT_INCLUDES))
LIBFDT_version = $(addprefix $(LIBFDT_dir)/,$(LIBFDT_VERSION))
LIBFDT_objdir = libfdt
LIBFDT_srcdir = libfdt
LIBFDT_archive = $(LIBFDT_objdir)/libfdt.a
LIBFDT_lib = $(LIBFDT_objdir)/libfdt-$(DTC_VERSION).$(SHAREDLIB_EXT)
LIBFDT_include = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_INCLUDES))
LIBFDT_version = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_VERSION))

ifeq ($(STATIC_BUILD),1)
CFLAGS += -static
LIBFDT_dep = $(LIBFDT_archive)
else
LIBFDT_dep = $(LIBFDT_lib)
endif

include $(LIBFDT_dir)/Makefile.libfdt
include $(LIBFDT_srcdir)/Makefile.libfdt

.PHONY: libfdt
libfdt: $(LIBFDT_archive) $(LIBFDT_lib)

$(LIBFDT_archive): $(addprefix $(LIBFDT_dir)/,$(LIBFDT_OBJS))
$(LIBFDT_archive): $(addprefix $(LIBFDT_objdir)/,$(LIBFDT_OBJS))
$(LIBFDT_lib): $(addprefix $(LIBFDT_objdir)/,$(LIBFDT_OBJS))

$(LIBFDT_lib): $(addprefix $(LIBFDT_dir)/,$(LIBFDT_OBJS)) $(LIBFDT_version)
@$(VECHO) LD $@
$(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)
libfdt_clean:
@$(VECHO) CLEAN "(libfdt)"
rm -f $(addprefix $(LIBFDT_objdir)/,$(STD_CLEANFILES))
rm -f $(LIBFDT_objdir)/*.so

ifneq ($(DEPTARGETS),)
-include $(LIBFDT_OBJS:%.o=$(LIBFDT_dir)/%.d)
-include $(LIBFDT_OBJS:%.o=$(LIBFDT_objdir)/%.d)
endif

# This stops make from generating the lex and bison output during
@ -210,24 +191,27 @@ endif
install-bin: all $(SCRIPTS)
@$(VECHO) INSTALL-BIN
$(INSTALL) -d $(DESTDIR)$(BINDIR)
$(INSTALL_PROGRAM) $(BIN) $(DESTDIR)$(BINDIR)
$(INSTALL_SCRIPT) $(SCRIPTS) $(DESTDIR)$(BINDIR)
$(INSTALL) $(BIN) $(SCRIPTS) $(DESTDIR)$(BINDIR)

install-lib: libfdt
install-lib: all
@$(VECHO) INSTALL-LIB
$(INSTALL) -d $(DESTDIR)$(LIBDIR)
$(INSTALL_LIB) $(LIBFDT_lib) $(DESTDIR)$(LIBDIR)
$(INSTALL) $(LIBFDT_lib) $(DESTDIR)$(LIBDIR)
ln -sf $(notdir $(LIBFDT_lib)) $(DESTDIR)$(LIBDIR)/$(LIBFDT_soname)
ln -sf $(LIBFDT_soname) $(DESTDIR)$(LIBDIR)/libfdt.$(SHAREDLIB_EXT)
$(INSTALL_DATA) $(LIBFDT_archive) $(DESTDIR)$(LIBDIR)
$(INSTALL) -m 644 $(LIBFDT_archive) $(DESTDIR)$(LIBDIR)

install-includes:
@$(VECHO) INSTALL-INC
$(INSTALL) -d $(DESTDIR)$(INCLUDEDIR)
$(INSTALL_DATA) $(LIBFDT_include) $(DESTDIR)$(INCLUDEDIR)
$(INSTALL) -m 644 $(LIBFDT_include) $(DESTDIR)$(INCLUDEDIR)

install: install-bin install-lib install-includes

ifeq ($(NO_PYTHON),)
install: install_pylibfdt
endif

$(VERSION_FILE): Makefile FORCE
$(call filechk,version)

@ -240,11 +224,11 @@ convert-dtsv0: $(CONVERT_OBJS)

fdtdump: $(FDTDUMP_OBJS)

fdtget: $(FDTGET_OBJS) $(LIBFDT_dep)
fdtget: $(FDTGET_OBJS) $(LIBFDT_archive)

fdtput: $(FDTPUT_OBJS) $(LIBFDT_dep)
fdtput: $(FDTPUT_OBJS) $(LIBFDT_archive)

fdtoverlay: $(FDTOVERLAY_OBJS) $(LIBFDT_dep)
fdtoverlay: $(FDTOVERLAY_OBJS) $(LIBFDT_archive)

dist:
git archive --format=tar --prefix=dtc-$(dtc_version)/ HEAD \
@ -253,6 +237,21 @@ dist:
gzip -9 > ../dtc-$(dtc_version).tar.gz


#
# Rules for pylibfdt
#
PYLIBFDT_srcdir = pylibfdt
PYLIBFDT_objdir = pylibfdt

include $(PYLIBFDT_srcdir)/Makefile.pylibfdt

.PHONY: pylibfdt
pylibfdt: $(PYLIBFDT_objdir)/_libfdt.so

pylibfdt_clean:
@$(VECHO) CLEAN "(pylibfdt)"
rm -f $(addprefix $(PYLIBFDT_objdir)/,$(PYLIBFDT_cleanfiles))

#
# Release signing and uploading
# This is for maintainer convenience, don't try this at home.
@ -286,18 +285,19 @@ TESTS_BIN += fdtput
TESTS_BIN += fdtget
TESTS_BIN += fdtdump
TESTS_BIN += fdtoverlay

ifneq ($(MAKECMDGOALS),libfdt)
include tests/Makefile.tests
ifeq ($(NO_PYTHON),)
TESTS_PYLIBFDT += maybe_pylibfdt
endif

include tests/Makefile.tests

#
# Clean rules
#
STD_CLEANFILES = *~ *.o *.$(SHAREDLIB_EXT) *.d *.a *.i *.s core a.out vgcore.* \
*.tab.[ch] *.lex.c *.output

clean: libfdt_clean tests_clean
clean: libfdt_clean pylibfdt_clean tests_clean
@$(VECHO) CLEAN
rm -f $(STD_CLEANFILES)
rm -f $(VERSION_FILE)
@ -309,7 +309,7 @@ clean: libfdt_clean tests_clean
#
%: %.o
@$(VECHO) LD $@
$(LINK.c) -o $@ $^ $(LDLIBS_$*)
$(LINK.c) -o $@ $^

%.o: %.c
@$(VECHO) CC $@
@ -317,11 +317,11 @@ 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 $<
$(CC) $(CPPFLAGS) $(CFLAGS) -MM -MG -MT "$*.o $@" $< > $@
$(CC) $(CPPFLAGS) -MM -MG -MT "$*.o $@" $< > $@

%.d: %.S
@$(VECHO) DEP $<
@ -339,16 +339,16 @@ clean: libfdt_clean tests_clean
@$(VECHO) AR $@
$(AR) $(ARFLAGS) $@ $^

$(LIBFDT_lib):
@$(VECHO) LD $@
$(CC) $(LDFLAGS) $(SHAREDLIB_LDFLAGS)$(LIBFDT_soname) -o $(LIBFDT_lib) $^

%.lex.c: %.l
@$(VECHO) LEX $@
$(LEX) -o$@ $<

%.tab.c %.tab.h: %.y
%.tab.c %.tab.h %.output: %.y
@$(VECHO) BISON $@
$(BISON) -b $(basename $(basename $@)) -d $<
$(BISON) -d $<

FORCE:

ifeq ($(MAKE_RESTARTS),10)
$(error "Make re-executed itself $(MAKE_RESTARTS) times. Infinite recursion?")
endif

View File

@ -1,4 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-or-later
#
# This is not a complete Makefile of itself.
# Instead, it is designed to be easily embeddable

View File

@ -1,4 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Makefile.dtc
#
# This is not a complete Makefile of itself. Instead, it is designed to
@ -15,9 +14,5 @@ DTC_SRCS = \
treesource.c \
util.c

ifneq ($(NO_YAML),1)
DTC_SRCS += yamltree.c
endif

DTC_GEN_SRCS = dtc-lexer.lex.c dtc-parser.tab.c
DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o)

View File

@ -1,4 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-or-later
#
# This is not a complete Makefile of itself. Instead, it is designed to
# be easily embeddable into other systems of Makefiles.

93
README Normal file
View File

@ -0,0 +1,93 @@
The source tree contains the Device Tree Compiler (dtc) toolchain for
working with device tree source and binary files and also libfdt, a
utility library for reading and manipulating the binary format.

DTC and LIBFDT are maintained by:

David Gibson <david@gibson.dropbear.id.au>
Jon Loeliger <jdl@jdl.com>


Python library
--------------

A Python library is also available. To build this you will need to install
swig and Python development files. On Debian distributions:

sudo apt-get install swig python-dev

The library provides an Fdt class which you can use like this:

$ PYTHONPATH=../pylibfdt python
>>> import libfdt
>>> fdt = libfdt.Fdt(open('test_tree1.dtb').read())
>>> node = fdt.path_offset('/subnode@1')
>>> print node
124
>>> prop_offset = fdt.first_property_offset(node)
>>> prop = fdt.get_property_by_offset(prop_offset)
>>> print '%s=%r' % (prop.name, prop.value)
compatible=bytearray(b'subnode1\x00')
>>> print '%s=%s' % (prop.name, prop.value)
compatible=subnode1
>>> node2 = fdt.path_offset('/')
>>> print fdt.getprop(node2, 'compatible')
test_tree1

You will find tests in tests/pylibfdt_tests.py showing how to use each
method. Help is available using the Python help command, e.g.:

$ cd pylibfdt
$ python -c "import libfdt; help(libfdt)"

If you add new features, please check code coverage:

$ sudo apt-get install python-pip python-pytest
$ sudo pip install coverage
$ cd tests
$ coverage run pylibfdt_tests.py
$ coverage html
# Open 'htmlcov/index.html' in your browser


To install the library via the normal setup.py method, use:

./pylibfdt/setup.py [--prefix=/path/to/install_dir]

If --prefix is not provided, the default prefix is used, typically '/usr'
or '/usr/local'. See Python's distutils documentation for details. You can
also install via the Makefile if you like, but the above is more common.

To install both libfdt and pylibfdt you can use:

make install [SETUP_PREFIX=/path/to/install_dir] \
[PREFIX=/path/to/install_dir]

To disable building the python library, even if swig and Python are available,
use:

make NO_PYTHON=1


More work remains to support all of libfdt, including access to numeric
values.


Tests
-----

Test files are kept in the tests/ directory. Use 'make check' to build and run
all tests.

If you want to adjust a test file, be aware that tree_tree1.dts is compiled
and checked against a binary tree from assembler macros in trees.S. So
if you change that file you must change tree.S also.


Mailing list
------------
The following list is for discussion about dtc and libfdt implementation
mailto:devicetree-compiler@vger.kernel.org

Core device tree bindings are discussed on the devicetree-spec list:
mailto:devicetree-spec@vger.kernel.org

View File

@ -4,11 +4,11 @@ Licensing and contribution policy of dtc and libfdt
This dtc package contains two pieces of software: dtc itself, and
libfdt which comprises the files in the libfdt/ subdirectory. These
two pieces of software, although closely related, are quite distinct.
dtc does not incorporate or rely on libfdt for its operation, nor vice
dtc does not incoporate or rely on libfdt for its operation, nor vice
versa. It is important that these two pieces of software have
different license conditions.

As SPDX license tags in each source file attest, dtc is licensed
As the copyright banners in each source file attest, dtc is licensed
under the GNU GPL. The full text of the GPL can be found in the file
entitled 'GPL' which should be included in this package. dtc code,
therefore, may not be incorporated into works which do not have a GPL
@ -16,10 +16,10 @@ compatible license.

libfdt, however, is GPL/BSD dual-licensed. That is, it may be used
either under the terms of the GPL, or under the terms of the 2-clause
BSD license (aka the ISC license). The full terms of that license can
be found are in the file entitled 'BSD-2-Clause'. This is, in
practice, equivalent to being BSD licensed, since the terms of the BSD
license are strictly more permissive than the GPL.
BSD license (aka the ISC license). The full terms of that license are
given in the copyright banners of each of the libfdt source files.
This is, in practice, equivalent to being BSD licensed, since the
terms of the BSD license are strictly more permissive than the GPL.

I made the decision to license libfdt in this way because I want to
encourage widespread and correct usage of flattened device trees,
@ -28,12 +28,12 @@ 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
rocket science; so the incentive for such impolite behaviour is small,
and the inconvenience caused thereby is not dire.
and the inconvenience caused therby is not dire.

Licenses such as the LGPL which would allow code to be used in non-GPL
software, but also require contributions to be returned were

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

1050
checks.c

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,20 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005, 2008.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/

%option noyywrap nounput noinput never-interactive
@ -94,7 +108,7 @@ static const struct {
<INITIAL>[0-9a-fA-F]+ {
unsigned long long val;
int obase = 16, width = 0;
unsigned int i;
int i;

val = strtoull(yytext, NULL, cbase);


74
data.c
View File

@ -1,6 +1,21 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/

#include "dtc.h"
@ -21,10 +36,10 @@ void data_free(struct data d)
free(d.val);
}

struct data data_grow_for(struct data d, unsigned int xlen)
struct data data_grow_for(struct data d, int xlen)
{
struct data nd;
unsigned int newsize;
int newsize;

if (xlen == 0)
return d;
@ -59,8 +74,7 @@ struct data data_copy_escape_string(const char *s, int len)
struct data d;
char *q;

d = data_add_marker(empty_data, TYPE_STRING, NULL);
d = data_grow_for(d, len + 1);
d = data_grow_for(empty_data, len + 1);

q = d.val;
while (i < len) {
@ -80,11 +94,10 @@ struct data data_copy_file(FILE *f, size_t maxlen)
{
struct data d = empty_data;

d = data_add_marker(d, TYPE_NONE, NULL);
while (!feof(f) && (d.len < maxlen)) {
size_t chunksize, ret;

if (maxlen == (size_t)-1)
if (maxlen == -1)
chunksize = 4096;
else
chunksize = maxlen - d.len;
@ -228,7 +241,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 +267,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

@ -1,6 +1,21 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/

%option noyywrap nounput noinput never-interactive
@ -23,6 +38,7 @@ LINECOMMENT "//".*\n
#include "srcpos.h"
#include "dtc-parser.tab.h"

YYLTYPE yylloc;
extern bool treesource_error;

/* CAUTION: this will stop working if we ever use yyless() or yyunput() */
@ -57,7 +73,7 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
push_input_file(name);
}

<*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)* {
<*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)? {
char *line, *fnstart, *fnend;
struct data fn;
/* skip text before line # */
@ -137,13 +153,6 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
return DT_DEL_NODE;
}

<*>"/omit-if-no-ref/" {
DPRINT("Keyword: /omit-if-no-ref/\n");
DPRINT("<PROPNODENAME>\n");
BEGIN(PROPNODENAME);
return DT_OMIT_NO_REF;
}

<*>{LABEL}: {
DPRINT("Label: %s\n", yytext);
yylval.labelref = xstrdup(yytext);
@ -151,21 +160,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);
@ -212,14 +206,14 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
<*>\&{LABEL} { /* label reference */
DPRINT("Ref: %s\n", yytext+1);
yylval.labelref = xstrdup(yytext+1);
return DT_LABEL_REF;
return DT_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);
return DT_PATH_REF;
return DT_REF;
}

<BYTESTRING>[0-9a-fA-F]{2} {

View File

@ -1,9 +1,22 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
%locations

%{
#include <stdio.h>
#include <inttypes.h>
@ -19,16 +32,8 @@ extern void yyerror(char const *s);
treesource_error = true; \
} while (0)

#define YYERROR_CALL(msg) yyerror(msg)

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 {
@ -58,15 +63,13 @@ static bool is_ref_relative(const char *ref)
%token DT_BITS
%token DT_DEL_PROP
%token DT_DEL_NODE
%token DT_OMIT_NO_REF
%token <propnodename> DT_PROPNODENAME
%token <integer> DT_LITERAL
%token <integer> DT_CHAR_LITERAL
%token <byte> DT_BYTE
%token <data> DT_STRING
%token <labelref> DT_LABEL
%token <labelref> DT_LABEL_REF
%token <labelref> DT_PATH_REF
%token <labelref> DT_REF
%token DT_INCBIN

%type <data> propdata
@ -79,7 +82,6 @@ static bool is_ref_relative(const char *ref)
%type <data> bytestring
%type <prop> propdef
%type <proplist> proplist
%type <labelref> dt_ref

%type <node> devicetree
%type <node> nodedef
@ -155,8 +157,6 @@ memreserve:
}
;

dt_ref: DT_LABEL_REF | DT_PATH_REF;

devicetree:
'/' nodedef
{
@ -166,7 +166,7 @@ devicetree:
{
$$ = merge_nodes($1, $3);
}
| dt_ref nodedef
| DT_REF nodedef
{
/*
* We rely on the rule being always:
@ -175,20 +175,12 @@ 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),
""),
$2, $1);
$$ = add_orphan_node(name_node(build_node(NULL, NULL), ""), $2, $1);
}
| devicetree DT_LABEL dt_ref nodedef
| devicetree DT_LABEL DT_REF nodedef
{
struct node *target = get_node_by_ref($1, $3);

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);
@ -196,28 +188,7 @@ devicetree:
ERROR(&@3, "Label or path %s not found", $3);
$$ = $1;
}
| devicetree DT_PATH_REF nodedef
{
/*
* We rely on the rule being always:
* versioninfo plugindecl memreserves 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);

if (target)
merge_nodes(target, $3);
else
ERROR(&@2, "Label or path %s not found", $2);
}
$$ = $1;
}
| devicetree DT_LABEL_REF nodedef
| devicetree DT_REF nodedef
{
struct node *target = get_node_by_ref($1, $2);

@ -236,7 +207,7 @@ devicetree:
}
$$ = $1;
}
| devicetree DT_DEL_NODE dt_ref ';'
| devicetree DT_DEL_NODE DT_REF ';'
{
struct node *target = get_node_by_ref($1, $3);

@ -246,18 +217,6 @@ devicetree:
ERROR(&@3, "Label or path %s not found", $3);


$$ = $1;
}
| devicetree DT_OMIT_NO_REF dt_ref ';'
{
struct node *target = get_node_by_ref($1, $3);

if (target)
omit_node_if_unused(target);
else
ERROR(&@3, "Label or path %s not found", $3);


$$ = $1;
}
;
@ -265,7 +224,7 @@ devicetree:
nodedef:
'{' proplist subnodes '}' ';'
{
$$ = build_node($2, $3, &@$);
$$ = build_node($2, $3);
}
;

@ -283,18 +242,15 @@ proplist:
propdef:
DT_PROPNODENAME '=' propdata ';'
{
$$ = build_property($1, $3, &@$);
free($1);
$$ = build_property($1, $3);
}
| DT_PROPNODENAME ';'
{
$$ = build_property($1, empty_data, &@$);
free($1);
$$ = build_property($1, empty_data);
}
| DT_DEL_PROP DT_PROPNODENAME ';'
{
$$ = build_property_delete($2);
free($2);
}
| DT_LABEL propdef
{
@ -316,9 +272,8 @@ propdata:
{
$$ = data_merge($1, $3);
}
| propdataprefix dt_ref
| propdataprefix DT_REF
{
$1 = data_add_marker($1, TYPE_STRING, $2);
$$ = data_add_marker($1, REF_PATH, $2);
}
| propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')'
@ -372,27 +327,22 @@ arrayprefix:
DT_BITS DT_LITERAL '<'
{
unsigned long long bits;
enum markertype type = TYPE_UINT32;

bits = $2;

switch (bits) {
case 8: type = TYPE_UINT8; break;
case 16: type = TYPE_UINT16; break;
case 32: type = TYPE_UINT32; break;
case 64: type = TYPE_UINT64; break;
default:
if ((bits != 8) && (bits != 16) &&
(bits != 32) && (bits != 64)) {
ERROR(&@2, "Array elements must be"
" 8, 16, 32 or 64-bits");
bits = 32;
}

$$.data = data_add_marker(empty_data, type, NULL);
$$.data = empty_data;
$$.bits = bits;
}
| '<'
{
$$.data = data_add_marker(empty_data, TYPE_UINT32, NULL);
$$.data = empty_data;
$$.bits = 32;
}
| arrayprefix integer_prim
@ -407,19 +357,14 @@ 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);
}
| arrayprefix dt_ref
| arrayprefix DT_REF
{
uint64_t val = ~0ULL >> (64 - $1.bits);

@ -497,8 +442,8 @@ integer_rela:
;

integer_shift:
integer_shift DT_LSHIFT integer_add { $$ = ($3 < 64) ? ($1 << $3) : 0; }
| integer_shift DT_RSHIFT integer_add { $$ = ($3 < 64) ? ($1 >> $3) : 0; }
integer_shift DT_LSHIFT integer_add { $$ = $1 << $3; }
| integer_shift DT_RSHIFT integer_add { $$ = $1 >> $3; }
| integer_add
;

@ -541,7 +486,7 @@ integer_unary:
bytestring:
/* empty */
{
$$ = data_add_marker(empty_data, TYPE_UINT8, NULL);
$$ = empty_data;
}
| bytestring DT_BYTE
{
@ -573,16 +518,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
{
$$ = omit_node_if_unused($2);
$$ = name_node(build_node_delete(), $2);
}
| DT_LABEL subnode
{

58
dtc.c
View File

@ -1,6 +1,21 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/

#include <sys/stat.h>
@ -12,16 +27,14 @@
* 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 */
int auto_label_aliases; /* auto generate labels -> aliases */
int annotate; /* Level of annotation: 1 for input source location
>1 for full input source location. */

static int is_power_of_2(int x)
{
@ -47,7 +60,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:@Ahv";
static struct option const usage_long_opts[] = {
{"quiet", no_argument, NULL, 'q'},
{"in-format", a_argument, NULL, 'I'},
@ -67,9 +80,7 @@ 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'},
{"version", no_argument, NULL, 'v'},
{NULL, no_argument, NULL, 0x0},
@ -84,9 +95,6 @@ static const char * const usage_opts_help[] = {
"\n\tOutput formats are:\n"
"\t\tdts - device tree source text\n"
"\t\tdtb - device tree blob\n"
#ifndef NO_YAML
"\t\tyaml - device tree encoded as YAML\n"
#endif
"\t\tasm - assembler source",
"\n\tBlob version to produce, defaults to "stringify(DEFAULT_FDT_VERSION)" (for dtb and asm output)",
"\n\tOutput dependency file",
@ -105,9 +113,7 @@ 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",
"\n\tPrint version and exit",
NULL,
@ -122,10 +128,6 @@ static const char *guess_type_by_name(const char *fname, const char *fallback)
return fallback;
if (!strcasecmp(s, ".dts"))
return "dts";
if (!strcasecmp(s, ".yaml"))
return "yaml";
if (!strcasecmp(s, ".dtbo"))
return "dtb";
if (!strcasecmp(s, ".dtb"))
return "dtb";
return fallback;
@ -199,7 +201,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,17 +256,9 @@ int main(int argc, char *argv[])
case '@':
generate_symbols = 1;
break;

case 'L':
generate_fixups = 1;
break;

case 'A':
auto_label_aliases = 1;
break;
case 'T':
annotate++;
break;

case 'h':
usage(NULL);
@ -289,9 +283,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)
@ -305,8 +297,6 @@ int main(int argc, char *argv[])
outform = "dts";
}
}
if (annotate && (!streq(inform, "dts") || !streq(outform, "dts")))
die("--annotate requires -I dts -O dts\n");
if (streq(inform, "dts"))
dti = dt_from_source(arg);
else if (streq(inform, "fs"))
@ -360,12 +350,6 @@ int main(int argc, char *argv[])

if (streq(outform, "dts")) {
dt_to_source(outf, dti);
#ifndef NO_YAML
} else if (streq(outform, "yaml")) {
if (!streq(inform, "dts"))
die("YAML output format requires dts input format\n");
dt_to_yaml(outf, dti);
#endif
} else if (streq(outform, "dtb")) {
dt_to_blob(outf, dti, outversion);
} else if (streq(outform, "asm")) {

140
dtc.h
View File

@ -1,9 +1,24 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#ifndef DTC_H
#define DTC_H

/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/

#include <stdio.h>
@ -35,15 +50,14 @@
* 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 */
extern int auto_label_aliases; /* auto generate labels -> aliases */
extern int annotate; /* annotate .dts with input source location */

#define PHANDLE_LEGACY 0x1
#define PHANDLE_EPAPR 0x2
@ -51,88 +65,29 @@ extern int annotate; /* annotate .dts with input source location */

typedef uint32_t cell_t;

static inline bool phandle_is_valid(cell_t phandle)
{
return phandle != 0 && phandle != ~0U;
}

static inline uint16_t dtb_ld16(const void *p)
{
const uint8_t *bp = (const uint8_t *)p;

return ((uint16_t)bp[0] << 8)
| bp[1];
}

static inline uint32_t dtb_ld32(const void *p)
{
const uint8_t *bp = (const uint8_t *)p;

return ((uint32_t)bp[0] << 24)
| ((uint32_t)bp[1] << 16)
| ((uint32_t)bp[2] << 8)
| bp[3];
}

static inline uint64_t dtb_ld64(const void *p)
{
const uint8_t *bp = (const uint8_t *)p;

return ((uint64_t)bp[0] << 56)
| ((uint64_t)bp[1] << 48)
| ((uint64_t)bp[2] << 40)
| ((uint64_t)bp[3] << 32)
| ((uint64_t)bp[4] << 24)
| ((uint64_t)bp[5] << 16)
| ((uint64_t)bp[6] << 8)
| bp[7];
}

#define streq(a, b) (strcmp((a), (b)) == 0)
#define strstarts(s, prefix) (strncmp((s), (prefix), strlen(prefix)) == 0)
#define strprefixeq(a, n, b) (strlen(b) == (n) && (memcmp(a, b, n) == 0))
static inline bool strends(const char *str, const char *suffix)
{
unsigned int len, suffix_len;

len = strlen(str);
suffix_len = strlen(suffix);
if (len < suffix_len)
return false;
return streq(str + len - suffix_len, suffix);
}

#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))

/* Data blobs */
enum markertype {
TYPE_NONE,
REF_PHANDLE,
REF_PATH,
LABEL,
TYPE_UINT8,
TYPE_UINT16,
TYPE_UINT32,
TYPE_UINT64,
TYPE_STRING,
};

static inline bool is_type_marker(enum markertype type)
{
return type >= TYPE_UINT8;
}

extern const char *markername(enum markertype markertype);

struct marker {
enum markertype type;
unsigned int offset;
int offset;
char *ref;
struct marker *next;
};

struct data {
unsigned int len;
int len;
char *val;
struct marker *markers;
};
@ -146,26 +101,9 @@ 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;
}

void data_free(struct data d);

struct data data_grow_for(struct data d, unsigned int xlen);
struct data data_grow_for(struct data d, int xlen);

struct data data_copy_mem(const char *mem, int len);
struct data data_copy_escape_string(const char *s, int len);
@ -182,10 +120,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);
@ -214,7 +149,6 @@ struct property {
struct property *next;

struct label *labels;
struct srcpos *srcpos;
};

struct node {
@ -234,9 +168,6 @@ struct node {

struct label *labels;
const struct bus_type *bus;
struct srcpos *srcpos;

bool omit_if_unused, is_referenced;
};

#define for_each_label_withdel(l0, l) \
@ -263,18 +194,14 @@ 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 srcpos *srcpos);
struct property *build_property_delete(const char *name);
struct property *build_property(char *name, struct data val);
struct property *build_property_delete(char *name);
struct property *chain_property(struct property *first, struct property *list);
struct property *reverse_properties(struct property *first);

struct node *build_node(struct property *proplist, struct node *children,
struct srcpos *srcpos);
struct node *build_node_delete(struct srcpos *srcpos);
struct node *name_node(struct node *node, const char *name);
struct node *omit_node_if_unused(struct node *node);
struct node *reference_node(struct node *node);
struct node *build_node(struct property *proplist, struct node *children);
struct node *build_node_delete(void);
struct node *name_node(struct node *node, char *name);
struct node *chain_node(struct node *first, struct node *list);
struct node *merge_nodes(struct node *old_node, struct node *new_node);
struct node *add_orphan_node(struct node *old_node, struct node *new_node, char *ref);
@ -286,13 +213,12 @@ void add_child(struct node *parent, struct node *child);
void delete_node_by_name(struct node *parent, char *name);
void delete_node(struct node *node);
void append_to_property(struct node *node,
char *name, const void *data, int len,
enum markertype type);
char *name, const void *data, int len);

const char *get_unitname(struct node *node);
struct property *get_property(struct node *node, const char *propname);
cell_t propval_cell(struct property *prop);
cell_t propval_cell_n(struct property *prop, unsigned int n);
cell_t propval_cell_n(struct property *prop, int n);
struct property *get_property_by_label(struct node *tree, const char *label,
struct node **node);
struct marker *get_marker_label(struct node *tree, const char *label,
@ -339,9 +265,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 */

@ -360,10 +286,6 @@ struct dt_info *dt_from_blob(const char *fname);
void dt_to_source(FILE *f, struct dt_info *dti);
struct dt_info *dt_from_source(const char *f);

/* YAML source */

void dt_to_yaml(FILE *f, struct dt_info *dti);

/* FS trees */

struct dt_info *dt_from_fs(const char *dirname);

3
dtdiff
View File

@ -1,5 +1,4 @@
#! /bin/bash
# SPDX-License-Identifier: GPL-2.0-or-later

# This script uses the bash <(...) extension.
# If you want to change this to work with a generic /bin/sh, make sure
@ -17,7 +16,7 @@ source_and_sort () {
*.dts)
IFORMAT=dts
;;
*.dtb|*.dtbo)
*.dtb)
IFORMAT=dtb
;;
esac

View File

@ -1,4 +1,3 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* fdtdump.c - Contributed by Pantelis Antoniou <pantelis.antoniou AT gmail.com>
*/
@ -9,7 +8,6 @@
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <inttypes.h>

#include <libfdt.h>
#include <libfdt_env.h>
@ -18,10 +16,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)
@ -67,24 +65,23 @@ static void dump_blob(void *blob, bool debug)
shift = 4;

printf("/dts-v1/;\n");
printf("// magic:\t\t0x%"PRIx32"\n", fdt32_to_cpu(bph->magic));
printf("// totalsize:\t\t0x%"PRIx32" (%"PRIu32")\n",
totalsize, totalsize);
printf("// off_dt_struct:\t0x%"PRIx32"\n", off_dt);
printf("// off_dt_strings:\t0x%"PRIx32"\n", off_str);
printf("// off_mem_rsvmap:\t0x%"PRIx32"\n", off_mem_rsvmap);
printf("// version:\t\t%"PRIu32"\n", version);
printf("// last_comp_version:\t%"PRIu32"\n",
printf("// magic:\t\t0x%x\n", fdt32_to_cpu(bph->magic));
printf("// totalsize:\t\t0x%x (%d)\n", totalsize, totalsize);
printf("// off_dt_struct:\t0x%x\n", off_dt);
printf("// off_dt_strings:\t0x%x\n", off_str);
printf("// off_mem_rsvmap:\t0x%x\n", off_mem_rsvmap);
printf("// version:\t\t%d\n", version);
printf("// last_comp_version:\t%d\n",
fdt32_to_cpu(bph->last_comp_version));
if (version >= 2)
printf("// boot_cpuid_phys:\t0x%"PRIx32"\n",
printf("// boot_cpuid_phys:\t0x%x\n",
fdt32_to_cpu(bph->boot_cpuid_phys));

if (version >= 3)
printf("// size_dt_strings:\t0x%"PRIx32"\n",
printf("// size_dt_strings:\t0x%x\n",
fdt32_to_cpu(bph->size_dt_strings));
if (version >= 17)
printf("// size_dt_struct:\t0x%"PRIx32"\n",
printf("// size_dt_struct:\t0x%x\n",
fdt32_to_cpu(bph->size_dt_struct));
printf("\n");

@ -94,14 +91,14 @@ static void dump_blob(void *blob, bool debug)
if (addr == 0 && size == 0)
break;

printf("/memreserve/ %#"PRIx64" %#"PRIx64";\n",
addr, size);
printf("/memreserve/ %#llx %#llx;\n",
(unsigned long long)addr, (unsigned long long)size);
}

p = p_struct;
while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) {

dumpf("%04"PRIxPTR": tag: 0x%08"PRIx32" (%s)\n",
dumpf("%04zx: tag: 0x%08x (%s)\n",
(uintptr_t)p - blob_off - 4, tag, tagname(tag));

if (tag == FDT_BEGIN_NODE) {
@ -130,7 +127,7 @@ static void dump_blob(void *blob, bool debug)
}

if (tag != FDT_PROP) {
fprintf(stderr, "%*s ** Unknown tag 0x%08"PRIx32"\n", depth * shift, "", tag);
fprintf(stderr, "%*s ** Unknown tag 0x%08x\n", depth * shift, "", tag);
break;
}
sz = fdt32_to_cpu(GET_CELL(p));
@ -141,8 +138,8 @@ static void dump_blob(void *blob, bool debug)

p = PALIGN(p + sz, 4);

dumpf("%04"PRIxPTR": string: %s\n", (uintptr_t)s - blob_off, s);
dumpf("%04"PRIxPTR": value\n", (uintptr_t)t - blob_off);
dumpf("%04zx: string: %s\n", (uintptr_t)s - blob_off, s);
dumpf("%04zx: value\n", (uintptr_t)t - blob_off);
printf("%*s%s", depth * shift, "", s);
utilfdt_print_data(t, sz);
printf(";\n");
@ -163,7 +160,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 ||
@ -184,7 +181,7 @@ int main(int argc, char *argv[])
char *buf;
bool debug = false;
bool scan = false;
size_t len;
off_t len;

fprintf(stderr, "\n"
"**** fdtdump is a low-level debugging tool, not meant for general use.\n"
@ -207,7 +204,7 @@ int main(int argc, char *argv[])
usage("missing input filename");
file = argv[optind];

buf = utilfdt_read(file, &len);
buf = utilfdt_read_len(file, &len);
if (!buf)
die("could not read: %s\n", file);

@ -217,7 +214,7 @@ int main(int argc, char *argv[])
char *p = buf;
char *endp = buf + len;

fdt32_st(smagic, FDT_MAGIC);
fdt_set_magic(smagic, FDT_MAGIC);

/* poor man's memmem */
while ((endp - p) >= FDT_MAGIC_SIZE) {
@ -230,14 +227,14 @@ int main(int argc, char *argv[])
if (valid_header(p, this_len))
break;
if (debug)
printf("%s: skipping fdt magic at offset %#tx\n",
printf("%s: skipping fdt magic at offset %#zx\n",
file, p - buf);
}
++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);
printf("%s: found fdt at offset %#zx\n", file, p - buf);
buf = p;
} else if (!valid_header(buf, len))
die("%s: header is not valid\n", file);

View File

@ -1,4 +1,3 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
*
@ -7,6 +6,21 @@
* Based on code written by:
* Pantelis Antoniou <pantelis.antoniou@gmail.com> and
* Matthew McClintock <msm@freescale.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/

#include <assert.h>
@ -62,14 +76,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_to_cpu(*(const fdt32_t *)p) :
size == 2 ? (*p << 8) | p[1] : *p;
printf(fmt, value);
}

@ -97,11 +105,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) {
@ -137,6 +140,7 @@ static int show_data(struct display_info *disp, const char *data, int len)
*/
static int list_properties(const void *blob, int node)
{
const struct fdt_property *data;
const char *name;
int prop;

@ -145,7 +149,8 @@ static int list_properties(const void *blob, int node)
/* Stop silently when there are no more properties */
if (prop < 0)
return prop == -FDT_ERR_NOTFOUND ? 0 : prop;
fdt_getprop_by_offset(blob, prop, &name, NULL);
data = fdt_get_property_by_offset(blob, prop, NULL);
name = fdt_string(blob, fdt32_to_cpu(data->nameoff));
if (name)
puts(name);
prop = fdt_next_property_offset(blob, prop);
@ -268,7 +273,7 @@ static int do_fdtget(struct display_info *disp, const char *filename,
const char *prop;
int i, node;

blob = utilfdt_read(filename, NULL);
blob = utilfdt_read(filename);
if (!blob)
return -1;


View File

@ -1,9 +1,23 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2017 Konsulko Group Inc. All rights reserved.
*
* Author:
* Pantelis Antoniou <pantelis.antoniou@konsulko.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/

#include <assert.h>
@ -18,12 +32,12 @@

#include "util.h"

#define BUF_INCREMENT 65536

/* 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'},
@ -40,118 +54,65 @@ static const char * const usage_opts_help[] = {

int verbose = 0;

static void *apply_one(char *base, const char *overlay, size_t *buf_len,
const char *name)
{
char *tmp = NULL;
char *tmpo;
int ret;
bool has_symbols;

/*
* We take copies first, because a failed apply can trash
* both the base blob and the overlay
*/
tmpo = xmalloc(fdt_totalsize(overlay));

do {
tmp = xrealloc(tmp, *buf_len);
ret = fdt_open_into(base, tmp, *buf_len);
if (ret) {
fprintf(stderr,
"\nFailed to make temporary copy: %s\n",
fdt_strerror(ret));
goto fail;
}
ret = fdt_path_offset(tmp, "/__symbols__");
has_symbols = ret >= 0;

memcpy(tmpo, overlay, fdt_totalsize(overlay));

ret = fdt_overlay_apply(tmp, tmpo);
if (ret == -FDT_ERR_NOSPACE) {
*buf_len += BUF_INCREMENT;
}
} while (ret == -FDT_ERR_NOSPACE);

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;
}

free(base);
free(tmpo);
return tmp;

fail:
free(tmpo);
if (tmp)
free(tmp);

return NULL;
}
static int do_fdtoverlay(const char *input_filename,
const char *output_filename,
int argc, char *argv[])
{
char *blob = NULL;
char **ovblob = NULL;
size_t buf_len;
off_t blob_len, ov_len, total_len;
int i, ret = -1;

blob = utilfdt_read(input_filename, &buf_len);
blob = utilfdt_read_len(input_filename, &blob_len);
if (!blob) {
fprintf(stderr, "\nFailed to read '%s'\n", input_filename);
fprintf(stderr, "\nFailed to read base blob %s\n",
input_filename);
goto out_err;
}
if (fdt_totalsize(blob) > buf_len) {
if (fdt_totalsize(blob) > blob_len) {
fprintf(stderr,
"\nBase blob is incomplete (%lu / %" PRIu32 " bytes read)\n",
(unsigned long)buf_len, fdt_totalsize(blob));
(unsigned long)blob_len, fdt_totalsize(blob));
goto out_err;
}
ret = 0;

/* allocate blob pointer array */
ovblob = xmalloc(sizeof(*ovblob) * argc);
ovblob = malloc(sizeof(*ovblob) * argc);
memset(ovblob, 0, sizeof(*ovblob) * argc);

/* read and keep track of the overlay blobs */
total_len = 0;
for (i = 0; i < argc; i++) {
size_t ov_len;
ovblob[i] = utilfdt_read(argv[i], &ov_len);
ovblob[i] = utilfdt_read_len(argv[i], &ov_len);
if (!ovblob[i]) {
fprintf(stderr, "\nFailed to read '%s'\n", argv[i]);
goto out_err;
}
if (fdt_totalsize(ovblob[i]) > ov_len) {
fprintf(stderr,
"\nOverlay '%s' is incomplete (%lu / %" PRIu32 " bytes read)\n",
argv[i], (unsigned long)ov_len,
fdt_totalsize(ovblob[i]));
fprintf(stderr, "\nFailed to read overlay %s\n",
argv[i]);
goto out_err;
}
total_len += ov_len;
}

buf_len = fdt_totalsize(blob);
/* grow the blob to worst case */
blob_len = fdt_totalsize(blob) + total_len;
blob = xrealloc(blob, blob_len);
fdt_open_into(blob, blob, blob_len);

/* apply the overlays in sequence */
for (i = 0; i < argc; i++) {
blob = apply_one(blob, ovblob[i], &buf_len, argv[i]);
if (!blob)
ret = fdt_overlay_apply(blob, ovblob[i]);
if (ret) {
fprintf(stderr, "\nFailed to apply %s (%d)\n",
argv[i], ret);
goto out_err;
}
}

fdt_pack(blob);
ret = utilfdt_write(output_filename, blob);
if (ret)
fprintf(stderr, "\nFailed to write '%s'\n",
output_filename);
fprintf(stderr, "\nFailed to write output blob %s\n",
output_filename);

out_err:
if (ovblob) {

View File

@ -1,6 +1,20 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/

#include <assert.h>
@ -319,7 +333,7 @@ static int do_fdtput(struct display_info *disp, const char *filename,
char *node;
int len, ret = 0;

blob = utilfdt_read(filename, NULL);
blob = utilfdt_read(filename);
if (!blob)
return -1;

@ -389,8 +403,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",
@ -433,8 +447,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

@ -1,6 +1,21 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/

#include "dtc.h"
@ -124,8 +139,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 +149,9 @@ static void asm_emit_string(void *e, const char *str, int len)
FILE *f = e;

if (len != 0)
fprintf(f, "\t.asciz\t\"%.*s\"\n", len, str);
fprintf(f, "\t.string\t\"%.*s\"\n", len, str);
else
fprintf(f, "\t.asciz\t\"%s\"\n", str);
fprintf(f, "\t.string\t\"%s\"\n", str);
}

static void asm_emit_align(void *e, int a)
@ -150,14 +164,14 @@ static void asm_emit_align(void *e, int a)
static void asm_emit_data(void *e, struct data d)
{
FILE *f = e;
unsigned int off = 0;
int off = 0;
struct marker *m = d.markers;

for_each_marker_of_type(m, LABEL)
emit_offset_label(f, m->ref, m->offset);

while ((d.len - off) >= sizeof(uint32_t)) {
asm_emit_cell(e, dtb_ld32(d.val + off));
asm_emit_cell(e, fdt32_to_cpu(*((fdt32_t *)(d.val+off))));
off += sizeof(uint32_t);
}

@ -220,7 +234,7 @@ static struct emitter asm_emitter = {

static int stringtable_insert(struct data *d, const char *str)
{
unsigned int i;
int i;

/* FIXME: do this more efficiently? */

@ -296,7 +310,7 @@ static struct data flatten_reserve_list(struct reserve_info *reservelist,
{
struct reserve_info *re;
struct data d = empty_data;
unsigned int j;
int j;

for (re = reservelist; re; re = re->next) {
d = data_append_re(d, re->address, re->size);
@ -346,7 +360,7 @@ static void make_fdt_header(struct fdt_header *fdt,
void dt_to_blob(FILE *f, struct dt_info *dti, int version)
{
struct version_info *vi = NULL;
unsigned int i;
int i;
struct data blob = empty_data;
struct data reservebuf = empty_data;
struct data dtbuf = empty_data;
@ -379,7 +393,7 @@ void dt_to_blob(FILE *f, struct dt_info *dti, int version)
padlen = 0;
if (quiet < 1)
fprintf(stderr,
"Warning: blob size %"PRIu32" >= minimum size %d\n",
"Warning: blob size %d >= minimum size %d\n",
fdt32_to_cpu(fdt.totalsize), minsize);
}
}
@ -439,7 +453,7 @@ static void dump_stringtable_asm(FILE *f, struct data strbuf)

while (p < (strbuf.val + strbuf.len)) {
len = strlen(p);
fprintf(f, "\t.asciz \"%s\"\n", p);
fprintf(f, "\t.string \"%s\"\n", p);
p += len+1;
}
}
@ -447,7 +461,7 @@ static void dump_stringtable_asm(FILE *f, struct data strbuf)
void dt_to_asm(FILE *f, struct dt_info *dti, int version)
{
struct version_info *vi = NULL;
unsigned int i;
int i;
struct data strbuf = empty_data;
struct reserve_info *re;
const char *symprefix = "dt";
@ -503,7 +517,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");
@ -511,7 +525,7 @@ void dt_to_asm(FILE *f, struct dt_info *dti, int version)
fprintf(f, "/* Memory reserve map from source file */\n");

/*
* Use .long on high and low halves of u64s to avoid .quad
* Use .long on high and low halfs of u64s to avoid .quad
* as it appears .quad isn't available in some assemblers.
*/
for (re = dti->reservelist; re; re = re->next) {
@ -604,11 +618,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 +630,7 @@ static const char *flat_read_string(struct inbuf *inb)
len++;
} while ((*p++) != '\0');

str = inb->ptr;
str = xstrdup(inb->ptr);

inb->ptr += len;

@ -678,7 +692,7 @@ static struct property *flat_read_property(struct inbuf *dtbuf,

val = flat_read_data(dtbuf, proplen);

return build_property(name, val, NULL);
return build_property(name, val);
}


@ -711,7 +725,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 +739,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,18 +747,17 @@ 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);
node = build_node(NULL, NULL);

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 +799,10 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,
}
} while (val != FDT_END_NODE);

if (node->name != flatname) {
free(flatname);
}

return node;
}


View File

@ -1,6 +1,21 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/

#include "dtc.h"
@ -19,7 +34,7 @@ static struct node *read_fstree(const char *dirname)
if (!d)
die("Couldn't opendir() \"%s\": %s\n", dirname, strerror(errno));

tree = build_node(NULL, NULL, NULL);
tree = build_node(NULL, NULL);

while ((de = readdir(d)) != NULL) {
char *tmpname;
@ -30,7 +45,7 @@ static struct node *read_fstree(const char *dirname)

tmpname = join_path(dirname, de->d_name);

if (stat(tmpname, &st) < 0)
if (lstat(tmpname, &st) < 0)
die("stat(%s): %s\n", tmpname, strerror(errno));

if (S_ISREG(st.st_mode)) {
@ -43,10 +58,9 @@ 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);
st.st_size));
add_property(tree, prop);
fclose(pfile);
}

1
libfdt/.gitignore vendored
View File

@ -1 +0,0 @@
libfdt.so.1

View File

@ -1,22 +1,11 @@
# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
# Makefile.libfdt
#
# 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
fdt_addresses.c fdt_overlay.c
LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
LIBFDT_LIB = libfdt.$(SHAREDLIB_EXT).$(DTC_VERSION)

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,7 +1,52 @@
// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
*
* libfdt is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
*
* a) This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*
* Alternatively,
*
* b) Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libfdt_env.h"

@ -10,149 +55,36 @@

#include "libfdt_internal.h"

/*
* Minimal sanity check for a read-only tree. fdt_ro_probe_() checks
* that the given buffer contains what appears to be a flattened
* device tree with sane information in its header.
*/
int32_t fdt_ro_probe_(const void *fdt)
int fdt_check_header(const void *fdt)
{
uint32_t totalsize = fdt_totalsize(fdt);

if (can_assume(VALID_DTB))
return totalsize;

/* The device tree must be at an 8-byte aligned address */
if ((uintptr_t)fdt & 7)
return -FDT_ERR_ALIGNMENT;

if (fdt_magic(fdt) == FDT_MAGIC) {
/* Complete tree */
if (!can_assume(LATEST)) {
if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
return -FDT_ERR_BADVERSION;
if (fdt_last_comp_version(fdt) >
FDT_LAST_SUPPORTED_VERSION)
return -FDT_ERR_BADVERSION;
}
if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
return -FDT_ERR_BADVERSION;
if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)
return -FDT_ERR_BADVERSION;
} else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
/* Unfinished sequential-write blob */
if (!can_assume(VALID_INPUT) && fdt_size_dt_struct(fdt) == 0)
if (fdt_size_dt_struct(fdt) == 0)
return -FDT_ERR_BADSTATE;
} else {
return -FDT_ERR_BADMAGIC;
}

if (totalsize < INT32_MAX)
return totalsize;
else
return -FDT_ERR_TRUNCATED;
}

static int check_off_(uint32_t hdrsize, uint32_t totalsize, uint32_t off)
{
return (off >= hdrsize) && (off <= totalsize);
}

static int check_block_(uint32_t hdrsize, uint32_t totalsize,
uint32_t base, uint32_t size)
{
if (!check_off_(hdrsize, totalsize, base))
return 0; /* block start out of bounds */
if ((base + size) < base)
return 0; /* overflow */
if (!check_off_(hdrsize, totalsize, base + size))
return 0; /* block end out of bounds */
return 1;
}

size_t fdt_header_size_(uint32_t version)
{
if (version <= 1)
return FDT_V1_SIZE;
else if (version <= 2)
return FDT_V2_SIZE;
else if (version <= 3)
return FDT_V3_SIZE;
else if (version <= 16)
return FDT_V16_SIZE;
else
return FDT_V17_SIZE;
}

size_t fdt_header_size(const void *fdt)
{
return can_assume(LATEST) ? FDT_V17_SIZE :
fdt_header_size_(fdt_version(fdt));
}

int fdt_check_header(const void *fdt)
{
size_t hdrsize;

/* The device tree must be at an 8-byte aligned address */
if ((uintptr_t)fdt & 7)
return -FDT_ERR_ALIGNMENT;

if (fdt_magic(fdt) != FDT_MAGIC)
return -FDT_ERR_BADMAGIC;
if (!can_assume(LATEST)) {
if ((fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
|| (fdt_last_comp_version(fdt) >
FDT_LAST_SUPPORTED_VERSION))
return -FDT_ERR_BADVERSION;
if (fdt_version(fdt) < fdt_last_comp_version(fdt))
return -FDT_ERR_BADVERSION;
}
hdrsize = fdt_header_size(fdt);
if (!can_assume(VALID_DTB)) {
if ((fdt_totalsize(fdt) < hdrsize)
|| (fdt_totalsize(fdt) > INT_MAX))
return -FDT_ERR_TRUNCATED;

/* Bounds check memrsv block */
if (!check_off_(hdrsize, fdt_totalsize(fdt),
fdt_off_mem_rsvmap(fdt)))
return -FDT_ERR_TRUNCATED;

/* Bounds check structure block */
if (!can_assume(LATEST) && fdt_version(fdt) < 17) {
if (!check_off_(hdrsize, fdt_totalsize(fdt),
fdt_off_dt_struct(fdt)))
return -FDT_ERR_TRUNCATED;
} else {
if (!check_block_(hdrsize, fdt_totalsize(fdt),
fdt_off_dt_struct(fdt),
fdt_size_dt_struct(fdt)))
return -FDT_ERR_TRUNCATED;
}

/* Bounds check strings block */
if (!check_block_(hdrsize, fdt_totalsize(fdt),
fdt_off_dt_strings(fdt),
fdt_size_dt_strings(fdt)))
return -FDT_ERR_TRUNCATED;
}

return 0;
}

const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
{
unsigned int uoffset = offset;
unsigned int absoffset = offset + fdt_off_dt_struct(fdt);
unsigned absoffset = offset + fdt_off_dt_struct(fdt);

if (offset < 0)
if ((absoffset < offset)
|| ((absoffset + len) < absoffset)
|| (absoffset + len) > fdt_totalsize(fdt))
return NULL;

if (!can_assume(VALID_INPUT))
if ((absoffset < uoffset)
|| ((absoffset + len) < absoffset)
|| (absoffset + len) > fdt_totalsize(fdt))
return NULL;

if (can_assume(LATEST) || fdt_version(fdt) >= 0x11)
if (((uoffset + len) < uoffset)
if (fdt_version(fdt) >= 0x11)
if (((offset + len) < offset)
|| ((offset + len) > fdt_size_dt_struct(fdt)))
return NULL;

@ -162,13 +94,13 @@ 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;

*nextoffset = -FDT_ERR_TRUNCATED;
tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
if (!can_assume(VALID_DTB) && !tagp)
if (!tagp)
return FDT_END; /* premature end */
tag = fdt32_to_cpu(*tagp);
offset += FDT_TAGSIZE;
@ -180,28 +112,17 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
do {
p = fdt_offset_ptr(fdt, offset++, 1);
} while (p && (*p != '\0'));
if (!can_assume(VALID_DTB) && !p)
if (!p)
return FDT_END; /* premature end */
break;

case FDT_PROP:
lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
if (!can_assume(VALID_DTB) && !lenp)
if (!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;

if (!can_assume(LATEST) &&
fdt_version(fdt) < 0x10 && len >= 8 &&
((offset - len) % 8) != 0)
offset += 4;
offset += sizeof(struct fdt_property) - FDT_TAGSIZE
+ fdt32_to_cpu(*lenp);
break;

case FDT_END:
@ -222,11 +143,8 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)

int fdt_check_node_offset_(const void *fdt, int offset)
{
if (!can_assume(VALID_INPUT)
&& ((offset < 0) || (offset % FDT_TAGSIZE)))
return -FDT_ERR_BADOFFSET;

if (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE)
if ((offset < 0) || (offset % FDT_TAGSIZE)
|| (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE))
return -FDT_ERR_BADOFFSET;

return offset;
@ -234,11 +152,8 @@ int fdt_check_node_offset_(const void *fdt, int offset)

int fdt_check_prop_offset_(const void *fdt, int offset)
{
if (!can_assume(VALID_INPUT)
&& ((offset < 0) || (offset % FDT_TAGSIZE)))
return -FDT_ERR_BADOFFSET;

if (fdt_next_tag(fdt, offset, &offset) != FDT_PROP)
if ((offset < 0) || (offset % FDT_TAGSIZE)
|| (fdt_next_tag(fdt, offset, &offset) != FDT_PROP))
return -FDT_ERR_BADOFFSET;

return offset;
@ -312,26 +227,23 @@ int fdt_next_subnode(const void *fdt, int offset)
return offset;
}

const char *fdt_find_string_len_(const char *strtab, int tabsize, const char *s,
int slen)
const char *fdt_find_string_(const char *strtab, int tabsize, const char *s)
{
const char *last = strtab + tabsize - (slen + 1);
int len = strlen(s) + 1;
const char *last = strtab + tabsize - len;
const char *p;

for (p = strtab; p <= last; p++)
if (memcmp(p, s, slen) == 0 && p[slen] == '\0')
if (memcmp(p, s, len) == 0)
return p;
return NULL;
}

int fdt_move(const void *fdt, void *buf, int bufsize)
{
if (!can_assume(VALID_INPUT) && bufsize < 0)
return -FDT_ERR_NOSPACE;
FDT_CHECK_HEADER(fdt);

FDT_RO_PROBE(fdt);

if (fdt_totalsize(fdt) > (unsigned int)bufsize)
if (fdt_totalsize(fdt) > bufsize)
return -FDT_ERR_NOSPACE;

memmove(buf, fdt, fdt_totalsize(fdt));

View File

@ -1,13 +1,58 @@
/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
#ifndef FDT_H
#define FDT_H
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
* Copyright 2012 Kim Phillips, Freescale Semiconductor.
*
* libfdt is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
*
* a) This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*
* Alternatively,
*
* b) Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef __ASSEMBLER__
#ifndef __ASSEMBLY__

struct fdt_header {
fdt32_t magic; /* magic word FDT_MAGIC */
@ -35,17 +80,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

@ -1,8 +1,52 @@
// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2014 David Gibson <david@gibson.dropbear.id.au>
* Copyright (C) 2018 embedded brains GmbH
*
* libfdt is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
*
* a) This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*
* Alternatively,
*
* b) Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libfdt_env.h"

@ -11,91 +55,42 @@

#include "libfdt_internal.h"

static int fdt_cells(const void *fdt, int nodeoffset, const char *name)
{
const fdt32_t *c;
uint32_t val;
int len;

c = fdt_getprop(fdt, nodeoffset, name, &len);
if (!c)
return len;

if (len != sizeof(*c))
return -FDT_ERR_BADNCELLS;

val = fdt32_to_cpu(*c);
if (val > FDT_MAX_NCELLS)
return -FDT_ERR_BADNCELLS;

return (int)val;
}

int fdt_address_cells(const void *fdt, int nodeoffset)
{
const fdt32_t *ac;
int val;
int len;

val = fdt_cells(fdt, nodeoffset, "#address-cells");
if (val == 0)
return -FDT_ERR_BADNCELLS;
if (val == -FDT_ERR_NOTFOUND)
ac = fdt_getprop(fdt, nodeoffset, "#address-cells", &len);
if (!ac)
return 2;

if (len != sizeof(*ac))
return -FDT_ERR_BADNCELLS;

val = fdt32_to_cpu(*ac);
if ((val <= 0) || (val > FDT_MAX_NCELLS))
return -FDT_ERR_BADNCELLS;

return val;
}

int fdt_size_cells(const void *fdt, int nodeoffset)
{
const fdt32_t *sc;
int val;
int len;

sc = fdt_getprop(fdt, nodeoffset, "#size-cells", &len);
if (!sc)
return 2;

if (len != sizeof(*sc))
return -FDT_ERR_BADNCELLS;

val = fdt32_to_cpu(*sc);
if ((val < 0) || (val > FDT_MAX_NCELLS))
return -FDT_ERR_BADNCELLS;

val = fdt_cells(fdt, nodeoffset, "#size-cells");
if (val == -FDT_ERR_NOTFOUND)
return 1;
return val;
}

/* This function assumes that [address|size]_cells is 1 or 2 */
int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset,
const char *name, uint64_t addr, uint64_t size)
{
int addr_cells, size_cells, ret;
uint8_t data[sizeof(fdt64_t) * 2], *prop;

ret = fdt_address_cells(fdt, parent);
if (ret < 0)
return ret;
addr_cells = ret;

ret = fdt_size_cells(fdt, parent);
if (ret < 0)
return ret;
size_cells = ret;

/* check validity of address */
prop = data;
if (addr_cells == 1) {
if ((addr > UINT32_MAX) || (((uint64_t) UINT32_MAX + 1 - addr) < size))
return -FDT_ERR_BADVALUE;

fdt32_st(prop, (uint32_t)addr);
} else if (addr_cells == 2) {
fdt64_st(prop, addr);
} else {
return -FDT_ERR_BADNCELLS;
}

/* check validity of size */
prop += addr_cells * sizeof(fdt32_t);
if (size_cells == 1) {
if (size > UINT32_MAX)
return -FDT_ERR_BADVALUE;

fdt32_st(prop, (uint32_t)size);
} else if (size_cells == 2) {
fdt64_st(prop, size);
} else {
return -FDT_ERR_BADNCELLS;
}

return fdt_appendprop(fdt, nodeoffset, name, data,
(addr_cells + size_cells) * sizeof(fdt32_t));
}

View File

@ -1,96 +0,0 @@
// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
*/
#include "libfdt_env.h"

#include <fdt.h>
#include <libfdt.h>

#include "libfdt_internal.h"

int fdt_check_full(const void *fdt, size_t bufsize)
{
int err;
int num_memrsv;
int offset, nextoffset = 0;
uint32_t tag;
unsigned int depth = 0;
const void *prop;
const char *propname;
bool expect_end = false;

if (bufsize < FDT_V1_SIZE)
return -FDT_ERR_TRUNCATED;
if (bufsize < fdt_header_size(fdt))
return -FDT_ERR_TRUNCATED;
err = fdt_check_header(fdt);
if (err != 0)
return err;
if (bufsize < fdt_totalsize(fdt))
return -FDT_ERR_TRUNCATED;

num_memrsv = fdt_num_mem_rsv(fdt);
if (num_memrsv < 0)
return num_memrsv;

while (1) {
offset = nextoffset;
tag = fdt_next_tag(fdt, offset, &nextoffset);

if (nextoffset < 0)
return nextoffset;

/* If we see two root nodes, something is wrong */
if (expect_end && tag != FDT_END)
return -FDT_ERR_BADSTRUCTURE;

switch (tag) {
case FDT_NOP:
break;

case FDT_END:
if (depth != 0)
return -FDT_ERR_BADSTRUCTURE;
return 0;

case FDT_BEGIN_NODE:
depth++;
if (depth > INT_MAX)
return -FDT_ERR_BADSTRUCTURE;

/* The root node must have an empty name */
if (depth == 1) {
const char *name;
int len;

name = fdt_get_name(fdt, offset, &len);
if (!name)
return len;

if (*name || len)
return -FDT_ERR_BADSTRUCTURE;
}
break;

case FDT_END_NODE:
if (depth == 0)
return -FDT_ERR_BADSTRUCTURE;
depth--;
if (depth == 0)
expect_end = true;
break;

case FDT_PROP:
prop = fdt_getprop_by_offset(fdt, offset, &propname,
&err);
if (!prop)
return err;
break;

default:
return -FDT_ERR_INTERNAL;
}
}
}

View File

@ -1,7 +1,52 @@
// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2012 David Gibson, IBM Corporation.
*
* libfdt is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
*
* a) This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*
* Alternatively,
*
* b) Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libfdt_env.h"


View File

@ -1,9 +1,3 @@
// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2016 Free Electrons
* Copyright (C) 2016 NextThing Co.
*/
#include "libfdt_env.h"

#include <fdt.h>
@ -40,22 +34,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 targetting is
* done (through a phandle or a path)
*
* returns:
* the targetted node offset in the base device tree
* Negative error code on error
*/
static int overlay_get_target(const void *fdt, const void *fdto,
int fragment, 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 +110,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 +222,8 @@ static int overlay_update_local_node_references(void *fdto,

fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {
const fdt32_t *fixup_val;
const char *tree_val;
const char *name;
char *tree_val;
int fixup_len;
int tree_len;
int i;
@ -222,9 +235,8 @@ static int overlay_update_local_node_references(void *fdto,

if (fixup_len % sizeof(uint32_t))
return -FDT_ERR_BADOVERLAY;
fixup_len /= sizeof(uint32_t);

tree_val = fdt_getprop_w(fdto, tree_node, name, &tree_len);
tree_val = fdt_getprop(fdto, tree_node, name, &tree_len);
if (!tree_val) {
if (tree_len == -FDT_ERR_NOTFOUND)
return -FDT_ERR_BADOVERLAY;
@ -232,16 +244,34 @@ static int overlay_update_local_node_references(void *fdto,
return tree_len;
}

for (i = 0; i < fixup_len; i++) {
fdt32_t *refp;
for (i = 0; i < (fixup_len / sizeof(uint32_t)); i++) {
fdt32_t adj_val;
uint32_t poffset;

refp = (fdt32_t *)(tree_val + fdt32_ld_(fixup_val + i));
poffset = fdt32_to_cpu(fixup_val[i]);

/*
* phandles to fixup can be unaligned, so use
* fdt32_{ld,st}() to read/write them.
* phandles to fixup can be unaligned.
*
* Use a memcpy for the architectures that do
* not support unaligned accesses.
*/
fdt32_st(refp, fdt32_ld(refp) + delta);
memcpy(&adj_val, tree_val + poffset, sizeof(adj_val));

adj_val = cpu_to_fdt32(fdt32_to_cpu(adj_val) + delta);

ret = fdt_setprop_inplace_namelen_partial(fdto,
tree_node,
name,
strlen(name),
poffset,
&adj_val,
sizeof(adj_val));
if (ret == -FDT_ERR_NOSPACE)
return -FDT_ERR_BADOVERLAY;

if (ret)
return ret;
}
}

@ -307,6 +337,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 +345,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 +358,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 +397,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 +424,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 +434,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 +473,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 +528,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 +629,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;

@ -863,7 +646,7 @@ static int get_path_len(const void *fdt, int nodeoffset)
int len = 0, namelen;
const char *name;

FDT_RO_PROBE(fdt);
FDT_CHECK_HEADER(fdt);

for (;;) {
name = fdt_get_name(fdt, nodeoffset, &namelen);
@ -944,36 +727,26 @@ static int overlay_symbol_update(void *fdt, void *fdto)
/* keep end marker to avoid strlen() */
e = path + path_len;

/* format: /<fragment-name>/__overlay__/<relative-subnode-path> */

if (*path != '/')
return -FDT_ERR_BADVALUE;

/* get fragment name first */
s = strchr(path + 1, '/');
if (!s) {
/* Symbol refers to something that won't end
* up in the target tree */
continue;
}
if (!s)
return -FDT_ERR_BADOVERLAY;

frag_name = path + 1;
frag_name_len = s - path - 1;

/* verify format; safe since "s" lies in \0 terminated prop */
len = sizeof("/__overlay__/") - 1;
if ((e - s) > len && (memcmp(s, "/__overlay__/", len) == 0)) {
/* /<fragment-name>/__overlay__/<relative-subnode-path> */
rel_path = s + len;
rel_path_len = e - rel_path - 1;
} else if ((e - s) == len
&& (memcmp(s, "/__overlay__", len - 1) == 0)) {
/* /<fragment-name>/__overlay__ */
rel_path = "";
rel_path_len = 0;
} else {
/* Symbol refers to something that won't end
* up in the target tree */
continue;
}
if ((e - s) < len || memcmp(s, "/__overlay__/", len))
return -FDT_ERR_BADOVERLAY;

rel_path = s + len;
rel_path_len = e - rel_path;

/* find the fragment index in which the symbol lies */
ret = fdt_subnode_offset_namelen(fdto, 0, frag_name,
@ -989,7 +762,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 +784,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;
@ -1039,36 +812,24 @@ static int overlay_symbol_update(void *fdt, void *fdto)

int fdt_overlay_apply(void *fdt, void *fdto)
{
uint32_t delta;
uint32_t delta = fdt_get_max_phandle(fdt);
int ret;

FDT_RO_PROBE(fdt);
FDT_RO_PROBE(fdto);
FDT_CHECK_HEADER(fdt);
FDT_CHECK_HEADER(fdto);

ret = fdt_find_max_phandle(fdt, &delta);
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

@ -1,7 +1,52 @@
// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
*
* libfdt is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
*
* a) This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*
* Alternatively,
*
* b) Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libfdt_env.h"

@ -13,10 +58,9 @@
static int fdt_nodename_eq_(const void *fdt, int offset,
const char *s, int len)
{
int olen;
const char *p = fdt_get_name(fdt, offset, &olen);
const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1);

if (!p || olen < len)
if (!p)
/* short match */
return 0;

@ -31,171 +75,60 @@ static int fdt_nodename_eq_(const void *fdt, int offset,
return 0;
}

const char *fdt_get_string(const void *fdt, int stroffset, int *lenp)
{
int32_t totalsize;
uint32_t absoffset;
size_t len;
int err;
const char *s, *n;

if (can_assume(VALID_INPUT)) {
s = (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;

if (lenp)
*lenp = strlen(s);
return s;
}
totalsize = fdt_ro_probe_(fdt);
err = totalsize;
if (totalsize < 0)
goto fail;

err = -FDT_ERR_BADOFFSET;
absoffset = stroffset + fdt_off_dt_strings(fdt);
if (absoffset >= (unsigned)totalsize)
goto fail;
len = totalsize - absoffset;

if (fdt_magic(fdt) == FDT_MAGIC) {
if (stroffset < 0)
goto fail;
if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
if ((unsigned)stroffset >= fdt_size_dt_strings(fdt))
goto fail;
if ((fdt_size_dt_strings(fdt) - stroffset) < len)
len = fdt_size_dt_strings(fdt) - stroffset;
}
} else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
unsigned int sw_stroffset = -stroffset;

if ((stroffset >= 0) ||
(sw_stroffset > fdt_size_dt_strings(fdt)))
goto fail;
if (sw_stroffset < len)
len = sw_stroffset;
} else {
err = -FDT_ERR_INTERNAL;
goto fail;
}

s = (const char *)fdt + absoffset;
n = memchr(s, '\0', len);
if (!n) {
/* missing terminating NULL */
err = -FDT_ERR_TRUNCATED;
goto fail;
}

if (lenp)
*lenp = n - s;
return s;

fail:
if (lenp)
*lenp = err;
return NULL;
}

const char *fdt_string(const void *fdt, int stroffset)
{
return fdt_get_string(fdt, stroffset, NULL);
return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
}

static int fdt_string_eq_(const void *fdt, int stroffset,
const char *s, int len)
{
int slen;
const char *p = fdt_get_string(fdt, stroffset, &slen);
const char *p = fdt_string(fdt, stroffset);

return p && (slen == len) && (memcmp(p, s, len) == 0);
return (strlen(p) == len) && (memcmp(p, s, len) == 0);
}

int fdt_find_max_phandle(const void *fdt, uint32_t *phandle)
uint32_t fdt_get_max_phandle(const void *fdt)
{
uint32_t max = 0;
int offset = -1;
uint32_t max_phandle = 0;
int offset;

while (true) {
uint32_t value;
for (offset = fdt_next_node(fdt, -1, NULL);;
offset = fdt_next_node(fdt, offset, NULL)) {
uint32_t phandle;

offset = fdt_next_node(fdt, offset, NULL);
if (offset < 0) {
if (offset == -FDT_ERR_NOTFOUND)
break;
if (offset == -FDT_ERR_NOTFOUND)
return max_phandle;

return offset;
}
if (offset < 0)
return (uint32_t)-1;

value = fdt_get_phandle(fdt, offset);
phandle = fdt_get_phandle(fdt, offset);
if (phandle == (uint32_t)-1)
continue;

if (value > max)
max = value;
if (phandle > max_phandle)
max_phandle = phandle;
}

if (phandle)
*phandle = max;

return 0;
}

int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
{
uint32_t max;
int err;

err = fdt_find_max_phandle(fdt, &max);
if (err < 0)
return err;

if (max == FDT_MAX_PHANDLE)
return -FDT_ERR_NOPHANDLES;

if (phandle)
*phandle = max + 1;

return 0;
}

static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n)
{
unsigned int offset = n * sizeof(struct fdt_reserve_entry);
unsigned int absoffset = fdt_off_mem_rsvmap(fdt) + offset;

if (!can_assume(VALID_INPUT)) {
if (absoffset < fdt_off_mem_rsvmap(fdt))
return NULL;
if (absoffset > fdt_totalsize(fdt) -
sizeof(struct fdt_reserve_entry))
return NULL;
}
return fdt_mem_rsv_(fdt, n);
}

int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
{
const struct fdt_reserve_entry *re;

FDT_RO_PROBE(fdt);
re = fdt_mem_rsv(fdt, n);
if (!can_assume(VALID_INPUT) && !re)
return -FDT_ERR_BADOFFSET;

*address = fdt64_ld_(&re->address);
*size = fdt64_ld_(&re->size);
FDT_CHECK_HEADER(fdt);
*address = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->address);
*size = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->size);
return 0;
}

int fdt_num_mem_rsv(const void *fdt)
{
int i;
const struct fdt_reserve_entry *re;
int i = 0;

for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) {
if (fdt64_ld_(&re->size) == 0)
return i;
}
return -FDT_ERR_TRUNCATED;
while (fdt64_to_cpu(fdt_mem_rsv_(fdt, i)->size) != 0)
i++;
return i;
}

static int nextprop_(const void *fdt, int offset)
@ -227,7 +160,7 @@ int fdt_subnode_offset_namelen(const void *fdt, int offset,
{
int depth;

FDT_RO_PROBE(fdt);
FDT_CHECK_HEADER(fdt);

for (depth = 0;
(offset >= 0) && (depth >= 0);
@ -253,10 +186,7 @@ int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen)
const char *p = path;
int offset = 0;

FDT_RO_PROBE(fdt);

if (!can_assume(VALID_INPUT) && namelen <= 0)
return -FDT_ERR_BADPATH;
FDT_CHECK_HEADER(fdt);

/* see if we have an alias */
if (*path != '/') {
@ -303,34 +233,16 @@ int fdt_path_offset(const void *fdt, const char *path)
const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
{
const struct fdt_node_header *nh = fdt_offset_ptr_(fdt, nodeoffset);
const char *nameptr;
int err;

if (((err = fdt_ro_probe_(fdt)) < 0)
if (((err = fdt_check_header(fdt)) != 0)
|| ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0))
goto fail;

nameptr = nh->name;

if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
/*
* For old FDT versions, match the naming conventions of V16:
* give only the leaf name (after all /). The actual tree
* contents are loosely checked.
*/
const char *leaf;
leaf = strrchr(nameptr, '/');
if (leaf == NULL) {
err = -FDT_ERR_BADSTRUCTURE;
goto fail;
}
nameptr = leaf+1;
}

if (len)
*len = strlen(nameptr);
*len = strlen(nh->name);

return nameptr;
return nh->name;

fail:
if (len)
@ -356,15 +268,14 @@ int fdt_next_property_offset(const void *fdt, int offset)
return nextprop_(fdt, offset);
}

static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt,
int offset,
int *lenp)
const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
int offset,
int *lenp)
{
int err;
const struct fdt_property *prop;

if (!can_assume(VALID_INPUT) &&
(err = fdt_check_prop_offset_(fdt, offset)) < 0) {
if ((err = fdt_check_prop_offset_(fdt, offset)) < 0) {
if (lenp)
*lenp = err;
return NULL;
@ -373,76 +284,35 @@ static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt,
prop = fdt_offset_ptr_(fdt, offset);

if (lenp)
*lenp = fdt32_ld_(&prop->len);
*lenp = fdt32_to_cpu(prop->len);

return prop;
}

const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
int offset,
int *lenp)
{
/* Prior to version 16, properties may need realignment
* and this API does not work. fdt_getprop_*() will, however. */

if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
if (lenp)
*lenp = -FDT_ERR_BADVERSION;
return NULL;
}

return fdt_get_property_by_offset_(fdt, offset, lenp);
}

static const struct fdt_property *fdt_get_property_namelen_(const void *fdt,
int offset,
const char *name,
int namelen,
int *lenp,
int *poffset)
{
for (offset = fdt_first_property_offset(fdt, offset);
(offset >= 0);
(offset = fdt_next_property_offset(fdt, offset))) {
const struct fdt_property *prop;

prop = fdt_get_property_by_offset_(fdt, offset, lenp);
if (!can_assume(LIBFDT_FLAWLESS) && !prop) {
offset = -FDT_ERR_INTERNAL;
break;
}
if (fdt_string_eq_(fdt, fdt32_ld_(&prop->nameoff),
name, namelen)) {
if (poffset)
*poffset = offset;
return prop;
}
}

if (lenp)
*lenp = offset;
return NULL;
}


const struct fdt_property *fdt_get_property_namelen(const void *fdt,
int offset,
const char *name,
int namelen, int *lenp)
{
/* Prior to version 16, properties may need realignment
* and this API does not work. fdt_getprop_*() will, however. */
if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
if (lenp)
*lenp = -FDT_ERR_BADVERSION;
return NULL;
for (offset = fdt_first_property_offset(fdt, offset);
(offset >= 0);
(offset = fdt_next_property_offset(fdt, offset))) {
const struct fdt_property *prop;

if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) {
offset = -FDT_ERR_INTERNAL;
break;
}
if (fdt_string_eq_(fdt, fdt32_to_cpu(prop->nameoff),
name, namelen))
return prop;
}

return fdt_get_property_namelen_(fdt, offset, name, namelen, lenp,
NULL);
if (lenp)
*lenp = offset;
return NULL;
}


const struct fdt_property *fdt_get_property(const void *fdt,
int nodeoffset,
const char *name, int *lenp)
@ -454,18 +324,12 @@ const struct fdt_property *fdt_get_property(const void *fdt,
const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
const char *name, int namelen, int *lenp)
{
int poffset;
const struct fdt_property *prop;

prop = fdt_get_property_namelen_(fdt, nodeoffset, name, namelen, lenp,
&poffset);
prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp);
if (!prop)
return NULL;

/* Handle realignment */
if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
(poffset + sizeof(*prop)) % 8 && fdt32_ld_(&prop->len) >= 8)
return prop->data + 4;
return prop->data;
}

@ -474,31 +338,11 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
{
const struct fdt_property *prop;

prop = fdt_get_property_by_offset_(fdt, offset, lenp);
prop = fdt_get_property_by_offset(fdt, offset, lenp);
if (!prop)
return NULL;
if (namep) {
const char *name;
int namelen;

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;
}
} else {
*namep = fdt_string(fdt, fdt32_ld_(&prop->nameoff));
}
}

/* Handle realignment */
if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
(offset + sizeof(*prop)) % 8 && fdt32_ld_(&prop->len) >= 8)
return prop->data + 4;
if (namep)
*namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
return prop->data;
}

@ -522,34 +366,19 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
return 0;
}

return fdt32_ld_(php);
}

static const void *fdt_path_getprop_namelen(const void *fdt, const char *path,
const char *propname, int propnamelen,
int *lenp)
{
int offset = fdt_path_offset(fdt, path);

if (offset < 0)
return NULL;

return fdt_getprop_namelen(fdt, offset, propname, propnamelen, lenp);
return fdt32_to_cpu(*php);
}

const char *fdt_get_alias_namelen(const void *fdt,
const char *name, int namelen)
{
int len;
const char *alias;
int aliasoffset;

alias = fdt_path_getprop_namelen(fdt, "/aliases", name, namelen, &len);

if (!can_assume(VALID_DTB) &&
!(alias && len > 0 && alias[len - 1] == '\0' && *alias == '/'))
aliasoffset = fdt_path_offset(fdt, "/aliases");
if (aliasoffset < 0)
return NULL;

return alias;
return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL);
}

const char *fdt_get_alias(const void *fdt, const char *name)
@ -557,24 +386,13 @@ 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;
int offset, depth, namelen;
const char *name;

FDT_RO_PROBE(fdt);
FDT_CHECK_HEADER(fdt);

if (buflen < 2)
return -FDT_ERR_NOSPACE;
@ -626,7 +444,7 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
int offset, depth;
int supernodeoffset = -FDT_ERR_INTERNAL;

FDT_RO_PROBE(fdt);
FDT_CHECK_HEADER(fdt);

if (supernodedepth < 0)
return -FDT_ERR_NOTFOUND;
@ -648,12 +466,10 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
}
}

if (!can_assume(VALID_INPUT)) {
if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
return -FDT_ERR_BADOFFSET;
else if (offset == -FDT_ERR_BADOFFSET)
return -FDT_ERR_BADSTRUCTURE;
}
if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
return -FDT_ERR_BADOFFSET;
else if (offset == -FDT_ERR_BADOFFSET)
return -FDT_ERR_BADSTRUCTURE;

return offset; /* error from fdt_next_node() */
}
@ -665,8 +481,7 @@ int fdt_node_depth(const void *fdt, int nodeoffset)

err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth);
if (err)
return (can_assume(LIBFDT_FLAWLESS) || err < 0) ? err :
-FDT_ERR_INTERNAL;
return (err < 0) ? err : -FDT_ERR_INTERNAL;
return nodedepth;
}

@ -688,7 +503,7 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
const void *val;
int len;

FDT_RO_PROBE(fdt);
FDT_CHECK_HEADER(fdt);

/* FIXME: The algorithm here is pretty horrible: we scan each
* property of a node in fdt_getprop(), then if that didn't
@ -711,10 +526,10 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
{
int offset;

if ((phandle == 0) || (phandle == ~0U))
if ((phandle == 0) || (phandle == -1))
return -FDT_ERR_BADPHANDLE;

FDT_RO_PROBE(fdt);
FDT_CHECK_HEADER(fdt);

/* FIXME: The algorithm here is pretty horrible: we
* potentially scan each property of a node in
@ -867,7 +682,7 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
{
int offset, err;

FDT_RO_PROBE(fdt);
FDT_CHECK_HEADER(fdt);

/* FIXME: The algorithm here is pretty horrible: we scan each
* property of a node in fdt_node_check_compatible(), then if

View File

@ -1,7 +1,52 @@
// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
*
* libfdt is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
*
* a) This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*
* Alternatively,
*
* b) Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libfdt_env.h"

@ -22,31 +67,29 @@ static int fdt_blocks_misordered_(const void *fdt,
(fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt)));
}

static int fdt_rw_probe_(void *fdt)
static int fdt_rw_check_header_(void *fdt)
{
if (can_assume(VALID_DTB))
return 0;
FDT_RO_PROBE(fdt);
FDT_CHECK_HEADER(fdt);

if (!can_assume(LATEST) && fdt_version(fdt) < 17)
if (fdt_version(fdt) < 17)
return -FDT_ERR_BADVERSION;
if (fdt_blocks_misordered_(fdt, sizeof(struct fdt_reserve_entry),
fdt_size_dt_struct(fdt)))
return -FDT_ERR_BADLAYOUT;
if (!can_assume(LATEST) && fdt_version(fdt) > 17)
if (fdt_version(fdt) > 17)
fdt_set_version(fdt, 17);

return 0;
}

#define FDT_RW_PROBE(fdt) \
#define FDT_RW_CHECK_HEADER(fdt) \
{ \
int err_; \
if ((err_ = fdt_rw_probe_(fdt)) != 0) \
if ((err_ = fdt_rw_check_header_(fdt)) != 0) \
return err_; \
}

static inline unsigned int fdt_data_size_(void *fdt)
static inline int fdt_data_size_(void *fdt)
{
return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
}
@ -54,16 +97,15 @@ static inline unsigned int fdt_data_size_(void *fdt)
static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen)
{
char *p = splicepoint;
unsigned int dsize = fdt_data_size_(fdt);
size_t soff = p - (char *)fdt;
char *end = (char *)fdt + fdt_data_size_(fdt);

if ((oldlen < 0) || (soff + oldlen < soff) || (soff + oldlen > dsize))
if (((p + oldlen) < p) || ((p + oldlen) > end))
return -FDT_ERR_BADOFFSET;
if ((p < (char *)fdt) || (dsize + newlen < (unsigned)oldlen))
if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt))
return -FDT_ERR_BADOFFSET;
if (dsize - oldlen + newlen > fdt_totalsize(fdt))
if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt)))
return -FDT_ERR_NOSPACE;
memmove(p + newlen, p + oldlen, ((char *)fdt + dsize) - (p + oldlen));
memmove(p + newlen, p + oldlen, end - p - oldlen);
return 0;
}

@ -94,14 +136,6 @@ static int fdt_splice_struct_(void *fdt, void *p,
return 0;
}

/* Must only be used to roll back in case of error */
static void fdt_del_last_string_(void *fdt, const char *s)
{
int newlen = strlen(s) + 1;

fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) - newlen);
}

static int fdt_splice_string_(void *fdt, int newlen)
{
void *p = (char *)fdt
@ -115,42 +149,25 @@ static int fdt_splice_string_(void *fdt, int newlen)
return 0;
}

/**
* fdt_find_add_string_() - Find or allocate a string
*
* @fdt: pointer to the device tree to check/adjust
* @s: string to find/add
* @allocated: Set to 0 if the string was found, 1 if not found and so
* 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)
{
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);
}

@ -159,7 +176,7 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)
struct fdt_reserve_entry *re;
int err;

FDT_RW_PROBE(fdt);
FDT_RW_CHECK_HEADER(fdt);

re = fdt_mem_rsv_w_(fdt, fdt_num_mem_rsv(fdt));
err = fdt_splice_mem_rsv_(fdt, re, 0, 1);
@ -175,7 +192,7 @@ int fdt_del_mem_rsv(void *fdt, int n)
{
struct fdt_reserve_entry *re = fdt_mem_rsv_w_(fdt, n);

FDT_RW_PROBE(fdt);
FDT_RW_CHECK_HEADER(fdt);

if (n >= fdt_num_mem_rsv(fdt))
return -FDT_ERR_NOTFOUND;
@ -183,15 +200,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,18 +219,17 @@ 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;
int namestroff;
int err;
int allocated;

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);
if (namestroff < 0)
return namestroff;

@ -223,12 +237,8 @@ static int fdt_add_property_(void *fdt, int nodeoffset, const char *name,
proplen = sizeof(**prop) + FDT_TAGALIGN(len);

err = fdt_splice_struct_(fdt, *prop, 0, proplen);
if (err) {
/* Delete the string if we failed to add it */
if (!can_assume(NO_ROLLBACK) && allocated)
fdt_del_last_string_(fdt, name);
if (err)
return err;
}

(*prop)->tag = cpu_to_fdt32(FDT_PROP);
(*prop)->nameoff = cpu_to_fdt32(namestroff);
@ -242,7 +252,7 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name)
int oldlen, newlen;
int err;

FDT_RW_PROBE(fdt);
FDT_RW_CHECK_HEADER(fdt);

namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen);
if (!namep)
@ -259,18 +269,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);
FDT_RW_CHECK_HEADER(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 +287,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;

@ -300,7 +308,7 @@ int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
struct fdt_property *prop;
int err, oldlen, newlen;

FDT_RW_PROBE(fdt);
FDT_RW_CHECK_HEADER(fdt);

prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
if (prop) {
@ -313,8 +321,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);
@ -327,7 +334,7 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name)
struct fdt_property *prop;
int len, proplen;

FDT_RW_PROBE(fdt);
FDT_RW_CHECK_HEADER(fdt);

prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
if (!prop)
@ -347,7 +354,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
uint32_t tag;
fdt32_t *endtag;

FDT_RW_PROBE(fdt);
FDT_RW_CHECK_HEADER(fdt);

offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen);
if (offset >= 0)
@ -356,10 +363,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
return offset;

/* Try to place the new node after the parent's properties */
tag = fdt_next_tag(fdt, parentoffset, &nextoffset);
/* the fdt_subnode_offset_namelen() should ensure this never hits */
if (!can_assume(LIBFDT_FLAWLESS) && (tag != FDT_BEGIN_NODE))
return -FDT_ERR_INTERNAL;
fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */
do {
offset = nextoffset;
tag = fdt_next_tag(fdt, offset, &nextoffset);
@ -390,7 +394,7 @@ int fdt_del_node(void *fdt, int nodeoffset)
{
int endoffset;

FDT_RW_PROBE(fdt);
FDT_RW_CHECK_HEADER(fdt);

endoffset = fdt_node_end_offset_(fdt, nodeoffset);
if (endoffset < 0)
@ -401,9 +405,7 @@ int fdt_del_node(void *fdt, int nodeoffset)
}

static void fdt_packblocks_(const char *old, char *new,
int mem_rsv_size,
int struct_size,
int strings_size)
int mem_rsv_size, int struct_size)
{
int mem_rsv_off, struct_off, strings_off;

@ -418,7 +420,8 @@ static void fdt_packblocks_(const char *old, char *new,
fdt_set_off_dt_struct(new, struct_off);
fdt_set_size_dt_struct(new, struct_size);

memmove(new + strings_off, old + fdt_off_dt_strings(old), strings_size);
memmove(new + strings_off, old + fdt_off_dt_strings(old),
fdt_size_dt_strings(old));
fdt_set_off_dt_strings(new, strings_off);
fdt_set_size_dt_strings(new, fdt_size_dt_strings(old));
}
@ -432,25 +435,22 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
const char *fdtend = fdtstart + fdt_totalsize(fdt);
char *tmp;

FDT_RO_PROBE(fdt);
FDT_CHECK_HEADER(fdt);

mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
* sizeof(struct fdt_reserve_entry);

if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
if (fdt_version(fdt) >= 17) {
struct_size = fdt_size_dt_struct(fdt);
} else if (fdt_version(fdt) == 16) {
} else {
struct_size = 0;
while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END)
;
if (struct_size < 0)
return struct_size;
} else {
return -FDT_ERR_BADVERSION;
}

if (can_assume(LIBFDT_ORDER) ||
!fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) {
if (!fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) {
/* no further work necessary */
err = fdt_move(fdt, buf, bufsize);
if (err)
@ -478,8 +478,7 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
return -FDT_ERR_NOSPACE;
}

fdt_packblocks_(fdt, tmp, mem_rsv_size, struct_size,
fdt_size_dt_strings(fdt));
fdt_packblocks_(fdt, tmp, mem_rsv_size, struct_size);
memmove(buf, tmp, newsize);

fdt_set_magic(buf, FDT_MAGIC);
@ -495,12 +494,11 @@ int fdt_pack(void *fdt)
{
int mem_rsv_size;

FDT_RW_PROBE(fdt);
FDT_RW_CHECK_HEADER(fdt);

mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
* sizeof(struct fdt_reserve_entry);
fdt_packblocks_(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt),
fdt_size_dt_strings(fdt));
fdt_packblocks_(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt));
fdt_set_totalsize(fdt, fdt_data_size_(fdt));

return 0;

View File

@ -1,7 +1,51 @@
// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
*
* libfdt is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
*
* a) This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*
* Alternatively,
*
* b) Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libfdt_env.h"
@ -38,10 +82,8 @@ static struct fdt_errtabent fdt_errtable[] = {
FDT_ERRTABENT(FDT_ERR_BADVALUE),
FDT_ERRTABENT(FDT_ERR_BADOVERLAY),
FDT_ERRTABENT(FDT_ERR_NOPHANDLES),
FDT_ERRTABENT(FDT_ERR_BADFLAGS),
FDT_ERRTABENT(FDT_ERR_ALIGNMENT),
};
#define FDT_ERRTABSIZE ((int)(sizeof(fdt_errtable) / sizeof(fdt_errtable[0])))
#define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))

const char *fdt_strerror(int errval)
{
@ -49,7 +91,7 @@ const char *fdt_strerror(int errval)
return "<valid offset/length>";
else if (errval == 0)
return "<no error>";
else if (-errval < FDT_ERRTABSIZE) {
else if (errval > -FDT_ERRTABSIZE) {
const char *s = fdt_errtable[-errval].str;

if (s)

View File

@ -1,7 +1,52 @@
// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
*
* libfdt is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
*
* a) This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*
* Alternatively,
*
* b) Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libfdt_env.h"

@ -10,91 +55,25 @@

#include "libfdt_internal.h"

static int fdt_sw_probe_(void *fdt)
static int fdt_sw_check_header_(void *fdt)
{
if (!can_assume(VALID_INPUT)) {
if (fdt_magic(fdt) == FDT_MAGIC)
return -FDT_ERR_BADSTATE;
else if (fdt_magic(fdt) != FDT_SW_MAGIC)
return -FDT_ERR_BADMAGIC;
}

if (fdt_magic(fdt) != FDT_SW_MAGIC)
return -FDT_ERR_BADMAGIC;
/* FIXME: should check more details about the header state */
return 0;
}

#define FDT_SW_PROBE(fdt) \
#define FDT_SW_CHECK_HEADER(fdt) \
{ \
int err; \
if ((err = fdt_sw_probe_(fdt)) != 0) \
if ((err = fdt_sw_check_header_(fdt)) != 0) \
return err; \
}

/* 'memrsv' state: Initial state after fdt_create()
*
* Allowed functions:
* fdt_add_reservemap_entry()
* fdt_finish_reservemap() [moves to 'struct' state]
*/
static int fdt_sw_probe_memrsv_(void *fdt)
{
int err = fdt_sw_probe_(fdt);
if (err)
return err;

if (!can_assume(VALID_INPUT) && fdt_off_dt_strings(fdt) != 0)
return -FDT_ERR_BADSTATE;
return 0;
}

#define FDT_SW_PROBE_MEMRSV(fdt) \
{ \
int err; \
if ((err = fdt_sw_probe_memrsv_(fdt)) != 0) \
return err; \
}

/* 'struct' state: Enter this state after fdt_finish_reservemap()
*
* Allowed functions:
* fdt_begin_node()
* fdt_end_node()
* fdt_property*()
* fdt_finish() [moves to 'complete' state]
*/
static int fdt_sw_probe_struct_(void *fdt)
{
int err = fdt_sw_probe_(fdt);
if (err)
return err;

if (!can_assume(VALID_INPUT) &&
fdt_off_dt_strings(fdt) != fdt_totalsize(fdt))
return -FDT_ERR_BADSTATE;
return 0;
}

#define FDT_SW_PROBE_STRUCT(fdt) \
{ \
int err; \
if ((err = fdt_sw_probe_struct_(fdt)) != 0) \
return err; \
}

static inline uint32_t sw_flags(void *fdt)
{
/* assert: (fdt_magic(fdt) == FDT_SW_MAGIC) */
return fdt_last_comp_version(fdt);
}

/* 'complete' state: Enter this state after fdt_finish()
*
* Allowed functions: none
*/

static void *fdt_grab_space_(void *fdt, size_t len)
{
unsigned int offset = fdt_size_dt_struct(fdt);
unsigned int spaceleft;
int offset = fdt_size_dt_struct(fdt);
int spaceleft;

spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt)
- fdt_size_dt_strings(fdt);
@ -106,63 +85,39 @@ static void *fdt_grab_space_(void *fdt, size_t len)
return fdt_offset_ptr_w_(fdt, offset);
}

int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags)
int fdt_create(void *buf, int bufsize)
{
const int hdrsize = FDT_ALIGN(sizeof(struct fdt_header),
sizeof(struct fdt_reserve_entry));
void *fdt = buf;

if (bufsize < hdrsize)
if (bufsize < sizeof(struct fdt_header))
return -FDT_ERR_NOSPACE;

if (flags & ~FDT_CREATE_FLAGS_ALL)
return -FDT_ERR_BADFLAGS;

memset(buf, 0, bufsize);

/*
* magic and last_comp_version keep intermediate state during the fdt
* creation process, which is replaced with the proper FDT format by
* fdt_finish().
*
* flags should be accessed with sw_flags().
*/
fdt_set_magic(fdt, FDT_SW_MAGIC);
fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION);
fdt_set_last_comp_version(fdt, flags);

fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
fdt_set_totalsize(fdt, bufsize);

fdt_set_off_mem_rsvmap(fdt, hdrsize);
fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header),
sizeof(struct fdt_reserve_entry)));
fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt));
fdt_set_off_dt_strings(fdt, 0);
fdt_set_off_dt_strings(fdt, bufsize);

return 0;
}

int fdt_create(void *buf, int bufsize)
{
return fdt_create_with_flags(buf, bufsize, 0);
}

int fdt_resize(void *fdt, void *buf, int bufsize)
{
size_t headsize, tailsize;
char *oldtail, *newtail;

FDT_SW_PROBE(fdt);
FDT_SW_CHECK_HEADER(fdt);

if (bufsize < 0)
return -FDT_ERR_NOSPACE;

headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
headsize = fdt_off_dt_struct(fdt);
tailsize = fdt_size_dt_strings(fdt);

if (!can_assume(VALID_DTB) &&
headsize + tailsize > fdt_totalsize(fdt))
return -FDT_ERR_INTERNAL;

if ((headsize + tailsize) > (unsigned)bufsize)
if ((headsize + tailsize) > bufsize)
return -FDT_ERR_NOSPACE;

oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize;
@ -178,9 +133,8 @@ int fdt_resize(void *fdt, void *buf, int bufsize)
memmove(buf, fdt, headsize);
}

fdt_set_off_dt_strings(buf, bufsize);
fdt_set_totalsize(buf, bufsize);
if (fdt_off_dt_strings(buf))
fdt_set_off_dt_strings(buf, bufsize);

return 0;
}
@ -190,7 +144,10 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
struct fdt_reserve_entry *re;
int offset;

FDT_SW_PROBE_MEMRSV(fdt);
FDT_SW_CHECK_HEADER(fdt);

if (fdt_size_dt_struct(fdt))
return -FDT_ERR_BADSTATE;

offset = fdt_off_dt_struct(fdt);
if ((offset + sizeof(*re)) > fdt_totalsize(fdt))
@ -207,23 +164,16 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)

int fdt_finish_reservemap(void *fdt)
{
int err = fdt_add_reservemap_entry(fdt, 0, 0);

if (err)
return err;

fdt_set_off_dt_strings(fdt, fdt_totalsize(fdt));
return 0;
return fdt_add_reservemap_entry(fdt, 0, 0);
}

int fdt_begin_node(void *fdt, const char *name)
{
struct fdt_node_header *nh;
int namelen;
int namelen = strlen(name) + 1;

FDT_SW_PROBE_STRUCT(fdt);
FDT_SW_CHECK_HEADER(fdt);

namelen = strlen(name) + 1;
nh = fdt_grab_space_(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
if (! nh)
return -FDT_ERR_NOSPACE;
@ -237,7 +187,7 @@ int fdt_end_node(void *fdt)
{
fdt32_t *en;

FDT_SW_PROBE_STRUCT(fdt);
FDT_SW_CHECK_HEADER(fdt);

en = fdt_grab_space_(fdt, FDT_TAGSIZE);
if (! en)
@ -247,73 +197,43 @@ int fdt_end_node(void *fdt)
return 0;
}

static int fdt_add_string_(void *fdt, const char *s)
static int fdt_find_add_string_(void *fdt, const char *s)
{
char *strtab = (char *)fdt + fdt_totalsize(fdt);
unsigned int strtabsize = fdt_size_dt_strings(fdt);
unsigned int len = strlen(s) + 1;
unsigned int struct_top, offset;

offset = strtabsize + len;
struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
if (fdt_totalsize(fdt) - offset < struct_top)
return 0; /* no more room :( */

memcpy(strtab - offset, s, len);
fdt_set_size_dt_strings(fdt, strtabsize + len);
return -offset;
}

/* Must only be used to roll back in case of error */
static void fdt_del_last_string_(void *fdt, const char *s)
{
const char *p;
int strtabsize = fdt_size_dt_strings(fdt);
int len = strlen(s) + 1;

fdt_set_size_dt_strings(fdt, strtabsize - len);
}

static int fdt_find_add_string_(void *fdt, const char *s, int *allocated)
{
char *strtab = (char *)fdt + fdt_totalsize(fdt);
int strtabsize = fdt_size_dt_strings(fdt);
const char *p;

*allocated = 0;
int struct_top, offset;

p = fdt_find_string_(strtab - strtabsize, strtabsize, s);
if (p)
return p - strtab;

*allocated = 1;
/* Add it */
offset = -strtabsize - len;
struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
if (fdt_totalsize(fdt) + offset < struct_top)
return 0; /* no more room :( */

return fdt_add_string_(fdt, s);
memcpy(strtab + offset, s, len);
fdt_set_size_dt_strings(fdt, strtabsize + len);
return offset;
}

int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp)
{
struct fdt_property *prop;
int nameoff;
int allocated;

FDT_SW_PROBE_STRUCT(fdt);
FDT_SW_CHECK_HEADER(fdt);

/* String de-duplication can be slow, _NO_NAME_DEDUP skips it */
if (sw_flags(fdt) & FDT_CREATE_FLAG_NO_NAME_DEDUP) {
allocated = 1;
nameoff = fdt_add_string_(fdt, name);
} else {
nameoff = fdt_find_add_string_(fdt, name, &allocated);
}
nameoff = fdt_find_add_string_(fdt, name);
if (nameoff == 0)
return -FDT_ERR_NOSPACE;

prop = fdt_grab_space_(fdt, sizeof(*prop) + FDT_TAGALIGN(len));
if (! prop) {
if (allocated)
fdt_del_last_string_(fdt, name);
if (! prop)
return -FDT_ERR_NOSPACE;
}

prop->tag = cpu_to_fdt32(FDT_PROP);
prop->nameoff = cpu_to_fdt32(nameoff);
@ -342,7 +262,7 @@ int fdt_finish(void *fdt)
uint32_t tag;
int offset, nextoffset;

FDT_SW_PROBE_STRUCT(fdt);
FDT_SW_CHECK_HEADER(fdt);

/* Add terminator */
end = fdt_grab_space_(fdt, sizeof(*end));
@ -375,10 +295,6 @@ int fdt_finish(void *fdt)

/* Finally, adjust the header */
fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));

/* And fix up fields that were keeping intermediate state. */
fdt_set_last_comp_version(fdt, FDT_LAST_COMPATIBLE_VERSION);
fdt_set_magic(fdt, FDT_MAGIC);

return 0;
}

View File

@ -1,7 +1,52 @@
// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
*
* libfdt is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
*
* a) This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*
* Alternatively,
*
* b) Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libfdt_env.h"

@ -23,7 +68,7 @@ int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
if (!propval)
return proplen;

if ((unsigned)proplen < (len + idx))
if (proplen < (len + idx))
return -FDT_ERR_NOSPACE;

memcpy((char *)propval + idx, val, len);

File diff suppressed because it is too large Load Diff

View File

@ -1,18 +1,61 @@
/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
#ifndef LIBFDT_ENV_H
#define LIBFDT_ENV_H
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
* Copyright 2012 Kim Phillips, Freescale Semiconductor.
*
* libfdt is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
*
* a) This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*
* Alternatively,
*
* b) Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>

#ifdef __CHECKER__
#define FDT_FORCE __attribute__((force))

View File

@ -1,35 +1,70 @@
/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
#ifndef LIBFDT_INTERNAL_H
#define LIBFDT_INTERNAL_H
/*
* libfdt - Flat Device Tree manipulation
* Copyright (C) 2006 David Gibson, IBM Corporation.
*
* libfdt is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
*
* a) This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*
* Alternatively,
*
* b) Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <fdt.h>
#include <string.h>

#define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
#define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE))

int32_t fdt_ro_probe_(const void *fdt);
#define FDT_RO_PROBE(fdt) \
{ \
int32_t totalsize_; \
if ((totalsize_ = fdt_ro_probe_(fdt)) < 0) \
return totalsize_; \
#define FDT_CHECK_HEADER(fdt) \
{ \
int err_; \
if ((err_ = fdt_check_header(fdt)) != 0) \
return err_; \
}

int fdt_check_node_offset_(const void *fdt, int offset);
int fdt_check_prop_offset_(const void *fdt, int offset);

const char *fdt_find_string_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,147 +90,6 @@ static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n)
return (void *)(uintptr_t)fdt_mem_rsv_(fdt, n);
}

/*
* Internal helpers to access structural elements of the device tree
* blob (rather than for example reading integers from within property
* values). We assume that we are either given a naturally aligned
* address for the platform or if we are not, we are on a platform
* where unaligned memory reads will be handled in a graceful manner.
* If not the external helpers fdtXX_ld() from libfdt.h can be used
* instead.
*/
static inline uint32_t fdt32_ld_(const fdt32_t *p)
{
return fdt32_to_cpu(*p);
}

static inline uint64_t fdt64_ld_(const fdt64_t *p)
{
return fdt64_to_cpu(*p);
}

#define FDT_SW_MAGIC (~FDT_MAGIC)

/**********************************************************************/
/* Checking controls */
/**********************************************************************/

#ifndef FDT_ASSUME_MASK
#define FDT_ASSUME_MASK 0
#endif

/*
* Defines assumptions which can be enabled. Each of these can be enabled
* individually. For maximum safety, don't enable any assumptions!
*
* For minimal code size and no safety, use ASSUME_PERFECT at your own risk.
* You should have another method of validating the device tree, such as a
* signature or hash check before using libfdt.
*
* For situations where security is not a concern it may be safe to enable
* ASSUME_SANE.
*/
enum {
/*
* This does essentially no checks. Only the latest device-tree
* version is correctly handled. Inconsistencies or errors in the device
* tree may cause undefined behaviour or crashes. Invalid parameters
* passed to libfdt may do the same.
*
* If an error occurs when modifying the tree it may leave the tree in
* an intermediate (but valid) state. As an example, adding a property
* where there is insufficient space may result in the property name
* being added to the string table even though the property itself is
* not added to the struct section.
*
* Only use this if you have a fully validated device tree with
* the latest supported version and wish to minimise code size.
*/
ASSUME_PERFECT = 0xff,

/*
* This assumes that the device tree is sane. i.e. header metadata
* and basic hierarchy are correct.
*
* With this assumption enabled, normal device trees produced by libfdt
* and the compiler should be handled safely. Malicious device trees and
* complete garbage may cause libfdt to behave badly or crash. Truncated
* device trees (e.g. those only partially loaded) can also cause
* problems.
*
* Note: Only checks that relate exclusively to the device tree itself
* (not the parameters passed to libfdt) are disabled by this
* assumption. This includes checking headers, tags and the like.
*/
ASSUME_VALID_DTB = 1 << 0,

/*
* This builds on ASSUME_VALID_DTB and further assumes that libfdt
* functions are called with valid parameters, i.e. not trigger
* FDT_ERR_BADOFFSET or offsets that are out of bounds. It disables any
* extensive checking of parameters and the device tree, making various
* assumptions about correctness.
*
* It doesn't make sense to enable this assumption unless
* ASSUME_VALID_DTB is also enabled.
*/
ASSUME_VALID_INPUT = 1 << 1,

/*
* This disables checks for device-tree version and removes all code
* which handles older versions.
*
* Only enable this if you know you have a device tree with the latest
* version.
*/
ASSUME_LATEST = 1 << 2,

/*
* This assumes that it is OK for a failed addition to the device tree,
* due to lack of space or some other problem, to skip any rollback
* steps (such as dropping the property name from the string table).
* This is safe to enable in most circumstances, even though it may
* leave the tree in a sub-optimal state.
*/
ASSUME_NO_ROLLBACK = 1 << 3,

/*
* This assumes that the device tree components appear in a 'convenient'
* order, i.e. the memory reservation block first, then the structure
* block and finally the string block.
*
* This order is not specified by the device-tree specification,
* but is expected by libfdt. The device-tree compiler always created
* device trees with this order.
*
* This assumption disables a check in fdt_open_into() and removes the
* ability to fix the problem there. This is safe if you know that the
* device tree is correctly ordered. See fdt_blocks_misordered_().
*/
ASSUME_LIBFDT_ORDER = 1 << 4,

/*
* This assumes that libfdt itself does not have any internal bugs. It
* drops certain checks that should never be needed unless libfdt has an
* undiscovered bug.
*
* This can generally be considered safe to enable.
*/
ASSUME_LIBFDT_FLAWLESS = 1 << 5,
};

/**
* can_assume_() - check if a particular assumption is enabled
*
* @mask: Mask to check (ASSUME_...)
* @return true if that assumption is enabled, else false
*/
static inline bool can_assume_(int mask)
{
return FDT_ASSUME_MASK & mask;
}

/** helper macros for checking assumptions */
#define can_assume(_assume) can_assume_(ASSUME_ ## _assume)

#endif /* LIBFDT_INTERNAL_H */

View File

@ -1,63 +0,0 @@
version_script = '-Wl,--version-script=@0@'.format(meson.current_source_dir() / 'version.lds')
if not cc.has_link_argument(version_script)
version_script = []
endif

sources = files(
'fdt.c',
'fdt_addresses.c',
'fdt_check.c',
'fdt_empty_tree.c',
'fdt_overlay.c',
'fdt_ro.c',
'fdt_rw.c',
'fdt_strerror.c',
'fdt_sw.c',
'fdt_wip.c',
)

link_args = []
if cc.has_link_argument('-Wl,--no-undefined')
link_args += '-Wl,--no-undefined'
else
# -undefined error is the equivalent of --no-undefined for the macOS linker,
# but -undefined would also be understood as a valid argument for GNU ld!
link_args += cc.get_supported_link_arguments('-Wl,-undefined,error')
endif

link_args += version_script
libfdt = library(
'fdt', sources,
version: meson.project_version(),
link_args: link_args,
link_depends: 'version.lds',
install: get_option('default_library') != 'static' or not wheel_only,
)

libfdt_inc = include_directories('.')

libfdt_dep = declare_dependency(
include_directories: libfdt_inc,
link_with: libfdt,
)
meson.override_dependency('libfdt', libfdt_dep)

if not wheel_only
install_headers(
files(
'fdt.h',
'libfdt.h',
'libfdt_env.h',
)
)

pkgconfig = import('pkgconfig')

pkgconfig.generate(
libraries: libfdt,
version: meson.project_version(),
filebase: 'libfdt',
name: 'libfdt',
description: 'Flat Device Tree manipulation',
)
endif

View File

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

View File

@ -1,4 +1,3 @@
/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
LIBFDT_1.2 {
global:
fdt_next_node;
@ -20,7 +19,6 @@ LIBFDT_1.2 {
fdt_get_alias_namelen;
fdt_get_alias;
fdt_get_path;
fdt_header_size;
fdt_supernode_atdepth_offset;
fdt_node_depth;
fdt_parent_offset;
@ -43,7 +41,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;
@ -68,20 +65,7 @@ LIBFDT_1.2 {
fdt_stringlist_get;
fdt_resize;
fdt_overlay_apply;
fdt_get_string;
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

@ -1,10 +1,24 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/

#include "dtc.h"
#include "srcpos.h"

/*
* Tree building functions
@ -36,27 +50,25 @@ void delete_labels(struct label **labels)
label->deleted = 1;
}

struct property *build_property(const char *name, struct data val,
struct srcpos *srcpos)
struct property *build_property(char *name, struct data val)
{
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;
@ -85,8 +97,7 @@ struct property *reverse_properties(struct property *first)
return head;
}

struct node *build_node(struct property *proplist, struct node *children,
struct srcpos *srcpos)
struct node *build_node(struct property *proplist, struct node *children)
{
struct node *new = xmalloc(sizeof(*new));
struct node *child;
@ -95,7 +106,6 @@ struct node *build_node(struct property *proplist, struct node *children,

new->proplist = reverse_properties(proplist);
new->children = children;
new->srcpos = srcpos_copy(srcpos);

for_each_child(new, child) {
child->parent = new;
@ -104,37 +114,22 @@ struct node *build_node(struct property *proplist, struct node *children,
return new;
}

struct node *build_node_delete(struct srcpos *srcpos)
struct node *build_node_delete(void)
{
struct node *new = xmalloc(sizeof(*new));

memset(new, 0, sizeof(*new));

new->deleted = 1;
new->srcpos = srcpos_copy(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);

return node;
}

struct node *omit_node_if_unused(struct node *node)
{
node->omit_if_unused = 1;

return node;
}

struct node *reference_node(struct node *node)
{
node->is_referenced = 1;
node->name = name;

return node;
}
@ -174,8 +169,6 @@ 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);
old_prop->srcpos = new_prop->srcpos;
free(new_prop);
new_prop = NULL;
break;
@ -216,8 +209,6 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
add_child(old_node, new_child);
}

old_node->srcpos = srcpos_extend(old_node->srcpos, new_node->srcpos);

/* The new node contents are now merged into the old node. Free
* the new node. */
free(new_node);
@ -233,24 +224,16 @@ struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref)
struct data d = empty_data;
char *name;

if (ref[0] == '/') {
d = data_add_marker(d, TYPE_STRING, ref);
d = data_append_data(d, ref, strlen(ref) + 1);
d = data_add_marker(d, REF_PHANDLE, ref);
d = data_append_integer(d, 0xffffffff, 32);

p = build_property("target-path", d, NULL);
} else {
d = data_add_marker(d, REF_PHANDLE, ref);
d = data_append_integer(d, 0xffffffff, 32);

p = build_property("target", d, NULL);
}
p = build_property("target", d);

xasprintf(&name, "fragment@%u",
next_orphan_fragment++);
name_node(new_node, "__overlay__");
node = build_node(p, new_node, NULL);
node = build_node(p, new_node);
name_node(node, name);
free(name);

add_child(dt, node);
return dt;
@ -337,21 +320,18 @@ void delete_node(struct node *node)
}

void append_to_property(struct node *node,
char *name, const void *data, int len,
enum markertype type)
char *name, const void *data, int len)
{
struct data d;
struct property *p;

p = get_property(node, name);
if (p) {
d = data_add_marker(p->val, type, name);
d = data_append_data(d, data, len);
d = data_append_data(p->val, data, len);
p->val = d;
} else {
d = data_add_marker(empty_data, type, name);
d = data_append_data(d, data, len);
p = build_property(name, d, NULL);
d = data_append_data(empty_data, data, len);
p = build_property(name, d);
add_property(node, p);
}
}
@ -439,9 +419,9 @@ cell_t propval_cell(struct property *prop)
return fdt32_to_cpu(*((fdt32_t *)prop->val.val));
}

cell_t propval_cell_n(struct property *prop, unsigned int n)
cell_t propval_cell_n(struct property *prop, int n)
{
assert(prop->val.len / sizeof(cell_t) > n);
assert(prop->val.len / sizeof(cell_t) >= n);
return fdt32_to_cpu(*((fdt32_t *)prop->val.val + n));
}

@ -504,7 +484,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;
@ -527,7 +507,8 @@ 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 && (strlen(child->name) == p-path) &&
strprefixeq(path, p - path, child->name))
return get_node_by_path(child, p+1);
else if (!p && streq(path, child->name))
return child;
@ -560,7 +541,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;
}
@ -582,62 +563,19 @@ 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 */

if (phandle_is_valid(node->phandle))
if ((node->phandle != 0) && (node->phandle != -1))
return node->phandle;

while (get_node_by_phandle(root, phandle))
@ -645,8 +583,17 @@ 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);
if (!get_property(node, "linux,phandle")
&& (phandle_format & PHANDLE_LEGACY))
add_property(node,
build_property("linux,phandle",
data_append_cell(empty_data, phandle)));

if (!get_property(node, "phandle")
&& (phandle_format & PHANDLE_EPAPR))
add_property(node,
build_property("phandle",
data_append_cell(empty_data, phandle)));

/* If the node *does* have a phandle property, we must
* be dealing with a self-referencing phandle, which will be
@ -816,18 +763,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);
node = build_node(NULL, NULL);
name_node(node, xstrdup(name));
add_child(parent, node);

return node;
}

static struct node *build_root_node(struct node *dt, const char *name)
static struct node *build_root_node(struct node *dt, char *name)
{
struct node *an;

@ -881,9 +828,8 @@ static void generate_label_tree_internal(struct dt_info *dti,

/* insert it */
p = build_property(l->label,
data_copy_escape_string(node->fullpath,
strlen(node->fullpath)),
NULL);
data_copy_mem(node->fullpath,
strlen(node->fullpath) + 1));
add_property(an, p);
}

@ -927,19 +873,13 @@ static void add_fixup_entry(struct dt_info *dti, struct node *fn,
/* 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);
append_to_property(fn, m->ref, entry, strlen(entry) + 1, TYPE_STRING);
append_to_property(fn, m->ref, entry, strlen(entry) + 1);

free(entry);
}
@ -999,7 +939,7 @@ static void add_local_fixup_entry(struct dt_info *dti,
char **compp;
int i, depth;

/* walk back retrieving depth */
/* walk back retreiving depth */
depth = 0;
for (wn = node; wn; wn = wn->parent)
depth++;
@ -1014,13 +954,15 @@ static void 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);
append_to_property(wn, prop->name, &value_32, sizeof(value_32), TYPE_UINT32);
append_to_property(wn, prop->name, &value_32, sizeof(value_32));
}

static void generate_local_fixups_tree_internal(struct dt_info *dti,
@ -1046,7 +988,7 @@ static void generate_local_fixups_tree_internal(struct dt_info *dti,
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;
@ -1054,31 +996,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)
{
struct node *n = get_subnode(dti->dt, name);

/* Start with an empty __fixups__ node to not get duplicates */
if (n)
n->deleted = true;

if (!any_fixup_tree(dti, dti->dt))
return;
generate_fixups_tree_internal(dti,
build_and_name_child_node(dti->dt, 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)
{
struct node *n = get_subnode(dti->dt, name);

/* Start with an empty __local_fixups__ node to not get duplicates */
if (n)
n->deleted = true;
if (!any_local_fixup_tree(dti, dti->dt))
return;
generate_local_fixups_tree_internal(dti,
build_and_name_child_node(dti->dt, name),
generate_local_fixups_tree_internal(dti, build_root_node(dti->dt, name),
dti->dt);
}

View File

@ -1,131 +0,0 @@
project('dtc', 'c',
version: files('VERSION.txt'),
license: ['GPL2+', 'BSD-2'],
default_options: ['werror=true', 'default_library=both'],
meson_version: '>=0.57.0'
)

cc = meson.get_compiler('c')

add_project_arguments(
cc.get_supported_arguments([
'-Wpointer-arith',
'-Wcast-qual',
'-Wnested-externs',
'-Wstrict-prototypes',
'-Wmissing-prototypes',
'-Wredundant-decls',
'-Wshadow',
'-Wsuggest-attribute=format',
'-Wwrite-strings',
]),
language: 'c'
)

add_project_arguments(
'-DFDT_ASSUME_MASK=' + get_option('assume-mask').to_string(),
language: 'c'
)

yamltree = 'yamltree.c'
yaml = dependency('yaml-0.1', version: '>=0.2.3', required: get_option('yaml'))
if not yaml.found()
add_project_arguments('-DNO_YAML', language: 'c')
yamltree = []
endif

valgrind = dependency('valgrind', required: get_option('valgrind'))
if not valgrind.found()
add_project_arguments('-DNO_VALGRIND', language: 'c')
endif

py = import('python')
py = py.find_installation(required: get_option('python'))
swig = find_program('swig', required: get_option('python'))
pylibfdt_enabled = not meson.is_cross_build() and py.found() and swig.found() ? true : false
wheel_only = get_option('wheel-only')

version_gen_h = vcs_tag(
command: ['git', 'describe', '--dirty=+'],
input: 'version_gen.h.in',
output: 'version_gen.h',
)

subdir('libfdt')

dtc_tools = []
util_dep = declare_dependency(
sources: ['util.c', version_gen_h],
include_directories: '.',
dependencies: libfdt_dep
)

if get_option('tools') and not wheel_only
flex = find_program('flex', required: true)
bison = find_program('bison', required: true)

lgen = generator(
flex,
output: '@PLAINNAME@.lex.c',
arguments: ['-o', '@OUTPUT@', '@INPUT@'],
)

pgen = generator(
bison,
output: ['@BASENAME@.tab.c', '@BASENAME@.tab.h'],
arguments: ['@INPUT@', '--defines=@OUTPUT1@', '--output=@OUTPUT0@'],
)

if cc.check_header('fnmatch.h')
dtc_tools += executable(
'convert-dtsv0',
[
lgen.process('convert-dtsv0-lexer.l'),
'srcpos.c',
],
dependencies: util_dep,
install: true,
)
endif

dtc_tools += executable(
'dtc',
[
lgen.process('dtc-lexer.l'),
pgen.process('dtc-parser.y'),
'checks.c',
'data.c',
'dtc.c',
'flattree.c',
'fstree.c',
'livetree.c',
'srcpos.c',
'treesource.c',
yamltree,
],
dependencies: [util_dep, yaml],
install: true,
)

foreach e: ['fdtdump', 'fdtget', 'fdtput', 'fdtoverlay']
dtc_tools += executable(e, files(e + '.c'), dependencies: util_dep, install: true)
endforeach

install_data(
'dtdiff',
install_dir: get_option('bindir'),
install_mode: 'rwxr-xr-x',
)
endif

foreach e: dtc_tools
meson.override_find_program(e.name(), e)
endforeach

if pylibfdt_enabled
subdir('pylibfdt')
endif

if get_option('tests')
subdir('tests')
endif

View File

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

2
pylibfdt/.gitignore vendored
View File

@ -1,3 +1,3 @@
libfdt.py
*.pyc
libfdt.pyc
libfdt_wrap.c

View File

@ -0,0 +1,24 @@
# Makefile.pylibfdt
#

PYLIBFDT_srcs = $(addprefix $(LIBFDT_srcdir)/,$(LIBFDT_SRCS)) \
$(PYLIBFDT_srcdir)/libfdt.i
PYMODULE = $(PYLIBFDT_objdir)/_libfdt.so

define run_setup
SOURCES="$(1)" CPPFLAGS="$(CPPFLAGS)" OBJDIR="$(PYLIBFDT_objdir)"
VERSION="$(dtc_version)"
$(PYLIBFDT_objdir)/setup.py --quiet $(2)
endef

$(PYMODULE): $(PYLIBFDT_srcs)
@$(VECHO) PYMOD $@
$(call run_setup, $^, build_ext --inplace)
mv _libfdt.so $@

install_pylibfdt: $(PYMODULE)
$(VECHO) INSTALL-PYLIB; \
$(call run_setup, $(PYLIBFDT_srcs), \
install $(if $(SETUP_PREFIX),--prefix=$(SETUP_PREFIX)))

PYLIBFDT_cleanfiles = libfdt_wrap.c libfdt.py libfdt.pyc _libfdt.so

File diff suppressed because it is too large Load Diff

View File

@ -1,21 +0,0 @@
libfdt_c = custom_target(
'swig',
input: 'libfdt.i',
output: ['libfdt.c', 'libfdt.py'],
install: true,
install_dir: [false, py.get_install_dir(pure: false)],
command: [swig, '-python', '-I'+meson.current_source_dir() / '../libfdt', '-o', '@OUTPUT0@', '@INPUT@']
)

nowarn_gen = cc.get_supported_arguments(
'-Wno-cast-qual',
'-Wno-missing-prototypes',
'-Wno-redundant-decls',
)
pylibfdt = py.extension_module(
'_libfdt',
libfdt_c,
c_args: ['-DPY_SSIZE_T_CLEAN'] + nowarn_gen,
dependencies: [libfdt_dep, py.dependency()],
install: true,
)

121
pylibfdt/setup.py Executable file
View File

@ -0,0 +1,121 @@
#!/usr/bin/env python2

"""
setup.py file for SWIG libfdt
Copyright (C) 2017 Google, Inc.
Written by Simon Glass <sjg@chromium.org>

Files to be built into the extension are provided in SOURCES
C flags to use are provided in CPPFLAGS
Object file directory is provided in OBJDIR
Version is provided in VERSION

If these variables are not given they are parsed from the Makefiles. This
allows this script to be run stand-alone, e.g.:

./pylibfdt/setup.py install [--prefix=...]
"""

from distutils.core import setup, Extension
import os
import re
import sys

# Decodes a Makefile assignment line into key and value (and plus for +=)
RE_KEY_VALUE = re.compile('(?P<key>\w+) *(?P<plus>[+])?= *(?P<value>.*)$')


def ParseMakefile(fname):
"""Parse a Makefile to obtain its variables.

This collects variable assigments of the form:

VAR = value
VAR += more

It does not pick out := assignments, as these are not needed here. It does
handle line continuation.

Returns a dict:
key: Variable name (e.g. 'VAR')
value: Variable value (e.g. 'value more')
"""
makevars = {}
with open(fname) as fd:
prev_text = '' # Continuation text from previous line(s)
for line in fd.read().splitlines():
if line and line[-1] == '\\': # Deal with line continuation
prev_text += line[:-1]
continue
elif prev_text:
line = prev_text + line
prev_text = '' # Continuation is now used up
m = RE_KEY_VALUE.match(line)
if m:
value = m.group('value') or ''
key = m.group('key')

# Appending to a variable inserts a space beforehand
if 'plus' in m.groupdict() and key in makevars:
makevars[key] += ' ' + value
else:
makevars[key] = value
return makevars

def GetEnvFromMakefiles():
"""Scan the Makefiles to obtain the settings we need.

This assumes that this script is being run from the top-level directory,
not the pylibfdt directory.

Returns:
Tuple with:
List of swig options
Version string
List of files to build
List of extra C preprocessor flags needed
Object directory to use (always '')
"""
basedir = os.path.dirname(os.path.dirname(os.path.abspath(sys.argv[0])))
swig_opts = ['-I%s' % basedir]
makevars = ParseMakefile(os.path.join(basedir, 'Makefile'))
version = '%s.%s.%s' % (makevars['VERSION'], makevars['PATCHLEVEL'],
makevars['SUBLEVEL'])
makevars = ParseMakefile(os.path.join(basedir, 'libfdt', 'Makefile.libfdt'))
files = makevars['LIBFDT_SRCS'].split()
files = [os.path.join(basedir, 'libfdt', fname) for fname in files]
files.append('pylibfdt/libfdt.i')
cflags = ['-I%s' % basedir, '-I%s/libfdt' % basedir]
objdir = ''
return swig_opts, version, files, cflags, objdir


progname = sys.argv[0]
files = os.environ.get('SOURCES', '').split()
cflags = os.environ.get('CPPFLAGS', '').split()
objdir = os.environ.get('OBJDIR')
version = os.environ.get('VERSION')
swig_opts = []

# If we were called directly rather than through our Makefile (which is often
# the case with Python module installation), read the settings from the
# Makefile.
if not all((version, files, cflags, objdir)):
swig_opts, version, files, cflags, objdir = GetEnvFromMakefiles()

libfdt_module = Extension(
'_libfdt',
sources = files,
extra_compile_args = cflags,
swig_opts = swig_opts,
)

setup(
name='libfdt',
version= version,
author='Simon Glass <sjg@chromium.org>',
description='Python binding for libfdt',
ext_modules=[libfdt_module],
package_dir={'': objdir},
py_modules=['pylibfdt/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 valgrind which
elif [ "$NAME" = "Alpine Linux" ]
then
apk add build-base bison coreutils flex git yaml yaml-dev python3-dev \
meson py3-setuptools_scm swig valgrind
elif [ "$NAME" = "Fedora Linux" ]
then
dnf install -y bison diffutils flex gcc git libyaml libyaml-devel \
make meson python3-devel python3-setuptools swig valgrind which
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 valgrind
else
echo "ERROR: OS name is not provided."
exit 1
fi

View File

@ -1,5 +1,4 @@
#! /bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later

REMOTE_GIT=/pub/scm/utils/dtc/dtc.git
REMOTE_PATH=/pub/software/utils/dtc

View File

@ -1,5 +1,4 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0-or-later
# Print additional version information for non-release trees.

usage() {

193
srcpos.c
View File

@ -1,11 +1,23 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/

#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif

#include <stdio.h>

@ -21,9 +33,6 @@ struct search_path {
/* This is the list of directories that we search for source files */
static struct search_path *search_path_head, **search_path_tail;

/* Detect infinite include recursion. */
#define MAX_SRCFILE_DEPTH (200)
static int srcfile_depth; /* = 0 */

static char *get_dirname(const char *path)
{
@ -42,51 +51,11 @@ static char *get_dirname(const char *path)

FILE *depfile; /* = NULL */
struct srcfile_state *current_srcfile; /* = NULL */
static char *initial_path; /* = NULL */
static int initial_pathlen; /* = 0 */
static bool initial_cpp = true;

static void set_initial_path(char *fname)
{
int i, len = strlen(fname);
/* Detect infinite include recursion. */
#define MAX_SRCFILE_DEPTH (100)
static int srcfile_depth; /* = 0 */

xasprintf(&initial_path, "%s", fname);
initial_pathlen = 0;
for (i = 0; i != len; i++)
if (initial_path[i] == '/')
initial_pathlen++;
}

static char *shorten_to_initial_path(char *fname)
{
char *p1, *p2, *prevslash1 = NULL;
int slashes = 0;

for (p1 = fname, p2 = initial_path; *p1 && *p2; p1++, p2++) {
if (*p1 != *p2)
break;
if (*p1 == '/') {
prevslash1 = p1;
slashes++;
}
}
p1 = prevslash1 + 1;
if (prevslash1) {
int diff = initial_pathlen - slashes, i, j;
int restlen = strlen(fname) - (p1 - fname);
char *res;

res = xmalloc((3 * diff) + restlen + 1);
for (i = 0, j = 0; i != diff; i++) {
res[j++] = '.';
res[j++] = '.';
res[j++] = '/';
}
strcpy(res + j, p1);
return res;
}
return NULL;
}

/**
* Try to open a file in a given directory.
@ -160,10 +129,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;
@ -190,9 +157,6 @@ void srcfile_push(const char *fname)
srcfile->colno = 1;

current_srcfile = srcfile;

if (srcfile_depth == 1)
set_initial_path(srcfile->name);
}

bool srcfile_pop(void)
@ -233,6 +197,20 @@ void srcfile_add_search_path(const char *dirname)
search_path_tail = &node->next;
}

/*
* The empty source position.
*/

struct srcpos srcpos_empty = {
.first_line = 0,
.first_column = 0,
.last_line = 0,
.last_column = 0,
.file = NULL,
};

#define TAB_SIZE 8

void srcpos_update(struct srcpos *pos, const char *text, int len)
{
int i;
@ -246,6 +224,9 @@ void srcpos_update(struct srcpos *pos, const char *text, int len)
if (text[i] == '\n') {
current_srcfile->lineno++;
current_srcfile->colno = 1;
} else if (text[i] == '\t') {
current_srcfile->colno =
ALIGN(current_srcfile->colno, TAB_SIZE);
} else {
current_srcfile->colno++;
}
@ -258,46 +239,13 @@ struct srcpos *
srcpos_copy(struct srcpos *pos)
{
struct srcpos *pos_new;
struct srcfile_state *srcfile_state;

if (!pos)
return NULL;

pos_new = xmalloc(sizeof(struct srcpos));
assert(pos->next == NULL);
memcpy(pos_new, pos, sizeof(struct srcpos));

/* allocate without free */
srcfile_state = xmalloc(sizeof(struct srcfile_state));
memcpy(srcfile_state, pos->file, sizeof(struct srcfile_state));
pos_new->file = srcfile_state;

return pos_new;
}

struct srcpos *srcpos_extend(struct srcpos *pos, struct srcpos *newtail)
{
struct srcpos *p;

if (!pos)
return newtail;

for (p = pos; p->next != NULL; p = p->next);
p->next = newtail;
return pos;
}

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)
{
@ -323,68 +271,6 @@ srcpos_string(struct srcpos *pos)
return pos_str;
}

static char *
srcpos_string_comment(struct srcpos *pos, bool first_line, int level)
{
char *pos_str, *fresh_fname = NULL, *first, *rest;
const char *fname;

if (!pos) {
if (level > 1) {
xasprintf(&pos_str, "<no-file>:<no-line>");
return pos_str;
} else {
return NULL;
}
}

if (!pos->file)
fname = "<no-file>";
else if (!pos->file->name)
fname = "<no-filename>";
else if (level > 1)
fname = pos->file->name;
else {
fresh_fname = shorten_to_initial_path(pos->file->name);
if (fresh_fname)
fname = fresh_fname;
else
fname = pos->file->name;
}

if (level > 1)
xasprintf(&first, "%s:%d:%d-%d:%d", fname,
pos->first_line, pos->first_column,
pos->last_line, pos->last_column);
else
xasprintf(&first, "%s:%d", fname,
first_line ? pos->first_line : pos->last_line);

if (fresh_fname)
free(fresh_fname);

if (pos->next != NULL) {
rest = srcpos_string_comment(pos->next, first_line, level);
xasprintf(&pos_str, "%s, %s", first, rest);
free(first);
free(rest);
} else {
pos_str = first;
}

return pos_str;
}

char *srcpos_string_first(struct srcpos *pos, int level)
{
return srcpos_string_comment(pos, true, level);
}

char *srcpos_string_last(struct srcpos *pos, int level)
{
return srcpos_string_comment(pos, false, level);
}

void srcpos_verror(struct srcpos *pos, const char *prefix,
const char *fmt, va_list va)
{
@ -413,9 +299,4 @@ void srcpos_set_line(char *f, int l)
{
current_srcfile->name = f;
current_srcfile->lineno = l;

if (initial_cpp) {
initial_cpp = false;
set_initial_path(f);
}
}

View File

@ -1,6 +1,20 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/

#ifndef SRCPOS_H
@ -60,7 +74,6 @@ struct srcpos {
int last_line;
int last_column;
struct srcfile_state *file;
struct srcpos *next;
};

#define YYLTYPE struct srcpos
@ -80,19 +93,19 @@ struct srcpos {
YYRHSLOC(Rhs, 0).last_column; \
(Current).file = YYRHSLOC (Rhs, 0).file; \
} \
(Current).next = NULL; \
} while (0)


/*
* Fictional source position used for IR nodes that are
* created without otherwise knowing a true source position.
* For example,constant definitions from the command line.
*/
extern struct srcpos srcpos_empty;

extern void srcpos_update(struct srcpos *pos, const char *text, int len);
extern struct srcpos *srcpos_copy(struct srcpos *pos);
extern struct srcpos *srcpos_extend(struct srcpos *new_srcpos,
struct srcpos *old_srcpos);
extern 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);


extern void PRINTF(3, 0) srcpos_verror(struct srcpos *pos, const char *prefix,
const char *fmt, va_list va);

14
tests/.gitignore vendored
View File

@ -1,19 +1,13 @@
*.dtb
*.dts.test.s
*.test.dts
*.test.dt.yaml
tmp.*
/fs/
/add_subnode_with_nops
/addr_size_cells
/addr_size_cells2
/appendprop[12]
/appendprop_addrrange
/asm_tree_dump
/boot-cpuid
/char_literal
/check_full
/check_header
/check_path
/del_node
/del_property
@ -29,10 +23,8 @@ tmp.*
/get_path
/get_phandle
/getprop
/get_prop_offset
/incbin
/integer-expressions
/fs_tree1
/mangle-layout
/move_and_save
/node_check_compatible
@ -54,10 +46,8 @@ tmp.*
/property_iterate
/propname_escapes
/references
/relref_merge
/root_node
/rw_tree1
/rw_oom
/set_name
/setprop
/setprop_inplace
@ -68,10 +58,6 @@ tmp.*
/subnode_offset
/supernode_atdepth_offset
/sw_tree1
/sw_states
/truncated_property
/truncated_string
/truncated_memrsv
/utilfdt_test
/value-labels
/get_next_tag_invalid_prop_len

View File

@ -1,24 +1,22 @@
LIB_TESTS_L = get_mem_rsv \
root_node find_property subnode_offset path_offset \
get_name getprop get_prop_offset get_phandle \
get_name getprop get_phandle \
get_path supernode_atdepth_offset parent_offset \
node_offset_by_prop_value node_offset_by_phandle \
node_check_compatible node_offset_by_compatible \
get_alias get_next_tag_invalid_prop_len \
get_alias \
char_literal \
sized_cells \
notfound \
addr_size_cells \
addr_size_cells2 \
appendprop_addrrange \
stringlist \
setprop_inplace nop_property nop_node \
sw_tree1 sw_states \
sw_tree1 \
move_and_save mangle-layout nopulate \
open_pack rw_tree1 rw_oom set_name setprop del_property del_node \
open_pack rw_tree1 set_name setprop del_property del_node \
appendprop1 appendprop2 propname_escapes \
string_escapes references path-references phandle_format \
boot-cpuid incbin relref_merge \
boot-cpuid incbin \
extra-terminating-null \
dtbs_equal_ordered \
dtb_reverse dtbs_equal_unordered \
@ -28,24 +26,18 @@ LIB_TESTS_L = get_mem_rsv \
property_iterate \
subnode_iterate \
overlay overlay_bad_fixup \
check_path check_header check_full \
fs_tree1
check_path
LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%)

LIBTREE_TESTS_L = truncated_property truncated_string truncated_memrsv

LIBTREE_TESTS_L = truncated_property
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)
@ -53,49 +45,38 @@ TESTS_TARGETS = $(TESTS) $(TESTS_TREES)
TESTS_DEPFILES = $(TESTS:%=%.d) \
$(addprefix $(TESTS_PREFIX),testutils.d trees.d dumptrees.d)

TESTS_CLEANFILES_L = $(STD_CLEANFILES) \
*.dtb *.test.dts *.test.dt.yaml *.dtsv1 tmp.* *.bak \
dumptrees
TESTS_CLEANFILES_L = *.output vglog.* vgcore.* *.dtb *.test.dts *.dtsv1 tmp.*
TESTS_CLEANFILES_L += dumptrees
TESTS_CLEANFILES = $(TESTS) $(TESTS_CLEANFILES_L:%=$(TESTS_PREFIX)%)
TESTS_CLEANDIRS_L = fs
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_archive)

# 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_archive)
@$(VECHO) LD [libdl] $@
$(LINK.c) -o $@ $^ $(LIBDL)
$(LINK.c) -o $@ $^ -ldl

$(LIBTREE_TESTS): %: $(TESTS_PREFIX)testutils.o $(TESTS_PREFIX)trees.o \
util.o $(LIBFDT_dep)
util.o $(LIBFDT_archive)

$(TESTS_PREFIX)dumptrees: $(TESTS_PREFIX)trees.o

$(TESTS_TREES): $(TESTS_PREFIX)dumptrees
@$(VECHO) DUMPTREES
cd $(TESTS_PREFIX); ./dumptrees . >/dev/null
cd $(TESTS_PREFIX); ./dumptrees >/dev/null

tests_clean:
@$(VECHO) CLEAN "(tests)"
rm -f $(STD_CLEANFILES:%=$(TESTS_PREFIX)%)
rm -f $(TESTS_CLEANFILES)
rm -rf $(TESTS_CLEANDIRS)

check: tests ${TESTS_BIN} $(TESTS_PYLIBFDT)
cd $(TESTS_PREFIX); ./run_tests.sh

ifeq ($(NO_VALGRIND),1)
checkm:
@echo "make checkm requires valgrind, but NO_VALGRIND=1"
else
checkm: tests ${TESTS_BIN} $(TESTS_PYLIBFDT)
cd $(TESTS_PREFIX); ./run_tests.sh -m
endif
cd $(TESTS_PREFIX); ./run_tests.sh -m 2>&1 | tee vglog.$$$$

checkv: tests ${TESTS_BIN} $(TESTS_PYLIBFDT)
cd $(TESTS_PREFIX); ./run_tests.sh -v
@ -103,3 +84,4 @@ checkv: tests ${TESTS_BIN} $(TESTS_PYLIBFDT)
ifneq ($(DEPTARGETS),)
-include $(TESTS_DEPFILES)
endif


View File

@ -1,8 +1,21 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_nop_node()
* Copyright (C) 2006 David Gibson, IBM Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include <stdlib.h>

View File

@ -1,8 +1,21 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for #address-cells and #size-cells handling
* Copyright (C) 2014 David Gibson, <david@gibson.dropbear.id.au>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdlib.h>
#include <stdio.h>
@ -45,12 +58,7 @@ int main(int argc, char *argv[])
fdt = load_blob(argv[1]);

check_node(fdt, "/", 2, 2);
check_node(fdt, "/identity-bus@0", 2, 1);
check_node(fdt, "/identity-bus@0", 2, 2);
check_node(fdt, "/simple-bus@1000000", 2, 1);
check_node(fdt, "/discrete-bus@2000000", 1, 0);
check_node(fdt, "/c0", -FDT_ERR_BADNCELLS, -FDT_ERR_BADNCELLS);
check_node(fdt, "/c1", -FDT_ERR_BADNCELLS, -FDT_ERR_BADNCELLS);
check_node(fdt, "/c2", -FDT_ERR_BADNCELLS, -FDT_ERR_BADNCELLS);
check_node(fdt, "/c3", -FDT_ERR_BADNCELLS, 0);
PASS();
}

View File

@ -1,49 +0,0 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for #address-cells and #size-cells handling
* Copyright (C) 2014 David Gibson, <david@gibson.dropbear.id.au>
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>

#include <libfdt.h>

#include "tests.h"
#include "testdata.h"

static void check_node(const void *fdt, const char *path, int ac, int sc)
{
int offset;
int xac, xsc;

offset = fdt_path_offset(fdt, path);
if (offset < 0)
FAIL("Couldn't find path %s", path);

xac = fdt_address_cells(fdt, offset);
xsc = fdt_size_cells(fdt, offset);

if (xac != ac)
FAIL("Address cells for %s is %d instead of %d\n",
path, xac, ac);
if (xsc != sc)
FAIL("Size cells for %s is %d instead of %d\n",
path, xsc, sc);
}

int main(int argc, char *argv[])
{
void *fdt;

if (argc != 2)
CONFIG("Usage: %s <dtb file>\n", argv[0]);

test_init(argc, argv);
fdt = load_blob(argv[1]);

check_node(fdt, "/", 2, 1);
PASS();
}

View File

@ -12,29 +12,4 @@
#address-cells = <2>;
#size-cells = <1>;
};

discrete-bus@2000000 {
#address-cells = <1>;
#size-cells = <0>;
};

c0@0 {
#address-cells = <1 1>;
#size-cells = <1 1>;
};

c1@0 {
#address-cells = <0x80000000>;
#size-cells = <0x80000000>;
};

c2@0 {
#address-cells = <5>;
#size-cells = <5>;
};

c3@0 {
#address-cells = <0>;
#size-cells = <0>;
};
};

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

@ -1,8 +1,21 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_appendprop()
* Copyright (C) 2006 David Gibson, IBM Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include <stdlib.h>

View File

@ -1,8 +1,21 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_appendprop()
* Copyright (C) 2006 David Gibson, IBM Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include <stdlib.h>
@ -36,7 +49,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

@ -1,95 +0,0 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_appendprop_addrrange()
* Copyright (C) 2018 AKASHI Takahiro, Linaro Limited
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>

#include <libfdt.h>

#include "tests.h"
#include "testdata.h"

int main(int argc, char *argv[])
{
void *fdt, *buf;
int offset, xac, xsc, num, i, err;
uint64_t addr, size;

if (argc != 5)
CONFIG("Usage: %s <dtb file> <address-cells> <size-cells> <num>\n",
argv[0]);

test_init(argc, argv);
fdt = load_blob(argv[1]);
xac = strtol(argv[2], NULL, 10);
xsc = strtol(argv[3], NULL, 10);
num = strtol(argv[4], NULL, 10);

buf = xmalloc(0x1000);
if (!buf)
FAIL("Couldn't allocate temporary buffer");
err = fdt_open_into(fdt, buf, 0x1000);
if (err)
FAIL("fdt_open_into(): %s", fdt_strerror(err));
free(fdt);
fdt = buf;

/* Set up */
err = fdt_setprop_cell(fdt, 0, "#address-cells", xac);
if (err)
FAIL("fdt_setprop_cell(\"#address-cells\"): %s",
fdt_strerror(err));
err = fdt_setprop_cell(fdt, 0, "#size-cells", xsc);
if (err)
FAIL("fdt_setprop_cell(\"#size-cells\"): %s",
fdt_strerror(err));

offset = fdt_path_offset(fdt, "/node@1");
if (offset < 0)
FAIL("Couldn't find path %s", "/node@1");

addr = TEST_MEMREGION_ADDR;
if (xac > 1)
addr += TEST_MEMREGION_ADDR_HI;
size = TEST_MEMREGION_SIZE;
if (xsc > 1)
size += TEST_MEMREGION_SIZE_HI;

/*
* Do test
*/
/* 1. repeat append's */
for (i = 0; i < num; i++) {
err = fdt_appendprop_addrrange(fdt, 0, offset,
"prop-memregion", addr, size);
if (err)
FAIL("Failed to append[%d] \"prop-memregion\": %s",
i, fdt_strerror(err));

check_getprop_addrrange(fdt, 0, offset, "prop-memregion",
i + 1);

addr += size;
size += TEST_MEMREGION_SIZE_INC;
}

/* 2. default property name */
addr = TEST_MEMREGION_ADDR;
if (xac > 1)
addr += TEST_MEMREGION_ADDR_HI;
size = TEST_MEMREGION_SIZE;
if (xsc > 1)
size += TEST_MEMREGION_SIZE_HI;

err = fdt_appendprop_addrrange(fdt, 0, offset, "reg", addr, size);
if (err)
FAIL("Failed to set \"reg\": %s", fdt_strerror(err));
check_getprop_addrrange(fdt, 0, offset, "reg", 1);

PASS();
}

View File

@ -1,8 +1,21 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Tests if an asm tree built into a shared object matches a given dtb
* Copyright (C) 2008 David Gibson, IBM Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include <stdlib.h>

View File

@ -1,12 +0,0 @@
/dts-v1/;

/ {
#address-cells = <2>;
#size-cells = <2>;
node {
#address-cells = <1>;
#size-cells = <1>;
ranges;
dma-ranges = <0 0 0 0 0>;
};
};

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,24 +0,0 @@
/dts-v1/;

/ {
ports {
#address-cells = <1>;
#size-cells = <0>;

bad_endpoint: port-a@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;

endpoint@d0 {
reg = <0>;
remote-endpoint = <0xdeadbeef>;
};

};

port@1 {
reg = <0>;
};
};
};

View File

@ -1,7 +0,0 @@
/dts-v1/;

/ {
intc: interrupt-controller {
interrupt-controller;
};
};

View File

@ -1,20 +0,0 @@
/dts-v1/;

/ {
interrupt-parent = <&intc>;
intc: interrupt-controller {
#interrupt-cells = <3>;
interrupt-controller;
};

node {
#address-cells = <0>;
#interrupt-cells = <1>;
interrupt-map = <1 &intc 1 2 3>;
interrupt-map-mask = <0 0>;

child {
interrupts = <1>;
};
};
};

View File

@ -1,17 +0,0 @@
/dts-v1/;

/ {
interrupt-parent = <&intc>;
intc: interrupt-controller {
};

node {
#address-cells = <0>;
#interrupt-cells = <1>;
interrupt-map = <1 &intc 1 2 3>;

child {
interrupts = <1>;
};
};
};

View File

@ -1,19 +0,0 @@
/dts-v1/;

/ {
interrupt-parent = <&intc>;
intc: interrupt-controller {
#interrupt-cells = <3>;
interrupt-controller;
};

node {
/* Missing #address-cells = <0>; */
#interrupt-cells = <1>;
interrupt-map = <1 &intc 1 2 3>;

child {
interrupts = <1>;
};
};
};

View File

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

View File

@ -1,6 +1,19 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* Copyright (C) 2008 David Gibson, IBM Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include <stdlib.h>

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

@ -1,9 +1,22 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for character literals in dtc
* Copyright (C) 2006 David Gibson, IBM Corporation.
* Copyright (C) 2011 The Chromium Authors. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdlib.h>
#include <stdio.h>

View File

@ -1,50 +0,0 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Tests if two given dtbs are structurally equal (including order)
* Copyright (C) 2007 David Gibson, IBM Corporation.
*/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>

#include <libfdt.h>

#include "tests.h"
#include "testdata.h"

static int expect_bad; /* = 0 */

int main(int argc, char *argv[])
{
const char *filename;
char *fdt;
size_t len;
int err;

test_init(argc, argv);
if ((argc != 2)
&& ((argc != 3) || !streq(argv[1], "-n")))
CONFIG("Usage: %s [-n] <dtb file>", argv[0]);
if (argc == 3)
expect_bad = 1;

filename = argv[argc-1];
err = utilfdt_read_err(filename, &fdt, &len);
if (err)
CONFIG("Couldn't open blob from \"%s\": %s",
filename, strerror(err));

vg_prepare_blob(fdt, len);

err = fdt_check_full(fdt, len);

if (expect_bad && (err == 0))
FAIL("fdt_check_full() succeeded unexpectedly");
else if (!expect_bad && (err != 0))
FAIL("fdt_check_full() failed: %s", fdt_strerror(err));

PASS();
}

View File

@ -1,115 +0,0 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_check_header
* Copyright (C) 2018 David Gibson
*/

#include <stdio.h>

#include <libfdt.h>

#include "tests.h"

static void *dtdup(void *dt)
{
size_t bufsize = fdt_totalsize(dt);
void *buf = xmalloc(bufsize);
fdt_move(dt, buf, bufsize);
return buf;
}

#define CHECK_MANGLE(exerr, code) \
do { \
void *fdt = dtdup(template); \
{ code } \
err = fdt_check_header(fdt); \
verbose_printf("\"%s\" => %s\n", #code, fdt_strerror(err)); \
if (err != (exerr)) \
FAIL("fdt_check_header() didn't catch mangle %s", \
#code); \
free(fdt); \
} while (0)

int main(int argc, char *argv[])
{
void *template;
int err;

test_init(argc, argv);
template = load_blob(argv[1]);

/* Check that the base dt is valid before mangling it */
err = fdt_check_header(template);
if (err != 0)
FAIL("Base tree fails: %s", fdt_strerror(err));

/* Check a no-op mangle doesn't break things */
CHECK_MANGLE(0, ; );

/* Mess up the magic number */
CHECK_MANGLE(-FDT_ERR_BADMAGIC,
fdt_set_magic(fdt, fdt_magic(fdt) ^ 0x1);
);
CHECK_MANGLE(-FDT_ERR_BADMAGIC,
fdt_set_magic(fdt, fdt_magic(fdt) ^ 0x80000000);
);

/* Mess up the version */
CHECK_MANGLE(-FDT_ERR_BADVERSION,
fdt_set_version(fdt, FDT_FIRST_SUPPORTED_VERSION - 1);
fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION - 1);
);
CHECK_MANGLE(-FDT_ERR_BADVERSION,
fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION + 1);
fdt_set_last_comp_version(fdt, FDT_LAST_SUPPORTED_VERSION + 1);
);
CHECK_MANGLE(-FDT_ERR_BADVERSION,
fdt_set_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
fdt_set_last_comp_version(fdt, FDT_LAST_SUPPORTED_VERSION);
);

/* Out of bounds sizes */
CHECK_MANGLE(-FDT_ERR_TRUNCATED,
fdt_set_totalsize(fdt, FDT_V1_SIZE - 1);
);
CHECK_MANGLE(-FDT_ERR_TRUNCATED,
fdt_set_totalsize(fdt, (uint32_t)INT_MAX + 1);
);

/* Truncate within various blocks */
CHECK_MANGLE(-FDT_ERR_TRUNCATED,
fdt_set_totalsize(fdt, fdt_off_dt_struct(fdt) - 1);
);
CHECK_MANGLE(-FDT_ERR_TRUNCATED,
fdt_set_totalsize(fdt, fdt_off_dt_strings(fdt) - 1);
);
CHECK_MANGLE(-FDT_ERR_TRUNCATED,
fdt_set_totalsize(fdt, fdt_off_mem_rsvmap(fdt) - 1);
);
CHECK_MANGLE(-FDT_ERR_TRUNCATED,
fdt_set_totalsize(fdt, fdt_off_dt_struct(fdt) + 1);
);
CHECK_MANGLE(-FDT_ERR_TRUNCATED,
fdt_set_totalsize(fdt, fdt_off_dt_strings(fdt) + 1);
);
CHECK_MANGLE(-FDT_ERR_TRUNCATED,
fdt_set_totalsize(fdt, fdt_off_mem_rsvmap(fdt) + 1);
);

/* Negative block sizes */
CHECK_MANGLE(-FDT_ERR_TRUNCATED,
fdt_set_size_dt_struct(fdt, (uint32_t)-1);
);
CHECK_MANGLE(-FDT_ERR_TRUNCATED,
fdt_set_size_dt_strings(fdt, (uint32_t)-1);
);
CHECK_MANGLE(-FDT_ERR_TRUNCATED,
fdt_set_size_dt_struct(fdt, (uint32_t)INT_MIN);
);
CHECK_MANGLE(-FDT_ERR_TRUNCATED,
fdt_set_size_dt_strings(fdt, (uint32_t)INT_MIN);
);

PASS();
}

View File

@ -1,8 +1,21 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for node existence
* Copyright (C) 2016 Konsulko Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include <stdio.h>
@ -32,7 +45,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

@ -1,8 +1,21 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_nop_node()
* Copyright (C) 2006 David Gibson, IBM Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include <stdlib.h>
@ -18,16 +31,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

@ -1,8 +1,21 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for fdt_delprop()
* Copyright (C) 2006 David Gibson, IBM Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include <stdlib.h>
@ -18,17 +31,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 +86,5 @@ int main(int argc, char *argv[])
if (newsize >= oldsize)
FAIL("Tree failed to shrink after deletions");

free(fdt);
PASS();
}

View File

@ -1,8 +1,21 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Tests if two given dtbs are structurally equal (including order)
* Copyright (C) 2010 David Gibson, IBM Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include <stdlib.h>

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