Linux カルテット ( 2 ) ~ ブートの部 ~

November 20, 2017

Boot Sequence

登場人物

  • ファームウェア ( BIOS/UEFI )
  • ブートローダ ( GRUB )
  • 初期 RAM ディスク ( initramfs)

など

概要

BIOS からデーモンプロセスの起動が完了するまで。

流れ

BIOS -> ブートローダ -> Linux カーネル -> 初期 RAM ディスク -> スタートアッププログラム

  1. CPU が BIOS のコードを実行し、ハードウェアの初期化を行う
  2. ブートローダがディスクを読み取り Linux カーネルに制御を移す
  3. カーネルが OS の初期化を行う
  4. 初期 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                                     ..

x86 で使える命令

  • 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 レジスタの値を用いる )

0x10 の定義

上記の命令を実装してくれているのが 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

 © 2023, Dealing with Ambiguity