diff --git a/airoha/an7581/UNION_AN7581_KITE_LOGAN_KERNEL_5_4_demo.mak b/airoha/an7581/UNION_AN7581_KITE_LOGAN_KERNEL_5_4_demo.mak
index e81b8ac3ce1eab3ede7a7b7326c94a960e9246d3..69308bc251862d66dfa66c0295ae4576d6b528a3 100644
--- a/airoha/an7581/UNION_AN7581_KITE_LOGAN_KERNEL_5_4_demo.mak
+++ b/airoha/an7581/UNION_AN7581_KITE_LOGAN_KERNEL_5_4_demo.mak
@@ -291,8 +291,11 @@ TCSUPPORT_CPU_ARMV8=y
 TCSUPPORT_CPU_ARMV8_64=y
 # TCSUPPORT_CPU_ARMV8_NO_NEON is not set
 TCSUPPORT_UBOOT=y
-TCSUPPORT_UBOOT_2014=y
-TCSUPPORT_ATF_2_1=y
+#TCSUPPORT_UBOOT_2014 is not set
+TCSUPPORT_UBOOT_2023=y
+TCSUPPORT_TPL_SUPPORT=y
+TCSUPPORT_OPTEE=y
+TCSUPPORT_ATF_2_10=y
 TCSUPPORT_UBOOT_64BIT=y
 # TCSUPPORT_NP is not set
 # TCSUPPORT_NP_CMCC is not set
diff --git a/airoha/dts/en7523-basic.dts b/airoha/dts/en7523-basic.dts
index 383686efccc47b79237a13b6ddd19bdc137c6d0d..0e2708dbfe14fb323c5675a3e0484930ee8ae045 100644
--- a/airoha/dts/en7523-basic.dts
+++ b/airoha/dts/en7523-basic.dts
@@ -26,6 +26,10 @@
 / {
 	model = "en75xx-arm";
 	compatible = "econet,en7523";
+
+	config {
+		bootdelay = <2>;
+	};
 };
 
 &voip {
diff --git a/airoha/dts/en7523_evb.dts b/airoha/dts/en7523_evb.dts
index c886ea865f0cef8b61120a3d5e35bc3ff696f4e9..02ea0df5c5bc8a684f9b18276ec29dca659cef02 100644
--- a/airoha/dts/en7523_evb.dts
+++ b/airoha/dts/en7523_evb.dts
@@ -14,6 +14,10 @@
 		compatible = "iopsys,tcledctrl_stub";
 		pon-tx-power-gpio = <&gpio0 16 GPIO_ACTIVE_LOW>;
 	};
+
+	config {
+		bootdelay = <2>;
+	};
 };
 
 &pon_phy {
diff --git a/airoha/dts/en7581-base.dtsi b/airoha/dts/en7581-base.dtsi
index 343984d5b6ea778ec8dc898553a9b1735c493311..4fb1e219a30f323e5ba11600b58c898602f20a80 100644
--- a/airoha/dts/en7581-base.dtsi
+++ b/airoha/dts/en7581-base.dtsi
@@ -138,6 +138,11 @@
 			reg = <0x0 0x84000000 0x0 0x100000>;
 		};
 
+		optee_reserved: optee_os@8a800000 {
+			no-map;
+			reg = <0x0 0x8a800000 0x0 0x800000>;
+		};
+
 		/* pstore memory reservations */
 		#include "en7581-pstore.dtsi"
 
@@ -389,6 +394,7 @@
 	};
 
 	scu: scu@1fb00000 {
+		bootph-all;
 		compatible = "econet,ecnt-scu";
 			// ------------------------------------------------------------
 			// WARNING:
@@ -641,6 +647,7 @@
 	};
 
 	uart1: serial@1fbf0000 {
+		bootph-all;
 		compatible = "airoha,en7523-uart";
 		reg = <0x0 0x1fbf0000 0x0 0x30>;
 		reg-io-width = <4>;
@@ -746,6 +753,7 @@
 	};
 
 	spi_ctrl: spi_controller@1fa10000 {
+		bootph-all;
 		compatible = "econet,en75xx-spi";
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -758,6 +766,7 @@
 		spi-ecc = <&spi_ecc>;
 
 		spinand@0 {
+			bootph-all;
 			compatible = "spi-nand";
 			reg = <0x0>;			// Chip select
 			spi-tx-bus-width = <2>;
@@ -767,11 +776,13 @@
 	};
 
 	spi_spi2nfi: spi_spi2nfi@1fa11000 {
+		bootph-all;
 		compatible = "econet,ecnt-spi2nfi";
 		reg = <0x0 0x1fa11000 0x0 0x160>;	//NFI2SPI
 	};
 
 	spi_ecc: spi_ecc@1fa12000 {
+		bootph-all;
 		compatible = "econet,ecnt-spi_ecc";
 		reg = <0x0 0x1fa12000 0x0 0x150>;	//NFI ECC
 	};
@@ -1003,6 +1014,7 @@
 	};
 
 	mmc0: mmc@1fa0e000 {
+		bootph-all;
 		compatible = "airoha,an758x-mmc";
 		reg = <0x0 0x1fa0e000 0x0 0x1000>,
 		      <0x0 0x1fa0c000 0x0 0x60>;
@@ -1039,6 +1051,12 @@
 		phy15: phy@15 {
 			reg = <15>;
 		};
+		phy29: phy@29 {
+			reg = <29>;
+		};
+		phy31: phy@31 {
+			eg = <31>;
+		};
 	};
 
 	thermal-zones {
diff --git a/airoha/dts/en7581-basic.dts b/airoha/dts/en7581-basic.dts
index 92195b3c97617624246e675acfefd3a285929045..96fa35835b60bef672e733b66f010d68f8d74f56 100644
--- a/airoha/dts/en7581-basic.dts
+++ b/airoha/dts/en7581-basic.dts
@@ -11,6 +11,10 @@
 / {
 	model = "EN75xx GENERIC";
 	compatible = "econet,en7581", "airoha,en7581";
+
+	config {
+		bootdelay = <2>;
+	};
 };
 
 &voip {
diff --git a/airoha/dts/en7581_eagle.dts b/airoha/dts/en7581_eagle.dts
index d063908daf85625a867794e82cae118e9cc1324b..c0a14c0acc9e3cac36d2d3d5233549e85fc68660 100644
--- a/airoha/dts/en7581_eagle.dts
+++ b/airoha/dts/en7581_eagle.dts
@@ -16,8 +16,11 @@
 		bootargs = "console=ttyS0,115200n8 qdma_init=bb onu_type=72 serdes_ethernet=112 serdes_wifi1=01 serdes_wifi2=01 serdes_usb1=00 serdes_usb2=02 serdes_pon=00";
 		stdout-path = &uart1;
 	};
-};
 
+	config {
+		bootdelay = <2>;
+	};
+};
 
 &voip {
 	slic-power-mode = "none";
diff --git a/airoha/dts/en7581_evb.dts b/airoha/dts/en7581_evb.dts
index 8c3c5f3b2478b0c831b656a5af90c2460b975000..5fa1c9ba52db4c505a2e156039355316d5a9cbb3 100644
--- a/airoha/dts/en7581_evb.dts
+++ b/airoha/dts/en7581_evb.dts
@@ -11,6 +11,10 @@
 / {
 	model = "EN75xx GENERIC";
 	compatible = "econet,en7581-evb", "econet,en7581", "airoha,en7581";
+
+	config {
+		bootdelay = <2>;
+	};
 };
 
 &voip {
diff --git a/airoha/dts/en7581_kite.dts b/airoha/dts/en7581_kite.dts
index 46b0805702e23ed03a7aa29c37bdebc826a03264..6b387eb268a1596192bafc2be3309397a2f8ea0f 100644
--- a/airoha/dts/en7581_kite.dts
+++ b/airoha/dts/en7581_kite.dts
@@ -16,8 +16,11 @@
 		bootargs = "console=ttyS0,115200n8 qdma_init=bb onu_type=72 serdes_ethernet=112 serdes_wifi1=001 serdes_wifi2=001 serdes_usb1=000 serdes_usb2=002 serdes_pon=000";
 		stdout-path = &uart1;
 	};
-};
 
