Ubuntu Core 20 boot-hang on i.MX8MP

Hello there,

Been a while since I was last here. I was given a imx8 devboard to start developing a Core20 image, with a TPM for FDE. My initial boot process works, but then times out with the error that the “writable” partition was not found. I patched the kernel with the apparmor + snappy configs I made previously. The devboard is currently booting off a SD-card, with later modifications to be made to the image to point to the internal eMMC.

Kernel log:

[    3.231017]   No soundcards found.
[    3.279416] mmc1: new ultra high speed SDR104 SDHC card at address 5048
[    3.289118] mmcblk1: mmc1:5048 SD32G 29.7 GiB
[    3.297684]  mmcblk1: p1
[    3.761797] imx6q-pcie 33800000.pcie: Phy link never came up
[    3.770090] imx6q-pcie 33800000.pcie: failed to initialize host
[    3.778537] imx6q-pcie 33800000.pcie: unable to add pcie port.
[    3.787575] Freeing unused kernel memory: 2816K
[    3.800535] Run /init as init process
Loading, please wait...
starting version 229
[    3.837309] random: systemd-udevd: uninitialized urandom read (16 bytes read)
[    3.839901] random: udevadm: uninitialized urandom read (16 bytes read)
[    3.846828] random: systemd-udevd: uninitialized urandom read (16 bytes read)
Begin: Loading essential drivers ... done.
Begin: Running /scripts/init-premount ... done.
Begin: Mounting root file system ... Begin: Running /scripts/nfs-top ... done.
Begin: Running /scripts/nfs-premount ... done.
Begin: Running /scripts/local-top ... done.
Begin: Running /scripts/local-premount ... [   84.196253] random: crng init done
[   84.201903] random: 7 urandom warning(s) missed due to ratelimiting
findfs: unable to resolve 'LABEL=writable'
the requried kernel commandline s[  184.556636] kvm: exiting hardware virtualization
nap_core is not set
Rebooting automatically due to panic= boot argument
[  184.620441] imx2-wdt 30280000.watchdog: Device shutdown: Expect reboot!
[  184.629756] reboot: Restarting system

I used the bootscript copied + modified for my use:

# Ubuntu Classic RPi U-Boot script (for armhf and arm64)

# Expects to be called with the following environment variables set:
#  devtype              e.g. mmc/scsi etc
#  devnum               The device number of the given type
#  distro_bootpart      The partition containing the boot files
#                       (introduced in u-boot mainline 2016.01)
#  prefix               Prefix within the boot partiion to the boot files
#  kernel_addr_r        Address to load the kernel to
#  fdt_addr_r           Address to load the FDT to
#  ramdisk_addr_r       Address to load the initrd to.

#devnum 1 is SDCard, 0 is MMC
setenv devnum 1
#partition number should stay the same.
setenv distro_bootpart 1
#prefix should stay the same with '/'
setenv prefix /

#imx8mp specific addresses.
setenv fdt_addr_r 0x43000000
setenv ramdisk_addr_r 0x43800000
setenv kernel_addr_r 0x40480000

#Ubuntu Core specific stuffs.
setenv devtype mmc
setenv kernel_filename vmlinuz
setenv core_state "uboot/ubuntu/boot.sel"
setenv kernel_bootpart ${distro_bootpart}

if test -z "${fk_image_locations}"; then
  setenv fk_image_locations ${prefix}

