Installer Debian Stretch sur un Orange Pi PC2¶
toolchain¶
On travaille sur une architecture amd64 et l”Orange Pi PC2 a une architecture ARM 64 bits, également appelée AARCH64.
On va donc commencer par installer une toolchain Linaro. On télécharge l’archive binaire sur le site, actuellement la version 6.3.1
On l’extrait sous $HOME, ce qui crée le répertoire
gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/
, que l’on ajoute
au PATH
export PATH=~/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin:$PATH
Les exécutables sont préfixés par aarch64-linux-gnu-
qu’il faudra
indiquer pour les cross-compilations.
u-boot + atf¶
Pour booter, l”Orange Pi PC2 a besoin de u-boot mais également de arm-trusted-firmware.
Dans un premier temps, on clone les dépôts git correspondant
git clone git://git.denx.de/u-boot.git
git clone https://github.com/apritzel/arm-trusted-firmware.git
On commence par construire le firmware bl31.bin
en se mettant sur la branche allwinner
ou allwinner-stable selon les gouts et on le copie dans le répertoire u-boot:
cd arm-trusted-firmware
git checkout allwinner-stable
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j4 PLAT=sun50iw1p1 bl31
cp build/sun50iw1p1/release/bl31.bin ~/u-boot
On va dans le répertoire u-boot et on se positionne sur la dernière release stable, actuellement la v2017.09. Par exemple
cd ~/u-boot
git co v2017.09
Note : le support de l”Orange Pi PC2 existe seulement depuis la v2017.07.
Puis on lance la compilation. La variable CROSS_COMPILE contient le préfixe correspondant aux outils de la toolchain installés précédemment
make ARCH=arm CROSS_COMPILE=aarch64-linux-gnu- orangepi_pc2_defconfig
make ARCH=arm CROSS_COMPILE=aarch64-linux-gnu- -j4
A la fin de la compilation, on va concaténer tous les fichiers utiles en un seul que l’on va écrire sur la carte SD
cat spl/sunxi-spl.bin u-boot.itb > u-boot-sunxi-with-spl.bin
dd if=u-boot-sunxi-with-spl.bin of=/dev/sdX bs=8k seek=1
Dans la commande ci-dessus, il faut remplacer /dev/sdX
par le device
correspondant à la carte SD (/dev/sdb
ou /dev/mmcblk0
par exemple).
Noyau Linux¶
Actuellement, le noyau mainline ne supporte pas complétement l”Orange Pi PC2. Il manque en particulier le support de l’interface Ethernet.
Heureusement, il existe une version patchée à l”adresse suivante.
On commence donc par cloner cette version et se positioner sur la branche souhaitée (ici orange-pi-4.13)
git clone https://github.com/megous/linux
cd linux
git checkout origin/orange-pi-4.13
On exécute ensuite un script de compilation du noyau qui utilise la configuration par défaut (linux-4.13-64) et qui permet de compiler dans un répertoire dédié (KBUILD_OUTPUT) et d’obtenir les binaires utiles dans OUT/IMAGE.
OUT=$HOME/build64
IMAGE=v1
export KERNEL_DIR=$HOME/linux
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
export KBUILD_OUTPUT=$OUT/.tmp/linux-arm64
cp -v "$KERNEL_DIR/linux-4.13-64" "$KBUILD_OUTPUT/.config"
make -C $KERNEL_DIR -j4 clean
make -C $KERNEL_DIR -j4 Image dtbs
mkdir -p $OUT/$IMAGE
cp -f $KBUILD_OUTPUT/arch/arm64/boot/Image $OUT/$IMAGE
cp -f $KBUILD_OUTPUT/.config $OUT/$IMAGE/linux.config
cp -f $KBUILD_OUTPUT/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dtb $OUT/$IMAGE/board.dtb
A la fin de la compilation, on obtient 3 fichiers utiles dans le répertoire OUT, que l’on va copier sur la carte SD.
Partitionnement de la carte SD¶
On considère que la carte SD est le device /dev/sdX. On va créer une partition de boot en format FAT, un swap et la partition root.
La parition boot va contenir le noyau, le device tree et le script de configuration.
La partition root va être constitué d’un système de fichiers en F2FS, a priori plus adapté à une carte SD que le format ext4. C’est une des raisons de l’existence de la partition FAT : u-boot saurait se contenter d’une partition unique ext4 mais, à ma connaissance, pas en F2FS. De plus, ce n’est pas très génant de séparer boot et root.
Device Start End Sectors Size Id Type
/dev/sdX1 2048 264191 262144 128M c W95 FAT32 (LBA)
/dev/sdX2 264192 2361343 2097152 1G 82 Linux swap / Solaris
/dev/sdX3 2361344 31116287 28754944 13,7G 83 Linux
Création et montage des systèmes de fichiers¶
sudo mkfs.vfat /dev/sdX1
sudo mkswap /dev/sdX2
sudo mkfs.f2fs /dev/sdX3
sudo mount /dev/sdX1 /mnt/boot
sudo mount /dev/sdX3 /mnt/root
Partition boot¶
Depuis le répertoire OUT utilisé pour la compilation du noyau, on copie les 3 fichiers présents
cp board.dtb Image linux.config /mnt/tmp1
Reste le fichier de configuration de boot. On édite le fichier boot.cmd
avec le contenu suivant
# default values
setenv load_addr "0x44000000"
setenv rootdev "/dev/mmcblk0p3"
setenv verbosity "1"
setenv rootfstype "f2fs"
setenv console "serial"
# Print boot source
itest.b *0x10028 == 0x00 && echo "U-boot loaded from SD"
itest.b *0x10028 == 0x02 && echo "U-boot loaded from eMMC or secondary SD"
itest.b *0x10028 == 0x03 && echo "U-boot loaded from SPI"
echo "Boot script loaded from ${devtype}"
if load ${devtype} 0 ${load_addr} env.txt; then
env import -t ${load_addr} ${filesize}
fi
# temp fix: increase cpufreq and bus clock / speeds things up with vanilla images
if test "${cpufreq_hack}" = "on"; then
mw.l 0x1c2005c 1
mw.l 0x1c20000 0x80001010
fi
# No display driver yet
if test "${console}" = "display" || test "${console}" = "both"; then setenv consoleargs "console=tty1"; fi
if test "${console}" = "serial" || test "${console}" = "both"; then setenv consoleargs "${consoleargs} console=ttyS0,115200"; fi
setenv bootargs "root=${rootdev} noinitrd rootwait rootfstype=${rootfstype} ${consoleargs} panic=10 consoleblank=0 enforcing=0 loglevel=${verbosity} ${extraargs} ${extraboardargs}"
load ${devtype} 0 ${fdt_addr_r} board.dtb
fdt addr ${fdt_addr_r}
fdt resize
load ${devtype} 0 ${kernel_addr_r} Image
booti ${kernel_addr_r} - ${fdt_addr_r}
# Recompile with:
# mkimage -C none -A arm -T script -d boot.cmd boot.scr
Ce script est repris, en l’adaptant, du script de démarrage utilisé par armbian.
Il faut ensuite compiler ce fichier par la commande suivante
mkimage -C none -A arm -T script -d boot.cmd boot.scr
Si la commande mkimage n’existe pas, il faut installer le package
u-boot-tools
.
On copie également les deux fichiers sur la partition boot de la carte SD
cp boot.cmd boot.scr /mnt/tmp1
Partition rootfs¶
On a de quoi booter un noyau mais il faut maintenant créer un système complet
dans la partition root. Le choix fait ici est de créer un système Debian
en utilisant la commande multistrap
. On aura également besoin de
qemu-aarch64-static
pour émuler un processeur ARM 64 bits et chrooter dans le
rootfs.
On commence donc par installer les packages
apt install multistrap qemu-user-static qemu-system-arm
Il faut ensuite un fichier de configuration pour préparer les packages debian que l’on veut installer sur l’image.
Fichier arm64.conf
[general]
cleanup=true
noauth=true
unpack=true
debootstrap=Debian Net Utils Init
[Debian]
packages=apt kmod lsof apt-utils
source=http://deb.debian.org/debian
keyring=debian-archive-keyring
suite=stretch
components=main contrib non-free
[Net]
packages=netbase net-tools ethtool udev iproute iputils-ping ifupdown isc-dhcp-client ssh ca-certificates openssl chrony
source=http://deb.debian.org/debian
[Utils]
packages=locales adduser vim zsh less wget dialog usbutils rsync tmux git
source=http://deb.debian.org/debian
[Init]
packages=init systemd
source=http://deb.debian.org/debian
Pour créer les devices présents dans /dev/
dans l’image, on va utiliser le
script device-table.pl
fourni avec multistrap
. Auparavant, il faut
fournir la liste des devices à créer dans un fichier dev_table
#<name> <type> <mode> <uid> <gid> <major> <minor> <start> <inc> <count>
/dev d 755 0 0 - - - - -
/dev/mem c 640 0 0 1 1 0 0 -
/dev/kmem c 640 0 0 1 2 0 0 -
/dev/null c 640 0 0 1 3 0 0 -
/dev/zero c 640 0 0 1 5 0 0 -
/dev/random c 640 0 0 1 8 0 0 -
/dev/urandom c 640 0 0 1 9 0 0 -
/dev/tty c 666 0 0 5 0 0 0 -
/dev/tty c 666 0 0 4 0 0 1 6
/dev/console c 640 0 0 5 1 0 0 -
/dev/ram b 640 0 0 1 1 0 0 -
/dev/ram b 640 0 0 1 0 0 1 4
/dev/loop b 640 0 0 7 0 0 1 2
/dev/ptmx c 666 0 0 5 2 0 0 -
Pour simplifier l’installation, on regroupe ensuite les différentes opérations dans un script à exécuter en tant que root
#!/bin/sh
ARCH=arm64
QEMU=/usr/bin/qemu-aarch64-static
ROOTFS_DIR="/images/debian_arm64"
HOSTNAME="opipc2"
ROOTDEV="/dev/mmcblk0p3"
BOOTDEV="/dev/mmcblk0p1"
ID_RSA_PUB="ssh-rsa AAAAB3...JglcE61D36Xs1aWF37Q9DKP54L user@example"
rm -rf $ROOTFS_DIR
/usr/share/multistrap/device-table.pl --no-fakeroot -d $ROOTFS_DIR -f dev_table
multistrap -d $ROOTFS_DIR -a $ARCH -f $ARCH.conf
cp $QEMU $ROOTFS_DIR/usr/bin
export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true
export LC_ALL=C LANGUAGE=C LANG=C
chroot $ROOTFS_DIR /var/lib/dpkg/info/dash.preinst install
chroot $ROOTFS_DIR dpkg --configure -a
#users
chroot $ROOTFS_DIR useradd -m -s /bin/zsh -U -G sudo -u 1000 philippe
chroot $ROOTFS_DIR usermod -p '$1$SzENG9k7$BosCWiw59HnQsYiZse4nU/' root
#hostname
filename=$ROOTFS_DIR/etc/hostname
echo $HOSTNAME > $filename
#network interfaces
filename=$ROOTFS_DIR/etc/network/interfaces
echo auto eth0 >> $filename
echo iface eth0 inet dhcp >> $filename
#fstab
filename=$ROOTFS_DIR/etc/fstab
echo $BOOTDEV /boot vfat noatime 0 1 > $filename
echo $ROOTDEV / ext4 noatime 0 1 >> $filename
#apt sources
filename=$ROOTFS_DIR/etc/apt/sources.list
echo deb http://deb.debian.org/debian stretch main > $filename
echo deb http://deb.debian.org/security stretch/updates main >> $filename
echo deb http://deb.debian.org/debian stretch-updates main >> $filename
# ssh
mkdir -p $ROOTFS_DIR/root/.ssh
chmod 700 $ROOTFS_DIR/root/.ssh
echo $ID_RSA_PUB >> $ROOTFS_DIR/root/.ssh/authorized_keys
Il suffit ensuite de recopier ce rootfs sur la partition root, par exemple
en utilisant la commande rsync -av
.