Appendix · reference

Build environment

ssh honor, mise tasks, the patch pipeline, and the cross-build.sh trap.

This is the operational reference for the build host and the patch-build-deploy loop. For the narrative — why these constraints exist and what we tried before settling on them — see essay 3, “Building from source on honor”.

Build host

honor is the only machine we cross-build on.

A clean buildkernel is about 5 minutes. An incremental rebuild after touching one driver file is around 18 seconds.

Why stable/15 + clang specifically

The patch pipeline

mise run patch does, in order:

  1. honeyguide/patch.shgit reset --hard on freebsd-src, then apply the Honeyguide overlays and patches on top of stock stable/15.
  2. cp -r ~/drm-subtree/* freebsd-src/sys/dev/drm/ — drop the full out-of-tree DRM panfrost stack on top.
  3. cp -r ../src/* freebsd-src/ — apply our overlays. These override anything Honeyguide or drm-subtree shipped, file-for-file.
  4. For every *.patch under ../patches/, patch -p0 it onto the matching path in freebsd-src/.

The git reset --hard is destructive. Never edit freebsd-src/ directly on honor — anything you change there gets wiped on the next mise run patch. Always edit in this repo, push, pull on honor, then run patch.

mise tasks

mise run patch                          # sync overlays + apply patches
mise run build-kernel                   # full PINEPHONE_PRO buildkernel (clang)
mise run build-module bcm_hostwake      # single module
mise run build-dtb                      # rebuild base DTB (rare; we use overlays)
mise run build                          # patch + build-dtb + build-kernel
mise run create-image                   # clean expandable SD image
mise run create-image-preloaded         # image with X11 + omfreebdy + packages
mise run install <drive>                # copy kernel + DTB to mounted SD card
mise run flash                          # dd image to phone in UMS mode
mise run boot                           # tap U-Boot menu over serial to boot
mise run image                          # full pipeline: sync + build + create-image-preloaded
mise run sync                           # rsync local repo → honor (alternative to git push)

Task definitions live in mise.toml at the repo root.

The deploy step

Kernels build on honor; the phone runs them; the laptop sits in the middle. We pipe through it rather than letting honor push directly to the phone, both because honor doesn’t have routing to the phone’s USB network and because we want one canonical workflow regardless of where honor lives.

╞═ deploy a freshly built kernel ═╡
ssh honor 'cat ~/pine64-freebsd/honeyguide/obj.clang/.../kernel/kernel' \
  | ssh pinephone 'sudo tee /boot/kernel/kernel > /dev/null'
ssh pinephone 'sudo reboot'

ssh pinephone resolves to the phone’s USB-Ethernet IP (10.0.0.2 in our setup; see essay 4). The phone reboots, the kernel comes up, and serial console is captured to a local log file (always — see the serial capture rule).

The git workflow rule

All code changes happen locally in this repo. The flow is:

  1. Edit src/, patches/, sys/, etc. on the laptop
  2. git commit && git push origin master
  3. ssh honor 'cd ~/pine64-freebsd && git pull'
  4. mise run patch && mise run build-kernel
  5. Pipe + reboot as above

Never rsync or scp directly to honor’s freebsd-src. The git reset --hard in patch.sh will wipe it. Everything has to flow through git so the source of truth stays in one place and Honeyguide’s upstream-merge flow stays clean.

Build smoke test

If a kernel built on honor hangs at boot but a kernel from a known-good day boots fine, the suspect is almost always a stale object directory or a buildworld/kernel mismatch. The recovery is rm -rf ~/pine64-freebsd/honeyguide/obj.clang && mise run build — it costs ten minutes but isolates the variable.