DESK-MP1-L/Development/How to create a bootable microSD card

From DAVE Developer's Wiki
< DESK-MP1-L
Revision as of 12:30, 28 July 2023 by U0031 (talk | contribs) (Created page with "==How to create a bootable SD card== {{ImportantMessage|text=The procedure described here was tested with a virtual machine such as the MVM....")

(diff) ← Older revision | Approved revision (diff) | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

How to create a bootable SD card[edit | edit source]

200px-Emblem-important.svg.png

The procedure described here was tested with a virtual machine such as the MVM. The USB controller of the MVM should be enabled by default. If you are using Linux-based distribution and are having trouble detecting a USB device in virtual machine, please make sure your user belongs to the vboxusers group.


This article shows how to create a bootable microSD for the DESK-MP1-L Release Notes kit by using a simple bash script.

The procedure has been tested on a MVM released with DESK-MP1-L 1.0.0 release with

  • a 32 GB microSD card [1]
  • a USB SD card reader
  • the binary files delivered along with the DESK-MP1-L 1.0.0

The resulting card is partitioned as depicted here below:

  • partition:
    • 1: ATF binary
    • 2: ATF binary copy
    • 3: Metadata
    • 4: Metadata
    • 5: Fip binary
    • 6: Fip binary copy
    • 7: U-boot environment
    • 8: Boot partition (kernel, dtb, bootscr, splash_image)
    • 9: VendorFS
    • 10: RFS
    • 11: UserFS

Before use the script for create the uSD, prepare the binary needed:

  • ATF binary : present on /tftp/desk-mp1-l/uSD_tf-a-stm32mp157a-dcsb5000dd1r.stm32 or build it with repo on ~/desk-mp1-l/desk-mp1-boot-image
  • FIP binary : present on /tftp/desk-mp1-l/uSD_fip.bin or build it with repo on ~/desk-mp1-l/desk-mp1-boot-image
  • bootscript.txt : create bootscript.txt file and insert the code here into the script file
  • uImage : present on /tftp/desk-mp1-l/uImage or build it with repo on ~/desk-mp1-l/linux
  • dtb : present on /tftp/desk-mp1-l/desk-mp1-l-1.0.0_stm32mp157a-dcsb5000dd1r.dtb or build it with repo on ~/desk-mp1-l/linux
  • vendorfs : present on ~/desk-mp1-l/rfs/desk-mp1-l-1.0.0_st-image-vendorfs-openstlinux-weston-desk-mp1.tar.xz
  • rootfs : present on ~/desk-mp1-l/rfs/desk-mp1-l-1.0.0_desk-image-qt5-openstlinux-weston-desk-mp1.tar.xz
  • userfs : present on ~/desk-mp1-l/rfs/desk-mp1-l-1.0.0_st-image-userfs-openstlinux-weston-desk-mp1.tar.xz

The script - named mksd.sh - can be realized with the following code:

#!/bin/bash

help(){
    echo "$0 Usage:"
    echo "$0 <device> <name_binary_to_write> <paths...>"
    echo "The value <name_binary_to_write> could be:"
    echo "  - atf: if you want flash only ATF binary on the uSD"
    echo "  - fip: if you want flash only FIP binary on the uSD"
    echo "  - bootfs: if you want build minmal bootfs and flash on the uSD"
    echo "  - rootfs: if you want flash only FIP ext4 file on the uSD"
    echo "  - vendorfs: if you want flash only FIP ext4 file on the uSD"
    echo "  - userfs: if you want flash only FIP ext4 file on the uSD"
    echo "  - all: if you want flash all binary for uSD"
    echo "After the <name_binary_to_write> write the path of the binary to want write"
    echo "If you want flash all binary, write all path with this sequence:"
    echo "path for ATF, FIP, Bootscr, Kernel, dtb, Vendorfs, Rootfs, Userfs"
}

PARTITION_SIZES=("any" "256K" "256K" "256K" "256K" "4M" "4M" "512K" "64M" "any" "any" "any")

