# SPDX-License-Identifier: GPL-2.0+ OR MIT
#
# Copyright 2020 Toradex
#
# Toradex boot script.
#
# Allows to change boot and rootfs devices independently.
# Supports:
# - boot device type: boot_devtype := {mmc, usb, tftp, dhcp}
# - boot device num (for mmc, usb types): boot_devnum := {0 .. MAX_DEV_NUM}
# - boot partition (for mmc, usb types): boot_part := {1 .. MAX_PART_NUM}
# - root device type: root_devtype := {mmc, usb, nfs-dhcp, nfs-static}
# - root device num (for mmc, usb types): root_devnum := {0 .. MAX_DEV_NUM}
# - root partition (for mmc, usb types): root_part := {1 .. MAX_PART_NUM}
#
# Defaults:
#    root_devtype = boot_devtype = devtype
#    root_devnum = boot_devnum = devnum
#    boot_part = distro_bootpart
#    root_part = 2
#
# Common variables used in tftp/dhcp modes:
# - Static/dynamic IP mode: ip_dyn := {yes, no}
# - Static IP-address of TFTP/NFS server: serverip := {legal IPv4 address}
# - Static IP-address of the module: ipaddr := {legal IPv4 address}
# - Root-path on NFS-server: rootpath := {legal path, exported by an NFS-server}
#
# Common flags:
# - Skip loading overlays: skip_fdt_overlays := {1, 0}
#   1 - skip, any other value (or undefined variable) - don't skip.
#   This variable is adopted from the TorizonCore and shouldn't be
#   renamed separately.

if test ${devtype} = "ubi"; then
    echo "This script is not meant to distro boot from raw NAND flash."
    exit
fi

test -n ${m4boot} || env set m4boot ';'
test -n ${fdtfile} || env set fdtfile ${fdt_file}
test -n ${boot_part} || env set boot_part ${distro_bootpart}
test -n ${root_part} || env set root_part 2
test -n ${boot_devnum} || env set boot_devnum ${devnum}
test -n ${root_devnum} || env set root_devnum ${devnum}
test -n ${kernel_image} || env set kernel_image @@KERNEL_IMAGETYPE@@
test -n ${boot_devtype} || env set boot_devtype ${devtype}
test -n ${overlays_file} || env set overlays_file "overlays.txt"
test -n ${overlays_prefix} || env set overlays_prefix "overlays/"
test -n ${fitconf_fdt_overlays} || env set fitconf_fdt_overlays '@@FITCONF_FDT_OVERLAYS@@'

test ${boot_devtype} = "mmc" && env set load_cmd 'load ${boot_devtype} ${boot_devnum}:${boot_part}'
test ${boot_devtype} = "usb" && env set load_cmd 'load ${boot_devtype} ${boot_devnum}:${boot_part}'
test ${boot_devtype} = "tftp" && env set load_cmd 'tftp'
test ${boot_devtype} = "dhcp" && env set load_cmd 'dhcp'

# Set Root source type properly.
# devtype tftp => nfs-static
# devtype ghcp => nfs-dhcp
if test "${root_devtype}" = ""; then
    if test ${devtype} = "tftp"; then
        env set root_devtype "nfs-static"
    elif test ${devtype} = "dhcp"; then
        env set root_devtype "nfs-dhcp"
    else
        env set root_devtype ${devtype}
    fi
fi

if test -n ${setup}; then
    run setup
else
    env set setupargs console=tty1 console=${console},${baudrate} consoleblank=0
fi

env set bootcmd_unzip ';'
if test ${kernel_image} = "fitImage"; then
    env set kernel_addr_load ${ramdisk_addr_r}
elif test -n ${kernel_comp_addr_r}; then
    # use booti automatic decompression
    env set kernel_addr_load ${loadaddr}
elif test ${kernel_image} = "Image.gz"; then
    env set kernel_addr_load ${loadaddr}
    env set bootcmd_unzip 'unzip ${kernel_addr_load} ${kernel_addr_r}'
else
    env set kernel_addr_load ${kernel_addr_r}
fi

# Set dynamic commands
env set set_bootcmd_kernel 'env set bootcmd_kernel "${load_cmd} \\${kernel_addr_load} \\${kernel_image}"'
env set set_load_overlays_file 'env set load_overlays_file "${load_cmd} \\${loadaddr} \\${overlays_file} && env import -t \\${loadaddr} \\${filesize}"'
if test ${kernel_image} = "fitImage"; then
    env set fdt_high
    env set fdt_resize true
    env set set_bootcmd_dtb 'env set bootcmd_dtb "true"'
    env set set_apply_overlays 'env set apply_overlays "for overlay_file in \"\\${fdt_overlays}\"; do env set fitconf_fdt_overlays \"\\"\\${fitconf_fdt_overlays}#conf-\\${overlay_file}\\"\"; env set overlay_file; done; true"'
    env set bootcmd_boot 'echo "Bootargs: \${bootargs}" && bootm ${kernel_addr_load}#conf-@@KERNEL_DTB_PREFIX@@\${fdtfile}\${fitconf_fdt_overlays}'
else
    env set fdt_resize 'fdt addr ${fdt_addr_r} && fdt resize 0x20000'
    env set set_bootcmd_dtb 'env set bootcmd_dtb "echo Loading DeviceTree: \\${fdtfile}; ${load_cmd} \\${fdt_addr_r} \\${fdtfile}"'
    env set set_apply_overlays 'env set apply_overlays "for overlay_file in \\${fdt_overlays}; do echo Applying Overlay: \\${overlay_file} && ${load_cmd} \\${loadaddr} \\${overlays_prefix}\\${overlay_file} && fdt apply \\${loadaddr}; env set overlay_file; done; true"'
    env set bootcmd_boot 'echo "Bootargs: \${bootargs}" && @@KERNEL_BOOTCMD@@ ${kernel_addr_r} - ${fdt_addr_r}'
fi

# Set static commands
if test ${root_devtype} = "nfs-dhcp"; then
    env set rootfsargs_set 'env set rootfsargs "root=/dev/nfs ip=dhcp"'
elif test ${root_devtype} = "nfs-static"; then
    env set rootfsargs_set 'env set rootfsargs "root=/dev/nfs nfsroot=${serverip}:/${rootpath}"'
else
    env set uuid_set 'part uuid ${root_devtype} ${root_devnum}:${root_part} uuid'
    env set rootfsargs_set 'run uuid_set && env set rootfsargs "root=PARTUUID=${uuid} ro rootwait"'
fi

env set bootcmd_args 'run rootfsargs_set && env set bootargs ${defargs} ${rootfsargs} ${setupargs} ${vidargs} ${tdxargs}'
if test ${skip_fdt_overlays} != 1; then
    env set bootcmd_overlays 'run load_overlays_file && run fdt_resize && run apply_overlays'
else
    env set bootcmd_overlays true
fi
env set bootcmd_prepare 'run set_bootcmd_kernel; run set_bootcmd_dtb; run set_load_overlays_file; run set_apply_overlays'
env set bootcmd_run 'run m4boot; run bootcmd_dtb && run bootcmd_overlays && run bootcmd_args && run bootcmd_kernel && run bootcmd_unzip && run bootcmd_boot; echo "Booting from ${devtype} failed!" && false'

run bootcmd_prepare
run bootcmd_run

