mirror of
				https://github.com/FreeRTOS/FreeRTOS-Kernel.git
				synced 2025-11-04 02:32:42 -05:00 
			
		
		
		
	Normalize line endings and whitespace in source files
This commit is contained in:
		
							parent
							
								
									151fb04ad1
								
							
						
					
					
						commit
						01820d3ed9
					
				
					 574 changed files with 162626 additions and 172362 deletions
				
			
		| 
						 | 
				
			
			@ -1,470 +1,470 @@
 | 
			
		|||
/*
 | 
			
		||||
 * FreeRTOS Kernel <DEVELOPMENT BRANCH>
 | 
			
		||||
 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: MIT
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 | 
			
		||||
 * this software and associated documentation files (the "Software"), to deal in
 | 
			
		||||
 * the Software without restriction, including without limitation the rights to
 | 
			
		||||
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 | 
			
		||||
 * the Software, and to permit persons to whom the Software is furnished to do so,
 | 
			
		||||
 * subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
 * copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 | 
			
		||||
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 | 
			
		||||
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 | 
			
		||||
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
			
		||||
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 *
 | 
			
		||||
 * https://www.FreeRTOS.org
 | 
			
		||||
 * https://github.com/FreeRTOS
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Standard includes. */
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE ensures that PRIVILEGED_FUNCTION
 | 
			
		||||
 * is defined correctly and privileged functions are placed in correct sections. */
 | 
			
		||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
 | 
			
		||||
 | 
			
		||||
/* Portasm includes. */
 | 
			
		||||
#include "portasm.h"
 | 
			
		||||
 | 
			
		||||
/* MPU_WRAPPERS_INCLUDED_FROM_API_FILE is needed to be defined only for the
 | 
			
		||||
 * header files. */
 | 
			
		||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
 | 
			
		||||
 | 
			
		||||
