The power of the doc side 1: Taming GRUB 2

There is something special about updating software documentation. Sometimes, it’s just boring as hell, but at other times, it is a unique occasion to step down and think about what you’ve done and whether it was the right choice. And as I am working on a documentation page about Makefiles, it’s time for me to take a second look at three previous potentially harmful implementation decisions : sticking with GRUB Legacy as a bootloader for now, not trying hard enough to build a Makefile that auto-detects source files and their dependencies, and mixing kernel code with bootstrap code. Today, we’ll begin with bootloader matters.

GRUB 2: Most common OSS mistake, meets OS bootloader

From a theoretical point of view, GRUB 2, which has recently reached stable version 2.00, is a very nice project. It aims to provide a replacement to the original GRUB bootloader with a more modular structure, allowing it to support much more architectures (such as x86 UEFI) and have more features handy when the loaded OS needs them (think localization, ACPI setup, firmware-independent framebuffer activation…). If this works, you have potentially more fun on your hand (due to increased code sharing), less hacks, and as far as I can tell a very solid implementation. So, can you guess what is missing ? Well, you name it : quality documentation.

At the time where I’m writing this article, documentation for GRUB 2 is simply not up to par with that of its older cousin. In fact, I would even go as far as saying that as soon as you leaves the territory of “How do I fix the broken bootloader of my HDD-based Linux install”, both first-party and third-party documentations are quite a bit lacking. In particular, the official documentation failed to provide a centralized and satisfactory answer to the following questions :

  • How does GRUB 2 work, qualitatively-speaking ?
  • What do the grub2-install and grub2-mkrescue scripts do ?
  • How do I migrate existing GRUB legacy/multiboot1 configuration files to GRUB 2 ?
  • How do some important undocumented parts of multiboot1 change in GRUB 2 ?
  • What do all those ~200 GRUB 2 modules full of new functionality do ? How are they used ?
  • One may embed a config file within a GRUB 2 image. Will it work like an on-disk one ?

In the end, I have managed to find answers to most (but not all) of these questions, which were essential to successfully installing GRUB 2 on my ISO cd images and having it boot my OS. Some answers were scattered all over the web, and I had to find out about others by myself. So, let’s begin…

Unofficial GRUB 2 FAQ for OS developers

How does GRUB 2 work, qualitatively-speaking ?

To answer this question, it is probably best if I quickly recall what a bootloader is and what kind of problems it is designed to solved.

When a computer is turned on, its motherboard’s firmware, such as BIOS or UEFI on x86, performs some sanity checks and basic hardware initialization steps. Once these are finished, it proceeds to probe storage media in a well-defined order, using medium-specific tests, to look for a way to boot the computer from each of them. This takes the form a standardized binary image, localized on reserved region of the storage medium, which the firmware will proceed to load into RAM and execute once it finds it. After this point, GRUB 2’s part in the boot process begins.

GRUB 2 is a bootloader, a program which is designed to run after the firmware initialization stage but before an actual operating system. It is here to perform some additional hardware initialization steps, so as to put the computer in a state which OS kernels to be run will be more comfortable with. These typically include enabling widely used “new” features of old hardware architectures like x86, and abstracting away all the intricacies of firmware- and storage medium-specific booting procedures so that the OS does not have to care about those until it has reached an initialization stage where it is ready for that. As a bonus, and this is what many people mainly know it for, the GRUB family of bootloaders also allows OS users to selectively boot multiple operating systems in a firmware-independent fashion, by picking one from a menu that is displayed at boot.

Now we are ready to discuss how GRUB 2 works.

At the heart of GRUB 2 is a “core” binary image, in practice a sort of small OS that executes user-provided scripts and is able to load and execute operating system kernels in the aforementioned “comfortable” hardware configuration. To perform the required steps, this image is built upon a firmware-dependent core, selectively stuffed with ELF binary modules that contain the code required to probe storage media, locate scripts, load them, and execute them, along with some hardcoded configuration data. Such binary images are built by the grub-mkimage program (or grub2-mkimage on some variants of the grub2 package).

The core binary image does itself depend on some storage medium-specific initialization steps, which are performed by another, firmware *and* medium-dependent binary image which runs before the core one. This is, as an example, boot.img for floppy drives on BIOS-based x86 computers and cdboot.img for El Torito-compatible ISO 9660 CD-ROMs on the same platform. Due to some linker magic, it is sometimes sufficient to concatenate both images with the “cat” UNIX program in order to create a fully functional GRUB 2 image for the target storage medium+firmware combination. However, some older architectures put size constraints on firmware-bootable images and for those, a GRUB 2 install may have to be split in two binary images, one which is actually loaded and run by the firmware and another which is loaded and run by the first one.

What do the grub2-install and grub2-mkrescue scripts do ?

These scripts address two common use cases of GRUB 2, which are

  1. Prepare a GRUB install on a writable physical storage media that is connected to the host computer, for use with that computer
  2. Creating a basic “rescue” ISO image that can be burned to a CD or written to a USB disk, and features enough functionality to fix a broken GRUB 2 install

Neither can be directly used by an OS development project, because they do not address the use case of creating a disk image of arbitrary content and organization with GRUB 2 installed as a bootloader. However, since these are UNIX shell scripts which can be edited with a regular text editor, in the event where project documentation would be insufficient (as is the case here), their code can easily be explored so as to find some clues as for how installing GRUB 2 on a disk image works.

It should be noted that this approach is suboptimal because the content of a shell script is not subject to any guarantee of remaining valid forever, unlike a written documentation that also counts as a standard which the GRUB team can be held accountable for in the event of a compatibility breakage. However, since GRUB 2 has recently been declared stable, I believe that a reasonable level of risk can be taken, as long as we stick with general principles and avoid copying extremely specialized behaviour from the script.

How do I migrate existing GRUB 1/multiboot 1 configuration files to GRUB 2 ?

Quite a few things have changed in configuration file syntax from GRUB 1 to GRUB 2. The GRUB 2 documentation provides an (incomplete) reference of the new configuration file syntax, but here is a short list of the main differences as far as OS booting basics are concerned :

  • Some GRUB parameters (e.g. default OS to boot, timeout before it is booted) are now managed as environment variables instead of using commands. As an example, the ” timeout N ” command of GRUB Legacy becomes ” set timeout=N ” in the new syntax.
  • The default menu entry to boot is now specified using a string, which can include either a name or an entry number (by order of declaration in the config file, starting from 0). As an example, in a configuration where the first boot menu entry is called “The OS|periment”, commands ” set default=”0″ ” and ” set default=”The OS|periment” ” are both valid and equivalent. The goal is probably to make easier for programs to automatically manipulate GRUB configuration files
  • Since GRUB now has a modular structure, you must be careful to either include the module providing the commands you use in your core.img image or to dynamically load them with the ” insmod <module> ” command. The commands required for loading multiboot1-compliant kernels are provided by the “multiboot” GRUB 2 module. “kernel” is now called “multiboot”, and “module” is still called “module” but with a slightly different behaviour that I will discuss later.
  • Menu entries declarations now begin with the “menuentry” keyword and are now enclosed in C-style curly braces. To migrate a GRUB 1 configuration file, replace all occurences of ” title Xyz ” in it by ” menuentry “Xyz” { “, and add a closing curly brace ” } ” at the end of each declaration. Be careful : this is not as flexible as your favorite programming language, and you MUST put a newline between the last command associated to that menu entry and the closing curly brace.

For an overview, here is what the GRUB Legacy “menu.lst” configuration file of the OS|periment looked like :

default 0
timeout 0

title The OS-periment
kernel /System/boot/bs-kernel.bin
module /System/boot/kernel.bin

And here’s what the new “grub2.cfg” GRUB 2 configuration file looks like :

set default="The OS|periment"
set timeout=0

menuentry "The OS|periment" {
    insmod multiboot
    insmod elf
    multiboot /System/boot/bs-kernel.bin
# HACK : An undocumented change from GRUB 1 to GRUB 2 is that Multiboot
# modules are only labeled by their filename if it is explicitly requested
    module /System/boot/kernel.bin /System/boot/kernel.bin
}

I’ll discuss that “HACK” comment which may have attracted your eyes here in a bit.

How does the multiboot1 implementation change in GRUB 2 ?

The original Multiboot specification was designed along with GRUB, as part of the GNU/Hurd project. It is one of these things that make GRUB so much more than yet another Linux/Windows bootloader: using this specification, any OS kernel can theoretically be adapted to work with GRUB and any future version of it. There are two things, however, which should in my opinion have been featured in the Multiboot specification but haven’t. One is some ability to control where kernel modules are loaded by GRUB, and another, perhaps even more important one, is some standard ability to discriminate multiboot modules from each other when more than one is loaded.

One can understand why the Multiboot specification does not, as an explicit goal, let GRUB users specify where exactly kernel modules should be loaded. First, a running instance of GRUB does happen to be loaded in RAM, and it wouldn’t be a very wise idea to have it forcibly overwrite itself. Second, the functions used by GRUB to load kernel modules can be subjected to alignment constraints which will not allow it to load these modules anywhere it wants, and there is no way to know in advance what these constraints would be.

Still, having the bootloader load kernel modules at (seemingly) totally random RAM addresses is not necessarily a very sensible thing to do either, and having at least a way to blacklist some RAM regions away from GRUB’s reach would also be a nice addition. The reason being that in its early booting stages, OS kernels may have to use some hard-coded virtual memory addresses. And if you put something important at the same physical memory addresses, then said kernels will have to struggle with virtual memory intricacies early on instead of being able to rely on the assumption that most virtual memory addresses do map to the same physical memory addresses. Which is a Bad Thing.

Thankfully, GRUB 1 worked as one could reasonably expect and loaded kernel modules directly above itself, at relatively low RAM addresses. So the question was: does GRUB 2 still work in the same way? I am happy to announce that yes, it does.

Now, onto module identification matters… Here, the Multiboot specification provides a way to tag kernel modules with a string so as to ease their identification by the kernel, but it does not specify what the contents of said strings should be. And as it turns out, what happens when simply loading a kernel module with the “module” command differs from GRUB 1 to GRUB 2. In GRUB 1, kernel modules will be labeled by their file name, whereas in GRUB 2, the name used to refer to each individual kernel module must be explicitly specified in the associated GRUB configuration file.

Hence the HACK comment line above, and the repetition of the kernel module filename on the line below it. That’s the only way to keep kernels which were formerly running on top of GRUB 1 running on top of GRUB 2 without alterations. Of course, once the switch to GRUB 2 is completed, one can put this feature to more useful use and give kernel modules names which are independent of filesystem layout, if that is relevant to the OS project being worked on.

As an aside, GRUB 2 also provides a new revision of the Multiboot specification, aptly called multiboot2, which is a bit more flexible and introduces interesting improvements in the area of framebuffer-based graphics. Since I do not need a framebuffer yet and since embracing multiboot2 is much work, however, I will hold on moving to the new specification for now.

How do all those ~200 GRUB 2 modules work ?

Bad luck, I can’t fully answer this one. In a remarkably strange move, the GRUB 2 team has apparently decided to implement boatloads of functionality in modules without bothering to extensively document anywhere what that functionality is and in which modules it is stored. That being said, there are SOME things which I can tell you about GRUB 2 modules :

  • The scripts used to make GRUB 2 core images implement some form of module dependency tracking, so you only needed to wonder about which modules are required for the highest-level tasks that GRUB 2 will have to perform.
  • The “configfile” module is needed for GRUB to properly run and parse configuration files, so you probably want it in your core image.
  • You will need some module to let GRUB access storage media (“biosdisk” is generally enough for x86 computers with a BIOS firmware, except for pathological cases like RAID setups), and another one to let GRUB read information from the partition which it is stored on (ISO 9660, extN, FAT…). Thankfully, the latter ones have clear and predictable naming conventions.
  • A number of GRUB 2 modules only implement one command and bear the name of that command. For those, a web search can help.
  • And of course, even if it is very incomplete, you can still have a look at the GRUB 2 reference documentation and at Linux-oriented tutorials for enabling specific features of GRUB (mostly graphics-related).
How do I instruct GRUB 2 to use an arbitrary config file ?

GRUB Legacy used to always look for a configuration file at a specific location, /boot/grub/menu.lst, which could get quite a bit inconvenient for OSs which do not use the standard Unix filesystem layout. With GRUB 2, however, an alternative to this way of doing things has appeared : configuration files can now be directly embedded in the GRUB image and automatically executed once GRUB is loaded.

However, there is a twist : GRUB 2 does not parse these configuration files exactly like it would parse a “regular” one. I wouldn’t be able to tell what exactly the difference is, but if you take a working configuration file like the one above and embed it into a GRUB image, GRUB will fail to load the corresponding OS on boot, instead spitting a bunch of syntax errors and complaining about a lack of valid menu entries.

The best workaround which I have found so far is to embed a one-line configuration file inside my GRUB image, which specifies where the actual configuration file is located and instructs GRUB to parse it :

    configfile /System/boot/grub2/grub2.cfg

Making a bootable TOSP ISO image with GRUB 2

Introduction

Having gathered all the information above from personal experience, reverse-engineering of GRUB 2 scripts, and various corners of the Internet, I could finally reliably use GRUB 2 as the OS|periment’s bootloader. Here is a detailed overview of how it works, which may double as a tutorial for other hobby OS developers who might be struggling with GRUB 2 and settling with suboptimal solutions like generating their ISOs with grub2-mkrescue.

Getting a binary distribution of GRUB 2

First, please note that the GRUB team no longer distributes a binary version of GRUB 2 that is ready for use by OS developers, as was the case with GRUB 1. Therefore, you need to get a binary GRUB 2 package from your favorite Unix-ish repository, and find out where the main binary files (modules, etc…) have been copied. On my Fedora install, it is /usr/lib/grub2, whereas on Cygwin, it is /lib/grub.

Once you have found out, copy the “i386-pc” folder somewhere in the directory that is to become your ISO image, in the place where GRUB 2 is to be installed. For me, it was /System/boot/grub2. This is also the folder in which your GRUB 2 configuration file is to be copied. It is also theoretically possible to translate grub2 in multiple languages, in which case the translations would be put in a “locale” subfolder”, but I have not found quality documentation on how this should be done.

Making a GRUB 2 core image

Core GRUB images are generated using the grub2-mkimage script, also called grub-mkimage on some distributions. You should have installed it at the previous step. The syntax for a BIOS-compatible image is

grub2-mkimage -p <prefix> -c  -o <output file> -O i386-pc <list of modules>

where…

  • <prefix> is the location of the i386-pc folder mentioned above on the CD image. So in my case, this is : /System/boot/grub2/i386-pc
  • designates a configuration file that is to be embedded in the GRUB image and automatically run once the GRUB is loaded. See above for a little warning about such embedded configuration files.
  • <output file> is the name of the resulting GRUB 2 core image file. In my case, I call it “core.img”, following GRUB’s naming conventions.
  • <list of modules> is the list of modules that are to be directly linked in the GRUB 2 image. It is probably a good idea to only put the absolute minimum here (in my case, “biosdisk iso9660 configfile”) and dynamically load all other modules which you may need using the “insmod” command in your configuration file.
Turning a GRUB 2 core image into an “El Torito” bootable image

As has been discussed earlier, the core image file that has been generated previously is a fairly generic one, which lacks the specialized code required to deal with each individual type of bootable storage media. To make a bootable CD image out ot it, one simply has to locate the cdboot.img file, which is located in the i386-pc folder that we have copied earlier, then concatenate it with the core image, as an example using the cat Unix command…

cat <cdboot.img> <core image> > <final image>

where…

  • <cdboot.img> is the path to the cdboot.img file mentioned earlier
  • <core image> is the path to the core image file that we have generated at the previous step
  • <finale image> is the location where the final bootable image of GRUB 2 is to be stored. You should probably put it in the same directory as other GRUB 2 files, in my case System/boot/grub2 from the root of the CD image.
