Convert from armhf to arm64 on Raspberry Pi 3 B running 64-bit Ubuntu Server 18.04 LTS (Bionic)

10,130

Can I convert the architecture of my Ubuntu 18.04 LTS server from armhf to arm64? I've already got it doing a "multiarch" thing, but I'm not sure that's the best solution. How should I proceed?

Yes, you can, but here there be dragons - the initial conversion process will have to be largely manual, and even afterwards you'll have to initially pay very close attention to what your package manager intends to do. I've done multiple conversions - from i386 to amd64, from armel to armhf to arm64, and the other way around - from amd64 to i386 and from arm64 to armhf to armel. Why? Because I can.

First thing to note - if you are cross-grading from less advanced architecture to more advanced (that is, i386->amd64 and armel->armhf->arm64) you need to first install the target architecture kernel and boot into it and only then cross-grade the rest of the packages. If you're cross-grading the other way around (I've done so on a system after I found out 64-bit packages leave too little free RAM) you need to first transition all of the packages to the less advanced architecture and only then transition kernel (if such is available in lesser architecture at all). Second thing to note - APT is not smart enough to cross-grade packages safely, it has a tendency to remove critical components if it believes some of the dependencies are broken. Until all of dpkg, apt, and aptitude (if used) and all of their dependencies are installed in the target architecture - the cross-grading will absolutely have to be done manually, though it should be possible to at least partially script it.

Now onto the process of cross-grading:

  1. make sure you have some way of booting the system and chroot'ing into it in case things go south, e.g. on Pinebook Pro that normally boots from eMMC it can be achieved by keeping around a microSD card with another OS, on x86 - just keep around a live CD/USB.
  2. add the target architecture to dpkg, e.g. dpkg --add-architecture arm64
  3. update APT sources, e.g. apt update
  4. install the kernel in target architecture, e.g. apt install linux-image-arm64:arm64, reboot into that new kernel
  5. open at least a couple of root terminals, especially if you don't have root password and use sudo: sudo -i. Can be quite useful to also install mc and keep it running in one of those root terminals - it can make some recovery tasks easier.
  6. use something like apt-rdepends to obtain full recursive list of all dependencies for the target architecture versions of dpkg, apt, and, optionally, aptitude, download all of those packages using apt download <package1> <package2> .... Do the same for sed, tar, coreutils, findutils - those are runtime dependencies for dpkg, and installing those manually will reduce the chances of getting broken system when moving onto automatic phase.
  7. Use dpkg -i <package_file> to install all the downloaded packages one by one, starting from the most core dependency and moving onto dependent packages - this essentially "upgrades" the old architecture packages with the new architecture packages, correctly removing old files and installing new ones for non-multiarch packages like dpkg and installing new in parallel with old for multiarch packages like libc6.
  8. Once you have new architecture version of apt installed you may run apt update and attempt apt -f install to install/cross-grade any missing dependencies for the target architecture, but be careful to make sure APT doesn't try to remove any packages related to package management or networking - without those the system can still be recovered, but the process is rather tedious. If you see APT proposing to remove any of those critical packages - fall back to apt-rdepends and installing missing dependencies manually.
  9. Once you had at least one successful run of apt -f install you should run apt full-upgrade at least once - it will likely pick up more packages in target architecture that still need to be installed.
  10. ...
  11. PROFIT!!!

How can I systematically go through all of the apt packages I have installed, and replace the armhf ones with arm64 where possible/available?

The way I do it is using aptitude and piping output through grep searching for old architecture, e.g. aptitude search ~i | grep :armhf. For all the found packages - first, attempt to install the new arch version, e.g., if the above command lists firefox:armhf then just do apt install firefox and that should replace armhf version with arm64. Eventually only multi-arch packages will be left installed, at that point it should be possible to just purge all the packages returned by aptitude search ~i | grep :armhf. Once all old architecture packages are purged you should be able to run dpkg --remove-architecture armhf.

Share:
10,130

Related videos on Youtube

Harley Day
Author by

Harley Day

I'm an Engineering PhD student at Imperial College London. My interests include cycling, astronomy, playing the saxophone, clarinet and piano, programming and mathematics. I work mainly in MATLAB, and increasingly in R developing bioinformatics tools. My programming skills include C, C++, MATLAB, R, HTML, CSS and JavaScript.

Updated on September 18, 2022

Comments

  • Harley Day
    Harley Day over 1 year

    Questions

    1. Can I convert the architecture of my Ubuntu 18.04 LTS server from armhf to arm64? I've already got it doing a "multiarch" thing, but I'm not sure that's the best solution. How should I proceed?
    2. How can I systematically go through all of the apt packages I have installed, and replace the armhf ones with arm64 where possible/available?

    I have this disk image backed-up, so I don't mind solutions which may destroy the server - I can just reinstall the image if anything goes wrong.


    Background

    I would like to convert from armhf to arm64 on my Raspberry Pi 3 B. I have followed the instructions here, and produced a working 64-bit Ubuntu Bionic Server (which is cool). However, I notice that, while I can install and run arm64 (i.e. 64-bit) packages, most of the packages on my server are armhf (i.e. 32-bit). I would like to replace all (or as many as possible) of the armhf with arm64. The server currently lists arm64 as a "foreign" architecture, and armhf as its native architecture. Can I switch these round?

    ubuntu@ubuntu:~$ dpkg --print-architecture
    armhf
    ubuntu@ubuntu:~$ dpkg --print-foreign-architectures
    arm64
    

    Is there some way to make the system switch these two around so that arm64 becomes the default, and armhf is used only where arm64 packages are not available?


    Please note: I have no background in computer science, so please forgive my naivety. My thinking is that 64-bit computing will be on average quicker than 32-bit since any software trying to deal with large numbers or high precision can just use the 64-bit architecture of the ARMv8 chip on the Pi 3 B rather than extending the processing of the numbers to several clock cycles. I have seen discussions on Raspberry Pi forums where some conflicting opinions are aired regarding the pros and cons of converting to 64-bit. I would be very grateful if somebody could compile a simple list of pros and cons as I don't understand the complexities of these discussions.

    Currently, I don't know if there will be a performance increase in moving to 64-bit, but what the heck - it's a Raspberry Pi - you're supposed to play around with them!


    Methods

    I followed the instructions at the Ubuntu Wiki page; doing this:

    sudo dpkg --add-architecture arm64 
    sudo apt update
    

    I now find

    dpkg --print-foreign-architectures
    

    returns

    arm64
    

    To confirm the 64-bit nature of the server:

    uname -a
    

    which returns:

    Linux ubuntu 4.15.0-1022-raspi2 #24-Ubuntu SMP PREEMPT Wed Aug 29 10:40:48 UTC 2018 aarch64 aarch64 aarch64 GNU/Linux
    

    Additionally:

    dpkg-architecture --list
    

    returns

    DEB_BUILD_ARCH=armhf
    DEB_BUILD_ARCH_ABI=eabihf
    DEB_BUILD_ARCH_BITS=32
    DEB_BUILD_ARCH_CPU=arm
    DEB_BUILD_ARCH_ENDIAN=little
    DEB_BUILD_ARCH_LIBC=gnu
    DEB_BUILD_ARCH_OS=linux
    DEB_BUILD_GNU_CPU=arm
    DEB_BUILD_GNU_SYSTEM=linux-gnueabihf
    DEB_BUILD_GNU_TYPE=arm-linux-gnueabihf
    DEB_BUILD_MULTIARCH=arm-linux-gnueabihf
    DEB_HOST_ARCH=armhf
    DEB_HOST_ARCH_ABI=eabihf
    DEB_HOST_ARCH_BITS=32
    DEB_HOST_ARCH_CPU=arm
    DEB_HOST_ARCH_ENDIAN=little
    DEB_HOST_ARCH_LIBC=gnu
    DEB_HOST_ARCH_OS=linux
    DEB_HOST_GNU_CPU=arm
    DEB_HOST_GNU_SYSTEM=linux-gnueabihf
    DEB_HOST_GNU_TYPE=arm-linux-gnueabihf
    DEB_HOST_MULTIARCH=arm-linux-gnueabihf
    DEB_TARGET_ARCH=armhf
    DEB_TARGET_ARCH_ABI=eabihf
    DEB_TARGET_ARCH_BITS=32
    DEB_TARGET_ARCH_CPU=arm
    DEB_TARGET_ARCH_ENDIAN=little
    DEB_TARGET_ARCH_LIBC=gnu
    DEB_TARGET_ARCH_OS=linux
    DEB_TARGET_GNU_CPU=arm
    DEB_TARGET_GNU_SYSTEM=linux-gnueabihf
    DEB_TARGET_GNU_TYPE=arm-linux-gnueabihf
    DEB_TARGET_MULTIARCH=arm-linux-gnueabihf
    

    This seems to suggest that whenever I install a package using apt, the system will go for an armhf package by default.

    I would like to make arm64 the non-foreign architecture, and armhf my foreign architecture on this server.

    • Thomas Ward
      Thomas Ward over 5 years
      You can't convert between architecture versions safely. Backup data you want to keep, then install the arm64 variant, then restore your data.
    • Harley Day
      Harley Day over 5 years
      Oh is that all I've done! Okay great. I shall go back to the Ubuntu Server ARM images page, and be sure to download the arm64 version. Thank you!