임베디드를 좋아하는 조금 특이한 개발자?

[Buildroot] 라즈베리파이4 U-boot 부트로더 설정 본문

Embedded/Buildroot

[Buildroot] 라즈베리파이4 U-boot 부트로더 설정

Gordon_ 2026. 6. 12. 23:10
반응형

- 개발 환경

개발 보드 : Raspberrypi 4

WSL2 (Ubuntu 24.04 LTS)

buildroot(2024.02)

- 소스 코드

https://github.com/MainForm/rpi4_debug_linux_with_JTAG_with_UBOOT

 

GitHub - MainForm/rpi4_debug_linux_with_JTAG_with_UBOOT

Contribute to MainForm/rpi4_debug_linux_with_JTAG_with_UBOOT development by creating an account on GitHub.

github.com

 위 소스코드는 아래 포스트를 기준으로 구성되어 있습니다.

https://littlebitodd-developer.tistory.com/57

 

[Buildroot] Github로 관리하기 위한 개발 환경 구축

- 개발 환경개발 보드 : Raspberrypi 4WSL2 (Ubuntu 22.04 LTS)buildroot(2024.02)1. 서론 Buildroot를 이용하여 개발하다 보면 Buildroot 내에 이미 개발보드나 패키지들이 많이 정의되어 있어 추가적인 개발보드나 패

littlebitodd-developer.tistory.com

 


1. 서론

  U-boot는 임베디드 환경에서 가장 많이 쓰이는 부트로더라고 생각합니다. Buildroot의 기본 설정은 따로 부트로더가 없지만 U-boot을 추가할 수 있습니다. U-boot을 사용하면 많은 것들을 할 수 있습니다. 

  • 리눅스 부팅 인자 설정
  • 다중 OS 부팅
  • NFS rootfs 부팅
  • OS 업데이트 기능 추가

  하지만 실제로 U-boot를 buildroot에 추가하는 방법은 쉽지 않습니다. 이번 포스트에서는 Buildroot에서 U-boot을 추가하는 방법을 알아보고 실제 Linux까지 부팅해보도록 하겠습니다.

 

2. Board 폴더 내 파일 수정

Board 폴더는 개발 환경에 따라 디렉토리 위치가 다를 수 있습니다. 그러므로 반드시 정확한 Board 위치를 확인해야합니다.

- 기본 Board 폴더 위치

./board/raspberrypi4-64

 

2.1. cmdline.txt 파일

root=/dev/mmcblk0p2 rootwait console=tty1 console=serial0,115200

 

ttyAMA0 -> serial0 로 변경해야 U-boot에서 serial0 으로 terminal을 사용할 수 있습니다.

 

2.2. config_4_64bit.txt 파일

# Please note that this is only a sample, we recommend you to change it to fit
# your needs.
# You should override this file using BR2_PACKAGE_RPI_FIRMWARE_CONFIG_FILE.
# See http://buildroot.org/manual.html#rootfs-custom
# and http://elinux.org/RPiconfig for a description of config.txt syntax

start_file=start4.elf
fixup_file=fixup4.dat

# kernel=Image
kernel=u-boot.bin

# To use an external initramfs file
#initramfs rootfs.cpio.gz

# Disable overscan assuming the display supports displaying the full resolution
# If the text shown on the screen disappears off the edge, comment this out
disable_overscan=1

# How much memory in MB to assign to the GPU on Pi models having
# 256, 512 or 1024 MB total memory
gpu_mem_256=100
gpu_mem_512=100
gpu_mem_1024=100

# fixes rpi (3B, 3B+, 3A+, 4B and Zero W) ttyAMA0 serial console
# dtoverlay=miniuart-bt
dtoverlay=disable-bt
enable_uart=1

# enable autoprobing of Bluetooth driver without need of hciattach/btattach
dtparam=krnbt=on

# enable 64bits support
arm_64bit=1

 

여기서는 크게 2가지를 변경하였습니다.

# kernel=Image
kernel=u-boot.bin

 

먼저 kernel 파일을 u-boot.bin으로 변경하여 처음 보드가 부팅 할 파일을 Linux가 아닌 u-boot으로 설정하였습니다.

 

# fixes rpi (3B, 3B+, 3A+, 4B and Zero W) ttyAMA0 serial console
# dtoverlay=miniuart-bt
dtoverlay=disable-bt
enable_uart=1

 

그리고 enable_uart=1로 하여 serial를 enable 하였습니다.

 

2.3.post-image.sh 파일

#!/bin/bash

set -e

