OS自作入門【1】

にあえん

August 21, 2023

wasmに入門したりprismaにハマったりいろいろありますが、以前から興味のあった自作OSというものに手を出してみます。

この書籍を参考にしています。

ゼロからのOS自作入門 | 内田 公太 |本 | 通販 | Amazon

機械語でHello World!

まずはバイナリの編集に使用するエディターをダウンロードします。

sudo apt install okteta

エディターがダウンロードできたら、ひたすらHello Worldを実装します。

以下に上がっていますが、本見ながら写経しました。チカレタ。。

mikanos-build/day01/bin/hello.efi at master · uchan-nos/mikanos-build · GitHub

実際はこんな感じです。痺れますね。

これをBOOTX64.efiとして保存します。

ちゃんとコーディングできていれば、sumコマンドでチェックサムが12430となっています。

% sum ../../study/custom_os/BOOTX64.efi
12430     2

ではこれをエミュレーターで実行します。

QEMUをダウンロードしましょう。

Download QEMU - QEMU

公式にダウンロードのためのshがあったので使ってみます。

wget https://download.qemu.org/qemu-8.1.0-rc4.tar.xz
tar xvJf qemu-8.1.0-rc4.tar.xz
cd qemu-8.1.0-rc4
./configure
make

しかし./configureのあたりでエラーになってしまいました。。

% ./configure                                         
Using './build' as the directory for build output
python determined to be '/home/username/.anyenv/envs/pyenv/shims/python3'
python version: Python 3.8.12
mkvenv: Creating non-isolated virtual environment at 'pyvenv'
mkvenv: checking for meson>=0.63.0
mkvenv: installing meson>=0.63.0
mkvenv: checking for sphinx>=1.6.0, sphinx-rtd-theme>=0.5.0

'sphinx>=1.6.0' not found:
 • Python package 'sphinx' was not found nor installed.
 • mkvenv was configured to operate offline and did not check PyPI.


Sphinx not found/usable, disabling docs.

ERROR: Cannot find Ninja

なんかpython使っているっぽいです。

pipで関連パッケージをインストールしておきましょう。

pip install sphinx sphinx-rtd-theme

Ninjaというツールも必要らしい。ということでインストールしておきます。

aptだとうまくインストールできなかったのでbrewでインストールしました。

brew install ninja

ということで再チャレンジします。

% ./configure              
Using './build' as the directory for build output
python determined to be '/home/username/.anyenv/envs/pyenv/shims/python3'
python version: Python 3.8.12
mkvenv: Creating non-isolated virtual environment at 'pyvenv'
mkvenv: checking for meson>=0.63.0
mkvenv: installing meson>=0.63.0
mkvenv: checking for sphinx>=1.6.0, sphinx-rtd-theme>=0.5.0
The Meson build system
Version: 1.2.1
Source dir: /home/username/Project/personal/hugo-blog/qemu-8.1.0-rc4
Build dir: /home/username/Project/personal/hugo-blog/qemu-8.1.0-rc4/build
Build type: native build
Project name: qemu
Project version: 8.0.94
C compiler for the host machine: cc -m64 -mcx16 (gcc 11.4.0 "cc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0")
C linker for the host machine: cc -m64 -mcx16 ld.bfd 2.38
Host machine cpu family: x86_64
Host machine cpu: x86_64
Program scripts/symlink-install-tree.py found: YES (/home/username/Project/personal/hugo-blog/qemu-8.1.0-rc4/build/pyvenv/bin/python3 /home/username/Project/personal/hugo-blog/qemu-8.1.0-rc4/scripts/symlink-install-tree.py)
Program sh found: YES (/usr/bin/sh)
Program python3 found: YES (/home/username/Project/personal/hugo-blog/qemu-8.1.0-rc4/build/pyvenv/bin/python3)
Program bzip2 found: YES (/usr/bin/bzip2)
Program iasl found: NO
Compiler for C supports link arguments -Wl,-z,relro: YES 
Compiler for C supports link arguments -Wl,-z,now: YES 
Compiler for C supports link arguments -Wl,--warn-common: YES 
Compiler for C supports arguments -Wundef: YES 
Compiler for C supports arguments -Wwrite-strings: YES 
Compiler for C supports arguments -Wmissing-prototypes: YES 
Compiler for C supports arguments -Wstrict-prototypes: YES 
Compiler for C supports arguments -Wredundant-decls: YES 
Compiler for C supports arguments -Wold-style-declaration: YES 
Compiler for C supports arguments -Wold-style-definition: YES 
Compiler for C supports arguments -Wtype-limits: YES 
Compiler for C supports arguments -Wformat-security: YES 
Compiler for C supports arguments -Wformat-y2k: YES 
Compiler for C supports arguments -Winit-self: YES 
Compiler for C supports arguments -Wignored-qualifiers: YES 
Compiler for C supports arguments -Wempty-body: YES 
Compiler for C supports arguments -Wnested-externs: YES 
Compiler for C supports arguments -Wendif-labels: YES 
Compiler for C supports arguments -Wexpansion-to-defined: YES 
Compiler for C supports arguments -Wimplicit-fallthrough=2: YES 
Compiler for C supports arguments -Wmissing-format-attribute: YES 
Compiler for C supports arguments -Wno-initializer-overrides: NO 
Compiler for C supports arguments -Wno-missing-include-dirs: YES 
Compiler for C supports arguments -Wno-shift-negative-value: YES 
Compiler for C supports arguments -Wno-string-plus-int: NO 
Compiler for C supports arguments -Wno-typedef-redefinition: NO 
Compiler for C supports arguments -Wno-tautological-type-limit-compare: NO 
Compiler for C supports arguments -Wno-psabi: YES 
Compiler for C supports arguments -Wno-gnu-variable-sized-type-not-at-end: NO 
Compiler for C supports arguments -Wthread-safety: NO 
Program cgcc found: NO
Library m found: YES
Run-time dependency threads found: YES
Library util found: YES
Run-time dependency appleframeworks found: NO (tried framework)
Found pkg-config: /usr/bin/pkg-config (0.29.2)
Run-time dependency glib-2.0 found: NO (tried pkgconfig)

../meson.build:729:10: ERROR: Dependency "glib-2.0" not found, tried pkgconfig

A full log can be found at /home/username/Project/personal/hugo-blog/qemu-8.1.0-rc4/build/meson-logs/meson-log.txt

ERROR: meson setup failed

またパッケージが見つからなくて怒られました。

以下の記事を参考にインストールしました。

【C言語】glib2.0を使ってみた〜confファイル読み込み〜 - Qiita

sudo apt install libglib2.0-dev

再度実行します。

% ./configure

# ...中略....

../meson.build:840:11: ERROR: Dependency "pixman-1" not found, tried pkgconfig

A full log can be found at /home/username/Project/personal/hugo-blog/qemu-8.1.0-rc4/build/meson-logs/meson-log.txt

ERROR: meson setup failed

また失敗しました。

(いっぺんに出してほしい…)

これもインストールします。

pixman package : Ubuntu

sudo apt install -y libpixman-1-dev

再度実行します。

% ./configure

# ...中略....

Program scripts/decodetree.py found: YES (/home/username/Project/personal/hugo-blog/qemu-8.1.0-rc4/build/pyvenv/bin/python3 /home/username/Project/personal/hugo-blog/qemu-8.1.0-rc4/scripts/decodetree.py)
Program flex found: NO

../target/hexagon/meson.build:180:8: ERROR: Program 'flex' not found or not executable

A full log can be found at /home/username/Project/personal/hugo-blog/qemu-8.1.0-rc4/build/meson-logs/meson-log.txt

ERROR: meson setup failed

これもインストールします。

sudo apt install -y flex

再実行してやっと成功しました。

makeも実行しましょう。

make

これがめっっっっっっっっちゃ時間かかりました。

というかここまでやって分かったんですが、ソースコードからコンパイルする必要なかったです!!!!!!

