diff options
author | Cyril Bur <cyril.bur@au1.ibm.com> | 2015-06-18 17:08:26 +1000 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2015-06-19 07:37:36 +1000 |
commit | ff33d18c92b794a3343cbed2b3f79f0f31c87760 (patch) | |
tree | ec8a688eaa6dde4f48c8bd2ca9aecbe0369a5866 /external | |
parent | 0872bb0ab8c865a2c5feeae7d0493aff4ed8ebc5 (diff) | |
download | skiboot-ff33d18c92b794a3343cbed2b3f79f0f31c87760.zip skiboot-ff33d18c92b794a3343cbed2b3f79f0f31c87760.tar.gz skiboot-ff33d18c92b794a3343cbed2b3f79f0f31c87760.tar.bz2 |
external/pflash: Add --clear command
The current pflash --erase command simply sets all the bits of the flash
back to 1 and When hostboot decides to gard everything there isn't a
useful way to get the machine booting again as even --eraseing the GUARD
partition won't leave the necessary ECC bits.
The --clear command will erase the specified partition and then fill in the
ECC bits.
Signed-off-by: Cyril Bur <cyril.bur@au1.ibm.com>
Reviewed-by: Samuel Mendoza-Jonas <sam.mj@au1.ibm.com>
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'external')
-rw-r--r-- | external/pflash/pflash.c | 52 |
1 files changed, 47 insertions, 5 deletions
diff --git a/external/pflash/pflash.c b/external/pflash/pflash.c index 2bea98f..8a86517 100644 --- a/external/pflash/pflash.c +++ b/external/pflash/pflash.c @@ -271,6 +271,25 @@ static void erase_range(uint32_t start, uint32_t size, bool will_program) } } +static void set_ecc(uint32_t start, uint32_t size) +{ + uint32_t i = start + 8; + uint8_t ecc = 0; + + printf("About to erase and set ECC bits in region 0x%08x to 0x%08x\n", start, start + size); + check_confirm(); + erase_range(start, size, true); + + printf("Programming ECC bits...\n"); + progress_init(size); + while (i < start + size) { + blocklevel_write(bl, i, &ecc, sizeof(ecc)); + i += 9; + progress_tick(i - start); + } + progress_end(); +} + static void program_file(const char *file, uint32_t start, uint32_t size) { int fd, rc; @@ -554,6 +573,10 @@ static void print_help(const char *pname) printf("\t-t, --tune\n"); printf("\t\tJust tune the flash controller & access size\n"); printf("\t\t(Implicit for all other operations)\n\n"); + printf("\t-c --clear\n"); + printf("\t\tUsed to ECC clear a partition of the flash\n"); + printf("\t\tMust be used in conjunction with -P. Will erase the\n"); + printf("\t\tpartition and then set all the ECC bits as they should be\n\n"); printf("\t-i, --info\n"); printf("\t\tDisplay some information about the flash.\n\n"); printf("\t-h, --help\n"); @@ -565,7 +588,7 @@ int main(int argc, char *argv[]) const char *pname = argv[0]; uint32_t address = 0, read_size = 0, write_size = 0; uint32_t erase_start = 0, erase_size = 0; - bool erase = false; + bool erase = false, do_clear = false; bool program = false, erase_all = false, info = false, do_read = false; bool enable_4B = false, disable_4B = false, use_lpc = true; bool show_help = false, show_version = false; @@ -597,10 +620,11 @@ int main(int argc, char *argv[]) {"debug", no_argument, NULL, 'g'}, {"side", required_argument, NULL, 'S'}, {"toc", required_argument, NULL, 'T'}, + {"clear", no_argument, NULL, 'c'} }; int c, oidx = 0; - c = getopt_long(argc, argv, "a:s:P:r:43Eep:fdihlvbtgS:T:", + c = getopt_long(argc, argv, "a:s:P:r:43Eep:fdihlvbtgS:T:c", long_opts, &oidx); if (c == EOF) break; @@ -669,6 +693,9 @@ int main(int argc, char *argv[]) ffs_toc_seen = true; ffs_toc = strtoul(optarg, NULL, 0); break; + case 'c': + do_clear = true; + break; default: exit(1); } @@ -678,7 +705,7 @@ int main(int argc, char *argv[]) * also tune them as a side effect */ no_action = !erase && !program && !info && !do_read && - !enable_4B && !disable_4B && !tune; + !enable_4B && !disable_4B && !tune && !do_clear; /* Nothing to do, if we didn't already, print usage */ if (no_action && !show_version) @@ -736,6 +763,11 @@ int main(int argc, char *argv[]) exit(1); } + if (do_clear && !part_name) { + fprintf(stderr, "--clear only supported on a partition name\n"); + exit(1); + } + /* Explicitly only support two sides */ if (flash_side != 0 && flash_side != 1) { fprintf(stderr, "Unexpected value for --side '%d'\n", flash_side); @@ -799,15 +831,24 @@ int main(int argc, char *argv[]) /* We have a partition, adjust read/write size if needed */ if (ffsh && ffs_index >= 0) { uint32_t pstart, pmaxsz, pactsize; + bool ecc; int rc; rc = ffs_part_info(ffsh, ffs_index, NULL, - &pstart, &pmaxsz, &pactsize, NULL); + &pstart, &pmaxsz, &pactsize, &ecc); if (rc) { fprintf(stderr,"Failed to get partition info\n"); exit(1); } + if (!ecc && do_clear) { + fprintf(stderr, "The partition on which to do --clear " + "does not have ECC, are you sure?\n"); + check_confirm(); + /* Still confirm later on */ + must_confirm = true; + } + /* Read size is obtained from partition "actual" size */ if (!read_size) read_size = pactsize; @@ -873,6 +914,7 @@ int main(int argc, char *argv[]) erase_range(erase_start, erase_size, program); if (program) program_file(write_file, address, write_size); - + if (do_clear) + set_ecc(address, write_size); return 0; } |