Compare commits

..

4 Commits

Author SHA1 Message Date
Miroslav Rezanina 9700e166c3 Update to dtc-1.4.3-1.el7 2017-07-18 07:19:45 +02:00
Miroslav Rezanina 836b4e3d7c redhat/Makefile: honor BREW_FLAGS like the kernel
When doing make rh-brew on a RHEL kernel one can set BREW_FLAGS
to anything that 'brew build' accepts (see 'brew build -h'). This
is useful to avoid wasting resources when only one arch needs to
be compiled for a test, as the arch-override parameter can be
set. For example,

  BREW_FLAGS='--arch-override=aarch64' make -C redhat rh-brew

only builds for aarch64.

Signed-off-by: Andrew Jones <drjones@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
2017-07-14 10:56:54 +02:00
Peter Xu c8afc5ecbc script: update git-backport-diff to latest
RH-Author: Peter Xu <peterx@redhat.com>
Message-id: <1490341487-21581-1-git-send-email-peterx@redhat.com>
Patchwork-id: 74520
O-Subject: [RHEV-7.4 qemu-kvm-rhev PATCH] script: update git-backport-diff to latest
Bugzilla:

BZ:       None
Brew:     None
Upstream: Downstream only

Upstream git-backport-diff (https://github.com/codyprime/git-scripts)
has several enhancements. Let's sync up with that one. This patch will
upgrade the script to the following commit on Apr 22th, 2016 (which is
current latest):

  a7ccff88e (More fixes for printing literal strings)

Signed-off-by: Peter Xu <peterx@redhat.com>
---
 redhat/scripts/git-backport-diff | 75 ++++++++++++++++++++++++++--------------
 1 file changed, 50 insertions(+), 25 deletions(-)

Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
2017-04-05 09:15:32 +02:00
Miroslav Rezanina 9059912187 Add redhat directory 2017-03-06 10:48:03 +01:00
243 changed files with 4463 additions and 12639 deletions

View File

@ -1,39 +0,0 @@
# FreeBSD build with multiple versions
freebsd_versions_task:
name: FreeBSD $FREEBSD_VERSION make build
freebsd_instance:
image_family: $FREEBSD_IMAGE
matrix:
- env:
FREEBSD_VERSION: "13.5"
FREEBSD_IMAGE: freebsd-13-5
- env:
FREEBSD_VERSION: "14.3"
FREEBSD_IMAGE: freebsd-14-3
install_script:
- pkg install -y git gmake flex bison python3 py312-setuptools swig libyaml pkgconf
build_script:
- gmake
check_script:
- gmake check

# FreeBSD meson builds with multiple versions
freebsd_meson_versions_task:
name: FreeBSD $FREEBSD_VERSION meson build
freebsd_instance:
image_family: $FREEBSD_IMAGE
matrix:
- env:
FREEBSD_VERSION: "13.5"
FREEBSD_IMAGE: freebsd-13-5
- env:
FREEBSD_VERSION: "14.3"
FREEBSD_IMAGE: freebsd-14-3
install_script:
- pkg install -y git meson ninja flex bison python3 py312-setuptools swig libyaml pkgconf
setup_script:
- meson setup -D python=enabled -D yaml=enabled build
build_script:
- meson compile -C build
test_script:
- if ! meson test -C build; then cat build/meson-logs/testlog.txt; false; fi

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

# ensure that the workflow is only triggered once per PR, subsequent pushes to the PR will cancel
# and restart the workflow. See https://docs.github.com/en/actions/using-jobs/using-concurrency
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

jobs:
build-make:
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
os: [ "alpine", "archlinux", "fedora", "ubuntu" ]

container:
image: ${{ matrix.os }}

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Install Dependencies
run: |
./scripts/install-deps.sh

- name: Build
run: |
make

- name: Run check
run: |
make check

build-meson:
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
os: [ "alpine", "archlinux", "fedora", "ubuntu" ]

container:
image: ${{ matrix.os }}

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Install Dependencies
run: |
./scripts/install-deps.sh

- name: Setup
run: meson setup -D python=enabled -D yaml=enabled build

- name: Build
run: meson compile -C build

- name: Run check
run: if ! meson test -C build; then cat build/meson-logs/testlog.txt; false; fi

build-windows:
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
include:
- { sys: mingw32 }
- { sys: mingw64 }
- { sys: ucrt64 }
- { sys: clang64 }
name: ${{ matrix.sys }}
defaults:
run:
shell: msys2 {0}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup MSYS2
uses: msys2/setup-msys2@v2
with:
msystem: ${{matrix.sys}}
update: true
install: >-
git
flex
bison
pacboy: >-
toolchain:p
meson:p
ninja:p
libyaml:p
swig:p
python-setuptools-scm:p

- name: 'đźš§ Build'
run: |
meson setup -Dtools=true -Dtests=false build
meson compile -C build

13
.gitignore vendored
View File

@ -3,28 +3,15 @@
*.a
*.patch
*.so
*.so.*
*~
*.bak
*.tab.[ch]
lex.yy.c
*.lex.c
.*.swp
/dtc
/fdtdump
/convert-dtsv0
/version_gen.h
/fdtget
/fdtput
/fdtoverlay
/patches
/.pc

# cscope files
cscope.*
ncscope.*

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

View File

@ -1,65 +0,0 @@
stages:
- build

variables:
GIT_DEPTH: 1

workflow:
rules:
- if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "main"
- if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "ci"
- if: $CI_PIPELINE_SOURCE == "merge_request_event"

# Linux builds with make
.build-make-template: &build-make-template
stage: build
before_script:
- ./scripts/install-deps.sh
script:
- make
- make check
interruptible: true

build-make-alpine:
<<: *build-make-template
image: alpine:latest

build-make-archlinux:
<<: *build-make-template
image: archlinux:latest

build-make-fedora:
<<: *build-make-template
image: fedora:latest

build-make-ubuntu:
<<: *build-make-template
image: ubuntu:latest

# Linux builds with meson
.build-meson-template: &build-meson-template
stage: build
before_script:
- ./scripts/install-deps.sh
script:
- meson setup -D python=enabled -D yaml=enabled build
- meson compile -C build
- if ! meson test -C build; then cat build/meson-logs/testlog.txt; false; fi
interruptible: true

build-meson-alpine:
<<: *build-meson-template
image: alpine:latest

build-meson-archlinux:
<<: *build-meson-template
image: archlinux:latest

build-meson-fedora:
<<: *build-meson-template
image: fedora:latest

build-meson-ubuntu:
<<: *build-meson-template
image: ubuntu:latest

8
.gitpublish Normal file
View File

@ -0,0 +1,8 @@
# The first profile is the default
[gitpublishprofile "rhel"]
base = rhel7/master-1.4.3
prefix = RHEL-7.4 dtc PATCH
to = rhvirt-patches@redhat.com
suppresscc = all
message = True

5
.travis.yml Normal file
View File

@ -0,0 +1,5 @@
language: c

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).
@ -688,86 +674,4 @@ The fdtdump program prints a readable version of a flat device tree file.

The syntax of the fdtdump command line is:

fdtdump [options] <DTB-file-name>

Where options are:
-d,--debug Dump debug information while decoding the file
-s,--scan Scan for an embedded fdt in given file

3) fdtoverlay -- Flat Device Tree overlay applicator

The fdtoverlay applies an arbitrary number of FDT overlays to a base FDT blob
to a given output file.

The syntax of the fdtoverlay command line is:

fdtoverlay -i <base-blob> -o <output-blob> <overlay-blob0> [<overlay-blob1> ...]

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.
fdtdump <DTB-file-name>

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.

157
Makefile
View File

@ -1,45 +1,29 @@
# 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 = 3
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 \
-Wwrite-strings
ifeq ($(shell $(CC) --version | grep -q gcc && echo gcc),gcc)
WARNINGS += -Wsuggest-attribute=format
endif
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 -fPIC -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
@ -47,45 +31,14 @@ LIBDIR = $(PREFIX)/lib
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

HAS_VERSION_SCRIPT := $(shell echo 'int main(){}' | $(CC) -Wl,--version-script=/dev/null -x c - -o /dev/null 2>/dev/null && echo y)
sed -e 's/\(cygwin\).*/cygwin/')

ifeq ($(HOSTOS),darwin)
SHAREDLIB_EXT = dylib
SHAREDLIB_CFLAGS = -fPIC
SHAREDLIB_LDFLAGS = -fPIC -dynamiclib -Wl,-install_name -Wl,
else ifeq ($(HOSTOS),$(filter $(HOSTOS),msys cygwin))
SHAREDLIB_EXT = so
SHAREDLIB_CFLAGS =
SHAREDLIB_LDFLAGS = -shared -Wl,-soname,
SHAREDLIB_EXT=dylib
SHAREDLIB_LINK_OPTIONS=-dynamiclib -Wl,-install_name -Wl,
else
SHAREDLIB_EXT = so
SHAREDLIB_CFLAGS = -fPIC
SHAREDLIB_LDFLAGS = -fPIC -shared -Wl,-soname,
endif

ifeq ($(HAS_VERSION_SCRIPT),y)
SHAREDLIB_LDFLAGS += -Wl,--version-script=$(LIBFDT_version)
SHAREDLIB_EXT=so
SHAREDLIB_LINK_OPTIONS=-shared -Wl,--version-script=$(LIBFDT_version) -Wl,-soname,
endif

#
@ -110,6 +63,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; \
@ -158,21 +112,18 @@ BIN += dtc
BIN += fdtdump
BIN += fdtget
BIN += fdtput
BIN += fdtoverlay

SCRIPTS = dtdiff

all: $(BIN) libfdt


ifneq ($(DEPTARGETS),)
ifneq ($(MAKECMDGOALS),libfdt)
-include $(DTC_OBJS:%.o=%.d)
-include $(CONVERT_OBJS:%.o=%.d)
-include $(FDTDUMP_OBJS:%.o=%.d)
-include $(FDTGET_OBJS:%.o=%.d)
-include $(FDTPUT_OBJS:%.o=%.d)
-include $(FDTOVERLAY_OBJS:%.o=%.d)
endif
endif


@ -180,35 +131,28 @@ 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
@ -219,21 +163,20 @@ 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

@ -249,11 +192,9 @@ convert-dtsv0: $(CONVERT_OBJS)

fdtdump: $(FDTDUMP_OBJS)

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

fdtput: $(FDTPUT_OBJS) $(LIBFDT_dep)

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

dist:
git archive --format=tar --prefix=dtc-$(dtc_version)/ HEAD \
@ -261,7 +202,6 @@ dist:
cat ../dtc-$(dtc_version).tar | \
gzip -9 > ../dtc-$(dtc_version).tar.gz


#
# Release signing and uploading
# This is for maintainer convenience, don't try this at home.
@ -294,11 +234,8 @@ TESTS_BIN += convert-dtsv0
TESTS_BIN += fdtput
TESTS_BIN += fdtget
TESTS_BIN += fdtdump
TESTS_BIN += fdtoverlay

ifneq ($(MAKECMDGOALS),libfdt)
include tests/Makefile.tests
endif

#
# Clean rules
@ -318,7 +255,7 @@ clean: libfdt_clean tests_clean
#
%: %.o
@$(VECHO) LD $@
$(LINK.c) -o $@ $^ $(LDLIBS_$*)
$(LINK.c) -o $@ $^

%.o: %.c
@$(VECHO) CC $@
@ -326,11 +263,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 $<
@ -348,16 +285,16 @@ clean: libfdt_clean tests_clean
@$(VECHO) AR $@
$(AR) $(ARFLAGS) $@ $^

