| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // \title AMPCSSequence.cpp | ||
| 2 | // \author Rob Bocchino | ||
| 3 | // \brief AMPCSSequence implementation | ||
| 4 | // | ||
| 5 | // \copyright | ||
| 6 | // Copyright (C) 2009-2018 California Institute of Technology. | ||
| 7 | // ALL RIGHTS RESERVED. United States Government Sponsorship | ||
| 8 | // acknowledged. | ||
| 9 | // | ||
| 10 | // ====================================================================== | ||
| 11 | |||
| 12 | #include "Svc/CmdSequencer/formats/AMPCSSequence.hpp" | ||
| 13 | #include <Utils/Hash/Hash.hpp> | ||
| 14 | #include "Fw/Com/ComPacket.hpp" | ||
| 15 | #include "Fw/Types/Assert.hpp" | ||
| 16 | #include "Os/FileSystem.hpp" | ||
| 17 | |||
| 18 | namespace Svc { | ||
| 19 | |||
| 20 |
3/3✓ Branch 10 taken 74 times.
✓ Branch 16 taken 74 times.
✓ Branch 22 taken 74 times.
|
74 | AMPCSSequence ::AMPCSSequence(CmdSequencerComponentImpl& component) : CmdSequencerComponentImpl::Sequence(component) {} |
| 21 | |||
| 22 | 38 | bool AMPCSSequence ::loadFile(const Fw::ConstStringBase& fileName) { | |
| 23 | // Make sure there is a buffer allocated | ||
| 24 | 38 | FW_ASSERT(this->m_buffer.getBuffAddr() != nullptr); | |
| 25 | |||
| 26 |
1/1✓ Branch 2 taken 38 times.
|
38 | Fw::CmdStringArg crcFileName(fileName); |
| 27 |
1/1✓ Branch 2 taken 38 times.
|
38 | crcFileName += ".CRC32"; |
| 28 | |||
| 29 |
1/1✓ Branch 6 taken 38 times.
|
38 | this->m_header.m_timeBase = TimeBase::TB_DONT_CARE; |
| 30 | 38 | this->m_header.m_timeContext = FW_CONTEXT_DONT_CARE; | |
| 31 | |||
| 32 |
4/4✓ Branch 4 taken 38 times.
✓ Branch 10 taken 35 times.
✓ Branch 12 taken 33 times.
✓ Branch 13 taken 2 times.
|
73 | const bool status = this->readCRCFile(crcFileName) and this->getFileSize(fileName) and |
| 33 |
6/6✓ Branch 4 taken 33 times.
✓ Branch 6 taken 29 times.
✓ Branch 7 taken 4 times.
✓ Branch 12 taken 29 times.
✓ Branch 14 taken 28 times.
✓ Branch 15 taken 1 times.
|
33 | this->readSequenceFile(fileName) and this->validateCRC() and |
| 34 |
7/8✓ Branch 0 taken 35 times.
✓ Branch 1 taken 3 times.
✓ Branch 11 taken 28 times.
✓ Branch 13 taken 28 times.
✗ Branch 14 not taken.
✓ Branch 19 taken 28 times.
✓ Branch 21 taken 26 times.
✓ Branch 22 taken 2 times.
|
73 | this->m_header.validateTime(this->m_component) and this->validateRecords(); |
| 35 | |||
| 36 | 38 | return status; | |
| 37 | 38 | } | |
| 38 | |||
| 39 | 38 | bool AMPCSSequence ::readCRCFile(Fw::CmdStringArg& crcFileName) { | |
| 40 | bool result; | ||
| 41 | |||
| 42 | 38 | this->setFileName(crcFileName); | |
| 43 | |||
| 44 | 38 | Os::File::Status status = this->m_crcFile.open(crcFileName.toChar(), Os::File::OPEN_READ); | |
| 45 | |||
| 46 |
2/2✓ Branch 0 taken 35 times.
✓ Branch 1 taken 3 times.
|
38 | if (status == Os::File::OP_OK) { |
| 47 |
2/4✓ Branch 4 taken 35 times.
✗ Branch 5 not taken.
✓ Branch 10 taken 35 times.
✗ Branch 11 not taken.
|
35 | result = this->readCRC() and this->deserializeCRC(); |
| 48 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
|
3 | } else if (status == Os::File::DOESNT_EXIST) { |
| 49 | 2 | this->m_events.fileNotFound(); | |
| 50 | 2 | result = false; | |
| 51 | } else { | ||
| 52 | 1 | this->m_events.fileReadError(); | |
| 53 | 1 | result = false; | |
| 54 | } | ||
| 55 | |||
| 56 | 38 | this->m_crcFile.close(); | |
| 57 | 38 | return result; | |
| 58 | } | ||
| 59 | |||
| 60 | 35 | bool AMPCSSequence ::getFileSize(const Fw::ConstStringBase& seqFileName) { | |
| 61 | 35 | bool status = true; | |
| 62 | 35 | FwSizeType fileSize; | |
| 63 |
1/1✓ Branch 5 taken 35 times.
|
35 | this->setFileName(seqFileName); |
| 64 |
1/1✓ Branch 7 taken 35 times.
|
35 | const Os::FileSystem::Status fileStatus = Os::FileSystem::getFileSize(this->m_fileName.toChar(), fileSize); |
| 65 |
4/4✓ Branch 0 taken 34 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 33 times.
✓ Branch 3 taken 1 times.
|
35 | if (fileStatus == Os::FileSystem::OP_OK and fileSize >= static_cast<FwSizeType>(sizeof(this->m_sequenceHeader))) { |
| 66 | 66 | this->m_header.m_fileSize = | |
| 67 | 66 | static_cast<U32>(fileSize - static_cast<FwSizeType>(sizeof(this->m_sequenceHeader))); | |
| 68 | } else { | ||
| 69 |
1/1✓ Branch 4 taken 2 times.
|
2 | this->m_events.fileInvalid(CmdSequencer_FileReadStage::READ_HEADER_SIZE, fileStatus); |
| 70 | 2 | status = false; | |
| 71 | } | ||
| 72 | 35 | return status; | |
| 73 | } | ||
| 74 | |||
| 75 | 33 | bool AMPCSSequence ::readSequenceFile(const Fw::ConstStringBase& seqFileName) { | |
| 76 | bool result; | ||
| 77 | |||
| 78 | 33 | this->setFileName(seqFileName); | |
| 79 | 33 | Os::File::Status status = this->m_sequenceFile.open(this->m_fileName.toChar(), Os::File::OPEN_READ); | |
| 80 | |||
| 81 |
1/2✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
|
33 | if (status == Os::File::OP_OK) { |
| 82 | 33 | result = this->readOpenSequenceFile(); | |
| 83 | ✗ | } else if (status == Os::File::DOESNT_EXIST) { | |
| 84 | ✗ | this->m_events.fileNotFound(); | |
| 85 | ✗ | result = false; | |
| 86 | } else { | ||
| 87 | ✗ | this->m_events.fileReadError(); | |
| 88 | ✗ | result = false; | |
| 89 | } | ||
| 90 | |||
| 91 | 33 | this->m_sequenceFile.close(); | |
| 92 | 33 | return result; | |
| 93 | } | ||
| 94 | |||
| 95 | 29 | bool AMPCSSequence ::validateCRC() { | |
| 96 | 29 | bool result = true; | |
| 97 | 29 | U32 computed = this->m_crc.finalize(); | |
| 98 |
2/2✓ Branch 4 taken 1 times.
✓ Branch 5 taken 28 times.
|
29 | if (this->m_crc.m_stored != computed) { |
| 99 | 1 | this->m_events.fileCRCFailure(this->m_crc.m_stored, computed); | |
| 100 | 1 | result = false; | |
| 101 | } | ||
| 102 | 29 | return result; | |
| 103 | } | ||
| 104 | |||
| 105 | 28 | bool AMPCSSequence ::validateRecords() { | |
| 106 | 28 | Fw::LinearBufferBase& buffer = this->m_buffer; | |
| 107 |
1/1✓ Branch 2 taken 28 times.
|
28 | Sequence::Record record; |
| 108 | |||
| 109 | // Deserialize all records and count the records | ||
| 110 |
1/1✓ Branch 7 taken 28 times.
|
28 | const U32 loopBound = static_cast<U32>(buffer.getDeserializeSizeLeft()); |
| 111 | 28 | U32 numRecords = 0; | |
| 112 |
1/2✓ Branch 0 taken 147 times.
✗ Branch 1 not taken.
|
147 | for (; numRecords < loopBound; ++numRecords) { |
| 113 |
3/3✓ Branch 7 taken 147 times.
✓ Branch 9 taken 26 times.
✓ Branch 10 taken 121 times.
|
147 | if (not this->hasMoreRecords()) { |
| 114 | 26 | break; | |
| 115 | } | ||
| 116 |
1/1✓ Branch 4 taken 121 times.
|
121 | Fw::SerializeStatus status = this->deserializeRecord(record); |
| 117 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 119 times.
|
121 | if (status != Fw::FW_SERIALIZE_OK) { |
| 118 |
1/1✓ Branch 4 taken 2 times.
|
2 | this->m_events.recordInvalid(numRecords, status); |
| 119 | 2 | return false; | |
| 120 | } | ||
| 121 | } | ||
| 122 | // Set the number of records | ||
| 123 | 26 | this->m_header.m_numRecords = numRecords; | |
| 124 | // Reset deserialization | ||
| 125 |
1/1✓ Branch 7 taken 26 times.
|
26 | this->reset(); |
| 126 | |||
| 127 | 26 | return true; | |
| 128 | 28 | } | |
| 129 | |||
| 130 | 197 | bool AMPCSSequence ::hasMoreRecords() const { | |
| 131 | 197 | return this->m_buffer.getDeserializeSizeLeft() > 0; | |
| 132 | } | ||
| 133 | |||
| 134 | 46 | void AMPCSSequence ::nextRecord(Sequence::Record& record) { | |
| 135 | 46 | Fw::SerializeStatus status = this->deserializeRecord(record); | |
| 136 | 46 | FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); | |
| 137 | 46 | } | |
| 138 | |||
| 139 | 29 | void AMPCSSequence ::reset() { | |
| 140 | 29 | this->m_buffer.resetDeser(); | |
| 141 | 29 | } | |
| 142 | |||
| 143 | 34 | void AMPCSSequence ::clear() { | |
| 144 | 34 | this->m_buffer.resetSer(); | |
| 145 | 34 | } | |
| 146 | |||
| 147 | 35 | bool AMPCSSequence ::readCRC() { | |
| 148 | 35 | Os::File& file = this->m_crcFile; | |
| 149 | 35 | Fw::LinearBufferBase& buffer = this->m_buffer; | |
| 150 | 35 | bool status = true; | |
| 151 | Fw::SerializeStatus ser_status; | ||
| 152 | |||
| 153 | 35 | FwSizeType readLen = static_cast<FwSizeType>(sizeof(U32)); | |
| 154 |
1/1✓ Branch 7 taken 35 times.
|
35 | ser_status = buffer.setBuffLen(static_cast<Fw::Serializable::SizeType>(readLen)); |
| 155 | 35 | FW_ASSERT(ser_status == Fw::FW_SERIALIZE_OK, ser_status); | |
| 156 | |||
| 157 | 35 | U8* const addr = buffer.getBuffAddr(); | |
| 158 |
1/1✓ Branch 4 taken 35 times.
|
35 | Os::File::Status fileStatus = file.read(addr, readLen); |
| 159 | |||
| 160 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
|
35 | if (fileStatus != Os::File::OP_OK) { |
| 161 | ✗ | this->m_events.fileInvalid(CmdSequencer_FileReadStage::READ_SEQ_CRC, fileStatus); | |
| 162 | ✗ | status = false; | |
| 163 | } | ||
| 164 | |||
| 165 | 35 | return status; | |
| 166 | } | ||
| 167 | |||
| 168 | 35 | bool AMPCSSequence ::deserializeCRC() { | |
| 169 | 35 | bool status = true; | |
| 170 | 35 | Fw::SerializeStatus serializeStatus = this->m_buffer.deserializeTo(this->m_crc.m_stored); | |
| 171 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
|
35 | if (serializeStatus != Fw::FW_SERIALIZE_OK) { |
| 172 | ✗ | this->m_events.fileInvalid(CmdSequencer_FileReadStage::READ_SEQ_CRC, serializeStatus); | |
| 173 | ✗ | status = false; | |
| 174 | } | ||
| 175 | 35 | return status; | |
| 176 | } | ||
| 177 | |||
| 178 | 33 | bool AMPCSSequence ::readOpenSequenceFile() { | |
| 179 | 33 | this->m_buffer.resetSer(); | |
| 180 | 33 | this->m_crc.init(); | |
| 181 | 33 | bool status = this->readSequenceHeader(); | |
| 182 |
2/2✓ Branch 0 taken 32 times.
✓ Branch 1 taken 1 times.
|
33 | if (status) { |
| 183 | 32 | this->m_crc.update(this->m_sequenceHeader, sizeof(this->m_sequenceHeader)); | |
| 184 | 32 | status = this->readRecords(); | |
| 185 | } | ||
| 186 |
2/2✓ Branch 0 taken 29 times.
✓ Branch 1 taken 4 times.
|
33 | if (status) { |
| 187 | 29 | U8* const buffAddr = this->m_buffer.getBuffAddr(); | |
| 188 | 29 | const FwSizeType buffLen = this->m_buffer.getSize(); | |
| 189 | 29 | FW_ASSERT(buffLen == this->m_header.m_fileSize, static_cast<FwAssertArgType>(buffLen), | |
| 190 | static_cast<FwAssertArgType>(this->m_header.m_fileSize)); | ||
| 191 | 29 | this->m_crc.update(buffAddr, buffLen); | |
| 192 | } | ||
| 193 | 33 | return status; | |
| 194 | } | ||
| 195 | |||
| 196 | 33 | bool AMPCSSequence ::readSequenceHeader() { | |
| 197 | 33 | Os::File& file = this->m_sequenceFile; | |
| 198 | |||
| 199 | 33 | bool status = true; | |
| 200 | |||
| 201 | 33 | FwSizeType readLen = sizeof this->m_sequenceHeader; | |
| 202 |
1/1✓ Branch 6 taken 33 times.
|
33 | const Os::File::Status fileStatus = file.read(this->m_sequenceHeader, readLen); |
| 203 | |||
| 204 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 32 times.
|
33 | if (fileStatus != Os::File::OP_OK) { |
| 205 |
1/1✓ Branch 4 taken 1 times.
|
1 | this->m_events.fileInvalid(CmdSequencer_FileReadStage::READ_HEADER, fileStatus); |
| 206 | 1 | status = false; | |
| 207 | } | ||
| 208 | |||
| 209 |
3/4✓ Branch 0 taken 32 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
|
33 | if (status and readLen != sizeof this->m_sequenceHeader) { |
| 210 | ✗ | this->m_events.fileInvalid(CmdSequencer_FileReadStage::READ_HEADER_SIZE, static_cast<I32>(readLen)); | |
| 211 | ✗ | status = false; | |
| 212 | } | ||
| 213 | |||
| 214 | 33 | return status; | |
| 215 | } | ||
| 216 | |||
| 217 | 32 | bool AMPCSSequence ::readRecords() { | |
| 218 | 32 | Os::File& file = this->m_sequenceFile; | |
| 219 | 32 | const FwSizeType size = this->m_header.m_fileSize; | |
| 220 | 32 | Fw::LinearBufferBase& buffer = this->m_buffer; | |
| 221 | 32 | U8* const addr = buffer.getBuffAddr(); | |
| 222 | |||
| 223 | // Check file size | ||
| 224 |
2/2✓ Branch 6 taken 1 times.
✓ Branch 7 taken 31 times.
|
32 | if (size > this->m_buffer.getCapacity()) { |
| 225 |
1/1✓ Branch 4 taken 1 times.
|
1 | this->m_events.fileSizeError(static_cast<U32>(size)); |
| 226 | 1 | return false; | |
| 227 | } | ||
| 228 | |||
| 229 | 31 | FwSizeType readLen = size; | |
| 230 |
1/1✓ Branch 4 taken 31 times.
|
31 | const Os::File::Status fileStatus = file.read(addr, readLen); |
| 231 | // Check read status | ||
| 232 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 30 times.
|
31 | if (fileStatus != Os::File::OP_OK) { |
| 233 |
1/1✓ Branch 4 taken 1 times.
|
1 | this->m_events.fileInvalid(CmdSequencer_FileReadStage::READ_SEQ_DATA, fileStatus); |
| 234 | 1 | return false; | |
| 235 | } | ||
| 236 | // Check read size | ||
| 237 | 30 | const FwSizeType readLenUint = static_cast<FwSizeType>(readLen); | |
| 238 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 29 times.
|
30 | if (readLenUint != size) { |
| 239 |
1/1✓ Branch 4 taken 1 times.
|
1 | this->m_events.fileInvalid(CmdSequencer_FileReadStage::READ_SEQ_DATA_SIZE, static_cast<I32>(readLen)); |
| 240 | 1 | return false; | |
| 241 | } | ||
| 242 | // set buffer size | ||
| 243 |
1/1✓ Branch 7 taken 29 times.
|
29 | const Fw::SerializeStatus serializeStatus = buffer.setBuffLen(size); |
| 244 | 29 | FW_ASSERT(serializeStatus == Fw::FW_SERIALIZE_OK, serializeStatus); | |
| 245 | 29 | return true; | |
| 246 | } | ||
| 247 | |||
| 248 | 167 | Fw::SerializeStatus AMPCSSequence ::deserializeRecord(Sequence::Record& record) { | |
| 249 | 167 | Record::CmdLength::t cmdLength; | |
| 250 | |||
| 251 |
1/1✓ Branch 6 taken 167 times.
|
167 | Fw::SerializeStatus status = this->deserializeTimeFlag(record.m_descriptor); |
| 252 | |||
| 253 |
2/2✓ Branch 0 taken 165 times.
✓ Branch 1 taken 2 times.
|
167 | if (status == Fw::FW_SERIALIZE_OK) { |
| 254 |
1/1✓ Branch 7 taken 165 times.
|
165 | status = this->deserializeTime(record.m_timeTag); |
| 255 | } | ||
| 256 |
2/2✓ Branch 0 taken 165 times.
✓ Branch 1 taken 2 times.
|
167 | if (status == Fw::FW_SERIALIZE_OK) { |
| 257 |
1/1✓ Branch 4 taken 165 times.
|
165 | status = this->deserializeCmdLength(cmdLength); |
| 258 | } | ||
| 259 |
2/2✓ Branch 0 taken 165 times.
✓ Branch 1 taken 2 times.
|
167 | if (status == Fw::FW_SERIALIZE_OK) { |
| 260 |
1/1✓ Branch 7 taken 165 times.
|
165 | status = this->translateCommand(record.m_command, cmdLength); |
| 261 | } | ||
| 262 | |||
| 263 | 167 | return status; | |
| 264 | } | ||
| 265 | |||
| 266 | 167 | Fw::SerializeStatus AMPCSSequence ::deserializeTimeFlag(Sequence::Record::Descriptor& descriptor) { | |
| 267 | 167 | Fw::LinearBufferBase& buffer = this->m_buffer; | |
| 268 | 167 | Record::TimeFlag::Serial::t timeFlagSerial; | |
| 269 |
1/1✓ Branch 7 taken 167 times.
|
167 | Fw::SerializeStatus status = buffer.deserializeTo(timeFlagSerial); |
| 270 |
1/2✓ Branch 0 taken 167 times.
✗ Branch 1 not taken.
|
167 | if (status == Fw::FW_SERIALIZE_OK) { |
| 271 |
3/3✓ Branch 0 taken 4 times.
✓ Branch 1 taken 161 times.
✓ Branch 2 taken 2 times.
|
167 | switch (timeFlagSerial) { |
| 272 | 4 | case Record::TimeFlag::ABSOLUTE: | |
| 273 | 4 | descriptor = Sequence::Record::ABSOLUTE; | |
| 274 | 4 | break; | |
| 275 | 161 | case Record::TimeFlag::RELATIVE: | |
| 276 | 161 | descriptor = Sequence::Record::RELATIVE; | |
| 277 | 161 | break; | |
| 278 | 2 | default: | |
| 279 | 2 | status = Fw::FW_DESERIALIZE_FORMAT_ERROR; | |
| 280 | 2 | break; | |
| 281 | } | ||
| 282 | } | ||
| 283 | 167 | return status; | |
| 284 | } | ||
| 285 | |||
| 286 | 165 | Fw::SerializeStatus AMPCSSequence ::deserializeTime(Fw::Time& timeTag) { | |
| 287 | 165 | Record::Time::t time; | |
| 288 | 165 | Fw::LinearBufferBase& buffer = this->m_buffer; | |
| 289 |
1/1✓ Branch 7 taken 165 times.
|
165 | Fw::SerializeStatus status = buffer.deserializeTo(time); |
| 290 |
1/2✓ Branch 0 taken 165 times.
✗ Branch 1 not taken.
|
165 | if (status == Fw::FW_SERIALIZE_OK) { |
| 291 |
1/1✓ Branch 4 taken 165 times.
|
165 | timeTag.set(time, 0); |
| 292 | } | ||
| 293 | 165 | return status; | |
| 294 | } | ||
| 295 | |||
| 296 | 165 | Fw::SerializeStatus AMPCSSequence ::deserializeCmdLength(Record::CmdLength::t& cmdLength) { | |
| 297 | 165 | Fw::LinearBufferBase& buffer = this->m_buffer; | |
| 298 | 165 | Fw::SerializeStatus status = buffer.deserializeTo(cmdLength); | |
| 299 |
3/6✓ Branch 0 taken 165 times.
✗ Branch 1 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 165 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 165 times.
|
165 | if (status == Fw::FW_SERIALIZE_OK and cmdLength > buffer.getDeserializeSizeLeft()) { |
| 300 | // Not enough data left | ||
| 301 | ✗ | status = Fw::FW_DESERIALIZE_SIZE_MISMATCH; | |
| 302 | } | ||
| 303 | // The translated record occupies the packet descriptor, the zero-extension bytes prepended to | ||
| 304 | // the two-byte AMPCS opcode, and the record body. It must fit the ComBuffer capacity: | ||
| 305 | // SERIALIZED_SIZE is the capacity plus the stored length, and comparing against it admits | ||
| 306 | // records that setBuffLen then rejects, asserting in translateCommand | ||
| 307 | 165 | const FwSizeType translatedSize = | |
| 308 | 165 | sizeof(FwPacketDescriptorType) + (sizeof(FwOpcodeType) - 2) + static_cast<FwSizeType>(cmdLength); | |
| 309 |
2/4✓ Branch 0 taken 165 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 165 times.
|
165 | if (status == Fw::FW_SERIALIZE_OK and translatedSize > FW_COM_BUFFER_MAX_SIZE) { |
| 310 | // Record size is too big for com buffer | ||
| 311 | ✗ | status = Fw::FW_DESERIALIZE_SIZE_MISMATCH; | |
| 312 | } | ||
| 313 | 165 | return status; | |
| 314 | } | ||
| 315 | |||
| 316 | 165 | Fw::SerializeStatus AMPCSSequence ::translateCommand(Fw::ComBuffer& comBuffer, const Record::CmdLength::t cmdLength) { | |
| 317 | 165 | Fw::LinearBufferBase& buffer = this->m_buffer; | |
| 318 |
1/1✓ Branch 5 taken 165 times.
|
165 | comBuffer.resetSer(); |
| 319 | // Serialize the command packet descriptor | ||
| 320 | 165 | const FwPacketDescriptorType cmdDescriptor = Fw::ComPacketType::FW_PACKET_COMMAND; | |
| 321 |
1/1✓ Branch 5 taken 165 times.
|
165 | Fw::SerializeStatus status = comBuffer.serializeFrom(cmdDescriptor); |
| 322 | 165 | FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); | |
| 323 | // Zero-extend the two-byte AMPCS opcode by (sizeof(FwOpcodeType) - 2) bytes | ||
| 324 | static_assert(sizeof(FwOpcodeType) >= 2, "FwOpcodeType must be at least two bytes wide"); | ||
| 325 | 165 | U32 sizeOfZeros = 0; | |
| 326 | 165 | const FwIndexType bytesToExtend = sizeof(FwOpcodeType) - 2; | |
| 327 | 165 | const U8 zeros = 0; | |
| 328 |
2/2✓ Branch 0 taken 330 times.
✓ Branch 1 taken 165 times.
|
495 | for (FwIndexType i = 0; i < bytesToExtend; i++) { |
| 329 |
1/1✓ Branch 5 taken 330 times.
|
330 | status = comBuffer.serializeFrom(zeros); |
| 330 | 330 | FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); | |
| 331 | 330 | sizeOfZeros += static_cast<U32>(sizeof(zeros)); | |
| 332 | } | ||
| 333 | // Set the buffer length | ||
| 334 |
1/1✓ Branch 5 taken 165 times.
|
165 | const U32 fixedBuffLen = static_cast<U32>(comBuffer.getSize()); |
| 335 | 165 | FW_ASSERT(fixedBuffLen == sizeof(cmdDescriptor) + sizeOfZeros, static_cast<FwAssertArgType>(fixedBuffLen)); | |
| 336 | 165 | const U32 totalBuffLen = fixedBuffLen + cmdLength; | |
| 337 |
1/1✓ Branch 5 taken 165 times.
|
165 | status = comBuffer.setBuffLen(totalBuffLen); |
| 338 | 165 | FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status); | |
| 339 | // Copy the opcode and argument bytes | ||
| 340 | 165 | FwSizeType size = cmdLength; | |
| 341 | 165 | U8* const addr = comBuffer.getBuffAddr(); | |
| 342 | 165 | FW_ASSERT(addr != nullptr); | |
| 343 | // true means "don't serialize the length" | ||
| 344 |
1/1✓ Branch 8 taken 165 times.
|
165 | status = buffer.deserializeTo(&addr[fixedBuffLen], size, Fw::Serialization::OMIT_LENGTH); |
| 345 | 165 | return status; | |
| 346 | } | ||
| 347 | |||
| 348 | } // namespace Svc | ||
| 349 |