Загрузка ядра в память - как написать сам загрузчик? - PullRequest
3 голосов
/ 20 июня 2011

Я работаю над созданием собственного загрузчика и ядра для D и наткнулся на камень преткновения.

Справочная информация:

  • Я пишу все с нуля. Итак, загрузочный сектор находится в сборке. И я не использую GRUB.
  • Я использую Qemu для тестирования.
  • Загрузочный сектор считывает ядро ​​с «диска» (который в настоящее время представляет собой простой двоичный файл, первый сектор которого является загрузчиком, а остальная часть - код ядра) в виртуальный адрес 0xC0000000 и вызывает kmain(), точка входа в мое ядро.
  • Я использую формат файла PE для своего ядра. (Пожалуйста, не говорите мне использовать Elf - мой выбор - PE.)

Проблема

Это часть работы ядра, чтобы иметь возможность загружать PE файлы. Итак, как мне загрузить само ядро ​​в память, чтобы оно действительно могло работать правильно?

Я не могу сделать это из загрузочного сектора, потому что (1) он не умещается в 512 байт, и (2) это болезненно делать в сборке. Очевидно, я не могу сделать это и в самом ядре. Так как мне это сделать?

1 Ответ

8 голосов
/ 20 июня 2011

Как GRUB это делает?

В GRUB загрузочный сектор 512 байт не загружает ядро. Вместо этого он загружает остальную часть загрузчика, который намного больше, чем 512 байт. Именно этот загрузчик второго уровня загружает ядро. Вам придется сделать что-то подобное.

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

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

Ядро Linux делало что-то подобное в прошлом. Вы можете скопировать сырое ядро ​​прямо на дискету. Первые 512 байт были загрузочным сектором дискеты, который загружал следующие несколько секторов (все еще в реальном режиме) по фиксированному адресу в нехватке памяти. Эти следующие несколько секторов имели код (все еще в сборке) для загрузки остальной части ядра в фиксированный адрес памяти и перехода к его реальной точке входа. В настоящее время IIRC большая часть этого кода была удалена, и ядро ​​Linux теперь зависит от внешних загрузчиков.

...