2017/03/26

[勉]最近のPCのブートを知る (3) : ブートマネージャー

ここまで調べたところで、パーティションテーブルの扱い方に新しいやり方が加わったということがわかった。
まあ「新しい」といってもずいぶん前からなのだが。。。

もう1つ気になっていることがある。
外付けUSB-HDDにLinuxをインストールしたのだが、起動ディスクを選択するときにOS名が出てきたのだ。
そして、そのUSB-HDDを同じ機種である別のPCに挿したのだが、OS名も出ないし、起動するドライブとしてインストールしたディスクやパーティションを選択しても起動できなかったのだ。

UEFIにブートマネージャーなるものがあるようだが、それが関係しているのだろうか?


https://ja.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface#.E3.83.96.E3.83.BC.E3.83.88.E3.83.9E.E3.83.8D.E3.83.BC.E3.82.B8.E3.83.A3.E3.83.BC

どうも、特定のセクタ(ブートセクタ)を読込んで起動を始めるのではなく、「ここにロードするファイルがある」という情報をUEFIに教えておき、UEFIはNon-Volatileなメモリにそれを保持しておいて、それを使って起動するようだ。
ブートセクタに何も書いていないのなら、それはUSB-HDDだけ挿しても立ち上がらないはずだな。

そのロードするファイルは、OSに依存しない場所に置かれ、OSに依存しない形式のフォーマットで、OSに依存しない実行形式なり情報なりが書かれているはずだ。
そして、インストーラがそれをUEFIに教えることになるから、何かしらのAPIというかABIというか、そういうので通信していることになるだろう。
それがPEというやつか。

ここら辺までひっくるめて「UEFI」と呼んでいるような気がする。
ディスクだけ挿して起動するという時代は終わったのか。。。

ただ、USBメモリにISOファイルを書込んで起動することができるから、できないというわけではない。
そういうブート形式でインストールされていないだけなのだろう。
VirtualBoxみたいに、移動できてどこでも同じように動くLinux環境を作りたかったのだが。

ブートセクタにブートローダを書込んでおいて、UEFIから起動するときにブートセクタを読込んでくれるようであれば、動く気がする。
ブートローダをどこに書込むかは、インストーラが聞いてくるので指定できる。
ドライブの方に書込むのか、パーティションの方に書込むのかいつも迷うのだが、さっきの話からするとUEFIに登録するようなものになるから、どこでもよいのかもしれない。

ブートローダー - ArchWiki
読んだときは、2017年1月更新になっている。
Linuxのブートローダって、たくさんあるんだな。。

Ubuntu系はGRUB2というか、GRUB(Legacyではない方)が使われていたと思う。
GRUB - ArchWiki
保護用にパーティションを作るなどと手順が書かれているが、私は何も考えずに「/」とswapのパーティションしか作らずにインストールしたので、そこらへんがよくなかったのかも。
Linux 上の GRUB 2 がブートできなくなったときの対処方法
リムーバブルディスクから起動できると書いてあるしね。

そういえば、Raspberry PiもbootはFATパーティションに置いてあるから、そういうのがいるのかもしれん。
まあ、今回は最近の情報を調べたかっただけなので、これで終わるとしよう。

2017/03/24

[勉]最近のPCのブートを知る (2) : UEFIモードとBIOSモード

UEFIのWindowsをBIOSモードで起動させる « ライフボート 裏ブログ(非公式ブログ)
どうも、UEFIはBIOSとは別物のようだ。
前回見ていったMBRやGPTは、どちらかといえばディスクのフォーマットに関するものだが、それだけでは済まないらしい。

 

UEFI モードまたは従来の BIOS モードでの起動
Microsoftのページで、まだWindows10は入っていない(別のページにあるのかもしれんが)。
UEFIモードの場合はGPTで、BIOSモードの場合はMBRと書いてある。

うちのノートPCはどうだっけ、と管理画面を見てみると、UEFIモードのようだ(EFIという文字があったので)。

image

 

Unified Extensible Firmware Interface - Wikipedia
ディスクの管理についても書かれているが、MBRもあればGPTもある、という感じで、別にGPTだけとなっているわけではなさそうだ。
もしかすると、MBRもある、がBIOSモードのことかもしれんが、さすがにそこまではわからん。