Making the final CD image

Once all these steps have been completed, we can use any mkisofs-compatible ISO CD image generation program to build a bootable image. Here, I am going to use genisoimage, a GPL-licensed fork of mkisofs that can be found on pretty much any Unix-ish repository, including Cygwin’s. The minimal command that should be used is…

genisoimage -o <cd image> -b <final bootable image> -r -no-emul-boot -boot-info-table --boot-load-size 4 <cd contents directory>

where…

  • <cd image> is the name of the iso file that is to be created
  • <final bootable image> is the location of the bootable image that have been generated earlier within the directory hierarchy of the CD itself. In my case, that would simply be “System/boot/grub2/grub2_eltorito.img”, without prefixing that with the location of the CD’s contents.
  • -r is used to enable the Rock Ridge extensions to the ISO 9660 standard, which allow for such things as longer file names and symlinks.
  • -no-emul-boot is used to disable the legacy way of booting from a CD-ROM drive, which basically involved the cumbersome emulation of a floppy disk drive.
  • -boot-info-table asks genisoimage to store some information that is required for GRUB to boot inside of the ISO image.
  • –boot-load-size 4 forces the BIOS to only load the first 4 sectors (8KB) of the GRUB image and let GRUB load the rest by itself. It normally shouldn’t be needed, except that many buggy BIOSes will fail to load GRUB properly without this.
  • <cd contents directory>, finally, is the folder in which you have stored all the files that are to comprise the folder hierarchy of the final CD image
And to conclude, here’s a LiveUSB trick…

Following the previous tips should give you a working bootable CD image of GRUB 2, that works on virtual machines as well as physical ones once burned to an optical storage medium. However, you may have also met one of these fancy Linux CD images that can also be written to USB pen drives and SD cards, and wondered how that works. Here’s the trick.

The ISO 9660 standard and its extensions all specify that the first 16 sectors (32KB) of a CD-ROM are reserved. Considering that the various optical media in existence today have reached maturity and are unlikely to see a successor, we can safely say that these reserved sectors will remain without a standard use forever. And, as it turns out, 32 KB is more than enough to store a standard 512 bytes long Master Boot Record, just like the ones which you would see on a regular disk drive or flash storage media…

You can probably guess how it works from that point : mkisofs-compatible image creation software have introduced the “-G” command-line option, which allows one to write something in those famous first 32KB of a CD-ROM. Using this feature together with a bit of sorcery to make a working image of GRUB 2 fit in 32KB, one can envision making an ISO image that can as well be copied on a USB drive, and look sufficiently like a MBR-formatted disk for a BIOS to boot it without asking much questions.

I wouldn’t know how well GRUB 2 does this job, though, since I haven’t tried it yet, and to the best of my knowledge no one has since ISO Linux images traditionally use ISOLINUX, a Linux-specific bootloader. As such, anyone who feels like trying, please feel free to report how well it works ! And on these words, let’s close this article which took me long enough to write, with the hope that you will have found it useful…

Advertisements

