Dual-booting the pinenote with android and debian

IMPORTANT: This will trash your userdata. Back up your files first. You will get the full android back but without your data.

Pre-requisites: – Pinenote kernel, dtb and modulesRooted android – Termux and ssh – this method is REALLY the easiest to get up and running with. If you want, you could fight replacing busybox to include curl and get files over some other way, but you're taking the path less travelled. – Your data you need on your pinenote BACKED UP – I'm not kidding, it all goes.

Stage 1: prepare:

Copy onto your android device (I recommend using termux and scp) : – Image, rk3566-pinenote.dtb – the kernel and it's device tree.

Stage 2: repartitioning

The only ext4 filesystem that isn't going to be upset by us placing linux on it is the /cache partition and unfortunately, debian with a window manager, wifi and onscreen keyboard is about 1Gig, and so is that partition, so no headroom. So we need to repartition.

First, we'll use that /cache partition to house a the smallest distro with parted (alpine, what a surprise) so in termux let's grab the stuff we need :

curl https://dl-cdn.alpinelinux.org/alpine/v3.15/releases/aarch64/alpine-minirootfs-3.15.0-aarch64.tar.gz > min.tar.gz
su -
mount -o remount,rw /cache
cp Image rk3566-pinenote.dtb /cache/
tar -zxf min.tar.gz -C /cache
echo "nameserver $(getprop net.dns1)" > /cache/etc/resolv.conf 
chroot /cache
apk add --no-cache parted e2fsprogs

Now, you need that USB dongle that came with your pinenote for this next step : – connect the USB dongle to your pc in-line to the pinenote – fire up a terminal emulator connected to the device at 1150000/8n1 – touch the touchscreen to see that you get output – reboot your pinenote and spam Ctrl+C in that terminal until you get

=> <INTERRUPT>

Then paste these u-boot commands :

load mmc 0:b ${kernel_addr_r} /Image
load mmc 0:b ${fdt_addr_r} /rk3566-pinenote.dtb
setenv bootargs ignore_loglevel root=/dev/mmcblk0p11 rw rootwait earlycon console=tty0 console=ttyS2,1500000n8 fw_devlink=off init=/bin/sh
booti ${kernel_addr_r} - ${fdt_addr_r}

You should get a prompt that looks similar to this :

/bin/sh: can't access tty; job control turned off
/ # ␛[6n

Now we have a VERY minimal linux running, so that's cool, but what we're here for is partitioning, so let's go!

export TERM=dumb
parted
print

You should see something like this :

Model: Generic SD/MMC Storage Card (sd/mmc)                                                                             Disk /dev/mmcblk0: 124GB                                                                                                Sector size (logical/physical): 512B/512B                                                                               Partition Table: gpt                                                                                                    Disk Flags:                                                                                                                                                                                                                                     Number  Start   End     Size    File system  Name      Flags                                                             1      8389kB  12.6MB  4194kB               uboot                                                                       2      12.6MB  16.8MB  4194kB               trust                                                                       3      16.8MB  18.9MB  2097kB               waveform                                                                    4      18.9MB  23.1MB  4194kB               misc                                                                        5      23.1MB  27.3MB  4194kB               dtbo                                                                        6      27.3MB  28.3MB  1049kB               vbmeta                                                                      7      28.3MB  70.3MB  41.9MB               boot                                                                        8      70.3MB  74.4MB  4194kB               security                                                                    9      74.4MB  209MB   134MB                recovery                                                                   10      209MB   611MB   403MB                backup                                                                     11      611MB   1685MB  1074MB  ext4         cache                                                                      12      1685MB  1702MB  16.8MB  ext4         metadata                                                                   13      1702MB  4965MB  3263MB               super                                                                      14      4965MB  4982MB  16.8MB               logo                                                                       15      4982MB  5049MB  67.1MB  fat16        device                                                                     16      5049MB  124GB   119GB   f2fs         userdata         

We're going to split that userdata partition – my suggestion (and what's documented here) is 8Gb for Android and the rest for Linux : (it looks weird here because serial connections to odd terminals are, well, weird)

(parted) resizepart 16 13049M
Warning: Shrinking a partition can cause data loss, are you sure you want to
continue?
Yes/No?
Yes/No? yes
Error: Partition(s) 11 on /dev/mmcblk0 have been written, but we have been unable to inform the kernel of the change, probably because it/they are in use.
As a result, the old partition(s) will remain in use.  You should reboot now before making further changes.
Ignore/Cancel?
Ignore/Cancel? Ignore
(parted) mkpart primary ext4 13G 100%
: Partition(s) 11 on /dev/mmcblk0 have been written, but we have been unable to inform the kernel of the change, probably because it/they are in use.
As a result, the old partition(s) will remain in use.  You should reboot now before making further changes.
Ignore/Cancel?
Ignore/Cancel? Ignore
(parted)
(parted) quit
Information: You may need to update /etc/fstab.
/ #
/ # ␛[6n exit

Here's just the commands for copy-pasta-funtimes:

resizepart 16 13049M
yes
Ignore
mkpart primary ext4 13G 100%
Ignore
quit
exit

At this point your pinenote will attempt to reboot, but we really upset the android system (you did read the warning, right?). So now we need to get back to the u-boot prompt again (spam that ctrl-c whilst rebooting the device).

Once you got there :

=> fastboot usb 0
Enter fastboot...OK 

and remove the dongle between your usb-cable and the pinenote and plug in the cable directly. Now we use the android fastboot command to wipe the userdata part in a way it will like, and boot into recovery :

