Ошибки Bootmgr

Метки:  , , , , , , , , , , , , , , , ,

Многие технические специалисты в своей работе сталкиваются с ошибками, возникающими на различных стадиях загрузки операционной системы Windows. Случился и в моем практике не так давно достаточно нетипичный сбой этапа загрузки, в котором мне, к моему огромному недовольству, затруднительно было сходу разобраться. Смысл проблемы заключался в том, что вышедшая из строя по достаточно нетривиальной цепочке причин, система Windows 7 (Профессиональная) отказывалась грузиться во всех, без исключения, режимах загрузки. Процесс загрузки просто "вис" на черном экране на этапе, следующем за графическим экраном заставки (splash screen). Код работы с видеоадаптером устанавливал разрешение в родное для монитора, а далее загрузка просто-напросто останавливалась, при этом отчетливо был виден графический курсор мыши, сам манипулятор функционировал. Я так полагаю, что у профессионалов подобное явление обозначается термином черный экран смерти (Black Screen of Death, KSOD), наиболее распространенными причинами которого являются: повреждение различных частей реестра, невозможность запуска критически важных служб и кривая установка разрешений на системные каталоги (все эти вещи зачастую вызваны обновлениями). Большая просьба не путать термин "черный экран смерти" с общеизвестным синим экраном смерти (Blue Screen of Death, BSOD). Как я уже упоминал, загрузка в безопасном режиме останавливалась на том же самом месте, то есть я вообще никак, ни в каком из режимов не мог загрузить ОС!! С грустью вспомнил обо всех хваленых средствах диагностики загрузки вида xbootmgr и прочих трассировщиках, которые оказывались абсолютно бесполезными в подобной ситуации. Потом пришла мысль, что хорошо было бы подключиться каким-нибудь отладчиком удаленно и просто протрассировать код до ошибки, но подобным опытом я пока не обладаю, а проблему надо было решать в сжатые сроки.

В действительности, проблему удалось таки решить "по старинке", воспользовавшись отличным средством Microsoft DaRT, благо удалось докопаться до виновника сбоя.

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

Вот тут то была допущена основная ошибка :) Вернувшись к этому месту после довольно продолжительного времени изучения кода я могу смело утверждать, что попал я в настоящий кодовый кошмар. Я осознал, что алгоритмический пласт информации оказался очень большим, да и ошибки коррелируются между собой настолько витиевато, что иногда упускаешь из виду сам смысл происходящего. Материалы поддержки в Сети просто отсутствуют, поэтому приходится прорубать себе путь по абсолютно незнакомому маршруту.

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

Скажу честно, статья получилась сырая, потому как познания в реверсинге у меня явно не соответствуют уровню материала, посему и некоторые выводы не до конца проработаны и частично ошибочны! Но я всё же набрался смелости опубликовать материал, авось кому то и будет полезной в качестве базиса.

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

В данной версии статьи будет описана классическая схема разбиения и загрузки (legacy boot), основанная на использовании PC/AT BIOS и MBR.

Да просто потому, что под рукой в нужный момент оказалась именно эта конфигурация. Алгоритм с использованием GPT быть может опишу в будущем, но сразу могу сказать, что уже даже на достаточно ранних этапах код, в большинстве своем, идентичен.

Об ошибках в модулях загрузки

Непосредственно перед тем как начать описание процесса загрузки и возникающих в процессе проблем, я бы хотел сделать небольшое отступление на тему ошибок Bootmgr, Winload и ntoskrnl, возникающих в ходе работы кода одноименных модулей. Многие критичные процедуры кода, реагируя на те или иные условия, генерируют числовые идентификаторы ошибок и возвращают их через произвольный регистр (чаще всего это eax). Поскольку регистр, хранящий код ошибки, часто сохраняется либо умышленно не используется, ошибки в "сквозном" режиме передаются на верхний уровень иерархии вложенных подпрограмм, то есть просто при множественном возврате из них по команде ret. Таким образом ошибки регистрируются до тех пор, пока в коде не встречается логика обработки ошибки. Подобных участков обработки ошибок Bootmgr у нас несколько:

  • Блок кода в процедуре BmMain, выдающий ошибку BlInitializeLibrary failed ...;
  • Блок кода в процедуре BmMain, выдающий ошибку BlResourceFindMessage failed ...;
  • Блок кода в процедуре BmMain, выдающий ошибку BlXmiInitialize failed ...;
  • Процедура BmFatalErrorEx, которая является глобальным обработчиком ошибок на все остальные случаи;
  • Процедура BlStatusError, которая вызывается из процедур MmHapReportHeapCorruption и BmFatalErrorEx в аварийной ситуации, проверяет наличие активного отладчика и случае наличия выдает специальную ошибку *** Fatal error ...;

Некоторые обработчики незамедлительно выдают сообщение о возникшей проблеме на консоль, а вот глобальный кейс-обработчик BmFatalErrorEx содержит более витиеватую логику обработки поступившего кода с выдачей уже развернутого текста ошибки. Другая особенность обработки ошибок Bootmgr/Winload заключается в том, что, насколько я смог разобраться, менее значимые ошибки замещаются более значимыми. А это означает, что если ошибка возникла в какой-то процедуре как реакция на определенное условие, то другая ошибка, возникшая позже и являющаяся более приоритетной, может в процессе дальнейшего исполнения кода просто "затереть" первичную ошибку. Из этого следует, что на консоли пользователь видит лишь один результирующий статус, имеющий самый высокий приоритет, хотя, вероятно, имелся и менее приоритетный статус (или серия статусов), который был потерян.
Все ошибки, возникающие на этапах загрузки операционной системы Windows можно подразделить на две общие категории:

  • Ошибка NT_ERROR (NTSTATUS). Хорошо знакомый разработчикам статус, использующийся для передачи результатов ошибок между разными компонентами ОС. Используется в ошибках Bootmgr/Winload, то есть сразу начиная с этапа Bootmgr.
  • Ошибка BSOD BugCheck (STOP). Фатальная ошибка, хорошо знакомый всем нам синий экран смерти. Может возникать на поздних стадиях загрузки ОС, после того как подгружается логика обработки критических ошибок на этапе Ntoskrnl.
Код NTSTATUS - это 32-битное числовое значение, описывающее статус выполнения (результат завершения) кода подпрограммы/функции.

NTSTATUS частично описан в заголовочном файле ntstatus.h комплекта Windows WDK. Значения подразделяются на четыре категории:

  • NT_SUCCESS (0 − 0x3FFFFFFF);
  • NT_INFORMATION (0x40000000 − 0x7FFFFFFF);
  • NT_WARNING (0x80000000 − 0xBFFFFFFF);
  • NT_ERROR (0xC0000000 - 0xFFFFFFFF);

По коду можно заметить, что неотрицательные значения соответствуют "успешному" завершению подпрограммы, отрицательные — "ошибочному". Числовой статус обычно ассоциирован с текстовым описателем, который призван олицетворять понятный человеку, осмысленный текст ошибки (в теории, а на практике иногда весь мозг сломаешь в догадках). Полный список статусов NTSTATUS достаточно внушителен, но весь он нам не потребуется, поскольку далеко не все ошибки из этого списка мы можем наблюдать на изучаемых этапах загрузки Windows, а это, согласитесь, существенно облегчает нам работу :)

Некоторые особенности ошибок

У ошибок в коде Bottmgr я выделил несколько особенностей:

  • В коде Bootmgr присутствуют так называемых "перекодирующих процедур", которые на входе проверяют значения некоторых ошибок NT_ERROR (диапазон 0xC0000000-0xFFFFFFFF) и, в зависимости от неких условий, преобразуют их в предупреждения NT_WARNING (диапазон 0x80000000-0xBFFFFFFF). По этой причине некоторые ошибки пользователь вообще никогда не будет наблюдать на результирующем ошибочном экране, выводимом Bootmgr. Однако, я этот факт в своей работе не учитывал и описывал все без исключения ошибки.
  • Следующий немаловажный момент в логике обработки ошибок заключается вот в чем: Информационные сообщения об ошибках BootMgr/Winload, выводимые кодом модулей, вовсе не обязательно будут однозначно соответствовать уникальному значению NTSTATUS! Вот вам простой пример, наверняка многие видели на практике вот такую вот ошибку:

    А вот теперь та же самая ошибка, но с другим состоянием:

    Описание идентично, а коды разные!! Из этого следует, что одно текстовое сообщение об ошибке (сведения) может группировать сразу несколько родственных состояний (кодов ошибок). Если я нигде не ошибся, то для меня это, честно говоря, открытие! Получается, что разработчики решили особо не заморачиваться и не описывать в коде реакции на все возможные варианты ошибок, а ограничиться лишь конечным списком пояснений с выдачей конкретизирующего кода состояния (по которому и можно определить детали). И удивляться тут нечему, ведь данный факт опирается на бессмысленность генерации в коде реакции на все возможные состояния, поскольку код Bootmgr генерирует более 70 (!) уникальных ошибок, при том что многие неявны и по ним очень сложно работать, да и многие коды ошибок Bootmgr действительно одинаковы на разные события. Не думаю, что разработчик будет сидеть и корпеть над уникальным описанием для каждой ошибки.

  • Еще одна особенность ошибок Bootmgr проистекает из второго пункта и заключается в том, что одно и то же состояние (например, C00000001) может иметь различные причины возникновения внутри разных по назначению функций. Имеется ряд ошибок Bootmgr, под которые может подпадать достаточно широкий спектр проблем в разнообразных функциональных частях образа Bootmgr. В одной функции ошибка имеет один смысл, в другой функции - другой. Поэтому, подобные ошибки лишь с большой натяжкой могут быть подогнаны под общее определение, иногда лишь отдаленно отражающее реальную суть происходящего, соответственно и рекомендации по устранению могут иметь большое количество пунктов, логически не связанных между собой. Вот такая вот реальность!!

