u-boot

U-Boot에서 커널 및 루트파일시스템 로딩 (RK3399 기준)

임베디드 친구 2025. 12. 9. 20:20
반응형

U-Boot에서 커널 및 루트파일시스템 로딩 (RK3399 기준)

1. 개요

U-Boot는 Embedded Linux 시스템에서 가장 먼저 실행되는 부트로더이며, 하드웨어 초기화부터 커널과 루트파일시스템(RootFS) 로딩까지 전체 부팅 과정의 핵심적인 역할을 맡습니다. 본 글에서는 Rockchip RK3399 기반 보드를 기준으로 U-Boot가 커널(zImage, uImage, fitImage)과 RootFS를 어떻게 로딩하고, 어떤 방식으로 커널 커맨드라인을 전달하며, SD/eMMC/NAND/네트워크(TFTP) 부팅 설정을 통해 실제 리눅스 커널을 기동하는지 로그 분석과 함께 정리합니다.

글의 마지막에는 “U-Boot의 마지막 임무는 커널을 안전하게 넘겨주는 것이다”라는 결론으로 내용을 정리합니다.


2. U-Boot에서 커널 이미지 로딩 방식

RK3399과 같은 ARMv8 기반 SoC는 여러 형식의 커널 이미지를 지원합니다. 각각의 특징과 실제 U-Boot 명령 예제를 통해 살펴봅니다.

2.1 zImage

zImage는 압축된 커널 이미지로, 대부분의 ARM64 플랫폼에서 사용됩니다. 압축 해제는 커널 내부에서 수행하며, U-Boot는 단순히 메모리에 로드만 하면 됩니다.

로드 예제 (eMMC):

load mmc 1:1 0x02000000 Image

2.2 uImage

uImage는 U-Boot의 mkimage 도구로 패킹한 커널 이미지로, U-Boot 헤더가 포함되어 있어 U-Boot가 이미지의 종류, 아키텍처, 로딩 주소 등을 판별할 수 있습니다.

로드 예제:

load mmc 1:1 0x02000000 uImage
bootm 0x02000000

2.3 FIT Image (fitImage)

최근 Embedded Linux에서는 fitImage 형태가 널리 사용됩니다. DTB(Device Tree), 커널, RAMDisk를 하나의 이미지로 묶어 보안 부팅(Verified Boot) 구성에도 적합한 형태입니다.

FIT 이미지 로딩 및 부팅 예제:

load mmc 1:1 0x02000000 fitImage
bootm 0x02000000

FIT Image는 아래와 같은 구조를 가집니다.

images {
  kernel@1 {
    data = ...;
    type = "kernel";
    arch = "arm64";
  };
  fdt@1 {
    data = ...;
  };
  ramdisk@1 {
    data = ...;
  };
};

3. RootFS 마운트 및 커맨드라인 전달

커널이 RootFS를 마운트하기 위해서는 U-Boot가 올바른 커맨드라인을 설정해 주어야 합니다. 이 문자열은 bootargs 환경 변수에 저장됩니다.

3.1 bootargs 설정 예제

아래는 RK3399에서 eMMC RootFS를 사용하기 위한 예제입니다.

setenv bootargs "console=ttyFIQ0,1500000 root=/dev/mmcblk1p7 rw rootwait"

Network RootFS를 사용하는 예:

setenv bootargs "console=ttyFIQ0,1500000 root=/dev/nfs nfsroot=192.168.0.10:/nfsroot,v3 ip=dhcp"

bootargs는 최종적으로 커널의 /proc/cmdline 에서 확인할 수 있습니다.

3.2 DTB 전달

U-Boot는 DTB 파일(dtb)을 특정 주소에 로딩한 후 booti 또는 bootm 시 커널에 함께 전달합니다.

예제:

load mmc 1:1 0x01f00000 rk3399-board.dtb
booti 0x02000000 - 0x01f00000

4. 다양한 저장장치별 부팅 설정

4.1 SD 카드 부팅

setenv devnum 0
setenv loadcmd "load mmc ${devnum}:1"
setenv image Image
${loadcmd} 0x02000000 ${image}
${loadcmd} 0x01f00000 rk3399.dtb
booti 0x02000000 - 0x01f00000

4.2 eMMC 부팅

setenv devnum 1
load mmc 1:1 0x02000000 Image
load mmc 1:1 0x01f00000 rk3399.dtb
booti 0x02000000 - 0x01f00000

4.3 NAND 부팅

NAND Flash를 사용하는 경우에는 MTD 파티션을 설정해 두고 아래와 같이 이미지 로딩이 가능합니다.

nand read 0x02000000 kernel
nand read 0x01f00000 dtb
booti 0x02000000 - 0x01f00000

4.4 네트워크(TFTP) 부팅

개발 환경에서 가장 많이 사용하는 방식입니다.

setenv serverip 192.168.0.10
setenv ipaddr 192.168.0.20

tftp 0x02000000 Image
tftp 0x01f00000 rk3399.dtb
booti 0x02000000 - 0x01f00000

RAMDisk를 함께 보내는 경우:

tftp 0x03000000 ramdisk.img
booti 0x02000000 0x03000000 0x01f00000

5. 실제 커널 부팅까지의 로그 분석

아래는 RK3399 시스템에서 booti로 커널을 부팅할 때 나타나는 로그 예시입니다.

Booting Linux on physical CPU 0x0
Linux version 5.10.110 (gcc version 10.2.1)
Machine model: RK3399 Custom Board
efi: UEFI not found.
OF: fdt: Ignoring memory range 0x0 - 0x100000

devtmpfs: initialized
Freeing unused kernel memory: 448K
Run /init as init process
EXT4-fs (mmcblk1p7): mounted filesystem with ordered data mode
Starting syslogd: OK
Starting network: OK

로그는 크게 다음 단계를 의미합니다.

  1. 커널이 실행되었으며 CPU 초기화
  2. Device Tree 적용
  3. 드라이버 초기화(devtmpfs 등)
  4. RootFS 마운트
  5. init 프로세스 실행 → 사용자 공간 시작

특히 RootFS 마운트 구문은 bootargs 설정이 올바른지 검증하는 핵심 지점입니다.


6. 정리: U-Boot의 마지막 임무

U-Boot의 역할은 매우 크지만, 결국 다음 한 가지로 요약됩니다.

“U-Boot의 마지막 임무는 커널을 안전하게 넘겨주는 것이다.”

이를 위해 U-Boot는

  • 하드웨어 초기화
  • 커널/DTB/Ramdisk 로딩
  • 커맨드라인 전달
  • 저장장치 및 네트워크 부팅 환경 구성
    을 수행합니다.

RK3399과 같은 ARM 보드에서 U-Boot는 매우 중요한 구성 요소이며, 이를 이해하면 전체 Embedded Linux 시스템의 동작을 보다 깊이 있게 파악할 수 있습니다.

이상으로 U-Boot에서 커널과 RootFS를 로딩하고 리눅스 커널까지 부팅되는 전체 흐름을 정리했습니다.

반응형