Skip to content

Booting Updating Debugging and Configuring LOKI Systems

Joseph Nobes edited this page Feb 18, 2025 · 22 revisions

LOKI - Booting, Updating, Debugging and Configuration

This is a summary of how typical LOKI-based systems will boot, and how you can update images / recover them. For more detailed documentation on the project toolflow and build process, see Guidance on Top-level Design.

Generally, your tool for working with images on the LOKI system itself is loki-update.sh, which is built in. See loki-update.sh --help for information beyond what appears in this guide.

Table of Contents:

Summary

LOKI boards have three available boot devices: SoM internal flash, the eMMC (build-in MMC card), and the micro-SD card slot. The reccomended use of these devices is below:

%%{ init : { "theme" : "default" }}%%
flowchart LR
    subgraph LOKI["Motherboard: LOKI"]
        direction TB
        subgraph eMMCEmbedded["eMMC Embedded Storage"]
           eMMC["Primary<br>System<br>Image"]
           eMMCbkp["Backup<br>Image"]
        end


        subgraph SoM["System on Module (SoM)"]
            subgraph flash
                recoveryImage["Recovery<br>Image"]
            end
        end

        subgraph MicroSDSlot["Micro SD (Optional)"]
            microSD["Alternative / Transfer<br>Image"]
        end
    end
    
    subgraph ImageDeconstruction["Image Deconstruction"]
        direction TB
        bootbin[<b>BOOT.BIN</b><br>Bootloader<br>Bitstream<br>FSBL<br>PMUFW<br>ATF<br>Device Tree]
        bootscr[<b>boot.scr</b><br>Bootloader<br>Script]
        imageub[<b>image.ub</b><br>Kernel Image<br>RootFS<br>Device Tree]
    end

    ImageDeconstruction -.-> eMMC 

    classDef board fill:#9f6,stroke:#333,stroke-width:3px;
    classDef img fill:#f96,stroke:#333,stroke-width:2px;
    classDef imgpart fill:#fad4c0,stroke:#333,stroke-width:1px;
    classDef device fill:#829cfa,stroke:#333,stroke-width:2px;
    classDef optionaldevice fill:#b6c5fa,stroke:#333,stroke-width:2px,stroke-dasharray: 5 5;
    class SoM,LOKI board
    class ImageDeconstruction,eMMC,microSD,recoveryImage img
    class bootbin,bootscr,imageub imgpart
    class flash,eMMCEmbedded device
    class MicroSDSlot optionaldevice
Loading

The eMMC is used as the typical boot location for application images. This means that the image is a property of the board, which is considered the main part of any system being controlled. Swapping the any other part is not changing the system, but swapping the board is (information such as the system ID is also stored in the eMMC). Due to its size, the eMMC is also used as an optional store of a backup image, which can be restored from any booted image.

