paint-brush
Le monde caché du micrologiciel : exploration du processus de démarrage de votre ordinateurpar@tristejoursoir
3,062 lectures
3,062 lectures

Le monde caché du micrologiciel : exploration du processus de démarrage de votre ordinateur

par Aleksandr Goncharov15m2023/04/21
Read on Terminal Reader

Trop long; Pour lire

Dans cet article, nous donnons un aperçu du processus de démarrage, y compris ses différentes étapes, les composants clés impliqués et les défis rencontrés au cours du processus. Bien que nous nous concentrions principalement sur l'**architecture x86** (la plus largement utilisée), d'autres architectures présentent de nombreuses similitudes dans leur processus de démarrage.
featured image - Le monde caché du micrologiciel : exploration du processus de démarrage de votre ordinateur
Aleksandr Goncharov HackerNoon profile picture


Beaucoup de gens s'intéressent à la façon dont l'ordinateur démarre. C'est là que la magie commence et continue tant que l'appareil est allumé. Dans cet article, nous donnerons un aperçu du processus de démarrage , y compris ses différentes étapes, les composants clés impliqués et les défis rencontrés au cours du processus.


Bien que nous nous concentrions principalement sur l' architecture x86 (la plus largement utilisée), d'autres architectures auraient de nombreuses similitudes dans leur processus de démarrage. J'espère que cet article sera une ressource précieuse pour tous ceux qui cherchent à approfondir leurs connaissances dans ce domaine. Nous y voilà!

Table des matières:

  • BOOT ROM
    • Une mémoire non volatile
      • Programmable une seule fois
      • Programmable sur le terrain
    • Exécuter sur place (XIP)
      • Cache-As-Ram (CAR)
    • Disposition et mappage de la mémoire
      • Mode sans descripteur
      • Descripteur Flash Intel / mode Descripteur
      • Tableau d'interface du micrologiciel Intel (FIT)
      • Structure du micrologiciel embarqué AMD
  • Initialisation du silicium
    • Package de prise en charge du micrologiciel Intel (FSP)
    • Architecture logicielle encapsulée générique AMD (AGESA)
  • Sous-systèmes autonomes
    • Intel ME
    • AMD PSP
  • Séquences d'alimentation matérielles

BOOT ROM

Un circuit intégré (puce) situé sur la carte mère et stockant le code du micrologiciel responsable du démarrage de l'ordinateur est appelé BOOT ROM . Ce nom n'est pas standardisé, donc les autres développeurs l'appellent souvent FLASH ROM , BIOS FLASH , BOOT FLASH , SPI FLASH , etc. (ces noms leur sont donnés en raison de la technologie, de l'interface et des noms d'objectif). Ne vous inquiétez pas, ces termes sont interchangeables. Le code du micrologiciel dans la BOOT ROM est exécuté en premier lorsque l'ordinateur est sous tension. Il effectue des tests de base, initialise le matériel, puis charge le chargeur de système d'exploitation à partir d'un périphérique amorçable, tel qu'un disque dur ou une clé USB, dans la mémoire. Cette puce est fabriquée à partir de mémoire non volatile (NVM) .

Une mémoire non volatile

La mémoire non volatile est un type de mémoire d'ordinateur qui conserve son contenu même lorsque l'alimentation est coupée . Cela rend ce type de mémoire idéal pour stocker des données importantes qui doivent être conservées même lorsque l'ordinateur est éteint. De plus, la discussion se concentrera uniquement sur la mémoire qui contient le code du firmware. Nous ne parlerons pas de stockage tels que les disques durs (HDD), les disques SSD (Solid State Drives), les disquettes, etc.


Fondamentalement, nous pouvons classer ce type de mémoire dans les groupes suivants.

Programmable une seule fois

  • ROM masquée : le contenu est déterminé au moment de la fabrication et ne peut plus être modifié par la suite.
  • ROM programmable (PROM) : Contrairement à la ROM masquée, ce type de mémoire peut être programmé après fabrication. Mais toujours une seule fois.

