Image of an arrow

Comment reprogrammer une EEPROM sous Linux

Avatar

evigier

EEPROMDans ce premier billet, je vous propose de démontrer qu’il est très simple de lire et écrire une EEPROM sous Linux. Malheureusement, en embarqué, les problèmes les plus simples se compliquent toujours. C’est pourquoi, dans un 2e billet, nous verrons comment contourner les petits soucis à l’aide de quelques connaissances au niveau de l’architecture matérielle, des pilotes linux et du bus i2c. Tout cela sans aucune compilation, mais avec un peu d’huile de coude.

Un problème?

Il y a quelques jours, un ingénieur matériel m’expose un problème délicat. Deux cent équipements ont été déployés mais ne fonctionnent pas car ils sont mal configurés. La configuration en question se trouve sur une mémoire non-volatile programmable de type EEPROM. Habituellement, les techniciens suivent la procédure qui suit:

  1. Démonter l’équipement de son support
  2. Démonter le boîtier
  3. Connecter un émulateur JTAG à l’équipement
  4. Reprogrammer la mémoire à l’aide de la connexion JTAG
  5. Remonter le boîtier
  6. Remonter l’équipement sur son support
  7. goto 1 et répéter pour les 200 équipements.

Ouch! Voilà qui risque d’être long! Bonne nouvelle, cependant : le système roule un Linux plutôt récent (2.6.30). On devrait donc pouvoir faire plus subtil en utilisant la méthode logicielle.

I-squared-C

Les EEPROM sont le plus souvent interfacées sur un bus i2c. L’i2c est un bus à 2 fils, normalisé par Philips en 1992, dont le protocole de communication maître/esclave est simple et très bien supporté par Linux. Dans un système Linux, les périphériques i2c se trouvent dans /sys/bus/i2c/devices.

# ls -l /sys/bus/i2c/devices
total 0
lrwxrwxrwx 1 root root 0 Feb 11 01:49 0-004c -> ../../../devices/e0000000.soc/e0003000.i2c/i2c-0/0-004c
lrwxrwxrwx 1 root root 0 Feb 11 01:49 0-0050 -> ../../../devices/e0000000.soc/e0003000.i2c/i2c-0/0-0050
lrwxrwxrwx 1 root root 0 Feb 11 01:49 0-0068 -> ../../../devices/e0000000.soc/e0003000.i2c/i2c-0/0-0068
lrwxrwxrwx 1 root root 0 Feb 11 01:49 1-0070 -> ../../../devices/e0000000.soc/e0003100.i2c/i2c-1/1-0070
lrwxrwxrwx 1 root root 0 Feb 11 01:49 2-0024 -> ../../../devices/e0000000.soc/e0003100.i2c/i2c-1/i2c-2/2-0024
lrwxrwxrwx 1 root root 0 Feb 11 01:49 2-004c -> ../../../devices/e0000000.soc/e0003100.i2c/i2c-1/i2c-2/2-004c
lrwxrwxrwx 1 root root 0 Feb 11 01:49 2-0054 -> ../../../devices/e0000000.soc/e0003100.i2c/i2c-1/i2c-2/2-0054
lrwxrwxrwx 1 root root 0 Feb 11 01:49 2-0055 -> ../../../devices/e0000000.soc/e0003100.i2c/i2c-1/i2c-2/2-0055
lrwxrwxrwx 1 root root 0 Feb 11 01:49 i2c-0 -> ../../../devices/e0000000.soc/e0003000.i2c/i2c-0
lrwxrwxrwx 1 root root 0 Feb 11 01:49 i2c-1 -> ../../../devices/e0000000.soc/e0003100.i2c/i2c-1
lrwxrwxrwx 1 root root 0 Feb 11 01:49 i2c-2 -> ../../../devices/e0000000.soc/e0003100.i2c/i2c-1/i2c-2

 

Le premier chiffre renseigne le numéro du bus sur lequel le périphérique est connecté (4). Le nombre suivant représente l’adresse hexadécimale (0x54) du périphérique. Celui-ci va répondre aux commandes contenant cette adresse et ignorer les commandes contenant une adresse différente.

Hexadécimal après la virgule

Habituellement les EEPROM sont programmées en hexadécimal, c’est à dire que leur contenu n’est pas lisible par un éditeur de texte classique. Une telle lecture ne retournera pas grand chose d’utile. Par exemple :

# cat /sys/bus/i2c/devices/4-0054/eeprom
♦®♦™♦©♦

 

Il existe cependant de nombreux outils sous Linux pour lire l’hexadécimal, comme hexdumpod ou xxd:

# od -x eeprom
0000000 4b5a 2020 2020 2020 2020 2020 2020 2020
0000020 2020 2020 2020 2020 2020 2020 2020 2020
0000040 2020 2020 2020 2020 2020 2020 2020 4e50
0000080 454e 3031 2020 2020 2020 2020 2020 2020

# hexdump -C eeprom
00000000  4b 5a 20 20 20 20 20 20  20 20 20 20 20 20 20 20  |KZ              |
00000010  20 20 20 20 20 20 20 20  20 20 20 20 20 20 20 20  |                |
00000020  20 20 20 20 20 20 20 20  20 20 20 20 20 20 4e 50  |              NP|
00000030  45 4e 30 31 20 20 20 20  20 20 20 20 20 20 20 20  |EN01            |

 

