%D%/configuration.c \
%D%/log.c \
%D%/command.c \
+ %D%/crc32.c \
%D%/time_support.c \
%D%/replacements.c \
%D%/fileio.c \
%D%/types.h \
%D%/log.h \
%D%/command.h \
+ %D%/crc32.h \
%D%/time_support.h \
%D%/replacements.h \
%D%/fileio.h \
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/***************************************************************************
+ * Copyright (C) 2013-2014 by Franck Jullien *
+ * elec4fun@gmail.com *
+ * *
+ * Copyright (C) 2022 Otto-von-Guericke-Universität Magdeburg *
+ * marian.buschsieweke@ovgu.de *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "crc32.h"
+#include <stdint.h>
+#include <stddef.h>
+
+static uint32_t crc_le_step(uint32_t poly, uint32_t crc, uint32_t data_in,
+ unsigned int data_bits)
+{
+ for (unsigned int i = 0; i < data_bits; i++) {
+ uint32_t d, c;
+ d = ((data_in >> i) & 0x1) ? 0xffffffff : 0;
+ c = (crc & 0x1) ? 0xffffffff : 0;
+ crc = crc >> 1;
+ crc = crc ^ ((d ^ c) & poly);
+ }
+
+ return crc;
+}
+
+uint32_t crc32_le(uint32_t poly, uint32_t seed, const void *_data,
+ size_t data_len)
+{
+ if (((uintptr_t)_data & 0x3) || (data_len & 0x3)) {
+ /* data is unaligned, processing data one byte at a time */
+ const uint8_t *data = _data;
+ for (size_t i = 0; i < data_len; i++)
+ seed = crc_le_step(poly, seed, data[i], 8);
+ } else {
+ /* data is aligned, processing 32 bit at a time */
+ data_len >>= 2;
+ const uint32_t *data = _data;
+ for (size_t i = 0; i < data_len; i++)
+ seed = crc_le_step(poly, seed, data[i], 32);
+ }
+
+ return seed;
+}
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/***************************************************************************
+ * Copyright (C) 2022 Otto-von-Guericke-Universität Magdeburg *
+ * marian.buschsieweke@ovgu.de *
+ ***************************************************************************/
+
+#ifndef OPENOCD_HELPER_CRC32_H
+#define OPENOCD_HELPER_CRC32_H
+
+#include <stdint.h>
+#include <stddef.h>
+
+/** @file
+ * A generic CRC32 implementation
+ */
+
+/**
+ * CRC32 polynomial commonly used for little endian CRC32
+ */
+#define CRC32_POLY_LE 0xedb88320
+
+/**
+ * Calculate the CRC32 value of the given data
+ * @param poly The polynomial of the CRC
+ * @param seed The seed to use (mostly either `0` or `0xffffffff`)
+ * @param data The data to calculate the CRC32 of
+ * @param data_len The length of the data in @p data in bytes
+ * @return The CRC value of the first @p data_len bytes at @p data
+ * @note This function can be used to incrementally compute the CRC one
+ * chunk of data at a time by using the CRC32 of the previous chunk
+ * as @p seed for the next chunk.
+ */
+uint32_t crc32_le(uint32_t poly, uint32_t seed, const void *data,
+ size_t data_len);
+
+#endif /* OPENOCD_HELPER_CRC32_H */
#include "or1k_du.h"
#include "jsp_server.h"
-#include <target/target.h>
+#include <helper/crc32.h>
#include <jtag/jtag.h>
+#include <target/target.h>
#define JSP_BANNER "\n\r" \
"******************************\n\r" \
#define DBG_CPU_CR_STALL 0x01
#define DBG_CPU_CR_RESET 0x02
-/* Polynomial for the CRC calculation
- * Yes, it's backwards. Yes, this is on purpose.
- * The hardware is designed this way to save on logic and routing,
- * and it's really all the same to us here.
- */
-#define ADBG_CRC_POLY 0xedb88320
-
/* These are for the internal registers in the Wishbone module
* The first is the length of the index register,
* the indexes of the various registers are defined after that.
static const char * const chain_name[] = {"WISHBONE", "CPU0", "CPU1", "JSP"};
-static uint32_t adbg_compute_crc(uint32_t crc, uint32_t data_in,
- int length_bits)
-{
- for (int i = 0; i < length_bits; i++) {
- uint32_t d, c;
- d = ((data_in >> i) & 0x1) ? 0xffffffff : 0;
- c = (crc & 0x1) ? 0xffffffff : 0;
- crc = crc >> 1;
- crc = crc ^ ((d ^ c) & ADBG_CRC_POLY);
- }
-
- return crc;
-}
-
static int find_status_bit(void *_buf, int len)
{
int i = 0;
memcpy(data, in_buffer, total_size_bytes);
memcpy(&crc_read, &in_buffer[total_size_bytes], 4);
- uint32_t crc_calc = 0xffffffff;
- for (int i = 0; i < total_size_bytes; i++)
- crc_calc = adbg_compute_crc(crc_calc, data[i], 8);
+ uint32_t crc_calc = crc32_le(CRC32_POLY_LE, 0xffffffff, data,
+ total_size_bytes);
if (crc_calc != crc_read) {
LOG_WARNING("CRC ERROR! Computed 0x%08" PRIx32 ", read CRC 0x%08" PRIx32, crc_calc, crc_read);
field[0].out_value = &value;
field[0].in_value = NULL;
- uint32_t crc_calc = 0xffffffff;
- for (int i = 0; i < (count * size); i++)
- crc_calc = adbg_compute_crc(crc_calc, data[i], 8);
+ uint32_t crc_calc = crc32_le(CRC32_POLY_LE, 0xffffffff, data,
+ count * size);
field[1].num_bits = count * size * 8;
field[1].out_value = data;