Programmable sur le terrain

  • ROM programmable effaçable (EPROM) : peut être programmée plusieurs fois, mais son contenu peut être effacé et reprogrammé à l'aide de la lumière ultraviolette .


  • Programmable électriquement effaçable (EEPROM) : peut être reprogrammé plusieurs fois à l'aide de signaux électriques .


    • Mémoire Flash NOR : Agencement architectural en blocs où les données sont effacées au niveau du bloc et peuvent être lues ou écrites au niveau de l'octet . La mémoire NOR est directement accessible à l'aide d'une interface standard telle que byte parallel, I2C ou SPI.


      Dans l'industrie, il existe une convention pour réserver le terme EEPROM aux mémoires effaçables par octet par rapport aux mémoires flash effaçables par bloc.


La mémoire programmable est livrée avec une règle : effacer avant d'écrire . Dans une telle mémoire, l'écriture de nouvelles données est plus compliquée car les données sont stockées sous forme de charge sur une grille flottante (la raison principale réside simplement dans la physique des cellules de mémoire). La quantité de charge sur la grille détermine si la cellule stocke "0" ou "1".


Lorsque vous effacez une puce de mémoire flash, vous définissez tous les bits de données qui y sont stockés sur un état connu (par défaut), généralement un "1" logique. Cela vous permet de commencer avec une table rase, pour ainsi dire, et de programmer de nouvelles données sur la puce sans avoir de restes des anciennes données qui y sont encore stockées. Lorsque de nouvelles données sont écrites sur la puce, l'état des bits individuels passe de "1" à "0" pour représenter les nouvelles données.


Si vous écrivez simplement de nouvelles données sur la puce sans les effacer au préalable, les nouvelles données seraient combinées avec les anciennes, ce qui donnerait des résultats imprévisibles. Par exemple, considérons une puce de mémoire flash dotée de 8 bits de mémoire stockant la valeur "0110 0010". Si vous écrivez de nouvelles données "1100 1001" sur la puce sans les effacer au préalable, l'état résultant de la puce serait "0100 0000", ce qui n'est peut-être pas ce que vous vouliez.


La principale confusion est liée au mot ROM qui signifie Read Only Memory . Le terme "mémoire en lecture seule" a été historiquement utilisé pour désigner la mémoire qui est permanente et ne peut pas être modifiée par l'utilisateur. Cependant, à mesure que la technologie a progressé, la définition de la ROM a changé et elle est maintenant souvent utilisée pour désigner une mémoire préprogrammée en usine et qui ne peut pas être facilement modifiée par l'utilisateur final. Mais si l'utilisateur a les compétences souhaitées et l'équipement spécialisé (par exemple, un programmeur), il peut reprogrammer la puce. Le nom ROM est resté, même si la définition a changé, comme une référence historique à l'objectif initial de la mémoire.


En appliquant une protection en écriture, certains types de ROM reprogrammables peuvent temporairement devenir une mémoire en lecture seule.


Ce ne sont PAS TOUS les types de mémoire non volatile existants, mais la plupart des plus populaires dont vous pourriez entendre parler par hasard. De nos jours, sur la plupart des cartes mères, ces puces sont fabriquées en utilisant la technologie NOR Flash .

Exécuter sur place (XIP)

L'exécution sur place (XIP) est une méthode qui permet au processeur d'exécuter du code directement à partir de la mémoire flash sans le copier d'abord dans la mémoire volatile (telle que la RAM ). Ceci est réalisé en mappant la mémoire flash dans l'espace d'adressage du processeur, de sorte que l'exécution du code puisse être effectuée directement à partir de la mémoire flash. Ainsi, le système est capable de commencer à exécuter le code dès que possible, sans avoir à attendre que la RAM soit initialisée en premier.


Attendez... le CPU peut communiquer avec BOOT ROM via le protocole SPI/Parallel/etc ? Bien sûr que non, il ne s'agit que de récupérer les instructions de la mémoire système, les requêtes vers cette région mémoire sont redirigées vers Intel Direct Media Interface (DMI ) ou AMD Infinity Fabric (IF) / Unified Media Interface (UMI) (prédécesseur). C'est le lien entre le CPU et le chipset de la carte mère. À ce stade, le décodage de l'adresse est effectué via des décodeurs situés dans le jeu de puces et les données de la puce sont renvoyées au processeur.


