M1 Macで始める「ゼロからのOS自作入門」- 第1章
2021.07.24
この記事は最終更新日から1年以上が経過しています。
どもです。
今回は、購入したまま積本となってしまっていた、2021年3月22日に発売された「ゼロからのOS自作入門」を、ついに進めて行こうかなと思って最近やっております。
実は、「30日でできる! OS自作入門」も所持しているのですが、途中まで進めたまま最後までやりきれていなかったので、今回こそは最後まで進めるぞといった意気込みです。
当初は、本著に従ってUbuntuで開発を進めていたのですが、やっぱりMacで開発したいなぁと思ってM1 Mac miniで開発を進めております。
環境
- Mac mini (M1, 2020)
- Mac OS 11.3
- Apple clang version 12.0.5 (clang-1205.0.22.11)
1章 PCの仕組みとハローワールド
既に、先人の有志達が記事を上げて頂いておりますので、そちらも参考に進めさせて頂きました。
参考文献
本著では、EFIファイルをバイナリエディタ「okteta」を使用していて、最初はUbuntuで行っていたのでそのまま使用して作成したのですが、それもMacで作成する場合は バイナリエディタ「0xED」をインストールすると良さそうです。
ということで、EFIファイルをバイナリエディタで作成したとして、(QEMUのインストール済みとして)
まずは、必要なものをHome Brewでインストール。
$ brew install dosfstools qemu llvm nasm binutils
LLVMのpathを通す。
# Intel Mac の場合 $ export PATH=/usr/local/opt/llvm/bin:$PATH # Apple Silicon Mac の場合 $ export PATH=/opt/homebrew/opt/llvm/bin:$PATH
binutilsのpathを通す。
# Intel Mac の場合 $ export PATH=/usr/local/opt/binutils/bin:$PATH # Apple Silicon Mac の場合 $ export PATH=/opt/homebrew/sbin:/opt/homebrew/opt/binutils/bin:$PATH
「QEMU」のエミュレータで実行していきたいので以下のコマンドを実行していきます。
- 1.qemu-imgコマンドで200MBのからのファイルを作成、FAT形式でフォーマット
- 2.disk.imgと言う名前のディスクイメージ作成
- 3.マウント用のディレクトリ「mnt」を作成
- 4.disk.imgをマウント
- 5.ブートディレクトリ作成
- 6.BOOTX64.EFIファイルをマウントしたdisk.imgに書き込む
- 7.アンマウント → BOOTX64.EFIを含んだdisk.imgファイルを作成
$ 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 $ hdiutil attach -mountpoint mnt disk.img $ mkdir -p mnt/EFI/BOOT $ cp BOOTX64.EFI mnt/EFI/BOOT/BOOTX64.EFI $ hdiutil detach mnt
本著と異なるところは、「sudo mount〜」が「hdiutil attach -mountpoint〜」と言った形になる所ですね。
上記のコマンドがエラーも出ず、うまく行きましたら、「OVMF_CODE.fd」と「OVMF_VARS.fd」ファイルが必要となりますので、curlコマンドで取得します。
$ curl -O https://raw.githubusercontent.com/uchan-nos/mikanos-build/master/devenv/OVMF_CODE.fd $ curl -O https://raw.githubusercontent.com/uchan-nos/mikanos-build/master/devenv/OVMF_VARS.fd
「QEMU」のエミュレータで実行するため以下のコマンド入力。
$ qemu-system-x86_64 -drive if=pflash,file=OVMF_CODE.fd -drive if=pflash,file=OVMF_VARS.fd -hda disk.img
すると、「Hello world!」の文字列確認。
上手く行きました。
C言語でハローワールド
対象となるC言語プログラムは以下の箇所。
https://raw.githubusercontent.com/uchan-nos/mikanos-build/master/day01/c/hello.c
こちらになります。
typedef unsigned short CHAR16; typedef unsigned long long EFI_STATUS; typedef void *EFI_HANDLE; struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL; typedef EFI_STATUS (*EFI_TEXT_STRING)( struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, CHAR16 *String); typedef struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL { void *dummy; EFI_TEXT_STRING OutputString; } EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL; typedef struct { char dummy[52]; EFI_HANDLE ConsoleOutHandle; EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut; } EFI_SYSTEM_TABLE; EFI_STATUS EfiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) { SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Hello, world!\n"); while (1); return 0; }
上記のプログラムをClangとLLDを使ってコンパイル&リンクを行っていきます。
$ clang -target x86_64-pc-win32-coff -mno-red-zone -fno-stack-protector -fshort-wchar -Wall -c hello.c $ lld-link /subsystem:efi_application /entry:EfiMain /out:hello.efi hello.o
エラーがなく成功すると、hello.efiファイルが生成されますので、機械語で実行したように、disk.imgをマウントして「BOOTX64.EFI」という名前のファイルでコピーします。
$ hdiutil attach -mountpoint mnt disk.img $ cp hello.efi mnt/EFI/BOOT/BOOTX64.EFI $ hdiutil detach mnt
「QEMU」のエミュレータで実行するため以下のコマンド入力。
$ qemu-system-x86_64 -drive if=pflash,file=OVMF_CODE.fd -drive if=pflash,file=OVMF_VARS.fd -hda disk.img
同じく、ウィンドウが立ち上がり、「Hello world!」の文字列が表示すれば成功。
というわけで、M1 Macでも自作OSの書籍を進められそうなので、このまま進めて行きたいと思います。
今回は、1章を実行するため、環境など簡略化してすすめたのですが、実は、このままだと第2章で躓いてしまうので、修正などが必要となってきます。
というのを次回 第2章にでもと。
ではではぁ。