
이전에는 buildroot 으로 rootfs 를 만들어 QEMU 로 커널을 디버깅했다. 하지만 커널 디버깅만 하기에 buildroot 는 너무 무겁다. (빌드도 오래 걸리고 부팅 시간도 길다.) 따라서 이번에는 busybox 를 통해 minimal 한 rootfs 를 구성한 뒤, 이를 QEMU 로 디버깅 해볼 것이다.
busybox 다운로드 받기
https://busybox.net/downloads/?C=M;O=D
위 링크로 들어가면 busybox 를 다운로드 받을 수 있다. 필자는 Last modified 로 정렬해서 (글을 작성하는 시점인 25년 07월 05일 기준) 가장 최신 버전인 busybox-1.37.0.tar.bz2 를 다운로드 받았다.

wget https://busybox.net/downloads/busybox-1.37.0.tar.bz2
tar -xf busybox-1.37.0.tar.bz2
rm busybox-1.37.0.tar.bz2
mv busybox-1.37.0 busybox
압축을 풀고 압축파일을 삭제하였다.
sysroot) 필자는 arm64 커널을 디버깅 할 예정이기 때문에 rootfs 의 바이너리도 aarch64 로 빌드해야 한다. 필자의 호스트 머신은 x86_64 이므로 크로스 컴파일이 필요하다. 여기서부터는 배포판마다 진행 과정이 약간씩은 다를 수 있으나 큰 줄기는 같다. 필자는 Fedora Linux 42 (Workstation Edition) x86_64 를 기준으로 서술한다.
sudo dnf install gcc-aarch64-linux-gnu gcc-c++-aarch64-linux-gnu
sudo dnf install binutils-aarch64-linux-gnu
sudo dnf install sysroot-aarch64-fc42-glibc
busybox 를 빌드하기 위해선 sysroot 패키지가 필요한데 여기에서 sysroot 이란, 크로스 컴파일 툴체인이 default 로 인식하는 header 와 library 의 논리적인 root directory 를 의미한다. (출처: https://gcc.gnu.org/onlinedocs/gcc/Directory-Options.html)

Fedora 의 경우, aarch64-linux-gnu 가 aarch64-redhat-linux 의 경로와 통합되어 있지 않기 때문에 직접 sys-root 을 이어줘야 한다. 어찌보면 이러한 패키지 디렉토리 구조가 sysroot 의 취지에 잘 들어맞는다고 볼 수도 있다.
ln -s /usr/aarch64-redhat-linux/sys-root/fc42/usr /usr/aarch64-redhat-linux/sys-root/usr
ln -s /usr/aarch64-redhat-linux/sys-root /usr/aarch64-linux-gnu/sys-root
mkdir build
make O=build/ ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- defconfig
우선 defconfig 명령어를 입력하고 몇 가지 에러를 수정해야 한다. 가장 먼저 해야 하는 일은 menuconfig 에서 발생하는 버그를 수정하는 것이다.

이것은 ncurses-devel 패키지를 설치해도 발생하는 문제로 scripts/kconfig/lxdialog/check-lxdialog.sh 라는 쉘 스크립트의 내용을 수정해야 해결할 수 있다. 50번째 라인을 아래와 같이 수정한다:

make O=build/ ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- menuconfig
수정한 뒤에 menuconfig 을 입력하면 정상적으로 다이얼로그가 나오는 것을 확인할 수 있다.

그 다음으로 할 일은 몇 가지 설정을 변경하는 것이다:
Networking Utilities -> tc [ ]Settings -> Build static binary (no shared libs) [*]Settings -> SHA1 [ ] : Use hardware accelerated instructions if possibleSettings -> SHA256 [ ] : Use hardware accelerated instructions if possible다음과 같이 언/체크한다.

networking/tls_aesgcm.c 파일에 9~11 번 라인을 추가로 작성해준다. LONG_BIT 가 정의되지 않아서 발생하는 문제인데 그냥 직접 정의해도 별 문제 없다.
rootfs 생성
make O=build/ ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-
경고가 조금 발생하긴 하지만 빌드는 문제없이 잘 된다. 이제 make install 을 통해 rootfs 를 생성하면 된다.

make O=build/ ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- CONFIG_PREFIX=install/ install
이제 build/install 디렉토리로 들어가면 bin, linuxrc, sbin, usr 디렉토리를 확인할 수 있다.

initramfs 만들기이제 이 rootfs 에 몇 가지 파일과 디렉토리를 추가해볼 것이다.
mkdir proc sys dev etc etc/init.d
ln -s bin/busybox init
touch etc/init.d/rcS
chmod +x etc/init.d/rcS
etc/init.d/rcS 파일의 내용을 이하와 같이 구성한다:
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
mount -t debugfs none /sys/kernel/debug
exec /bin/sh

최종적으로 다음과 같이 구성하면 끝난다. 이제 이 파일들을 그러모아서 하나의 initramfs 파일을 만들면 된다.
find . | cpio -o -H newc | gzip > ../../initramfs.cpio.gz
QEMU 로 실행하기
qemu-system-aarch64 -M virt -cpu cortex-a57 -kernel <Image> -nographic -initrd <initramfs.cpio.gz>
끝!