Учитывая все вышеописанные обстоятельства, мы примем на вооружение следующую логику:

При возникновении ошибки сначала обращаем внимание на код состояния (NTSTATUS), как на наиболее информативный, а уж затем, при необходимости, руководствуемся сведениями об ошибке.

Собственно, этот постулат и будет у нас основополагающим, мы будем изучать ошибки Bootmgr, а не их описания. Это позволит нам более детально локализовать, конкретизировать проблему, то есть сделать её более определенной в причине собственного возникновения.

BmFatalErrorEx

Хотелось бы еще отдельно упомянуть основную процедуру для вывода сообщений об ошибках на консоль, именуемую BmFatalErrorEx. Она вызывается примерно из 9 мест на протяжении всего кода Bootmgr. Сама процедура предназначена для группировки ошибок по классам и вывода ограниченного количества сообщений об ошибках. Я думаю практически всем специалистам приведенный ниже шаблон достаточно хорошо знаком:

Указанная самой последней строка "Сведения" может содержать одну из нижеследующих текстовых строк:

Русское обозначение Английское обозначение
An error occured while attempting to read the boot configuration data file
An error occured while attempting to load the boot application
Ошибка при перечислении глобальных параметров An error occured while enumerating global parameters
Произошла непредвиденная ошибка An unexpected error has occured
Возникла неожиданная ошибка ввода-вывода An unexpected I/O error has occured
Не удается загрузить выбранную запись, поскольку приложение отсутствует или повреждено. The selected entry could not be loaded because the application is missing or corrupt
Файл данных конфигурации загрузки Windows не содержит действительного элемента списка загрузки ОС. The Windows Boot onfiguration Data file does not contain a valid OS entry
Введена неверная группа цифр. Исправьте выделенную группу. Invalid group of digits entered. Please correct the highlighted group
Сбой меню загрузки, поскольку требуемое устройство недоступно. The boot selection failed because a required device is inaccessible.
Не удается завершить действие, поскольку не получен ключ программы шифрования диска BitLocker, необходимый для снятия блокировки с тома. The action could not be completed because the BitLocker Drive Encryption key required to unlock the volume could not be obtained
Не удается создать диск в памяти, поскольку недостаточно памяти Ramdisk device creation failed due to insufficient memory
Требуемая информация отсутствует в файле данных конфигурации загрузки Windows The Windows Boot Configuration Data file is missing required information
Попытка загрузить 64-разрядное приложение, однако данный процессор не совместим с 64-разрядным режимом. Attempting to load a 64-bit application, however the CPU is not compatible with 64-bit mode
Возможно, файл поврежден. Указанная в его заголовке контрольная сумма не совпадает с вычисленной. The file possibly corrupt. Its header checksum does not match the computed checksum
Не удается проверить цифровую подпись этого файла. Windows cannot verify the digital signature for this file
В хранилище данных конфигурации загрузки обнаружена недопустимая конфигурация элемента объекта. The configuration for an element within the object is invalid in the boot configuration data store
The boot manager experienced an error parsing element within BCD object.
The boot manager experienced error due to an invalid entry in the BCD store.
Файл хранилища данных конфигурации загрузки Windows содержит неправильные данные The boot configuration file is invalid.
No valid entries found in the boot configuration data file

Как можно заметить, не все ошибки имеют свою локализацию на русскому языке. Не знаю с чем это может быть связано, однако имеются две вероятных причины: я неправильно распарсил ресурсы главного модуля bootmgr.exe, либо пропустил какие-то записи в файле локализации bootmgr.exe.mui.
Ну и наконец то давайте уже переходит к анализу ошибок Bootmgr. Хотелось бы заметить, что вступление у нас было бы неполным, если бы сразу перешли к этапу Bootmgr и не осветили, хотя бы даже и поверхностно, стадии, которые ему предшествуют и относятся к процессу работы кода BIOS, MBR, PBR (VBR), ибо без них сюжетная линия повествования не была бы цельной.

Стадия BIOS

На IBM PC/AT-совместимой машине с классическим BIOS, код прошивки (firmware) на финальной стадии своего функционирования, по очереди перебирает устройства загрузки, заданные пользователем через меню настройки (Setup), и пытается считать с каждого из этих устройств загрузочный сектор. Сектор этот носит название Главной Загрузочной Записи (Master Boot Record, MBR). После загрузки с носителя загрузочного сектора, код BIOS проверяет наличие в последних двух байтах сигнатуры AA55h, и если сигнатура не обнаружена, то будет предпринята попытка перехода к другому устройству, если это устройство последнее в списке загрузки, то выдается одна из следующих ошибок (зависит от вендора оборудования):

Ошибка
  • Черный экран после прохождения POST;
  • Operating system not found;
  • MBR missing;
Описание BIOS не нашел Master Boot Record (MBR)! А записан ли он вообще? Необходимо удостовериться:

  • Правильно ли в BIOS задан загрузочный носитель? Не редки ситуации, когда ошибочно задается (или выбирается автоматически) другой, не имеющий системной разметки.
  • Заданный физический носитель размечен и на него определенно производилась установка операционной системы?
Решение Если Вы уверены, что носитель выбран правильно и система на него устанавливалась, то, вероятнее всего, повреждена информация в первом физическом секторе носителя. В этом случае требуется загрузиться в консоль восстановления и выполнить в командной строке следующую команду:
bootrec /fixmbr

Как Вы видите, с точки зрения ошибок финальная стадия BIOS достаточно проста, поскольку характеризуется всего-лишь невозможность нахождения кода MBR, а именно 512-байтного физического сектора с предопределенной сигнатурой AA55h.

Стадия MBR

Если коду BIOS удалось успешно считать первый физический сектор носителя в память и успешно проверить его сигнатуру, то он передает считанным данным управление. Начинает выполняться непосредственно сам код MBR. Поскольку в этом миниатюрном участке кода сложно выделить данные, то мы просто будем говорить о блоке кода и данных, который содержит всего три ошибки, детектируемые на стадии выполнения кода главной загрузочной записи. ASCII-строки ошибок располагаются во второй половине 512-байтного сектора и выглядят следующим образом:

Строки ошибок MBR

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

Ошибка Invalid partition table
Описание код MBR не нашел в таблице разделов активный раздел (маркер 80h), то есть раздел, с которого должна происходить дальнейшая загрузка. Повреждена таблица разделов, то есть она не содержит активного раздела для загрузки.
Решение Для начала попробуем автоматические средства. Загрузимся в консоль восстановления и выполним команду: bootrec /fixmbr
Ошибка Error loading operating system
Описание Код не смог считать сектор с носителя при помощи функций прерывания int 13h. Ошибку возвращает код BIOS, который взаимодействует с портами контроллера. Проблема в BIOS? Это слишком старая материнская плата, у которой имеются проблемы с обработкой int 13h? :) Или физическая проблема контроллера/носителя?
Решение
  • Обновить/сбросить BIOS.
  • Поменять материнскую плату на совместимую :)
  • Проверить шлейф;
  • Проверить накопитель на предмет аппаратных неисправностей.
Ошибка Missing operating system
Описание Считали загрузочный сектор раздела (PBR), однако у него сигнатура оказалась не AA55h. То есть, считается, что на месте сектора записан мусор. По какой то причине поврежден PBR. Скорее всего с самим разделом всё нормально, то он существует и назначен активным, а вот с первым сектором раздела что-то не так.
Решение Требуется восстановить PBR. Для этого загружается в консоль восстановления и выполняем команду: bootrec /fixmbr
bootrec /fixboot

Стадия PBR (VBR)

MBR нашел раздел, помеченный активным, загрузил с него первый физический сектор NTFS-раздела (партиции, тома) PBR (VBR), проверил его сигнатуру и передал ему управление. Как мы помним, основной целью кода PBR является загрузка Менеджера загрузки Windows (Windows Boot Manager, BootMgr) и передача ему управления.

