cancel
Showing results for 
Search instead for 
Did you mean: 

Boot Failure on STM32MP157C: Secure Mode Issues (smc execution failure)

VivekB
Associate III

Hi, 

I am working with an STM32MP157CAA Rev.Z on a custom STM32CubeMX board running OpenSTLinux 6.6 (Yocto Scarthgap MPU v24.11.06). I have successfully integrated and bootstrapped various boot components.

I first got the TF-A and OPTEE to boot the system and now it is also able to bring up the uboot. However, while trying to boot up the uboot gets into an "secure mode execution errors". I am not sure where it is coming from? We have hash-and-boot-options_hash-and-boot-options.bin flashed into the OTP area. Is that something could potentially lead to this type of issue? 

BL2 (TF-A) Loading

  • BL2 (TF-A) executes as expected and starts platform initialization.

  • The board is in trusted mode, and secure boot appears to be enabled.

  • Below are the logs confirming BL2 is executing:

 

NOTICE:  CPU: STM32MP157CAA Rev.Z
NOTICE:  Model: STMicroelectronics custom STM32CubeMX board - openstlinux-6.6-yocto-scarthgap-mpu-v24.11.06
NOTICE:  BL2: v2.10-stm32mp1-r1.0(release)
NOTICE:  BL2: Built : 14:58:08, Mar  4 2025
NOTICE:  TRUSTED_BOARD_BOOT support enabled

 

Image Loading Sequence

  • BL2 successfully attempts to load various images, including:

    • TF-A (tf-a-stm32mp157c-ccb-mx_Signed.stm32)
    • OP-TEE (tos-fw.bin, tos-fw-extra1.bin)
    • SCP firmware (scp-fw.bin)
    • NT firmware (nt-fw.bin)

 

ERROR:   BL2: Preparing to load image id 1 (tf-a-stm32mp157c-ccb-mx_Signed.stm32)
ERROR:   BL2: Loading image id 1 (tf-a-stm32mp157c-ccb-mx_Signed.stm32)
ERROR:   BL2: Calling load_auth_image() for image id 1 with base 0x2ffff000
ERROR:   ROTPK is not deployed on platform. Skipping ROTPK verification.

 

"ROTPK is not deployed", looks like Root of Trust Public Key (ROTPK) verification is being skipped. I am not sure whether this is expected behaviour in my setup or what is causing this.

OP-TEE Boot & Peripheral Initialization

  • OP-TEE initialises successfully and maps secure memory regions.

  • Secure components like TZC400, STPMIC, and STM32MP1 clocks are initialized.

  • However, multiple SMC call failures appear:

 

stm32_smc: Failed to exec svc=82001003 op=1 in secure mode (err = -1)

 

U-Boot Execution

  • U-Boot executes successfully but reports errors related to secure mode calls:

 

stm32_smc: Failed to exec svc=82001003 op=1 in secure mode (err = -1)

 

EFI system partition detection fails, which is unexpected:

 

No EFI system partition
Failed to persist EFI variables

 

At this point, the system does not proceed further due to the OP-TEE watchdog panic.

 

E/TC:0   Panic 'Watchdog' at core/drivers/stm32_iwdg.c:228 <stm32_iwdg_it_handler>

 

I have also attached the full boot_log.txt in the attachment for reference. 

The below is the details of my platform: 

Hardware & Software Details

  • CPU: STM32MP157CAA Rev.Z
  • Board: STMicroelectronics custom STM32CubeMX board
  • Software Version: OpenSTLinux 6.6 Yocto Scarthgap MPU (v24.11.06)
  • TF-A Version: v2.10-stm32mp1-r1.0 (Release)
  • U-Boot Version: 2023.10-stm32mp-r1
  • OP-TEE Version: REL_0.8.7-8-g79647115eb
  • Boot Mode: Trusted Mode with Secure Boot Enabled

I need some help to understand what are the areas I need to investigate to resolve this issue. 