$(LIBFDT_lib):
@$(VECHO) LD $@
$(CC) $(LDFLAGS) -fPIC $(SHAREDLIB_LINK_OPTIONS)$(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.
@ -23,9 +22,3 @@ FDTPUT_SRCS = \
util.c

FDTPUT_OBJS = $(FDTPUT_SRCS:%.c=%.o)

FDTOVERLAY_SRCS = \
fdtoverlay.c \
util.c

FDTOVERLAY_OBJS = $(FDTOVERLAY_SRCS:%.c=%.o)

16
README Normal file
View File

@ -0,0 +1,16 @@
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>

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

1495
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
@ -35,7 +49,7 @@ static int saw_hyphen; /* = 0 */
static unsigned long long last_val;
static char *last_name; /* = NULL */

static const struct {
const struct {
const char *pattern;
int obase, width;
} guess_table[] = {
@ -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);


90
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;
@ -158,9 +171,9 @@ struct data data_merge(struct data d1, struct data d2)
struct data data_append_integer(struct data d, uint64_t value, int bits)
{
uint8_t value_8;
fdt16_t value_16;
fdt32_t value_32;
fdt64_t value_64;
uint16_t value_16;
uint32_t value_32;
uint64_t value_64;

switch (bits) {
case 8:
@ -184,14 +197,14 @@ struct data data_append_integer(struct data d, uint64_t value, int bits)
}
}

struct data data_append_re(struct data d, uint64_t address, uint64_t size)
struct data data_append_re(struct data d, const struct fdt_reserve_entry *re)
{
struct fdt_reserve_entry re;
struct fdt_reserve_entry bere;

re.address = cpu_to_fdt64(address);
re.size = cpu_to_fdt64(size);
bere.address = cpu_to_fdt64(re->address);
bere.size = cpu_to_fdt64(re->size);

return data_append_data(d, &re, sizeof(re));
return data_append_data(d, &bere, sizeof(bere));
}

struct data data_append_cell(struct data d, cell_t word)
@ -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() */
@ -46,7 +62,12 @@ static int dts_version = 1;

static void push_input_file(const char *filename);
static bool pop_input_file(void);
static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
#ifdef __GNUC__
static void lexical_error(const char *fmt, ...)
__attribute__((format (printf, 1, 2)));
#else
static void lexical_error(const char *fmt, ...);
#endif

%}

@ -57,7 +78,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 +158,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 +165,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 +211,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,29 +166,11 @@ devicetree:
{
$$ = merge_nodes($1, $3);
}
| dt_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))
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);
}
| 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,47 +178,17 @@ 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);

if (target) {
if (target)
merge_nodes(target, $3);
} else {
/*
* We rely on the rule being always:
* versioninfo plugindecl memreserves devicetree
* so $-1 is what we want (plugindecl)
*/
if ($<flags>-1 & DTSF_PLUGIN)
add_orphan_node($1, $3, $2);
else
ERROR(&@2, "Label or path %s not found", $2);
}
else
ERROR(&@2, "Label or path %s not found", $2);
$$ = $1;
}
| devicetree DT_DEL_NODE dt_ref ';'
| devicetree DT_DEL_NODE DT_REF ';'
{
struct node *target = get_node_by_ref($1, $3);

@ -246,18 +198,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 +205,7 @@ devicetree:
nodedef:
'{' proplist subnodes '}' ';'
{
$$ = build_node($2, $3, &@$);
$$ = build_node($2, $3);
}
;

@ -283,18 +223,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 +253,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 +308,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 +338,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 +423,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 +467,7 @@ integer_unary:
bytestring:
/* empty */
{
$$ = data_add_marker(empty_data, TYPE_UINT8, NULL);
$$ = empty_data;
}
| bytestring DT_BYTE
{
@ -573,16 +499,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
{

72
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 phandle_format = PHANDLE_EPAPR; /* Use linux,phandle or phandle properties */
int alignsize; /* Additional padding to blob accroding to the alignsize */
int phandle_format = PHANDLE_BOTH; /* 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)
{
@ -46,8 +59,10 @@ static void fill_fullpaths(struct node *tree, const char *prefix)
}

/* Usage related data. */
#define FDT_VERSION(version) _FDT_VERSION(version)
#define _FDT_VERSION(version) #version
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 +82,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,11 +97,8 @@ 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\tBlob version to produce, defaults to "FDT_VERSION(DEFAULT_FDT_VERSION)" (for dtb and asm output)",
"\n\tOutput dependency file",
"\n\tMake space for <number> reserve map entries (for dtb and asm output)",
"\n\tMake the blob at least <bytes> long (extra space)",
@ -105,9 +115,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 +130,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;
@ -134,7 +138,7 @@ static const char *guess_type_by_name(const char *fname, const char *fallback)
static const char *guess_input_format(const char *fname, const char *fallback)
{
struct stat statbuf;
fdt32_t magic;
uint32_t magic;
FILE *f;

if (stat(fname, &statbuf) != 0)
@ -155,7 +159,8 @@ static const char *guess_input_format(const char *fname, const char *fallback)
}
fclose(f);

if (fdt32_to_cpu(magic) == FDT_MAGIC)
magic = fdt32_to_cpu(magic);
if (magic == FDT_MAGIC)
return "dtb";

return guess_type_by_name(fname, fallback);
@ -199,7 +204,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 +259,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 +286,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 +300,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"))
@ -327,14 +320,13 @@ int main(int argc, char *argv[])
dti->boot_cpuid_phys = cmdline_boot_cpuid;

fill_fullpaths(dti->dt, "");
process_checks(force, dti);

/* on a plugin, generate by default */
if (dti->dtsflags & DTSF_PLUGIN) {
generate_fixups = 1;
}

process_checks(force, dti);

if (auto_label_aliases)
generate_label_tree(dti, "aliases", false);

@ -360,12 +352,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")) {

160
dtc.h
View File

@ -1,9 +1,24 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#ifndef DTC_H
#define DTC_H
#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>
@ -16,7 +31,6 @@
#include <ctype.h>
#include <errno.h>
#include <unistd.h>
#include <inttypes.h>

#include <libfdt_env.h>
#include <fdt.h>
@ -29,21 +43,21 @@
#define debug(...)
#endif


#define DEFAULT_FDT_VERSION 17

/*
* 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,28 @@ 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 strneq(a, b, n) (strncmp((a), (b), (n)) == 0)

#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 +100,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);
@ -177,15 +114,12 @@ struct data data_insert_at_marker(struct data d, struct marker *m,
struct data data_merge(struct data d1, struct data d2);
struct data data_append_cell(struct data d, cell_t word);
struct data data_append_integer(struct data d, uint64_t word, int bits);
struct data data_append_re(struct data d, uint64_t address, uint64_t size);
struct data data_append_re(struct data d, const struct fdt_reserve_entry *re);
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);
@ -202,10 +136,6 @@ struct label {
struct label *next;
};

struct bus_type {
const char *name;
};

struct property {
bool deleted;
char *name;
@ -214,7 +144,6 @@ struct property {
struct property *next;

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

struct node {
@ -233,10 +162,6 @@ struct node {
int addr_cells, size_cells;

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,21 +188,16 @@ struct node {
void add_label(struct label **labels, char *label);
void delete_labels(struct label **labels);

struct property *build_property(const char *name, struct data val,
struct 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);

void add_property(struct node *node, struct property *prop);
void delete_property_by_name(struct node *node, char *name);
@ -286,13 +206,11 @@ 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);
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,
@ -309,7 +227,7 @@ uint32_t guess_boot_cpuid(struct node *tree);
/* Boot info (tree plus memreserve information */

struct reserve_info {
uint64_t address, size;
struct fdt_reserve_entry re;

struct reserve_info *next;

@ -339,9 +257,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,12 +278,8 @@ 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);

#endif /* DTC_H */
#endif /* _DTC_H */

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,11 +16,11 @@
#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 GET_CELL(p) (p += 4, *((const fdt32_t *)(p-4)))
#define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a))))
#define GET_CELL(p) (p += 4, *((const uint32_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,12 +160,12 @@ 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 ||
fdt_version(p) > MAX_VERSION ||
fdt_last_comp_version(p) > MAX_VERSION ||
fdt_last_comp_version(p) >= MAX_VERSION ||
fdt_totalsize(p) >= len ||
fdt_off_dt_struct(p) >= len ||
fdt_off_dt_strings(p) >= len)
@ -184,13 +181,8 @@ 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"
"**** If you want to decompile a dtb, you probably want\n"
"**** dtc -I dtb -O dts <filename>\n\n"
);
while ((opt = util_getopt_long()) != EOF) {
switch (opt) {
case_USAGE_COMMON_FLAGS
@ -207,7 +199,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 +209,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 +222,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>
@ -39,43 +53,6 @@ static void report_error(const char *where, int err)
fprintf(stderr, "Error at '%s': %s\n", where, fdt_strerror(err));
}

/**
* Shows a list of cells in the requested format
*
* @param disp Display information / options
* @param data Data to display
* @param len Maximum length of buffer
* @param size Data size to use for display (e.g. 4 for 32-bit)
* @return 0 if ok, -1 on error
*/
static int show_cell_list(struct display_info *disp, const char *data, int len,
int size)
{
const uint8_t *p = (const uint8_t *)data;
char fmt[3];
int value;
int i;

fmt[0] = '%';
fmt[1] = disp->type ? disp->type : 'd';
fmt[2] = '\0';
for (i = 0; i < len; i += size, p += size) {
if (i)
printf(" ");
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;
}
printf(fmt, value);
}

return 0;
}

/**
* Displays data of a given length according to selected options
*
@ -89,19 +66,17 @@ static int show_cell_list(struct display_info *disp, const char *data, int len,
*/
static int show_data(struct display_info *disp, const char *data, int len)
{
int size;
int i, size;
const uint8_t *p = (const uint8_t *)data;
const char *s;
int value;
int is_string;
char fmt[3];

/* no data, don't print */
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) {
@ -124,8 +99,17 @@ static int show_data(struct display_info *disp, const char *data, int len)
"selected data size\n");
return -1;
}

return show_cell_list(disp, data, len, size);
fmt[0] = '%';
fmt[1] = disp->type ? disp->type : 'd';
fmt[2] = '\0';
for (i = 0; i < len; i += size, p += size) {
if (i)
printf(" ");
value = size == 4 ? fdt32_to_cpu(*(const uint32_t *)p) :
size == 2 ? (*p << 8) | p[1] : *p;
printf(fmt, value);
}
return 0;
}

/**
@ -137,6 +121,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 +130,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);
@ -259,7 +245,7 @@ static int show_data_for_item(const void *blob, struct display_info *disp,
* @param filename Filename of blob file
* @param arg List of arguments to process
* @param arg_count Number of arguments
* @return 0 if ok, -ve on error
* @param return 0 if ok, -ve on error
*/
static int do_fdtget(struct display_info *disp, const char *filename,
char **arg, int arg_count, int args_per_step)
@ -268,7 +254,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,214 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2017 Konsulko Group Inc. All rights reserved.
*
* Author:
* Pantelis Antoniou <pantelis.antoniou@konsulko.com>
*/

#include <assert.h>
#include <ctype.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>

#include <libfdt.h>

#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>]]";
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'},
{"output", required_argument, NULL, 'o'},
{"verbose", no_argument, NULL, 'v'},
USAGE_COMMON_LONG_OPTS,
};
static const char * const usage_opts_help[] = {
"Input base DT blob",
"Output DT blob",
"Verbose messages",
USAGE_COMMON_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;
int i, ret = -1;

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

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

/* read and keep track of the overlay blobs */
for (i = 0; i < argc; i++) {
size_t ov_len;
ovblob[i] = utilfdt_read(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]));
goto out_err;
}
}

buf_len = fdt_totalsize(blob);

/* apply the overlays in sequence */
for (i = 0; i < argc; i++) {
blob = apply_one(blob, ovblob[i], &buf_len, argv[i]);
if (!blob)
goto out_err;
}

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

out_err:
if (ovblob) {
for (i = 0; i < argc; i++) {
if (ovblob[i])
free(ovblob[i]);
}
free(ovblob);
}
free(blob);

return ret;
}

int main(int argc, char *argv[])
{
int opt, i;
char *input_filename = NULL;
char *output_filename = NULL;

while ((opt = util_getopt_long()) != EOF) {
switch (opt) {
case_USAGE_COMMON_FLAGS

case 'i':
input_filename = optarg;
break;
case 'o':
output_filename = optarg;
break;
case 'v':
verbose = 1;
break;
}
}

if (!input_filename)
usage("missing input file");

if (!output_filename)
usage("missing output file");

argv += optind;
argc -= optind;

if (argc <= 0)
usage("missing overlay file(s)");

if (verbose) {
printf("input = %s\n", input_filename);
printf("output = %s\n", output_filename);
for (i = 0; i < argc; i++)
printf("overlay[%d] = %s\n", i, argv[i]);
}

if (do_fdtoverlay(input_filename, output_filename, argc, argv))
return 1;

return 0;
}

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>
@ -9,7 +23,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#include <libfdt.h>

@ -54,7 +67,7 @@ static void report_error(const char *name, int namelen, int err)
* @param arg List of arguments from command line
* @param arg_count Number of arguments (may be 0)
* @param valuep Returns buffer containing value
* @param value_len Returns length of value encoded
* @param *value_len Returns length of value encoded
*/
static int encode_value(struct display_info *disp, char **arg, int arg_count,
char **valuep, int *value_len)
@ -65,12 +78,16 @@ static int encode_value(struct display_info *disp, char **arg, int arg_count,
int len; /* length of this cell/string/byte */
int ival;
int upto; /* the number of bytes we have written to buf */
char fmt[3];

upto = 0;

if (disp->verbose)
fprintf(stderr, "Decoding value:\n");

fmt[0] = '%';
fmt[1] = disp->type ? disp->type : 'd';
fmt[2] = '\0';
for (; arg_count > 0; arg++, arg_count--, upto += len) {
/* assume integer unless told otherwise */
if (disp->type == 's')
@ -90,35 +107,8 @@ static int encode_value(struct display_info *disp, char **arg, int arg_count,
if (disp->verbose)
fprintf(stderr, "\tstring: '%s'\n", ptr);
} else {
fdt32_t *iptr = (fdt32_t *)ptr;
char *endptr;

errno = 0;
switch (disp->type) {
case 'x':
ival = strtoul(*arg, &endptr, 16);
break;
case 'o':
ival = strtoul(*arg, &endptr, 8);
break;
case 'i':
ival = strtol(*arg, &endptr, 0);
break;
case 'u':
ival = strtoul(*arg, &endptr, 0);
break;
default: /* 0 or 'd' */
ival = strtol(*arg, &endptr, 10);
}

if (*endptr != '\0' || errno) {
if (disp->verbose) {
fprintf(stderr,
"Couldn't parse \"%s\" as an integer\n",
*arg);
}
return -1;
}
int *iptr = (int *)ptr;
sscanf(*arg, fmt, &ival);
if (len == 4)
*iptr = cpu_to_fdt32(ival);
else
@ -140,7 +130,7 @@ static int encode_value(struct display_info *disp, char **arg, int arg_count,

#define ALIGN(x) (((x) + (FDT_TAGSIZE) - 1) & ~((FDT_TAGSIZE) - 1))

static char *realloc_fdt(char *fdt, int delta)
static char *_realloc_fdt(char *fdt, int delta)
{
int new_sz = fdt_totalsize(fdt) + delta;
fdt = xrealloc(fdt, new_sz);
@ -154,7 +144,7 @@ static char *realloc_node(char *fdt, const char *name)
/* FDT_BEGIN_NODE, node name in off_struct and FDT_END_NODE */
delta = sizeof(struct fdt_node_header) + ALIGN(strlen(name) + 1)
+ FDT_TAGSIZE;
return realloc_fdt(fdt, delta);
return _realloc_fdt(fdt, delta);
}

static char *realloc_property(char *fdt, int nodeoffset,
@ -171,7 +161,7 @@ static char *realloc_property(char *fdt, int nodeoffset,
/* actual value in off_struct */
delta += ALIGN(newlen) - ALIGN(oldlen);

return realloc_fdt(fdt, delta);
return _realloc_fdt(fdt, delta);
}

static int store_key_value(char **blob, const char *node_name,
@ -343,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;

@ -413,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",
@ -457,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"
@ -34,7 +49,7 @@ static struct version_info {

struct emitter {
void (*cell)(void *, cell_t);
void (*string)(void *, const char *, int);
void (*string)(void *, char *, int);
void (*align)(void *, int);
void (*data)(void *, struct data);
void (*beginnode)(void *, struct label *labels);
@ -49,7 +64,7 @@ static void bin_emit_cell(void *e, cell_t val)
*dtbuf = data_append_cell(*dtbuf, val);
}

static void bin_emit_string(void *e, const char *str, int len)
static void bin_emit_string(void *e, char *str, int len)
{
struct data *dtbuf = e;

@ -124,20 +139,27 @@ 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);
}

static void asm_emit_string(void *e, const char *str, int len)
static void asm_emit_string(void *e, char *str, int len)
{
FILE *f = e;
char c = 0;

if (len != 0)
fprintf(f, "\t.asciz\t\"%.*s\"\n", len, str);
else
fprintf(f, "\t.asciz\t\"%s\"\n", str);
if (len != 0) {
/* XXX: ewww */
c = str[len];
str[len] = '\0';
}

fprintf(f, "\t.string\t\"%s\"\n", str);

if (len != 0) {
str[len] = c;
}
}

static void asm_emit_align(void *e, int a)
@ -150,14 +172,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(*((uint32_t *)(d.val+off))));
off += sizeof(uint32_t);
}

@ -220,7 +242,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,16 +318,17 @@ static struct data flatten_reserve_list(struct reserve_info *reservelist,
{
struct reserve_info *re;
struct data d = empty_data;
unsigned int j;
static struct fdt_reserve_entry null_re = {0,0};
int j;

for (re = reservelist; re; re = re->next) {
d = data_append_re(d, re->address, re->size);
d = data_append_re(d, &re->re);
}
/*
* Add additional reserved slots if the user asked for them.
*/
for (j = 0; j < reservenum; j++) {
d = data_append_re(d, 0, 0);
d = data_append_re(d, &null_re);
}

return d;
@ -346,7 +369,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 +402,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 +462,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 +470,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 +526,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 +534,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) {
@ -521,11 +544,11 @@ void dt_to_asm(FILE *f, struct dt_info *dti, int version)
fprintf(f, "\t.globl\t%s\n", l->label);
fprintf(f, "%s:\n", l->label);
}
ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->address >> 32));
ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.address >> 32));
ASM_EMIT_BELONG(f, "0x%08x",
(unsigned int)(re->address & 0xffffffff));
ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->size >> 32));
ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->size & 0xffffffff));
(unsigned int)(re->re.address & 0xffffffff));
ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.size >> 32));
ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.size & 0xffffffff));
}
for (i = 0; i < reservenum; i++) {
fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n");
@ -586,7 +609,7 @@ static void flat_read_chunk(struct inbuf *inb, void *p, int len)

static uint32_t flat_read_word(struct inbuf *inb)
{
fdt32_t val;
uint32_t val;

assert(((inb->ptr - inb->base) % sizeof(val)) == 0);

@ -604,11 +627,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 +639,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 +701,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);
}


@ -695,15 +718,13 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb)
* First pass, count entries.
*/
while (1) {
uint64_t address, size;

flat_read_chunk(inb, &re, sizeof(re));
address = fdt64_to_cpu(re.address);
size = fdt64_to_cpu(re.size);
if (size == 0)
re.address = fdt64_to_cpu(re.address);
re.size = fdt64_to_cpu(re.size);
if (re.size == 0)
break;

new = build_reserve_entry(address, size);
new = build_reserve_entry(re.address, re.size);
reservelist = add_reserve_entry(reservelist, new);
}

@ -711,13 +732,13 @@ 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;

plen = strlen(ppath);

if (!strstarts(cpath, ppath))
if (!strneq(ppath, cpath, plen))
die("Path \"%s\" is not valid as a child of \"%s\"\n",
cpath, ppath);

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

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

return node;
}

@ -793,7 +817,6 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,
struct dt_info *dt_from_blob(const char *fname)
{
FILE *f;
fdt32_t magic_buf, totalsize_buf;
uint32_t magic, totalsize, version, size_dt, boot_cpuid_phys;
uint32_t off_dt, off_str, off_mem_rsvmap;
int rc;
@ -810,7 +833,7 @@ struct dt_info *dt_from_blob(const char *fname)

f = srcfile_relative_open(fname, NULL);

rc = fread(&magic_buf, sizeof(magic_buf), 1, f);
rc = fread(&magic, sizeof(magic), 1, f);
if (ferror(f))
die("Error reading DT blob magic number: %s\n",
strerror(errno));
@ -821,11 +844,11 @@ struct dt_info *dt_from_blob(const char *fname)
die("Mysterious short read reading magic number\n");
}

magic = fdt32_to_cpu(magic_buf);
magic = fdt32_to_cpu(magic);
if (magic != FDT_MAGIC)
die("Blob has incorrect magic number\n");

rc = fread(&totalsize_buf, sizeof(totalsize_buf), 1, f);
rc = fread(&totalsize, sizeof(totalsize), 1, f);
if (ferror(f))
die("Error reading DT blob size: %s\n", strerror(errno));
if (rc < 1) {
@ -835,7 +858,7 @@ struct dt_info *dt_from_blob(const char *fname)
die("Mysterious short read reading blob size\n");
}

totalsize = fdt32_to_cpu(totalsize_buf);
totalsize = fdt32_to_cpu(totalsize);
if (totalsize < FDT_V1_SIZE)
die("DT blob size (%d) is too small\n", totalsize);


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,2 +1,3 @@
- Tree traversal functions
- Graft function
- Complete libfdt.h documenting comments

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,165 +55,52 @@

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

return fdt_offset_ptr_(fdt, offset);
return _fdt_offset_ptr(fdt, offset);
}

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:
@ -220,25 +141,19 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
return tag;
}

int fdt_check_node_offset_(const void *fdt, int offset)
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;
}

int fdt_check_prop_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;
@ -250,7 +165,7 @@ int fdt_next_node(const void *fdt, int offset, int *depth)
uint32_t tag;

if (offset >= 0)
if ((nextoffset = fdt_check_node_offset_(fdt, offset)) < 0)
if ((nextoffset = _fdt_check_node_offset(fdt, offset)) < 0)
return nextoffset;

do {
@ -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
#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)
@ -63,4 +108,4 @@ struct fdt_property {
#define FDT_V16_SIZE FDT_V3_SIZE
#define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(fdt32_t))

#endif /* FDT_H */
#endif /* _FDT_H */

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"

@ -36,3 +81,4 @@ int fdt_create_empty_tree(void *buf, int bufsize)

return fdt_open_into(buf, buf, bufsize);
}


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>
@ -27,61 +21,65 @@
*/
static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
{
const fdt32_t *val;
const uint32_t *val;
int len;

val = fdt_getprop(fdto, fragment, "target", &len);
if (!val)
return 0;

if ((len != sizeof(*val)) || (fdt32_to_cpu(*val) == (uint32_t)-1))
if ((len != sizeof(*val)) || (*val == (uint32_t)-1))
return (uint32_t)-1;

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
*
* 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)
{
uint32_t phandle;
const char *path = NULL;
int path_len = 0, ret;
const char *path;
int path_len;

/* 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);
if (path)
ret = fdt_path_offset(fdt, path);
else
ret = path_len;
} else
ret = fdt_node_offset_by_phandle(fdt, phandle);
if (phandle)
return fdt_node_offset_by_phandle(fdt, phandle);

/*
* If we haven't found either a target or a
* target-path property in a node that contains a
* __overlay__ subnode (we wouldn't be called
* otherwise), consider it a improperly written
* overlay
*/
if (ret < 0 && path_len == -FDT_ERR_NOTFOUND)
ret = -FDT_ERR_BADOVERLAY;
/* And then a path based lookup */
path = fdt_getprop(fdto, fragment, "target-path", &path_len);
if (!path) {
/*
* If we haven't found either a target or a
* target-path property in a node that contains a
* __overlay__ subnode (we wouldn't be called
* otherwise), consider it a improperly written
* overlay
*/
if (path_len == -FDT_ERR_NOTFOUND)
return -FDT_ERR_BADOVERLAY;

/* return on error */
if (ret < 0)
return ret;
return path_len;
}

/* return pointer to path (if available) */
if (pathp)
*pathp = path ? path : NULL;

return ret;
return fdt_path_offset(fdt, path);
}

/**
@ -101,22 +99,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 uint32_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);
}

/**
@ -208,9 +210,9 @@ static int overlay_update_local_node_references(void *fdto,
int ret;

fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {
const fdt32_t *fixup_val;
const uint32_t *fixup_val;
const char *tree_val;
const char *name;
char *tree_val;
int fixup_len;
int tree_len;
int i;
@ -222,9 +224,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 +233,35 @@ 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++) {
uint32_t adj_val, 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 = fdt32_to_cpu(adj_val);
adj_val += delta;
adj_val = cpu_to_fdt32(adj_val);

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

@ -252,7 +272,7 @@ static int overlay_update_local_node_references(void *fdto,

tree_child = fdt_subnode_offset(fdto, tree_node,
fixup_child_name);
if (tree_child == -FDT_ERR_NOTFOUND)
if (ret == -FDT_ERR_NOTFOUND)
return -FDT_ERR_BADOVERLAY;
if (tree_child < 0)
return tree_child;
@ -307,6 +327,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 +335,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,29 +348,44 @@ 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)
{
fdt32_t phandle_prop;
int fixup_off;
const char *symbol_path;
uint32_t phandle;
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;
if (fixup_off < 0)
return fixup_off;

phandle_prop = cpu_to_fdt32(phandle);
phandle = cpu_to_fdt32(phandle);
return fdt_setprop_inplace_namelen_partial(fdto, fixup_off,
name, name_len, poffset,
&phandle_prop,
sizeof(phandle_prop));
}
&phandle, sizeof(phandle));
};

/**
* overlay_fixup_phandle - Set an overlay phandle to the base one
@ -376,10 +412,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 +422,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 +461,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 +516,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
@ -818,7 +589,7 @@ static int overlay_apply_node(void *fdt, int target,
*
* overlay_merge() merges an overlay into its base device tree.
*
* This is the next to last step in the device tree overlay application
* This is the final step in the device tree overlay application
* process, when all the phandles have been adjusted and resolved and
* you just have to merge overlay into the base device tree.
*
@ -846,7 +617,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);
if (target < 0)
return target;

@ -858,225 +629,30 @@ static int overlay_merge(void *fdt, void *fdto)
return 0;
}

static int get_path_len(const void *fdt, int nodeoffset)
{
int len = 0, namelen;
const char *name;

FDT_RO_PROBE(fdt);

for (;;) {
name = fdt_get_name(fdt, nodeoffset, &namelen);
if (!name)
return namelen;

/* root? we're done */
if (namelen == 0)
break;

nodeoffset = fdt_parent_offset(fdt, nodeoffset);
if (nodeoffset < 0)
return nodeoffset;
len += namelen + 1;
}

/* in case of root pretend it's "/" */
if (len == 0)
len++;
return len;
}

/**
* overlay_symbol_update - Update the symbols of base tree after a merge
* @fdt: Base Device Tree blob
* @fdto: Device tree overlay blob
*
* overlay_symbol_update() updates the symbols of the base tree with the
* symbols of the applied overlay
*
* This is the last step in the device tree overlay application
* process, allowing the reference of overlay symbols by subsequent
* overlay operations.
*
* returns:
* 0 on success
* Negative error code on failure
*/
static int overlay_symbol_update(void *fdt, void *fdto)
{
int root_sym, ov_sym, prop, path_len, fragment, target;
int len, frag_name_len, ret, rel_path_len;
const char *s, *e;
const char *path;
const char *name;
const char *frag_name;
const char *rel_path;
const char *target_path;
char *buf;
void *p;

ov_sym = fdt_subnode_offset(fdto, 0, "__symbols__");

/* if no overlay symbols exist no problem */
if (ov_sym < 0)
return 0;

root_sym = fdt_subnode_offset(fdt, 0, "__symbols__");

/* it no root symbols exist we should create them */
if (root_sym == -FDT_ERR_NOTFOUND)
root_sym = fdt_add_subnode(fdt, 0, "__symbols__");

/* any error is fatal now */
if (root_sym < 0)
return root_sym;

/* iterate over each overlay symbol */
fdt_for_each_property_offset(prop, fdto, ov_sym) {
path = fdt_getprop_by_offset(fdto, prop, &name, &path_len);
if (!path)
return path_len;

/* verify it's a string property (terminated by a single \0) */
if (path_len < 1 || memchr(path, '\0', path_len) != &path[path_len - 1])
return -FDT_ERR_BADVALUE;

/* keep end marker to avoid strlen() */
e = path + path_len;

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

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

/* find the fragment index in which the symbol lies */
ret = fdt_subnode_offset_namelen(fdto, 0, frag_name,
frag_name_len);
/* not found? */
if (ret < 0)
return -FDT_ERR_BADOVERLAY;
fragment = ret;

/* an __overlay__ subnode must exist */
ret = fdt_subnode_offset(fdto, fragment, "__overlay__");
if (ret < 0)
return -FDT_ERR_BADOVERLAY;

/* get the target of the fragment */
ret = fdt_overlay_target_offset(fdt, fdto, fragment, &target_path);
if (ret < 0)
return ret;
target = ret;

/* if we have a target path use */
if (!target_path) {
ret = get_path_len(fdt, target);
if (ret < 0)
return ret;
len = ret;
} else {
len = strlen(target_path);
}

ret = fdt_setprop_placeholder(fdt, root_sym, name,
len + (len > 1) + rel_path_len + 1, &p);
if (ret < 0)
return ret;

if (!target_path) {
/* again in case setprop_placeholder changed it */
ret = fdt_overlay_target_offset(fdt, fdto, fragment, &target_path);
if (ret < 0)
return ret;
target = ret;
}

buf = p;
if (len > 1) { /* target is not root */
if (!target_path) {
ret = fdt_get_path(fdt, target, buf, len + 1);
if (ret < 0)
return ret;
} else
memcpy(buf, target_path, len + 1);

} else
len--;

buf[len] = '/';
memcpy(buf + len + 1, rel_path, rel_path_len);
buf[len + 1 + rel_path_len] = '\0';
}

return 0;
}

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;

ret = overlay_symbol_update(fdt, fdto);
if (ret)
goto err;

/*
* The overlay has been damaged, erase its magic.
*/

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,13 +55,12 @@

#include "libfdt_internal.h"

static int fdt_nodename_eq_(const void *fdt, int offset,
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,174 +75,63 @@ 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,
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)
static int _nextprop(const void *fdt, int offset)
{
uint32_t tag;
int nextoffset;
@ -227,13 +160,13 @@ 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);
offset = fdt_next_node(fdt, offset, &depth))
if ((depth == 1)
&& fdt_nodename_eq_(fdt, offset, name, namelen))
&& _fdt_nodename_eq(fdt, offset, name, namelen))
return offset;

if (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 != '/') {
@ -302,35 +232,17 @@ 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;
const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset);
int err;

if (((err = fdt_ro_probe_(fdt)) < 0)
|| ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 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)
@ -342,107 +254,65 @@ int fdt_first_property_offset(const void *fdt, int nodeoffset)
{
int offset;

if ((offset = fdt_check_node_offset_(fdt, nodeoffset)) < 0)
if ((offset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
return offset;

return nextprop_(fdt, offset);
return _nextprop(fdt, offset);
}

int fdt_next_property_offset(const void *fdt, int offset)
{
if ((offset = fdt_check_prop_offset_(fdt, offset)) < 0)
if ((offset = _fdt_check_prop_offset(fdt, offset)) < 0)
return offset;

return nextprop_(fdt, offset);
}

static 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 (lenp)
*lenp = err;
return NULL;
}

prop = fdt_offset_ptr_(fdt, offset);

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

return prop;
return _nextprop(fdt, offset);
}

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. */
int err;
const struct fdt_property *prop;

if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) {
if (lenp)
*lenp = -FDT_ERR_BADVERSION;
*lenp = err;
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;
}
}
prop = _fdt_offset_ptr(fdt, offset);

if (lenp)
*lenp = offset;
return NULL;
}
*lenp = fdt32_to_cpu(prop->len);

return prop;
}

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);
if (!prop)
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"

@ -10,8 +55,8 @@

#include "libfdt_internal.h"

static int fdt_blocks_misordered_(const void *fdt,
int mem_rsv_size, int struct_size)
static int _fdt_blocks_misordered(const void *fdt,
int mem_rsv_size, int struct_size)
{
return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8))
|| (fdt_off_dt_struct(fdt) <
@ -22,57 +67,54 @@ 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),
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) \
return err_; \
int __err; \
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);
}

static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen)
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;
}

static int fdt_splice_mem_rsv_(void *fdt, struct fdt_reserve_entry *p,
static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p,
int oldn, int newn)
{
int delta = (newn - oldn) * sizeof(*p);
int err;
err = fdt_splice_(fdt, p, oldn * sizeof(*p), newn * sizeof(*p));
err = _fdt_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p));
if (err)
return err;
fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta);
@ -80,13 +122,13 @@ static int fdt_splice_mem_rsv_(void *fdt, struct fdt_reserve_entry *p,
return 0;
}

static int fdt_splice_struct_(void *fdt, void *p,
static int _fdt_splice_struct(void *fdt, void *p,
int oldlen, int newlen)
{
int delta = newlen - oldlen;
int err;

if ((err = fdt_splice_(fdt, p, oldlen, newlen)))
if ((err = _fdt_splice(fdt, p, oldlen, newlen)))
return err;

fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta);
@ -94,63 +136,38 @@ 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)
static int _fdt_splice_string(void *fdt, int newlen)
{
void *p = (char *)fdt
+ fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
int err;

if ((err = fdt_splice_(fdt, p, 0, newlen)))
if ((err = _fdt_splice(fdt, p, 0, newlen)))
return err;

fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + 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,10 +176,10 @@ 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);
re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt));
err = _fdt_splice_mem_rsv(fdt, re, 0, 1);
if (err)
return err;

@ -173,29 +190,27 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)

int fdt_del_mem_rsv(void *fdt, int n)
{
struct fdt_reserve_entry *re = fdt_mem_rsv_w_(fdt, 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;

return fdt_splice_mem_rsv_(fdt, re, 1, 0);
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);
if (!*prop)
*prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
if (! (*prop))
return oldlen;

if ((err = fdt_splice_struct_(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),
if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),
FDT_TAGALIGN(len))))
return err;

@ -203,32 +218,27 @@ static int fdt_resize_property_(void *fdt, int nodeoffset,
return 0;
}

static int fdt_add_property_(void *fdt, int nodeoffset, const char *name,
int namelen, int len, struct fdt_property **prop)
static int _fdt_add_property(void *fdt, int nodeoffset, const char *name,
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)
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;

*prop = fdt_offset_ptr_w_(fdt, nextoffset);
*prop = _fdt_offset_ptr_w(fdt, nextoffset);
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);
err = _fdt_splice_struct(fdt, *prop, 0, proplen);
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)
@ -250,7 +260,7 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name)

newlen = strlen(name);

err = fdt_splice_struct_(fdt, namep, FDT_TAGALIGN(oldlen+1),
err = _fdt_splice_struct(fdt, namep, FDT_TAGALIGN(oldlen+1),
FDT_TAGALIGN(newlen+1));
if (err)
return err;
@ -259,38 +269,22 @@ 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(void *fdt, int nodeoffset, const char *name,
const void *val, int len)
{
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);
if (err)
return err;

*prop_data = prop->data;
return 0;
}

int fdt_setprop_namelen(void *fdt, int nodeoffset, const char *name,
int namelen, const void *val, int len)
{
void *prop_data;
int err;

err = fdt_setprop_placeholder_namelen(fdt, nodeoffset, name, namelen,
len, &prop_data);
err = _fdt_add_property(fdt, nodeoffset, name, len, &prop);
if (err)
return err;

if (len)
memcpy(prop_data, val, len);
memcpy(prop->data, val, len);
return 0;
}

@ -300,12 +294,12 @@ 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) {
newlen = len + oldlen;
err = fdt_splice_struct_(fdt, prop->data,
err = _fdt_splice_struct(fdt, prop->data,
FDT_TAGALIGN(oldlen),
FDT_TAGALIGN(newlen));
if (err)
@ -313,8 +307,7 @@ int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
prop->len = cpu_to_fdt32(newlen);
memcpy(prop->data + oldlen, val, len);
} else {
err = fdt_add_property_(fdt, nodeoffset, name, strlen(name),
len, &prop);
err = _fdt_add_property(fdt, nodeoffset, name, len, &prop);
if (err)
return err;
memcpy(prop->data, val, len);
@ -327,14 +320,14 @@ 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)
if (! prop)
return len;

proplen = sizeof(*prop) + FDT_TAGALIGN(len);
return fdt_splice_struct_(fdt, prop, proplen, 0);
return _fdt_splice_struct(fdt, prop, proplen, 0);
}

