cyberdeck/docs/emmc-multiboot.md

6.7 KiB

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

Proposed new partition schema:

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    root_opios   (Orange Pi OS Arch)
    ├── mmcblk1p3   ext4    85GB    root_armbian   (Armbian)
    └── mmcblk1p4   ext4    ~84GB   root_nixos   (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

Move Orange Pi OS from the microSD card to eMMC and leave two more root paritions ready for other operating systems later.

1.1 — Identify devices

Run on the running Orange Pi OS (booted from SD):

lsblk
mount | grep mmcblk

Expected:

  • mmcblk0 = SD card (current boot device)
  • mmcblk1 = eMMC (target boot device) Actual:
  • mmcblk0 = eMMC (target boot device)
  • mmcblk1 = SD card (current boot device)

Ground truth state with only OPi OS on SD card:

[jez@Rocky ~]$ lsblk
NAME         MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
mtdblock0     31:0    0    16M  0 disk 
mmcblk0      179:0    0   233G  0 disk 
mmcblk0boot0 179:32   0     4M  1 disk 
mmcblk0boot1 179:64   0     4M  1 disk 
mmcblk1      179:96   0 238.4G  0 disk 
├─mmcblk1p1  179:97   0 213.6M  0 part /boot
└─mmcblk1p2  179:98   0 238.2G  0 part /
zram0        254:0    0     0B  0 disk 

1.2 — Wipe eMMC partition table

Destroys everything on eMMC. Skip if eMMC is already empty.

sudo sgdisk --zap-all /dev/mmcblk0
sudo blkdiscard /dev/mmcblk0   # optional

1.3 — Partition eMMC

sudo gdisk /dev/mmcblk0

In gdisk interactive mode:

o   (new GPT)
n   1   default  +1G    ef00   name=boot
n   2   default  +85G   8300   name=root_opios
n   3   default  +85G   8300   name=root_armbian
n   4   default  default 8300   name=root_nixos
w   (write, confirm 'y')

1.4 — Create filesystems

sudo mkfs.vfat -F 32 -n BOOT /dev/mmcblk0p1
sudo mkfs.ext4 -L root_opios /dev/mmcblk0p2
sudo mkfs.ext4 -L root_armbian /dev/mmcblk0p3
sudo mkfs.ext4 -L root_nixos /dev/mmcblk0p4

1.5 — Mount and rsync the live rootfs

sudo mkdir -p /mnt/root_opios
sudo mount /dev/mmcblk0p2 /mnt/root_opios
sudo mkdir -p /mnt/root_opios/boot
sudo mount /dev/mmcblk0p1 /mnt/root_opios/boot

sudo rsync -axHAWX --info=progress2 / /mnt/root_opios/

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

sudo mkdir -p /mnt/root_opios/{proc,sys,dev,run,tmp}
sudo mount --bind /proc /mnt/root_opios/proc
sudo mount --bind /sys /mnt/root_opios/sys
sudo mount --bind /dev /mnt/root_opios/dev
sudo mount --bind /run /mnt/root_opios/run

1.7 — Update fstab

sudo blkid /dev/mmcblk0p1 /dev/mmcblk0p2

Edit /mnt/root_opios/etc/fstab. Replace old SD card references with:

UUID=<boot-UUID>  /boot  vfat  defaults,noatime  0  2
UUID=<root_opios-UUID> /     ext4  defaults,noatime  0  1

1.8 — Write extlinux.conf

uname -r
find /mnt/root_opios/boot -name "*.dtb" | grep orangepi-3b

Create /mnt/root_opios/boot/extlinux/extlinux.conf:

TIMEOUT 10
DEFAULT orangepi-os

LABEL orangepi-os
    MENU LABEL Orange Pi OS
    LINUX /vmlinuz-<kernel-version>
    INITRD /initrd.img-<kernel-version>
    FDT /dtbs/rockchip/rk3566-orangepi-3b.dtb
    APPEND root=UUID=<root_opios-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:

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:

sudo dd if=/dev/mmcblk1 of=idbloader.img bs=512 count=16384
sudo dd if=/dev/mmcblk1 of=u-boot.itb bs=512 skip=16384 count=8192

Write to eMMC hardware boot partition:

echo 0 | sudo tee /sys/block/mmcblk0/force_ro
sudo mmc bootpart enable 1 1 /dev/mmcblk0
sudo dd if=idbloader.img of=/dev/mmcblk0boot0 bs=512 seek=64
sudo dd if=u-boot.itb of=/dev/mmcblk0boot0 bs=512 seek=16384
sudo sync

1.10 — Clean up and test

sudo umount /mnt/root_opios/boot
sudo umount /mnt/root_opios/proc /mnt/root_opios/sys /mnt/root_opios/dev /mnt/root_opios/run
sudo umount /mnt/root_opios
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 root_armbian, kernel+DTB added to shared /boot, next LABEL added to extlinux.conf.)

Step 3: Install NixOS

(To be documented — NixOS rootfs goes into root_nixos. Likely the trickiest since NixOS generates its own /boot structure.)

Reference