Many Thanks

Best Regards, 

Vivek

24 REPLIES 24
 

I am having the same issue with SVC ID: 0x82001003.  

The error happens in stm32mp_bsec_read_shadow().  So I am assuming that the error is higher up and it never should have called this function in the first place.  CONFIG_OPTEE=y appears in u-boot  build/.config

 

 

Tom-IowaSoft
Associate II

After adding some debug statements (*TRN*) to code it appears that in my case...

There is no Tee struct in the the efuse@5c005000 device/driver. This results in it calling stm32mp_bsec_read_shadow() instead of OP-TEE in stm32mp_bsec_read() defined in bsec.c 

The Tee struct is private data from the efuse device and is retrieve via dev_get_priv(dev)

*TRN* in stm32mp_bsec_read(); udevice="efuse@5c005000"
*TRN* CONFIG_OPTEE=y, ,priv->tee=0x00000000 in stm32mp_bsec_read()

*TRN* in stm32mp_bsec_read_shadow()

stm32_smc: Failed to exec svc=82001003 op=1 in secure mode (err = -1)

So does this mean that efuse@5c005000 needs to be moved down into etzpc in stm32mp151.dtsi ?

.

 

GatienC
ST Employee

Hello,

Thank you for the details. If there's priv->tee=0x00000000, then the op-tee driver may not be probed. Can you check that the OP-TEE node is present in your board.dtb using a tool like "fdtdump" please? The OP-TEE node is define in xx-scmi.dtsi device tree file because of legacy. This file should be included by the board, you can see what has been done on the STM32 reference boards.

I'm currently investigating if there are issue with the generation tools.

 

I hope this helps,

Gatien

Yes, I was able to determine this late last night.  I had to add the following to the device tree root node. The strange thing is that it solved the issue for all but the first three times that error occurs just after u-boot displays it's title line. The first three times it continued to show priv->tee == 0x00000000.  We did not use any generation tool. We started from the Odyssey device tree since our board uses the Odyssey SOM from Seeed Studio.

    firmware {
        optee {
            compatible = "linaro,optee-tz";
            method = "smc";
        };
    };
 

I suggest to add: bootph-some-ram; property to the OP-TEE node, suggesting that it should be probed before relocation. Maybe that'll solve you issue. You can refer to arch/arm/dts/stm32mp15-scmi-u-boot.dtsi.

 

I hope this solves your issue,

Gatien

 

 

Yes, the remaining priv-tee == 0x00000000 were solved by adding bootph items to the device tree.

Thank you. Now on to the remaining errors. Hopefully this was of use to VivekB too.

Thanks, @GatienC  and @Tom-IowaSoft . I had been caught up with other errors, but I noticed that despite those, my board was making progress before ultimately failing to initialize the MMC.

During boot, the system attempts to initialize mmc0 and mmc1 by calling mmc_init(). While mmc_init() succeeds for mmc0, it fails for mmc1. However, when I manually run mmc dev 1 followed by mmc rescan, mmc1 initializes successfully.

Based on this, I decided to implement a retry mechanism to replicate the manual rescan automatically, and I succeeded in getting mmc_init() to pass for both mmc0 and mmc1. However, I then encountered a new issue—while initialization succeeds, the system fails to determine the correct device size, leading to another failure.

Below is the original error I started with:

VBDBG: mmc_init: 2995 - Entering mmc_init()
VBDBG: mmc_init: 3003 - Timer started: 12330
VBDBG: mmc_init: 3006 - Calling mmc_start_init()
VBDBG: mmc_init: 3008 - mmc_start_init() returned 0
VBDBG: mmc_init: 3012 - Calling mmc_complete_init()
VBDBG: mmc_init: 3014 - mmc_complete_init() returned 0
VBDBG: mmc_init: 3021 - MMC initialized successfully, time elapsed: 28
VBDBG: mmc_init: 2995 - Entering mmc_init()
VBDBG: mmc_init: 3003 - Timer started: 12517
VBDBG: mmc_init: 3006 - Calling mmc_start_init()
VBDBG: mmc_init: 3008 - mmc_start_init() returned -110
VBDBG: mmc_init: 3018 - MMC initialization failed: -110, time elapsed: 28

And here is the retry mechanism I implemented:

VBDBG: mmc_init: 3007 - Entering mmc_init() for STM32 SD/MMC
VBDBG: mmc_init: 3017 - Timer started: 36837
VBDBG: mmc_init: 3021 - Attempting MMC initialization for STM32 SD/MMC, try 1
VBDBG:mmc_start_init: 2916 - Entering mmc_start_init()
VBDBG:mmc_start_init: 2920 - Host capabilities set: 0x3000400f
VBDBG:mmc_start_init: 2942 - Calling mmc_deferred_probe()
VBDBG:mmc_start_init: 2948 - mmc_getcd() returned 1, no_card=0
VBDBG:mmc_start_init: 2967 - Calling mmc_get_op_cond()
VBDBG:mmc_start_init: 2969 - mmc_get_op_cond() returned -110
VBDBG:mmc_start_init: 2976 - Exiting mmc_start_init(), err=-110
VBDBG: mmc_init: 3026 - mmc_start_init() returned -110
VBDBG: mmc_init: 3030 - MMC STM32 SD/MMC failed to start, forcing rescan...
mmc1 = mmc@58007000 not found in device tree!
VBDBG:mmc_start_init: 2916 - Entering mmc_start_init()
VBDBG:mmc_start_init: 2920 - Host capabilities set: 0x7000400f
VBDBG:mmc_start_init: 2942 - Calling mmc_deferred_probe()
VBDBG:mmc_start_init: 2948 - mmc_getcd() returned 1, no_card=0
VBDBG:mmc_start_init: 2967 - Calling mmc_get_op_cond()
VBDBG:mmc_start_init: 2969 - mmc_get_op_cond() returned 0
VBDBG:mmc_start_init: 2973 - MMC initialization in progress
VBDBG:mmc_start_init: 2976 - Exiting mmc_start_init(), err=0
VBDBG: mmc_init: 3046 - mmc_start_init() after rescan returned 0
VBDBG: mmc_init: 3051 - Calling mmc_complete_init() for STM32 SD/MMC
VBDBG: mmc_init: 3054 - mmc_complete_init() returned -110
VBDBG: mmc_init: 3065 - Retrying MMC initialization for STM32 SD/MMC in 100ms
VBDBG: mmc_init: 3021 - Attempting MMC initialization for STM32 SD/MMC, try 2
VBDBG:mmc_start_init: 2916 - Entering mmc_start_init()
VBDBG:mmc_start_init: 2920 - Host capabilities set: 0x7000400f
VBDBG:mmc_start_init: 2942 - Calling mmc_deferred_probe()
VBDBG:mmc_start_init: 2948 - mmc_getcd() returned 1, no_card=0
VBDBG:mmc_start_init: 2967 - Calling mmc_get_op_cond()
VBDBG:mmc_start_init: 2969 - mmc_get_op_cond() returned 0
VBDBG:mmc_start_init: 2973 - MMC initialization in progress
VBDBG:mmc_start_init: 2976 - Exiting mmc_start_init(), err=0
VBDBG: mmc_init: 3026 - mmc_start_init() returned 0
VBDBG: mmc_init: 3051 - Calling mmc_complete_init() for STM32 SD/MMC
VBDBG: mmc_init: 3054 - mmc_complete_init() returned 0
VBDBG: mmc_init: 3059 - MMC STM32 SD/MMC initialized successfully, time elapsed: 215
MMC: block number 0x1 exceeds max(0x0)
MMC: block number 0x1 exceeds max(0x0)
MMC: block number 0x44 exceeds max(0x0)
Disk mmc@48004000.blk not ready
No EFI system partition
No EFI system partition
Failed to persist EFI variables
Missing RNG device for EFI_RNG_PROTOCOL

