| Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente |
| la_partie_executable_du_mbr [Le 07/09/2016, 10:00] – [Exemple de zone exécutable d'un mbr] Nasman | la_partie_executable_du_mbr [Le 20/12/2021, 19:22] (Version actuelle) – passage de http à https sur les liens externes (détecté et corrigé via le bot wiki-corrector (https://forum.ubuntu-fr.org/viewtopic.php?id=2067892) wiki-corrector-bot |
|---|
| | |
| . | . |
| {{tag> tutoriel mbr BROUILLON}} | {{tag> tutoriel mbr BROUILLON}} |
| ====== Que trouve-t-on comme programme dans le mbr ====== | ====== Que trouve-t-on comme programme dans le mbr ====== |
| |
| Si vous êtes arrivés sur cette page par erreur, faites demi tour sans tarder car ici se trouve l'antre de la bête :-( - et il ne faut pas connaitre la peur car vous allez découvrir les entrailles de votre machine. 8-o | Si vous êtes arrivés sur cette page par erreur, faites demi tour sans tarder car ici se trouve l'antre de la bête :-( - où il ne faut pas connaître la peur car vous allez découvrir les entrailles de votre machine. 8-o |
| \\ | \\ |
| Le mbr est le premier secteur du disque chargé en mémoire lors du démarrage d'un ordinateur. Il a pour fonction principale de rechercher une partition où se trouve un système d'exploitation à lancer. | Le mbr est le premier secteur du disque chargé en mémoire lors du démarrage d'un ordinateur. Il a pour fonction principale de rechercher une partition où se trouve un système d'exploitation à lancer. |
| \\ | \\ |
| Une fois le chargement terminé et sans erreur, l'exécution se poursuit à l'adresse 0000:7C00, et donc suit les instructions qui figurent dans le premier secteur du mbr | Une fois le chargement terminé et sans erreur, l'exécution se poursuit à l'adresse 0000:7C00, et donc suit les instructions qui figurent dans le premier secteur du mbr |
| | \\ |
| | <note tip>Lors d'un démarrage en mode UEFI avec un disque GPT, le mbr (protector) ne semble quasiment pas utilisé et seul l'emplacement de l'en-tête GPT est nécessaire (unique entrée de la table des partitions du mbr protector)</note> |
| ===== Comment accéder à ces informations ===== | ===== Comment accéder à ces informations ===== |
| |
| J'ai effectué une analyse (partielle) du fonctionnement des différents morceaux mais des parties restent encore nébuleuses. | J'ai effectué une analyse (partielle) du fonctionnement des différents morceaux mais des parties restent encore nébuleuses. |
| \\ | \\ |
| Le programme utilise des fonctions du bios (seules fonctions disponible à ce stade du démarrage du PC) et je me suis servi de la liste des [[http://www.ctyme.com/intr/int.htm|interruptions]] | Le programme utilise des fonctions du bios (seules fonctions disponibles à ce stade du démarrage du PC) et je me suis servi de la liste des [[http://www.ctyme.com/intr/int.htm|interruptions]] |
| établies par Ralph Brown. | établies par Ralph Brown. |
| \\ | \\ |
| Voilà donc à quoi ressemble la chose. | Voilà donc à quoi ressemble la chose. |
| \\ | \\ |
| <code>; Programme chargé en 0000:7C00 | <code>; Programme 16 bits chargé en 0000:7C00 |
| 00000000 EB63 jmp short 0x65 | 00000000 EB63 jmp short 0x65 |
| 00000002 90 nop | 00000002 90 nop |
| 00000003 D0 | 00000003 D0 |
| | 00000004 resb 1 ; mode : 0x00 pour le mode CHS, 0x01 pour le mode LBA |
| |
| ; Buffer pour disque dur | ; Buffer pour chargement en mode CHS |
| 00000004 resb 1 ; 0x00 | |
| 00000005 resd 1 ; nombre de secteurs | 00000005 resd 1 ; nombre de secteurs |
| 00000009 resd 1 ; nombre de têtes | 00000009 resd 1 ; nombre de têtes |
| 0000000D resd 1 ; nombre de cylindres | 0000000D resd 1 ; nombre de cylindres |
| |
| ; Buffer pour extension | ; Buffer pour chargement en mode LBA |
| (00000004 resb 1 ; 0x01) | 00000005 resw 1 ; 0x0010 - taille paquet |
| (00000005 resw 1 ; 0x0010 - taille paquet) | 00000007 resw 1 ; 0x0001 - nb blocs à transférer |
| (00000007 resw 1 ; 0x0001 - nb block à transférer) | 00000009 resw 1 ; 0x0000 |
| (00000009 resw 1 ; 0x0000) | 0000000B resw 1 ; 0x7000 - buffer en 0x70000000 |
| (0000000B resw 1 ; 0x7000 - buffer en 0x70000000) | 0000000D resd 1 ; 0x00000001 - emplacement LBA du bloc à charger |
| (0000000D resd 1 ; 0x00000001) | 00000011 resd 1 ; 0x00000000 - démarrer au bloc 0x0000000000000001 |
| (00000011 resd 1 ; 0x00000000 - démarrer au bloc 0x0000000000000001) | |
| |
| 00000004 BC007C mov sp,0x7c00 | |
| 00000007 8EC0 mov es,ax | |
| 00000009 8ED8 mov ds,ax | |
| 0000000B BE007C mov si,0x7c00 | |
| 0000000E BF0006 mov di,0x600 | |
| 00000011 B90002 mov cx,0x200 | |
| 00000014 FC cld | |
| 00000015 F3A4 rep movsb ; copie le secteur de 7C00-7DFF en 600-7FF | |
| 00000017 50 push ax | |
| 00000018 681C06 push word 0x61c | |
| 0000001B CB retf ; saute en 61c (contenu ci dessous) | |
| |
| 0000001C FB sti | 0000005A 0080 dw 0x8000 ; Emplacement de l'offset où le contenu du tampon sera copié |
| 0000001D B90400 mov cx,0x4 | 0000005C 01000000 dd 0x00000001 ; Adresse LBA (valeur basse) où se trouve le secteur suivant de chargement (core.img) |
| 00000020 BDBE07 mov bp,0x7be ; pointe sur le début de la table des partitions | 00000060 00000000 dd 0x00000000 ; Valeur haute du qword de l'adresse LBA |
| | 00000064 FF db 0xff ; 0xff pour le chargement de core.img sur le disque de boot, si 0x80 premier disque dur, si 0x81 deuxième... |
| 00000023 807E0000 cmp byte [bp+0x0],0x0 | |
| 00000027 7C0B jl 0x34 ; teste si marqueur "boot" | |
| 00000029 0F851001 jnz word 0x13d ; ni boot ni zéro | |
| 0000002D 83C510 add bp,byte +0x10 ; pointe sur partition suivante | |
| 00000030 E2F1 loop 0x23 ; 4 boucles pour 4 partitions | |
| 00000032 CD18 int 0x18 ; appelé si pas de partition de boot | |
| 00000034 885600 mov [bp+0x0],dl | |
| 00000037 55 push bp ; sauvegarde adresse (partition de boot) | |
| 00000038 C6461105 mov byte [bp+0x11],0x5 | |
| 0000003C C6461000 mov byte [bp+0x10],0x0 | |
| 00000040 B441 mov ah,0x41 | |
| 00000042 BBAA55 mov bx,0x55aa | |
| 00000045 CD13 int 0x13 ; installation check | |
| 00000047 5D pop bp | |
| 00000048 720F jc 0x59 ; extension non supportée | |
| 0000004A 81FB55AA cmp bx,0xaa55 ; | |
| 0000004E 7509 jnz 0x59 ; extension non installée | |
| 00000050 F7C10100 test cx,0x1 | |
| 00000054 7403 jz 0x59 ; fonctions 42h-44h, 47h et 48h non supportées | |
| 00000056 FE4610 inc byte [bp+0x10] | |
| 00000059 66 | |
| 0000005A 0080 | |
| 0000005C 01000000 dd 0x00000001 ; Adresse LBA où se trouve le secteur suivant de chargement (core.img) | |
| 00000060 00000000 dd 0x00000000 ; | |
| 00000064 FF db 0xff | |
| |
| 00000065 FA cli | 00000065 FA cli |
| 00000081 3CFF cmp al,0xff | 00000081 3CFF cmp al,0xff |
| 00000083 7402 jz 0x87 | 00000083 7402 jz 0x87 |
| 00000085 88C2 mov dl,al ; si non égal à 0xff, sauvegardé dans dl | 00000085 88C2 mov dl,al ; si non égal à 0xff, sauvegardé dans dl - si core.img est sur un autre disque |
| 00000087 52 push dx | 00000087 52 push dx |
| 00000088 BB1704 mov bx,0x417 | 00000088 BB1704 mov bx,0x417 ; adresse clavier |
| 0000008B 802703 and byte [bx],0x3 | 0000008B 802703 and byte [bx],0x3 ; teste si une touche shift est activée |
| 0000008E 7406 jz 0x96 | 0000008E 7406 jz 0x96 |
| 00000090 BE887D mov si,0x7d88 ; pointe sur la chaine "GRUB" | 00000090 BE887D mov si,0x7d88 ; pointe sur la chaine "GRUB" |
| 00000093 E81C01 call word 0x1b2 | 00000093 E81C01 call word 0x1b2 |
| |
| 00000096 BE057C mov si,0x7c05 ; définit une zone tampon | 00000096 BE057C mov si,0x7c05 ; définit une zone tampon pour les paramètres de chargement |
| 00000099 F6C280 test dl,0x80 ; teste si disque dur | 00000099 F6C280 test dl,0x80 ; teste si disque dur |
| 0000009C 7448 jz 0xe6 ; pas disque dur | 0000009C 7448 jz 0xe6 ; pas disque dur |
| 000000AD 7537 jnz 0xe6 ; extension non installée | 000000AD 7537 jnz 0xe6 ; extension non installée |
| |
| ; traitement extension | |
| 000000AF 83E101 and cx,byte +0x1 | 000000AF 83E101 and cx,byte +0x1 |
| 000000B2 7432 jz 0xe6 ; fonctions 42h-44h, 47h et 48h non supportées | 000000B2 7432 jz 0xe6 ; fonctions 42h-44h, 47h et 48h non supportées |
| 000000B4 31C0 xor ax,ax | |
| | ; traitement extension lba_mode |
| | 000000B4 31C0 xor ax,ax |
| 000000B6 894404 mov [si+0x4],ax ; met zéro en 7c09 et 7c0a | 000000B6 894404 mov [si+0x4],ax ; met zéro en 7c09 et 7c0a |
| 000000B9 40 inc ax | 000000B9 40 inc ax |
| 000000BA 8844FF mov [si-0x1],al ; met 1 en 7c04 | 000000BA 8844FF mov [si-0x1],al ; met 1 en 7c04 (1=lba_mode) |
| 000000BD 894402 mov [si+0x2],ax ; met 0001 en 7c07 | 000000BD 894402 mov [si+0x2],ax ; met 0x0001 en 7c07 |
| 000000C0 C7041000 mov word [si],0x10 ; met 0x0010 en 7c05 | 000000C0 C7041000 mov word [si],0x10 ; met 0x0010 en 7c05 |
| 000000C4 668B1E5C7C mov ebx,[0x7c5c] | 000000C4 668B1E5C7C mov ebx,[0x7c5c] ; récupère l'emplacement (partie basse du qword) de core.img |
| 000000C9 66895C08 mov [si+0x8],ebx | 000000C9 66895C08 mov [si+0x8],ebx ; sauvegarde cet emplacement pour le charger |
| 000000CD 668B1E607C mov ebx,[0x7c60] | 000000CD 668B1E607C mov ebx,[0x7c60] ; récupère la partie haute du qword de core.img |
| 000000D2 66895C0C mov [si+0xc],ebx | 000000D2 66895C0C mov [si+0xc],ebx ; sauvegarde |
| 000000D6 C744060070 mov word [si+0x6],0x7000 | 000000D6 C744060070 mov word [si+0x6],0x7000 ; adresse de segment du tampon |
| 000000DB B442 mov ah,0x42 | 000000DB B442 mov ah,0x42 |
| 000000DD CD13 int 0x13 ; fonction extended read | 000000DD CD13 int 0x13 ; fonction extended read |
| 000000E4 EB76 jmp short 0x15c | 000000E4 EB76 jmp short 0x15c |
| |
| ; traitement sans extension | ; traitement sans extension chs_mode |
| 000000E6 B408 mov ah,0x8 | 000000E6 B408 mov ah,0x8 |
| 000000E8 CD13 int 0x13 ; récupère les paramètres du disque | 000000E8 CD13 int 0x13 ; récupère les paramètres du disque (numéro maxi tête, numéro maxi secteur, numéro maxi cylindre) |
| 000000EA 730D jnc 0xf9 ; si pas d'erreur | 000000EA 730D jnc 0xf9 ; si pas d'erreur |
| 000000EC F6C280 test dl,0x80 | 000000EC F6C280 test dl,0x80 |
| 000000F6 E98200 jmp word 0x17b | 000000F6 E98200 jmp word 0x17b |
| |
| ; Disque dur OK | |
| 000000F9 660FB6C6 movzx eax,dh ; numéro maxi de têtes | 000000F9 660FB6C6 movzx eax,dh ; numéro maxi de têtes |
| 000000FD 8864FF mov [si-0x1],ah ; met zéro en 7c04 | 000000FD 8864FF mov [si-0x1],ah ; met zéro en 7c04 |
| 0000011C 66A1607C mov eax,[0x7c60] | 0000011C 66A1607C mov eax,[0x7c60] |
| 00000120 6609C0 or eax,eax ; teste si zéro | 00000120 6609C0 or eax,eax ; teste si zéro |
| 00000123 754E jnz 0x173 | 00000123 754E jnz 0x173 ; erreur de géométrie |
| |
| ; Convertit adresse linéaire en tête, secteur et cylindre | ; Convertit adresse linéaire en tête, secteur et cylindre |
| 00000125 66A15C7C mov eax,[0x7c5c] ; charge l'adresse LBA de l'emplacement de core.img | 00000125 66A15C7C mov eax,[0x7c5c] ; charge l'adresse LBA de l'emplacement de core.img (valeur basse qword) |
| 00000129 6631D2 xor edx,edx ; met à zéro | 00000129 6631D2 xor edx,edx ; met à zéro |
| 0000012C 66F734 div dword [si] ; division numéro secteur/nb secteurs par piste | 0000012C 66F734 div dword [si] ; divise l'adresse LBA par le nombre de secteurs par piste |
| 0000012F 88D1 mov cl,dl ; reste de la division=numéro secteur | 0000012F 88D1 mov cl,dl ; reste de la division = numéro secteur (commencement à 0) |
| 00000131 31D2 xor dx,dx | 00000131 31D2 xor dx,dx |
| 00000133 66F77404 div dword [si+0x4] ; divise par le nombre de têtes - donne un nb de cylindres | 00000133 66F77404 div dword [si+0x4] ; divise par le nombre de têtes - donne un nb de cylindres |
| 00000137 3B4408 cmp ax,[si+0x8] | 00000137 3B4408 cmp ax,[si+0x8] ; compare au nombre de cylindres du disque |
| 0000013A 7D37 jnl 0x173 ; supérieur au nombre de cylindres du disque - erreur | 0000013A 7D37 jnl 0x173 ; supérieur au nombre de cylindres du disque - erreur |
| 0000013C FEC1 inc cl ; rajoute 1 car les n°secteurs commencent à 1 | 0000013C FEC1 inc cl ; rajoute 1 car les n°secteurs commencent à 1 |
| 0000015A 8CC3 mov bx,es | 0000015A 8CC3 mov bx,es |
| |
| | ; Copie des données chargées (partie commune mode CHS ou LBA) |
| 0000015C 60 pushaw | 0000015C 60 pushaw |
| 0000015D 1E push ds | 0000015D 1E push ds |
| 0000015E B90001 mov cx,0x100 | 0000015E B90001 mov cx,0x100 |
| 00000161 8EDB mov ds,bx ; charge le segment du buffer | 00000161 8EDB mov ds,bx ; charge le segment du buffer |
| 00000163 31F6 xor si,si ; ds:di pointe sur 7000:0000 | 00000163 31F6 xor si,si ; ds:si pointe sur 7000:0000 |
| 00000165 BF0080 mov di,0x8000 | 00000165 BF0080 mov di,0x8000 |
| 00000168 8EC6 mov es,si ; es:di pointe sur 0000:8000 | 00000168 8EC6 mov es,si ; es:di pointe sur 0000:8000 |
| 0000016D 1F pop ds | 0000016D 1F pop ds |
| 0000016E 61 popaw | 0000016E 61 popaw |
| 0000016F FF265A7C jmp word near [0x7c5a]; saute en 0000:8000 (car 7c5a contient 8000) | 0000016F FF265A7C jmp word near [0x7c5a]; saute en 0000:8000 (car 7c5a contient 8000) - début de core.img |
| |
| |
| 00000186 EBFE jmp short 0x186 ; boucle sans fin | 00000186 EBFE jmp short 0x186 ; boucle sans fin |
| |
| ; Chaines messages d'erreur | ; Chaînes messages d'erreur |
| 00000188 db "GRUB ",0 | 00000188 db "GRUB ",0 |
| 0000018E db "Geom",0 | 0000018E db "Geom",0 |
| 000001B7 C3 ret</code> | 000001B7 C3 ret</code> |
| \\ | \\ |
| La partie qui commence à l'adresse hexa 65 est commune avec le fichier boot.img qui se trouve dans /boot/grub/ | <note tip>L'emplacement de la LBA où se trouve core.img est indiquée en 5c (8 octets). |
| | \\ |
| | Ici nous avons la LBA qui vaut 1, soit le secteur qui suit le mbr. Dans le cas d'un partitionnement GPT cet emplacement est occupé par l'en-tête GPT et n'est plus disponible pour core.img. Il faudra donc mettre l'adresse LBA de la partition bios_boot pour le boot en mode bios sur un disque GPT</note> |
| | \\ |
| | Le programme chargé en mémoire à l'adresse 0000:7c00 commence par l'instruction jmp short 0x65 qui saute directement à l'adresse 065 |
| | \\ |
| | \\ |
| | Différentes parties sont visibles : |
| \\ | \\ |
| Le programme chargé en mémoire à l'adresse 0000:7c00 commence par l'instruction jmp short 0x65 qui saute directement dans la partie commune à boot.img | |
| \\ | \\ |
| | de 065 à 095 - Routine vérifie que le boot s'effectue à partir du disque dur |
| \\ | \\ |
| Différentes parties sont visibles | de 096 à 0b3 - Définit l'emplacement des paramètres de chargement du prochain secteur et le mode CHS ou LBA selon les capacités du bios |
| de 004 à 01b - Routine qui recopie à une autre adresse le contenu du mbr - peut être en prévision du chargement d'un autre secteur. | |
| \\ | \\ |
| de 01c à 037 - Détermine la partition de boot | de 0b4 à 0e5 - Charge le premier secteur de core.img en mode LBA (interruption bios int13/ah=42h) |
| \\ | \\ |
| de 038 à 059 - Détermine si le bios reconnait le système d'adressage LBA | de 0e6 à 0f8 - Récupère les paramètres du disque et gère les erreurs |
| \\ | \\ |
| de 05c à 05f - Adresse LBA de core.img | de 0f9 à 124 - Sauvegarde ces paramètres dans la zone des paramètres de chargement |
| \\ | \\ |
| de 125 à 14a - Calcule les valeurs HSC à partir de la LBA | de 125 à 15b - Convertit l'adresse LBA de core.img dans le mode CHS et charge ce secteur dans le tampon (interruption bios int13/ah=02h) |
| \\ | \\ |
| de 14c à 158 - Charge un secteur | de 15c à 172 - Recopie le secteur chargé à son nouvel emplacement et saute à cet emplacement (première partie de core.img, soit diskboot.img) |
| \\ | \\ |
| de 173 à 186 - Gestion des erreurs | de 173 à 187 - Affichage des messages d'erreur |
| \\ | \\ |
| de 1ab à 1b0 - Affichage de caractères | de 1ab à 1b0 - Affichage de caractères |
| \\ | \\ |
| de 1b2 à 1b7 - Affichage des chaines des messages d'erreurs | de 1b2 à 1b7 - Affichage des chaînes des messages d'erreurs |
| \\ | \\ |
| ===== Voir aussi ===== | ===== Voir aussi ===== |
| \\ | \\ |
| | |
| * **(fr)** [[http://fr.wikipedia.org/wiki/Master_boot_record]] | * **(fr)** [[https://fr.wikipedia.org/wiki/Master_boot_record]] |
| * **(fr)**[[http://fr.wikipedia.org/wiki/Partition_de_disque_dur]] | * **(fr)**[[https://fr.wikipedia.org/wiki/Partition_de_disque_dur]] |
| * [[http://forum.ubuntu-fr.org/viewtopic.php?id=390336]] sur le forum ubuntu-fr | * [[https://forum.ubuntu-fr.org/viewtopic.php?id=390336]] sur le forum ubuntu-fr |
| * **(fr)**[[http://fr.wikipedia.org/wiki/Logical_block_addressing]] | * **(fr)**[[https://fr.wikipedia.org/wiki/Logical_block_addressing]] |
| |
| |