Lorsque la puce est fabriquée à partir de mémoire flash NOR, qui prend en charge les lectures à accès aléatoire, mais pas les écritures à accès aléatoire, un problème s'est posé. Tant que la mémoire inscriptible n'est pas disponible, tous les calculs doivent être effectués dans les registres du processeur. À ce stade, le code ne peut être écrit qu'en langage d'assemblage et tend à configurer l'environnement pour un langage de haut niveau (généralement, pour le langage C ). La raison en est que l'initialisation de la mémoire est devenue si complexe qu'il serait difficile d'écrire uniquement en assembleur. Étant donné que ces langages nécessitent au moins un tas et une pile, nous avons besoin de mémoire inscriptible. Certains processeurs ont de la SRAM intégrée dans la puce elle-même, mais une approche plus moderne consiste à utiliser la mémoire cache intégrée en tant que RAM (CAR) .


Cache-As-Ram (CAR)

Le cache du processeur est une mémoire à grande vitesse qui stocke une copie des données et des instructions fréquemment utilisées à partir de la mémoire principale. Un cache est situé plus près du processeur et organisé en plusieurs niveaux (L1, L2, L3, ...), chaque niveau étant plus grand et plus lent que le précédent.


Si les données sont dans le cache, le processeur peut récupérer les données demandées dans le cache (c'est ce qu'on appelle un succès de cache ). Lorsque le cache du processeur est incapable de trouver les données requises, cela entraîne un échec du cache . Cela peut se produire soit parce que les données n'ont jamais été stockées dans le cache, soit parce que les données ont été précédemment stockées mais ont été supprimées du cache. Quoi qu'il en soit, le processeur doit aller jusqu'à la mémoire principale pour accéder aux données et les copier dans le cache.


L'éviction du cache est le processus de suppression des données du cache pour libérer de l'espace pour de nouvelles données. L'éviction des données peut être initiée soit par le système de mise en cache (généralement lorsqu'un cache est plein et que de nouvelles données doivent être stockées, ou lorsque la politique de durée de vie des données a expiré) ou par une demande explicite.


Cependant, si nous voulons utiliser le cache du processeur comme RAM , nous devons configurer le cache pour qu'il fonctionne en mode sans expulsion , également appelé mode sans remplissage . Cette technique empêche l'éviction due à un défaut de cache . Au lieu de cela, le cache est traité comme une SRAM normale et tous les accès (lecture/écriture) atteindront le cache et n'atteindront pas la mémoire principale. Le mode peut être activé à l'aide d'instructions CPU spécifiques au fournisseur.

Disposition et mappage de la mémoire

En réalité, la BOOT ROM contient plusieurs types de firmware. Une fois qu'un groupe de micrologiciels est stocké dans la BOOT ROM, il doit être organisé d'une manière ou d'une autre pour les distinguer. Découvrons comment c'est fait.

Mode sans descripteur

À l'origine, le chipset effectue un mappage direct de l'intégralité du contenu de la BOOT ROM vers la mémoire (de 4 Go à 4 Go - 16 Mo). Généralement, si la BOOT ROM est inférieure à 16 Mo, le contenu est mappé à plusieurs reprises. Le CPU et le firmware peuvent lire/écrire sur la mémoire flash sans aucune restriction.





Le mode non-descripteur n'est plus pris en charge sur les nouveaux chipsets.

Descripteur Flash Intel / mode Descripteur

Finalement, dans l'ICH8, Intel introduit une disposition spéciale pour BOOT ROM. Le flash est divisé dans les régions suivantes :


  • Flash Descriptor (FD) - cette structure de données doit être située au début de l'appareil avec un décalage 0x10 . Il est composé de onze sections comme le montre la figure ci-dessous :



Le descripteur MAP a des pointeurs vers les autres régions et la taille de chacune également.


La section Composant contient des informations sur le(s) flash(s) du système (nombre de composants, densité de chacun, instructions non valides, etc.).


La section Master définit les autorisations de lecture/écriture pour les régions. En ce qui concerne la lecture/écriture, les autorisations doivent être définies sur Lecture seule, les informations stockées dans cette région ne peuvent être écrites que pendant le processus de fabrication.


  • BIOS - seule cette région est mappée en mémoire.





  • Intel Converged Security and Management Engine (CSME / ME) - le micrologiciel prenant en charge différentes technologies Intel et ME.
  • Gigabit Ethernet (GbE) - uniquement accessible directement par le contrôleur Gigabit Ethernet.
  • Données de la plateforme
  • Contrôleur embarqué (EC)


