logo search
MBR под микроскопом

Mbr под микроскопом. Альтернативные методы загрузки.

Александр Куприн. e-mail: ru_classic@mail.ru

Цель этой статьи объяснить принципы функционирования такого элемента в ПК как MBR (master boot record - главная загрузочная запись) и показать как можно самому поучаствовать в процессе загрузки. Думаю, это будет интересно тем, кто хочет знать более полно принципы и методы, согласно которым происходит загрузка операционной системы на ПК. К сожалению, понимание этого материала требует знаний (хотя бы минимальных) ассемблера для x86, знаний о логической структуре жестких дисков (отличать сторону от трека, трек от сектора и иметь представление о структуре partition table).

Впервые, столкнуться с более детальным изучением MBR мне пришлось в 1996 году, когда встал вопрос об одновременном использовании на одном ПК MS DOS 6.22 и MS Windows'95. Конечно, можно было бы воспользоваться тем сервисом, который предлагал Windows'95 при установке поверх MS DOS 6.22 - F8 при загрузке и выбор "Previous version MS-DOS". У этого метода был один очевидный недостаток, - обе операционные системы делили общее дисковое пространство или, по крайней мере, первый логический диск, т.к. он должен был быть отформатирован в формате FAT16 (для того, чтобы MS DOS могла увидеть этот диск, а то и вообще загрузиться). Следующие логические диски, если они были, могли быть отформатированы под FAT32, и в этом случае MS DOS их не увидит. Замечательно, но не очень. Хотелось выделить для каждой системы свою "комнатушку" и чтобы они "жили" в них и не мешали друг другу. И последняя причина, - я не знал тогда об этой возможности.

Вооружившись программой diskedit.exe из набора Norton Utility я скопировал MBR в файл (всего каких-то 512 байт) и скормил его sr.exe (Sourcer 5.1 - дизассемблер для MS DOS). Полученный при этом asm-файл я внимательно изучил и добавил к нему комментарии для того, чтобы в нем можно было не заблудиться. При дизассемблировании я указал формат выходного файла совместимый с tasm 3.2, т.к. именно этот ассемблер у меня был под рукой. Файл я назвал mbr_std.asm (см. подкаталог _mbr_std\). Для его сборки я написал маленький bat-файл mbr_std.bat и получил com-файл размером в 219 байт. Вы можете спросить, - а где остальные 293 байта (512 - 219 = 293)? Всё дело в том, что MBR состоит из двух частей: программного кода и данных. Данные занимают последние 66 байт этого сектора: 64 байт информация под 4-е раздела по 16 байт и два последних байта, которые содержат специальную сигнатуру (в шестнадцатеричном виде) 55 AA. Всё остальное в нашем случае - это нули, которые не несут никакой информативной нагрузки. Комментарии, которые я поместил в mbr_std.asm достаточно ясно объясняют что, зачем и как? Если вам это интересно, изучите этот файл, - не пожалеете. Если же, это делать лениво :), и вы хотите продолжить читать дальше, то вот вкратце алгоритм работы MBR (обращаю ваше внимание на то, что этот алгоритм применялся MS DOS 6.22, Windows прописывает несколько изменённый вариант загрузчика, но основные принципы загрузки те же):

Теперь я знал, что делает MBR, и я знал, что буду делать я. Дело в том, что за пару месяцев до этого я видел как один мой знакомый "пальцами" грузил две операционки с двух разных логических дисков. При этом он сделал их оба primary с помощью diskedit.exe, "насильно" указав в MBR, что это BIGDOS - код 06h, т.к. программа fdisk.exe не позволяет создавать более одного primary раздела. Перезагрузился с дискеты и отформатировал их с ключом /s. А потом при помощи diskedit.exe менял признак активного раздела. После этого перезагружал компьютер, и компьютер грузил систему с активного раздела. При этом происходил свопинг логических дисков, тот, что был C становился D и наоборот, т.к. MS DOS и Windows ставят первым диском загрузочный.

Итак, теперь мне надо было сделать две вещи: создать два primary раздела и добавить в код MBR возможность выбора одного из них в качестве загрузочного. Для начала я решил изменить код MBR так, чтобы он делал то же, что и мой приятель. Помня о том, что прерывание 16h (обработка ввода с клавиатуры, прошита в BIOS-е) уже доступно в момент включения ПК, то я добавил сообщение 'Your choice: [M]sDos or [W]in95?' и заставил проверять программу какую из клавиш нажал пользователь [M] или [W] и в зависимости от этого менять активный раздел и записывать MBR обратно на жесткий диск (int 13h), после чего запускать на выполнение тот сектор, на который указывал активный раздел. Исходник этой программы лежит в подкаталоге _mbr_2os\. Размер бинарника составляет 355 байт, что не превышает допустимого (512 - 66 = 446). Хотя если быть точным до конца, то этот размер еще чуть меньше, т.к. Windows'95/98/NT пишет в MBR в диапазоне 1B0h-1BDh служебную информацию. Какую? Не знаю, но факт остается фактом. По крайней мере, после работы администратора дисков (Windows NT 4.0) в этот диапазон пишется несколько байт. Примерно там же что-то прописывает и Windows'9x, но после выполнения какой программы - не знаю. "Средством доставки" нового кода MBR на место старого послужил тот же diskedit.exe (очень удачная и удобная программа, если конечно знаешь, что делаешь). Перезагружаю компьютер и : о, чудо! Вижу сообщение 'Your choice:'. Проверяю. Работает. Класс.

