/*********************************************************************************************************************** * FILE DESCRIPTION * ------------------------------------------------------------------------------------------------------------------*/ /** \file * \brief Application dependent routines * * \note Please note, that this file contains a collection of callback functions to be used with the * Flash Bootloader. These functions may influence the behavior of the bootloader in principle. * Therefore, great care must be taken to verify the correctness of the implementation. * The contents of the originally delivered files are only examples resp. implementation proposals. * With regard to the fact that these functions are meant for demonstration purposes only, Vector * Informatik's liability shall be expressly excluded in cases of ordinary negligence, to the extent * admissible by law or statute. * * -------------------------------------------------------------------------------------------------------------------- * COPYRIGHT * -------------------------------------------------------------------------------------------------------------------- * \par Copyright * \verbatim * Copyright (c) 2025 by Vector Informatik GmbH. All rights reserved. * * This software is copyright protected and proprietary to Vector Informatik GmbH. * Vector Informatik GmbH grants to you only those rights as set out in the license conditions. * All other rights remain with Vector Informatik GmbH. * \endverbatim */ /**********************************************************************************************************************/ /*********************************************************************************************************************** * REVISION HISTORY * -------------------------------------------------------------------------------------------------------------------- * Version Date Author Change Id Description * -------------------------------------------------------------------------------------------------------------------- * 01.00.00 2019-01-28 visrie - Initial version * 01.01.00 2019-02-18 vismvi ESCAN00102171 Variable declared but never referenced * visrie ESCAN00102310 Added callout to check reprogramming flag * 01.01.01 2019-03-07 visrie ESCAN00102386 Fixed compiler error in ApplFbl_DetEntryHandler * ESCAN00102399 Check NvPattern only for non-RAM blocks * 02.00.00 2019-05-02 visrie ESCAN00102518 Added support to read block/application validity from NV-Memory * ESCAN00102761 Added support for 3rd Party Tricore HSM * ESCAN00103026 Provide BmHeader instead of StartAddress to ApplFblBmStartSoftware * 03.00.00 2019-07-17 visrie ESCAN00103750 Removed target order list configuration * 03.01.00 2019-08-14 visrie FBL-487 Exclude callouts if overwritten by OEM/HW layer * 03.01.01 2019-09-04 visrcn ESCAN00103607 Memory qualifier mismatch * 04.00.00 2019-12-04 visrie FBL-456 Updated to new LibSecBoot interface * ESCAN00105135 Added support for new BRS API * 04.01.00 2020-01-16 visrie FBL-524 Added support for vHsm SecBoot library * 05.00.00 2020-04-09 visrie FBL-1016 Support new vBaseEnv, added support for VTT * 05.01.00 2020-04-29 vistmo FBL-1584 Added OTA startup support * 05.02.00 2020-08-13 vistmo FBL-1489 Added support for OTA swap activation * 05.02.01 2021-03-17 vishor ESCAN00108386 ApplFblBmIsValidBlock implementation does not consider * all possible use cases * FBL-3018 No changes * 05.03.00 2021-08-11 visrie FBL-3394 Move default implementation of CheckReprogFlag into FblBm_Ap * 05.04.00 2021-09-17 visjdn FBL-3865 Add default SecBoot implementation for GHS/Escrypt * 05.04.01 2022-04-06 vismix FBL-4773 Support THUMB mode * 05.05.00 2022-04-07 vishor FBL-4822 Add support for new MagicFlag value and Swap API * 05.05.01 2022-06-23 vismix ESCAN00111879 Boot manager does not wait for HSM update recovery * 05.06.00 2022-07-13 vismix FBL-5391 Add callout for missing optional dependency * 05.06.01 2022-11-29 vishor ESCAN00112986 Compiler error: Undefined symbols * ApplFblPreMemDriver/ApplFblPostMemDriver * 05.07.00 2023-06-29 vistbe FBL-7052 Add evaluation of ActivationPending * 05.07.01 2023-12-18 visrie ESCAN00104829 Compiler error: Det.h missing in GENy based standalone BM * ESCAN00111036 Compiler error: 'kFblApplicationValid' may be undeclared * ESCAN00115752 No changes * 05.08.00 2024-05-16 vishor FBL-8602 Add support for OEM updater solution * 05.09.00 2025-05-23 dganesh FBL-9715 Extend presence pattern to connect validity information **********************************************************************************************************************/ #define BM_AP_SOURCE /*********************************************************************************************************************** * INCLUDES **********************************************************************************************************************/ #include "bm_ap.h" #include "bm_main.h" #include "fbl_inc.h" #include "fbl_main_types.h" #if defined( FBLNVPATTERN_ENABLE_SIGN_PRESENCE_PATTERN ) # include "Csm.h" #endif /* FBLNVPATTERN_ENABLE_SIGN_PRESENCE_PATTERN */ # if defined( FBLBM_ENABLE_STANDALONE_MODE ) # include "Det.h" # endif #if defined( FBLBM_ENABLE_SECURE_BOOT ) # include "fbl_secboot.h" # include "Csm.h" # include "Crypto_30_vHsm.h" #endif /* FBLBM_AP_ENABLE_3RD_PARTY_TRICORE_HSM_USED */ # include "BrsHw.h" /*********************************************************************************************************************** * VERSION **********************************************************************************************************************/ #if ( FBLBM_AP_VERSION != 0x0509u ) || \ ( FBLBM_AP_RELEASE_VERSION != 0x00u ) # error "Error in bm_ap.c: Source and Header file are inconsistent!" #endif /*********************************************************************************************************************** * DEFINES **********************************************************************************************************************/ #if defined( _MICROSOFT_C_VTT_ ) # define FBLBM_AP_ENABLE_VTT_USECASE #endif /* _MICROSOFT_C_VTT_ */ /* If no explicit LB for the LBT exists use the bootloader LB */ #if !defined( FBL_MTAB_LBT_BLOCK_NUMBER ) # define FBL_MTAB_LBT_BLOCK_NUMBER FBL_MTAB_BOOTLOADER_BLOCK_NUMBER #endif /* FBL_MTAB_LBT_BLOCK_NUMBER */ /* Helper macro to get number of array entries */ #if defined( FBLBMAP_ARRAY_SIZE ) #else # define FBLBMAP_ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) /* PRQA S 3453 */ /* MD_MSR_FctLikeMacro */ #endif #if defined( FBLBM_AP_CALLOUT_CHECK_TARGET_VALIDITY ) && \ !defined( FBL_ENABLE_PRESENCE_PATTERN ) /** Compatibility define in case OEM layer uses different macro scheme */ # if !defined( kFblApplicationValid ) # if defined( kEepApplConsistent ) # define kFblApplicationValid kEepApplConsistent # else # error "kFblApplicationValid not defined or can't be mapped to an equivalent define/value." /* TODO_CUSTOMER: Adjust the following define to map kFblApplicationValid to the correct value/define used by the OEM */ /* #define kFblApplicationValid */ # endif # endif /* !kFblApplicationValid */ #endif /* FBLBM_AP_CALLOUT_CHECK_TARGET_VALIDITY && !FBL_ENABLE_PRESENCE_PATTERN */ #if defined( FBLNVPATTERN_ENABLE_SIGN_PRESENCE_PATTERN ) /** Key size of signed presence pattern */ # define FBLBM_SIGNED_PP_KEY_SIZE 0x10u #endif /* FBLNVPATTERN_ENABLE_SIGN_PRESENCE_PATTERN */ /*********************************************************************************************************************** * LOCAL DATA **********************************************************************************************************************/ #define FBLBMAP_START_SEC_VAR #include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */ #if defined( FBLBM_ENABLE_UPDATER_FAILSAFE ) V_MEMRAM0 static V_MEMRAM1 vuintx V_MEMRAM2 g_ApplFblBmSearchUpdaterHeaderIndex; #endif /* FBLBM_ENABLE_UPDATER_FAILSAFE */ #define FBLBMAP_STOP_SEC_VAR #include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */ /*********************************************************************************************************************** * LOCAL FUNCTION PROTOTYPES **********************************************************************************************************************/ #if defined( FBLBM_ENABLE_SECURE_BOOT ) # define FBLBMAP_RAMCODE_START_SEC_CODE # include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */ static void ApplFblBmWaitForHsm(void); # define FBLBMAP_RAMCODE_STOP_SEC_CODE # include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */ #endif /* FBLBM_ENABLE_SECURE_BOOT */ /*********************************************************************************************************************** * LOCAL FUNCTIONS **********************************************************************************************************************/ #if defined( FBLBM_ENABLE_SECURE_BOOT ) # define FBLBMAP_RAMCODE_START_SEC_CODE # include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */ /*********************************************************************************************************************** * ApplFblBmWaitForHsm **********************************************************************************************************************/ /*! \brief Wait until vHSM is ready **********************************************************************************************************************/ static void ApplFblBmWaitForHsm(void) { Std_ReturnType retVal; uint32 keyLength; uint32 hsm2host; uint32 host2hsm; /* Wait until vHsm has been started */ do { keyLength = 4u; retVal = Csm_KeyElementGet(0u, CRYPTO_KE_CUSTOM_VHSM_STATUS_HSM2HOST, (uint8 *)&hsm2host, &keyLength); assertFblUser(retVal == E_OK, kFblSysAssertDet); } while (hsm2host == 0u); /* When a vHsmUpd is pending */ if ((hsm2host & (1uL << CRYPTO_30_VHSM_HSM2HOST_UPDATERRUNNING)) == (1uL << CRYPTO_30_VHSM_HSM2HOST_UPDATERRUNNING)) { keyLength = 4u; # error "Comment this line if vHsmUpdater is not used. If vHsmUpdater is used, please assign the value configured in the vHsm-updater to host2hsm below" host2hsm = 0x80000000u; /* Set configured Bit pattern to signalize the vHsmUpd that update can be started */ retVal = Csm_KeyElementSet(0u, CRYPTO_KE_CUSTOM_VHSM_STATUS_HOST2HSM, (uint8 *)&host2hsm, keyLength); assertFblUser(retVal == E_OK, kFblSysAssertDet); /* Wait until vHsmUpd has been finished */ do { FblLookForWatchdogVoid(); keyLength = 4u; retVal = Csm_KeyElementGet(0u, CRYPTO_KE_CUSTOM_VHSM_STATUS_HSM2HOST, (uint8 *)&hsm2host, &keyLength); assertFblUser(retVal == E_OK, kFblSysAssertDet); } while ((hsm2host & ((1u << CRYPTO_30_VHSM_HSM2HOST_READY) | (1u << CRYPTO_30_VHSM_HSM2HOST_ACTIVE))) != ((1u << CRYPTO_30_VHSM_HSM2HOST_READY) | (1u << CRYPTO_30_VHSM_HSM2HOST_ACTIVE))); } /* Wait until vHsm is ready */ Crypto_30_vHsm_WaitForHsmRam(); } # define FBLBMAP_RAMCODE_STOP_SEC_CODE # include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */ #endif /* FBLBM_ENABLE_SECURE_BOOT */ /*********************************************************************************************************************** * GLOBAL FUNCTIONS **********************************************************************************************************************/ #define FBLBMAP_START_SEC_CODE #include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */ /*********************************************************************************************************************** * ApplFblBmPowerOnPre **********************************************************************************************************************/ /*! \brief Initialization callout **********************************************************************************************************************/ void ApplFblBmPowerOnPre( void ) { } /*********************************************************************************************************************** * ApplFblBmPowerOnPost **********************************************************************************************************************/ /*! \brief Initialization callout **********************************************************************************************************************/ void ApplFblBmPowerOnPost( void ) { #if defined( FBL_ENABLE_OTA ) vOtaM_InitMemory(); #endif /* FBL_ENABLE_OTA */ } /*********************************************************************************************************************** * ApplFblBmInitPre **********************************************************************************************************************/ /*! \brief Initialization callout **********************************************************************************************************************/ void ApplFblBmInitPre( void ) { # if defined( BRS_FBL_LEGACY ) # if defined( BRSHW_PREINIT_AVAILABLE ) /* HW specific pre-initialization. */ BrsHwPreInitPowerOn(); # endif /* BRSHW_PREINIT_AVAILABLE */ # if defined( BRS_ENABLE_WATCHDOG ) /* Disable Watchdog */ BrsHwWatchdogInitPowerOn(); # endif /* BRS_ENABLE_WATCHDOG */ # if defined( BRS_ENABLE_PLLCLOCKS ) /* Initialize the PLLs. */ BrsHwPllInitPowerOn(); # endif /* BRS_ENABLE_PLLCLOCKS */ # if defined( BRSHW_DISABLE_ECC_AVAILABLE ) /* Disable Flash ECC error reporting. */ BrsHwDisableEccErrorReporting(); # endif /* BRSHW_DISABLE_ECC_AVAILABLE */ # if defined( FBL_ENABLE_PRE_TIMERINIT ) /* Timer is stopped by mode switch and has to be re-initialized. */ FblTimerInit(); # endif /* FBL_ENABLE_PRE_TIMERINIT */ # endif /* BRS_FBL_LEGACY */ } /*********************************************************************************************************************** * ApplFblBmInitPost **********************************************************************************************************************/ /*! \brief Initialization callout **********************************************************************************************************************/ void ApplFblBmInitPost( void ) { #if defined( FBLBM_ENABLE_SECURE_BOOT ) volatile vuint8 executeTestcode = kFblOk; /* Wait until vHSM is ready */ ApplFblBmWaitForHsm(); if (executeTestcode == kFblOk) /* Testcode to initialize RAM key, to simulate written key */ { Std_ReturnType retVal; uint8 version[3u] = {0u}; uint32 versionLength = sizeof( version ); Crypto_VerifyResultType result = CRYPTO_E_VER_NOT_OK; const uint8 key[16u] = {0u}; uint8 mac[16u] = {0u}; const uint8 data[16u] = {0u}; uint32 length = sizeof( mac ); /* Get the Version of the vHsm Firmware */ retVal = Crypto_30_vHsm_KeyElementGet( CryptoConf_CryptoKey_vHsm_Info, CRYPTO_KE_CUSTOM_VHSM_VERSION, version, &versionLength ); /* Fill the key used for the CMAC and set it to valid */ retVal |= Csm_KeyElementSet( CsmConf_CsmKey_CsmKey_SymmetricKey, CRYPTO_KE_MAC_KEY, key, sizeof( key ) ); retVal |= Csm_KeySetValid( CsmConf_CsmKey_CsmKey_SymmetricKey ); /* Generate the CMAC with the software implementation on the vHsm */ retVal |= Csm_MacGenerate( CsmConf_CsmJob_CsmJob_MacGen_Key1, CRYPTO_OPERATIONMODE_SINGLECALL, data, sizeof( data ), mac, &length ); retVal |= Csm_MacVerify( CsmConf_CsmJob_CsmJob_MacVer_Key1, CRYPTO_OPERATIONMODE_SINGLECALL, data, sizeof( data ), mac, sizeof( mac ) * 8u, &result ); if (retVal != E_OK) { while (1u) { ; } } } #endif /* FBLBM_ENABLE_SECURE_BOOT */ #if defined( FBL_ENABLE_OTA ) if (vOtaM_Init() != E_OK) { /* PRQA S 2741, 4558 1 */ /* MD_FblBmAp_2741_4558 */ assertFblUser(0u, kFblSysAssertInitializationFailed); } #endif /* FBL_ENABLE_OTA */ } #if defined( FBLBM_AP_CALLOUT_RESET ) /*********************************************************************************************************************** * ApplFblBmReset **********************************************************************************************************************/ /*! \brief Issue Reset **********************************************************************************************************************/ void ApplFblBmReset(void) { /* Reset ECU */ BrsHwSoftwareResetECU(); } #endif /* FBLBM_AP_CALLOUT_RESET */ #if defined( FBLBM_AP_CALLOUT_CHECK_TARGET_VALIDITY ) /*********************************************************************************************************************** * ApplFblBmCheckTargetValidity **********************************************************************************************************************/ /*! \brief Checks the validity of the target (Usually: Is the Application Validity Presence Pattern set) * \param[in] targetHandle Target handle (e.g. Bootloader, Application, Updater) * \return Result of operation * kFblOk when operation succeeded * kFblFailed otherwise **********************************************************************************************************************/ /* PRQA S 6080 1 */ /* MD_MSR_STMIF */ tFblResult ApplFblBmCheckTargetValidity(tFblBmHdrTargetHandle targetHandle) { tFblResult result; # if defined( FBL_ENABLE_PRESENCE_PATTERN ) vuint8 blockNo; tBlockDescriptor blockDescriptor; vuint8 device; # else vuint8 applValidity; # endif /* Check overall application validity for Application target */ if (targetHandle == FBLBMHDR_TARGET_APPL) { result = kFblFailed; # if defined( FBL_ENABLE_PRESENCE_PATTERN ) /* Check if any PP for appl validity is set */ blockNo = 0u; while ((blockNo < FblLbtGetBlockCount()) && (result != kFblOk)) { if (kFblOk == FblLbtGetBlockDescriptorByNr(blockNo, &blockDescriptor)) { if (kFblOk == FblMemGetDeviceByRange(blockDescriptor.blockStartAddress, blockDescriptor.blockLength, &device)) { # if defined( kMioDeviceRam ) /* Do not check the presence pattern for RAM */ if (device != kMioDeviceRam) # endif { result = FblNvPatternGet(&blockDescriptor, kFblNvPatternId_ApplValidity); } } } /* Prepare index for next loop */ blockNo++; } # else /* Read validity from NV-memory */ if (ApplFblNvReadApplValidity(&applValidity) == kFblOk) { if (applValidity == kFblApplicationValid) { result = kFblOk; } } # endif } else { /* For all other targets, no overall validity is necessary */ result = kFblOk; } return result; } #endif /* FBLBM_AP_CALLOUT_CHECK_TARGET_VALIDITY */ #if defined( FBLBM_AP_CALLOUT_IS_VALIDBLOCK ) /*********************************************************************************************************************** * ApplFblBmIsValidBlock **********************************************************************************************************************/ /*! \brief Checks the preconditions of a specific target * \param[in] targetHandle Target handle (e.g. Bootloader, Application) * \param[in] pLogicalBlock Pointer to current logical block * \return Result of operation * kFblOk when operation succeeded * kFblFailed otherwise **********************************************************************************************************************/ tFblResult ApplFblBmIsValidBlock(tFblBmHdrTargetHandle targetHandle, const V_MEMRAM1 tBlockDescriptor V_MEMRAM2 V_MEMRAM3 * pLogicalBlock) { tFblResult result; # if defined( FBL_ENABLE_PRESENCE_PATTERN ) || defined( FBLBM_ENABLE_STANDALONE_MODE ) vuint8 device; # endif /* FBL_ENABLE_PRESENCE_PATTERN || FBLBM_ENABLE_STANDALONE_MODE */ # if !defined( FBL_ENABLE_PRESENCE_PATTERN ) vuint8 validityFlags[kEepSizeValidityFlags]; vuint8 validityMask; vuint8 byteIdx; # endif /* !FBL_ENABLE_PRESENCE_PATTERN */ # if (!defined( FBLBM_ENABLE_STANDALONE_MODE ) || defined( FBL_ENABLE_PRESENCE_PATTERN )) # if defined( V_ENABLE_USE_DUMMY_STATEMENT ) (void)targetHandle; # endif /* V_ENABLE_USE_DUMMY_STATEMENT */ # endif /* ( !FBLBM_ENABLE_STANDALONE_MODE || FBL_ENABLE_PRESENCE_PATTERN ) */ result = kFblFailed; # if defined( FBLBM_ENABLE_STANDALONE_MODE ) && !defined( FBL_ENABLE_PRESENCE_PATTERN) # error "If presence pattern is disabled special handling must be configured for the FBL because \ validity flags are not available for the FBL." /* Perform presence pattern check only for FBL, use NV validity flags for other blocks */ if (targetHandle == FBLBMHDR_TARGET_FBL) # endif /* FBLBM_ENABLE_STANDALONE_MODE && !FBL_ENABLE_PRESENCE_PATTERN */ # if defined( FBL_ENABLE_PRESENCE_PATTERN ) || defined( FBLBM_ENABLE_STANDALONE_MODE ) { /* Check the presence pattern value */ if (kFblOk == FblMemGetDeviceByRange(pLogicalBlock->blockStartAddress, pLogicalBlock->blockLength, &device)) { # if defined( kMioDeviceRam ) /* Do not check the presence pattern for RAM */ if (device != kMioDeviceRam) # endif /* kMioDeviceRam */ { result = FblNvPatternGetByBlockDescriptor(pLogicalBlock, kFblNvPatternId_BlockValidity ); } } } # endif /* FBL_ENABLE_PRESENCE_PATTERN || FBLBM_ENABLE_STANDALONE_MODE */ # if !defined( FBL_ENABLE_PRESENCE_PATTERN ) # if defined( FBLBM_ENABLE_STANDALONE_MODE ) /* Check NV validity flags if block other than FBL is checked */ else # endif /* FBLBM_ENABLE_STANDALONE_MODE */ { /* Calculate index and mask for validity bit of logical block */ byteIdx = (pLogicalBlock->blockNr >> 0x03u); validityMask = (vuint8)(0x01u << (pLogicalBlock->blockNr & 0x07u)); /* Read validity information from non-volatile memory */ if (ApplFblNvReadValidityFlags(validityFlags) == kFblOk) { if ((validityFlags[byteIdx] & validityMask) == 0u) { /* Block is valid */ result = kFblOk; } } } # endif /* !FBL_ENABLE_PRESENCE_PATTERN */ return result; } #endif /* FBLBM_AP_CALLOUT_IS_VALIDBLOCK */ #if defined( FBLNVPATTERN_ENABLE_SIGN_PRESENCE_PATTERN ) # if defined( FBLBM_AP_CALLOUT_IS_VALIDPATTERN ) /*********************************************************************************************************************** * ApplFblBmCheckPresencePattern **********************************************************************************************************************/ /*! \brief Explicitly checks the presence pattern(excluding the CMAC) validity of the target * \param[in] targetHandle Target handle (e.g. Bootloader, Application) * \param[in] pLogicalBlock Pointer to current logical block * \return Result of operation * kFblOk when operation succeeded * kFblFailed otherwise **********************************************************************************************************************/ tFblResult ApplFblBmCheckPresencePattern(tFblBmHdrTargetHandle targetHandle, const V_MEMRAM1 tBlockDescriptor V_MEMRAM2 V_MEMRAM3 * pLogicalBlock) { tFblResult result; vuint8 device; IO_PositionType patternAddress; IO_SizeType patternLength; tFblNvPatternState patternState; # if defined( V_ENABLE_USE_DUMMY_STATEMENT ) (void)targetHandle; # endif /* V_ENABLE_USE_DUMMY_STATEMENT */ result = kFblFailed; /* Check the presence pattern value of Target */ if (kFblOk == FblMemGetDeviceByRange(pLogicalBlock->blockStartAddress, pLogicalBlock->blockLength, &device)) { # if defined( kMioDeviceRam ) /* Do not check the presence pattern for RAM */ if (device != kMioDeviceRam) # endif /* kMioDeviceRam */ { /* Check state of Target pattern */ patternState = FblNvPatternGetPatternState(pLogicalBlock, kFblNvPatternId_BlockValidity, &patternAddress, &patternLength); if ((patternState.markerState == FBL_NVPATTERN_STATE_EXPECTEDVALUE) && (patternState.maskState == FBL_NVPATTERN_STATE_ERASED)) { result = kFblOk; } } } return result; } # endif /* FBLBM_AP_CALLOUT_IS_VALIDPATTERN */ # if defined( FBLBM_AP_CALLOUT_GET_PP_SIGN_KEYEMPTY ) /*********************************************************************************************************************** * ApplFblBmGetPresPattSignInitStatus **********************************************************************************************************************/ /*! \brief Checks if now keys has been programmed so far Presence pattern * \return FBLBM_KEY_IS_AVAILABLE if the keys are already programmed FBLBM_KEY_IS_NOT_AVAILABLE else **********************************************************************************************************************/ tFblBmKeyEmptyResult ApplFblBmGetPresPattSignInitStatus( void ) { /* TODO_CUSTOMER: implement check if key is available here. This can be done by querying the HSM/SHE (depending * on the used hardware) or e.g. by checking a pattern in the flash which indicates that the FBL has written the key * into the Crypto. */ tFblBmKeyEmptyResult result; vuint8 key[FBLBM_SIGNED_PP_KEY_SIZE]; vuint32 keyLength; if (Csm_KeyElementGet(FblNvPattern_GetCsmKeyIdMac, CRYPTO_KE_CIPHER_KEY, key, (uint32*)&keyLength) != CRYPTO_E_KEY_NOT_AVAILABLE) { result = FBLBM_KEY_IS_AVAILABLE; } else { result = FBLBM_KEY_IS_NOT_AVAILABLE; } return result; } # endif /* FBLBM_AP_CALLOUT_GET_PP_SIGN_KEYEMPTY */ #endif /* FBLNVPATTERN_ENABLE_SIGN_PRESENCE_PATTERN */ #if defined( FBLBM_CALLOUT_IS_OPTIONALBLOCK ) /*********************************************************************************************************************** * ApplFblBmIsOptionalBlock **********************************************************************************************************************/ /*! \brief Callout when logical block is optional and not present * \param[in] targetHandle Target handle (e.g. Bootloader, Application) * \param[in] pLogicalBlock Pointer to current logical block **********************************************************************************************************************/ void ApplFblBmIsOptionalBlock(tFblBmHdrTargetHandle targetHandle, const V_MEMRAM1 tBlockDescriptor V_MEMRAM2 V_MEMRAM3 * pLogicalBlock) { # if defined( V_ENABLE_USE_DUMMY_STATEMENT ) (void)targetHandle; (void)pLogicalBlock; # endif /* V_ENABLE_USE_DUMMY_STATEMENT */ } #endif /* FBLBM_CALLOUT_IS_OPTIONALBLOCK */ #if defined( FBLBM_AP_CALLOUT_START_SOFTWARE ) /*********************************************************************************************************************** * ApplFblBmStartSoftware **********************************************************************************************************************/ /*! \brief This function is called to start a software (e.g. Bootloader) * \details Please note: The function will never return because control is handed over to the running software. * \param[in] bmHeader Pointer to the targets BM Header structure, which shall be started **********************************************************************************************************************/ void ApplFblBmStartSoftware(const V_MEMRAM1 tFblBmHdrHeader V_MEMRAM2 V_MEMRAM3 * bmHeader) { # if defined( BRS_INSTRUCTION_SET_THUMB ) JSR(bmHeader->bmEntryAddress | 1u); /* PRQA S 0305 */ /* MD_FblBmAp_0305 */ # else JSR(bmHeader->bmEntryAddress); /* PRQA S 0305 */ /* MD_FblBmAp_0305 */ # endif # if defined( FBL_ENABLE_SYSTEM_CHECK ) /* Code should never be reached */ while (1u) { ; } # endif /* FBL_ENABLE_SYSTEM_CHECK */ } #endif /* FBLBM_AP_CALLOUT_START_SOFTWARE* */ #if defined( FBLBM_AP_CALLOUT_FAILSAFE_UPDATER_USER_CHECK ) && defined( FBLBM_ENABLE_UPDATER_FAILSAFE_USER ) /*********************************************************************************************************************** * ApplFblBmFailsafeUpdaterUserCheck **********************************************************************************************************************/ /*! \brief This function can be used to implement a user-defined updater and provide its entry address * \details This function will be called if the user-defined updater feature is enabled and will control the rest * of the bootmanager program flow * \param[out] bmHeader Pointer to the BM Header structure whose jump address must be updated in case updater is found * \return kFblOk: User-defined updater is available, jump to address given by bmHeader->bmEntryAddress * kFblFailed: User-defined updater is not available, proceed to next state (failed state) **********************************************************************************************************************/ /* PRQA S 3673 1 */ /* MD_MSR_Rule8.13 */ tFblResult ApplFblBmFailsafeUpdaterUserCheck(V_MEMRAM1 tFblBmHdrHeader V_MEMRAM2 V_MEMRAM3 * bmHeader) { # if defined( V_ENABLE_USE_DUMMY_STATEMENT ) (void)bmHeader; # endif /* V_ENABLE_USE_DUMMY_STATEMENT */ /* TODO_CUSTOMER: Implement user updater check here. If the user updater is valid, set bmHeader->bmEntryAddress * to the jump address of the updater entry function and set return value to kFblOk */ return kFblFailed; } #endif #if defined( FBLBM_ENABLE_SECURE_BOOT ) # if defined( FBLBM_ENABLE_SECBOOT_FBL_INIT_KEY ) # if defined( FBLBM_AP_CALLOUT_GET_KEYEMPTY ) /*********************************************************************************************************************** * ApplFblBmGetKeyEmpty **********************************************************************************************************************/ /*! \brief Checks if now keys has been programmed so far * \return FBLBM_KEY_IS_AVAILABLE if the keys are already programmed FBLBM_KEY_IS_NOT_AVAILABLE else **********************************************************************************************************************/ tFblBmKeyEmptyResult ApplFblBmGetKeyEmpty( void ) { /* TODO_CUSTOMER: implement check if key is available here. This can be done by querying the HSM/SHE (depending * on the used hardware) or e.g. by checking a pattern in the flash which indicates that the FBL has written the key * into the Crypto. */ tFblBmKeyEmptyResult result; # error "No default implementation for this variant available." /* Per default assume that the key is available */ result = FBLBM_KEY_IS_AVAILABLE; return result; } # endif /* FBLBM_AP_CALLOUT_GET_KEYEMPTY */ # endif /* FBLBM_ENABLE_SECBOOT_FBL_INIT_KEY */ # if defined( FBLBM_ENABLE_SECBOOT_FBL_INIT_MAC ) # if defined( FBLBM_AP_CALLOUT_GET_FBL_CMACERASED ) /*********************************************************************************************************************** * ApplFblBmGetFblCmacErased **********************************************************************************************************************/ /*! \brief Checks if MACs for the FBL has been programmed so far * \return FBLBM_MAC_IS_AVAILABLE If the MACs of the FBL are already written * FBLBM_MAC_IS_NOT_AVAILABLE Else. E.g. because the FBL is just flashed by a debugger **********************************************************************************************************************/ tFblBmMacEmptyResult ApplFblBmGetFblCmacErased( const tFblBmBlockInfo * fblBlockInfo ) { /* TODO_CUSTOMER: implement check if CMAC is available here. This can be done by checking the CMAC content or e.g. * by checking a pattern in the flash which indicates that the FBL CMAC was already written */ tFblBmMacEmptyResult result; # if defined( V_ENABLE_USE_DUMMY_STATEMENT ) (void)fblBlockInfo; # endif /* V_ENABLE_USE_DUMMY_STATEMENT */ if (ApplFblSbIsInitialStartup() == kFblOk) { /* This is the first startup, the SecureBootSegments needs to be updated */ result = FBLBM_MAC_IS_NOT_AVAILABLE; } else { result = FBLBM_MAC_IS_AVAILABLE; } return result; } # endif /* FBLBM_AP_CALLOUT_GET_FBL_CMACERASED */ # endif /* FBLBM_ENABLE_SECBOOT_FBL_INIT_MAC */ #endif /* FBLBM_ENABLE_SECURE_BOOT */ #if defined( FBLBM_AP_CALLOUT_CHECKREPROGFLAG ) /*********************************************************************************************************************** * ApplFblBmCheckReprogFlag **********************************************************************************************************************/ /*! \brief Checks if a reprogramming request flag is set. * \return Result of operation * kFblOk when reprogramming request flag is set * kFblFailed otherwise **********************************************************************************************************************/ tFblResult ApplFblBmCheckReprogFlag( void ) { tFblResult result = kFblFailed; # if !defined( FBL_ENABLE_FBL_START ) vuint8 progReqFlag = 0u; # endif # if defined( FBL_ENABLE_FBL_START ) if (FblBmChkFblStartMagicFlag()) { /* FblStart magic flag is set, do not clear flag as the Bootloader requires it as well */ result = kFblOk; } # else /* Check the reprogramming request flag */ if (ApplFblNvReadProgReqFlag(&progReqFlag) == kFblOk) { if (progReqFlag == kEepFblReprogram) { /* UDS-Reprogramming flag is set, do not clear flag as the Bootloader requires it as well */ result = kFblOk; } # if defined( FBL_ENABLE_XCP ) else if (progReqFlag == kEepFblXcpProgram) { /* XCP-Reprogramming flag is set, do not clear flag as the Bootloader requires it as well */ result = kFblOk; } # endif # if defined( FBL_ENABLE_OTA ) else if (progReqFlag == kEepFblOtaReprogram) { /* OTA-Reprogramming flag is set, do not clear flag as the Bootloader requires it as well */ result = kFblOk; } # endif else { /* Nothing to do */ } } # endif /* FBL_ENABLE_FBL_START */ # if defined( FBLBM_MAIN_ENABLE_MAGICFLAG ) && \ defined( FBLBM_ENABLE_SECURE_BOOT ) && \ defined( FBLBM_MAIN_ENABLE_HARDWARE_SWAP ) if (FblBmChkSBUpdateMagicFlag()) { /* Start FBL in case of secure boot update */ result = kFblOk; } # endif # if defined( FBL_ENABLE_OTA ) if (vOtaM_GetState() == vOtaM_State_OtaRequest) { /* OTA request is pending -> bootloader should be started */ result = kFblOk; } # endif /* FBL_ENABLE_OTA */ return result; } #endif /* FBLBM_AP_CALLOUT_CHECKREPROGFLAG */ #if defined( FBLBM_ENABLE_UPDATER_FAILSAFE ) # if defined( FBLBM_AP_CALLOUT_SEARCH_FAILSAFE_UPDATER_INIT ) /*********************************************************************************************************************** * ApplFblBmSearchUpdaterHeaderInit **********************************************************************************************************************/ /*! \brief Prepare search for updater BmHeader location * \return Result of operation * kFblOk when operation succeeded * kFblFailed otherwise **********************************************************************************************************************/ tFblResult ApplFblBmSearchUpdaterHeaderInit(void) { g_ApplFblBmSearchUpdaterHeaderIndex = 0u; return kFblOk; } # endif /* FBLBM_AP_CALLOUT_SEARCH_FAILSAFE_UPDATER_INIT */ # if defined( FBLBM_AP_CALLOUT_SEARCH_FAILSAFE_UPDATER_HEADER_ADDRESS ) /*********************************************************************************************************************** * ApplFblBmSearchUpdaterHeaderAddress **********************************************************************************************************************/ /*! \brief Get address of possible location of a BmHeader for the Failsafe Updater * \param[out] headerAddress Address where the BmHeader could possible be located * \return Result of operation * kFblOk when operation succeeded * kFblFailed otherwise **********************************************************************************************************************/ tFblResult ApplFblBmSearchUpdaterHeaderAddress(vuint32 * headerAddress) { vuint32 offset = 0u; (* headerAddress) = FlashBlock[g_ApplFblBmSearchUpdaterHeaderIndex].begin + offset; return kFblOk; } # endif /* FBLBM_AP_CALLOUT_SEARCH_FAILSAFE_UPDATER_HEADER_ADDRESS */ # if defined( FBLBM_AP_CALLOUT_SEARCH_FAILSAFE_UPDATER_NEXT ) /*********************************************************************************************************************** * ApplFblBmSearchUpdaterHeaderNext **********************************************************************************************************************/ /*! \brief Get (next) possible location of a BmHeader for the Failsafe Updater * \return Result of operation * kFblOk when operation succeeded * kFblFailed otherwise **********************************************************************************************************************/ tFblResult ApplFblBmSearchUpdaterHeaderNext(void) { tFblResult result; g_ApplFblBmSearchUpdaterHeaderIndex++; if (g_ApplFblBmSearchUpdaterHeaderIndex < kNrOfFlashBlock) { result = kFblOk; } else { result = kFblFailed; } return result; } # endif /* FBLBM_AP_CALLOUT_SEARCH_FAILSAFE_UPDATER_NEXT */ #endif /* FBLBM_ENABLE_UPDATER_FAILSAFE */ #if defined( FBLBM_AP_CALLOUT_FATAL_ERROR ) /*********************************************************************************************************************** * ApplFblBmFatalError **********************************************************************************************************************/ /*! \brief This function is called in case no valid starting software was found * \details Provide here some final tasks which shall be executed **********************************************************************************************************************/ void ApplFblBmFatalError(tFblBmError error) { # if defined( V_ENABLE_USE_DUMMY_STATEMENT ) (void)error; # endif /* V_ENABLE_USE_DUMMY_STATEMENT */ # if defined( FBL_ENABLE_SYSTEM_CHECK ) /* Code should never be reached */ while (1u) { ; } # endif /* FBL_ENABLE_SYSTEM_CHECK */ } #endif /* FBLBM_AP_CALLOUT_FATAL_ERROR */ /*-- Other callout functions -----------------------------------------------------------------------------------------*/ #if defined( FBLBM_ENABLE_STANDALONE_MODE ) # if defined( FBL_ENABLE_ASSERTION ) /*********************************************************************************************************************** * ApplFblFatalError **********************************************************************************************************************/ /*! \brief Will be called in case of an urecoverable error **********************************************************************************************************************/ void ApplFblFatalError( FBL_DECL_ASSERT_EXTENDED_INFO(vuint8 errorCode) ) { /* Change this variable in debugger in order to return to caller */ volatile vuint8 stayInWhile = 1u; # if defined( V_ENABLE_USE_DUMMY_STATEMENT ) (void)errorCode; # endif /* V_ENABLE_USE_DUMMY_STATEMENT */ while (0u != stayInWhile) { FblLookForWatchdogVoid(); } } # endif /* FBL_ENABLE_ASSERTION */ # if (DET_ENABLED == STD_ON) /*********************************************************************************************************************** * ApplFbl_DetEntryHandler **********************************************************************************************************************/ /*! \brief Called by DET module to check if a DET error is intended bootloader behavior or not. * \param[in] ModuleId Code number of the encountered assertion * \param[in] InstanceId Name of the affected module (Only if extended info is enabled) * \param[in] ApiId Line number where the assertion occurred (Only if extended info is enabled) * \param[in] ErrorId Line number where the assertion occurred (Only if extended info is enabled) * \return Report if error should be handed over to DET or not **********************************************************************************************************************/ # if ((DET_AR_RELEASE_MAJOR_VERSION >= 4u) && (DET_AR_RELEASE_MINOR_VERSION >= 3u)) FUNC(Std_ReturnType, DET_CODE) ApplFbl_DetEntryHandler( uint16 ModuleId, uint8 InstanceId, uint8 ApiId, uint8 ErrorId ) # else FUNC(boolean, DET_APPL_CODE) ApplFbl_DetEntryHandler( uint16 ModuleId, uint8 InstanceId, uint8 ApiId, uint8 ErrorId ) # endif /* DET_AR_RELEASE_ */ { # if ((DET_AR_RELEASE_MAJOR_VERSION >= 4u) && (DET_AR_RELEASE_MINOR_VERSION >= 3u)) Std_ReturnType result = E_OK; /* Use result value of E_NOT_OK to ignore the DET */ # else boolean result = FALSE; /* Use result value of TRUE to ignore the DET */ # endif /* DET_AR_RELEASE_ */ # if defined( V_ENABLE_USE_DUMMY_STATEMENT ) (void)ModuleId; (void)InstanceId; (void)ApiId; (void)ErrorId; # endif /* V_ENABLE_USE_DUMMY_STATEMENT */ return result; } # endif /* DET_ENABLED == STD_ON */ # if defined( FBL_MIO_ENABLE_HOOKS ) /*********************************************************************************************************************** * ApplFblPreMemDriver **********************************************************************************************************************/ /*! \brief Function is called before the memory driver is executed. * \param[in] device Memory device, which is going to be used. * \param[in] function Function of the memory device, which is going to be called. **********************************************************************************************************************/ void ApplFblPreMemDriver( vuint8 device, vuint8 function ) { uint8 opMode; Std_ReturnType retVal; # if defined( V_ENABLE_USE_DUMMY_STATEMENT ) /* Parameters not used: avoid compiler warning */ (void)device; (void)function; # endif /* TODO_CUSTOMER: Adapt this example implementation to project-specific needs/requirements */ /* Suspend vHSM operations in data flash */ opMode = CRYPTO_30_VHSM_DATAFLASH_START; retVal = Csm_KeyElementSet(CsmConf_CsmKey_CsmKey_vHsm_Hardware, CRYPTO_KE_CUSTOM_VHSM_FLASH_OPERATION, &opMode, 1u); /* Suspend vHSM operations in code flash -> send it to RAM loop */ opMode = CRYPTO_30_VHSM_CODEFLASH_START; retVal |= Csm_KeyElementSet(CsmConf_CsmKey_CsmKey_vHsm_Hardware, CRYPTO_KE_CUSTOM_VHSM_FLASH_OPERATION, &opMode, 1u); /* Simulate DET functionality in case of any error */ assertFblUser(retVal == E_OK, kFblSysAssertDet); } /*********************************************************************************************************************** * ApplFblPostMemDriver **********************************************************************************************************************/ /*! \brief Function is called after the memory driver has finished the operation. * \param[in] device Memory device, which is going to be used. * \param[in] function Function of the memory device, which is going to be called. **********************************************************************************************************************/ void ApplFblPostMemDriver( vuint8 device, vuint8 function ) { uint8 opMode; Std_ReturnType retVal; # if defined( V_ENABLE_USE_DUMMY_STATEMENT ) /* Parameters not used: avoid compiler warning */ (void)device; (void)function; # endif /* TODO_CUSTOMER: Adapt this example implementation to project-specific needs/requirements */ /* Get vHSM back from RAM loop */ opMode = CRYPTO_30_VHSM_CODEFLASH_STOP; retVal = Csm_KeyElementSet(CsmConf_CsmKey_CsmKey_vHsm_Hardware, CRYPTO_KE_CUSTOM_VHSM_FLASH_OPERATION, &opMode, 1u); /* Give vHSM access to data flash operations */ opMode = CRYPTO_30_VHSM_DATAFLASH_STOP; retVal |= Csm_KeyElementSet(CsmConf_CsmKey_CsmKey_vHsm_Hardware, CRYPTO_KE_CUSTOM_VHSM_FLASH_OPERATION, &opMode, 1u); /* Simulate DET functionality in case of any error */ assertFblUser(retVal == E_OK, kFblSysAssertDet); } # endif /* FBL_MIO_ENABLE_HOOKS */ #endif /* FBLBM_ENABLE_STANDALONE_MODE */ #define FBLBMAP_STOP_SEC_CODE #include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */ /*********************************************************************************************************************** * MISRA DEVIATIONS **********************************************************************************************************************/ /* Justification for module-specific MISRA deviations: MD_FblBmAp_0305: Reason: Boot manager needs to jump to a memory location to start a target/software. Risk: Unintended jump to wrong memory location. Prevention: No prevention possible, address is defined by the corresponding target. MD_FblBmAp_0306: Reason: Address conversion between integer values and pointers is required to allow for hardware independent configuration and address range checks. Risk: The size of integer required to hold the result of a pointer cast is implementation-defined. Prevention: The size of the respective integer data type which holds the address value is adapted on a hardware specific basis. The correctness of the respective implementation is verified by runtime tests. MD_FblBmAp_2741_4558: Reason: Assertion macros have to be disabled in production code and are used only for development. Risk: Assertion code may be enabled in production code unintentionally. If a assertion condition is unexpectedly false, the code is active. A problem may occur if the Macro is additionally changed from single statement to multiple statement. Prevention: Macro is not allowed to be changed without review. Development code is automatically disabled via configuration of project state "Production". */ /*********************************************************************************************************************** * END OF FILE: BM_AP.C **********************************************************************************************************************/