From f19fac7e1fdaae7eab016393a0ed9d6c3b5d2479 Mon Sep 17 00:00:00 2001 From: Mathew Benson Date: Tue, 17 Jul 2018 10:59:48 -0500 Subject: [PATCH] Initial commit of remaining files. --- Makefile | 9 + README.md | 21 + include/ccsds.h | 463 ++++++++++++++++ include/cfe_mission_cfg.h | 477 +++++++++++++++++ include/cfe_sb.h | 443 ++++++++++++++++ include/common_types.h | 374 +++++++++++++ include/config.h | 100 ++++ include/explain.h | 162 ++++++ include/list.h | 165 ++++++ include/memtools.h | 68 +++ include/message.h | 285 ++++++++++ include/parser.h | 198 +++++++ include/usage.h | 96 ++++ include/utils.h | 102 ++++ python/.gitignore | 1 + python/attribdef.py | 19 + python/jsoncombine.py | 19 + python/merged_file.json | 3 + python/parse_gateway_msgs.sh | 72 +++ python/pyexplain.py | 225 ++++++++ python/structdef.py | 26 + setup_deps.sh | 5 + src/Makefile | 38 ++ src/ccsds.c | 178 +++++++ src/cfe_sb_util.c | 409 ++++++++++++++ src/example.c | 189 +++++++ src/explain.c | 231 ++++++++ src/input.json | 96 ++++ src/list.c | 330 ++++++++++++ src/memtools.c | 166 ++++++ src/message.c | 353 +++++++++++++ src/obj/.gitkeep | 0 src/parser.c | 360 +++++++++++++ src/usage.c | 109 ++++ src/utils.c | 111 ++++ test/explain_app_test.c | 995 +++++++++++++++++++++++++++++++++++ test/explain_app_test.h | 41 ++ test/explain_test_utils.c | 57 ++ test/explain_test_utils.h | 50 ++ test/explain_testrunner.c | 46 ++ test/makefile | 125 +++++ test/test_input.json | 164 ++++++ 42 files changed, 7381 insertions(+) create mode 100644 Makefile create mode 100644 README.md create mode 100644 include/ccsds.h create mode 100644 include/cfe_mission_cfg.h create mode 100644 include/cfe_sb.h create mode 100644 include/common_types.h create mode 100644 include/config.h create mode 100644 include/explain.h create mode 100644 include/list.h create mode 100644 include/memtools.h create mode 100644 include/message.h create mode 100644 include/parser.h create mode 100644 include/usage.h create mode 100644 include/utils.h create mode 100644 python/.gitignore create mode 100644 python/attribdef.py create mode 100755 python/jsoncombine.py create mode 100644 python/merged_file.json create mode 100755 python/parse_gateway_msgs.sh create mode 100755 python/pyexplain.py create mode 100644 python/structdef.py create mode 100755 setup_deps.sh create mode 100644 src/Makefile create mode 100644 src/ccsds.c create mode 100644 src/cfe_sb_util.c create mode 100644 src/example.c create mode 100644 src/explain.c create mode 100644 src/input.json create mode 100644 src/list.c create mode 100644 src/memtools.c create mode 100644 src/message.c create mode 100644 src/obj/.gitkeep create mode 100644 src/parser.c create mode 100644 src/usage.c create mode 100644 src/utils.c create mode 100644 test/explain_app_test.c create mode 100644 test/explain_app_test.h create mode 100644 test/explain_test_utils.c create mode 100644 test/explain_test_utils.h create mode 100644 test/explain_testrunner.c create mode 100644 test/makefile create mode 100644 test/test_input.json diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..41c16f9 --- /dev/null +++ b/Makefile @@ -0,0 +1,9 @@ +all: + make -C ./src + make -C ./test +clean: + make -C ./src clean + make -C ./test clean +test: + make -C ./test test + diff --git a/README.md b/README.md new file mode 100644 index 0000000..c495cb2 --- /dev/null +++ b/README.md @@ -0,0 +1,21 @@ +# explain +*verb* +> to make plain or clear; render understandable or intelligible. + +---- +## what is explain? + +explain simplifies the process of exchanging messages between different architectures by parsing the architecture specific application binary interface information from host and target compiled binaries. At run-time the explain adapter modifies messages as required between a host and target. + +---- +## dependencies +TODO + +---- +## usage +1. make +To run an example ./explain -p ../test/test_input.json +---- +## changelog +* TODO + diff --git a/include/ccsds.h b/include/ccsds.h new file mode 100644 index 0000000..a077d2c --- /dev/null +++ b/include/ccsds.h @@ -0,0 +1,463 @@ +/****************************************************************************** +** File: ccsds.h +** +** Copyright (c) 2004-2012, United States government as represented by the +** administrator of the National Aeronautics Space Administration. +** All rights reserved. This software(cFE) was created at NASA's Goddard +** Space Flight Center pursuant to government contracts. +** +** This is governed by the NASA Open Source Agreement and may be used, +** distributed and modified only pursuant to the terms of that agreement. +** +** +** Purpose: +** Define typedefs and macros for CCSDS packet headers. +** +** $Log: ccsds.h $ +** Revision 1.6.1.2 2014/12/02 13:48:54GMT-05:00 rmcgraw +** DCR22841:3 Added CFE_MAKE_BIG16 to ccsds.h in branch64 +** Revision 1.6.1.1 2014/12/01 11:18:00EST rmcgraw +** DCR22841:1 Reverted cmd sec hdr struct and RD/WR macros to pre-6.4.0 state +** Revision 1.6 2014/07/10 10:24:07EDT rmcgraw +** DCR9772:1 Changes from C. Monaco & W.M Reid from APL for endianess neutrality +** Revision 1.5 2011/02/03 15:27:48EST lwalling +** Modified telemetry secondary header definition to support CFE_SB_PACKET_TIME_FORMAT selection +** Revision 1.4 2010/10/25 15:01:27EDT jmdagost +** Corrected bad apostrophe in prologue. +** Revision 1.3 2010/10/04 15:25:32EDT jmdagost +** Cleaned up copyright symbol. +** Revision 1.2 2010/09/21 16:15:16EDT jmdagost +** Removed unused function prototypes. +** Revision 1.1 2008/04/17 08:05:18EDT ruperera +** Initial revision +** Member added to project c:/MKSDATA/MKS-REPOSITORY/MKS-CFE-PROJECT/fsw/cfe-core/src/inc/project.pj +** Revision 1.4 2006/06/12 11:18:18EDT rjmcgraw +** Added legal statement +** Revision 1.3 2006/04/28 15:09:44EDT rjmcgraw +** Corrected comments in CCSDS_CmdSecHdr_t definition +** +******************************************************************************/ + +#ifndef _ccsds_ +#define _ccsds_ + +/* +** Include Files +*/ + +#include "common_types.h" +#include "cfe_mission_cfg.h" + + +/* Macro to convert 16 bit word from platform "endianness" to Big Endian */ +#ifdef SOFTWARE_BIG_BIT_ORDER + #define CFE_MAKE_BIG16(n) (n) +#else + #define CFE_MAKE_BIG16(n) ( (((n) << 8) & 0xFF00) | (((n) >> 8) & 0x00FF) ) +#endif + + +/* CCSDS_TIME_SIZE is specific to the selected CFE_SB time format */ +#if (CFE_SB_PACKET_TIME_FORMAT == CFE_SB_TIME_32_16_SUBS) + /* 32 bits seconds + 16 bits subseconds */ + #define CCSDS_TIME_SIZE 6 +#elif (CFE_SB_PACKET_TIME_FORMAT == CFE_SB_TIME_32_32_SUBS) + /* 32 bits seconds + 32 bits subseconds */ + #define CCSDS_TIME_SIZE 8 +#elif (CFE_SB_PACKET_TIME_FORMAT == CFE_SB_TIME_32_32_M_20) + /* 32 bits seconds + 20 bits microsecs + 12 bits reserved */ + #define CCSDS_TIME_SIZE 8 +#else + /* unknown format */ + #error unable to define CCSDS_TIME_SIZE! +#endif + + +/* +** Type Definitions +*/ + +/********************************************************************** +** Structure definitions for CCSDS headers. All items in the structure +** must be aligned on 16-bit words. Bitfields must be avoided since +** some compilers (such as gcc) force them into 32-bit alignment. +**********************************************************************/ + +/*----- CCSDS packet primary header. -----*/ + +typedef struct { + + uint8 StreamId[2]; /* packet identifier word (stream ID) */ + /* bits shift ------------ description ---------------- */ + /* 0x07FF 0 : application ID */ + /* 0x0800 11 : secondary header: 0 = absent, 1 = present */ + /* 0x1000 12 : packet type: 0 = TLM, 1 = CMD */ + /* 0xE000 13 : CCSDS version, always set to 0 */ + + uint8 Sequence[2]; /* packet sequence word */ + /* bits shift ------------ description ---------------- */ + /* 0x3FFF 0 : sequence count */ + /* 0xC000 14 : segmentation flags: 3 = complete packet */ + + uint8 Length[2]; /* packet length word */ + /* bits shift ------------ description ---------------- */ + /* 0xFFFF 0 : (total packet length) - 7 */ + +} CCSDS_PriHdr_t; + +/*----- CCSDS command secondary header. -----*/ + +typedef struct { + + uint16 Command; /* command secondary header */ + /* bits shift ------------ description ---------------- */ + /* 0x00FF 0 : checksum, calculated by ground system */ + /* 0x7F00 8 : command function code */ + /* 0x8000 15 : reserved, set to 0 */ + +} CCSDS_CmdSecHdr_t; + +/*----- CCSDS telemetry secondary header. -----*/ + +typedef struct { + + uint8 Time[CCSDS_TIME_SIZE]; + +} CCSDS_TlmSecHdr_t; + +/*----- Generic combined command header. -----*/ + +typedef struct { + CCSDS_PriHdr_t PriHdr; + CCSDS_CmdSecHdr_t SecHdr; +} CCSDS_CmdPkt_t; + +/*----- Generic combined telemetry header. -----*/ + +typedef struct { + CCSDS_PriHdr_t PriHdr; + CCSDS_TlmSecHdr_t SecHdr; +} CCSDS_TlmPkt_t; + + +/* +** Macro Definitions +*/ + +/********************************************************************** +** Constant values. +**********************************************************************/ + +/* Value of packet type for a telemetry packet. */ +#define CCSDS_TLM 0 +/* Value of packet type for a command packet. */ +#define CCSDS_CMD 1 + +/* Value of secondary header flag if secondary header not present. */ +#define CCSDS_NO_SEC_HDR 0 +/* Value of secondary header flag if secondary header exists. */ +#define CCSDS_HAS_SEC_HDR 1 + +#define NUM_CCSDS_APIDS 2048 +#define NUM_CCSDS_PKT_TYPES 2 + + +/********************************************************************** +** Initial values for CCSDS header fields. +**********************************************************************/ + +/* Initial value of the sequence count. */ +#define CCSDS_INIT_SEQ 0 +/* Initial value of the sequence flags. */ +#define CCSDS_INIT_SEQFLG 3 +/* Initial value of the command function code. */ +#define CCSDS_INIT_FC 0 +/* Initial value of the command checksum. */ +#define CCSDS_INIT_CHECKSUM 0 + +/* Note: the stream ID and length are always explicitly set for a packet, +** so default values are not required. */ + + +/********************************************************************** +** Macros for reading and writing bit fields in a 16-bit integer. +** These are used to implement the read and write macros below. +**********************************************************************/ + +/* Read bits specified by 'mask' from 'word' and shift down by 'shift'. */ +#define CCSDS_RD_BITS(word,mask,shift) \ + (((word) & mask) >> shift) + +/* Shift 'value' up by 'shift' and write to those bits in 'word' that +** are specified by 'mask'. Other bits in 'word' are unchanged. */ +#define CCSDS_WR_BITS(word,mask,shift,value) \ + ((word) = (uint16)(((word) & ~mask) | (((value) & (mask >> shift)) << shift))) + + +/********************************************************************** +** Macros for reading and writing the fields in a CCSDS header. All +** of the macros are used in a similar way: +** +** CCSDS_RD_xxx(header) -- Read field xxx from header. +** CCSDS_WR_xxx(header,value) -- Write value to field xxx of header. +** +** Note that 'header' is a reference to the actual header structure, +** not to a pointer to the structure. If using a pointer, one must +** refer to the structure as *pointer. +** +** The CCSDS_WR_xxx macros may refer to 'header' more than once; thus +** the expression for 'header' must NOT contain any side effects. +**********************************************************************/ + +/* Read entire stream ID from primary header. */ +#define CCSDS_RD_SID(phdr) (((phdr).StreamId[0] << 8) + ((phdr).StreamId[1])) +/* Write entire stream ID to primary header. */ +#define CCSDS_WR_SID(phdr,value) ( ((phdr).StreamId[0] = (value >> 8) ) ,\ + ((phdr).StreamId[1] = (value & 0xff) ) ) + +/* Read application ID from primary header. */ +#define CCSDS_RD_APID(phdr) (CCSDS_RD_SID(phdr) & 0x07FF) +/* Write application ID to primary header. */ +#define CCSDS_WR_APID(phdr,value) ((((phdr).StreamId[0] = ((phdr).StreamId[0] & 0xF8) | ((value >> 8) & 0x07))) ,\ + (((phdr).StreamId[1] = ((value)) & 0xff)) ) + +/* Read secondary header flag from primary header. */ +#define CCSDS_RD_SHDR(phdr) (((phdr).StreamId[0] & 0x08) >> 3) +/* Write secondary header flag to primary header. */ +#define CCSDS_WR_SHDR(phdr,value) ((phdr).StreamId[0] = ((phdr).StreamId[0] & 0xf7) | ((value << 3) & 0x08)) + +/* Read packet type (0=TLM,1=CMD) from primary header. */ +#define CCSDS_RD_TYPE(phdr) (((phdr).StreamId[0] & 0x10) >> 4) +/* Write packet type (0=TLM,1=CMD) to primary header. */ +#define CCSDS_WR_TYPE(phdr,value) ((phdr).StreamId[0] = ((phdr).StreamId[0] & 0xEF) | ((value << 4) & 0x10)) + +/* Read CCSDS version from primary header. */ +#define CCSDS_RD_VERS(phdr) (((phdr).StreamId[0] & 0xE0) >> 5) +/* Write CCSDS version to primary header. */ +#define CCSDS_WR_VERS(phdr,value) ((phdr).StreamId[0] = ((phdr).StreamId[0] & 0x1F) | ((value << 5) & 0xE0)) + +/* Read sequence count from primary header. */ +#define CCSDS_RD_SEQ(phdr) ((((phdr).Sequence[0] & 0x3F) << 8) + ((phdr).Sequence[1])) +/* Write sequence count to primary header. */ +#define CCSDS_WR_SEQ(phdr,value) ((((phdr).Sequence[0] = ((phdr).Sequence[0] & 0xC0) | ((value >> 8) & 0x3f))) ,\ + (((phdr).Sequence[1] = ((value)) & 0xff)) ) + +/* Read sequence flags from primary header. */ +#define CCSDS_RD_SEQFLG(phdr) (((phdr).Sequence[0] & 0xC0) >> 6) +/* Write sequence flags to primary header. */ +#define CCSDS_WR_SEQFLG(phdr,value) ((phdr).Sequence[0] = ((phdr).Sequence[0] & 0x3F) | ((value << 6) & 0xC0) ) + +/* Read total packet length from primary header. */ +#define CCSDS_RD_LEN(phdr) ( ( (phdr).Length[0] << 8) + (phdr).Length[1] + 7) +/* Write total packet length to primary header. */ +#define CCSDS_WR_LEN(phdr,value) ((((phdr).Length[0] = ((value) - 7) >> 8)) ,\ + (((phdr).Length[1] = ((value) - 7) & 0xff)) ) + +/* Read function code from command secondary header. */ +#define CCSDS_RD_FC(shdr) CCSDS_RD_BITS((shdr).Command, 0x7F00, 8) +/* Write function code to command secondary header. */ +#define CCSDS_WR_FC(shdr,value) CCSDS_WR_BITS((shdr).Command, 0x7F00, 8, value) + +/* Read checksum from command secondary header. */ +#define CCSDS_RD_CHECKSUM(shdr) CCSDS_RD_BITS((shdr).Command, 0x00FF, 0) +/* Write checksum to command secondary header. */ +#define CCSDS_WR_CHECKSUM(shdr,val) CCSDS_WR_BITS((shdr).Command, 0x00FF, 0, val) + + +/********************************************************************** +** Macros for clearing a CCSDS header to a standard initial state. All +** of the macros are used in a similar way: +** CCSDS_CLR_xxx_HDR(header) -- Clear header of type xxx. +**********************************************************************/ + +/* Clear primary header. */ +#define CCSDS_CLR_PRI_HDR(phdr) \ + ( (phdr).StreamId[0] = 0,\ + (phdr).StreamId[1] = 0,\ + (phdr).Sequence[0] = (CCSDS_INIT_SEQFLG << 6),\ + (phdr).Sequence[1] = 0,\ + (phdr).Length[0] = 0, \ + (phdr).Length[1] = 0 ) + +/* Clear command secondary header. */ +#define CCSDS_CLR_CMDSEC_HDR(shdr) \ + ( (shdr).Command = (CCSDS_INIT_CHECKSUM << 0) | (CCSDS_INIT_FC << 8) ) + + +#define CCSDS_WR_SEC_HDR_SEC(shdr, value) shdr.Time[0] = ((value>>24) & 0xFF), \ + shdr.Time[1] = ((value>>16) & 0xFF), \ + shdr.Time[2] = ((value>>8) & 0xFF), \ + shdr.Time[3] = ((value) & 0xFF) + +#define CCSDS_RD_SEC_HDR_SEC(shdr) (((uint32)shdr.Time[0]) << 24) | \ + (((uint32)shdr.Time[1]) << 16) | \ + (((uint32)shdr.Time[2]) << 8) | \ + ((uint32)shdr.Time[3]) + +/* Clear telemetry secondary header. */ +#if (CFE_SB_PACKET_TIME_FORMAT == CFE_SB_TIME_32_16_SUBS) + /* 32 bits seconds + 16 bits subseconds */ + #define CCSDS_CLR_TLMSEC_HDR(shdr) \ + ( (shdr).Time[0] = 0,\ + (shdr).Time[1] = 0,\ + (shdr).Time[2] = 0,\ + (shdr).Time[3] = 0,\ + (shdr).Time[4] = 0,\ + (shdr).Time[5] = 0 ) + + +#define CCSDS_WR_SEC_HDR_SUBSEC(shdr, value) shdr.Time[4] = ((value>>8) & 0xFF), \ + shdr.Time[5] = ((value) & 0xFF) + +#define CCSDS_RD_SEC_HDR_SUBSEC(shdr) (((uint32)shdr.Time[4]) << 8) | \ + ((uint32)shdr.Time[5]) +#elif ((CFE_SB_PACKET_TIME_FORMAT == CFE_SB_TIME_32_32_SUBS) ||\ + (CFE_SB_PACKET_TIME_FORMAT == CFE_SB_TIME_32_32_M_20)) + /* 32 bits seconds + 32 bits subseconds */ + #define CCSDS_CLR_TLMSEC_HDR(shdr) \ + ( (shdr).Time[0] = 0,\ + (shdr).Time[1] = 0,\ + (shdr).Time[2] = 0,\ + (shdr).Time[3] = 0,\ + (shdr).Time[4] = 0,\ + (shdr).Time[5] = 0,\ + (shdr).Time[6] = 0,\ + (shdr).Time[7] = 0 ) + +#define CCSDS_WR_SEC_HDR_SUBSEC(shdr, value) shdr.Time[4] = ((value>>24) & 0xFF), \ + shdr.Time[5] = ((value>>16) & 0xFF), \ + shdr.Time[6] = ((value>>8) & 0xFF), \ + shdr.Time[7] = ((value) & 0xFF) + +#define CCSDS_RD_SEC_HDR_SUBSEC(shdr) (((uint32)shdr.Time[4]) << 24) | \ + (((uint32)shdr.Time[5]) << 16) | \ + (((uint32)shdr.Time[6]) << 8) | \ + ((uint32)shdr.Time[7]) +#endif + + + +/********************************************************************** +** Macros for extracting fields from a stream ID. All of the macros +** are used in a similar way: +** +** CCSDS_SID_xxx(sid) -- Extract field xxx from sid. +**********************************************************************/ + +/* Extract application ID from stream ID. */ +#define CCSDS_SID_APID(sid) CCSDS_RD_BITS(sid, 0x07FF, 0) + +/* Extract secondary header flag from stream ID. */ +#define CCSDS_SID_SHDR(sid) CCSDS_RD_BITS(sid, 0x0800, 11) + +/* Extract packet type (0=TLM,1=CMD) from stream ID. */ +#define CCSDS_SID_TYPE(sid) CCSDS_RD_BITS(sid, 0x1000, 12) + +/* Extract CCSDS version from stream ID. */ +#define CCSDS_SID_VERS(sid) CCSDS_RD_BITS(sid, 0xE000, 13) + + +/********************************************************************** +** Macros for frequently used combinations of operations. +** +** CCSDS_INC_SEQ(phdr) -- Increment sequence count. +**********************************************************************/ + +/* Increment sequence count in primary header by 1. */ +#define CCSDS_INC_SEQ(phdr) \ + CCSDS_WR_SEQ(phdr, (CCSDS_RD_SEQ(phdr)+1)) + + +/*********************************************************************/ + +/* +** Exported Functions +*/ + +/****************************************************************************** +** Function: CCSDS_InitPkt() +** +** Purpose: +** Initialize a CCSDS packet. The primary header is initialized with +** specified values, and if the Clear flag is set, the rest of the packet +** is filled with zeros. +** +** Arguments: +** PktPtr : Pointer to primary header of packet. +** StreamId : Stream ID to use for the packet. +** Length : Length of the packet in bytes. +** Clear : Indicates whether to clear the entire packet: +** TRUE = fill sequence count and packet data with zeros +** (used after a cold restart) +** FALSE = leave sequence count and packet data unchanged +** (used after a warm restart if data must be preserved) +** +** Return: +** (none) +*/ + +void CCSDS_InitPkt (CCSDS_PriHdr_t *PktPtr, + uint16 StreamId, + uint16 Length, + boolean Clear ); + + + +/****************************************************************************** +** Function: CCSDS_LoadCheckSum() +** +** Purpose: +** Compute and load a checksum for a CCSDS command packet that has a +** secondary header. +** +** Arguments: +** PktPtr : Pointer to header of command packet. The packet must +** have a secondary header and the length in the primary +** header must be correct. The checksum field in the packet +** will be modified. +** +** Return: +** (none) +*/ + +void CCSDS_LoadCheckSum (CCSDS_CmdPkt_t *PktPtr); + +/****************************************************************************** +** Function: CCSDS_ValidCheckSum() +** +** Purpose: +** Determine whether a checksum in a command packet is valid. +** +** Arguments: +** PktPtr : Pointer to header of command packet. The packet must +** have a secondary header and the length in the primary +** header must be correct. +** +** Return: +** TRUE if checksum of packet is valid; FALSE if not. +** A valid checksum is 0. +*/ + +boolean CCSDS_ValidCheckSum (CCSDS_CmdPkt_t *PktPtr); + +/****************************************************************************** +** Function: CCSDS_ComputeCheckSum() +** +** Purpose: +** Compute the checksum for a command packet. The checksum is the XOR of +** all bytes in the packet; a valid checksum is zero. +** +** Arguments: +** PktPtr : Pointer to header of command packet. The packet must +** have a secondary header and the length in the primary +** header must be correct. +** +** Return: +** TRUE if checksum of packet is valid; FALSE if not. +*/ + +uint8 CCSDS_ComputeCheckSum (CCSDS_CmdPkt_t *PktPtr); + + +#endif /* _ccsds_ */ +/*****************************************************************************/ diff --git a/include/cfe_mission_cfg.h b/include/cfe_mission_cfg.h new file mode 100644 index 0000000..7c99045 --- /dev/null +++ b/include/cfe_mission_cfg.h @@ -0,0 +1,477 @@ +/****************************************************************************** +** File: cfe_mission_cfg.h +** +** Purpose: +** This header file contains the mission configuration parameters and +** typedefs with mission scope. +** +** Author: R.McGraw/SSI +** +** Notes: +** +** $Log: cfe_mission_cfg.h $ +** Revision 1.9 2011/11/30 15:13:24GMT-05:00 jmdagost +** Changed definitions to be TRUE/FALSE instead of commenting/uncommenting them. +** Revision 1.8 2011/02/03 15:20:10EST lwalling +** Added definition for CFE_SB_PACKET_TIME_FORMAT and list of supported selections +** Revision 1.7 2009/06/26 10:17:13EDT rmcgraw +** DCR8290:6 Comment changes +** Revision 1.6 2009/02/26 17:45:07EST rmcgraw +** Member moved from ../fsw/build/inc/ to ../fsw/mission_inc/ +** Revision 1.5 2009/02/26 17:45:07ACT rmcgraw +** DCR6805:1 Added comments to reflect SB cfg paramater limits +** Revision 1.4 2008/12/08 12:07:02EST dkobe +** Updates to correct doxygen errors +** Revision 1.3 2008/11/19 08:45:22EST wfmoleski +** The changes are as follows: +** added 6 #defines (2 for each cpu) that indicate the APPID_BASE for cmds and tlm. +** Revision 1.2 2008/07/07 14:09:42EDT apcudmore +** Removed FS Message ID defines from system config files. +** Revision 1.1 2008/04/17 08:02:33EDT ruperera +** Initial revision +** Member added to /fsw/build/inc/project.pj +** Revision 1.21 2007/09/19 15:21:16EDT rjmcgraw +** DCR4488 Removed all SB network message numbers and message ids +** Revision 1.20 2007/09/12 16:06:11EDT David Kobe (dlkobe) +** Moved the definitions of CFE_ES_CRC_xx to the cfe_mission_cfg.h file and deleted TBL Services +** CRC #define statement. +** Revision 1.19 2007/09/12 09:46:03EDT David Kobe (dlkobe) +** Added doxygen comments to commands and some configuration parameters +** Revision 1.18 2007/06/08 11:12:47EDT rjmcgraw +** Added doxygen comments +** Revision 1.17 2007/05/04 20:07:53EDT dlkobe +** Added command to telemeter memory pool statistics +** Revision 1.16 2007/04/19 15:43:48EDT rjmcgraw +** Removed SBP related #defines +** Revision 1.15 2007/02/23 09:11:33EST njyanchik +** Added CFE_ES_SHELL_TLM_MSG +** Revision 1.14 2006/12/28 16:25:40EST rjmcgraw +** Added msg numbers for new SB subscription pkts +** Revision 1.13 2006/12/26 15:13:37EST rjmcgraw +** Comment changes in networking defines +** Revision 1.12 2006/11/28 11:28:30EST mobartholomew +** Updated cfe_mission_cfg to reference valid CRC type +** Revision 1.11 2006/11/09 15:30:07EST rjmcgraw +** Added #define for CFE_SPACECRAFT_ID +** Revision 1.10 2006/10/30 12:53:13EST dlkobe +** Baseline Critical Data Store Implementation +** +******************************************************************************/ + +#ifndef _cfe_mission_cfg_ +#define _cfe_mission_cfg_ + + +/** +** \cfemissioncfg Spacecraft ID +** +** \par Description: +** This defines the value that is returned by the call to +** CFE_PSP_GetSpacecraftId. +** +** \par Limits +** The cFE does not place a limit on this configuration paramter. +** CCSDS allocates 8 bits for this field in the standard VCDU. +*/ +#define CFE_SPACECRAFT_ID 0x42 + + +/** +** \cfemissioncfg Spacecraft ID +** +** \par Description: +** Dictates the message format used by the cFE. +** +** \par Limits +** All versions of the cFE currently support only CCSDS as the message format +*/ +#define MESSAGE_FORMAT_IS_CCSDS + + +/** \name Packet timestamp format identifiers */ +/** \{ */ +#define CFE_SB_TIME_32_16_SUBS 1 /**< \brief 32 bits seconds + 16 bits subseconds (units = 2^^-16) */ +#define CFE_SB_TIME_32_32_SUBS 2 /**< \brief 32 bits seconds + 32 bits subseconds (units = 2^^-32) */ +#define CFE_SB_TIME_32_32_M_20 3 /**< \brief 32 bits seconds + 20 bits microsecs + 12 bits reserved */ +/** \} */ + +/** +** \cfemissioncfg Packet Timestamp Format Selection +** +** \par Description: +** Defines the size, format and contents of the telemetry packet timestamp. +** +** \par Limits +** Must be defined as one of the supported formats listed above +*/ +#define CFE_SB_PACKET_TIME_FORMAT CFE_SB_TIME_32_16_SUBS + + +/** +** \cfesbcfg Maximum SB Message Size +** +** \par Description: +** The following definition dictates the maximum message size allowed on +** the software bus. SB checks the pkt length field in the header of all +** messages sent. If the pkt length field indicates the message is larger +** than this define, SB sends an event and rejects the send. +** +** +** \par Limits +** This parameter has a lower limit of 6 (CCSDS primary header size), +** and an upper limit (including headers) of 32768 bytes. +*/ +#define CFE_SB_MAX_SB_MSG_SIZE 32768 + + +/** +** \cfetimecfg Default Time Format +** +** \par Description: +** The following definitions select either UTC or TAI as the default +** (mission specific) time format. Although it is possible for an +** application to request time in a specific format, most callers +** should use CFE_TIME_GetTime(), which returns time in the default +** format. This avoids having to modify each individual caller +** when the default choice is changed. +** +** +** \par Limits +** if CFE_TIME_CFG_DEFAULT_TAI is defined as TRUE then CFE_TIME_CFG_DEFAULT_UTC must be +** defined as FALSE. +** if CFE_TIME_CFG_DEFAULT_TAI is defined as FALSE then CFE_TIME_CFG_DEFAULT_UTC must be +** defined as TRUE. +*/ +#define CFE_TIME_CFG_DEFAULT_TAI TRUE +#define CFE_TIME_CFG_DEFAULT_UTC FALSE + + +/** +** \cfetimecfg Default Time Format +** +** \par Description: +** The following definition enables the use of a simulated time at +** the tone signal using a software bus message. +** +** +** \par Limits +** Not Applicable +*/ +#define CFE_TIME_CFG_FAKE_TONE TRUE + + +/** +** \cfetimecfg Default Time and Tone Order +** +** \par Description: +** Time Services may be configured to expect the time at the tone +** data packet to either precede or follow the tone signal. If the +** time at the tone data packet follows the tone signal, then the +** data within the packet describes what the time "was" at the tone. +** If the time at the tone data packet precedes the tone signal, then +** the data within the packet describes what the time "will be" at +** the tone. One, and only one, of the following symbols must be set to TRUE: +** - CFE_TIME_AT_TONE_WAS +** - CFE_TIME_AT_TONE_WILL_BE +** Note: If Time Services is defined as using a simulated tone signal +** (see #CFE_TIME_CFG_FAKE_TONE above), then the tone data packet +** must follow the tone signal. +** +** \par Limits +** Either CFE_TIME_AT_TONE_WAS or CFE_TIME_AT_TONE_WILL_BE must be set to TRUE. +** They may not both be TRUE and they may not both be FALSE. +*/ +#define CFE_TIME_AT_TONE_WAS TRUE +#define CFE_TIME_AT_TONE_WILL_BE FALSE + +/** +** \cfetimecfg Min and Max Time Elapsed +** +** \par Description: +** Based on the definition of Time and Tone Order +** (CFE_TIME_AT_TONE_WAS/WILL_BE) either the "time at the tone" signal or +** data packet will follow the other. This definition sets the valid window +** of time for the second of the pair to lag behind the first. Time +** Services will invalidate both the tone and packet if the second does not +** arrive within this window following the first. +** +** For example, if the data packet follows the tone, it might be valid for +** the data packet to arrive between zero and 100,000 micro-seconds after +** the tone. But, if the tone follows the the packet, it might be valid +** only if the packet arrived between 200,000 and 700,000 micro-seconds +** before the tone. +** +** Note: units are in micro-seconds +** +** +** \par Limits +** 0 to 999,999 decimal +*/ +#define CFE_TIME_MIN_ELAPSED 0 +#define CFE_TIME_MAX_ELAPSED 200000 + + +/** +** \cfetimecfg Default Time Values +** +** \par Description: +** Default time values are provided to avoid problems due to time +** calculations performed after startup but before commands can be +** processed. For example, if the default time format is UTC then +** it is important that the sum of MET and STCF always exceed the +** value of Leap Seconds to prevent the UTC time calculation +** (time = MET + STCF - Leap Seconds) from resulting in a negative +** (very large) number.