Что дальше? Идея правильная и работает. Через пару месяцев после этого возникла необходимость в том, чтобы загружать уже три операционки на одной машине. При этом одна из них - MS DOS, две других Windows'95 - одна для работы, другая для тестовых установок программ (отладка инсталляций и т.д.). При этом уже нужно было сделать так, чтобы одна операционка не видела другую (если это необходимо). На мысль о том, как это сделать меня навёл тот факт, что MS DOS не видит диски с FAT32, поэтому я решил найти такой код раздела, чтобы его не знал ни MS DOS ни Windows'95. Таким кодом оказался 10h. Для чего он зарезервирован не знаю, так и не нашел описание на этот код, но что я знаю точно, так это то, что раздел с таким кодом не понимают следующие операционные системы: MS DOS, Windows'95/98/NT, Linux. Хотя Linux, если ему сказать при монтировании, что это за тип раздела, - его увидит, однако, на этапе инсталляции этот раздел проигнорирует.

Теперь задача стояла следующая: в зависимости от выбора одни разделы помечать кодом 10h, а другие реальными значениями. Засунуть всё это в 432 байта уже не представлялось возможным и пришлось сделать следующее: после загрузки MBR загружает в память еще несколько секторов, которые содержат остальной код и передает ему управление. В этих секторах должна находится оставшаяся часть программы, которая позволит сделать выбор и результат возвратит коду MBR. Но где взять эти лишние сектора? А вот где: 62 сектора (это относится к IDE винчестерам, как это реализовано в SCSI - не знаю), которые расположены следом за MBR, официально никем не используются, кроме вирусов ? (как правило). Поэтому я решил занять несколько секторов для своих целей, начиная с 50. Идея оказалась живучей. (Примечание. Если уж быть точным, то эти 62 сектора можно увеличить до такого размера, который вам нужен, если вы захотите "засунуть" туда что-то глобальное. Для этого придется в partition table прописать пальцами новую геометрию логического диска. По умолчанию, разделы начинаются с начала трека и т.к. в треке 63 сектора, то у нас появляется свободных 63 - 1 = 62 сектора.).

Теперь программа состояла из двух частей. Первую часть, модифицированный MBR, который вызывает второй кусок программы с 50 сектора, достаточно было написать один раз и забыть о ней (см. подкаталог _mbr_3os\, файл sec_00.asm). Второй файл (sec_50.asm, комментариями, к сожалению уже не блещет ?) представляет собой программу по обработке данных, вводимых пользователем и передаче их обратно программе sec_00.asm (звучит немного коряво, но надеюсь понятно, о чём речь). Программа sec_50.asm работает с данными partition, которые были загружены при старте по адресу 0000h:0600h. И когда выбор окончательно сделан, то измененный partition будет записан sec_00.asm. В sec_50.asm первой строкой стоит debug_mode = 1, эта переменная используется на этапе компиляции для отладочного режима. Если она равна 0, то откомпилированная программа будет обращаться к адресам в диапазоне 0000h:0600h- 0000h:07FFh, если же она равна 1, то используется переменная partition, и программа будет обращаться к ней и программу можно спокойно отладить не вызывая крах системы. В подкаталоге _mbr_3os\ лежит откомпилированная в отладочном режиме программа sec_50.com. Если интересно запустите её. Лучше всего находится в текстовом режиме, - я объясню позже почему. Вы увидите три диска. Сделать видимым диск для других можно при помощи клавиши "+" на дополнительной цифровой клавиатуре. Клавиша "-" делает его невидимым. Чтобы выбрать диск с которого грузиться нажмите "B". И нажмите "Enter", чтобы начать загрузку. Стрелки вверх/вниз позволяют вам перемещаться в меню выбора, а стрелка слева от названия диска будет заменять собой курсор. Чтобы реализовать все эти "рюшечки" и возможность читать по-русски мне пришлось добавить в программу возможность перепрограммировать знакогенератор (его верхнюю часть - символы со 128 по 255), потому что прошивка видеокарт, как правило, не поддерживает кодировку CP866. Для этого я воспользовался программой evafont.exe для исправления нужных мне символов и с её помощью сгенерировал include-файл sec_50.inc, который содержал данные о прорисовке символов 8х16.

Отладив и получив то, что хотел, я занялся разбивкой жёсткого диска на три логических. Делал я это так (если вам это интересно):

*К сожалению, при инсталяции Windows'9x переписывает mbr заново, хотя Windows NT себе таких вольностей не позволяет. И поэтому, каждый раз после инсталяции Windows'9x приходилось восстанавливать mbr.

Есть ещё один плюс в использовании механизма закрывающего логические диски от других операционных систем. В этом я убедился на собственном опыте полгода назад. Если у вас стоит Windows'9x и Linux на одной машине и Linux устанавливался в extended разделы (а не в primary), то, в это случае, Windows распознаёт этот extended раздел, но т.к. в нём есть только две записи - первая с сигнатурой диска 83h (Linux native) и второй 05h - указатель на следующий extended раздел, то Windows показывает этот раздел как логический диск с нулевым размером и, иногда, предлагает его отформатировать, т.к. считает, что этот диск неотформатирован. Вежливые отказы, судя по всему, не всегда помогают - раздел "/home" у меня оказался оказался испорчен напрочь и восстановлению не подлежал.

Возможно, это "случайность" в работе "форточек" и у других пользователей Windows и Linux такое не происходило - значит, мне не повезло и стоило мне это невезение двух недель работы :(.

В заключении, хотелось сказать следующее - цель этой статьи рассказать, что и как устроено в MBR и можно было бы ограничиться дизассемблированным кодом MBR с комментариями к нему. Но мне хотелось показать, что можно сделать с этим знанием. Я ни в коей мере не призываю вас ломать, устоявшуюся структуру разбивки ваших дисков на ту, о которой рассказал я и отказываться от тех загрузчиков операционных систем, которыми пользуетесь (LILO, NT Loader, System Commander и etc.). Может быть, она вам и не подойдёт. Хотя я для себя настроил четыре операционки для работы (в порядке расположения): MS DOS, Windows NT 4.0, Windows'95 и Linux Mandrake 7.0 RE и все они спокойно уживаются и не видят друг друга, если я им не позволю. Хотя, если кто-то начнёт лупить напрямую через int 13h, тогда, конечно, никакая разбивка не поможет (например, вирус "Чернобыль").

Главная загрузочная запись (англ. master boot record, MBR) — это код и данные, необходимые для загрузки операционной системы (ОС), и расположенные в первых физических секторах (чаще всего в самом первом) на жёстком диске или другом устройстве хранения информации. MBR содержит небольшой фрагмент исполняемого кода, таблицу разделов (partition table) и специальную сигнатуру.

Цель MBR — ещё не загрузка ОС, а всего лишь выбор, «с какого раздела жёсткого диска следует загружать ОС». На стадии MBR происходит выбор раздела диска и ничего более. Загрузка самой ОС происходит на более поздних этапах.

В процессе запуска компьютера после окончания начального теста (Power On Self Test, POST) MBR загружается базовой системой ввода-вывода (BIOS) в оперативную память (в компьютерах архитектуры IBM PC обычно с адреса 0000:7c00) и передаётся управление находящемуся в MBR загрузочному коду (обычно командой long jump).

Структура Главной загрузочной записи (MBR)

Адрес

Содержимое

0x0000

Код загрузчика

0x01B8

4-х байтная сигнатура диска (только в Windows 2000, XP [1], но не в Windows 95/98 [2])

0x01BE

Четыре 16-байтных записи таблицы основных разделов (только схема таблицы основных разделов MBR)

0x01FE

2-х байтная сигнатура MBR (55AA16)

Содержание

[убрать]

  • 1 Роль и место MBR в загрузке компьютера (для архитектуры x86)

    • 1.1 Развитие MBR

    • 1.2 Другие (не x86) системы

  • 2 Стандартизация MBR

    • 2.1 Наиболее частый формат MBR

    • 2.2 Иные форматы MBR

  • 3 MBR от Microsoft (MS DOS и MS Windows)

    • 3.1 Структура MBR

    • 3.2 Алгоритм работы кода MBR от Microsoft

      • 3.2.1 BIOS (до MBR)

      • 3.2.2 MBR

      • 3.2.3 Загрузочный сектор логического диска (после MBR)

  • 4 Структура MBR

    • 4.1 Код загрузчика

    • 4.2 Таблица разделов

    • 4.3 Сигнатура

  • 5 Структура описания раздела

    • 5.1 Признак активности разделов

    • 5.2 Начало раздела / Конец раздела

    • 5.3 Код типа раздела

    • 5.4 Смещение первого сектора

  • 6 Восстановление MBR

  • 7 См. также

  • 8 Примечания

  • 9 Ссылки