April 8, 2021

パソコンを持っていない私が「ゼロからのOS自作入門」した

追記:初回以降の記録は#osbookタグで記録していきます。

長らく止めていたblogを再開させるにあたって、何か良いネタがないかな?と探していたところ、この本の話題が流れてきた。

ゼロからのOS自作入門(内田公太)

その場で購入してザッピングして、手を動かしたい欲がとても高まったので、ガツガツ実装して記録を残してみることにする。タイトルの通り、現在パソコンを所有していないので、同じような状況の人の一助になれば。なお、レビュー欄やtwitterの話題を眺める限り、この本は「みかん本」と呼ばれているようなので、本項でもそれに従う。(実装するOSの名前がMikan OSであるのが由来のようだ)

私はMikan OSがターゲットにしているx64のコンピュータを持っていない。それどころか「パソコン」を所有していない123。手元にあるのはMagic Keyboardを接続したiPad AirとRaspberry Pi4で構築したheadlessサーバ(ArchLinux ARMが動いている)のみである。日常で必要な作業はほとんどiPadだけで完結しており、iPadの守備範囲を外れる作業(プログラミングなど)はRaspberry Piにssh接続して行っている。

みかん本では、開発環境としてUbuntu(含WSL)、Mikan OS(実装するOS)の動作環境として、実機あるいはqemuによるエミュレーションを想定している。前述した通り、私の作業環境はiPadを介したheadlessサーバなので、本ではカバーされていない工夫が必要になる。ここでは、最初のチュートリアルである1.1節「ハローワールド」を題材にして、作業環境を紹介したい。

このチュートリアルでは、バイナリエディタでHello Worldを出力する実行バイナリを手打ちして、それをUEFIアプリケーションとして起動して出力を確認することを行う。これを実現するには、iPadからサーバに接続し、バイナリエディタでファイルを作成し、qemuで実行してその画面を確認する必要がある。

SSHターミナル

Blinkを使っている。これは有償で2000円ほどで比較的高価なアプリだが4、なかなか完成度が高いターミナルソフトウェアである(ただし最近のiOSではたまに動作が不安定である5)。iPadを作業環境にするときに、さまざまなツールをサーベイしたが、ハードウェアキーボード(Magic Keyboard)に関する機能と設定が最も充実していたのがこのソフトウェアだった。

私はemacs使いなのでCtrl-Spaceのキーバインドを多用する6。iOSはこのキーコンビネーションを入力言語切り替えに割り当てており、これを変更することができない7。Blinkの場合はCustom Keypressというキーバインド機能を使うことで、この問題を回避できる(Ctrl-SpaceをそのままCtrl-Spaceとして送信するようにバインドする)。他にもApp Storeでの評価が高いSSHクライアントアプリケーションをいくつか試したが、これが実現できたのはBlinkだけであった。(もちろん全部試したわけではないので、漏れがあるかもしれない)

Blinkを起動するとblink>とプロンプトが表示される。これは簡易シェルになっていて、*nixな環境での標準的なコマンドがいくつか使える。configコマンドでBlinkの設定画面が表示される。ここでキーボードの設定や、接続プロファイルの管理を行う。簡易シェルでsshコマンドを実行するとssh接続を開始できる。接続先、ユーザ名を指定することもできるし、設定画面で作成したプロファイル名を指定して接続することもできる8。2本指でタップすると画面が切り替わって新しいターミナルが開く。ターミナル間はスワイプで移動することができる。

バイナリエディタ

本文中ではGUIなバイナリエディタが紹介されているが。私の環境では使えないので、ターミナルで動作するバイナリエディタをいろいろ試した。本に掲載されている16進数のデータを入力していくので、WYSIWIG的に編集できるものを探した。

まず最初に試したのは、emacsのhexl-modeである。これはemacsに標準搭載されているモードで、任意のファイルをバイナリ表示にして、また編集することができる。私はCLI環境ではemacsでプログラムを書くので、これが使えると大変都合が良いのだけど、16進数での入力は1バイトごとにキーストロークの入力が必要で、みかん本に掲載されている16進データをドコドコ入力することはできなかった。(なお、任意のファイルを16進ダンプしたり、1バイトだけ書き換える、みたいな用途には十分使える)