+** Some past missions have also created known (albeit wrong) default +** timestamps. For example, assume the epoch is defined as Jan 1, 1970 +** and further assume the default time values are set to create a timestamp +** of Jan 1, 2000. Even though the year 2000 timestamps are wrong, it +** may be of value to keep the time within some sort of bounds acceptable +** to the software.

+** Note: Sub-second units are in micro-seconds (0 to 999,999) and +** all values must be defined +** +** \par Limits +** Not Applicable +*/ +#define CFE_TIME_DEF_MET_SECS 1000 +#define CFE_TIME_DEF_MET_SUBS 0 + +#define CFE_TIME_DEF_STCF_SECS 1000000 +#define CFE_TIME_DEF_STCF_SUBS 0 + +#define CFE_TIME_DEF_LEAPS 32 + +#define CFE_TIME_DEF_DELAY_SECS 0 +#define CFE_TIME_DEF_DELAY_SUBS 1000 + + +/** +** \cfetimecfg Default EPOCH Values +** +** \par Description: +** Default ground time epoch values +** Note: these values are used only by the CFE_TIME_Print() API function +** +** \par Limits +** Year - must be within 136 years +** Day - Jan 1 = 1, Feb 1 = 32, etc. +** Hour - 0 to 23 +** Minute - 0 to 59 +** Second - 0 to 59 +*/ +#define CFE_TIME_EPOCH_YEAR 1980 +#define CFE_TIME_EPOCH_DAY 1 +#define CFE_TIME_EPOCH_HOUR 0 +#define CFE_TIME_EPOCH_MINUTE 0 +#define CFE_TIME_EPOCH_SECOND 0 + + +/** +** \cfetimecfg Time File System Factor +** +** \par Description: +** Define the s/c vs file system time conversion constant... +** +** Note: this value is intended for use only by CFE TIME API functions to +** convert time values based on the ground system epoch (s/c time) to +** and from time values based on the file system epoch (fs time). +** +** FS time = S/C time + factor +** S/C time = FS time - factor +** +** Worksheet: +** +** S/C epoch = Jan 1, 2005 (LRO ground system epoch) +** FS epoch = Jan 1, 1980 (vxWorks DOS file system epoch) +** +** Delta = 25 years, 0 days, 0 hours, 0 minutes, 0 seconds +** +** Leap years = 1980, 1984, 1988, 1992, 1996, 2000, 2004 +** (divisible by 4 -- except if by 100 -- unless also by 400) +** +** 1 year = 31,536,000 seconds +** 1 day = 86,400 seconds +** 1 hour = 3,600 seconds +** 1 minute = 60 seconds +** +** 25 years = 788,400,000 seconds +** 7 extra leap days = 604,800 seconds +** +** total delta = 789,004,800 seconds +** +** \par Limits +** Not Applicable +*/ +#define CFE_TIME_FS_FACTOR 789004800 + + +/** +** \cfeescfg Maximum Length of CDS Name +** +** \par Description: +** Indicates the maximum length (in characers) of the CDS name ('CDSName') +** portion of a Full CDS Name of the following form: +** "ApplicationName.CDSName" +** +** +** \par Limits +** Not Applicable +*/ +#define CFE_ES_CDS_MAX_NAME_LENGTH 16 + + + +/** +** \cfeevscfg Maximum Event Message Length +** +** \par Description: +** Indicates the maximum length (in characers) of the formatted text +** string portion of an event message +** +** \par Limits +** Not Applicable +*/ +#define CFE_EVS_MAX_MESSAGE_LENGTH 122 + + +/** \name Checksum/CRC algorithm identifiers */ +/** \{ */ +#define CFE_ES_CRC_8 1 /**< \brief CRC ( 8 bit additive - returns 32 bit total) (Currently not implemented) */ +#define CFE_ES_CRC_16 2 /**< \brief CRC (16 bit additive - returns 32 bit total) */ +#define CFE_ES_CRC_32 3 /**< \brief CRC (32 bit additive - returns 32 bit total) (Currently not implemented) */ +/** \} */ + +/** +** \cfeescfg Mission Default CRC algorithm +** +** \par Description: +** Indicates the which CRC algorithm should be used as the default +** for verifying the contents of Critical Data Stores and when calculating +** Table Image data integrity values. +** +** \par Limits +** Currently only CFE_ES_CRC_16 is supported (see #CFE_ES_CRC_16) +*/ +#define CFE_ES_DEFAULT_CRC CFE_ES_CRC_16 + + +/** +** \cfetblcfg Maximum Table Name Length +** +** \par Description: +** Indicates the maximum length (in characers) of the table name +** ('TblName') portion of a Full Table Name of the following +** form: "ApplicationName.TblName" +** +** \par Limits +** Not Applicable +*/ +#define CFE_TBL_MAX_NAME_LENGTH 16 + + +/** +** \cfemissioncfg cFE Message ID Base Numbers +** +** \par Description: +** Message Id base numbers for the cFE messages +** NOTE: cFE MsgIds are the sum of the base numbers and the portable msg +** numbers. +** +** \par Limits +** Must be less than CFE_SB_HIGHEST_VALID_MSGID +*/ +#define CFE_CMD_MID_BASE_CPU1 0x1800 +#define CFE_TLM_MID_BASE_CPU1 0x0800 +#define CFE_CMD_APPID_BASE_CPU1 1 +#define CFE_TLM_APPID_BASE_CPU1 0 + +#define CFE_CMD_MID_BASE_CPU2 0x1820 +#define CFE_TLM_MID_BASE_CPU2 0x0820 +#define CFE_CMD_APPID_BASE_CPU2 33 +#define CFE_TLM_APPID_BASE_CPU2 32 + +#define CFE_CMD_MID_BASE_CPU3 0x1840 +#define CFE_TLM_MID_BASE_CPU3 0x0840 +#define CFE_CMD_APPID_BASE_CPU3 65 +#define CFE_TLM_APPID_BASE_CPU3 64 + +#define CFE_CMD_MID_BASE_GLOB 0x1860 +#define CFE_TLM_MID_BASE_GLOB 0x0860 + + + +/** +** \cfemissioncfg cFE Portable Message Numbers for Commands +** +** \par Description: +** Portable message numbers for the cFE command messages +** NOTE: cFE MsgIds are the sum of the base numbers and the portable msg +** numbers. +** +** \par Limits +** Not Applicable +*/ +#define CFE_EVS_CMD_MSG 1 + /* Offset 2 is available */ +#define CFE_SB_CMD_MSG 3 +#define CFE_TBL_CMD_MSG 4 +#define CFE_TIME_CMD_MSG 5 +#define CFE_ES_CMD_MSG 6 + +#define CFE_ES_SEND_HK_MSG 8 +#define CFE_EVS_SEND_HK_MSG 9 + /* Offset 10 is available */ +#define CFE_SB_SEND_HK_MSG 11 +#define CFE_TBL_SEND_HK_MSG 12 +#define CFE_TIME_SEND_HK_MSG 13 + +#define CFE_TIME_TONE_CMD_MSG 16 +#define CFE_TIME_1HZ_CMD_MSG 17 + + +/** +** \cfemissioncfg cFE Portable Message Numbers for Global Messages +** +** \par Description: +** Portable message numbers for the cFE global messages +** NOTE: cFE MsgIds are the sum of the base numbers and the portable msg +** numbers. +** +** \par Limits +** Not Applicable +*/ +#define CFE_TIME_DATA_CMD_MSG 0 +#define CFE_TIME_FAKE_CMD_MSG 1 +#define CFE_TIME_SEND_CMD_MSG 2 + + +/** +** \cfemissioncfg cFE Portable Message Numbers for Telemetry +** +** \par Description: +** Portable message numbers for the cFE telemetry messages +** NOTE: cFE MsgIds are the sum of the base numbers and the portable msg +** numbers. +** +** \par Limits +** Not Applicable +*/ +#define CFE_ES_HK_TLM_MSG 0 +#define CFE_EVS_HK_TLM_MSG 1 + /* Offset 2 is available */ +#define CFE_SB_HK_TLM_MSG 3 +#define CFE_TBL_HK_TLM_MSG 4 +#define CFE_TIME_HK_TLM_MSG 5 +#define CFE_TIME_DIAG_TLM_MSG 6 + +#define CFE_EVS_EVENT_MSG_MSG 8 +#define CFE_SB_STATS_TLM_MSG 10 +#define CFE_ES_APP_TLM_MSG 11 +#define CFE_TBL_REG_TLM_MSG 12 +#define CFE_SB_ALLSUBS_TLM_MSG 13 +#define CFE_SB_ONESUB_TLM_MSG 14 +#define CFE_ES_SHELL_TLM_MSG 15 +#define CFE_ES_MEMSTATS_TLM_MSG 16 + +#endif diff --git a/include/cfe_sb.h b/include/cfe_sb.h new file mode 100644 index 0000000..75d8a13 --- /dev/null +++ b/include/cfe_sb.h @@ -0,0 +1,443 @@ +/****************************************************************************** +** File: cfe_sb.h +** +** Copyright (c) 2004-2006, United States government as represented by the +** administrator of the National Aeronautics Space Administration. +** All rights reserved. This software(cFE) was created at NASA's Goddard +** Space Flight Center pursuant to government contracts. +** +** This is governed by the NASA Open Source Agreement and may be used, +** distributed and modified only pursuant to the terms of that agreement. +** +** +** Purpose: +** This header file contains all definitions for the cFE Software Bus +** Application Programmer's Interface. +** +** Author: R.McGraw/SSI +** +** $Log: cfe_sb.h $ +** Revision 1.10 2011/04/07 08:34:14GMT-05:00 lwalling +** This file references CFE TIME structures, therefore it should include cfe_time.h +** Revision 1.9 2009/07/29 19:21:50EDT aschoeni +** Added ZeroCopyHandle_t +** Revision 1.8 2009/07/24 18:25:20EDT aschoeni +** Added Zero Copy Mode +** Revision 1.7 2009/07/17 19:42:20EDT aschoeni +** Added PassMsg API to sb to support sequence count preservation +** Revision 1.6 2009/06/10 09:15:06EDT acudmore +** updated os_bsp.h to cfe_psp.h +** Revision 1.5 2009/04/29 10:03:59EDT rmcgraw +** DCR5801:11 Changed comments related to subscription return value +** Revision 1.4 2009/02/27 09:55:04EST rmcgraw +** DCR1709:1 Removed incorrect comment in SetTotalMsgLength +** and reworded other comments +** Revision 1.3 2009/02/26 17:49:19EST rmcgraw +** DCR6805:1 Added note under subscription API declaration +** Revision 1.2 2008/12/08 12:06:56EST dkobe +** Updates to correct doxygen errors +** Revision 1.1 2008/04/17 08:05:22EDT ruperera +** Initial revision +** Member added to cfe project on tlserver3 +** Revision 1.25 2007/09/25 10:34:38EDT rjmcgraw +** DCR5127 Added doxygen comments +** Revision 1.24 2007/07/06 13:18:35EDT rjmcgraw +** DCR469:1 Changed function prototype for GetLastSenderId +** Revision 1.23 2007/05/23 11:22:02EDT dlkobe +** Added doxygen formatting +** Revision 1.22 2007/04/19 15:47:03EDT rjmcgraw +** Moved subscription reporting structs to cfe_sb_msg.h +** Revision 1.20 2007/03/22 12:55:20EST rjmcgraw +** Added comments regarding Qos +** Revision 1.19 2007/01/24 16:49:35EST rjmcgraw +** Added Pipe to SubEntries_t +** Revision 1.18 2007/01/08 14:42:18EST rjmcgraw +** Moved SubscribeLocal prototypes to this file from cfe_sb_priv.h +** Revision 1.17 2007/01/04 14:49:44EST rjmcgraw +** Added SubType to CFE_SB_SubRprtMsg_t +** Revision 1.16 2007/01/02 10:01:35EST rjmcgraw +** Moved structs from priv.h to cfe_sb.h for exposure to apps +** Revision 1.15 2006/12/28 16:27:34EST rjmcgraw +** Added cmd codes for SB subscription processing +** +******************************************************************************/ + +#ifndef _cfe_sb_ +#define _cfe_sb_ + +/* +** Includes +*/ + +#include "common_types.h" +#include "cfe_mission_cfg.h" +#include "ccsds.h" + + +/* +** Macro Definitions +*/ +#define CFE_BIT(x) (1 << (x)) /**< \brief Places a one at bit positions 0 - 31*/ +#define CFE_SET(i,x) ((i) |= CFE_BIT(x)) /**< \brief Sets bit x of i */ +#define CFE_CLR(i,x) ((i) &= ~CFE_BIT(x)) /**< \brief Clears bit x of i */ +#define CFE_TST(i,x) (((i) & CFE_BIT(x)) != 0)/**< \brief TRUE(non zero) if bit x of i is set */ + + +/* +** Type Definitions +*/ + +/**< \brief Generic Software Bus Message Type Definition */ +typedef union { + CCSDS_PriHdr_t Hdr; /**< \brief CCSDS Primary Header #CCSDS_PriHdr_t */ + uint32 Dword; /**< \brief Forces minimum of 32-bit alignment for this object */ + uint8 Byte[sizeof(CCSDS_PriHdr_t)]; /**< \brief Allows byte-level access */ +}CFE_SB_Msg_t; + +/**< \brief Generic Software Bus Command Header Type Definition */ +typedef struct{ + CCSDS_PriHdr_t Pri;/**< \brief CCSDS Primary Header #CCSDS_PriHdr_t */ + CCSDS_CmdSecHdr_t Sec;/**< \brief CCSDS Command Secondary Header #CCSDS_CmdSecHdr_t */ +}CFE_SB_CmdHdr_t; + +/**< \brief Generic Software Bus Telemetry Header Type Definition */ +typedef struct{ + CCSDS_PriHdr_t Pri;/**< \brief CCSDS Primary Header #CCSDS_PriHdr_t */ + CCSDS_TlmSecHdr_t Sec;/**< \brief CCSDS Telemetry Secondary Header #CCSDS_TlmSecHdr_t */ +}CFE_SB_TlmHdr_t; + +#define CFE_SB_CMD_HDR_SIZE (sizeof(CFE_SB_CmdHdr_t))/**< \brief Size of #CFE_SB_CmdHdr_t in bytes */ +#define CFE_SB_TLM_HDR_SIZE (sizeof(CFE_SB_TlmHdr_t))/**< \brief Size of #CFE_SB_TlmHdr_t in bytes */ + + + +/**< \brief CFE_SB_MsgId_t to primitive type definition +** +** Software Bus message identifier used in many SB APIs +*/ +typedef uint16 CFE_SB_MsgId_t; + +/**< \brief CFE_SB_MsgPtr_t defined as a pointer to an SB Message */ +typedef CFE_SB_Msg_t *CFE_SB_MsgPtr_t; + +/**< \brief CFE_SB_MsgPayloadPtr_t defined as an opaque pointer to a message Payload portion */ +typedef uint8 *CFE_SB_MsgPayloadPtr_t; + + +/* +** cFE SB Application Programmer Interface's (API's) +*/ + + +/*****************************************************************************/ +/** +** \brief Initialize a buffer for a software bus message. +** +** \par Description +** This routine fills in the header information needed to create a +** valid software bus message. +** +** \par Assumptions, External Events, and Notes: +** None +** +** \param[in] MsgPtr A pointer to the buffer that will contain the message. +** This will point to the first byte of the message header. +** The \c void* data type allows the calling routine to use +** any data type when declaring its message buffer. +** +** \param[in] MsgId The message ID to put in the message header. +** +** \param[in] Length The total number of bytes of message data, including the SB +** message header . +** +** \param[in] Clear A flag indicating whether to clear the rest of the message: +** \arg TRUE - fill sequence count and packet data with zeroes. +** \arg FALSE - leave sequence count and packet data unchanged. +** +** \sa #CFE_SB_SetMsgId, #CFE_SB_SetUserDataLength, #CFE_SB_SetTotalMsgLength, +** #CFE_SB_SetMsgTime, #CFE_SB_TimeStampMsg, #CFE_SB_SetCmdCode +**/ +void CFE_SB_InitMsg(void *MsgPtr, + CFE_SB_MsgId_t MsgId, + uint16 Length, + boolean Clear ); + +/*****************************************************************************/ +/** +** \brief Get the size of a software bus message header. +** +** \par Description +** This routine returns the number of bytes in a software bus message header. +** This can be used for sizing buffers that need to store SB messages. SB +** message header formats can be different for each deployment of the cFE. +** So, applications should use this function and avoid hard coding their buffer +** sizes. +** +** \par Assumptions, External Events, and Notes: +** - For statically defined messages, a function call will not work. The +** macros #CFE_SB_CMD_HDR_SIZE and #CFE_SB_TLM_HDR_SIZE are available for use +** in static message buffer sizing or structure definitions. +** +** \param[in] MsgId The message ID to calculate header size for. The size of the message +** header may depend on the MsgId in some implementations. For example, +** if SB messages are implemented as CCSDS packets, the size of the header +** is different for command vs. telemetry packets. +** +** \returns +** \retstmt The number of bytes in the software bus message header for +** messages with the given \c MsgId. endstmt +** \endreturns +** +** \sa #CFE_SB_GetUserData, #CFE_SB_GetMsgId, #CFE_SB_GetUserDataLength, #CFE_SB_GetTotalMsgLength, +** #CFE_SB_GetMsgTime, #CFE_SB_GetCmdCode, #CFE_SB_GetChecksum +**/ +uint16 CFE_SB_MsgHdrSize(CFE_SB_MsgId_t MsgId); + +/*****************************************************************************/ +/** +** \brief Get a pointer to the user data portion of a software bus message. +** +** \par Description +** This routine returns a pointer to the user data portion of a software +** bus message. SB message header formats can be different for each +** deployment of the cFE. So, applications should use this function and +** avoid hard coding offsets into their SB message buffers. +** +** \par Assumptions, External Events, and Notes: +** None +** +** \param[in] MsgPtr A pointer to the buffer that contains the software bus message. +** +** \returns +** \retstmt A pointer to the first byte of user data within the software bus message. \endstmt +** \endreturns +** +** \sa #CFE_SB_GetMsgId, #CFE_SB_GetUserDataLength, #CFE_SB_GetTotalMsgLength, +** #CFE_SB_GetMsgTime, #CFE_SB_GetCmdCode, #CFE_SB_GetChecksum, #CFE_SB_MsgHdrSize +**/ +void *CFE_SB_GetUserData(CFE_SB_MsgPtr_t MsgPtr); + +/*****************************************************************************/ +/** +** \brief Get the message ID of a software bus message. +** +** \par Description +** This routine returns the message ID from a software bus message. +** +** \par Assumptions, External Events, and Notes: +** None +** +** \param[in] MsgPtr A pointer to the buffer that contains the software bus message. +** +** \returns +** \retstmt The software bus Message ID from the message header. \endstmt +** \endreturns +** +** \sa #CFE_SB_GetUserData, #CFE_SB_SetMsgId, #CFE_SB_GetUserDataLength, #CFE_SB_GetTotalMsgLength, +** #CFE_SB_GetMsgTime, #CFE_SB_GetCmdCode, #CFE_SB_GetChecksum, #CFE_SB_MsgHdrSize +**/ +CFE_SB_MsgId_t CFE_SB_GetMsgId(CFE_SB_MsgPtr_t MsgPtr); + +/*****************************************************************************/ +/** +** \brief Sets the message ID of a software bus message. +** +** \par Description +** This routine sets the Message ID in a software bus message header. +** +** \par Assumptions, External Events, and Notes: +** None +** +** \param[in] MsgPtr A pointer to the buffer that contains the software bus message. +** This must point to the first byte of the message header. +** +** \param[in] MsgId The message ID to put into the message header. +** +** \returns +** \retstmt The software bus Message ID from the message header. \endstmt +** \endreturns +** +** \sa #CFE_SB_GetMsgId, #CFE_SB_SetUserDataLength, #CFE_SB_SetTotalMsgLength, +** #CFE_SB_SetMsgTime, #CFE_SB_TimeStampMsg, #CFE_SB_SetCmdCode, #CFE_SB_InitMsg +**/ +void CFE_SB_SetMsgId(CFE_SB_MsgPtr_t MsgPtr, + CFE_SB_MsgId_t MsgId); + +/*****************************************************************************/ +/** +** \brief Gets the length of user data in a software bus message. +** +** \par Description +** This routine returns the size of the user data in a software bus message. +** +** \par Assumptions, External Events, and Notes: +** None +** +** \param[in] MsgPtr A pointer to the buffer that contains the software bus message. +** This must point to the first byte of the message header. +** +** \returns +** \retstmt The size (in bytes) of the user data in the software bus message. \endstmt +** \endreturns +** +** \sa #CFE_SB_GetUserData, #CFE_SB_GetMsgId, #CFE_SB_SetUserDataLength, #CFE_SB_GetTotalMsgLength, +** #CFE_SB_GetMsgTime, #CFE_SB_GetCmdCode, #CFE_SB_GetChecksum, #CFE_SB_MsgHdrSize +**/ +uint16 CFE_SB_GetUserDataLength(CFE_SB_MsgPtr_t MsgPtr); + +/*****************************************************************************/ +/** +** \brief Sets the length of user data in a software bus message. +** +** \par Description +** This routine sets the field in the SB message header that determines +** the size of the user data in a software bus message. SB message header +** formats can be different for each deployment of the cFE. So, applications +** should use this function rather than trying to poke a length value directly +** into their SB message buffers. +** +** \par Assumptions, External Events, and Notes: +** - You must set a valid message ID in the SB message header before +** calling this function. +** +** \param[in] MsgPtr A pointer to the buffer that contains the software bus message. +** This must point to the first byte of the message header. +** +** \param[in] DataLength The length to set (size of the user data, in bytes). +** +** +** \sa #CFE_SB_SetMsgId, #CFE_SB_GetUserDataLength, #CFE_SB_SetTotalMsgLength, +** #CFE_SB_SetMsgTime, #CFE_SB_TimeStampMsg, #CFE_SB_SetCmdCode, #CFE_SB_InitMsg +**/ +void CFE_SB_SetUserDataLength(CFE_SB_MsgPtr_t MsgPtr,uint16 DataLength); + +/*****************************************************************************/ +/** +** \brief Gets the total length of a software bus message. +** +** \par Description +** This routine returns the total size of the software bus message. +** +** \par Assumptions, External Events, and Notes: +** - For the CCSDS implementation of this API, the size is derived from +** the message header. +** +** \param[in] MsgPtr A pointer to the buffer that contains the software bus message. +** This must point to the first byte of the message header. +** +** \returns +** \retstmt The total size (in bytes) of the software bus message, including headers. \endstmt +** \endreturns +** +** \sa #CFE_SB_GetUserData, #CFE_SB_GetMsgId, #CFE_SB_GetUserDataLength, #CFE_SB_SetTotalMsgLength, +** #CFE_SB_GetMsgTime, #CFE_SB_GetCmdCode, #CFE_SB_GetChecksum, #CFE_SB_MsgHdrSize +**/ +uint16 CFE_SB_GetTotalMsgLength(CFE_SB_MsgPtr_t MsgPtr); + +/*****************************************************************************/ +/** +** \brief Sets the total length of a software bus message. +** +** \par Description +** This routine sets the field in the SB message header that determines +** the total length of the message. SB message header formats can be +** different for each deployment of the cFE. So, applications should +** use this function rather than trying to poke a length value directly +** into their SB message buffers. +** +** \par Assumptions, External Events, and Notes: +** None +** +** \param[in] MsgPtr A pointer to the buffer that contains the software bus message. +** This must point to the first byte of the message header. +** +** \param[in] TotalLength The length to set (total size of the message, in bytes, +** including headers). +** +** \sa #CFE_SB_SetMsgId, #CFE_SB_SetUserDataLength, #CFE_SB_GetTotalMsgLength, +** #CFE_SB_SetMsgTime, #CFE_SB_TimeStampMsg, #CFE_SB_SetCmdCode, #CFE_SB_InitMsg +**/ +void CFE_SB_SetTotalMsgLength(CFE_SB_MsgPtr_t MsgPtr,uint16 TotalLength); + +/*****************************************************************************/ +/** +** \brief Gets the checksum field from a software bus message. +** +** \par Description +** This routine gets the checksum (or other message integrity check +** value) from a software bus message. The contents and location of +** this field will depend on the underlying implementation of software +** bus messages. It may be a checksum, a CRC, or some other algorithm. +** Users should not call this function as part of a message integrity +** check (call #CFE_SB_ValidateChecksum instead). +** +** \par Assumptions, External Events, and Notes: +** - If the underlying implementation of software bus messages does not +** include a checksum field, then this routine will return a zero. +** +** \param[in] MsgPtr A pointer to the buffer that contains the software bus message. +** This must point to the first byte of the message header. +** +** \returns +** \retstmt The checksum included in the software bus message header (if present), otherwise, +** returns a checksum value of zero. \endstmt +** \endreturns +** +** \sa #CFE_SB_GetUserData, #CFE_SB_GetMsgId, #CFE_SB_GetUserDataLength, #CFE_SB_GetTotalMsgLength, +** #CFE_SB_GetMsgTime, #CFE_SB_GetCmdCode, #CFE_SB_GetChecksum, #CFE_SB_MsgHdrSize, +** #CFE_SB_ValidateChecksum, #CFE_SB_GenerateChecksum +**/ +uint16 CFE_SB_GetChecksum(CFE_SB_MsgPtr_t MsgPtr); + +/*****************************************************************************/ +/** +** \brief Calculates and sets the checksum of a software bus message +** +** \par Description +** This routine calculates the checksum of a software bus message according +** to an implementation-defined algorithm. Then, it sets the checksum field +** in the message with the calculated value. The contents and location of +** this field will depend on the underlying implementation of software bus +** messages. It may be a checksum, a CRC, or some other algorithm. +** +** \par Assumptions, External Events, and Notes: +** - If the underlying implementation of software bus messages does not +** include a checksum field, then this routine will do nothing. +** +** \param[in] MsgPtr A pointer to the buffer that contains the software bus message. +** This must point to the first byte of the message header. +** +** \sa #CFE_SB_ValidateChecksum, #CFE_SB_GetChecksum +**/ +void CFE_SB_GenerateChecksum(CFE_SB_MsgPtr_t MsgPtr); + +/*****************************************************************************/ +/** +** \brief Validates the checksum of a software bus message. +** +** \par Description +** This routine calculates the expected checksum of a software bus message +** according to an implementation-defined algorithm. Then, it checks the +** calculated value against the value in the message's checksum. If the +** checksums do not match, this routine will generate an event message +** reporting the error. +** +** \par Assumptions, External Events, and Notes: +** - If the underlying implementation of software bus messages does not +** include a checksum field, then this routine will always return \c TRUE. +** +** \param[in] MsgPtr A pointer to the buffer that contains the software bus message. +** This must point to the first byte of the message header. +** +** \returns +** \retcode TRUE \retdesc The checksum field in the packet is valid. \endcode +** \retcode FALSE \retdesc The checksum field in the packet is not valid or the message type is wrong. \endcode +** \endreturns +** +** \sa #CFE_SB_GenerateChecksum, #CFE_SB_GetChecksum +**/ +boolean CFE_SB_ValidateChecksum(CFE_SB_MsgPtr_t MsgPtr); + + +#endif /* _cfesb_ */ +/*****************************************************************************/ diff --git a/include/common_types.h b/include/common_types.h new file mode 100644 index 0000000..e915f00 --- /dev/null +++ b/include/common_types.h @@ -0,0 +1,374 @@ +/*--------------------------------------------------------------------------- +** +** Filename: +** $Id: common_types.h 1.9 2014/01/14 16:28:32GMT-05:00 acudmore Exp $ +** +** Copyright (c) 2004-2006, United States government as represented by the +** administrator of the National Aeronautics Space Administration. +** All rights reserved. This software was created at NASAs Goddard +** Space Flight Center pursuant to government contracts. +** +** This is governed by the NASA Open Source Agreement and may be used, +** distributed and modified only pursuant to the terms of that agreement. +** +** Purpose: +** Unit specification for common types. +** +** Design Notes: +** Assumes make file has defined processor family +** +** References: +** Flight Software Branch C Coding Standard Version 1.0a +** +** +** Notes: +** +** +** $Date: 2014/01/14 16:28:32GMT-05:00 $ +** $Revision: 1.9 $ +** $Log: common_types.h $ +** Revision 1.9 2014/01/14 16:28:32GMT-05:00 acudmore +** Fixed typo in macro for x86-64 +** Revision 1.8 2013/08/09 13:58:04GMT-05:00 acudmore +** Added int64 type, added support for ARM arch, added 64 bit x86 arch, added arch check for GCC arch macros, added check for proper data type sizes +** Revision 1.7 2013/07/25 10:01:29GMT-05:00 acudmore +** Added C++ support +** Revision 1.6 2012/04/11 09:19:03GMT-05:00 acudmore +** added OS_USED attribute +** Revision 1.5 2010/02/18 16:43:29EST acudmore +** Added SPARC processor section +** Removed special characters from comments that cause problems with some tools. +** Revision 1.4 2010/02/18 16:41:39EST acudmore +** Added a block of defines for GCC specific pragmas and extensions. +** Removed RTEMS boolean related ifdefs +** moved OS_PACK into the GCC specific block +** Revision 1.3 2010/02/01 12:31:17EST acudmore +** Added uint64 type +** Revision 1.2 2009/07/07 16:30:05EDT acudmore +** Removed conditinal comp. around boolean for m68k. +** This will need to be done for all RTEMS targets +** Revision 1.1 2009/06/02 10:04:58EDT acudmore +** Initial revision +** Member added to project c:/MKSDATA/MKS-REPOSITORY/MKS-OSAL-REPOSITORY/src/os/inc/project.pj +** Revision 1.1 2008/04/20 22:35:58EDT ruperera +** Initial revision +** Member added to project c:/MKSDATA/MKS-REPOSITORY/MKS-OSAL-REPOSITORY/src/inc/project.pj +** Revision 1.1 2007/10/16 16:14:49EDT apcudmore +** Initial revision +** Member added to project d:/mksdata/MKS-OSAL-REPOSITORY/src/inc/project.pj +** Revision 1.2 2006/06/08 14:28:32EDT David Kobe (dlkobe) +** Added NASA Open Source Legal Statement +** Revision 1.1 2005/06/09 09:57:51GMT-05:00 rperera +** Initial revision +** Member added to project d:/mksdata/MKS-CFE-REPOSITORY/cfe-core/inc/project.pj +** Revision 1.6 2005/03/24 19:20:52 rmcgraw +** Wrapped the boolean defintion for all three processors with #ifndef _USING_RTEMS_INCLUDES_ +** +** Revision 1.5 2005/03/10 16:59:08 acudmore +** removed boolean prefix to TRUE and FALSE defintion to avoid vxWorks conflict. +** +** Revision 1.4 2005/03/07 20:23:34 acudmore +** removed duplicate boolean definition +** +** Revision 1.3 2005/03/07 20:05:17 acudmore +** updated with __PPC__ macro that gnu compiler uses +** +** Revision 1.2 2005/03/04 16:02:44 acudmore +** added coldfire architecture +** +** Revision 1.1 2005/03/04 15:58:45 acudmore +** Added common_types.h +** +** +** +**-------------------------------------------------------------------------*/ + +#ifndef _common_types_ +#define _common_types_ + +#ifdef __cplusplus + extern "C" { +#endif + +/* +** Includes +*/ + +/* +** Macro Definitions +*/ + +/* +** Condition = TRUE is ok, Condition = FALSE is error +*/ +#define CompileTimeAssert(Condition, Message) typedef char Message[(Condition) ? 1 : -1] + + +/* +** Define compiler specific macros +** The __extension__ compiler pragma is required +** for the uint64 type using GCC with the ANSI C90 standard. +** Other macros can go in here as needed, for example alignment +** pragmas. +** +** NOTE: The white-box (coverage) unit testing may need to disable +** these extra attributes. These test builds define the OSAPI_NO_SPECIAL_ATTRIBS +** macro to disable this. +*/ +#if defined (__GNUC__) && !defined(OSAPI_NO_SPECIAL_ATTRIBS) + #define _EXTENSION_ __extension__ + #define OS_PACK __attribute__ ((packed)) + #define OS_ALIGN(n) __attribute__((aligned(n))) + #define OS_USED __attribute__((used)) + #define OS_PRINTF(n,m) __attribute__ ((format (printf, n, m))) +#else + #define _EXTENSION_ + #define OS_PACK + #define OS_ALIGN(n) + #define OS_USED + #define OS_PRINTF(n,m) +#endif + +/* + * If the host system has a ISO C99 standard stdint header file, prefer it. + * This ensures that fixed-width types are correct including on 64-bit systems. + */ +#if defined(_HAVE_STDINT_) + +#include +#include +/* + * NOTE - NOT DEFINING STRUCT_LOW_BIT_FIRST or STRUCT_HIGH_BIT_FIRST + * We should not make assumptions about the bit order here + */ + + typedef uint8_t osalbool; + typedef int8_t int8; + typedef int16_t int16; + typedef int32_t int32; + typedef int64_t int64; + typedef uint8_t uint8; + typedef uint16_t uint16; + typedef uint32_t uint32; + typedef uint64_t uint64; + typedef intptr_t intptr; + typedef uintptr_t cpuaddr; + typedef size_t cpusize; + typedef ptrdiff_t cpudiff; + +/* + * Fall back to default integer type maps - + * These definitions assume a 32-bit processor + */ +#elif defined(_ix86_) || defined (__i386__) +/* ----------------------- Intel x86 processor family -------------------------*/ + /* Little endian */ + #undef _STRUCT_HIGH_BIT_FIRST_ + #define _STRUCT_LOW_BIT_FIRST_ + + typedef unsigned char osalbool; + typedef signed char int8; + typedef short int int16; + typedef long int int32; + _EXTENSION_ typedef long long int int64; + typedef unsigned char uint8; + typedef unsigned short int uint16; + typedef unsigned long int uint32; + _EXTENSION_ typedef unsigned long long int uint64; + + typedef unsigned long int cpuaddr; + typedef unsigned long int cpusize; + typedef long int cpudiff; + +#elif defined (_ix64_) || defined (__x86_64__) +/* ----------------------- Intel/AMD x64 processor family -------------------------*/ + /* Little endian */ + #undef _STRUCT_HIGH_BIT_FIRST_ + #define _STRUCT_LOW_BIT_FIRST_ + + typedef unsigned char osalbool; + typedef signed char int8; + typedef short int int16; + typedef int int32; + typedef long int int64; + typedef unsigned char uint8; + typedef unsigned short int uint16; + typedef unsigned int uint32; + typedef unsigned long int uint64; + + typedef unsigned long int cpuaddr; + typedef unsigned long int cpusize; + typedef long int cpudiff; + +#elif defined(__PPC__) || defined (__ppc__) + /* ----------------------- Motorola Power PC family ---------------------------*/ + /* The PPC can be programmed to be big or little endian, we assume native */ + /* Big endian */ + #define _STRUCT_HIGH_BIT_FIRST_ + #undef _STRUCT_LOW_BIT_FIRST_ + + typedef unsigned char osalbool; + typedef signed char int8; + typedef short int int16; + typedef long int int32; + _EXTENSION_ typedef long long int int64; + typedef unsigned char uint8; + typedef unsigned short int uint16; + typedef unsigned long int uint32; + _EXTENSION_ typedef unsigned long long int uint64; + + typedef unsigned long int cpuaddr; + typedef unsigned long int cpusize; + typedef long int cpudiff; + +#elif defined(_m68k_) || defined(__m68k__) + /* ----------------------- Motorola m68k/Coldfire family ---------------------------*/ + /* Big endian */ + #define _STRUCT_HIGH_BIT_FIRST_ + #undef _STRUCT_LOW_BIT_FIRST_ + + typedef unsigned char osalbool; + typedef signed char int8; + typedef short int int16; + typedef long int int32; + _EXTENSION_ typedef long long int int64; + typedef unsigned char uint8; + typedef unsigned short int uint16; + typedef unsigned long int uint32; + _EXTENSION_ typedef unsigned long long int uint64; + + typedef unsigned long int cpuaddr; + typedef unsigned long int cpusize; + typedef long int cpudiff; + +#elif defined (__ARM__) || defined(__arm__) +/* ----------------------- ARM processor family -------------------------*/ + /* Little endian */ + #undef _STRUCT_HIGH_BIT_FIRST_ + #define _STRUCT_LOW_BIT_FIRST_ + + typedef unsigned char osalbool; + typedef signed char int8; + typedef short int int16; + typedef long int int32; + _EXTENSION_ typedef long long int int64; + typedef unsigned char uint8; + typedef unsigned short int uint16; + typedef unsigned long int uint32; + _EXTENSION_ typedef unsigned long long int uint64; + + typedef unsigned long int cpuaddr; + typedef unsigned long int cpusize; + typedef long int cpudiff; + +#elif defined(__SPARC__) || defined (_sparc_) + /* ----------------------- SPARC/LEON family ---------------------------*/ + /* SPARC Big endian */ + #define _STRUCT_HIGH_BIT_FIRST_ + #undef _STRUCT_LOW_BIT_FIRST_ + + typedef unsigned char osalbool; + typedef signed char int8; + typedef short int int16; + typedef long int int32; + _EXTENSION_ typedef long long int int64; + typedef unsigned char uint8; + typedef unsigned short int uint16; + typedef unsigned long int uint32; + _EXTENSION_ typedef unsigned long long int uint64; + + typedef unsigned long int cpuaddr; + typedef unsigned long int cpusize; + typedef long int cpudiff; + +#else /* not any of the above */ + #error undefined processor +#endif /* processor types */ + +/* + * Boolean type for compatibility -- + * + * Note it is a bad idea to typedef "bool" or "boolean" -- MANY other projects + * and libraries also define a boolean type due to the lack of a standard bool in C89. + * But calling it simply "bool" or "boolean" almost guarantees a namespace conflict + * if trying to use OSAL with one of those other existing projects. + * + * RTEMS 4.11 no longer defines boolean type by default (deprecated) probably also + * due to the high likelihood of name conflicts. + * + * In order to preserve compatibility for apps written against prior versions of + * OSAL, the name "boolean" is typedefed as well, but this may be turned off + * in a future version whenever appropriate. + */ + +#if (!defined(_USING_RTEMS_INCLUDES_) || !defined(RTEMS_DEPRECATED_TYPES)) + typedef osalbool boolean; +#endif + + +#ifndef NULL /* pointer to nothing */ + #define NULL ((void *) 0) +#endif + +#ifndef TRUE /* Boolean true */ + #define TRUE (1) +#endif + +#ifndef FALSE /* Boolean false */ + #define FALSE (0) +#endif + +/* +** Check Sizes +*/ +CompileTimeAssert(sizeof(uint8)==1, TypeUint8WrongSize); +CompileTimeAssert(sizeof(uint16)==2, TypeUint16WrongSize); +CompileTimeAssert(sizeof(uint32)==4, TypeUint32WrongSize); +CompileTimeAssert(sizeof(uint64)==8, TypeUint64WrongSize); +CompileTimeAssert(sizeof(int8)==1, Typeint8WrongSize); +CompileTimeAssert(sizeof(int16)==2, Typeint16WrongSize); +CompileTimeAssert(sizeof(int32)==4, Typeint32WrongSize); +CompileTimeAssert(sizeof(int64)==8, Typeint64WrongSize); +CompileTimeAssert(sizeof(cpuaddr) >= sizeof(void *), TypePtrWrongSize); + +/* + * TEMPORARY COMPATIBILITY MACRO + * + * Any code that depends on this macro should be fixed so as to not need it. + * The value for this had been set by the BSP makefiles but this is not reliable, + * especially on processors that support both big- and little- endian modes e.g. + * ARM and MIPS. + * + * This is deprecated and only here to bridge the gap until code that depends + * on this can be fixed. Do not write any new code that uses this macro. + * + * If using an older makefile that defines one of the BIT_ORDER macros already, + * then this entire section is skipped and the macro is used as-is. + */ +#if !defined(SOFTWARE_BIG_BIT_ORDER) && !defined(SOFTWARE_LITTLE_BIT_ORDER) + +#if defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN || \ + defined(__BIG_ENDIAN__) || \ + defined(__ARMEB__) || \ + defined(__THUMBEB__) || \ + defined(__AARCH64EB__) || \ + defined(_MIBSEB) || defined(__MIBSEB) || defined(__MIBSEB__) +/* It is a big-endian target architecture */ +#define SOFTWARE_BIG_BIT_ORDER +#elif defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN || \ + defined(__LITTLE_ENDIAN__) || \ + defined(__ARMEL__) || \ + defined(__THUMBEL__) || \ + defined(__AARCH64EL__) || \ + defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__) +/* It is a little-endian target architecture */ +#define SOFTWARE_LITTLE_BIT_ORDER +#endif + +#endif /* !defined(SOFTWARE_BIG_BIT_ORDER) && !defined(SOFTWARE_LITTLE_BIT_ORDER) */ + +#ifdef __cplusplus + } +#endif + +#endif /* _common_types_ */ diff --git a/include/config.h b/include/config.h new file mode 100644 index 0000000..3ac7f35 --- /dev/null +++ b/include/config.h @@ -0,0 +1,100 @@ +/**************************************************************************** +* +* Copyright (c) 2017 Windhover Labs, L.L.C. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* 3. Neither the name Windhover Labs nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ +#ifndef CONFIG_H +#define CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* Start for explain. */ +/** \brief Maximum buffer size to store the json input string. */ +#define EXPLAIN_MAX_BUFFER_SIZE (10000) +/** \brief Maximum length of the input file path. */ +#define EXPLAIN_MAX_PATH_LENGTH PATH_MAX +/* Not yet used. */ +/** \brief The endianness of the source. */ +#define EXPLAIN_SRC_ENDIANNESS (0) +/* End for explain. */ + +/* Start for message. */ +/** \brief Maximum length of an ops name. */ +#define EXPLAIN_MAX_OPS_NAME_LENGTH (256) +/** \brief Maximum length of a symbol name. */ +#define EXPLAIN_MAX_SYMBOL_LENGTH (256) +/* End for messages. */ + +/* Start for parser. */ +/* keys used in input json. */ +/** \brief Key name for message id. */ +#define EXPLAIN_IDENTIFICATION_KEY "id" +/** \brief Key name for the destination symbol. */ +#define EXPLAIN_DESTINATION_SYMBOL "dst_symbol" +/** \brief Key name for the source symbol. */ +#define EXPLAIN_SOURCE_SYMBOL "src_symbol" +/** \brief Key name for message ops name. */ +#define EXPLAIN_OPS_MESSAGE_NAME_KEY "ops_name" +/** \brief Key name for message op name. */ +#define EXPLAIN_OPS_FIELD_NAME_KEY "op_name" +/** \brief Key name for source endianness. */ +#define EXPLAIN_SOURCE_ENDIANNESS_KEY "src_endian" +/** \brief Key name for destination endianness. */ +#define EXPLAIN_DEST_ENDIANNESS_KEY "dst_endian" +/** \brief Key name for length. */ +#define EXPLAIN_LENGTH_KEY "length" +/** \brief Key name for source offset. */ +#define EXPLAIN_SOURCE_OFFSET_KEY "src_offset" +/** \brief Key name for destination offset. */ +#define EXPLAIN_DESTINATION_OFFSET_KEY "dst_offset" +/* Value definitions. */ +/** \brief Max length of endianness key. */ +#define EXPLAIN_MAX_ENDIANNESS_LENGTH (1) +/** \brief Little endian value. */ +#define EXPLAIN_LITTLE_ENDIAN_VALUE "L" +/** \brief Big endian value. */ +#define EXPLAIN_BIG_ENDIAN_VALUE "B" +/** \brief Max key length. */ +#define EXPLAIN_MAX_KEY_LENGTH (24) +/* Max recursive calls for the parser. */ +/** \brief Max recursive call count for json parser. */ +#define EXPLAIN_MAX_RECURSIVE_CALL_COUNT (100) +/* End for parser. */ + + +#ifdef __cplusplus +} +#endif + +#endif /* CONFIG_H */ diff --git a/include/explain.h b/include/explain.h new file mode 100644 index 0000000..d520559 --- /dev/null +++ b/include/explain.h @@ -0,0 +1,162 @@ +/**************************************************************************** +* +* Copyright (c) 2017 Windhover Labs, L.L.C. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* 3. Neither the name Windhover Labs nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ +#ifndef EXPLAIN_H +#define EXPLAIN_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "message.h" +#include "config.h" +#include + + +/** +** \brief Application data. +*/ +typedef struct +{ + /** \brief Path to the input json file. */ + char inputPath[EXPLAIN_MAX_PATH_LENGTH]; + /** \brief The raw json string from the input file. */ + char rawInput[EXPLAIN_MAX_BUFFER_SIZE]; + /** \brief The current message being parsed. */ + explain_msg_t *currentMsg; + /** \brief The current field being parsed. */ + explain_field_t currentField; + /** \brief The message linked list. */ + explain_msg_list_t message_list; +} explain_data_t; + + +/** +** \brief Bitwise copy direction enumeration. +*/ +typedef enum +{ + /** \brief Copy from source to destination. */ + EXPLAIN_FORWARD = 0, + /** \brief Copy from destination to source. */ + EXPLAIN_REVERSE = 1 +} explain_direction_t; + + +/************************************************************************/ +/** \brief Initialize explain library data. +** +** \par Description +** This function clears the data structure, initializes the +** linked list, and allocates the first message. +** +** \par Assumptions, External Events, and Notes: +** This function must be called first. +** +** \param [in/out] app_data The pointer to the app_data to init. +** +** \returns true for success, false for failure. +** +*************************************************************************/ +bool explain_init_data(explain_data_t *app_data); + +/************************************************************************/ +/** \brief Uninitialize explain library data. +** +** \par Description +** This deallocates any allocated memory. +** +** \par Assumptions, External Events, and Notes: +** None. +** +** \param [in/out] app_data The pointer to explain library data. +** +*************************************************************************/ +void explain_uninit_data(explain_data_t *app_data); + +/************************************************************************/ +/** \brief Load the memory map from json. +** +** \par Description +** This function parses a memory map stored in a json file and +** stores in a linked list pointed to by the explain handle. +** +** \par Assumptions, External Events, and Notes: +** init_data must be called first to initialize explain data. +** +** \param [in] filepath Path to the json input file. +** +** \param [in\out] handle The handle to explain data. +** +** \returns true for success, false for failure. +** +*************************************************************************/ +bool explain_load_memory_map(const char *filepath, explain_data_t *handle); + + +/************************************************************************/ +/** \brief Translate a buffer between source and destination ABI. +** +** \par Description +** This function translates the application binary interface of +** a source to a destination. The memory copy will not exceed +** max length. If a field exceeds max length the field will not +** be copied. The destination buffer will be memset before the +** translation starts. +** +** \par Assumptions, External Events, and Notes: +** The returned size written may be shorter than sizeof the +** structure due to padding at the end of the structure. +** +** +** \param [in\out] dst The destination buffer. +** +** \param [in] src The source buffer. +** +** \param [in] definition The handle to the message +** definition. +** \param [in] max_len The max byte length to copy. +** +** \param [in] direction The direction of translation. +** +** \returns size written in bytes for success -1 for failure and sets +** an appropriete error number. +** +*************************************************************************/ +int explain_translate_buffer(char *dst, const char *src, const explain_msg_t *definition, unsigned int max_len, explain_direction_t direction); + + +#ifdef __cplusplus +} +#endif + +#endif /* EXPLAIN_H */ diff --git a/include/list.h b/include/list.h new file mode 100644 index 0000000..f909fa2 --- /dev/null +++ b/include/list.h @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2004, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + * Author: Adam Dunkels + * + */ + +/** + * \file + * Linked list manipulation routines. + * \author Adam Dunkels + * + */ + +/** \addtogroup lib + @{ */ +/** + * \defgroup list Linked list library + * + * The linked list library provides a set of functions for + * manipulating linked lists. + * + * A linked list is made up of elements where the first element \b + * must be a pointer. This pointer is used by the linked list library + * to form lists of the elements. + * + * Lists are declared with the LIST() macro. The declaration specifies + * the name of the list that later is used with all list functions. + * + * Lists can be manipulated by inserting or removing elements from + * either sides of the list (list_push(), list_add(), list_pop(), + * list_chop()). A specified element can also be removed from inside a + * list with list_remove(). The head and tail of a list can be + * extracted using list_head() and list_tail(), respectively. + * + * @{ + */ + +#ifndef LIST_H_ +#define LIST_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define LIST_CONCAT2(s1, s2) s1##s2 +#define LIST_CONCAT(s1, s2) LIST_CONCAT2(s1, s2) + +/** + * Declare a linked list. + * + * This macro declares a linked list with the specified \c type. The + * type \b must be a structure (\c struct) with its first element + * being a pointer. This pointer is used by the linked list library to + * form the linked lists. + * + * The list variable is declared as static to make it easy to use in a + * single C module without unnecessarily exporting the name to other + * modules. + * + * \param name The name of the list. + */ +#define LIST(name) \ + static void *LIST_CONCAT(name,_list) = NULL; \ + static list_t name = (list_t)&LIST_CONCAT(name,_list) + +/** + * Declare a linked list inside a structure declaraction. + * + * This macro declares a linked list with the specified \c type. The + * type \b must be a structure (\c struct) with its first element + * being a pointer. This pointer is used by the linked list library to + * form the linked lists. + * + * Internally, the list is defined as two items: the list itself and a + * pointer to the list. The pointer has the name of the parameter to + * the macro and the name of the list is a concatenation of the name + * and the suffix "_list". The pointer must point to the list for the + * list to work. Thus the list must be initialized before using. + * + * The list is initialized with the LIST_STRUCT_INIT() macro. + * + * \param name The name of the list. + */ +#define LIST_STRUCT(name) \ + void *LIST_CONCAT(name,_list); \ + list_t name + +/** + * Initialize a linked list that is part of a structure. + * + * This macro sets up the internal pointers in a list that has been + * defined as part of a struct. This macro must be called before using + * the list. + * + * \param struct_ptr A pointer to the struct + * \param name The name of the list. + */ +#define LIST_STRUCT_INIT(struct_ptr, name) \ + do { \ + (struct_ptr)->name = &((struct_ptr)->LIST_CONCAT(name,_list)); \ + (struct_ptr)->LIST_CONCAT(name,_list) = NULL; \ + list_init((struct_ptr)->name); \ + } while(0) + +/** + * The linked list type. + * + */ +typedef void ** list_t; + +void list_init(list_t list); +void * list_head(list_t list); +void * list_tail(list_t list); +void * list_pop (list_t list); +void list_push(list_t list, void *item); + +void * list_chop(list_t list); + +void list_add(list_t list, void *item); +void list_remove(list_t list, void *item); + +int list_length(list_t list); + +void list_copy(list_t dest, list_t src); + +void list_insert(list_t list, void *previtem, void *newitem); + +void * list_item_next(void *item); + +#ifdef __cplusplus +} +#endif + +#endif /* LIST_H_ */ + +/** @} */ +/** @} */ diff --git a/include/memtools.h b/include/memtools.h new file mode 100644 index 0000000..1cfeaed --- /dev/null +++ b/include/memtools.h @@ -0,0 +1,68 @@ +/**************************************************************************** +* +* Copyright (c) 2017 Windhover Labs, L.L.C. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* 3. Neither the name Windhover Labs nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ +#ifndef MEMTOOLS_H +#define MEMTOOLS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************/ +/** \brief An extended memcpy with support for bits. +** +** \par Description +** This function performs a bitwise memcpy. +** +** \par Assumptions, External Events, and Notes: +** The total destination buffer must be cleared before repeated +** calls to this function to copy fields are made. +** +** \param [in/out] dst_buf The destination buffer. +** +** \param [in] dst_off The destination offset. +** +** \param [in] src_buf The source buffer. +** +** \param [in] src_off The source offset. +** +** \param [in] bit_len The bit length to copy. +** +*************************************************************************/ +void memcpy_bitwise(char *dst_buf, unsigned int dst_off, const char *src_buf, unsigned int src_off, unsigned int bit_len); + + +#ifdef __cplusplus +} +#endif + +#endif /* MEMTOOLS_H */ diff --git a/include/message.h b/include/message.h new file mode 100644 index 0000000..97cc2c9 --- /dev/null +++ b/include/message.h @@ -0,0 +1,285 @@ +/**************************************************************************** +* +* Copyright (c) 2017 Windhover Labs, L.L.C. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* 3. Neither the name Windhover Labs nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ +#ifndef MESSAGE_H +#define MESSAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "list.h" +#include "config.h" + + +/** +** \brief enum for Endianness. +*/ +typedef enum +{ + /** \brief Little Endian. */ + EXPLAIN_LITTLE_ENDIAN = 0, + /** \brief Big Endian. */ + EXPLAIN_BIG_ENDIAN = 1 +} explain_endianess_t; + + +/** +** \brief A source / destination description of a field. +*/ +typedef struct explain_field +{ + /** \brief Pointer to next field. Must be first. */ + struct explain_field *next; + /** \brief opsname alias for the field. */ + char opName[EXPLAIN_MAX_OPS_NAME_LENGTH]; + /** \brief Length of the field. */ + unsigned int length; + /** \brief Source offset. */ + unsigned int srcOffset; + /** \brief Destination offset. */ + unsigned int dstOffset; +} explain_field_t; + + +/** +** \brief A source / destination description of a field. +*/ +typedef struct explain_msg +{ + /** \brief Pointer to next message. Must be first. */ + struct explain_msg *next; + /** \brief Identifier. */ + unsigned int id; + /** \brief Opsname alias for the identifier. */ + char opsName[EXPLAIN_MAX_OPS_NAME_LENGTH]; + /** \brief Destination symbol. */ + char dstSymbol[EXPLAIN_MAX_SYMBOL_LENGTH]; + /** \brief Source symbol. */ + char srcSymbol[EXPLAIN_MAX_SYMBOL_LENGTH]; + /** \brief Source endianness. */ + explain_endianess_t srcEndian; + /** \brief Destination endianness. */ + explain_endianess_t dstEndian; + /** \brief Linked list. */ + LIST_STRUCT(fields); +} explain_msg_t; + + +/** +** \brief A message linked list. +*/ +typedef struct explain_msg_list +{ + /** \brief Linked list. */ + LIST_STRUCT(messages); +} explain_msg_list_t; + + +/************************************************************************/ +/** \brief Perform any required initialization. +** +** \par Description +** This function initializes the outer message linked list. +** +** \par Assumptions, External Events, and Notes: +** This function must be called before any other API calls. +** +** \param [in] handle the handle to the message list. +** +*************************************************************************/ +void explain_message_init(explain_msg_list_t *handle); + + +/************************************************************************/ +/** \brief Perform any required cleanup. +** +** \par Description +** This cleans up all allocated memory. +** +** \par Assumptions, External Events, and Notes: +** This function must be called before application exit. +** +** \param [in] handle the handle to the message list. +** +*************************************************************************/ +void explain_message_deinit(explain_msg_list_t *handle); + + +/************************************************************************/ +/** \brief Add a new message to the linked list. +** +** \par Description +** This function allocates, initializes, and adds a message to +** the messages linked list. +** +** \par Assumptions, External Events, and Notes: +** message_init must be called before a message can be added. +** +** \returns msg_t the pointer to the new message on success, NULL on +** failure. +** +** \param [in] handle the handle to the message list. +** +*************************************************************************/ +explain_msg_t *explain_message_add(explain_msg_list_t *handle); + + +/************************************************************************/ +/** \brief Add a new field to a message. +** +** \par Description +** This function allocates a new field, copies the contents of +** addition to the new field, and adds the field to the message +** fields linked list. +** +** \par Assumptions, External Events, and Notes: +** message_add must be called before a field can be added. +** +** \param [in/out] msg_ptr The pointer to the message. +** +** \param [in] addition The pointer to the field to copy. +** +** \returns field_t the pointer to the new field on success, NULL on +** failure. +** +*************************************************************************/ +explain_field_t * explain_field_add(explain_msg_t *msg_ptr, const explain_field_t *addition); + + +/************************************************************************/ +/** \brief Find a message via its id. +** +** \par Description +** This function searches the messages linked list for the id and +** returns a pointer to message if found. +** +** \par Assumptions, External Events, and Notes: +** None. +** +** \param [in] id The message id. +** +** \param [in] handle The handle to the message list. +** +** \returns msg_t the pointer to the message on success, NULL on +** failure. +** +*************************************************************************/ +explain_msg_t * explain_message_find_via_id(unsigned int id, explain_msg_list_t *handle); + + +/************************************************************************/ +/** \brief Find a message via its ops name. +** +** \par Description +** This function searches the messages linked list for the ops +** name and returns a pointer to message if found. +** +** \par Assumptions, External Events, and Notes: +** None. +** +** \param [in] ops_name a pointer to the ops name. +** +** \param [in] handle The handle to the message list. +** +** \returns msg_t the pointer to the message on success, NULL on +** failure. +** +*************************************************************************/ +explain_msg_t * explain_message_find_via_name(const char *ops_name, explain_msg_list_t *handle); + + +/************************************************************************/ +/** \brief Find a message via its source symbol name. +** +** \par Description +** This function searches the messages linked list for the source +** symbol name and returns a pointer to message if found. +** +** \par Assumptions, External Events, and Notes: +** None. +** +** \param [in] src_symbol a pointer to the source symbol. +** +** \param [in] handle The handle to the message list. +** +** \returns msg_t the pointer to the message on success, NULL on +** failure. +** +*************************************************************************/ +explain_msg_t * explain_message_find_via_src_symbol(const char *src_symbol, explain_msg_list_t *handle); + + +/************************************************************************/ +/** \brief Find a message via its destination symbol name. +** +** \par Description +** This function searches the messages linked list for the +** destination symbol name and returns a pointer to message if +** found. +** +** \par Assumptions, External Events, and Notes: +** None. +** +** \param [in] dst_symbol a pointer to the destination symbol. +** +** \param [in] handle The handle to the message list. +** +** \returns msg_t the pointer to the message on success, NULL on +** failure. +** +*************************************************************************/ +explain_msg_t * explain_message_find_via_dst_symbol(const char *dst_symbol, explain_msg_list_t *handle); + + +/************************************************************************/ +/** \brief Print all messages and fields. +** +** \par Description +** This iterates through the linked list and prints all messages +** and all fields. +** +** \par Assumptions, External Events, and Notes: +** None. +** +** \param [in] handle The handle to the message list. +** +** +*************************************************************************/ +void explain_print_all_fields(explain_msg_list_t *handle); + + +#ifdef __cplusplus +} +#endif + +#endif /* MESSAGE_H */ diff --git a/include/parser.h b/include/parser.h new file mode 100644 index 0000000..0ec2af9 --- /dev/null +++ b/include/parser.h @@ -0,0 +1,198 @@ +/**************************************************************************** +* +* Copyright (c) 2017 Windhover Labs, L.L.C. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* 3. Neither the name Windhover Labs nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ +#ifndef PARSER_H +#define PARSER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "explain.h" +#include "config.h" +#include +#include + +/* keys used in input json. */ +/** \brief Key name for message id. */ +#define IDENTIFICATION_KEY EXPLAIN_IDENTIFICATION_KEY +/** \brief Key name for the destination symbol. */ +#define DESTINATION_SYMBOL EXPLAIN_DESTINATION_SYMBOL +/** \brief Key name for the source symbol. */ +#define SOURCE_SYMBOL EXPLAIN_SOURCE_SYMBOL +/** \brief Key name for message ops name. */ +#define OPS_MESSAGE_NAME_KEY EXPLAIN_OPS_MESSAGE_NAME_KEY +/** \brief Key name for message op name. */ +#define OPS_FIELD_NAME_KEY EXPLAIN_OPS_FIELD_NAME_KEY +/** \brief Key name for source endianness. */ +#define SOURCE_ENDIANNESS_KEY EXPLAIN_SOURCE_ENDIANNESS_KEY +/** \brief Key name for destination endianness. */ +#define DEST_ENDIANNESS_KEY EXPLAIN_DEST_ENDIANNESS_KEY +/** \brief Key name for length. */ +#define LENGTH_KEY EXPLAIN_LENGTH_KEY +/** \brief Key name for source offset. */ +#define SOURCE_OFFSET_KEY EXPLAIN_SOURCE_OFFSET_KEY +/** \brief Key name for destination offset. */ +#define DESTINATION_OFFSET_KEY EXPLAIN_DESTINATION_OFFSET_KEY +/* Value definitions. */ +/** \brief Max length of endianness key. */ +#define MAX_ENDIANNESS_LENGTH EXPLAIN_MAX_ENDIANNESS_LENGTH +/** \brief Little endian value. */ +#define LITTLE_ENDIAN_VALUE EXPLAIN_LITTLE_ENDIAN_VALUE +/** \brief Big endian value. */ +#define BIG_ENDIAN_VALUE EXPLAIN_BIG_ENDIAN_VALUE +/** \brief Max key length. */ +#define MAX_KEY_LENGTH EXPLAIN_MAX_KEY_LENGTH +/* Max recursive calls for the parser. */ +/** \brief Max recursive call count for json parser. */ +#define MAX_RECURSIVE_CALL_COUNT EXPLAIN_MAX_RECURSIVE_CALL_COUNT + + +/************************************************************************/ +/** \brief Parses a json object and loads the linked list of the +** explain data handle. +** +** \par Description +** This function parses the json object and loads the messages +** linked list pointed to by the explain data handle. +** +** \par Assumptions, External Events, and Notes: +** None. +** +** \param [in] jobj The json object. +** +** \param [in\out] call_count The call_count to limit recursion. +** +** \param [in\out] handle The handle to the explain data structure. +** +** \returns true for success, false for failure. +** +*************************************************************************/ +bool json_parse(json_object * jobj, unsigned int *call_count, explain_data_t *handle); + + +/************************************************************************/ +/** \brief Parses a value in a json key value pair. +** +** \par Description +** This function parses a value in a key value pair and calls the +** appropriate function to continue parsing depending on the type. +** +** \par Assumptions, External Events, and Notes: +** None. +** +** \param [in] jobj The json object. +** +** \param [in] key The current key. +** +** \param [in\out] handle The handle to the explain data structure. +** +** \returns true for success, false for failure. +** +*************************************************************************/ +bool parse_json_value(json_object *jobj, const char* key, explain_data_t *handle); + + +/************************************************************************/ +/** \brief Parses a json array object and loads the linked list of the +** explain data handle. +** +** \par Description +** This function parses a json array object and loads the messages +** linked list pointed to by the explain data handle. +** +** \par Assumptions, External Events, and Notes: +** None. +** +** \param [in] jobj The json object. +** +** \param [in] key The current key. +** +** \param [in\out] call_count The call_count to limit recursion. +** +** \param [in\out] handle The handle to the explain data structure. +** +** \returns true for success, false for failure. +** +*************************************************************************/ +bool json_parse_array(json_object *jobj, const char *key, unsigned int *call_count, explain_data_t *handle); + + +/************************************************************************/ +/** \brief Parse and load an int value into the current message field. +** +** \par Description +** This function parses and loads a integer into the current +** message or message field pointed to by the handle. +** +** \par Assumptions, External Events, and Notes: +** None. +** +** \param [in] jobj The json object. +** +** \param [in] key The current key. +** +** \param [in\out] handle The handle to the explain data structure. +** +** \returns true for success, false for failure. +** +*************************************************************************/ +bool load_int(json_object * jobj, const char *key, explain_data_t *handle); + + +/************************************************************************/ +/** \brief Parse and load a string value into the current message field. +** +** \par Description +** This function parses and loads a string into the current +** message or message field pointed to by the handle. +** +** \par Assumptions, External Events, and Notes: +** None. +** +** \param [in] jobj The json object. +** +** \param [in] key The current key. +** +** \param [in\out] handle The handle to the explain data structure. +** +** \returns true for success, false for failure. +** +*************************************************************************/ +bool load_string(json_object * jobj, const char *key, explain_data_t *handle); + + +#ifdef __cplusplus +} +#endif + +#endif /* PARSER_H */ diff --git a/include/usage.h b/include/usage.h new file mode 100644 index 0000000..8def2d2 --- /dev/null +++ b/include/usage.h @@ -0,0 +1,96 @@ +/**************************************************************************** +* +* Copyright (c) 2017 Windhover Labs, L.L.C. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* 3. Neither the name Windhover Labs nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ +#ifndef USAGE_H +#define USAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/** +** \brief application short options. +*/ +typedef enum +{ + /** \brief short help option -h */ + OPT_HELP = 'h', + /** \brief short path option -p */ + OPT_PATH = 'p' +} explain_options_t; + + + +/************************************************************************/ +/** \brief Print a usage message and exit. +** +** \par Description +** This function prints a usage calls and exits the application. +** +** \par Assumptions, External Events, and Notes: +** For use with a stand-alone application that parses user +** arguments. +** +*************************************************************************/ +void usage(void); + + +/************************************************************************/ +/** \brief Parse input argument options. +** +** \par Description +** This function parses arguments and copies the input file path +** if provided. +** +** \par Assumptions, External Events, and Notes: +** None. +** +** \param [in/out] inputPath A pointer to copy the input path to. +** +** \param [in] argc The argument count. +** +** \param [in] argv The argument vector. +** +** \returns bool true for success, false for failure. +** +*************************************************************************/ +bool parse_options(char *inputPath, int argc, char **argv); + + +#ifdef __cplusplus +} +#endif + +#endif /* USAGE_H */ diff --git a/include/utils.h b/include/utils.h new file mode 100644 index 0000000..861399d --- /dev/null +++ b/include/utils.h @@ -0,0 +1,102 @@ +/**************************************************************************** +* +* Copyright (c) 2017 Windhover Labs, L.L.C. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* 3. Neither the name Windhover Labs nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ +#ifndef UTILS_H +#define UTILS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/************************************************************************/ +/** \brief Validate an input file path. +** +** \par Description +** This attempts to validate the path to an input file. +** +** \par Assumptions, External Events, and Notes: +** None. +** +** \param [in] inputPath The input path. +** +** \returns TRUE for success, FALSE for failure. +** +*************************************************************************/ +bool validate_path(const char *inputPath); + + +/************************************************************************/ +/** \brief Copy the input from filepath to fileContent. +** +** \par Description +** Opens and copies the file indicated by the file path to the +** buffer fileContent. +** +** \par Assumptions, External Events, and Notes: +** fileContent must be large enough to store the contents of the +** file indicated by filepath. +** +** \param [in] filePath The input file path. +** +** \param [in/out] fileContent The buffer to copy to. +** +** \returns TRUE for success, FALSE for failure. +** +*************************************************************************/ +bool read_input(const char *filePath, char *fileContent); + + +/************************************************************************/ +/** \brief Get the ccsds message id from a buffer. +** +** \par Description +** Get the ccsds message id of a message stored in the input +** buffer. +** +** \par Assumptions, External Events, and Notes: +** None. +** +** \param [in] input The input buffer. +** +** \returns the message id. +** +*************************************************************************/ +unsigned int get_ccsds_msg_id(const char *input); + + +#ifdef __cplusplus +} +#endif + +#endif /* UTILS_H */ diff --git a/python/.gitignore b/python/.gitignore new file mode 100644 index 0000000..0d20b64 --- /dev/null +++ b/python/.gitignore @@ -0,0 +1 @@ +*.pyc diff --git a/python/attribdef.py b/python/attribdef.py new file mode 100644 index 0000000..32f8ff7 --- /dev/null +++ b/python/attribdef.py @@ -0,0 +1,19 @@ +#!/usr/bin/python +#------------------------------------------------------------------------------- +# attribdef.py +# +# This class contains the structure definition. +# +# Mathew Benson (mbenson@windhoverlabs.com) + + +class AttributeDef(object): + def __init__(self, name, offset, size, ctype): + """ + """ + self.name = name + self.offset = offset + self.size = size + self.ctype = ctype + + diff --git a/python/jsoncombine.py b/python/jsoncombine.py new file mode 100755 index 0000000..136997d --- /dev/null +++ b/python/jsoncombine.py @@ -0,0 +1,19 @@ +#!/usr/bin/python +import json +import argparse +import sys + +##parser = argparse.ArgumentParser(description='Merges two or more json files into a single file.') + +if __name__ == '__main__': + result = {'bitmap':[]} + for filename in sys.argv[1:]: + with open(filename, "rb") as infile: + input_data = json.load(infile) + for bitmap in input_data['bitmap'] : + result['bitmap'].append(bitmap) + + #merged_dict = {key: value for (key, value) in (dictA.items() + dictB.items())} + + with open("merged_file.json", "wb") as outfile: + json.dump(result, outfile, sort_keys=False, indent=4, separators=(',', ': ')) diff --git a/python/merged_file.json b/python/merged_file.json new file mode 100644 index 0000000..7f762a1 --- /dev/null +++ b/python/merged_file.json @@ -0,0 +1,3 @@ +{ + "bitmap": [] +} \ No newline at end of file diff --git a/python/parse_gateway_msgs.sh b/python/parse_gateway_msgs.sh new file mode 100755 index 0000000..7f6b70e --- /dev/null +++ b/python/parse_gateway_msgs.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +#------------- +# Variables to set +#------------- +#Path to source binary compiled with -g flag +PATH_TO_SRC_EXE="/home/vagrant/Desktop/OSR/gateway/sims/SIM_aug_module/S_main_Linux_5.4_x86_64.exe" +#Path to destination binary compiled with -g flag +PATH_TO_DST_EXE="/home/vagrant/Desktop/OSR/gateway/sims/SIM_aug_module/S_main_Linux_5.4_x86_64.exe" +#Input message symbol names this assumes the names are the same in src and dst +INPUT_MSG_ARRAY=("StarTrackerTelemetry" "ImuTelemetry" "LidarTelemetry" "SbandSensorTelemetry" "VisibleNfovCameraTelemetry") +#Output message symbol names also assumes names are the same in src and dst binaries +OUTPUT_MSG_ARRAY=("DveFireCommand" "RcsFireCommand") +#Combined output file name +OUTPUT_FILE_NAME="explain_output.json" +#Combined input file name +INPUT_FILE_NAME="explain_input.json" +#Merged file name output of jsoncombine.py +MERGED_FILE_NAME="merged_file.json" + +# No editing should be needed beyond this point. + +#------------- +# Get Telemetry Message Memory Maps +#------------- +for i in ${INPUT_MSG_ARRAY[@]} +do +echo "Parsing input $i memory map" +python pyexplain.py -o "$i" -m 0 -ss "$i" -ds "$i" -sf $PATH_TO_SRC_EXE -df $PATH_TO_DST_EXE +done + +# Merge json files +echo "Merging input files ${INPUT_MSG_ARRAY[*]}" +python jsoncombine.py ${INPUT_MSG_ARRAY[*]} + +# Rename merged_file.json +echo "Renaming $MERGED_FILE_NAME to $INPUT_FILE_NAME" +mv $MERGED_FILE_NAME $INPUT_FILE_NAME + +#------------- +# Get Command Message Memory Maps +#------------- +for i in ${OUTPUT_MSG_ARRAY[@]} +do +echo "Parsing output $i memory map" +python pyexplain.py -o "$i" -m 0 -ss "$i" -ds "$i" -sf $PATH_TO_SRC_EXE -df $PATH_TO_DST_EXE +done + +# Merge json files +echo "Merging input files ${OUTPUT_MSG_ARRAY[*]}" +python jsoncombine.py ${OUTPUT_MSG_ARRAY[*]} + +# Rename merged_file.json +echo "Renaming $MERGED_FILE_NAME to $OUTPUT_FILE_NAME" +mv $MERGED_FILE_NAME $OUTPUT_FILE_NAME + +#------------- +# Cleanup +#------------- +echo "cleanup" +for i in ${INPUT_MSG_ARRAY[@]} +do +echo "removing $i" +rm "$i" +done + +for i in ${OUTPUT_MSG_ARRAY[@]} +do +echo "removing $i" +rm "$i" +done + diff --git a/python/pyexplain.py b/python/pyexplain.py new file mode 100755 index 0000000..9155842 --- /dev/null +++ b/python/pyexplain.py @@ -0,0 +1,225 @@ +#!/usr/bin/python +#------------------------------------------------------------------------------- +# pyexplain.py +# +# This utility parses an elf image and generates memory bitmaps for the +# libexplain library. +# +# Mathew Benson (mbenson@windhoverlabs.com) +#------------------------------------------------------------------------------- +from __future__ import print_function + +import elftools.dwarf.compileunit +from structdef import * +import json +import argparse + +class MyCompileUnit(elftools.dwarf.compileunit.CompileUnit): + + def get_DIE_at_offset(self, offset): + for die in self.iter_DIEs(): + if die.offset == offset: + return die + return None + +elftools.dwarf.compileunit.CompileUnit = MyCompileUnit + +import sys + +# If pyelftools is not installed, the utility can also run from the root dir of +# the source distribution. +sys.path[0:0] = ['.', '..'] + +from elftools.elf.elffile import ELFFile + +def process_file(filename, symbol): + print('Processing file:', filename) + with open(filename, 'rb') as f: + elffile = ELFFile(f) + + if elffile.little_endian == True : + endian = 'L' + else : + endian = 'B' + + if not elffile.has_dwarf_info(): + print(' file has no DWARF info') + return + + # get_dwarf_info returns a DWARFInfo context object, which is the + # starting point for all DWARF-based processing in pyelftools. + dwarfinfo = elffile.get_dwarf_info() + + for CU in dwarfinfo.iter_CUs(): + # DWARFInfo allows to iterate over the compile units contained in + # the .debug_info section. CU is a CompileUnit object, with some + # computed attributes (such as its offset in the section) and + # a header which conforms to the DWARF standard. The access to + # header elements is, as usual, via item-lookup. + #print(' Found a compile unit at offset %s, length %s' % ( + # CU.cu_offset, CU['unit_length'])) + + # Start with the top DIE, the root for this CU's DIE tree + top_DIE = CU.get_top_DIE() + #print(' Top DIE with tag=%s' % top_DIE.tag) + + # We're interested in the filename... + #print(' name=%s' % top_DIE.get_full_path()) + + # Display DIEs recursively starting with top_DIE + return endian, die_info_rec(top_DIE, CU, symbol) + +def die_info_rec(die, CU, symbol, struct = None): + """ A recursive function for showing information about a DIE and its + children. + """ + if die.get_full_path() == symbol : + try: + struct_die = CU.get_DIE_at_offset(die.attributes['DW_AT_type'].value) + except KeyError, e: + print ('KeyError, ensure that the structure does not have a tag, key: %s' % (str(e))) + print ('Exiting...') + sys.exit(1) + if struct_die is not None : + struct = StructDef(-1, die.get_full_path()) + die_structure_type_rec(struct_die, CU, struct) + + for child in die.iter_children(): + struct = die_info_rec(child, CU, symbol, struct) + + return struct + + +def die_structure_type_rec(die, CU, struct): + """ A recursive function for showing information about a DIE and its + children. + """ + for child in die.iter_children(): + die_member_rec(child, CU, struct) + + +def die_member_rec(die, CU, struct): + """ A recursive function for showing information about a DIE and its + children. + """ + byte_offset_attrib = die.attributes.get('DW_AT_data_member_location', None) + byte_size_attrib = die.attributes.get('DW_AT_byte_size', None) + bit_size_attrib = die.attributes.get('DW_AT_bit_size', None) + bit_offset_attrib = die.attributes.get('DW_AT_bit_offset', None) + + byte_offset = 0 + byte_size = 0 + bit_length = 0 + bit_offset = 0 + + if byte_offset_attrib is not None : + byte_offset = byte_offset_attrib.value + + if byte_size_attrib is not None : + byte_size = byte_size_attrib.value + + if bit_size_attrib is not None : + bit_length = bit_size_attrib.value + + if bit_offset_attrib is not None : + bit_offset = bit_offset_attrib.value + + bit_offset = bit_offset + (byte_offset * 8) + + if bit_length == 0 : + bit_length = get_bit_length_from_at_type(CU.get_DIE_at_offset(die.attributes['DW_AT_type'].value), CU) + + field_name = die.get_full_path() + struct.add_attribute(field_name, bit_offset, bit_length, 'UNKNOWN') + + +def get_bit_length_from_at_type(die, CU): + bit_length = -1 + + if die.tag == 'DW_TAG_array_type' : + upper_bound = -1 + for child in die.iter_children(): + upper_bound_temp = parse_array_type_child(child, CU) + if upper_bound_temp != -1 : + upper_bound = upper_bound_temp + + bit_length = get_bit_length_from_at_type(CU.get_DIE_at_offset(die.attributes['DW_AT_type'].value), CU) * upper_bound + else : + byte_size_attrib = die.attributes.get('DW_AT_byte_size', None) + + + if byte_size_attrib is None : + bit_length = get_bit_length_from_at_type(CU.get_DIE_at_offset(die.attributes['DW_AT_type'].value), CU) + else : + byte_size = byte_size_attrib.value + bit_length = byte_size * 8 + + return bit_length + + +def parse_array_type_child(die, CU) : + upper_bound = -1 + upper_bound_attrib = die.attributes.get('DW_AT_upper_bound', None) + + if upper_bound_attrib is not None : + # Array size is calculated as (DW_AT_upper_bound - DW_AT_lower_bound) + 1. + upper_bound = upper_bound_attrib.value + 1 + return upper_bound + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description='Generate bitmap files directly from as-built ELF files for the libextract library.') + parser.add_argument('-o', '--output', metavar='', type=str, help='Output file name', required=True) + parser.add_argument('-m', '--msgid', metavar='', type=str, help='Message ID. 0x0000 to 0x1fff', required=True) + parser.add_argument('-ss', '--src-symbol', metavar='', type=str, help='Source symbol name.', required=True) + parser.add_argument('-ds', '--dst-symbol', metavar='', type=str, help='Destination symbol name', required=True) + parser.add_argument('-sf', '--src-file', metavar='', type=str, help='Source file', required=True) + parser.add_argument('-df', '--dst-file', metavar='', type=str, help='Destination file', required=True) + parser.add_argument('-a', '--append', action='store_true', help='Append to output file.', required=False) + + args = parser.parse_args() + + source_endian, source_struct = process_file(args.src_file, args.src_symbol) + dest_endian, dest_struct = process_file(args.dst_file, args.dst_symbol) + + + # Check that process_file returned a value + if source_struct == None or dest_struct == None: + print ('Error, source or destination structure not found') + print ('Ensure the structure is used, that the compiler has not optimized it out, and that a tag is not used.') + print ('Exiting...') + sys.exit(1) + + if args.append == False : + output = {'bitmap': []} + else : + with open(args.output, 'r') as json_data: + output = json.load(json_data) + json_data.close() + + struct = { + 'id':args.msgid, + 'src_symbol':args.src_symbol, + 'dst_symbol':args.dst_symbol, + 'ops_name':'', + 'src_endian':source_endian, + 'dst_endian':dest_endian, + 'fields':[] + } + + fields = struct['fields'] + + for i in range(0, len(source_struct.list)) : + field = { + 'op_name': source_struct.list[i].name, + 'length': source_struct.list[i].size, + 'src_offset': source_struct.list[i].offset, + 'dst_offset': dest_struct.list[i].offset} + fields.append(field) + + output['bitmap'].append(struct) + + print('Writing file %s:' % (args.output)) + with open(args.output, 'w') as outfile : + json.dump(output, outfile, sort_keys=False, indent=4, separators=(',', ': ')) + diff --git a/python/structdef.py b/python/structdef.py new file mode 100644 index 0000000..8f8bb26 --- /dev/null +++ b/python/structdef.py @@ -0,0 +1,26 @@ +#!/usr/bin/python +#------------------------------------------------------------------------------- +# structdef.py +# +# This class contains the structure definition. +# +# Mathew Benson (mbenson@windhoverlabs.com) + +from attribdef import * + +class StructDef(object): + def __init__(self, msgid, name): + """ + """ + self.msgid = msgid + self.name = name + self.list = [] + + + def add_attribute(self, name, offset, size, ctype): + """ + """ + attrib = AttributeDef(name, offset, size, ctype) + self.list.append(attrib) + + diff --git a/setup_deps.sh b/setup_deps.sh new file mode 100755 index 0000000..88fb630 --- /dev/null +++ b/setup_deps.sh @@ -0,0 +1,5 @@ +#!/bin/bash +sudo apt-get -y install libjson0 libjson0-dev + +# python deps +pip install pyelftools diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..f0114f1 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,38 @@ +IDIR=../include +LIB=-Wl,-Bstatic -ljson -Wl,-Bdynamic +CC=gcc +CFLAGS=-g -Wno-deprecated-declarations -fPIC -I$(IDIR) +STATICLIB=$(shell find /usr/lib/ -type f -name "libjson-c.a") + +ODIR=obj + +_DEPS = cfe_sb.h utils.h cfe_mission_cfg.h common_types.h ccsds.h memtools.h list.h message.h usage.h explain.h parser.h +DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS)) + +_OBJ = cfe_sb_util.o utils.o ccsds.o memtools.o list.o message.o usage.o explain.o parser.o example.o +OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ)) + +_OBJ_LIB = cfe_sb_util.o utils.o ccsds.o memtools.o list.o message.o usage.o explain.o parser.o +OBJ_LIB = $(patsubst %,$(ODIR)/%,$(_OBJ_LIB)) + +$(ODIR)/%.o: %.c $(DEPS) + $(CC) -c -o $@ $< $(CFLAGS) + +all: example.exe libexplain.so archive + +example.exe: $(OBJ) + $(CC) -o $@ $^ $(LIB) + +libexplain.so: $(OBJ_LIB) + $(CC) -shared -o $@ $^ + +archive: $(OBJ_LIB) + cd obj; \ + ar x $(STATICLIB) + ar rcs libexplain.a obj/*.o + + +.PHONY: clean + +clean: + rm -f *.exe *.so *.a $(ODIR)/*.o *~ core $(INCDIR)/*~ diff --git a/src/ccsds.c b/src/ccsds.c new file mode 100644 index 0000000..5c8dc3d --- /dev/null +++ b/src/ccsds.c @@ -0,0 +1,178 @@ +/****************************************************************************** +** File: ccsds.c +** +** Copyright (c) 2004-2012, United States government as represented by the +** administrator of the National Aeronautics Space Administration. +** All rights reserved. This software(cFE) was created at NASA's Goddard +** Space Flight Center pursuant to government contracts. +** +** This is governed by the NASA Open Source Agreement and may be used, +** distributed and modified only pursuant to the terms of that agreement. +** +** +** +** Purpose: +** Functions for working with CCSDS headers. +** +** $Log: ccsds.c $ +** Revision 1.5 2012/01/13 12:15:11GMT-05:00 acudmore +** Changed license text to reflect open source +** Revision 1.4 2010/10/25 15:00:51EDT jmdagost +** Corrected bad apostrophe in prologue. +** Revision 1.3 2010/10/04 15:21:32EDT jmdagost +** Cleaned up copyright symbol. +** Revision 1.2 2009/06/10 09:17:28EDT acudmore +** Updated OS_Mem* and OS_BSP* to CFE_PSP_* +** Revision 1.1 2008/04/17 08:05:29EDT ruperera +** Initial revision +** Member added to project c:/MKSDATA/MKS-REPOSITORY/MKS-CFE-PROJECT/fsw/cfe-core/src/sb/project.pj +** Revision 1.3 2007/09/24 11:02:22EDT rjmcgraw +** Removed unused macros +** Revision 1.2 2006/06/12 15:26:03EDT rjmcgraw +** Added legal statement +** +******************************************************************************/ + +/* +** Include Files +*/ + +#include "common_types.h" +#include "ccsds.h" +//#include "osapi.h" +//#include "cfe_psp.h" +#include + +/****************************************************************************** +** Function: CCSDS_InitPkt() +** +** Purpose: +** Initialize a CCSDS packet. The primary header is initialized with +** specified values, and if the Clear flag is set, the rest of the packet +** is filled with zeros. +** +** Arguments: +** PktPtr : Pointer to primary header of packet. +** StreamId : Stream ID to use for the packet. +** Length : Length of the packet in bytes. +** Clear : Indicates whether to clear the entire packet: +** TRUE = fill sequence count and packet data with zeros +** (used after a cold restart) +** FALSE = leave sequence count and packet data unchanged +** (used after a warm restart if data must be preserved) +** +** Return: +** (none) +*/ + +void CCSDS_InitPkt (CCSDS_PriHdr_t *PktPtr, + uint16 StreamId, + uint16 Length, + boolean Clear ) +{ + uint16 SeqCount; + + /* Save the sequence count in case it must be preserved. */ + SeqCount = CCSDS_RD_SEQ(*PktPtr); + + /* Zero the entire packet if needed. */ + if (Clear) memset((void *)PktPtr, 0, Length); + + /* Clear the primary header. */ + CCSDS_CLR_PRI_HDR(*PktPtr); + + /* Set the stream ID and length fields in the primary header. */ + CCSDS_WR_SID(*PktPtr, StreamId); + CCSDS_WR_LEN(*PktPtr, Length); + + /* Restore the sequence count if needed. */ + if (!Clear) CCSDS_WR_SEQ(*PktPtr, SeqCount); + +} /* END CCSDS_InitPkt() */ + + +/****************************************************************************** +** Function: CCSDS_LoadCheckSum() +** +** Purpose: +** Compute and load a checksum for a CCSDS command packet that has a +** secondary header. +** +** Arguments: +** PktPtr : Pointer to header of command packet. The packet must +** have a secondary header and the length in the primary +** header must be correct. The checksum field in the packet +** will be modified. +** +** Return: +** (none) +*/ + +void CCSDS_LoadCheckSum (CCSDS_CmdPkt_t *PktPtr) +{ + uint8 CheckSum; + + /* Clear the checksum field so the new checksum is correct. */ + CCSDS_WR_CHECKSUM(PktPtr->SecHdr, 0); + + /* Compute and load new checksum. */ + CheckSum = CCSDS_ComputeCheckSum(PktPtr); + CCSDS_WR_CHECKSUM(PktPtr->SecHdr, CheckSum); + +} /* END CCSDS_LoadCheckSum() */ + + +/****************************************************************************** +** Function: CCSDS_ValidCheckSum() +** +** Purpose: +** Determine whether a checksum in a command packet is valid. +** +** Arguments: +** PktPtr : Pointer to header of command packet. The packet must +** have a secondary header and the length in the primary +** header must be correct. +** +** Return: +** TRUE if checksum of packet is valid; FALSE if not. +** A valid checksum is 0. +*/ + +boolean CCSDS_ValidCheckSum (CCSDS_CmdPkt_t *PktPtr) +{ + + return (CCSDS_ComputeCheckSum(PktPtr) == 0); + +} /* END CCSDS_ValidCheckSum() */ + + +/****************************************************************************** +** Function: CCSDS_ComputeCheckSum() +** +** Purpose: +** Compute the checksum for a command packet. The checksum is the XOR of +** all bytes in the packet; a valid checksum is zero. +** +** Arguments: +** PktPtr : Pointer to header of command packet. The packet must +** have a secondary header and the length in the primary +** header must be correct. +** +** Return: +** TRUE if checksum of packet is valid; FALSE if not. +*/ + +uint8 CCSDS_ComputeCheckSum (CCSDS_CmdPkt_t *PktPtr) +{ + uint16 PktLen = CCSDS_RD_LEN(PktPtr->PriHdr); + uint8 *BytePtr = (uint8 *)PktPtr; + uint8 CheckSum; + + CheckSum = 0xFF; + while (PktLen--) CheckSum ^= *(BytePtr++); + + return CheckSum; + +} /* END CCSDS_ComputeCheckSum() */ + +/*****************************************************************************/ diff --git a/src/cfe_sb_util.c b/src/cfe_sb_util.c new file mode 100644 index 0000000..7084ce8 --- /dev/null +++ b/src/cfe_sb_util.c @@ -0,0 +1,409 @@ +/****************************************************************************** +** File: cfe_sb_util.c +** +** Copyright (c) 2004-2012, United States government as represented by the +** administrator of the National Aeronautics Space Administration. +** All rights reserved. This software(cFE) was created at NASA's Goddard +** Space Flight Center pursuant to government contracts. +** +** This is governed by the NASA Open Source Agreement and may be used, +** distributed and modified only pursuant to the terms of that agreement. +** +** +** +** Purpose: +** This file contains 'access' macros and functions for reading and +** writing message header fields. +** +** Author: R.McGraw/SSI +** +** $Log: cfe_sb_util.c $ +** Revision 1.8 2014/07/10 09:24:08GMT-05:00 rmcgraw +** DCR9772:1 Changes from C. Monaco & W.M Reid from APL for endianess neutrality +** Revision 1.7 2014/06/06 15:18:37EDT rmcgraw +** DCR21559 - Changed CFE_SB_MsgHdrSize to use macro instead of writing msgid directly +** Revision 1.6 2012/09/27 17:16:04EDT aschoeni +** Fixed 32_32_M_20 get function to shift by 12 instead of masking +** Revision 1.5 2012/01/13 12:15:13EST acudmore +** Changed license text to reflect open source +** Revision 1.4 2011/02/03 15:25:37EST lwalling +** Modified Get/Set time functions to support CFE_SB_PACKET_TIME_FORMAT selection +** Revision 1.3 2010/10/25 13:54:10EDT aschoeni +** Removed unused value from SetUserDataLength +** Revision 1.2 2010/10/04 15:21:13EDT jmdagost +** Cleaned up copyright symbol. +** Revision 1.1 2008/04/17 08:05:32EDT ruperera +** Initial revision +** Member added to project c:/MKSDATA/MKS-REPOSITORY/MKS-CFE-PROJECT/fsw/cfe-core/src/sb/project.pj +** Revision 1.10 2006/10/16 14:31:00EDT rjmcgraw +** Minor changes to comply with MISRA standard +** Revision 1.9 2006/06/12 19:26:06GMT rjmcgraw +** Added legal statement +** Revision 1.8 2006/06/05 15:43:50EDT rjmcgraw +** Comment changes in reference to DCR398 +** Revision 1.7 2006/04/28 18:35:14GMT rjmcgraw +** Corrected problems with checksum utils when no sec hdr present +** Revision 1.6 2006/04/28 18:02:20GMT rjmcgraw +** Corrected problems with Set/GetCmdCode for cmd pkts wo sec hdr +** Revision 1.5 2006/04/27 18:45:10GMT rjmcgraw +** Corrected problems with Set/GetMsgTime when no sec hdr is present in tlm pkts +** +******************************************************************************/ + + +/* +** Include Files +*/ + +#include "cfe_sb.h" +#include "ccsds.h" + +#define MESSAGE_FORMAT_IS_CCSDS + + +/****************************************************************************** +** Function: CFE_SB_InitMsg() +** +** Purpose: +** Initialize the header fields of a message +** +** Arguments: +** MsgPtr - Pointer to the header of a message. +** MsgId - MsgId to use for the message. +** Length - Length of the message in bytes. +** Clear - Indicates whether to clear the entire message: +** TRUE = fill sequence count and packet data with zeros +** FALSE = leave sequence count and packet data unchanged +** Return: +** (none) +*/ +void CFE_SB_InitMsg(void *MsgPtr, + CFE_SB_MsgId_t MsgId, + uint16 Length, + boolean Clear ) +{ +#ifdef MESSAGE_FORMAT_IS_CCSDS + + CCSDS_InitPkt ((CCSDS_PriHdr_t *)MsgPtr,(uint16)MsgId,Length,Clear); + +#endif +} /* end CFE_SB_InitMsg */ + + + +/****************************************************************************** +** Function: CFE_SB_MsgHdrSize() +** +** Purpose: +** Get the size of a message header. +** +** Arguments: +** MsgPtr - Pointer to a CFE_SB_Msg_t +** +** Return: +** Size of Message Header. +*/ +uint16 CFE_SB_MsgHdrSize(CFE_SB_MsgId_t MsgId) +{ +#ifdef MESSAGE_FORMAT_IS_CCSDS + + uint16 size; + CCSDS_PriHdr_t CCSDSPriHdr; + + CCSDS_WR_SID(CCSDSPriHdr,MsgId); + + /* if secondary hdr is not present... */ + if(CCSDS_RD_SHDR(CCSDSPriHdr) == 0){ + + size = sizeof(CCSDS_PriHdr_t); + + }else if(CCSDS_RD_TYPE(CCSDSPriHdr) == CCSDS_CMD){ + + size = CFE_SB_CMD_HDR_SIZE; + + }else{ + + size = CFE_SB_TLM_HDR_SIZE; + } + + return size; + +#endif +}/* end CFE_SB_MsgHdrSize */ + + +/****************************************************************************** +** Function: CFE_SB_GetUserData() +** +** Purpose: +** Get a pointer to the user data portion of a message. +** +** Arguments: +** MsgPtr - Pointer to a CFE_SB_Msg_t +** +** Return: +** Pointer to the first byte after the headers +*/ +void *CFE_SB_GetUserData(CFE_SB_MsgPtr_t MsgPtr) +{ +#ifdef MESSAGE_FORMAT_IS_CCSDS + uint8 *BytePtr; + CFE_SB_MsgId_t MsgId; + uint16 HdrSize; + + BytePtr = (uint8 *)MsgPtr; + MsgId = CCSDS_RD_SID(MsgPtr->Hdr); + HdrSize = CFE_SB_MsgHdrSize(MsgId); + + return (BytePtr + HdrSize); +#endif +}/* end CFE_SB_GetUserData */ + + +/****************************************************************************** +** Function: CFE_SB_GetMsgId() +** +** Purpose: +** Get the message ID of a message. +** +** Arguments: +** MsgPtr - Pointer to a CFE_SB_Msg_t +** +** Return: +** The Message Id in the message. +*/ +CFE_SB_MsgId_t CFE_SB_GetMsgId(CFE_SB_MsgPtr_t MsgPtr) +{ +#ifdef MESSAGE_FORMAT_IS_CCSDS + + return CCSDS_RD_SID(MsgPtr->Hdr); + +#endif +}/* end CFE_SB_GetMsgId */ + + +/****************************************************************************** +** Function: CFE_SB_SetMsgId() +** +** Purpose: +** Set the message Id of a message. +** +** Arguments: +** MsgPtr - Pointer to a CFE_SB_Msg_t +** MsgId - Message Id to be written +** +** Return: +** (none) +*/ +void CFE_SB_SetMsgId(CFE_SB_MsgPtr_t MsgPtr, + CFE_SB_MsgId_t MsgId) +{ +#ifdef MESSAGE_FORMAT_IS_CCSDS + + CCSDS_WR_SID(MsgPtr->Hdr,MsgId); + +#endif +}/* end CFE_SB_SetMsgId */ + + +/****************************************************************************** +** Function: CFE_SB_GetUserDataLength() +** +** Purpose: +** Get the length of the user data of a message (total size - hdrs). +** +** Arguments: +** MsgPtr - Pointer to a CFE_SB_Msg_t +** +** Return: +** Size of the message minus the headers +*/ +uint16 CFE_SB_GetUserDataLength(CFE_SB_MsgPtr_t MsgPtr) +{ +#ifdef MESSAGE_FORMAT_IS_CCSDS + uint16 TotalMsgSize; + uint16 HdrSize; + + CFE_SB_MsgId_t MsgId; + MsgId = CCSDS_RD_SID(MsgPtr->Hdr); + TotalMsgSize = CFE_SB_GetTotalMsgLength(MsgPtr); + HdrSize = CFE_SB_MsgHdrSize(MsgId); + + return (TotalMsgSize - HdrSize); +#endif +}/* end CFE_SB_GetUserDataLength */ + + +/****************************************************************************** +** Function: CFE_SB_SetUserDataLength() +** +** Purpose: +** Set the length field in the hdr, given the user data length. +** +** Arguments: +** MsgPtr - Pointer to a CFE_SB_Msg_t +** DataLength - Length of the user data +** +** Return: +** (none) +*/ +void CFE_SB_SetUserDataLength(CFE_SB_MsgPtr_t MsgPtr,uint16 DataLength) +{ +#ifdef MESSAGE_FORMAT_IS_CCSDS + + uint32 TotalMsgSize, HdrSize; + + CFE_SB_MsgId_t MsgId; + MsgId = CCSDS_RD_SID(MsgPtr->Hdr); + HdrSize = CFE_SB_MsgHdrSize(MsgId); + TotalMsgSize = HdrSize + DataLength; + CCSDS_WR_LEN(MsgPtr->Hdr,TotalMsgSize); + +#endif +}/* end CFE_SB_SetUserDataLength */ + + +/****************************************************************************** +** Function: CFE_SB_GetTotalMsgLength() +** +** Purpose: +** Get the total length of the message. +** +** Arguments: +** MsgPtr - Pointer to a CFE_SB_Msg_t +** +** Return: +** Total Length of the message +*/ +uint16 CFE_SB_GetTotalMsgLength(CFE_SB_MsgPtr_t MsgPtr) +{ +#ifdef MESSAGE_FORMAT_IS_CCSDS + + return CCSDS_RD_LEN(MsgPtr->Hdr); + +#endif +}/* end CFE_SB_GetTotalMsgLength */ + + +/****************************************************************************** +** Function: CFE_SB_SetTotalMsgLength() +** +** Purpose: +** Set the length field, given the total length of the message. +** +** Arguments: +** MsgPtr - Pointer to a CFE_SB_Msg_t +** TotalLength - Total Length of the message +** +** Return: +** (none) +*/ +void CFE_SB_SetTotalMsgLength(CFE_SB_MsgPtr_t MsgPtr,uint16 TotalLength) +{ +#ifdef MESSAGE_FORMAT_IS_CCSDS + + CCSDS_WR_LEN(MsgPtr->Hdr,TotalLength); + +#endif +}/* end CFE_SB_SetTotalMsgLength */ + + +/****************************************************************************** +** Function: CFE_SB_GetChecksum() +** +** Purpose: +** Get the checksum field of message. +** +** Arguments: +** MsgPtr - Pointer to a CFE_SB_Msg_t +** +** Return: +** +*/ +uint16 CFE_SB_GetChecksum(CFE_SB_MsgPtr_t MsgPtr) +{ +#ifdef MESSAGE_FORMAT_IS_CCSDS + + CFE_SB_CmdHdr_t *CmdHdrPtr; + + /* if msg type is telemetry or there is no secondary hdr... */ + if((CCSDS_RD_TYPE(MsgPtr->Hdr) == CCSDS_TLM)||(CCSDS_RD_SHDR(MsgPtr->Hdr) == 0)){ + return 0; + }/* end if */ + + /* cast the input pointer to a Cmd Msg pointer */ + CmdHdrPtr = (CFE_SB_CmdHdr_t *)MsgPtr; + + return CCSDS_RD_CHECKSUM(CmdHdrPtr->Sec); + +#endif +}/* end CFE_SB_GetChecksum */ + + +/****************************************************************************** +** Function: CFE_SB_GenerateChecksum() +** +** Purpose: +** Calculate and Set the checksum field of message. +** +** Arguments: +** MsgPtr - Pointer to a CFE_SB_Msg_t +** +** Note: If any header fields are changed after this call, the checksum will +** no longer be valid. +** Also, the packet length field dictates the number of iterations +** used in the checksum algorithm and therefore must be properly set +** before calling this function. +** +** Return: +** (none) +*/ +void CFE_SB_GenerateChecksum(CFE_SB_MsgPtr_t MsgPtr) +{ +#ifdef MESSAGE_FORMAT_IS_CCSDS + + CCSDS_CmdPkt_t *CmdPktPtr; + + /* if msg type is telemetry or there is no secondary hdr... */ + if((CCSDS_RD_TYPE(MsgPtr->Hdr) == CCSDS_TLM)||(CCSDS_RD_SHDR(MsgPtr->Hdr) == 0)){ + return; + }/* end if */ + + CmdPktPtr = (CCSDS_CmdPkt_t *)MsgPtr; + + CCSDS_LoadCheckSum(CmdPktPtr); + +#endif +}/* end CFE_SB_GenerateChecksum */ + + +/****************************************************************************** +** Function: CFE_SB_ValidateChecksum() +** +** Purpose: +** Validate the checksum field of message. +** +** Arguments: +** MsgPtr - Pointer to a CFE_SB_Msg_t +** +** Return: +** TRUE if checksum of packet is valid; FALSE if not. +*/ +boolean CFE_SB_ValidateChecksum(CFE_SB_MsgPtr_t MsgPtr) +{ +#ifdef MESSAGE_FORMAT_IS_CCSDS + + CCSDS_CmdPkt_t *CmdPktPtr; + + /* if msg type is telemetry or there is no secondary hdr... */ + if((CCSDS_RD_TYPE(MsgPtr->Hdr) == CCSDS_TLM)||(CCSDS_RD_SHDR(MsgPtr->Hdr) == 0)){ + return FALSE; + }/* end if */ + + CmdPktPtr = (CCSDS_CmdPkt_t *)MsgPtr; + + return CCSDS_ValidCheckSum (CmdPktPtr); + +#endif +}/* end CFE_SB_ValidateChecksum */ + diff --git a/src/example.c b/src/example.c new file mode 100644 index 0000000..ec287f6 --- /dev/null +++ b/src/example.c @@ -0,0 +1,189 @@ +/**************************************************************************** +* +* Copyright (c) 2017 Windhover Labs, L.L.C. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* 3. Neither the name Windhover Labs nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ +#include "explain.h" +#include "usage.h" +#include "common_types.h" +#include "cfe_sb.h" +#include "utils.h" +#include +#include +#include + + +/* Test structure for source. Note uint8 padding. */ +typedef struct +{ + uint8 TlmHeader[CFE_SB_TLM_HDR_SIZE]; + uint16 synch; + + uint8 padding; + + uint8 bit1:1; + uint8 bit2:1; + uint8 bit34:2; + uint8 bit56:2; + uint8 bit78:2; + + uint8 nibble1:4; + uint8 nibble2:4; + + uint8 bl1, bl2; /* boolean */ + int8 b1, b2, b3, b4; + int16 w1,w2; + int32 dw1, dw2; + float f1, f2; + double df1, df2; + char str[10]; +} test_data_types_src; + +/* Test structure for destination. Note uint16 padding. */ +typedef struct +{ + uint8 TlmHeader[CFE_SB_TLM_HDR_SIZE]; + uint16 synch; + + uint16 padding; + + uint8 bit1:1; + uint8 bit2:1; + uint8 bit34:2; + uint8 bit56:2; + uint8 bit78:2; + + uint8 nibble1:4; + uint8 nibble2:4; + /* boolean */ + uint8 bl1, bl2; + int8 b1, b2, b3, b4; + int16 w1,w2; + int32 dw1, dw2; + float f1, f2; + double df1, df2; + + char str[10]; +} test_data_types_dst; + + +int main(int argc, char *argv[]) +{ + int exitCode = EXIT_SUCCESS; + boolean returnBool = FALSE; + explain_msg_t *msg_map_ptr = NULL; + explain_field_t *field_map_ptr = NULL; + /* Message src symbol name. */ + char src_symbol[] = "test_data_types_src"; + /* Message dst symbol name. */ + char dst_symbol[] = "test_data_types_dst"; + /* Message id. */ + uint32 msg_id = 2177; + /* Ops name. */ + char ops_name[] = ""; + /* Input and output packets for test. */ + test_data_types_src src_pkt; + test_data_types_dst dst_pkt; + /* Pointers to input and output structs. */ + uint8 *src_ptr = (uint8 *) &src_pkt; + uint8 *dst_ptr = (uint8 *) &dst_pkt; + /* Size written to destination buffer. */ + int size_written = 0; + + /* Clear packets. */ + memset(src_ptr, 0, sizeof(src_pkt)); + memset(dst_ptr, 0, sizeof(dst_pkt)); + + /* Application data. */ + explain_data_t app_data; + + /* Initialize application data */ + (void) explain_init_data(&app_data); + + /* Parse args and get the input file path */ + returnBool = parse_options(&app_data.inputPath[0], argc, argv); + if(FALSE == returnBool) + { + printf("Parse options failed \n"); + exitCode = EXIT_FAILURE; + goto end_of_function; + } + + /* Validate the path argument */ + returnBool = validate_path(&app_data.inputPath[0]); + if(FALSE == returnBool) + { + printf("Validate path failed \n"); + exitCode = EXIT_FAILURE; + goto end_of_function; + } + + /* Read in the input file */ + returnBool = explain_load_memory_map(&app_data.inputPath[0], &app_data); + if(FALSE == returnBool) + { + printf("Load memory map failed \n"); + exitCode = EXIT_FAILURE; + goto end_of_function; + } + + /* Print everything. */ + printf("Begin dump of parsed memory map.\n"); + explain_print_all_fields(&app_data.message_list); + printf("End dump of parsed memory map.\n"); + + /* Lookup message by source symbol name. */ + msg_map_ptr = explain_message_find_via_src_symbol(src_symbol, &app_data.message_list); + /* Lookup message by destination symbol name. */ + msg_map_ptr = explain_message_find_via_dst_symbol(dst_symbol, &app_data.message_list); + /* Lookup message by ops name. */ + msg_map_ptr = explain_message_find_via_name(ops_name, &app_data.message_list); + /* Lookup message by message id. */ + msg_map_ptr = explain_message_find_via_id(msg_id, &app_data.message_list); + + /* Set a field to a value. */ + src_pkt.synch = 2; + + /* Translate from source to destination. */ + printf("Translate from source to destination.\n"); + size_written = explain_translate_buffer(src_ptr, dst_ptr, msg_map_ptr, sizeof(dst_pkt), EXPLAIN_FORWARD); + + printf("src_pkt.synch == %u\n", src_pkt.synch); + printf("dst_pkt.synch == %u\n", dst_pkt.synch); + printf("size_written = %d\n", size_written); + printf("size of destination packet %lu\n",sizeof(dst_pkt)); + printf("size of src packet %lu\n",sizeof(src_pkt)); + + explain_uninit_data(&app_data); + +end_of_function: + + return exitCode; +} diff --git a/src/explain.c b/src/explain.c new file mode 100644 index 0000000..510a604 --- /dev/null +++ b/src/explain.c @@ -0,0 +1,231 @@ +/**************************************************************************** +* +* Copyright (c) 2017 Windhover Labs, L.L.C. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* 3. Neither the name Windhover Labs nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ +/* Local includes */ +#include "explain.h" +#include "memtools.h" +#include "parser.h" +#include "utils.h" +/* Lib includes */ +#include +#include +#include +#include +#include +#include + + +/* Regular copy from source to destination. */ +static void copy_field_forward(char *dst_buf, const char *src_buf, explain_field_t *field_ptr); + + +/* Reverse copy from destination to source. */ +static void copy_field_reverse(char *dst_buf, const char *src_buf, explain_field_t *field_ptr); + + +static void copy_field_forward(char *dst_buf, const char *src_buf, explain_field_t *field_ptr) +{ + memcpy_bitwise(dst_buf, field_ptr->dstOffset, src_buf, field_ptr->srcOffset, field_ptr->length); +} + + +static void copy_field_reverse(char *dst_buf, const char *src_buf, explain_field_t *field_ptr) +{ + memcpy_bitwise(dst_buf, field_ptr->srcOffset, src_buf, field_ptr->dstOffset, field_ptr->length); +} + + +int explain_translate_buffer(char *dst, const char *src, const explain_msg_t *msg_def, unsigned int max_len, explain_direction_t direction) +{ + explain_field_t *field_map_ptr = 0; + unsigned int size_written = 0; + /* Padding can be negative if parsing out of order bit-field. */ + int padding = 0; + + /* Null pointer checks */ + if (0 == src || 0 == dst || 0 == msg_def) + { + goto end_of_function; + } + + /* Clear the destination buffer. */ + memset((void*)dst, 0, max_len); + + for(field_map_ptr = list_head(msg_def->fields); + field_map_ptr != 0; + field_map_ptr = list_item_next(field_map_ptr)) + { + if (direction == EXPLAIN_FORWARD) + { + /* Calculate any padding between current and last field. */ + padding = field_map_ptr->dstOffset - size_written; + + /* Check size to not exceed destination buffer. */ + if((field_map_ptr->length + size_written + padding) <= max_len * 8) + { + /* Copy the field. */ + copy_field_forward(dst, src, field_map_ptr); + /* Add to the total size written. */ + size_written += field_map_ptr->length + padding; + } + else + { + /* Destination buffer is not large enough. */ + size_written = -1; + errno = ENOMEM; + goto end_of_function; + } + } + else if (direction == EXPLAIN_REVERSE) + { + /* Calculate any padding between current and last field. */ + padding = field_map_ptr->srcOffset - size_written; + + /* Check size to not exceed destination buffer. */ + if((field_map_ptr->length + size_written + padding) <= max_len * 8) + { + /* Copy the field. */ + copy_field_reverse(dst, src, field_map_ptr); + /* Add to the total size written. */ + size_written += field_map_ptr->length + padding; + } + else + { + /* Destination buffer is not large enough. */ + size_written = -1; + errno = ENOMEM; + goto end_of_function; + } + } + else + { + /* Do nothing */ + printf("Unknown option in translate buffer\n"); + } + + } + + /* Check for bits copied. */ + if(size_written % 8 != 0) + { + /* + * Check that +1 byte would fit in the destination buffer. + * Ensure future size read access will not go out of bounds. + */ + if((size_written / 8) + 1 <= max_len) + { + size_written = (size_written / 8) + 1; + } + } + else + { + size_written = size_written / 8; + } + +end_of_function: + return size_written; +} + + +bool explain_load_memory_map(const char *filepath, explain_data_t *handle) +{ + bool returnBool = true; + uint32_t recursive_count = 0; + + /* Null pointer checks. */ + if(0 == filepath || 0 == handle) + { + returnBool = false; + printf("Null pointer in explain_load_memory_map\n"); + goto end_of_function; + } + + returnBool = read_input(filepath, &handle->rawInput[0]); + if(false == returnBool) + { + goto end_of_function; + } + + /* TODO error checking + * convert to json_tokener_parse_ex + * */ + json_object * jobj = json_tokener_parse(&handle->rawInput[0]); + returnBool = json_parse(jobj, &recursive_count, handle); + +end_of_function: + return returnBool; +} + + +bool explain_init_data(explain_data_t *app_data) +{ + + bool returnBool = true; + /* Null pointer checks. */ + if(0 != app_data) + { + /* Initialize application data. */ + memset((void*)app_data, 0x00, sizeof(app_data)); + /* Initialize linked list. */ + explain_message_init(&app_data->message_list); + /* Get the first message. */ + app_data->currentMsg = explain_message_add(&app_data->message_list); + /* */ + if (0 == app_data->currentMsg) + { + returnBool = false; + } + } + else + { + returnBool = false; + printf("Null pointer in explain_init_data\n"); + } + + return returnBool; +} + + +void explain_uninit_data(explain_data_t *app_data) +{ + /* Null pointer checks. */ + if(0 != app_data) + { + explain_message_deinit(&app_data->message_list); + } + else + { + printf("Null pointer in explain_uninit_data\n"); + } +} + + diff --git a/src/input.json b/src/input.json new file mode 100644 index 0000000..dad65d1 --- /dev/null +++ b/src/input.json @@ -0,0 +1,96 @@ +{ + "bitmap": [ + { + "dst_symbol": "CI_HkTlm_t", + "fields": [ + { + "length": 88, + "src_offset": 0, + "op_name": "TlmHeader", + "dst_offset": 0 + }, + { + "length": 8, + "src_offset": 96, + "op_name": "usCmdCnt", + "dst_offset": 96 + }, + { + "length": 8, + "src_offset": 104, + "op_name": "usCmdErrCnt", + "dst_offset": 104 + }, + { + "length": 8, + "src_offset": 112, + "op_name": "padding", + "dst_offset": 112 + }, + { + "length": 8, + "src_offset": 128, + "op_name": "IngestMsgCount", + "dst_offset": 128 + }, + { + "length": 8, + "src_offset": 136, + "op_name": "IngestErrorCount", + "dst_offset": 136 + } + ], + "ops_name": "test1", + "src_endian": "L", + "src_symbol": "CI_HkTlm_t", + "id": "123", + "dst_endian": "L" + }, + { + "dst_symbol": "CI_HkTlm_t", + "fields": [ + { + "length": 88, + "src_offset": 0, + "op_name": "TlmHeader", + "dst_offset": 0 + }, + { + "length": 8, + "src_offset": 96, + "op_name": "usCmdCnt", + "dst_offset": 96 + }, + { + "length": 8, + "src_offset": 104, + "op_name": "usCmdErrCnt", + "dst_offset": 104 + }, + { + "length": 8, + "src_offset": 112, + "op_name": "padding", + "dst_offset": 112 + }, + { + "length": 8, + "src_offset": 128, + "op_name": "IngestMsgCount", + "dst_offset": 128 + }, + { + "length": 8, + "src_offset": 136, + "op_name": "IngestErrorCount", + "dst_offset": 136 + } + ], + "ops_name": "test2", + "src_endian": "L", + "src_symbol": "CI_HkTlm_t", + "id": "1234", + "dst_endian": "L" + } + ] +} diff --git a/src/list.c b/src/list.c new file mode 100644 index 0000000..e19a419 --- /dev/null +++ b/src/list.c @@ -0,0 +1,330 @@ +/* + * Copyright (c) 2004, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + * Author: Adam Dunkels + * + */ + +/** + * \file + * Linked list library implementation. + * + * \author Adam Dunkels + * + */ + +/** + * \addtogroup list + * @{ + */ + +#include "list.h" + +#define NULL 0 + +struct list { + struct list *next; +}; + +/*---------------------------------------------------------------------------*/ +/** + * Initialize a list. + * + * This function initalizes a list. The list will be empty after this + * function has been called. + * + * \param list The list to be initialized. + */ +void +list_init(list_t list) +{ + *list = NULL; +} +/*---------------------------------------------------------------------------*/ +/** + * Get a pointer to the first element of a list. + * + * This function returns a pointer to the first element of the + * list. The element will \b not be removed from the list. + * + * \param list The list. + * \return A pointer to the first element on the list. + * + * \sa list_tail() + */ +void * +list_head(list_t list) +{ + return *list; +} +/*---------------------------------------------------------------------------*/ +/** + * Duplicate a list. + * + * This function duplicates a list by copying the list reference, but + * not the elements. + * + * \note This function does \b not copy the elements of the list, but + * merely duplicates the pointer to the first element of the list. + * + * \param dest The destination list. + * \param src The source list. + */ +void +list_copy(list_t dest, list_t src) +{ + *dest = *src; +} +/*---------------------------------------------------------------------------*/ +/** + * Get the tail of a list. + * + * This function returns a pointer to the elements following the first + * element of a list. No elements are removed by this function. + * + * \param list The list + * \return A pointer to the element after the first element on the list. + * + * \sa list_head() + */ +void * +list_tail(list_t list) +{ + struct list *l; + + if(*list == NULL) { + return NULL; + } + + for(l = *list; l->next != NULL; l = l->next); + + return l; +} +/*---------------------------------------------------------------------------*/ +/** + * Add an item at the end of a list. + * + * This function adds an item to the end of the list. + * + * \param list The list. + * \param item A pointer to the item to be added. + * + * \sa list_push() + * + */ +void +list_add(list_t list, void *item) +{ + struct list *l; + + /* Make sure not to add the same element twice */ + list_remove(list, item); + + ((struct list *)item)->next = NULL; + + l = list_tail(list); + + if(l == NULL) { + *list = item; + } else { + l->next = item; + } +} +/*---------------------------------------------------------------------------*/ +/** + * Add an item to the start of the list. + */ +void +list_push(list_t list, void *item) +{ + /* struct list *l;*/ + + /* Make sure not to add the same element twice */ + list_remove(list, item); + + ((struct list *)item)->next = *list; + *list = item; +} +/*---------------------------------------------------------------------------*/ +/** + * Remove the last object on the list. + * + * This function removes the last object on the list and returns it. + * + * \param list The list + * \return The removed object + * + */ +void * +list_chop(list_t list) +{ + struct list *l, *r; + + if(*list == NULL) { + return NULL; + } + if(((struct list *)*list)->next == NULL) { + l = *list; + *list = NULL; + return l; + } + + for(l = *list; l->next->next != NULL; l = l->next); + + r = l->next; + l->next = NULL; + + return r; +} +/*---------------------------------------------------------------------------*/ +/** + * Remove the first object on a list. + * + * This function removes the first object on the list and returns a + * pointer to it. + * + * \param list The list. + * \return Pointer to the removed element of list. + */ +/*---------------------------------------------------------------------------*/ +void * +list_pop(list_t list) +{ + struct list *l; + l = *list; + if(*list != NULL) { + *list = ((struct list *)*list)->next; + } + + return l; +} +/*---------------------------------------------------------------------------*/ +/** + * Remove a specific element from a list. + * + * This function removes a specified element from the list. + * + * \param list The list. + * \param item The item that is to be removed from the list. + * + */ +/*---------------------------------------------------------------------------*/ +void +list_remove(list_t list, void *item) +{ + struct list *l, *r; + + if(*list == NULL) { + return; + } + + r = NULL; + for(l = *list; l != NULL; l = l->next) { + if(l == item) { + if(r == NULL) { + /* First on list */ + *list = l->next; + } else { + /* Not first on list */ + r->next = l->next; + } + l->next = NULL; + return; + } + r = l; + } +} +/*---------------------------------------------------------------------------*/ +/** + * Get the length of a list. + * + * This function counts the number of elements on a specified list. + * + * \param list The list. + * \return The length of the list. + */ +/*---------------------------------------------------------------------------*/ +int +list_length(list_t list) +{ + struct list *l; + int n = 0; + + for(l = *list; l != NULL; l = l->next) { + ++n; + } + + return n; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Insert an item after a specified item on the list + * \param list The list + * \param previtem The item after which the new item should be inserted + * \param newitem The new item that is to be inserted + * \author Adam Dunkels + * + * This function inserts an item right after a specified + * item on the list. This function is useful when using + * the list module to ordered lists. + * + * If previtem is NULL, the new item is placed at the + * start of the list. + * + */ +void +list_insert(list_t list, void *previtem, void *newitem) +{ + if(previtem == NULL) { + list_push(list, newitem); + } else { + + ((struct list *)newitem)->next = ((struct list *)previtem)->next; + ((struct list *)previtem)->next = newitem; + } +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Get the next item following this item + * \param item A list item + * \returns A next item on the list + * + * This function takes a list item and returns the next + * item on the list, or NULL if there are no more items on + * the list. This function is used when iterating through + * lists. + */ +void * +list_item_next(void *item) +{ + return item == NULL? NULL: ((struct list *)item)->next; +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/src/memtools.c b/src/memtools.c new file mode 100644 index 0000000..6053082 --- /dev/null +++ b/src/memtools.c @@ -0,0 +1,166 @@ +/**************************************************************************** +* +* Copyright (c) 2017 Windhover Labs, L.L.C. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* 3. Neither the name Windhover Labs nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ +#include +#include +#include + +/* TODO refactor. */ +/* +#define PREPARE_FIRST_COPY() \ + do { \ + if (bit_len >= (CHAR_BIT - dst_offset_modulo)) { \ + *dst &= reverse_mask[dst_offset_modulo]; \ + bit_len -= CHAR_BIT - dst_offset_modulo; \ + } else { \ + *dst &= reverse_mask[dst_offset_modulo] \ + | reverse_mask_xor[dst_offset_modulo + bit_len + 1];\ + c &= reverse_mask[dst_offset_modulo + bit_len ];\ + bit_len = 0; \ + } } while (0) +*/ + +void memcpy_bitwise(char *dst_buf, unsigned int dst_offset, const char *src_buf, unsigned int src_offset, unsigned int bit_len) +{ + + //static const uint8 mask[] = + // { 0x55, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff }; + static const char reverse_mask[] = + { 0x55, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff }; + static const char reverse_mask_xor[] = + { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01, 0x00 }; + + /* Null check */ + if (0 == src_buf || 0 == dst_buf) + { + goto end_of_function; + } + + if (bit_len) + { + const char *src; + char *dst; + int src_offset_modulo; + int dst_offset_modulo; + + src = src_buf + (src_offset / CHAR_BIT); + dst = dst_buf + (dst_offset / CHAR_BIT); + + src_offset_modulo = src_offset % CHAR_BIT; + dst_offset_modulo = dst_offset % CHAR_BIT; + + if (src_offset_modulo == dst_offset_modulo) + { + int byte_len; + int src_len_modulo; + if (src_offset_modulo) + { + char c; + c = reverse_mask_xor[dst_offset_modulo] & *src++; + //PREPARE_FIRST_COPY(); + *dst++ |= c; + } + + byte_len = bit_len / CHAR_BIT; + src_len_modulo = bit_len % CHAR_BIT; + + if (byte_len) + { + memcpy(dst, src, byte_len); + src += byte_len; + dst += byte_len; + } + + if (src_len_modulo) + { + *dst &= reverse_mask_xor[src_len_modulo]; + *dst |= reverse_mask[src_len_modulo] & *src; + } + + } + else + { + int bit_diff_ls; + int bit_diff_rs; + int byte_len; + int src_len_modulo; + char c; + + /* Begin: Line things up on destination. */ + if (src_offset_modulo > dst_offset_modulo) + { + bit_diff_ls = src_offset_modulo - dst_offset_modulo; + bit_diff_rs = CHAR_BIT - bit_diff_ls; + + c = *src++ << bit_diff_ls; + c |= *src >> bit_diff_rs; + c &= reverse_mask_xor[dst_offset_modulo]; + } + else + { + bit_diff_rs = dst_offset_modulo - src_offset_modulo; + bit_diff_ls = CHAR_BIT - bit_diff_rs; + + c = *src >> bit_diff_rs & + reverse_mask_xor[dst_offset_modulo]; + } + + //PREPARE_FIRST_COPY(); + *dst++ |= c; + + /* Middle: copy with only shifting the source. */ + byte_len = bit_len / CHAR_BIT; + + while (--byte_len >= 0) + { + c = *src++ << bit_diff_ls; + c |= *src >> bit_diff_rs; + *dst++ = c; + } + + /* End: copy the remaing bits. */ + src_len_modulo = bit_len % CHAR_BIT; + + if (src_len_modulo) + { + c = *src++ << bit_diff_ls; + c |= *src >> bit_diff_rs; + c &= reverse_mask[src_len_modulo]; + + *dst &= reverse_mask_xor[src_len_modulo]; + *dst |= c; + } + } + } +end_of_function: + return; +} diff --git a/src/message.c b/src/message.c new file mode 100644 index 0000000..b1b1b66 --- /dev/null +++ b/src/message.c @@ -0,0 +1,353 @@ +/**************************************************************************** +* +* Copyright (c) 2017 Windhover Labs, L.L.C. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* 3. Neither the name Windhover Labs nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ +#include "message.h" +#include +#include +#include + + +/* Initialize a message. */ +static void message_clear(explain_msg_t *msg_ptr); + + +/* Allocate a new message. */ +static explain_msg_t *message_allocate(void); + + +/* Allocate a new field. */ +static explain_field_t *field_allocate(void); + + +/* Cleanup all messages. */ +static void purge_messages(explain_msg_list_t *handle); + + +/* Free a message. */ +static void message_free(explain_msg_t *msg_ptr); + + +/* Free a field. */ +static void field_free(explain_field_t *field_ptr); + + +void explain_message_init(explain_msg_list_t *handle) +{ + /* Initialize the outer linked list. */ + LIST_STRUCT_INIT(handle, messages); +} + + +void explain_message_deinit(explain_msg_list_t *handle) +{ + purge_messages(handle); +} + + +static void message_clear(explain_msg_t *msg_ptr) +{ + /* Initialize the inner linked list. */ + LIST_STRUCT_INIT(msg_ptr, fields); +} + + +static explain_msg_t *message_allocate(void) +{ + explain_msg_t *msg_ptr = NULL; + + msg_ptr = (explain_msg_t*) malloc(sizeof(explain_msg_t)); + if(NULL == msg_ptr) + { + /* TODO error condition */ + printf("message_allocate failed\n"); + goto end_of_function; + } + +end_of_function: + + return (msg_ptr); + +} + + +static explain_field_t *field_allocate(void) +{ + explain_field_t *field_ptr = NULL; + + field_ptr = (explain_field_t*) malloc(sizeof(explain_field_t)); + if(NULL == field_ptr) + { + /* TODO error condition */ + printf("field_allocate failed\n"); + } + + return (field_ptr); +} + + +explain_msg_t *explain_message_add(explain_msg_list_t *handle) +{ + explain_msg_t *msg_ptr = NULL; + + if(0 == handle) + { + printf("Null pointer in message message_add\n"); + goto end_of_function; + } + + msg_ptr = message_allocate(); + if(NULL == msg_ptr) + { + /* TODO error condition */ + printf("message_add failed\n"); + goto end_of_function; + } + + /* Initialize the allocated message. */ + message_clear(msg_ptr); + + /* Add the new message to the list. */ + list_add(handle->messages, msg_ptr); + +end_of_function: + return msg_ptr; +} + + +explain_field_t *explain_field_add(explain_msg_t *msg_ptr, const explain_field_t *addition) +{ + explain_field_t *field_ptr = NULL; + + if(0 == msg_ptr || 0 == addition) + { + printf("Null pointer in message field_add\n"); + goto end_of_function; + } + + field_ptr = field_allocate(); + if(NULL == field_ptr) + { + /* TODO error condition */ + printf("field_add failed\n"); + goto end_of_function; + } + + /* Copy fields. */ + memcpy(field_ptr, addition, sizeof(explain_field_t)); + + /* Add the new field to the list. */ + list_add(msg_ptr->fields, field_ptr); + +end_of_function: + return field_ptr; +} + + +static void purge_messages(explain_msg_list_t *handle) +{ + explain_msg_t *msg_ptr = NULL; + explain_msg_t *msg_next = NULL; + + for(msg_ptr = list_head(handle->messages); msg_ptr != NULL;) + { + msg_next = msg_ptr->next; + message_free(msg_ptr); + msg_ptr = msg_next; + } +} + + +static void message_free(explain_msg_t *msg_ptr) +{ + explain_field_t *field_ptr = NULL; + + if(0 != msg_ptr) + { + while((field_ptr = list_pop(msg_ptr->fields)) != NULL) + { + field_free(field_ptr); + } + + free(msg_ptr); + } + else + { + printf("Null pointer in message free\n"); + } +} + + +static void field_free(explain_field_t *field_ptr) +{ + if(0 != field_ptr) + { + free(field_ptr); + } + else + { + printf("Null pointer in field free\n"); + } +} + + +explain_msg_t * explain_message_find_via_id(unsigned int id, explain_msg_list_t *handle) +{ + explain_msg_t *msg_ptr = NULL; + + if(0 == handle) + { + printf("Null pointer in message_find_via_id\n"); + goto end_of_function; + } + + for(msg_ptr = list_head(handle->messages); + msg_ptr != NULL; + msg_ptr = list_item_next(msg_ptr)) + { + if(id == msg_ptr->id) + { + return msg_ptr; + } + } + +end_of_function: + return NULL; +} + + +explain_msg_t * explain_message_find_via_name(const char *ops_name, explain_msg_list_t *handle) +{ + explain_msg_t *msg_ptr = NULL; + + if(0 == handle || 0 == ops_name) + { + printf("Null pointer in message_find_via_name\n"); + goto end_of_function; + } + + for(msg_ptr = list_head(handle->messages); + msg_ptr != NULL; + msg_ptr = list_item_next(msg_ptr)) + { + if(0 == strcmp(msg_ptr->opsName, ops_name)) + { + return msg_ptr; + } + } + +end_of_function: + return NULL; +} + + +explain_msg_t * explain_message_find_via_src_symbol(const char *src_symbol, explain_msg_list_t *handle) +{ + explain_msg_t *msg_ptr = NULL; + + if(0 == handle || 0 == src_symbol) + { + printf("Null pointer in message_find_via_src_symbol\n"); + goto end_of_function; + } + + for(msg_ptr = list_head(handle->messages); + msg_ptr != NULL; + msg_ptr = list_item_next(msg_ptr)) + { + if(0 == strcmp(msg_ptr->srcSymbol, src_symbol)) + { + return msg_ptr; + } + } + +end_of_function: + return NULL; +} + + +explain_msg_t * explain_message_find_via_dst_symbol(const char *dst_symbol, explain_msg_list_t *handle) +{ + explain_msg_t *msg_ptr = NULL; + + if(0 == handle || 0 == dst_symbol) + { + printf("Null pointer in message_find_via_dst_symbol\n"); + goto end_of_function; + } + + for(msg_ptr = list_head(handle->messages); + msg_ptr != NULL; + msg_ptr = list_item_next(msg_ptr)) + { + if(0 == strcmp(msg_ptr->dstSymbol, dst_symbol)) + { + return msg_ptr; + } + } + +end_of_function: + return NULL; +} + + +void explain_print_all_fields(explain_msg_list_t *handle) +{ + explain_field_t *field_ptr = NULL; + explain_msg_t *msg_ptr = NULL; + + for(msg_ptr = list_head(handle->messages); + msg_ptr != NULL; + msg_ptr = list_item_next(msg_ptr)) + { + /* Print the message info. */ + printf("opsName %s\n", msg_ptr->opsName); + printf("dstSymbol %s\n", msg_ptr->dstSymbol); + printf("srcSymbol %s\n", msg_ptr->srcSymbol); + printf("srcEndian %d\n", msg_ptr->srcEndian); + printf("dstEndian %d\n", msg_ptr->dstEndian); + printf("id %d\n", msg_ptr->id); + + /* Print all the field info. */ + for(field_ptr = list_head(msg_ptr->fields); + field_ptr != NULL; + field_ptr = list_item_next(field_ptr)) + { + printf("opName %s\n", field_ptr->opName); + printf("length %u\n", field_ptr->length); + printf("srcOffset %u\n", field_ptr->srcOffset); + printf("dstOffset %u\n", field_ptr->dstOffset); + } + } +} + + + diff --git a/src/obj/.gitkeep b/src/obj/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/parser.c b/src/parser.c new file mode 100644 index 0000000..7f7b486 --- /dev/null +++ b/src/parser.c @@ -0,0 +1,360 @@ +/**************************************************************************** +* +* Copyright (c) 2017 Windhover Labs, L.L.C. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* 3. Neither the name Windhover Labs nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ +#include "parser.h" +#include +#include + + +bool json_parse(json_object * jobj, unsigned int *call_count, explain_data_t *handle) +{ + enum json_type type = 0; + bool returnBool = false; + + /* Null pointer check */ + if(0 == jobj || 0 == call_count) + { + goto end_of_function; + } + + /* Recursive call stack depth check */ + if (*call_count >= MAX_RECURSIVE_CALL_COUNT) + { + printf("Recursive call stack exceeded %d\n", *call_count); + goto end_of_function; + } + else + { + *call_count = *call_count + 1; + } + + json_object_object_foreach(jobj, key, val) + { + type = json_object_get_type(val); + + switch (type) + { + case json_type_boolean: + { + printf("Unknown json type boolean in parser\n"); + break; + } + case json_type_double: + { + printf("Unknown json type double in parser\n"); + break; + } + case json_type_int: + { + returnBool = parse_json_value(val, key, handle); + break; + } + case json_type_string: + { + returnBool = parse_json_value(val, key, handle); + break; + } + case json_type_object: + { + printf("Unknown json type object in parser\n"); + //jobj = json_object_object_get(jobj, key); + //json_parse(jobj, state, cursor); + break; + } + case json_type_array: + { + //printf("json_type_array\n"); + returnBool = json_parse_array(jobj, key, call_count, handle); + break; + } + default : + { + printf("Unkown json type in parser\n"); + } + } + } + +end_of_function: + return (returnBool); +} + + +bool json_parse_array(json_object *jobj, const char *key, unsigned int *call_count, explain_data_t *handle) +{ + unsigned int i = 0; + enum json_type type = 0; + bool returnBool = false; + + /* Null pointer check */ + if(0 == jobj || 0 == key || 0 == call_count) + { + goto end_of_function; + } + + /* Recursive call stack depth check */ + if (*call_count >= MAX_RECURSIVE_CALL_COUNT) + { + printf("Recursive call stack exceeded in array %d\n", *call_count); + goto end_of_function; + } + else + { + *call_count = *call_count + 1; + } + + json_object *jarray = jobj; + + /* Simply get the array. */ + if(key) + { + /* Getting the array if it is a key value pair. */ + jarray = json_object_object_get(jobj, key); + } + + /* Getting the length of the array. */ + int arraylen = json_object_array_length(jarray); + //printf("Array Length: %d\n", arraylen); + + json_object * jvalue; + + for (i = 0; i < arraylen; ++i) + { + /* Getting the array element at position i */ + jvalue = json_object_array_get_idx(jarray, i); + type = json_object_get_type(jvalue); + + if (type == json_type_array) + { + returnBool = json_parse_array(jvalue, NULL, call_count, handle); + } + else if (type != json_type_object) + { + parse_json_value(jvalue, key, handle); + } + else + { + returnBool = json_parse(jvalue, call_count, handle); + } + } + +end_of_function: + return (returnBool); +} + + +bool parse_json_value(json_object *jobj, const char* key, explain_data_t *handle) +{ + enum json_type type = 0; + bool returnBool = false; + + /* Null pointer check */ + if(0 == jobj || 0 == key) + { + goto end_of_function; + } + + /* Getting the type of the json object */ + type = json_object_get_type(jobj); + switch (type) + { + case json_type_boolean: + { + printf("Unknown json type boolean in parser\n"); + break; + } + case json_type_double: + { + printf("Unknown json type double in parser\n"); + break; + } + case json_type_int: + { + returnBool = load_int(jobj, key, handle); + break; + } + case json_type_string: + { + returnBool = load_string(jobj, key, handle); + break; + } + default : + { + printf("Unkown json type value in parser\n"); + } + } + +end_of_function: + return (returnBool); +} + + +bool load_int(json_object * jobj, const char *key, explain_data_t *handle) +{ + bool returnBool = false; + int value = json_object_get_int(jobj); + + /* Null pointer check */ + if(0 == jobj || 0 == key) + { + goto end_of_function; + } + + if (0 == strncmp(key, LENGTH_KEY, MAX_KEY_LENGTH)) + { + //printf("got key fields length %d\n", value); + handle->currentField.length = value; + returnBool = true; + } + else if (0 == strncmp(key, SOURCE_OFFSET_KEY, MAX_KEY_LENGTH)) + { + //printf("got key fields source %d\n", value); + handle->currentField.srcOffset = value; + returnBool = true; + } + else if (0 == strncmp(key, DESTINATION_OFFSET_KEY, MAX_KEY_LENGTH)) + { + //printf("got key fields destination %d\n", value); + handle->currentField.dstOffset = value; + /* For now assume a field is complete. */ + /* TODO error checking. */ + (void) explain_field_add(handle->currentMsg, &handle->currentField); + returnBool = true; + } + else + { + /* Error state */ + printf("got unknown key in load_int %s\n", key); + + } + +end_of_function: + return (returnBool); +} + + +bool load_string(json_object * jobj, const char *key, explain_data_t *handle) +{ + bool returnBool = FALSE; + const char *value = json_object_get_string(jobj); + + /* Null pointer check */ + if(0 == jobj || 0 == key) + { + goto end_of_function; + } + + /* Check keys for known values */ + if (0 == strncmp(key, IDENTIFICATION_KEY, MAX_KEY_LENGTH)) + { + handle->currentMsg->id = strtoul(value, NULL, 16); + //printf("got key bitmap id %d\n", handle->currentMsg->id); + returnBool = true; + } + else if (0 == strncmp(key, DESTINATION_SYMBOL, MAX_KEY_LENGTH)) + { + strncpy(handle->currentMsg->dstSymbol, value, EXPLAIN_MAX_OPS_NAME_LENGTH); + //printf("got key bitmap dest symbol %s\n", handle->currentMsg->opsName); + returnBool = true; + } + else if (0 == strncmp(key, SOURCE_SYMBOL, MAX_KEY_LENGTH)) + { + strncpy(handle->currentMsg->srcSymbol, value, EXPLAIN_MAX_OPS_NAME_LENGTH); + //printf("got key bitmap src symbol %s\n", handle->currentMsg->opsName); + returnBool = true; + } + else if (0 == strncmp(key, OPS_MESSAGE_NAME_KEY, MAX_KEY_LENGTH)) + { + strncpy(handle->currentMsg->opsName, value, EXPLAIN_MAX_OPS_NAME_LENGTH); + //printf("got key bitmap ops_name %s\n", handle->currentMsg->opsName); + returnBool = true; + } + else if (0 == strncmp(key, OPS_FIELD_NAME_KEY, MAX_KEY_LENGTH)) + { + strncpy(handle->currentField.opName, value, EXPLAIN_MAX_OPS_NAME_LENGTH); + //printf("got key field op_name %s\n", handle->currentField.opName); + returnBool = true; + } + else if (0 == strncmp(key, SOURCE_ENDIANNESS_KEY, MAX_KEY_LENGTH)) + { + /* Decode endianess. */ + if(0 == strncmp(value, LITTLE_ENDIAN_VALUE, MAX_ENDIANNESS_LENGTH)) + { + handle->currentMsg->srcEndian = EXPLAIN_LITTLE_ENDIAN; + returnBool = true; + } + else if (0 == strncmp(value, BIG_ENDIAN_VALUE, MAX_ENDIANNESS_LENGTH)) + { + handle->currentMsg->srcEndian = EXPLAIN_BIG_ENDIAN; + returnBool = true; + } + else + { + /* TODO error condition unknown endianness value. */ + printf("Unknown endianness value in parser, got %s\n", value); + } + //printf("got key field src endian %d\n", app_data.currentMsg->srcEndian); + } + else if (0 == strncmp(key, DEST_ENDIANNESS_KEY, MAX_KEY_LENGTH)) + { + /* Decode endianness. */ + if(0 == strncmp(value, LITTLE_ENDIAN_VALUE, MAX_ENDIANNESS_LENGTH)) + { + handle->currentMsg->dstEndian = EXPLAIN_LITTLE_ENDIAN; + returnBool = true; + } + else if (0 == strncmp(value, BIG_ENDIAN_VALUE, MAX_ENDIANNESS_LENGTH)) + { + handle->currentMsg->dstEndian = EXPLAIN_BIG_ENDIAN; + returnBool = true; + } + else + { + /* TODO error condition unknown endianness value. */ + printf("Unknown endianness value in parser, got %s\n", value); + } + //printf("got key field dst endian %d\n", app_data.currentMsg->dstEndian); + /* For now assume we've completed a message. */ + /* Add a new message. */ + handle->currentMsg = explain_message_add(&handle->message_list); + } + else + { + /* Error state */ + printf("got unknown key in load_string %s\n", key); + } + +end_of_function: + return (returnBool); +} + + + diff --git a/src/usage.c b/src/usage.c new file mode 100644 index 0000000..a3de84f --- /dev/null +++ b/src/usage.c @@ -0,0 +1,109 @@ +/**************************************************************************** +* +* Copyright (c) 2017 Windhover Labs, L.L.C. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* 3. Neither the name Windhover Labs nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ +#include +#include +#include +#include +#include +#include +#include "config.h" +#include "usage.h" + + +/* Application long options. */ +static struct option longopts[] = +{ + /* Long help option -help. */ + {"help", no_argument, NULL, OPT_HELP}, + /* Long path option -path. */ + {"path", required_argument, NULL, OPT_PATH}, + /* Null. */ + {0, 0, 0, 0} +}; + + +void usage(void) +{ + printf("explain 0.0.0 requires a json file path argument\n"); + printf("Parameters with '=' requires an argument\n"); + printf("[ Example ]\n"); + printf(" ./explain -p input.json\n"); + printf("[ Options ]\n"); + printf(" --path= : Specify the json input file\n"); + printf(" --help : Print this help\n"); + exit(EXIT_SUCCESS); +} + + +bool parse_options(char *inputPath, int argc, char **argv) +{ + int ch = 0; + bool returnBool = false; + + assert(inputPath); + + /* make -p input.json required */ + if (argc == 1) + { + usage(); + goto end_of_function; + } + + while ((ch = getopt_long(argc, argv, "hp:", longopts, NULL)) != -1) + { + switch(ch) + { + case OPT_HELP: + { + usage(); + break; + } + case OPT_PATH: + { + (void) strncpy(inputPath, optarg, EXPLAIN_MAX_PATH_LENGTH); + returnBool = true; + break; + } + default: + { + usage(); + break; + } + } + } + +end_of_function: + + return returnBool; +} + diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 0000000..1a292be --- /dev/null +++ b/src/utils.c @@ -0,0 +1,111 @@ +/**************************************************************************** +* +* Copyright (c) 2017 Windhover Labs, L.L.C. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* 3. Neither the name Windhover Labs nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ +#include "cfe_sb.h" +#include +#include +#include +#include +#include +#include +#include "utils.h" + + +bool validate_path(const char *inputPath) +{ + struct stat fileStat; + bool returnBool = false; + int returnVal = -1; + + returnVal = stat(inputPath, &fileStat); + + if (returnVal < 0) + { + goto end_of_function; + } + else + { + returnBool = true; + } + + /* TODO add additional validation */ + +end_of_function: + return returnBool; +} + + +bool read_input(const char* filePath, char* fileContent) +{ + FILE *f = 0; + char c = 0; + int index = 0; + boolean returnBool = true; + + f = fopen(filePath, "rt"); + if (NULL == f) + { + printf("fopen returned errno %d\n", errno); + returnBool = false; + goto end_of_function; + } + + while((c = fgetc(f)) != EOF) + { + fileContent[index] = c; + index++; + } + + fileContent[index] = '\0'; + +end_of_function: + return returnBool; +} + + +unsigned int get_ccsds_msg_id(const char *input) +{ + CFE_SB_Msg_t* MsgPtr = (CFE_SB_MsgPtr_t) input; + unsigned int id = 0; + + /* Null pointer checks */ + if (0 == input) + { + goto end_of_function; + } + + /* Get the CCSDS message id */ + id = CFE_SB_GetMsgId(MsgPtr); + +end_of_function: + return id; +} diff --git a/test/explain_app_test.c b/test/explain_app_test.c new file mode 100644 index 0000000..7876f76 --- /dev/null +++ b/test/explain_app_test.c @@ -0,0 +1,995 @@ +/**************************************************************************** +* +* Copyright (c) 2017 Windhover Labs, L.L.C. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* 3. Neither the name Windhover Labs nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ + +#include "explain_app_test.h" +#include "../include/explain.h" +#include "../include/memtools.h" +#include "explain_test_utils.h" +#include "utils.h" +#include +#include "cfe_sb.h" +#include + +#define EXPLAIN_TEST_INPUT_PATH "test_input.json" + +/* Test structure for source. Note uint8 padding. */ +typedef struct +{ + uint8 TlmHeader[CFE_SB_TLM_HDR_SIZE]; + uint16 synch; + + uint8 padding; + + uint8 bit1:1; + uint8 bit2:1; + uint8 bit34:2; + uint8 bit56:2; + uint8 bit78:2; + + uint8 nibble1:4; + uint8 nibble2:4; + + uint8 bl1, bl2; /* boolean */ + int8 b1, b2, b3, b4; + int16 w1,w2; + int32 dw1, dw2; + float f1, f2; + double df1, df2; + char str[10]; +} test_data_types_src; + +/* Test structure for destination. Note uint16 padding. */ +typedef struct +{ + uint8 TlmHeader[CFE_SB_TLM_HDR_SIZE]; + uint16 synch; + + uint16 padding; + + uint8 bit1:1; + uint8 bit2:1; + uint8 bit34:2; + uint8 bit56:2; + uint8 bit78:2; + + uint8 nibble1:4; + uint8 nibble2:4; + /* boolean */ + uint8 bl1, bl2; + int8 b1, b2, b3, b4; + int16 w1,w2; + int32 dw1, dw2; + float f1, f2; + double df1, df2; + + char str[10]; +} test_data_types_dst; + + +typedef struct +{ + uint8 bit1:1; + uint8 bit2:1; + uint8 bit34:2; + uint8 bit5678:4; + uint8 padding; +} test_data_bit_fields; + + +void Explain_Test_Offsets(void) +{ + /* Input and output packets for test. */ + test_data_types_src src_pkt; + test_data_types_dst dst_pkt; + /* Pointers to input and output structs. */ + uint8 *src_ptr = (uint8 *) &src_pkt; + uint8 *dst_ptr = (uint8 *) &dst_pkt; + uint8 *temp_ptr = NULL; + /* Pointer to the messsage definition. */ + explain_msg_t *msg_map_ptr = NULL; + explain_field_t *field_map_ptr = NULL; + /* Variables for bitfield checks. */ + uint32 src_off_byte = 0; + uint32 dst_off_byte = 0; + uint32 src_off_bit = 0; + uint32 dst_off_bit = 0; + /* Message src symbol name. */ + char src_symbol[] = "test_data_types_src"; + + /* initialize test environment to default state for every test */ + boolean returnBool = FALSE; + explain_data_t app_data; + (void) explain_init_data(&app_data); + + strncpy(&app_data.inputPath[0], EXPLAIN_TEST_INPUT_PATH, EXPLAIN_MAX_PATH_LENGTH); + + returnBool = validate_path(&app_data.inputPath[0]); + if(FALSE == returnBool) + { + printf("validate path failed, exiting\n"); + exit(-1); + } + + returnBool = explain_load_memory_map(&app_data.inputPath[0], &app_data); + if(FALSE == returnBool) + { + printf("load memory map failed, exiting\n"); + /* cleanup test environment */ + explain_uninit_data(&app_data); + exit(-1); + } + + /* Clear buffers. */ + memset(&src_pkt, 0, sizeof(src_pkt)); + memset(&dst_pkt, 0, sizeof(dst_pkt)); + + msg_map_ptr = explain_message_find_via_src_symbol(src_symbol, &app_data.message_list); + + for(field_map_ptr = list_head(msg_map_ptr->fields); + field_map_ptr != NULL; + field_map_ptr = list_item_next(field_map_ptr)) + { + if(0 == strcmp(field_map_ptr->opName, "TlmHeader")) + { + UtAssert_True((offsetof(test_data_types_src, TlmHeader) * 8) + == field_map_ptr->srcOffset, "Test incorrect offset"); + UtAssert_True((offsetof(test_data_types_dst, TlmHeader) * 8) + == field_map_ptr->dstOffset, "Test incorrect offset"); + } + else if(0 == strcmp(field_map_ptr->opName, "synch")) + { + UtAssert_True((offsetof(test_data_types_src, synch) * 8) + == field_map_ptr->srcOffset, "Test incorrect offset"); + UtAssert_True((offsetof(test_data_types_dst, synch) * 8) + == field_map_ptr->dstOffset, "Test incorrect offset"); + } + else if(0 == strcmp(field_map_ptr->opName, "padding")) + { + UtAssert_True((offsetof(test_data_types_src, padding) * 8) + == field_map_ptr->srcOffset, "Test incorrect offset"); + UtAssert_True((offsetof(test_data_types_dst, padding) * 8) + == field_map_ptr->dstOffset, "Test incorrect offset"); + } + else if(0 == strcmp(field_map_ptr->opName, "bit1")) + { + /* Check source by setting a bit. */ + src_off_byte = (field_map_ptr->srcOffset / 8); + src_off_bit = 7 - (field_map_ptr->srcOffset % 8); + dst_off_byte = (field_map_ptr->dstOffset / 8); + dst_off_bit = 7 - (field_map_ptr->dstOffset % 8); + + temp_ptr = src_ptr + src_off_byte; + *temp_ptr |= 1 << src_off_bit; + + temp_ptr = dst_ptr + dst_off_byte; + *temp_ptr |= 1 << dst_off_bit; + + UtAssert_True(1 == src_pkt.bit1, "Test incorrect offset"); + UtAssert_True(1 == dst_pkt.bit1, "Test incorrect offset"); + + /* Clear buffers. */ + memset(&src_pkt, 0, sizeof(src_pkt)); + memset(&dst_pkt, 0, sizeof(dst_pkt)); + + } + else if(0 == strcmp(field_map_ptr->opName, "bit2")) + { + /* Check source by setting a bit. */ + + src_off_byte = (field_map_ptr->srcOffset / 8); + src_off_bit = 7 - (field_map_ptr->srcOffset % 8); + dst_off_byte = (field_map_ptr->dstOffset / 8); + dst_off_bit = 7 - (field_map_ptr->dstOffset % 8); + + temp_ptr = src_ptr + src_off_byte; + *temp_ptr |= 1 << src_off_bit; + + temp_ptr = dst_ptr + dst_off_byte; + *temp_ptr |= 1 << dst_off_bit; + + UtAssert_True(1 == src_pkt.bit2, "Test incorrect offset"); + UtAssert_True(1 == dst_pkt.bit2, "Test incorrect offset"); + /* Clear buffers. */ + memset(&src_pkt, 0, sizeof(src_pkt)); + memset(&dst_pkt, 0, sizeof(dst_pkt)); + } + else if(0 == strcmp(field_map_ptr->opName, "bit34")) + { + /* Check source by setting a bit. */ + src_off_byte = (field_map_ptr->srcOffset / 8); + src_off_bit = 6 - (field_map_ptr->srcOffset % 8); + dst_off_byte = (field_map_ptr->dstOffset / 8); + dst_off_bit = 6 - (field_map_ptr->dstOffset % 8); + + temp_ptr = src_ptr + src_off_byte; + *temp_ptr |= 1 << src_off_bit; + + temp_ptr = dst_ptr + dst_off_byte; + *temp_ptr |= 1 << dst_off_bit; + + UtAssert_True(1 == src_pkt.bit34, "Test incorrect offset"); + UtAssert_True(1 == dst_pkt.bit34, "Test incorrect offset"); + /* Clear buffers. */ + memset(&src_pkt, 0, sizeof(src_pkt)); + memset(&dst_pkt, 0, sizeof(dst_pkt)); + } + else if(0 == strcmp(field_map_ptr->opName, "bit56")) + { + /* Check source by setting a bit. */ + src_off_byte = (field_map_ptr->srcOffset / 8); + src_off_bit = 6 - (field_map_ptr->srcOffset % 8); + dst_off_byte = (field_map_ptr->dstOffset / 8); + dst_off_bit = 6 - (field_map_ptr->dstOffset % 8); + + temp_ptr = src_ptr + src_off_byte; + *temp_ptr |= 1 << src_off_bit; + + temp_ptr = dst_ptr + dst_off_byte; + *temp_ptr |= 1 << dst_off_bit; + + UtAssert_True(1 == src_pkt.bit56, "Test incorrect offset"); + UtAssert_True(1 == dst_pkt.bit56, "Test incorrect offset"); + /* Clear buffers. */ + memset(&src_pkt, 0, sizeof(src_pkt)); + memset(&dst_pkt, 0, sizeof(dst_pkt)); + } + else if(0 == strcmp(field_map_ptr->opName, "bit78")) + { + /* Check source by setting a bit. */ + src_off_byte = (field_map_ptr->srcOffset / 8); + src_off_bit = 6 - (field_map_ptr->srcOffset % 8); + dst_off_byte = (field_map_ptr->dstOffset / 8); + dst_off_bit = 6 - (field_map_ptr->dstOffset % 8); + + temp_ptr = src_ptr + src_off_byte; + *temp_ptr |= 1 << src_off_bit; + + temp_ptr = dst_ptr + dst_off_byte; + *temp_ptr |= 1 << dst_off_bit; + + UtAssert_True(1 == src_pkt.bit78, "Test incorrect offset"); + UtAssert_True(1 == dst_pkt.bit78, "Test incorrect offset"); + /* Clear buffers. */ + memset(&src_pkt, 0, sizeof(src_pkt)); + memset(&dst_pkt, 0, sizeof(dst_pkt)); + } + else if(0 == strcmp(field_map_ptr->opName, "nibble1")) + { + /* Check source by setting a bit. */ + src_off_byte = (field_map_ptr->srcOffset / 8); + src_off_bit = 4 - (field_map_ptr->srcOffset % 8); + dst_off_byte = (field_map_ptr->dstOffset / 8); + dst_off_bit = 4 - (field_map_ptr->dstOffset % 8); + + temp_ptr = src_ptr + src_off_byte; + *temp_ptr |= 1 << src_off_bit; + + temp_ptr = dst_ptr + dst_off_byte; + *temp_ptr |= 1 << dst_off_bit; + + UtAssert_True(1 == src_pkt.nibble1, "Test incorrect offset"); + UtAssert_True(1 == dst_pkt.nibble1, "Test incorrect offset"); + /* Clear buffers. */ + memset(&src_pkt, 0, sizeof(src_pkt)); + memset(&dst_pkt, 0, sizeof(dst_pkt)); + } + else if(0 == strcmp(field_map_ptr->opName, "nibble2")) + { + /* Check source by setting a bit. */ + src_off_byte = (field_map_ptr->srcOffset / 8); + src_off_bit = 4 - (field_map_ptr->srcOffset % 8); + dst_off_byte = (field_map_ptr->dstOffset / 8); + dst_off_bit = 4 - (field_map_ptr->dstOffset % 8); + + temp_ptr = src_ptr + src_off_byte; + *temp_ptr |= 1 << src_off_bit; + + temp_ptr = dst_ptr + dst_off_byte; + *temp_ptr |= 1 << dst_off_bit; + + UtAssert_True(1 == src_pkt.nibble2, "Test incorrect offset"); + UtAssert_True(1 == dst_pkt.nibble2, "Test incorrect offset"); + /* Clear buffers. */ + memset(&src_pkt, 0, sizeof(src_pkt)); + memset(&dst_pkt, 0, sizeof(dst_pkt)); + } + else if(0 == strcmp(field_map_ptr->opName, "bl1")) + { + UtAssert_True((offsetof(test_data_types_src, bl1) * 8) + == field_map_ptr->srcOffset, "Test incorrect offset"); + UtAssert_True((offsetof(test_data_types_dst, bl1) * 8) + == field_map_ptr->dstOffset, "Test incorrect offset"); + } + else if(0 == strcmp(field_map_ptr->opName, "bl2")) + { + UtAssert_True((offsetof(test_data_types_src, bl2) * 8) + == field_map_ptr->srcOffset, "Test incorrect offset"); + UtAssert_True((offsetof(test_data_types_dst, bl2) * 8) + == field_map_ptr->dstOffset, "Test incorrect offset"); + } + else if(0 == strcmp(field_map_ptr->opName, "b1")) + { + UtAssert_True((offsetof(test_data_types_src, b1) * 8) + == field_map_ptr->srcOffset, "Test incorrect offset"); + UtAssert_True((offsetof(test_data_types_dst, b1) * 8) + == field_map_ptr->dstOffset, "Test incorrect offset"); + } + else if(0 == strcmp(field_map_ptr->opName, "b2")) + { + UtAssert_True((offsetof(test_data_types_src, b2) * 8) + == field_map_ptr->srcOffset, "Test incorrect offset"); + UtAssert_True((offsetof(test_data_types_dst, b2) * 8) + == field_map_ptr->dstOffset, "Test incorrect offset"); + } + else if(0 == strcmp(field_map_ptr->opName, "b3")) + { + UtAssert_True((offsetof(test_data_types_src, b3) * 8) + == field_map_ptr->srcOffset, "Test incorrect offset"); + UtAssert_True((offsetof(test_data_types_dst, b3) * 8) + == field_map_ptr->dstOffset, "Test incorrect offset"); + } + else if(0 == strcmp(field_map_ptr->opName, "b4")) + { + UtAssert_True((offsetof(test_data_types_src, b4) * 8) + == field_map_ptr->srcOffset, "Test incorrect offset"); + UtAssert_True((offsetof(test_data_types_dst, b4) * 8) + == field_map_ptr->dstOffset, "Test incorrect offset"); + } + else if(0 == strcmp(field_map_ptr->opName, "w1")) + { + UtAssert_True((offsetof(test_data_types_src, w1) * 8) + == field_map_ptr->srcOffset, "Test incorrect offset"); + UtAssert_True((offsetof(test_data_types_dst, w1) * 8) + == field_map_ptr->dstOffset, "Test incorrect offset"); + } + else if(0 == strcmp(field_map_ptr->opName, "w2")) + { + UtAssert_True((offsetof(test_data_types_src, w2) * 8) + == field_map_ptr->srcOffset, "Test incorrect offset"); + UtAssert_True((offsetof(test_data_types_dst, w2) * 8) + == field_map_ptr->dstOffset, "Test incorrect offset"); + } + else if(0 == strcmp(field_map_ptr->opName, "dw1")) + { + UtAssert_True((offsetof(test_data_types_src, dw1) * 8) + == field_map_ptr->srcOffset, "Test incorrect offset"); + UtAssert_True((offsetof(test_data_types_dst, dw1) * 8) + == field_map_ptr->dstOffset, "Test incorrect offset"); + } + else if(0 == strcmp(field_map_ptr->opName, "dw2")) + { + UtAssert_True((offsetof(test_data_types_src, dw2) * 8) + == field_map_ptr->srcOffset, "Test incorrect offset"); + UtAssert_True((offsetof(test_data_types_dst, dw2) * 8) + == field_map_ptr->dstOffset, "Test incorrect offset"); + } + else if(0 == strcmp(field_map_ptr->opName, "f1")) + { + UtAssert_True((offsetof(test_data_types_src, f1) * 8) + == field_map_ptr->srcOffset, "Test incorrect offset"); + UtAssert_True((offsetof(test_data_types_dst, f1) * 8) + == field_map_ptr->dstOffset, "Test incorrect offset"); + } + else if(0 == strcmp(field_map_ptr->opName, "f2")) + { + UtAssert_True((offsetof(test_data_types_src, f2) * 8) + == field_map_ptr->srcOffset, "Test incorrect offset"); + UtAssert_True((offsetof(test_data_types_dst, f2) * 8) + == field_map_ptr->dstOffset, "Test incorrect offset"); + } + else if(0 == strcmp(field_map_ptr->opName, "df1")) + { + UtAssert_True((offsetof(test_data_types_src, df1) * 8) + == field_map_ptr->srcOffset, "Test incorrect offset"); + UtAssert_True((offsetof(test_data_types_dst, df1) * 8) + == field_map_ptr->dstOffset, "Test incorrect offset"); + } + else if(0 == strcmp(field_map_ptr->opName, "df2")) + { + UtAssert_True((offsetof(test_data_types_src, df2) * 8) + == field_map_ptr->srcOffset, "Test incorrect offset"); + UtAssert_True((offsetof(test_data_types_dst, df2) * 8) + == field_map_ptr->dstOffset, "Test incorrect offset"); + } + else if(0 == strcmp(field_map_ptr->opName, "str")) + { + UtAssert_True((offsetof(test_data_types_src, str) * 8) + == field_map_ptr->srcOffset, "Test incorrect offset"); + UtAssert_True((offsetof(test_data_types_dst, str) * 8) + == field_map_ptr->dstOffset, "Test incorrect offset"); + } + else + { + /* Test should not encounter an extra field. */ + UtAssert_True(1 == 2, "Incorrect extra field"); + } + } + + /* cleanup test environment */ + explain_uninit_data(&app_data); +} + + +void Explain_Test_Translation(void) +{ + + /* Input and output buffers. */ + uint8 input_buffer[1024]; + uint8 output_buffer[1024]; + /* Pointers to input and output buffer. */ + uint8 *input_ptr = input_buffer; + uint8 *output_ptr = output_buffer; + /* Input and output packets for test. */ + test_data_types_src input_pkt; + test_data_types_dst output_pkt; + /* Test string. */ + char string_variable[10] = "ABCDEFGHIJ"; + /* Pointer to the messsage definition. */ + explain_msg_t *msg_def = NULL; + /* Message src symbol name. */ + char src_symbol[] = "test_data_types_src"; + int16 i; + /* Size written to destination buffer. */ + int size_written = 0; + + /* initialize test environment to default state for every test */ + boolean returnBool = FALSE; + explain_data_t app_data; + explain_init_data(&app_data); + + strncpy(&app_data.inputPath[0], EXPLAIN_TEST_INPUT_PATH, EXPLAIN_MAX_PATH_LENGTH); + + returnBool = validate_path(&app_data.inputPath[0]); + if(FALSE == returnBool) + { + printf("validate path failed, exiting\n"); + exit(-1); + } + + returnBool = explain_load_memory_map(&app_data.inputPath[0], &app_data); + if(FALSE == returnBool) + { + printf("load memory map failed, exiting\n"); + /* cleanup test environment */ + explain_uninit_data(&app_data); + exit(-1); + } + + /* Clear buffers. */ + memset(&input_buffer, 0, sizeof(input_buffer)); + memset(&output_buffer, 0, sizeof(output_buffer)); + + /* Clear output pkt, input_pkt is cleared in InitMsg. */ + memset(&output_pkt, 0, sizeof(output_pkt)); + + /* Initialize data types packet. */ + CFE_SB_InitMsg(&input_pkt, 0x0881, + sizeof(input_pkt), TRUE); + + /* initialize the packet data with test values. */ + input_pkt.synch = 0x6969; + input_pkt.bit1 = 1; + input_pkt.bit2 = 0; + input_pkt.bit34 = 2; + input_pkt.bit56 = 3; + input_pkt.bit78 = 1; + input_pkt.nibble1 = 0xA; + input_pkt.nibble2 = 0x4; + input_pkt.bl1 = FALSE; + input_pkt.bl2 = TRUE; + input_pkt.b1 = 16; + input_pkt.b2 = 127; + input_pkt.b3 = 0x7F; + input_pkt.b4 = 0x45; + input_pkt.w1 = 0x2468; + input_pkt.w2 = 0x7FFF; + input_pkt.dw1 = 0x12345678; + input_pkt.dw2 = 0x87654321; + input_pkt.f1 = 90.01; + input_pkt.f2 = .0000045; + input_pkt.df1 = 99.9; + input_pkt.df2 = .4444; + + /* Copy the test string. */ + for (i=0; i < 10; ++i) + { + input_pkt.str[i] = string_variable[i]; + } + + /* Copy the test packet into the input buffer. */ + memcpy(&input_buffer, &input_pkt, sizeof(input_pkt)); + + msg_def = explain_message_find_via_src_symbol(src_symbol, &app_data.message_list); + /* Translate the input buffer into the output buffer. */ + size_written = explain_translate_buffer((char *)output_ptr, (char *)input_ptr, msg_def, sizeof(output_buffer), EXPLAIN_FORWARD); + + /* Copy the output buffer to the output packet. */ + memcpy(&output_pkt, output_ptr, sizeof(output_pkt)); + + /* cleanup test environment */ + explain_uninit_data(&app_data); + + /* Check results. */ + UtAssert_True(size_written > 0, "Test incorrect translation"); + UtAssert_True(input_pkt.synch == output_pkt.synch, "Test incorrect translation"); + UtAssert_True(input_pkt.bit1 == output_pkt.bit1, "Test incorrect translation"); + UtAssert_True(input_pkt.bit2 == output_pkt.bit2, "Test incorrect translation"); + UtAssert_True(input_pkt.bit34 == output_pkt.bit34, "Test incorrect translation"); + UtAssert_True(input_pkt.bit56 == output_pkt.bit56, "Test incorrect translation"); + UtAssert_True(input_pkt.bit78 == output_pkt.bit78, "Test incorrect translation"); + UtAssert_True(input_pkt.nibble1 == output_pkt.nibble1, "Test incorrect translation"); + UtAssert_True(input_pkt.nibble2 == output_pkt.nibble2, "Test incorrect translation"); + UtAssert_True(input_pkt.bl1 == output_pkt.bl1, "Test incorrect translation"); + UtAssert_True(input_pkt.bl2 == output_pkt.bl2, "Test incorrect translation"); + UtAssert_True(input_pkt.b1 == output_pkt.b1, "Test incorrect translation"); + UtAssert_True(input_pkt.b2 == output_pkt.b2, "Test incorrect translation"); + UtAssert_True(input_pkt.b3 == output_pkt.b3, "Test incorrect translation"); + UtAssert_True(input_pkt.b4 == output_pkt.b4, "Test incorrect translation"); + UtAssert_True(input_pkt.w1 == output_pkt.w1, "Test incorrect translation"); + UtAssert_True(input_pkt.dw2 == output_pkt.dw2, "Test incorrect translation"); + UtAssert_True(input_pkt.f1 == output_pkt.f1, "Test incorrect translation"); + UtAssert_True(input_pkt.f2 == output_pkt.f2, "Test incorrect translation"); + UtAssert_True(input_pkt.df1 == output_pkt.df1, "Test incorrect translation"); + UtAssert_True(input_pkt.df2 == output_pkt.df2, "Test incorrect translation"); + for(i = 0; i < 10; ++i) + { + UtAssert_True(input_pkt.str[i] == output_pkt.str[i], "Test incorrect reverse translation"); + } +} + + +void Explain_Test_Reverse_Direction(void) +{ + /* Input and output buffers. */ + uint8 input_buffer[1024]; + uint8 output_buffer[1024]; + /* Pointers to input and output buffer. */ + uint8 *input_ptr = input_buffer; + uint8 *output_ptr = output_buffer; + /* Input and output packets for test. */ + /* swap input and output pkts. */ + test_data_types_src output_pkt; + test_data_types_dst input_pkt; + /* Test string. */ + char string_variable[10] = "ABCDEFGHIJ"; + /* Pointer to the messsage definition. */ + explain_msg_t *msg_def = NULL; + /* Message src symbol name. */ + char src_symbol[] = "test_data_types_src"; + int16 i; + /* Size written to destination buffer. */ + int size_written = 0; + + /* initialize test environment to default state for every test */ + boolean returnBool = FALSE; + explain_data_t app_data; + explain_init_data(&app_data); + + strncpy(&app_data.inputPath[0], EXPLAIN_TEST_INPUT_PATH, EXPLAIN_MAX_PATH_LENGTH); + + returnBool = validate_path(&app_data.inputPath[0]); + if(FALSE == returnBool) + { + printf("validate path failed, exiting\n"); + exit(-1); + } + + returnBool = explain_load_memory_map(&app_data.inputPath[0], &app_data); + if(FALSE == returnBool) + { + printf("load memory map failed, exiting\n"); + /* cleanup test environment */ + explain_uninit_data(&app_data); + exit(-1); + } + + /* Clear buffers. */ + memset(&input_buffer, 0, sizeof(input_buffer)); + memset(&output_buffer, 0, sizeof(output_buffer)); + + /* Clear output pkt, input_pkt is cleared in InitMsg. */ + memset(&output_pkt, 0, sizeof(output_pkt)); + + /* Initialize data types packet. */ + CFE_SB_InitMsg(&input_pkt, 0x0881, + sizeof(input_pkt), TRUE); + + /* initialize the packet data with test values. */ + input_pkt.synch = 0x6969; + input_pkt.bit1 = 1; + input_pkt.bit2 = 0; + input_pkt.bit34 = 2; + input_pkt.bit56 = 3; + input_pkt.bit78 = 1; + input_pkt.nibble1 = 0xA; + input_pkt.nibble2 = 0x4; + input_pkt.bl1 = FALSE; + input_pkt.bl2 = TRUE; + input_pkt.b1 = 16; + input_pkt.b2 = 127; + input_pkt.b3 = 0x7F; + input_pkt.b4 = 0x45; + input_pkt.w1 = 0x2468; + input_pkt.w2 = 0x7FFF; + input_pkt.dw1 = 0x12345678; + input_pkt.dw2 = 0x87654321; + input_pkt.f1 = 90.01; + input_pkt.f2 = .0000045; + input_pkt.df1 = 99.9; + input_pkt.df2 = .4444; + + /* Copy the test string. */ + for (i=0; i < 10; ++i) + { + input_pkt.str[i] = string_variable[i]; + } + + /* Copy the test packet into the input buffer. */ + memcpy(&input_buffer, &input_pkt, sizeof(input_pkt)); + + msg_def = explain_message_find_via_src_symbol(src_symbol, &app_data.message_list); + /* Translate the input buffer into the output buffer. */ + size_written = explain_translate_buffer((char *)output_ptr, (char *)input_ptr, msg_def, sizeof(output_buffer), EXPLAIN_REVERSE); + + /* Copy the output buffer to the output packet. */ + memcpy(&output_pkt, output_ptr, sizeof(output_pkt)); + + /* cleanup test environment */ + explain_uninit_data(&app_data); + + /* Check results. */ + UtAssert_True(size_written > 0, "Test incorrect reverse translation"); + UtAssert_True(input_pkt.synch == output_pkt.synch, "Test incorrect reverse translation"); + UtAssert_True(input_pkt.bit1 == output_pkt.bit1, "Test incorrect reverse translation"); + UtAssert_True(input_pkt.bit2 == output_pkt.bit2, "Test incorrect reverse translation"); + UtAssert_True(input_pkt.bit34 == output_pkt.bit34, "Test incorrect reverse translation"); + UtAssert_True(input_pkt.bit56 == output_pkt.bit56, "Test incorrect reverse translation"); + UtAssert_True(input_pkt.bit78 == output_pkt.bit78, "Test incorrect reverse translation"); + UtAssert_True(input_pkt.nibble1 == output_pkt.nibble1, "Test incorrect reverse translation"); + UtAssert_True(input_pkt.nibble2 == output_pkt.nibble2, "Test incorrect reverse translation"); + UtAssert_True(input_pkt.bl1 == output_pkt.bl1, "Test incorrect reverse translation"); + UtAssert_True(input_pkt.bl2 == output_pkt.bl2, "Test incorrect reverse translation"); + UtAssert_True(input_pkt.b1 == output_pkt.b1, "Test incorrect reverse translation"); + UtAssert_True(input_pkt.b2 == output_pkt.b2, "Test incorrect reverse translation"); + UtAssert_True(input_pkt.b3 == output_pkt.b3, "Test incorrect reverse translation"); + UtAssert_True(input_pkt.b4 == output_pkt.b4, "Test incorrect reverse translation"); + UtAssert_True(input_pkt.w1 == output_pkt.w1, "Test incorrect reverse translation"); + UtAssert_True(input_pkt.dw2 == output_pkt.dw2, "Test incorrect reverse translation"); + UtAssert_True(input_pkt.f1 == output_pkt.f1, "Test incorrect reverse translation"); + UtAssert_True(input_pkt.f2 == output_pkt.f2, "Test incorrect reverse translation"); + UtAssert_True(input_pkt.df1 == output_pkt.df1, "Test incorrect reverse translation"); + UtAssert_True(input_pkt.df2 == output_pkt.df2, "Test incorrect reverse translation"); + for(i = 0; i < 10; ++i) + { + UtAssert_True(input_pkt.str[i] == output_pkt.str[i], "Test incorrect reverse translation"); + } +} + + +void Explain_Test_Bitwise_Memcpy(void) +{ + /* Test source buffer. */ + uint8 src_buf[8] = {0, 0, 0, 0, 1, 2, 3, 4}; + /* Test destination buffer. */ + uint8 dst_buf[8] = {0}; + /* Source offset. */ + uint32 src_offset = 32; + /* Destination offset. */ + uint32 dst_offset = 0; + /* Bit length to copy. */ + uint32 bit_len = 32; + + /* Test for endianness. */ + int32 a = 0x12345678; + uint8 *c = (uint8*)(&a); + if (*c != 0x78) + { + printf("big-endian, skipping test Explain_Test_Bitwise_Memcpy\n"); + goto end_of_function; + } + + /* Call function under test. */ + memcpy_bitwise((char *)&dst_buf[0], dst_offset, (char *)&src_buf[0], src_offset, bit_len); + + /* Verify destination. */ + UtAssert_True(dst_buf[0] == 1, "Test bitwise memcpy destination"); + UtAssert_True(dst_buf[1] == 2, "Test bitwise memcpy destination"); + UtAssert_True(dst_buf[2] == 3, "Test bitwise memcpy destination"); + UtAssert_True(dst_buf[3] == 4, "Test bitwise memcpy destination"); + UtAssert_True(dst_buf[4] == 0, "Test bitwise memcpy destination"); + UtAssert_True(dst_buf[5] == 0, "Test bitwise memcpy destination"); + UtAssert_True(dst_buf[6] == 0, "Test bitwise memcpy destination"); + UtAssert_True(dst_buf[7] == 0, "Test bitwise memcpy destination"); + + /* Verify source. */ + UtAssert_True(src_buf[0] == 0, "Test bitwise memcpy source"); + UtAssert_True(src_buf[1] == 0, "Test bitwise memcpy source"); + UtAssert_True(src_buf[2] == 0, "Test bitwise memcpy source"); + UtAssert_True(src_buf[3] == 0, "Test bitwise memcpy source"); + UtAssert_True(src_buf[4] == 1, "Test bitwise memcpy source"); + UtAssert_True(src_buf[5] == 2, "Test bitwise memcpy source"); + UtAssert_True(src_buf[6] == 3, "Test bitwise memcpy source"); + UtAssert_True(src_buf[7] == 4, "Test bitwise memcpy source"); + +end_of_function: + return; +} + + +/* Todo this test makes some assumptions. By the C standard, + * the compiler is free to store the bit field any random way. Also, + * the test assumes little endianness. Todo for getting the memory + * map from the python utility and making this test independent of + * endianness and random bit field order. */ +void Explain_Test_Bitwise_Memcpy_BitFields(void) +{ + /* Todo assumes little endianness */ + /* bit5678, bit34, bit2, bit1 */ + /* 0000 00 0 0 */ + test_data_bit_fields bit_fields = {1, 0, 0, 0}; + test_data_bit_fields bit_test = {0}; + uint8 i = 0; + /* Expected results for initial iteration. */ + uint8 expected1 = 1; + uint8 expected2 = 0; + uint8 expected34 = 0; + uint8 expected5678 = 0; + + /* Bit test offsets and lengths. */ + uint32 bit_test_dst_offset = 7; + uint32 bit_test_src_offset = 7; + uint32 bit_test_length = 1; + + int32 a = 0x12345678; + uint8 *c = (uint8*)(&a); + if (*c != 0x78) + { + printf("big-endian, skipping test Explain_Test_Bitwise_Memcpy_BitFields\n"); + goto end_of_function; + } + + /* Test for bit packing. */ + test_data_bit_fields pack_check = {1, 0, 0, 0}; + uint8 * check_ptr = (uint8 *) &pack_check + 1; + if(1 == (*check_ptr & 1 << 0)) + { + printf("bit field randomly packed, skipping test Explain_Test_Bitwise_Memcpy_BitFields\n"); + goto end_of_function; + } + + pack_check.bit1 = 0; + pack_check.bit2 = 1; + + if(1 == (*check_ptr & 1 << 1)) + { + printf("bit field randomly packed, skipping test Explain_Test_Bitwise_Memcpy_BitFields\n"); + goto end_of_function; + } + + pack_check.bit2 = 0; + pack_check.bit34 = 1; + + if(1 == (*check_ptr & 1 << 2)) + { + printf("bit field randomly packed, skipping test Explain_Test_Bitwise_Memcpy_BitFields\n"); + goto end_of_function; + } + + pack_check.bit34 = 0; + pack_check.bit5678 = 1; + + if(1 == (*check_ptr & 1 << 4)) + { + printf("bit field randomly packed, skipping test Explain_Test_Bitwise_Memcpy_BitFields\n"); + goto end_of_function; + } + + /* First test portion single bit copy checks. */ + for(i = 0; i < 8; ++i) + { + /* Call function under test. */ + memcpy_bitwise((char *)&bit_test, bit_test_dst_offset, (char *)&bit_fields, bit_test_src_offset, bit_test_length); + + /* Evaluate results bit_test */ + UtAssert_True(bit_test.bit1 == expected1, "Test bitwise memcpy bit fields"); + UtAssert_True(bit_test.bit2 == expected2, "Test bitwise memcpy bit fields"); + UtAssert_True(bit_test.bit34 == expected34, "Test bitwise memcpy bit fields"); + UtAssert_True(bit_test.bit5678 == expected5678, "Test bitwise memcpy bit fields"); + + /* Decrement the destination offset to copy to the next bit + * in the destination structure. */ + bit_test_dst_offset--; + + /* Update the expected results. */ + if(0 == i) + { + expected1 = 0; + expected2 = 1; + } + else if (1 == i) + { + expected2 = 0; + expected34 = 1; + } + else if (2 == i) + { + expected34 = 2; + } + else if (3 == i) + { + expected34 = 0; + expected5678 = 1; + } + else if (4 == i) + { + expected5678 = 2; + } + else if (5 == i) + { + expected5678 = 4; + } + else if (6 == i) + { + expected5678 = 8; + } + + /* Reset bit_test */ + memset(&bit_test, 0, sizeof(bit_test)); + } + /* Second test portion multiple bit copy checks. */ + bit_test_dst_offset = 6; + bit_test_src_offset = 4; + bit_test_length = 2; + /* Reset bit_test. */ + memset(&bit_test, 0, sizeof(bit_test)); + /* Reset bit_fields. */ + memset(&bit_fields, 0, sizeof(bit_fields)); + + + bit_fields.bit34 = 3; + + /* Set expected results. */ + expected1 = 1; + expected2 = 1; + expected34 = 0; + expected5678 = 0; + + /* Call function under test. */ + memcpy_bitwise((char *)&bit_test, bit_test_dst_offset, (char *)&bit_fields, bit_test_src_offset, bit_test_length); + + /* Evaluate results bit_test. */ + UtAssert_True(bit_test.bit1 == expected1, "Test bitwise memcpy bit fields"); + UtAssert_True(bit_test.bit2 == expected2, "Test bitwise memcpy bit fields"); + UtAssert_True(bit_test.bit34 == expected34, "Test bitwise memcpy bit fields"); + UtAssert_True(bit_test.bit5678 == expected5678, "Test bitwise memcpy bit fields"); + + /* Reset bit_test. */ + memset(&bit_test, 0, sizeof(bit_test)); + /* Set expected results. */ + expected1 = 0; + expected2 = 0; + expected34 = 3; + expected5678 = 0; + /* Moved destination offset. */ + bit_test_dst_offset = 4; + + /* Call function under test. */ + memcpy_bitwise((char *)&bit_test, bit_test_dst_offset, (char *)&bit_fields, bit_test_src_offset, bit_test_length); + + /* Evaluate results bit_test. */ + UtAssert_True(bit_test.bit1 == expected1, "Test bitwise memcpy bit fields"); + UtAssert_True(bit_test.bit2 == expected2, "Test bitwise memcpy bit fields"); + UtAssert_True(bit_test.bit34 == expected34, "Test bitwise memcpy bit fields"); + UtAssert_True(bit_test.bit5678 == expected5678, "Test bitwise memcpy bit fields"); + + /* Reset bit_test. */ + memset(&bit_test, 0, sizeof(bit_test)); + /* Set expected results. */ + expected1 = 0; + expected2 = 0; + expected34 = 0; + expected5678 = 3; + /* Moved destination offset. */ + bit_test_dst_offset = 2; + + /* Call function under test. */ + memcpy_bitwise((char *)&bit_test, bit_test_dst_offset, (char *)&bit_fields, bit_test_src_offset, bit_test_length); + + /* Evaluate results bit_test. */ + UtAssert_True(bit_test.bit1 == expected1, "Test bitwise memcpy bit fields"); + UtAssert_True(bit_test.bit2 == expected2, "Test bitwise memcpy bit fields"); + UtAssert_True(bit_test.bit34 == expected34, "Test bitwise memcpy bit fields"); + UtAssert_True(bit_test.bit5678 == expected5678, "Test bitwise memcpy bit fields"); + + /* Reset bit_test. */ + memset(&bit_test, 0, sizeof(bit_test)); + /* Set expected results. */ + expected1 = 0; + expected2 = 0; + expected34 = 0; + expected5678 = 12; + /* Moved destination offset. */ + bit_test_dst_offset = 0; + + /* Call function under test. */ + memcpy_bitwise((char *)&bit_test, bit_test_dst_offset, (char *)&bit_fields, bit_test_src_offset, bit_test_length); + + /* Evaluate results bit_test. */ + UtAssert_True(bit_test.bit1 == expected1, "Test bitwise memcpy bit fields"); + UtAssert_True(bit_test.bit2 == expected2, "Test bitwise memcpy bit fields"); + UtAssert_True(bit_test.bit34 == expected34, "Test bitwise memcpy bit fields"); + UtAssert_True(bit_test.bit5678 == expected5678, "Test bitwise memcpy bit fields"); + + /* Third test portion nibble bit copy checks. */ + bit_test_dst_offset = 4; + bit_test_src_offset = 0; + bit_test_length = 4; + /* Reset bit_test. */ + memset(&bit_test, 0, sizeof(bit_test)); + /* Reset bit_fields. */ + memset(&bit_fields, 0, sizeof(bit_fields)); + + bit_fields.bit5678 = 15; + + /* Set expected results. */ + expected1 = 1; + expected2 = 1; + expected34 = 3; + expected5678 = 0; + + /* Call function under test. */ + memcpy_bitwise((char *)&bit_test, bit_test_dst_offset, (char *)&bit_fields, bit_test_src_offset, bit_test_length); + + /* Evaluate results bit_test. */ + UtAssert_True(bit_test.bit1 == expected1, "Test bitwise memcpy bit fields"); + UtAssert_True(bit_test.bit2 == expected2, "Test bitwise memcpy bit fields"); + UtAssert_True(bit_test.bit34 == expected34, "Test bitwise memcpy bit fields"); + UtAssert_True(bit_test.bit5678 == expected5678, "Test bitwise memcpy bit fields"); + +end_of_function: + return; +} + + +void Explain_App_Test_AddTestCases(void) +{ + UtTest_Add(Explain_Test_Offsets, Explain_Test_Setup, Explain_Test_TearDown, "Explain_Test_Offsets"); + UtTest_Add(Explain_Test_Translation, Explain_Test_Setup, Explain_Test_TearDown, "Explain_Test_Translation"); + UtTest_Add(Explain_Test_Reverse_Direction, Explain_Test_Setup, Explain_Test_TearDown, "Explain_Test_Reverse_Direction"); + UtTest_Add(Explain_Test_Bitwise_Memcpy, Explain_Test_Setup, Explain_Test_TearDown, "Explain_Test_Bitwise_Memcpy"); + UtTest_Add(Explain_Test_Bitwise_Memcpy_BitFields, Explain_Test_Setup, Explain_Test_TearDown, "Explain_Test_Bitwise_Memcpy_BitFields"); +} /* end Explain_App_Test_AddTestCases */ + +/************************/ +/* End of File Comment */ +/************************/ diff --git a/test/explain_app_test.h b/test/explain_app_test.h new file mode 100644 index 0000000..b927cd2 --- /dev/null +++ b/test/explain_app_test.h @@ -0,0 +1,41 @@ +/**************************************************************************** +* +* Copyright (c) 2017 Windhover Labs, L.L.C. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* 3. Neither the name Windhover Labs nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ + +#include "../../ut_assert/inc/utassert.h" +#include "../../ut_assert/inc/uttest.h" + +void Explain_App_Test_AddTestCases(void); + +/************************/ +/* End of File Comment */ +/************************/ diff --git a/test/explain_test_utils.c b/test/explain_test_utils.c new file mode 100644 index 0000000..b04f37c --- /dev/null +++ b/test/explain_test_utils.c @@ -0,0 +1,57 @@ +/**************************************************************************** +* +* Copyright (c) 2017 Windhover Labs, L.L.C. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* 3. Neither the name Windhover Labs nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ + +#include "explain_test_utils.h" +#include "../include/explain.h" +#include "../include/config.h" +#include +#include + +/* + * Function Definitions + */ + + +void Explain_Test_Setup(void) +{ + +} /* end Explain_Test_Setup */ + +void Explain_Test_TearDown(void) +{ + +} /* end Explain_Test_TearDown */ + +/************************/ +/* End of File Comment */ +/************************/ diff --git a/test/explain_test_utils.h b/test/explain_test_utils.h new file mode 100644 index 0000000..b765b69 --- /dev/null +++ b/test/explain_test_utils.h @@ -0,0 +1,50 @@ +/**************************************************************************** +* +* Copyright (c) 2017 Windhover Labs, L.L.C. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* 3. Neither the name Windhover Labs nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ + +/* + * Includes + */ + +#include "../include/explain.h" +#include + +/* + * Function Definitions + */ + +void Explain_Test_Setup(void); +void Explain_Test_TearDown(void); + +/************************/ +/* End of File Comment */ +/************************/ diff --git a/test/explain_testrunner.c b/test/explain_testrunner.c new file mode 100644 index 0000000..604bb55 --- /dev/null +++ b/test/explain_testrunner.c @@ -0,0 +1,46 @@ +/**************************************************************************** +* +* Copyright (c) 2017 Windhover Labs, L.L.C. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* 3. Neither the name Windhover Labs nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ + +#include "../../ut_assert/inc/uttest.h" +#include "explain_app_test.h" + +int main(void) +{ + Explain_App_Test_AddTestCases(); + + return(UtTest_Run()); +} /* end main */ + +/************************/ +/* End of File Comment */ +/************************/ diff --git a/test/makefile b/test/makefile new file mode 100644 index 0000000..3dfc495 --- /dev/null +++ b/test/makefile @@ -0,0 +1,125 @@ +############################################################################## +## File: +## $Id: makefile 1.1 2016/06/14 16:47:23EDT czogby Exp $ +## +## Purpose: +## Makefile for building the UT-Assert example unit tests +## +## $Log: makefile $ +## Revision 1.1 2016/06/14 16:47:23EDT czogby +## Initial revision +## Member added to project /FSW-TOOLs-REPOSITORY/ut-assert/example/fsw/unit_test/project.pj +## +############################################################################## +## GNU Makefile for building UT unit tests + +# +# Supported MAKEFILE targets: +# clean - deletes object files, executables, output files, and gcov files +# all - makes example_testrunner.exe +# run - runs example_testrunner.exe +# gcov - prints a GCOV coverage report (make all, make run, make gcov) +# +# GCOV is disabled by default. If you are using the source level debugger you will want to +# disable GCOV. To enable GCOV you can override the ENABLE_GCOV variable on the command line +# by setting it to TRUE. For example "make ENABLE_GCOV=TRUE". +# + +# +# VPATH specifies the search paths for source files outside of the current directory. Note that +# all object files will be created in the current directory even if the source file is not in the +# current directory. +# +VPATH := . +# ut_assert src directory +VPATH += ../../ut_assert/src +# Application under test directory +VPATH += ../src + +EXPLAIN_PATH=../ + +# +# INCLUDES specifies the search paths for include files outside of the current directory. +# Note that the -I is required. +# +INCLUDES := -I. +INCLUDES += -I../../ut_assert/inc +INCLUDES += -I$(EXPLAIN_PATH)/src +INCLUDES += -I$(EXPLAIN_PATH)/include + + +# +# FLIGHT_OBJS specifies flight software object files. +# +FLIGHT_OBJS := ccsds.o utils.o cfe_sb_util.o explain.o list.o memtools.o message.o parser.o usage.o + +# +# UT_OBJS specifies unit test object files. +# +UT_OBJS += utassert.o +UT_OBJS += utlist.o +UT_OBJS += uttest.o +UT_OBJS += uttools.o +UT_OBJS += explain_app_test.o +UT_OBJS += explain_testrunner.o +UT_OBJS += explain_test_utils.o + +# +# UT_TEST_RUNNER specifies the name of the test runner. +# +UT_TEST_RUNNER = explain_testrunner.exe + +############################################################################### + +COMPILER=gcc +LINKER=gcc + +# +# Compiler and Linker Options +# +GCOV_COPT = -fprofile-arcs -ftest-coverage -pg -p +GCOV_LOPT = -pg -p -fprofile-arcs -ftest-coverage -lgcov -lm +JSON_LOPT = -ljson + +#WARNINGS = -Wall -W -ansi -Werror -Wstrict-prototypes -Wundef +WARNINGS = -Wall -Wstrict-prototypes -Wundef +DEBUGGER = -g + +COPT = $(WARNINGS) $(DEBUGGER) $(GCOV_COPT) -DUT_VERBOSE -Wno-deprecated-declarations + +LOPT = $(GCOV_LOPT) + +############################################################################### +## Rule to make the specified TARGET +## +%.exe: %.o + $(LINKER) $(LOPT) $^ -o $*.exe $(JSON_LOPT) + +############################################################################### +## "C" COMPILER RULE +## +%.o: %.c + $(COMPILER) -c $(COPT) $(INCLUDES) $< + +############################################################################## +## + +all:$(UT_TEST_RUNNER) + +$(UT_TEST_RUNNER): $(UT_OBJS) $(FLIGHT_OBJS) + +clean :: + rm -f *.o *.exe *.gcda *.gcno *.gcov gmon.out + +run :: + ./$(UT_TEST_RUNNER) + +gcov :: + @echo + @gcov $(FLIGHT_OBJS:.o=.gcda) | sed 'N;s/\n/ /' | \ + sed -n '/File/p' | sed '/ads/d' | sed -e '/\.h/d' | \ + sed 's/ Lines executed:/ /; s/File/gcov:/; s/of// ' + @rm -f *.gcda *.gcno + @echo + +# end of file diff --git a/test/test_input.json b/test/test_input.json new file mode 100644 index 0000000..0c28fe6 --- /dev/null +++ b/test/test_input.json @@ -0,0 +1,164 @@ +{ + "bitmap": [ + { + "dst_symbol": "test_data_types_dst", + "fields": [ + { + "length": 88, + "src_offset": 0, + "op_name": "TlmHeader", + "dst_offset": 0 + }, + { + "length": 16, + "src_offset": 96, + "op_name": "synch", + "dst_offset": 96 + }, + { + "length": 8, + "src_offset": 112, + "op_name": "padding", + "dst_offset": 112 + }, + { + "length": 1, + "src_offset": 127, + "op_name": "bit1", + "dst_offset": 135 + }, + { + "length": 1, + "src_offset": 126, + "op_name": "bit2", + "dst_offset": 134 + }, + { + "length": 2, + "src_offset": 124, + "op_name": "bit34", + "dst_offset": 132 + }, + { + "length": 2, + "src_offset": 122, + "op_name": "bit56", + "dst_offset": 130 + }, + { + "length": 2, + "src_offset": 120, + "op_name": "bit78", + "dst_offset": 128 + }, + { + "length": 4, + "src_offset": 132, + "op_name": "nibble1", + "dst_offset": 140 + }, + { + "length": 4, + "src_offset": 128, + "op_name": "nibble2", + "dst_offset": 136 + }, + { + "length": 8, + "src_offset": 136, + "op_name": "bl1", + "dst_offset": 144 + }, + { + "length": 8, + "src_offset": 144, + "op_name": "bl2", + "dst_offset": 152 + }, + { + "length": 8, + "src_offset": 152, + "op_name": "b1", + "dst_offset": 160 + }, + { + "length": 8, + "src_offset": 160, + "op_name": "b2", + "dst_offset": 168 + }, + { + "length": 8, + "src_offset": 168, + "op_name": "b3", + "dst_offset": 176 + }, + { + "length": 8, + "src_offset": 176, + "op_name": "b4", + "dst_offset": 184 + }, + { + "length": 16, + "src_offset": 192, + "op_name": "w1", + "dst_offset": 192 + }, + { + "length": 16, + "src_offset": 208, + "op_name": "w2", + "dst_offset": 208 + }, + { + "length": 32, + "src_offset": 224, + "op_name": "dw1", + "dst_offset": 224 + }, + { + "length": 32, + "src_offset": 256, + "op_name": "dw2", + "dst_offset": 256 + }, + { + "length": 32, + "src_offset": 288, + "op_name": "f1", + "dst_offset": 288 + }, + { + "length": 32, + "src_offset": 320, + "op_name": "f2", + "dst_offset": 320 + }, + { + "length": 64, + "src_offset": 384, + "op_name": "df1", + "dst_offset": 384 + }, + { + "length": 64, + "src_offset": 448, + "op_name": "df2", + "dst_offset": 448 + }, + { + "length": 80, + "src_offset": 512, + "op_name": "str", + "dst_offset": 512 + } + ], + "ops_name": "", + "src_endian": "L", + "src_symbol": "test_data_types_src", + "id": "0x0881", + "dst_endian": "L" + } + ] +}