Crossgrading ODROID: De armhf a arm64

Con el ODROID-N2 inevitablemente en camino, es posible que tengas el mismo problema que tuve yo: dispones de una compleja configuración que está funcionando muy bien en un XU4 y deseas migrarla a una nueva plataforma de 64 bits. En mi caso, quería migrar mi XU4 NAS (que cuenta con bastantes servicios y adaptaciones para duplicar) a un ODROID-N1.

La mejor forma de hacerlo es con una instalación limpia, pero como se trata de Linux, puedes migrar de 32 a 64 bits con un complejo proceso llamado crossgrading. El requisito es que el sistema de destino permita ejecutar de forma nativa las instrucciones del sistema de origen (de 64 -> 32 bits no funciona). Antes de empezar, debes tener en cuenta lo siguiente: no es un proceso apto para personas pusilánimes, y debes contar en todo momento de una copia de seguridad de tus datos, ya que el resultado final no siempre puede ses el esperado. También puede que sea necesario disponer de acceso en serie ya que desinstalarás la mayor parte de tu sistema durante el proceso.

 

 

El kernel de 64 bits

Puedes empezar haciendo un clon del sistema que deseas migrar. Puedes recurrir a una herramienta como odroid-backup (https://github.com/mad-ady/odroid-backup) o dd. Deberás preparar una tarjeta SD o un módulo eMMC de destino con una imagen funcional para tu plataforma de destino (preferiblemente con la misma versión de distribución). Por ejemplo, para migrar un sistema armhf de Ubuntu 18.04 puedes emplear una imagen arm64 18.04. Inícialo, ejecuta todas las actualizaciones de kernel, uboot y boot.ini y copia algunos archivos en una ubicación segura (conservando los permisos):

# uname -a
# apt list --installed | cut -d '/' -f 1 | tee ~odroid/armhf_packages.txt
# tar -cvf ~odroid/modules.tar /lib/modules
# tar -cvf ~odroid/firmware.tar /lib/firmware
# tar -cvf ~odroid/packages.tar /etc/apt
# tar -cvf ~odroid/include.tar /usr/include/linux/
El kernel arm64 debe tener "CONFIG_COMPAT = y" activado en su configuración, de modo que puedas ejecutar un código de 32 bits. Puedes verificarlo con:
$ zcat /proc/config.gz | grep CONFIG_COMPAT
A continuación, apaga el sistema arm64 y en un PC aparte, sobrescribe la partición rootfs (generalmente la segunda partición) con los rootfs del sistema armhf (Figura 1). Por supuesto, asegúrate de guardar los archivos que acaba de crear antes de sobrescribir la partición (no después, como lo hice yo).

Figure1 - /dev/sde2 is from the armhf system and replaces the stock arm64 partition
Figura 1 - /dev/sde2 es del sistema armhf y reemplaza la partición estándar de arm64

Una vez realizada la copia, deberás desempaquetar los archivos tar en el sistema de archivos raíz de destino para que el kernel de 64 bits pueda encontrar sus módulos al arrancar:

# cd /path/to/armhf/rootfs
# tar -xvf ~/modules.tar
# tar -xvf ~/firmware.tar
# tar -xvf ~/packages.tar
# tar -xvf ~/include.tar
En caso de que la partición armhf tenga un UUID diferente al rootfs de arm64, deberás corregir esto ya sea sobrescribiendo el UUID de armhf o cambiando bootargs en boot.ini. En mi caso, elegí sobrescribir el UUID por el UUID que el sistema arm64 espera que sea:
# e2fsck -f /dev/sdd2
# tune2fs /dev/sdd2 -U a130ca78-0841-400a-8823-06a304a00850
Ahora estás listo para arrancar en un sistema híbrido: un kernel de 64 bits con un espacio de usuario de 32 bits. Es mejor usar una conexión en serie con el dispositivo para identificar y solucionar cualquier problema. También es mejor dejar los periféricos desconectados (discos externos, etc.) llegado a este punto. Yo tuve que desactivar manualmente watchdog antes de que pudiera arrancar de forma estable en el nuevo hardware.
# rm -f /path/to/armhf/rootfs/etc/systemd/system/default.target.wants/watchdog.service
Una vez que inicies, verifica que la configuración de la red para asegurarte de que no se esté duplicando la dirección IP en tu LAN (en caso de que fuera estática) y podamos empezar a convertir los paquetes a 64 bits.

Conversión de 64 bits

Ahora viene la parte más delicada: tienes que reinstalar la mayoría de los paquetes mientras el sistema se está ejecutando. Afortunadamente, alguien se ha molestado en preparar un script que automatiza la mayor parte del trabajo, pero ha sido diseñado para realizar una migración de i386 a amd64. Hice un fork con algunos cambios (en su mayoría, renombrar i386 por armhf y amd64 por arm64) y hace su trabajo sobre el ODROID.

Antes de empezar, deberías echar un vistazo a /etc/apt/sources.list* y desactivar los repositorios específicos de ODROID para la plataforma armhf (por ejemplo, http://deb.odroid.in/5422-s para XU4) y habilitar los repositorios (si existe alguno) para arm64. También debes comprobar que los componentes universe, restricted y multiverse estén activados para que Ubuntu tenga más posibilidades de encontrar todos los paquetes necesarios.

Puedes clonar el script desde aquí al sistema de destino:

# apt-get install git
# git clone https://github.com/mad-ady/distrorejuve.git
# cd distrorejuve
# ./distrorejuve
Cuando lo ejecutas sin argumentos, éste chequea tu sistema y hace algunas recomendaciones para ayudarte con la migración. Por ejemplo, en mi caso, me recomendó desinstalar una larga lista de paquetes X11, que puedo reinstalar más tarde, y así lo hice.

Ya estás listo para iniciar el proceso de crossgrading. Asegúrate de que la red esté conectada, de que haya suficiente espacio libre en el disco (al menos unos pocos gigas) y que no haya nada que pueda interrumpir el proceso (ejecutar desde una conexión en serie o desde una sesión tmux/screen).

# ./distrorejuve.sh --to-64bit | tee -a distrorejuve.log
Una vez que se ejecute, puede indicar que algunos paquetes deb no se han instalado desde apt y que es mejor eliminarlos. Algunos pueden ser críticos, como los paquetes del kernel, así que estate atento a lo que eliminas. Puedes ignorarlo y volver a ejecutar con IGNORECRUFT=Y.
# IGNORECRUFT=Y ./distrorejuve.sh --to-64bit | tee -a distrorejuve.log
Espera a que el script muestre más información y solicite que desinstales manualmente algunos paquetes. Haz una lista con todos ellos para que puedas volver a instalarlos cuando haya terminado. El script me pidió que eliminara wpasupplicant (lo cual eliminó Network Manager), así que asegúrate de que la red este gestionada con systemd-networkd o static.

Una vez que el script empiece a hacer su trabajo, podrás ver interminables pantallas de paquetes que se eliminan, varios errores de dependencia y, en última instancia, paquetes que se instalan como arm64 nuevamente. Este proceso llevará un tiempo dependiendo de cuántos paquetes tengas instalados.

El inevitable fallo

El proceso de crossgrading puede tardar algunas horas, pero en mi caso, parece que se quedó atascado al intentar instalar libclang1-6.0 (intentó instalarlo una y otra vez). El mensaje de error era:

Unpacking libclang1-6.0:arm64 (1:6.0-1ubuntu2) ...
dpkg: error processing archive /var/cache/apt/archives/libclang1-6.0_1%3a6.0-1ubuntu2_arm64.deb (--unpack):
trying to overwrite shared '/usr/lib/llvm-6.0/lib/libclang-6.0.so.1', which is different from other instances of package libclang1-6.0:arm64
El archivo en cuestión es un enlace simbólico a una librería armhf:
# ls -l /usr/lib/llvm-6.0/lib/libclang-6.0.so.1
lrwxrwxrwx 1 root root 43 Apr 6 2018 /usr/lib/llvm-6.0/lib/libclang-6.0.so.1 -> ../../arm-linux-gnueabihf/libclang-6.0.so.1
Eliminé manualmente el archivo (desde un intérprete de comandos aparte) y el proceso de actualización continuó:
# rm /usr/lib/llvm-6.0/lib/libclang-6.0.so.1
# ls -l /usr/lib/llvm-6.0/lib/libclang-6.0.so.1
lrwxrwxrwx 1 root root 41 Apr 6 2018 /usr/lib/llvm-6.0/lib/libclang-6.0.so.1 -> ../../aarch64-linux-gnu/libclang-6.0.so.1
Es posible que aparezcan diversos problemas que tendrás que resolver por ti mismo, de modo que ésta no debe concebirse como una guía completa.

Una vez que distrorejuve finalice su trabajo, es probable que te diga que te quedan muchos paquetes armhf por eliminar.

Figure 2 - Leftover packages
Figura 2 - Paquetes residuales

También debes ejecutar el siguiente comando para ver qué archivos de configuración varían con respecto a los paquetes normales.

# bash ./distrorejuve.sh --show-changes
En mi caso, apt se interrumpió y aún quedaban un montón de paquetes dañados que necesitaban atención. Por ejemplo, ejecutar el siguiente comando dio lugar a fallos con libcdio-dev que intento sobrescribir un archivo de configuración compartido tal y como se muestra en la Figura 3.
# apt-get --fix-broken install
Figure 3 - Symptom of a broken package
Figura 3 - Síntoma de un paquete dañado

El modo de solucionar este problema fue desinstalar los paquetes ofensivos:

# apt-get remove libcdio-dev:armhf libcdio-cdda-dev:armhf libass-dev:armhf libcdio-paranoia-dev:armhf libgnutls28-dev:armhf libharfbuzz-dev:armhf libxml2-dev:armhf libbluray-dev:armhf libicu-le-hb-dev:armhf librtmp-dev:armhf samba-libs:armhf libcdio-cdda-dev libcdio-paranoia-dev ibverbs-providers:armhf ibverbs-providers:armhf
Después de esto, apt logró configurar todos los paquetes sobrantes. También puede llevar tiempo eliminar los paquetes antiguos de 32 bits:
# ./distrorejuve --remove-cruft
Tuve problemas para eliminar dash:armhf, así que apunté /bin/sh y /bin/sh.distrib hacía /bin/bash en lugar de dash. Si no hay un /bin/sh válido, obtendrás muchos fallos extraños, incluso con apt.

Figure 4 - Removing dash:armhf
Figura 4 - Eliminando dash:armhf

En este punto, es posible que quieras asegurarte de que el sistema se encuentre en un estado normal. Necesitarás comprobar lo siguiente:

  • Aún tienes paquetes básicos instalados (vim, ip, bash, netplan, etc.). Me faltaba vim, así que necesitaba reinstalarlo.
  • Comprueba que los paquetes de kernel, uboot, bootini están bien. En mi caso, estoy en un N1 que no tiene paquetes de este tipo para Ubuntu, pero existe el riesgo de que se hayan eliminado componentes clave en el proceso de migración y que tu placa no pueda arrancar. Instala los paquetes que faltan o restaura los archivos perdidos si fuera necesario.

Mantén tus dedos cruzados y reinicia.

Verificación de Servicios y parches

Probablemente tu placa arrancará sin demasiados problemas. Si es así, ¡alégrate! Si no es así, restaura la copia de seguridad y vuelve a mirar más detenidamente qué paquetes se eliminaron (recuerda, ¡no hay reembolsos!).

Pero, aun así, el sistema puede no estar en buena forma por completo. Todavía tendrás que revisar los servicios críticos y ver qué falta o qué no funciona. En mi caso:

  • Apache2 no se iniciaría porque faltaban libapache2-mod-php7.2 y libapache2-mod-fcgid
  • Git estaba ausente y necesitaba reinstalarse
  • Faltaba Samba y necesitaba una reinstalación (aunque la configuración estaba bien)
  • Faltaba Nfs-kernel-server y había que volver a instalarlo
  • Transmisión-daemon había desaparecido

Recuerda que hiciste una copia de seguridad de los paquetes armhf instalados; ahora es el momento de revisar esa lista y compararla con lo que tienes ahora para ver si falta algo importante. Observa que el filtro grep ignora las librerías, ya que generalmente son una dependencia de algo diferente. En el sistema arm64 ejecuta:

# apt list --installed | cut -d '/' -f 1 | tee /root/arm64_packages.txt
# diff -u arm64_packages.txt armhf_packages.txt | egrep '^\+' | grep -v '^\+lib'
Debes revisar la lista e instalar los paquetes necesarios antes de continuar.

Programas heredados de 32 bits

Puede haber programas que se compilaron manualmente y no se instalaron como paquetes deb. En este caso, deberás localizarlos y recompilarlos para arm64. Suponiendo que están en algún lugar de /usr/local (o en rutas conocidas), puedes encontrarlos con:

# find /usr/local -type f -executable -exec file {} \; | grep 32-bit
El problema con estos programas es que no se ejecutarán porque la migración ha eliminado armhf libc (/lib/ld-linux-armhf.so.3) y las librerías de las que dependen. Si intentas ejecutar alguno, recibirás un error de "No such file or directory" nada útil, refiriéndose al cargador que falta, no al programa en sí. Si no puede recompilarlos, puede añadir armhf como una arquitectura ajena e instalar libc6 y las dependencias de las librerías que faltan, aunque terminaras nuevamente con un sistema parcialmente híbrido.
# dpkg --add-architecture armhf
# apt-get update
# apt-get install libc6:armhf
Figure 5 - Finding armhf programs
Figura 5 - Buscando programas armhf

GPIOs y WiringPi

Los módulos (como lirc_odroid) y los programas que utilizan pines GPIO deberán revisarse manualmente porque los números de pines GPIO pueden diferir de una placa a otra. Además, si está utilizando WiringPi, necesitaras obtener e instalar la versión correcta para la placa arm64.

Configuración apuntando a dirs de 32 bits

Hay algunos programas que pueden fallar al ejecutarse porque su configuración apunta a librerias de 32 bits. Lirc puede fallar al iniciar porque suele apuntar a /usr/lib/arm-linux-gnueabihf/lirc/plugins. Deberás ajustar /etc/lirc/lirc_options.conf y cambiar plugindir=/usr/lib/aarch64-linux-gnu/lirc/plugins y reiniciar lirc. KDE puede apuntar a librerías compartidas de 32 bits y pueden tener como resultado paneles dañados igualmente. (https://wiki.debian.org/CrossGrading#Caveats_and_Known_Problems)

Librerías Perl de 32 bits

Las librerías Perl XS que se instalaron desde CPAN también podrían estar dañadas. Estas librerías tienen algún código compilado dentro que depende de la arquitectura. Puedes localizarlas con:

# perldoc perllocal | grep XS

Tipos especiales de datos

Otros programas pueden codificar sus datos utilizando estructuras que dependen del tamaño de la plataforma (o utilizan marcas de tiempo de 32 bits). Uno de estos tipos de datos es rrd, que contiene datos de series de tiempo de round-robin. Herramientas como munin o cactus generalmente escriben en archivos rrd. El programa rrdtool de 64 bits no puede funcionar con archivos rrd creados en sistemas de 32 bits, por lo que deberás exportar todos tus datos rrd a xml al mismo tiempo que se ejecutan en un sistema de 32 bits y volver a crear el rrd en el sistema de 64 bits. Puedes hacer esto en el sistema armhf:

# cd /path/to/rrd/files
# find . -type f -name '*.rrd' -exec rrdtool dump {} {}.xml \;
Puedes crearlos de nuevo en el sistema arm64 con:
# find . -type f -name "*.rrd.xml" -exec sh -c 'file="{}"; newfile=`basename $file .xml`; dir=`dirname $file`; rrdtool restore "$file" "$dir/$newfile"' \;

Conclusión

¿Cómo tal me fue con el proceso? ¡Mejor de lo esperado! ¿Deberías intentarlo? Si tiene tiempo y una copia de seguridad, no veo por qué no. Para ser justos, solo lo he probado en un sistema "servidor" hasta ahora, pero con los paquetes correctos (y los correspondientes ajustes de configuración en /etc/X11/xorg.conf) también debería funcionar con un sistema de escritorio. Hay disponible más información y ayuda en el hilo de soporte en https://forum.odroid.com/viewtopic.php?f=55&t=33861.

Be the first to comment

Leave a Reply