Info16.fr

Le blog de B@rtounet

#Gnu/Linux, Planet Libre

Boot d'un kernel bzImage sur les anciennes versions de Xen < 3.4

30 janvier 2012 Rédigé par bartounet

nasmaison Boot d'un DomU, sur un Kernel bzimage sur Xen inférieur à 3.4

Juste un petit arcticle, qui me sert d'aide mémoire.

Je suis tombé sur un problème:
J'ai voulut booter un DomU à base de Ubuntu 10.04LTS sur un système de virtualisation Xen 3.1
En l'ocurence il s'agissait d'une Distri SLES10SP4 + Xen 3.1

Je pensais que cela ne poserai aucun problème, j'utilise mon template DomU Ubuntu10.04LTS depuis un petit moment déjà sur des Xen plus récent.

En voulant booter ce fameux domU j'ai eut droit à l'erreur suivante:

Error: (2, 'Invalid kernel', 'xc_dom_find_loader

J'ai cherché un bon moment, c'est comme si le Kernel n'était pas reconnu.
Et en fait je suis tombé sur cette page: https://www.globalways.net/blog/archives/76-Extracting-bzImage-from-vmlinuz.html

Il explique que Les anciennes versions de Xen ne supporte pas les nouveaux formats d'image du noyau. Wikipedia affirme que "Aucun outil spécifique existe pour décompresser le fichier bzImage».

En effet sous Ubuntu depuis la 9.10, le kernel n'est plus un simple fichier gzipé mais un bzImage.

root@ubuntults:/boot# file vmlinuz-2.6.32-37-server
vmlinuz-2.6.32-37-server: Linux kernel x86 boot executable bzImage, version 2.6.32-37-server (buildd@allspi, RO-rootFS, root_dev 0x6801, swap_dev 0x3, Normal VGA


On voit bien que le Kernel est un bzImage.

On sait que ce fameux bzimage commence par une entête spécifique. et que après il y a l'entête de gzip qui est:

ID1 0x1f
ID2 0x8b
CM 0x08 (Compression Method deflate=)
FLG 0x00 (no extra fields)


Le but: supprimer tout ce qui se trouve avant cette entête afin d'avoir un kernel basique.

Pour cela, 2 méthodes:


Celle décrite dans la page web, grace à binoffset::

L'auteur à développer une commande qui permet de trouver ce fameux offset et d'en donner son emplacement en octet

    La commande est présente ici:
    http://svn.opentom.org/opentom/trunk/linux-2.6/scripts/binoffset.c

    Après l'avoir compilé.

    gcc -o binoffset binoffset.c
    On peut utiliser la commande dd:

    root@ubuntults:/boot# dd if=vmlinuz-2.6.32-37-server bs=1 skip=$(/root/binoffset vmlinuz-2.6.32-37-server 0x1f 0x8b 0x08 0x0) of=vmlinuz-2.6.32-37-server-UNPACK.gz

    filesize: 4110432

    number of pattern matches = 1

    14441

    4095991+0 records in

    4095991+0 records out

    4095991 bytes (4.1 MB) copied, 15.2127 s, 269 kB/s


    On lit le kernel en bs de 1octet on skeep 14441 octets ( qui correspondent au debut du fichier jusqu'a ce fameux offset ) autrement dit on aura supprimer tout l'entete du bzimage et on aura un kernel gzip classique.


    root@ubuntults:/boot# file vmlinuz-2.6.32-37-server-UNPACK.gz

    vmlinuz-2.6.32-37-server-UNPACK.gz: gzip compressed data, from Unix,
    last modified: Fri Dec  2 22:02:53 2011, max compression

    root@ubuntults:/boot# gunzip vmlinuz-2.6.32-37-server-UNPACK.gz



    gzip: vmlinuz-2.6.32-37-server-UNPACK.gz: decompression OK, trailing
    garbage ignored

    root@ubuntults:/boot# file vmlinuz-2.6.32-37-server-UNPACK

    vmlinuz-2.6.32-37-server-UNPACK: ELF 64-bit LSB executable, x86-64,
    version 1 (SYSV), statically linked, stripped

    Une fois dézippé on voit bien qu'on a kernel classique.
    D'ailleurs ce kernel est reconnu aussi bien gzipé ou pas.



    Méthode en bash (moins sure):
    Ce qui m'embête dans la première méthode, c'est qu'il faut avoir sous la main le fameux binoffset.c et le compiler...
    J'aurais aimé faire cela avec des commandes système basiques sans rien avoir à installer...

    Après maintes commande j'ai fait ce que je voulais avec la commande suivante...

    root@ubuntults:/boot# a=$(cat vmlinuz-2.6.32-37-server | xxd -g1 | grep "1f 8b 08 00" | awk -F":" '{print $1}' | sed 's/^[0\t]*//'); b=$(cat vmlinuz-2.6.32-37-server | xxd -g1 | grep "1f 8b 08 00" | awk -F":" '{print $2}' | awk -F"1f 8b 08 00" '{print $1}'| awk '{x=x+NF}END{print x}'); c=$(( $a + $b )); echo Hexa=$c ; echo Decimal=$((0x$c))

    Hexa=3869

    Decimal=14441

A coup de grep et d'awk et de sed, j'arrive à trouver le nombre d'octet à effacer sur le fichier.

le même dd:

dd if=vmlinuz-2.6.32-37-server bs=1 skip=14441 of=vmlinuz-2.6.32-37-server-UNPACK2.gz

Je n'ai as testé en profondeur, cette commande ne fonctionne pas forcément partout à mon avis.

Information sur bartounet auteur de l'article

Les commentaires sont fermés.