diff --git a/ci/fvp-base-ts-ftpm.yml b/ci/fvp-base-ts-ftpm.yml
new file mode 100644
index 00000000..87539a7e
--- /dev/null
+++ b/ci/fvp-base-ts-ftpm.yml
@@ -0,0 +1,27 @@
+# yaml-language-server: $schema=https://raw.githubusercontent.com/siemens/kas/master/kas/schema-kas.json
+
+header:
+  version: 14
+  includes:
+    - ci/fvp-base-ts.yml
+    - ci/meta-secure-core.yml
+
+repos:
+  meta-secure-core:
+    layers:
+      meta-tpm2:
+
+local_conf_header:
+  remove_secureboot: |
+    BBMASK += "efi-secure-boot"
+
+  ftpm_sp_test: |
+    # Include tpm2 related packages
+    IMAGE_INSTALL:append = " tpm2-tools-tests tpm2-abrmd tpm2-tss"
+    # Use systemd as the init system, which is required for the tpm2 self-tests
+    INIT_MANAGER = "systemd"
+    IMAGE_INSTALL:append = " systemd util-linux"
+
+  ts_ftpm_sp: |
+    MACHINE_FEATURES:append = " ts-ftpm"
+    RUN_TPM2_TESTS = "1"
diff --git a/meta-arm/conf/layer.conf b/meta-arm/conf/layer.conf
index 956a67c7..9d18c7c4 100644
--- a/meta-arm/conf/layer.conf
+++ b/meta-arm/conf/layer.conf
@@ -24,3 +24,8 @@ WARN_QA:append:layer-meta-arm = " patch-status"
 
 # Define base directory for meta-arm
 META_ARM_LAYER_DIR := "${LAYERDIR}"
