При включении питания, аппаратном сбросе от кнопки Reset или нажатии комбинации клавиш Ctrl+Alt+Del процессор переходит к исполнению кода начального самотестирования POST (PowerOn Self Test — самотестирование при включении), хранящегося в микросхеме BIOS. POST выполняет тестирование процессора, памяти и системных средств ввода-вывода, а также конфигурирование всех программно-управляемых аппаратных средств системной платы. Часть процедуры конфигурирования выполняется однозначно, часть управляется джамперами системной платы, но ряд параметров позволяет или даже требует конфигурирования по желанию пользователя. Для этих целей служит утилита Setup, встроенная в код BIOS. После тестирования и конфигурирования (включающего настройку устройств PnP) POST инициирует загрузку операционной системы.
При прохождении каждой секции POST записывает ее код (номер) в диагностический регистр. Этот регистр физически располагается на специальной диагностической плате POST Card (это не почтовая карточка), устанавливаемой в слот шины расширения. Плата содержит 8-битный регистр со световой (двоичной или шестнадцатеричной) индикацией состояния битов. В пространстве ввода-вывода регистр занимает один адрес, зависящий от архитектуры PC (точнее, версии BIOS): ISA, EISA - 80h, ISA-Compaq - 84h, ISA-PS/2 - 90h, MCA-PS/2 — 680h, некоторые модели EISA — 300h (часто пишут то же и в 80h). По индикаторам платы можно определить, на какой секции остановился тест POST, и выяснить причину неисправности. Однако для такой диагностики необходимы, во-первых, сама плата-индикатор и, во-вторых, «словарь» неисправностей — таблица, специфическая для версии BIOS и системной платы.
Во время выполнения POST может выдавать диагностические сообщения в виде последовательности коротких и длинных звуковых сигналов, а после успешной инициализации графического адаптера — в виде небольших текстовых сообщений на экране монитора.
Ниже представлена обычная последовательность шагов теста POST:
1. Тестирование регистров процессора.
2. Проверка контрольной суммы ROM BIOS.
3. Проверка и инициализация таймера 8253/8254, портов 8255. После этого шага становится доступной звуковая диагностика (табл. 5.1).
4. Проверка и инициализация контроллеров DMA 8237.
5. Проверка регенерации памяти.
6. Тестирование 64 Кбайт нижней памяти.
Загрузка векторов прерывания и стека в нижнюю область памяти.
8. Инициализация видеоконтроллера — на экране появляется заставка Video BIOS, обычно с указанием модели видеокарты и объемом установленной ви деопамяти.
После успеха этого шага изображение на экране сменяется заставкой системного модуля BIOS со счетчиком объема тестируемой динамической памяти. Теперь диагностические сообщения выводятся на экран (табл. 5.2). POST продолжает работу.
9. Тестирование полного объема ОЗУ.
10. Тестирование клавиатуры.
11. Тестирование CMOS-памяти и часов.
12. Инициализация СОМ- и LPT-портов.
13. Инициализация и тест контроллера НГМД.
14. Инициализация и тест контроллера НЖМД.
15. Сканирование области дополнительной памяти ROM BIOS.
16. Вызов Bootstrap (Int 19h) — загрузка операционной системы, при невозмож ности — попытка запуска ROM Basic (Int 18h), при неудаче — останов про цессора с сообщением System Halted (система остановлена).
На новых системных платах реализуется и речевая звуковая диагностика (voice diagnostics) — через динамик пользователю предлагают проверить установку модулей памяти, видеоадаптера, подключения кабеля винчестера и т. п. Язык сообщений можно выбрать в CMOS Setup (когда эту процедуру удастся запустить), правда, русского языка пока не встречается.
В процессе работы POST используются ячейки CMOS: результаты прохождения тестов заносятся в ячейку OEh (Post Diagnostic Status Byte), в ячейке OFh (Shutdown Flag) находятся идентификаторы состояния перед началом теста. В BIOS DATA AREA [0:0472] задается тип рестарта (1234h - Ctrl+Alt+Del -«теплый» старт, 432 lh — сброс с сохранением памяти). Это позволяет различать причины рестарта (перезагрузка, выход из защищенного режима 286 и т. д.) для обхода некоторых секций POST.
Начальная загрузка
Стандартная процедура начальной загрузки (bootsrap loader), вызываемая по прерыванию Int 19h BIOS в конце теста POST, выбирает устройство начальной загрузки (Initial Program Loader, IPL) — блочное устройство, поддерживающее функцию чтения секторов. С этого устройства процедура пытается загрузить в ОЗУ самый первый сектор, и если у него в конце имеется сигнатура загрузчика, ему передается управление. До выполнения начальной загрузки должны быть инициализированы перечисленные ниже загрузочные устройства (boot device), которыми пользуются сама эта процедура и загружаемые ею модули:
♦ Устройство ввода (input device) — как правило, клавиатура, с которой мож но управлять загрузкой, отвечая на запросы. Это устройство должно поддер живать посимвольный ввод — сервис Int 09h BIOS.
♦ Устройство вывода (output device) — как правило, дисплей, на который вы водятся сообщения загрузчика. Это устройство должно поддерживать по символьный вывод — сервис Int 10h BIOS.
♦ Устройство начальной загрузки (IPL) — как правило, НГМД, НЖМД и дру гие устройства, поддерживающие функции блочного чтения — сервис Int 13h (02 или 42h) BIOS. Для краткости в дальнейшем его будем называть просто устройством загрузки.
Первый сектор с выбранного устройства загрузки функцией чтения Int 13h (02) BIOS загружается в память по адресу 0000:7C00h, и если в его конце (по адресу 0000:7DFE) обнаружена сигнатура загрузочного сектора (слово AA55h), управление передается на его начало (по адресу 0000:7C00h), где расположена точка входа в программу загрузки. На этом деятельность теста POST завершается, хотя вызовом прерывания Int 18h загрузчик может снова отдать ему управление в случае своих неудач, и POST попробует выполнить загрузку с другого устройства. Нормального возврата из загрузчика не предусмотрено (только вперед, на загрузку ОС!).
Прерывание Int 18h BIOS на старых машинах предназначалось для вызова встроенного интерпретатора BASIC при невозможности загрузки с диска. Позже это соглашение стали использовать для попыток загрузки с альтернативных устройств, и Int 18h BIOS определили как функцию аварийного возврата для начального загрузчика. По прерыванию Int 18h POST снова инициализирует стек и переходит к другому устройству загрузки.
Содержимое загруженного первого сектора зависит от того, с какого устройства он был загружен. На загрузочной дискете первый сектор содержит загрузчик — программу, загружающую операционную систему или только ее ядро. Этот загрузчик привязан к своей ОС и записывается на диск при форматировании его средствами этой ОС. Загрузочный сектор содержит собственно код загрузчика и необходимые ему параметры диска (см. 9.6). Для дисков DOS загрузчик, пользуясь этими параметрами, находит начало корневого каталога и ищет в его первых двух элементах знакомые имена файлов — IO.SYS и MSDOS.SYS. Найдя их, он считывает первые 3 сектора файла IO.SYS в память по адресу 0070:0000 (или 0000:0700, что одно и то же) и передает управление на его начало, сохранив в регистре СН тип носителя, в регистре DL — номер привода, в регистрах АХ и ВХ — старшую и младшую части линейного адреса начала корневого каталога. Сам файл IO.SYS гораздо длиннее трех секторов, но в дальнейшем процессе его загрузки и продолжения загрузки ОС данный загрузчик уже участия не принимает.
На жестком диске первый сектор содержит главную загрузочную запись (MBR). Он также загружается в память по адресу 0000:7C00h, и если в его конце обнаружена сигнатура загрузочного сектора (AA55h), управление передается на его начало. При исполнении главный загрузчик первым делом перемещает (копирует) свой код (и таблицу разделов) по адресу 0000:0600h и продолжает свое исполнение уже из новой области. Задача главного загрузчика — найти активный раздел, загрузить его первый сектор в память и, если он имеет сигнатуру загрузочного сектора, передать ему управление. Найдя описатель активного раздела, главный загрузчик загружает в память по адресу 0000:7C00h его первый сектор, при этом регистр SI указывает на описатель активного раздела (после перемещения таблица разделов оказывается в памяти по адресам 0000:07В0-07FDh). Первый сектор загружаемого раздела ищется просто: в регистр DX заносится слово 0, а в СХ — слово 2 из описателя активного раздела. После этого остается лишь задать адрес буфера в памяти (в ES:BX), функцию чтения одного сектора (АХ = 0201h) и вызвать дисковый сервис Int 13h BIOS. Если считать сектор без ошибок не удается (делается до 5 попыток), главный загрузчик останавливается с сообщением «Error loading operating system».
Программный код загрузчика, расположенного на разделе жесткого диска, несколько отличается от дискетного, поскольку для работы с дискетой требуется инициализация ее таблицы параметров. Однако общая идея процесса загрузки у них одинакова. Для других операционных систем загрузчик выполняет иные действия, но цель та же — загрузить в память начальные модули и передать им управление.
Главный загрузчик инвариантен по отношению к загружаемым операционным системам и дискам, его программный код, как и таблица разделов, записывается утилитой FDISK при конфигурировании жесткого диска (см. 9.12). Однако традиционный главный загрузчик в принципе не способен загрузить раздел, находящийся дальше чем через 8,4 Гбайт от начала диска, поскольку пользуется исключительно трехмерным (CHS) описанием границ разделов. Для больших дисков главный загрузчик должен использовать линейные описания разделов.
Помимо вышеописанного штатного способа загрузки с диска, выполняемой традиционным системным модулем BIOS, имеется возможность загрузки, в принципе, с любого устройства, с которого можно загрузить в память требуемый блок данных. Так, возможна загрузка с CD-ROM, но для этого необходимо выполнение специальной процедуры, включающей эмуляцию диском CD-ROM дискеты или жесткого диска (см. 9.11). Возможна загрузка и с нестандартного устройства, подключаемого через карту расширения. Однако системный модуль BIOS сам этого не умеет, и такое загрузочное устройство должно иметь ПЗУ расширения BIOS (см. 5.3) с собственной процедурой загрузки. Для такого устройства процедура инициализации в ПЗУ расширения должна перехватить вектор Int 19h (чтобы стать первым загрузочным устройством) или Int 18h (чтобы получить управление, если загрузка со штатных устройств не удается). Этот перехваченный вектор должен указывать на специфическую процедуру загрузки с данного устройства, которая и будет выполняться тестом POST вместо или в качестве запасного варианта обычной загрузки. Такой способ применяется для устройств удаленной загрузки (Remote Program Loader, RPL) — например, адаптеров локальной сети, снабженных ПЗУ удаленной загрузки (boot ROM). Когда подобный адаптер установлен и работа ПЗУ удаленной загрузки разрешена, при каждой перезагрузке на консоли может появляться предложение о выборе между загрузкой с жесткого диска или по сети (загрузка с дискеты свой приоритет не потеряет).
Для сложных систем, которые содержат разные устройства, претендующие на роль загрузочных (НГМД, жесткие диски и CD-ROM ATA/ATAPI и SCSI, USB флэш-диски, сетевые адаптеры и т. п.), требуется механизм упорядочивания загрузочных устройств. Пользователь должен иметь возможность знакомиться со всем списком имеющихся устройств и выбирать порядок их опроса в загрузочной последовательности. Для этих целей фирмами Compaq, Phoenix и Intel в 1996 году была выпущена спецификация BIOS Boot Specification (BBS). Подробнее процедура загрузки, спецификация BBS и способы создания «самодельных» загрузочных устройств описаны в [6].