summaryrefslogtreecommitdiffstats
path: root/src/ipmiblob/crc.cpp
blob: 617a9d6b8817510aea92d4fae6fb09f2b8a84f52 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include "crc.hpp"

namespace ipmiblob
{

/*
 * This implementation tracks the specification given at
 * http://srecord.sourceforge.net/crc16-ccitt.html
 * Code copied from internal portable sources.
 */
std::uint16_t generateCrc(const std::vector<std::uint8_t>& data)
{
    const std::uint16_t kPoly = 0x1021;
    const std::uint16_t kLeftBit = 0x8000;
    const int kExtraRounds = 2;
    const std::uint8_t* bytes = data.data();
    std::uint16_t crc = 0xFFFF;
    std::size_t i;
    std::size_t j;
    std::size_t size = data.size();

    for (i = 0; i < size + kExtraRounds; ++i)
    {
        for (j = 0; j < 8; ++j)
        {
            bool xor_flag = (crc & kLeftBit) ? 1 : 0;
            crc <<= 1;
            // If this isn't an extra round and the current byte's j'th bit from
            // the left is set, increment the CRC.
            if (i < size && (bytes[i] & (1 << (7 - j))))
            {
                crc++;
            }
            if (xor_flag)
            {
                crc ^= kPoly;
            }
        }
    }

    return crc;
}

} // namespace ipmiblob
OpenPOWER on IntegriCloud