diff --git a/src/crc32.c b/src/crc32.c index d5be271924f..7b05155cc05 100644 --- a/src/crc32.c +++ b/src/crc32.c @@ -100,7 +100,7 @@ static uint32_t crc32_calc(const uint32_t crc, const uint8_t data) return (crc << 8U) ^ crc32_table[((crc >> 24U) ^ data) & 0xffU]; } -bool generic_crc32(target_s *const t, uint32_t *const crc_res, uint32_t base, size_t len) +bool generic_crc32(target_s *const target, uint32_t *const result, const uint32_t base, const size_t len) { uint32_t crc = 0xffffffffU; #if PC_HOSTED == 1 @@ -108,83 +108,81 @@ bool generic_crc32(target_s *const t, uint32_t *const crc_res, uint32_t base, si * Reading a 2 MByte on a H743 takes about 80 s@128, 28s @ 1k, * 22 s @ 4k and 21 s @ 64k */ - uint8_t bytes[0x1000]; + uint8_t bytes[4096U]; #else - uint8_t bytes[128]; + uint8_t bytes[128U]; #endif #if defined(ENABLE_DEBUG) const uint32_t start_time = platform_time_ms(); #endif uint32_t last_time = platform_time_ms(); - while (len) { + for (size_t offset = 0; offset < len; offset += sizeof(bytes)) { const uint32_t actual_time = platform_time_ms(); if (actual_time > last_time + 1000U) { last_time = actual_time; gdb_if_putchar(0, true); } - const size_t read_len = MIN(sizeof(bytes), len); - if (target_mem_read(t, bytes, base, (read_len + 3U) & ~3U)) { - DEBUG_ERROR("generic_crc32 error around address 0x%08" PRIx32 "\n", base); + const size_t read_len = MIN(sizeof(bytes), len - offset); + if (target_mem_read(target, bytes, base + offset, (read_len + 3U) & ~3U)) { + DEBUG_ERROR("generic_crc32 error around address 0x%08" PRIx32 "\n", (uint32_t)(base + offset)); return false; } for (size_t i = 0; i < read_len; i++) crc = crc32_calc(crc, bytes[i]); - - base += read_len; - len -= read_len; } DEBUG_WARN("%" PRIu32 " ms\n", platform_time_ms() - start_time); - *crc_res = crc; + *result = crc; return true; } #else #include +#include "buffer_utils.h" -bool generic_crc32(target_s *const t, uint32_t *const crc_res, uint32_t base, size_t len) +bool generic_crc32(target_s *const target, uint32_t *const result, const uint32_t base, const size_t len) { - uint8_t bytes[128]; + uint8_t bytes[128U]; CRC_CR |= CRC_CR_RESET; uint32_t last_time = platform_time_ms(); - while (len > 3U) { + const size_t adjusted_len = len & ~3U; + for (size_t offset = 0; offset < adjusted_len; offset += sizeof(bytes)) { const uint32_t actual_time = platform_time_ms(); if (actual_time > last_time + 1000U) { last_time = actual_time; gdb_if_putchar(0, true); } - const size_t read_len = MIN(sizeof(bytes), len) & ~3U; - if (target_mem_read(t, bytes, base, read_len)) { - DEBUG_ERROR("generic_crc32 error around address 0x%08" PRIx32 "\n", base); + const size_t read_len = MIN(sizeof(bytes), adjusted_len - offset); + if (target_mem_read(target, bytes, base + offset, read_len)) { + DEBUG_ERROR("generic_crc32 error around address 0x%08" PRIx32 "\n", (uint32_t)(base + offset)); return false; } for (size_t i = 0; i < read_len; i += 4U) - CRC_DR = __builtin_bswap32(*(uint32_t *)(bytes + i)); - - base += read_len; - len -= read_len; + CRC_DR = read_be4(bytes, i); } uint32_t crc = CRC_DR; - if (target_mem_read(t, bytes, base, len)) { - DEBUG_ERROR("generic_crc32 error around address 0x%08" PRIx32 "\n", base); - return false; - } - uint8_t *data = bytes; - while (len--) { - crc ^= *data++ << 24U; - for (size_t i = 0; i < 8U; i++) { - if (crc & 0x80000000U) - crc = (crc << 1U) ^ 0x4c11db7U; - else - crc <<= 1U; + const size_t remainder = len - adjusted_len; + if (remainder) { + if (target_mem_read(target, bytes, base + adjusted_len, remainder)) { + DEBUG_ERROR("generic_crc32 error around address 0x%08" PRIx32 "\n", (uint32_t)(base + adjusted_len)); + return false; + } + for (size_t offset = 0; offset < remainder; ++offset) { + crc ^= bytes[offset] << 24U; + for (size_t i = 0; i < 8U; i++) { + if (crc & 0x80000000U) + crc = (crc << 1U) ^ 0x4c11db7U; + else + crc <<= 1U; + } } } - *crc_res = crc; + *result = crc; return true; } #endif diff --git a/src/include/buffer_utils.h b/src/include/buffer_utils.h index c8792be1b23..085d75af9ad 100644 --- a/src/include/buffer_utils.h +++ b/src/include/buffer_utils.h @@ -62,4 +62,10 @@ static inline uint32_t read_le4(const uint8_t *const buffer, const size_t offset ((uint32_t)buffer[offset + 3U] << 24U); } +static inline uint32_t read_be4(const uint8_t *const buffer, const size_t offset) +{ + return ((uint32_t)buffer[offset + 0U] << 24U) | ((uint32_t)buffer[offset + 1U] << 16U) | + ((uint32_t)buffer[offset + 2U] << 8U) | buffer[offset + 3U]; +} + #endif /*INCLUDE_BUFFER_UTILS_H*/ diff --git a/src/include/crc32.h b/src/include/crc32.h index 99b285af255..9521255504a 100644 --- a/src/include/crc32.h +++ b/src/include/crc32.h @@ -21,6 +21,9 @@ #ifndef INCLUDE_CRC32_H #define INCLUDE_CRC32_H -bool generic_crc32(target_s *t, uint32_t *crc, uint32_t base, int len); +#include +#include + +bool generic_crc32(target_s *target, uint32_t *crc, uint32_t base, size_t len); #endif /* INCLUDE_CRC32_H */