diff --git a/hw/mcu/native/src/hal_flash.c b/hw/mcu/native/src/hal_flash.c index b39b5158ce..feec9661bd 100644 --- a/hw/mcu/native/src/hal_flash.c +++ b/hw/mcu/native/src/hal_flash.c @@ -152,7 +152,7 @@ static int flash_native_write_internal(uint32_t address, const void *src, uint32_t length, int allow_overwrite) { - static uint8_t buf[256]; + uint8_t buf[256] = { 0 }; uint32_t cur; uint32_t end; int chunk_sz; diff --git a/sys/log/full/include/log/log.h b/sys/log/full/include/log/log.h index 5fb2587c25..6b644eb455 100644 --- a/sys/log/full/include/log/log.h +++ b/sys/log/full/include/log/log.h @@ -77,6 +77,46 @@ struct log_storage_info { }; #endif +#if MYNEWT_VAL(LOG_FLAGS_TRAILER) + +#define LOG_TRAILER_LEN_SIZE 2 + +/** @typedef log_trailer_free_func_t + * @brief Callback that frees the trailer buffer, to be called by user of the + * library once append returns, either successfully or unsuccessfully + * + * @param log The log the trailer is being appended to + * @param om mbuf pointer to be freed + * @param arg Argument to be passed to the trailer handler + * + * @return 0 on success, non-zero on failure + */ +typedef int log_trailer_free_func_t(struct log *log, struct os_mbuf *om, void *arg); + +/** @typedef log_trailer_get_data_func_t + * @brief Callback that is executed each time the corresponding log entry is + * appended to + * + * @param log The log the trailer needs to be appended to + * @param om mbuf pointer to be set to mbuf which contains + * trailer data + * @param arg Argument to be passed to the trailer handler + * + * @return 0 on success, non-zero on failure + */ +typedef int log_trailer_get_data_func_t(struct log *log, struct os_mbuf **om, void *arg); + +/** @typedef log_trailer_reset_data_func_t + * @brief Callback used to reset trailer data per log + * + * @param log The log the trailer is to be read from + * @param arg Argument to be passed to the trailer handler + * + * @return 0 on success, non-zero on failure. + */ +typedef int log_trailer_reset_data_func_t(struct log *log, void *arg); +#endif + typedef int (*log_walk_func_t)(struct log *, struct log_offset *log_offset, const void *dptr, uint16_t len); @@ -99,6 +139,7 @@ typedef int (*lh_append_mbuf_body_func_t)(struct log *log, typedef int (*lh_walk_func_t)(struct log *, log_walk_func_t walk_func, struct log_offset *log_offset); typedef int (*lh_flush_func_t)(struct log *); +typedef uint16_t (*lh_read_entry_len_func_t)(struct log *log, const void *dptr); #if MYNEWT_VAL(LOG_STORAGE_INFO) typedef int (*lh_storage_info_func_t)(struct log *, struct log_storage_info *); #endif @@ -118,6 +159,7 @@ struct log_handler { lh_walk_func_t log_walk; lh_walk_func_t log_walk_sector; lh_flush_func_t log_flush; + lh_read_entry_len_func_t log_read_entry_len; #if MYNEWT_VAL(LOG_STORAGE_INFO) lh_storage_info_func_t log_storage_info; #endif @@ -131,8 +173,9 @@ struct log_handler { /* Image hash length to be looged */ #define LOG_IMG_HASHLEN 4 -/* Flags used to indicate type of data in reserved payload*/ +/* Flags used to indicate type of data in reserved payload */ #define LOG_FLAGS_IMG_HASH (1 << 0) +#define LOG_FLAGS_TRAILER (1 << 1) #if MYNEWT_VAL(LOG_VERSION) == 3 struct log_entry_hdr { @@ -204,6 +247,20 @@ STATS_SECT_END #define LOG_STATS_INCN(log, name, cnt) #endif +#if MYNEWT_VAL(LOG_FLAGS_TRAILER) +/* Trailer support callbacks */ +struct log_trailer_handler { + /* Frees the trailer buffer */ + log_trailer_free_func_t *lth_trailer_free; + /* Trailer append callback used to append trailer to the log entry */ + log_trailer_get_data_func_t *lth_trailer_get_data; + /* Trailer reset data callback used to reset the trailer data + * per log which is defined by the application registering these callbacks + */ + log_trailer_reset_data_func_t *lth_trailer_reset_data; +}; +#endif + struct log { const char *l_name; const struct log_handler *l_log; @@ -219,6 +276,23 @@ struct log { #if MYNEWT_VAL(LOG_STATS) STATS_SECT_DECL(logs) l_stats; #endif +#if MYNEWT_VAL(LOG_INIT_CB) + /* Custom log init callback to be called by the last hdr + * read function to read custom data from log entries + * at init + */ + log_walk_func_t l_init_cb; +#endif + +#if MYNEWT_VAL(LOG_FLAGS_TRAILER) + /* Log trailer support */ + /* Void argument for callbacks registeration */ + void *l_tr_arg; + /* Trailer mbuf */ + struct os_mbuf *l_tr_om; + /* Trailer handler with callbacks */ + struct log_trailer_handler *l_th; +#endif }; /* Log system level functions (for all logs.) */ @@ -514,6 +588,121 @@ void log_printf(struct log *log, uint8_t module, uint8_t level, int log_read(struct log *log, const void *dptr, void *buf, uint16_t off, uint16_t len); +#if MYNEWT_VAL(LOG_INIT_CB) +/** + * Reads entry length from the specified log. + * + * @return The number of bytes of entry length; 0 on failure. + */ +uint16_t +log_read_entry_len(struct log *log, const void *dptr); + +#if MYNEWT_VAL(LOG_FLAGS_TRAILER) + +/** + * @brief Read log trailer of a specific entry + * + * @param log The log to read trailer data from + * @param dptr Data pointer to the log entry + * @param buf Pointer to the buffer to read the trailer into + * + * @return 0 on success; nonzero on failure. + */ +uint16_t +log_read_trailer(struct log *log, const void *dptr, uint8_t *buf); + +/**Add commentMore actions + * @brief Returns trailer data in an mbuf specified by the caller + * + * @param log The log to append to + * @param om mbuf pointer to be set to buffer which contains + * trailer data + * @param arg Argument to be passed to the trailer handler + * + * @return 0 on success; nonzero on failure. + */ +static inline int +log_trailer_get_data(struct log *log, struct os_mbuf **om, void *arg) +{ + if (log->l_th && log->l_th->lth_trailer_get_data) { + return log->l_th->lth_trailer_get_data(log, om, arg); + } + return SYS_ENOTSUP; +} + +/** + * @brief Callback that frees the trailer buffer, to be called by user of the library + * once append returns, either successfully or unsuccessfully + * + * @param log The log the trailer is being appended to + * @param om mbuf pointer to be freed + * @param arg Argument to be passed to the trailer handler + * + * @return 0 on success; nonzero on failure. + */ +static inline int +log_trailer_free(struct log *log, struct os_mbuf *om, void *arg) +{ + if (log->l_th && log->l_th->lth_trailer_free) { + return log->l_th->lth_trailer_free(log, om, arg); + } + return SYS_ENOTSUP; +} + +/** + * @brief Resets the trailer data in the log, calling user callback + * + * @param log The log to reset. + * @param arg Argument to be passed to the trailer handler + * + * @return 0 on success; nonzero on failure. + */ +static inline int +log_trailer_reset_data(struct log *log, void *arg) +{ + if (log->l_th && log->l_th->lth_trailer_reset_data) { + return log->l_th->lth_trailer_reset_data(log, arg); + } + return SYS_ENOTSUP; +} + +/** + * @brief Register trailer callbacks + * + * @param log The log to read from. + * @param lth The trailer handler to register. + * @param arg Argument to be passed to the trailer handler + * + * @return 0 on success; nonzero on failure. + */ +static inline void +log_trailer_cbs_register(struct log *log, struct log_trailer_handler *lth, + void *arg) +{ + if (!lth || !log) { + return; + } + + log->l_th = lth; + log->l_tr_arg = arg; +} +#endif + +/** + * @brief Register Log init callback to be called by log_read_last_hdr + * while reading the last log entry at init + * + * @param log The log to register. + * @param cb The callback to associate with the log. + * + */ +static inline void +log_register_init_cb(struct log *log, log_walk_func_t cb) +{ + log->l_init_cb = cb; +} +#endif + /** * @brief Reads a single log entry header. * @@ -531,7 +720,7 @@ int log_read_hdr(struct log *log, const void *dptr, struct log_entry_hdr *hdr); * @brief Reads the header length * * @param hdr Ptr to the header - * + * * @return Length of the header */ uint16_t @@ -738,6 +927,21 @@ int log_set_watermark(struct log *log, uint32_t index); int log_fill_current_img_hash(struct log_entry_hdr *hdr); +/** + * @brief Reads the final log entry's header and processes trailer if the flag + * indicates so from the specified log only if the log supports trailers + * and mynewt val LOG_FLAGS_TRAILER is 1 + * + * @param log The log to read from. + * @param out_hdr On success, the last entry header gets written + * here. + * @param trailer_exists Pointer to a boolean + * + * @return 0 on success; nonzero on failure. + */ +int log_read_last_hdr_trailer(struct log *log, struct log_entry_hdr *out_hdr, + bool *trailer_exists); + /* Handler exports */ #if MYNEWT_VAL(LOG_CONSOLE) extern const struct log_handler log_console_handler; diff --git a/sys/log/full/selftest/util/src/testcases/log_test_case_2logs.c b/sys/log/full/selftest/util/src/testcases/log_test_case_2logs.c index 7e5735541b..3a84e71fba 100644 --- a/sys/log/full/selftest/util/src/testcases/log_test_case_2logs.c +++ b/sys/log/full/selftest/util/src/testcases/log_test_case_2logs.c @@ -44,9 +44,9 @@ TEST_CASE_SELF(log_test_case_2logs) { int rc; struct fcb_log fcb_log1; - struct log log1; + struct log log1 = {0}; struct fcb_log fcb_log2; - struct log log2; + struct log log2 = {0}; ltu_setup_2fcbs(&fcb_log1, &log1, &fcb_log2, &log2); diff --git a/sys/log/full/selftest/util/src/testcases/log_test_case_append_cb.c b/sys/log/full/selftest/util/src/testcases/log_test_case_append_cb.c index b1d2444a83..66ae592d42 100644 --- a/sys/log/full/selftest/util/src/testcases/log_test_case_append_cb.c +++ b/sys/log/full/selftest/util/src/testcases/log_test_case_append_cb.c @@ -43,7 +43,7 @@ ltcwc_append_cb(struct log *log, uint32_t idx) TEST_CASE_SELF(log_test_case_append_cb) { struct fcb_log fcb_log; - struct log log; + struct log log = {0}; ltu_setup_fcb(&fcb_log, &log); diff --git a/sys/log/full/selftest/util/src/testcases/log_test_case_cbmem_append_body.c b/sys/log/full/selftest/util/src/testcases/log_test_case_cbmem_append_body.c index 0a7fb1c110..e8c0cf24be 100644 --- a/sys/log/full/selftest/util/src/testcases/log_test_case_cbmem_append_body.c +++ b/sys/log/full/selftest/util/src/testcases/log_test_case_cbmem_append_body.c @@ -22,7 +22,7 @@ TEST_CASE_SELF(log_test_case_cbmem_append_body) { struct cbmem cbmem; - struct log log; + struct log log = {0}; char *str; int i; diff --git a/sys/log/full/selftest/util/src/testcases/log_test_case_cbmem_append_mbuf.c b/sys/log/full/selftest/util/src/testcases/log_test_case_cbmem_append_mbuf.c index 3bf305549a..065b532b80 100644 --- a/sys/log/full/selftest/util/src/testcases/log_test_case_cbmem_append_mbuf.c +++ b/sys/log/full/selftest/util/src/testcases/log_test_case_cbmem_append_mbuf.c @@ -23,8 +23,8 @@ TEST_CASE_SELF(log_test_case_cbmem_append_mbuf) { struct cbmem cbmem; struct os_mbuf *om; - struct log log; char *str; + struct log log = {0}; int rc; int i; diff --git a/sys/log/full/selftest/util/src/testcases/log_test_case_cbmem_append_mbuf_body.c b/sys/log/full/selftest/util/src/testcases/log_test_case_cbmem_append_mbuf_body.c index fddb1bbc85..e5d87d3721 100644 --- a/sys/log/full/selftest/util/src/testcases/log_test_case_cbmem_append_mbuf_body.c +++ b/sys/log/full/selftest/util/src/testcases/log_test_case_cbmem_append_mbuf_body.c @@ -23,7 +23,7 @@ TEST_CASE_SELF(log_test_case_cbmem_append_mbuf_body) { struct cbmem cbmem; struct os_mbuf *om; - struct log log; + struct log log = {0}; char *str; int rc; int i; diff --git a/sys/log/full/selftest/util/src/testcases/log_test_case_cbmem_printf.c b/sys/log/full/selftest/util/src/testcases/log_test_case_cbmem_printf.c index f48b876571..a738246471 100644 --- a/sys/log/full/selftest/util/src/testcases/log_test_case_cbmem_printf.c +++ b/sys/log/full/selftest/util/src/testcases/log_test_case_cbmem_printf.c @@ -22,7 +22,7 @@ TEST_CASE_SELF(log_test_case_cbmem_printf) { struct cbmem cbmem; - struct log log; + struct log log = {0}; char *str; int i; diff --git a/sys/log/full/selftest/util/src/testcases/log_test_case_fcb_append.c b/sys/log/full/selftest/util/src/testcases/log_test_case_fcb_append.c index 808188ce1a..3e4ae85687 100644 --- a/sys/log/full/selftest/util/src/testcases/log_test_case_fcb_append.c +++ b/sys/log/full/selftest/util/src/testcases/log_test_case_fcb_append.c @@ -22,7 +22,7 @@ TEST_CASE_SELF(log_test_case_fcb_append) { struct fcb_log fcb_log; - struct log log; + struct log log = {0}; uint8_t buf[256]; char *str; int body_len; diff --git a/sys/log/full/selftest/util/src/testcases/log_test_case_fcb_append_body.c b/sys/log/full/selftest/util/src/testcases/log_test_case_fcb_append_body.c index 1d0a86637e..af077751ca 100644 --- a/sys/log/full/selftest/util/src/testcases/log_test_case_fcb_append_body.c +++ b/sys/log/full/selftest/util/src/testcases/log_test_case_fcb_append_body.c @@ -22,7 +22,7 @@ TEST_CASE_SELF(log_test_case_fcb_append_body) { struct fcb_log fcb_log; - struct log log; + struct log log = {0}; char *str; int i; diff --git a/sys/log/full/selftest/util/src/testcases/log_test_case_fcb_append_mbuf.c b/sys/log/full/selftest/util/src/testcases/log_test_case_fcb_append_mbuf.c index e566c78bd7..f755b99352 100644 --- a/sys/log/full/selftest/util/src/testcases/log_test_case_fcb_append_mbuf.c +++ b/sys/log/full/selftest/util/src/testcases/log_test_case_fcb_append_mbuf.c @@ -23,7 +23,7 @@ TEST_CASE_SELF(log_test_case_fcb_append_mbuf) { struct fcb_log fcb_log; struct os_mbuf *om; - struct log log; + struct log log = {0}; char *str; int rc; int i; diff --git a/sys/log/full/selftest/util/src/testcases/log_test_case_fcb_append_mbuf_body.c b/sys/log/full/selftest/util/src/testcases/log_test_case_fcb_append_mbuf_body.c index 25d536479a..e4ee880199 100644 --- a/sys/log/full/selftest/util/src/testcases/log_test_case_fcb_append_mbuf_body.c +++ b/sys/log/full/selftest/util/src/testcases/log_test_case_fcb_append_mbuf_body.c @@ -23,7 +23,7 @@ TEST_CASE_SELF(log_test_case_fcb_append_mbuf_body) { struct fcb_log fcb_log; struct os_mbuf *om; - struct log log; + struct log log = {0}; char *str; int rc; int i; diff --git a/sys/log/full/selftest/util/src/testcases/log_test_case_fcb_printf.c b/sys/log/full/selftest/util/src/testcases/log_test_case_fcb_printf.c index d3470f9e91..419632e5c6 100644 --- a/sys/log/full/selftest/util/src/testcases/log_test_case_fcb_printf.c +++ b/sys/log/full/selftest/util/src/testcases/log_test_case_fcb_printf.c @@ -22,7 +22,7 @@ TEST_CASE_SELF(log_test_case_fcb_printf) { struct fcb_log fcb_log; - struct log log; + struct log log = {0}; char *str; int i; diff --git a/sys/log/full/src/log.c b/sys/log/full/src/log.c index 23dece179d..c9b1df5afd 100644 --- a/sys/log/full/src/log.c +++ b/sys/log/full/src/log.c @@ -294,9 +294,81 @@ log_find(const char *name) return log; } +#if MYNEWT_VAL(LOG_FLAGS_TRAILER) +uint16_t +log_read_trailer(struct log *log, const void *dptr, uint8_t *buf) +{ + int rc = 0; + uint16_t offset = 0; + uint16_t trailer_len = 0; + + if (log->l_th) { + /* This reads log entry length without alignment */ + offset = log_read_entry_len(log, dptr); + if (offset) { + rc = log_read(log, dptr, &trailer_len, + offset - LOG_TRAILER_LEN_SIZE, + LOG_TRAILER_LEN_SIZE); + if (rc == LOG_TRAILER_LEN_SIZE) { + offset -= LOG_TRAILER_LEN_SIZE; + rc = log_read(log, dptr, buf, offset - trailer_len, + trailer_len); + if (rc != trailer_len) { + /* Trailer read failed, return 0 length + * buffer remains untouched + */ + return 0; + } + } + } else { + /* Entry length is 0, no trailer buffer remains untouched */ + return 0; + } + } + + /* No trailer, return 0 length */ + return trailer_len; +} + +uint16_t +log_read_trailer_len(struct log *log, const void *dptr) +{ + int rc = 0; + uint16_t offset = 0; + uint16_t trailer_len = 0; + + if (log->l_th) { + /* This reads log entry length without alignment */ + offset = log_read_entry_len(log, dptr); + if (offset) { + rc = log_read(log, dptr, &trailer_len, + offset - LOG_TRAILER_LEN_SIZE, + LOG_TRAILER_LEN_SIZE); + if (rc == LOG_TRAILER_LEN_SIZE) { + return trailer_len; + } else { + /* Trailer read failed, return 0 length */ + return 0; + } + } else { + /* Entry length is 0, no trailer */ + return 0; + } + } + + return 0; +} +#endif /* MYNEWT_VAL(LOG_FLAGS_TRAILER) */ + +/* Argument for header/trailer walks */ struct log_read_hdr_arg { struct log_entry_hdr *hdr; int read_success; + /* This is needed if the init_cb is called to read the trailer data */ +#if MYNEWT_VAL(LOG_FLAGS_TRAILER) + bool trailer_exists; + void *trailer_arg; +#endif }; static int @@ -320,6 +392,13 @@ log_read_hdr_walk(struct log *log, struct log_offset *log_offset, const void *dp } } +#if MYNEWT_VAL(LOG_INIT_CB) + if (log->l_init_cb) { + /* If the log has an init callback, call it with the header. */ + log->l_init_cb(log, log_offset, dptr, len); + } +#endif + /* Abort the walk; only one header needed. */ return 1; } @@ -336,7 +415,7 @@ log_read_hdr_walk(struct log *log, struct log_offset *log_offset, const void *dp static int log_read_last_hdr(struct log *log, struct log_entry_hdr *out_hdr) { - struct log_read_hdr_arg arg; + struct log_read_hdr_arg arg = {0}; struct log_offset log_offset = {}; arg.hdr = out_hdr; @@ -348,6 +427,7 @@ log_read_last_hdr(struct log *log, struct log_entry_hdr *out_hdr) log_offset.lo_data_len = 0; log_walk(log, log_read_hdr_walk, &log_offset); + if (!arg.read_success) { return -1; } @@ -382,6 +462,12 @@ log_register(const char *name, struct log *log, const struct log_handler *lh, log->l_idx = 0; #endif +#if MYNEWT_VAL(LOG_FLAGS_TRAILER) + log->l_tr_om = NULL; + log->l_tr_arg = NULL; + log->l_th = NULL; +#endif + if (!log_registered(log)) { #if MYNEWT_VAL(LOG_STATS) stats_init(STATS_HDR(log->l_stats), @@ -496,6 +582,9 @@ log_append_prepare(struct log *log, uint8_t module, uint8_t level, int sr; struct os_timeval tv; uint32_t idx; +#if MYNEWT_VAL(LOG_FLAGS_TRAILER) + struct os_mbuf *om = NULL; +#endif rc = 0; @@ -571,6 +660,19 @@ log_append_prepare(struct log *log, uint8_t module, uint8_t level, } #endif +#if MYNEWT_VAL(LOG_FLAGS_TRAILER) + if (log->l_th) { + rc = log_trailer_get_data(log, &om, log->l_tr_arg); + if (!rc && om) { + ue->ue_flags |= LOG_FLAGS_TRAILER; + log->l_tr_om = om; + rc = 0; + } else { + rc = SYS_ENOMEM; + } + } +#endif + err: return (rc); } @@ -625,8 +727,15 @@ log_append_typed(struct log *log, uint8_t module, uint8_t level, uint8_t etype, log_call_append_cb(log, hdr->ue_index); +#if MYNEWT_VAL(LOG_FLAGS_TRAILER) + log_trailer_free(log, log->l_tr_om, log->l_tr_arg); +#endif + return (0); err: +#if MYNEWT_VAL(LOG_FLAGS_TRAILER) + log_trailer_free(log, log->l_tr_om, log->l_tr_arg); +#endif return (rc); } @@ -641,24 +750,32 @@ log_append_body(struct log *log, uint8_t module, uint8_t level, uint8_t etype, rc = log_chk_max_entry_len(log, body_len); if (rc != OS_OK) { - return rc; + goto err; } rc = log_append_prepare(log, module, level, etype, &hdr); if (rc != 0) { LOG_STATS_INC(log, drops); - return rc; + goto err; } rc = log->l_log->log_append_body(log, &hdr, body, body_len); if (rc != 0) { LOG_STATS_INC(log, errs); - return rc; + goto err; } log_call_append_cb(log, hdr.ue_index); +#if MYNEWT_VAL(LOG_FLAGS_TRAILER) + log_trailer_free(log, log->l_tr_om, log->l_tr_arg); +#endif return 0; +err: +#if MYNEWT_VAL(LOG_FLAGS_TRAILER) + log_trailer_free(log, log->l_tr_om, log->l_tr_arg); +#endif + return rc; } int @@ -671,7 +788,7 @@ log_append_mbuf_typed_no_free(struct log *log, uint8_t module, uint8_t level, uint16_t hdr_len; int rc; - /* Remove a loyer of indirection for convenience. */ + /* Remove a layer of indirection for convenience. */ om = *om_ptr; LOG_STATS_INC(log, writes); @@ -729,6 +846,9 @@ log_append_mbuf_typed_no_free(struct log *log, uint8_t module, uint8_t level, log_call_append_cb(log, hdr->ue_index); +#if MYNEWT_VAL(LOG_FLAGS_TRAILER) + log_trailer_free(log, log->l_tr_om, log->l_tr_arg); +#endif *om_ptr = om; return 0; @@ -736,6 +856,9 @@ log_append_mbuf_typed_no_free(struct log *log, uint8_t module, uint8_t level, err: LOG_STATS_INC(log, errs); drop: +#if MYNEWT_VAL(LOG_FLAGS_TRAILER) + log_trailer_free(log, log->l_tr_om, log->l_tr_arg); +#endif if (om) { os_mbuf_free_chain(om); *om_ptr = NULL; @@ -792,10 +915,17 @@ log_append_mbuf_body_no_free(struct log *log, uint8_t module, uint8_t level, log_call_append_cb(log, hdr.ue_index); +#if MYNEWT_VAL(LOG_FLAGS_TRAILER) + log_trailer_free(log, log->l_tr_om, log->l_tr_arg); +#endif + return 0; err: LOG_STATS_INC(log, errs); drop: +#if MYNEWT_VAL(LOG_FLAGS_TRAILER) + log_trailer_free(log, log->l_tr_om, log->l_tr_arg); +#endif return rc; } @@ -938,6 +1068,20 @@ log_walk_body_section(struct log *log, log_walk_body_func_t walk_body_func, return rc; } +/** + * Reads entry length from the specified log. + * + * @return The number of bytes of entry length; 0 on failure. + */ +uint16_t +log_read_entry_len(struct log *log, const void *dptr) +{ + if (log->l_log->log_read_entry_len) { + return log->l_log->log_read_entry_len(log, dptr); + } + return 0; +} + /** * Reads from the specified log. * @@ -957,7 +1101,7 @@ log_read(struct log *log, const void *dptr, void *buf, uint16_t off, int log_read_hdr(struct log *log, const void *dptr, struct log_entry_hdr *hdr) { - int bytes_read; + int bytes_read = 0; bytes_read = log_read(log, dptr, hdr, 0, LOG_BASE_ENTRY_HDR_SIZE); if (bytes_read != LOG_BASE_ENTRY_HDR_SIZE) { @@ -1025,6 +1169,14 @@ log_flush(struct log *log) { int rc; +#if MYNEWT_VAL(LOG_FLAGS_TRAILER) + /* Reset trailer data if it exists, if it does not exist + * this function will return SYS_ENOTSUP. Currently, + * we do not use the return value. + */ + log_trailer_reset_data(log, log->l_tr_arg); +#endif + rc = log->l_log->log_flush(log); if (rc != 0) { goto err; diff --git a/sys/log/full/src/log_fcb.c b/sys/log/full/src/log_fcb.c index bc43babc3b..70144f4616 100644 --- a/sys/log/full/src/log_fcb.c +++ b/sys/log/full/src/log_fcb.c @@ -30,6 +30,13 @@ /* Assume the flash alignment requirement is no stricter than 32. */ #define LOG_FCB_MAX_ALIGN 32 +#define LOG_FCB_EXT_HDR_SIZE LOG_BASE_ENTRY_HDR_SIZE + LOG_IMG_HASHLEN + \ + LOG_FCB_MAX_ALIGN + +/* Assuming the trailer fits in this, an arbitrary value */ +#define LOG_FCB_FLAT_BUF_SIZE (LOG_FCB_EXT_HDR_SIZE > LOG_FCB_MAX_ALIGN * 2) ? \ + LOG_FCB_EXT_HDR_SIZE : LOG_FCB_MAX_ALIGN * 2 + static int log_fcb_rtr_erase(struct log *log); static int @@ -324,20 +331,15 @@ log_fcb_start_append(struct log *log, int len, struct fcb_entry *loc) return (rc); } -/** - * Calculates the number of message body bytes that should be included after - * the entry header in the first write. Inclusion of body bytes is necessary - * to satisfy the flash hardware's write alignment restrictions. - */ static int -log_fcb_hdr_body_bytes(uint8_t align, uint8_t hdr_len) +log_fcb_hdr_bytes(uint16_t align, uint16_t len) { - uint8_t mod; + uint16_t mod; /* Assume power-of-two alignment for faster modulo calculation. */ assert((align & (align - 1)) == 0); - mod = hdr_len & (align - 1); + mod = len & (align - 1); if (mod == 0) { return 0; } @@ -349,37 +351,40 @@ static int log_fcb_append_body(struct log *log, const struct log_entry_hdr *hdr, const void *body, int body_len) { - uint8_t buf[LOG_BASE_ENTRY_HDR_SIZE + LOG_IMG_HASHLEN + - LOG_FCB_MAX_ALIGN - 1]; + uint8_t buf[LOG_FCB_FLAT_BUF_SIZE] = {0}; struct fcb *fcb; struct fcb_entry loc = {}; struct fcb_log *fcb_log; const uint8_t *u8p; int hdr_alignment; - int chunk_sz; + int chunk_sz = 0; int rc; uint16_t hdr_len; +#if MYNEWT_VAL(LOG_FLAGS_TRAILER) + int trailer_alignment = 0; + uint16_t trailer_len = 0; +#endif + uint16_t padding = 0; + uint16_t offset = 0; fcb_log = (struct fcb_log *)log->l_arg; fcb = &fcb_log->fl_fcb; + (void)offset; + (void)padding; + if (fcb->f_align > LOG_FCB_MAX_ALIGN) { return SYS_ENOTSUP; } hdr_len = log_hdr_len(hdr); - rc = log_fcb_start_append(log, hdr_len + body_len, &loc); - if (rc != 0) { - return rc; - } - /* Append the first chunk (header + x-bytes of body, where x is however * many bytes are required to increase the chunk size up to a multiple of * the flash alignment). If the hash flag is set, we have to account for * appending the hash right after the header. */ - hdr_alignment = log_fcb_hdr_body_bytes(fcb->f_align, hdr_len); + hdr_alignment = log_fcb_hdr_bytes(fcb->f_align, hdr_len); if (hdr_alignment > body_len) { chunk_sz = hdr_len + body_len; } else { @@ -397,8 +402,36 @@ log_fcb_append_body(struct log *log, const struct log_entry_hdr *hdr, if (hdr->ue_flags & LOG_FLAGS_IMG_HASH) { memcpy(buf + LOG_BASE_ENTRY_HDR_SIZE, hdr->ue_imghash, LOG_IMG_HASHLEN); } + memcpy(buf + hdr_len, u8p, hdr_alignment); +#if MYNEWT_VAL(LOG_FLAGS_TRAILER) + if (hdr->ue_flags & LOG_FLAGS_TRAILER && log->l_tr_om) { + /* Calculate trailer alignment */ + trailer_alignment = log_fcb_hdr_bytes(fcb->f_align, + chunk_sz + body_len - + hdr_alignment); + /* If trailer is set, we need to write the trailer length and + * trailer data after the body. + * ------------------------------------------------------ + * | hdr + align | body | align + trailer | trailer len | + * ------------------------------------------------------ + */ + trailer_len = os_mbuf_len(log->l_tr_om); + rc = log_fcb_start_append(log, hdr_len + body_len + trailer_len + + trailer_alignment + LOG_TRAILER_LEN_SIZE, + &loc); + } else +#endif + { + /* If trailer is not set, we just write the header + body */ + rc = log_fcb_start_append(log, hdr_len + body_len, &loc); + } + + if (rc != 0) { + return rc; + } + rc = fcb_write(fcb, &loc, buf, chunk_sz); if (rc != 0) { return rc; @@ -407,13 +440,59 @@ log_fcb_append_body(struct log *log, const struct log_entry_hdr *hdr, /* Append the remainder of the message body. */ u8p += hdr_alignment; - body_len -= hdr_alignment; + if (body_len > hdr_alignment) { + body_len -= hdr_alignment; + } + +#if MYNEWT_VAL(LOG_FLAGS_TRAILER) + if (hdr->ue_flags & LOG_FLAGS_TRAILER && log->l_tr_om) { + memset(buf, 0, sizeof(buf)); + padding = trailer_alignment ? fcb->f_align - trailer_alignment : 0; + /* This writes padding + trailer_alignment if needed */ + if (body_len > padding) { + /* Writes body - padding bytes */ + rc = fcb_write(fcb, &loc, u8p, body_len - padding); + u8p += (body_len - padding); + memcpy(buf, u8p, padding); + offset = padding; + } else { + /* Just write the entire body since its less than padding */ + rc = fcb_write(fcb, &loc, u8p, body_len); + u8p += body_len; + } - if (body_len > 0) { - rc = fcb_write(fcb, &loc, u8p, body_len); if (rc != 0) { return rc; } + + offset += trailer_alignment; + + rc = os_mbuf_copydata(log->l_tr_om, 0, trailer_len, buf + offset); + if (rc) { + return rc; + } + offset += trailer_len; + memcpy(buf + offset, &trailer_len, LOG_TRAILER_LEN_SIZE); + offset += LOG_TRAILER_LEN_SIZE; + + /* Writes the following: + * ------------------------------------------------------------------ + * | body: [padding] | trailer_alignment | trailer | trailer length | + * ------------------------------------------------------------------ + * + * Padding is optional based on whether body_len > padding. + */ + rc = fcb_write(fcb, &loc, buf, offset); + } else +#endif + { + if (body_len > 0) { + rc = fcb_write(fcb, &loc, u8p, body_len); + } + } + + if (rc != 0) { + return rc; } rc = fcb_append_finish(fcb, &loc); @@ -463,6 +542,11 @@ log_fcb_append_mbuf_body(struct log *log, const struct log_entry_hdr *hdr, struct fcb_log *fcb_log; int len; int rc; +#if MYNEWT_VAL(LOG_FLAGS_TRAILER) + int trailer_alignment = 0; + uint8_t pad[LOG_FCB_MAX_ALIGN] = {0}; + uint16_t trailer_len = 0; +#endif fcb_log = (struct fcb_log *)log->l_arg; fcb = &fcb_log->fl_fcb; @@ -475,6 +559,28 @@ log_fcb_append_mbuf_body(struct log *log, const struct log_entry_hdr *hdr, } len = log_hdr_len(hdr) + os_mbuf_len(om); + +#if MYNEWT_VAL(LOG_FLAGS_TRAILER) + if (hdr->ue_flags & LOG_FLAGS_TRAILER) { + /* The trailer gets appended after the trailer_alignment + * Trailers start from updated loc.fe_data_off. Write everything + * together + * Writes the following: + * ----------------------------------------------------------------- + * | body: body_len | trailer_alignment | trailer | trailer length | + * ----------------------------------------------------------------- + * part of body len + trailer_alignment = fcb->f_align + * So, we just pad trailer_alignment agt the end of the mbuf chain + */ + if (log->l_tr_om) { + trailer_len = os_mbuf_len(log->l_tr_om); + /* Calculate trailer alignment */ + trailer_alignment = log_fcb_hdr_bytes(fcb->f_align, trailer_len); + len += (trailer_alignment + trailer_len + LOG_TRAILER_LEN_SIZE); + } + } +#endif + rc = log_fcb_start_append(log, len, &loc); if (rc != 0) { return rc; @@ -496,6 +602,43 @@ log_fcb_append_mbuf_body(struct log *log, const struct log_entry_hdr *hdr, } loc.fe_data_off += LOG_IMG_HASHLEN; } + +#if MYNEWT_VAL(LOG_FLAGS_TRAILER) + if (hdr->ue_flags & LOG_FLAGS_TRAILER) { + /* The trailer gets appended after the padding + trailer_alignment + * Trailers start from updated loc.fe_data_off. Write everything + * together + * Writes the following: + * ----------------------------------------------------------------- + * | body: body_len | trailer_alignment | trailer | trailer length | + * ----------------------------------------------------------------- + * part of body_len + trailer_alignment = f_align + */ + + if (log->l_tr_om) { + /* Copy mbuf chain len */ + rc = os_mbuf_copyinto(om, trailer_len, pad, trailer_alignment); + if (rc) { + return rc; + } + + /* Append from the trailer */ + rc = os_mbuf_appendfrom(om, log->l_tr_om, 0, trailer_len); + if (rc) { + return rc; + } + + om = os_mbuf_pullup(om, LOG_TRAILER_LEN_SIZE); + /* Copy the trailer length */ + rc = os_mbuf_copyinto(om, trailer_len, &trailer_len, + LOG_TRAILER_LEN_SIZE); + if (rc) { + return rc; + } + } + } +#endif + rc = log_fcb_write_mbuf(&loc, om); if (rc != 0) { return rc; @@ -551,6 +694,20 @@ log_fcb_append_mbuf(struct log *log, struct os_mbuf *om) return rc; } +static uint16_t +log_fcb_read_entry_len(struct log *log, const void *dptr) +{ + struct fcb_entry *loc; + + loc = (struct fcb_entry *)dptr; + + if (!log || !dptr) { + return 0; + } + + return loc->fe_data_len; +} + static int log_fcb_read(struct log *log, const void *dptr, void *buf, uint16_t offset, uint16_t len) @@ -1063,6 +1220,7 @@ const struct log_handler log_fcb_handler = { .log_walk = log_fcb_walk, .log_walk_sector = log_fcb_walk_area, .log_flush = log_fcb_flush, + .log_read_entry_len = log_fcb_read_entry_len, #if MYNEWT_VAL(LOG_STORAGE_INFO) .log_storage_info = log_fcb_storage_info, #endif diff --git a/sys/log/full/syscfg.yml b/sys/log/full/syscfg.yml index dc228d2185..b6efac0040 100644 --- a/sys/log/full/syscfg.yml +++ b/sys/log/full/syscfg.yml @@ -63,6 +63,12 @@ syscfg.defs: 1 - enable. value: 0 + LOG_FLAGS_TRAILER: + description: > + Enable logging trailer with custom data types in every log entry + 0 - disable; 1 - enable. + value: 0 + LOG_FCB: description: 'Support logging to FCB.' value: 0 @@ -197,6 +203,12 @@ syscfg.defs: - LOG_FCB_BOOKMARKS - LOG_FCB + LOG_INIT_CB: + description: > + Enable log init callback. This callback is called after the log + module is initialized and most recent entry is read. + value: 0 + syscfg.vals.CONSOLE_TICKS: LOG_CONSOLE_PRETTY_WITH_TIMESTAMP: 0