check_usd_partitioning() {
    _count=0
    _RESIZE_SD=0
    if [ $(lsblk -o NAME,SIZE,FSTYPE /dev/$DEVICE | grep -Ec "${DEVICE}[0-11]*") != "12" ]
    then
        _RESIZE_SD=1
    fi

    if [ "$_RESIZE_SD" == "0" ]
    then
        while IFS= read -r line; do
            partition=$(echo "$line" | awk '{print $1}')
            size=$(echo "$line" | awk '{print $2}')
            fstype=$(echo "$line" | awk '{print $3}')

            echo "Partition: $partition"
            echo "Dimension: $size"
            if [ -z "$fstype" ]
            then
                echo "Partition type: None"
            else
                echo "Partition type: $fstype"
            fi

            if [[ ${PARTITION_SIZES[${_count}]} ]]
            then
                if [ "${PARTITION_SIZES[${_count}]}" != "any" ]
                then
                    if [ "${PARTITION_SIZES[${_count}]}" != "$size" ]
                    then
                        echo "This partition aren't correct! expected ${PARTITION_SIZES[${_count}]}"
                        _RESIZE_SD=1
                        break
                    fi
                fi
            fi
            echo ""
            ((_count += 1))

        done <<<"$(lsblk -o NAME,SIZE,FSTYPE /dev/$DEVICE | grep -E "${DEVICE}[0-11]*")"
    fi

    if [ "$_RESIZE_SD" == "1" ]
    then
        echo "formatting uSD because incorrect partitioning!"
        umount /dev/${DEVICE}*
        sudo sgdisk -o /dev/$DEVICE
        partprobe
        sudo sgdisk --resize-table=128 -a 1 \
            -n 1:34:545   -c 1:"fsbl1"      -t 1:8301 \
            -n 2:546:1057 -c 2:"fsbl2"      -t 2:8301 \
            -n 3:1058:1569 -c 3:"metadata1" -t 3:8301 \
            -n 4:1570:2081 -c 4:"metadata2" -t 4:8301 \
            -n 5:2082:10273 -c 5:"fip" -u 3:4fd84c93-54ef-463f-a7ef-ae25ff887087 \
            -n 6:10274:18465 -c 6:"fip" -u 4:09c54952-d5bf-45af-acee-335303766fb3 \
            -n 7:18466:19489 -c 7:"uboot-env" -t 7:8301 \
            -n 8:19490:150561 -c 8:"bootfs" -t 8:8300 \
            -n 9:150562:183329 -c 9:"vendorfs" -t 9:8300 \
            -n 10:183330:4377633 -c 10:"rootfs" -t 10:8300 -u 8:491f6117-415d-4f53-88c9-6e0de54deac6\
            -n 11:4377634:4639777 -c 11:"userfs" -t 11:8300 \
            -p /dev/$DEVICE

        partprobe
        mkfs.ext4 -O ^metadata_csum -F -L bootfs "/dev/${DEVICE}8"
        mkfs.ext4 -O ^metadata_csum -F -L vendorfs "/dev/${DEVICE}9"
        mkfs.ext4 -O ^metadata_csum -F -L rootfs "/dev/${DEVICE}10"
        mkfs.ext4 -O ^metadata_csum -F -L userfs "/dev/${DEVICE}11"
    fi
}

flash_atf(){
    if file -b "$2" | grep -q "data"
    then
        dd if=$2 of=/dev/${1}1 conv=fdatasync
        dd if=$2 of=/dev/${1}2 conv=fdatasync
    else
        echo "ATF binary not valid!"
        exit 1
    fi
}

flash_fip(){
    if file -b $2 | grep -q "data"
    then
        dd if=$2 of=/dev/${1}5 conv=fdatasync
        dd if=$2 of=/dev/${1}6 conv=fdatasync
    else
        echo "FIP binary not valid!"
        exit 1
    fi
}

flash_bootfs(){
    if [ -f "$2" ] && [ -f "$3" ] && [ -f "$4" ]
    then
        mkfs.ext4 -O ^metadata_csum -F -L bootfs "/dev/${1}8"
        echo "do bootfs"
        mount /dev/${1}8 /mnt
        mkimage -C none -A ARM -T script -n DESK-MP1 -d $2 /mnt/boot.scr
        cp $3 /mnt
        cp $4 /mnt
        sync
        umount /dev/${1}8
    else
        echo "Invalid argument for build and flash boofs!"
        exit 1
    fi
}

flash_vendorfs(){
    if [[ -f $2 ]]
    then
        mkfs.ext4 -O ^metadata_csum -F -L vendorfs "/dev/${1}9"
        echo "do vendorfs"
        mount /dev/${1}9 /mnt
        tar -xf $2 -C /mnt
        sync
        umount /dev/${1}9
    else
        echo "Vendorfs file not valid!"
        exit 1
    fi
}

flash_rootfs(){
    if [[ -f $2 ]]
    then
        mkfs.ext4 -O ^metadata_csum -F -L rootfs "/dev/${1}10"
        echo "do rootfs"
        mount /dev/${1}10 /mnt
        tar -xf $2 -C /mnt
        sync
        umount /dev/${1}10
    else
        echo "Rootfs file not valid!"
        exit 1
    fi
}

flash_userfs(){
    echo "valore userfs $2"
    if [[ -f $2 ]]
    then
        mkfs.ext4 -O ^metadata_csum -F -L userfs "/dev/${1}11"
        echo "do userfs"
        mount /dev/${1}11 /mnt
        tar -xf $2 -C /mnt
        sync
        umount /dev/${1}11
    else
        echo "Userfs file not valid!"
        exit 1
    fi
}

if [[ -z $1 || -z $2 || -z $3 ]]
then
    help
    exit 1
fi

if [ "$(whoami)" != "root" ]
then
    echo "you must be root to run this script!"
    exit
fi

if ! [[ -b "/dev/$1" ]]
then
    echo "/dev/$1 is not a valid block device!"
    exit
fi

DEVICE=$1
check_usd_partitioning

umount /dev/${DEVICE}*

