Dual-booting the pinenote with android and debian
(Restored: original date: January 8, 2022)
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 modules
– Rooted 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 1500000/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.