Pour éditer le contenu, il faudrait un éditeur hexadécimal. Malheureusement :

  1. Il est plutôt rare d’avoir ce genre d’outil disponible sur un Linux embarqué
  2. Certaines (vieilles) EEPROM ne peuvent pas être reprogrammées partiellement. On ne peut que tout effacer et tout réécrire.

Nous allons donc employer la méthode suivante :

  • Faire une copie locale
  • La transférer sur la machine de travail
  • Modifier la copie à l’aide d’un éditeur hexadécimal
  • Transférer la copie modifiée sur l’équipement
  • Reprogrammer l’EEPROM à l’aide du fichier modifié.

Pour la copie locale, on va utiliser dd :

# dd if=/sys/bus/i2c/devices/4-0054/eeprom of=/tmp/eeprom.orig conv=direct

 

C’est l’utilisation la plus simple de dd: on copie le contenu du fichier d’entrée (if: input file) vers le fichier de sortie (of: output file). L’option conv=direct empêche l’utilisation de mémoire tampon (cache) pour le transfert. Notez qu’on aurait aussi pu utiliser un simple cp, ici.

Passons au transfert sur la machine de travail. L’équipement est connecté en ethernet et dispose d’un client FTP embarqué (busybox) qui permet de transférer le fichier facilement. Si votre équipement est équipé d’un serveur SSH (dropbear), pensez aussi à scp. Dernièrement, je suis tombé sur un équipement ne disposant ni d’un serveur, ni d’un client ssh ou FTP. Eh oui, ça existe! Heureusement, netcat était présent et la copie a pu se faire ainsi :

(target) $ nc -w 3 192.168.1.22 1234 < ~/tmp/eeprom.orig
(host)   # nc -l -p 1234 > ~/eeprom.orig

 

Place à la modification. Si votre poste de travail est sous Linux, vous pouvez éditer le fichier en mode hexadécimal avec vim etxxd ou l’outil graphique bless. Sous Windows, jetez un oeil à frhed. Sous Mac OS, regardez HexEdit. La modification terminée, on ramène le fichier modifié eeprom.new sur l’équipement. Puis on réécrit l’EEPROM, toujours avec dd:

# dd if=/tmp/eeprom.new of=/sys/bus/i2c/devices/4-0054/eeprom conv=direct

 

Ecran bleu sous Linux

Vous pouvez essayer chez vous, c’est sans danger et cela devrait fonctionner. Dans mon cas, j’ai eu droit à une jolie error: permission denied. Réfléchissons. Nous sommes connectés en tant que root, essayons (naïvement) de changer les droits d’accès:

# chmod 777 /sys/bus/i2c/devices/4-0054/eeprom
# ls -l /sys/bus/i2c/devices/4-0054/eeprom
-rwxrwxrwx 1 root root    0 fév 28 21:57 eeprom

# dd if=/tmp/eeprom.new of=/sys/bus/i2c/devices/4-0054/eeprom conv=direct
error: permission denied

 

ideeOn dirait que cela ne va pas être aussi simple que prévu.

Comment s’en sortir dans ce cas-là?
Avez-vous une idée?

Solution au prochain épisode!

Comments are closed.


Articles similaires

Image of an arrow

Comment apporter des capacités de communication entièrement distribuées et sécurisées aux produits embarqués et à l’IOT (Partie 2). [L’introduction est en français, le reste du texte en anglais] Dans un précédent article, nous vous présentions notre travail sur l’ajout de Jami dans Yocto. C’était un grand pas pour l’utilisation de Jami sur tous types d’appareils. […]

Comment apporter des capacités de communication entièrement distribuées et sécurisées aux produits embarqués et à l’IOT (Partie 1). [L’introduction est en français, le reste du texte en anglais] Jami est un outil de communication développé par Savoir-faire Linux. Il est disponible sur Windows, MacOS, des distributions Linux standards comme Ubuntu ou Fedora et sur smartphones […]

[L’introduction est en français, le reste du texte en anglais] Linux avec l’option PREEMPT_RT peut permettre d’exécuter un kernel moderne et robuste sur des plateformes matérielles anciennes et aux performances limitées. Dans le cadre d’un parc matérielle en service, ces briques logicielles peuvent vous permettre d’éviter une coûteuse campagne de rappel. Ce sujet sera traité […]

[L’introduction est en français, le reste du texte en anglais] Le premier article de cette série présentait les motivations et les avantages de l’intégration d’une image de conteneur dans un système Linux embarqué et examinait les défis que ce nouveau paradigme soulève. Le second article présentait différentes approches pour intégrer un conteneur dans le système […]

Thumbnail image

[L’introduction est en français, le reste du texte en anglais] Points clés: La série de correctifs PREEMPT_RT permet au noyau Linux de répondre aux besoins des systèmes temps-réel. Différents réglages permettent un compromis entre performance et latence. Un paquet de support de carte minimal permet une réduction de la latence. Les mesures de durcissement du […]