diff --git a/Os/File.cpp b/Os/File.cpp index b2619fde2ca..8bd0e517739 100644 --- a/Os/File.cpp +++ b/Os/File.cpp @@ -4,11 +4,9 @@ // ====================================================================== #include #include +#include #include -extern "C" { -#include // borrow CRC -} namespace Os { File::File() : m_crc_buffer(), m_handle_storage(), m_delegate(*FileInterface::getDelegate(m_handle_storage)) { @@ -229,7 +227,7 @@ File::Status File::calculateCrc(U32& crc) { File::Status File::incrementalCrc(FwSizeType& size) { File::Status status = File::Status::OP_OK; - FW_ASSERT(size <= FW_FILE_CHUNK_SIZE); + FW_ASSERT(size <= FW_FILE_CHUNK_SIZE, FwAssertArgType(size)); if (OPEN_NO_MODE == this->m_mode) { status = File::Status::NOT_OPENED; } else if (OPEN_READ != this->m_mode) { @@ -238,9 +236,14 @@ File::Status File::incrementalCrc(FwSizeType& size) { // Read data without waiting for additional data to be available status = this->read(this->m_crc_buffer, size, File::WaitType::NO_WAIT); if (OP_OK == status) { - for (FwSizeType i = 0; i < size && i < FW_FILE_CHUNK_SIZE; i++) { - this->m_crc = static_cast(update_crc_32(this->m_crc, static_cast(this->m_crc_buffer[i]))); - } + FW_ASSERT(size <= FW_FILE_CHUNK_SIZE, FwAssertArgType(size)); + // FIXME: Utils::Hash should be integrated more carefully into File + Utils::Hash hash; + hash.setHashValue(U32(~this->m_crc)); + hash.update(this->m_crc_buffer, size); + U32 crc; + hash.finalize(crc); + this->m_crc = ~crc; } } return status; diff --git a/Os/test/ut/file/FileRules.cpp b/Os/test/ut/file/FileRules.cpp index 1e871646084..5d5ad99a817 100644 --- a/Os/test/ut/file/FileRules.cpp +++ b/Os/test/ut/file/FileRules.cpp @@ -6,9 +6,7 @@ #include #include "RulesHeaders.hpp" #include "STest/Pick/Pick.hpp" -extern "C" { -#include // borrow CRC -} +#include "Utils/Hash/Hash.hpp" // For testing, limit files to 32K const FwSizeType FILE_DATA_MAXIMUM = 32 * 1024; @@ -82,14 +80,22 @@ void Os::Test::FileTest::Tester::shadow_flush() { } void Os::Test::FileTest::Tester::shadow_crc(U32& crc) { - crc = this->m_independent_crc; + Utils::Hash hash; + hash.setHashValue(U32(~this->m_independent_crc)); + SyntheticFileData& data = *reinterpret_cast(this->m_shadow.getHandle()); // Calculate CRC on full file starting at m_pointer for (FwSizeType i = data.m_pointer; i < data.m_data.size(); i++, this->m_shadow.seek(1, Os::File::SeekType::RELATIVE)) { - crc = update_crc_32(crc, static_cast(data.m_data.at(i))); + U8 byte = data.m_data.at(i); + hash.update(&byte, sizeof(byte)); } + + U32 crcFinal; + hash.finalize(crcFinal); + crc = ~crcFinal; + // Update tracking variables this->m_independent_crc = Os::File::INITIAL_CRC; } @@ -102,7 +108,16 @@ void Os::Test::FileTest::Tester::shadow_partial_crc(FwSizeType& size) { std::min(static_cast(data.m_pointer) + size, static_cast(data.m_data.size())); size = (data.m_pointer >= bound) ? 0 : static_cast(bound - data.m_pointer); for (FwSizeType i = data.m_pointer; i < bound; i++) { - this->m_independent_crc = update_crc_32(this->m_independent_crc, static_cast(data.m_data.at(i))); + U8 byte = data.m_data.at(i); + + Utils::Hash hash; + hash.setHashValue(U32(~this->m_independent_crc)); + hash.update(&byte, sizeof(byte)); + + U32 crcFinal; + hash.finalize(crcFinal); + this->m_independent_crc = ~crcFinal; + this->m_shadow.seek(1, Os::File::SeekType::RELATIVE); } } diff --git a/Svc/Ccsds/Utils/CRC16.hpp b/Svc/Ccsds/Utils/CRC16.hpp index 9ce16090fbf..6d2113ecd63 100644 --- a/Svc/Ccsds/Utils/CRC16.hpp +++ b/Svc/Ccsds/Utils/CRC16.hpp @@ -2,7 +2,7 @@ #define SVC_CCSDS_UTILS_CRC16_HPP #include "Fw/Types/BasicTypes.hpp" -// Include the lic crc c library: +// Include the libcrc library because we need update_crc_ccitt that is not provided through the main interface. extern "C" { #include } diff --git a/Svc/CmdSequencer/CmdSequencerImpl.cpp b/Svc/CmdSequencer/CmdSequencerImpl.cpp index f105e65b984..326c4b9c6e6 100644 --- a/Svc/CmdSequencer/CmdSequencerImpl.cpp +++ b/Svc/CmdSequencer/CmdSequencerImpl.cpp @@ -12,9 +12,7 @@ #include #include #include -extern "C" { -#include -} +#include namespace Svc { diff --git a/Svc/CmdSequencer/CmdSequencerImpl.hpp b/Svc/CmdSequencer/CmdSequencerImpl.hpp index c10c5d01fe7..f12f4a1378c 100644 --- a/Svc/CmdSequencer/CmdSequencerImpl.hpp +++ b/Svc/CmdSequencer/CmdSequencerImpl.hpp @@ -11,6 +11,7 @@ #ifndef Svc_CmdSequencerImpl_HPP #define Svc_CmdSequencerImpl_HPP +#include #include "Fw/Com/ComBuffer.hpp" #include "Fw/Types/MemAllocator.hpp" #include "Os/File.hpp" @@ -297,11 +298,8 @@ class CmdSequencerComponentImpl final : public CmdSequencerComponentBase { FwSizeType bufferSize //!< The buffer size ); - //! Finalize computed CRC - void finalize(); - //! Computed CRC - U32 m_computed; + Utils::Hash m_computed; //! Stored CRC U32 m_stored; diff --git a/Svc/CmdSequencer/FPrimeSequence.cpp b/Svc/CmdSequencer/FPrimeSequence.cpp index 1cbd2bef2f4..a76bb82fe7d 100644 --- a/Svc/CmdSequencer/FPrimeSequence.cpp +++ b/Svc/CmdSequencer/FPrimeSequence.cpp @@ -10,27 +10,18 @@ #include "Fw/Types/Assert.hpp" #include "Svc/CmdSequencer/CmdSequencerImpl.hpp" -extern "C" { -#include "Utils/Hash/libcrc/lib_crc.h" -} namespace Svc { -CmdSequencerComponentImpl::FPrimeSequence::CRC ::CRC() : m_computed(INITIAL_COMPUTED_VALUE), m_stored(0) {} +CmdSequencerComponentImpl::FPrimeSequence::CRC ::CRC() : m_computed(), m_stored(0) {} void CmdSequencerComponentImpl::FPrimeSequence::CRC ::init() { - this->m_computed = INITIAL_COMPUTED_VALUE; + this->m_computed.init(); } void CmdSequencerComponentImpl::FPrimeSequence::CRC ::update(const BYTE* buffer, FwSizeType bufferSize) { FW_ASSERT(buffer); - for (FwSizeType index = 0; index < bufferSize; index++) { - this->m_computed = static_cast(update_crc_32(this->m_computed, static_cast(buffer[index]))); - } -} - -void CmdSequencerComponentImpl::FPrimeSequence::CRC ::finalize() { - this->m_computed = ~this->m_computed; + this->m_computed.update(buffer, bufferSize); } CmdSequencerComponentImpl::FPrimeSequence ::FPrimeSequence(CmdSequencerComponentImpl& component) @@ -38,8 +29,10 @@ CmdSequencerComponentImpl::FPrimeSequence ::FPrimeSequence(CmdSequencerComponent bool CmdSequencerComponentImpl::FPrimeSequence ::validateCRC() { bool result = true; - if (this->m_crc.m_stored != this->m_crc.m_computed) { - this->m_events.fileCRCFailure(this->m_crc.m_stored, this->m_crc.m_computed); + U32 computed; + this->m_crc.m_computed.finalize(computed); + if (this->m_crc.m_stored != computed) { + this->m_events.fileCRCFailure(this->m_crc.m_stored, computed); result = false; } return result; @@ -104,7 +97,6 @@ bool CmdSequencerComponentImpl::FPrimeSequence ::readOpenFile() { if (status) { const FwSizeType buffLen = this->m_buffer.getSize(); this->m_crc.update(buffAddr, buffLen); - this->m_crc.finalize(); } return status; } diff --git a/Svc/CmdSequencer/formats/AMPCSSequence.cpp b/Svc/CmdSequencer/formats/AMPCSSequence.cpp index 397ccf9e438..6c55bc9ed65 100644 --- a/Svc/CmdSequencer/formats/AMPCSSequence.cpp +++ b/Svc/CmdSequencer/formats/AMPCSSequence.cpp @@ -10,12 +10,10 @@ // ====================================================================== #include "Svc/CmdSequencer/formats/AMPCSSequence.hpp" +#include #include "Fw/Com/ComPacket.hpp" #include "Fw/Types/Assert.hpp" #include "Os/FileSystem.hpp" -extern "C" { -#include "Utils/Hash/libcrc/lib_crc.h" -} namespace Svc { @@ -96,8 +94,10 @@ bool AMPCSSequence ::readSequenceFile(const Fw::ConstStringBase& seqFileName) { bool AMPCSSequence ::validateCRC() { bool result = true; - if (this->m_crc.m_stored != this->m_crc.m_computed) { - this->m_events.fileCRCFailure(this->m_crc.m_stored, this->m_crc.m_computed); + U32 computed; + this->m_crc.m_computed.finalize(computed); + if (this->m_crc.m_stored != computed) { + this->m_events.fileCRCFailure(this->m_crc.m_stored, computed); result = false; } return result; @@ -190,7 +190,6 @@ bool AMPCSSequence ::readOpenSequenceFile() { FW_ASSERT(buffLen == this->m_header.m_fileSize, static_cast(buffLen), static_cast(this->m_header.m_fileSize)); this->m_crc.update(buffAddr, buffLen); - this->m_crc.finalize(); } return status; } diff --git a/Svc/CmdSequencer/test/ut/InvalidFiles.cpp b/Svc/CmdSequencer/test/ut/InvalidFiles.cpp index e90041dabad..a326df6cfe2 100644 --- a/Svc/CmdSequencer/test/ut/InvalidFiles.cpp +++ b/Svc/CmdSequencer/test/ut/InvalidFiles.cpp @@ -46,7 +46,9 @@ void CmdSequencerTester ::BadCRC() { // Assert events const CmdSequencerComponentImpl::FPrimeSequence::CRC& crc = file.getCRC(); ASSERT_EVENTS_SIZE(1); - ASSERT_EVENTS_CS_FileCrcFailure(0, file.getName().toChar(), crc.m_stored, crc.m_computed); + U32 crcFinal; + crc.m_computed.finalize(crcFinal); + ASSERT_EVENTS_CS_FileCrcFailure(0, file.getName().toChar(), crc.m_stored, crcFinal); // Assert telemetry ASSERT_TLM_SIZE(1); ASSERT_TLM_CS_Errors(0, 1); diff --git a/Svc/CmdSequencer/test/ut/SequenceFiles/AMPCS/CRCs.cpp b/Svc/CmdSequencer/test/ut/SequenceFiles/AMPCS/CRCs.cpp index e54df5c3d21..0f84d6a293d 100644 --- a/Svc/CmdSequencer/test/ut/SequenceFiles/AMPCS/CRCs.cpp +++ b/Svc/CmdSequencer/test/ut/SequenceFiles/AMPCS/CRCs.cpp @@ -55,7 +55,9 @@ void writeFile(Os::File& file, //!< The file void createFile(Fw::SerializeBufferBase& buffer, const char* const fileName) { CRC crc; computeCRC(buffer, crc); - writeCRC(crc.m_computed, fileName); + U32 crcFinal; + crc.m_computed.finalize(crcFinal); + writeCRC(crcFinal, fileName); } void computeCRC(Fw::SerializeBufferBase& buffer, CRC& crc) { @@ -63,7 +65,6 @@ void computeCRC(Fw::SerializeBufferBase& buffer, CRC& crc) { const U8* const addr = buffer.getBuffAddr(); const U32 size = buffer.getSize(); crc.update(addr, size); - crc.finalize(); } void removeFile(const char* const fileName) { diff --git a/Svc/CmdSequencer/test/ut/SequenceFiles/BadCRCFile.cpp b/Svc/CmdSequencer/test/ut/SequenceFiles/BadCRCFile.cpp index 8441d8aa8ce..46f5898e4d6 100644 --- a/Svc/CmdSequencer/test/ut/SequenceFiles/BadCRCFile.cpp +++ b/Svc/CmdSequencer/test/ut/SequenceFiles/BadCRCFile.cpp @@ -36,8 +36,9 @@ void BadCRCFile ::serializeFPrime(Fw::SerializeBufferBase& buffer) { const U32 size = buffer.getSize(); this->crc.init(); this->crc.update(addr, size); - this->crc.finalize(); - crc.m_stored = this->crc.m_computed + 1; + U32 crcFinal; + this->crc.m_computed.finalize(crcFinal); + crc.m_stored = crcFinal + 1; ASSERT_EQ(Fw::FW_SERIALIZE_OK, buffer.serializeFrom(this->crc.m_stored)); } @@ -49,7 +50,9 @@ void BadCRCFile ::serializeAMPCS(Fw::SerializeBufferBase& buffer) { ASSERT_EQ(Fw::FW_SERIALIZE_OK, buffer.serializeFrom(recordData)); // CRC AMPCS::CRCs::computeCRC(buffer, this->crc); - this->crc.m_stored = this->crc.m_computed + 1; + U32 crcFinal; + this->crc.m_computed.finalize(crcFinal); + crc.m_stored = crcFinal + 1; AMPCS::CRCs::writeCRC(this->crc.m_stored, this->getName().toChar()); } diff --git a/Svc/CmdSequencer/test/ut/SequenceFiles/FPrime/CRCs.cpp b/Svc/CmdSequencer/test/ut/SequenceFiles/FPrime/CRCs.cpp index bfb55120733..19ab861f3cf 100644 --- a/Svc/CmdSequencer/test/ut/SequenceFiles/FPrime/CRCs.cpp +++ b/Svc/CmdSequencer/test/ut/SequenceFiles/FPrime/CRCs.cpp @@ -23,8 +23,9 @@ void serialize(Fw::SerializeBufferBase& destBuffer) { CmdSequencerComponentImpl::FPrimeSequence::CRC crc; crc.init(); crc.update(destBuffer.getBuffAddr(), destBuffer.getSize()); - crc.finalize(); - ASSERT_EQ(destBuffer.serializeFrom(crc.m_computed), Fw::FW_SERIALIZE_OK); + U32 crcFinal; + crc.m_computed.finalize(crcFinal); + ASSERT_EQ(destBuffer.serializeFrom(crcFinal), Fw::FW_SERIALIZE_OK); } } // namespace CRCs diff --git a/Svc/FpySequencer/FpySequencer.cpp b/Svc/FpySequencer/FpySequencer.cpp index 4fd12c50de1..82fbf734bf8 100644 --- a/Svc/FpySequencer/FpySequencer.cpp +++ b/Svc/FpySequencer/FpySequencer.cpp @@ -19,7 +19,7 @@ FpySequencer ::FpySequencer(const char* const compName) m_allocatorId(0), m_sequenceFilePath(""), m_sequenceObj(), - m_computedCRC(0), + m_computedCRC(), m_sequenceBlockState(), m_savedOpCode(0), m_savedCmdSeq(0), diff --git a/Svc/FpySequencer/FpySequencer.hpp b/Svc/FpySequencer/FpySequencer.hpp index 703229d5b66..20ac552e771 100644 --- a/Svc/FpySequencer/FpySequencer.hpp +++ b/Svc/FpySequencer/FpySequencer.hpp @@ -21,6 +21,7 @@ #include "Svc/FpySequencer/HeaderSerializableAc.hpp" #include "Svc/FpySequencer/SequenceSerializableAc.hpp" #include "Svc/FpySequencer/StatementSerializableAc.hpp" +#include "Utils/Hash/Hash.hpp" #include "config/FppConstantsAc.hpp" static_assert(Svc::Fpy::MAX_SEQUENCE_ARG_COUNT <= std::numeric_limits::max(), @@ -604,7 +605,7 @@ class FpySequencer : public FpySequencerComponentBase { // the sequence, loaded in memory Fpy::Sequence m_sequenceObj; // live running computation of CRC (updated as we read) - U32 m_computedCRC; + Utils::Hash m_computedCRC; // whether or not the sequence we're about to run should return immediately or // block on completion @@ -709,11 +710,6 @@ class FpySequencer : public FpySequencerComponentBase { // Validation state // ---------------------------------------------------------------------- - static void updateCrc(U32& crc, //!< The CRC to update - const U8* buffer, //!< The buffer - FwSizeType bufferSize //!< The buffer size - ); - // loads the sequence in memory, and does header/crc/integrity checks. // return SUCCESS if sequence is valid, FAILURE otherwise Fw::Success validate(); diff --git a/Svc/FpySequencer/FpySequencerValidationState.cpp b/Svc/FpySequencer/FpySequencerValidationState.cpp index fdf2edc03e4..d1882253059 100644 --- a/Svc/FpySequencer/FpySequencerValidationState.cpp +++ b/Svc/FpySequencer/FpySequencerValidationState.cpp @@ -1,8 +1,7 @@ +#include #include "Svc/FpySequencer/FppConstantsAc.hpp" #include "Svc/FpySequencer/FpySequencer.hpp" -extern "C" { -#include "Utils/Hash/libcrc/lib_crc.h" -} + namespace Svc { void FpySequencer::allocateBuffer(FwEnumStoreType identifier, Fw::MemAllocator& allocator, FwSizeType bytes) { @@ -24,13 +23,6 @@ void FpySequencer::deallocateBuffer(Fw::MemAllocator& allocator) { this->m_sequenceBuffer.clear(); } -void FpySequencer::updateCrc(U32& crc, const U8* buffer, FwSizeType bufferSize) { - FW_ASSERT(buffer); - for (FwSizeType index = 0; index < bufferSize; index++) { - crc = static_cast(update_crc_32(crc, static_cast(buffer[index]))); - } -} - // loads the sequence in memory, and does header/crc/integrity checks. // return SUCCESS if sequence is valid, FAILURE otherwise Fw::Success FpySequencer::validate() { @@ -38,7 +30,7 @@ Fw::Success FpySequencer::validate() { // crc needs to be initialized with a particular value // for the calculation to work - this->m_computedCRC = CRC_INITIAL_VALUE; + this->m_computedCRC.init(); Os::File sequenceFile; Os::File::Status openStatus = sequenceFile.open(this->m_sequenceFilePath.toChar(), Os::File::OPEN_READ); @@ -179,10 +171,11 @@ Fw::Success FpySequencer::readFooter() { } // need this for some reason to "finalize" the crc TODO get an explanation on this - this->m_computedCRC = ~this->m_computedCRC; + U32 computedCRC; + this->m_computedCRC.finalize(computedCRC); - if (this->m_computedCRC != this->m_sequenceObj.get_footer().get_crc()) { - this->log_WARNING_HI_WrongCRC(this->m_sequenceObj.get_footer().get_crc(), this->m_computedCRC); + if (computedCRC != this->m_sequenceObj.get_footer().get_crc()) { + this->log_WARNING_HI_WrongCRC(this->m_sequenceObj.get_footer().get_crc(), computedCRC); return Fw::Success::FAILURE; } @@ -229,7 +222,7 @@ Fw::Success FpySequencer::readBytes(Os::File& file, FW_ASSERT(serializeStatus == Fw::FW_SERIALIZE_OK, serializeStatus); if (updateCrc) { - FpySequencer::updateCrc(this->m_computedCRC, this->m_sequenceBuffer.getBuffAddr(), expectedReadLen); + this->m_computedCRC.update(this->m_sequenceBuffer.getBuffAddr(), expectedReadLen); } return Fw::Success::SUCCESS; diff --git a/Svc/FpySequencer/test/ut/FpySequencerTester.cpp b/Svc/FpySequencer/test/ut/FpySequencerTester.cpp index e4d918ee2bd..4692112ae2c 100644 --- a/Svc/FpySequencer/test/ut/FpySequencerTester.cpp +++ b/Svc/FpySequencer/test/ut/FpySequencerTester.cpp @@ -82,10 +82,12 @@ void FpySequencerTester::writeToFile(const char* name, FwSizeType maxBytes) { ASSERT_EQ(buf.serializeFrom(seq.get_statements()[ii]), Fw::SerializeStatus::FW_SERIALIZE_OK); } - U32 crc = FpySequencer::CRC_INITIAL_VALUE; - FpySequencer::updateCrc(crc, buf.getBuffAddr(), buf.getSize()); + Utils::Hash hash; + hash.update(buf.getBuffAddr(), buf.getSize()); + U32 crc; + hash.finalize(crc); - seq.get_footer().set_crc(~crc); + seq.get_footer().set_crc(crc); ASSERT_EQ(buf.serializeFrom(seq.get_footer()), Fw::SerializeStatus::FW_SERIALIZE_OK); @@ -648,7 +650,7 @@ void FpySequencerTester::tester_set_m_statementsDispatched(U64 val) { } void FpySequencerTester::tester_set_m_computedCRC(U32 crc) { - this->cmp.m_computedCRC = crc; + this->cmp.m_computedCRC.setHashValue(U32(~crc)); } // Get cmp member pointers diff --git a/Svc/PrmDb/PrmDbImpl.cpp b/Svc/PrmDb/PrmDbImpl.cpp index b8f30fbc535..a5c97f29dd3 100644 --- a/Svc/PrmDb/PrmDbImpl.cpp +++ b/Svc/PrmDb/PrmDbImpl.cpp @@ -9,9 +9,7 @@ #include #include -extern "C" { -#include -} +#include #include #include @@ -117,28 +115,6 @@ void PrmDbImpl::pingIn_handler(FwIndexType portNum, U32 key) { this->pingOut_out(0, key); } -U32 PrmDbImpl::computeCrc(U32 crc, const BYTE* buff, FwSizeType size) { - // Note: The crc parameter accepts any U32 value as valid input. - // This is correct behavior for CRC32 accumulation functions where: - // - Initial CRC values are typically 0x00000000 or 0xFFFFFFFF - // - Intermediate CRC values (from prior computeCrc calls) can be any U32 value - - // Check for null pointer before dereferencing - if (buff == nullptr) { - // Return the input CRC unchanged if buffer is null - return crc; - } - - // Check for zero size to avoid unnecessary processing - if (size == 0) { - return crc; - } - for (FwSizeType byte = 0; byte < size; byte++) { - crc = static_cast(update_crc_32(crc, static_cast(buff[byte]))); - } - return crc; -} - void PrmDbImpl::PRM_SAVE_FILE_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) { // Reject PRM_SAVE_FILE command during non-idle file load states if (m_state != PrmDbFileLoadState::IDLE) { @@ -160,9 +136,10 @@ void PrmDbImpl::PRM_SAVE_FILE_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) { } // write placeholder for the CRC - U32 crc = 0xFFFFFFFF; - FwSizeType writeSize = static_cast(sizeof(crc)); - stat = paramFile.write(reinterpret_cast(&crc), writeSize, Os::File::WaitType::WAIT); + Utils::Hash crc; + FwSizeType writeSize = static_cast(HASH_DIGEST_LENGTH); + U32 crcInitial = U32(~0); + stat = paramFile.write(reinterpret_cast(&crcInitial), writeSize, Os::File::WaitType::WAIT); if (stat != Os::File::OP_OK) { this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::CRC_PLACE, 0, stat); @@ -198,7 +175,7 @@ void PrmDbImpl::PRM_SAVE_FILE_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) { } // add delimiter to CRC - crc = this->computeCrc(crc, &delim, sizeof(delim)); + crc.update(&delim, sizeof(delim)); // serialize record size = id field + data U32 recordSize = static_cast(sizeof(FwPrmIdType) + entry.getValue().getSize()); @@ -227,7 +204,9 @@ void PrmDbImpl::PRM_SAVE_FILE_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) { } // add recordSize to CRC - crc = this->computeCrc(crc, buff.getBuffAddr(), writeSize); + if (buff.getBuffAddr() != nullptr && writeSize != 0) { + crc.update(buff.getBuffAddr(), writeSize); + } // reset buffer buff.resetSer(); @@ -256,7 +235,9 @@ void PrmDbImpl::PRM_SAVE_FILE_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) { } // add parameter ID to CRC - crc = this->computeCrc(crc, buff.getBuffAddr(), writeSize); + if (buff.getBuffAddr() != nullptr && writeSize != 0) { + crc.update(buff.getBuffAddr(), writeSize); + } // write serialized parameter value @@ -277,7 +258,9 @@ void PrmDbImpl::PRM_SAVE_FILE_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) { } // add serialized parameter value to crc - crc = this->computeCrc(crc, entry.getValue().getBuffAddr(), writeSize); + if (entry.getValue().getBuffAddr() != nullptr && writeSize != 0) { + crc.update(entry.getValue().getBuffAddr(), writeSize); + } numRecords++; } @@ -301,8 +284,11 @@ void PrmDbImpl::PRM_SAVE_FILE_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) { this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR); return; } - writeSize = static_cast(sizeof(crc)); - stat = paramFile.write(reinterpret_cast(&crc), writeSize, Os::File::WaitType::WAIT); + writeSize = static_cast(HASH_DIGEST_LENGTH); + U32 crcFinal; + crc.finalize(crcFinal); + crcFinal = ~crcFinal; + stat = paramFile.write(reinterpret_cast(&crcFinal), writeSize, Os::File::WaitType::WAIT); if (stat != Os::File::OP_OK) { this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::CRC_REAL, 0, stat); this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR); diff --git a/Svc/PrmDb/PrmDbImpl.hpp b/Svc/PrmDb/PrmDbImpl.hpp index b6bbbd79551..7cebee69d8f 100644 --- a/Svc/PrmDb/PrmDbImpl.hpp +++ b/Svc/PrmDb/PrmDbImpl.hpp @@ -88,9 +88,6 @@ class PrmDbImpl final : public PrmDbComponentBase { PrmDbFileLoadState m_state; // Current file load state of the parameter database - // helper to compute CRC over a buffer - U32 computeCrc(U32 crc, const BYTE* buff, FwSizeType size); - // Pointers to the active and staging databases // These point to the actual storage arrays below // The active database is the ONLY one used for getting parameters diff --git a/Utils/CMakeLists.txt b/Utils/CMakeLists.txt index 2a98dca1fe7..a8f2a050fa1 100644 --- a/Utils/CMakeLists.txt +++ b/Utils/CMakeLists.txt @@ -1,3 +1,8 @@ +# Module subdirectories + +add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Hash/") +add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Types/") + #Source files set(SOURCE_FILES "${CMAKE_CURRENT_LIST_DIR}/RateLimiter.cpp" @@ -29,8 +34,3 @@ set (UT_TARGET_NAME "${FPRIME_CURRENT_MODULE}_ut_exe") if (TARGET "${UT_TARGET_NAME}") target_compile_options("${UT_TARGET_NAME}" PRIVATE -Wno-conversion) endif() - -# Module subdirectories - -add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Hash/") -add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Types/") diff --git a/Utils/Hash/CMakeLists.txt b/Utils/Hash/CMakeLists.txt index c04cec2859b..b4f357e5e8f 100644 --- a/Utils/Hash/CMakeLists.txt +++ b/Utils/Hash/CMakeLists.txt @@ -5,13 +5,33 @@ # MOD_DEPS: (optional) module dependencies # #### -set(SOURCE_FILES - "${CMAKE_CURRENT_LIST_DIR}/libcrc/CRC32.cpp" - "${CMAKE_CURRENT_LIST_DIR}/libcrc/lib_crc.c" - "${CMAKE_CURRENT_LIST_DIR}/HashBufferCommon.cpp" - "${CMAKE_CURRENT_LIST_DIR}/HashCommon.cpp" + +register_fprime_library( + SOURCES + HashBufferCommon.cpp + HashCommon.cpp + + Crc32/Crc32.cpp + Crc32/HashImpl.cpp + + # Only provided to satisfy CCSDS + libcrc/lib_crc.c + HEADERS + Hash.hpp + HashBuffer.hpp + HashConfig.hpp + + Crc32/Crc32.hpp + + # Only provided to satisfy CCSDS + libcrc/lib_crc.h + DEPENDS + Fw_Types ) -set(MOD_DEPS - "Fw/Types" + +register_fprime_ut( + SOURCES + Crc32/test/ut/Crc32Test.cpp + DEPENDS + Utils_Hash ) -register_fprime_module() \ No newline at end of file diff --git a/Utils/Hash/Crc32/Crc32.cpp b/Utils/Hash/Crc32/Crc32.cpp new file mode 100644 index 00000000000..da1254b6614 --- /dev/null +++ b/Utils/Hash/Crc32/Crc32.cpp @@ -0,0 +1,212 @@ +// Copyright 2025 California Institute of Technology +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 + +/* + This file contains a CRC32 implementation based on the implementation from + https://create.stephan-brumme.com/crc32/#sarwate. + + Here is the original software license: + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "Crc32.hpp" +#include "Fw/FPrimeBasicTypes.hpp" +#include "Fw/Types/Assert.hpp" + +namespace Utils { + +// Generated by TableGenerator.c. +static const U32 crc32_ieee802_3_lookup0[256] = { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, + 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, + 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, + 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, + 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, + 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, + 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, + 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, + 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, + 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, + 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, + 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, + 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, + 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, + 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, + 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, + 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, + 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, + 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, + 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, + 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, + 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, + 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, + 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, + 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, + 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D, +}; +static const U32 crc32_ieee802_3_lookup1[256] = { + 0x00000000, 0x191B3141, 0x32366282, 0x2B2D53C3, 0x646CC504, 0x7D77F445, 0x565AA786, 0x4F4196C7, 0xC8D98A08, + 0xD1C2BB49, 0xFAEFE88A, 0xE3F4D9CB, 0xACB54F0C, 0xB5AE7E4D, 0x9E832D8E, 0x87981CCF, 0x4AC21251, 0x53D92310, + 0x78F470D3, 0x61EF4192, 0x2EAED755, 0x37B5E614, 0x1C98B5D7, 0x05838496, 0x821B9859, 0x9B00A918, 0xB02DFADB, + 0xA936CB9A, 0xE6775D5D, 0xFF6C6C1C, 0xD4413FDF, 0xCD5A0E9E, 0x958424A2, 0x8C9F15E3, 0xA7B24620, 0xBEA97761, + 0xF1E8E1A6, 0xE8F3D0E7, 0xC3DE8324, 0xDAC5B265, 0x5D5DAEAA, 0x44469FEB, 0x6F6BCC28, 0x7670FD69, 0x39316BAE, + 0x202A5AEF, 0x0B07092C, 0x121C386D, 0xDF4636F3, 0xC65D07B2, 0xED705471, 0xF46B6530, 0xBB2AF3F7, 0xA231C2B6, + 0x891C9175, 0x9007A034, 0x179FBCFB, 0x0E848DBA, 0x25A9DE79, 0x3CB2EF38, 0x73F379FF, 0x6AE848BE, 0x41C51B7D, + 0x58DE2A3C, 0xF0794F05, 0xE9627E44, 0xC24F2D87, 0xDB541CC6, 0x94158A01, 0x8D0EBB40, 0xA623E883, 0xBF38D9C2, + 0x38A0C50D, 0x21BBF44C, 0x0A96A78F, 0x138D96CE, 0x5CCC0009, 0x45D73148, 0x6EFA628B, 0x77E153CA, 0xBABB5D54, + 0xA3A06C15, 0x888D3FD6, 0x91960E97, 0xDED79850, 0xC7CCA911, 0xECE1FAD2, 0xF5FACB93, 0x7262D75C, 0x6B79E61D, + 0x4054B5DE, 0x594F849F, 0x160E1258, 0x0F152319, 0x243870DA, 0x3D23419B, 0x65FD6BA7, 0x7CE65AE6, 0x57CB0925, + 0x4ED03864, 0x0191AEA3, 0x188A9FE2, 0x33A7CC21, 0x2ABCFD60, 0xAD24E1AF, 0xB43FD0EE, 0x9F12832D, 0x8609B26C, + 0xC94824AB, 0xD05315EA, 0xFB7E4629, 0xE2657768, 0x2F3F79F6, 0x362448B7, 0x1D091B74, 0x04122A35, 0x4B53BCF2, + 0x52488DB3, 0x7965DE70, 0x607EEF31, 0xE7E6F3FE, 0xFEFDC2BF, 0xD5D0917C, 0xCCCBA03D, 0x838A36FA, 0x9A9107BB, + 0xB1BC5478, 0xA8A76539, 0x3B83984B, 0x2298A90A, 0x09B5FAC9, 0x10AECB88, 0x5FEF5D4F, 0x46F46C0E, 0x6DD93FCD, + 0x74C20E8C, 0xF35A1243, 0xEA412302, 0xC16C70C1, 0xD8774180, 0x9736D747, 0x8E2DE606, 0xA500B5C5, 0xBC1B8484, + 0x71418A1A, 0x685ABB5B, 0x4377E898, 0x5A6CD9D9, 0x152D4F1E, 0x0C367E5F, 0x271B2D9C, 0x3E001CDD, 0xB9980012, + 0xA0833153, 0x8BAE6290, 0x92B553D1, 0xDDF4C516, 0xC4EFF457, 0xEFC2A794, 0xF6D996D5, 0xAE07BCE9, 0xB71C8DA8, + 0x9C31DE6B, 0x852AEF2A, 0xCA6B79ED, 0xD37048AC, 0xF85D1B6F, 0xE1462A2E, 0x66DE36E1, 0x7FC507A0, 0x54E85463, + 0x4DF36522, 0x02B2F3E5, 0x1BA9C2A4, 0x30849167, 0x299FA026, 0xE4C5AEB8, 0xFDDE9FF9, 0xD6F3CC3A, 0xCFE8FD7B, + 0x80A96BBC, 0x99B25AFD, 0xB29F093E, 0xAB84387F, 0x2C1C24B0, 0x350715F1, 0x1E2A4632, 0x07317773, 0x4870E1B4, + 0x516BD0F5, 0x7A468336, 0x635DB277, 0xCBFAD74E, 0xD2E1E60F, 0xF9CCB5CC, 0xE0D7848D, 0xAF96124A, 0xB68D230B, + 0x9DA070C8, 0x84BB4189, 0x03235D46, 0x1A386C07, 0x31153FC4, 0x280E0E85, 0x674F9842, 0x7E54A903, 0x5579FAC0, + 0x4C62CB81, 0x8138C51F, 0x9823F45E, 0xB30EA79D, 0xAA1596DC, 0xE554001B, 0xFC4F315A, 0xD7626299, 0xCE7953D8, + 0x49E14F17, 0x50FA7E56, 0x7BD72D95, 0x62CC1CD4, 0x2D8D8A13, 0x3496BB52, 0x1FBBE891, 0x06A0D9D0, 0x5E7EF3EC, + 0x4765C2AD, 0x6C48916E, 0x7553A02F, 0x3A1236E8, 0x230907A9, 0x0824546A, 0x113F652B, 0x96A779E4, 0x8FBC48A5, + 0xA4911B66, 0xBD8A2A27, 0xF2CBBCE0, 0xEBD08DA1, 0xC0FDDE62, 0xD9E6EF23, 0x14BCE1BD, 0x0DA7D0FC, 0x268A833F, + 0x3F91B27E, 0x70D024B9, 0x69CB15F8, 0x42E6463B, 0x5BFD777A, 0xDC656BB5, 0xC57E5AF4, 0xEE530937, 0xF7483876, + 0xB809AEB1, 0xA1129FF0, 0x8A3FCC33, 0x9324FD72, +}; +static const U32 crc32_ieee802_3_lookup2[256] = { + 0x00000000, 0x01C26A37, 0x0384D46E, 0x0246BE59, 0x0709A8DC, 0x06CBC2EB, 0x048D7CB2, 0x054F1685, 0x0E1351B8, + 0x0FD13B8F, 0x0D9785D6, 0x0C55EFE1, 0x091AF964, 0x08D89353, 0x0A9E2D0A, 0x0B5C473D, 0x1C26A370, 0x1DE4C947, + 0x1FA2771E, 0x1E601D29, 0x1B2F0BAC, 0x1AED619B, 0x18ABDFC2, 0x1969B5F5, 0x1235F2C8, 0x13F798FF, 0x11B126A6, + 0x10734C91, 0x153C5A14, 0x14FE3023, 0x16B88E7A, 0x177AE44D, 0x384D46E0, 0x398F2CD7, 0x3BC9928E, 0x3A0BF8B9, + 0x3F44EE3C, 0x3E86840B, 0x3CC03A52, 0x3D025065, 0x365E1758, 0x379C7D6F, 0x35DAC336, 0x3418A901, 0x3157BF84, + 0x3095D5B3, 0x32D36BEA, 0x331101DD, 0x246BE590, 0x25A98FA7, 0x27EF31FE, 0x262D5BC9, 0x23624D4C, 0x22A0277B, + 0x20E69922, 0x2124F315, 0x2A78B428, 0x2BBADE1F, 0x29FC6046, 0x283E0A71, 0x2D711CF4, 0x2CB376C3, 0x2EF5C89A, + 0x2F37A2AD, 0x709A8DC0, 0x7158E7F7, 0x731E59AE, 0x72DC3399, 0x7793251C, 0x76514F2B, 0x7417F172, 0x75D59B45, + 0x7E89DC78, 0x7F4BB64F, 0x7D0D0816, 0x7CCF6221, 0x798074A4, 0x78421E93, 0x7A04A0CA, 0x7BC6CAFD, 0x6CBC2EB0, + 0x6D7E4487, 0x6F38FADE, 0x6EFA90E9, 0x6BB5866C, 0x6A77EC5B, 0x68315202, 0x69F33835, 0x62AF7F08, 0x636D153F, + 0x612BAB66, 0x60E9C151, 0x65A6D7D4, 0x6464BDE3, 0x662203BA, 0x67E0698D, 0x48D7CB20, 0x4915A117, 0x4B531F4E, + 0x4A917579, 0x4FDE63FC, 0x4E1C09CB, 0x4C5AB792, 0x4D98DDA5, 0x46C49A98, 0x4706F0AF, 0x45404EF6, 0x448224C1, + 0x41CD3244, 0x400F5873, 0x4249E62A, 0x438B8C1D, 0x54F16850, 0x55330267, 0x5775BC3E, 0x56B7D609, 0x53F8C08C, + 0x523AAABB, 0x507C14E2, 0x51BE7ED5, 0x5AE239E8, 0x5B2053DF, 0x5966ED86, 0x58A487B1, 0x5DEB9134, 0x5C29FB03, + 0x5E6F455A, 0x5FAD2F6D, 0xE1351B80, 0xE0F771B7, 0xE2B1CFEE, 0xE373A5D9, 0xE63CB35C, 0xE7FED96B, 0xE5B86732, + 0xE47A0D05, 0xEF264A38, 0xEEE4200F, 0xECA29E56, 0xED60F461, 0xE82FE2E4, 0xE9ED88D3, 0xEBAB368A, 0xEA695CBD, + 0xFD13B8F0, 0xFCD1D2C7, 0xFE976C9E, 0xFF5506A9, 0xFA1A102C, 0xFBD87A1B, 0xF99EC442, 0xF85CAE75, 0xF300E948, + 0xF2C2837F, 0xF0843D26, 0xF1465711, 0xF4094194, 0xF5CB2BA3, 0xF78D95FA, 0xF64FFFCD, 0xD9785D60, 0xD8BA3757, + 0xDAFC890E, 0xDB3EE339, 0xDE71F5BC, 0xDFB39F8B, 0xDDF521D2, 0xDC374BE5, 0xD76B0CD8, 0xD6A966EF, 0xD4EFD8B6, + 0xD52DB281, 0xD062A404, 0xD1A0CE33, 0xD3E6706A, 0xD2241A5D, 0xC55EFE10, 0xC49C9427, 0xC6DA2A7E, 0xC7184049, + 0xC25756CC, 0xC3953CFB, 0xC1D382A2, 0xC011E895, 0xCB4DAFA8, 0xCA8FC59F, 0xC8C97BC6, 0xC90B11F1, 0xCC440774, + 0xCD866D43, 0xCFC0D31A, 0xCE02B92D, 0x91AF9640, 0x906DFC77, 0x922B422E, 0x93E92819, 0x96A63E9C, 0x976454AB, + 0x9522EAF2, 0x94E080C5, 0x9FBCC7F8, 0x9E7EADCF, 0x9C381396, 0x9DFA79A1, 0x98B56F24, 0x99770513, 0x9B31BB4A, + 0x9AF3D17D, 0x8D893530, 0x8C4B5F07, 0x8E0DE15E, 0x8FCF8B69, 0x8A809DEC, 0x8B42F7DB, 0x89044982, 0x88C623B5, + 0x839A6488, 0x82580EBF, 0x801EB0E6, 0x81DCDAD1, 0x8493CC54, 0x8551A663, 0x8717183A, 0x86D5720D, 0xA9E2D0A0, + 0xA820BA97, 0xAA6604CE, 0xABA46EF9, 0xAEEB787C, 0xAF29124B, 0xAD6FAC12, 0xACADC625, 0xA7F18118, 0xA633EB2F, + 0xA4755576, 0xA5B73F41, 0xA0F829C4, 0xA13A43F3, 0xA37CFDAA, 0xA2BE979D, 0xB5C473D0, 0xB40619E7, 0xB640A7BE, + 0xB782CD89, 0xB2CDDB0C, 0xB30FB13B, 0xB1490F62, 0xB08B6555, 0xBBD72268, 0xBA15485F, 0xB853F606, 0xB9919C31, + 0xBCDE8AB4, 0xBD1CE083, 0xBF5A5EDA, 0xBE9834ED, +}; +static const U32 crc32_ieee802_3_lookup3[256] = { + 0x00000000, 0xB8BC6765, 0xAA09C88B, 0x12B5AFEE, 0x8F629757, 0x37DEF032, 0x256B5FDC, 0x9DD738B9, 0xC5B428EF, + 0x7D084F8A, 0x6FBDE064, 0xD7018701, 0x4AD6BFB8, 0xF26AD8DD, 0xE0DF7733, 0x58631056, 0x5019579F, 0xE8A530FA, + 0xFA109F14, 0x42ACF871, 0xDF7BC0C8, 0x67C7A7AD, 0x75720843, 0xCDCE6F26, 0x95AD7F70, 0x2D111815, 0x3FA4B7FB, + 0x8718D09E, 0x1ACFE827, 0xA2738F42, 0xB0C620AC, 0x087A47C9, 0xA032AF3E, 0x188EC85B, 0x0A3B67B5, 0xB28700D0, + 0x2F503869, 0x97EC5F0C, 0x8559F0E2, 0x3DE59787, 0x658687D1, 0xDD3AE0B4, 0xCF8F4F5A, 0x7733283F, 0xEAE41086, + 0x525877E3, 0x40EDD80D, 0xF851BF68, 0xF02BF8A1, 0x48979FC4, 0x5A22302A, 0xE29E574F, 0x7F496FF6, 0xC7F50893, + 0xD540A77D, 0x6DFCC018, 0x359FD04E, 0x8D23B72B, 0x9F9618C5, 0x272A7FA0, 0xBAFD4719, 0x0241207C, 0x10F48F92, + 0xA848E8F7, 0x9B14583D, 0x23A83F58, 0x311D90B6, 0x89A1F7D3, 0x1476CF6A, 0xACCAA80F, 0xBE7F07E1, 0x06C36084, + 0x5EA070D2, 0xE61C17B7, 0xF4A9B859, 0x4C15DF3C, 0xD1C2E785, 0x697E80E0, 0x7BCB2F0E, 0xC377486B, 0xCB0D0FA2, + 0x73B168C7, 0x6104C729, 0xD9B8A04C, 0x446F98F5, 0xFCD3FF90, 0xEE66507E, 0x56DA371B, 0x0EB9274D, 0xB6054028, + 0xA4B0EFC6, 0x1C0C88A3, 0x81DBB01A, 0x3967D77F, 0x2BD27891, 0x936E1FF4, 0x3B26F703, 0x839A9066, 0x912F3F88, + 0x299358ED, 0xB4446054, 0x0CF80731, 0x1E4DA8DF, 0xA6F1CFBA, 0xFE92DFEC, 0x462EB889, 0x549B1767, 0xEC277002, + 0x71F048BB, 0xC94C2FDE, 0xDBF98030, 0x6345E755, 0x6B3FA09C, 0xD383C7F9, 0xC1366817, 0x798A0F72, 0xE45D37CB, + 0x5CE150AE, 0x4E54FF40, 0xF6E89825, 0xAE8B8873, 0x1637EF16, 0x048240F8, 0xBC3E279D, 0x21E91F24, 0x99557841, + 0x8BE0D7AF, 0x335CB0CA, 0xED59B63B, 0x55E5D15E, 0x47507EB0, 0xFFEC19D5, 0x623B216C, 0xDA874609, 0xC832E9E7, + 0x708E8E82, 0x28ED9ED4, 0x9051F9B1, 0x82E4565F, 0x3A58313A, 0xA78F0983, 0x1F336EE6, 0x0D86C108, 0xB53AA66D, + 0xBD40E1A4, 0x05FC86C1, 0x1749292F, 0xAFF54E4A, 0x322276F3, 0x8A9E1196, 0x982BBE78, 0x2097D91D, 0x78F4C94B, + 0xC048AE2E, 0xD2FD01C0, 0x6A4166A5, 0xF7965E1C, 0x4F2A3979, 0x5D9F9697, 0xE523F1F2, 0x4D6B1905, 0xF5D77E60, + 0xE762D18E, 0x5FDEB6EB, 0xC2098E52, 0x7AB5E937, 0x680046D9, 0xD0BC21BC, 0x88DF31EA, 0x3063568F, 0x22D6F961, + 0x9A6A9E04, 0x07BDA6BD, 0xBF01C1D8, 0xADB46E36, 0x15080953, 0x1D724E9A, 0xA5CE29FF, 0xB77B8611, 0x0FC7E174, + 0x9210D9CD, 0x2AACBEA8, 0x38191146, 0x80A57623, 0xD8C66675, 0x607A0110, 0x72CFAEFE, 0xCA73C99B, 0x57A4F122, + 0xEF189647, 0xFDAD39A9, 0x45115ECC, 0x764DEE06, 0xCEF18963, 0xDC44268D, 0x64F841E8, 0xF92F7951, 0x41931E34, + 0x5326B1DA, 0xEB9AD6BF, 0xB3F9C6E9, 0x0B45A18C, 0x19F00E62, 0xA14C6907, 0x3C9B51BE, 0x842736DB, 0x96929935, + 0x2E2EFE50, 0x2654B999, 0x9EE8DEFC, 0x8C5D7112, 0x34E11677, 0xA9362ECE, 0x118A49AB, 0x033FE645, 0xBB838120, + 0xE3E09176, 0x5B5CF613, 0x49E959FD, 0xF1553E98, 0x6C820621, 0xD43E6144, 0xC68BCEAA, 0x7E37A9CF, 0xD67F4138, + 0x6EC3265D, 0x7C7689B3, 0xC4CAEED6, 0x591DD66F, 0xE1A1B10A, 0xF3141EE4, 0x4BA87981, 0x13CB69D7, 0xAB770EB2, + 0xB9C2A15C, 0x017EC639, 0x9CA9FE80, 0x241599E5, 0x36A0360B, 0x8E1C516E, 0x866616A7, 0x3EDA71C2, 0x2C6FDE2C, + 0x94D3B949, 0x090481F0, 0xB1B8E695, 0xA30D497B, 0x1BB12E1E, 0x43D23E48, 0xFB6E592D, 0xE9DBF6C3, 0x516791A6, + 0xCCB0A91F, 0x740CCE7A, 0x66B96194, 0xDE0506F1, +}; + +U32 crc32_ieee802_3_update(const U8* data, FwSizeType length, U32 crc) { + FW_ASSERT(data != nullptr, FwAssertArgType(length)); + + FwSizeType i = 0; + if (length >= 4) { + constexpr U32 step_size = 4; + + // First, make sure that we are 4-byte aligned, using single-byte CRC calculations. + // The fast algorithm below would work on any platform, but aligned reads are typically + // more efficient. + PlatformPointerCastType data_address = reinterpret_cast(data); + U32 correction = (step_size - (data_address & (step_size - 1))) & (step_size - 1); + for (; i < correction; i++) { + crc = (crc >> 8) ^ crc32_ieee802_3_lookup0[(crc & 0xFF) ^ data[i]]; + } + + // Double check alignment. (This should be optimized away, since the compiler can prove + // this is always true.) + FW_ASSERT(((data_address + i) & (step_size - 1)) == 0, FwAssertArgType(data_address), FwAssertArgType(i), + FwAssertArgType(step_size)); + + // Once we are aligned, we can apply a faster algorithm, where we read 4 bytes of + // data at once. (This relies on the compiler applying a straightforward optimization + // to consolidate 4x U8 loads into 1x U32 load. We could do that manually, but then + // we'd need the complexity of considering endianness.) + FwSizeType stop_at = length - 3; + for (; i < stop_at; i += 4) { + crc ^= U32(data[i + 0] | (data[i + 1] << 8) | (data[i + 2] << 16) | (data[i + 3] << 24)); + crc = crc32_ieee802_3_lookup3[crc & 0xFF] ^ crc32_ieee802_3_lookup2[(crc >> 8) & 0xFF] ^ + crc32_ieee802_3_lookup1[(crc >> 16) & 0xFF] ^ crc32_ieee802_3_lookup0[crc >> 24]; + } + } + + // Handle the last few bytes one-by-one. + for (; i < length; i++) { + crc = (crc >> 8) ^ crc32_ieee802_3_lookup0[(crc & 0xFF) ^ data[i]]; + } + return crc; +} + +} // namespace Utils diff --git a/Utils/Hash/Crc32/Crc32.hpp b/Utils/Hash/Crc32/Crc32.hpp new file mode 100644 index 00000000000..37177b688f5 --- /dev/null +++ b/Utils/Hash/Crc32/Crc32.hpp @@ -0,0 +1,38 @@ +#ifndef Components_Cascade_Crc32_HPP +#define Components_Cascade_Crc32_HPP + +#include "Fw/FPrimeBasicTypes.hpp" + +namespace Utils { + +// This is an implementation of the IEEE 802.3 CRC32 polynomial, which is +// 0x82608EDB when expressed as a reverse reciprocal form, or 0xEDB88320 +// when expressed in a reverse form. +// +// Note that this specific function does not perform the one's complement +// that is typically performed when calculating a CRC32 hash. Use the Hash +// class implementation instead. +U32 crc32_ieee802_3_update(const U8* data, FwSizeType length, U32 crc); + +//! Define the hash handle type for this +//! implementation. This is required. +#ifndef HASH_HANDLE_TYPE +#define HASH_HANDLE_TYPE U32 // NO_CODESONAR LANG.PREPROC.MACROSTART/END +#endif + +//! Define the size of a hash digest in bytes for this +//! implementation. This is required. +#ifndef HASH_DIGEST_LENGTH +#define HASH_DIGEST_LENGTH (4) +#endif + +//! Define the string to be used as a filename +//! extension (ie. file.txt.SHA256) for this +//! implementation. This is required. +#ifndef HASH_EXTENSION_STRING +#define HASH_EXTENSION_STRING (".CRC32") +#endif + +} // namespace Utils + +#endif diff --git a/Utils/Hash/libcrc/CRC32.cpp b/Utils/Hash/Crc32/HashImpl.cpp similarity index 58% rename from Utils/Hash/libcrc/CRC32.cpp rename to Utils/Hash/Crc32/HashImpl.cpp index a16370a708e..79370137b01 100644 --- a/Utils/Hash/libcrc/CRC32.cpp +++ b/Utils/Hash/Crc32/HashImpl.cpp @@ -11,8 +11,7 @@ // ====================================================================== #include - -static_assert(sizeof(unsigned long) >= sizeof(U32), "CRC32 cannot fit in CRC32 library chosen types"); +#include "Crc32.hpp" namespace Utils { @@ -23,19 +22,9 @@ Hash ::Hash() { Hash ::~Hash() = default; void Hash ::hash(const void* const data, const FwSizeType len, HashBuffer& buffer) { - HASH_HANDLE_TYPE local_hash_handle; - local_hash_handle = 0xffffffffL; - FW_ASSERT(data); - char c; - for (FwSizeType index = 0; index < len; index++) { - c = static_cast(data)[index]; - local_hash_handle = static_cast(update_crc_32(local_hash_handle, c)); - } - HashBuffer bufferOut; - // For CRC32 we need to return the one's complement of the result: - Fw::SerializeStatus status = bufferOut.serializeFrom(~(local_hash_handle)); - FW_ASSERT(Fw::FW_SERIALIZE_OK == status); - buffer = bufferOut; + Hash crc32; + crc32.update(data, len); + crc32.finalize(buffer); } void Hash ::init() { @@ -43,15 +32,12 @@ void Hash ::init() { } void Hash ::update(const void* const data, FwSizeType len) { + static_assert(sizeof(Utils::Hash::hash_handle) == sizeof(U32), "hash handle size must match CRC32 size"); FW_ASSERT(data); - char c = 0; - for (FwSizeType index = 0; index < len; index++) { - c = static_cast(data)[index]; - this->hash_handle = static_cast(update_crc_32(this->hash_handle, c)); - } + this->hash_handle = crc32_ieee802_3_update(static_cast(data), len, this->hash_handle); } -void Hash ::finalize(HashBuffer& buffer) { +void Hash ::finalize(HashBuffer& buffer) const { HashBuffer bufferOut; // For CRC32 we need to return the one's complement of the result: Fw::SerializeStatus status = bufferOut.serializeFrom(~(this->hash_handle)); @@ -59,8 +45,7 @@ void Hash ::finalize(HashBuffer& buffer) { buffer = bufferOut; } -void Hash ::finalize(U32& hashvalue) { - FW_ASSERT(sizeof(this->hash_handle) == sizeof(U32)); +void Hash ::finalize(U32& hashvalue) const { // For CRC32 we need to return the one's complement of the result: hashvalue = ~(this->hash_handle); } @@ -72,4 +57,9 @@ void Hash ::setHashValue(HashBuffer& value) { // here for correct hash updates this->hash_handle = ~this->hash_handle; } + +void Hash ::setHashValue(U32 value) { + this->hash_handle = ~value; +} + } // namespace Utils diff --git a/Utils/Hash/Crc32/TableGenerator.c b/Utils/Hash/Crc32/TableGenerator.c new file mode 100644 index 00000000000..63013517eec --- /dev/null +++ b/Utils/Hash/Crc32/TableGenerator.c @@ -0,0 +1,72 @@ +// Copyright 2025 California Institute of Technology +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 + +/* + This file contains a CRC32 table generator based on the implementation from + https://create.stephan-brumme.com/crc32/#sarwate. + + Here is the original software license: + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include +#include + +int main(int argc, char* argv[]) { + uint32_t polynomial = 0xEDB88320; + + uint32_t Crc32Lookup[4][0x100]; + + for (uint32_t i = 0; i < 0x100; i++) { + uint32_t crc = i; + for (uint32_t j = 0; j < 8; j++) { + crc = (crc >> 1) ^ (-(uint32_t)(crc & 1) & polynomial); + } + Crc32Lookup[0][i] = crc; + } + for (uint32_t i = 0; i < 0x100; i++) { + Crc32Lookup[1][i] = (Crc32Lookup[0][i] >> 8) ^ Crc32Lookup[0][Crc32Lookup[0][i] & 0xFF]; + Crc32Lookup[2][i] = (Crc32Lookup[1][i] >> 8) ^ Crc32Lookup[0][Crc32Lookup[1][i] & 0xFF]; + Crc32Lookup[3][i] = (Crc32Lookup[2][i] >> 8) ^ Crc32Lookup[0][Crc32Lookup[2][i] & 0xFF]; + } + + for (uint32_t k = 0; k < 4; k++) { + printf("static const U32 crc32_ieee802_3_lookup%d[256] = {", k); + for (uint32_t i = 0; i < 0x100; i++) { + if (i % 4 == 0) { + printf("\n "); + } + printf(" 0x%08X,", Crc32Lookup[k][i]); + } + printf("\n};\n"); + } + return 0; +} diff --git a/Utils/Hash/Crc32/test/ut/Crc32Test.cpp b/Utils/Hash/Crc32/test/ut/Crc32Test.cpp new file mode 100644 index 00000000000..f10dd1ef0e7 --- /dev/null +++ b/Utils/Hash/Crc32/test/ut/Crc32Test.cpp @@ -0,0 +1,222 @@ +// Copyright 2026 California Institute of Technology +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 + +#include +#include +#include "gtest/gtest.h" + +TEST(Crc32Test, testEmptyInput) { + Utils::HashBuffer hb; + Utils::Hash::hash("", 0, hb); + U32 output = hb.asBigEndianU32(); + EXPECT_EQ(output, 0); +} + +TEST(Crc32Test, testHelloWorld) { + Utils::HashBuffer hb; + U8 input[] = "Hello, World!"; + Utils::Hash::hash(input, sizeof(input) - 1 /* null terminator */, hb); + U32 output = hb.asBigEndianU32(); + EXPECT_EQ(output, 0xEC4AC3D0); +} + +TEST(Crc32Test, testBinary) { + U8 input[256]; + for (U32 i = 0; i < sizeof(input); i++) { + input[i] = U8(i); + } + + Utils::HashBuffer hb; + Utils::Hash::hash(input, sizeof(input), hb); + U32 output = hb.asBigEndianU32(); + EXPECT_EQ(output, 0x29058C73); +} + +// We need sample data to operate on, how about this? +static const U8 sample_input[] = + "Public Law 85-568\n" + "\n" + "AN ACT\n" + "\n" + "To provide for research into problems of flight within and outside the earth's\n" + "atmosphere, and for other purposes.\n" + "\n" + "Be it enacted by the Senate and House of Representatives of the\n" + "United States of America in Congress assembled,\n" + "\n" + "TITLE I - SHORT TITLE, DECLARATION OF POLICY, AND DEFINITIONS\n" + "\n" + "SHORT TITLE\n" + "\n" + "SEC. 101. This Act may be cited as the \"National Aeronautics and" + "Space Act of 1958\"." + "\n" + "DECLARATION OF POLICY AND PURPOSE\n" + "\n" + "SEC. 102. (a) The Congress hereby declares that it is the policy of\n" + "the United States that activities in space should be devoted to peaceful\n" + "purposes for the benefit of all mankind.\n" + "\n" + "(b) The Congress declares that the general welfare and security of\n" + "the United States require that adequate provision be made for aeronautical\n" + "and space activities. The Congress further declares that\n" + "such activities shall be the responsibility of, and shall be directed by,\n" + "a civilian agency exercising control over aeronautical and space activities\n" + "sponsored by the United States, except that activities peculiar\n" + "to or primarily associated with the development of weapons systems,\n" + "military operations, or the defense of the United States (including\n" + "the research and development necessary to make effective provision for\n" + "the defense of the United States) shall be the responsibility of, and\n" + "shall be directed by, the Department of Defense; and that determination\n" + "as to which such agency has responsibility for and direction of\n" + "any such activity shall be made by the President in conformity with\n" + "section 201 (e).\n" + "\n" + "(c) The aeronautical and space activities of the United States shall\n" + "be conducted so as to contribute materially to one or more of the\n" + "following objectives:\n" + "(1) The expansion of human knowledge of phenomena in the\n" + "atmosphere and space;\n" + "(2) The improvement of the usefulness, performance, speed,\n" + "safety, and efficiency of aeronautical and space vehicles;\n" + "(3) The development and operation of vehicles capable of\n" + "carrying instruments, equipment, supplies, and living organisms\n" + "through space;\n" + "(4) The establishment of long-range studies of the potential\n" + "benefits to be gained from, the opportunities for, and the problems\n" + "involved in the utilization of aeronautical and space activities for\n" + "peaceful and scientific purposes;\n" + "(5) The preservation of the role of the United States as a\n" + "leader in aeronautical and space science and technology and in\n" + "the application thereof to the conduct of peaceful activities within\n" + "and outside the atmosphere;\n" + "(6) The making available to agencies directly concerned with\n" + "national defense of discoveries that have military value or significance,\n" + "and the furnishing by such agencies, to the civilian agency\n" + "established to direct and control nonmilitary aeronautical and\n" + "space activities, of information as to discoveries which have value\n" + "or significance to that agency;\n" + "(7) Cooperation by the United States with other nations and\n" + "groups of nations in work done pursuant to this Act and in the\n" + "peaceful application of the results thereof; and\n" + "(8) The most effective utilization of the scientific and engineer-\n" + "ing resources of the United States, with close cooperation among\n" + "all interested agencies of the United States in order to avoid\n" + "unnecessary duplication of effort, facilities, and equipment.\n" + "\n" + "(d) It is the purpose of this Act to carry out and effectuate the\n" + "policies declared in subsections (a), (b), and (c),\n" + "\n" + "DEFINITIONS\n" + "\n" + "SEC. 103. As used in this Act--\n" + "\n" + "(1) the term \"aeronautical and space activities\" means (A)\n" + "research into, and the solution of, problems of flight within and\n" + "outside the earth's atmosphere, (B) the development, construction,\n" + "testing, and operation for research purposes of aeronautical\n" + "and space vehicles, and (C) such other activities as may be\n" + "required for the exploration of space; and\n" + "\n" + "(2) the term \"aeronautical and space vehicles\" means air-\n" + "craft, missiles, satellites, and other space vehicles, manned and\n" + "unmanned, together with related equipment, devices, components,\n" + "and parts.\n"; + +constexpr U32 sample_input_hash = 0x5E6BB4BD; +constexpr U32 sample_input_length = sizeof(sample_input) - 1 /* null terminator */; + +TEST(Crc32Test, testLongText) { + Utils::HashBuffer hb; + Utils::Hash::hash(sample_input, sample_input_length, hb); + U32 output = hb.asBigEndianU32(); + EXPECT_EQ(output, sample_input_hash); +} + +const U32 varyingSizeVectors[] = {0xB969BE79, 0xB02D9F38, 0x620C7FA4, 0x8091341E, 0x55FE1940, 0x2978FC8E, + 0x16C9BBDA, 0x35075533, 0x2D058B95, 0x6EBD4DD1, 0xD6CCCFCA, 0xFF4A3832}; + +TEST(Crc32Test, testVaryingSizes) { + Utils::Hash hash; + for (U32 i = 0; i < FW_NUM_ARRAY_ELEMENTS(varyingSizeVectors); i++) { + U32 offset = (1 << i) - 1; + U32 length = std::min(U32(1 << i), U32(sample_input_length - offset)); + hash.init(); + hash.update(sample_input + offset, length); + U32 output; + hash.finalize(output); + EXPECT_EQ(output, varyingSizeVectors[i]); + } +} + +TEST(Crc32Test, testSimpleMultiUpdate) { + Utils::Hash hash; + hash.update(sample_input, sizeof(sample_input) / 2); + hash.update(sample_input + sizeof(sample_input) / 2, sample_input_length - sizeof(sample_input) / 2); + U32 output; + hash.finalize(output); + EXPECT_EQ(output, sample_input_hash); +} + +TEST(Crc32Test, testMultiUpdatePartitions) { + Utils::Hash hash; + for (U32 i = 0; i <= sample_input_length; i++) { + hash.init(); + hash.update(sample_input, i); + hash.update(sample_input + i, sample_input_length - i); + U32 output; + hash.finalize(output); + EXPECT_EQ(output, sample_input_hash); + } +} + +TEST(Crc32Test, testVeryLargeInput) { + // Pick a size (20 megabytes) that is large enough to use more than 24 bits + constexpr U32 largeSize = 20 * 1000 * 1000; + U8* largeInput = static_cast(malloc(largeSize)); + FW_ASSERT(largeInput != nullptr); + + // Fill input with arbitrary data + U32 value = largeSize; + for (U32 i = 0; i < largeSize; i++) { + value -= (i * i) ^ i; + value ^= sample_input[i % sample_input_length]; + largeInput[i] = value & 0xFF; + } + + // Checksum the whole thing all at once + Utils::HashBuffer allAtOnce; + Utils::Hash::hash(largeInput, largeSize, allAtOnce); + + // Then checksum it 13 bytes at a time. + Utils::Hash hash; + U32 limit = largeSize - largeSize % 13; + for (U32 i = 0; i < limit; i += 13) { + hash.update(largeInput + i, 13); + } + hash.update(largeInput + limit, largeSize - limit); + U32 output; + hash.finalize(output); + + EXPECT_EQ(output, allAtOnce.asBigEndianU32()); + + free(largeInput); +} + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/Utils/Hash/Hash.hpp b/Utils/Hash/Hash.hpp index 724149de52f..50e7b23bd63 100644 --- a/Utils/Hash/Hash.hpp +++ b/Utils/Hash/Hash.hpp @@ -62,6 +62,11 @@ class Hash { void setHashValue(HashBuffer& value //! Hash value ); + //! Set hash value to specified value + //! + void setHashValue(U32 value //! Hash value + ); + //! Update an incremental computation with new data //! \param data: pointer to start of data to add to hash calculation //! \param len: length of data to add to hash calculation @@ -70,11 +75,11 @@ class Hash { //! Finalize an incremental computation and return the result //! void finalize(HashBuffer& buffer //! The result - ); + ) const; //! Finalize an incremental computation and return the result //! - void finalize(U32& hashvalue); + void finalize(U32& hashvalue) const; //! Get the file extension for the supported hash type //! E.g., could return "SHA256" diff --git a/Utils/Hash/HashConfig.hpp b/Utils/Hash/HashConfig.hpp index 6a35526f82d..24fa94d1e09 100644 --- a/Utils/Hash/HashConfig.hpp +++ b/Utils/Hash/HashConfig.hpp @@ -7,6 +7,6 @@ //! //! #include //! -#include +#include #endif diff --git a/Utils/Hash/libcrc/CRC32.hpp b/Utils/Hash/libcrc/CRC32.hpp deleted file mode 100644 index e8405da15dd..00000000000 --- a/Utils/Hash/libcrc/CRC32.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef UTILS_CRC32_CONFIG_HPP -#define UTILS_CRC32_CONFIG_HPP - -// Include the lic crc c library: -extern "C" { -#include -} - -//! Define the hash handle type for this -//! implementation. This is required. -#ifndef HASH_HANDLE_TYPE -#define HASH_HANDLE_TYPE U32 // NO_CODESONAR LANG.PREPROC.MACROSTART/END -#endif - -//! Define the size of a hash digest in bytes for this -//! implementation. This is required. -#ifndef HASH_DIGEST_LENGTH -#define HASH_DIGEST_LENGTH (4) -#endif - -//! Define the string to be used as a filename -//! extension (ie. file.txt.SHA256) for this -//! implementation. This is required. -#ifndef HASH_EXTENSION_STRING -#define HASH_EXTENSION_STRING (".CRC32") -#endif - -#endif diff --git a/Utils/Hash/libcrc/lib_crc.c b/Utils/Hash/libcrc/lib_crc.c index b8345ba3bc0..26767508f9e 100644 --- a/Utils/Hash/libcrc/lib_crc.c +++ b/Utils/Hash/libcrc/lib_crc.c @@ -89,13 +89,19 @@ \*******************************************************************/ static int crc_tab16_init = CRC_FALSE; +// F PRIME CHANGE (see header) +#if 0 static int crc_tab32_init = CRC_FALSE; +#endif static int crc_tabccitt_init = CRC_FALSE; static int crc_tabdnp_init = CRC_FALSE; static int crc_tabkermit_init = CRC_FALSE; static unsigned short crc_tab16[256]; +// F PRIME CHANGE (see header) +#if 0 static unsigned long crc_tab32[256]; +#endif static unsigned short crc_tabccitt[256]; static unsigned short crc_tabdnp[256]; static unsigned short crc_tabkermit[256]; @@ -112,7 +118,10 @@ static unsigned short crc_tabkermit[256]; \*******************************************************************/ static void init_crc16_tab( void ); +// F PRIME CHANGE (see header) +#if 0 static void init_crc32_tab( void ); +#endif static void init_crcccitt_tab( void ); static void init_crcdnp_tab( void ); static void init_crckermit_tab( void ); @@ -269,6 +278,8 @@ unsigned short update_crc_dnp( unsigned short crc, char c ) { * * \*******************************************************************/ +// F PRIME CHANGE (see header) +#if 0 unsigned long update_crc_32( unsigned long crc, char c ) { unsigned long tmp, long_c; @@ -283,6 +294,7 @@ unsigned long update_crc_32( unsigned long crc, char c ) { return crc; } /* update_crc_32 */ +#endif @@ -403,6 +415,8 @@ static void init_crcdnp_tab( void ) { * * \*******************************************************************/ +// F PRIME CHANGE (see header) +#if 0 static void init_crc32_tab( void ) { int i, j; @@ -424,6 +438,7 @@ static void init_crc32_tab( void ) { crc_tab32_init = CRC_TRUE; } /* init_crc32_tab */ +#endif diff --git a/Utils/Hash/libcrc/lib_crc.h b/Utils/Hash/libcrc/lib_crc.h index c12e2b37a61..41fdfb4683f 100644 --- a/Utils/Hash/libcrc/lib_crc.h +++ b/Utils/Hash/libcrc/lib_crc.h @@ -65,7 +65,12 @@ extern "C" { unsigned short update_crc_16( unsigned short crc, char c ); +// F PRIME CHANGE: +// Instead of this function, use the alternative more efficient implementation +// via the Utils/Hash interface. +#if 0 unsigned long update_crc_32( unsigned long crc, char c ); +#endif unsigned short update_crc_ccitt( unsigned short crc, char c ); unsigned short update_crc_dnp( unsigned short crc, char c ); unsigned short update_crc_kermit( unsigned short crc, char c );