for pathprefix in ${fk_image_locations}; do
  echo "loading ${pathprefix}${core_state}"
  if load ${devtype} ${devnum}:${distro_bootpart} ${kernel_addr_r} ${pathprefix}${core_state}; then
    echo "Loaded core state..."
    # Core image; set defaults for core's state then import from the first
    # boot.sel file. Then load the mutable boot.sel file from the next
    # partition
    setenv kernel_filename kernel.img
    setenv kernel_vars "snap_kernel snap_try_kernel kernel_status"
    setenv recovery_vars "snapd_recovery_mode snapd_recovery_system snapd_recovery_kernel"
    setenv snapd_recovery_mode "install"
    setenv snapd_standard_params "panic=-1 systemd.gpt_auto=0 rd.systemd.unit=basic.target"

    env import ${kernel_addr_r} ${filesize} ${recovery_vars}
    setenv bootargs "${bootargs} snapd_recovery_mode=${snapd_recovery_mode} snapd_recovery_system=${snapd_recovery_system} ${snapd_standard_params}"

    if test "${snapd_recovery_mode}" = "run"; then
      setexpr kernel_bootpart ${distro_bootpart} + 1
      load ${devtype} ${devnum}:${kernel_bootpart} ${kernel_addr_r} ${pathprefix}${core_state}
      env import ${kernel_addr_r} ${filesize} ${kernel_vars}
      setenv kernel_name "${snap_kernel}"

      if test -n "${kernel_status}"; then
        if test "${kernel_status}" = "try"; then
          if test -n "${snap_try_kernel}"; then
            setenv kernel_status trying
            setenv kernel_name "${snap_try_kernel}"
        elif test "${kernel_status}" = "trying"; then
          setenv kernel_status ""
        env export ${kernel_addr_r} ${kernel_vars}
        echo "saving ${pathprefix}${core_state} on ${devtype} ${devnum}:${kernel_bootpart}"
        save ${devtype} ${devnum}:${kernel_bootpart} ${kernel_addr_r} ${pathprefix}${core_state} ${filesize}
                echo "saved"
      setenv kernel_prefix "${pathprefix}uboot/ubuntu/${kernel_name}/"
      setenv kernel_prefix "${pathprefix}systems/${snapd_recovery_system}/kernel/"
    # Classic image; the kernel prefix is unchanged, nothing special to do
    setenv kernel_prefix "${pathprefix}"

  # Store the gzip header (1f 8b) in the kernel area for comparison to the
  # header of the image we load. Load "$kernel_filename" into the portion of
  # memory for the RAM disk (because we want to uncompress to the kernel area
  # if it's compressed) and compare the word at the start
  mw.w ${kernel_addr_r} 0x8b1f  # little endian
  if load ${devtype} ${devnum}:${kernel_bootpart} ${ramdisk_addr_r} ${kernel_prefix}${kernel_filename}; then
        load ${devtype} ${devnum}:${kernel_bootpart} ${fdt_addr_r} ${kernel_prefix}/dtbs/imx8mp-var-som-symphony.dtb
    if cmp.w ${kernel_addr_r} ${ramdisk_addr_r} 1; then
      # gzip compressed image (NOTE: *not* a self-extracting gzip compressed
      # kernel, just a kernel image that has been gzip'd)
      echo "Decompressing kernel..."
      unzip ${ramdisk_addr_r} ${kernel_addr_r}
      setenv kernel_size ${filesize}
      setenv try_boot "booti"
      # Possibly self-extracting or uncompressed; copy data into the kernel area
      # and attempt launch with bootz then booti
      echo "Copying kernel..."
      cp.b ${ramdisk_addr_r} ${kernel_addr_r} ${kernel_size}
      setenv try_boot "bootz booti"

    if load ${devtype} ${devnum}:${kernel_bootpart} ${ramdisk_addr_r} ${kernel_prefix}initrd.img; then
      setenv ramdisk_param "${ramdisk_addr_r}:${filesize}"
      setenv ramdisk_param "-"
    for cmd in ${try_boot}; do
        echo "Booting Ubuntu (with ${cmd}) from ${devtype} ${devnum}:${partition}..."
        ${cmd} ${kernel_addr_r} ${ramdisk_param} ${fdt_addr_r}

I suspect that the bootscript is valid, but not the kernel? I noticed that it threw an error of

findfs: unable to resolve 'LABEL=writable'
the requried kernel commandline snap_core is not set

I see that there’s still some Core16-18 related stuff in there.

Do I need to recompile the kernel on a newer snapcraft version? (Mine is currently on 4.x for legacy support reasons)

It appears that the newer snapcraft versions does not have the kernel plugin included, so I then used this information from here: Tracks 18 & 20 request for nitrogen-gadget & nitrogen-kernel to compile the kernel.

Note that the kernel referenced by the user, points to a git repo, and I found the extra initrd and kernel plugin to compile the snap. Also note that snapcraft version 7.x does not support local plugins anymore, so just use an older snapcraft version (6.x) to compile your kernel.