Beispiel #1
0
/*
** Output single test's pass/fail status
*/
void UT_Report(boolean test, char *fun_name, char *info, char *test_num)
{
    if (test)
    {
#ifdef UT_SHOW_PASS
        SNPRINTF(cMsg, UT_MAX_MESSAGE_LENGTH,
                 "PASSED  [cFE.%s.%s] %s - %s\n-----",
                 UT_subsys, test_num, fun_name, info);
        UT_Text(cMsg);
#endif
        UT_passed++;
    }
    else
    {
        SNPRINTF(cMsg, UT_MAX_MESSAGE_LENGTH,
                 "FAILED  [cFE.%s.%s] %s - %s\n-----",
                 UT_subsys, test_num, fun_name, info);
        UT_Text(cMsg);
#ifdef CFE_LINUX
#ifdef UT_VERBOSE
        printf("FAILED [cFE.%s.%s] %s - %s\n",
               UT_subsys, test_num, fun_name, info);
#endif
#endif
        UT_failed++;
    }
}
/**
** \brief CFE_SB_Subscribe stub function
**
** \par Description
**        This function is used to mimic the response of the cFE SB function
**        CFE_SB_Subscribe.  The user can adjust the response by setting
**        the values in the SB_SubscribeRtn structure prior to this function
**        being called.  If the value SB_SubscribeRtn.count is greater than
**        zero then the counter is decremented; if it then equals zero the
**        return value is set to the user-defined value SB_SubscribeRtn.value.
**        CFE_SUCCESS is returned otherwise.
**
** \par Assumptions, External Events, and Notes:
**        None
**
** \returns
**        Returns either a user-defined status flag or CFE_SUCCESS.
**
******************************************************************************/
int32 CFE_SB_Subscribe(CFE_SB_MsgId_t MsgId, CFE_SB_PipeId_t PipeId)
{
    int32   status = CFE_SUCCESS;
#ifdef UT_VERBOSE
    boolean flag = FALSE;
#endif

    if (SB_SubscribeRtn.count > 0)
    {
        SB_SubscribeRtn.count--;

        if (SB_SubscribeRtn.count == 0)
        {
            status = SB_SubscribeRtn.value;
#ifdef UT_VERBOSE
            flag = TRUE;
            SNPRINTF(cMsg, UT_MAX_MESSAGE_LENGTH,
                     "  CFE_SB_Subscribe called: %ld", SB_SubscribeRtn.value);
            UT_Text(cMsg);
#endif
        }
    }

#ifdef UT_VERBOSE
    if (flag == FALSE)
    {
        SNPRINTF(cMsg, UT_MAX_MESSAGE_LENGTH,
                 "  CFE_SB_Subscribe called: subscribed to msg %d", MsgId);
        UT_Text(cMsg);
    }
#endif

    return status;
}
/**
** \brief CFE_SB_CreatePipe stub function
**
** \par Description
**        This function is used to mimic the response of the cFE SB function
**        CFE_SB_CreatePipe.  The user can adjust the response by setting
**        the values in the SB_CreatePipeRtn structure prior to this function
**        being called.  If the value SB_CreatePipeRtn.count is greater than
**        zero then the counter is decremented; if it then equals zero the
**        return value is set to the user-defined value SB_CreatePipeRtn.value.
**        CFE_SUCCESS is returned otherwise.
**
** \par Assumptions, External Events, and Notes:
**        None
**
** \returns
**        Returns either a user-defined status flag or CFE_SUCCESS.
**
******************************************************************************/
int32 CFE_SB_CreatePipe(CFE_SB_PipeId_t *PipeIdPtr, uint16 Depth,
                        char *PipeName)
{
    int32   status = CFE_SUCCESS;
#ifdef UT_VERBOSE
    boolean flag = FALSE;
#endif

    if (SB_CreatePipeRtn.count > 0)
    {
        SB_CreatePipeRtn.count--;

        if (SB_CreatePipeRtn.count == 0)
        {
#ifdef UT_VERBOSE
            SNPRINTF(cMsg, UT_MAX_MESSAGE_LENGTH,
                     "  CFE_SB_CreatePipe called: %ld",
                     SB_CreatePipeRtn.value);
            UT_Text(cMsg);
            flag = TRUE;
#endif
            status = SB_CreatePipeRtn.value;
        }
    }

#ifdef UT_VERBOSE
    if (flag == FALSE)
    {
        UT_Text("  CFE_SB_CreatePipe called");
    }
#endif

    return status;
}
/**
** \brief CFE_FS_WriteHeader stub function
**
** \par Description
**        This function is used to mimic the response of the cFE FS function
**        CFE_FS_WriteHeader.  The user can adjust the response by setting
**        the values in the FSWriteHdrRtn structure prior to this function
**        being called.  If the value FSWriteHdrRtn.count is greater than
**        zero then the counter is decremented; if it then equals zero the
**        return value is set to the user-defined value FSWriteHdrRtn.value.
**        The size of the CFE_FS_Header_t structure, in bytes, is returned
**        otherwise.
**
** \par Assumptions, External Events, and Notes:
**        None
**
** \returns
**        Returns either a user-defined status flag or the size of the
**        CFE_FS_Header_t structure in bytes.
**
******************************************************************************/
int32 CFE_FS_WriteHeader(int32 filedes, CFE_FS_Header_t *hdr)
{
    int32   status = sizeof(CFE_FS_Header_t);
#ifdef UT_VERBOSE
    boolean flag = FALSE;
#endif

    if (FSWriteHdrRtn.count > 0)
    {
        FSWriteHdrRtn.count--;

        if(FSWriteHdrRtn.count == 0)
        {
            status = FSWriteHdrRtn.value;
#ifdef UT_VERBOSE
            flag = TRUE;
#endif
        }
    }

#ifdef UT_VERBOSE
    if (flag == FALSE)
    {
        SNPRINTF(cMsg, UT_MAX_MESSAGE_LENGTH,
                 "  CFE_FS_WriteHeader called: %ld; %s",
                 filedes, hdr->Description);
        UT_Text(cMsg);
    }
#endif

    return status;
}
/**
** \brief CFE_FS_ReadHeader stub function
**
** \par Description
**        This function is used to mimic the response of the cFE FS function
**        CFE_FS_ReadHeader.  The user can adjust the response by setting
**        the values in the FSReadHdrRtn structure prior to this function
**        being called.  If the value FSReadHdrRtn.count is greater than
**        zero then the counter is decremented; if it then equals zero the
**        return value is set to the user-defined value FSReadHdrRtn.value.
**        The size of the CFE_FS_Header_t structure, in bytes, is returned
**        otherwise.
**
** \par Assumptions, External Events, and Notes:
**        None
**
** \returns
**        Returns either a user-defined status flag or the size of the
**        CFE_FS_Header_t structure in bytes.
**
******************************************************************************/
int32 CFE_FS_ReadHeader(CFE_FS_Header_t *Hdr, int32 FileDes)
{
    int32   status = sizeof(CFE_FS_Header_t);
    boolean flag = FALSE;

    if (FSReadHdrRtn.count > 0)
    {
        FSReadHdrRtn.count--;

        if (FSReadHdrRtn.count == 0)
        {
            status = FSReadHdrRtn.value;
            flag = TRUE;
        }
    }

    if (flag == FALSE)
    {
        memcpy(Hdr, &UT_ReadHdr[UT_ReadHdrOffset], sizeof(CFE_FS_Header_t));
        UT_ReadHdrOffset += sizeof(CFE_FS_Header_t);
#ifdef UT_VERBOSE
        SNPRINTF(cMsg, UT_MAX_MESSAGE_LENGTH,
                 "  CFE_FS_ReadHeader called: %ld; %s",
                 FileDes, Hdr->Description);
        UT_Text(cMsg);
#endif
    }

    return status;
}
Beispiel #6
0
/*
** Display the contents of a packet
*/
void UT_DisplayPkt(CFE_SB_MsgPtr_t ptr, uint32 size)
{
    uint8 *BytePtr = (uint8 *) ptr;
    uint32 i;
    int delta;
    char *msgPtr = cMsg;

    cMsg[0] = '\0';

    if (UT_Endianess == UT_LITTLE_ENDIAN)
    {
        /* Little endian */
        BytePtr += size;
        delta = -1;
    }
    else
    {
        /* Big endian */
        delta = 1;
    }

    for (i = 0; i < size; i++)
    {
        SNPRINTF(msgPtr, UT_MAX_MESSAGE_LENGTH, "%02x ", *BytePtr);
        msgPtr += 3;
        BytePtr += delta;
    }

    UT_Text(cMsg);
}
/**
** \brief CFE_FS_SetTimestamp stub function
**
** \par Description
**        This function is used to mimic the response of the cFE FS function
**        CFE_FS_SetTimestamp.  The user can adjust the response by setting
**        the values in the FSSetTimestampRtn structure prior to this function
**        being called.  If the value FSSetTimestampRtn.count is greater than
**        zero then the counter is decremented; if it then equals zero the
**        return value is set to the user-defined value
**        FSSetTimestampRtn.value.  OS_FS_SUCCESS is returned otherwise.
**
** \par Assumptions, External Events, and Notes:
**        None
**
** \returns
**        Returns either a user-defined status flag or OS_FS_SUCCESS.
**
******************************************************************************/
int32 CFE_FS_SetTimestamp(int32 FileDes, CFE_TIME_SysTime_t NewTimestamp)
{
    int32   status = OS_FS_SUCCESS;
#ifdef UT_VERBOSE
    boolean flag = FALSE;
#endif

    if (FSSetTimestampRtn.count > 0)
    {
        FSSetTimestampRtn.count--;

        if (FSSetTimestampRtn.count == 0)
        {
            status = FSSetTimestampRtn.value;
#ifdef UT_VERBOSE
            flag = TRUE;
#endif
        }
    }

#ifdef UT_VERBOSE
    if (flag == FALSE)
    {
        UT_Text("  CFE_FS_SetTimeStamp called");
    }
#endif

    return status;
}
/**
** \brief CFE_SB_SetMsgTime stub function
**
** \par Description
**        This function is used to mimic the response of the cFE SB function
**        CFE_SB_SetMsgTime.  It always returns CFE_SUCCESS.
**
** \par Assumptions, External Events, and Notes:
**        None
**
** \returns
**        Returns CFE_SUCCESS.
**
******************************************************************************/
int32 CFE_SB_SetMsgTime(CFE_SB_MsgPtr_t MsgPtr, CFE_TIME_SysTime_t time)
{
#ifdef UT_VERBOSE
    UT_Text("  CFE_SB_SetMsgTime called");
#endif
    return CFE_SUCCESS;
}
/**
** \brief CFE_PSP_Panic stub function
**
** \par Description
**        This function is used to mimic the response of the OS API function
**        CFE_PSP_Panic.  The variable PSPPanicRtn.value is set equal to the
**        input variable ErrorCode and the variable PSPPanicRtn.count is
**        incremented each time this function is called.  The unit tests
**        compare these values to expected results to verify proper system
**        response.
**
** \par Assumptions, External Events, and Notes:
**        None
**
** \returns
**        This function does not return a value.
**
******************************************************************************/
void CFE_PSP_Panic(int32 ErrorCode)
{
#ifdef UT_VERBOSE
    snprintf(cMsg, UT_MAX_MESSAGE_LENGTH,
             "  CFE_PSP_Panic called: EC = 0x%lx", (uint32) ErrorCode);
    UT_Text(cMsg);
#endif
    PSPPanicRtn.value = ErrorCode;
    PSPPanicRtn.count++;
}
/**
** \brief CFE_PSP_Restart stub function
**
** \par Description
**        This function is used as a placeholder for the PSP function
**        CFE_PSP_Restart.  The variable PSPRestartRtn.value is set to the
**        value passed to the function, reset_type, and the variable
**        PSPRestartRtn.count is incremented each time this function is called.
**        The unit tests compare these values to expected results to verify
**        proper system response.
**
** \par Assumptions, External Events, and Notes:
**        None
**
** \returns
**        This function does not return a value.
**
******************************************************************************/
void CFE_PSP_Restart(uint32 reset_type)
{
#ifdef UT_VERBOSE
    snprintf(cMsg, UT_MAX_MESSAGE_LENGTH,
             "  CFE_PSP__Restart called: reset_type = %lu", reset_type);
    UT_Text(cMsg);
#endif
    PSPRestartRtn.value = reset_type;
    PSPRestartRtn.count++;
}
Beispiel #11
0
/*
** Test pass/fail summary
*/
int UT_ReportFailures(void)
{
    SNPRINTF(cMsg, UT_MAX_MESSAGE_LENGTH,
             "\n%s PASSED %d tests.", UT_appname, UT_passed);
    UT_Text(cMsg);
    SNPRINTF(cMsg, UT_MAX_MESSAGE_LENGTH,
             "%s FAILED %d tests.", UT_appname, UT_failed);
    UT_Text(cMsg);

#ifdef CFE_LINUX
    printf("\n%s PASSED %d tests.\n%s FAILED %d tests.\n\n",
            UT_appname, UT_passed, UT_appname, UT_failed);

    /* Ensure everything gets written */
    fflush(stdout);
    fclose(UT_logfile);
#endif

    return UT_failed;
}
/**
** \brief CFE_SB_InitMsg stub function
**
** \par Description
**        This function is used to mimic the response of the cFE SB function
**        CFE_SB_InitMsg.
**
** \par Assumptions, External Events, and Notes:
**        None
**
** \returns
**        This function does not return a value.
**
******************************************************************************/
void CFE_SB_InitMsg(void *MsgPtr,
                    CFE_SB_MsgId_t MsgId,
                    uint16 Length,
                    boolean Clear)
{
#ifdef UT_VERBOSE
    SNPRINTF(cMsg, UT_MAX_MESSAGE_LENGTH,
             "  CFE_SB_InitMsg called: initialized msg %d", MsgId);
    UT_Text(cMsg);
#endif
    CFE_SB_SetMsgId(MsgPtr, MsgId);
}
/**
** \brief CFE_PSP_GetCDSSize stub function
**
** \par Description
**        This function is used to mimic the response of the PSP function
**        CFE_PSP_GetCDSSize.  The user can adjust the response by
**        setting the value of UT_BSP_Fail prior to this function being called.
**
** \par Assumptions, External Events, and Notes:
**        None
**
** \returns
**        Returns either OS_SUCCESS or OS_ERROR.
**
******************************************************************************/
int32 CFE_PSP_GetCDSSize(uint32 *SizeOfCDS)
{
    int32 status = OS_SUCCESS;

    if (UT_BSP_Fail & BSP_GETCDSSIZE_FAIL)
    {
        status = OS_ERROR;
#ifdef UT_VERBOSE
        UT_Text("  CFE_PSP_GetCDSSize called: (FAILURE)");
#endif
    } 
#ifdef UT_VERBOSE
    else 
    {
        UT_Text("  CFE_PSP_GEtCDSSize called: (SUCCESS)");
    }
#endif

    *SizeOfCDS = UT_CDS_Size;
    return status;   
}
Beispiel #14
0
/*
** Report and close any sockets found open
*/
void UT_CheckForOpenSockets(void)
{
    int i;
    int InUse = 0;

    for (i = 0; i < OS_MAX_QUEUES; i++)
    {
        if (UT_Queue[i].free == FALSE)
        {
            InUse++;
#ifdef UT_VERBOSE
            SNPRINTF(cMsg, UT_MAX_MESSAGE_LENGTH,
                     "  UT_Queue[%d].%s left open. ID=%d",
                     i, UT_Queue[i].name, UT_Queue[i].id);
            UT_Text(cMsg);
#ifdef SOCKET_QUEUE
            SNPRINTF(cMsg, UT_MAX_MESSAGE_LENGTH,
                     "   Closing socket ID %d, close returned %d",
                     UT_Queue[i].id, close(UT_Queue[i].id));
            UT_Text(cMsg);
#endif
#endif

            /* Clean up same as OS_QueueDelete stub */
            UT_Queue[i].free = TRUE;
            strcpy(UT_Queue[i].name, "");
            UT_Queue[i].id = 0;
        }
    }

#ifdef UT_VERBOSE
    if (InUse > 0)
    {
        SNPRINTF(cMsg, UT_MAX_MESSAGE_LENGTH, "%d socket(s) open", InUse);
        UT_Text(cMsg);
    }
#endif
}
/**
** \brief CFE_PSP_WriteToCDS stub function
**
** \par Description
**        This function is used to mimic the response of the PSP function
**        CFE_PSP_WriteToCDS.  The user can adjust the response by setting
**        the values in the BSPWriteCDSRtn structure prior to this function
**        being called.  If the value BSPWriteCDSRtn.count is greater than
**        zero then the counter is decremented; if it then equals zero the
**        return value is set to the user-defined value BSPWriteCDSRtn.value.
**        Otherwise, the value of the user-defined variable UT_BSP_Fail
**        determines the status returned by the function.
**
** \par Assumptions, External Events, and Notes:
**        None
**
** \returns
**        Returns either OS_SUCCESS, OS_ERROR, or a user-defined value.
**
******************************************************************************/
int32 CFE_PSP_WriteToCDS(void *PtrToDataToWrite,
                         uint32 CDSOffset,
                         uint32 NumBytes)
{
    int32   status = OS_SUCCESS;
    boolean flag = FALSE;

    if (BSPWriteCDSRtn.count > 0)
    {
        BSPWriteCDSRtn.count--;

        if (BSPWriteCDSRtn.count == 0)
        {
            status = BSPWriteCDSRtn.value;
            flag = TRUE;
        }
    }
      
    if (flag == FALSE)
    {
        if (UT_BSP_Fail & BSP_WRITECDS_FAIL)
        {
            status = OS_ERROR;
#ifdef UT_VERBOSE
            UT_Text("  CFE_PSP_WriteToCDS called: (FAILURE)");
#endif
        }
#ifdef UT_VERBOSE
        else
        {
            UT_Text("  CFE_PSP_WriteToCDS called: (SUCCESS)");
        }
#endif
    }

    return status;
}
/**
** \brief CFE_PSP_GetVolatileDiskMem stub function
**
** \par Description
**        This function is used to mimic the response of the PSP function
**        CFE_PSP_GetVolatileDiskMem.  The user can adjust the response by
**        setting the value of UT_BSP_Fail prior to this function being called.
**
** \par Assumptions, External Events, and Notes:
**        None
**
** \returns
**        Returns either OS_SUCCESS or OS_ERROR.
**
******************************************************************************/
int32 CFE_PSP_GetVolatileDiskMem(cpuaddr *PtrToVolDisk, uint32 *SizeOfVolDisk)
{
    int32 status = OS_SUCCESS;

    if (UT_BSP_Fail & BSP_GETVOLDISKMEM_FAIL)
    {
        status = OS_ERROR;
#ifdef UT_VERBOSE
        UT_Text("  CFE_PSP_GetVolatileDiskMem called: (FAILURE)");
#endif
    } 
    else if (SizeOfVolDisk == NULL)
    {
        status = OS_ERROR;
    }
    else
    {
        *PtrToVolDisk = 0;
        *SizeOfVolDisk = 0;
    }

    return status;
}
/**
** \brief CFE_SB_TimeStampMsg stub function
**
** \par Description
**        This function is used as a placeholder for the cFE SB function
**        CFE_SB_TimeStampMsg.
**
** \par Assumptions, External Events, and Notes:
**        None
**
** \returns
**        This function does not return a value.
**
******************************************************************************/
void CFE_SB_TimeStampMsg(CFE_SB_MsgPtr_t MsgPtr)
{
#ifdef UT_VERBOSE
    UT_Text("  CFE_SB_TimeStampMsg called");
#endif
}
/* Only doing subset of total messages;
** NOTE: Currently does EVS, TIME
*/
int32 CFE_SB_SendMsg(CFE_SB_Msg_t *MsgPtr)
{
    int32            status = CFE_SUCCESS;
    boolean          flag = FALSE;
    CFE_EVS_Packet_t *packet;
#ifdef UT_VERBOSE
    int              i;
    CFE_EVS_TlmPkt_t *tlmpkt;
#endif

    if (SBSendMsgRtn.count > 0)
    {
        SBSendMsgRtn.count--;

        if (SBSendMsgRtn.count == 0)
        {
            status = SBSendMsgRtn.value;
            flag = TRUE;
        }
    }

    if (flag == FALSE)
    {
        /* Process message per type */
        switch (CFE_SB_GetMsgId(MsgPtr))
        {
            case CFE_EVS_EVENT_MSG_MID:

                packet = (CFE_EVS_Packet_t *) MsgPtr;
                SendMsgEventIDRtn.value = packet->PacketID.EventID;
#ifdef UT_VERBOSE
                SNPRINTF(cMsg, UT_MAX_MESSAGE_LENGTH,
"  CFE_SB_SendMsg called: type CFE_EVS_EVENT_MSG_MID\n  %lu/%lu/%s %u:%s",
                        packet->PacketID.SpacecraftID,
                        packet->PacketID.ProcessorID,
                        packet->PacketID.AppName,
                        packet->PacketID.EventID,
                        packet->Message);
                UT_Text(cMsg);
#endif

                if (*packet->Message != '\0')
                {
                    SendMsgEventIDRtn.count++;
                }

                break;

            case CFE_EVS_HK_TLM_MID:

                SendMsgEventIDRtn.value = CFE_EVS_HK_TLM_MID;
#ifdef UT_VERBOSE
                tlmpkt = (CFE_EVS_TlmPkt_t *) MsgPtr;
                SNPRINTF(cMsg, UT_MAX_MESSAGE_LENGTH,
                         "  CFE_SB_SendMsg: type CFE_EVS_HK_TLM_MID\n"
                           "   CommandCounter = %d\n"
                           "   CommandErrCounter = %d\n"
                           "   MessageFormatMode = %d\n"
                           "   MessageSendCounter = %d\n"
                           "   MessageTruncCounter = %d\n"
                           "   UnregisteredAppCounter = %d\n"
                           "   OutputPort = %d\n   LogFullFlag = %d\n"
                           "   LogMode = %d\n   LogOverflowCounter = %d",
                         tlmpkt->CommandCounter, tlmpkt->CommandErrCounter,
                         tlmpkt->MessageFormatMode, tlmpkt->MessageSendCounter,
                         tlmpkt->MessageTruncCounter,
                         tlmpkt->UnregisteredAppCounter, tlmpkt->OutputPort,
                         tlmpkt->LogFullFlag, tlmpkt->LogMode,
                         tlmpkt->LogOverflowCounter);
                UT_Text(cMsg);

                for (i = 0; i < CFE_ES_MAX_APPLICATIONS; i++)
                {
                    SNPRINTF(cMsg, UT_MAX_MESSAGE_LENGTH,
                             "   AppID = %lu\n    AppEnableStatus = %d\n    "
                               "AppMessageSentCounter = %d",
                             tlmpkt->AppData[i].AppID,
                             tlmpkt->AppData[i].AppEnableStatus,
                             tlmpkt->AppData[i].AppMessageSentCounter);
                    UT_Text(cMsg);
               }
#endif
                break;

            case CFE_TIME_DIAG_TLM_MID:

                SendMsgEventIDRtn.value = CFE_TIME_DIAG_TLM_MID;
#ifdef UT_VERBOSE
                SNPRINTF(cMsg, UT_MAX_MESSAGE_LENGTH,
                         "Incomplete TIME command: %d",
                         CFE_SB_GetMsgId(MsgPtr));
                UT_Text(cMsg);
#endif
                break;

            case CFE_TIME_HK_TLM_MID:

                SendMsgEventIDRtn.value = CFE_TIME_HK_TLM_MID;
#ifdef UT_VERBOSE
                SNPRINTF(cMsg, UT_MAX_MESSAGE_LENGTH,
                         "Incomplete TIME housekeeping command: %d",
                         CFE_SB_GetMsgId(MsgPtr));
                UT_Text(cMsg);
#endif
                break;

            default:
                /* Process the message with subsystem specific call */
                UT_ProcessSBMsg(MsgPtr);
                break;
        }
    }

    return status;
}
/**
** \brief CFE_PSP_Get_Timebase stub function
**
** \par Description
**        This function is used as a placeholder for the PSP function
**        CFE_PSP_Get_Timebase.
**
** \par Assumptions, External Events, and Notes:
**        None
**
** \returns
**        This function does not return a value.
**
******************************************************************************/
void CFE_PSP_Get_Timebase(uint32 *Tbu, uint32* Tbl)
{
#ifdef UT_VERBOSE
    UT_Text("  CFE_PSP_Get_Timebase called");
#endif
}
/**
** \brief CFE_PSP_ReadFromCDS stub function
**
** \par Description
**        This function is used to mimic the response of the PSP function
**        CFE_PSP_ReadFromCDS.  The user can adjust the response by setting
**        the values in the BSPReadCDSRtn structure prior to this function
**        being called.  If the value BSPReadCDSRtn.count is greater than
**        zero then the counter is decremented; if it then equals zero the
**        return value is set to the user-defined value BSPReadCDSRtn.value.
**        Otherwise, the value of the user-defined variable UT_BSP_Fail
**        determines the status returned by the function.
**
** \par Assumptions, External Events, and Notes:
**        None
**
** \returns
**        Returns either OS_SUCCESS, OS_ERROR, or a user-defined value.
**
******************************************************************************/
int32 CFE_PSP_ReadFromCDS(void *PtrToDataToRead,
                          uint32 CDSOffset,
                          uint32 NumBytes)
{
    int32   status = OS_SUCCESS;
    boolean flag = FALSE;

    if (BSPReadCDSRtn.count > 0)
    {
        BSPReadCDSRtn.count--;

        if (BSPReadCDSRtn.count == 0)
        {
            if (UT_BSPCheckValidity == TRUE)
            {
                memcpy((char *) PtrToDataToRead, "_CDSBeg_", NumBytes);
            }

            status = BSPReadCDSRtn.value;
            flag = TRUE;
        }
    }    
  
    if (flag == FALSE)
    {
        if (UT_BSP_Fail & BSP_READCDS_FAIL)
        {
            status = OS_ERROR;
#ifdef UT_VERBOSE
            UT_Text("  CFE_PSP_ReadFromCDS called: (FAILURE)");
#endif
        }
        else if (UT_CDS_Rebuild)
        {
            if (UT_BSPCheckValidity == TRUE)
            {
                memcpy((char *) PtrToDataToRead, "_CDSBeg_", NumBytes);
                UT_BSPCheckValidity = FALSE;
                BSPReadCDSRtn.value = 1234;

            }
            else
            {
                memcpy(PtrToDataToRead, "_CDSEnd_", NumBytes);
                UT_SetCDSRebuild(FALSE);
            }

#ifdef UT_VERBOSE
            UT_Text("  CFE_PSP_ReadFromCDS called: (REBUILD)");
#endif
        }
        else
        {
            if (UT_CDS_GoodEnd == TRUE)
            {
                if (UT_BSPCheckValidity == TRUE)
                {
                    memcpy(PtrToDataToRead, "_CDSEnd_", NumBytes);
                }
            }
            else
            {
                if (UT_BSPCheckValidity == TRUE)
                {
                    memcpy(PtrToDataToRead, "gibberish", NumBytes);
                }
            }

#ifdef UT_VERBOSE
            UT_Text("  CFE_PSP_ReadFromCDS called: (SUCCESS)");
#endif
        }
    }

    return status;
}