This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CSM (Code Security) and Bootloader

Other Parts Discussed in Thread: F28M36P63C2

Dear e2e,

I am attempting to add code security to an F28M36 MCU project that has been working well for several months.

Basically I have a Bootloader that resides in M3 flash sector N. Flash sectors M-A are used for the Main application. The bootloader will copy a new main application from an SD Card into RAM and then burn it into Flash sectors M-A when requested.

When I change dcsm_z1_sec_values.asm to have a password other than FF... (11... for example). The bootloader continues to run, but it hangs up during the flash procedure. The has been very difficult to debug.

I have tried to use secure memory for everything to avoid problems. 

My .cmd file is attached. Thank you for your help. 

/*
// NOTE: IMA copied most of this file from the flash programming example project
//
//###########################################################################
// FILE:    F28M36H63C2_m3.cmd
// TITLE:   Linker Command File for F28M36H63C2 projects that run from FLASH
//          Keep in mind that C0 and C1 are protected by the code security module.
//          What this means is in most cases you will want to move to
//          another memory map file which has more memory defined.
//###########################################################################
// $TI Release: F28M36x Support Library v201 $
// $Release Date: Fri Jun  7 10:37:02 CDT 2013 $
//###########################################################################
*/

//--retain=g_pfnVectors

/* The following command line options are set as part of the CCS project.    */
/* If you are building using the command line, or for some reason want to    */
/* define them here, you can uncomment and modify these lines as needed.     */
/* If you are using CCS for building, it is probably better to make any such */
/* modifications in your CCS project and leave this file alone.              */
/*                                                                           */
/* --heap_size=0                                                             */
/* --stack_size=256                                                          */
/* --library=rtsv7M3_T_le_eabi.lib                                           */


/* The following options allow the user to program Z1 and Z2 DCSM security   */
/* values, include CSM PSWD, ECSL PSWD, GRABSECT, GRABRAM, and FLASH EXEONLY */
/* The driverlib/dcsm_z1_secvalues.s and driverlib/dcsm_z2_secvalues.s files */
/* must be included in the Flash project for the below 2 lines to take       */
/* effect.                                                                   */
--retain=dcsm_z1_secvalues.obj(.z1secvalues,.z1_csm_rsvd)
//--retain=dcsm_z2_secvalues.obj(.z2secvalues,.z2_csm_rsvd)

--retain=BL_REVISION.obj(.blrev)

/* System memory map */