5 thoughts on “The power of the doc side 1: Taming GRUB 2

  1. Alfman October 25, 2012 / 10:58 pm

    The most common technical problem I’ve had with grub is it’s reliance on synchronised device maps between the bios and the kernel. When drives are added/removed and systems refuse to boot, this is usually the culprit. Unfortunately, depending on the particular system, this can happen very often say if the presence of thumb drives is changed between boots.

    Most bootloaders don’t have a device mapping problem because they can use the DX register to load the kernel from the same drive that the bios found the bootloader on. This technique has been used forever by bootloaders such as syslinux because it works equally well on hard disk, floppy, cdrom, thumb drives regardless of bios drive assignments.

    Often times grub is unable to find the kernel & initrd because of naive assumptions about having constant drive ordering from the last time grub-mkdevicemap was run. I’d given up at trying to use grub on portable media like thumbdrives or cdroms, because the drive map that works on one system will attempt to boot from a wrong drive on another system. I had been looking forward to grub2 for a long time to fix this shortcoming of grub1, but was disappointed that they fell into the exact same design flaw.

    Unless they’ve finally fixed this limitation, I’d recommend supporting grub, but not installing it by default on removable media. It’s not likely to be giving you crucial functionality over installing your kernel’s bootloader directly and using DX yourself to load the kernel from the correct drive.

    The linux kernel, for it’s part, ameliorated the situation by allowing the kernel parameters to specify partition UUIDs for the root and initrd partitions instead of device names. To my knowledge it’s not possible to explicitly use the DX “boot drive”, but at least the system is unlikely to find a conflicting UUIDs unless a drive was cloned.

  2. Hadrien October 26, 2012 / 8:28 am

    I have not encountered this problem so far since I have not gotten into mass storage code yet, relying on multiboot modules to have GRUB load the bits I need from the CDROM. But while checking out my Linux distro’s grub.cfg, I noticed that they combine putting an UUID on the kernel command line and explicitly asking GRUB to use BIOS partition ordering with commands like “set root='(hd0,msdos2)'”. Could this work ?

    I ask because writing a bootloader sounds like a fair amount of extra work (more so if I want it to peform some of GRUB’s nice tricks like enabling framebuffer functionality in a firmware-independent fashion), thus I’d be glad to continue reusing GRUB code in the predictable future if I am able to. Autogenerating grub.cfg files like most linux distros do today, although annoying, seemed like a fair price to pay for that to me.

  3. Alfman October 26, 2012 / 8:11 pm

    “Autogenerating grub.cfg files like most linux distros do today, although annoying, seemed like a fair price to pay for that to me.”

    Well actually that’s not a big deal to me. And since linux now-a-days uses UUIDs, the kernel completely ignores both the bios disk ordering, and also kernel device naming (/dev/sda /dev/sdb /dev/hda), which used to be a problem. So as long as grub can load the kernel, the kernel will find the partition with the UUID and everything will run regardless of how drives get loaded. But the problem is with grub itself finding the /boot directory of the correct drive. When you install grub to /dev/sdX, it will lookup the assumed bios partition number from the device map and this is the drive it will try to open the /boot directory on, regardless of which bios drive was actually booted. This can easily be the wrong drive.

    In my particular case, I have external SATA drive racks, and depending on the order in which they come on changes the drive ordering on the system. They might even probe BEFORE the internal drives where grub was installed. With syslinux this is never a problem because it simply doesn’t care about device ordering, but grub does care and it would complain that the kernel was not found, the user would have to manually specify the correct root=hdX for that boot, then linux would load fine. I could of course change the bootup procedure, like deferring power to the external disks until after boot, but I decided syslinux was a better solution without compromising on anything I really needed.

    “I ask because writing a bootloader sounds like a fair amount of extra work (more so if I want it to peform some of GRUB’s nice tricks like enabling framebuffer functionality in a firmware-independent fashion), thus I’d be glad to continue reusing GRUB code in the predictable future if I am able to.”

    I do think the bootloader work is pretty minimal, a few bios calls will easily load the kernel from disk. The complicated part is if the bootloader has to understand a filesystem to load the kernel (I meant to ask, what filesystem are you using with grub? Are you going to use a grub-supported fs in your OS?)

    I admittedly don’t know much about grub’s framebuffer, but wouldn’t grub be calling VBE/UEFI to do the initialization anyways? What does it save us? I think one strong argument against depending on grub for initialization is that in principal a microkernel should be able to update & initialize individual system modules on the fly. It could be awkward to have to reboot because the video driver cannot reinitialize the hardware without grub. Along the same lines, you’ll probably have to reinitialize the video hardware after waking up from a deep sleep state.

  4. Hadrien October 29, 2012 / 6:52 pm

    Well actually that’s not a big deal to me. And since linux now-a-days uses UUIDs, the kernel completely ignores both the bios disk ordering, and also kernel device naming (/dev/sda /dev/sdb /dev/hda), which used to be a problem. So as long as grub can load the kernel, the kernel will find the partition with the UUID and everything will run regardless of how drives get loaded. But the problem is with grub itself finding the /boot directory of the correct drive. When you install grub to /dev/sdX, it will lookup the assumed bios partition number from the device map and this is the drive it will try to open the /boot directory on, regardless of which bios drive was actually booted. This can easily be the wrong drive.

    In my particular case, I have external SATA drive racks, and depending on the order in which they come on changes the drive ordering on the system. They might even probe BEFORE the internal drives where grub was installed. With syslinux this is never a problem because it simply doesn’t care about device ordering, but grub does care and it would complain that the kernel was not found, the user would have to manually specify the correct root=hdX for that boot, then linux would load fine. I could of course change the bootup procedure, like deferring power to the external disks until after boot, but I decided syslinux was a better solution without compromising on anything I really needed.

    Indeed, that sounds problematic. I don’t know if syslinux would be a viable option for hobby kernels, though, since the project sounds highly Linux-specific (From the project website : “SYSLINUX is a boot loader for the Linux operating system”)

    “I ask because writing a bootloader sounds like a fair amount of extra work (more so if I want it to peform some of GRUB’s nice tricks like enabling framebuffer functionality in a firmware-independent fashion), thus I’d be glad to continue reusing GRUB code in the predictable future if I am able to.”

    I do think the bootloader work is pretty minimal, a few bios calls will easily load the kernel from disk. The complicated part is if the bootloader has to understand a filesystem to load the kernel (I meant to ask, what filesystem are you using with grub? Are you going to use a grub-supported fs in your OS?)

    Well, as I see it, bootloader code has to deal with even more intricacies of each specific architecture than OS kernels, including but not limited to BIOS bugs, multiple methods of RAM mapping, idiotic design decisions like 512 byte long boot sectors, firmware independence of kernel images, legacy design decisions like real mode on x86… That in addition to the problem of multiple disk partition formats that you mention.

    I currently use ISO CD/DVD images formatted with an ISO 9660 filesystem + Rock Ridge extensions, something which GRUB supports well. I aim at relative filesystem independence in the long run, even if discovering some really useful fs-specific feature that requires explicit OS and program support might change these plans. I strongly prefer those FS features that work automagically within the boundaries of the FS driver like journaling.

    I admittedly don’t know much about grub’s framebuffer, but wouldn’t grub be calling VBE/UEFI to do the initialization anyways? What does it save us? I think one strong argument against depending on grub for initialization is that in principal a microkernel should be able to update & initialize individual system modules on the fly. It could be awkward to have to reboot because the video driver cannot reinitialize the hardware without grub. Along the same lines, you’ll probably have to reinitialize the video hardware after waking up from a deep sleep state.

    I have not explored this part of GRUB 2’s feature set much yet, so I wouldn’t know if it performs well enough for my needs or if I’ll need to do it myself anyway (as an example, making good use of a framebuffer requires access to the screen’s EDID information so as to properly handle DPI-dependent stuff, and GRUB may or may not provide that). But I see how it could be useful, if it worked well enough.

    There is a number of hardware features that can prove useful during kernel initialization, and thus before any driver is running since those run on top of the kernel in the architecture I’m envisioning. Framebuffer-based video output would be one of these, because it can be used to output higher-quality status information than the one available through 80×25 VGA text output that is directly available on boot.

    Of course, if I can write VBE and GOP drivers, I can as well put some framebuffer initialization code in the kernel initialization (“bootstrap”) code. It would be better to leave that to a well-tested third-party implementation though, if available, in order to avoid duplicating code and increasing the complexity of the kernel initialization code (which operates in an extremely limited execution environment).

    As an aside, you raise an interesting point regarding video hardware initialization. VBE is something that is extremely hard to operate from 64-bit code (one needs either a real mode emulator or multiple costly CPU mode switches during which all CPU-bound code is stalled), so I need to somehow make sure that if a VBE-based video driver crashes, its successor is able to fallback to the information about VBE framebuffer location that has been provided at boot time. Which in turn means that the initial video driver must have only received a duplicate of the initial VBE information, and not a pointer to it.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s