I had the pleasure of going to RustConf 2025 in Seattle this year. During the conference, I met lots of new people, but in particular, I had the pleasure of spending a large portion of the conference hanging out with Jeremy Soller of Redox and System76. Eventually, we got chatting about EFI and bootloaders, and my contributions to PostmarketOS, and my experience booting EFI-based operating systems (Linux) on smartphones using U-Boot. Redox OS is also booted via EFI, and so the nerdsnipe began. Could I run Redox OS on my smartphone the same way I could run PostmarketOS Linux?
Spoilers, yes.
This blog post will document the process I took to get it to boot, so that others can hopefully follow in my footsteps and improve some of the challenges I bumped up against, and maybe even contribute drivers and further the support. It will be a little handwavey and assume a high level of knowledge in some areas, because it is written for developers, and I don't want to explain every little detail.
As alluded to in the introduction, U-Boot is a critical part of getting this to work. PostmarketOS developers (and others), have created compatible Qualcomm U-Boot Android bootimg for a handful of devices. This work is very much ongoing and scattered, but a few places to look include: the PostmarketOS wiki, the U-Boot Qualcomm blogpost by Linaro Tauchgang U-Boot Qualcomm matrix channel.
Now, we'll assume those resources are sufficient, and that you have a U-Boot Android Bootimg for the device in question. The first thing to do is get into fastboot (refer to postmarketos wiki), and flash the U-Boot image to your boot partition. We'll also assume you have backed up any internal storage you want to keep from your device.
THE FOLLOWING WILL OVERWRITE INTERNAL STORAGE AND YOU COULD BREAK THE PHONE, PLEASE TAKE APPROPRIATE PRECAUTIONS
fastboot erase dtbo
fastboot flash boot /tmp/u-boot.img
fastboot reboot
Now the device will boot into U-Boot, and for most Qualcomm phones you have to hold volume up while U-Boot is booting to get a menu.
Select USB Mass Storage in this menu (use volume and power to navigate), plug in a USB cable, and your phone's internal storage should show up as a series of partitions on your computer.
https://static.redox-os.org/img/aarch64/
(currently at time of writing https://static.redox-os.org/img/aarch64/redox_desktop_aarch64_2025-09-21_91_redox-live.iso.zst)zstd -d redox_desktop_aarch64_2025-09-21_91_redox-live.iso.zst
losetup -f -P redox_desktop_aarch64_2025-09-21_91_redox-live.iso
Now we have the individual partitions of the redox image ready to flash and change on the phone. We'll be overwriting the phone's storage once again, so ensure you have a copy of whatever you want to keep.
Alright then, choose a couple small partitions that are big enough on the phone's internal storage, in my case that's cache and system but in your case it might be different.
dd if=/dev/loop0p2 of=/dev/disk/by-partlabel/cache bs=8M oflag=direct status=progress
dd if=/dev/loop0p3 of=/dev/disk/by-partlabel/system bs=8M oflag=direct status=progress
Now we need to mount the partitions we just flashed onto the phone and make some changes.
Perhaps eventually Redox will support split images, and the problems I uncovered with the bootloader and pcid will be fixed, and this will all be redundant.
The RedoxFS filesystem isn't natively supported under Linux, but can be mounted as a Filesystem-in-userspace by running the redoxfs command from the following repo https://gitlab.redox-os.org/redox-os/redoxfs
mkdir -p /mnt/redox-boot
mkdir -p /mnt/redox-root
mount /dev/disk/by-partlabel/cache /mnt/redox-boot
redoxfs /dev/disk/by-partlabel/system /mnt/redox-root
Copy the DTB for your phone (from postmarketos or u-boot) to the boot partition
cp u-boot/.output/dts/dt.dtb /mnt/redox-boot/dt.dtb
The Redox bootloader does some weird stuff when parsing DTBs, and I hacked around it to get things working. My patch doesn't make a lot of sense so I haven't upstreamed it yet, but basically it turns all reads into 32-bit. Apply the following patch to the bootloader, recompile it, and copy it over the existing one.
git clone https://gitlab.redox-os.org/redox-os/bootloader
cd bootloader
vim bootloader.patch
diff --git a/src/os/uefi/dtb.rs b/src/os/uefi/dtb.rs
index 3c7662e..59bf25e 100644
--- a/src/os/uefi/dtb.rs
+++ b/src/os/uefi/dtb.rs
@@ -46,24 +46,25 @@ unsafe fn get_dev_mem_region(fdt: &Fdt) {
}
};
let parent_bus_addr = {
- if cell_sizes.address_cells == 1 {
- BE::read_u32(&chunk[4..8]) as u64
- } else if cell_sizes.address_cells == 2 {
- BE::read_u32(&chunk[8..16]) as u64
- } else {
- DEV_MEM_AREA.clear();
- return;
- }
+ BE::read_u32(&chunk[0..4]) as u64
};
let addr_size = {
- if cell_sizes.size_cells == 1 {
- BE::read_u32(&chunk[8..12]) as u64
- } else if cell_sizes.size_cells == 2 {
- BE::read_u32(&chunk[16..20]) as u64
- } else {
- DEV_MEM_AREA.clear();
- return;
- }
+ BE::read_u32(&chunk[0..4]) as u64
};
println!(
"dev mem 0x{:08x} 0x{:08x} 0x{:08x}",
git apply bootloader.patch
make TARGET=aarch64-unknown-uefi BUILD=build
cp build/bootloader.efi /mnt/redox-boot/EFI/BOOT/BOOTAA64.EFI
pcid fails to launch because Redox doesn't have a pci controller for Qualcomm. It doesn't need it to boot, but by
default it will try and halt the boot if it fails.
Remove the following line from /mnt/redox-root/usr/lib/init.d/00_drivers
pcid-spawner /etc/pcid.d/
Alright, changes made, unmount and let's get booting!
umount /mnt/redox-root
umount /mnt/redox-boot
losetup -d /dev/loop0
Press volume buttons to exit the usb mass storage function of u-boot, and select the usb serial gadget function Then we'll get to configuring the bootloader.
picocom -b 115200 /dev/ttyACM0
eficonfig
This will bring up the menu to configure EFI, unfortunately the partitions are listed by number rather than name, so
either try a bunch of them until you find the partition redox boot partition, or go back to ums and run blkid
to find
it.
Configure roughly as follows:
Then run bootefi bootmgr
and the Redox bootloader should start
Press l
for live mode when prompted, then press enter
After all that work, it will most likely still be temperamental and require a few retries to boot. There's some weird issue with parsing and mapping the available memory
After a few tries though, it should show the login prompt. This is the end of the road for now, because there are no touch drivers etc. Until next time.