mirror of
https://github.com/dgibson/dtc.git
synced 2026-07-10 13:29:48 -04:00
Compare commits
26 commits
47d7c01ba8
...
66e1201c37
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
66e1201c37 | ||
|
|
214372a273 | ||
|
|
4df9ca4c8d | ||
|
|
f116f4800e | ||
|
|
9b53b9a4c2 | ||
|
|
5f919a25d7 | ||
|
|
6c1426dfa9 | ||
|
|
23fd89bc8e | ||
|
|
3ad5ebbdd9 | ||
|
|
4ad496846a | ||
|
|
c0e1d0fd58 | ||
|
|
d245851f06 | ||
|
|
a74b952f94 | ||
|
|
d320877b07 | ||
|
|
84d13508d5 | ||
|
|
8f48565e5c | ||
|
|
25a368100a | ||
|
|
040c1f7e29 | ||
|
|
b1337df195 | ||
|
|
83cdc93ca9 | ||
|
|
1aaa44849b | ||
|
|
dd1c7f1a91 | ||
|
|
7fdf750154 | ||
|
|
5c35036b2c | ||
|
|
f57e7df35d | ||
|
|
2164019f84 |
33 changed files with 1343 additions and 654 deletions
39
.cirrus.yml
39
.cirrus.yml
|
|
@ -1,39 +0,0 @@
|
||||||
# FreeBSD build with multiple versions
|
|
||||||
freebsd_versions_task:
|
|
||||||
name: FreeBSD $FREEBSD_VERSION make build
|
|
||||||
freebsd_instance:
|
|
||||||
image_family: $FREEBSD_IMAGE
|
|
||||||
matrix:
|
|
||||||
- env:
|
|
||||||
FREEBSD_VERSION: "13.5"
|
|
||||||
FREEBSD_IMAGE: freebsd-13-5
|
|
||||||
- env:
|
|
||||||
FREEBSD_VERSION: "14.3"
|
|
||||||
FREEBSD_IMAGE: freebsd-14-3
|
|
||||||
install_script:
|
|
||||||
- pkg install -y git gmake flex bison python3 py312-setuptools swig libyaml pkgconf
|
|
||||||
build_script:
|
|
||||||
- gmake
|
|
||||||
check_script:
|
|
||||||
- gmake check
|
|
||||||
|
|
||||||
# FreeBSD meson builds with multiple versions
|
|
||||||
freebsd_meson_versions_task:
|
|
||||||
name: FreeBSD $FREEBSD_VERSION meson build
|
|
||||||
freebsd_instance:
|
|
||||||
image_family: $FREEBSD_IMAGE
|
|
||||||
matrix:
|
|
||||||
- env:
|
|
||||||
FREEBSD_VERSION: "13.5"
|
|
||||||
FREEBSD_IMAGE: freebsd-13-5
|
|
||||||
- env:
|
|
||||||
FREEBSD_VERSION: "14.3"
|
|
||||||
FREEBSD_IMAGE: freebsd-14-3
|
|
||||||
install_script:
|
|
||||||
- pkg install -y git meson ninja flex bison python3 py312-setuptools swig libyaml pkgconf
|
|
||||||
setup_script:
|
|
||||||
- meson setup -D python=enabled -D yaml=enabled build
|
|
||||||
build_script:
|
|
||||||
- meson compile -C build
|
|
||||||
test_script:
|
|
||||||
- if ! meson test -C build; then cat build/meson-logs/testlog.txt; false; fi
|
|
||||||
147
.github/workflows/build.yml
vendored
147
.github/workflows/build.yml
vendored
|
|
@ -8,6 +8,8 @@ name: Build test
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
# ensure that the workflow is only triggered once per PR, subsequent pushes to the PR will cancel
|
# 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
|
# and restart the workflow. See https://docs.github.com/en/actions/using-jobs/using-concurrency
|
||||||
|
|
@ -16,78 +18,93 @@ concurrency:
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-make:
|
build-linux:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
os: [ "alpine", "archlinux", "fedora", "ubuntu" ]
|
os: [ "alpine", "archlinux", "fedora", "ubuntu" ]
|
||||||
|
build: [ "make", "meson" ]
|
||||||
|
|
||||||
container:
|
container:
|
||||||
image: ${{ matrix.os }}
|
image: ${{ matrix.os }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
|
- name: Install Dependencies
|
||||||
|
run: ./scripts/install-deps.sh
|
||||||
|
|
||||||
|
- name: Build (Make)
|
||||||
|
if: matrix.build == 'make'
|
||||||
|
run: make
|
||||||
|
|
||||||
|
- name: Run check (Make)
|
||||||
|
if: matrix.build == 'make'
|
||||||
|
run: make check
|
||||||
|
|
||||||
|
- name: Setup (Meson)
|
||||||
|
if: matrix.build == 'meson'
|
||||||
|
run: meson setup -D python=enabled -D yaml=enabled build
|
||||||
|
|
||||||
|
- name: Build (Meson)
|
||||||
|
if: matrix.build == 'meson'
|
||||||
|
run: meson compile -C build
|
||||||
|
|
||||||
|
- name: Run check (Meson)
|
||||||
|
if: matrix.build == 'meson'
|
||||||
|
run: if ! meson test -C build; then cat build/meson-logs/testlog.txt; false; fi
|
||||||
|
|
||||||
|
build-macos:
|
||||||
|
runs-on: macos-latest
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
build: [ "make", "meson" ]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v6
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: |
|
run: |
|
||||||
./scripts/install-deps.sh
|
./scripts/install-deps.sh
|
||||||
|
|
||||||
- name: Build
|
- name: Build (Make)
|
||||||
|
if: matrix.build == 'make'
|
||||||
run: |
|
run: |
|
||||||
make
|
make
|
||||||
|
|
||||||
- name: Run check
|
- name: Setup (Meson)
|
||||||
run: |
|
if: matrix.build == 'meson'
|
||||||
make check
|
run: meson setup -D python=enabled -D yaml=enabled -D tests=false build
|
||||||
|
|
||||||
build-meson:
|
- name: Build (Meson)
|
||||||
runs-on: ubuntu-latest
|
if: matrix.build == 'meson'
|
||||||
|
|
||||||
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
|
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:
|
build-windows:
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- { sys: mingw32 }
|
- { sys: mingw32, swig: false }
|
||||||
- { sys: mingw64 }
|
- { sys: mingw64, swig: true }
|
||||||
- { sys: ucrt64 }
|
- { sys: ucrt64, swig: true }
|
||||||
- { sys: clang64 }
|
- { sys: clang64, swig: true }
|
||||||
name: ${{ matrix.sys }}
|
name: ${{ matrix.sys }}
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
shell: msys2 {0}
|
shell: msys2 {0}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
|
@ -105,10 +122,60 @@ jobs:
|
||||||
meson:p
|
meson:p
|
||||||
ninja:p
|
ninja:p
|
||||||
libyaml:p
|
libyaml:p
|
||||||
swig:p
|
${{ matrix.swig && 'swig:p python-setuptools-scm:p' || '' }}
|
||||||
python-setuptools-scm:p
|
|
||||||
|
|
||||||
- name: '🚧 Build'
|
- name: '🚧 Build'
|
||||||
run: |
|
run: |
|
||||||
meson setup -Dtools=true -Dtests=false build
|
meson setup -Dtools=true -Dtests=false build
|
||||||
meson compile -C build
|
meson compile -C build
|
||||||
|
|
||||||
|
build-freebsd:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
version: [ "13.5", "14.3" ]
|
||||||
|
build: [ "make", "meson" ]
|
||||||
|
|
||||||
|
name: FreeBSD ${{ matrix.version }} ${{ matrix.build }} build
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
|
- name: Start VM
|
||||||
|
uses: cross-platform-actions/action@v1
|
||||||
|
with:
|
||||||
|
operating_system: freebsd
|
||||||
|
version: ${{ matrix.version }}
|
||||||
|
shell: sh
|
||||||
|
|
||||||
|
- name: Install Dependencies
|
||||||
|
shell: cpa.sh {0}
|
||||||
|
run: sudo ./scripts/install-deps.sh
|
||||||
|
|
||||||
|
- name: Build (Make)
|
||||||
|
if: matrix.build == 'make'
|
||||||
|
shell: cpa.sh {0}
|
||||||
|
run: gmake
|
||||||
|
|
||||||
|
- name: Run check (Make)
|
||||||
|
if: matrix.build == 'make'
|
||||||
|
shell: cpa.sh {0}
|
||||||
|
run: gmake check
|
||||||
|
|
||||||
|
- name: Setup (Meson)
|
||||||
|
if: matrix.build == 'meson'
|
||||||
|
shell: cpa.sh {0}
|
||||||
|
run: meson setup -D python=enabled -D yaml=enabled build
|
||||||
|
|
||||||
|
- name: Build (Meson)
|
||||||
|
if: matrix.build == 'meson'
|
||||||
|
shell: cpa.sh {0}
|
||||||
|
run: meson compile -C build
|
||||||
|
|
||||||
|
- name: Run check (Meson)
|
||||||
|
if: matrix.build == 'meson'
|
||||||
|
shell: cpa.sh {0}
|
||||||
|
run: if ! meson test -C build; then cat build/meson-logs/testlog.txt; false; fi
|
||||||
|
|
|
||||||
138
AGENTS.md
Normal file
138
AGENTS.md
Normal file
|
|
@ -0,0 +1,138 @@
|
||||||
|
# AGENTS.md
|
||||||
|
|
||||||
|
This file provides guidance to AI coding assistants when working with
|
||||||
|
code in this repository.
|
||||||
|
|
||||||
|
## Build and Test
|
||||||
|
|
||||||
|
The build system is Meson (the legacy Makefile still works but is
|
||||||
|
deprecated).
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# Configure and build
|
||||||
|
meson setup build
|
||||||
|
meson compile -C build
|
||||||
|
|
||||||
|
# Run all tests
|
||||||
|
meson test -C build
|
||||||
|
|
||||||
|
# Run a specific test suite (libfdt, dtc, fdtget, fdtput, fdtdump, fdtoverlay, pylibfdt, utilfdt, dtbs_equal)
|
||||||
|
meson test -C build dtc
|
||||||
|
meson test -C build libfdt
|
||||||
|
|
||||||
|
# Legacy make (deprecated, still functional)
|
||||||
|
make
|
||||||
|
make check # all tests
|
||||||
|
make checkm # tests under valgrind
|
||||||
|
```
|
||||||
|
|
||||||
|
Optional build dependencies: libyaml (>= 0.2.3) for YAML output,
|
||||||
|
valgrind for memory checking, swig + python3-dev for pylibfdt.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
The repo contains three main components:
|
||||||
|
|
||||||
|
### dtc (Device Tree Compiler)
|
||||||
|
|
||||||
|
Compiles device tree source (.dts) to binary (.dtb) and vice versa. The pipeline is: parse source → live tree → flatten to blob (or reverse).
|
||||||
|
|
||||||
|
- **Parsing**: `dtc-lexer.l` (flex) + `dtc-parser.y` (bison) produce a live tree from .dts source. `flattree.c` reads .dtb blobs. `fstree.c` reads /proc/device-tree style filesystem trees. `yamltree.c` writes YAML output.
|
||||||
|
|
||||||
|
- **Live tree** (`livetree.c`, `dtc.h`): In-memory representation as `struct node` / `struct property` trees with labels, phandles, and source position tracking. The `struct data` type carries property values with type markers and cross-reference markers.
|
||||||
|
- **Checks** (`checks.c`): ~50 semantic checks registered via `WARNING()`, `ERROR()`, and `CHECK()` macros into a `check_table[]`. Each check declares prerequisite checks, forming a DAG. Checks validate DT conventions (node naming, property types, interrupt structures, etc.). Use `-W`/`-E` flags to promote/demote.
|
||||||
|
- **Output**: `flattree.c` writes .dtb blobs and assembler output. `treesource.c` writes .dts source.
|
||||||
|
|
||||||
|
### libfdt (Flat Device Tree library)
|
||||||
|
|
||||||
|
C library for reading/writing .dtb blobs in-place, dual-licensed
|
||||||
|
GPL-2.0-or-later OR BSD-2-Clause. Used in bootloaders, kernels, and
|
||||||
|
hypervisors where the full compiler isn't available.
|
||||||
|
|
||||||
|
- `fdt_ro.c` — read-only access (property lookup, node traversal)
|
||||||
|
- `fdt_rw.c` — read-write modification of existing blobs
|
||||||
|
- `fdt_sw.c` — sequential-write creation of new blobs
|
||||||
|
- `fdt_wip.c` — "write in place" operations (in-place modification)
|
||||||
|
- `fdt_overlay.c` — device tree overlay application
|
||||||
|
- `fdt_check.c` — blob validation (`fdt_check_full`)
|
||||||
|
- `fdt_addresses.c` — address/size cell helpers
|
||||||
|
- `version.lds` — exported symbol list; new public functions must be added here
|
||||||
|
|
||||||
|
libfdt is designed to be embeddable: `Makefile.libfdt` can be included
|
||||||
|
by external build systems. The `FDT_ASSUME_MASK` controls safety
|
||||||
|
vs. performance tradeoffs (see `libfdt_internal.h`).
|
||||||
|
|
||||||
|
### pylibfdt
|
||||||
|
|
||||||
|
SWIG-generated Python bindings for libfdt
|
||||||
|
(`pylibfdt/libfdt.i`). Functions not supportable by SWIG should be
|
||||||
|
behind `#ifndef SWIG` in `libfdt.h`.
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
|
||||||
|
Tests live in `tests/`. The test runner is `tests/run_tests.sh` which
|
||||||
|
defines test groups: `libfdt_tests`, `dtc_tests`, `fdtget_tests`,
|
||||||
|
`fdtput_tests`, `fdtoverlay_tests`, `pylibfdt_tests`, etc.
|
||||||
|
|
||||||
|
Individual C test programs link against libfdt and use helpers from
|
||||||
|
`tests/testutils.c`. Binary test trees are built from assembler macros
|
||||||
|
in `tests/trees.S` via `tests/dumptrees.c` — if you modify
|
||||||
|
`tests/test_tree1.dts`, you must also update `tests/trees.S`.
|
||||||
|
|
||||||
|
## AI Contribution Policy
|
||||||
|
|
||||||
|
See the "AI Coding Assistants" section in CONTRIBUTING.md. Key rules:
|
||||||
|
|
||||||
|
- **Do not** add `Signed-off-by` tags — only humans can certify the DCO
|
||||||
|
- Use `Assisted-by: AGENT_NAME:MODEL_VERSION [TOOL1] [TOOL2]` for attribution in commit messages
|
||||||
|
- The human submitter is responsible for reviewing all AI-generated code and ensuring license compliance
|
||||||
|
- Do not add `Co-authored-by` tags.
|
||||||
|
|
||||||
|
## Tagging a New Release
|
||||||
|
|
||||||
|
Releases use the `vMAJOR.MINOR.PATCH` tag format (e.g., `v1.7.2`).
|
||||||
|
|
||||||
|
An AI agent can prepare the release; the human maintainer reviews,
|
||||||
|
adds `Signed-off-by`, and signs the tag.
|
||||||
|
|
||||||
|
1. **Update `VERSION.txt` and commit** — run the prepare script:
|
||||||
|
```sh
|
||||||
|
scripts/prepare-release X.Y.Z
|
||||||
|
```
|
||||||
|
This updates `VERSION.txt` and creates the version bump commit
|
||||||
|
(without `Signed-off-by`, per the AI contribution policy).
|
||||||
|
|
||||||
|
2. **Draft the tag message** — write it to a temporary file (e.g.,
|
||||||
|
`tag-message.txt`) for the maintainer to review. The format is:
|
||||||
|
```
|
||||||
|
DTC X.Y.Z
|
||||||
|
|
||||||
|
Changes since vPREV include:
|
||||||
|
* Component
|
||||||
|
- Change description
|
||||||
|
- ...
|
||||||
|
```
|
||||||
|
Group changes by component (dtc, libfdt, pylibfdt, fdtget,
|
||||||
|
fdtoverlay, Build, General, etc.) with a bullet per notable change.
|
||||||
|
Generate the changelog from `git log vPREV..HEAD`.
|
||||||
|
|
||||||
|
3. **Human review** — the maintainer reviews the commit and tag
|
||||||
|
message, then runs the finalize script which amends the commit to
|
||||||
|
add `Signed-off-by`, creates the signed annotated tag, pushes the
|
||||||
|
release commit and tag to origin, and optionally uploads to
|
||||||
|
kernel.org via kup:
|
||||||
|
```sh
|
||||||
|
scripts/finalize-release tag-message.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
Agents must **never** run `scripts/finalize-release` or
|
||||||
|
`scripts/kup-dtc`. These perform signing, push, and upload operations
|
||||||
|
that only a human maintainer may execute.
|
||||||
|
|
||||||
|
## Coding Conventions
|
||||||
|
|
||||||
|
- License: GPL-2.0-or-later for dtc tools; (GPL-2.0-or-later OR BSD-2-Clause) for libfdt
|
||||||
|
- SPDX identifiers on every file
|
||||||
|
- C style follows kernel conventions: tabs for indentation, `lower_case` names
|
||||||
|
- Compiler warnings are errors (`-Werror`)
|
||||||
|
- libfdt functions return negative `FDT_ERR_*` codes on failure (never errno)
|
||||||
17
CLAUDE.md
Normal file
17
CLAUDE.md
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
Read and follow AGENTS.md — it has build instructions, architecture
|
||||||
|
notes, coding conventions, and the AI contribution policy for this
|
||||||
|
project.
|
||||||
|
|
||||||
|
## Claude Code Specifics
|
||||||
|
|
||||||
|
When writing `Assisted-by` commit trailers, use `Claude` as the agent
|
||||||
|
name and the model's short ID as the version. For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
Assisted-by: Claude:claude-opus-4-6
|
||||||
|
```
|
||||||
|
|
||||||
|
Do not use `claude-code`, `Claude Code`, or other variations as the
|
||||||
|
agent name.
|
||||||
|
|
@ -77,3 +77,51 @@ from people handling and transporting the patch, but were not involved
|
||||||
in its development. SoB chains should reflect the **real** route a
|
in its development. SoB chains should reflect the **real** route a
|
||||||
patch took as it was propagated to the maintainers, with the first SoB
|
patch took as it was propagated to the maintainers, with the first SoB
|
||||||
entry signalling primary authorship of a single author.
|
entry signalling primary authorship of a single author.
|
||||||
|
|
||||||
|
## AI Coding Assistants
|
||||||
|
|
||||||
|
AI tools helping with dtc/libfdt development must follow the standard
|
||||||
|
contribution process described in this document.
|
||||||
|
|
||||||
|
### Licensing and Legal Requirements
|
||||||
|
|
||||||
|
All contributions must comply with the project's licensing requirements:
|
||||||
|
|
||||||
|
* All code must be compatible with GPL-2.0-or-later
|
||||||
|
* All libfdt code must also be compatible with BSD-2-Clause
|
||||||
|
* Use appropriate SPDX license identifiers
|
||||||
|
|
||||||
|
### Signed-off-by and Developer Certificate of Origin
|
||||||
|
|
||||||
|
AI agents MUST NOT add Signed-off-by tags. Only humans can legally
|
||||||
|
certify the Developer Certificate of Origin (DCO). The human submitter
|
||||||
|
is responsible for:
|
||||||
|
|
||||||
|
* Reviewing all AI-generated code
|
||||||
|
* Ensuring compliance with licensing requirements
|
||||||
|
* Adding their own Signed-off-by tag to certify the DCO
|
||||||
|
* Taking full responsibility for the contribution
|
||||||
|
|
||||||
|
### Attribution
|
||||||
|
|
||||||
|
When AI tools contribute to development, proper attribution helps track
|
||||||
|
the evolving role of AI in the development process. Contributions
|
||||||
|
should include an `Assisted-by` tag in the following format:
|
||||||
|
|
||||||
|
```
|
||||||
|
Assisted-by: AGENT_NAME:MODEL_VERSION [TOOL1] [TOOL2]
|
||||||
|
```
|
||||||
|
|
||||||
|
Where:
|
||||||
|
|
||||||
|
* `AGENT_NAME` is the name of the AI tool or framework
|
||||||
|
* `MODEL_VERSION` is the specific model version used
|
||||||
|
* `[TOOL1] [TOOL2]` are optional specialized analysis tools used
|
||||||
|
(e.g., coccinelle, sparse, smatch, clang-tidy)
|
||||||
|
|
||||||
|
Basic development tools (git, gcc, make, editors) should not be listed.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```
|
||||||
|
Assisted-by: Claude:claude-3-opus coccinelle sparse
|
||||||
|
```
|
||||||
|
|
|
||||||
28
Makefile
28
Makefile
|
|
@ -153,6 +153,11 @@ include Makefile.convert-dtsv0
|
||||||
include Makefile.dtc
|
include Makefile.dtc
|
||||||
include Makefile.utils
|
include Makefile.utils
|
||||||
|
|
||||||
|
# Flex-generated source triggers -Wsign-compare in its templates
|
||||||
|
dtc-lexer.lex.o: CFLAGS += -Wno-sign-compare
|
||||||
|
convert-dtsv0-lexer.lex.o: CFLAGS += -Wno-sign-compare
|
||||||
|
|
||||||
|
|
||||||
BIN += convert-dtsv0
|
BIN += convert-dtsv0
|
||||||
BIN += dtc
|
BIN += dtc
|
||||||
BIN += fdtdump
|
BIN += fdtdump
|
||||||
|
|
@ -255,29 +260,6 @@ fdtput: $(FDTPUT_OBJS) $(LIBFDT_dep)
|
||||||
|
|
||||||
fdtoverlay: $(FDTOVERLAY_OBJS) $(LIBFDT_dep)
|
fdtoverlay: $(FDTOVERLAY_OBJS) $(LIBFDT_dep)
|
||||||
|
|
||||||
dist:
|
|
||||||
git archive --format=tar --prefix=dtc-$(dtc_version)/ HEAD \
|
|
||||||
> ../dtc-$(dtc_version).tar
|
|
||||||
cat ../dtc-$(dtc_version).tar | \
|
|
||||||
gzip -9 > ../dtc-$(dtc_version).tar.gz
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# Release signing and uploading
|
|
||||||
# This is for maintainer convenience, don't try this at home.
|
|
||||||
#
|
|
||||||
ifeq ($(MAINTAINER),y)
|
|
||||||
GPG = gpg2
|
|
||||||
KUP = kup
|
|
||||||
KUPDIR = /pub/software/utils/dtc
|
|
||||||
|
|
||||||
kup: dist
|
|
||||||
$(GPG) --detach-sign --armor -o ../dtc-$(dtc_version).tar.sign \
|
|
||||||
../dtc-$(dtc_version).tar
|
|
||||||
$(KUP) put ../dtc-$(dtc_version).tar.gz ../dtc-$(dtc_version).tar.sign \
|
|
||||||
$(KUPDIR)/dtc-$(dtc_version).tar.gz
|
|
||||||
endif
|
|
||||||
|
|
||||||
tags: FORCE
|
tags: FORCE
|
||||||
rm -f tags
|
rm -f tags
|
||||||
find . \( -name tests -type d -prune \) -o \
|
find . \( -name tests -type d -prune \) -o \
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
1.7.2
|
1.8.1
|
||||||
|
|
|
||||||
2
checks.c
2
checks.c
|
|
@ -1769,7 +1769,7 @@ static void check_interrupts_property(struct check *c,
|
||||||
irq_prop->val.len, (int)(irq_cells * sizeof(cell_t)));
|
irq_prop->val.len, (int)(irq_cells * sizeof(cell_t)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WARNING(interrupts_property, check_interrupts_property, &phandle_references);
|
WARNING(interrupts_property, check_interrupts_property, NULL, &phandle_references);
|
||||||
|
|
||||||
static const struct bus_type graph_port_bus = {
|
static const struct bus_type graph_port_bus = {
|
||||||
.name = "graph-port",
|
.name = "graph-port",
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,8 @@ int fdt_check_full(const void *fdt, size_t bufsize)
|
||||||
const char *propname;
|
const char *propname;
|
||||||
bool expect_end = false;
|
bool expect_end = false;
|
||||||
|
|
||||||
|
if (can_assume(PERFECT))
|
||||||
|
return 0;
|
||||||
if (bufsize < FDT_V1_SIZE)
|
if (bufsize < FDT_V1_SIZE)
|
||||||
return -FDT_ERR_TRUNCATED;
|
return -FDT_ERR_TRUNCATED;
|
||||||
if (bufsize < fdt_header_size(fdt))
|
if (bufsize < fdt_header_size(fdt))
|
||||||
|
|
|
||||||
|
|
@ -292,6 +292,13 @@ int fdt_setprop_placeholder_namelen(void *fdt, int nodeoffset, const char *name,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int fdt_setprop_placeholder(void *fdt, int nodeoffset,
|
||||||
|
const char *name, int len, void **prop_data)
|
||||||
|
{
|
||||||
|
return fdt_setprop_placeholder_namelen(fdt, nodeoffset, name,
|
||||||
|
strlen(name), len, prop_data);
|
||||||
|
}
|
||||||
|
|
||||||
int fdt_setprop_namelen(void *fdt, int nodeoffset, const char *name,
|
int fdt_setprop_namelen(void *fdt, int nodeoffset, const char *name,
|
||||||
int namelen, const void *val, int len)
|
int namelen, const void *val, int len)
|
||||||
{
|
{
|
||||||
|
|
@ -308,6 +315,13 @@ int fdt_setprop_namelen(void *fdt, int nodeoffset, const char *name,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int fdt_setprop(void *fdt, int nodeoffset, const char *name,
|
||||||
|
const void *val, int len)
|
||||||
|
{
|
||||||
|
return fdt_setprop_namelen(fdt, nodeoffset, name, strlen(name), val,
|
||||||
|
len);
|
||||||
|
}
|
||||||
|
|
||||||
int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
|
int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
|
||||||
const void *val, int len)
|
const void *val, int len)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -330,7 +330,8 @@ int fdt_property(void *fdt, const char *name, const void *val, int len)
|
||||||
ret = fdt_property_placeholder(fdt, name, len, &ptr);
|
ret = fdt_property_placeholder(fdt, name, len, &ptr);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
memcpy(ptr, val, len);
|
if (len)
|
||||||
|
memcpy(ptr, val, len);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1935,12 +1935,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_setprop_placeholder_namelen - allocate space for a property
|
||||||
|
|
@ -2002,13 +1998,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, int len,
|
const char *name, 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
|
||||||
|
|
|
||||||
|
|
@ -1234,7 +1234,7 @@ void fixup_phandles(struct dt_info *dti, const char *name)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
offset = strtol(soffset, NULL, 0);
|
offset = strtol(soffset, NULL, 0);
|
||||||
if (offset < 0 || offset + 4 > p->val.len) {
|
if (offset < 0 || (unsigned int)offset + 4 > p->val.len) {
|
||||||
if (quiet < 1)
|
if (quiet < 1)
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Warning: Label %s contains invalid offset for property %s in node %s\n",
|
"Warning: Label %s contains invalid offset for property %s in node %s\n",
|
||||||
|
|
|
||||||
98
scripts/finalize-release
Executable file
98
scripts/finalize-release
Executable file
|
|
@ -0,0 +1,98 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
#
|
||||||
|
# Finalize a release (possibly prepared with AI agent assistance)
|
||||||
|
# Amends the version bump commit to add Signed-off-by, then creates a
|
||||||
|
# signed annotated tag from the drafted tag message.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo "Usage: $0 <tag-message-file>" >&2
|
||||||
|
echo "" >&2
|
||||||
|
echo "Run this from the repository root with VERSION.txt updated" >&2
|
||||||
|
echo "and a draft tag message in given file." >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
TAG_MSG_FILE="$1"
|
||||||
|
if [ -z "$TAG_MSG_FILE" ] || [ ! -f "$TAG_MSG_FILE" ]; then
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
VERSION=$(cat VERSION.txt)
|
||||||
|
TAG="v${VERSION}"
|
||||||
|
|
||||||
|
if git rev-parse "$TAG" >/dev/null 2>&1; then
|
||||||
|
echo "Error: tag $TAG already exists" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
HEAD_SUBJECT=$(git log -1 --format=%s)
|
||||||
|
EXPECTED="Bump version to $TAG"
|
||||||
|
if [ "$HEAD_SUBJECT" != "$EXPECTED" ]; then
|
||||||
|
echo "Error: HEAD commit subject is:" >&2
|
||||||
|
echo " $HEAD_SUBJECT" >&2
|
||||||
|
echo "Expected:" >&2
|
||||||
|
echo " $EXPECTED" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Version: $VERSION"
|
||||||
|
echo "Tag: $TAG"
|
||||||
|
echo ""
|
||||||
|
echo "--- Tag message ---"
|
||||||
|
cat "$TAG_MSG_FILE"
|
||||||
|
echo "--- End tag message ---"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
printf "Proceed? [y/N] "
|
||||||
|
read answer
|
||||||
|
case "$answer" in
|
||||||
|
y|Y) ;;
|
||||||
|
*) echo "Aborted."; exit 1 ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
git commit --amend -s --no-edit
|
||||||
|
git tag -s "$TAG" -F "$TAG_MSG_FILE"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Created signed tag $TAG."
|
||||||
|
echo "Review with: git show $TAG"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
git push origin main "$TAG"
|
||||||
|
git push github main "$TAG"
|
||||||
|
git push gitlab main "$TAG"
|
||||||
|
|
||||||
|
SCRIPTDIR=$(dirname "$0")
|
||||||
|
|
||||||
|
printf "Upload to kernel.org via kup? [y/N] "
|
||||||
|
read answer
|
||||||
|
case "$answer" in
|
||||||
|
y|Y) "$SCRIPTDIR/kup-dtc" "$VERSION" ;;
|
||||||
|
*) echo "Skipping kup upload." ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
TAG_BODY=$(git tag -l --format='%(contents:body)' "$TAG")
|
||||||
|
|
||||||
|
ANNOUNCE="announce-${TAG}.txt"
|
||||||
|
cat > "$ANNOUNCE" <<MAIL
|
||||||
|
To: devicetree-compiler@vger.kernel.org
|
||||||
|
Subject: DTC $VERSION released
|
||||||
|
|
||||||
|
DTC $VERSION is now available.
|
||||||
|
|
||||||
|
Git tree:
|
||||||
|
https://git.kernel.org/pub/scm/utils/dtc/dtc.git
|
||||||
|
|
||||||
|
Tagged release ($TAG):
|
||||||
|
https://git.kernel.org/pub/scm/utils/dtc/dtc.git/tag/?h=$TAG
|
||||||
|
|
||||||
|
Tarball:
|
||||||
|
https://kernel.org/pub/software/utils/dtc/dtc-${VERSION}.tar.gz
|
||||||
|
|
||||||
|
$TAG_BODY
|
||||||
|
MAIL
|
||||||
|
|
||||||
|
echo "Announcement draft written to $ANNOUNCE"
|
||||||
|
|
@ -1,6 +1,19 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
if [ "$(uname -s)" = "Darwin" ]
|
||||||
|
then
|
||||||
|
brew install --quiet libyaml swig meson ninja pkg-config
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$(uname -s)" = "FreeBSD" ]
|
||||||
|
then
|
||||||
|
pkg install -y git gmake flex bison meson ninja \
|
||||||
|
python3 py312-setuptools swig libyaml pkgconf
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
if [ -f /etc/os-release ]
|
if [ -f /etc/os-release ]
|
||||||
then
|
then
|
||||||
. /etc/os-release
|
. /etc/os-release
|
||||||
|
|
|
||||||
70
scripts/prepare-release
Executable file
70
scripts/prepare-release
Executable file
|
|
@ -0,0 +1,70 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
#
|
||||||
|
# Prepare a release: update VERSION.txt and create the version bump
|
||||||
|
# commit. This handles steps 1 and 2 of the release procedure in
|
||||||
|
# AGENTS.md. Step 3 (drafting the tag message) requires judgement to
|
||||||
|
# categorise and summarise changes, so is left to the caller.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo "Usage: $0 <version>" >&2
|
||||||
|
echo "" >&2
|
||||||
|
echo " version X.Y.Z or vX.Y.Z" >&2
|
||||||
|
echo "" >&2
|
||||||
|
echo "Example: $0 1.8.1" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
RAW="$1"
|
||||||
|
if [ -z "$RAW" ]; then
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
VERSION="${RAW#v}"
|
||||||
|
|
||||||
|
case "$VERSION" in
|
||||||
|
[0-9]*.[0-9]*.[0-9]*)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Error: version '$VERSION' does not look like X.Y.Z" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
TAG="v${VERSION}"
|
||||||
|
|
||||||
|
if git rev-parse "$TAG" >/dev/null 2>&1; then
|
||||||
|
echo "Error: tag $TAG already exists" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! git diff-index --quiet HEAD; then
|
||||||
|
echo "Error: working tree is dirty; commit or stash first" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$VERSION" > VERSION.txt
|
||||||
|
git add VERSION.txt
|
||||||
|
git commit -m "$(cat <<EOF
|
||||||
|
Bump version to $TAG
|
||||||
|
|
||||||
|
Prepare for a new release.
|
||||||
|
EOF
|
||||||
|
)"
|
||||||
|
|
||||||
|
echo "Building with make..."
|
||||||
|
git clean -fdx
|
||||||
|
make check
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Building with meson..."
|
||||||
|
git clean -fdx
|
||||||
|
meson setup build
|
||||||
|
meson test -C build
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "All builds and tests passed."
|
||||||
|
echo "Next: draft the tag message to tag-message.txt, then run:"
|
||||||
|
echo " scripts/finalize-release tag-message.txt"
|
||||||
1
tests/.gitignore
vendored
1
tests/.gitignore
vendored
|
|
@ -69,6 +69,7 @@ tmp.*
|
||||||
/supernode_atdepth_offset
|
/supernode_atdepth_offset
|
||||||
/sw_tree1
|
/sw_tree1
|
||||||
/sw_states
|
/sw_states
|
||||||
|
/treegen
|
||||||
/truncated_property
|
/truncated_property
|
||||||
/truncated_string
|
/truncated_string
|
||||||
/truncated_memrsv
|
/truncated_memrsv
|
||||||
|
|
|
||||||
|
|
@ -29,34 +29,32 @@ LIB_TESTS_L = get_mem_rsv \
|
||||||
subnode_iterate \
|
subnode_iterate \
|
||||||
overlay overlay_bad_fixup \
|
overlay overlay_bad_fixup \
|
||||||
check_path check_header check_full \
|
check_path check_header check_full \
|
||||||
fs_tree1
|
fs_tree1 \
|
||||||
LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%)
|
truncated_property truncated_string \
|
||||||
|
|
||||||
LIBTREE_TESTS_L = truncated_property truncated_string \
|
|
||||||
truncated_memrsv unterminated_memrsv
|
truncated_memrsv unterminated_memrsv
|
||||||
|
LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%)
|
||||||
LIBTREE_TESTS = $(LIBTREE_TESTS_L:%=$(TESTS_PREFIX)%)
|
|
||||||
|
|
||||||
ifneq ($(STATIC_BUILD),1)
|
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
|
endif
|
||||||
|
|
||||||
TESTS = $(LIB_TESTS) $(LIBTREE_TESTS) $(DL_LIB_TESTS)
|
TESTS = $(LIB_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_node_char.dtb bad_node_format.dtb \
|
||||||
bad_prop_char.dtb ovf_size_strings.dtb truncated_property.dtb \
|
bad_prop_char.dtb ovf_size_strings.dtb truncated_property.dtb \
|
||||||
truncated_string.dtb truncated_memrsv.dtb two_roots.dtb named_root.dtb
|
truncated_string.dtb truncated_memrsv.dtb unterminated_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)
|
||||||
|
|
||||||
TESTS_DEPFILES = $(TESTS:%=%.d) \
|
TESTS_DEPFILES = $(TESTS:%=%.d) \
|
||||||
$(addprefix $(TESTS_PREFIX),testutils.d trees.d dumptrees.d)
|
$(addprefix $(TESTS_PREFIX),testutils.d)
|
||||||
|
|
||||||
TESTS_CLEANFILES_L = $(STD_CLEANFILES) \
|
TESTS_CLEANFILES_L = $(STD_CLEANFILES) \
|
||||||
*.dtb *.test.dts *.test.dt.yaml *.dtsv1 tmp.* *.bak \
|
*.dtb *.test.dts *.test.dt.yaml *.dtsv1 tmp.* *.bak \
|
||||||
dumptrees
|
treegen
|
||||||
TESTS_CLEANFILES = $(TESTS) $(TESTS_CLEANFILES_L:%=$(TESTS_PREFIX)%)
|
TESTS_CLEANFILES = $(TESTS) $(TESTS_CLEANFILES_L:%=$(TESTS_PREFIX)%)
|
||||||
TESTS_CLEANDIRS_L = fs
|
TESTS_CLEANDIRS_L = fs
|
||||||
TESTS_CLEANDIRS = $(TESTS_CLEANDIRS_L:%=$(TESTS_PREFIX)%)
|
TESTS_CLEANDIRS = $(TESTS_CLEANDIRS_L:%=$(TESTS_PREFIX)%)
|
||||||
|
|
@ -73,14 +71,9 @@ $(DL_LIB_TESTS): %: %.o $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_dep)
|
||||||
@$(VECHO) LD [libdl] $@
|
@$(VECHO) LD [libdl] $@
|
||||||
$(LINK.c) -o $@ $^ $(LIBDL)
|
$(LINK.c) -o $@ $^ $(LIBDL)
|
||||||
|
|
||||||
$(LIBTREE_TESTS): %: $(TESTS_PREFIX)testutils.o $(TESTS_PREFIX)trees.o \
|
$(TESTS_TREES): $(TESTS_PREFIX)treegen
|
||||||
util.o $(LIBFDT_dep)
|
@$(VECHO) TREEGEN
|
||||||
|
cd $(TESTS_PREFIX); ./treegen . >/dev/null
|
||||||
$(TESTS_PREFIX)dumptrees: $(TESTS_PREFIX)trees.o
|
|
||||||
|
|
||||||
$(TESTS_TREES): $(TESTS_PREFIX)dumptrees
|
|
||||||
@$(VECHO) DUMPTREES
|
|
||||||
cd $(TESTS_PREFIX); ./dumptrees . >/dev/null
|
|
||||||
|
|
||||||
tests_clean:
|
tests_clean:
|
||||||
@$(VECHO) CLEAN "(tests)"
|
@$(VECHO) CLEAN "(tests)"
|
||||||
|
|
|
||||||
|
|
@ -1,69 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
/*
|
|
||||||
* dumptrees - utility for libfdt testing
|
|
||||||
*
|
|
||||||
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2006.
|
|
||||||
*/
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include <libfdt.h>
|
|
||||||
|
|
||||||
#include "testdata.h"
|
|
||||||
|
|
||||||
static struct {
|
|
||||||
void *blob;
|
|
||||||
const char *filename;
|
|
||||||
} trees[] = {
|
|
||||||
#define TREE(name) { &name, #name ".dtb" }
|
|
||||||
TREE(test_tree1),
|
|
||||||
TREE(bad_node_char), TREE(bad_node_format), TREE(bad_prop_char),
|
|
||||||
TREE(ovf_size_strings),
|
|
||||||
TREE(truncated_property), TREE(truncated_string),
|
|
||||||
TREE(truncated_memrsv),
|
|
||||||
TREE(two_roots),
|
|
||||||
TREE(named_root)
|
|
||||||
};
|
|
||||||
|
|
||||||
#define NUM_TREES (sizeof(trees) / sizeof(trees[0]))
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
if (argc != 2) {
|
|
||||||
fprintf(stderr, "Missing output directory argument\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chdir(argv[1]) != 0) {
|
|
||||||
perror("chdir()");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < NUM_TREES; i++) {
|
|
||||||
void *blob = trees[i].blob;
|
|
||||||
const char *filename = trees[i].filename;
|
|
||||||
int size;
|
|
||||||
int fd;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
size = fdt_totalsize(blob);
|
|
||||||
|
|
||||||
printf("Tree \"%s\", %d bytes\n", filename, size);
|
|
||||||
|
|
||||||
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
|
||||||
if (fd < 0)
|
|
||||||
perror("open()");
|
|
||||||
|
|
||||||
ret = write(fd, blob, size);
|
|
||||||
if (ret != size)
|
|
||||||
perror("write()");
|
|
||||||
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
@ -24,7 +24,11 @@ static void start_dir(const char *name)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
rc = mkdir(name, 0777);
|
rc = mkdir(name, 0777);
|
||||||
|
#else
|
||||||
|
rc = mkdir(name);
|
||||||
|
#endif
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
FAIL("mkdir(\"%s\"): %s", name, strerror(errno));
|
FAIL("mkdir(\"%s\"): %s", name, strerror(errno));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,14 @@
|
||||||
#include "tests.h"
|
#include "tests.h"
|
||||||
#include "testdata.h"
|
#include "testdata.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some of these trip the -Wconstant-logical-operand warning introduced in gcc
|
||||||
|
* 17. Disable it temporarily, we also have to disable -Wpragmas for the
|
||||||
|
* benefit of older compiler versions that don't know about that warning.
|
||||||
|
*/
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wpragmas"
|
||||||
|
#pragma GCC diagnostic ignored "-Wconstant-logical-operand"
|
||||||
static struct test_expr {
|
static struct test_expr {
|
||||||
const char *expr;
|
const char *expr;
|
||||||
uint32_t result;
|
uint32_t result;
|
||||||
|
|
@ -51,6 +59,7 @@ static struct test_expr {
|
||||||
TE(11 * 257 * 1321517ULL),
|
TE(11 * 257 * 1321517ULL),
|
||||||
TE(123456790 - 4/2 + 17%4),
|
TE(123456790 - 4/2 + 17%4),
|
||||||
};
|
};
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,10 @@
|
||||||
trees = static_library('trees', files('trees.S'),
|
treegen = executable('treegen', files('treegen.c'),
|
||||||
build_by_default: false,
|
build_by_default: false,
|
||||||
include_directories: libfdt_inc)
|
dependencies: [util_dep])
|
||||||
|
|
||||||
dumptrees = executable('dumptrees', files('dumptrees.c'),
|
treegen_dtb = custom_target(
|
||||||
build_by_default: false,
|
'treegen_dtb',
|
||||||
link_with: trees, dependencies: libfdt_dep)
|
command: [treegen, meson.current_build_dir()],
|
||||||
|
|
||||||
dumptrees_dtb = custom_target(
|
|
||||||
'dumptrees',
|
|
||||||
command: [dumptrees, meson.current_build_dir()],
|
|
||||||
output: [
|
output: [
|
||||||
'test_tree1.dtb',
|
'test_tree1.dtb',
|
||||||
'bad_node_char.dtb',
|
'bad_node_char.dtb',
|
||||||
|
|
@ -18,10 +14,13 @@ dumptrees_dtb = custom_target(
|
||||||
'truncated_property.dtb',
|
'truncated_property.dtb',
|
||||||
'truncated_string.dtb',
|
'truncated_string.dtb',
|
||||||
'truncated_memrsv.dtb',
|
'truncated_memrsv.dtb',
|
||||||
|
'unterminated_memrsv.dtb',
|
||||||
|
'two_roots.dtb',
|
||||||
|
'named_root.dtb',
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
testutil_dep = declare_dependency(sources: ['testutils.c'], link_with: trees)
|
testutil_dep = declare_dependency(sources: ['testutils.c'])
|
||||||
|
|
||||||
tests = [
|
tests = [
|
||||||
'add_subnode_with_nops',
|
'add_subnode_with_nops',
|
||||||
|
|
@ -89,14 +88,11 @@ tests = [
|
||||||
'supernode_atdepth_offset',
|
'supernode_atdepth_offset',
|
||||||
'sw_states',
|
'sw_states',
|
||||||
'sw_tree1',
|
'sw_tree1',
|
||||||
'utilfdt_test',
|
|
||||||
]
|
|
||||||
|
|
||||||
tests += [
|
|
||||||
'truncated_memrsv',
|
'truncated_memrsv',
|
||||||
'truncated_property',
|
'truncated_property',
|
||||||
'truncated_string',
|
'truncated_string',
|
||||||
'unterminated_memrsv',
|
'unterminated_memrsv',
|
||||||
|
'utilfdt_test',
|
||||||
]
|
]
|
||||||
|
|
||||||
test_deps = [testutil_dep, util_dep, libfdt_dep]
|
test_deps = [testutil_dep, util_dep, libfdt_dep]
|
||||||
|
|
@ -141,10 +137,10 @@ run_test_types = [
|
||||||
'fdtget',
|
'fdtget',
|
||||||
'fdtput',
|
'fdtput',
|
||||||
'fdtdump',
|
'fdtdump',
|
||||||
'fdtoverlay'
|
'fdtoverlay',
|
||||||
]
|
]
|
||||||
run_test_deps = [
|
run_test_deps = [
|
||||||
dtc_tools, dumptrees_dtb, tests_exe
|
dtc_tools, treegen_dtb, tests_exe,
|
||||||
]
|
]
|
||||||
if pylibfdt_enabled
|
if pylibfdt_enabled
|
||||||
run_test_types += 'pylibfdt'
|
run_test_types += 'pylibfdt'
|
||||||
|
|
|
||||||
|
|
@ -13,26 +13,15 @@ sys.path.insert(0, '../pylibfdt')
|
||||||
import libfdt
|
import libfdt
|
||||||
from libfdt import Fdt, FdtSw, FdtException, QUIET_NOTFOUND, QUIET_ALL
|
from libfdt import Fdt, FdtSw, FdtException, QUIET_NOTFOUND, QUIET_ALL
|
||||||
|
|
||||||
TEST_ADDR_1H = 0xdeadbeef
|
|
||||||
TEST_ADDR_1L = 0x00000000
|
|
||||||
TEST_ADDR_1 = (TEST_ADDR_1H << 32) | TEST_ADDR_1L
|
|
||||||
TEST_ADDR_1 = 0x8000000000000000
|
TEST_ADDR_1 = 0x8000000000000000
|
||||||
TEST_SIZE_1H = 0x00000000
|
TEST_SIZE_1 = 0x0000000000100000
|
||||||
TEST_SIZE_1L = 0x00100000
|
TEST_ADDR_2 = 123456789
|
||||||
TEST_SIZE_1 = (TEST_SIZE_1H << 32) | TEST_SIZE_1L
|
TEST_SIZE_2 = 0o10000
|
||||||
TEST_ADDR_2H = 0
|
|
||||||
TEST_ADDR_2L = 123456789
|
|
||||||
TEST_ADDR_2 = (TEST_ADDR_2H << 32) | TEST_ADDR_2L
|
|
||||||
TEST_SIZE_2H = 0
|
|
||||||
TEST_SIZE_2L = 0o10000
|
|
||||||
TEST_SIZE_2 = (TEST_SIZE_2H << 32) | TEST_SIZE_2L
|
|
||||||
|
|
||||||
TEST_VALUE_1 = 0xdeadbeef
|
TEST_VALUE_1 = 0xdeadbeef
|
||||||
TEST_VALUE_2 = 123456789
|
TEST_VALUE_2 = 123456789
|
||||||
|
|
||||||
TEST_VALUE64_1H = 0xdeadbeef
|
TEST_VALUE64_1 = 0xdeadbeef01abcdef
|
||||||
TEST_VALUE64_1L = 0x01abcdef
|
|
||||||
TEST_VALUE64_1 = (TEST_VALUE64_1H << 32) | TEST_VALUE64_1L
|
|
||||||
|
|
||||||
PHANDLE_1 = 0x2000
|
PHANDLE_1 = 0x2000
|
||||||
PHANDLE_2 = 0x2001
|
PHANDLE_2 = 0x2001
|
||||||
|
|
|
||||||
|
|
@ -492,10 +492,10 @@ libfdt_tests () {
|
||||||
run_test appendprop_addrrange unit-addr-without-reg.dtb 2 1 3
|
run_test appendprop_addrrange unit-addr-without-reg.dtb 2 1 3
|
||||||
|
|
||||||
# Tests for behaviour on various sorts of corrupted trees
|
# Tests for behaviour on various sorts of corrupted trees
|
||||||
run_test truncated_property
|
run_test truncated_property truncated_property.dtb
|
||||||
run_test truncated_string
|
run_test truncated_string truncated_string.dtb
|
||||||
run_test truncated_memrsv
|
run_test truncated_memrsv truncated_memrsv.dtb
|
||||||
run_test unterminated_memrsv
|
run_test unterminated_memrsv unterminated_memrsv.dtb
|
||||||
|
|
||||||
# Check aliases support in fdt_path_offset
|
# Check aliases support in fdt_path_offset
|
||||||
run_dtc_test -I dts -O dtb -o aliases.dtb "$SRCDIR/aliases.dts"
|
run_dtc_test -I dts -O dtb -o aliases.dtb "$SRCDIR/aliases.dts"
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,12 @@
|
||||||
#ifdef __ASSEMBLER__
|
#define TEST_ADDR_1 0xdeadbeef00000000ULL
|
||||||
#define ASM_CONST_LL(x) (x)
|
#define TEST_SIZE_1 0x0000000000100000ULL
|
||||||
#else
|
#define TEST_ADDR_2 123456789ULL
|
||||||
#define ASM_CONST_LL(x) (x##ULL)
|
#define TEST_SIZE_2 010000ULL
|
||||||
#endif
|
|
||||||
|
|
||||||
#define TEST_ADDR_1H ASM_CONST_LL(0xdeadbeef)
|
|
||||||
#define TEST_ADDR_1L ASM_CONST_LL(0x00000000)
|
|
||||||
#define TEST_ADDR_1 ((TEST_ADDR_1H << 32) | TEST_ADDR_1L)
|
|
||||||
#define TEST_SIZE_1H ASM_CONST_LL(0x00000000)
|
|
||||||
#define TEST_SIZE_1L ASM_CONST_LL(0x00100000)
|
|
||||||
#define TEST_SIZE_1 ((TEST_SIZE_1H << 32) | TEST_SIZE_1L)
|
|
||||||
#define TEST_ADDR_2H ASM_CONST_LL(0)
|
|
||||||
#define TEST_ADDR_2L ASM_CONST_LL(123456789)
|
|
||||||
#define TEST_ADDR_2 ((TEST_ADDR_2H << 32) | TEST_ADDR_2L)
|
|
||||||
#define TEST_SIZE_2H ASM_CONST_LL(0)
|
|
||||||
#define TEST_SIZE_2L ASM_CONST_LL(010000)
|
|
||||||
#define TEST_SIZE_2 ((TEST_SIZE_2H << 32) | TEST_SIZE_2L)
|
|
||||||
|
|
||||||
#define TEST_VALUE_1 0xdeadbeef
|
#define TEST_VALUE_1 0xdeadbeef
|
||||||
#define TEST_VALUE_2 123456789
|
#define TEST_VALUE_2 123456789
|
||||||
|
|
||||||
#define TEST_VALUE64_1H ASM_CONST_LL(0xdeadbeef)
|
#define TEST_VALUE64_1 0xdeadbeef01abcdefULL
|
||||||
#define TEST_VALUE64_1L ASM_CONST_LL(0x01abcdef)
|
|
||||||
#define TEST_VALUE64_1 ((TEST_VALUE64_1H << 32) | TEST_VALUE64_1L)
|
|
||||||
|
|
||||||
#define PHANDLE_1 0x2000
|
#define PHANDLE_1 0x2000
|
||||||
#define PHANDLE_2 0x2001
|
#define PHANDLE_2 0x2001
|
||||||
|
|
@ -45,17 +29,3 @@
|
||||||
#define TEST_MEMREGION_SIZE 0x9abcdef0
|
#define TEST_MEMREGION_SIZE 0x9abcdef0
|
||||||
#define TEST_MEMREGION_SIZE_HI 0x0fedcba900000000
|
#define TEST_MEMREGION_SIZE_HI 0x0fedcba900000000
|
||||||
#define TEST_MEMREGION_SIZE_INC 0x1000
|
#define TEST_MEMREGION_SIZE_INC 0x1000
|
||||||
|
|
||||||
#ifndef __ASSEMBLER__
|
|
||||||
extern struct fdt_header test_tree1;
|
|
||||||
extern struct fdt_header truncated_property;
|
|
||||||
extern struct fdt_header bad_node_char;
|
|
||||||
extern struct fdt_header bad_node_format;
|
|
||||||
extern struct fdt_header bad_prop_char;
|
|
||||||
extern struct fdt_header ovf_size_strings;
|
|
||||||
extern struct fdt_header truncated_string;
|
|
||||||
extern struct fdt_header truncated_memrsv;
|
|
||||||
extern struct fdt_header unterminated_memrsv;
|
|
||||||
extern struct fdt_header two_roots;
|
|
||||||
extern struct fdt_header named_root;
|
|
||||||
#endif /* ! __ASSEMBLER__ */
|
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,6 @@ void test_init(int argc, char *argv[]);
|
||||||
|
|
||||||
#define streq(s1, s2) (strcmp((s1),(s2)) == 0)
|
#define streq(s1, s2) (strcmp((s1),(s2)) == 0)
|
||||||
|
|
||||||
/* Each test case must define this function */
|
|
||||||
void cleanup(void);
|
|
||||||
|
|
||||||
#define verbose_printf(...) \
|
#define verbose_printf(...) \
|
||||||
if (verbose_test) { \
|
if (verbose_test) { \
|
||||||
printf(__VA_ARGS__); \
|
printf(__VA_ARGS__); \
|
||||||
|
|
@ -39,21 +36,18 @@ void cleanup(void);
|
||||||
|
|
||||||
#define PASS() \
|
#define PASS() \
|
||||||
do { \
|
do { \
|
||||||
cleanup(); \
|
|
||||||
printf("PASS\n"); \
|
printf("PASS\n"); \
|
||||||
exit(RC_PASS); \
|
exit(RC_PASS); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define PASS_INCONCLUSIVE() \
|
#define PASS_INCONCLUSIVE() \
|
||||||
do { \
|
do { \
|
||||||
cleanup(); \
|
|
||||||
printf("PASS (inconclusive)\n"); \
|
printf("PASS (inconclusive)\n"); \
|
||||||
exit(RC_PASS); \
|
exit(RC_PASS); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define IRRELEVANT() \
|
#define IRRELEVANT() \
|
||||||
do { \
|
do { \
|
||||||
cleanup(); \
|
|
||||||
printf("PASS (irrelevant)\n"); \
|
printf("PASS (irrelevant)\n"); \
|
||||||
exit(RC_PASS); \
|
exit(RC_PASS); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
@ -61,21 +55,18 @@ void cleanup(void);
|
||||||
/* Look out, gcc extension below... */
|
/* Look out, gcc extension below... */
|
||||||
#define FAIL(fmt, ...) \
|
#define FAIL(fmt, ...) \
|
||||||
do { \
|
do { \
|
||||||
cleanup(); \
|
|
||||||
printf("FAIL\t" fmt "\n", ##__VA_ARGS__); \
|
printf("FAIL\t" fmt "\n", ##__VA_ARGS__); \
|
||||||
exit(RC_FAIL); \
|
exit(RC_FAIL); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define CONFIG(fmt, ...) \
|
#define CONFIG(fmt, ...) \
|
||||||
do { \
|
do { \
|
||||||
cleanup(); \
|
|
||||||
printf("Bad configuration: " fmt "\n", ##__VA_ARGS__); \
|
printf("Bad configuration: " fmt "\n", ##__VA_ARGS__); \
|
||||||
exit(RC_CONFIG); \
|
exit(RC_CONFIG); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define TEST_BUG(fmt, ...) \
|
#define TEST_BUG(fmt, ...) \
|
||||||
do { \
|
do { \
|
||||||
cleanup(); \
|
|
||||||
printf("BUG in testsuite: " fmt "\n", ##__VA_ARGS__); \
|
printf("BUG in testsuite: " fmt "\n", ##__VA_ARGS__); \
|
||||||
exit(RC_BUG); \
|
exit(RC_BUG); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
|
||||||
|
|
@ -42,29 +42,21 @@ static inline void VALGRIND_MAKE_MEM_DEFINED(void *p, size_t len)
|
||||||
int verbose_test = 1;
|
int verbose_test = 1;
|
||||||
char *test_name;
|
char *test_name;
|
||||||
|
|
||||||
void __attribute__((weak)) cleanup(void)
|
static void sigint_handler(int signum)
|
||||||
{
|
{
|
||||||
}
|
fprintf(stderr, "%s: signal %d (pid=%d)\n", test_name,
|
||||||
|
signum, getpid());
|
||||||
static void sigint_handler(int signum, siginfo_t *si, void *uc)
|
|
||||||
{
|
|
||||||
cleanup();
|
|
||||||
fprintf(stderr, "%s: %s (pid=%d)\n", test_name,
|
|
||||||
strsignal(signum), getpid());
|
|
||||||
exit(RC_BUG);
|
exit(RC_BUG);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_init(int argc, char *argv[])
|
void test_init(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int err;
|
|
||||||
struct sigaction sa_int = {
|
|
||||||
.sa_sigaction = sigint_handler,
|
|
||||||
};
|
|
||||||
|
|
||||||
test_name = argv[0];
|
test_name = argv[0];
|
||||||
|
|
||||||
err = sigaction(SIGINT, &sa_int, NULL);
|
/* Use signal(), not sigaction() because it also works on the Windows /
|
||||||
if (err)
|
* mingw environments we support.
|
||||||
|
*/
|
||||||
|
if (signal(SIGINT, sigint_handler) == SIG_ERR)
|
||||||
FAIL("Can't install SIGINT handler");
|
FAIL("Can't install SIGINT handler");
|
||||||
|
|
||||||
if (getenv("QUIET_TEST"))
|
if (getenv("QUIET_TEST"))
|
||||||
|
|
|
||||||
756
tests/treegen.c
Normal file
756
tests/treegen.c
Normal file
|
|
@ -0,0 +1,756 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
/*
|
||||||
|
* treegen - generate test device tree blobs
|
||||||
|
*
|
||||||
|
* Build example device tree blobs for test. Note that some of the generated
|
||||||
|
* blobs are deliberately malformed, in order to test error conditions.
|
||||||
|
*/
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include <libfdt_env.h>
|
||||||
|
#include <fdt.h>
|
||||||
|
|
||||||
|
#include "tests.h"
|
||||||
|
#include "testdata.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Buffer with write cursor. Emit helpers write at the cursor, advance it, and
|
||||||
|
* return the offset at which data was written.
|
||||||
|
*/
|
||||||
|
struct buf {
|
||||||
|
char *data;
|
||||||
|
size_t size, cursor;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CHUNKSIZE 1024
|
||||||
|
|
||||||
|
static struct buf buf_init(void)
|
||||||
|
{
|
||||||
|
struct buf b = { NULL, 0, 0 };
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Low-level helpers */
|
||||||
|
|
||||||
|
static size_t emit_bytes(struct buf *b, const void *data, int len)
|
||||||
|
{
|
||||||
|
size_t off = b->cursor;
|
||||||
|
|
||||||
|
if (!len)
|
||||||
|
return off;
|
||||||
|
|
||||||
|
if (b->cursor + len > b->size) {
|
||||||
|
size_t newsize = b->cursor + len + CHUNKSIZE;
|
||||||
|
|
||||||
|
b->data = xrealloc(b->data, newsize);
|
||||||
|
memset(b->data + b->size, 0, newsize - b->size);
|
||||||
|
b->size = newsize;
|
||||||
|
}
|
||||||
|
memcpy(b->data + b->cursor, data, len);
|
||||||
|
b->cursor += len;
|
||||||
|
return off;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t emit_u32(struct buf *b, uint32_t val)
|
||||||
|
{
|
||||||
|
fdt32_t beval = cpu_to_fdt32(val);
|
||||||
|
|
||||||
|
return emit_bytes(b, &beval, sizeof(beval));
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t emit_u64(struct buf *b, uint64_t val)
|
||||||
|
{
|
||||||
|
fdt64_t beval = cpu_to_fdt64(val);
|
||||||
|
|
||||||
|
return emit_bytes(b, &beval, sizeof(beval));
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t emit_string(struct buf *b, const char *str)
|
||||||
|
{
|
||||||
|
return emit_bytes(b, str, strlen(str) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAX_ALIGNMENT 8
|
||||||
|
|
||||||
|
static size_t emit_align(struct buf *b, size_t alignment)
|
||||||
|
{
|
||||||
|
size_t pad = ((b->cursor + alignment - 1) & ~(alignment - 1)) - b->cursor;
|
||||||
|
static const char zeros[MAX_ALIGNMENT];
|
||||||
|
|
||||||
|
assert(alignment <= MAX_ALIGNMENT);
|
||||||
|
assert(pad < alignment);
|
||||||
|
|
||||||
|
return emit_bytes(b, zeros, pad);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t start_block(struct buf *b)
|
||||||
|
{
|
||||||
|
return b->cursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fill_prop_name(struct buf *b, size_t strs, size_t prop, size_t stroff)
|
||||||
|
{
|
||||||
|
struct fdt_property *fp = (struct fdt_property *)(b->data + prop);
|
||||||
|
|
||||||
|
fp->nameoff = cpu_to_fdt32(stroff - strs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FDT structure helpers */
|
||||||
|
|
||||||
|
static size_t emit_fdt_header(struct buf *b)
|
||||||
|
{
|
||||||
|
size_t off = emit_u32(b, FDT_MAGIC);
|
||||||
|
|
||||||
|
emit_u32(b, 0); /* totalsize */
|
||||||
|
emit_u32(b, 0); /* off_dt_struct */
|
||||||
|
emit_u32(b, 0); /* off_dt_strings */
|
||||||
|
emit_u32(b, 0); /* off_mem_rsvmap */
|
||||||
|
emit_u32(b, 0x11); /* version */
|
||||||
|
emit_u32(b, 0x10); /* last_comp_version */
|
||||||
|
emit_u32(b, 0); /* boot_cpuid_phys */
|
||||||
|
emit_u32(b, 0); /* size_dt_strings */
|
||||||
|
emit_u32(b, 0); /* size_dt_struct */
|
||||||
|
return off;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void finish_rsvmap(struct buf *b, size_t hdr, size_t rsvmap)
|
||||||
|
{
|
||||||
|
struct fdt_header *fh = (struct fdt_header *)(b->data + hdr);
|
||||||
|
|
||||||
|
fh->off_mem_rsvmap = cpu_to_fdt32(rsvmap - hdr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void finish_struct_block(struct buf *b, size_t hdr, size_t start)
|
||||||
|
{
|
||||||
|
struct fdt_header *fh = (struct fdt_header *)(b->data + hdr);
|
||||||
|
|
||||||
|
fh->off_dt_struct = cpu_to_fdt32(start - hdr);
|
||||||
|
fh->size_dt_struct = cpu_to_fdt32(b->cursor - start);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void finish_strings_block(struct buf *b, size_t hdr, size_t start)
|
||||||
|
{
|
||||||
|
struct fdt_header *fh = (struct fdt_header *)(b->data + hdr);
|
||||||
|
|
||||||
|
fh->off_dt_strings = cpu_to_fdt32(start - hdr);
|
||||||
|
fh->size_dt_strings = cpu_to_fdt32(b->cursor - start);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void finish_totalsize(struct buf *b, size_t hdr)
|
||||||
|
{
|
||||||
|
struct fdt_header *fh = (struct fdt_header *)(b->data + hdr);
|
||||||
|
|
||||||
|
fh->totalsize = cpu_to_fdt32(b->cursor - hdr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t emit_rsvmap_entry(struct buf *b, uint64_t addr, uint64_t size)
|
||||||
|
{
|
||||||
|
size_t off = emit_u64(b, addr);
|
||||||
|
|
||||||
|
emit_u64(b, size);
|
||||||
|
return off;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t emit_rsvmap_term(struct buf *b)
|
||||||
|
{
|
||||||
|
return emit_rsvmap_entry(b, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void emit_rsvmap_empty(struct buf *b, size_t hdr)
|
||||||
|
{
|
||||||
|
size_t rsvmap = start_block(b);
|
||||||
|
|
||||||
|
emit_rsvmap_term(b);
|
||||||
|
finish_rsvmap(b, hdr, rsvmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t emit_begin_node(struct buf *b, const char *name)
|
||||||
|
{
|
||||||
|
size_t off = emit_u32(b, FDT_BEGIN_NODE);
|
||||||
|
|
||||||
|
emit_string(b, name);
|
||||||
|
emit_align(b, FDT_TAGSIZE);
|
||||||
|
return off;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t emit_end_node(struct buf *b)
|
||||||
|
{
|
||||||
|
return emit_u32(b, FDT_END_NODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t emit_fdt_end(struct buf *b)
|
||||||
|
{
|
||||||
|
return emit_u32(b, FDT_END);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t emit_prop_header(struct buf *b, int nameoff, int len)
|
||||||
|
{
|
||||||
|
size_t off = emit_u32(b, FDT_PROP);
|
||||||
|
|
||||||
|
emit_u32(b, len);
|
||||||
|
emit_u32(b, nameoff);
|
||||||
|
return off;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t emit_prop_nil(struct buf *b, int nameoff)
|
||||||
|
{
|
||||||
|
return emit_prop_header(b, nameoff, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t emit_prop_u32(struct buf *b, int nameoff, uint32_t val)
|
||||||
|
{
|
||||||
|
size_t off = emit_prop_header(b, nameoff, 4);
|
||||||
|
|
||||||
|
emit_u32(b, val);
|
||||||
|
return off;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t emit_prop_u64(struct buf *b, int nameoff, uint64_t val)
|
||||||
|
{
|
||||||
|
size_t off = emit_prop_header(b, nameoff, 8);
|
||||||
|
|
||||||
|
emit_u64(b, val);
|
||||||
|
return off;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t emit_prop_str(struct buf *b, int nameoff, const char *str)
|
||||||
|
{
|
||||||
|
int len = strlen(str) + 1;
|
||||||
|
size_t off = emit_prop_header(b, nameoff, len);
|
||||||
|
|
||||||
|
emit_bytes(b, str, len);
|
||||||
|
emit_align(b, FDT_TAGSIZE);
|
||||||
|
return off;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define emit_prop_strings(b, nameoff, ...) \
|
||||||
|
emit_prop_strings_(b, nameoff, __VA_ARGS__, NULL)
|
||||||
|
|
||||||
|
static size_t emit_prop_strings_(struct buf *b, int nameoff, ...)
|
||||||
|
{
|
||||||
|
size_t off = emit_prop_header(b, nameoff, 0);
|
||||||
|
size_t start = b->cursor;
|
||||||
|
va_list ap;
|
||||||
|
const char *s;
|
||||||
|
|
||||||
|
va_start(ap, nameoff);
|
||||||
|
while ((s = va_arg(ap, const char *)) != NULL)
|
||||||
|
emit_string(b, s);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
((struct fdt_property *)(b->data + off))->len =
|
||||||
|
cpu_to_fdt32(b->cursor - start);
|
||||||
|
emit_align(b, FDT_TAGSIZE);
|
||||||
|
return off;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tree generators
|
||||||
|
*
|
||||||
|
* Each function builds a complete DTB in a buffer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static struct buf make_test_tree1(void)
|
||||||
|
{
|
||||||
|
struct buf b = buf_init();
|
||||||
|
size_t hdr;
|
||||||
|
size_t p_compatible, p_prop_int, p_prop_int64, p_prop_str,
|
||||||
|
p_address_cells, p_size_cells;
|
||||||
|
size_t p_s1_compatible, p_s1_reg, p_s1_prop_int;
|
||||||
|
size_t p_s1ss_compatible, p_s1ss_placeholder, p_s1ss_prop_int;
|
||||||
|
size_t p_s2_reg, p_s2_linux_phandle, p_s2_prop_int,
|
||||||
|
p_s2_address_cells, p_s2_size_cells;
|
||||||
|
size_t p_s2ss0_reg, p_s2ss0_phandle, p_s2ss0_compatible,
|
||||||
|
p_s2ss0_prop_int;
|
||||||
|
|
||||||
|
hdr = emit_fdt_header(&b);
|
||||||
|
emit_align(&b, 8);
|
||||||
|
|
||||||
|
{
|
||||||
|
size_t rsvmap = start_block(&b);
|
||||||
|
|
||||||
|
emit_rsvmap_entry(&b, TEST_ADDR_1, TEST_SIZE_1);
|
||||||
|
emit_rsvmap_entry(&b, TEST_ADDR_2, TEST_SIZE_2);
|
||||||
|
emit_rsvmap_term(&b);
|
||||||
|
finish_rsvmap(&b, hdr, rsvmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
size_t ss = start_block(&b);
|
||||||
|
|
||||||
|
emit_begin_node(&b, "");
|
||||||
|
p_compatible = emit_prop_str(&b, 0, "test_tree1");
|
||||||
|
p_prop_int = emit_prop_u32(&b, 0, TEST_VALUE_1);
|
||||||
|
p_prop_int64 = emit_prop_u64(&b, 0, TEST_VALUE64_1);
|
||||||
|
p_prop_str = emit_prop_str(&b, 0, TEST_STRING_1);
|
||||||
|
p_address_cells = emit_prop_u32(&b, 0, 1);
|
||||||
|
p_size_cells = emit_prop_u32(&b, 0, 0);
|
||||||
|
|
||||||
|
emit_begin_node(&b, "subnode@1");
|
||||||
|
p_s1_compatible = emit_prop_str(&b, 0, "subnode1");
|
||||||
|
p_s1_reg = emit_prop_u32(&b, 0, 1);
|
||||||
|
p_s1_prop_int = emit_prop_u32(&b, 0, TEST_VALUE_1);
|
||||||
|
|
||||||
|
emit_begin_node(&b, "subsubnode");
|
||||||
|
p_s1ss_compatible = emit_prop_strings(&b, 0,
|
||||||
|
"subsubnode1", "subsubnode");
|
||||||
|
p_s1ss_placeholder = emit_prop_strings(&b, 0,
|
||||||
|
"this is a placeholder string",
|
||||||
|
"string2");
|
||||||
|
p_s1ss_prop_int = emit_prop_u32(&b, 0, TEST_VALUE_1);
|
||||||
|
emit_end_node(&b);
|
||||||
|
|
||||||
|
emit_begin_node(&b, "ss1");
|
||||||
|
emit_end_node(&b);
|
||||||
|
|
||||||
|
emit_end_node(&b);
|
||||||
|
|
||||||
|
emit_begin_node(&b, "subnode@2");
|
||||||
|
p_s2_reg = emit_prop_u32(&b, 0, 2);
|
||||||
|
p_s2_linux_phandle = emit_prop_u32(&b, 0, PHANDLE_1);
|
||||||
|
p_s2_prop_int = emit_prop_u32(&b, 0, TEST_VALUE_2);
|
||||||
|
p_s2_address_cells = emit_prop_u32(&b, 0, 1);
|
||||||
|
p_s2_size_cells = emit_prop_u32(&b, 0, 0);
|
||||||
|
|
||||||
|
emit_begin_node(&b, "subsubnode@0");
|
||||||
|
p_s2ss0_reg = emit_prop_u32(&b, 0, 0);
|
||||||
|
p_s2ss0_phandle = emit_prop_u32(&b, 0, PHANDLE_2);
|
||||||
|
p_s2ss0_compatible = emit_prop_strings(&b, 0,
|
||||||
|
"subsubnode2", "subsubnode");
|
||||||
|
p_s2ss0_prop_int = emit_prop_u32(&b, 0, TEST_VALUE_2);
|
||||||
|
emit_end_node(&b);
|
||||||
|
|
||||||
|
emit_begin_node(&b, "ss2");
|
||||||
|
emit_end_node(&b);
|
||||||
|
|
||||||
|
emit_end_node(&b);
|
||||||
|
|
||||||
|
emit_end_node(&b);
|
||||||
|
emit_fdt_end(&b);
|
||||||
|
finish_struct_block(&b, hdr, ss);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
size_t strs = start_block(&b);
|
||||||
|
size_t s;
|
||||||
|
|
||||||
|
s = emit_string(&b, "compatible");
|
||||||
|
fill_prop_name(&b, strs, p_compatible, s);
|
||||||
|
fill_prop_name(&b, strs, p_s1_compatible, s);
|
||||||
|
fill_prop_name(&b, strs, p_s1ss_compatible, s);
|
||||||
|
fill_prop_name(&b, strs, p_s2ss0_compatible, s);
|
||||||
|
|
||||||
|
s = emit_string(&b, "prop-int");
|
||||||
|
fill_prop_name(&b, strs, p_prop_int, s);
|
||||||
|
fill_prop_name(&b, strs, p_s1_prop_int, s);
|
||||||
|
fill_prop_name(&b, strs, p_s1ss_prop_int, s);
|
||||||
|
fill_prop_name(&b, strs, p_s2_prop_int, s);
|
||||||
|
fill_prop_name(&b, strs, p_s2ss0_prop_int, s);
|
||||||
|
|
||||||
|
fill_prop_name(&b, strs, p_prop_int64,
|
||||||
|
emit_string(&b, "prop-int64"));
|
||||||
|
|
||||||
|
fill_prop_name(&b, strs, p_prop_str,
|
||||||
|
emit_string(&b, "prop-str"));
|
||||||
|
|
||||||
|
fill_prop_name(&b, strs, p_s2_linux_phandle,
|
||||||
|
emit_string(&b, "linux,phandle"));
|
||||||
|
|
||||||
|
fill_prop_name(&b, strs, p_s2ss0_phandle,
|
||||||
|
emit_string(&b, "phandle"));
|
||||||
|
|
||||||
|
s = emit_string(&b, "reg");
|
||||||
|
fill_prop_name(&b, strs, p_s1_reg, s);
|
||||||
|
fill_prop_name(&b, strs, p_s2_reg, s);
|
||||||
|
fill_prop_name(&b, strs, p_s2ss0_reg, s);
|
||||||
|
|
||||||
|
fill_prop_name(&b, strs, p_s1ss_placeholder,
|
||||||
|
emit_string(&b, "placeholder"));
|
||||||
|
|
||||||
|
s = emit_string(&b, "#address-cells");
|
||||||
|
fill_prop_name(&b, strs, p_address_cells, s);
|
||||||
|
fill_prop_name(&b, strs, p_s2_address_cells, s);
|
||||||
|
|
||||||
|
s = emit_string(&b, "#size-cells");
|
||||||
|
fill_prop_name(&b, strs, p_size_cells, s);
|
||||||
|
fill_prop_name(&b, strs, p_s2_size_cells, s);
|
||||||
|
|
||||||
|
finish_strings_block(&b, hdr, strs);
|
||||||
|
}
|
||||||
|
|
||||||
|
finish_totalsize(&b, hdr);
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct buf make_truncated_property(void)
|
||||||
|
{
|
||||||
|
struct buf b = buf_init();
|
||||||
|
size_t hdr;
|
||||||
|
size_t p;
|
||||||
|
|
||||||
|
hdr = emit_fdt_header(&b);
|
||||||
|
emit_align(&b, 8);
|
||||||
|
|
||||||
|
emit_rsvmap_empty(&b, hdr);
|
||||||
|
|
||||||
|
{
|
||||||
|
size_t ss = start_block(&b);
|
||||||
|
|
||||||
|
emit_begin_node(&b, "");
|
||||||
|
p = emit_prop_header(&b, 0, 4);
|
||||||
|
finish_struct_block(&b, hdr, ss);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
size_t strs = start_block(&b);
|
||||||
|
|
||||||
|
emit_string(&b, "truncated");
|
||||||
|
fill_prop_name(&b, strs, p, strs);
|
||||||
|
finish_strings_block(&b, hdr, strs);
|
||||||
|
}
|
||||||
|
|
||||||
|
finish_totalsize(&b, hdr);
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct buf make_bad_node_char(void)
|
||||||
|
{
|
||||||
|
struct buf b = buf_init();
|
||||||
|
size_t hdr;
|
||||||
|
|
||||||
|
hdr = emit_fdt_header(&b);
|
||||||
|
emit_align(&b, 8);
|
||||||
|
|
||||||
|
emit_rsvmap_empty(&b, hdr);
|
||||||
|
|
||||||
|
{
|
||||||
|
size_t ss = start_block(&b);
|
||||||
|
|
||||||
|
emit_begin_node(&b, "");
|
||||||
|
emit_begin_node(&b, "sub$node");
|
||||||
|
emit_end_node(&b);
|
||||||
|
emit_end_node(&b);
|
||||||
|
emit_fdt_end(&b);
|
||||||
|
finish_struct_block(&b, hdr, ss);
|
||||||
|
}
|
||||||
|
|
||||||
|
finish_strings_block(&b, hdr, start_block(&b));
|
||||||
|
|
||||||
|
finish_totalsize(&b, hdr);
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct buf make_bad_node_format(void)
|
||||||
|
{
|
||||||
|
struct buf b = buf_init();
|
||||||
|
size_t hdr;
|
||||||
|
|
||||||
|
hdr = emit_fdt_header(&b);
|
||||||
|
emit_align(&b, 8);
|
||||||
|
|
||||||
|
emit_rsvmap_empty(&b, hdr);
|
||||||
|
|
||||||
|
{
|
||||||
|
size_t ss = start_block(&b);
|
||||||
|
|
||||||
|
emit_begin_node(&b, "");
|
||||||
|
emit_begin_node(&b, "subnode@1@2");
|
||||||
|
emit_end_node(&b);
|
||||||
|
emit_end_node(&b);
|
||||||
|
emit_fdt_end(&b);
|
||||||
|
finish_struct_block(&b, hdr, ss);
|
||||||
|
}
|
||||||
|
|
||||||
|
finish_strings_block(&b, hdr, start_block(&b));
|
||||||
|
|
||||||
|
finish_totalsize(&b, hdr);
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct buf make_bad_prop_char(void)
|
||||||
|
{
|
||||||
|
struct buf b = buf_init();
|
||||||
|
size_t hdr;
|
||||||
|
size_t p;
|
||||||
|
|
||||||
|
hdr = emit_fdt_header(&b);
|
||||||
|
emit_align(&b, 8);
|
||||||
|
|
||||||
|
emit_rsvmap_empty(&b, hdr);
|
||||||
|
|
||||||
|
{
|
||||||
|
size_t ss = start_block(&b);
|
||||||
|
|
||||||
|
emit_begin_node(&b, "");
|
||||||
|
p = emit_prop_u32(&b, 0, TEST_VALUE_1);
|
||||||
|
emit_end_node(&b);
|
||||||
|
emit_fdt_end(&b);
|
||||||
|
finish_struct_block(&b, hdr, ss);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
size_t strs = start_block(&b);
|
||||||
|
|
||||||
|
fill_prop_name(&b, strs, p,
|
||||||
|
emit_string(&b, "prop$erty"));
|
||||||
|
finish_strings_block(&b, hdr, strs);
|
||||||
|
}
|
||||||
|
|
||||||
|
finish_totalsize(&b, hdr);
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct buf make_ovf_size_strings(void)
|
||||||
|
{
|
||||||
|
struct buf b = buf_init();
|
||||||
|
size_t hdr;
|
||||||
|
|
||||||
|
hdr = emit_fdt_header(&b);
|
||||||
|
emit_align(&b, 8);
|
||||||
|
|
||||||
|
emit_rsvmap_empty(&b, hdr);
|
||||||
|
|
||||||
|
{
|
||||||
|
size_t ss = start_block(&b);
|
||||||
|
|
||||||
|
emit_begin_node(&b, "");
|
||||||
|
emit_prop_u32(&b, 0x10000000, 0);
|
||||||
|
emit_end_node(&b);
|
||||||
|
emit_fdt_end(&b);
|
||||||
|
finish_struct_block(&b, hdr, ss);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
size_t strs = start_block(&b);
|
||||||
|
|
||||||
|
emit_string(&b, "x");
|
||||||
|
finish_strings_block(&b, hdr, strs);
|
||||||
|
}
|
||||||
|
|
||||||
|
((struct fdt_header *)(b.data + hdr))->size_dt_strings =
|
||||||
|
cpu_to_fdt32(0xffffffff);
|
||||||
|
|
||||||
|
finish_totalsize(&b, hdr);
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct buf make_truncated_string(void)
|
||||||
|
{
|
||||||
|
struct buf b = buf_init();
|
||||||
|
size_t hdr;
|
||||||
|
size_t p_good, p_bad;
|
||||||
|
|
||||||
|
hdr = emit_fdt_header(&b);
|
||||||
|
emit_align(&b, 8);
|
||||||
|
|
||||||
|
emit_rsvmap_empty(&b, hdr);
|
||||||
|
|
||||||
|
{
|
||||||
|
size_t ss = start_block(&b);
|
||||||
|
|
||||||
|
emit_begin_node(&b, "");
|
||||||
|
p_good = emit_prop_nil(&b, 0);
|
||||||
|
p_bad = emit_prop_nil(&b, 0);
|
||||||
|
emit_end_node(&b);
|
||||||
|
emit_fdt_end(&b);
|
||||||
|
finish_struct_block(&b, hdr, ss);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
size_t strs = start_block(&b);
|
||||||
|
|
||||||
|
fill_prop_name(&b, strs, p_good, emit_string(&b, "good"));
|
||||||
|
fill_prop_name(&b, strs, p_bad, emit_bytes(&b, "bad", 3));
|
||||||
|
finish_strings_block(&b, hdr, strs);
|
||||||
|
}
|
||||||
|
|
||||||
|
finish_totalsize(&b, hdr);
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct buf make_truncated_memrsv(void)
|
||||||
|
{
|
||||||
|
struct buf b = buf_init();
|
||||||
|
size_t hdr;
|
||||||
|
|
||||||
|
hdr = emit_fdt_header(&b);
|
||||||
|
|
||||||
|
{
|
||||||
|
size_t ss = start_block(&b);
|
||||||
|
|
||||||
|
emit_begin_node(&b, "");
|
||||||
|
emit_end_node(&b);
|
||||||
|
emit_fdt_end(&b);
|
||||||
|
finish_struct_block(&b, hdr, ss);
|
||||||
|
}
|
||||||
|
|
||||||
|
finish_strings_block(&b, hdr, start_block(&b));
|
||||||
|
|
||||||
|
{
|
||||||
|
size_t rsvmap;
|
||||||
|
|
||||||
|
emit_align(&b, 8);
|
||||||
|
rsvmap = start_block(&b);
|
||||||
|
emit_rsvmap_entry(&b, TEST_ADDR_1, TEST_SIZE_1);
|
||||||
|
finish_rsvmap(&b, hdr, rsvmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
finish_totalsize(&b, hdr);
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct buf make_unterminated_memrsv(void)
|
||||||
|
{
|
||||||
|
struct buf b = buf_init();
|
||||||
|
size_t hdr;
|
||||||
|
|
||||||
|
hdr = emit_fdt_header(&b);
|
||||||
|
|
||||||
|
{
|
||||||
|
size_t rsvmap;
|
||||||
|
|
||||||
|
emit_align(&b, 8);
|
||||||
|
rsvmap = start_block(&b);
|
||||||
|
emit_rsvmap_entry(&b, TEST_ADDR_1, TEST_SIZE_1);
|
||||||
|
finish_rsvmap(&b, hdr, rsvmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
size_t ss = start_block(&b);
|
||||||
|
|
||||||
|
emit_begin_node(&b, "");
|
||||||
|
emit_end_node(&b);
|
||||||
|
emit_fdt_end(&b);
|
||||||
|
finish_struct_block(&b, hdr, ss);
|
||||||
|
}
|
||||||
|
|
||||||
|
finish_strings_block(&b, hdr, start_block(&b));
|
||||||
|
|
||||||
|
finish_totalsize(&b, hdr);
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct buf make_two_roots(void)
|
||||||
|
{
|
||||||
|
struct buf b = buf_init();
|
||||||
|
size_t hdr;
|
||||||
|
|
||||||
|
hdr = emit_fdt_header(&b);
|
||||||
|
emit_align(&b, 8);
|
||||||
|
|
||||||
|
emit_rsvmap_empty(&b, hdr);
|
||||||
|
|
||||||
|
{
|
||||||
|
size_t ss = start_block(&b);
|
||||||
|
|
||||||
|
emit_begin_node(&b, "");
|
||||||
|
emit_end_node(&b);
|
||||||
|
emit_begin_node(&b, "");
|
||||||
|
emit_end_node(&b);
|
||||||
|
emit_fdt_end(&b);
|
||||||
|
finish_struct_block(&b, hdr, ss);
|
||||||
|
}
|
||||||
|
|
||||||
|
finish_strings_block(&b, hdr, start_block(&b));
|
||||||
|
|
||||||
|
finish_totalsize(&b, hdr);
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct buf make_named_root(void)
|
||||||
|
{
|
||||||
|
struct buf b = buf_init();
|
||||||
|
size_t hdr;
|
||||||
|
|
||||||
|
hdr = emit_fdt_header(&b);
|
||||||
|
emit_align(&b, 8);
|
||||||
|
|
||||||
|
emit_rsvmap_empty(&b, hdr);
|
||||||
|
|
||||||
|
{
|
||||||
|
size_t ss = start_block(&b);
|
||||||
|
|
||||||
|
emit_begin_node(&b, "fake");
|
||||||
|
emit_end_node(&b);
|
||||||
|
emit_fdt_end(&b);
|
||||||
|
finish_struct_block(&b, hdr, ss);
|
||||||
|
}
|
||||||
|
|
||||||
|
finish_strings_block(&b, hdr, start_block(&b));
|
||||||
|
|
||||||
|
finish_totalsize(&b, hdr);
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tree table and main */
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
struct buf (*generator)(void);
|
||||||
|
const char *filename;
|
||||||
|
} trees[] = {
|
||||||
|
#define TREE(name) { make_##name, #name ".dtb" }
|
||||||
|
TREE(test_tree1),
|
||||||
|
TREE(bad_node_char), TREE(bad_node_format), TREE(bad_prop_char),
|
||||||
|
TREE(ovf_size_strings),
|
||||||
|
TREE(truncated_property), TREE(truncated_string),
|
||||||
|
TREE(truncated_memrsv),
|
||||||
|
TREE(unterminated_memrsv),
|
||||||
|
TREE(two_roots),
|
||||||
|
TREE(named_root),
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if (argc != 2) {
|
||||||
|
fprintf(stderr, "Usage: %s <output-dir>\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chdir(argv[1]) != 0) {
|
||||||
|
perror("chdir()");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(trees); i++) {
|
||||||
|
struct buf b = trees[i].generator();
|
||||||
|
const char *filename = trees[i].filename;
|
||||||
|
int fd;
|
||||||
|
ssize_t ret;
|
||||||
|
|
||||||
|
printf("Tree \"%s\", %zu bytes\n", filename, b.cursor);
|
||||||
|
|
||||||
|
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||||
|
if (fd < 0)
|
||||||
|
perror("open()");
|
||||||
|
|
||||||
|
ret = write(fd, b.data, b.cursor);
|
||||||
|
if (ret < 0 || (size_t)ret != b.cursor)
|
||||||
|
perror("write()");
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
free(b.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
343
tests/trees.S
343
tests/trees.S
|
|
@ -1,343 +0,0 @@
|
||||||
#include <fdt.h>
|
|
||||||
#include "testdata.h"
|
|
||||||
|
|
||||||
.macro fdtlong val
|
|
||||||
.byte ((\val) >> 24) & 0xff
|
|
||||||
.byte ((\val) >> 16) & 0xff
|
|
||||||
.byte ((\val) >> 8) & 0xff
|
|
||||||
.byte (\val) & 0xff
|
|
||||||
.endm
|
|
||||||
|
|
||||||
.macro treehdr tree
|
|
||||||
.balign 8
|
|
||||||
.globl \tree
|
|
||||||
\tree :
|
|
||||||
fdtlong FDT_MAGIC
|
|
||||||
fdtlong (\tree\()_end - \tree)
|
|
||||||
fdtlong (\tree\()_struct - \tree)
|
|
||||||
fdtlong (\tree\()_strings - \tree)
|
|
||||||
fdtlong (\tree\()_rsvmap - \tree)
|
|
||||||
fdtlong 0x11
|
|
||||||
fdtlong 0x10
|
|
||||||
fdtlong 0
|
|
||||||
fdtlong (\tree\()_strings_end - \tree\()_strings)
|
|
||||||
fdtlong (\tree\()_struct_end - \tree\()_struct)
|
|
||||||
.endm
|
|
||||||
|
|
||||||
.macro rsvmape addrh, addrl, lenh, lenl
|
|
||||||
fdtlong \addrh
|
|
||||||
fdtlong \addrl
|
|
||||||
fdtlong \lenh
|
|
||||||
fdtlong \lenl
|
|
||||||
.endm
|
|
||||||
|
|
||||||
.macro empty_rsvmap tree
|
|
||||||
.balign 8
|
|
||||||
\tree\()_rsvmap:
|
|
||||||
rsvmape 0, 0, 0, 0
|
|
||||||
\tree\()_rsvmap_end:
|
|
||||||
.endm
|
|
||||||
|
|
||||||
.macro prophdr tree, name, len
|
|
||||||
fdtlong FDT_PROP
|
|
||||||
fdtlong \len
|
|
||||||
fdtlong (\tree\()_\name - \tree\()_strings)
|
|
||||||
.endm
|
|
||||||
|
|
||||||
.macro propnil tree, name
|
|
||||||
prophdr \tree, \name, 0
|
|
||||||
.endm
|
|
||||||
|
|
||||||
.macro propu32 tree, name, val
|
|
||||||
prophdr \tree, \name, 4
|
|
||||||
fdtlong \val
|
|
||||||
.endm
|
|
||||||
|
|
||||||
.macro propu64 tree, name, valh, vall
|
|
||||||
prophdr \tree, \name, 8
|
|
||||||
fdtlong \valh
|
|
||||||
fdtlong \vall
|
|
||||||
.endm
|
|
||||||
|
|
||||||
.macro propstr tree, name, str:vararg
|
|
||||||
prophdr \tree, \name, (55f - 54f)
|
|
||||||
54:
|
|
||||||
.asciz \str
|
|
||||||
55:
|
|
||||||
.balign 4
|
|
||||||
.endm
|
|
||||||
|
|
||||||
.macro beginn name:vararg
|
|
||||||
fdtlong FDT_BEGIN_NODE
|
|
||||||
.asciz \name
|
|
||||||
.balign 4
|
|
||||||
.endm
|
|
||||||
|
|
||||||
.macro endn
|
|
||||||
fdtlong FDT_END_NODE
|
|
||||||
.endm
|
|
||||||
|
|
||||||
.macro string tree, name, str:vararg
|
|
||||||
\tree\()_\name :
|
|
||||||
.asciz \str
|
|
||||||
.endm
|
|
||||||
|
|
||||||
|
|
||||||
.data
|
|
||||||
|
|
||||||
treehdr test_tree1
|
|
||||||
|
|
||||||
.balign 8
|
|
||||||
test_tree1_rsvmap:
|
|
||||||
rsvmape TEST_ADDR_1H, TEST_ADDR_1L, TEST_SIZE_1H, TEST_SIZE_1L
|
|
||||||
rsvmape TEST_ADDR_2H, TEST_ADDR_2L, TEST_SIZE_2H, TEST_SIZE_2L
|
|
||||||
rsvmape 0, 0, 0, 0
|
|
||||||
test_tree1_rsvmap_end:
|
|
||||||
|
|
||||||
test_tree1_struct:
|
|
||||||
beginn ""
|
|
||||||
propstr test_tree1, compatible, "test_tree1"
|
|
||||||
propu32 test_tree1, prop_int, TEST_VALUE_1
|
|
||||||
propu64 test_tree1, prop_int64, TEST_VALUE64_1H, TEST_VALUE64_1L
|
|
||||||
propstr test_tree1, prop_str, TEST_STRING_1
|
|
||||||
propu32 test_tree1, address_cells, 1
|
|
||||||
propu32 test_tree1, size_cells, 0
|
|
||||||
|
|
||||||
beginn "subnode@1"
|
|
||||||
propstr test_tree1, compatible, "subnode1"
|
|
||||||
propu32 test_tree1, reg, 1
|
|
||||||
propu32 test_tree1, prop_int, TEST_VALUE_1
|
|
||||||
|
|
||||||
beginn "subsubnode"
|
|
||||||
propstr test_tree1, compatible, "subsubnode1\0subsubnode"
|
|
||||||
propstr test_tree1, placeholder, "this is a placeholder string\0string2"
|
|
||||||
propu32 test_tree1, prop_int, TEST_VALUE_1
|
|
||||||
endn
|
|
||||||
|
|
||||||
beginn "ss1"
|
|
||||||
endn
|
|
||||||
|
|
||||||
endn
|
|
||||||
|
|
||||||
beginn "subnode@2"
|
|
||||||
propu32 test_tree1, reg, 2
|
|
||||||
propu32 test_tree1, linux_phandle, PHANDLE_1
|
|
||||||
propu32 test_tree1, prop_int, TEST_VALUE_2
|
|
||||||
propu32 test_tree1, address_cells, 1
|
|
||||||
propu32 test_tree1, size_cells, 0
|
|
||||||
|
|
||||||
beginn "subsubnode@0"
|
|
||||||
propu32 test_tree1, reg, 0
|
|
||||||
propu32 test_tree1, phandle, PHANDLE_2
|
|
||||||
propstr test_tree1, compatible, "subsubnode2\0subsubnode"
|
|
||||||
propu32 test_tree1, prop_int, TEST_VALUE_2
|
|
||||||
endn
|
|
||||||
|
|
||||||
beginn "ss2"
|
|
||||||
endn
|
|
||||||
|
|
||||||
endn
|
|
||||||
|
|
||||||
endn
|
|
||||||
fdtlong FDT_END
|
|
||||||
test_tree1_struct_end:
|
|
||||||
|
|
||||||
test_tree1_strings:
|
|
||||||
string test_tree1, compatible, "compatible"
|
|
||||||
string test_tree1, prop_int, "prop-int"
|
|
||||||
string test_tree1, prop_int64, "prop-int64"
|
|
||||||
string test_tree1, prop_str, "prop-str"
|
|
||||||
string test_tree1, linux_phandle, "linux,phandle"
|
|
||||||
string test_tree1, phandle, "phandle"
|
|
||||||
string test_tree1, reg, "reg"
|
|
||||||
string test_tree1, placeholder, "placeholder"
|
|
||||||
string test_tree1, address_cells, "#address-cells"
|
|
||||||
string test_tree1, size_cells, "#size-cells"
|
|
||||||
test_tree1_strings_end:
|
|
||||||
test_tree1_end:
|
|
||||||
|
|
||||||
|
|
||||||
treehdr truncated_property
|
|
||||||
empty_rsvmap truncated_property
|
|
||||||
|
|
||||||
truncated_property_struct:
|
|
||||||
beginn ""
|
|
||||||
prophdr truncated_property, prop_truncated, 4
|
|
||||||
/* Oops, no actual property data here */
|
|
||||||
truncated_property_struct_end:
|
|
||||||
|
|
||||||
truncated_property_strings:
|
|
||||||
string truncated_property, prop_truncated, "truncated"
|
|
||||||
truncated_property_strings_end:
|
|
||||||
|
|
||||||
truncated_property_end:
|
|
||||||
|
|
||||||
|
|
||||||
treehdr bad_node_char
|
|
||||||
empty_rsvmap bad_node_char
|
|
||||||
|
|
||||||
bad_node_char_struct:
|
|
||||||
beginn ""
|
|
||||||
beginn "sub$node"
|
|
||||||
endn
|
|
||||||
endn
|
|
||||||
fdtlong FDT_END
|
|
||||||
bad_node_char_struct_end:
|
|
||||||
|
|
||||||
bad_node_char_strings:
|
|
||||||
bad_node_char_strings_end:
|
|
||||||
bad_node_char_end:
|
|
||||||
|
|
||||||
|
|
||||||
treehdr bad_node_format
|
|
||||||
empty_rsvmap bad_node_format
|
|
||||||
|
|
||||||
bad_node_format_struct:
|
|
||||||
beginn ""
|
|
||||||
beginn "subnode@1@2"
|
|
||||||
endn
|
|
||||||
endn
|
|
||||||
fdtlong FDT_END
|
|
||||||
bad_node_format_struct_end:
|
|
||||||
|
|
||||||
bad_node_format_strings:
|
|
||||||
bad_node_format_strings_end:
|
|
||||||
bad_node_format_end:
|
|
||||||
|
|
||||||
|
|
||||||
treehdr bad_prop_char
|
|
||||||
empty_rsvmap bad_prop_char
|
|
||||||
|
|
||||||
bad_prop_char_struct:
|
|
||||||
beginn ""
|
|
||||||
propu32 bad_prop_char, prop, TEST_VALUE_1
|
|
||||||
endn
|
|
||||||
fdtlong FDT_END
|
|
||||||
bad_prop_char_struct_end:
|
|
||||||
|
|
||||||
bad_prop_char_strings:
|
|
||||||
string bad_prop_char, prop, "prop$erty"
|
|
||||||
bad_prop_char_strings_end:
|
|
||||||
bad_prop_char_end:
|
|
||||||
|
|
||||||
|
|
||||||
/* overflow_size_strings */
|
|
||||||
.balign 8
|
|
||||||
.globl ovf_size_strings
|
|
||||||
ovf_size_strings:
|
|
||||||
fdtlong FDT_MAGIC
|
|
||||||
fdtlong (ovf_size_strings_end - ovf_size_strings)
|
|
||||||
fdtlong (ovf_size_strings_struct - ovf_size_strings)
|
|
||||||
fdtlong (ovf_size_strings_strings - ovf_size_strings)
|
|
||||||
fdtlong (ovf_size_strings_rsvmap - ovf_size_strings)
|
|
||||||
fdtlong 0x11
|
|
||||||
fdtlong 0x10
|
|
||||||
fdtlong 0
|
|
||||||
fdtlong 0xffffffff
|
|
||||||
fdtlong (ovf_size_strings_struct_end - ovf_size_strings_struct)
|
|
||||||
empty_rsvmap ovf_size_strings
|
|
||||||
|
|
||||||
ovf_size_strings_struct:
|
|
||||||
beginn ""
|
|
||||||
propu32 ovf_size_strings, bad_string, 0
|
|
||||||
endn
|
|
||||||
fdtlong FDT_END
|
|
||||||
ovf_size_strings_struct_end:
|
|
||||||
|
|
||||||
ovf_size_strings_strings:
|
|
||||||
string ovf_size_strings, x, "x"
|
|
||||||
ovf_size_strings_bad_string = ovf_size_strings_strings + 0x10000000
|
|
||||||
ovf_size_strings_strings_end:
|
|
||||||
ovf_size_strings_end:
|
|
||||||
|
|
||||||
|
|
||||||
/* truncated_string */
|
|
||||||
treehdr truncated_string
|
|
||||||
empty_rsvmap truncated_string
|
|
||||||
|
|
||||||
truncated_string_struct:
|
|
||||||
beginn ""
|
|
||||||
propnil truncated_string, good_string
|
|
||||||
propnil truncated_string, bad_string
|
|
||||||
endn
|
|
||||||
fdtlong FDT_END
|
|
||||||
truncated_string_struct_end:
|
|
||||||
|
|
||||||
truncated_string_strings:
|
|
||||||
string truncated_string, good_string, "good"
|
|
||||||
truncated_string_bad_string:
|
|
||||||
.ascii "bad"
|
|
||||||
/* NOTE: terminating \0 deliberately missing */
|
|
||||||
truncated_string_strings_end:
|
|
||||||
truncated_string_end:
|
|
||||||
|
|
||||||
|
|
||||||
/* truncated_memrsv */
|
|
||||||
treehdr truncated_memrsv
|
|
||||||
|
|
||||||
truncated_memrsv_struct:
|
|
||||||
beginn ""
|
|
||||||
endn
|
|
||||||
fdtlong FDT_END
|
|
||||||
truncated_memrsv_struct_end:
|
|
||||||
|
|
||||||
truncated_memrsv_strings:
|
|
||||||
truncated_memrsv_strings_end:
|
|
||||||
|
|
||||||
.balign 8
|
|
||||||
truncated_memrsv_rsvmap:
|
|
||||||
rsvmape TEST_ADDR_1H, TEST_ADDR_1L, TEST_SIZE_1H, TEST_SIZE_1L
|
|
||||||
truncated_memrsv_rsvmap_end:
|
|
||||||
|
|
||||||
truncated_memrsv_end:
|
|
||||||
|
|
||||||
/* unterminated_memrsv */
|
|
||||||
treehdr unterminated_memrsv
|
|
||||||
|
|
||||||
unterminated_memrsv_rsvmap:
|
|
||||||
rsvmape TEST_ADDR_1H, TEST_ADDR_1L, TEST_SIZE_1H, TEST_SIZE_1L
|
|
||||||
unterminated_memrsv_rsvmap_end:
|
|
||||||
|
|
||||||
unterminated_memrsv_struct:
|
|
||||||
beginn ""
|
|
||||||
endn
|
|
||||||
fdtlong FDT_END
|
|
||||||
unterminated_memrsv_struct_end:
|
|
||||||
|
|
||||||
unterminated_memrsv_strings:
|
|
||||||
unterminated_memrsv_strings_end:
|
|
||||||
|
|
||||||
unterminated_memrsv_end:
|
|
||||||
|
|
||||||
/* two root nodes */
|
|
||||||
treehdr two_roots
|
|
||||||
empty_rsvmap two_roots
|
|
||||||
|
|
||||||
two_roots_struct:
|
|
||||||
beginn ""
|
|
||||||
endn
|
|
||||||
beginn ""
|
|
||||||
endn
|
|
||||||
fdtlong FDT_END
|
|
||||||
two_roots_struct_end:
|
|
||||||
|
|
||||||
two_roots_strings:
|
|
||||||
two_roots_strings_end:
|
|
||||||
|
|
||||||
two_roots_end:
|
|
||||||
|
|
||||||
|
|
||||||
/* root node with a non-empty name */
|
|
||||||
treehdr named_root
|
|
||||||
empty_rsvmap named_root
|
|
||||||
|
|
||||||
named_root_struct:
|
|
||||||
beginn "fake"
|
|
||||||
endn
|
|
||||||
fdtlong FDT_END
|
|
||||||
named_root_struct_end:
|
|
||||||
|
|
||||||
named_root_strings:
|
|
||||||
named_root_strings_end:
|
|
||||||
|
|
||||||
named_root_end:
|
|
||||||
|
|
@ -19,12 +19,13 @@
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
void *fdt = &truncated_memrsv;
|
void *fdt;
|
||||||
void *buf;
|
void *buf;
|
||||||
int err;
|
int err;
|
||||||
uint64_t addr, size;
|
uint64_t addr, size;
|
||||||
|
|
||||||
test_init(argc, argv);
|
test_init(argc, argv);
|
||||||
|
fdt = load_blob_arg(argc, argv);
|
||||||
|
|
||||||
err = fdt_check_header(fdt);
|
err = fdt_check_header(fdt);
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
|
|
|
||||||
|
|
@ -13,17 +13,15 @@
|
||||||
#include <libfdt.h>
|
#include <libfdt.h>
|
||||||
|
|
||||||
#include "tests.h"
|
#include "tests.h"
|
||||||
#include "testdata.h"
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
void *fdt = &truncated_property;
|
void *fdt;
|
||||||
const void *prop;
|
const void *prop;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
test_init(argc, argv);
|
test_init(argc, argv);
|
||||||
|
fdt = load_blob_arg(argc, argv);
|
||||||
vg_prepare_blob(fdt, fdt_totalsize(fdt));
|
|
||||||
|
|
||||||
prop = fdt_getprop(fdt, 0, "truncated", &len);
|
prop = fdt_getprop(fdt, 0, "truncated", &len);
|
||||||
if (prop)
|
if (prop)
|
||||||
|
|
|
||||||
|
|
@ -13,18 +13,16 @@
|
||||||
#include <libfdt.h>
|
#include <libfdt.h>
|
||||||
|
|
||||||
#include "tests.h"
|
#include "tests.h"
|
||||||
#include "testdata.h"
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
void *fdt = &truncated_string;
|
void *fdt;
|
||||||
const struct fdt_property *good, *bad;
|
const struct fdt_property *good, *bad;
|
||||||
int off, len;
|
int off, len;
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
test_init(argc, argv);
|
test_init(argc, argv);
|
||||||
|
fdt = load_blob_arg(argc, argv);
|
||||||
vg_prepare_blob(fdt, fdt_totalsize(fdt));
|
|
||||||
|
|
||||||
off = fdt_first_property_offset(fdt, 0);
|
off = fdt_first_property_offset(fdt, 0);
|
||||||
good = fdt_get_property_by_offset(fdt, off, NULL);
|
good = fdt_get_property_by_offset(fdt, off, NULL);
|
||||||
|
|
|
||||||
|
|
@ -22,12 +22,13 @@
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
void *fdt = &unterminated_memrsv;
|
void *fdt;
|
||||||
void *buf;
|
void *buf;
|
||||||
int err;
|
int err;
|
||||||
uint64_t addr, size;
|
uint64_t addr, size;
|
||||||
|
|
||||||
test_init(argc, argv);
|
test_init(argc, argv);
|
||||||
|
fdt = load_blob_arg(argc, argv);
|
||||||
|
|
||||||
err = fdt_check_header(fdt);
|
err = fdt_check_header(fdt);
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue