Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Напиши свою операционную систему!


Информационный Канал Subscribe.Ru

Напиши свою операционную систему!

Напиши свою ОС! #3

Введение

Здравствуйте, уважаемые подписчики!

Сразу разберемся с организационными вопросами.
С этого выпуска у рассылки будет 4 со-ведущих. И уже этот выпуск пишу я, Khimov Roman (khimov@mail.ru). Каждый выпуск будет готовить кто-то один, передавая эстафету следующему. Надеюсь, что это позволит нам выдержать строгую периодичность - раз в неделю по пятницам, чтобы Вам было что почитать на выходных :-)
После меня, следующий выпуск будет делать commrade, потом Doberman, и потом Wanderer, после чего опять моя очередь. Чем то напоминает принцип ротации выпускающих редакторов журнала "Компьютерра"...

В этом выпуске мы обещали познакомить вас поближе с загрузочными секторами. А значит, пора приступать! :-)

Что есть bootsector?

Bootsector, он же загрузочный сектор, - это то, что позволяет нам загрузить непосредственно операционную систему. Как писал в предыдущем выпуске Wanderer, после выполнения POST, BIOS смотрит в список очередности загрузки и пытается найти "правильный" загрузочный сектор. Правильным, с точки зрения BIOS, будет загрузочный сектор, содержащий двухбайтовое55AAh со смещением на 510 байт от начала загрузочного сектора. Весь загрузочый сектор должен умещаться в 512 байт, поэтому при его разработке, как правило, используется ассемблер.

Где живет bootsector?

Bootsector всегда можно найти по адресу: "нулевой цилиндр, нулевая головка, первый сектор" :-). Это означает, что bootsector всегда находится в самом начале того диска, с которого производится загрузка. Однако есть одно важное исключение: на всех HDD по адресу, данному выше, располагается MBR - Master Boot Record - Головная Загрузочная Запись (по версии Lingvo 8.0, честное слово, к английским терминам так привыкаешь, что порой не можешь подобрать адекватный перевод, да и есть вопрос: "а нужен ли он?", т.к. английская терминология точнее, да и это оригинал все-таки... Хотя, для понимания перевод нужен...). MBR состоит из трех основных частей:

  • Код, который позволит запустить загрузочный сектор с одного из четырех возможных разделов (partition).
  • Таблица разделов (partition table), записанная со смещением на 446 байт. Она содержит четыре записи, по 16 байт каждая
  • "Магические" числа 55h и AAh в 510 и 511 байте соответственно.

Про "магические" числа мы уже знаем, что это признак "правильности" загрузочного сектора, который очень любит BIOS.
Записи в таблице разделов имеют очень простую структуру:
Смещение Размер Описание
00h 1 байт Флаг типа раздела (0=не загрузочный, 80h=загрузочный, или 'активный')
01h 1 байт Головка, на которой начинается раздел
02h 2 байта Первые десять бит содержат номер цилиндра, с которого начинается раздел, последние шесть - номер сектора, с которого начинается раздел.
04h 1 байт Индикатор/указатель/код файловой системы или операционной системы, находящейся на этом разделе.
05h 1 байт Головка, на которой раздел заканчивается
06h 2 байта Первые десять бит - номер последнего цилиндра раздела, последние шесть - номер сектора, на котором раздел заканчивается.
08h 4 байта 32-битный LBA номер первого сектора раздела
0Ch 4 байта 32-битный LBA количество секторов в разделе
Оччень просто, правда? :-)

О самом "вкусном", о коде, который грузит загрузочный сектор чуть дальше.

И одно маленькое замечание: теоретически винчестер может и не содержать MBR, а иметь по этому адресу, как и старая добрая дискетка (жизненное наблюдение владельца ноутбука БЕЗ floppy привода - хоть раз в месяц, но случаются ситуации, когда тот самый флоппи-драйв нужен позарез! а нету...), самый настоящий загрузочный сектор. Но на сегодняшний день это экзотика, так что не расстраивайтесь, не зря читали, все что выше про MBR :-)

Как загружается bootsector?

Самый простой процесс загрузки bootsector'a - при загрузке его с дискеты. В этом случае BIOS просто читает первый сектор дискеты в память со смещением 0000:7C00h, после чего проверяет его на "правильность" (обращается по абсолютному адресу 0000:7DFEh (0000:7C00h + 510) в поисках знакомого нам "магического" числа. Если все в порядке, начинается выполнение кода bootsector'а с адреса 0000:7C00h, если нет, то выдается сообщение об ошибке.

Все выглядит несколько веселее, если загрузка идет с HDD. Как мы уже выяснили, винчестер в первом секторе содержит MBR, но BIOS все равно грузит его по тому же адресу, что и для дискеты: 0000:7C00h. Как правило (хотя это не стандарт!) код MBR перемещает сам себя ниже, с адреса 0000:0600. Уже оттуда код MBR начинает проверять таблицу разделов на предмет наличия в ней раздела, помеченного как "active" или "bootable", то есть того, с которого должна начаться загрузка. Как только он находит такой раздел, он загружает его первый сектор по адресу 0000:7C00h и передает туда управление (вот почему MBR смещает собственный код ниже!).

Еще одна маленькая особенность: после поиска активного раздела, MBR оставляет в регистре DL (младший байт регистров DX, EDX)значение 80h, которое он использовал при сравнении, прочитанного флага типа раздела. При загрузке с дискеты DL будет содержать 00h, таким образом загрузчик может узнать, откуда он был запущен.

Основные задачи загрузочного сектора

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

