From 4e5ce4293a724bce9e1fa36c5e305bdbc85946bd Mon Sep 17 00:00:00 2001 From: Hsuan Ting Chen Date: Tue, 15 Sep 2020 15:30:00 +0800 Subject: vboot/ui: Force to reacquire log on initialization Force to reacquire a newer firmware log snapshot every time when the user enters the firmware log screen. Re-entering (e.g. back from language selection or debug info tab) will still show the cached firmware log string. BUG=b:146399181, b:168442372 TEST=make clean && make runtests TEST=Build locally, navigate to the firmware log screen, go back, and enter the firmware log screen again. BRANCH=none Cq-Depend: chromium:2409742 Change-Id: I8c3eea23446c58603ce698a86f1aca4b264ebb0e Signed-off-by: Hsuan Ting Chen Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/2411761 Commit-Queue: Yu-Ping Wu --- firmware/2lib/2stub.c | 2 +- firmware/2lib/2ui_screens.c | 4 +- firmware/2lib/include/2api.h | 8 ++-- tests/vb2_ui_tests.c | 90 ++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 95 insertions(+), 9 deletions(-) diff --git a/firmware/2lib/2stub.c b/firmware/2lib/2stub.c index 697b0fc5..dba852e1 100644 --- a/firmware/2lib/2stub.c +++ b/firmware/2lib/2stub.c @@ -81,7 +81,7 @@ const char *vb2ex_get_debug_info(struct vb2_context *ctx) } __attribute__((weak)) -const char *vb2ex_get_firmware_log(void) +const char *vb2ex_get_firmware_log(int reset) { return NULL; } diff --git a/firmware/2lib/2ui_screens.c b/firmware/2lib/2ui_screens.c index 6cdae95a..3e7ead2a 100644 --- a/firmware/2lib/2ui_screens.c +++ b/firmware/2lib/2ui_screens.c @@ -314,7 +314,7 @@ static const struct vb2_screen_info debug_info_screen = { static vb2_error_t firmware_log_init(struct vb2_ui_context *ui) { - const char *log_string = vb2ex_get_firmware_log(); + const char *log_string = vb2ex_get_firmware_log(1); if (!log_string) { VB2_DEBUG("ERROR: Failed to retrieve firmware log\n"); ui->error_code = VB2_UI_ERROR_FIRMWARE_LOG; @@ -334,7 +334,7 @@ static vb2_error_t firmware_log_init(struct vb2_ui_context *ui) static vb2_error_t firmware_log_reinit(struct vb2_ui_context *ui) { - const char *log_string = vb2ex_get_firmware_log(); + const char *log_string = vb2ex_get_firmware_log(0); if (!log_string) { VB2_DEBUG("ERROR: Failed to retrieve firmware log\n"); ui->error_code = VB2_UI_ERROR_FIRMWARE_LOG; diff --git a/firmware/2lib/include/2api.h b/firmware/2lib/include/2api.h index dc661675..9f4dbcb9 100644 --- a/firmware/2lib/include/2api.h +++ b/firmware/2lib/include/2api.h @@ -1440,12 +1440,14 @@ char *vb2api_get_debug_info(struct vb2_context *ctx); * * Return a pointer to the full firmware log string which is guaranteed to be * null-terminated. The function implementation should snapshot the full - * firmware log when it is called the first time. Subsequent calls should - * return the same pointer. + * firmware log when it is called. If `reset` is not zero, it will reset the + * firmware log snapshot. * + * @param reset Discard the current firmware log snapshot and + * reacquire a new one. * @return The pointer to the full firmware log string. NULL on error. */ -const char *vb2ex_get_firmware_log(void); +const char *vb2ex_get_firmware_log(int reset); /** * Specify the string to be used for an upcoming log screen display. diff --git a/tests/vb2_ui_tests.c b/tests/vb2_ui_tests.c index 66916602..5dc1a2e7 100644 --- a/tests/vb2_ui_tests.c +++ b/tests/vb2_ui_tests.c @@ -91,6 +91,11 @@ static int mock_pp_pressed_total; static int mock_enable_dev_mode; +#define MOCK_PREPARE_LOG_SIZE 32 + +static int mock_snapshot_count; +static char mock_prepare_log[64][MOCK_PREPARE_LOG_SIZE]; +static int mock_prepare_log_count; static uint32_t mock_log_page_count; static void add_mock_key(uint32_t press, int trusted) @@ -321,6 +326,8 @@ static void reset_common_data(enum reset_type t) mock_enable_dev_mode = 0; /* For vb2ex_prepare_log_screen */ + mock_snapshot_count = 0; + mock_prepare_log_count = 0; mock_log_page_count = 1; /* Avoid Iteration #0 */ @@ -526,17 +533,26 @@ const char *vb2ex_get_debug_info(struct vb2_context *c) return "mocked debug info"; } -const char *vb2ex_get_firmware_log(void) +const char *vb2ex_get_firmware_log(int reset) { - return "mocked firmware log"; + static char mock_firmware_log_buf[MOCK_PREPARE_LOG_SIZE]; + if (reset) + mock_snapshot_count++; + snprintf(mock_firmware_log_buf, MOCK_PREPARE_LOG_SIZE, + "%d", mock_snapshot_count); + return mock_firmware_log_buf; } uint32_t vb2ex_prepare_log_screen(const char *str) { + if (mock_prepare_log_count < ARRAY_SIZE(mock_prepare_log)) + strncpy(mock_prepare_log[mock_prepare_log_count], + str, MOCK_PREPARE_LOG_SIZE); + mock_prepare_log_count++; + return mock_log_page_count; } - /* Tests */ static void developer_tests(void) { @@ -1168,6 +1184,73 @@ static void debug_info_tests(void) VB2_DEBUG("...done.\n"); } +static void firmware_log_tests(void) +{ + VB2_DEBUG("Testing firmware log screens...\n"); + + /* Get firmware log */ + reset_common_data(FOR_MANUAL_RECOVERY); + add_mock_keypress(VB_KEY_DOWN); + add_mock_keypress(VB_KEY_DOWN); + if (DIAGNOSTIC_UI) + add_mock_keypress(VB_KEY_DOWN); + add_mock_keypress(VB_KEY_ENTER); + add_mock_keypress(VB_KEY_DOWN); + add_mock_keypress(VB_KEY_DOWN); + add_mock_keypress(VB_KEY_ENTER); + TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN, + "get firmware log"); + TEST_EQ(mock_prepare_log_count, 1, + " prepared firmware log once"); + TEST_EQ(strcmp(mock_prepare_log[0], "1"), 0, + " got correct firmware log"); + + /* Enter firmware log screen again will reacquire a newer one */ + reset_common_data(FOR_MANUAL_RECOVERY); + add_mock_keypress(VB_KEY_DOWN); + add_mock_keypress(VB_KEY_DOWN); + if (DIAGNOSTIC_UI) + add_mock_keypress(VB_KEY_DOWN); + add_mock_keypress(VB_KEY_ENTER); + add_mock_keypress(VB_KEY_DOWN); + add_mock_keypress(VB_KEY_DOWN); + add_mock_keypress(VB_KEY_ENTER); + add_mock_keypress(VB_KEY_ESC); + add_mock_keypress(VB_KEY_ENTER); + TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN, + "enter the screen again and reacquire a new log"); + TEST_EQ(mock_prepare_log_count, 2, + " prepared firmware log twice"); + TEST_EQ(strcmp(mock_prepare_log[0], "1"), 0, + " got correct firmware log"); + TEST_EQ(strcmp(mock_prepare_log[1], "2"), 0, + " got a new firmware log"); + + /* Back to firmware log screen again will not reacquire a newer one */ + reset_common_data(FOR_MANUAL_RECOVERY); + add_mock_keypress(VB_KEY_DOWN); + add_mock_keypress(VB_KEY_DOWN); + if (DIAGNOSTIC_UI) + add_mock_keypress(VB_KEY_DOWN); + add_mock_keypress(VB_KEY_ENTER); + add_mock_keypress(VB_KEY_DOWN); + add_mock_keypress(VB_KEY_DOWN); + add_mock_keypress(VB_KEY_ENTER); + add_mock_keypress('\t'); /* enter debug info screen */ + add_mock_keypress(VB_KEY_ESC); + TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN, + "back to the screen and do not reacquire a new log"); + TEST_EQ(mock_prepare_log_count, 3, + " prepared firmware log three times"); + TEST_EQ(strcmp(mock_prepare_log[0], "1"), 0, + " got correct firmware log"); + /* Skip entry #1 which is for preparing debug info */ + TEST_EQ(strcmp(mock_prepare_log[2], "1"), 0, + " got the same firmware log"); + + VB2_DEBUG("...done.\n"); +} + static void developer_screen_tests(void) { VB2_DEBUG("Testing developer mode screens...\n"); @@ -1669,6 +1752,7 @@ int main(void) manual_recovery_tests(); language_selection_tests(); debug_info_tests(); + firmware_log_tests(); /* Screen displayed */ developer_screen_tests(); -- cgit v1.2.1