void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
 | 
			
		||||
{
 | 
			
		||||
    __asm volatile
 | 
			
		||||
    (
 | 
			
		||||
        "	.syntax unified									\n"
 | 
			
		||||
        "													\n"
 | 
			
		||||
        "	ldr  r2, pxCurrentTCBConst2						\n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
 | 
			
		||||
        "	ldr  r3, [r2]									\n"/* Read pxCurrentTCB. */
 | 
			
		||||
        "	ldr  r0, [r3]									\n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
 | 
			
		||||
        "													\n"
 | 
			
		||||
        #if ( configENABLE_MPU == 1 )
 | 
			
		||||
            "	dmb											\n"/* Complete outstanding transfers before disabling MPU. */
 | 
			
		||||
            "	ldr r2, xMPUCTRLConst2						\n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
 | 
			
		||||
            "	ldr r4, [r2]								\n"/* Read the value of MPU_CTRL. */
 | 
			
		||||
            "	bic r4, #1									\n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
 | 
			
		||||
            "	str r4, [r2]								\n"/* Disable MPU. */
 | 
			
		||||
            "												\n"
 | 
			
		||||
            "	adds r3, #4									\n"/* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
 | 
			
		||||
            "	ldr  r4, [r3]								\n"/* r4 = *r3 i.e. r4 = MAIR0. */
 | 
			
		||||
            "	ldr  r2, xMAIR0Const2						\n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
 | 
			
		||||
            "	str  r4, [r2]								\n"/* Program MAIR0. */
 | 
			
		||||
            "	ldr  r2, xRNRConst2							\n"/* r2 = 0xe000ed98 [Location of RNR]. */
 | 
			
		||||
            "	movs r4, #4									\n"/* r4 = 4. */
 | 
			
		||||
            "	str  r4, [r2]								\n"/* Program RNR = 4. */
 | 
			
		||||
            "	adds r3, #4									\n"/* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
 | 
			
		||||
            "	ldr  r2, xRBARConst2						\n"/* r2 = 0xe000ed9c [Location of RBAR]. */
 | 
			
		||||
            "	ldmia r3!, {r4-r11}							\n"/* Read 4 set of RBAR/RLAR registers from TCB. */
 | 
			
		||||
            "	stmia r2!, {r4-r11}							\n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
 | 
			
		||||
            "												\n"
 | 
			
		||||
        #if ( configTOTAL_MPU_REGIONS == 16 )
 | 
			
		||||
            "	ldr  r2, xRNRConst2							\n"/* r2 = 0xe000ed98 [Location of RNR]. */
 | 
			
		||||
            "	movs r4, #8									\n"/* r4 = 8. */
 | 
			
		||||
            "	str  r4, [r2]								\n"/* Program RNR = 8. */
 | 
			
		||||
            "	ldr  r2, xRBARConst2						\n"/* r2 = 0xe000ed9c [Location of RBAR]. */
 | 
			
		||||
            "	ldmia r3!, {r4-r11}							\n"/* Read 4 set of RBAR/RLAR registers from TCB. */
 | 
			
		||||
            "	stmia r2!, {r4-r11}							\n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
 | 
			
		||||
            "	ldr  r2, xRNRConst2							\n"/* r2 = 0xe000ed98 [Location of RNR]. */
 | 
			
		||||
            "	movs r4, #12								\n"/* r4 = 12. */
 | 
			
		||||
            "	str  r4, [r2]								\n"/* Program RNR = 12. */
 | 
			
		||||
            "	ldr  r2, xRBARConst2						\n"/* r2 = 0xe000ed9c [Location of RBAR]. */
 | 
			
		||||
            "	ldmia r3!, {r4-r11}							\n"/* Read 4 set of RBAR/RLAR registers from TCB. */
 | 
			
		||||
            "	stmia r2!, {r4-r11}							\n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
 | 
			
		||||
        #endif /* configTOTAL_MPU_REGIONS == 16 */
 | 
			
		||||
            "												\n"
 | 
			
		||||
            "	ldr r2, xMPUCTRLConst2						\n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
 | 
			
		||||
            "	ldr r4, [r2]								\n"/* Read the value of MPU_CTRL. */
 | 
			
		||||
            "	orr r4, #1									\n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
 | 
			
		||||
            "	str r4, [r2]								\n"/* Enable MPU. */
 | 
			
		||||
            "	dsb											\n"/* Force memory writes before continuing. */
 | 
			
		||||
        #endif /* configENABLE_MPU */
 | 
			
		||||
        "													\n"
 | 
			
		||||
        #if ( configENABLE_MPU == 1 )
 | 
			
		||||
            "	ldm  r0!, {r1-r4}							\n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */
 | 
			
		||||
            "	ldr  r5, xSecureContextConst2				\n"
 | 
			
		||||
            "	str  r1, [r5]								\n"/* Set xSecureContext to this task's value for the same. */
 | 
			
		||||
            "	msr  psplim, r2								\n"/* Set this task's PSPLIM value. */
 | 
			
		||||
            "	msr  control, r3							\n"/* Set this task's CONTROL value. */
 | 
			
		||||
            "	adds r0, #32								\n"/* Discard everything up to r0. */
 | 
			
		||||
            "	msr  psp, r0								\n"/* This is now the new top of stack to use in the task. */
 | 
			
		||||
            "	isb											\n"
 | 
			
		||||
            "	mov  r0, #0									\n"
 | 
			
		||||
            "	msr  basepri, r0							\n"/* Ensure that interrupts are enabled when the first task starts. */
 | 
			
		||||
            "	bx   r4										\n"/* Finally, branch to EXC_RETURN. */
 | 
			
		||||
        #else /* configENABLE_MPU */
 | 
			
		||||
            "	ldm  r0!, {r1-r3}							\n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
 | 
			
		||||
            "	ldr  r4, xSecureContextConst2				\n"
 | 
			
		||||
            "	str  r1, [r4]								\n"/* Set xSecureContext to this task's value for the same. */
 | 
			
		||||
            "	msr  psplim, r2								\n"/* Set this task's PSPLIM value. */
 | 
			
		||||
            "	movs r1, #2									\n"/* r1 = 2. */
 | 
			
		||||
            "	msr  CONTROL, r1							\n"/* Switch to use PSP in the thread mode. */
 | 
			
		||||
            "	adds r0, #32								\n"/* Discard everything up to r0. */
 | 
			
		||||
            "	msr  psp, r0								\n"/* This is now the new top of stack to use in the task. */
 | 
			
		||||
            "	isb											\n"
 | 
			
		||||
            "	mov  r0, #0									\n"
 | 
			
		||||
            "	msr  basepri, r0							\n"/* Ensure that interrupts are enabled when the first task starts. */
 | 
			
		||||
            "	bx   r3										\n"/* Finally, branch to EXC_RETURN. */
 | 
			
		||||
        #endif /* configENABLE_MPU */
 | 
			
		||||
        "													\n"
 | 
			
		||||
        "	.align 4										\n"
 | 
			
		||||
        "pxCurrentTCBConst2: .word pxCurrentTCB				\n"
 | 
			
		||||
        "xSecureContextConst2: .word xSecureContext			\n"
 | 
			
		||||
        #if ( configENABLE_MPU == 1 )
 | 
			
		||||
            "xMPUCTRLConst2: .word 0xe000ed94				\n"
 | 
			
		||||
            "xMAIR0Const2: .word 0xe000edc0					\n"
 | 
			
		||||
            "xRNRConst2: .word 0xe000ed98					\n"
 | 
			
		||||
            "xRBARConst2: .word 0xe000ed9c					\n"
 | 
			
		||||
        #endif /* configENABLE_MPU */
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
 | 
			
		||||
{
 | 
			
		||||
    __asm volatile
 | 
			
		||||
    (
 | 
			
		||||
        "	.syntax unified									\n"
 | 
			
		||||
        "													\n"
 | 
			
		||||
        "	mrs r0, control									\n"/* r0 = CONTROL. */
 | 
			
		||||
        "	tst r0, #1										\n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
 | 
			
		||||
        "	ite ne											\n"
 | 
			
		||||
        "	movne r0, #0									\n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
 | 
			
		||||
        "	moveq r0, #1									\n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
 | 
			
		||||
        "	bx lr											\n"/* Return. */
 | 
			
		||||
        "													\n"
 | 
			
		||||
        "	.align 4										\n"
 | 
			
		||||
        ::: "r0", "memory"
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
 | 
			
		||||
{
 | 
			
		||||
    __asm volatile
 | 
			
		||||
    (
 | 
			
		||||
        "	.syntax unified									\n"
 | 
			
		||||
        "													\n"
 | 
			
		||||
        "	mrs r0, control									\n"/* Read the CONTROL register. */
 | 
			
		||||
        "	bic r0, #1										\n"/* Clear the bit 0. */
 | 
			
		||||
        "	msr control, r0									\n"/* Write back the new CONTROL value. */
 | 
			
		||||
        "	bx lr											\n"/* Return to the caller. */
 | 
			
		||||
        ::: "r0", "memory"
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
void vResetPrivilege( void ) /* __attribute__ (( naked )) */
 | 
			
		||||
{
 | 
			
		||||
    __asm volatile
 | 
			
		||||
    (
 | 
			
		||||
        "	.syntax unified									\n"
 | 
			
		||||
        "													\n"
 | 
			
		||||
        "	mrs r0, control									\n"/* r0 = CONTROL. */
 | 
			
		||||
        "	orr r0, #1										\n"/* r0 = r0 | 1. */
 | 
			
		||||
        "	msr control, r0									\n"/* CONTROL = r0. */
 | 
			
		||||
        "	bx lr											\n"/* Return to the caller. */
 | 
			
		||||
        ::: "r0", "memory"
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
 | 
			
		||||
{
 | 
			
		||||
    __asm volatile
 | 
			
		||||
    (
 | 
			
		||||
        "	.syntax unified									\n"
 | 
			
		||||
        "													\n"
 | 
			
		||||
        "	ldr r0, xVTORConst								\n"/* Use the NVIC offset register to locate the stack. */
 | 
			
		||||
        "	ldr r0, [r0]									\n"/* Read the VTOR register which gives the address of vector table. */
 | 
			
		||||
        "	ldr r0, [r0]									\n"/* The first entry in vector table is stack pointer. */
 | 
			
		||||
        "	msr msp, r0										\n"/* Set the MSP back to the start of the stack. */
 | 
			
		||||
        "	cpsie i											\n"/* Globally enable interrupts. */
 | 
			
		||||
        "	cpsie f											\n"
 | 
			
		||||
        "	dsb												\n"
 | 
			
		||||
        "	isb												\n"
 | 
			
		||||
        "	svc %0											\n"/* System call to start the first task. */
 | 
			
		||||
        "	nop												\n"
 | 
			
		||||
        "													\n"
 | 
			
		||||
        "   .align 4										\n"
 | 
			
		||||
        "xVTORConst: .word 0xe000ed08						\n"
 | 
			
		||||
        ::"i" ( portSVC_START_SCHEDULER ) : "memory"
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
 | 
			
		||||
{
 | 
			
		||||
    __asm volatile
 | 
			
		||||
    (
 | 
			
		||||
        "	.syntax unified									\n"
 | 
			
		||||
        "													\n"
 | 
			
		||||
        "	mrs r0, basepri									\n"/* r0 = basepri. Return original basepri value. */
 | 
			
		||||
        "	mov r1, %0										\n"/* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */
 | 
			
		||||
        "	msr basepri, r1									\n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
 | 
			
		||||
        "	dsb												\n"
 | 
			
		||||
        "	isb												\n"
 | 
			
		||||
        "	bx lr											\n"/* Return. */
 | 
			
		||||
        ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
 | 
			
		||||
{
 | 
			
		||||
    __asm volatile
 | 
			
		||||
    (
 | 
			
		||||
        "	.syntax unified									\n"
 | 
			
		||||
        "													\n"
 | 
			
		||||
        "	msr basepri, r0									\n"/* basepri = ulMask. */
 | 
			
		||||
        "	dsb												\n"
 | 
			
		||||
        "	isb												\n"
 | 
			
		||||
        "	bx lr											\n"/* Return. */
 | 
			
		||||
        ::: "memory"
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
 | 
			
		||||
{
 | 
			
		||||
    __asm volatile
 | 
			
		||||
    (
 | 
			
		||||
        "	.syntax unified									\n"
 | 
			
		||||
        "	.extern SecureContext_SaveContext				\n"
 | 
			
		||||
        "	.extern SecureContext_LoadContext				\n"
 | 
			
		||||
        "													\n"
 | 
			
		||||
        "	ldr r3, xSecureContextConst						\n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
 | 
			
		||||
        "	ldr r0, [r3]									\n"/* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
 | 
			
		||||
        "	ldr r3, pxCurrentTCBConst						\n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
 | 
			
		||||
        "	ldr r1, [r3]									\n"/* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later. */
 | 
			
		||||
        "	mrs r2, psp										\n"/* Read PSP in r2. */
 | 
			
		||||
        "													\n"
 | 
			
		||||
        "	cbz r0, save_ns_context							\n"/* No secure context to save. */
 | 
			
		||||
        "	push {r0-r2, r14}								\n"
 | 
			
		||||
        "	bl SecureContext_SaveContext					\n"/* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
 | 
			
		||||
        "	pop {r0-r3}										\n"/* LR is now in r3. */
 | 
			
		||||
        "	mov lr, r3										\n"/* LR = r3. */
 | 
			
		||||
        "	lsls r1, r3, #25								\n"/* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
 | 
			
		||||
        "	bpl save_ns_context								\n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
 | 
			
		||||
        "													\n"
 | 
			
		||||
        "	ldr r3, pxCurrentTCBConst						\n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
 | 
			
		||||
        "	ldr r1, [r3]									\n"/* Read pxCurrentTCB.*/
 | 
			
		||||
        #if ( configENABLE_MPU == 1 )
 | 
			
		||||
            "	subs r2, r2, #16							\n"/* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */
 | 
			
		||||
            "	str r2, [r1]								\n"/* Save the new top of stack in TCB. */
 | 
			
		||||
            "	mrs r1, psplim								\n"/* r1 = PSPLIM. */
 | 
			
		||||
            "	mrs r3, control								\n"/* r3 = CONTROL. */
 | 
			
		||||
            "	mov r4, lr									\n"/* r4 = LR/EXC_RETURN. */
 | 
			
		||||
            "	stmia r2!, {r0, r1, r3, r4}					\n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
 | 
			
		||||
        #else /* configENABLE_MPU */
 | 
			
		||||
            "	subs r2, r2, #12							\n"/* Make space for xSecureContext, PSPLIM and LR on the stack. */
 | 
			
		||||
            "	str r2, [r1]								\n"/* Save the new top of stack in TCB. */
 | 
			
		||||
            "	mrs r1, psplim								\n"/* r1 = PSPLIM. */
 | 
			
		||||
            "	mov r3, lr									\n"/* r3 = LR/EXC_RETURN. */
 | 
			
		||||
            "	stmia r2!, {r0, r1, r3}						\n"/* Store xSecureContext, PSPLIM and LR on the stack. */
 | 
			
		||||
        #endif /* configENABLE_MPU */
 | 
			
		||||
        "	b select_next_task								\n"
 | 
			
		||||
        "													\n"
 | 
			
		||||
        " save_ns_context:									\n"
 | 
			
		||||
        "	ldr r3, pxCurrentTCBConst						\n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
 | 
			
		||||
        "	ldr r1, [r3]									\n"/* Read pxCurrentTCB. */
 | 
			
		||||
        #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
 | 
			
		||||
            "	tst lr, #0x10								\n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
 | 
			
		||||
            "	it eq										\n"
 | 
			
		||||
            "	vstmdbeq r2!, {s16-s31}						\n"/* Store the additional FP context registers which are not saved automatically. */
 | 
			
		||||
        #endif /* configENABLE_FPU || configENABLE_MVE */
 | 
			
		||||
        #if ( configENABLE_MPU == 1 )
 | 
			
		||||
            "	subs r2, r2, #48							\n"/* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */
 | 
			
		||||
            "	str r2, [r1]								\n"/* Save the new top of stack in TCB. */
 | 
			
		||||
            "	adds r2, r2, #16							\n"/* r2 = r2 + 16. */
 | 
			
		||||
            "	stm r2, {r4-r11}							\n"/* Store the registers that are not saved automatically. */
 | 
			
		||||
            "	mrs r1, psplim								\n"/* r1 = PSPLIM. */
 | 
			
		||||
            "	mrs r3, control								\n"/* r3 = CONTROL. */
 | 
			
		||||
            "	mov r4, lr									\n"/* r4 = LR/EXC_RETURN. */
 | 
			
		||||
            "	subs r2, r2, #16							\n"/* r2 = r2 - 16. */
 | 
			
		||||
            "	stmia r2!, {r0, r1, r3, r4}					\n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
 | 
			
		||||
        #else /* configENABLE_MPU */
 | 
			
		||||
            "	subs r2, r2, #44							\n"/* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */
 | 
			
		||||
            "	str r2, [r1]								\n"/* Save the new top of stack in TCB. */
 | 
			
		||||
            "	adds r2, r2, #12							\n"/* r2 = r2 + 12. */
 | 
			
		||||
            "	stm r2, {r4-r11}							\n"/* Store the registers that are not saved automatically. */
 | 
			
		||||
            "	mrs r1, psplim								\n"/* r1 = PSPLIM. */
 | 
			
		||||
            "	mov r3, lr									\n"/* r3 = LR/EXC_RETURN. */
 | 
			
		||||
            "	subs r2, r2, #12							\n"/* r2 = r2 - 12. */
 | 
			
		||||
            "	stmia r2!, {r0, r1, r3}						\n"/* Store xSecureContext, PSPLIM and LR on the stack. */
 | 
			
		||||
        #endif /* configENABLE_MPU */
 | 
			
		||||
        "													\n"
 | 
			
		||||
        " select_next_task:									\n"
 | 
			
		||||
        "	mov r0, %0										\n"/* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
 | 
			
		||||
        "	msr basepri, r0									\n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
 | 
			
		||||
        "	dsb												\n"
 | 
			
		||||
        "	isb												\n"
 | 
			
		||||
        "	bl vTaskSwitchContext							\n"
 | 
			
		||||
        "	mov r0, #0										\n"/* r0 = 0. */
 | 
			
		||||
        "	msr basepri, r0									\n"/* Enable interrupts. */
 | 
			
		||||
        "													\n"
 | 
			
		||||
        "	ldr r3, pxCurrentTCBConst						\n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
 | 
			
		||||
        "	ldr r1, [r3]									\n"/* Read pxCurrentTCB. */
 | 
			
		||||
        "	ldr r2, [r1]									\n"/* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
 | 
			
		||||
        "													\n"
 | 
			
		||||
        #if ( configENABLE_MPU == 1 )
 | 
			
		||||
            "	dmb											\n"/* Complete outstanding transfers before disabling MPU. */
 | 
			
		||||
            "	ldr r3, xMPUCTRLConst						\n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
 | 
			
		||||
            "	ldr r4, [r3]								\n"/* Read the value of MPU_CTRL. */
 | 
			
		||||
            "	bic r4, #1									\n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
 | 
			
		||||
            "	str r4, [r3]								\n"/* Disable MPU. */
 | 
			
		||||
            "												\n"
 | 
			
		||||
            "	adds r1, #4									\n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
 | 
			
		||||
            "	ldr r4, [r1]								\n"/* r4 = *r1 i.e. r4 = MAIR0. */
 | 
			
		||||
            "	ldr r3, xMAIR0Const							\n"/* r3 = 0xe000edc0 [Location of MAIR0]. */
 | 
			
		||||
            "	str r4, [r3]								\n"/* Program MAIR0. */
 | 
			
		||||
            "	ldr r3, xRNRConst							\n"/* r3 = 0xe000ed98 [Location of RNR]. */
 | 
			
		||||
            "	movs r4, #4									\n"/* r4 = 4. */
 | 
			
		||||
            "	str r4, [r3]								\n"/* Program RNR = 4. */
 | 
			
		||||
            "	adds r1, #4									\n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
 | 
			
		||||
            "	ldr r3, xRBARConst							\n"/* r3 = 0xe000ed9c [Location of RBAR]. */
 | 
			
		||||
            "	ldmia r1!, {r4-r11}							\n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
 | 
			
		||||
            "	stmia r3!, {r4-r11}							\n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
 | 
			
		||||
            "												\n"
 | 
			
		||||
            #if ( configTOTAL_MPU_REGIONS == 16 )
 | 
			
		||||
            "	ldr r3, xRNRConst							\n"/* r3 = 0xe000ed98 [Location of RNR]. */
 | 
			
		||||
            "	movs r4, #8									\n"/* r4 = 8. */
 | 
			
		||||
            "	str r4, [r3]								\n"/* Program RNR = 8. */
 | 
			
		||||
            "	ldr r3, xRBARConst							\n"/* r3 = 0xe000ed9c [Location of RBAR]. */
 | 
			
		||||
            "	ldmia r1!, {r4-r11}							\n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
 | 
			
		||||
            "	stmia r3!, {r4-r11}							\n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
 | 
			
		||||
            "	ldr r3, xRNRConst							\n"/* r3 = 0xe000ed98 [Location of RNR]. */
 | 
			
		||||
            "	movs r4, #12								\n"/* r4 = 12. */
 | 
			
		||||
            "	str r4, [r3]								\n"/* Program RNR = 12. */
 | 
			
		||||
            "	ldr r3, xRBARConst							\n"/* r3 = 0xe000ed9c [Location of RBAR]. */
 | 
			
		||||
            "	ldmia r1!, {r4-r11}							\n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
 | 
			
		||||
            "	stmia r3!, {r4-r11}							\n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
 | 
			
		||||
            #endif /* configTOTAL_MPU_REGIONS == 16 */
 | 
			
		||||
            "												\n"
 | 
			
		||||
            "	ldr r3, xMPUCTRLConst						\n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
 | 
			
		||||
            "	ldr r4, [r3]								\n"/* Read the value of MPU_CTRL. */
 | 
			
		||||
            "	orr r4, #1									\n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
 | 
			
		||||
            "	str r4, [r3]								\n"/* Enable MPU. */
 | 
			
		||||
            "	dsb											\n"/* Force memory writes before continuing. */
 | 
			
		||||
        #endif /* configENABLE_MPU */
 | 
			
		||||
        "													\n"
 | 
			
		||||
        #if ( configENABLE_MPU == 1 )
 | 
			
		||||
            "	ldmia r2!, {r0, r1, r3, r4}					\n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM, r3 = CONTROL and r4 = LR. */
 | 
			
		||||
            "	msr psplim, r1								\n"/* Restore the PSPLIM register value for the task. */
 | 
			
		||||
            "	msr control, r3								\n"/* Restore the CONTROL register value for the task. */
 | 
			
		||||
            "	mov lr, r4									\n"/* LR = r4. */
 | 
			
		||||
            "	ldr r3, xSecureContextConst					\n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
 | 
			
		||||
            "	str r0, [r3]								\n"/* Restore the task's xSecureContext. */
 | 
			
		||||
            "	cbz r0, restore_ns_context					\n"/* If there is no secure context for the task, restore the non-secure context. */
 | 
			
		||||
            "	ldr r3, pxCurrentTCBConst					\n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
 | 
			
		||||
            "	ldr r1, [r3]								\n"/* Read pxCurrentTCB. */
 | 
			
		||||
            "	push {r2, r4}								\n"
 | 
			
		||||
            "	bl SecureContext_LoadContext				\n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
 | 
			
		||||
            "	pop {r2, r4}								\n"
 | 
			
		||||
            "	mov lr, r4									\n"/* LR = r4. */
 | 
			
		||||
            "	lsls r1, r4, #25							\n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
 | 
			
		||||
            "	bpl restore_ns_context						\n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
 | 
			
		||||
            "	msr psp, r2									\n"/* Remember the new top of stack for the task. */
 | 
			
		||||
            "	bx lr										\n"
 | 
			
		||||
        #else /* configENABLE_MPU */
 | 
			
		||||
            "	ldmia r2!, {r0, r1, r4}						\n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */
 | 
			
		||||
            "	msr psplim, r1								\n"/* Restore the PSPLIM register value for the task. */
 | 
			
		||||
            "	mov lr, r4									\n"/* LR = r4. */
 | 
			
		||||
            "	ldr r3, xSecureContextConst					\n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
 | 
			
		||||
            "	str r0, [r3]								\n"/* Restore the task's xSecureContext. */
 | 
			
		||||
            "	cbz r0, restore_ns_context					\n"/* If there is no secure context for the task, restore the non-secure context. */
 | 
			
		||||
            "	ldr r3, pxCurrentTCBConst					\n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
 | 
			
		||||
            "	ldr r1, [r3]								\n"/* Read pxCurrentTCB. */
 | 
			
		||||
            "	push {r2, r4}								\n"
 | 
			
		||||
            "	bl SecureContext_LoadContext				\n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
 | 
			
		||||
            "	pop {r2, r4}								\n"
 | 
			
		||||
            "	mov lr, r4									\n"/* LR = r4. */
 | 
			
		||||
            "	lsls r1, r4, #25							\n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
 | 
			
		||||
            "	bpl restore_ns_context						\n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
 | 
			
		||||
            "	msr psp, r2									\n"/* Remember the new top of stack for the task. */
 | 
			
		||||
            "	bx lr										\n"
 | 
			
		||||
        #endif /* configENABLE_MPU */
 | 
			
		||||
        "													\n"
 | 
			
		||||
        " restore_ns_context:								\n"
 | 
			
		||||
        "	ldmia r2!, {r4-r11}								\n"/* Restore the registers that are not automatically restored. */
 | 
			
		||||
        #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
 | 
			
		||||
            "	tst lr, #0x10								\n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
 | 
			
		||||
            "	it eq										\n"
 | 
			
		||||
            "	vldmiaeq r2!, {s16-s31}						\n"/* Restore the additional FP context registers which are not restored automatically. */
 | 
			
		||||
        #endif /* configENABLE_FPU || configENABLE_MVE */
 | 
			
		||||
        "	msr psp, r2										\n"/* Remember the new top of stack for the task. */
 | 
			
		||||
        "	bx lr											\n"
 | 
			
		||||
        "													\n"
 | 
			
		||||
        "	.align 4										\n"
 | 
			
		||||
        "pxCurrentTCBConst: .word pxCurrentTCB				\n"
 | 
			
		||||
        "xSecureContextConst: .word xSecureContext			\n"
 | 
			
		||||
        #if ( configENABLE_MPU == 1 )
 | 
			
		||||
            "xMPUCTRLConst: .word 0xe000ed94				\n"
 | 
			
		||||
            "xMAIR0Const: .word 0xe000edc0					\n"
 | 
			
		||||
            "xRNRConst: .word 0xe000ed98					\n"
 | 
			
		||||
            "xRBARConst: .word 0xe000ed9c					\n"
 | 
			
		||||
        #endif /* configENABLE_MPU */
 | 
			
		||||
        ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
 | 
			
		||||
{
 | 
			
		||||
    __asm volatile
 | 
			
		||||
    (
 | 
			
		||||
        "	.syntax unified									\n"
 | 
			
		||||
        "													\n"
 | 
			
		||||
        "	tst lr, #4										\n"
 | 
			
		||||
        "	ite eq											\n"
 | 
			
		||||
        "	mrseq r0, msp									\n"
 | 
			
		||||
        "	mrsne r0, psp									\n"
 | 
			
		||||
        "	ldr r1, svchandler_address_const				\n"
 | 
			
		||||
        "	bx r1											\n"
 | 
			
		||||
        "													\n"
 | 
			
		||||
        "	.align 4										\n"
 | 
			
		||||
        "svchandler_address_const: .word vPortSVCHandler_C	\n"
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) /* __attribute__ (( naked )) */
 | 
			
		||||
{
 | 
			
		||||
    __asm volatile
 | 
			
		||||
    (
 | 
			
		||||
        "	.syntax unified									\n"
 | 
			
		||||
        "													\n"
 | 
			
		||||
        "	svc %0											\n"/* Secure context is allocated in the supervisor call. */
 | 
			
		||||
        "	bx lr											\n"/* Return. */
 | 
			
		||||
        ::"i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory"
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
 | 
			
		||||
{
 | 
			
		||||
    __asm volatile
 | 
			
		||||
    (
 | 
			
		||||
        "	.syntax unified									\n"
 | 
			
		||||
        "													\n"
 | 
			
		||||
        "	ldr r2, [r0]									\n"/* The first item in the TCB is the top of the stack. */
 | 
			
		||||
        "	ldr r1, [r2]									\n"/* The first item on the stack is the task's xSecureContext. */
 | 
			
		||||
        "	cmp r1, #0										\n"/* Raise svc if task's xSecureContext is not NULL. */
 | 
			
		||||
        "	it ne											\n"
 | 
			
		||||
        "	svcne %0										\n"/* Secure context is freed in the supervisor call. */
 | 
			
		||||
        "	bx lr											\n"/* Return. */
 | 
			
		||||
        ::"i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory"
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
/*
 | 
			
		||||
 * FreeRTOS Kernel <DEVELOPMENT BRANCH>
 | 
			
		||||
 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: MIT
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 | 
			
		||||
 * this software and associated documentation files (the "Software"), to deal in
 | 
			
		||||
 * the Software without restriction, including without limitation the rights to
 | 
			
		||||
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 | 
			
		||||
 * the Software, and to permit persons to whom the Software is furnished to do so,
 | 
			
		||||
 * subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
 * copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 | 
			
		||||
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 | 
			
		||||
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 | 
			
		||||
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
			
		||||
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 *
 | 
			
		||||
 * https://www.FreeRTOS.org
 | 
			
		||||
 * https://github.com/FreeRTOS
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Standard includes. */
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE ensures that PRIVILEGED_FUNCTION
 | 
			
		||||
 * is defined correctly and privileged functions are placed in correct sections. */
 | 
			
		||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
 | 
			
		||||
 | 
			
		||||
/* Portasm includes. */
 | 
			
		||||
#include "portasm.h"
 | 
			
		||||
 | 
			
		||||
/* MPU_WRAPPERS_INCLUDED_FROM_API_FILE is needed to be defined only for the
 | 
			
		||||
 * header files. */
 | 
			
		||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
 | 
			
		||||
 | 
			
		||||
void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
 | 
			
		||||
{
 | 
			
		||||
    __asm volatile
 | 
			
		||||
    (
 | 
			
		||||
        "   .syntax unified                                 \n"
 | 
			
		||||
        "                                                   \n"
 | 
			
		||||
        "   ldr  r2, pxCurrentTCBConst2                     \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
 | 
			
		||||
        "   ldr  r3, [r2]                                   \n"/* Read pxCurrentTCB. */
 | 
			
		||||
        "   ldr  r0, [r3]                                   \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
 | 
			
		||||
        "                                                   \n"
 | 
			
		||||
        #if ( configENABLE_MPU == 1 )
 | 
			
		||||
            "   dmb                                         \n"/* Complete outstanding transfers before disabling MPU. */
 | 
			
		||||
            "   ldr r2, xMPUCTRLConst2                      \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
 | 
			
		||||
            "   ldr r4, [r2]                                \n"/* Read the value of MPU_CTRL. */
 | 
			
		||||
            "   bic r4, #1                                  \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
 | 
			
		||||
            "   str r4, [r2]                                \n"/* Disable MPU. */
 | 
			
		||||
            "                                               \n"
 | 
			
		||||
            "   adds r3, #4                                 \n"/* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
 | 
			
		||||
            "   ldr  r4, [r3]                               \n"/* r4 = *r3 i.e. r4 = MAIR0. */
 | 
			
		||||
            "   ldr  r2, xMAIR0Const2                       \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
 | 
			
		||||
            "   str  r4, [r2]                               \n"/* Program MAIR0. */
 | 
			
		||||
            "   ldr  r2, xRNRConst2                         \n"/* r2 = 0xe000ed98 [Location of RNR]. */
 | 
			
		||||
            "   movs r4, #4                                 \n"/* r4 = 4. */
 | 
			
		||||
            "   str  r4, [r2]                               \n"/* Program RNR = 4. */
 | 
			
		||||
            "   adds r3, #4                                 \n"/* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
 | 
			
		||||
            "   ldr  r2, xRBARConst2                        \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
 | 
			
		||||
            "   ldmia r3!, {r4-r11}                         \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
 | 
			
		||||
            "   stmia r2!, {r4-r11}                         \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
 | 
			
		||||
            "                                               \n"
 | 
			
		||||
        #if ( configTOTAL_MPU_REGIONS == 16 )
 | 
			
		||||
            "   ldr  r2, xRNRConst2                         \n"/* r2 = 0xe000ed98 [Location of RNR]. */
 | 
			
		||||
            "   movs r4, #8                                 \n"/* r4 = 8. */
 | 
			
		||||
            "   str  r4, [r2]                               \n"/* Program RNR = 8. */
 | 
			
		||||
            "   ldr  r2, xRBARConst2                        \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
 | 
			
		||||
            "   ldmia r3!, {r4-r11}                         \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
 | 
			
		||||
            "   stmia r2!, {r4-r11}                         \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
 | 
			
		||||
            "   ldr  r2, xRNRConst2                         \n"/* r2 = 0xe000ed98 [Location of RNR]. */
 | 
			
		||||
            "   movs r4, #12                                \n"/* r4 = 12. */
 | 
			
		||||
            "   str  r4, [r2]                               \n"/* Program RNR = 12. */
 | 
			
		||||
            "   ldr  r2, xRBARConst2                        \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
 | 
			
		||||
            "   ldmia r3!, {r4-r11}                         \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
 | 
			
		||||
            "   stmia r2!, {r4-r11}                         \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
 | 
			
		||||
        #endif /* configTOTAL_MPU_REGIONS == 16 */
 | 
			
		||||
            "                                               \n"
 | 
			
		||||
            "   ldr r2, xMPUCTRLConst2                      \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
 | 
			
		||||
            "   ldr r4, [r2]                                \n"/* Read the value of MPU_CTRL. */
 | 
			
		||||
            "   orr r4, #1                                  \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
 | 
			
		||||
            "   str r4, [r2]                                \n"/* Enable MPU. */
 | 
			
		||||
            "   dsb                                         \n"/* Force memory writes before continuing. */
 | 
			
		||||
        #endif /* configENABLE_MPU */
 | 
			
		||||
        "                                                   \n"
 | 
			
		||||
        #if ( configENABLE_MPU == 1 )
 | 
			
		||||
            "   ldm  r0!, {r1-r4}                           \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */
 | 
			
		||||
            "   ldr  r5, xSecureContextConst2               \n"
 | 
			
		||||
            "   str  r1, [r5]                               \n"/* Set xSecureContext to this task's value for the same. */
 | 
			
		||||
            "   msr  psplim, r2                             \n"/* Set this task's PSPLIM value. */
 | 
			
		||||
            "   msr  control, r3                            \n"/* Set this task's CONTROL value. */
 | 
			
		||||
            "   adds r0, #32                                \n"/* Discard everything up to r0. */
 | 
			
		||||
            "   msr  psp, r0                                \n"/* This is now the new top of stack to use in the task. */
 | 
			
		||||
            "   isb                                         \n"
 | 
			
		||||
            "   mov  r0, #0                                 \n"
 | 
			
		||||
            "   msr  basepri, r0                            \n"/* Ensure that interrupts are enabled when the first task starts. */
 | 
			
		||||
            "   bx   r4                                     \n"/* Finally, branch to EXC_RETURN. */
 | 
			
		||||
        #else /* configENABLE_MPU */
 | 
			
		||||
            "   ldm  r0!, {r1-r3}                           \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
 | 
			
		||||
            "   ldr  r4, xSecureContextConst2               \n"
 | 
			
		||||
            "   str  r1, [r4]                               \n"/* Set xSecureContext to this task's value for the same. */
 | 
			
		||||
            "   msr  psplim, r2                             \n"/* Set this task's PSPLIM value. */
 | 
			
		||||
            "   movs r1, #2                                 \n"/* r1 = 2. */
 | 
			
		||||
            "   msr  CONTROL, r1                            \n"/* Switch to use PSP in the thread mode. */
 | 
			
		||||
            "   adds r0, #32                                \n"/* Discard everything up to r0. */
 | 
			
		||||
            "   msr  psp, r0                                \n"/* This is now the new top of stack to use in the task. */
 | 
			
		||||
            "   isb                                         \n"
 | 
			
		||||
            "   mov  r0, #0                                 \n"
 | 
			
		||||
            "   msr  basepri, r0                            \n"/* Ensure that interrupts are enabled when the first task starts. */
 | 
			
		||||
            "   bx   r3                                     \n"/* Finally, branch to EXC_RETURN. */
 | 
			
		||||
        #endif /* configENABLE_MPU */
 | 
			
		||||
        "                                                   \n"
 | 
			
		||||
        "   .align 4                                        \n"
 | 
			
		||||
        "pxCurrentTCBConst2: .word pxCurrentTCB             \n"
 | 
			
		||||
        "xSecureContextConst2: .word xSecureContext         \n"
 | 
			
		||||
        #if ( configENABLE_MPU == 1 )
 | 
			
		||||
            "xMPUCTRLConst2: .word 0xe000ed94               \n"
 | 
			
		||||
            "xMAIR0Const2: .word 0xe000edc0                 \n"
 | 
			
		||||
            "xRNRConst2: .word 0xe000ed98                   \n"
 | 
			
		||||
            "xRBARConst2: .word 0xe000ed9c                  \n"
 | 
			
		||||
        #endif /* configENABLE_MPU */
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
 | 
			
		||||
{
 | 
			
		||||
    __asm volatile
 | 
			
		||||
    (
 | 
			
		||||
        "   .syntax unified                                 \n"
 | 
			
		||||
        "                                                   \n"
 | 
			
		||||
        "   mrs r0, control                                 \n"/* r0 = CONTROL. */
 | 
			
		||||
        "   tst r0, #1                                      \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
 | 
			
		||||
        "   ite ne                                          \n"
 | 
			
		||||
        "   movne r0, #0                                    \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
 | 
			
		||||
        "   moveq r0, #1                                    \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
 | 
			
		||||
        "   bx lr                                           \n"/* Return. */
 | 
			
		||||
        "                                                   \n"
 | 
			
		||||
        "   .align 4                                        \n"
 | 
			
		||||
        ::: "r0", "memory"
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
 | 
			
		||||
{
 | 
			
		||||
    __asm volatile
 | 
			
		||||
    (
 | 
			
		||||
        "   .syntax unified                                 \n"
 | 
			
		||||
        "                                                   \n"
 | 
			
		||||
        "   mrs r0, control                                 \n"/* Read the CONTROL register. */
 | 
			
		||||
        "   bic r0, #1                                      \n"/* Clear the bit 0. */
 | 
			
		||||
        "   msr control, r0                                 \n"/* Write back the new CONTROL value. */
 | 
			
		||||
        "   bx lr                                           \n"/* Return to the caller. */
 | 
			
		||||
        ::: "r0", "memory"
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
void vResetPrivilege( void ) /* __attribute__ (( naked )) */
 | 
			
		||||
{
 | 
			
		||||
    __asm volatile
 | 
			
		||||
    (
 | 
			
		||||
        "   .syntax unified                                 \n"
 | 
			
		||||
        "                                                   \n"
 | 
			
		||||
        "   mrs r0, control                                 \n"/* r0 = CONTROL. */
 | 
			
		||||
        "   orr r0, #1                                      \n"/* r0 = r0 | 1. */
 | 
			
		||||
        "   msr control, r0                                 \n"/* CONTROL = r0. */
 | 
			
		||||
        "   bx lr                                           \n"/* Return to the caller. */
 | 
			
		||||
        ::: "r0", "memory"
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
 | 
			
		||||
{
 | 
			
		||||
    __asm volatile
 | 
			
		||||
    (
 | 
			
		||||
        "   .syntax unified                                 \n"
 | 
			
		||||
        "                                                   \n"
 | 
			
		||||
        "   ldr r0, xVTORConst                              \n"/* Use the NVIC offset register to locate the stack. */
 | 
			
		||||
        "   ldr r0, [r0]                                    \n"/* Read the VTOR register which gives the address of vector table. */
 | 
			
		||||
        "   ldr r0, [r0]                                    \n"/* The first entry in vector table is stack pointer. */
 | 
			
		||||
        "   msr msp, r0                                     \n"/* Set the MSP back to the start of the stack. */
 | 
			
		||||
        "   cpsie i                                         \n"/* Globally enable interrupts. */
 | 
			
		||||
        "   cpsie f                                         \n"
 | 
			
		||||
        "   dsb                                             \n"
 | 
			
		||||
        "   isb                                             \n"
 | 
			
		||||
        "   svc %0                                          \n"/* System call to start the first task. */
 | 
			
		||||
        "   nop                                             \n"
 | 
			
		||||
        "                                                   \n"
 | 
			
		||||
        "   .align 4                                        \n"
 | 
			
		||||
        "xVTORConst: .word 0xe000ed08                       \n"
 | 
			
		||||
        ::"i" ( portSVC_START_SCHEDULER ) : "memory"
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
 | 
			
		||||
{
 | 
			
		||||
    __asm volatile
 | 
			
		||||
    (
 | 
			
		||||
        "   .syntax unified                                 \n"
 | 
			
		||||
        "                                                   \n"
 | 
			
		||||
        "   mrs r0, basepri                                 \n"/* r0 = basepri. Return original basepri value. */
 | 
			
		||||
        "   mov r1, %0                                      \n"/* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */
 | 
			
		||||
        "   msr basepri, r1                                 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
 | 
			
		||||
        "   dsb                                             \n"
 | 
			
		||||
        "   isb                                             \n"
 | 
			
		||||
        "   bx lr                                           \n"/* Return. */
 | 
			
		||||
        ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
 | 
			
		||||
{
 | 
			
		||||
    __asm volatile
 | 
			
		||||
    (
 | 
			
		||||
        "   .syntax unified                                 \n"
 | 
			
		||||
        "                                                   \n"
 | 
			
		||||
        "   msr basepri, r0                                 \n"/* basepri = ulMask. */
 | 
			
		||||
        "   dsb                                             \n"
 | 
			
		||||
        "   isb                                             \n"
 | 
			
		||||
        "   bx lr                                           \n"/* Return. */
 | 
			
		||||
        ::: "memory"
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
 | 
			
		||||
{
 | 
			
		||||
    __asm volatile
 | 
			
		||||
    (
 | 
			
		||||
        "   .syntax unified                                 \n"
 | 
			
		||||
        "   .extern SecureContext_SaveContext               \n"
 | 
			
		||||
        "   .extern SecureContext_LoadContext               \n"
 | 
			
		||||
        "                                                   \n"
 | 
			
		||||
        "   ldr r3, xSecureContextConst                     \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
 | 
			
		||||
        "   ldr r0, [r3]                                    \n"/* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
 | 
			
		||||
        "   ldr r3, pxCurrentTCBConst                       \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
 | 
			
		||||
        "   ldr r1, [r3]                                    \n"/* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later. */
 | 
			
		||||
        "   mrs r2, psp                                     \n"/* Read PSP in r2. */
 | 
			
		||||
        "                                                   \n"
 | 
			
		||||
        "   cbz r0, save_ns_context                         \n"/* No secure context to save. */
 | 
			
		||||
        "   push {r0-r2, r14}                               \n"
 | 
			
		||||
        "   bl SecureContext_SaveContext                    \n"/* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
 | 
			
		||||
        "   pop {r0-r3}                                     \n"/* LR is now in r3. */
 | 
			
		||||
        "   mov lr, r3                                      \n"/* LR = r3. */
 | 
			
		||||
        "   lsls r1, r3, #25                                \n"/* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
 | 
			
		||||
        "   bpl save_ns_context                             \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
 | 
			
		||||
        "                                                   \n"
 | 
			
		||||
        "   ldr r3, pxCurrentTCBConst                       \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
 | 
			
		||||
        "   ldr r1, [r3]                                    \n"/* Read pxCurrentTCB.*/
 | 
			
		||||
        #if ( configENABLE_MPU == 1 )
 | 
			
		||||
            "   subs r2, r2, #16                            \n"/* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */
 | 
			
		||||
            "   str r2, [r1]                                \n"/* Save the new top of stack in TCB. */
 | 
			
		||||
            "   mrs r1, psplim                              \n"/* r1 = PSPLIM. */
 | 
			
		||||
            "   mrs r3, control                             \n"/* r3 = CONTROL. */
 | 
			
		||||
            "   mov r4, lr                                  \n"/* r4 = LR/EXC_RETURN. */
 | 
			
		||||
            "   stmia r2!, {r0, r1, r3, r4}                 \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
 | 
			
		||||
        #else /* configENABLE_MPU */
 | 
			
		||||
            "   subs r2, r2, #12                            \n"/* Make space for xSecureContext, PSPLIM and LR on the stack. */
 | 
			
		||||
            "   str r2, [r1]                                \n"/* Save the new top of stack in TCB. */
 | 
			
		||||
            "   mrs r1, psplim                              \n"/* r1 = PSPLIM. */
 | 
			
		||||
            "   mov r3, lr                                  \n"/* r3 = LR/EXC_RETURN. */
 | 
			
		||||
            "   stmia r2!, {r0, r1, r3}                     \n"/* Store xSecureContext, PSPLIM and LR on the stack. */
 | 
			
		||||
        #endif /* configENABLE_MPU */
 | 
			
		||||
        "   b select_next_task                              \n"
 | 
			
		||||
        "                                                   \n"
 | 
			
		||||
        " save_ns_context:                                  \n"
 | 
			
		||||
        "   ldr r3, pxCurrentTCBConst                       \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
 | 
			
		||||
        "   ldr r1, [r3]                                    \n"/* Read pxCurrentTCB. */
 | 
			
		||||
        #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
 | 
			
		||||
            "   tst lr, #0x10                               \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
 | 
			
		||||
            "   it eq                                       \n"
 | 
			
		||||
            "   vstmdbeq r2!, {s16-s31}                     \n"/* Store the additional FP context registers which are not saved automatically. */
 | 
			
		||||
        #endif /* configENABLE_FPU || configENABLE_MVE */
 | 
			
		||||
        #if ( configENABLE_MPU == 1 )
 | 
			
		||||
            "   subs r2, r2, #48                            \n"/* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */
 | 
			
		||||
            "   str r2, [r1]                                \n"/* Save the new top of stack in TCB. */
 | 
			
		||||
            "   adds r2, r2, #16                            \n"/* r2 = r2 + 16. */
 | 
			
		||||
            "   stm r2, {r4-r11}                            \n"/* Store the registers that are not saved automatically. */
 | 
			
		||||
            "   mrs r1, psplim                              \n"/* r1 = PSPLIM. */
 | 
			
		||||
            "   mrs r3, control                             \n"/* r3 = CONTROL. */
 | 
			
		||||
            "   mov r4, lr                                  \n"/* r4 = LR/EXC_RETURN. */
 | 
			
		||||
            "   subs r2, r2, #16                            \n"/* r2 = r2 - 16. */
 | 
			
		||||
            "   stmia r2!, {r0, r1, r3, r4}                 \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
 | 
			
		||||
        #else /* configENABLE_MPU */
 | 
			
		||||
            "   subs r2, r2, #44                            \n"/* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */
 | 
			
		||||
            "   str r2, [r1]                                \n"/* Save the new top of stack in TCB. */
 | 
			
		||||
            "   adds r2, r2, #12                            \n"/* r2 = r2 + 12. */
 | 
			
		||||
            "   stm r2, {r4-r11}                            \n"/* Store the registers that are not saved automatically. */
 | 
			
		||||
            "   mrs r1, psplim                              \n"/* r1 = PSPLIM. */
 | 
			
		||||
            "   mov r3, lr                                  \n"/* r3 = LR/EXC_RETURN. */
 | 
			
		||||
            "   subs r2, r2, #12                            \n"/* r2 = r2 - 12. */
 | 
			
		||||
            "   stmia r2!, {r0, r1, r3}                     \n"/* Store xSecureContext, PSPLIM and LR on the stack. */
 | 
			
		||||
        #endif /* configENABLE_MPU */
 | 
			
		||||
        "                                                   \n"
 | 
			
		||||
        " select_next_task:                                 \n"
 | 
			
		||||
        "   mov r0, %0                                      \n"/* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
 | 
			
		||||
        "   msr basepri, r0                                 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
 | 
			
		||||
        "   dsb                                             \n"
 | 
			
		||||
        "   isb                                             \n"
 | 
			
		||||
        "   bl vTaskSwitchContext                           \n"
 | 
			
		||||
        "   mov r0, #0                                      \n"/* r0 = 0. */
 | 
			
		||||
        "   msr basepri, r0                                 \n"/* Enable interrupts. */
 | 
			
		||||
        "                                                   \n"
 | 
			
		||||
        "   ldr r3, pxCurrentTCBConst                       \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
 | 
			
		||||
        "   ldr r1, [r3]                                    \n"/* Read pxCurrentTCB. */
 | 
			
		||||
        "   ldr r2, [r1]                                    \n"/* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
 | 
			
		||||
        "                                                   \n"
 | 
			
		||||
        #if ( configENABLE_MPU == 1 )
 | 
			
		||||
            "   dmb                                         \n"/* Complete outstanding transfers before disabling MPU. */
 | 
			
		||||
            "   ldr r3, xMPUCTRLConst                       \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
 | 
			
		||||
            "   ldr r4, [r3]                                \n"/* Read the value of MPU_CTRL. */
 | 
			
		||||
            "   bic r4, #1                                  \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
 | 
			
		||||
            "   str r4, [r3]                                \n"/* Disable MPU. */
 | 
			
		||||
            "                                               \n"
 | 
			
		||||
            "   adds r1, #4                                 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
 | 
			
		||||
            "   ldr r4, [r1]                                \n"/* r4 = *r1 i.e. r4 = MAIR0. */
 | 
			
		||||
            "   ldr r3, xMAIR0Const                         \n"/* r3 = 0xe000edc0 [Location of MAIR0]. */
 | 
			
		||||
            "   str r4, [r3]                                \n"/* Program MAIR0. */
 | 
			
		||||
            "   ldr r3, xRNRConst                           \n"/* r3 = 0xe000ed98 [Location of RNR]. */
 | 
			
		||||
            "   movs r4, #4                                 \n"/* r4 = 4. */
 | 
			
		||||
            "   str r4, [r3]                                \n"/* Program RNR = 4. */
 | 
			
		||||
            "   adds r1, #4                                 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
 | 
			
		||||
            "   ldr r3, xRBARConst                          \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
 | 
			
		||||
            "   ldmia r1!, {r4-r11}                         \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
 | 
			
		||||
            "   stmia r3!, {r4-r11}                         \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
 | 
			
		||||
            "                                               \n"
 | 
			
		||||
            #if ( configTOTAL_MPU_REGIONS == 16 )
 | 
			
		||||
            "   ldr r3, xRNRConst                           \n"/* r3 = 0xe000ed98 [Location of RNR]. */
 | 
			
		||||
            "   movs r4, #8                                 \n"/* r4 = 8. */
 | 
			
		||||
            "   str r4, [r3]                                \n"/* Program RNR = 8. */
 | 
			
		||||
            "   ldr r3, xRBARConst                          \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
 | 
			
		||||
            "   ldmia r1!, {r4-r11}                         \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
 | 
			
		||||
            "   stmia r3!, {r4-r11}                         \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
 | 
			
		||||
            "   ldr r3, xRNRConst                           \n"/* r3 = 0xe000ed98 [Location of RNR]. */
 | 
			
		||||
            "   movs r4, #12                                \n"/* r4 = 12. */
 | 
			
		||||
            "   str r4, [r3]                                \n"/* Program RNR = 12. */
 | 
			
		||||
            "   ldr r3, xRBARConst                          \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
 | 
			
		||||
            "   ldmia r1!, {r4-r11}                         \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
 | 
			
		||||
            "   stmia r3!, {r4-r11}                         \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
 | 
			
		||||
            #endif /* configTOTAL_MPU_REGIONS == 16 */
 | 
			
		||||
            "                                               \n"
 | 
			
		||||
            "   ldr r3, xMPUCTRLConst                       \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
 | 
			
		||||
            "   ldr r4, [r3]                                \n"/* Read the value of MPU_CTRL. */
 | 
			
		||||
            "   orr r4, #1                                  \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
 | 
			
		||||
            "   str r4, [r3]                                \n"/* Enable MPU. */
 | 
			
		||||
            "   dsb                                         \n"/* Force memory writes before continuing. */
 | 
			
		||||
        #endif /* configENABLE_MPU */
 | 
			
		||||
        "                                                   \n"
 | 
			
		||||
        #if ( configENABLE_MPU == 1 )
 | 
			
		||||
            "   ldmia r2!, {r0, r1, r3, r4}                 \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM, r3 = CONTROL and r4 = LR. */
 | 
			
		||||
            "   msr psplim, r1                              \n"/* Restore the PSPLIM register value for the task. */
 | 
			
		||||
            "   msr control, r3                             \n"/* Restore the CONTROL register value for the task. */
 | 
			
		||||
            "   mov lr, r4                                  \n"/* LR = r4. */
 | 
			
		||||
            "   ldr r3, xSecureContextConst                 \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
 | 
			
		||||
            "   str r0, [r3]                                \n"/* Restore the task's xSecureContext. */
 | 
			
		||||
            "   cbz r0, restore_ns_context                  \n"/* If there is no secure context for the task, restore the non-secure context. */
 | 
			
		||||
            "   ldr r3, pxCurrentTCBConst                   \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
 | 
			
		||||
            "   ldr r1, [r3]                                \n"/* Read pxCurrentTCB. */
 | 
			
		||||
            "   push {r2, r4}                               \n"
 | 
			
		||||
            "   bl SecureContext_LoadContext                \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
 | 
			
		||||
            "   pop {r2, r4}                                \n"
 | 
			
		||||
            "   mov lr, r4                                  \n"/* LR = r4. */
 | 
			
		||||
            "   lsls r1, r4, #25                            \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
 | 
			
		||||
            "   bpl restore_ns_context                      \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
 | 
			
		||||
            "   msr psp, r2                                 \n"/* Remember the new top of stack for the task. */
 | 
			
		||||
            "   bx lr                                       \n"
 | 
			
		||||
        #else /* configENABLE_MPU */
 | 
			
		||||
            "   ldmia r2!, {r0, r1, r4}                     \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */
 | 
			
		||||
            "   msr psplim, r1                              \n"/* Restore the PSPLIM register value for the task. */
 | 
			
		||||
            "   mov lr, r4                                  \n"/* LR = r4. */
 | 
			
		||||
            "   ldr r3, xSecureContextConst                 \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
 | 
			
		||||
            "   str r0, [r3]                                \n"/* Restore the task's xSecureContext. */
 | 
			
		||||
            "   cbz r0, restore_ns_context                  \n"/* If there is no secure context for the task, restore the non-secure context. */
 | 
			
		||||
            "   ldr r3, pxCurrentTCBConst                   \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
 | 
			
		||||
            "   ldr r1, [r3]                                \n"/* Read pxCurrentTCB. */
 | 
			
		||||
            "   push {r2, r4}                               \n"
 | 
			
		||||
            "   bl SecureContext_LoadContext                \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
 | 
			
		||||
            "   pop {r2, r4}                                \n"
 | 
			
		||||
            "   mov lr, r4                                  \n"/* LR = r4. */
 | 
			
		||||
            "   lsls r1, r4, #25                            \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
 | 
			
		||||
            "   bpl restore_ns_context                      \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
 | 
			
		||||
            "   msr psp, r2                                 \n"/* Remember the new top of stack for the task. */
 | 
			
		||||
            "   bx lr                                       \n"
 | 
			
		||||
        #endif /* configENABLE_MPU */
 | 
			
		||||
        "                                                   \n"
 | 
			
		||||
        " restore_ns_context:                               \n"
 | 
			
		||||
        "   ldmia r2!, {r4-r11}                             \n"/* Restore the registers that are not automatically restored. */
 | 
			
		||||
        #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
 | 
			
		||||
            "   tst lr, #0x10                               \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
 | 
			
		||||
            "   it eq                                       \n"
 | 
			
		||||
            "   vldmiaeq r2!, {s16-s31}                     \n"/* Restore the additional FP context registers which are not restored automatically. */
 | 
			
		||||
        #endif /* configENABLE_FPU || configENABLE_MVE */
 | 
			
		||||
        "   msr psp, r2                                     \n"/* Remember the new top of stack for the task. */
 | 
			
		||||
        "   bx lr                                           \n"
 | 
			
		||||
        "                                                   \n"
 | 
			
		||||
        "   .align 4                                        \n"
 | 
			
		||||
        "pxCurrentTCBConst: .word pxCurrentTCB              \n"
 | 
			
		||||
        "xSecureContextConst: .word xSecureContext          \n"
 | 
			
		||||
        #if ( configENABLE_MPU == 1 )
 | 
			
		||||
            "xMPUCTRLConst: .word 0xe000ed94                \n"
 | 
			
		||||
            "xMAIR0Const: .word 0xe000edc0                  \n"
 | 
			
		||||
            "xRNRConst: .word 0xe000ed98                    \n"
 | 
			
		||||
            "xRBARConst: .word 0xe000ed9c                   \n"
 | 
			
		||||
        #endif /* configENABLE_MPU */
 | 
			
		||||
        ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
 | 
			
		||||
{
 | 
			
		||||
    __asm volatile
 | 
			
		||||
    (
 | 
			
		||||
        "   .syntax unified                                 \n"
 | 
			
		||||
        "                                                   \n"
 | 
			
		||||
        "   tst lr, #4                                      \n"
 | 
			
		||||
        "   ite eq                                          \n"
 | 
			
		||||
        "   mrseq r0, msp                                   \n"
 | 
			
		||||
        "   mrsne r0, psp                                   \n"
 | 
			
		||||
        "   ldr r1, svchandler_address_const                \n"
 | 
			
		||||
        "   bx r1                                           \n"
 | 
			
		||||
        "                                                   \n"
 | 
			
		||||
        "   .align 4                                        \n"
 | 
			
		||||
        "svchandler_address_const: .word vPortSVCHandler_C  \n"
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) /* __attribute__ (( naked )) */
 | 
			
		||||
{
 | 
			
		||||
    __asm volatile
 | 
			
		||||
    (
 | 
			
		||||
        "   .syntax unified                                 \n"
 | 
			
		||||
        "                                                   \n"
 | 
			
		||||
        "   svc %0                                          \n"/* Secure context is allocated in the supervisor call. */
 | 
			
		||||
        "   bx lr                                           \n"/* Return. */
 | 
			
		||||
        ::"i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory"
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
 | 
			
		||||
{
 | 
			
		||||
    __asm volatile
 | 
			
		||||
    (
 | 
			
		||||
        "   .syntax unified                                 \n"
 | 
			
		||||
        "                                                   \n"
 | 
			
		||||
        "   ldr r2, [r0]                                    \n"/* The first item in the TCB is the top of the stack. */
 | 
			
		||||
        "   ldr r1, [r2]                                    \n"/* The first item on the stack is the task's xSecureContext. */
 | 
			
		||||
        "   cmp r1, #0                                      \n"/* Raise svc if task's xSecureContext is not NULL. */
 | 
			
		||||
        "   it ne                                           \n"
 | 
			
		||||
        "   svcne %0                                        \n"/* Secure context is freed in the supervisor call. */
 | 
			
		||||
        "   bx lr                                           \n"/* Return. */
 | 
			
		||||
        ::"i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory"
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,114 +1,114 @@
 | 
			
		|||
/*
 | 
			
		||||
 * FreeRTOS Kernel <DEVELOPMENT BRANCH>
 | 
			
		||||
 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: MIT
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 | 
			
		||||
 * this software and associated documentation files (the "Software"), to deal in
 | 
			
		||||
 * the Software without restriction, including without limitation the rights to
 | 
			
		||||
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 | 
			
		||||
 * the Software, and to permit persons to whom the Software is furnished to do so,
 | 
			
		||||
 * subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
 * copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 | 
			
		||||
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 | 
			
		||||
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 | 
			
		||||
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
			
		||||
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 *
 | 
			
		||||
 * https://www.FreeRTOS.org
 | 
			
		||||
 * https://github.com/FreeRTOS
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __PORT_ASM_H__
 | 
			
		||||
#define __PORT_ASM_H__
 | 
			
		||||
 | 
			
		||||
/* Scheduler includes. */
 | 
			
		||||
#include "FreeRTOS.h"
 | 
			
		||||
 | 
			
		||||
/* MPU wrappers includes. */
 | 
			
		||||
#include "mpu_wrappers.h"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Restore the context of the first task so that the first task starts
 | 
			
		||||
 * executing.
 | 
			
		||||
 */
 | 
			
		||||
void vRestoreContextOfFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Checks whether or not the processor is privileged.
 | 
			
		||||
 *
 | 
			
		||||
 * @return 1 if the processor is already privileged, 0 otherwise.
 | 
			
		||||
 */
 | 
			
		||||
BaseType_t xIsPrivileged( void ) __attribute__( ( naked ) );
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Raises the privilege level by clearing the bit 0 of the CONTROL
 | 
			
		||||
 * register.
 | 
			
		||||
 *
 | 
			
		||||
 * @note This is a privileged function and should only be called from the kenrel
 | 
			
		||||
 * code.
 | 
			
		||||
 *
 | 
			
		||||
 * Bit 0 of the CONTROL register defines the privilege level of Thread Mode.
 | 
			
		||||
 *  Bit[0] = 0 --> The processor is running privileged
 | 
			
		||||
 *  Bit[0] = 1 --> The processor is running unprivileged.
 | 
			
		||||
 */
 | 
			
		||||
void vRaisePrivilege( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Lowers the privilege level by setting the bit 0 of the CONTROL
 | 
			
		||||
 * register.
 | 
			
		||||
 *
 | 
			
		||||
 * Bit 0 of the CONTROL register defines the privilege level of Thread Mode.
 | 
			
		||||
 *  Bit[0] = 0 --> The processor is running privileged
 | 
			
		||||
 *  Bit[0] = 1 --> The processor is running unprivileged.
 | 
			
		||||
 */
 | 
			
		||||
void vResetPrivilege( void ) __attribute__( ( naked ) );
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Starts the first task.
 | 
			
		||||
 */
 | 
			
		||||
void vStartFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Disables interrupts.
 | 
			
		||||
 */
 | 
			
		||||
uint32_t ulSetInterruptMask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Enables interrupts.
 | 
			
		||||
 */
 | 
			
		||||
void vClearInterruptMask( uint32_t ulMask ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief PendSV Exception handler.
 | 
			
		||||
 */
 | 
			
		||||
void PendSV_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief SVC Handler.
 | 
			
		||||
 */
 | 
			
		||||
void SVC_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Allocate a Secure context for the calling task.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] ulSecureStackSize The size of the stack to be allocated on the
 | 
			
		||||
 * secure side for the calling task.
 | 
			
		||||
 */
 | 
			
		||||
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) __attribute__( ( naked ) );
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Free the task's secure context.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] pulTCB Pointer to the Task Control Block (TCB) of the task.
 | 
			
		||||
 */
 | 
			
		||||
void vPortFreeSecureContext( uint32_t * pulTCB ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
 | 
			
		||||
 | 
			
		||||
#endif /* __PORT_ASM_H__ */
 | 
			
		||||
/*
 | 
			
		||||
 * FreeRTOS Kernel <DEVELOPMENT BRANCH>
 | 
			
		||||
 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: MIT
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 | 
			
		||||
 * this software and associated documentation files (the "Software"), to deal in
 | 
			
		||||
 * the Software without restriction, including without limitation the rights to
 | 
			
		||||
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 | 
			
		||||
 * the Software, and to permit persons to whom the Software is furnished to do so,
 | 
			
		||||
 * subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
 * copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 | 
			
		||||
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 | 
			
		||||
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 | 
			
		||||
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
			
		||||
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 *
 | 
			
		||||
 * https://www.FreeRTOS.org
 | 
			
		||||
 * https://github.com/FreeRTOS
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __PORT_ASM_H__
 | 
			
		||||
#define __PORT_ASM_H__
 | 
			
		||||
 | 
			
		||||
/* Scheduler includes. */
 | 
			
		||||
#include "FreeRTOS.h"
 | 
			
		||||
 | 
			
		||||
/* MPU wrappers includes. */
 | 
			
		||||
#include "mpu_wrappers.h"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Restore the context of the first task so that the first task starts
 | 
			
		||||
 * executing.
 | 
			
		||||
 */
 | 
			
		||||
void vRestoreContextOfFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Checks whether or not the processor is privileged.
 | 
			
		||||
 *
 | 
			
		||||
 * @return 1 if the processor is already privileged, 0 otherwise.
 | 
			
		||||
 */
 | 
			
		||||
BaseType_t xIsPrivileged( void ) __attribute__( ( naked ) );
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Raises the privilege level by clearing the bit 0 of the CONTROL
 | 
			
		||||
 * register.
 | 
			
		||||
 *
 | 
			
		||||
 * @note This is a privileged function and should only be called from the kenrel
 | 
			
		||||
 * code.
 | 
			
		||||
 *
 | 
			
		||||
 * Bit 0 of the CONTROL register defines the privilege level of Thread Mode.
 | 
			
		||||
 *  Bit[0] = 0 --> The processor is running privileged
 | 
			
		||||
 *  Bit[0] = 1 --> The processor is running unprivileged.
 | 
			
		||||
 */
 | 
			
		||||
void vRaisePrivilege( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Lowers the privilege level by setting the bit 0 of the CONTROL
 | 
			
		||||
 * register.
 | 
			
		||||
 *
 | 
			
		||||
 * Bit 0 of the CONTROL register defines the privilege level of Thread Mode.
 | 
			
		||||
 *  Bit[0] = 0 --> The processor is running privileged
 | 
			
		||||
 *  Bit[0] = 1 --> The processor is running unprivileged.
 | 
			
		||||
 */
 | 
			
		||||
void vResetPrivilege( void ) __attribute__( ( naked ) );
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Starts the first task.
 | 
			
		||||
 */
 | 
			
		||||
void vStartFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Disables interrupts.
 | 
			
		||||
 */
 | 
			
		||||
uint32_t ulSetInterruptMask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Enables interrupts.
 | 
			
		||||
 */
 | 
			
		||||
void vClearInterruptMask( uint32_t ulMask ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief PendSV Exception handler.
 | 
			
		||||
 */
 | 
			
		||||
void PendSV_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief SVC Handler.
 | 
			
		||||
 */
 | 
			
		||||
void SVC_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Allocate a Secure context for the calling task.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] ulSecureStackSize The size of the stack to be allocated on the
 | 
			
		||||
 * secure side for the calling task.
 | 
			
		||||
 */
 | 
			
		||||
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) __attribute__( ( naked ) );
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Free the task's secure context.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] pulTCB Pointer to the Task Control Block (TCB) of the task.
 | 
			
		||||
 */
 | 
			
		||||
void vPortFreeSecureContext( uint32_t * pulTCB ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
 | 
			
		||||
 | 
			
		||||
#endif /* __PORT_ASM_H__ */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,66 +1,66 @@
 | 
			
		|||
/*
 | 
			
		||||
 * FreeRTOS Kernel <DEVELOPMENT BRANCH>
 | 
			
		||||
 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: MIT
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 | 
			
		||||
 * this software and associated documentation files (the "Software"), to deal in
 | 
			
		||||
 * the Software without restriction, including without limitation the rights to
 | 
			
		||||
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 | 
			
		||||
 * the Software, and to permit persons to whom the Software is furnished to do so,
 | 
			
		||||
 * subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
 * copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 | 
			
		||||
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 | 
			
		||||
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 | 
			
		||||
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
			
		||||
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 *
 | 
			
		||||
 * https://www.FreeRTOS.org
 | 
			
		||||
 * https://github.com/FreeRTOS
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef PORTMACRO_H
 | 
			
		||||
#define PORTMACRO_H
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
    extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "portmacrocommon.h"
 | 
			
		||||
 | 
			
		||||
/*------------------------------------------------------------------------------
 | 
			
		||||
 * Port specific definitions.
 | 
			
		||||
 *
 | 
			
		||||
 * The settings in this file configure FreeRTOS correctly for the given hardware
 | 
			
		||||
 * and compiler.
 | 
			
		||||
 *
 | 
			
		||||
 * These settings should not be altered.
 | 
			
		||||
 *------------------------------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Architecture specifics.
 | 
			
		||||
 */
 | 
			
		||||
#define portARCH_NAME                       "Cortex-M33"
 | 
			
		||||
#define portDONT_DISCARD                    __attribute__( ( used ) )
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Critical section management.
 | 
			
		||||
 */
 | 
			
		||||
#define portDISABLE_INTERRUPTS()            ulSetInterruptMask()
 | 
			
		||||
#define portENABLE_INTERRUPTS()             vClearInterruptMask( 0 )
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* PORTMACRO_H */
 | 
			
		||||
/*
 | 
			
		||||
 * FreeRTOS Kernel <DEVELOPMENT BRANCH>
 | 
			
		||||
 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: MIT
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 | 
			
		||||
 * this software and associated documentation files (the "Software"), to deal in
 | 
			
		||||
 * the Software without restriction, including without limitation the rights to
 | 
			
		||||
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 | 
			
		||||
 * the Software, and to permit persons to whom the Software is furnished to do so,
 | 
			
		||||
 * subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
 * copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 | 
			
		||||
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 | 
			
		||||
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 | 
			
		||||
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
			
		||||
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 *
 | 
			
		||||
 * https://www.FreeRTOS.org
 | 
			
		||||
 * https://github.com/FreeRTOS
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef PORTMACRO_H
 | 
			
		||||
#define PORTMACRO_H
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
    extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "portmacrocommon.h"
 | 
			
		||||
 | 
			
		||||
/*------------------------------------------------------------------------------
 | 
			
		||||
 * Port specific definitions.
 | 
			
		||||
 *
 | 
			
		||||
 * The settings in this file configure FreeRTOS correctly for the given hardware
 | 
			
		||||
 * and compiler.
 | 
			
		||||
 *
 | 
			
		||||
 * These settings should not be altered.
 | 
			
		||||
 *------------------------------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Architecture specifics.
 | 
			
		||||
 */
 | 
			
		||||
#define portARCH_NAME                       "Cortex-M33"
 | 
			
		||||
#define portDONT_DISCARD                    __attribute__( ( used ) )
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Critical section management.
 | 
			
		||||
 */
 | 
			
		||||
#define portDISABLE_INTERRUPTS()            ulSetInterruptMask()
 | 
			
		||||
#define portENABLE_INTERRUPTS()             vClearInterruptMask( 0 )
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* PORTMACRO_H */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -155,9 +155,9 @@
 | 
			
		|||
 * 8-bit values encoded as follows:
 | 
			
		||||
 *  Bit[7:4] - 0000 - Device Memory
 | 
			
		||||
 *  Bit[3:2] - 00 --> Device-nGnRnE
 | 
			
		||||
 *				01 --> Device-nGnRE
 | 
			
		||||
 *				10 --> Device-nGRE
 | 
			
		||||
 *				11 --> Device-GRE
 | 
			
		||||
 *              01 --> Device-nGnRE
 | 
			
		||||
 *              10 --> Device-nGRE
 | 
			
		||||
 *              11 --> Device-GRE
 | 
			
		||||
 *  Bit[1:0] - 00, Reserved.
 | 
			
		||||
 */
 | 
			
		||||
    #define portMPU_DEVICE_MEMORY_nGnRnE                  ( 0x00 )   /* 0000 0000 */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,351 +1,351 @@
 | 
			
		|||
/*
 | 
			
		||||
 * FreeRTOS Kernel <DEVELOPMENT BRANCH>
 | 
			
		||||
 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: MIT
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 | 
			
		||||
 * this software and associated documentation files (the "Software"), to deal in
 | 
			
		||||
 * the Software without restriction, including without limitation the rights to
 | 
			
		||||
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 | 
			
		||||
 * the Software, and to permit persons to whom the Software is furnished to do so,
 | 
			
		||||
 * subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
 * copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 | 
			
		||||
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 | 
			
		||||
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 | 
			
		||||
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
			
		||||
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 *
 | 
			
		||||
 * https://www.FreeRTOS.org
 | 
			
		||||
 * https://github.com/FreeRTOS
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Secure context includes. */
 | 
			
		||||
#include "secure_context.h"
 | 
			
		||||
 | 
			
		||||
/* Secure heap includes. */
 | 
			
		||||
#include "secure_heap.h"
 | 
			
		||||
 | 
			
		||||
/* Secure port macros. */
 | 
			
		||||
#include "secure_port_macros.h"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief CONTROL value for privileged tasks.
 | 
			
		||||
 *
 | 
			
		||||
 * Bit[0] - 0 --> Thread mode is privileged.
 | 
			
		||||
 * Bit[1] - 1 --> Thread mode uses PSP.
 | 
			
		||||
 */
 | 
			
		||||
#define securecontextCONTROL_VALUE_PRIVILEGED      0x02
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief CONTROL value for un-privileged tasks.
 | 
			
		||||
 *
 | 
			
		||||
 * Bit[0] - 1 --> Thread mode is un-privileged.
 | 
			
		||||
 * Bit[1] - 1 --> Thread mode uses PSP.
 | 
			
		||||
 */
 | 
			
		||||
#define securecontextCONTROL_VALUE_UNPRIVILEGED    0x03
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Size of stack seal values in bytes.
 | 
			
		||||
 */
 | 
			
		||||
#define securecontextSTACK_SEAL_SIZE               8
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Stack seal value as recommended by ARM.
 | 
			
		||||
 */
 | 
			
		||||
#define securecontextSTACK_SEAL_VALUE              0xFEF5EDA5
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Maximum number of secure contexts.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef secureconfigMAX_SECURE_CONTEXTS
 | 
			
		||||
    #define secureconfigMAX_SECURE_CONTEXTS        8UL
 | 
			
		||||
#endif
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Pre-allocated array of secure contexts.
 | 
			
		||||
 */
 | 
			
		||||
SecureContext_t xSecureContexts[ secureconfigMAX_SECURE_CONTEXTS ];
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Get a free secure context for a task from the secure context pool (xSecureContexts).
 | 
			
		||||
 *
 | 
			
		||||
 * This function ensures that only one secure context is allocated for a task.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] pvTaskHandle The task handle for which the secure context is allocated.
 | 
			
		||||
 *
 | 
			
		||||
 * @return Index of a free secure context in the xSecureContexts array.
 | 
			
		||||
 */
 | 
			
		||||
static uint32_t ulGetSecureContext( void * pvTaskHandle );
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Return the secure context to the secure context pool (xSecureContexts).
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] ulSecureContextIndex Index of the context in the xSecureContexts array.
 | 
			
		||||
 */
 | 
			
		||||
static void vReturnSecureContext( uint32_t ulSecureContextIndex );
 | 
			
		||||
 | 
			
		||||
/* These are implemented in assembly. */
 | 
			
		||||
extern void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext );
 | 
			
		||||
extern void SecureContext_SaveContextAsm( SecureContext_t * pxSecureContext );
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
static uint32_t ulGetSecureContext( void * pvTaskHandle )
 | 
			
		||||
{
 | 
			
		||||
    /* Start with invalid index. */
 | 
			
		||||
    uint32_t i, ulSecureContextIndex = secureconfigMAX_SECURE_CONTEXTS;
 | 
			
		||||
 | 
			
		||||
    for( i = 0; i < secureconfigMAX_SECURE_CONTEXTS; i++ )
 | 
			
		||||
    {
 | 
			
		||||
        if( ( xSecureContexts[ i ].pucCurrentStackPointer == NULL ) &&
 | 
			
		||||
            ( xSecureContexts[ i ].pucStackLimit == NULL ) &&
 | 
			
		||||
            ( xSecureContexts[ i ].pucStackStart == NULL ) &&
 | 
			
		||||
            ( xSecureContexts[ i ].pvTaskHandle == NULL ) &&
 | 
			
		||||
            ( ulSecureContextIndex == secureconfigMAX_SECURE_CONTEXTS ) )
 | 
			
		||||
        {
 | 
			
		||||
            ulSecureContextIndex = i;
 | 
			
		||||
        }
 | 
			
		||||
        else if( xSecureContexts[ i ].pvTaskHandle == pvTaskHandle )
 | 
			
		||||
        {
 | 
			
		||||
            /* A task can only have one secure context. Do not allocate a second
 | 
			
		||||
             * context for the same task. */
 | 
			
		||||
            ulSecureContextIndex = secureconfigMAX_SECURE_CONTEXTS;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ulSecureContextIndex;
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
static void vReturnSecureContext( uint32_t ulSecureContextIndex )
 | 
			
		||||
{
 | 
			
		||||
    xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer = NULL;
 | 
			
		||||
    xSecureContexts[ ulSecureContextIndex ].pucStackLimit = NULL;
 | 
			
		||||
    xSecureContexts[ ulSecureContextIndex ].pucStackStart = NULL;
 | 
			
		||||
    xSecureContexts[ ulSecureContextIndex ].pvTaskHandle = NULL;
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
secureportNON_SECURE_CALLABLE void SecureContext_Init( void )
 | 
			
		||||
{
 | 
			
		||||
    uint32_t ulIPSR, i;
 | 
			
		||||
    static uint32_t ulSecureContextsInitialized = 0;
 | 
			
		||||
 | 
			
		||||
    /* Read the Interrupt Program Status Register (IPSR) value. */
 | 
			
		||||
    secureportREAD_IPSR( ulIPSR );
 | 
			
		||||
 | 
			
		||||
    /* Do nothing if the processor is running in the Thread Mode. IPSR is zero
 | 
			
		||||
     * when the processor is running in the Thread Mode. */
 | 
			
		||||
    if( ( ulIPSR != 0 ) && ( ulSecureContextsInitialized == 0 ) )
 | 
			
		||||
    {
 | 
			
		||||
        /* Ensure to initialize secure contexts only once. */
 | 
			
		||||
        ulSecureContextsInitialized = 1;
 | 
			
		||||
 | 
			
		||||
        /* No stack for thread mode until a task's context is loaded. */
 | 
			
		||||
        secureportSET_PSPLIM( securecontextNO_STACK );
 | 
			
		||||
        secureportSET_PSP( securecontextNO_STACK );
 | 
			
		||||
 | 
			
		||||
        /* Initialize all secure contexts. */
 | 
			
		||||
        for( i = 0; i < secureconfigMAX_SECURE_CONTEXTS; i++ )
 | 
			
		||||
        {
 | 
			
		||||
            xSecureContexts[ i ].pucCurrentStackPointer = NULL;
 | 
			
		||||
            xSecureContexts[ i ].pucStackLimit = NULL;
 | 
			
		||||
            xSecureContexts[ i ].pucStackStart = NULL;
 | 
			
		||||
            xSecureContexts[ i ].pvTaskHandle = NULL;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #if ( configENABLE_MPU == 1 )
 | 
			
		||||
            {
 | 
			
		||||
                /* Configure thread mode to use PSP and to be unprivileged. */
 | 
			
		||||
                secureportSET_CONTROL( securecontextCONTROL_VALUE_UNPRIVILEGED );
 | 
			
		||||
            }
 | 
			
		||||
        #else /* configENABLE_MPU */
 | 
			
		||||
            {
 | 
			
		||||
                /* Configure thread mode to use PSP and to be privileged. */
 | 
			
		||||
                secureportSET_CONTROL( securecontextCONTROL_VALUE_PRIVILEGED );
 | 
			
		||||
            }
 | 
			
		||||
        #endif /* configENABLE_MPU */
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
#if ( configENABLE_MPU == 1 )
 | 
			
		||||
    secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
 | 
			
		||||
                                                                                       uint32_t ulIsTaskPrivileged,
 | 
			
		||||
                                                                                       void * pvTaskHandle )
 | 
			
		||||
#else /* configENABLE_MPU */
 | 
			
		||||
    secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
 | 
			
		||||
                                                                                       void * pvTaskHandle )
 | 
			
		||||
#endif /* configENABLE_MPU */
 | 
			
		||||
{
 | 
			
		||||
    uint8_t * pucStackMemory = NULL;
 | 
			
		||||
    uint8_t * pucStackLimit;
 | 
			
		||||
    uint32_t ulIPSR, ulSecureContextIndex;
 | 
			
		||||
    SecureContextHandle_t xSecureContextHandle = securecontextINVALID_CONTEXT_ID;
 | 
			
		||||
 | 
			
		||||
    #if ( configENABLE_MPU == 1 )
 | 
			
		||||
        uint32_t * pulCurrentStackPointer = NULL;
 | 
			
		||||
    #endif /* configENABLE_MPU */
 | 
			
		||||
 | 
			
		||||
    /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit
 | 
			
		||||
     * Register (PSPLIM) value. */
 | 
			
		||||
    secureportREAD_IPSR( ulIPSR );
 | 
			
		||||
    secureportREAD_PSPLIM( pucStackLimit );
 | 
			
		||||
 | 
			
		||||
    /* Do nothing if the processor is running in the Thread Mode. IPSR is zero
 | 
			
		||||
     * when the processor is running in the Thread Mode.
 | 
			
		||||
     * Also do nothing, if a secure context us already loaded. PSPLIM is set to
 | 
			
		||||
     * securecontextNO_STACK when no secure context is loaded. */
 | 
			
		||||
    if( ( ulIPSR != 0 ) && ( pucStackLimit == securecontextNO_STACK ) )
 | 
			
		||||
    {
 | 
			
		||||
        /* Ontain a free secure context. */
 | 
			
		||||
        ulSecureContextIndex = ulGetSecureContext( pvTaskHandle );
 | 
			
		||||
 | 
			
		||||
        /* Were we able to get a free context? */
 | 
			
		||||
        if( ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS )
 | 
			
		||||
        {
 | 
			
		||||
            /* Allocate the stack space. */
 | 
			
		||||
            pucStackMemory = pvPortMalloc( ulSecureStackSize + securecontextSTACK_SEAL_SIZE );
 | 
			
		||||
 | 
			
		||||
            if( pucStackMemory != NULL )
 | 
			
		||||
            {
 | 
			
		||||
                /* Since stack grows down, the starting point will be the last
 | 
			
		||||
                 * location. Note that this location is next to the last
 | 
			
		||||
                 * allocated byte for stack (excluding the space for seal values)
 | 
			
		||||
                 * because the hardware decrements the stack pointer before
 | 
			
		||||
                 * writing i.e. if stack pointer is 0x2, a push operation will
 | 
			
		||||
                 * decrement the stack pointer to 0x1 and then write at 0x1. */
 | 
			
		||||
                xSecureContexts[ ulSecureContextIndex ].pucStackStart = pucStackMemory + ulSecureStackSize;
 | 
			
		||||
 | 
			
		||||
                /* Seal the created secure process stack. */
 | 
			
		||||
                *( uint32_t * )( pucStackMemory + ulSecureStackSize ) = securecontextSTACK_SEAL_VALUE;
 | 
			
		||||
                *( uint32_t * )( pucStackMemory + ulSecureStackSize + 4 ) = securecontextSTACK_SEAL_VALUE;
 | 
			
		||||
 | 
			
		||||
                /* The stack cannot go beyond this location. This value is
 | 
			
		||||
                 * programmed in the PSPLIM register on context switch.*/
 | 
			
		||||
                xSecureContexts[ ulSecureContextIndex ].pucStackLimit = pucStackMemory;
 | 
			
		||||
 | 
			
		||||
                xSecureContexts[ ulSecureContextIndex ].pvTaskHandle = pvTaskHandle;
 | 
			
		||||
 | 
			
		||||
                #if ( configENABLE_MPU == 1 )
 | 
			
		||||
                    {
 | 
			
		||||
                        /* Store the correct CONTROL value for the task on the stack.
 | 
			
		||||
                         * This value is programmed in the CONTROL register on
 | 
			
		||||
                         * context switch. */
 | 
			
		||||
                        pulCurrentStackPointer = ( uint32_t * ) xSecureContexts[ ulSecureContextIndex ].pucStackStart;
 | 
			
		||||
                        pulCurrentStackPointer--;
 | 
			
		||||
 | 
			
		||||
                        if( ulIsTaskPrivileged )
 | 
			
		||||
                        {
 | 
			
		||||
                            *( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_PRIVILEGED;
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
                        {
 | 
			
		||||
                            *( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_UNPRIVILEGED;
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        /* Store the current stack pointer. This value is programmed in
 | 
			
		||||
                         * the PSP register on context switch. */
 | 
			
		||||
                        xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer = ( uint8_t * ) pulCurrentStackPointer;
 | 
			
		||||
                    }
 | 
			
		||||
                #else /* configENABLE_MPU */
 | 
			
		||||
                    {
 | 
			
		||||
                        /* Current SP is set to the starting of the stack. This
 | 
			
		||||
                         * value programmed in the PSP register on context switch. */
 | 
			
		||||
                        xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer = xSecureContexts[ ulSecureContextIndex ].pucStackStart;
 | 
			
		||||
                    }
 | 
			
		||||
                #endif /* configENABLE_MPU */
 | 
			
		||||
 | 
			
		||||
                /* Ensure to never return 0 as a valid context handle. */
 | 
			
		||||
                xSecureContextHandle = ulSecureContextIndex + 1UL;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return xSecureContextHandle;
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle )
 | 
			
		||||
{
 | 
			
		||||
    uint32_t ulIPSR, ulSecureContextIndex;
 | 
			
		||||
 | 
			
		||||
    /* Read the Interrupt Program Status Register (IPSR) value. */
 | 
			
		||||
    secureportREAD_IPSR( ulIPSR );
 | 
			
		||||
 | 
			
		||||
    /* Do nothing if the processor is running in the Thread Mode. IPSR is zero
 | 
			
		||||
     * when the processor is running in the Thread Mode. */
 | 
			
		||||
    if( ulIPSR != 0 )
 | 
			
		||||
    {
 | 
			
		||||
        /* Only free if a valid context handle is passed. */
 | 
			
		||||
        if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )
 | 
			
		||||
        {
 | 
			
		||||
            ulSecureContextIndex = xSecureContextHandle - 1UL;
 | 
			
		||||
 | 
			
		||||
            /* Ensure that the secure context being deleted is associated with
 | 
			
		||||
             * the task. */
 | 
			
		||||
            if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle )
 | 
			
		||||
            {
 | 
			
		||||
                /* Free the stack space. */
 | 
			
		||||
                vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );
 | 
			
		||||
 | 
			
		||||
                /* Return the secure context back to the free secure contexts pool. */
 | 
			
		||||
                vReturnSecureContext( ulSecureContextIndex );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
secureportNON_SECURE_CALLABLE void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle )
 | 
			
		||||
{
 | 
			
		||||
    uint8_t * pucStackLimit;
 | 
			
		||||
    uint32_t ulSecureContextIndex;
 | 
			
		||||
 | 
			
		||||
    if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )
 | 
			
		||||
    {
 | 
			
		||||
        ulSecureContextIndex = xSecureContextHandle - 1UL;
 | 
			
		||||
 | 
			
		||||
        secureportREAD_PSPLIM( pucStackLimit );
 | 
			
		||||
 | 
			
		||||
        /* Ensure that no secure context is loaded and the task is loading it's
 | 
			
		||||
         * own context. */
 | 
			
		||||
        if( ( pucStackLimit == securecontextNO_STACK ) &&
 | 
			
		||||
            ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) )
 | 
			
		||||
        {
 | 
			
		||||
            SecureContext_LoadContextAsm( &( xSecureContexts[ ulSecureContextIndex ] ) );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle )
 | 
			
		||||
{
 | 
			
		||||
    uint8_t * pucStackLimit;
 | 
			
		||||
    uint32_t ulSecureContextIndex;
 | 
			
		||||
 | 
			
		||||
    if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )
 | 
			
		||||
    {
 | 
			
		||||
        ulSecureContextIndex = xSecureContextHandle - 1UL;
 | 
			
		||||
 | 
			
		||||
        secureportREAD_PSPLIM( pucStackLimit );
 | 
			
		||||
 | 
			
		||||
        /* Ensure that task's context is loaded and the task is saving it's own
 | 
			
		||||
         * context. */
 | 
			
		||||
        if( ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == pucStackLimit ) &&
 | 
			
		||||
            ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) )
 | 
			
		||||
        {
 | 
			
		||||
            SecureContext_SaveContextAsm( &( xSecureContexts[ ulSecureContextIndex ] ) );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
/*
 | 
			
		||||
 * FreeRTOS Kernel <DEVELOPMENT BRANCH>
 | 
			
		||||
 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: MIT
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 | 
			
		||||
 * this software and associated documentation files (the "Software"), to deal in
 | 
			
		||||
 * the Software without restriction, including without limitation the rights to
 | 
			
		||||
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 | 
			
		||||
 * the Software, and to permit persons to whom the Software is furnished to do so,
 | 
			
		||||
 * subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
 * copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 | 
			
		||||
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 | 
			
		||||
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 | 
			
		||||
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
			
		||||
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 *
 | 
			
		||||
 * https://www.FreeRTOS.org
 | 
			
		||||
 * https://github.com/FreeRTOS
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Secure context includes. */
 | 
			
		||||
#include "secure_context.h"
 | 
			
		||||
 | 
			
		||||
/* Secure heap includes. */
 | 
			
		||||
#include "secure_heap.h"
 | 
			
		||||
 | 
			
		||||
/* Secure port macros. */
 | 
			
		||||
#include "secure_port_macros.h"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief CONTROL value for privileged tasks.
 | 
			
		||||
 *
 | 
			
		||||
 * Bit[0] - 0 --> Thread mode is privileged.
 | 
			
		||||
 * Bit[1] - 1 --> Thread mode uses PSP.
 | 
			
		||||
 */
 | 
			
		||||
#define securecontextCONTROL_VALUE_PRIVILEGED      0x02
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief CONTROL value for un-privileged tasks.
 | 
			
		||||
 *
 | 
			
		||||
 * Bit[0] - 1 --> Thread mode is un-privileged.
 | 
			
		||||
 * Bit[1] - 1 --> Thread mode uses PSP.
 | 
			
		||||
 */
 | 
			
		||||
#define securecontextCONTROL_VALUE_UNPRIVILEGED    0x03
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Size of stack seal values in bytes.
 | 
			
		||||
 */
 | 
			
		||||
#define securecontextSTACK_SEAL_SIZE               8
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Stack seal value as recommended by ARM.
 | 
			
		||||
 */
 | 
			
		||||
#define securecontextSTACK_SEAL_VALUE              0xFEF5EDA5
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Maximum number of secure contexts.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef secureconfigMAX_SECURE_CONTEXTS
 | 
			
		||||
    #define secureconfigMAX_SECURE_CONTEXTS        8UL
 | 
			
		||||
#endif
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Pre-allocated array of secure contexts.
 | 
			
		||||
 */
 | 
			
		||||
SecureContext_t xSecureContexts[ secureconfigMAX_SECURE_CONTEXTS ];
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Get a free secure context for a task from the secure context pool (xSecureContexts).
 | 
			
		||||
 *
 | 
			
		||||
 * This function ensures that only one secure context is allocated for a task.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] pvTaskHandle The task handle for which the secure context is allocated.
 | 
			
		||||
 *
 | 
			
		||||
 * @return Index of a free secure context in the xSecureContexts array.
 | 
			
		||||
 */
 | 
			
		||||
static uint32_t ulGetSecureContext( void * pvTaskHandle );
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Return the secure context to the secure context pool (xSecureContexts).
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] ulSecureContextIndex Index of the context in the xSecureContexts array.
 | 
			
		||||
 */
 | 
			
		||||
static void vReturnSecureContext( uint32_t ulSecureContextIndex );
 | 
			
		||||
 | 
			
		||||
/* These are implemented in assembly. */
 | 
			
		||||
extern void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext );
 | 
			
		||||
extern void SecureContext_SaveContextAsm( SecureContext_t * pxSecureContext );
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
static uint32_t ulGetSecureContext( void * pvTaskHandle )
 | 
			
		||||
{
 | 
			
		||||
    /* Start with invalid index. */
 | 
			
		||||
    uint32_t i, ulSecureContextIndex = secureconfigMAX_SECURE_CONTEXTS;
 | 
			
		||||
 | 
			
		||||
    for( i = 0; i < secureconfigMAX_SECURE_CONTEXTS; i++ )
 | 
			
		||||
    {
 | 
			
		||||
        if( ( xSecureContexts[ i ].pucCurrentStackPointer == NULL ) &&
 | 
			
		||||
            ( xSecureContexts[ i ].pucStackLimit == NULL ) &&
 | 
			
		||||
            ( xSecureContexts[ i ].pucStackStart == NULL ) &&
 | 
			
		||||
            ( xSecureContexts[ i ].pvTaskHandle == NULL ) &&
 | 
			
		||||
            ( ulSecureContextIndex == secureconfigMAX_SECURE_CONTEXTS ) )
 | 
			
		||||
        {
 | 
			
		||||
            ulSecureContextIndex = i;
 | 
			
		||||
        }
 | 
			
		||||
        else if( xSecureContexts[ i ].pvTaskHandle == pvTaskHandle )
 | 
			
		||||
        {
 | 
			
		||||
            /* A task can only have one secure context. Do not allocate a second
 | 
			
		||||
             * context for the same task. */
 | 
			
		||||
            ulSecureContextIndex = secureconfigMAX_SECURE_CONTEXTS;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return ulSecureContextIndex;
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
static void vReturnSecureContext( uint32_t ulSecureContextIndex )
 | 
			
		||||
{
 | 
			
		||||
    xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer = NULL;
 | 
			
		||||
    xSecureContexts[ ulSecureContextIndex ].pucStackLimit = NULL;
 | 
			
		||||
    xSecureContexts[ ulSecureContextIndex ].pucStackStart = NULL;
 | 
			
		||||
    xSecureContexts[ ulSecureContextIndex ].pvTaskHandle = NULL;
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
secureportNON_SECURE_CALLABLE void SecureContext_Init( void )
 | 
			
		||||
{
 | 
			
		||||
    uint32_t ulIPSR, i;
 | 
			
		||||
    static uint32_t ulSecureContextsInitialized = 0;
 | 
			
		||||
 | 
			
		||||
    /* Read the Interrupt Program Status Register (IPSR) value. */
 | 
			
		||||
    secureportREAD_IPSR( ulIPSR );
 | 
			
		||||
 | 
			
		||||
    /* Do nothing if the processor is running in the Thread Mode. IPSR is zero
 | 
			
		||||
     * when the processor is running in the Thread Mode. */
 | 
			
		||||
    if( ( ulIPSR != 0 ) && ( ulSecureContextsInitialized == 0 ) )
 | 
			
		||||
    {
 | 
			
		||||
        /* Ensure to initialize secure contexts only once. */
 | 
			
		||||
        ulSecureContextsInitialized = 1;
 | 
			
		||||
 | 
			
		||||
        /* No stack for thread mode until a task's context is loaded. */
 | 
			
		||||
        secureportSET_PSPLIM( securecontextNO_STACK );
 | 
			
		||||
        secureportSET_PSP( securecontextNO_STACK );
 | 
			
		||||
 | 
			
		||||
        /* Initialize all secure contexts. */
 | 
			
		||||
        for( i = 0; i < secureconfigMAX_SECURE_CONTEXTS; i++ )
 | 
			
		||||
        {
 | 
			
		||||
            xSecureContexts[ i ].pucCurrentStackPointer = NULL;
 | 
			
		||||
            xSecureContexts[ i ].pucStackLimit = NULL;
 | 
			
		||||
            xSecureContexts[ i ].pucStackStart = NULL;
 | 
			
		||||
            xSecureContexts[ i ].pvTaskHandle = NULL;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #if ( configENABLE_MPU == 1 )
 | 
			
		||||
            {
 | 
			
		||||
                /* Configure thread mode to use PSP and to be unprivileged. */
 | 
			
		||||
                secureportSET_CONTROL( securecontextCONTROL_VALUE_UNPRIVILEGED );
 | 
			
		||||
            }
 | 
			
		||||
        #else /* configENABLE_MPU */
 | 
			
		||||
            {
 | 
			
		||||
                /* Configure thread mode to use PSP and to be privileged. */
 | 
			
		||||
                secureportSET_CONTROL( securecontextCONTROL_VALUE_PRIVILEGED );
 | 
			
		||||
            }
 | 
			
		||||
        #endif /* configENABLE_MPU */
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
#if ( configENABLE_MPU == 1 )
 | 
			
		||||
    secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
 | 
			
		||||
                                                                                       uint32_t ulIsTaskPrivileged,
 | 
			
		||||
                                                                                       void * pvTaskHandle )
 | 
			
		||||
#else /* configENABLE_MPU */
 | 
			
		||||
    secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
 | 
			
		||||
                                                                                       void * pvTaskHandle )
 | 
			
		||||
#endif /* configENABLE_MPU */
 | 
			
		||||
{
 | 
			
		||||
    uint8_t * pucStackMemory = NULL;
 | 
			
		||||
    uint8_t * pucStackLimit;
 | 
			
		||||
    uint32_t ulIPSR, ulSecureContextIndex;
 | 
			
		||||
    SecureContextHandle_t xSecureContextHandle = securecontextINVALID_CONTEXT_ID;
 | 
			
		||||
 | 
			
		||||
    #if ( configENABLE_MPU == 1 )
 | 
			
		||||
        uint32_t * pulCurrentStackPointer = NULL;
 | 
			
		||||
    #endif /* configENABLE_MPU */
 | 
			
		||||
 | 
			
		||||
    /* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit
 | 
			
		||||
     * Register (PSPLIM) value. */
 | 
			
		||||
    secureportREAD_IPSR( ulIPSR );
 | 
			
		||||
    secureportREAD_PSPLIM( pucStackLimit );
 | 
			
		||||
 | 
			
		||||
    /* Do nothing if the processor is running in the Thread Mode. IPSR is zero
 | 
			
		||||
     * when the processor is running in the Thread Mode.
 | 
			
		||||
     * Also do nothing, if a secure context us already loaded. PSPLIM is set to
 | 
			
		||||
     * securecontextNO_STACK when no secure context is loaded. */
 | 
			
		||||
    if( ( ulIPSR != 0 ) && ( pucStackLimit == securecontextNO_STACK ) )
 | 
			
		||||
    {
 | 
			
		||||
        /* Ontain a free secure context. */
 | 
			
		||||
        ulSecureContextIndex = ulGetSecureContext( pvTaskHandle );
 | 
			
		||||
 | 
			
		||||
        /* Were we able to get a free context? */
 | 
			
		||||
        if( ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS )
 | 
			
		||||
        {
 | 
			
		||||
            /* Allocate the stack space. */
 | 
			
		||||
            pucStackMemory = pvPortMalloc( ulSecureStackSize + securecontextSTACK_SEAL_SIZE );
 | 
			
		||||
 | 
			
		||||
            if( pucStackMemory != NULL )
 | 
			
		||||
            {
 | 
			
		||||
                /* Since stack grows down, the starting point will be the last
 | 
			
		||||
                 * location. Note that this location is next to the last
 | 
			
		||||
                 * allocated byte for stack (excluding the space for seal values)
 | 
			
		||||
                 * because the hardware decrements the stack pointer before
 | 
			
		||||
                 * writing i.e. if stack pointer is 0x2, a push operation will
 | 
			
		||||
                 * decrement the stack pointer to 0x1 and then write at 0x1. */
 | 
			
		||||
                xSecureContexts[ ulSecureContextIndex ].pucStackStart = pucStackMemory + ulSecureStackSize;
 | 
			
		||||
 | 
			
		||||
                /* Seal the created secure process stack. */
 | 
			
		||||
                *( uint32_t * )( pucStackMemory + ulSecureStackSize ) = securecontextSTACK_SEAL_VALUE;
 | 
			
		||||
                *( uint32_t * )( pucStackMemory + ulSecureStackSize + 4 ) = securecontextSTACK_SEAL_VALUE;
 | 
			
		||||
 | 
			
		||||
                /* The stack cannot go beyond this location. This value is
 | 
			
		||||
                 * programmed in the PSPLIM register on context switch.*/
 | 
			
		||||
                xSecureContexts[ ulSecureContextIndex ].pucStackLimit = pucStackMemory;
 | 
			
		||||
 | 
			
		||||
                xSecureContexts[ ulSecureContextIndex ].pvTaskHandle = pvTaskHandle;
 | 
			
		||||
 | 
			
		||||
                #if ( configENABLE_MPU == 1 )
 | 
			
		||||
                    {
 | 
			
		||||
                        /* Store the correct CONTROL value for the task on the stack.
 | 
			
		||||
                         * This value is programmed in the CONTROL register on
 | 
			
		||||
                         * context switch. */
 | 
			
		||||
                        pulCurrentStackPointer = ( uint32_t * ) xSecureContexts[ ulSecureContextIndex ].pucStackStart;
 | 
			
		||||
                        pulCurrentStackPointer--;
 | 
			
		||||
 | 
			
		||||
                        if( ulIsTaskPrivileged )
 | 
			
		||||
                        {
 | 
			
		||||
                            *( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_PRIVILEGED;
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
                        {
 | 
			
		||||
                            *( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_UNPRIVILEGED;
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        /* Store the current stack pointer. This value is programmed in
 | 
			
		||||
                         * the PSP register on context switch. */
 | 
			
		||||
                        xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer = ( uint8_t * ) pulCurrentStackPointer;
 | 
			
		||||
                    }
 | 
			
		||||
                #else /* configENABLE_MPU */
 | 
			
		||||
                    {
 | 
			
		||||
                        /* Current SP is set to the starting of the stack. This
 | 
			
		||||
                         * value programmed in the PSP register on context switch. */
 | 
			
		||||
                        xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer = xSecureContexts[ ulSecureContextIndex ].pucStackStart;
 | 
			
		||||
                    }
 | 
			
		||||
                #endif /* configENABLE_MPU */
 | 
			
		||||
 | 
			
		||||
                /* Ensure to never return 0 as a valid context handle. */
 | 
			
		||||
                xSecureContextHandle = ulSecureContextIndex + 1UL;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return xSecureContextHandle;
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle )
 | 
			
		||||
{
 | 
			
		||||
    uint32_t ulIPSR, ulSecureContextIndex;
 | 
			
		||||
 | 
			
		||||
    /* Read the Interrupt Program Status Register (IPSR) value. */
 | 
			
		||||
    secureportREAD_IPSR( ulIPSR );
 | 
			
		||||
 | 
			
		||||
    /* Do nothing if the processor is running in the Thread Mode. IPSR is zero
 | 
			
		||||
     * when the processor is running in the Thread Mode. */
 | 
			
		||||
    if( ulIPSR != 0 )
 | 
			
		||||
    {
 | 
			
		||||
        /* Only free if a valid context handle is passed. */
 | 
			
		||||
        if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )
 | 
			
		||||
        {
 | 
			
		||||
            ulSecureContextIndex = xSecureContextHandle - 1UL;
 | 
			
		||||
 | 
			
		||||
            /* Ensure that the secure context being deleted is associated with
 | 
			
		||||
             * the task. */
 | 
			
		||||
            if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle )
 | 
			
		||||
            {
 | 
			
		||||
                /* Free the stack space. */
 | 
			
		||||
                vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );
 | 
			
		||||
 | 
			
		||||
                /* Return the secure context back to the free secure contexts pool. */
 | 
			
		||||
                vReturnSecureContext( ulSecureContextIndex );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
secureportNON_SECURE_CALLABLE void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle )
 | 
			
		||||
{
 | 
			
		||||
    uint8_t * pucStackLimit;
 | 
			
		||||
    uint32_t ulSecureContextIndex;
 | 
			
		||||
 | 
			
		||||
    if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )
 | 
			
		||||
    {
 | 
			
		||||
        ulSecureContextIndex = xSecureContextHandle - 1UL;
 | 
			
		||||
 | 
			
		||||
        secureportREAD_PSPLIM( pucStackLimit );
 | 
			
		||||
 | 
			
		||||
        /* Ensure that no secure context is loaded and the task is loading it's
 | 
			
		||||
         * own context. */
 | 
			
		||||
        if( ( pucStackLimit == securecontextNO_STACK ) &&
 | 
			
		||||
            ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) )
 | 
			
		||||
        {
 | 
			
		||||
            SecureContext_LoadContextAsm( &( xSecureContexts[ ulSecureContextIndex ] ) );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle )
 | 
			
		||||
{
 | 
			
		||||
    uint8_t * pucStackLimit;
 | 
			
		||||
    uint32_t ulSecureContextIndex;
 | 
			
		||||
 | 
			
		||||
    if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )
 | 
			
		||||
    {
 | 
			
		||||
        ulSecureContextIndex = xSecureContextHandle - 1UL;
 | 
			
		||||
 | 
			
		||||
        secureportREAD_PSPLIM( pucStackLimit );
 | 
			
		||||
 | 
			
		||||
        /* Ensure that task's context is loaded and the task is saving it's own
 | 
			
		||||
         * context. */
 | 
			
		||||
        if( ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == pucStackLimit ) &&
 | 
			
		||||
            ( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) )
 | 
			
		||||
        {
 | 
			
		||||
            SecureContext_SaveContextAsm( &( xSecureContexts[ ulSecureContextIndex ] ) );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,135 +1,135 @@
 | 
			
		|||
/*
 | 
			
		||||
 * FreeRTOS Kernel <DEVELOPMENT BRANCH>
 | 
			
		||||
 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: MIT
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 | 
			
		||||
 * this software and associated documentation files (the "Software"), to deal in
 | 
			
		||||
 * the Software without restriction, including without limitation the rights to
 | 
			
		||||
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 | 
			
		||||
 * the Software, and to permit persons to whom the Software is furnished to do so,
 | 
			
		||||
 * subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
 * copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 | 
			
		||||
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 | 
			
		||||
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 | 
			
		||||
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
			
		||||
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 *
 | 
			
		||||
 * https://www.FreeRTOS.org
 | 
			
		||||
 * https://github.com/FreeRTOS
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __SECURE_CONTEXT_H__
 | 
			
		||||
#define __SECURE_CONTEXT_H__
 | 
			
		||||
 | 
			
		||||
/* Standard includes. */
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
/* FreeRTOS includes. */
 | 
			
		||||
#include "FreeRTOSConfig.h"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief PSP value when no secure context is loaded.
 | 
			
		||||
 */
 | 
			
		||||
#define securecontextNO_STACK               0x0
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Invalid context ID.
 | 
			
		||||
 */
 | 
			
		||||
#define securecontextINVALID_CONTEXT_ID     0UL
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Structure to represent a secure context.
 | 
			
		||||
 *
 | 
			
		||||
 * @note Since stack grows down, pucStackStart is the highest address while
 | 
			
		||||
 * pucStackLimit is the first address of the allocated memory.
 | 
			
		||||
 */
 | 
			
		||||
typedef struct SecureContext
 | 
			
		||||
{
 | 
			
		||||
    uint8_t * pucCurrentStackPointer; /**< Current value of stack pointer (PSP). */
 | 
			
		||||
    uint8_t * pucStackLimit;          /**< Last location of the stack memory (PSPLIM). */
 | 
			
		||||
    uint8_t * pucStackStart;          /**< First location of the stack memory. */
 | 
			
		||||
    void * pvTaskHandle;              /**< Task handle of the task this context is associated with. */
 | 
			
		||||
} SecureContext_t;
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Opaque handle for a secure context.
 | 
			
		||||
 */
 | 
			
		||||
typedef uint32_t SecureContextHandle_t;
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Initializes the secure context management system.
 | 
			
		||||
 *
 | 
			
		||||
 * PSP is set to NULL and therefore a task must allocate and load a context
 | 
			
		||||
 * before calling any secure side function in the thread mode.
 | 
			
		||||
 *
 | 
			
		||||
 * @note This function must be called in the handler mode. It is no-op if called
 | 
			
		||||
 * in the thread mode.
 | 
			
		||||
 */
 | 
			
		||||
void SecureContext_Init( void );
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Allocates a context on the secure side.
 | 
			
		||||
 *
 | 
			
		||||
 * @note This function must be called in the handler mode. It is no-op if called
 | 
			
		||||
 * in the thread mode.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] ulSecureStackSize Size of the stack to allocate on secure side.
 | 
			
		||||
 * @param[in] ulIsTaskPrivileged 1 if the calling task is privileged, 0 otherwise.
 | 
			
		||||
 *
 | 
			
		||||
 * @return Opaque context handle if context is successfully allocated, NULL
 | 
			
		||||
 * otherwise.
 | 
			
		||||
 */
 | 
			
		||||
#if ( configENABLE_MPU == 1 )
 | 
			
		||||
    SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
 | 
			
		||||
                                                         uint32_t ulIsTaskPrivileged,
 | 
			
		||||
                                                         void * pvTaskHandle );
 | 
			
		||||
#else /* configENABLE_MPU */
 | 
			
		||||
    SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
 | 
			
		||||
                                                         void * pvTaskHandle );
 | 
			
		||||
#endif /* configENABLE_MPU */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Frees the given context.
 | 
			
		||||
 *
 | 
			
		||||
 * @note This function must be called in the handler mode. It is no-op if called
 | 
			
		||||
 * in the thread mode.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] xSecureContextHandle Context handle corresponding to the
 | 
			
		||||
 * context to be freed.
 | 
			
		||||
 */
 | 
			
		||||
void SecureContext_FreeContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle );
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Loads the given context.
 | 
			
		||||
 *
 | 
			
		||||
 * @note This function must be called in the handler mode. It is no-op if called
 | 
			
		||||
 * in the thread mode.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] xSecureContextHandle Context handle corresponding to the context
 | 
			
		||||
 * to be loaded.
 | 
			
		||||
 */
 | 
			
		||||
void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle );
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Saves the given context.
 | 
			
		||||
 *
 | 
			
		||||
 * @note This function must be called in the handler mode. It is no-op if called
 | 
			
		||||
 * in the thread mode.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] xSecureContextHandle Context handle corresponding to the context
 | 
			
		||||
 * to be saved.
 | 
			
		||||
 */
 | 
			
		||||
void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle );
 | 
			
		||||
 | 
			
		||||
#endif /* __SECURE_CONTEXT_H__ */
 | 
			
		||||
/*
 | 
			
		||||
 * FreeRTOS Kernel <DEVELOPMENT BRANCH>
 | 
			
		||||
 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: MIT
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 | 
			
		||||
 * this software and associated documentation files (the "Software"), to deal in
 | 
			
		||||
 * the Software without restriction, including without limitation the rights to
 | 
			
		||||
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 | 
			
		||||
 * the Software, and to permit persons to whom the Software is furnished to do so,
 | 
			
		||||
 * subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
 * copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 | 
			
		||||
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 | 
			
		||||
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 | 
			
		||||
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
			
		||||
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 *
 | 
			
		||||
 * https://www.FreeRTOS.org
 | 
			
		||||
 * https://github.com/FreeRTOS
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __SECURE_CONTEXT_H__
 | 
			
		||||
#define __SECURE_CONTEXT_H__
 | 
			
		||||
 | 
			
		||||
/* Standard includes. */
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
/* FreeRTOS includes. */
 | 
			
		||||
#include "FreeRTOSConfig.h"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief PSP value when no secure context is loaded.
 | 
			
		||||
 */
 | 
			
		||||
#define securecontextNO_STACK               0x0
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Invalid context ID.
 | 
			
		||||
 */
 | 
			
		||||
#define securecontextINVALID_CONTEXT_ID     0UL
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Structure to represent a secure context.
 | 
			
		||||
 *
 | 
			
		||||
 * @note Since stack grows down, pucStackStart is the highest address while
 | 
			
		||||
 * pucStackLimit is the first address of the allocated memory.
 | 
			
		||||
 */
 | 
			
		||||
typedef struct SecureContext
 | 
			
		||||
{
 | 
			
		||||
    uint8_t * pucCurrentStackPointer; /**< Current value of stack pointer (PSP). */
 | 
			
		||||
    uint8_t * pucStackLimit;          /**< Last location of the stack memory (PSPLIM). */
 | 
			
		||||
    uint8_t * pucStackStart;          /**< First location of the stack memory. */
 | 
			
		||||
    void * pvTaskHandle;              /**< Task handle of the task this context is associated with. */
 | 
			
		||||
} SecureContext_t;
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Opaque handle for a secure context.
 | 
			
		||||
 */
 | 
			
		||||
typedef uint32_t SecureContextHandle_t;
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Initializes the secure context management system.
 | 
			
		||||
 *
 | 
			
		||||
 * PSP is set to NULL and therefore a task must allocate and load a context
 | 
			
		||||
 * before calling any secure side function in the thread mode.
 | 
			
		||||
 *
 | 
			
		||||
 * @note This function must be called in the handler mode. It is no-op if called
 | 
			
		||||
 * in the thread mode.
 | 
			
		||||
 */
 | 
			
		||||
void SecureContext_Init( void );
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Allocates a context on the secure side.
 | 
			
		||||
 *
 | 
			
		||||
 * @note This function must be called in the handler mode. It is no-op if called
 | 
			
		||||
 * in the thread mode.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] ulSecureStackSize Size of the stack to allocate on secure side.
 | 
			
		||||
 * @param[in] ulIsTaskPrivileged 1 if the calling task is privileged, 0 otherwise.
 | 
			
		||||
 *
 | 
			
		||||
 * @return Opaque context handle if context is successfully allocated, NULL
 | 
			
		||||
 * otherwise.
 | 
			
		||||
 */
 | 
			
		||||
#if ( configENABLE_MPU == 1 )
 | 
			
		||||
    SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
 | 
			
		||||
                                                         uint32_t ulIsTaskPrivileged,
 | 
			
		||||
                                                         void * pvTaskHandle );
 | 
			
		||||
#else /* configENABLE_MPU */
 | 
			
		||||
    SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
 | 
			
		||||
                                                         void * pvTaskHandle );
 | 
			
		||||
#endif /* configENABLE_MPU */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Frees the given context.
 | 
			
		||||
 *
 | 
			
		||||
 * @note This function must be called in the handler mode. It is no-op if called
 | 
			
		||||
 * in the thread mode.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] xSecureContextHandle Context handle corresponding to the
 | 
			
		||||
 * context to be freed.
 | 
			
		||||
 */
 | 
			
		||||
void SecureContext_FreeContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle );
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Loads the given context.
 | 
			
		||||
 *
 | 
			
		||||
 * @note This function must be called in the handler mode. It is no-op if called
 | 
			
		||||
 * in the thread mode.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] xSecureContextHandle Context handle corresponding to the context
 | 
			
		||||
 * to be loaded.
 | 
			
		||||
 */
 | 
			
		||||
void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle );
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Saves the given context.
 | 
			
		||||
 *
 | 
			
		||||
 * @note This function must be called in the handler mode. It is no-op if called
 | 
			
		||||
 * in the thread mode.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] xSecureContextHandle Context handle corresponding to the context
 | 
			
		||||
 * to be saved.
 | 
			
		||||
 */
 | 
			
		||||
void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle );
 | 
			
		||||
 | 
			
		||||
#endif /* __SECURE_CONTEXT_H__ */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,97 +1,97 @@
 | 
			
		|||
/*
 | 
			
		||||
 * FreeRTOS Kernel <DEVELOPMENT BRANCH>
 | 
			
		||||
 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: MIT
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 | 
			
		||||
 * this software and associated documentation files (the "Software"), to deal in
 | 
			
		||||
 * the Software without restriction, including without limitation the rights to
 | 
			
		||||
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 | 
			
		||||
 * the Software, and to permit persons to whom the Software is furnished to do so,
 | 
			
		||||
 * subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
 * copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 | 
			
		||||
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 | 
			
		||||
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 | 
			
		||||
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
			
		||||
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 *
 | 
			
		||||
 * https://www.FreeRTOS.org
 | 
			
		||||
 * https://github.com/FreeRTOS
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Secure context includes. */
 | 
			
		||||
#include "secure_context.h"
 | 
			
		||||
 | 
			
		||||
/* Secure port macros. */
 | 
			
		||||
#include "secure_port_macros.h"
 | 
			
		||||
 | 
			
		||||
void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext ) __attribute__( ( naked ) );
 | 
			
		||||
void SecureContext_SaveContextAsm( SecureContext_t * pxSecureContext ) __attribute__( ( naked ) );
 | 
			
		||||
 | 
			
		||||
void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext )
 | 
			
		||||
{
 | 
			
		||||
    /* pxSecureContext value is in r0. */
 | 
			
		||||
    __asm volatile
 | 
			
		||||
    (
 | 
			
		||||
        " .syntax unified                   \n"
 | 
			
		||||
        "                                   \n"
 | 
			
		||||
        " mrs r1, ipsr                      \n" /* r1 = IPSR. */
 | 
			
		||||
        " cbz r1, load_ctx_therad_mode      \n" /* Do nothing if the processor is running in the Thread Mode. */
 | 
			
		||||
        " ldmia r0!, {r1, r2}               \n" /* r1 = pxSecureContext->pucCurrentStackPointer, r2 = pxSecureContext->pucStackLimit. */
 | 
			
		||||
        "                                   \n"
 | 
			
		||||
        #if ( configENABLE_MPU == 1 )
 | 
			
		||||
            " ldmia r1!, {r3}               \n" /* Read CONTROL register value from task's stack. r3 = CONTROL. */
 | 
			
		||||
            " msr control, r3               \n" /* CONTROL = r3. */
 | 
			
		||||
        #endif /* configENABLE_MPU */
 | 
			
		||||
        "                                   \n"
 | 
			
		||||
        " msr psplim, r2                    \n" /* PSPLIM = r2. */
 | 
			
		||||
        " msr psp, r1                       \n" /* PSP = r1. */
 | 
			
		||||
        "                                   \n"
 | 
			
		||||
        " load_ctx_therad_mode:             \n"
 | 
			
		||||
        "    bx lr                          \n"
 | 
			
		||||
        "                                   \n"
 | 
			
		||||
        ::: "r0", "r1", "r2"
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
void SecureContext_SaveContextAsm( SecureContext_t * pxSecureContext )
 | 
			
		||||
{
 | 
			
		||||
    /* pxSecureContext value is in r0. */
 | 
			
		||||
    __asm volatile
 | 
			
		||||
    (
 | 
			
		||||
        " .syntax unified                   \n"
 | 
			
		||||
        "                                   \n"
 | 
			
		||||
        " mrs r1, ipsr                      \n" /* r1 = IPSR. */
 | 
			
		||||
        " cbz r1, save_ctx_therad_mode      \n" /* Do nothing if the processor is running in the Thread Mode. */
 | 
			
		||||
        " mrs r1, psp                       \n" /* r1 = PSP. */
 | 
			
		||||
        "                                   \n"
 | 
			
		||||
        #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
 | 
			
		||||
            " vstmdb r1!, {s0}              \n" /* Trigger the deferred stacking of FPU registers. */
 | 
			
		||||
            " vldmia r1!, {s0}              \n" /* Nullify the effect of the previous statement. */
 | 
			
		||||
        #endif /* configENABLE_FPU || configENABLE_MVE */
 | 
			
		||||
        "                                   \n"
 | 
			
		||||
        #if ( configENABLE_MPU == 1 )
 | 
			
		||||
            " mrs r2, control               \n" /* r2 = CONTROL. */
 | 
			
		||||
            " stmdb r1!, {r2}               \n" /* Store CONTROL value on the stack. */
 | 
			
		||||
        #endif /* configENABLE_MPU */
 | 
			
		||||
        "                                   \n"
 | 
			
		||||
        " str r1, [r0]                      \n" /* Save the top of stack in context. pxSecureContext->pucCurrentStackPointer = r1. */
 | 
			
		||||
        " movs r1, %0                       \n" /* r1 = securecontextNO_STACK. */
 | 
			
		||||
        " msr psplim, r1                    \n" /* PSPLIM = securecontextNO_STACK. */
 | 
			
		||||
        " msr psp, r1                       \n" /* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */
 | 
			
		||||
        "                                   \n"
 | 
			
		||||
        " save_ctx_therad_mode:             \n"
 | 
			
		||||
        "    bx lr                          \n"
 | 
			
		||||
        "                                   \n"
 | 
			
		||||
        ::"i" ( securecontextNO_STACK ) : "r1", "memory"
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
/*
 | 
			
		||||
 * FreeRTOS Kernel <DEVELOPMENT BRANCH>
 | 
			
		||||
 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: MIT
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 | 
			
		||||
 * this software and associated documentation files (the "Software"), to deal in
 | 
			
		||||
 * the Software without restriction, including without limitation the rights to
 | 
			
		||||
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 | 
			
		||||
 * the Software, and to permit persons to whom the Software is furnished to do so,
 | 
			
		||||
 * subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
 * copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 | 
			
		||||
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 | 
			
		||||
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 | 
			
		||||
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
			
		||||
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 *
 | 
			
		||||
 * https://www.FreeRTOS.org
 | 
			
		||||
 * https://github.com/FreeRTOS
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Secure context includes. */
 | 
			
		||||
#include "secure_context.h"
 | 
			
		||||
 | 
			
		||||
/* Secure port macros. */
 | 
			
		||||
#include "secure_port_macros.h"
 | 
			
		||||
 | 
			
		||||
void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext ) __attribute__( ( naked ) );
 | 
			
		||||
void SecureContext_SaveContextAsm( SecureContext_t * pxSecureContext ) __attribute__( ( naked ) );
 | 
			
		||||
 | 
			
		||||
void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext )
 | 
			
		||||
{
 | 
			
		||||
    /* pxSecureContext value is in r0. */
 | 
			
		||||
    __asm volatile
 | 
			
		||||
    (
 | 
			
		||||
        " .syntax unified                   \n"
 | 
			
		||||
        "                                   \n"
 | 
			
		||||
        " mrs r1, ipsr                      \n" /* r1 = IPSR. */
 | 
			
		||||
        " cbz r1, load_ctx_therad_mode      \n" /* Do nothing if the processor is running in the Thread Mode. */
 | 
			
		||||
        " ldmia r0!, {r1, r2}               \n" /* r1 = pxSecureContext->pucCurrentStackPointer, r2 = pxSecureContext->pucStackLimit. */
 | 
			
		||||
        "                                   \n"
 | 
			
		||||
        #if ( configENABLE_MPU == 1 )
 | 
			
		||||
            " ldmia r1!, {r3}               \n" /* Read CONTROL register value from task's stack. r3 = CONTROL. */
 | 
			
		||||
            " msr control, r3               \n" /* CONTROL = r3. */
 | 
			
		||||
        #endif /* configENABLE_MPU */
 | 
			
		||||
        "                                   \n"
 | 
			
		||||
        " msr psplim, r2                    \n" /* PSPLIM = r2. */
 | 
			
		||||
        " msr psp, r1                       \n" /* PSP = r1. */
 | 
			
		||||
        "                                   \n"
 | 
			
		||||
        " load_ctx_therad_mode:             \n"
 | 
			
		||||
        "    bx lr                          \n"
 | 
			
		||||
        "                                   \n"
 | 
			
		||||
        ::: "r0", "r1", "r2"
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
void SecureContext_SaveContextAsm( SecureContext_t * pxSecureContext )
 | 
			
		||||
{
 | 
			
		||||
    /* pxSecureContext value is in r0. */
 | 
			
		||||
    __asm volatile
 | 
			
		||||
    (
 | 
			
		||||
        " .syntax unified                   \n"
 | 
			
		||||
        "                                   \n"
 | 
			
		||||
        " mrs r1, ipsr                      \n" /* r1 = IPSR. */
 | 
			
		||||
        " cbz r1, save_ctx_therad_mode      \n" /* Do nothing if the processor is running in the Thread Mode. */
 | 
			
		||||
        " mrs r1, psp                       \n" /* r1 = PSP. */
 | 
			
		||||
        "                                   \n"
 | 
			
		||||
        #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
 | 
			
		||||
            " vstmdb r1!, {s0}              \n" /* Trigger the deferred stacking of FPU registers. */
 | 
			
		||||
            " vldmia r1!, {s0}              \n" /* Nullify the effect of the previous statement. */
 | 
			
		||||
        #endif /* configENABLE_FPU || configENABLE_MVE */
 | 
			
		||||
        "                                   \n"
 | 
			
		||||
        #if ( configENABLE_MPU == 1 )
 | 
			
		||||
            " mrs r2, control               \n" /* r2 = CONTROL. */
 | 
			
		||||
            " stmdb r1!, {r2}               \n" /* Store CONTROL value on the stack. */
 | 
			
		||||
        #endif /* configENABLE_MPU */
 | 
			
		||||
        "                                   \n"
 | 
			
		||||
        " str r1, [r0]                      \n" /* Save the top of stack in context. pxSecureContext->pucCurrentStackPointer = r1. */
 | 
			
		||||
        " movs r1, %0                       \n" /* r1 = securecontextNO_STACK. */
 | 
			
		||||
        " msr psplim, r1                    \n" /* PSPLIM = securecontextNO_STACK. */
 | 
			
		||||
        " msr psp, r1                       \n" /* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */
 | 
			
		||||
        "                                   \n"
 | 
			
		||||
        " save_ctx_therad_mode:             \n"
 | 
			
		||||
        "    bx lr                          \n"
 | 
			
		||||
        "                                   \n"
 | 
			
		||||
        ::"i" ( securecontextNO_STACK ) : "r1", "memory"
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,454 +1,454 @@
 | 
			
		|||
/*
 | 
			
		||||
 * FreeRTOS Kernel <DEVELOPMENT BRANCH>
 | 
			
		||||
 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: MIT
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 | 
			
		||||
 * this software and associated documentation files (the "Software"), to deal in
 | 
			
		||||
 * the Software without restriction, including without limitation the rights to
 | 
			
		||||
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 | 
			
		||||
 * the Software, and to permit persons to whom the Software is furnished to do so,
 | 
			
		||||
 * subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
 * copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 | 
			
		||||
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 | 
			
		||||
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 | 
			
		||||
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
			
		||||
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 *
 | 
			
		||||
 * https://www.FreeRTOS.org
 | 
			
		||||
 * https://github.com/FreeRTOS
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Standard includes. */
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
/* Secure context heap includes. */
 | 
			
		||||
#include "secure_heap.h"
 | 
			
		||||
 | 
			
		||||
/* Secure port macros. */
 | 
			
		||||
#include "secure_port_macros.h"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Total heap size.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef secureconfigTOTAL_HEAP_SIZE
 | 
			
		||||
    #define secureconfigTOTAL_HEAP_SIZE    ( ( ( size_t ) ( 10 * 1024 ) ) )
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* No test marker by default. */
 | 
			
		||||
#ifndef mtCOVERAGE_TEST_MARKER
 | 
			
		||||
    #define mtCOVERAGE_TEST_MARKER()
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* No tracing by default. */
 | 
			
		||||
#ifndef traceMALLOC
 | 
			
		||||
    #define traceMALLOC( pvReturn, xWantedSize )
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* No tracing by default. */
 | 
			
		||||
#ifndef traceFREE
 | 
			
		||||
    #define traceFREE( pv, xBlockSize )
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Block sizes must not get too small. */
 | 
			
		||||
#define secureheapMINIMUM_BLOCK_SIZE    ( ( size_t ) ( xHeapStructSize << 1 ) )
 | 
			
		||||
 | 
			
		||||
/* Assumes 8bit bytes! */
 | 
			
		||||
#define secureheapBITS_PER_BYTE         ( ( size_t ) 8 )
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/* Allocate the memory for the heap. */
 | 
			
		||||
#if ( configAPPLICATION_ALLOCATED_HEAP == 1 )
 | 
			
		||||
 | 
			
		||||
/* The application writer has already defined the array used for the RTOS
 | 
			
		||||
* heap - probably so it can be placed in a special segment or address. */
 | 
			
		||||
    extern uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ];
 | 
			
		||||
#else /* configAPPLICATION_ALLOCATED_HEAP */
 | 
			
		||||
    static uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ];
 | 
			
		||||
#endif /* configAPPLICATION_ALLOCATED_HEAP */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief The linked list structure.
 | 
			
		||||
 *
 | 
			
		||||
 * This is used to link free blocks in order of their memory address.
 | 
			
		||||
 */
 | 
			
		||||
typedef struct A_BLOCK_LINK
 | 
			
		||||
{
 | 
			
		||||
    struct A_BLOCK_LINK * pxNextFreeBlock; /**< The next free block in the list. */
 | 
			
		||||
    size_t xBlockSize;                     /**< The size of the free block. */
 | 
			
		||||
} BlockLink_t;
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Called automatically to setup the required heap structures the first
 | 
			
		||||
 * time pvPortMalloc() is called.
 | 
			
		||||
 */
 | 
			
		||||
static void prvHeapInit( void );
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Inserts a block of memory that is being freed into the correct
 | 
			
		||||
 * position in the list of free memory blocks.
 | 
			
		||||
 *
 | 
			
		||||
 * The block being freed will be merged with the block in front it and/or the
 | 
			
		||||
 * block behind it if the memory blocks are adjacent to each other.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] pxBlockToInsert The block being freed.
 | 
			
		||||
 */
 | 
			
		||||
static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert );
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief The size of the structure placed at the beginning of each allocated
 | 
			
		||||
 * memory block must by correctly byte aligned.
 | 
			
		||||
 */
 | 
			
		||||
static const size_t xHeapStructSize = ( sizeof( BlockLink_t ) + ( ( size_t ) ( secureportBYTE_ALIGNMENT - 1 ) ) ) & ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Create a couple of list links to mark the start and end of the list.
 | 
			
		||||
 */
 | 
			
		||||
static BlockLink_t xStart;
 | 
			
		||||
static BlockLink_t * pxEnd = NULL;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Keeps track of the number of free bytes remaining, but says nothing
 | 
			
		||||
 * about fragmentation.
 | 
			
		||||
 */
 | 
			
		||||
static size_t xFreeBytesRemaining = 0U;
 | 
			
		||||
static size_t xMinimumEverFreeBytesRemaining = 0U;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Gets set to the top bit of an size_t type.
 | 
			
		||||
 *
 | 
			
		||||
 * When this bit in the xBlockSize member of an BlockLink_t structure is set
 | 
			
		||||
 * then the block belongs to the application. When the bit is free the block is
 | 
			
		||||
 * still part of the free heap space.
 | 
			
		||||
 */
 | 
			
		||||
static size_t xBlockAllocatedBit = 0;
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
static void prvHeapInit( void )
 | 
			
		||||
{
 | 
			
		||||
    BlockLink_t * pxFirstFreeBlock;
 | 
			
		||||
    uint8_t * pucAlignedHeap;
 | 
			
		||||
    size_t uxAddress;
 | 
			
		||||
    size_t xTotalHeapSize = secureconfigTOTAL_HEAP_SIZE;
 | 
			
		||||
 | 
			
		||||
    /* Ensure the heap starts on a correctly aligned boundary. */
 | 
			
		||||
    uxAddress = ( size_t ) ucHeap;
 | 
			
		||||
 | 
			
		||||
    if( ( uxAddress & secureportBYTE_ALIGNMENT_MASK ) != 0 )
 | 
			
		||||
    {
 | 
			
		||||
        uxAddress += ( secureportBYTE_ALIGNMENT - 1 );
 | 
			
		||||
        uxAddress &= ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
 | 
			
		||||
        xTotalHeapSize -= uxAddress - ( size_t ) ucHeap;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pucAlignedHeap = ( uint8_t * ) uxAddress;
 | 
			
		||||
 | 
			
		||||
    /* xStart is used to hold a pointer to the first item in the list of free
 | 
			
		||||
     * blocks.  The void cast is used to prevent compiler warnings. */
 | 
			
		||||
    xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap;
 | 
			
		||||
    xStart.xBlockSize = ( size_t ) 0;
 | 
			
		||||
 | 
			
		||||
    /* pxEnd is used to mark the end of the list of free blocks and is inserted
 | 
			
		||||
     * at the end of the heap space. */
 | 
			
		||||
    uxAddress = ( ( size_t ) pucAlignedHeap ) + xTotalHeapSize;
 | 
			
		||||
    uxAddress -= xHeapStructSize;
 | 
			
		||||
    uxAddress &= ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
 | 
			
		||||
    pxEnd = ( void * ) uxAddress;
 | 
			
		||||
    pxEnd->xBlockSize = 0;
 | 
			
		||||
    pxEnd->pxNextFreeBlock = NULL;
 | 
			
		||||
 | 
			
		||||
    /* To start with there is a single free block that is sized to take up the
 | 
			
		||||
     * entire heap space, minus the space taken by pxEnd. */
 | 
			
		||||
    pxFirstFreeBlock = ( void * ) pucAlignedHeap;
 | 
			
		||||
    pxFirstFreeBlock->xBlockSize = uxAddress - ( size_t ) pxFirstFreeBlock;
 | 
			
		||||
    pxFirstFreeBlock->pxNextFreeBlock = pxEnd;
 | 
			
		||||
 | 
			
		||||
    /* Only one block exists - and it covers the entire usable heap space. */
 | 
			
		||||
    xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
 | 
			
		||||
    xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
 | 
			
		||||
 | 
			
		||||
    /* Work out the position of the top bit in a size_t variable. */
 | 
			
		||||
    xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * secureheapBITS_PER_BYTE ) - 1 );
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert )
 | 
			
		||||
{
 | 
			
		||||
    BlockLink_t * pxIterator;
 | 
			
		||||
    uint8_t * puc;
 | 
			
		||||
 | 
			
		||||
    /* Iterate through the list until a block is found that has a higher address
 | 
			
		||||
     * than the block being inserted. */
 | 
			
		||||
    for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock )
 | 
			
		||||
    {
 | 
			
		||||
        /* Nothing to do here, just iterate to the right position. */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Do the block being inserted, and the block it is being inserted after
 | 
			
		||||
     * make a contiguous block of memory? */
 | 
			
		||||
    puc = ( uint8_t * ) pxIterator;
 | 
			
		||||
 | 
			
		||||
    if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert )
 | 
			
		||||
    {
 | 
			
		||||
        pxIterator->xBlockSize += pxBlockToInsert->xBlockSize;
 | 
			
		||||
        pxBlockToInsert = pxIterator;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        mtCOVERAGE_TEST_MARKER();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Do the block being inserted, and the block it is being inserted before
 | 
			
		||||
     * make a contiguous block of memory? */
 | 
			
		||||
    puc = ( uint8_t * ) pxBlockToInsert;
 | 
			
		||||
 | 
			
		||||
    if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock )
 | 
			
		||||
    {
 | 
			
		||||
        if( pxIterator->pxNextFreeBlock != pxEnd )
 | 
			
		||||
        {
 | 
			
		||||
            /* Form one big block from the two blocks. */
 | 
			
		||||
            pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize;
 | 
			
		||||
            pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            pxBlockToInsert->pxNextFreeBlock = pxEnd;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* If the block being inserted plugged a gab, so was merged with the block
 | 
			
		||||
     * before and the block after, then it's pxNextFreeBlock pointer will have
 | 
			
		||||
     * already been set, and should not be set here as that would make it point
 | 
			
		||||
     * to itself. */
 | 
			
		||||
    if( pxIterator != pxBlockToInsert )
 | 
			
		||||
    {
 | 
			
		||||
        pxIterator->pxNextFreeBlock = pxBlockToInsert;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        mtCOVERAGE_TEST_MARKER();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
void * pvPortMalloc( size_t xWantedSize )
 | 
			
		||||
{
 | 
			
		||||
    BlockLink_t * pxBlock;
 | 
			
		||||
    BlockLink_t * pxPreviousBlock;
 | 
			
		||||
    BlockLink_t * pxNewBlockLink;
 | 
			
		||||
    void * pvReturn = NULL;
 | 
			
		||||
 | 
			
		||||
    /* If this is the first call to malloc then the heap will require
 | 
			
		||||
     * initialisation to setup the list of free blocks. */
 | 
			
		||||
    if( pxEnd == NULL )
 | 
			
		||||
    {
 | 
			
		||||
        prvHeapInit();
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        mtCOVERAGE_TEST_MARKER();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Check the requested block size is not so large that the top bit is set.
 | 
			
		||||
     * The top bit of the block size member of the BlockLink_t structure is used
 | 
			
		||||
     * to determine who owns the block - the application or the kernel, so it
 | 
			
		||||
     * must be free. */
 | 
			
		||||
    if( ( xWantedSize & xBlockAllocatedBit ) == 0 )
 | 
			
		||||
    {
 | 
			
		||||
        /* The wanted size is increased so it can contain a BlockLink_t
 | 
			
		||||
         * structure in addition to the requested amount of bytes. */
 | 
			
		||||
        if( xWantedSize > 0 )
 | 
			
		||||
        {
 | 
			
		||||
            xWantedSize += xHeapStructSize;
 | 
			
		||||
 | 
			
		||||
            /* Ensure that blocks are always aligned to the required number of
 | 
			
		||||
             * bytes. */
 | 
			
		||||
            if( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) != 0x00 )
 | 
			
		||||
            {
 | 
			
		||||
                /* Byte alignment required. */
 | 
			
		||||
                xWantedSize += ( secureportBYTE_ALIGNMENT - ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) );
 | 
			
		||||
                secureportASSERT( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) == 0 );
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                mtCOVERAGE_TEST_MARKER();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            mtCOVERAGE_TEST_MARKER();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) )
 | 
			
		||||
        {
 | 
			
		||||
            /* Traverse the list from the start (lowest address) block until
 | 
			
		||||
             * one of adequate size is found. */
 | 
			
		||||
            pxPreviousBlock = &xStart;
 | 
			
		||||
            pxBlock = xStart.pxNextFreeBlock;
 | 
			
		||||
 | 
			
		||||
            while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) )
 | 
			
		||||
            {
 | 
			
		||||
                pxPreviousBlock = pxBlock;
 | 
			
		||||
                pxBlock = pxBlock->pxNextFreeBlock;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            /* If the end marker was reached then a block of adequate size was
 | 
			
		||||
             * not found. */
 | 
			
		||||
            if( pxBlock != pxEnd )
 | 
			
		||||
            {
 | 
			
		||||
                /* Return the memory space pointed to - jumping over the
 | 
			
		||||
                 * BlockLink_t structure at its start. */
 | 
			
		||||
                pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + xHeapStructSize );
 | 
			
		||||
 | 
			
		||||
                /* This block is being returned for use so must be taken out
 | 
			
		||||
                 * of the list of free blocks. */
 | 
			
		||||
                pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
 | 
			
		||||
 | 
			
		||||
                /* If the block is larger than required it can be split into
 | 
			
		||||
                 * two. */
 | 
			
		||||
                if( ( pxBlock->xBlockSize - xWantedSize ) > secureheapMINIMUM_BLOCK_SIZE )
 | 
			
		||||
                {
 | 
			
		||||
                    /* This block is to be split into two.  Create a new
 | 
			
		||||
                     * block following the number of bytes requested. The void
 | 
			
		||||
                     * cast is used to prevent byte alignment warnings from the
 | 
			
		||||
                     * compiler. */
 | 
			
		||||
                    pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize );
 | 
			
		||||
                    secureportASSERT( ( ( ( size_t ) pxNewBlockLink ) & secureportBYTE_ALIGNMENT_MASK ) == 0 );
 | 
			
		||||
 | 
			
		||||
                    /* Calculate the sizes of two blocks split from the single
 | 
			
		||||
                     * block. */
 | 
			
		||||
                    pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
 | 
			
		||||
                    pxBlock->xBlockSize = xWantedSize;
 | 
			
		||||
 | 
			
		||||
                    /* Insert the new block into the list of free blocks. */
 | 
			
		||||
                    prvInsertBlockIntoFreeList( pxNewBlockLink );
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    mtCOVERAGE_TEST_MARKER();
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                xFreeBytesRemaining -= pxBlock->xBlockSize;
 | 
			
		||||
 | 
			
		||||
                if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining )
 | 
			
		||||
                {
 | 
			
		||||
                    xMinimumEverFreeBytesRemaining = xFreeBytesRemaining;
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    mtCOVERAGE_TEST_MARKER();
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                /* The block is being returned - it is allocated and owned by
 | 
			
		||||
                 * the application and has no "next" block. */
 | 
			
		||||
                pxBlock->xBlockSize |= xBlockAllocatedBit;
 | 
			
		||||
                pxBlock->pxNextFreeBlock = NULL;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                mtCOVERAGE_TEST_MARKER();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            mtCOVERAGE_TEST_MARKER();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        mtCOVERAGE_TEST_MARKER();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    traceMALLOC( pvReturn, xWantedSize );
 | 
			
		||||
 | 
			
		||||
    #if ( secureconfigUSE_MALLOC_FAILED_HOOK == 1 )
 | 
			
		||||
        {
 | 
			
		||||
            if( pvReturn == NULL )
 | 
			
		||||
            {
 | 
			
		||||
                extern void vApplicationMallocFailedHook( void );
 | 
			
		||||
                vApplicationMallocFailedHook();
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                mtCOVERAGE_TEST_MARKER();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    #endif /* if ( secureconfigUSE_MALLOC_FAILED_HOOK == 1 ) */
 | 
			
		||||
 | 
			
		||||
    secureportASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) secureportBYTE_ALIGNMENT_MASK ) == 0 );
 | 
			
		||||
    return pvReturn;
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
void vPortFree( void * pv )
 | 
			
		||||
{
 | 
			
		||||
    uint8_t * puc = ( uint8_t * ) pv;
 | 
			
		||||
    BlockLink_t * pxLink;
 | 
			
		||||
 | 
			
		||||
    if( pv != NULL )
 | 
			
		||||
    {
 | 
			
		||||
        /* The memory being freed will have an BlockLink_t structure immediately
 | 
			
		||||
         * before it. */
 | 
			
		||||
        puc -= xHeapStructSize;
 | 
			
		||||
 | 
			
		||||
        /* This casting is to keep the compiler from issuing warnings. */
 | 
			
		||||
        pxLink = ( void * ) puc;
 | 
			
		||||
 | 
			
		||||
        /* Check the block is actually allocated. */
 | 
			
		||||
        secureportASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 );
 | 
			
		||||
        secureportASSERT( pxLink->pxNextFreeBlock == NULL );
 | 
			
		||||
 | 
			
		||||
        if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 )
 | 
			
		||||
        {
 | 
			
		||||
            if( pxLink->pxNextFreeBlock == NULL )
 | 
			
		||||
            {
 | 
			
		||||
                /* The block is being returned to the heap - it is no longer
 | 
			
		||||
                 * allocated. */
 | 
			
		||||
                pxLink->xBlockSize &= ~xBlockAllocatedBit;
 | 
			
		||||
 | 
			
		||||
                secureportDISABLE_NON_SECURE_INTERRUPTS();
 | 
			
		||||
                {
 | 
			
		||||
                    /* Add this block to the list of free blocks. */
 | 
			
		||||
                    xFreeBytesRemaining += pxLink->xBlockSize;
 | 
			
		||||
                    traceFREE( pv, pxLink->xBlockSize );
 | 
			
		||||
                    prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
 | 
			
		||||
                }
 | 
			
		||||
                secureportENABLE_NON_SECURE_INTERRUPTS();
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                mtCOVERAGE_TEST_MARKER();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            mtCOVERAGE_TEST_MARKER();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
size_t xPortGetFreeHeapSize( void )
 | 
			
		||||
{
 | 
			
		||||
    return xFreeBytesRemaining;
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
size_t xPortGetMinimumEverFreeHeapSize( void )
 | 
			
		||||
{
 | 
			
		||||
    return xMinimumEverFreeBytesRemaining;
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
/*
 | 
			
		||||
 * FreeRTOS Kernel <DEVELOPMENT BRANCH>
 | 
			
		||||
 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: MIT
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 | 
			
		||||
 * this software and associated documentation files (the "Software"), to deal in
 | 
			
		||||
 * the Software without restriction, including without limitation the rights to
 | 
			
		||||
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 | 
			
		||||
 * the Software, and to permit persons to whom the Software is furnished to do so,
 | 
			
		||||
 * subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
 * copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 | 
			
		||||
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 | 
			
		||||
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 | 
			
		||||
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
			
		||||
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 *
 | 
			
		||||
 * https://www.FreeRTOS.org
 | 
			
		||||
 * https://github.com/FreeRTOS
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Standard includes. */
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
/* Secure context heap includes. */
 | 
			
		||||
#include "secure_heap.h"
 | 
			
		||||
 | 
			
		||||
/* Secure port macros. */
 | 
			
		||||
#include "secure_port_macros.h"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Total heap size.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef secureconfigTOTAL_HEAP_SIZE
 | 
			
		||||
    #define secureconfigTOTAL_HEAP_SIZE    ( ( ( size_t ) ( 10 * 1024 ) ) )
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* No test marker by default. */
 | 
			
		||||
#ifndef mtCOVERAGE_TEST_MARKER
 | 
			
		||||
    #define mtCOVERAGE_TEST_MARKER()
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* No tracing by default. */
 | 
			
		||||
#ifndef traceMALLOC
 | 
			
		||||
    #define traceMALLOC( pvReturn, xWantedSize )
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* No tracing by default. */
 | 
			
		||||
#ifndef traceFREE
 | 
			
		||||
    #define traceFREE( pv, xBlockSize )
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Block sizes must not get too small. */
 | 
			
		||||
#define secureheapMINIMUM_BLOCK_SIZE    ( ( size_t ) ( xHeapStructSize << 1 ) )
 | 
			
		||||
 | 
			
		||||
/* Assumes 8bit bytes! */
 | 
			
		||||
#define secureheapBITS_PER_BYTE         ( ( size_t ) 8 )
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/* Allocate the memory for the heap. */
 | 
			
		||||
#if ( configAPPLICATION_ALLOCATED_HEAP == 1 )
 | 
			
		||||
 | 
			
		||||
/* The application writer has already defined the array used for the RTOS
 | 
			
		||||
* heap - probably so it can be placed in a special segment or address. */
 | 
			
		||||
    extern uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ];
 | 
			
		||||
#else /* configAPPLICATION_ALLOCATED_HEAP */
 | 
			
		||||
    static uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ];
 | 
			
		||||
#endif /* configAPPLICATION_ALLOCATED_HEAP */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief The linked list structure.
 | 
			
		||||
 *
 | 
			
		||||
 * This is used to link free blocks in order of their memory address.
 | 
			
		||||
 */
 | 
			
		||||
typedef struct A_BLOCK_LINK
 | 
			
		||||
{
 | 
			
		||||
    struct A_BLOCK_LINK * pxNextFreeBlock; /**< The next free block in the list. */
 | 
			
		||||
    size_t xBlockSize;                     /**< The size of the free block. */
 | 
			
		||||
} BlockLink_t;
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Called automatically to setup the required heap structures the first
 | 
			
		||||
 * time pvPortMalloc() is called.
 | 
			
		||||
 */
 | 
			
		||||
static void prvHeapInit( void );
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Inserts a block of memory that is being freed into the correct
 | 
			
		||||
 * position in the list of free memory blocks.
 | 
			
		||||
 *
 | 
			
		||||
 * The block being freed will be merged with the block in front it and/or the
 | 
			
		||||
 * block behind it if the memory blocks are adjacent to each other.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] pxBlockToInsert The block being freed.
 | 
			
		||||
 */
 | 
			
		||||
static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert );
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief The size of the structure placed at the beginning of each allocated
 | 
			
		||||
 * memory block must by correctly byte aligned.
 | 
			
		||||
 */
 | 
			
		||||
static const size_t xHeapStructSize = ( sizeof( BlockLink_t ) + ( ( size_t ) ( secureportBYTE_ALIGNMENT - 1 ) ) ) & ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Create a couple of list links to mark the start and end of the list.
 | 
			
		||||
 */
 | 
			
		||||
static BlockLink_t xStart;
 | 
			
		||||
static BlockLink_t * pxEnd = NULL;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Keeps track of the number of free bytes remaining, but says nothing
 | 
			
		||||
 * about fragmentation.
 | 
			
		||||
 */
 | 
			
		||||
static size_t xFreeBytesRemaining = 0U;
 | 
			
		||||
static size_t xMinimumEverFreeBytesRemaining = 0U;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Gets set to the top bit of an size_t type.
 | 
			
		||||
 *
 | 
			
		||||
 * When this bit in the xBlockSize member of an BlockLink_t structure is set
 | 
			
		||||
 * then the block belongs to the application. When the bit is free the block is
 | 
			
		||||
 * still part of the free heap space.
 | 
			
		||||
 */
 | 
			
		||||
static size_t xBlockAllocatedBit = 0;
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
static void prvHeapInit( void )
 | 
			
		||||
{
 | 
			
		||||
    BlockLink_t * pxFirstFreeBlock;
 | 
			
		||||
    uint8_t * pucAlignedHeap;
 | 
			
		||||
    size_t uxAddress;
 | 
			
		||||
    size_t xTotalHeapSize = secureconfigTOTAL_HEAP_SIZE;
 | 
			
		||||
 | 
			
		||||
    /* Ensure the heap starts on a correctly aligned boundary. */
 | 
			
		||||
    uxAddress = ( size_t ) ucHeap;
 | 
			
		||||
 | 
			
		||||
    if( ( uxAddress & secureportBYTE_ALIGNMENT_MASK ) != 0 )
 | 
			
		||||
    {
 | 
			
		||||
        uxAddress += ( secureportBYTE_ALIGNMENT - 1 );
 | 
			
		||||
        uxAddress &= ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
 | 
			
		||||
        xTotalHeapSize -= uxAddress - ( size_t ) ucHeap;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pucAlignedHeap = ( uint8_t * ) uxAddress;
 | 
			
		||||
 | 
			
		||||
    /* xStart is used to hold a pointer to the first item in the list of free
 | 
			
		||||
     * blocks.  The void cast is used to prevent compiler warnings. */
 | 
			
		||||
    xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap;
 | 
			
		||||
    xStart.xBlockSize = ( size_t ) 0;
 | 
			
		||||
 | 
			
		||||
    /* pxEnd is used to mark the end of the list of free blocks and is inserted
 | 
			
		||||
     * at the end of the heap space. */
 | 
			
		||||
    uxAddress = ( ( size_t ) pucAlignedHeap ) + xTotalHeapSize;
 | 
			
		||||
    uxAddress -= xHeapStructSize;
 | 
			
		||||
    uxAddress &= ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
 | 
			
		||||
    pxEnd = ( void * ) uxAddress;
 | 
			
		||||
    pxEnd->xBlockSize = 0;
 | 
			
		||||
    pxEnd->pxNextFreeBlock = NULL;
 | 
			
		||||
 | 
			
		||||
    /* To start with there is a single free block that is sized to take up the
 | 
			
		||||
     * entire heap space, minus the space taken by pxEnd. */
 | 
			
		||||
    pxFirstFreeBlock = ( void * ) pucAlignedHeap;
 | 
			
		||||
    pxFirstFreeBlock->xBlockSize = uxAddress - ( size_t ) pxFirstFreeBlock;
 | 
			
		||||
    pxFirstFreeBlock->pxNextFreeBlock = pxEnd;
 | 
			
		||||
 | 
			
		||||
    /* Only one block exists - and it covers the entire usable heap space. */
 | 
			
		||||
    xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
 | 
			
		||||
    xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
 | 
			
		||||
 | 
			
		||||
    /* Work out the position of the top bit in a size_t variable. */
 | 
			
		||||
    xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * secureheapBITS_PER_BYTE ) - 1 );
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert )
 | 
			
		||||
{
 | 
			
		||||
    BlockLink_t * pxIterator;
 | 
			
		||||
    uint8_t * puc;
 | 
			
		||||
 | 
			
		||||
    /* Iterate through the list until a block is found that has a higher address
 | 
			
		||||
     * than the block being inserted. */
 | 
			
		||||
    for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock )
 | 
			
		||||
    {
 | 
			
		||||
        /* Nothing to do here, just iterate to the right position. */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Do the block being inserted, and the block it is being inserted after
 | 
			
		||||
     * make a contiguous block of memory? */
 | 
			
		||||
    puc = ( uint8_t * ) pxIterator;
 | 
			
		||||
 | 
			
		||||
    if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert )
 | 
			
		||||
    {
 | 
			
		||||
        pxIterator->xBlockSize += pxBlockToInsert->xBlockSize;
 | 
			
		||||
        pxBlockToInsert = pxIterator;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        mtCOVERAGE_TEST_MARKER();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Do the block being inserted, and the block it is being inserted before
 | 
			
		||||
     * make a contiguous block of memory? */
 | 
			
		||||
    puc = ( uint8_t * ) pxBlockToInsert;
 | 
			
		||||
 | 
			
		||||
    if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock )
 | 
			
		||||
    {
 | 
			
		||||
        if( pxIterator->pxNextFreeBlock != pxEnd )
 | 
			
		||||
        {
 | 
			
		||||
            /* Form one big block from the two blocks. */
 | 
			
		||||
            pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize;
 | 
			
		||||
            pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            pxBlockToInsert->pxNextFreeBlock = pxEnd;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* If the block being inserted plugged a gab, so was merged with the block
 | 
			
		||||
     * before and the block after, then it's pxNextFreeBlock pointer will have
 | 
			
		||||
     * already been set, and should not be set here as that would make it point
 | 
			
		||||
     * to itself. */
 | 
			
		||||
    if( pxIterator != pxBlockToInsert )
 | 
			
		||||
    {
 | 
			
		||||
        pxIterator->pxNextFreeBlock = pxBlockToInsert;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        mtCOVERAGE_TEST_MARKER();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
void * pvPortMalloc( size_t xWantedSize )
 | 
			
		||||
{
 | 
			
		||||
    BlockLink_t * pxBlock;
 | 
			
		||||
    BlockLink_t * pxPreviousBlock;
 | 
			
		||||
    BlockLink_t * pxNewBlockLink;
 | 
			
		||||
    void * pvReturn = NULL;
 | 
			
		||||
 | 
			
		||||
    /* If this is the first call to malloc then the heap will require
 | 
			
		||||
     * initialisation to setup the list of free blocks. */
 | 
			
		||||
    if( pxEnd == NULL )
 | 
			
		||||
    {
 | 
			
		||||
        prvHeapInit();
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        mtCOVERAGE_TEST_MARKER();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Check the requested block size is not so large that the top bit is set.
 | 
			
		||||
     * The top bit of the block size member of the BlockLink_t structure is used
 | 
			
		||||
     * to determine who owns the block - the application or the kernel, so it
 | 
			
		||||
     * must be free. */
 | 
			
		||||
    if( ( xWantedSize & xBlockAllocatedBit ) == 0 )
 | 
			
		||||
    {
 | 
			
		||||
        /* The wanted size is increased so it can contain a BlockLink_t
 | 
			
		||||
         * structure in addition to the requested amount of bytes. */
 | 
			
		||||
        if( xWantedSize > 0 )
 | 
			
		||||
        {
 | 
			
		||||
            xWantedSize += xHeapStructSize;
 | 
			
		||||
 | 
			
		||||
            /* Ensure that blocks are always aligned to the required number of
 | 
			
		||||
             * bytes. */
 | 
			
		||||
            if( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) != 0x00 )
 | 
			
		||||
            {
 | 
			
		||||
                /* Byte alignment required. */
 | 
			
		||||
                xWantedSize += ( secureportBYTE_ALIGNMENT - ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) );
 | 
			
		||||
                secureportASSERT( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) == 0 );
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                mtCOVERAGE_TEST_MARKER();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            mtCOVERAGE_TEST_MARKER();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) )
 | 
			
		||||
        {
 | 
			
		||||
            /* Traverse the list from the start (lowest address) block until
 | 
			
		||||
             * one of adequate size is found. */
 | 
			
		||||
            pxPreviousBlock = &xStart;
 | 
			
		||||
            pxBlock = xStart.pxNextFreeBlock;
 | 
			
		||||
 | 
			
		||||
            while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) )
 | 
			
		||||
            {
 | 
			
		||||
                pxPreviousBlock = pxBlock;
 | 
			
		||||
                pxBlock = pxBlock->pxNextFreeBlock;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            /* If the end marker was reached then a block of adequate size was
 | 
			
		||||
             * not found. */
 | 
			
		||||
            if( pxBlock != pxEnd )
 | 
			
		||||
            {
 | 
			
		||||
                /* Return the memory space pointed to - jumping over the
 | 
			
		||||
                 * BlockLink_t structure at its start. */
 | 
			
		||||
                pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + xHeapStructSize );
 | 
			
		||||
 | 
			
		||||
                /* This block is being returned for use so must be taken out
 | 
			
		||||
                 * of the list of free blocks. */
 | 
			
		||||
                pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
 | 
			
		||||
 | 
			
		||||
                /* If the block is larger than required it can be split into
 | 
			
		||||
                 * two. */
 | 
			
		||||
                if( ( pxBlock->xBlockSize - xWantedSize ) > secureheapMINIMUM_BLOCK_SIZE )
 | 
			
		||||
                {
 | 
			
		||||
                    /* This block is to be split into two.  Create a new
 | 
			
		||||
                     * block following the number of bytes requested. The void
 | 
			
		||||
                     * cast is used to prevent byte alignment warnings from the
 | 
			
		||||
                     * compiler. */
 | 
			
		||||
                    pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize );
 | 
			
		||||
                    secureportASSERT( ( ( ( size_t ) pxNewBlockLink ) & secureportBYTE_ALIGNMENT_MASK ) == 0 );
 | 
			
		||||
 | 
			
		||||
                    /* Calculate the sizes of two blocks split from the single
 | 
			
		||||
                     * block. */
 | 
			
		||||
                    pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
 | 
			
		||||
                    pxBlock->xBlockSize = xWantedSize;
 | 
			
		||||
 | 
			
		||||
                    /* Insert the new block into the list of free blocks. */
 | 
			
		||||
                    prvInsertBlockIntoFreeList( pxNewBlockLink );
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    mtCOVERAGE_TEST_MARKER();
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                xFreeBytesRemaining -= pxBlock->xBlockSize;
 | 
			
		||||
 | 
			
		||||
                if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining )
 | 
			
		||||
                {
 | 
			
		||||
                    xMinimumEverFreeBytesRemaining = xFreeBytesRemaining;
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    mtCOVERAGE_TEST_MARKER();
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                /* The block is being returned - it is allocated and owned by
 | 
			
		||||
                 * the application and has no "next" block. */
 | 
			
		||||
                pxBlock->xBlockSize |= xBlockAllocatedBit;
 | 
			
		||||
                pxBlock->pxNextFreeBlock = NULL;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                mtCOVERAGE_TEST_MARKER();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            mtCOVERAGE_TEST_MARKER();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        mtCOVERAGE_TEST_MARKER();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    traceMALLOC( pvReturn, xWantedSize );
 | 
			
		||||
 | 
			
		||||
    #if ( secureconfigUSE_MALLOC_FAILED_HOOK == 1 )
 | 
			
		||||
        {
 | 
			
		||||
            if( pvReturn == NULL )
 | 
			
		||||
            {
 | 
			
		||||
                extern void vApplicationMallocFailedHook( void );
 | 
			
		||||
                vApplicationMallocFailedHook();
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                mtCOVERAGE_TEST_MARKER();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    #endif /* if ( secureconfigUSE_MALLOC_FAILED_HOOK == 1 ) */
 | 
			
		||||
 | 
			
		||||
    secureportASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) secureportBYTE_ALIGNMENT_MASK ) == 0 );
 | 
			
		||||
    return pvReturn;
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
void vPortFree( void * pv )
 | 
			
		||||
{
 | 
			
		||||
    uint8_t * puc = ( uint8_t * ) pv;
 | 
			
		||||
    BlockLink_t * pxLink;
 | 
			
		||||
 | 
			
		||||
    if( pv != NULL )
 | 
			
		||||
    {
 | 
			
		||||
        /* The memory being freed will have an BlockLink_t structure immediately
 | 
			
		||||
         * before it. */
 | 
			
		||||
        puc -= xHeapStructSize;
 | 
			
		||||
 | 
			
		||||
        /* This casting is to keep the compiler from issuing warnings. */
 | 
			
		||||
        pxLink = ( void * ) puc;
 | 
			
		||||
 | 
			
		||||
        /* Check the block is actually allocated. */
 | 
			
		||||
        secureportASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 );
 | 
			
		||||
        secureportASSERT( pxLink->pxNextFreeBlock == NULL );
 | 
			
		||||
 | 
			
		||||
        if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 )
 | 
			
		||||
        {
 | 
			
		||||
            if( pxLink->pxNextFreeBlock == NULL )
 | 
			
		||||
            {
 | 
			
		||||
                /* The block is being returned to the heap - it is no longer
 | 
			
		||||
                 * allocated. */
 | 
			
		||||
                pxLink->xBlockSize &= ~xBlockAllocatedBit;
 | 
			
		||||
 | 
			
		||||
                secureportDISABLE_NON_SECURE_INTERRUPTS();
 | 
			
		||||
                {
 | 
			
		||||
                    /* Add this block to the list of free blocks. */
 | 
			
		||||
                    xFreeBytesRemaining += pxLink->xBlockSize;
 | 
			
		||||
                    traceFREE( pv, pxLink->xBlockSize );
 | 
			
		||||
                    prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
 | 
			
		||||
                }
 | 
			
		||||
                secureportENABLE_NON_SECURE_INTERRUPTS();
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                mtCOVERAGE_TEST_MARKER();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            mtCOVERAGE_TEST_MARKER();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
size_t xPortGetFreeHeapSize( void )
 | 
			
		||||
{
 | 
			
		||||
    return xFreeBytesRemaining;
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
size_t xPortGetMinimumEverFreeHeapSize( void )
 | 
			
		||||
{
 | 
			
		||||
    return xMinimumEverFreeBytesRemaining;
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,66 +1,66 @@
 | 
			
		|||
/*
 | 
			
		||||
 * FreeRTOS Kernel <DEVELOPMENT BRANCH>
 | 
			
		||||
 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: MIT
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 | 
			
		||||
 * this software and associated documentation files (the "Software"), to deal in
 | 
			
		||||
 * the Software without restriction, including without limitation the rights to
 | 
			
		||||
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 | 
			
		||||
 * the Software, and to permit persons to whom the Software is furnished to do so,
 | 
			
		||||
 * subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
 * copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 | 
			
		||||
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 | 
			
		||||
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 | 
			
		||||
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
			
		||||
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 *
 | 
			
		||||
 * https://www.FreeRTOS.org
 | 
			
		||||
 * https://github.com/FreeRTOS
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __SECURE_HEAP_H__
 | 
			
		||||
#define __SECURE_HEAP_H__
 | 
			
		||||
 | 
			
		||||
/* Standard includes. */
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Allocates memory from heap.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] xWantedSize The size of the memory to be allocated.
 | 
			
		||||
 *
 | 
			
		||||
 * @return Pointer to the memory region if the allocation is successful, NULL
 | 
			
		||||
 * otherwise.
 | 
			
		||||
 */
 | 
			
		||||
void * pvPortMalloc( size_t xWantedSize );
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Frees the previously allocated memory.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] pv Pointer to the memory to be freed.
 | 
			
		||||
 */
 | 
			
		||||
void vPortFree( void * pv );
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Get the free heap size.
 | 
			
		||||
 *
 | 
			
		||||
 * @return Free heap size.
 | 
			
		||||
 */
 | 
			
		||||
size_t xPortGetFreeHeapSize( void );
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Get the minimum ever free heap size.
 | 
			
		||||
 *
 | 
			
		||||
 * @return Minimum ever free heap size.
 | 
			
		||||
 */
 | 
			
		||||
size_t xPortGetMinimumEverFreeHeapSize( void );
 | 
			
		||||
 | 
			
		||||
#endif /* __SECURE_HEAP_H__ */
 | 
			
		||||
/*
 | 
			
		||||
 * FreeRTOS Kernel <DEVELOPMENT BRANCH>
 | 
			
		||||
 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: MIT
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 | 
			
		||||
 * this software and associated documentation files (the "Software"), to deal in
 | 
			
		||||
 * the Software without restriction, including without limitation the rights to
 | 
			
		||||
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 | 
			
		||||
 * the Software, and to permit persons to whom the Software is furnished to do so,
 | 
			
		||||
 * subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
 * copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 | 
			
		||||
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 | 
			
		||||
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 | 
			
		||||
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
			
		||||
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 *
 | 
			
		||||
 * https://www.FreeRTOS.org
 | 
			
		||||
 * https://github.com/FreeRTOS
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __SECURE_HEAP_H__
 | 
			
		||||
#define __SECURE_HEAP_H__
 | 
			
		||||
 | 
			
		||||
/* Standard includes. */
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Allocates memory from heap.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] xWantedSize The size of the memory to be allocated.
 | 
			
		||||
 *
 | 
			
		||||
 * @return Pointer to the memory region if the allocation is successful, NULL
 | 
			
		||||
 * otherwise.
 | 
			
		||||
 */
 | 
			
		||||
void * pvPortMalloc( size_t xWantedSize );
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Frees the previously allocated memory.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] pv Pointer to the memory to be freed.
 | 
			
		||||
 */
 | 
			
		||||
void vPortFree( void * pv );
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Get the free heap size.
 | 
			
		||||
 *
 | 
			
		||||
 * @return Free heap size.
 | 
			
		||||
 */
 | 
			
		||||
size_t xPortGetFreeHeapSize( void );
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Get the minimum ever free heap size.
 | 
			
		||||
 *
 | 
			
		||||
 * @return Minimum ever free heap size.
 | 
			
		||||
 */
 | 
			
		||||
size_t xPortGetMinimumEverFreeHeapSize( void );
 | 
			
		||||
 | 
			
		||||
#endif /* __SECURE_HEAP_H__ */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,106 +1,106 @@
 | 
			
		|||
/*
 | 
			
		||||
 * FreeRTOS Kernel <DEVELOPMENT BRANCH>
 | 
			
		||||
 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: MIT
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 | 
			
		||||
 * this software and associated documentation files (the "Software"), to deal in
 | 
			
		||||
 * the Software without restriction, including without limitation the rights to
 | 
			
		||||
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 | 
			
		||||
 * the Software, and to permit persons to whom the Software is furnished to do so,
 | 
			
		||||
 * subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
 * copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 | 
			
		||||
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 | 
			
		||||
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 | 
			
		||||
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
			
		||||
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 *
 | 
			
		||||
 * https://www.FreeRTOS.org
 | 
			
		||||
 * https://github.com/FreeRTOS
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Standard includes. */
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
/* Secure init includes. */
 | 
			
		||||
#include "secure_init.h"
 | 
			
		||||
 | 
			
		||||
/* Secure port macros. */
 | 
			
		||||
#include "secure_port_macros.h"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Constants required to manipulate the SCB.
 | 
			
		||||
 */
 | 
			
		||||
#define secureinitSCB_AIRCR                 ( ( volatile uint32_t * ) 0xe000ed0c )  /* Application Interrupt and Reset Control Register. */
 | 
			
		||||
#define secureinitSCB_AIRCR_VECTKEY_POS     ( 16UL )
 | 
			
		||||
#define secureinitSCB_AIRCR_VECTKEY_MASK    ( 0xFFFFUL << secureinitSCB_AIRCR_VECTKEY_POS )
 | 
			
		||||
#define secureinitSCB_AIRCR_PRIS_POS        ( 14UL )
 | 
			
		||||
#define secureinitSCB_AIRCR_PRIS_MASK       ( 1UL << secureinitSCB_AIRCR_PRIS_POS )
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Constants required to manipulate the FPU.
 | 
			
		||||
 */
 | 
			
		||||
#define secureinitFPCCR                     ( ( volatile uint32_t * ) 0xe000ef34 )  /* Floating Point Context Control Register. */
 | 
			
		||||
#define secureinitFPCCR_LSPENS_POS          ( 29UL )
 | 
			
		||||
#define secureinitFPCCR_LSPENS_MASK         ( 1UL << secureinitFPCCR_LSPENS_POS )
 | 
			
		||||
#define secureinitFPCCR_TS_POS              ( 26UL )
 | 
			
		||||
#define secureinitFPCCR_TS_MASK             ( 1UL << secureinitFPCCR_TS_POS )
 | 
			
		||||
 | 
			
		||||
#define secureinitNSACR                     ( ( volatile uint32_t * ) 0xe000ed8c )  /* Non-secure Access Control Register. */
 | 
			
		||||
#define secureinitNSACR_CP10_POS            ( 10UL )
 | 
			
		||||
#define secureinitNSACR_CP10_MASK           ( 1UL << secureinitNSACR_CP10_POS )
 | 
			
		||||
#define secureinitNSACR_CP11_POS            ( 11UL )
 | 
			
		||||
#define secureinitNSACR_CP11_MASK           ( 1UL << secureinitNSACR_CP11_POS )
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
secureportNON_SECURE_CALLABLE void SecureInit_DePrioritizeNSExceptions( void )
 | 
			
		||||
{
 | 
			
		||||
    uint32_t ulIPSR;
 | 
			
		||||
 | 
			
		||||
    /* Read the Interrupt Program Status Register (IPSR) value. */
 | 
			
		||||
    secureportREAD_IPSR( ulIPSR );
 | 
			
		||||
 | 
			
		||||
    /* Do nothing if the processor is running in the Thread Mode. IPSR is zero
 | 
			
		||||
     * when the processor is running in the Thread Mode. */
 | 
			
		||||
    if( ulIPSR != 0 )
 | 
			
		||||
    {
 | 
			
		||||
        *( secureinitSCB_AIRCR ) = ( *( secureinitSCB_AIRCR ) & ~( secureinitSCB_AIRCR_VECTKEY_MASK | secureinitSCB_AIRCR_PRIS_MASK ) ) |
 | 
			
		||||
                                   ( ( 0x05FAUL << secureinitSCB_AIRCR_VECTKEY_POS ) & secureinitSCB_AIRCR_VECTKEY_MASK ) |
 | 
			
		||||
                                   ( ( 0x1UL << secureinitSCB_AIRCR_PRIS_POS ) & secureinitSCB_AIRCR_PRIS_MASK );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
secureportNON_SECURE_CALLABLE void SecureInit_EnableNSFPUAccess( void )
 | 
			
		||||
{
 | 
			
		||||
    uint32_t ulIPSR;
 | 
			
		||||
 | 
			
		||||
    /* Read the Interrupt Program Status Register (IPSR) value. */
 | 
			
		||||
    secureportREAD_IPSR( ulIPSR );
 | 
			
		||||
 | 
			
		||||
    /* Do nothing if the processor is running in the Thread Mode. IPSR is zero
 | 
			
		||||
     * when the processor is running in the Thread Mode. */
 | 
			
		||||
    if( ulIPSR != 0 )
 | 
			
		||||
    {
 | 
			
		||||
        /* CP10 = 1 ==> Non-secure access to the Floating Point Unit is
 | 
			
		||||
         * permitted. CP11 should be programmed to the same value as CP10. */
 | 
			
		||||
        *( secureinitNSACR ) |= ( secureinitNSACR_CP10_MASK | secureinitNSACR_CP11_MASK );
 | 
			
		||||
 | 
			
		||||
        /* LSPENS = 0 ==> LSPEN is writable fron non-secure state. This ensures
 | 
			
		||||
         * that we can enable/disable lazy stacking in port.c file. */
 | 
			
		||||
        *( secureinitFPCCR ) &= ~( secureinitFPCCR_LSPENS_MASK );
 | 
			
		||||
 | 
			
		||||
        /* TS = 1 ==> Treat FP registers as secure i.e. callee saved FP
 | 
			
		||||
         * registers (S16-S31) are also pushed to stack on exception entry and
 | 
			
		||||
         * restored on exception return. */
 | 
			
		||||
        *( secureinitFPCCR ) |= ( secureinitFPCCR_TS_MASK );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
/*
 | 
			
		||||
 * FreeRTOS Kernel <DEVELOPMENT BRANCH>
 | 
			
		||||
 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: MIT
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 | 
			
		||||
 * this software and associated documentation files (the "Software"), to deal in
 | 
			
		||||
 * the Software without restriction, including without limitation the rights to
 | 
			
		||||
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 | 
			
		||||
 * the Software, and to permit persons to whom the Software is furnished to do so,
 | 
			
		||||
 * subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
 * copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 | 
			
		||||
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 | 
			
		||||
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 | 
			
		||||
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
			
		||||
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 *
 | 
			
		||||
 * https://www.FreeRTOS.org
 | 
			
		||||
 * https://github.com/FreeRTOS
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Standard includes. */
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
/* Secure init includes. */
 | 
			
		||||
#include "secure_init.h"
 | 
			
		||||
 | 
			
		||||
/* Secure port macros. */
 | 
			
		||||
#include "secure_port_macros.h"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Constants required to manipulate the SCB.
 | 
			
		||||
 */
 | 
			
		||||
#define secureinitSCB_AIRCR                 ( ( volatile uint32_t * ) 0xe000ed0c )  /* Application Interrupt and Reset Control Register. */
 | 
			
		||||
#define secureinitSCB_AIRCR_VECTKEY_POS     ( 16UL )
 | 
			
		||||
#define secureinitSCB_AIRCR_VECTKEY_MASK    ( 0xFFFFUL << secureinitSCB_AIRCR_VECTKEY_POS )
 | 
			
		||||
#define secureinitSCB_AIRCR_PRIS_POS        ( 14UL )
 | 
			
		||||
#define secureinitSCB_AIRCR_PRIS_MASK       ( 1UL << secureinitSCB_AIRCR_PRIS_POS )
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Constants required to manipulate the FPU.
 | 
			
		||||
 */
 | 
			
		||||
#define secureinitFPCCR                     ( ( volatile uint32_t * ) 0xe000ef34 )  /* Floating Point Context Control Register. */
 | 
			
		||||
#define secureinitFPCCR_LSPENS_POS          ( 29UL )
 | 
			
		||||
#define secureinitFPCCR_LSPENS_MASK         ( 1UL << secureinitFPCCR_LSPENS_POS )
 | 
			
		||||
#define secureinitFPCCR_TS_POS              ( 26UL )
 | 
			
		||||
#define secureinitFPCCR_TS_MASK             ( 1UL << secureinitFPCCR_TS_POS )
 | 
			
		||||
 | 
			
		||||
#define secureinitNSACR                     ( ( volatile uint32_t * ) 0xe000ed8c )  /* Non-secure Access Control Register. */
 | 
			
		||||
#define secureinitNSACR_CP10_POS            ( 10UL )
 | 
			
		||||
#define secureinitNSACR_CP10_MASK           ( 1UL << secureinitNSACR_CP10_POS )
 | 
			
		||||
#define secureinitNSACR_CP11_POS            ( 11UL )
 | 
			
		||||
#define secureinitNSACR_CP11_MASK           ( 1UL << secureinitNSACR_CP11_POS )
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
secureportNON_SECURE_CALLABLE void SecureInit_DePrioritizeNSExceptions( void )
 | 
			
		||||
{
 | 
			
		||||
    uint32_t ulIPSR;
 | 
			
		||||
 | 
			
		||||
    /* Read the Interrupt Program Status Register (IPSR) value. */
 | 
			
		||||
    secureportREAD_IPSR( ulIPSR );
 | 
			
		||||
 | 
			
		||||
    /* Do nothing if the processor is running in the Thread Mode. IPSR is zero
 | 
			
		||||
     * when the processor is running in the Thread Mode. */
 | 
			
		||||
    if( ulIPSR != 0 )
 | 
			
		||||
    {
 | 
			
		||||
        *( secureinitSCB_AIRCR ) = ( *( secureinitSCB_AIRCR ) & ~( secureinitSCB_AIRCR_VECTKEY_MASK | secureinitSCB_AIRCR_PRIS_MASK ) ) |
 | 
			
		||||
                                   ( ( 0x05FAUL << secureinitSCB_AIRCR_VECTKEY_POS ) & secureinitSCB_AIRCR_VECTKEY_MASK ) |
 | 
			
		||||
                                   ( ( 0x1UL << secureinitSCB_AIRCR_PRIS_POS ) & secureinitSCB_AIRCR_PRIS_MASK );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
secureportNON_SECURE_CALLABLE void SecureInit_EnableNSFPUAccess( void )
 | 
			
		||||
{
 | 
			
		||||
    uint32_t ulIPSR;
 | 
			
		||||
 | 
			
		||||
    /* Read the Interrupt Program Status Register (IPSR) value. */
 | 
			
		||||
    secureportREAD_IPSR( ulIPSR );
 | 
			
		||||
 | 
			
		||||
    /* Do nothing if the processor is running in the Thread Mode. IPSR is zero
 | 
			
		||||
     * when the processor is running in the Thread Mode. */
 | 
			
		||||
    if( ulIPSR != 0 )
 | 
			
		||||
    {
 | 
			
		||||
        /* CP10 = 1 ==> Non-secure access to the Floating Point Unit is
 | 
			
		||||
         * permitted. CP11 should be programmed to the same value as CP10. */
 | 
			
		||||
        *( secureinitNSACR ) |= ( secureinitNSACR_CP10_MASK | secureinitNSACR_CP11_MASK );
 | 
			
		||||
 | 
			
		||||
        /* LSPENS = 0 ==> LSPEN is writable fron non-secure state. This ensures
 | 
			
		||||
         * that we can enable/disable lazy stacking in port.c file. */
 | 
			
		||||
        *( secureinitFPCCR ) &= ~( secureinitFPCCR_LSPENS_MASK );
 | 
			
		||||
 | 
			
		||||
        /* TS = 1 ==> Treat FP registers as secure i.e. callee saved FP
 | 
			
		||||
         * registers (S16-S31) are also pushed to stack on exception entry and
 | 
			
		||||
         * restored on exception return. */
 | 
			
		||||
        *( secureinitFPCCR ) |= ( secureinitFPCCR_TS_MASK );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,54 +1,54 @@
 | 
			
		|||
/*
 | 
			
		||||
 * FreeRTOS Kernel <DEVELOPMENT BRANCH>
 | 
			
		||||
 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: MIT
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 | 
			
		||||
 * this software and associated documentation files (the "Software"), to deal in
 | 
			
		||||
 * the Software without restriction, including without limitation the rights to
 | 
			
		||||
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 | 
			
		||||
 * the Software, and to permit persons to whom the Software is furnished to do so,
 | 
			
		||||
 * subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
 * copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 | 
			
		||||
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 | 
			
		||||
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 | 
			
		||||
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
			
		||||
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 *
 | 
			
		||||
 * https://www.FreeRTOS.org
 | 
			
		||||
 * https://github.com/FreeRTOS
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __SECURE_INIT_H__
 | 
			
		||||
#define __SECURE_INIT_H__
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief De-prioritizes the non-secure exceptions.
 | 
			
		||||
 *
 | 
			
		||||
 * This is needed to ensure that the non-secure PendSV runs at the lowest
 | 
			
		||||
 * priority. Context switch is done in the non-secure PendSV handler.
 | 
			
		||||
 *
 | 
			
		||||
 * @note This function must be called in the handler mode. It is no-op if called
 | 
			
		||||
 * in the thread mode.
 | 
			
		||||
 */
 | 
			
		||||
void SecureInit_DePrioritizeNSExceptions( void );
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Sets up the Floating Point Unit (FPU) for Non-Secure access.
 | 
			
		||||
 *
 | 
			
		||||
 * Also sets FPCCR.TS=1 to ensure that the content of the Floating Point
 | 
			
		||||
 * Registers are not leaked to the non-secure side.
 | 
			
		||||
 *
 | 
			
		||||
 * @note This function must be called in the handler mode. It is no-op if called
 | 
			
		||||
 * in the thread mode.
 | 
			
		||||
 */
 | 
			
		||||
void SecureInit_EnableNSFPUAccess( void );
 | 
			
		||||
 | 
			
		||||
#endif /* __SECURE_INIT_H__ */
 | 
			
		||||
/*
 | 
			
		||||
 * FreeRTOS Kernel <DEVELOPMENT BRANCH>
 | 
			
		||||
 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: MIT
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 | 
			
		||||
 * this software and associated documentation files (the "Software"), to deal in
 | 
			
		||||
 * the Software without restriction, including without limitation the rights to
 | 
			
		||||
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 | 
			
		||||
 * the Software, and to permit persons to whom the Software is furnished to do so,
 | 
			
		||||
 * subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
 * copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 | 
			
		||||
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 | 
			
		||||
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 | 
			
		||||
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
			
		||||
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 *
 | 
			
		||||
 * https://www.FreeRTOS.org
 | 
			
		||||
 * https://github.com/FreeRTOS
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __SECURE_INIT_H__
 | 
			
		||||
#define __SECURE_INIT_H__
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief De-prioritizes the non-secure exceptions.
 | 
			
		||||
 *
 | 
			
		||||
 * This is needed to ensure that the non-secure PendSV runs at the lowest
 | 
			
		||||
 * priority. Context switch is done in the non-secure PendSV handler.
 | 
			
		||||
 *
 | 
			
		||||
 * @note This function must be called in the handler mode. It is no-op if called
 | 
			
		||||
 * in the thread mode.
 | 
			
		||||
 */
 | 
			
		||||
void SecureInit_DePrioritizeNSExceptions( void );
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Sets up the Floating Point Unit (FPU) for Non-Secure access.
 | 
			
		||||
 *
 | 
			
		||||
 * Also sets FPCCR.TS=1 to ensure that the content of the Floating Point
 | 
			
		||||
 * Registers are not leaked to the non-secure side.
 | 
			
		||||
 *
 | 
			
		||||
 * @note This function must be called in the handler mode. It is no-op if called
 | 
			
		||||
 * in the thread mode.
 | 
			
		||||
 */
 | 
			
		||||
void SecureInit_EnableNSFPUAccess( void );
 | 
			
		||||
 | 
			
		||||
#endif /* __SECURE_INIT_H__ */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,140 +1,140 @@
 | 
			
		|||
/*
 | 
			
		||||
 * FreeRTOS Kernel <DEVELOPMENT BRANCH>
 | 
			
		||||
 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: MIT
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 | 
			
		||||
 * this software and associated documentation files (the "Software"), to deal in
 | 
			
		||||
 * the Software without restriction, including without limitation the rights to
 | 
			
		||||
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 | 
			
		||||
 * the Software, and to permit persons to whom the Software is furnished to do so,
 | 
			
		||||
 * subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
 * copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 | 
			
		||||
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 | 
			
		||||
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 | 
			
		||||
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
			
		||||
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 *
 | 
			
		||||
 * https://www.FreeRTOS.org
 | 
			
		||||
 * https://github.com/FreeRTOS
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __SECURE_PORT_MACROS_H__
 | 
			
		||||
#define __SECURE_PORT_MACROS_H__
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Byte alignment requirements.
 | 
			
		||||
 */
 | 
			
		||||
#define secureportBYTE_ALIGNMENT         8
 | 
			
		||||
#define secureportBYTE_ALIGNMENT_MASK    ( 0x0007 )
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Macro to declare a function as non-secure callable.
 | 
			
		||||
 */
 | 
			
		||||
#if defined( __IAR_SYSTEMS_ICC__ )
 | 
			
		||||
    #define secureportNON_SECURE_CALLABLE    __cmse_nonsecure_entry __root
 | 
			
		||||
#else
 | 
			
		||||
    #define secureportNON_SECURE_CALLABLE    __attribute__( ( cmse_nonsecure_entry ) ) __attribute__( ( used ) )
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Set the secure PRIMASK value.
 | 
			
		||||
 */
 | 
			
		||||
#define secureportSET_SECURE_PRIMASK( ulPrimaskValue ) \
 | 
			
		||||
    __asm volatile ( "msr primask, %0" : : "r" ( ulPrimaskValue ) : "memory" )
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Set the non-secure PRIMASK value.
 | 
			
		||||
 */
 | 
			
		||||
#define secureportSET_NON_SECURE_PRIMASK( ulPrimaskValue ) \
 | 
			
		||||
    __asm volatile ( "msr primask_ns, %0" : : "r" ( ulPrimaskValue ) : "memory" )
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Read the PSP value in the given variable.
 | 
			
		||||
 */
 | 
			
		||||
#define secureportREAD_PSP( pucOutCurrentStackPointer ) \
 | 
			
		||||
    __asm volatile ( "mrs %0, psp"  : "=r" ( pucOutCurrentStackPointer ) )
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Set the PSP to the given value.
 | 
			
		||||
 */
 | 
			
		||||
#define secureportSET_PSP( pucCurrentStackPointer ) \
 | 
			
		||||
    __asm volatile ( "msr psp, %0" : : "r" ( pucCurrentStackPointer ) )
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Read the PSPLIM value in the given variable.
 | 
			
		||||
 */
 | 
			
		||||
#define secureportREAD_PSPLIM( pucOutStackLimit ) \
 | 
			
		||||
    __asm volatile ( "mrs %0, psplim"  : "=r" ( pucOutStackLimit ) )
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Set the PSPLIM to the given value.
 | 
			
		||||
 */
 | 
			
		||||
#define secureportSET_PSPLIM( pucStackLimit ) \
 | 
			
		||||
    __asm volatile ( "msr psplim, %0" : : "r" ( pucStackLimit ) )
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Set the NonSecure MSP to the given value.
 | 
			
		||||
 */
 | 
			
		||||
#define secureportSET_MSP_NS( pucMainStackPointer ) \
 | 
			
		||||
    __asm volatile ( "msr msp_ns, %0" : : "r" ( pucMainStackPointer ) )
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Set the CONTROL register to the given value.
 | 
			
		||||
 */
 | 
			
		||||
#define secureportSET_CONTROL( ulControl ) \
 | 
			
		||||
    __asm volatile ( "msr control, %0" : : "r" ( ulControl ) : "memory" )
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Read the Interrupt Program Status Register (IPSR) value in the given
 | 
			
		||||
 * variable.
 | 
			
		||||
 */
 | 
			
		||||
#define secureportREAD_IPSR( ulIPSR ) \
 | 
			
		||||
    __asm volatile ( "mrs %0, ipsr"  : "=r" ( ulIPSR ) )
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief PRIMASK value to enable interrupts.
 | 
			
		||||
 */
 | 
			
		||||
#define secureportPRIMASK_ENABLE_INTERRUPTS_VAL     0
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief PRIMASK value to disable interrupts.
 | 
			
		||||
 */
 | 
			
		||||
#define secureportPRIMASK_DISABLE_INTERRUPTS_VAL    1
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Disable secure interrupts.
 | 
			
		||||
 */
 | 
			
		||||
#define secureportDISABLE_SECURE_INTERRUPTS()        secureportSET_SECURE_PRIMASK( secureportPRIMASK_DISABLE_INTERRUPTS_VAL )
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Disable non-secure interrupts.
 | 
			
		||||
 *
 | 
			
		||||
 * This effectively disables context switches.
 | 
			
		||||
 */
 | 
			
		||||
#define secureportDISABLE_NON_SECURE_INTERRUPTS()    secureportSET_NON_SECURE_PRIMASK( secureportPRIMASK_DISABLE_INTERRUPTS_VAL )
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Enable non-secure interrupts.
 | 
			
		||||
 */
 | 
			
		||||
#define secureportENABLE_NON_SECURE_INTERRUPTS()     secureportSET_NON_SECURE_PRIMASK( secureportPRIMASK_ENABLE_INTERRUPTS_VAL )
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Assert definition.
 | 
			
		||||
 */
 | 
			
		||||
#define secureportASSERT( x )                      \
 | 
			
		||||
    if( ( x ) == 0 )                               \
 | 
			
		||||
    {                                              \
 | 
			
		||||
        secureportDISABLE_SECURE_INTERRUPTS();     \
 | 
			
		||||
        secureportDISABLE_NON_SECURE_INTERRUPTS(); \
 | 
			
		||||
        for( ; ; ) {; }                            \
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#endif /* __SECURE_PORT_MACROS_H__ */
 | 
			
		||||
/*
 | 
			
		||||
 * FreeRTOS Kernel <DEVELOPMENT BRANCH>
 | 
			
		||||
 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: MIT
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 | 
			
		||||
 * this software and associated documentation files (the "Software"), to deal in
 | 
			
		||||
 * the Software without restriction, including without limitation the rights to
 | 
			
		||||
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 | 
			
		||||
 * the Software, and to permit persons to whom the Software is furnished to do so,
 | 
			
		||||
 * subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
 * copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 | 
			
		||||
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 | 
			
		||||
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 | 
			
		||||
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
			
		||||
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 *
 | 
			
		||||
 * https://www.FreeRTOS.org
 | 
			
		||||
 * https://github.com/FreeRTOS
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __SECURE_PORT_MACROS_H__
 | 
			
		||||
#define __SECURE_PORT_MACROS_H__
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Byte alignment requirements.
 | 
			
		||||
 */
 | 
			
		||||
#define secureportBYTE_ALIGNMENT         8
 | 
			
		||||
#define secureportBYTE_ALIGNMENT_MASK    ( 0x0007 )
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Macro to declare a function as non-secure callable.
 | 
			
		||||
 */
 | 
			
		||||
#if defined( __IAR_SYSTEMS_ICC__ )
 | 
			
		||||
    #define secureportNON_SECURE_CALLABLE    __cmse_nonsecure_entry __root
 | 
			
		||||
#else
 | 
			
		||||
    #define secureportNON_SECURE_CALLABLE    __attribute__( ( cmse_nonsecure_entry ) ) __attribute__( ( used ) )
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Set the secure PRIMASK value.
 | 
			
		||||
 */
 | 
			
		||||
#define secureportSET_SECURE_PRIMASK( ulPrimaskValue ) \
 | 
			
		||||
    __asm volatile ( "msr primask, %0" : : "r" ( ulPrimaskValue ) : "memory" )
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Set the non-secure PRIMASK value.
 | 
			
		||||
 */
 | 
			
		||||
#define secureportSET_NON_SECURE_PRIMASK( ulPrimaskValue ) \
 | 
			
		||||
    __asm volatile ( "msr primask_ns, %0" : : "r" ( ulPrimaskValue ) : "memory" )
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Read the PSP value in the given variable.
 | 
			
		||||
 */
 | 
			
		||||
#define secureportREAD_PSP( pucOutCurrentStackPointer ) \
 | 
			
		||||
    __asm volatile ( "mrs %0, psp"  : "=r" ( pucOutCurrentStackPointer ) )
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Set the PSP to the given value.
 | 
			
		||||
 */
 | 
			
		||||
#define secureportSET_PSP( pucCurrentStackPointer ) \
 | 
			
		||||
    __asm volatile ( "msr psp, %0" : : "r" ( pucCurrentStackPointer ) )
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Read the PSPLIM value in the given variable.
 | 
			
		||||
 */
 | 
			
		||||
#define secureportREAD_PSPLIM( pucOutStackLimit ) \
 | 
			
		||||
    __asm volatile ( "mrs %0, psplim"  : "=r" ( pucOutStackLimit ) )
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Set the PSPLIM to the given value.
 | 
			
		||||
 */
 | 
			
		||||
#define secureportSET_PSPLIM( pucStackLimit ) \
 | 
			
		||||
    __asm volatile ( "msr psplim, %0" : : "r" ( pucStackLimit ) )
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Set the NonSecure MSP to the given value.
 | 
			
		||||
 */
 | 
			
		||||
#define secureportSET_MSP_NS( pucMainStackPointer ) \
 | 
			
		||||
    __asm volatile ( "msr msp_ns, %0" : : "r" ( pucMainStackPointer ) )
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Set the CONTROL register to the given value.
 | 
			
		||||
 */
 | 
			
		||||
#define secureportSET_CONTROL( ulControl ) \
 | 
			
		||||
    __asm volatile ( "msr control, %0" : : "r" ( ulControl ) : "memory" )
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Read the Interrupt Program Status Register (IPSR) value in the given
 | 
			
		||||
 * variable.
 | 
			
		||||
 */
 | 
			
		||||
#define secureportREAD_IPSR( ulIPSR ) \
 | 
			
		||||
    __asm volatile ( "mrs %0, ipsr"  : "=r" ( ulIPSR ) )
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief PRIMASK value to enable interrupts.
 | 
			
		||||
 */
 | 
			
		||||
#define secureportPRIMASK_ENABLE_INTERRUPTS_VAL     0
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief PRIMASK value to disable interrupts.
 | 
			
		||||
 */
 | 
			
		||||
#define secureportPRIMASK_DISABLE_INTERRUPTS_VAL    1
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Disable secure interrupts.
 | 
			
		||||
 */
 | 
			
		||||
#define secureportDISABLE_SECURE_INTERRUPTS()        secureportSET_SECURE_PRIMASK( secureportPRIMASK_DISABLE_INTERRUPTS_VAL )
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Disable non-secure interrupts.
 | 
			
		||||
 *
 | 
			
		||||
 * This effectively disables context switches.
 | 
			
		||||
 */
 | 
			
		||||
#define secureportDISABLE_NON_SECURE_INTERRUPTS()    secureportSET_NON_SECURE_PRIMASK( secureportPRIMASK_DISABLE_INTERRUPTS_VAL )
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Enable non-secure interrupts.
 | 
			
		||||
 */
 | 
			
		||||
#define secureportENABLE_NON_SECURE_INTERRUPTS()     secureportSET_NON_SECURE_PRIMASK( secureportPRIMASK_ENABLE_INTERRUPTS_VAL )
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Assert definition.
 | 
			
		||||
 */
 | 
			
		||||
#define secureportASSERT( x )                      \
 | 
			
		||||
    if( ( x ) == 0 )                               \
 | 
			
		||||
    {                                              \
 | 
			
		||||
        secureportDISABLE_SECURE_INTERRUPTS();     \
 | 
			
		||||
        secureportDISABLE_NON_SECURE_INTERRUPTS(); \
 | 
			
		||||
        for( ; ; ) {; }                            \
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#endif /* __SECURE_PORT_MACROS_H__ */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue