Kategória: Linux všeobecne

Zmenené: 5. august 2009

Disketa bez diskety

Disketa je stále dôležitý nástroj pre správu počítačov, najmä tých starších, ktoré nemajú CD/DVD mechaniku, či z nej nedokážu bootovať. No v mnohých nových počítačoch však už disketová mechanika nie je. Tak sa poďme pozrieť ako s disketou pracovať bez disketovej mechaniky.

Riešením je tzv. obraz diskety. Jedná sa vlastne o súbor, ktorý obsahuje celý obsah diskety a viac-menej môže plne nahradiť fyzickú disketovú mechaniku (za istých okolností sa dá z neho aj bootovať). Ja som sa do problémov s chýbajúcou disketovou mechanikou dostal práve kvôli bootovaniu, pretože som si chcel pripraviť bootovacie obrazy diskiet, ktoré som si pripravoval pre použitie na sieťový boot (PXELinux).

Vytvorenie obrazu

Ak máte k dispozícii fyzickú mechaniku, je obraz diskety najjednoduchšie získať jej prekopírovaním do súboru, na čo poslúži príkaz dd, napr.:

dd if=/dev/fd0 of=disketa.img

Parameter if udáva vstupný súbor (input file) a parameter of zase súbor výstupný (output file). Áno, pripomínam, že v Linuxe je všetko (ohľadom súborového systému) súbor, teda aj disketová mechanika (či disketa) je súbor. Ale ani keď disketovú mechaniku nemáte, nie je nič stratené, pretože rovnaký príkaz dokáže vytvoriť obraz diskety, samozrejme prázdny:

dd if=/dev/zero of=disketa.img bs=1k count=1440

Teda nie prázdny, ale obsahujúci samé nuly. Keďže však v tomto prípade súbor s nulami (/dev/zero) nekončí, je treba mu zadať kedy má skončiť. V tomto prípade má prekopírovať 1440 (count) blokov, každý o veľkosti 1 kB (bs), to je dohromady 1440 kB. Teda mnohým dobre známa veľkosť bežnej diskety. Jednoduchým zmenením hodnoty count možno riadiť veľkosť vzniknutého obrazu diskety. Chcete disketu s veľkosťou 770 kB? Žiadny problém:

dd if=/dev/zero of=disketa770.img bs=1k count=770

Alebo radšej disketu s veľkosťou 2.8 MB? Prosím:

dd if=/dev/zero of=disketa770.img bs=1k count=2880

Ak Vás napadlo, že takto si môžete vytvoriť disketu ľubovoľnou veľkosťou, máte pravdu. Ale..

Formátovanie obrazu

Jedna vec je disketu vytvoriť, druhá však je, že ju treba naformátovať. Keďže som chcel cez PXE bootovať MS-DOS (respektíve jeho klony ako FreeDOS a pod), potrebujem disketu naformátovať súborovým systémom FAT, no a tu to už s tou ľubovoľnosťou veľkosti nie je až také jednoduché. Preto v ďalšom popise ostanem pri štandardných veľkostiach, konkrétne 1,4 a 2,8 MB.

Na formátovanie súbúrúvého systému FAT v Linuxe poslúži príkaz mkdosfs, ktorý je v Debiane súčasťou balíka dosfstools. Jeho použitie je pomerne jednoduché, na naformátovanie našej 1,4 MB diskety (teda jej obrazu) stačí zadať príkaz:

mkdosfs -n MojDisk disketa.img

Tento príkaz automaticky vyberie vhodnú veľkosť FAT (12, 16 alebo 32), čo je v tomto prípade FAT12 a nastaví meno diskety (label) na MojDisk. Nastavenie mena diskety nie je povinné, ale ja si diskety rád popisujem aj takto… Inou možnosťou (ktorú ešte budem spomínať neskôr) je použitie programu mformat, z balíka mtools. Ak by ste si teraz tento obraz zapísali na disketu, napríklad takto:

dd if=disketa.img of=/dev/fd0

a túto vložili do nejakej mechaniky, zistíte, že máte plne funkčnú DOS-ovskú disketu – len prázdnu veď ste ju len naformátovali.

Pripájanie obrazu

