synth/arm/hal/lib/common/xil_util.c

1238 lines
35 KiB
C

/******************************************************************************/
/**
* Copyright (c) 2019 - 2022 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/****************************************************************************/
/**
* @file xil_util.c
*
* xil_util.c file contains xil utility functions
* Except few functions, most of these functions are wrappers to standard functions.
* The standard string functions do not validate the input and that results into
* buffer overflows. To avoid it, the wrapper function validates the input and
* then passed to standard function. There are few constant time functions
* ( xxx_CT() ) which are used to compare the data in constant time.
* The constant time functions should be used while comparing secure data
* like password, keys which prevent disclosing of the data using
* timing analysis.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- -------- -------- -----------------------------------------------
* 6.4 mmd 04/21/19 First release.
* 7.2 nava 08/01/20 Updated Xil_WaitForEvent() and Xil_WaitForEvents(()
* API to use microsecond timeout instead of a free
* counter.
* 7.3 kal 06/30/20 Converted Xil_Ceil macro to API.
* rpo 08/19/20 Added function for read,modify,write
* kal 09/22/20 Changed the param type from const char to const char*
* to avoid copying key onto stack
* td 10/16/20 Added Xil_Strcpy, Xil_Strcat, Xil_SecureMemCpy and
* Xil_MemCmp functions
* 7.4 am 11/26/20 Added Xil_StrCpyRange function
* 7.6 kpt 07/15/21 Added Xil_SecureZeroize function
* 7.7 kpt 11/09/21 Added Xil_SMemCmp, Xil_SMemCmp_CT, Xil_SMemCpy,
* Xil_SMemSet, Xil_SStrCat, Xil_SStrCmp, Xil_SStrCmp_CT
* Xil_SStrCpy functions
* kpt 11/25/21 Added strnlen function to fix ARMCC compilation
* failure
* 7.7 sk 01/10/22 Update functions return type and update RetVal variable
* data type to fix misra_c_2012_directive_4_6 misrac
* violations.
* 7.7 sk 01/10/22 Update values from signed to unsigned to fix
* misra_c_2012_rule_10_4 violation.
* 7.7 sk 01/10/22 Add explicit parentheses to fix misra_c_2012_rule_12_1
* violation.
* 7.7 sk 01/10/22 Typecast character strings to u8 to fix misra_c_2012_rule_
* 10_3 violation.
* 7.7 sk 01/10/22 Modify the code to reduce multiple break statements
* and fix misra_c_2012_rule_15_4 violation.
* 7.7 sk 01/10/22 Modify Xil_SMemCmp_CT and Xil_SMemCmp function argument
* type to fix misra_c_2012_rule_8_3 violation.
* 7.7 sk 01/10/22 Update conditional expression to fix misra_c_2012_rule_14_4
* violation.
* bm 01/20/22 Fix compilation warnings in Xil_SMemCpy
* mmd 02/28/22 Added Xil_SMemMove function
* 7.7 sk 03/02/22 Add explicit parentheses to fix misra_c_2012_rule_12_1
* violation.
* 7.7 sk 03/02/22 Add const qualifier to varaibles to fix misra_c_2012_rule_
* 11_8 violation.
* 7.7 sk 03/02/22 Typecast expression with unsigned int to fix
* misra_c_2012_rule_10_7 violation.
* 7.7 sk 03/02/22 Typecast variables with unsigned or signed to fix misra_c
* _2012_rule_10_3 violation.
* 7.7 sk 03/02/22 Add const to unmodified variable to fix misra_c_2012
* _rule_8_13 violation.
* 7.7 sk 03/02/22 Typecast the function with void as return type is
* not used and fix misra_c_2012_rule_17_7 violation.
* 7.7 sk 03/02/22 Remove increment operations during comparision to
* fix misra_c_2012_rule_13_3 violation.
* 7.7 sk 03/02/22 Update values from signed to unsigned to fix
* misra_c_2012_rule_10_4 violation.
*
* </pre>
*
*****************************************************************************/
/****************************** Include Files *********************************/
#include "xil_util.h"
#include "sleep.h"
/************************** Constant Definitions ****************************/
#define MAX_NIBBLES 8U
/************************** Function Prototypes *****************************/
#ifdef __ARMCC_VERSION
/******************************************************************************/
/**
*
* This API returns the length of the input string
*
* @param StartPtr is the pointer to the input string
* @param StrSize is the maximum length of the input string
*
* @return Returns the length of the input string
*
******************************************************************************/
static size_t strnlen (const char *StartPtr, size_t StrSize)
{
const char *EndPtr = StartPtr;
size_t StrLen = 0U;
EndPtr = memchr(StartPtr, '\0', StrSize);
if (EndPtr == NULL) {
StrLen = StrSize;
}
else {
StrLen = (size_t) (EndPtr - StartPtr);
}
return StrLen;
}
#endif
/******************************************************************************/
/**
* This API ceils the provided float value.
*
* @param Value is a float variable which has to ceiled to nearest
* integer.
*
* @return Returns ceiled value.
*
*******************************************************************************/
s32 Xil_Ceil(float Value)
{
s32 Result = Value;
if (Value > Result) {
Result = Result + 1;
}
return Result;
}
/****************************************************************************/
/**
* Converts the char into the equivalent nibble.
* Ex: 'a' -> 0xa, 'A' -> 0xa, '9'->0x9
*
* @param InChar - Input character to be converted to nibble.
* Valid characters are between 0-9, a-f, A-F
* @param Num - Memory location where nibble is to be stored
*
* @return
* XST_SUCCESS - Character converted to nibble
* XST_FAILURE - Invalid input character
*
* @note None.
*
*****************************************************************************/
u32 Xil_ConvertCharToNibble(u8 InChar, u8 *Num)
{
u32 Status;
/* Convert the char to nibble */
if ((InChar >= (u8)'0') && (InChar <= (u8)'9')) {
*Num = InChar - (u8)'0';
Status = XST_SUCCESS;
}
else if ((InChar >= (u8)'a') && (InChar <= (u8)'f')) {
*Num = InChar - (u8)'a' + 10U;
Status = XST_SUCCESS;
}
else if ((InChar >= (u8)'A') && (InChar <= (u8)'F')) {
*Num = InChar - (u8)'A' + 10U;
Status = XST_SUCCESS;
}
else {
Status = XST_FAILURE;
}
return Status;
}
/****************************************************************************/
/*
* Converts the string into the equivalent Hex buffer.
* Ex: "abc123" -> {0xab, 0xc1, 0x23}
*
* @param Str - Pointer to string to be converted to Hex.
* Accepted characters in string are between 0-9, a-f and A-F
* @param Buf - Pointer to memory location where converted hex values are to
* be stored.
* @param Len - Length of input string
*
* @return
* XST_SUCCESS - Input string is converted to hex
* XST_FAILURE - Invalid character in inpit string
*
* @note None.
*
*****************************************************************************/
u32 Xil_ConvertStringToHex(const char *Str, u32 *buf, u8 Len)
{
u32 Status = XST_FAILURE;
u8 ConvertedLen = 0U, index = 0U;
u8 Nibble[MAX_NIBBLES] = {0U};
u8 i;
while (ConvertedLen < Len) {
for (i = 0U; i < MAX_NIBBLES; i++) {
Status = Xil_ConvertCharToNibble((u8)Str[ConvertedLen],
&Nibble[i]);
ConvertedLen = ConvertedLen +1U;
if (Status != XST_SUCCESS) {
/* Error converting char to nibble */
goto END;
}
}
buf[index] = (((u32)Nibble[0] << (u8)28U) | ((u32)Nibble[1] << (u8)24U) |
((u32)Nibble[2] << (u8)20U) | ((u32)Nibble[3] << (u8)16U) |
((u32)Nibble[4] << (u8)12U) | ((u32)Nibble[5] << (u8)8U) |
((u32)Nibble[6] << (u8)4U) | (u32)Nibble[7]);
index++;
}
END:
return Status;
}
/****************************************************************************/
/*
* Waits for the event
*
* @param RegAddr - Address of register to be checked for event(s) occurrence
* @param EventMask - Mask indicating event(s) to be checked
* @param Event - Specific event(s) value to be checked
* @param Timeout - Max number of microseconds to wait for an event(s).
*
* @return
* XST_SUCCESS - On occurrence of the event(s).
* XST_FAILURE - Event did not occur before counter reaches 0
*
* @note None.
*
*****************************************************************************/
u32 Xil_WaitForEvent(u32 RegAddr, u32 EventMask, u32 Event, u32 Timeout)
{
u32 EventStatus;
u32 PollCount = Timeout;
u32 Status = XST_FAILURE;
while(PollCount > 0U) {
EventStatus = Xil_In32(RegAddr) & EventMask;
if (EventStatus == Event) {
Status = XST_SUCCESS;
break;
}
PollCount--;
usleep(1U);
}
return Status;
}
/******************************************************************************/
/**
* Waits for the events. Returns on occurrence of first event / timeout.
*
* @param EventsRegAddr - Address of register to be checked for event(s)
* occurrence
* @param EventsMask - Mask indicating event(s) to be checked
* @param WaitEvents - Specific event(s) to be checked
* @param Timeout - Max number of microseconds to wait for an event(s).
* @param Events - Mask of Events occurred returned in memory pointed by
* this variable
*
* @return
* XST_SUCCESS - On occurrence of the event(s).
* XST_FAILURE - Event did not occur before counter reaches 0
*
******************************************************************************/
u32 Xil_WaitForEvents(u32 EventsRegAddr, u32 EventsMask, u32 WaitEvents,
u32 Timeout, u32* Events)
{
u32 EventStatus;
u32 PollCount = Timeout;
u32 Status = XST_TIMEOUT;
*Events = 0x00;
do {
EventStatus = Xil_In32(EventsRegAddr);
EventStatus &= EventsMask;
if((EventStatus & WaitEvents) != 0U) {
Status = XST_SUCCESS;
*Events = EventStatus;
break;
}
PollCount--;
usleep(1U);
}
while(PollCount > 0U);
return Status;
}
/******************************************************************************/
/**
* Checks whether the passed character is a valid hex digit
*
* @param Ch - Pointer to the input character
*
* @return
* XST_SUCCESS - on valid hex digit
* XST_FAILURE - on invalid hex digit
*
* @note None.
*
******************************************************************************/
u32 Xil_IsValidHexChar(const char *Ch)
{
u32 Status = XST_FAILURE;
if(NULL == Ch) {
goto END;
}
if (((*Ch >= '0') && (*Ch <='9'))||
((*Ch >= 'a') && (*Ch <='f'))||
((*Ch >= 'A') && (*Ch <='F'))) {
Status = XST_SUCCESS;
}
END:
return Status;
}
/******************************************************************************/
/**
* Validate the input string contains only hexadecimal characters
*
* @param HexStr - Pointer to string to be validated
*
* @return
* XST_SUCCESS - On valid input hex string
* XST_INVALID_PARAM - On invalid length of the input string
* XST_FAILURE - On non hexadecimal character in string
*
* @note None
*
******************************************************************************/
u32 Xil_ValidateHexStr(const char *HexStr)
{
u32 Idx;
u32 Len;
u32 Status = XST_INVALID_PARAM;
if(NULL == HexStr) {
goto END;
}
Len = Xil_Strnlen(HexStr, XIL_MAX_HEX_STR_LEN + 1U);
if (Len > XIL_MAX_HEX_STR_LEN) {
goto END;
}
for (Idx = 0U; Idx < Len; Idx++) {
Status = Xil_IsValidHexChar(&HexStr[Idx]);
if (Status != XST_SUCCESS) {
break;
}
}
END:
return Status;
}
/****************************************************************************/
/**
* Converts the string into the equivalent Hex buffer.
* Ex: "abc123" -> {0xab, 0xc1, 0x23}
*
* @param Str is a Input String. Will support the lower and upper case values.
* Value should be between 0-9, a-f and A-F
* @param Buf is Output buffer.
* @param Len of the input string. Should have even values
*
* @return
* - XST_SUCCESS no errors occurred.
* - XST_FAILURE an error when input parameters are not valid
* - an error when input buffer has invalid values
*
* TDD Test Cases:
* ---Initialization---
* Len is odd
* Len is zero
* Str is NULL
* Buf is NULL
* ---Functionality---
* Str input with only numbers
* Str input with All values in A-F
* Str input with All values in a-f
* Str input with values in a-f, 0-9, A-F
* Str input with values in a-z, 0-9, A-Z
* Boundary Cases
* Memory Bounds of buffer checking
* ****************************************************************************/
u32 Xil_ConvertStringToHexBE(const char *Str, u8 *Buf, u32 Len)
{
u32 ConvertedLen;
u8 LowerNibble = 0U;
u8 UpperNibble = 0U;
u32 Status = (u32)XST_FAILURE;
if ((Str == NULL) || (Buf == NULL)) {
Status = (u32)XST_INVALID_PARAM;
goto END;
}
if ((Len == 0U) || ((Len % XIL_SIZE_OF_BYTE_IN_BITS) != 0U)) {
Status = (u32)XST_INVALID_PARAM;
goto END;
}
if(Len != (strlen(Str) * XIL_SIZE_OF_NIBBLE_IN_BITS)) {
Status = (u32)XST_INVALID_PARAM;
goto END;
}
ConvertedLen = 0U;
while (ConvertedLen < (Len / XIL_SIZE_OF_NIBBLE_IN_BITS)) {
if ((Xil_ConvertCharToNibble(((u8)Str[ConvertedLen]),&UpperNibble)
== (u32)XST_SUCCESS) && (Xil_ConvertCharToNibble(((u8)Str[ConvertedLen+1U]),
&LowerNibble) == (u32)XST_SUCCESS)) {
Buf[ConvertedLen/2U] =
(UpperNibble << XIL_SIZE_OF_NIBBLE_IN_BITS) |
LowerNibble;
}
else {
Status = (u32)XST_INVALID_PARAM;
goto END;
}
ConvertedLen += 2U;
}
Status = (u32)XST_SUCCESS;
END:
return Status;
}
/******************************************************************************/
/**
* Converts the string into the equivalent Hex buffer.
* Ex: "abc123" -> {0x23, 0xc1, 0xab}
*
* @param Str - Input String to be converted to hex number in little
* endian format. Valid characters of input strin are between
* 0-9, a-f and A-F
* @param Buf - Pointer to memory location where converted hex numbers are to
* be stored.
* @param Len - Expected number of output bits
*
* @return
* XST_SUCCESS - Input string is converted to hex number(s)
* XST_FAILURE - Invalid input character detected in input string
*
* @note
*
******************************************************************************/
u32 Xil_ConvertStringToHexLE(const char *Str, u8 *Buf, u32 Len)
{
u32 ConvertedLen;
u8 LowerNibble = 0U;
u8 UpperNibble = 0U;
u32 StrIndex;
u32 Status = XST_FAILURE;
if ((NULL == Str) || (NULL == Buf)) {
Status = XST_INVALID_PARAM;
goto END;
}
if ((Len == 0U) || ((Len % XIL_SIZE_OF_BYTE_IN_BITS) != 0U)) {
Status = XST_INVALID_PARAM;
goto END;
}
if(Len != (strlen(Str) * XIL_SIZE_OF_NIBBLE_IN_BITS)) {
Status = XST_INVALID_PARAM;
goto END;
}
StrIndex = (Len / XIL_SIZE_OF_BYTE_IN_BITS) - 1U;
ConvertedLen = 0U;
while (ConvertedLen < (Len / XIL_SIZE_OF_NIBBLE_IN_BITS)) {
if ((Xil_ConvertCharToNibble(((u8)Str[ConvertedLen]),
&UpperNibble) == XST_SUCCESS) &&
(Xil_ConvertCharToNibble(((u8)Str[ConvertedLen + 1U]),
&LowerNibble) == XST_SUCCESS)) {
Buf[StrIndex] =
(UpperNibble << XIL_SIZE_OF_NIBBLE_IN_BITS) |
LowerNibble;
StrIndex = StrIndex - 1U;
}
else {
Status = XST_INVALID_PARAM;
goto END;
}
ConvertedLen += 2U;
}
Status = XST_SUCCESS;
END:
return Status;
}
/******************************************************************************/
/**
* Returns the length of input string.
*
* @param Str - Input string
* @param MaxLen - Maximum expected length of the input string
*
* @return
* Returns length of the input string if length is less than MaxLen.
* Returns MaxLen if the length of the input string is >= MaxLen.
*
* @note
*
******************************************************************************/
u32 Xil_Strnlen(const char *Str, u32 MaxLen)
{
const char *InStr = Str;
u32 StrLen = 0U;
if (NULL == Str) {
goto END;
}
while(StrLen < MaxLen) {
if ('\0' == *InStr) {
break;
}
StrLen++;
InStr++;
}
END:
return StrLen;
}
/*****************************************************************************/
/**
* @brief This function will Read, Modify and Write to an address.
*
* @param Addr denotes Address
* @param Mask denotes the bits to be modified
* @param Value is the value to be written to the address
*
* @return None
*
*****************************************************************************/
void Xil_UtilRMW32(u32 Addr, u32 Mask, u32 Value)
{
u32 Val;
Val = Xil_In32(Addr);
Val = (Val & (~Mask)) | (Mask & Value);
Xil_Out32(Addr, Val);
}
/*****************************************************************************/
/**
* @brief This functions copies source string to destination string. This
* function is a safe version of strcpy
*
* @param DestPtr is pointer to destination string
* @param SrcPtr is pointer to source string
* @param Size is the maximum number of bytes of the source string
* to be copied
*
* @return XST_SUCCESS on success and error code on failure
*
******************************************************************************/
int Xil_Strcpy(char *DestPtr, const char *SrcPtr, const u32 Size)
{
int Status = XST_FAILURE;
u32 Count;
if ((SrcPtr == NULL) || (DestPtr == NULL) || (Size == 0U)) {
goto END;
}
for (Count = 0U; (SrcPtr[Count] != '\0') && (Count < Size); ++Count) {
DestPtr[Count] = SrcPtr[Count];
}
if (Count == Size) {
DestPtr[0U] = '\0';
goto END;
}
DestPtr[Count] = '\0';
Status = XST_SUCCESS;
END:
return Status;
}
/****************************************************************************/
/**
* @brief Copies specified range from source string to destination string
*
* @param Src is a pointer to source string
* @param Dest is a pointer to destination string
* @param From is 0 based index from where string copy starts
* @param To is 0 based index till which string is copied
* @param MaxSrcLen is the maximum length of source string
* @param MaxDstLen is the maximum length of destination string
*
* @return XST_SUCCESS on success
* XST_FAILURE on failure
*
* @note None
*
****************************************************************************/
int Xil_StrCpyRange(const u8 *Src, u8 *Dest, u32 From, u32 To, u32 MaxSrcLen,
u32 MaxDstLen)
{
int Status = XST_FAILURE;
u32 SrcLength;
u32 Index;
if ((Src == NULL) || (Dest == NULL)) {
Status = XST_INVALID_PARAM;
goto END;
}
if ((To >= MaxSrcLen) || (To < From)) {
Status = XST_INVALID_PARAM;
goto END;
}
if ((To - From + 1U) >= MaxDstLen) {
Status = XST_INVALID_PARAM;
goto END;
}
SrcLength = Xil_Strnlen((const char *)Src, MaxSrcLen);
if (To >= SrcLength) {
Status = XST_INVALID_PARAM;
goto END;
}
for (Index = From; (Index <= To) && (Src[Index]!= (u8)'\0'); Index++) {
Dest[Index - From] = Src[Index];
}
Dest[Index - From] = (u8)'\0';
Status = XST_SUCCESS;
END:
return Status;
}
/*****************************************************************************/
/**
* @brief This function appends string2 to string1. This function is a safe
* version of strcat
*
* @param Str1Ptr is pointer to string1
* @param Str2Ptr is pointer to string2
* @param Size is the maximum number of bytes Str1 can hold
*
* @return XST_SUCCESS on success and error code on failure
*
******************************************************************************/
int Xil_Strcat(char* Str1Ptr, const char* Str2Ptr, const u32 Size)
{
int Status = XST_FAILURE;
u32 Count = 0U;
u32 CountTmp = 0U;
if ((Str1Ptr == NULL) || (Str2Ptr == NULL) || (Size == 0U)) {
goto END;
}
while ((Count < Size) && (Str1Ptr[Count] != '\0')) {
Count++;
}
while ((Str2Ptr[CountTmp] != '\0') && (Count < Size)) {
Str1Ptr[Count] = Str2Ptr[CountTmp];
Count++;
CountTmp++;
}
if (Count == Size) {
Str1Ptr[0U] = '\0';
goto END;
}
Str1Ptr[Count] = '\0';
Status = XST_SUCCESS;
END:
return Status;
}
/*****************************************************************************/
/**
* @brief This function copies Len bytes from source memory to destination
* memory. If Len is greater than DestPtrLen, then DestPtr is also
* filled with 0s till DestPtrLen bytes and is considered as a failure.
* This function is a secure implementation of memcpy
*
* @param DestPtr is pointer to destination address
* @param DestPtrLen is the memory alloted to the destination buffer
* @param SrcPtr is pointer to source address
* @param Len is number of bytes to be copied
*
* @return XST_SUCCESS on success and error code on failure
*
******************************************************************************/
int Xil_SecureMemCpy(void * DestPtr, u32 DestPtrLen, const void * SrcPtr, u32 Len)
{
int Status = XST_FAILURE;
u8 *Dest = (u8 *)DestPtr;
const u8 *Src = (const u8 *)SrcPtr;
if ((DestPtr == NULL) || (SrcPtr == NULL)) {
goto END;
}
if (Len > DestPtrLen) {
while (DestPtrLen != 0U) {
*Dest = 0U;
Dest++;
DestPtrLen--;
}
goto END;
}
/* Loop and copy. */
while (Len != 0U) {
*Dest = *Src;
Dest++;
Src++;
Len--;
}
Status = XST_SUCCESS;
END:
return Status;
}
/*****************************************************************************/
/**
* @brief This function compares Len bytes from memory1 and memory2. This
* function is a secure implementation of memcmp
*
* @param Buf1Ptr is pointer to memory1
* @param Buf2Ptr is pointer to memory2
* @param Len is number of byets to be compared
*
* @return 0 if contents of both the memory regions are same,
* -1 if first non-matching character has lower value in Buf1Ptr
* 1 if first non-matching character is greater value in Buf1Ptr
*
******************************************************************************/
int Xil_MemCmp(const void * Buf1Ptr, const void * Buf2Ptr, u32 Len)
{
volatile int RetVal = 1;
const u8 *Buf1 = Buf1Ptr;
const u8 *Buf2 = Buf2Ptr;
u32 Size = Len;
/* Assert validates the input arguments */
if ((Buf1 == NULL) || (Buf2 == NULL) || (Len == 0x0U)) {
goto END;
}
/* Loop and compare */
while (Size != 0U) {
if (*Buf1 > *Buf2) {
RetVal = 1;
goto END;
} else if (*Buf1 < *Buf2) {
RetVal = -1;
goto END;
} else {
Buf1++;
Buf2++;
Size--;
}
}
/* Make sure size is zero to know the whole of data is compared */
if (Size == 0U) {
RetVal = 0;
}
END:
return RetVal;
}
/*****************************************************************************/
/**
* @brief This function is used to zeroize the memory
*
* @param DataPtr Pointer to the memory which need to be zeroized.
* @param Length Length of the data in bytes.
*
* @return
* - XST_SUCCESS: If Zeroization is successful.
* - XST_FAILURE: If Zeroization is not successful.
********************************************************************************/
int Xil_SecureZeroize(u8 *DataPtr, const u32 Length)
{
u32 Index;
int Status = XST_FAILURE;
/* Clear the data */
(void)memset(DataPtr, 0, Length);
/* Read it back to verify */
for (Index = 0U; Index < Length; Index++) {
if (DataPtr[Index] != 0x00U) {
goto END;
}
}
if (Index == Length) {
Status = XST_SUCCESS;
}
END:
return Status;
}
/*****************************************************************************/
/**
* @brief This function compares two memory regions for specified number
* of bytes. This function takes size of two memory regions to
* make sure not to read from or write to out of bound memory
* region.
*
* @param Src1 - Pointer to first memory range
* @param Src1Size - Maximum size of first memory range
* @param Src2 - Pointer to second memory range
* @param Src2Size - Maximum size of second memory range
* @param CmpLen - Number of bytes to be compared
*
* @return
* XST_SUCCESS - If specified number of bytes matches
* XST_FAILURE - If there is a mistmatch found during comparison
* XST_INVALID_PARAM - Invalid inputs
*
*****************************************************************************/
int Xil_SMemCmp(const void *Src1, const u32 Src1Size,
const void *Src2, const u32 Src2Size, const u32 CmpLen)
{
int Status = XST_FAILURE;
if ((Src1 == NULL) || (Src2 == NULL)) {
Status = XST_INVALID_PARAM;
}
else if ((CmpLen == 0U) || (Src1Size < CmpLen) || (Src2Size < CmpLen)) {
Status = XST_INVALID_PARAM;
}
else {
Status = memcmp (Src1, Src2, CmpLen);
if (Status != 0) {
Status = XST_FAILURE;
}
}
return Status;
}
/*****************************************************************************/
/**
* @brief This function compares two memory regions for specified number
* of bytes. This function takes size of two memory regions to
* make sure not to read from or write to out of bound memory
* region.
* Note that this function compares till end to make it execute
* in constant time irrespective of the content of input memory.
*
* @param Src1 - Pointer to first memory range
* @param Src1Size - Maximum size of first memory range
* @param Src2 - Pointer to second memory range
* @param Src2Size - Maximum size of second memory range
* @param CmpLen - Number of bytes to be compared
*
* @return
* XST_SUCCESS - If specified number of bytes matches
* XST_FAILURE - If mistmatch
* XST_INVALID_PARAM - Invalid inputs
*
*****************************************************************************/
int Xil_SMemCmp_CT(const void *Src1, const u32 Src1Size,
const void *Src2, const u32 Src2Size, const u32 CmpLen)
{
volatile int Status = XST_FAILURE;
volatile int StatusRedundant = XST_FAILURE;
volatile u32 Data = 0U;
volatile u32 DataRedundant = 0xFFFFFFFFU;
u32 Cnt = CmpLen;
const u8 *Src_1 = (const u8 *)Src1;
const u8 *Src_2 = (const u8 *)Src2;
if ((Src1 == NULL) || (Src2 == NULL)) {
Status = XST_INVALID_PARAM;
}
else if ((CmpLen == 0U) || (Src1Size < CmpLen) || (Src2Size < CmpLen)) {
Status = XST_INVALID_PARAM;
}
else {
while (Cnt >= sizeof(u32)) {
Data |= (*(const u32 *)Src_1 ^ *(const u32 *)Src_2);
DataRedundant &= ~Data;
Src_1 += sizeof(u32);
Src_2 += sizeof(u32);
Cnt -= sizeof(u32);
}
while (Cnt > 0U) {
Data |= (u32)(*Src_1 ^ *Src_2);
DataRedundant &= ~Data;
Src_1++;
Src_2++;
Cnt--;
}
if ((Data == 0U) && (DataRedundant == 0xFFFFFFFFU)) {
Status = XST_SUCCESS;
StatusRedundant = XST_SUCCESS;
}
}
return (Status | StatusRedundant);
}
/*****************************************************************************/
/**
* @brief This is wrapper function to memcpy function. This function
* takes size of two memory regions to make sure not read from
* or write to out of bound memory region.
*
* @param Dest - Pointer to destination memory
* @param DestSize - Memory available at destination
* @param Src - Pointer to source memory
* @param SrcSize - Maximum data that can be copied from source
* @param CopyLen - Number of bytes to be copied
*
* @return
* XST_SUCCESS - Copy is successful
* XST_INVALID_PARAM - Invalid inputs
*
*****************************************************************************/
int Xil_SMemCpy(void *Dest, const u32 DestSize,
const void *Src, const u32 SrcSize, const u32 CopyLen)
{
int Status = XST_FAILURE;
const u8 *Src8 = (const u8 *) Src;
const u8 *Dst8 = (u8 *) Dest;
void * volatile DestTemp = Dest;
const void * volatile SrcTemp = Src;
if ((Dest == NULL) || (Src == NULL)) {
Status = XST_INVALID_PARAM;
}
else if ((CopyLen == 0U) || (DestSize < CopyLen) || (SrcSize < CopyLen)) {
Status = XST_INVALID_PARAM;
}
/* Return error for overlap string */
else if ((Src8 < Dst8) && (&Src8[CopyLen - 1U] >= Dst8)) {
Status = XST_INVALID_PARAM;
}
else if ((Dst8 < Src8) && (&Dst8[CopyLen - 1U] >= Src8)) {
Status = XST_INVALID_PARAM;
}
else {
(void)memcpy(DestTemp, SrcTemp, CopyLen);
Status = XST_SUCCESS;
}
return Status;
}
/*****************************************************************************/
/**
* @brief This is wrapper function to memset function. This function
* writes specified byte to destination specified number of times.
* This function also takes maximum string size that destination
* holds to make sure not to write out of bound area.
*
* @param Dest - Pointer to destination memory
* @param DestSize - Memory available at destination
* @param Data - Any value from 0 to 255
* @param Len - Number of bytes to be copied
*
* @return
* XST_SUCCESS - Copy is successful
* XST_INVALID_PARAM - Invalid inputs
*
*****************************************************************************/
int Xil_SMemSet(void *Dest, const u32 DestSize,
const u8 Data, const u32 Len)
{
int Status = XST_FAILURE;
if ((Dest == NULL) || (DestSize < Len) || (Len == 0U)) {
Status = XST_INVALID_PARAM;
}
else {
(void)memset(Dest, (s32)Data, Len);
Status = XST_SUCCESS;
}
return Status;
}
/*****************************************************************************/
/**
* @brief This function concatenates two strings. This function
* takes size of both strings to make sure not to read from /
* write to out of bound area.
*
* @param DestStr - Pointer to destination string
* @param DestSize - Maximum string size that detination can hold
* @param SrcStr - Pointer to source string
* @param SrcSize - Maximum string size that source can hold
*
* @return
* XST_SUCCESS - Copy is successful
* XST_INVALID_PARAM - Invalid inputs
*
*****************************************************************************/
int Xil_SStrCat (u8 *DestStr, const u32 DestSize,
const u8 *SrcStr, const u32 SrcSize)
{
int Status = XST_FAILURE;
u32 SrcLen;
u32 DstLen;
if ((DestStr == NULL) || (SrcStr == NULL)) {
Status = XST_INVALID_PARAM;
goto END;
}
SrcLen = strnlen((const char*)SrcStr, SrcSize);
DstLen = strnlen((const char*)DestStr, DestSize);
if ((DestSize <= DstLen) || (SrcSize <= SrcLen)) {
Status = XST_INVALID_PARAM;
}
else if (DestSize <= (SrcLen + DstLen)) {
Status = XST_INVALID_PARAM;
}
else {
(void)strcat((char*)DestStr, (const char*)SrcStr);
Status = XST_SUCCESS;
}
END:
return Status;
}
/*****************************************************************************/
/**
* @brief This function compares two strings. It also takes maximum string
* size that Src1 and Src2 can hold to make sure not to read out of
* bound data for comparison.
*
* @param Str1 - Pointer to first string
* @param Str1Size - Maximum string size that Str1 can hold
* @param Str2 - Pointer to second string
* @param Str2Size - Maximum string size that Str2 can hold
*
* @return
* XST_SUCCESS - If both strings are same
* XST_FAILURE - If there is difference between two strings
* XST_INVALID_PARAM - Invalid inputs
*
*****************************************************************************/
int Xil_SStrCmp(const u8 *Str1, const u32 Str1Size,
const u8 *Str2, const u32 Str2Size)
{
int Status = XST_FAILURE;
u32 Str1Len = 0U;
u32 Str2Len = 0U;
if ((Str1 == NULL) || (Str2 == NULL)) {
Status = XST_INVALID_PARAM;
goto END;
}
Str1Len = strnlen((const char*)Str1, Str1Size);
Str2Len = strnlen((const char*)Str2, Str2Size);
if ((Str1Size <= Str1Len) || (Str2Size <= Str2Len)) {
Status = XST_INVALID_PARAM;
}
else if ((Str1Len < Str2Len) || (Str1Len > Str2Len)) {
Status = XST_FAILURE;
}
else {
Status = memcmp(Str1, Str2, Str1Len);
if (Status != 0) {
Status = XST_FAILURE;
}
}
END:
return Status;
}
/*****************************************************************************/
/**
* @brief This function compares two strings. It also takes maximum string
* size that Src1 and Src2 can hold to make sure not to read out of
* bound data for comparison. This function compares each character
* of the strings so that execution time of the function is not
* dependent on the content of two input strings. The execution
* time is constant when string size are same.
*
* @param Str1 - Pointer to first string
* @param Str1Size - Maximum string size that Str1 can hold
* @param Str2 - Pointer to second string
* @param Str2Size - Maximum string size that Str2 can hold
*
* @return
* XST_SUCCESS - If both strings are same
* XST_FAILURE - If there is difference between two strings
* XST_INVALID_PARAM - Invalid inputs
*
*****************************************************************************/
int Xil_SStrCmp_CT (const u8 *Str1, const u32 Str1Size,
const u8 *Str2, const u32 Str2Size)
{
int Status = XST_FAILURE;
u32 Str1Len = 0U;
u32 Str2Len = 0U;
if ((Str1 == NULL) || (Str2 == NULL)) {
Status = XST_INVALID_PARAM;
goto END;
}
Str1Len = strnlen((const char*)Str1, Str1Size);
Str2Len = strnlen((const char*)Str2, Str2Size);
if ((Str1Size <= Str1Len) || (Str2Size <= Str2Len)) {
Status = XST_INVALID_PARAM;
}
else if (Str1Len != Str2Len) {
Status = XST_FAILURE;
}
else {
Status = Xil_SMemCmp_CT (Str1, Str1Size, Str2, Str2Size, Str1Len);
}
END:
return Status;
}
/*****************************************************************************/
/**
* @brief This function copies one string to other. This function
* takes size of both strings to make sure not to read from /
* write to out of bound area.
*
* @param DestStr - Pointer to destination string
* @param DestSize - Maximum string size that detination can hold
* @param SrcStr - Pointer to source string
* @param SrcSize - Maximum string size that source can hold
*
* @return
* XST_SUCCESS - Copy is successful
* XST_INVALID_PARAM - Invalid inputs
*
*****************************************************************************/
int Xil_SStrCpy(u8 *DestStr, const u32 DestSize,
const u8 *SrcStr, const u32 SrcSize)
{
int Status = XST_FAILURE;
u32 SrcLen = 0U;
if ((DestStr == NULL) || (SrcStr == NULL)) {
Status = XST_INVALID_PARAM;
goto END;
}
SrcLen = strnlen((const char*)SrcStr, SrcSize);
if ((DestSize <= SrcLen) || (SrcSize <= SrcLen)) {
Status = XST_INVALID_PARAM;
}
else {
(void)memcpy(DestStr, SrcStr, SrcLen + 1U);
Status = XST_SUCCESS;
}
END:
return Status;
}
/*****************************************************************************/
/**
* @brief This is wrapper function to memmove function. This function
* takes size of two memory regions to avoid out of bound memory region.
*
* @param Dest - Pointer to destination memory
* @param DestSize - Memory available at destination
* @param Src - Pointer to source memory
* @param SrcSize - Maximum data that can be copied from source
* @param CopyLen - Number of bytes to be copied
*
* @return
* XST_SUCCESS - Copy is successful
* XST_INVALID_PARAM - Invalid inputs
*
*****************************************************************************/
int Xil_SMemMove(void *Dest, const u32 DestSize,
const void *Src, const u32 SrcSize, const u32 CopyLen)
{
volatile int Status = XST_FAILURE;
void *Output = NULL;
if ((Dest == NULL) || (Src == NULL)) {
Status = XST_INVALID_PARAM;
}
else if ((CopyLen == 0U) || (DestSize < CopyLen) || (SrcSize < CopyLen)) {
Status = XST_INVALID_PARAM;
}
else {
Output = memmove(Dest, Src, CopyLen);
if (Output != NULL) {
Status = XST_SUCCESS;
}
}
return Status;
}