Tools: to boot mainline Debian on a vendor-locked ARM tablet How

Tools: to boot mainline Debian on a vendor-locked ARM tablet How

The problem: a $80 tablet running a kernel from 2018

Root cause: the vendor BSP trap

Step 1: find a recovery path before you break anything

Step 2: build U-Boot for the SoC, not the board

Step 3: boot from SD card first, never eMMC

Step 4: device tree is where you'll lose a weekend

Prevention: what to check before you buy Picked up a cheap Rockchip-based Android tablet last month — RK3562 SoC, 4GB RAM, 64GB eMMC, under a hundred bucks. On paper it's perfect for a kiosk, a tiny build agent, or just an ARM dev box on my desk. In practice? It ships with an Android fork running a vendor kernel that's frozen in time. No root, no developer mode, no terminal, and no obvious way to install anything that didn't come from the manufacturer's app store. I wanted a Debian shell. Not Termux pretending to be Debian, not a chroot trick, not a VM. Actual Debian, owning the hardware. This is a problem you hit constantly with cheap ARM gear: vendor BSPs are a graveyard. Old kernels, no upstream changes, a single security patch on launch day and then silence. If you want a usable Linux machine out of one, you have to bring it yourself. Here's how I worked through it, what broke, and what to check before you start. Most ARM SoCs ship with a Board Support Package — a vendor-maintained kernel fork plus a custom bootloader, device trees, and binary blobs for things like GPU, video decode, and Wi-Fi. The vendor uses it to ship a product, then walks away. The trap has three layers: So "install Debian" is really four problems stacked: get code to run at boot, get the kernel to recognize the hardware, get userspace to talk to it, and do all of this without bricking a device whose recovery path you don't fully understand yet. Rule one of ARM hacking: know how to unbrick before you brick. Most Rockchip SoCs have a maskrom mode — a hardware-level recovery state where the CPU listens on USB for a loader image, totally independent of whatever's on eMMC. Even if you nuke the bootloader, you can usually recover with rkdeveloptool: The exact PID and loader filename depend on the SoC family. Rockchip publishes prebuilt loader blobs in the rkbin tree; verify the binary matches your SoC before flashing anything persistent. If your device doesn't have a documented maskrom button combo or test pad, stop here. Recovery without it usually means short-pinning a flash chip on the PCB, and that's a different blog post. Mainline U-Boot has reasonable Rockchip support, but it expects you to pick a board config. For an SoC where there's no upstream board file for your exact tablet, the pragmatic path is to start from the closest reference design and override the device tree later. BL31 is ARM Trusted Firmware — the secure-world runtime U-Boot hands control to. You can build ATF yourself from the TF-A project or pull a prebuilt blob from rkbin. Building from source is the right long-term answer; pulling prebuilt is the right answer when you're still bisecting which combination boots at all. This is the single biggest mistake I see people make: they flash an experimental image straight to internal storage on the first try. Don't. Rockchip's boot ROM checks SD card before eMMC by default. So you can iterate on a boot image entirely from an SD card while the original Android partition on eMMC stays untouched. If the image is broken, pull the SD card — the tablet boots Android like nothing happened. Then drop a Debian arm64 rootfs onto the root partition with debootstrap: The two-stage debootstrap works because qemu-user-static transparently executes aarch64 binaries on your x86 host. Don't forget to register binfmt handlers (binfmt-support package on Debian). The kernel will boot, panic on PMIC init, and reboot. That's normal. You're missing a working DTB. Expect the touchscreen, Wi-Fi, and internal sensors to not work on first boot. Serial console and USB will. Get a USB-to-serial adapter on the debug UART pads — without one, you're flying blind. If you're shopping for cheap ARM hardware specifically to run mainline Linux, vet it first: I haven't tested every Rockchip variant thoroughly, but the RK35xx family in general has a much healthier mainline story than the RK30xx-era parts ever did. Your mileage will vary by exact silicon revision and board. The payoff is real though. An $80 chunk of hardware running clean Debian, on a current kernel, that you actually control — that's worth the weekend. Templates let you quickly answer FAQs or store snippets for re-use. Hide child comments as well For further actions, you may consider blocking this person and/or reporting abuse

Command

Copy

