Files
reverse-engineering-anything/scripts/verify/firmware/devicetree.mjs
T
morluto c0dd084376 refactor(verify): give seven verifier directories' fixture roots to VerifierFixture (#11055)
* refactor(verify): give the android, electron, firmware, ghidra-seed, harmony, inspector and managed verifiers' roots to VerifierFixture

Each root is removed only after the MCP clients, transports, owned processes
and file handles that may still use it confirm cleanup; a failed cleanup
retains and names the root. The verifier-fixture-root baseline shrinks from
90 files / 95 sites to 80 / 85.

* fix(verify): keep nested Electron and inspector children owned by the fixture, and plain roots where Windows creates directories

The Electron cancellation CLI and application, and each inspector target,
now register their stop with the fixture (onceConfirmed keeps the early stop),
so the root is removed only after they confirm. The android and inspector
verifiers keep a plain directory as before: tools create directories beneath
the root, which a private root blocks on Windows.
2026-11-15 19:33:03 +08:00

101 lines
3.1 KiB
JavaScript

import assert from "node:assert/strict";
import { createPackageVerifierCommands } from "../../lib/verify-package-commands.mjs";
import { withVerifierCleanup } from "../../lib/verifier-cleanup.mjs";
import { VerifierFixture } from "../../lib/verifier-fixture.mjs";
import { readFileSync, writeFileSync } from "node:fs";
import { join } from "node:path";
// Optional verification tool only; the runtime inspector never starts dtc.
const dtc = process.env.REA_DTC_PATH ?? "dtc";
const fixture = await VerifierFixture.open({
prefix: "rea-dtb-verification-",
});
const root = fixture.path;
const commands = await createPackageVerifierCommands({
workspace: {
path: root,
close: () => fixture.release(),
},
});
const exec = async (command, args) =>
(
await commands.exec(command, args, {
timeout: 120_000,
maxBuffer: 16 * 1024 * 1024,
})
).stdout;
await withVerifierCleanup(async () => {
assert.match(await exec(dtc, ["--version"]), /DTC 1\.8\.1\b/);
const source = join(root, "board.dts"),
blob = join(root, "board.dtb");
writeFileSync(
source,
`/dts-v1/;
/memreserve/ 0x80000000 0x1000;
/ {
compatible = "rea,verification"; model = "REA DTB verification";
#address-cells = <1>; #size-cells = <1>;
chosen { bootargs = "console=ttyS0"; stdout-path = "serial0"; };
aliases { serial0 = &serial; };
reserved-memory { #address-cells = <1>; #size-cells = <1>; ranges;
region@80000000 { reg = <0x80000000 0x1000>; no-map; };
};
serial: serial@1000 { reg = <0x1000 0x100>; phandle = <1>; };
consumer { remote-endpoint = <&serial>; };
};\n`,
);
await exec(dtc, ["-I", "dts", "-O", "dtb", "-o", blob, source]);
const decompiled = await exec(dtc, ["-I", "dtb", "-O", "dts", blob]);
const evidence = JSON.parse(
await exec(process.execPath, [
"scripts/rea.mjs",
"inspect-devicetree",
blob,
"--json",
]),
);
const report = evidence.normalized_result;
// This controlled fixture uses one opening/closing brace per node line.
const paths = [],
stack = [];
for (const line of decompiled.split("\n")) {
const begin = /^\s*([^\s{}]+)\s*\{\s*$/.exec(line);
if (begin) {
stack.push(begin[1]);
paths.push(stack.length === 1 ? "/" : `/${stack.slice(1).join("/")}`);
}
if (/^\s*};/.test(line)) stack.pop();
}
assert.deepEqual(
report.nodes.map((n) => n.path),
paths,
);
assert.equal(report.summary.bootargs, "console=ttyS0");
assert.deepEqual(report.summary.aliases, [
{ name: "serial0", path: "/serial@1000" },
]);
assert.equal(report.references[0].target, "/serial@1000");
assert.equal(report.reservations[0].address, "0x80000000");
assert.equal(
report.nodes
.find((n) => n.path.endsWith("region@80000000"))
.properties.find((p) => p.name === "reg").derived.reg[0].size,
"0x1000",
);
assert.equal(readFileSync(blob).readUInt32BE(0), 0xd00dfeed);
console.log(
JSON.stringify(
{
dtc: "1.8.1",
matched_node_paths: paths,
summary: report.summary,
reservations: report.reservations,
references: report.references,
},
null,
2,
),
);
}, [() => commands.close()]);