Для начала давай попробуем разобраться, что происходит с твоим HDD, когда ты включаешь компьютер. На него поступает питающее напряжение от блока питания, после чего на управляющей микропроцессор подается сигнал RESET (для этих целей существует специальная схема сброса накопителя). Управляющий микропроцессор инициализирует состояние портов ввода/вывода HDD и производит сброс рабочей области памяти данных. После подается сигнал на запуск двигателя HDD. Далее выполняется диагностика диска, то есть проверяются основные узлы HDD. Когда двигатель раскрутится до нужных оборотов, управляющий микропроцессор с помощью системы позиционирования устанавливает головки в зону, где находится служебная информация HDD (к ней, например, относится название твоего винта) и считывает ее в буферное ОЗУ (за эту операцию отвечает однокристальный микроконтроллер). На завершающем этапе управляющий микропроцессор устанавливает бит 6 (DRDY – HDD готов к работе) и бит 4 (DSC – показывает, что операция поиска выполнена успешно), сбрасывает бит 7 (Busy – определяет состояние HDD, то есть «занят» или «готов к работе») регистра команд/состояния и записывает в регистр ошибок код 01h. В таком состоянии HDD находится, ожидая команду со стороны компьютера.
Ты уже обратил внимание на операцию диагностики в процессе инициализации твоего HDD? Так вот, сейчас мы напишем программку, которая протестирует (по крайней мере, должна протестировать
) основные электронные компоненты твоего накопителя. В идеале, ты сможешь понять основные принципы написания системных утилит для HDD, определить, почему твой винчестер не «ловится» BIOS и просто протестировать свой жесткий диск. Но сначала я должен дать тебе еще немного теории.
Если ты внимательно читал статью, то уже обратил внимание на какие-то регистры HDD (которые, кстати, расположены в однокристальном микроконтроллере). С помощью этих регистров можно выполнять множество операций с жестким диском, например запись/чтение сектора, форматирование сектора, верификация и так далее. Для адресации этих регистров используется область с адресами 1F0h-1F7h (Primary channel) и 170h-177h (Secondary channel). Рассмотрим описание нужных нам регистров для написания программы на примере Primary channel.
Регистр выбора HDD/номера головки (1F6h чтение/запись) имеет следующий вид:
7-ой бит – зарезервирован.
6-ой бит – используется для выбора способа адресации HDD: если бит установлен в 0, то используется адресация CHS (Cylinder, Head, Sector), а если в 1, то используется адресация LBA (Logical block address).
5-ый бит – зарезервирован.
4-ый бит – используется для выбора устройства: если бит установлен в 0, то используется устройство Master, если в 1, то используется устройство Slave.
Биты 3-0 – если установлен режим адресации CHS, то с помощью этих битов задается двоичный код выбранной головки, а если режим адресации LBA, то в них записываются старшие биты логического адреса.
Регистр состояния (1F7h чтение) показывает текущее состояние HDD. Его содержимое изменяется после выполнения каждой команды.
7-ой бит (бит BUSY) – устанавливается во время выполнения команды или диагностики HDD. Определяет текущее состояние HDD.
6-ой бит (бит DRDY) – показывает готовность накопителя к работе.
5-ый бит (бит WFT) – показывает неисправность накопителя или попытку записи с некорректными параметрами.
4-ый бит (бит DSC) – показывает, что головки накопителя завершили операцию поиска.
0-ой бит (бит ERROR) – устанавливается, если команда завершилась с ошибкой. Код ошибки лежит в 1F1h.
Регистр команд (1F7h, запись) используется для загрузки команд. В случае рассматриваемой программы нас интересует команда с кодом 90H или внутренняя диагностика HDD. В результате выполнения команды в регистре ошибок формируется код ошибки.
Регистр ошибок (1F1h, чтение) показывает состояние HDD после выполнения операции.
Состояние этого регистра действительно:
1. после выполнения команды, если установлен бит Error в регистре состояния,
2. после выполнения команды «Диагностика» или после внутренней диагностики HDD по системному сбросу.
В диагностическом режиме выделяют следующие коды ошибок:
* 01h – нет ошибок;
* 02h – ошибка микроконтроллера;
* 03h – ошибка буферного ОЗУ;
* 04h – ошибка аппаратуры ECC (ECC – код обнаружения ошибки);
* 05h – ошибка микропроцессора;
* 8Xh – HDD неисправен.
Теперь рассмотрим эти ошибки более подробно.
1. 01h – без комментариев
.
2. Ошибка однокристального микроконтроллера. Однокристальный микроконтроллер является наиболее сложной частью HDD. Это устройство отвечает за операции чтения, записи, форматирования и верификации секторов и дорожек, управляет регистрами ввода/вывода, буферным ОЗУ и еще многим чем интересным.
3. Ошибка буферного ОЗУ. С помощью буферного ОЗУ осуществляется обмен данными между различными устройствами, входящими в состав HDD.
4. Ошибка аппаратуры ECC. Это общее название аппаратной системы обнаружения и коррекции ошибок.
5. Ошибка управляющего микропроцессора. Это устройство является «мозгом» HDD. Его ближайший аналог это центральный процессор в компьютере.
6. 8Xh – без комментариев
.
В случае если бит Error регистра команд/состояния установлен в 1 то, считав и проанализировав содержимое регистра ошибок, можно выделить следующие состояние:
7-ой бит (бит BBK) – устанавливается, если в идентификаторе сектора обнаружена метка, что он дефектный.
6-ой бит (бит UNC) – устанавливается в случае некорректируемой ошибки ECC в поле данных.
5-ый бит – не используется, всегда равен нулю.
4-ый бит (бит IDNF) – не обнаружены требуемые цилиндр, головка, сектор.
3-ий бит – не используется, всегда равен нулю.
2-ой бит (бит ABRT) – устанавливается, если накопителю задана неправильная команда или если HDD не выходит в готовность, операция записи не выполнена, операция поиска не выполнена.
1-ый бит (бит T0NF) – устанавливается, если после рекалибровки HDD не найдена дорожка 0.
0-ой бит (бит AMNF) – устанавливается, если не найден адресный маркер сектора.
Наконец, вооружившись необходимыми знаниями, мы можем начать процесс написания программы. Для начала нам надо выбрать тестируемый HDD. Для этого зададим две константы, с помощью которых можно будет осуществить выбор Primary или Secondary канала и выбрать Master или Slave HDD.
Port equ 1f0h
HDD equ 0
В нашем случае выбран Primary Master HDD, но тебе ничего не мешает указать свои значения. Затем мы записываем в регистр выбора HDD/головки двоичный код, образованный параметром HDD.
mov dx, Port + 6
mov al, 10100000b or (HDD shl 4)
out dx, al
jmp $ + 2
Последняя команда – это задержка, необходимая для того, чтобы HDD успел обработать записанную в него информацию. Обрати внимание на конструкцию mov al, 10100000b or (HDD shl 4). С ее помощью мы формируем двоичную структуру (10100000b, если HDD=0 или 10110000b, если HDD=1), которая будет записана в регистр 1f6h (регистр выбора HDD/головки). Далее нам надо записать в регистр команд код команды, которую нам необходимо выполнить. Нас интересует команда внутренней диагностики – ее код 90h. Вот пример кода, реализующий данную функцию.
inc dx
mov al, 090h
out dx, al
jmp $ + 2
В данном примере мы записали в регистр команд (1f7h) код команды (90h). Затем нам нужно проверить состояние устройства, то есть занято оно или свободно.
_Wait: in al, dx
jmp $ + 2
test al, 80h
jnz _Wait
Здесь мы считываем из регистра 1f7h текущее состояние HDD и проверяем, сброшен ли бит BUSY (80h=10000000b). Если сброшен, то продолжаем выполнение программы дальше, если нет, то повторяем процедуру заново. Далее мы считаем код состояния HDD из регистра ошибок (1f1h).
mov dx, Port + 1
in al, dx
jmp $ + 2
На последнем этапе необходимо провести анализ результата и вывести его на экран монитора. Вот пример для обработки кода 01h (нет ошибок).
cmp al, 01h
jz _NoError
...
_NoError: mov ah, 9h
mov dx, offset NoError
int 21h
jmp _Bla
...
_Bla: ret
_NoError db "No Errors!!!",0Dh,0Ah,'$'
Полную версию программы с моими комментариями ты сможешь найти на диске. Для ее компиляции в среде TASM набери:
tasm check.asm tlink /t /x check.obj
Внимание! Программа работает из-под DOS!
И напоследок, пример работы программы с различными HDD. В случае если твой HDD исправен, как, например, этот экземпляр, ты увидишь такую надпись.
Если же HDD неисправен, то тут может быть множество вариантов
. Ну, например, для этого устройства программа вывела следующее сообщение.
А теперь немного о грустном... К сожалению, производители HDD по-разному трактуют коды ошибок, вследствие чего при диагностике жесткого диска возможны два варианта:
1. Если в регистре ошибок лежит 01h, то внутренняя диагностика успешно завершена.
2. Если в регистре ошибок лежит число, отличное от 01h, то тест провален.
Но это еще не все! Некоторые накопители корректно выполняют диагностику только в специальном режиме, который называется технологический режим. Особенно этим грешен наш «любимый» производитель – Fujitsu.
С чем едят MBR
MBR (master boot record) – главная загрузочная запись, которая располагается по адресу 0-0-1 в адресации CHS или в 0-м сектор в адресации LBA. Занимает она один сектор или 512 байт.
В состав MBR входят:
* внесистемный загрузчик (или загрузочная запись);
* таблица описания разделов накопителя.
Обрати внимание на последние два байта MBR. Там должно располагаться число AA55h, так называемый Magic Key. По этому числу определяется, что данный сектор содержит MBR. В таблице разделов описываются размещение и параметры имеющихся на накопителе разделов. Разделы подразделяются на primary (первичные) и extended (расширенные). Первичных разделов не может быть больше четырех, на HDD обязательно должен быть хотя бы один Primary раздел, на первичном разделе может быть только один логический диск. В следующей таблице представлен приблизительный вид элемента таблицы разделов.
Я прокомментирую следующие элементы этой структуры:
* Признак активности – показывает, является этот раздел загрузочным или нет. Загрузочным может быть только один раздел.
* Принадлежность к ОС – показывает, к какой операционной системе принадлежит этот раздел. Например, код 00h означает пустой раздел, а код 06h означает FAT16.
* Также в этой структуре указываются начальный и конечный цилиндр, головка, сектор раздела, а также размер раздела в секторах.
У расширенных разделов может быть несколько логических дисков, которые описываются структурами Secondary MBR (SMBR). По своей сути SMBR похожа на MBR, но загрузочная запись у SMBR заполнена нулями, и из четырех описаний раздела используются только два. В первом элементе лежит указатель на логический диск, второй элемент указывает на следующую SMBR, у последней SMBR второй элемент содержит нули.
В качестве закрепления материала мы с тобой напишем программку, которая будет записывать MBR накопителя, подключенного как Primary master, в файл. Зачем это надо? Частичное или полное разрушение MBR даже на абсолютно «здоровом» накопителе грозит тебе кучей различных неприятностей вплоть до полной потери твоих драгоценных данных (терабайты mp3 и веселых картинок
). И даже такой примитивный инструмент в определенных случаях может тебя здорово выручить.
Чтобы проиллюстрировать вышесказанное, я расскажу следующий случай. Однажды мой очень хороший приятель попросил меня восстановить данные с его HDD. Придя домой и подключив устройство, я обнаружил, что накопитель абсолютно рабочий, но ни linux-овый fdisk, ни мастдайный Partition Magic не находят на нем никаких разделов, показывая, что на HDD есть только неразмеченная область. Применив свою программу и проанализировав полученный файл (собственно, там анализировать особенно нечего было
), я сразу все понял. В MBR вместо информации о разделах каким-то чудом оказались записаны нули. Расследование, как такое могло получиться, результатов не дало – приятель клялся и божился, что ничего ужасного с HDD не делал
. Но после посекторного сканирования с последующим анализом содержимого накопителя товарищ получил назад свои mp3 и курсовики
.
Программу и исходный код ты сможешь найти на диске. Если ты внимательно читал первую главу, то ты должен без проблем разобраться и в ней. Я заострю твое внимание на следующих аспектах:
В регистр выбора накопителя записывается выражение, устанавливающее бит №6 в единицу, то есть включается режим адресации LBA (каждый сектор описывается своим уникальным 28 разрядным номером), следовательно, последние 3 бита задают 24-27 разряды адреса LBA.
В регистр счетчика секторов 1F2h мы записываем количество секторов, которые хотим считать, то есть 1 сектор.
В регистр номера секторов 1F3h, регистр выбора младшего цилиндра 1F4h, и регистр выбора старшего цилиндра 1F5h мы записываем 0-7, 8-15 и 16-23 разряды адреса LBA соответственно.
В регистр команд мы записываем команду чтения сектора (код 20h) и в результате получаем в регистре данных 1F0h содержимое этого сектора.
После выполнения этой программы мы получим файл hdd.mbr в директории, где находится программа.
Чтобы проиллюстрировать работу программы, я покажу содержимое моей MBR.
Подчеркнутые символы – это тот самый Magic key. Он записан в обратном порядке, так как старшие разряды стоят впереди младших (в процессорах Intel и совместимых).
Можно сделать вывод, что у меня на Primary master установлен Linux и в качестве загрузчика я использую GRUB. Конечно, эта программка написана примерно за 5 минут на коленке и у нее куча недостатков, например, она не работает с расширенными разделами, но ты ведь сможешь написать лучше
. Кстати, в качестве домашнего задания, попробуй изменить эту программу так, чтобы она выводила Magic key на экран.
Эксплуатируем регистры
Ты убедился, что регистр состояния весьма активно используется при работе с накопителем. В связке с регистром ошибок он дает мощное средство диагностики неисправностей HDD. Существует много различных программ, которые напрямую работают с регистрами накопителя, например, великолепная программа Дмитрия Постриганя Mhdd, но мы не ищем легких путей и попробуем во всем разобраться сами. Я намеренно не стал делать пример программы для демонстрации этой возможности, потому что, в принципе, у тебя уже должно быть достаточно знаний, чтобы написать простейший тестер самостоятельно. Но я, все-таки, не такое чудовище
, и покажу тебе примерный алгоритм.
1. Выбрать с помощью регистра выбора HDD 1F6h накопитель и способ его адресации.
2. Подготовить начальные данные, записав их в соответствующие регистры.
3. Записать в регистр команд 1F7h код какой-либо команды из спецификации протокола ATA.
4. Считать содержимое регистра состояния 1F7h.
5. Провести анализ содержимого регистра состояния, уделив особое внимание биту ERROR, биту DRDY, биту BUSY, и, по необходимости, биту WFT.
6. Если произошла ошибка, то нужно считать содержимое регистра ошибок 1F1h.
7. Произвести анализ всех битов регистра ошибок и на основании этих показаний сделать вывод о природе неисправностей накопителя.
Может показаться, что я очень расплывчато охарактеризовал проблему, но каждая такая неисправность требуют индивидуального рассмотрения, и я не могу рассмотреть все варианты в рамках этой статьи. Например, если HDD не может выполнить позиционирование на указанный цилиндр, то можно предположить дефект сервометки накопителя (сервометка – это специальная область, с помощью которой HDD устанавливает головки на указанный цилиндр), или, если при чтении сектора «загорается» бит IDNF, велика вероятность порченого поля идентификатора сектора, и т.д. Наконец, возможен вариант, когда накопитель мертв аки камень, например, поврежден управляющий микропроцессор. Тогда все попытки считать что-либо из регистров обречены на провал.
Напоследок рассмотрим пример работы следующего кода с абстрактным «неисправным» накопителем:
...
mov dx, 1F7h
mov al, 10h
out dx, al
jmp $+2
...
Мы загрузили в регистр команд команду с кодом 10h, или рекалибровка накопителя. По этой команде накопитель устанавливает головки на цилиндр с номером ноль. Далее нам надо считать содержимое регистра состояний.
...
mov dx, 1F7h
in al, dx
jmp $+2
test al, 01h
jnz _metka
...
Опаньки! Команда рекалибровки завершена с ошибкой. Теперь необходимо считать содержимое регистра ошибок и выполнить анализ его содержимого.
...
_metka: mov dx, 1F1h
in al, dx
jmp $+2
...
test al, 02h
jnz _t0nf_err
...
В результате анализа регистра ошибок было обнаружено, что накопитель не может установить свои головки на нулевой цилиндр, но команда позиционирования успешно работает с другими цилиндрами, тогда с большой долей вероятности можно утверждать, что вышла из строя сервометка нулевого цилиндра, что очень плохо, ибо, как ты помнишь, по адресу 0-0-1 располагается MBR. Методы решения таких проблем я расскажу в следующей главе.
Технологический режим – скрываем дефекты
Наконец мы плавно подошли к понятию технологический режим работы накопителя. В этом режиме появляется множество новых способов работы с HDD, будь то работа с микропрограммой накопителя (чтение/запись), редактирование паспорта диска, дефект-листов, служебной информации HDD и еще много чего интересного
. Но я не был бы самим собой, если бы не опошлил и этот аспект – вход в технологический режим сильно различается не только среди различных производителей HDD, но и среди различных моделей одного производителя. Это может быть загрузка команды, которая сугубо специфична для данной серии HDD, замыкание определенных контактов на технологическом разъеме и даже замыкание некоторых ножек определенной микросхемы. После входа в технологический режим тебе становится доступна вся область HDD. Для демонстрации я приведу следующую иллюстрацию. Сразу стало понятно, что нулевой цилиндр в стандартном режиме работы – далеко не нулевой в технологическом режиме.
Теперь вернемся к вопросу скрытия дефектов HDD. Для этих целей в служебной зоне существуют структуры под названием дефект-листы, которые предназначены для хранения местоположения дефектных секторов/дорожек и местоположения секторов/дорожек, которые им сопоставлены. Различают два типа дефект-листов: первичный (P-list), и растущий (G-list). P-list заполняется на заводе в процессе тестирования накопителя, он недоступен пользователю в обычном режиме. С G-list могут работать различные утилиты (например mhdd), но сектор/дорожка, занесенные в G-list (даже по ошибке), не могут потом быть удалены из него в обычном режиме, и при полном заполнении G-list у накопителя будут видны BAD-сектора. С дефект-листами тесно связано понятие транслятора. Транслятор – это программа, записанная в служебной области HDD, которая на основании данных в дефект-листах производит замещение или пропуск дефектного сектора/дорожки (зависит от режима трансляции).
Таким образом, для скрытия дефектов необходим следующий цикл:
1. установить технологический режим на накопителе;
2. очистить P-list и G-list;
3. стереть транслятор;
4. выполнить низкоуровневое форматирование (код – 50h);
5. заполнить P-list;
6. на основании P-list восстановить транслятор;
7. выйти из технологического режима.
То есть, когда у тебя заполнится G-list, и на харде появятся BAD’ы, для скрытия дефектов придется очистить P-list и G-list и стереть транслятор, чтобы не было пропусков/перенаправлений. Дальше нужно протестировать HDD, и на основании теста заполнить P-list и восстановить транслятор. В результате у тебя «девственная» поверхность HDD и чистый G-list. Также это самый лучший способ борьбы с софт-бэдами. Транслятор у каждой модели – свой, и чтобы выяснить, как он выглядит и как его восстанавливать, нужно разобрать «служебку» харда. Как видишь, задача, в принципе, выполнимая, но не самая простая.
?: Такая работа (как показано в примере) возможна с любым HDD (включая самые новые) или есть ограничения?
!: Требования к компу: проц от 386 и далее, хард, совместимый со стандартом АТА-2, то есть все накопители Parallel ATA.