FLEX-FORD-OBC-BM/Source/bsw/FblNvPattern/fbl_nvpattern.c

1307 lines
64 KiB
C
Raw Permalink Normal View History

2026-03-19 11:49:16 +01:00
/***********************************************************************************************************************
* FILE DESCRIPTION
* ------------------------------------------------------------------------------------------------------------------*/
/** \file
* \brief Implementation of pattern/mask based non-volatile information storage
*
* --------------------------------------------------------------------------------------------------------------------
* 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
* --------------------------------------------------------------------------------------------------------------------
* 02.00.00 2025-03-11 virjjn FBL-9704 Initial version
* 02.01.00 2025-06-19 dganesh FBL-11034 Improvements in extended presence pattern
**********************************************************************************************************************/
#define FBL_NVPATTERN_SOURCE
/***********************************************************************************************************************
* INCLUDES
**********************************************************************************************************************/
#include "fbl_inc.h"
#include "fbl_nvpattern.h"
/***********************************************************************************************************************
* VERSION
**********************************************************************************************************************/
#if ( FBLLIB_NVPATTERN_VERSION != 0x0201u ) || \
( FBLLIB_NVPATTERN_RELEASE_VERSION != 0x00u )
# error "Error in fbl_nvpattern.c: Source and header file are inconsistent!"
#endif
#if ( FBLLIB_NVPATTERN_VERSION != _FBLLIB_NVPATTERN_VERSION ) || \
( FBLLIB_NVPATTERN_RELEASE_VERSION != _FBLLIB_NVPATTERN_RELEASE_VERSION )
# error "Error in fbl_nvpattern.c: Source and v_ver.h are inconsistent!"
#endif
/***********************************************************************************************************************
* DEFINES
**********************************************************************************************************************/
/* Definition of marker/mask values and their size */
#if !defined( kFblNvMarkerValue )
# define kFblNvMarkerValue {0x73u, 0x6Au, 0x29u, 0x3Eu}
#endif /* kFblNvMarkerValue */
#if !defined( kFblNvMaskValue )
# define kFblNvMaskValue {0x8Cu, 0x95u, 0xD6u, 0xC1u}
#endif /* kFblNvMaskValue */
#if !defined( kFblNvPatternSize )
# define kFblNvPatternSize 4u
#endif /* kFblNvPatternSize */
/* Macro to calculate the page aligned size to hold a value of size len */
#define PAGE_ALIGN(len, align) (((len) + ((align) - 1u)) & ~((align) - 1u))
/* Macro to check if val is a power of two */
#define IS_POWOFTWO(val) (((val) & ~((val) - 1u)) == (val))
/* Size of write buffer with enough space to hold one marker/mask value */
#if ( FBL_MAX_SEGMENT_SIZE < kFblNvPatternSize )
# define kFblNvPatternSegmentSize PAGE_ALIGN(kFblNvPatternSize, FBL_MAX_SEGMENT_SIZE)
#else
# define kFblNvPatternSegmentSize FBL_MAX_SEGMENT_SIZE
#endif
/* Checks if tFblNvPatternId belongs to a block property or a pattern */
#define IS_VALID_PATTERN_ID(id) (((id) > kFblNvPatternId_Invalid) && ((id) < kFblNvPatternId_Separator))
#define IS_VALID_PROPERTY_ID(id) (((id) > kFblNvPatternId_Separator) && ((id) < kFblNvPatternId_Last))
/* Parameter value to skip comparison for function FblNvPatternGetPatternItemState */
#define DONT_COMPARE (vuint8*)0u
/* Enable the unexpected value check by default */
#if !defined( FBL_NVPATTERN_DISABLE_CHECK_UNEXPECTEDVALUE )
# define FBL_NVPATTERN_ENABLE_CHECK_UNEXPECTEDVALUE
#endif /* !FBL_NVPATTERN_DISABLE_CHECK_UNEXPECTEDVALUE && !FBL_NVPATTERN_ENABLE_CHECK_UNEXPECTEDVALUE */
/***********************************************************************************************************************
* TYPEDEFS
**********************************************************************************************************************/
/** Buffer with alignment to platform requirements */
typedef struct
{
vuint32 alignDummy; /**< Used to force 4Byte alignment */
vuint8 data[kFblNvPatternSegmentSize];
} tFblNvPatternAlignedBuffer;
/***********************************************************************************************************************
* LOCAL DATA
**********************************************************************************************************************/
#define FBLNVPATTERN_START_SEC_VAR
#include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
V_MEMRAM0 static V_MEMRAM1 tFblNvPatternAlignedBuffer V_MEMRAM2 pageBuffer;
#define FBLNVPATTERN_STOP_SEC_VAR
#include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
/***********************************************************************************************************************
* LOCAL FUNCTION PROTOTYPES
**********************************************************************************************************************/
#define FBLNVPATTERN_START_SEC_CODE
#include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
static tFblResult FblNvPatternWritePageAligned( const vuint8* pSrcBuffer, IO_PositionType address, IO_SizeType length );
static tFblNvPatternItemState FblNvPatternGetPatternItemState( IO_PositionType patternAddress, IO_SizeType length, const vuint8* compareValue );
static tFblResult FblNvPatternGetPatternBlockDescriptorByStartAddress( IO_PositionType patternStartAddress,
V_MEMRAM1 tBlockDescriptor V_MEMRAM2 V_MEMRAM3 * blockDescriptor );
static IO_SizeType FblNvPatternGetPatternOffset( tFblNvPatternId patternId,
V_MEMRAM1 IO_SizeType V_MEMRAM2 V_MEMRAM3 * patternLength );
/***********************************************************************************************************************
* LOCAL FUNCTIONS
**********************************************************************************************************************/
/***********************************************************************************************************************
* FblNvPatternWritePageAligned
**********************************************************************************************************************/
/*! \brief Writes data respecting the page size of the memory device
* \pre GetBaseAddr function has been called first
* \param[in] pSrcBuffer pointer to source data
* \param[in] address target address
* \param[in] length length of data
**********************************************************************************************************************/
static tFblResult FblNvPatternWritePageAligned( const vuint8* pSrcBuffer, IO_PositionType address, IO_SizeType length )
{
tFblResult result;
IO_SizeType i;
IO_SizeType writeGranularity;
IO_SizeType actualWriteLength;
IO_SizeType localLength;
IO_PositionType offset;
/* Initialize variables */
result = kFblOk;
localLength = length;
offset = 0u;
while (localLength > 0u)
{
(void)FblRealTimeSupport();
/* Determine page aligned write length, limit to buffer length */
if (localLength > kFblNvPatternSegmentSize)
{
writeGranularity = kFblNvPatternSegmentSize;
actualWriteLength = kFblNvPatternSegmentSize;
}
else
{
writeGranularity = PAGE_ALIGN(localLength, (IO_SizeType)MemDriver_SegmentSize);
actualWriteLength = localLength;
}
/* Fill buffer with payload data */
for (i = 0u; i < actualWriteLength; i++)
{
pageBuffer.data[i] = pSrcBuffer[i + offset];
}
/* Pad remaining buffer if necessary */
if (actualWriteLength < kFblNvPatternSegmentSize)
{
for (i = actualWriteLength; i < writeGranularity; i++)
{
pageBuffer.data[i] = 0u;
}
}
/* Call MIO to write data */
if (MemDriver_RWriteSync(pageBuffer.data, writeGranularity, address + offset) != IO_E_OK)
{
result = kFblFailed;
break;
}
/* Update variables */
localLength -= actualWriteLength;
offset += actualWriteLength;
}
return result;
}
/***********************************************************************************************************************
* FblNvPatternGetPatternItemState
**********************************************************************************************************************/
/*! \brief Reads one marker/mask and returns the state of it
* \pre Global variable memSegment is set to the block where the pattern is stored
* \param[in] patternAddress address of pattern item
* \param[in] length the length of the pattern item to read
* \param[in] compareValue pointer to expected pattern value (return ExpectedValue), 0 if no comparison is needed
* \return The state of the pattern item
**********************************************************************************************************************/
/* PRQA S 6010, 6030, 6080 1 */ /* MD_MSR_STPTH, MD_MSR_STCYC, MD_MSR_STMIF */
static tFblNvPatternItemState FblNvPatternGetPatternItemState( IO_PositionType patternAddress, IO_SizeType length, const vuint8* compareValue)
{
tFblNvPatternItemState itemState = FBL_NVPATTERN_STATE_READERROR;
vuint8 memErasedValue;
IO_SizeType currentReadLength;
IO_SizeType localLength = length;
IO_PositionType readOffset = 0u;
vuint32 i;
vuint32 countExpectedValue = 0u;
vuint32 countErasedValue = 0u;
/* Determine memory erased value of used device */
#if defined( FBL_ENABLE_MULTIPLE_MEM_DEVICES )
memErasedValue = memDrvLst[FlashBlock[memSegment].device].erasedValue;
#else
memErasedValue = FBL_FLASH_DELETED;
#endif
while (localLength > 0u)
{
/* Limit read length to buffer size */
if (localLength > kFblNvPatternSegmentSize)
{
currentReadLength = kFblNvPatternSegmentSize;
}
else
{
currentReadLength = localLength;
}
/* Read marker/mask */
switch (MemDriver_RReadSync(pageBuffer.data, currentReadLength, patternAddress + readOffset))
{
case IO_E_OK:
case IO_E_ERASED:
{
/* Read successful. Because some drivers don't return IO_E_ERASED,
* we have to assume that memory is erased if all bytes show the erased value
* and compare against the erased value later. */
itemState = FBL_NVPATTERN_STATE_ERASED;
break;
}
default:
{
/* Read error */
itemState = FBL_NVPATTERN_STATE_READERROR;
assertFbl(0u, kFblSysAssertParameterOutOfRange); /* PRQA S 2741, 4558 */ /* MD_FblNvPattern_Assertion */
break;
}
}
if (itemState == FBL_NVPATTERN_STATE_ERASED)
{
/* Check all bytes of marker/mask */
for (i = 0u; i < currentReadLength; i++)
{
/* Compare one byte of pattern against the expected value/erased value */
if ((compareValue != DONT_COMPARE) && (pageBuffer.data[i] == compareValue[readOffset + i]))
{
countExpectedValue++;
}
else if (pageBuffer.data[i] == memErasedValue)
{
countErasedValue++;
}
else /* (pageBuffer.data[i] != memErasedValue) */
{
/* This might happen in case of unintended writes to pattern area */
itemState = FBL_NVPATTERN_STATE_UNEXPECTEDVALUE;
}
/* In case of an unexpected value break out of the for loop */
if (itemState == FBL_NVPATTERN_STATE_UNEXPECTEDVALUE)
{
break;
}
}
/* Check if there were expected and erased bytes included */
if ( (countErasedValue != 0u)
&& (countExpectedValue != 0u))
{
itemState = FBL_NVPATTERN_STATE_UNEXPECTEDVALUE;
}
}
/* Abort in case of error */
if ((itemState == FBL_NVPATTERN_STATE_UNEXPECTEDVALUE) || (itemState == FBL_NVPATTERN_STATE_READERROR))
{
break;
}
/* Update variables */
localLength -= currentReadLength;
readOffset += currentReadLength;
}
/* Set itemState according to the counts */
if (length == 0u)
{
itemState = FBL_NVPATTERN_STATE_NOMEMSEGMENT;
}
else if (countErasedValue == length)
{
itemState = FBL_NVPATTERN_STATE_ERASED;
}
else if (countExpectedValue == length)
{
itemState = FBL_NVPATTERN_STATE_EXPECTEDVALUE;
}
else
{
/* itemState already set correctly */
}
return itemState;
}
/***********************************************************************************************************************
* FblNvPatternGetPatternBlockDescriptorByStartAddress
**********************************************************************************************************************/
/*! \brief Prepares a dummy block descriptor spaning only the pattern region
* \param[in] patternStartAddress Start address of pattern region
* \param[out] blockDescriptor Pointer to RAM buffer in which the dummy block descriptor can be stored
* \return kFblOk: block descriptor created successfully , kFblFailed: Else
**********************************************************************************************************************/
static tFblResult FblNvPatternGetPatternBlockDescriptorByStartAddress( IO_PositionType patternStartAddress,
V_MEMRAM1 tBlockDescriptor V_MEMRAM2 V_MEMRAM3 * blockDescriptor )
{
tFblResult result = kFblFailed;
IO_SizeType patternLength;
IO_SizeType patternRegionLength = 0u;
/* Get memory segment index */
memSegment = FblMemSegmentNrGet(patternStartAddress);
/* Check if a valid memory segment in flash block table was found */
if (memSegment >= 0)
{
/* Get offset for last pattern/property as this offset equals size of the complete pattern region */
/* PRQA S 4342 1 */ /* MD_FblNvPattern_4342 */
patternRegionLength = FblNvPatternGetPatternOffset((tFblNvPatternId)((vuintx)kFblNvPatternId_Last - 1u), &patternLength);
blockDescriptor->blockStartAddress = patternStartAddress;
blockDescriptor->blockLength = patternRegionLength;
result = kFblOk;
}
return result;
}
/***********************************************************************************************************************
* FblNvPatternGetPatternOffset
**********************************************************************************************************************/
/*! \brief Returns the offset for a certain pattern/property
* \details The returned offset is calculated from the end of the pattern region. Therefore a lower offset has
* the meaning that the respective pattern is located closer to the end of the pattern region.
* \pre Global variable memSegment is set to the block where the pattern region is stored
* \param[in] patternId ID of pattern/property for which the offset shall be calculated
* \param[out] patternOffset Pointer to RAM buffer to store the offset to the requested pattern
* \param[out] pPatternLength Pointer to RAM buffer to store the actual write address of the NvPattern or property
* \return Offset to the requested pattern
**********************************************************************************************************************/
static IO_SizeType FblNvPatternGetPatternOffset( tFblNvPatternId patternId,
V_MEMRAM1 IO_SizeType V_MEMRAM2 V_MEMRAM3 * patternLength )
{
IO_SizeType patternOffset = 0u;
IO_SizeType localPatternLength = 0u;
vuintx i;
vuintx upperBound;
/* Segment size must be a power of two */
assertFbl(IS_POWOFTWO(MemDriver_SegmentSize), kFblSysAssertParameterOutOfRange);
/* Adjust patternLength to write segment size of device */
localPatternLength = PAGE_ALIGN(kFblNvPatternSize, (IO_SizeType)MemDriver_SegmentSize);
/* Add size of NvPatterns to offset...
* Upper bound for loop is either the last NvPattern element if base address of block property has been requested
* or patternId in case the requested element is a NvPattern */
upperBound = (patternId > kFblNvPatternId_Separator) ? ((vuintx)kFblNvPatternId_Separator - 1u) : (vuintx)patternId;
for (i = 0u; i < upperBound; i++)
{
#if defined( FBL_NVPATTERN_ENABLE_MULTIPLE_VALIDATION )
patternOffset += (localPatternLength * ((IO_SizeType)fblNvPatternMultiplicity[i] * 2u));
#else
patternOffset += (localPatternLength * 2u);
#endif /* FBL_NVPATTERN_ENABLE_MULTIPLE_VALIDATION */
}
/* ... then add sizes of block property elements */
#if defined( FBL_NVPATTERN_ENABLE_BLOCK_PROPERTIES )
/* Skip this loop (set upperBound to 0) if the requested Id is not a block property,
* otherwise subtract kFblNvPatternId_Separator from pattern id to get the index into fblNvPatternElementLength */
upperBound = (patternId > kFblNvPatternId_Separator) ? ((vuintx)patternId - (vuintx)kFblNvPatternId_Separator) : 0u;
for (i = 0u; i < upperBound; i++)
{
patternOffset += PAGE_ALIGN(fblNvBlockProperties[i].length, (IO_SizeType)MemDriver_SegmentSize);
localPatternLength = PAGE_ALIGN(fblNvBlockProperties[i].length, (IO_SizeType)MemDriver_SegmentSize);
}
#endif /* FBL_NVPATTERN_ENABLE_BLOCK_PROPERTIES */
/* Put results into arguments */
*patternLength = localPatternLength;
return patternOffset;
}
/***********************************************************************************************************************
* GLOBAL FUNCTIONS
**********************************************************************************************************************/
/***********************************************************************************************************************
* FblNvPatternGetPatternState
**********************************************************************************************************************/
/*! \brief Determines the state of one or a set of marker/mask pairs.
* \details Iterates through all sub-patterns in case of multiple validation.
* Returns address and length of pattern which stores the currently relevant state.
* \param[in] pBlockDescriptor descriptor of the logical block which contains the NvPattern
* \param[in] patternId Id of pattern to read
* \param[out] pPatternAddress Pointer to RAM buffer which keeps the pattern base address
* \param[out] pPatternLength Pointer to RAM buffer which keeps the actual write length of the pattern
* \return The state of the (sub) pattern which holds the current state of the pattern
**********************************************************************************************************************/
tFblNvPatternState FblNvPatternGetPatternState( const V_MEMRAM1 tBlockDescriptor V_MEMRAM2 V_MEMRAM3 * pBlockDescriptor,
tFblNvPatternId patternId,
V_MEMRAM1 IO_PositionType V_MEMRAM2 V_MEMRAM3 * pPatternAddress,
V_MEMRAM1 IO_SizeType V_MEMRAM2 V_MEMRAM3 * pPatternLength )
{
vuint32 multiplicity;
tFblNvPatternState patternState;
IO_PositionType patternAddress;
vuint8 fblMarkerValue[] = kFblNvMarkerValue; /* PRQA S 3678 */ /* MD_FblNvPattern_3678_LocalVariable */
vuint8 fblMaskValue[] = kFblNvMaskValue; /* PRQA S 3678 */ /* MD_FblNvPattern_3678_LocalVariable */
/* PRQA S 2742, 2880 2 */ /* MD_FblNvPattern_Assertion */
assertFblUser(sizeof(fblMarkerValue) == kFblNvPatternSize, kFblSysAssertParameterOutOfRange);
assertFblUser(sizeof(fblMaskValue) == kFblNvPatternSize, kFblSysAssertParameterOutOfRange);
/* Initialize variables */
patternAddress = *pPatternAddress;
patternState.markerState = FBL_NVPATTERN_STATE_NOMEMSEGMENT;
patternState.maskState = FBL_NVPATTERN_STATE_NOMEMSEGMENT;
memSegment = -1;
/* Get Base Address of pattern if id is valid */
if (IS_VALID_PATTERN_ID(patternId))
{
memSegment = FblNvPatternGetBaseAddrByBlockDescriptor(pBlockDescriptor, patternId, &patternAddress, pPatternLength);
}
if (memSegment >= 0)
{
/* Determine number of sub-patterns */
#if defined( FBL_NVPATTERN_ENABLE_MULTIPLE_VALIDATION )
multiplicity = (vuint32)fblNvPatternMultiplicity[((vuintx)patternId - 1u)];
#else
multiplicity = 1u;
#endif
}
else
{
/* No memory segment found, abort */
multiplicity = 0u;
}
/* Go through all configured sub-patterns until we have found the sub-pattern which holds the most recent state */
while (multiplicity >= 1u)
{
/* Poll watchdog function */
(void)FblRealTimeSupport();
/* Read marker and mask area */
patternState.markerState = FblNvPatternGetPatternItemState(patternAddress, kFblNvPatternSize, fblMarkerValue);
patternState.maskState = FblNvPatternGetPatternItemState((patternAddress + *pPatternLength), kFblNvPatternSize, fblMaskValue);
if ( ((patternState.markerState == FBL_NVPATTERN_STATE_EXPECTEDVALUE) && (patternState.maskState == FBL_NVPATTERN_STATE_ERASED))
|| ((patternState.markerState == FBL_NVPATTERN_STATE_ERASED) && (patternState.maskState == FBL_NVPATTERN_STATE_ERASED)))
{
/* One pattern item is in erased state, this is the most recent state of the pattern */
break;
}
/* Get base address of next sub-pattern */
patternAddress += (*pPatternLength * 2u);
/* Decrement number of sub-patterns to process */
multiplicity--;
}
/* Write current address to passed argument pointer */
*pPatternAddress = patternAddress;
return patternState;
}
/***********************************************************************************************************************
* FblNvPatternGetPatternStateByStartAddress
**********************************************************************************************************************/
/*! \brief Determines the state of one or a set of marker/mask pairs.
* \details Iterates through all sub-patterns in case of multiple validation.
* Returns address and length of pattern which stores the currently relevant state.
* \param[in] patternStartAddress Start address of pattern region
* \param[in] patternId Id of pattern to read
* \param[out] pPatternAddress Pointer to RAM buffer which keeps the address of the pattern
* \param[out] pPatternLength Pointer to RAM buffer which keeps the actual write length of the pattern
* \return The state of the (sub) pattern which holds the current state of the pattern
**********************************************************************************************************************/
tFblNvPatternState FblNvPatternGetPatternStateByStartAddress( IO_PositionType patternStartAddress,
tFblNvPatternId patternId,
V_MEMRAM1 IO_PositionType V_MEMRAM2 V_MEMRAM3 * patternAddress,
V_MEMRAM1 IO_SizeType V_MEMRAM2 V_MEMRAM3 * patternLength )
{
tBlockDescriptor dummyBlockDescriptor = { 0u };
tFblNvPatternState patternState = { 0u };
if(FblNvPatternGetPatternBlockDescriptorByStartAddress(patternStartAddress, &dummyBlockDescriptor) == kFblOk)
{
patternState = FblNvPatternGetPatternState(&dummyBlockDescriptor, patternId, patternAddress, patternLength);
}
return patternState;
}
/***********************************************************************************************************************
* FblNvPatternGetBaseAddr
**********************************************************************************************************************/
/*! \brief Calculates base address and actual (write) length of pattern and mask
* \pre LBT is present
* \param[in] blockNr Logical block number
* \param[in] patternId ID of the pattern which shall be checked
* \param[out] pPatternAddress Pointer to RAM buffer which keeps the pattern base address
* \param[out] pPatternLength Pointer to RAM buffer which keeps the actual write length of the pattern
* \return memSegment of the pattern location or -1 in case of an error
**********************************************************************************************************************/
vsint16 FblNvPatternGetBaseAddr( vuint8 blockNr,
tFblNvPatternId patternId,
V_MEMRAM1 IO_PositionType V_MEMRAM2 V_MEMRAM3 * pPatternAddress,
V_MEMRAM1 IO_SizeType V_MEMRAM2 V_MEMRAM3 * pPatternLength )
{
tBlockDescriptor blockDescriptor;
tFblResult result;
result = FblLbtGetBlockDescriptorByNr(blockNr, &blockDescriptor);
if (result == kFblOk)
{
memSegment = FblNvPatternGetBaseAddrByBlockDescriptor(&blockDescriptor, patternId, pPatternAddress, pPatternLength);
}
else
{
/* Invalid block number passed, signal failure via return value */
memSegment = -1;
}
return memSegment;
}
/***********************************************************************************************************************
* FblNvPatternGetBaseAddrByBlockDescriptor
**********************************************************************************************************************/
/*! \brief Calculates base address and actual (write) length of an NvPattern or block property element
* \param[in] blockDescriptor Logical block descriptor
* \param[in] patternId ID of the NvPattern or block property for which the base address is requested
* \param[out] pPatternAddress Pointer to RAM buffer to store the base address
* \param[out] pPatternLength Pointer to RAM buffer to store the actual write address of the NvPattern or property
* \return memSegment of the pattern location or -1 in case of an error
**********************************************************************************************************************/
vsint16 FblNvPatternGetBaseAddrByBlockDescriptor( const V_MEMRAM1 tBlockDescriptor V_MEMRAM2 V_MEMRAM3 * blockDescriptor,
tFblNvPatternId patternId,
V_MEMRAM1 IO_PositionType V_MEMRAM2 V_MEMRAM3 * patternAddress,
V_MEMRAM1 IO_SizeType V_MEMRAM2 V_MEMRAM3 * patternLength )
{
IO_PositionType lastBlockAddress;
/* Get address of last byte in block */
lastBlockAddress = blockDescriptor->blockStartAddress + (blockDescriptor->blockLength - 1u);
/* Get corresponding memory segment index */
memSegment = FblMemSegmentNrGet(lastBlockAddress);
/* Check if a valid memory segment in flash block table was found */
if (memSegment >= 0)
{
IO_SizeType offsetLength = FblNvPatternGetPatternOffset(patternId, patternLength);
/* Calculate pattern address */
*patternAddress = (lastBlockAddress - offsetLength) + 1u;
/* Check for range overflow */
assertFbl(*patternAddress >= blockDescriptor->blockStartAddress, kFblSysAssertParameterOutOfRange);
/* All NvPattern data must be stored in the same memSegment */
assertFbl(FblMemSegmentNrGet(*patternAddress) == memSegment, kFblSysAssertParameterOutOfRange);
}
else
{
/* No memory segment found, this is a configuration error. */
assertFbl(0u, kFblSysAssertParameterOutOfRange); /* PRQA S 2741, 4558 */ /* MD_FblNvPattern_Assertion */
}
return memSegment;
}
/***********************************************************************************************************************
* FblNvPatternGetPatternRegionSizeByStartAddress
**********************************************************************************************************************/
/*! \brief Calculates length of complete region containing NvPattern or block property elements
* \param[in] patternStartAddress Start address of pattern region
* \param[out] patternLength Pointer to RAM buffer to store the region size
* \return kFblOk: Pattern region size calculated successfully , kFblFailed: Else
**********************************************************************************************************************/
tFblResult FblNvPatternGetPatternRegionSizeByStartAddress( IO_PositionType patternStartAddress,
V_MEMRAM1 IO_SizeType V_MEMRAM2 V_MEMRAM3 * patternRegionLength)
{
tBlockDescriptor blockDescriptor;
tFblResult result = FblNvPatternGetPatternBlockDescriptorByStartAddress(patternStartAddress, &blockDescriptor);
if (result == kFblOk)
{
*patternRegionLength = (IO_SizeType)blockDescriptor.blockLength;
}
return result;
}
/***********************************************************************************************************************
* FblNvPatternSet
**********************************************************************************************************************/
/*! \brief Writes the pattern into the flash memory.
* \details The location of the pattern will be taken from the logical block table
* \param[in] blockDescriptor Pointer to the logical block descriptor
* \param[in] patternId ID of the pattern which shall be set
* \return kFblOk: pattern successfully written, kFblFailed: Error writing pattern
**********************************************************************************************************************/
tFblResult FblNvPatternSet( const V_MEMRAM1 tBlockDescriptor V_MEMRAM2 V_MEMRAM3 * blockDescriptor, tFblNvPatternId patternId )
{
tBlockDescriptor localBlockDescriptor;
tFblResult result;
result = FblLbtGetBlockDescriptorByNr(blockDescriptor->blockNr, &localBlockDescriptor);
if (result == kFblOk)
{
result = FblNvPatternSetByBlockDescriptor(&localBlockDescriptor, patternId);
}
return result;
}
/***********************************************************************************************************************
* FblNvPatternSetByBlockDescriptor
**********************************************************************************************************************/
/*! \brief Writes the pattern into the flash memory.
* \details The location of the pattern will be taken from the logical block descriptor.
* \param[in] blockDescriptor Pointer to the logical block descriptor
* \param[in] patternId ID of the pattern which shall be set
* \return kFblOk: pattern successfully written or already set, kFblFailed: Error writing pattern
**********************************************************************************************************************/
tFblResult FblNvPatternSetByBlockDescriptor( const V_MEMRAM1 tBlockDescriptor V_MEMRAM2 V_MEMRAM3 * blockDescriptor,
tFblNvPatternId patternId )
{
IO_PositionType patternAddress;
IO_SizeType patternLength;
tFblResult result;
tFblNvPatternState patternState;
vuint8 fblMarkerValue[] = kFblNvMarkerValue; /* PRQA S 3678 */ /* MD_FblNvPattern_3678_LocalVariable */
/* PRQA S 2742, 2880 1 */ /* MD_FblNvPattern_Assertion */
assertFblUser(sizeof(fblMarkerValue) == kFblNvPatternSize, kFblSysAssertParameterOutOfRange);
/* Initialize variables */
result = kFblFailed;
/* Check state of pattern */
patternState = FblNvPatternGetPatternState(blockDescriptor, patternId, &patternAddress, &patternLength);
/* Proceed if marker is blank */
if (patternState.markerState == FBL_NVPATTERN_STATE_ERASED)
{
/* Write pattern */
if (kFblOk == FblNvPatternWritePageAligned(fblMarkerValue, patternAddress, kFblNvPatternSize))
{
/* Verify that pattern is valid now */
patternState = FblNvPatternGetPatternState(blockDescriptor, patternId, &patternAddress, &patternLength);
if (patternState.markerState == FBL_NVPATTERN_STATE_EXPECTEDVALUE)
{
#if defined( FBLNVPATTERN_ENABLE_SIGN_PRESENCE_PATTERN )
result = FblNvPatternUpdateCmacByBlockDescriptor(blockDescriptor, patternId);
#else
result = kFblOk;
#endif /* FBLNVPATTERN_ENABLE_SIGN_PRESENCE_PATTERN */
}
}
}
else if ((patternState.markerState == FBL_NVPATTERN_STATE_EXPECTEDVALUE) && (patternState.maskState == FBL_NVPATTERN_STATE_ERASED))
{
/* Pattern already has expected state */
result = kFblOk;
}
else
{
/* For the sake of completeness */
}
return result;
}
/***********************************************************************************************************************
* FblNvPatternSetByStartAddress
**********************************************************************************************************************/
/*! \brief Writes the pattern into the flash memory.
* \param[in] patternStartAddress Start address of pattern region
* \param[in] patternId ID of the pattern which shall be set
* \return kFblOk: pattern successfully written or already set, kFblFailed: Error writing pattern
**********************************************************************************************************************/
tFblResult FblNvPatternSetByStartAddress( IO_PositionType patternStartAddress,
tFblNvPatternId patternId)
{
tBlockDescriptor dummyBlockDescriptor = { 0u };
tFblResult result = FblNvPatternGetPatternBlockDescriptorByStartAddress(patternStartAddress, &dummyBlockDescriptor);
if (result == kFblOk)
{
result = FblNvPatternSetByBlockDescriptor(&dummyBlockDescriptor, patternId);
}
return result;
}
/***********************************************************************************************************************
* FblNvPatternClr
**********************************************************************************************************************/
/*! \brief Writes the mask to invalidate the pattern
* \details The location of the pattern will be taken from the logical block table
* \param[in] blockDescriptor Pointer to the logical block descriptor
* \param[in] patternId ID of the pattern which shall be set
* \return kFblOk: Mask for invalidation successfully written, kFblFailed: Error writing invalidation mask
**********************************************************************************************************************/
tFblResult FblNvPatternClr( const V_MEMRAM1 tBlockDescriptor V_MEMRAM2 V_MEMRAM3 * blockDescriptor, tFblNvPatternId patternId )
{
tBlockDescriptor localBlockDescriptor;
tFblResult result;
result = FblLbtGetBlockDescriptorByNr(blockDescriptor->blockNr, &localBlockDescriptor);
if (result == kFblOk)
{
result = FblNvPatternClrByBlockDescriptor(&localBlockDescriptor, patternId);
}
return result;
}
/***********************************************************************************************************************
* FblNvPatternClrByBlockDescriptor
**********************************************************************************************************************/
/*! \brief Writes the mask to invalidate the pattern
* \details The location of the pattern will be taken from the passed logical block descriptor
* \param[in] blockDescriptor Pointer to the logical block descriptor
* \param[in] patternId ID of the pattern which shall be set
* \return kFblOk: Mask for invalidation successfully written, kFblFailed: Error writing invalidation mask
**********************************************************************************************************************/
tFblResult FblNvPatternClrByBlockDescriptor( const V_MEMRAM1 tBlockDescriptor V_MEMRAM2 V_MEMRAM3 * blockDescriptor,
tFblNvPatternId patternId )
{
tFblResult result;
IO_PositionType patternAddress;
IO_SizeType patternLength;
tFblNvPatternState patternState;
vuint8 fblMaskValue[] = kFblNvMaskValue; /* PRQA S 3678 */ /* MD_FblNvPattern_3678_LocalVariable */
/* PRQA S 2742, 2880 1 */ /* MD_FblNvPattern_Assertion */
assertFblUser(sizeof(fblMaskValue) == kFblNvPatternSize, kFblSysAssertParameterOutOfRange);
/* Check state of pattern */
patternState = FblNvPatternGetPatternState(blockDescriptor, patternId, &patternAddress, &patternLength);
/* Only set mask if pattern is set to valid */
if ((patternState.markerState == FBL_NVPATTERN_STATE_EXPECTEDVALUE) && (patternState.maskState == FBL_NVPATTERN_STATE_ERASED))
{
/* Write mask value to flash */
result = FblNvPatternWritePageAligned(fblMaskValue, (patternAddress + patternLength), kFblNvPatternSize);
}
else
{
/* Pattern is already in invalid state, do nothing. Illegal states are detected with assertions only. */
result = kFblOk;
}
return result;
}
/***********************************************************************************************************************
* FblNvPatternClrByStartAddress
**********************************************************************************************************************/
/*! \brief Writes the mask to invalidate the pattern
* \param[in] patternStartAddress Start address of pattern region
* \param[in] patternId ID of the pattern which shall be cleared
* \return kFblOk: Mask for invalidation successfully written, kFblFailed: Error writing invalidation mask
**********************************************************************************************************************/
tFblResult FblNvPatternClrByStartAddress( IO_PositionType patternStartAddress, tFblNvPatternId patternId )
{
tBlockDescriptor dummyBlockDescriptor = { 0u };
tFblResult result = FblNvPatternGetPatternBlockDescriptorByStartAddress(patternStartAddress, &dummyBlockDescriptor);
if (result == kFblOk)
{
result = FblNvPatternClrByBlockDescriptor(&dummyBlockDescriptor, patternId);
}
return result;
}
/***********************************************************************************************************************
* FblNvPatternGet
**********************************************************************************************************************/
/*! \brief Checks if the pattern state is 'valid' (correct pattern value is set/mask is erased)
* \details The location of the pattern and mask is taken from the logical block table
* \param[in] blockDescriptor Pointer to the logical block descriptor
* \param[in] patternId ID of the pattern which shall be checked
* \return kFblOk: Pattern is set and mask is erased,
* kFblFailed: Pattern is not set or mask not erased
**********************************************************************************************************************/
tFblResult FblNvPatternGet( const V_MEMRAM1 tBlockDescriptor V_MEMRAM2 V_MEMRAM3 * blockDescriptor, tFblNvPatternId patternId )
{
tBlockDescriptor localBlockDescriptor;
tFblResult result;
result = FblLbtGetBlockDescriptorByNr(blockDescriptor->blockNr, &localBlockDescriptor);
if (result == kFblOk)
{
result = FblNvPatternGetByBlockDescriptor(&localBlockDescriptor, patternId);
}
return result;
}
/***********************************************************************************************************************
* FblNvPatternGetByBlockDescriptor
**********************************************************************************************************************/
/*! \brief Checks if the pattern state is 'valid' (correct pattern value is set/mask is erased)
* \details The location of the pattern and mask is taken from the passed logical block descriptor
* \param[in] blockDescriptor Pointer to the logical block descriptor
* \param[in] patternId ID of the pattern which shall be checked
* \return kFblOk: Pattern is set and mask is erased,
* kFblFailed: Pattern is not set or mask not erased
**********************************************************************************************************************/
tFblResult FblNvPatternGetByBlockDescriptor( const V_MEMRAM1 tBlockDescriptor V_MEMRAM2 V_MEMRAM3 * blockDescriptor,
tFblNvPatternId patternId )
{
IO_PositionType patternAddress;
IO_SizeType patternLength;
tFblNvPatternState patternState;
tFblResult result;
/* Initialize result */
result = kFblFailed;
/* Check state of pattern */
patternState = FblNvPatternGetPatternState(blockDescriptor, patternId, &patternAddress, &patternLength);
if ((patternState.markerState == FBL_NVPATTERN_STATE_EXPECTEDVALUE) && (patternState.maskState == FBL_NVPATTERN_STATE_ERASED))
{
#if defined( FBLNVPATTERN_ENABLE_SIGN_PRESENCE_PATTERN )
result = FblNvPatternVerifyCmacByBlockDescriptor(blockDescriptor, patternId);
#else
result = kFblOk;
#endif /* FBLNVPATTERN_ENABLE_SIGN_PRESENCE_PATTERN */
}
return result;
}
/***********************************************************************************************************************
* FblNvPatternGetByStartAddress
**********************************************************************************************************************/
/*! \brief Checks if the pattern state is 'valid' (correct pattern value is set/mask is erased)
* \param[in] patternStartAddress Start address of pattern region
* \param[in] patternId ID of the pattern which shall be checked
* \return kFblOk: Pattern is set and mask is erased,
* kFblFailed: Pattern is not set or mask not erased
**********************************************************************************************************************/
tFblResult FblNvPatternGetByStartAddress( IO_PositionType patternStartAddress, tFblNvPatternId patternId )
{
tBlockDescriptor dummyBlockDescriptor = { 0u };
tFblResult result = FblNvPatternGetPatternBlockDescriptorByStartAddress(patternStartAddress, &dummyBlockDescriptor);
if (result == kFblOk)
{
result = FblNvPatternGetByBlockDescriptor(&dummyBlockDescriptor, patternId);
}
return result;
}
#if defined( FBL_NVPATTERN_ENABLE_BLOCK_PROPERTIES )
# if defined( FBLNVPATTERN_ENABLE_SIGN_PRESENCE_PATTERN )
/***********************************************************************************************************************
* FblNvPatternGetPropertyStateAndAddrByBlockDescriptor
**********************************************************************************************************************/
/*! \brief Retrieve the property state and address
* \details The location of the property is taken from the passed logical block descriptor
* \param[in] blockDescriptor Pointer to the logical block descriptor
* \param[in] propertyId Id of the property to check the erase state
* \param[out] address Pointer to the property address
* \param[out] state Pointer to the property state
* \return kFblOk: Property state and address are read,
* kFblFailed: Property state and address are not read
**********************************************************************************************************************/
tFblResult FblNvPatternGetPropertyStateAndAddrByBlockDescriptor(const V_MEMRAM1 tBlockDescriptor V_MEMRAM2 V_MEMRAM3 * blockDescriptor,
tFblNvPatternId propertyId,
V_MEMRAM1 IO_PositionType V_MEMRAM2 V_MEMRAM3 * address,
V_MEMRAM1 tFblNvPatternItemState V_MEMRAM2 V_MEMRAM3 * state)
{
IO_PositionType propertyAddress = 0u;
IO_SizeType propertyLength;
IO_SizeType actualPropertyLength;
tFblResult result = kFblFailed;
/* Init variables */
*state = FBL_NVPATTERN_STATE_UNEXPECTEDVALUE;
*address = 0u;
/* Check if requested Id is valid */
if (IS_VALID_PROPERTY_ID(propertyId))
{
/* Get address of element. Length is not used. */
if (FblNvPatternGetBaseAddrByBlockDescriptor(blockDescriptor, propertyId, &propertyAddress, &propertyLength) >= 0)
{
/* Get the property length */
actualPropertyLength = fblNvBlockProperties[(vuintx)propertyId - (vuintx)kFblNvPatternId_Separator - 1u].length;
*state = FblNvPatternGetPatternItemState(propertyAddress, actualPropertyLength, DONT_COMPARE);
*address = propertyAddress;
result = kFblOk;
}
}
return result;
}
# endif /* FBLNVPATTERN_ENABLE_SIGN_PRESENCE_PATTERN */
/***********************************************************************************************************************
* FblNvPatternGetProperty
**********************************************************************************************************************/
/*! \brief Reads value of a block property element
* \details Location of the property is taken from the logical block table
* \param[in] blockDescriptor Pointer to the logical block descriptor
* \param[in] propertyId Id of property to read
* \param[in] bufferLength Length of destination buffer
* \param[out] pDestBuffer Pointer to RAM where read property value will be stored
* \return kFblOk: Property successfully read, kFblFailed: Error reading property
**********************************************************************************************************************/
tFblResult FblNvPatternGetProperty( const V_MEMRAM1 tBlockDescriptor V_MEMRAM2 V_MEMRAM3 * blockDescriptor,
tFblNvPatternId propertyId,
IO_SizeType bufferLength,
vuint8* pDestBuffer )
{
tBlockDescriptor localBlockDescriptor;
tFblResult result;
result = FblLbtGetBlockDescriptorByNr(blockDescriptor->blockNr, &localBlockDescriptor);
if (result == kFblOk)
{
result = FblNvPatternGetPropertyByBlockDescriptor(&localBlockDescriptor, propertyId, bufferLength, pDestBuffer);
}
return result;
}
/***********************************************************************************************************************
* FblNvPatternGetPropertyByBlockDescriptor
**********************************************************************************************************************/
/*! \brief Reads value of an block property element
* \details The location of the block property is taken from the passed logical block descriptor
* \param[in] blockDescriptor Pointer to the logical block descriptor
* \param[in] propertyId Id of the property to read
* \param[in] bufferLength Length of destination buffer
* \param[out] pDestBuffer Pointer to RAM where the read property value will be stored
* \return kFblOk: Property successfully read, kFblFailed: Error reading property
**********************************************************************************************************************/
tFblResult FblNvPatternGetPropertyByBlockDescriptor( const V_MEMRAM1 tBlockDescriptor V_MEMRAM2 V_MEMRAM3 * blockDescriptor,
tFblNvPatternId propertyId,
IO_SizeType bufferLength,
vuint8* pDestBuffer )
{
IO_PositionType propertyAddress;
IO_SizeType propertyLength;
IO_SizeType sizeToRead = 0u;
tFblNvPatternId depPattern;
tFblResult result;
result = kFblFailed;
propertyAddress = 0u;
/* Check if requested Id is valid */
if (IS_VALID_PROPERTY_ID(propertyId))
{
sizeToRead = fblNvBlockProperties[(vuintx)propertyId - (vuintx)kFblNvPatternId_Separator - 1u].length;
depPattern = fblNvBlockProperties[(vuintx)propertyId - (vuintx)kFblNvPatternId_Separator - 1u].dependentPattern;
/* Check if buffer length is sufficient for storing requested data */
if (sizeToRead <= bufferLength)
{
/* If dependent pattern configured, check its validity */
if (depPattern != kFblNvPatternId_Invalid)
{
result = FblNvPatternGetByBlockDescriptor(blockDescriptor, depPattern);
}
else
{
result = kFblOk;
}
}
}
if (result == kFblOk)
{
/* Get address of property (length is not needed) */
if (FblNvPatternGetBaseAddrByBlockDescriptor(blockDescriptor, propertyId, &propertyAddress, &propertyLength) >= 0)
{
if (MemDriver_RReadSync(pDestBuffer, sizeToRead, propertyAddress) == IO_E_OK)
{
result = kFblOk;
}
}
}
return result;
}
/***********************************************************************************************************************
* FblNvPatternGetPropertyByStartAddress
**********************************************************************************************************************/
/*! \brief Reads value of an block property element
* \param[in] patternStartAddress Start address of pattern region
* \param[in] propertyId Id of the property to read
* \param[in] bufferLength Length of destination buffer
* \param[out] pDestBuffer Pointer to RAM where the read property value will be stored
* \return kFblOk: Property successfully read, kFblFailed: Error reading property
**********************************************************************************************************************/
tFblResult FblNvPatternGetPropertyByStartAddress( IO_PositionType patternStartAddress,
tFblNvPatternId propertyId,
IO_SizeType bufferLength,
vuint8 * destBuffer )
{
tBlockDescriptor dummyBlockDescriptor = { 0u };
tFblResult result = FblNvPatternGetPatternBlockDescriptorByStartAddress(patternStartAddress, &dummyBlockDescriptor);
if (result == kFblOk)
{
result = FblNvPatternGetPropertyByBlockDescriptor(&dummyBlockDescriptor, propertyId, bufferLength, destBuffer);
}
return result;
}
/***********************************************************************************************************************
* FblNvPatternSetProperty
**********************************************************************************************************************/
/*! \brief Writes value of a block property
* \details The location of the property is taken from the logical block table
* \param[in] blockDescriptor Pointer to the logical block descriptor
* \param[in] pSrcBuffer Pointer to RAM with the data to write
* \param[in] propertyId Id of the block property to write
* \return kFblOk: Property successfully written, kFblFailed: Error writing property
**********************************************************************************************************************/
tFblResult FblNvPatternSetProperty( const V_MEMRAM1 tBlockDescriptor V_MEMRAM2 V_MEMRAM3 * blockDescriptor,
const vuint8* pSrcBuffer,
tFblNvPatternId propertyId )
{
tBlockDescriptor localBlockDescriptor;
tFblResult result;
result = FblLbtGetBlockDescriptorByNr(blockDescriptor->blockNr, &localBlockDescriptor);
if (result == kFblOk)
{
result = FblNvPatternSetPropertyByBlockDescriptor(&localBlockDescriptor, pSrcBuffer, propertyId);
}
return result;
}
/***********************************************************************************************************************
* FblNvPatternSetPropertyByBlockDescriptor
**********************************************************************************************************************/
/*! \brief Writes value of a block property
* \details The location of the property is taken from the passed logical block descriptor
* \param[in] blockDescriptor Pointer to the logical block descriptor
* \param[in] pSrcBuffer Pointer to RAM with the data to write
* \param[in] propertyId Id of the property to write
* \return kFblOk: Property successfully written, kFblFailed: Error writing property
**********************************************************************************************************************/
tFblResult FblNvPatternSetPropertyByBlockDescriptor( const V_MEMRAM1 tBlockDescriptor V_MEMRAM2 V_MEMRAM3 * blockDescriptor,
const vuint8* pSrcBuffer,
tFblNvPatternId propertyId )
{
IO_PositionType propertyAddress;
IO_SizeType propertyLength;
IO_SizeType actualPropertyLength;
tFblResult result;
/* Initialize variables */
result = kFblFailed;
propertyAddress = 0u;
/* Check if requested Id is valid */
if (IS_VALID_PROPERTY_ID(propertyId))
{
/* Get address and length of element */
if (FblNvPatternGetBaseAddrByBlockDescriptor(blockDescriptor, propertyId, &propertyAddress, &propertyLength) >= 0)
{
/* Only write block property to memory if it has not been set before */
actualPropertyLength = fblNvBlockProperties[(vuintx)propertyId - (vuintx)kFblNvPatternId_Separator - 1u].length;
if (FblNvPatternGetPatternItemState(propertyAddress, actualPropertyLength, DONT_COMPARE) == FBL_NVPATTERN_STATE_ERASED)
{
result = FblNvPatternWritePageAligned(pSrcBuffer, propertyAddress, actualPropertyLength);
}
}
}
return result;
}
/***********************************************************************************************************************
* FblNvPatternSetPropertyByStartAddress
**********************************************************************************************************************/
/*! \brief Writes value of a block property
* \param[in] patternStartAddress Start address of pattern region
* \param[in] pSrcBuffer Pointer to RAM with the data to write
* \param[in] propertyId Id of the property to write
* \return kFblOk: Property successfully written, kFblFailed: Error writing property
**********************************************************************************************************************/
tFblResult FblNvPatternSetPropertyByStartAddress( IO_PositionType patternStartAddress,
const vuint8* srcBuffer,
tFblNvPatternId propertyId )
{
tBlockDescriptor dummyBlockDescriptor = { 0u };
tFblResult result = FblNvPatternGetPatternBlockDescriptorByStartAddress(patternStartAddress, &dummyBlockDescriptor);
if (result == kFblOk)
{
result = FblNvPatternSetPropertyByBlockDescriptor(&dummyBlockDescriptor, srcBuffer, propertyId);
}
return result;
}
# if defined( FBLNVPATTERN_ENABLE_SIGN_PRESENCE_PATTERN )
/***********************************************************************************************************************
* FblNvPatternSignedPresencePatternInit
**********************************************************************************************************************/
/*! \brief Init the AES key and update the CMAC for all valid logical block during the first startup of ECU
**********************************************************************************************************************/
void FblNvPatternSignedPresencePatternInit(void)
{
ApplFblNvPatternSignedPresencePatternInit();
}
/***********************************************************************************************************************
* FblNvPatternUpdateCmacByBlockDescriptor
**********************************************************************************************************************/
/*! \brief Calculate the CMAC for the received patternId and update it in the respective property
* \details The address of the property will be fetched from the logical block descriptor
* \param[in] blockDescriptor Pointer to the logical block descriptor
* \param[in] patternId Id of the pattern for which the CMAC needs to be calculated and written
* \return kFblOk: CMAC updated
* kFblFailed: CMAC not updated
**********************************************************************************************************************/
tFblResult FblNvPatternUpdateCmacByBlockDescriptor(const V_MEMRAM1 tBlockDescriptor V_MEMRAM2 V_MEMRAM3 * blockDescriptor,
tFblNvPatternId patternId)
{
tFblResult result = kFblFailed;
IO_PositionType propertyAddress = 0u;
tFblNvPatternItemState propertyState;
vuint8 signatureBuffer[FBL_NVPATTERN_PP_CMAC_SIZE];
if (fblNvPatternProperties[patternId] != kFblNvPatternId_Invalid)
{
assertFblUser(fblNvBlockProperties[(vuintx)fblNvPatternProperties[patternId] - (vuintx)kFblNvPatternId_Separator - 1u].dependentPattern
== kFblNvPatternId_Invalid, kFblSysAssertParameterOutOfRange);
if (FblNvPatternGetPropertyStateAndAddrByBlockDescriptor(blockDescriptor, fblNvPatternProperties[patternId],
&propertyAddress, &propertyState) == kFblOk)
{
if (propertyState == FBL_NVPATTERN_STATE_ERASED)
{
if (ApplFblNvPatternGenerateCMAC(fblNvPatternProperties[patternId], blockDescriptor, signatureBuffer) == kFblOk)
{
result = FblNvPatternSetPropertyByBlockDescriptor(blockDescriptor, signatureBuffer, fblNvPatternProperties[patternId]);
}
}
}
}
else
{
result = kFblOk;
}
return result;
}
/***********************************************************************************************************************
* FblNvPatternVerifyCmacByBlockDescriptor
**********************************************************************************************************************/
/*! \brief Verify the CMAC for the received patternId
* \details The address of the property will be fetched from the logical block descriptor
* \param[in] blockDescriptor Pointer to the logical block descriptor
* \param[in] patternId Id of the pattern for which the CMAC needs to be verified
* \return kFblOk: CMAC verified successfully
* kFblFailed: CMAC not verified or verification failed
**********************************************************************************************************************/
tFblResult FblNvPatternVerifyCmacByBlockDescriptor(const V_MEMRAM1 tBlockDescriptor V_MEMRAM2 V_MEMRAM3 * blockDescriptor,
tFblNvPatternId patternId)
{
vuint8 signatureBuffer[FBL_NVPATTERN_PP_CMAC_SIZE];
IO_PositionType propertyAddress = 0u;
IO_SizeType actualPropertyLength;
tFblNvPatternItemState propertyState;
tFblResult result = kFblFailed;
if (fblNvPatternProperties[patternId] != kFblNvPatternId_Invalid)
{
assertFblUser(fblNvBlockProperties[(vuintx)fblNvPatternProperties[patternId] - (vuintx)kFblNvPatternId_Separator - 1u].dependentPattern
== kFblNvPatternId_Invalid, kFblSysAssertParameterOutOfRange);
if (FblNvPatternGetPropertyStateAndAddrByBlockDescriptor(blockDescriptor, fblNvPatternProperties[patternId],
&propertyAddress, &propertyState) == kFblOk)
{
if (propertyState != FBL_NVPATTERN_STATE_ERASED)
{
actualPropertyLength = fblNvBlockProperties[(vuintx)fblNvPatternProperties[patternId] -
(vuintx)kFblNvPatternId_Separator - 1u].length;
if (MemDriver_RReadSync(signatureBuffer, actualPropertyLength, propertyAddress) == IO_E_OK)
{
result = ApplFblNvPatternVerifyCMAC(fblNvPatternProperties[patternId], blockDescriptor, signatureBuffer);
}
}
}
}
else
{
result = kFblOk;
}
return result;
}
# endif /* FBLNVPATTERN_ENABLE_SIGN_PRESENCE_PATTERN */
#endif /* FBL_NVPATTERN_ENABLE_BLOCK_PROPERTIES */
#define FBLNVPATTERN_STOP_SEC_CODE
#include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */
/***********************************************************************************************************************
* ERROR CHECKS
**********************************************************************************************************************/
#if (!IS_POWOFTWO(FBL_MAX_SEGMENT_SIZE))
# error "FBL_MAX_SEGMENT_SIZE must be a power of two."
#endif
/***********************************************************************************************************************
* MISRA DEVIATIONS
**********************************************************************************************************************/
/* Justification for module-specific MISRA deviations:
MD_FblNvPattern_Assertion:
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".
MD_FblNvPattern_3678_LocalVariable:
Reason: Local variable/array is not declared as const as some compiler/platforms have issues with that.
Risk: Content of the variable/array could be modified within the function.
Prevention: Code is checked for unintended write accesses by code inspection.
MD_FblNvPattern_4342:
Reason: An expression of essential type has been cast to an enum type.
Risk: The essential type is not in range of enum type.
Prevention: Code must be reviewed to ensure cast is only applied on values in valid range
*/
/***********************************************************************************************************************
* END OF FILE: FBL_NVPATTERN.C
**********************************************************************************************************************/