Raspberry Pi 5에 간단한 Linux 시스템 올리기

이 포스팅에서는 Raspberry pi 5(RPi5)에 아주 단순한 리눅스 시스템을 구성해서 부팅해 보는 과정을 다룬다. Ubuntu 24.04 개발환경에서 RPi5를 위한 u-boot, Linux, Busybox를 설정하고 부팅해 볼 것이다.

SD card 준비

SD card를 개발 호스트 머신에 삽입하고 lsblk 명령어로 연결된 디바이스들을 확인한다.

위의 예제에서 SD card는 mmclbk0이다. 저장공간의 크기를 통해 구분하거나 SD card를 삽입할 때 커널 메세지를 잘 보고 엉뚱한 디바이스를 지정하지 않도록 주의하자 실수하면 의도치 않게 시스템 정보를 날려 먹을 수도 있다.

파티션 생성

parted 명령어로 파티션을 생성한다. 부팅만을 위해는 첫번째 파티션인 256MiB짜리 FAT32만 설정해도 된다. 이 공간에 부팅에 관련된 boot loader, kernel, RAM disk image를 넣어주게 된다.

# MBR 설정을 위한 msdos label을 생성
sudo parted /dev/mmcblk0 mklabel msdos

# 파티션 두개(boot / data)를 만든다. ext4는 부팅과는 상관 없다.
sudo parted -a optimal /dev/mmcblk0 mkpart primary fat32 1MiB 256MiB
sudo parted -a optimal /dev/mmcblk0 mkpart primary ext4 256MiB 100%

# 파일 시스템을 생성한다.
sudo mkfs.vfat /dev/mmcblk0p1
sudo mkfs.ext4 /dev/mmcblk0p2

Kernel – Linux v6.12.58

LTS 커널 중에 2025년 11월 현재 가장 최신 버전인 v6.12.58을 골랐다. 딱히 특정한 버전을 사용해야 하는 것은 아니므로 안정적이라고 알려진 버전 중에 아무것이나 고르면된다.

Source code

GitHub를 통해서 코드를 받거나 Kernel Archive에서 tarball을 받아도 되는데, GtiHub는 히스토리를 다운로드 받는 것 때문에 생각보다 시간이 좀 걸렸다.

git clone https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
cd linux
git checkout v6.12.58

Kernel Build

ARM64 CPU인 RPi5용 커널을 x86에서 빌드하기 위해서 cross compiler를 설치해야 한다.

sudo apt update
sudo apt install -y crossbuild-essential-arm64

Cross compile을 위해 ARCH와 CROSS_COMPILE 환경변수들을 아래와 같이 설정해 주고, make defconfig를 실행해서 .config 파일을 생성한다. 컴파일 타겟은 kernel image를 위한 Image, device tree blob을 위해 dtbs 그리고 kernel module들을 위한 modules를 지정해 주었다.

export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-

# Defconfig
make defconfig

# Compile
make -j `nproc` Image dtbs modules

빌드가 완료된 후에는 다음 두개의 파일이 잘 생성되어 있는지 확인한다.

# Linux kernel image
$ ls -l arch/arm64/boot/Image
-rw-rw-r-- 1 litcoder litcoder  arch/arm64/boot/Image

# BCM2712용 device tree blob
$ ls -l arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb
-rw-rw-r-- 1 litcoder litcoder  arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dtb

Boot loader – u-boot v2025.10

2025년 11월 현재 최신 버전인 tag v2025.10를 사용했다.

git clone https://github.com/u-boot/u-boot.git && cd $_
git checkout v2025.10

Compile

u-boot을 빌드하기 위해, 앞서 설정한 cross compiler외에도 파서 생성에 필요한 flex, bison과 GNU TLS를 위한 libgnutls28-dev를 설치해 주었다. 만약 24.04가 아닌 다른 버전을 사용하고 있다면 apt-cache search libgnutls 명령어로 대체 가능한 다른 패키지를 검색해 볼 수 있을 것이다.

sudo apt update
sudo apt install flex bison libgnutls28-dev

v2025.10 버전에서는 명시적으로 RPi5 이름이 붙은 defconfig 파일은 없고 대신에 rpi_arm64_defconfig를 사용하면 된다. ARCH와 CROSS_COMPILE 환경변수를 설정하고 컴파일한다.

export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-

# Defconfig PRi5
make rpi_arm64_defconfig

# Compile
make -j `nproc`

