Multiboot2 Bare Bones: Difference between revisions

Jump to navigation Jump to search
m
Replace deprecated <source> tag with <syntaxhighlight>
[unchecked revision][unchecked revision]
m (Remove EPLOS reference.)
m (Replace deprecated <source> tag with <syntaxhighlight>)
 
Line 169:
 
You can then assemble boot.s using:
<sourcesyntaxhighlight lang="bash">i686-elf-as boot.s -o boot.o</sourcesyntaxhighlight>
 
== Implementing the Kernel ==
Line 185:
<b>IMPORTANT NOTE</b>: the VGA text mode (as well as the BIOS) is deprecated on newer machines, and UEFI only supports pixel buffers. For forward compatibility you might want to start with that. Ask [[GRUB]] to set up a framebuffer using appropriate Multiboot flags or call [[Vesa|VESA VBE]] yourself. Unlike VGA text mode, a framebuffer has pixels, so you have to draw each glyph yourself. This means you'll need a different <code>terminal_putchar</code>, and you'll need a font (bitmap images for each character). All Linux distro ships [[PC Screen Font]]s that you can use, and the wiki article has a simple putchar() example. Otherwise everything else described here still stands (you have to keep track of the cursor position, implement line breaks and scrolling etc.)
 
<sourcesyntaxhighlight lang="c">
#include <stdbool.h>
#include <stddef.h>
Line 300:
terminal_writestring("Hello, kernel World!\n");
}
</syntaxhighlight>
</source>
 
Notice how in the code you wished to use the common C function <tt>strlen</tt>, but this function is part of the C standard library that you don't have available. Instead, you relied on the freestanding header <stddef.h> to provide <tt>size_t</tt> and you simply declared your own implementation of <tt>strlen</tt>. You will have to do this for every function you wish to use (as the freestanding headers only provide macros and data types).
 
Compile using:
<sourcesyntaxhighlight lang="bash">i686-elf-gcc -c kernel.c -o kernel.o -std=gnu99 -ffreestanding -O2 -Wall -Wextra</sourcesyntaxhighlight>
 
Note that the above code uses a few extensions and hence you build as the GNU version of C99.
Line 315:
You can compile the file kernel.c++ using:
 
<sourcesyntaxhighlight lang="bash">i686-elf-g++ -c kernel.c++ -o kernel.o -ffreestanding -O2 -Wall -Wextra -fno-exceptions -fno-rtti</sourcesyntaxhighlight>
 
Note that you must have also built a cross C++ compiler for this work.
Line 323:
You can now assemble boot.s and compile kernel.c. This produces two object files that each contain part of the kernel. To create the full and final kernel you will have to link these object files into the final kernel program, usable by the bootloader. When developing user-space programs, your toolchain ships with default scripts for linking such programs. However, these are unsuitable for kernel development and you need to provide your own customized linker script. Save the following in linker.ld:
 
<sourcesyntaxhighlight lang="c">
/* The bootloader will look at this image and start execution at the symbol
designated as the entry point. */
Line 367:
a segment with the same name. Simply add stuff here as needed. */
}
</syntaxhighlight>
</source>
 
With these components you can now actually build the final kernel. We use the compiler as the linker as it allows it greater control over the link process. Note that if your kernel is written in C++, you should use the C++ compiler instead.
Line 373:
You can then link your kernel using:
 
<sourcesyntaxhighlight lang="bash">i686-elf-gcc -T linker.ld -o myos.bin -ffreestanding -O2 -nostdlib boot.o kernel.o -lgcc</sourcesyntaxhighlight>
 
Note: Some tutorials suggest linking with i686-elf-ld rather than the compiler, however this prevents the compiler from performing various tasks during linking.
Line 383:
If you have [[GRUB]] installed, you can check whether a file has a valid [[Multiboot2]] version header, which is the case for your kernel. It's important that the Multiboot2 header is within the first 8 KiB of the actual program file at 4 byte alignment. This can potentially break later if you make a mistake in the boot assembly, the linker script, or anything else that might go wrong. If the header isn't valid, GRUB will give an error that it can't find a Multiboot2 header when you try to boot it. This code fragment will help you diagnose such cases:
 
<sourcesyntaxhighlight lang="bash">
grub-file --is-x86-multiboot2 myos.bin
</syntaxhighlight>
</source>
 
<tt>grub-file</tt> is quiet but will exit 0 (successfully) if it is a valid multiboot2 kernel and exit 1 (unsuccessfully) otherwise. You can type <tt>echo $?</tt> in your shell immediately afterwards to see the exit status. You can add this grub-file check to your build scripts as a sanity test to catch the problem at compile time. Multiboot version 1 can be checked with the <tt>--is-x86-multiboot1</tt> option instead. If you invoke the <tt>grub-file</tt> command manually in a shell, it is convenient to wrap it in a conditional to easily see the status. This command should work now:
 
<sourcesyntaxhighlight lang="bash">
if grub-file --is-x86-multiboot2 myos.bin; then
echo multiboot2 confirmed
Line 395:
echo the file is not multiboot2
fi
</syntaxhighlight>
</source>
 
== Booting the Kernel ==
Line 403:
You can easily create a bootable CD-ROM image containing the GRUB bootloader and your kernel using the program <tt>grub-mkrescue</tt>. You may need to install the GRUB utility programs and the program <tt>xorriso</tt> (version 0.5.6 or higher). First you should create a file called grub.cfg containing the contents:
 
<sourcesyntaxhighlight lang="c">
menuentry "myos" {
multiboot2 /boot/myos.bin
}
</syntaxhighlight>
</source>
 
Note that the braces must be placed as shown here. You can now create a bootable image of your operating system by typing these commands:
<sourcesyntaxhighlight lang="bash">
mkdir -p isodir/boot/grub
cp myos.bin isodir/boot/myos.bin
cp grub.cfg isodir/boot/grub/grub.cfg
grub-mkrescue -o myos.iso isodir
</syntaxhighlight>
</source>
 
Congratulations! You have now created a file called myos.iso that contains your Hello World operating system. If you don't have the program <tt>grub-mkrescue</tt> installed, now is a good time to install GRUB. It should already be installed on Linux systems. Windows users will likely want to use a Cygwin variant if no native grub-mkrescue program is available.
Line 428:
Install QEMU from your repositories, and then use the following command to start your new operating system.
 
<sourcesyntaxhighlight lang="bash">qemu-system-i386 -cdrom myos.iso</sourcesyntaxhighlight>
 
This should start a new virtual machine containing only your ISO as a cdrom. If all goes well, you will be met with a menu provided by the bootloader. Simply select myos and if all goes well, you should see the happy words "Hello, Kernel World!" followed by some mysterious character.
Line 438:
Or alternatively, you can burn it to an USB stick (erasing all data on it!). To do so, simply find out the name of the USB block device, in my case /dev/sdb but this may vary, and using the wrong block device (your harddisk, gasp!) may be disastrous. If you are using Linux and /dev/sdx is your block name, simply:
 
<sourcesyntaxhighlight lang="bash">sudo dd if=myos.iso of=/dev/sdx && sync</sourcesyntaxhighlight>
 
Your operating system will then be installed on your USB stick. If you configure your BIOS to boot from USB first, you can insert the USB stick and your computer should start your operating system.
Cookies help us deliver our services. By using our services, you agree to our use of cookies.

Navigation menu