В качестве примера хорошего загрузчика я бы привел GRUB, он помещается в 512 байт и умеет работать с FAT, FAT32, EXT2, EXT3, ReiserFS. Хотя, он может и не ограничиваться отведенным ему местом и будет рад обнаружить конфигурационный файл на своем разделе (про GRUB можно писать долго, если интересно - сходите на www.gnu.org/software/grub/). И на этом мы переходим к более интересным случаям: когда загрузчик не помещается целиком в отведенные ему 512 байт.

В этом случае возникает необходимость загрузить вторую часть загрузчика (частенько ее называют просто "вторичным загрузчиком"). И здесь есть три случая:

  • Диск не имеет файловой системы
    В этом случае предполагается, что вторая часть загрузчика располагается сразу за первой, то есть в следующем секторе, вывод простой - надо читать! :-) При этом загрузчик должен знать, сколько секторов ему необходимо прочитать.
  • Диск может быть имеет, а может и нет, файловую систему
    Используется специальный блок, который находит вторичный загрузчик. Это, пожалуй, самый сложный случай, приходится "знать" очень много - и сколько читать, если диск не имеет файловую систему, и знать откуда брать, если имеет, да еще надо уметь контактировать с разными ФС. А у нас всего 512 байт под загрузочный сектор, становится грустно... :-)
  • Диск имеет файловую систему
    Используется файловая система. Лучше, конечно, чем предыдущий случай, но тоже не сахар - надо знать разные ФС. Хотя, повторюсь, мы рассматриваем пример хорошего загрузчика, в простейшем случае ФС одна.

После того, как, наконец-то, наш моногострадальный загрузочный сектор почувствовал себя настоящим загрузчиком, можно переходить к следующей части: загрузка непосредственно ядра операционной системы.

Грузим ядро

Загрузчик должен прочитать ядро в память и передать ему управление. При этом как читать мы узнаем на предыдущем шаге (через ФС, или посекторно), а откуда должен знать загрузчик. Продвинутые загрузчики позволяют пройтись по ФС (случай с диском без ФС не рассматриваем - это крайняя редкость) самому (т.е. предоставляют командную строку!) и выбрать нужное ядро. Казалось бы все просто, но нет и тут может быть множество подвохов, да и было бы неинтересно, если бы все было бы так просто. :-)

Во-первых, ядро надо проверить! Умеет ли загрузчик с ним работать, т.е. знает ли он его формат? Нужен ли ядру 32-битный режим работы процессора? Включать/выключать A20? Необходима ли релокация в памяти? Хватит ли памяти вообще??? Только после выяснения всех этих вопросов загрузчик может что-то делать.

После выяснения всего этого загрузчик готовится к загрузке и соотвественно включает/выключает A20, переводит/выводит процессор из 32-битного режима и т.д.
Только после этого всего ядро может быть загружено. И оно грузится! :-)
Загрузчик должен посмотреть, сжато ли ядро? Если да, то распаковать его. После этого приходим к вопросу: надо ли ядро копировать (перемещать) в памяти? Если да, то копируем.

Загрузчик также может передавать какую-то информацию ядру, например, параметры загрузки ОС.

Некоторые загрузчики, при "незнании" файловой системы, тем не менее предлагают загрузить с нее ОС. В этом случае управление передается предполагаемому загрузчику, который должен находиться в начале соответствующего раздела.

А может хватит? :-)

Фуф! Неплохо, правда? На самом деле, как правило, загрузка идет по простейшему пути, и ядро ни коим образом не проверяется, однако, файловая система используется.

На десерт: в приложении к этому письму (Те, кто получат эту рассылку через Subscribe.ru могут получить его по этому адресу) Вы найдете программку wba.com, она умеет записывать загрузочные сектора на дискеты. Таким образом, у Вас есть возможность "побаловаться" с загрузочным сектором и написать загрузчик, который будет что-то делать, что - на Ваше усмотрение! :-)

Ну и чтобы было еще интереснее, в приложении еще один файл - sampleboot.asm, это пример загрузчика, который загружает стороннюю программу (можете подсунуть ядро ОС! :-) правда какой, чтобы уместилась на дискете?). Сама программа - отдельный .asm файл - loadable_program.asm, а для того, чтобы все записать на дискету последовательно (!), приложен еще один файл - Disk_img.asm, он подобьет в кучу загрузчик и программку. Записать же все на дискету поможет wba.com. Все ассемблерные программки прекрасно компилируются с помощью Nasm, удачи в творческих поисках! Только помните, что за любые последствия, связанные с использованием этих файлов, мы ответственности не несем! Так что осторожнее, не перепишите MBR своего любимого диска! :-)

Послесловие

Следующий выпуск будет готовить commrade, а у меня все!

Послесловие от Wanderer

Итак, вы ознакомились с очередным выпуском. В связи с тем, что достаточно малое количество подписчиков переподписалось на новый адрес этот выпуск распространяется так же через Subscribe.ru. Это последний выпуск, распротраняющийся через эту систему, поэтому, для переподписки прошу нажать здесь, а затем отправить сгенерированное письмо. Следующий выпуск будет посвящен переходу в защищенный режим, так что не пропустите! :-)

Вопросы вы по-прежнему можете задавать либо мне либо Роману (e-mail вы можете найти в начале письма либо чуть ниже этого текста). На этом я с вами прощаюсь. До следующего выпуска!

Удачи!
Khimov Roman
ICQ: 32705527



http://subscribe.ru/
E-mail: ask@subscribe.ru
Отписаться
Убрать рекламу

В избранное