Le descripteur Flash et Intel ME sont les seules régions requises.

Tableau d'interface du micrologiciel Intel (FIT)

Le FIT est une structure de données à l'intérieur de la région du BIOS et contient diverses entrées qui décrivent la configuration de la plate-forme. Chaque entrée du tableau a une taille de 16 octets. Le premier s'appelle l' en-tête FIT , l'autre s'appelle l' entrée FIT . Il est localisé par un pointeur FIT à une adresse physique 0xFFFFFFC0 (4 Go - 0x40).


Ces composants doivent être traités avant l'exécution de la première instruction CPU à partir du vecteur de réinitialisation . Les entrées incluent les mises à jour du microcode du processeur, l'ACM de démarrage, les politiques de démarrage de la plate-forme/TPM/BIOS/TXT et d'autres éléments. Mais au moins, le FIT doit inclure les entrées d'en-tête FIT et de mise à jour du microcode . Ainsi, l'usage courant de FIT est de mettre à jour le microcode avant d'exécuter le vecteur de réinitialisation .


Voici à quoi ressemble la carte mémoire :






Structure du micrologiciel embarqué AMD

Malheureusement, il y a beaucoup moins d'informations, je n'ai trouvé aucune documentation de chipset AMD divulguée avec des détails sur leur mise en page. Je ne peux donc pas vous dire mieux que ce que dit la documentation coreboot . Il est écrit sur la base de la documentation AMD qui n'est disponible que sous NDA.


En fait, il suffira de savoir que l'analogue AMD du descripteur Flash est Embedded Firmware Structure et qu'il contient des pointeurs vers la table de répertoire PSP , la table de répertoire BIOS et d'autres micrologiciels.


Initialisation du silicium

Si vous souhaitez voir comment la mémoire et le processeur modernes sont exactement initialisés, je dois vous contrarier. Intel et AMD ne sont pas pressés de publier le Silicon Initialization Code à la communauté. Dans la mesure où ces informations ne sont pas accessibles au public, elles offrent une distribution binaire du code d'initialisation de silicium nécessaire. Ceci doit être considéré comme une bibliothèque pour les développeurs de micrologiciels et contient du code binaire pour initialiser le contrôleur de mémoire, le chipset, le processeur et d'autres parties différentes du système.

Package de prise en charge du micrologiciel Intel (FSP)

Ce binaire peut être divisé en 4 composants :


  • FSP-T : Mise en place de l'environnement d'exécution précoce (« RAM temporaire ») dans lequel le code C peut être exécuté. En pratique, ce binaire configure CAR, mais effectue également une initialisation matérielle précoce, comme la configuration de l'espace de configuration mappé en mémoire PCIe.
  • FSP-M : Initialisation de la mémoire permanente (telle que la DRAM).
  • FSP-S : achèvement de l'initialisation du silicium, y compris l'initialisation du processeur et du contrôleur IO.
  • FSP-O : composant facultatif qui fournit l'initialisation des périphériques OEM.


Voici un référentiel de binaires Intel FSP publié par Intel que vous pouvez trouver sur leur GitHub. La spécification FSP v2.1 peut être obtenue sur le site Web d'Intel.

Architecture logicielle encapsulée générique AMD (AGESA)

AGESA pour les produits antérieurs à la famille 17h est connu sous le nom de v5 ou Arch2008 . À cette époque, AGESA était open source et le code était disponible dans le référentiel coreboot (il était obsolète après la version 4.18). La spécification pour Arch2008 peut être trouvée sur le site Web d'AMD.


Avec l'introduction des produits de la famille 17h (microarchitecture Zen), AMD n'a pas publié de code source AGESA, uniquement des solutions binaires préconstruites. Un tel successeur s'appelle AGESA v9 et prend en charge la famille 17h et les versions ultérieures.

openSIL

Il n'y a pas d'informations détaillées disponibles, seulement des nouvelles .

Sous-systèmes autonomes

Une partie intégrante du processus de démarrage x86 moderne, sans lequel les cœurs x86 ne seraient jamais activés. Il est donc impossible de les désactiver complètement . Ces technologies sont responsables de l'initialisation du matériel, de la vérification de l'intégrité du système, de la gestion de l'alimentation et du lancement du processeur. Le micrologiciel de ces sous-systèmes est chargé et exécuté avant que le processeur principal ne commence à exécuter son propre micrologiciel. Un code sur de tels systèmes s'exécute indépendamment des cœurs de processeur de la plate-forme.


Tant que de nombreuses entreprises de matériel informatique ont intégré le principe de la sécurité par l'obscurité , ni le code source ni la documentation de ces sous-systèmes ne sont disponibles. Heureusement, nous savons comment cela affecte le processus de démarrage - voir Hardware Power Sequences .


Nous n'entrerons pas dans les détails, car il existe déjà de nombreux articles sur Internet rédigés par des chercheurs du monde entier. Mais je vais juste vous donner une brève description de ce que c'est.

Moteur de gestion Intel (ME)

Intel ME est un microprocesseur i486/80486 séparé intégré au chipset Intel (PCH) depuis 2008. Il possède sa propre RAM, une ROM intégrée, des ponts de bus vers tous les bus à l'intérieur du chipset (en conséquence, il peut accéder au réseau et même la RAM principale sur le CPU), et ainsi de suite. Exécute un système d'exploitation personnalisé basé sur MINIX.

Processeur de sécurité de plate-forme AMD (PSP)

AMD PSP est un cœur ARM reposant sur l'extension Trustzone, qui est insérée dans la matrice du processeur en tant que coprocesseur. Cette puce est intégrée à la plupart des plates-formes AMD depuis 2013. Exécute un système d'exploitation non documenté et propriétaire.

Séquences d'alimentation matérielles

Ce processus, également connu sous le nom de Power On Sequence ou Power Sequencing , fournit un certain nombre de niveaux de tension dérivés et/ou de rails d'alimentation dans un ordre particulier nécessaire sur la plate-forme. En termes plus simples, il alimente un certain nombre de composants de la plate-forme dans un ordre spécifique. Le processus varie en fonction de la conception du système ou de la plate-forme, mais un PC standard comprend généralement les étapes suivantes :


  • Vous appuyez sur le bouton d'alimentation . Mais attendez... ce bouton se trouve sur le boîtier de l'ordinateur qui n'est pas une partie nécessaire d'un ordinateur. Habituellement, le bouton d'alimentation est un câble. Nous avons un bouton d'un côté et un interrupteur que nous plaçons sur deux broches métalliques de la carte mère de l'autre côté. Lorsque nous appuyons sur le bouton, ces broches sont connectées afin que l'électricité puisse les traverser. Regardez la vidéo ci-dessous pour savoir comment allumer un ordinateur sans bouton d'alimentation si vous êtes intéressé.


  • La carte mère envoie un signal au bloc d'alimentation (PSU).


  • L'alimentation reçoit le signal, fournit la bonne quantité d'électricité et renvoie un signal à la carte mère.
  • Une fois que la carte mère reçoit le signal de bonne alimentation, elle alimente les composants de la plate-forme tels que le cœur, les horloges, le chipset, la mémoire, les différents contrôleurs, etc.
  • Une variété de sous-systèmes, y compris des sous-systèmes autonomes (discutés ci-dessus), peuvent démarrer avant le processeur principal.


  • Systèmes basés sur AMD (pour la famille 17h et versions ultérieures)


    • PSP s'exécute sur -chip BOOT ROM.

    • PSP localise le tableau des micrologiciels intégrés dans la ROM de démarrage hors puce et exécute le micrologiciel PSP.

    • PSP analyse la table de répertoire PSP pour trouver les étapes ABL et les exécute.

    • Les étapes ABL initialisent la mémoire principale, localisent l'image du BIOS dans la BOOT ROM et la chargent dans la DRAM (se décompresse si l'image est compressée).


      Cette plate-forme n'a aucune raison d'utiliser CAR car la DRAM est déjà disponible et la PSP y charge l'image du firmware.


  • Systèmes basés sur Intel
    • Le chipset (ICH/PCH) trouve le descripteur Intel Flash dans la BOOT ROM.
    • Le chipset copie le firmware CSME dans la mémoire interne où Intel ME peut y accéder et le dernier commence à l'exécuter.
    • Le chipset mappe la région du BIOS sur la mémoire.
    • Les mises à jour du microcode situées dans la table d'interface du micrologiciel sont chargées dans la CPU. Ils doivent être appliqués à chaque démarrage du système .
    • (facultatif) Si des modules de code authentifiés (ACM) sont trouvés, cette entrée est exécutée.


  • Pendant tout ce temps, le signal de réinitialisation de la CPU est appliqué pour empêcher la CPU de démarrer avant que d'autres parties du système ne soient prêtes. Lorsque la plate-forme est prête, la ligne de réinitialisation du processeur est désactivée. Dans un système multiprocesseur ou multicœur, un processeur est dynamiquement choisi pour être le processeur d'amorçage (BSP) qui exécute tout le code d'initialisation du micrologiciel. Les processeurs restants, appelés processeurs d'application (AP) à ce stade, restent arrêtés jusqu'à plus tard, lorsqu'ils sont explicitement activés par le micrologiciel/noyau.


  • Après la première mise sous tension, le CPU fonctionne en mode réel . La plupart des registres ont des valeurs bien définies , y compris le pointeur d'instruction (IP), le segment de code (CS) et le cache de descripteur , qui est une copie de chaque descripteur de segment dans le processeur pour permettre un accès rapide à la mémoire de segment.


    Le descripteur de segment est une entrée dans la table des descripteurs globaux (GDT) et contient l'adresse de base, la limite de segment et les informations d'accès (cette partie est ignorée car le mode réel n'a pas de contrôle d'accès comme le mode protégé). Au lieu d'accéder au GDT (qui est situé dans la mémoire) pour chaque accès à la mémoire, les informations sont stockées dans un cache de descripteurs.


    Cependant, le GDT n'est pas impliqué en mode réel, donc le processeur génère des entrées en interne. Le registre du sélecteur CS, utilisé pour accéder au descripteur de segment, est chargé avec 0xF000 . L'adresse de base CS est initialisée à 0xFFFF_0000 . IP est initialisé à 0xFFF0 .


    Par conséquent, le processeur commence à récupérer les instructions de la mémoire située à l'adresse physique 0xFFFF_FFF0 ( 0xFFFF_0000 + 0x0000_FFF0 ). La première instruction exécutée à cette adresse est appelée le vecteur de réinitialisation .


    REMARQUE : cette astuce vous donne accès à l'espace d'adressage élevé, cependant, vous ne pouvez pas accéder au code sous l'adresse 0xFFFF_0000 . L'adresse de base CS reste à cette valeur initiale jusqu'à ce que le registre du sélecteur CS soit chargé par le firmware. Cela peut être fait en exécutant un saut lointain .


    À ce stade, la meilleure décision est de passer en mode protégé avec 4 Go d'adressabilité. Si le firmware ne le fait pas, pour que le mode réel fonctionne, le chipset doit être capable d'aliaser une plage de mémoire inférieure à 1 Mo à une plage équivalente juste en dessous de 4 Go. Certains chipsets n'ont pas cet aliasing et peuvent nécessiter de passer à un autre mode de fonctionnement avant d'effectuer le premier saut en longueur.


  • L'adresse se trouve dans une section de mémoire non volatile , de sorte que le CPU utilise la méthode Execute In Place (XIP). Bien que s'il s'agit d'un système basé sur AMD, vous lisez probablement à partir de la mémoire principale.


  • La CPU exécute un code de firmware.


Je vous recommande de regarder la vidéo ci-dessous sur la séquence de mise sous tension, qui explique le processus en utilisant la carte mère ASUS P9X79 comme exemple. Malgré le fait qu'il soit en langue russe, vous pourrez tout comprendre si vous activez les sous-titres anglais générés automatiquement.




Cet article a fourni de nombreuses informations théoriques sur le fonctionnement du démarrage. Cependant, pour vraiment comprendre ce processus, nous devons examiner de plus près le code source et l'architecture du micrologiciel existant.


Dans le prochain article, nous approfondirons le BIOS , l'UEFI et le coreboot pour les examiner en détail.

Ressources