Agencement de la mémoire flash
Il y a les disques durs qui sont considérés comme des périphériques blocs, et il y a la mémoire flash. Il y a différents types de mémoire flash comme: NOR, SLC NAND et MLC NAND.
Si le circuit intégré (peu importe le type) est directement connecté au SoC et doit être adressé directement par Linux, on l'appelle “raw flash” (mémoire flash brute).
Si le circuit intégré ne peut pas être adressé directement par le système d'exploitation (parce qu'il y a un composant contrôleur additionnel entre lui et le SoC), on l'appelle “FTL (Flash Translation Layer) flash”. Les logiciels embarqués utilisent presqu'exclusivement de la “raw flash”, tandis que les clés USB utilisent presqu'exclusivement de la “FTL flash”!
Partitionnement des images SquashFS
Le composant flash, sur les systèmes embarqués, n'est pas accompagné par un composant contrôleur, et par conséquent, n'est pas un composant “FTL” mais un composant “raw flash”. L'espace de stockage est traité et adressé comme un MTD (Memory Technology Device) et des système de fichiers spéciaux sont utilisés. L'espace de stockage n'est pas partitionné de manière traditionnelle, dans laquelle vous stockez les informations relatives aux partitions dans le MBR et les PBRs, mais c'est fait dans le Noyau Linux (et parfois indépendamment dans le chargeur d'amorçage !). Vous définissez simplement, que la “partition noyau commence à l'offset x et se termine à l'offset y”. L'avantage de cette méthode, c'est que, plus tard, vous pouvez adresser ces partitions par nom, plutôt qu'en précisant le point de départ précis des données.
Le document suivant, présentant l'arrangement mémoire du TL-WR1043ND en est un pur exemple! Un autre exemple, légèrement différent, est disponible à la page du wiki DIR-300. Ainsi donc, les arrangements de la mémoire diffèrent d'un routeur à l'autre ! Reportez-vous à la page de wiki de votre routeur, pour connaître son arrangement particulier et vérifiez le vous même sur votre routeur.
TP-Link WR1043ND Arrangement de la mémoire Flash | |||||
---|---|---|---|---|---|
Couche0 | m25p80 spi0.0: m25p64 8192KiB | ||||
Couche1 | mtd0 u-boot 128KiB | mtd5 firmware 8000KiB | mtd4 art 64KiB | ||
Couche2 | mtd1 kernel 1280KiB | mtd2 rootfs 6720KiB | |||
Point de montage | / | ||||
Système de fichiers | mini_fo/overlayfs | ||||
Couche3 | mtd3 rootfs_data 5184KiB | ||||
Taille en KO | 128KiB | 1280KiB | 1536KiB | 5184KiB | 64KiB |
Nom | u-boot | kernel | rootfs_data | art | |
Point de montage | aucun | aucun | /rom | /overlay | aucun |
Système de fichiers | aucun | aucun | SquashFS | JFFS2 | aucun |
Partitions
Comme les partitions sont imbriquées, cet ensemble peut être vu en couches :
- Couche0: nous avons le composant flash, d'une taille de 8MiB , qui est soudé au circuit imprimé et connecté au soc via le SPI (Serial Peripheral Interface Bus)(Bus d'Interface Série).
- Couche1: nous “partitionnons” l'espace en mtd0 pour le chargeur d'amorçage, mtd5 pour le firmware et, dans ce cas, mtd4 pour l'ART (Atheros Radio Test) - il contient les adresses MAC et les données de calibration pour le sans fil (EEPROM). S'il est manquant ou corrompu,
ath9k
(pilote du sans fil) ne démarrera pas. - Couche2: nous subdivisons mtd5 (firmware) en mtd1 (noyau) et mtd2 (rootfs); Dans le processus de génération du firware, (voir imagebuilder) le fichier binaire du noyau est le premier empaqueté avec le LZMA, puis, le fichier résultant est empaqueté avec gzip et finalement, ce fichier est écrit dans la mémoire raw flash (mtd1) sans faire partie d'aucun système de fichiers !
- Couche3: nous subdivisons rootfs encore plus en mtd3 pour les données rootfs_data et le reste pour une partition sans nom qui recevra la partition SquashFS.
Systèmes de fichiers
Points de montage
/
c'est votre système de fichiers racine dans son intégralité ; il comprend/rom
et/overlay
. Ignorez/rom
et/overlay
et utilisez exclusivement/
pour vos routines courantes!
/rom
contient tous les fichiers de base, commebusybox
,dropbear
ouiptables
y compris les fichiers de configuration par défaut. Elle ne contient pas le noyau. Les fichiers de ce dossier sont sur la partition SqashFS , et par conséquent ne peuvent être effacés. Mais, comme nous utilisons le système de fichiers mini_fo, aussi appelé overlay-whiteout-des liens symboliques peuvent être créés sur la partition JFFS2./overlay
est la partie inscriptible de système de fichiers qui est fusionné/rom
pour créer un -arbre-/
uniforme. Elle contient tout ce qui a été écrit dans le routeur après l'installation, comme les fichiers de configuration modifiés, les paquets additionnels installés avecopkg
, etc. Elle est formaté en JFFS2.
Plutôt que d'effacer les fichiers, insérez un whiteout, une entrée spéciale haute priorité qui marque le fichier comme effacé. Le système de fichiers, quand il voit une entrée whiteout pour le fichier F, se comporte comme si le fichier F n'existait pas.
#!/bin/bash # shows all overlay-whiteout symlinks find /overlay -type l | while read FILE do [ -z "$FILE" ] && break if ls -la "$FILE" 2>&- | grep -q '(overlay-whiteout)'; then echo "$FILE" fi done
hiérarchie des systèmes de fichiers
NOTE1
: si le noyau faisait partie de la partition SquashFS, nous ne pourrions contrôler à quel emplacement exact dans la mémoire flash il serait écrit (dans quels blocs se trouveraient ses données). Par conséquent, nous ne pourrions nous contenter de dire au chargeur d'amorçage de charger et exécuter certains blocs sur la mémoire flash, mais nous devrions l'adresser avec un chemin et un nom de fichier. Ce ne serait pas mauvais en soi, mais pour le faire, le chargeur d'amorçage aurait à connaître et comprendre le système de fichier SquashFS, ce qui n'est pas le cas. Les chargeurs d'amorçage embarqués que nous utilisons avec OpenWrt ne comprennent pas le concept de système de fichiers et, par conséquent, sont incapables d'adresser un fichier par chemin/nom.Le mieux qu'il fassent, c'est de supposer que le début de la section trx data est du code exécutable.
NOTE2
: la dénomination “firmware”
est généralement employée pour l'intégralité des données de la mémoire flash, y compris le chargeur d'amorçage et les autres données nécessaires au fonctionnement du routeur, comme ART, NVRAM, FIS, etc, mais nous l'employons aussi pour désigner la partie ré-inscriptible. Ne vous laissez pas embrouiller par cela.
Partitionnement des images JFFS2
TODO
Découverte (Comment trouver)
cat /proc/mtd dev: size erasesize name mtd0: 00020000 00010000 "u-boot" mtd1: 00140000 00010000 "kernel" mtd2: 00690000 00010000 "rootfs" mtd3: 00530000 00010000 "rootfs_data" mtd4: 00010000 00010000 "art" mtd5: 007d0000 00010000 "firmware"
Le champ erasesize est la taille de bloc de la mémoire flash, en l'occurrence 64KiB. Cette taille est écrite en valeur hexadécimales little ou big endian en Octets. Dans le cas de little endian, vous commutez en mole hexa et entrez 02 0000 dans l'ordinateur par exemple et convertissez en décimal (en re-commutant en mode décimal). Puis estimez estimez commant elles sont imbriquées l'une dans l'autre. Ou bien, exécutez dmesg
juste après un boot et voyez quelque chose comme :
Creating 5 MTD partitions on "spi0.0": 0x000000000000-0x000000020000 : "u-boot" 0x000000020000-0x000000160000 : "kernel" 0x000000160000-0x0000007f0000 : "rootfs" mtd: partition "rootfs" set to be root filesystem mtd: partition "rootfs_data" created automatically, ofs=2C0000, len=530000 0x0000002c0000-0x0000007f0000 : "rootfs_data" 0x0000007f0000-0x000000800000 : "art" 0x000000020000-0x0000007f0000 : "firmware"
Ce sont les offsets de début et de fin des partitions en valeur hexa-décimales représentant des Octets.Maintenant, vous n'avez plus besoin de supposer qui est inclus dans qui.Ex : 02 0000 = 131.072 Bytes = 128KiB
Details
Générique
La mémoire flash peut être vue comme un grand bloc d'espace continu:
début de la mémoire flash ................. fin de la mémoire flash |
Il n'y a pas de ROM à partir de laquelle booter; à la mise sous tension, le CPU commence à exécuter le code au tout début de la mémoire flash. Fort heureusement, il ne s'agit pas du firmware, sinon nous serions en réel danger à chaque ré-écriture du firmware. Le démarrage est en fait pris en charge par une section de code que nous avons tendance à appeler chargeur d'amorçage (le BIOS de votre PC est un chargeur d'amorçage).
Partition du chargeur d'amorçage | Partition du firmware | Données spéciale de configuration |
|||
---|---|---|---|---|---|
Atheros | U-Boot | firmware | ART |
||
Broadcom | CFE | firmware | NVRAM |
||
Atheros | RedBoot | firmware | FIS recovery | RedBoot config | boardconfig |
La (ou les) partition(s) contenant les données spéciales de configuration diffèrent beaucoup entre elles.Exemple: la partitionART
' que l'on rencontre concomitamment avec Atheros-Wireless et U-Boot, ne contient que les données relatives au pilote sans fil, tandis que la partition NVRAM
des routeurs Broadcom est utilisée pour bien d'autres choses en plus.
Broadcom avec CFE
Si vous plongez dans la section “firmware”, vous trouverez un trx. Un trx n'est qu'une encapsulation qui ressemble à ceci :
trx-header (entête trx) | ||||||
---|---|---|---|---|---|---|
HDR0 | length | crc32 | flags | pointers | data |
“HDR0” est un nombre magique pour indiquer une entête trx, le reste est une valeur non signée de 4 octets suivie par le contenu réel. En bref, c'est un bloc de données avec une longueur et une somme de contrôle. Ainsi, l'utilisation de notre mémoire flash ressemble à ceci :
CFE | trx contenant le firmware | NVRAM |
Sauf que le firmware est en général très petit et n'occupe pas l'espace entier en CFE et NVRAM :
CFE | trx firmware | unused | NVRAM |
(NOTE
: The <model>.bin files are nothing more than the generic *.trx file with an additional header appended to the start to identify the model. The model information gets verified by the vendor's upgrade utilities and only the remaining data -- the trx -- gets written to the flash. When upgrading from within OpenWrt remember to use the *.trx file.)
So what exactly is the firmware?
The boot loader really has no concept of filesystems, it pretty much assumes that the start of the trx data section is executable code. So, at the very start of our firmware is the kernel. But just putting a kernel directly onto flash is quite boring and consumes a lot of space, so we compress the kernel with a heavy compression known as LZMA. Now the start of firmware is code for an LZMA decompress:
lzma decompress | lzma compreszsed kernel |
Now, the boot loader boots into an LZMA program which decompresses the kernel into memory and executes it. It adds one second to the bootup time, but it saves a large chunk of flash space. (And if that wasn't amusing enough, it turns out the boot loader does know gzip compression, so we gzip compressed the LZMA decompression program)
Immediately following the kernel is the filesystem. We use SquashFS for this because it's a highly compressed readonly filesystem -- remember that altering the contents of the trx in any way would invalidate the crc, so we put our writable data in a JFFS2 partition, which is outside the trx. This means that our firmware looks like this:
trx | gzip'd lzma decompress | lzma'd kernel | (SquashFS filesystem) |
And the entire flash usage looks like this -
CFE | trx | gz'd lzma | lzma'd kernel | SquashFS | JFFS2 filesystem | NVRAM |
That's about as tight as we can possibly pack things into flash.