F´ Flight Software - C/C++ Documentation
A framework for building embedded system applications to NASA flight quality standards.
FpySequencerValidationState.cpp
Go to the documentation of this file.
3 extern "C" {
5 }
6 namespace Svc {
7 
9  // if this assertion fails, you aren't allocating enough bytes for the
10  // FpySequencer. this is because you must have a buffer big enough to fit the
11  // header of a sequence
12  FW_ASSERT(bytes >= Fpy::Header::SERIALIZED_SIZE, static_cast<FwAssertArgType>(bytes));
13  FwSizeType originalBytes = bytes;
14  bool recoverable = false;
15  this->m_allocatorId = identifier;
16  U8* allocatedMemory = static_cast<U8*>(allocator.allocate(identifier, bytes, recoverable));
17  // if this fails, unable to allocate the requested amount of money
18  FW_ASSERT(bytes >= originalBytes, static_cast<FwAssertArgType>(bytes));
19  this->m_sequenceBuffer.setExtBuffer(allocatedMemory, bytes);
20 }
21 
23  allocator.deallocate(this->m_allocatorId, this->m_sequenceBuffer.getBuffAddr());
24  this->m_sequenceBuffer.clear();
25 }
26 
27 void FpySequencer::updateCrc(U32& crc, const U8* buffer, FwSizeType bufferSize) {
28  FW_ASSERT(buffer);
29  for (FwSizeType index = 0; index < bufferSize; index++) {
30  crc = static_cast<U32>(update_crc_32(crc, static_cast<char>(buffer[index])));
31  }
32 }
33 
34 // loads the sequence in memory, and does header/crc/integrity checks.
35 // return SUCCESS if sequence is valid, FAILURE otherwise
36 Fw::Success FpySequencer::validate() {
37  FW_ASSERT(this->m_sequenceFilePath.length() > 0);
38 
39  // crc needs to be initialized with a particular value
40  // for the calculation to work
41  this->m_computedCRC = CRC_INITIAL_VALUE;
42 
43  Os::File sequenceFile;
44  Os::File::Status openStatus = sequenceFile.open(this->m_sequenceFilePath.toChar(), Os::File::OPEN_READ);
45 
46  if (openStatus != Os::File::Status::OP_OK) {
47  this->log_WARNING_HI_FileOpenError(this->m_sequenceFilePath, static_cast<I32>(openStatus));
48  return Fw::Success::FAILURE;
49  }
50 
51  Fw::Success readStatus =
53 
54  if (readStatus != Fw::Success::SUCCESS) {
55  return Fw::Success::FAILURE;
56  }
57 
58  readStatus = this->readHeader();
59 
60  if (readStatus != Fw::Success::SUCCESS) {
61  return Fw::Success::FAILURE;
62  }
63 
64  readStatus =
65  readBytes(sequenceFile, this->m_sequenceObj.get_header().get_bodySize(), FpySequencer_FileReadStage::BODY);
66 
67  if (readStatus != Fw::Success::SUCCESS) {
68  return Fw::Success::FAILURE;
69  }
70 
71  readStatus = this->readBody();
72 
73  if (readStatus != Fw::Success::SUCCESS) {
74  return Fw::Success::FAILURE;
75  }
76 
77  // read footer bytes but don't include in CRC
78  readStatus = this->readBytes(sequenceFile, Fpy::Footer::SERIALIZED_SIZE, FpySequencer_FileReadStage::FOOTER, false);
79 
80  if (readStatus != Fw::Success::SUCCESS) {
81  return Fw::Success::FAILURE;
82  }
83 
84  readStatus = this->readFooter();
85 
86  if (readStatus != Fw::Success::SUCCESS) {
87  return Fw::Success::FAILURE;
88  }
89 
90  // make sure we're at EOF
91  FwSizeType sequenceFileSize;
92  FW_ASSERT(sequenceFile.size(sequenceFileSize) == Os::File::Status::OP_OK);
93 
94  FwSizeType sequenceFilePosition;
95  FW_ASSERT(sequenceFile.position(sequenceFilePosition) == Os::File::Status::OP_OK);
96 
97  if (sequenceFileSize != sequenceFilePosition) {
98  this->log_WARNING_HI_ExtraBytesInSequence(static_cast<FwSizeType>(sequenceFileSize - sequenceFilePosition));
99  return Fw::Success::FAILURE;
100  }
101 
102  Fpy::StackSizeType availableSpace = Fpy::MAX_STACK_SIZE - this->m_runtime.stack.size;
103 
104  if (this->m_sequenceArgs.get_size() > availableSpace) {
105  return Fw::Success::FAILURE;
106  }
107 
108  return Fw::Success::SUCCESS;
109 }
110 
111 // reads and validates the header from the m_sequenceBuffer
112 // return SUCCESS if sequence is valid, FAILURE otherwise
113 Fw::Success FpySequencer::readHeader() {
114  // deser header
115  Fw::SerializeStatus deserStatus = this->m_sequenceBuffer.deserializeTo(this->m_sequenceObj.get_header());
116  if (deserStatus != Fw::SerializeStatus::FW_SERIALIZE_OK) {
118  FpySequencer_FileReadStage::HEADER, this->m_sequenceFilePath, static_cast<I32>(deserStatus),
119  this->m_sequenceBuffer.getDeserializeSizeLeft(), this->m_sequenceBuffer.getSize());
120  return Fw::Success::FAILURE;
121  }
122 
123  // check matching schema version
124  if (this->m_sequenceObj.get_header().get_schemaVersion() != Fpy::SCHEMA_VERSION) {
126  this->m_sequenceObj.get_header().get_schemaVersion());
127  return Fw::Success::FAILURE;
128  }
129 
130  if (this->m_sequenceObj.get_header().get_argumentCount() > Fpy::MAX_SEQUENCE_ARG_COUNT) {
133  return Fw::Success::FAILURE;
134  }
135 
136  if (this->m_sequenceObj.get_header().get_statementCount() > Fpy::MAX_SEQUENCE_STATEMENT_COUNT) {
139  return Fw::Success::FAILURE;
140  }
141  return Fw::Success::SUCCESS;
142 }
143 
144 // reads and validates the body from the m_sequenceBuffer
145 // return SUCCESS if sequence is valid, FAILURE otherwise
146 Fw::Success FpySequencer::readBody() {
147  Fw::SerializeStatus deserStatus;
148  // deser body:
149  // deser arg mappings
150  for (U8 argMappingIdx = 0; argMappingIdx < this->m_sequenceObj.get_header().get_argumentCount(); argMappingIdx++) {
151  // serializable register index of arg $argMappingIdx
152  // TODO should probably check that this serReg is inside range
153  deserStatus = this->m_sequenceBuffer.deserializeTo(this->m_sequenceObj.get_args()[argMappingIdx]);
154  if (deserStatus != Fw::FW_SERIALIZE_OK) {
156  FpySequencer_FileReadStage::BODY, this->m_sequenceFilePath, static_cast<I32>(deserStatus),
157  this->m_sequenceBuffer.getDeserializeSizeLeft(), this->m_sequenceBuffer.getSize());
158  return Fw::Success::FAILURE;
159  }
160  }
161 
162  // deser statements
163  for (U16 statementIdx = 0; statementIdx < this->m_sequenceObj.get_header().get_statementCount(); statementIdx++) {
164  // deser statement
165  deserStatus = this->m_sequenceBuffer.deserializeTo(this->m_sequenceObj.get_statements()[statementIdx]);
166  if (deserStatus != Fw::FW_SERIALIZE_OK) {
168  FpySequencer_FileReadStage::BODY, this->m_sequenceFilePath, static_cast<I32>(deserStatus),
169  this->m_sequenceBuffer.getDeserializeSizeLeft(), this->m_sequenceBuffer.getSize());
170  return Fw::Success::FAILURE;
171  }
172  }
173  return Fw::Success::SUCCESS;
174 }
175 
176 // reads and validates the footer from the m_sequenceBuffer
177 // return SUCCESS if sequence is valid, FAILURE otherwise
178 Fw::Success FpySequencer::readFooter() {
179  Fw::SerializeStatus deserStatus = this->m_sequenceBuffer.deserializeTo(this->m_sequenceObj.get_footer());
180  if (deserStatus != Fw::FW_SERIALIZE_OK) {
182  FpySequencer_FileReadStage::FOOTER, this->m_sequenceFilePath, static_cast<I32>(deserStatus),
183  this->m_sequenceBuffer.getDeserializeSizeLeft(), this->m_sequenceBuffer.getSize());
184  return Fw::Success::FAILURE;
185  }
186 
187  // need this for some reason to "finalize" the crc TODO get an explanation on this
188  this->m_computedCRC = ~this->m_computedCRC;
189 
190  if (this->m_computedCRC != this->m_sequenceObj.get_footer().get_crc()) {
191  this->log_WARNING_HI_WrongCRC(this->m_sequenceObj.get_footer().get_crc(), this->m_computedCRC);
192  return Fw::Success::FAILURE;
193  }
194 
195  return Fw::Success::SUCCESS;
196 }
197 
198 // reads some bytes from the open file into the m_sequenceBuffer.
199 // return success if successful
200 Fw::Success FpySequencer::readBytes(Os::File& file,
201  FwSizeType expectedReadLen,
202  const FpySequencer_FileReadStage& readStage,
203  bool updateCrc) {
204  FW_ASSERT(file.isOpen());
205  // this has to be declared a var because file.read must take a ref
206  FwSizeType actualReadLen = expectedReadLen;
207 
208  const FwSizeType capacity = this->m_sequenceBuffer.getCapacity();
209 
210  // if this fails, then you need to give the sequencer more buffer memory. pass in a bigger number
211  // to fpySeq.allocateBuffer(). This is usually done in topology setup CPP
212  if (expectedReadLen > capacity) {
213  this->log_WARNING_HI_InsufficientBufferSpace(static_cast<U64>(capacity), this->m_sequenceFilePath);
214  return Fw::Success::FAILURE;
215  }
216 
217  Os::File::Status fileStatus = file.read(this->m_sequenceBuffer.getBuffAddr(), actualReadLen);
218 
219  if (fileStatus != Os::File::OP_OK) {
220  this->log_WARNING_HI_FileReadError(readStage, this->m_sequenceFilePath, static_cast<I32>(fileStatus));
221  return Fw::Success::FAILURE;
222  }
223 
224  if (actualReadLen < expectedReadLen) {
225  this->log_WARNING_HI_EndOfFileError(readStage, this->m_sequenceFilePath);
226  return Fw::Success::FAILURE;
227  }
228 
229  // should probably fail if we read in MORE bytes than we ask for
230  FW_ASSERT(expectedReadLen == actualReadLen, static_cast<FwAssertArgType>(expectedReadLen),
231  static_cast<FwAssertArgType>(actualReadLen));
232 
233  Fw::SerializeStatus serializeStatus =
234  this->m_sequenceBuffer.setBuffLen(static_cast<Fw::Serializable::SizeType>(expectedReadLen));
235  FW_ASSERT(serializeStatus == Fw::FW_SERIALIZE_OK, serializeStatus);
236 
237  if (updateCrc) {
238  FpySequencer::updateCrc(this->m_computedCRC, this->m_sequenceBuffer.getBuffAddr(), expectedReadLen);
239  }
240 
241  return Fw::Success::SUCCESS;
242 }
243 
244 } // namespace Svc
Serialization/Deserialization operation was successful.
void clear()
Clear external buffer.
virtual void * allocate(const FwEnumStoreType identifier, FwSizeType &size, bool &recoverable, FwSizeType alignment=alignof(std::max_align_t))=0
Operation succeeded.
Definition: Os.hpp:26
U16 get_statementCount() const
Get member statementCount.
Type_of_args & get_args()
Get member args.
Representing success.
void log_WARNING_HI_InsufficientBufferSpace(U64 bufferSize, const Fw::StringBase &filePath) const
Log event InsufficientBufferSpace.
PlatformSizeType FwSizeType
I32 FwEnumStoreType
void log_WARNING_HI_WrongCRC(U32 expected, U32 actual) const
Log event WrongCRC.
const char * toChar() const
Convert to a C-style char*.
Definition: String.hpp:50
Serializable::SizeType getSize() const override
Get current buffer size.
Status position(FwSizeType &position_result) override
get file pointer position of the currently open file
Definition: File.cpp:120
Status size(FwSizeType &size_result) override
get size of currently open file
Definition: File.cpp:111
Os::FileInterface::Status open(const char *path, Mode mode)
open file with supplied path and mode
void log_WARNING_HI_FileReadError(Svc::FpySequencer_FileReadStage readStage, const Fw::StringBase &filePath, I32 errorCode) const
Log event FileReadError.
void log_WARNING_HI_ExtraBytesInSequence(FwSizeType remaining) const
Log event ExtraBytesInSequence.
The size of the serial representation.
void log_WARNING_HI_TooManySequenceDirectives(U16 count, U16 max) const
Log event TooManySequenceDirectives.
SerializeStatus
forward declaration for string
unsigned long update_crc_32(unsigned long crc, char c)
Definition: lib_crc.c:272
U8 get_schemaVersion() const
Get member schemaVersion.
Serializable::SizeType getCapacity() const
Get buffer capacity.
Svc::Fpy::Header & get_header()
Get member header.
Serializable::SizeType getDeserializeSizeLeft() const override
Get remaining deserialization buffer size.
void log_WARNING_HI_EndOfFileError(Svc::FpySequencer_FileReadStage readStage, const Fw::StringBase &filePath) const
Log event EndOfFileError.
U32 get_bodySize() const
Get member bodySize.
Type_of_statements & get_statements()
Get member statements.
void allocateBuffer(FwEnumStoreType identifier, Fw::MemAllocator &allocator, FwSizeType bytes)
FwSizeType get_size() const
Get member size.
Representing failure.
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.h:53
Status read(U8 *buffer, FwSizeType &size)
read data from this file into supplied buffer bounded by size
Definition: File.cpp:194
void log_WARNING_HI_FileOpenError(const Fw::StringBase &filePath, I32 errorCode) const
Log event FileOpenError.
void setExtBuffer(U8 *buffPtr, Serializable::SizeType size)
Set the external buffer.
Memory Allocation base class.
Svc::Fpy::Footer & get_footer()
Get member footer.
Operation was successful.
Definition: File.hpp:41
void log_WARNING_HI_FileReadDeserializeError(Svc::FpySequencer_FileReadStage readStage, const Fw::StringBase &filePath, I32 errorCode, U64 buffLeft, U64 buffLength) const
Log event FileReadDeserializeError.
Open file for reading.
Definition: File.hpp:32
U8 get_argumentCount() const
Get member argumentCount.
void log_WARNING_HI_WrongSchemaVersion(U8 expected, U8 actual) const
Log event WrongSchemaVersion.
RateGroupDivider component implementation.
virtual SizeType length() const
Get the length of the string.
SerializeStatus deserializeTo(U8 &val, Endianness mode=Endianness::BIG) override
Deserialize an 8-bit unsigned integer value.
void log_WARNING_HI_TooManySequenceArgs(U8 count, U8 max) const
Log event TooManySequenceArgs.
virtual void deallocate(const FwEnumStoreType identifier, void *ptr)=0
void deallocateBuffer(Fw::MemAllocator &allocator)
SerializeStatus setBuffLen(Serializable::SizeType length) override
Set buffer length manually.
#define FW_ASSERT(...)
Definition: Assert.hpp:14
Success/Failure.
bool isOpen() const
determine if the file is open
Definition: File.cpp:105
U32 StackSizeType
the type which everything referencing a size or offset on the stack is represented in ...
U8 * getBuffAddr()
Get buffer address for data filling (non-const version)