U-Boot 부팅 시퀀스 완전 해부
임베디드 시스템에서 U-Boot는 커널이 실행되기까지 하드웨어를 단계적으로 초기화하며 시스템을 준비시키는 핵심 부트로더입니다. 특히 Rockchip RK3399과 같은 ARM 기반 SoC에서는 ROM → SPL → U-Boot → Kernel 형태의 다단계 부팅 구조를 사용합니다. 본 글에서는 각 단계에서 어떤 초기화가 수행되는지, U-Boot의 핵심 흐름(start.S → _main → board_init_f → board_init_r), 그리고 실제 부팅 로그를 기반으로 부팅 시퀀스를 어떻게 추적하는지까지 상세히 설명합니다.
1. 전체 부팅 시퀀스 개요
RK3399을 기준으로 한 전체 부팅 순서는 다음과 같습니다.
[ROM] → [SPL/TPL] → [U-Boot] → [Linux Kernel]각 단계는 다음과 같은 역할을 담당합니다.
● ROM(1st stage)
- SoC 내부 Mask-ROM에 저장된 부트 코드
- 부팅 가능한 스토리지(eMMC, SD, SPI-NOR 등) 검색
- SPL 또는 TPL 로드 후 실행
- 시리얼 로그 불가, 제조사에서 제공하는 고정 동작
● SPL / TPL (2nd stage)
- Small / Tiny Program Loader
- DRAM 초기화가 가장 큰 목적
- 실행 가능한 크기의 U-Boot 이미지를 DRAM으로 로드
- Clock, PMIC(전원관리), 초기 핀 설정 수행
● U-Boot(3rd stage)
- 콘솔 출력 가능
- 디바이스 드라이버 초기화 (MMC, USB, Ethernet 등)
- 환경 변수 로딩
- 부팅 커맨드 수행 (bootcmd)
- Kernel 및 DTB/Initrd 로드 후 Jump
● Linux Kernel(4th stage)
- U-Boot가 전달한 DTB 기반으로 디바이스 초기화
- rootfs 마운트 후 사용자 공간 시작
2. 단계별 초기화 과정
각 부팅 단계에서 무엇이 초기화되는지 좀 더 상세하게 정리하면 다음과 같습니다.
2.1 ROM 단계 초기화
- Boot Mode 핀 체크
- Boot Order(eMMC → SD → USB → NAND 등) 결정
- SPL/TPL 로드
ROM은 우리가 수정할 수 없으며 SoC 벤더가 고정해두는 단계입니다.
2.2 SPL/TPL 단계 초기화
RK3399은 DRAM 초기화를 위해 TPL(Trusted SPL)을 먼저 실행하는 경우가 많습니다.
초기화 항목은 다음과 같습니다.
- PLL/Clock 최소 설정
- PMIC 초기화(SCPI 통신 포함)
- DRAM Training 및 초기화
- Pinmux 기본 설정
- Stack/Heap 설정
- U-Boot 이미지 로드 후 Jump
예시 로그:
U-Boot TPL board init
rk3399 dram init start
rk3399 dram training success
Load U-Boot SPL from eMMC2.3 U-Boot 단계 초기화
U-Boot는 SPL을 통해 DRAM에서 실행되므로 상당히 많은 기능을 초기화합니다.
- 콘솔 초기화 (UART)
- Timer 초기화
- GPIO, I2C, SPI, MMC 등 드라이버 초기화
- 환경 변수(env) 로딩
- Storage(MMC/eMMC/NVMe) 초기화
- 네트워크 드라이버 초기화
- 부팅 장치 탐색
- bootcmd 실행
커널이 로드되기 전까지의 대부분의 하드웨어 초기화는 이 단계에서 완료됩니다.
3. U-Boot 코드 흐름 분석
U-Boot의 진입점은 arch/arm/cpu/armv8/start.S 입니다.
3.1 start.S
ARM64 U-Boot의 초기 진입점은 다음과 같습니다.
- MMU 비활성화 상태에서 실행
- Exception Level 정렬 (EL3 → EL2 → EL1)
- Stack Pointer 설정
- C 초기화 준비
_main함수 호출
start.S(요약):
bl save_boot_params
bl cpu_init
bl _main3.2 _main()
위 코드는 다음 파일에서 확인됩니다.
common/board_f.c_main 함수는 초기 함수(board_init_f)를 호출한 뒤, 메모리 재배치 후 board_init_r을 호출합니다.
흐름은 다음과 같습니다:
_main
├─ setup_reloc
├─ board_init_f() → 초기 하드웨어 설정
├─ relocate_code → U-Boot를 DRAM에 재배치
└─ board_init_r() → 전체 디바이스 초기화, Shell 실행3.3 board_init_f()
board_init_f는 최저 수준의 장치 초기화를 처리합니다.
- 기본 Clock 초기화
- UART 콘솔 초기화
- Timer 초기화
- DRAM이 이미 초기화되어 있음(SPL/TPL)
- 보드 정보 데이터 구조 설정
RK3399용 예제 코드(요약):
void board_init_f(ulong boot_flags)
{
/* UART 초기화 */
board_early_uart_init();
/* 시스템 클록 설정 */
clk_set_defaults();
/* 시스템 타이머 */
timer_init();
}3.4 board_init_r()
이 함수는 DRAM에 재배치된 이후 실행되므로 가능한 모든 초기화가 수행됩니다.
- MMC/eMMC 드라이버 초기화
- USB, Ethernet 등 주변 장치 초기화
- 환경 변수 로딩
- Boot Device 탐색 및 Kernel 로드
board_init_r 흐름 예시:
board_init_r
├─ dm_init_and_scan
├─ load_env
├─ init_mmc
├─ init_usb
├─ run_command_list(bootcmd)4. RK3399 부팅 로그 기반 분석
아래는 실제 RK3399 U-Boot 부팅 로그를 단순화하여 예시로 만든 것입니다.
U-Boot TPL 2023.07 (RK3399)
DRAM init success
Load SPL
U-Boot SPL 2023.07
Trying to boot from eMMC
Load u-boot.itb OK
U-Boot 2023.07 (rk3399)
CPU: rk3399
Model: Rockchip RK3399 Board
DRAM: 3 GiB
MMC: mmc0(eMMC)
In: serial
Out: serial
Err: serial
Net: eth0
Hit any key to stop autoboot: 0
Booting kernel from eMMC
Loading Image...
Loading rk3399.dtb...이 로그를 기반으로 분석하면 다음과 같은 흐름이 보입니다.
- TPL 실행 및 DRAM 초기화 성공 → SPL로 점프
- SPL이 eMMC에서 U-Boot 이미지 로딩 → U-Boot 본체 실행
- U-Boot가 주변장치 초기화(MMC, UART, Ethernet) 수행
- autoboot 타이머 후 커널 로드 및 실행
이 과정은 U-Boot의 단계적 초기화 흐름을 그대로 보여주는 대표적인 예입니다.
5. 결론 요약
본 글에서 정리한 내용을 다시 한 번 요약하면 다음과 같습니다.
✔ “U-Boot는 단계별로 하드웨어를 깨우며 부팅한다.”
- ROM은 스토리지에서 SPL을 찾는 역할만 수행한다.
- SPL/TPL은 전원 및 DRAM 초기화를 주로 담당한다.
- U-Boot는 콘솔/스토리지/네트워크 등 다양한 디바이스를 활성화한다.
- 최종적으로 Kernel을 DRAM으로 로드하고 Jump하여 시스템을 OS 수준으로 넘긴다.
U-Boot는 단순한 부트로더가 아니라 하드웨어를 단계별로 깨워서 커널이 실행될 준비를 완성하는 핵심 구성 요소입니다.
앞으로는 각 단계별 코드 분석, RK3399 특화 설정, 그리고 U-Boot 디바이스 드라이버 포팅 방법에 대해 추가로 다뤄 보겠습니다.
'u-boot' 카테고리의 다른 글
| U-Boot 드라이버 구조와 포팅 방법 (0) | 2025.12.05 |
|---|---|
| U-Boot 빌드 및 보드 포팅 준비 (0) | 2025.12.03 |
| U-Boot 소스코드 구조 분석 – RK3399 기반으로 이해하기 (0) | 2025.12.02 |
| U-Boot란 무엇인가? (0) | 2025.12.01 |