Ошибка A disk read error occurred
Описание Универсальная комплексная ошибка, используемая кодом PBR сразу на нескольких стадиях:

  • код PBR в попытке проверить самого себя (!) сравнивает начальные байты сектора с ASCII-значением NTFS (сигнатура, которая предваряет Boot Parameter Block, BPB)
  • код не смог определить наличие расширений int 13h
  • код пытается получить расширенный блок параметров диска при помощи int 13h
  • код сравнивает значение из BPB, расположенного в начале сектора со значением, возвращенным функцией 48h прерывания int 13h.
Решение Ваш BIOS не поддерживает расширения прерывания работы с диском 13h? Такие ситуации у нас полностью должны быть исключены, ну конечно если Вы не откопали совсем уж старую материнскую плату :) Во всех остальных случаях остается вариант с поврежденным блоком BPB в загрузочном секторе раздела. Его можно восстановить целиком со всем PBR, загрузившись в консоль восстановления и выполнив команду:
bootrec /fixboot
Ошибка BOOTMGR is missing
Описание Код PBR не смог найти файл BOOTMGR на специализированном разделе.
Решение Идем по списку:

  • Сперва проверить фактическое наличие зарезервированного (скрытого) раздела, его целостность;
  • В случае присутствия раздела проверить (при помощи diskpart), помечен ли раздел как активный (active);
  • Проверить наличие на разделе необходимой файловой структуры, включающей и актуальный для данной системы файл Bootmgr.exe. Для PCAT/MBR-загрузки: неплохо было бы переписать Bootmgr.exe с системного диска из \Windows\Boot\PCAT\Bootmgr.exe.
Ошибка BOOTMGR is compressed
Описание Код PBR определил, что что-то не так с разделом, на котором располагается Bootmgr.
Решение Снять атрибут сжатия с раздела, на котором находится Bootmgr.
Ошибка An operating system wasn't found
Описание Очередная комплексная ошибка дополнительного кода PBR, возникает в следующих случаях:

  • Для PCAT/MBR- загрузки: код не смог найти активный раздел, с которого будет производиться загрузка файла Bootmgr. Нет раздела, помеченного как активный (active).
  • Код на может найти файл Bootmgr в корне несмонтированного системного раздела.
Решение
  • Загрузиться в среду восстановления и из командной строки при помощи diskpart назначить активный раздел;
  • Загрузиться в любую среду WinPE и скопировать в корень несмонтированного системного раздела файл Bootmgr. Файл должен быть той же версии. Обычно он содержится на разделе с установленной системой по пути %SystemRoot%\Boot\PCAT.

Стадия Boot Manager (BOOTMGR)

Вот тут то у нас и начинается самое интересное, собственно то, ради чего данная статья и задумывалась. Код PBR(VBR) находит зарезервированный загрузочный раздел (System Reserved), находит в корне раздела файл Bootmgr и загружает его в память, затем передает ему управление. Стоит обратить отдельное внимание на оригинальный файл Bootmgr, располагающийся в корне зарезервированного раздела. Если Вы заметили он не имеет расширения, поскольку это не исполняемый PE-файл в привычном нам понимании, а составной файл, содержащий в начале 16-битную "заглушку" реального режима и "запакованный" 32-битный PE-файл bootmgr.exe. После загрузки в память управление получает именно 16-битная "заглушка", которая и занимается переводом процессора в 32-битный защищенный режим, использующий плоскую модель памяти, распаковкой оригинального .exe-файла и передачей ему управления.

Инициализация

Bootmgr.exe стартует с основной процедуры BmMain, которая сразу же начинает выполнять инициализацию внутренних структур и ключевых аппаратных компонентов системы при помощи процедуры: BlInitializeLibrary. Эта процедура включает в себя такие подпрограммы как InitializeLibrary, ReinitializeLibrary. Код которых, в свою очередь, друг за другом вызывает следующие процедуры:

Процедура Описание
BlFwSetParameters Инициализация параметров, предназначающихся для последующей работы с функциями BIOS PC/AT. В том числе задается ключевой для всей логики параметр PcatServicesTable;
BlpMmInitialize Выделение памяти под рабочий процесс;
BlpTimeInitialize Замеры производительности системы, и определение параметра BlpTimePerformanceFrequency, который далее будет часто использоваться в коде;
BlpArchInitialize Инициализация служебных структур: глобальная таблица дескрипторов (GDT), таблица векторов прерываний (IDT), схема управления страницами физической памяти и прочее;
BlpTpmInitialize Инициализация модуля TPM;
BlpIoInitialize Инициализация файловых систем FAT32/NTFS для обеспечения доступа к основному системному разделу, содержащему операционную систему;
BlNetInitialize Инициализация сети. Используется для работы с PXE?;
BlUtlInitialize Инициализация внутренних переменных модуля. Для нас процедура на данный момент абсолютно не интересная;
PltInitializePciConfiguration Выделяет область памяти для работы с пространством PCI;
BlpSiInitialize Инициализация подсистемы безопасности;
BlBdInitialize Проверка на наличие отладчика этапа загрузки. Конфигурирование отладки режима загрузки;
BlpLogInitialize Конфигурирование файла хранения журнала загрузки;
BlpDisplayInitialize Инициализация консоли для вывода. Под консолью подразумевается как текстовый, так и графический локальный терминал, так и удаленная сетевая консоль.
BlpResourceInitialize Инициализация данных в ресурсной (.rsrc) секции, получения параметров дисплея, загрузка данных из файлов локализации (.mui), инициализация локали. Достаточно важная, я бы даже сказал, ключевая процедура, поскольку именно от её функционирования зависит дальнейшая работа с конфигурационными файлами.

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

Текст вывода намекает нам на то, что произошел сбой в какой-то из перечисленных выше подпрограмм. Поскольку данная ошибка охватывает достаточно большой диапазон кода и не имеет текстового описателя, то оператору будет довольно сложно понять в какой именно подпрограмме она возникла. Из этого следует, что единственный способ выявить причину, это попытаться вычислить её по коду ошибки. А что, в свою очередь, представляет из себя код 0xXXXXXXXX? Так ведь это же описанный выше NTSTATUS. Коды ошибок и их описания смотри в разделе ниже. Ну а мы двигаемся дальше.

Открытие BCD

После первичной инициализации логика bootmgr выполняет открытие файла данных конфигурации загрузки (BCD), который размещается:

  • Для традиционной PC/AT (MBR) загрузки -- на активном разделе по пути \Boot\BCD;
  • Для современной UEFI загрузки -- на разделе EFI по пути \EFI\Microsoft\Boot\BCD;

Для достижения этой цели используется процедура под названием BmOpenDataStore.

Файл данных конфигурации загрузки (Boot Configuration Data, BCD) - база данных, содержащая конфигурацию отдельных аспектов этапа загрузки. По структуре идентична файлу реестра Windows, после загрузки монтируется в куст HKLM\BCD00000000.

Как Вы уже поняли, BCD является одной из ключевых структур процесса загрузки, содержащей пункты меню загрузки, описывающие пути и настройки определенных элементов конфигурации. Естественно, что любые проблемы с этой базой сразу же выливаются в критические ошибки Bootmgr и невозможность продолжения процесса загрузки операционной системы.
Далее проверяются настройки журналирования этапов загрузки и если логгирование включено, то статус записывается в файл %SystemDrive%\Boot\bootstat.dat процедурой BmpInitializeBootStatusDatalog.
Затем процедура BlResourceFindHtml используется для поиска ресурсного файла bootmgr.xsl внутри ресурсной секции (.rsrc) образа файла bootmgr.exe.

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

Затем предпринимается попытка найти файл bootmgr.exe.mui, содержащий локализованные версии сообщений. На этапе поиска ресурсов, в случае возникновения проблем с нахождением/открытием оных, мы можем наблюдать ошибку:

Тут у нас ситуация, похожая ту, которая описывалась на этапе инициализации. Текст данной ошибки Bootmgr говорит о том, что в процедуре возникла проблема с нахождением ключевых ресурсов, которые потребуются в дальнейшей работе. Поскольку процедура многосоставная, то и источников проблемы может быть множество. Одной из причин данной ошибки могут быть проблемы с файлом bootmgr.xsl, поскольку без параметров, в нем описанных, дальнейшее выполнение невозможно. Коды ошибок у нас опять же сгруппированы в разделе под названием "Возникающие ошибки" ниже по тексту.
Далее ссылка на данные, загруженные из файла bootmgr.xsl передается процедуре BlXmiInitialize, которая предназначена для разбора содержимого файла и вывода на консоль меню загрузки на основе обнаруженных настроек. В случае, когда инсталлировано несколько операционных систем, либо присутствует несколько пунктов выбора, процедура отображает текстовое меню загрузки и ожидает пользовательского выбора.
при неудачном окончании процедуры выдается ошибка:

Ошибка говорит нам о том, что на этот раз уже с содержимым файла bootmgr.xsl что-то не так. Вероятно, присутствуют ошибки в операндах, структуре. Возможно, пользователь пытался изменить внешнее представление меню при помощи какой-то редактора и допустил ошибку.
Далее происходит проверка собственной цифровой подписи при помощи процедуры BmFwVerifySelfIntegrity. На этом этапе мы можем видеть ошибку C0000428.
Отдельно происходит проверка на наличии файла гибернации hiberfil.sys при помощи процедуры BmResumeFromHibernate, и в случае необходимости, код вызывает winresume.exe и начинает восстановление системы из режима гибернации.

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

Честно признаюсь, воочию я никогда в живой природе подобной ошибки не наблюдал, да и судя по коду она возникает только в случае подключенного отладчика в теле процедуры BlStatusError непосредственно перед передачей управления отладчику посредством вызова прерывания командой int 3, поэтому акцентировать внимание мы на ней не будем.

Загрузка пункта и передача управления OSLoader

Этот этап у нас является финальным в логике работы модуля Bootmgr. Когда пункт загрузки выбран пользователем, либо назначен автоматически, процедура под названием BmpLaunchBootEntry начинает загружать выбранный пункт загрузки. Процедура BlImgStartBootApplication через подмножество вложенных процедур передает параметры и управление загрузчику операционной системы следующего этапа под названием winload.exe (OSLoader), располагающемуся на выбранном разделе по пути ?:\Windows\System32\winload.exe либо ?:\Windows\System32\boot\winload.exe.

Возникающие ошибки

Для удобства поиска по коду ошибки и её описателю, в данном разделе будут сведены воедино все ошибки Bootmgr, возникающие на различных стадиях процесса функционирования кода модуля. Сортироваться у нас они будут по коду NTSTATUS и иметь возможные варианты описания причины возникновения. К сожалению, таблица получилась не достаточно удобной, однако другого формата представления данных я пока не придумал, поэтому что есть то есть.