Aby sme na obraz diskety moli aj zapisovať súbory, je teba ho pripojiť do nejakého adresára. Na pripájanie zariadení je v adresárovej štruktúre vyčlenený adresár /mnt, prípadne /media. Teda, radšej to výslovne napíšem, určite nepripájajte zariadenia priamo do týchto adresárov, ale vytvorne si v nich podadresár a pripájajte do neho! Na pokusné pripájanie však dávam prednosť adresáru /tmp, čím si doma šetrím prácu so zmazaním adresára na pripájanie. Takže vytvorme si tam podadresár:

mkdir /tmp/disketa

a do toho adresára teraz môžme pripojiť náš obraz diskety, a to pomocou zariadenia loop:

mount -o loop disketa.img /tmp/disketa

teraz všetko, čo zapíšem do adresára /tmp/disketa, vlastne zapisujeme do obrazu diskety. Príkaz mount automaticky vyberie prvé prázdne zariadenie /dev/loopX. Ak z nejakého dôvodu treba zadať konkrétne zariadenie, možno mu ho definovať v príkaze, napríklad pre /dev/loop6 by to vyzeralo takto:

mount -o loop=/dev/loop6 disketa /tmp/disketa

Celé to však má jeden háčik, a tým sú prístupové práva, respektíve vlastníctvo súborov. Samozrejme súborový systém FAT nič také nepozná, ale Linux áno a pracuje s prístupovými právami aj pri tomto súborovom systéme. A keďže toto pripájanie bolo zatiaľ robiť ako root, všetky súbory a adresáre pripojeného obrazu vlastní práve root, čo môže spôsobiť problémy pri zapisovaní. Riešením by mohlo byť pridanie záznamu do /etc/fstab, ktorý by povoľoval pripojenie aj bežnému používateľovi, čo však iste nie je dobrý nápad pre dočasné pokusy.

Za lepšie riešenie považujem zadanie používateľa a jeho skupiny pri pripájaní. Avšak príkaz mount neumožňuje zadať používateľa a skupinu pomocou ich mena, len pomocou ich identifikačných čísel. Preto najprv potrebujeme zistiť pod akým číslom nás pozná systém, čo vyčítame z výstupu príkazu id:

id
uid=1000(slavko) gid=1000(slavko) skupiny=4(adm),7(lp),20(dialout),24(cdrom),25(floppy),...

Tento príkaz vypíše okrem mena a čísla používateľa aj mená a čísla všetkých skupín, do ktorých používateľ patrí. Nás však teraz zaujímajú len dva údaje, ktoré som zvýraznil vo výpise červenou farbou. Tieto hodnoty (väčšinou stačí UID) stačí pridať do parametrov pripojenia obrazu a problém s právami prestane existovať:

mount -o loop -o uid=1000 disketa.img /tmp/disketa

Po zapísaní dát do obrazu (teda do pripojeného adresára) je treba pred ďalším použitím odpojiť, pretože inak sa ľahko stane, že údaje nebudú skutočne zapísané v súbore obrazu diskety, ale osanú niekde vo vyrovnávacej pamäti:

umount /tmp/disketa

Bootovacia dvojdisketa

Trochu iná situácia je, keď chcem vytvoriť bootovaciu disketu, teda jej obraz. Tu si bez nejakého originálu (rozumejme existujúci bootovací disk, či jeho obraz) nepomôžem, pretože Linux prosto neobsahuje veci, ktoré je potrebné na takú bootovaciu disketu vložiť. Ak použijete na vytvorenie obrazu vyššie spomínaný príkaz dd z reálnej diskety, ktoré je bootovacia, bude aj jej obraz bootovací. Ak takú disketu k dispozícii nemáte alebo nemáte k dispozícii disketovú mechaniku, treba sa popozerať po internete. Dobrým začiatkom môžu byť stránky ako AllBootDisks.com, či BootDisk.com, či iné zdroje…

Každopádne, keď som si chcel vyrobiť bootovaciu dvojdisketu (2,8 MB), internet mi nepomohol a musel som si ju vyrobiť sám. Tu však už je príkaz mkdosfs krátky a do hry vstupuje balík mtools so svojimi príkazmi mformat a mcopy. Príkaz mformat dokáže pri formátovaní prekopírovať bootsektor z inej diskety (obrazu) a mcopy zase dokáže na takto naformátovanú disketu prekopírovať (okrem iných aj) potrebné systémové súbory. Ale pekne poporiadku.

Ako celkom prvé si musíme zohnať obraz bootovacej diskety, povedzme, že ho máme a volá sa diskboot.img a je uložený v rovnakom adresári ako obraz našej dvojdiskety (disketa.img), ktorú sme si vytvorili príkazom:

dd if=/dev/zero of=disketa.img bs=1k count=2880

Jeho naformátovanie spolu s prekopírovaním bootsektoru dosiahneme príkazom:

mformat -i disketa.img -f 2880 -B diskboot.img ::

Parametrami príkazu vravíme, aby naformátoval obraz diskety (-i disketa.img), a to na veľkosť 2880 kB (-f 2880) a skopíroval zavádzací sektor z nášho bootovacieho obrazu (-B diskboot.img). Tá dvojitá dvojbodka na konci je dôležitá, pretože nahradzuje DOS-ové označenie zariadenia (napr. A:), aby príkaz mformat vedel, že nemá hľadať disketovú mechaniku, ale použiť zadaný obraz.

Po naformátovaní je treba prekopírovať (najmä) systémové súbory z pôvodného bootovacieho obrazu. Ak Vás napadne obrazy pripojiť a použť cp, tak nebudete úspešný, disketa nenaštartuje, pretože systémové súbory musia byť na konkrétnom mieste, čo cp nezaistí. Ale zaistí to príkaz mcopy, ktorému však musíme najprv nastaviť disketu, z ktorej má súbory kopírovať. Toto nastavenie je treba urobiť v konfiguračnom súbore /etc/mtools.conf, kde mu nastavíme DOS-ovské písmeno mechaniky tak, aby odkazovalo na náš pôvodný bootovací obraz:

#drive a: file="/dev/fd0" exclusive
#drive a: file="/dev/loop0" exclusive
drive a: file="/celá/cesta/k/diskboot.img" exclusive

Prvý riadok, ktorý je zakomentovaný znakom #, je pôvodný riadok tohoto konfiguračného súboru. Druhý riadok je tiež zakomentovaný a teda nebude braný do úvahy, je tu len ako ukážka použitia zariadenia loop. Použité bude vlastne len nastavenie tretieho riadku, kde je treba zadať úplnú cestu k nášmu bootovaciemu obrazu. Toto nastavenie umožní, že v príkaze mcopy bude možné k súborom na obraze diskety pomocou DOS-ovskéh písmena a:. Teraz môžme prekopírovať celý obsah bootovacej diskety na našu dvojdisketu:

mcopy -i disketa.img a: ::

V prípade, že chcete rekurzívne kopírovať aj obsah adresárov, treba pridať voľbu -s:

mcopy -s -i disketa.img a: ::

Teraz je naša dvojdisketa použiteľná ako bootovacia. Ak máte nainštalovaný virtualizačný nástroj qemu, môžete bootovanie z obrazu vyskúšať zadaním:

qemu -fda disketa.img -m 64 -boot a

Trojdisketa?

Hoci známy štandardný rozmer diskety končí dvojnásobnou veľkosťou (2880 kB), nie je to ani zďaleka koniec, viz. napríklad floopy.c v zdrojáku jadra. Mňa však veľké disketyzaujímali najmä kvôli PXE. Spolu so zadaním geometrie disku je možné vytvoriť prakticky ľubovoľne veľkú disketu, ktorú možno po sieti nabootovať pomocou memdisk. Ako ju však vytvoriť? Na stránke The GUI project sú k dispozícii dva skripty, mkfloppyimage.sh a newmkfloppyimg.sh. Oba robia v podstate to isté, ale ten s new na začiatku to robí trošku príjemnejšie a keď ho spustíte s parametrom -h, vypíše popis použitia… A čo robia?

Vytvárajú obrazy diskiet skoro ľubovoľnej veľkosti a potebujú k tomu iný obraz bootovacej diskety s veľkosťou 1440 alebo 2880 kB. A to ešte nie je všetko, pretože na konci vypíšu parametre, ktoré je treba zadať pre správnu funkciu v memdisk. Napísal som „skoro ľubovoľnú veľkosť“, tento môj záver vychádza z toho, že skripty sú pripravené na tvorbu naozaj veľkých diskiet a požadovaná veľkosť diskety sa zadáva v MB. Tieto sú v skripte prepočítané na kB, takže po malej úprave skriptu je to naozaj veľkosť ľubovoľná.

