You are here

Bouw een eigen initrd-image!

Waarom? Gewoon, omdat het kan, omdat het leuk en leerzaam kan zijn. Bij een poging tot het bouwen van een eigen 'Live CD' begon ik mij af te vragen wat de absolute minimale benodigdheden zouden zijn voor een initrd-image.

Even voor de minder technische mensen: Het initrd-image is een initiële ramdisk (vandaar de naam: initial ramdisk) welke op Linux-systemen wordt gebruikt om modules als scsi-drivers alvast te laden voordat root wordt gemount. Zonder dit image zou Linux de root-partitie op een hedendaagse pc waarschijnlijk niet eens meer kunnen vinden omdat de drivers van de controller waaraan deze hangt nog niet zijn geladen.

Welnu, ik wilde graag een Live CD bakken, en daarvoor was ik druk bezig met het bouwen van een mooi initrd-image. Hiervoor gebruikte ik een bewerkte versie van mklivecd, maar omdat ik hier vanaf wil wilde ik graag weten wat er nodig zou zijn om zelf zo'n image te bakken. Gewoon met normale Linux commando's.

Goed. We hebben 2 opties voor het bouwen van een initrd-image. De eerste optie is het 'ouderwetse' initrd. Dit is een image file met een vaste maat, met daarop een ext2-filesystem. Sinds kernel 2.6.0 is het ook mogelijk een cpio-archief als initrd te gebruiken. Dit is vergelijkbaar met een tar of zip-bestand. Beide type bestanden kunnen met gzip worden gecomprimeerd.

Het 'ouderwetse' initrd-image

De optie van een image met ext2 filesystem heeft als nadeel dat het image een vaste maat heeft. Je zult dus van te voren willen weten hoeveel ruimte je nodig hebt. Dit kun je bekijken met het du-commando:

$ du -sk /pad/naar/jouw/tijdelijke/initrd/map

Het getal dat je van dit commando terug krijgt is het formaat van alles in de opgegeven map, in kilobytes.

Vervolgens maak je met dd een bestand aan van die maat + een beetje extra voor het filesystem, dus voor 4000k zou je een bestand van zo'n 4200k kunnen aanmaken:

$ dd if=/dev/zero of=mijninitrd.img bs=1024 count=4200

Vervolgens maak je hierop een ext2 filesystem aan:

$ mke2fs -F -m 0 mijninitrd.img

Nu kun je het image mounten:

# mount -o loop mijninitrd.img /mnt/initrd

Vervolgens is het een kwestie van alle bestanden uit de tijdelijke map naar het mountpoint waarop je jouw image hebt gemount te verplaatsen, en daarna het image weer te unmounten. Daarna is het image klaar voor gebruik. Eventueel kun je het image met gzip comprimeren.

Het cpio-archief

De tweede optie is het maken van een cpio archief. Voordeel hiervan is dat je geen rekening hoeft te houden met het formaat van de bestanden, en geen filesystem hoeft aan te maken. Gemakkelijker dus! Een cpio-archief kun je vergelijken bijvoorbeeld met een tar-of zip-archief.

Het cpio-archief dient van het type 'newc' te zijn. Met de volgende commando's bouw je een cpio-archief:

# cd /pad/naar/jouw/initrd/map
# find . | cpio -H newc -o > mijninitrd.img

Eventueel kun je de uitvoer ook direct door gzip pipen:

# find . | cpio -H newc -o | gzip -9 > mijninitrd.img

Het cpio-archief kun je eventueel als volgt weer uitpakken:

# mkdir test
# cd test
# zcat [cpio archief] | cpio --extract --make-directories --absolute-filenames -H newc

Absoluut minimum

Wat is nu het absolute minimum wat we aan bestanden nodig hebben in ons initrd-bestand?

Om te beginnen dient de device-node /dev/console aanwezig te zijn. Deze kun je aanmaken met mknod:

# mknod /mnt/initrd/dev/console c 5 1

Daarnaast moet een uitvoerbaar-bestand in de root van het image aanwezig zijn. In geval van het 'ouderwetse' initrd-image dient dit bestand de naam 'linuxrc' te krijgen, in geval van een cpio-archief moet dit 'init' zijn.
Als dit een script is, is uiteraard de interpreter waarvoor dit script is geschreven ook een vereiste. Ik gebruik bijvoorbeeld busybox ash. Daarvoor moet ik de busybox-binary op mijn image plaatsen.

Wat verder de inhoud van het linuxrc/init script is laat ik aan je eigen verbeelding over. ;)