FreeCalypso > hg > freecalypso-tools
comparison 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 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:e7502631a0f9 |
---|---|
1 /* | |
2 * This module implements the dump2bin and dump2srec functionality | |
3 * of fc-loadtool. | |
4 */ | |
5 | |
6 #include <sys/types.h> | |
7 #include <stdio.h> | |
8 #include <stdint.h> | |
9 #include <string.h> | |
10 #include <strings.h> | |
11 #include <stdlib.h> | |
12 #include <time.h> | |
13 | |
14 extern uint32_t crc32_table[]; | |
15 extern char target_response_line[]; | |
16 | |
17 crc32_on_target(area_base, area_len, retptr) | |
18 u_long area_base, area_len, *retptr; | |
19 { | |
20 char arg1[10], arg2[10], *argv[4]; | |
21 int stat; | |
22 char *strtoul_endp; | |
23 | |
24 sprintf(arg1, "%lx", area_base); | |
25 sprintf(arg2, "%lx", area_len); | |
26 argv[0] = "crc32"; | |
27 argv[1] = arg1; | |
28 argv[2] = arg2; | |
29 argv[3] = 0; | |
30 tpinterf_make_cmd(argv); | |
31 if (tpinterf_send_cmd() < 0) | |
32 return(-1); | |
33 stat = tpinterf_capture_output_oneline(10); /* 10 s timeout */ | |
34 if (stat != 1) { | |
35 errout: fprintf(stderr, "error: malformed response to crc32 command\n"); | |
36 return(-1); | |
37 } | |
38 if (strlen(target_response_line) != 8) | |
39 goto errout; | |
40 *retptr = strtoul(target_response_line, &strtoul_endp, 16); | |
41 if (strtoul_endp != target_response_line + 8) | |
42 goto errout; | |
43 return(0); | |
44 } | |
45 | |
46 cmd_crc32(argc, argv) | |
47 char **argv; | |
48 { | |
49 u_long area_base, area_len; | |
50 char *strtoul_endp; | |
51 u_long crc_result; | |
52 int stat; | |
53 | |
54 area_base = strtoul(argv[1], &strtoul_endp, 16); | |
55 if (*strtoul_endp) { | |
56 inv: fprintf(stderr, "usage: crc32 hex-start hex-len\n"); | |
57 return(-1); | |
58 } | |
59 area_len = strtoul(argv[2], &strtoul_endp, 16); | |
60 if (*strtoul_endp) | |
61 goto inv; | |
62 stat = crc32_on_target(area_base, area_len, &crc_result); | |
63 if (stat == 0) | |
64 printf("%08lX\n", crc_result); | |
65 return(stat); | |
66 } | |
67 | |
68 /* the actual dump facility */ | |
69 | |
70 static FILE *dump_outfile; | |
71 static int dump_save_srec; | |
72 static uint32_t dump_nextaddr, dump_crcaccum; | |
73 static uint32_t dump_total_len, dump_progress_len; | |
74 static u_char dump_binrec[0x86]; | |
75 static time_t dump_last_time; | |
76 | |
77 static char dumpsrec_s0_line[] = "S007000044554D50C2\n"; | |
78 static char dumpsrec_s7_line[] = "S70500000000FA\n"; | |
79 | |
80 static | |
81 dump_receiver(line) | |
82 char *line; | |
83 { | |
84 int i, b; | |
85 u_char sr_cksum; | |
86 uint32_t addr_from_srec; | |
87 time_t curtime; | |
88 | |
89 if (strncmp(line, "S385", 4)) { | |
90 fprintf(stderr, | |
91 "error: target response is not the expected S385...\n"); | |
92 return(-1); | |
93 } | |
94 for (i = 0; i < 0x86; i++) { | |
95 b = decode_hex_byte(line + i*2 + 2); | |
96 if (b < 0) { | |
97 fprintf(stderr, | |
98 "data from target: S-record hex decode error\n"); | |
99 return(-1); | |
100 } | |
101 dump_binrec[i] = b; | |
102 } | |
103 sr_cksum = 0; | |
104 for (i = 0; i < 0x86; i++) | |
105 sr_cksum += dump_binrec[i]; | |
106 if (sr_cksum != 0xFF) { | |
107 fprintf(stderr, "data from target: bad S-record checksum\n"); | |
108 return(-1); | |
109 } | |
110 /* basic S-record format OK; now verify the address */ | |
111 addr_from_srec = ((uint32_t) dump_binrec[1] << 24) | | |
112 ((uint32_t) dump_binrec[2] << 16) | | |
113 ((uint32_t) dump_binrec[3] << 8) | | |
114 (uint32_t) dump_binrec[4]; | |
115 if (addr_from_srec != dump_nextaddr) { | |
116 fprintf(stderr, | |
117 "error: S3 record from target has the wrong address\n"); | |
118 return(-1); | |
119 } | |
120 /* all checks passed - save it */ | |
121 if (dump_save_srec) { | |
122 if (!dump_progress_len) | |
123 fputs(dumpsrec_s0_line, dump_outfile); | |
124 fprintf(dump_outfile, "%s\n", line); | |
125 } else | |
126 fwrite(dump_binrec + 5, 1, 0x80, dump_outfile); | |
127 /* update running CRC */ | |
128 for (i = 0; i < 0x80; i++) | |
129 dump_crcaccum = crc32_table[dump_crcaccum & 0xFF ^ | |
130 dump_binrec[i+5]] ^ | |
131 (dump_crcaccum >> 8); | |
132 /* progress indication */ | |
133 dump_progress_len += 0x80; | |
134 i = dump_progress_len * 100 / dump_total_len; | |
135 time(&curtime); | |
136 if (curtime != dump_last_time || i == 100) { | |
137 printf("\rRx %lu out of %lu bytes (%i%%)", | |
138 (u_long) dump_progress_len, (u_long) dump_total_len, i); | |
139 fflush(stdout); | |
140 } | |
141 dump_nextaddr += 0x80; | |
142 dump_last_time = curtime; | |
143 return(1); | |
144 } | |
145 | |
146 loadtool_memdump(start_addr, area_len, filename, fmt_srec) | |
147 u_long start_addr, area_len; | |
148 char *filename; | |
149 { | |
150 u_long target_crc_init, target_crc_fin; | |
151 char *target_argv[4], target_arg1[10], target_arg2[10]; | |
152 int stat; | |
153 | |
154 if (start_addr & 0x7F || area_len & 0x7F) { | |
155 fprintf(stderr, | |
156 "error: implementation limit: 128-byte alignment required\n"); | |
157 return(-1); | |
158 } | |
159 printf("Requesting initial CRC-32 of the area from target...\n"); | |
160 stat = crc32_on_target(start_addr, area_len, &target_crc_init); | |
161 if (stat) | |
162 return(stat); | |
163 printf("got %08lX\n", target_crc_init); | |
164 dump_outfile = fopen(filename, "w"); | |
165 if (!dump_outfile) { | |
166 perror(filename); | |
167 return(-1); | |
168 } | |
169 dump_save_srec = fmt_srec; | |
170 dump_nextaddr = start_addr; | |
171 dump_crcaccum = 0xFFFFFFFF; | |
172 dump_total_len = area_len; | |
173 dump_progress_len = 0; | |
174 | |
175 printf("Requesting memory dump...\n"); | |
176 sprintf(target_arg1, "%lx", start_addr); | |
177 sprintf(target_arg2, "%lx", area_len); | |
178 target_argv[0] = "DUMP"; | |
179 target_argv[1] = target_arg1; | |
180 target_argv[2] = target_arg2; | |
181 target_argv[3] = 0; | |
182 tpinterf_make_cmd(target_argv); | |
183 stat = tpinterf_send_cmd(); | |
184 if (stat < 0) { | |
185 fclose(dump_outfile); | |
186 return(stat); | |
187 } | |
188 stat = tpinterf_capture_output(2, dump_receiver); | |
189 if (stat < 0) { | |
190 fclose(dump_outfile); | |
191 return(stat); | |
192 } | |
193 putchar('\n'); /* after last progress line */ | |
194 | |
195 /* sanity checks */ | |
196 if (dump_nextaddr != start_addr + area_len) { | |
197 fclose(dump_outfile); | |
198 fprintf(stderr, | |
199 "error: received dump length does not match expected\n"); | |
200 return(-1); | |
201 } | |
202 if (dump_crcaccum != (uint32_t) target_crc_init) { | |
203 fclose(dump_outfile); | |
204 fprintf(stderr, "error: CRC mismatch (computed %lX)\n", | |
205 (u_long) dump_crcaccum); | |
206 return(-1); | |
207 } | |
208 if (fmt_srec) | |
209 fputs(dumpsrec_s7_line, dump_outfile); | |
210 fclose(dump_outfile); | |
211 printf("Requesting another CRC-32 of the area from target...\n"); | |
212 stat = crc32_on_target(start_addr, area_len, &target_crc_fin); | |
213 if (stat) | |
214 return(stat); | |
215 if (target_crc_fin == target_crc_init) { | |
216 printf("match, dump successful\n"); | |
217 return(0); | |
218 } else { | |
219 fprintf(stderr, "mismatch: got %lX this time\n", | |
220 target_crc_fin); | |
221 return(-1); | |
222 } | |
223 } | |
224 | |
225 cmd_dump2bin(argc, argv) | |
226 char **argv; | |
227 { | |
228 u_long area_base, area_len; | |
229 char *strtoul_endp; | |
230 | |
231 area_base = strtoul(argv[1], &strtoul_endp, 16); | |
232 if (*strtoul_endp) { | |
233 inv: fprintf(stderr, "usage: dump2bin hex-start hex-len outfile\n"); | |
234 return(-1); | |
235 } | |
236 area_len = strtoul(argv[2], &strtoul_endp, 16); | |
237 if (*strtoul_endp) | |
238 goto inv; | |
239 return loadtool_memdump(area_base, area_len, argv[3], 0); | |
240 } | |
241 | |
242 cmd_dump2srec(argc, argv) | |
243 char **argv; | |
244 { | |
245 u_long area_base, area_len; | |
246 char *strtoul_endp; | |
247 | |
248 area_base = strtoul(argv[1], &strtoul_endp, 16); | |
249 if (*strtoul_endp) { | |
250 inv: fprintf(stderr, "usage: dump2srec hex-start hex-len outfile\n"); | |
251 return(-1); | |
252 } | |
253 area_len = strtoul(argv[2], &strtoul_endp, 16); | |
254 if (*strtoul_endp) | |
255 goto inv; | |
256 return loadtool_memdump(area_base, area_len, argv[3], 1); | |
257 } |