FreeCalypso > hg > freecalypso-tools
diff loadtools/ltdump.c @ 0:e7502631a0f9
initial import from freecalypso-sw rev 1033:5ab737ac3ad7
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 11 Jun 2016 00:13:35 +0000 |
parents | |
children | 98474043ecdd |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/loadtools/ltdump.c Sat Jun 11 00:13:35 2016 +0000 @@ -0,0 +1,257 @@ +/* + * This module implements the dump2bin and dump2srec functionality + * of fc-loadtool. + */ + +#include <sys/types.h> +#include <stdio.h> +#include <stdint.h> +#include <string.h> +#include <strings.h> +#include <stdlib.h> +#include <time.h> + +extern uint32_t crc32_table[]; +extern char target_response_line[]; + +crc32_on_target(area_base, area_len, retptr) + u_long area_base, area_len, *retptr; +{ + char arg1[10], arg2[10], *argv[4]; + int stat; + char *strtoul_endp; + + sprintf(arg1, "%lx", area_base); + sprintf(arg2, "%lx", area_len); + argv[0] = "crc32"; + argv[1] = arg1; + argv[2] = arg2; + argv[3] = 0; + tpinterf_make_cmd(argv); + if (tpinterf_send_cmd() < 0) + return(-1); + stat = tpinterf_capture_output_oneline(10); /* 10 s timeout */ + if (stat != 1) { +errout: fprintf(stderr, "error: malformed response to crc32 command\n"); + return(-1); + } + if (strlen(target_response_line) != 8) + goto errout; + *retptr = strtoul(target_response_line, &strtoul_endp, 16); + if (strtoul_endp != target_response_line + 8) + goto errout; + return(0); +} + +cmd_crc32(argc, argv) + char **argv; +{ + u_long area_base, area_len; + char *strtoul_endp; + u_long crc_result; + int stat; + + area_base = strtoul(argv[1], &strtoul_endp, 16); + if (*strtoul_endp) { +inv: fprintf(stderr, "usage: crc32 hex-start hex-len\n"); + return(-1); + } + area_len = strtoul(argv[2], &strtoul_endp, 16); + if (*strtoul_endp) + goto inv; + stat = crc32_on_target(area_base, area_len, &crc_result); + if (stat == 0) + printf("%08lX\n", crc_result); + return(stat); +} + +/* the actual dump facility */ + +static FILE *dump_outfile; +static int dump_save_srec; +static uint32_t dump_nextaddr, dump_crcaccum; +static uint32_t dump_total_len, dump_progress_len; +static u_char dump_binrec[0x86]; +static time_t dump_last_time; + +static char dumpsrec_s0_line[] = "S007000044554D50C2\n"; +static char dumpsrec_s7_line[] = "S70500000000FA\n"; + +static +dump_receiver(line) + char *line; +{ + int i, b; + u_char sr_cksum; + uint32_t addr_from_srec; + time_t curtime; + + if (strncmp(line, "S385", 4)) { + fprintf(stderr, + "error: target response is not the expected S385...\n"); + return(-1); + } + for (i = 0; i < 0x86; i++) { + b = decode_hex_byte(line + i*2 + 2); + if (b < 0) { + fprintf(stderr, + "data from target: S-record hex decode error\n"); + return(-1); + } + dump_binrec[i] = b; + } + sr_cksum = 0; + for (i = 0; i < 0x86; i++) + sr_cksum += dump_binrec[i]; + if (sr_cksum != 0xFF) { + fprintf(stderr, "data from target: bad S-record checksum\n"); + return(-1); + } + /* basic S-record format OK; now verify the address */ + addr_from_srec = ((uint32_t) dump_binrec[1] << 24) | + ((uint32_t) dump_binrec[2] << 16) | + ((uint32_t) dump_binrec[3] << 8) | + (uint32_t) dump_binrec[4]; + if (addr_from_srec != dump_nextaddr) { + fprintf(stderr, + "error: S3 record from target has the wrong address\n"); + return(-1); + } + /* all checks passed - save it */ + if (dump_save_srec) { + if (!dump_progress_len) + fputs(dumpsrec_s0_line, dump_outfile); + fprintf(dump_outfile, "%s\n", line); + } else + fwrite(dump_binrec + 5, 1, 0x80, dump_outfile); + /* update running CRC */ + for (i = 0; i < 0x80; i++) + dump_crcaccum = crc32_table[dump_crcaccum & 0xFF ^ + dump_binrec[i+5]] ^ + (dump_crcaccum >> 8); + /* progress indication */ + dump_progress_len += 0x80; + i = dump_progress_len * 100 / dump_total_len; + time(&curtime); + if (curtime != dump_last_time || i == 100) { + printf("\rRx %lu out of %lu bytes (%i%%)", + (u_long) dump_progress_len, (u_long) dump_total_len, i); + fflush(stdout); + } + dump_nextaddr += 0x80; + dump_last_time = curtime; + return(1); +} + +loadtool_memdump(start_addr, area_len, filename, fmt_srec) + u_long start_addr, area_len; + char *filename; +{ + u_long target_crc_init, target_crc_fin; + char *target_argv[4], target_arg1[10], target_arg2[10]; + int stat; + + if (start_addr & 0x7F || area_len & 0x7F) { + fprintf(stderr, + "error: implementation limit: 128-byte alignment required\n"); + return(-1); + } + printf("Requesting initial CRC-32 of the area from target...\n"); + stat = crc32_on_target(start_addr, area_len, &target_crc_init); + if (stat) + return(stat); + printf("got %08lX\n", target_crc_init); + dump_outfile = fopen(filename, "w"); + if (!dump_outfile) { + perror(filename); + return(-1); + } + dump_save_srec = fmt_srec; + dump_nextaddr = start_addr; + dump_crcaccum = 0xFFFFFFFF; + dump_total_len = area_len; + dump_progress_len = 0; + + printf("Requesting memory dump...\n"); + sprintf(target_arg1, "%lx", start_addr); + sprintf(target_arg2, "%lx", area_len); + target_argv[0] = "DUMP"; + target_argv[1] = target_arg1; + target_argv[2] = target_arg2; + target_argv[3] = 0; + tpinterf_make_cmd(target_argv); + stat = tpinterf_send_cmd(); + if (stat < 0) { + fclose(dump_outfile); + return(stat); + } + stat = tpinterf_capture_output(2, dump_receiver); + if (stat < 0) { + fclose(dump_outfile); + return(stat); + } + putchar('\n'); /* after last progress line */ + + /* sanity checks */ + if (dump_nextaddr != start_addr + area_len) { + fclose(dump_outfile); + fprintf(stderr, + "error: received dump length does not match expected\n"); + return(-1); + } + if (dump_crcaccum != (uint32_t) target_crc_init) { + fclose(dump_outfile); + fprintf(stderr, "error: CRC mismatch (computed %lX)\n", + (u_long) dump_crcaccum); + return(-1); + } + if (fmt_srec) + fputs(dumpsrec_s7_line, dump_outfile); + fclose(dump_outfile); + printf("Requesting another CRC-32 of the area from target...\n"); + stat = crc32_on_target(start_addr, area_len, &target_crc_fin); + if (stat) + return(stat); + if (target_crc_fin == target_crc_init) { + printf("match, dump successful\n"); + return(0); + } else { + fprintf(stderr, "mismatch: got %lX this time\n", + target_crc_fin); + return(-1); + } +} + +cmd_dump2bin(argc, argv) + char **argv; +{ + u_long area_base, area_len; + char *strtoul_endp; + + area_base = strtoul(argv[1], &strtoul_endp, 16); + if (*strtoul_endp) { +inv: fprintf(stderr, "usage: dump2bin hex-start hex-len outfile\n"); + return(-1); + } + area_len = strtoul(argv[2], &strtoul_endp, 16); + if (*strtoul_endp) + goto inv; + return loadtool_memdump(area_base, area_len, argv[3], 0); +} + +cmd_dump2srec(argc, argv) + char **argv; +{ + u_long area_base, area_len; + char *strtoul_endp; + + area_base = strtoul(argv[1], &strtoul_endp, 16); + if (*strtoul_endp) { +inv: fprintf(stderr, "usage: dump2srec hex-start hex-len outfile\n"); + return(-1); + } + area_len = strtoul(argv[2], &strtoul_endp, 16); + if (*strtoul_endp) + goto inv; + return loadtool_memdump(area_base, area_len, argv[3], 1); +}