Boot Sequence
登場人物
- ファームウェア ( BIOS/UEFI )
- ブートローダ ( GRUB )
- 初期 RAM ディスク ( initramfs)
など
概要
BIOS からデーモンプロセスの起動が完了するまで。
流れ
BIOS -> ブートローダ -> Linux カーネル -> 初期 RAM ディスク -> スタートアッププログラム
- CPU が BIOS のコードを実行し、ハードウェアの初期化を行う
- ブートローダがディスクを読み取り Linux カーネルに制御を移す
- カーネルが OS の初期化を行う
- 初期 RAM ディスクがルートボリュームをマウント
…
CPU と機械語
CPU の動作
- メモリから命令を読み出し、実行
- アーキテクチャにより備える命令が異なる ( x86_64 等 )
- レジスタというデータ保持領域を持つ
基本的にはレジスタとメモリでデータをやりとりし、処理を行う。
32 bit のレジスタは EAX
64 bit のレジスタは RAX
のように、E と R がつく。
CPU のモード
- リアルモード ( 16 bit )
- プロテクトモード ( 32 bit )
専用の命令でプロテクトモードへ切り替える。
リセットベクタ
- CPU は電源投入後、リセットベクタと呼ばれるメモリアドレスから命令の実行を開始
- リセットベクタの値は CPU の種類により異なる
- リセットベクタのアドレスは BIOS または UEFI の命令を指す
アセンブラプログラムの作成
- nasa: intel 記法
- gas: AT-T 記法
$ cat mov_gas.s
mov $0x10, %AL # AX レジスタの下位 8 bit 分
# アセンブル
$ as mov_gas.s
# ELF のヘッダを除去
$ objcopy -S -O binary a.out mov_gas.bin
$ ls
a.out mov_gas.bin mov_gas.s
a.out には実行時に必要な情報が色々ついてる。(ELF)
このままだとかなり長い binary ファイルになってしまうので除去した。
gas
$ xxd a.out
0000000: 7f45 4c46 0201 0100 0000 0000 0000 0000 .ELF............
0000010: 0100 3e00 0100 0000 0000 0000 0000 0000 ..>.............
0000020: 0000 0000 0000 0000 d800 0000 0000 0000 ................
0000030: 0000 0000 4000 0000 0000 4000 0700 0400 ....@.....@.....
0000040: b010 002e 7379 6d74 6162 002e 7374 7274 ....symtab..strt
0000050: 6162 002e 7368 7374 7274 6162 002e 7465 ab..shstrtab..te
0000060: 7874 002e 6461 7461 002e 6273 7300 0000 xt..data..bss...
0000070: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000080: 0000 0000 0000 0000 0000 0000 0300 0100 ................
0000090: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000a0: 0000 0000 0300 0200 0000 0000 0000 0000 ................
00000b0: 0000 0000 0000 0000 0000 0000 0300 0300 ................
00000c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000100: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000110: 0000 0000 0000 0000 1b00 0000 0100 0000 ................
0000120: 0600 0000 0000 0000 0000 0000 0000 0000 ................
0000130: 4000 0000 0000 0000 0200 0000 0000 0000 @...............
0000140: 0000 0000 0000 0000 0100 0000 0000 0000 ................
0000150: 0000 0000 0000 0000 2100 0000 0100 0000 ........!.......
0000160: 0300 0000 0000 0000 0000 0000 0000 0000 ................
0000170: 4200 0000 0000 0000 0000 0000 0000 0000 B...............
0000180: 0000 0000 0000 0000 0100 0000 0000 0000 ................
0000190: 0000 0000 0000 0000 2700 0000 0800 0000 ........'.......
00001a0: 0300 0000 0000 0000 0000 0000 0000 0000 ................
00001b0: 4200 0000 0000 0000 0000 0000 0000 0000 B...............
00001c0: 0000 0000 0000 0000 0100 0000 0000 0000 ................
00001d0: 0000 0000 0000 0000 1100 0000 0300 0000 ................
00001e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00001f0: 4200 0000 0000 0000 2c00 0000 0000 0000 B.......,.......
0000200: 0000 0000 0000 0000 0100 0000 0000 0000 ................
0000210: 0000 0000 0000 0000 0100 0000 0200 0000 ................
0000220: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000230: 7000 0000 0000 0000 6000 0000 0000 0000 p.......`.......
0000240: 0600 0000 0400 0000 0800 0000 0000 0000 ................
0000250: 1800 0000 0000 0000 0900 0000 0300 0000 ................
0000260: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000270: d000 0000 0000 0000 0100 0000 0000 0000 ................
0000280: 0000 0000 0000 0000 0100 0000 0000 0000 ................
0000290: 0000 0000 0000 0000 ........
# ELF ヘッダの情報を見る
$ readelf -h a.out
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 216 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 64 (bytes)
Number of section headers: 7
Section header string table index: 4
$ xxd mov_gas.bin
0000000: b010 ..
nasm
$ nasm -o mov_nasm.bin mov_nasm.asm
$ cat mov_nasm.asm
mov AL, 0x10
両方の dump を見てみる。
$ xxd mov_gas.bin
0000000: b010 ..
$ xxd mov_nasm.bin
0000000: b010 ..
- b0 (opcode): 1 バイト分の即地を AL に格納する
- 10 (operand): 格納する値 (0x10 = 16)
BIOS と UEFI
- CPU の起動時に最初に実行されるプログラム
- ハードウェアの初期化並びに基本的な IO ルーチンの提供を行う
- マザーボードの不揮発性メモリに保存されている
- BIOS の機能上の制約から置き換えるものとして UEFI ( Unified Extensive Firmware Interface ) が開発された
CPU のリセットから BIOS の実行
- CPU は reset vector である 0xffff0 から命令を実行する
- 0xffff0 の命令により BIOS の最初の領域へジャンプする
- BIOS コードへのアクセスはアドレスデコーダによりマザーボード上の不揮発性メモリに転送される
BIOS の処理内容
- 作業メモリの確保
- 割り込みルーチンのセットアップ
-
POST ( Power On Self Test )
- デバイスの検出
- 初期化
- 設定
-
ブートローダの呼び出し
- ブートデバイスの検出
- 先頭領域の読み出し
- ジャンプ
(hands-on) CPU リセット後の流れを見てみる
$ cat mbr.asm
[bits 16]
[org 0x7c00]
entry:
;; レジスタの初期化
xor ax, ax
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov sp, 0x7c00
mov si, msg
;; 文字出力のループ
putchar:
mov al, [si]
add si, 1
;; alの値が0だったらendにジャンプ
cmp al, 0
je end
mov ah, 0x0e
mov bl, 15
int 0x10
jmp putchar
;; 無限ループ
end:
hlt
jmp end
msg:
db 0x0a, 0x0a
db "message from mbr!" ; 任意の文字列を入力
db 0x0a
db 0
times 510-($-$$) db 0 ; 510 byte目まで0で埋める
dw 0xaa55 ; ブートデバイスシグネチャ
# アセンブル
$ nasm -o mbr.bin mbr.asm
# デバイスのイメージファイルを作成
$ dd if=/dev/zero of=fd.img count=2880
2880+0 records in
2880+0 records out
1474560 bytes (1.5 MB) copied, 0.00318686 s, 463 MB/s
# ブートセクタにイメージを書き込み
$ dd if=mbr.bin of=fd.img conv=notrunc
1+0 records in
1+0 records out
512 bytes (512 B) copied, 0.000121714 s, 4.2 MB/s
./qemu-2.11.0-rc0/x86_64-softmmu/qemu-system-x86_64 -machine accel=tcg -boot once=a,menu=off -drive file=/home/centos/ASM/MBR/fd.img,format=raw,if=floppy,index=0 -display curses -nographic
SeaBIOS (version rel-1.10.0-74-gcd47172a67-prebuilt.qemu-project.org)
iPXE (http://ipxe.org) 00:03.0 C980 PCI2.10 PnP PMM+07F915B0+07EF15B0 C980
Booting from Floppy...
message from mbr!
コード解説
[bits 16]
16 bit アーキテクチャ用のバイナリファイルを出力
[org 0x7c00]
0x7c00 にロードする
mov si, msg # si に msg を代入
mov al, [si] # [si] のアドレスを取得し、AL に入れる
add si, 1 # si をインクリメント ( 2 文字目 )
cmp al, 0 # al と 0 を比べる
je end # al = 0 であれば end に jmp
si の指すメモリに格納されている値を AL にコピー、0 であれば end にジャンプ
mov ah, 0x0e
mov bl, 15
int 0x10 # interrupt ( BIOS の割り込み。テーブルの 16 番目の命令をコールする )
int 0x10 ( AH BL AL レジスタの値を用いる )
上記の命令を実装してくれているのが BIOS。
GRUB はこれらの BIOS の機能を用いて、デバイスにアクセスする。
god を用いたデバッグ
./qemu-2.11.0-rc0/x86_64-softmmu/qemu-system-x86_64 \
-machine accel=tcg -boot once=a,menu=off \
-drive file=/home/centos/ASM/MBR/fd.img,format=raw,if=floppy,index=0 -nographic \
-s \
-S
$ netstat -tanp | grep qemu
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
tcp 0 0 0.0.0.0:1234 0.0.0.0:* LISTEN 4177/./qemu-2.11.0-
$ ./gdb-7.12.1/gdb/gdb
# アーキテクチャをセット
(gdb) set architecture i8086
warning: A handler for the OS ABI "GNU/Linux" is not built into this configuration
of GDB. Attempting to continue with the default i8086 settings.
The target architecture is assumed to be i8086
# localhost で待ってる qemu に接続
(gdb) target remote localhost:1234
# program counter の値を表示
(gdb) info registers pc
pc 0x7c24 0x7c24
# レジスタの一覧の今の値
(gdb) layout reg
# break point の設定
(gdb) break *0x7c00
Breakpoint 1 at 0x7c00
# 次の break point までプログラムを実行する
(gdb) continue
Continuing.
# Step interruption ( 命令を一つずつ実行する )
(gdb) si
(int 命令を実行すると、命令内容自体は別のアドレスにあるので、いきなりアドレスが飛ぶ)
(gdb) p (char)*0x7c26
$2 = 10 '\n'
(gdb) p (char)*0x7c27
$3 = 10 '\n'
(gdb) p (char)*0x7c28
$4 = 72 'H'
(gdb) p *0x7c28
$5 = 1819043144
(gdb) p (char)*0x7c29
$6 = 101 'e'
ディスクアドレス指定方式
- ディスクのアドレスを指定する方式
- CHS と LBA が存在する
ブートの初期段階ではファイルシステムが存在しないので、ディスクの物理アドレスに対して読み書きをしなければならない。
CHS
-
Cylinder/Header/Sector の値で表す
- Cylinder: ディスクの円筒
- Header: データを読み取るヘッダ
- Sector: ブロックデバイスの最小単位
- 先頭のセクタは 0/0/1
- 一般的な FDD だと 80/2/18 かつ 512 Byte/sector なので
80 ( cylinder/header ) * 2 ( header/disk ) * 18 ( sector/cylinder ) * 512 ( Byte/sector ) /1024 ( Byte/KiB ) = 1440 ( KiB/disk )
LBA
- Logical Block Addressing
- 現在主流なアドレス指定方式
- ディスクの全てのセクタに一意な番号を割り当てる
- 最初のセクタは LBA0
- (論理的な) セクタ番号と物理的なセクタの位置の対応は、ハードディスクのコントローラに内蔵されたファームウェアが計算する
ディスクパーティション方式
MBR 方式 (Master Boot Record)
- 1980 年代から使用されている方式
- ディスクアドレス方法に CHS または LBA を使用する
- ディスクの先頭 512 バイトにデバイス情報、ブートロード用のコード及びパーティションテーブルを持つ
- パーティションは 1 エントリあたり 16 bit で表されている
MBR では、パーティションを 4 つしか切れない。
GPT 方式 (GUID Partition Table)
- MBR を置き換えるものとして、UEFI の一部として開発されたパーティショニング方式
- ディスクアドレス方式に LBA を使用する
- 冗長化のため、LBA1 と最後の LBA にパーティションテーブルを持つ
- MBR への互換性のため、先頭 LBA0 には “Protective MBR” をもつ
- パーティションエントリのサイズは GPT ヘッダで 128 * 2 ^ nByte で定義する
- パーティションのデータ格納に使用可能な LBA の範囲はヘッダに記載されている
GPT 方式の EBS ボリュームを拡張し、ファイルシステムの拡張をすると、
MBR の中身を見てみよう
$ sudo dd if=/dev/xvda of=/tmp/mbr.dump bs=512 count=1
1+0 records in
1+0 records out
512 bytes (512 B) copied, 0.000142464 s, 3.6 MB/s
$ xxd /tmp/mbr.dump
0000000: eb63 9010 8ed0 bc00 b0b8 0000 8ed8 8ec0 .c..............
0000010: fbbe 007c bf00 06b9 0002 f3a4 ea21 0600 ...|.........!..
0000020: 00be be07 3804 750b 83c6 1081 fefe 0775 ....8.u........u
0000030: f3eb 16b4 02b0 01bb 007c b280 8a74 018b .........|...t..
0000040: 4c02 cd13 ea00 7c00 00eb fe00 0000 0000 L.....|.........
0000050: 0000 0000 0000 0000 0000 0080 0100 0000 ................
0000060: 0000 0000 fffa 9090 f6c2 8074 05f6 c270 ...........t...p
0000070: 7402 b280 ea79 7c00 0031 c08e d88e d0bc t....y|..1......
0000080: 0020 fba0 647c 3cff 7402 88c2 52be 057c . ..d|<.t...R..|
0000090: b441 bbaa 55cd 135a 5272 3d81 fb55 aa75 .A..U..ZRr=..U.u
00000a0: 3783 e101 7432 31c0 8944 0440 8844 ff89 7...t21..D.@.D..
00000b0: 4402 c704 1000 668b 1e5c 7c66 895c 0866 D.....f..\|f.\.f
00000c0: 8b1e 607c 6689 5c0c c744 0600 70b4 42cd ..`|f.\..D..p.B.
00000d0: 1372 05bb 0070 eb76 b408 cd13 730d 5a84 .r...p.v....s.Z.
00000e0: d20f 83de 00be 857d e982 0066 0fb6 c688 .......}...f....
00000f0: 64ff 4066 8944 040f b6d1 c1e2 0288 e888 d.@f.D..........
0000100: f440 8944 080f b6c2 c0e8 0266 8904 66a1 .@.D.......f..f.
0000110: 607c 6609 c075 4e66 a15c 7c66 31d2 66f7 `|f..uNf.\|f1.f.
0000120: 3488 d131 d266 f774 043b 4408 7d37 fec1 4..1.f.t.;D.}7..
0000130: 88c5 30c0 c1e8 0208 c188 d05a 88c6 bb00 ..0........Z....
0000140: 708e c331 dbb8 0102 cd13 721e 8cc3 601e p..1......r...`.
0000150: b900 018e db31 f6bf 0080 8ec6 fcf3 a51f .....1..........
0000160: 61ff 265a 7cbe 807d eb03 be8f 7de8 3400 a.&Z|..}....}.4.
0000170: be94 7de8 2e00 cd18 ebfe 4752 5542 2000 ..}.......GRUB .
0000180: 4765 6f6d 0048 6172 6420 4469 736b 0052 Geom.Hard Disk.R
0000190: 6561 6400 2045 7272 6f72 0d0a 00bb 0100 ead. Error......
00001a0: b40e cd10 ac3c 0075 f4c3 0000 0000 0000 .....<.u........
00001b0: 0000 0000 0000 0000 0dbb 0a00 0000 8020 ...............
00001c0: 2100 83fe ffff 0008 0000 dff7 7f0c 0000 !...............
00001d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00001e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00001f0: 0000 0000 0000 0000 0000 0000 0000 55aa ..............U.
# 逆アセンブル
$ objdump -D -b binary -m i8086 -M addr16.data16 /tmp/mbr.dump > /tmp/mbr.s
$ cat /tmp/mbr.s
/tmp/mbr.dump: file format binary
Disassembly of section .data:
00000000 <.data>:
0: eb 63 jmp 0x65
2: 90 nop
3: 10 8e d0 bc adc %cl,-0x4330(%bp)
7: 00 b0 b8 00 add %dh,0xb8(%bx,%si)
b: 00 8e d8 8e add %cl,-0x7128(%bp)
f: c0 fb be sar $0xbe,%bl
12: 00 7c bf add %bh,-0x41(%si)
15: 00 06 b9 00 add %al,0xb9
19: 02 f3 add %bl,%dh
1b: a4 movsb %ds:(%si),%es:(%di)
1c: ea 21 06 00 00 ljmp $0x0,$0x621
21: be be 07 mov $0x7be,%si
24: 38 04 cmp %al,(%si)
26: 75 0b jne 0x33
28: 83 c6 10 add $0x10,%si
2b: 81 fe fe 07 cmp $0x7fe,%si
2f: 75 f3 jne 0x24
31: eb 16 jmp 0x49
33: b4 02 mov $0x2,%ah
35: b0 01 mov $0x1,%al
37: bb 00 7c mov $0x7c00,%bx
3a: b2 80 mov $0x80,%dl
3c: 8a 74 01 mov 0x1(%si),%dh
3f: 8b 4c 02 mov 0x2(%si),%cx
42: cd 13 int $0x13
44: ea 00 7c 00 00 ljmp $0x0,$0x7c00
49: eb fe jmp 0x49
...
5b: 80 01 00 addb $0x0,(%bx,%di)
5e: 00 00 add %al,(%bx,%si)
60: 00 00 add %al,(%bx,%si)
62: 00 00 add %al,(%bx,%si)
64: ff (bad)
65: fa cli
66: 90 nop
67: 90 nop
68: f6 c2 80 test $0x80,%dl
6b: 74 05 je 0x72
6d: f6 c2 70 test $0x70,%dl
70: 74 02 je 0x74
72: b2 80 mov $0x80,%dl
74: ea 79 7c 00 00 ljmp $0x0,$0x7c79
79: 31 c0 xor %ax,%ax
7b: 8e d8 mov %ax,%ds
7d: 8e d0 mov %ax,%ss
7f: bc 00 20 mov $0x2000,%sp
82: fb sti
83: a0 64 7c mov 0x7c64,%al
86: 3c ff cmp $0xff,%al
88: 74 02 je 0x8c
8a: 88 c2 mov %al,%dl
8c: 52 push %dx
8d: be 05 7c mov $0x7c05,%si
90: b4 41 mov $0x41,%ah
92: bb aa 55 mov $0x55aa,%bx
95: cd 13 int $0x13
97: 5a pop %dx
98: 52 push %dx
99: 72 3d jb 0xd8
9b: 81 fb 55 aa cmp $0xaa55,%bx
9f: 75 37 jne 0xd8
a1: 83 e1 01 and $0x1,%cx
a4: 74 32 je 0xd8
a6: 31 c0 xor %ax,%ax
a8: 89 44 04 mov %ax,0x4(%si)
ab: 40 inc %ax
ac: 88 44 ff mov %al,-0x1(%si)
af: 89 44 02 mov %ax,0x2(%si)
b2: c7 04 10 00 movw $0x10,(%si)
b6: 66 8b 1e 5c 7c mov 0x7c5c,%ebx
bb: 66 89 5c 08 mov %ebx,0x8(%si)
bf: 66 8b 1e 60 7c mov 0x7c60,%ebx
c4: 66 89 5c 0c mov %ebx,0xc(%si)
c8: c7 44 06 00 70 movw $0x7000,0x6(%si)
cd: b4 42 mov $0x42,%ah
cf: cd 13 int $0x13
d1: 72 05 jb 0xd8
d3: bb 00 70 mov $0x7000,%bx
d6: eb 76 jmp 0x14e
d8: b4 08 mov $0x8,%ah
da: cd 13 int $0x13
dc: 73 0d jae 0xeb
de: 5a pop %dx
df: 84 d2 test %dl,%dl
e1: 0f 83 de 00 jae 0x1c3
e5: be 85 7d mov $0x7d85,%si
e8: e9 82 00 jmp 0x16d
eb: 66 0f b6 c6 movzbl %dh,%eax
ef: 88 64 ff mov %ah,-0x1(%si)
f2: 40 inc %ax
f3: 66 89 44 04 mov %eax,0x4(%si)
f7: 0f b6 d1 movzbw %cl,%dx
fa: c1 e2 02 shl $0x2,%dx
fd: 88 e8 mov %ch,%al
ff: 88 f4 mov %dh,%ah
101: 40 inc %ax
102: 89 44 08 mov %ax,0x8(%si)
105: 0f b6 c2 movzbw %dl,%ax
108: c0 e8 02 shr $0x2,%al
10b: 66 89 04 mov %eax,(%si)
10e: 66 a1 60 7c mov 0x7c60,%eax
112: 66 09 c0 or %eax,%eax
115: 75 4e jne 0x165
117: 66 a1 5c 7c mov 0x7c5c,%eax
11b: 66 31 d2 xor %edx,%edx
11e: 66 f7 34 divl (%si)
121: 88 d1 mov %dl,%cl
123: 31 d2 xor %dx,%dx
125: 66 f7 74 04 divl 0x4(%si)
129: 3b 44 08 cmp 0x8(%si),%ax
12c: 7d 37 jge 0x165
12e: fe c1 inc %cl
130: 88 c5 mov %al,%ch
132: 30 c0 xor %al,%al
134: c1 e8 02 shr $0x2,%ax
137: 08 c1 or %al,%cl
139: 88 d0 mov %dl,%al
13b: 5a pop %dx
13c: 88 c6 mov %al,%dh
13e: bb 00 70 mov $0x7000,%bx
141: 8e c3 mov %bx,%es
143: 31 db xor %bx,%bx
145: b8 01 02 mov $0x201,%ax
148: cd 13 int $0x13
14a: 72 1e jb 0x16a
14c: 8c c3 mov %es,%bx
14e: 60 pusha
14f: 1e push %ds
150: b9 00 01 mov $0x100,%cx
153: 8e db mov %bx,%ds
155: 31 f6 xor %si,%si
157: bf 00 80 mov $0x8000,%di
15a: 8e c6 mov %si,%es
15c: fc cld
15d: f3 a5 rep movsw %ds:(%si),%es:(%di)
15f: 1f pop %ds
160: 61 popa
161: ff 26 5a 7c jmp *0x7c5a
165: be 80 7d mov $0x7d80,%si
168: eb 03 jmp 0x16d
16a: be 8f 7d mov $0x7d8f,%si
16d: e8 34 00 call 0x1a4
170: be 94 7d mov $0x7d94,%si
173: e8 2e 00 call 0x1a4
176: cd 18 int $0x18
178: eb fe jmp 0x178
17a: 47 inc %di
17b: 52 push %dx
17c: 55 push %bp
17d: 42 inc %dx
17e: 20 00 and %al,(%bx,%si)
180: 47 inc %di
181: 65 6f outsw %gs:(%si),(%dx)
183: 6d insw (%dx),%es:(%di)
184: 00 48 61 add %cl,0x61(%bx,%si)
187: 72 64 jb 0x1ed
189: 20 44 69 and %al,0x69(%si)
18c: 73 6b jae 0x1f9
18e: 00 52 65 add %dl,0x65(%bp,%si)
191: 61 popa
192: 64 00 20 add %ah,%fs:(%bx,%si)
195: 45 inc %bp
196: 72 72 jb 0x20a
198: 6f outsw %ds:(%si),(%dx)
199: 72 0d jb 0x1a8
19b: 0a 00 or (%bx,%si),%al
19d: bb 01 00 mov $0x1,%bx
1a0: b4 0e mov $0xe,%ah
1a2: cd 10 int $0x10
1a4: ac lods %ds:(%si),%al
1a5: 3c 00 cmp $0x0,%al
1a7: 75 f4 jne 0x19d
1a9: c3 ret
...
1b6: 00 00 add %al,(%bx,%si)
1b8: 0d bb 0a or $0xabb,%ax
1bb: 00 00 add %al,(%bx,%si)
1bd: 00 80 20 21 add %al,0x2120(%bx,%si)
1c1: 00 83 fe ff add %al,-0x2(%bp,%di)
1c5: ff 00 incw (%bx,%si)
1c7: 08 00 or %al,(%bx,%si)
1c9: 00 df add %bl,%bh
1cb: f7 7f 0c idivw 0xc(%bx)
...
1fe: 55 push %bp
1ff: aa stos %al,%es:(%di)
パーティションサイズを見てみる。
00001c0: 2100 83fe ffff 0008 0000 dff7 7f0c 0000
エンディアン変換
0c 7f f7 df
-> 209713119 sector
209713119 * 512 = 107373116928
$ sudo fdisk -l /dev/xvda1
Disk /dev/xvda1: 107.4 GB, 107373116928 bytes, 209713119 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
ブートローダ
- OS をメモリにロードし、制御を移すプログラム
- MBR のコードが 0x7c00 にロードされ、開始される
- カーネルはファイルシステム上にファイルとして保存されている
- BIOS はファイルシステムを解釈できないため、直接カーネルを読み出せない
- ブートローダがファイルシステムのドライバをロードし、カーネルを呼び出す
ブートローダの種類
- LILO: EFI をサポートする ELILO が開発されている
- GRUB: LILO に変わり現在多くのディストリビューションで使用されているブートローダ
- SYSLINUX: 様々な種類のデバイス、及びファイルシステムに対応する、複数のコンポーネントから構成される
GRUB 2 の処理の流れ
-
Stage 1:
- MBR に存在する
- Stage 1.5 のプログラムをメモリにロードし、制御を移す
-
Stage 1.5:
- MBR から最初のパーティションまでの領域に存在する
- コンフィグファイル及びファイルシステムドライバをロードする
-
Stage 2:
- ファイルシステムの /boot/grub 配下のものをロード
grub> set root='hd0,msdos1'
grub> linux16 /vmlinuz-3.10.0-693.el7.x86_64 root=UUID=7ad23b0a-fa52-4015-b9f1-a
4e3c6ed2267 ro crashkernel=auto console=ttyS0 LANG=ja_JP.UTF-8
grub> initrd16 /initramfs-3.10.0-693.el7.x86_64.img
grub> boot