[ Pagina Principale || Redazione || Informazioni || Vai a... ]

Bootiamo ?

di Francesco Sileno

Forse qualcuno di voi si sara' chiesto cosa succede quando il PC viene acceso e il Sistema Operativo parte... magari se lo sara' chiesto il giorno che il S.O. non ne vuole piu' sapere di partire, o quando improvvisamente l'HD risulta privo di partizioni, o se se ne esce con un terrorizzante NO ROM BASIC - SYSTEM HALTED.
Beh, chi ha gia' trovato la risposta, passi pure avanti; chi non l'ha trovata, sta per avvicinarsi agli arcani segreti del Master Boot Record, della Partition Table e del Boot Sector.

In una prima analisi semplificata, ecco cosa avviene:

    - Il PC viene acceso. Vengono eseguiti i POST.
    - Il PC guarda il BIOS, prende il primo HD 
        configurato (il MASTER in caso di 2 o piu 'HD), e ne carica il primo settore 
        assoluto. Cioe' quel settore che ha come coordinate Faccia=0, Cilindro=0 e
        Settore=1.
        NOTA: Tutti gli HD hanno Settori fisici da 512bytes   
        (almeno mi risulta), e a questo livello il termine CLUSTER non ha ancora significato.
    - Se non viene trovato un HD, il BIOS passa a leggere il primo settore del
        primo floppy attivo, altrimenti...
    - Il settore appena caricato e' il Master Boot Record, contenente la
        tavola delle partizioni e il codice necessario alla determinazione
        e avviamento della partizione di boot.
    - L'esecuzione passa al codice del Master Boot Record, che provvede ad
        identificare tramite il Boot Flag quale partizione e' quella da
        avviare, o a visualizzare un messaggio di errore se risulta piu' di
        una partizione avviabile, o nessuna, o se la Tavola delle
        Partizioni e' corrotta.
    - Determinata quale partizione e' quella di boot, ne viene caricato in
        memoria il primo settore (della partizione, non dell'HD!), e quindi
        l'esecuzione passa al codice contenuto in tale settore.
        Questo e' il Boot Sector della partizione.
    - A questo punto e' in esecuzione il codice che permette ad ogni S.O.
        di avviarsi, e che ovviamente cambia da S.O. a S.O.

Detto cio', diamo un occhiata a come sono fatti questi settori...

Master Boot Record

Le dimensioni sono in byte, e gli offset sono espressi in esadecimale.

Offset  Dimensione   Contenuto
------------------------------
 +0     1BEh         Codice per caricare il Boot Sector della partizione attiva 
 +1BEh  10h          Informazioni partizione 1
 +1CEh  10h          Informazioni partizione 2
 +1DEh  10h          Informazioni partizione 3
 +1EEh  10h          Informazioni partizione 4
 +1FEh  2            55 AA  (Identificativo tavola partizioni: 0AA55h)

Potrebbe sembrare che siano quindi permesse al piu' 4 partizioni per HD... in realta' 4 e' il limite di PARTIZIONI PRIMARIE e ESTESE, pero' poi ricordate che ogni ESTESA puo' contenere piu' UNITA' LOGICHE. Il codice identificativo e' usato semplicemente per assicurarsi che il settore in esame e' il Master Boot Record e che sia stato letto correttamente.

E cosa c'e' dentro ogni blocco di informazioni di ogni partizione? Ecco qui:

Informazioni partizione

Offset  Dimensioni  Contenuto   Descrizione
-------------------------------------------
 +0     1           Boot        Boot Flag: 0=non attiva, 80h = attiva
 +1     1           Hd          Inizio: numero testina
 +2     2           Sec Cyl     Inizio: settore & cilindro del boot sector
 +4     1           Sys         System code: 0=unknown, 1=DOS 12-bit FAT, 
                                             4=16-bit FAT
 +5     1           Hd          Fine: numero testina
 +6     2           Sec Cyl     Fine: settore & cilindro dell'ultimo settore
 +8     4           low  high   Inizio espresso in settori relativi
 +0Ch   4           low  high   Dimensione, in numero di settori
 +10h               inizio del prossimo blocco di informazioni, o 0aa55H se era
                    l'ultimo
Come vedete qui sono contenute tutte le informazioni relativa ad una partizione: dove inizia, dove finisce, quanto occupa, se e' di boot, e persino che tipo di File System adotta.

Nota:
Settori e Cilindri sono rispettivamente 6 bits e 10 bits, memorizzati nel seguente modo:

C7 C6 C5 C4 C3 C2 C1 C0 | C9 C8 S5 S4 S3 S2 S1 S0
ovvero i 2 bit piu' significativi del cilindro sono memorizzati nel byte meno significativo.
In questo modo si mantiene la compatibilita' con le modalita' di funzionamento dell' INT 13h, e si ha la famosa limitazione dei 1024 cilindri (2^10): vedi BETA Numero 2, "Uno sguardo al Setup -prima parte".

Boot Sector

Questa e' la struttura che ci si aspetta da un Boot Sector DOS-like:

Offset  Dim. Contenuto                    Descrizione 
------  ---- -------------------------------------------------------------------
 +0      3   JMP xx xx                NEAR jump all'inizio del codice
           
 +3      8   'I' 'B' 'M'  '3' '.' '2' Nome e versione del SO
           
 +0Bh    2   SectSiz                  bytes per settore
            
 +0Dh    1   ClustSiz                 settori per unita' di allocazione (cluster)
 +0Eh    2   ResSecs                  settori riservati (settori prima della prima   
                                      FAT [** link a FAT **])
 +10h    1   FatCnt                   numero di FAT
            
 +11h    2   RootSiz                  numero massimo di elementi di root directory
 +13h    2   TotSecs                  numero totale di settori
 +15h    1   Media                    descrittore partizione
 +16h    2   FatSize                  numero di settori in una FAT
 +18h    2   TrkSecs                  settori per traccia (cilindro)
 +1Ah    2   HeadCnt                  numero di testine di lettura/scrittura
 +1BH    2   HidnSec                  settori nascosti
 +1Eh                                 informazioni aggiuntive (DOS 4.00+)
 +??h                                 inizio codice/dati Boot Sector


Debugging!

Bene, adesso cominciamo a fare sul serio, e mettiamoci a curiosare nel disassemblato di un MBR rubato all'MS-DOS 6.2. Tenendo presente che il MBR viene automaticamente caricato all'indirizzo 0000:7C00, quella che segue e' l'immagine di cio' che effettivamente risiede in memoria, quindi leggermente piu' complesso di un sorgente! L'immagine e' suddivisa in blocchi, ognuno seguito da un commento; fate pero' attenzione che i blocchi non vengono necessariamente eseguiti nell'ordine in cui compaiono: tenete d'occhio i salti!

0000:7C00 FA            CLI
0000:7C01 33C0          XOR     AX,AX
0000:7C03 8ED0          MOV     SS,AX
0000:7C05 BC007C        MOV     SP,7C00
0000:7C08 8BF4          MOV     SI,SP
0000:7C0A 50            PUSH    AX
0000:7C0B 07            POP     ES
0000:7C0C 50            PUSH    AX
0000:7C0D 1F            POP     DS
0000:7C0E FB            STI
Vengono inizializzati i segmenti, tutti a 0. Notate come lo stack viene posizionato in coincidenza dell' inizio del codice, con la conseguenza che ogni operazione su di esso comporta la perdita di istruzioni. Tuttavia il codice perso viene eseguito una sola volta e non si corre il pericolo che la dimensione dello stack aumenti in maniera eccessiva.

0000:7C0F FC            CLD
0000:7C10 BF0006        MOV     DI,0600
0000:7C13 B90001        MOV     CX,0100
0000:7C16 F2            REPNZ
0000:7C17 A5            MOVSW
0000:7C18 EA1D060000    JMP     0000:061D
Il codice viene spostato da 0000:7C00 a 0000:0600, e questo perche' il Boot Sector dell'eventuale partizione attiva viene ricaricato all'indirizzo 0000:7C00.
Il JMP viene effettuato a 61D per arrivare direttamente al blocco seguente.

NOTA: da questo punto in poi, le istruzioni di JZ, JNZ etc fanno riferimento all'offset 7C00, mentre le MOV SI,xxxx sono gia' pronte per lo spostamento in 0000:0600 effettuato poco prima. Quindi, per convertire xxxx in modo che riusciate a capire dove punta, dovete fare xxxx-0x600+0x7C00.
Es. nella prima riga del blocco successivo, 0x7BE -> 0x7DBE, che corrisponde all'inizio della tavola delle partizioni (offset relativo 0x1BE, piu' 0x7C00).
Accanto alle conversioni, il '(msg)' sta a significare che SI punta a un messaggio di errore, elencati in fondo al disassemblato.

0000:7C1D BEBE07        MOV     SI,07BE             ; 7DBE
0000:7C20 B304          MOV     BL,04
0000:7C22 803C80        CMP     BYTE PTR [SI],80
0000:7C25 740E          JZ      7C35
0000:7C27 803C00        CMP     BYTE PTR [SI],00
0000:7C2A 751C          JNZ     7C48
0000:7C2C 83C610        ADD     SI,+10
0000:7C2F FECB          DEC     BL
0000:7C31 75EF          JNZ     7C22
0000:7C33 CD18          INT     18
Un piccolo loop che controlla il Boot Flag di ogni partizione, verificando anche che non ci siano flag settati con valori impossibili.
Se alla fine del loop non e' stata trovata una partizione attiva, viene eseguito l'INT 18h, che nei PC originali avviava il ROM BASIC, nei PC attuali stampa l'orribile messaggio e inchioda tutto; altrimenti si passa al blocco successivo.

0000:7C35 8B14          MOV     DX,[SI]
0000:7C37 8B4C02        MOV     CX,[SI+02]
0000:7C3A 8BEE          MOV     BP,SI
0000:7C3C 83C610        ADD     SI,+10
0000:7C3F FECB          DEC     BL
0000:7C41 741A          JZ      7C5D
0000:7C43 803C00        CMP     BYTE PTR [SI],00
0000:7C46 74F4          JZ      7C3C
0000:7C48 BE8B06        MOV     SI,068B                 ; 7C8B (msg)
Quest'altro loop si occupa di verificare che non ci siano altre partizioni attive o con Boot Flag invalido oltre a quella gia' trovata. Se non si trovano errori, si passa al blocco che provvede a caricare il Boot Record.
Notate come nelle prime 2 righe si provvede a salvare le informazioni riguardanti settore cilindro e testina di inizio della partizione. Notate la raffinatezza: in DX viene posto il Boot Flag (DL) e la testina di inizio (DH). La funzione 2 dell'INT 13h richiede che DL contenga il numero del drive di cui leggere i settori, e guarda caso 0x80 identifica il primo HD. Ora sappiamo perche' il Boot Flag di una partizione attiva e' 0x80.

0000:7C4B AC            LODSB
0000:7C4C 3C00          CMP     AL,00
0000:7C4E 740B          JZ      7C5B
0000:7C50 56            PUSH    SI
0000:7C51 BB0700        MOV     BX,0007
0000:7C54 B40E          MOV     AH,0E
0000:7C56 CD10          INT     10
0000:7C58 5E            POP     SI
0000:7C59 EBF0          JMP     7C4B
0000:7C5B EBFE          JMP     7C5B
Questa e' una semplice routine per stampare un msg a video, facente uso dell'INT 10h.
L'ultima riga, un loop infinito, inchioda la macchina costringendo al reset.
Qualcuno potrebbe chiedersi, come ho fatto io, che cosa sta a fare in mezzo al programma... beh, e' roba Microsoft, non scordiamolo! ;-)

0000:7C5D BF0500        MOV     DI,0005
0000:7C60 BB007C        MOV     BX,7C00
0000:7C63 B80102        MOV     AX,0201
0000:7C66 57            PUSH    DI
0000:7C67 CD13          INT     13
0000:7C69 5F            POP     DI
0000:7C6A 730C          JNB     7C78
0000:7C6C 33C0          XOR     AX,AX
0000:7C6E CD13          INT     13
0000:7C70 4F            DEC     DI
0000:7C71 75ED          JNZ     7C60
Qui si cerca di caricare in 0000:7C00 il Boot Sector della partizione attiva, riprovando al piu' 5 volte prima di dare errore, provando a ricalibrare il disco.

0000:7C73 BEAE06        MOV     SI,06AE                 ; 7CAE (msg)
0000:7C76 EBD3          JMP     7C4B
0000:7C78 BEE306        MOV     SI,06E3                 ; 7CE3 (msg)
0000:7C7B BFFE7D        MOV     DI,7DFE
0000:7C7E 813D55AA      CMP     WORD PTR [DI],AA55
0000:7C82 75C7          JNZ     7C4B
Una volta caricato il Boot Sector, lo si controlla esaminando gli ultimi 2 bytes. Se non sono anche loro settati con il codice 0xAA55, evidentemente non e' un settore di Boot quello caricato...

0000:7C84 8BF5          MOV     SI,BP
0000:7C86 EA007C0000    JMP     0000:7C00
E questo e' il JMP che termina l'esecuzione del MBR e passa il comando al Boot Sector appena caricato.

0000:7C80  55 AA 75 C7 8B F5 EA 00-7C 00 00 54 61 76 6F 6C   U.u.....|..Tavol
0000:7C90  61 20 64 65 6C 6C 65 20-70 61 72 74 69 7A 69 6F   a delle partizio
0000:7CA0  6E 69 20 6E 6F 6E 20 76-61 6C 69 64 61 00 45 72   ni non valida.Er
0000:7CB0  72 6F 72 65 20 64 75 72-61 6E 74 65 20 6C 27 69   rore durante l'i
0000:7CC0  6E 73 74 61 6C 6C 61 7A-69 6F 6E 65 20 64 65 6C   nstallazione del
0000:7CD0  20 73 69 73 74 65 6D 61-20 6F 70 65 72 61 74 69    sistema operati
0000:7CE0  76 6F 00 53 69 73 74 65-6D 61 20 6F 70 65 72 61   vo.Sistema opera
0000:7CF0  74 69 76 6F 20 6D 61 6E-63 61 6E 74 65 00 00 00   tivo mancante...
Questo e' l'insieme dei messaggi d'errore, ASCII Zero-Terminated. Come faceva notare Luciano Giustini, e' opprimente vedere solo messaggi demoralizzanti, e nessuno tipo "Master Boot Record perfettamente avviato." :-)

Questo e' solo un esempio, altri S.O. possono fare cose diverse, ma l'essenza dei passi DEVE essere la stessa.

Ora si potrebbe curiosare nel Boot Sector, ma qui in effetti ogni S.O. fa quello che gli pare, quindi se volete divertirvi, potete grabbare il settore relativo 0 della partizione di boot e darlo in pasto al debug... buon lavoro!

                                                        binariamente,
                                                                Cthulhu

[ Pagina Principale || Redazione || Informazioni || Vai a... ]
BETA - la rivista ipertestuale tecnica, copyright © 1994-95 Luciano Giustini e Fernando Carello. Tutti i diritti riservati.
Numero di accessi a questa pagina dal 29/08/95: (installazione in rete)