comparison loadtools/flamdsec.c @ 983:0407d14fb854

PL-J flash PPB ops: rework for full verification of lock state
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 02 Dec 2023 08:22:00 +0000
parents 1c5b485f10ba
children 84c9869a3659
comparison
equal deleted inserted replaced
982:1c5b485f10ba 983:0407d14fb854
6 6
7 #include <sys/types.h> 7 #include <sys/types.h>
8 #include <stdio.h> 8 #include <stdio.h>
9 #include <stdint.h> 9 #include <stdint.h>
10 #include <stdlib.h> 10 #include <stdlib.h>
11 #include <string.h>
12 #include <strings.h>
11 #include <unistd.h> 13 #include <unistd.h>
12 #include "flash.h" 14 #include "flash.h"
13 15
14 extern struct flash_bank_info flash_bank_info[2]; 16 extern struct flash_bank_info flash_bank_info[2];
15 17
179 } 181 }
180 return(0); 182 return(0);
181 } 183 }
182 184
183 /* 185 /*
186 * Here comes a version of the above lock-state checking code,
187 * modified for use from within ppb-program-all and ppb-erase-all
188 * functions for chips that don't do this work internally.
189 */
190
191 static
192 int_lock_state_check(bi, sought_state)
193 struct flash_bank_info *bi;
194 {
195 struct amd_lock_info *li = bi->amd_lock;
196 struct lock_group_desc *grp;
197 uint32_t offset, part_addr;
198 uint16_t word;
199 unsigned ng, nb;
200 int lock_state;
201
202 offset = 0;
203 for (ng = 0; ng < li->ngroups; ng++) {
204 grp = li->groups + ng;
205 if (grp->part_begin) {
206 part_addr = bi->base_addr + offset;
207 if (issue_read_id(part_addr) < 0)
208 return(-1);
209 }
210 for (nb = 0; nb < grp->nblocks; nb++) {
211 if (do_r16(bi->base_addr + offset + 4, &word) < 0)
212 return(-1);
213 lock_state = word & 1;
214 if (lock_state != sought_state)
215 break;
216 offset += grp->block_size;
217 }
218 if (lock_state != sought_state) {
219 if (issue_reset_cmd(part_addr) < 0)
220 return(-1);
221 return(0);
222 }
223 if (grp->part_end) {
224 if (issue_reset_cmd(part_addr) < 0)
225 return(-1);
226 }
227 }
228 return(1);
229 }
230
231 /*
184 * Spansion PL-J PPB write functions, referenced from lock_info structures 232 * Spansion PL-J PPB write functions, referenced from lock_info structures
185 * in fldevs.c device descriptions. 233 * in fldevs.c device descriptions.
186 */ 234 */
187 235
188 static 236 static
226 continue; 274 continue;
227 printf("PPB 0x%X programmed with %u pulse%s\n", sector_addr, 275 printf("PPB 0x%X programmed with %u pulse%s\n", sector_addr,
228 pulsecnt, pulsecnt > 1 ? "s" : ""); 276 pulsecnt, pulsecnt > 1 ? "s" : "");
229 return amd_reset_cmd(bi); 277 return amd_reset_cmd(bi);
230 } 278 }
231 printf("PPB 0x%X programming FAILED, tried %u pulses\n", sector_addr, 279 fprintf(stderr, "PPB 0x%X programming FAILED, tried %u pulses\n",
232 pulsecnt); 280 sector_addr, pulsecnt);
233 return(-1); 281 return(-1);
234 } 282 }
235 283
236 plj_ppb_program_all_single(bank) 284 plj_ppb_program_all(bi)
237 { 285 struct flash_bank_info *bi;
238 struct flash_bank_info *bi = flash_bank_info + bank; 286 {
239 struct amd_lock_info *li = bi->amd_lock; 287 struct amd_lock_info *li = bi->amd_lock;
240 struct lock_group_desc *grp; 288 struct lock_group_desc *grp;
241 uint32_t offset; 289 uint32_t offset;
242 unsigned ng, nb; 290 unsigned ng, nb;
243 int rc; 291 int rc;
250 if (rc < 0) 298 if (rc < 0)
251 return(rc); 299 return(rc);
252 offset += grp->block_size; 300 offset += grp->block_size;
253 } 301 }
254 } 302 }
255 return(0); 303 printf("Verifying PPB programming\n");
256 } 304 rc = int_lock_state_check(bi, 1);
257
258 plj_ppb_program_all_dualbank(reqbank)
259 {
260 int altbank = !reqbank;
261 int rc;
262
263 if (flash_detect(altbank, 0) < 0)
264 return(-1);
265 if (flash_bank_info[0].device != flash_bank_info[1].device) {
266 fprintf(stderr, "error: mismatch between two flash banks\n");
267 return(-1);
268 }
269 printf("Programming all PPBs in flash bank 0\n");
270 rc = plj_ppb_program_all_single(0);
271 if (rc < 0) 305 if (rc < 0)
272 return(-1); 306 return(rc);
273 printf("Programming all PPBs in flash bank 1\n"); 307 if (rc)
274 rc = plj_ppb_program_all_single(1); 308 return(0);
275 if (rc < 0) 309 fprintf(stderr, "flash error: one or more PPBs failed to program\n");
276 return(-1); 310 return(-1);
277 return(0); 311 }
278 } 312
279 313 static
280 static 314 plj_ppb_erase_cycle(bi)
281 plj_ppb_erase_cycle(bank) 315 struct flash_bank_info *bi;
282 { 316 {
283 struct flash_bank_info *bi = flash_bank_info + bank;
284 uint16_t stat; 317 uint16_t stat;
285 unsigned pulsecnt; 318 unsigned pulsecnt;
286 int rc; 319 int rc;
287 320
288 printf("Performing PPB erase cycle\n"); 321 printf("Performing PPB erase cycle\n");
295 continue; 328 continue;
296 printf("PPB erase cycle succeeded after %u pulse%s\n", 329 printf("PPB erase cycle succeeded after %u pulse%s\n",
297 pulsecnt, pulsecnt > 1 ? "s" : ""); 330 pulsecnt, pulsecnt > 1 ? "s" : "");
298 return amd_reset_cmd(bi); 331 return amd_reset_cmd(bi);
299 } 332 }
300 printf("PPB erase cycle FAILED, tried %u pulses\n", pulsecnt); 333 fprintf(stderr, "PPB erase cycle FAILED, tried %u pulses\n", pulsecnt);
301 return(-1); 334 return(-1);
302 } 335 }
303 336
304 plj_ppb_erase_all_single(bank) 337 plj_ppb_erase_all_single(bank, raw_mode)
305 { 338 {
339 struct flash_bank_info *bi = flash_bank_info + bank;
340 unsigned pulsecnt;
341 uint16_t stat;
306 int rc; 342 int rc;
307 343
344 if (raw_mode)
345 return plj_ppb_erase_cycle(bi);
308 printf("Programming all PPBs before erase cycle\n"); 346 printf("Programming all PPBs before erase cycle\n");
309 rc = plj_ppb_program_all_single(bank); 347 rc = plj_ppb_program_all(bi);
310 if (rc < 0) 348 if (rc < 0)
311 return(-1); 349 return(-1);
312 return plj_ppb_erase_cycle(bank); 350 printf("Entering PPB erase and verify loop\n");
313 } 351 for (pulsecnt = 0; ; ) {
314 352 if (pulsecnt >= 1000) {
315 plj_ppb_erase_all_dualbank(reqbank) 353 fprintf(stderr,
316 { 354 "flash error: unable to complete PPB erase after %u pulses\n",
355 pulsecnt);
356 return(-1);
357 }
358 rc = plj_ppb_write_op(bi->base_addr, 1, &stat);
359 if (rc < 0)
360 return(rc);
361 pulsecnt++;
362 if (stat & 1)
363 continue;
364 putchar('.');
365 fflush(stdout);
366 rc = amd_reset_cmd(bi);
367 if (rc < 0)
368 return(rc);
369 rc = int_lock_state_check(bi, 0);
370 if (rc < 0)
371 return(rc);
372 if (rc)
373 break;
374 }
375 printf("\nPPB erase complete, total pulses: %u\n", pulsecnt);
376 return(0);
377 }
378
379 plj_ppb_erase_all_dualbank(reqbank, raw_mode)
380 {
381 int altbank = !reqbank;
382 unsigned pulsecnt;
383 uint16_t stat;
317 int rc; 384 int rc;
318 385
319 rc = plj_ppb_program_all_dualbank(reqbank); 386 if (flash_detect(altbank, 0) < 0)
387 return(-1);
388 if (flash_bank_info[0].device != flash_bank_info[1].device) {
389 fprintf(stderr, "error: mismatch between two flash banks\n");
390 return(-1);
391 }
392 if (raw_mode)
393 return plj_ppb_erase_cycle(flash_bank_info + reqbank);
394 printf("Programming all PPBs in flash bank 0\n");
395 rc = plj_ppb_program_all(&flash_bank_info[0]);
320 if (rc < 0) 396 if (rc < 0)
321 return(-1); 397 return(-1);
322 return plj_ppb_erase_cycle(reqbank); 398 printf("Programming all PPBs in flash bank 1\n");
399 rc = plj_ppb_program_all(&flash_bank_info[1]);
400 if (rc < 0)
401 return(-1);
402 printf("Entering PPB erase and verify loop\n");
403 for (pulsecnt = 0; ; ) {
404 if (pulsecnt >= 1000) {
405 fprintf(stderr,
406 "flash error: unable to complete PPB erase after %u pulses\n",
407 pulsecnt);
408 return(-1);
409 }
410 rc = plj_ppb_write_op(flash_bank_info[0].base_addr, 1, &stat);
411 if (rc < 0)
412 return(rc);
413 pulsecnt++;
414 if (stat & 1)
415 continue;
416 putchar('.');
417 fflush(stdout);
418 rc = amd_reset_cmd(&flash_bank_info[0]);
419 if (rc < 0)
420 return(rc);
421 rc = int_lock_state_check(&flash_bank_info[0], 0);
422 if (rc < 0)
423 return(rc);
424 if (!rc)
425 continue;
426 rc = int_lock_state_check(&flash_bank_info[1], 0);
427 if (rc < 0)
428 return(rc);
429 if (rc)
430 break;
431 }
432 printf("\nPPB erase complete, total pulses: %u\n", pulsecnt);
433 return(0);
323 } 434 }
324 435
325 /* 436 /*
326 * Front end functions for PPB operation commands. 437 * Front end functions for PPB operation commands.
327 */ 438 */
388 if (!li || !li->ppb_program_all) { 499 if (!li || !li->ppb_program_all) {
389 fprintf(stderr, 500 fprintf(stderr,
390 "Operation not supported for this flash chip type\n"); 501 "Operation not supported for this flash chip type\n");
391 return(-1); 502 return(-1);
392 } 503 }
393 return li->ppb_program_all(bank); 504 return li->ppb_program_all(bi);
394 } 505 }
395 506
396 flashcmd_ppb_erase_all(argc, argv, bank) 507 flashcmd_ppb_erase_all(argc, argv, bank)
397 char **argv; 508 char **argv;
398 { 509 {
399 struct flash_bank_info *bi; 510 struct flash_bank_info *bi;
400 struct amd_lock_info *li; 511 struct amd_lock_info *li;
401 512 int raw_mode;
402 if (argc > 2) { 513
403 fprintf(stderr, "error: too many arguments\n"); 514 switch (argc) {
515 case 2:
516 raw_mode = 0;
517 break;
518 case 3:
519 if (!strcmp(argv[2], "raw")) {
520 raw_mode = 1;
521 break;
522 }
523 /* FALL THRU */
524 default:
525 fprintf(stderr, "usage: %s %s [raw]\n", argv[0], argv[1]);
404 return(-1); 526 return(-1);
405 } 527 }
406 if (flash_detect(bank, 0) < 0) 528 if (flash_detect(bank, 0) < 0)
407 return(-1); 529 return(-1);
408 bi = flash_bank_info + bank; 530 bi = flash_bank_info + bank;
410 if (!li || !li->ppb_erase_all) { 532 if (!li || !li->ppb_erase_all) {
411 fprintf(stderr, 533 fprintf(stderr,
412 "Operation not supported for this flash chip type\n"); 534 "Operation not supported for this flash chip type\n");
413 return(-1); 535 return(-1);
414 } 536 }
415 return li->ppb_erase_all(bank); 537 return li->ppb_erase_all(bank, raw_mode);
416 } 538 }