MEMORY
{
    /* Flash Block 0, Sector 0 Z1 CSM */
    CSM_ECSL_Z1     : origin = 0x00200000, length = 0x0024
    CSM_RSVD_Z1     : origin = 0x00200024, length = 0x000C
    //CSM_RSVD_OTHER : origin = 0x00200050, length = 0x01AF //Found at TRM pg. 550, but not verified
    
    /* Flash Block 0, Sector 0 */
    RESETISR (RX)   	: origin = 0x00200030, length = 0x0008   /* Reset ISR is mapped to boot to Flash location */
    BL_INTVECS (RX)    	: origin = 0x00200038, length = 0x0258
    BL_FLASH (RX)		: origin = 0x00200290, length = 0x7D60    // The Bootloader resides here - never touch this block (N)

    BL_REVISION     : origin = 0x00207FF0, length = 0x0004    //4 bytes used for the bootloader revision number
                                                              //8 empty bytes in the middle
    BL_RSVD         : origin = 0x00207FFC, length = 0x0004    //4 bytes reserved for resolution reduction mode

    APP_RESETISR (RX)	: origin = 0x00208000, length = 0x0008	// Entry point into the application
    APP_INTVECS (RX)	: origin = 0x00208008, length = 0x0258	// Interrupt Vectors for the application
    APP_FLASH (RX)		: origin = 0x00208260, length = 0xF7BA0 // The Application resides here

    /* Flash Block 0, Sector 13 Z2 CSM*/
    CSM_RSVD_OTHER2 : origin = 0x002FFE00, length = 0x01D0 	//Note found at TRM pg. 550 (set to 0x00)
    CSM_RSVD_Z2     : origin = 0x002FFFD0, length = 0x000C
    CSM_ECSL_Z2     : origin = 0x002FFFDC, length = 0x0024

    /*	ACTUAL FLASH PAGES (KEEP FOR REFERENCE):
    FLASH_N (RX)    : origin = 0x00201258, length = 0x6DA8   // For storing code in Flash to copy to RAM at runtime
    FLASH_M (RX)    : origin = 0x00208000, length = 0x8000
    FLASH_L (RX)    : origin = 0x00210000, length = 0x8000
    FLASH_K (RX)    : origin = 0x00218000, length = 0x8000
    FLASH_J (RX)    : origin = 0x00220000, length = 0x20000
    FLASH_I (RX)    : origin = 0x00240000, length = 0x20000
    FLASH_H (RX)    : origin = 0x00260000, length = 0x20000
    FLASH_G (RX)    : origin = 0x00280000, length = 0x20000
    FLASH_F (RX)    : origin = 0x002A0000, length = 0x20000
    FLASH_E (RX)    : origin = 0x002C0000, length = 0x20000
    FLASH_D (RX)    : origin = 0x002E0000, length = 0x8000
    FLASH_C (RX)    : origin = 0x002E8000, length = 0x8000
    FLASH_B (RX)    : origin = 0x002F0000, length = 0x8000
    FLASH_A (RX)    : origin = 0x002F8000, length = 0x7FD0
    */
    
    /* RAM */
    C0 (RWX)        : origin = 0x20000000, length = 0x2000
    C1 (RWX)        : origin = 0x20002000, length = 0x2000
    BOOT_RSVD (RX)  : origin = 0x20004000, length = 0x0FF8
    C2 (RWX)        : origin = 0x200051B0, length = 0x0E50
    C3 (RWX)        : origin = 0x20006000, length = 0x2000

    // USED TO STORE NEW BINARY IMAGE FOR FLASHING C28
    SHARED_RAM		: origin = 0x20008000, length = 0x10000

    /* SHARED RAM (KEEP FOR REFERENCE):
    S0 (RWX)        : origin = 0x20008000, length = 0x2000
    S1 (RWX)        : origin = 0x2000A000, length = 0x2000
    S2 (RWX)        : origin = 0x2000C000, length = 0x2000
    S3 (RWX)        : origin = 0x2000E000, length = 0x2000
    S4 (RWX)        : origin = 0x20010000, length = 0x2000
    S5 (RWX)        : origin = 0x20012000, length = 0x2000
    S6 (RWX)        : origin = 0x20014000, length = 0x2000
    S7 (RWX)        : origin = 0x20016000, length = 0x2000
    */
    
    //USED TO STORE NEW BINARY IMAGE FOR FLASHING M3
    RAM_HIGH (RWX)	: origin = 0x20018000, length = 0x18000

    /* ACTUAL RAM PAGES (KEEP FOR REFERENCE):
    C4  (RWX)        : origin = 0x20018000, length = 0x2000
    C5  (RWX)        : origin = 0x2001A000, length = 0x2000
    C6  (RWX)        : origin = 0x2001C000, length = 0x2000
    C7  (RWX)        : origin = 0x2001E000, length = 0x2000
    C8  (RWX)        : origin = 0x20020000, length = 0x2000
    C9  (RWX)        : origin = 0x20022000, length = 0x2000
    C10 (RWX)        : origin = 0x20024000, length = 0x2000
    C11 (RWX)        : origin = 0x20026000, length = 0x2000
    C12 (RWX)        : origin = 0x20028000, length = 0x2000
    C13 (RWX)        : origin = 0x2002A000, length = 0x2000
    C14 (RWX)        : origin = 0x2002C000, length = 0x2000
    C15 (RWX)        : origin = 0x2002E000, length = 0x2000
    */
    
    CTOMRAM (RX)    : origin = 0x2007F000, length = 0x0800
    MTOCRAM (RWX)   : origin = 0x2007F800, length = 0x0800
}

/* Section allocation in memory */

SECTIONS
{
	.resetisr:  > RESETISR
    .intvecs:   > BL_INTVECS
    .text   :   > BL_FLASH
    .const  :   > BL_FLASH
    .cinit  :   > BL_FLASH
    .pinit  :   > BL_FLASH

    .vtable :   >  C0
    .data   :   >  C0
    .bss    :   >  C1
    .sysmem :   >  C0
    .stack  :   >  C0
    
    .z1secvalues  :   >  CSM_ECSL_Z1
    .z1_csm_rsvd  :   >  CSM_RSVD_Z1
//    .z2secvalues  :   >  CSM_ECSL_Z2
//    .z2_csm_rsvd  :   >  CSM_RSVD_Z2

    .blrev : > BL_REVISION

    m3rambuffer		:	>>	RAM_HIGH
    c28rambuffer	:	>>  SHARED_RAM

     GROUP
     {
       ramfuncs
       {
         -l F021_API_CortexM3_LE.lib
       }
     }                       LOAD = BL_FLASH,
                             RUN = C0,
                             LOAD_START(RamfuncsLoadStart),
                             LOAD_SIZE(RamfuncsLoadSize),
                             LOAD_END(RamfuncsLoadEnd),
                             RUN_START(RamfuncsRunStart),
                             RUN_SIZE(RamfuncsRunSize),
                             RUN_END(RamfuncsRunEnd),
                             PAGE = 0

    GROUP : > MTOCRAM
    {
        PUTBUFFER  
        PUTWRITEIDX
        GETREADIDX  
    }

    GROUP : > CTOMRAM 
    {
        GETBUFFER : TYPE = DSECT
        GETWRITEIDX : TYPE = DSECT
        PUTREADIDX : TYPE = DSECT
    }
}

__STACK_TOP = __stack + 256;

Isaac

  • Isaac,

    So it sounds like the since the bootloader is in sector N it is unsecure, but it is trying to program code into a secure memory.  For this to work the device must be unlocked.  The other option is to move the flash programming code to a secure location in the device and then execute it from there.

    BR,

  • Thanks for your response, Trey.

    Yes, the bootloader is in sector N, which is controlled by CSM zone 1. The main app is in Sectors M-A (but doesn't actually go all the way down to A yet). 

    I secured only zone 1 and assigned RAM C0/C1 and Flash sectors N-B to it. SO, I believe that my bootloader and main application only use secure memory, except for Sector N if the application ever gets big enough to use it.

    I did discover this morning that the bootloader fails to erase sector A even though it is in secure memory and sector A is unsecure.

    I'm still trying to debug and find where the flash operation fails.

    Isaac

  • On further debugging, it appears as though the erase operation is failing on the other sectors as well. I do not get an error when I issue:

    oReturnCheck = Fapi_issueAsyncCommandWithAddress( Fapi_EraseSector, (uint32 *)SectorAddress[sector] );

    but the error occurs when I do a blank check:

    oReturnCheck = Fapi_doBlankCheck( (uint32 *)SectorAddress[sector], SectorLength[sector], &oFlashStatusWord);

  • Isaac,

    Interesting... Thanks for the additional information.  I'm going to ping one of our flash experts to see if he can shed some light on this.

    BR,

  • Isaac,

    A sector may not get erased for any of the following 4 reasons.  Please check if your application for these possible issues.

    1) Executing Flash API functions from Flash instead of RAM. 

    2) Modifying or removing the content of Fapi_setupBankSectorEnable() function in Fapi_UserDefinedFunctions.c file.

    3) MWRALLOW is not properly initialized to disable protection for Flash controller registers.

    4) Sector that is being erased is secured and the Flash erase function is being executed from an unsecured RAM or secured RAM of another zone.

    In your case, as you mentioned that the application is working fine until you added security, I feel that #4 above is the reason for erase failure.  Fapi_issueAsyncCommandWithAddress() function does not give an error because it does not check whether the sector is secured or not.  As you did, blank check has to be executed to know whether the Flash is erased or not.

    Please check to make sure that Flash API is being executed from Zone 1 RAM when you try to erase sectors B to N which are in Zone 1.

    May be the application has to do the password match flow for Zone 2 to unlock it (even though passwords are not programmed) before erasing Sector A.  I will ask our security expert to take a look at this post.

    Thanks and regards,

    Vamsi

  • Since I don't actually use sector A, I removed the step that attempted to erase it.

    I have attached my dcsm_z1_sec_values.asm file where you can see that I have assigned sectors B-N and ram C0 and C1 to zone 1.

    As you can see from my .cmd file attached in an earlier post, I run all flash API operations from RAM C0. In fact I only use RAM C0 and C1 just to make sure that everything is in secure RAM.

    I've done a little more digging and discovered that the error I get from BlankCheck is 500 which is a generic error. When I checked the FMSTAT flags I found that CSTAT and EV were set.

    Next I attempted to only erase sector M and this was successful. I repeated for L and K and they both failed.

    0842.dcsm_z1_secvalues.asm

    Thank you for your help,

    Isaac

  • It turns out that sector M was somehow previously erased, which makes more sense.

  • I have not found a solution to this problem, but a potential work-around is this:

    DCSMUnlockZone1CSM (&Zone1KEY);
    FlashGainPump();
    SetupF021FlashAPI();
    err = UpdateM3Firmware(m3_HEX_filename);
    FlashLeavePump();
    DCSMSecureZone1();

    But I don't want to do this because it requires embedding the password in my application which is not very secure!

  • Hi again,

    I have created a simple program to demonstrate the problem. This program runs on the ControlCard and is similar to the flash programming example in MWare, except that I created it by stripping all the extras out of my own bootloader application.

    If you load the program without CSM, LED D1 will become solid ON to indicate that Flash was successfully erased and programmed. If you turn CSM on by changing the passwords in dcsm_z1_sec_values.asm, the LED (D1) will blink to indicate that it failed during a flash operation. It will fail on erase if something is already in Flash and fail on program if flash was not previously programmed.

    To test this, remember to disconnect from the Debugger.

    Again, I assign all flash (except sector A) and RAM to CSM zone 1. I do all flash operations from secure memory. I think this should work.

    Thank you for your help,

    Isaac

    1234.Bootloader-CSM.zip

  • Hi Isaac,

    Thanks for sending the sample code to reproduce the issue. After running your code, I found that there is step missing in this which was causing the issue. As you know we have dual zone security on M3 side and to prevent the corruption of flash operation from one zone by other zone, there is a semaphore mechanism implemented using SECZONEREQUEST register (please refer TRM for the definition of the register bits). While doing the flash operation from any secure zone, user must grab this semaphore from that secure zone. 

    Please add following line of code before "FlashInit()" function call to resolve this issue.

    *(int *)0x400FA160 = 0xC12F59A1;

    In TRM the definition of this semaphore (SEM bit field) is little bit confusing which we'll correct it.

    Hope this resolve the issue you are facing.

    Regards,

    Vivek Singh

     

  • Thank you, Vivek, it seems to work now.