GRUB: Difference between revisions

5,661 bytes added ,  7 days ago
m
Fix minor error
[unchecked revision][unchecked revision]
No edit summary
m (Fix minor error)
 
(45 intermediate revisions by 22 users not shown)
Line 1:
{{In ProgressTutorialTone}}
'''GRUB''' is the GNU project's bootloader. The current version 2 series have a more complete feature set than [[GRUB Legacy|GRUB 0.97]] (commonly referred to as "GRUB Legacy").
 
'''GRUB 2''' is the GNU Project's next-generation bootloader. It has a more complete feature set than [[GRUB]] 0.97 (commonly referred to as "GRUB Legacy"). Still, all things considered, [[GRUB]] Legacy is more mature and most of the available documentation is for [[GRUB]] Legacy (hence the brief page).
 
 
== History ==
GRUB version 2 started its life as the [http://www.nongnu.org/pupa/ PUPA] (note the pun) research project and was rewritten from the ground up. Since then GRUB 2 (actually at time of update 1.97) has grown more stable and even hobby operating systems use of the new bootloader instead of GRUB Legacy.
 
GRUB 2 started its life as the [http://www.nongnu.org/pupa/ PUPA] (note the pun) research project and was rewritten from the ground up. Since then GRUB 2 (actually at time of update 1.97) has grown more stable and even hobby operating systems are starting to make use of the new bootloader instead of GRUB Legacy.
 
 
== Features ==
 
* Basic scripting support
* GUI (better bootsplash support, custom colors, custom themes, ...)
Line 18 ⟶ 11:
* Internationalization
* Rescue mode
A complete list of features can be found on the GNU mailing lists [https://lists.gnu.org/archive/html/grub-devel/2012-06/msg00093.html]
 
== Using GRUB to boot your OS==
 
Complete example code for booting your operating system with GRUB can be found in the [[Bare_Bones#Booting_the_Operating_System|Bare Bones tutorial]]. The general idea is that you want to create a file that has [[Multiboot#Header_Format|Multiboot header]] which GRUB can use to identity your program as a kernel and boot it.
== Upgrading from GRUB Legacy ==
''WARNING: These steps have not been tested very well yet. Use at your own risk!''
 
Since modern GRUB 2 is very different from GRUB Legacy, the directions for getting your kernel up and running are different. Modern GRUB 2 differs from GRUB Legacy in that to implement all but the most basic functionality, the user must load so-called "modules": little bits of code that add components (e.g. a different file system or a VGA font). This section gives you an overview of the process you need to go through when you want to have GRUB 2 load your kernel. It's actually rather simple to create a GRUB2GRUB 2 image (assuming you have GRUB2GRUB 2 either built or installed):
 
=== ISO instructions ===
There have been a lot of tries to make Grub2 work good with ISOs, but mostly failed. The only combination of commands that seems to work is the following.
Line 32 ⟶ 25:
Now run:
grub-mkrescue -o bootable.iso iso
 
Be sure that your grub.cfg is syntactically correct. A common mistake is to put the menuentry brace on newline. It '''must''' be like:
menuentry "Place your os name here" {
}
 
grub-mkrescue depends on program '''xorriso''' with version '''0.5.6 or higher'''.
 
Line 43 ⟶ 34:
GNU xorriso can be used where it gets built, without further installation:
grub-mkrescue --xorriso=/...full.path.../xorriso/xorriso -o bootable.iso iso
 
=== Floppy instructions ===
<sourcesyntaxhighlight lang="bash">
mkdir tmp
grub-mkimage -p /boot -o tmp/core.img multiboot sh fat # This should work... I hope :D
</syntaxhighlight>
</source>
==== Explanation ====
 
=== Explanation ===
Let's go through those <tt>grub-mkimage</tt> options:
 
{| {{wikitable}}
|-
Line 69 ⟶ 57:
| '''iso9660/fat'''
| Allows GRUB 2 to look on the image for different files.
|-
|'''sh'''
| This module allows GRUB to parse the configuration file.
|}
 
GRUB 2, like GRUB Legacy, needs a configuration file to find your kernel. In GRUB Legacy it's called '''menu.lst''', but in GRUB2, it's called '''grub.cfg'''. The syntax for the configuration file is also a bit different.
 
Here's a sample configuration file (NOTE: This file should be placed into the <tt>/boot/grub</tt> folder of your disk image, and be named '''grub.cfg'''):
<syntaxhighlight lang="bash">
 
<source lang="bash">
set timeout=15
set default=0 # Set the default menu entry
 
menuentry "OS Name" {
multiboot /boot/kernel-file # The multiboot command replaces the kernel command
# For multiboot v2, use the multiboot2 command
multiboot /boot/kernel-file
boot
}
</syntaxhighlight>
</source>
 
That's basically it. Copy these files to a disk image, pop it in an emulator, and you're done!
 
Double check that you put the brace on the same line of "menuentry". It can't be on a new line. This is not C.
 
=== USB instructions ===
Fewer and fewer systems have a floppy disc controller these days, but USB ports are found on all. Modern BIOSes can boot from a USB device, usually by pressing some special key during startup.
Line 99 ⟶ 85:
1. Create a FAT32-formatted USB disk, without partitions:
 
'''Warning: the follingfollowing command uses superuser privileges (sudo). E.g. just typing the wrong character for X could cause severe troubles for your current system'''
<pre>sudo mkfs.vfat -F 32 -n YourLabel -I /dev/sdX</pre> (where sdX is your USB device)
 
The "-I" option is needed because we are targeting a partition-less device
 
Line 108 ⟶ 93:
3. Invoke grub-install (on some systems this command is called grub2-install, located under /usr/sbin or /usr/local/sbin)
<pre>sudo grub-install --root-directory=/media/YourLabel --no-floppy --recheck --force /dev/sdX</pre>
 
It is important to do this as root (or sudo), else the generated device.map listing available boot devices can be empty.
/media/YourLabel is the mount point under Fedora 16, it may be different for other distributions.
 
4. Create a grub.cfg for your kernel (see above), and copy it to your new bootable USB disk
=== Disk image instructions ===
For a more detailed tutorial, see [[Bootable_Disk|bootable disk]] creation.
 
=== Disk image instructions ===
Hobby operating systems don't have to use real devices when running on virtual machines (although it may be, and it usually is faster). Creating bootable GRUB disk image is similar to installing it on USB devices, but here you're working with image itself and partition device at once.
 
Line 123 ⟶ 108:
67108864 bytes (67 MB) copied, 0.349436 s, 192 MB/s
</pre>
 
2. Create new DOS partition table with bootable entry for your filesystem
<pre>$ fdisk disk.img</pre>
Line 151 ⟶ 135:
Syncing disks.
</pre>
 
3. Setup two loop devices. One will be used for writing GRUB and its additional codes to MBR, and the second will be used for mounting filesystem of your operating system.
<pre>
Line 163 ⟶ 146:
<pre>$ sudo mke2fs /dev/loop1</pre>
<pre>$ sudo mkdosfs -F32 -f 2 /dev/loop1</pre>
 
5. Mount your newly formatted partition
<pre>$ sudo mount /dev/loop1 /mnt</pre>
Line 169 ⟶ 151:
 
7. Install GRUB using ''grub-install''
<pre>sudo grub-install --root-directory=/mnt --no-floppy --modules="normal part_msdos ext2 multiboot biosdev" /dev/loop0</pre>
If you mistyped ''/dev/loop1'' (pointing on your partition) instead of ''/dev/loop0'' (pointing on your MBR), you would receive message that ''grub-install'' can't use 'embedding' (because there's no space for it) and that it would like to use 'block lists', which are not recomended.
 
Don't forget to flush the filesystem buffers when manipulating with files on mounted disk image. On a Unix-like system, this can be simply done by executing the <tt>sync</tt> program in your shell.
 
== HDD Image Instructions for OS X users==
It might be useful to create an image file for a HDD; The following instructions help you create a HDD with an MBR partition map.
Based on information from <palk> on #osdev, it is slightly more complicated to create a HDD image than you'd expect.
 
This information might not be applicable to Linux users, who will most probably want to use a loopback device. This is for developers on OSXOS X, which doesn't
have a loopback device and has a finicky image mounter.
 
 
1. First, create a blank, raw image with DD, with the required size. Here, I'll make a 80MB image -- 163840 sectors of 512 bytes.
<sourcesyntaxhighlight lang="bash">
dd if=/dev/zero of=disk.img count=163840 bs=512
</syntaxhighlight>
</source>
2. For an explaination on calculating the CHS values from the LBA / size see [[Floppy_Disk_Controller#CHS]]
 
Since we have a 80MB disk, the CHS values are 78, 32 and 63 respectively.
2. Next, calculate the CHS values for the disk and have them at hand. TODO: Explain this.
3. Fire up FDISK (or your tool of choice) -- I'm using the OS X version here, so commands may differ. The concept is essentially identical.
Here, it's a 80MB disk, so the CHS values are 78, 32 and 63 respectively.
 
3. Fire up FDISK (or your tool of choice) -- I'm using the OSX version here, so commands may differ. The concept is essentially identical.
 
What will show on your screen (in OSXOS X anyway) is on the left, what you enter is on the right.
<sourcesyntaxhighlight lang="bash">
fdisk -e disk.img
 
Line 214 ⟶ 192:
fdisk:*1> write
fdisk:*1> quit
</syntaxhighlight>
</source>
 
 
4. Now that the MBR Partition Table is initialised, you'll want to make a Filesystem on the disk. But first.
Here, we separate the MBR bit, and the actual FS bit.
<sourcesyntaxhighlight lang="bash">
dd if=disk.img of=mbr.img bs=512 count=2047
dd if=disk.img of=fs.img bs=512 skip=2047
</syntaxhighlight>
</source>
5. Because we're on OS X, we need to attach the disk image first, without actually mounting it.
 
<syntaxhighlight lang="bash">
5. Because we're on OS X, we need to mount the disk image first, without actually mounting it.
<source lang="bash">
hdiutil attach -nomount fs.img
</syntaxhighlight>
</source>
 
6. Use 'diskutil list' to find out which device your image is, use that below.
 
7. Now, make a FAT12/16/32 filesystem on the FS.img disk. Remember, use FS.img -- not disk.img
<sourcesyntaxhighlight lang="bash">
newfs_msdos -F 32 /dev/diskX
</syntaxhighlight>
</source>
 
8. Now you'll want to unmount it, then recombine the two images, then install GRUB.
<sourcesyntaxhighlight lang="bash">
hdiutil detach /dev/diskX
cat mbr.img fs.img > disk.img
Line 246 ⟶ 219:
grub-install --modules="part_msdos biosdisk fat multiboot configfile" --root-directory="/Volumes/NO NAME" disk.img
Installation finished. No error reported.
</syntaxhighlight>
</source>
And there it is! You know have a disk.img, that will have GRUB 2 installed, ready to go. It should be mountable in OS X simply by double clicking (or with the mount command).
 
And there it is! You know have a disk.img, that will have GRUB2 installed, ready to go. It should be mountable in OSX simply by double clicking (or with the mount command).
Enjoy!
=== Additional useful options ===
Whatever device you are using, you may want to have a PC partition table and create a partition you format in one of the filesystems supported by GRUB. If you do, be sure to add the following option the grub-install arguments:
--modules="part_msdos"
In general, if GRUB 2 happens to fail to do what you want and you suspect that it needs some missing functionality, just try to add a module name you believe has the functionality you need to the --modules argument. The module files generally are in /boot/grub/i386-pc/.
== Multiboot ==
Some versions of GRUB 2 like to put Multiboot modules in relatively high physical memory addresses, in contrast to GRUB-legacy which loaded them into low memory. Be careful when making your kernel work with GRUB 2 that it is not making any assumptions about where the Multiboot modules will appear.
 
When your kernel gets control, the machine state is defined as follows: [http://www.gnu.org/software/grub/manual/multiboot/html_node/Machine-state.html Multiboot machine state]. Your code should have minimal dependency on this initial state; for example, define your own GDT instead of relying on the GDT setup by GRUB.
=== Header ===
As the GRUB 2 manual puts it:
{{quote|The primary requirement for GRUB is that it be compliant with the ''Multiboot Specification''.}}
But the Multiboot header as used by older versions of GRUB 2 (field is present in GRUB 1.99 and newer) did ''not'' include the ''header_length'' field that is specified in the [http://nongnu.askapache.com/grub/phcoder/multiboot.pdf Multiboot 1.6 specification].
 
GRUB 2 also supports the old [https://www.gnu.org/software/grub/manual/multiboot/multiboot.html Multiboot 0.6.96 specification]. It is possible to include both headers.
== Installing GRUB 2 on OS X ==
The installation of GRUB 2 on OS X is a little tricky. The latest released version 2.00 (as of 7th of October, 2014) doesn't seem to work with any configuration. The developer team fixed this in the newer revisions.
 
'''Important:''' To build GRUB 2 so that it can produce a bootloader for your output target you need to have a compiler for that target. So for example, if you want a bootloader for i386-elf (as suggested in the bare bones) you'll need Binutils + a compiler for that target. This is required on OS X because the built-in LLVM doesn't know how to make i386-elf binaries. So you can either [http://wiki.osdev.org/GCC_Cross-Compiler build a cross-compiler] or [http://wiki.osdev.org/OS_Specific_Toolchain create an OS-specific toolchain] (recommended) for your target platform.
'''You will need the cross-versions of GCC, objcopy, strip, nm and ranlib in step 4.'''
 
'''1.''' Clone the developer version of the sources:
=== Additional useful options ===
<syntaxhighlight lang="bash">git clone git://git.savannah.gnu.org/grub.git</syntaxhighlight>
Whatever device you are using, you may want to have a PC partition table and create a partition you format in one of the filesystems supported by GRUB. If you do, be sure to add the following option the grub-install arguments:
(This was tested on revision: 77063f4cb672f423272db7e21ca448cf3de98dcf)
--modules="part_msdos"
 
'''2.''' A tool named '''objconv''' is required, get it from:
In general, if GRUB2 happens to fail to do what you want and you suspect that it needs some missing functionality, just try to add a module name you believe has the functionality you need to the --modules argument. The module files generally are in /boot/grub/i386-pc/.
https://github.com/vertis/objconv
Download sources, compile (see website for details) and make available in your PATH.
 
'''3.''' Run "autogen.sh" in the GRUB sources folder
== Multiboot ==
 
'''4.''' Create a seperate build directory, switch to it, and run GRUB's configure script ''(insert your target-specific tools!)'':
Some versions of GRUB 2 like to put multiboot modules in relatively high physical memory addresses, in contrast to GRUB-legacy which loaded them into low memory. Be careful when making your kernel work with GRUB 2 that it is not making any assumptions about where the multiboot modules will appear.
../grub/configure --disable-werror TARGET_CC=i386-elf-gcc TARGET_OBJCOPY=i386-elf-objcopy \
TARGET_STRIP=i386-elf-strip TARGET_NM=i386-elf-nm TARGET_RANLIB=i386-elf-ranlib --target=i386-elf
'''5.''' Run "make" and "make install"
 
Now you have a working GRUB 2 that has the required files to build an image that boots on i386 platforms.
When your kernel gets control, the machine state is defined as follows: [http://www.gnu.org/software/grub/manual/multiboot/html_node/Machine-state.html Multiboot machine state]. Your code should have minimal dependency on this initial state; for example, define your own GDT instead of relying on the GDT setup by GRUB.
==GRUB for UEFI==
===Compiling GRUB===
Older GRUB versions are riddled with nasty bugs. As this probably includes the version from your package management, you should be compiling GRUB from source. As we're compiling for UEFI, you should pass the appropriate flags to configure. An example invocation might look something like this:
<syntaxhighlight lang="text">
../grub-2.02~rc2/configure --prefix="$HOME/opt/grub" --target=x86_64 --with-platform=efi
</syntaxhighlight>
After completing the build, GRUB refused to do anything as it was missing a font file. To fix this, run
<syntaxhighlight lang="text">
bin/grub-mkfont -o share/grub/unicode.pf2 /usr/share/fonts/truetype/unifont/unifont.ttf
</syntaxhighlight>
GRUB might warn you about share/locale/ missing. To solution is to create the missing directory.
===Building a GRUB UEFI binary (BOOTX64.EFI)===
This method builds a standalone GRUB binary you can copy to a FAT partition. However, note that some UEFI implementations assume that it is located at <code>/EFI/BOOT/BOOTX64.EFI</code> for x86_64 platforms.
 
Generally, all compiled modules are included in this binary; if you want to cut down on its size, you can specify what modules to include.
=== Header ===
As the GRUB 2 manual puts it:
 
This method uses two separate configuration files; this is needed as all GRUB data is located within the binary, but we'll be working around that. The binary contains a memdisk, which also serves as the prefix. As far as I'm aware, there's no way of working around this fact directly. We can, however, use the memdisk grub.cfg to load a configuration file from the disk. This way, we don't have to recreate the binary for every configuration change.
{{quote|The primary requirement for GRUB is that it be compliant with the ''Multiboot Specification''.}}
 
Start off with creating the memdisk grub.cfg. I saved it at build/grub.cfg (we'll need this path later on):
But the Multiboot header as used by most versions of GRUB 2 (including GRUB 1.98-2) does ''not'' include the ''header_length'' field that is specified in the [http://nongnu.askapache.com/grub/phcoder/multiboot.pdf Multiboot 1.6 specification].
<syntaxhighlight lang="text">
insmod part_msdos
configfile (hd0,msdos1)/boot/grub/grub.cfg
</syntaxhighlight>
All this does is loading the module for reading the disk partitions (line 1) and loading the configuration file from the disk (line 2). Note that it doesn't have to be located at /boot/grub/grub.cfg; you can change this path on the disk to whatever you like, just remember to apply the changes to the memdisk grub.cfg.
 
The second grub.cfg (the one on the disk) is pretty much up to you, except that you have to load the part_msdos module and set the root (which by default is memdisk):
GRUB 2 also supports the old [https://www.gnu.org/software/grub/manual/multiboot/multiboot.html Multiboot 0.6.96 specification]. It is possible to include both headers.
<syntaxhighlight lang="text">
insmod part_msdos
set root=(hd0,msdos1)
</syntaxhighlight>
Add your regular GRUB2 configuration below the <code>set root</code> line.
 
Finally, all that's left is to create the binary. Note that you have to specify what file to include at what path in the memdisk:
<syntaxhighlight lang="text">
bin/grub-mkstandalone -O x86_64-efi -o BOOTX64.EFI "boot/grub/grub.cfg=build/grub.cfg"
</syntaxhighlight>
===Blessing the binary on macOS===
Macs require bootable binaries to be 'blessed' by a utility:
<syntaxhighlight lang="text">
bless --verbose --folder=/Volumes/EFI --file=/Volumes/EFI/EFI/BOOT/BOOTX64.EFI --setBoot
</syntaxhighlight>
== See Also ==
 
=== Articles ===
* [[GRUB Legacy]]
 
* [[GRUB|GRUB Legacy]]
* [[Bootable El-Torito CD with GRUB Legacy]]
* [[Multiboot]]
* [[BOOTBOOT]] an alternative boot loader with exactly the opposite philosophy as GRUB's
 
* [[Limine]] another boot loader supporting Multiboot
=== External Links ===
 
* [http://www.gnu.org/software/grub/ GRUB 2 Homepage]
* [http://grub.enbug.org/ GRUB 2 Wiki]
 
[[Category:Bootloaders]]
[[Category:GRUB]]
[[Category:UEFI]]
[[de:Grand_Unified_Bootloader]]