Richard Hughes has uploaded this change for review.

View Change

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);

To view, visit change 49643. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: flashrom
Gerrit-Branch: master
Gerrit-Change-Id: I7197572bb7f19e3bdb2bde855d70a0f50fd3854c
Gerrit-Change-Number: 49643
Gerrit-PatchSet: 1
Gerrit-Owner: Richard Hughes <richard@hughsie.com>
Gerrit-MessageType: newchange