1. LINUX VAN CD NAAR RAMDISK
Inhoud
- Theorie
- Inleiding
- Booten vanaf CD
- Het bootproces
- De kernel
- Root-bestandssysteem opzetten
- Het root-bestandssysteem
- De binary's
- Scripts en configratiebestanden
- fstab
- inittab
- rcS
- Opstartdiskette maken
- Het root-bestandssyteem comprimeren
- Lilo en zo
- Alles op de flop
- CD invullen
- Iso-bestand maken en CD branden
- Bronnen
1. Theorie
1.1 Inleiding
Een Linux bootdisk, oftewel: Linux op een diskette, kan in een aantal gevallen erg handig
zijn, bijv. bij het testen van een nieuwe kernel, of om je Linux installatie te repareren na
een crash, of om op een Windows-computer Linux te laten draaien, zonder aan de harde schijf te
komen.
Er zijn verschillende manieren om aan zo'n bootdisk te komen:
- Gebruik de bootdisk van je bestaande installatie
- Pluk een resue-pakket van internet en maak daarmee je bootdisk
- Leer hoe zo'n disk werkt en maak hem zelf
Van deze laatste manier kun je veel over Linux leren.
We gaan in dit artikel echter nog een stapje verder: we gaan een bootable CD met Linux
maken, waarbij na het opstarten Linux helemaal in het geheugen, op een zgn ramdisk, komt te
staan.
Let wel: dit is niet bedoeld voor Linux-newbies. Je hoeft echter ook geen guru te zijn om
tot een goed eindresultaat te komen...
1.2 Booten vanaf CD
Om te kunnen opstarten vanaf een CD moet aan een paar voorwaarden voldaan worden:
- Je computer moet ervoor geschikt zijn. De meeste, redelijk moderne bios'en kunnen dit
tegenwoordig wel aan. Kijk evt. in de bios-setup en verander zo nodig de opstart-volgorde.
- De CD moet geschikt zijn om van op te starten. Hij moet voldoen aan de zgn. El
Torito-standaard.
Deze El Torito-standaard werkt, doordat het bios de CD-drive even ziet als een floppy-drive.
Op de CD moet een image van een opstart-diskette (van precies 1440kB) staan. En in de headers
van de CD wordt verwezen naar deze image. Het bios leest de diskette-image van de CD en
behandelt deze als een normale flop (/dev/fd0).
We hebben dus, om een bootable CD te maken, eerst een opstart-diskette nodig.
Een extra eis hierbij is, dat het opstarten van die diskette gebeurt m.b.v. een
bootloader, zoals Lilo. Er mag dus niet rechtstreeks met de kernel opgestart
worden.
Het is belangrijk om alle bestanden voor de opstartdiskette, incl. de kernel, zo klein
mogelijk te houden: het moet tenslotte allemaal binnen die 1440kb passen. Na de eerste
opstartfase kunnen de overige bestanden dan, eventueel via een script, van de CD naar de
ramdisk gekopieerd worden.
1.3 Het boot-proces
Voordat we aan het werk gaan is enige achtergrond-kennis over het boot-proces
nodig.
Elke PC start op met het uitvoeren van een programma in het bios. Dit programma leest de
eerste sector van de opstartschijf (meestal harde schijf, diskette of CD, afhankelijk van de
bios-instellingen). Het bios probeert de code van die eerste sector uit te voeren. En die code
zal, als het goed is, de kernel lezen en laden.
Als de kernel geladen is, zal die de nodige device-drivers en data-strukturen
initialiseren. Daarna wordt het root-bestandssysteem gemount. Dit is simpelweg
een bestandssysteem, dat als "/" gemount wordt. De kernel moet echter wel weten,
waar dat bestandssysteem te vinden is. In ons geval zorgt Lilo voor die
wetenschap (via lilo.conf).
Ons root-bestandssysteem zal in ramdisk geladen worden. Ramdisk is een stukje
geheugen, dat door het systeem als een schijf behandeld wordt. De kernel is in
staat een gecomprimeerd root-bestandssysteem van de diskette (of CD) te lezen en
dit uit te pakken in de ramdisk. Zo passen er veel meer bestanden op een
diskette.
Na het mounten van "/" zal de kernel het init-programma uitvoeren. Init
leest z'n configuratie uit het bestand /etc/inittab, zoekt o.a. naar een regel die
begint met "sysinit" en voert het script, dat in die regel vermeld wordt, uit.
Sysinit verwijst vaak naar /etc/rc of /etc/init.d/boot o.i.d..
Dit script bevat een serie shell-opdrachten o.a. om een aantal services op te starten (bijv.
een fsck), de nodige kernel-modules te laden en verschillende bestandssystemen (benoemd in
/etc/fstab) te mounten. Bij het bouwen van ons systeem zullen we het
sysinit-script echter heel eenvoudig houden.
Als het sysinit-script klaar is, krijgt init weer de controle, die naar
het juiste runlevel door zal starten. Dit runlevel wordt in /etc/inittab
gespecificeerd met "initdefault". De op te starten services en programma's voor dit
runlevel worden in verschillende scripts aangegeven.
2. De kernel
Onze opstartdiskette zal dus een kernel moeten bevatten en een root-bestandssysteem. We
gaan hier niet in op het zelf configureren en compileren van een kernel. Het is echter wel
belangrijk, dat een aantal zaken in de kernel meegecompileerd wordt (dus niet als module):
- Natuurlijk de ondersteuning van de hardware, die nodig is bij het opstarten, zoals de
CD-speler (IDE of SCSI) en de floppy-drive.
- Ook ondersteuning voor ramdisk en ext2 moet meegecompileerd worden.
Laat verder alles weg, wat niet nodig is. Het is belangrijk, dat de kernel klein blijft.
Hij moet tenslotte, samen het het root-bestandssysteem, op een enkele diskette passen. Zaken,
die niet direct nodig zijn bij het opstart-proces kun je als module compileren, om ze na de
eerste opstartfase alsnog te laden vanaf de CD.
Comprimeer de kernel met een "make bzImage".
3. Het root-bestandssysteem opzetten
3.1 Het root-bestandssysteem
Het root-bestandssysteem kan in eerste instantie opgebouwd worden in een
directory binnen een bestaand linux-systeem, bv. de directory ~/rfs.
Maak daar eerst een aantal (sub-) directory's aan: dev, etc, etc/init.d, proc, bin,
sbin, usr, usr/bin, usr/sbin, tmp en mnt.
In de dev-directory moet een aantal devices aangemaakt worden. Dat kan met de
Linux-opdracht "mknod", maar eenvoudiger is het ze gewoon te kopieren uit het
bestaande Linux-systeem. Maak alleen die devices aan, die je echt nodig hebt (ook devices
kosten ruimte, of in ieder geval inodes). In ieder geval heb je nodig: fd0, hdc (als
dat je CD-speler is), tty0-3, console, kmem, mem, null en ram0. Bij het
kopieren van de devices met de opdracht "cp" moet je de optie "-R"
(hoofdletter R!) gebruiken, bijv. "cp -R /dev/fd0 ~/rfs/dev/".
3.2 De binary's
Omdat het bestandssyteem klein moet blijven, maken we gebruik van BusyBox.
BusyBox is een programma, dat veel Linux-utilities vervangt, als is het wel vaak met wat
minder opties.
Als je een link maakt naar BusyBox met de naam van de functie, die je wilt hebben, dan
zal BusyBox, als hij via die link aangeroepen wordt, zich gedragen als die functie.
Bijvoorbeeld: maak een link met de naam "ls":
ln -s ./busybox ls
Type daarna "./ls" en je krijgt de uitvoer, die je van de opdracht "ls"
mag verwachten.
De homepage van BusyBox is te vinden op www.busybox.net;
daar kun je het ook, als broncode, downloaden.
Het compileren is erg eenvoudig, al moet er voor ons doel nog wel wat veranderd worden in
het bestand "Makefile". Daar staat achter de variabele DOSTATIC
"false" vermeld. Verander dit in "true" om een statisch gelinkte BusyBox
te krijgen. Dan hebben we verder geen library's in ons root-bestandssysteem nodig. Mocht je
die toch nodig hebben voor andere programma's, dan is het beter ze later, via een
opstart-script van de CD naar de ramdisk te kopieren.
Na het veranderen van de DOSTATIC-variabele is het nog een kwestie van
make
make install
en het hele BusyBox-systeem, incl. de subdirectory's en de links is te vinden in de
directory "_install". Kopieer ze vandaar naar de betreffende directory's in je
root-bestandssysteem en je hebt al de Linux basis-programma's bij de hand!
4. De configuratie-scripts
4.1 fstab
Deze staan allemaal in de etc-directory. Er is niet veel nodig: alleen fstab,
inittab en etc/init.d/rcS. Het init-onderdeel van BusyBox kent nl.
geen verschillende runlevels. Het start altijd op in de single-user-mode. Mede daardoor kan
alles erg eenvoudig gehouden worden.
In fstab komt minimaal het volgende te staan:
/dev/ram0 / ext2 defaults
/proc /proc proc defaults
Wellicht is het handig om ook nog een regeltje voor de CD-speler toe te voegen (we gaan
ervan uit dat /dev/hdc de cd-speler is):
/dev/hdc /mnt iso9660 noauto
Omdat we de CD-speler niet automatisch mounten, moet dat later eventueel in de scripts
nog gebeuren.
Zet de mode van fstab juist: chmod 644 fstab.
4.2 inittab
Het volgende script is inittab. Dit ziet er als volgt uit:
::sysinit:/etc/init.d/rcS
::askfirst:/bin/sh
tty2::askfirst:/bin/sh
tty3::askfirst:/bin/sh
::restart:/sbin/init
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
Ook hier weer de juiste mode zetten: chmod 644 inittab.
4.3 rcS
Als laatste is er nog het rcS script (etc/ini.d/rcS). Dit moet minimaal het
volgende bevatten:
#!/bin/sh
mount -a #mount alle default bestandssystemen, vermeld in fstab
Omdat het rcS script in het root-bestandssysteem hoort, dat straks gecomprimeerd
wordt en samen met de kernel "versmolten" tot een diskette-image, is het lastig om er
naderhand nog iets aan te wijzigen. Daarom laten we rcS de CD mounten en vandaar
een script kopieren naar ramdisk, wat dan uitgevoerd wordt. Dit script (laten we het
"sec" noemen, als vervolg op "init") is wat eenvoudiger te veranderen.
Aan rcS voegen we het volgende toe:
mount /mnt # meer hoeft niet, dankzij de vermelding in fstab
cp /mnt/sec /usr/bin # sec kopieren van CD naar ramdisk
sec # script "sec" uitvoeren
umount /mnt # CD unmounten
Het script "sec" kun je verder alles laten uitvoeren, wat je wilt: modules laden,
bestanden van CD naar ramdisk kopieren, enz. Vergeet dan niet de CD eerst weer te mounten...
Zorg dat rcS uitvoerbaar is: chmod 755 rcS.
En dat waren alle nodige configuratie-scripts!
5. Opstartdiskette maken
5.1 Het root-bestandssysteem comprimeren
Nu gaan we het hele root-bestandssysteem in een bestand zetten, dat we "rootfs"
gaan noemen. De grootte van rootfs bepaalt straks de groote van de ramdisk. Minimaal
heb je zo'n 4Mb nodig, maar op een moderne computer, met minimaal 128Mb geheugen mag de
ramdisk best 32Mb zijn.
Daarom maken we eerst een leeg bestand van 32Mb. Hoewel: het is niet leeg, maar gevuld
met nullen. Dat zorgt ervoor, dat de ongebruikte ruimte straks goed gecomprimeerd
kan worden.
dd if=/dev/zero of=rootfs bs=1k count=32768
In dat bestand maken we een bestandssysteem aan:
mke2fs -m 0 -N 4000 rootfs
De optie -N 4000 geeft het aantal inodes aan, en is aan te passen aan de eigen
behoefte.
Nu kun je het rootfs-bestand mounten via een loopdevice:
mount -o loop -t ext2 rootfs /mnt
En tenslotte kun je het eerder aangemaakte root-bestandssysteem naar het gemounte
rootfs-bestand kopieren:
cp -dpR ~/rfs/* /mnt/
Vergeet de optie -dpR niet!
Nu het bestand nog unmounten:
umount /mnt
Rootfs bevat nu het root-bestandssysteem en is 32Mb groot. Dat past natuurlijk
nooit op een diskette. Dus moeten we het comprimeren:
gzip -v9 rootfs
Nu heb je een bestand "rootfs.gz" van nog maar enkele honderden kilobytes!
5.2 Lilo en zo
We hebben nu dus een root-bestandssysteem gecomprimeerd in het bestand rootfs.gz
en we hebben een zelfgebakken kernel bzImage. Controleer of beide bestanden samen
op een diskette passen. Er moet ook nog wat ruimte overblijven voor wat andere zaken, o.a.
voor het lilo configuratie-bestand. Dit bevat de volgende tekst:
boot=/dev/fd0
install=/boot/boot.b
map=/boot/map
read-write
backup=/dev/null
compact
image=/bzImage
label=linuxCD
initrd=/rootfs.gz
root=/dev/ram0
append="ramdisk_size=32768"
Sla het op onder de naam cdlilo.conf.
5.3 Alles op een flop
Stop een diskette in de drive en maak er een ext2 bestandssysteem op aan:
mke2fs -m 0 /dev/fd0
Mount dit bestandssyteem, verwijder de lost+found directory en maak de
directory's dev en boot aan:
mount -o dev /dev/fd0 /mnt
rm -rf /mnt/lost+found
mkdir /mnt/{boot,dev}
In de dev-directory hebben we weer wat devices nodig, die je kunt kopieren (met
de -R optie) van de harde schijf:
cp -R /dev/{null,fd0,ram0} /mnt/dev/
Dan moet voor lilo boot.b op de diskette gezet worden, wat je ook kunt kopieren
van de harde schijf:
cp /boot/boot.b /mnt/boot/
Tenslotte moeten cdlilo.conf, de kernel en ons gecomprimeerde
root-bestandssysteem nog op de flop geplaatst worden:
cp cdlilo.conf bzImage rootfs.gz /mnt/
Zo, alles wat lilo nodig heeft staat op de diskette. Nu moeten we lilo nog draaien:
lilo -v -C cdlilo.conf -r /mnt
De -C optie vertelt lilo dat cdlilo.conf het te gebruiken configuratie-bestand
is en de -r optie dat /mnt even als rootdirectory ("/") gezien moet worden.
Lilo moet werken zonder foutmeldingen (de eventuele waarschuwingen van
lilo over LBA32 mag je negeren).
De inhoud van de diskette is, na al dat harde werk, als volgt:
/mnt:
totaal 537
-rw-r--r-- 1 root root 182 aug 5 11:07 cdlilo.conf
drwxr-xr-x 2 root root 1024 aug 5 11:11 boot/
-rw-r--r-- 1 root root 542268 aug 2 20:16 bzImage
drwxr-xr-x 2 root root 1024 aug 4 22:08 dev/
-rw-r--r-- 1 root root 367534 aug 4 23:16 rootfs.gz
/mnt/boot:
totaal 11
-rw-r--r-- 1 root root 5824 aug 4 22:08 boot.b
-rw------- 1 root root 4608 aug 5 11:11 map
/mnt/dev:
totaal 0
brw-r----- 1 root root 2, 0 aug 4 22:08 fd0
crw-r--r-- 1 root root 1, 3 aug 4 22:08 null
brw-r----- 1 root root 1, 0 aug 4 22:08 ram0
Je hoeft je niet druk te maken over eventuele kleine verschillen.
Nu kunnen we de proef op de som nemen: we gaan de computer opstarten van onze
vers gebakken boot-flop. Denk wel aan de bios-opstartopties...
Als je alles goed gedaan hebt, zie je eerst de woorden "LILO 22.1 loading
linuxCD", waarna de lappen tekst van de kernel over je scherm vliegen. Aan het eind
zul je wat foutmeldingen krijgen, omdat het bestand "sec" niet gevonden kan worden
(en waarschijnlijk de CD niet gemount). Druk, als alles op het scherm stil staat, op
enter, en je hebt een prachtige prompt van BusyBox.
Geef nu even de opdracht "df", en je ziet, dat je ramdisk een kleine 32Mb groot
is (er is wat afgesnoept voor de inodes) en dat maar een klein deel ervan gevuld is door
het root-bestandssyteem. Er kan dus nog heel wat bij...
6. CD invullen
Nu hebben we een opstartdiskette, maar nog geen CD. De directory's en bestanden, die
straks op de CD komen, zetten we eerst nog even in een aparte directory op de harde schijf
(bijv. "~/cd"). Maak daar eerst de sub-directory "boot" aan en cd daar
naar toe. Dit wordt de plaats waar de image van de opstart-diskette komt te staan:
dd if=/dev/fd0 of=boot.img bs=10k count=144
Verder kun je onder de cd-directory alles kwijt, wat je in je ramdisk wilt hebben,
zolang je maar rekening houdt met de maximale ruimte van ongeveer 30Mb van die ramdisk.
Als je nog drivers, modules, programma's, library's, e.d. wilt laden, nadat het
root-bestandssyteem in de ramdisk is opgezet, dan zet je die in de cd-directory, zonodig
in een sub-directory daarvan.
Daarna moet het "sec"-script nog gemaakt worden.
Stel, dat je de sub-directory's "lib" en "bin" hebt aangemaakt, en die
gevuld hebt met resp. library's en binary's, die naar de ramdisk geschreven moeten worden,
dan zou het "sec"-script er als volgt uit kunnen zien:
#!/bin/sh
mkdir /lib # als die nog niet bestaat...
mount /mnt # staat in inittab
cp /mnt/lib/* /lib/
cp /mnt/bin/* /usr/bin/ # of een andere directory
umount /mnt
Dit is natuurlijk een eenvoudig voorbeeld, maar je kunt het zo ingewikkeld maken als je
wilt. Dat is helemaal afhankelijk van het doel, waarvoor je de CD wilt maken. Dat laten we
dan ook verder aan je eigen inventiviteit over.
7. Iso-bestand maken en CD branden
De El Torito standaard vereist eigenlijk ook nog een boot.catalog bestand van
2048 bytes. Echter, de opdracht "mkisofs" regelt dat automatisch (hulde aan de
makers ervan!). We zijn dus helemaal klaar om het iso-bestand te maken.
Ga naar de cd-directory en geef de volgende opdracht:
mkisofs -r -b boot/boot.img -c boot/boot/catalog -o bootcd.iso .
(Vergeet die laatste punt niet!).
Je iso-bestand is klaar en kan op CD gebrand worden. Daarvoor kun je "cdrecord"
gebruiken, of een van de grafische frontends daarvan. Ook dat laten we aan je eigen
wensen over.
Tenslotte is het tijd om de CD te testen. Stop hem in de drive en reboot je computer
(denk aan de opstart-instellingen in het bios). Als je alles goed gedaan hebt, start de
computer netjes op, en zal op het laatst ook je "sec"-script uitgevoerd worden.
Veel succes!
Bronnen
Linux Bootdisk HOWTO
http://nl.linux.org/doc/books/bootdisk/t1.html
BusyBox
http://www.busybox.net/downloads/BusyBox.html
Ramdisk.txt
http://www.linuxhq.com/kernel/v2.4/doc/ramdisk.txt.html
Laatst herzien op 25-09-2005
|