mirror of
https://github.com/dgibson/dtc.git
synced 2025-10-14 08:47:41 -04:00
Compare commits
No commits in common. "main" and "v1.6.0" have entirely different histories.
129 changed files with 1276 additions and 4321 deletions
52
.cirrus.yml
52
.cirrus.yml
|
@ -1,39 +1,23 @@
|
||||||
# FreeBSD build with multiple versions
|
env:
|
||||||
freebsd_versions_task:
|
CIRRUS_CLONE_DEPTH: 1
|
||||||
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_12_task:
|
||||||
freebsd_meson_versions_task:
|
|
||||||
name: FreeBSD $FREEBSD_VERSION meson build
|
|
||||||
freebsd_instance:
|
freebsd_instance:
|
||||||
image_family: $FREEBSD_IMAGE
|
image: freebsd-12-1-release-amd64
|
||||||
matrix:
|
|
||||||
- env:
|
|
||||||
FREEBSD_VERSION: "13.5"
|
|
||||||
FREEBSD_IMAGE: freebsd-13-5
|
|
||||||
- env:
|
|
||||||
FREEBSD_VERSION: "14.3"
|
|
||||||
FREEBSD_IMAGE: freebsd-14-3
|
|
||||||
install_script:
|
install_script:
|
||||||
- pkg install -y git meson ninja flex bison python3 py312-setuptools swig libyaml pkgconf
|
pkg install -y bison gmake pkgconf
|
||||||
setup_script:
|
|
||||||
- meson setup -D python=enabled -D yaml=enabled build
|
|
||||||
build_script:
|
build_script:
|
||||||
- meson compile -C build
|
gmake
|
||||||
test_script:
|
test_script:
|
||||||
- if ! meson test -C build; then cat build/meson-logs/testlog.txt; false; fi
|
gmake check
|
||||||
|
|
||||||
|
linux_gcc_task:
|
||||||
|
container:
|
||||||
|
image: gcc:latest
|
||||||
|
install_script:
|
||||||
|
- apt-get update
|
||||||
|
- apt-get -y install bison flex
|
||||||
|
build_script:
|
||||||
|
- make
|
||||||
|
test_script:
|
||||||
|
- make check
|
||||||
|
|
135
.clang-format
135
.clang-format
|
@ -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
|
|
||||||
...
|
|
|
@ -28,6 +28,3 @@ indent_size = 4
|
||||||
[meson.build]
|
[meson.build]
|
||||||
indent_style = space
|
indent_style = space
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
|
||||||
[*.lds]
|
|
||||||
indent_style = tab
|
|
||||||
|
|
114
.github/workflows/build.yml
vendored
114
.github/workflows/build.yml
vendored
|
@ -1,114 +0,0 @@
|
||||||
---
|
|
||||||
name: Build test
|
|
||||||
'on':
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
- ci
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
|
|
||||||
# ensure that the workflow is only triggered once per PR, subsequent pushes to the PR will cancel
|
|
||||||
# and restart the workflow. See https://docs.github.com/en/actions/using-jobs/using-concurrency
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-make:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
os: [ "alpine", "archlinux", "fedora", "ubuntu" ]
|
|
||||||
|
|
||||||
container:
|
|
||||||
image: ${{ matrix.os }}
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install Dependencies
|
|
||||||
run: |
|
|
||||||
./scripts/install-deps.sh
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: |
|
|
||||||
make
|
|
||||||
|
|
||||||
- name: Run check
|
|
||||||
run: |
|
|
||||||
make check
|
|
||||||
|
|
||||||
build-meson:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
os: [ "alpine", "archlinux", "fedora", "ubuntu" ]
|
|
||||||
|
|
||||||
container:
|
|
||||||
image: ${{ matrix.os }}
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install Dependencies
|
|
||||||
run: |
|
|
||||||
./scripts/install-deps.sh
|
|
||||||
|
|
||||||
- name: Setup
|
|
||||||
run: meson setup -D python=enabled -D yaml=enabled build
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: meson compile -C build
|
|
||||||
|
|
||||||
- name: Run check
|
|
||||||
run: if ! meson test -C build; then cat build/meson-logs/testlog.txt; false; fi
|
|
||||||
|
|
||||||
build-windows:
|
|
||||||
runs-on: windows-latest
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- { sys: mingw32 }
|
|
||||||
- { sys: mingw64 }
|
|
||||||
- { sys: ucrt64 }
|
|
||||||
- { sys: clang64 }
|
|
||||||
name: ${{ matrix.sys }}
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
shell: msys2 {0}
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Setup MSYS2
|
|
||||||
uses: msys2/setup-msys2@v2
|
|
||||||
with:
|
|
||||||
msystem: ${{matrix.sys}}
|
|
||||||
update: true
|
|
||||||
install: >-
|
|
||||||
git
|
|
||||||
flex
|
|
||||||
bison
|
|
||||||
pacboy: >-
|
|
||||||
toolchain:p
|
|
||||||
meson:p
|
|
||||||
ninja:p
|
|
||||||
libyaml:p
|
|
||||||
swig:p
|
|
||||||
python-setuptools-scm:p
|
|
||||||
|
|
||||||
- name: '🚧 Build'
|
|
||||||
run: |
|
|
||||||
meson setup -Dtools=true -Dtests=false build
|
|
||||||
meson compile -C build
|
|
11
.gitignore
vendored
11
.gitignore
vendored
|
@ -3,13 +3,11 @@
|
||||||
*.a
|
*.a
|
||||||
*.patch
|
*.patch
|
||||||
*.so
|
*.so
|
||||||
*.so.*
|
|
||||||
*~
|
*~
|
||||||
*.bak
|
*.bak
|
||||||
*.tab.[ch]
|
*.tab.[ch]
|
||||||
lex.yy.c
|
lex.yy.c
|
||||||
*.lex.c
|
*.lex.c
|
||||||
.*.swp
|
|
||||||
/dtc
|
/dtc
|
||||||
/fdtdump
|
/fdtdump
|
||||||
/convert-dtsv0
|
/convert-dtsv0
|
||||||
|
@ -19,12 +17,3 @@ lex.yy.c
|
||||||
/fdtoverlay
|
/fdtoverlay
|
||||||
/patches
|
/patches
|
||||||
/.pc
|
/.pc
|
||||||
|
|
||||||
# cscope files
|
|
||||||
cscope.*
|
|
||||||
ncscope.*
|
|
||||||
|
|
||||||
.eggs/
|
|
||||||
build/
|
|
||||||
dist/
|
|
||||||
*.egg-info/
|
|
||||||
|
|
|
@ -1,65 +0,0 @@
|
||||||
stages:
|
|
||||||
- build
|
|
||||||
|
|
||||||
variables:
|
|
||||||
GIT_DEPTH: 1
|
|
||||||
|
|
||||||
workflow:
|
|
||||||
rules:
|
|
||||||
- if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "main"
|
|
||||||
- if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "ci"
|
|
||||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
|
||||||
|
|
||||||
# Linux builds with make
|
|
||||||
.build-make-template: &build-make-template
|
|
||||||
stage: build
|
|
||||||
before_script:
|
|
||||||
- ./scripts/install-deps.sh
|
|
||||||
script:
|
|
||||||
- make
|
|
||||||
- make check
|
|
||||||
interruptible: true
|
|
||||||
|
|
||||||
build-make-alpine:
|
|
||||||
<<: *build-make-template
|
|
||||||
image: alpine:latest
|
|
||||||
|
|
||||||
build-make-archlinux:
|
|
||||||
<<: *build-make-template
|
|
||||||
image: archlinux:latest
|
|
||||||
|
|
||||||
build-make-fedora:
|
|
||||||
<<: *build-make-template
|
|
||||||
image: fedora:latest
|
|
||||||
|
|
||||||
build-make-ubuntu:
|
|
||||||
<<: *build-make-template
|
|
||||||
image: ubuntu:latest
|
|
||||||
|
|
||||||
# Linux builds with meson
|
|
||||||
.build-meson-template: &build-meson-template
|
|
||||||
stage: build
|
|
||||||
before_script:
|
|
||||||
- ./scripts/install-deps.sh
|
|
||||||
script:
|
|
||||||
- meson setup -D python=enabled -D yaml=enabled build
|
|
||||||
- meson compile -C build
|
|
||||||
- if ! meson test -C build; then cat build/meson-logs/testlog.txt; false; fi
|
|
||||||
interruptible: true
|
|
||||||
|
|
||||||
build-meson-alpine:
|
|
||||||
<<: *build-meson-template
|
|
||||||
image: alpine:latest
|
|
||||||
|
|
||||||
build-meson-archlinux:
|
|
||||||
<<: *build-meson-template
|
|
||||||
image: archlinux:latest
|
|
||||||
|
|
||||||
build-meson-fedora:
|
|
||||||
<<: *build-meson-template
|
|
||||||
image: fedora:latest
|
|
||||||
|
|
||||||
build-meson-ubuntu:
|
|
||||||
<<: *build-meson-template
|
|
||||||
image: ubuntu:latest
|
|
||||||
|
|
65
.travis.yml
Normal file
65
.travis.yml
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
language: c
|
||||||
|
|
||||||
|
# Coverity Scan uploads
|
||||||
|
env:
|
||||||
|
global:
|
||||||
|
# COVERITY_SCAN_TOKEN (dgibson/dtc)
|
||||||
|
- secure: "vlHvXe618//IM9LQaKzqsrUbjs7ng0L9UCST4kJbJnFQDXvVe5JiSmJGd4ef7mm0NUv5bMRl2W3xCiu6BYAu/NvU3tMNHoLG+JgCJs0+wLJXbWOwji/NmH7olqgJG+CmpaCMXjARF6+nrTnBYHJL6cYyf4KVoV4B0I/hLUW91+s="
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- swig
|
||||||
|
- python-dev
|
||||||
|
- valgrind
|
||||||
|
- libyaml-0-2
|
||||||
|
coverity_scan:
|
||||||
|
project:
|
||||||
|
name: dtc
|
||||||
|
description: Device Tree Compiler
|
||||||
|
notification_email: david@gibson.dropbear.id.au
|
||||||
|
build_command: make
|
||||||
|
branch_pattern: coverity_scan
|
||||||
|
script:
|
||||||
|
- make
|
||||||
|
- make check && make checkm
|
||||||
|
|
||||||
|
# Check it builds properly without optional packages:
|
||||||
|
# python, valgrind, libyaml
|
||||||
|
- script:
|
||||||
|
- make
|
||||||
|
- make check
|
||||||
|
|
||||||
|
- arch: arm64
|
||||||
|
addons:
|
||||||
|
apt_packages:
|
||||||
|
- swig
|
||||||
|
- python-dev
|
||||||
|
- valgrind
|
||||||
|
- libyaml-0-2
|
||||||
|
script:
|
||||||
|
- make
|
||||||
|
- make check checkm
|
||||||
|
|
||||||
|
- arch: ppc64le
|
||||||
|
addons:
|
||||||
|
apt_packages:
|
||||||
|
- swig
|
||||||
|
- python-dev
|
||||||
|
- libyaml-0-2
|
||||||
|
script:
|
||||||
|
- make
|
||||||
|
- make check
|
||||||
|
|
||||||
|
- arch: s390x
|
||||||
|
addons:
|
||||||
|
apt_packages:
|
||||||
|
- swig
|
||||||
|
- python-dev
|
||||||
|
- valgrind
|
||||||
|
- libyaml-0-2
|
||||||
|
script:
|
||||||
|
- make
|
||||||
|
- make check checkm
|
|
@ -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.
|
|
|
@ -6,7 +6,7 @@ the hardware capabilities. This is insufficient for platforms
|
||||||
that need to dynamically insert Device Tree fragments into the
|
that need to dynamically insert Device Tree fragments into the
|
||||||
live tree.
|
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.
|
modifications made to the Device Tree compiler, which make it possible.
|
||||||
|
|
||||||
1. Simplified Problem Definition
|
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.
|
should result in different Device Tree configuration.
|
||||||
|
|
||||||
We cannot boot with this static tree because due to the configuration of the
|
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:
|
So for the bar peripheral we would have this:
|
||||||
|
|
||||||
|
|
|
@ -43,8 +43,9 @@ The gitweb interface for the upstream repository is:
|
||||||
|
|
||||||
1.1) Submitting Patches
|
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>
|
David Gibson <david@gibson.dropbear.id.au>
|
||||||
|
Jon Loeliger <jdl@jdl.com>
|
||||||
and CCed to <devicetree-compiler@vger.kernel.org>.
|
and CCed to <devicetree-compiler@vger.kernel.org>.
|
||||||
|
|
||||||
2) Description
|
2) Description
|
||||||
|
@ -122,24 +123,12 @@ Options:
|
||||||
Relevant for dtb and asm output only.
|
Relevant for dtb and asm output only.
|
||||||
|
|
||||||
-@
|
-@
|
||||||
Generates a __symbols__ node at the root node. This node contains a
|
Generates a __symbols__ node at the root node of the resulting blob
|
||||||
property for each label. The property's name is the label name and the
|
for any node labels used, and for any local references using phandles
|
||||||
value is the path of the labeled node.
|
it also generates a __local_fixups__ node that tracks them.
|
||||||
|
|
||||||
-L
|
When using the /plugin/ tag all unresolved label references to
|
||||||
Possibly generates a __local_fixups__ and a __fixups__ node at the root node.
|
be tracked in the __fixups__ node, making dynamic resolution possible.
|
||||||
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).
|
|
||||||
|
|
||||||
-A
|
-A
|
||||||
Generate automatically aliases for all node labels. This is similar to
|
Generate automatically aliases for all node labels. This is similar to
|
||||||
|
@ -723,7 +712,7 @@ The syntax of the fdtget command is:
|
||||||
|
|
||||||
where options are:
|
where options are:
|
||||||
|
|
||||||
<type> s=string, i=int, u=unsigned, x=hex, r=raw
|
<type> s=string, i=int, u=unsigned, x=hex
|
||||||
Optional modifier prefix:
|
Optional modifier prefix:
|
||||||
hh or b=byte, h=2 byte, l=4 byte (default)
|
hh or b=byte, h=2 byte, l=4 byte (default)
|
||||||
|
|
||||||
|
|
118
Makefile
118
Makefile
|
@ -3,17 +3,16 @@
|
||||||
# Device Tree Compiler
|
# 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:
|
# 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.
|
# LOCAL_VERSION is likely from command line.
|
||||||
# CONFIG_LOCALVERSION from some future config system.
|
# CONFIG_LOCALVERSION from some future config system.
|
||||||
#
|
#
|
||||||
DTC_VERSION = $(shell cat VERSION.txt)
|
VERSION = 1
|
||||||
|
PATCHLEVEL = 6
|
||||||
|
SUBLEVEL = 0
|
||||||
|
EXTRAVERSION =
|
||||||
LOCAL_VERSION =
|
LOCAL_VERSION =
|
||||||
CONFIG_LOCALVERSION =
|
CONFIG_LOCALVERSION =
|
||||||
|
|
||||||
|
@ -22,20 +21,17 @@ CONFIG_LOCALVERSION =
|
||||||
ASSUME_MASK ?= 0
|
ASSUME_MASK ?= 0
|
||||||
|
|
||||||
CPPFLAGS = -I libfdt -I . -DFDT_ASSUME_MASK=$(ASSUME_MASK)
|
CPPFLAGS = -I libfdt -I . -DFDT_ASSUME_MASK=$(ASSUME_MASK)
|
||||||
WARNINGS = -Wall -Wpointer-arith -Wcast-qual -Wnested-externs -Wsign-compare \
|
WARNINGS = -Wall -Wpointer-arith -Wcast-qual -Wnested-externs \
|
||||||
-Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls -Wshadow \
|
-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)
|
CFLAGS = -g -Os $(SHAREDLIB_CFLAGS) -Werror $(WARNINGS) $(EXTRA_CFLAGS)
|
||||||
|
|
||||||
BISON = bison
|
BISON = bison
|
||||||
LEX = flex
|
LEX = flex
|
||||||
SWIG = swig
|
SWIG = swig
|
||||||
PKG_CONFIG ?= pkg-config
|
PKG_CONFIG ?= pkg-config
|
||||||
|
PYTHON ?= python3
|
||||||
|
|
||||||
INSTALL = install
|
INSTALL = /usr/bin/install
|
||||||
INSTALL_PROGRAM = $(INSTALL)
|
INSTALL_PROGRAM = $(INSTALL)
|
||||||
INSTALL_LIB = $(INSTALL)
|
INSTALL_LIB = $(INSTALL)
|
||||||
INSTALL_DATA = $(INSTALL) -m 644
|
INSTALL_DATA = $(INSTALL) -m 644
|
||||||
|
@ -49,6 +45,8 @@ INCLUDEDIR = $(PREFIX)/include
|
||||||
HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \
|
HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \
|
||||||
sed -e 's/\(cygwin\|msys\).*/\1/')
|
sed -e 's/\(cygwin\|msys\).*/\1/')
|
||||||
|
|
||||||
|
NO_PYTHON ?= 0
|
||||||
|
|
||||||
NO_VALGRIND := $(shell $(PKG_CONFIG) --exists valgrind; echo $$?)
|
NO_VALGRIND := $(shell $(PKG_CONFIG) --exists valgrind; echo $$?)
|
||||||
ifeq ($(NO_VALGRIND),1)
|
ifeq ($(NO_VALGRIND),1)
|
||||||
CPPFLAGS += -DNO_VALGRIND
|
CPPFLAGS += -DNO_VALGRIND
|
||||||
|
@ -56,20 +54,13 @@ else
|
||||||
CFLAGS += $(shell $(PKG_CONFIG) --cflags valgrind)
|
CFLAGS += $(shell $(PKG_CONFIG) --cflags valgrind)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# libyaml before version 0.2.3 expects non-const string parameters. Supporting
|
NO_YAML := $(shell $(PKG_CONFIG) --exists yaml-0.1; echo $$?)
|
||||||
# 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)
|
ifeq ($(NO_YAML),1)
|
||||||
CFLAGS += -DNO_YAML
|
CFLAGS += -DNO_YAML
|
||||||
else
|
else
|
||||||
LDLIBS_dtc += $(shell $(PKG_CONFIG) --libs yaml-0.1)
|
LDLIBS_dtc += $(shell $(PKG_CONFIG) --libs yaml-0.1)
|
||||||
CFLAGS += $(shell $(PKG_CONFIG) --cflags yaml-0.1)
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
HAS_VERSION_SCRIPT := $(shell echo 'int main(){}' | $(CC) -Wl,--version-script=/dev/null -x c - -o /dev/null 2>/dev/null && echo y)
|
|
||||||
|
|
||||||
ifeq ($(HOSTOS),darwin)
|
ifeq ($(HOSTOS),darwin)
|
||||||
SHAREDLIB_EXT = dylib
|
SHAREDLIB_EXT = dylib
|
||||||
SHAREDLIB_CFLAGS = -fPIC
|
SHAREDLIB_CFLAGS = -fPIC
|
||||||
|
@ -77,15 +68,11 @@ SHAREDLIB_LDFLAGS = -fPIC -dynamiclib -Wl,-install_name -Wl,
|
||||||
else ifeq ($(HOSTOS),$(filter $(HOSTOS),msys cygwin))
|
else ifeq ($(HOSTOS),$(filter $(HOSTOS),msys cygwin))
|
||||||
SHAREDLIB_EXT = so
|
SHAREDLIB_EXT = so
|
||||||
SHAREDLIB_CFLAGS =
|
SHAREDLIB_CFLAGS =
|
||||||
SHAREDLIB_LDFLAGS = -shared -Wl,-soname,
|
SHAREDLIB_LDFLAGS = -shared -Wl,--version-script=$(LIBFDT_version) -Wl,-soname,
|
||||||
else
|
else
|
||||||
SHAREDLIB_EXT = so
|
SHAREDLIB_EXT = so
|
||||||
SHAREDLIB_CFLAGS = -fPIC
|
SHAREDLIB_CFLAGS = -fPIC
|
||||||
SHAREDLIB_LDFLAGS = -fPIC -shared -Wl,-soname,
|
SHAREDLIB_LDFLAGS = -fPIC -shared -Wl,--version-script=$(LIBFDT_version) -Wl,-soname,
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(HAS_VERSION_SCRIPT),y)
|
|
||||||
SHAREDLIB_LDFLAGS += -Wl,--version-script=$(LIBFDT_version)
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -110,6 +97,7 @@ endif
|
||||||
# Rules for versioning
|
# Rules for versioning
|
||||||
#
|
#
|
||||||
|
|
||||||
|
DTC_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
|
||||||
VERSION_FILE = version_gen.h
|
VERSION_FILE = version_gen.h
|
||||||
|
|
||||||
CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
|
CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
|
||||||
|
@ -164,8 +152,30 @@ SCRIPTS = dtdiff
|
||||||
|
|
||||||
all: $(BIN) libfdt
|
all: $(BIN) libfdt
|
||||||
|
|
||||||
|
# We need both Python and swig to build/install pylibfdt.
|
||||||
|
# This builds the given make ${target} if those deps are found.
|
||||||
|
check_python_deps = \
|
||||||
|
if $(PKG_CONFIG) --cflags $(PYTHON) >/dev/null 2>&1; then \
|
||||||
|
if which swig >/dev/null 2>&1; then \
|
||||||
|
can_build=yes; \
|
||||||
|
fi; \
|
||||||
|
fi; \
|
||||||
|
if [ "$${can_build}" = "yes" ]; then \
|
||||||
|
$(MAKE) $${target}; \
|
||||||
|
else \
|
||||||
|
echo "\#\# Skipping pylibfdt (install python dev and swig to build)"; \
|
||||||
|
fi ;
|
||||||
|
|
||||||
|
.PHONY: maybe_pylibfdt
|
||||||
|
maybe_pylibfdt: FORCE
|
||||||
|
target=pylibfdt; $(check_python_deps)
|
||||||
|
|
||||||
|
ifeq ($(NO_PYTHON),0)
|
||||||
|
all: maybe_pylibfdt
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
ifneq ($(DEPTARGETS),)
|
ifneq ($(DEPTARGETS),)
|
||||||
ifneq ($(MAKECMDGOALS),libfdt)
|
|
||||||
-include $(DTC_OBJS:%.o=%.d)
|
-include $(DTC_OBJS:%.o=%.d)
|
||||||
-include $(CONVERT_OBJS:%.o=%.d)
|
-include $(CONVERT_OBJS:%.o=%.d)
|
||||||
-include $(FDTDUMP_OBJS:%.o=%.d)
|
-include $(FDTDUMP_OBJS:%.o=%.d)
|
||||||
|
@ -173,7 +183,6 @@ ifneq ($(MAKECMDGOALS),libfdt)
|
||||||
-include $(FDTPUT_OBJS:%.o=%.d)
|
-include $(FDTPUT_OBJS:%.o=%.d)
|
||||||
-include $(FDTOVERLAY_OBJS:%.o=%.d)
|
-include $(FDTOVERLAY_OBJS:%.o=%.d)
|
||||||
endif
|
endif
|
||||||
endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -186,13 +195,6 @@ LIBFDT_lib = $(LIBFDT_dir)/$(LIBFDT_LIB)
|
||||||
LIBFDT_include = $(addprefix $(LIBFDT_dir)/,$(LIBFDT_INCLUDES))
|
LIBFDT_include = $(addprefix $(LIBFDT_dir)/,$(LIBFDT_INCLUDES))
|
||||||
LIBFDT_version = $(addprefix $(LIBFDT_dir)/,$(LIBFDT_VERSION))
|
LIBFDT_version = $(addprefix $(LIBFDT_dir)/,$(LIBFDT_VERSION))
|
||||||
|
|
||||||
ifeq ($(STATIC_BUILD),1)
|
|
||||||
CFLAGS += -static
|
|
||||||
LIBFDT_dep = $(LIBFDT_archive)
|
|
||||||
else
|
|
||||||
LIBFDT_dep = $(LIBFDT_lib)
|
|
||||||
endif
|
|
||||||
|
|
||||||
include $(LIBFDT_dir)/Makefile.libfdt
|
include $(LIBFDT_dir)/Makefile.libfdt
|
||||||
|
|
||||||
.PHONY: libfdt
|
.PHONY: libfdt
|
||||||
|
@ -205,7 +207,6 @@ $(LIBFDT_lib): $(addprefix $(LIBFDT_dir)/,$(LIBFDT_OBJS)) $(LIBFDT_version)
|
||||||
$(CC) $(LDFLAGS) $(SHAREDLIB_LDFLAGS)$(LIBFDT_soname) -o $(LIBFDT_lib) \
|
$(CC) $(LDFLAGS) $(SHAREDLIB_LDFLAGS)$(LIBFDT_soname) -o $(LIBFDT_lib) \
|
||||||
$(addprefix $(LIBFDT_dir)/,$(LIBFDT_OBJS))
|
$(addprefix $(LIBFDT_dir)/,$(LIBFDT_OBJS))
|
||||||
ln -sf $(LIBFDT_LIB) $(LIBFDT_dir)/$(LIBFDT_soname)
|
ln -sf $(LIBFDT_LIB) $(LIBFDT_dir)/$(LIBFDT_soname)
|
||||||
ln -sf $(LIBFDT_soname) $(LIBFDT_dir)/$(LIBFDT_so)
|
|
||||||
|
|
||||||
ifneq ($(DEPTARGETS),)
|
ifneq ($(DEPTARGETS),)
|
||||||
-include $(LIBFDT_OBJS:%.o=$(LIBFDT_dir)/%.d)
|
-include $(LIBFDT_OBJS:%.o=$(LIBFDT_dir)/%.d)
|
||||||
|
@ -222,7 +223,7 @@ install-bin: all $(SCRIPTS)
|
||||||
$(INSTALL_PROGRAM) $(BIN) $(DESTDIR)$(BINDIR)
|
$(INSTALL_PROGRAM) $(BIN) $(DESTDIR)$(BINDIR)
|
||||||
$(INSTALL_SCRIPT) $(SCRIPTS) $(DESTDIR)$(BINDIR)
|
$(INSTALL_SCRIPT) $(SCRIPTS) $(DESTDIR)$(BINDIR)
|
||||||
|
|
||||||
install-lib: libfdt
|
install-lib: all
|
||||||
@$(VECHO) INSTALL-LIB
|
@$(VECHO) INSTALL-LIB
|
||||||
$(INSTALL) -d $(DESTDIR)$(LIBDIR)
|
$(INSTALL) -d $(DESTDIR)$(LIBDIR)
|
||||||
$(INSTALL_LIB) $(LIBFDT_lib) $(DESTDIR)$(LIBDIR)
|
$(INSTALL_LIB) $(LIBFDT_lib) $(DESTDIR)$(LIBDIR)
|
||||||
|
@ -237,6 +238,14 @@ install-includes:
|
||||||
|
|
||||||
install: install-bin install-lib install-includes
|
install: install-bin install-lib install-includes
|
||||||
|
|
||||||
|
.PHONY: maybe_install_pylibfdt
|
||||||
|
maybe_install_pylibfdt: FORCE
|
||||||
|
target=install_pylibfdt; $(check_python_deps)
|
||||||
|
|
||||||
|
ifeq ($(NO_PYTHON),0)
|
||||||
|
install: maybe_install_pylibfdt
|
||||||
|
endif
|
||||||
|
|
||||||
$(VERSION_FILE): Makefile FORCE
|
$(VERSION_FILE): Makefile FORCE
|
||||||
$(call filechk,version)
|
$(call filechk,version)
|
||||||
|
|
||||||
|
@ -249,11 +258,11 @@ convert-dtsv0: $(CONVERT_OBJS)
|
||||||
|
|
||||||
fdtdump: $(FDTDUMP_OBJS)
|
fdtdump: $(FDTDUMP_OBJS)
|
||||||
|
|
||||||
fdtget: $(FDTGET_OBJS) $(LIBFDT_dep)
|
fdtget: $(FDTGET_OBJS) $(LIBFDT_lib)
|
||||||
|
|
||||||
fdtput: $(FDTPUT_OBJS) $(LIBFDT_dep)
|
fdtput: $(FDTPUT_OBJS) $(LIBFDT_lib)
|
||||||
|
|
||||||
fdtoverlay: $(FDTOVERLAY_OBJS) $(LIBFDT_dep)
|
fdtoverlay: $(FDTOVERLAY_OBJS) $(LIBFDT_lib)
|
||||||
|
|
||||||
dist:
|
dist:
|
||||||
git archive --format=tar --prefix=dtc-$(dtc_version)/ HEAD \
|
git archive --format=tar --prefix=dtc-$(dtc_version)/ HEAD \
|
||||||
|
@ -262,6 +271,16 @@ dist:
|
||||||
gzip -9 > ../dtc-$(dtc_version).tar.gz
|
gzip -9 > ../dtc-$(dtc_version).tar.gz
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Rules for pylibfdt
|
||||||
|
#
|
||||||
|
PYLIBFDT_dir = pylibfdt
|
||||||
|
|
||||||
|
include $(PYLIBFDT_dir)/Makefile.pylibfdt
|
||||||
|
|
||||||
|
.PHONY: pylibfdt
|
||||||
|
pylibfdt: $(PYLIBFDT_dir)/_libfdt.so
|
||||||
|
|
||||||
#
|
#
|
||||||
# Release signing and uploading
|
# Release signing and uploading
|
||||||
# This is for maintainer convenience, don't try this at home.
|
# This is for maintainer convenience, don't try this at home.
|
||||||
|
@ -295,18 +314,19 @@ TESTS_BIN += fdtput
|
||||||
TESTS_BIN += fdtget
|
TESTS_BIN += fdtget
|
||||||
TESTS_BIN += fdtdump
|
TESTS_BIN += fdtdump
|
||||||
TESTS_BIN += fdtoverlay
|
TESTS_BIN += fdtoverlay
|
||||||
|
ifeq ($(NO_PYTHON),0)
|
||||||
ifneq ($(MAKECMDGOALS),libfdt)
|
TESTS_PYLIBFDT += maybe_pylibfdt
|
||||||
include tests/Makefile.tests
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
include tests/Makefile.tests
|
||||||
|
|
||||||
#
|
#
|
||||||
# Clean rules
|
# Clean rules
|
||||||
#
|
#
|
||||||
STD_CLEANFILES = *~ *.o *.$(SHAREDLIB_EXT) *.d *.a *.i *.s core a.out vgcore.* \
|
STD_CLEANFILES = *~ *.o *.$(SHAREDLIB_EXT) *.d *.a *.i *.s core a.out vgcore.* \
|
||||||
*.tab.[ch] *.lex.c *.output
|
*.tab.[ch] *.lex.c *.output
|
||||||
|
|
||||||
clean: libfdt_clean tests_clean
|
clean: libfdt_clean pylibfdt_clean tests_clean
|
||||||
@$(VECHO) CLEAN
|
@$(VECHO) CLEAN
|
||||||
rm -f $(STD_CLEANFILES)
|
rm -f $(STD_CLEANFILES)
|
||||||
rm -f $(VERSION_FILE)
|
rm -f $(VERSION_FILE)
|
||||||
|
@ -326,7 +346,7 @@ clean: libfdt_clean tests_clean
|
||||||
|
|
||||||
%.o: %.S
|
%.o: %.S
|
||||||
@$(VECHO) AS $@
|
@$(VECHO) AS $@
|
||||||
$(CC) $(CPPFLAGS) $(AFLAGS) -o $@ -c $<
|
$(CC) $(CPPFLAGS) $(AFLAGS) -D__ASSEMBLY__ -o $@ -c $<
|
||||||
|
|
||||||
%.d: %.c
|
%.d: %.c
|
||||||
@$(VECHO) DEP $<
|
@$(VECHO) DEP $<
|
||||||
|
@ -352,12 +372,8 @@ clean: libfdt_clean tests_clean
|
||||||
@$(VECHO) LEX $@
|
@$(VECHO) LEX $@
|
||||||
$(LEX) -o$@ $<
|
$(LEX) -o$@ $<
|
||||||
|
|
||||||
%.tab.c %.tab.h: %.y
|
%.tab.c %.tab.h %.output: %.y
|
||||||
@$(VECHO) BISON $@
|
@$(VECHO) BISON $@
|
||||||
$(BISON) -b $(basename $(basename $@)) -d $<
|
$(BISON) -b $(basename $(basename $@)) -d $<
|
||||||
|
|
||||||
FORCE:
|
FORCE:
|
||||||
|
|
||||||
ifeq ($(MAKE_RESTARTS),10)
|
|
||||||
$(error "Make re-executed itself $(MAKE_RESTARTS) times. Infinite recursion?")
|
|
||||||
endif
|
|
||||||
|
|
91
README
Normal file
91
README
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
The source tree contains the Device Tree Compiler (dtc) toolchain for
|
||||||
|
working with device tree source and binary files and also libfdt, a
|
||||||
|
utility library for reading and manipulating the binary format.
|
||||||
|
|
||||||
|
DTC and LIBFDT are maintained by:
|
||||||
|
|
||||||
|
David Gibson <david@gibson.dropbear.id.au>
|
||||||
|
Jon Loeliger <jdl@jdl.com>
|
||||||
|
|
||||||
|
|
||||||
|
Python library
|
||||||
|
--------------
|
||||||
|
|
||||||
|
A Python library is also available. To build this you will need to install
|
||||||
|
swig and Python development files. On Debian distributions:
|
||||||
|
|
||||||
|
sudo apt-get install swig python3-dev
|
||||||
|
|
||||||
|
The library provides an Fdt class which you can use like this:
|
||||||
|
|
||||||
|
$ PYTHONPATH=../pylibfdt python3
|
||||||
|
>>> import libfdt
|
||||||
|
>>> fdt = libfdt.Fdt(open('test_tree1.dtb', mode='rb').read())
|
||||||
|
>>> node = fdt.path_offset('/subnode@1')
|
||||||
|
>>> print(node)
|
||||||
|
124
|
||||||
|
>>> prop_offset = fdt.first_property_offset(node)
|
||||||
|
>>> prop = fdt.get_property_by_offset(prop_offset)
|
||||||
|
>>> print('%s=%s' % (prop.name, prop.as_str()))
|
||||||
|
compatible=subnode1
|
||||||
|
>>> node2 = fdt.path_offset('/')
|
||||||
|
>>> print(fdt.getprop(node2, 'compatible').as_str())
|
||||||
|
test_tree1
|
||||||
|
|
||||||
|
You will find tests in tests/pylibfdt_tests.py showing how to use each
|
||||||
|
method. Help is available using the Python help command, e.g.:
|
||||||
|
|
||||||
|
$ cd pylibfdt
|
||||||
|
$ python3 -c "import libfdt; help(libfdt)"
|
||||||
|
|
||||||
|
If you add new features, please check code coverage:
|
||||||
|
|
||||||
|
$ sudo apt-get install python3-coverage
|
||||||
|
$ cd tests
|
||||||
|
# It's just 'coverage' on most other distributions
|
||||||
|
$ python3-coverage run pylibfdt_tests.py
|
||||||
|
$ python3-coverage html
|
||||||
|
# Open 'htmlcov/index.html' in your browser
|
||||||
|
|
||||||
|
|
||||||
|
To install the library via the normal setup.py method, use:
|
||||||
|
|
||||||
|
./pylibfdt/setup.py install [--prefix=/path/to/install_dir]
|
||||||
|
|
||||||
|
If --prefix is not provided, the default prefix is used, typically '/usr'
|
||||||
|
or '/usr/local'. See Python's distutils documentation for details. You can
|
||||||
|
also install via the Makefile if you like, but the above is more common.
|
||||||
|
|
||||||
|
To install both libfdt and pylibfdt you can use:
|
||||||
|
|
||||||
|
make install [SETUP_PREFIX=/path/to/install_dir] \
|
||||||
|
[PREFIX=/path/to/install_dir]
|
||||||
|
|
||||||
|
To disable building the python library, even if swig and Python are available,
|
||||||
|
use:
|
||||||
|
|
||||||
|
make NO_PYTHON=1
|
||||||
|
|
||||||
|
|
||||||
|
More work remains to support all of libfdt, including access to numeric
|
||||||
|
values.
|
||||||
|
|
||||||
|
|
||||||
|
Tests
|
||||||
|
-----
|
||||||
|
|
||||||
|
Test files are kept in the tests/ directory. Use 'make check' to build and run
|
||||||
|
all tests.
|
||||||
|
|
||||||
|
If you want to adjust a test file, be aware that tree_tree1.dts is compiled
|
||||||
|
and checked against a binary tree from assembler macros in trees.S. So
|
||||||
|
if you change that file you must change tree.S also.
|
||||||
|
|
||||||
|
|
||||||
|
Mailing list
|
||||||
|
------------
|
||||||
|
The following list is for discussion about dtc and libfdt implementation
|
||||||
|
mailto:devicetree-compiler@vger.kernel.org
|
||||||
|
|
||||||
|
Core device tree bindings are discussed on the devicetree-spec list:
|
||||||
|
mailto:devicetree-spec@vger.kernel.org
|
|
@ -28,7 +28,7 @@ tools. Allowing libfdt to be used under the terms of the BSD license
|
||||||
makes that it easier for vendors or authors of such software to do so.
|
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
|
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
|
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
|
believe the goal of allowing libfdt to be widely used is more
|
||||||
important than avoiding that. libfdt is quite small, and hardly
|
important than avoiding that. libfdt is quite small, and hardly
|
||||||
|
|
100
README.md
100
README.md
|
@ -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.
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
1.7.2
|
|
356
checks.c
356
checks.c
|
@ -31,7 +31,7 @@ typedef void (*check_fn)(struct check *c, struct dt_info *dti, struct node *node
|
||||||
struct check {
|
struct check {
|
||||||
const char *name;
|
const char *name;
|
||||||
check_fn fn;
|
check_fn fn;
|
||||||
const void *data;
|
void *data;
|
||||||
bool warn, error;
|
bool warn, error;
|
||||||
enum checkstatus status;
|
enum checkstatus status;
|
||||||
bool inprogress;
|
bool inprogress;
|
||||||
|
@ -114,7 +114,6 @@ static inline void PRINTF(5, 6) check_msg(struct check *c, struct dt_info *dti,
|
||||||
}
|
}
|
||||||
|
|
||||||
fputs(str, stderr);
|
fputs(str, stderr);
|
||||||
free(str);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FAIL(c, dti, node, ...) \
|
#define FAIL(c, dti, node, ...) \
|
||||||
|
@ -144,14 +143,6 @@ static void check_nodes_props(struct check *c, struct dt_info *dti, struct node
|
||||||
check_nodes_props(c, dti, child);
|
check_nodes_props(c, dti, child);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_multiple_of(int multiple, int divisor)
|
|
||||||
{
|
|
||||||
if (divisor == 0)
|
|
||||||
return multiple == 0;
|
|
||||||
else
|
|
||||||
return (multiple % divisor) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool run_check(struct check *c, struct dt_info *dti)
|
static bool run_check(struct check *c, struct dt_info *dti)
|
||||||
{
|
{
|
||||||
struct node *dt = dti->dt;
|
struct node *dt = dti->dt;
|
||||||
|
@ -208,7 +199,7 @@ static void check_is_string(struct check *c, struct dt_info *dti,
|
||||||
struct node *node)
|
struct node *node)
|
||||||
{
|
{
|
||||||
struct property *prop;
|
struct property *prop;
|
||||||
const char *propname = c->data;
|
char *propname = c->data;
|
||||||
|
|
||||||
prop = get_property(node, propname);
|
prop = get_property(node, propname);
|
||||||
if (!prop)
|
if (!prop)
|
||||||
|
@ -227,7 +218,7 @@ static void check_is_string_list(struct check *c, struct dt_info *dti,
|
||||||
{
|
{
|
||||||
int rem, l;
|
int rem, l;
|
||||||
struct property *prop;
|
struct property *prop;
|
||||||
const char *propname = c->data;
|
char *propname = c->data;
|
||||||
char *str;
|
char *str;
|
||||||
|
|
||||||
prop = get_property(node, propname);
|
prop = get_property(node, propname);
|
||||||
|
@ -255,7 +246,7 @@ static void check_is_cell(struct check *c, struct dt_info *dti,
|
||||||
struct node *node)
|
struct node *node)
|
||||||
{
|
{
|
||||||
struct property *prop;
|
struct property *prop;
|
||||||
const char *propname = c->data;
|
char *propname = c->data;
|
||||||
|
|
||||||
prop = get_property(node, propname);
|
prop = get_property(node, propname);
|
||||||
if (!prop)
|
if (!prop)
|
||||||
|
@ -306,20 +297,19 @@ ERROR(duplicate_property_names, check_duplicate_property_names, NULL);
|
||||||
#define LOWERCASE "abcdefghijklmnopqrstuvwxyz"
|
#define LOWERCASE "abcdefghijklmnopqrstuvwxyz"
|
||||||
#define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
#define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
#define DIGITS "0123456789"
|
#define DIGITS "0123456789"
|
||||||
#define NODECHARS LOWERCASE UPPERCASE DIGITS ",._+-@"
|
#define PROPNODECHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-"
|
||||||
#define PROPCHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-"
|
|
||||||
#define PROPNODECHARSSTRICT LOWERCASE UPPERCASE DIGITS ",-"
|
#define PROPNODECHARSSTRICT LOWERCASE UPPERCASE DIGITS ",-"
|
||||||
|
|
||||||
static void check_node_name_chars(struct check *c, struct dt_info *dti,
|
static void check_node_name_chars(struct check *c, struct dt_info *dti,
|
||||||
struct node *node)
|
struct node *node)
|
||||||
{
|
{
|
||||||
size_t n = strspn(node->name, c->data);
|
int n = strspn(node->name, c->data);
|
||||||
|
|
||||||
if (n < strlen(node->name))
|
if (n < strlen(node->name))
|
||||||
FAIL(c, dti, node, "Bad character '%c' in node name",
|
FAIL(c, dti, node, "Bad character '%c' in node name",
|
||||||
node->name[n]);
|
node->name[n]);
|
||||||
}
|
}
|
||||||
ERROR(node_name_chars, check_node_name_chars, NODECHARS);
|
ERROR(node_name_chars, check_node_name_chars, PROPNODECHARS "@");
|
||||||
|
|
||||||
static void check_node_name_chars_strict(struct check *c, struct dt_info *dti,
|
static void check_node_name_chars_strict(struct check *c, struct dt_info *dti,
|
||||||
struct node *node)
|
struct node *node)
|
||||||
|
@ -340,20 +330,6 @@ static void check_node_name_format(struct check *c, struct dt_info *dti,
|
||||||
}
|
}
|
||||||
ERROR(node_name_format, check_node_name_format, NULL, &node_name_chars);
|
ERROR(node_name_format, check_node_name_format, NULL, &node_name_chars);
|
||||||
|
|
||||||
static void check_node_name_vs_property_name(struct check *c,
|
|
||||||
struct dt_info *dti,
|
|
||||||
struct node *node)
|
|
||||||
{
|
|
||||||
if (!node->parent)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (get_property(node->parent, node->name)) {
|
|
||||||
FAIL(c, dti, node, "node name and property name conflict");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
WARNING(node_name_vs_property_name, check_node_name_vs_property_name,
|
|
||||||
NULL, &node_name_chars);
|
|
||||||
|
|
||||||
static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti,
|
static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti,
|
||||||
struct node *node)
|
struct node *node)
|
||||||
{
|
{
|
||||||
|
@ -376,7 +352,7 @@ static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti,
|
||||||
FAIL(c, dti, node, "node has a reg or ranges property, but no unit name");
|
FAIL(c, dti, node, "node has a reg or ranges property, but no unit name");
|
||||||
} else {
|
} else {
|
||||||
if (unitname[0])
|
if (unitname[0])
|
||||||
FAIL(c, dti, node, "node has a unit name, but no reg or ranges property");
|
FAIL(c, dti, node, "node has a unit name, but no reg property");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WARNING(unit_address_vs_reg, check_unit_address_vs_reg, NULL);
|
WARNING(unit_address_vs_reg, check_unit_address_vs_reg, NULL);
|
||||||
|
@ -387,14 +363,14 @@ static void check_property_name_chars(struct check *c, struct dt_info *dti,
|
||||||
struct property *prop;
|
struct property *prop;
|
||||||
|
|
||||||
for_each_property(node, prop) {
|
for_each_property(node, prop) {
|
||||||
size_t n = strspn(prop->name, c->data);
|
int n = strspn(prop->name, c->data);
|
||||||
|
|
||||||
if (n < strlen(prop->name))
|
if (n < strlen(prop->name))
|
||||||
FAIL_PROP(c, dti, node, prop, "Bad character '%c' in property name",
|
FAIL_PROP(c, dti, node, prop, "Bad character '%c' in property name",
|
||||||
prop->name[n]);
|
prop->name[n]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ERROR(property_name_chars, check_property_name_chars, PROPCHARS);
|
ERROR(property_name_chars, check_property_name_chars, PROPNODECHARS);
|
||||||
|
|
||||||
static void check_property_name_chars_strict(struct check *c,
|
static void check_property_name_chars_strict(struct check *c,
|
||||||
struct dt_info *dti,
|
struct dt_info *dti,
|
||||||
|
@ -404,7 +380,7 @@ static void check_property_name_chars_strict(struct check *c,
|
||||||
|
|
||||||
for_each_property(node, prop) {
|
for_each_property(node, prop) {
|
||||||
const char *name = prop->name;
|
const char *name = prop->name;
|
||||||
size_t n = strspn(name, c->data);
|
int n = strspn(name, c->data);
|
||||||
|
|
||||||
if (n == strlen(prop->name))
|
if (n == strlen(prop->name))
|
||||||
continue;
|
continue;
|
||||||
|
@ -521,7 +497,7 @@ static cell_t check_phandle_prop(struct check *c, struct dt_info *dti,
|
||||||
|
|
||||||
phandle = propval_cell(prop);
|
phandle = propval_cell(prop);
|
||||||
|
|
||||||
if (!phandle_is_valid(phandle)) {
|
if ((phandle == 0) || (phandle == -1)) {
|
||||||
FAIL_PROP(c, dti, node, prop, "bad value (0x%x) in %s property",
|
FAIL_PROP(c, dti, node, prop, "bad value (0x%x) in %s property",
|
||||||
phandle, prop->name);
|
phandle, prop->name);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -580,7 +556,7 @@ static void check_name_properties(struct check *c, struct dt_info *dti,
|
||||||
if (!prop)
|
if (!prop)
|
||||||
return; /* No name property, that's fine */
|
return; /* No name property, that's fine */
|
||||||
|
|
||||||
if ((prop->val.len != node->basenamelen + 1U)
|
if ((prop->val.len != node->basenamelen+1)
|
||||||
|| (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) {
|
|| (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) {
|
||||||
FAIL(c, dti, node, "\"name\" property is incorrect (\"%s\" instead"
|
FAIL(c, dti, node, "\"name\" property is incorrect (\"%s\" instead"
|
||||||
" of base node name)", prop->val.val);
|
" of base node name)", prop->val.val);
|
||||||
|
@ -681,6 +657,7 @@ ERROR(omit_unused_nodes, fixup_omit_unused_nodes, NULL, &phandle_references, &pa
|
||||||
*/
|
*/
|
||||||
WARNING_IF_NOT_CELL(address_cells_is_cell, "#address-cells");
|
WARNING_IF_NOT_CELL(address_cells_is_cell, "#address-cells");
|
||||||
WARNING_IF_NOT_CELL(size_cells_is_cell, "#size-cells");
|
WARNING_IF_NOT_CELL(size_cells_is_cell, "#size-cells");
|
||||||
|
WARNING_IF_NOT_CELL(interrupt_cells_is_cell, "#interrupt-cells");
|
||||||
|
|
||||||
WARNING_IF_NOT_STRING(device_type_is_string, "device_type");
|
WARNING_IF_NOT_STRING(device_type_is_string, "device_type");
|
||||||
WARNING_IF_NOT_STRING(model_is_string, "model");
|
WARNING_IF_NOT_STRING(model_is_string, "model");
|
||||||
|
@ -695,7 +672,8 @@ static void check_names_is_string_list(struct check *c, struct dt_info *dti,
|
||||||
struct property *prop;
|
struct property *prop;
|
||||||
|
|
||||||
for_each_property(node, prop) {
|
for_each_property(node, prop) {
|
||||||
if (!strends(prop->name, "-names"))
|
const char *s = strrchr(prop->name, '-');
|
||||||
|
if (!s || !streq(s, "-names"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
c->data = prop->name;
|
c->data = prop->name;
|
||||||
|
@ -718,14 +696,11 @@ static void check_alias_paths(struct check *c, struct dt_info *dti,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This check does not work for overlays with external paths */
|
if (!prop->val.val || !get_node_by_path(dti->dt, prop->val.val)) {
|
||||||
if (!(dti->dtsflags & DTSF_PLUGIN) &&
|
|
||||||
(!prop->val.val || !get_node_by_path(dti->dt, prop->val.val))) {
|
|
||||||
FAIL_PROP(c, dti, node, prop, "aliases property is not a valid node (%s)",
|
FAIL_PROP(c, dti, node, prop, "aliases property is not a valid node (%s)",
|
||||||
prop->val.val);
|
prop->val.val);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strspn(prop->name, LOWERCASE DIGITS "-") != strlen(prop->name))
|
if (strspn(prop->name, LOWERCASE DIGITS "-") != strlen(prop->name))
|
||||||
FAIL(c, dti, node, "aliases property name must include only lowercase and '-'");
|
FAIL(c, dti, node, "aliases property name must include only lowercase and '-'");
|
||||||
}
|
}
|
||||||
|
@ -778,7 +753,7 @@ static void check_reg_format(struct check *c, struct dt_info *dti,
|
||||||
size_cells = node_size_cells(node->parent);
|
size_cells = node_size_cells(node->parent);
|
||||||
entrylen = (addr_cells + size_cells) * sizeof(cell_t);
|
entrylen = (addr_cells + size_cells) * sizeof(cell_t);
|
||||||
|
|
||||||
if (!is_multiple_of(prop->val.len, entrylen))
|
if (!entrylen || (prop->val.len % entrylen) != 0)
|
||||||
FAIL_PROP(c, dti, node, prop, "property has invalid length (%d bytes) "
|
FAIL_PROP(c, dti, node, prop, "property has invalid length (%d bytes) "
|
||||||
"(#address-cells == %d, #size-cells == %d)",
|
"(#address-cells == %d, #size-cells == %d)",
|
||||||
prop->val.len, addr_cells, size_cells);
|
prop->val.len, addr_cells, size_cells);
|
||||||
|
@ -819,7 +794,7 @@ static void check_ranges_format(struct check *c, struct dt_info *dti,
|
||||||
"#size-cells (%d) differs from %s (%d)",
|
"#size-cells (%d) differs from %s (%d)",
|
||||||
ranges, c_size_cells, node->parent->fullpath,
|
ranges, c_size_cells, node->parent->fullpath,
|
||||||
p_size_cells);
|
p_size_cells);
|
||||||
} else if (!is_multiple_of(prop->val.len, entrylen)) {
|
} else if ((prop->val.len % entrylen) != 0) {
|
||||||
FAIL_PROP(c, dti, node, prop, "\"%s\" property has invalid length (%d bytes) "
|
FAIL_PROP(c, dti, node, prop, "\"%s\" property has invalid length (%d bytes) "
|
||||||
"(parent #address-cells == %d, child #address-cells == %d, "
|
"(parent #address-cells == %d, child #address-cells == %d, "
|
||||||
"#size-cells == %d)", ranges, prop->val.len,
|
"#size-cells == %d)", ranges, prop->val.len,
|
||||||
|
@ -896,7 +871,7 @@ static void check_pci_device_bus_num(struct check *c, struct dt_info *dti, struc
|
||||||
} else {
|
} else {
|
||||||
cells = (cell_t *)prop->val.val;
|
cells = (cell_t *)prop->val.val;
|
||||||
min_bus = fdt32_to_cpu(cells[0]);
|
min_bus = fdt32_to_cpu(cells[0]);
|
||||||
max_bus = fdt32_to_cpu(cells[1]);
|
max_bus = fdt32_to_cpu(cells[0]);
|
||||||
}
|
}
|
||||||
if ((bus_num < min_bus) || (bus_num > max_bus))
|
if ((bus_num < min_bus) || (bus_num > max_bus))
|
||||||
FAIL_PROP(c, dti, node, prop, "PCI bus number %d out of range, expected (%d - %d)",
|
FAIL_PROP(c, dti, node, prop, "PCI bus number %d out of range, expected (%d - %d)",
|
||||||
|
@ -916,8 +891,10 @@ static void check_pci_device_reg(struct check *c, struct dt_info *dti, struct no
|
||||||
return;
|
return;
|
||||||
|
|
||||||
prop = get_property(node, "reg");
|
prop = get_property(node, "reg");
|
||||||
if (!prop)
|
if (!prop) {
|
||||||
|
FAIL(c, dti, node, "missing PCI reg property");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
cells = (cell_t *)prop->val.val;
|
cells = (cell_t *)prop->val.val;
|
||||||
if (cells[1] || cells[2])
|
if (cells[1] || cells[2])
|
||||||
|
@ -1027,7 +1004,7 @@ static void check_i2c_bus_bridge(struct check *c, struct dt_info *dti, struct no
|
||||||
} else if (strprefixeq(node->name, node->basenamelen, "i2c")) {
|
} else if (strprefixeq(node->name, node->basenamelen, "i2c")) {
|
||||||
struct node *child;
|
struct node *child;
|
||||||
for_each_child(node, child) {
|
for_each_child(node, child) {
|
||||||
if (strprefixeq(child->name, child->basenamelen, "i2c-bus"))
|
if (strprefixeq(child->name, node->basenamelen, "i2c-bus"))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
node->bus = &i2c_bus;
|
node->bus = &i2c_bus;
|
||||||
|
@ -1045,9 +1022,6 @@ static void check_i2c_bus_bridge(struct check *c, struct dt_info *dti, struct no
|
||||||
}
|
}
|
||||||
WARNING(i2c_bus_bridge, check_i2c_bus_bridge, NULL, &addr_size_cells);
|
WARNING(i2c_bus_bridge, check_i2c_bus_bridge, NULL, &addr_size_cells);
|
||||||
|
|
||||||
#define I2C_OWN_SLAVE_ADDRESS (1U << 30)
|
|
||||||
#define I2C_TEN_BIT_ADDRESS (1U << 31)
|
|
||||||
|
|
||||||
static void check_i2c_bus_reg(struct check *c, struct dt_info *dti, struct node *node)
|
static void check_i2c_bus_reg(struct check *c, struct dt_info *dti, struct node *node)
|
||||||
{
|
{
|
||||||
struct property *prop;
|
struct property *prop;
|
||||||
|
@ -1070,8 +1044,6 @@ static void check_i2c_bus_reg(struct check *c, struct dt_info *dti, struct node
|
||||||
}
|
}
|
||||||
|
|
||||||
reg = fdt32_to_cpu(*cells);
|
reg = fdt32_to_cpu(*cells);
|
||||||
/* Ignore I2C_OWN_SLAVE_ADDRESS */
|
|
||||||
reg &= ~I2C_OWN_SLAVE_ADDRESS;
|
|
||||||
snprintf(unit_addr, sizeof(unit_addr), "%x", reg);
|
snprintf(unit_addr, sizeof(unit_addr), "%x", reg);
|
||||||
if (!streq(unitname, unit_addr))
|
if (!streq(unitname, unit_addr))
|
||||||
FAIL(c, dti, node, "I2C bus unit address format error, expected \"%s\"",
|
FAIL(c, dti, node, "I2C bus unit address format error, expected \"%s\"",
|
||||||
|
@ -1079,16 +1051,10 @@ static void check_i2c_bus_reg(struct check *c, struct dt_info *dti, struct node
|
||||||
|
|
||||||
for (len = prop->val.len; len > 0; len -= 4) {
|
for (len = prop->val.len; len > 0; len -= 4) {
|
||||||
reg = fdt32_to_cpu(*(cells++));
|
reg = fdt32_to_cpu(*(cells++));
|
||||||
/* Ignore I2C_OWN_SLAVE_ADDRESS */
|
if (reg > 0x3ff)
|
||||||
reg &= ~I2C_OWN_SLAVE_ADDRESS;
|
|
||||||
|
|
||||||
if (reg & I2C_TEN_BIT_ADDRESS) {
|
|
||||||
if ((reg & ~I2C_TEN_BIT_ADDRESS) > 0x3ff)
|
|
||||||
FAIL_PROP(c, dti, node, prop, "I2C address must be less than 10-bits, got \"0x%x\"",
|
FAIL_PROP(c, dti, node, prop, "I2C address must be less than 10-bits, got \"0x%x\"",
|
||||||
reg);
|
reg);
|
||||||
} else if (reg > 0x7f)
|
|
||||||
FAIL_PROP(c, dti, node, prop, "I2C address must be less than 7-bits, got \"0x%x\". Set I2C_TEN_BIT_ADDRESS for 10 bit addresses or fix the property",
|
|
||||||
reg);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WARNING(i2c_bus_reg, check_i2c_bus_reg, NULL, ®_format, &i2c_bus_bridge);
|
WARNING(i2c_bus_reg, check_i2c_bus_reg, NULL, ®_format, &i2c_bus_bridge);
|
||||||
|
@ -1113,7 +1079,7 @@ static void check_spi_bus_bridge(struct check *c, struct dt_info *dti, struct no
|
||||||
for_each_child(node, child) {
|
for_each_child(node, child) {
|
||||||
struct property *prop;
|
struct property *prop;
|
||||||
for_each_property(child, prop) {
|
for_each_property(child, prop) {
|
||||||
if (strstarts(prop->name, "spi-")) {
|
if (strprefixeq(prop->name, 4, "spi-")) {
|
||||||
node->bus = &spi_bus;
|
node->bus = &spi_bus;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1185,7 +1151,7 @@ static void check_unit_address_format(struct check *c, struct dt_info *dti,
|
||||||
/* skip over 0x for next test */
|
/* skip over 0x for next test */
|
||||||
unitname += 2;
|
unitname += 2;
|
||||||
}
|
}
|
||||||
if (unitname[0] == '0' && isxdigit((unsigned char)unitname[1]))
|
if (unitname[0] == '0' && isxdigit(unitname[1]))
|
||||||
FAIL(c, dti, node, "unit name should not have leading 0s");
|
FAIL(c, dti, node, "unit name should not have leading 0s");
|
||||||
}
|
}
|
||||||
WARNING(unit_address_format, check_unit_address_format, NULL,
|
WARNING(unit_address_format, check_unit_address_format, NULL,
|
||||||
|
@ -1220,27 +1186,24 @@ WARNING(avoid_default_addr_size, check_avoid_default_addr_size, NULL,
|
||||||
static void check_avoid_unnecessary_addr_size(struct check *c, struct dt_info *dti,
|
static void check_avoid_unnecessary_addr_size(struct check *c, struct dt_info *dti,
|
||||||
struct node *node)
|
struct node *node)
|
||||||
{
|
{
|
||||||
|
struct property *prop;
|
||||||
struct node *child;
|
struct node *child;
|
||||||
|
bool has_reg = false;
|
||||||
|
|
||||||
if (!node->parent || node->addr_cells < 0 || node->size_cells < 0)
|
if (!node->parent || node->addr_cells < 0 || node->size_cells < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (get_property(node, "ranges") || get_property(node, "dma-ranges") || !node->children)
|
if (get_property(node, "ranges") || !node->children)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for_each_child(node, child) {
|
for_each_child(node, child) {
|
||||||
/*
|
prop = get_property(child, "reg");
|
||||||
* Even if the child devices' address space is not mapped into
|
if (prop)
|
||||||
* the parent bus (no 'ranges' property on node), children can
|
has_reg = true;
|
||||||
* still have registers on a local bus, or map local addresses
|
|
||||||
* to another subordinate address space. The properties on the
|
|
||||||
* child nodes then make #address-cells/#size-cells necessary:
|
|
||||||
*/
|
|
||||||
if (get_property(child, "reg") || get_property(child, "ranges"))
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FAIL(c, dti, node, "unnecessary #address-cells/#size-cells without \"ranges\", \"dma-ranges\" or child \"reg\" or \"ranges\" property");
|
if (!has_reg)
|
||||||
|
FAIL(c, dti, node, "unnecessary #address-cells/#size-cells without \"ranges\" or child \"reg\" property");
|
||||||
}
|
}
|
||||||
WARNING(avoid_unnecessary_addr_size, check_avoid_unnecessary_addr_size, NULL, &avoid_default_addr_size);
|
WARNING(avoid_unnecessary_addr_size, check_avoid_unnecessary_addr_size, NULL, &avoid_default_addr_size);
|
||||||
|
|
||||||
|
@ -1396,9 +1359,9 @@ static void check_property_phandle_args(struct check *c,
|
||||||
const struct provider *provider)
|
const struct provider *provider)
|
||||||
{
|
{
|
||||||
struct node *root = dti->dt;
|
struct node *root = dti->dt;
|
||||||
unsigned int cell, cellsize = 0;
|
int cell, cellsize = 0;
|
||||||
|
|
||||||
if (!is_multiple_of(prop->val.len, sizeof(cell_t))) {
|
if (prop->val.len % sizeof(cell_t)) {
|
||||||
FAIL_PROP(c, dti, node, prop,
|
FAIL_PROP(c, dti, node, prop,
|
||||||
"property size (%d) is invalid, expected multiple of %zu",
|
"property size (%d) is invalid, expected multiple of %zu",
|
||||||
prop->val.len, sizeof(cell_t));
|
prop->val.len, sizeof(cell_t));
|
||||||
|
@ -1408,15 +1371,14 @@ static void check_property_phandle_args(struct check *c,
|
||||||
for (cell = 0; cell < prop->val.len / sizeof(cell_t); cell += cellsize + 1) {
|
for (cell = 0; cell < prop->val.len / sizeof(cell_t); cell += cellsize + 1) {
|
||||||
struct node *provider_node;
|
struct node *provider_node;
|
||||||
struct property *cellprop;
|
struct property *cellprop;
|
||||||
cell_t phandle;
|
int phandle;
|
||||||
unsigned int expected;
|
|
||||||
|
|
||||||
phandle = propval_cell_n(prop, cell);
|
phandle = propval_cell_n(prop, cell);
|
||||||
/*
|
/*
|
||||||
* Some bindings use a cell value 0 or -1 to skip over optional
|
* Some bindings use a cell value 0 or -1 to skip over optional
|
||||||
* entries when each index position has a specific definition.
|
* entries when each index position has a specific definition.
|
||||||
*/
|
*/
|
||||||
if (!phandle_is_valid(phandle)) {
|
if (phandle == 0 || phandle == -1) {
|
||||||
/* Give up if this is an overlay with external references */
|
/* Give up if this is an overlay with external references */
|
||||||
if (dti->dtsflags & DTSF_PLUGIN)
|
if (dti->dtsflags & DTSF_PLUGIN)
|
||||||
break;
|
break;
|
||||||
|
@ -1459,12 +1421,10 @@ static void check_property_phandle_args(struct check *c,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
expected = (cell + cellsize + 1) * sizeof(cell_t);
|
if (prop->val.len < ((cell + cellsize + 1) * sizeof(cell_t))) {
|
||||||
if ((expected <= cell) || prop->val.len < expected) {
|
|
||||||
FAIL_PROP(c, dti, node, prop,
|
FAIL_PROP(c, dti, node, prop,
|
||||||
"property size (%d) too small for cell size %u",
|
"property size (%d) too small for cell size %d",
|
||||||
prop->val.len, cellsize);
|
prop->val.len, cellsize);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1473,7 +1433,7 @@ static void check_provider_cells_property(struct check *c,
|
||||||
struct dt_info *dti,
|
struct dt_info *dti,
|
||||||
struct node *node)
|
struct node *node)
|
||||||
{
|
{
|
||||||
const struct provider *provider = c->data;
|
struct provider *provider = c->data;
|
||||||
struct property *prop;
|
struct property *prop;
|
||||||
|
|
||||||
prop = get_property(node, provider->prop_name);
|
prop = get_property(node, provider->prop_name);
|
||||||
|
@ -1484,8 +1444,7 @@ static void check_provider_cells_property(struct check *c,
|
||||||
}
|
}
|
||||||
#define WARNING_PROPERTY_PHANDLE_CELLS(nm, propname, cells_name, ...) \
|
#define WARNING_PROPERTY_PHANDLE_CELLS(nm, propname, cells_name, ...) \
|
||||||
static struct provider nm##_provider = { (propname), (cells_name), __VA_ARGS__ }; \
|
static struct provider nm##_provider = { (propname), (cells_name), __VA_ARGS__ }; \
|
||||||
WARNING_IF_NOT_CELL(nm##_is_cell, cells_name); \
|
WARNING(nm##_property, check_provider_cells_property, &nm##_provider, &phandle_references);
|
||||||
WARNING(nm##_property, check_provider_cells_property, &nm##_provider, &nm##_is_cell, &phandle_references);
|
|
||||||
|
|
||||||
WARNING_PROPERTY_PHANDLE_CELLS(clocks, "clocks", "#clock-cells");
|
WARNING_PROPERTY_PHANDLE_CELLS(clocks, "clocks", "#clock-cells");
|
||||||
WARNING_PROPERTY_PHANDLE_CELLS(cooling_device, "cooling-device", "#cooling-cells");
|
WARNING_PROPERTY_PHANDLE_CELLS(cooling_device, "cooling-device", "#cooling-cells");
|
||||||
|
@ -1506,17 +1465,24 @@ WARNING_PROPERTY_PHANDLE_CELLS(thermal_sensors, "thermal-sensors", "#thermal-sen
|
||||||
|
|
||||||
static bool prop_is_gpio(struct property *prop)
|
static bool prop_is_gpio(struct property *prop)
|
||||||
{
|
{
|
||||||
|
char *str;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* *-gpios and *-gpio can appear in property names,
|
* *-gpios and *-gpio can appear in property names,
|
||||||
* so skip over any false matches (only one known ATM)
|
* so skip over any false matches (only one known ATM)
|
||||||
*/
|
*/
|
||||||
if (strends(prop->name, ",nr-gpios"))
|
if (strstr(prop->name, "nr-gpio"))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return strends(prop->name, "-gpios") ||
|
str = strrchr(prop->name, '-');
|
||||||
streq(prop->name, "gpios") ||
|
if (str)
|
||||||
strends(prop->name, "-gpio") ||
|
str++;
|
||||||
streq(prop->name, "gpio");
|
else
|
||||||
|
str = prop->name;
|
||||||
|
if (!(streq(str, "gpios") || streq(str, "gpio")))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void check_gpios_property(struct check *c,
|
static void check_gpios_property(struct check *c,
|
||||||
|
@ -1551,10 +1517,13 @@ static void check_deprecated_gpio_property(struct check *c,
|
||||||
struct property *prop;
|
struct property *prop;
|
||||||
|
|
||||||
for_each_property(node, prop) {
|
for_each_property(node, prop) {
|
||||||
|
char *str;
|
||||||
|
|
||||||
if (!prop_is_gpio(prop))
|
if (!prop_is_gpio(prop))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!strends(prop->name, "gpio"))
|
str = strstr(prop->name, "gpio");
|
||||||
|
if (!streq(str, "gpio"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
FAIL_PROP(c, dti, node, prop,
|
FAIL_PROP(c, dti, node, prop,
|
||||||
|
@ -1578,121 +1547,6 @@ static bool node_is_interrupt_provider(struct node *node)
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void check_interrupt_provider(struct check *c,
|
|
||||||
struct dt_info *dti,
|
|
||||||
struct node *node)
|
|
||||||
{
|
|
||||||
struct property *prop;
|
|
||||||
bool irq_provider = node_is_interrupt_provider(node);
|
|
||||||
|
|
||||||
prop = get_property(node, "#interrupt-cells");
|
|
||||||
if (irq_provider && !prop) {
|
|
||||||
FAIL(c, dti, node,
|
|
||||||
"Missing '#interrupt-cells' in interrupt provider");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!irq_provider && prop) {
|
|
||||||
FAIL(c, dti, node,
|
|
||||||
"'#interrupt-cells' found, but node is not an interrupt provider");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
WARNING(interrupt_provider, check_interrupt_provider, NULL, &interrupts_extended_is_cell);
|
|
||||||
|
|
||||||
static void check_interrupt_map(struct check *c,
|
|
||||||
struct dt_info *dti,
|
|
||||||
struct node *node)
|
|
||||||
{
|
|
||||||
struct node *root = dti->dt;
|
|
||||||
struct property *prop, *irq_map_prop;
|
|
||||||
size_t cellsize, cell, map_cells;
|
|
||||||
|
|
||||||
irq_map_prop = get_property(node, "interrupt-map");
|
|
||||||
if (!irq_map_prop)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (node->addr_cells < 0) {
|
|
||||||
FAIL(c, dti, node,
|
|
||||||
"Missing '#address-cells' in interrupt-map provider");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
cellsize = node_addr_cells(node);
|
|
||||||
cellsize += propval_cell(get_property(node, "#interrupt-cells"));
|
|
||||||
|
|
||||||
prop = get_property(node, "interrupt-map-mask");
|
|
||||||
if (prop && (prop->val.len != (cellsize * sizeof(cell_t))))
|
|
||||||
FAIL_PROP(c, dti, node, prop,
|
|
||||||
"property size (%d) is invalid, expected %zu",
|
|
||||||
prop->val.len, cellsize * sizeof(cell_t));
|
|
||||||
|
|
||||||
if (!is_multiple_of(irq_map_prop->val.len, sizeof(cell_t))) {
|
|
||||||
FAIL_PROP(c, dti, node, irq_map_prop,
|
|
||||||
"property size (%d) is invalid, expected multiple of %zu",
|
|
||||||
irq_map_prop->val.len, sizeof(cell_t));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
map_cells = irq_map_prop->val.len / sizeof(cell_t);
|
|
||||||
for (cell = 0; cell < map_cells; ) {
|
|
||||||
struct node *provider_node;
|
|
||||||
struct property *cellprop;
|
|
||||||
int phandle;
|
|
||||||
size_t parent_cellsize;
|
|
||||||
|
|
||||||
if ((cell + cellsize) >= map_cells) {
|
|
||||||
FAIL_PROP(c, dti, node, irq_map_prop,
|
|
||||||
"property size (%d) too small, expected > %zu",
|
|
||||||
irq_map_prop->val.len, (cell + cellsize) * sizeof(cell_t));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
cell += cellsize;
|
|
||||||
|
|
||||||
phandle = propval_cell_n(irq_map_prop, cell);
|
|
||||||
if (!phandle_is_valid(phandle)) {
|
|
||||||
/* Give up if this is an overlay with external references */
|
|
||||||
if (!(dti->dtsflags & DTSF_PLUGIN))
|
|
||||||
FAIL_PROP(c, dti, node, irq_map_prop,
|
|
||||||
"Cell %zu is not a phandle(%d)",
|
|
||||||
cell, phandle);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
provider_node = get_node_by_phandle(root, phandle);
|
|
||||||
if (!provider_node) {
|
|
||||||
FAIL_PROP(c, dti, node, irq_map_prop,
|
|
||||||
"Could not get phandle(%d) node for (cell %zu)",
|
|
||||||
phandle, cell);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
cellprop = get_property(provider_node, "#interrupt-cells");
|
|
||||||
if (cellprop) {
|
|
||||||
parent_cellsize = propval_cell(cellprop);
|
|
||||||
} else {
|
|
||||||
FAIL(c, dti, node, "Missing property '#interrupt-cells' in node %s or bad phandle (referred from interrupt-map[%zu])",
|
|
||||||
provider_node->fullpath, cell);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
cellprop = get_property(provider_node, "#address-cells");
|
|
||||||
if (cellprop)
|
|
||||||
parent_cellsize += propval_cell(cellprop);
|
|
||||||
else
|
|
||||||
FAIL_PROP(c, dti, node, irq_map_prop,
|
|
||||||
"Missing property '#address-cells' in node %s, using 0 as fallback",
|
|
||||||
provider_node->fullpath);
|
|
||||||
|
|
||||||
cell += 1 + parent_cellsize;
|
|
||||||
if (cell > map_cells)
|
|
||||||
FAIL_PROP(c, dti, node, irq_map_prop,
|
|
||||||
"property size (%d) mismatch, expected %zu",
|
|
||||||
irq_map_prop->val.len, cell * sizeof(cell_t));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
WARNING(interrupt_map, check_interrupt_map, NULL, &phandle_references, &addr_size_cells, &interrupt_provider);
|
|
||||||
|
|
||||||
static void check_interrupts_property(struct check *c,
|
static void check_interrupts_property(struct check *c,
|
||||||
struct dt_info *dti,
|
struct dt_info *dti,
|
||||||
struct node *node)
|
struct node *node)
|
||||||
|
@ -1700,13 +1554,13 @@ static void check_interrupts_property(struct check *c,
|
||||||
struct node *root = dti->dt;
|
struct node *root = dti->dt;
|
||||||
struct node *irq_node = NULL, *parent = node;
|
struct node *irq_node = NULL, *parent = node;
|
||||||
struct property *irq_prop, *prop = NULL;
|
struct property *irq_prop, *prop = NULL;
|
||||||
cell_t irq_cells, phandle;
|
int irq_cells, phandle;
|
||||||
|
|
||||||
irq_prop = get_property(node, "interrupts");
|
irq_prop = get_property(node, "interrupts");
|
||||||
if (!irq_prop)
|
if (!irq_prop)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!is_multiple_of(irq_prop->val.len, sizeof(cell_t)))
|
if (irq_prop->val.len % sizeof(cell_t))
|
||||||
FAIL_PROP(c, dti, node, irq_prop, "size (%d) is invalid, expected multiple of %zu",
|
FAIL_PROP(c, dti, node, irq_prop, "size (%d) is invalid, expected multiple of %zu",
|
||||||
irq_prop->val.len, sizeof(cell_t));
|
irq_prop->val.len, sizeof(cell_t));
|
||||||
|
|
||||||
|
@ -1719,7 +1573,7 @@ static void check_interrupts_property(struct check *c,
|
||||||
prop = get_property(parent, "interrupt-parent");
|
prop = get_property(parent, "interrupt-parent");
|
||||||
if (prop) {
|
if (prop) {
|
||||||
phandle = propval_cell(prop);
|
phandle = propval_cell(prop);
|
||||||
if (!phandle_is_valid(phandle)) {
|
if ((phandle == 0) || (phandle == -1)) {
|
||||||
/* Give up if this is an overlay with
|
/* Give up if this is an overlay with
|
||||||
* external references */
|
* external references */
|
||||||
if (dti->dtsflags & DTSF_PLUGIN)
|
if (dti->dtsflags & DTSF_PLUGIN)
|
||||||
|
@ -1750,12 +1604,12 @@ static void check_interrupts_property(struct check *c,
|
||||||
|
|
||||||
prop = get_property(irq_node, "#interrupt-cells");
|
prop = get_property(irq_node, "#interrupt-cells");
|
||||||
if (!prop) {
|
if (!prop) {
|
||||||
/* We warn about that already in another test. */
|
FAIL(c, dti, irq_node, "Missing #interrupt-cells in interrupt-parent");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
irq_cells = propval_cell(prop);
|
irq_cells = propval_cell(prop);
|
||||||
if (!is_multiple_of(irq_prop->val.len, irq_cells * sizeof(cell_t))) {
|
if (irq_prop->val.len % (irq_cells * sizeof(cell_t))) {
|
||||||
FAIL_PROP(c, dti, node, prop,
|
FAIL_PROP(c, dti, node, prop,
|
||||||
"size is (%d), expected multiple of %d",
|
"size is (%d), expected multiple of %d",
|
||||||
irq_prop->val.len, (int)(irq_cells * sizeof(cell_t)));
|
irq_prop->val.len, (int)(irq_cells * sizeof(cell_t)));
|
||||||
|
@ -1781,11 +1635,6 @@ static void check_graph_nodes(struct check *c, struct dt_info *dti,
|
||||||
get_property(child, "remote-endpoint")))
|
get_property(child, "remote-endpoint")))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* The root node cannot be a port */
|
|
||||||
if (!node->parent) {
|
|
||||||
FAIL(c, dti, node, "root node contains endpoint node '%s', potentially misplaced remote-endpoint property", child->name);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
node->bus = &graph_port_bus;
|
node->bus = &graph_port_bus;
|
||||||
|
|
||||||
/* The parent of 'port' nodes can be either 'ports' or a device */
|
/* The parent of 'port' nodes can be either 'ports' or a device */
|
||||||
|
@ -1799,6 +1648,31 @@ static void check_graph_nodes(struct check *c, struct dt_info *dti,
|
||||||
}
|
}
|
||||||
WARNING(graph_nodes, check_graph_nodes, NULL);
|
WARNING(graph_nodes, check_graph_nodes, NULL);
|
||||||
|
|
||||||
|
static void check_graph_child_address(struct check *c, struct dt_info *dti,
|
||||||
|
struct node *node)
|
||||||
|
{
|
||||||
|
int cnt = 0;
|
||||||
|
struct node *child;
|
||||||
|
|
||||||
|
if (node->bus != &graph_ports_bus && node->bus != &graph_port_bus)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for_each_child(node, child) {
|
||||||
|
struct property *prop = get_property(child, "reg");
|
||||||
|
|
||||||
|
/* No error if we have any non-zero unit address */
|
||||||
|
if (prop && propval_cell(prop) != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cnt == 1 && node->addr_cells != -1)
|
||||||
|
FAIL(c, dti, node, "graph node has single child node '%s', #address-cells/#size-cells are not necessary",
|
||||||
|
node->children->name);
|
||||||
|
}
|
||||||
|
WARNING(graph_child_address, check_graph_child_address, NULL, &graph_nodes);
|
||||||
|
|
||||||
static void check_graph_reg(struct check *c, struct dt_info *dti,
|
static void check_graph_reg(struct check *c, struct dt_info *dti,
|
||||||
struct node *node)
|
struct node *node)
|
||||||
{
|
{
|
||||||
|
@ -1836,21 +1710,17 @@ static void check_graph_port(struct check *c, struct dt_info *dti,
|
||||||
if (node->bus != &graph_port_bus)
|
if (node->bus != &graph_port_bus)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
check_graph_reg(c, dti, node);
|
|
||||||
|
|
||||||
/* skip checks below for overlays */
|
|
||||||
if (dti->dtsflags & DTSF_PLUGIN)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!strprefixeq(node->name, node->basenamelen, "port"))
|
if (!strprefixeq(node->name, node->basenamelen, "port"))
|
||||||
FAIL(c, dti, node, "graph port node name should be 'port'");
|
FAIL(c, dti, node, "graph port node name should be 'port'");
|
||||||
|
|
||||||
|
check_graph_reg(c, dti, node);
|
||||||
}
|
}
|
||||||
WARNING(graph_port, check_graph_port, NULL, &graph_nodes);
|
WARNING(graph_port, check_graph_port, NULL, &graph_nodes);
|
||||||
|
|
||||||
static struct node *get_remote_endpoint(struct check *c, struct dt_info *dti,
|
static struct node *get_remote_endpoint(struct check *c, struct dt_info *dti,
|
||||||
struct node *endpoint)
|
struct node *endpoint)
|
||||||
{
|
{
|
||||||
cell_t phandle;
|
int phandle;
|
||||||
struct node *node;
|
struct node *node;
|
||||||
struct property *prop;
|
struct property *prop;
|
||||||
|
|
||||||
|
@ -1860,7 +1730,7 @@ static struct node *get_remote_endpoint(struct check *c, struct dt_info *dti,
|
||||||
|
|
||||||
phandle = propval_cell(prop);
|
phandle = propval_cell(prop);
|
||||||
/* Give up if this is an overlay with external references */
|
/* Give up if this is an overlay with external references */
|
||||||
if (!phandle_is_valid(phandle))
|
if (phandle == 0 || phandle == -1)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
node = get_node_by_phandle(dti->dt, phandle);
|
node = get_node_by_phandle(dti->dt, phandle);
|
||||||
|
@ -1878,15 +1748,11 @@ static void check_graph_endpoint(struct check *c, struct dt_info *dti,
|
||||||
if (!node->parent || node->parent->bus != &graph_port_bus)
|
if (!node->parent || node->parent->bus != &graph_port_bus)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
check_graph_reg(c, dti, node);
|
|
||||||
|
|
||||||
/* skip checks below for overlays */
|
|
||||||
if (dti->dtsflags & DTSF_PLUGIN)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!strprefixeq(node->name, node->basenamelen, "endpoint"))
|
if (!strprefixeq(node->name, node->basenamelen, "endpoint"))
|
||||||
FAIL(c, dti, node, "graph endpoint node name should be 'endpoint'");
|
FAIL(c, dti, node, "graph endpoint node name should be 'endpoint'");
|
||||||
|
|
||||||
|
check_graph_reg(c, dti, node);
|
||||||
|
|
||||||
remote_node = get_remote_endpoint(c, dti, node);
|
remote_node = get_remote_endpoint(c, dti, node);
|
||||||
if (!remote_node)
|
if (!remote_node)
|
||||||
return;
|
return;
|
||||||
|
@ -1900,7 +1766,7 @@ WARNING(graph_endpoint, check_graph_endpoint, NULL, &graph_nodes);
|
||||||
static struct check *check_table[] = {
|
static struct check *check_table[] = {
|
||||||
&duplicate_node_names, &duplicate_property_names,
|
&duplicate_node_names, &duplicate_property_names,
|
||||||
&node_name_chars, &node_name_format, &property_name_chars,
|
&node_name_chars, &node_name_format, &property_name_chars,
|
||||||
&name_is_string, &name_properties, &node_name_vs_property_name,
|
&name_is_string, &name_properties,
|
||||||
|
|
||||||
&duplicate_label,
|
&duplicate_label,
|
||||||
|
|
||||||
|
@ -1908,7 +1774,7 @@ static struct check *check_table[] = {
|
||||||
&phandle_references, &path_references,
|
&phandle_references, &path_references,
|
||||||
&omit_unused_nodes,
|
&omit_unused_nodes,
|
||||||
|
|
||||||
&address_cells_is_cell, &size_cells_is_cell,
|
&address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell,
|
||||||
&device_type_is_string, &model_is_string, &status_is_string,
|
&device_type_is_string, &model_is_string, &status_is_string,
|
||||||
&label_is_string,
|
&label_is_string,
|
||||||
|
|
||||||
|
@ -1943,47 +1809,29 @@ static struct check *check_table[] = {
|
||||||
&chosen_node_is_root, &chosen_node_bootargs, &chosen_node_stdout_path,
|
&chosen_node_is_root, &chosen_node_bootargs, &chosen_node_stdout_path,
|
||||||
|
|
||||||
&clocks_property,
|
&clocks_property,
|
||||||
&clocks_is_cell,
|
|
||||||
&cooling_device_property,
|
&cooling_device_property,
|
||||||
&cooling_device_is_cell,
|
|
||||||
&dmas_property,
|
&dmas_property,
|
||||||
&dmas_is_cell,
|
|
||||||
&hwlocks_property,
|
&hwlocks_property,
|
||||||
&hwlocks_is_cell,
|
|
||||||
&interrupts_extended_property,
|
&interrupts_extended_property,
|
||||||
&interrupts_extended_is_cell,
|
|
||||||
&io_channels_property,
|
&io_channels_property,
|
||||||
&io_channels_is_cell,
|
|
||||||
&iommus_property,
|
&iommus_property,
|
||||||
&iommus_is_cell,
|
|
||||||
&mboxes_property,
|
&mboxes_property,
|
||||||
&mboxes_is_cell,
|
|
||||||
&msi_parent_property,
|
&msi_parent_property,
|
||||||
&msi_parent_is_cell,
|
|
||||||
&mux_controls_property,
|
&mux_controls_property,
|
||||||
&mux_controls_is_cell,
|
|
||||||
&phys_property,
|
&phys_property,
|
||||||
&phys_is_cell,
|
|
||||||
&power_domains_property,
|
&power_domains_property,
|
||||||
&power_domains_is_cell,
|
|
||||||
&pwms_property,
|
&pwms_property,
|
||||||
&pwms_is_cell,
|
|
||||||
&resets_property,
|
&resets_property,
|
||||||
&resets_is_cell,
|
|
||||||
&sound_dai_property,
|
&sound_dai_property,
|
||||||
&sound_dai_is_cell,
|
|
||||||
&thermal_sensors_property,
|
&thermal_sensors_property,
|
||||||
&thermal_sensors_is_cell,
|
|
||||||
|
|
||||||
&deprecated_gpio_property,
|
&deprecated_gpio_property,
|
||||||
&gpios_property,
|
&gpios_property,
|
||||||
&interrupts_property,
|
&interrupts_property,
|
||||||
&interrupt_provider,
|
|
||||||
&interrupt_map,
|
|
||||||
|
|
||||||
&alias_paths,
|
&alias_paths,
|
||||||
|
|
||||||
&graph_nodes, &graph_port, &graph_endpoint,
|
&graph_nodes, &graph_child_address, &graph_port, &graph_endpoint,
|
||||||
|
|
||||||
&always_fail,
|
&always_fail,
|
||||||
};
|
};
|
||||||
|
@ -2003,7 +1851,7 @@ static void enable_warning_error(struct check *c, bool warn, bool error)
|
||||||
|
|
||||||
static void disable_warning_error(struct check *c, bool warn, bool error)
|
static void disable_warning_error(struct check *c, bool warn, bool error)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
int i;
|
||||||
|
|
||||||
/* Lowering level, also lower it for things this is the prereq
|
/* Lowering level, also lower it for things this is the prereq
|
||||||
* for */
|
* for */
|
||||||
|
@ -2024,7 +1872,7 @@ static void disable_warning_error(struct check *c, bool warn, bool error)
|
||||||
|
|
||||||
void parse_checks_option(bool warn, bool error, const char *arg)
|
void parse_checks_option(bool warn, bool error, const char *arg)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
int i;
|
||||||
const char *name = arg;
|
const char *name = arg;
|
||||||
bool enable = true;
|
bool enable = true;
|
||||||
|
|
||||||
|
@ -2051,7 +1899,7 @@ void parse_checks_option(bool warn, bool error, const char *arg)
|
||||||
|
|
||||||
void process_checks(bool force, struct dt_info *dti)
|
void process_checks(bool force, struct dt_info *dti)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
int i;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(check_table); i++) {
|
for (i = 0; i < ARRAY_SIZE(check_table); i++) {
|
||||||
|
|
|
@ -94,7 +94,7 @@ static const struct {
|
||||||
<INITIAL>[0-9a-fA-F]+ {
|
<INITIAL>[0-9a-fA-F]+ {
|
||||||
unsigned long long val;
|
unsigned long long val;
|
||||||
int obase = 16, width = 0;
|
int obase = 16, width = 0;
|
||||||
unsigned int i;
|
int i;
|
||||||
|
|
||||||
val = strtoull(yytext, NULL, cbase);
|
val = strtoull(yytext, NULL, cbase);
|
||||||
|
|
||||||
|
|
53
data.c
53
data.c
|
@ -21,10 +21,10 @@ void data_free(struct data d)
|
||||||
free(d.val);
|
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;
|
struct data nd;
|
||||||
unsigned int newsize;
|
int newsize;
|
||||||
|
|
||||||
if (xlen == 0)
|
if (xlen == 0)
|
||||||
return d;
|
return d;
|
||||||
|
@ -84,7 +84,7 @@ struct data data_copy_file(FILE *f, size_t maxlen)
|
||||||
while (!feof(f) && (d.len < maxlen)) {
|
while (!feof(f) && (d.len < maxlen)) {
|
||||||
size_t chunksize, ret;
|
size_t chunksize, ret;
|
||||||
|
|
||||||
if (maxlen == (size_t)-1)
|
if (maxlen == -1)
|
||||||
chunksize = 4096;
|
chunksize = 4096;
|
||||||
else
|
else
|
||||||
chunksize = maxlen - d.len;
|
chunksize = maxlen - d.len;
|
||||||
|
@ -228,7 +228,11 @@ struct data data_add_marker(struct data d, enum markertype type, char *ref)
|
||||||
{
|
{
|
||||||
struct marker *m;
|
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);
|
return data_append_markers(d, m);
|
||||||
}
|
}
|
||||||
|
@ -250,44 +254,3 @@ bool data_is_one_string(struct data d)
|
||||||
|
|
||||||
return true;
|
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;
|
|
||||||
}
|
|
||||||
|
|
19
dtc-lexer.l
19
dtc-lexer.l
|
@ -57,7 +57,7 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
|
||||||
push_input_file(name);
|
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;
|
char *line, *fnstart, *fnend;
|
||||||
struct data fn;
|
struct data fn;
|
||||||
/* skip text before line # */
|
/* skip text before line # */
|
||||||
|
@ -151,21 +151,6 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
|
||||||
return DT_LABEL;
|
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)? {
|
<V1>([0-9]+|0[xX][0-9a-fA-F]+)(U|L|UL|LL|ULL)? {
|
||||||
char *e;
|
char *e;
|
||||||
DPRINT("Integer Literal: '%s'\n", yytext);
|
DPRINT("Integer Literal: '%s'\n", yytext);
|
||||||
|
@ -215,7 +200,7 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
|
||||||
return DT_LABEL_REF;
|
return DT_LABEL_REF;
|
||||||
}
|
}
|
||||||
|
|
||||||
<*>"&{"{PATHCHAR}*\} { /* new-style path reference */
|
<*>"&{/"{PATHCHAR}*\} { /* new-style path reference */
|
||||||
yytext[yyleng-1] = '\0';
|
yytext[yyleng-1] = '\0';
|
||||||
DPRINT("Ref: %s\n", yytext+2);
|
DPRINT("Ref: %s\n", yytext+2);
|
||||||
yylval.labelref = xstrdup(yytext+2);
|
yylval.labelref = xstrdup(yytext+2);
|
||||||
|
|
33
dtc-parser.y
33
dtc-parser.y
|
@ -23,12 +23,6 @@ extern void yyerror(char const *s);
|
||||||
|
|
||||||
extern struct dt_info *parser_output;
|
extern struct dt_info *parser_output;
|
||||||
extern bool treesource_error;
|
extern bool treesource_error;
|
||||||
|
|
||||||
static bool is_ref_relative(const char *ref)
|
|
||||||
{
|
|
||||||
return ref[0] != '/' && strchr(&ref[1], '/');
|
|
||||||
}
|
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%union {
|
%union {
|
||||||
|
@ -175,8 +169,6 @@ devicetree:
|
||||||
*/
|
*/
|
||||||
if (!($<flags>-1 & DTSF_PLUGIN))
|
if (!($<flags>-1 & DTSF_PLUGIN))
|
||||||
ERROR(&@2, "Label or path %s not found", $1);
|
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(
|
$$ = add_orphan_node(
|
||||||
name_node(build_node(NULL, NULL, NULL),
|
name_node(build_node(NULL, NULL, NULL),
|
||||||
""),
|
""),
|
||||||
|
@ -186,9 +178,6 @@ devicetree:
|
||||||
{
|
{
|
||||||
struct node *target = get_node_by_ref($1, $3);
|
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) {
|
if (target) {
|
||||||
add_label(&target->labels, $2);
|
add_label(&target->labels, $2);
|
||||||
merge_nodes(target, $4);
|
merge_nodes(target, $4);
|
||||||
|
@ -204,8 +193,6 @@ devicetree:
|
||||||
* so $-1 is what we want (plugindecl)
|
* so $-1 is what we want (plugindecl)
|
||||||
*/
|
*/
|
||||||
if ($<flags>-1 & DTSF_PLUGIN) {
|
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);
|
add_orphan_node($1, $3, $2);
|
||||||
} else {
|
} else {
|
||||||
struct node *target = get_node_by_ref($1, $2);
|
struct node *target = get_node_by_ref($1, $2);
|
||||||
|
@ -284,17 +271,14 @@ propdef:
|
||||||
DT_PROPNODENAME '=' propdata ';'
|
DT_PROPNODENAME '=' propdata ';'
|
||||||
{
|
{
|
||||||
$$ = build_property($1, $3, &@$);
|
$$ = build_property($1, $3, &@$);
|
||||||
free($1);
|
|
||||||
}
|
}
|
||||||
| DT_PROPNODENAME ';'
|
| DT_PROPNODENAME ';'
|
||||||
{
|
{
|
||||||
$$ = build_property($1, empty_data, &@$);
|
$$ = build_property($1, empty_data, &@$);
|
||||||
free($1);
|
|
||||||
}
|
}
|
||||||
| DT_DEL_PROP DT_PROPNODENAME ';'
|
| DT_DEL_PROP DT_PROPNODENAME ';'
|
||||||
{
|
{
|
||||||
$$ = build_property_delete($2);
|
$$ = build_property_delete($2);
|
||||||
free($2);
|
|
||||||
}
|
}
|
||||||
| DT_LABEL propdef
|
| DT_LABEL propdef
|
||||||
{
|
{
|
||||||
|
@ -407,14 +391,9 @@ arrayprefix:
|
||||||
* within the mask to one (i.e. | in the
|
* within the mask to one (i.e. | in the
|
||||||
* mask), all bits are one.
|
* mask), all bits are one.
|
||||||
*/
|
*/
|
||||||
if (($2 > mask) && (($2 | mask) != -1ULL)) {
|
if (($2 > mask) && (($2 | mask) != -1ULL))
|
||||||
char *loc = srcpos_string(&@2);
|
ERROR(&@2, "Value out of range for"
|
||||||
fprintf(stderr,
|
" %d-bit array element", $1.bits);
|
||||||
"WARNING: %s: Value 0x%016" PRIx64
|
|
||||||
" truncated to 0x%0*" PRIx64 "\n",
|
|
||||||
loc, $2, $1.bits / 4, ($2 & mask));
|
|
||||||
free(loc);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$$.data = data_append_integer($1.data, $2, $1.bits);
|
$$.data = data_append_integer($1.data, $2, $1.bits);
|
||||||
|
@ -497,8 +476,8 @@ integer_rela:
|
||||||
;
|
;
|
||||||
|
|
||||||
integer_shift:
|
integer_shift:
|
||||||
integer_shift DT_LSHIFT integer_add { $$ = ($3 < 64) ? ($1 << $3) : 0; }
|
integer_shift DT_LSHIFT integer_add { $$ = $1 << $3; }
|
||||||
| integer_shift DT_RSHIFT integer_add { $$ = ($3 < 64) ? ($1 >> $3) : 0; }
|
| integer_shift DT_RSHIFT integer_add { $$ = $1 >> $3; }
|
||||||
| integer_add
|
| integer_add
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -573,12 +552,10 @@ subnode:
|
||||||
DT_PROPNODENAME nodedef
|
DT_PROPNODENAME nodedef
|
||||||
{
|
{
|
||||||
$$ = name_node($2, $1);
|
$$ = name_node($2, $1);
|
||||||
free($1);
|
|
||||||
}
|
}
|
||||||
| DT_DEL_NODE DT_PROPNODENAME ';'
|
| DT_DEL_NODE DT_PROPNODENAME ';'
|
||||||
{
|
{
|
||||||
$$ = name_node(build_node_delete(&@$), $2);
|
$$ = name_node(build_node_delete(&@$), $2);
|
||||||
free($2);
|
|
||||||
}
|
}
|
||||||
| DT_OMIT_NO_REF subnode
|
| DT_OMIT_NO_REF subnode
|
||||||
{
|
{
|
||||||
|
|
21
dtc.c
21
dtc.c
|
@ -12,10 +12,10 @@
|
||||||
* Command line options
|
* Command line options
|
||||||
*/
|
*/
|
||||||
int quiet; /* Level of quietness */
|
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 minsize; /* Minimum blob size */
|
||||||
int padsize; /* Additional padding to blob */
|
int padsize; /* Additional padding to blob */
|
||||||
int alignsize; /* Additional padding to blob according to the alignsize */
|
int alignsize; /* Additional padding to blob accroding to the alignsize */
|
||||||
int phandle_format = PHANDLE_EPAPR; /* Use linux,phandle or phandle properties */
|
int phandle_format = PHANDLE_EPAPR; /* Use linux,phandle or phandle properties */
|
||||||
int generate_symbols; /* enable symbols & fixup support */
|
int generate_symbols; /* enable symbols & fixup support */
|
||||||
int generate_fixups; /* suppress generation of fixups on symbol support */
|
int generate_fixups; /* suppress generation of fixups on symbol support */
|
||||||
|
@ -47,7 +47,7 @@ static void fill_fullpaths(struct node *tree, const char *prefix)
|
||||||
|
|
||||||
/* Usage related data. */
|
/* Usage related data. */
|
||||||
static const char usage_synopsis[] = "dtc [options] <input file>";
|
static const char usage_synopsis[] = "dtc [options] <input file>";
|
||||||
static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@LAThv";
|
static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@AThv";
|
||||||
static struct option const usage_long_opts[] = {
|
static struct option const usage_long_opts[] = {
|
||||||
{"quiet", no_argument, NULL, 'q'},
|
{"quiet", no_argument, NULL, 'q'},
|
||||||
{"in-format", a_argument, NULL, 'I'},
|
{"in-format", a_argument, NULL, 'I'},
|
||||||
|
@ -67,7 +67,6 @@ static struct option const usage_long_opts[] = {
|
||||||
{"warning", a_argument, NULL, 'W'},
|
{"warning", a_argument, NULL, 'W'},
|
||||||
{"error", a_argument, NULL, 'E'},
|
{"error", a_argument, NULL, 'E'},
|
||||||
{"symbols", no_argument, NULL, '@'},
|
{"symbols", no_argument, NULL, '@'},
|
||||||
{"local-fixups", no_argument, NULL, 'L'},
|
|
||||||
{"auto-alias", no_argument, NULL, 'A'},
|
{"auto-alias", no_argument, NULL, 'A'},
|
||||||
{"annotate", no_argument, NULL, 'T'},
|
{"annotate", no_argument, NULL, 'T'},
|
||||||
{"help", no_argument, NULL, 'h'},
|
{"help", no_argument, NULL, 'h'},
|
||||||
|
@ -105,7 +104,6 @@ static const char * const usage_opts_help[] = {
|
||||||
"\n\tEnable/disable warnings (prefix with \"no-\")",
|
"\n\tEnable/disable warnings (prefix with \"no-\")",
|
||||||
"\n\tEnable/disable errors (prefix with \"no-\")",
|
"\n\tEnable/disable errors (prefix with \"no-\")",
|
||||||
"\n\tEnable generation of symbols",
|
"\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\tEnable auto-alias of labels",
|
||||||
"\n\tAnnotate output .dts with input source file and line (-T -T for more details)",
|
"\n\tAnnotate output .dts with input source file and line (-T -T for more details)",
|
||||||
"\n\tPrint this help and exit",
|
"\n\tPrint this help and exit",
|
||||||
|
@ -124,8 +122,6 @@ static const char *guess_type_by_name(const char *fname, const char *fallback)
|
||||||
return "dts";
|
return "dts";
|
||||||
if (!strcasecmp(s, ".yaml"))
|
if (!strcasecmp(s, ".yaml"))
|
||||||
return "yaml";
|
return "yaml";
|
||||||
if (!strcasecmp(s, ".dtbo"))
|
|
||||||
return "dtb";
|
|
||||||
if (!strcasecmp(s, ".dtb"))
|
if (!strcasecmp(s, ".dtb"))
|
||||||
return "dtb";
|
return "dtb";
|
||||||
return fallback;
|
return fallback;
|
||||||
|
@ -199,7 +195,7 @@ int main(int argc, char *argv[])
|
||||||
depname = optarg;
|
depname = optarg;
|
||||||
break;
|
break;
|
||||||
case 'R':
|
case 'R':
|
||||||
reservenum = strtoul(optarg, NULL, 0);
|
reservenum = strtol(optarg, NULL, 0);
|
||||||
break;
|
break;
|
||||||
case 'S':
|
case 'S':
|
||||||
minsize = strtol(optarg, NULL, 0);
|
minsize = strtol(optarg, NULL, 0);
|
||||||
|
@ -254,11 +250,6 @@ int main(int argc, char *argv[])
|
||||||
case '@':
|
case '@':
|
||||||
generate_symbols = 1;
|
generate_symbols = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'L':
|
|
||||||
generate_fixups = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'A':
|
case 'A':
|
||||||
auto_label_aliases = 1;
|
auto_label_aliases = 1;
|
||||||
break;
|
break;
|
||||||
|
@ -289,9 +280,7 @@ int main(int argc, char *argv[])
|
||||||
if (!depfile)
|
if (!depfile)
|
||||||
die("Couldn't open dependency file %s: %s\n", depname,
|
die("Couldn't open dependency file %s: %s\n", depname,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
|
fprintf(depfile, "%s:", outname);
|
||||||
fprint_path_escaped(depfile, outname);
|
|
||||||
fputc(':', depfile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inform == NULL)
|
if (inform == NULL)
|
||||||
|
|
96
dtc.h
96
dtc.h
|
@ -35,10 +35,10 @@
|
||||||
* Command line options
|
* Command line options
|
||||||
*/
|
*/
|
||||||
extern int quiet; /* Level of quietness */
|
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 minsize; /* Minimum blob size */
|
||||||
extern int padsize; /* Additional padding to blob */
|
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 phandle_format; /* Use linux,phandle or phandle properties */
|
||||||
extern int generate_symbols; /* generate symbols for nodes with labels */
|
extern int generate_symbols; /* generate symbols for nodes with labels */
|
||||||
extern int generate_fixups; /* generate fixups */
|
extern int generate_fixups; /* generate fixups */
|
||||||
|
@ -51,56 +51,10 @@ extern int annotate; /* annotate .dts with input source location */
|
||||||
|
|
||||||
typedef uint32_t cell_t;
|
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 streq(a, b) (strcmp((a), (b)) == 0)
|
||||||
#define strstarts(s, prefix) (strncmp((s), (prefix), strlen(prefix)) == 0)
|
#define strstarts(s, prefix) (strncmp((s), (prefix), strlen(prefix)) == 0)
|
||||||
#define strprefixeq(a, n, b) (strlen(b) == (n) && (memcmp(a, b, n) == 0))
|
#define strprefixeq(a, n, b) (strlen(b) == (n) && (memcmp(a, b, n) == 0))
|
||||||
static inline bool strends(const char *str, const char *suffix)
|
|
||||||
{
|
|
||||||
unsigned int len, suffix_len;
|
|
||||||
|
|
||||||
len = strlen(str);
|
|
||||||
suffix_len = strlen(suffix);
|
|
||||||
if (len < suffix_len)
|
|
||||||
return false;
|
|
||||||
return streq(str + len - suffix_len, suffix);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
|
#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
|
||||||
|
|
||||||
|
@ -116,23 +70,17 @@ enum markertype {
|
||||||
TYPE_UINT64,
|
TYPE_UINT64,
|
||||||
TYPE_STRING,
|
TYPE_STRING,
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline bool is_type_marker(enum markertype type)
|
|
||||||
{
|
|
||||||
return type >= TYPE_UINT8;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern const char *markername(enum markertype markertype);
|
extern const char *markername(enum markertype markertype);
|
||||||
|
|
||||||
struct marker {
|
struct marker {
|
||||||
enum markertype type;
|
enum markertype type;
|
||||||
unsigned int offset;
|
int offset;
|
||||||
char *ref;
|
char *ref;
|
||||||
struct marker *next;
|
struct marker *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct data {
|
struct data {
|
||||||
unsigned int len;
|
int len;
|
||||||
char *val;
|
char *val;
|
||||||
struct marker *markers;
|
struct marker *markers;
|
||||||
};
|
};
|
||||||
|
@ -146,26 +94,11 @@ struct data {
|
||||||
for_each_marker(m) \
|
for_each_marker(m) \
|
||||||
if ((m)->type == (t))
|
if ((m)->type == (t))
|
||||||
|
|
||||||
static inline struct marker *next_type_marker(struct marker *m)
|
size_t type_marker_length(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);
|
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_mem(const char *mem, int len);
|
||||||
struct data data_copy_escape_string(const char *s, int len);
|
struct data data_copy_escape_string(const char *s, int len);
|
||||||
|
@ -182,10 +115,7 @@ struct data data_append_addr(struct data d, uint64_t addr);
|
||||||
struct data data_append_byte(struct data d, uint8_t byte);
|
struct data data_append_byte(struct data d, uint8_t byte);
|
||||||
struct data data_append_zeroes(struct data d, int len);
|
struct data data_append_zeroes(struct data d, int len);
|
||||||
struct data data_append_align(struct data d, int align);
|
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);
|
struct data data_add_marker(struct data d, enum markertype type, char *ref);
|
||||||
|
|
||||||
bool data_is_one_string(struct data d);
|
bool data_is_one_string(struct data d);
|
||||||
|
@ -263,16 +193,16 @@ struct node {
|
||||||
void add_label(struct label **labels, char *label);
|
void add_label(struct label **labels, char *label);
|
||||||
void delete_labels(struct label **labels);
|
void delete_labels(struct label **labels);
|
||||||
|
|
||||||
struct property *build_property(const char *name, struct data val,
|
struct property *build_property(char *name, struct data val,
|
||||||
struct srcpos *srcpos);
|
struct srcpos *srcpos);
|
||||||
struct property *build_property_delete(const char *name);
|
struct property *build_property_delete(char *name);
|
||||||
struct property *chain_property(struct property *first, struct property *list);
|
struct property *chain_property(struct property *first, struct property *list);
|
||||||
struct property *reverse_properties(struct property *first);
|
struct property *reverse_properties(struct property *first);
|
||||||
|
|
||||||
struct node *build_node(struct property *proplist, struct node *children,
|
struct node *build_node(struct property *proplist, struct node *children,
|
||||||
struct srcpos *srcpos);
|
struct srcpos *srcpos);
|
||||||
struct node *build_node_delete(struct srcpos *srcpos);
|
struct node *build_node_delete(struct srcpos *srcpos);
|
||||||
struct node *name_node(struct node *node, const char *name);
|
struct node *name_node(struct node *node, char *name);
|
||||||
struct node *omit_node_if_unused(struct node *node);
|
struct node *omit_node_if_unused(struct node *node);
|
||||||
struct node *reference_node(struct node *node);
|
struct node *reference_node(struct node *node);
|
||||||
struct node *chain_node(struct node *first, struct node *list);
|
struct node *chain_node(struct node *first, struct node *list);
|
||||||
|
@ -292,7 +222,7 @@ void append_to_property(struct node *node,
|
||||||
const char *get_unitname(struct node *node);
|
const char *get_unitname(struct node *node);
|
||||||
struct property *get_property(struct node *node, const char *propname);
|
struct property *get_property(struct node *node, const char *propname);
|
||||||
cell_t propval_cell(struct property *prop);
|
cell_t propval_cell(struct property *prop);
|
||||||
cell_t propval_cell_n(struct property *prop, unsigned int n);
|
cell_t propval_cell_n(struct property *prop, int n);
|
||||||
struct property *get_property_by_label(struct node *tree, const char *label,
|
struct property *get_property_by_label(struct node *tree, const char *label,
|
||||||
struct node **node);
|
struct node **node);
|
||||||
struct marker *get_marker_label(struct node *tree, const char *label,
|
struct marker *get_marker_label(struct node *tree, const char *label,
|
||||||
|
@ -339,9 +269,9 @@ struct dt_info *build_dt_info(unsigned int dtsflags,
|
||||||
struct reserve_info *reservelist,
|
struct reserve_info *reservelist,
|
||||||
struct node *tree, uint32_t boot_cpuid_phys);
|
struct node *tree, uint32_t boot_cpuid_phys);
|
||||||
void sort_tree(struct dt_info *dti);
|
void sort_tree(struct dt_info *dti);
|
||||||
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);
|
||||||
void generate_fixups_tree(struct dt_info *dti, const char *name);
|
void generate_fixups_tree(struct dt_info *dti, char *name);
|
||||||
void generate_local_fixups_tree(struct dt_info *dti, const char *name);
|
void generate_local_fixups_tree(struct dt_info *dti, char *name);
|
||||||
|
|
||||||
/* Checks */
|
/* Checks */
|
||||||
|
|
||||||
|
|
2
dtdiff
2
dtdiff
|
@ -17,7 +17,7 @@ source_and_sort () {
|
||||||
*.dts)
|
*.dts)
|
||||||
IFORMAT=dts
|
IFORMAT=dts
|
||||||
;;
|
;;
|
||||||
*.dtb|*.dtbo)
|
*.dtb)
|
||||||
IFORMAT=dtb
|
IFORMAT=dtb
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
10
fdtdump.c
10
fdtdump.c
|
@ -18,10 +18,10 @@
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#define FDT_MAGIC_SIZE 4
|
#define FDT_MAGIC_SIZE 4
|
||||||
#define MAX_VERSION 17U
|
#define MAX_VERSION 17
|
||||||
|
|
||||||
#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
|
#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
|
||||||
#define PALIGN(p, a) ((void *)(ALIGN((uintptr_t)(p), (a))))
|
#define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a))))
|
||||||
#define GET_CELL(p) (p += 4, *((const fdt32_t *)(p-4)))
|
#define GET_CELL(p) (p += 4, *((const fdt32_t *)(p-4)))
|
||||||
|
|
||||||
static const char *tagname(uint32_t tag)
|
static const char *tagname(uint32_t tag)
|
||||||
|
@ -163,7 +163,7 @@ static const char * const usage_opts_help[] = {
|
||||||
USAGE_COMMON_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) ||
|
if (len < sizeof(struct fdt_header) ||
|
||||||
fdt_magic(p) != FDT_MAGIC ||
|
fdt_magic(p) != FDT_MAGIC ||
|
||||||
|
@ -217,7 +217,7 @@ int main(int argc, char *argv[])
|
||||||
char *p = buf;
|
char *p = buf;
|
||||||
char *endp = buf + len;
|
char *endp = buf + len;
|
||||||
|
|
||||||
fdt32_st(smagic, FDT_MAGIC);
|
fdt_set_magic(smagic, FDT_MAGIC);
|
||||||
|
|
||||||
/* poor man's memmem */
|
/* poor man's memmem */
|
||||||
while ((endp - p) >= FDT_MAGIC_SIZE) {
|
while ((endp - p) >= FDT_MAGIC_SIZE) {
|
||||||
|
@ -235,7 +235,7 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
++p;
|
++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);
|
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 %#tx\n", file, p - buf);
|
||||||
buf = p;
|
buf = p;
|
||||||
|
|
15
fdtget.c
15
fdtget.c
|
@ -62,14 +62,8 @@ static int show_cell_list(struct display_info *disp, const char *data, int len,
|
||||||
for (i = 0; i < len; i += size, p += size) {
|
for (i = 0; i < len; i += size, p += size) {
|
||||||
if (i)
|
if (i)
|
||||||
printf(" ");
|
printf(" ");
|
||||||
switch (size) {
|
value = size == 4 ? fdt32_ld((const fdt32_t *)p) :
|
||||||
case 4: value = fdt32_ld((const fdt32_t *)p); break;
|
size == 2 ? (*p << 8) | p[1] : *p;
|
||||||
case 2: value = fdt16_ld((const fdt16_t *)p); break;
|
|
||||||
case 1:
|
|
||||||
default:
|
|
||||||
value = *p;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
printf(fmt, value);
|
printf(fmt, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,11 +91,6 @@ static int show_data(struct display_info *disp, const char *data, int len)
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (disp->type == 'r') {
|
|
||||||
fwrite(data, 1, len, stdout);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
is_string = (disp->type) == 's' ||
|
is_string = (disp->type) == 's' ||
|
||||||
(!disp->type && util_is_printable_string(data, len));
|
(!disp->type && util_is_printable_string(data, len));
|
||||||
if (is_string) {
|
if (is_string) {
|
||||||
|
|
14
fdtoverlay.c
14
fdtoverlay.c
|
@ -23,7 +23,9 @@
|
||||||
/* Usage related data. */
|
/* Usage related data. */
|
||||||
static const char usage_synopsis[] =
|
static const char usage_synopsis[] =
|
||||||
"apply a number of overlays to a base blob\n"
|
"apply a number of overlays to a base blob\n"
|
||||||
" fdtoverlay <options> [<overlay.dtbo> [<overlay.dtbo>]]";
|
" fdtoverlay <options> [<overlay.dtbo> [<overlay.dtbo>]]\n"
|
||||||
|
"\n"
|
||||||
|
USAGE_TYPE_MSG;
|
||||||
static const char usage_short_opts[] = "i:o:v" USAGE_COMMON_SHORT_OPTS;
|
static const char usage_short_opts[] = "i:o:v" USAGE_COMMON_SHORT_OPTS;
|
||||||
static struct option const usage_long_opts[] = {
|
static struct option const usage_long_opts[] = {
|
||||||
{"input", required_argument, NULL, 'i'},
|
{"input", required_argument, NULL, 'i'},
|
||||||
|
@ -46,10 +48,9 @@ static void *apply_one(char *base, const char *overlay, size_t *buf_len,
|
||||||
char *tmp = NULL;
|
char *tmp = NULL;
|
||||||
char *tmpo;
|
char *tmpo;
|
||||||
int ret;
|
int ret;
|
||||||
bool has_symbols;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We take copies first, because a failed apply can trash
|
* We take a copies first, because a a failed apply can trash
|
||||||
* both the base blob and the overlay
|
* both the base blob and the overlay
|
||||||
*/
|
*/
|
||||||
tmpo = xmalloc(fdt_totalsize(overlay));
|
tmpo = xmalloc(fdt_totalsize(overlay));
|
||||||
|
@ -63,8 +64,6 @@ static void *apply_one(char *base, const char *overlay, size_t *buf_len,
|
||||||
fdt_strerror(ret));
|
fdt_strerror(ret));
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
ret = fdt_path_offset(tmp, "/__symbols__");
|
|
||||||
has_symbols = ret >= 0;
|
|
||||||
|
|
||||||
memcpy(tmpo, overlay, fdt_totalsize(overlay));
|
memcpy(tmpo, overlay, fdt_totalsize(overlay));
|
||||||
|
|
||||||
|
@ -77,11 +76,6 @@ static void *apply_one(char *base, const char *overlay, size_t *buf_len,
|
||||||
if (ret) {
|
if (ret) {
|
||||||
fprintf(stderr, "\nFailed to apply '%s': %s\n",
|
fprintf(stderr, "\nFailed to apply '%s': %s\n",
|
||||||
name, fdt_strerror(ret));
|
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;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
40
fdtput.c
40
fdtput.c
|
@ -9,7 +9,6 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include <libfdt.h>
|
#include <libfdt.h>
|
||||||
|
|
||||||
|
@ -65,12 +64,16 @@ static int encode_value(struct display_info *disp, char **arg, int arg_count,
|
||||||
int len; /* length of this cell/string/byte */
|
int len; /* length of this cell/string/byte */
|
||||||
int ival;
|
int ival;
|
||||||
int upto; /* the number of bytes we have written to buf */
|
int upto; /* the number of bytes we have written to buf */
|
||||||
|
char fmt[3];
|
||||||
|
|
||||||
upto = 0;
|
upto = 0;
|
||||||
|
|
||||||
if (disp->verbose)
|
if (disp->verbose)
|
||||||
fprintf(stderr, "Decoding value:\n");
|
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) {
|
for (; arg_count > 0; arg++, arg_count--, upto += len) {
|
||||||
/* assume integer unless told otherwise */
|
/* assume integer unless told otherwise */
|
||||||
if (disp->type == 's')
|
if (disp->type == 's')
|
||||||
|
@ -91,34 +94,7 @@ static int encode_value(struct display_info *disp, char **arg, int arg_count,
|
||||||
fprintf(stderr, "\tstring: '%s'\n", ptr);
|
fprintf(stderr, "\tstring: '%s'\n", ptr);
|
||||||
} else {
|
} else {
|
||||||
fdt32_t *iptr = (fdt32_t *)ptr;
|
fdt32_t *iptr = (fdt32_t *)ptr;
|
||||||
char *endptr;
|
sscanf(*arg, fmt, &ival);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
if (len == 4)
|
if (len == 4)
|
||||||
*iptr = cpu_to_fdt32(ival);
|
*iptr = cpu_to_fdt32(ival);
|
||||||
else
|
else
|
||||||
|
@ -413,8 +389,8 @@ static struct option const usage_long_opts[] = {
|
||||||
USAGE_COMMON_LONG_OPTS,
|
USAGE_COMMON_LONG_OPTS,
|
||||||
};
|
};
|
||||||
static const char * const usage_opts_help[] = {
|
static const char * const usage_opts_help[] = {
|
||||||
"Create nodes",
|
"Create nodes if they don't already exist",
|
||||||
"Delete nodes (and any subnodes)",
|
"Delete nodes (and any subnodes) if they already exist",
|
||||||
"Delete properties if they already exist",
|
"Delete properties if they already exist",
|
||||||
"Automatically create nodes as needed for the node path",
|
"Automatically create nodes as needed for the node path",
|
||||||
"Type of data",
|
"Type of data",
|
||||||
|
@ -457,8 +433,6 @@ int main(int argc, char *argv[])
|
||||||
if (utilfdt_decode_type(optarg, &disp.type,
|
if (utilfdt_decode_type(optarg, &disp.type,
|
||||||
&disp.size))
|
&disp.size))
|
||||||
usage("Invalid type string");
|
usage("Invalid type string");
|
||||||
if (disp.type == 'r')
|
|
||||||
usage("Unsupported raw data type");
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'v':
|
case 'v':
|
||||||
|
|
44
flattree.c
44
flattree.c
|
@ -124,8 +124,7 @@ static void asm_emit_cell(void *e, cell_t val)
|
||||||
{
|
{
|
||||||
FILE *f = e;
|
FILE *f = e;
|
||||||
|
|
||||||
fprintf(f, "\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",
|
||||||
"\t.byte\t0x%02x\n" "\t.byte\t0x%02x\n",
|
|
||||||
(val >> 24) & 0xff, (val >> 16) & 0xff,
|
(val >> 24) & 0xff, (val >> 16) & 0xff,
|
||||||
(val >> 8) & 0xff, val & 0xff);
|
(val >> 8) & 0xff, val & 0xff);
|
||||||
}
|
}
|
||||||
|
@ -135,9 +134,9 @@ static void asm_emit_string(void *e, const char *str, int len)
|
||||||
FILE *f = e;
|
FILE *f = e;
|
||||||
|
|
||||||
if (len != 0)
|
if (len != 0)
|
||||||
fprintf(f, "\t.asciz\t\"%.*s\"\n", len, str);
|
fprintf(f, "\t.string\t\"%.*s\"\n", len, str);
|
||||||
else
|
else
|
||||||
fprintf(f, "\t.asciz\t\"%s\"\n", str);
|
fprintf(f, "\t.string\t\"%s\"\n", str);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void asm_emit_align(void *e, int a)
|
static void asm_emit_align(void *e, int a)
|
||||||
|
@ -150,14 +149,14 @@ static void asm_emit_align(void *e, int a)
|
||||||
static void asm_emit_data(void *e, struct data d)
|
static void asm_emit_data(void *e, struct data d)
|
||||||
{
|
{
|
||||||
FILE *f = e;
|
FILE *f = e;
|
||||||
unsigned int off = 0;
|
int off = 0;
|
||||||
struct marker *m = d.markers;
|
struct marker *m = d.markers;
|
||||||
|
|
||||||
for_each_marker_of_type(m, LABEL)
|
for_each_marker_of_type(m, LABEL)
|
||||||
emit_offset_label(f, m->ref, m->offset);
|
emit_offset_label(f, m->ref, m->offset);
|
||||||
|
|
||||||
while ((d.len - off) >= sizeof(uint32_t)) {
|
while ((d.len - off) >= sizeof(uint32_t)) {
|
||||||
asm_emit_cell(e, dtb_ld32(d.val + off));
|
asm_emit_cell(e, fdt32_to_cpu(*((fdt32_t *)(d.val+off))));
|
||||||
off += sizeof(uint32_t);
|
off += sizeof(uint32_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,7 +219,7 @@ static struct emitter asm_emitter = {
|
||||||
|
|
||||||
static int stringtable_insert(struct data *d, const char *str)
|
static int stringtable_insert(struct data *d, const char *str)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
int i;
|
||||||
|
|
||||||
/* FIXME: do this more efficiently? */
|
/* FIXME: do this more efficiently? */
|
||||||
|
|
||||||
|
@ -296,7 +295,7 @@ static struct data flatten_reserve_list(struct reserve_info *reservelist,
|
||||||
{
|
{
|
||||||
struct reserve_info *re;
|
struct reserve_info *re;
|
||||||
struct data d = empty_data;
|
struct data d = empty_data;
|
||||||
unsigned int j;
|
int j;
|
||||||
|
|
||||||
for (re = reservelist; re; re = re->next) {
|
for (re = reservelist; re; re = re->next) {
|
||||||
d = data_append_re(d, re->address, re->size);
|
d = data_append_re(d, re->address, re->size);
|
||||||
|
@ -346,7 +345,7 @@ static void make_fdt_header(struct fdt_header *fdt,
|
||||||
void dt_to_blob(FILE *f, struct dt_info *dti, int version)
|
void dt_to_blob(FILE *f, struct dt_info *dti, int version)
|
||||||
{
|
{
|
||||||
struct version_info *vi = NULL;
|
struct version_info *vi = NULL;
|
||||||
unsigned int i;
|
int i;
|
||||||
struct data blob = empty_data;
|
struct data blob = empty_data;
|
||||||
struct data reservebuf = empty_data;
|
struct data reservebuf = empty_data;
|
||||||
struct data dtbuf = empty_data;
|
struct data dtbuf = empty_data;
|
||||||
|
@ -439,7 +438,7 @@ static void dump_stringtable_asm(FILE *f, struct data strbuf)
|
||||||
|
|
||||||
while (p < (strbuf.val + strbuf.len)) {
|
while (p < (strbuf.val + strbuf.len)) {
|
||||||
len = strlen(p);
|
len = strlen(p);
|
||||||
fprintf(f, "\t.asciz \"%s\"\n", p);
|
fprintf(f, "\t.string \"%s\"\n", p);
|
||||||
p += len+1;
|
p += len+1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -447,7 +446,7 @@ static void dump_stringtable_asm(FILE *f, struct data strbuf)
|
||||||
void dt_to_asm(FILE *f, struct dt_info *dti, int version)
|
void dt_to_asm(FILE *f, struct dt_info *dti, int version)
|
||||||
{
|
{
|
||||||
struct version_info *vi = NULL;
|
struct version_info *vi = NULL;
|
||||||
unsigned int i;
|
int i;
|
||||||
struct data strbuf = empty_data;
|
struct data strbuf = empty_data;
|
||||||
struct reserve_info *re;
|
struct reserve_info *re;
|
||||||
const char *symprefix = "dt";
|
const char *symprefix = "dt";
|
||||||
|
@ -503,7 +502,7 @@ void dt_to_asm(FILE *f, struct dt_info *dti, int version)
|
||||||
* Reserve map entries.
|
* Reserve map entries.
|
||||||
* Align the reserve map to a doubleword boundary.
|
* Align the reserve map to a doubleword boundary.
|
||||||
* Each entry is an (address, size) pair of u64 values.
|
* 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);
|
asm_emit_align(f, 8);
|
||||||
emit_label(f, symprefix, "reserve_map");
|
emit_label(f, symprefix, "reserve_map");
|
||||||
|
@ -604,11 +603,11 @@ static void flat_realign(struct inbuf *inb, int align)
|
||||||
die("Premature end of data parsing flat device tree\n");
|
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;
|
int len = 0;
|
||||||
const char *p = inb->ptr;
|
const char *p = inb->ptr;
|
||||||
const char *str;
|
char *str;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (p >= inb->limit)
|
if (p >= inb->limit)
|
||||||
|
@ -616,7 +615,7 @@ static const char *flat_read_string(struct inbuf *inb)
|
||||||
len++;
|
len++;
|
||||||
} while ((*p++) != '\0');
|
} while ((*p++) != '\0');
|
||||||
|
|
||||||
str = inb->ptr;
|
str = xstrdup(inb->ptr);
|
||||||
|
|
||||||
inb->ptr += len;
|
inb->ptr += len;
|
||||||
|
|
||||||
|
@ -711,7 +710,7 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const char *nodename_from_path(const char *ppath, const char *cpath)
|
static char *nodename_from_path(const char *ppath, const char *cpath)
|
||||||
{
|
{
|
||||||
int plen;
|
int plen;
|
||||||
|
|
||||||
|
@ -725,7 +724,7 @@ static const char *nodename_from_path(const char *ppath, const char *cpath)
|
||||||
if (!streq(ppath, "/"))
|
if (!streq(ppath, "/"))
|
||||||
plen++;
|
plen++;
|
||||||
|
|
||||||
return cpath + plen;
|
return xstrdup(cpath + plen);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct node *unflatten_tree(struct inbuf *dtbuf,
|
static struct node *unflatten_tree(struct inbuf *dtbuf,
|
||||||
|
@ -733,7 +732,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,
|
||||||
const char *parent_flatname, int flags)
|
const char *parent_flatname, int flags)
|
||||||
{
|
{
|
||||||
struct node *node;
|
struct node *node;
|
||||||
const char *flatname;
|
char *flatname;
|
||||||
uint32_t val;
|
uint32_t val;
|
||||||
|
|
||||||
node = build_node(NULL, NULL, NULL);
|
node = build_node(NULL, NULL, NULL);
|
||||||
|
@ -741,10 +740,9 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,
|
||||||
flatname = flat_read_string(dtbuf);
|
flatname = flat_read_string(dtbuf);
|
||||||
|
|
||||||
if (flags & FTF_FULLPATH)
|
if (flags & FTF_FULLPATH)
|
||||||
node->name = xstrdup(nodename_from_path(parent_flatname,
|
node->name = nodename_from_path(parent_flatname, flatname);
|
||||||
flatname));
|
|
||||||
else
|
else
|
||||||
node->name = xstrdup(flatname);
|
node->name = flatname;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
struct property *prop;
|
struct property *prop;
|
||||||
|
@ -786,6 +784,10 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,
|
||||||
}
|
}
|
||||||
} while (val != FDT_END_NODE);
|
} while (val != FDT_END_NODE);
|
||||||
|
|
||||||
|
if (node->name != flatname) {
|
||||||
|
free(flatname);
|
||||||
|
}
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2
fstree.c
2
fstree.c
|
@ -43,7 +43,7 @@ static struct node *read_fstree(const char *dirname)
|
||||||
"WARNING: Cannot open %s: %s\n",
|
"WARNING: Cannot open %s: %s\n",
|
||||||
tmpname, strerror(errno));
|
tmpname, strerror(errno));
|
||||||
} else {
|
} else {
|
||||||
prop = build_property(de->d_name,
|
prop = build_property(xstrdup(de->d_name),
|
||||||
data_copy_file(pfile,
|
data_copy_file(pfile,
|
||||||
st.st_size),
|
st.st_size),
|
||||||
NULL);
|
NULL);
|
||||||
|
|
|
@ -4,19 +4,15 @@
|
||||||
# This is not a complete Makefile of itself. Instead, it is designed to
|
# This is not a complete Makefile of itself. Instead, it is designed to
|
||||||
# be easily embeddable into other systems of Makefiles.
|
# be easily embeddable into other systems of Makefiles.
|
||||||
#
|
#
|
||||||
|
|
||||||
LIBFDT_so = libfdt.$(SHAREDLIB_EXT)
|
|
||||||
LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1
|
LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1
|
||||||
LIBFDT_INCLUDES = fdt.h libfdt.h libfdt_env.h
|
LIBFDT_INCLUDES = fdt.h libfdt.h libfdt_env.h
|
||||||
LIBFDT_VERSION = version.lds
|
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 \
|
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 fdt_check.c
|
||||||
LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
|
LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
|
||||||
LIBFDT_LIB = libfdt.$(SHAREDLIB_EXT).$(DTC_VERSION)
|
LIBFDT_LIB = libfdt-$(DTC_VERSION).$(SHAREDLIB_EXT)
|
||||||
|
|
||||||
libfdt_clean:
|
libfdt_clean:
|
||||||
@$(VECHO) CLEAN "(libfdt)"
|
@$(VECHO) CLEAN "(libfdt)"
|
||||||
rm -f $(STD_CLEANFILES:%=$(LIBFDT_dir)/%)
|
rm -f $(STD_CLEANFILES:%=$(LIBFDT_dir)/%)
|
||||||
rm -f $(LIBFDT_dir)/$(LIBFDT_so)
|
|
||||||
rm -f $(LIBFDT_dir)/$(LIBFDT_soname)
|
rm -f $(LIBFDT_dir)/$(LIBFDT_soname)
|
||||||
rm -f $(LIBFDT_dir)/$(LIBFDT_LIB)
|
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
- Tree traversal functions
|
- Tree traversal functions
|
||||||
- Graft function
|
- Graft function
|
||||||
|
- Complete libfdt.h documenting comments
|
||||||
|
|
67
libfdt/fdt.c
67
libfdt/fdt.c
|
@ -22,10 +22,6 @@ int32_t fdt_ro_probe_(const void *fdt)
|
||||||
if (can_assume(VALID_DTB))
|
if (can_assume(VALID_DTB))
|
||||||
return totalsize;
|
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) {
|
if (fdt_magic(fdt) == FDT_MAGIC) {
|
||||||
/* Complete tree */
|
/* Complete tree */
|
||||||
if (!can_assume(LATEST)) {
|
if (!can_assume(LATEST)) {
|
||||||
|
@ -90,10 +86,6 @@ int fdt_check_header(const void *fdt)
|
||||||
{
|
{
|
||||||
size_t hdrsize;
|
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)
|
if (fdt_magic(fdt) != FDT_MAGIC)
|
||||||
return -FDT_ERR_BADMAGIC;
|
return -FDT_ERR_BADMAGIC;
|
||||||
if (!can_assume(LATEST)) {
|
if (!can_assume(LATEST)) {
|
||||||
|
@ -106,6 +98,7 @@ int fdt_check_header(const void *fdt)
|
||||||
}
|
}
|
||||||
hdrsize = fdt_header_size(fdt);
|
hdrsize = fdt_header_size(fdt);
|
||||||
if (!can_assume(VALID_DTB)) {
|
if (!can_assume(VALID_DTB)) {
|
||||||
|
|
||||||
if ((fdt_totalsize(fdt) < hdrsize)
|
if ((fdt_totalsize(fdt) < hdrsize)
|
||||||
|| (fdt_totalsize(fdt) > INT_MAX))
|
|| (fdt_totalsize(fdt) > INT_MAX))
|
||||||
return -FDT_ERR_TRUNCATED;
|
return -FDT_ERR_TRUNCATED;
|
||||||
|
@ -114,7 +107,9 @@ int fdt_check_header(const void *fdt)
|
||||||
if (!check_off_(hdrsize, fdt_totalsize(fdt),
|
if (!check_off_(hdrsize, fdt_totalsize(fdt),
|
||||||
fdt_off_mem_rsvmap(fdt)))
|
fdt_off_mem_rsvmap(fdt)))
|
||||||
return -FDT_ERR_TRUNCATED;
|
return -FDT_ERR_TRUNCATED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!can_assume(VALID_DTB)) {
|
||||||
/* Bounds check structure block */
|
/* Bounds check structure block */
|
||||||
if (!can_assume(LATEST) && fdt_version(fdt) < 17) {
|
if (!can_assume(LATEST) && fdt_version(fdt) < 17) {
|
||||||
if (!check_off_(hdrsize, fdt_totalsize(fdt),
|
if (!check_off_(hdrsize, fdt_totalsize(fdt),
|
||||||
|
@ -139,20 +134,16 @@ int fdt_check_header(const void *fdt)
|
||||||
|
|
||||||
const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
|
const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
|
||||||
{
|
{
|
||||||
unsigned int uoffset = offset;
|
unsigned absoffset = offset + fdt_off_dt_struct(fdt);
|
||||||
unsigned int absoffset = offset + fdt_off_dt_struct(fdt);
|
|
||||||
|
|
||||||
if (offset < 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (!can_assume(VALID_INPUT))
|
if (!can_assume(VALID_INPUT))
|
||||||
if ((absoffset < uoffset)
|
if ((absoffset < offset)
|
||||||
|| ((absoffset + len) < absoffset)
|
|| ((absoffset + len) < absoffset)
|
||||||
|| (absoffset + len) > fdt_totalsize(fdt))
|
|| (absoffset + len) > fdt_totalsize(fdt))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (can_assume(LATEST) || fdt_version(fdt) >= 0x11)
|
if (can_assume(LATEST) || fdt_version(fdt) >= 0x11)
|
||||||
if (((uoffset + len) < uoffset)
|
if (((offset + len) < offset)
|
||||||
|| ((offset + len) > fdt_size_dt_struct(fdt)))
|
|| ((offset + len) > fdt_size_dt_struct(fdt)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -162,7 +153,7 @@ const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
|
||||||
uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
|
uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
|
||||||
{
|
{
|
||||||
const fdt32_t *tagp, *lenp;
|
const fdt32_t *tagp, *lenp;
|
||||||
uint32_t tag, len, sum;
|
uint32_t tag;
|
||||||
int offset = startoffset;
|
int offset = startoffset;
|
||||||
const char *p;
|
const char *p;
|
||||||
|
|
||||||
|
@ -188,19 +179,12 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
|
||||||
lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
|
lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
|
||||||
if (!can_assume(VALID_DTB) && !lenp)
|
if (!can_assume(VALID_DTB) && !lenp)
|
||||||
return FDT_END; /* premature end */
|
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 */
|
/* skip-name offset, length and value */
|
||||||
offset += sizeof(struct fdt_property) - FDT_TAGSIZE + len;
|
offset += sizeof(struct fdt_property) - FDT_TAGSIZE
|
||||||
|
+ fdt32_to_cpu(*lenp);
|
||||||
if (!can_assume(LATEST) &&
|
if (!can_assume(LATEST) &&
|
||||||
fdt_version(fdt) < 0x10 && len >= 8 &&
|
fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 &&
|
||||||
((offset - len) % 8) != 0)
|
((offset - fdt32_to_cpu(*lenp)) % 8) != 0)
|
||||||
offset += 4;
|
offset += 4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -222,11 +206,10 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
|
||||||
|
|
||||||
int fdt_check_node_offset_(const void *fdt, int offset)
|
int fdt_check_node_offset_(const void *fdt, int offset)
|
||||||
{
|
{
|
||||||
if (!can_assume(VALID_INPUT)
|
if (can_assume(VALID_INPUT))
|
||||||
&& ((offset < 0) || (offset % FDT_TAGSIZE)))
|
return offset;
|
||||||
return -FDT_ERR_BADOFFSET;
|
if ((offset < 0) || (offset % FDT_TAGSIZE)
|
||||||
|
|| (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE))
|
||||||
if (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE)
|
|
||||||
return -FDT_ERR_BADOFFSET;
|
return -FDT_ERR_BADOFFSET;
|
||||||
|
|
||||||
return offset;
|
return offset;
|
||||||
|
@ -234,11 +217,8 @@ int fdt_check_node_offset_(const void *fdt, int offset)
|
||||||
|
|
||||||
int fdt_check_prop_offset_(const void *fdt, int offset)
|
int fdt_check_prop_offset_(const void *fdt, int offset)
|
||||||
{
|
{
|
||||||
if (!can_assume(VALID_INPUT)
|
if ((offset < 0) || (offset % FDT_TAGSIZE)
|
||||||
&& ((offset < 0) || (offset % FDT_TAGSIZE)))
|
|| (fdt_next_tag(fdt, offset, &offset) != FDT_PROP))
|
||||||
return -FDT_ERR_BADOFFSET;
|
|
||||||
|
|
||||||
if (fdt_next_tag(fdt, offset, &offset) != FDT_PROP)
|
|
||||||
return -FDT_ERR_BADOFFSET;
|
return -FDT_ERR_BADOFFSET;
|
||||||
|
|
||||||
return offset;
|
return offset;
|
||||||
|
@ -312,26 +292,23 @@ int fdt_next_subnode(const void *fdt, int offset)
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *fdt_find_string_len_(const char *strtab, int tabsize, const char *s,
|
const char *fdt_find_string_(const char *strtab, int tabsize, const char *s)
|
||||||
int slen)
|
|
||||||
{
|
{
|
||||||
const char *last = strtab + tabsize - (slen + 1);
|
int len = strlen(s) + 1;
|
||||||
|
const char *last = strtab + tabsize - len;
|
||||||
const char *p;
|
const char *p;
|
||||||
|
|
||||||
for (p = strtab; p <= last; 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 p;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fdt_move(const void *fdt, void *buf, int bufsize)
|
int fdt_move(const void *fdt, void *buf, int bufsize)
|
||||||
{
|
{
|
||||||
if (!can_assume(VALID_INPUT) && bufsize < 0)
|
|
||||||
return -FDT_ERR_NOSPACE;
|
|
||||||
|
|
||||||
FDT_RO_PROBE(fdt);
|
FDT_RO_PROBE(fdt);
|
||||||
|
|
||||||
if (fdt_totalsize(fdt) > (unsigned int)bufsize)
|
if (fdt_totalsize(fdt) > bufsize)
|
||||||
return -FDT_ERR_NOSPACE;
|
return -FDT_ERR_NOSPACE;
|
||||||
|
|
||||||
memmove(buf, fdt, fdt_totalsize(fdt));
|
memmove(buf, fdt, fdt_totalsize(fdt));
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* Copyright 2012 Kim Phillips, Freescale Semiconductor.
|
* Copyright 2012 Kim Phillips, Freescale Semiconductor.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __ASSEMBLER__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
struct fdt_header {
|
struct fdt_header {
|
||||||
fdt32_t magic; /* magic word FDT_MAGIC */
|
fdt32_t magic; /* magic word FDT_MAGIC */
|
||||||
|
@ -35,17 +35,17 @@ struct fdt_reserve_entry {
|
||||||
|
|
||||||
struct fdt_node_header {
|
struct fdt_node_header {
|
||||||
fdt32_t tag;
|
fdt32_t tag;
|
||||||
char name[];
|
char name[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fdt_property {
|
struct fdt_property {
|
||||||
fdt32_t tag;
|
fdt32_t tag;
|
||||||
fdt32_t len;
|
fdt32_t len;
|
||||||
fdt32_t nameoff;
|
fdt32_t nameoff;
|
||||||
char data[];
|
char data[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* !__ASSEMBLER__ */
|
#endif /* !__ASSEMBLY */
|
||||||
|
|
||||||
#define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */
|
#define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */
|
||||||
#define FDT_TAGSIZE sizeof(fdt32_t)
|
#define FDT_TAGSIZE sizeof(fdt32_t)
|
||||||
|
|
|
@ -73,7 +73,7 @@ int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset,
|
||||||
/* check validity of address */
|
/* check validity of address */
|
||||||
prop = data;
|
prop = data;
|
||||||
if (addr_cells == 1) {
|
if (addr_cells == 1) {
|
||||||
if ((addr > UINT32_MAX) || (((uint64_t) UINT32_MAX + 1 - addr) < size))
|
if ((addr > UINT32_MAX) || ((UINT32_MAX + 1 - addr) < size))
|
||||||
return -FDT_ERR_BADVALUE;
|
return -FDT_ERR_BADVALUE;
|
||||||
|
|
||||||
fdt32_st(prop, (uint32_t)addr);
|
fdt32_st(prop, (uint32_t)addr);
|
||||||
|
|
|
@ -19,12 +19,9 @@ int fdt_check_full(const void *fdt, size_t bufsize)
|
||||||
unsigned int depth = 0;
|
unsigned int depth = 0;
|
||||||
const void *prop;
|
const void *prop;
|
||||||
const char *propname;
|
const char *propname;
|
||||||
bool expect_end = false;
|
|
||||||
|
|
||||||
if (bufsize < FDT_V1_SIZE)
|
if (bufsize < FDT_V1_SIZE)
|
||||||
return -FDT_ERR_TRUNCATED;
|
return -FDT_ERR_TRUNCATED;
|
||||||
if (bufsize < fdt_header_size(fdt))
|
|
||||||
return -FDT_ERR_TRUNCATED;
|
|
||||||
err = fdt_check_header(fdt);
|
err = fdt_check_header(fdt);
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
return err;
|
return err;
|
||||||
|
@ -42,10 +39,6 @@ int fdt_check_full(const void *fdt, size_t bufsize)
|
||||||
if (nextoffset < 0)
|
if (nextoffset < 0)
|
||||||
return nextoffset;
|
return nextoffset;
|
||||||
|
|
||||||
/* If we see two root nodes, something is wrong */
|
|
||||||
if (expect_end && tag != FDT_END)
|
|
||||||
return -FDT_ERR_BADSTRUCTURE;
|
|
||||||
|
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case FDT_NOP:
|
case FDT_NOP:
|
||||||
break;
|
break;
|
||||||
|
@ -59,27 +52,12 @@ int fdt_check_full(const void *fdt, size_t bufsize)
|
||||||
depth++;
|
depth++;
|
||||||
if (depth > INT_MAX)
|
if (depth > INT_MAX)
|
||||||
return -FDT_ERR_BADSTRUCTURE;
|
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;
|
break;
|
||||||
|
|
||||||
case FDT_END_NODE:
|
case FDT_END_NODE:
|
||||||
if (depth == 0)
|
if (depth == 0)
|
||||||
return -FDT_ERR_BADSTRUCTURE;
|
return -FDT_ERR_BADSTRUCTURE;
|
||||||
depth--;
|
depth--;
|
||||||
if (depth == 0)
|
|
||||||
expect_end = true;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FDT_PROP:
|
case FDT_PROP:
|
||||||
|
|
|
@ -40,22 +40,37 @@ static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
|
||||||
return fdt32_to_cpu(*val);
|
return fdt32_to_cpu(*val);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fdt_overlay_target_offset(const void *fdt, const void *fdto,
|
/**
|
||||||
int fragment_offset, char const **pathp)
|
* overlay_get_target - retrieves the offset of a fragment's target
|
||||||
|
* @fdt: Base device tree blob
|
||||||
|
* @fdto: Device tree overlay blob
|
||||||
|
* @fragment: node offset of the fragment in the overlay
|
||||||
|
* @pathp: pointer which receives the path of the target (or NULL)
|
||||||
|
*
|
||||||
|
* overlay_get_target() retrieves the target offset in the base
|
||||||
|
* device tree of a fragment, no matter how the actual targeting is
|
||||||
|
* done (through a phandle or a path)
|
||||||
|
*
|
||||||
|
* returns:
|
||||||
|
* the targeted node offset in the base device tree
|
||||||
|
* Negative error code on error
|
||||||
|
*/
|
||||||
|
static int overlay_get_target(const void *fdt, const void *fdto,
|
||||||
|
int fragment, char const **pathp)
|
||||||
{
|
{
|
||||||
uint32_t phandle;
|
uint32_t phandle;
|
||||||
const char *path = NULL;
|
const char *path = NULL;
|
||||||
int path_len = 0, ret;
|
int path_len = 0, ret;
|
||||||
|
|
||||||
/* Try first to do a phandle based lookup */
|
/* 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)
|
if (phandle == (uint32_t)-1)
|
||||||
return -FDT_ERR_BADPHANDLE;
|
return -FDT_ERR_BADPHANDLE;
|
||||||
|
|
||||||
/* no phandle, try path */
|
/* no phandle, try path */
|
||||||
if (!phandle) {
|
if (!phandle) {
|
||||||
/* And then a path based lookup */
|
/* And then a path based lookup */
|
||||||
path = fdt_getprop(fdto, fragment_offset, "target-path", &path_len);
|
path = fdt_getprop(fdto, fragment, "target-path", &path_len);
|
||||||
if (path)
|
if (path)
|
||||||
ret = fdt_path_offset(fdt, path);
|
ret = fdt_path_offset(fdt, path);
|
||||||
else
|
else
|
||||||
|
@ -101,22 +116,26 @@ int fdt_overlay_target_offset(const void *fdt, const void *fdto,
|
||||||
static int overlay_phandle_add_offset(void *fdt, int node,
|
static int overlay_phandle_add_offset(void *fdt, int node,
|
||||||
const char *name, uint32_t delta)
|
const char *name, uint32_t delta)
|
||||||
{
|
{
|
||||||
fdt32_t *valp, val;
|
const fdt32_t *val;
|
||||||
|
uint32_t adj_val;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
valp = fdt_getprop_w(fdt, node, name, &len);
|
val = fdt_getprop(fdt, node, name, &len);
|
||||||
if (!valp)
|
if (!val)
|
||||||
return len;
|
return len;
|
||||||
|
|
||||||
if (len != sizeof(val))
|
if (len != sizeof(*val))
|
||||||
return -FDT_ERR_BADPHANDLE;
|
return -FDT_ERR_BADPHANDLE;
|
||||||
|
|
||||||
val = fdt32_ld(valp);
|
adj_val = fdt32_to_cpu(*val);
|
||||||
if (val + delta < val || val + delta == (uint32_t)-1)
|
if ((adj_val + delta) < adj_val)
|
||||||
return -FDT_ERR_NOPHANDLES;
|
return -FDT_ERR_NOPHANDLES;
|
||||||
|
|
||||||
fdt32_st(valp, val + delta);
|
adj_val += delta;
|
||||||
return 0;
|
if (adj_val == (uint32_t)-1)
|
||||||
|
return -FDT_ERR_NOPHANDLES;
|
||||||
|
|
||||||
|
return fdt_setprop_inplace_u32(fdt, node, name, adj_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -209,8 +228,8 @@ static int overlay_update_local_node_references(void *fdto,
|
||||||
|
|
||||||
fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {
|
fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {
|
||||||
const fdt32_t *fixup_val;
|
const fdt32_t *fixup_val;
|
||||||
|
const char *tree_val;
|
||||||
const char *name;
|
const char *name;
|
||||||
char *tree_val;
|
|
||||||
int fixup_len;
|
int fixup_len;
|
||||||
int tree_len;
|
int tree_len;
|
||||||
int i;
|
int i;
|
||||||
|
@ -222,9 +241,8 @@ static int overlay_update_local_node_references(void *fdto,
|
||||||
|
|
||||||
if (fixup_len % sizeof(uint32_t))
|
if (fixup_len % sizeof(uint32_t))
|
||||||
return -FDT_ERR_BADOVERLAY;
|
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_val) {
|
||||||
if (tree_len == -FDT_ERR_NOTFOUND)
|
if (tree_len == -FDT_ERR_NOTFOUND)
|
||||||
return -FDT_ERR_BADOVERLAY;
|
return -FDT_ERR_BADOVERLAY;
|
||||||
|
@ -232,16 +250,34 @@ static int overlay_update_local_node_references(void *fdto,
|
||||||
return tree_len;
|
return tree_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < fixup_len; i++) {
|
for (i = 0; i < (fixup_len / sizeof(uint32_t)); i++) {
|
||||||
fdt32_t *refp;
|
fdt32_t adj_val;
|
||||||
|
uint32_t poffset;
|
||||||
|
|
||||||
refp = (fdt32_t *)(tree_val + fdt32_ld_(fixup_val + i));
|
poffset = fdt32_to_cpu(fixup_val[i]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* phandles to fixup can be unaligned, so use
|
* phandles to fixup can be unaligned.
|
||||||
* fdt32_{ld,st}() to read/write them.
|
*
|
||||||
|
* Use a memcpy for the architectures that do
|
||||||
|
* not support unaligned accesses.
|
||||||
*/
|
*/
|
||||||
fdt32_st(refp, fdt32_ld(refp) + delta);
|
memcpy(&adj_val, tree_val + poffset, sizeof(adj_val));
|
||||||
|
|
||||||
|
adj_val = cpu_to_fdt32(fdt32_to_cpu(adj_val) + delta);
|
||||||
|
|
||||||
|
ret = fdt_setprop_inplace_namelen_partial(fdto,
|
||||||
|
tree_node,
|
||||||
|
name,
|
||||||
|
strlen(name),
|
||||||
|
poffset,
|
||||||
|
&adj_val,
|
||||||
|
sizeof(adj_val));
|
||||||
|
if (ret == -FDT_ERR_NOSPACE)
|
||||||
|
return -FDT_ERR_BADOVERLAY;
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,6 +343,7 @@ static int overlay_update_local_references(void *fdto, uint32_t delta)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* overlay_fixup_one_phandle - Set an overlay phandle to the base one
|
* overlay_fixup_one_phandle - Set an overlay phandle to the base one
|
||||||
|
* @fdt: Base Device Tree blob
|
||||||
* @fdto: Device tree overlay blob
|
* @fdto: Device tree overlay blob
|
||||||
* @symbols_off: Node offset of the symbols node in the base device tree
|
* @symbols_off: Node offset of the symbols node in the base device tree
|
||||||
* @path: Path to a node holding a phandle in the overlay
|
* @path: Path to a node holding a phandle in the overlay
|
||||||
|
@ -314,7 +351,7 @@ static int overlay_update_local_references(void *fdto, uint32_t delta)
|
||||||
* @name: Name of the property holding the phandle reference in the overlay
|
* @name: Name of the property holding the phandle reference in the overlay
|
||||||
* @name_len: number of name characters to consider
|
* @name_len: number of name characters to consider
|
||||||
* @poffset: Offset within the overlay property where the phandle is stored
|
* @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
|
* overlay_fixup_one_phandle() resolves an overlay phandle pointing to
|
||||||
* a node in the base device tree.
|
* a node in the base device tree.
|
||||||
|
@ -327,17 +364,34 @@ static int overlay_update_local_references(void *fdto, uint32_t delta)
|
||||||
* 0 on success
|
* 0 on success
|
||||||
* Negative error code on failure
|
* 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 *path, uint32_t path_len,
|
||||||
const char *name, uint32_t name_len,
|
const char *name, uint32_t name_len,
|
||||||
int poffset, uint32_t phandle)
|
int poffset, const char *label)
|
||||||
{
|
{
|
||||||
|
const char *symbol_path;
|
||||||
|
uint32_t phandle;
|
||||||
fdt32_t phandle_prop;
|
fdt32_t phandle_prop;
|
||||||
int fixup_off;
|
int symbol_off, fixup_off;
|
||||||
|
int prop_len;
|
||||||
|
|
||||||
if (symbols_off < 0)
|
if (symbols_off < 0)
|
||||||
return symbols_off;
|
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);
|
fixup_off = fdt_path_offset_namelen(fdto, path, path_len);
|
||||||
if (fixup_off == -FDT_ERR_NOTFOUND)
|
if (fixup_off == -FDT_ERR_NOTFOUND)
|
||||||
return -FDT_ERR_BADOVERLAY;
|
return -FDT_ERR_BADOVERLAY;
|
||||||
|
@ -349,7 +403,7 @@ static int overlay_fixup_one_phandle(void *fdto, int symbols_off,
|
||||||
name, name_len, poffset,
|
name, name_len, poffset,
|
||||||
&phandle_prop,
|
&phandle_prop,
|
||||||
sizeof(phandle_prop));
|
sizeof(phandle_prop));
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* overlay_fixup_phandle - Set an overlay phandle to the base one
|
* overlay_fixup_phandle - Set an overlay phandle to the base one
|
||||||
|
@ -376,10 +430,6 @@ static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
|
||||||
const char *value;
|
const char *value;
|
||||||
const char *label;
|
const char *label;
|
||||||
int len;
|
int len;
|
||||||
const char *symbol_path;
|
|
||||||
int prop_len;
|
|
||||||
int symbol_off;
|
|
||||||
uint32_t phandle;
|
|
||||||
|
|
||||||
value = fdt_getprop_by_offset(fdto, property,
|
value = fdt_getprop_by_offset(fdto, property,
|
||||||
&label, &len);
|
&label, &len);
|
||||||
|
@ -390,18 +440,6 @@ static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
|
||||||
return len;
|
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 {
|
do {
|
||||||
const char *path, *name, *fixup_end;
|
const char *path, *name, *fixup_end;
|
||||||
const char *fixup_str = value;
|
const char *fixup_str = value;
|
||||||
|
@ -441,9 +479,9 @@ static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
|
||||||
if ((*endptr != '\0') || (endptr <= (sep + 1)))
|
if ((*endptr != '\0') || (endptr <= (sep + 1)))
|
||||||
return -FDT_ERR_BADOVERLAY;
|
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,
|
path, path_len, name, name_len,
|
||||||
poffset, phandle);
|
poffset, label);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
} while (len > 0);
|
} while (len > 0);
|
||||||
|
@ -496,255 +534,6 @@ static int overlay_fixup_phandles(void *fdt, void *fdto)
|
||||||
return 0;
|
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
|
* overlay_apply_node - Merges a node into the base device tree
|
||||||
* @fdt: Base Device Tree blob
|
* @fdt: Base Device Tree blob
|
||||||
|
@ -846,7 +635,7 @@ static int overlay_merge(void *fdt, void *fdto)
|
||||||
if (overlay < 0)
|
if (overlay < 0)
|
||||||
return overlay;
|
return overlay;
|
||||||
|
|
||||||
target = fdt_overlay_target_offset(fdt, fdto, fragment, NULL);
|
target = overlay_get_target(fdt, fdto, fragment, NULL);
|
||||||
if (target < 0)
|
if (target < 0)
|
||||||
return target;
|
return target;
|
||||||
|
|
||||||
|
@ -989,7 +778,7 @@ static int overlay_symbol_update(void *fdt, void *fdto)
|
||||||
return -FDT_ERR_BADOVERLAY;
|
return -FDT_ERR_BADOVERLAY;
|
||||||
|
|
||||||
/* get the target of the fragment */
|
/* get the target of the fragment */
|
||||||
ret = fdt_overlay_target_offset(fdt, fdto, fragment, &target_path);
|
ret = overlay_get_target(fdt, fdto, fragment, &target_path);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
target = ret;
|
target = ret;
|
||||||
|
@ -1011,7 +800,7 @@ static int overlay_symbol_update(void *fdt, void *fdto)
|
||||||
|
|
||||||
if (!target_path) {
|
if (!target_path) {
|
||||||
/* again in case setprop_placeholder changed it */
|
/* again in case setprop_placeholder changed it */
|
||||||
ret = fdt_overlay_target_offset(fdt, fdto, fragment, &target_path);
|
ret = overlay_get_target(fdt, fdto, fragment, &target_path);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
target = ret;
|
target = ret;
|
||||||
|
@ -1049,26 +838,18 @@ int fdt_overlay_apply(void *fdt, void *fdto)
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
/* Increase all phandles in the fdto by delta */
|
|
||||||
ret = overlay_adjust_local_phandles(fdto, delta);
|
ret = overlay_adjust_local_phandles(fdto, delta);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
/* Adapt the phandle values in fdto to the above increase */
|
|
||||||
ret = overlay_update_local_references(fdto, delta);
|
ret = overlay_update_local_references(fdto, delta);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
/* Update fdto's phandles using symbols from fdt */
|
|
||||||
ret = overlay_fixup_phandles(fdt, fdto);
|
ret = overlay_fixup_phandles(fdt, fdto);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
/* Don't overwrite phandles in fdt */
|
|
||||||
ret = overlay_prevent_phandle_overwrite(fdt, fdto);
|
|
||||||
if (ret)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
ret = overlay_merge(fdt, fdto);
|
ret = overlay_merge(fdt, fdto);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
|
@ -53,7 +53,7 @@ const char *fdt_get_string(const void *fdt, int stroffset, int *lenp)
|
||||||
|
|
||||||
err = -FDT_ERR_BADOFFSET;
|
err = -FDT_ERR_BADOFFSET;
|
||||||
absoffset = stroffset + fdt_off_dt_strings(fdt);
|
absoffset = stroffset + fdt_off_dt_strings(fdt);
|
||||||
if (absoffset >= (unsigned)totalsize)
|
if (absoffset >= totalsize)
|
||||||
goto fail;
|
goto fail;
|
||||||
len = totalsize - absoffset;
|
len = totalsize - absoffset;
|
||||||
|
|
||||||
|
@ -61,19 +61,17 @@ const char *fdt_get_string(const void *fdt, int stroffset, int *lenp)
|
||||||
if (stroffset < 0)
|
if (stroffset < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
|
if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
|
||||||
if ((unsigned)stroffset >= fdt_size_dt_strings(fdt))
|
if (stroffset >= fdt_size_dt_strings(fdt))
|
||||||
goto fail;
|
goto fail;
|
||||||
if ((fdt_size_dt_strings(fdt) - stroffset) < len)
|
if ((fdt_size_dt_strings(fdt) - stroffset) < len)
|
||||||
len = fdt_size_dt_strings(fdt) - stroffset;
|
len = fdt_size_dt_strings(fdt) - stroffset;
|
||||||
}
|
}
|
||||||
} else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
|
} else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
|
||||||
unsigned int sw_stroffset = -stroffset;
|
if ((stroffset >= 0)
|
||||||
|
|| (stroffset < -fdt_size_dt_strings(fdt)))
|
||||||
if ((stroffset >= 0) ||
|
|
||||||
(sw_stroffset > fdt_size_dt_strings(fdt)))
|
|
||||||
goto fail;
|
goto fail;
|
||||||
if (sw_stroffset < len)
|
if ((-stroffset) < len)
|
||||||
len = sw_stroffset;
|
len = -stroffset;
|
||||||
} else {
|
} else {
|
||||||
err = -FDT_ERR_INTERNAL;
|
err = -FDT_ERR_INTERNAL;
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -159,8 +157,8 @@ int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
|
||||||
|
|
||||||
static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n)
|
static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n)
|
||||||
{
|
{
|
||||||
unsigned int offset = n * sizeof(struct fdt_reserve_entry);
|
int offset = n * sizeof(struct fdt_reserve_entry);
|
||||||
unsigned int absoffset = fdt_off_mem_rsvmap(fdt) + offset;
|
int absoffset = fdt_off_mem_rsvmap(fdt) + offset;
|
||||||
|
|
||||||
if (!can_assume(VALID_INPUT)) {
|
if (!can_assume(VALID_INPUT)) {
|
||||||
if (absoffset < fdt_off_mem_rsvmap(fdt))
|
if (absoffset < fdt_off_mem_rsvmap(fdt))
|
||||||
|
@ -181,8 +179,8 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
|
||||||
if (!can_assume(VALID_INPUT) && !re)
|
if (!can_assume(VALID_INPUT) && !re)
|
||||||
return -FDT_ERR_BADOFFSET;
|
return -FDT_ERR_BADOFFSET;
|
||||||
|
|
||||||
*address = fdt64_ld_(&re->address);
|
*address = fdt64_ld(&re->address);
|
||||||
*size = fdt64_ld_(&re->size);
|
*size = fdt64_ld(&re->size);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,7 +190,7 @@ int fdt_num_mem_rsv(const void *fdt)
|
||||||
const struct fdt_reserve_entry *re;
|
const struct fdt_reserve_entry *re;
|
||||||
|
|
||||||
for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) {
|
for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) {
|
||||||
if (fdt64_ld_(&re->size) == 0)
|
if (fdt64_ld(&re->size) == 0)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
return -FDT_ERR_TRUNCATED;
|
return -FDT_ERR_TRUNCATED;
|
||||||
|
@ -255,9 +253,6 @@ int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen)
|
||||||
|
|
||||||
FDT_RO_PROBE(fdt);
|
FDT_RO_PROBE(fdt);
|
||||||
|
|
||||||
if (!can_assume(VALID_INPUT) && namelen <= 0)
|
|
||||||
return -FDT_ERR_BADPATH;
|
|
||||||
|
|
||||||
/* see if we have an alias */
|
/* see if we have an alias */
|
||||||
if (*path != '/') {
|
if (*path != '/') {
|
||||||
const char *q = memchr(path, '/', end - p);
|
const char *q = memchr(path, '/', end - p);
|
||||||
|
@ -373,7 +368,7 @@ static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt,
|
||||||
prop = fdt_offset_ptr_(fdt, offset);
|
prop = fdt_offset_ptr_(fdt, offset);
|
||||||
|
|
||||||
if (lenp)
|
if (lenp)
|
||||||
*lenp = fdt32_ld_(&prop->len);
|
*lenp = fdt32_ld(&prop->len);
|
||||||
|
|
||||||
return prop;
|
return prop;
|
||||||
}
|
}
|
||||||
|
@ -411,7 +406,7 @@ static const struct fdt_property *fdt_get_property_namelen_(const void *fdt,
|
||||||
offset = -FDT_ERR_INTERNAL;
|
offset = -FDT_ERR_INTERNAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (fdt_string_eq_(fdt, fdt32_ld_(&prop->nameoff),
|
if (fdt_string_eq_(fdt, fdt32_ld(&prop->nameoff),
|
||||||
name, namelen)) {
|
name, namelen)) {
|
||||||
if (poffset)
|
if (poffset)
|
||||||
*poffset = offset;
|
*poffset = offset;
|
||||||
|
@ -464,7 +459,7 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
|
||||||
|
|
||||||
/* Handle realignment */
|
/* Handle realignment */
|
||||||
if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
|
if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
|
||||||
(poffset + sizeof(*prop)) % 8 && fdt32_ld_(&prop->len) >= 8)
|
(poffset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
|
||||||
return prop->data + 4;
|
return prop->data + 4;
|
||||||
return prop->data;
|
return prop->data;
|
||||||
}
|
}
|
||||||
|
@ -482,22 +477,22 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
|
||||||
int namelen;
|
int namelen;
|
||||||
|
|
||||||
if (!can_assume(VALID_INPUT)) {
|
if (!can_assume(VALID_INPUT)) {
|
||||||
name = fdt_get_string(fdt, fdt32_ld_(&prop->nameoff),
|
name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff),
|
||||||
&namelen);
|
&namelen);
|
||||||
*namep = name;
|
|
||||||
if (!name) {
|
if (!name) {
|
||||||
if (lenp)
|
if (lenp)
|
||||||
*lenp = namelen;
|
*lenp = namelen;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
*namep = name;
|
||||||
} else {
|
} else {
|
||||||
*namep = fdt_string(fdt, fdt32_ld_(&prop->nameoff));
|
*namep = fdt_string(fdt, fdt32_ld(&prop->nameoff));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle realignment */
|
/* Handle realignment */
|
||||||
if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
|
if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
|
||||||
(offset + sizeof(*prop)) % 8 && fdt32_ld_(&prop->len) >= 8)
|
(offset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
|
||||||
return prop->data + 4;
|
return prop->data + 4;
|
||||||
return prop->data;
|
return prop->data;
|
||||||
}
|
}
|
||||||
|
@ -522,34 +517,19 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return fdt32_ld_(php);
|
return fdt32_ld(php);
|
||||||
}
|
|
||||||
|
|
||||||
static const void *fdt_path_getprop_namelen(const void *fdt, const char *path,
|
|
||||||
const char *propname, int propnamelen,
|
|
||||||
int *lenp)
|
|
||||||
{
|
|
||||||
int offset = fdt_path_offset(fdt, path);
|
|
||||||
|
|
||||||
if (offset < 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return fdt_getprop_namelen(fdt, offset, propname, propnamelen, lenp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *fdt_get_alias_namelen(const void *fdt,
|
const char *fdt_get_alias_namelen(const void *fdt,
|
||||||
const char *name, int namelen)
|
const char *name, int namelen)
|
||||||
{
|
{
|
||||||
int len;
|
int aliasoffset;
|
||||||
const char *alias;
|
|
||||||
|
|
||||||
alias = fdt_path_getprop_namelen(fdt, "/aliases", name, namelen, &len);
|
aliasoffset = fdt_path_offset(fdt, "/aliases");
|
||||||
|
if (aliasoffset < 0)
|
||||||
if (!can_assume(VALID_DTB) &&
|
|
||||||
!(alias && len > 0 && alias[len - 1] == '\0' && *alias == '/'))
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return alias;
|
return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *fdt_get_alias(const void *fdt, const char *name)
|
const char *fdt_get_alias(const void *fdt, const char *name)
|
||||||
|
@ -557,17 +537,6 @@ const char *fdt_get_alias(const void *fdt, const char *name)
|
||||||
return fdt_get_alias_namelen(fdt, name, strlen(name));
|
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 fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
|
||||||
{
|
{
|
||||||
int pdepth = 0, p = 0;
|
int pdepth = 0, p = 0;
|
||||||
|
@ -711,7 +680,7 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
|
||||||
{
|
{
|
||||||
int offset;
|
int offset;
|
||||||
|
|
||||||
if ((phandle == 0) || (phandle == ~0U))
|
if ((phandle == 0) || (phandle == -1))
|
||||||
return -FDT_ERR_BADPHANDLE;
|
return -FDT_ERR_BADPHANDLE;
|
||||||
|
|
||||||
FDT_RO_PROBE(fdt);
|
FDT_RO_PROBE(fdt);
|
||||||
|
|
|
@ -46,7 +46,7 @@ static int fdt_rw_probe_(void *fdt)
|
||||||
return err_; \
|
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);
|
return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
|
||||||
}
|
}
|
||||||
|
@ -54,16 +54,15 @@ static inline unsigned int fdt_data_size_(void *fdt)
|
||||||
static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen)
|
static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen)
|
||||||
{
|
{
|
||||||
char *p = splicepoint;
|
char *p = splicepoint;
|
||||||
unsigned int dsize = fdt_data_size_(fdt);
|
char *end = (char *)fdt + fdt_data_size_(fdt);
|
||||||
size_t soff = p - (char *)fdt;
|
|
||||||
|
|
||||||
if ((oldlen < 0) || (soff + oldlen < soff) || (soff + oldlen > dsize))
|
if (((p + oldlen) < p) || ((p + oldlen) > end))
|
||||||
return -FDT_ERR_BADOFFSET;
|
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;
|
return -FDT_ERR_BADOFFSET;
|
||||||
if (dsize - oldlen + newlen > fdt_totalsize(fdt))
|
if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt)))
|
||||||
return -FDT_ERR_NOSPACE;
|
return -FDT_ERR_NOSPACE;
|
||||||
memmove(p + newlen, p + oldlen, ((char *)fdt + dsize) - (p + oldlen));
|
memmove(p + newlen, p + oldlen, end - p - oldlen);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,33 +123,31 @@ static int fdt_splice_string_(void *fdt, int newlen)
|
||||||
* allocated. Ignored if can_assume(NO_ROLLBACK)
|
* allocated. Ignored if can_assume(NO_ROLLBACK)
|
||||||
* @return offset of string in the string table (whether found or added)
|
* @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,
|
static int fdt_find_add_string_(void *fdt, const char *s, int *allocated)
|
||||||
int *allocated)
|
|
||||||
{
|
{
|
||||||
char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
|
char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
|
||||||
const char *p;
|
const char *p;
|
||||||
char *new;
|
char *new;
|
||||||
|
int len = strlen(s) + 1;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!can_assume(NO_ROLLBACK))
|
if (!can_assume(NO_ROLLBACK))
|
||||||
*allocated = 0;
|
*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)
|
if (p)
|
||||||
/* found it */
|
/* found it */
|
||||||
return (p - strtab);
|
return (p - strtab);
|
||||||
|
|
||||||
new = strtab + fdt_size_dt_strings(fdt);
|
new = strtab + fdt_size_dt_strings(fdt);
|
||||||
err = fdt_splice_string_(fdt, slen + 1);
|
err = fdt_splice_string_(fdt, len);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
if (!can_assume(NO_ROLLBACK))
|
if (!can_assume(NO_ROLLBACK))
|
||||||
*allocated = 1;
|
*allocated = 1;
|
||||||
|
|
||||||
memcpy(new, s, slen);
|
memcpy(new, s, len);
|
||||||
new[slen] = '\0';
|
|
||||||
|
|
||||||
return (new - strtab);
|
return (new - strtab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,15 +180,13 @@ int fdt_del_mem_rsv(void *fdt, int n)
|
||||||
return fdt_splice_mem_rsv_(fdt, re, 1, 0);
|
return fdt_splice_mem_rsv_(fdt, re, 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fdt_resize_property_(void *fdt, int nodeoffset,
|
static int fdt_resize_property_(void *fdt, int nodeoffset, const char *name,
|
||||||
const char *name, int namelen,
|
|
||||||
int len, struct fdt_property **prop)
|
int len, struct fdt_property **prop)
|
||||||
{
|
{
|
||||||
int oldlen;
|
int oldlen;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
*prop = fdt_get_property_namelen_w(fdt, nodeoffset, name, namelen,
|
*prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
|
||||||
&oldlen);
|
|
||||||
if (!*prop)
|
if (!*prop)
|
||||||
return oldlen;
|
return oldlen;
|
||||||
|
|
||||||
|
@ -204,7 +199,7 @@ static int fdt_resize_property_(void *fdt, int nodeoffset,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fdt_add_property_(void *fdt, int nodeoffset, const char *name,
|
static int fdt_add_property_(void *fdt, int nodeoffset, const char *name,
|
||||||
int namelen, int len, struct fdt_property **prop)
|
int len, struct fdt_property **prop)
|
||||||
{
|
{
|
||||||
int proplen;
|
int proplen;
|
||||||
int nextoffset;
|
int nextoffset;
|
||||||
|
@ -215,7 +210,7 @@ static int fdt_add_property_(void *fdt, int nodeoffset, const char *name,
|
||||||
if ((nextoffset = fdt_check_node_offset_(fdt, nodeoffset)) < 0)
|
if ((nextoffset = fdt_check_node_offset_(fdt, nodeoffset)) < 0)
|
||||||
return nextoffset;
|
return nextoffset;
|
||||||
|
|
||||||
namestroff = fdt_find_add_string_(fdt, name, namelen, &allocated);
|
namestroff = fdt_find_add_string_(fdt, name, &allocated);
|
||||||
if (namestroff < 0)
|
if (namestroff < 0)
|
||||||
return namestroff;
|
return namestroff;
|
||||||
|
|
||||||
|
@ -259,18 +254,17 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fdt_setprop_placeholder_namelen(void *fdt, int nodeoffset, const char *name,
|
int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name,
|
||||||
int namelen, int len, void **prop_data)
|
int len, void **prop_data)
|
||||||
{
|
{
|
||||||
struct fdt_property *prop;
|
struct fdt_property *prop;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
FDT_RW_PROBE(fdt);
|
FDT_RW_PROBE(fdt);
|
||||||
|
|
||||||
err = fdt_resize_property_(fdt, nodeoffset, name, namelen, len, &prop);
|
err = fdt_resize_property_(fdt, nodeoffset, name, len, &prop);
|
||||||
if (err == -FDT_ERR_NOTFOUND)
|
if (err == -FDT_ERR_NOTFOUND)
|
||||||
err = fdt_add_property_(fdt, nodeoffset, name, namelen, len,
|
err = fdt_add_property_(fdt, nodeoffset, name, len, &prop);
|
||||||
&prop);
|
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -278,14 +272,13 @@ int fdt_setprop_placeholder_namelen(void *fdt, int nodeoffset, const char *name,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fdt_setprop_namelen(void *fdt, int nodeoffset, const char *name,
|
int fdt_setprop(void *fdt, int nodeoffset, const char *name,
|
||||||
int namelen, const void *val, int len)
|
const void *val, int len)
|
||||||
{
|
{
|
||||||
void *prop_data;
|
void *prop_data;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = fdt_setprop_placeholder_namelen(fdt, nodeoffset, name, namelen,
|
err = fdt_setprop_placeholder(fdt, nodeoffset, name, len, &prop_data);
|
||||||
len, &prop_data);
|
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -313,8 +306,7 @@ int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
|
||||||
prop->len = cpu_to_fdt32(newlen);
|
prop->len = cpu_to_fdt32(newlen);
|
||||||
memcpy(prop->data + oldlen, val, len);
|
memcpy(prop->data + oldlen, val, len);
|
||||||
} else {
|
} else {
|
||||||
err = fdt_add_property_(fdt, nodeoffset, name, strlen(name),
|
err = fdt_add_property_(fdt, nodeoffset, name, len, &prop);
|
||||||
len, &prop);
|
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
memcpy(prop->data, val, len);
|
memcpy(prop->data, val, len);
|
||||||
|
@ -356,10 +348,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
|
||||||
return offset;
|
return offset;
|
||||||
|
|
||||||
/* Try to place the new node after the parent's properties */
|
/* Try to place the new node after the parent's properties */
|
||||||
tag = fdt_next_tag(fdt, parentoffset, &nextoffset);
|
fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */
|
||||||
/* the fdt_subnode_offset_namelen() should ensure this never hits */
|
|
||||||
if (!can_assume(LIBFDT_FLAWLESS) && (tag != FDT_BEGIN_NODE))
|
|
||||||
return -FDT_ERR_INTERNAL;
|
|
||||||
do {
|
do {
|
||||||
offset = nextoffset;
|
offset = nextoffset;
|
||||||
tag = fdt_next_tag(fdt, offset, &nextoffset);
|
tag = fdt_next_tag(fdt, offset, &nextoffset);
|
||||||
|
@ -401,9 +390,7 @@ int fdt_del_node(void *fdt, int nodeoffset)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fdt_packblocks_(const char *old, char *new,
|
static void fdt_packblocks_(const char *old, char *new,
|
||||||
int mem_rsv_size,
|
int mem_rsv_size, int struct_size)
|
||||||
int struct_size,
|
|
||||||
int strings_size)
|
|
||||||
{
|
{
|
||||||
int mem_rsv_off, struct_off, strings_off;
|
int mem_rsv_off, struct_off, strings_off;
|
||||||
|
|
||||||
|
@ -418,7 +405,8 @@ static void fdt_packblocks_(const char *old, char *new,
|
||||||
fdt_set_off_dt_struct(new, struct_off);
|
fdt_set_off_dt_struct(new, struct_off);
|
||||||
fdt_set_size_dt_struct(new, struct_size);
|
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_off_dt_strings(new, strings_off);
|
||||||
fdt_set_size_dt_strings(new, fdt_size_dt_strings(old));
|
fdt_set_size_dt_strings(new, fdt_size_dt_strings(old));
|
||||||
}
|
}
|
||||||
|
@ -439,17 +427,15 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
|
||||||
|
|
||||||
if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
|
if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
|
||||||
struct_size = fdt_size_dt_struct(fdt);
|
struct_size = fdt_size_dt_struct(fdt);
|
||||||
} else if (fdt_version(fdt) == 16) {
|
} else {
|
||||||
struct_size = 0;
|
struct_size = 0;
|
||||||
while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END)
|
while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END)
|
||||||
;
|
;
|
||||||
if (struct_size < 0)
|
if (struct_size < 0)
|
||||||
return struct_size;
|
return struct_size;
|
||||||
} else {
|
|
||||||
return -FDT_ERR_BADVERSION;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (can_assume(LIBFDT_ORDER) ||
|
if (can_assume(LIBFDT_ORDER) |
|
||||||
!fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) {
|
!fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) {
|
||||||
/* no further work necessary */
|
/* no further work necessary */
|
||||||
err = fdt_move(fdt, buf, bufsize);
|
err = fdt_move(fdt, buf, bufsize);
|
||||||
|
@ -478,8 +464,7 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
|
||||||
return -FDT_ERR_NOSPACE;
|
return -FDT_ERR_NOSPACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
fdt_packblocks_(fdt, tmp, mem_rsv_size, struct_size,
|
fdt_packblocks_(fdt, tmp, mem_rsv_size, struct_size);
|
||||||
fdt_size_dt_strings(fdt));
|
|
||||||
memmove(buf, tmp, newsize);
|
memmove(buf, tmp, newsize);
|
||||||
|
|
||||||
fdt_set_magic(buf, FDT_MAGIC);
|
fdt_set_magic(buf, FDT_MAGIC);
|
||||||
|
@ -499,8 +484,7 @@ int fdt_pack(void *fdt)
|
||||||
|
|
||||||
mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
|
mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
|
||||||
* sizeof(struct fdt_reserve_entry);
|
* sizeof(struct fdt_reserve_entry);
|
||||||
fdt_packblocks_(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt),
|
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_set_totalsize(fdt, fdt_data_size_(fdt));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -39,9 +39,8 @@ static struct fdt_errtabent fdt_errtable[] = {
|
||||||
FDT_ERRTABENT(FDT_ERR_BADOVERLAY),
|
FDT_ERRTABENT(FDT_ERR_BADOVERLAY),
|
||||||
FDT_ERRTABENT(FDT_ERR_NOPHANDLES),
|
FDT_ERRTABENT(FDT_ERR_NOPHANDLES),
|
||||||
FDT_ERRTABENT(FDT_ERR_BADFLAGS),
|
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)
|
const char *fdt_strerror(int errval)
|
||||||
{
|
{
|
||||||
|
@ -49,7 +48,7 @@ const char *fdt_strerror(int errval)
|
||||||
return "<valid offset/length>";
|
return "<valid offset/length>";
|
||||||
else if (errval == 0)
|
else if (errval == 0)
|
||||||
return "<no error>";
|
return "<no error>";
|
||||||
else if (-errval < FDT_ERRTABSIZE) {
|
else if (errval > -FDT_ERRTABSIZE) {
|
||||||
const char *s = fdt_errtable[-errval].str;
|
const char *s = fdt_errtable[-errval].str;
|
||||||
|
|
||||||
if (s)
|
if (s)
|
||||||
|
|
|
@ -32,7 +32,7 @@ static int fdt_sw_probe_(void *fdt)
|
||||||
/* 'memrsv' state: Initial state after fdt_create()
|
/* 'memrsv' state: Initial state after fdt_create()
|
||||||
*
|
*
|
||||||
* Allowed functions:
|
* Allowed functions:
|
||||||
* fdt_add_reservemap_entry()
|
* fdt_add_reservmap_entry()
|
||||||
* fdt_finish_reservemap() [moves to 'struct' state]
|
* fdt_finish_reservemap() [moves to 'struct' state]
|
||||||
*/
|
*/
|
||||||
static int fdt_sw_probe_memrsv_(void *fdt)
|
static int fdt_sw_probe_memrsv_(void *fdt)
|
||||||
|
@ -93,8 +93,8 @@ static inline uint32_t sw_flags(void *fdt)
|
||||||
|
|
||||||
static void *fdt_grab_space_(void *fdt, size_t len)
|
static void *fdt_grab_space_(void *fdt, size_t len)
|
||||||
{
|
{
|
||||||
unsigned int offset = fdt_size_dt_struct(fdt);
|
int offset = fdt_size_dt_struct(fdt);
|
||||||
unsigned int spaceleft;
|
int spaceleft;
|
||||||
|
|
||||||
spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt)
|
spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt)
|
||||||
- fdt_size_dt_strings(fdt);
|
- fdt_size_dt_strings(fdt);
|
||||||
|
@ -108,7 +108,7 @@ static void *fdt_grab_space_(void *fdt, size_t len)
|
||||||
|
|
||||||
int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags)
|
int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags)
|
||||||
{
|
{
|
||||||
const int hdrsize = FDT_ALIGN(sizeof(struct fdt_header),
|
const size_t hdrsize = FDT_ALIGN(sizeof(struct fdt_header),
|
||||||
sizeof(struct fdt_reserve_entry));
|
sizeof(struct fdt_reserve_entry));
|
||||||
void *fdt = buf;
|
void *fdt = buf;
|
||||||
|
|
||||||
|
@ -152,9 +152,6 @@ int fdt_resize(void *fdt, void *buf, int bufsize)
|
||||||
|
|
||||||
FDT_SW_PROBE(fdt);
|
FDT_SW_PROBE(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) + fdt_size_dt_struct(fdt);
|
||||||
tailsize = fdt_size_dt_strings(fdt);
|
tailsize = fdt_size_dt_strings(fdt);
|
||||||
|
|
||||||
|
@ -162,7 +159,7 @@ int fdt_resize(void *fdt, void *buf, int bufsize)
|
||||||
headsize + tailsize > fdt_totalsize(fdt))
|
headsize + tailsize > fdt_totalsize(fdt))
|
||||||
return -FDT_ERR_INTERNAL;
|
return -FDT_ERR_INTERNAL;
|
||||||
|
|
||||||
if ((headsize + tailsize) > (unsigned)bufsize)
|
if ((headsize + tailsize) > bufsize)
|
||||||
return -FDT_ERR_NOSPACE;
|
return -FDT_ERR_NOSPACE;
|
||||||
|
|
||||||
oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize;
|
oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize;
|
||||||
|
@ -250,18 +247,18 @@ int fdt_end_node(void *fdt)
|
||||||
static int fdt_add_string_(void *fdt, const char *s)
|
static int fdt_add_string_(void *fdt, const char *s)
|
||||||
{
|
{
|
||||||
char *strtab = (char *)fdt + fdt_totalsize(fdt);
|
char *strtab = (char *)fdt + fdt_totalsize(fdt);
|
||||||
unsigned int strtabsize = fdt_size_dt_strings(fdt);
|
int strtabsize = fdt_size_dt_strings(fdt);
|
||||||
unsigned int len = strlen(s) + 1;
|
int len = strlen(s) + 1;
|
||||||
unsigned int struct_top, offset;
|
int struct_top, offset;
|
||||||
|
|
||||||
offset = strtabsize + len;
|
offset = -strtabsize - len;
|
||||||
struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
|
struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
|
||||||
if (fdt_totalsize(fdt) - offset < struct_top)
|
if (fdt_totalsize(fdt) + offset < struct_top)
|
||||||
return 0; /* no more room :( */
|
return 0; /* no more room :( */
|
||||||
|
|
||||||
memcpy(strtab - offset, s, len);
|
memcpy(strtab + offset, s, len);
|
||||||
fdt_set_size_dt_strings(fdt, strtabsize + len);
|
fdt_set_size_dt_strings(fdt, strtabsize + len);
|
||||||
return -offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Must only be used to roll back in case of error */
|
/* Must only be used to roll back in case of error */
|
||||||
|
@ -377,7 +374,7 @@ int fdt_finish(void *fdt)
|
||||||
fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
|
fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
|
||||||
|
|
||||||
/* And fix up fields that were keeping intermediate state. */
|
/* And fix up fields that were keeping intermediate state. */
|
||||||
fdt_set_last_comp_version(fdt, FDT_LAST_COMPATIBLE_VERSION);
|
fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
|
||||||
fdt_set_magic(fdt, FDT_MAGIC);
|
fdt_set_magic(fdt, FDT_MAGIC);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -23,7 +23,7 @@ int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
|
||||||
if (!propval)
|
if (!propval)
|
||||||
return proplen;
|
return proplen;
|
||||||
|
|
||||||
if ((unsigned)proplen < (len + idx))
|
if (proplen < (len + idx))
|
||||||
return -FDT_ERR_NOSPACE;
|
return -FDT_ERR_NOSPACE;
|
||||||
|
|
||||||
memcpy((char *)propval + idx, val, len);
|
memcpy((char *)propval + idx, val, len);
|
||||||
|
|
598
libfdt/libfdt.h
598
libfdt/libfdt.h
|
@ -9,12 +9,7 @@
|
||||||
#include <libfdt_env.h>
|
#include <libfdt_env.h>
|
||||||
#include <fdt.h>
|
#include <fdt.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define FDT_FIRST_SUPPORTED_VERSION 0x02
|
#define FDT_FIRST_SUPPORTED_VERSION 0x02
|
||||||
#define FDT_LAST_COMPATIBLE_VERSION 0x10
|
|
||||||
#define FDT_LAST_SUPPORTED_VERSION 0x11
|
#define FDT_LAST_SUPPORTED_VERSION 0x11
|
||||||
|
|
||||||
/* Error codes: informative error codes */
|
/* Error codes: informative error codes */
|
||||||
|
@ -102,11 +97,7 @@ extern "C" {
|
||||||
/* FDT_ERR_BADFLAGS: The function was passed a flags field that
|
/* FDT_ERR_BADFLAGS: The function was passed a flags field that
|
||||||
* contains invalid flags or an invalid combination of flags. */
|
* contains invalid flags or an invalid combination of flags. */
|
||||||
|
|
||||||
#define FDT_ERR_ALIGNMENT 19
|
#define FDT_ERR_MAX 18
|
||||||
/* FDT_ERR_ALIGNMENT: The device tree base address is not 8-byte
|
|
||||||
* aligned. */
|
|
||||||
|
|
||||||
#define FDT_ERR_MAX 19
|
|
||||||
|
|
||||||
/* constants */
|
/* constants */
|
||||||
#define FDT_MAX_PHANDLE 0xfffffffe
|
#define FDT_MAX_PHANDLE 0xfffffffe
|
||||||
|
@ -116,20 +107,6 @@ extern "C" {
|
||||||
/* Low-level functions (you probably don't need these) */
|
/* Low-level functions (you probably don't need these) */
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
|
|
||||||
/**
|
|
||||||
* fdt_offset_ptr - safely get a byte range within the device tree blob
|
|
||||||
* @fdt: Pointer to the device tree blob
|
|
||||||
* @offset: Offset within the blob to the desired byte range
|
|
||||||
* @checklen: Required length of the byte range
|
|
||||||
*
|
|
||||||
* fdt_offset_ptr() returns a pointer to the byte range of length @checklen at
|
|
||||||
* the given @offset within the device tree blob, after verifying that the byte
|
|
||||||
* range fits entirely within the blob and does not overflow.
|
|
||||||
*
|
|
||||||
* returns:
|
|
||||||
* pointer to the byte range, on success
|
|
||||||
* NULL, if the requested range does not fit within the blob
|
|
||||||
*/
|
|
||||||
#ifndef SWIG /* This function is not useful in Python */
|
#ifndef SWIG /* This function is not useful in Python */
|
||||||
const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen);
|
const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen);
|
||||||
#endif
|
#endif
|
||||||
|
@ -138,33 +115,14 @@ static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
|
||||||
return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen);
|
return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* fdt_next_tag - get next tag in the device tree
|
|
||||||
* @fdt: Pointer to the device tree blob
|
|
||||||
* @offset: Offset within the blob to start searching
|
|
||||||
* @nextoffset: Pointer to variable to store the offset of the next tag
|
|
||||||
*
|
|
||||||
* fdt_next_tag() returns the tag type of the next tag in the device tree
|
|
||||||
* blob starting from the given @offset. If @nextoffset is non-NULL, it will
|
|
||||||
* be set to the offset immediately following the tag.
|
|
||||||
*
|
|
||||||
* returns:
|
|
||||||
* the tag type (FDT_BEGIN_NODE, FDT_END_NODE, FDT_PROP, FDT_NOP, FDT_END),
|
|
||||||
* FDT_END, if offset is out of bounds
|
|
||||||
*/
|
|
||||||
uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
|
uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* External helpers to access words from a device tree blob. They're built
|
* Alignment helpers:
|
||||||
* to work even with unaligned pointers on platforms (such as ARMv5) that don't
|
* These helpers access words from a device tree blob. They're
|
||||||
* like unaligned loads and stores.
|
* built to work even with unaligned pointers on platforms (ike
|
||||||
|
* ARM) that don't like unaligned loads and stores
|
||||||
*/
|
*/
|
||||||
static inline uint16_t fdt16_ld(const fdt16_t *p)
|
|
||||||
{
|
|
||||||
const uint8_t *bp = (const uint8_t *)p;
|
|
||||||
|
|
||||||
return ((uint16_t)bp[0] << 8) | bp[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint32_t fdt32_ld(const fdt32_t *p)
|
static inline uint32_t fdt32_ld(const fdt32_t *p)
|
||||||
{
|
{
|
||||||
|
@ -222,22 +180,22 @@ int fdt_next_node(const void *fdt, int offset, int *depth);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fdt_first_subnode() - get offset of first direct subnode
|
* fdt_first_subnode() - get offset of first direct subnode
|
||||||
|
*
|
||||||
* @fdt: FDT blob
|
* @fdt: FDT blob
|
||||||
* @offset: Offset of node to check
|
* @offset: Offset of node to check
|
||||||
*
|
* @return offset of first subnode, or -FDT_ERR_NOTFOUND if there is none
|
||||||
* Return: offset of first subnode, or -FDT_ERR_NOTFOUND if there is none
|
|
||||||
*/
|
*/
|
||||||
int fdt_first_subnode(const void *fdt, int offset);
|
int fdt_first_subnode(const void *fdt, int offset);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fdt_next_subnode() - get offset of next direct subnode
|
* fdt_next_subnode() - get offset of next direct subnode
|
||||||
* @fdt: FDT blob
|
|
||||||
* @offset: Offset of previous subnode
|
|
||||||
*
|
*
|
||||||
* After first calling fdt_first_subnode(), call this function repeatedly to
|
* After first calling fdt_first_subnode(), call this function repeatedly to
|
||||||
* get direct subnodes of a parent node.
|
* get direct subnodes of a parent node.
|
||||||
*
|
*
|
||||||
* Return: offset of next subnode, or -FDT_ERR_NOTFOUND if there are no more
|
* @fdt: FDT blob
|
||||||
|
* @offset: Offset of previous subnode
|
||||||
|
* @return offset of next subnode, or -FDT_ERR_NOTFOUND if there are no more
|
||||||
* subnodes
|
* subnodes
|
||||||
*/
|
*/
|
||||||
int fdt_next_subnode(const void *fdt, int offset);
|
int fdt_next_subnode(const void *fdt, int offset);
|
||||||
|
@ -263,6 +221,7 @@ int fdt_next_subnode(const void *fdt, int offset);
|
||||||
* Note that this is implemented as a macro and @node is used as
|
* Note that this is implemented as a macro and @node is used as
|
||||||
* iterator in the loop. The parent variable be constant or even a
|
* iterator in the loop. The parent variable be constant or even a
|
||||||
* literal.
|
* literal.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
#define fdt_for_each_subnode(node, fdt, parent) \
|
#define fdt_for_each_subnode(node, fdt, parent) \
|
||||||
for (node = fdt_first_subnode(fdt, parent); \
|
for (node = fdt_first_subnode(fdt, parent); \
|
||||||
|
@ -291,36 +250,32 @@ int fdt_next_subnode(const void *fdt, int offset);
|
||||||
struct fdt_header *fdth = (struct fdt_header *)fdt; \
|
struct fdt_header *fdth = (struct fdt_header *)fdt; \
|
||||||
fdth->name = cpu_to_fdt32(val); \
|
fdth->name = cpu_to_fdt32(val); \
|
||||||
}
|
}
|
||||||
fdt_set_hdr_(magic)
|
fdt_set_hdr_(magic);
|
||||||
fdt_set_hdr_(totalsize)
|
fdt_set_hdr_(totalsize);
|
||||||
fdt_set_hdr_(off_dt_struct)
|
fdt_set_hdr_(off_dt_struct);
|
||||||
fdt_set_hdr_(off_dt_strings)
|
fdt_set_hdr_(off_dt_strings);
|
||||||
fdt_set_hdr_(off_mem_rsvmap)
|
fdt_set_hdr_(off_mem_rsvmap);
|
||||||
fdt_set_hdr_(version)
|
fdt_set_hdr_(version);
|
||||||
fdt_set_hdr_(last_comp_version)
|
fdt_set_hdr_(last_comp_version);
|
||||||
fdt_set_hdr_(boot_cpuid_phys)
|
fdt_set_hdr_(boot_cpuid_phys);
|
||||||
fdt_set_hdr_(size_dt_strings)
|
fdt_set_hdr_(size_dt_strings);
|
||||||
fdt_set_hdr_(size_dt_struct)
|
fdt_set_hdr_(size_dt_struct);
|
||||||
#undef fdt_set_hdr_
|
#undef fdt_set_hdr_
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fdt_header_size - return the size of the tree's header
|
* fdt_header_size - return the size of the tree's header
|
||||||
* @fdt: pointer to a flattened device tree
|
* @fdt: pointer to a flattened device tree
|
||||||
*
|
|
||||||
* Return: size of DTB header in bytes
|
|
||||||
*/
|
*/
|
||||||
size_t fdt_header_size(const void *fdt);
|
size_t fdt_header_size(const void *fdt);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fdt_header_size_ - internal function to get header size from a version number
|
* fdt_header_size_ - internal function which takes a version number
|
||||||
* @version: device tree version number
|
|
||||||
*
|
|
||||||
* Return: size of DTB header in bytes
|
|
||||||
*/
|
*/
|
||||||
size_t fdt_header_size_(uint32_t version);
|
size_t fdt_header_size_(uint32_t version);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fdt_check_header - sanity check a device tree header
|
* fdt_check_header - sanity check a device tree header
|
||||||
|
|
||||||
* @fdt: pointer to data which might be a flattened device tree
|
* @fdt: pointer to data which might be a flattened device tree
|
||||||
*
|
*
|
||||||
* fdt_check_header() checks that the given buffer contains what
|
* fdt_check_header() checks that the given buffer contains what
|
||||||
|
@ -362,23 +317,6 @@ int fdt_move(const void *fdt, void *buf, int bufsize);
|
||||||
/* Read-only functions */
|
/* Read-only functions */
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
|
|
||||||
/**
|
|
||||||
* fdt_check_full - check device tree validity
|
|
||||||
* @fdt: pointer to the device tree blob
|
|
||||||
* @bufsize: size of the buffer containing the device tree
|
|
||||||
*
|
|
||||||
* fdt_check_full() checks that the given buffer contains a valid
|
|
||||||
* flattened device tree and that the tree structure is internally
|
|
||||||
* consistent. This is a more thorough check than fdt_check_header().
|
|
||||||
*
|
|
||||||
* returns:
|
|
||||||
* 0, on success
|
|
||||||
* -FDT_ERR_BADMAGIC,
|
|
||||||
* -FDT_ERR_BADVERSION,
|
|
||||||
* -FDT_ERR_BADSTATE,
|
|
||||||
* -FDT_ERR_BADSTRUCTURE,
|
|
||||||
* -FDT_ERR_TRUNCATED, standard meanings
|
|
||||||
*/
|
|
||||||
int fdt_check_full(const void *fdt, size_t bufsize);
|
int fdt_check_full(const void *fdt, size_t bufsize);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -462,7 +400,8 @@ static inline uint32_t fdt_get_max_phandle(const void *fdt)
|
||||||
* highest phandle value in the device tree blob) will be returned in the
|
* highest phandle value in the device tree blob) will be returned in the
|
||||||
* @phandle parameter.
|
* @phandle parameter.
|
||||||
*
|
*
|
||||||
* Return: 0 on success or a negative error-code on failure
|
* Returns:
|
||||||
|
* 0 on success or a negative error-code on failure
|
||||||
*/
|
*/
|
||||||
int fdt_generate_phandle(const void *fdt, uint32_t *phandle);
|
int fdt_generate_phandle(const void *fdt, uint32_t *phandle);
|
||||||
|
|
||||||
|
@ -482,11 +421,9 @@ int fdt_num_mem_rsv(const void *fdt);
|
||||||
/**
|
/**
|
||||||
* fdt_get_mem_rsv - retrieve one memory reserve map entry
|
* fdt_get_mem_rsv - retrieve one memory reserve map entry
|
||||||
* @fdt: pointer to the device tree blob
|
* @fdt: pointer to the device tree blob
|
||||||
* @n: index of reserve map entry
|
* @address, @size: pointers to 64-bit variables
|
||||||
* @address: pointer to 64-bit variable to hold the start address
|
|
||||||
* @size: pointer to 64-bit variable to hold the size of the entry
|
|
||||||
*
|
*
|
||||||
* On success, @address and @size will contain the address and size of
|
* On success, *address and *size will contain the address and size of
|
||||||
* the n-th reserve map entry from the device tree blob, in
|
* the n-th reserve map entry from the device tree blob, in
|
||||||
* native-endian format.
|
* native-endian format.
|
||||||
*
|
*
|
||||||
|
@ -509,8 +446,6 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size);
|
||||||
* namelen characters of name for matching the subnode name. This is
|
* namelen characters of name for matching the subnode name. This is
|
||||||
* useful for finding subnodes based on a portion of a larger string,
|
* useful for finding subnodes based on a portion of a larger string,
|
||||||
* such as a full path.
|
* such as a full path.
|
||||||
*
|
|
||||||
* Return: offset of the subnode or -FDT_ERR_NOTFOUND if name not found.
|
|
||||||
*/
|
*/
|
||||||
#ifndef SWIG /* Not available in Python */
|
#ifndef SWIG /* Not available in Python */
|
||||||
int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
|
int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
|
||||||
|
@ -550,8 +485,6 @@ int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
|
||||||
*
|
*
|
||||||
* Identical to fdt_path_offset(), but only consider the first namelen
|
* Identical to fdt_path_offset(), but only consider the first namelen
|
||||||
* characters of path as the path name.
|
* characters of path as the path name.
|
||||||
*
|
|
||||||
* Return: offset of the node or negative libfdt error value otherwise
|
|
||||||
*/
|
*/
|
||||||
#ifndef SWIG /* Not available in Python */
|
#ifndef SWIG /* Not available in Python */
|
||||||
int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen);
|
int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen);
|
||||||
|
@ -569,35 +502,10 @@ int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen);
|
||||||
* level matching the given component, differentiated only by unit
|
* level matching the given component, differentiated only by unit
|
||||||
* address).
|
* address).
|
||||||
*
|
*
|
||||||
* If the path is not absolute (i.e. does not begin with '/'), the
|
|
||||||
* first component is treated as an alias. That is, the property by
|
|
||||||
* that name is looked up in the /aliases node, and the value of that
|
|
||||||
* property used in place of that first component.
|
|
||||||
*
|
|
||||||
* For example, for this small fragment
|
|
||||||
*
|
|
||||||
* / {
|
|
||||||
* aliases {
|
|
||||||
* i2c2 = &foo; // RHS compiles to "/soc@0/i2c@30a40000/eeprom@52"
|
|
||||||
* };
|
|
||||||
* soc@0 {
|
|
||||||
* foo: i2c@30a40000 {
|
|
||||||
* bar: eeprom@52 {
|
|
||||||
* };
|
|
||||||
* };
|
|
||||||
* };
|
|
||||||
* };
|
|
||||||
*
|
|
||||||
* these would be equivalent:
|
|
||||||
*
|
|
||||||
* /soc@0/i2c@30a40000/eeprom@52
|
|
||||||
* i2c2/eeprom@52
|
|
||||||
*
|
|
||||||
* returns:
|
* returns:
|
||||||
* structure block offset of the node with the requested path (>=0), on
|
* structure block offset of the node with the requested path (>=0), on
|
||||||
* success
|
* success
|
||||||
* -FDT_ERR_BADPATH, given path does not begin with '/' and the first
|
* -FDT_ERR_BADPATH, given path does not begin with '/' or is invalid
|
||||||
* component is not a valid alias
|
|
||||||
* -FDT_ERR_NOTFOUND, if the requested node does not exist
|
* -FDT_ERR_NOTFOUND, if the requested node does not exist
|
||||||
* -FDT_ERR_BADMAGIC,
|
* -FDT_ERR_BADMAGIC,
|
||||||
* -FDT_ERR_BADVERSION,
|
* -FDT_ERR_BADVERSION,
|
||||||
|
@ -676,7 +584,7 @@ int fdt_next_property_offset(const void *fdt, int offset);
|
||||||
/**
|
/**
|
||||||
* fdt_for_each_property_offset - iterate over all properties of a node
|
* fdt_for_each_property_offset - iterate over all properties of a node
|
||||||
*
|
*
|
||||||
* @property: property offset (int, lvalue)
|
* @property_offset: property offset (int, lvalue)
|
||||||
* @fdt: FDT blob (const void *)
|
* @fdt: FDT blob (const void *)
|
||||||
* @node: node offset (int)
|
* @node: node offset (int)
|
||||||
*
|
*
|
||||||
|
@ -730,13 +638,6 @@ int fdt_next_property_offset(const void *fdt, int offset);
|
||||||
const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
|
const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
|
||||||
int offset,
|
int offset,
|
||||||
int *lenp);
|
int *lenp);
|
||||||
static inline struct fdt_property *fdt_get_property_by_offset_w(void *fdt,
|
|
||||||
int offset,
|
|
||||||
int *lenp)
|
|
||||||
{
|
|
||||||
return (struct fdt_property *)(uintptr_t)
|
|
||||||
fdt_get_property_by_offset(fdt, offset, lenp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fdt_get_property_namelen - find a property based on substring
|
* fdt_get_property_namelen - find a property based on substring
|
||||||
|
@ -748,22 +649,12 @@ static inline struct fdt_property *fdt_get_property_by_offset_w(void *fdt,
|
||||||
*
|
*
|
||||||
* Identical to fdt_get_property(), but only examine the first namelen
|
* Identical to fdt_get_property(), but only examine the first namelen
|
||||||
* characters of name for matching the property name.
|
* characters of name for matching the property name.
|
||||||
*
|
|
||||||
* Return: pointer to the structure representing the property, or NULL
|
|
||||||
* if not found
|
|
||||||
*/
|
*/
|
||||||
#ifndef SWIG /* Not available in Python */
|
#ifndef SWIG /* Not available in Python */
|
||||||
const struct fdt_property *fdt_get_property_namelen(const void *fdt,
|
const struct fdt_property *fdt_get_property_namelen(const void *fdt,
|
||||||
int nodeoffset,
|
int nodeoffset,
|
||||||
const char *name,
|
const char *name,
|
||||||
int namelen, int *lenp);
|
int namelen, int *lenp);
|
||||||
static inline struct fdt_property *
|
|
||||||
fdt_get_property_namelen_w(void *fdt, int nodeoffset, const char *name,
|
|
||||||
int namelen, int *lenp)
|
|
||||||
{
|
|
||||||
return (struct fdt_property *)(uintptr_t)fdt_get_property_namelen(
|
|
||||||
fdt, nodeoffset, name, namelen, lenp);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -816,7 +707,7 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
|
||||||
* to within the device blob itself, not a copy of the value). If
|
* to within the device blob itself, not a copy of the value). If
|
||||||
* lenp is non-NULL, the length of the property value is also
|
* lenp is non-NULL, the length of the property value is also
|
||||||
* returned, in the integer pointed to by lenp. If namep is non-NULL,
|
* returned, in the integer pointed to by lenp. If namep is non-NULL,
|
||||||
* the property's name will also be returned in the char * pointed to
|
* the property's namne will also be returned in the char * pointed to
|
||||||
* by namep (this will be a pointer to within the device tree's string
|
* by namep (this will be a pointer to within the device tree's string
|
||||||
* block, not a new copy of the name).
|
* block, not a new copy of the name).
|
||||||
*
|
*
|
||||||
|
@ -824,7 +715,7 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
|
||||||
* pointer to the property's value
|
* pointer to the property's value
|
||||||
* if lenp is non-NULL, *lenp contains the length of the property
|
* if lenp is non-NULL, *lenp contains the length of the property
|
||||||
* value (>=0)
|
* value (>=0)
|
||||||
* if namep is non-NULL *namep contains a pointer to the property
|
* if namep is non-NULL *namep contiains a pointer to the property
|
||||||
* name.
|
* name.
|
||||||
* NULL, on error
|
* NULL, on error
|
||||||
* if lenp is non-NULL, *lenp contains an error code (<0):
|
* if lenp is non-NULL, *lenp contains an error code (<0):
|
||||||
|
@ -850,8 +741,6 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
|
||||||
*
|
*
|
||||||
* Identical to fdt_getprop(), but only examine the first namelen
|
* Identical to fdt_getprop(), but only examine the first namelen
|
||||||
* characters of name for matching the property name.
|
* characters of name for matching the property name.
|
||||||
*
|
|
||||||
* Return: pointer to the property's value or NULL on error
|
|
||||||
*/
|
*/
|
||||||
#ifndef SWIG /* Not available in Python */
|
#ifndef SWIG /* Not available in Python */
|
||||||
const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
|
const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
|
||||||
|
@ -873,10 +762,10 @@ static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset,
|
||||||
* @lenp: pointer to an integer variable (will be overwritten) or NULL
|
* @lenp: pointer to an integer variable (will be overwritten) or NULL
|
||||||
*
|
*
|
||||||
* fdt_getprop() retrieves a pointer to the value of the property
|
* fdt_getprop() retrieves a pointer to the value of the property
|
||||||
* named @name of the node at offset @nodeoffset (this will be a
|
* named 'name' of the node at offset nodeoffset (this will be a
|
||||||
* pointer to within the device blob itself, not a copy of the value).
|
* pointer to within the device blob itself, not a copy of the value).
|
||||||
* If @lenp is non-NULL, the length of the property value is also
|
* If lenp is non-NULL, the length of the property value is also
|
||||||
* returned, in the integer pointed to by @lenp.
|
* returned, in the integer pointed to by lenp.
|
||||||
*
|
*
|
||||||
* returns:
|
* returns:
|
||||||
* pointer to the property's value
|
* pointer to the property's value
|
||||||
|
@ -918,14 +807,11 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);
|
||||||
/**
|
/**
|
||||||
* fdt_get_alias_namelen - get alias based on substring
|
* fdt_get_alias_namelen - get alias based on substring
|
||||||
* @fdt: pointer to the device tree blob
|
* @fdt: pointer to the device tree blob
|
||||||
* @name: name of the alias to look up
|
* @name: name of the alias th look up
|
||||||
* @namelen: number of characters of name to consider
|
* @namelen: number of characters of name to consider
|
||||||
*
|
*
|
||||||
* Identical to fdt_get_alias(), but only examine the first @namelen
|
* Identical to fdt_get_alias(), but only examine the first namelen
|
||||||
* characters of @name for matching the alias name.
|
* characters of name for matching the alias name.
|
||||||
*
|
|
||||||
* Return: a pointer to the expansion of the alias named @name, if it exists,
|
|
||||||
* NULL otherwise
|
|
||||||
*/
|
*/
|
||||||
#ifndef SWIG /* Not available in Python */
|
#ifndef SWIG /* Not available in Python */
|
||||||
const char *fdt_get_alias_namelen(const void *fdt,
|
const char *fdt_get_alias_namelen(const void *fdt,
|
||||||
|
@ -935,10 +821,10 @@ const char *fdt_get_alias_namelen(const void *fdt,
|
||||||
/**
|
/**
|
||||||
* fdt_get_alias - retrieve the path referenced by a given alias
|
* fdt_get_alias - retrieve the path referenced by a given alias
|
||||||
* @fdt: pointer to the device tree blob
|
* @fdt: pointer to the device tree blob
|
||||||
* @name: name of the alias to look up
|
* @name: name of the alias th look up
|
||||||
*
|
*
|
||||||
* fdt_get_alias() retrieves the value of a given alias. That is, the
|
* fdt_get_alias() retrieves the value of a given alias. That is, the
|
||||||
* value of the property named @name in the node /aliases.
|
* value of the property named 'name' in the node /aliases.
|
||||||
*
|
*
|
||||||
* returns:
|
* returns:
|
||||||
* a pointer to the expansion of the alias named 'name', if it exists
|
* a pointer to the expansion of the alias named 'name', if it exists
|
||||||
|
@ -946,42 +832,6 @@ const char *fdt_get_alias_namelen(const void *fdt,
|
||||||
*/
|
*/
|
||||||
const char *fdt_get_alias(const void *fdt, const char *name);
|
const char *fdt_get_alias(const void *fdt, const char *name);
|
||||||
|
|
||||||
/**
|
|
||||||
* fdt_get_symbol_namelen - get symbol based on substring
|
|
||||||
* @fdt: pointer to the device tree blob
|
|
||||||
* @name: name of the symbol to look up
|
|
||||||
* @namelen: number of characters of name to consider
|
|
||||||
*
|
|
||||||
* Identical to fdt_get_symbol(), but only examine the first @namelen
|
|
||||||
* characters of @name for matching the symbol name.
|
|
||||||
*
|
|
||||||
* Return: a pointer to the expansion of the symbol named @name, if it exists,
|
|
||||||
* NULL otherwise
|
|
||||||
*/
|
|
||||||
#ifndef SWIG /* Not available in Python */
|
|
||||||
const char *fdt_get_symbol_namelen(const void *fdt,
|
|
||||||
const char *name, int namelen);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* fdt_get_symbol - retrieve the path referenced by a given symbol
|
|
||||||
* @fdt: pointer to the device tree blob
|
|
||||||
* @name: name of the symbol to look up
|
|
||||||
*
|
|
||||||
* fdt_get_symbol() retrieves the value of a given symbol. That is,
|
|
||||||
* the value of the property named @name in the node
|
|
||||||
* /__symbols__. Such a node exists only for a device tree blob that
|
|
||||||
* has been compiled with the -@ dtc option. Each property corresponds
|
|
||||||
* to a label appearing in the device tree source, with the name of
|
|
||||||
* the property being the label and the value being the full path of
|
|
||||||
* the node it is attached to.
|
|
||||||
*
|
|
||||||
* returns:
|
|
||||||
* a pointer to the expansion of the symbol named 'name', if it exists
|
|
||||||
* NULL, if the given symbol or the /__symbols__ node does not exist
|
|
||||||
*/
|
|
||||||
const char *fdt_get_symbol(const void *fdt, const char *name);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fdt_get_path - determine the full path of a node
|
* fdt_get_path - determine the full path of a node
|
||||||
* @fdt: pointer to the device tree blob
|
* @fdt: pointer to the device tree blob
|
||||||
|
@ -1150,13 +1000,14 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
|
||||||
int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle);
|
int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fdt_node_check_compatible - check a node's compatible property
|
* fdt_node_check_compatible: check a node's compatible property
|
||||||
* @fdt: pointer to the device tree blob
|
* @fdt: pointer to the device tree blob
|
||||||
* @nodeoffset: offset of a tree node
|
* @nodeoffset: offset of a tree node
|
||||||
* @compatible: string to match against
|
* @compatible: string to match against
|
||||||
*
|
*
|
||||||
|
*
|
||||||
* fdt_node_check_compatible() returns 0 if the given node contains a
|
* fdt_node_check_compatible() returns 0 if the given node contains a
|
||||||
* @compatible property with the given string as one of its elements,
|
* 'compatible' property with the given string as one of its elements,
|
||||||
* it returns non-zero otherwise, or on error.
|
* it returns non-zero otherwise, or on error.
|
||||||
*
|
*
|
||||||
* returns:
|
* returns:
|
||||||
|
@ -1220,7 +1071,7 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
|
||||||
* one or more strings, each terminated by \0, as is found in a device tree
|
* one or more strings, each terminated by \0, as is found in a device tree
|
||||||
* "compatible" property.
|
* "compatible" property.
|
||||||
*
|
*
|
||||||
* Return: 1 if the string is found in the list, 0 not found, or invalid list
|
* @return: 1 if the string is found in the list, 0 not found, or invalid list
|
||||||
*/
|
*/
|
||||||
int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
|
int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
|
||||||
|
|
||||||
|
@ -1229,8 +1080,7 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
|
||||||
* @fdt: pointer to the device tree blob
|
* @fdt: pointer to the device tree blob
|
||||||
* @nodeoffset: offset of a tree node
|
* @nodeoffset: offset of a tree node
|
||||||
* @property: name of the property containing the string list
|
* @property: name of the property containing the string list
|
||||||
*
|
* @return:
|
||||||
* Return:
|
|
||||||
* the number of strings in the given property
|
* the number of strings in the given property
|
||||||
* -FDT_ERR_BADVALUE if the property value is not NUL-terminated
|
* -FDT_ERR_BADVALUE if the property value is not NUL-terminated
|
||||||
* -FDT_ERR_NOTFOUND if the property does not exist
|
* -FDT_ERR_NOTFOUND if the property does not exist
|
||||||
|
@ -1250,7 +1100,7 @@ int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property);
|
||||||
* small-valued cell properties, such as #address-cells, when searching for
|
* small-valued cell properties, such as #address-cells, when searching for
|
||||||
* the empty string.
|
* the empty string.
|
||||||
*
|
*
|
||||||
* return:
|
* @return:
|
||||||
* the index of the string in the list of strings
|
* the index of the string in the list of strings
|
||||||
* -FDT_ERR_BADVALUE if the property value is not NUL-terminated
|
* -FDT_ERR_BADVALUE if the property value is not NUL-terminated
|
||||||
* -FDT_ERR_NOTFOUND if the property does not exist or does not contain
|
* -FDT_ERR_NOTFOUND if the property does not exist or does not contain
|
||||||
|
@ -1274,7 +1124,7 @@ int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
|
||||||
* If non-NULL, the length of the string (on success) or a negative error-code
|
* If non-NULL, the length of the string (on success) or a negative error-code
|
||||||
* (on failure) will be stored in the integer pointer to by lenp.
|
* (on failure) will be stored in the integer pointer to by lenp.
|
||||||
*
|
*
|
||||||
* Return:
|
* @return:
|
||||||
* A pointer to the string at the given index in the string list or NULL on
|
* A pointer to the string at the given index in the string list or NULL on
|
||||||
* failure. On success the length of the string will be stored in the memory
|
* failure. On success the length of the string will be stored in the memory
|
||||||
* location pointed to by the lenp parameter, if non-NULL. On failure one of
|
* location pointed to by the lenp parameter, if non-NULL. On failure one of
|
||||||
|
@ -1363,8 +1213,6 @@ int fdt_size_cells(const void *fdt, int nodeoffset);
|
||||||
* starting from the given index, and using only the first characters
|
* starting from the given index, and using only the first characters
|
||||||
* of the name. It is useful when you want to manipulate only one value of
|
* of the name. It is useful when you want to manipulate only one value of
|
||||||
* an array and you have a string that doesn't end with \0.
|
* an array and you have a string that doesn't end with \0.
|
||||||
*
|
|
||||||
* Return: 0 on success, negative libfdt error value otherwise
|
|
||||||
*/
|
*/
|
||||||
#ifndef SWIG /* Not available in Python */
|
#ifndef SWIG /* Not available in Python */
|
||||||
int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
|
int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
|
||||||
|
@ -1478,13 +1326,8 @@ static inline int fdt_setprop_inplace_u64(void *fdt, int nodeoffset,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fdt_setprop_inplace_cell - change the value of a single-cell property
|
* fdt_setprop_inplace_cell - change the value of a single-cell property
|
||||||
* @fdt: pointer to the device tree blob
|
|
||||||
* @nodeoffset: offset of the node containing the property
|
|
||||||
* @name: name of the property to change the value of
|
|
||||||
* @val: new value of the 32-bit cell
|
|
||||||
*
|
*
|
||||||
* This is an alternative name for fdt_setprop_inplace_u32()
|
* This is an alternative name for fdt_setprop_inplace_u32()
|
||||||
* Return: 0 on success, negative libfdt error number otherwise.
|
|
||||||
*/
|
*/
|
||||||
static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
|
static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
|
||||||
const char *name, uint32_t val)
|
const char *name, uint32_t val)
|
||||||
|
@ -1556,14 +1399,14 @@ int fdt_nop_node(void *fdt, int nodeoffset);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fdt_create_with_flags - begin creation of a new fdt
|
* fdt_create_with_flags - begin creation of a new fdt
|
||||||
* @buf: pointer to memory allocated where fdt will be created
|
* @fdt: pointer to memory allocated where fdt will be created
|
||||||
* @bufsize: size of the memory space at fdt
|
* @bufsize: size of the memory space at fdt
|
||||||
* @flags: a valid combination of FDT_CREATE_FLAG_ flags, or 0.
|
* @flags: a valid combination of FDT_CREATE_FLAG_ flags, or 0.
|
||||||
*
|
*
|
||||||
* fdt_create_with_flags() begins the process of creating a new fdt with
|
* fdt_create_with_flags() begins the process of creating a new fdt with
|
||||||
* the sequential write interface.
|
* the sequential write interface.
|
||||||
*
|
*
|
||||||
* fdt creation process must end with fdt_finish() to produce a valid fdt.
|
* fdt creation process must end with fdt_finished() to produce a valid fdt.
|
||||||
*
|
*
|
||||||
* returns:
|
* returns:
|
||||||
* 0, on success
|
* 0, on success
|
||||||
|
@ -1574,7 +1417,7 @@ int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fdt_create - begin creation of a new fdt
|
* fdt_create - begin creation of a new fdt
|
||||||
* @buf: pointer to memory allocated where fdt will be created
|
* @fdt: pointer to memory allocated where fdt will be created
|
||||||
* @bufsize: size of the memory space at fdt
|
* @bufsize: size of the memory space at fdt
|
||||||
*
|
*
|
||||||
* fdt_create() is equivalent to fdt_create_with_flags() with flags=0.
|
* fdt_create() is equivalent to fdt_create_with_flags() with flags=0.
|
||||||
|
@ -1585,90 +1428,10 @@ int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags);
|
||||||
*/
|
*/
|
||||||
int fdt_create(void *buf, int bufsize);
|
int fdt_create(void *buf, int bufsize);
|
||||||
|
|
||||||
/**
|
|
||||||
* fdt_resize - move and resize a device tree in sequential write state
|
|
||||||
* @fdt: Pointer to the device tree to resize
|
|
||||||
* @buf: Buffer where resized tree should be placed
|
|
||||||
* @bufsize: Size of the buffer at @buf
|
|
||||||
*
|
|
||||||
* fdt_resize() moves the device tree blob from @fdt to @buf and
|
|
||||||
* resizes it to fit in the new buffer size.
|
|
||||||
*
|
|
||||||
* returns:
|
|
||||||
* 0, on success
|
|
||||||
* -FDT_ERR_NOSPACE, if @bufsize is too small
|
|
||||||
* -FDT_ERR_BADMAGIC,
|
|
||||||
* -FDT_ERR_BADVERSION,
|
|
||||||
* -FDT_ERR_BADSTATE, standard meanings
|
|
||||||
*/
|
|
||||||
int fdt_resize(void *fdt, void *buf, int bufsize);
|
int fdt_resize(void *fdt, void *buf, int bufsize);
|
||||||
|
|
||||||
/**
|
|
||||||
* fdt_add_reservemap_entry - add an entry to the memory reserve map
|
|
||||||
* @fdt: Pointer to the device tree blob
|
|
||||||
* @addr: Start address of the reserve map entry
|
|
||||||
* @size: Size of the reserved region
|
|
||||||
*
|
|
||||||
* fdt_add_reservemap_entry() adds a memory reserve map entry to the
|
|
||||||
* device tree blob during the sequential write process. This function
|
|
||||||
* can only be called after fdt_create() and before fdt_finish_reservemap().
|
|
||||||
*
|
|
||||||
* returns:
|
|
||||||
* 0, on success
|
|
||||||
* -FDT_ERR_NOSPACE, if there is insufficient space in the blob
|
|
||||||
* -FDT_ERR_BADSTATE, if not in the correct sequential write state
|
|
||||||
*/
|
|
||||||
int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size);
|
int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size);
|
||||||
|
|
||||||
/**
|
|
||||||
* fdt_finish_reservemap - complete the memory reserve map
|
|
||||||
* @fdt: Pointer to the device tree blob
|
|
||||||
*
|
|
||||||
* fdt_finish_reservemap() completes the memory reserve map section
|
|
||||||
* of the device tree blob during sequential write. After calling this
|
|
||||||
* function, no more reserve map entries can be added and the blob
|
|
||||||
* moves to the structure creation phase.
|
|
||||||
*
|
|
||||||
* returns:
|
|
||||||
* 0, on success
|
|
||||||
* -FDT_ERR_BADSTATE, if not in the correct sequential write state
|
|
||||||
*/
|
|
||||||
int fdt_finish_reservemap(void *fdt);
|
int fdt_finish_reservemap(void *fdt);
|
||||||
|
|
||||||
/**
|
|
||||||
* fdt_begin_node - start creation of a new node
|
|
||||||
* @fdt: Pointer to the device tree blob
|
|
||||||
* @name: Name of the node to create
|
|
||||||
*
|
|
||||||
* fdt_begin_node() starts the creation of a new node with the given
|
|
||||||
* @name during sequential write. After calling this function, properties
|
|
||||||
* can be added with fdt_property() and subnodes can be created with
|
|
||||||
* additional fdt_begin_node() calls. The node must be completed with
|
|
||||||
* fdt_end_node().
|
|
||||||
*
|
|
||||||
* returns:
|
|
||||||
* 0, on success
|
|
||||||
* -FDT_ERR_NOSPACE, if there is insufficient space in the blob
|
|
||||||
* -FDT_ERR_BADSTATE, if not in the correct sequential write state
|
|
||||||
*/
|
|
||||||
int fdt_begin_node(void *fdt, const char *name);
|
int fdt_begin_node(void *fdt, const char *name);
|
||||||
|
|
||||||
/**
|
|
||||||
* fdt_property - add a property to the current node
|
|
||||||
* @fdt: Pointer to the device tree blob
|
|
||||||
* @name: Name of the property to add
|
|
||||||
* @val: Pointer to the property value
|
|
||||||
* @len: Length of the property value in bytes
|
|
||||||
*
|
|
||||||
* fdt_property() adds a property with the given @name and value to
|
|
||||||
* the current node during sequential write. This function can only
|
|
||||||
* be called between fdt_begin_node() and fdt_end_node().
|
|
||||||
*
|
|
||||||
* returns:
|
|
||||||
* 0, on success
|
|
||||||
* -FDT_ERR_NOSPACE, if there is insufficient space in the blob
|
|
||||||
* -FDT_ERR_BADSTATE, if not currently within a node
|
|
||||||
*/
|
|
||||||
int fdt_property(void *fdt, const char *name, const void *val, int len);
|
int fdt_property(void *fdt, const char *name, const void *val, int len);
|
||||||
static inline int fdt_property_u32(void *fdt, const char *name, uint32_t val)
|
static inline int fdt_property_u32(void *fdt, const char *name, uint32_t val)
|
||||||
{
|
{
|
||||||
|
@ -1694,7 +1457,7 @@ static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
|
||||||
* @fdt: pointer to the device tree blob
|
* @fdt: pointer to the device tree blob
|
||||||
* @name: name of property to add
|
* @name: name of property to add
|
||||||
* @len: length of property value in bytes
|
* @len: length of property value in bytes
|
||||||
* @valp: returns a pointer to where the value should be placed
|
* @valp: returns a pointer to where where the value should be placed
|
||||||
*
|
*
|
||||||
* returns:
|
* returns:
|
||||||
* 0, on success
|
* 0, on success
|
||||||
|
@ -1705,101 +1468,21 @@ int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp);
|
||||||
|
|
||||||
#define fdt_property_string(fdt, name, str) \
|
#define fdt_property_string(fdt, name, str) \
|
||||||
fdt_property(fdt, name, str, strlen(str)+1)
|
fdt_property(fdt, name, str, strlen(str)+1)
|
||||||
|
|
||||||
/**
|
|
||||||
* fdt_end_node - complete the current node
|
|
||||||
* @fdt: Pointer to the device tree blob
|
|
||||||
*
|
|
||||||
* fdt_end_node() completes the current node during sequential write. This
|
|
||||||
* function must be called to close each node started with
|
|
||||||
* fdt_begin_node(). After calling this function, no more properties or subnodes
|
|
||||||
* can be added to the node.
|
|
||||||
*
|
|
||||||
* returns:
|
|
||||||
* 0, on success
|
|
||||||
* -FDT_ERR_BADSTATE, if not currently within a node
|
|
||||||
*/
|
|
||||||
int fdt_end_node(void *fdt);
|
int fdt_end_node(void *fdt);
|
||||||
|
|
||||||
/**
|
|
||||||
* fdt_finish - complete device tree creation
|
|
||||||
* @fdt: Pointer to the device tree blob
|
|
||||||
*
|
|
||||||
* fdt_finish() completes the device tree creation process started with
|
|
||||||
* fdt_create(). This function finalizes the device tree blob and makes it ready
|
|
||||||
* for use. After calling this function, the blob is complete and can be used
|
|
||||||
* with libfdt read-only and read-write functions, but not with sequential write
|
|
||||||
* functions.
|
|
||||||
*
|
|
||||||
* returns:
|
|
||||||
* 0, on success
|
|
||||||
* -FDT_ERR_BADSTATE, if the sequential write process is incomplete
|
|
||||||
*/
|
|
||||||
int fdt_finish(void *fdt);
|
int fdt_finish(void *fdt);
|
||||||
|
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
/* Read-write functions */
|
/* Read-write functions */
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
|
|
||||||
/**
|
|
||||||
* fdt_create_empty_tree - create an empty device tree
|
|
||||||
* @buf: Buffer where the empty tree should be created
|
|
||||||
* @bufsize: Size of the buffer at @buf
|
|
||||||
*
|
|
||||||
* fdt_create_empty_tree() creates a minimal empty device tree blob
|
|
||||||
* in the given buffer. The tree contains only a root node with no
|
|
||||||
* properties or subnodes.
|
|
||||||
*
|
|
||||||
* returns:
|
|
||||||
* 0, on success
|
|
||||||
* -FDT_ERR_NOSPACE, if @bufsize is too small for even an empty tree
|
|
||||||
*/
|
|
||||||
int fdt_create_empty_tree(void *buf, int bufsize);
|
int fdt_create_empty_tree(void *buf, int bufsize);
|
||||||
|
|
||||||
/**
|
|
||||||
* fdt_open_into - move a device tree into a new buffer and make editable
|
|
||||||
* @fdt: Pointer to the device tree to move
|
|
||||||
* @buf: Buffer where the editable tree should be placed
|
|
||||||
* @bufsize: Size of the buffer at @buf
|
|
||||||
*
|
|
||||||
* fdt_open_into() moves and reorganizes the device tree blob from @fdt
|
|
||||||
* into @buf, converting it to a format suitable for read-write operations.
|
|
||||||
* The new buffer should allow space for modifications.
|
|
||||||
*
|
|
||||||
* returns:
|
|
||||||
* 0, on success
|
|
||||||
* -FDT_ERR_NOSPACE, if @bufsize is too small
|
|
||||||
* -FDT_ERR_BADMAGIC,
|
|
||||||
* -FDT_ERR_BADVERSION,
|
|
||||||
* -FDT_ERR_BADSTATE,
|
|
||||||
* -FDT_ERR_BADSTRUCTURE,
|
|
||||||
* -FDT_ERR_TRUNCATED, standard meanings
|
|
||||||
*/
|
|
||||||
int fdt_open_into(const void *fdt, void *buf, int bufsize);
|
int fdt_open_into(const void *fdt, void *buf, int bufsize);
|
||||||
|
|
||||||
/**
|
|
||||||
* fdt_pack - pack a device tree blob
|
|
||||||
* @fdt: Pointer to the device tree blob
|
|
||||||
*
|
|
||||||
* fdt_pack() reorganizes the device tree blob to eliminate any free space
|
|
||||||
* and pack it into the minimum possible size. This is useful after making
|
|
||||||
* modifications that might have left gaps in the blob.
|
|
||||||
*
|
|
||||||
* returns:
|
|
||||||
* 0, on success
|
|
||||||
* -FDT_ERR_BADMAGIC,
|
|
||||||
* -FDT_ERR_BADVERSION,
|
|
||||||
* -FDT_ERR_BADSTATE,
|
|
||||||
* -FDT_ERR_BADSTRUCTURE,
|
|
||||||
* -FDT_ERR_BADLAYOUT, standard meanings
|
|
||||||
*/
|
|
||||||
int fdt_pack(void *fdt);
|
int fdt_pack(void *fdt);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fdt_add_mem_rsv - add one memory reserve map entry
|
* fdt_add_mem_rsv - add one memory reserve map entry
|
||||||
* @fdt: pointer to the device tree blob
|
* @fdt: pointer to the device tree blob
|
||||||
* @address: 64-bit start address of the reserve map entry
|
* @address, @size: 64-bit values (native endian)
|
||||||
* @size: 64-bit size of the reserved region
|
|
||||||
*
|
*
|
||||||
* Adds a reserve map entry to the given blob reserving a region at
|
* Adds a reserve map entry to the given blob reserving a region at
|
||||||
* address address of length size.
|
* address address of length size.
|
||||||
|
@ -1870,38 +1553,6 @@ int fdt_del_mem_rsv(void *fdt, int n);
|
||||||
*/
|
*/
|
||||||
int fdt_set_name(void *fdt, int nodeoffset, const char *name);
|
int fdt_set_name(void *fdt, int nodeoffset, const char *name);
|
||||||
|
|
||||||
/**
|
|
||||||
* fdt_setprop_namelen - create or change a property
|
|
||||||
* @fdt: pointer to the device tree blob
|
|
||||||
* @nodeoffset: offset of the node whose property to change
|
|
||||||
* @name: name of the property to change
|
|
||||||
* @namelen: length of the name
|
|
||||||
* @val: pointer to data to set the property value to
|
|
||||||
* @len: length of the property value
|
|
||||||
*
|
|
||||||
* fdt_setprop_namelen() sets the value of the named property in the given
|
|
||||||
* node to the given value and length, creating the property if it
|
|
||||||
* does not already exist.
|
|
||||||
*
|
|
||||||
* This function may insert or delete data from the blob, and will
|
|
||||||
* therefore change the offsets of some existing nodes.
|
|
||||||
*
|
|
||||||
* returns:
|
|
||||||
* 0, on success
|
|
||||||
* -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
|
|
||||||
* contain the new property value
|
|
||||||
* -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
|
|
||||||
* -FDT_ERR_BADLAYOUT,
|
|
||||||
* -FDT_ERR_BADMAGIC,
|
|
||||||
* -FDT_ERR_BADVERSION,
|
|
||||||
* -FDT_ERR_BADSTATE,
|
|
||||||
* -FDT_ERR_BADSTRUCTURE,
|
|
||||||
* -FDT_ERR_BADLAYOUT,
|
|
||||||
* -FDT_ERR_TRUNCATED, standard meanings
|
|
||||||
*/
|
|
||||||
int fdt_setprop_namelen(void *fdt, int nodeoffset, const char *name,
|
|
||||||
int namelen, const void *val, int len);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fdt_setprop - create or change a property
|
* fdt_setprop - create or change a property
|
||||||
* @fdt: pointer to the device tree blob
|
* @fdt: pointer to the device tree blob
|
||||||
|
@ -1930,44 +1581,8 @@ int fdt_setprop_namelen(void *fdt, int nodeoffset, const char *name,
|
||||||
* -FDT_ERR_BADLAYOUT,
|
* -FDT_ERR_BADLAYOUT,
|
||||||
* -FDT_ERR_TRUNCATED, standard meanings
|
* -FDT_ERR_TRUNCATED, standard meanings
|
||||||
*/
|
*/
|
||||||
static inline int fdt_setprop(void *fdt, int nodeoffset, const char *name,
|
int fdt_setprop(void *fdt, int nodeoffset, const char *name,
|
||||||
const void *val, int len)
|
const void *val, int len);
|
||||||
{
|
|
||||||
return fdt_setprop_namelen(fdt, nodeoffset, name, strlen(name), val,
|
|
||||||
len);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* fdt_setprop_placeholder_namelen - allocate space for a property
|
|
||||||
* @fdt: pointer to the device tree blob
|
|
||||||
* @nodeoffset: offset of the node whose property to change
|
|
||||||
* @name: name of the property to change
|
|
||||||
* @namelen: length of the name
|
|
||||||
* @len: length of the property value
|
|
||||||
* @prop_data: return pointer to property data
|
|
||||||
*
|
|
||||||
* fdt_setprop_placeholder_namelen() allocates the named property in the given node.
|
|
||||||
* If the property exists it is resized. In either case a pointer to the
|
|
||||||
* property data is returned.
|
|
||||||
*
|
|
||||||
* This function may insert or delete data from the blob, and will
|
|
||||||
* therefore change the offsets of some existing nodes.
|
|
||||||
*
|
|
||||||
* returns:
|
|
||||||
* 0, on success
|
|
||||||
* -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
|
|
||||||
* contain the new property value
|
|
||||||
* -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
|
|
||||||
* -FDT_ERR_BADLAYOUT,
|
|
||||||
* -FDT_ERR_BADMAGIC,
|
|
||||||
* -FDT_ERR_BADVERSION,
|
|
||||||
* -FDT_ERR_BADSTATE,
|
|
||||||
* -FDT_ERR_BADSTRUCTURE,
|
|
||||||
* -FDT_ERR_BADLAYOUT,
|
|
||||||
* -FDT_ERR_TRUNCATED, standard meanings
|
|
||||||
*/
|
|
||||||
int fdt_setprop_placeholder_namelen(void *fdt, int nodeoffset, const char *name,
|
|
||||||
int namelen, int len, void **prop_data);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fdt_setprop_placeholder - allocate space for a property
|
* fdt_setprop_placeholder - allocate space for a property
|
||||||
|
@ -1977,7 +1592,7 @@ int fdt_setprop_placeholder_namelen(void *fdt, int nodeoffset, const char *name,
|
||||||
* @len: length of the property value
|
* @len: length of the property value
|
||||||
* @prop_data: return pointer to property data
|
* @prop_data: return pointer to property data
|
||||||
*
|
*
|
||||||
* fdt_setprop_placeholder() allocates the named property in the given node.
|
* fdt_setprop_placeholer() allocates the named property in the given node.
|
||||||
* If the property exists it is resized. In either case a pointer to the
|
* If the property exists it is resized. In either case a pointer to the
|
||||||
* property data is returned.
|
* property data is returned.
|
||||||
*
|
*
|
||||||
|
@ -1997,13 +1612,8 @@ int fdt_setprop_placeholder_namelen(void *fdt, int nodeoffset, const char *name,
|
||||||
* -FDT_ERR_BADLAYOUT,
|
* -FDT_ERR_BADLAYOUT,
|
||||||
* -FDT_ERR_TRUNCATED, standard meanings
|
* -FDT_ERR_TRUNCATED, standard meanings
|
||||||
*/
|
*/
|
||||||
static inline int fdt_setprop_placeholder(void *fdt, int nodeoffset,
|
int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name,
|
||||||
const char *name, int len,
|
int len, void **prop_data);
|
||||||
void **prop_data)
|
|
||||||
{
|
|
||||||
return fdt_setprop_placeholder_namelen(fdt, nodeoffset, name,
|
|
||||||
strlen(name), len, prop_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fdt_setprop_u32 - set a property to a 32-bit integer
|
* fdt_setprop_u32 - set a property to a 32-bit integer
|
||||||
|
@ -2077,14 +1687,8 @@ static inline int fdt_setprop_u64(void *fdt, int nodeoffset, const char *name,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fdt_setprop_cell - set a property to a single cell value
|
* fdt_setprop_cell - set a property to a single cell value
|
||||||
* @fdt: pointer to the device tree blob
|
|
||||||
* @nodeoffset: offset of the node whose property to change
|
|
||||||
* @name: name of the property to change
|
|
||||||
* @val: 32-bit integer value for the property (native endian)
|
|
||||||
*
|
*
|
||||||
* This is an alternative name for fdt_setprop_u32()
|
* This is an alternative name for fdt_setprop_u32()
|
||||||
*
|
|
||||||
* Return: 0 on success, negative libfdt error value otherwise.
|
|
||||||
*/
|
*/
|
||||||
static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
|
static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
|
||||||
uint32_t val)
|
uint32_t val)
|
||||||
|
@ -2123,38 +1727,6 @@ static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
|
||||||
#define fdt_setprop_string(fdt, nodeoffset, name, str) \
|
#define fdt_setprop_string(fdt, nodeoffset, name, str) \
|
||||||
fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
|
fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
|
||||||
|
|
||||||
/**
|
|
||||||
* fdt_setprop_namelen_string - set a property to a string value
|
|
||||||
* @fdt: pointer to the device tree blob
|
|
||||||
* @nodeoffset: offset of the node whose property to change
|
|
||||||
* @name: name of the property to change
|
|
||||||
* @namelen: number of characters of name to consider
|
|
||||||
* @str: string value for the property
|
|
||||||
*
|
|
||||||
* fdt_setprop_namelen_string() sets the value of the named property in the
|
|
||||||
* given node to the given string value (using the length of the
|
|
||||||
* string to determine the new length of the property), or creates a
|
|
||||||
* new property with that value if it does not already exist.
|
|
||||||
*
|
|
||||||
* This function may insert or delete data from the blob, and will
|
|
||||||
* therefore change the offsets of some existing nodes.
|
|
||||||
*
|
|
||||||
* returns:
|
|
||||||
* 0, on success
|
|
||||||
* -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
|
|
||||||
* contain the new property value
|
|
||||||
* -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
|
|
||||||
* -FDT_ERR_BADLAYOUT,
|
|
||||||
* -FDT_ERR_BADMAGIC,
|
|
||||||
* -FDT_ERR_BADVERSION,
|
|
||||||
* -FDT_ERR_BADSTATE,
|
|
||||||
* -FDT_ERR_BADSTRUCTURE,
|
|
||||||
* -FDT_ERR_BADLAYOUT,
|
|
||||||
* -FDT_ERR_TRUNCATED, standard meanings
|
|
||||||
*/
|
|
||||||
#define fdt_setprop_namelen_string(fdt, nodeoffset, name, namelen, str) \
|
|
||||||
fdt_setprop_namelen((fdt), (nodeoffset), (name), (namelen), (str), \
|
|
||||||
strlen(str) + 1)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fdt_setprop_empty - set a property to an empty value
|
* fdt_setprop_empty - set a property to an empty value
|
||||||
|
@ -2287,14 +1859,8 @@ static inline int fdt_appendprop_u64(void *fdt, int nodeoffset,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fdt_appendprop_cell - append a single cell value to a property
|
* fdt_appendprop_cell - append a single cell value to a property
|
||||||
* @fdt: pointer to the device tree blob
|
|
||||||
* @nodeoffset: offset of the node whose property to change
|
|
||||||
* @name: name of the property to change
|
|
||||||
* @val: 32-bit integer value to append to the property (native endian)
|
|
||||||
*
|
*
|
||||||
* This is an alternative name for fdt_appendprop_u32()
|
* This is an alternative name for fdt_appendprop_u32()
|
||||||
*
|
|
||||||
* Return: 0 on success, negative libfdt error value otherwise.
|
|
||||||
*/
|
*/
|
||||||
static inline int fdt_appendprop_cell(void *fdt, int nodeoffset,
|
static inline int fdt_appendprop_cell(void *fdt, int nodeoffset,
|
||||||
const char *name, uint32_t val)
|
const char *name, uint32_t val)
|
||||||
|
@ -2345,7 +1911,7 @@ static inline int fdt_appendprop_cell(void *fdt, int nodeoffset,
|
||||||
* address and size) to the value of the named property in the given
|
* address and size) to the value of the named property in the given
|
||||||
* node, or creates a new property with that value if it does not
|
* node, or creates a new property with that value if it does not
|
||||||
* already exist.
|
* already exist.
|
||||||
*
|
* If "name" is not specified, a default "reg" is used.
|
||||||
* Cell sizes are determined by parent's #address-cells and #size-cells.
|
* Cell sizes are determined by parent's #address-cells and #size-cells.
|
||||||
*
|
*
|
||||||
* This function may insert data into the blob, and will therefore
|
* This function may insert data into the blob, and will therefore
|
||||||
|
@ -2375,7 +1941,7 @@ int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset,
|
||||||
* @nodeoffset: offset of the node whose property to nop
|
* @nodeoffset: offset of the node whose property to nop
|
||||||
* @name: name of the property to nop
|
* @name: name of the property to nop
|
||||||
*
|
*
|
||||||
* fdt_delprop() will delete the given property.
|
* fdt_del_property() will delete the given property.
|
||||||
*
|
*
|
||||||
* This function will delete data from the blob, and will therefore
|
* This function will delete data from the blob, and will therefore
|
||||||
* change the offsets of some existing nodes.
|
* change the offsets of some existing nodes.
|
||||||
|
@ -2397,16 +1963,13 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name);
|
||||||
* fdt_add_subnode_namelen - creates a new node based on substring
|
* fdt_add_subnode_namelen - creates a new node based on substring
|
||||||
* @fdt: pointer to the device tree blob
|
* @fdt: pointer to the device tree blob
|
||||||
* @parentoffset: structure block offset of a node
|
* @parentoffset: structure block offset of a node
|
||||||
* @name: name of the subnode to create
|
* @name: name of the subnode to locate
|
||||||
* @namelen: number of characters of name to consider
|
* @namelen: number of characters of name to consider
|
||||||
*
|
*
|
||||||
* Identical to fdt_add_subnode(), but use only the first @namelen
|
* Identical to fdt_add_subnode(), but use only the first namelen
|
||||||
* characters of @name as the name of the new node. This is useful for
|
* characters of name as the name of the new node. This is useful for
|
||||||
* creating subnodes based on a portion of a larger string, such as a
|
* creating subnodes based on a portion of a larger string, such as a
|
||||||
* full path.
|
* full path.
|
||||||
*
|
|
||||||
* Return: structure block offset of the created subnode (>=0),
|
|
||||||
* negative libfdt error value otherwise
|
|
||||||
*/
|
*/
|
||||||
#ifndef SWIG /* Not available in Python */
|
#ifndef SWIG /* Not available in Python */
|
||||||
int fdt_add_subnode_namelen(void *fdt, int parentoffset,
|
int fdt_add_subnode_namelen(void *fdt, int parentoffset,
|
||||||
|
@ -2425,9 +1988,10 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
|
||||||
*
|
*
|
||||||
* This function will insert data into the blob, and will therefore
|
* This function will insert data into the blob, and will therefore
|
||||||
* change the offsets of some existing nodes.
|
* change the offsets of some existing nodes.
|
||||||
*
|
|
||||||
* returns:
|
* returns:
|
||||||
* structure block offset of the created subnode (>=0), on success
|
* structure block offset of the created nodeequested subnode (>=0), on
|
||||||
|
* success
|
||||||
* -FDT_ERR_NOTFOUND, if the requested subnode does not exist
|
* -FDT_ERR_NOTFOUND, if the requested subnode does not exist
|
||||||
* -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE
|
* -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE
|
||||||
* tag
|
* tag
|
||||||
|
@ -2482,7 +2046,7 @@ int fdt_del_node(void *fdt, int nodeoffset);
|
||||||
* returns:
|
* returns:
|
||||||
* 0, on success
|
* 0, on success
|
||||||
* -FDT_ERR_NOSPACE, there's not enough space in the base device tree
|
* -FDT_ERR_NOSPACE, there's not enough space in the base device tree
|
||||||
* -FDT_ERR_NOTFOUND, the overlay points to some nonexistent nodes or
|
* -FDT_ERR_NOTFOUND, the overlay points to some inexistant nodes or
|
||||||
* properties in the base DT
|
* properties in the base DT
|
||||||
* -FDT_ERR_BADPHANDLE,
|
* -FDT_ERR_BADPHANDLE,
|
||||||
* -FDT_ERR_BADOVERLAY,
|
* -FDT_ERR_BADOVERLAY,
|
||||||
|
@ -2499,42 +2063,10 @@ int fdt_del_node(void *fdt, int nodeoffset);
|
||||||
*/
|
*/
|
||||||
int fdt_overlay_apply(void *fdt, void *fdto);
|
int fdt_overlay_apply(void *fdt, void *fdto);
|
||||||
|
|
||||||
/**
|
|
||||||
* fdt_overlay_target_offset - retrieves the offset of a fragment's target
|
|
||||||
* @fdt: Base device tree blob
|
|
||||||
* @fdto: Device tree overlay blob
|
|
||||||
* @fragment_offset: node offset of the fragment in the overlay
|
|
||||||
* @pathp: pointer which receives the path of the target (or NULL)
|
|
||||||
*
|
|
||||||
* fdt_overlay_target_offset() retrieves the target offset in the base
|
|
||||||
* device tree of a fragment, no matter how the actual targeting is
|
|
||||||
* done (through a phandle or a path)
|
|
||||||
*
|
|
||||||
* returns:
|
|
||||||
* the targeted node offset in the base device tree
|
|
||||||
* Negative error code on error
|
|
||||||
*/
|
|
||||||
int fdt_overlay_target_offset(const void *fdt, const void *fdto,
|
|
||||||
int fragment_offset, char const **pathp);
|
|
||||||
|
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
/* Debugging / informational functions */
|
/* Debugging / informational functions */
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
|
|
||||||
/**
|
|
||||||
* fdt_strerror - return string description of error code
|
|
||||||
* @errval: Error code returned by a libfdt function
|
|
||||||
*
|
|
||||||
* fdt_strerror() returns a string description of the error code passed
|
|
||||||
* in @errval.
|
|
||||||
*
|
|
||||||
* returns:
|
|
||||||
* pointer to a string describing the error code
|
|
||||||
*/
|
|
||||||
const char *fdt_strerror(int errval);
|
const char *fdt_strerror(int errval);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LIBFDT_H */
|
#endif /* LIBFDT_H */
|
||||||
|
|
|
@ -66,4 +66,31 @@ static inline fdt64_t cpu_to_fdt64(uint64_t x)
|
||||||
#undef CPU_TO_FDT16
|
#undef CPU_TO_FDT16
|
||||||
#undef EXTRACT_BYTE
|
#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 */
|
||||||
|
|
|
@ -20,15 +20,7 @@ int32_t fdt_ro_probe_(const void *fdt);
|
||||||
|
|
||||||
int fdt_check_node_offset_(const void *fdt, int offset);
|
int fdt_check_node_offset_(const void *fdt, int offset);
|
||||||
int fdt_check_prop_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);
|
||||||
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);
|
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)
|
||||||
|
@ -54,25 +46,6 @@ static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n)
|
||||||
return (void *)(uintptr_t)fdt_mem_rsv_(fdt, n);
|
return (void *)(uintptr_t)fdt_mem_rsv_(fdt, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Internal helpers to access structural elements of the device tree
|
|
||||||
* blob (rather than for example reading integers from within property
|
|
||||||
* values). We assume that we are either given a naturally aligned
|
|
||||||
* address for the platform or if we are not, we are on a platform
|
|
||||||
* where unaligned memory reads will be handled in a graceful manner.
|
|
||||||
* If not the external helpers fdtXX_ld() from libfdt.h can be used
|
|
||||||
* instead.
|
|
||||||
*/
|
|
||||||
static inline uint32_t fdt32_ld_(const fdt32_t *p)
|
|
||||||
{
|
|
||||||
return fdt32_to_cpu(*p);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint64_t fdt64_ld_(const fdt64_t *p)
|
|
||||||
{
|
|
||||||
return fdt64_to_cpu(*p);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define FDT_SW_MAGIC (~FDT_MAGIC)
|
#define FDT_SW_MAGIC (~FDT_MAGIC)
|
||||||
|
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
|
|
|
@ -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
|
|
|
@ -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"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -43,7 +43,6 @@ LIBFDT_1.2 {
|
||||||
fdt_add_mem_rsv;
|
fdt_add_mem_rsv;
|
||||||
fdt_del_mem_rsv;
|
fdt_del_mem_rsv;
|
||||||
fdt_set_name;
|
fdt_set_name;
|
||||||
fdt_setprop_namelen;
|
|
||||||
fdt_setprop;
|
fdt_setprop;
|
||||||
fdt_delprop;
|
fdt_delprop;
|
||||||
fdt_add_subnode_namelen;
|
fdt_add_subnode_namelen;
|
||||||
|
@ -72,16 +71,12 @@ LIBFDT_1.2 {
|
||||||
fdt_find_max_phandle;
|
fdt_find_max_phandle;
|
||||||
fdt_generate_phandle;
|
fdt_generate_phandle;
|
||||||
fdt_check_full;
|
fdt_check_full;
|
||||||
fdt_setprop_placeholder_namelen;
|
|
||||||
fdt_setprop_placeholder;
|
fdt_setprop_placeholder;
|
||||||
fdt_property_placeholder;
|
fdt_property_placeholder;
|
||||||
fdt_header_size_;
|
fdt_header_size_;
|
||||||
fdt_appendprop_addrrange;
|
fdt_appendprop_addrrange;
|
||||||
fdt_setprop_inplace_namelen_partial;
|
fdt_setprop_inplace_namelen_partial;
|
||||||
fdt_create_with_flags;
|
fdt_create_with_flags;
|
||||||
fdt_overlay_target_offset;
|
|
||||||
fdt_get_symbol;
|
|
||||||
fdt_get_symbol_namelen;
|
|
||||||
local:
|
local:
|
||||||
*;
|
*;
|
||||||
};
|
};
|
||||||
|
|
223
livetree.c
223
livetree.c
|
@ -36,27 +36,27 @@ void delete_labels(struct label **labels)
|
||||||
label->deleted = 1;
|
label->deleted = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct property *build_property(const char *name, struct data val,
|
struct property *build_property(char *name, struct data val,
|
||||||
struct srcpos *srcpos)
|
struct srcpos *srcpos)
|
||||||
{
|
{
|
||||||
struct property *new = xmalloc(sizeof(*new));
|
struct property *new = xmalloc(sizeof(*new));
|
||||||
|
|
||||||
memset(new, 0, sizeof(*new));
|
memset(new, 0, sizeof(*new));
|
||||||
|
|
||||||
new->name = xstrdup(name);
|
new->name = name;
|
||||||
new->val = val;
|
new->val = val;
|
||||||
new->srcpos = srcpos_copy(srcpos);
|
new->srcpos = srcpos_copy(srcpos);
|
||||||
|
|
||||||
return new;
|
return new;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct property *build_property_delete(const char *name)
|
struct property *build_property_delete(char *name)
|
||||||
{
|
{
|
||||||
struct property *new = xmalloc(sizeof(*new));
|
struct property *new = xmalloc(sizeof(*new));
|
||||||
|
|
||||||
memset(new, 0, sizeof(*new));
|
memset(new, 0, sizeof(*new));
|
||||||
|
|
||||||
new->name = xstrdup(name);
|
new->name = name;
|
||||||
new->deleted = 1;
|
new->deleted = 1;
|
||||||
|
|
||||||
return new;
|
return new;
|
||||||
|
@ -116,11 +116,11 @@ struct node *build_node_delete(struct srcpos *srcpos)
|
||||||
return new;
|
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);
|
assert(node->name == NULL);
|
||||||
|
|
||||||
node->name = xstrdup(name);
|
node->name = name;
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
@ -174,7 +174,7 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
|
||||||
|
|
||||||
old_prop->val = new_prop->val;
|
old_prop->val = new_prop->val;
|
||||||
old_prop->deleted = 0;
|
old_prop->deleted = 0;
|
||||||
srcpos_free(old_prop->srcpos);
|
free(old_prop->srcpos);
|
||||||
old_prop->srcpos = new_prop->srcpos;
|
old_prop->srcpos = new_prop->srcpos;
|
||||||
free(new_prop);
|
free(new_prop);
|
||||||
new_prop = NULL;
|
new_prop = NULL;
|
||||||
|
@ -250,7 +250,6 @@ struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref)
|
||||||
name_node(new_node, "__overlay__");
|
name_node(new_node, "__overlay__");
|
||||||
node = build_node(p, new_node, NULL);
|
node = build_node(p, new_node, NULL);
|
||||||
name_node(node, name);
|
name_node(node, name);
|
||||||
free(name);
|
|
||||||
|
|
||||||
add_child(dt, node);
|
add_child(dt, node);
|
||||||
return dt;
|
return dt;
|
||||||
|
@ -340,73 +339,20 @@ void append_to_property(struct node *node,
|
||||||
char *name, const void *data, int len,
|
char *name, const void *data, int len,
|
||||||
enum markertype type)
|
enum markertype type)
|
||||||
{
|
{
|
||||||
struct property *p;
|
struct data d;
|
||||||
|
|
||||||
p = get_property(node, name);
|
|
||||||
if (!p) {
|
|
||||||
p = build_property(name, empty_data, NULL);
|
|
||||||
add_property(node, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
p->val = data_add_marker(p->val, type, name);
|
|
||||||
p->val = data_append_data(p->val, data, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int append_unique_str_to_property(struct node *node,
|
|
||||||
char *name, const char *data, int len)
|
|
||||||
{
|
|
||||||
struct property *p;
|
struct property *p;
|
||||||
|
|
||||||
p = get_property(node, name);
|
p = get_property(node, name);
|
||||||
if (p) {
|
if (p) {
|
||||||
const char *s;
|
d = data_add_marker(p->val, type, name);
|
||||||
|
d = data_append_data(d, data, len);
|
||||||
if (p->val.len && p->val.val[p->val.len - 1] != '\0')
|
p->val = d;
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
p = build_property(name, empty_data, NULL);
|
d = data_add_marker(empty_data, type, name);
|
||||||
|
d = data_append_data(d, data, len);
|
||||||
|
p = build_property(name, d, NULL);
|
||||||
add_property(node, p);
|
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)
|
struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
|
||||||
|
@ -492,9 +438,9 @@ cell_t propval_cell(struct property *prop)
|
||||||
return fdt32_to_cpu(*((fdt32_t *)prop->val.val));
|
return fdt32_to_cpu(*((fdt32_t *)prop->val.val));
|
||||||
}
|
}
|
||||||
|
|
||||||
cell_t propval_cell_n(struct property *prop, unsigned int n)
|
cell_t propval_cell_n(struct property *prop, int n)
|
||||||
{
|
{
|
||||||
assert(prop->val.len / sizeof(cell_t) > n);
|
assert(prop->val.len / sizeof(cell_t) >= n);
|
||||||
return fdt32_to_cpu(*((fdt32_t *)prop->val.val + n));
|
return fdt32_to_cpu(*((fdt32_t *)prop->val.val + n));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -557,7 +503,7 @@ struct node *get_subnode(struct node *node, const char *nodename)
|
||||||
struct node *child;
|
struct node *child;
|
||||||
|
|
||||||
for_each_child(node, child)
|
for_each_child(node, child)
|
||||||
if (streq(child->name, nodename) && !child->deleted)
|
if (streq(child->name, nodename))
|
||||||
return child;
|
return child;
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -580,7 +526,7 @@ struct node *get_node_by_path(struct node *tree, const char *path)
|
||||||
p = strchr(path, '/');
|
p = strchr(path, '/');
|
||||||
|
|
||||||
for_each_child(tree, child) {
|
for_each_child(tree, child) {
|
||||||
if (p && strprefixeq(path, (size_t)(p - path), child->name))
|
if (p && strprefixeq(path, p - path, child->name))
|
||||||
return get_node_by_path(child, p+1);
|
return get_node_by_path(child, p+1);
|
||||||
else if (!p && streq(path, child->name))
|
else if (!p && streq(path, child->name))
|
||||||
return child;
|
return child;
|
||||||
|
@ -613,7 +559,7 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
|
||||||
{
|
{
|
||||||
struct node *child, *node;
|
struct node *child, *node;
|
||||||
|
|
||||||
if (!phandle_is_valid(phandle)) {
|
if ((phandle == 0) || (phandle == -1)) {
|
||||||
assert(generate_fixups);
|
assert(generate_fixups);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -635,62 +581,20 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
|
||||||
|
|
||||||
struct node *get_node_by_ref(struct node *tree, const char *ref)
|
struct node *get_node_by_ref(struct node *tree, const char *ref)
|
||||||
{
|
{
|
||||||
struct node *target = tree;
|
|
||||||
const char *label = NULL, *path = NULL;
|
|
||||||
|
|
||||||
if (streq(ref, "/"))
|
if (streq(ref, "/"))
|
||||||
return tree;
|
return tree;
|
||||||
|
else if (ref[0] == '/')
|
||||||
if (ref[0] == '/')
|
return get_node_by_path(tree, ref);
|
||||||
path = ref;
|
|
||||||
else
|
else
|
||||||
label = ref;
|
return get_node_by_label(tree, 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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cell_t get_node_phandle(struct node *root, struct node *node)
|
cell_t get_node_phandle(struct node *root, struct node *node)
|
||||||
{
|
{
|
||||||
static cell_t phandle = 1; /* FIXME: ick, static local */
|
static cell_t phandle = 1; /* FIXME: ick, static local */
|
||||||
|
struct data d = empty_data;
|
||||||
|
|
||||||
if (phandle_is_valid(node->phandle))
|
if ((node->phandle != 0) && (node->phandle != -1))
|
||||||
return node->phandle;
|
return node->phandle;
|
||||||
|
|
||||||
while (get_node_by_phandle(root, phandle))
|
while (get_node_by_phandle(root, phandle))
|
||||||
|
@ -698,8 +602,16 @@ cell_t get_node_phandle(struct node *root, struct node *node)
|
||||||
|
|
||||||
node->phandle = phandle;
|
node->phandle = phandle;
|
||||||
|
|
||||||
add_phandle_property(node, "linux,phandle", PHANDLE_LEGACY);
|
d = data_add_marker(d, TYPE_UINT32, NULL);
|
||||||
add_phandle_property(node, "phandle", PHANDLE_EPAPR);
|
d = data_append_cell(d, phandle);
|
||||||
|
|
||||||
|
if (!get_property(node, "linux,phandle")
|
||||||
|
&& (phandle_format & PHANDLE_LEGACY))
|
||||||
|
add_property(node, build_property("linux,phandle", d, NULL));
|
||||||
|
|
||||||
|
if (!get_property(node, "phandle")
|
||||||
|
&& (phandle_format & PHANDLE_EPAPR))
|
||||||
|
add_property(node, build_property("phandle", d, NULL));
|
||||||
|
|
||||||
/* If the node *does* have a phandle property, we must
|
/* If the node *does* have a phandle property, we must
|
||||||
* be dealing with a self-referencing phandle, which will be
|
* be dealing with a self-referencing phandle, which will be
|
||||||
|
@ -869,18 +781,18 @@ void sort_tree(struct dt_info *dti)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* utility helper to avoid code duplication */
|
/* 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;
|
struct node *node;
|
||||||
|
|
||||||
node = build_node(NULL, NULL, NULL);
|
node = build_node(NULL, NULL, NULL);
|
||||||
name_node(node, name);
|
name_node(node, xstrdup(name));
|
||||||
add_child(parent, node);
|
add_child(parent, node);
|
||||||
|
|
||||||
return 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;
|
struct node *an;
|
||||||
|
|
||||||
|
@ -971,36 +883,27 @@ static bool any_fixup_tree(struct dt_info *dti, struct node *node)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int add_fixup_entry(struct dt_info *dti, struct node *fn,
|
static void add_fixup_entry(struct dt_info *dti, struct node *fn,
|
||||||
struct node *node, struct property *prop,
|
struct node *node, struct property *prop,
|
||||||
struct marker *m)
|
struct marker *m)
|
||||||
{
|
{
|
||||||
char *entry;
|
char *entry;
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* m->ref can only be a REF_PHANDLE, but check anyway */
|
/* m->ref can only be a REF_PHANDLE, but check anyway */
|
||||||
assert(m->type == REF_PHANDLE);
|
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 */
|
/* there shouldn't be any ':' in the arguments */
|
||||||
if (strchr(node->fullpath, ':') || strchr(prop->name, ':'))
|
if (strchr(node->fullpath, ':') || strchr(prop->name, ':'))
|
||||||
die("arguments should not contain ':'\n");
|
die("arguments should not contain ':'\n");
|
||||||
|
|
||||||
xasprintf(&entry, "%s:%s:%u",
|
xasprintf(&entry, "%s:%s:%u",
|
||||||
node->fullpath, prop->name, m->offset);
|
node->fullpath, prop->name, m->offset);
|
||||||
ret = append_unique_str_to_property(fn, m->ref, entry, strlen(entry) + 1);
|
append_to_property(fn, m->ref, entry, strlen(entry) + 1, TYPE_STRING);
|
||||||
|
|
||||||
free(entry);
|
free(entry);
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int generate_fixups_tree_internal(struct dt_info *dti,
|
static void generate_fixups_tree_internal(struct dt_info *dti,
|
||||||
struct node *fn,
|
struct node *fn,
|
||||||
struct node *node)
|
struct node *node)
|
||||||
{
|
{
|
||||||
|
@ -1009,23 +912,18 @@ static int generate_fixups_tree_internal(struct dt_info *dti,
|
||||||
struct property *prop;
|
struct property *prop;
|
||||||
struct marker *m;
|
struct marker *m;
|
||||||
struct node *refnode;
|
struct node *refnode;
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
for_each_property(node, prop) {
|
for_each_property(node, prop) {
|
||||||
m = prop->val.markers;
|
m = prop->val.markers;
|
||||||
for_each_marker_of_type(m, REF_PHANDLE) {
|
for_each_marker_of_type(m, REF_PHANDLE) {
|
||||||
refnode = get_node_by_ref(dt, m->ref);
|
refnode = get_node_by_ref(dt, m->ref);
|
||||||
if (!refnode)
|
if (!refnode)
|
||||||
if (add_fixup_entry(dti, fn, node, prop, m))
|
add_fixup_entry(dti, fn, node, prop, m);
|
||||||
ret = -1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for_each_child(node, c)
|
for_each_child(node, c)
|
||||||
if (generate_fixups_tree_internal(dti, fn, c))
|
generate_fixups_tree_internal(dti, fn, c);
|
||||||
ret = -1;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool any_local_fixup_tree(struct dt_info *dti, struct node *node)
|
static bool any_local_fixup_tree(struct dt_info *dti, struct node *node)
|
||||||
|
@ -1050,7 +948,7 @@ static bool any_local_fixup_tree(struct dt_info *dti, struct node *node)
|
||||||
return false;
|
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 node *lfn, struct node *node,
|
||||||
struct property *prop, struct marker *m,
|
struct property *prop, struct marker *m,
|
||||||
struct node *refnode)
|
struct node *refnode)
|
||||||
|
@ -1075,16 +973,18 @@ static int add_local_fixup_entry(struct dt_info *dti,
|
||||||
/* walk the path components creating nodes if they don't exist */
|
/* walk the path components creating nodes if they don't exist */
|
||||||
for (wn = lfn, i = 1; i < depth; i++, wn = nwn) {
|
for (wn = lfn, i = 1; i < depth; i++, wn = nwn) {
|
||||||
/* if no node exists, create it */
|
/* 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);
|
free(compp);
|
||||||
|
|
||||||
value_32 = cpu_to_fdt32(m->offset);
|
value_32 = cpu_to_fdt32(m->offset);
|
||||||
return append_unique_u32_to_property(wn, prop->name, value_32);
|
append_to_property(wn, prop->name, &value_32, sizeof(value_32), TYPE_UINT32);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int generate_local_fixups_tree_internal(struct dt_info *dti,
|
static void generate_local_fixups_tree_internal(struct dt_info *dti,
|
||||||
struct node *lfn,
|
struct node *lfn,
|
||||||
struct node *node)
|
struct node *node)
|
||||||
{
|
{
|
||||||
|
@ -1093,26 +993,21 @@ static int generate_local_fixups_tree_internal(struct dt_info *dti,
|
||||||
struct property *prop;
|
struct property *prop;
|
||||||
struct marker *m;
|
struct marker *m;
|
||||||
struct node *refnode;
|
struct node *refnode;
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
for_each_property(node, prop) {
|
for_each_property(node, prop) {
|
||||||
m = prop->val.markers;
|
m = prop->val.markers;
|
||||||
for_each_marker_of_type(m, REF_PHANDLE) {
|
for_each_marker_of_type(m, REF_PHANDLE) {
|
||||||
refnode = get_node_by_ref(dt, m->ref);
|
refnode = get_node_by_ref(dt, m->ref);
|
||||||
if (refnode)
|
if (refnode)
|
||||||
if (add_local_fixup_entry(dti, lfn, node, prop, m, refnode))
|
add_local_fixup_entry(dti, lfn, node, prop, m, refnode);
|
||||||
ret = -1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for_each_child(node, c)
|
for_each_child(node, c)
|
||||||
if (generate_local_fixups_tree_internal(dti, lfn, c))
|
generate_local_fixups_tree_internal(dti, lfn, c);
|
||||||
ret = -1;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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))
|
if (!any_label_tree(dti, dti->dt))
|
||||||
return;
|
return;
|
||||||
|
@ -1120,22 +1015,18 @@ void generate_label_tree(struct dt_info *dti, const char *name, bool allocph)
|
||||||
dti->dt, 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))
|
if (!any_fixup_tree(dti, dti->dt))
|
||||||
return;
|
return;
|
||||||
if (generate_fixups_tree_internal(dti, build_root_node(dti->dt, name), dti->dt))
|
generate_fixups_tree_internal(dti, build_root_node(dti->dt, name),
|
||||||
fprintf(stderr,
|
dti->dt);
|
||||||
"Warning: Preexisting data in %s malformed, some content could not be added.\n",
|
|
||||||
name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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))
|
if (!any_local_fixup_tree(dti, dti->dt))
|
||||||
return;
|
return;
|
||||||
if (generate_local_fixups_tree_internal(dti, build_root_node(dti->dt, name), dti->dt))
|
generate_local_fixups_tree_internal(dti, build_root_node(dti->dt, name),
|
||||||
fprintf(stderr,
|
dti->dt);
|
||||||
"Warning: Preexisting data in %s malformed, some content could not be added.\n",
|
|
||||||
name);
|
|
||||||
}
|
}
|
||||||
|
|
131
meson.build
131
meson.build
|
@ -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
|
|
|
@ -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')
|
|
30
pylibfdt/Makefile.pylibfdt
Normal file
30
pylibfdt/Makefile.pylibfdt
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
|
||||||
|
# Makefile.pylibfdt
|
||||||
|
#
|
||||||
|
|
||||||
|
PYLIBFDT_srcs = $(PYLIBFDT_dir)/libfdt.i
|
||||||
|
PYMODULE = $(PYLIBFDT_dir)/_libfdt.so
|
||||||
|
PYLIBFDT_CLEANFILES_L = libfdt_wrap.c libfdt.py *.pyc *.so
|
||||||
|
PYLIBFDT_CLEANFILES = $(PYLIBFDT_CLEANFILES_L:%=$(PYLIBFDT_dir)/%)
|
||||||
|
PYLIBFDT_CLEANDIRS_L = build __pycache__
|
||||||
|
PYLIBFDT_CLEANDIRS = $(PYLIBFDT_CLEANDIRS_L:%=$(PYLIBFDT_dir)/%)
|
||||||
|
|
||||||
|
SETUP = $(PYLIBFDT_dir)/setup.py
|
||||||
|
SETUPFLAGS =
|
||||||
|
|
||||||
|
ifndef V
|
||||||
|
SETUPFLAGS += --quiet
|
||||||
|
endif
|
||||||
|
|
||||||
|
$(PYMODULE): $(PYLIBFDT_srcs) $(LIBFDT_archive) $(SETUP) $(VERSION_FILE)
|
||||||
|
@$(VECHO) PYMOD $@
|
||||||
|
$(PYTHON) $(SETUP) $(SETUPFLAGS) build_ext --build-lib=../$(PYLIBFDT_dir)
|
||||||
|
|
||||||
|
install_pylibfdt: $(PYMODULE)
|
||||||
|
@$(VECHO) INSTALL-PYLIB
|
||||||
|
$(PYTHON) $(SETUP) $(SETUPFLAGS) install --prefix=$(PREFIX)
|
||||||
|
|
||||||
|
pylibfdt_clean:
|
||||||
|
@$(VECHO) CLEAN "(pylibfdt)"
|
||||||
|
rm -f $(PYLIBFDT_CLEANFILES)
|
||||||
|
rm -rf $(PYLIBFDT_CLEANDIRS)
|
|
@ -114,14 +114,11 @@ def check_err_null(val, quiet=()):
|
||||||
FdtException if val indicates an error was reported and the error
|
FdtException if val indicates an error was reported and the error
|
||||||
is not in @quiet.
|
is not in @quiet.
|
||||||
"""
|
"""
|
||||||
# Compatibility for SWIG v4.2 and earlier. SWIG 4.2 would drop the first
|
# Normally a list is returned which contains the data and its length.
|
||||||
# item from the list if it was None, returning only the second item.
|
# If we get just an integer error code, it means the function failed.
|
||||||
if not isinstance(val, list):
|
if not isinstance(val, list):
|
||||||
val = [None, val]
|
if -val not in quiet:
|
||||||
|
raise FdtException(val)
|
||||||
if val[0] is None:
|
|
||||||
if -val[1] not in quiet:
|
|
||||||
raise FdtException(val[1])
|
|
||||||
return val
|
return val
|
||||||
|
|
||||||
class FdtRo(object):
|
class FdtRo(object):
|
||||||
|
@ -162,7 +159,7 @@ class FdtRo(object):
|
||||||
quiet: Errors to ignore (empty to raise on all errors)
|
quiet: Errors to ignore (empty to raise on all errors)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Tuple:
|
Typle:
|
||||||
Offset of the next node, if any, else a -ve error
|
Offset of the next node, if any, else a -ve error
|
||||||
Depth of the returned node, if any, else undefined
|
Depth of the returned node, if any, else undefined
|
||||||
|
|
||||||
|
@ -298,9 +295,7 @@ class FdtRo(object):
|
||||||
Returns:
|
Returns:
|
||||||
Number of memory reserve-map records
|
Number of memory reserve-map records
|
||||||
"""
|
"""
|
||||||
val = fdt_get_mem_rsv(self._fdt, index)
|
return check_err(fdt_get_mem_rsv(self._fdt, index), quiet)
|
||||||
check_err(val[0], quiet)
|
|
||||||
return val[1:]
|
|
||||||
|
|
||||||
def subnode_offset(self, parentoffset, name, quiet=()):
|
def subnode_offset(self, parentoffset, name, quiet=()):
|
||||||
"""Get the offset of a named subnode
|
"""Get the offset of a named subnode
|
||||||
|
@ -398,8 +393,8 @@ class FdtRo(object):
|
||||||
"""
|
"""
|
||||||
pdata = check_err_null(
|
pdata = check_err_null(
|
||||||
fdt_get_property_by_offset(self._fdt, prop_offset), quiet)
|
fdt_get_property_by_offset(self._fdt, prop_offset), quiet)
|
||||||
if pdata[0] is None:
|
if isinstance(pdata, (int)):
|
||||||
return pdata[1]
|
return pdata
|
||||||
return Property(pdata[0], pdata[1])
|
return Property(pdata[0], pdata[1])
|
||||||
|
|
||||||
def getprop(self, nodeoffset, prop_name, quiet=()):
|
def getprop(self, nodeoffset, prop_name, quiet=()):
|
||||||
|
@ -420,39 +415,10 @@ class FdtRo(object):
|
||||||
"""
|
"""
|
||||||
pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name),
|
pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name),
|
||||||
quiet)
|
quiet)
|
||||||
if pdata[0] is None:
|
if isinstance(pdata, (int)):
|
||||||
return pdata[1]
|
return pdata
|
||||||
return Property(prop_name, bytearray(pdata[0]))
|
return Property(prop_name, bytearray(pdata[0]))
|
||||||
|
|
||||||
def hasprop(self, nodeoffset, prop_name, quiet=()):
|
|
||||||
"""Check if a node has a property
|
|
||||||
|
|
||||||
This can be used to check boolean properties
|
|
||||||
|
|
||||||
Args:
|
|
||||||
nodeoffset: Node offset containing property to check
|
|
||||||
prop_name: Name of property to check
|
|
||||||
quiet: Errors to ignore (empty to raise on all errors). Note that
|
|
||||||
NOTFOUND is added internally by this function so need not be
|
|
||||||
provided
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
True if the property exists in the node, else False. If an error
|
|
||||||
other than -NOTFOUND is returned by fdt_getprop() then the error
|
|
||||||
is return (-ve integer)
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
FdtError if any error occurs other than NOTFOUND (e.g. the
|
|
||||||
nodeoffset is invalid)
|
|
||||||
"""
|
|
||||||
pdata = check_err_null(fdt_getprop(self._fdt, nodeoffset, prop_name),
|
|
||||||
quiet + (NOTFOUND,))
|
|
||||||
if pdata[0] is None:
|
|
||||||
if pdata[1] == -NOTFOUND:
|
|
||||||
return False
|
|
||||||
return pdata[1]
|
|
||||||
return True
|
|
||||||
|
|
||||||
def get_phandle(self, nodeoffset):
|
def get_phandle(self, nodeoffset):
|
||||||
"""Get the phandle of a node
|
"""Get the phandle of a node
|
||||||
|
|
||||||
|
@ -477,29 +443,6 @@ class FdtRo(object):
|
||||||
"""
|
"""
|
||||||
return fdt_get_alias(self._fdt, name)
|
return fdt_get_alias(self._fdt, name)
|
||||||
|
|
||||||
def get_path(self, nodeoffset, size_hint=1024, quiet=()):
|
|
||||||
"""Get the full path of a node
|
|
||||||
|
|
||||||
Args:
|
|
||||||
nodeoffset: Node offset to check
|
|
||||||
size_hint: Hint for size of returned string
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Full path to the node
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
FdtException if an error occurs
|
|
||||||
"""
|
|
||||||
while True:
|
|
||||||
ret, path = fdt_get_path(self._fdt, nodeoffset, size_hint)
|
|
||||||
if ret == -NOSPACE:
|
|
||||||
size_hint *= 2
|
|
||||||
continue
|
|
||||||
err = check_err(ret, quiet)
|
|
||||||
if err:
|
|
||||||
return err
|
|
||||||
return path
|
|
||||||
|
|
||||||
def parent_offset(self, nodeoffset, quiet=()):
|
def parent_offset(self, nodeoffset, quiet=()):
|
||||||
"""Get the offset of a node's parent
|
"""Get the offset of a node's parent
|
||||||
|
|
||||||
|
@ -639,32 +582,6 @@ class Fdt(FdtRo):
|
||||||
return check_err(fdt_setprop(self._fdt, nodeoffset, prop_name, val,
|
return check_err(fdt_setprop(self._fdt, nodeoffset, prop_name, val,
|
||||||
len(val)), quiet)
|
len(val)), quiet)
|
||||||
|
|
||||||
def setprop_bool(self, nodeoffset, prop_name, val, quiet=()):
|
|
||||||
"""Set the boolean value of a property
|
|
||||||
|
|
||||||
Either:
|
|
||||||
adds the property if not already present; or
|
|
||||||
deletes the property if present
|
|
||||||
|
|
||||||
Args:
|
|
||||||
nodeoffset: Node offset containing the property to create/delete
|
|
||||||
prop_name: Name of property
|
|
||||||
val: Boolean value to write (i.e. True or False)
|
|
||||||
quiet: Errors to ignore (empty to raise on all errors)
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Error code, or 0 if OK
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
FdtException if no parent found or other error occurs
|
|
||||||
"""
|
|
||||||
exists = self.hasprop(nodeoffset, prop_name, quiet)
|
|
||||||
if val != exists:
|
|
||||||
if val:
|
|
||||||
return self.setprop(nodeoffset, prop_name, b'', quiet=quiet)
|
|
||||||
else:
|
|
||||||
return self.delprop(nodeoffset, prop_name, quiet=quiet)
|
|
||||||
|
|
||||||
def setprop_u32(self, nodeoffset, prop_name, val, quiet=()):
|
def setprop_u32(self, nodeoffset, prop_name, val, quiet=()):
|
||||||
"""Set the value of a property
|
"""Set the value of a property
|
||||||
|
|
||||||
|
@ -799,21 +716,6 @@ class Property(bytearray):
|
||||||
def as_int64(self):
|
def as_int64(self):
|
||||||
return self.as_cell('q')
|
return self.as_cell('q')
|
||||||
|
|
||||||
def as_list(self, fmt):
|
|
||||||
return list(map(lambda x: x[0], struct.iter_unpack('>' + fmt, self)))
|
|
||||||
|
|
||||||
def as_uint32_list(self):
|
|
||||||
return self.as_list('L')
|
|
||||||
|
|
||||||
def as_int32_list(self):
|
|
||||||
return self.as_list('l')
|
|
||||||
|
|
||||||
def as_uint64_list(self):
|
|
||||||
return self.as_list('Q')
|
|
||||||
|
|
||||||
def as_int64_list(self):
|
|
||||||
return self.as_list('q')
|
|
||||||
|
|
||||||
def as_str(self):
|
def as_str(self):
|
||||||
"""Unicode is supported by decoding from UTF-8"""
|
"""Unicode is supported by decoding from UTF-8"""
|
||||||
if self[-1] != 0:
|
if self[-1] != 0:
|
||||||
|
@ -822,13 +724,6 @@ class Property(bytearray):
|
||||||
raise ValueError('Property contains embedded nul characters')
|
raise ValueError('Property contains embedded nul characters')
|
||||||
return self[:-1].decode('utf-8')
|
return self[:-1].decode('utf-8')
|
||||||
|
|
||||||
def as_stringlist(self):
|
|
||||||
"""Unicode is supported by decoding from UTF-8"""
|
|
||||||
if self[-1] != 0:
|
|
||||||
raise ValueError('Property lacks nul termination')
|
|
||||||
parts = self[:-1].split(b'\x00')
|
|
||||||
return list(map(lambda x: x.decode('utf-8'), parts))
|
|
||||||
|
|
||||||
|
|
||||||
class FdtSw(FdtRo):
|
class FdtSw(FdtRo):
|
||||||
"""Software interface to create a device tree from scratch
|
"""Software interface to create a device tree from scratch
|
||||||
|
@ -1096,9 +991,6 @@ class NodeAdder():
|
||||||
|
|
||||||
%rename(fdt_property) fdt_property_func;
|
%rename(fdt_property) fdt_property_func;
|
||||||
|
|
||||||
%immutable fdt_property::data;
|
|
||||||
%immutable fdt_node_header::name;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* fdt32_t is a big-endian 32-bit value defined to uint32_t in libfdt_env.h
|
* fdt32_t is a big-endian 32-bit value defined to uint32_t in libfdt_env.h
|
||||||
* so use the same type here.
|
* so use the same type here.
|
||||||
|
@ -1117,7 +1009,7 @@ typedef uint32_t fdt32_t;
|
||||||
}
|
}
|
||||||
$1 = (void *)PyByteArray_AsString($input);
|
$1 = (void *)PyByteArray_AsString($input);
|
||||||
fdt = $1;
|
fdt = $1;
|
||||||
(void)fdt; /* avoid unused variable warning */
|
fdt = fdt; /* avoid unused variable warning */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Some functions do change the device tree, so use void * */
|
/* Some functions do change the device tree, so use void * */
|
||||||
|
@ -1128,7 +1020,7 @@ typedef uint32_t fdt32_t;
|
||||||
}
|
}
|
||||||
$1 = PyByteArray_AsString($input);
|
$1 = PyByteArray_AsString($input);
|
||||||
fdt = $1;
|
fdt = $1;
|
||||||
(void)fdt; /* avoid unused variable warning */
|
fdt = fdt; /* avoid unused variable warning */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* typemap used for fdt_get_property_by_offset() */
|
/* typemap used for fdt_get_property_by_offset() */
|
||||||
|
@ -1140,7 +1032,7 @@ typedef uint32_t fdt32_t;
|
||||||
fdt_string(fdt1, fdt32_to_cpu($1->nameoff)));
|
fdt_string(fdt1, fdt32_to_cpu($1->nameoff)));
|
||||||
buff = PyByteArray_FromStringAndSize(
|
buff = PyByteArray_FromStringAndSize(
|
||||||
(const char *)($1 + 1), fdt32_to_cpu($1->len));
|
(const char *)($1 + 1), fdt32_to_cpu($1->len));
|
||||||
resultobj = SWIG_AppendOutput(resultobj, buff);
|
resultobj = SWIG_Python_AppendOutput(resultobj, buff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1148,16 +1040,14 @@ typedef uint32_t fdt32_t;
|
||||||
|
|
||||||
/* typemap used for fdt_getprop() */
|
/* typemap used for fdt_getprop() */
|
||||||
%typemap(out) (const void *) {
|
%typemap(out) (const void *) {
|
||||||
if (!$1) {
|
if (!$1)
|
||||||
$result = Py_None;
|
$result = Py_None;
|
||||||
Py_INCREF($result);
|
else
|
||||||
} else {
|
|
||||||
%#if PY_VERSION_HEX >= 0x03000000
|
%#if PY_VERSION_HEX >= 0x03000000
|
||||||
$result = Py_BuildValue("y#", $1, (Py_ssize_t)*arg4);
|
$result = Py_BuildValue("y#", $1, *arg4);
|
||||||
%#else
|
%#else
|
||||||
$result = Py_BuildValue("s#", $1, (Py_ssize_t)*arg4);
|
$result = Py_BuildValue("s#", $1, *arg4);
|
||||||
%#endif
|
%#endif
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* typemap used for fdt_setprop() */
|
/* typemap used for fdt_setprop() */
|
||||||
|
@ -1181,7 +1071,7 @@ typedef uint32_t fdt32_t;
|
||||||
|
|
||||||
%typemap(argout) int *depth {
|
%typemap(argout) int *depth {
|
||||||
PyObject *val = Py_BuildValue("i", *arg$argnum);
|
PyObject *val = Py_BuildValue("i", *arg$argnum);
|
||||||
resultobj = SWIG_AppendOutput(resultobj, val);
|
resultobj = SWIG_Python_AppendOutput(resultobj, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
%apply int *depth { int *depth };
|
%apply int *depth { int *depth };
|
||||||
|
@ -1193,14 +1083,14 @@ typedef uint32_t fdt32_t;
|
||||||
|
|
||||||
%typemap(argout) uint64_t * {
|
%typemap(argout) uint64_t * {
|
||||||
PyObject *val = PyLong_FromUnsignedLongLong(*arg$argnum);
|
PyObject *val = PyLong_FromUnsignedLongLong(*arg$argnum);
|
||||||
resultobj = SWIG_AppendOutput(resultobj, val);
|
if (!result) {
|
||||||
|
if (PyTuple_GET_SIZE(resultobj) == 0)
|
||||||
|
resultobj = val;
|
||||||
|
else
|
||||||
|
resultobj = SWIG_Python_AppendOutput(resultobj, val);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
%include "cstring.i"
|
|
||||||
|
|
||||||
%cstring_output_maxsize(char *buf, int buflen);
|
|
||||||
int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen);
|
|
||||||
|
|
||||||
/* We have both struct fdt_property and a function fdt_property() */
|
/* We have both struct fdt_property and a function fdt_property() */
|
||||||
%warnfilter(302) fdt_property;
|
%warnfilter(302) fdt_property;
|
||||||
|
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
libfdt_c = custom_target(
|
|
||||||
'swig',
|
|
||||||
input: 'libfdt.i',
|
|
||||||
output: ['libfdt.c', 'libfdt.py'],
|
|
||||||
install: true,
|
|
||||||
install_dir: [false, py.get_install_dir(pure: false)],
|
|
||||||
command: [swig, '-python', '-I'+meson.current_source_dir() / '../libfdt', '-o', '@OUTPUT0@', '@INPUT@']
|
|
||||||
)
|
|
||||||
|
|
||||||
nowarn_gen = cc.get_supported_arguments(
|
|
||||||
'-Wno-cast-qual',
|
|
||||||
'-Wno-missing-prototypes',
|
|
||||||
'-Wno-redundant-decls',
|
|
||||||
)
|
|
||||||
pylibfdt = py.extension_module(
|
|
||||||
'_libfdt',
|
|
||||||
libfdt_c,
|
|
||||||
c_args: ['-DPY_SSIZE_T_CLEAN'] + nowarn_gen,
|
|
||||||
dependencies: [libfdt_dep, py.dependency()],
|
|
||||||
install: true,
|
|
||||||
)
|
|
48
pylibfdt/setup.py
Executable file
48
pylibfdt/setup.py
Executable file
|
@ -0,0 +1,48 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
|
||||||
|
|
||||||
|
# While Python 3 is the default, it's also possible to invoke
|
||||||
|
# this setup.py script with Python 2.
|
||||||
|
|
||||||
|
"""
|
||||||
|
setup.py file for SWIG libfdt
|
||||||
|
Copyright (C) 2017 Google, Inc.
|
||||||
|
Written by Simon Glass <sjg@chromium.org>
|
||||||
|
"""
|
||||||
|
|
||||||
|
from distutils.core import setup, Extension
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
VERSION_PATTERN = '^#define DTC_VERSION "DTC ([^"]*)"$'
|
||||||
|
|
||||||
|
|
||||||
|
def get_version():
|
||||||
|
version_file = "../version_gen.h"
|
||||||
|
f = open(version_file, 'rt')
|
||||||
|
m = re.match(VERSION_PATTERN, f.readline())
|
||||||
|
return m.group(1)
|
||||||
|
|
||||||
|
|
||||||
|
setupdir = os.path.dirname(os.path.abspath(sys.argv[0]))
|
||||||
|
os.chdir(setupdir)
|
||||||
|
|
||||||
|
libfdt_module = Extension(
|
||||||
|
'_libfdt',
|
||||||
|
sources=['libfdt.i'],
|
||||||
|
include_dirs=['../libfdt'],
|
||||||
|
libraries=['fdt'],
|
||||||
|
library_dirs=['../libfdt'],
|
||||||
|
swig_opts=['-I../libfdt'],
|
||||||
|
)
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name='libfdt',
|
||||||
|
version=get_version(),
|
||||||
|
author='Simon Glass <sjg@chromium.org>',
|
||||||
|
description='Python binding for libfdt',
|
||||||
|
ext_modules=[libfdt_module],
|
||||||
|
py_modules=['libfdt'],
|
||||||
|
)
|
|
@ -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,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
|
|
55
srcpos.c
55
srcpos.c
|
@ -3,9 +3,7 @@
|
||||||
* Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc.
|
* Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _GNU_SOURCE
|
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
@ -22,7 +20,7 @@ struct search_path {
|
||||||
static struct search_path *search_path_head, **search_path_tail;
|
static struct search_path *search_path_head, **search_path_tail;
|
||||||
|
|
||||||
/* Detect infinite include recursion. */
|
/* Detect infinite include recursion. */
|
||||||
#define MAX_SRCFILE_DEPTH (200)
|
#define MAX_SRCFILE_DEPTH (100)
|
||||||
static int srcfile_depth; /* = 0 */
|
static int srcfile_depth; /* = 0 */
|
||||||
|
|
||||||
static char *get_dirname(const char *path)
|
static char *get_dirname(const char *path)
|
||||||
|
@ -88,26 +86,6 @@ static char *shorten_to_initial_path(char *fname)
|
||||||
return NULL;
|
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.
|
* Try to open a file in a given directory.
|
||||||
*
|
*
|
||||||
|
@ -123,7 +101,7 @@ static char *try_open(const char *dirname, const char *fname, FILE **fp)
|
||||||
{
|
{
|
||||||
char *fullname;
|
char *fullname;
|
||||||
|
|
||||||
if (!dirname || is_absolute_path(fname))
|
if (!dirname || fname[0] == '/')
|
||||||
fullname = xstrdup(fname);
|
fullname = xstrdup(fname);
|
||||||
else
|
else
|
||||||
fullname = join_path(dirname, fname);
|
fullname = join_path(dirname, fname);
|
||||||
|
@ -180,10 +158,8 @@ FILE *srcfile_relative_open(const char *fname, char **fullnamep)
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (depfile) {
|
if (depfile)
|
||||||
fputc(' ', depfile);
|
fprintf(depfile, " %s", fullname);
|
||||||
fprint_path_escaped(depfile, fullname);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fullnamep)
|
if (fullnamep)
|
||||||
*fullnamep = fullname;
|
*fullnamep = fullname;
|
||||||
|
@ -307,17 +283,6 @@ struct srcpos *srcpos_extend(struct srcpos *pos, struct srcpos *newtail)
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void srcpos_free(struct srcpos *pos)
|
|
||||||
{
|
|
||||||
struct srcpos *p_next;
|
|
||||||
|
|
||||||
while (pos) {
|
|
||||||
p_next = pos->next;
|
|
||||||
free(pos);
|
|
||||||
pos = p_next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
char *
|
||||||
srcpos_string(struct srcpos *pos)
|
srcpos_string(struct srcpos *pos)
|
||||||
{
|
{
|
||||||
|
@ -346,8 +311,8 @@ srcpos_string(struct srcpos *pos)
|
||||||
static char *
|
static char *
|
||||||
srcpos_string_comment(struct srcpos *pos, bool first_line, int level)
|
srcpos_string_comment(struct srcpos *pos, bool first_line, int level)
|
||||||
{
|
{
|
||||||
char *pos_str, *fresh_fname = NULL, *first, *rest;
|
char *pos_str, *fname, *first, *rest;
|
||||||
const char *fname;
|
bool fresh_fname = false;
|
||||||
|
|
||||||
if (!pos) {
|
if (!pos) {
|
||||||
if (level > 1) {
|
if (level > 1) {
|
||||||
|
@ -365,9 +330,9 @@ srcpos_string_comment(struct srcpos *pos, bool first_line, int level)
|
||||||
else if (level > 1)
|
else if (level > 1)
|
||||||
fname = pos->file->name;
|
fname = pos->file->name;
|
||||||
else {
|
else {
|
||||||
fresh_fname = shorten_to_initial_path(pos->file->name);
|
fname = shorten_to_initial_path(pos->file->name);
|
||||||
if (fresh_fname)
|
if (fname)
|
||||||
fname = fresh_fname;
|
fresh_fname = true;
|
||||||
else
|
else
|
||||||
fname = pos->file->name;
|
fname = pos->file->name;
|
||||||
}
|
}
|
||||||
|
@ -381,7 +346,7 @@ srcpos_string_comment(struct srcpos *pos, bool first_line, int level)
|
||||||
first_line ? pos->first_line : pos->last_line);
|
first_line ? pos->first_line : pos->last_line);
|
||||||
|
|
||||||
if (fresh_fname)
|
if (fresh_fname)
|
||||||
free(fresh_fname);
|
free(fname);
|
||||||
|
|
||||||
if (pos->next != NULL) {
|
if (pos->next != NULL) {
|
||||||
rest = srcpos_string_comment(pos->next, first_line, level);
|
rest = srcpos_string_comment(pos->next, first_line, level);
|
||||||
|
|
1
srcpos.h
1
srcpos.h
|
@ -88,7 +88,6 @@ extern void srcpos_update(struct srcpos *pos, const char *text, int len);
|
||||||
extern struct srcpos *srcpos_copy(struct srcpos *pos);
|
extern struct srcpos *srcpos_copy(struct srcpos *pos);
|
||||||
extern struct srcpos *srcpos_extend(struct srcpos *new_srcpos,
|
extern struct srcpos *srcpos_extend(struct srcpos *new_srcpos,
|
||||||
struct srcpos *old_srcpos);
|
struct srcpos *old_srcpos);
|
||||||
extern void srcpos_free(struct srcpos *pos);
|
|
||||||
extern char *srcpos_string(struct srcpos *pos);
|
extern char *srcpos_string(struct srcpos *pos);
|
||||||
extern char *srcpos_string_first(struct srcpos *pos, int level);
|
extern char *srcpos_string_first(struct srcpos *pos, int level);
|
||||||
extern char *srcpos_string_last(struct srcpos *pos, int level);
|
extern char *srcpos_string_last(struct srcpos *pos, int level);
|
||||||
|
|
2
tests/.gitignore
vendored
2
tests/.gitignore
vendored
|
@ -54,7 +54,6 @@ tmp.*
|
||||||
/property_iterate
|
/property_iterate
|
||||||
/propname_escapes
|
/propname_escapes
|
||||||
/references
|
/references
|
||||||
/relref_merge
|
|
||||||
/root_node
|
/root_node
|
||||||
/rw_tree1
|
/rw_tree1
|
||||||
/rw_oom
|
/rw_oom
|
||||||
|
@ -74,4 +73,3 @@ tmp.*
|
||||||
/truncated_memrsv
|
/truncated_memrsv
|
||||||
/utilfdt_test
|
/utilfdt_test
|
||||||
/value-labels
|
/value-labels
|
||||||
/get_next_tag_invalid_prop_len
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ LIB_TESTS_L = get_mem_rsv \
|
||||||
get_path supernode_atdepth_offset parent_offset \
|
get_path supernode_atdepth_offset parent_offset \
|
||||||
node_offset_by_prop_value node_offset_by_phandle \
|
node_offset_by_prop_value node_offset_by_phandle \
|
||||||
node_check_compatible node_offset_by_compatible \
|
node_check_compatible node_offset_by_compatible \
|
||||||
get_alias get_next_tag_invalid_prop_len \
|
get_alias \
|
||||||
char_literal \
|
char_literal \
|
||||||
sized_cells \
|
sized_cells \
|
||||||
notfound \
|
notfound \
|
||||||
|
@ -18,7 +18,7 @@ LIB_TESTS_L = get_mem_rsv \
|
||||||
open_pack rw_tree1 rw_oom set_name setprop del_property del_node \
|
open_pack rw_tree1 rw_oom set_name setprop del_property del_node \
|
||||||
appendprop1 appendprop2 propname_escapes \
|
appendprop1 appendprop2 propname_escapes \
|
||||||
string_escapes references path-references phandle_format \
|
string_escapes references path-references phandle_format \
|
||||||
boot-cpuid incbin relref_merge \
|
boot-cpuid incbin \
|
||||||
extra-terminating-null \
|
extra-terminating-null \
|
||||||
dtbs_equal_ordered \
|
dtbs_equal_ordered \
|
||||||
dtb_reverse dtbs_equal_unordered \
|
dtb_reverse dtbs_equal_unordered \
|
||||||
|
@ -33,19 +33,14 @@ LIB_TESTS_L = get_mem_rsv \
|
||||||
LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%)
|
LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%)
|
||||||
|
|
||||||
LIBTREE_TESTS_L = truncated_property truncated_string truncated_memrsv
|
LIBTREE_TESTS_L = truncated_property truncated_string truncated_memrsv
|
||||||
|
|
||||||
LIBTREE_TESTS = $(LIBTREE_TESTS_L:%=$(TESTS_PREFIX)%)
|
LIBTREE_TESTS = $(LIBTREE_TESTS_L:%=$(TESTS_PREFIX)%)
|
||||||
|
|
||||||
ifneq ($(STATIC_BUILD),1)
|
DL_LIB_TESTS_L = asm_tree_dump value-labels
|
||||||
DL_LIB_TESTS_L = asm_tree_dump value-labels
|
DL_LIB_TESTS = $(DL_LIB_TESTS_L:%=$(TESTS_PREFIX)%)
|
||||||
DL_LIB_TESTS = $(DL_LIB_TESTS_L:%=$(TESTS_PREFIX)%)
|
|
||||||
endif
|
|
||||||
|
|
||||||
TESTS = $(LIB_TESTS) $(LIBTREE_TESTS) $(DL_LIB_TESTS)
|
TESTS = $(LIB_TESTS) $(LIBTREE_TESTS) $(DL_LIB_TESTS)
|
||||||
|
|
||||||
TESTS_TREES_L = test_tree1.dtb bad_node_char.dtb bad_node_format.dtb \
|
TESTS_TREES_L = test_tree1.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 = $(TESTS_TREES_L:%=$(TESTS_PREFIX)%)
|
TESTS_TREES = $(TESTS_TREES_L:%=$(TESTS_PREFIX)%)
|
||||||
|
|
||||||
TESTS_TARGETS = $(TESTS) $(TESTS_TREES)
|
TESTS_TARGETS = $(TESTS) $(TESTS_TREES)
|
||||||
|
@ -63,17 +58,17 @@ TESTS_CLEANDIRS = $(TESTS_CLEANDIRS_L:%=$(TESTS_PREFIX)%)
|
||||||
.PHONY: tests
|
.PHONY: tests
|
||||||
tests: $(TESTS) $(TESTS_TREES)
|
tests: $(TESTS) $(TESTS_TREES)
|
||||||
|
|
||||||
$(LIB_TESTS): %: $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_dep)
|
$(LIB_TESTS): %: $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_lib)
|
||||||
|
|
||||||
# Not necessary on all platforms; allow -ldl to be excluded instead of forcing
|
# Not necessary on all platforms; allow -ldl to be excluded instead of forcing
|
||||||
# other platforms to patch it out.
|
# other platforms to patch it out.
|
||||||
LIBDL = -ldl
|
LIBDL = -ldl
|
||||||
$(DL_LIB_TESTS): %: %.o $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_dep)
|
$(DL_LIB_TESTS): %: %.o $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_lib)
|
||||||
@$(VECHO) LD [libdl] $@
|
@$(VECHO) LD [libdl] $@
|
||||||
$(LINK.c) -o $@ $^ $(LIBDL)
|
$(LINK.c) -o $@ $^ $(LIBDL)
|
||||||
|
|
||||||
$(LIBTREE_TESTS): %: $(TESTS_PREFIX)testutils.o $(TESTS_PREFIX)trees.o \
|
$(LIBTREE_TESTS): %: $(TESTS_PREFIX)testutils.o $(TESTS_PREFIX)trees.o \
|
||||||
util.o $(LIBFDT_dep)
|
util.o $(LIBFDT_lib)
|
||||||
|
|
||||||
$(TESTS_PREFIX)dumptrees: $(TESTS_PREFIX)trees.o
|
$(TESTS_PREFIX)dumptrees: $(TESTS_PREFIX)trees.o
|
||||||
|
|
||||||
|
|
|
@ -5,10 +5,6 @@
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
|
|
||||||
aliases {
|
aliases {
|
||||||
empty = "";
|
|
||||||
loop = "loop";
|
|
||||||
nonull = [626164];
|
|
||||||
relative = "s1/subsubnode";
|
|
||||||
s1 = &sub1;
|
s1 = &sub1;
|
||||||
ss1 = &subsub1;
|
ss1 = &subsub1;
|
||||||
sss1 = &subsubsub1;
|
sss1 = &subsubsub1;
|
||||||
|
|
|
@ -36,7 +36,6 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
buf = xmalloc(SPACE);
|
buf = xmalloc(SPACE);
|
||||||
CHECK(fdt_open_into(fdt, buf, SPACE));
|
CHECK(fdt_open_into(fdt, buf, SPACE));
|
||||||
free(fdt);
|
|
||||||
fdt = buf;
|
fdt = buf;
|
||||||
|
|
||||||
CHECK(fdt_appendprop(fdt, 0, "prop-bytes", bytes, sizeof(bytes)));
|
CHECK(fdt_appendprop(fdt, 0, "prop-bytes", bytes, sizeof(bytes)));
|
||||||
|
|
|
@ -36,7 +36,7 @@ int main(int argc, char *argv[])
|
||||||
err = fdt_open_into(fdt, buf, 0x1000);
|
err = fdt_open_into(fdt, buf, 0x1000);
|
||||||
if (err)
|
if (err)
|
||||||
FAIL("fdt_open_into(): %s", fdt_strerror(err));
|
FAIL("fdt_open_into(): %s", fdt_strerror(err));
|
||||||
free(fdt);
|
|
||||||
fdt = buf;
|
fdt = buf;
|
||||||
|
|
||||||
/* Set up */
|
/* Set up */
|
||||||
|
|
|
@ -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>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -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>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -1,7 +0,0 @@
|
||||||
/dts-v1/;
|
|
||||||
|
|
||||||
/ {
|
|
||||||
foo {
|
|
||||||
remote-endpoint = <0xdeadbeef>;
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -1,2 +0,0 @@
|
||||||
/dts-v1/;
|
|
||||||
/ { endpoint {}; };
|
|
|
@ -1,14 +0,0 @@
|
||||||
/dts-v1/;
|
|
||||||
|
|
||||||
/ {
|
|
||||||
bar: bar {
|
|
||||||
port {
|
|
||||||
bar_con: endpoint {
|
|
||||||
remote-endpoint = <&foo_con>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
foo_con: endpoint {
|
|
||||||
remote-endpoint = <&bar_con>;
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -1,19 +0,0 @@
|
||||||
/dts-v1/;
|
|
||||||
|
|
||||||
/ {
|
|
||||||
|
|
||||||
bar: bar {
|
|
||||||
port {
|
|
||||||
bar_con: endpoint {
|
|
||||||
remote-endpoint = <&foo_con>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
foo {
|
|
||||||
remote-endpoint = <&bar_con>; // misplaced remote-endpoint property
|
|
||||||
port {
|
|
||||||
foo_con: endpoint {
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -1,7 +0,0 @@
|
||||||
/dts-v1/;
|
|
||||||
|
|
||||||
/ {
|
|
||||||
intc: interrupt-controller {
|
|
||||||
interrupt-controller;
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -1,20 +0,0 @@
|
||||||
/dts-v1/;
|
|
||||||
|
|
||||||
/ {
|
|
||||||
interrupt-parent = <&intc>;
|
|
||||||
intc: interrupt-controller {
|
|
||||||
#interrupt-cells = <3>;
|
|
||||||
interrupt-controller;
|
|
||||||
};
|
|
||||||
|
|
||||||
node {
|
|
||||||
#address-cells = <0>;
|
|
||||||
#interrupt-cells = <1>;
|
|
||||||
interrupt-map = <1 &intc 1 2 3>;
|
|
||||||
interrupt-map-mask = <0 0>;
|
|
||||||
|
|
||||||
child {
|
|
||||||
interrupts = <1>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -1,17 +0,0 @@
|
||||||
/dts-v1/;
|
|
||||||
|
|
||||||
/ {
|
|
||||||
interrupt-parent = <&intc>;
|
|
||||||
intc: interrupt-controller {
|
|
||||||
};
|
|
||||||
|
|
||||||
node {
|
|
||||||
#address-cells = <0>;
|
|
||||||
#interrupt-cells = <1>;
|
|
||||||
interrupt-map = <1 &intc 1 2 3>;
|
|
||||||
|
|
||||||
child {
|
|
||||||
interrupts = <1>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -1,19 +0,0 @@
|
||||||
/dts-v1/;
|
|
||||||
|
|
||||||
/ {
|
|
||||||
interrupt-parent = <&intc>;
|
|
||||||
intc: interrupt-controller {
|
|
||||||
#interrupt-cells = <3>;
|
|
||||||
interrupt-controller;
|
|
||||||
};
|
|
||||||
|
|
||||||
node {
|
|
||||||
/* Missing #address-cells = <0>; */
|
|
||||||
#interrupt-cells = <1>;
|
|
||||||
interrupt-map = <1 &intc 1 2 3>;
|
|
||||||
|
|
||||||
child {
|
|
||||||
interrupts = <1>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -32,7 +32,7 @@ _dt_reserve_map:
|
||||||
dt_struct_start:
|
dt_struct_start:
|
||||||
_dt_struct_start:
|
_dt_struct_start:
|
||||||
.long OF_DT_BEGIN_NODE
|
.long OF_DT_BEGIN_NODE
|
||||||
.asciz ""
|
.string ""
|
||||||
.balign 4
|
.balign 4
|
||||||
.long OF_DT_PROP
|
.long OF_DT_PROP
|
||||||
.long 0xa
|
.long 0xa
|
||||||
|
@ -58,7 +58,7 @@ _dt_struct_start:
|
||||||
.long 0x2
|
.long 0x2
|
||||||
.balign 4
|
.balign 4
|
||||||
.long OF_DT_BEGIN_NODE
|
.long OF_DT_BEGIN_NODE
|
||||||
.asciz "memory@0"
|
.string "memory@0"
|
||||||
.balign 4
|
.balign 4
|
||||||
.long OF_DT_PROP
|
.long OF_DT_PROP
|
||||||
.long 0x7
|
.long 0x7
|
||||||
|
@ -77,7 +77,7 @@ _dt_struct_start:
|
||||||
.balign 4
|
.balign 4
|
||||||
.long OF_DT_END_NODE
|
.long OF_DT_END_NODE
|
||||||
.long OF_DT_BEGIN_NODE
|
.long OF_DT_BEGIN_NODE
|
||||||
.asciz "cpus"
|
.string "cpus"
|
||||||
.balign 4
|
.balign 4
|
||||||
.long OF_DT_PROP
|
.long OF_DT_PROP
|
||||||
.long 0x4
|
.long 0x4
|
||||||
|
@ -151,22 +151,22 @@ _dt_struct_end:
|
||||||
.globl dt_strings_start
|
.globl dt_strings_start
|
||||||
dt_strings_start:
|
dt_strings_start:
|
||||||
_dt_strings_start:
|
_dt_strings_start:
|
||||||
.asciz "model"
|
.string "model"
|
||||||
.asciz "compatible"
|
.string "compatible"
|
||||||
.asciz "#address-cells"
|
.string "#address-cells"
|
||||||
.asciz "#size-cells"
|
.string "#size-cells"
|
||||||
.asciz "device_type"
|
.string "device_type"
|
||||||
.asciz "reg"
|
.string "reg"
|
||||||
.asciz "d10"
|
.string "d10"
|
||||||
.asciz "d23"
|
.string "d23"
|
||||||
.asciz "b101"
|
.string "b101"
|
||||||
.asciz "o17"
|
.string "o17"
|
||||||
.asciz "hd00d"
|
.string "hd00d"
|
||||||
.asciz "stuff"
|
.string "stuff"
|
||||||
.asciz "bad-d-1"
|
.string "bad-d-1"
|
||||||
.asciz "bad-d-2"
|
.string "bad-d-2"
|
||||||
.asciz "bad-o-1"
|
.string "bad-o-1"
|
||||||
.asciz "bad-o-2"
|
.string "bad-o-2"
|
||||||
.globl dt_strings_end
|
.globl dt_strings_end
|
||||||
dt_strings_end:
|
dt_strings_end:
|
||||||
_dt_strings_end:
|
_dt_strings_end:
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
/dts-v1/;
|
|
||||||
|
|
||||||
/ {
|
|
||||||
prop1 = < 0 >;
|
|
||||||
prop2 = < 0xffffffff >;
|
|
||||||
prop3 = < 0 >;
|
|
||||||
};
|
|
|
@ -1,7 +0,0 @@
|
||||||
/dts-v1/;
|
|
||||||
|
|
||||||
/ {
|
|
||||||
prop1 = < (-0xffffffff - 1) >;
|
|
||||||
prop2 = < (-0xffffffff - 2) >;
|
|
||||||
prop3 = < ((-0xffffffff - 1) * 2) >;
|
|
||||||
};
|
|
|
@ -32,7 +32,6 @@ static void *open_dt(char *path)
|
||||||
* Resize our DTs to 4k so that we have room to operate on
|
* Resize our DTs to 4k so that we have room to operate on
|
||||||
*/
|
*/
|
||||||
CHECK(fdt_open_into(dt, copy, FDT_COPY_SIZE));
|
CHECK(fdt_open_into(dt, copy, FDT_COPY_SIZE));
|
||||||
free(dt);
|
|
||||||
|
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
prop7;
|
prop7;
|
||||||
/* yet
|
/* yet
|
||||||
* another
|
* another
|
||||||
* multiline
|
* multline
|
||||||
* comment
|
* comment
|
||||||
*/
|
*/
|
||||||
prop8;
|
prop8;
|
||||||
|
|
|
@ -18,16 +18,15 @@
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
void *fdt, *blob;
|
void *fdt;
|
||||||
int subnode1_offset, subnode2_offset, subsubnode2_offset;
|
int subnode1_offset, subnode2_offset, subsubnode2_offset;
|
||||||
int err;
|
int err;
|
||||||
int oldsize, delsize, newsize;
|
int oldsize, delsize, newsize;
|
||||||
|
|
||||||
test_init(argc, argv);
|
test_init(argc, argv);
|
||||||
blob = load_blob_arg(argc, argv);
|
fdt = load_blob_arg(argc, argv);
|
||||||
|
|
||||||
fdt = open_blob_rw(blob);
|
fdt = open_blob_rw(fdt);
|
||||||
free(blob);
|
|
||||||
|
|
||||||
oldsize = fdt_totalsize(fdt);
|
oldsize = fdt_totalsize(fdt);
|
||||||
|
|
||||||
|
|
|
@ -18,17 +18,16 @@
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
void *fdt, *blob;
|
void *fdt;
|
||||||
const uint32_t *intp;
|
const uint32_t *intp;
|
||||||
const char *strp;
|
const char *strp;
|
||||||
int err, lenerr;
|
int err, lenerr;
|
||||||
int oldsize, delsize, newsize;
|
int oldsize, delsize, newsize;
|
||||||
|
|
||||||
test_init(argc, argv);
|
test_init(argc, argv);
|
||||||
blob = load_blob_arg(argc, argv);
|
fdt = load_blob_arg(argc, argv);
|
||||||
|
|
||||||
fdt = open_blob_rw(blob);
|
fdt = open_blob_rw(fdt);
|
||||||
free(blob);
|
|
||||||
|
|
||||||
oldsize = fdt_totalsize(fdt);
|
oldsize = fdt_totalsize(fdt);
|
||||||
|
|
||||||
|
@ -74,6 +73,5 @@ int main(int argc, char *argv[])
|
||||||
if (newsize >= oldsize)
|
if (newsize >= oldsize)
|
||||||
FAIL("Tree failed to shrink after deletions");
|
FAIL("Tree failed to shrink after deletions");
|
||||||
|
|
||||||
free(fdt);
|
|
||||||
PASS();
|
PASS();
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,15 +24,13 @@ static struct {
|
||||||
TREE(ovf_size_strings),
|
TREE(ovf_size_strings),
|
||||||
TREE(truncated_property), TREE(truncated_string),
|
TREE(truncated_property), TREE(truncated_string),
|
||||||
TREE(truncated_memrsv),
|
TREE(truncated_memrsv),
|
||||||
TREE(two_roots),
|
|
||||||
TREE(named_root)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NUM_TREES (sizeof(trees) / sizeof(trees[0]))
|
#define NUM_TREES (sizeof(trees) / sizeof(trees[0]))
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
unsigned int i;
|
int i;
|
||||||
|
|
||||||
if (argc != 2) {
|
if (argc != 2) {
|
||||||
fprintf(stderr, "Missing output directory argument\n");
|
fprintf(stderr, "Missing output directory argument\n");
|
||||||
|
|
|
@ -9,7 +9,7 @@ rm -f $LOG $EXPECT
|
||||||
trap "rm -f $LOG $EXPECT" 0
|
trap "rm -f $LOG $EXPECT" 0
|
||||||
|
|
||||||
expect="$1"
|
expect="$1"
|
||||||
printf "$expect\n" > $EXPECT
|
printf '%b\n' "$expect" > $EXPECT
|
||||||
shift
|
shift
|
||||||
|
|
||||||
verbose_run_log_check "$LOG" $VALGRIND $DTGET "$@"
|
verbose_run_log_check "$LOG" $VALGRIND $DTGET "$@"
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
/dts-v1/;
|
|
||||||
/plugin/;
|
|
||||||
|
|
||||||
/ {
|
|
||||||
prop = < &{/path/to/node} >;
|
|
||||||
};
|
|
|
@ -54,7 +54,7 @@ static void mkfile(const char *name, void *data, size_t len)
|
||||||
rc = write(fd, data, len);
|
rc = write(fd, data, len);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
FAIL("write(\"%s\"): %s", name, strerror(errno));
|
FAIL("write(\"%s\"): %s", name, strerror(errno));
|
||||||
if ((unsigned)rc != len)
|
if (rc != len)
|
||||||
FAIL("write(\"%s\"): short write", name);
|
FAIL("write(\"%s\"): short write", name);
|
||||||
|
|
||||||
rc = close(fd);
|
rc = close(fd);
|
||||||
|
|
|
@ -21,16 +21,9 @@ static void check_alias(void *fdt, const char *path, const char *alias)
|
||||||
|
|
||||||
aliaspath = fdt_get_alias(fdt, alias);
|
aliaspath = fdt_get_alias(fdt, alias);
|
||||||
|
|
||||||
if (!path && !aliaspath)
|
if (path && !aliaspath)
|
||||||
return;
|
|
||||||
|
|
||||||
if (!aliaspath)
|
|
||||||
FAIL("fdt_get_alias(%s) failed\n", alias);
|
FAIL("fdt_get_alias(%s) failed\n", alias);
|
||||||
|
|
||||||
if (!path)
|
|
||||||
FAIL("fdt_get_alias(%s) returned %s instead of NULL",
|
|
||||||
alias, aliaspath);
|
|
||||||
|
|
||||||
if (strcmp(aliaspath, path) != 0)
|
if (strcmp(aliaspath, path) != 0)
|
||||||
FAIL("fdt_get_alias(%s) returned %s instead of %s\n",
|
FAIL("fdt_get_alias(%s) returned %s instead of %s\n",
|
||||||
alias, aliaspath, path);
|
alias, aliaspath, path);
|
||||||
|
@ -43,14 +36,9 @@ int main(int argc, char *argv[])
|
||||||
test_init(argc, argv);
|
test_init(argc, argv);
|
||||||
fdt = load_blob_arg(argc, argv);
|
fdt = load_blob_arg(argc, argv);
|
||||||
|
|
||||||
check_alias(fdt, NULL, "empty");
|
|
||||||
check_alias(fdt, NULL, "nonull");
|
|
||||||
check_alias(fdt, NULL, "relative");
|
|
||||||
check_alias(fdt, "/subnode@1", "s1");
|
check_alias(fdt, "/subnode@1", "s1");
|
||||||
check_alias(fdt, "/subnode@1/subsubnode", "ss1");
|
check_alias(fdt, "/subnode@1/subsubnode", "ss1");
|
||||||
check_alias(fdt, "/subnode@1/subsubnode/subsubsubnode", "sss1");
|
check_alias(fdt, "/subnode@1/subsubnode/subsubsubnode", "sss1");
|
||||||
|
|
||||||
check_alias(fdt, NULL, "loop"); // Might trigger a stack overflow
|
|
||||||
|
|
||||||
PASS();
|
PASS();
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,14 +34,12 @@ static void check_name(void *fdt, const char *path)
|
||||||
offset, getname, len);
|
offset, getname, len);
|
||||||
if (!getname)
|
if (!getname)
|
||||||
FAIL("fdt_get_name(%d): %s", offset, fdt_strerror(len));
|
FAIL("fdt_get_name(%d): %s", offset, fdt_strerror(len));
|
||||||
if (len < 0)
|
|
||||||
FAIL("negative name length (%d) for returned node name\n", len);
|
|
||||||
|
|
||||||
if (strcmp(getname, checkname) != 0)
|
if (strcmp(getname, checkname) != 0)
|
||||||
FAIL("fdt_get_name(%s) returned \"%s\" instead of \"%s\"",
|
FAIL("fdt_get_name(%s) returned \"%s\" instead of \"%s\"",
|
||||||
path, getname, checkname);
|
path, getname, checkname);
|
||||||
|
|
||||||
if ((unsigned)len != strlen(getname))
|
if (len != strlen(getname))
|
||||||
FAIL("fdt_get_name(%s) returned length %d instead of %zd",
|
FAIL("fdt_get_name(%s) returned length %d instead of %zd",
|
||||||
path, len, strlen(getname));
|
path, len, strlen(getname));
|
||||||
|
|
||||||
|
|
|
@ -1,100 +0,0 @@
|
||||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
|
||||||
/*
|
|
||||||
* libfdt - Flat Device Tree manipulation
|
|
||||||
* Testcase for fdt_next_tag()
|
|
||||||
*/
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include <libfdt.h>
|
|
||||||
#include "tests.h"
|
|
||||||
#include "testdata.h"
|
|
||||||
|
|
||||||
#define FDT_SIZE 65536
|
|
||||||
#define CHECK_ERR(err) \
|
|
||||||
({ if (err) \
|
|
||||||
FAIL("%s: %d: %s", __FILE__, __LINE__, fdt_strerror(err)); \
|
|
||||||
})
|
|
||||||
|
|
||||||
static void fdt_next_tag_test(bool fdt_finished)
|
|
||||||
{
|
|
||||||
struct fdt_property *prp;
|
|
||||||
void *fdt;
|
|
||||||
int nextoff = 0, offset, err;
|
|
||||||
uint32_t tag;
|
|
||||||
|
|
||||||
fdt = malloc(FDT_SIZE);
|
|
||||||
if (!fdt)
|
|
||||||
FAIL("Can't allocate memory");
|
|
||||||
err = fdt_create(fdt, FDT_SIZE);
|
|
||||||
CHECK_ERR(err);
|
|
||||||
err = fdt_finish_reservemap(fdt);
|
|
||||||
CHECK_ERR(err);
|
|
||||||
/* Create a root node and add two properties */
|
|
||||||
err = fdt_begin_node(fdt, "");
|
|
||||||
CHECK_ERR(err);
|
|
||||||
err = fdt_property_u32(fdt, "prop-int-32", 0x1234);
|
|
||||||
CHECK_ERR(err);
|
|
||||||
err = fdt_property_u32(fdt, "prop2-int-32", 0x4321);
|
|
||||||
CHECK_ERR(err);
|
|
||||||
err = fdt_end_node(fdt);
|
|
||||||
CHECK_ERR(err);
|
|
||||||
if (fdt_finished) {
|
|
||||||
/* Call fdt_finish to set the correct fdt state. */
|
|
||||||
err = fdt_finish(fdt);
|
|
||||||
CHECK_ERR(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
offset = fdt_first_property_offset(fdt, 0);
|
|
||||||
if (offset <= 0)
|
|
||||||
FAIL("Invalid offset %x, expected value greater than 0, finished=%d\n",
|
|
||||||
offset, fdt_finished);
|
|
||||||
|
|
||||||
/* Normal case */
|
|
||||||
tag = fdt_next_tag(fdt, offset, &nextoff);
|
|
||||||
if (tag != FDT_PROP)
|
|
||||||
FAIL("Invalid tag %x, expected FDT_PROP, finished=%d\n",
|
|
||||||
tag, fdt_finished);
|
|
||||||
if (nextoff <= 0)
|
|
||||||
FAIL("Invalid nextoff %d, expected value greater than 0, finished=%d",
|
|
||||||
nextoff, fdt_finished);
|
|
||||||
|
|
||||||
/* Get a writable ptr to the first property and corrupt the length */
|
|
||||||
prp = fdt_get_property_by_offset_w(fdt, offset, NULL);
|
|
||||||
if (!prp)
|
|
||||||
FAIL("Bad property pointer, finished=%d", fdt_finished);
|
|
||||||
|
|
||||||
/* int overflow case */
|
|
||||||
prp->len = cpu_to_fdt32(0xFFFFFFFA);
|
|
||||||
tag = fdt_next_tag(fdt, offset, &nextoff);
|
|
||||||
if (tag != FDT_END)
|
|
||||||
FAIL("Invalid tag %x, expected premature FDT_END, finished=%d",
|
|
||||||
tag, fdt_finished);
|
|
||||||
if (nextoff != -FDT_ERR_BADSTRUCTURE)
|
|
||||||
FAIL("Invalid nextoff, expected error -FDT_ERR_BADSTRUCTURE, finished=%d",
|
|
||||||
fdt_finished);
|
|
||||||
|
|
||||||
/* negative offset case */
|
|
||||||
prp->len = cpu_to_fdt32(0x7FFFFFFA);
|
|
||||||
tag = fdt_next_tag(fdt, offset, &nextoff);
|
|
||||||
if (tag != FDT_END)
|
|
||||||
FAIL("Invalid tag %x, expected premature FDT_END, finished=%d",
|
|
||||||
tag, fdt_finished);
|
|
||||||
if (nextoff != -FDT_ERR_BADSTRUCTURE)
|
|
||||||
FAIL("Invalid nextoff, expected -FDT_ERR_BADSTRUCTURE, finished=%d",
|
|
||||||
fdt_finished);
|
|
||||||
|
|
||||||
free(fdt);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
test_init(argc, argv);
|
|
||||||
|
|
||||||
fdt_next_tag_test(false);
|
|
||||||
fdt_next_tag_test(true);
|
|
||||||
|
|
||||||
PASS();
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
/dts-v1/;
|
|
||||||
|
|
||||||
/ {
|
|
||||||
gpio: gpio-controller {
|
|
||||||
#gpio-cells = <3>;
|
|
||||||
};
|
|
||||||
|
|
||||||
node {
|
|
||||||
foo,nr-gpios = <1>;
|
|
||||||
foo-gpios = <&gpio 1 2 3>;
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -59,7 +59,7 @@ int main(int argc, char *argv[])
|
||||||
void *fdt;
|
void *fdt;
|
||||||
const fdt32_t *res;
|
const fdt32_t *res;
|
||||||
int reslen;
|
int reslen;
|
||||||
unsigned int i;
|
int i;
|
||||||
|
|
||||||
test_init(argc, argv);
|
test_init(argc, argv);
|
||||||
|
|
||||||
|
|
|
@ -1,163 +0,0 @@
|
||||||
trees = static_library('trees', files('trees.S'),
|
|
||||||
build_by_default: false,
|
|
||||||
include_directories: libfdt_inc)
|
|
||||||
|
|
||||||
dumptrees = executable('dumptrees', files('dumptrees.c'),
|
|
||||||
build_by_default: false,
|
|
||||||
link_with: trees, dependencies: libfdt_dep)
|
|
||||||
|
|
||||||
dumptrees_dtb = custom_target(
|
|
||||||
'dumptrees',
|
|
||||||
command: [dumptrees, meson.current_build_dir()],
|
|
||||||
output: [
|
|
||||||
'test_tree1.dtb',
|
|
||||||
'bad_node_char.dtb',
|
|
||||||
'bad_node_format.dtb',
|
|
||||||
'bad_prop_char.dtb',
|
|
||||||
'ovf_size_strings.dtb',
|
|
||||||
'truncated_property.dtb',
|
|
||||||
'truncated_string.dtb',
|
|
||||||
'truncated_memrsv.dtb',
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
testutil_dep = declare_dependency(sources: ['testutils.c'], link_with: trees)
|
|
||||||
|
|
||||||
tests = [
|
|
||||||
'add_subnode_with_nops',
|
|
||||||
'addr_size_cells',
|
|
||||||
'addr_size_cells2',
|
|
||||||
'appendprop1',
|
|
||||||
'appendprop2',
|
|
||||||
'appendprop_addrrange',
|
|
||||||
'boot-cpuid',
|
|
||||||
'char_literal',
|
|
||||||
'check_full',
|
|
||||||
'check_header',
|
|
||||||
'check_path',
|
|
||||||
'del_node',
|
|
||||||
'del_property',
|
|
||||||
'dtb_reverse',
|
|
||||||
'dtbs_equal_ordered',
|
|
||||||
'dtbs_equal_unordered',
|
|
||||||
'extra-terminating-null',
|
|
||||||
'find_property',
|
|
||||||
'fs_tree1',
|
|
||||||
'get_alias',
|
|
||||||
'get_mem_rsv',
|
|
||||||
'get_name',
|
|
||||||
'get_path',
|
|
||||||
'get_phandle',
|
|
||||||
'get_prop_offset',
|
|
||||||
'get_next_tag_invalid_prop_len',
|
|
||||||
'getprop',
|
|
||||||
'incbin',
|
|
||||||
'integer-expressions',
|
|
||||||
'mangle-layout',
|
|
||||||
'move_and_save',
|
|
||||||
'node_check_compatible',
|
|
||||||
'node_offset_by_compatible',
|
|
||||||
'node_offset_by_phandle',
|
|
||||||
'node_offset_by_prop_value',
|
|
||||||
'nop_node',
|
|
||||||
'nop_property',
|
|
||||||
'nopulate',
|
|
||||||
'notfound',
|
|
||||||
'open_pack',
|
|
||||||
'overlay',
|
|
||||||
'overlay_bad_fixup',
|
|
||||||
'parent_offset',
|
|
||||||
'path-references',
|
|
||||||
'path_offset',
|
|
||||||
'path_offset_aliases',
|
|
||||||
'phandle_format',
|
|
||||||
'property_iterate',
|
|
||||||
'propname_escapes',
|
|
||||||
'references',
|
|
||||||
'relref_merge',
|
|
||||||
'root_node',
|
|
||||||
'rw_oom',
|
|
||||||
'rw_tree1',
|
|
||||||
'set_name',
|
|
||||||
'setprop',
|
|
||||||
'setprop_inplace',
|
|
||||||
'sized_cells',
|
|
||||||
'string_escapes',
|
|
||||||
'stringlist',
|
|
||||||
'subnode_iterate',
|
|
||||||
'subnode_offset',
|
|
||||||
'supernode_atdepth_offset',
|
|
||||||
'sw_states',
|
|
||||||
'sw_tree1',
|
|
||||||
'utilfdt_test',
|
|
||||||
]
|
|
||||||
|
|
||||||
tests += [
|
|
||||||
'truncated_memrsv',
|
|
||||||
'truncated_property',
|
|
||||||
'truncated_string',
|
|
||||||
]
|
|
||||||
|
|
||||||
test_deps = [testutil_dep, util_dep, libfdt_dep]
|
|
||||||
|
|
||||||
dl = cc.find_library('dl', required: false)
|
|
||||||
if dl.found()
|
|
||||||
tests += [
|
|
||||||
'asm_tree_dump',
|
|
||||||
'value-labels',
|
|
||||||
]
|
|
||||||
test_deps += [dl]
|
|
||||||
endif
|
|
||||||
|
|
||||||
tests_exe = []
|
|
||||||
foreach t: tests
|
|
||||||
tests_exe += executable(t, files(t + '.c'), dependencies: test_deps, build_by_default: false)
|
|
||||||
endforeach
|
|
||||||
|
|
||||||
run_tests = find_program('run_tests.sh')
|
|
||||||
|
|
||||||
env = []
|
|
||||||
if not py.found()
|
|
||||||
env += 'NO_PYTHON=1'
|
|
||||||
else
|
|
||||||
env += [
|
|
||||||
'PYTHON=' + py.full_path(),
|
|
||||||
'PYTHONPATH=' + meson.project_source_root() / 'pylibfdt',
|
|
||||||
'NO_PYTHON=0',
|
|
||||||
]
|
|
||||||
endif
|
|
||||||
if not yaml.found()
|
|
||||||
env += 'NO_YAML=1'
|
|
||||||
else
|
|
||||||
env += 'NO_YAML=0'
|
|
||||||
endif
|
|
||||||
|
|
||||||
run_test_types = [
|
|
||||||
'libfdt',
|
|
||||||
'utilfdt',
|
|
||||||
'dtc',
|
|
||||||
'dtbs_equal',
|
|
||||||
'fdtget',
|
|
||||||
'fdtput',
|
|
||||||
'fdtdump',
|
|
||||||
'fdtoverlay'
|
|
||||||
]
|
|
||||||
run_test_deps = [
|
|
||||||
dtc_tools, dumptrees_dtb, tests_exe
|
|
||||||
]
|
|
||||||
if pylibfdt_enabled
|
|
||||||
run_test_types += 'pylibfdt'
|
|
||||||
run_test_deps += pylibfdt
|
|
||||||
endif
|
|
||||||
foreach test_type : run_test_types
|
|
||||||
test(
|
|
||||||
test_type,
|
|
||||||
run_tests,
|
|
||||||
args: ['-t', test_type],
|
|
||||||
is_parallel: false,
|
|
||||||
workdir: meson.current_build_dir(),
|
|
||||||
depends: run_test_deps,
|
|
||||||
env: env,
|
|
||||||
timeout: 1800, # mostly for valgrind
|
|
||||||
)
|
|
||||||
endforeach
|
|
|
@ -43,8 +43,7 @@ static int nopulate_struct(char *buf, const char *fdt)
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
char *fdt, *fdt2, *buf;
|
char *fdt, *fdt2, *buf;
|
||||||
int newsize, struct_end_old, struct_end_new, delta;
|
int newsize, struct_start, struct_end_old, struct_end_new, delta;
|
||||||
unsigned int struct_start;
|
|
||||||
const char *inname;
|
const char *inname;
|
||||||
char outname[PATH_MAX];
|
char outname[PATH_MAX];
|
||||||
|
|
||||||
|
@ -65,7 +64,7 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
verbose_printf("Nopulated structure block has new size %d\n", newsize);
|
verbose_printf("Nopulated structure block has new size %d\n", newsize);
|
||||||
|
|
||||||
/* Replace old structure block with the new */
|
/* Replace old strcutre block with the new */
|
||||||
|
|
||||||
fdt2 = xmalloc(fdt_totalsize(fdt) + newsize);
|
fdt2 = xmalloc(fdt_totalsize(fdt) + newsize);
|
||||||
|
|
||||||
|
|
|
@ -35,11 +35,7 @@ static int fdt_getprop_u32_by_poffset(void *fdt, const char *path,
|
||||||
return node_off;
|
return node_off;
|
||||||
|
|
||||||
val = fdt_getprop(fdt, node_off, name, &len);
|
val = fdt_getprop(fdt, node_off, name, &len);
|
||||||
if (val && len < 0)
|
if (!val || (len < (sizeof(uint32_t) * (poffset + 1))))
|
||||||
FAIL("fdt_getprop() returns negative length");
|
|
||||||
if (!val && len < 0)
|
|
||||||
return len;
|
|
||||||
if (!val || ((unsigned)len < (sizeof(uint32_t) * (poffset + 1))))
|
|
||||||
return -FDT_ERR_NOTFOUND;
|
return -FDT_ERR_NOTFOUND;
|
||||||
|
|
||||||
*out = fdt32_to_cpu(*(val + poffset));
|
*out = fdt32_to_cpu(*(val + poffset));
|
||||||
|
@ -186,7 +182,6 @@ static void *open_dt(char *path)
|
||||||
* Resize our DTs to 4k so that we have room to operate on
|
* Resize our DTs to 4k so that we have room to operate on
|
||||||
*/
|
*/
|
||||||
CHECK(fdt_open_into(dt, copy, FDT_COPY_SIZE));
|
CHECK(fdt_open_into(dt, copy, FDT_COPY_SIZE));
|
||||||
free(dt);
|
|
||||||
|
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2024 Uwe Kleine-König
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0+
|
|
||||||
*/
|
|
||||||
|
|
||||||
/dts-v1/;
|
|
||||||
|
|
||||||
/ {
|
|
||||||
node_a: a {
|
|
||||||
value = <17>;
|
|
||||||
};
|
|
||||||
|
|
||||||
node_b: b {
|
|
||||||
a = <&node_a>;
|
|
||||||
};
|
|
||||||
|
|
||||||
node_d: d {
|
|
||||||
b = <&node_b>;
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -46,7 +46,3 @@
|
||||||
new-sub-test-property;
|
new-sub-test-property;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
&{/new-local-node} {
|
|
||||||
another-new-property;
|
|
||||||
};
|
|
||||||
|
|
|
@ -72,14 +72,6 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
fragment@7 {
|
|
||||||
target-path = "/new-local-node";
|
|
||||||
|
|
||||||
__overlay__ {
|
|
||||||
another-new-property;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
__local_fixups__ {
|
__local_fixups__ {
|
||||||
fragment@5 {
|
fragment@5 {
|
||||||
__overlay__ {
|
__overlay__ {
|
||||||
|
|
|
@ -48,7 +48,7 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
fragment@4 {
|
fragment@5 {
|
||||||
target = <&test>;
|
target = <&test>;
|
||||||
|
|
||||||
__overlay__ {
|
__overlay__ {
|
||||||
|
@ -58,7 +58,7 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
fragment@5 {
|
fragment@6 {
|
||||||
target = <&test>;
|
target = <&test>;
|
||||||
|
|
||||||
__overlay__ {
|
__overlay__ {
|
||||||
|
@ -66,7 +66,7 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
fragment@6 {
|
fragment@7 {
|
||||||
target = <&test>;
|
target = <&test>;
|
||||||
|
|
||||||
__overlay__ {
|
__overlay__ {
|
||||||
|
@ -74,7 +74,7 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
fragment@7 {
|
fragment@8 {
|
||||||
target = <&test>;
|
target = <&test>;
|
||||||
|
|
||||||
__overlay__ {
|
__overlay__ {
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2024 Uwe Kleine-König
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0+
|
|
||||||
*/
|
|
||||||
|
|
||||||
/dts-v1/;
|
|
||||||
/plugin/;
|
|
||||||
|
|
||||||
&{/} {
|
|
||||||
/*
|
|
||||||
* /b already has a label "node_b" in the base dts, also b is already
|
|
||||||
* referenced in the base, so both the base's b and this b have a
|
|
||||||
* phandle value.
|
|
||||||
*/
|
|
||||||
node_b2: b {
|
|
||||||
value = <42>;
|
|
||||||
d = <&node_d>;
|
|
||||||
};
|
|
||||||
|
|
||||||
node_c: c {
|
|
||||||
value = <23>;
|
|
||||||
b = <&node_b2>;
|
|
||||||
};
|
|
||||||
|
|
||||||
d {
|
|
||||||
a = <&node_a>;
|
|
||||||
c = <&node_c>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
&node_a {
|
|
||||||
value = <32>;
|
|
||||||
};
|
|
|
@ -53,7 +53,7 @@ int main(int argc, char *argv[])
|
||||||
void *fdt;
|
void *fdt;
|
||||||
const char *p;
|
const char *p;
|
||||||
int len, multilen;
|
int len, multilen;
|
||||||
int n1, n2, n3, n4, n5;
|
int n1, n2, n3, n4;
|
||||||
|
|
||||||
test_init(argc, argv);
|
test_init(argc, argv);
|
||||||
fdt = load_blob_arg(argc, argv);
|
fdt = load_blob_arg(argc, argv);
|
||||||
|
@ -89,12 +89,6 @@ int main(int argc, char *argv[])
|
||||||
check_ref(fdt, n3, "/foobar/baz");
|
check_ref(fdt, n3, "/foobar/baz");
|
||||||
check_ref(fdt, n4, "/foo/baz");
|
check_ref(fdt, n4, "/foo/baz");
|
||||||
|
|
||||||
n5 = fdt_path_offset(fdt, "/bar/baz");
|
|
||||||
if (n5 < 0)
|
|
||||||
FAIL("fdt_path_offset(/bar/baz): %s", fdt_strerror(n5));
|
|
||||||
|
|
||||||
check_ref(fdt, n5, "/bar/baz");
|
|
||||||
|
|
||||||
check_rref(fdt);
|
check_rref(fdt);
|
||||||
|
|
||||||
PASS();
|
PASS();
|
||||||
|
|
|
@ -25,13 +25,4 @@
|
||||||
lref = &n3;
|
lref = &n3;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
n5: bar {
|
|
||||||
baz {
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
n6: &{n5/baz} {
|
|
||||||
ref = &{n6/};
|
|
||||||
lref = &{n5/baz};
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -41,25 +41,22 @@ static int check_subnode(void *fdt, int parent, const char *name)
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void check_path_offset(void *fdt, const char *path, int offset)
|
static void check_path_offset(void *fdt, char *path, int offset)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
verbose_printf("Checking offset of \"%s\" is %d...\n", path, offset);
|
verbose_printf("Checking offset of \"%s\" is %d...\n", path, offset);
|
||||||
|
|
||||||
rc = fdt_path_offset(fdt, path);
|
rc = fdt_path_offset(fdt, path);
|
||||||
if (rc == offset)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
FAIL("fdt_path_offset(\"%s\") failed: %s",
|
FAIL("fdt_path_offset(\"%s\") failed: %s",
|
||||||
path, fdt_strerror(rc));
|
path, fdt_strerror(rc));
|
||||||
else
|
if (rc != offset)
|
||||||
FAIL("fdt_path_offset(\"%s\") returned incorrect offset"
|
FAIL("fdt_path_offset(\"%s\") returned incorrect offset"
|
||||||
" %d instead of %d", path, rc, offset);
|
" %d instead of %d", path, rc, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void check_path_offset_namelen(void *fdt, const char *path, int namelen,
|
static void check_path_offset_namelen(void *fdt, char *path, int namelen,
|
||||||
int offset)
|
int offset)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
@ -105,7 +102,6 @@ int main(int argc, char *argv[])
|
||||||
check_path_offset(fdt, "/subnode@2/subsubnode", subsubnode2_offset2);
|
check_path_offset(fdt, "/subnode@2/subsubnode", subsubnode2_offset2);
|
||||||
|
|
||||||
/* Test paths with extraneous separators */
|
/* Test paths with extraneous separators */
|
||||||
check_path_offset(fdt, "", -FDT_ERR_BADPATH);
|
|
||||||
check_path_offset(fdt, "//", 0);
|
check_path_offset(fdt, "//", 0);
|
||||||
check_path_offset(fdt, "///", 0);
|
check_path_offset(fdt, "///", 0);
|
||||||
check_path_offset(fdt, "//subnode@1", subnode1_offset);
|
check_path_offset(fdt, "//subnode@1", subnode1_offset);
|
||||||
|
@ -114,8 +110,6 @@ int main(int argc, char *argv[])
|
||||||
check_path_offset(fdt, "/subnode@2////subsubnode", subsubnode2_offset2);
|
check_path_offset(fdt, "/subnode@2////subsubnode", subsubnode2_offset2);
|
||||||
|
|
||||||
/* Test fdt_path_offset_namelen() */
|
/* Test fdt_path_offset_namelen() */
|
||||||
check_path_offset_namelen(fdt, "/subnode@1", -1, -FDT_ERR_BADPATH);
|
|
||||||
check_path_offset_namelen(fdt, "/subnode@1", 0, -FDT_ERR_BADPATH);
|
|
||||||
check_path_offset_namelen(fdt, "/subnode@1", 1, 0);
|
check_path_offset_namelen(fdt, "/subnode@1", 1, 0);
|
||||||
check_path_offset_namelen(fdt, "/subnode@1/subsubnode", 10, subnode1_offset);
|
check_path_offset_namelen(fdt, "/subnode@1/subsubnode", 10, subnode1_offset);
|
||||||
check_path_offset_namelen(fdt, "/subnode@1/subsubnode", 11, subnode1_offset);
|
check_path_offset_namelen(fdt, "/subnode@1/subsubnode", 11, subnode1_offset);
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue