Request for Guidance and Documentation on ERASEPROTECT/APPROTECT/SECUREAPPROTECT

Hi,

We've created an application for the nRF9160 non secure image with TF-M and are looking to add in ERASEPROTECT/APPROTECT/SECUREAPPROTECT functionality. From reading the Production Programming document I can see that when enabling ERASEPROTECT, APPROTECT, and SECUREAPPROTECT, the only way to recover the device is "if the installed firmware and the debugger both write the same non-zero 32-bit KEY value to ERASPROTECT.DISABLE (0x01C)"

My understanding is that since we already have a application that we want to build for non secure (for example, if it was the Blinky sample built for the nrf9160dk_nrf9160_ns with TF-M), we would need to create a separate secure image in order to write the non-zero 32-bit key value to ERASEPROTECT.DISABLE.

My questions are:

  1. How can we create a separate secure image with our nonsecure application? As I understand, the secure image should run first before handing over control of the execution to the nonsecure application. What would be the best way to add an additional secure image to something like the nonsecure Blinky sample? Would this be a child image?
  2. Is there any examples of how to interact with the ERASEPROTECT, APPROTECT, and SECUREAPPROTECT settings from the application side? I unfortunately don't have much experience working directly with various registers on the nRF9160 and would be happy to get any help possible, especially with regards to what needs to be provisioned to interact with the registers and if there is a getting started guide for tasks like this. I want to create a script that upon boot up of the nRF9160, the program: 
    1. Checks if any of the ERASEPROTECT, APPROTECT, and SECUREAPPROTECT functionalities are not enabled. If any of these are not enabled, the program will enable the protection and perform a reset of the device. On the next boot up, all three of the protections should be enabled.
    2. If ERASEPROTECT, APPROTECT, and SECUREAPPROTECT are all enabled, it will write a 32-bit key to ERASPROTECT.DISABLE. This way, if we need to recover the device, we can use the SWD to write in the 32-bit key to trigger an erase all
    3. Finally, hands over execution to our nonsecure program
  3. Our current application uses MCUBOOT and supports OTA. Would ERASEPROTECT affect the application's ability to download new application updates and boot up with the new updates?

I've found some previous posts which seem to be quite helpful, however I'm still unsure of how I would need to go about integrating it into an existing nonsecure application. 
This post seems fairly helpful in talking about how to create a non-ns script to remove erase protect. However, I'm having a bit of difficulty following/finding the documentation on modifying/reading contents for items like NRF_NVMC and NRF_UICR through the application, and what the particular bits like (NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos) being set indicate. 

Thank you in advance!

Parents
  • Hi

    We have a GitHub script that should work for disabling eraseprotect that Sigurd links to in this ticket. Here he also links to the device protection Application note that can be usefult for additional information. Other than that we don't have a specific sample that does this I'm afraid.

    Best regards,

    Simon

  • Hi everyone,

    I read through this Q&A and also this one and copied the same question from there, I wanted to test the working of ERASEPROTECT and disable it using the Jlink script shared in the discussions, but I am neither able to disable erase protection using the script nor nrfjprog --recover 


    /*
     * Copyright (c) 2012-2014 Wind River Systems, Inc.
     *
     * SPDX-License-Identifier: Apache-2.0
     */
    
    #include <zephyr.h>
    
    void main(void)
    {
            const uint32_t key = 0xDEADBEEF;
    
            NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen;
    
            while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
            NRF_UICR->APPROTECT = 0x00000000;
    
            while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
            NRF_UICR->ERASEPROTECT = 0x00000000;
    
            while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
            NRF_UICR->SECUREAPPROTECT = 0x00000000;
    
            while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
            NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
    
            while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
            if (NRF_UICR_S->ERASEPROTECT != UICR_ERASEPROTECT_PALL_Unprotected)
            {
                    NRF_CTRL_AP_PERI_S->ERASEPROTECT.LOCK = (uint32_t)0x00000001;
            }
    
            while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
            if (NRF_UICR_S->ERASEPROTECT != UICR_ERASEPROTECT_PALL_Unprotected)
            {
                NRF_CTRL_AP_PERI_S->ERASEPROTECT.DISABLE = key;
            }
    
            printk("Before Write Key.\n");
            printk("ERASEPROTECT     Addr    0x%p\n", &NRF_CTRL_AP_PERI_S->ERASEPROTECT.LOCK);
            printk("ERASEPROTECT          0x%X\n",  NRF_UICR->ERASEPROTECT);
            printk("ERASEPROTECT.LOCK    0x%X\n",   NRF_CTRL_AP_PERI_S->ERASEPROTECT.LOCK);
            printk("ERASEPROTECT.DISABLE 0x%X\n",   NRF_CTRL_AP_PERI_S->ERASEPROTECT.DISABLE);
            uint32_t count = 0;
    
            k_msleep(1000);
    
            while (count < 10)
            {
                    k_msleep(1000);
                    printk("Count:: %u\r\n", count++);
            }
    
    }


    output:

    *** Booting Zephyr OS build zephyr-v2.3.0-22164-gb121d671c44c  ***                                                                     
    Before Write Key.                                                                                                                      
    ERASEPROTECT     Addr    0x0x50006500                                                                                                  
    ERASEPROTECT          0x0                                                                                                              
    ERASEPROTECT.LOCK    0x1                                                                                                               
    ERASEPROTECT.DISABLE 0x0                                                                                                               
    Count:: 0                                                                                                                              
    Count:: 1                                                                                                                              
    Count:: 2                                                                                                                              
    Count:: 3                                                                                                                              
    Count:: 4                                                                                                                              
    Count:: 5                                                                                                                              
    Count:: 6                                                                                                                              
    Count:: 7                                                                                                                              
    Count:: 8                                                                                                                              
    Count:: 9


    jlink script:

    USB 960093400
    SWDSelect
    SWDWriteDP 1 0x50000000  
    SWDWriteDP 2 0x04000010
    SWDWriteAP 3 0xDEADBEEF
    
    sleep 10000
    SWDWriteDP 1 0x50000000
    SWDWriteDP 2 0x04000000
    SWDWriteAP 0 0x00000001
    SWDReadAP 0
    SWDReadAP 0
    sleep 5000
    SWDWriteAP 0 0x00000000
    SWDReadAP 0
    SWDReadAP 0
    sleep 1000
    
    exit


    Help needed.

    Thanks,
    Dinesh Kumar K

  • The problem is likely with the code setting both ERASEPROTECT.LOCK and ERASEPROTECT.DISABLE. These can't both be set. If you read the documentation on ERASEPROTECT.LOCK, you will see that it prevents ERASEPROTECT.DISABLE from being set until next boot. You cannot set them both in sequence like this. Notice how in the output ERASEPROTECT.DISABLE never actually get set to 0xDEADBEEF, it just stays at 0x0 because it was previously locked.

            while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
            if (NRF_UICR_S->ERASEPROTECT != UICR_ERASEPROTECT_PALL_Unprotected)
            {
                    NRF_CTRL_AP_PERI_S->ERASEPROTECT.LOCK = (uint32_t)0x00000001;
            }
    
            while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
            if (NRF_UICR_S->ERASEPROTECT != UICR_ERASEPROTECT_PALL_Unprotected)
            {
                NRF_CTRL_AP_PERI_S->ERASEPROTECT.DISABLE = key;
            }

    I stated in my original post that ERASEPROTECT.LOCK could optionally be set if ERASEPROTECT.DISABLE is not to be set on bootup.

    If serial recovery is not activated at boot, you can optionally prevent ERASEPROTECT.DISABLE from being written to until next reboot by setting NRF_CTRL_AP_PERI_S->ERASEPROTECT.LOCK = (uint32_t)0x00000001

    Try just removing these lines and it should properly set ERASEPROTECT.DISABLE

            while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
            if (NRF_UICR_S->ERASEPROTECT != UICR_ERASEPROTECT_PALL_Unprotected)
            {
                    NRF_CTRL_AP_PERI_S->ERASEPROTECT.LOCK = (uint32_t)0x00000001;
            }

    Unfortunately, the nRF9160 you flashed with your previous code cannot be recovered now, you'll need to get a new board. Also, the command nrfjprog --recover can't be used to disable ERASEPROTECT since there is no way to supply it the key. Your script looks to be correct, and that is the only way to properly disable ERASEPROTECT and perform and ERASEALL.

  • Thanks   for the reply, Understood your comments, 

    since I am not afford to brick another device

    just need a reconfirmation for below steps.

    1. flash this sample code.

    void main(void)
    {
    	const uint32_t key = 0xDEADBEEF;
    
    	NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen;
    
    	while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
    
    	NRF_CTRL_AP_PERI_S->ERASEPROTECT.DISABLE = key;
    
    	printk("ERASEPROTECT         0x%X\n", NRF_UICR->ERASEPROTECT);
    	printk("ERASEPROTECT.LOCK    0x%X\n", NRF_CTRL_AP_PERI_S->ERASEPROTECT.LOCK);
    	printk("ERASEPROTECT.DISABLE 0x%X\n", NRF_CTRL_AP_PERI_S->ERASEPROTECT.DISABLE);
    }


    2. cmd line values to set protections and reboot the device should enable erase protect with disabling
    key value of 0xDEADBEEF  

     

    # Enable APPROTECT
    nrfjprog --family nRF91 --memwr 0x00FF8000 --val 0
    # Enable SECUREAPPROTECT
    nrfjprog --family nRF91 --memwr 0x00FF802C --val 0
    # Enable ERASEPROTECT
    nrfjprog --family nRF91 --memwr 0x00FF8030 --val 0



    3. JLink script to unlock eraseprotect.

    USB 960093400
    SWDSelect
    SWDWriteDP 1 0x50000000
    SWDWriteDP 2 0x04000010
    SWDWriteAP 3 0xDEADBEEF
    
    sleep 10000
    SWDWriteDP 2 0x04000000
    SWDWriteAP 1 0x00000001
    SWDReadAP 1
    SWDReadAP 1
    sleep 5000
    SWDWriteAP 1 0x00000000
    SWDReadAP 1
    SWDReadAP 1
    sleep 1000
    
    exit

  • Hi Dinesh,

    I just wanted to give you a bit of a recommendation while you do your testing for now. If you can't afford to brick a couple of devices while developing, I recommend doing the ERASEPROTECT development separately from using the APPROTECT and SECUREAPPROTECT for now. This way, if you are unable to get the ERASEPROTECT.disable to work, you can always use use 

    nrfjprog --family nRF91 --recover

    to recover the device and erase all of the firmware. When APPROTECT and SECUREAPPROTECT are enabled, I haven't been able to use the recover command. 

    Once you've finished with developing your solution and can consistently disable ERASEPROTECT by supplying the erase protect key, you could return to also using the APPROTECT and SECUREAPPROTECT functionalities.

    I recommend changing your second step to 

    # Enable ERASEPROTECT
    nrfjprog --family nRF91 --memwr 0x00FF8030 --val 0

    for the meantime until your ERASEPROTECT disable solution works smoothly.

Reply
  • Hi Dinesh,

    I just wanted to give you a bit of a recommendation while you do your testing for now. If you can't afford to brick a couple of devices while developing, I recommend doing the ERASEPROTECT development separately from using the APPROTECT and SECUREAPPROTECT for now. This way, if you are unable to get the ERASEPROTECT.disable to work, you can always use use 

    nrfjprog --family nRF91 --recover

    to recover the device and erase all of the firmware. When APPROTECT and SECUREAPPROTECT are enabled, I haven't been able to use the recover command. 

    Once you've finished with developing your solution and can consistently disable ERASEPROTECT by supplying the erase protect key, you could return to also using the APPROTECT and SECUREAPPROTECT functionalities.

    I recommend changing your second step to 

    # Enable ERASEPROTECT
    nrfjprog --family nRF91 --memwr 0x00FF8030 --val 0

    for the meantime until your ERASEPROTECT disable solution works smoothly.

Children
No Data
Related