Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions Svc/FpySequencer/FpySequencer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,17 @@ FpySequencer ::FpySequencer(const char* const compName)
m_sequenceFilePath("<invalid_seq>"),
m_sequenceObj(),
m_computedCRC(0),
m_totalExpectedArgSize(0),
m_sequenceBlockState(),
m_savedOpCode(0),
m_savedCmdSeq(0),
m_sequenceArgs(0, 0),
m_goalState(),
m_sequencesStarted(0),
m_statementsDispatched(0),
m_runtime(),
m_breakpoint(),
m_debug(),
m_tlm() {}

FpySequencer ::~FpySequencer() {}
Expand All @@ -47,8 +50,8 @@ void FpySequencer::RUN_cmdHandler(FwOpcodeType opCode, //!< The op
void FpySequencer ::RUN_ARGS_cmdHandler(FwOpcodeType opCode, //!< The opcode
U32 cmdSeq, //!< The command sequence number
const Fw::CmdStringArg& fileName, //!< The name of the sequence file
BlockState block, //!< Return command status when complete or not
Comment thread
Lex-ari marked this conversation as resolved.
Svc::SeqArgs args //!< Arguments to pass to the sequencer
Svc::BlockState block, //!< Return command status when complete or not
Svc::SeqArgs args //!< Arguments to pass to the sequencer
) {
// can only run a seq while in idle
if (sequencer_getState() != State::IDLE) {
Expand Down
10 changes: 7 additions & 3 deletions Svc/FpySequencer/FpySequencer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,14 +144,14 @@ class FpySequencer : public FpySequencerComponentBase {
void RUN_cmdHandler(FwOpcodeType opCode, //!< The opcode
U32 cmdSeq, //!< The command sequence number
const Fw::CmdStringArg& fileName, //!< The name of the sequence file
BlockState block //!< Return command status when complete or not
Svc::BlockState block //!< Return command status when complete or not
) override;

//! Handler implementation for command RUN_ARGS
void RUN_ARGS_cmdHandler(FwOpcodeType opCode, //!< The opcode
U32 cmdSeq, //!< The command sequence number
const Fw::CmdStringArg& fileName, //!< The name of the sequence file
BlockState block, //!< Return command status when complete or not
Svc::BlockState block, //!< Return command status when complete or not
Svc::SeqArgs args //!< Arguments to pass to the sequencer
) override;

Expand Down Expand Up @@ -641,9 +641,13 @@ class FpySequencer : public FpySequencerComponentBase {
// live running computation of CRC (updated as we read)
U32 m_computedCRC;

// Size of arguments read in current sequence. Used for validation between
// User provided arguments and what is requested of the sequence.
Fpy::StackSizeType m_totalExpectedArgSize;

// whether or not the sequence we're about to run should return immediately or
// block on completion
BlockState m_sequenceBlockState;
Svc::BlockState m_sequenceBlockState;
// if we are to block on completion, save the opCode and cmdSeq we should
// return
FwOpcodeType m_savedOpCode;
Expand Down
14 changes: 14 additions & 0 deletions Svc/FpySequencer/FpySequencerEvents.fppi
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,20 @@ event TooManySequenceDirectives(
severity warning high \
format "A sequence specified it had {} directives but the max was {}"

event ArgSizeMismatch(
expected: Fpy.StackSizeType
actual: FwSizeType
filePath: string
) \
severity warning high \
format "Expected {} bytes of arguments, but received {} in sequence file {}"

event ArgTotalSizeExceedsStackLimit(
argSize: Fpy.StackSizeType
) \
severity warning high \
format "Arguments of size {} would exceed max stack size."

event SequencePaused(
stmtIdx: U32
) \
Expand Down
17 changes: 15 additions & 2 deletions Svc/FpySequencer/FpySequencerTypes.fpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module Svc {
module Fpy {
@ the current schema version (must be representable in U8)
constant SCHEMA_VERSION = 5;
constant SCHEMA_VERSION = 6;

@ the type which everything referencing a size or offset on the stack is represented in
# we use a U32 because U16 is too small (would only allow up to 65 kB max stack size)
Expand Down Expand Up @@ -130,6 +130,19 @@ module Svc {
CMD_FAIL = 17
}

@ Maximum length for argument or type names in arg_specs
@ Fpy serializes these as U8 length prefix, so max is 255
constant MAX_ARG_SPEC_NAME_LEN = 255

@ Argument specification describing an input argument's name, type, and stack size
@ NOTE: This struct does use FPP's auto-generated serialization!
struct ArgSpec {
argName: string size MAX_ARG_SPEC_NAME_LEN
typeName: string size MAX_ARG_SPEC_NAME_LEN
@ Size of this argument on the stack in bytes
argSize: StackSizeType
} default {argName = "", typeName = "", argSize = 0 }

struct Header {
@ the major version of the FSW
majorVersion: U8
Expand Down Expand Up @@ -165,7 +178,7 @@ module Svc {
header: Header
@ an array of size m_header.argumentCount mapping argument position to local
@ variable index
args: [MAX_SEQUENCE_ARG_COUNT] U8
args: [MAX_SEQUENCE_ARG_COUNT] ArgSpec
statements: [MAX_SEQUENCE_STATEMENT_COUNT] Statement
footer: Footer
}
Expand Down
32 changes: 25 additions & 7 deletions Svc/FpySequencer/FpySequencerValidationState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,18 +145,36 @@ Fw::Success FpySequencer::readHeader() {
// return SUCCESS if sequence is valid, FAILURE otherwise
Fw::Success FpySequencer::readBody() {
Fw::SerializeStatus deserStatus;
// deser body:
// deser arg mappings
for (U8 argMappingIdx = 0; argMappingIdx < this->m_sequenceObj.get_header().get_argumentCount(); argMappingIdx++) {
// serializable register index of arg $argMappingIdx
// TODO should probably check that this serReg is inside range
deserStatus = this->m_sequenceBuffer.deserializeTo(this->m_sequenceObj.get_args()[argMappingIdx]);
if (deserStatus != Fw::FW_SERIALIZE_OK) {

const U8 argumentCount = this->m_sequenceObj.get_header().get_argumentCount();
this->m_totalExpectedArgSize = 0;

// deser arguments
// Read and deserialize each arg_spec incrementally since they're variable-length
for (U8 i = 0; i < argumentCount; i++) {
Fpy::ArgSpec& argSpec = this->m_sequenceObj.get_args()[i];
deserStatus = this->m_sequenceBuffer.deserializeTo(argSpec);
if (deserStatus != Fw::SerializeStatus::FW_SERIALIZE_OK) {
this->log_WARNING_HI_FileReadDeserializeError(
FpySequencer_FileReadStage::BODY, this->m_sequenceFilePath, static_cast<I32>(deserStatus),
this->m_sequenceBuffer.getDeserializeSizeLeft(), this->m_sequenceBuffer.getSize());
return Fw::Success::FAILURE;
}

m_totalExpectedArgSize += argSpec.get_argSize();
}

// Check for overflow
if (m_totalExpectedArgSize > Fpy::MAX_STACK_SIZE) {
this->log_WARNING_HI_ArgTotalSizeExceedsStackLimit(m_totalExpectedArgSize);
return Fw::Success::FAILURE;
}

// Validate total argument size
if (this->m_totalExpectedArgSize != this->m_sequenceArgs.get_size()) {
this->log_WARNING_HI_ArgSizeMismatch(this->m_totalExpectedArgSize, this->m_sequenceArgs.get_size(),
this->m_sequenceFilePath);
return Fw::Success::FAILURE;
}

// deser statements
Expand Down
Loading
Loading