int fdt_add_subnode_namelen(void *fdt, int parentoffset,
@ -347,7 +340,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,19 +349,16 @@ 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);
} while ((tag == FDT_PROP) || (tag == FDT_NOP));

nh = fdt_offset_ptr_w_(fdt, offset);
nh = _fdt_offset_ptr_w(fdt, offset);
nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE;

err = fdt_splice_struct_(fdt, nh, 0, nodelen);
err = _fdt_splice_struct(fdt, nh, 0, nodelen);
if (err)
return err;

@ -390,20 +380,18 @@ 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);
endoffset = _fdt_node_end_offset(fdt, nodeoffset);
if (endoffset < 0)
return endoffset;

return fdt_splice_struct_(fdt, fdt_offset_ptr_w_(fdt, nodeoffset),
return _fdt_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset),
endoffset - nodeoffset, 0);
}

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

@ -418,7 +406,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 +421,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 +464,7 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
return -FDT_ERR_NOSPACE;
}

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

fdt_set_magic(buf, FDT_MAGIC);
@ -495,13 +480,12 @@ 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_set_totalsize(fdt, fdt_data_size_(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)
static void *_fdt_grab_space(void *fdt, size_t len)
{
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);
@ -103,46 +82,29 @@ static void *fdt_grab_space_(void *fdt, size_t len)
return NULL;

fdt_set_size_dt_struct(fdt, offset + len);
return fdt_offset_ptr_w_(fdt, offset);
}

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

if (bufsize < hdrsize)
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_totalsize(fdt, bufsize);

fdt_set_off_mem_rsvmap(fdt, hdrsize);
fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt));
fdt_set_off_dt_strings(fdt, 0);

return 0;
return _fdt_offset_ptr_w(fdt, offset);
}

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

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

memset(buf, 0, bufsize);

fdt_set_magic(fdt, FDT_SW_MAGIC);
fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION);
fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
fdt_set_totalsize(fdt, bufsize);

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, bufsize);

return 0;
}

int fdt_resize(void *fdt, void *buf, int bufsize)
@ -150,19 +112,12 @@ 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,24 +164,17 @@ 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));
nh = _fdt_grab_space(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
if (! nh)
return -FDT_ERR_NOSPACE;

@ -237,9 +187,9 @@ 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);
en = _fdt_grab_space(fdt, FDT_TAGSIZE);
if (! en)
return -FDT_ERR_NOSPACE;

@ -247,90 +197,48 @@ 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;
int struct_top, offset;

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;

p = fdt_find_string_(strtab - strtabsize, strtabsize, s);
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);
}

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

/* 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);
}
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);
return -FDT_ERR_NOSPACE;
}

prop->tag = cpu_to_fdt32(FDT_PROP);
prop->nameoff = cpu_to_fdt32(nameoff);
prop->len = cpu_to_fdt32(len);
*valp = prop->data;
return 0;
memcpy(strtab + offset, s, len);
fdt_set_size_dt_strings(fdt, strtabsize + len);
return offset;
}

int fdt_property(void *fdt, const char *name, const void *val, int len)
{
void *ptr;
int ret;
struct fdt_property *prop;
int nameoff;

ret = fdt_property_placeholder(fdt, name, len, &ptr);
if (ret)
return ret;
memcpy(ptr, val, len);
FDT_SW_CHECK_HEADER(fdt);

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)
return -FDT_ERR_NOSPACE;

prop->tag = cpu_to_fdt32(FDT_PROP);
prop->nameoff = cpu_to_fdt32(nameoff);
prop->len = cpu_to_fdt32(len);
memcpy(prop->data, val, len);
return 0;
}

@ -342,10 +250,10 @@ 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));
end = _fdt_grab_space(fdt, sizeof(*end));
if (! end)
return -FDT_ERR_NOSPACE;
*end = cpu_to_fdt32(FDT_END);
@ -361,7 +269,7 @@ int fdt_finish(void *fdt)
while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {
if (tag == FDT_PROP) {
struct fdt_property *prop =
fdt_offset_ptr_w_(fdt, offset);
_fdt_offset_ptr_w(fdt, offset);
int nameoff;

nameoff = fdt32_to_cpu(prop->nameoff);
@ -375,10 +283,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);
@ -37,7 +82,7 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
int proplen;

propval = fdt_getprop(fdt, nodeoffset, name, &proplen);
if (!propval)
if (! propval)
return proplen;

if (proplen != len)
@ -48,7 +93,7 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
val, len);
}

static void fdt_nop_region_(void *start, int len)
static void _fdt_nop_region(void *start, int len)
{
fdt32_t *p;

@ -62,15 +107,15 @@ int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
int len;

prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
if (!prop)
if (! prop)
return len;

fdt_nop_region_(prop, len + sizeof(*prop));
_fdt_nop_region(prop, len + sizeof(*prop));

return 0;
}

int fdt_node_end_offset_(void *fdt, int offset)
int _fdt_node_end_offset(void *fdt, int offset)
{
int depth = 0;

@ -84,11 +129,11 @@ int fdt_nop_node(void *fdt, int nodeoffset)
{
int endoffset;

endoffset = fdt_node_end_offset_(fdt, nodeoffset);
endoffset = _fdt_node_end_offset(fdt, nodeoffset);
if (endoffset < 0)
return endoffset;

fdt_nop_region_(fdt_offset_ptr_w(fdt, nodeoffset, 0),
_fdt_nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0),
endoffset - nodeoffset);
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,30 +1,73 @@
/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
#ifndef LIBFDT_ENV_H
#define LIBFDT_ENV_H
#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))
#define FDT_BITWISE __attribute__((bitwise))
#define __force __attribute__((force))
#define __bitwise __attribute__((bitwise))
#else
#define FDT_FORCE
#define FDT_BITWISE
#define __force
#define __bitwise
#endif

typedef uint16_t FDT_BITWISE fdt16_t;
typedef uint32_t FDT_BITWISE fdt32_t;
typedef uint64_t FDT_BITWISE fdt64_t;
typedef uint16_t __bitwise fdt16_t;
typedef uint32_t __bitwise fdt32_t;
typedef uint64_t __bitwise fdt64_t;

#define EXTRACT_BYTE(x, n) ((unsigned long long)((uint8_t *)&x)[n])
#define CPU_TO_FDT16(x) ((EXTRACT_BYTE(x, 0) << 8) | EXTRACT_BYTE(x, 1))
@ -37,60 +80,33 @@ typedef uint64_t FDT_BITWISE fdt64_t;

static inline uint16_t fdt16_to_cpu(fdt16_t x)
{
return (FDT_FORCE uint16_t)CPU_TO_FDT16(x);
return (__force uint16_t)CPU_TO_FDT16(x);
}
static inline fdt16_t cpu_to_fdt16(uint16_t x)
{
return (FDT_FORCE fdt16_t)CPU_TO_FDT16(x);
return (__force fdt16_t)CPU_TO_FDT16(x);
}

static inline uint32_t fdt32_to_cpu(fdt32_t x)
{
return (FDT_FORCE uint32_t)CPU_TO_FDT32(x);
return (__force uint32_t)CPU_TO_FDT32(x);
}
static inline fdt32_t cpu_to_fdt32(uint32_t x)
{
return (FDT_FORCE fdt32_t)CPU_TO_FDT32(x);
return (__force fdt32_t)CPU_TO_FDT32(x);
}

static inline uint64_t fdt64_to_cpu(fdt64_t x)
{
return (FDT_FORCE uint64_t)CPU_TO_FDT64(x);
return (__force uint64_t)CPU_TO_FDT64(x);
}
static inline fdt64_t cpu_to_fdt64(uint64_t x)
{
return (FDT_FORCE fdt64_t)CPU_TO_FDT64(x);
return (__force fdt64_t)CPU_TO_FDT64(x);
}
#undef CPU_TO_FDT64
#undef CPU_TO_FDT32
#undef CPU_TO_FDT16
#undef EXTRACT_BYTE

#ifdef __APPLE__
#include <AvailabilityMacros.h>

/* strnlen() is not available on Mac OS < 10.7 */
# if !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED < \
MAC_OS_X_VERSION_10_7)

#define strnlen fdt_strnlen

/*
* fdt_strnlen: returns the length of a string or max_count - which ever is
* smallest.
* Input 1 string: the string whose size is to be determined
* Input 2 max_count: the maximum value returned by this function
* Output: length of the string or max_count (the smallest of the two)
*/
static inline size_t fdt_strnlen(const char *string, size_t max_count)
{
const char *p = memchr(string, 0, max_count);
return p ? p - string : max_count;
}

#endif /* !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED <
MAC_OS_X_VERSION_10_7) */

#endif /* __APPLE__ */

#endif /* LIBFDT_ENV_H */
#endif /* _LIBFDT_ENV_H */

View File

@ -1,47 +1,83 @@
/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
#ifndef LIBFDT_INTERNAL_H
#define LIBFDT_INTERNAL_H
#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>

#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);
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(const char *strtab, int tabsize, const char *s);
int _fdt_node_end_offset(void *fdt, int nodeoffset);

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

int fdt_node_end_offset_(void *fdt, int nodeoffset);

static inline const void *fdt_offset_ptr_(const void *fdt, int offset)
static inline const void *_fdt_offset_ptr(const void *fdt, int offset)
{
return (const char *)fdt + fdt_off_dt_struct(fdt) + offset;
}

static inline void *fdt_offset_ptr_w_(void *fdt, int offset)
static inline void *_fdt_offset_ptr_w(void *fdt, int offset)
{
return (void *)(uintptr_t)fdt_offset_ptr_(fdt, offset);
return (void *)(uintptr_t)_fdt_offset_ptr(fdt, offset);
}

static inline const struct fdt_reserve_entry *fdt_mem_rsv_(const void *fdt, int n)
static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n)
{
const struct fdt_reserve_entry *rsv_table =
(const struct fdt_reserve_entry *)
@ -49,152 +85,11 @@ static inline const struct fdt_reserve_entry *fdt_mem_rsv_(const void *fdt, int

return rsv_table + n;
}
static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n)
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);
return (void *)(uintptr_t)_fdt_mem_rsv(fdt, n);
}

#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 */
#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;
@ -63,25 +60,9 @@ LIBFDT_1.2 {
fdt_address_cells;
fdt_size_cells;
fdt_stringlist_contains;
fdt_stringlist_count;
fdt_stringlist_search;
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);
@ -225,37 +216,6 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
return old_node;
}

struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref)
{
static unsigned int next_orphan_fragment = 0;
struct node *node;
struct property *p;
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);

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

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

add_child(dt, node);
return dt;
}

struct node *chain_node(struct node *first, struct node *list)
{
assert(first->next_sibling == NULL);
@ -337,76 +297,20 @@ void delete_node(struct node *node)
}

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

p = get_property(node, name);
if (!p) {
p = build_property(name, empty_data, NULL);
add_property(node, p);
}

p->val = data_add_marker(p->val, type, name);
p->val = data_append_data(p->val, data, len);
}

static int append_unique_str_to_property(struct node *node,
char *name, const char *data, int len)
char *name, const void *data, int len)
{
struct data d;
struct property *p;

p = get_property(node, name);
if (p) {
const char *s;

if (p->val.len && p->val.val[p->val.len - 1] != '\0')
/* The current content doesn't look like a string */
return -1;

for (s = p->val.val; s < p->val.val + p->val.len; s = strchr(s, '\0') + 1) {
if (strcmp(data, s) == 0)
/* data already contained in node.name */
return 0;
}
d = data_append_data(p->val, data, len);
p->val = d;
} else {
p = build_property(name, empty_data, NULL);
d = data_append_data(empty_data, data, len);
p = build_property(name, d);
add_property(node, p);
}

p->val = data_add_marker(p->val, TYPE_STRING, name);
p->val = data_append_data(p->val, data, len);

return 0;
}

static int append_unique_u32_to_property(struct node *node, char *name, fdt32_t value)
{
struct property *p;

p = get_property(node, name);
if (p) {
const fdt32_t *v, *val_end = (const fdt32_t *)p->val.val + p->val.len / 4;

if (p->val.len % 4 != 0)
/* The current content doesn't look like a u32 array */
return -1;

for (v = (const void *)p->val.val; v < val_end; v++) {
if (*v == value)
/* value already contained */
return 0;
}
} else {
p = build_property(name, empty_data, NULL);
add_property(node, p);
}

p->val = data_add_marker(p->val, TYPE_UINT32, name);
p->val = data_append_data(p->val, &value, 4);

return 0;
}

struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
@ -415,8 +319,8 @@ struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)

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

new->address = address;
new->size = size;
new->re.address = address;
new->re.size = size;

return new;
}
@ -489,13 +393,7 @@ struct property *get_property(struct node *node, const char *propname)
cell_t propval_cell(struct property *prop)
{
assert(prop->val.len == sizeof(cell_t));
return fdt32_to_cpu(*((fdt32_t *)prop->val.val));
}

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

struct property *get_property_by_label(struct node *tree, const char *label,
@ -557,7 +455,7 @@ struct node *get_subnode(struct node *node, const char *nodename)
struct node *child;

for_each_child(node, child)
if (streq(child->name, nodename) && !child->deleted)
if (streq(child->name, nodename))
return child;

return NULL;
@ -580,7 +478,7 @@ struct node *get_node_by_path(struct node *tree, const char *path)
p = strchr(path, '/');

for_each_child(tree, child) {
if (p && strprefixeq(path, (size_t)(p - path), child->name))
if (p && strneq(path, child->name, p-path))
return get_node_by_path(child, p+1);
else if (!p && streq(path, child->name))
return child;
@ -613,10 +511,7 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
{
struct node *child, *node;

if (!phandle_is_valid(phandle)) {
assert(generate_fixups);
return NULL;
}
assert((phandle != 0) && (phandle != -1));

if (tree->phandle == phandle) {
if (tree->deleted)
@ -635,62 +530,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))
@ -698,8 +550,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
@ -738,13 +599,13 @@ static int cmp_reserve_info(const void *ax, const void *bx)
a = *((const struct reserve_info * const *)ax);
b = *((const struct reserve_info * const *)bx);

if (a->address < b->address)
if (a->re.address < b->re.address)
return -1;
else if (a->address > b->address)
else if (a->re.address > b->re.address)
return 1;
else if (a->size < b->size)
else if (a->re.size < b->re.size)
return -1;
else if (a->size > b->size)
else if (a->re.size > b->re.size)
return 1;
else
return 0;
@ -869,18 +730,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;

@ -934,9 +795,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);
}

@ -971,61 +831,47 @@ static bool any_fixup_tree(struct dt_info *dti, struct node *node)
return false;
}

static int add_fixup_entry(struct dt_info *dti, struct node *fn,
struct node *node, struct property *prop,
struct marker *m)
static void add_fixup_entry(struct dt_info *dti, struct node *fn,
struct node *node, struct property *prop,
struct marker *m)
{
char *entry;
int ret;

/* m->ref can only be a REF_PHANDLE, but check anyway */
assert(m->type == REF_PHANDLE);

/* The format only permits fixups for references to label, not
* references to path */
if (strchr(m->ref, '/'))
die("Can't generate fixup for reference to path &{%s}\n",
m->ref);

/* there shouldn't be any ':' in the arguments */
if (strchr(node->fullpath, ':') || strchr(prop->name, ':'))
die("arguments should not contain ':'\n");

xasprintf(&entry, "%s:%s:%u",
node->fullpath, prop->name, m->offset);
ret = append_unique_str_to_property(fn, m->ref, entry, strlen(entry) + 1);
append_to_property(fn, m->ref, entry, strlen(entry) + 1);

free(entry);

return ret;
}

static int generate_fixups_tree_internal(struct dt_info *dti,
struct node *fn,
struct node *node)
static void generate_fixups_tree_internal(struct dt_info *dti,
struct node *fn,
struct node *node)
{
struct node *dt = dti->dt;
struct node *c;
struct property *prop;
struct marker *m;
struct node *refnode;
int ret = 0;

for_each_property(node, prop) {
m = prop->val.markers;
for_each_marker_of_type(m, REF_PHANDLE) {
refnode = get_node_by_ref(dt, m->ref);
if (!refnode)
if (add_fixup_entry(dti, fn, node, prop, m))
ret = -1;
add_fixup_entry(dti, fn, node, prop, m);
}
}

for_each_child(node, c)
if (generate_fixups_tree_internal(dti, fn, c))
ret = -1;

return ret;
generate_fixups_tree_internal(dti, fn, c);
}

static bool any_local_fixup_tree(struct dt_info *dti, struct node *node)
@ -1050,17 +896,17 @@ static bool any_local_fixup_tree(struct dt_info *dti, struct node *node)
return false;
}

static int add_local_fixup_entry(struct dt_info *dti,
static void add_local_fixup_entry(struct dt_info *dti,
struct node *lfn, struct node *node,
struct property *prop, struct marker *m,
struct node *refnode)
{
struct node *wn, *nwn; /* local fixup node, walk node, new */
fdt32_t value_32;
uint32_t value_32;
char **compp;
int i, depth;

/* walk back retrieving depth */
/* walk back retreiving depth */
depth = 0;
for (wn = node; wn; wn = wn->parent)
depth++;
@ -1075,44 +921,41 @@ static int add_local_fixup_entry(struct dt_info *dti,
/* walk the path components creating nodes if they don't exist */
for (wn = lfn, i = 1; i < depth; i++, wn = nwn) {
/* if no node exists, create it */
nwn = build_root_node(wn, compp[i]);
nwn = get_subnode(wn, compp[i]);
if (!nwn)
nwn = build_and_name_child_node(wn, compp[i]);
}

free(compp);

value_32 = cpu_to_fdt32(m->offset);
return append_unique_u32_to_property(wn, prop->name, value_32);
append_to_property(wn, prop->name, &value_32, sizeof(value_32));
}

static int generate_local_fixups_tree_internal(struct dt_info *dti,
struct node *lfn,
struct node *node)
static void generate_local_fixups_tree_internal(struct dt_info *dti,
struct node *lfn,
struct node *node)
{
struct node *dt = dti->dt;
struct node *c;
struct property *prop;
struct marker *m;
struct node *refnode;
int ret = 0;

for_each_property(node, prop) {
m = prop->val.markers;
for_each_marker_of_type(m, REF_PHANDLE) {
refnode = get_node_by_ref(dt, m->ref);
if (refnode)
if (add_local_fixup_entry(dti, lfn, node, prop, m, refnode))
ret = -1;
add_local_fixup_entry(dti, lfn, node, prop, m, refnode);
}
}

for_each_child(node, c)
if (generate_local_fixups_tree_internal(dti, lfn, c))
ret = -1;

return ret;
generate_local_fixups_tree_internal(dti, lfn, c);
}

void generate_label_tree(struct dt_info *dti, const char *name, bool allocph)
void generate_label_tree(struct dt_info *dti, char *name, bool allocph)
{
if (!any_label_tree(dti, dti->dt))
return;
@ -1120,22 +963,18 @@ void generate_label_tree(struct dt_info *dti, const char *name, bool allocph)
dti->dt, allocph);
}

void generate_fixups_tree(struct dt_info *dti, const char *name)
void generate_fixups_tree(struct dt_info *dti, char *name)
{
if (!any_fixup_tree(dti, dti->dt))
return;
if (generate_fixups_tree_internal(dti, build_root_node(dti->dt, name), dti->dt))
fprintf(stderr,
"Warning: Preexisting data in %s malformed, some content could not be added.\n",
name);
generate_fixups_tree_internal(dti, build_root_node(dti->dt, name),
dti->dt);
}

void generate_local_fixups_tree(struct dt_info *dti, const char *name)
void generate_local_fixups_tree(struct dt_info *dti, char *name)
{
if (!any_local_fixup_tree(dti, dti->dt))
return;
if (generate_local_fixups_tree_internal(dti, build_root_node(dti->dt, name), dti->dt))
fprintf(stderr,
"Warning: Preexisting data in %s malformed, some content could not be added.\n",
name);
generate_local_fixups_tree_internal(dti, build_root_node(dti->dt, name),
dti->dt);
}

View File

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

cc = meson.get_compiler('c')

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

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

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

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

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

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

subdir('libfdt')

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

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

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

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

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

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

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

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

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

if pylibfdt_enabled
subdir('pylibfdt')
endif

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

View File

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

3
pylibfdt/.gitignore vendored
View File

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

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,
)

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']

1
redhat/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
v*.tar.gz

67
redhat/Makefile Normal file
View File

@ -0,0 +1,67 @@
include Makefile.common

REDHAT:=$(shell pwd)
SCRIPTS:=$(REDHAT)/scripts
RPMBUILD:=$(REDHAT)/rpmbuild

# Hide command calls without debug option
ifeq ($(DEBUG),1)
DS=
else
DS=@
endif

BREW_OPTIONS:=$(BREW_FLAGS) --scratch

# Hide progress bar in scripts
ifeq ($(NOPROGRESS),1)
BREW_OPTIONS:=$(BREW_OPTIONS) --noprogress
endif

# Do not wait for build finish
ifeq ($(NOWAIT),1)
BREW_OPTIONS:=$(BREW_OPTIONS) --nowait
endif

# create an empty localversion file if you don't want a local buildid
ifneq ($(NOLOCALVERSION),1)
ifeq ($(LOCALVERSION),)
LOCALVERSION=$(shell cat ../localversion 2>/dev/null)
endif
ifeq ($(LOCALVERSION),)
LOCALVERSION:=.test
else
LOCALVERSION:=.$(LOCALVERSION)
endif
else
LOCALVERSION:=
endif

.PHONY: rh-brew rh-srpm rh-prep rh-help rh-clean-sources
all: rh-help

