ベアメタル(Bare-metal)から(1) - BIOS、ブート過程とブートローダー作成

ベアメタル

ベアメタルとは以下のように定義される。

Quote

In computer science, bare machine (or bare metal) refers to a computer executing instructions directly on logic hardware without an intervening operating system.

先ほど、オペレーティングシステムはプログラムを管理するプログラムだと言いました。

つまり、本質はプログラムである。

C言語で書いた簡単なプログラムを実際のCPU上で動かしてみるのがこの章の目標です。

まだオペレーティングシステムと言うには憚られるが、なんとリヌスのLinuxもターミナルプログラムから始まった!

仮想環境の準備

我々がLinusになり、CPUで簡単なプログラムを動かしてみよう。

まず用意する環境は以下の通りです。

  1. QEMU
  2. プログラムエディタ(VScode, Vim, Emacsなど)

QEMUをインストールする

QEMUは私たちが直接コンピュータを購入しなくても仮想のコンピュータを動かしてくれる仮想化ツールです。

基本的にオープンソースで、WindowsとLinuxで使用することができます。

Windowsの場合、別のWSL環境を構築してインストールすると、簡単にコマンドだけでインストールすることができます。

下記のリンクを使ってインストールしてみましょう。

WSL2

WSL2 설치

WSL2를 설치하고 설정이 끝나면

C 언어와 친해지기 전의 준비#Linux로 넘어간다.

または、QEMUサイトのダウンロードページでもダウンロード可能です。

プログラムエディタ

プログラムエディタの場合、ここでは説明しませんが、様々なエディタを調べて使いやすいものを選んで使ってみましょう。

とりあえず初めてプログラミングを始める人には次のようなオプションをおすすめします。

  1. Microsoft - VScode
  2. Jetbrain - CLion

これらの編集ツールに慣れたら、以下のようにキーボードから手を離さずに使えるオプションを調べてみましょう。

  1. Neovim (現在使用しているツール)
    1. LazyVim (現在使っているツール)このプラグインをインストールして使用中
  2. Emacs

実はエディタは使いやすいように作ったツールに過ぎない、メモ帳やNotepad++のような種類に関係なく何でも使ってもいい!!!

Hello World?

では、簡単なプログラムを作って動かしてみましょう。

これはC言語を始めたときに書いたプログラムであるHello World!を出力するプログラムのコードです。

コードは下記のようになります。

// hello.c
#include <stdio.h
int main()
{ printf("Hello World\n")
	printf("Hello World\n");
	return 0;
}

果たして、このコードが動くかな?

もちろん 動作しない.

では、ここで”なぜ?” という質問に答えてみましょう。

今まで私たちはC言語とオペレーティングシステムの歴史について見てきました。

これまでの内容から私たちが知っておくべき内容は以下の通りです、

1.オペレーティングシステムは抽象化を提供する
2.Hello Worldのコードは #include<stdio.h> という標準ライブラリを使用している。
3.私たちが現在設定したQEMU環境は以下の写真のようになります。

image-20231106142900672.png|center round|700

そして、現在の全体的な構成は次のようになります。
image-20231106143025350.png|center round|700
左は私たちが現在使っている環境であり、右はQEMUで構成した環境です。

何がないのか?

  1. ディスプレイがない
  2. キーボードがない
  3. マウスがない
  4. ストレージがない!!!

なんてこった!!!

コンピュータの画面はどのように表示されるのか(printf関数を単純に使うだけでは全く考えなかった部分です!)

そして、私たちが書いたコードはCPUでどのような順番で処理されるのだろうか?

そもそも、私たちが書いたコードをどのようにQEMUに読めと命令するのだろうか?

Toward printing "Hello World!"

コンピュータの出発点は何だろう?

それはBIOSです、BIOSとは何でしょうか?ウィキペディアによると、以下の通りです。

BIOS

In computing, BIOS (/ˈbaɪɒs, -oʊs/, BY-oss, -⁠ohss; Basic Input/Output System, also known as the System BIOS, ROM BIOS, BIOS ROM or PC BIOS) is firmware used to provide runtime services for operating systems and programs and to perform hardware initialization during the booting process (power-on startup)
BIOS - https://en.wikipedia.org/wiki/BIOS

つまり、簡単な入出力機能を実行し、OSを実行させ、ハードウェアを初期化するファームウェアです。

突然ファームウェアという新しい単語が出てきましたが、結局ファームウェアもプログラムです。

ここで重要なキーワードは入出力機能OSの実行ハードウェアの初期化である。

この3つのキーワードに上記の質問のほとんどに対する答えが存在する、一つずつ見てみよう。

ハードウェアの初期化 (コードの移動)

まず、皆さんが書いたコードをどのように動かすことができるでしょうか?

有線通信? 無線通信?, いいえ、あなたのコンピュータはまだそれほどスマートではありません。

私たちは 主記憶装置(USB、Floppy Disk、HDD、SSDなど)を通して移動します。