読んでいくと、BIOS時代から考えるとかなり高機能になっていることがうかがえる。
組み込みでも、RedBootやuBootの用に1段目のブートローダを使うことがあるが、そういう位置づけなのかもしれん。
あれが提供されているおかげで、あまり考えずにLinuxなどが動かせたりするからな。


だんだんまとまりがなくなってきたが、そもそも「最近のPCブートを知る」という漠然とした内容だから仕方あるまい。

2017/03/22

[勉]最近のPCのブートを知る (1) : MBRとGPT

まずは、UEFIから調べる。

BIOSに代わるファームウェア“UEFI”とは一体何か? 1/2 | 震撼性能! Sandy Bridgeに死角なし!! | DOS/V POWER REPORT

DOS/V POWER REPORTだから、PCを自作する人向けの情報ではあるものの、ポイントが絞られている分わかりやすい。

  • 起動ドライブの容量制限がなくなる(実質的に)
  • 設定画面がGUIにできる

今回はブートのことを知りたいだけなので、前者だけ見ていく。


Master Boot Record(MBR)の管理しか知らなかったのだが、GUID Partition Table(GPT)という管理があるらしい。

MBRは、HDDなどのセクタ0にパーティション情報が書いてある形式・・・と思っていたが、セクタ0だけじゃなくてパーティション分けされた先頭セクタでも良いようだ。
マスターブートレコード - Wikipedia

昔のHDDはCHS方式でアクセスしていたけど、容量が足りなくなってLBA方式になった。
SATAになる前のパラレルなHDDは40ピンあって、けっこうな本数がLBA用に割り当てられていたような記憶がある。
Advanced Technology Attachment - Wikipedia

パーティションテーブルのオフセットが8byte目のところがLBA方式で、サイズが4byteしかないというのが「MBRは32bit管理」という部分だろうか。
でも、これは先頭位置だけだから、その次の「全セクタ数」が4byteになっている方が32bitで制限される原因としては大きいのか。


GUIDパーティションテーブル - Wikipedia
こちらがGPT。
なんとなく肝臓付近を意識してしまうが、γ-GTPなんかとは関係がない。

LBAのアドレス表記で言えば、こうなっているそうだ。

  • LBA0 : MBRに相当する情報
  • LBA1 : GPTヘッダ
  • LBA2~33 : パーティションエントリ

GPTで管理していても、GPTに管理していないツールなどのためにMBRを用意してあるのだと。
MBR部分をどう見るかはOSによって異なるらしいので、自分でパーティションテーブルを作るときには注意した方がよさそうだ。

 

名前の由来になっているGUIDがどこに出てくるかというと、パーティションエントリという部分のようだ。
図によると1つのセクタに4エントリ入るようなので、512byte / 4 = 128byte/エントリ、ということになる(HDD系の1セクタサイズって、まだ512byteでよいよね??)。

  • 0- 15 [16]: パーティションの種類を表すGUID
  • 16- 31 [16]: パーティション固有のGUID
  • 32- 39 [ 8]: パーティション開始LBA
  • 40- 47 [ 8]: パーティション最後LBA
  • 48- 55 [ 8]: 属性フラグ
  • 56-127 [72]: パーティション名(UTF-16LE)

後半はわからなかったので、英語版wikipediaの情報を使った。
https://en.wikipedia.org/wiki/GUID_Partition_Table#Partition_entries


そこそこに衝撃だったのは、fdiskではGPTを扱えない、ということを知ったことだろうか。
まあ、Raspberry Piくらいだったらfdiskで済んでいるのだけど、PC Linuxが起動しないときに自分で対応しようとして悩まないように・・・というか、よけい破壊しないように覚えておいた方が良かろう。

[勉]最近のPCのブートを知る (0)

「PC」と書いたが、WindowsやLinuxがインストールできるような、お店でマザーボードやCPUを買って組み立てるようなPC、というのが正しいかもしれん。
昔だと「DOS/V互換機」などと呼んでいたように思うが、最近の名称がわからん。
また、Macは文化が異なりそうなので、今回は除外する。

 

なんで今さらブートのことを調べようと思ったのかというと、知識が追いついていないからだ。
作業に支障が出ることを心配するくらいには、取り残されてしまっている。

