Vista la notevole difficoltá intrinseca alla realizzazione di un
sistema operativo abbiamo deciso di partire da un approccio relativamente
semplice, riservandoci di tornare in un secondo momento indietro per
modificare e arricchire il codice e l'impostazione generale del
sistema.
Per la fase di
avvio e di configurazione della memoria abbiamo scelto di prendere a
modello il primo kernel scritto per Linux che appare abbastanza chiaro e
ben strutturato (il codice comunque non puó essere troppo seguito date le
differenze degli attuali compilatori).
Tutto il sistema operativo (o per meglio dire quel poco che
abbiamo realizzato finora) e' contenuto in un unico file chiamato "Image".
Questo file,
che come dice lo stesso nome rappresenta l'immagine del sistema, é a sua
volta composto da tre diversi file concatenati tra loro: "boot"
"setup" e
"system". System contiene a sua volta linkati al suo interno tutti i file
che compongono il sistema vero e proprio.
Per i motivi
che si esamineranno in seguito "boot" "setup" e "system" non possono
essere linkati tra loro, ma devono essere semplicemente "attaccati" l'uno
all'altro.
Questa "unione"
comporta di fatto due problemi fondamentali:
1. Il file di boot deve conoscere esattamente le dimensioni
del file "setup" per avere il conto esatto di quanti dati deve
leggere dal disco;
2. Deve essere
eliminato l'header dei file "setup" e "system" prima che vengano
concatenati al file "boot" in modo che si ottenga una continuitá del
codice esguibile e si possa saltare al corretto segmento e offset non
appena entrati in modalitá protetta.
Il primo problema viene risolto all'interno del makefile il
quale compila i file "setup" e "system", ne calcola la lunghezza, la va a
scrivere nel sorgente e poi ricompila quest'ultimo che in tal modo viene a
conoscere la lunghezza esatta dei dati da leggere dal disco (ricordiamoci
che non abbiamo ancora un sistema operativo che ci dice dove finisce il
file da caricare in memoria :-).
Il secondo
problema viene risolto da "build", un file scritto in C che si occupa di
verificare la validitá del bootsector, eliminare gli header e concatenare
i file tra loro fondendoli nell'immagine del sistema (file "Image").
Il file
"boot" si occupa dell'avvio del sistema.
Come
noto esistono dei requisiti specifici per far sí che tale file venga
riconosciuto come tale dalla macchina all'accensione.
Il
file deve essere infatti lungo esattamente 512 byte e deve essere concluso
dai due valori: "0x55" e "0xAA".
Nell'attuale
versione di Ares il file non riempie tutto lo spazio a disposizione, ma il
"build" si occupa automaticamente di riempire lo spazio che avanza ed
inserire alla fine i due valori di riconoscimento.
Diamo quindi un'occhiata ravvicinata alle operazioni che
compie il boot:
La routine di
startup del Bios all'accensione della macchina carica il primo settore del
disco (512 bytes) in memoria all'indirizzo 0x7c000. Ció vuol dire che
troviamo in memoria i primi 512 byte del file Image, e cioé esattamente il
codice corrispondente al file "boot".
A questo punto
boot sposta sé stesso all'indirizzo 0x90000 e salta a quella
locazione.
In questo
momento abbiamo ancora gli interrupt del Bios a disposizione e quindi
possiamo facilmente scrivere a video la stringa "Loading setup..." a mezzo
dell'int. 0x10.
A questo punto
viene caricata dal disco alla locazione 0x010000 una porzione di codice
corrispondente al file "setup" (ricordiamoci che build aveva scritto nel
sorgente la lunghezza del file in bytes). Il relativo codice viene poi
spostato alla locazione 0x90200 e viene quindi operato un jump immediate
alla medesima locazione. Ci ritroviamo così all'inizio del file
setup.s.