diff --git a/app/DTNode.stories.tsx b/app/DTNode.stories.tsx index 9552d44..714e838 100644 --- a/app/DTNode.stories.tsx +++ b/app/DTNode.stories.tsx @@ -10,7 +10,7 @@ const meta = { baseAddr: {}, compat: {}, }, - status: { control: "radio", options: ["okay", "disabled"] }, + status: { control: "radio", options: ["okay", "disabled", undefined] }, }, } satisfies Meta; @@ -22,6 +22,7 @@ export const Simple: Story = { data: { label: "UART", baseAddr: "0x0c00_0000", + compat: "ns16550a", }, status: "okay", }, diff --git a/app/DTNode.tsx b/app/DTNode.tsx index dec406e..c611ed0 100644 --- a/app/DTNode.tsx +++ b/app/DTNode.tsx @@ -4,6 +4,7 @@ import { Handle, type NodeProps, Position } from "reactflow"; import { type DTStatus, type DTNodeData } from "./lib"; import compatDb from "./compat-db.json"; import type { DocsCategory } from "./compat-db.json"; +import genericNames from "./generic-names.json"; const dotColors: Record = { okay: "blue", @@ -79,37 +80,112 @@ const Compat: FC<{ compat?: string }> = ({ compat }) => { ); }; +export const Extra: FC<{ data: DTNodeData }> = ({ data }) => { + const { + // handles + resets, + clocks, + mboxes, + phandle, + phySupply, + phyHandle, + pcsphyHandle, + fmanMac, + // generic + type, + description, + // FIT + arch, + os, + kernel, + compression, + load, + entry, + } = data; + + const e = JSON.stringify( + { + resets, + clocks, + mboxes, + phandle, + phySupply, + phyHandle, + pcsphyHandle, + fmanMac, + }, + null, + 2, + ); + const x = JSON.stringify( + { + type, + description, + arch, + os, + kernel, + compression, + load, + entry, + }, + null, + 2, + ); + + return ( +
+ {e} + {x} +
+ ); +}; + export const DataNode: FC<{ data: DTNodeData; status?: DTStatus }> = ({ data, status, }) => { - if (!data) { - return null; - } - + const extraClass = genericNames.includes(data.label) ? "generic" : ""; return (
- {data.label} - {data.baseAddr} - - +
{data.label}
+
+ {data.model} + {data.baseAddr} + + + {data.extra} + +
); diff --git a/app/lib.ts b/app/lib.ts index e99da87..63597e8 100644 --- a/app/lib.ts +++ b/app/lib.ts @@ -75,6 +75,17 @@ const getPropStr = (n: DTNode, pname: string): string | null => { return p ? p.join(", ") : null; }; +const getExtra = (n: DTNode) => { + if (n.name === "aliases" || n.name === "chosen") { + const ps = n.props.map((p) => { + const [k, v] = p; + return `${k}=${u8ArrToStr(v)}`; + }); + return ps.join("\n"); + } + return null; +}; + // transform a node's props into numbers and strings, omitting many const transformNode = (n: DTNode): DTNode => { const name = n.name || "root"; @@ -83,24 +94,66 @@ const transformNode = (n: DTNode): DTNode => { // phy-handle is a ref to another node // TODO: make list of props that are refs const phyHandle = getProp(n, "phy-handle"); + const pcsphyHandle = getProp(n, "pcsphy-handle"); const phySupply = getProp(n, "phy-supply"); + const mboxes = getProp(n, "mboxes"); const resets = getProp(n, "resets"); const dmas = getProp(n, "dmas"); - const clks = getProp(n, "clocks"); + const clocks = getProp(n, "clocks"); const cnames = getStringProp(n, "clock-names"); const compat = getStringProp(n, "compatible"); const status = getStringProp(n, "status"); + const model = getStringProp(n, "model"); + + // Freescale SDK, _NOT_ mainline + const fmanMac = getProp(n, "fsl,fman-mac"); + + const fitStrings = [ + "description", + "type", + "arch", + "os", + "kernel", + "compression", + ]; + const fit = fitStrings.reduce((a, p) => { + const s = getStringProp(n, p); + if (s) { + a[p] = s; + } + return a; + }, {}); + const fitVals = ["load", "entry"]; + const fitV = fitVals.reduce((a, p) => { + const s = getProp(n, p); + if (s) { + // console.info({ [p]: s }); + a[p] = padHexStr(s[0].toString(16)); + } + return a; + }, {}); + + const extra = getExtra(n); + return { name, ...(phandle ? { phandle: phandle[0] } : null), ...(phySupply ? { phySupply: phySupply[0] } : null), ...(phyHandle ? { phyHandle: phyHandle[0] } : null), + ...(pcsphyHandle ? { pcsphyHandle: pcsphyHandle[0] } : null), + ...(fmanMac ? { fmanMac: fmanMac[0] } : null), ...(resets ? { resets } : null), ...(dmas ? { dmas } : null), - ...(clks ? { clks } : null), + ...(clocks ? { clocks } : null), ...(cnames ? { cnames } : null), ...(compat ? { compat } : null), ...(status ? { status } : null), + ...(model ? { model } : null), + ...(mboxes ? { mboxes } : null), + + ...fit, + ...fitV, + extra, }; }; @@ -114,8 +167,8 @@ export const transform = (n: DTNode, id: string = "10000") => { }; }; -const NODE_WIDTH = 160; -const NODE_HEIGHT = 80; +const NODE_WIDTH = 320; +const NODE_HEIGHT = 480; const weightedNode = (node: DTNode): DTNode => { if (node.children && node.children.length > 0) { @@ -134,11 +187,11 @@ const weightedNode = (node: DTNode): DTNode => { * Format to hex with leading 0x, padded with zeroes to groups of four digits. * At least print 8 digits, but omit the first 4 of 12 if they are all 0. */ -const transformAddr = (addr: string): string => { - if (addr === undefined) { +const padHexStr = (val: string): string => { + if (val === undefined) { return ""; } - const padded = addr.padStart(12, "0"); + const padded = val.padStart(12, "0"); const p1 = padded.substr(0, 4); const p2 = padded.substr(4, 4); const p3 = padded.substr(8, 4); @@ -152,31 +205,38 @@ const transformAddr = (addr: string): string => { export const getNodesEdges = (tree: DTNode) => { const nodes: TransformedNode[] = []; const edges: TransformedEdge[] = []; + // map phandle -> id + const phandles = {}; const rec = ( n: DTNode, d: number = 1, baseX: number = 0, baseY: number = 0, ) => { - const [name, addr] = n.name.split("@"); - const baseAddr = transformAddr(addr); + const { id, name, ...data } = n; + const [label, addr] = name.split("@"); + const baseAddr = padHexStr(addr); nodes.push({ - id: n.id, + id, type: NodeType.custom, position: { x: baseX + (n.size * NODE_WIDTH) / 2, y: baseY + d * NODE_HEIGHT, }, data: { - label: name, + label, baseAddr, - size: n.size, - compat: n.compat, - status: n.status, + ...data, }, }); let offset = baseX; + + // TODO: store ID + #*-size + const phandle = data.phandle; + if (phandle != null) { + phandles[phandle] = id; + } n.children.forEach((c: DTNode, i: number) => { edges.push({ id: `${n.id}${c.id}`, @@ -189,5 +249,76 @@ export const getNodesEdges = (tree: DTNode) => { }; const t = weightedNode(tree); rec(t); + + console.info({ phandles }); + + // create edges for phandles + nodes.forEach((n) => { + if (n.data.clocks) { + const ref = n.data.clocks[0]; + const refId = phandles[ref]; + if (refId !== undefined) { + const e = { + id: `clocks-${refId}_${n.id}`, + source: n.id, + target: refId, + }; + console.info({ ...e }); + edges.push(e); + } + } + if (n.data.mboxes) { + const ref = n.data.mboxes[0]; + const refId = phandles[ref]; + if (refId !== undefined) { + const e = { + id: `mboxes-${refId}_${n.id}`, + source: n.id, + target: refId, + }; + console.info({ ...e }); + edges.push(e); + } + } + if (n.data.phyHandle) { + const ref = n.data.phyHandle; + const refId = phandles[ref]; + if (refId !== undefined) { + const e = { + id: `phy-${refId}_${n.id}`, + source: n.id, + target: refId, + }; + console.info({ ...e }); + edges.push(e); + } + } + if (n.data.pcsphyHandle) { + const ref = n.data.pcsphyHandle; + const refId = phandles[ref]; + if (refId !== undefined) { + const e = { + id: `pcsphy-${refId}_${n.id}`, + source: n.id, + target: refId, + }; + console.info({ ...e }); + edges.push(e); + } + } + if (n.data.fmanMac) { + const ref = n.data.fmanMac; + const refId = phandles[ref]; + if (refId !== undefined) { + const e = { + id: `fmanmac-${refId}_${n.id}`, + source: n.id, + target: refId, + }; + console.info({ ...e }); + edges.push(e); + } + } + }); return { nodes, edges }; }; diff --git a/app/page.tsx b/app/page.tsx index 9e6c4c0..b9a919c 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -26,7 +26,9 @@ type ParseDtbFunction = (data: number[]) => Promise; export default function Home() { const [fbuf, setFbuf] = useState(null); const [inProgress, setInProgress] = useState(false); - const [parser, setParser] = useState<{ parse_dtb: ParseDtbFunction } | null>(null); + const [parser, setParser] = useState<{ parse_dtb: ParseDtbFunction } | null>( + null, + ); const [nodes, setNodes, onNodesChange] = useNodesState([]); const [edges, setEdges, onEdgesChange] = useEdgesState([]); diff --git a/parser/Cargo.lock b/parser/Cargo.lock index 2e7f3fa..273eef2 100644 --- a/parser/Cargo.lock +++ b/parser/Cargo.lock @@ -16,9 +16,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.21" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" dependencies = [ "anstyle", "anstyle-parse", @@ -37,9 +37,9 @@ checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "anstyle-parse" -version = "0.2.7" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" dependencies = [ "utf8parse", ] @@ -72,7 +72,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -111,9 +111,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.4.18" +version = "4.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" +checksum = "473c7e07f409a8d772161724aa8db6a765a2532a70f9667eeb7b49d3d02fbdca" dependencies = [ "clap_builder", "clap_derive", @@ -121,9 +121,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.18" +version = "4.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7" +checksum = "7b48fea5a88e9ae728a2dcbedbfc0e730f7d60da42e1cb049a83c9fb8b789889" dependencies = [ "anstream", "anstyle", @@ -133,21 +133,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.4.7" +version = "4.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +checksum = "d012d2b9d65aca7f18f4d9878a045bc17899bba951561ba5ec3c2ba1eed9a061" dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 3.0.4", ] [[package]] name = "clap_lex" -version = "0.6.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] name = "colorchoice" @@ -233,9 +233,9 @@ dependencies = [ [[package]] name = "heck" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "is_terminal_polyfill" @@ -386,7 +386,7 @@ checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -414,9 +414,9 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "strsim" -version = "0.10.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" @@ -429,6 +429,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6275cddf4610d1775e6d1fe9469b2e77d0f39fd98fb7450901b821e0c53649f" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "unicode-ident" version = "1.0.11" @@ -499,7 +510,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn", + "syn 2.0.117", "wasm-bindgen-shared", ] @@ -542,7 +553,7 @@ checksum = "186ddfe8383ba7ae7927bae3bb7343fd1f03ba2dbaf1474410f0d831131c269b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -602,5 +613,5 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] diff --git a/parser/Cargo.toml b/parser/Cargo.toml index 0801ede..476c393 100644 --- a/parser/Cargo.toml +++ b/parser/Cargo.toml @@ -19,7 +19,7 @@ default = ["console_error_panic_hook"] # all the `std::fmt` and `std::panicking` infrastructure, so isn't great for # code size when deploying. console_error_panic_hook = { version = "0.1.7", optional = true } -device_tree = { git = "https://github.com/platform-system-interface/device_tree-rs", tag = "v2.1.0", package = "psi_device_tree" } +device_tree = { path = "../../device_tree-rs", package = "psi_device_tree" } gloo-utils = { version = "0.3.0", features = ["serde"] } serde = { version = "1.0", features = ["derive"] } wasm-bindgen = "0.2.88"