
As you might know I'm not much of an Android user (let alone
developer) but in order to figure out how something low level works
you sometimes need to peek at how vendor kernels handles this. For
that it is often useful to add additional debugging.
One such case is QMI communication going on in Qualcomm SOCs.
Joel
Selvaraj wrote some nice
tooling
for this.
To make use of this a rooted device and a small kernel patch is needed
and what would be a no-brainer with Linux Mobile took me a moment to
get it to work on Android. Here's the steps I took on a Pixel 3a to
first root the device via Magisk, then build the patched kernel and
put that into a
boot.img
to boot it.
Flashing the factory image
If you still have Android on the device you can skip this step.
You can get Android 12 from
developers.google.com. I've
downloaded
sargo-sp2a.220505.008-factory-071e368a.zip
. Then put the
device into Fastboot mode (
Power
+
Vol-Down
), connect it to your
PC via USB, unzip/unpack the archive and reflash the phone:
unpack sargo-sp2a.220505.008-factory-071e368a.zip
./flash-all.sh
This wipes your device! I had to run it twice since it would time out
on the first run. Note that this unpacked zip contains another zip
(
image-sargo-sp2a.220505.008.zip
) which will become useful below.
Enabling USB debugging
Now boot Android and enable
Developer mode by going to
Settings
About then touching
Build Number (at the very bottom) 7 times.
Go back one level, then go to
System Developer Options and
enable "USB Debugging".
Obtaining boot.img
There are several ways to get
boot.img
. If you just flashed Android
above then you can fetch
boot.img
from the already mentioned
image-sargo-sp2a.220505.008.zip
:
unzip image-sargo-sp2a.220505.008.zip boot.img
If you want to fetch the exact
boot.img
from your device you can use
TWRP (see the very end of this post).
Becoming root with Magisk
Being able to
su
via
adb
will later be useful to fetch kernel
logs. For that we first download Magisk as APK. At the time of writing
v28.1 is
current.
Once downloaded we upload the APK and the
boot.img
from the previous
step onto the phone (which needs to have Android booted):
adb push Magisk-v28.1.apk /sdcard/Download
adb push boot.img /sdcard/Download
In Android open the
Files app, navigate to
/sdcard/Download
and
install the Magisk APK by opening the APK.
We now want to patch
boot.img
to get
su
via
adb
to work (so we
can run
dmesg
). This happens by hitting
Install
in the Magisk app,
then "Select a file to patch". You then select the
boot.img
we just
uploaded.
The installation process will create a
magisk_patched-<random>.img
in
/sdcard/Download
. We can pull that file via
adb
back to our
PC:
adb pull /sdcard/Download/magisk_patched-28100_3ucVs.img
Then reboot the phone into fastboot (
adb reboot bootloader
) and
flash it (this is optional see below):
fastboot flash boot magisk_patched-28100_3ucVs.img
Now boot the phone again, open the Magisk app, go to
SuperUser at
the bottom and enable
Shell.
If you now connect to your phone via
adb
again and now
su
should
work:
adb shell
su
As noted above if you want to keep your Android installation pristine
you don't even need to flash this Magisk enabled
boot.img
. I've flashed
it so I have
su
access for other operations too. If you don't want
to flash it you can still test boot it via:
fastboot boot magisk_patched-28100_3ucVs.img
and then perform the same
adb shell su
check as above.
Building the custom kernel
For our QMI debugging to work we need to patch the kernel a bit and
place that in
boot.img
too. So let's build the kernel first. For
that we install the necessary tools (which are thankfully packaged in
Debian) and fetch the Android kernel sources:
sudo apt install repo android-platform-tools-base kmod ccache build-essential mkbootimg
mkdir aosp-kernel && cd aosp-kernel
repo init -u https://android.googlesource.com/kernel/manifest -b android-msm-bonito-4.9-android12L
repo sync
With that we can apply Joel's kernel patches and also compile in the touch controller
driver so we don't need to worry if the modules in the initramfs match the kernel. The kernel
sources are in
private/msm-google
. I've just applied the diffs on top with
patch
and modified
the defconfig and committed the changes. The resulting tree is
here.
We then build the kernel:
PATH=/usr/sbin:$PATH ./build_bonito.sh
The resulting kernel is at
./out/android-msm-pixel-4.9/private/msm-google/arch/arm64/boot/Image.lz4-dtb
.
In order to boot that kernel I found it to be the simplest to just
replace the kernel in the Magisk patched
boot.img
as we have that
already. In case you have already deleted that for any reason we can
always fetch the current
boot.img
from the phone via TWRP (see below).
Preparing a new boot.img
To replace the kernel in our Magisk enabled
magisk_patched-28100_3ucVs.img
from above with the just built kernel
we can use
mkbootimg
for that. I basically copied the steps we're
using when building the
boot.img
on the Linux Mobile side:
ARGS=$(unpack_bootimg --format mkbootimg --out tmp --boot_img magisk_patched-28100_3ucVs.img)
CLEAN_PARAMS="$(echo "$ ARGS " sed -e "s/ --cmdline '.*'//" -e "s/ --board '.*'//")"
cp android-kernel/out/android-msm-pixel-4.9/private/msm-google/arch/arm64/boot/Image.lz4-dtb tmp/kernel
mkbootimg -o "boot.patched.img" $ CLEAN_PARAMS --cmdline "$ ARGS "
This will give you a
boot.patched.img
with the just built kernel.
Boot the new kernel via fastboot
We can now boot the new
boot.patched.img
. No need to flash that onto
the device for that:
fastboot boot boot.patched.img
Fetching the kernel logs
With that we can fetch the kernel logs with the debug output via
adb
:
adb shell su -c 'dmesg -t' > dmesg_dump.xml
or already filtering out the QMI commands:
adb shell su -c 'dmesg -t' grep "@QMI@" sed -e "s/@QMI@//g" &> sargo_qmi_dump.xml
That's it. You can apply this method for testing out other kernel
patches as well. If you want to apply the above to other devices you basically
need to make sure you patch the right kernel sources, the other steps should be
very similar.
In case you just need a rooted
boot.img
for sargo you can find a
patched one
here.
If this procedure can be improved / streamlined somehow please
let me know.
Appendix: Fetching boot.img from the phone
If, for some reason you lost
boot.img
somewhere on the way you can always use
TWRP to fetch the
boot.img
currently in use on your phone.
First get
TWRP for the Pixel 3a. You can
boot that directly by putting your device into fastboot mode, then running:
fastboot boot twrp-3.7.1_12-1-sargo.img
Within TWRP select
Backup Boot and backup the file. You can then use
adb shell
to locate the backup in
/sdcard/TWRP/BACKUPS/
and pull it:
adb pull /sdcard/TWRP/BACKUPS/97GAY10PWS/2025-04-02--09-24-24_SP2A220505008/boot.emmc.win
You now have the device's
boot.img
on your PC and can e.g. replace the kernel or make
modifications to the initramfs.