问题
I want to boot a custom kernel (non-multiboot) with GRUB2, I've read that I need grub.cfg
like this:
menuentry "custom kernel" {
set root=(hd0,0)
chainloader +1
}
So, I have some questions:
- How grub detect kernel? (with multiboot spec I used
kernel /boot/kernel.bin
) - How my kernel must look like (sorry for my bad english)? Must it be 512 bytes at all (like custom bootloader, which loaded into 0x7c00)?
(hd0,0)
is hard drive partition and what I must put if I use CD? Maybe(cdrom0,0)
?- To boot Linux kernel we can use
linux
command, can I use it to boot my custom kernel (with some changes)? - Will Grub enter
Protected mode
or not?
回答1:
See the documentation:
Multiboot (see Multiboot Specification) is the native format supported by GRUB. For the sake of convenience, there is also support for Linux, FreeBSD, NetBSD and OpenBSD. If you want to boot other operating systems, you will have to chain-load them (see Chain-loading).
So for your non-multiboot kernel you'll have to use the chain-loader feature. Chain-loading means GRUB will load the first sector (512 bytes) of the specified harddisk partition and boots it like the BIOS would boot a MBR. This means the CPU is in real mode and your boot sector is loaded at 0x7C00.
And yes, you could boot your kernel using the linux
command, by making it compatible with the Linux boot process, but that would be more complex than simply making your kernel multiboot-compliant.
回答2:
When the computer starts up, it loads a sector(512 bytes) from the beginning of the hard disk to memory location 0x7C00, and executes it. This is in real mode. When you use GRUB, it installs its own code into this area (the MBR, or Master Boot Record). The reason chain loading exists is that other OSs have their own bootloaders. It allows GRUB to be used as the main bootloaders, but when it chainloads an entry, it loads 512 bytes from the partition that entry is on, and loads it in real mode, to 0x7C00, and pretends that the computer is loading up. This means instead of installing into the MBR, an OS can install into its VBR (Volume Boot Record), and have this loaded by GRUB if the user chooses that OS.
If you went down this route, you would have to write your own bootloader anyway, and there's no point using GRUB unless you want to load multiple OSs. It would be easier just to use multiboot, since GRUB goes into protected mode and enables the A20 line for you. I don't know about the Linux format, but it's bound to be a bit excessive for a simple kernel. If you take it far, then switching to the Linux format - or even writing your own bootloader for a custom format - might be useful.
回答3:
How my kernel must look like?
With chainloader
, GRUB makes it get treated exactly as a boot sector would. Minimal example:
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
Compile and run
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
Tested on Ubuntu 14.04 ADM64.
Expected outcome: a
gets printed to the screen.
This example on a GitHub repository: https://github.com/cirosantilli/x86-bare-metal-examples/tree/cba0757990843f412b14dffad45467ad0034d286/grub/chainloader
Will Grub enter Protected mode or not?
With chainloader
we are still in real mode since we used the BIOS.
With multiboot
(GRUB2 for kernel
) the kernel is left in protected mode, as mentioned at the Multiboot spec: https://www.gnu.org/software/grub/manual/multiboot/multiboot.html#Machine-state: "'CR0' Bit 0 (PE) must be set". Example.
How grub detect kernel?
It does not, you've told it exactly where to look with the +1
as I have with /boot/main.img
.
来源:https://stackoverflow.com/questions/17909429/booting-a-non-multiboot-kernel-with-grub2