device-tree alias·label 디버깅 — 무엇을 보고 어떻게 맞추나
보드 로그에 serial0이 보이는데 DTS에는 uart0:만 있고, 오버레이 target = <&i2c1>은 되는데 /aliases의 i2c1 경로는 예전 SoC 주소를 가리키는 식의 이름 혼선이 흔합니다. 원인은 대개 alias · label · node를 같은 것으로 취급하는 데 있습니다.
이 글의 축은 셋뿐입니다. alias는? · label vs node? · 디버그 팁은? 오버레이 -@/__symbols__ 자체는 device-tree-overlay-debug 쪽이고, 여기서는 별칭과 라벨을 맞추는 법만 다룹니다. 보드 실측 MB·가격·창작 현장 후기·제휴는 없습니다.
근거: Device Tree Specification — /aliases, DTS Labels, Linux DeviceTree Kernel API(of_find_node_opts_by_path, of_alias_get_id 등).
alias는?
한 줄 답: alias는 루트 /aliases 노드의 프로퍼티입니다. 이름 = 짧은 공개 별칭, 값 = 그 노드의 full path 문자열입니다. DTS의 uart0: 같은 라벨과는 별개입니다.
스펙 요약(§3.3 /aliases):
| 항목 | 규칙 |
|---|---|
| 위치 | 루트 직속, 노드 이름 /aliases |
| 프로퍼티 이름 | alias 이름 (공개 단축명) |
| 프로퍼티 값 | full path 문자열 (리프가 아니어도 됨) |
| 이름 문자 | 소문자 a-z, 숫자 0-9, -만 · 1–31자 |
| 클라이언트 | 경로 문자열을 볼 때 alias를 감지·치환해야 함 |
스펙 예(경로는 스펙 예시이며 특정 보드 주장이 아님):
aliases {
serial0 = "/simple-bus@fe000000/serial@llc500";
ethernet0 = "/simple-bus@fe000000/ethernet@31c000";
};
DTS에서는 라벨로 full path를 채우는 관용도 흔합니다. 셀 배열 밖의 &Label은 그 노드의 full path로 펼쳐집니다(§6.3):
aliases {
serial0 = &uart0; /* → uart0 라벨 노드의 full path 문자열 */
};
리눅스 OF 쪽(Kernel API):
of_find_node_opts_by_path(path, …)—path가/로 시작하지 않으면/aliases의 그 이름 프로퍼티로 해석합니다.of_alias_get_id(np, stem)/of_alias_get_highest_id(stem)—serial0,serial1처럼 stem + 숫자 alias에서 인덱스를 얻습니다./chosen의stdout-path등은 값이 alias여도 된다고 스펙이 명시합니다(§3.5).
하지 말 것: DTS 라벨 이름(uart0)만 보고 “커널이 uart0 alias를 안다”고 가정하기. alias 테이블에 없으면 path lookup은 그 이름을 모릅니다.
label vs node?
한 줄 답: node는 트리에 남는 실체(이름·unit-address·프로퍼티)이고, label은 DTS 소스 전용 식별자입니다. DTB에는 라벨 문자열이 들어가지 않습니다(스펙 §6.2).
| 구분 | node | label | alias |
|---|---|---|---|
| 어디에 있나 | 트리(DTS→DTB) | DTS만 | /aliases 프로퍼티(DTB에 path 문자열로 존재) |
| 표기 | serial@llc500 { … } | uart0: serial@… | serial0 = "/…/serial@…"; |
| 참조 | full path / phandle | &uart0 | path 앞의 단축명 serial0 |
| DTB | 노드·프로퍼티로 인코딩 | 인코딩 안 됨 | path 문자열 프로퍼티로 인코딩 |
| 길이·문자 | 노드 이름 규칙 | 1–31자 · 0-9a-zA-Z_ · 숫자로 시작 금지 | 1–31자 · a-z0-9-만(소문자) |
& 참조의 펼침 규칙(§6.3):
- 셀 배열 안
< &label >→ 그 노드의 phandle(숫자). 예:interrupt-parent = <&mpic>; - 셀 배열 밖
prop = &label;→ 그 노드의 full path 문자열. 예:ethernet0 = &EMAC0; - 경로 직접 참조:
<&{/soc/interrupt-controller@40000}>
노드 정의 형태:
[label:] node-name[@unit-address] {
[properties]
[child nodes]
};
phandle은 스펙상 노드를 가리키는 트리 내 유일 숫자 ID이고, 대부분 DTS에는 명시하지 않으며 dtc가 DTB 생성 시 삽입합니다(basics · phandle). 라벨은 “사람이 &로 쓰기 쉽게” 하는 소스 편의이고, alias는 “부트·드라이버·유저가 짧은 공개 이름으로 path를 말하게” 하는 런타임 테이블입니다.
혼동 포인트:
- 같은 노드에
uart0:라벨과serial0alias를 둘 다 달 수 있습니다. 이름이 같아질 필요는 없습니다. - 오버레이에서
target = <&i2c1>은 베이스의 라벨/심볼 쪽이고,/aliases의i2c1 = "/…"는 별도 엔트리입니다. 한쪽만 고치면 다른 쪽이 어긋납니다. dtc -@로__symbols__에 라벨→path가 실리는 경우는 심볼 테이블이지, 스펙/aliases와 동일하지 않습니다.
디버그 팁은?
한 줄 답: (1) /aliases path 문자열 → (2) 실제 노드 존재 → (3) DTS 라벨/& 참조 → (4) 커널 stem id 순으로 맞추십시오. “라벨 이름 = alias 이름” 가정부터 버리십시오.
1) 살아 있는 트리에서 alias 먼저
# 런타임(권한이 있을 때) — aliases 프로퍼티 = path 문자열
ls /proc/device-tree/aliases/
cat /proc/device-tree/aliases/serial0 # NUL 종료 문자열일 수 있음
# 또는 fs 형태를 DTS로
dtc -I fs -O dts /proc/device-tree 2>/dev/null | sed -n '/aliases/,/^};/p'
확인할 것: alias 이름 철자, 값이 지금 보드의 full path인지, 오버레이·보드 dtsi 병합 뒤 주소가 바뀌었는데 문자열만 옛값인지.
2) DTB/DTS에서 라벨은 “소스에만”
# 바이너리 → 소스: 라벨(: name)은 원래 DTB에 없음 → 복원본에 label이 안 보이는 것이 정상
dtc -I dtb -O dts -o dumped.dts your.dtb
# 심볼을 켠 빌드라면 __symbols__에 label→path가 있을 수 있음(오버레이용)
grep -n '__symbols__\|aliases' dumped.dts
증상 매핑:
| 증상 | 의심 |
|---|---|
of_find_node_by_path("uart0") 실패 | uart0이 alias가 아님. /aliases에 넣거나 full path/& 규칙을 쓸 것 |
serial0은 찾는데 잘못된 UART | /aliases path 문자열이 stale (노드 이동·주소 변경 후 미갱신) |
오버레이 target = <&foo> 실패 | 베이스 라벨/심볼 문제(-@, __symbols__). alias 테이블과 별개로 볼 것 |
ttyS 번호가 기대와 다름 | serialN stem의 숫자 N(of_alias_get_id)과 바인딩 관행을 확인 |
DTS엔 foo:가 있는데 dumped DTB에 없음 | 정상 — 라벨은 DTB 미인코딩 |
3) 소스에서 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
복붙 점검 순서:
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) 커널 API로 기대 동작 고정
- path/
alias해석:of_find_node_opts_by_path - stem 인덱스:
of_alias_get_id/of_alias_get_highest_id - phandle 해석:
of_find_node_by_phandle,of_parse_phandle*
드라이버·부트 문서가 “serial0 alias 필요”라고 하면 /aliases에 그 프로퍼티를 두는 것이 계약이고, DTS 라벨 uart0:만으로는 부족합니다.
한 줄 정리: label = 소스 &용, alias = /aliases의 path 단축명, node = 트리 실체. 디버그는 path 문자열과 노드 존재부터 맞추고, 라벨은 컴파일·오버레이 참조 축으로 따로 보십시오.
FAQ
alias 이름과 label 이름을 같게 해야 하나?
필수가 아닙니다. 관행상 serial0 alias + uart0: label처럼 공개 번호 체계와 SoC 블록 이름을 나누는 경우가 많습니다. 맞출 때는 의도적으로 맞추고, 문서에 표로 남기십시오.
/aliases 값이 &label이면 DTB에는 무엇이 남나?
셀 밖 참조이므로 dtc가 full path 문자열로 펼칩니다. 런타임에 남는 것은 그 path 문자열이지 라벨 토큰이 아닙니다.
stdout-path에 alias를 넣어도 되나?
스펙상 /chosen의 stdout-path/stdin-path 값은 alias여도 됩니다. 클라이언트는 경로로 볼 때 alias를 해석해야 합니다.
라벨 문자 집합과 alias 문자 집합이 다른 이유는?
스펙이 다릅니다. 라벨은 A-Z·_ 허용·숫자 시작 금지, alias는 소문자·숫자·-만. 대문자 라벨을 그대로 alias 이름으로 복사하면 잘못된 alias 이름이 됩니다.
출처 (Sources)
- Devicetree Specification — §3.3
/aliases— alias 노드·이름·path 문자열 - Devicetree Specification — §6.2 Labels / §6.3 nodes — 라벨·
&펼침(phandle vs path) - Devicetree Specification — phandle basics — phandle·dtc 삽입
- Linux — DeviceTree Kernel API —
of_find_node_opts_by_path,of_alias_get_id, phandle helpers - 인접: device-tree-overlay-debug(오버레이·
-@·fixups)