今回は、なんで調べようと思ったのかを記録しておこう。


昨年買ったノートPCに、今はWindows10がメインでインストールされているが、VirtualBoxでUbuntuもインストールしている。
しかし、ゲストOSではパワーが足りないので、外付けSSDにネイティブLinuxをインストールしようと考えた。

外付けSSDと書いたが、実際は外付けHDD(BuffaloのHD-PLFU3)を持っていて、蓋を無理やりはがして余っていたSSDを取り付けたのだ。

USBメモリにLinuxインストーラのISOファイルを焼いて、USBメモリから起動し、外付けSSDにインストールすることはできた。
ブートローダをどこに書込むか聞かれたので、外付けSSDの一番上(パーティション番号が付かないところ)を指定した。

 

その外付けSSDを持って作業場に行った。
実は、家のノートPCと作業場のノートPCはほぼ同じ機種だから、全部外付けSSDに書込んでいるから接続すれば起動するだろう、と軽く考えていた。
しかし、起動しなかった。。。

よくわからないが、面倒なので、インストールに使ったUSBメモリを挿し、インストールし直すことにした。
しかし、これはインストーラのせいか何か分からないが、うまくいっていない。

 

こうやって考えていくと、自分のブートに関する知識がまったく役に立っていないことが分かる。
当時はBIOSが主流だったが、今はUEFIとかいうやつだ。
パーティションも、だいたいprimaryで4つまで分割するのが主だったと思う。

 

などと振り返っていくと、このままの知識では仕事に影響が出るんじゃなかろうか、と心配になった。
心配なら、調べて安心しようではないか、と思ったのだ。
それに、何がどうなっているか知っていないと、心配どころではなく、作業に差し障りが出てしまう。
ブログにするネタもないことだし、しばらく調べるとしよう。

2017/03/21

[c/c++]main関数の引数

最近、本業が忙しく、記事の更新ができてないし、書くネタがない。。。
1週間空けるのも嫌なので、Cのmain関数のことを調べ直すことにした。

 

普段フリースタンディング環境を使うことが多いので、main関数はあってもなくてもよいというか、名前は何でもよいけど慣習として使っておこう、くらいのイメージしか持っていない。
関数とは書いたけれども、returnされてもやることがないので、スタックを消費するのも嫌だからコールじゃなくてジャンプさせている、という人も多いんじゃなかろうか(そしてmainの最後は無限ループになっている)。

 

ただ、普通のホスト環境では、main関数は重要だ。


今回もオライリーの『Cクイックリファレンス』を読む。
「7.1.5 main()関数」だ。

  • int main(void)
  • int main(int argc, char *argv[])

この両者がC標準とのこと。
引数無しでもいいんだ。。。

これに加えて、次の形式もサポートしていることが多いのだと。

  • int main(int argc, char *argv[], char *envp[])

envpは環境変数で、getenv()を使ってアクセスできるそうだ。

 

main()の特徴として、returnを書かずにブロックが終わった場合、自動的に0を返すことになっている。
そして、0はstdlib.hのEXIT_SUCCESSと同じ値。
また、main()の終了は、exit()の呼び出しと等価とのこと。

exit()はちょっと特別扱いされていると思っていたのだ。
atexit()でexit時に呼び出す関数が登録できるというところが不思議だったのだ。
説明文を読むと「exit()かmain()のreturn」と書かれているので、同じ扱いなのだな。


昔、C++で作っていたとき、グローバル変数で2つのclassのインスタンスをそれぞれ作り、片方のclassがもう片方のclassのstatic値をコンストラクタで参照するようにしていたのだが、最初は動いていたのに、プログラムを書き換えているうちにうまく動作しなくなった、ということがあった(あまり覚えてないが。。)。

グローバル変数のコンストラクタはどういう順番で動くかはっきりせず、コンストラクタが呼ばれていないと値が設定されないので、最終的にはコンストラクタで初期化は行わず、classに初期化関数を追加してmain()で呼ぶ、というような対処をしたような気がする。

mainが呼ばれる前後の混沌とした状態は制御が難しいので、なるべくmain後の安定した状態で処理を順番に行った方がよいな、と思ったのでした。