common/omv_crc: Update CRC support.

- Add support for CRC32 with software fallback.
- Update polynomials and lookup tables.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
This commit is contained in:
iabdalkader 2025-09-24 13:36:35 +02:00
parent 26aa191ad7
commit e075aefca4
2 changed files with 161 additions and 68 deletions

View File

@ -23,64 +23,120 @@
*/ */
#include "omv_crc.h" #include "omv_crc.h"
// CRC16 lookup table for polynomial 0xF94F (HD=6, len=135)
static const uint16_t crc16_table[256] = { static const uint16_t crc16_table[256] = {
0x0000, 0xBAAD, 0xCFF7, 0x755A, 0x2543, 0x9FEE, 0xEAB4, 0x5019, 0x0000, 0xF94F, 0x0BD1, 0xF29E, 0x17A2, 0xEEED, 0x1C73, 0xE53C,
0x4A86, 0xF02B, 0x8571, 0x3FDC, 0x6FC5, 0xD568, 0xA032, 0x1A9F, 0x2F44, 0xD60B, 0x2495, 0xDDDA, 0x38E6, 0xC1A9, 0x3337, 0xCA78,
0x950C, 0x2FA1, 0x5AFB, 0xE056, 0xB04F, 0x0AE2, 0x7FB8, 0xC515, 0x5E88, 0xA7C7, 0x5559, 0xAC16, 0x492A, 0xB065, 0x42FB, 0xBBB4,
0xDF8A, 0x6527, 0x107D, 0xAAD0, 0xFAC9, 0x4064, 0x353E, 0x8F93, 0x71CC, 0x8883, 0x7A1D, 0x8352, 0x666E, 0x9F21, 0x6DBF, 0x94F0,
0x90B5, 0x2A18, 0x5F42, 0xE5EF, 0xB5F6, 0x0F5B, 0x7A01, 0xC0AC, 0xBD10, 0x445F, 0xB6C1, 0x4F8E, 0xAAB2, 0x53FD, 0xA163, 0x582C,
0xDA33, 0x609E, 0x15C4, 0xAF69, 0xFF70, 0x45DD, 0x3087, 0x8A2A, 0x9254, 0x6B1B, 0x9985, 0x60CA, 0x85F6, 0x7CB9, 0x8E27, 0x7768,
0x05B9, 0xBF14, 0xCA4E, 0x70E3, 0x20FA, 0x9A57, 0xEF0D, 0x55A0, 0xE398, 0x1AD7, 0xE849, 0x1106, 0xF43A, 0x0D75, 0xFFEB, 0x06A4,
0x4F3F, 0xF592, 0x80C8, 0x3A65, 0x6A7C, 0xD0D1, 0xA58B, 0x1F26, 0xCCDC, 0x3593, 0xC70D, 0x3E42, 0xDB7E, 0x2231, 0xD0AF, 0x29E0,
0x9BC7, 0x216A, 0x5430, 0xEE9D, 0xBE84, 0x0429, 0x7173, 0xCBDE, 0x836F, 0x7A20, 0x88BE, 0x71F1, 0x94CD, 0x6D82, 0x9F1C, 0x6653,
0xD141, 0x6BEC, 0x1EB6, 0xA41B, 0xF402, 0x4EAF, 0x3BF5, 0x8158, 0xAC2B, 0x5564, 0xA7FA, 0x5EB5, 0xBB89, 0x42C6, 0xB058, 0x4917,
0x0ECB, 0xB466, 0xC13C, 0x7B91, 0x2B88, 0x9125, 0xE47F, 0x5ED2, 0xDDE7, 0x24A8, 0xD636, 0x2F79, 0xCA45, 0x330A, 0xC194, 0x38DB,
0x444D, 0xFEE0, 0x8BBA, 0x3117, 0x610E, 0xDBA3, 0xAEF9, 0x1454, 0xF2A3, 0x0BEC, 0xF972, 0x003D, 0xE501, 0x1C4E, 0xEED0, 0x179F,
0x0B72, 0xB1DF, 0xC485, 0x7E28, 0x2E31, 0x949C, 0xE1C6, 0x5B6B, 0x3E7F, 0xC730, 0x35AE, 0xCCE1, 0x29DD, 0xD092, 0x220C, 0xDB43,
0x41F4, 0xFB59, 0x8E03, 0x34AE, 0x64B7, 0xDE1A, 0xAB40, 0x11ED, 0x113B, 0xE874, 0x1AEA, 0xE3A5, 0x0699, 0xFFD6, 0x0D48, 0xF407,
0x9E7E, 0x24D3, 0x5189, 0xEB24, 0xBB3D, 0x0190, 0x74CA, 0xCE67, 0x60F7, 0x99B8, 0x6B26, 0x9269, 0x7755, 0x8E1A, 0x7C84, 0x85CB,
0xD4F8, 0x6E55, 0x1B0F, 0xA1A2, 0xF1BB, 0x4B16, 0x3E4C, 0x84E1, 0x4FB3, 0xB6FC, 0x4462, 0xBD2D, 0x5811, 0xA15E, 0x53C0, 0xAA8F,
0x8D23, 0x378E, 0x42D4, 0xF879, 0xA860, 0x12CD, 0x6797, 0xDD3A, 0xFF91, 0x06DE, 0xF440, 0x0D0F, 0xE833, 0x117C, 0xE3E2, 0x1AAD,
0xC7A5, 0x7D08, 0x0852, 0xB2FF, 0xE2E6, 0x584B, 0x2D11, 0x97BC, 0xD0D5, 0x299A, 0xDB04, 0x224B, 0xC777, 0x3E38, 0xCCA6, 0x35E9,
0x182F, 0xA282, 0xD7D8, 0x6D75, 0x3D6C, 0x87C1, 0xF29B, 0x4836, 0xA119, 0x5856, 0xAAC8, 0x5387, 0xB6BB, 0x4FF4, 0xBD6A, 0x4425,
0x52A9, 0xE804, 0x9D5E, 0x27F3, 0x77EA, 0xCD47, 0xB81D, 0x02B0, 0x8E5D, 0x7712, 0x858C, 0x7CC3, 0x99FF, 0x60B0, 0x922E, 0x6B61,
0x1D96, 0xA73B, 0xD261, 0x68CC, 0x38D5, 0x8278, 0xF722, 0x4D8F, 0x4281, 0xBBCE, 0x4950, 0xB01F, 0x5523, 0xAC6C, 0x5EF2, 0xA7BD,
0x5710, 0xEDBD, 0x98E7, 0x224A, 0x7253, 0xC8FE, 0xBDA4, 0x0709, 0x6DC5, 0x948A, 0x6614, 0x9F5B, 0x7A67, 0x8328, 0x71B6, 0x88F9,
0x889A, 0x3237, 0x476D, 0xFDC0, 0xADD9, 0x1774, 0x622E, 0xD883, 0x1C09, 0xE546, 0x17D8, 0xEE97, 0x0BAB, 0xF2E4, 0x007A, 0xF935,
0xC21C, 0x78B1, 0x0DEB, 0xB746, 0xE75F, 0x5DF2, 0x28A8, 0x9205, 0x334D, 0xCA02, 0x389C, 0xC1D3, 0x24EF, 0xDDA0, 0x2F3E, 0xD671,
0x16E4, 0xAC49, 0xD913, 0x63BE, 0x33A7, 0x890A, 0xFC50, 0x46FD, 0x7CFE, 0x85B1, 0x772F, 0x8E60, 0x6B5C, 0x9213, 0x608D, 0x99C2,
0x5C62, 0xE6CF, 0x9395, 0x2938, 0x7921, 0xC38C, 0xB6D6, 0x0C7B, 0x53BA, 0xAAF5, 0x586B, 0xA124, 0x4418, 0xBD57, 0x4FC9, 0xB686,
0x83E8, 0x3945, 0x4C1F, 0xF6B2, 0xA6AB, 0x1C06, 0x695C, 0xD3F1, 0x2276, 0xDB39, 0x29A7, 0xD0E8, 0x35D4, 0xCC9B, 0x3E05, 0xC74A,
0xC96E, 0x73C3, 0x0699, 0xBC34, 0xEC2D, 0x5680, 0x23DA, 0x9977, 0x0D32, 0xF47D, 0x06E3, 0xFFAC, 0x1A90, 0xE3DF, 0x1141, 0xE80E,
0x8651, 0x3CFC, 0x49A6, 0xF30B, 0xA312, 0x19BF, 0x6CE5, 0xD648, 0xC1EE, 0x38A1, 0xCA3F, 0x3370, 0xD64C, 0x2F03, 0xDD9D, 0x24D2,
0xCCD7, 0x767A, 0x0320, 0xB98D, 0xE994, 0x5339, 0x2663, 0x9CCE, 0xEEAA, 0x17E5, 0xE57B, 0x1C34, 0xF908, 0x0047, 0xF2D9, 0x0B96,
0x135D, 0xA9F0, 0xDCAA, 0x6607, 0x361E, 0x8CB3, 0xF9E9, 0x4344, 0x9F66, 0x6629, 0x94B7, 0x6DF8, 0x88C4, 0x718B, 0x8315, 0x7A5A,
0x59DB, 0xE376, 0x962C, 0x2C81, 0x7C98, 0xC635, 0xB36F, 0x09C2 0xB022, 0x496D, 0xBBF3, 0x42BC, 0xA780, 0x5ECF, 0xAC51, 0x551E,
}; };
__attribute__((weak)) void omv_crc_init(void) { // CRC32 lookup table for polynomial 0xFA567D89
const uint32_t crc32_table[256] = {
0x00000000, 0xFA567D89, 0x0EFA869B, 0xF4ACFB12, 0x1DF50D36, 0xE7A370BF, 0x130F8BAD, 0xE959F624,
0x3BEA1A6C, 0xC1BC67E5, 0x35109CF7, 0xCF46E17E, 0x261F175A, 0xDC496AD3, 0x28E591C1, 0xD2B3EC48,
0x77D434D8, 0x8D824951, 0x792EB243, 0x8378CFCA, 0x6A2139EE, 0x90774467, 0x64DBBF75, 0x9E8DC2FC,
0x4C3E2EB4, 0xB668533D, 0x42C4A82F, 0xB892D5A6, 0x51CB2382, 0xAB9D5E0B, 0x5F31A519, 0xA567D890,
0xEFA869B0, 0x15FE1439, 0xE152EF2B, 0x1B0492A2, 0xF25D6486, 0x080B190F, 0xFCA7E21D, 0x06F19F94,
0xD44273DC, 0x2E140E55, 0xDAB8F547, 0x20EE88CE, 0xC9B77EEA, 0x33E10363, 0xC74DF871, 0x3D1B85F8,
0x987C5D68, 0x622A20E1, 0x9686DBF3, 0x6CD0A67A, 0x8589505E, 0x7FDF2DD7, 0x8B73D6C5, 0x7125AB4C,
0xA3964704, 0x59C03A8D, 0xAD6CC19F, 0x573ABC16, 0xBE634A32, 0x443537BB, 0xB099CCA9, 0x4ACFB120,
0x2506AEE9, 0xDF50D360, 0x2BFC2872, 0xD1AA55FB, 0x38F3A3DF, 0xC2A5DE56, 0x36092544, 0xCC5F58CD,
0x1EECB485, 0xE4BAC90C, 0x1016321E, 0xEA404F97, 0x0319B9B3, 0xF94FC43A, 0x0DE33F28, 0xF7B542A1,
0x52D29A31, 0xA884E7B8, 0x5C281CAA, 0xA67E6123, 0x4F279707, 0xB571EA8E, 0x41DD119C, 0xBB8B6C15,
0x6938805D, 0x936EFDD4, 0x67C206C6, 0x9D947B4F, 0x74CD8D6B, 0x8E9BF0E2, 0x7A370BF0, 0x80617679,
0xCAAEC759, 0x30F8BAD0, 0xC45441C2, 0x3E023C4B, 0xD75BCA6F, 0x2D0DB7E6, 0xD9A14CF4, 0x23F7317D,
0xF144DD35, 0x0B12A0BC, 0xFFBE5BAE, 0x05E82627, 0xECB1D003, 0x16E7AD8A, 0xE24B5698, 0x181D2B11,
0xBD7AF381, 0x472C8E08, 0xB380751A, 0x49D60893, 0xA08FFEB7, 0x5AD9833E, 0xAE75782C, 0x542305A5,
0x8690E9ED, 0x7CC69464, 0x886A6F76, 0x723C12FF, 0x9B65E4DB, 0x61339952, 0x959F6240, 0x6FC91FC9,
0x4A0D5DD2, 0xB05B205B, 0x44F7DB49, 0xBEA1A6C0, 0x57F850E4, 0xADAE2D6D, 0x5902D67F, 0xA354ABF6,
0x71E747BE, 0x8BB13A37, 0x7F1DC125, 0x854BBCAC, 0x6C124A88, 0x96443701, 0x62E8CC13, 0x98BEB19A,
0x3DD9690A, 0xC78F1483, 0x3323EF91, 0xC9759218, 0x202C643C, 0xDA7A19B5, 0x2ED6E2A7, 0xD4809F2E,
0x06337366, 0xFC650EEF, 0x08C9F5FD, 0xF29F8874, 0x1BC67E50, 0xE19003D9, 0x153CF8CB, 0xEF6A8542,
0xA5A53462, 0x5FF349EB, 0xAB5FB2F9, 0x5109CF70, 0xB8503954, 0x420644DD, 0xB6AABFCF, 0x4CFCC246,
0x9E4F2E0E, 0x64195387, 0x90B5A895, 0x6AE3D51C, 0x83BA2338, 0x79EC5EB1, 0x8D40A5A3, 0x7716D82A,
0xD27100BA, 0x28277D33, 0xDC8B8621, 0x26DDFBA8, 0xCF840D8C, 0x35D27005, 0xC17E8B17, 0x3B28F69E,
0xE99B1AD6, 0x13CD675F, 0xE7619C4D, 0x1D37E1C4, 0xF46E17E0, 0x0E386A69, 0xFA94917B, 0x00C2ECF2,
0x6F0BF33B, 0x955D8EB2, 0x61F175A0, 0x9BA70829, 0x72FEFE0D, 0x88A88384, 0x7C047896, 0x8652051F,
0x54E1E957, 0xAEB794DE, 0x5A1B6FCC, 0xA04D1245, 0x4914E461, 0xB34299E8, 0x47EE62FA, 0xBDB81F73,
0x18DFC7E3, 0xE289BA6A, 0x16254178, 0xEC733CF1, 0x052ACAD5, 0xFF7CB75C, 0x0BD04C4E, 0xF18631C7,
0x2335DD8F, 0xD963A006, 0x2DCF5B14, 0xD799269D, 0x3EC0D0B9, 0xC496AD30, 0x303A5622, 0xCA6C2BAB,
0x80A39A8B, 0x7AF5E702, 0x8E591C10, 0x740F6199, 0x9D5697BD, 0x6700EA34, 0x93AC1126, 0x69FA6CAF,
0xBB4980E7, 0x411FFD6E, 0xB5B3067C, 0x4FE57BF5, 0xA6BC8DD1, 0x5CEAF058, 0xA8460B4A, 0x521076C3,
0xF777AE53, 0x0D21D3DA, 0xF98D28C8, 0x03DB5541, 0xEA82A365, 0x10D4DEEC, 0xE47825FE, 0x1E2E5877,
0xCC9DB43F, 0x36CBC9B6, 0xC26732A4, 0x38314F2D, 0xD168B909, 0x2B3EC480, 0xDF923F92, 0x25C4421B,
};
} __attribute__((weak)) uint16_t omv_crc16_start(const void *buf, size_t len) {
const uint8_t *data = (const uint8_t *) buf;
uint16_t crc = OMV_CRC16_INIT;
__attribute__((weak)) omv_crc_t omv_crc_start(const void *buf, size_t size) { for (size_t i = 0; i < len; i++) {
const uint8_t *data = (const uint8_t *)buf;
omv_crc_t crc = OMV_CRC_INIT;
for (size_t i = 0; i < size; i++) {
uint8_t index = (crc >> 8) ^ data[i]; uint8_t index = (crc >> 8) ^ data[i];
crc = (crc << 8) ^ crc16_table[index]; crc = (crc << 8) ^ crc16_table[index];
} }
return crc; return crc;
} }
__attribute__((weak)) omv_crc_t omv_crc_update(omv_crc_t crc, const void *buf, size_t size) { __attribute__((weak)) uint16_t omv_crc16_update(uint16_t crc, const void *buf, size_t len) {
const uint8_t *data = (const uint8_t *)buf; const uint8_t *data = (const uint8_t *) buf;
for (size_t i = 0; i < size; i++) { for (size_t i = 0; i < len; i++) {
uint8_t index = (crc >> 8) ^ data[i]; uint8_t index = (crc >> 8) ^ data[i];
crc = (crc << 8) ^ crc16_table[index]; crc = (crc << 8) ^ crc16_table[index];
} }
return crc;
}
__attribute__((weak)) uint32_t omv_crc32_start(const void *buf, size_t len) {
const uint8_t *data = (const uint8_t *) buf;
uint32_t crc = OMV_CRC32_INIT;
for (size_t i = 0; i < len; i++) {
uint8_t index = (crc >> 24) ^ data[i];
crc = (crc << 8) ^ crc32_table[index];
}
return crc;
}
__attribute__((weak)) uint32_t omv_crc32_update(uint32_t crc, const void *buf, size_t len) {
const uint8_t *data = (const uint8_t *) buf;
for (size_t i = 0; i < len; i++) {
uint8_t index = (crc >> 24) ^ data[i];
crc = (crc << 8) ^ crc32_table[index];
}
return crc; return crc;
} }

View File

@ -27,37 +27,74 @@
#include <stddef.h> #include <stddef.h>
#include <stdbool.h> #include <stdbool.h>
// 0xBAAD is ironically good - HD=5 up to 108 bits, HD=4 up to 7985 bits // CRC size enumeration
#define OMV_CRC_POLY (0xBAAD) typedef enum {
#define OMV_CRC_INIT (0xFFFF) OMV_CRC16 = 16,
#define OMV_CRC_SIZE (16) OMV_CRC32 = 32
typedef uint16_t omv_crc_t; } omv_crc_size_t;
// Initialize CRC hardware (if available) // HD=6 up to 114 bits
void omv_crc_init(void); #define OMV_CRC16_POLY (0xF94F)
#define OMV_CRC16_INIT (0xFFFF)
// Start CRC calculation for buffer data // HD=6 up to 32738 bits (~4K)
omv_crc_t omv_crc_start(const void *buf, size_t size); #define OMV_CRC32_POLY (0xFA567D89)
#define OMV_CRC32_INIT (0xFFFFFFFF)
// Update CRC with additional buffer data // Default software implementations
omv_crc_t omv_crc_update(omv_crc_t crc, const void *buf, size_t size); uint16_t omv_crc16_start(const void *buf, size_t len);
uint16_t omv_crc16_update(uint16_t crc, const void *buf, size_t len);
// Read CRC value from the last 2 bytes of buffer uint32_t omv_crc32_start(const void *buf, size_t len);
static inline omv_crc_t omv_crc_read(const void *buf, size_t size) { uint32_t omv_crc32_update(uint32_t crc, const void *buf, size_t len);
const uint8_t *crc_buf = (const uint8_t *)buf + size - 2;
return *((omv_crc_t*) crc_buf); // Public API functions
static inline uint32_t omv_crc_start(omv_crc_size_t size, const void *buf, size_t len) {
if (size == OMV_CRC16) {
return omv_crc16_start(buf, len);
} else if (size == OMV_CRC32) {
return omv_crc32_start(buf, len);
}
return 0;
} }
// Calculate CRC and write it to the last 2 bytes of buffer static inline uint32_t omv_crc_update(omv_crc_size_t size, uint32_t crc, const void *buf, size_t len) {
static inline void omv_crc_write(void *buf, size_t size) { if (size == OMV_CRC16) {
omv_crc_t crc = omv_crc_start(buf, size - 2); return omv_crc16_update((uint16_t) crc, buf, len);
uint8_t *crc_buf = (uint8_t *)buf + size - 2; } else if (size == OMV_CRC32) {
crc_buf[0] = crc & 0xFF; return omv_crc32_update(crc, buf, len);
crc_buf[1] = (crc >> 8) & 0xFF; }
return crc;
}
// Read CRC value from the last bytes of buffer
static inline uint32_t omv_crc_read(omv_crc_size_t crc_size, const void *buf, size_t size) {
const uint8_t *crc_buf = (const uint8_t *) buf + size - (crc_size == OMV_CRC16 ? 2 : 4);
if (crc_size == OMV_CRC16) {
return *((uint16_t *) crc_buf);
} else {
return *((uint32_t *) crc_buf);
}
}
// Calculate CRC and write it to the last bytes of buffer
static inline void omv_crc_write(omv_crc_size_t crc_size, void *buf, size_t size) {
uint32_t crc = omv_crc_start(crc_size, buf, size - (crc_size == OMV_CRC16 ? 2 : 4));
uint8_t *crc_buf = (uint8_t *) buf + size - (crc_size == OMV_CRC16 ? 2 : 4);
if (crc_size == OMV_CRC16) {
crc_buf[0] = crc & 0xFF;
crc_buf[1] = (crc >> 8) & 0xFF;
} else {
crc_buf[0] = crc & 0xFF;
crc_buf[1] = (crc >> 8) & 0xFF;
crc_buf[2] = (crc >> 16) & 0xFF;
crc_buf[3] = (crc >> 24) & 0xFF;
}
} }
// Calculate and check if CRC matches the one stored in buffer // Calculate and check if CRC matches the one stored in buffer
static inline bool omv_crc_check(const void *buf, size_t size) { static inline bool omv_crc_check(omv_crc_size_t crc_size, const void *buf, size_t size) {
return omv_crc_read(buf, size) == omv_crc_start(buf, size - 2); return omv_crc_read(crc_size, buf, size) == omv_crc_start(crc_size, buf, size - (crc_size == OMV_CRC16 ? 2 : 4));
} }
#endif // __OMV_CRC_H__ #endif // __OMV_CRC_H__