Creazione del file IMG del dischetto floppy di avvio FreeDOS DOS per V86 su OSX


2

Sto cercando di creare un disco di avvio FreeDOS con OSX compatibile con la libreria V86 . Devo farlo nel terminale (in uno script bash). Sto facendo tutto questo su OSX High Sierra.

Il disco di avvio che sto tentando di creare è un .img di un dischetto floppy. Sono consapevole che ci sono altri modi per fornire dischi di avvio a V86 come un'immagine del disco rigido o un cdrom .iso, ma ci sto provando in questo modo e vorrei almeno capire cosa sto facendo di sbagliato.

Sospetto che il problema che sto riscontrando sia nel tentativo di creare correttamente il Master Boot Record (MBR) dell'immagine del dischetto .


Per il contesto, ecco la mia comprensione del processo di avvio / avvio principale:

Ai vecchi tempi su DOS o su macchine Win9x, mi sembra di ricordare di aver bisogno di eseguire un comando di formattazione con alcuni switch su di esso che renderebbe l'MBR sul disco piuttosto che solo una tabella FAT nella parte anteriore del disco, anche se io ' Non sono sicuro di capire correttamente l'MBR.

La mia comprensione di base e semplificata dell'MBR in quanto l'MBR è i primi 512 byte del dischetto, che specifica quanto è grande il disco, così come le istruzioni che dicono al BIOS di saltare alla prima istruzione di un boot loader che si avvierà il sistema operativo. Ad esempio, su un dischetto DOS è presente / era presente un campo COMMAND.COM. Presumibilmente in quel caso, l'MBR è stato scritto per dire al BIOS di avviare l'esecuzione con la prima istruzione in COMMAND.COM.

Capire dove si trova la prima istruzione sembra che potrebbe essere complicato perché devono accadere un certo numero di cose (penso ..). I primi 512 byte del disco saranno riservati per l'MBR, quindi dopo che un FAT viene annotato che occupa altri X byte del disco, quindi dopo il FAT, c'è spazio vuoto per mettere i file. Quando un file come COMMAND.COM viene scritto sul disco, il FAT viene aggiornato con le informazioni su dove sono memorizzati i byte sul disco. Perché l'MBR sappia dove saltare per trovare la prima istruzione di COMMAND.COM, dovrebbe sapere dove è memorizzato COMMAND.COM, che potrebbe trovarsi ovunque sul disco nello spazio vuoto dopo il FAT, giusto?


Ecco il mio attuale tentativo di creare il disco:

# create a 720k empty img file with all zeros in it

dd if=/dev/zero of=myfloppy.img bs=1024 count=1440

# attach our .img file without mounting it, saving the attached name such as "/dev/disk2" in the var ${DEVICE}

DEVICE=`hdiutil attach -nomount myfloppy.img`

# attempt to use diskutil to format the device as a bootable FAT12 diskette
# question: are dos boot diskettes supposed to be FAT12, FAT16, or FAT32?

diskutil eraseVolume "MS-DOS FAT12" MYFLOPPY bootable ${DEVICE}

# detach our unmounted .img file

hdiutil detach $DEVICE -force

# mount our source freedos image fetched from the V86 demo page, this mounts as /Volume/FREEDOS
# note that this sample image is also 720K

hdiutil mount freedos722.img 

# mount our target .img file we just created, it'll mount as /VOLUMES/MYFLOPPY

hdiutil mount myfloppy.img

# copy minimal set of files necessary to boot the disk (probably dont need autoexec.bat ..)
# question: does the copy order of these files matter? 

cp /Volumes/FREEDOS/COMMAND.COM /Volumes/MYFLOPPY/
cp /Volumes/FREEDOS/KERNEL.SYS /Volumes/MYFLOPPY/
cp /Volumes/FREEDOS/CONFIG.SYS /Volumes/MYFLOPPY/
cp /Volumes/FREEDOS/AUTOEXEC.BAT /Volumes/MYFLOPPY/

# unmount our disks

hdiutil unmount /Volumes/MYFLOPPY/
hdiutil unmount /Volumes/FREEDOS/

#TODO: might need to detach our image files even though we did mount/unmount above

Lo script sopra mi avvicina all'avvio, l'avvio V86 mostra "FREEDOS" anziché lamentarsi del fatto che il disco non è avviabile, ma si blocca dopo aver detto "FREEDOS", piuttosto che continuare il processo di avvio.


Ho anche provato vari altri modi / tentativi di creare l'MBR, in tutti questi casi ho creato il file img vuoto con il comando dd, quindi li ho eseguiti su di esso per creare l'MBR, quindi ho copiato i file come mostrato sopra.

# Attempt #1: After the files are copied to the target disk, try to copy the 512 byte MBR from the source image to mine, if this worked I would be surprised, it didn't.
# this shouldn't work afaik because the MBR on the source image will have instructions to jump to the first instruction in COMMAND.COM as it's layed down on the source disk, which likely isn't where it is on our target disk.

dd if=freedos722.img of=myfloppy.img bs=512 count=1 conv=notrunc

# Attempt #2: try using the diskutil partition instead of erase disk command

diskutil partitiondisk ${DEVICE} 1 MBR "MS-DOS FAT12" "MYFLOPPY" 100%

# Attempt #3: try same as above, but with FAT16 (shouldn't work, didn't, because source img was FAT12)

diskutil partitiondisk ${DEVICE} 1 MBR "MS-DOS FAT16" "MYFLOPPY" 0B

# Attempt #4: use the newfs_msdos command without any diskutil commands

newfs_msdos -F 12 -v MYFLOPPY $DEVICE

# Attempt #5: use fdisk rather than any diskutil or newfs_msdos commands
# I *think* this is making an MBR, but not sure, maybe just making a partition
#note that I have no idea what to specify here for cylinders (c) and heads (h) and just copy/pasted this from somewhere

fdisk -i -c 1024 -h 255 -s 1440 -b 512 -a dos ${DEVICE}

# Attempt #6: use fdisk to create MBR / FAT, then use fdisk to mark that partition 'active'

fdisk -i -c 1024 -h 255 -s 1440 -b 512 -a dos ${DEVICE}
fdisk -e ${DEVICE} 
#fdisk -e puts us in an interactive edit mode, so we do the following
type 'a', then enter # gets us into 'set partition as active' mode
type '1', then enter # sets partition as active
type 'w', then enter # writes the MBR with the partition now marked active

Ho anche provato vari incantesimi in cui mescolo i comandi sopra, come l'esecuzione della partizione diskutil e quindi l'esecuzione del comando fdisk -i per vedere se c'è qualcosa che fdisk farà per correggere l'MBR per la partizione esistente data.


Sono consapevole che ci sono molti modi per creare un dischetto di avvio, ma voglio farlo in uno script. Questi metodi sono elencati qui per completezza nel caso in cui altri siano alla ricerca di possibili modi per farlo:

1: utilizzare il programma di installazione di FreeDOS in un ambiente virtuale come QEMU o VirtualBox, quindi salvare un'immagine del dischetto floppy creato.

2: utilizzare una macchina antica per creare un dischetto di avvio da una vera installazione DOS o Windows.


Ho pensato che forse V86 ha una possibilità molto limitata di avviare un dischetto se qualcosa non va, il che non avrebbe senso come il suo semplice emulazione di x86, ma ho provato ad avviarlo da molti dei tentativi di creazione anche con qemu. Per chiunque stia cercando di farlo, puoi facilmente installare qemu con homebrew, quindi avviare una semplice VM con questo:

qemu-system-x86_64 -fda myfloppy.img

E un collegamento a un problema di V86 in cui lo sviluppatore menziona come creare immagini QEMU tramite processi di installazione del sistema operativo completi che funzioneranno con V86:

https://github.com/copy/v86/issues/128


Se non hai familiarità con V86, è un emulatore x86 scritto sopra asm.js che esegue un sistema operativo virtualizzato in un browser.

L'autore ha vari sistemi operativi demo Linux, Windows e DOS in esecuzione su v86 sul suo host personale:

https://copy.sh/v86/

Mi ci è voluto un po 'per capire come eseguire solo la sua immagine demo di FreeDOS localmente senza la grande demo che richiede il download di più immagini del sistema operativo, ecco la mia fonte per questo:

<!doctype html>
<script src="libv86.js"></script>
<script>
    "use strict";

    window.onload = function() {
            var emulator = window.emulator = new V86Starter({
            memory_size: 32 * 1024 * 1024,
            vga_memory_size: 2 * 1024 * 1024,
            screen_container: document.getElementById("screen_container"),
            bios: { url: "seabios.bin", },
            vga_bios: { url: "vgabios.bin", },
            fda: { "url": "freedos722-t.img", },
            autostart: true,
        });
    }
</script>

<div id="screen_container">
    <div style="white-space: pre; font: 14px monospace; line-height: 14px"></div>
    <canvas style="display: none"></canvas>
