FreeCalypso > hg > freecalypso-tools
comparison loadtools/flprogsrec.c @ 628:9c5b0629e346
fc-loadtool SREC programming revamp implemented, compiles
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 29 Feb 2020 02:14:30 +0000 |
parents | 97fe41e9242a |
children | 0f70fe9395c4 |
comparison
equal
deleted
inserted
replaced
627:d04502de49ed | 628:9c5b0629e346 |
---|---|
10 #include <time.h> | 10 #include <time.h> |
11 #include "flash.h" | 11 #include "flash.h" |
12 #include "srecreader.h" | 12 #include "srecreader.h" |
13 | 13 |
14 extern struct flash_bank_info flash_bank_info[2]; | 14 extern struct flash_bank_info flash_bank_info[2]; |
15 extern uint32_t crc32_table[]; | |
16 | |
17 #define MAX_SREC_REGIONS 256 | |
18 | |
19 read_srec_img_for_flash(imgfile, is_m0, bank_size, reglistp, regcountp, | |
20 totalp, tmpfilep) | |
21 char *imgfile; | |
22 uint32_t bank_size, *totalp; | |
23 struct discontig_prog *reglistp; | |
24 unsigned *regcountp; | |
25 FILE **tmpfilep; | |
26 { | |
27 struct srecreader srr; | |
28 struct discontig_prog *regp; | |
29 unsigned regcount; | |
30 uint32_t total_len; | |
31 char tmpfilename[] = "/tmp/fc-loadtoolXXXXXX"; | |
32 int rc, tmpfd, i, c; | |
33 FILE *tmpfile; | |
34 | |
35 printf("Reading S-record image from %s\n", imgfile); | |
36 srr.filename = imgfile; | |
37 rc = open_srec_file(&srr); | |
38 if (rc < 0) | |
39 return(rc); | |
40 tmpfd = mkstemp(tmpfilename); | |
41 if (tmpfd < 0) { | |
42 fprintf(stderr, "unable to get temp file via mkstemp()\n"); | |
43 fclose(srr.openfile); | |
44 return(-1); | |
45 } | |
46 unlink(tmpfilename); | |
47 tmpfile = fdopen(tmpfd, "w+"); | |
48 if (!tmpfile) { | |
49 perror("fdopen"); | |
50 close(tmpfd); | |
51 fclose(srr.openfile); | |
52 return(-1); | |
53 } | |
54 regp = reglistp; | |
55 regcount = 0; | |
56 total_len = 0; | |
57 for (;;) { | |
58 if (read_s_record(&srr) < 0) { | |
59 /* error msg already printed */ | |
60 fclose(srr.openfile); | |
61 fclose(tmpfile); | |
62 return(-1); | |
63 } | |
64 if (srr.record_type == '0') { | |
65 if (srr.lineno == 1) | |
66 continue; | |
67 fprintf(stderr, | |
68 "error: S0 record found in line %d of %s (expected in line 1 only)\n", | |
69 srr.lineno, srr.filename); | |
70 fclose(srr.openfile); | |
71 fclose(tmpfile); | |
72 return(-1); | |
73 } else if (srr.record_type == '7') | |
74 break; | |
75 else if (srr.record_type != '3') { | |
76 fprintf(stderr, | |
77 "error: unsupported S%c record type in line %d of %s\n", | |
78 srr.record_type, srr.lineno, srr.filename); | |
79 fclose(srr.openfile); | |
80 fclose(tmpfile); | |
81 return(-1); | |
82 } | |
83 /* must be S3 */ | |
84 if (s3s7_get_addr_data(&srr) < 0) { | |
85 /* error msg already printed */ | |
86 fclose(srr.openfile); | |
87 fclose(tmpfile); | |
88 return(-1); | |
89 } | |
90 if (srr.datalen < 1) { | |
91 fprintf(stderr, | |
92 "%s line %d: S3 record of zero data length ignored\n", | |
93 srr.filename, srr.lineno); | |
94 continue; | |
95 } | |
96 if (srr.addr & 1 || srr.datalen & 1) { | |
97 fprintf(stderr, | |
98 "%s line %d: violates word alignment requirement\n", | |
99 srr.filename, srr.lineno); | |
100 fclose(srr.openfile); | |
101 fclose(tmpfile); | |
102 return(-1); | |
103 } | |
104 srr.addr &= bank_size - 1; | |
105 if (srr.addr + srr.datalen > bank_size) { | |
106 fprintf(stderr, | |
107 "%s line %d: goes past the end of the flash bank\n", | |
108 srr.filename, srr.lineno); | |
109 fclose(srr.openfile); | |
110 fclose(tmpfile); | |
111 return(-1); | |
112 } | |
113 /* is this the first record of the first region? */ | |
114 if (!regcount) { | |
115 regp->start = srr.addr; | |
116 regp->end = srr.addr; | |
117 regp->crc = 0xFFFFFFFF; | |
118 regcount = 1; | |
119 } | |
120 if (srr.addr < regp->end) { | |
121 fprintf(stderr, "%s line %d: address going backwards\n", | |
122 srr.filename, srr.lineno); | |
123 fclose(srr.openfile); | |
124 fclose(tmpfile); | |
125 return(-1); | |
126 } | |
127 if (srr.addr != regp->end) { | |
128 if (regcount >= MAX_SREC_REGIONS) { | |
129 fprintf(stderr, | |
130 "error: %s has too many discontiguous regions\n", | |
131 imgfile); | |
132 fclose(srr.openfile); | |
133 fclose(tmpfile); | |
134 return(-1); | |
135 } | |
136 regp++; | |
137 regcount++; | |
138 regp->start = srr.addr; | |
139 regp->end = srr.addr; | |
140 regp->crc = 0xFFFFFFFF; | |
141 } | |
142 /* take in the payload */ | |
143 if (is_m0) { | |
144 for (i = 0; i < srr.datalen; i += 2) { | |
145 c = srr.record[i+6]; | |
146 regp->crc = crc32_table[regp->crc & 0xFF ^ c] | |
147 ^ (regp->crc >> 8); | |
148 putc(c, tmpfile); | |
149 c = srr.record[i+5]; | |
150 regp->crc = crc32_table[regp->crc & 0xFF ^ c] | |
151 ^ (regp->crc >> 8); | |
152 putc(c, tmpfile); | |
153 } | |
154 } else { | |
155 for (i = 0; i < srr.datalen; i++) { | |
156 c = srr.record[i+5]; | |
157 regp->crc = crc32_table[regp->crc & 0xFF ^ c] | |
158 ^ (regp->crc >> 8); | |
159 putc(c, tmpfile); | |
160 } | |
161 } | |
162 regp->end += srr.datalen; | |
163 total_len += srr.datalen; | |
164 } | |
165 /* got S7 */ | |
166 fclose(srr.openfile); | |
167 if (!regcount) { | |
168 fprintf(stderr, | |
169 "%s line %d: S7 without any preceding S3 data records\n", | |
170 srr.filename, srr.lineno); | |
171 fclose(tmpfile); | |
172 return(-1); | |
173 } | |
174 /* good read */ | |
175 if (regcount == 1) | |
176 printf("Got %lu (0x%lx) bytes in one contiguous region\n", | |
177 (u_long) total_len, (u_long) total_len); | |
178 else | |
179 printf("Got %lu (0x%lx) bytes in %u discontiguous regions\n", | |
180 (u_long) total_len, (u_long) total_len, regcount); | |
181 *regcountp = regcount; | |
182 *totalp = total_len; | |
183 *tmpfilep = tmpfile; | |
184 return(0); | |
185 } | |
15 | 186 |
16 flashcmd_progsrec_gen(bank, imgfile, is_m0) | 187 flashcmd_progsrec_gen(bank, imgfile, is_m0) |
17 char *imgfile; | 188 char *imgfile; |
18 { | 189 { |
19 struct flash_bank_info *bi; | 190 struct flash_bank_info *bi; |
20 struct srecreader srr; | 191 struct discontig_prog regions[MAX_SREC_REGIONS], *regp; |
192 unsigned nregions, reg; | |
193 uint32_t total_len, bytesdone, addr, len; | |
194 FILE *tmpfile; | |
21 char *targv[4], shortarg[10], longarg[513]; | 195 char *targv[4], shortarg[10], longarg[513]; |
22 int resp; | 196 u_char databuf[256]; |
23 unsigned long rec_count; | 197 int reclen, cc, rc; |
24 time_t start_time, finish_time; | 198 time_t initial_time, curtime, last_time; |
25 unsigned duration, mm, ss; | 199 unsigned duration, mm, ss; |
200 u_long crc_from_target; | |
26 | 201 |
27 if (flash_detect(bank, 0) < 0) | 202 if (flash_detect(bank, 0) < 0) |
28 return(-1); | 203 return(-1); |
29 bi = flash_bank_info + bank; | 204 bi = flash_bank_info + bank; |
30 srr.filename = imgfile; | 205 rc = read_srec_img_for_flash(imgfile, is_m0, bi->geom->total_size, |
31 resp = open_srec_file(&srr); | 206 regions, &nregions, &total_len, &tmpfile); |
32 if (resp < 0) | 207 if (rc < 0) |
33 return(resp); | 208 return(rc); |
34 sprintf(shortarg, "%lx", (u_long) bi->base_addr); | 209 sprintf(shortarg, "%lx", (u_long) bi->base_addr); |
35 targv[0] = bi->ops->loadagent_setbase_cmd; | 210 targv[0] = bi->ops->loadagent_setbase_cmd; |
36 targv[1] = shortarg; | 211 targv[1] = shortarg; |
37 targv[2] = 0; | 212 targv[2] = 0; |
38 printf("Setting flash base address: %s %s\n", targv[0], targv[1]); | 213 printf("Setting flash base address: %s %s\n", targv[0], targv[1]); |
39 tpinterf_make_cmd(targv); | 214 tpinterf_make_cmd(targv); |
40 if (tpinterf_send_cmd() < 0) { | 215 if (tpinterf_send_cmd() < 0) { |
41 fclose(srr.openfile); | 216 fclose(tmpfile); |
42 return(-1); | 217 return(-1); |
43 } | 218 } |
44 resp = tpinterf_pass_output(1); | 219 rc = tpinterf_pass_output(1); |
45 if (resp) { | 220 if (rc) { |
46 fclose(srr.openfile); | 221 fclose(tmpfile); |
47 return(resp); | 222 return(rc); |
48 } | 223 } |
49 if (bi->ops->prep_for_program(bi) < 0) { | 224 if (bi->ops->prep_for_program(bi) < 0) { |
50 fclose(srr.openfile); | 225 fclose(tmpfile); |
51 return(-1); | 226 return(-1); |
52 } | 227 } |
228 rewind(tmpfile); | |
53 targv[0] = bi->ops->loadagent_program_cmd; | 229 targv[0] = bi->ops->loadagent_program_cmd; |
54 targv[1] = shortarg; | 230 targv[1] = shortarg; |
55 targv[2] = longarg; | 231 targv[2] = longarg; |
56 targv[3] = 0; | 232 targv[3] = 0; |
57 for (rec_count = 0; ; ) { | 233 printf("Programming flash\n"); |
58 if (read_s_record(&srr) < 0) { | 234 bytesdone = 0; |
59 /* error msg already printed */ | 235 last_time = 0; |
60 fclose(srr.openfile); | 236 time(&initial_time); |
61 return(-1); | 237 for (reg = 0, regp = regions; reg < nregions; reg++, regp++) { |
62 } | 238 addr = regp->start; |
63 if (srr.record_type == '0') { | 239 len = regp->end - addr; |
64 if (srr.lineno == 1) | 240 while (len) { |
65 continue; | 241 if (len >= 256) |
66 fprintf(stderr, | 242 reclen = 256; |
67 "Warning: S0 record found in line %d of %s (expected in line 1 only)\n", | 243 else |
68 srr.lineno, srr.filename); | 244 reclen = len; |
69 continue; | 245 cc = fread(databuf, 1, reclen, tmpfile); |
70 } else if (srr.record_type == '7') { | 246 if (cc != reclen) { |
71 time(&finish_time); | 247 fclose(tmpfile); |
72 break; | 248 fprintf(stderr, |
73 } else if (srr.record_type != '3') { | 249 "error reading from temp file!\n"); |
74 fprintf(stderr, | 250 return(-1); |
75 "Warning: unsupported S%c record type in line %d of %s\n", | 251 } |
76 srr.record_type, srr.lineno, srr.filename); | 252 sprintf(shortarg, "%lx", addr); |
77 continue; | 253 build_flashw_hex_string(databuf, longarg, reclen >> 1, |
78 } | 254 0); |
79 /* must be S3 */ | 255 tpinterf_make_cmd(targv); |
80 if (s3s7_get_addr_data(&srr) < 0) { | 256 if (tpinterf_send_cmd() < 0) { |
81 /* error msg already printed */ | 257 fclose(tmpfile); |
82 fclose(srr.openfile); | 258 return(-1); |
83 return(-1); | 259 } |
84 } | 260 rc = tpinterf_pass_output(8); /* 8 s timeout */ |
85 if (srr.datalen < 1) { | 261 if (rc) { |
86 fprintf(stderr, | 262 fclose(tmpfile); |
87 "%s line %d: S3 record of zero data length ignored\n", | 263 return(rc); |
88 srr.filename, srr.lineno); | 264 } |
89 continue; | 265 addr += reclen; |
90 } | 266 len -= reclen; |
91 if (srr.addr & 1 || srr.datalen & 1) { | 267 bytesdone += reclen; |
92 fprintf(stderr, | 268 cc = bytesdone * 100 / total_len; |
93 "%s line %d: violates word alignment requirement\n", | 269 time(&curtime); |
94 srr.filename, srr.lineno); | 270 if (curtime != last_time || cc == 100) { |
95 fclose(srr.openfile); | 271 printf("\r0x%lx bytes programmed (%i%%)", |
96 return(-1); | 272 bytesdone, cc); |
97 } | 273 fflush(stdout); |
98 srr.addr &= bi->geom->total_size - 1; | 274 } |
99 if (srr.addr + srr.datalen > bi->geom->total_size) { | 275 last_time = curtime; |
100 fprintf(stderr, | 276 } |
101 "%s line %d: goes past the end of the flash bank\n", | 277 } |
102 srr.filename, srr.lineno); | 278 putchar('\n'); |
103 fclose(srr.openfile); | 279 fclose(tmpfile); |
104 return(-1); | 280 duration = last_time - initial_time; |
105 } | |
106 if (!rec_count) { | |
107 printf("Programming flash, each \'.\' is 100 S-records\n"); | |
108 time(&start_time); | |
109 } | |
110 sprintf(shortarg, "%lx", (u_long) srr.addr); | |
111 build_flashw_hex_string(srr.record + 5, longarg, | |
112 srr.datalen >> 1, is_m0); | |
113 tpinterf_make_cmd(targv); | |
114 if (tpinterf_send_cmd() < 0) { | |
115 fclose(srr.openfile); | |
116 return(-1); | |
117 } | |
118 resp = tpinterf_pass_output(8); /* 8 s timeout */ | |
119 if (resp) { | |
120 fclose(srr.openfile); | |
121 return(resp); | |
122 } | |
123 rec_count++; | |
124 if (rec_count % 100 == 0) { | |
125 putchar('.'); | |
126 fflush(stdout); | |
127 } | |
128 } | |
129 /* got S7 */ | |
130 fclose(srr.openfile); | |
131 if (!rec_count) { | |
132 fprintf(stderr, | |
133 "%s line %d: S7 without any preceding S3 data records\n", | |
134 srr.filename, srr.lineno); | |
135 return(-1); | |
136 } | |
137 duration = finish_time - start_time; | |
138 mm = duration / 60; | 281 mm = duration / 60; |
139 ss = duration - mm * 60; | 282 ss = duration - mm * 60; |
140 printf("\nOperation completed in %um%us\n", mm, ss); | 283 printf("Operation completed in %um%us\n", mm, ss); |
284 | |
285 /* reset flash to read mode */ | |
286 if (bi->ops->reset_cmd(bi) < 0) | |
287 return(-1); | |
288 printf("Verifying CRC-32 of %u programmed region(s)\n", nregions); | |
289 for (reg = 0, regp = regions; reg < nregions; reg++, regp++) { | |
290 rc = crc32_on_target((u_long) regp->start, | |
291 (u_long) (regp->end - regp->start), | |
292 &crc_from_target); | |
293 if (rc < 0) | |
294 return(rc); | |
295 if (crc_from_target != regp->crc) { | |
296 fprintf(stderr, "error: CRC mismatch!\n"); | |
297 return(-1); | |
298 } | |
299 putchar('.'); | |
300 fflush(stdout); | |
301 } | |
302 putchar('\n'); | |
141 return(0); | 303 return(0); |
142 } | 304 } |
143 | 305 |
144 flashcmd_program_srec(argc, argv, bank) | 306 flashcmd_program_srec(argc, argv, bank) |
145 char **argv; | 307 char **argv; |