FreeCalypso > hg > freecalypso-tools
comparison 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 |
comparison
equal
deleted
inserted
replaced
| 640:5385aca4d813 | 641:b4070292640a |
|---|---|
| 2 * This module implements the dump2bin and dump2srec functionality | 2 * This module implements the dump2bin and dump2srec functionality |
| 3 * of fc-loadtool. | 3 * of fc-loadtool. |
| 4 */ | 4 */ |
| 5 | 5 |
| 6 #include <sys/types.h> | 6 #include <sys/types.h> |
| 7 #include <sys/time.h> | |
| 8 #include <sys/errno.h> | |
| 7 #include <stdio.h> | 9 #include <stdio.h> |
| 8 #include <stdint.h> | 10 #include <stdint.h> |
| 9 #include <string.h> | 11 #include <string.h> |
| 10 #include <strings.h> | 12 #include <strings.h> |
| 11 #include <stdlib.h> | 13 #include <stdlib.h> |
| 12 #include <time.h> | 14 #include <time.h> |
| 13 | 15 |
| 16 extern int errno; | |
| 17 | |
| 18 extern int target_fd; | |
| 14 extern uint32_t crc32_table[]; | 19 extern uint32_t crc32_table[]; |
| 15 | |
| 16 static FILE *dump_outfile; | |
| 17 static int dump_save_srec; | |
| 18 static uint32_t dump_nextaddr, dump_crcaccum; | |
| 19 static uint32_t dump_total_len, dump_progress_len; | |
| 20 static u_char dump_binrec[0x86]; | |
| 21 static time_t dump_initial_time, dump_last_time; | |
| 22 | 20 |
| 23 static char dumpsrec_s0_line[] = "S007000044554D50C2\n"; | 21 static char dumpsrec_s0_line[] = "S007000044554D50C2\n"; |
| 24 static char dumpsrec_s7_line[] = "S70500000000FA\n"; | 22 static char dumpsrec_s7_line[] = "S70500000000FA\n"; |
| 25 | 23 |
| 26 static | 24 collect_binblock_from_target(buf, expect_len, timeout) |
| 27 dump_receiver(line) | 25 u_char *buf; |
| 28 char *line; | 26 unsigned expect_len; |
| 29 { | 27 { |
| 30 int i, b; | 28 fd_set fds; |
| 31 u_char sr_cksum; | 29 struct timeval tv; |
| 32 uint32_t addr_from_srec; | 30 unsigned rcvd; |
| 33 time_t curtime; | 31 int cc; |
| 34 | 32 |
| 35 if (strncmp(line, "S385", 4)) { | 33 for (rcvd = 0; rcvd < expect_len; ) { |
| 36 fprintf(stderr, | 34 FD_ZERO(&fds); |
| 37 "error: target response is not the expected S385...\n"); | 35 FD_SET(target_fd, &fds); |
| 38 return(-1); | 36 tv.tv_sec = timeout; |
| 39 } | 37 tv.tv_usec = 0; |
| 40 for (i = 0; i < 0x86; i++) { | 38 cc = select(target_fd+1, &fds, NULL, NULL, &tv); |
| 41 b = decode_hex_byte(line + i*2 + 2); | 39 if (cc < 0) { |
| 42 if (b < 0) { | 40 if (errno == EINTR) |
| 41 continue; | |
| 42 perror("select"); | |
| 43 return(-1); | |
| 44 } | |
| 45 if (cc < 1) { | |
| 43 fprintf(stderr, | 46 fprintf(stderr, |
| 44 "data from target: S-record hex decode error\n"); | 47 "error: timeout waiting for binary block\n"); |
| 45 return(-1); | 48 return(-1); |
| 46 } | 49 } |
| 47 dump_binrec[i] = b; | 50 cc = read(target_fd, buf + rcvd, expect_len - rcvd); |
| 48 } | 51 if (cc <= 0) { |
| 49 sr_cksum = 0; | 52 perror("read after successful select"); |
| 50 for (i = 0; i < 0x86; i++) | 53 return(-1); |
| 51 sr_cksum += dump_binrec[i]; | 54 } |
| 52 if (sr_cksum != 0xFF) { | 55 rcvd += cc; |
| 53 fprintf(stderr, "data from target: bad S-record checksum\n"); | 56 } |
| 54 return(-1); | 57 return(0); |
| 55 } | 58 } |
| 56 /* basic S-record format OK; now verify the address */ | 59 |
| 57 addr_from_srec = ((uint32_t) dump_binrec[1] << 24) | | 60 write_block_in_srec(buf, addr, blklen, outfile) |
| 58 ((uint32_t) dump_binrec[2] << 16) | | 61 u_char *buf; |
| 59 ((uint32_t) dump_binrec[3] << 8) | | 62 uint32_t addr; |
| 60 (uint32_t) dump_binrec[4]; | 63 unsigned blklen; |
| 61 if (addr_from_srec != dump_nextaddr) { | 64 FILE *outfile; |
| 62 fprintf(stderr, | 65 { |
| 63 "error: S3 record from target has the wrong address\n"); | 66 unsigned remain, reclen, n; |
| 64 return(-1); | 67 u_char binrec[38], accum; |
| 65 } | 68 |
| 66 /* all checks passed - save it */ | 69 for (remain = blklen; remain; remain -= reclen) { |
| 67 if (dump_save_srec) { | 70 reclen = 32; |
| 68 if (!dump_progress_len) | 71 if (remain < reclen) |
| 69 fputs(dumpsrec_s0_line, dump_outfile); | 72 reclen = remain; |
| 70 fprintf(dump_outfile, "%s\n", line); | 73 binrec[0] = reclen + 5; |
| 71 } else | 74 binrec[1] = addr >> 24; |
| 72 fwrite(dump_binrec + 5, 1, 0x80, dump_outfile); | 75 binrec[2] = addr >> 16; |
| 73 /* update running CRC */ | 76 binrec[3] = addr >> 8; |
| 74 for (i = 0; i < 0x80; i++) | 77 binrec[4] = addr; |
| 75 dump_crcaccum = crc32_table[dump_crcaccum & 0xFF ^ | 78 bcopy(buf, binrec + 5, reclen); |
| 76 dump_binrec[i+5]] ^ | 79 accum = 0; |
| 77 (dump_crcaccum >> 8); | 80 for (n = 0; n < reclen + 5; n++) |
| 78 /* progress indication */ | 81 accum += binrec[n]; |
| 79 dump_progress_len += 0x80; | 82 binrec[n] = ~accum; |
| 80 i = dump_progress_len * 100 / dump_total_len; | 83 putc('S', outfile); |
| 81 time(&curtime); | 84 putc('3', outfile); |
| 82 if (curtime != dump_last_time || i == 100) { | 85 for (n = 0; n < reclen + 6; n++) |
| 83 printf("\rRx %lu out of %lu bytes (%i%%)", | 86 fprintf(outfile, "%02X", binrec[n]); |
| 84 (u_long) dump_progress_len, (u_long) dump_total_len, i); | 87 putc('\n', outfile); |
| 85 fflush(stdout); | 88 buf += reclen; |
| 86 } | 89 addr += reclen; |
| 87 dump_nextaddr += 0x80; | 90 } |
| 88 dump_last_time = curtime; | |
| 89 return(1); | |
| 90 } | 91 } |
| 91 | 92 |
| 92 loadtool_memdump(start_addr, area_len, filename, fmt_srec) | 93 loadtool_memdump(start_addr, area_len, filename, fmt_srec) |
| 93 u_long start_addr, area_len; | 94 u_long start_addr, area_len; |
| 94 char *filename; | 95 char *filename; |
| 95 { | 96 { |
| 96 u_long target_crc_init, target_crc_fin; | 97 u_long target_crc_init, target_crc_fin; |
| 98 FILE *dump_outfile; | |
| 99 uint32_t dump_nextaddr, dump_crcaccum; | |
| 100 uint32_t dump_total_len, dump_progress_len, dump_remain; | |
| 101 unsigned blklen, n; | |
| 97 char *target_argv[4], target_arg1[10], target_arg2[10]; | 102 char *target_argv[4], target_arg1[10], target_arg2[10]; |
| 103 u_char recvbuf[8192], expect_blkhdr[8]; | |
| 104 time_t dump_initial_time, dump_last_time, curtime; | |
| 98 unsigned duration, mm, ss; | 105 unsigned duration, mm, ss; |
| 99 int stat; | 106 int rc; |
| 100 | 107 |
| 101 if (!area_len) { | |
| 102 fprintf(stderr, | |
| 103 "error: dump of zero length is not supported\n"); | |
| 104 return(-1); | |
| 105 } | |
| 106 if (start_addr & 0x7F || area_len & 0x7F) { | |
| 107 fprintf(stderr, | |
| 108 "error: implementation limit: 128-byte alignment required\n"); | |
| 109 return(-1); | |
| 110 } | |
| 111 printf("Requesting initial CRC-32 of the area from target...\n"); | 108 printf("Requesting initial CRC-32 of the area from target...\n"); |
| 112 stat = crc32_on_target(start_addr, area_len, &target_crc_init); | 109 rc = crc32_on_target(start_addr, area_len, &target_crc_init); |
| 113 if (stat) | 110 if (rc) |
| 114 return(stat); | 111 return(rc); |
| 115 printf("got %08lX\n", target_crc_init); | 112 printf("got %08lX\n", target_crc_init); |
| 116 dump_outfile = fopen(filename, "w"); | 113 dump_outfile = fopen(filename, "w"); |
| 117 if (!dump_outfile) { | 114 if (!dump_outfile) { |
| 118 perror(filename); | 115 perror(filename); |
| 119 return(-1); | 116 return(-1); |
| 120 } | 117 } |
| 121 dump_save_srec = fmt_srec; | |
| 122 dump_nextaddr = start_addr; | 118 dump_nextaddr = start_addr; |
| 123 dump_crcaccum = 0xFFFFFFFF; | 119 dump_crcaccum = 0xFFFFFFFF; |
| 124 dump_total_len = area_len; | 120 dump_total_len = area_len; |
| 125 dump_progress_len = 0; | 121 dump_progress_len = 0; |
| 126 | 122 |
| 127 printf("Requesting memory dump...\n"); | 123 printf("Requesting memory dump...\n"); |
| 128 time(&dump_initial_time); | 124 time(&dump_initial_time); |
| 129 sprintf(target_arg1, "%lx", start_addr); | 125 sprintf(target_arg1, "%lx", start_addr); |
| 130 sprintf(target_arg2, "%lx", area_len); | 126 sprintf(target_arg2, "%lx", area_len); |
| 131 target_argv[0] = "DUMP"; | 127 target_argv[0] = "BINDUMP"; |
| 132 target_argv[1] = target_arg1; | 128 target_argv[1] = target_arg1; |
| 133 target_argv[2] = target_arg2; | 129 target_argv[2] = target_arg2; |
| 134 target_argv[3] = 0; | 130 target_argv[3] = 0; |
| 135 tpinterf_make_cmd(target_argv); | 131 tpinterf_make_cmd(target_argv); |
| 136 stat = tpinterf_send_cmd(); | 132 rc = tpinterf_send_cmd(); |
| 137 if (stat < 0) { | 133 if (rc < 0) { |
| 138 fclose(dump_outfile); | 134 fclose(dump_outfile); |
| 139 return(stat); | 135 return(rc); |
| 140 } | 136 } |
| 141 stat = tpinterf_capture_output(2, dump_receiver); | 137 expect_blkhdr[0] = 0x55; |
| 142 if (stat < 0) { | 138 expect_blkhdr[1] = 0xAA; |
| 143 fclose(dump_outfile); | 139 for (dump_remain = dump_total_len; dump_remain; dump_remain -= blklen) { |
| 144 return(stat); | 140 blklen = 8192; |
| 141 if (dump_remain < blklen) | |
| 142 blklen = dump_remain; | |
| 143 rc = collect_binblock_from_target(recvbuf, 8, 2); | |
| 144 if (rc < 0) { | |
| 145 fclose(dump_outfile); | |
| 146 return(rc); | |
| 147 } | |
| 148 expect_blkhdr[2] = dump_nextaddr >> 24; | |
| 149 expect_blkhdr[3] = dump_nextaddr >> 16; | |
| 150 expect_blkhdr[4] = dump_nextaddr >> 8; | |
| 151 expect_blkhdr[5] = dump_nextaddr; | |
| 152 expect_blkhdr[6] = blklen >> 8; | |
| 153 expect_blkhdr[7] = blklen; | |
| 154 if (bcmp(recvbuf, expect_blkhdr, 8)) { | |
| 155 fprintf(stderr, | |
| 156 "error: expected block header mismatch\n"); | |
| 157 fclose(dump_outfile); | |
| 158 return(rc); | |
| 159 } | |
| 160 rc = collect_binblock_from_target(recvbuf, blklen, 2); | |
| 161 if (rc < 0) { | |
| 162 fclose(dump_outfile); | |
| 163 return(rc); | |
| 164 } | |
| 165 /* save the bits */ | |
| 166 if (fmt_srec) { | |
| 167 if (!dump_progress_len) | |
| 168 fputs(dumpsrec_s0_line, dump_outfile); | |
| 169 write_block_in_srec(recvbuf, dump_nextaddr, blklen, | |
| 170 dump_outfile); | |
| 171 } else | |
| 172 fwrite(recvbuf, 1, blklen, dump_outfile); | |
| 173 /* update running CRC */ | |
| 174 for (n = 0; n < blklen; n++) | |
| 175 dump_crcaccum = crc32_table[dump_crcaccum & 0xFF ^ | |
| 176 recvbuf[n]] ^ | |
| 177 (dump_crcaccum >> 8); | |
| 178 /* progress indication */ | |
| 179 dump_progress_len += blklen; | |
| 180 n = dump_progress_len * 100 / dump_total_len; | |
| 181 time(&curtime); | |
| 182 if (curtime != dump_last_time || n == 100) { | |
| 183 printf("\rRx %lu out of %lu bytes (%u%%)", | |
| 184 (u_long) dump_progress_len, | |
| 185 (u_long) dump_total_len, n); | |
| 186 fflush(stdout); | |
| 187 } | |
| 188 dump_nextaddr += blklen; | |
| 189 dump_last_time = curtime; | |
| 145 } | 190 } |
| 146 putchar('\n'); /* after last progress line */ | 191 putchar('\n'); /* after last progress line */ |
| 147 | |
| 148 /* sanity checks */ | 192 /* sanity checks */ |
| 149 if (dump_nextaddr != start_addr + area_len) { | 193 if (dump_nextaddr != start_addr + area_len) { |
| 150 fclose(dump_outfile); | 194 fclose(dump_outfile); |
| 151 fprintf(stderr, | 195 fprintf(stderr, |
| 152 "error: received dump length does not match expected\n"); | 196 "error: received dump length does not match expected\n"); |
| 159 return(-1); | 203 return(-1); |
| 160 } | 204 } |
| 161 if (fmt_srec) | 205 if (fmt_srec) |
| 162 fputs(dumpsrec_s7_line, dump_outfile); | 206 fputs(dumpsrec_s7_line, dump_outfile); |
| 163 fclose(dump_outfile); | 207 fclose(dump_outfile); |
| 208 | |
| 209 /* collect '=' at the end */ | |
| 210 rc = collect_binblock_from_target(recvbuf, 1, 1); | |
| 211 if (rc < 0) | |
| 212 return(rc); | |
| 213 time(&dump_last_time); | |
| 214 if (recvbuf[0] != '=') { | |
| 215 fprintf(stderr, "error: \'=\' not received at the end\n"); | |
| 216 return(-1); | |
| 217 } | |
| 164 duration = dump_last_time - dump_initial_time; | 218 duration = dump_last_time - dump_initial_time; |
| 165 mm = duration / 60; | 219 mm = duration / 60; |
| 166 ss = duration - mm * 60; | 220 ss = duration - mm * 60; |
| 167 printf("Dump stream received in %um%us\n", mm, ss); | 221 printf("Dump stream received in %um%us\n", mm, ss); |
| 168 | 222 |
| 169 printf("Requesting another CRC-32 of the area from target...\n"); | 223 printf("Requesting another CRC-32 of the area from target...\n"); |
| 170 stat = crc32_on_target(start_addr, area_len, &target_crc_fin); | 224 rc = crc32_on_target(start_addr, area_len, &target_crc_fin); |
| 171 if (stat) | 225 if (rc) |
| 172 return(stat); | 226 return(rc); |
| 173 if (target_crc_fin == target_crc_init) { | 227 if (target_crc_fin == target_crc_init) { |
| 174 printf("match, dump successful\n"); | 228 printf("match, dump successful\n"); |
| 175 return(0); | 229 return(0); |
| 176 } else { | 230 } else { |
| 177 fprintf(stderr, "mismatch: got %lX this time\n", | 231 fprintf(stderr, "mismatch: got %lX this time\n", |
