jeudi 5 novembre 2015

Comment démarre un ordinateur

Comment démarre un ordinateur ? Ben tiens, j'appuie sur son interrupteur, pis j'ai Windows qui apparaît, c'est pas compliqué non ?

Bon, on peut effectivement se satisfaire de ce niveau de compréhension. Cependant, le jour où on voudra faire des choses un peu plus avancées avec sa machine, comme se débattre avec un système multi-boot récalcitrant, ou un "secure" boot trop restrictif, il pourra s'avérer utile d'avoir quelques notions.

En outre, vu la période actuelle où on est encore à cheval sur deux périodes (BIOS vs UEFI), les explications trouvées ici et là sur Internet peuvent être confuses, dépassées ou inadaptées à votre configuration . Il faudra alors plonger dans la documentation technique (la vraie, pas un article de blog), et là bon courage, c'est quand même assez hardcore pour le commun des mortels, et même pour la plupart des informaticiens "modernes" (c'est à dire assez ignorants du fonctionnement de leur outil de travail).

So, je me suis attelé à la tâche, et je vais essayer de résumer les choses dans les grandes lignes, histoire de fournir un premier niveau de compréhension pour faciliter une étude plus poussée...

Alors, un pré-requis absolu, sauf pour les purs et durs (mais que feraient ils ici ?) :
Le B-A BA de la gestion des disques

Et si vous êtes un curieux qui n'a pas froid aux yeux qui tente juste le coup, sans grande connaissance préalable en informatique, je vous conseille fortement aussi celui là :
Le B-A de l'assemblage (hardware). J'y explique les notions de base sur le matériel et le logiciel système (OS, Bios/Uefi)

C'est parti mon kiki.

Explication de la problématique

Alors, un ordinateur c'est grosso-modo un processeur qui exécute des suites d'instructions en langage machine (le seul qu'il comprend donc).

Cependant quand on l'allume l'ordinateur, ben il faut encore lui donner à manger au processeur, à savoir charger en mémoire les instructions qu'il est censé exécuter, puis le prendre par la  main et l'emmener sur la première instruction de la (longue) liste, puis lui donner une petite poussée dans le dos. Après c'est bon, il va dérouler les instructions les unes derrière les autres (exécuter le programme quoi), et normalement vous allez avoir votre écran d'accueil Windows au bout d'un certain temps, voire d'un temps certain.

Et ces instructions, ben faut bien aller les chercher sur un support physique où elles sont mémorisées, en l’occurrence un disque dur (ou SSD on s'en fout, même une clé USB ou un DVD si vous voulez).

Hé ben tout ça, ça ne se fait pas tout seul par magie, ça résulte de l'exécution d'un programme. Or, le programme habilité à lancer des programmes c'est le système d'exploitation. Or, il n'est pas lancé le système d'exploitation quand on démarre l'ordinateur. On est donc face à un niéme problème du type "qui de la poule et l'oeuf..." (courant en informatique).

Et là tout de suite ça devient plus drôle. Enfin façon de parler, car on est obligé de se pencher un peu dans les entrailles de la bête et ça devient vite pénible quand on ne calcule pas de tête en hexadécimal, qu'on ne programme pas en assembleur depuis ses 8 ans, et qu'on n'a pas de formation en électronique. Mais on peut y arriver, je suis là pour vous aider.

Alors déjà, il faut savoir que le processus de démarrage, à partir de maintenant on dira boot car c'est moins long à écrire, diffère sensiblement selon le type de votre carte mère : une carte mère avec un firmware conforme à la norme BIOS et une carte mère conforme à la nouvelle norme UEFI ne bootent pas de la même façon.

update 11/2016 > 
Petite précision utile. Les PC modernes sont tous équipés de firmware UEFI, il y a déjà pas mal d'années qu'on ne trouve plus de machines équipées de firmware BIOS. Pour autant, connaître la distinction entre le fonctionnement de BIOS et d'UEFI reste importante car un firmware UEFI est susceptible de booter dans deux modes : le mode standard (UEFI way) qui permet de booter depuis un disque de plus de 2.2 To et d'activer le secure boot, ou le mode BIOS (appelé selon les cartes et les documentations : legacy, hérité, CSM). La façon dont le mode est déterminé est spécifique à chaque modèle de carte mère donc je ne peux guère en parler, et ce d'autant que c'est généralement assez opaque. Il est généralement possible de forcer le mode de démarrage via l'appui sur une touche ou une option dans le setup du firmware (ce qui est indispensable pour permettre par exemple de démarrer un installeur Windows en mode UEFI afin qu'il puisse installer l'OS sur un disque partitionné en GPT)


La séquence de Boot

Quand l'ordinateur démarre, il exécute automatiquement le programme inscrit dans la ROM de la carte mère (le firmware). C'est tout simplement inscrit dans le marbre, par fabrication.

Alors, je ne le répéterais pas à chaque fois, pour exécuter un programme, il faut le charger dans la mémoire, puis dire au processeur d'exécuter les instructions qui démarrent à l'adresse mémoire de la première instruction. Il va l'exécuter et toutes celles qui suivent jusqu'à ce qu'il n'y ait plus rien. Et si la dernière instruction c'est "retourne à la première instruction", le programme tournera éternellement, du moins tant qu'on ne coupera pas le courant.

Notre premier programme est stocké dans la ROM et est donc limité en taille et en fonctionnalités pour des raisons techniques sur lesquelles je ne m'étendrais pas.

Alors ce programme, il va faire tout ce qu'il peut mais le pauvre est limité : il va savoir gérer à peu près correctement les disques de façon pas optimale, mais bon ça suffira pour le moment, il saura afficher des caractères à l'écran, pas de façon sexy mais bon ce sera lisible, il sera même capable de reconnaître le clavier et la souris (si si, la souris), même quand ils sont branchés en USB (si votre système est pas trop ancien) et quelques autre trucs de base.

Avec tout ça, il va déjà faire l'essentiel, à savoir initialiser l'ensemble du matériel, compter ses petits, vérifier que la mémoire fonctionne bien etc... C'est la phase de POST (Power On Self Test, auto test automatique au démarrage dans la langue de Molière).

Puis une fois l'ordinateur prêt (tout le monde est réveillé, prêt à travailler, rien n'est tombé en panne depuis le dernier boot), on va devoir passer aux choses sérieuses et là le malheureux firmware il va arriver à ses limites le pauvre. 

C'est pas lui qui va vous afficher des jolies fenêtres avec des effets de transparence, jouer des clips vidéo et vous permettre de faire un partie de Candy Crush. Pour tout ça, il faut un programme beaucoup plus sophistiqué, écrit dans un langage évolué, et qui est bien trop gros pour tenir dans la ROM, un système d'exploitation quoi !

Donc notre firmware va rendre la main. Sa dernière activité va consister à charger en mémoire, non pas le système d'exploitation directement, mais un programme chargé de charger le système d'exploitation (le bootloader). Après c'est fini pour lui. 

Alors vous devez vous dire, ils sont bien tarés ces informaticiens : pourquoi charger un programme qui va charger l'OS et pas directement charger l'OS ? Hé bien tout simplement car il existe différents OS et qu'ils se chargent tous différemment. Du coup, comme on veut pouvoir utiliser l'ordinateur avec différents OS, il nous faut un programme intermédiaire ; comme ça, il nous suffira de mettre celui qui va bien par rapport à l'OS qu'on veut utiliser. Alors, vous allez me rétorquer, pourquoi ne pas modifier directement le premier programme, le firmware ? Ben la réponse c'est que c'est pas possible et vous vous en contenterez (bon ok, il est spécifique au matériel, il faudrait autant de versions de programme que de systèmes multiplié par le nombre de cartes mères différentes).

La suite vous la connaissez.

Vous avez votre interface utilisateur (les fenêtres sous Windows, la ligne de commande sous d'autres systèmes), et ça vous permet de dire à l'ordinateur ce que vous voulez qu'il fasse. Et pour vous satisfaire, il chargera des programmes en mémoire et les fera exécuter par le processeur, plus pleins de truc qu'il fait sans que vous en ayez conscience (transmettre votre code de carte bleue à un réseau de pirates russes, se faire passer pour vous et pénétrer le réseau du Pentagone, télécharger des images pédophiles pour vous faire envoyer en prison avec des co-détenus très sympas etc.).

Alors BIOS et UEFI font la même chose, mais il le font de façon un peu différente. 

Le bootloader appelé par le BIOS est écrit en langage assembleur (donc directement en langage machine pour faire simple) ; autant dire que c'est pas un poème car écrire en assembleur est quelque chose de très difficile. Cependant ça a un énorme avantage (plusieurs en fait) : c'est très rapide car parfaitement optimisé pour le processeur, et encore mieux ça fait des programmes tout petits (et ça tombe bien car on a toujours un problème de place). 

Le bootloader appelé par UEFI lui est écrit en langage C, un langage évolué beaucoup plus simple (tout est relatif) et du coup il sait faire plus de choses, et comme il permet de faire plus de choses, on lui en fait faire plus (et il n'a pas les mêmes contraintes de taille).

En prime, comme UEFI est plus récent il sait dépasser les capacités du BIOS qui a été conçu il y a 30 ans, pour les matériels d'il y a 30 ans (tiens au hasard, pour des disques durs de capacité beaucoup moins importante). Mais ça vous le savez déjà si vous avez lu l'article sur la gestion des disques.

Vous avez peut être remarqué que l'écran de configuration du firmware que vous pouvez appeler au démarrage de l'ordinateur en appuyant sur une touche (suppr souvent, ou F2 ou autre encore), il est beaucoup plus sexy avec une carte mère UEFI qu'avec une carte mère BIOS ? Ben c'est grâce au langage de programmation C supporté par UEFI qui permet de faire ça sans lancer un chantier de 3 ans avec 50 programmeurs.


the BIOS way of life

C'est la partie la plus simple, ça existe depuis 30 ans, on trouve pleins d'explications sur Internet. Je vais donc faire rapide. Et en plus, ça va être de moins en moins utile.

Petit avertissement ; j'ai en partie rétro-conçu l'algorithme à partir de diverses sources et par intuition, il doit y avoir des variantes et des subtilités, mais pour autant je pense être dans le vrai.

Bon alors c'est pas compliqué, du moins dans l'esprit, et si on se garde de trop plonger dans les détails.

Sur chaque disque de la machine, les 512 premiers octets sont réservés. On appelle cette zone le MBR (Master Boot Record). Dans cette zone, on trouve principalement deux choses : la table de partitions bien mal dénommée MBR également, et un tout petit programme qui dispose de quelques centaines d'octets seulement. Ce programme c'est le bootloader, c'est lui qui sera chargé de charger le système d'exploitation.



Pour charger le système (c'est à dire le lire sur le disque et l'écrire en mémoire, en informatique on en revient toujours aux entrées-sorties), il faut déjà déterminer où il se cache. Ben oui, potentiellement l'ordinateur a plusieurs disques, et chaque disque peut avoir plusieurs partitions. Et le système, il est quelque part là dedans, mais où ? Comme en plus, le système ça peut être n'importe quoi (le premier qui dit que Windows c'est n'importe quoi prend la porte), il ne peut même pas essayer d'en détecter la présence en reconnaissant sa tête.

Rappelez vous que dans l'écran de configuration du BIOS/UEFI, on peut dire quels sont les disques à partir desquels on peut booter, et quel est l'ordre de préférence.

Le firmware, a lu cette information. Il va donc commencer par le premier disque, il va regarder si les 512 premiers octet de ce disque constituent un MBR valide (il contrôle la présence d'une valeur particulière résultant d'une convention par défaut dans le 511 et 512 éme octets, la "boot signature" dans notre schéma). Si tel est le cas, il lit la table des partitions. Si une des partitions est flaguée "bootable", bingo il sait qu'il va y trouver un système d'exploitation. Dans ce cas, il charge en mémoire le bootloader (le programme stocké dans la MBR, le "bootstrap code" dans notre schéma) puis il lui passe la main. Le bootloader s'exécute, il charge en mémoire le système d'exploitation depuis la partition qui lui a été communiquée par le firmware, et roule ma poule.

Si le premier disque n'a pas de MBR, ou pas de partition bootable, le firmware va tenter le coup avec le second disque dont on a indiqué dans la configuration qu'il pouvait servir à démarrer, etc. Si à la fin il ne trouve rien, il affiche un message d'erreur et l'ordinateur est inutilisable.

Déjà ici vous devez comprendre pourquoi vous devez contrôler ou changer l'ordre du boot dans le BIOS/UEFI quand vous voulez démarrer depuis un DVD (pour installer un nouvel OS le plus souvent) ; il faut que le lecteur de DVD soit en premier avant le disque qui a votre système déjà installé, sinon vous démarrerez toujours depuis votre disque dur et jamais de votre DVD.

Alors quelques déductions. Le bootloader est nécessairement spécifique au système d'exploitation chargé (sinon il ne saurait pas quoi charger). Windows à le sien, Linux à le sien etc. Chaque système vient avec ses outils pour inscrire son bootloader dans le MBR et peut potentiellement écraser celui de son petit copain si on ne fait pas attention. Pour Windows, ça dépend des versions mais avec une version moderne c'est NTLDR (NT Loader, NT étant un ancien nom des Windows actuels), pour Linux il en existe plusieurs, LILO et GRUB semblent être les plus utilisés.

Multi-boot : si vous avez plusieurs systèmes d'exploitation installés sur plusieurs partitions, vous avez sans doute envie de pouvoir choisir sur lequel démarrer. Si ce sont tous des Windows, NTLDR fera l'affaire, par contre si vous mixez Windows et Linux, il faudra utiliser GRUB ou LILO (GRUB semble plus utilisé de nos jours), ou encore un autre. Tous ces outils requièrent un peu de configuration.


the UEFI way of life

Le fonctionnement est similaire mais diffère de façon significative sur plusieurs aspects. 

J'ai eu beaucoup de difficulté à trouver des informations sur ces sujets, si certains points sont clairement établis (ESP, GPT), d'autres sont plus sujets à caution (mais ce n'est guère important). Ma principale référence pour les curieux est celle ci.

Déjà, dans un système UEFI, il y a une partition cachée (vous ne la voyez pas, sauf à utiliser des outils d'administration) qu'on appelle ESP (EFI System Partition). 

Cette partition permet de stocker les programmes qui seront appelés par le firmware à l'issue du POST. Du coup, on n'a plus la contrainte du MBR qui ne laissait que quelques centaines d'octets au bootlader dans le BIOS. Du coup, on peut écrire les programmes avec un langage évolué comme le C car on n'a plus la même contrainte de taille (un programme écrit en langage évolué comme le C sera toujours beaucoup plus gros qu'un programme directement écrit en assembleur). Et aussi, on peut faire des programmes plus évolués et plus riches fonctionnellement (pour le bootloader qui ne fait pas grand chose c'est pas très important, par contre pour l'outil de configuration du UEFI c'est sympa).

Cette partition est référencée, comme toutes les partitions, dans la table des partitions. Et ce n'est pas un problème car contrairement au BIOS avec son MBR qui nous limitait à 4 partitions maximum (et de 2.2 To Max, je sais je suis lourd), UEFI s'appuie sur une table GPT plus évoluée (128 partitions possibles, ça devrait aller).

Ensuite, le firmware ne se base pas sur la lecture du premier secteur des disques (les premiers 512 octet) pour détecter la présence de partitions contenant un système bootable. A la place, il se base sur une série de variables dont il obtient la valorisation en lisant la ROM. Certaines de ces variables lui indiquent la présence de programmes stockés dans l'ESP et qui ont la capacité à charger un système d'exploitation (bootloader), ou un programme qui se chargera à son tour de charger un système (donnant éventuellement la possibilité de choisir parmi plusieurs).

Ces variables sont normalement valorisées à l'installation des systèmes d'exploitation. Quand un OS s'installe, il est censé faire le job (copier son bootloader dans l'ESP dans un certain répertoire et avec un certain nom, et mettre à jour la variables d'environnement dans la mémoire permanente où elle est stockée). A priori, il semblerait qu'il y ait encore pas mal de soucis, en particulier pour faire cohabiter un système Windows et Linux sur la même machine (mais on peut le faire, chez moi je fait cohabiter un Windows 10 et un Linux Mint, mais bon j'ai eu quelques frayeurs et j'ai du bidouiller en serrant les fesses). Bref, il est bon de savoir qu'il y a parfois des problèmes de jeunesse potentiellement très délicats à résoudre (voire impossible parfois). 

La gestion du multi-boot est censée pouvoir être assurée directement par le firmware via un menu qu'il gère directement mais ceci est variable selon les contructeurs (par exemple, la carte mère UEFI de mon PC, une ASUS P8Z77-V LX2, ne le permet pas). Ce n'est pas gênant car il existe des bootloader qui gèrent très bien cette problématique.

secure boot : le secure boot, ou boot "sécurisé" a fait couler beaucoup d'encre. C'est une nouvelle fonctionnalité apporté par UEFI. Sans entrer dans le détail de mise en oeuvre des techniques de cryptographie (je prévois des articles là-dessus), il permet de vérifier qu'un programme chargé par le firmware (un bootloader) n'a pas été modifié de façon malicieuse par un virus. En effet, les virus intervenant au niveau du bootloading sont particulièrement pernicieux : ils sont chargés avant le système d'exploitation et sont donc totalement indétectables et ont toute liberté d'action.


Le souci est que cette vérification s'appuie sur une empreinte numérique et que cette technique implique que le bootloader chargée par le firmware ait été signé numériquement, et que le certificat du tiers de confiance ayant réalisé cette prestation soit installé sur la machine ; et ceci pose des soucis pour les os open source, à tel point que Microsoft (à l'origine de la spécification UEFI) a été publiquement accusé de mettre en place une technique visant à empêcher les consommateurs de mettre en place un système alternatif à Windows sur les machine vendues pré-équipées en Windows (depuis la version 8), ce qui serait effectivement gravissime. Ceci dis, les choses semblent être en voie de résolution à cette date. En tout état de cause, la spécification UEFI précise que le secure boot doit pouvoir être désactivé (via le programme de setup UEFI).

Conclusion

Bon finalement, c'était pas si compliqué ? Heu si un peu quand même.

Bon, l'idée ici était de donner un premier niveau de compréhension générale afin de pouvoir  lire des ressources techniques plus détaillées en ayant une chance raisonnable d'y comprendre quelque chose. J'espère être arrivé à cet objectif.