diff --git a/include/libflashrom.h b/include/libflashrom.h index 96479ed5e..b9b0d1708 100644 --- a/include/libflashrom.h +++ b/include/libflashrom.h @@ -57,6 +57,20 @@ enum flashrom_log_level { FLASHROM_MSG_SPEW = 5, }; typedef int(flashrom_log_callback)(enum flashrom_log_level, const char *format, va_list); + +/** + * @brief Set the log level. + * + * Set a log level for messages from libflashrom. + * The print callback will be invoked only for messages + * with a log level less than or equal to the configured value. + * The default log level is FLASHROM_MSG_INFO. + * + * @param level The log level to be set. + */ + + void flashrom_set_log_level(enum flashrom_log_level level); + /** * @brief Set the log callback function. * diff --git a/libflashrom.c b/libflashrom.c index 5cc33b320..a9aff5019 100644 --- a/libflashrom.c +++ b/libflashrom.c @@ -3,6 +3,7 @@ * * Copyright (C) 2012, 2016 secunet Security Networks AG * (Written by Nico Huber for secunet) + * Copyright (C) 2025 Dmitry Zhadinets * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,6 +34,7 @@ static flashrom_log_callback *global_log_callback = NULL; static flashrom_log_callback_v2 *global_log_callback_v2 = NULL; static void *global_log_user_data = NULL; +static enum flashrom_log_level global_log_level = FLASHROM_MSG_INFO; int flashrom_init(const int perform_selfcheck) { @@ -46,8 +48,11 @@ int flashrom_shutdown(void) return 0; /* TODO: nothing to do? */ } -/* TODO: flashrom_set_loglevel()? do we need it? - For now, let the user decide in their callback. */ +void flashrom_set_log_level(enum flashrom_log_level level) +{ + global_log_level = level; +} + void flashrom_set_log_callback(flashrom_log_callback *const log_callback) { global_log_callback = log_callback; @@ -98,7 +103,7 @@ void flashrom_set_log_callback_v2(flashrom_log_callback_v2 *const log_callback, /** @private */ int print(const enum flashrom_log_level level, const char *const fmt, ...) { - if (global_log_callback) { + if (global_log_callback && level <= global_log_level) { int ret; va_list args; va_start(args, fmt); diff --git a/tests/libflashrom.c b/tests/libflashrom.c index 42a2da011..3320597cf 100644 --- a/tests/libflashrom.c +++ b/tests/libflashrom.c @@ -23,26 +23,22 @@ static int test_log_callback(enum flashrom_log_level level, const char *format, va_list vargs) { - /* check that loglevel has passed corectly */ - assert_int_equal(level, FLASHROM_MSG_INFO); char message[3] = {0}; vsnprintf(message, 3, format, vargs); assert_string_equal(message, "1\n"); - return 0x666 + 1; + return 0x666 + (int)level; } static void test_log_callback_v2(enum flashrom_log_level level, const char *message, void *user_data) { - /* check that loglevel has passed corectly */ - assert_int_equal(level, FLASHROM_MSG_ERROR); /* check that user dta has passed */ assert_ptr_not_equal(user_data, 0); /* check that user_data is correct */ assert_int_equal(*(int *)(user_data), 100500); /* check that format is working correctly */ assert_string_equal(message, "2\n"); - *(int*)user_data = 0x666 + 2; + *(int*)user_data = 0x666 + (int)level; } void flashrom_set_log_callback_test_success(void **state) @@ -50,7 +46,7 @@ void flashrom_set_log_callback_test_success(void **state) (void)state; /* unused */ flashrom_set_log_callback(test_log_callback); /* check that callback is called */ - assert_int_equal(print(FLASHROM_MSG_INFO, "1%s", "\n"), 0x666 + 1); + assert_int_equal(print(FLASHROM_MSG_INFO, "1%s", "\n"), 0x666 + (int)FLASHROM_MSG_INFO); flashrom_set_log_callback(NULL); } @@ -61,6 +57,43 @@ void flashrom_set_log_callback_v2_test_success(void **state) flashrom_set_log_callback_v2(test_log_callback_v2, &user_data); print(FLASHROM_MSG_ERROR, "2%s", "\n"); /* check that callback is called */ - assert_int_equal(user_data, 0x666 + 2); + assert_int_equal(user_data, 0x666 + (int)FLASHROM_MSG_ERROR); flashrom_set_log_callback_v2(NULL, NULL); } + +void flashrom_set_log_level_test_success(void **state) +{ + (void)state; /* unused */ + int user_data; + + flashrom_set_log_level(FLASHROM_MSG_WARN); + + /* v2 API check */ + user_data = 100500; + flashrom_set_log_callback_v2(test_log_callback_v2, &user_data); + print(FLASHROM_MSG_DEBUG, "2%s", "\n"); + /* check that callback is not called */ + assert_int_equal(user_data, 100500); + print(FLASHROM_MSG_ERROR, "2%s", "\n"); + /* check that callback is called for less */ + assert_int_equal(user_data, 0x666 + (int)FLASHROM_MSG_ERROR); + user_data = 100500; + print(FLASHROM_MSG_WARN, "2%s", "\n"); + /* check that callback is called for equal */ + assert_int_equal(user_data, 0x666 + (int)FLASHROM_MSG_WARN); + + /* v1 API check */ + flashrom_set_log_callback(test_log_callback); + + /* check that callback is not called */ + assert_int_equal(print(FLASHROM_MSG_INFO, "1%s", "\n"), 0); + /* check that callback is called for equal */ + assert_int_equal(print(FLASHROM_MSG_WARN, "1%s", "\n"), 0x666 + (int)FLASHROM_MSG_WARN); + /* check that callback is called for less*/ + assert_int_equal(print(FLASHROM_MSG_ERROR, "1%s", "\n"), 0x666 + (int)FLASHROM_MSG_ERROR); + + flashrom_set_log_level(FLASHROM_MSG_INFO); + /* check that callback is called after the change*/ + assert_int_equal(print(FLASHROM_MSG_INFO, "1%s", "\n"), 0x666 + (int)FLASHROM_MSG_INFO); + flashrom_set_log_callback(NULL); +} \ No newline at end of file diff --git a/tests/tests.c b/tests/tests.c index 1c7285390..ef719675b 100644 --- a/tests/tests.c +++ b/tests/tests.c @@ -481,6 +481,7 @@ int main(int argc, char *argv[]) const struct CMUnitTest libflashrom_tests[] = { cmocka_unit_test(flashrom_set_log_callback_test_success), cmocka_unit_test(flashrom_set_log_callback_v2_test_success), + cmocka_unit_test(flashrom_set_log_level_test_success), }; ret |= cmocka_run_group_tests_name("libflashrom.c tests", libflashrom_tests, NULL, NULL); diff --git a/tests/tests.h b/tests/tests.h index a71eded0f..e358e86b8 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -34,6 +34,7 @@ void flashbuses_to_text_test_success(void **state); /* libflashrom.c */ void flashrom_set_log_callback_test_success(void **state); void flashrom_set_log_callback_v2_test_success(void **state); +void flashrom_set_log_level_test_success(void **state); /* spi25.c */ void spi_write_enable_test_success(void **state);