# dtc 1.7.0 -- the Device Tree Compiler and its libfdt clients. # # The gate is the round trip the ticket names: compile data/dtc-sample.dts to a # .dtb, decompile it back, and compare. It is compared TWICE, in two different # currencies, because each catches what the other cannot: # # - dtc/roundtrip-dts compares the decompiled text against `dtc -I dts -O dts` # of the same source. That is the source in dtc's OWN canonical spelling, so # the comparison is against the fixture rather than against a stored file # that would rot the day dtc's pretty-printer changes -- and it changes: 1.7.2 # prints a string list as "a", "b", "c" where 1.7.0 prints "a\0b\0c", which is # exactly why the fixture carries no string list. # - dtc/roundtrip-dtb recompiles that decompiled text and cmps the result # against the first .dtb. Text equality can be true while the blob differs; # blob equality is what a consumer of the tree actually depends on. # # dtc/dtb-bytes is the one comparison against a STORED artifact, and it is stored # rather than derived because it is the only case here that would survive dtc # itself being wrong in a self-consistent way -- a round trip is a fixed point of # whatever the compiler does, including the wrong thing. Pinning the bytes is safe # where pinning the text is not: dtc 1.7.0 and 1.7.2 emit this blob byte-for-byte # identically (checked, both directions), because a .dtb is a header, a struct # block and a string block with no timestamp, no padding entropy and no ordering # freedom left after the source is canonicalised. . "$BST_LIB" require dtc dtc/present tmp=${TMPDIR:-/tmp}/bst-dtc.$$ mkdir -p "$tmp" 2>/dev/null src=$BST_DATA/dtc-sample.dts ref=$BST_DATA/dtc-sample.dtb check dtc/fixture-dts test -f "$src" check dtc/fixture-dtb test -f "$ref" check_out dtc/version "1.7.0" dtc --version # --- the round trip ------------------------------------------------------- check dtc/compile dtc -I dts -O dtb -o "$tmp/out.dtb" "$src" check dtc/canon dtc -I dts -O dts -o "$tmp/canon.dts" "$src" check dtc/decompile dtc -I dtb -O dts -o "$tmp/back.dts" "$tmp/out.dtb" check dtc/dtb-bytes cmp "$ref" "$tmp/out.dtb" check dtc/roundtrip-dts cmp "$tmp/canon.dts" "$tmp/back.dts" check dtc/recompile dtc -I dts -O dtb -o "$tmp/again.dtb" "$tmp/back.dts" check dtc/roundtrip-dtb cmp "$tmp/out.dtb" "$tmp/again.dtb" # A tree that does not parse must be refused, not half-written. dtc exits 1 and # says so; a compiler that returns 0 on garbage is the failure this catches. printf '/dts-v1/;\n/ { bogus = <;\n' > "$tmp/bad.dts" check_rc dtc/reject-rc 1 dtc -I dts -O dtb -o "$tmp/never.dtb" "$tmp/bad.dts" # Not check_out: that helper also requires exit 0, and the whole point here is a # non-zero exit, so it would report a correct refusal as a failure. bad=$(dtc -I dts -O dtb -o "$tmp/never.dtb" "$tmp/bad.dts" 2>&1) case "$bad" in *"syntax error"*) bst_ok dtc/reject-msg ;; *) bst_notok dtc/reject-msg "$(_bst_1line "$bad")" ;; esac check dtc/reject-nofile test ! -f "$tmp/never.dtb" # --- libfdt through its shipped clients ----------------------------------- # fdtget/fdtput/fdtdump/fdtoverlay are the libfdt.a that -staticdev installs, # linked and run: the read path (fdt_path_offset/fdt_getprop), the write path # (fdt_setprop on a resized blob) and the overlay applicator. There is no # separate compiled probe for the library because these four ARE it -- a probe # would re-link the same archive to re-ask the same question. if command -v fdtget >/dev/null 2>&1; then check_out fdtget/string "brintOS dtc round-trip fixture" fdtget "$ref" / model check_out fdtget/cells "40000000 10000000" fdtget -t x "$ref" /memory@40000000 reg check_out fdtget/subnode "gpio@10001000" fdtget -l "$ref" /soc check_rc fdtget/missing 1 fdtget "$ref" /nope prop else bst_skip dtc/fdtget "fdtget absent" fi if command -v fdtput >/dev/null 2>&1; then cp "$ref" "$tmp/put.dtb" check fdtput/set fdtput -t s "$tmp/put.dtb" /chosen bootargs "console=hvc0 quiet" check_out fdtput/readback "console=hvc0 quiet" fdtget "$tmp/put.dtb" /chosen bootargs else bst_skip dtc/fdtput "fdtput absent" fi if command -v fdtdump >/dev/null 2>&1; then # 749 is the fixture's own totalsize, so this asserts fdtdump read the header # of THIS blob rather than merely running. check_out fdtdump/header "totalsize:" fdtdump "$ref" check_eq fdtdump/size "749" "$(fdtdump "$ref" 2>/dev/null | awk -F'[()]' '/totalsize:/{print $2; exit}')" else bst_skip dtc/fdtdump "fdtdump absent" fi if command -v fdtoverlay >/dev/null 2>&1; then check dtc/overlay-compile dtc -@ -I dts -O dtb -o "$tmp/ovl.dtbo" "$BST_DATA/dtc-overlay.dts" check dtc/overlay-base dtc -@ -I dts -O dtb -o "$tmp/base.dtb" "$src" check fdtoverlay/apply fdtoverlay -i "$tmp/base.dtb" -o "$tmp/merged.dtb" "$tmp/ovl.dtbo" check_out fdtoverlay/override "disabled" fdtget "$tmp/merged.dtb" /soc/serial@10000000 status check_out fdtoverlay/added "yes" fdtget "$tmp/merged.dtb" /soc/serial@10000000 emcraft,overlay-applied else bst_skip dtc/fdtoverlay "fdtoverlay absent" fi # --- what -dev/-staticdev put on the image -------------------------------- check dtc/libfdt-a test -f /usr/lib/libfdt.a check dtc/libfdt-h test -f /usr/include/libfdt.h check dtc/fdt-h test -f /usr/include/fdt.h check dtc/libfdt-pc test -f /usr/lib/pkgconfig/libfdt.pc rm -rf "$tmp"