Compago

...free knowledge

 
  • Increase font size
  • Default font size
  • Decrease font size
Home Manuali Programmazione Storia di un boot - Partition Boot Sector

Storia di un boot - Partition Boot Sector

E-mail Stampa PDF
Indice
Storia di un boot
Partition Boot Sector
Dentro la partizione
Tutte le pagine

 

Partition Boot Sector

Un settore è l'unità minima di dati in lettura e scrittura su disco ed è fatto da 512 byte.
Un claster è l'unità minima di allocazione di un file su disco e può essere formato da un numero fisso di settori (sempre potenza di 2).

Questo blocco viene caricato in memoria all'indirizzo 0000:7C00 dall'MBR.
Questa volta non inserisco anche l'indirizzamento di memoria dato che in seguito con un artifico verrà fatto coincidere con l'indirizzo locale del blocco di codice per cui l'indirizzo iniziale 0000:7C00 => 07C0:0000 sempre uguale a 7C00h, e finisce in 7E00h

Questo blocco rappresenta il codice iniziale della partizione designata come bootable (partition Boot Sector).

00000000 EB52 jmp short 0x54 ;Salta direttamente all'inizio del codice 
00000002 90 nop ;Se il salto fosse stato più lungo avrebbe utilizzato anche questo byte

Questa area è usata per le variabili e le costanti che costituiscono il BPB (BIOS parameter block) e che servono per trovare la tabella MFT la quale a sua volta serve per sapere dove trovare i file su disco.

