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/include/flash.h b/include/flash.h
index db47219..b411f34 100644
--- a/include/flash.h
+++ b/include/flash.h
@@ -339,6 +339,14 @@
 
 typedef int (*chip_restore_fn_cb_t)(struct flashctx *flash, uint8_t status);
 
+struct flashprog_progress {
+	flashprog_progress_callback *callback;
+	enum flashprog_progress_stage stage;
+	size_t current;
+	size_t total;
+	void *user_data;
+};
+
 struct flashprog_flashctx {
 	struct flashchip *chip;
 	/* FIXME: The memory mappings should be saved in a more structured way. */
@@ -375,6 +383,8 @@
 		chip_restore_fn_cb_t func;
 		uint8_t status;
 	} chip_restore_fn[MAX_CHIP_RESTORE_FUNCTIONS];
+
+	struct flashprog_progress progress;
 };
 
 /* Timing used in probe routines. ZERO is -2 to differentiate between an unset
@@ -438,6 +448,7 @@
 int erase_flash(struct flashctx *flash);
 struct registered_master;
 int probe_flash(struct registered_master *mst, int startchip, struct flashctx *fill_flash, int force);
+int flashprog_read_range(struct flashctx *, uint8_t *buf, unsigned int start, unsigned int len);
 int verify_range(struct flashctx *flash, const uint8_t *cmpbuf, unsigned int start, unsigned int len);
 void emergency_help_message(void);
 void list_programmers_linebreak(int startcol, int cols, int paren);
@@ -471,6 +482,7 @@
 int close_logfile(void);
 void start_logging(void);
 int flashprog_print_cb(enum flashprog_log_level level, const char *fmt, va_list ap);
+void flashprog_progress_cb(enum flashprog_progress_stage, size_t current, size_t total, void *user_data);
 /* Let gcc and clang check for correct printf-style format strings. */
 int print(enum flashprog_log_level level, const char *fmt, ...)
 #ifdef __MINGW32__
@@ -499,6 +511,7 @@
 #define msg_gspew(...)	print(FLASHPROG_MSG_SPEW, __VA_ARGS__)	/* general debug spew  */
 #define msg_pspew(...)	print(FLASHPROG_MSG_SPEW, __VA_ARGS__)	/* programmer debug spew  */
 #define msg_cspew(...)	print(FLASHPROG_MSG_SPEW, __VA_ARGS__)	/* chip debug spew  */
+void flashprog_progress_add(struct flashprog_flashctx *, size_t progress);
 
 /* spi.c */
 struct spi_command {
diff --git a/include/libflashprog.h b/include/libflashprog.h
index 9c39f5f..40050e3 100644
--- a/include/libflashprog.h
+++ b/include/libflashprog.h
@@ -51,6 +51,14 @@
 int flashprog_flash_erase(struct flashprog_flashctx *);
 void flashprog_flash_release(struct flashprog_flashctx *);
 
+enum flashprog_progress_stage {
+	FLASHPROG_PROGRESS_READ,
+	FLASHPROG_PROGRESS_WRITE,
+	FLASHPROG_PROGRESS_ERASE,
+};
+typedef void(flashprog_progress_callback)(enum flashprog_progress_stage, size_t current, size_t total, void *user_data);
+void flashprog_set_progress_callback(struct flashprog_flashctx *, flashprog_progress_callback *, void *user_data);
+
 /** @ingroup flashprog-flash */
 enum flashprog_flag {
 	FLASHPROG_FLAG_FORCE,