Enabling UBports recovery support¶
Historically since the start of GSI-based ports each port copied the recovery ramdisk into their device-specific repos, usually from already ported devices which is hardly ideal. Fortunately now with the unified UBports recovery there is just one version built on UBports CI that can be used across the board :)
Migrating to unified recovery base¶
Ideally the switch could be as simple as:
deviceinfo_use_unified_recovery="true"
deviceinfo_unified_recovery_ui_density="xxhdpi"
and if needed relocate your fstab to ramdisk-recovery-overlay/system/etc/recovery.fstab. Most other previous non-fstab files from ramdisk-recovery-overlay/ can/should be dropped unless their required purpose is verified/known (compare non-device-specific files to versions in Halium 14 unified recovery branch). For example fake /cache bind-mounting and USB ConfigFS setup should already be taken care of which also allows minimizing contents of ramdisk-recovery-overlay/init.recovery.*.rc etc.
Note
GKI v5.4/5.10 devices should disable CONFIG_USB_DUMMY_HCD in their kernels (like already done for the generic kernel-android-common branches) to avoid the need to configure sys.usb.controller prop in /init.recovery.*.rc for working USB, elsewhere this should be automatically working when the recovery boots.
Finally you may want to verify information from the below subsection matches on your port already. Updates to the recovery ramdisk will now be automatic with new commits or CI pipeline runs on the device-specific repo similar to kernel rebuilds.
Bringing up support from scratch¶
Everything from above still applies; the ramdisk-recovery-overlay/system/etc/recovery.fstab base should be created from unpacked stock (vendor/recovery) ramdisk. The file must exist with a /data entry as otherwise recovery will not boot at all. It should be further adapted e.g. from f2fs to ext4 userdata so that adb shell mount /data works (Q25 userdata example).
Additionaly ensure partitions (even with emmc type) which would receive new images during OTA updates such as those under workdir/tmp/partitions/*.img have valid /mountpoints matching their /dev/block/by-name/ partitions (FP4 recovery example). Slotted A/B ones should exclude e.g. the _a / _b suffix and let slotselect fsmgr option pick the one for current slot automatically on boot (Q25 vendor_boot/dtbo example). In the end verify the generated /etc/fstab entries point to valid block devices.
Qualcomm SoC devices typically also want at least the fs bootdevice symlink bits from original ramdisk around at ramdisk-recovery-overlay/init.recovery.${ro.hardware}.rc for the fstab entries to be correct without further changes.
Expected working features¶
Display output
USB access via ADB for e.g. UBports installer
Ubuntu Touch OTAs, see testing local OTA
Factory reset
Rebooting to specific modes (e.g.
adb reboot bootloader)FastbootD on devices with
superpartitionTouchscreen (optional)
Battery percentage reporting (optional)
Automatic display brightness dimming/blanking after timeout (optional)
Some examples across ports¶
Volla Phone X, MediaTek kernel v4.9, recovery partition, new integration
Volla Phone Quintus, MediaTek kernel v4.19, recovery as boot, switch from vendored copy
Volla Phone X23, MediaTek kernel v5.10, recovery as boot, switch from vendored copy
Fairphone 4, Qualcomm kernel v4.19, recovery partition, switch from vendored copy
As needed please get in touch with the community for help.
Additional configuration¶
Further custom prop values should be added in ramdisk-recovery-overlay/prop.halium, e.g. for tablets a landscape UI may be interesting:
ro.minui.default_rotation=ROTATION_RIGHT
ro.minui.default_touch_rotation=ROTATION_RIGHT
Others miscellaneous options of interest may be:
ro.fastbootd.available=trueto use it on even older devices with less convenient flashing optionse.g.
ro.recovery.ui.margin_height=24added margin for top logo on notched devicesro.recovery.batteryless=trueto hiding battery percentage reporting in case that’s brokenro.minui.use_qti_drm=trueto use modified-for-QTI (Qualcomm) DRM backend even withoutro.hardware=qcom, or disable it in case problematicor even
ro.boot.quiescent=trueto disable rendering of recovery UI during early bringup
Conditional or otherwise more advanced tweaks belong in the ramdisk-recovery-overlay/init.recovery.${ro.hardware}.rc.
Root filesystem expansion¶
For devices with a super partition but with originally too small logical system_a partition setup when bootstrapping with UBports installer, it’s possible to resize for grown requirements (of e.g. 24.04-2.x now shipping Qt6 stuff alongside Qt5 as well), provided enough space is still available in the container itself:
ro.systemimage.system_partition_size=4500
Testing local OTA¶
Once UBports recovery boots and you get USB connection (ADB) working you can try the following in your standalone kernel port toplevel directory:
mkdir -p ramdisk-recovery-overlay/system/bin
wget https://github.com/ubports/halium_bootable_recovery/raw/refs/heads/halium-14.0/ubports/system-image-upgrader -O ramdisk-recovery-overlay/system/bin/system-image-upgrader
chmod +x ramdisk-recovery-overlay/system/bin/system-image-upgrader
sed -i '/verify_signature()/a\ return 0' ramdisk-recovery-overlay/system/bin/system-image-upgrader
./build.sh
adb reboot bootloader; (cd workdir/tmp/partitions && for i in *.img; do fastboot flash ${i%.img} $i; done) && fastboot reboot recovery
sudo ./build/prepare-fake-ota.sh out/device_$(awk -F'"' '/^deviceinfo_codename=/ {print $2}' deviceinfo)_usrmerge.tar.xz ota
adb push ota/{*.tar.xz*,ubuntu_command} /cache/recovery && adb reboot recovery
adb wait-for-recovery && sleep 1 && adb shell tail -f /cache/ubuntu_updater.log
Once errors are fixed and assuming the OTA files aren’t the culprit the process can be retried without another push via adb shell 'mv /cache/recovery/ubuntu_command{.applying,}; setprop ctl.restart recovery'. When successful don’t forget to rm ramdisk-recovery-overlay/system/bin/system-image-upgrader ;)