😸

Linux From Scratchをqemuで実行する方法

2020/12/17に公開

Linux From Scratch

Linux From Scratchはaptとかyumとかdnfを使わずにあらゆるパッケージを自前でビルドしてlinuxを動かそうというものです。linux kernelの勉強のために触ってみたのですが、最後の最後でgrubというブートローダのホスト側の設定を変えなければならず、しかも起動するたびにパソコンを再起動しなければならないというめんどくささ、そしてググってみた感じではほかに記事がなかったのでqemuで実行できるようにしてみました。

環境

ホストマシン:Ubuntu 20.04
qemu-system-x86_64:QEMU emulator version 4.2.1 (Debian 1:4.2-3ubuntu6.10)
Linux From Scratch(LFS):Version 10.0-systemd
10.LFS システムのブート設定のLinux-5.8.3まで作業が終わっていること
lfsフォルダは/home/lfs以下に置かれていることとする

$ ls ~/lfs
bin   dev  home  lib64    media  opt   root  sbin     srv  tmp  var
boot  etc  lib   linuxrc  mnt    proc  run   sources  sys  usr

イメージディスクの作成

当初はinitramfsでやろうと考えていましたが、initramfsは3GB程度の制限を受けてしまうため(sourceフォルダを除外すれば2GB程度に収まるがsourceを除外するのはなんだかもったいないと思った)ここではイメージディスクを作成します。
まず、空のイメージディスクを作成します。

dd if=/dev/zero of=disk.img bs=1G count=50

これで50GBのイメージファイルが作成されます。

ループバックデバイスの登録

先ほど作成したイメージファイルをループバックデバイスとして登録します。ループバックデバイスはファイルをあたかもデバイスとして扱えるようにする仕組みのことです。

sudo losetup /dev/loop20 disk.img

パーティションの作成

作成したイメージファイルにパーティションを作成します。

sudo parted /dev/loop20

実行すると以下のような表示になると思います。

GNU Parted 3.3
/dev/loop20 を使用
GNU Parted へようこそ! コマンド一覧を見るには 'help' と入力してください。
(parted)

この状態で以下を実行します。

mklabel msdos
mkpart primary fat32 1 512M
mkpart primary ext2 512M 100%
set 1 boot on
q

これでパーティションの作成が完了しました。

パーティションのデバイス登録

イメージディスクにパーティションを作成しましたので、次はそれぞれのパーティションをマウントしていきます。イメージディスクにパーティションが複数あるときはkpartxを使ってマウントしていきます。

sudo apt update
sudo install kpartx
sudo kpartx -a /dev/loop20

これで/dev/mapperにloop20p1(パーティション1)、loop20p2(パーティション2)がそれぞれできます。

パーティションのフォーマット

作成したパーティションをフォーマットしていきます。

sudo mkfs.fat -F32 /dev/mapper/loop20p1
sudo mkfs -t ext2 /dev/mapper/loop20p2

パーティションのマウント

フォーマットしたパーティションをマウントしてきます。

mkdir $(pwd)/mnt
sudo mount /dev/mapper/loop20p2 $(pwd)/mnt/
sudo mkdir $(pwd)/mnt/boot
sudo mount /dev/mapper/loop20p1 $(pwd)/mnt/boot

LFSのファイル群のコピー

sudo cp -r ~/lfs/* $(pwd)/mnt

grubのインストール

最後にgrubをインストールします。(ここをミスると下手をすればホストのgrubを上書きする恐れがあるのでミスはしないように)

sudo grub-install --target=i386-pc --root-directory=$(pwd)/mnt /dev/loop20
cat <<EOF | sudo tee $(pwd)/mnt/boot/grub/grub.cfg
# Begin /boot/grub/grub.cfg

set default=0
set timeout=5

menuentry "GNU/Linux, Linux 5.8.3-lfs-10.0-systemd" {
        insmod ext2
        set root=(hd0,1)
        linux   /vmlinuz-5.8.3-lfs-10.0-systemd root=/dev/sda2
}
EOF
sync

起動

qemuを使って起動します。

qemu-system-x86_64 -drive format=raw,file=disk.img -curses

終了するときはAlt+2を押した後、quitを入力

おまけ

今回はbiosによるブートをしています。EFIによるブートをするのであればefiパーティションを作ってgrub-installのtargetをi386-efiやx86_64-efiにすればいいと思われますが、まだ試してないのでわかりません。
また、ファイル作成時(例えばtouchコマンド)に

touch: a: Read-only file system

と怒られます。理由は探し中ですが、対処法として

mount -o rw,remount /

を入力すれば作成できるようになります。

Discussion