Richard Hughes has uploaded this change for review. ( https://review.coreboot.org/c/flashrom/+/49643 )
Change subject: libflashrom: Return progress state to the library user ......................................................................
libflashrom: Return progress state to the library user
Include test for the dummy spi25 device.
Change-Id: I7197572bb7f19e3bdb2bde855d70a0f50fd3854c Signed-off-by: Richard Hughes richard@hughsie.com --- M flash.h M libflashrom.c M libflashrom.h M spi.c M spi25.c M tests/spi25.c M tests/tests.c M tests/tests.h 8 files changed, 85 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/43/49643/1
diff --git a/flash.h b/flash.h index 883b6f4..66010ce 100644 --- a/flash.h +++ b/flash.h @@ -285,6 +285,9 @@ chip_restore_fn_cb_t func; uint8_t status; } chip_restore_fn[MAX_CHIP_RESTORE_FUNCTIONS]; + /* Progress reporting */ + flashrom_progress_callback *progress_callback; + void *progress_userdata; };
/* Timing used in probe routines. ZERO is -2 to differentiate between an unset @@ -415,6 +418,7 @@ #define msg_gspew(...) print(FLASHROM_MSG_SPEW, __VA_ARGS__) /* general debug spew */ #define msg_pspew(...) print(FLASHROM_MSG_SPEW, __VA_ARGS__) /* programmer debug spew */ #define msg_cspew(...) print(FLASHROM_MSG_SPEW, __VA_ARGS__) /* chip debug spew */ +void set_progress(struct flashctx *flash, enum flashrom_progress_stage stage, size_t current, size_t total);
/* layout.c */ int register_include_arg(struct layout_include_args **args, char *name); diff --git a/libflashrom.c b/libflashrom.c index ae2d33d..10d8882 100644 --- a/libflashrom.c +++ b/libflashrom.c @@ -95,6 +95,29 @@ return 0; }
+/** + * @brief Set the progress callback function. + * + * Set a callback function which will be invoked whenever libflashrom wants + * to indicate the progress has chaned. This allows frontends to do whatever + * they see fit with such values, e.g. update a progress bar in a GUI tool. + * + * @param progress_callback Pointer to the new progress callback function. + * @param userdata Userdata pointer to include with the progress callback. + */ +void flashrom_set_progress_callback(struct flashrom_flashctx *flashctx, flashrom_progress_callback *progress_callback, void *progress_userdata) +{ + flashctx->progress_callback = progress_callback; + flashctx->progress_userdata = progress_userdata; +} +/** @private */ +void set_progress(struct flashrom_flashctx *flashctx, enum flashrom_progress_stage stage, size_t current, size_t total) +{ + if (flashctx->progress_callback == NULL) + return; + flashctx->progress_callback(flashctx, stage, current, total, flashctx->progress_userdata); +} + /** @} */ /* end flashrom-general */
diff --git a/libflashrom.h b/libflashrom.h index d0d5826..4f2474c 100644 --- a/libflashrom.h +++ b/libflashrom.h @@ -35,6 +35,13 @@ FLASHROM_MSG_DEBUG2 = 4, FLASHROM_MSG_SPEW = 5, }; + +/** @ingroup flashrom-general */ +enum flashrom_progress_stage { + FLASHROM_PROGRESS_READ, + FLASHROM_PROGRESS_WRITE, +}; + /** @ingroup flashrom-general */ typedef int(flashrom_log_callback)(enum flashrom_log_level, const char *format, va_list); void flashrom_set_log_callback(flashrom_log_callback *); @@ -93,6 +100,10 @@ int flashrom_flash_erase(struct flashrom_flashctx *); void flashrom_flash_release(struct flashrom_flashctx *);
+/** @ingroup flashrom-general */ +typedef void(flashrom_progress_callback)(struct flashrom_flashctx *flashctx, enum flashrom_progress_stage stage, size_t current, size_t total, void *user_data); +void flashrom_set_progress_callback(struct flashrom_flashctx *const flashctx, flashrom_progress_callback *, void *); + /** @ingroup flashrom-flash */ enum flashrom_flag { FLASHROM_FLAG_FORCE, diff --git a/spi.c b/spi.c index aed2a92..49b23fc 100644 --- a/spi.c +++ b/spi.c @@ -101,6 +101,8 @@ { int ret; size_t to_read; + size_t progress_start = start; + size_t progress_total = len - start; for (; len; len -= to_read, buf += to_read, start += to_read) { /* Do not cross 16MiB boundaries in a single transfer. This helps with @@ -110,6 +112,7 @@ ret = flash->mst->spi.read(flash, buf, start, to_read); if (ret) return ret; + set_progress(flash, FLASHROM_PROGRESS_READ, start - progress_start, progress_total); } return 0; } diff --git a/spi25.c b/spi25.c index 213273f..58f3936 100644 --- a/spi25.c +++ b/spi25.c @@ -669,11 +669,14 @@ { int ret; size_t to_read; + size_t progress_start = start; + size_t progress_total = len - start; for (; len; len -= to_read, buf += to_read, start += to_read) { to_read = min(chunksize, len); ret = spi_nbyte_read(flash, start, buf, to_read); if (ret) return ret; + set_progress(flash, FLASHROM_PROGRESS_READ, start - progress_start, progress_total); } return 0; } @@ -693,6 +696,8 @@ * we're OK for now. */ unsigned int page_size = flash->chip->page_size; + size_t progress_start = start; + size_t progress_total = len - start;
/* Warning: This loop has a very unusual condition and body. * The loop needs to go through each page with at least one affected @@ -717,6 +722,7 @@ if (rc) return rc; } + set_progress(flash, FLASHROM_PROGRESS_WRITE, start - progress_start, progress_total); }
return 0; @@ -736,6 +742,7 @@ for (i = start; i < start + len; i++) { if (spi_nbyte_program(flash, i, buf + i - start, 1)) return 1; + set_progress(flash, FLASHROM_PROGRESS_WRITE, i - start, len - start); } return 0; } diff --git a/tests/spi25.c b/tests/spi25.c index 942fe6e..2d4b18d 100644 --- a/tests/spi25.c +++ b/tests/spi25.c @@ -49,6 +49,41 @@ .write = NULL, };
+static void spi_read_progress_cb(struct flashrom_flashctx *flashctx, + enum flashrom_progress_stage stage, + size_t current, + size_t total, + void *user_data) +{ + uint32_t *cnt = (uint32_t *) user_data; + assert_int_equal(0x300, total); + (*cnt)++; +} + +void spi_read_chunked_test_success(void **state) +{ + (void) state; /* unused */ + uint8_t buf[0x400] = { 0x0 }; + uint32_t cnt = 0; + const unsigned int max_data_read = 0x100; + const unsigned int offset = 0x100; + struct registered_master mst = { .spi.read = default_spi_read, + .spi.max_data_read = max_data_read }; + + /* setup initial test state */ + struct flashctx flashctx = { .chip = &mock_chip, .mst = &mst }; + flashrom_set_progress_callback(&flashctx, spi_read_progress_cb, (void *) &cnt); + for (int i = 0; i < 4; i++) { + expect_memory(__wrap_spi_send_command, flash, + &flashctx, sizeof(flashctx)); + will_return(__wrap_spi_send_command, JEDEC_WRDI); + will_return(__wrap_spi_send_command, JEDEC_READ); + will_return(__wrap_spi_send_command, max_data_read); + } + assert_int_equal(0, spi_chip_read(&flashctx, buf, offset, sizeof(buf))); + assert_int_equal(5, cnt); +} + void spi_write_enable_test_success(void **state) { (void) state; /* unused */ diff --git a/tests/tests.c b/tests/tests.c index 3124607..e749f77 100644 --- a/tests/tests.c +++ b/tests/tests.c @@ -52,6 +52,7 @@ const struct CMUnitTest spi25_tests[] = { cmocka_unit_test(spi_write_enable_test_success), cmocka_unit_test(spi_write_disable_test_success), + cmocka_unit_test(spi_read_chunked_test_success), cmocka_unit_test(probe_spi_rdid_test_success), cmocka_unit_test(probe_spi_rdid4_test_success), cmocka_unit_test(probe_spi_rems_test_success), diff --git a/tests/tests.h b/tests/tests.h index cb905fd..cf8f0ba 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -31,6 +31,7 @@ /* spi25.c */ void spi_write_enable_test_success(void **state); void spi_write_disable_test_success(void **state); +void spi_read_chunked_test_success(void **state); void probe_spi_rdid_test_success(void **state); void probe_spi_rdid4_test_success(void **state); void probe_spi_rems_test_success(void **state);