Код ошибки Контекст / Причина
C0000001
STATUS_UNSUCCESSFUL
Запрошенная операция была неудачной.
BlpNetInitialize :: Выставляется, если параметр BlpPxeInfo равен нулю.
BlpNetSoftReboot :: Выставляется, если параметр BlpPxeInfo равен нулю.
BmpGetCustomAction :: Возникает при проверке списка возвращенных опций из BlpGetBootOptionIntegerList.
BmPopulateBootEntryList :: Возникает при ошибке MiscGetBootOption, которая ищет опции загрузки по заданному типу.
BmpInitializeDisplayMeasurements :: Возникает как реакция на ошибку BlResourceFindMessage, которая ищет ошибку в ресурсной секции по её идентификатору.
DmDisplayFveRecovery :: Возникает как реакция на ошибку BlResourceFindMessage, которая ищет ошибку в ресурсной секции по её идентификатору.
DmDisplayFvePinEntry :: Возникает как реакция на ошибку BlResourceFindMessage, которая ищет ошибку в ресурсной секции по её идентификатору.
BmpResumeCreateBootEntry :: Возникает при проверке существования опции загрузки, получении описателя записи загрузки.
BmpBootIniConvertToOptionList :: Возникает как реакция на ошибку AhCreateLoadOptionsList, которая создает список опций загрузки для записи загрузки.
PcatGetNextE820Descriptor :: Возникает как реакция на ошибку PcatBiosInterrupt, которая вызывает прерывание.
FvebpPromptForExternalMedia :: Возникает как реакция на ошибку отклика от консоли вывода.
DeviceTablePurge :: Возникает при проверке открыто ли уже текущее устройство.
BcInitialize :: Возникает если BcpBlockAllocatorHandle = -1.
UdpFirmwareReceivePacket :: Возникает при проверке таймера через BlpFwCheckTimer.
VhdiDynamicReadWriteAtOffset :: Возникает при проверке первого входного аргумента функции на не нулевое значение.
VhdiReadVhdInfornationAtOffset :: Возникает при проверке четвертого входного аргумента функции.
BlDisplayGetCharacterResolution :: Возникает при проверке параметра DspTextConsole на нулевое значение.
BlDisplayGetTextColor :: Возникает при проверке параметра DspTextConsole на значение 14h.
BlDisplayGetScreenResolution :: Возникает при проверке параметра DspTextConsole на нулевое значение.
BfiPrintBitmap :: Возникает при проверке входных параметров функции.
ConsoleTextLocalSetTextResolution :: Возникает при проверке результата ConsolepFindResolution, которая выполняет поиск разрешения в списке.
ConsoleGraphicalGetConsoleResolution :: Возникает при проверке значения переменной блока входных параметров.
ConsoleGraphicalGetOriginalResolution :: Возникает при проверке значения переменной блока входных параметров.
ConsoleGraphicalGetOriginalFormat :: Возникает при проверке значения переменной блока входных параметров.
ConsoleGraphicalClearPixels :: Возникает при проверке значения переменной блока входных параметров.
ConsoleGraphicalReadPixels :: Возникает при проверке значения переменной блока входных параметров.
ConsoleGraphicalWritePixels :: Возникает при проверке значения переменной блока входных параметров.
ConsoleGraphicalGetFrameBuffer :: Возникает при проверке значения переменной блока входных параметров.
BfiMapCharacterCodeToGlyphIndex :: Возникает при проверке входных параметров функции.
ConsolePcatFindModeFromAllowed :: Возникает при проверке входных параметров функции.
ConsolePcatFindTargetMode :: Возникает при ошибке функции ConsolePcatFindModeFromAllowed.
FileTablePurgeEntry :: Возникает при проверке входных параметров функции.
FileIoOpen :: Возникает при ошибке нахождения записи о файле в файловой системе.
FatMount :: Возникает при отсутствии инструкции jmp (E9h) в первом байте загрузочного сектора раздела, то есть это не FAT!.
FatpIoOperation :: Статус по умолчанию?
EtfspCheckEtfs ::
EtfspCheckCdfs :: Возникает при ошибке сравнения имен посредством функции EtfsCompareNames.
UdfspGetNextDirectoryEntry :: Возникает при сравнении локального параметра (?) со значением 101h.
NtfsMount :: Возникает как реакция на неправильное значение параметра в BPB.
NtfsDecodeUsa :: .
NtfspDeviceReadAtOffset :: Возникает при проверке входного параметра на определенное значение.
NtfspDeviceWriteAtOffset :: Возникает при проверке входного параметра на определенное значение.
NtfspFileRecordPurgeEntry :: Выставляется при проверке блока входных параметров.
NetMount :: Выставляется при проверке входного параметра.
WimpValidateWim :: Ошибка проверки длины wim-образа.
BsdpGetLogControl :: Выставляется, если функция BlFileReadAtOffset вернула ошибку.
BsdpWriteAtLogOffset :: Выставляется, если функция BlFileWriteAtOffset вернула ошибку.
PxeGetBcdFilePath :: Выставляется при проверке на ноль второго параметра функции PxepGetPacketByType.
PxeGetBcdFilePath :: Выставляется как реакция на ошибку в функции PxepFindOption.
PxepGetInformation :: Выставляется при проверке на ноль второго параметра функции PxepGetPacketByType.
BlUtlRegisterMulticastRoutine :: Появляется если параметр UtlMcDisplayMessageRoutine равен нулю.
BlUtlRegisterProgressRoutine :: Появляется если параметр UtlProgressRoutine равен нулю.
BlEnRegisterEventHandler :: Появляется если параметр EnSubsystemInitialized равен нулю.
BlPdFreeData :: Возникает как реакция на ошибку в BlMmTranslateVirtualAddress, которая выполняет преобразование реальных и виртуальных адресов.
TblDoNotPurgeEntry :: Функция всегда возвращает данный код.
BlTftpQueryFileSize :: Возникает как ошибка при вычислении длины получаемого по TFTP файла
TftppGetImageRegular :: Выставляется, если первый входной параметр функции равен нулю.
TftppGetImageWindow :: Ставится при равенстве пятого входного параметра некоему значению.
TftppReceive :: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
TftppNegotiate :: Ставится при возврате в eax значения 0FFFFFFFFh из функции TftppSafeAtol.
PxeApiService :: Возвращается в коде ошибки в любом случае.
PxeSoftReboot :: Выставляется в случае значения переменной BlpPxeInfo, отличной от нуля.
SipGetOrCreatePersistentState :: Ошибка выставляется при значении определенной переменной в блоке параметров BlpLibraryParameters значению 100h.
SipInitializePhase1 :: Выставляет при вхождении подсистемы безопасности в некое незащищенное состояние. Пока не ясно, что это такое?
SipGracefulCloseEnvironment :: Возникает при проверке некоего глобального статуса безопасности (?).
BlTpmpFirmwareCall :: Возникает после проверки некоего глобального параметра, указывающего на номер функции работы с TPM. Если не укладываемся в диапазон функций, то ошибка.
ImgPcatStartLegacyLoader :: Возникает при ошибках функций RtlUnicodeStringToAnsiString и BlGetBootOptionString.
ImgPcatStartRestartBootcode :: Код ошибки в любом случае устанавливается на выходе функции.
BlMmFreeHeap :: Выставляется при проверке параметра HapInitializationStatus на несоответствие значению 1.
BlMmAllocateMemoryBlocks :: Выставляется при нулевом значении параметра MmBlockAllocatorInitialized.
BlMmDeleteBlockAllocator :: Выставляется при нулевом значении параметра MmBlockAllocatorInitialized.
BlpMmFreeMemoryBlocks :: Выставляется при нулевом значении параметра MmBlockAllocatorInitialized.
MmBapPurgeBlockAllocatorTableEntry :: Возникает при проверке блока входных параметров.
BcdGetElementDataWithFlags ::
BcdDeleteElement ::
BdpReconfigureDebuggerDevice :: Возникает при невозможности инициализировать контроллер шины 1394.
BdSetupPciDevice :: Ошибка выставляется, когда функция поиска отладочного устройства BdSearchForPciDebuggingDevice ничего не находит.
BdSendWaitContinue :: Возникает при проверке ошибок от множества функций, в том числе от BdMoveMemory и KdTransportMaxPacketSize.
BdWriteBreakPointEx :: возникает при проверке статуса выполнения функции BdDeleteBreakPoint.
BdRestoreBreakPointEx :: возникает при проверке статуса выполнения функции BdDeleteBreakPoint.
FveStatusFromHResult :: Возникает при перекодировке определенных статусов Bitlocker.
FveDatumCreateAndCopy ::
FveDatumFree :: Возникает при проверке локальной переменной.
Dbg1394_ReadPhyRegister :: Возникает как реакция на ошибку в функции BL_READ_REGISTER_ULONG.
Dbg1394_InitializeController :: Возникает при невозможности инициализировать контроллер шины 1394.
C0000002
STATUS_NOT_IMPLEMENTED
Запрошенная операция не выполнена.
BlDeviceEnumerateDeviceClass :: Выставляется при нулевом значении переменной BlockIoDeviceFunctionTable.
BlpDeviceOpen :: Выставляет при неподдерживаемом типе устройства.
BlockIoEnumerateDeviceClass :: Выставляется при нулевом значении переменной DiskDeviceFunctionTable.
BlockIoCreate :: Выставляется при проверки серии глобальных переменных на нулевое значение.
UdpEnumerateDeviceClass :: Единственный код возврата из функции. Вероятно говорит о том, что данная функция не доработана?
UdpReset :: Единственный код возврата из функции. Вероятно говорит о том, что данная функция не доработана?
ConsoleGraphicalSetTextResolution :: Выставляется, если первый параметр функции нулевой.
BfiGetEbdtBitmapInformationFromSubTable ::
BfiReadEbdtImage :: Выставляется при проверке значения третьего входного параметра функции.
WimWrite :: Единственный код возврата из функции. Вероятно говорит о том, что данная функция не доработана?
NtfspReadWriteAttributeEx :: Выставляется при нулевом значении седьмого входного параметра функции.
BlTpmpFirmwareCall :: Выставляется при отсутствии необходимых функций для работы с TPM.
BlTcgFwGetLog :: Выставляется при различных проблемах дешифровки проверки TPM/дешифровки содержимого.
MmPaeInitializeTranslation :: Выставляется при ненулевом значении второго входного параметра функции.
MmDefInitializeTranslation :: Выставляется при ненулевом значении второго входного параметра функции.
RtlpImageDirectoryEntryToData32 ::
RtlpImageDirectoryEntryToData64 ::
FveStatusFromHResult :: Выставляется при результате 80004001 (Unable to activate partition) BitLocker.
FveVmkInfoProcess :: Выставляется при проверке некой локальной переменной на значение 1?
C0000005
STATUS_ACCESS_VIOLATION
Инструкция обратилась к определенному адресу памяти и не может выполнить (чтение/запись/выполнение).
BdTrap0d ::
BdTrap0e ::
C000000E
STATUS_NO_SUCH_DEVICE
Заданное устройство не существует.
BmOpenDataStore :: возникает при неготовности PXE.
BmResumeProbeLegacyHiberFile :: Не может получить доступ к устройству загрузки.
BmReadBootIni :: Выставляется как реакция на ошибку в функции BlGetBootOptionDevice, которая получает различные опции для устройства загрузки.
FileDeviceOpen :: Возникает как реакция на ошибку в функции BlDeviceOpen.
DiskFirmwareOpen :: Устанавливается, если переменная NextDiskNumber больше FirmwareDisks.
CdromFirmwareOpen :: Возникает при проверке блока параметров, на который указывает BlpRootDevice.
FloppyFirmwareOpen :: Возникает, если переменная NextFloppyNumber больше значения 2.
BlNetSoftReboot :: Возникает если переменная BlpBootDevice принимает нулевое значение.
PxeGetBcdFilePath :: Выставляется при проверке переменной BlpPxeInfo на нулевое значение.
AhGetBootEnvironmentDevice :: Выставляется при проверке локальной переменной после вызова BlDeviceEnumerateDeviceClass и при равенстве переменной BlpPxeInfo нулю.
AhGetFilePath :: Генерируется при проверке выходных переменных функции BlGetDevice.
PltpCheckDeviceExistence :: Устанавливается при ошибках доступа к устройству по шине.
C000000F
STATUS_NO_SUCH_FILE
Файл не найден. Файл не существует.
BmpReadBootIni :: Возникает при проверке параметра из блока параметров BlpPxeInfo.
FvebpReadKeyFile :: Возникает при несовпадении при сравнении внутреннего параметра с аргументом. Скорее всего по факту считывания блока данных, относящего к ключевому файлу BitLocker'а из внешнего источника.
FvebpSearchForKeyFileNoPrompt :: Возникает при ошибке выполнения функции BlDeviceEnumerateDeviceClass. Скорее всего отсутствует ключевой файл BitLocker'a.
FileDeviceOpen :: Возникает при ошибке в функции BlpFileOpen. В глобальном плане система не может найти файл следующего этапа (зачастую это \Windows\System32\Winload.exe (Winload.efi)).
RdpLoadImage :: Возникает при ошибке в функции RdpQueryImageSize. Вероятно, в глобальном плане это ошибка загрузки образа виртуального диска (ramdisk).
RdpUnlockSourceDevice :: Устанавливается как реакция на ошибку функции BlGetDevice. Относится к виртуальному диску (ramdisk).
RdpLoadFileToImage :: Возникает при ошибке функции BlGetFilePath. В глобальном плане функция монтирует файл в образ в памяти (ramdisk).
FatpGetNextDirent :: Вероятно, возникает при вычислении следующего элемента файловой таблицы?
EtfspSearchForDirent :: Появляется при ошибке функции EtfspGetDirent. В глобальном плане имеется в виду файловая система El Torito File System, используемая на CD диска. Скорее всего ошибка поиска записи в файловой системе.
EtfspGetDirent :: Ошибка в получении записи файла из файловой системы El Torito File System.
UdfspSearchForMatchingFid :: Возникает при проблемах получения записи о файле при помощи функции UdfspGetNextDirectoryEntry. Подразумевается файловая система udfs, которая может использоваться на широком спектре сменных носителей (чаще оптические диски).
NtfspSearchForFileIndexEntryEx :: Генерируется при ошибке функции NtfspGetNextFileIndexEntry, которая выполняет поиск записи о файле в файловой системе ntfs.
NtfspGetNextFileIndexEntry :: Генерируется при ошибке функции NtfspGetNextIndexEntry, которая выполняет поиск записи любого типа в файловой системе ntfs.
WimOpen :: Возникает при работе с блоком данных WimFunctionTable. В глобальном плане это попытка открытия wim-образа инсталляции.
WimpSearchForDirent :: Ошибка поиска файловой записи в образе.
BlTftpQueryFileSize :: Устанавливается при ошибках длины удаленного файла.
TftppReceive :: Генерируется при проверке входного параметра на значение 100h.
C0000010
STATUS_INVALID_DEVICE_ REQUEST
Указанный запрос является не допустимой операцией для целевого устройства.
BlockIopReadWriteVirtualDevice ::
UdpOpen ::
UdpRead ::
UdpWrite ::
DeviceLogGetDeviceInfo ::
NetOpen ::
NetRead ::
NetWrite ::
C0000011
STATUS_END_OF_FILE
Достигнут конец файла. Далее данной отметки в файле данных не обнаружено.
NtfspGetNextIndexEntry :: Возникает при отсутствии следующего индекса в цепочке кластеров. Данных для файла больше нет.
NtfspReadWriteAttribute :: Возникает при проверке входных параметров функции. Скорее всего при проверке атрибутов файла.
C0000017
STATUS_NO_MEMORY
Не хватает виртуальной памяти или файла подкачки для завершения операции.
BlMmAllocateHeap :: Возникает, когда функция не смогла выделить кучу (блок) памяти коду произвольной стадии. Выделение памяти инициируется в более чем 180 (!) фрагментах кода Bootmgr, однако привести огромный список всех процедур пока не могу. Причина ошибки может быть:

  • проблемы в работе оперативной памяти;
  • недостаточное количество оперативной памяти;
  • интегрирование большого количества драйверов в образ;
  • интегрирование большого количества приложений в образ;
