comparison loadtools/flcmplboot.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 2cd705c8116e
comparison
equal deleted inserted replaced
-1:000000000000 0:e7502631a0f9
1 /*
2 * This module contains the implementation of the flash erase-program-boot
3 * hack for brickable Compal phones.
4 */
5
6 #include <sys/types.h>
7 #include <sys/stat.h>
8 #include <ctype.h>
9 #include <stdio.h>
10 #include <stdint.h>
11 #include <string.h>
12 #include <strings.h>
13 #include <stdlib.h>
14 #include "flash.h"
15
16 extern struct flash_bank_info flash_bank_info[2];
17 extern struct flash_cmdset flash_cmdset_intel;
18
19 extern uint32_t crc32_table[];
20
21 static int hack_enabled;
22 static uint32_t boot_sector_size;
23 static uint32_t ram_buffer_addr;
24
25 /* called from hwparam.c config file parser */
26 void
27 set_boot_reflash_hack(arg, filename_for_errs, lineno_for_errs)
28 char *arg;
29 char *filename_for_errs;
30 int lineno_for_errs;
31 {
32 char *cp, *np, *ep;
33
34 if (hack_enabled) {
35 fprintf(stderr,
36 "%s line %d: duplicate boot-reflash-hack setting\n",
37 filename_for_errs, lineno_for_errs);
38 exit(1);
39 }
40 for (cp = arg; isspace(*cp); cp++)
41 ;
42 if (!*cp || *cp == '#') {
43 too_few_arg: fprintf(stderr,
44 "%s line %d: boot-reflash-hack setting: too few arguments\n",
45 filename_for_errs, lineno_for_errs);
46 exit(1);
47 }
48 for (np = cp; *cp && !isspace(*cp); cp++)
49 ;
50 if (!*cp)
51 goto too_few_arg;
52 *cp++ = '\0';
53 ram_buffer_addr = strtoul(np, &ep, 16);
54 if (*ep) {
55 invhex: fprintf(stderr,
56 "%s line %d: syntax error (hex arguments expected)\n",
57 filename_for_errs, lineno_for_errs);
58 exit(1);
59 }
60 while (isspace(*cp))
61 cp++;
62 if (!*cp || *cp == '#')
63 goto too_few_arg;
64 for (np = cp; *cp && !isspace(*cp); cp++)
65 ;
66 if (*cp)
67 *cp++ = '\0';
68 boot_sector_size = strtoul(np, &ep, 16);
69 if (*ep)
70 goto invhex;
71 while (isspace(*cp))
72 cp++;
73 if (*cp && *cp != '#') {
74 fprintf(stderr,
75 "%s line %d: boot-reflash-hack setting: too many arguments\n",
76 filename_for_errs, lineno_for_errs);
77 exit(1);
78 }
79 hack_enabled = 1;
80 }
81
82 static void
83 make_s3_record(buf, dest_addr, datalen)
84 u_char *buf;
85 uint32_t dest_addr;
86 {
87 int totlen, i;
88 u_char accum;
89
90 buf[0] = totlen = datalen + 5;
91 buf[1] = dest_addr >> 24;
92 buf[2] = dest_addr >> 16;
93 buf[3] = dest_addr >> 8;
94 buf[4] = dest_addr;
95 accum = 0;
96 for (i = 0; i < totlen; i++)
97 accum += buf[i];
98 buf[i] = ~accum;
99 }
100
101 static void
102 make_ml_arg(rec, buf)
103 u_char *rec;
104 char *buf;
105 {
106 register int i, len;
107 register char *s;
108
109 len = rec[0] + 1;
110 s = buf;
111 for (i = 0; i < len; i++) {
112 sprintf(s, "%02X", rec[i]);
113 s += 2;
114 }
115 *s = '\0';
116 }
117
118 flashcmd_erase_program_boot(argc, argv)
119 char **argv;
120 {
121 FILE *binf;
122 struct stat filestat;
123 size_t len;
124 char *strtoul_endp;
125 char *targv[5], longarg[513];
126 char shortarg1[9], shortarg2[9], shortarg3[9];
127 u_char databuf[256];
128 int reclen, cc, i;
129 uint32_t ramaddr, remlen, crcaccum;
130 u_long crc_from_target;
131
132 if (!hack_enabled) {
133 fprintf(stderr,
134 "Operation not applicable to this target device\n");
135 return(-1);
136 }
137 if (argc < 3 || argc > 4) {
138 inv: fprintf(stderr, "usage: %s %s binfile [length]\n",
139 argv[0], argv[1]);
140 return(-1);
141 }
142 if (flash_get_cfi(0) < 0)
143 return(-1);
144 if (flash_bank_info[0].geom->regions[0].sector_size
145 != boot_sector_size) {
146 fprintf(stderr,
147 "error: detected flash boot sector size differs from config\n");
148 return(-1);
149 }
150 if (flash_bank_info[0].ops != &flash_cmdset_intel) {
151 fprintf(stderr,
152 "error: operation implemented for Intel flash only\n");
153 return(-1);
154 }
155
156 binf = fopen(argv[2], "r");
157 if (!binf) {
158 perror(argv[2]);
159 return(-1);
160 }
161 fstat(fileno(binf), &filestat);
162 if (!S_ISREG(filestat.st_mode)) {
163 fprintf(stderr, "%s is not a regular file\n", argv[2]);
164 fclose(binf);
165 return(-1);
166 }
167 if (argc > 3) {
168 len = strtoul(argv[3], &strtoul_endp, 16);
169 if (*strtoul_endp) {
170 fclose(binf);
171 goto inv;
172 }
173 if (len > filestat.st_size) {
174 fprintf(stderr,
175 "error: specified length exceeds file length\n");
176 fclose(binf);
177 return(-1);
178 }
179 } else
180 len = filestat.st_size;
181 if (len > boot_sector_size) {
182 fprintf(stderr, "error: length exceeds boot sector size\n");
183 fclose(binf);
184 return(-1);
185 }
186 if (len & 1) {
187 fprintf(stderr, "error: length must be even\n");
188 fclose(binf);
189 return(-1);
190 }
191
192 printf("Loading new boot code into target RAM at %lx\n",
193 (u_long) ram_buffer_addr);
194 targv[0] = "ML";
195 targv[1] = longarg;
196 targv[2] = 0;
197 ramaddr = ram_buffer_addr;
198 crcaccum = 0xFFFFFFFF;
199 for (remlen = len; remlen; remlen -= reclen) {
200 if (remlen >= 250)
201 reclen = 250;
202 else
203 reclen = remlen;
204 cc = fread(databuf + 5, 1, reclen, binf);
205 if (cc != reclen) {
206 fclose(binf);
207 fprintf(stderr, "error reading from %s\n", argv[2]);
208 return(-1);
209 }
210 for (i = 0; i < reclen; i++) /* update running CRC */
211 crcaccum = crc32_table[crcaccum & 0xFF ^ databuf[i+5]]
212 ^ (crcaccum >> 8);
213 make_s3_record(databuf, ramaddr, reclen);
214 make_ml_arg(databuf, longarg);
215 tpinterf_make_cmd(targv);
216 if (tpinterf_send_cmd() < 0) {
217 fclose(binf);
218 return(-1);
219 }
220 cc = tpinterf_pass_output(1);
221 if (cc) {
222 fclose(binf);
223 return(cc);
224 }
225 ramaddr += reclen;
226 putchar('.');
227 fflush(stdout);
228 }
229 putchar('\n');
230 fclose(binf);
231
232 printf("Verifying CRC-32 in target RAM\n");
233 if (crc32_on_target((u_long) ram_buffer_addr, (u_long) len,
234 &crc_from_target) < 0)
235 return(-1);
236 if (crc_from_target == crcaccum)
237 printf("match (%08lX)\n", crc_from_target);
238 else {
239 fprintf(stderr, "error: CRC mismatch!\n");
240 return(-1);
241 }
242
243 printf("Commanding flash erase+program operation on the target\n");
244 sprintf(shortarg1, "%lx", (u_long) ram_buffer_addr);
245 sprintf(shortarg2, "%lx", (u_long) flash_bank_info[0].base_addr);
246 sprintf(shortarg3, "%lx", (u_long) len);
247 targv[0] = "intel-rewrite-sector";
248 targv[1] = shortarg1;
249 targv[2] = shortarg2;
250 targv[3] = shortarg3;
251 targv[4] = 0;
252 tpinterf_make_cmd(targv);
253 if (tpinterf_send_cmd() < 0)
254 return(-1);
255 return tpinterf_pass_output(20); /* 20 s timeout */
256 }