0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ついに自作OSが起動したので作業内容を紹介

Posted at

はい、miku_JK_Jbです

今回は自作OSを起動させることができたので、起動させるまでの開発記録を紹介していく

これまた久しぶりのブログ更新だな。自作OSのエラーが多かったり私生活が忙しかったので投稿が遅くなった🥺

自作OSが起動したことが気になると思うので先に起動した画面を見せるとしよう。
PXL_20250623_143220939.MP~2.jpg

これが自作OSが起動した画面だ!!

は??起動しているの??

っと見ている人は思っただろう。

大丈夫だ問題ない。

これが正常だ。

理由はカーネルが起動した後にグラフィックを描画するようにしていないからだ。

じゃあこの - みたいなのは何だって?

これはUEFIブートローダーで設定されたフレームバッファの状態がそのまま表示されているのだ。

カーネルを起動したら画面をクリアするようにしたら消える。

ただ、私はカーネルが起動しているかを確認するために消していない

動画でも自作OSが動いているのを見ることができるよ
https://youtube.com/shorts/PlddQI49z7I

さて、自作OSが起動した画面を見せたのでそろそろ開発記録を紹介していくとするか

まずは1日目

この日は以前ビルドしていたブートローダーとカーネルを実機で起動するかを検証した

↓検証した際の動画
https://youtube.com/shorts/kqJcFWZcu1Y

ちなみになぜ実機で検証しているのかと言うと、QEMUなどの仮想マシンとかを使うよりも開発している雰囲気が出るじゃん?笑

検証結果はPCにそもそも自作OSの存在を認識されなかった🤪

クソが😮‍💨

ってことでエラーの理由を探っていくとすぐにエラーの原因を発見

そもそもカーネルのパスを間違っていた🤪
495926441_17909082687110983_962121762246228490_n.png

あとRootを開く処理を実装していなかった😱

Rootを開く処理とはOSがファイルを操作する下準備といった感じ
処理の流れはYoutubeにて解説しているよ
こんな大事な処理を実装していなかったのは自分でも謎である

そしてRootを開く処理を実装中に気づく
ExitBootServiceの前に最新のメモリマップを取得していない

これの何が問題かというと古いメモリマップを使用してしまうとカーネルが誤ったメモリ領域にアクセスしてしまうのでクラッシュやフリーズが起きてしまう

ってことですぐに修正と再ビルド

これ1日目に行った作業の内容
結構抜けがあった感じだな

2日目

2日目は1日目に修正したブートローダーが動くかをテスト

↓検証した動画
https://youtube.com/shorts/UvWolbnV2oo

ちなみに1日目とは違うPCを使って検証している
理由は1日目の検証で使用したPCは設定が面倒なため

結果は黒い画面に赤い点線が出た
PXL_20250625_114854406.MP~2.jpg

考えられる原因はフレームバッファの描画処理で問題が起こっている?
もしくはカーネルのビルド設定に問題がある?

ってことでエラーの理由を探っていくと致命的なミスを発見
55355c9bb0e1d43ab4133041af500caf.jpg

写真にもデカデカと書かれているがカーネルを静的リンクではなく動的リンクにしていた
はぁ😮‍💨このお馬鹿さんは一体何をやっているのか😩

ってことでカーネルを静的リンクで再ビルド

で、結果は
PXL_20250625_114854406.MP~2.jpg

全く変わらず黒い画面上部に赤い点線が出る状態に

ってことで別の方法で試すことに

考えられる原因は検証用PCにグラボが刺さっているから、GPUを特定してGOPを取得する幅を広げればいいのではと考えた

GOPを超簡単に説明するとOSがグラフィックを描くようにする奴

処理の流れはこんな感じ

PCIデバイスのスキャン

スキャンで取得したクラスコードを元に手動で検出

GPUを見つけたらBARを読み込みメモリを初期化

流れとしては最初にPCIデバイスのスキャンを行い、取得したクラスコードもとに手動で検出、GPUを見つけたらBARを読み込み、メモリを初期化といった流れ