C0000022
STATUS_ACCESS_DENIED
Процесс запросил доступ к объекту, но не был наделен правами доступа.
CdromFirmwareOpen :: Выставляется при проверке типа устройства загрузки, содержащемся в переменной BlpBootDevice
FileIoOpen :: Проверяется валидность и наличие DeviceID в таблице DmDeviceTable.
TftppReceive :: Выставляется при проверке входного аргумента функции на значение 100h (512).
C0000023
STATUS_BUFFER_TOO_SMALL
Буфер слишком мал, чтобы уместить запись. Информация не записана в буфер.
BmpProcessBadMemory :: Возникает обработка вызова BlPdQueryData
BmGetOptionList :: Функция предназначена для загрузки опций приложений из BCD. Возникает при обработке возвращаемых значений из BcdEnumerateAndUnpackElements
BmErrorGetData :: Возникает если ячейка loc_404607 = 0.
BmpHandleInvalidBcdEntryEvent :: возникает при обработке ошибки из BcdGetElementDataWithFlags
BmpBootIniConvertToOptionList :: возникает при обработке ошибки из AhCreateLoadOptionsList
FvebpLogError :: возникает при обработке ошибки из FveDatasetAppendDatum
PartitionEnumerateDeviceClass :: возникает при обработке ошибки из PartpEnumerateGptPartitions
PartpEnumerateMbrPartitions :: возникает при обработке результатов из PartpTraverseMbrPartitions
PartpEnumerateGptPartitions ::
DiskEnumerateDeviceClass ::
RdDeviceEnumerate ::
FatGetNextFile ::
EtfsGetNextFile ::
UdfsGetNextFile ::
NtfsGetNextFile ::
WimGetNextFile ::
PxeAddDhcpOption ::
BlLogData :: Функция предназначена для записи статуса операции в bootlog.
BlImgLoadImageWithProgressEx ::
ImgpLoadPEImage ::
BlPdQueryData ::
AhGetFilePath ::
ArcConvertStringIntegerToOption ::
ArcConvertStringToOption ::
BlTftpGetImage ::
BlTcgFwGetLog ::
ImgPcatStartLegacyLoader ::
BlMmGetMemoryMap ::
BiConvertRegistryDataToElement ::
BiEnumerateSubObjectElements ::
BiConvertBcdElements ::
FveWorksetCommit ::
FveGetExternalFileName ::
FveDatasetAppendDatum ::
FveKeyringCreate ::
FveKeyringCreateDataset ::
sub_44CBDF ::
C0000024
STATUS_OBJECT_TYPE_ MISMATCH
Существует несоответствие между типом объекта, который требуется по запрошенной операции и типом объекта, указанным в запросе.
FvebOpen ::
FvebpCheckAndAllocateFvebDevice ::
BiGetObjectDescription ::
BiConvertRegistryDataToElement ::
BiGetRegistryValue ::
sub_44CBDF ::
C0000032
STATUS_DISK_CORRUPT_ ERROR
Структура файловой системы на диске повреждена и непригодна для использования. Запустите служебную программу chkdsk для тома.
WimpinitilizeDecompressionWordspace ::
C0000033
STATUS_OBJECT_NAME_ INVALID
Имя объекта является недействительным.
VhdiLoadVerifyParentVhd ::
C0000034
STATUS_OBJECT_NAME_NOT_ FOUND
Имя объекта не найдено.
BiOpenKey :: Возникает как реакция на значение 0FFFFFFFFh в статусе ошибки при возврате из CmpFindSubKeyByName.
BiEnumerateSubKeys :: Возникает при сравнении какого то параметра с 0.
CmpFindSubKeyInLeafWithStatus :: .
CmpFindSubKeyByHashWithStatus :: .
CmpFindNameInListWithStatus :: .
C0000035
STATUS_OBJECT_NAME_ COLLISION
Имя объекта уже существует.
BlHtStore :: Возникает при обработке возвращенной ошибки из BlHtLookup
C000003F
STATUS_CRC_ERROR
Ошибка контрольной суммы.
FveAesCcmDecrypt :: возникает как реакция на возвращаемые значения процедурой FvepAesCcmComputeUnencryptedTag
C0000040
STATUS_SECTION_TOO_BIG
Указанный раздел слишком большой, чтобы быть отображенным на файл.
ImgPcatStartLegacyLoader :: возникает по причине стартового адреса, меньше чем 7F000h
C0000059
STATUS_REVISION_MISMATCH
Указывает на то, что два уровня редакции являются несовместимыми.
BmpGetCustomAction :: возникает по причине стартового адреса, меньше чем 7F000h
BmErrorGetData :: Возникает при проверке каких-то данных, возвращаемых BlPdQueryData.
C000007A
STATUS_PROCEDURE_NOT_FOUND
Адрес процедуры не найден в библиотеке DLL.
FveLibAllocZero :: возникает как реакция на несоответствие какого-то глобального параметра на входе процедуры.
FveLibUnseal :: возникает при проверке глобального параметра 46D1BC на входе процедуры.
FveLibRandom :: возникает при проверке глобального параметра 46D1BC на входе процедуры.
FveLibGetTime :: возникает при проверке глобального параметра 46D1BC на входе процедуры.
FveLibFree :: возникает при проверке глобального параметра 46D1BC на входе процедуры.
C000007B
STATUS_INVALID_IMAGE_ FORMAT
Образ либо не предназначен для выполнения в Windows, либо содержит ошибку в структуре.
BmpResumeProbeLegacyHiberFile :: Генерируется при некорректном заголовке файла гибернации (hiberfil.sys).
BmpResumeReadLegacyHiberFileHeader :: Выставляется при проверке некоторых атрибутов файла гибернации (hiberfil.sys).
BmpResumeInvalidateLegacyHiberfile :: Выставляется при проверке некоторых атрибутов файла гибернации (hiberfil.sys).
BfiInitializeFonts :: Появляется при проверке входного параметра. Глобально функция относится к коду по работе со шрифтами.
BfiLoadFontFile :: Возникает проверке структуры считываемого файла шрифта.
BfiConvertIndexSubTable :: .
BfiReadCmapTable :: Возникает при ошибке чтения блоков данных из файла шрифтов.
BfiReadEdbtImage :: Возникает при ошибке чтения блоков данных из файла шрифтов.
BfiReadSegmentMapHeader :: Возникает при ошибке чтения блоков данных из файла шрифтов.
BfiValidateFontNameTable :: Возникает при проверке таблицы имен шрифта.
ImgpLoadPEImage :: Возникает при проверке загружаемого PE-образа.
ResInitializeMuiResources :: Возникает при попытке найти секции различного назначения в PE-образе.
ImgArchPcatLoadBootApplication :: Возникает при загружаемого образа на валидность.
RtlImageNtHeaderEx :: Генерируется при отсутствии корректной сигнатуры 'MZ' заголовка .exe-файла.
LdrRelocateImageWithBias :: Появляется при проверке загружаемого образа через функцию RtlImageNtHeader.
C0000095
STATUS_INTEGER_OVERFLOW
Целочисленное переполнение.
RtlULongAdd ::
RtlULongLongToULong ::
BmpReadBootIni ::
RtlULongLongAdd ::
RtlULongSub ::
RtlULongLongSub ::
RtlULongLongMult ::
FvebpCheckAndAllocateFvebDevice ::
BfiReadEblcIndexSubTables ::
RtlULongPtrAdd ::
UdfspValidateFileIcb ::
BlGetApplicationImageName ::
MmHapHeapAllocatorExtend ::
BlXmiTransformTextForXml ::
C0000098
STATUS_FILE_INVALID
Раздел, на котором размещался файл был изменен извне, таким образом открытый файл больше не действителен.
BmpGetSelectedBootEntry :: возникает при проверде данных, возвращенных из BmEnumerateBootEntries.
BmFwVerifySelfIntegrity :: возникает при обработке параметров из RtlImageNtHeader.
UdfspFileRead :: возникает при проверке каких то значений.
WimpReadResource :: .
WimpFixupSecurity :: .
WimpFixupDirectory :: .
WimpFixupStreams :: .
WimpRead :: .
WimpDecompress :: .
BlImgGetModuleName :: .
BlImgVerifySignedPeImageFileContents :: .
ImgpLoadPEImage :: .
BdpPopulateDataTableEntry :: .
C000009A
STATUS_INSUFFICIENT_ RESOURCES
Недостаточно системных ресурсов для завершения вызова API.
Генерируется при ошибках функции выделения блока памяти BlMmAllocateHeap. Приводить список всех процедур не имеет особого смысла. Вероятно причиной является: недостаточное количество доступной физической памяти, физически неисправная память, попытка загрузиться со сжатого диска VHD(X), размер которого превышает 100 Гбайт.
C000009C
STATUS_DEVICE_DATA_ ERROR
На жестком диске имеются сбойные блоки (сектора).
BdSetupPciDevice ::
C000009D
STATUS_DEVICE_NOT_CONNECTED
Проблема с кабелем, диск не терминирован, или контроллер не смог получить доступ к жесткому диску.
RcpGetEmsParameters :: относится к службе аварийного управления?
BdTrap :: .
C00000A0
STATUS_MEMORY_NOT_ALLOCATED
Была сделана попытка освободить виртуальную память, которая не выделялась.
BlImgUnloadBootApplication ::
C00000A2
STATUS_MEDIA_WRITE_ PROTECTED
Запись на диск невозможна, потому что он защищен от записи. Снимите защиту от записи.
BiDeleteKey ::
FveDecryptRegion :: .
FveEncryptRegion :: .
FveFilteredWrite :: .
C00000A3
STATUS_DEVICE_NOT_READY
Привод не готов к использованию; возможно открыта дверца. Убедитесь, что диск вставлен и дверца привода закрыта.
BlpDeviceOpen ::
C00000BA
STATUS_FILE_IS_A_DIRECTORY
Файл, который был указан как целевой, является директорией, а вызывающий код указал, что это может быть что угодно, но не каталог.
FatRead ::
FatWrite :: .
NtfsRead :: .
NtfsWrite :: .
NtfsSetInformation :: .
C00000BB
STATUS_NOT_SUPPORTED
Запрос не поддерживается.
BmProcessCustomAction :: возникает как реакция на выходную ошибку BmpGetCustomAction.
BmpCreateDevices :: возникает при работе с входными параметрами.
BmpBootIniParseLine :: возникает при возврате из strnicmp при сравнении с "c:\".
PcatVesaGetVideoMode :: ??? не факт, маска.
PcatVesaGetVideoModeInformation :: .
BlpDeviceResolveLocate :: .
UdpSetInformation :: .
PartitionEnumerateDeviceClass :: .
PartpOpenMbrPartition :: .
PartpOpenGptPartition :: .
PartpCreatePartitionDeviceEntry :: .
PartpTraverseMbrPartitions :: .
VhdiBuildVhdData :: .
VhdiVerifyAndInitializeVhd :: .
VhdiVerifyVhdFooter :: Возникает при проверке завершающего блока vhd-образа, скорее всего параметра Current Size, то есть длины.
VhdiFileDeviceReadWrite :: .
VhdiReadVhdInformation :: .
DiskPcatGetDiskInformationEx :: .
BfiGetFontStrikeForCharacter :: .
BfiGetFontStrikeForResolution :: .
ConsoleTextSplitterGetTextState :: .
ConsoleTextSplitterGetTextResolution :: .
ConsoleTextSplitterSetTextResolution :: .
ConsoleGraphicalSplitterGetConsoleResolution :: .
ConsoleGraphicalSplitterGetGraphicalResolution :: .
ConsoleGraphicalSplitterGetOriginalResolution :: .
ConsoleGraphicalSplitterSetGraphicalResolution :: .
ConsoleGraphicalSplitterGetCharacterResolution :: .
ConsoleGraphicalSplitterGetTextCellResolution :: .
ConsoleGraphicalSplitterGetFormat :: .
ConsoleGraphicalSplitterGetOriginalFormat :: .
ConsoleGraphicalSplitterReadPixels :: .
ConsoleGraphicalSplitterGetFrameBuffer :: .
BfiGetTableOffsetAndSize :: .
NtfspReadWriteNonResidentAttributeEx :: .
BlNetSoftReboot :: .
ImgpGetFileSize :: .
ImgPcatStartLegacyLoader :: .
BlMmAllocatePagesInRange :: .
PltpAccessPciConfig :: .
RtlCompressWorkSpaceSizeLZNT1 :: .
RtlUnicodeToMultiByteN :: Всегда возвращает значение в eax (на выходе).
C00000BD
STATUS_DUPLICATE_NAME
Дубликат имени обнаружен в сети.
SipGetOrCreatePersistentState ::
C00000C0
STATUS_DEVICE_DOES_NOT_ EXIST
Данное устройство не существует.
ImgpCopyApplicationBootDevice ::
BlTpmpHardwarePresent ::
C00000E4
STATUS_INTERNAL_DB_CORRUPTION
Запрошенная операция не может быть завершена из-за катастрофического сбоя носителя или повреждении структуры данных на диске.
FveInitializeCrypto ::
sub_44CBDF :: возникает как реакия на выходной параметр GveDatumKeyGetSize
C00000E9
STATUS_UNEXPECTED_IO_ ERROR
Если возвращается ошибка ввода-вывода, которая не определена в стандартном фильтре FsRtl, она конвертируется в данный код. Непредвиденная ошибка ввода-вывода. Скорее всего проблемы с чтением носителя.
FvebpEndTpmBinding ::
BlockIoPcatExtendedInt13 :: Выдается при проблемах чтения с устройства. Сигнализирует о проблемах чтения с устройства.
BlockIoPcatConventionalInt13 :: Выводится при возникновении проблем чтения с загрузочного носителя.
DiskPcatGetLegacyGeometry ::.
DiskPcatGetDiskInformationEx ::.
UdfspFileRead ::.
UdfspVolumeRead ::.
NtfspGetNextIndexEntry ::.
C00000F0
STATUS_INVALID_PARAMETER_2
Неверный параметр был передан функции в качестве второго аргумента.
RtlAnsiStringToUnicodeString ::
RtlUnicodeStringToAnsiString ::
C00000F7
STATUS_INVALID_PARAMETER_9
Неверный параметр был передан функции в качестве девятого аргумента.
InitializeLibrary ::
C0000103
STATUS_NOT_A_DIRECTORY
Запрошенный открытый файл не является каталогом.
BlFileGetNextFile ::
C0000106
STATUS_NAME_TOO_LONG
Указанное имя строки слишком длинное. Невозможно использовать в целевой функции.
BiEnumerateSubKeys ::
C0000120
STATUS_CANCELLED
Запрос ввода-вывода был отменен.
BmpLaunchBootEntry :: Возникает при расшифровке ошибок от функции DmDisplayDumpError, которая выводит на экран меню ошибок.
BmUpdateMulticastMessage :: Появляется как реакция на любую возвращенную функцией OsxmlResultHasAction ошибку.
BmDisplayFveRecovery :: Появляется при возникновении проблем с удаленной консолью.
C0000141
STATUS_INVALID_ADDRESS
Дескриптор адреса недействителен.
BlFileGetNextFile ::
C000014C
STATUS_REGISTRY_CORRUPT
Структура одного из файлов, содержащего данные реестра, повреждена; Образ файла в памяти поврежден; или файл не может быть восстановлен, поскольку резервная копия или журнал отсутствуют или повреждены.
::
C000014F
STATUS_UNRECOGNIZED_ VOLUME
Том не содержит распознаваемую файловую систему. Убедитесь, что все необходимые драйверы файловой системы были загружены и том не поврежден.
::
C0000184
STATUS_INVALID_DEVICE_ STATE
Устройство не находится в допустимом состоянии для выполнения запроса.
::
C0000185
STATUS_IO_DEVICE_ ERROR
Устройство ввода/вывода сообщает об ошибке ввода/вывода.
???????? :: Появляется при таймаутах (чрезвычайно низкой скорости) чтения с загрузочного носителя. Подобное поведение характерно в случае физической неисправности загрузочного носителя (различного рода повреждениях жесткого/твердотельного накопителя).
PcatSetVideoMode :: Генерируется при ошибке проверки поддерживаемых видеоадаптером текстовых режимов.
SppGetByte :: Появляется при ошибках работы с последовательным портом.
BlpTpmInitialize :: Выставляется при ошибке функции TpmApiSetTpmCallback, которая тестирует наличие обработчика драйвера TPM.
FveStatusFromHResult :: Выставляется при обработке внутренних статусов BitLocker.
C0000190
STATUS_TRUST_FAILURE
Ошибка входа в сеть. Узел проверки недоступен.
::
C0000221
STATUS_IMAGE_CHECKSUM_MISMATCH
Возможно образ файла поврежден. Контрольная сумма, указанная в заголовке, не совпадает с расчетной.
::
C0000225
STATUS_NOT_FOUND
Объект не найден.
Общие причины:

  • Неправильно выставленные параметры загрузки в BIOS: UEFI/Legacy-схемы загрузки.
  • Невозможно найти файл \Boot\BCD: неправильно подготовленный загрузочный USB-диск - выставлен некорректный BIOS DISK ID в MBR (не 80).