00000003 4E54465320202020 "NTFS " (OEM ID)
0000000B 0002 ;N° byte per settore - variabile usata nella terza fase O1
0000000D 08 ;N° settori per cluster - variabile usata nella terza fase O2
0000000E 0000 ;Decrementato se la lettura è andata bene (settori da leggere) O5
00000010 00000000 ;Incrementato se la lettura è andata bene (Offset lettura rispetto partizione) O6
00000014 00 ;Viene impostato durante il processo di boot - Se questo byte è 0 = non LBA se è 1 LBA OK
00000015 F8 ;Media descriptor
;Byte Capacity Media Size and Type
;F0 2.88 MB 3.5-inch, 2-sided, 36-sector
;F0 1.44 MB 3.5-inch, 2-sided, 18-sector
;F9 720 KB 3.5-inch, 2-sided, 9-sector
;F9 1.2 MB 5.25-inch, 2-sided, 15-sector
;FD 360 KB 5.25-inch, 2-sided, 9-sector
;FF 320 KB 5.25-inch, 2-sided, 8-sector
;FC 180 KB 5.25-inch, 1-sided, 9-sector
;FE 160 KB 5.25-inch, 1-sided, 8-sector
;F8 ----- Fixed disk
00000016 0000
00000018 3F00 ;N° settori per tracia (3Fh=63)
0000001A FF00 ;N° testine (FFH=255)
0000001C 3F000000 ;Inizio partizione (=n° settori nascosti)
00000020 00000000 ;Viene impostato durante il processo di boot - DWord che rappresenta la capacità massima del disco
;in settori
00000024 80 ;Numero drive fisico - Usato per identificare il drive nelle chimate di interrupt (00 per un floppy)
00000025 00 //Testina corrente (indica la testina dove si trova il record di boot, di fatto viene usato da windows
//come flag per autochk deve eseguire chkdsk all'avvio(bit inferiore), e per indicare se deve essere
//eseguita una scansione superficiale (secondo bit più basso)
00000026 80 //
00000027 00 //
00000028 C04BA11200000000 ;N° totale settori (12A14BC0h = 312560576 settori = 160031014912 byte = 160GB
00000030 00000C0000000000 ;N° cluster inizio MFT - variabile usata nella terza fase O3
00000038 BC142A0100000000 ;N° cluster inizio MFTmirr
00000040 F6000000 ;N° cluster per file record segment - variabile usata nella terza fase O4
00000044 01000000 ;N° cluster per Indexblock
00000048 AFB290E0D390E05E ;Volume serial number
00000050 00000000 ;Checksum

Inizio codice

00000054 FA cli               ;Disabilita gli interrupt
00000055 33C0 xor ax,ax ;Azzera AX
00000057 8ED0 mov ss,ax ;Azzera SS (Stak segment)
00000059 BC007C mov sp,0x7c00 ;SP = 7C00h (Lo stack pointer punta all'inizio del codice)
0000005C FB sti ;Abilita gli interrupt
0000005D B8C007 mov ax,0x7c0
00000060 8ED8 mov ds,ax ;DS=AX=7C0h In questo modo l'indirizzamento in memoria sarà del tipo 07C0:0000
;Che è del tutto equivalente a 0000:7C00, in questo modo gli indirizzi assoluti
;coincideranno con gli indirizzi locali del blocco di codice

00000062 E81600 call word 0x7b ;Procedura di controllo disco per il calcolo dei settori totali ->7Bh
00000065 B8000D mov ax,0xd00 ;AX = D00h
00000068 8EC0 mov es,ax ;ES = D00h (extra segment)
0000006A 33DB xor bx,bx ;Azzera BX
0000006C C6060E0010 mov byte [0xe],0x10 ;inserisce il valore 10h in una variabile all'indirizzo 000Eh (contatore settori da leggere)
00000071 E85300 call word 0xc7 ;Procedura di lettura da disco e copia dati in memoria -> C7h
00000074 68000D push word 0xd00 ;Inserisce l'indirizzo a cui passare in seguito
00000077 686A02 push word 0x26a ; 0D00:026A
0000007A CB retf ;Passa il controllo del codice all'indirizzo 0D00:026Ah (Far return sovrascrive CS:IP non solo IP)

Per calcolare il numero massimo di settori sul disco viene usata una funzione di interrupt INT 13 con AH = 8 , in questo modo vengono calcolati i settori contenuti nel disco ma con la limitazione di 8GB nel caso di dischi più grandi infatti verrà comunque impostato il valore massimo di 8GB, questo servirà per detterminare il tipo di lettura infatti se la partizione inizierà prima degli 8GB verrà utulizzata una lettura con le coordinate CHS altrimenti verrà utilizzata la modalita LBA.

Funzione di controllo disco:

0000007B 8A162400 mov dl,[0x24] ;DL=[24h]=80 (7h bit = 1 => hard disc)
0000007F B408 mov ah,0x8 ;AH=8
00000081 CD13 int 0x13 ;Invia la richiesta parametri del disco
00000083 7305 jnc 0x8a ;Se tutto è andato bene va ad -> 8Ah per il controllo geometria
00000085 B9FFFF mov cx,0xffff ;Altrimenti imposta al massimo il numero di settori (3Fh=63) e cilindri(3FFh=1023+1) => CX=FFFFh
00000088 8AF1 mov dh,cl ;e massimo di testine => DH=FFh (255+1)

Controllo geometria disco dopo la richiesta parametri:

0000008A 660FB6C6 movzx eax,dh   ;Carica in AX il numero massimo di testine
0000008E 40 inc ax ;Incrementa il numero massimo di testine di 1 (dato che il numero precedente è un indice e quindi partendo da zero per avere il numero bisogna sommare 1)
0000008F 660FB6D1 movzx edx,cl ;carica in EDX il massimo numero di settori
00000093 80E23F and dl,0x3f ;Del valore precedente seleziona solo i primi 6 bit
00000096 F7E2 mul dx ;moltiplica il numero di settori per le testine e lo inserisce in DX:AX = DX*AX
00000098 86CD xchg cl,ch ;Scambia il contenuto dei registri CL e CH
0000009A C0ED06 shr ch,0x6 ;Traslazione degli ultimi 2 bit del vecchio CL in modo che CH+CL ora dia il numero di cilindri
0000009D 41 inc cx ;Aumenta di uno il massimo numero di cilindri per avere il numero esatto (indice partiva da 0)
0000009E 660FB7C9 movzx ecx,cx
000000A2 66F7E1 mul ecx ;moltiplica il num di cilindri per il risultato della precedente moltiplicazione e lo inserisce in EDX:EAX
000000A5 66A32000 mov [0x20],eax ;Il risultato sarà la capacità massima del disco in termini di settori e verrà conservata all'indirizzo 20h (BPB area)
;nel caso di valori al max la capacità sarà : FC0000h = 16.515.072 settori = 8.455.716.864 byte
000000A9 C3 ret ;Fine controllo disco e ritorno all'indirizzo ->65h

Verifica supporto LBA:

000000AA B441 mov ah,0x41         ;Prepara i parametri per la chiamata di interrupt INT 13 (AH=41 BX=55AA DL=80)
000000AC BBAA55 mov bx,0x55aa
000000AF 8A162400 mov dl,[0x24]
000000B3 CD13 int 0x13 ;Verifica supporto LBA
000000B5 720F jc 0xc6 ;Se si verifica un problema vai a C6
000000B7 81FB55AA cmp bx,0xaa55 ;Verifica se il supporto esiste
000000BB 7509 jnz 0xc6 ;Se non esiste vai a C6
000000BD F6C101 test cl,0x1 ;Se invce il supporto esiste verifica che si possano usare le funzioni esese di accesso al disco (CL = 0)
000000C0 7404 jz 0xc6 ;Se le funzioni estese non possono essere usate va a C6
000000C2 FE061400 inc byte [0x14] ;altrimenti incrementa il byte all'indirizzo 14h
000000C6 C3 ret ;fine vefifica LBA

Lettura dati da disco e copia in memoria (ricordarsi che ES:BX è l'indirizzo di di destinazione ed EAX è la posizione del settore iniziale)

000000C7 6660 pushad               ;Inserisce nello stack i registri EAX(D00h), ECX, EDX, EBX(0), EBP, ESP(7C00h), EBP, ESI e EDI
000000C9 1E push ds ;Inserisce nello stack DS = 7C0h
000000CA 06 push es ;Inserisce nello stack ES = D00h
(J->158h) Preparazione parametri per la lettura
000000CB 66A11000 mov eax,[0x10] ;EAX = [10h] (è una variabile usata come offset lettura, inizialmente = 0)
000000CF 6603061C00 add eax,[0x1c] ;[1Ch]=3Fh=inizio partizione => EAX = 3Fh + O6 (offset lett.)
000000D4 663B062000 cmp eax,[0x20] ; confronta EAX( inizialmente=3Fh) con [20h]=capacità disco
000000D9 0F823A00 jc word 0x117 ;Se l'inizio della settore è inferiore della capacità va a -> 117h (lettura normale disco)
000000DD 1E push ds ;Altrimenti proverà a leggere in LBA; inserisce nello stack DS = 7C0h
000000DE 666A00 push dword 0x0 ;Inserisce nello 00000000h stack
000000E1 6650 push eax ;Inserisce nello stack EAX = 0000003Fh (+ offset sett.)
000000E3 06 push es ;Inserisce nello stack ES = 0D00h (+ 20h*offset sett.)
000000E4 53 push bx ;Inserisce nello stack BX = 0000h
000000E5 666810000100 push dword 0x10010 ;Inserisce nello stack 00010010h
000000EB 803E140000 cmp byte [0x14],0x0 ;Verifica che LBA sia supportato
000000F0 0F850C00 jnz word 0x100 ;Se LBA è supportato vai a -> 100h (lettura con LBA)
000000F4 E8B3FF call word 0xaa ;Altrimenti esegui verifica LBA ->AAh
000000F7 803E140000 cmp byte [0x14],0x0 ;Ricontrolla il supporto LBA
000000FC 0F846100 jz word 0x161 ;Se non è supportato vai a 161h (Errore di lettura disco)

Lettura disco con LBA

00000100 B442 mov ah,0x42       ;imposta i parametri per la chiamata di interrupt 
00000102 8A162400 mov dl,[0x24] ;[24h]=80h numero drive
00000106 16 push ss ;Inserisce nello stack SS = 0000h
00000107 1F pop ds ;Imposta DS = 0
00000108 8BF4 mov si,sp ; SI = SP (= forse 7C3Ah) (a causa dei push precedenti)
0000010A CD13 int 0x13 ;Chiama la routine di interrupt 13 (AH 42h) che legge i settori del disco in modalità LBA
;I parametri per la lettura li prende dai dati all'indirizzo DS:SI che è lo stack :
; 10 | 00 | 01 00 | 00 00 00 0D | 3F 00 00 00 00 00 00 00
; 10h 1 0D00(+ 20h*offset):0000 3Fh (+ sett.letti)
; Dim.Pack Riserv. Num. blocchi Destinazione Indirizzo blocco di partenza(CHS)
; 3Fh=(63*512)= 7E00h bytes
0000010C 6658 pop eax
0000010E 5B pop bx ;BX=0
0000010F 07 pop es ;ES = 0D00h (+ 20h*offset sett.)
00000110 6658 pop eax
00000112 6658 pop eax ;EAX=0
00000114 1F pop ds ;DS = 7C0h
00000115 EB2D jmp short 0x144 ;Verifica lettura -> 144h

Lettura normale del disco, ma per questo prima si dovrà ricavare le coordinate CHS del settore da leggere partendo dalla posizione assoluta della partizione:

00000117 6633D2 xor edx,edx
0000011A 660FB70E1800 movzx ecx,word [0x18] ;ECX = 3Fh posizione assoluta in termini di settore della partizione da leggere
;ricordare che EAX = 0000003Fh (+ offset sett.)
00000120 66F7F1 div ecx ;divide DX:AX(3Fh)/ECX(3Fh) e il risultato in AX(1) e il resto in DX(0 o sett.letti)
00000123 FEC2 inc dl ;Incrementa DL => DL = 1
00000125 8ACA mov cl,dl ;CL=DL=1 (=settori letti +1=>sett da leggere)
00000127 668BD0 mov edx,eax ;EDX=1
0000012A 66C1EA10 shr edx,0x10 ;EDX=0 (questa operazione dara risultato sempre zero fino a che EDX<10000h=65536)
0000012E F7361A00 div word [0x1a] ;divide DX:AX(1)/n°max testine(FFh) e il risultato in AX(0) e il resto in DX(1)
00000132 86D6 xchg dl,dh ;DH = 1 indice head
00000134 8A162400 mov dl,[0x24] ;DL = 80h indica il primo hard disk
00000138 8AE8 mov ch,al ;CH = 0 primo cilindro
0000013A C0E406 shl ah,0x6 ;AH = 0->0
0000013D 0ACC or cl,ah ;CL = 1 indice settore
0000013F B80102 mov ax,0x201 ;AX = 201h -> AH=02 AL=01 (n° settori da leggere)
00000142 CD13 int 0x13 ;Chiamata di interrupt INT 13 (AH=02) legge i dati dal disco e li copia in memoria
;Verifichiamo se le coordinate CHS coincidono con quella LBA, che ci da la pasizione assoluta del settore
; LBA = (Cylinder*NumHeads + SelectedHead) * SectorPerTrack + SelectedSector - 1
= ( 0 * FFh + 1 ) * 3Fh + 1 - 1 = 3Fh
( J->115h)
00000144 0F821900 jc word 0x161 ;Verifica se la lettura ha dato errori se si va a -> 161h ("Errore lettura da disco")
;Altrimenti prosegui
00000148 8CC0 mov ax,es ;AX=D00h
0000014A 052000 add ax,0x20 ;AX=D20h
0000014D 8EC0 mov es,ax ;ES=D20h (Incrementare l'indirizzo di segmento di 20h equivale a incrementare l'offset di 200h = 512 byte)
0000014F 66FF061000 inc dword [0x10] ;incrementa il contatore settori letti = offset dei settori in lettura (O6)
00000154 FF0E0E00 dec word [0xe] ;decrementa il numero settori da leggere (inizialmente erano 16) (O5)
00000158 0F856FFF jnz word 0xcb ;ripete lettura fino ad azzerare il contatore ->CBh
0000015C 07 pop es ;Ripristina il registro ES = D00h
0000015D 1F pop ds ;Ripristina il registro DS = 7C0h
0000015E 6661 popad ;Ripristina tutti i registri
00000160 C3 ret ;Ritorna -> 74h (fine lettura)

Fallita lettura LBA

00000161 A0F801 mov al,[0x1f8]  ;Inizia la procedura di stampa della stringa "Errore lettura da disco" 
00000164 E80900 call word 0x170 ;Stampa
00000167 A0FB01 mov al,[0x1fb] ;Inizia la procedura di stampa della stringa "Premere CTRL+ALT+CANC per riavviare"
0000016A E80300 call word 0x170 ;Stampa
0000016D FB sti ;Abilita interrupt
0000016E EBFE jmp short 0x16e ;Inizia un loop infinito in attesa di un interrupt (CTRL+ALT+CANC)

Procedura di stampa

00000170 B401 mov ah,0x1       ;Inserisce in AH il valore 1 in questo modo -AX sarà nella forma 1?? dove la parte mancante è contenuta in AL.
;AX contiene l'indirizzo del primo carattere della striga
00000172 8BF0 mov si,ax ;SI ora punta all'inizio stringa
00000174 AC lodsb ;Carica il carattere puntato da SI in AL
00000175 3C00 cmp al,0x0 ;Verifica che la stringa sia finita
00000177 7409 jz 0x182 ;Se è finita va a 182h
00000179 B40E mov ah,0xe ;Prepara i parametri per la stampa a video
0000017B BB0700 mov bx,0x7 ;
0000017E CD10 int 0x10 ;Interrupt INT 10 (AH=0Eh BX=07) stampa carattere contenuto in AL a video
00000180 EBF2 jmp short 0x174 ;Ripete la stampa fino a che la stringa è finita
00000182 C3 ret

Stringhe

00000183 0D0A4572726F7265 "Errore lettura da disco"
206C657474757261
2064612064697363
6F00
0000019D 0D0A4E544C445220 "NTLDR mancante"
6D616E63616E7465
00
000001AE 0D0A4E544C445220 "NTLDR compresso"
636F6D7072657373
6F00
000001C0 0D0A5072656D6572 "Premere CTRL+ALT+CANC per riavviare"
65204354524C2B41
4C542B43414E4320
7065722072696176
76696172650D0A00
000001E8 0D0A00 Ritorno a capo
000001EB 00
...
000001F7 00
000001F8 83 ;Indirizzo parziale (1+83) stringa: "Errore lettura da disco"
000001F9 9D ;Indirizzo parziale (1+9D) stringa: "NTLDR mancante"
000001FA AE ;Indirizzo parziale (1+AE) stringa: "NTLDR compresso"
000001FB C0 ;Indirizzo parziale (1+C0) stringa: "Premere CTRL+ALT+CANC per riavviare"
000001FC 0000
000001FE 55AA ;Partition Boot sector end signature


Ultimo aggiornamento ( Martedì 31 Maggio 2016 16:22 )  
Loading

Login