主に以下の流れで作成する。

  1. Linux Kernelのイメージのインストール
  2. rootfsの作成
  3. QEMUでのテスト
  4. USBメモリへのインストール

Linux Kernelのビルド

https://kernel.org/ からインストールする。インストールしたバージョンは6.19.11。

Macのアーキテクチャはx86_64では無いのでDockerを使用してビルドする。Dockerコマンドを実行するディレクトリに、ダウンロードしてきたLinuxの .tar.gz ファイルを配置する。

docker volume create linux-build
docker run -it -v linux-build:/work ubuntu:24.04

コンテナ内でビルドツールをインストールする。

apt update
apt install -y build-essential flex bison bc libelf-dev libssl-dev wget

カーネルをインストールして、ビルドする。

cd /work
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.19.11.tar.xz
tar xf linux-6.19.11.tar.xz
cd linux-6.19.11

make defconfig
make -j4

BusyBoxのビルド

BusyBoxの1.36.1をビルドする。

先程のDockerコンテナに入り、ビルドツールをインストールする。

apt update
apt install -y build-essential flex bison bc libelf-dev libssl-dev wget cpio

BusyBox(1.36.1)をインストールする。

cd /work
wget https://busybox.net/downloads/busybox-1.36.1.tar.bz2
tar xf busybox-1.36.1.tar.bz2
cd busybox-1.36.1

設定でライブラリを静的リンクにする設定をした後に、ビルドをする。

make defconfig // 初期設定にする

apt install libncurses5-dev libncursesw5-dev // curses.hのインストール

// 設定画面に移行する
// Settings -> Build static binaryにチェック
// Networking Utilities -> tcのチェックを外す
make menuconfig

make install -j4

起動後ルートファイルシステムになるファイルを作成する

cd _install
find . | cpio -o --format=newc > ../rootfs.img

QEMUでのテスト

Dockerコンテナ内でビルドした2つのファイルをローカルにコピーする。

docker cp <コンテナ名>:/work/linux-6.19.11/arch/x86/boot/bzImage ./bzImage
docker cp <コンテナ名>:/work/busybox-1.36.1/rootfs.img ./rootfs.img

以下のコマンドを実行することで、Linux Kernel + BusyBoxの環境にアクセスできる。

qemu-system-x86_64 -kernel bzImage -initrd rootfs.img -append "root=/dev/ram rdinit=/bin/sh"

USBメモリへのインストール

パーティションの作成

UbuntuにUSBを指して、lsblk コマンドを使用した後に出た出力で USB と思われるドライブのパスを調べる。 私の場合は、sda というディスクの中に sda1 というパーティションがあることが分かった。

sda           8:0    1   7.5G  0 disk
└─sda1        8:1    1   7.5G  0 part /media/totosuki/09D4-6C68

USBメモリのパーティションがマウントされている場合は、アンマウントする。

sudo umount /dev/sda1

fdisk コマンドを使用してインタプリタ的に、パーティションを作成する。

sudo fdisk /dev/sda

// 以下の順に設定を行っていく
g # GPTパーティションテーブル作成
n # 新規パーティション (EFI用)
1 # パーティション番号
  # (Enterでデフォルト) 
+512M # サイズ
t # タイプ変更
1 # EFI System
n # 新規パーティション (Linux用)
2 # パーティション番号
  # (Enter)
  # (Enter 残り全部)
w # 書き込み

lsblk でパーティションができているか確認をする。 2つパーティションを作成したので、sda1sda2 が出ていたら成功。

sda           8:0    1   7.5G  0 disk
├─sda1        8:1    1   512M  0 part
└─sda2        8:2    1     7G  0 part

ファイルを実際にフォーマットする。

sudo mkfs.fat -F32 /dev/sda1
sudo mkfs.ext4 /dev/sda2

ファイルをマウントする。

sudo mount /dev/sda2
/mnt sudo mkdir -p /mnt/boot/efi
sudo mount /dev/sda1 /mnt/boot/efi

lsblk で正しくマウントができているか確認をする。

sda           8:0    1   7.5G  0 disk
├─sda1        8:1    1   512M  0 part /mnt/boot/efi
└─sda2        8:2    1     7G  0 part /mnt

ビルドデータのコピー

ビルドデータをUSBメモリ(今回のファイルシステム名だとsda2)にコピーする。

sudo cp /path/to/bzImage /mnt/boot/vmlinuz
sudo cp /path/to/rootfs.img /mnt/boot/

GRUBのインストール

grub-efi-amd64 をインストールする。

sudo apt install grub-efi-amd64

GRUBをUSBに入れる。コマンドの詳細は grub-installのオプション にて説明している。

sudo grub-install --target=x86_64-efi --efi-directory=/mnt/boot/efi --boot-directory=/mnt/boot --removable

GRUBの設定ファイルを作成

以下の内容を、/mnt/boot/grub/grub.cfg を手動で作る。

set timeout=5
set default=0

menuentry "My Linux" {
    echo "START LOADING LINUX KERNEL!!!!!"
    linux /vmlinuz rdinit=/init
    initrd /rootfs.img
}

PCで起動する

アンマウントしてUSBを取り外す。/mnt ディレクトリ内に居るとアンマウントできない点に注意。

sudo umount /mnt/boot/efi
sudo umount /mnt
sync

以下の手順で Linux Kernel を起動する。

  1. USBを差し込み、電源を入れる
  2. BIOS/UEFI 設定画面に入る(今回の中古PCの場合F2連打)
  3. Secure Bootを無効にする
  4. ブート順序をUSBファーストにする。

GRUBメニューが出て「My Linux」を選べば、カーネルと initramfs が読み込まれて起動するはず!!