+
+BBFILES_DYNAMIC += " \
+    tpm2:${LAYERDIR}/dynamic-layers/meta-tpm2/*/*/*.bb \
+    tpm2:${LAYERDIR}/dynamic-layers/meta-tpm2/*/*/*.bbappend \
+"
diff --git a/meta-arm/dynamic-layers/meta-tpm2/recipes-tpm/tpm2-tools/files/0001-Remove-simulator-and-abrmd-startup.patch b/meta-arm/dynamic-layers/meta-tpm2/recipes-tpm/tpm2-tools/files/0001-Remove-simulator-and-abrmd-startup.patch
new file mode 100644
index 00000000..b38fb9a7
--- /dev/null
+++ b/meta-arm/dynamic-layers/meta-tpm2/recipes-tpm/tpm2-tools/files/0001-Remove-simulator-and-abrmd-startup.patch
@@ -0,0 +1,55 @@
+From b5269bd5380a8a7b202a27a558d98468e14ac642 Mon Sep 17 00:00:00 2001
+From: Imre Kis <imre.kis@arm.com>
+Date: Wed, 25 Sep 2024 15:44:08 +0200
+Subject: [PATCH] Remove simulator and abrmd startup
+
+Upstream-Status: Inappropriate
+Signed-off-by: Imre Kis <imre.kis@arm.com>
+---
+ test/integration/helpers.sh | 31 -------------------------------
+ 1 file changed, 31 deletions(-)
+
+diff --git a/test/integration/helpers.sh b/test/integration/helpers.sh
+index 4c861567..bb339078 100644
+--- a/test/integration/helpers.sh
++++ b/test/integration/helpers.sh
+@@ -396,37 +396,6 @@ function start_up() {
+
+     run_startup=true
+
+-    if [ -n "$TPM2_SIM" ]; then
+-        # Start the simulator
+-        echo "Starting the simulator"
+-        start_sim || exit 1
+-        echo "Started the simulator"
+-    else
+-        echo "not starting simulator"
+-    fi
+-
+-    if [ -n "$TPM2_ABRMD" ]; then
+-        echo "Starting tpm2-abrmd"
+-        # Start tpm2-abrmd
+-        start_abrmd || exit 1
+-        run_startup=false
+-    else
+-        echo "not starting abrmd"
+-    fi
+-
+-    echo "TPM2TOOLS_TEST_TCTI=$TPM2TOOLS_TEST_TCTI"
+-    if [ -z "$TPM2TOOLS_TEST_TCTI" ]; then
+-        echo "TPM2TOOLS_TEST_TCTI not set, attempting to figure out default"
+-        if [ -z "$tpm2tools_tcti" ]; then
+-            echo "The simulator not abrmd was started, cannot determine a TCTI for tools."
+-            exit 1;
+-        fi
+-        TPM2TOOLS_TEST_TCTI="$tpm2tools_tcti"
+-    fi
+-
+-    echo "export TPM2TOOLS_TCTI=\"$TPM2TOOLS_TEST_TCTI\""
+-    export TPM2TOOLS_TCTI="$TPM2TOOLS_TEST_TCTI"
+-
+     recreate_info
+
+     echo "run_startup: $run_startup"
+--
+2.34.1
\ No newline at end of file
diff --git a/meta-arm/dynamic-layers/meta-tpm2/recipes-tpm/tpm2-tools/files/0003-abrmd_policysigned_sh-fix-error-clear-lockout.patch b/meta-arm/dynamic-layers/meta-tpm2/recipes-tpm/tpm2-tools/files/0003-abrmd_policysigned_sh-fix-error-clear-lockout.patch
new file mode 100644
index 00000000..f6e1e9dd
--- /dev/null
+++ b/meta-arm/dynamic-layers/meta-tpm2/recipes-tpm/tpm2-tools/files/0003-abrmd_policysigned_sh-fix-error-clear-lockout.patch
@@ -0,0 +1,56 @@
+From be44c3231fe40c99ba55abe4f8ae6a7bfed92bde Mon Sep 17 00:00:00 2001
+From: Gabor Toth <gabor.toth2@arm.com>
+Date: Thu, 30 Jan 2025 15:11:48 +0100
+Subject: [PATCH] abrmd_policysigned.sh: fix error, clear lockout
+
+Fix cleanup function to be able to return success.
+Clear lockout state at the end of the test.
+
+Upstream-Status: Pending
+Signed-off-by: Gabor Toth <gabor.toth2@arm.com>
+---
+ test/integration/tests/abrmd_policysigned.sh | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/test/integration/tests/abrmd_policysigned.sh b/test/integration/tests/abrmd_policysigned.sh
+index 2a0b3994..d062f033 100644
+--- a/test/integration/tests/abrmd_policysigned.sh
++++ b/test/integration/tests/abrmd_policysigned.sh
+@@ -3,15 +3,19 @@
+ source helpers.sh
+ 
+ cleanup() {
+-    rm -f session.ctx secret.dat private.pem public.pem signature.dat \
++    rm -f secret.dat private.pem public.pem signature.dat \
+     signing_key.ctx policy.signed prim.ctx sealing_key.priv sealing_key.pub \
+     unsealed.dat qual.dat to_sign.bin
+ 
+-    tpm2 flushcontext $session_ctx 2>/dev/null || true
++    tpm2 flushcontext session.ctx 2>/dev/null || true
++
++    rm -f session.ctx
+ 
+     if [ "${1}" != "no-shutdown" ]; then
+         shut_down
+     fi
++
++    return 0
+ }
+ trap cleanup EXIT
+ 
+@@ -129,10 +133,12 @@ openssl dgst -sha256 -sign signing_key.priv -out signature.dat to_sign.bin
+ tpm2 policysigned -S session.ctx -g sha256 -s signature.dat -f ecdsa \
+ -c signing_key_pub.ctx --cphash cphash.bin
+ ### Authorize
+-tpm2 dictionarylockout -c session:session.ctx
++tpm2 dictionarylockout -c -p session:session.ctx
+ 
+ tpm2 flushcontext session.ctx
+ rm -f signing_key.priv signing_key.pub signing_key_pub.ctx cphash.bin \
+       session.ctx policy.signed to_sign.bin signature.dat
++
++tpm2 clear -c l "password"
+ 
+ exit 0
+-- 
+2.34.1
diff --git a/meta-arm/dynamic-layers/meta-tpm2/recipes-tpm/tpm2-tools/files/tpm2-test b/meta-arm/dynamic-layers/meta-tpm2/recipes-tpm/tpm2-tools/files/tpm2-test
new file mode 100644
index 00000000..da70121e
--- /dev/null
+++ b/meta-arm/dynamic-layers/meta-tpm2/recipes-tpm/tpm2-tools/files/tpm2-test
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+# Some tests refers to these variables, which is not set at runtime
+export srcdir=/usr/share/tpm2-tools
+export abs_srcdir=$srcdir
+
+cd /usr/share/tpm2-tools/test/integration
+dbus-run-session bash tests/$1.sh
diff --git a/meta-arm/dynamic-layers/meta-tpm2/recipes-tpm/tpm2-tools/files/tpm2-test-all b/meta-arm/dynamic-layers/meta-tpm2/recipes-tpm/tpm2-tools/files/tpm2-test-all
new file mode 100644
index 00000000..f5e3baf5
--- /dev/null
+++ b/meta-arm/dynamic-layers/meta-tpm2/recipes-tpm/tpm2-tools/files/tpm2-test-all
@@ -0,0 +1,123 @@
+#!/bin/bash
+
+tests=(
+    abrmd_extended-sessions
+    abrmd_nvundefinespecial
+    abrmd_policyauthorizenv
+    abrmd_policyauthorize
+    abrmd_policyauthvalue
+    abrmd_policycommandcode
+    abrmd_policycountertimer
+    abrmd_policycphash
+    abrmd_policyduplicationselect
+    abrmd_policynamehash
+    abrmd_policynv
+    abrmd_policynvwritten
+    abrmd_policyor
+    abrmd_policypassword
+    abrmd_policypcr
+    abrmd_policysecret
+    abrmd_policysigned
+    abrmd_policytemplate
+    abrmd_policyticket
+    activecredential
+    attestation
+    certifycreation
+    certify
+    changeauth
+    changeeps
+    changepps
+    checkquote
+    clearcontrol
+    clear
+    clockrateadjust
+    commandaudit
+    createak
+    createpolicy
+    createprimary
+    create
+    dictionarylockout
+    duplicate
+    ecc
+    encryptdecrypt
+    evictcontrol
+    flushcontext
+    getcap
+    getpolicydigest
+    getrandom
+    gettestresult
+    gettime
+    hash
+    hierarchycontrol
+    hmac
+    import
+    import_tpm
+    incrementalselftest
+    load
+    makecredential
+    nvcertify
+    nvinc
+    output_formats
+    pcrevent
+    pcrextend
+    pcrlist
+    pcrreset
+    pcrs_format
+    print
+    readclock
+    readpublic
+    rsadecrypt
+    rsaencrypt
+    selftest
+    sessionconfig
+    setprimarypolicy
+    startup
+    stirrandom
+    symlink
+    testparms
+    unseal
+    verifysignature
+    X509certutil
+)
+
+failed_tests=()
+
+# Failing tests:
+# createek
+# eventlog
+# getekcertificate
+# loadexternal
+# quote
+# rc_decode
+# send
+# send-tcti-cmd
+# sign
+# toggle_options
+# nv
+# pcrallocate
+# sessionaudit
+# setclock
+
+for test in "${tests[@]}"; do
+    echo '*******************************************************************************'
+    echo "${test} Starting..."
+    
+    if tpm2-test "${test}"
+    then
+        echo "${test} OK"
+    else
+        echo "${test} FAILED"
+        failed_tests+=("${test}")
+    fi
+done
+echo '*******************************************************************************'
+
+if [ ${#failed_tests[@]} -ne 0 ]
+then
+    echo "ERROR: the following tpm2 tests failed:"
+    printf '\t%s\n' "${failed_tests[@]}"
+fi
+
+echo '*******************************************************************************'
+
+(exit ${#failed_tests[@]})
diff --git a/meta-arm/dynamic-layers/meta-tpm2/recipes-tpm/tpm2-tools/tpm2-tools_5.7.bbappend b/meta-arm/dynamic-layers/meta-tpm2/recipes-tpm/tpm2-tools/tpm2-tools_5.7.bbappend
new file mode 100644
index 00000000..092e8134
--- /dev/null
+++ b/meta-arm/dynamic-layers/meta-tpm2/recipes-tpm/tpm2-tools/tpm2-tools_5.7.bbappend
@@ -0,0 +1,27 @@
+# Include tpm2-tools dependencies. diffutils is needed for cmp tool, coreutils needed for dd and head (GNU instead of the busybox variant)
+# need perl-misc for shasum
+
+PACKAGES:prepend = "${PN}-tests "
+
+RDEPENDS:${PN}-tests += " ${PN} xxd bash bash-completion dbus python3-yamllint python3 perl-misc coreutils diffutils curl"
+
+FILESEXTRAPATHS:prepend := "${THISDIR}/files:"
+
+SRC_URI:append = " \
+            file://0001-Remove-simulator-and-abrmd-startup.patch \
+            file://0003-abrmd_policysigned_sh-fix-error-clear-lockout.patch \
+            file://tpm2-test     \
+            file://tpm2-test-all \
+        "
+
+do_install:append() {
+    install -d ${D}${datadir}/tpm2-tools/test
+    install -m 0755 ${UNPACKDIR}/tpm2-test ${D}${bindir}
+    install -m 0755 ${UNPACKDIR}/tpm2-test-all ${D}${bindir}
+
+    cd ${S}/test
+    find . -type d -exec install -d -m 0755 ${D}${datadir}/tpm2-tools/test/{} \;
+    find . -type f -exec install -m 0755 {} ${D}${datadir}/tpm2-tools/test/{} \;
+}
+
+FILES:${PN}-tests += "${datadir}/tpm2-tools/test ${bindir}/tpm2-test ${bindir}/tpm2-test-all"
diff --git a/meta-arm/lib/oeqa/runtime/cases/trusted_services.py b/meta-arm/lib/oeqa/runtime/cases/trusted_services.py
index 54423999..6981bb98 100644
--- a/meta-arm/lib/oeqa/runtime/cases/trusted_services.py
+++ b/meta-arm/lib/oeqa/runtime/cases/trusted_services.py
@@ -4,6 +4,7 @@ from oeqa.runtime.case import OERuntimeTestCase
 from oeqa.core.decorator.depends import OETestDepends
 from oeqa.runtime.decorator.package import OEHasPackage
 from oeqa.core.decorator.data import skipIfNotInDataVar
+from oeqa.core.decorator.oetimeout import OETimeout
 
 class TrustedServicesTest(OERuntimeTestCase):
 
@@ -102,3 +103,11 @@ class TrustedServicesTest(OERuntimeTestCase):
            'ts-se-proxy' not in self.tc.td['MACHINE_FEATURES']:
             self.skipTest('Crypto SP is not deployed in the system.')
         self.run_test_tool('ts-service-test -g Crypto')
+
+    @OEHasPackage(['tpm2-tools-tests'])
+    @skipIfNotInDataVar('MACHINE_FEATURES', 'ts-ftpm', 'fTPM SP is not included')
+    @skipIfNotInDataVar('RUN_TPM2_TESTS', '1', 'Automated test is disabled (RUN_TPM2_TESTS is undefined).')
+    @OETestDepends(['ssh.SSHTest.test_ssh'])
+    @OETimeout(4*60*60)
+    def test_16_tpm2_test_all(self):
+        self.run_test_tool('tpm2-test-all')
