megi's PinePhone Development Log RSS


2020–09–04: Pinebook Pro and Levinboot

Pinebook Pro is a very nice laptop. Software support just has a few annoying quirks:

Thankfully, a discord user CrystalGamma took to creating Levinboot, which is a specialized bootloader for Pinebook Pro and other similar RK3399 based computers. Its goals are almost identical to my p-boot project: boot the kernel as fast as possible from local storage and get out of the way. Its limitations are similar too. No or very limited support for partition schemes, no support for traditional filesystems, etc.

Version 0.7.1 was released a few days ago, so I decided to give it a try on my Pinebook Pro, and I'm happy to report that it works quite nicely, and it looks like it's going to have a bright future. :)

Boot process now shows a feedback. At first, red LED turns on for 1 sec, then green LED turns on for another sec, then red LED turns off and in another 2–3 seconds the tty shows up, and the system is interactive. That's with a small 7MiB gzip compressed kernel payload. I also tried a large 20MiB zstd compressed payload from eMMC, but that doesn't yet work as expected. I get load speeds of about 5MiB/s with that.

With lack of support for system suspend, fast boot times help make the laptop more useable.

My Levinboot setup

I use eMMC to load the payload, and SD card to load Levinboot itself. This way I can easily upgrade and test new Levinboot versions, and not worry about it breaking, because I just pop out a SD card, and update the bootloader from my PC, in case something fails.

To get Levinboot, I compile it from source code:

export CC=$CROSS-gcc
export OBJCOPY=$CROSS-objcopy
export LD=$CROSS-gcc

git clone
cd levinboot
# currently contains fixes for reading GPT partition table
git checkout dev
./ --payload-emmc --payload-zstd --payload-initcpio --with-tf-a-headers $ATF_DIR/include/export

# Copy levinboot-sd.img to my Pinebook Pro
scp levinboot-sd.img root@pbp:/boot/levinboot-emmc.img

Then I install it to SD card from Pinebook Pro itself, along with flashing payload to eMMC:

set -e -x



cp -f board.dtb board-lv.dtb
fdtput -pt s board-lv.dtb /chosen bootargs "$BOOTOPTS"

truncate -s 0 payload-lv.img
zstd -zc bl31.elf >> payload-lv.img
zstd -zc board-lv.dtb >> payload-lv.img
zstd -zc Image >> payload-lv.img
zstd -zc initramfs.img >> payload-lv.img

dd if=payload-lv.img of=/dev/mmcblk2p1
dd if=levinboot-emmc.img of=/dev/mmcblk1 seek=64
#dd if=levinboot-sd.img of=/dev/mmcblk1 seek=64


When booting from eMMC, Levinboot expects to find payload in a special GPT partition. I just use a single partition with GUID e5ab07a0-8e5e-46f6-9ce8-41a518929b7c.

This is all documented in detail in the Levinboot README file.