Структура Master Boot Record

Дата: 30/03/06;  Автор: Mikae; 


Задача MBR (Master Boot Record) предельно проста. Однако, чтобы лучше понять как происходит загрузка компьютера и что именно находится в компетенции MBR надо заглянуть "чуть-чуть назад" и "чуть-чуть вперед".

Итак, при включении компьютера управление получает BIOS. BIOS производит настройку и программирование устройств на самом низком уровне -- контроллеров и т.п. Для нас самым интересным и важным, пожалуй, является тот факт, что BIOS настраивает т.н. "вектор прерываний" -- область памяти, содержащую таблицу, по которой процессор сопоставляет номер прерывания и адрес процедуры его (прерывания) обработки. В том числе происходит и назначение уже известного нам обработчика 0x13ого прерывания. Подробнее о действиях BIOSа в процессе загрузки можно прочитать тут.
Интересно отметить, что процессоры x86 начинают выполнение инструкций в реальном режиме, с адреса FFFF:0, оставляя всего лишь 16 байт на инструкцию. Соответственно, разместить там возможно всего несколько инструций. Наиболее верятно, это будет инструкция "jmp", после выполнения которой регистр счетчика инструкций (IP/EIP) должен указать куда-либо "пораньше". К сожалению, я так и не понял, каким образом происходит отображение кода, записанного в микросхеме BIOSа в память. Соответственно, вопрос, как и кем интсрукция jmp, а также код, на который она прыгнет  будут отображены в память остается открытым.

После того, как все готово к запуску системы BIOS загружает "первый" сектор винчестера в память, по адресу 0x7C00 и передает туда управление (jmp). Почему я взял слово "первый" в кавычки? Потому что сейчас довольно сложно сказать о физическом расположении этого сектора. Если смотреть на адрес сектора с т.з. LBA -- это будет нулевой сектор. Если с т.з. *CHS/AssistedLBA -- головка 0, цилиндр 0, сектор 1. Впрочем, это даже и не важно. Главное понимать, что BIOS считает с винчестера в память определенный и заранее известный сектор, после чего передаст ему управление. Нетрудно догадаться, что именно там и находится MBR.

Небольшое лирическое отступление.
А для чего же нужна MBR?

Винчестеры по некоторым причинам иногда необходимо разбивать на разделы, или "партиции". Например, если мы хотим установить две ОС на один винчестер необходимо разделить его между ними. Тогда, каждая ОС может разместить свою файловую систему на одном (или нескольких) разделах, не повреждая данных файловой системы другой ОС. Собственно в MBR хранится таблица разделов, а так же код, обрабатывающий таблицу и выполняющий на основании обработки некоторые действия. Необходимо отметить одно из важнейших понятий MBR -- активный раздел. Активный раздел это раздел, который содержит код, необходимый для продолжения загрузки системы. Как правило, активным можеть быть только один раздел. Скорее всего, это будет раздел с загрузчиком ОС, или загрузочный менеджер, типа LILO или GRUB (в случае, когда на винчестере имеется несколько ОС). Собственно, все действия кода MBR сводятся к поиску активного раздела в таблице разделов, загрузке первых его 512 байт в память и передаче им управления.

Теперь, имея представление о том, для чего нужна MBR и что она делает можно разобрать ее структуру более детально.
Начнем с того, что MBR занимает ровно 512 байт. Из них 64 байта отведено под таблицу разделов, 2 байта -- сигнатура MBR и 446 -- код, обрабатывающий таблицу разделов. На описание одного раздела отводится 16 байт. Соответственно, максимальное число разделов, которые возможно описать в MBR равно 4. Все эти данные скомпонованы в MBR таким образом:

Таблица 1.
Смещение Размер Описание
0 446 Исполняемый код MBR.
446 16 Элемент таблицы разделов №1
462 16 Элемент таблицы разделов №2
478 16 Элемент таблицы разделов №3
494 16 Элемент таблицы разделов №4
510 2 Сигнатура MBR

Каждый элемент таблицы разделов описывает "физическое" размещение раздела -- его границы. А также признак активности, количество секторов (не байт!) перед разделом и размер раздела (тоже в секторах). Отметим, что порядок следования элементов в таблице может не совпадать с физическим расположением описываемых ими разделов. Например, раздел, описанный в первом элементе таблицы может физически располагаться "в конце" пластины и т.д. Структура элемента таблицы разделов представляет собой следующее:

Таблица 2.
Смещение Размер Описание
0 1 Признак активности. Определяет, является ли раздел активным (0x80) или нет (0x0)
1 3 Координаты начала раздела. Хранятся в формате CHS. Первый байт описывает номер головки, 6 младших бит второго байта описывают номер сектора и 2 старших бит второго байта и 8 бит третьего -- номер цилиндра.
4 1 Идентификатор файловой системы. Несмотря на название это поле не обязательно описывает ФС, для которой предназначен раздел. Идентификатор может описывать тип раздела, например, "LBA VFAT (DOS Extended)", или "DOS Extended". Играет весьма важную роль в определении того, какие поля элемента таблицы разделов должны быть использованы в определении границ раздела. (Подробности ниже.)
5 3 Координаты конца раздела. Формат в точности соответствует формату поля "Координаты начала раздела".
8 4 Количество секторов (не байт!), предшествующее разделу.
12 4 Количество секторов (не байт!), занимаемое разделом.


Теперь, имея всю необходимую информацию рассмотрим картину работы кода MBR в целом:
  1. BIOS заканчивает подготовку оборудования, считывает MBR с устройства, указанного в настройках BIOSа как загрузочное, размещает ее в памяти по линейному адресу 0x7C00 и передает ей управление (jmp). Перед передачей управления MBR BIOS должен проверить ее сигнатуру и сообщить о некорректности MBR если сигнатура не равна 0x55AA. (Однако, не все BIOSы это делают.)

  2. Код MBR (первые 446 байт) разбирает таблицу разделов в поисках активного (0x80) раздела.

  3. Если активный раздел не найден, код должен вывести соответсвующее сообщение и остановиться. Опять же, не все MBR это делают.
    Если же активный раздел присутствует, то MBR выполнит следующие шаги:
    • Переместит себя "вниз", на линейный адрес 0x600.
    • Считает первые 512 байт активного раздела (загрузочный сектор файловой системы) по линейному адресу 0x7C00 (т.е. на свое предыдущее место).
    • Проверит сигнатуру загруженного сектора. Вот тут вот тоже когда как, по-моему...
    • Передаст управление в загрузочный сектор файловой системы (jmp).
      Начиная с этого момента действия зависят от ОС, установленной на активном разделе.

В общем, ничего особо сложного и сверхестественного MBR не выполняет. Отметим несколько ключевых моментов, которые, время от времени, вызывают небольшие недоразумения.
Немного технических интересностей.
  1. По каким-то неизвестным мне причинам, дорожка винчестера, на которой размещается MBR, никогда не может быть использована каким-либо разделом. Т.е. мы всегда имеем 62 свободных и никем не занятых сектора, находящихся сразу за MBR. Причем, эти сектора всегда будут свободны, независимо от разметки винчестера. Подозреваю, что они оставлены для возможности расширения MBR, но точно не уверен. Это пространство (31,5 КБ -- весьма прилично для кода на ассемблере) запросто может быть использовано хакерами, желающими спрятать данные. Файловыми системами они повреждены не будут, и, более того, файловые системы даже и не подозревают об их существовании. Слышал, что некоторые вирусы активно используют эту дорожку. Изначально (при отсутствии вирусов :) ) эти 62 сектора заполнены нулями.

  2. Если внимательно присмотреться к таблице 2, то можно увидеть, что координаты начала и конца раздела хранятся в формате CHS и на них стандартно отводится 3 байта. А это опять приводит нас к ограничению 8 ГБ. К счастью, помимо этих значений, таблица содержит избыточные данные -- количество секторов перед разделом и размер раздела в секторах. Именно они и используются для определения расположения раздела в том случае, если его размер или позицию не возможно описать в формате CHS. В этом случае в поля "начало раздела" и "конец раздела" (CHS) просто записываются максимальные значения. Здесь надо быть осторожным: если раздел будет использоваться ОС, которая работает с винчестером через старый интерфейс int0x13 (например, DOS), то она будет явно удивлена столь странной геометрией. (И возможно испортит данные других ОС). Для различения разделов, расположение которых может быть описано в формате CHS от тех, чье не может, используется идентификатор файловой системы. Например, 05 -- "DOS Extended" (координаты корректны!) и 0F "LBA VFAT (DOS Extended)"  (координаты не корректны). Т.о. ОС может определить, как ей высчитывать расположение раздела.

  3. Максимальный размер раздела сейчас. Собственно, это ограничение вытекает из предыдущего пункта: Современные ОС определяют расположение раздела по двум последним полям элемента таблицы разделов. А это значит, что максимальный размер раздела не может быть более 2^41 байт (2 террабайта), а также его расположение не может быть "дальше" этого значения. Соответственно, когда винчестеры достигнут этих размеров нас ждут очередные изменения в ПО. Думаю, что особенно сильно изменится формат MBR.

Полезные ссылки:
  http://www.mossywell.com/boot%2Dsequence
  http://www.tldp.org/HOWTO/Large-Disk-HOWTO.html
  FreeBSD: ручная разметка диска