aboutsummaryrefslogtreecommitdiff
path: root/external
diff options
context:
space:
mode:
authorCyril Bur <cyril.bur@au1.ibm.com>2017-07-28 16:46:34 +1000
committerStewart Smith <stewart@linux.vnet.ibm.com>2017-08-01 13:57:56 +1000
commitae6cb86c277e6a9b1d11548d8fa1b430116dba08 (patch)
treeab2d2f81c9cd5936022ed8a5d773d7bb0f98015c /external
parent4915837a7b7f482c0d4561061e01f5e998e65120 (diff)
downloadskiboot-ae6cb86c277e6a9b1d11548d8fa1b430116dba08.zip
skiboot-ae6cb86c277e6a9b1d11548d8fa1b430116dba08.tar.gz
skiboot-ae6cb86c277e6a9b1d11548d8fa1b430116dba08.tar.bz2
external/pflash: Reinstate the progress bars
Recent work did some optimising which unfortunately removed some of the progress bars in pflash. It turns out that there's only one thing people prefer to correctly programmed flash chips, it is the ability to watch little equals characters go across their screens for potentially minutes. Personally I don't understand the appeal but I have received strongly worded requests for the reinstatement of the progress bars in pflash and I fear for the stability of our society if pflash doesn't promptly regain its most unimportant feature. Signed-off-by: Cyril Bur <cyril.bur@au1.ibm.com> Reviewed-by: Samuel Mendoza-Jonas <sam@mendozajonas.com> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'external')
-rw-r--r--external/pflash/pflash.c79
1 files changed, 63 insertions, 16 deletions
diff --git a/external/pflash/pflash.c b/external/pflash/pflash.c
index eadc650..a08ea94 100644
--- a/external/pflash/pflash.c
+++ b/external/pflash/pflash.c
@@ -256,17 +256,18 @@ static struct ffs_handle *lookup_partition_at_side(struct flash_details *flash,
return lookup_partition_at_toc(flash, name, index);
}
-static int erase_chip(struct blocklevel_device *bl)
+static int erase_chip(struct flash_details *flash)
{
bool confirm;
int rc;
+ uint64_t pos;
printf("About to erase chip !\n");
confirm = check_confirm();
if (!confirm)
return 1;
- printf("Erasing... (may take a while !) ");
+ printf("Erasing... (may take a while)\n");
fflush(stdout);
if (dummy_run) {
@@ -274,20 +275,33 @@ static int erase_chip(struct blocklevel_device *bl)
return 1;
}
- rc = arch_flash_erase_chip(bl);
+ /*
+ * We could use arch_flash_erase_chip() here BUT everyone really
+ * likes the progress bars.
+ * Lets do an erase block at a time erase then...
+ */
+ progress_init(flash->total_size);
+ for (pos = 0; pos < flash->total_size; pos += flash->erase_granule) {
+ rc = blocklevel_erase(flash->bl, pos, flash->erase_granule);
+ if (rc)
+ break;
+ progress_tick(pos);
+ }
+ progress_end();
if (rc) {
fprintf(stderr, "Error %d erasing chip\n", rc);
- return 1;
+ return rc;
}
printf("done !\n");
return 0;
}
-static int erase_range(struct blocklevel_device *bl,
+static int erase_range(struct flash_details *flash,
uint32_t start, uint32_t size, bool will_program,
struct ffs_handle *ffsh, int ffs_index)
{
+ uint32_t done = 0, erase_mask = flash->erase_granule - 1;
bool confirm;
int rc;
@@ -302,12 +316,45 @@ static int erase_range(struct blocklevel_device *bl,
}
printf("Erasing...\n");
- rc = blocklevel_smart_erase(bl, start, size);
- if (rc) {
- fprintf(stderr, "Failed to blocklevel_smart_erase(): %d\n", rc);
- return 1;
+ /*
+ * blocklevel_smart_erase() can do the entire thing in one call
+ * BUT everyone really likes progress bars so break stuff up
+ */
+ progress_init(size);
+ if (start & erase_mask) {
+ /* Align to next erase block */
+ rc = blocklevel_smart_erase(flash->bl, start,
+ flash->erase_granule - (start & erase_mask));
+ if (rc) {
+ fprintf(stderr, "Failed to blocklevel_smart_erase(): %d\n", rc);
+ return 1;
+ }
+ start += flash->erase_granule - (start & erase_mask);
+ size -= flash->erase_granule - (start & erase_mask);
+ done = flash->erase_granule - (start & erase_mask);
}
-
+ progress_tick(done);
+ while (size & ~(erase_mask)) {
+ rc = blocklevel_smart_erase(flash->bl, start, flash->erase_granule);
+ if (rc) {
+ fprintf(stderr, "Failed to blocklevel_smart_erase(): %d\n", rc);
+ return 1;
+ }
+ start += flash->erase_granule;
+ size -= flash->erase_granule;
+ done += flash->erase_granule;
+ progress_tick(done);
+ }
+ if (size) {
+ rc = blocklevel_smart_erase(flash->bl, start, size);
+ if (rc) {
+ fprintf(stderr, "Failed to blocklevel_smart_erase(): %d\n", rc);
+ return 1;
+ }
+ done += size;
+ progress_tick(done);
+ }
+ progress_end();
/* If this is a flash partition, mark it empty if we aren't
* going to program over it as well
*/
@@ -318,7 +365,7 @@ static int erase_range(struct blocklevel_device *bl,
return 0;
}
-static int set_ecc(struct blocklevel_device *bl, uint32_t start, uint32_t size)
+static int set_ecc(struct flash_details *flash, uint32_t start, uint32_t size)
{
uint32_t i = start + 8;
uint8_t ecc = 0;
@@ -329,12 +376,12 @@ static int set_ecc(struct blocklevel_device *bl, uint32_t start, uint32_t size)
if (!confirm)
return 1;
- erase_range(bl, start, size, true, NULL, 0);
+ erase_range(flash, start, size, true, NULL, 0);
printf("Programming ECC bits...\n");
progress_init(size);
while (i < start + size) {
- blocklevel_write(bl, i, &ecc, sizeof(ecc));
+ blocklevel_write(flash->bl, i, &ecc, sizeof(ecc));
i += 9;
progress_tick(i - start);
}
@@ -1071,15 +1118,15 @@ int main(int argc, char *argv[])
if (do_read)
rc = do_read_file(flash.bl, read_file, address, read_size);
if (!rc && erase_all)
- rc = erase_chip(flash.bl);
+ rc = erase_chip(&flash);
else if (!rc && erase)
- rc = erase_range(flash.bl, address, write_size,
+ rc = erase_range(&flash, address, write_size,
program, ffsh, ffs_index);
if (!rc && program)
rc = program_file(flash.bl, write_file, address, write_size,
ffsh, ffs_index);
if (!rc && do_clear)
- rc = set_ecc(flash.bl, address, write_size);
+ rc = set_ecc(&flash, address, write_size);
close:
if (flash.need_relock)