if [[ "$2" == "atf" ]]
then
    flash_atf $1 $3
fi

if [[ "$2" == "fip" ]]
then
    flash_fip $1 $3
fi

if [[ "$2" == "bootfs" ]]
then
    if [[ -z $3 || -z $4 || -z $5 ]]
    then
        help
        exit 1
    fi
    flash_bootfs $1 $3 $4 $5
fi

if [[ "$2" == "vendorfs" ]]
then
    flash_vendorfs $1 $3
fi

if [[ "$2" == "rootfs" ]]
then
    flash_rootfs $1 $3
fi

if [[ "$2" == "userfs" ]]
then
    flash_userfs $1 $3
fi

if [[ "$2" == "all" ]]
then
    if [[ -z $3 || -z $4 || -z $5 || -z $6 || -z $7 || -z $8 || -z $9 || -z $10 ]]
    then
        help
        exit 1
    fi
    flash_atf $1 $3
    flash_fip $1 $4
    flash_bootfs $1 $5 $6 $7
    flash_vendorfs $1 $8
    flash_rootfs $1 $9
    flash_userfs $1 ${10}
fi

echo "[Done]"

Here is an example that shows how to use this script. We use here files delivered with DESK-MP1-L 1.0.0 release. Before invoking the script, the following files has to be renamed in order to make them compatible with the default U-Boot environment variables:

  • bootscript: boot.scr
  • Linux kernel: uImage
  • Device tree blob: stm32mp157a-dcsb5000dd1r.dtb.

In the case of you don't have some file on MVM, please download it from mirro.dave.eu.

You can now run the script, by passing the following parameters:

  • Device file of the microSD card (sdb in the example)
  • operation to do (next variable depend from operation used):
    • Absolute path of ATF binary
    • Absolute path of FIP binary
    • Absolute path of bootscritp.txt
    • Absolute path of uImage binary
    • Absolute path of dtb binary
    • Absolute path of vendorfs tar.xz
    • Absolute path of rootfs tar.xz
    • Absolute path of userfs tar.xz
sudo ./mksd.sh sdb all /tftp/desk-mp1-l/uSD_tf-a-stm32mp157a-dcsb5000dd1r.stm32 /tftp/desk-mp1-l/uSD_fip.bin ./bootscript.txt /tftp/desk-mp1-l/uImage /tftp/desk-mp1-l/desk-mp1-l-1.0.0_stm32mp157a-dcsb5000dd1r.dtb ~/desk-mp1-l/rfs/desk-mp1-l-1.0.0_st-image-vendorfs-openstlinux-weston-desk-mp1.tar.xz ~/desk-mp1-l/rfs/desk-mp1-l-1.0.0_desk-image-qt5-openstlinux-weston-desk-mp1.tar.xz ~/desk-mp1-l/rfs/desk-mp1-l-1.0.0_st-image-userfs-openstlinux-weston-desk-mp1.tar.xz

Another example where we aupdate only a partition:

  • update FIP(U-boot) partition
sudo ./mksd.sh sdb fip /tftp/desk-mp1-l/uSD_fip.bin
  • update bootfs partition
sudo ./mksd.sh sdb bootfs ./bootscript.txt /tftp/desk-mp1-l/uImage /tftp/desk-mp1-l/desk-mp1-l-1.0.0_stm32mp157a-dcsb5000dd1r.dtb

bootscr[edit | edit source]

Once you got the new binaries compiled from your modified sources, they have to be installed on first SD partition preserving the original file names used into boot.scr U-Boot bootscript.

Here below there is an example on how to create a boot.scr file from the bootscript.txt for booting from SD card:

echo 'bootscript generated with command "./tools/mkimage -C none -A arm -T script -d boot.src.cmd boot.scr.uimg"'

setenv desk_release 'desk-mp1-l-1.0.0'

if test 0x${som_configid#} = 0x00000001;
then
    if test 0x${cb_configid#} = 0x00000001;
    then
        setenv fdtfile stm32mp157a-dcsb5000dd1r.dtb
    else
        echo Invalid CB! Autoreset ...
        sleep 30
        reset
    fi
else
    echo Invalid SOM! Autoreset ...
    sleep 30
	reset
fi

setenv bootfile uImage

# if booting from NOR assume that this bootscript is inside uSD
# so override boot_device/boot_instance to continue booting from this device
if test ${boot_device} = "nor"
then
    env set boot_device = "mmc"
    env set boot_instance = "0"
fi

if test ${boot_instance} = "1";
then
    env set b_part 6
    env set rfs_part mmcblk2p8
else
    env set b_part 8
    env set rfs_part mmcblk1p10
fi

ext4load ${boot_device} ${boot_instance}:${b_part} ${fdtaddr} /${fdtfile}
ext4load ${boot_device} ${boot_instance}:${b_part} ${loadaddr} /${bootfile}
run mmc0args addcons
bootm ${loadaddr} - ${fdtaddr}

and compile it using:

mkimage -A ARM -T script -C none -n DESK-MP1 -d bootscript.txt boot.scr