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.

Using the C6748 secure kernel in DSP/BIOS

Other Parts Discussed in Thread: OMAP-L138

Hi experts,

I am currently trying to integrate the secure kernel into a DSP/BIOS based application running on the C6748, but I am receiving linking errors (see attached file)

4762.dsp_bios_secure_kernel_linker_error.txt

I have read on the secure boot wiki that I need to include the following line in the TCF script:

bios.GBL.ENABLE_SK = true;

but that I also need some C wrapper APIs from my local distributor. I have already received some secure booting examples from TI on a previous occasion, but I they were all non-DSP/BIOS based. From the examples I have, the only files I could find that seem to be applicable are:

- sk_basic.h

- sk_load.h

- sk_cwrap.asm

Can someone please advise?

Thanks in advance!

  • Hi,

    Looks like you are linking with the correct biosSK library.

    I would throw the sk_cwrap.asm into your project build to see if the linking errors go away.

    Judah

  • Hi Judah,

    That was the first thing I tried, which did not work.

    In sk_cwrap.asm, I noticed the following code:

    syscall _SK_registerSCWP,	SK_SYSCALL_REGSCWP
    syscall _SK_allocSC,		        SK_SYSCALL_ALLOCSC
    syscall _SK_switchNonSec,	SK_SYSCALL_SWITCHNONSEC
    syscall _SK_setUserKey,		SK_SYSCALL_SETUSERKEY
    syscall _SK_setJTAGControl,	SK_SYSCALL_SETJTAGENABLE
    syscall _SK_getSecKey,		SK_SYSCALL_GETSECKEY
    syscall _SK_decryptMod,           SK_SYSCALL_DECRYPTMOD

    The symbols that the linker is not finding have the same naming convention:

    _SK_cacheL1DChangeSize
    _SK_cacheL1PChangeSize
    _SK_cacheL2ChangeSize
    _SK_registerOSHWE
    _SK_registerOSIntr
    _SK_registerOSSWE
    _SK_setEventReg

    So do I need similar wrapper calls for these functions? It still appears that I do not have all the libraries necessary, since I am linking against biosSK.a674 and the above symbols do not seem to be in this library.

  • There should be syscall entries in sk_cwrap.asm for all those undefined references.  Here is a copy from my tree:
    5466.sk_cwrap.asm
    7701.sk_cwrap.h

    It seems you have a stubbed out version if you're missing those key SK entry points.

    There's no assurance that the syscall numbers being used in the file that I'm attaching match up correctly with the actual syscall numbers implemented in the secure kernel of your chip, but the odds are good that they do.

    Regards,

    - Rob

  • Hi Rob,

    Thanks a lot, this seemed to solve my linker errors. It appears that I did in fact have an outdated version of the software.

    Just an FYI, the following line in sk_cwrap.asm

    sect ".text"

    Should be

            .sect ".text"

    (requires at tab space in front, which is maybe not apparent from above)

  • Hi Rob,

    I am now experiencing some additional problems with the secure kernel in DSP/BIOS, which I hope you can help me with. 

    My secure binding application is DSP/BIOS based, with a few tasks executing. I seem to run into problems when I exit in SECUREWITHSK mode (as configured in the INI file). For starters I simply created DSP/BIOS task which toggles a LED in a while(1) loop, using TSK_sleep(). When I exit in NONSECURE mode, this simple application executes perfectly, but as soon as I exit with SECUREWITHSK mode, the application seems to cause a UTL_halt().

    I am aware that the hardware should be enabled in the INI file with the PSCCONFIG, MPUCONFIG and IOPUCONFIG commands. I believe I am doing this correct, since I am using the example INI files which were supplied to me.

    I have a suspicion that my problem somehow lies in the context switching with the secure stack. If I put the LED toggling functionality in the main() function (not using TSK_sleep(), just for-loops for crude delays), it works fine, but as soon as I move it to a task, it does not work anymore.

    All of the secure kernel examples I have received from TI is not DSP/BIOS based, so I am actually not sure how the SK APIs should be propely used in the DSP/BIOS (multithreaded) environment.

    Can you please assist with some examples?

  • ReinierC said:
    I seem to run into problems when I exit in SECUREWITHSK mode (as configured in the INI file). For starters I simply created DSP/BIOS task which toggles a LED in a while(1) loop, using TSK_sleep(). When I exit in NONSECURE mode, this simple application executes perfectly, but as soon as I exit with SECUREWITHSK mode, the application seems to cause a UTL_halt().

    Hi Reinier,

    I am not familiar with these modes associated with "exit" and an INI file.  I know secure kernel code and its architecture, its C (or asm, really) interface and DSP/BIOS integration.  What do you mean when you say something like "problems when I exit in SECUREWITHSK mode"?  What is this mode and what is "exiting"?

    ReinierC said:

    I am aware that the hardware should be enabled in the INI file with the PSCCONFIG, MPUCONFIG and IOPUCONFIG commands. I believe I am doing this correct, since I am using the example INI files which were supplied to me.

    Again this is all unfamiliar terminology to me, are you using SK and DSP/BIOS with some overlying package?

    I'm getting the sense that this "exit" mode has to do with the transition from secure kernel bootup to non-secure kernel code.  DSP/BIOS should be executing in NONSECURE mode, as dictated from a security standpoint, and the problem may well occur because the DSP/BIOS app is placed in non-secure memory (again, as it should be).  If you wanted it to run your DSP/BIOS application in secure mode (which is what I assume would be happening when the "exit" mode is SECUREWITHSK) then you would have to modify SK to give secure permission to the code memory and/or data memory that the DSP/BIOS application uses.  However, from what I know about DSP/BIOS-with-SK customers, the DSP/BIOS application runs in NONSECURE mode.

    ReinierC said:

    I have a suspicion that my problem somehow lies in the context switching with the secure stack. If I put the LED toggling functionality in the main() function (not using TSK_sleep(), just for-loops for crude delays), it works fine, but as soon as I move it to a task, it does not work anymore.

    Please be aware that, as far as secure kernel is concerned, a DSP/BIOS application is just some non-secure caller/user of the SK APIs, and as such secure kernel knows nothing of DSP/BIOS TSKs and their associated stacks and stack switching.  There is no "OS" associated with DSP/BIOS, i.e., within the DSP/BIOS application there is no different modes such as user/supervisor or secure/nonsecure.  DSP/BIOS is mostly a real-time toolkit where all code (including all DSP/BIOS library code) executes at the same level.

    You may be mixing up DSP/BIOS task switching with the secure kernel stack contexts.  When a secure kernel API is invoked through the SWE asm instruction mechanism, the secure kernel knows that it needs to save the existing non-secure stack pointer, switch to a secure stack, run the API, and then switch back to the non-secure stack.  It doesn't know that DSP/BIOS switches the stack between tasks, nor does it care.

    Regards,

    - Rob

  • Hi Rob,

    My apologies, I was under the impression that you were familiar with the secure OMAP-L138/C6748 platform.

    Therefore, I would first like to provide you with some background. I agree that the final application should only execute in non-secure mode, but what I am busy with is the development of the secure binding application. This application only executes once during the production phase, where the software header (which contains the customer encryption key or CEK) of the final application has to be encrypted with the specific key encryption key (KEK) of the C6748 DSP.

    To have access to the required encryption algorithms, the C6748 therefore has to be placed in secure mode after the booting phase. This is achieved by the TI supplied SecureHexAIS command line utility, which takes as input an INI text file with various configuration parameters and creates a secure bootable binary image. All of the terms that you are unfamiliar with, are related to this utility. See the link below for more details:

    http://processors.wiki.ti.com/index.php/Basic_Secure_Boot_for_OMAP-L138_C6748

    I believe I can achieve the secure binding with a non-DSP/BIOS application, but I really would prefer to use DSP/BIOS for convenience. The problem is that the guys at TI's C6748 forums referred me to the DSP/BIOS forums, because I essentially have a DSP/BIOS related problem, which they are not too familiar with, but I guess if you are not too familiar with the C6748 platform it is also difficult for you to provide effective support.

    What I am currently struggling with is to get multithreading working in DSP/BIOS while the C6748 is in secure-mode. For the normal non-secure mode, I can easily achieve this. I am really in need of some concrete DSP/BIOS   examples (specificially for the C6748) for achieving this.

  • ReinierC said:
    My apologies, I was under the impression that you were familiar with the secure OMAP-L138/C6748 platform

    Hi Reinier,

    Thankyou for the detailed explanation and pointer to documentation, very interesting stuff.  I was not aware of this layer (but now I can see where the discussions I was involved in lead).

    As I now understand, your DSP/BIOS application will be executing in nonsecure mode with the capability to call SK APIs (as opposed to NONSECURE exit, where SK and all security is essentially gone).  You mentioned that you're able to run your simple DSP/BIOS app with NONSECURE exit, but not with SECUREWITHSK.  I assume therefore that you've created the NONSECURE app without
        bios.GBL.ENABLE_SK = true;
    and created the SECUREWITHSK app with it.

    You mentioned that when it fails, the DSP/BIOS app reaches UTL_halt().  I could help you determine why, from a low-level standpoint.

    Is there any SYS_printf() output in the SYS trace buffer?

    Do any of the MPFSR/MPFAR registers have non-zero contents?  These are the Memory Protection Fault Status/Address Registers, and there is a set of those each for L1D/L1P/L2 memory (also known as DMC/PMC/UMC memories).

    I expect that for your situation reaching UTL_halt(), there has been an exception caused by some missing permission attribute, and answering the above questions may lead to the cause.

    Regards,

    - Rob

  • Hi Rob,

    Rob said:

     I assume therefore that you've created the NONSECURE app without
        bios.GBL.ENABLE_SK = true;
    and created the SECUREWITHSK app with it.

    No, I have in fact set this parameter in the TCF script.

    Rob said:

    You mentioned that when it fails, the DSP/BIOS app reaches UTL_halt().  I could help you determine why, from a low-level standpoint.

    I was in fact wrong here, I had assumed it was a UTL_halt() call, where it is in fact a run-into-the-weeds case. The main() function would finish executing and in the process of starting all the various DSP/BIOS modules, it would just end up at some seemingly random address (0x7F7FF0). In particular, this would happen during a call to TSK_startup in the generated *.s62 source file. Maybe its an exception of sorts?

    In parallel to this, I also created a similar non-DSP/BIOS application and I saw the exact same behavior in SECUREWITHSK mode, the moment the interrupt vector table (ISTP register) was set, i.e. I also ended up at address 0x7F7FF0. 

    It does appear to be related to the setting of some permissions in secure mode (in non-secure mode everything just works as expected), but I have configured the MPUs and IOPUs in the INI file as it was recommended by the C6748 support guys, so I really am not sure what else to do.

    Any ideas?

  • ReinierC said:

    I was in fact wrong here, I had assumed it was a UTL_halt() call, where it is in fact a run-into-the-weeds case. The main() function would finish executing and in the process of starting all the various DSP/BIOS modules, it would just end up at some seemingly random address (0x7F7FF0). In particular, this would happen during a call to TSK_startup in the generated *.s62 source file. Maybe its an exception of sorts?

    Address 0x7f7ff0 is in the L2 ROM, and is likely the SK code.  It might be the "SK_ns_wedge" function which parks the CPU in an inifinite loop when SK detects something wrong.

    Can you determine with more precision exactly what operation is making it "jump into the weeds"?  It's either a badly formed SK syscall, or accessing something that it can't access which is causing an exception.  The OMAP-L138 was one of the last processors to get SK support in DSP/BIOS, and it's possible that something was missed.

    ReinierC said:
    In parallel to this, I also created a similar non-DSP/BIOS application and I saw the exact same behavior in SECUREWITHSK mode, the moment the interrupt vector table (ISTP register) was set, i.e. I also ended up at address 0x7F7FF0

    Since ISTP is a secure-access-only register, it makes sense that you'd end up in this bad place.  DSP/BIOS, in the SK mode, calls into SK to register for interrupt processing (and exception processing) and doesn't write the ISTP register (in normal, non-SK mode DSP/BIOS writes directly to the ISTP).  Your non-DSP/BIOS application could conceivably call the same SK syscalls that DSP/BIOS does (the ones in sk_cwrap.asm).  It would want to *not* write the ISTP nor try to write into the vector table pointed to by ISTP (which it can't even see), but instead just make calls into SK_registerOSIntr().

    There are many things that an app can't do when running in the SK mode that it normally could (and would) do, hence the existence of the SK syscalls.

    Regards,

    - Rob 

  • Hi Rob,

    Sorry for the delay in my response.

    I have tried a couple of other things, but my conclusion is that what I am trying to achieve cannot be done in SK mode. My original goal was to have a single embedded app, which would be booted over UART and once executing would be capable of downloading the final application image over UART from a PC-based application. Once the entire image have been downloaded, the binding would be immediately performed in RAM before writing the complete binded image to NOR flash.

    However, since some of the functionality is not available in SK mode, I decided to split the image flashing and binding into two separate apps, which seem to have solved my problem. The guys at the C6748 forums also told me that no DSP/BIOS-based examples exist for SK mode, so I guess it just was not intended to be used in this way.

    I now have a new problem I was hoping you could assist me with.

    I have managed to secure bind a few simple apps to test the entire procedure, which works fine, but I now want to bind our main app, which is about a 13 MB image. The flashing and secure binding of the app seem to be fine, but when it actually boots from NOR flash I seem to run into a few problems, i.e. it won't boot properly and I do not know what exactly is going wrong.

    This main application executes fine on this platform if I first unlock the JTAG via a simple unlock app over UART and then download the main application via the emulator.

    I suspect it might have something to do with the fact that the first 16KB  (i.e. 0x0080_4000 to 0x0080_7FFF) of internal RAM is off-limits for use by the SK during the booting process (refer to the previous link I gave). It might be that my main application has some sections in this region of internal RAM, which the primary bootloader might attempt to write to.

    My desired configuration is to use 128KB of the internal RAM as cache and the remaining 128KB for the application.  

    My question is thus, how can I prevent the linker at compile time from placing any objects in the first 16KB of internal RAM, but reclaim this memory back during runtime?

    I have come across the DSP/BIOS function MEM_redefine(), but I seem to have used it incorrectly because it caused a UTL_halt when I tried using it via the emulator. Can you maybe provide the correct steps for reconfiguring the memory and cache during runtime? 

  • ReinierC,

    "My question is thus, how can I prevent the linker at compile time from placing any objects in the first 16KB of internal RAM, but reclaim this memory back during runtime?"

    You could try removing the first 16KB internal RAM from your memory map either via the linkercommand file or if using DSP/BIOS via the configuration.

    Judah

  • Hi Judah,

    Yes, that is the easy part. What I am unsure about, is how to reclaim this 16KB of internal RAM during runtime, when the SK is no longer using this piece of memory. Can you maybe provide some example code, please?

  • ReinierC,

    If you are thinking about reclaiming this part of memory for code then you could use the "load/run" linker options.  Basically what this allows you do to is load the code to some slow memory like DDR but then the code gets run from some fast memory like IRAM.  At runtime you would need a function to copy the code from slow memory (DDR) to  fast memory (IRAM).  Here is the snippet from SRPU186W.pdf:

     7.4.29.1 Carrying Trampolines From Load Space to Run Space

    It is sometimes useful to load code in one location in memory and run it in another. The linker provides the capability to specify separate load and run allocations for a section. The burden of actually copying the code from the load space to the run space is left to you.

    A copy function must be executed before the real function can be executed in its run space. To facilitate this copy function, the assembler provides the .label directive, which allows you to define a load-time address. These load-time addresses can then be used to determine the start address and size of the code to be copied. However, this mechanism will not  work if the code contains a call that requires a trampoline to reach its called function. This is because the trampoline code is generated at link time, after the loadtime addresses associated with the .label directive have been defined. If the linker detects the definition of a .label symbol in an input section that contains a trampoline call, then a warning is generated.

    To solve this problem, you can use the START(), END(), and SIZE() operators (see Section 7.5.8.7). These operators allow you to define symbols to represent the load-time start address and size inside the link command file. These symbols can be referenced by the copy code, and their values are not resolved until link time, after the trampoline sections have been allocated. Here is an example of how you could use the START() and SIZE() operators in association with an output section to copy the trampoline code section along with the code containing the calls that need trampolines:

    SECTIONS
    {   .foo : load = ROM, run = RAM, start(foo_start), size(foo_size)
                   { x.obj(.text) }

        .text: {} > ROM

        .far : { -l=rts.lib(.text) } > FAR_MEM
    }

    A function in x.obj contains an run-time-support call. The run-time-support library is placed in far memory and so the call is out-of-range. A trampoline section will be added to the .foo output section by the linker. The copy code can refer to the symbols foo_start and foo_size as parameters for the load start address and size of the entire .foo output section. This allows the copy code to copy the trampoline section along with the original x.obj code in .text from its load space to its run space

    Judah

  • Hi Judah,

    Thanks a lot for the detailed response, it is much appreciated. 

    However, I think in my case it is typically not code that needs to be copied back to internal RAM at runtime, but mostly data, in particular the heap defined in the internal RAM.

    By looking at the MAP file generated by the linker, I noticed that the heap would typically be placed at the start of internal RAM, and it also takes up the most space for our particular application.

    The C6748 DSP has 256KB of internal RAM, of which the first 128KB is used for the application and the remaining 128KB is used for cache (very important for performance).

    However, when the SK is active on the C6748, the second 16KB (0x1180_4000 to 0x1180_7FFF) is off limits, but I believe its not possible to define the internal RAM as two separate pieces of memory (i.e. it has to be continuous), so effectively the first 32KB of internal RAM is off-limits during boot time when the SK is active.

    To solve this, I simply redefined the internal RAM memory map in the TCF file:

    bios.MEM.instance("IRAM").base = 0x11808000;
    bios.MEM.instance("IRAM").len = 0x00018000;

    This prevented the linker from placing any objects in the SK memory region, at the cost of a reduced heap. From your post I can understand how to solve this for code sections, but is it possible to move the location of the heap at runtime and then resize it?

     

  • ReinerC,

    "but I believe its not possible to define the internal RAM as two separate pieces of memory (i.e. it has to be continuous), so effectively the first 32KB of internal RAM is off-limits during boot time when the SK is active."

    -You would have to give it a different name.  You should be able to create another instance and set the base and length to the 16KB that you desire.  You can certainly define more than one logical name for a physical memory partitiion.

    "This prevented the linker from placing any objects in the SK memory region, at the cost of a reduced heap. From your post I can understand how to solve this for code sections, but is it possible to move the location of the heap at runtime and then resize it?"

    -This is a much more difficult question because I'm not exactly sure what you are wanting to do.  Are you trying to make the heap bigger and preserve the current contents of the heap?  If so, I do not think that would be possible.  Also is the heap created at static time or at runtime?  I think what you should be able to do is:

    1.  If the heap is created statically then there's not much you can do to the current heap.  The best you can do is create a second heap.

    2.  If the heap is created at runtime, then if you aren't trying to perserve its contents, then you can free the heap and create a new heap with the bigger size.  You could also create a second heap on just the smaller memory that you are trying to add.

    Again, I'm not sure if any of those solutions fits your need without understanding more of what you want to do.

    Judah