Запускаем ReactOS с BTRFS раздела

Привет, Хабр!
Меня зовут Виктор, и в этом году я единственный студент в программе Google Summer of Code на проекте ReactOS. Сегодня я расскажу немного о том, что я делаю в рамках стажировки.

ReactOS поддерживает кучу всяких разных файловых систем для чтения и записи (fat32, ext2, ReiserFS, BTRFS), однако загружаться до сих пор умеет только с раздела, отформатированного в fat32. Этой весной я решил что пора начать исправлять эту ситуацию, и подал заявку на GSoC. И вот, спустя несколько месяцев я пишу этот пост :)

Почему BTRFS? Ответ прост — драйвер файловой системы WinBtrfs на текущий момент самый стабильный и полнофункциональный из всех, что включены в код РеактОС. На данном этапе, мы хотим пофиксить именно баги ядра, которые мешают использовать другие ФС для загрузки, так что баги драйвера ФС нам тут совсем ни к чему.

xh2xuv2jeovrhpxdbuiphffbbde.png
Но начать мне пришлось не с ядра ОС, а с установщика. Благо для установщика было уже почти всё готово: нужно было только включить загрузку драйвера WinBtrfs в нашем установщике (usetup), и добавить пару строчек кода, для поддержки форматирования в нужной файловой системе. После чего мне удалось (почти) без проблем скопировать файлы ReactOS на раздел, отформатированный в BTRFS.

С установщиком расправились быстро, а вот следующая задача гораздо интереснее. Загрузчик ReactOS — FreeLdr поддерживает практически только две файловые системы — fat32 и iso (есть код для ext2 и ntfs, но его уже лет 5 никто не пробовал запускать). Поскольку FreeLdr повторяет принцип работы загрузчика ntldr от MS, он состоит из двух частей — загрузочного сектора вначале раздела, куда передает управление MBR диска, и основной части, которая переводит процессор в защищенный режим, загружает ядро ntoskrnl.exe в память, и делает ещё кучу всего.

clgoi1um3vitkoe9crfvakqkzeq.png
(так выглядит процесс загрузки ReactOS)

Таким образом, для поддержки новой файловой системы, нужно написать загрузочную запись раздела (VBR), задача которой найти в корневой директории диска исполняемый файл основной части загрузчика (у нас он называется freeldr.sys), загрузить его в память и передать туда управление. Но это ещё не всё, в самом freeldr.sys нужен практически полноценный read-only драйвер файловой системы, для того чтобы считывать конфигурационные файлы, ядро, кусты реестра и т.д.

Вначале нужно было разобраться с самой файловой системой BTRFS. До этого самыми сложными вещами, что я ковырял были fat32 и ext2, так что на изучение «комбайна» BTRFS мне потребовалось немало времени. Документация на wiki.kernel.org помогает разобраться, но для полного понимания её было недостаточно — приходилось ходить в исходники grub, u-boot и других загрузчиков. Очень полезной для изучения строения файловой системы оказалась утилита на python, которую я написал для вывода структур файловой системы в консоль. С помощью нее я и написал первый прототип загрузочного сектора, который вытаскивает загрузчик из бинарного файла с образом диска с файловой системой BTRFS.
wmw9ommue1ojm4ys1wnbenakzvw.png
(на картинке видны элементы корневой директории)

Теперь пришло время настоящего загрузочного сектора. Осложняется его написание тем, что тут мы работаем в реальном режиме процессора со всеми вытекающими последствиями (~1 мб памяти, сегментная адресация и работа с диском через прерывания BIOS). Раздолье для любителей олдскула типа меня :)
В структурах BTRFS почти все поля имеют 64-битный размер, что весьма «раздуло» код, поскольку пришлось активно использовать 32-битные x86 инструкции. Частенько приходится использовать конструкции типа:

mov si, SOME_OFFSET
lea si, [esi+ecx*8] 
lea si, [esi+ecx*8]
lea si, [esi+ecx*8] // one element is 24 bytes long


Самой трудоёмкой оказалось написание процедуры обхода b-дерева, на её отладку ушло больше всего времени. И после нескольких бессонных ночей, мне таки удалось получить заветное сообщение об ошибке из второго этапа загрузки:
xwouzrpnw0_wbttpcghv8j7q6am.png
freeldr.sys получилось успешно загрузить в память, и даже не понадобилось использовать магию вроде Unreal Mode. 640 кб хватит всем!

Код загрузочного сектора можно посмотреть в моём репозитории на github (его ещё ожидает рефакторинг), а всю работу по BTRFS в этой ветке.

Теперь очередь за второй частью загрузчика — нужно научить его считывать файл конфигурации с новой файловой системы. Следите за новостями!

© Habrahabr.ru