brew使っているなら一発でダウンロードできました!!!!!今までの時間!!!!!!!

% brew install qemu

# ...中略...

==> Pouring llvm@15--15.0.7.x86_64_linux.bottle.tar.gz
Error: Too many open files @ rb_sysopen - /home/linuxbrew/.linuxbrew/Cellar/llvm@15/15.0.7/bin/verify-uselistorder

ただ途中でインストールできませんでした。かなしい。

結局先程ビルドしたディレクトリの一部をPATHに通すように.zshrcを書き換えることでコマンドを使用可能にしました。

export PATH="[格納されたディレクトリ]/qemu-8.1.0-rc4/build:$PATH"

qemuのコマンドが使用可能になったら、ディスクイメージを作成します。

qemu-img create -f raw disk.img 200M
mkfs.fat -n "MIKAN OS" -s 2 -f 2 -R 32 -F 32 disk.img
mkdir -p mnt
sudo mount -o loop disk.img mnt
sudo mkdir -p mnt/EFI/BOOT
sudo cp BOOTX64.efi mnt/EFI/BOOT/BOOTX64.efi
sudo umount mnt

これでディスクイメージが出来上がりました。(disk.img)

qemu-system-x86_64 \
    -drive if=pflash,file=../mikanos-build/devenv/OVMF_CODE.fd \
    -drive if=pflash,file=../mikanos-build/devenv/OVMF_VARS.fd \
    -hda disk.img

-driveオプションで指定しているファイルは、作者のリポジトリに上がっていました。

これをダウンロードしておきます。

mikanos-build/devenv at master · uchan-nos/mikanos-build · GitHub

これを実行します。

% qemu-system-x86_64 \
    -drive if=pflash,file=../mikanos-build/devenv/OVMF_CODE.fd \
    -drive if=pflash,file=../mikanos-build/devenv/OVMF_VARS.fd \
    -hda disk.img
WARNING: Image format was not specified for '../mikanos-build/devenv/OVMF_CODE.fd' and probing guessed raw.
         Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
         Specify the 'raw' format explicitly to remove the restrictions.
WARNING: Image format was not specified for '../mikanos-build/devenv/OVMF_VARS.fd' and probing guessed raw.
         Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
         Specify the 'raw' format explicitly to remove the restrictions.
WARNING: Image format was not specified for 'disk.img' and probing guessed raw.
         Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
         Specify the 'raw' format explicitly to remove the restrictions.
Could not open option rom 'kvmvapic.bin': No such file or directory
qemu-system-x86_64: failed to find romfile "vgabios-stdvga.bin"

うまくいきませんね…

なんかファイルが見つからないようです。

あまりに面倒くさすぎて2日ほど放置していました。

調べると、以下のような記事が見つかりました。

error with run1.bat: qemu-system-x86_64: failed to find romfile "vgabios-stdvga.bin · Issue #9 · Absurdponcho/PonchoOS · GitHub

qemuの特定のディレクトリでコマンドを実行する必要があるようです。

面倒ですが、qemu-system-x86_64コマンドを実行するためのshファイルを実装します。

これはコマンド実行のたびにディレクトリ移動をしないために用意します。

#!/bin/bash
cd $HOME/Project/tools/qemu-8.1.0-rc4/pc-bios
qemu-system-x86_64 $@

実行権限を付与します。

chmod -x qemu-system-x86_64.sh

このshを実行するエイリアスを登録します。

alias qemu-system-x86_64="$HOME/Project/tools/toolbox/qemu-system-x86_64.sh"

これで再度コマンドを実行しましょう。

ただ、これにより相対パス指定が使えなくなったので絶対パスに直しておきます。

% qemu-system-x86_64 \
    -drive if=pflash,file=$HOME/Project/study/mikanos-build/devenv/OVMF_CODE.fd \
    -drive if=pflash,file=$HOME/Project/study/mikanos-build/devenv/OVMF_VARS.fd \
    -hda $HOME/Project/study/custom_os/disk.img
