Upgrade Arch Linux for Raspberry Pi 2
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
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.
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 issuingpacman -Qqn | pacman -S -
.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.
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.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.
Works like a charm, perfect how-to. Thanks!
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?
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 π
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!
Indeed… I’ve fixed that. Thanks!
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?
Turns out the problem were that I was using http://archlinuxarm.org/os/ArchLinuxARM-rpi-3-latest.tar.gz instead for http://archlinuxarm.org/os/ArchLinuxARM-rpi-2-latest.tar.gz
Thanks for this blog post!
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.
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”.
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!
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”).
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.