こうすることで内蔵GPUと外部GPUの両方が存在しても、それぞれを識別して任意に選べて、複数のGPUがぶら下がってても、優先順位を決めて描画デバイスを選べるはず!!

中々実装も大変で1週間以上かかった。PCIのクラスコードの取得やBARを取得の機能自体は元々実装してあったのでそこだけは唯一の救いだった

だが、結果は全く変わらなかった

次にカーネルのようにブートローダーにもビルドミスが無いかをチェックした

結果は
file BOOTX64.EFI.png

ブートローダーがEFI形式ではなく、ELF形式でビルドされていた\(^o^)/

ってことで修正していく

修正した内容は以下の通り

・コンパイラ g++からclang++に変更
・リンカ ldからld.lldに変更
・リンカスクリプトを独自に変更
・ターゲット形式 .EFI固定から elfからEFI形式に変換するように変更

こうすることでしっかりとブートローダーをEFI形式でビルドすることができた
file BOOTX64.EFI EFI format.png

ちなみにコンパイラの変更やリンカの変更を行ったので3週間近く掛かってしまった

だが、それでも変わらなかった。

次に描画設定を詰め込む処理を修正した

詰め込んでいる描画処理の設定はこんな感じ
・ピクセルの書き込み先アドレス
・解像度
・1ラインあたりのピクセル数

・ ピクセルの並び順

ピクセルの書き込み先アドレスや1ラインあたりのピクセル数が分からない人向けに説明すると
ピクセルの書き込み先アドレス = 画面
1ラインあたりのピクセル数 = ピッチ
ピクセルの並び順 = RGBなど

修正した内容は以下の通り
・戻り値をvoid型からEFI_STATUSを返すように修正

・GOP, FBC に対してNULLチェックをするように修正

・汎用ポインタで扱えるように修正

修正内容をざっくりと伝えると

戻り値をVOID型からEFI_STATUSを返すように修正して関数の呼び出し元が、
「何が悪かったか」を明確に検出できるようになった

GOP, FBCにたいしてNULLチェックを行うことでクラッシュした時の耐性を向上させた

汎用ポインタで扱えるようにして、読み書き型依存性をなくすようにした

尚、結果は変わらない模様

最後にBIOSの設定でフルスクリーンロゴを有効にさせた
PXL_20250626_145757443.jpg

フルスクリーンロゴはこんな感じ
PXL_20250626_145811660.jpg

フルスクリーンロゴを有効にした所、無事に起動した
PXL_20250623_143220939.MP~2.jpg

では、なぜフルスクリーンロゴを有効にしたら起動したのだろうか?

原因は主に2つ
・GOPが初期化されていない
・コンソールモードの初期状態が異なる

GOPが初期化されていない点について解説していくと

フルスクリーンロゴが有効な場合だと、UEFIが自動的にGOPを初期化してくれ、画面を表示する準備をしてくれるので、先にGOPの初期化が済んでいる状態になる
ちなみにフルスクリーンロゴが無効な場合だと、UEFIがGOPの初期化をしないことがあるので、ブートローダーでもGOPの取得に失敗することがある

コンソールモードの初期状態が異なる点ついて解説していくと

フルスクリーンロゴを有効にすると、UEFIが最初にコンソール出力を非表示にして、ロゴを表示させるので、
文字出力やフォントの扱いに独特な状態遷移が起こる
ちなみにフルスクリーンロゴを無効にすると、設定が異なるので、コンソールの出力ポインタであるConOutと、コンソールの出力モードのSetModeの呼び出しが崩れてしまう

そう考えると意外とフルスクリーンロゴを有効にすることって大事なんだな

尚、EFI形式でビルドした後のソースコードを修正を行わずに、フルスクリーンロゴの設定を有効にした状態で、起動するか検証したが、起動することはなかった。

これが自作OSのカーネルを起動するまでの作業内容だったよ
これでようやくスタートラインに立った

​​次回はブートローダーの開発で大変だったことを上げていくよ

ということで以上miku_JK_Jbでした

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?