2
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?

More than 3 years have passed since last update.

ノートPCで自作OS(MikanOS)を動かしたい

Last updated at Posted at 2021-04-18

はじめに

ゼロからのOS自作入門(通称:みかん本)で楽しくOS自作に取り組んでいます。
本書の内容を追うだけならQEMUで起動するだけで十分なのですがせっかくOSを自作しているのに、実機でやらないと勿体ない。

というわけで、この記事では私がノートPC ( LG gram model 13Z980-NA77J ) で本書の自作OS (MikanOS)を起動する際にうまく動かなかった点とそれに対する解決策をまとめていきます。
注意
あくまで私のノートPCで必要だった変更ですので、変更は自己責任にてお願いします。

※2021/04/18時点 osbook_day06cまで確認済みです。進め次第追記していきます。

障害 1. ノートPC標準搭載のwindowsが起動してしまう

USBストレージに焼きこんだMikanOSを起動させたいのですが、ブート中に素通りして標準搭載のwindowsが起動してしまいました。

解決手順1-1. USB ストレージブートの優先度を上げる

まずはLG GramのUEFIの設定を変更しUSBストレージの起動優先度をwindows搭載のストレージよりも高くします。LG GramのUEFIにはwindowsから入ります。こちらを参考にさせていただきました。

解決手順1-2. Secure BootをOFFにする

みかん本でも言及されていますが、Secure bootはOFFにしなければいけません。上記のリンクにSecure bootをOFFにする方法も書かれていますので参照ください。

解決手順1-3. USBストレージのファイルシステムをFAT32にする

本書ではexFATファイルシステムでフォーマットするように書かれていますが私の環境ではexFATではブートできず、FAT32でフォーマットする必要がありました(原因は未解決。これはかなり詰まりました。)。

障害 2. kernelページをAllocateできない

QEMUでは動作するのに、実機では"faild to allocate pages: Not Found"となりました。

解決手順2-1. カーネルのエントリアドレスを変更する。

実機のメモリマップを確認してると、私のLG gramでは0x0010000が予約されててEfiConventinalMemoryが0x00110000からになってることに気づきました。
以下のようにカーネルのベースアドレスを0x00110000に設定してビルドしたら起動できました。

Makefile
#LDFLAGS  += --entry KernelMain -z norelro --image-base 0x100000 --static  
LDFLAGS  += --entry KernelMain -z norelro --image-base 0x110000 --static

今回のように、AllocatePagesが失敗する場合は物理メモリアドレスが既存のプログラムとバッティングしている可能性があるので一度確認されることをおすすめします。このようなことを見越してか、メモリマップの確認方法は本書で触れてくれています。

障害 3. USBマウスが認識しない

QEMUではマウスカーソルが動くのに、実機ではうまく反応してくれませんでした。なお、タッチパッドではなくUSBマウスを外付けしています。

解決手順3-1. kMemoryPoolSizeのサイズ数を大きくする。

LogレベルをDebugにして出力を確認していると、xhc.InitializeでkNoEnoughMemoryで初期化失敗していました。

usbドライバのコードをたどっていくとusb/xhci/ring.cppの67行目

usb/xhci/ring.cpp
  buf_ = AllocArray<TRB>(buf_size_, 64, 64 * 1024);  

でbuf_にnullptrが返ってくることが問題のようです。

さらに、AllocArray<>()をたどるとusb/memory.cppの32行目

usb/memory.cpp
    if (reinterpret_cast<uintptr_t>(memory_pool) + kMemoryPoolSize
        < alloc_ptr + size) {
      return nullptr;
    }

でnullptrがかえってくることが原因のようでしたので、if文の条件式から、 kMemoryPoolSizeを変更することにしました。
具体的にはusb/memory.hppの13行目を以下のように変更しました。

usb/memory.hpp
 // [org] static const size_t kMemoryPoolSize = 4096 * 32
 static const size_t kMemoryPoolSize = 4096 * 64; 

これで初期化が成功し無事マウスカーソルを動かすことができました。

障害4. カーネル側にメモリマップが渡らない(8章 osbook_day08a)

解決手順 4-1. UEFIに変更を加えたので、UEFIアプリ側の再ビルドが必要

忘れてて、結構なやんだ。

適宜、追加していきます。

2
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
2
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?