Android 버전만으로 이미지 구성을 단정하지 않습니다
옛 설명에서 “boot.img 안에는 커널과 ramdisk가 들어 있습니다”라고 읽었다면, 그 기기가 어느 Android 버전으로 출시됐는지 먼저 확인해야 합니다. Android 12의 GKI 구성에서는 generic ramdisk가 boot 이미지에 들어갑니다. Android 13으로 출시하는 기기는 이를 init_boot로 분리합니다. 기존 커널 구성을 유지하며 업그레이드하는 기기는 예외가 있으므로 OS의 현재 버전 숫자만으로 파티션을 추측하면 안 됩니다. AOSP generic boot 구성
| 이미지 | 담는 대표 내용 | 오해하기 쉬운 점 |
|---|---|---|
boot | GKI kernel, header와 해당 형식의 정보 | 모든 버전에서 generic ramdisk가 함께 있는 것은 아닙니다. |
init_boot | Android 13 출시 기기의 generic ramdisk | vendor 전용 드라이버 전체를 넣는 공간이라는 뜻이 아닙니다. |
vendor_boot | vendor ramdisk, DTB 등 보드 관련 정보 | header v4의 ramdisk fragment 구조 등 버전 차이를 확인합니다. |
vbmeta | 검증에 사용하는 서명·descriptor 등 메타데이터 | 여기에서 커널 명령이 실행되는 것이 아닙니다. |
super | dynamic partition의 공간과 메타데이터 | 하나의 일반 파일 시스템으로 통째로 마운트하는 대상과 다릅니다. |
header의 version은 이미지 형식의 버전입니다. kernel release와 같지 않습니다. GKI 인증용 boot_signature와 제품의 AVB 검증 서명도 역할이 다릅니다. boot header 형식 vendor_boot 구성
AVB의 부팅 검증과 dm-verity의 읽기 검증은 다릅니다
AVB는 신뢰한 키를 기준으로 서명된 VBMeta와 descriptor를 검증합니다. 작은 boot 이미지의 hash와 큰 읽기 전용 system·vendor 영역의 hashtree를 구분하며, 검증 메타데이터가 chained partition으로 연결될 수도 있습니다. 하나의 vbmeta에 모든 데이터가 직접 들어 있다고 해석하지 않습니다. 키 신뢰·rollback index와 locked/unlocked 정책도 제품 구성의 일부입니다.
dm-verity는 신뢰한 root digest를 바탕으로 블록 장치에서 읽는 데이터의 무결성을 확인합니다. 파일 API를 호출할 때마다 파일 전체를 다시 검사하는 기능은 아닙니다. 이미 캐시된 데이터와 check_at_most_once 같은 설정도 구분해야 합니다.
부팅 중의 서명 검증 실패와 실행 중의 hashtree 오류는 발견 시점과 처리 주체가 다릅니다. 실행 중 손상에 대한 I/O 오류·재시작 등의 반응은 선택된 정책에 달려 있으며, 모든 Android Automotive 기기가 반드시 재부팅한다고 단정할 수 없습니다. 실제 이미지 구성·검증 설정·오류 로그를 함께 봐야 합니다.
이 보완은 공개 공식 문서의 범위를 대조한 것입니다. 원본 게시물의 그림을 재사용하지 않았고, 특정 기기의 부팅·손상 주입 시험을 수행한 것은 아닙니다.
부트로더의 적재와 init의 마운트는 다른 단계입니다
- 부트로더
선택한 slot의 이미지와 검증 정보를 읽고 필요한 커널·ramdisk·DTB를 RAM에 배치합니다.
커널 진입 조건에 맞춰 실행을 넘깁니다.
- Linux 커널
CPU·메모리·드라이버를 초기화하고 초기 사용자 공간의 init을 실행합니다.
PID 1의 사용자 공간 실행이 시작됩니다.
- first-stage init
필요한 초기 모듈·장치와 fstab 정보를 바탕으로 초기 마운트를 수행합니다.
SELinux 설정 등 부팅 단계가 이어집니다.
- second-stage init
rc의 action과 service를 처리해 Android 서비스를 시작합니다.
화살표는 부팅 단계의 진행입니다. 부트로더가 init.rc의 service를 직접 실행하거나 system_server가 커널을 시작한다는 뜻이 아닙니다.
그림은 세부 분기를 생략한 구조 설명입니다. recovery, A/B 여부, vendor ramdisk 구성에 따라 경로가 달라집니다. 커널의 일반적인 initramfs 동작과 Android의 init 정책을 구분해서 읽어야 합니다. Linux 초기 사용자 공간 Android init의 action과 service
rc를 읽은 것과 서비스를 실행한 것은 다릅니다
Android 14의 android-14.0.0_r3 init 문법에서 rc는 셸 스크립트가 아닙니다. action은 trigger가 맞을 때 명령 실행 큐에 들어가며, service 선언은 프로세스의 실행 파일과 옵션을 정의합니다. 선언을 파싱했다고 그 프로세스가 즉시 시작되는 것은 아닙니다. import도 다른 설정을 읽어들이는 구문이지 서비스를 시작하는 명령이 아닙니다.
disabled 서비스는 자신의 class가 시작돼도 자동 시작하지 않습니다. 이름이나 interface를 통한 명시적 시작 등이 필요합니다. oneshot은 서비스 종료 뒤 자동 재시작하지 않는다는 뜻이며, rc 파일 전체를 한 번만 실행한다는 뜻이 아닙니다. 실제 시작 여부는 trigger·class·옵션과 실행 조건을 함께 확인해야 합니다.
예를 들어 on boot && property:example.ready=1은 boot 이벤트가 발생할 때 해당 속성이 이미 1인 경우를 뜻합니다. boot 뒤에 속성만 1로 바뀌었다고 이 event·property 조합이 다시 실행되는 것은 아닙니다. 이 예의 속성은 문법 설명용이며 실제 기기의 설정을 바꾸라는 지시가 아닙니다.
소스 트리의 init.rc와 제품에 설치된 system·vendor·odm 등의 rc 구성을 구분하고, 해당 빌드의 import 경로와 파싱 순서를 확인합니다. first-stage의 초기 마운트, SELinux 설정 단계와 second-stage의 rc 처리를 하나의 셸 실행으로 합치지 않습니다. 이 보완은 고정 버전 README의 문법 대조이며 기기 부팅이나 원본 PDF 전체의 독립 검증을 뜻하지 않습니다. Android 14 init의 action·service·trigger·import 규칙
bootargs·bootconfig·property는 같은 저장소가 아닙니다
| 위치 | 읽는 쪽 | 예 |
|---|---|---|
| 커널 command line | 커널과 이를 참고하는 사용자 공간 | console=, root= 등 커널 파라미터 |
| bootconfig | 커널의 bootconfig 처리 및 Android init | Android 12 이후의 androidboot 관련 정보 전달 구성 |
| Android system property | property API를 사용하는 프로세스 | ro.boot.* 등 init이 부팅 정보를 반영한 속성 |
부트로더 변수 하나를 바꾸었다고 실행 중인 Android property가 즉시 바뀌는 것은 아닙니다. 부트로더가 실제 전달한 데이터, 커널이 받은 값, init이 만든 property를 순서대로 확인해야 합니다. 명령 줄과 bootconfig에 같은 의미의 값이 있으면 해당 버전의 init이 무엇을 읽는지도 확인합니다. AOSP bootconfig 전달
cat /proc/cmdline
cat /proc/bootconfig
getprop ro.boot.slot_suffix
getprop ro.boot.verifiedbootstate첫 두 명령은 커널이 노출한 부팅 정보를 읽고, 뒤 두 명령은 Android property를 읽습니다. /proc/bootconfig의 존재와 내용은 커널 설정·부팅 방식에 따라 달라집니다. 출력이 없다는 이유만으로 곧바로 부트로더 오류라고 단정하지 않습니다.
실패한 단계에서 증거를 찾습니다
| 관찰 | 우선 확인할 것 |
|---|---|
| 커널 첫 로그도 나오지 않습니다. | 부트로더의 검증 결과, 이미지 header와 적재 주소, DTB 선택, 콘솔 설정을 확인합니다. |
| 커널은 시작하지만 root를 못 찾습니다. | 초기 ramdisk·저장장치 드라이버·fstab·해당 slot의 파티션 구성을 확인합니다. |
| init은 실행됐지만 특정 서비스가 없습니다. | rc의 import·trigger·class·disabled 설정과 SELinux 거부를 확인합니다. |
| 예전 unpack 도구가 이미지를 읽지 못합니다. | 이미지 손상에 앞서 header v3/v4와 vendor ramdisk fragment를 지원하는 도구인지 확인합니다. |
오래된 LK/aboot의 boot image 분석은 그 구현을 이해하는 데 유효합니다. 그 구조를 최근 GKI 이미지의 전체 규칙으로 확장하지 않는 것이 핵심입니다.