Загрузка ядра без мультизагрузки с помощью GRUB2

Я хочу загрузить собственное ядро ​​(без мультизагрузки) с помощью GRUB2, я читал, что мне нужно grub.cfg вот так:

menuentry "custom kernel" {
    set root=(hd0,0)
    chainloader +1
}

Итак, у меня есть несколько вопросов:

  1. Как grub обнаруживает ядро? (со спецификацией мультизагрузки я использовал kernel /boot/kernel.bin)
  2. Как должно выглядеть мое ядро ​​(извините за мой плохой английский)? Должен ли он вообще быть 512 байт (как кастомный загрузчик, который загружается в 0x7c00)?
  3. (hd0,0) - это раздел жесткого диска, и что я должен указать, если использую компакт-диск? Может (cdrom0,0)?
  4. Для загрузки ядра Linux мы можем использовать команду linux, могу ли я использовать ее для загрузки собственного ядра (с некоторыми изменениями)?
  5. Войдет ли Grub в Protected mode или нет?

person Vanzef    schedule 28.07.2013    source источник


Ответы (3)


См. документацию:

Мультизагрузка (см. Спецификацию мультизагрузки) — это собственный формат, поддерживаемый GRUB. Для удобства также есть поддержка Linux, FreeBSD, NetBSD и OpenBSD. Если вы хотите загрузить другие операционные системы, вам придется загружать их по цепочке (см. Загрузка по цепочке).

Поэтому для вашего ядра без мультизагрузки вам придется использовать функцию цепного загрузчика. Цепная загрузка означает, что GRUB загрузит первый сектор (512 байт) указанного раздела жесткого диска и загрузит его так же, как BIOS загружает MBR. Это означает, что ЦП находится в реальном режиме, а ваш загрузочный сектор загружен по адресу 0x7C00.

И да, вы можете загрузить свое ядро ​​с помощью команды linux, сделав его совместимым с процессом загрузки Linux, но это будет сложнее, чем просто сделать ваше ядро ​​совместимым с мультизагрузкой.

person Martijn van den Broek    schedule 29.07.2013

Как должно выглядеть мое ядро?

С chainloader GRUB обрабатывает его точно так же, как загрузочный сектор. Минимальный пример:

iso/boot/grub/grub.cfg

menuentry "hello-world" {
    chainloader /boot/main.img
}

main.S

.code16
.global _start
_start:
    cli
    /* Sane programs should also do some extra
     * initialization here like stack and segments.
     */
    mov $0x0E61, %ax
    /* BIOS call that prints 'a' to screen. */
    int $0x10
    hlt

Скомпилируйте и запустите

as -o main.o main.S
/* Sane programs should use a dedicated linker script. */
ld --oformat binary -o main.img -Ttext 0x7C00 main.o
cp main.img iso/boot/
grub-mkrescue -o main.iso iso
qemu-system-i386 -hda main.iso

Протестировано на Ubuntu 14.04 ADM64.

Ожидаемый результат: a выводится на экран.

Этот пример в репозитории GitHub: https://github.com/cirosantilli/x86-bare-metal-examples/tree/cba0757990843f412b14dffad45467ad0034d286/grub/chainloader

Войдет ли Grub в защищенный режим или нет?

С chainloader мы все еще в реальном режиме, так как мы использовали BIOS.

С multiboot (GRUB2 для kernel) ядро ​​остается в защищенном режиме, как указано в спецификации мультизагрузки: https://www.gnu.org/software/grub/manual/multiboot/multiboot.html#Machine-state: "CR0" Бит 0 (PE) должен быть установлен". Пример.

Как grub обнаруживает ядро?

Это не так, вы точно сказали, где искать с +1, как я с /boot/main.img.

person Ciro Santilli 新疆再教育营六四事件ۍ    schedule 03.10.2015
comment
Ваш ответ замалчивает тот факт, что причина, по которой вы все еще находитесь в реальном режиме, заключается в том, что когда вы специально используете chainloader, он должен работать так же, как BIOS загрузил загрузочный сектор и перешел напрямую. Если бы ОП использовал kernel (и записал загрузчик хита в спецификацию мультизагрузки), то по умолчанию он был бы в защищенном режиме. Кстати, если вы загружаетесь на 386, то, скорее всего, вы действительно находитесь в нереальном режиме по умолчанию (а не в реальном режиме). - person Michael Petch; 04.10.2015
comment
@MichaelPetch спасибо за отзыв. Я также попытался добавить эту информацию. - person Ciro Santilli 新疆再教育营六四事件ۍ 04.10.2015

Когда компьютер запускается, он загружает сектор (512 байт) с начала жесткого диска в ячейку памяти 0x7C00 и выполняет его. Это в реальном режиме. Когда вы используете GRUB, он устанавливает свой собственный код в эту область (MBR или Master Boot Record). Причина, по которой существует цепная загрузка, заключается в том, что другие ОС имеют свои собственные загрузчики. Это позволяет использовать GRUB в качестве основного загрузчика, но когда он загружает запись по цепочке, он загружает 512 байт из раздела, в котором находится эта запись, и загружает его в реальном режиме в 0x7C00 и делает вид, что компьютер загружается. Это означает, что вместо установки в MBR ОС может устанавливаться в свою VBR (объемную загрузочную запись) и загружать ее с помощью GRUB, если пользователь выбирает эту ОС.

Если вы пойдете по этому пути, вам все равно придется писать свой собственный загрузчик, и нет смысла использовать GRUB, если вы не хотите загружать несколько ОС. Было бы проще просто использовать мультизагрузку, так как GRUB переходит в защищенный режим и включает для вас линию A20. Я не знаю о формате Linux, но он должен быть немного избыточным для простого ядра. Если вы зайдете далеко, то переход на формат Linux или даже написание собственного загрузчика для пользовательского формата может оказаться полезным.

person jfla    schedule 30.07.2013