Pour bien comprendre cette astuce, lisez d'abord comment établir les chemins d'inclusion, comment définir des variables conditionnelles et comment réécrire dynamiquement des chemins de fichier.

Liens d'inclusion habituels

Le chargeur de démarrage GRUB2 a été porté sur de nombreuses architectures informatiques pour offrir un moyen uniforme de choisir et démarrer un OS. Toutefois, il n'existe qu'un arbre source englobant toutes les "machines" et "modes" possibles.

L'arbre source a une organisation plus simple que celui du noyau Linux, car le seul objectif est de démarrer la machine sans s'occuper de fonctions évoluées comme le multi-threading, le lancement de processus ou la synchronisation.

Mais, l'essentiel de l'initialisation matérielle doit être faite en assembleur et ce code ne peut pas être commun aux diverses architectures. Ceci amène "naturellement" à séparer les fichiers liés au matériel dans des sous-répertoires de presque tous les répertoires principaux.

Le répertoire include/ contient à la fois les fichiers de définition universels et les fichiers spécifiques d'un matériel. Ces derniers sont rangés dans des sous-répertoires portant le nom de l'architecture.

Un fichier source typique commence par:

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

Comme on le voit, le répertoire include/ est implicite. Son emplacement est passé au compilateur par une option. Nous devons donc imiter cela pour permettre la construction d'hyperlien sous les directives #include. C'est possible par le recours à un paramètre 'incprefix' dans lxr.conf:

, 'incprefix' => [ '/include' ]
BUG! Certains fichiers sont incorrectement rédigés et grub/ manque dans l'argument de la directive #include. Pour obtenir quand même l'hyperlien, il suffit d'augmenter 'incprefix' avec: , 'incprefix' => [ '/include', '/include/grub' ]

Des fichiers de définition globale résident aussi à la racine de l'arbre, comme config.h. Le paramètre 'incprefix' complet devient:

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

Liens d'architecture

Les parties spécifiques d'un matériel sont rangées dans leur propre sous-répertoire (i386/, ia64/, powerpc/, x86_64/, …). Mais, ces parties ne sont pas directement incluses par le code indépendant de l'architecture. Au lieu de cela, la directive est écrite #include <grub/cpu/...> comme dans l'exemple suivant:

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

Le répertoire abstrait cpu/ est associé à un répertoire d'architecture réel par le système de gestion de configuration à travers la spécification d'une option au compilateur. Si nous sommes intéressés par l'architecture mips, nous ne pouvons pas modifier le 'incprefix' ci-dessus car il faut substituer dynamiquement mips à cpu.

Cette réécriture est accomplie par la fonction 'maps' avec substitution de variable.

D'abord, nous créons une variable dont la valeur sera l'architecture cible (ou plutôt, le nom du sous-répertoire pour l'architecture). Appelons-la 'a' pour architecture:

, 'variables' => { 'v' => { … } # Variable de version (obligatoire) , 'a' => { 'name' => 'Architecture' , 'range' => [ qw(i386 ia64 mips powerpc sparc64 x86_64) ] , 'default' => 'x86_64' } } Le contenu de 'range' est déterminé d'après les noms des sous-répertoires dans include/grub/. Il y en a un nombre limité, ce n'est donc pas insurmontable.

Quand LXR est lancé, cette variable est affichée dans l'en-tête de la page. Sélectionnez l'architecture cible et cliquez sur le bouton Change pour modifier la variable.

Ensuite, une règle de réécriture de chemin doit être appliquée juste avant le test d'existence du fichier avec la valeur de la variable en paramètre:

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

Liens d'environnement

GRUB2 peut être utilisé non seulement pour démarrer un matériel physique mais aussi une machine virtuelle ou un contexte multi-OS. Ceci introduit des variations subtiles dans le processus de démarrage. Ces variantes sont incluses avec des directives comme:

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

Les fichiers de définition associés se trouvent dans un sous-répertoire du répertoire matériel spécifique. Il est facile de gérer le nouveau chemin virtuel avec une autre règle 'maps'.

De nouveau, nous créons une variable dont la valeur sera l'environnement sélectionné (ou plutôt, le nom du sous-répertoire pour l'environnement). Appelons-la 'm' pour mode:

, 'variables' => { 'v' => { … } # Variable de version (obligatoire) , 'a' => { … } # Variable d'architecture , 'm' => { 'name' => 'Mode' , 'range' => [ qw(coreboot multiboot qemu pc) ] , 'default' => 'pc' } } Le contenu de 'range' est encore renseigné d'après les noms des sous-répertoires dans include/grub/architecture/.

La nouvelle règle de réécriture est aussi simple que la première:

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

Résumé

Après configuration standard, le fichier lxr.conf n'a besoin d'être augmenté qu'en trois endroits: