Le gestionnaire IDE a cinq sources d'information concernant la géométrie. La première (G_user) est celle donnée par l'utilisateur sur la ligne de commande. La deuxième (G_bios) est la 'BIOS Fixed Disk Parameter Table' -- table des paramètres de disque fixe du BIOS -- (pour le premier et second disque dur seulement) qui est lue au démarrage du système, avant le passage au mode 32 bits. Les troisième (G_phys) et quatrième (G_log) sont données par le contrôleur IDE en réponse à la commande IDENTIFY -- ce sont les géométries 'physique' et 'logique du moment'.
D'un autre côté, le gestionnaire a besoin de deux valeurs pour la
géométrie : d'abord G_fdisk, donnée par un ioctl HDIO_GETGEO
et
ensuite G_used, qui est effectivement utilisée pour les Éntrées/Sorties. G_fdisk
et G_used sont toutes deux initialisées avec la valeur de G_user si elle est
fournie, avec G_bios quand le CMOS dit que cette valeur est présente et avec
G_phys autrement. Si G_log semble vraisemblable, alors G_used est positionnée à
cette valeur. Sinon, si G_used n'est pas vraisemblable et que G_phys semble
l'être, alors G_used prend la valeur de G_phys. Ici, 'vraisemblable' signifie
que le nombre de têtes est compris dans l'intervalle 1-16.
En d'autres termes : la ligne de commande prend le pas sur le BIOS et va
déterminer ce que va voir fdisk
, mais si elle donne une géométrie
convertie (avec plus de 16 têtes), alors pour les Éntrées/Sorties qu'effectuera
le noyau elle sera elle-même remplacée par les valeurs que fournira la commande
IDENTIFY.
Remarquez que G_bios est assez peu fiable : pour des systèmes qui démarrent depuis un périphérique SCSI, les premier et second disques durs peuvent très bien être SCSI ; et la géométrie que le BIOS aura donné pour sda sera utilisée par le noyau pour hda. Du reste, les disques durs qui ne sont pas déclarés dans la configuration du BIOS ne sont pas vus par ce dernier. Cela signifie que, par exemple, dans un système uniquement IDE où hdb n'est pas déclaré dans la configuration, les géométries rapportées par le BIOS pour les premier et second disques vont être appliquées à hda et hdc.
Quand on envoie la commande IDENTIF DRIVE (0xec) à un disque dur IDE, il retournera 256 mots d'information contenant de nombreux détails techniques. Concentrons nous uniquement sur ce qui joue une rôle pour la géométrie. Les mots sont numérotés de 0 à 255.
Nous trouvons ici trois informations : DefaultCHS (mots 1,3,6), CurrentCHS (mots 54-58) et LBAcapacity (mots 60-61).
Description | Exemple | |
0 | Champ de bits : bit 6 : disque fixe, bit 7 : media amovible | 0x0040 |
1 | Nombre par défaut de cylindres | 16383 |
3 | Nombre par défaut de têtes | 16 |
6 | Nombre par défautl de secteurs par piste | 63 |
10-19 | Numéro de série (en ASCII) | K8033FEC |
23-26 | Révision du micro-code (en ASCII) | DA620CQ0 |
27-46 | Nom du modèle (en ASCII) | Maxtor 54098U8 |
49 | Champ de bits : bit 9 : supporte le LBA | 0x2f00 |
53 | Champ de bits : bit 0 : les mots 54-58 sont valides | 0x0007 |
54 | Nombre actuel de cylindres | 16383 |
55 | Nombre actuel têtes | 16 |
56 | Nombre actuel de secteurs par piste | 63 |
57-58 | Nombre total actuel de secteurs | 16514064 |
60-61 | Nombre par défaut de secteurs | 80041248 |
255 | Checksum et signature (0xa5) | 0xf9a5 |
Les chaînes ASCII sont composées de mots contenant chacun deux caractères, le premier étant l'octet de poids fort et le second l'octet de poids faible. Les valeurs 32-bits sont données avec le mot de poids faible d'abord. Les mots 54-58 sont positionnés à l'aide de la commande INITIALIZE DRIVE PARAMETERS (0x91). Ils n'ont un sens que quand CHS est utilisé, mais peuvent aider à trouver la taille réelle du disque dans le cas où celui-ci donne les valeurs 4092/16/63 à DefaultCHS (dans le but d'éviter les problèmes de BIOS).
Parfois, quand un cavalier force un disque à donner une fausse valeur pour LBAcapacity (le plus souvent une valeur de 66055248 secteurs pour pouvoir rester en dessous de la valeur limite de 33,8 Go), il faut disposer d'une quatrième information pour trouver la taille réelle du disque : le résultat de la commande READ NATIVE MAX ADDRESS (0xf8).
La situation pour le SCSI est légèrement différente, puisque les commandes
SCSI utilisent déjà les numéros de blocks logiques, donc une 'géométrie' est
complètement hors de propos pour les véritables Éntrées/Sorties.
Cependant, le format de la table des partitions est toujours le même,
donc fdisk
ne fait pas la différence entre des disques IDE et SCSI.
Comme on peut le voir à partir de la description détaillée ci-dessus, chaque
gestionnaire de disques s'invente une géométrie différente. Un gros foutoir
en fait.
Si vous n'utilisez pas DOS ou un équivalent, alors évitez toute configuration qui met en jeu des conversions étendues et utilisez simplement 64 têtes, 32 secteurs par piste (cela a pour effet de donner une valeur tout à fait sympathique et commode de 1 Mio par cylindre), si possible, comme ça il n'y aura pas de problème quand vous déplacerez le disque dur d'un contrôleur à un autre. Certains gestionnaires de disque SCSI (aha152x, pas16, ppa, qlogicfas, qlogicisp) sont si sensibles au sujet de la compatibilité avec le DOS qu'ils ne permettront pas à un système uniquement Linux d'utiliser plus de 8 Gio. C'est un bug.
Quelle est la vraie géométrie ?
La réponse la plus facile est qu'elle n'existe pas.
Et si elle existait, vous ne voudriez pas la connaître et à coup sûr
JAMAIS, AU GRAND JAMAIS ne devrez en dire quoi que ce soit à fdisk
ou à
LILO ou au noyau.
C'est uniquement une histoire entre le contrôleur SCSI et le disque dur.
Laissez-moi le redire : seules les personnes stupides donnent à
fdisk
, à LILO ou au noyau la véritable géométrie d'un disque SCSI.
Mais si vous êtes curieux et que vous insistez, vous devez demander au disque
dur lui-même. Il y a l'importante commande READ CAPACITY qui donnera la
capacité complète du disque dur et il y a la commande MODE SENSE, qui, dans
la Rigid Disk Drive Geometry Page (page 04) donne le nombre de cylindres et
de têtes (c'est une donnée qui ne peut pas être changée) et dans
la Format Page (page 03) donne le nombre d'octets par secteur et de secteurs
par piste. Ce dernier nombre est typiquement dépendant du rang et le nombre
de secteurs par piste varie -- les pistes extérieures ont plus de secteurs que
les pistes intérieures. Le programme Linux scsiinfo
donnera cette
information. Il y a de nombreux détails et complications et il est clair que
personne (probablement même pas le système d'exploitation) ne désire
utiliser cette information. Du reste, tant que nous ne nous intéressons qu'à
fdisk
et à LILO, on a typiquement des réponses du style
C/H/S=4476/27/171 -- valeurs qui ne peuvent pas être utilisées par
fdisk
parce que la table des partitions ne réserve que 10,8 et 6 bits pour
respectivement C/H/S.
Mais alors, d'où le HDIO_GETGEO
du noyau tire-t-il ses
informations ?
Eh bien, soit du contrôleur SCSI, soit en faisant une supposition éclairée.
Certains gestionnaires de disque semblent croire que nous voulons
connaître la 'réalité', mais bien sûr nous ne voulons savoir que ce que
FDISK de DOS ou de OS/2 (ou AFDISK de Adaptec, etc.) utiliseront.
Remarquez que le fdisk
de linux a besoin des nombres H et S de
têtes et de secteurs par piste pour convertir les nombres de secteurs
LBA en adresses c/h/s, mais le nombre de cylindres C ne joue aucun
rôle. Quelques gestionnaires de disque utilisent (C,H,S)=(1023,255,63) pour
signaler que la capacité du disque dur est d'au moins 1023×255×63
secteurs. Ce n'est pas de chance, puisqu'ils ne révèlent pas la vraie taille et
limiteront les utilisateurs de la plupart des versions de fdisk
à
n'avoir accès qu'à environ 8 Gio de leur disque -- une sérieuse
limitation de nos jours.
Dans le texte ci-dessous, M représente la capacité totale du disque dur et C, H, S, le nombres de cylindres, de têtes et de secteurs par piste. Il suffit de donner H, S si l'on voit C comme étant défini par M/(H×S).
Par défaut, H=64 et S=32.
H=64, S=32.
H=64, S=32 à moins que C ne soit supérieur à 1024, auquel cas H=255, S=63,
C=min(1023, M/(H×S)).
(Ainsi C est tronqué et H×S×C n'est pas une approximation de la
capacité M du disque dur. Cela va dérouter la plupart des versions de
fdisk
.) Le code de ppa.c
utilise M+1 à la place de M et dit qu'à
cause d'un bug dans sd.c
, M est plus petit de 1.
H=64 et S=32 à moins que C ne soit supérieur à 1024 ou que, encore mieux, l'option du BIOS '> 1 GB' ait été activée, auquel cas H=255 et S=63.
Demande au contrôleur lequel des deux schémas de conversion est utilisé et se sert soit de H=255, S=63, soit de H=64, S=32. Dans le dernier cas, il y a un message au démarrage qui dit "aha1542.c: Using extended bios translation" ("aha1542.c: Utilisation du mode de conversion étendu du bios")
H=64 et S=32 à moins que C ne soit supérieur à 1024 ou que, mieux encore,
le paramètre de démarrage "extended" ait été passé, ou que le bit 'extended'
ait été positionné dans la SEEPROM ou dans le BIOS, auquel cas H=255, S=63.
Dans Linux 2.0.36 ce mode de conversion étendu devrait toujours être
automatiquement utilisé si il n'y a pas de SEEPROM, mais dans Linux 2.2.6,
si le même cas se présente, le mode de conversion étendu est utilisé
seulement si l'utilisateur le demande au travers du paramètre de démarrage (de
ce fait, quand une SEEPROM est trouvée, le paramètre de démarrage est ignoré).
Cela signifie qu'une configuration qui fonctionne en 2.0.36 peut ne pas
démarrer avec un noyau 2.2.6 (LILO nécessite alors le mot-clé
linear
, ou le noyau a besoin du paramètre aic7xxx=extended
au
démarrage).
H=64 et S=32 à moins que C ne soit supérieur à 1024, ou que, encore mieux, le mode de conversion étendu ait été autorisé au niveau du contrôleur, auquel cas si M<2^22 alors H=128, S=32 ; sinon H=255, S=63. Cependant, après avoir fait ce choix pour (C,H,S), la table des partitions est lue et si pour l'une des trois possibilités (H,S)=(64,32),(128,32),(255,63) la valeur endH=H-1 est vue quelque part, alors cette paire est utilisée et le message "Adopting Geometry from Partition Table" ("Adoption de la géométrie lue dans la table des partitions") est affiché au démarrage.
Il trouve l'information sur la géométrie dans la Table des Paramètres des Disques du BIOS (BIOS Drive Parameter Table), ou lit la table des partitions et utilise H=endH+1, S=endS pour la première partition, à condition qu'elle ne soit pas vide, ou utilise H=64, S=32 pour M<2^21 (1 Gio), H=128, S=63 pout M<63×2^17 (3.9 Gio) et H=255, S=63 dans les autres cas.
Il utilise le premier couple (H,S)=(64,32),(64,63),(128,63),(255,63) qui rendra C<1024. Dans le dernier cas, C est ramené à la valeur 1023.
Il lit C,H,S depuis le disque dur. (Horreur !) Si C ou S sont trop grands, alors il fixe S=17, H=2 et double la valeur de H tant que C<=1024. Cela signifie que H sera mis à 0 si M>128×1024×17 (1.1 Gio). C'est un bug.
Un de ces trois couples de référence est utilisé ((H,S)=(16,63),(64,32),(64,63)) en fonction du mode de cartographie du contrôleur.
Regardez la table des partitions. Puisque par convention les partitions se
terminent à la limite d'un cylindre, nous pouvons, étant donné que
end=(endC,endH,endS)
pour n'importe quelle partition, simplement fixer
H=endH+1
et S=endS
. (Il est rappelé que le décompte des
secteurs commence à 1.)
Plus précisément, voilà ce qui est fait : s'il existe une partition non
vide, prendre la partition avec le plus grand begin
. Pour cette
partition, regarder endH+1
, calculé à la fois en additionnant
start
et length
et en supposant le fait que cette partition se
termine à la limite d'un cylindre. Si les deux valeurs concordent, ou si
endC
=1023 et start+length
est un multiple entier de
(endH+1)xendS
, alors accepter le fait que cette partition se termine
effectivement sur la frontière d'un cylindre et fixer H=endH+1
et
S=endS
.
Si cela échoue, soit parce qu'il n'y a pas de partition, soit parce qu'elles ont
des tailles bizarres, il faut uniquement se fier à la capacité totale M
du disque dur.
Algorithme : fixer H=M/
(62×1024) (arrondi au chiffre
supérieur), S=M/
(1024×H) (arrondi au chiffre supérieur),
C=M/
(H×S) (arrondi au chiffre inférieur).
Cela a pour effet de générer un triplet (C,H,S) avec C égal à 1024 au plus et
S égal à 62 au plus.