fastboot erase userdata
erasing 'userdata'...
OKAY [  4.026s]
finished. total time: 4.027s
fastboot reboot

The pinenote will switch to “Charging” mode, so power it on and watch the progress-bar which will cycle MANY times at this point (it's creating a fs on userdata for us and possibly other files) but eventually the backlight will come on and then android will boot.

You probably want to reboot into fastboot mode again to re-flash your magisk'd boot partition (no need to start from a clean image though, you can simply flash the magisk'd version again from fastboot). Follow Step 1 from the other blog post then on your computer :

adb reboot bootloader
fastboot flash boot magisk_patched-23016_oYeer.img

Congratulations, android resized, and once you've launched the magisk app, back to rooted. Now, again, install termux and ssh and come back for stage 3. You're safe to restore your files and use android again, we're not going to mess with it from hereon in.

Stage 3: (re)prep for Linux

copy everything back to android : – Image, rk3566-pinenote.dtb – the kernel and it's device tree.
modules – the ones from your kernel build.

You can grab these from my github if you like (not random binary, but built from source, see the CI) with

curl -L https://github.com/iMartyn/auto-pinenote-kernel/releases/download/0f33365e0a84/release.zip > release.zip
unzip release.zip

Stage 4: minimal debian (finally!)

Here's a rant on why I suggest getting this from github

in termux:

su -
mkdir target
mkfs.ext4 /dev/block/mmcblk2p17
mount /dev/block/mmcblk2p17 target
exit

Fetch a debian arm64 base image and extract it (jq for the messy github stuff, you could also just visit https://github.com/iMartyn/pinedeb/releases/ and copy the link for the withwifi tarball) :

pkg install jq
curl -L $(curl --silent "https://api.github.com/repos/iMartyn/pinedeb/releases/latest" | jq '.assets[] | select(.name == "debian-bullseye-arm64-withwifi.tar.bz2") | .browser_download_url') > fs.tar.bz2
sudo tar -jxf fs.tar.bz2 --same-owner -C target/

Let's also add the kernel, dtbs, modules and firmware files from android at this point:

sudo cp Image rk3566-pinenote.dtb target/
sudo cp -r modules/ target/lib/
sudo mkdir -p target/lib/firmware/brcm
sudo cp -r /vendor/etc/firmware/* target/lib/firmware/
sudo cp /vendor/etc/firmware/fw_bcm43455c0_ag_cy.bin target/lib/firmware/brcm/brcmfmac43455-sdio.bin
sudo cp /vendor/etc/firmware/nvram_ap6255_cy.txt target/lib/firmware/brcm/brcmfmac43455-sdio.txt
sudo cp target/lib/firmware/BCM4345C0.hcd target/lib/firmware/brcm/BCM4345C0.hcd

Now we need to chroot to set the root password. Note that the PATH and TMP env vars from android are not friendly, so we'll set those too before running any commands in the chroot. Also, sudo from tsu won't chroot, so we're back to su

su -
chroot /mnt/linux /bin/bash
export TMP=/tmp/
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
passwd

you can if you want, add more stuff at this point with apt but given we're going to have to “rescue boot” for the next stage, you may as well wait.

So, debian installed, but not really fully bootable yet, but we can now boot into a rescue shell for that!

Stage 5: boot rescue

Again comes the need for the dongle – so go ahead and plug that in and start your terminal session in one window.

You can reboot either by issuing reboot in a su shell or by using the android interface to reboot. Then spam that control-c to get your u-boot prompt and issue the commands to boot rescue shell :

load mmc 0:11 ${kernel_addr_r} /Image
load mmc 0:11 ${fdt_addr_r} /rk3566-pinenote.dtb
setenv bootargs ignore_loglevel root=/dev/mmcblk0p17 rw rootwait earlycon console=tty0 console=ttyS2,1500000n8 fw_devlink=off init=/bin/sh
booti ${kernel_addr_r} - ${fdt_addr_r}

Very similar to before, only this time we're on a different partition :–)

You'll want to wait about 30s for some more kernel messages to pop in, but then we'll grab the waveform partition and make it a file :

dd if=/dev/mmcblk0p3 of=/lib/firmware/waveform.bin bs=1k count=2048

Now you can start making the ramdisk that debian expects (TERM=dumb helps on difficult terminals like miniterm in windows) :

export TERM=dumb
bash
mount -t proc none /proc
mount -t sysfs none /sys
depmod -a
mkinitrd /dracut-initrd.img $(uname -r)
mkimage -A arm -T ramdisk -C none -n uInitrd -d /dracut-initrd.img /uInitrd.img
exit

Ready to boot into full debian yet?! YES! When you type exit again, the pinenote will reboot, so get ready to spam the control-c again and at the INTERRUPT prompt you need :

load mmc 0:11 ${kernel_addr_r} /Image
load mmc 0:11 ${fdt_addr_r} /rk3566-pinenote.dtb
load mmc 0:11 ${ramdisk_addr_r} /uInitrd.img
setenv bootargs ignore_loglevel root=/dev/mmcblk0p17 rw rootwait earlycon console=tty0 console=ttyS2,1500000n8 fw_devlink=off init=/sbin/init
booti ${kernel_addr_r} ${ramdisk_addr_r} ${fdt_addr_r}

Note that we're now loading a ramdisk. You'll also get a terminal on the screen, so you can use a usbc docking-station to use a keyboard, mouse etc.

This post is way too long at this point, so next post will be a shorter one on getting X up and running with the touchscreen, pen and onscreen keyboard.