Moja úprava mkfloppyimage.sh

#!/bin/bash

# Last updated: 5.Augusta 2009

if [ $(id -u) -ne 0 ]; then
   echo "Spúšťať ako root!!!"
   exit 2
fi

if [ $# -ne 3 ]; then
   echo "Použitie: $(basename $0) newimage oldimage size[kB]"
   exit 1
fi

NEWIMAGE=$1
OLDIMAGE=$2
SIZEKB=$3

MKDOSFS=$(which mkdosfs)
((NUMSECT= SIZEKB << 1))
MNTNEW=`mktemp -d /tmp/new.XXXXXX` # Create a mountpoint
MNTOLD=`mktemp -d /tmp/old.XXXXXX` # Create a mountpoint

# Create the filesystem
OUTLINE=`$MKDOSFS -I -v -C $NEWIMAGE $SIZEKB | grep heads`
HEADS=`echo $OUTLINE | cut -f3 -d' '`
SECTORS=`echo $OUTLINE | cut -f6 -d' '`
((CYLINDERS= NUMSECT / HEADS / SECTORS ))
# Copy contents from old image to new image
mount -o loop $NEWIMAGE $MNTNEW
mount -o loop $OLDIMAGE $MNTOLD
cp -r $MNTOLD/* $MNTNEW
umount $MNTNEW
umount $MNTOLD
rmdir $MNTNEW
rmdir $MNTOLD

# Create the boot sector of the new image
# copy the first 512 bytes from the OLD image
#      except the bytes 11 through 61 (inclusive) -- if starting at 0
#      of bytes 12 through 62 (inclusive) -- if starting at 1
#      dd starts counting at 1 -- Thanks to Christian Schneider
#         for pointing this bug (which should not cause any damage)

# copy uptil the 12th byte (not including the 12th byte)
dd if=$OLDIMAGE of=$NEWIMAGE bs=1 count=11 conv=notrunc 2>/dev/null

# copy from 63 (i.e. skip first 62 bytes) to 512 bytes
# hence we need to copy 512-62=450 bytes
dd if=$OLDIMAGE of=$NEWIMAGE bs=1 skip=62 seek=62 conv=notrunc count=450 2>/dev/null

# Print the details
echo "Your floppy image is in $NEWIMAGE. When using it in iso/pxelinux, dont forget to add"
echo "\"floppy c=$CYLINDERS s=$SECTORS h=$HEADS\" to the argument of memdisk"

Obraz diskety vo wine

Občas sa mi stane, že dostanem obsah diskety k dispozícii ako samorozbaľovací archív, ktorý treba spustiť a sám svoj obsah prekopíruje priamo na disketu. Výbroná vec. V emulátore wine mi to niekedy funguje, ale nemám disketovú mechaniku, čiže tento samorozbaľovací nástroj sa nemá kam rozbaliť. Prečo ho však jeho obsah nerozbaliť do obrazu?

Je to prosté. Stačí v adresári ~/.wine/dosdevices/ vytvoriť adresár a: (áno aj z dvojbodkou). Prípadne vytvoriť adresár inde a na tento vytvoriť symbolický odkaz, ale to je na jednorázovú akciu zbytočne zložité… Takže adresár:

mkdir ~/.wine/dosdevices/a:

Do tohoto adresára pripojíme náš obraz diskety tak, aby používateľ bol vlastníkom súborov:

mount -o loop -o uid=1000 -o gid=1000 disketa.img /home/slavko/.wine/dosdevices/a:

Teraz už zápisu na disketu prostredníctvom wine nič nebráni. Možno len funkčnosť samotného programu, teda, či bude vo wine fungovať, ale to je o tom, ako program pristupuje k diskete. Bez problému mi funguje vytvorenie univerzálneho NetBootDisk-u, pravdepodobne pretože pristupuje na úrovni súborového systému. Rozbaľovanie archívov z AllBootDisks a podobných už nefunguje a končí chybou „The current image format is not supported by the disk drive“.