blob: 031ccb207c6d9da8fa0f59633c66e38ab6570ae4 [file] [log] [blame]
Norman James6a58a272015-10-07 14:34:16 -05001#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <fcntl.h>
5#include <sys/mman.h>
6#include <sys/types.h>
7#include <sys/stat.h>
8#include <unistd.h>
9#include <byteswap.h>
10#include <stdint.h>
11#include <stdbool.h>
12#include <getopt.h>
13#include <limits.h>
14#include <arpa/inet.h>
15#include <assert.h>
16
17#include <libflash/libflash.h>
18#include <libflash/libffs.h>
19#include "progress.h"
20#include "io.h"
21#include "ast.h"
22#include "sfc-ctrl.h"
23
24#define __aligned(x) __attribute__((aligned(x)))
25
26#define PFLASH_VERSION "0.8.6"
27
28static bool must_confirm = false;
29static bool dummy_run;
30static bool need_relock;
31static bool bmc_flash;
32#ifdef __powerpc__
33static bool using_sfc;
34#endif
35
36#define FILE_BUF_SIZE 0x10000
37static uint8_t file_buf[FILE_BUF_SIZE] __aligned(0x1000);
38
39static struct spi_flash_ctrl *fl_ctrl;
40static struct flash_chip *fl_chip;
41static struct ffs_handle *ffsh;
42static uint32_t fl_total_size, fl_erase_granule;
43static const char *fl_name;
44static int32_t ffs_index = -1;
45
46static void check_confirm(void)
47{
48 char yes[8], *p;
49
50 if (!must_confirm)
51 return;
52
53 printf("WARNING ! This will modify your %s flash chip content !\n",
54 bmc_flash ? "BMC" : "HOST");
55 printf("Enter \"yes\" to confirm:");
56 memset(yes, 0, sizeof(yes));
57 if (!fgets(yes, 7, stdin))
58 exit(1);
59 p = strchr(yes, 10);
60 if (p)
61 *p = 0;
62 p = strchr(yes, 13);
63 if (p)
64 *p = 0;
65 if (strcmp(yes, "yes")) {
66 printf("Operation cancelled !\n");
67 exit(1);
68 }
69 must_confirm = false;
70}
71
72static void print_flash_info(void)
73{
74 uint32_t i;
75 int rc;
76
77 printf("Flash info:\n");
78 printf("-----------\n");
79 printf("Name = %s\n", fl_name);
80 printf("Total size = %dMB \n", fl_total_size >> 20);
81 printf("Erase granule = %dKB \n", fl_erase_granule >> 10);
82
83 if (bmc_flash)
84 return;
85
86 if (!ffsh) {
87 rc = ffs_open_flash(fl_chip, 0, 0, &ffsh);
88 if (rc) {
89 fprintf(stderr, "Error %d opening ffs !\n", rc);
90 ffsh = NULL;
91 }
92 }
93 if (!ffsh)
94 return;
95
96 printf("\n");
97 printf("Partitions:\n");
98 printf("-----------\n");
99
100 for (i = 0;; i++) {
101 uint32_t start, size, act, end;
102 char *name;
103
104 rc = ffs_part_info(ffsh, i, &name, &start, &size, &act);
105 if (rc == FFS_ERR_PART_NOT_FOUND)
106 break;
107 if (rc) {
108 fprintf(stderr, "Error %d scanning partitions\n", rc);
109 break;
110 }
111 end = start + size;
112 printf("ID=%02d %15s %08x..%08x (actual=%08x)\n",
113 i, name, start, end, act);
114 free(name);
115 }
116}
117
118static void lookup_partition(const char *name)
119{
120 uint32_t index;
121 int rc;
122
123 /* Open libffs if needed */
124 if (!ffsh) {
125 rc = ffs_open_flash(fl_chip, 0, 0, &ffsh);
126 if (rc) {
127 fprintf(stderr, "Error %d opening ffs !\n", rc);
128 exit(1);
129 }
130 }
131
132 /* Find partition */
133 rc = ffs_lookup_part(ffsh, name, &index);
134 if (rc == FFS_ERR_PART_NOT_FOUND) {
135 fprintf(stderr, "Partition '%s' not found !\n", name);
136 exit(1);
137 }
138 if (rc) {
139 fprintf(stderr, "Error %d looking for partition '%s' !\n",
140 rc, name);
141 exit(1);
142 }
143 ffs_index = index;
144}
145
146static void erase_chip(void)
147{
148 int rc;
149
150 printf("About to erase chip !\n");
151 check_confirm();
152
153 printf("Erasing... (may take a while !) ");
154 fflush(stdout);
155
156 if (dummy_run) {
157 printf("skipped (dummy)\n");
158 return;
159 }
160
161 rc = flash_erase_chip(fl_chip);
162 if (rc) {
163 fprintf(stderr, "Error %d erasing chip\n", rc);
164 exit(1);
165 }
166
167 printf("done !\n");
168}
169
170static void erase_range(uint32_t start, uint32_t size, bool will_program)
171{
172 uint32_t done = 0;
173 int rc;
174
175 printf("About to erase 0x%08x..0x%08x !\n", start, start + size);
176 check_confirm();
177
178 if (dummy_run) {
179 printf("skipped (dummy)\n");
180 return;
181 }
182
183 printf("Erasing...\n");
184 progress_init(size >> 8);
185 while(size) {
186 /* If aligned to 64k and at least 64k, use 64k erase */
187 if ((start & 0xffff) == 0 && size >= 0x10000) {
188 rc = flash_erase(fl_chip, start, 0x10000);
189 if (rc) {
190 fprintf(stderr, "Error %d erasing 0x%08x\n",
191 rc, start);
192 exit(1);
193 }
194 start += 0x10000;
195 size -= 0x10000;
196 done += 0x10000;
197 } else {
198 rc = flash_erase(fl_chip, start, 0x1000);
199 if (rc) {
200 fprintf(stderr, "Error %d erasing 0x%08x\n",
201 rc, start);
202 exit(1);
203 }
204 start += 0x1000;
205 size -= 0x1000;
206 done += 0x1000;
207 }
208 progress_tick(done >> 8);
209 }
210 progress_end();
211
212 /* If this is a flash partition, mark it empty if we aren't
213 * going to program over it as well
214 */
215 if (ffsh && ffs_index >= 0 && !will_program) {
216 printf("Updating actual size in partition header...\n");
217 ffs_update_act_size(ffsh, ffs_index, 0);
218 }
219}
220
221static void program_file(const char *file, uint32_t start, uint32_t size)
222{
223 int fd, rc;
224 ssize_t len;
225 uint32_t actual_size = 0;
226
227 fd = open(file, O_RDONLY);
228 if (fd == -1) {
229 perror("Failed to open file");
230 exit(1);
231 }
232 printf("About to program \"%s\" at 0x%08x..0x%08x !\n",
233 file, start, size);
234 check_confirm();
235
236 if (dummy_run) {
237 printf("skipped (dummy)\n");
238 return;
239 }
240
241 printf("Programming & Verifying...\n");
242 progress_init(size >> 8);
243 while(size) {
244 len = read(fd, file_buf, FILE_BUF_SIZE);
245 if (len < 0) {
246 perror("Error reading file");
247 exit(1);
248 }
249 if (len == 0)
250 break;
251 if (len > size)
252 len = size;
253 size -= len;
254 actual_size += len;
255 rc = flash_write(fl_chip, start, file_buf, len, true);
256 if (rc) {
257 if (rc == FLASH_ERR_VERIFY_FAILURE)
258 fprintf(stderr, "Verification failed for"
259 " chunk at 0x%08x\n", start);
260 else
261 fprintf(stderr, "Flash write error %d for"
262 " chunk at 0x%08x\n", rc, start);
263 exit(1);
264 }
265 start += len;
266 progress_tick(actual_size >> 8);
267 }
268 progress_end();
269 close(fd);
270
271 /* If this is a flash partition, adjust its size */
272 if (ffsh && ffs_index >= 0) {
273 printf("Updating actual size in partition header...\n");
274 ffs_update_act_size(ffsh, ffs_index, actual_size);
275 }
276}
277
278static void do_read_file(const char *file, uint32_t start, uint32_t size)
279{
280 int fd, rc;
281 ssize_t len;
282 uint32_t done = 0;
283
284 fd = open(file, O_WRONLY | O_TRUNC | O_CREAT, 00666);
285 if (fd == -1) {
286 perror("Failed to open file");
287 exit(1);
288 }
289 printf("Reading to \"%s\" from 0x%08x..0x%08x !\n",
290 file, start, size);
291
292 progress_init(size >> 8);
293 while(size) {
294 len = size > FILE_BUF_SIZE ? FILE_BUF_SIZE : size;
295 rc = flash_read(fl_chip, start, file_buf, len);
296 if (rc) {
297 fprintf(stderr, "Flash read error %d for"
298 " chunk at 0x%08x\n", rc, start);
299 exit(1);
300 }
301 rc = write(fd, file_buf, len);
302 if (rc < 0) {
303 perror("Error writing file");
304 exit(1);
305 }
306 start += len;
307 size -= len;
308 done += len;
309 progress_tick(done >> 8);
310 }
311 progress_end();
312 close(fd);
313}
314
315static void enable_4B_addresses(void)
316{
317 int rc;
318
319 printf("Switching to 4-bytes address mode\n");
320
321 rc = flash_force_4b_mode(fl_chip, true);
322 if (rc) {
323 fprintf(stderr, "Error %d enabling 4b mode\n", rc);
324 exit(1);
325 }
326}
327
328static void disable_4B_addresses(void)
329{
330 int rc;
331
332 printf("Switching to 3-bytes address mode\n");
333
334 rc = flash_force_4b_mode(fl_chip, false);
335 if (rc) {
336 fprintf(stderr, "Error %d disabling 4b mode\n", rc);
337 exit(1);
338 }
339}
340
341static void flash_access_cleanup_bmc(void)
342{
343 if (ffsh)
344 ffs_close(ffsh);
345 flash_exit(fl_chip);
346 ast_sf_close(fl_ctrl);
347 close_devs();
348}
349
350static void flash_access_setup_bmc(bool use_lpc, bool need_write)
351{
352 int rc;
353
354 /* Open and map devices */
355 open_devs(use_lpc, true);
356
357 /* Create the AST flash controller */
358 rc = ast_sf_open(AST_SF_TYPE_BMC, &fl_ctrl);
359 if (rc) {
360 fprintf(stderr, "Failed to open controller\n");
361 exit(1);
362 }
363
364 /* Open flash chip */
365 rc = flash_init(fl_ctrl, &fl_chip);
366 if (rc) {
367 fprintf(stderr, "Failed to open flash chip\n");
368 exit(1);
369 }
370
371 /* Setup cleanup function */
372 atexit(flash_access_cleanup_bmc);
373}
374
375static void flash_access_cleanup_pnor(void)
376{
377 /* Re-lock flash */
378 if (need_relock)
379 set_wrprotect(true);
380
381 if (ffsh)
382 ffs_close(ffsh);
383 flash_exit(fl_chip);
384#ifdef __powerpc__
385 if (using_sfc)
386 sfc_close(fl_ctrl);
387 else
388 ast_sf_close(fl_ctrl);
389#else
390 ast_sf_close(fl_ctrl);
391#endif
392 close_devs();
393}
394
395static void flash_access_setup_pnor(bool use_lpc, bool use_sfc, bool need_write)
396{
397 int rc;
398
399 /* Open and map devices */
400 open_devs(use_lpc, false);
401
402#ifdef __powerpc__
403 if (use_sfc) {
404 /* Create the SFC flash controller */
405 rc = sfc_open(&fl_ctrl);
406 if (rc) {
407 fprintf(stderr, "Failed to open controller\n");
408 exit(1);
409 }
410 using_sfc = true;
411 } else {
412#endif
413 /* Create the AST flash controller */
414 rc = ast_sf_open(AST_SF_TYPE_PNOR, &fl_ctrl);
415 if (rc) {
416 fprintf(stderr, "Failed to open controller\n");
417 exit(1);
418 }
419#ifdef __powerpc__
420 }
421#endif
422
423 /* Open flash chip */
424 rc = flash_init(fl_ctrl, &fl_chip);
425 if (rc) {
426 fprintf(stderr, "Failed to open flash chip\n");
427 exit(1);
428 }
429
430 /* Unlock flash (PNOR only) */
431 if (need_write)
432 need_relock = set_wrprotect(false);
433
434 /* Setup cleanup function */
435 atexit(flash_access_cleanup_pnor);
436}
437
438static void print_version(void)
439{
440 printf("Palmetto Flash tool " PFLASH_VERSION "\n");
441}
442
443static void print_help(const char *pname)
444{
445 printf("Usage: %s [options] commands...\n\n", pname);
446 printf(" Options:\n");
447 printf("\t-a address, --address=address\n");
448 printf("\t\tSpecify the start address for erasing, reading\n");
449 printf("\t\tor flashing\n\n");
450 printf("\t-s size, --size=size\n");
451 printf("\t\tSpecify the size in bytes for erasing, reading\n");
452 printf("\t\tor flashing\n\n");
453 printf("\t-P part_name, --partition=part_name\n");
454 printf("\t\tSpecify the partition whose content is to be erased\n");
455 printf("\t\tprogrammed or read. This is an alternative to -a and -s\n");
456 printf("\t\tif both -P and -s are specified, the smallest of the\n");
457 printf("\t\ttwo will be used\n\n");
458 printf("\t-f, --force\n");
459 printf("\t\tDon't ask for confirmation before erasing or flashing\n\n");
460 printf("\t-d, --dummy\n");
461 printf("\t\tDon't write to flash\n\n");
462#ifdef __powerpc__
463 printf("\t-l, --lpc\n");
464 printf("\t\tUse LPC accesses instead of PCI\n\n");
465#endif
466 printf("\t-b, --bmc\n");
467 printf("\t\tTarget BMC flash instead of host flash\n\n");
468 printf(" Commands:\n");
469 printf("\t-4, --enable-4B\n");
470 printf("\t\tSwitch the flash and controller to 4-bytes address\n");
471 printf("\t\tmode (no confirmation needed).\n\n");
472 printf("\t-3, --disable-4B\n");
473 printf("\t\tSwitch the flash and controller to 3-bytes address\n");
474 printf("\t\tmode (no confirmation needed).\n\n");
475 printf("\t-r file, --read=file\n");
476 printf("\t\tRead flash content from address into file, use -s\n");
477 printf("\t\tto specify the size to read (or it will use the source\n");
478 printf("\t\tfile size if used in conjunction with -p and -s is not\n");
479 printf("\t\tspecified). When using -r together with -e or -p, the\n");
480 printf("\t\tread will be peformed first\n\n");
481 printf("\t-E, --erase-all\n");
482 printf("\t\tErase entire flash chip\n");
483 printf("\t\t(Not supported on all chips/controllers)\n\n");
484 printf("\t-e, --erase\n");
485 printf("\t\tErase the specified region. If size or address are not\n");
486 printf("\t\tspecified, but \'--program\' is used, then the file\n");
487 printf("\t\tsize will be used (rounded to an erase block) and the\n");
488 printf("\t\taddress defaults to 0.\n\n");
489 printf("\t-p file, --program=file\n");
490 printf("\t\tWill program the file to flash. If the address is not\n");
491 printf("\t\tspecified, it will use 0. If the size is not specified\n");
492 printf("\t\tit will use the file size. Otherwise it will limit to\n");
493 printf("\t\tthe specified size (whatever is smaller). If used in\n");
494 printf("\t\tconjunction with any erase command, the erase will\n");
495 printf("\t\ttake place first.\n\n");
496 printf("\t-t, --tune\n");
497 printf("\t\tJust tune the flash controller & access size\n");
498 printf("\t\t(Implicit for all other operations)\n\n");
499 printf("\t-i, --info\n");
500 printf("\t\tDisplay some information about the flash.\n\n");
501 printf("\t-h, --help\n");
502 printf("\t\tThis message.\n\n");
503}
504
505int pflash_main(int argc, char *argv[])
506{
507 const char *pname = argv[0];
508 uint32_t address = 0, read_size = 0, write_size = 0;
509 uint32_t erase_start = 0, erase_size = 0;
510 bool erase = false;
511 bool program = false, erase_all = false, info = false, do_read = false;
512 bool enable_4B = false, disable_4B = false, use_lpc = true;
513 bool show_help = false, show_version = false;
514 bool has_sfc = false, has_ast = false;
515 bool no_action = false, tune = false;
516 char *write_file = NULL, *read_file = NULL, *part_name = NULL;
517 int rc;
518
519 while(1) {
520 static struct option long_opts[] = {
521 {"address", required_argument, NULL, 'a'},
522 {"size", required_argument, NULL, 's'},
523 {"partition", required_argument, NULL, 'P'},
524 {"lpc", no_argument, NULL, 'l'},
525 {"bmc", no_argument, NULL, 'b'},
526 {"enable-4B", no_argument, NULL, '4'},
527 {"disable-4B", no_argument, NULL, '3'},
528 {"read", required_argument, NULL, 'r'},
529 {"erase-all", no_argument, NULL, 'E'},
530 {"erase", no_argument, NULL, 'e'},
531 {"program", required_argument, NULL, 'p'},
532 {"force", no_argument, NULL, 'f'},
533 {"info", no_argument, NULL, 'i'},
534 {"tune", no_argument, NULL, 't'},
535 {"dummy", no_argument, NULL, 'd'},
536 {"help", no_argument, NULL, 'h'},
537 {"version", no_argument, NULL, 'v'},
538 {"debug", no_argument, NULL, 'g'},
539 };
540 int c, oidx = 0;
541
542 c = getopt_long(argc, argv, "a:s:P:r:43Eep:fdihlvbtg",
543 long_opts, &oidx);
544 if (c == EOF)
545 break;
546 switch(c) {
547 case 'a':
548 address = strtoul(optarg, NULL, 0);
549 break;
550 case 's':
551 read_size = write_size = strtoul(optarg, NULL, 0);
552 break;
553 case 'P':
554 part_name = strdup(optarg);
555 break;
556 case '4':
557 enable_4B = true;
558 break;
559 case '3':
560 disable_4B = true;
561 break;
562 case 'r':
563 do_read = true;
564 read_file = strdup(optarg);
565 break;
566 case 'E':
567 erase_all = erase = true;
568 break;
569 case 'e':
570 erase = true;
571 break;
572 case 'p':
573 program = true;
574 write_file = strdup(optarg);
575 break;
576 case 'f':
577 must_confirm = false;
578 break;
579 case 'd':
580 must_confirm = false;
581 dummy_run = true;
582 break;
583 case 'i':
584 info = true;
585 break;
586 case 'l':
587 use_lpc = true;
588 break;
589 case 'b':
590 bmc_flash = true;
591 break;
592 case 't':
593 tune = true;
594 break;
595 case 'v':
596 show_version = true;
597 break;
598 case 'h':
599 show_help = show_version = true;
600 break;
601 case 'g':
602 libflash_debug = true;
603 break;
604 default:
605 exit(1);
606 }
607 }
608
609 /* Check if we need to access the flash at all (which will
610 * also tune them as a side effect
611 */
612 no_action = !erase && !program && !info && !do_read &&
613 !enable_4B && !disable_4B && !tune;
614
615 /* Nothing to do, if we didn't already, print usage */
616 if (no_action && !show_version)
617 show_help = show_version = true;
618
619 if (show_version)
620 print_version();
621 if (show_help)
622 print_help(pname);
623
624 if (no_action)
625 return 0;
626
627 /* --enable-4B and --disable-4B are mutually exclusive */
628 if (enable_4B && disable_4B) {
629 fprintf(stderr, "--enable-4B and --disable-4B are mutually"
630 " exclusive !\n");
631 exit(1);
632 }
633
634 /* 4B not supported on BMC flash */
635 if (enable_4B && bmc_flash) {
636 fprintf(stderr, "--enable-4B not supported on BMC flash !\n");
637 exit(1);
638 }
639
640 /* partitions not supported on BMC flash */
641 if (part_name && bmc_flash) {
642 fprintf(stderr, "--partition not supported on BMC flash !\n");
643 exit(1);
644 }
645
646 /* part-name and erase-all make no sense together */
647 if (part_name && erase_all) {
648 fprintf(stderr, "--partition and --erase-all are mutually"
649 " exclusive !\n");
650 exit(1);
651 }
652
653 /* Read command should always come with a file */
654 if (do_read && !read_file) {
655 fprintf(stderr, "Read with no file specified !\n");
656 exit(1);
657 }
658
659 /* Program command should always come with a file */
660 if (program && !write_file) {
661 fprintf(stderr, "Program with no file specified !\n");
662 exit(1);
663 }
664
665 /* If both partition and address specified, error out */
666 if (address && part_name) {
667 fprintf(stderr, "Specify partition or address, not both !\n");
668 exit(1);
669 }
670
671 /* If file specified but not size, get size from file
672 */
673 if (write_file && !write_size) {
674 struct stat stbuf;
675
676 if (stat(write_file, &stbuf)) {
677 perror("Failed to get file size");
678 exit(1);
679 }
680 write_size = stbuf.st_size;
681 }
682
683 /* Check platform */
684 check_platform(&has_sfc, &has_ast);
685
686 /* Prepare for access */
687 if (bmc_flash) {
688 if (!has_ast) {
689 fprintf(stderr, "No BMC on this platform\n");
690 exit(1);
691 }
692 flash_access_setup_bmc(use_lpc, erase || program);
693 } else {
694 if (!has_ast && !has_sfc) {
695 fprintf(stderr, "No BMC nor SFC on this platform\n");
696 exit(1);
697 }
698 flash_access_setup_pnor(use_lpc, has_sfc, erase || program);
699 }
700
701 rc = flash_get_info(fl_chip, &fl_name,
702 &fl_total_size, &fl_erase_granule);
703 if (rc) {
704 fprintf(stderr, "Error %d getting flash info\n", rc);
705 exit(1);
706 }
707
708 /* If -t is passed, then print a nice message */
709 if (tune)
710 printf("Flash and controller tuned\n");
711
712 /* If read specified and no read_size, use flash size */
713 if (do_read && !read_size && !part_name)
714 read_size = fl_total_size;
715
716 /* We have a partition specified, grab the details */
717 if (part_name)
718 lookup_partition(part_name);
719
720 /* We have a partition, adjust read/write size if needed */
721 if (ffsh && ffs_index >= 0) {
722 uint32_t pstart, pmaxsz, pactsize;
723 int rc;
724
725 rc = ffs_part_info(ffsh, ffs_index, NULL,
726 &pstart, &pmaxsz, &pactsize);
727 if (rc) {
728 fprintf(stderr,"Failed to get partition info\n");
729 exit(1);
730 }
731
732 /* Read size is obtained from partition "actual" size */
733 if (!read_size)
734 read_size = pactsize;
735
736 /* Write size is max size of partition */
737 if (!write_size)
738 write_size = pmaxsz;
739
740 /* Crop write size to partition size */
741 if (write_size > pmaxsz) {
742 printf("WARNING: Size (%d bytes) larger than partition"
743 " (%d bytes), cropping to fit\n",
744 write_size, pmaxsz);
745 write_size = pmaxsz;
746 }
747
748 /* If erasing, check partition alignment */
749 if (erase && ((pstart | pmaxsz) & 0xfff)) {
750 fprintf(stderr,"Partition not aligned properly\n");
751 exit(1);
752 }
753
754 /* Set address */
755 address = pstart;
756 }
757
758 /* Align erase boundaries */
759 if (erase && !erase_all) {
760 uint32_t mask = 0xfff;
761 uint32_t erase_end;
762
763 /* Dummy size for erase, will be adjusted later */
764 if (!write_size)
765 write_size = 1;
766 erase_start = address & ~mask;
767 erase_end = ((address + write_size) + mask) & ~mask;
768 erase_size = erase_end - erase_start;
769
770 if (erase_start != address || erase_size != write_size)
771 fprintf(stderr, "WARNING: Erase region adjusted"
772 " to 0x%08x..0x%08x\n",
773 erase_start, erase_end);
774 }
775
776 /* Process commands */
777 if (enable_4B)
778 enable_4B_addresses();
779 if (disable_4B)
780 disable_4B_addresses();
781 if (info)
782 print_flash_info();
783 if (do_read)
784 do_read_file(read_file, address, read_size);
785 if (erase_all)
786 erase_chip();
787 else if (erase)
788 erase_range(erase_start, erase_size, program);
789 if (program)
790 program_file(write_file, address, write_size);
791
792 return 0;
793}