To fully understand this tip, read first how to set include paths, how to define conditional variables and how to dynamically remap file paths.

Standard include links

The GRUB2 boot loader has been ported on many computer architectures to provide a uniform way to choose and boot OSes. However, there exists a single source tree encompassing both all possible "machines" and "modes".

The source tree has a simpler organisation than the Linux kernel one, since the only goal is to boot the machine without caring for high-level functions such as multi-threading, process dispatching or synchronisation.

But, most early initialisation must be done in assembler and this code cannot be shared between different hardwares. This leads "naturally" to segregate hardware dependent files into subdirectories in virtually every principal directory.

The include/ directory contains both the universal definition files and the hardware-dependent files. The latter are stored in sub-directories named after the target architecture..

A typical source file begins like:

#include <grub/loader.h> #include <grub/command.h> #include <grub/multiboot.h>

As can be seen, the include/ directory is implicit. Its location is passed to the compiler through an option. We need then to mimic this to enable hyperlink construction under the #include directives. This is possible with an 'incprefix' parameter in lxr.conf:

, 'incprefix' => [ '/include' ]
BUG! Some files are incorrectly coded and grub/ is missing in the #include directive argument. To get the hyperlink anyway, the 'incprefix' is simply augmented as: , 'incprefix' => [ '/include', '/include/grub' ]

Global definition files also reside at the root of the source-tree, like config.h. The complete 'incprefix' parameter becomes:

, 'incprefix' => [ '/include', '/', '/include/grub' ]

Architecture links

Hardware-specific parts are stored in their own sub-directories (i386/, ia64/, powerpc/, x86_64/, …). But these parts are not directly #included by the architecture-independent code. Instead, the directive is written #include <grub/cpu/...> as in the following example:

#include <grub/cpu/multiboot.h> #include <grub/cpu/relocator.h>

The abstract cpu/ directory is mapped to a real hardware directory by the configuration management system through an option specification given to the compiler. If we are interested in the mips hardware, we cannot modify the above 'incprefix' because it involves substituting mips for cpu.

This rewriting is a job for the 'maps' feature with variable substitution.

First, we create a variable whose value will be the target architecture (in fact, the name of the architecture sub-directory). Let us call it 'a' for architecture:

, 'variables' => { 'v' => { … } # Version variable (mandatory) , 'a' => { 'name' => 'Architecture' , 'range' => [ qw(i386 ia64 mips powerpc sparc64 x86_64) ] , 'default' => 'x86_64' } } The 'range' content is filled from the names of the sub-directories in include/grub/. There is a limited number of them, so this is not a difficult task.

When LXR is launched, this variable appears in the header area. Just select the target architecture and click the Change button to set the variable.

Next, a path rewrite rule must be applied just before the test for file existence with the variable value as parameter:

, 'maps' => [ '^/include/grub/cpu/' => '/include/grub/$a/' ]

Environment links

GRUB2 can be used not only to boot on physical hardware but also on virtual machines or in multiple OS context. This introduces subtle variations in the boot process. These variants are included with directives like:

#include <grub/machine/memory.h> #include <grub/machine/kernel.h>

The corresponding definition files are found in a sub-directory of the hardware-dependent directory. It is easy to deal with the virtual path through another 'maps' rule.

Once again, we create a variable whose value will be the target environment (in fact, the name of the environment sub-directory). Let us call it 'm' for mode:

, 'variables' => { 'v' => { … } # Version variable (mandatory) , 'a' => { … } # Architecture variable , 'm' => { 'name' => 'Mode' , 'range' => [ qw(coreboot multiboot qemu pc) ] , 'default' => 'pc' } } The 'range' content is again filled from the names of the sub-directories in include/grub/architecture/.

The new rewrite rule is as simple as the first one:

, 'maps' => [ … , '^/include/grub/machine/' => '/include/grub/$a/$m/' ]

Summary

After standard configuration, file lxr.conf needs to be augmented in three locations.