aboutsummaryrefslogtreecommitdiff
path: root/src/target
diff options
context:
space:
mode:
authorTim Newsome <tim@sifive.com>2021-03-03 12:41:03 -0800
committerAntonio Borneo <borneo.antonio@gmail.com>2021-03-19 21:58:17 +0000
commit41147e6fcde9bbbc485e35f6a9270907b2e38513 (patch)
treeeed7873fd7cdd67ebae36eeb447f2aa9ddfb1b32 /src/target
parent6c0151623cb09da6a80655cedf568db927ae2d93 (diff)
downloadriscv-openocd-41147e6fcde9bbbc485e35f6a9270907b2e38513.zip
riscv-openocd-41147e6fcde9bbbc485e35f6a9270907b2e38513.tar.gz
riscv-openocd-41147e6fcde9bbbc485e35f6a9270907b2e38513.tar.bz2
Implement CRC32 algorithm for RISC-V.
Signed-off-by: Tim Newsome <tim@sifive.com> Change-Id: Id437f78e74e3d837ff203f84c4eeb996bfad9a01 Reviewed-on: http://openocd.zylin.com/6076 Reviewed-by: Jan Matyas <matyas@codasip.com> Reviewed-by: Marc Schink <dev@zapb.de> Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com> Tested-by: jenkins
Diffstat (limited to 'src/target')
-rw-r--r--src/target/image.c2
-rw-r--r--src/target/riscv/riscv.c81
2 files changed, 81 insertions, 2 deletions
diff --git a/src/target/image.c b/src/target/image.c
index 20c6d77..e63cd0f 100644
--- a/src/target/image.c
+++ b/src/target/image.c
@@ -1052,7 +1052,7 @@ int image_calculate_checksum(const uint8_t *buffer, uint32_t nbytes, uint32_t *c
keep_alive();
}
- LOG_DEBUG("Calculating checksum done");
+ LOG_DEBUG("Calculating checksum done; checksum=0x%" PRIx32, crc);
*checksum = crc;
return ERROR_OK;
diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c
index c26e635..c883b42 100644
--- a/src/target/riscv/riscv.c
+++ b/src/target/riscv/riscv.c
@@ -1853,7 +1853,86 @@ static int riscv_checksum_memory(struct target *target,
target_addr_t address, uint32_t count,
uint32_t *checksum)
{
- return ERROR_FAIL;
+ struct working_area *crc_algorithm;
+ struct reg_param reg_params[2];
+ int retval;
+
+ LOG_DEBUG("address=0x%" TARGET_PRIxADDR "; count=0x%" PRIx32, address, count);
+
+ static const uint8_t riscv32_crc_code[] = {
+#include "../../contrib/loaders/checksum/riscv32_crc.inc"
+ };
+ static const uint8_t riscv64_crc_code[] = {
+#include "../../contrib/loaders/checksum/riscv64_crc.inc"
+ };
+
+ static const uint8_t *crc_code;
+
+ unsigned xlen = riscv_xlen(target);
+ unsigned crc_code_size;
+ if (xlen == 32) {
+ crc_code = riscv32_crc_code;
+ crc_code_size = sizeof(riscv32_crc_code);
+ } else {
+ crc_code = riscv64_crc_code;
+ crc_code_size = sizeof(riscv64_crc_code);
+ }
+
+ if (count < crc_code_size * 4) {
+ /* Don't use the algorithm for relatively small buffers. It's faster
+ * just to read the memory. target_checksum_memory() will take care of
+ * that if we fail. */
+ return ERROR_FAIL;
+ }
+
+ retval = target_alloc_working_area(target, crc_code_size, &crc_algorithm);
+ if (retval != ERROR_OK)
+ return retval;
+
+ if (crc_algorithm->address + crc_algorithm->size > address &&
+ crc_algorithm->address < address + count) {
+ /* Region to checksum overlaps with the work area we've been assigned.
+ * Bail. (Would be better to manually checksum what we read there, and
+ * use the algorithm for the rest.) */
+ target_free_working_area(target, crc_algorithm);
+ return ERROR_FAIL;
+ }
+
+ retval = target_write_buffer(target, crc_algorithm->address, crc_code_size,
+ crc_code);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Failed to write code to " TARGET_ADDR_FMT ": %d",
+ crc_algorithm->address, retval);
+ target_free_working_area(target, crc_algorithm);
+ return retval;
+ }
+
+ init_reg_param(&reg_params[0], "a0", xlen, PARAM_IN_OUT);
+ init_reg_param(&reg_params[1], "a1", xlen, PARAM_OUT);
+ buf_set_u64(reg_params[0].value, 0, xlen, address);
+ buf_set_u64(reg_params[1].value, 0, xlen, count);
+
+ /* 20 second timeout/megabyte */
+ int timeout = 20000 * (1 + (count / (1024 * 1024)));
+
+ retval = target_run_algorithm(target, 0, NULL, 2, reg_params,
+ crc_algorithm->address,
+ 0, /* Leave exit point unspecified because we don't know. */
+ timeout, NULL);
+
+ if (retval == ERROR_OK)
+ *checksum = buf_get_u32(reg_params[0].value, 0, 32);
+ else
+ LOG_ERROR("error executing RISC-V CRC algorithm");
+
+ destroy_reg_param(&reg_params[0]);
+ destroy_reg_param(&reg_params[1]);
+
+ target_free_working_area(target, crc_algorithm);
+
+ LOG_DEBUG("checksum=0x%" PRIx32 ", result=%d", *checksum, retval);
+
+ return retval;
}
/*** OpenOCD Helper Functions ***/