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.

f28035_flash_kernel with CSM

Other Parts Discussed in Thread: CONTROLSUITE

Are there any concerns with controlsuite's f28035_flash_kernel (or other f280xx flash kernels) and serial_flash_programmer with loading programs that have CSM enabled with a password.  Do I have to modify the f28035_flash_kernel example in order to have the csm section in the linker file along with the correct passwords??

  • Hi Fulano,

    You can program flash applications with CSM passwords. If you build your executable with the CSM passwords in Flash and then load the hex file to the kernel with the serial flash programmer, everything should work perfectly. You will need to reset the device in order to lock it.

    However, if you want to unlock the device before flashing another program, you will need to modify the hex file and flash kernel. You can do this by post-processing the hex file manually and putting the passwords in the header of the hex file. There are 16 unused bytes in the hex boot format where you can store the passwords. Then, you will need to modify the flash kernel slightly to read these passwords and write them to the CSM Key registers in RAM before loading the flash application and programming it.

    Alternatively, you can structure your flash kernel like the F2837xD flash kernel which waits on the host for a command.
    Please see: www.ti.com/sprabv4

    Best Regards,
    sal

  • Thanks Sal for your response.  I am looking at the hex file in the boot ROM format (--sci8 --ascii --boot) and I don't see the 16 bytes to store the password.  Is this because it is in ASCII format?  I'm expecting to see a long string of FFFFs but don't see anything like that.  Is the hex boot format spelled out somewhere?

  • I see now in DSP2803x_SysCtrl.c part of the f28035_flash_kernel project ... that there is a CsmUnlock() function that places the passwords into the CSM registers, I guess I can just put the passwords in there and hard code the password into the flash kernel itself.

  • Please look at Table 9 of Chapter 2 in www.ti.com/lit/sprugo0.  It shows the boot loader format.  Chapter 2 discusses the bootloaders.

    You can definitely hard code the CSM passwords into the flash kernel to unlock it.

    Best Regards,

    sal

  • Hi Sal,

    I am having trouble with hard-coded passwords in the flash kernel.

    I first had an unlocked device (all 0xFFFF passwords).

    I then programmed an application with csm passwords section, and changed the passwords (to all 0x0123).

    I recompiled a new flash kernel that has hardcoded passwords. I set the boot mode pins to SCI boot mode, it loaded the kernel fine, but then failed to load the application.

    Uint16 CsmUnlock()
    {
    volatile Uint16 temp;

    // Load the key registers with the current password. The 0xFFFF's are dummy
    // passwords. User should replace them with the correct password for the DSP.

    EALLOW;
    CsmRegs.KEY0 = 0x0123;
    CsmRegs.KEY1 = 0x0123;
    CsmRegs.KEY2 = 0x0123;
    CsmRegs.KEY3 = 0x0123;
    CsmRegs.KEY4 = 0x0123;
    CsmRegs.KEY5 = 0x0123;
    CsmRegs.KEY6 = 0x0123;
    CsmRegs.KEY7 = 0x0123;
    EDIS;

    // Perform a dummy read of the password locations
    // if they match the key values, the CSM will unlock

    temp = CsmPwl.PSWD0;
    temp = CsmPwl.PSWD1;
    temp = CsmPwl.PSWD2;
    temp = CsmPwl.PSWD3;
    temp = CsmPwl.PSWD4;
    temp = CsmPwl.PSWD5;
    temp = CsmPwl.PSWD6;
    temp = CsmPwl.PSWD7;

    // If the CSM unlocked, return succes, otherwise return
    // failure.
    if (CsmRegs.CSMSCR.bit.SECURE == 0) return STATUS_SUCCESS;
    else return STATUS_FAIL;

    }
    For some reason, this is not unlocking the device. The call to CsmUnlock() is done in CopyData() before any of the Flash is erased

    void CopyData()
    {

    struct HEADER {
    Uint16 BlockSize;
    Uint32 DestAddr;
    Uint32 ProgBuffAddr;
    } BlockHeader;

    Uint16 wordData;
    Uint16 status;
    Uint16 i,j;

    //Make sure code security is disabled
    CsmUnlock();

    EALLOW;
    Flash_CPUScaleFactor = SCALE_FACTOR;
    Flash_CallbackPtr = NULL;
    EDIS;

    status = Flash_Erase((SECTORA | SECTORB | SECTORC | SECTORD | SECTORE | SECTORF | SECTORG | SECTORH), &FlashStatus);
    if(status != STATUS_SUCCESS)
    {
    //TODO fix so that it returns a serial error and reboot device
    return ;
    }

    ......
    I believe what it happening is that Flash_Erase fails because it is not unlocked, and then CopyData() just returns;
  • Does CsmUnlock() return a success or fail?  You can run the kernel with the JTAG debugger. Just modify the serial_flash_programmer not skip the step of downloading the kernel.

    Where are you loading your kernel into?  Is it RAML0L1 0x8000 - 0x8C00 like the example?

    I actually think the CsmUnlock function may be incorrect...  You need to first read from 0x3F 7FF8 − 0x3F 7FFF, then write the passwords.

    See www.ti.com/lit/sprugl8. Section 2.3.2.  Please switch the order of the dummy reads and the Key writes.  Let me know if this works to unlock the device.

    Best Regards,

    sal

  • I am in fact loading the kernel into RAML0L1 0x8000-0x8C00, I am using the example f28035_flash_kernel unmodified as it comes in controlSUITE.

    I tried changing CsmUnlock() to do the dummy read first, then writing the passwords but that didn't work. I also tried doing an additional dummy read after (dummy read > load passwds > dummy read) and that didn't seem to work either.

    I tried turning on an LED to tell me if CsmUnlock() was returning a fail. Didn't see the LED light up. Tried to turn on LED if CsmUnlock() was returning a success, and also no LED.

    This leads me to believe that maybe the kernel is not getting loaded at all??? You mentioned modifying serial_flash_programmer so that the kernel loading is not skipped. Where does this happen? f05_DownloadImage.cpp never skips the loading of the kernel. This is the output of serial_flash_programmer:

    C2000 Serial Firmware Upgrader
    Copyright (c) 2013 Texas Instruments Incorporated. All rights reserved.

    getting comm state
    building comm DCB
    adjusting port settings

    calling f05_DownloadImage
    Downloading myapplication.txt to device...

    Kernel AutoBaud Successful
    Kernel Loaded
    Done Waiting for kernel boot...attempting autobaud
    Application AutoBaud Successful

    then it just exits.
  • To clarify, when I first loaded myapplication.txt (with passwords section set to 0x0123) to the unsecured device, serial_flash_programmer and f28035_flash_kernel (with passwords hardcoded to 0xFFFF) worked fine and successfully programmed it.  I verified CsmUnlock() was returning SUCCESS by lighting up an LED.

    It seems once I use serial_flash_programmer to try to load the modified kernel with hardcoded passwords, that CsmUnlock() never even gets called, because neither of the LEDs turn on (I have one for SUCCESS and one for FAIL).

    I also put some code to just turn on any LED in the beginning of main() of the kernel, and it never turns on.  This makes me think the kernel is never getting loaded or started.  Once the device is locked, it seems SCI boot mode doesn't allow me to load or start the kernel.


    When I set the device in SCI boot mode, does SCI boot mode care if the device is secured or not? I would imagine since the flash kernel is loaded into RAM (not secured by CSM), then it shouldn't matter.

  • You can load the kernel with JTAG and run it with JTAG, and modify the serial flash programmer to no load the kernel, just the application and have the kernel communicate with the serial flash programmer and attempt to debug it with JTAG.

    I am not very familiar with CSM on F2803x. I will reply after consulting someone.

    sal
  • I have verified that kernel is not being loaded/started once the device has been secured and is started in SCI boot mode. I have edited my last comment above).
  • It is correct procedure to write the KEY and then perform the dummy reads from flash.  It should immediately unlock if the passwords read match the Key.

    I think the problem is that you are trying to load the kernel into secure RAM.  The bootloader is communicating properly with the host, but the CPU is unable to write the kernel into RAM.  So, the kernel is never actually getting loaded into RAM.

    Try putting the kernel into a different RAM bank.  Put RAMM0 and RAMM1 in the same Page of the linker command file and use that for your kernel, at least the .text section. 

    Let me know if this works.  Using JTAG will help you debug this as well, as I mentioned above.

    sal

  • I think you're on the right track.  I moved M1 to page 0 and placed .text in M0 and .InitBoot in M1.

    However, that still leaves .ebss in L2/L3 (ECSL secured). Shared_Boot.c has CopyData() which is in ramfuncs(M0) but the variables in .ebss won't fit if we put them in M0/M1.

    I think it is mostly due to 

    Uint16 progBuf[PROG_BUFFER_LENGTH]; //PROG_BUFFER_LENGTH = 0x400

    Any ideas on how to rearrange this better?

  • Hi Fulano,

    The buffer was implemented to increase the performance of flash programming.  It is quicker to send a checksum for a chunk of data than to echo-back every byte back to the host.  

    It looks to me like we ran out of unsecure memory to put the kernel in.  I have two suggestions:

    1. Reduce the size of the memory block in both the kernel and the serial_flash_programmer and see if it fits in the unsecure RAM.  OR
    2. Eliminate the checksum and the progBuf and instead echo-back every byte that is sent to the kernel.

    In the second suggestion, you will not have a need for a large buffer or a checksum.  You can echo-back every byte from the host and the host should wait on the echo-back from the device before sending the next byte.  This is what the bootloader does.  You can see the F2837xD kernel.  It does something like this.  You will also have to modify the host code, but this should be easy because you would download the application the same was as downloading the kernel to the bootloader.

    sal

  • Fulano,

    We need to limit memory usage of the flash kernel...

    1. In Properties, Go to C2000 Compiler -> Optimization and optimize for size (0) and also increase the level to 1 for Local Optimization.
    2. In C2000 Compiler -> Advanced Options ->  Advanced Optimizations, check "Optimize for code size."
    3. Go to C2000 Linker -> Basic Options and reduce the size of the stack.  You can test what size is optimal.

    If you reduce the size of the buffer (progBuf) and reduce the size of the stack and optimize for size, you should have enough memory.  My suggestion is to reduce the buffer size (PROG_BUFFER_LENGTH) to 0x100 and reduce the stack to 0x100.  After this,  the flash kernel will fit into unsecure RAM.

    We need to modify the serial_flash_programmer to work wit the modified kernel...

    We reduced the buffer in the kernel to 0x100, 1/4 the original size. So reduce 0x800 to 0x200 in line 369 of f05_DownloadImage.cpp of the serial_flash_programmer.  Now, the kernel should send the checksum after 0x100 16-bit words and the host should expect a checksum from the device after 0x200 bytes. 

    Let me know if this works.

    sal

  • Sal, that sounds like a plan. I'll try that and post my results here tomorrow. Thank you for you quick responses and guidance, you're a great resource to this community!
  • Sal, I am happy to report that your suggestions worked!  With hard-coding the passwords into the flash kernel, allocating the kernel to unsecured memory sections, compiler optimizations for size, reduction of the stack size, and changing PROG_BUFFER_LENGTH size, and modifications to serial_flash_programmer, I can now successfully load code to a CSM-locked device.  This is a huge help to us, as we could not use C2Prog for our serial programming.

    If you are curious as to why, C2Prog loads its bootloader at 9600 baud, then loads the application at 115200 baud.  We are using a serial Bluetooth module that is only programmable to one specific baud speed.  With a wired serial interface there is no issue, but using the bluetooth module was critical for our application.

    Thanks again, you've been an incredible help!!!

  • Fulano,

    Great to hear! I am happy we got this working and you found the serial_flash_programmer useful.

    sal
  • Sal,
    When I want to load an application via SCI Boot, and use hex2000 to generate the application in this format (--sci8 --ascii --boot), should I have any concern that the passwords could somehow be extracted from this ascii-hex file?
  • Fulano,

    Yes.  The passwords can be extracted from the hex file.  

    I believe your solution has the passwords hard-coded in the kernel and not the application.  In this case, the passwords can be extracted from the hex of the kernel.  

    You can add some decryption to your kernel and send an encrypted password to the kernel in the application hex file, but your kernel would have to have a key for the decryption.  Either way there has to be some secret information known in the kernel.

    I was just thinking a little, and I suppose you can "hide" some passwords in Flash of the device and send that address in the hex file, or hard-code reads from those addresses and write the data to the DCSM KEY.  This way you are not actually sending the password and it cannot be extracted from the hex file.  But, if someone has access to the device, they can hook up JTAG and read the passwords from those "hidden" addresses.

    Best Regards,

    sal

  • Sal,
    Thanks for your thoughts on this. I have been experimenting with embedding the flash kernel into my application. I have taken f28035_flash_kernel and integrated with my application and located everything in secure RAM. I also modified serial_flash_programmer to skip the kernel loading and assume it's already there and waiting for the application.

    In order to get the device into an SCI boot mode without having to play with GPIO pins, I just send a special command over SCI while the device is running, and (after disabling interrupts and resetting SCI regs to reset state) it calls InitBoot which then calls SCI_Boot. Just as in the Boot ROM or f28035_flash_kernel. I originally tried just branching to the BootROM SCI_Boot but after looking at the source, I see it would not be compatible with how serial_flash_programmer communicates the application file. So I used the InitBoot and SCI_Boot from the f28035_flash_kernel and embedded it into my application. Now, the passwords are only stored in the Passwords.asm file and since everything resides in secure memory, I don't have to worry about unlocking CSM while I'm doing an upgrade.

    As far as security, my concern is having the passwords in the hex file (which can be solved by how you mentioned, hiding in a specific address in Flash). You mentioned if you have JTAG you could read from those addresses? I thought if the CSM is active, it would not allow this to happen since Flash is secure memory.

    So even if we hide the passwords somewhere in Flash, we avoid having the passwords in the hex file. But what about the rest of the code in the hex?

    There is also some risk with the "special command" to get it into this upgrade state. But even if they figured out this special command, all it could do is get the device into this upgrade state and the CSM is still locked. I guess the bigger risk is in sending the ascii-hex file to a customer. I guess the most secure way would be to encrypt the content of each block in the ascii-hex file and have the kernel decrypt it as the data comes in. I could have serial_flash_programmer do the decrypting, but then one could still sniff the SCI comm and just read the decrypted application.
  • I figured the passwords would be in unsecure memory because you need them to unlock the device. If you are already running from secure memory then you are right and do not have to worry about unlocking the CSM while doing an upgrade.

    You can have the serial flash programmer decrypt the hex file and send it to the kernel or send the encrypted hex file to the kernel and have the kernel decrypt the contents of the file.

    sal