いろいろ探してみたところ、hexedit (https://github.com/pixel/hexedit) が要件に合いそうだったので、とりあえず採用してみることに。キーバインドがemacs likeであるのもよい(非常に重要)。

どうやら存在するファイルしか編集できないようなので、まずは空のファイルを作る

$ touch BOOTX64.EFI

デフォルトだとカラー表示がなかったり、1行あたりに表示されるバイト数が28バイトだったりで使いづらいので、以下のオプション付きで起動する。

$ hexedit -l16 —color BOOTX64.EFI

以下はKindleでみかん本を表示しながら、hexeditでバイナリデータを編集しているところである。

hexedit

なお私の環境では、Blinkから直接hexeditを起動すると1行目の表示が崩れる問題が発生した。この問題はtmuxなどのターミナルマルチプレクサを使うことで回避できる。(私は普段からtmuxをかまして作業するので、この点はあまり問題にならなかった)なお、TERM環境変数にscreenなどの適当な代替を渡すことでも回避できる。9

qemuの画面出力

x64の実機を持っていないので、動作確認はqemuを用いることになる。ArchLinux ARMでは以下のコマンドでx64のエミュレーションが有効な状態でインストールされる。(依存パッケージとしてqemuそのものもインストールされる)

pacman -S qemu-arch-extra

通常ならば、qemuを立ち上げるとGUIなウィンドウが生成されて、そこにエミュレートされた画面が出力される。しかしながら、私の環境はheadlessなのでそれができない。幸いなことにqemuには、エミュレートした画面をVNCで転送する機能が搭載されているので、これを使えばなんとかなりそうである。問題はiPadからの経路だが、調べてみたところ、BlinkにSSH Portforwarding機能が搭載されていることがわかった。これを使って手元にVNCのポートを引っ張ってくることにする。

まず、適当なVNCクライアントをiPadに入れる。私はVNC Viewerをインストールした。次にBlinkでサーバ側のVNCのデフォルトポート(5900/tcp)に向かってport forwardingを張る。Blinkで新しいターミナルを開いて、簡易シェルから以下のコマンドでiPadのポートをサーバ側に転送できる。(通常のsshコマンドと同じノリで使えるのが嬉しい)

blink> ssh -L 5900:localhost:5900 [profile name]

ポート転送ができたら、打ち込んだプログラムをディスクイメージに仕込んでqemuで実行する。コマンドは基本的にみかん本に掲載されている通りだが、-vncオプションを有効にする点が異なる。(なお実行の前には、UEFIファームウェアのイメージが含まれる開発環境のダウンロード、ディスクイメージの作成が必要である。これはみかん本に掲載されている内容と同じなので省略する)

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

あとはVNCクライアントでローカルに転送されたVNCのポートに接続すると、Hello Worldが表示されたqemuの画面を確認することができる。たまにPort Forwardingに失敗することがあるので、しばらく経っても接続できなかったら何回かリトライする。

qemu_result

パソコンがなくてもOSは書ける

いわゆる「パソコン」がなくても、このようにみかん本で手を動かすことができる。私は既に持っている環境がRaspberry Pi + iPadなのでこのような形になったが、以下のような形態も考えられる。

  • Raspberry Piにモニタを繋いで開発  *(実質、PCで開発するのと等価である)
    • この記事での内容と基本的には同じ(qemuの画面転送は不要)
    • Raspberry Piで動作するubuntuのイメージを使えば、みかん本の内容がそのまま使えるのでは?
  • タブレット + 安価なVPSで開発
    • これまで説明したのと基本的に同じ。Raspberry Piの部分がVPSで構築したサーバに置き換わる
    • Mikan OSをqemuで動かすのにはハイスペックな環境は(おそらく)不要なので、毎月数百円で環境を作れそう。途中で止めたくなったらVPSを解約すればおしまい
  • PC+ 安価なVPSで開発
    • PCは持っているけど、環境構築がめんどくさい貴方に
    • ちなみに、みかん本ではWSLを用いた開発についても解説があるので、Windows 10環境があるならばそれを使うのが素直ではある。ただ、手元環境を汚したくない、WSLを入れるリソースが足りない10、という場合には有効な選択肢である。

「OS自作には興味があるけど開発環境がないから…」と諦めてしまうのはもったいなので、ぜひトライしてみてほしい。(それそのものが、よい学習題材になるだろう)


  1. もちろん、何をもって「パソコン」というのかは議論が難しいところだ。ここでは、LenovoなりDellなりAppleなりが売っているハードウェアに、汎用OS(Windows/macOS/Linux/BSDの子孫たち, etc…)を搭載したものとする。要は「お店で売っているパソコン」だ。ところでmacの中身はBSDでは…みたいな話はここではしない ↩︎

  2. 業務用の端末としてラップトップを所有しているが、これは厳に業務用なのだ…(当然の話ではあるが) ↩︎

  3. かつてはサーバも含めてゴテゴテ所有していたけれど、ある日思い立って全て処分してしまった。 ↩︎

  4. 購入した時の領収書をみると2440円であった。なおBlinkはOSSなので、自分でビルドすれば無料で使うことができる。ただし、iOS向けの開発環境や、実機へのインストール手段の確保が必要になる。 ↩︎

  5. issueとしても報告されている。 ↩︎

  6. 一般的にはMark Set(範囲指定の開始)に割り当てられることが多い ↩︎

  7. 実はiOSの設定でキーボードの種類を英語1種に限定してしまえば、Ctrl-Spaceを自由に使うことができる。しかしながら日本語環境での実用性を考えるとナンセンスな選択肢である。(開発時だけキーボードの種類を1種に限定するのも試してみたが、とても苦痛だった) ↩︎

  8. 通常のsshコマンドにおける$HOME/.ssh/configファイルでの接続先定義に似ている ↩︎

  9. 根本原因は突き止められていない。本文中で述べた通り、私はtmuxを常用しているので実質問題がない。 ↩︎

  10. 特にWSL2の場合は仮想マシンでLinuxを動作させるので、それなりのディスク容量を消費する。 ↩︎

© Gaku Nakagawa 2021