Booter un raspberry Pi 4 B sur un SSD : attention à l'interface !

Quand vous avez fait tout ce qui est dit dans la doc 28 fois et que ça ne marche toujours pas.

6 minute de lecture
Par Stéphane
Booter un raspberry Pi 4 B sur un SSD : attention à l'interface !

Mon boitier préféré pour coller un SSD avec son interface USB est celui-ci car il suffit de le regarder pour connaitre la taille du SSD qui est dedans. De plus il coûte moins de 10€ livraison comprise !

Je précise tout de suite que mes Pi sont headless, c'est à dire sans écran connecté, et je n'ai même pas d'adaptateur pour ce faire. Comme ils fonctionnent en mode serveur, je n'ai pas besoin d'écran, ssh suffit.

Revenons au sujet de l'article. Les références du boitier et son interface sont les suivantes :

  • Product: JMS578
  • Manufacturer: JMicron
Comme la publicité le montre, il est "compatible" avec tous les systèmes.

Pour ceux qui veulent la documentation complète, elle se trouve en bas de page.

Je lui ai mis un disque de 480 Go dedans, et j'ai installé un système Linux dessus afin de pouvoir le relier à mon Raspberry Pi 4 B. Et c'est là que les ennuis ont commencés.

D'abord, il faut faire quelques petits réglages afin que le RasPi puisse démarrer sur un périphérique USB et non sur la carte SD. Il y a plein de raison de vouloir faire ça les deux principales sont la rapidité et la fiabilité des SSD bien supérieure au carte flash SD. Surtout sur un modèle 4.

Penser à mettre à jour l'EEPROM

En suivant les indications du site raspberrypi.org on trouve facilement les instructions pour mettre le système à jour. Il faut en particulier que l'EEPROM (une petite mémoire que l'on peut normalement seulement lire) soit à jour, comme indiqué dans le chapitre Raspberry Pi 4 boot EEPROM.

Mon système est à jour :

$ sudo rpi-eeprom-update -a
BCM2711 detected
VL805 firmware in bootloader EEPROM
BOOTLOADER: up-to-date
CURRENT: Fri 11 Dec 11:15:17 UTC 2020 (1607685317)
 LATEST: Thu  3 Sep 12:11:43 UTC 2020 (1599135103)
 FW DIR: /lib/firmware/raspberrypi/bootloader/critical
VL805: up-to-date
CURRENT: 000138a1
 LATEST: 000138a1

$ vcgencmd bootloader_version
Dec 11 2020 11:15:17
version c3f26b6070054bca030366de2550d79ddae1207a (release)
timestamp 1607685317
update-time 1608777319
capabilities 0x0000001f

$ ls -l /lib/firmware/raspberrypi/bootloader/stable/
total 2856
-rw-r--r-- 1 root root 524288 Apr 23  2020 pieeprom-2020-04-16.bin
-rw-r--r-- 1 root root 524288 Jun 17  2020 pieeprom-2020-06-15.bin
-rw-r--r-- 1 root root 524288 Jul 20 12:17 pieeprom-2020-07-16.bin
-rw-r--r-- 1 root root 524288 Aug 10 14:17 pieeprom-2020-07-31.bin
-rw-r--r-- 1 root root 524288 Sep  7 14:35 pieeprom-2020-09-03.bin
-rw-r--r-- 1 root root  98196 Sep  7 14:35 recovery.bin
-rw-r--r-- 1 root root  98904 Feb 28  2020 vl805-000137ad.bin
-rw-r--r-- 1 root root  99224 Jul 20 12:17 vl805-000138a1.bin

Et pourtant, au boot la led verte clignote 4 fois très rapidement, et celle du contrôleur du SSD une fois par seconde (en alternance avec la verte). Étant donné que le système cherche à booter alternativement sur la SD et sur le USB :

$ sudo rpi-eeprom-config |grep ORDER
BOOT_ORDER=0xf41

cela me parait normal. Alors pourquoi ça démarre pas ? Je peux faire des fsck sans problème sur le SSD, et même le monter  mount -t vfat /dev/sda1 /mnt ou mount /dev/sda2 /mnt sans problème. J'ai tout essayé pour créer l'image sur le SSD, la dernière mouture étant de le faire par dd.

Trouver le message d'erreur

Au final, je me suis dis que j'avais peut être un problème de câble. J'ai repensé aux années 1995/2000 quand on se battait entres toutes les normes SCSI disponibles à l'époque (SCSI1, 2, 3, SE, LVD, etc.), et les câbles et connecteurs qui allaient avec. Donc, je fais un dmesg | tail et là, oh! surprise :

[   35.694527] sd 0:0:0:0: [sda] tag#21 uas_eh_abort_handler 0 uas-tag 2 inflight: CMD IN
[   35.694544] sd 0:0:0:0: [sda] tag#21 CDB: opcode=0x28 28 00 37 e4 35 b8 00 00 48 00
[   37.614509] sd 0:0:0:0: [sda] tag#20 uas_eh_abort_handler 0 uas-tag 1 inflight: CMD IN
[   37.614518] sd 0:0:0:0: [sda] tag#20 CDB: opcode=0x28 28 00 00 08 1f 80 00 00 08 00
[   37.654510] scsi host0: uas_eh_device_reset_handler start
[   37.805203] usb 2-1: reset SuperSpeed Gen 1 USB device number 2 using xhci_hcd
[   37.838602] scsi host0: uas_eh_device_reset_handler success

