Linux: процесс загрузки, часть #1 – BIOS и MBR

 

Введение

В общих чертах – загрузка Linux разбита на несколько шагов:

  1. BIOS
  2. MBR
  3. GRUB 2 (bootloader)
  4. Linux Kernel

В этой части:

  1. BIOS
  2. MBR 
    1. Описание MBR
    2. Содержимое MBR
    3. Disk signature
    4. VBR

BIOS

После нажатия кнопки питания на ПК или ноубуке – материнская плата подаёт сигнал блоку питания ПК. Блок питания подаёт напряжение на аппаратные ресурсы компьютера и возвращает материнской плате power-good сигнал, после чего та пытается запустить CPU. Тот, в свою очередь – сбрасывает все текущие значения с регистров и заполняет их значениями по умолчанию, а затем обращается к памяти BIOS-а для получения первой инструкции для выполнения.

BIOS возвращает CPU указание на запуск POST, который выполняет проверку всех подключенных аппаратных средств машины, после чего начинается непосредственно процесс запуска самой операционной системы.

Для её загрузки – BIOS проверяет свои настройки в поисках списка устройств, с которых можно загрузиться.

После того, как устройство для загрузки определено (из настроек, или после нажатия F12 и указания диска вручную) – BIOS пытается считать первый сектор (512 байт), т.е. непосредственно MBR, который находится по адресу «цилиндр 0, головка 0, сектор 1», и помещает его в область памяти по физическому адресу 0x7C00. Далее BIOS проверяет последние два байта сектора, которые должны заканчиваться на 0x55 и 0xaa, которые указывают на то, что раздел является загрузочным, и если это так – то передаёт управление загрузчику.

MBR

Описание MBR

Master Boot Record располагается в первых 512 байтах первого сектора загрузочного диска. Кроме таблицы разделов – он содержит в себе загрузчик и так называемое “магическое число” (или “сигнатура” диска, см. ниже).

Непосредственно загрузчик занимает бОльшую часть MBR – 440 байт, который так же называется основным (primary) загрузчиком. Этот загрузчик считывает таблицу разделов в MBR (следующие 64 байта после кода загрузчика) и ищет активный (bootable) раздел, после чего либо загружает ядро ОС, либо запускает вторичный (secondary) загрузчик с VBR (Volume Boot Record) сектора этого раздела, который, в свою очередь – начинает процесс загрузки самого ядра системы.

Последние два байта (0x55 и 0xaa) MBR содержат т.н. “магическое число” – 0xAA55, которые указывают BIOS-у на то, что данный раздел является загрузочным. Если это число не найдено или имеет неверное значение – вы получите сообщение о том, что BIOS не может найти bootable device.

Содержимое MBR

Для того, что бы прочитать содержимое MBR – можно создать его дамп.

Например, на ноутбуке имеется два диска:

# lsblk -dn
sda    8:0    0 596,2G  0 disk 
sr0   11:0    1  1024M  0 rom

sr0 тут – это привод компакт-дисков, а sda – жесткий диск.

Создаём дамп первых 512 байт диска sda:

# dd if=/dev/sda of=/tmp/mbr.bin bs=512 count=1
1+0 records in
1+0 records out
512 bytes (512 B) copied, 0,0002367 s, 2,2 MB/s

Прочитать его можно с помощью file:

# file -k /tmp/mbr.bin 
/tmp/mbr.bin: x86 boot sector; 
partition 1: ID=0x83, starthead 32, startsector 2048, 4194304 sectors; 
partition 2: ID=0x82, starthead 53, startsector 4196352, 33554432 sectors; 
partition 3: ID=0x83, starthead 223, startsector 37750784, 1048576000 sectors; 
partition 4: ID=0x7, active, starthead 254, startsector 1086326784, 163934208 sectors DOS executable (COM), boot code

Обратите внимание на partition 4 у него есть отметка “active” –  это загрузочный диск sda4 в результатах fdisk (там Windows):

# fdisk  -l /dev/sda

Disk /dev/sda: 640.1 GB, 640135028736 bytes
255 heads, 63 sectors/track, 77825 cylinders, total 1250263728 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
Disk identifier: 0x6fa60981

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1            2048     4196351     2097152   83  Linux
/dev/sda2         4196352    37750783    16777216   82  Linux swap / Solaris
/dev/sda3        37750784  1086326783   524288000   83  Linux
/dev/sda4   *  1086326784  1250260991    81967104    7  HPFS/NTFS/exFAT

Дамп MBR можно так же просмотреть с помощью hexdump:

# hexdump -C /tmp/mbr.bin 
00000000  eb 63 90 d0 bc 00 7c 8e  c0 8e d8 be 00 7c bf 00  |.c....|......|..|
00000010  06 b9 00 02 fc f3 a4 50  68 1c 06 cb fb b9 04 00  |.......Ph.......|
...
000001d0  71 05 82 df 72 2d 00 08  40 00 00 00 00 02 00 df  |q...r-..@.......|
000001e0  73 2d 83 b6 12 24 00 08  40 02 00 00 80 3e 80 fe  |s-...$..@....>..|
000001f0  ff ff 07 fe ff ff 00 08  c0 40 00 70 c5 09 55 aa  |.........@.p..U.|
00000200

(хорошее описание hexdump есть вот тут>>>)

Схема MBR:

mbr_1

Более наглядный вариант:

linux_load_1

Т.е., дамп MBR  вэтом примере представляет собой:

# hexdump /tmp/mbr.bin  -C -n 440 
00000000  eb 63 90 d0 bc 00 7c 8e  c0 8e d8 be 00 7c bf 00  |.c....|......|..|
00000010  06 b9 00 02 fc f3 a4 50  68 1c 06 cb fb b9 04 00  |.......Ph.......|
....
000001a0  64 00 20 45 72 72 6f 72  0d 0a 00 bb 01 00 b4 0e  |d. Error........|
000001b0  cd 10 ac 3c 00 75 f4 c3                           |...<.u..|
000001b8

Тут показаны первые 440 байт – код загрузчика.

Далее следует подпись диска (Disk Identifier), 4 байта (-s, offset, смещение – читать начиная с 440 байта, -nlength – сколько байт прочитать):

# hexdump /tmp/mbr.bin  -C -s 440 -n 4
000001b8  81 09 a6 6f                                       |...o|
000001bc

Таблица разделов (4 по 16 байт == 64 байта):

# hexdump /tmp/mbr.bin  -C -s 446 -n 64
000001be  00 20 21 00 83 35 70 05  00 08 00 00 00 00 40 00  |. !..5p.......@.|
000001ce  00 35 71 05 82 df 72 2d  00 08 40 00 00 00 00 02  |.5q...r-..@.....|
000001de  00 df 73 2d 83 b6 12 24  00 08 40 02 00 00 80 3e  |..s-...$..@....>|
000001ee  80 fe ff ff 07 fe ff ff  00 08 c0 40 00 70 c5 09  |...........@.p..|
000001fe

И подпись о том, что диск загрузочный (“магическое число”) – два последних байта:

# hexdump /tmp/mbr.bin  -C -s 510 
000001fe  55 aa                                             |U.|
00000200

Disk signature

Disk signature (так же Disk Identifier, Disk ID) представляет собой 32-х битное (4 байта) число и относится к жесткому диску, а не его разделам (в отличии от UUID/GUID). Disk Identifier/Disk Signature генерируется во время создания MBR и таблицы разметки диска.

Получить его можно с помощью того же fdisk:

# fdisk -lu /dev/sda | grep ident
Disk identifier: 0x6fa60981

А найти в дампе MBR – так:

# hexdump /tmp/mbr.bin -s 440 -n 4
00001b8 0981 6fa6

Возвращаясь к загрузке.

BIOS пытается считать первый сектор (512 байт), т.е. непосредственно MBR, который находится по адресу «цилиндр 0, головка 0, сектор 1», и помещает его в область памяти по физическому адресу 0x7C00.

Как мы увидели – BIOS помещает в память начальный загрузчик, который находится в первых 440 байтах, и запускает его выполнение.

Как правило (для Linux) – используется GRUB2, но имеются и другие системы, см. в Wiki (интересно, что в английской версии нет такой удобной таблицы).

VBR

GRUB и Linux не используют VBR (Volume Boot Record), однако – она требуется для некоторых систем, например – Windows.

Для этого – Windows добавляет VBR в первый сектор своего загрузочного раздела (отедльный 100MB раздел у Windows 7). Далее загрузчик GRUB, при выборе загрузки Windows, выполняет код из VBR, который содержит в себе инструкции по запску Windows. Подробнее – можно почитать тут>>>.

Продолжение (GRUB и iniramfs) пока в черновиках.

Ссылки по теме (всё подряд):

Arch boot process

Kernel booting process. Part 1.

6 Stages of Linux Boot Process

The System Boot Process Explained

Easy way to read mbr

The boot process in closer look

Analysing the Master Boot Record (MBR) with a hex editor (Hex Workshop)

An example of Master Boot Record

GRUB 2 bootloader – Full tutorial

about extracting grub2 files from mbr