FreeCalypso > hg > freecalypso-tools
view loadtools/ltdump.c @ 643:cd031e2501fa
loadtool.help: dump2bin and dump2srec improvements
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 01 Mar 2020 21:30:49 +0000 |
parents | b4070292640a |
children | 141372e0d28f |
line wrap: on
line source
/* * This module implements the dump2bin and dump2srec functionality * of fc-loadtool. */ #include <sys/types.h> #include <sys/time.h> #include <sys/errno.h> #include <stdio.h> #include <stdint.h> #include <string.h> #include <strings.h> #include <stdlib.h> #include <time.h> extern int errno; extern int target_fd; extern uint32_t crc32_table[]; static char dumpsrec_s0_line[] = "S007000044554D50C2\n"; static char dumpsrec_s7_line[] = "S70500000000FA\n"; collect_binblock_from_target(buf, expect_len, timeout) u_char *buf; unsigned expect_len; { fd_set fds; struct timeval tv; unsigned rcvd; int cc; for (rcvd = 0; rcvd < expect_len; ) { FD_ZERO(&fds); FD_SET(target_fd, &fds); tv.tv_sec = timeout; tv.tv_usec = 0; cc = select(target_fd+1, &fds, NULL, NULL, &tv); if (cc < 0) { if (errno == EINTR) continue; perror("select"); return(-1); } if (cc < 1) { fprintf(stderr, "error: timeout waiting for binary block\n"); return(-1); } cc = read(target_fd, buf + rcvd, expect_len - rcvd); if (cc <= 0) { perror("read after successful select"); return(-1); } rcvd += cc; } return(0); } write_block_in_srec(buf, addr, blklen, outfile) u_char *buf; uint32_t addr; unsigned blklen; FILE *outfile; { unsigned remain, reclen, n; u_char binrec[38], accum; for (remain = blklen; remain; remain -= reclen) { reclen = 32; if (remain < reclen) reclen = remain; binrec[0] = reclen + 5; binrec[1] = addr >> 24; binrec[2] = addr >> 16; binrec[3] = addr >> 8; binrec[4] = addr; bcopy(buf, binrec + 5, reclen); accum = 0; for (n = 0; n < reclen + 5; n++) accum += binrec[n]; binrec[n] = ~accum; putc('S', outfile); putc('3', outfile); for (n = 0; n < reclen + 6; n++) fprintf(outfile, "%02X", binrec[n]); putc('\n', outfile); buf += reclen; addr += reclen; } } 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; FILE *dump_outfile; uint32_t dump_nextaddr, dump_crcaccum; uint32_t dump_total_len, dump_progress_len, dump_remain; unsigned blklen, n; char *target_argv[4], target_arg1[10], target_arg2[10]; u_char recvbuf[8192], expect_blkhdr[8]; time_t dump_initial_time, dump_last_time, curtime; unsigned duration, mm, ss; int rc; printf("Requesting initial CRC-32 of the area from target...\n"); rc = crc32_on_target(start_addr, area_len, &target_crc_init); if (rc) return(rc); printf("got %08lX\n", target_crc_init); dump_outfile = fopen(filename, "w"); if (!dump_outfile) { perror(filename); return(-1); } dump_nextaddr = start_addr; dump_crcaccum = 0xFFFFFFFF; dump_total_len = area_len; dump_progress_len = 0; printf("Requesting memory dump...\n"); time(&dump_initial_time); sprintf(target_arg1, "%lx", start_addr); sprintf(target_arg2, "%lx", area_len); target_argv[0] = "BINDUMP"; target_argv[1] = target_arg1; target_argv[2] = target_arg2; target_argv[3] = 0; tpinterf_make_cmd(target_argv); rc = tpinterf_send_cmd(); if (rc < 0) { fclose(dump_outfile); return(rc); } expect_blkhdr[0] = 0x55; expect_blkhdr[1] = 0xAA; for (dump_remain = dump_total_len; dump_remain; dump_remain -= blklen) { blklen = 8192; if (dump_remain < blklen) blklen = dump_remain; rc = collect_binblock_from_target(recvbuf, 8, 2); if (rc < 0) { fclose(dump_outfile); return(rc); } expect_blkhdr[2] = dump_nextaddr >> 24; expect_blkhdr[3] = dump_nextaddr >> 16; expect_blkhdr[4] = dump_nextaddr >> 8; expect_blkhdr[5] = dump_nextaddr; expect_blkhdr[6] = blklen >> 8; expect_blkhdr[7] = blklen; if (bcmp(recvbuf, expect_blkhdr, 8)) { fprintf(stderr, "error: expected block header mismatch\n"); fclose(dump_outfile); return(rc); } rc = collect_binblock_from_target(recvbuf, blklen, 2); if (rc < 0) { fclose(dump_outfile); return(rc); } /* save the bits */ if (fmt_srec) { if (!dump_progress_len) fputs(dumpsrec_s0_line, dump_outfile); write_block_in_srec(recvbuf, dump_nextaddr, blklen, dump_outfile); } else fwrite(recvbuf, 1, blklen, dump_outfile); /* update running CRC */ for (n = 0; n < blklen; n++) dump_crcaccum = crc32_table[dump_crcaccum & 0xFF ^ recvbuf[n]] ^ (dump_crcaccum >> 8); /* progress indication */ dump_progress_len += blklen; n = dump_progress_len * 100 / dump_total_len; time(&curtime); if (curtime != dump_last_time || n == 100) { printf("\rRx %lu out of %lu bytes (%u%%)", (u_long) dump_progress_len, (u_long) dump_total_len, n); fflush(stdout); } dump_nextaddr += blklen; dump_last_time = curtime; } 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); /* collect '=' at the end */ rc = collect_binblock_from_target(recvbuf, 1, 1); if (rc < 0) return(rc); time(&dump_last_time); if (recvbuf[0] != '=') { fprintf(stderr, "error: \'=\' not received at the end\n"); return(-1); } duration = dump_last_time - dump_initial_time; mm = duration / 60; ss = duration - mm * 60; printf("Dump stream received in %um%us\n", mm, ss); printf("Requesting another CRC-32 of the area from target...\n"); rc = crc32_on_target(start_addr, area_len, &target_crc_fin); if (rc) return(rc); 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); }