Custom core20 image: boot error: file '/kernel.efi' not found

Hi,

I built a custom image following the documentation from https://ubuntu.com/core/docs/custom-images . The custom model assertion I used to build the image looks like:

{
    "type": "model",
    "series": "16",
    "authority-id": "my-id",
    "brand-id": "my-id",
    "model": "custom-ubuntu-core-20-amd64",
    "architecture": "amd64",
    "timestamp": "2021-02-17T20:33:40+00:00",
    "base": "core20",
    "grade": "signed",
    "snaps": [
        {
            "name": "pc",
            "type": "gadget",
            "default-channel": "20/stable",
            "id": "UqFziVZDHLSyO3TqSWgNBoAdHbLI4dAH"
        },
        {
            "name": "pc-kernel",
            "type": "kernel",
            "default-channel": "latest/stable",
            "id": "pYVQrBcKmBa0mZ4CCN7ExT6jH8rY1hza"
        },
        {
            "name": "core20",
            "type": "base",
            "default-channel": "latest/stable",
            "id": "DLqre5XGLbDqg9jPtiAhRRjDuPVa5X1q"
        },
         {
            "name": "snapd",
            "type": "snapd",
            "default-channel": "latest/stable",
            "id": "PMrrV4ml8uWuEUDBT8dSGnKUYbevVhc4"
        },
        {
            "name": "htop",
            "type": "app",
            "default-channel": "latest/stable",
            "id": "hJmReLmgXSUj4SF7WhyTVRV6IzUa4QUZ"
        }
    ]
}

Once the image was generated I tested it using QEMU with the following command:

qemu-system-x86_64 -enable-kvm -smp 2 -m 1500 -netdev user,id=mynet0,hostfwd=tcp::8022-:22,hostfwd=tcp::8090-:80 -device virtio-net-pci,netdev=mynet0 -drive file=custom-model-image20/pc.img,format=raw -drive file=/usr/share/OVMF/OVMF_CODE.fd,if=pflash,format=raw,unit=0,readonly=on

But it fails booting with the following message:

error: file '/kernel.efi' not found. 

So, the kernel never gets loaded and the process doesn’t pass from the GRUB menu.

Does anyone know why that’s failing if the snaps are all from stable channels?

Thanks.

You need to use a kernel from track 20, eg in your model:

        {
            "name": "pc-kernel",
            "type": "kernel",
            "default-channel": "20/stable",
            "id": "pYVQrBcKmBa0mZ4CCN7ExT6jH8rY1hza"
        },
1 Like

Yes, that works very well, thank you for your answer!

The next step would be to create a custom image with a custom kernel, for that I cloned the ubuntu-focal kernel repository (https://kernel.ubuntu.com/git/ubuntu/ubuntu-focal.git) and built the kernel snap. Now the model assertion uses the grade “dangerous” and contains a local rebuilt kernel snap, it looks like:

{
    "type": "model",
    "series": "16",
    "authority-id": "my-id",
    "brand-id": "my-id",
    "model": "custom-ubuntu-core-20-amd64",
    "architecture": "amd64",
    "timestamp": "2021-02-17T20:33:40+00:00",
    "base": "core20",
    "grade": "dangerous",
    "snaps": [
        {
            "name": "pc",
            "type": "gadget",
            "default-channel": "20/stable",
            "id": "UqFziVZDHLSyO3TqSWgNBoAdHbLI4dAH"
        },
        {
            "name": "ubuntu-focal-kernel",
            "type": "kernel"
        },
        {
            "name": "core20",
            "type": "base",
            "default-channel": "latest/stable",
            "id": "DLqre5XGLbDqg9jPtiAhRRjDuPVa5X1q"
        },
         {
            "name": "snapd",
            "type": "snapd",
            "default-channel": "latest/stable",
            "id": "PMrrV4ml8uWuEUDBT8dSGnKUYbevVhc4"
        },
        {
            "name": "htop",
            "type": "app",
            "default-channel": "latest/stable",
            "id": "hJmReLmgXSUj4SF7WhyTVRV6IzUa4QUZ"
        }
    ]
}

But after creating and booting the image, the same error happens:

error: file '/kernel.efi' not found.

It seems that only the kernel snap from the track 20 works well, if another kernel snap is used it fails booting.

What configuration could be missing in the kernel snap that could help fixing this error?

Thanks.

I’m afraid that building a kernel snap for UC20 is slightly more involved. For an amd64 system using grub bootloader, we expect a single EFI kernel binary, the file must be named kernel.efi and contain the kernel and initramfs. Initramfs can be built using the ubuntu-core-initramfs tool which assembles the right pieces. You can take a look at theis repository to get some insight into how it is built: https://git.launchpad.net/~canonical-kernel-snaps/+git/kernel-snaps-uc20/tree/?h=pc There are pc and pi branches which contain snapcraft.yaml for building amd64 and pi kernels respectively. Actual build files are in the master branch.

I haven’t built these kernels myself, but IIRC @ijohnson from the snapd did so he may have some tips on the process. If you want to build a kernel for a system other than amd64, perhaps @ogra can help too.

Thanks for the information! I tried to build that repository but it’s failing to fetch required packages:

W: Failed to fetch http://ftpmaster.internal/ubuntu/dists/focal-proposed/InRelease  Could not resolve 'ftpmaster.internal'

It would be great if those guys could share some tips to generate the kernel.efi from sources for a custom image.

Thanks.

In the snapcraft.yaml definition, you can change some of the make variables:

I’ve changed the MIRROR below, for example:

    make-parameters:
      - KERNEL_SOURCE=focal:linux-uc20-efi
      - KERNEL=linux-pc-image
      - KERNEL_IMAGE_FORMAT='$(if $(filter x86_64,$(shell uname -a)),efi,vmlinuz)'
      - PROPOSED=true
      - MIRROR=gb.archive.ubuntu.com/ubuntu
    build-packages:
      - debootstrap
      - gnupg
      - kmod
      - lsb-release

Thanks! That did the trick!

Checking the makefiles and the .deb files contents gives an idea of what images should contain the kernel.efi binary but it’s not completely clear how to generate it.