# Custom U-Boot base environment for Nerves

# This environment is a majorly trimmed down version of the default
# one that ships with the Beaglebone.
#
# Why?
#   1. We want to store settings in the U-boot environment so that they're
#      accessible both to Elixir and U-boot.
#   2. This makes us add an environment block.
#   3. Unfortunately, if we point U-Boot to this block, it replaces its
#      default environment settings which contain all of the logic to
#      boot the boards. Therefore we have to copy/paste the relevant
#      parts here.
#   4. We can support more complicated firmware validation methods by
#      deferring validation of new software to the application. The
#      default below is to automatically validate new software.
#
# See U-Boot/include/configs/ti_armv7_common.h and
# U-Boot/include/configs/am335x_evm.h for most of what's below.

#
# Nerves variables
#

nerves_fw_active=a

# nerves_fw_autovalidate controls whether updates are considered valid once
# applied. If set to 0, the user needs to set nerves_fw_validated to 1 in their
# application. If they don't set it before a reboot, then the previous software
# is run. If 1, then no further action needs to be taken.
nerves_fw_autovalidate=1

# nerves_fw_validated is 1 if the current boot selection is accepted It is set
# to 1 here, since this environment is written in the factory, so it is
# implicitly valid.
nerves_fw_validated=1

# nerves_fw_booted is 0 for the first boot and 1 for all reboots after that.
# NOTE: Keep this '0' so that all new boards run a 'saveenv' to exercise the
#       code that writes back to the eMMC early on.
nerves_fw_booted=0

# The nerves initialization logic
#
# The nerves_init code is run at boot (see the last line of the file). It
# checks whether this is a first boot or not. If it's not the first boot, then
# the firmware better be validated or it reverts to running the firmware on
# the opposite partition.
nerves_revert=\
    if test ${nerves_fw_active} = "a"; then\
        echo "Reverting to partition B";\
        setenv nerves_fw_active "b";\
    else\
        echo "Reverting to partition A";\
        setenv nerves_fw_active "a";\
    fi

nerves_init=\
    if test ${nerves_fw_booted} = 1; then\
        if test ${nerves_fw_validated} = 0; then\
            run nerves_revert;\
            setenv nerves_fw_validated 1;\
            saveenv;\
        fi;\
    else\
        setenv nerves_fw_booted 1;\
        if test ${nerves_fw_autovalidate} = 1; then\
            setenv nerves_fw_validated 1;\
        fi;\
        saveenv;\
    fi;\
    setenv bootfile zImage.${nerves_fw_active};\
    if test ${nerves_fw_active} = "a"; then\
        setenv uenv_root /dev/mmcblk0p2;\
        setenv bootpart 0:2;\
    else\
        setenv uenv_root /dev/mmcblk0p3;\
        setenv bootpart 0:3;\
    fi

#
# Beagleboard variables with Nerves updates
#

#
# Default Linux commandline:
#
# coherent_pool=1M          - copied from Beaglebone defaults. It's needed for some WiFi drivers.
# net.ifnames=0             - copied from Beaglebone defaults
# omap_wdt.early_enable=1   - turn on the internal watchdog timer asap
# omap_wdt.timer_margin=120 - Erlang heart has 120 seconds to start petting the timer
# quiet                     - limit kernel prints to the console
cmdline=coherent_pool=1M net.ifnames=0 omap_wdt.early_enable=1 omap_wdt.timer_margin=120 quiet

# Defaults
console=ttyS0,115200n8
bootdir=
fdtdir=/boot
fdtfile=undefined
devtype=mmc
# squashfs support is slow, so always load the kernel from FAT (FIXME)
kernel_bootpart=0:1

# Allocate memory for calls to dma_alloc_coherent. USB WiFi adapters
# use this.
optargs=coherent_pool=1M

# Memory offset for loading files
loadaddr=0x82000000
kernel_addr_r=0x82000000
fdtaddr=0x88000000
fdt_addr_r=0x88000000
rdaddr=0x88080000
ramdisk_addr_r=0x88080000
scriptaddr=0x80000000
bootm_size=0x10000000

# Helper functions
args_uenv_root=setenv bootargs console=${console} ${optargs} ${cape_disable} ${cape_enable} ${cape_uboot} root=${uenv_root} rootfstype=squashfs rootwait ${uboot_detected_capes} ${cmdline}

loadimage=load ${devtype} ${kernel_bootpart} ${loadaddr} ${bootdir}/${bootfile}
loadfdt=echo loading ${fdtdir}/${fdtfile} ...; load ${devtype} ${bootpart} ${fdtaddr} ${fdtdir}/${fdtfile}

