Rustでベアメタルプログラミングをやってみた

ベアメタルプログラミングとはOSなどを利用せずに、直接ハードウェア上にプログラムを走らせるプログラミング手法である。要するにOSなどを自分で作る練習にもってこいなのである。また、Rust言語は型安全なプログラミングであるにも関わらず、メモリへの直接アクセスなどを行えるため、このベアメタルプログラミングが可能な言語である。

というわけで、今回はRustでベアメタルプログラミングをやってみたので感想を述べたい。とはいっても、現状はQEMUで動かしているだけので、いずれ実機でも試してみたいところである。ちなみに、Rustもベアメタルプログラミングも今回はじめてである。

今回行ったことは、1つのCPUコアのみ動作させて、UART0からシリアルでHello Worldを出したあと、グラフィック描画のフレームバッファを取得してマンデルブロ集合を描画するという、比較的単純なものである。他の仕事もやりつつ、実質6日程度でグラフィック描画までできたので、ちょっと試して見るだけならハードルはそれほど高くないと思う。今ならWeb上に色々と資料もあるし、お手本となるC言語の実装もあるため簡単である。

ちなみに、実機でやっていない理由は、QEMUで利用可能なターゲットはRaspberry Pi 3であり、実際に手元にあるのはRaspberry Pi 4と少しハードウェアが違うためである。しかも、Raspberry Pi 4でのベアメタルプログラミング関連資料が少ないため、まだ、若干ハードルが高いように思う。

グラフィック描画までの道

1日目(2月14日)

1日めはコンパイルのためのDocker環境を整えて、手元のマシンでQEMUを動かして試せるようにした。RustのコンパイルはDockerコンテナ内で行い、QEMUの起動はホストOS(Mac)で動かすようにした。

2日目(2月15日)

2日目はRustのマングリングと出力バイナリの調査を行った。これはアセンブリでRustの関数を呼んだり、Rustからアセンブリコードを読むのに必須なので、objdump等で色々調べていた。

3日目(2月16日)

3日目はお手本のC言語ソースコードをRustにポーティングして、UART1のシリアルからHello World!を出力するようにした。

その後、しばらく仕事が忙しくて手を付けられず。

4日目(2月21日)

4日目はMailbox関連のコードをRustにポーティングした。MailboxとはCPUとGPU間のインターフェースのことである。

5日目(2月22日)

Mailboxのコードを更に修正し、UART1ではなく、UART0からシリアルでHello World!を出力できるようにした。Mailboxの仕様がいまいちわからなかったため、ドキュメントを主に読んでいた。

6日目(2月23日)

グラフィック周りの仕様がわかったため、マンデルブロ集合を描画してみた。

f:id:ytakano:20200223184003p:plain

ベアメタルプログラミングによるマンデルブロ集合

感想

やり始める前は、いくらメモリアクセスが簡単にできると言っても、少し難しいのではないかと思っていたが、思いの外簡単であった。また、1日のすべてをプログラミングに費やしていたわけではないので、時間のある学生時代なら2〜3日ぐらいでできたのではないかと思う。

Rustももう少しハマるかと思ったが、こちらも特に問題はなかった。以前、線形型システムとリージョンベースのメモリ管理手法を勉強していたので、構文を調べるだけで実装はできたように思う。いざとなればインラインアセンブラもかけるので、どうにでもなる。正直、Haskellより簡単だと思う。

ただ、やはりメモリアクセスのところはunsafeの嵐になるので、Rustといえども注意してプログラミングしなければならない。しかし、unsafeから抜け出すと型システムの庇護下にあるため大変安心である。

というわけで、これからは低まった人たちにも心置きなくRustを勧めていこうと思う。

あとは仮想メモリや、スケジューラあたりを書けばOSモドキなのも作れるだろう。いまのところOSを実装する予定はないが。

それでは、ソワカソワカ

 

続き↓

ytakano.hatenablog.com