The SoM flash (given that the SoM is intended to be a swappable component) is intended to contain a 'recovery' image; this can be booted by force or automatically if no other image is avaiable (#TODO is this currently the case automatically?). The intention of this image is to boot 'something' and present as many interfaces as possible such that the user can either fix their image, or is able to install a new one in the normal location. Note that at present, a 'recovery' image can just be a copy of the main image used for the application, but eventually the intention is to have a recovery-specific image (#TODO update if necessary).

The micro-SD is currently used as a mechanism for getting images onto the system for flashing, but can be used as a boot device. However, this is not reccomended beyond debugging and test since it requires distributing and keeping track of external storage devices. It does however have the advantage of having them portable and easily swappable between systems.

Boot Process

Layout

Reduced diagram with most common routes to booting the device. In bold, the primary uninterrupted boot with application bitstream. Booting into recovery, or interrupting the boot opens up other alternatives.

%%{ init : { "theme" : "default" }}%%
flowchart LR
    subgraph Boot Process
        direction LR
        subgraph bootselect["Boot Select Switch"]
            bootswpos{Switch<br>Position?}
        end

        subgraph bootflash["SoM Flash"]
            flash_bl[<b>Recovery Bootloader</b><br>Recovery Bitstream]
            flash_interrupt{Boot Interrupted?}
            flash_buttons{Buttons<br>Pressed?}
            flash_img[<b>Recovery Kernel Image</b>]
            flash_bl --> flash_interrupt
            flash_interrupt -->|No| flash_buttons
        end
        bootswpos -->|Flash|flash_bl

        subgraph bootemmc["eMMC"]
            emmc_bl[<b>eMMC Bootloader</b><br>Primary Bitstream]
            emmc_buttons{Buttons<br>Pressed?}
            emmc_img[<b>Primary Kernel Image</b>]
            emmc_bl ==> emmc_buttons
        end
        bootswpos ==>|eMMC|emmc_bl

        emmc_buttons -->|Button 1 Pressed| flash_img
        flash_buttons -->|Button 1 Pressed| flash_img
        emmc_buttons ==>|None| emmc_img
        flash_buttons -->|None| flash_img

        flash_interrupt -.->|Yes| flash_img
        flash_interrupt -.->|Yes| emmc_img
    end


    classDef imgpart fill:#fad4c0,stroke:#333,stroke-width:1px;
    classDef device fill:#829cfa,stroke:#333,stroke-width:2px;
    classDef optionaldevice fill:#b6c5fa,stroke:#333,stroke-width:2px,stroke-dasharray: 5 5;
    
    class ImageDeconstruction,eMMC,microSD,recoveryImage img
    class flash_bl,emmc_bl,flash_img,emmc_img imgpart
    class bootselect,bootflash,bootemmc device
    class bootsd optionaldevice
Loading
  1. The boot process will begin with the bootloader (actually, the combination of the FSBL, PMUFW, ATF, the bitstream and U-Boot). Among other things, this software will scan boot devices for valid images, in order. It will also check for the pressing of certain button sequencences to trigger recovery behaviours.

Note

The firmware design (bitstream) is part of BOOT.BIN, and is stored along with the bootloader. This means that if you take an indirect route (for example: booting the eMMC bootloader and then the flash kernel image), you will still have the firmware from the first device you chose with the boot switch.

Note

If you interrupt the boot over UART, you can manually boot any of the available devices from the U-Boot console.

  1. If U-boot is located and finds a valid script to run, it will strobe the user LEDS from 0-3. Once U-Boot has located its first 'bootable' device with a valid image, it will boot the available Linux kernel image (image.ub) found there.

Debugging both the bootloader and kernel are possible using the available UART (see Debugging).

Booting to Recovery from eMMC Bootloader

By holding user button 1 during the boot process, you can boot to the recovery image in SoM flash. This will work without touching the boot select switch, as long as there is a working bootloader present in the eMMC.

Hold the button down while the device is reset or power cycled until you see the normal strobe from user LED 0-3 (red->green) followed by both green LEDS remaining lit.

Flashing from uSD

Warning

Planned feature, not implemented. DRAFT

If you have a bootable bootloader in your selected boot device (boot switches), holding button 0 down while the U-Boot script runs will take all files (if present) from a mounted microSD card and install them in the eMMC.

This would for example allow you to program the eMMC of board which has no flash image and no image in eMMC without any external connection by inserting a bootable microSD, changing the boot device to SD with the boot switches, and then booting with button 0. Following this, you could restore the boot switches to eMMC, remove the SD card and boot as normal (though note that there would be no recovery image installed).

There will need to be a way to indicate that this is done since the user may not even have a UART printout of the progress. It should also be able to indicate failure. Also consider what happens if someone confuses which button is which - perhaps use both?

Image Inspection

You can inspect the version and timestamp of the currently running image, as well as those stored in flash, eMMC, the SD card, and eMMC-backup.

To do this, use the loki-update.sh --info flag (check --help for more functionality):

petalinux-custom:~$ loki-update.sh --info all --target emmc
image info in emmc:
        timestamp: Tue Jan  7 11:39:34 GMT 2025
        Application name: babyd
        Application version: v1.2.2
        LOKI core version: v1.3.0
        Hardware Platform: 4cg_2gb,loki_1_0

Note

Note that to inspect the image in flash, you will need to be root.

Tip

You can also supply a file path to image.ub to inspect images stored elsewhere on the device.

Tip

If you have dumpimage (part of u-boot-tools) on your development host system, you can get LOKI metadata information by running:

dumpimage -T flat_dt -p 1 ./image.ub -o /dev/stdout 2>/dev/null | fdtget -t s /dev/fd/0 /loki-metadata application-name

Available fields are application-name, application-version, loki-version, platform.

Updating

In essence, the idea is to get the boot files (image.ub, boot.scr, BOOT.BIN) onto the desired boot device. Typically this is the eMMC, which is mounted to /mnt/sd-mmcblk0p1. For progamming the flash, the files go on separate mtd 'partitions' that must be programmed with flashcp. Although this could be done manually, some tools have been written to make it easier.

Getting Boot Files Onto The Device

There are three files (see Files) that are used to boot the device. The image.ub contains only the OS image, but if you have only made updates to the software build, it is safe to simply replace this. However, if you have made changes to the hardware design (firmware), you MUST also replace the BOOT.BIN.

There are a few methods:

  1. Network Copy: The easiest method is typically to use scp to copy over an available network to the unprivileged loki user's home directory (convenient since this is volatile and will be erased at restart): scp /PATH/TO/BUILDFILES/{image.ub,boot.scr,BOOT.BIN} loki@<LOKIIP>:~/. You can then ssh in and proceed with steps below.

  2. microSD Transfer: An alternative method is to use a microSD card: copy the files onto it, insert it into the device, and after logging in they will be found in /mnt/sd-mmclk1p1/. They can be installed using the tools (below) directly from this directory.

  3. NFS Mount: Finally, some systems are configured to NFS mount directories from a host machine. If there is an image update directory (typically configured in the host's layout.conf as IMAGE_UPDATE_LOC_), copy the files there on the host. When you log in, the files will be present at /controlhost/<APPLICATION NAME>/${IMAGE__UPDATE_LOC}.

Updating Main (Application) Image

Warning

You must be root

To update everything from a known directory:

# loki-update.sh --source-path /PATH/TO/BOOTFILES/

From this point, you must power cycle to include firmware changes.

Note

You must ensure that the eMMC has been written to fully (synced) before power cycling to avoid corruption. To ensure this happens, I'd recommend running poweroff, then hardware resetting the board. You could also use reboot, but only if there are no firmware changes.

To update the OS image only (no firmware changes):

# loki-update.sh --source-file /PATH/TO/BOOTFILES/image.ub

You can simply reboot the board at this point.

On Older Systems (without loki-update.sh):

To update everything, copy manually to the eMMC:

# cp /PATH/TO/BOOTFILES/{image.ub,boot.scr,BOOT.BIN} /mnt/sd-mmcblk0p1/

All-in-one Update Bash Function

To make all of this even easier, I like to combine the upload to the device and update of the image with one command defined in a couple of shell functions I add to my ~/.bashrc:

# General LOKI utilities
function loki-netflash() {
    # First arg is LOKI host, the last number in the IP
    local FILEPATH=$2
    local LOKI_HOST=$1
    echo "Flashing LOKI at host $LOKI_HOST with files $FILEPATH"
    scp $FILEPATH/{image.ub,boot.scr,BOOT.BIN} loki@$LOKI_HOST:~/ && \
        ssh -t loki@$LOKI_HOST 'su - root -c "loki-update.sh --source-path /home/loki/"'
    return $?
}

function loki-netflash-reboot() {
    local FILEPATH=$2
    local LOKI_HOST=$1
    loki-netflash "$@" && ssh -t loki@$LOKI_HOST 'su - root -c reboot'
    return $?
}

This means that assuming I've already added my SSH key to the device, everything works on one command and I only have to type in the root password. If you've added an SSH config entry for the device (and potentially used a passwordless key) this could be as simple as something like loki-netflash-reboot babyd loki/os/petalinux-custom/images/linux/ assuming I'm in the application project's root directory.

Updating Recovery Image

Warning

You must be root

To be safe, I would recommend replacing all parts of the system.

# loki-update.sh --target=flash --source-path /PATH/TO/BOOTFILES/

On Older Systems (without loki-update.sh):

  • Update the bootloader script: eval $(lsmtd -P | grep 'NAME="bootscr"' | cut -d' ' -f 1); flashcp -v /PATH/TO/BOOTFILES/boot.scr /dev/${DEVICE}
  • Update the bootloader: eval $(lsmtd -P | grep 'NAME="boot"' | cut -d' ' -f 1); flashcp -v /PATH/TO/BOOTFILES/BOOT.BIN /dev/${DEVICE}
  • Update the OS image: eval $(lsmtd -P | grep 'NAME="kernel"' | cut -d' ' -f 1); flashcp -v /PATH/TO/BOOTFILES/image.ub /dev/${DEVICE}

Backing up an image

Although the 'recovery' image is present to ensure that a bootable image is already present, you may wish to back up a more current application image before applying an update so that it can be easily restored in the event of error. This facility will store the image in a secondary directory in the eMMC so that it can be later recovered. The eMMC is by far large enough to accommodate this.

To back up the current eMMC image:

# loki-update.sh --backup

You can then restore the backed up image to the main image location (even if booted from the recovery image):

# loki-update.sh --restore

To inspect the image that is stored in the backup, use loki-update.sh --info all --target backup.

First Boot / Program

The process of booting a new board for the first time will vary depending on whether your SoM (Trenz module) is already programmed in Flash or not. Your eMMC will be empty, and so the default boot switch location will do nothing. You will need to either change it to boot from flash (if available) or micro-SD. If you want to program the board, you will also need a mechanism for getting an image onto it: network scp is easiest, but you can also use a micro-SD for the transfer if not.

Note

On first boot, the system will automatically format the eMMC for you, so it will appear as /mnt/sd-mmcblk0p1.

If you don't want to actually program the board -if are just testing it- you could use the micro-SD boot method without programming in a new image.

If your SoM is already programmed (Flash)

  1. Change the boot select switch to flash (See Bootswitch Positions).
  2. Boot the board either with network access to it, or using an XMOD adapter for USB UART (see Debugging).

Tip

Don't forget to return the boot switches to normal once you're done!

If you are booting from micro-SD

  1. Add the relevant boot.scr, BOOT.BIN and image.ub files to your micro-SD card.
  2. Insert the card into the SD slot with the device powered off.
  3. Change the boot select switch to uSD (SW5=X101, See Bootswitch Positions).
  4. Boot the board either with network access to it, or using an XMOD adapter for USB UART (see Debugging).
  5. From here you can:
    • Utilise the tools available in the Embedded Linux image to run test code, debug hardware and operate peripherals.
    • Clone your image to the eMMC (loki-update.sh --target=emmc --source-dev sd as root) if you would like a persistent installation.
    • Consider programming a recovery image if there is nothing in flash (loki-update.sh --target=flash --source-dev sd as root) (Updating Recovery Image).

Tip

Don't forget to return the boot switches to normal once you're done!

Bootswitch Positions

The selected boot device for the bootloader is chosen based on a dip-switch on the underside of the board (opposite to the SoM headers), near the battery holder: SW5. The position of the switches can be inspected by looking at the switches themselves, or the small windows to the right that show a black square when on. The first switch is not related to boot selection.

Below is the default setup for a boot from eMMC:

All relevant combinations:

Switch Number (top to bottom) eMMC Boot Flash (Recovery) Boot SD Boot
1 X (don't care) X (don't care) X (don't care)
2 0 0 1
3 1 1 0
4 1 0 1

Debugging

To access a Linux terminal, you have two options:

  1. ssh over ethernet: If your board has come up on a network that you have access to, and you know the IP (unless otherwise configured for a static IP, LOKI will use DHCP) you can ssh into the device with the unprivileged user account loki. This account is password protected, so if you require frequent access it is reccomended that you use a key (if configured properly these will be persistent). It is not possible to directly ssh as the root user.
  2. Over UART: The LOKI board has a site for a Trenz XMOD module, which provides a JTAG and UART interface over USB to the SoM. Mount an XMOD, connect a USB cable, and open up the port with any serial terminal software at baud 115200. If two interfaces appear, choose the higher number:
$ ls /dev/ttyUSB*
ttyUSB0     ttyUSB1
$ screen /dev/ttyUSB1 115200

If you aim to debug the boot process (for example if Linux is not booting, or if you are unable to log in over the network), you will need to use the TTY UART method above.