I have now started looking into the power settings in the Device Tree (.dts) file. Initially, I assumed the STM32CubeMX-generated DTS would be sufficient with minor tweaks, but it seems I need to examine it further.

In the meantime, I appreciate your update, @Tom-IowaSoft, and both your suggestions, @Tom-IowaSoft and @GatienC. I will test these approaches and share my findings.

Many thanks,
Best Regards,
Vivek

I am also having mmc errors. I get this and just started looking into it
       Card did not respond to voltage select! : -110

Ah! We seem to be on the same page then. Look for the function in the uboot:

mmc_init()

 That's the function possibly timing out on 

mmc_get_op_cond()

Try dropping to the uboot prompt and try the following just to double chekc if this is the same issue as mine: 

mmc dev 0
mmc dev 1
mmc list
mmc info
mmc part
mmc rescan

This might give you the boot device list at uboot prompt: 

printenv boot_targets

Below is the retry mechanism I have done in the uboot code, it succeeds with this but then fails to retrieve the size of the bocks etc. Have a look maybe similar.

From 2e902d53bcb4540376293030cf2aa2032642695b Mon Sep 17 00:00:00 2001
From: Vivek Bhadra <vivek.bhadra@indra.co.uk>
Date: Tue, 18 Mar 2025 18:16:05 +0000
Subject: [PATCH] Implementing retry mechanism in mmc_init.