</div>

Il file .img di FreeDOS che funziona con V86 è stato recuperato da qui:

https://github.com/copy/images/


I floppy disk non hanno un MBR. Storicamente, il formato del disco floppy IBM esisteva prima ancora che l'MBR fosse pensato.
David Anderson,

Interessante. Cosa c'era di diverso in un dischetto di avvio floppy rispetto a un dischetto normale, allora? Le prime istruzioni per il BIOS a cui saltare sono sempre scritte su un determinato byte sul disco, quindi i miei lavori di copia sopra non si allineano?
Jason Baker,

Considera di avviare il computer BIOS che tenta di eseguire l'avvio da un'unità che contiene un MBR. Il firmware carica l'MBR nella RAM ed esegue il software memorizzato nell'MBR. (L'MBR è memorizzato nel primo settore dell'unità.) Questo software esamina la tabella delle partizioni MBR e determina quale partizione è attiva. Successivamente, questo software carica il Volume Boot Record (VBR) della partizione attiva in memoria ed esegue il software memorizzato nel VBR. (Il VBR è memorizzato nel primo settore della partizione attiva.) Da qui, vengono completati più passaggi per completare l'avvio del computer.
David Anderson,

Ora, considera il computer che avvia il BIOS cercando di avviarsi da un'unità floppy. Non esiste un MBR. Il firmware carica il Volume Boot Record (VBR) in memoria ed esegue il software memorizzato nel VBR. (Il VBR è memorizzato nel primo settore dell'unità.) Da qui vengono completati più passaggi per completare l'avvio del computer.
David Anderson,

Per quanto riguarda le domande postate nel tuo commento, ecco la mia risposta. Se avviabile, allora ci sarà almeno il codice di avvio memorizzato nel VBR. Con altri sistemi operativi, ci può essere più codice di avvio nei settori successivi, ma FreeDos sembra aver bisogno solo del VBR. Il resto del codice necessario per completare l'avvio viene archiviato in file.
David Anderson,

Risposte:


2

Ecco il mio attuale tentativo di creare il disco:

# create a 720k empty img file with all zeros in it

dd if=/dev/zero of=myfloppy.img bs=512 count=1440

# after using the freedos722.img fetched from the V86 demo page 
# to determine the reserve was 1 logical sector, extract the boot code.

dd if=freedos722.img of=boot.img bs=512 count=1

# after using the 720K freedos722.img to determine the command 
# options, format the floppy image

newfs_msdos -B ./boot.img -v MYFLOPPY -f 720 -b 1024 -S 512 -r 1 -F 12 ./myfloppy.img

# remove the boot code file

rm boot.img

# mount our source freedos image fetched from the V86 demo page, 
# this mounts as /Volumes/FREEDOS

hdiutil attach -readonly freedos722.img 

# mount our target .img file we just created, it'll mount as /Volumes/MYFLOPPY

hdiutil attach myfloppy.img

# copy minimal set of files necessary to boot the disk (probably dont need autoexec.bat ..)
# note: the order of the files does not seem to matter.

cp /Volumes/FREEDOS/COMMAND.COM /Volumes/MYFLOPPY/
cp /Volumes/FREEDOS/KERNEL.SYS /Volumes/MYFLOPPY/
cp /Volumes/FREEDOS/CONFIG.SYS /Volumes/MYFLOPPY/
cp /Volumes/FREEDOS/AUTOEXEC.BAT /Volumes/MYFLOPPY/
mkdir /Volumes/MYFLOPPY/FDOS/
cp /Volumes/FREEDOS/FDOS/HIMEM.EXE /Volumes/MYFLOPPY/FDOS/

# eject our disks

hdiutil eject /Volumes/MYFLOPPY/
hdiutil eject /Volumes/FREEDOS/

Come determinare i valori interi utilizzati nei comandi precedenti

Per determinare la dimensione dell'immagine floppy e il tipo di FAT, immettere la seguente sequenza di comandi.

  1. Il comando seguente monta l'immagine.

    hdiutil attach -readonly freedos722.img
    

    L'output di questo comando è mostrato di seguito. Questo output mostra che il volume può essere identificato come FREEDOS.

    /dev/disk1                                              /Volumes/FREEDOS
    
  2. Immettere il comando seguente per ottenere informazioni sull'immagine.

    diskutil info FREEDOS
    

    Di seguito è l'output pertinente da questo comando.

       File System Personality:  MS-DOS FAT12
       Disk Size:                737.3 KB (737280 Bytes) (exactly 1440 512-Byte-Units)
    

    Quindi è qui bs=512che count=1440sono stati determinati i valori dei parametri e per creare il file immagine vuoto. Inoltre, è qui che è -F 12stato determinato il valore del parametro per il newfs_msdoscomando.

  3. Immettere il comando seguente per espellere il volume.

    diskutil eject FREEDOS
    

