libflashrom: Return progress state to the library user

Projects using libflashrom like fwupd expect the user to wait for the
operation to complete. To avoid the user thinking the process has
"hung" or "got stuck" report back the progress complete of the erase,
write and read operations.

Add a new --progress flag to the CLI to report progress of operations.

Include a test for the dummy spi25 device.

Tested: ./test_build.sh; ./flashrom -p lspcon_i2c_spi:bus=7 -r /dev/null --progress

flashrom-stable:
* Closer to original libflashrom API.
* Split update_progress() into progress_start/_set/_add/_finish:
  Simplifies progress calls scattered through the code base. We let
  the core code in `flashprog.c` handle the total progress. Only API
  is flashprog_progress_add().  Erase progress is completely handled
  in `flashprog.c`. Fine grained read/write progress can be reported
  at the chip/programmer level.
* Add calls to all chip read/write paths and opaque programmers
  except for read_memmapped() (which is handled in follow ups).
* At least one wrinkle left: Erasing unaligned regions will slightly
  overshoot total progress.

Change-Id: I7197572bb7f19e3bdb2bde855d70a0f50fd3854c
Signed-off-by: Richard Hughes <richard@hughsie.com>
Signed-off-by: Daniel Campello <campello@chromium.org>
Signed-off-by: Nico Huber <nico.h@gmx.de>
Original-Reviewed-on: https://review.coreboot.org/c/flashrom/+/49643
Original-Reviewed-by: Edward O'Callaghan <quasisec@chromium.org>
Original-Reviewed-by: Anastasia Klimchuk <aklm@chromium.org>
Original-Reviewed-by: Thomas Heijligen <src@posteo.de>
Reviewed-on: https://review.sourcearcade.org/c/flashprog/+/74731
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
diff --git a/cli_classic.c b/cli_classic.c
index fede2ca..ab5f8b1 100644
--- a/cli_classic.c
+++ b/cli_classic.c
@@ -70,6 +70,7 @@
 #if CONFIG_PRINT_WIKI == 1
 	       " -z | --list-supported-wiki         print supported devices in wiki syntax\n"
 #endif
+	       "      --progress                    show progress percentage on the standard output\n"
 	       " -p | --programmer <name>[:<param>] specify the programmer device. One of\n");
 	list_programmers_linebreak(4, 80, 0);
 	printf(".\n\nYou can specify one of -h, -R, -L, "
@@ -219,6 +220,7 @@
 	bool read_it = false, write_it = false, erase_it = false, verify_it = false;
 	bool dont_verify_it = false, dont_verify_all = false;
 	bool list_supported = false;
+	bool show_progress = false;
 	struct flashprog_layout *layout = NULL;
 	static const struct programmer_entry *prog = NULL;
 	enum {
@@ -228,6 +230,7 @@
 		OPTION_FLASH_CONTENTS,
 		OPTION_FLASH_NAME,
 		OPTION_FLASH_SIZE,
+		OPTION_PROGRESS,
 	};
 	int ret = 0;
 
@@ -258,6 +261,7 @@
 		{"help",		0, NULL, 'h'},
 		{"version",		0, NULL, 'R'},
 		{"output",		1, NULL, 'o'},
+		{"progress",		0, NULL, OPTION_PROGRESS},
 		{NULL,			0, NULL, 0},
 	};
 
@@ -474,6 +478,9 @@
 				cli_classic_abort_usage("No log filename specified.\n");
 			}
 			break;
+		case OPTION_PROGRESS:
+			show_progress = true;
+			break;
 		default:
 			cli_classic_abort_usage(NULL);
 			break;
@@ -649,6 +656,9 @@
 
 	fill_flash = &flashes[0];
 
+	if (show_progress)
+		flashprog_set_progress_callback(fill_flash, &flashprog_progress_cb, NULL);
+
 	print_chip_support_status(fill_flash->chip);
 
 	if (max_decode_exceeded(matched_master, fill_flash) && !force) {