+	config {
+		bootdelay = <2>;
+	};
+};
 
 &voip {
 	slic-power-mode = "none";
diff --git a/airoha/image/Makefile b/airoha/image/Makefile
index 575125fcc0b435651352d0336c505a0d4e534b35..a601321bbbc777a5d91d06d87658f24ae8d3d8a0 100755
--- a/airoha/image/Makefile
+++ b/airoha/image/Makefile
@@ -21,19 +21,19 @@ endef
 define Device/Default-airoha-nand
   $(Device/nand)
   FIT_PARTITION :=
-  KERNEL := kernel-bin | lzma | generate-uboot-images | iowrt-kernel-fit lzma external-static
+  KERNEL := kernel-bin | lzma | generate-uboot-images | prepare-atf-blobs | airoha-iowrt-kernel-fit lzma external-static
   DEVICE_UBI_LAYOUT := ubinize.cfg.in
   UBINIZE_OPTS := -m 2048 -p 131072 -s 2048
-  ARTIFACTS := u-boot-nand.bin u-boot-ram.itb bootext.ram
+  ARTIFACTS := u-boot-nand.bin u-boot-recovery.bin u-boot-ram.itb bootext.ram
   IMAGE/production.img := $$(call airoha-nand-production)
 endef
 
 define Device/Default-airoha-emmc
   $(Device/emmc)
   FIT_PARTITION := 1
-  KERNEL := kernel-bin | lzma | generate-uboot-images | iowrt-kernel-fit lzma external-static-with-rootfs
+  KERNEL := kernel-bin | lzma | generate-uboot-images | prepare-atf-blobs | airoha-iowrt-kernel-fit lzma external-static-with-rootfs
   ARTIFACT/u-boot-emmc.fip := append-uboot-emmc
-  ARTIFACTS := u-boot-emmc.fip u-boot-nand.bin u-boot-ram.itb bootext.ram
+  ARTIFACTS := u-boot-emmc.fip u-boot-nand.bin u-boot-recovery.bin u-boot-ram.itb bootext.ram
   IMAGE/production.img := $$(call airoha-emmc-production)
 endef
 
@@ -52,6 +52,7 @@ define Device/Default-airoha-common
   UBOOT_RAM_LOADADDR := $(UBOOT_LOADADDR)
   UBOOT_RAM_COMPRESSION := lzma
   UBOOT_ENV_BLACKLIST := $(DEFAULT_UBOOT_ENV_BLACKLIST)
+  ARTIFACT/u-boot-recovery.bin := append-uboot-recovery
   ARTIFACT/u-boot-nand.bin := append-uboot-nand
   ARTIFACT/u-boot-ram.itb := append-uboot-ram | lzma | iowrt-uboot-fit lzma
   ARTIFACT/bootext.ram := append-bootext-ram
diff --git a/airoha/image/iopsys-image-common.mk b/airoha/image/iopsys-image-common.mk
index 91a862ecb7a007f7f7800793eb766d584258aac5..000f541fc0d139c6f63d62ee37a8c7431f2984da 100644
--- a/airoha/image/iopsys-image-common.mk
+++ b/airoha/image/iopsys-image-common.mk
@@ -95,40 +95,46 @@ define generate-uboot-nand
 
 # This is mostly generic (depends on which fiptool is used though)
 	fiptool create                                                                             \
-		$(if $(call secure-boot-check), \
-			--trusted-key-cert      $(CERT_PATH)-$(notdir $(1))/trusted_key.crt                \
-			--tb-fw-cert            $(CERT_PATH)-$(notdir $(1))/tb_fw.crt                      \
-			--soc-fw-cert           $(CERT_PATH)-$(notdir $(1))/soc_fw_content.crt             \
-			--soc-fw-key-cert       $(CERT_PATH)-$(notdir $(1))/soc_fw_key.crt                 \
-			--nt-fw-cert            $(CERT_PATH)-$(notdir $(1))/nt_fw_content.crt              \
-			--nt-fw-key-cert        $(CERT_PATH)-$(notdir $(1))/nt_fw_key.crt                  \
-		) \
+		$(if $(call secure-boot-check),                                                    \
+			--trusted-key-cert      $(CERT_PATH)-$(notdir $(1))/trusted_key.crt        \
+			--tb-fw-cert            $(CERT_PATH)-$(notdir $(1))/tb_fw.crt              \
+		    $(if $(TCSUPPORT_TPL_SUPPORT),,                                                \
+			--soc-fw-cert           $(CERT_PATH)-$(notdir $(1))/soc_fw_content.crt     \
+			--soc-fw-key-cert       $(CERT_PATH)-$(notdir $(1))/soc_fw_key.crt         \
+		    )                                                                              \
+		)                                                                                  \
 		--align 1024                                                                       \
 		--tb-fw                 $(STAGING_DIR_IMAGE)/$(TCPLATFORM)-bl2.bin                 \
-		--soc-fw                $(STAGING_DIR_IMAGE)/$(TCPLATFORM)-bl31.lzma               \
-		--nt-fw                 $(WORK_PATH)-$(notdir $(1))/u-boot-ram.lzma                \
-		$(WORK_PATH)-$(notdir $(1))/preloader.bin
-
-	fiptool info $(WORK_PATH)-$(notdir $(1))/preloader.bin
-
-# This is mostly generic
-	# create bootext.ram (binary stripped of certs)
-	cp $(WORK_PATH)-$(notdir $(1))/preloader.bin $(WORK_PATH)-$(notdir $(1))/bootext.ram
-	fiptool remove                                                                             \
-		--soc-fw-key-cert                                                                  \
-		--nt-fw-key-cert                                                                   \
-		--soc-fw-cert                                                                      \
-		--nt-fw-cert                                                                       \
-		--soc-fw                                                                           \
-		--nt-fw                                                                            \
-		--align 1024                                                                       \
 		$(WORK_PATH)-$(notdir $(1))/bootext.ram
 
+	fiptool create                                                                             \
+		$(if $(call secure-boot-check),                                                    \
+			--trusted-key-cert      $(CERT_PATH)-$(notdir $(1))/trusted_key.crt        \
+			--tb-fw-cert            $(CERT_PATH)-$(notdir $(1))/tb_fw.crt              \
+			--soc-fw-cert           $(CERT_PATH)-$(notdir $(1))/soc_fw_content.crt     \
+			--soc-fw-key-cert       $(CERT_PATH)-$(notdir $(1))/soc_fw_key.crt         \
+		    $(if $(TCSUPPORT_TPL_SUPPORT),,                                                \
+			--nt-fw-cert            $(CERT_PATH)-$(notdir $(1))/nt_fw_content.crt      \
+			--nt-fw-key-cert        $(CERT_PATH)-$(notdir $(1))/nt_fw_key.crt          \
+		    )                                                                              \
+		)                                                                                  \
+		--align 1024                                                                       \
+		--tb-fw                 $(STAGING_DIR_IMAGE)/$(TCPLATFORM)-bl2.bin                 \
+		$(if $(TCSUPPORT_TPL_SUPPORT),                                                     \
+		    --soc-fw            $(WORK_PATH)-$(notdir $(1))/u-boot-ram.lzma                \
+		,                                                                                  \
+		    --soc-fw            $(STAGING_DIR_IMAGE)/$(TCPLATFORM)-bl31.lzma               \
+		    --nt-fw             $(WORK_PATH)-$(notdir $(1))/u-boot-ram.lzma                \
+		)                                                                                  \
+		$(WORK_PATH)-$(notdir $(1))/tcboot.fip
+
+	fiptool info $(WORK_PATH)-$(notdir $(1))/tcboot.fip
+
 # This is airoha specific
 	# create nand image (tcboot.bin)
 	cp $(STAGING_DIR_IMAGE)/$(TCPLATFORM)-bl1.bin $(WORK_PATH)-$(notdir $(1))/test.bin
 	dd of=$(WORK_PATH)-$(notdir $(1))/test.bin if=/dev/null bs=1 seek=2048 count=0
-	dd of=$(WORK_PATH)-$(notdir $(1))/test.bin if=$(WORK_PATH)-$(notdir $(1))/preloader.bin bs=2048 seek=1
+	dd of=$(WORK_PATH)-$(notdir $(1))/test.bin if=$(WORK_PATH)-$(notdir $(1))/tcboot.fip bs=2048 seek=1
 	# add u-boot snapshot version string
 	cat $(STAGING_DIR_IMAGE)/$(UBOOT_TARGET)-u-boot-version.txt >> $(WORK_PATH)-$(notdir $(1))/test.bin
 	# add iopsys u-boot version id string
@@ -143,9 +149,20 @@ define generate-uboot-nand
 
 	rm -rf $(CERT_PATH)-$(notdir $(1)) $(WORK_PATH)-$(notdir $(1))
 
+# create an7581 specific bootloader image for board recovery
+# --------------------------------------------------------------
+# This bootloader go directly to command line instead of loading
+# BL31/OPTEE images to the memory. This may be needed if BL31/OPTEE
+# are bad, but properly signed.
+#
+# Note: there is no difference in behavior for en7523 case
+	cp $@-u-boot-nand.bin $@-u-boot-recovery.bin
+	echo -n recovery | dd of=$@-u-boot-recovery.bin bs=$$((0x7c000)) seek=1 conv=notrunc
+
 	@echo Saving U-Boot images for $(DEVICE_NAME)
 	cp $@-bootext.ram     $(STAGING_DIR_IMAGE)/$(UBOOT_TARGET)-$(DEVICE_NAME)-bootext.ram
 	cp $@-u-boot-nand.bin $(STAGING_DIR_IMAGE)/$(UBOOT_TARGET)-$(DEVICE_NAME)-u-boot-nand.bin
+	cp $@-u-boot-recovery.bin $(STAGING_DIR_IMAGE)/$(UBOOT_TARGET)-$(DEVICE_NAME)-u-boot-recovery.bin
 endef
 
 # Generate U-Boot eMMC image
@@ -163,6 +180,17 @@ define Build/generate-uboot-images
 	$(call generate-uboot-emmc,$@,$@-u-boot-nand.bin)
 endef
 
+define Build/prepare-atf-blobs
+	if [ $(ARCH) = aarch64 ]; then \
+		lzma d "$(STAGING_DIR_IMAGE)/$(TCPLATFORM)-bl31.lzma" $@-bl31.bin; \
+		lzma d "$(STAGING_DIR_IMAGE)/$(TCPLATFORM)-bl32_optee.lzma" $@-optee.bin; \
+	fi
+endef
+
+define Build/append-uboot-recovery
+	dd if=$(STAGING_DIR_IMAGE)/$(UBOOT_TARGET)-$(DEVICE_NAME)-u-boot-recovery.bin >> $@
+endef
+
 define Build/append-uboot-nand
 	dd if=$(STAGING_DIR_IMAGE)/$(UBOOT_TARGET)-$(DEVICE_NAME)-u-boot-nand.bin >> $@
 endef
@@ -208,6 +236,66 @@ define Build/append-ubi-image
 	rm -f $@.env1 $@.env2 $@.tmp
 endef
 
+# arg(1) is the descriprion string in form:
+#   description = "some text";
+# or
+#   /* some comment */
+# if no description is planned
+define airoha-aarch64-atf-blobs-its
+	echo -e '/ {\n\t\
+		$(1)\n\t\
+		#address-cells = <1>;\n\t\
+		images {\n\t\t\
+			atf {\n\t\t\t\
+				description = "ATF BL31 image";\n\t\t\t\
+				data = /incbin/("$@-bl31.bin");\n\t\t\t\
+				type = "firmware";\n\t\t\t\
+				arch = "arm64";\n\t\t\t\
+				os = "arm-trusted-firmware";\n\t\t\t\
+				compression = "none";\n\t\t\t\
+				load = <0x80003000>;\n\t\t\t\
+				entry = <0x80003000>;\n\t\t\t\
+				hash-1 {\n\t\t\t\t\
+					algo = "crc32";\n\t\t\t\
+				};\n\t\t\t\
+				hash-2 {\n\t\t\t\t\
+					algo = "sha1";\n\t\t\t\
+				};\n\t\t\
+			};\n\t\t\
+			tee {\n\t\t\t\
+				description = "OPTEE (ATF BL32) image";\n\t\t\t\
+				data = /incbin/("$@-optee.bin");\n\t\t\t\
+				type = "tee";\n\t\t\t\
+				arch = "arm64";\n\t\t\t\
+				os = "arm-trusted-firmware";\n\t\t\t\
+				compression = "none";\n\t\t\t\
+				load = <0x8a800000>;\n\t\t\t\
+				entry = <0x8a800000>;\n\t\t\t\
+				hash-1 {\n\t\t\t\t\
+					algo = "crc32";\n\t\t\t\
+				};\n\t\t\t\
+				hash-2 {\n\t\t\t\t\
+					algo = "sha1";\n\t\t\t\
+				};\n\t\t\
+			};\n\t\
+		};\n\t\
+		configurations {\n\t\t\
+			default = "atf_blobs";\n\t\t\
+			atf_blobs {\n\t\t\t\
+				description = "ATF blobs";\n\t\t\t\
+				firmware = "atf";\n\t\t\t\
+				loadables = "atf", "tee";\n\t\t\
+			};\n\t\
+		};\n\
+	};' >> $@.its
+endef
+
+define Build/airoha-iowrt-kernel-fit
+	$(call iowrt-kernel-fit-gen-its,$(1),$(2))
+	$(if $(findstring aarch64,$(ARCH)),$(call airoha-aarch64-atf-blobs-its,/* no description */))
+	$(call iowrt-kernel-fit-mkimage,$(1),$(2))
+endef
+
 # %(1) boardid to set, default is $(firstword $(DEVICE_DTS))
 define Build/append_emmc_production_image
 	echo "Build/append_emmc_production_image[$@]: $(1)"
@@ -220,6 +308,15 @@ define Build/append_emmc_production_image
 	$(call Build/pad-to,1K)
 	mv $@ $@.sysupgrade.itb
 	mv $@.bak $@
+# generate fit image with atf blobs to put inside production image (must fit in 2M)
+	touch $@.its
+	mv $@.its $@.its.bak
+	$(Build/prepare-atf-blobs)
+	echo '/dts-v1/;' > $@.its
+	$(call airoha-aarch64-atf-blobs-its, description = "ATF-2.10 BL31/BL32 images";)
+	mv $@.its $@.boot1.its
+	PATH=$(LINUX_DIR)/scripts/dtc:$(PATH) mkimage -E -B 0x1000 -r -f $@.boot1.its $@.boot1.fit
+	mv $@.its.bak $@.its
 # create GPT image with env1, env2, sysupgrade partitions
 #  * GPT image size will be calculated automatically (-d 0)
 #  * put Primary GPT entry table at 512K offset (-e 512K)
@@ -228,7 +325,7 @@ define Build/append_emmc_production_image
 #  * env2 partition will start at 2560K offset (just after env1)
 #  * sysupgrade partition will start at 3M offset (just after env2).
 #    ptgen uses sizes in KB, so divide sysupgrade image size to 1024
-	ptgen -o $@.img -g -d 0 -e 512K -a 100 -N env1 -p 512K@2M -N env2 -p 512K -N sysupgrade -p "$$(( $$(stat --format=%s $@.sysupgrade.itb) / 1024 ))K"
+	ptgen -o $@.img -g -d 0 -e 512K -a 100 -N env1 -p 512K@2M -N env2 -p 512K -N boot1 -p 2M -N sysupgrade -p "$$(( $$(stat --format=%s $@.sysupgrade.itb) / 1024 ))K"
 # write bootloader with 2K offset to GPT image (after PMBR and PGPT header, but before Primary GPT entry table)
 	dd bs=2K seek=1 conv=notrunc of=$@.img if=$(STAGING_DIR_IMAGE)/$(UBOOT_TARGET)-$(DEVICE_NAME)-u-boot-emmc.fip
 # generate 1-st environment (-s 0)
@@ -251,8 +348,10 @@ define Build/append_emmc_production_image
 		-O "mmc dev 0 && part size mmc 0 sysupgrade __size && read mmc "0#sysupgrade" \$${loadaddr} 0 \$${__size} && env delete __size && source \$${loadaddr}:u-boot-script && run __script_emmc_write_production && env set once true && env save"
 # write 2-nd environment with 2560K offset (env2 partition) to GPT image
 	dd bs=2560K seek=1 conv=notrunc of=$@.img if=$@.env2
-# write sysupgrade image with 3M offset (sysupgrade partition) to GPT image
-	dd bs=3M seek=1 conv=notrunc of=$@.img if=$@.sysupgrade.itb
+# write atf blob image with 3M offset (boot1 partition) to GPT image
+	dd bs=3M seek=1 conv=notrunc of=$@.img if=$@.boot1.fit
+# write sysupgrade image with 5M offset (sysupgrade partition) to GPT image
+	dd bs=5M seek=1 conv=notrunc of=$@.img if=$@.sysupgrade.itb
 # add GPT image to the current target file
 	cat $@.img >> $@
 # remove temporary files
diff --git a/airoha/image/iopsys-secure-boot.mk b/airoha/image/iopsys-secure-boot.mk
index 879a23bf5e45cffb3de17d0a68153d475a9064d0..be96ce8c33d2f2b837a7f40d7769a61f9228c9e5 100644
--- a/airoha/image/iopsys-secure-boot.mk
+++ b/airoha/image/iopsys-secure-boot.mk
@@ -52,6 +52,7 @@ define secure-boot-create-cert/Default
 		--non-trusted-world-key         $(CERT_PATH)-$(notdir $(1))/NTWkey                 \
 		--scp-fw-key                    $(CERT_PATH)-$(notdir $(1))/SCPFKey                \
 		--soc-fw-key                    $(CERT_PATH)-$(notdir $(1))/SOCFkey                \
+		--tos-fw-key                    $(CERT_PATH)-$(notdir $(1))/TFkey                  \
 		--nt-fw-key                     $(CERT_PATH)-$(notdir $(1))/NTFkey                 \
 		--tfw-nvctr 0 --ntfw-nvctr 0                                                       \
 		--trusted-key-cert              $(CERT_PATH)-$(notdir $(1))/trusted_key.crt        \
@@ -62,10 +63,13 @@ define secure-boot-create-cert/Default
 		--tb-fw-cert                    $(CERT_PATH)-$(notdir $(1))/tb_fw.crt              \
 		--soc-fw-cert                   $(CERT_PATH)-$(notdir $(1))/soc_fw_content.crt     \
 		--soc-fw-key-cert               $(CERT_PATH)-$(notdir $(1))/soc_fw_key.crt         \
+		--tos-fw-cert                   $(CERT_PATH)-$(notdir $(1))/tos_fw_content.crt     \
+		--tos-fw-key-cert               $(CERT_PATH)-$(notdir $(1))/tos_fw_key.crt         \
 		--nt-fw-cert                    $(CERT_PATH)-$(notdir $(1))/nt_fw_content.crt      \
 		--nt-fw-key-cert                $(CERT_PATH)-$(notdir $(1))/nt_fw_key.crt          \
 		--tb-fw                         $(STAGING_DIR_IMAGE)/$(TCPLATFORM)-bl2.bin         \
 		--soc-fw                        $(STAGING_DIR_IMAGE)/$(TCPLATFORM)-bl31.lzma       \
+		--tos-fw                        $(STAGING_DIR_IMAGE)/$(TCPLATFORM)-bl32_optee.lzma \
 		--nt-fw                         $(WORK_PATH)-$(notdir $(1))/u-boot-ram.lzma
 endef
 
diff --git a/airoha/image/u-boot-script b/airoha/image/u-boot-script
index 81b147bbf89ed5dc8cd726aee3e897ab2f645aa6..838a823c24e64319dd9088d5d82ab294f17191fd 100644
--- a/airoha/image/u-boot-script
+++ b/airoha/image/u-boot-script
@@ -37,14 +37,11 @@ setenv __script_emmc_write_gpt '
 	run do_report_result;
 ';
 setenv __script_emmc_clear_part '
-	test $? -eq 0 && part size mmc 0 ${part_name} part_size;
-	test $? -eq 0 && setexpr mw_size ${part_size} * 0x80;
-	test $? -eq 0 && mw.l ${loadaddr} 0 ${mw_size};
-	test $? -eq 0 && write mmc 0#${part_name} ${loadaddr} 0 ${part_size};
+	mmc erase ${part_name};
 	env set result $?;
 	echo;
 	echo -n "Clear partition ${part_name} -- ";
-	env delete part_name part_size mw_size;
+	env delete part_name;
 	run do_report_result;
 ';
 # This command by design should delete all environment variables added by