Частные причины:
BmMain :: Выставляется при ошибках в функциях: BmpInitializeBootStatusDataLog, BmpLogBootResolution, BlResourceFindHtml, которые выполняют инициализацию файла журнала и поиск ресурсов внутри секций модуля Bootmgr.

BmpGetCustomAction :: Возникает, если функция BlpGetOptionIntegerList не находит опций для выбранной записи загрузки.
BmpTransferExecution :: Выставляется при обработке результатов функции BlPdQueryData, которая проверяет корректность параметров.
BlHtLookup :: Возникает при обработке хэш-таблицы.
BlHtGetNext :: Выставляется при поиске в хэш-таблице.
BlpmFreeMemoryBlocks :: Генерируется при поиске по битовой карте памяти.
BcdGetElementDataWithFlags :: Возникает как реакция на ошибку в функции BiOpenKey, вероятно предназначающейся для работы с ключами реестра или файлов, построенных на схожей основе.
BcdDeleteElement :: Возникает как реакция на ошибку в функции BiOpenKey, вероятно предназначающейся для работы с ключами реестра или файлов, построенных на схожей основе.
FveDatasetGetDatumHeader :: Возникает при проверке на корректность входных параметров. В глобальном плане функция относится к функционалу BitLocker'а.
FveKeyringGetDataset :: Возникает при проверке на корректность входных параметров. В глобальном плане функция относится к функционалу BitLocker'а.
FveDatumValidateCode :: Возникает при ошибке функции FveDatumGetDataSegment. В глобальном плане функция относится к функционалу BitLocker'а.
C0000229
STATUS_FAIL_CHECK
Проверка не удалась.
::
C0000242
STATUS_BAD_COMPRESSION_ BUFFER
Указанный буфер содержит неправильно оформленные данные.
::
C000025F
STATUS_UNSUPPORTED_ COMPRESSION
Указанный формат сжатия не поддерживается.
::
C0000273
STATUS_NO_MORE_MATCHES
Больше нет совпадений для текущего индекса перечисления.
::
C0000354
STATUS_DEBUGGER_INACTIVE
Попытка произвести действие с отладочным портом не удалась, порт находится в процессе удаления.
::
C0000359
STATUS_INVALID_IMAGE_WIN_32
Указанный образа файла имеет неправильный формат; возможно это образ для 32-битной Windows.
::
C000035A
STATUS_INVALID_IMAGE_WIN_64
Указанный образа файла имеет неправильный формат; возможно это образ для 64-битной Windows.
::
C0000420
STATUS_ASSERTION_FAILURE
Произошла ошибка утверждения.
::
C0000428
STATUS_INVALID_IMAGE_HASH
Хэш для образа не найден в системных каталогах. Образ поврежден или подделан.
ImgpValidateImageHash :: Проверка хэша кода самого модуля Bootmgr. При модификации кода исполняемого файла именно здесь выставляется ошибка.
C0000453
STATUS_RESTART_ BOOT_ APPLICATION
Это приложение загрузки необходимо перезапустить.
::
C0000718
STATUS_ALREADY_REGISTERED
Функция обратного вызова уже зарегистрирована.
::
C0000904
STATUS_FILE_TOO_LARGE
Размер файла превышает допустимый и не может быть записан.
::
C0140019
STATUS_ACPI_INVALID_TABLE
Была сделана попытка использовать некорректную таблицу.
::
C01A000A
STATUS_LOG_BLOCK_INVALID
Служба логгирования обнаружила недопустимый блок.
::
C03A0002
STATUS_VHD_DRIVE_FOOTER_ CHECKSUM_ MISMATCH
Некорректная контрольная сумма футера (завершающего блока) виртуального образа.
::
C03A0003
STATUS_VHD_DRIVE_FOOTER_ CORRUPT
Поврежденный футер (завершающий блок) виртуального образа.
::
C03A0004
STATUS_VHD_FORMAT_UNKNOWN
Некорректный формат виртуального образа.
::
C03A0005
STATUS_VHD_FORMAT_ UNSUPPORTED_ VERSION
Неподдерживаемая версия формата виртуального образа.
::
C03A000B
STATUS_VHD_INVALID_BLOCK_ SIZE
Неправильный размер блока виртуального образа.
::
C03A000C
STATUS_VHD_BITMAP_MISMATCH
Несоответствие битовой карты виртуального диска.
::
C03A000E
STATUS_VHD_CHILD_PARENT_ID_ MISMATCH
Ошибка идентификатора ID виртуального образа.
::
C03A0012
STATUS_VHD_INVALID_SIZE
Некорректный размер виртуального образа.
::

