Vues : 30
Ubuntu Core (UC) est la prise de Canonical dans l’espace IoT. Il existe des images pré-construites pour les appareils officiellement pris en charge, comme Raspberry Pi ou Intel NUC, mais pour d’autres conseils, quand il n’y a pas de port communautaire, il faut en créer un par eux-mêmes. C’est le cas si l’on veut exécuter Ubuntu Core 18 sur Nvidia Jetson TX1 par exemple. Des instructions de haut niveau sur la façon de le faire se trouvent dans les documents officiels. Le processus est simple une fois que nous avons deux composants critiques: le noyau et le gadget snap.
La création de ces clichés n’est pas nécessairement complexe, mais il peut y avoir des bosses dans la route si vous êtes nouveau à la tâche. Dans ce post, j’explique comment je les ai créés pour le conseil de kit de développeur Jetson TX1, et comment ils ont été utilisés pour créer une image UC pour ledit appareil, en espérant que cela fournira de nouvelles astuces pour les pirates travaillant sur les ports pour d’autres appareils. Toutes les sources pour les clichés et les
scripts de construction sont disponibles dans github:
https://github.com/alfonsosanchezbeato/jetson-kernel-snap
https://github.com/alfonsosanchezbeato/jetson-gadget-snap
https://github.com/alfonsosanchezbeato/jetson-ubuntu-core
Alors, commençons par…
Table des matières
Le snap de noyau
Le noyau Linux que nous allons utiliser a besoin de quelques options de configuration du noyau pour être activé, et il est également particulièrement important qu’il a une version moderne de l’apparmor afin snaps peuvent être correctement confinés. Le noyau officiel jetson est la version 4.4, qui est assez vieux, mais heureusement Canonical a une référence 4.4 noyau avec tous les correctifs nécessaires pour les snaps backported. Sachant cela, nous sommes une commande loin d’obtenir les correctifs que nous allons utiliser sur le noyau Nvidia. Les correctifs incluent également des fichiers avec les options de configuration dont nous avons besoin pour les clichés, ainsi que quelques modifications afin que le snap pourrait être compilé avec succès sur Ubuntu 18.04 bureau.git format-patch
Une fois que nous avons les sources, nous avons besoin, bien sûr, de créer un fichier snapcraft.yamil qui décrira comment construire le noyau snap. Nous allons marcher à travers elle, en soulignant les parties plus spécifiques à l’appareil Jetson.
En commençant par la partie noyau, il s’avère que nous ne pouvons pas utiliser facilement le plugin de noyau, en raison de la façon particulière dont le noyau doit être construit: Nvidia distribue une partie des pilotes nécessaires comme dépôts distincts à celui utilisé par l’arborescence du noyau principal. Par conséquent, j’ai eu recours à l’utilisation du plugin zéro afin que je puisse écrire à la main les commandes pour faire la construction.
L’étape de traction qui en a résulté est
override-pull: | snapcraftctl pull # Get kernel sources, which are distributed across different repos ./source_sync.sh -k tegra-l4t-r28.2.1 # Apply canonical patches - apparmor stuff essentially cd sources/kernel/display git am ../../../patch-display/* cd - cd sources/kernel/kernel-4.4 git am ../../../patch/*
qui exécute un script pour récupérer les sources (j’ai tiré ce script de Nvidia Linux pour Tegra -L4T- distribution) et applique des correctifs canoniques.
L’étape de construction est un peu plus de lignes, alors j’ai décidé d’utiliser un script externe pour l’implémenter. Nous allons analyser maintenant certaines parties de celui-ci. Pour la configuration du noyau, nous ajoutons tous les bits Ubuntu nécessaires :
make "$JETSON_KERNEL_CONFIG" \ snappy/containers.config \ snappy/generic.config \ snappy/security.config \ snappy/snappy.config \ snappy/systemd.config
Ensuite, pour faire la construction que nous courons
make -j"$num_cpu" Image modules dtbs
Une prise intéressante ici est que les fichiers zImage ne sont pas pris en charge en raison de l’absence d’une implémentation de décompresseur dans le noyau arm64. Nous devons donc construire une image non compressée à la place.
Après un code qui met en scène les fichiers construits afin qu’ils soient inclus dans le snap plus tard, nous récupérons les initramfs à partir du snap de base. Cette étape est généralement cachée de nous par le plugin noyau, mais cette fois nous devons le coder nous-mêmes:
# Get initramfs from core snap, which we need to download core_url=$(curl -s -H "X-Ubuntu-Series: 16" -H "X-Ubuntu-Architecture: arm64" \ "https://search.apps.ubuntu.com/api/v1/snaps/details/core?channel=stable" \ | jq -r ".anon_download_url") curl -L "$core_url" > core.snap # Glob so we get both link and regular file unsquashfs core.snap "boot/initrd.img-core*" cp squashfs-root/boot/initrd.img-core "$SNAPCRAFT_PART_INSTALL"/initrd.img ln "$SNAPCRAFT_PART_INSTALL"/initrd.img "$SNAPCRAFT_PART_INSTALL"/initrd-"$KERNEL_RELEASE".img
Pour en revenir à la recette snapcraft, nous avons également une partie initramfs, qui prend soin de faire quelques changements à l’initramfs par défaut expédiés par UC:
initramfs: after: [ kernel ] plugin: nil source: ../initramfs override-build: | find . | cpio --quiet -o -H newc | lzma >> "$SNAPCRAFT_STAGE"/initrd.img
Ici, nous profitons du fait que les initramfs peuvent être construits comme une vanité d’archives cpio comprimées. Lorsque le noyau le décompresse, les fichiers inclus dans les archives ultérieures remplacent les fichiers des premiers, ce qui nous permet de modifier facilement les fichiers dans les initramfs sans avoir à changer celui expédié avec le noyau. Le changement que nous faisons ici est une modification du script redimensionner qui permet UC d’obtenir tout l’espace libre dans le disque sur la première botte. La modification permet de s’assurer que cela se produit dans le cas où la partition est déjà prise tout l’espace disponible, mais le système de fichiers ne le fait pas. Nous pourrions supprimer cette modification lorsque ces changements atteignent le snap de base, chose qui se produira éventuellement.
La dernière partie de ce snap est la partie firmware:
firmware: plugin: nil override-build: | set -xe wget https://developer.nvidia.com/embedded/dlc/l4t-jetson-tx1-driver-package-28-2-ga -O Tegra210_Linux_R28.2.0_aarch64.tbz2 tar xf Tegra210_Linux_R28.2.0_aarch64.tbz2 Linux_for_Tegra/nv_tegra/nvidia_drivers.tbz2 tar xf Linux_for_Tegra/nv_tegra/nvidia_drivers.tbz2 lib/firmware/ cd lib; cp -r firmware/ "$SNAPCRAFT_PART_INSTALL" mkdir -p "$SNAPCRAFT_PART_INSTALL"/firmware/gm20b cd "$SNAPCRAFT_PART_INSTALL"/firmware/gm20b ln -sf "../tegra21x/acr_ucode.bin" "acr_ucode.bin" ln -sf "../tegra21x/gpmu_ucode.bin" "gpmu_ucode.bin" ln -sf "../tegra21x/gpmu_ucode_desc.bin" "gpmu_ucode_desc.bin" ln -sf "../tegra21x/gpmu_ucode_image.bin" "gpmu_ucode_image.bin" ln -sf "../tegra21x/gpu2cde.bin" "gpu2cde.bin" ln -sf "../tegra21x/NETB_img.bin" "NETB_img.bin" ln -sf "../tegra21x/fecs_sig.bin" "fecs_sig.bin" ln -sf "../tegra21x/pmu_sig.bin" "pmu_sig.bin" ln -sf "../tegra21x/pmu_bl.bin" "pmu_bl.bin" ln -sf "../tegra21x/fecs.bin" "fecs.bin" ln -sf "../tegra21x/gpccs.bin" "gpccs.bin"
Ici, nous téléchargeons quelques fichiers afin que nous puissions ajouter blobs firmware à la snap. Ces fichiers sont séparés des sources de noyau Nvidia.
Donc, c’est pour le noyau snap, maintenant vous avez juste besoin de suivre les instructions pour le faire construire.
Le snap gadget
Il est temps maintenant de jeter un oeil à la photo gadget. Tout d’abord, je recommande de commencer par lire le post de grande ogra sur les clichés gadget pour les appareils avec bootloader you-boot avant de passer par cette section. Maintenant, comme pour le noyau un, nous allons passer par les différentes parties qui sont définies dans le fichier snapcraft.yamil. Le premier construit le binaire u-boot :
uboot: plugin: nil source: git://nv-tegra.nvidia.com/3rdparty/u-boot.git source-type: git source-tag: tegra-l4t-r28.2 override-pull: | snapcraftctl pull # Apply UC patches + bug fixes git am ../../../uboot-patch/*.patch override-build: | export ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make p2371-2180_defconfig nice make -j$(nproc) cp "$SNAPCRAFT_PART_BUILD"/u-boot.bin $SNAPCRAFT_PART_INSTALL"/
Nous avons décidé à nouveau d’utiliser le plugin zéro que nous avons besoin de faire quelques bizarreries spéciales. Les sources sont tirées du référentiel u-boot de Nvidia, mais nous appliquons quelques correctifs sur le dessus. Ces patchs, ainsi que l’environnement uboot, fournissent
- Prise en charge du chargement du noyau UC et des initramfs à partir du disque
- Prise en charge de la fonctionnalité de retour en cas de erreur d’installation d’un noyau ou d’un élément de rupture de noyau
- Corrections de bogues pour le sous-système ext4 de you-boot – requis parce que la fonctionnalité de retour vient d’être mentionnée doit appeler la commande u-boot , qui s’est avérée être cassée pour les systèmes de fichiers ext4 dans le u-boot de Tegra
saveenv
Plus d’informations sur les spécificités des correctifs you-boot pour UC peuvent être trouvés dans ce grand blog.
La seule autre partie que le snap a est uboot-env:
uboot-env: plugin: nil source: uboot-env override-build: | mkenvimage -r -s 131072 -o uboot.env uboot.env.in cp "$SNAPCRAFT_PART_BUILD"/uboot.env "$SNAPCRAFT_PART_INSTALL"/ # Link needed for ubuntu-image to work properly cd "$SNAPCRAFT_PART_INSTALL"/; ln -s uboot.env uboot.conf build-packages: - u-boot-tools
Cela code simplement le fichier dans un format lisible par u-boot. Le fichier résultant, , est inclus dans le snap.uboot.env.in
uboot.env
Cet environnement est l’endroit où la plupart de la prise en charge de l’UC est codée. Je ne vais pas trop plonger dans les détails, mais je veux juste mentionner que les variables qui doivent être modifiées généralement pour les nouveaux appareils sont
devnum
, et pour définir la partition de démarrage système, à partir de laquelle nous chargeons le noyau et les initramfspartition
devtype
fdtfile
, et pour déterminer le nom de l’arborescence du périphérique et l’endroit où il doit être chargé dans la mémoirefdt_addr_r
fdt_high
ramdisk_addr_r
et de définir l’emplacement de chargement des initramfsinitrd_high
kernel_addr_r
pour définir où le noyau doit être chargéargs
contient des arguments de noyau et doit être adapté aux spécificités de l’appareil- Enfin, pour cet appareil, a été changé de sorte qu’il a utilisé au lieu de , car nous ne pouvions pas utiliser un noyau comprimé comme expliqué ci-dessus
snappy_boot
booti
bootz
Outre la recette snapcraft, l’autre fichier obligatoire lors de la définition d’un gadget snap est le fichier gadget.yamil. Ce fichier définit, entre autres, la disposition de partitionnement d’image. Il ya plus à elle, mais dans ce cas, le partitionnement est la seule chose que nous avons défini:
volumes: jetson: bootloader: u-boot schema: gpt structure: - name: system-boot role: system-boot type: 0FC63DAF-8483-4772-8E79-3D69D8477DE4 filesystem: ext4 filesystem-label: system-boot offset: 17408 size: 67108864 - name: TBC type: EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 size: 2097152 - name: EBT type: EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 size: 4194304 - name: BPF type: EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 size: 2097152 - name: WB0 type: EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 size: 6291456 - name: RP1 type: EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 size: 4194304 - name: TOS type: EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 size: 6291456 - name: EKS type: EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 size: 2097152 - name: FX type: EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 size: 2097152 - name: BMP type: EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 size: 134217728 - name: SOS type: EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 size: 20971520 - name: EXI type: EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 size: 67108864 - name: LNX type: 0FC63DAF-8483-4772-8E79-3D69D8477DE4 size: 67108864 content: - image: u-boot.bin - name: DTB type: EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 size: 4194304 - name: NXT type: EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 size: 2097152 - name: MXB type: EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 size: 6291456 - name: MXP type: EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 size: 6291456 - name: USP type: EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 size: 2097152
Le Jetson TX1 a une disposition de partitionnement complexe, avec de nombreuses partitions étant allouées pour le bootloader première étape, et beaucoup d’autres qui sont sans papiers. Donc, pour minimiser le risque de toucher une partition critique, j’ai préféré garder la plupart d’entre eux intacts et faire juste la quantité mineure de changements pour s’adapter UC dans l’appareil. Par conséquent, l’entrée de volumes gadget.yagl décrit principalement les valeurs par défaut TX1, avec les principales différences par rapport à l’original étant:
- La partition APP est rebaptisée system-boot et réduite à seulement 64 Mo. Il contiendra le fichier d’environnement uboot plus le noyau et initramfs, comme d’habitude dans les systèmes UC avec bootloader you-boot.
- La partition LNX contiendra notre binaire u-boot
- Si une partition avec n’est pas définie explicitement (ce qui est le cas en l’espèce), une partition dont un tel rôle et avec l’étiquette « rrabl » est implicitement définie à la fin du volume. Cela prendra tout l’espace disponible laissé de côté par la réduction de la partition APP, et contiendra le système de fichiers racine UC. Cela remplacera la partition UDA qui est la dernière dans le schéma de partitionnement Nvidia.
role: system-data
Maintenant, il est temps de construire le gadget snap en suivant les instructions du référentiel.
Construire et clignoter l’image
Maintenant que nous avons les clichés, il est temps de construire l’image. Il n’y a pas grand-chose à elle, vous avez juste besoin d’un compte Ubuntu One et de suivre les instructions pour créer une clé pour être en mesure de signer une affirmation de modèle. Avec cela il suffit de suivre le fichier README.md dans le dépôt jetson-ubuntu-core. Vous pouvez également télécharger le dernier tarball à partir du référentiel si vous préférez.
Le script de génération générera non seulement un fichier d’image complet, mais aussi un tarball qui contiendra des fichiers distincts pour chaque partition qui doit être flashé dans l’appareil. Ceci est nécessaire parce que malheureusement il n’y a aucun moyen que nous pouvons entièrement flash l’appareil Jetson avec une image GPT, au lieu de cela, nous pouvons clignoter uniquement des partitions individuelles avec les outils nvidia fournit.
Une fois la construction terminée, nous pouvons prendre le tarball résultant et suivre les instructions pour obtenir les partitions nécessaires flashé. Comme on peut le lire là-bas, nous devons télécharger le package Nvidia L4T. Notez également que pour pouvoir modifier la taille des partitions et les fichiers pour clignoter, quelques correctifs doivent être appliqués sur les scripts L4T.

Résumé
Après cela, vous devriez avoir un appareil Ubuntu Core 18 de travail. Vous pouvez utiliser le port de série ou un moniteur externe pour le configurer avec votre compte launchpad afin que vous puissiez le ssh dans. Profiter!
Ce blog a été initialement publié sur le blog d’Alfonso Beato