---
 drivers/mmc/mmc.c | 187 +++++++++++++++++++++++++++++++---------------
 1 file changed, 127 insertions(+), 60 deletions(-)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 31cfda28858..6f530a377f1 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -2910,59 +2910,71 @@ retry:
 
 int mmc_start_init(struct mmc *mmc)
 {
-	bool no_card;
-	int err = 0;
+    bool no_card;
+    int err = 0;
+
+    printk(KERN_EMERG "VBDBG:%s: %d - Entering mmc_start_init()\n", __func__, __LINE__);
+
+    /* All hosts support at least 1-bit bus width and legacy mode */
+    mmc->host_caps = mmc->cfg->host_caps | MMC_CAP(MMC_LEGACY) | MMC_MODE_1BIT;
+    printk(KERN_EMERG "VBDBG:%s: %d - Host capabilities set: 0x%x\n", __func__, __LINE__, mmc->host_caps);
+
+    if (IS_ENABLED(CONFIG_MMC_SPEED_MODE_SET)) {
+        if (mmc->user_speed_mode != MMC_MODES_END) {
+            int i;
+            printk(KERN_EMERG "VBDBG:%s: %d - User speed mode set to %d\n", __func__, __LINE__, mmc->user_speed_mode);
+
+            if (mmc->host_caps & MMC_CAP(mmc->user_speed_mode)) {
+                /* Remove all existing speed capabilities */
+                for (i = MMC_LEGACY; i < MMC_MODES_END; i++) {
+                    mmc->host_caps &= ~MMC_CAP(i);
+                }
+                mmc->host_caps |= (MMC_CAP(mmc->user_speed_mode) | MMC_CAP(MMC_LEGACY) | MMC_MODE_1BIT);
+                printk(KERN_EMERG "VBDBG:%s: %d - Host capabilities updated: 0x%x\n", __func__, __LINE__, mmc->host_caps);
+            } else {
+                printk(KERN_EMERG "VBDBG:%s: %d - Requested bus mode not supported!\n", __func__, __LINE__);
+                return -EINVAL;
+            }
+        }
+    }
 
-	/*
-	 * all hosts are capable of 1 bit bus-width and able to use the legacy
-	 * timings.
-	 */
-	mmc->host_caps = mmc->cfg->host_caps | MMC_CAP(MMC_LEGACY) |
-			 MMC_MODE_1BIT;
-
-	if (IS_ENABLED(CONFIG_MMC_SPEED_MODE_SET)) {
-		if (mmc->user_speed_mode != MMC_MODES_END) {
-			int i;
-			/* set host caps */
-			if (mmc->host_caps & MMC_CAP(mmc->user_speed_mode)) {
-				/* Remove all existing speed capabilities */
-				for (i = MMC_LEGACY; i < MMC_MODES_END; i++)
-					mmc->host_caps &= ~MMC_CAP(i);
-				mmc->host_caps |= (MMC_CAP(mmc->user_speed_mode)
-						   | MMC_CAP(MMC_LEGACY) |
-						   MMC_MODE_1BIT);
-			} else {
-				pr_err("bus_mode requested is not supported\n");
-				return -EINVAL;
-			}
-		}
-	}
 #if CONFIG_IS_ENABLED(DM_MMC)
-	mmc_deferred_probe(mmc);
+    printk(KERN_EMERG "VBDBG:%s: %d - Calling mmc_deferred_probe()\n", __func__, __LINE__);
+    mmc_deferred_probe(mmc);
 #endif
+
 #if !defined(CONFIG_MMC_BROKEN_CD)
-	no_card = mmc_getcd(mmc) == 0;
+    no_card = mmc_getcd(mmc) == 0;
+    printk(KERN_EMERG "VBDBG:%s: %d - mmc_getcd() returned %d, no_card=%d\n", __func__, __LINE__, mmc_getcd(mmc), no_card);
 #else
-	no_card = 0;
+    no_card = 0;
 #endif
+
 #if !CONFIG_IS_ENABLED(DM_MMC)
-	/* we pretend there's no card when init is NULL */
-	no_card = no_card || (mmc->cfg->ops->init == NULL);
+    /* If init function is NULL, pretend there's no card */
+    no_card = no_card || (mmc->cfg->ops->init == NULL);
+    printk(KERN_EMERG "VBDBG:%s: %d - Checking init function, no_card=%d\n", __func__, __LINE__, no_card);
 #endif
-	if (no_card) {
-		mmc->has_init = 0;
+
+    if (no_card) {
+        mmc->has_init = 0;
 #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
-		pr_err("MMC: no card present\n");
+        printk(KERN_EMERG "VBDBG:%s: %d - MMC: No card present\n", __func__, __LINE__);
 #endif
-		return -ENOMEDIUM;
-	}
+        return -ENOMEDIUM;
+    }
 
-	err = mmc_get_op_cond(mmc, false);
+    printk(KERN_EMERG "VBDBG:%s: %d - Calling mmc_get_op_cond()\n", __func__, __LINE__);
+    err = mmc_get_op_cond(mmc, false);
+    printk(KERN_EMERG "VBDBG:%s: %d - mmc_get_op_cond() returned %d\n", __func__, __LINE__, err);
 
-	if (!err)
-		mmc->init_in_progress = 1;
+    if (!err) {
+        mmc->init_in_progress = 1;
+        printk(KERN_EMERG "VBDBG:%s: %d - MMC initialization in progress\n", __func__, __LINE__);
+    }
 
-	return err;
+    printk(KERN_EMERG "VBDBG:%s: %d - Exiting mmc_start_init(), err=%d\n", __func__, __LINE__, err);
+    return err;
 }
 
 static int mmc_complete_init(struct mmc *mmc)
@@ -2984,27 +2996,82 @@ static int mmc_complete_init(struct mmc *mmc)
 
 int mmc_init(struct mmc *mmc)
 {
-	int err = 0;
-	__maybe_unused ulong start;
-#if CONFIG_IS_ENABLED(DM_MMC)
-	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(mmc->dev);
-
-	upriv->mmc = mmc;
-#endif
-	if (mmc->has_init)
-		return 0;
-
-	start = get_timer(0);
-
-	if (!mmc->init_in_progress)
-		err = mmc_start_init(mmc);
+    int err = 0, retries = 3;
+    __maybe_unused ulong start;
 
-	if (!err)
-		err = mmc_complete_init(mmc);
-	if (err)
-		pr_info("%s: %d, time %lu\n", __func__, err, get_timer(start));
-
-	return err;
+#if CONFIG_IS_ENABLED(DM_MMC)
+    struct mmc_uclass_priv *upriv = dev_get_uclass_priv(mmc->dev);
+    upriv->mmc = mmc;
+#endif
+
+    printk(KERN_EMERG "VBDBG: %s: %d - Entering mmc_init() for %s\n",
+           __func__, __LINE__, mmc->cfg->name);
+
+    if (mmc->has_init) {
+        printk(KERN_EMERG "VBDBG: %s: %d - MMC %s already initialized\n",
+               __func__, __LINE__, mmc->cfg->name);
+        return 0;
+    }
+
+    start = get_timer(0);
+    printk(KERN_EMERG "VBDBG: %s: %d - Timer started: %lu\n",
+           __func__, __LINE__, start);
+
+    while (retries--) {
+        printk(KERN_EMERG "VBDBG: %s: %d - Attempting MMC initialization for %s, try %d\n",
+               __func__, __LINE__, mmc->cfg->name, 3 - retries);
+
+        /* Normal Initialization */
+        err = mmc_start_init(mmc);
+        printk(KERN_EMERG "VBDBG: %s: %d - mmc_start_init() returned %d\n",
+               __func__, __LINE__, err);
+
+        if (err) {
+            printk(KERN_EMERG "VBDBG: %s: %d - MMC %s failed to start, forcing rescan...\n",
+                   __func__, __LINE__, mmc->cfg->name);
+
+            /* Mimic `mmc rescan` behavior */
+            mmc->has_init = 0;
+            mmc->init_in_progress = 0;
+
+            /* Re-fetch the MMC device dynamically */
+            mmc = find_mmc_device(mmc_get_env_dev());
+            if (!mmc) {
+                printk(KERN_EMERG "VBDBG: %s: %d - Failed to re-fetch MMC device!\n",
+                       __func__, __LINE__);
+                return -ENODEV;
+            }
+
+            err = mmc_start_init(mmc);
+            printk(KERN_EMERG "VBDBG: %s: %d - mmc_start_init() after rescan returned %d\n",
+                   __func__, __LINE__, err);
+        }
+
+        if (!err) {
+            printk(KERN_EMERG "VBDBG: %s: %d - Calling mmc_complete_init() for %s\n",
+                   __func__, __LINE__, mmc->cfg->name);
+            err = mmc_complete_init(mmc);
+            printk(KERN_EMERG "VBDBG: %s: %d - mmc_complete_init() returned %d\n",
+                   __func__, __LINE__, err);
+        }
+
+        if (!err) {
+            printk(KERN_EMERG "VBDBG: %s: %d - MMC %s initialized successfully, time elapsed: %lu\n",
+                   __func__, __LINE__, mmc->cfg->name, get_timer(start));
+            return 0;
+        }
+
+        if (retries) {
+            printk(KERN_EMERG "VBDBG: %s: %d - Retrying MMC initialization for %s in 100ms\n",
+                   __func__, __LINE__, mmc->cfg->name);
+            mdelay(100);
+        }
+    }
+
+    printk(KERN_EMERG "VBDBG: %s: %d - MMC %s initialization failed after retries: %d\n",
+           __func__, __LINE__, mmc->cfg->name, err);
+
+    return err;
 }
 
 #if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \
-- 
2.34.1

BTW which uboot release you are using if I may ask? I am using v2023.10-stm32mp-r1. Not sure if this is too advanced and not stable and if I should use a slightly older stanble release rather. Also, if you kindly let me know you tf-a and the optee releases as well. Many thanks, BR Vivek