FreeCalypso > hg > freecalypso-tools
diff loadtools/ltdump.c @ 641:b4070292640a
fc-loadtool: dump facility changed to use BINDUMP
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 01 Mar 2020 20:06:21 +0000 |
parents | 5385aca4d813 |
children | 141372e0d28f |
line wrap: on
line diff
--- a/loadtools/ltdump.c Sun Mar 01 18:54:29 2020 +0000 +++ b/loadtools/ltdump.c Sun Mar 01 20:06:21 2020 +0000 @@ -4,6 +4,8 @@ */ #include <sys/types.h> +#include <sys/time.h> +#include <sys/errno.h> #include <stdio.h> #include <stdint.h> #include <string.h> @@ -11,82 +13,81 @@ #include <stdlib.h> #include <time.h> -extern uint32_t crc32_table[]; +extern int errno; -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_initial_time, dump_last_time; +extern int target_fd; +extern uint32_t crc32_table[]; static char dumpsrec_s0_line[] = "S007000044554D50C2\n"; static char dumpsrec_s7_line[] = "S70500000000FA\n"; -static -dump_receiver(line) - char *line; +collect_binblock_from_target(buf, expect_len, timeout) + u_char *buf; + unsigned expect_len; { - int i, b; - u_char sr_cksum; - uint32_t addr_from_srec; - time_t curtime; + fd_set fds; + struct timeval tv; + unsigned rcvd; + int cc; - 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) { + 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, - "data from target: S-record hex decode error\n"); + "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); } - 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); + rcvd += cc; } - /* 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); + 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; } - dump_nextaddr += 0x80; - dump_last_time = curtime; - return(1); } loadtool_memdump(start_addr, area_len, filename, fmt_srec) @@ -94,31 +95,26 @@ 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 stat; + int rc; - if (!area_len) { - fprintf(stderr, - "error: dump of zero length is not supported\n"); - return(-1); - } - 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); + 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_save_srec = fmt_srec; dump_nextaddr = start_addr; dump_crcaccum = 0xFFFFFFFF; dump_total_len = area_len; @@ -128,23 +124,71 @@ time(&dump_initial_time); sprintf(target_arg1, "%lx", start_addr); sprintf(target_arg2, "%lx", area_len); - target_argv[0] = "DUMP"; + target_argv[0] = "BINDUMP"; 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) { + rc = tpinterf_send_cmd(); + if (rc < 0) { fclose(dump_outfile); - return(stat); + return(rc); } - stat = tpinterf_capture_output(2, dump_receiver); - if (stat < 0) { - fclose(dump_outfile); - return(stat); + 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); @@ -161,15 +205,25 @@ 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"); - stat = crc32_on_target(start_addr, area_len, &target_crc_fin); - if (stat) - return(stat); + 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);