Upgrading from System Image Version 2 to Version 3 on NVME

Hey quick update. Typing this from my fully-upgraded MNT Reform!

Thank You for those links; they were crucial to my successful migration. Biggest hurdle (hinted at in the IRC logs) was the stateful reform-flash-* scripts on the system image provided; The Checksum mismatch is apparently due to an updated reform-check et al that is not on that image, along with a few other changes. Running a full apt update && apt upgrade on the system image, not on the prior installation, was required for me to be able to use the reform-tools.

Unfortunately, having taken a page from violet’s experience and decided to flash the system image directly to my emmc when it was not working, I ran into another barrier: There is not enough free space on the emmc at that point to allow the apt upgrade to take place. I had to work around this by mounting my nvme /home partition on /var/cache/apt/ to give it enough space to download everything.

In summation, the steps I took were:

  1. Run apt update and apt upgrade on my prior OS.
  2. Run apt install linux-image-arm64 explicitly, as for some reason it wasn’t installed. reform-tools was, though.
  3. Run the commands in the script to remove the unneeded parts from the prior installation.
  4. Run reform-check a bunch, addressing the issues mentioned. Specifically, I needed to install a bunch of packages and fix my fstab a bit (though this was overwritten later).
  5. Configure my MNT Reform to boot to the emmc using reform-boot-config.
  6. Reboot.
  7. Mount one of my nvme partitions on /var/cache/apt to give apt more space.
  8. Connect to my internet.
  9. Run apt update && apt upgrade in the emmc enviroment.
  10. Make sure my /etc/fstab in the emmc environment has a /boot/ entry.
  11. Run the commands You mentioned in the IRC log:
    • { echo LINUX_KERNEL_CMDLINE=\"console=ttymxc0,115200 console=tty1\"; echo LINUX_KERNEL_CMDLINE_DEFAULTS=\"ro no_console_suspend cma=512M pci=nomsi\"; } > /etc/default/flash-kernel
    • printf "pwm_imx27\nnwl-dsi\nti-sn65dsi86\nimx-dcss\npanel-edp\nmux-mmio\nmxsfb\nusbhid\nimx8mq-interconnect\n" > /etc/initramfs-tools/modules
    • echo "MNT Reform 2" > /etc/flash-kernel/machine
  12. Run reform-check a bunch, addressing the issues mentioned. Specific issues here included needing to update uboot on everything (reform-flash-uboot; reform-flash-uboot emmc; reform-flash-uboot sd) and having to clean up some errant files.
  13. Perform a fresh reform-migrate to the first partition on my NVME drive, allowing old files to be overwritten with new ones.
  14. Run reform-boot-config nvme to boot back to the right place.
  15. Reboot.
  16. Remove the SD Card I ended up not really using, as after updating my emmc uboot it will always be the boot target from emmc, as You mentioned.
  17. Reboot again.
  18. Finally in my nvme OS again, but a few stateful things aren’t working on the debian side, and /etc/fstab has been completely overwritten.
  19. Run apt --fix-broken install to fix the conflicts introduced by copying one debian over another.
  20. Run systemctl list-units --failed, mine had 3 issues:
    • I needed to run apt reinstall openssh-server avahi-daemon exim4 rtkit to let Debian do its thing.
    • I needed to delete the old /var/log/exim4/* files, as they were not accessible by the new exim4 user.
    • I needed to ignore the failed rtkit service, as it no longer exists and disappeared after a reboot.
  21. I had to reset my hostname using hostnamectl.
  22. I had to recreate my user, because (obviously) they were not in the new system yet, despite their homer directory existing (do this before You mount /home so that You don’t need to move Your files!).
  23. I had to add my user to the dialout group, as that’s the only supplemental group that’s missing from the defaults.
  24. /etc/fstab needed to be fully recreated; This prevented Guix from working at all up until this point, as the store is on a seperate partition. Once /etc/fstab had everything, I ran systemctl daemon-reload and mount -a.
  25. I then noticed my time was way off, so I ran timedatectl set-timezone to set my local time zone.
  26. I also needed to re-setup a bunch of other Guix things; After downloading the binary install script again, I reran a few of its sections:

NOTE: If You run Guix, this edit bypasses a bunch of the safety checks and stuff. Might be worth rerunning the script as a whole first and seeing if it works for You.

_msg()
{ # Default message to stdout.
    printf "[%s]: %s\n" "$(date +%s.%3N)" "$1"
}

_debug()
{
    if [ "${DEBUG}" = '1' ]; then
        printf "[%s]: %s\n" "$(date +%s.%3N)" "$1"
    fi
}

sys_create_build_user()
{ # Create the group and user accounts for build users.

    _debug "--- [ ${FUNCNAME[0]} ] ---"

    if getent group guixbuild > /dev/null; then
        _msg "${INF}group guixbuild exists"
    else
        groupadd --system guixbuild
        _msg "${PAS}group <guixbuild> created"
    fi

    if getent group kvm > /dev/null; then
        _msg "${INF}group kvm exists and build users will be added to it"
        local KVMGROUP=,kvm
    fi

    for i in $(seq -w 1 10); do
        if id "guixbuilder${i}" &>/dev/null; then
            _msg "${INF}user is already in the system, reset"
            usermod -g guixbuild -G guixbuild${KVMGROUP}     \
                    -d /var/empty -s "$(which nologin)" \
                    -c "Guix build user $i"             \
                    "guixbuilder${i}";
        else
            useradd -g guixbuild -G guixbuild${KVMGROUP}     \
                    -d /var/empty -s "$(which nologin)" \
                    -c "Guix build user $i" --system    \
                    "guixbuilder${i}";
            _msg "${PAS}user added <guixbuilder${i}>"
        fi
    done
}

sys_create_shell_completion()
{ # Symlink supported shell completions system-wide

    var_guix=/var/guix/profiles/per-user/root/current-guix
    bash_completion=/etc/bash_completion.d
    zsh_completion=/usr/share/zsh/site-functions
    fish_completion=/usr/share/fish/vendor_completions.d

    { # Just in case
        for dir_shell in $bash_completion $zsh_completion $fish_completion; do
            [ -d "$dir_shell" ] || mkdir -p $dir_shell
        done;

        ln -sf ${var_guix}/etc/bash_completion.d/* "$bash_completion";
        ln -sf ${var_guix}/share/zsh/site-functions/* "$zsh_completion";
        ln -sf ${var_guix}/share/fish/vendor_completions.d/* "$fish_completion"; } &&
        _msg "${PAS}installed shell completion"
}

sys_maybe_setup_selinux()
{
    if [ -f /sys/fs/selinux/policy ]
    then
	prompt_yes_no "Install SELinux policy required to run guix-daemon?" \
	    || return

	local var_guix=/var/guix/profiles/per-user/root/current-guix
	semodule -i "${var_guix}/share/selinux/guix-daemon.cil"
	restorecon -R /gnu /var/guix
    fi
}

sys_create_build_usr
sys_create_shell_completion
sys_maybe_setup_selinux

After all of that, I have a fully working MNT Reform on System Version 3 that boots from emmc to an NVME drive, without having to start completely from scratch.

Upon reflection, would probably have been easier to just fully start over with a fresh root partition, but I’m very stubborn, haha. I wanted to share my full experience in case it’s useful to anyone else trying to do the same thing.

I think my main barrier was that I have limited experience with Uboot, the ARM architecture in general, and the reform community in general (for news about updates and features; My machine had gotten very out of date). Here’s a brief list of things I learned about along the way that I couldn’t find clear documentation for before taking these last few days; Might try to write a guide to it somewhere eventually:

  • How Uboot actually works, including /boot.scr and the way the emmc uses it.
  • The differences between /dev/mmcblk0boot1, /dev/mmcblk0p1, /dev/mmcblk1p1, and how the system uses them.
  • What reform-boot-config, reform-check, reform-flash-*, and friends do.

Thanks for Your help and links! I learned a lot, and am happy to be a part of this community!

2 Likes