Upgrade Arch Linux for Raspberry Pi 2

Raspberry Pi 2 model B v1.1 (see the note below)This articles shows how to transition from Raspberry Pi to Raspberry Pi 2 without reinstalling Arch Linux.

Arch Linux ARM images are tied to specific hardware architecture. While this may be seen as an inconvenience, there is an advantage in that Arch Linux binaries for Raspberry Pi 2 are compiled for ARM7 CPU and thus can benefit from the new instruction set.

Because ARM7 architecture is backward compatible with ARM6, it’s possible to upgrade your Raspberry Pi hardware to version 2 without reinstalling Arch Linux. Here is how we can do that (it goes without saying, that if you have any important data, consider backing it up first).

Update: this guide works for Rapsberry Pi 3 as well

Let’s start from Raspberry Pi 1 prompt. Some of the commands will require root privileges, so either login as root user or use sudo to start an interactive shell:

sudo -i

It’s good idea to fully update the existing system before performing the upgrade:

pacman -Syu

1. Download the latest ArchLinux image for Raspberry Pi 2

wget http://archlinuxarm.org/os/ArchLinuxARM-rpi-2-latest.tar.gz

2. Extract required files from the archive

mkdir ~/update
bsdtar -xpf ArchLinuxARM-rpi-2-latest.tar.gz \
       -C ~/update boot usr/lib/modules

All we need is /boot directory (with an updated kernel image — kernel7.img) and updated kernel modules.

3. Replace files in /boot directory with the new ones (with backup)

mkdir -p ~/backup/boot
mv /boot/* ~/backup/boot

mv ~/update/boot/* /boot

4. Update boot configuration

If you have previously customized Rasperry Pi’s boot configuration, you may need to update config.txt and / or cmdline.txt files appropriately.

Use the following commands to display differences between the old configuration files and the new ones:

diff ~/backup/boot/config.txt /boot/config.txt
diff ~/backup/boot/cmdline.txt /boot/cmdline.txt

Then, update the configuration files (if needed):

nano /boot/config.txt
nano /boot/cmdline.txt

5. Replace files in /usr/lib/modules with the new ones (with backup)

mkdir -p ~/backup/modules
mv /usr/lib/modules/* ~/backup/modules

mv ~/update/usr/lib/modules/* /usr/lib/modules

6. Re-generate initial RAM file system (optional)

This step is require only if your Linux installation is relying on initramfs image to load additional drivers (like LVM, LUKS, etc.) early in boot sequence. If you are in doubt about whether your OS contains the initial ramdisk, you may check the backup/boot directory for presence of initramfs or initrd files (default Arch Linux images for Raspberry Pi don’t contain them).

Use the following command to print version of the new (ARM7) kernel:

ls /usr/lib/modules | grep ARCH

To generate a new ramdisk (with ARM7 kernel modules), run mkinitcpio with that kernel version:

mkinitcpio -c /etc/mkinitcpio.conf -g /boot/initramfs -k KERNEL_VERSION

7. Boot the image in Raspberry Pi 2

Power off the Raspberry Pi 1:

poweroff

Then insert your SD card into Raspberry Pi 2 (either by removing SD-adapter, or by cloning the data to microSD) and boot the device.

If Raspberry Pi 2 won’t boot, you can always restore original files from the ~/backup folder (using a separate machine) and boot from Raspberry Pi 1 again.

8. Upgrade binaries

After those steps, Raspberry Pi 2 should use new, ARM7 kernel and modules. However, all user-space binaries are still compiled for ARM6. While this combination works just fine (because ARM7 CPU is compatible with ARM6 instructions), me may want to update the binaries to use newer CPU instruction set.

First, we need to change system architecture in the package manager (pacman) — run:

nano /etc/pacman.conf

and replace armv6h with armv7h in the Architecture = armv6h line.

Then completely clean package cache:

pacman -Scc

and perform full package database synchronization:

pacman -Syy

We need to use --force option for Linux kernel package in order to overwrite the files that we’ve previously created manually (namely, /boot/kernel7.img, etc.):

pacman -S linux-raspberrypi --force

If the kernel version from package manager differs from version of the manually copied kernel, you may delete obsolete /usr/lib/modules/KERNEL_VERSION directory (which we’ve created on step 5) to save storage space.

Other packages should be re-installed (and, thus, upgraded) normally:

pacman -Qqn | pacman -S -

9. Re-generate initial RAM file system (optional)

If your system uses initial RAM disk, you may repeat the actions from step 6 one more time to include the updated binaries in the initramfs / initrd image.

10. Reboot the system

reboot

Login and display current machine hardware:

uname -m

It should be armv7l, which confirms that you have successfully upgraded your OS to the new architecture.

If everything works as expected, you may finally delete the ~/backup directory.

* The Raspberry Pi 2 board photo is from Wikipedia, licensed under CC BY-SA 4.0.

* Raspberry Pi is a trademark of the Raspberry Pi Foundation

17 Comments

  1. Huey Driver says:

    Thanks for this.

    I had a couple things I had to do.
    In step 8, commenting out Architecture led to errors. Changing armv6h to armv7h worked fine.
    Also in step 8, the final pacman sync isnt working for me. I get an error after checking for file conflicts
    error: failed to commit transaction (conflicting files)
    /usr/sbin exists in both ‘filesystem’ and ‘initscripts’
    Errors occurred, no packages were upgraded.

    The system is working, but I dont know if the updates will work until I fix that.

  2. Pavel says:

    Hi,

    Thanks for the feedback. Indeed, it’s probably better to specify the architecture explicitly (I’ve modified the step).

    The package conflict might has nothing to do with the architecture upgrade per se – it’s quite possible that your system was significantly out-of-date. There are many similar errors (and solutions) posted on the Internet.

    You may try to run pacman -Syu --ignore filesystem to update packages incrementally.

    Also, you may check a related Arch’s guide on how to migrate between architectures without reinstalling (x86 / x64). Particularly, it recommends to upgrade pacman separately with pactree -l pacman | pacman -S - before issuing pacman -Qqn | pacman -S -.

  3. Huey Driver says:

    Thanks for the tips and links. I was able to work around the problem
    Before following this process, I did a full system update using pacman. I used windiskimager and created an image that I loaded to a new SD card that I used so I could keep my original SD as a backup for the old Pi.
    I wound up determining that my problems were updating the ‘filesystem’ and ‘initscripts’ packages. I used the pactree command and redirected output to a text file (“pactree -l > files.txt”), then deleted lines with filesystem and initscripts from the text file. Then I did the update using the text file (“cat files.txt | pacman -Syu -“).
    After running that, I was able to update the filesystem package without any problem (pacman -Syu filesystem).
    Initscripts package still would not update because of /usr/sbin being a sym link. I used the –ignore option and it updated.
    When I get time, I’m going to load a clean copy of Arch for ARM7 to see what the problem is with the sym link. I’ve read most of the stuff about pacman following sym links and just don’t understand right now how that problem could have crept in.

  4. Pavel says:

    By the way, initscripts systems are not officially supported by Arch Linux since 2012, and neither my Raspberry Pi 1 nor my Raspberry Pi 2 have this package installed by default.

  5. Huey Driver says:

    Thanks for that info. I’ll remove it.
    I dont know how it got installed, but it was curious to me since it referenced rc.d and nothing I had configured used the ‘non-systemctl’ method of controlling daemon startup.

    Hopefully this conversation gets picked up by google robots to help anyone else who has this problem.

  6. Remco says:

    Works like a charm, perfect how-to. Thanks!

  7. Abby says:

    On Step 8. I have the following message:

    pacman -S linux-raspberrypi –force
    error: failed to prepare transaction (package architecture is not valid)
    :: package linux-raspberrypi-4.0.8-3-armv6h does not have a valid architecture

    uname -a
    Linux alarmpi 4.0.7-1-ARCH #1 SMP PREEMPT Wed Jul 1 15:20:35 MDT 2015 armv7l GNU/Linux

    Any idea?

  8. Abby says:

    Fixed it. The mirrorlist file was still pointing at armv6 repos… So in this tutorial the /etc/pacman.d/mirrorlist file should also be extracted from ArchLinuxARM-rpi-2-latest.tar.gz and copied.
    Put that after “nano /etc/pacman.conf” part

    Bye and tnx πŸ™‚

  9. Wessel 't Hoen says:

    Thanks for this excelent guide! Still relevant for the rpi3 since that uses the same armv7h architecture for now. Used this to upgrade my rpi1 image to rpi3 πŸ™‚

    1 very minor issue: the path at the end of the guide points to “/usr/bin/modules/KERNEL_VERSION” which I think should be “/usr/lib/modules/KERNEL_VERSION”. Just for completeness sake πŸ˜‰

    Thanks again!

  10. Pavel says:

    Indeed… I’ve fixed that. Thanks!

  11. nimo says:

    I am trying to upgrade from Raspberry pi 1 B+ to Raspberry Pi 3.

    But in the boot process I get error message about wrong exec format for /sbin/init.

    Did anyone else that also did the same upgrade got the same error message?

    How did you manage to solve it then?

  12. diap says:

    Thanks for this guide.

    Just need some minor clarification.

    At step 2
    bsdtar -xpf ArchLinuxARM-rpi-2-latest.tar.gz \
    -C ~/update boot usr/lib/modules

    is actually supposed to be two commands as follows
    bsdtar -xpf ArchLinuxARM-rpi-2-latest.tar.gz
    bsdtar -C ~/update boot usr/lib/modules

    Is it not? Pasting the former returns error.

  13. Pavel says:

    The “\” character is Bash line continuation – either paste the two lines simultaneously, or join the two parts into a single line: “bsdtar -xpf ArchLinuxARM-rpi-2-latest.tar.gz -C ~/update boot usr/lib/modules”.

  14. diap says:

    Thanks!!

    Another thing. At step 6 “ls ~/update/usr/lib/modules | grep ARCH” points to already moved files which I think means that the correct path to use would be “ls /usr/lib/modules | grep ARCH”.

    Last question if you dont’t mind. Are the contends of rpi2 /usr/lib/modules compatible with rp1? My original setup was an rpi1 with external drive and the partition scheme was /boot to sd and /root to hdd. However during migration rpi2 failed to mount /root. I then tried to boot again from rp1 (using of course original cmdline.txt, config.txt and initram) and worked fine even though I did not revert rpi2 /usr/lib/modules. Just thought it was weird and I wonder if I did something wrong and this is the reason it doesn’t seem to work.

    In any case again many thanks!

  15. Pavel says:

    Indeed, the directory should be “~/update/usr/lib/modules” at step 6, thanks!

    It seems that the content of “/usr/lib/modules” is compiled for armv6h, so everything works as it’s supposed to (you can use “gunzip” to decompress any module file and then use “readelf -A FILE” to make sure that the output contains “Tag_CPU_arch: v6K”).

  16. diap says:

    I see. πŸ™‚

    Well I finally managed to boot successfully. Just in case anybody in the future trying to migrate from an rpi1 with /root on a usb hdd finds after all these steps rpi2 not being able to mount the drive, then take these two steps.

    1. Plug the usb drive to a linux desktop and “fsck” it to make sure there is no corruption.

    2. Edit cmdline.txt and add “rootdelay=30”. “rootwait” might work too.