컴파일이 완료되면 아래와 같이 u-boot 관련 파일들이 생성되는데 이 중 u-boot.bin file이 생성된 부트로더 파일이다.

$ ls -l u-boot*
-rwxrwxr-x 1 litcoder litcoder  u-boot
-rw-rw-r-- 1 litcoder litcoder  u-boot-nodtb.bin
-rw-rw-r-- 1 litcoder litcoder  u-boot.bin # 부트로더 파일
-rw-rw-r-- 1 litcoder litcoder  u-boot.cfg
-rw-rw-r-- 1 litcoder litcoder  u-boot.dtb
-rw-rw-r-- 1 litcoder litcoder  u-boot.lds
-rw-rw-r-- 1 litcoder litcoder  u-boot.map
-rw-rw-r-- 1 litcoder litcoder  u-boot.srec
-rw-rw-r-- 1 litcoder litcoder  u-boot.sym

RootFS – Busybox 1_37_0

부트로더가 커널을 불러서 부팅까지 성공 했다면, 시스템 부팅의 후반 과정을 통해 필요한 데몬을 띄우거나 필요한 특수 파일 시스템을 구성하고 shell을 구동해서 명령어 입력이 가능한 상태로 만드는 일을 수행해야 하는데 이러한 정보를 담아두는 공간을 RootFS라고 한다. RootFS를 구성하는 여러가지 방법이 있으나, 여기에서는 가장 간단하게 Busybox를 이용해서 RAM disk image 형태로 만들어서 커널 부팅 이후의 과정을 수행하도록 한다.

Busybox git repository인 https://git.busybox.net/busybox 에서 필요한 버전을 tarball로 다운로드 받거나 git명령어로 받아서 소스 코드를 준비한다.

git clone https://git.busybox.net/busybox
cd busybox
git checkout 1_37_1

Compile

Cross compile을 위한 환경을 설정하고 make defconfig로 .config 파일을 생성한다.

export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-

make defconfig

생성된 .config 파일안에는 몇가지 설정이 있는데, 정적 링크를 위해 CONFIG_STATIC을 y로 설정해 주고 컴파일 오류를 방지 하기 위해 CONFIG_TC를 unset 해준다. 이 파일에서 보이듯이 기본 설치 디렉토리는 _install 디렉토리 이다.

# 생성된 .config 직접 편집
...
# not set -> y로 변경
CONFIG_STATIC=y
...
CONFIG_PREFIX="./_install"
...
# y -> not set으로 변경
#CONFIG_TC is not set

make oldconfig 후 컴파일 및 설치를 실행하면 _install directory안에 필요한 파일들이 설치된다.

make oldconfig
make -j `nproc`

# _install directory에 설치 파일 복사
# 주의: sudo를 쓰지 말것. 실수로 시스템이 망가지는 것을 막을 수 있음.
make install

RAM disk image 만들기

Busybox는 GNU coreutils처럼 기본적인 명령어들을 제공한다. 이러한 명령어들를 사용하기 위해서는 “busybox ls”와 같이 수행하고자 하는 명령어의 앞에 busybox를 입력해 주어야 하는데, /bin/sh가 /bin/busybox를 link하도록 하면 shell에 의해 자동적으로 이 부분이 수행 된다.

Linux kernel 부팅이 끝나고 나서 자동으로 init script가 불려지는 과정이 있는데, 이 내용을 포함한 RAM disk를 생성하는 과정을 아래와 같이 script로 만들어 두었다. 이 스크립트를 사용 하기 위해서는 위에서 설명한 busybox 관련 내용들을 make install까지 수행한 다음, export BUSYBOX_DIR=${PWD}로 환경변수를 설정해주고 스크립트를 수행하면 된다.

스크립트가 잘 수행되었다면 uInitrd 파일이 생성될 것이다.

설치 하기

RPi5의 ROM으 로드되면 FAT 파티션안에 있는 config.txt 파일의 내용을 읽어서 그 내용대로 수행해 준다. u-boot.bin 파일을 로드하기 위해 다음과 같이 config.txt file을 작성해 준다.

enable_uart=1
kernel=u-boot.bin
arm_64bit=1

bottfs라는 디렉토리를 하나 만들고 지금까지 생성한 모든 파일들을 한곳에 모아 둔다. 파일들의 내역은 다음과 같다.

$ ls -l ./bootfs
# 수동작성하는 설정파일
-rw-rw-r-- 1 litcoder litcoder  config.txt