Di seguito è riportata una tabella tratta da questo sito Web PCguide . La riga "Totale settori per disco" mostra l'immagine per rappresentare un floppy da 720 KB. Ciò in cui è -f 720stato determinato il valore del parametro per il newfs_msdoscomando.

XA1

Alcuni degli altri valori interi possono essere presi da questa tabella. I valori possono anche essere estratti dal BIOS Parameter Block memorizzato nel freedos722.imgfile.

Il comando seguente può essere utilizzato per visualizzare il Volume Boot Record (VBR) memorizzato nel freedos722.imgfile. Il blocco parametri BIOS inizia all'offset 0x0B.

dd if=freedos722.img  count=1 bs=512 | hexdump -Cv

La struttura del BIOS Parameter Block è descritta nell'output del man newfs_msdoscomando. Di seguito è l'output pertinente da questo comando.

Nota: l'output seguente mostra la mappatura tra le newfs_msdosopzioni di comando e i valori memorizzati nel BIOS Parameter Block.

struct bsbpb {
    u_int16_t   bps;            /* [-S] bytes per sector */
    u_int8_t    spc;            /* [-c] sectors per cluster */
    u_int16_t   res;            /* [-r] reserved sectors */
    u_int8_t    nft;            /* [-n] number of FATs */
    u_int16_t   rde;            /* [-e] root directory entries */
    u_int16_t   sec;            /* [-s] total sectors */
    u_int8_t    mid;            /* [-m] media descriptor */
    u_int16_t   spf;            /* [-a] sectors per FAT */
    u_int16_t   spt;            /* [-u] sectors per track */
    u_int16_t   hds;            /* [-h] drive heads */
    u_int32_t   hid;            /* [-o] hidden sectors */
    u_int32_t   bsec;           /* [-s] big total sectors */
};

Nota: il parametro [-s] big total sectorsdeve essere ignorato. Utilizzare [-s] total sectorsinvece il parametro

Un modo più eloquente per determinare i valori nel BIOS Parameter Block sarebbe quello di inserire prima le definizioni delle funzioni fornite di seguito.

getint() { hexdump -s 0x$1 -n $2 -e \"%u\\n\" freedos722.img; }
gethex() { hexdump -s 0x$1 -n $2 -e \"0x%x\\n\" freedos722.img; }

Queste funzioni hanno due parametri posizionali. Il primo è l'offset nel freedos722.imgfile. Questo valore deve essere inserito usando cifre esadecimali. Il secondo è il numero di byte da leggere. I valori validi sono 1, 2e 4.

La tabella seguente mostra i comandi utilizzati per estrarre i seguenti valori di blocco parametri BIOS dal freedos722.imgfile.

         Parameter               Command     Returned Value
----------------------------   -----------   --------------
[-S] bytes per sector          getint b  2         512
[-c] sectors per cluster       getint d  1           2
[-r] reserved sectors          getint e  2           1
[-n] number of FATs            getint 10 1           2 
[-e] root directory entries    getint 11 2         112
[-s] total sectors             getint 13 2        1440
[-m] media descriptor          gethex 15 1        0xf9
[-a] sectors per FAT           getint 16 2           3
[-u] sectors per track         getint 18 2           9
[-h] drive heads               getint 1a 2           2
[-o] hidden sectors            getint 1c 2           0
[-s] big total sectors         getint 1e 2           0

I valori bytes per sectore reserved sectorssono stati utilizzati per determinare i valori dei parametri bs=512e count=1per il ddcomando utilizzato per creare il file del codice di avvio boot.img. Il -b 1024valore del parametro per il newfs_msdoscomando è stato determinato moltiplicando il bytes per sectore sectors per clustervalori insieme.


Si avvia in VirtualBox. Che ne dici di testarlo in V86?
David Anderson,

Se si avvia lì, dovrebbe avviarsi in V86. :) +1
user3439894

Grazie mille per questo esempio. Funziona perfettamente.
Jason Baker,

@Jason Baker: proverò ad aggiungere una spiegazione di come ho determinato i valori interi utilizzati nei comandi.
David Anderson,

Grazie! La risposta estesa è incredibile. Grazie mille.
Jason Baker,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.