diff --git a/docs/emmc-multiboot.md b/docs/emmc-multiboot.md new file mode 100644 index 0000000..cb0c610 --- /dev/null +++ b/docs/emmc-multiboot.md @@ -0,0 +1,203 @@ +# eMMC Multi-Boot Setup — Orange Pi 3B + +**Status:** Procedural reference. Last verified: 2026-06-02 (discussion with Jez). + +## Goal + +Boot multiple ARM64 OSes from the OPi 3B's onboard 256GB eMMC, with a u-boot boot menu (`extlinux.conf`) appearing at power-on. No SD card needed after setup. + +**Planned OSes:** Orange Pi OS (Arch), Armbian, NixOS + +SPI NOR flash was erased via maskrom and is unused going forward. + +## Boot Chain (after SPI erase) + +``` +BootROM → SPI (empty, skip) → microSD (if inserted) → eMMC boot partition → extlinux.conf → menu → kernel +``` + +If microSD **is** inserted and has a valid bootloader, it takes priority over eMMC. Useful as a lifeboat/rescue path — if eMMC boot breaks, pop in the SD card and you're back. + +## Partition Layout + +``` +mmcblk1 (256GB eMMC) +├── mmcblk1boot0 (hardware boot partition — u-boot SPL + proper) +├── mmcblk1boot1 (unused mirror) +└── mmcblk1 + ├── mmcblk1p1 FAT32 1GB /boot (extlinux.conf, kernels, DTBs — shared) + ├── mmcblk1p2 ext4 85GB root1 (Orange Pi OS Arch) + ├── mmcblk1p3 ext4 85GB root2 (Armbian) + ├── mmcblk1p4 ext4 ~84GB root3 (NixOS) +``` + +### Why a dedicated FAT32 boot partition? + +u-boot reads `extlinux.conf` from a FAT, ext4, or btrfs partition. FAT32 is the most universally supported across distro kernel packages. A shared `/boot` means all three OSes drop their kernels and DTBs into one place, and a single `extlinux.conf` controls the menu. 1GB gives headroom for multiple kernel versions across all three OSes. + +## Step 1: Clone SD → eMMC (Orange Pi OS, leaves root2/root3 ready) + +### 1.1 — Identify devices + +Run on the running Orange Pi OS (booted from SD): + +```bash +lsblk +mount | grep mmcblk +``` + +Expected: `mmcblk0` = SD card (boot device), `mmcblk1` = eMMC (target). + +### 1.2 — Wipe eMMC partition table + +**Destroys everything on eMMC.** Skip if eMMC is already empty. + +```bash +sudo sgdisk --zap-all /dev/mmcblk1 +sudo blkdiscard /dev/mmcblk1 # optional +``` + +### 1.3 — Partition eMMC + +```bash +sudo gdisk /dev/mmcblk1 +``` + +In `gdisk` interactive mode: + +``` +o (new GPT) +n 1 default +1G ef00 name=boot +n 2 default +85G 8300 name=root1 +n 3 default +85G 8300 name=root2 +n 4 default default 8300 name=root3 +w (write, confirm 'y') +``` + +### 1.4 — Create filesystems + +```bash +sudo mkfs.vfat -F 32 -n BOOT /dev/mmcblk1p1 +sudo mkfs.ext4 -L root1 /dev/mmcblk1p2 +sudo mkfs.ext4 -L root2 /dev/mmcblk1p3 +sudo mkfs.ext4 -L root3 /dev/mmcblk1p4 +``` + +### 1.5 — Mount and rsync the live rootfs + +```bash +sudo mkdir -p /mnt/root1 +sudo mount /dev/mmcblk1p2 /mnt/root1 +sudo mkdir -p /mnt/root1/boot +sudo mount /dev/mmcblk1p1 /mnt/root1/boot + +sudo rsync -axHAWX --info=progress2 / /mnt/root1/ +``` + +Flags: archive, stay-on-filesystem (critical — skips /proc, /sys, /dev), preserve +hardlinks/ACLs/xattrs, copy whole files (faster locally). + +### 1.6 — Bind mount virtual filesystems + +```bash +sudo mkdir -p /mnt/root1/{proc,sys,dev,run,tmp} +sudo mount --bind /proc /mnt/root1/proc +sudo mount --bind /sys /mnt/root1/sys +sudo mount --bind /dev /mnt/root1/dev +sudo mount --bind /run /mnt/root1/run +``` + +### 1.7 — Update fstab + +```bash +sudo blkid /dev/mmcblk1p1 /dev/mmcblk1p2 +``` + +Edit `/mnt/root1/etc/fstab`. Replace old SD card references with: + +``` +UUID= /boot vfat defaults,noatime 0 2 +UUID= / ext4 defaults,noatime 0 1 +``` + +### 1.8 — Write extlinux.conf + +```bash +uname -r +find /mnt/root1/boot -name "*.dtb" | grep orangepi-3b +``` + +Create `/mnt/root1/boot/extlinux/extlinux.conf`: + +``` +TIMEOUT 10 +DEFAULT orangepi-os + +LABEL orangepi-os + MENU LABEL Orange Pi OS + LINUX /vmlinuz- + INITRD /initrd.img- + FDT /dtbs/rockchip/rk3566-orangepi-3b.dtb + APPEND root=UUID= rootwait console=ttyS2,115200 console=tty1 +``` + +### 1.9 — Install u-boot to eMMC hardware boot partition + +First check if Orange Pi OS ships u-boot binaries: + +```bash +find / -name "idbloader.img" -o -name "u-boot.itb" -o -name "*loader*" 2>/dev/null +``` + +If files exist at known paths, use them. If not, extract from SD card: + +```bash +sudo dd if=/dev/mmcblk0 of=idbloader.img bs=512 count=16384 +sudo dd if=/dev/mmcblk0 of=u-boot.itb bs=512 skip=16384 count=8192 +``` + +Write to eMMC hardware boot partition: + +```bash +echo 0 | sudo tee /sys/block/mmcblk1/force_ro +sudo mmc bootpart enable 1 1 /dev/mmcblk1 +sudo dd if=idbloader.img of=/dev/mmcblk1boot0 bs=512 seek=64 +sudo dd if=u-boot.itb of=/dev/mmcblk1boot0 bs=512 seek=16384 +sudo sync +``` + +### 1.10 — Clean up and test + +```bash +sudo umount /mnt/root1/boot +sudo umount /mnt/root1/proc /mnt/root1/sys /mnt/root1/dev /mnt/root1/run +sudo umount /mnt/root1 +sudo sync +sudo poweroff +``` + +Remove SD card. Power on. u-boot logo → boot menu → Orange Pi OS from eMMC. + +### Troubleshooting + +| Symptom | Likely cause | Fix | +|---------|-------------|-----| +| u-boot logo, then blank screen | EDID/HDMI handshake | Add `video=HDMI-A-1:1920x1080@60e` to APPEND line | +| "No bootable device" | u-boot not written to eMMC boot part | Re-do step 1.9 | +| Kernel panic: can't find root | Wrong UUID in extlinux.conf | Boot from SD, mount eMMC, fix UUID | +| Nothing on screen at all | SPI flash interference? HDMI? | Re-check SPI erase, try different monitor | + +## Step 2: Install Armbian + +(To be documented — Armbian rootfs goes into root2, kernel+DTB added to shared /boot, next LABEL added to extlinux.conf.) + +## Step 3: Install NixOS + +(To be documented — NixOS rootfs goes into root3. Likely the trickiest since NixOS generates its own /boot structure.) + +## Reference + +- Rockchip boot flow: +- U-boot extlinux format: +- OPi 3B bring-up: `docs/initial-bringup.md` +- Storage architecture: `docs/storage-architecture.md` \ No newline at end of file