はじめに
本書の読み方
# サンプルコードのダウンロード
# 想定読者
# 本書の構成
# 関連書籍について
# 開発環境のセットアップ
# 本書のコードの読み方
# 参照している仕様書の表記方法
目次
第1章:OSとは──コンピューターの裏側を支えるソフトウェアを知る
# OSとは何か
## 日常にあるOSの例
## OSとコンピューターの関係
### コンピューターの基本的なしくみ
### アプリケーション──人々がコンピューターを使う理由
### OS──ハードウェアとアプリケーションの狭間で
# 本書で実装するOSの全体像
## ベアメタルプログラミング
## 資源(メモリとCPU)の管理
## ハードウェアの制御
## 本書のゴールと関連書籍の紹介
# 本題に入る前に
第2章:ベアメタルプログラミングをしてみる──OSのない世界でプログラムを動かすための準備
# コンピューターの構成要素
## メモリ
## CPU
## 入出力
# すべてはバイナリ
## すべてのデータは2進法で表現できる
### 数値をバイナリで表現する
### 16進法は便利
### ひとくちサイズのバイナリ、byte
### 文字列のバイナリ表現
## 画像のバイナリ表現
## プログラムもバイナリ
## コンパイラ──ソースコードを翻訳してバイナリを作るプログラム
# UEFIアプリケーションを作ってみる
## 開発環境の構築
## Hello, worldを書いてみる
## Rustツールチェインのバージョンを固定する
## アプリケーションとOSの違い
## UEFI──OSよりも前に起動する、OSを起動するためのプログラム
[column]色々なファームウェア──Legacy BIOSとUEFI BIOS
## ターゲット──どの実行環境向けにバイナリを生成するのかコンパイラに伝える
## QEMUを利用してUEFIアプリケーションを実行する
# UEFIからの脱却
## "Hello, world"はどこへ行く?
## no_stdで生きていく──coreクレートと歩むベアメタル生活
[column]普段は当たり前だと思っているが実はOSが提供しているもの
## フレームバッファに何か描く
# Rustの便利機能を活用する
## ビルドや実行を簡単にする
## cargo clippyとHLT命令──CPUを無駄に回さないようにする
## cargo fmt──コードをきれいに整形する
# もっと色々なものを描く
## 四角形を描く
## 線分を描く
## 画面に文字を表示する
## 文字の列、文字列を表示する
# writeln!()マクロを使ってみる
## メモリマップを表示する
## 図形描画のコードを整理する
## UEFIのない世界へ行く──ExitBootServices
第3章:メモリ管理を実装しよう──限りある資源を効率良く使えるようにする
# OSとメモリの関係
## メモリとは何か
## メモリ管理とは何か
# 実装前の準備
## ソースコードの整理──ファイルを分割する
## cargo testが通らない理由
## カスタムテストフレームワークを有効にする
# バイト単位のアロケータを実装する
## アライメントはなぜ必要か
### メモリの速度とバス幅
### キャッシュ──よく使うものは近くに置こう
### アライメントが合っていないと回路がつらい
## 簡単なメモリアロケータの実装
# OSのテストをRustで書く
## シリアルポート出力の実装
[column]CONVENTIONAL_MEMORY以外の領域の正体
## デバッグを便利にする関数たちを実装する
# ページング──より高度なメモリ管理を行う
## ページングとは
## x86_64におけるページング
## 現在のページテーブルを表示してみる
## 動作確認のために割り込み処理・例外処理を実装する
### GDT──コンピューター黎明期、8086時代の遺物
### TSS──割り込み時のスタック切り替えを制御する
## コードセグメントとデータセグメントの設定
## 割り込み関連の初期化
## ブレークポイント例外のあとに実行を継続する
## ページテーブルを作って設定する
## ページングの動作確認をする
## Pinの落とし穴
第4章:マルチタスクを実装しよう──1つのCPUで複数の作業を並行して行う方法について知る
# マルチタスクとは何か
## マルチタスクの例
[column]並行と並列の違い
## 簡単にマルチタスクもどきを実装してみる
# Rustのasync/awaitで協調的マルチタスクをする
## aync/awaitを使えるようにする
### Future trait
### WakerとRawWaker
### block_onの実装
### Executor
### ほかのタスクに処理を譲る(yieldする)
## 時間経過を計る
### タイマー──時間を計るデバイス
### ACPIからHPETの場所を教えてもらう
### HPETを初期化する
### static mutを使ってHPETを共有する
## スレッド間で安全にデータを共有する
### データ競合とは
### Rustにおける参照のルール
### Mutex──実行時にメモリ競合を回避するしくみ
### Mutexを使ってHPETのインスタンスをOS全体で共有する
## タスクの実行を一定時間止めるFutureを作る
## 協調的マルチタスクの問題点
## (発展)非協調的マルチタスク
# ソースコードの整理
## HPETの初期化処理をリファクタリングする
## メモリアロケータの初期化を関数に切り出す
## ページング関連のコードを整理する
## 画面描画周りの初期化を別の関数に切り出す
## VramTextWriterをBitmapTextWriterに一般化する
## print系マクロの出力をQEMUの画面上にも表示する
第5章:ハードウェアを制御する(1)──デバイスを動かす方法を知る
# OSとハードウェアの関係
## Port Mapped I/OとMemory Mapped I/O
## Port Mapped I/Oの例──シリアル入力を実装する
# PCIとは
## PCIの概要
## Bus、Device、Function
## ベンダー ID、デバイスID
# PCIデバイスの一覧を取得する
## PCI Configuration空間
## ECAM──Enhanced Configuration Access Method
## PCIデバイスの一覧を表示するコードを実装する
# USBコントローラ(xHCI)のドライバを実装する
## USBとは
## xHCIとは
## xHCの検出
## ちょっと脱線──諸々の改良
## 起動時のページテーブル初期化の高速化
## Memory mapped I/OでxHCとやりとりをする
## xHCのレジスタ
## xHCの初期化
### xHCをリセットする
### Scratchpad Bufferを確保して設定する
### DCBAAを確保して設定する
### Primary Event Ringを用意する
### Command Ringを用意する
### xHCをスタートする
## IoBox──CPUのキャッシュとMemory-mapped I/Oの関係
## USBデバイス接続時の処理を実装する
### イベントのポーリングをする
### USBデバイスの検出
### デバイスの検出とポートの初期化
### Device Slotの有効化
### USBポートの初期化処理を整理する
### Address Deviceコマンド──USBデバイスにアドレスを割り当てる
第6章:ハードウェアを制御する(2)──USBデバイスを使えるようにする
# USBデバイスの情報を取得する
[column]FromトレイトとIntoトレイト
## Device Descriptorの取得
## デバイスクラス
## USBにおけるConfig、Interface、Endpointの関係
## Config Descriptorとその仲間たちを取得する
# USBキーボードを使えるようにする
## USBキーボードの基本
[column]Nキーロールオーバー
## キーの押下状態から変化したキーを特定する
## なぜHashSetではなくBTreeSetを使うのか
## キーコードから文字への変換
[column]キーボードレイアウトの闇──打ちたい記号が入力できない!
# USBマウス……もといタブレット入力を使えるようにする
## HIDレポートディスクリプタを解析する
## USBタブレットの状態変化を表示する
## ビットを切り出す関数を実装する
## マウスボタンの状態を解釈する
## ポインタ位置の情報を取り出して表示する
Appendix:実ハードウェアでの起動を試す
# USBメモリをFATファイルシステムでフォーマットする
# WasabiOSをUSBメモリに書き込む
# USBメモリからの起動
# 実機で試すときの注意点
おわりに
参照している仕様書の一覧
索引
著者プロフィール