図に置き換えると次のようになります。
image-20231106160103504.png|center round|700
流れを説明すると下記のようになります。
1.まず、皆さんが作ったコードをコンパイルします。
2.コンパイルしたバイナリを記憶装置(ここではFloppy disk)に保存します。
3.そしてコンピュータに認識させる(まるでUSBを挿すように)

そして、次はBIOSが登場します。

BIOS

BIOSはまずハードウェアを認識し、どのような場所にどのようなデバイスが接続されているか、もしRAMメモリがあれば容量はどれくらいか、モニター、キーボード、マウスは接続されているかなどを確認します。

下の図で流れを理解してみましょう。
image-20231106161337381.png|center round|600
RAMだけでは物足りないので、他のハードウェアを追加してみましょう。
まずは画面表示のためのモニター。
image-20231106161758316.png|center round|600
そして、私たちが書いたコードが存在するストレージを追加したら?
image-20231106161942699.png|center round|600

やっと最新のコンピュータで使われるハードウェアを追加した,コンピュータらしい(?)コンピュータが完成しました。そして、接続したハードウェアをBIOSが認識することも分かりました。

しかし、まだ解決しない問題がある。

ストレージに私たちが保存したコードが保存されていて、ストレージをBIOSが認識することもわかった。

しかし、少し考えれば、BIOSの立場ではどんなデータが入ってるかもわからないストレージが認識されたのに、どうやってこのデータをCPUに読ませることができるのだろうか?

どこにどんなデータが存在するのかBIOSの立場では全く分からないのに?

ブートローダ(コードの出発点)

実は答えは簡単で、約束をしておくことです。

エンジニアたちは、前章で提示した問題を解決するために、BIOSというプログラムが最後に行うべき行動を 約束しました。

まず、BIOSは指定された記憶装置に存在する最初のセクタ(0x200, 512 bytesの大きさ) 決まったアドレス(0x7c00)にコピー/貼り付けます。

第二に、BIOSは指定されたアドレスにジャンプし、私たち(または、あなたが作ったコードを動作させます!!)!

図で表すと次のようになります。
image-20231107143135220.png|center round|700
image-20231107143202779.png|center round|700 image-20231107143202779.png|center round|700 image-20231107143801801.png|center round|700

このような過程を経て、Floppy disk、USB、HDDなどの記録装置に保存されたコードが初めてコンピュータで実行されます。

付録

保存装置が複数ある場合?

私たちが接続したデバイスがFloppy diskだけでなく、様々なデバイスを接続するとどうなるでしょうか?

または、Floppy diskを接続する前にコンピュータにHDDが接続されていたら?

もし皆さんが様々なOSをインストールして実行したいとしたら?

この問題に対する答えは、BIOSがハードウェアを初期化することにあります。

BIOSはデバイスを初期化する過程で、すでにどのようなデバイスが接続されているかを認識しているので、BIOSを通してどのストレージを使用するかを指定することができます。
image-20231114222459509.png|center round|400
[最新のBIOSで起動順序を設定する].

なぜ0x7c00なのか?

なぜ私たちが作成したコードが最初に記録される場所が0x0777でもなく0x07c0なのか?

実はこのような値を持つ理由は一つもない!!!

ほとんどのコンピュータ工学におけるこのような疑問のある値は歴史と関係が深い場合が多く、今回も同じケースである。

結論から言えば、初期の商用コンピュータ(16KiBまたは32KiBサイズのメモリが使われていた頃)が登場したときのIBMやMS-DOSなどの歴史を経て、事実上の標準として0x07c0に決まった。

詳細は以下を参照しよう(0x07c0と0x7c00が2つ登場する理由は次の章で)。

上の資料を参考すれば、もう少し詳しい流れを理解することができます。

整理された流れは次のようになります。

1.CPUにreset信号を渡すと、最初の実行フロー(reset vector)が存在するアドレスをレジスタに保存します。
2.実行されたコードはBIOSが入ってるROMアドレスです。
1. 特定のアドレスはROM、グラフィックカード、モニタ(次の章でコードで説明します)などにマッピングされています。
2.これらのマッピングはCPUの設計によるものです。
3.BIOSは最後にコードを特定の領域(IBM compatible PCの場合は0x7c00)にコピーします。

それでOSはどうやって?

では、OSはどのような過程を経て実行されるのでしょうか?

全体的な流れは下の図のようになります。
image-20231107153309542.png
[出典 - https://en.wikipedia.org/wiki/BIOS\]

今まで私たちが作ってメモリにロードされるコードをBoot Loaderと呼んでこのBoot LoaderにOSの中心であるKernelをメモリにロードして実行する流れで進みます!!!

このような流れはOSをUSBなどに入れてインストールする過程と同じであり、USBにロードされたKernelを通してOSを実行させ、USBにあるOSコードをUSBに保存することです。

私たちがパソコンを買うたびに行ってきたOSのインストールがこのような過程で行われていたのです。

全体の変化を示した図です。
image-20231107143827633.png|center round|700

宿題

1.Floppy diskが何であるかを知る
2.では、BIOSの出発点は?
1. ファームウェアを調べる
2. ROMを調べる
3.上記のリンクを調査してもう一度記事を読む