I finally got a compatible device (Redmi Note 4 - 2017)
Hardest part?
Unlocking the bootloader. Because it’s Xiaomi. I have screenshots from the whole process, but that’s more of a thing for “mildly infuriating” community.
Fun fact: Xiaomi doesn’t even allow installing APKs via ADB without Mi account…
Why is it running plasma-desktop?
It’s the first UI I tried. I’ve used it with a touchscreen before, and it worked well.
I’ve also tried installing both plasma-mobile and plasma-desktop, but the configurations seem to clash.
Also, when I use Android I always increase DP in developer settings to >600 which switches some UI elements to tablet mode. I prefer more things on the screen.
plasma-mobile vs plasma-desktop
Apples and oranges, yes, but I’ll compare them. I am allergic to apples, but not oranges. Wait, that’s not what I was talking about…
Nice things in plasma-desktop
Sleep works (dmesg reports s2idle).
More powerful UI (proper desktop).
Nice things in plasma-mobile
Extra buttons in Konsole (tab, arrows, ctrl).
Screen can be locked and turned off.
Existing buttons on phone are automatically mapped to navigation in Plasma.
Bad things about plasma-desktop
Even if I set power button to “Turn of screen”, it immediately turns back on.
Awful CLI experience without needed buttons.
Bad things about plasma-mobile
Sleep isn’t available as power option. systemctl suspend seems to properly put it into sleep based on kernel logs, but pressing button first time won’t do anything, while causing a reboot when pressed the second time.
While phone’s buttons are mapped, I didn’t find a setting to hide on-screen buttons, so you just get each button twice.
Running without modifying anything (aside from bootloader unlocking)
I didn’t yet want to modify anything on the device, so I just flashed PostmarketOS to SD card.
The device is then booted through a computer using fastboot boot with lk2nd bootloader image.
Miscellaneous
This section is just about me being dumb.
I have no idea about what’s going on during the boot process.
There’s 49 partitions on the internal storage, I don’t know what they’re all used for, nor how data is loaded from them.
Partition table
<> Device Start End Size Attrs Name 1 131072 303103 84M GUID:60 modem 2 393216 393217 1K fsc 3 393218 393233 8K ssd 4 393234 394257 512K sbl1 5 394258 395281 512K sbl1bak 6 395282 396305 512K rpm 7 396306 397329 512K rpmbak 8 397330 401425 2M tz 9 401426 405521 2M tzbak 10 405522 406033 256K devcfg 11 406034 406545 256K devcfgbak 12 406546 439313 16M dsp 13 439314 442385 1.5M modemst1 14 442386 445457 1.5M modemst2 15 524288 524351 32K GUID:60 DDR 16 524352 527423 1.5M GUID:60 fsg 17 527424 527455 16K GUID:60 sec 18 655360 677887 11M splash 19 786432 788479 1M GUID:60 aboot 20 788480 790527 1M GUID:60 abootbak 21 790528 921599 64M GUID:60 boot 22 921600 1052671 64M GUID:60 recovery 23 1052672 1054719 1M GUID:60 devinfo 24 1054720 7346175 3G GUID:60 system 25 7471104 7995391 256M cache 26 7995392 8060927 32M persist 27 8060928 8062975 1M misc 28 8062976 8063999 512K keystore 29 8064000 8064063 32K config 30 8064064 8588351 256M oem 31 8650752 8650815 32K GUID:60 limits 32 8781824 8782847 512K mota 33 8782848 8784895 1M dip 34 8784896 8850431 32M mdtp 35 8850432 8851455 512K syscfg 36 8851456 8859647 4M mcfg 37 8912896 8913151 128K GUID:60 lksecapp 38 8913152 8913407 128K GUID:60 lksecappbak 39 8913408 8913919 256K GUID:60 cmnlib 40 8913920 8914431 256K GUID:60 cmnlibbak 41 8914432 8914943 256K GUID:60 cmnlib64 42 8914944 8915455 256K GUID:60 cmnlib64bak 43 8915456 8915967 256K GUID:60 keymaster 44 8915968 8916479 256K GUID:60 keymasterbak 45 9043968 9044479 256K apdp 46 9044480 9044991 256K msadp 47 9044992 9045007 8K dpo 48 9045008 10748943 832M cust 49 10748944 122142686 53.1G userdata
If I collected info correctly, BootROM loads whatever SBL is, which then loads whatever ABOOT is (which probably includes fastboot), which then decides what to load next (recovery, boot).
But how?
Does it look at the partition table for the names/UUID, or does it look for disk offsets? (There are suspicious holes between partitions.)
If the former, I could re-partition it.
If the latter, I’d be fucked.
Anyway, when it comes to backups, I first erased cache and userdata (fastboot erase), booted TWRP, and cat the internal storage over ADB shell, storing it as a sparse file. It takes up just 3.3GiB.
I also checksummed the storage and image file for verification.
I also tried to extract the stock recovery into Android boot image without extra data after it.
I don’t know how to determine the real size, so I used unpack_bootimg and mkbootimg to get the original image, rather than whole partition.
The checksum of re-created boot image was different to original truncated partition image, but upon closer inspection with xxd and diff, this was just a difference in header:
00000010: 68c2 4f00 0000 0081 0000 0000 0000 f080 h.O....... | 00000010: 68c2 4f00 0000 0081 0000 0000 0000 0000 h.O.......
But I found it might indeed be a good idea to just keep a full image backup. After a bunch of NULLs, there’s more data.
file doesn’t recognize it, but running strings on it reveals readable text:
California1
San Narciso1
Yoyodyne, Inc.1
Yoyodyne Mobility1
Yoyodyne1#0!
yoyodyne@example.com0
Indeed, it seems this is a certificate: source.android.com/docs/core/ota/sign_builds#sign…
Anyway, I am once again getting reminded it might be good to learn assembly (ARM in this case). The content of sbl1 and aboot seems to be an ELF, so I might be able to pop it into Ghdira, and try to figure out what it’s doing.
Maybe. I don’t know, I have the most stupid of ideas usually.
現地開催。「世界中のApple IT管理者が集うグローバルコミュニティMac Admins。その運営母体である米 Mac Admins Foundation の公式日本コミュニティ(一般社団法人 Mac Admins Japan)が、2026年7月に設立」
---
Mac Admins Japan Meet-up #0 (2026/08/25 19:00〜)
https://connpass.com/event/402234/#bookmarks
@VictoriaFerryRetroGeek@piaille.fr Negative bit number isn't necessarily incorrect. The CPU internally modulo the bit number by 32, even if negative.
Thus, for example:
btst #-32,d0
btst #-64,d0
btst #-96,d0
All those btst are entirely valid, and the same as btst #0,d0.
The question is if the value is actually correct (even if negative). If it is not correct then this is a problem indeed.
@harblinger@wizard.casa@bagder@mastodon.social possible the lad is either very good at grammar or used ai to help write. either way its a nice sentiment. curl has been my #0 tool since its inception.
Their write-up suggests that vulnerable external code trusts the file size from stat(), uses it in malloc(), then reads via read(), and read() fills more bytes than stat() reported.
The problem is: the mismatch between the reported file size and the readable data size is so common, so one must never use that stat()->malloc()->read() path.
A simple FAT corruption triggers that (the interrupted update chain is enough: the FAT records a longer cluster chain while a directory entry wasn't updated due to a power loss or a crash).
Even NTFS does that (the file size reported via readdir()-like calls can be different than the file size reported via the stat()-like calls).