rh-clean-sources:
$(DS)for i in $(RPMBUILD)/SOURCES/*; do \
rm -f $$i; \
done; \

rh-prep: rh-clean-sources
$(DS)if [ -n "$(SOURCES_FILELIST)" ]; then \
echo "Copying Sources: $(SOURCES_FILELIST)"; \
cp $(SOURCES_FILELIST) $(RPMBUILD)/SOURCES; \
fi
$(DS)$(SCRIPTS)/process-patches.sh "$(SCRIPTS)" "$(NAME)" "$(VERSION)" "$(RELEASE)" "$(DATE)" "$(COMMIT)" "$(TARFILE)" "$(TARURL)" "$(SPECFILE)" "$(BUILD_DIR)" "$(MARKER)" "$(LOCALVERSION)" "$(RHEV)" "$(ZRELEASE)"

rh-srpm: rh-prep
$(DS)rpmbuild --define "_sourcedir $(RPMBUILD)/SOURCES" --define "_builddir $(RPMBUILD)/BUILD" --define "_srcrpmdir $(RPMBUILD)/SRPMS" --define "_rpmdir $(RPMBUILD)/RPMS" --define "_specdir $(RPMBUILD)/SPECS" --define "dist $(DIST)" --nodeps -bs $(RPMBUILD)/SPECS/$(SPECFILE)

rh-brew: rh-srpm
@echo "Build $(SRPM_NAME)$(LOCALVERSION).src.rpm as $(BUILD_TARGET)"
$(DS)brew build $(BREW_OPTIONS) $(BUILD_TARGET) $(RPMBUILD)/SRPMS/$(SRPM_NAME)$(LOCALVERSION).src.rpm

rh-help:
@echo "rh-brew: Build package on brew"
@echo "rh-srpm: Prepare srpm package"
@echo "rh-prep: Prepare sources and spec file in rpmbuild/"
@echo "rh-help: Print this help"

35
redhat/Makefile.common Normal file
View File

@ -0,0 +1,35 @@
UNAME:=dtc
NAME:=dtc
RHEV:=0
VERSION:=1.4.3
DATE:=
COMMIT:=
RELEASE:=1
ZRELEASE:=
RELEASE_SEPARATOR:=-

TARFILE:=v$(VERSION).tar.gz
TARURL:=https://github.com/dgibson/dtc/archive/v1.4.3.tar.gz
TARSHA1:=cef129e4444a52dcd704c08c6375fa3894954048
MARKER:=fa8bc7f928ac25f23532afc8beb2073efc8fb063
SOURCES_FILELIST:=

SPECFILE:=$(NAME).spec
DIST:=.el7
BUILD_TARGET:=rhel-7.3-candidate

ifeq ($(RHEV),1)
NAME_SUFFIX:=-rhev
endif

ifneq ($(VERSION),)
BUILD_DIR:=$(UNAME)-$(VERSION)
SRPM_NAME:=$(NAME)$(NAME_SUFFIX)-$(VERSION)$(RELEASE_SEPARATOR)$(RELEASE)$(DIST)
else
BUILD_DIR:=$(UNAME)-$(GITCOMMIT
SRPM_NAME:=$(NAME)$(NAME_SUFFIX)-$(DATE)-$(RELEASE).git$(COMMIT)$(DIST)
endif

ifneq ($(ZRELEASE),)
SRPM_NAME:=$(SRPM_NAME).$(ZRELEASE)
endif

86
redhat/dtc.spec.template Normal file
View File

@ -0,0 +1,86 @@
Name: dtc
Version: %%VERSION%%
Release: %%RELEASE%%%{?dist}%%ZRELEASE%%%%LOCALVERSION%%
Summary: Device Tree Compiler
Group: Development/Tools
License: GPLv2+
URL: https://github.com/dgibson/dtc
Source: https://github.com/dgibson/dtc/archive/v%{version}.tar.gz

%%PATCHLIST%%

BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)

BuildRequires: flex, bison
ExclusiveArch: %{power64} aarch64

%description
The Device Tree Compiler generates flattened Open Firmware style device trees
for use with PowerPC machines that lack an Open Firmware implementation

%package -n libfdt
Summary: Device tree library
Group: Development/Libraries

%description -n libfdt
libfdt is a library to process Open Firmware style device trees on various
architectures.

%package -n libfdt-devel
Summary: Development headers for device tree library
Group: Development/Libraries
Requires: libfdt = %{version}-%{release}

%description -n libfdt-devel
This package provides development files for libfdt

%prep
%setup -q -n dtc-%{version}

%%PATCHAPPLY%%

%build
make %{?_smp_mflags}

%install
rm -rf $RPM_BUILD_ROOT
make install DESTDIR=$RPM_BUILD_ROOT PREFIX=/usr LIBDIR=%{_libdir}
rm -rf $RPM_BUILD_ROOT/%{_libdir}/*.a

# we don't want or need ftdump, so drop
rm -f $RPM_BUILD_ROOT/%{_bindir}/ftdump

%clean
rm -rf $RPM_BUILD_ROOT

%files
%defattr(-,root,root,-)
%doc GPL
%{_bindir}/*

%files -n libfdt
%defattr(-,root,root,-)
%doc GPL
%{_libdir}/libfdt-%{version}.so
%{_libdir}/libfdt.so.*

%files -n libfdt-devel
%defattr(-,root,root,-)
%{_libdir}/libfdt.so
%{_includedir}/*

%post -n libfdt -p /sbin/ldconfig

%postun -n libfdt -p /sbin/ldconfig

%changelog
* Mon Mar 06 2017 Miroslav Rezanina <mrezanin@redhat.com> - 1.4.3-1
- Rebase to 1.4.3 [bz#1427157]
- Resolves: bz#1427157
(package libfdt 1.4.3, when available)

* Tue Aug 19 2014 Miroslav Rezanina <mrezanin@redhat.com> - 1.4.0-2
- Update power macro for ppc64le

* Fri Jul 25 2014 Miroslav Rezanina <mrezanin@redhat.com> - 1.4.0-1
- Initial version

2
redhat/rpmbuild/BUILD/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*
!.gitignore

2
redhat/rpmbuild/RPMS/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*
!.gitignore

2
redhat/rpmbuild/SOURCES/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*
!.gitignore

2
redhat/rpmbuild/SPECS/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*
!.gitignore

2
redhat/rpmbuild/SRPMS/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*
!.gitignore

27
redhat/scripts/frh.py Executable file
View File

@ -0,0 +1,27 @@
#!/usr/bin/python

import re
import sys

def filter_file(inf):
ts_chunkstart = re.compile("diff --git ")
ts_redhat = re.compile(".*\/redhat\/")
ts_gitfile = re.compile(".*\/\.git")
skip = False
f = open(inf,"r")
for line in f.readlines():
if ts_chunkstart.match(line) is not None:
if ts_redhat.match(line) is not None or ts_gitfile.match(line) is not None:
skip = True
else:
skip = False
if skip == False:
sys.stdout.write(line)
f.close()

if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: %s <filename>" % sys.argv[0])
exit(1)
filter_file(sys.argv[1])

327
redhat/scripts/git-backport-diff Executable file
View File

@ -0,0 +1,327 @@
#!/bin/bash
#
# See $desc, below, for program description
#
# Copyright (c) 2013 Red Hat, Inc.
#
# Author(s):
# Jeff Cody <jcody@redhat.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; under version 2 of the license
#
# 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, see <http://www.gnu.org/licenses/gpl-2.0.html>.
#

set -C -u -e
set -o pipefail

desc="
$0 compares the commits in a specified git range, with the corresponding
upstream commit. This assumes that you have both the downstream and
upstream repositories added as remotes in your git repo.

Example usage:
$0 -r qemu-kvm-0.12.1.2-2.370.el6..my_feature_branch -u v1.5.0

Ouput key:
[----] Indicates the patches upstream and downstream are identical
[####] Indicates the number of differences (#### is substituted)
[down] Indicates the patch only exists downstream"

def_upstream="v1.7.0"
def_diffprog=meld
def_range="HEAD^!"
def_color='y'
def_pause='y'
def_sensitivity=0
def_summary='n'

upstream=`git config backport-diff.upstream || true`
diffprog=`git config backport-diff.diffprog || true`
range=`git config backport-diff.range || true`
color=`git config backport-diff.color || true`
pause=`git config backport-diff.pause || true`
sensitivity=`git config backport-diff.sensitivity || true`
summary=`git config backport-diff.summary || true`

if [[ -z "$upstream" ]]
then
upstream=$def_upstream
git config backport-diff.upstream $upstream || true
fi
if [[ -z "$diffprog" ]]
then
diffprog=$def_diffprog
git config backport-diff.diffprog $diffprog || true
fi
if [[ -z "$range" ]]
then
range=$def_range
git config backport-diff.range $range || true
fi
if [[ -z "$color" ]]
then
color=$def_color
git config backport-diff.color $color || true
fi
if [[ -z "$pause" ]]
then
pause=$def_pause
git config backport-diff.pause $pause || true
fi
if [[ -z "$sensitivity" ]]
then
sensitivity=$def_sensitivity
git config backport-diff.sensitivity $sensitivity || true
fi
if [[ -z "$summary" ]]
then
summary=$def_summary
git config backport-diff.summary $summary || true
fi


usage() {
echo ""
echo "$0 [OPTIONS]"
echo "$desc"
echo ""
echo "OPTIONS:"
echo " -r git range
optional; default is '$range'
"
echo " -u upstream git tag / branch / id
optional; default is '$upstream'
"
echo " -n do not use colors
"
echo " -d diff program to use
optional; default is '$diffprog'
"
echo " -p do not pause when viewing diffs
"
echo " -s sensitivity level of diff compares
0: only show functional code differences
1: show (0) + contextual differences
2+: offer to compare all patches, regardless of any differences
"
echo " -S summary only (no diff viewing)
"
echo " -h help"
echo ""
echo "You can set each of the default options using git-config:"
echo " git config backport-diff.upstream"
echo " git config backport-diff.diffprog"
echo " git config backport-diff.range"
echo " git config backport-diff.color"
echo " git config backport-diff.pause"
echo " git config backport-diff.summary"
}

while getopts ":r:u:nd:phs:S" opt
do
case $opt in
r) range=$OPTARG
;;
u) upstream=$OPTARG
;;
n) color='n'
;;
d) diffprog=$OPTARG
;;
p) pause='n'
;;
s) sensitivity=$OPTARG
if ! [[ "$sensitivity" =~ ^[0-9]+$ ]]
then
echo "Invalid argument for -s" >&2
usage
exit 1
fi
;;
S) summary='y'
;;
h) usage
exit
;;
\?) echo "Unknown option: -$OPTARG" >&2
usage
exit 1
;;
esac
done

if [[ $color == 'y' ]]
then
bold=$(tput bold)
color1=$(tput setaf 1)
color2=$(tput setaf 2)
color3=$(tput setaf 3)
color4=$(tput setaf 4)
color5=$(tput setaf 5)
color6=$(tput setaf 6)
color7=$(tput setaf 7)
reset=$(tput sgr0)
else
bold=
color1=
color2=
color3=
color4=
color5=
color6=
color7=
reset=
fi

trap cleanup EXIT

cleanup() {
echo $reset
}

total=`git rev-list "$range" |wc -l`

# verify the upstream exists
upstream_valid='n'
# branch
if git show-ref --quiet --verify refs/heads/${upstream}
then
upstream_valid='y'
# tag
elif git show-ref --quiet --verify refs/tags/${upstream}
then
upstream_valid='y'
# remote branch
elif git show-ref --quiet --verify refs/remotes/${upstream}
then
upstream_valid='y'
# commit id
elif git rev-list --max-count=1 --quiet $upstream >/dev/null 2>&1
then
upstream_valid='y'
fi

numdiff=0
label=
subjlist=
cnt=0
compare_git()
{
echo "Key:"
printf "[----] : patches are identical\n"
printf "[${bold}####${reset}] : number of functional differences between upstream/downstream patch\n"
printf "[${bold}${color1}down${reset}] : patch is downstream-only\n"
printf "The flags [${bold}FC${reset}] indicate (F)unctional and (C)ontextual differences, respectively\n\n"
# don't pipe the git job into read, to avoid subshells
while read hashsubj
do
let cnt=$cnt+1;
subj=${hashsubj:40}
downhash=${hashsubj:0:40}
# A little bit hackish, but find the match by looking at upstream
# subject lines, and using the last one. Not all backports contain
# the phrase "cherry-pick", so we can't really try and find the
# upstream hash from that...
uphash=`git log $upstream --pretty=format:"%H" --fixed-strings --grep="${subj}" |tail -n 1`
if [[ -n "$uphash" ]]
then
numdiff=`diff -u <(git diff $uphash^! |egrep ^[-+])\
<(git diff $downhash^! |egrep ^[-+])\
| egrep '^[-+]' | egrep -v '^[-+]{3}' |wc -l || true`
# for contextual diff checking, we will ignore hashes and line number offsets
condiff=`diff -u <(git diff $uphash^\! |sed -e s/^@@.*@@//g |egrep -v ^index |egrep -v ^diff)\
<(git diff $downhash^\!|sed -e s/^@@.*@@//g |egrep -v ^index |egrep -v ^diff)\
| egrep '^[-+]' | egrep -v '^[-+]{3}'|wc -l || true`
f="-"
c="-"
if [[ $sensitivity -gt 1 ]]
then
showdiff=1
else
showdiff=0
fi
if [[ $condiff -ne 0 ]]
then
c=${bold}C${reset}
if [[ $sensitivity -gt 0 ]]
then
showdiff=1
fi
fi
if [[ $numdiff -ne 0 ]]
then
f=${bold}F${reset}
showdiff=1
printf "%03d/${total}:[${bold}%04d${reset}] [${f}${c}] ${bold}${color4}'%s'${reset}\n" $cnt $numdiff "$subj"
else
printf "%03d/$total:[----] [${f}${c}] '%s'\n" $cnt "$subj"
fi
if [[ $showdiff -eq 1 ]]
then
if [[ $diffprog == "meld" ]]
then
label="--label=\"Patch #$cnt: $subj\" --label=\" \""
fi
subjlist[$cnt]=$subj
exe[$cnt]="${label} <(git show $uphash^!) <(git show $downhash^!) 2>/dev/null"
shortexe[$cnt]="<(git show ${uphash:0:7}^\!) <(git show ${downhash:0:7}^\!)"
fi
else
printf "%03d/$total:[${bold}${color1}down${reset}] ${bold}${color4}'%s'${reset}\n" $cnt "$subj"
fi
done < <(git log --pretty=tformat:"%H%s" --reverse $range)
}

show_diff()
{
echo "Do you want to view the diffs using ${bold}${diffprog}${reset}? y/[n]: "
read -n 1 view
echo ""
if [[ "$view" == "y" ]]
then
for idx in ${!exe[*]}
do
if [[ $pause == 'y' ]]
then
echo "Press [Enter] to view diff(diff) of ${idx}/${total}: ${bold}${color4}${subjlist[$idx]}${reset}"
read
else
echo "Viewing diff(diff) of ${idx}/${total}: ${bold}${color4}${subjlist[$idx]}${reset}"
fi
eval ${diffprog} ${exe[$idx]} || true
done
fi
}

if [[ $upstream_valid != 'y' ]]
then
echo "Upstream $upstream is not valid (does not exist)!"
echo "Do you need to add the remote upstream repo?"
exit 2
fi >&2

compare_git

if [[ $summary != 'y' ]]
then
show_diff
fi

if [[ ${!shortexe[*]} != '' ]]
then
echo ""
echo "To view diffs later, you may run:"
for idx in ${!shortexe[*]}
do
printf "%03d/$total: '${diffprog} ${shortexe[$idx]}'\n" $idx
done
fi

215
redhat/scripts/git-compile-check Executable file
View File

@ -0,0 +1,215 @@
#!/bin/bash
#
# See $desc, below, for program description
#
# Copyright (c) 2013 Red Hat, Inc.
#
# Author(s):
# Jeff Cody <jcody@redhat.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; under version 2 of the license
#
# 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, see <http://www.gnu.org/licenses/gpl-2.0.html>.
#

set -C -u -e
set -o pipefail

desc="
$0 iterates through a git commit range, and performs the
following on each commit:
- git checkout
- make clean
- configure
- make

It will also optionally perform a git-reset and git-clean between
checkouts, if requested via the '-f' option.

The script will exit and report on first error on any of the above steps,
(except no error checking is performed on 'make clean')

NOTE: While executing, the script will checkout out each commit
in the range in the current git tree. On exit, the HEAD
at the time the script was called is checked out"


# default range is the last commit
def_range="HEAD^!"
def_config_opt="--target-list=x86_64-softmmu"
# you may want to have make perform multiple jobs, e.g. -j4
# this is ommitted as the default in case the project makefile
# is not safe for parallel make processes
def_make_opt=""
def_log="output-$$.log"
def_logdir=""
force_clean='n'

logfile=$def_log
range=`git config compile-check.range || true`
config_opt=`git config compile-check.configopt || true`
make_opt=`git config compile-check.makeopt || true`
logdir=`git config compile-check.logdir || true`

if [[ -z "$range" ]]
then
range=$def_range
git config compile-check.range $range || true
fi
if [[ -z "$config_opt" ]]
then
config_opt=$def_config_opt
git config compile-check.configopt $config_opt || true
fi
if [[ -z "$make_opt" ]]
then
make_opt=$def_make_opt
git config compile-check.makeopt $make_opt || true
fi
if [[ -z "$logdir" ]]
then
logdir=$def_logdir
git config compile-check.logdir $logdir || true
fi

usage() {
echo ""
echo "$0 [OPTIONS]"
echo "$desc"
echo ""
echo "OPTIONS:"
echo " -r git range
optional; default is '$range'
"
echo " -c configure options
optional; default is '$config_opt'
"
echo " -m make options
optional; default is '$make_opt'
"
echo " -d log dir
optional; default is '$logdir'
"
echo " -l log filename
optional; default is output-PROCID, where PROCID is the bash process id
note: you may specify a full path for the log filename here, and exclude the
-d option.
"
echo " -f force a git reset and clean
this will cause a 'git reset --hard; git clean -fdx' to be run between checkouts.
!! WARNING: This may cause data loss in your git tree.
READ the git-clean and git-reset man pages and make
sure you understand the implications of
'git clean -fdx' and 'git reset --hard' before using !!
If you specify this option, make sure the logfile falls outside of the tree.
"
echo " -h help"
}

while getopts ":r:c:m:l:d:hf" opt
do
case $opt in
r) range=$OPTARG
;;
c) config_opt=$OPTARG
;;
m) make_opt=$OPTARG
;;
d) logdir=$OPTARG
;;
l) logfile=$OPTARG
;;
f) force_clean='y'
;;
h) usage
exit
;;
\?) echo "Unknown option: -$OPTARG" >&2
usage
exit 1
;;
esac
done

# append a '/' to logdir if $logdir was specified without one
[[ -n "$logdir" ]] && [[ ${logdir:${#logdir}-1} != "/" ]] && logdir="${logdir}/"

logfile="${logdir}${logfile}"

head=`git rev-parse --abbrev-ref=strict HEAD`
if [ HEAD = "$head" ]
then
# we're at a detached head, get hash
head=`git rev-parse HEAD`
fi


total=`git rev-list "$range" |wc -l`

echo "log output: $logfile"

rm -f "$logfile"
date > "$logfile"
echo "git compile check for $range." >> "$logfile"
echo "* configure options='$config_opt'" >> "$logfile"
echo "* make options='$make_opt'" >> "$logfile"
echo "Performing a test compile on $total patches" | tee -a "$logfile"
echo "-------------------------------------------------------------" >> "$logfile"
echo "" | tee -a "$logfile"

clean_repo() {
if [[ $force_clean == 'y' ]]
then
git reset --hard >> "$logfile" 2>&1 || true
git clean -fdx >> "$logfile" 2>&1 || true
fi
}

# we want to cleanup and return the git tree back to the previous head
trap cleanup EXIT

cleanup() {
echo ""
echo -n "Cleaning up..."
clean_repo
git checkout $head > /dev/null 2>&1
echo "done."
}

cnt=1
# don't pipe the git job into read, to avoid subshells
while read hash
do
txt=`git log --pretty=tformat:"%h: %s" $hash^!`
echo "${cnt}/${total}: compiling: $txt" | tee -a "$logfile"
let cnt=$cnt+1;
echo "####################" >> "$logfile"
clean_repo
make clean > /dev/null 2>&1 || true
git checkout $hash >> "$logfile" 2>&1 && \
./configure $config_opt >> "$logfile" 2>&1 && \
make $make_opt >> "$logfile" 2>&1 ||
(
S=$?
# don't complain for SIGINT, SIGTERM, SIGQUIT
if [ $S -ne 130 ] && [ $S -ne 131 ] && [ $S -ne 143 ]
then
echo "" | tee -a "$logfile"
echo "ERROR: commit $hash failed to build!" | tee -a "$logfile"
git show --stat $hash | tee -a "$logfile"
fi
exit 1
)
done < <(git log $range --pretty=tformat:"%H" --reverse)

echo "
All patches in $range compiled successfully!" | tee -a "$logfile"
exit 0

View File

@ -0,0 +1,77 @@
SCRIPTS=$1
shift
NAME=$1
shift
VERSION=$1
shift
RELEASE=$1
shift
DATE=$1
shift
COMMIT=$1
shift
TARBALL=$1
shift
TARURL=$1
shift
SPECNAME=$1
shift
BUILDDIR_NAME=$1
shift
MARKER=$1
shift
LOCALVERSION=$1
shift
RHEV=$1
shift
ZRELEASE=$1

SOURCES=rpmbuild/SOURCES
SRPMDIR=rpmbuild/SRPM
BUILDDIR=${SOURCES}/${BUILDDIR_NAME}
SPEC=rpmbuild/SPECS/${SPECNAME}

# Pre-cleaning
rm -rf .tmp asection psection patchlist

if [ ! -f ${TARBALL} ]; then
wget ${TARURL}
fi
cp ${TARBALL} ${SOURCES}/${TARBALL}

if [ -n "${ZRELEASE}" ]; then
ZRELEASE=.${ZRELEASE}
fi

# Handle patches
git format-patch --first-parent --no-renames -k --no-binary ${MARKER}.. > patchlist
for patchfile in `cat patchlist`; do
${SCRIPTS}/frh.py ${patchfile} > .tmp
if grep -q '^diff --git ' .tmp; then
num=$(echo $patchfile | sed 's/\([0-9]*\).*/\1/')
echo "Patch${num}: ${patchfile}" >> psection
echo "%patch${num} -p1" >> asection
mv .tmp ${SOURCES}/${patchfile}
fi
done

