Device-Tree Alias·Label Debugging — What to Check and How to Align
Logs mention serial0 while the DTS only shows a uart0: label; an overlay target = <&i2c1> works, yet /aliases still points i2c1 at an old SoC path. That kind of name mix-up usually means treating alias · label · node as the same thing.
This post has three axes only: what is an alias? · label vs node? · debug tips? Overlay -@ / __symbols__ belongs with device-tree-overlay-debug; here the focus is aligning public aliases and source labels. No board MB measurements, prices, invented field stories, or affiliates.
Grounded in the Device Tree Specification — /aliases, DTS Labels, and the Linux DeviceTree Kernel API (of_find_node_opts_by_path, of_alias_get_id, and related helpers).
What is an alias?
One-line answer: An alias is a property on the root /aliases node: name = short public nickname, value = that node’s full path string. It is not the same as a DTS label such as uart0:.
Spec summary (§3.3 /aliases):
| Item | Rule |
|---|---|
| Location | Direct child of root, node name /aliases |
| Property name | The alias name (public short name) |
| Property value | Full path string (need not be a leaf) |
| Name charset | Lowercase a-z, digits 0-9, - only · 1–31 chars |
| Clients | When treating a string as a device path, detect and use aliases |
Spec example (paths are illustrative, not a claim about a specific board):
aliases {
serial0 = "/simple-bus@fe000000/serial@llc500";
ethernet0 = "/simple-bus@fe000000/ethernet@31c000";
};
In DTS it is also common to fill the path via a label. Outside a cell array, &Label expands to that node’s full path (§6.3):
aliases {
serial0 = &uart0; /* → full path string of the uart0-labeled node */
};
On the Linux OF side (Kernel API):
of_find_node_opts_by_path(path, …)— ifpathdoes not start with/, it is treated as a property name under/aliases.of_alias_get_id(np, stem)/of_alias_get_highest_id(stem)— obtain the index from stem+number aliases such asserial0,serial1./chosenproperties likestdout-pathmay be an alias per the Spec (§3.5).
Do not: assume the kernel “knows” a DTS label name (uart0) as an alias. Without an /aliases entry, path lookup will not resolve that name.
Label vs node?
One-line answer: A node is the real tree object (name, unit-address, properties). A label is a DTS-only identifier. Labels are not encoded into the DTB (Spec §6.2).
| Aspect | node | label | alias |
|---|---|---|---|
| Where | Tree (DTS→DTB) | DTS only | /aliases property (path string in DTB) |
| Syntax | serial@llc500 { … } | uart0: serial@… | serial0 = "/…/serial@…"; |
| References | full path / phandle | &uart0 | short path name serial0 |
| In DTB | Encoded as node/properties | Not encoded | Encoded as path-string property |
| Length/charset | Node-name rules | 1–31 · 0-9a-zA-Z_ · must not start with a digit | 1–31 · a-z0-9- only (lowercase) |
How & expands (§6.3):
- Inside a cell array
< &label >→ that node’s phandle (number). Example:interrupt-parent = <&mpic>; - Outside a cell array
prop = &label;→ that node’s full path string. Example:ethernet0 = &EMAC0; - Path form:
<&{/soc/interrupt-controller@40000}>
Node shape:
[label:] node-name[@unit-address] {
[properties]
[child nodes]
};
A phandle is a unique numeric ID for a node within the tree; most DTS files omit explicit phandle properties and dtc inserts them when building the DTB (basics · phandle). Labels exist so humans can write &refs in source; aliases exist so boot/firmware/drivers can speak short public names that resolve to paths at runtime.
Confusion points:
- The same node may carry a
uart0:label and aserial0alias. The names need not match. - Overlay
target = <&i2c1>is about base labels/symbols;/aliasesi2c1 = "/…"is a separate entry. Fixing only one side leaves the other wrong. - With
dtc -@,__symbols__may map label→path. That is a symbol table for overlays, not the Spec/aliasesnode.
Debug tips?
One-line answer: Align in order: (1) /aliases path strings → (2) real node exists → (3) DTS labels/& refs → (4) kernel stem ids. Drop the assumption that “label name = alias name.”
1) Start with aliases on the live tree
# Runtime (when permitted) — alias properties = path strings
ls /proc/device-tree/aliases/
cat /proc/device-tree/aliases/serial0 # may be NUL-terminated
# Or dump FS form as DTS
dtc -I fs -O dts /proc/device-tree 2>/dev/null | sed -n '/aliases/,/^};/p'
Check: alias spelling, whether the value is the current full path, and whether a merge/overlay moved the node while the string stayed stale.
2) Labels exist only in source
# Binary → source: labels (: name) were never in the DTB — missing labels in a dump is normal
dtc -I dtb -O dts -o dumped.dts your.dtb
# Symbolized builds may show label→path under __symbols__ (overlay use)
grep -n '__symbols__\|aliases' dumped.dts
Symptom map:
| Symptom | Suspect |
|---|---|
of_find_node_by_path("uart0") fails | uart0 is not an alias. Add /aliases or use a full path / & rules |
serial0 resolves but wrong UART | /aliases path string is stale (node moved/address changed) |
Overlay target = <&foo> fails | Base label/symbol issue (-@, __symbols__) — separate from aliases |
ttyS index unexpected | Check serialN stem N (of_alias_get_id) and binding practice |
DTS has foo: but dumped DTB does not | Expected — labels are not encoded in the DTB |
3) One checklist for label ↔ alias
[ ] Label name (DTS): uart0
[ ] Node path: /soc/serial@...
[ ] Alias property name: serial0
[ ] Alias value string: matches Node path after merge
[ ] Cell refs use: <&uart0> (phandle)
[ ] Path-style refs use: &uart0 or "/soc/serial@..." outside <>
[ ] chosen/stdout-path: full path OR alias name per Spec
Copy-paste order:
1. Locate /aliases in merged DTS or live tree.
2. For each public name (serial0, ethernet0, …): read path string.
3. Resolve that path — node must exist with expected compatible/status.
4. Grep DTS for "label:" used by &refs and overlays — separate from step 2.
5. If stem IDs matter, list aliases matching ^stem[0-9]+$ and sort by N.
6. Never invent board-specific timings/prices; fix names and paths only.
4) Pin expected behavior with kernel APIs
- Path/alias resolution:
of_find_node_opts_by_path - Stem index:
of_alias_get_id/of_alias_get_highest_id - Phandle resolution:
of_find_node_by_phandle,of_parse_phandle*
If a driver or boot doc says “needs serial0 alias,” the contract is an /aliases property with that name — a DTS label uart0: alone is not enough.
One-line wrap-up: label = source & handle, alias = /aliases path shortcut, node = tree object. Debug path strings and node presence first; treat labels as the compile/overlay reference axis.
FAQ
Must alias and label names match?
No. Common practice keeps a numbered public alias (serial0) and a block label (uart0:). If you make them match, do it deliberately and document it in a table.
If /aliases uses &label, what remains in the DTB?
It is an out-of-cell reference, so dtc expands it to a full path string. Runtime keeps that string, not the label token.
May stdout-path be an alias?
Yes. Per the Spec, /chosen stdout-path / stdin-path values may be aliases. Clients must resolve aliases when treating the value as a path.
Why do label and alias character sets differ?
Different Spec rules. Labels allow A-Z and _ and must not start with a digit; aliases are lowercase, digits, and - only. Copying an uppercase label into an alias name yields an invalid alias name.
Sources
- Devicetree Specification — §3.3
/aliases— alias node, names, path strings - Devicetree Specification — §6.2 Labels / §6.3 nodes — labels and
&expansion (phandle vs path) - Devicetree Specification — phandle basics — phandle and dtc insertion
- Linux — DeviceTree Kernel API —
of_find_node_opts_by_path,of_alias_get_id, phandle helpers - Adjacent: device-tree-overlay-debug (overlays,
-@, fixups)