U-Boot 포팅 (1. U-Boot 개요 및 기본 개념 / U-Boot의 구조)

2025. 2. 26. 12:25프로그래밍/시스템

U-Boot의 구조

U-Boot는 임베디드 시스템에서 운영체제를 실행하기 전에 하드웨어를 초기화하고 커널을 로드하는 부트로더입니다.
이 과정에서 U-Boot는 크게 두 단계로 동작합니다.

  1. 1차 부트로더(SPL, Secondary Program Loader)
    • 부팅 시 가장 먼저 실행되는 코드로, 기본적인 하드웨어 초기화를 수행합니다.
    • 보드의 저장장치에서 2차 부트로더(U-Boot 메인 바이너리)를 로드하는 역할을 합니다.
  2. 2차 부트로더(U-Boot 메인 바이너리)
    • SPL이 실행한 후, 본격적으로 U-Boot가 실행됩니다.
    • 커널을 메모리에 로드하고 실행하며, 네트워크 부팅, 환경 변수 관리, 디바이스 트리 로드 등의 기능을 수행합니다.

이 외에도 환경 변수(env) 시스템을 활용하여, 부팅 설정을 유연하게 변경할 수 있습니다.


1. 1차 부트로더(SPL, Secondary Program Loader)

SPL이란?

  • SPL(Secondary Program Loader)은 U-Boot의 축소된 버전으로, 1차 부트로더 역할을 수행합니다.
  • 일부 SoC(System on Chip)에서는 부팅 시 ROM 코드가 실행되는데, 이때 SPL을 로드하여 실행합니다.
  • 목적: RAM이 아직 초기화되지 않은 상태에서 최소한의 하드웨어를 설정하고, 2차 부트로더(U-Boot 본체)를 RAM에 로드하는 역할을 합니다.

SPL의 주요 기능

CPU 및 클럭 설정
RAM(DDR) 초기화
스토리지(NAND, eMMC, SD 카드)에서 U-Boot 본체 로드
부트 미디어 탐색 및 선택

SPL 실행 과정

  1. ROM 코드 실행 후, SPL이 저장된 위치에서 로드됨.
  2. SPL이 실행되며 CPU, 클럭, RAM을 초기화.
  3. NAND, SD, eMMC 등의 저장장치에서 2차 부트로더(U-Boot 본체)를 로드.
  4. SPL이 2차 부트로더(U-Boot)를 실행.

📌 예제: SPL에서 RAM을 초기화하는 코드 (arch/arm/mach-/spl.c)

void board_init_f(ulong dummy)
{
    /* RAM 초기화 */
    dram_init();
    
    /* U-Boot 본체 로드 */
    spl_load_uboot();
}

SPL 빌드 결과물

SPL 빌드를 수행하면 보드의 설정에 따라 다음과 같은 파일이 생성됩니다.

파일명  설명
SPL 1차 부트로더 바이너리
MLO TI 계열 SoC에서 사용되는 SPL
u-boot-spl.bin SPL의 실행 바이너리

2. 2차 부트로더(U-Boot 메인 바이너리)

SPL이 실행한 후, 2차 부트로더(U-Boot 본체)가 실행됩니다.
이 단계에서 본격적으로 운영체제(OS) 로딩 및 실행이 수행됩니다.

U-Boot의 주요 기능

환경 변수 관리 (env 변수 활용)
커널 및 디바이스 트리 로드 및 실행
네트워크 부팅 (TFTP, PXE, NFS)
부팅 미디어(SD, eMMC, NAND)에서 OS 로드
파일 시스템(ext4, FAT, UBIFS) 지원
커맨드 라인 인터페이스(CLI) 제공

U-Boot 실행 과정

  1. SPL이 U-Boot 본체를 RAM에 로드하고 실행.
  2. U-Boot가 환경 변수를 불러오고 기본 하드웨어 설정 수행.
  3. U-Boot CLI(Command Line Interface) 또는 자동 부팅 명령 실행.
  4. OS 커널과 디바이스 트리를 메모리에 로드.
  5. OS 실행 (bootm, bootz 명령어 활용).

📌 예제: U-Boot에서 커널 실행

setenv bootargs console=ttyS0,115200 root=/dev/mmcblk0p2 rw
fatload mmc 0:1 0x82000000 zImage
bootz 0x82000000

U-Boot 빌드 결과물

U-Boot를 빌드하면 다음과 같은 실행 파일이 생성됩니다.

파일명 설명
u-boot.bin U-Boot의 기본 실행 바이너리
u-boot.img U-Boot의 이미지 파일
u-boot.elf 디버깅 가능한 U-Boot ELF 바이너리
u-boot-dtb.bin 디바이스 트리가 포함된 U-Boot

3. U-Boot 환경 변수 (env 변수의 역할과 저장 방식)

U-Boot는 환경 변수(Environment Variable)를 사용하여 부팅 설정을 관리합니다.
환경 변수는 플래시 메모리(eMMC, NAND, SD)에 저장되거나 RAM에서 임시로 사용할 수 있습니다.

환경 변수의 역할

부팅 과정 설정 (bootcmd, bootargs)
네트워크 설정 (ipaddr, serverip)
저장 장치 설정 (rootfs 위치 지정)

환경 변수 명령어

명령어  설명
printenv 현재 환경 변수 출력
setenv <변수> <값> 환경 변수 설정
saveenv 환경 변수 저장
fw_printenv 환경 변수 파일에서 값 읽기
fw_setenv 환경 변수 파일에서 값 설정

📌 예제: U-Boot 환경 변수 설정

setenv bootcmd 'tftp 0x82000000 zImage; bootz 0x82000000'
saveenv

4. 주요 디렉토리 및 파일 구조 분석

U-Boot 소스코드는 여러 디렉토리로 구성되어 있으며, 각각 특정 역할을 담당합니다.

디렉토리  설명
arch/ 아키텍처별 코드 (ARM, x86, RISC-V 등)
board/ 특정 보드별 코드
configs/ 보드별 기본 설정 파일 (*_defconfig)
include/ U-Boot 헤더 파일
common/ 공통 기능 코드 (환경 변수, 명령어 등)
drivers/ 하드웨어 드라이버 코드
fs/ 파일 시스템(ext4, FAT 등) 코드
net/ 네트워크 관련 코드
tools/ U-Boot 유틸리티 프로그램

📌 예제: 새로운 보드 추가하기

  1. board/<새로운 보드>/ 디렉토리 생성
  2. configs/<새로운 보드>_defconfig 파일 생성
  3. arch/arm/dts/ 디렉토리에 dts 파일 추가
  4. Makefile 및 Kconfig 수정하여 보드 인식

📌 정리

U-Boot는 SPL(1차 부트로더)과 U-Boot 본체(2차 부트로더)로 구성됨
SPL은 RAM을 초기화하고 2차 부트로더를 로드하는 역할을 수행
U-Boot 본체는 환경 변수를 관리하고 OS를 로드 및 실행하는 역할을 수행
환경 변수(bootcmd, bootargs 등)를 활용하여 부팅 과정을 유연하게 설정 가능
U-Boot의 소스코드는 아키텍처, 보드, 드라이버, 네트워크, 파일 시스템 등으로 구성됨