# Kernel에서 복사
-rw-rw-r-- 1 litcoder litcoder  bcm2712-rpi-5-b.dtb
-rw-rw-r-- 1 litcoder litcoder  Image

# u-boot에서 복사
-rw-rw-r-- 1 litcoder litcoder  u-boot.bin

# Busybox에서 생성
-rw-rw-r-- 1 litcoder litcoder  uInitrd

SD card를 삽입하고 위의 파일들을 모두 첫번째 파티션인 FAT32로 복사해 준다.

mkdir -p ~/mnt
sudo mount /dev/mmcblk0p1 ~/mnt
sudo cp bootfs/* ~/mnt/
sudo umount ~/mnt

이제, SD card를 RPi5에 넣고 부팅을 시도하면 u-boot이 실행되고 부팅을 위한 카운트 다운이 실행되는데, 이 때 Enter key를 눌러서 u-boot> prompt를 띄운다.

printenv로 현재 환경변수들을 살펴보면 bcm2712-rpi-5-b.dtb의 경로가 잘못되어 있고, bootcmd가 설정되어 있지 않는 것을 볼 수 있다. 아래와 같이 설정해서 환경변수를 저장하면 이후로는 곧바로 부팅 할 수 있다.

setenv fdtfile bcm2712-rpi-5-b.dtb
setenv bootcmd "fatload mmc 0:1 ${kernel_addr_r} Image; fatload mmc 0:1 ${fdt_addr_r} ${fdtfile}; fatload mmc 0:1 ${ramdisk_addr_r} uInitrd; booti ${kernel_addr_r} ${ramdisk_addr_r} ${fdt_addr_r}"
saveenv

run bootcmd

참고로 변경한 u-boot 환경변수들을 모두 reset 하고 싶으면 아래의 명령어를 수행하면 된다.

env default -a
saveenv

부팅완료 후 root shell

SSH Permission denied (publickey)

주로 시스템을 설정하는 초기에 발생하는 문제인데 private key가 제대로 있고 file permission도 잘 설정 되어 있음에도 ssh 접속을 시도하면 권한 오류가 발생하는 경우가 있다.

$ ssh -T git@github.com
git@github.com: Permission denied (publickey). 

해결하는 방법은 사용하려는 private key를 ssh-add 명령어를 이용해서 ssh-agent에게 추가해 주는 것인데, 만약 ssh-agent가 동작하지 않는 상태라면 이 동작에도 오류가 발생한다.

$ ssh-add ~/.ssh/my_private_key 
Could not open a connection to your authentication agent.

이와 같은 인증 agent 관련한 문제가 생길 때는 ssh-agent를 실행해서 나오는 결과물을 화면에 붙여 넣으면 된다.

# SSH-agent를 실행하면 환경변수 값들이 화면에 출력된다.
$ ssh-agent
SSH_AUTH_SOCK=/tmp/ssh-GWQEJqNDZHsI/agent.3260; export SSH_AUTH_SOCK;
SSH_AGENT_PID=3261; export SSH_AGENT_PID;
echo Agent pid 3261;

# 이것들을 그대로 화면에 붙여넣고
$ SSH_AUTH_SOCK=/tmp/ssh-GWQEJqNDZHsI/agent.3260; export SSH_AUTH_SOCK;
SSH_AGENT_PID=3261; export SSH_AGENT_PID;
echo Agent pid 3261;
Agent pid 3261

# ssh-add를 시도한다.
$ ssh-add ~/.ssh/my_private_key 
Identity added: /home/litcoder/.ssh/my_private_key (/home/litcoder/.ssh/my_private_key)

그런데 복붙하는 건 너무 번거로우니까 eval command를 사용해서 ssh-agent의 결과물을 그대로 수행하도록 하면 복붙한 것과 동일한 효과를 낼 수 있다.

$ eval `ssh-agent`
Agent pid 4416

$ ssh-add ~/.ssh/my_private_key 
Identity added: /home/litcoder/.ssh/my_private_key (/home/litcoder/.ssh/my_private_key)

매번 로그인 할 때 마다 반복 하는 건 귀찮으니까 .bashrc 같은곳에 넣어두자.

#.bashrc
...
eval `ssh-agent`
ssh-add ~/.ssh/my_private_key

다시 로그인해서 시험해보면 permission error가 없이 잘 실행되는 걸 볼 수 있다.

$ ssh -T git@github.com
Hi litcoder! You've successfully authenticated, but GitHub does not provide shell access.

OpenCore Legacy Patcher – 최신 macOS 최신버전으로 올리기

오래된 나의 2016년생 Intel MacBook Pro는 2025년 11월 현재 Monterey에서 더 이상 OS 업그레이드가 지원 되지 않는다. 우연히 OCLP(OpenCore Legacy Patcher) project를 알게 되었는데 2020년에 시작된 이 프로젝트는 부팅 단계에서 최신 OS가 지원되는 하드웨어인것 처럼 macOS를 속여서 최신 버전의 OS를 설치할 수 있도록 해준다. 2025년 11월 현재 Intel CPU를 지원해주는 최신 버전인 Sequoia를 설치해 보고자 OCLP를 설치해 보았다.

공식 지원이 되지 않는 최신 OS를 굳이 설치 하려고 시도한 이유는 여러 응용프로그램에서 macOS 버전에 따라 설치가 되지 않는 경우가 있기 때문이었다.

예를 들면 MS Teams나 Homebrew 처럼…

OCLP를 설치하는 것은 How to install 문서에 잘 명시된 과정을 따라 하는 것으로 어렵지 않게 진행 할 수 있었다.

설치파일은 GitHub의 release page에서 다운로드 받을 수 있는데, OpenCore-Patcher.pkg를 받으면 되고, AutoPkg-Assets.pkg는 필요에 따라 자동으로 다운로드 되는 것이서 따로 다운로드 받을 필요가 없다.

설치 순서는 다음과 같이 진행한다.

  1. macOS Installer 생성
  2. OpenCore 빌드 및 설치
  3. Reboot 할 때 Option key를 눌러서 OpenCore로 진입
  4. 설치 후 과정(post-installation) 수행

3번을 실행하기 위해서는 부팅하는 동안 Option key는 누르고 있다가 부팅 선택화면에서 OpenCore를 선택해 준다. 설치 과정동안 서너번 정도 스스로 재부팅 하고 나서는 모든 설치 과정이 완료 되었다.

디스크 포맷을 수행 하지 않아서인지 부팅 후에는 이전에 사용하던 설정이 모두 보존 되어 있었다.

설치 가이드 문서에는 USB thumb drive없이 부팅하기 위한 안내가 있었는데, 그동안 수정된것인지 내 경우에는 이 과정이 없이도 잘 동작했다.

설치가 완료된 후 부팅 할 때마다 거슬려 보이는 OS 선택창(Boot Picker)이 있는데, 이것은 post-installation 문서에 명시된 다음의 순서대로 변경하면 없앨 수 있다.

Boot Picker 없애기

먼저 가장 아래에 있는 Settings 버튼을 눌러서 설정으로 진입한다.

Build 탭의 오른쪽에 있는 “Show OpenCore Boot Picker”를 선택해제하고 Return 버튼을 눌러서 나간 다음 “Build and Install OpenCore” 메뉴를 선택해서 빌드를 수행한다.

그리고 나서는 처음 OCLP을 설치할 때 처럼 하드디스크에 Boot picker가 제거된 새로운 버전 인스톨 해주면 이전의 부팅화면 처럼 Boot picker없이 실행된다.

Post-Install Root Patch

이제, post-install root patch 버튼을 눌러서 필요한 하드웨어 드라이버를 설치하면 모든 업그레이드 과정이 완료된다.

업그레이드 때문에 post-install root patch가 실패 한다면

OS 업그레이드에 대한 정보를 수신한 경우 이 때문에 업그레이드를 수행 하지 않아서 post-install root patch를 진행할 수 없다는 메세지가 뜨면서 진행이 멈추는데 이 때는 다음의 명령어서 관련 정보를 삭제한 후 리붓을 수행하면 진행 할 수 있다.

# Remove software update files
sudo rm -rf /System/Library/AssetsV2/com_apple_MobileAsset_MacSoftwareUpdate/*

# Remove Update files
sudo rm -f /System/Volumes/Update/Update.plist
sudo rm -f /System/Volumes/Update/Preflight.plist

# NOTE: 리붓 필수!!

OCPL를 통해서 하는 것이 아닌 직접 OS 업그레이드는 위험할 수 있으니 막아 두자.

Settings -> General -> Software Update -> Automatic updates

이제 MS teams도 설치하고 MacPorts에서 Homebrew로 돌아가야지.