# Handle spec file
cp ${SPECNAME}.template ${SPEC}

sed -i -e "/%%PATCHLIST%%/r psection
/%%PATCHLIST%%/d
/%%PATCHAPPLY%%/r asection
/%%PATCHAPPLY%%/d
s/%%VERSION%%/${VERSION}/
s/%%RELEASE%%/${RELEASE}/
s/%%ZRELEASE%%/${ZRELEASE}/
s/%%DATE%%/${DATE}/
s/%%COMMIT%%/${COMMIT}/
s/%%LOCALVERSION%%/${LOCALVERSION}/
s/%%TARBALL%%/${TARBALL}/
s/%%RHEV%%/${RHEV}/" $SPEC

# Final cleaning
rm -rf `cat patchlist`
rm -rf .tmp asection psection patchlist

View File

@ -0,0 +1,3 @@
#!/bin/sh

sha1sum < $1 | cut -d ' ' -f 1

View File

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

if [ -f /etc/os-release ]
then
. /etc/os-release
else
echo "ERROR: OS name is not provided."
exit 1
fi

if [ "$NAME" = "Arch Linux" ]
then
pacman -Syu --needed --noconfirm bison diffutils flex gcc git libyaml \
make meson pkgconf python python-setuptools-scm swig
elif [ "$NAME" = "Alpine Linux" ]
then
apk add build-base bison flex git yaml yaml-dev python3-dev \
meson py3-setuptools_scm swig
elif [ "$NAME" = "Fedora Linux" ]
then
dnf install -y bison diffutils flex gcc git libyaml libyaml-devel \
make meson python3-devel python3-setuptools swig
elif [ "$NAME" = "Ubuntu" ]
then
apt update
apt install -yq build-essential bison flex git libyaml-dev pkg-config \
meson python3-dev python3-setuptools python3-setuptools-scm swig
else
echo "ERROR: OS name is not provided."
exit 1
fi

View File

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

215
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,71 +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;
}

/**
* Returns true if the given path is an absolute one.
*
* On Windows, it either needs to begin with a forward slash or with a drive
* letter (e.g. "C:").
* On all other operating systems, it must begin with a forward slash to be
* considered an absolute path.
*/
static bool is_absolute_path(const char *path)
{
#ifdef WIN32
return (
path[0] == '/' ||
(((path[0] >= 'A' && path[0] <= 'Z') || (path[0] >= 'a' && path[0] <= 'z')) && path[1] == ':')
);
#else
return (path[0] == '/');
#endif
}

/**
* Try to open a file in a given directory.
@ -123,7 +72,7 @@ static char *try_open(const char *dirname, const char *fname, FILE **fp)
{
char *fullname;

if (!dirname || is_absolute_path(fname))
if (!dirname || fname[0] == '/')
fullname = xstrdup(fname);
else
fullname = join_path(dirname, fname);
@ -180,10 +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;
@ -210,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)
@ -253,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;
@ -266,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++;
}
@ -278,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)
{
@ -343,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)
{
@ -433,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,14 +1,27 @@
/* 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
#define SRCPOS_H
#ifndef _SRCPOS_H_
#define _SRCPOS_H_

#include <stdio.h>
#include <stdbool.h>
#include "util.h"

struct srcfile_state {
FILE *f;
@ -60,7 +73,6 @@ struct srcpos {
int last_line;
int last_column;
struct srcfile_state *file;
struct srcpos *next;
};

#define YYLTYPE struct srcpos
@ -80,25 +92,27 @@ 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);
extern void PRINTF(3, 4) srcpos_error(struct srcpos *pos, const char *prefix,
const char *fmt, ...);
extern void srcpos_verror(struct srcpos *pos, const char *prefix,
const char *fmt, va_list va)
__attribute__((format(printf, 3, 0)));
extern void srcpos_error(struct srcpos *pos, const char *prefix,
const char *fmt, ...)
__attribute__((format(printf, 3, 4)));

extern void srcpos_set_line(char *f, int l);

#endif /* SRCPOS_H */
#endif /* _SRCPOS_H_ */

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,53 +45,43 @@ 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)
check: tests ${TESTS_BIN}
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
checkm: tests ${TESTS_BIN}
cd $(TESTS_PREFIX); ./run_tests.sh -m 2>&1 | tee vglog.$$$$

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

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

/ {
node2 {
chosen {
bootargs = <0xdeadbeef>;
stdout-path = <1>;
};
};
};

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

/ {
gpio: gpio-controller {
#gpio-cells = <3>;
};

node {
nr-gpios = <1>;
foo-gpios = <&gpio>;
bar-gpio = <&gpio 1 2 3>;
};
};

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

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