From 8f19470db3562046ed91920211a5d0a8cc4073fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Mon, 5 Sep 2022 20:46:43 +0200 Subject: [PATCH] Implement first draft of CRC core --- CMakeLists.txt | 1 + crc.c | 161 +++++++++++++++++++++++++++++++ include/patchelfcrc/crc.h | 54 +++++++++++ include/patchelfcrc/named_crcs.h | 25 +++-- include/patchelfcrc/version.h | 17 ++++ main.c | 39 +++++++- named_crcs.c | 95 ++++++++++-------- version.c | 17 ++++ 8 files changed, 362 insertions(+), 47 deletions(-) create mode 100644 crc.c create mode 100644 include/patchelfcrc/crc.h diff --git a/CMakeLists.txt b/CMakeLists.txt index d37fb08..8c6e9b4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,7 @@ set (CFILES main.c version.c named_crcs.c + crc.c ) set(GEN_HEADER_PATH "${CMAKE_CURRENT_BINARY_DIR}/include/generated") diff --git a/crc.c b/crc.c new file mode 100644 index 0000000..99852da --- /dev/null +++ b/crc.c @@ -0,0 +1,161 @@ +/* + * This file is part of patchelfcrc . + * Copyright (c) 2022 Mario Hüttel. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 only. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +int crc_len_from_poly(uint64_t polynomial) +{ + int pos = 0; + + /* Extract the MSB from the polynomial */ + for (pos = 63; pos >= 0; pos--) { + if (polynomial & (((uint64_t)1ULL) << pos)) { + /* Highest bit found */ + break; + } + } + + return pos; +} + +static uint64_t shorten_polynomial(uint64_t poly) +{ + int i; + + for (i = 31; i <= 0; i--) { + if (poly & (1 << i)) { + poly &= ~(1<crc_val; + + for (i = 0; i < len; i++, data++) { + crc_val = ((crc_val << 8) & crc->crc_mask) ^ crc->table[((crc_val >> (crc->crc_length-8u)) & 0xff) ^ *data]; + } + + crc->crc_val = crc_val; +} + +static void fill_crc_table(struct crc_calc *crc) +{ + uint32_t input; + uint32_t crc_reg; + uint32_t short_poly; + uint32_t crc_len; + int i; + + crc_len = crc->crc_length; + short_poly = (uint32_t)shorten_polynomial(crc->settings.polynomial); + + for (input = 0; input <= 255u; input++) { + + crc_reg = ((uint8_t)input) << (crc_len - 8u); + + for (i = 7; i >= 0; i--) { + + if (crc_reg & (1ul << (crc_len-1))) { + crc_reg <<= 1; + crc_reg ^= short_poly; + } else { + crc_reg <<= 1; + } + } + crc->table[input] = crc_reg; + } +} + +void crc_init(struct crc_calc *crc, const struct crc_settings *settings) +{ + uint32_t i; + + if (!crc || !settings) + return; + + memcpy(&crc->settings, settings, sizeof(struct crc_settings)); + + crc->table = (uint32_t *)malloc(256 * sizeof(uint32_t)); + crc->crc_length = crc_len_from_poly(crc->settings.polynomial); + crc->crc_val = settings->start_value; + + crc->crc_mask = 0x0UL; + for (i = 0; i < crc->crc_length; i++) + crc->crc_mask |= (1ul << i); + + /* Initialize the table */ + fill_crc_table(crc); +} + +void crc_push_bytes(struct crc_calc *crc, const uint8_t *b, size_t len) +{ + if (!crc) + return; + + internal_push_byte(crc, b, len); +} + +void crc_push_byte(struct crc_calc *crc, uint8_t b) +{ + if (!crc) + return; + + internal_push_byte(crc, &b, 1ul); +} + +void crc_destroy(struct crc_calc *crc) +{ + if (!crc) + return; + if (crc->table) + free(crc->table); +} + +uint32_t crc_get_value(struct crc_calc *crc) +{ + return crc->crc_val; +} + +void crc_finish_calc(struct crc_calc *crc) +{ + uint32_t val; + uint32_t i; + + if (!crc) + return; + + crc->crc_val ^= crc->settings.xor; + val = crc->crc_val; + if (crc->settings.rev) { + crc->crc_val = 0x0ul; + for (i = 0; i < crc->crc_length; i++) { + if (val & (1<<(crc->crc_length - i - 1))) { + crc->crc_val |= (1 << i); + } + } + } +} diff --git a/include/patchelfcrc/crc.h b/include/patchelfcrc/crc.h new file mode 100644 index 0000000..2af2d05 --- /dev/null +++ b/include/patchelfcrc/crc.h @@ -0,0 +1,54 @@ +/* + * This file is part of patchelfcrc . + * Copyright (c) 2022 Mario Hüttel. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 only. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _CRC_H_ +#define _CRC_H_ + +#include +#include +#include + +struct crc_settings { + uint64_t polynomial; + uint32_t xor; + uint32_t start_value; + bool rev; +}; + +struct crc_calc { + struct crc_settings settings; + uint32_t crc_val; + uint32_t crc_mask; + uint32_t crc_length; + uint32_t *table; +}; + +int crc_len_from_poly(uint64_t polynomial); + +void crc_init(struct crc_calc *crc, const struct crc_settings *settings); + +void crc_destroy(struct crc_calc *crc); + +void crc_push_byte(struct crc_calc *crc, uint8_t b); + +void crc_push_bytes(struct crc_calc *crc, const uint8_t *b, size_t len); + +void crc_finish_calc(struct crc_calc *crc); + +uint32_t crc_get_value(struct crc_calc *crc); + +#endif /* _CRC_H_ */ diff --git a/include/patchelfcrc/named_crcs.h b/include/patchelfcrc/named_crcs.h index 6c151e0..1feb86e 100644 --- a/include/patchelfcrc/named_crcs.h +++ b/include/patchelfcrc/named_crcs.h @@ -1,15 +1,26 @@ +/* + * This file is part of patchelfcrc . + * Copyright (c) 2022 Mario Hüttel. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 only. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #ifndef _NAMED_CRCS_H_ #define _NAMED_CRCS_H_ #include #include - -struct crc_settings { - uint32_t polynomial; - uint32_t xor; - uint32_t start_value; - bool rev; -}; +#include struct named_crc { const char *name; diff --git a/include/patchelfcrc/version.h b/include/patchelfcrc/version.h index a5b9305..8d0d9ea 100644 --- a/include/patchelfcrc/version.h +++ b/include/patchelfcrc/version.h @@ -1,3 +1,20 @@ +/* + * This file is part of patchelfcrc . + * Copyright (c) 2022 Mario Hüttel. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 only. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #ifndef _VERSION_H_ #define _VERSION_H_ diff --git a/main.c b/main.c index ff2e879..e72c49e 100644 --- a/main.c +++ b/main.c @@ -1,3 +1,20 @@ +/* + * This file is part of patchelfcrc . + * Copyright (c) 2022 Mario Hüttel. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 only. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #include #include #include @@ -5,6 +22,7 @@ #include #include #include +#include #include #include @@ -51,6 +69,8 @@ struct command_line_options { static error_t parse_opt(int key, char *arg, struct argp_state *state) { struct command_line_options *args = (struct command_line_options *)state->input; + char *endptr; + switch (key) { case ARG_KEY_DRY_RUN: args->dry_run = true; @@ -67,6 +87,13 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) case ARG_KEY_LIST: args->list = true; break; + case 'p': + /* Polyniomial */ + args->crc.polynomial = strtoull(arg, &endptr, 0); + if (endptr == arg) { + argp_error(state, "Error parsing polynomial: %s\n", arg); + } + break; case 'l': args->little_endian = true; break; @@ -140,7 +167,7 @@ static void prepare_default_opts(struct command_line_options *opts) opts->granularity = GRANULARITY_BYTE; opts->dry_run = false; opts->crc.xor = 0UL; - opts->crc.polynomial = 0x04C11DB7UL; + opts->crc.polynomial = 0x104C11DB7UL; opts->crc.start_value = 0xFFFFFFFFUL; opts->crc.rev = false; opts->format = FORMAT_BARE; @@ -169,6 +196,12 @@ static void print_verbose_start_info(const struct command_line_options *cmd_opts predef_crc = reverse_lookup_named_crc(&cmd_opts->crc); if (predef_crc) { print_debug("Predefined CRC detected: %s\n", predef_crc->name); + } else { + print_debug("Generator polynomial: 0x%lx\n", cmd_opts->crc.polynomial); + print_debug("Start value: 0x%x\n", cmd_opts->crc.start_value); + print_debug("Output XOR: 0x%x\n", cmd_opts->crc.xor); + print_debug("Reversed: %s\n", cmd_opts->crc.rev ? "yes" : "no"); + print_debug("CRC length: %d\n", crc_len_from_poly(cmd_opts->crc.polynomial)); } if (cmd_opts->section_list) { @@ -197,6 +230,7 @@ static void free_cmd_args(struct command_line_options *opts) int main(int argc, char **argv) { bool verbose; + struct crc_calc crc; struct command_line_options cmd_opts; prepare_default_opts(&cmd_opts); @@ -209,6 +243,9 @@ int main(int argc, char **argv) list_predefined_crcs(); goto free_cmds; } + + /* Build the CRC */ + crc_init(&crc, &cmd_opts.crc); free_cmds: free_cmd_args(&cmd_opts); diff --git a/named_crcs.c b/named_crcs.c index 1f9aae1..8605c8f 100644 --- a/named_crcs.c +++ b/named_crcs.c @@ -1,3 +1,20 @@ +/* + * This file is part of patchelfcrc . + * Copyright (c) 2022 Mario Hüttel. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 only. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #include #include #include @@ -14,44 +31,44 @@ }} const struct named_crc predefined_crc_table[] = { - NAMED_CRC("crc-8", 0x07, false, 0x00, 0x00), - NAMED_CRC("crc-8-darc", 0x39, true, 0x00, 0x00), - NAMED_CRC("crc-8-i-code", 0x1D, false, 0xFD, 0x00), - NAMED_CRC("crc-8-itu", 0x07, false, 0x55, 0x55), - NAMED_CRC("crc-8-maxim", 0x31, true, 0x00, 0x00), - NAMED_CRC("crc-8-rohc", 0x07, true, 0xFF, 0x00), - NAMED_CRC("crc-8-wcdma", 0x9B, true, 0x00, 0x00), - NAMED_CRC("crc-16", 0x8005, true, 0x0000, 0x0000), - NAMED_CRC("crc-16-buypass", 0x8005, false, 0x0000, 0x0000), - NAMED_CRC("crc-16-dds-110", 0x8005, false, 0x800D, 0x0000), - NAMED_CRC("crc-16-dect", 0x0589, false, 0x0001, 0x0001), - NAMED_CRC("crc-16-dnp", 0x3D65, true, 0xFFFF, 0xFFFF), - NAMED_CRC("crc-16-en-13757", 0x3D65, false, 0xFFFF, 0xFFFF), - NAMED_CRC("crc-16-genibus", 0x1021, false, 0x0000, 0xFFFF), - NAMED_CRC("crc-16-maxim", 0x8005, true, 0xFFFF, 0xFFFF), - NAMED_CRC("crc-16-mcrf4xx", 0x1021, true, 0xFFFF, 0x0000), - NAMED_CRC("crc-16-riello", 0x1021, true, 0x554D, 0x0000), - NAMED_CRC("crc-16-t10-dif", 0x8BB7, false, 0x0000, 0x0000), - NAMED_CRC("crc-16-teledisk", 0xA097, false, 0x0000, 0x0000), - NAMED_CRC("crc-16-usb", 0x8005, true, 0x0000, 0xFFFF), - NAMED_CRC("x-25", 0x1021, true, 0x0000, 0xFFFF), - NAMED_CRC("xmodem", 0x1021, false, 0x0000, 0x0000), - NAMED_CRC("modbus", 0x8005, true, 0xFFFF, 0x0000), - NAMED_CRC("kermit", 0x1021, true, 0x0000, 0x0000), - NAMED_CRC("crc-ccitt-false", 0x1021, false, 0xFFFF, 0x0000), - NAMED_CRC("crc-aug-ccitt", 0x1021, false, 0x1D0F, 0x0000), - NAMED_CRC("crc-24", 0x864CFB, false, 0xB704CE, 0x000000), - NAMED_CRC("crc-24-flexray-a", 0x5D6DCB, false, 0xFEDCBA, 0x000000), - NAMED_CRC("crc-24-flexray-b", 0x5D6DCB, false, 0xABCDEF, 0x000000), - NAMED_CRC("crc-32", 0x04C11DB7, true, 0x00000000, 0xFFFFFFFF), - NAMED_CRC("crc-32-bzip2", 0x04C11DB7, false, 0x00000000, 0xFFFFFFFF), - NAMED_CRC("crc-32c", 0x1EDC6F41, true, 0x00000000, 0xFFFFFFFF), - NAMED_CRC("crc-32d", 0xA833982B, true, 0x00000000, 0xFFFFFFFF), - NAMED_CRC("crc-32-mpeg", 0x04C11DB7, false, 0xFFFFFFFF, 0x00000000), - NAMED_CRC("posix", 0x04C11DB7, false, 0xFFFFFFFF, 0xFFFFFFFF), - NAMED_CRC("crc-32q", 0x814141AB, false, 0x00000000, 0x00000000), - NAMED_CRC("jamcrc", 0x04C11DB7, true, 0xFFFFFFFF, 0x00000000), - NAMED_CRC("xfer", 0x000000AF, false, 0x00000000, 0x00000000), + NAMED_CRC("crc-8", 0x107, false, 0x00, 0x00), + NAMED_CRC("crc-8-darc", 0x139, true, 0x00, 0x00), + NAMED_CRC("crc-8-i-code", 0x11D, false, 0xFD, 0x00), + NAMED_CRC("crc-8-itu", 0x107, false, 0x55, 0x55), + NAMED_CRC("crc-8-maxim", 0x131, true, 0x00, 0x00), + NAMED_CRC("crc-8-rohc", 0x107, true, 0xFF, 0x00), + NAMED_CRC("crc-8-wcdma", 0x19B, true, 0x00, 0x00), + NAMED_CRC("crc-16", 0x18005, true, 0x0000, 0x0000), + NAMED_CRC("crc-16-buypass", 0x18005, false, 0x0000, 0x0000), + NAMED_CRC("crc-16-dds-110", 0x18005, false, 0x800D, 0x0000), + NAMED_CRC("crc-16-dect", 0x10589, false, 0x0001, 0x0001), + NAMED_CRC("crc-16-dnp", 0x13D65, true, 0xFFFF, 0xFFFF), + NAMED_CRC("crc-16-en-13757", 0x13D65, false, 0xFFFF, 0xFFFF), + NAMED_CRC("crc-16-genibus", 0x11021, false, 0x0000, 0xFFFF), + NAMED_CRC("crc-16-maxim", 0x18005, true, 0xFFFF, 0xFFFF), + NAMED_CRC("crc-16-mcrf4xx", 0x11021, true, 0xFFFF, 0x0000), + NAMED_CRC("crc-16-riello", 0x11021, true, 0x554D, 0x0000), + NAMED_CRC("crc-16-t10-dif", 0x18BB7, false, 0x0000, 0x0000), + NAMED_CRC("crc-16-teledisk", 0x1A097, false, 0x0000, 0x0000), + NAMED_CRC("crc-16-usb", 0x18005, true, 0x0000, 0xFFFF), + NAMED_CRC("x-25", 0x11021, true, 0x0000, 0xFFFF), + NAMED_CRC("xmodem", 0x11021, false, 0x0000, 0x0000), + NAMED_CRC("modbus", 0x18005, true, 0xFFFF, 0x0000), + NAMED_CRC("kermit", 0x11021, true, 0x0000, 0x0000), + NAMED_CRC("crc-ccitt-false", 0x11021, false, 0xFFFF, 0x0000), + NAMED_CRC("crc-aug-ccitt", 0x11021, false, 0x1D0F, 0x0000), + NAMED_CRC("crc-24", 0x1864CFB, false, 0xB704CE, 0x000000), + NAMED_CRC("crc-24-flexray-a", 0x15D6DCB, false, 0xFEDCBA, 0x000000), + NAMED_CRC("crc-24-flexray-b", 0x15D6DCB, false, 0xABCDEF, 0x000000), + NAMED_CRC("crc-32", 0x104C11DB7, true, 0x00000000, 0xFFFFFFFF), + NAMED_CRC("crc-32-bzip2", 0x104C11DB7, false, 0x00000000, 0xFFFFFFFF), + NAMED_CRC("crc-32c", 0x11EDC6F41, true, 0x00000000, 0xFFFFFFFF), + NAMED_CRC("crc-32d", 0x1A833982B, true, 0x00000000, 0xFFFFFFFF), + NAMED_CRC("crc-32-mpeg", 0x104C11DB7, false, 0xFFFFFFFF, 0x00000000), + NAMED_CRC("posix", 0x104C11DB7, false, 0xFFFFFFFF, 0xFFFFFFFF), + NAMED_CRC("crc-32q", 0x1814141AB, false, 0x00000000, 0x00000000), + NAMED_CRC("jamcrc", 0x104C11DB7, true, 0xFFFFFFFF, 0x00000000), + NAMED_CRC("xfer", 0x1000000AF, false, 0x00000000, 0x00000000), /* SENTINEL */ {.name = NULL, .settings = {0, 0, 0, false}}, }; @@ -100,7 +117,7 @@ void list_predefined_crcs(void) ft_write_ln(table, "Name", "Polynomial", "Reversed", "Start Value", "Output XOR"); for (iter = predefined_crc_table; iter->name; iter++) { - ft_printf_ln(table, "%s|0x%x|%s|0x%x|0x%x", + ft_printf_ln(table, "%s|0x%lx|%s|0x%x|0x%x", iter->name, iter->settings.polynomial, iter->settings.rev ? "yes" : "no", diff --git a/version.c b/version.c index 24f07ae..df8cf15 100644 --- a/version.c +++ b/version.c @@ -1,3 +1,20 @@ +/* + * This file is part of patchelfcrc . + * Copyright (c) 2022 Mario Hüttel. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 only. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #include #include