# Confirm the device shows up in maskrom mode -weight: 600;">sudo rkdeveloptool ld # Expected: DevNo=1 Vid=0x2207,Pid=0x350a LocationID=... Maskrom # Push a working loader into RAM (not flash) -weight: 600;">sudo rkdeveloptool db rk356x_loader_vX.XX.bin # Confirm the device shows up in maskrom mode -weight: 600;">sudo rkdeveloptool ld # Expected: DevNo=1 Vid=0x2207,Pid=0x350a LocationID=... Maskrom # Push a working loader into RAM (not flash) -weight: 600;">sudo rkdeveloptool db rk356x_loader_vX.XX.bin # Confirm the device shows up in maskrom mode -weight: 600;">sudo rkdeveloptool ld # Expected: DevNo=1 Vid=0x2207,Pid=0x350a LocationID=... Maskrom # Push a working loader into RAM (not flash) -weight: 600;">sudo rkdeveloptool db rk356x_loader_vX.XX.bin -weight: 500;">git clone https://source.denx.de/u-boot/u-boot.-weight: 500;">git cd u-boot # Use a nearby supported board as the base config make rk3568-evb_defconfig # Cross-compile with an aarch64 toolchain make CROSS_COMPILE=aarch64-linux-gnu- \ BL31=bl31.elf u-boot-rockchip.bin -weight: 500;">git clone https://source.denx.de/u-boot/u-boot.-weight: 500;">git cd u-boot # Use a nearby supported board as the base config make rk3568-evb_defconfig # Cross-compile with an aarch64 toolchain make CROSS_COMPILE=aarch64-linux-gnu- \ BL31=bl31.elf u-boot-rockchip.bin -weight: 500;">git clone https://source.denx.de/u-boot/u-boot.-weight: 500;">git cd u-boot # Use a nearby supported board as the base config make rk3568-evb_defconfig # Cross-compile with an aarch64 toolchain make CROSS_COMPILE=aarch64-linux-gnu- \ BL31=bl31.elf u-boot-rockchip.bin # Drop U-Boot at the Rockchip-expected offset -weight: 600;">sudo dd if=u-boot-rockchip.bin of=/dev/sdX seek=64 conv=notrunc # Partition the rest of the card normally -weight: 600;">sudo parted /dev/sdX mklabel gpt -weight: 600;">sudo parted /dev/sdX mkpart boot fat32 16MiB 256MiB -weight: 600;">sudo parted /dev/sdX mkpart root ext4 256MiB 100% # Drop U-Boot at the Rockchip-expected offset -weight: 600;">sudo dd if=u-boot-rockchip.bin of=/dev/sdX seek=64 conv=notrunc # Partition the rest of the card normally -weight: 600;">sudo parted /dev/sdX mklabel gpt -weight: 600;">sudo parted /dev/sdX mkpart boot fat32 16MiB 256MiB -weight: 600;">sudo parted /dev/sdX mkpart root ext4 256MiB 100% # Drop U-Boot at the Rockchip-expected offset -weight: 600;">sudo dd if=u-boot-rockchip.bin of=/dev/sdX seek=64 conv=notrunc # Partition the rest of the card normally -weight: 600;">sudo parted /dev/sdX mklabel gpt -weight: 600;">sudo parted /dev/sdX mkpart boot fat32 16MiB 256MiB -weight: 600;">sudo parted /dev/sdX mkpart root ext4 256MiB 100% -weight: 600;">sudo debootstrap --arch=arm64 --foreign bookworm /mnt/root \ http://deb.debian.org/debian # Finish stage 2 inside a qemu-user chroot -weight: 600;">sudo cp /usr/bin/qemu-aarch64-static /mnt/root/usr/bin/ -weight: 600;">sudo chroot /mnt/root /debootstrap/debootstrap --second-stage -weight: 600;">sudo debootstrap --arch=arm64 --foreign bookworm /mnt/root \ http://deb.debian.org/debian # Finish stage 2 inside a qemu-user chroot -weight: 600;">sudo cp /usr/bin/qemu-aarch64-static /mnt/root/usr/bin/ -weight: 600;">sudo chroot /mnt/root /debootstrap/debootstrap --second-stage -weight: 600;">sudo debootstrap --arch=arm64 --foreign bookworm /mnt/root \ http://deb.debian.org/debian # Finish stage 2 inside a qemu-user chroot -weight: 600;">sudo cp /usr/bin/qemu-aarch64-static /mnt/root/usr/bin/ -weight: 600;">sudo chroot /mnt/root /debootstrap/debootstrap --second-stage - Bootloader: the board runs a vendor U-Boot or proprietary loader that expects a specific boot image format, partition layout, and sometimes signed payloads. - Device tree: the hardware description (.dts/.dtb) is custom per board. Mainline ships device trees for some reference boards, but the specific touchscreen controller, PMIC, and panel on your tablet are almost certainly not there. - Drivers: GPU (Mali), VPU, Wi-Fi, and audio frequently rely on out-of-tree drivers or firmware blobs. - Dump the Android partition's DTB blob and decompile it with dtc -I dtb -O dts to get a starting point. - Diff it against the mainline DTS for the closest reference SoC. - Strip out anything vendor-specific (Android boot partitions, proprietary properties). - Search the SoC plus "mainline" or "u-boot defconfig": if the SoC has zero upstream presence, walk away. - Look for an exposed UART: serial console access is non-negotiable for debugging. - Check for a maskrom button or documented test point: this is your unbrick path. - Prefer SoCs with an active community port (Pine64, Radxa, Orange Pi families) over no-name tablets — even if the silicon is the same, the upstream work is what saves you.