WARNING: Image format was not specified for '/home/username/Project/study/mikanos-build/devenv/OVMF_CODE.fd' and probing guessed raw.
         Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
         Specify the 'raw' format explicitly to remove the restrictions.
WARNING: Image format was not specified for '/home/username/Project/study/mikanos-build/devenv/OVMF_VARS.fd' and probing guessed raw.
         Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
         Specify the 'raw' format explicitly to remove the restrictions.
WARNING: Image format was not specified for '/home/username/Project/study/custom_os/disk.img' and probing guessed raw.
         Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
         Specify the 'raw' format explicitly to remove the restrictions.
qemu-system-x86_64: could not read keymap file: 'en-us'

またエラーです。

なんでこう一筋縄じゃいかないかね。。。

もうDockerとかで動かす方法ないかな〜と思って調べていたんですが、この辺の手順でやり忘れがありそうだったのでやってみます。

linuxでマルチアーキテクチャに対応したdockerイメージを作ろうの巻(buildx) | ゆっくり遅報

qemuのインストールディレクトリにscriptsディレクトリがあるので、ここのshを/usr/local/binに移動します。

chmod +x scripts/qemu-binfmt-conf.sh 
sudo mv scripts/qemu-binfmt-conf.sh /usr/local/bin/qemu-binfmt-conf.sh

あとはカーネルに登録するための準備を行います。

cat <<EOF | sudo tee /usr/local/bin/register.sh
#!/bin/sh
QEMU_BIN_DIR=${QEMU_BIN_DIR:-/usr/bin}
if [ ! -d /proc/sys/fs/binfmt_misc ]; then
    echo "No binfmt support in the kernel."
    echo "  Try: '/sbin/modprobe binfmt_misc' from the host"
    exit 1
fi
if [ ! -f /proc/sys/fs/binfmt_misc/register ]; then
    mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
fi
if [ "${1}" = "--reset" ]; then
    shift
    find /proc/sys/fs/binfmt_misc -type f -name 'qemu-*' -exec sh -c 'echo -1 > {}' \;
fi
exec /usr/local/bin/qemu-binfmt-conf.sh --qemu-suffix "-static" --qemu-path "${QEMU_BIN_DIR}" $@
EOF
sudo chmod +x /usr/local/bin/register.sh
cat <<EOF | sudo tee /etc/systemd/system/register.service
[Unit]
Description= register cpu emulator
[Service]
ExecStart = /usr/local/bin/register.sh
Restart = no
Type = simple
RemainAfterExit=yes
[Install]
WantedBy = multi-user.target
EOF

カーネルに登録しました。

sudo systemctl daemon-reload
sudo systemctl enable register.service
sudo systemctl start register.service
%sudo systemctl status register.service
× register.service - register cpu emulator
     Loaded: loaded (/etc/systemd/system/register.service; enabled; vendor preset: enabled)
     Active: failed (Result: exit-code) since Fri 2023-08-25 09:24:25 JST; 17s ago
    Process: 573950 ExecStart=/usr/local/bin/register.sh (code=exited, status=126)
   Main PID: 573950 (code=exited, status=126)
        CPU: 3ms

 8月 25 09:24:25 username-ThinkPad-X260 systemd[1]: Started register cpu emulator.
 8月 25 09:24:25 username-ThinkPad-X260 register.sh[573950]: /usr/local/bin/register.sh: 15: exec: /usr/local/bin/qemu-binfmt-conf.sh: Permission deni>
 8月 25 09:24:25 username-ThinkPad-X260 systemd[1]: register.service: Main process exited, code=exited, status=126/n/a
 8月 25 09:24:25 username-ThinkPad-X260 systemd[1]: register.service: Failed with result 'exit-code'.

まぁ失敗したんですけどね。

エミュレートするだけでこんなに面倒ですか。くそ〜〜〜〜〜

一旦心が折れたので、QEMUの動作環境構築は次回にまわして終わります。。

まとめ

大変すぎるぜQEMUの構築。

そもそも最初のソースコードからビルドする段階で間違っていたんだろうか。。

いろいろ前途多難です。