diff --git a/common/bootm_os.c b/common/bootm_os.c
index 5e6b1777e48ab04ff75776ef73d05f20a30e10a9..b84a8e26d2ce04000478c2cbccdf82e3b060b75c 100644
--- a/common/bootm_os.c
+++ b/common/bootm_os.c
@@ -11,6 +11,7 @@
 #include <linux/libfdt.h>
 #include <malloc.h>
 #include <vxworks.h>
+#include <tee/optee.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -433,6 +434,34 @@ static int do_bootm_openrtos(int flag, int argc, char * const argv[],
 }
 #endif
 
+#ifdef CONFIG_BOOTM_OPTEE
+static int do_bootm_tee(int flag, int argc, char * const argv[],
+			bootm_headers_t *images)
+{
+	int ret;
+
+	/* Verify OS type */
+	if (images->os.os != IH_OS_TEE) {
+		return 1;
+	};
+
+	/* Validate OPTEE header */
+	ret = optee_verify_bootm_image(images->os.image_start,
+				       images->os.load,
+				       images->os.image_len);
+	if (ret)
+		return ret;
+
+	/* Locate FDT etc */
+	ret = bootm_find_images(flag, argc, argv);
+	if (ret)
+		return ret;
+
+	/* From here we can run the regular linux boot path */
+	return do_bootm_linux(flag, argc, argv, images);
+}
+#endif
+
 static boot_os_fn *boot_os[] = {
 	[IH_OS_U_BOOT] = do_bootm_standalone,
 #ifdef CONFIG_BOOTM_LINUX
@@ -466,6 +495,9 @@ static boot_os_fn *boot_os[] = {
 #ifdef CONFIG_BOOTM_OPENRTOS
 	[IH_OS_OPENRTOS] = do_bootm_openrtos,
 #endif
+#ifdef CONFIG_BOOTM_OPTEE
+	[IH_OS_TEE] = do_bootm_tee,
+#endif
 };
 
 /* Allow for arch specific config before we boot */
diff --git a/lib/optee/Kconfig b/lib/optee/Kconfig
index cc73ec3fb56b6593621c4091d77fca007d2d5062..1e5ab45c3d77c84f42d6607c7dff78d6886754d4 100644
--- a/lib/optee/Kconfig
+++ b/lib/optee/Kconfig
@@ -28,3 +28,12 @@ config OPTEE_TZDRAM_BASE
 	help
 	  The base address of pre-allocated Trust Zone DRAM for
 	  the OPTEE runtime.
+
+config BOOTM_OPTEE
+	bool "Support OPTEE bootm command"
+	select BOOTM_LINUX
+	default n
+	help
+	  Select this command to enable chain-loading of a Linux kernel
+	  via an OPTEE firmware.
+	  The bootflow is BootROM -> u-boot -> OPTEE -> Linux in this case.