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", |