Clairement, il y a un truc qui va pas. UAS c'est USB Attached SCSI, ce qui veut dire qu'en gros on va passer des commandes SCSI (rapides) sur l'USB plutôt que des commandes USB (lentes).

Pour être sûr, je lance un tail -f /var/log/syslog en & et puis un fsck :

$ sudo fsck /dev/sda1
fsck from util-linux 2.33.1
Dec 24 22:22:51 raspberrypi kernel: [ 3248.556136] sd 0:0:0:0: [sda] tag#19 uas_eh_abort_handler 0 uas-tag 3 inflight: CMD IN
Dec 24 22:22:51 raspberrypi kernel: [ 3248.556153] sd 0:0:0:0: [sda] tag#19 CDB: opcode=0x28 28 00 00 08 1f 88 00 00 68 00
Dec 24 22:22:51 raspberrypi kernel: [ 3248.596144] scsi host0: uas_eh_device_reset_handler start
Dec 24 22:22:51 raspberrypi kernel: [ 3248.747178] usb 2-1: reset SuperSpeed Gen 1 USB device number 2 using xhci_hcd
Dec 24 22:22:51 raspberrypi kernel: [ 3248.782058] scsi host0: uas_eh_device_reset_handler success
fsck.fat 4.1 (2017-01-24)
/dev/sda1: 252 files, 110096/516190 clusters

Pas de doute, c'est le contrôleur qui déconne.

Retour à la doc.

RTFM

La doc s'appelle : If you have a Raspberry Pi 4 and are getting bad speeds transferring data to/from USB3.0 SSDs, read this

Elle dit en substance ceci :

  • avant le Raspberry Pi 4, l'USB était trop lent pour qu'on accepte le protocole UAS. Le modèle 4 le supporte lui.
  • les constructeurs d'interfaces USB font ce qu'ils veulent, et ne respectent pas toujours bien la norme UAS.
  • un symptôme est la lenteur des débits USB.
  • l'autre symptôme ce sont des déconnexions signalées par : scsi host6: uas_eh_device_reset_handler start ... scsi host6: uas_eh_device_reset_handler success

Solution

La solution consiste donc à interdire le mode UAS pour cette interface (JMicron 578). Pour cela il faut éditer le fichier /boot/cmdline.txt et rajouter devant : usb-storage.quirks=152d:0578:u

$ cat /boot/cmdline.txt
usb-storage.quirks=152d:0578:u console=serial0,115200 console=tty1 root=PARTUUID=ee4fbebf-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait

à noter que le 152d et 0578 proviennent des messages affichés par dmesg quand on tente d'accéder au SSD :

Dec 24 22:42:27 raspberrypi kernel: [ 4424.471482] sd 0:0:0:0: [sda] Synchronizing SCSI cache
Dec 24 22:42:27 raspberrypi kernel: [ 4425.071290] sd 0:0:0:0: [sda] Synchronize Cache(10) failed: Result: hostbyte=0x07 driverbyte=0x00
Dec 24 22:42:35 raspberrypi kernel: [ 4432.311892] usb 2-1: new SuperSpeed Gen 1 USB device number 3 using xhci_hcd
Dec 24 22:42:35 raspberrypi kernel: [ 4432.343270] usb 2-1: New USB device found, idVendor=152d, idProduct=0578, bcdDevice= 2.04
Dec 24 22:42:35 raspberrypi kernel: [ 4432.343290] usb 2-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
Dec 24 22:42:35 raspberrypi kernel: [ 4432.343307] usb 2-1: Product: JMS579
Dec 24 22:42:35 raspberrypi kernel: [ 4432.343323] usb 2-1: Manufacturer: JMicron
Dec 24 22:42:35 raspberrypi kernel: [ 4432.343338] usb 2-1: SerialNumber: 5002627783926619

Performances

En écriture sur le SSD, en gros 128 Mo/s soit 1Gbit/s :

 $ time dd if=/dev/zero of=bigfile bs=1M count=1000 conv=fsync
1000+0 records in
1000+0 records out
1048576000 bytes (1.0 GB, 1000 MiB) copied, 8.17308 s, 128 MB/s

real    0m8.840s
user    0m0.000s
sys     0m5.687s
$ time dd if=/dev/zero of=bigfile bs=10M count=100 conv=fsync
100+0 records in
100+0 records out
1048576000 bytes (1.0 GB, 1000 MiB) copied, 8.20822 s, 128 MB/s

real    0m8.880s
user    0m0.000s
sys     0m5.766s
Avec dd commande plutôt représentative.
$ sudo hdparm -tT /dev/sda
/dev/sda:
 Timing cached reads:   1602 MB in  2.00 seconds = 801.58 MB/sec
 Timing buffered disk reads: 816 MB in  3.00 seconds = 271.81 MB/sec
Avec hdparm utilitaire spécialisé.

Conclusion

J'espère que cela vous sera utile, parce que j'ai perdu beaucoup de temps sur ce bug ! Le prochain article sera dédié à l'adaptateur USB/SATA qui marchera sans problème, et sera plus rapide.

N'hésitez pas à laisser un commentaire !