Выводы

Изучение внутренней структуры ошибок Bootmgr достаточно трудоемкое и кропотливое занятие, требующее огромного количества времени, а самое главное, недюжих знаний, каковыми я пока что не обладаю. Следствием этого, как Вы могли уже заметить, является тот факт, что далеко не все ошибки Bootmgr освещены достаточно подробно. В отсутствии вменяемой логики анализа исходного кода приходится изучать ошибки Bootmgr по ассемблерному листингу в отладчике. Вероятно, кто-то из профессионалов реверсинга может посоветовать восстанавливать исходные тексты на языке C/C++ для упрощения восприятия, но и данными, казалось бы, необходимыми знаниями я пока не наделен. Поэтому, статья находится в статусе альфа как не до конца проработанная, тем не менее, надеюсь, что даже в таком сыром виде будет полезна кому-либо в качестве плацдарма для изучения специфических, возникающих на начальной стадии Bootmgr, ошибок. Какие выводы можно сделать по данному материалу? Я думаю, основной вывод, который напрашивается: невозможно точно характеризовать возникающую ошибку Bootmgr и определенно сказать об причине её возникновения даже по числовому идентификатору NTSTATUS, поскольку многие статусы имеют различные причины в различных функциях. Единственное что можно сделать, это попытаться по перебору возможных причин ошибки дойти до настоящего виновника сбоя, затем уже воспользовавшись для ошибки рекомендациями по устранению. Можно воспользоваться и общими алгоритмами, которые на каждом шагу можно встретить в Сети, однако не все из них действенны. Возможно, большинство ошибок, которые приведены в результирующей таблице, на практике никогда никому не встречались и скорее всего, в живой природе можно наблюдать значительно меньший диапазон ошибок, которые уже более-менее изучены и по которым написаны развернутые мануалы по устранению. Однако, судя по некоторым темам конференций, можно сказать, что раритетные ошибки всё же имеют место быть, поэтому в качестве отправной точки материал всё же пригодится.

Комментарии: 8

  1. Exotic Hadron

    STATUS_INSUFFICIENT_RESOURCES похоже может также означать, что вы пытаетесь загрузиться со сжатого диска VHD(X), размер которого превышает 100 Гбайт, см. STATUS_INSUFFICIENT_RESOURCES

    _https://blogs.msdn.microsoft.com/ntdebugging/2008/05/20/understanding-ntfs-compression/

    1. einaare

      Спасибо! Добавлено!

  2. Сергей

    Здравствуйте, тема невероятно интересная! В очередной раз столкнулся: Windows 10, уже после попытки вручную восстановить загрузчик (командой bcdboot C:\Windows) вышла ошибка: 0xc0000001. Никакого уточнения увы, не пишет (типа там winload.efi и т.д.). Никаких указаний на то, где искать причину. В связи с этим вопрос к вам - когда Windows не может загрузиться, где-то же в системе у себя он оставляет некий лог с указанием точной причины? Если да, не подскажете, где этот лог расположен? Переустановить Windows дело плёвое, но это дико скучно. Хочется хоть раз в жизни докопаться до точной причины, вызывавшей синий экран. Но, общая ошибка 0xc000001 - покрыта завесой тайны). Но, система же почему-то ее выдала! Значит на каком-то этапе загрузки она увидела, что где-то что-то не так, как надо) А если она это увидела - записала ли она об этом в какой-нибудь лог? В какой?)
    Если ответите, буду очень благодарен! Ваш сайт - ему равных пока не нашел нигде в инете! Статьи на глубоком уровне, ОЧЕНЬ ИНТЕРЕСНО читать! Не оставляете, пишите новые статьи! Спасибо!

    1. shofixti

      вот почитайте: http://datadump.ru/bootmgr-errors/

    2. shofixti

      тьфу, ссылкой ошибся.

    3. shofixti

      попробуйте из комплекта LIVECD (например: Sergei Strelec) использовать BCDEdit или EasyBCD.. если сможете - просто пересоздайте конфигурацию загрузки заново.

  3. Арик

    Как раз таки столкнулся с данной проблемой. Предысторию знаю только со слов жены.
    Смотрела ЮТаб, выскочил BSoD, собрал данные и пошёл на перезагрузку. Система грузилась крайне долго, дошло до экрана приветствия и тут вырубают свет.
    Дальнейшие попытки оживить комп результатов не имели. Не грузится ни с винта, ни с установочной флешки, выводит "blinitializelibrary failed 0xc0000017".
    Или может показывать приветственный логотип, "нажмите del для входа в UEFI", "F11 для вариантов загрузки" и так далее, затем, без показа логотипа винды, снова в перезагрузку.
    Грешу на память, либо на проблемы с матерью. Буду решать.

    1. shofixti

      кстати, было бы очень интересно увидеть результат. быть может тут и структура диска побилась?

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *