FreeCalypso > hg > freecalypso-tools
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 } |