BOARD_DIR="$(dirname $0)"
BOARD_NAME="$(basename ${BOARD_DIR})"
GENIMAGE_CFG="${BOARD_DIR}/genimage-${BOARD_NAME}.cfg"
GENIMAGE_TMP="${BUILD_DIR}/genimage.tmp"

# generate genimage from template if a board specific variant doesn't exists
if [ ! -e "${GENIMAGE_CFG}" ]; then
	GENIMAGE_CFG="${BINARIES_DIR}/genimage.cfg"
	FILES=()

	for i in "${BINARIES_DIR}"/*.dtb "${BINARIES_DIR}"/rpi-firmware/*; do
		FILES+=( "${i#${BINARIES_DIR}/}" )
	done

	KERNEL=$(sed -n 's/^kernel=//p' "${BINARIES_DIR}/rpi-firmware/config.txt")
	FILES+=( "${KERNEL}" )
	
	FILES+=( "Image" )

	BOOT_FILES=$(printf '\\t\\t\\t"%s",\\n' "${FILES[@]}")
	sed "s|#BOOT_FILES#|${BOOT_FILES}|" "${BOARD_DIR}/genimage.cfg.in" \
		> "${GENIMAGE_CFG}"
fi

# Pass an empty rootpath. genimage makes a full copy of the given rootpath to
# ${GENIMAGE_TMP}/root so passing TARGET_DIR would be a waste of time and disk
# space. We don't rely on genimage to build the rootfs image, just to insert a
# pre-built one in the disk image.

trap 'rm -rf "${ROOTPATH_TMP}"' EXIT
ROOTPATH_TMP="$(mktemp -d)"

rm -rf "${GENIMAGE_TMP}"

genimage \
	--rootpath "${ROOTPATH_TMP}"   \
	--tmppath "${GENIMAGE_TMP}"    \
	--inputpath "${BINARIES_DIR}"  \
	--outputpath "${BINARIES_DIR}" \
	--config "${GENIMAGE_CFG}"

exit $?

 

해당파일은 image 파일내 구성을 만드는 파일입니다.

여기서 중요한 것은 "config_4_64bit.txt" 파일을 읽어 필요한 파일을 자동적으로 image에 추가해주는 것입니다.

근데 저희는 u-boot로 부팅하기 위해 config_4_64bit.txt에서 kernel=image를 주석 처리하여 리눅스가 image에 포함되지 않는 문제가 발생합니다. 그러므로 우리가 직접 설정하여 추가해주어야합니다.

 

	KERNEL=$(sed -n 's/^kernel=//p' "${BINARIES_DIR}/rpi-firmware/config.txt")
	FILES+=( "${KERNEL}" )
	# 직접 Image 파일을 추가
	FILES+=( "Image" )

 

2.4.uboot.fragment 파일

CONFIG_BOOTCOMMAND="setenv bootargs root=/dev/mmcblk0p2 rootwait console=tty1 console=ttyAMA0,115200 earlycon=pl011,mmio32,0xfe201000 loglevel=8; fatload mmc 0:1 ${kernel_addr_r} Image; booti ${kernel_addr_r} - ${fdt_addr}"

 

uboot에 자동적으로 입력되는 명령어입니다. 해당 명령어를 통해 우리가 굳이 u-boot 명령어를 입력하지 않아도 자동적으로 u-boot에서 Linux로 부팅이 가능합니다.

 

3. menuconfig 설정

 

여기서 몇가지 중요한 설정만 확인하겠습니다.

 

3.1. Board defconfig 설정

 

Board defconfig는 u-boot 내 config 설정을 위한 파일을 설정하는 것입니다.

직접 u-boot에 대한 파일 위치를 넣어도 괜찮지만, 만약 github에 이미 설정된 config를 사용할 경우 "_defconfig"를 제외한 나머지 이름을 넣으면 됩니다.

 

3.1. Additional configuration fragment files 설정

 

uboot.fragment 의 파일 위치를 설정합니다.

 

4. 결론

  이 것으로 모든 u-boot 사용을 위한 buildroot 설정은 끝났습니다. 이제 image를 sd카드에 적용하여 부팅한다면 u-boot가 잘 나오는 것을 확인 할 수 있을 것입니다. 저는 단순히 u-boot을 사용하기 위해서가 아닌 라즈베리파이4를 디버깅하기 위해서 사용했지만,  Yocto에서 U-boot를 설정하는 것보다 너무 어렵고 정확하게 설정하는 글이 나오지 않아 꽤 애를 먹었습니다.

반응형