loadoverlay=echo uboot_overlays: loading ${uboot_overlay} ...;\
	load ${devtype} ${bootpart} ${rdaddr} ${uboot_overlay};\
	fdt addr ${fdtaddr}; fdt resize ${fdt_buffer};\
	fdt apply ${rdaddr}; fdt resize ${fdt_buffer}

virtualloadoverlay=if test -e ${devtype} ${bootpart} ${uboot_overlay}; then\
			run loadoverlay;\
		else\
			echo uboot_overlays: unable to find [${devtype} ${bootpart} ${uboot_overlay}]...;\
		fi

capeloadoverlay=if test -e ${devtype} ${bootpart} ${uboot_overlay}; then\
			run loadoverlay;\
			setenv cape_uboot bone_capemgr.uboot_capemgr_enabled=1;\
		else\
			echo uboot_overlays: unable to find [${devtype} ${bootpart} ${uboot_overlay}]...;\
		fi

findfdt=echo board_name=[$board_name] ...;\
        if test $board_name = A335PBGL; then\
		setenv fdtfile am335x-pocketbeagle.dtb; fi;\
	if test $board_name = A335BLGC; then\
		setenv fdtfile am335x-beaglelogic.dtb; fi;\
	if test $board_name = A335BONE; then\
		setenv fdtfile am335x-bone.dtb; fi;\
	if test $board_name = A335BNLT; then\
		echo board_rev=[$board_rev] ...;\
		if test $board_rev = GH01; then\
			setenv fdtfile am335x-boneblack.dtb;\
		elif test $board_rev = BBG1; then\
			setenv fdtfile am335x-bonegreen.dtb;\
		elif test $board_rev = BP00; then\
			setenv fdtfile am335x-pocketbone.dtb;\
		elif test $board_rev = GW1A; then\
			setenv fdtfile am335x-bonegreen-wireless.dtb;\
		elif test $board_rev = AIA0; then\
			setenv fdtfile am335x-abbbi.dtb;\
		elif test $board_rev = EIA0; then\
			setenv fdtfile am335x-boneblack.dtb;\
		elif test $board_rev = SE0A; then\
			setenv fdtfile am335x-sancloud-bbe.dtb;\
		elif test $board_rev = ME06; then\
			setenv fdtfile am335x-bonegreen.dtb;\
		elif test $board_rev = M10A; then\
			setenv fdtfile am335x-vsc8531bbb.dtb;\
		elif test $board_rev = OS00; then\
			setenv fdtfile am335x-osd3358-sm-red.dtb;\
		else\
			setenv fdtfile am335x-boneblack.dtb;\
		fi;\
	fi;\
	if test $board_name = BBBW; then\
		setenv fdtfile am335x-boneblack-wireless.dtb; fi;\
	if test $board_name = BBG1; then\
		setenv fdtfile am335x-bonegreen.dtb; fi;\
	if test $board_name = BBGW; then\
		setenv fdtfile am335x-bonegreen-wireless.dtb; fi;\
	if test $board_name = BBBL; then\
		setenv fdtfile am335x-boneblue.dtb; fi;\
	if test $board_name = SBBE; then\
		setenv fdtfile am335x-sancloud-bbe.dtb; fi;\
	if test $board_name = OS00; then\
		setenv fdtfile am335x-osd3358-sm-red.dtb; fi;\
	if test $board_name = A33515BB; then\
		setenv fdtfile am335x-evm.dtb; fi;\
	if test $board_name = A335X_SK; then\
		setenv fdtfile am335x-evmsk.dtb; fi;\
	if test $board_name = A335_ICE; then\
		setenv fdtfile am335x-icev2.dtb; fi;\
	if test $fdtfile = undefined; then\
		setenv board_name A335BNLT;\
		setenv board_rev EMMC;\
		setenv fdtfile am335x-boneblack-emmc-overlay.dtb;\
	fi;true

