From 75a960df1eb8abad7c1c693d8cad75db63478d6b Mon Sep 17 00:00:00 2001
From: guowenxue <guowenxue@gmail.com>
Date: Tue, 26 Sep 2023 00:17:38 +0800
Subject: [PATCH] Add build-evkboard shell script tools

---
 config.json          |   17 
 images/build.sh      |  279 +++++++++
 android/build.sh     |  251 ++++++++
 debian/build.sh      |  167 +++++
 kernel/build.sh      |  142 +++++
 tools/setup_tools.sh |  120 ++++
 yocto/build.sh       |  149 +++++
 bootloader/build.sh  |  376 +++++++++++++
 tools/imgmnt         |  120 ++++
 9 files changed, 1,621 insertions(+), 0 deletions(-)

diff --git a/android/build.sh b/android/build.sh
new file mode 100755
index 0000000..2ef67b9
--- /dev/null
+++ b/android/build.sh
@@ -0,0 +1,251 @@
+#!/bin/bash
+
+PRJ_PATH=`pwd`
+BOARD=evk_8mp
+
+ANDROID_VER=imx-android-12.0.0_1.0.0
+IMAGE_PATH=${PRJ_PATH}/android_image
+IMAGE_NAME=${ANDROID_VER}-${BOARD}.img
+IMAGE_SIZE=14336M  #14G
+
+JOBS=`cat /proc/cpuinfo | grep processor | wc -l`
+LOOP_DEV=`losetup  -f | cut -d/ -f3`
+
+set -e
+
+# display in green
+function pr_info() {
+    echo -e "\033[40;32m --I-- $1 \033[0m"
+}
+
+function exit_handler()
+{
+    pr_info "Shell script exit now, do some clean work"
+
+    set +e
+
+    if [ -L /dev/mapper/${LOOP_DEV}p1 ] ; then
+        echo "kpartx -dv /dev/${LOOP_DEV}"
+        kpartx -dv /dev/${LOOP_DEV} > /dev/null
+    fi
+
+    losetup -a | grep "${LOOP_DEV}" > /dev/null 2>&1
+    if [ $? == 0 ]  ; then
+        echo "losetup -d /dev/${LOOP_DEV}"
+        losetup -d /dev/${LOOP_DEV} > /dev/null
+    fi
+}
+
+function do_systool()
+{
+    if command -v simg2img > /dev/null 2>&1 ; then
+        pr_info "system tools installed already."
+        return ;
+    fi
+
+    pr_info "Start install system tools."
+    # ubuntu22.04 miss android-sdk-ext4-utils
+    sudo apt install -y uuid uuid-dev zlib1g-dev liblz-dev liblzo2-2 liblzo2-dev make libssl-dev \
+        lzop git curl u-boot-tools mtd-utils device-tree-compiler gdisk m4 bison flex gcc-multilib \
+        android-sdk-libsparse-utils android-sdk android-sdk-build-tools libncurses5
+
+    sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 1
+}
+
+function do_fetch()
+{
+    if [ -f ${PRJ_PATH}/${ANDROID_VER}/imx_android_setup.sh ] ; then
+        pr_info "android source code fetch already."
+        return;
+    fi
+
+    pr_info "Start fetch source code."
+    mkdir -p ${PRJ_PATH}/bin
+    curl https://storage.googleapis.com/git-repo-downloads/repo > ${PRJ_PATH}/bin/repo
+    chmod a+x ${PRJ_PATH}/bin/repo
+
+    export PATH=${PATH}:${PRJ_PATH}/bin
+
+
+    if [ ! -d $ANDROID_VER ] ; then
+        tar -xzf $ANDROID_VER.tar.gz
+    fi
+
+    source ${PRJ_PATH}/${ANDROID_VER}/imx_android_setup.sh 
+
+    # By default, after preceding command finishes execution, current working directory changed to the
+    # i.MX Android source code root directory.
+    # ${MY_ANDROID} will be refered as the i.MX Android source code root directory in all i.MX Andorid
+    # release documentation
+
+    export MY_ANDROID=${PRJ_PATH}
+}
+
+function do_build()
+{
+    IMX_TARGET="bootloader kernel mxmwifi dtboimage bootimage vendorbootimage vendorimage"
+
+    pr_info "Start build android source code."
+
+    export AARCH64_GCC_CROSS_COMPILE=aarch64-linux-gnu-
+    export MY_ANDROID=${PRJ_PATH}/android_build
+
+    cd $MY_ANDROID
+    source build/envsetup.sh
+    #lunch ${BOARD}-eng
+    lunch ${BOARD}-userdebug
+
+    # Build U-Boot/kernel with imx-make.sh first, but not to build Android images.
+    ./imx-make.sh -j${JOBS} ${IMX_TARGET} 2>&1 | tee build-log.txt
+
+    # Start the process of build Android images with "make" function.
+    make -j${JOBS} 2>&1 | tee -a build-log.txt
+
+    # output in ${MY_ANDROID}/out/target/product/${BOARD}
+    ls out/target/product/${BOARD}/*.img
+}
+
+function do_install()
+{
+    export MY_ANDROID=${PRJ_PATH}/android_build
+
+    IMAGE_FILES="boot.img  dtbo-imx8mp.img  partition-table.img  super.img  \
+        u-boot-imx8mp.imx  vbmeta-imx8mp.img  vendor_boot.img \
+        fastboot_imx_flashall.* imx-sdcard-partition.* uuu_imx_android_flash.* "
+
+    pr_info "Start install output images"
+
+    mkdir -p $IMAGE_PATH && rm -f $IMAGE_PATH/*
+    cd ${MY_ANDROID}/out/target/product/${BOARD}/
+
+    for f in $IMAGE_FILES
+    do
+        cp $f ${IMAGE_PATH}
+    done
+
+    cd $PRJ_PATH
+}
+
+function do_image()
+{
+    cd $IMAGE_PATH
+
+    # Generate android system image file and losetup for it
+    pr_info "Start generate android system images: ${IMAGE_NAME}"
+    cp partition-table.img ${IMAGE_NAME}
+    chmod +x ${IMAGE_NAME}
+
+    truncate -s ${IMAGE_SIZE} ${IMAGE_NAME}
+    sgdisk -e ${IMAGE_NAME}
+    gdisk -l ${IMAGE_NAME}
+
+    losetup /dev/${LOOP_DEV}  ${IMAGE_NAME}
+    kpartx -av /dev/${LOOP_DEV} > /dev/null
+
+    # Android system image partition table and written images
+    part1=(dtbo_a:dtbo-imx8mp.img)
+    part2=(dtbo_b:dtbo-imx8mp.img)
+    part3=(boot_a:boot.img)
+    part4=(boot_b:boot.img)
+    part5=(vendor_boot_a:vendor_boot.img)
+    part6=(vendor_boot_b:vendor_boot.img)
+    part7=(misc:zero)
+    part8=(metadata:ext4)
+    part9=(presistdata:zero)
+    part10=(super:super.img)
+    part11=(userdata:ext4)
+    part12=(fbmisc:zero)
+    part13=(vbmeta_a:vbmeta-imx8mp.img)
+    part14=(vbmeta_b:vbmeta-imx8mp.img)
+
+    pr_info "Start write built output images to android system images"
+    for i in `seq 1 14`
+    do
+        eval var=\${part${i}[@]}
+        for info in ${var}
+        do
+            partnum=$i
+            partname=`echo ${info} | cut -d: -f1`
+            imgfile=`echo ${info} | cut -d: -f2`
+
+            echo "Flash partition${partnum}($partname): $imgfile "
+
+            if [ "$imgfile" = "zero" ] ; then
+                size=`gdisk -l ${IMAGE_NAME} | grep -w ${partname} | awk '{print $4}' | cut -d. -f1`
+                unit=`gdisk -l ${IMAGE_NAME} | grep -w ${partname} | awk '{print $5}'`
+                dd if=/dev/zero of=/dev/mapper/${LOOP_DEV}p${partnum} bs=1${unit} count=${size} conv=fsync,nocreat status=none
+
+            elif [ "$imgfile" = "ext4" ] ; then
+                mkfs.ext4 -F /dev/mapper/${LOOP_DEV}p${partnum} -L${partname} > /dev/null 2>&1
+
+            elif [ "$imgfile" = "super.img" ] ; then
+                simg2img $imgfile /dev/mapper/${LOOP_DEV}p${partnum}
+
+            else
+                dd if=$imgfile of=/dev/mapper/${LOOP_DEV}p${partnum} bs=10M conv=fsync,nocreat status=none
+
+            fi
+        done
+    done
+
+    pr_info "Start write u-boot image to android system images"
+    dd if=u-boot-imx8mp.imx of=/dev/${LOOP_DEV} bs=1k seek=32 conv=fsync status=none
+
+    sync
+    pr_info "generate ${IMAGE_NAME} successful!"
+}
+
+function do_usage()
+{
+    echo ""
+    echo "Usage:"
+    echo " $0 [-b] [-g] [-h]"
+    echo "     -b : build android source code SDK"
+    echo "     -g : generate android system image"
+    echo "     -h : show this help message"
+    echo ""
+    echo " WARNNING: Generate android image need run as sudo"
+    echo ""
+    echo " Build Example: $0 -b && sudo $0 -g"
+    echo ""
+    exit;
+}
+
+action="usage"
+
+while getopts "bgh" OPTNAME
+do
+    case "${OPTNAME}" in
+        "b")
+            action="build"
+            shift
+            ;;  
+
+        "g")
+            action="generate"
+            shift
+            ;;  
+
+        "h")
+            action="usage"
+            ;;  
+    esac
+done
+
+trap 'exit_handler' EXIT
+
+#do_systool
+
+if [ $action == "usage" ] ; then
+    do_usage
+
+elif [ $action == "build" ] ; then
+    do_fetch
+    do_build
+    do_install
+
+elif [ $action == "generate" ] ; then
+    do_image
+
+fi
+
diff --git a/bootloader/build.sh b/bootloader/build.sh
new file mode 100755
index 0000000..d54aecd
--- /dev/null
+++ b/bootloader/build.sh
@@ -0,0 +1,376 @@
+#!/bin/bash
+
+# this project absolute path
+PRJ_PATH=$(cd $(dirname "${BASH_SOURCE[0]}") && pwd)
+
+# top project absolute path
+TOP_PATH=$(realpath $PRJ_PATH/..)
+
+# binaries build prefix install path
+PRFX_PATH=$PRJ_PATH/install
+
+# binaries finally install path if needed
+INST_PATH=/tftp
+
+# config file path
+CONF_FILE=$TOP_PATH/config.json
+
+# shell script will exit once get command error
+set -e
+
+#+-------------------------+
+#| Shell script functions  |
+#+-------------------------+
+
+function pr_error() {
+    echo -e "\033[40;31m $1 \033[0m"
+}
+
+function pr_warn() {
+    echo -e "\033[40;33m $1 \033[0m"
+}
+
+function pr_info() {
+    echo -e "\033[40;32m $1 \033[0m"
+}
+
+# select firmware version by BSP version
+function export_fmver()
+{
+    if [[ $BSP_VER =~ 6.1.22 ]] ;  then
+
+        export FMW_IMX=firmware-imx-8.20
+        export FMW_SENTINEL=firmware-sentinel-0.10
+        export FMW_UPOWER=firmware-upower-1.3.0
+
+    elif [[ $BSP_VER =~ 6.1.1 ]] ;  then
+
+        export FMW_IMX=firmware-imx-8.19
+        export FMW_SENTINEL=firmware-sentinel-0.9
+        export FMW_UPOWER=firmware-upower-1.2.0
+
+    elif [[ $BSP_VER =~ 5.15.71 ]] ;  then
+
+        export FMW_IMX=firmware-imx-8.18
+        export FMW_SENTINEL=firmware-sentinel-0.8
+        export FMW_UPOWER=firmware-upower-1.1.0
+
+    fi
+
+    export FMWS="$FMW_IMX $FMW_SENTINEL $FMW_UPOWER"
+    export FMW_URL=https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/
+    export FMW_PATH=$PRJ_PATH/firmware/
+}
+
+# parser configure file and export environment variable
+function export_env()
+{
+    export BOARD=`jq -r ".bsp.board" $CONF_FILE | tr 'A-Z' 'a-z'`
+    export BSP_VER=`jq -r ".bsp.version" $CONF_FILE | tr 'A-Z' 'a-z'`
+    export GIT_URL=`jq -r ".bsp.giturl" $CONF_FILE | tr 'A-Z' 'a-z'`
+    export CROSS_COMPILE=`jq -r ".bsp.cortexAtool" $CONF_FILE | tr 'A-Z' 'a-z'`
+    export MCORE_COMPILE=`jq -r ".bsp.cortexMtool" $CONF_FILE | tr 'A-Z' 'a-z'`
+
+    export SRCS="imx-atf uboot-imx imx-mkimage"
+    export BRANCH=$BSP_VER
+    export JOBS=`cat /proc/cpuinfo | grep processor | wc -l`
+    export ARCH=arm
+
+    export_fmver
+    export SRCS="imx-atf uboot-imx imx-mkimage"
+
+    if [[ $BOARD =~ mx93 ]] ; then
+
+        ATF_PLATFORM=imx93
+        IMX_BOOT_SOC_TARGET=iMX9
+        IMXBOOT_TARGETS=flash_singleboot
+        IMXBOOT_DTB=imx93-11x11-evk.dtb
+        MKIMG_BIN_PATH=$PRJ_PATH/imx-mkimage/iMX9/
+
+    elif [[ $BOARD =~ mx8ulp ]] ; then
+
+        MCORE_BUILD=yes
+        MCORE_BOARD=evkmimx8ulp
+        MCORE_IMAGE=m33_image.bin
+
+        ATF_PLATFORM=imx8ulp
+        IMX_BOOT_SOC_TARGET=iMX8ULP
+        IMXBOOT_TARGETS=flash_singleboot_m33
+        IMXBOOT_DTB=imx8ulp-evk.dtb
+        MKIMG_BIN_PATH=$PRJ_PATH/imx-mkimage/iMX8ULP/
+
+    elif [[ $BOARD =~ mx8mq ]] ; then
+
+        ATF_PLATFORM=imx8mq
+        IMX_BOOT_SOC_TARGET=iMX8M
+        IMXBOOT_TARGETS=flash_ddr4_val
+        IMXBOOT_DTB=imx8mq-ddr4-val.dtb
+        MKIMG_BIN_PATH=$PRJ_PATH/imx-mkimage/iMX8M/
+
+    elif [[ $BOARD =~ mx8mp ]] ; then
+
+        ATF_PLATFORM=imx8mp
+        IMX_BOOT_SOC_TARGET=iMX8MP
+        IMXBOOT_TARGETS=flash_ddr4_evk
+        IMXBOOT_DTB=imx8mp-ddr4-evk.dtb
+        MKIMG_BIN_PATH=$PRJ_PATH/imx-mkimage/iMX8M/
+
+
+    elif [[ $BOARD =~ mx8mm ]] ; then
+
+        ATF_PLATFORM=imx8mm
+        IMX_BOOT_SOC_TARGET=iMX8MM
+        IMXBOOT_TARGETS=flash_ddr4_evk
+        IMXBOOT_DTB=imx8mm-ddr4-evk.dtb
+        MKIMG_BIN_PATH=$PRJ_PATH/imx-mkimage/iMX8M/
+
+    elif [[ $BOARD =~ mx8mn ]] ; then
+
+        ATF_PLATFORM=imx8mn
+        IMX_BOOT_SOC_TARGET=iMX8MN
+        IMXBOOT_TARGETS=flash_ddr4_evk
+        IMXBOOT_DTB=imx8mn-ddr4-evk.dtb
+        MKIMG_BIN_PATH=$PRJ_PATH/imx-mkimage/iMX8M/
+
+    fi
+}
+
+function do_fetch()
+{
+    cd $PRJ_PATH
+
+    for src in $SRCS
+    do
+        if [ -d $src ] ; then
+            pr_info "$src source code fetched already"
+            continue
+        fi
+
+        pr_info "start fetch $src source code"
+        git clone $GIT_URL/$src.git -b $BRANCH
+    done
+
+
+    mkdir -p $FMW_PATH && cd $FMW_PATH
+
+    for fmw in $FMWS
+    do
+        if [ -d $fmw ] ; then
+            pr_info "Firmware $fmw fetch already"
+            continue
+        fi
+        pr_info "start fetch $fmw firmware"
+        wget $FMW_URL/$fmw.bin
+
+        bash $fmw.bin --auto-accept > /dev/null 2>&1
+    done
+
+    rm -f *.bin
+}
+
+function build_atf()
+{
+    SRC=imx-atf
+
+    pr_warn "start build $SRC"
+    cd $PRJ_PATH/${SRC}
+
+    make -j${JOBS} CROSS_COMPILE=${CROSS_COMPILE} PLAT=$ATF_PLATFORM bl31
+
+    set -x
+    cp build/$ATF_PLATFORM/release/bl31.bin $MKIMG_BIN_PATH
+    set +x
+}
+
+# Cortex-M SDK download from https://mcuxpresso.nxp.com/ by manual
+function build_cortexM()
+{
+    SRC=mcore-sdk
+    DEMO_PATH=boards/$MCORE_BOARD/multicore_examples/rpmsg_lite_str_echo_rtos/armgcc
+    DEMO_BIN=release/rpmsg_lite_str_echo_rtos.bin
+    export ARMGCC_DIR=$(echo $MCORE_COMPILE | sed 's\/bin/.*\\')
+
+    if [ ! -d $PRJ_PATH/$SRC ] ; then
+        if [ "$MCORE_BUILD" == "yes" ] ; then
+            pr_error "INFO: Please download $BOARD SDK from https://mcuxpresso.nxp.com"
+            pr_error "      by manual and decompress it to folder '$SRC'"
+            exit;
+        else
+            pr_warn "Skip build Cortex-M core SDK source code '$SRC'"
+            return ;
+        fi
+    fi
+
+    pr_warn "start build $SRC"
+
+    cd $PRJ_PATH/${SRC}
+    cd $DEMO_PATH
+
+    #bash clean.sh
+    if [ ! -s $DEMO_BIN ] ; then
+        bash build_release.sh
+    fi
+
+    set -x
+    cp $DEMO_BIN $MKIMG_BIN_PATH/$MCORE_IMAGE
+    set +x
+}
+
+function build_uboot()
+{
+    SRC=uboot-imx
+
+    pr_warn "start build $SRC"
+    cd $PRJ_PATH/${SRC}
+
+    defconfig=`echo ${BOARD} | sed 's/-/_/g'`_defconfig
+    if [ ! -f .config ] ; then
+        make ARCH=arm ${defconfig}
+    fi
+
+    make -j${JOBS} CROSS_COMPILE=${CROSS_COMPILE} ARCH=arm
+
+    set -x
+    cp u-boot.bin $MKIMG_BIN_PATH
+    cp u-boot-nodtb.bin $MKIMG_BIN_PATH
+    cp spl/u-boot-spl.bin $MKIMG_BIN_PATH
+    cp arch/arm/dts/${BOARD}.dtb $MKIMG_BIN_PATH/$IMXBOOT_DTB
+    cp tools/mkimage $MKIMG_BIN_PATH/mkimage_uboot
+    set +x
+}
+
+# The diagram below illustrate a signed iMX8 flash.bin image layout:
+#   reference: uboot-imx/doc/imx/habv4/guides/mx8m_secure_boot.txt
+#
+#                     +-----------------------------+
+#                     |                             |
+#                     |     *Signed HDMI/DP FW      |
+#                     |                             |
+#                     +-----------------------------+
+#                     |           Padding           |
+#             ------- +-----------------------------+ --------
+#                 ^   |          IVT - SPL          |   ^
+#          Signed |   +-----------------------------+   |
+#           Data  |   |        u-boot-spl.bin       |   |
+#                 |   |              +              |   |  SPL
+#                 v   |           DDR FW            |   | Image
+#             ------- +-----------------------------+   |
+#                     |      CSF - SPL + DDR FW     |   v
+#                     +-----------------------------+ --------
+#                     |           Padding           |
+#             ------- +-----------------------------+ --------
+#          Signed ^   |          FDT - FIT          |   ^
+#           Data  |   +-----------------------------+   |
+#                 v   |          IVT - FIT          |   |
+#             ------- +-----------------------------+   |
+#                     |          CSF - FIT          |   |
+#             ------- +-----------------------------+   |  FIT
+#                 ^   |       u-boot-nodtb.bin      |   | Image
+#                 |   +-----------------------------+   |
+#          Signed |   |       OP-TEE (Optional)     |   |
+#           Data  |   +-----------------------------+   |
+#                 |   |        bl31.bin (ATF)       |   |
+#                 |   +-----------------------------+   |
+#                 v   |          u-boot.dtb         |   v
+#             ------- +-----------------------------+ --------
+#
+#
+# Reference: <<IMX_LINUX_USERS_GUIDE.pdf>> 4.5.13 How to build imx-boot image by using imx-mkimage
+
+function build_imxboot()
+{
+    SRC=imx-mkimage
+
+    pr_warn "start build $SRC"
+    cd $PRJ_PATH/${SRC}
+
+    if [[ $BOARD =~ mx93 ]] ; then
+        pr_info "Copy iMX93 firmware to $MKIMG_BIN_PATH"
+
+        cp $FMW_PATH/firmware-sentinel-*/mx93a0-ahab-container.img $MKIMG_BIN_PATH
+        cp $FMW_PATH/firmware-imx-*/firmware/ddr/synopsys/lpddr4_imem_1d*.bin $MKIMG_BIN_PATH
+        cp $FMW_PATH/firmware-imx-*/firmware/ddr/synopsys/lpddr4_dmem_1d*.bin $MKIMG_BIN_PATH
+        cp $FMW_PATH/firmware-imx-*/firmware/ddr/synopsys/lpddr4_imem_2d*.bin $MKIMG_BIN_PATH
+        cp $FMW_PATH/firmware-imx-*/firmware/ddr/synopsys/lpddr4_dmem_2d*.bin $MKIMG_BIN_PATH
+
+    elif [[ $BOARD =~ mx8ulp ]] ; then
+        pr_info "Copy iMX8ULP firmware to $MKIMG_BIN_PATH"
+
+        cp $FMW_PATH/firmware-upower-*/upower_a1.bin $MKIMG_BIN_PATH/upower.bin
+        cp $FMW_PATH/firmware-sentinel-*/mx8ulpa2-ahab-container.img $MKIMG_BIN_PATH
+
+    elif [[ $BOARD =~ mx8 ]] ; then
+        pr_info "Copy DDR4 firmware to $MKIMG_BIN_PATH"
+
+        cp $FMW_PATH/firmware-imx-*/firmware/hdmi/cadence/signed_hdmi_imx8m.bin $MKIMG_BIN_PATH
+        cp $FMW_PATH/firmware-imx-*/firmware/ddr/synopsys/ddr4_imem_1d*.bin $MKIMG_BIN_PATH
+        cp $FMW_PATH/firmware-imx-*/firmware/ddr/synopsys/ddr4_dmem_1d*.bin $MKIMG_BIN_PATH
+        cp $FMW_PATH/firmware-imx-*/firmware/ddr/synopsys/ddr4_imem_2d*.bin $MKIMG_BIN_PATH
+        cp $FMW_PATH/firmware-imx-*/firmware/ddr/synopsys/ddr4_dmem_2d*.bin $MKIMG_BIN_PATH
+    fi
+
+    make SOC=$IMX_BOOT_SOC_TARGET REV=A2 $IMXBOOT_TARGETS
+
+    cp $MKIMG_BIN_PATH/flash.bin u-boot-${BOARD}.imx
+    chmod a+x u-boot-${BOARD}.imx
+
+    cp u-boot-${BOARD}.imx $PRFX_PATH
+}
+
+function do_build()
+{
+    cd $PRJ_PATH
+    mkdir -p $PRFX_PATH
+
+    build_atf
+    build_cortexM
+    build_uboot
+    build_imxboot
+}
+
+function do_install()
+{
+    cd $PRJ_PATH
+
+    echo ""
+    pr_info "bootloader installed to '$PRFX_PATH'"
+    ls $PRFX_PATH && echo ""
+
+    if [[ -n "$INST_PATH" && -w $INST_PATH ]] ; then
+        pr_info "install bootloader to '$INST_PATH'"
+        cp $PRFX_PATH/u-boot-${BOARD}.imx $INST_PATH
+    fi
+}
+
+function do_clean()
+{
+    for d in $SRCS
+    do
+        rm -rf $PRJ_PATH/$d
+    done
+
+    rm -rf $PRJ_PATH/firmware
+    rm -rf $PRFX_PATH
+}
+
+#+-------------------------+
+#| Shell script body entry |
+#+-------------------------+
+
+cd $PRJ_PATH
+
+export_env
+
+if [[ $# == 1 && $1 == -c ]] ;then
+    pr_warn "start clean bootloader"
+    do_clean
+    exit;
+fi
+
+pr_warn "start build bootloader for ${BOARD}"
+
+do_fetch
+
+do_build
+
+do_install
diff --git a/config.json b/config.json
new file mode 100644
index 0000000..2e6482e
--- /dev/null
+++ b/config.json
@@ -0,0 +1,17 @@
+{
+    "bsp":
+    {
+        "board":"imx8mp-evk",
+        "version":"lf-6.1.22-2.0.0",
+        "giturl":"https://github.com/nxp-imx/",
+        "cortexAtool":"/opt/gcc-aarch64-10.3-2021.07/bin/aarch64-none-linux-gnu-",
+        "cortexMtool":"/opt/gcc-cortexM-10.3-2021.07/bin/arm-none-eabi-"
+    },
+    "system":
+    {
+        "distro":"yocto",
+        "version":"mickledore",
+        "imgsize":"2048",
+        "bootsize":"100"
+    }
+}
diff --git a/debian/build.sh b/debian/build.sh
new file mode 100755
index 0000000..f1821da
--- /dev/null
+++ b/debian/build.sh
@@ -0,0 +1,167 @@
+#!/bin/bash
+# This shell script used to fetch debian root file system
+
+# this project absolute path
+PRJ_PATH=$(cd $(dirname "${BASH_SOURCE[0]}") && pwd)
+
+# the target board name and ARCH(armel/armhf/arm64)
+BOARD=igkboard
+ARCH=armhf
+ARCH=arm64
+
+# Debian 11 (bullseye)
+CODENAME=bullseye
+VERSION=11
+
+# Debian 12 (bookworm)
+CODENAME=bookworm
+VERSION=12
+
+# rootfs directory name
+ROOTFS_DIR=rootfs-debian-$CODENAME
+
+# rootfs configuration
+DEF_PASSWD=12345
+
+# shell script will exit once get command error
+set -e
+
+#+-------------------------+
+#| Shell script functions  |
+#+-------------------------+
+
+function pr_error() {
+    echo -e "\033[40;31m $1 \033[0m"
+}
+
+function pr_warn() {
+    echo -e "\033[40;33m $1 \033[0m"
+}
+
+function pr_info() {
+    echo -e "\033[40;32m $1 \033[0m"
+}
+
+# Debian 12 depends on the new keyring
+# https://packages.debian.org/sid/all/debian-archive-keyring/download
+function update_keyring()
+{
+    debname=debian-archive-keyring
+    debversion=2023.3
+
+    set +e
+    dpkg -l $debname > /dev/null 2>&1
+    if [ $? == 0 ] ; then
+        dpkg -s debian-archive-keyring | grep Version: | grep $debversion > /dev/null 2>&1
+        if [ $? != 0 ] ; then
+            pr_info "updating $debname"
+            apt purge -y $debname
+        else
+            pr_info "$debname is latest"
+            return;
+        fi
+    fi
+    set -e
+
+    pr_info "install $debname now"
+    wget http://ftp.us.debian.org/debian/pool/main/d/$debname/${debname}_${debversion}_all.deb > /dev/null
+    dpkg -i ${debname}_${debversion}_all.deb
+    rm -f ${debname}_${debversion}_all.deb
+}
+
+function do_install()
+{
+    pr_warn "\ninstall system tools"
+
+    update_keyring
+
+    debootstrap --version > /dev/null 2>&1
+    if [ $? == 0 ] ; then
+       pr_info "system tools installed already"
+       return ;
+    fi
+
+    apt install binfmt-support qemu qemu-user-static debootstrap
+}
+
+function do_fetch()
+{
+    pr_warn "\ndebootstrap fetch"
+
+    if [ -f ${ROOTFS_DIR}/bin/bash ] ; then
+       pr_info "debain rootfs fetched already"
+       return ;
+    fi
+    debootstrap --arch=${ARCH} --foreign ${CODENAME} ${ROOTFS_DIR} http://ftp.debian.org/debian/
+
+    cp -f /usr/bin/qemu-arm-static ${ROOTFS_DIR}/usr/bin/
+    DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true LC_ALL=C LANGUAGE=C LANG=C chroot ${ROOTFS_DIR} debootstrap/debootstrap --second-stage
+    DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true LC_ALL=C LANGUAGE=C LANG=C chroot ${ROOTFS_DIR} dpkg --configure -a
+    rm -f ${ROOTFS_DIR}/usr/bin/qemu-arm-static
+}
+
+function modify_rootfs()
+{
+    pr_warn "\nmodify rootfs environment"
+
+    # update hostnmae and issue
+    echo $BOARD > ${ROOTFS_DIR}/etc/hostname
+    echo "Debian GNU/Linux $VERSION \n \l, default password '$DEF_PASSWD'" > ${ROOTFS_DIR}/etc/issue
+
+    # update dns server
+    echo "nameserver 223.5.5.5" > ${ROOTFS_DIR}/etc/resolv.conf
+    echo "nameserver 114.114.114.114" >> ${ROOTFS_DIR}/etc/resolv.conf
+
+    set +e
+    # add ls alias for display with color
+    grep "color=auto" ${ROOTFS_DIR}/etc/profile > /dev/null 2>&1
+    if [ $? != 0 ] ; then
+       echo "alias ls='ls --color=auto'" >> ${ROOTFS_DIR}/etc/profile
+    fi
+
+    grep "^PermitRootLogin" ${ROOTFS_DIR}/etc/ssh/sshd_config > /dev/null 2>&1
+    if [ $? != 0 ] ; then
+       echo "PermitRootLogin yes" >> ${ROOTFS_DIR}/etc/ssh/sshd_config
+    fi
+    set -e
+}
+
+function do_conf()
+{
+    EXTRA_APPS="vim net-tools network-manager tree file parted locales lsb-release tzdata wireless-tools openssh-server"
+
+    pr_warn "\ndebootstrap configure"
+
+    cp -f /usr/bin/qemu-arm-static ${ROOTFS_DIR}/usr/bin/
+    DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true LC_ALL=C LANGUAGE=C LANG=C chroot ${ROOTFS_DIR} apt update
+    DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true LC_ALL=C LANGUAGE=C LANG=C chroot ${ROOTFS_DIR} apt install -y ${EXTRA_APPS}
+    DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true LC_ALL=C LANGUAGE=C LANG=C chroot ${ROOTFS_DIR} sh -c "echo root:${DEF_PASSWD} | chpasswd"
+    rm -f ${ROOTFS_DIR}/usr/bin/qemu-arm-static
+
+    modify_rootfs
+}
+
+function do_pack()
+{
+    pr_warn "\npackage $ROOTFS_DIR"
+
+    cd $PRJ_PATH/$ROOTFS_DIR
+    tar -cJf ../$ROOTFS_DIR.tar.xz *
+}
+
+#+-------------------------+
+#| Shell script body start |
+#+-------------------------+
+
+if [ `id -u` != 0 ] ; then
+   pr_error "ERRROR: This shell script must excuted as root privilege."
+   exit 0;
+fi
+
+do_install
+
+do_fetch
+
+do_conf
+
+do_pack
diff --git a/images/build.sh b/images/build.sh
new file mode 100755
index 0000000..ac9a555
--- /dev/null
+++ b/images/build.sh
@@ -0,0 +1,279 @@
+#!/bin/bash
+
+# this project absolute path
+PRJ_PATH=$(cd $(dirname "${BASH_SOURCE[0]}") && pwd)
+
+# top project absolute path
+TOP_PATH=$(realpath $PRJ_PATH/..)
+
+# binaries build prefix install path
+PRFX_PATH=$PRJ_PATH/install
+
+# binaries finally install path if needed
+INST_PATH=/tftp
+
+# config file path
+CONF_FILE=$TOP_PATH/config.json
+
+# shell script will exit once get command error
+set -e
+set -u
+
+#+-------------------------+
+#| Shell script functions  |
+#+-------------------------+
+
+function pr_error() {
+    echo -e "\033[40;31m $1 \033[0m"
+}
+
+function pr_warn() {
+    echo -e "\033[40;33m $1 \033[0m"
+}
+
+function pr_info() {
+    echo -e "\033[40;32m $1 \033[0m"
+}
+
+# decompress a packet to destination path
+function do_unpack()
+{
+    tarball=$1
+    dstpath=`pwd`
+
+    if [[ $# == 2 ]] ; then
+        dstpath=$2
+    fi
+
+    pr_info "decompress $tarball => $dstpath"
+
+    mkdir -p $dstpath
+    case $tarball in
+        *.tar.gz)
+            tar -xzf $tarball -C $dstpath
+            ;;
+
+        *.tar.bz2)
+            tar -xjf $tarball -C $dstpath
+            ;;
+
+        *.tar.xz)
+            tar -xJf $tarball -C $dstpath
+            ;;
+
+        *.tar.zst)
+            tar -I zstd -xf $tarball -C $dstpath
+            ;;
+
+        *.tar)
+            tar -xf $tarball -C $dstpath
+            ;;
+
+        *.zip)
+            unzip -qo $tarball -d $dstpath
+            ;;
+
+        *)
+            pr_error "decompress Unsupport packet: $tarball"
+            return 1;
+            ;;
+    esac
+}
+
+# parser configure file and export environment variable
+function export_env()
+{
+    export BOARD=`jq -r ".bsp.board" $CONF_FILE | tr 'A-Z' 'a-z'`
+    export BSP_VER=`jq -r ".bsp.version" $CONF_FILE | tr 'A-Z' 'a-z'`
+    export DIS_VER=`jq -r ".system.version" $CONF_FILE | tr 'A-Z' 'a-z'`
+    export IMAGE_SIZE=`jq -r ".system.imgsize" $CONF_FILE | tr 'A-Z' 'a-z'`
+    export BOOT_SIZE=`jq -r ".system.bootsize" $CONF_FILE | tr 'A-Z' 'a-z'`
+
+    export LOOP_DEV=`losetup  -f | cut -d/ -f3`
+    export MNT_POINT=$PRJ_PATH/mnt
+
+    export ROOTFS=rootfs-${DIS_VER}
+    export UBOOT_BINPATH=$TOP_PATH/bootloader/install/
+    export KERNEL_BINPATH=$TOP_PATH/kernel/install/
+    export ROOTFS_BINPATH=$TOP_PATH/yocto/install/
+
+    if [[ $BOARD =~ mx8ulp ]] || [[ $BOARD =~ mx8mq ]] || [[ $BOARD =~ mx8mm ]] ; then
+        export UBOOT_OFFSET_SECTOR=66
+    elif [[ $BOARD =~ mx8mn ]] || [[ $BOARD =~ mx8mp ]] || [[ $BOARD =~ mx93 ]] ; then
+        export UBOOT_OFFSET_SECTOR=64
+    elif [[ $BOARD =~ mx6 ]] || [[ $BOARD =~ mx7 ]] ; then
+        export UBOOT_OFFSET_SECTOR=2
+    fi
+}
+
+function do_fetch()
+{
+    cd $PRJ_PATH
+
+    SRCS=$ROOTFS
+
+    for src in $SRCS
+    do
+        if [ -d $ROOTFS/bin ] ; then
+            pr_info "$src fetched already"
+            continue
+        fi
+
+        for tarball in $ROOTFS_BINPATH/rootfs.tar.*
+        do
+            if [ -s $tarball ] ; then
+                mkdir -p $ROOTFS
+                do_unpack $tarball $ROOTFS
+                break;
+            fi
+        done
+    done
+}
+
+# System image layout map:
+# +-------------------+--------------------+----------------------+
+# | Raw Part(10MB)    | FAT32 Part2(100MB) | EXT4 Part3(All left) |
+# +-------------------+--------------------+----------------------+
+# | U-boot on #64     |   Kernel and DTB   |   Root file system   |
+# +-------------------+--------------------+----------------------+
+
+function build_image()
+{
+    export IMAGE_NAME=$BOARD-$DIS_VER.img
+
+    # Uboot size set be 10MB and deployed in 64th sector on eMMC/TFCard
+    UBOOT_SIZE=10
+
+    mkdir -p $MNT_POINT
+
+    pr_info "start generate empty system image"
+    dd if=/dev/zero of=${IMAGE_NAME} bs=1024k count=${IMAGE_SIZE} conv=sync
+    chmod a+x ${IMAGE_NAME}
+
+    pr_info "start partition system image"
+    fat_start=$UBOOT_SIZE
+    fat_end=`expr $UBOOT_SIZE + $BOOT_SIZE`
+    parted ${IMAGE_NAME} mklabel msdos
+    parted ${IMAGE_NAME} mkpart primary fat32 ${fat_start}M ${fat_end}M
+    parted ${IMAGE_NAME} mkpart primary ext4 ${fat_end}M 100%
+    sync
+
+    pr_info "losetup system image on $LOOP_DEV"
+    losetup /dev/${LOOP_DEV}  ${IMAGE_NAME}
+    kpartx -av /dev/${LOOP_DEV}
+
+    pr_info "start format system image"
+    mkfs.vfat /dev/mapper/${LOOP_DEV}p1
+    mkfs.ext4 /dev/mapper/${LOOP_DEV}p2
+    sync
+
+    pr_info "start install u-boot image"
+    dd if=$UBOOT_BINPATH/u-boot-${BOARD}.imx of=${IMAGE_NAME} bs=512 seek=$UBOOT_OFFSET_SECTOR conv=notrunc,sync
+
+    pr_info "start install linux kernel images"
+    mount -t vfat /dev/mapper/${LOOP_DEV}p1 ${MNT_POINT}
+    cp -rf $KERNEL_BINPATH/Image       ${MNT_POINT}/
+    cp -rf $KERNEL_BINPATH/${BOARD}.dtb ${MNT_POINT}/
+
+    sync && umount ${MNT_POINT}
+
+    pr_info "update drivers in root filesystem"
+    rm -rf $ROOTFS/lib/modules/
+    mkdir -p $ROOTFS/lib/modules/
+    cp -rf $KERNEL_BINPATH/lib/modules/[0-9]*\.[0-9]*\.[0-9]* $ROOTFS/lib/modules/
+
+    pr_info "start install root filesystem"
+    mount -t ext4 /dev/mapper/${LOOP_DEV}p2 ${MNT_POINT}
+    cp -af $ROOTFS/* ${MNT_POINT}
+    sync && umount ${MNT_POINT}
+
+    pr_warn "Build $BOARD-$BSP_VER-$DIS_VER system image done"
+}
+
+function exit_handler()
+{
+    pr_warn "Shell script exit now, do some clean work\n"
+    set +e
+
+    if mountpoint ${MNT_POINT} > /dev/null 2>&1 ; then
+        pr_info "umount ${MNT_POINT}"
+        umount ${MNT_POINT} > /dev/null 2>&1
+    fi
+
+    rm -rf ${MNT_POINT}
+
+    if [ -e /dev/mapper/${LOOP_DEV}p1 ] ; then
+        pr_info "kpartx -dv /dev/${LOOP_DEV}"
+        kpartx -dv /dev/${LOOP_DEV}
+    fi
+
+    losetup -a | grep "${LOOP_DEV}" > /dev/null 2>&1
+    if [ $? == 0 ]  ; then
+        pr_info "losetup -d /dev/${LOOP_DEV}"
+        losetup -d /dev/${LOOP_DEV}
+    fi
+}
+
+function do_build()
+{
+    cd $PRJ_PATH
+
+    build_image
+}
+
+function do_install()
+{
+    cd $PRJ_PATH
+
+    mkdir -p $PRFX_PATH
+    cp $UBOOT_BINPATH/u-boot-${BOARD}.imx $PRFX_PATH
+    mv $IMAGE_NAME $PRFX_PATH
+
+    if [[ -n "$INST_PATH" && -w $INST_PATH ]] ; then
+        pr_info "install bootloader and system image to '$INST_PATH'"
+        cp $PRFX_PATH/u-boot-${BOARD}.imx $INST_PATH
+        cp $PRFX_PATH/$IMAGE_NAME $INST_PATH
+    fi
+}
+
+
+function do_clean()
+{
+    for d in rootfs-*
+    do
+        rm -rf $PRJ_PATH/$d
+    done
+
+    rm -rf $PRFX_PATH
+    rm -f *.img
+}
+
+#+-------------------------+
+#| Shell script body entry |
+#+-------------------------+
+
+if [ `id -u` != 0 ] ; then
+    pr_error "ERROR: This shell script must run as root"
+    exit;
+fi
+
+cd $PRJ_PATH
+
+export_env
+
+if [[ $# == 1 && $1 == -c ]] ;then
+    pr_warn "start clean system image"
+    do_clean
+    exit;
+fi
+
+pr_warn "Build $BOARD-$BSP_VER-$DIS_VER system image"
+
+trap 'exit_handler' EXIT
+
+do_fetch
+
+do_build
+
+do_install
+
diff --git a/kernel/build.sh b/kernel/build.sh
new file mode 100755
index 0000000..71d697c
--- /dev/null
+++ b/kernel/build.sh
@@ -0,0 +1,142 @@
+#!/bin/bash
+
+# this project absolute path
+PRJ_PATH=$(cd $(dirname "${BASH_SOURCE[0]}") && pwd)
+
+# top project absolute path
+TOP_PATH=$(realpath $PRJ_PATH/..)
+
+# binaries build prefix install path
+PRFX_PATH=$PRJ_PATH/install
+
+# binaries finally install path if needed
+#INST_PATH=/tftp
+
+# config file path
+CONF_FILE=$TOP_PATH/config.json
+
+# shell script will exit once get command error
+set -e
+
+#+-------------------------+
+#| Shell script functions  |
+#+-------------------------+
+
+function pr_error() {
+    echo -e "\033[40;31m $1 \033[0m"
+}
+
+function pr_warn() {
+    echo -e "\033[40;33m $1 \033[0m"
+}
+
+function pr_info() {
+    echo -e "\033[40;32m $1 \033[0m"
+}
+
+# parser configure file and export environment variable
+function export_env()
+{
+    export BOARD=`jq -r ".bsp.board" $CONF_FILE | tr 'A-Z' 'a-z'`
+    export BSP_VER=`jq -r ".bsp.version" $CONF_FILE | tr 'A-Z' 'a-z'`
+    export GIT_URL=`jq -r ".bsp.giturl" $CONF_FILE | tr 'A-Z' 'a-z'`
+    export CROSS_COMPILE=`jq -r ".bsp.cortexAtool" $CONF_FILE | tr 'A-Z' 'a-z'`
+
+    export BRANCH=$BSP_VER
+    export KER_PATH=$PRJ_PATH/linux-imx
+
+    export JOBS=`cat /proc/cpuinfo | grep processor | wc -l`
+    export ARCH=arm64
+    export SRCS="linux-imx"
+}
+
+function build_kernel()
+{
+    cd $PRJ_PATH
+
+    if [ -d $KER_PATH ] ; then
+        pr_info "linux kernel source code fetched already"
+    else
+        pr_info "start fetch linux kernel source code"
+        git clone $GIT_URL/linux-imx.git -b $BRANCH
+    fi
+
+    pr_info "Start build linux kernel source code"
+
+    cd $KER_PATH
+
+    defconfig=imx_v8_defconfig
+    if [ ! -s .config ] ; then
+        make ${defconfig}
+    fi
+
+    make -j ${JOBS}
+}
+
+function do_install()
+{
+    pr_info "start install linux kernel images"
+
+    cd $KER_PATH
+
+    if [ -d $PRFX_PATH ] ; then
+        rm -rf $PRFX_PATH/*
+	else
+		mkdir -p $PRFX_PATH
+	fi
+
+    # Install image
+    cp arch/arm64/boot/Image $PRFX_PATH
+    cp arch/arm64/boot/dts/freescale/${BOARD}.dtb $PRFX_PATH
+
+    # Install kernel modules
+    make modules_install INSTALL_MOD_PATH=$PRFX_PATH INSTALL_MOD_STRIP=1
+
+    echo ""
+    pr_info "linux kernel installed to '$PRFX_PATH'"
+    ls $PRFX_PATH && echo ""
+
+    if [[ -n "$INST_PATH" && -w $INST_PATH ]] ; then
+        pr_info "install linux kernel to '$INST_PATH'"
+        cp $PRFX_PATH/Image $INST_PATH
+        cp $PRFX_PATH/${BOARD}.dtb $INST_PATH
+    fi
+}
+
+function do_build()
+{
+    cd $PRJ_PATH
+
+    build_kernel
+
+    do_install
+}
+
+function do_clean()
+{
+    cd $PRJ_PATH
+
+    for d in $SRCS
+    do
+        rm -rf $PRJ_PATH/$d
+    done
+
+    rm -rf $PRFX_PATH
+}
+
+#+-------------------------+
+#| Shell script body entry |
+#+-------------------------+
+
+export_env
+
+if [[ $# == 1 && $1 == -c ]] ;then
+    pr_warn "start clean linux kernel"
+    do_clean
+    exit;
+fi
+
+pr_warn "start build linux kernel for ${BOARD}"
+
+do_build
+
diff --git a/tools/imgmnt b/tools/imgmnt
new file mode 100755
index 0000000..0999302
--- /dev/null
+++ b/tools/imgmnt
@@ -0,0 +1,120 @@
+#!/bin/bash
+# This shell script used mount/umount an linux system image and update it
+
+mnt_boot=boot
+mnt_root=rootfs
+
+function mount_image()
+{ 
+    img_file=$1 
+    loop_dev=`losetup  -f | cut -d/ -f3`
+
+    if [ ! -s $img_file ] ; then 
+        echo "ERROR: $img_file not found!" 
+        exit 1; 
+    fi 
+
+    if [ -z $loop_dev ] ; then 
+        echo "ERROR: loop dev not found!"
+        exit 2;
+    fi 
+
+    echo "INFO: losetup /dev/${loop_dev} ${img_file}"
+    losetup /dev/${loop_dev} ${img_file}
+    if [ $? != 0 ] ; then 
+        echo "ERROR: losetup /dev/${loop_dev} ${img_file} failed!" 
+        exit 3; 
+    fi
+
+    echo "INFO: kpartx -av /dev/${loop_dev}"
+    kpartx -av /dev/${loop_dev}
+
+    echo "INFO: mount ${mnt_boot} ${mnt_root}"
+    mkdir -p ${mnt_boot} ${mnt_root}
+    mount /dev/mapper/${loop_dev}p1 ${mnt_boot}
+    mount /dev/mapper/${loop_dev}p2 ${mnt_root}
+
+    echo "INFO: mount $img_file done."
+}
+
+function umount_image()
+{
+    img_file=$1 
+
+    mountpoint $mnt_boot > /dev/null 2>&1
+    if [ $? == 0 ] ; then
+        echo "INFO: umount ${mnt_boot}"
+        umount ${mnt_boot}
+        rmdir  ${mnt_boot}
+    fi
+
+    mountpoint $mnt_root > /dev/null 2>&1
+    if [ $? == 0 ] ; then
+        echo "INFO: umount ${mnt_root}"
+        umount ${mnt_root}
+        rmdir  ${mnt_root}
+    fi
+
+    # loop_dev should be 'loopX' such as 'loop9'.
+    loop_dev=`losetup -a | grep $img_file| cut -d: -f1 | cut -d/ -f3`
+    if [[ -z $loop_dev ]] ; then
+        exit;
+    fi
+
+    if [[ -e /dev/mapper/${loop_dev}p1 ]] ; then
+        echo "INFO: kpartx -dv /dev/${loop_dev}"
+        kpartx -dv /dev/${loop_dev}
+    fi
+
+    echo "INFO: losetup -d /dev/${loop_dev}"
+    losetup -d /dev/${loop_dev}
+
+    echo "INFO: umount $img_file done."
+}
+
+
+function do_usage()
+{
+    echo ""
+    echo "Usage:"
+    echo "  $0 [-m] [-u] image_file"
+    echo "     -m:  mount the image file"
+    echo "     -u: umount the image file"
+    echo ""
+    exit;
+}
+
+action=
+img_file=
+
+while getopts "mu" OPTNAME
+do
+    case "${OPTNAME}" in
+        "m")
+            action=mount
+            ;;  
+
+        "u")
+            action=umount
+            ;;  
+
+        "*")
+            do_usage
+            ;;  
+    esac
+done
+
+shift $(( $OPTIND-1 ))
+img_file=$1
+
+if [[ -z $img_file ]] || [[ -z $action ]] ; then 
+    do_usage
+    exit;
+fi
+
+if [ $action == "mount" ] ; then
+    mount_image $img_file
+elif [ $action == "umount" ] ; then
+    umount_image $img_file
+fi
+
diff --git a/tools/setup_tools.sh b/tools/setup_tools.sh
new file mode 100755
index 0000000..5e4314c
--- /dev/null
+++ b/tools/setup_tools.sh
@@ -0,0 +1,120 @@
+#!/bin/bash
+# This shell script used to install system tools
+
+# display in red
+function pr_error() {
+    echo -e "\033[40;31m --E-- $1 \033[0m\n"
+}
+
+# display in green
+function pr_info() {
+    echo -e "\033[40;32m --I-- $1 \033[0m\n"
+}
+
+if [ `id -u` != 0 ] ; then
+    echo ""
+    pr_error "This shell script must be excuted as root privilege"
+    exit;
+fi
+
+function install_systools()
+{
+    if command -v jq > /dev/null 2>&1 ; then
+        pr_info "All system tools already installed, skip it"
+        return 0;
+    fi
+
+    pr_info "start apt install system tools(commands)"
+
+    systools="coreutils jq wget curl tree gawk sed unzip cpio bc lzop zstd rsync kmod kpartx \
+        desktop-file-utils iputils-ping xterm diffstat chrpath asciidoc docbook-utils help2man \
+        build-essential gcc g++ make cmake automake groff socat flex texinfo bison texi2html \
+        git cvs subversion mercurial autoconf autoconf-archive parted dosfstools \
+        python3 python3-pip python3-pexpect python3-git python3-jinja2 \
+        lib32z1 libssl-dev libncurses-dev libgl1-mesa-dev libglu1-mesa-dev libsdl1.2-dev "
+
+    apt update > /dev/null 2>&1
+    apt install -y $systools
+}
+
+
+function install_devtools()
+{
+    if command -v debootstrap > /dev/null 2>&1 ; then
+        pr_info "All development tools already installed, skip it"
+        return 0;
+    fi
+
+    pr_info "start apt install devlopment tools(commands)"
+
+    devtools="u-boot-tools mtd-utils device-tree-compiler binfmt-support \
+                qemu qemu-user-static debootstrap debian-archive-keyring "
+
+    apt install -y $devtools
+}
+
+
+# NXP document suggest cross compiler from ARM Developer:
+#   https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads
+function install_crosstool()
+{
+    ARMTOOL_VER=10.3-2021.07
+
+    CortexM_PACK=gcc-arm-none-eabi-$ARMTOOL_VER-`uname -p`-linux
+    CortexM_TAR=$CortexM_PACK.tar.bz2
+    CortexM_URL=https://developer.arm.com/-/media/Files/downloads/gnu-rm/$ARMTOOL_VER/
+    CortexM_NAME=gcc-cortexM-$ARMTOOL_VER
+
+    # Crosstool for Cortex-M download from ARM Developer
+
+    if [ -d /opt/$CortexM_NAME ]  ; then
+        pr_info "Cortex-M crosstool /opt/$CortexM_NAME installed already, skip it"
+    else
+        if [ ! -s $CortexM_TAR ] ; then
+            pr_info "start download cross compiler from ARM Developer for Cortex-M core"
+            wget $CortexM_URL/$CortexM_TAR
+        fi
+
+        pr_info "start decompress cross compiler for Cortex-M core"
+        tar -xjf $CortexM_TAR -C /opt
+        mv /opt/gcc-arm-none-eabi-$ARMTOOL_VER /opt/$CortexM_NAME
+        rm -f $CortexM_TAR
+
+        /opt/$CortexM_NAME/bin/arm-none-eabi-gcc -v
+        pr_info "cross compiler for Cortex-M installed to \"/opt/$CortexM_NAME\" successfully"
+    fi
+
+    # Crosstool for Cortex-A download from ARM Developer
+
+    CortexA_PACK=gcc-arm-$ARMTOOL_VER-`uname -p`-aarch64-none-linux-gnu
+    CortexA_TAR=$CortexA_PACK.tar.xz
+    CortexA_URL=https://developer.arm.com/-/media/Files/downloads/gnu-a/$ARMTOOL_VER/binrel/
+    CortexA_NAME=gcc-aarch64-$ARMTOOL_VER
+
+    if [ -d /opt/$CortexA_NAME ]  ; then
+        pr_info "Cortex-A crosstool /opt/$CortexA_NAME installed already, skip it"
+    else
+        if [ ! -s $CortexA_TAR ] ; then
+            pr_info "start download cross compiler from ARM Developer for Cortex-A core"
+            wget $CortexA_URL/$CortexA_TAR
+        fi
+
+        pr_info "start decompress cross compiler for Cortex-A core"
+        tar -xJf $CortexA_TAR -C /opt
+        mv /opt/$CortexA_PACK /opt/$CortexA_NAME
+        rm -f $CortexA_TAR
+
+        /opt/$CortexA_NAME/bin/aarch64-none-linux-gnu-gcc -v
+        pr_info "cross compiler for Cortex-A installed to \"/opt/$CortexA_NAME\" successfully"
+    fi
+}
+
+echo ""
+set -e
+
+install_systools
+
+install_devtools
+
+install_crosstool
+
diff --git a/yocto/build.sh b/yocto/build.sh
new file mode 100755
index 0000000..756d044
--- /dev/null
+++ b/yocto/build.sh
@@ -0,0 +1,149 @@
+#!/bin/bash
+
+# bitbake target
+BB_TARGET=imx-image-full
+
+# this project absolute path
+PRJ_PATH=$(cd $(dirname "${BASH_SOURCE[0]}") && pwd)
+
+# top project absolute path
+TOP_PATH=$(realpath $PRJ_PATH/..)
+
+# binaries install path
+INST_PATH=$PRJ_PATH/install
+
+# config file path
+CONF_FILE=$TOP_PATH/config.json
+
+# Download path
+#DL_PATH="/srv/yocto_packets/"
+
+# shell script will exit once get command error
+set -e
+
+#+-------------------------+
+#| Shell script functions  |
+#+-------------------------+
+
+function pr_error() {
+    echo -e "\033[40;31m $1 \033[0m"
+}
+
+function pr_warn() {
+    echo -e "\033[40;33m $1 \033[0m"
+}
+
+function pr_info() {
+    echo -e "\033[40;32m $1 \033[0m"
+}
+
+# parser configure file and export environment variable
+function export_env()
+{
+    export BOARD=`jq -r ".bsp.board" $CONF_FILE | tr 'A-Z' 'a-z'`
+    export BSP_VER=`jq -r ".bsp.version" $CONF_FILE | tr 'A-Z' 'a-z'`
+    export GIT_URL=`jq -r ".bsp.giturl" $CONF_FILE | tr 'A-Z' 'a-z'`
+    export YCT_VER=`jq -r ".system.version" $CONF_FILE | tr 'A-Z' 'a-z'`
+
+    export YCT_PATH=$PRJ_PATH/$YCT_VER-$BSP_VER
+    export BUILD_DIR=${BOARD}
+
+    if [[ $BOARD =~ mx93 ]] ; then
+        YCT_MACHINE=imx93evk
+    elif [[ $BOARD =~ mx8ulp ]] ; then
+        YCT_MACHINE=imx8ulp-lpddr4-evk
+    elif [[ $BOARD =~ mx8mq ]] ; then
+        YCT_MACHINE=imx8mqevk
+    elif [[ $BOARD =~ mx8mp ]] ; then
+        YCT_MACHINE=imx8mp-ddr4-evk
+    elif [[ $BOARD =~ mx8mm ]] ; then
+        YCT_MACHINE=imx8mm-ddr4-evk
+    elif [[ $BOARD =~ mx8mn ]] ; then
+        YCT_MACHINE=imx8mn-ddr4-evk
+    fi
+}
+
+function do_fetch()
+{
+    mkdir -p $YCT_PATH && cd $YCT_PATH
+
+    if [ ! -d sources ] ; then
+        pr_info "start repo fetch Yocto $YCT_VER source code"
+
+        if ! command -v repo > /dev/null 2>&1 ; then
+            curl https://storage.googleapis.com/git-repo-downloads/repo > repo
+            chmod a+x repo
+            export PATH=$YCT_PATH:$PATH
+        fi
+
+        BSP_VER=`echo $BSP_VER | sed 's/lf/imx/'`
+        repo init -u https://github.com/nxp-imx/imx-manifest -b imx-linux-$YCT_VER -m $BSP_VER.xml
+        repo sync && rm -f repo
+
+    else
+        pr_warn "Yocto $YCT_VER source code fetched already"
+    fi
+}
+
+function do_build()
+{
+    cd $YCT_PATH
+
+    if [ ! -f ${BUILD_DIR}/conf/local.conf ] ; then
+        pr_info "source imx-setup-release.sh for $BOARD"
+        DISTRO=fsl-imx-wayland MACHINE=$YCT_MACHINE source imx-setup-release.sh -b $BUILD_DIR
+    else
+        pr_info "source poky/oe-init-build-env"
+        source sources/poky/oe-init-build-env $BUILD_DIR
+    fi
+
+    if [[ -n "$DL_PATH" ]] ; then
+        sed -i "s|^#DL_DIR.*|DL_DIR ?= \"$DL_PATH\"|g" conf/local.conf
+        sed -i "s|^DL_DIR.*|DL_DIR ?= \"$DL_PATH\"|g" conf/local.conf
+    fi
+
+    bitbake $BB_TARGET
+}
+
+function do_install()
+{
+    cd $YCT_PATH
+
+    echo ""
+    pr_info "Yocto($YCT_VER) installed to '$INST_PATH'"
+
+    mkdir -p ${INST_PATH}
+    cp $BUILD_DIR/tmp/deploy/images/*/$BB_TARGET-*.rootfs.tar.zst ${INST_PATH}/rootfs.tar.zst
+    cp $BUILD_DIR/tmp/deploy/images/*/imx-boot ${INST_PATH}/u-boot-${BOARD}.imx
+    chmod a+x ${INST_PATH}/u-boot-${BOARD}.imx
+    cp $BUILD_DIR/tmp/deploy/images/*/$BB_TARGET-*.wic.zst ${INST_PATH}
+
+    ls ${INST_PATH} && echo ""
+}
+
+function do_clean()
+{
+    cd $PRJ_PATH
+
+    rm -rf $INST_PATH
+}
+
+#+-------------------------+
+#| Shell script body entry |
+#+-------------------------+
+
+export_env
+
+if [[ $# == 1 && $1 == -c ]] ;then
+    pr_warn "start clean Yocto source code"
+    do_clean
+    exit;
+fi
+
+pr_warn "start build Yocto $YCT_VER for ${BOARD}"
+
+do_fetch
+
+do_build
+
+do_install

--
Gitblit v1.9.1