libce
Libreria di Calcolatori Elettronici
|
Topics | |
Strutture dati hardware | |
Strutture dati | |
struct | boot64_segment |
Descrittore di segmento ELF. Continua... | |
struct | boot64_modinfo |
Descrittore di modulo. Continua... | |
struct | boot64_info |
Informazioni dal boot loader. Continua... | |
Definizioni | |
#define | MAX_MODULES 3 |
Numero massimo di moduli. | |
#define | MAX_SEGMENTS 4 |
Numero massimo di segmenti ELF. | |
Funzioni | |
bool | controlla_collisione (boot64_info *info, natq beg, natq end) |
Controlla che un modulo non si sovrapponga a quelli già esistenti. | |
bool | decodifica_modulo (multiboot_module_t *mod, boot64_modinfo *info, bool check_align) |
Estrae le informazioni sui moduli. | |
bool | carica_modulo (boot64_info *info, paddr mem_tot) |
Carica il primo modulo secondo le indicazioni della sua tabella di programma. | |
static void | parse_args (char *cmd) |
Interpreta gli argomenti passati al boot loader. | |
bool | crea_finestra_FM (paddr root_tab, paddr mem_tot) |
Mappa la memoria fisica e l'area PCI in memoria virtuale. | |
void | main (natl magic, multiboot_info_t *mbi) |
Entry point C++ del boot loader. | |
Variabili | |
static const int | MAXARGS = 10 |
Massimo numero di argomenti per il boot loader. | |
static int | debug_mode = 0 |
Flag settato se è richiesto il collegamento al debugger. | |
volatile int | wait_for_gdb |
sincronizzazione con gdb | |
boot64_info * | boot_info |
variabile globale in cui _start copia l'indirizzo del boot64_info ricevuto | |
natq | tss_punt_nucleo |
variabile globale in cui _start copia l'indirizzo di punt_nucleo nel TSS | |
Il boostrap avviene in due stadi.
Carica in memoria il secondo bootloader e eventuali moduli. Il secondo boot loader deve essere un file ELF e viene caricato agli indirizzi specificati nella sua tabella di programma (normalmente nel secondo MiB), mentre i moduli possono essere file generici e vengono semplicemente copiati in RAM (subito dopo il secondo boot loader). Il primo boot loader porta il processore da modo reale (16 bit) a modo protetto a 32 bit, quindi cede il controllo al secondo boot loader. Passa nel registro EAX una costante che permette al secondo boot loader di capire di essere stato avviato da un boot loader che rispetta lo standard "multiboot". Nel registro EBX passa l'indirizzo di una struttura multiboot_info_t che contiene varie informazioni (memoria RAM installata nel sistema, indirizzi in RAM delle copie dei moduli, ...). La struttura è definita in "mboot.h" in questa directory.
Stato della memoria alla fine dello stadio 1:
Lo stadio 1 deve aver caricato almeno un modulo e questo modulo deve essere di tipo ELF. Il secondo bootloader interpreta questo modulo e copia i segmenti ELF al loro indirizzo di caricamento (che deve partire dal terzo MiB in poi per non sovrascrivere il boot loader stesso e i moduli). Porta poi la CPU nella modalità a 64 bit e cede il controllo al primo modulo. Passa in EDI il puntatore ad una struttura boot64_info che contiene varie informazioni (in particolare gli indirizzi dei moduli, che si trovano ancora in memoria dove erano stati caricati dal primo boot loader).
Stato della memoria alla fine dello stadio 2:
bool carica_modulo | ( | boot64_info * | info, |
paddr | mem_tot ) |
Carica il primo modulo secondo le indicazioni della sua tabella di programma.
info | puntatore alla struttura che descrive i moduli |
mem_tot | memoria disponibile |
Definizione alla linea 417 del file boot.cpp.
bool controlla_collisione | ( | boot64_info * | info, |
natq | beg, | ||
natq | end ) |
Controlla che un modulo non si sovrapponga a quelli già esistenti.
info | puntatore alla struttura che descrive i moduli |
beg | base del modulo da controllare |
end | limite del modulo da controllare |
Definizione alla linea 320 del file boot.cpp.
Mappa la memoria fisica e l'area PCI in memoria virtuale.
root_tab | indirizzo fisico della tabella radice |
mem_tot | dimensione della memoria fisica |
mappiamo tutta la memoria fisica:
Mappiamo tutti gli altri indirizzi, fino a 4GiB, settando sia PWT che PCD. Questa zona di indirizzi è utilizzata in particolare dall'APIC per mappare i propri registri.
Definizione alla linea 494 del file boot.cpp.
bool decodifica_modulo | ( | multiboot_module_t * | mod, |
boot64_modinfo * | info, | ||
bool | check_align ) |
Estrae le informazioni sui moduli.
mod | puntatore alla struttura passata dal primo boot loader |
info | puntatore alla struttura da riempire |
check_align | opzionalmente, controlla che l'allinamento richiesto non sia superiore alla pagina |
Estrae le informazioni rilevanti dal modulo ELF e le copia nella struttura boot64_info. In questo modo il modulo successivo (il modulo sistema) non ha bisogno di dover interpretare il formato ELF.
Definizione alla linea 341 del file boot.cpp.
void main | ( | natl | magic, |
multiboot_info_t * | mbi ) |
Entry point C++ del boot loader.
magic | codice che identifica lo standard multiboot |
mbi | puntatore alle informazioni passate dal primo bootstrap loader |
Il primo bootstrap loader (in QEMU) attiva il modo protetto (per poter accedere agli indirizzi di memoria principale superiori a 1MiB) e carica il secondo boostrap loader (questo programma) in memoria, quindi salta alla sua prima istruzione. Il primo bootstrap loader può anche passare delle informazioni al secondo (tramite i registri e la memoria).
Il primo loader, prima di saltare alla prima istruzione del secondo (l'entry point specificato nel file eseguibile), lascia nel registro eax un valore di riconoscimento e in ebx l'indirizzo di una struttura dati, contentente varie informazioni (in particolare, la quantità di memoria principale installata nel sistema, il dispositivo da cui è stato eseguito il bootstrap e l'indirizzo di memoria in cui sono stati caricati gli eventuali moduli)
Definizione alla linea 564 del file boot.cpp.
|
static |
Interpreta gli argomenti passati al boot loader.
cmd | stringa degli argomenti |
Scompone la stringa cmd in argomenti separati da spazi. Al momento comprendiamo un solo argomento: -s
, che attiva la modalità debug.
Definizione alla linea 462 del file boot.cpp.
volatile int wait_for_gdb |
sincronizzazione con gdb
Se è richiesta la connessione con il debugger, settiamo a 1 questo flag. Il codice in attiva_paginazione(), prima di saltare all'entry point del primo modulo, entra in un ciclo e ci resta fino a quando il flag vale 1. Lo script debug resetta questo flag alla partenza di gdb.