uname_boot=if test -e ${devtype} ${kernel_bootpart} ${bootdir}/${bootfile}; then\
		echo loading ${bootdir}/${bootfile} ...;\
		run loadimage;\
		if test -n ${enable_uboot_overlays}; then\
			if test -n ${uboot_base_dtb_univ}; then\
				if test -n ${dtb}; then\
					echo uboot_overlays: dtb=${dtb} in /boot/uEnv.txt, unable to use [uboot_base_dtb=${uboot_base_dtb_univ}] ... ;\
				else\
					echo uboot_overlays: [uboot_base_dtb=${uboot_base_dtb_univ}] ... ;\
					if test -e ${devtype} ${bootpart} ${fdtdir}/${uboot_base_dtb_univ}; then\
						setenv fdtfile ${uboot_base_dtb_univ};\
						echo uboot_overlays: Switching too: dtb=${fdtfile} ...;\
						if test -n ${uboot_try_cape_universal}; then\
							env delete -f uboot_try_cape_universal;\
						fi;\
						setenv cape_uboot bone_capemgr.uboot_capemgr_enabled=1;\
					else\
						if test -n ${uboot_base_dtb}; then\
							echo uboot_overlays: [uboot_base_dtb=${uboot_base_dtb}] ... ;\
							if test -e ${devtype} ${bootpart} ${fdtdir}/${uboot_base_dtb}; then\
								setenv fdtfile ${uboot_base_dtb};\
								echo uboot_overlays: Switching too: dtb=${fdtfile} ...;\
							fi;\
						fi;\
					fi;\
				fi;\
			fi;\
		fi;\
                run loadfdt;\
		if test -n ${enable_uboot_overlays}; then\
			setenv fdt_buffer 0x60000;\
			if test -n ${uboot_fdt_buffer}; then\
				setenv fdt_buffer ${uboot_fdt_buffer};\
			fi;\
			echo uboot_overlays: [fdt_buffer=${fdt_buffer}] ... ;\
			if test -n ${uboot_silicon}; then\
				setenv uboot_overlay ${uboot_silicon};\
				run virtualloadoverlay;\
			fi;\
			if test -n ${uboot_model}; then\
				setenv uboot_overlay ${uboot_model};\
				run virtualloadoverlay;\
			fi;\
			if test -n ${uboot_overlay_addr0}; then\
				if test -n ${disable_uboot_overlay_addr0}; then\
					echo uboot_overlays: uboot loading of [${uboot_overlay_addr0}] disabled [disable_uboot_overlay_addr0=1]...;\
				else\
					setenv uboot_overlay ${uboot_overlay_addr0};\
					run capeloadoverlay;\
				fi;\
			fi;\
			if test -n ${uboot_overlay_addr1}; then\
				if test -n ${disable_uboot_overlay_addr1}; then\
					echo uboot_overlays: uboot loading of [${uboot_overlay_addr1}] disabled [disable_uboot_overlay_addr1=1]...;\
				else\
					setenv uboot_overlay ${uboot_overlay_addr1};\
					run capeloadoverlay;\
				fi;\
			fi;\
			if test -n ${uboot_overlay_addr2}; then\
				if test -n ${disable_uboot_overlay_addr2}; then\
					echo uboot_overlays: uboot loading of [${uboot_overlay_addr2}] disabled [disable_uboot_overlay_addr2=1]...;\
				else\
					setenv uboot_overlay ${uboot_overlay_addr2};\
					run capeloadoverlay;\
				fi;\
			fi;\
			if test -n ${uboot_overlay_addr3}; then\
				if test -n ${disable_uboot_overlay_addr3}; then\
					echo uboot_overlays: uboot loading of [${uboot_overlay_addr3}] disabled [disable_uboot_overlay_addr3=1]...;\
				else\
					setenv uboot_overlay ${uboot_overlay_addr3};\
					run capeloadoverlay;\
				fi;\
			fi;\
			if test -n ${uboot_overlay_addr4}; then\
				setenv uboot_overlay ${uboot_overlay_addr4};\
				run capeloadoverlay;\
			fi;\
			if test -n ${uboot_overlay_addr5}; then\
				setenv uboot_overlay ${uboot_overlay_addr5};\
				run capeloadoverlay;\
			fi;\
			if test -n ${uboot_overlay_addr6}; then\
				setenv uboot_overlay ${uboot_overlay_addr6};\
				run capeloadoverlay;\
			fi;\
			if test -n ${uboot_overlay_addr7}; then\
				setenv uboot_overlay ${uboot_overlay_addr7};\
				run capeloadoverlay;\
			fi;\
			if test -n ${uboot_emmc}; then\
				if test -n ${disable_uboot_overlay_emmc}; then\
					echo uboot_overlays: uboot loading of [${uboot_emmc}] disabled [disable_uboot_overlay_emmc=1]...;\
				else\
					setenv uboot_overlay ${uboot_emmc};\
					run virtualloadoverlay;\
				fi;\
			fi;\
			if test -n ${uboot_video}; then\
				if test -n ${disable_uboot_overlay_video}; then\
					echo uboot_overlays: uboot loading of [${uboot_video}] disabled [disable_uboot_overlay_video=1]...;\
				else\
					if test -n ${disable_uboot_overlay_audio}; then\
						echo uboot_overlays: uboot loading of [${uboot_video}] disabled [disable_uboot_overlay_audio=1]...;\
						setenv uboot_overlay ${uboot_video_naudio};\
						run virtualloadoverlay;\
					else\
						setenv uboot_overlay ${uboot_video};\
						run virtualloadoverlay;\
					fi;\
				fi;\
			fi;\
			if test -n ${uboot_wireless}; then\
				if test -n ${disable_uboot_overlay_wireless}; then\
					echo uboot_overlays: uboot loading of [${uboot_wireless}] disabled [disable_uboot_overlay_wireless=1]...;\
				else\
					setenv uboot_overlay ${uboot_wireless};\
					run virtualloadoverlay;\
				fi;\
			fi;\
			if test -n ${uboot_adc}; then\
				if test -n ${disable_uboot_overlay_adc}; then\
					echo uboot_overlays: uboot loading of [${uboot_adc}] disabled [disable_uboot_overlay_adc=1]...;\
				else\
					setenv uboot_overlay ${uboot_adc};\
					run virtualloadoverlay;\
				fi;\
			fi;\
			if test -n ${uboot_overlay_pru}; then\
				setenv uboot_overlay ${uboot_overlay_pru};\
				run virtualloadoverlay;\
			fi;\
			if test -n ${dtb_overlay}; then\
				setenv uboot_overlay ${dtb_overlay};\
				echo uboot_overlays: [dtb_overlay=${uboot_overlay}] ... ;\
				run capeloadoverlay;\
			fi;\
			if test -n ${uboot_detected_capes}; then\
				echo uboot_overlays: [uboot_detected_capes=${uboot_detected_capes_addr0}${uboot_detected_capes_addr1}${uboot_detected_capes_addr2}${uboot_detected_capes_addr3}] ... ;\
				setenv uboot_detected_capes uboot_detected_capes=${uboot_detected_capes_addr0}${uboot_detected_capes_addr1}${uboot_detected_capes_addr2}${uboot_detected_capes_addr3};\
			fi;\
			if test -n ${uboot_try_cape_universal}; then\
				if test -n ${enable_uboot_cape_universal}; then\
					if test -n ${cape_uboot}; then\
						echo uboot_overlays: cape universal disabled, external cape enabled or detected...;\
					else\
						if test -n ${uboot_cape_universal_bbb}; then\
							if test -n ${disable_uboot_overlay_emmc}; then\
								if test -n ${disable_uboot_overlay_video}; then\
									setenv uboot_overlay /lib/firmware/univ-bbb-xxx-00A0.dtbo;\
								else\
									if test -n ${disable_uboot_overlay_audio}; then\
										setenv uboot_overlay /lib/firmware/univ-bbb-xVx-00A0.dtbo;\
									else\
										setenv uboot_overlay /lib/firmware/univ-bbb-xVA-00A0.dtbo;\
									fi;\
								fi;\
							else\
								if test -n ${disable_uboot_overlay_video}; then\
									setenv uboot_overlay /lib/firmware/univ-bbb-Exx-00A0.dtbo;\
								else\
									if test -n ${disable_uboot_overlay_audio}; then\
										setenv uboot_overlay /lib/firmware/univ-bbb-EVx-00A0.dtbo;\
									else\
										setenv uboot_overlay /lib/firmware/univ-bbb-EVA-00A0.dtbo;\
									fi;\
								fi;\
							fi;\
							run capeloadoverlay;\
						fi;\
						if test -n ${uboot_cape_universal_bbg}; then\
							if test -n ${disable_uboot_overlay_emmc}; then\
								setenv uboot_overlay /lib/firmware/univ-bbb-xxx-00A0.dtbo;\
							else\
								setenv uboot_overlay /lib/firmware/univ-bbb-Exx-00A0.dtbo;\
							fi;\
							run capeloadoverlay;\
						fi;\
						if test -n ${uboot_cape_universal_bbgw}; then\
							if test -n ${disable_uboot_overlay_emmc}; then\
								if test -n ${disable_uboot_overlay_wireless}; then\
									setenv uboot_overlay /lib/firmware/univ-bbgw-xx-00A0.dtbo;\
								else\
									setenv uboot_overlay /lib/firmware/univ-bbgw-xW-00A0.dtbo;\
								fi;\
							else\
								if test -n ${disable_uboot_overlay_wireless}; then\
									setenv uboot_overlay /lib/firmware/univ-bbgw-Ex-00A0.dtbo;\
								else\
									setenv uboot_overlay /lib/firmware/univ-bbgw-EW-00A0.dtbo;\
								fi;\
							fi;\
							run capeloadoverlay;\
						fi;\
					fi;\
				else\
					echo uboot_overlays: add [enable_uboot_cape_universal=1] to enable...;\
				fi;\
			fi;\
		else\
			echo uboot_overlays: add [enable_uboot_overlays=1] to enable...;\
		fi;\
		run args_uenv_root;\
		echo debug: [${bootargs}] ... ;\
		echo debug: [bootz ${loadaddr} - ${fdtaddr}] ... ;\
		bootz ${loadaddr} - ${fdtaddr};\
	fi

# Boot
bootcmd=run nerves_init findfdt uname_boot
