diff --git a/fs/fcb2/include/fcb/fcb2.h b/fs/fcb2/include/fcb/fcb2.h index e089fccbce..2f0c720902 100644 --- a/fs/fcb2/include/fcb/fcb2.h +++ b/fs/fcb2/include/fcb/fcb2.h @@ -304,6 +304,15 @@ int fcb2_clear(struct fcb2 *fcb); */ int fcb2_area_info(struct fcb2 *fcb, int sector, int *elemsp, int *bytesp); +/** + * Length of data in flash considering alignment + * + * @param range Active range + * @param len Length to be calculated using alignment + * + */ +int fcb2_len_in_flash(const struct flash_sector_range *range, uint16_t len); + #ifdef __cplusplus } diff --git a/fs/fcb2/src/fcb.c b/fs/fcb2/src/fcb.c index e8a65ff123..0f1e31ee3f 100644 --- a/fs/fcb2/src/fcb.c +++ b/fs/fcb2/src/fcb.c @@ -101,6 +101,15 @@ fcb2_init(struct fcb2 *fcb) return rc; } +int +fcb2_len_in_flash(const struct flash_sector_range *range, uint16_t len) +{ + if (range->fsr_align <= 1) { + return len; + } + return (len + (range->fsr_align - 1)) & ~(range->fsr_align - 1); +} + int fcb2_free_sector_cnt(struct fcb2 *fcb) { diff --git a/fs/fcb2/src/fcb_priv.h b/fs/fcb2/src/fcb_priv.h index d02784fab5..6f91ff09f7 100644 --- a/fs/fcb2/src/fcb_priv.h +++ b/fs/fcb2/src/fcb_priv.h @@ -40,15 +40,6 @@ struct fcb2_sector_info { uint16_t si_sector_in_range; /* Sector number relative to si_range */ }; -static inline int -fcb2_len_in_flash(const struct flash_sector_range *range, uint16_t len) -{ - if (range->fsr_align <= 1) { - return len; - } - return (len + (range->fsr_align - 1)) & ~(range->fsr_align - 1); -} - int fcb2_getnext_in_area(struct fcb2 *fcb, struct fcb2_entry *loc); static inline int diff --git a/sys/log/full/include/log/log.h b/sys/log/full/include/log/log.h index 821a11d6bb..b3bc481959 100644 --- a/sys/log/full/include/log/log.h +++ b/sys/log/full/include/log/log.h @@ -75,18 +75,18 @@ struct log_storage_info { }; #endif -typedef int (*log_walk_func_t)(struct log *, struct log_offset *log_offset, +typedef int (*log_walk_func_t)(struct log *log, struct log_offset *log_offset, const void *dptr, uint16_t len); typedef int (*log_walk_body_func_t)(struct log *log, struct log_offset *log_offset, const struct log_entry_hdr *hdr, const void *dptr, uint16_t len); -typedef int (*lh_read_func_t)(struct log *, const void *dptr, void *buf, +typedef int (*lh_read_func_t)(struct log *log, const void *dptr, void *buf, uint16_t offset, uint16_t len); -typedef int (*lh_read_mbuf_func_t)(struct log *, const void *dptr, struct os_mbuf *om, +typedef int (*lh_read_mbuf_func_t)(struct log *log, const void *dptr, struct os_mbuf *om, uint16_t offset, uint16_t len); -typedef int (*lh_append_func_t)(struct log *, void *buf, int len); +typedef int (*lh_append_func_t)(struct log *log, void *buf, int len); typedef int (*lh_append_body_func_t)(struct log *log, const struct log_entry_hdr *hdr, const void *body, int body_len); @@ -94,17 +94,19 @@ typedef int (*lh_append_mbuf_func_t)(struct log *, struct os_mbuf *om); typedef int (*lh_append_mbuf_body_func_t)(struct log *log, const struct log_entry_hdr *hdr, struct os_mbuf *om); -typedef int (*lh_walk_func_t)(struct log *, +typedef int (*lh_walk_func_t)(struct log *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 *, const void *dptr); +typedef int (*lh_flush_func_t)(struct log *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 *); +typedef int (*lh_storage_info_func_t)(struct log *log, struct log_storage_info *); #endif #if MYNEWT_VAL(LOG_STORAGE_WATERMARK) -typedef int (*lh_set_watermark_func_t)(struct log *, uint32_t); +typedef int (*lh_set_watermark_func_t)(struct log *log, uint32_t); #endif -typedef int (*lh_registered_func_t)(struct log *); +typedef int (*lh_registered_func_t)(struct log *log); +/* This calculates length based on alignment of underlying medium */ +typedef int (*lh_len_in_medium_func_t)(struct log *log, uint16_t len); struct log_handler { int log_type; @@ -118,6 +120,7 @@ struct log_handler { lh_walk_func_t log_walk_sector; lh_flush_func_t log_flush; lh_read_entry_len_func_t log_read_entry_len; + lh_len_in_medium_func_t log_len_in_medium; #if MYNEWT_VAL(LOG_STORAGE_INFO) lh_storage_info_func_t log_storage_info; #endif @@ -136,6 +139,7 @@ struct log_handler { #define LOG_FLAGS_TLV_SUPPORT (1 << 1) #define LOG_TLV_NUM_ENTRIES (1 << 0) +#define LOG_TLV_NUM_TLVS (1 << 1) #if MYNEWT_VAL(LOG_VERSION) == 3 struct log_entry_hdr { @@ -146,12 +150,16 @@ struct log_entry_hdr { uint8_t ue_etype : 4; uint8_t ue_flags : 4; uint8_t ue_imghash[4]; + /* Number of entries field which helps in calculating number of + * entries per log, these go on incrementing similar to an index + * but per log. + */ uint32_t ue_num_entries; } __attribute__((__packed__)); struct log_tlv { - uint8_t tag; uint8_t len; + uint8_t tag; /* Value is of variable size appended based on len, * val is logged after the tag and len are logged */ @@ -164,6 +172,30 @@ struct log_tlv { #define LOG_BASE_ENTRY_HDR_SIZE (15) #define LOG_NUM_ENTRIES_SIZE (sizeof(((struct log *)0)->l_num_entries)) +#define LOG_NUM_TLVS_SIZE (1) + +#if MYNEWT_VAL(LOG_FCB2) +#define LF_MAX_ALIGN LOG_FCB2_MAX_ALIGN +#else +#define LF_MAX_ALIGN LOG_FCB_MAX_ALIGN +#endif + +#define LOG_FCB_MAX_TLV_SIZE(__tlv_name__) \ + /* sizeof(struct log_tlv)) + alignment */ \ + (LF_MAX_ALIGN + \ + /* Max size per value of TLV including alignment */ \ + (LOG_ ## __tlv_name__ ## _SIZE/LF_MAX_ALIGN) ? \ + (LOG_ ## __tlv_name__ ## _SIZE + LF_MAX_ALIGN) : \ + LF_MAX_ALIGN) + +#define LOG_FCB_MAX_TLVS_SIZE LOG_FCB_MAX_TLV_SIZE(NUM_ENTRIES) + \ + LOG_FCB_MAX_TLV_SIZE(NUM_TLVS) + +#define LOG_FCB_EXT_HDR_SIZE LOG_BASE_ENTRY_HDR_SIZE + LOG_IMG_HASHLEN + \ + LF_MAX_ALIGN + +#define LOG_FCB_FLAT_BUF_SIZE (LOG_FCB_EXT_HDR_SIZE > LOG_FCB_MAX_TLVS_SIZE) ? \ + LOG_FCB_EXT_HDR_SIZE : LOG_FCB_MAX_TLVS_SIZE #define LOG_MODULE_STR(module) log_module_get_name(module) @@ -532,6 +564,10 @@ int log_read(struct log *log, const void *dptr, void *buf, uint16_t off, /** * Reads entry length from the specified log. * + * @param log The log to read from. + * @param dptr Medium-specific data describing the area to + * read from; typically obtained by a call to + * `log_walk`. * @return The number of bytes of entry length; 0 on failure. */ uint16_t @@ -580,7 +616,7 @@ uint16_t log_hdr_len(const struct log_entry_hdr *hdr); * * @return Length of the trailer */ -uint16_t log_trailer_len(const struct log_entry_hdr *hdr); +uint16_t log_trailer_len(struct log *log, const struct log_entry_hdr *hdr); /** * @brief Reads data from the body of a log entry into a flat buffer. @@ -778,13 +814,27 @@ int log_set_watermark(struct log *log, uint32_t index); * * @param log Ptr to log structure * @param dptr Ptr to data to be read - * @param hdr Ptr to the header - * @param offset Offset of the num of entries in the log entry + * @param num_entries Ptr to number of entries + * @param offset Offset of the num of entries field in the log entry * * @return 0 on success, non-zero on failure */ int log_fill_num_entries(struct log *log, const void *dptr, - struct log_entry_hdr *hdr, uint16_t offset); + uint32_t *num_entries, + uint16_t offset); +/** + * Fill number of tlvs + * + * @param log Ptr to log structure + * @param dptr Ptr to data to be read + * @param num_entries Ptr to number of entries + * @param offset Offset of the num of entries field in the log entry + * + * @return 0 on success, non-zero on failure + */ +int +log_fill_num_tlvs(struct log *log, const void *dptr, uint8_t *num_tlvs, + uint16_t offset); /** * Fill log current image hash @@ -819,6 +869,14 @@ log_read_hdr_by_idx(struct log *log, uint32_t idx, struct log_entry_hdr *out_hdr int log_get_entries(struct log *log, uint32_t idx, uint32_t *entries); +/* Get the length of data in medium - storage (fcb/fcb2), memory or stream + * + * @param log The log to get number of entries for + * @param len Length in medium with padding if any + */ +int +log_len_in_medium(struct log *log, uint16_t len); + /* Handler exports */ #if MYNEWT_VAL(LOG_CONSOLE) extern const struct log_handler log_console_handler; diff --git a/sys/log/full/selftest/util/src/log_test_util.c b/sys/log/full/selftest/util/src/log_test_util.c index b8ee2ecd7d..ad42f70144 100644 --- a/sys/log/full/selftest/util/src/log_test_util.c +++ b/sys/log/full/selftest/util/src/log_test_util.c @@ -279,7 +279,7 @@ ltu_walk_verify(struct log *log, struct log_offset *log_offset, } hdr_len = log_hdr_len(&ueh); - trailer_len = log_trailer_len(&ueh); + trailer_len = log_trailer_len(log, &ueh); dlen = len - hdr_len - trailer_len; TEST_ASSERT(dlen < sizeof(data)); @@ -350,7 +350,7 @@ ltu_walk_body_verify(struct log *log, struct log_offset *log_offset, TEST_ASSERT(len < sizeof(data)); - len -= log_trailer_len(euh); + len -= log_trailer_len(log, euh); rc = log_read_body(log, dptr, data, 0, len); TEST_ASSERT(rc == len); diff --git a/sys/log/full/selftest/util/src/testcases/log_test_case_cbmem_append.c b/sys/log/full/selftest/util/src/testcases/log_test_case_cbmem_append.c index 1dc95db90d..5f5d9d17ae 100644 --- a/sys/log/full/selftest/util/src/testcases/log_test_case_cbmem_append.c +++ b/sys/log/full/selftest/util/src/testcases/log_test_case_cbmem_append.c @@ -39,7 +39,7 @@ TEST_CASE_SELF(log_test_case_cbmem_append) for (i = 0; i < num_strs; i++) { hdr = (struct log_entry_hdr *)(dummy_log_arr + off_arr[i]); - len = off_arr[i+1] - off_arr[i] - log_hdr_len(hdr) - log_trailer_len(hdr); + len = off_arr[i+1] - off_arr[i] - log_hdr_len(hdr) - log_trailer_len(&log, hdr); rc = log_append_typed(&log, 2, 3, LOG_ETYPE_STRING, dummy_log_arr + off_arr[i], len); 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 85a0c0d0d0..8948bacad3 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 @@ -40,7 +40,7 @@ TEST_CASE_SELF(log_test_case_cbmem_append_body) for (i = 0; i < num_strs; i++) { hdr = (struct log_entry_hdr *)(dummy_log_arr + off_arr[i]); len = off_arr[i + 1] - off_arr[i] - - log_hdr_len(hdr) - log_trailer_len(hdr); + log_hdr_len(hdr) - log_trailer_len(&log, hdr); rc = log_append_body(&log, 2, 3, LOG_ETYPE_STRING, dummy_log_arr + off_arr[i] + log_hdr_len(hdr), len); 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 4fe3791c2c..f29bdcdb1e 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 @@ -39,7 +39,7 @@ TEST_CASE_SELF(log_test_case_cbmem_printf) for (i = 0; i < num_strs; i++) { hdr = (struct log_entry_hdr *)(dummy_log_arr + off_arr[i]); - len = off_arr[i+1] - off_arr[i] - log_hdr_len(hdr) - log_trailer_len(hdr); + len = off_arr[i+1] - off_arr[i] - log_hdr_len(hdr) - log_trailer_len(&log, hdr); memcpy(data, dummy_log_arr + off_arr[i] + log_hdr_len(hdr), len); data[len] = '\0'; 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 f7495027c7..3fe8f4e284 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 @@ -39,7 +39,7 @@ TEST_CASE_SELF(log_test_case_fcb_append) for (i = 0;i < num_strs; i++) { hdr = (struct log_entry_hdr *)(dummy_log_arr + off_arr[i]); - len = off_arr[i+1] - off_arr[i] - log_hdr_len(hdr) - log_trailer_len(hdr); + len = off_arr[i+1] - off_arr[i] - log_hdr_len(hdr) - log_trailer_len(&log, hdr); rc = log_append_typed(&log, 2, 3, LOG_ETYPE_STRING, dummy_log_arr + off_arr[i], 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 7b313fb693..996ff647e5 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 @@ -40,7 +40,7 @@ TEST_CASE_SELF(log_test_case_fcb_append_body) for (i = 0; i < num_strs; i++) { hdr = (struct log_entry_hdr *)(dummy_log_arr + off_arr[i]); len = off_arr[i + 1] - off_arr[i] - - log_hdr_len(hdr) - log_trailer_len(hdr); + log_hdr_len(hdr) - log_trailer_len(&log, hdr); rc = log_append_body(&log, 2, 3, LOG_ETYPE_STRING, dummy_log_arr + off_arr[i] + log_hdr_len(hdr), len); 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 458c9e7864..7a3c2b0353 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 @@ -40,7 +40,7 @@ TEST_CASE_SELF(log_test_case_fcb_append_mbuf) for (i = 0; i < num_strs; i++) { hdr = (struct log_entry_hdr *)(dummy_log_arr + off_arr[i]); - len = off_arr[i+1] - off_arr[i] - log_trailer_len(hdr); + len = off_arr[i+1] - off_arr[i] - log_trailer_len(&log, hdr); /* Split chain into several mbufs. */ om = ltu_flat_to_fragged_mbuf(dummy_log_arr + off_arr[i], len, 2); 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 605e6e9624..bc980835ab 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 @@ -41,7 +41,7 @@ TEST_CASE_SELF(log_test_case_fcb_append_mbuf_body) for (i = 0; i < num_strs; i++) { hdr = (struct log_entry_hdr *)(dummy_log_arr + off_arr[i]); len = off_arr[i + 1] - off_arr[i] - - log_hdr_len(hdr) - log_trailer_len(hdr); + log_hdr_len(hdr) - log_trailer_len(&log, hdr); /* Split chain into several mbufs. */ om = ltu_flat_to_fragged_mbuf(dummy_log_arr + off_arr[i] + log_hdr_len(hdr), diff --git a/sys/log/full/src/log.c b/sys/log/full/src/log.c index 21660ce6b8..84443ebe48 100644 --- a/sys/log/full/src/log.c +++ b/sys/log/full/src/log.c @@ -332,15 +332,58 @@ log_update_num_entries_hdr_walk(struct log *log, struct log_offset *log_offset, return -1; } +static int +log_process_tlvs(struct log *log, const void *dptr, uint8_t num_tlvs, + uint16_t tlv_tag, void *buf, uint16_t len) +{ + struct log_tlv *tlv; + uint8_t tmpbuf[sizeof(*tlv) + 8] = {0}; + uint16_t offset; + int tlv_len; + int rc = SYS_ENOENT; + + offset = len; + tlv_len = log_len_in_medium(log, sizeof(*tlv)); + do { + offset -= tlv_len; + rc = log_read(log, dptr, tmpbuf, offset, tlv_len); + if (rc < tlv_len) { + return SYS_EINVAL; + } + tlv = (struct log_tlv *)tmpbuf; + + offset -= log_len_in_medium(log, tlv->len); + if (tlv->tag != tlv_tag) { + continue; + } + + switch (tlv_tag) { + case LOG_TLV_NUM_ENTRIES: + rc = log_fill_num_entries(log, dptr, buf, offset); + break; + case LOG_TLV_NUM_TLVS: + rc = log_fill_num_tlvs(log, dptr, buf, offset); + break; + default: + return SYS_ENOTSUP; + } + + if (!rc) { + return SYS_EOK; + } + } while (offset && num_tlvs); + + return SYS_EOK; +} + static int log_read_hdr_walk(struct log *log, struct log_offset *log_offset, const void *dptr, uint16_t len) { struct log_read_hdr_arg *arg; int rc; - uint16_t offset = 0; + uint8_t num_tlvs = 0; - (void)offset; arg = log_offset->lo_arg; rc = log_read(log, dptr, arg->hdr, 0, LOG_BASE_ENTRY_HDR_SIZE); @@ -353,19 +396,30 @@ log_read_hdr_walk(struct log *log, struct log_offset *log_offset, if (!rc || rc == SYS_ENOTSUP) { arg->read_success = 1; } - if (!rc) { - offset = LOG_BASE_ENTRY_HDR_SIZE + LOG_IMG_HASHLEN; - } } if (arg->hdr->ue_flags & LOG_FLAGS_TLV_SUPPORT) { - rc = log_fill_num_entries(log, dptr, arg->hdr, - len - log_trailer_len(arg->hdr)); + /* Read number of TLVs, if it does not exist + * num_tlvs = 0, so only one TLV will get read + * from the end of the entry + */ + rc = log_process_tlvs(log, dptr, 0, LOG_TLV_NUM_TLVS, + &num_tlvs, len); if (!rc || rc == SYS_ENOTSUP) { arg->read_success = 1; } else { arg->read_success = 0; } + + if (!rc || rc == SYS_ENOTSUP) { + rc = log_process_tlvs(log, dptr, num_tlvs, LOG_TLV_NUM_ENTRIES, + &arg->hdr->ue_num_entries, len); + if (!rc || rc == SYS_ENOTSUP) { + arg->read_success = 1; + } else { + arg->read_success = 0; + } + } } /* Abort the walk; only one header needed. */ @@ -539,13 +593,13 @@ log_register(const char *name, struct log *log, const struct log_handler *lh, } if (log->l_log->log_type == LOG_TYPE_STORAGE) { + memset(&hdr, 0, sizeof(hdr)); rc = log_read_last_hdr(log, &hdr); if (rc == 0) { /* If the number of entries are not set in the last header, * it was probably not supported when the entry was logged. * Count number of entries in this specific case */ - hdr.ue_num_entries = 0; if (!hdr.ue_num_entries) { log_update_num_entries(log, &num_entries); } @@ -598,15 +652,39 @@ log_hdr_len(const struct log_entry_hdr *hdr) return len; } +int +log_len_in_medium(struct log *log, uint16_t len) +{ + if (log->l_log->log_len_in_medium) { + return log->l_log->log_len_in_medium(log, len); + } + + return len; +} + uint16_t -log_trailer_len(const struct log_entry_hdr *hdr) +log_trailer_len(struct log *log, const struct log_entry_hdr *hdr) { uint16_t len = 0; + uint8_t num_tlvs = 0; + (void)num_tlvs; if (hdr->ue_flags & LOG_FLAGS_TLV_SUPPORT) { -#if MYNEWT_VAL(LOG_FLAGS_TLV_SUPPORT) && MYNEWT_VAL(LOG_TLV_NUM_ENTRIES) - len += sizeof(struct log_tlv); - len += LOG_NUM_ENTRIES_SIZE; +#if MYNEWT_VAL(LOG_FLAGS_TLV_SUPPORT) +#if MYNEWT_VAL(LOG_TLV_NUM_ENTRIES) + len += log_len_in_medium(log, sizeof(struct log_tlv)) + + log_len_in_medium(log, LOG_NUM_ENTRIES_SIZE); + num_tlvs++; +#endif + /* Number of TLVs TLV is only written if there are more than + * one TLVS, else its just one TLV at the end + */ +#if MYNEWT_VAL(LOG_TLV_NUM_TLVS) + if (num_tlvs > 1) { + len += log_len_in_medium(log, sizeof(struct log_tlv)) + + log_len_in_medium(log, LOG_NUM_TLVS_SIZE); + } +#endif #endif } @@ -843,7 +921,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); @@ -1151,8 +1229,8 @@ log_read_hdr(struct log *log, const void *dptr, struct log_entry_hdr *hdr) } if (hdr->ue_flags & LOG_FLAGS_IMG_HASH) { - bytes_read = log_read(log, dptr, hdr->ue_imghash, LOG_BASE_ENTRY_HDR_SIZE, - LOG_IMG_HASHLEN); + bytes_read = log_read(log, dptr, hdr->ue_imghash, + LOG_BASE_ENTRY_HDR_SIZE, LOG_IMG_HASHLEN); if (bytes_read != LOG_IMG_HASHLEN) { return SYS_EIO; } @@ -1161,6 +1239,26 @@ log_read_hdr(struct log *log, const void *dptr, struct log_entry_hdr *hdr) return 0; } +#if MYNEWT_VAL(LOG_FLAGS_TLV_SUPPORT) +static int +log_tlv_exists(uint16_t tlv) +{ + switch (tlv) { +#if MYNEWT_VAL(LOG_TLV_NUM_ENTRIES) + case LOG_TLV_NUM_ENTRIES: + return 0; +#endif + +#if MYNEWT_VAL(LOG_TLV_NUM_TLVS) + case LOG_TLV_NUM_TLVS: + return 0; +#endif + default: + return SYS_ENOTSUP; + } +} +#endif + int log_read_trailer(struct log *log, const void *dptr, uint16_t tlv, void *buf) { @@ -1168,21 +1266,37 @@ log_read_trailer(struct log *log, const void *dptr, uint16_t tlv, void *buf) int rc; struct log_entry_hdr hdr; uint16_t entry_len; + uint8_t num_tlvs = 0; if (!buf) { return SYS_EINVAL; } + rc = log_tlv_exists(tlv); + if (rc) { + return rc; + } + rc = log_read_hdr(log, dptr, &hdr); if (rc) { return rc; } if (hdr.ue_flags & LOG_FLAGS_TLV_SUPPORT) { + entry_len = log_read_entry_len(log, dptr); + if (tlv == LOG_TLV_NUM_TLVS) { + rc = log_process_tlvs(log, dptr, 0, LOG_TLV_NUM_TLVS, &num_tlvs, + entry_len); + if (rc) { + return rc; + } + + memcpy(buf, &num_tlvs, LOG_NUM_TLVS_SIZE); + } + if (tlv == LOG_TLV_NUM_ENTRIES) { - entry_len = log_read_entry_len(log, dptr); - rc = log_fill_num_entries(log, dptr, &hdr, entry_len - - log_trailer_len(&hdr)); + rc = log_process_tlvs(log, dptr, num_tlvs, LOG_TLV_NUM_ENTRIES, + &hdr.ue_num_entries, entry_len); if (rc) { return rc; } @@ -1338,30 +1452,43 @@ log_set_max_entry_len(struct log *log, uint16_t max_entry_len) } int -log_fill_num_entries(struct log *log, const void *dptr, - struct log_entry_hdr *hdr, uint16_t offset) +log_fill_num_entries(struct log *log, const void *dptr, uint32_t *num_entries, + uint16_t offset) { #if MYNEWT_VAL(LOG_FLAGS_TLV_SUPPORT) && MYNEWT_VAL(LOG_TLV_NUM_ENTRIES) int rc = 0; - struct log_tlv tlv = {0}; + uint32_t tmpdata; - rc = log_read(log, dptr, &tlv, offset, sizeof(struct log_tlv)); - if (rc < sizeof(struct log_tlv)) { + rc = log_read(log, dptr, &tmpdata, offset, LOG_NUM_ENTRIES_SIZE); + if (rc < LOG_NUM_ENTRIES_SIZE) { return rc; } - offset += sizeof(struct log_tlv); + *num_entries = tmpdata; - rc = log_read(log, dptr, &hdr->ue_num_entries, offset, - LOG_NUM_ENTRIES_SIZE); - if (rc >= LOG_NUM_ENTRIES_SIZE) { - return SYS_EOK; - } else { + return SYS_EOK; +#else + return SYS_ENOTSUP; +#endif +} + +int +log_fill_num_tlvs(struct log *log, const void *dptr, uint8_t *num_tlvs, + uint16_t offset) +{ +#if MYNEWT_VAL(LOG_FLAGS_TLV_SUPPORT) && MYNEWT_VAL(LOG_TLV_NUM_TLVS) + int rc = 0; + uint32_t tmpdata; + + rc = log_read(log, dptr, &tmpdata, offset, LOG_NUM_TLVS_SIZE); + if (rc < LOG_NUM_TLVS_SIZE) { return rc; } -#else - hdr->ue_num_entries = 0; + *num_tlvs = tmpdata; + + return SYS_EOK; +#else return SYS_ENOTSUP; #endif } diff --git a/sys/log/full/src/log_cbmem.c b/sys/log/full/src/log_cbmem.c index e37185b1ff..5b4e73cafa 100644 --- a/sys/log/full/src/log_cbmem.c +++ b/sys/log/full/src/log_cbmem.c @@ -27,6 +27,7 @@ log_cbmem_append_body(struct log *log, const struct log_entry_hdr *hdr, { int rc = 0; struct cbmem *cbmem; + uint16_t num_tlvs = 0; struct cbmem_scat_gath sg = { .entries = (struct cbmem_scat_gath_entry[]) { { @@ -41,16 +42,27 @@ log_cbmem_append_body(struct log *log, const struct log_entry_hdr *hdr, .flat_buf = body, .flat_len = body_len, }, + { + .flat_buf = &log->l_num_entries, + .flat_len = 0 + }, { .flat_buf = NULL, .flat_len = 0, }, + /* + * Number of tlvs will always get written at the end + */ { - .flat_buf = &log->l_num_entries, + .flat_buf = &num_tlvs, .flat_len = 0 }, + { + .flat_buf = NULL, + .flat_len = 0, + }, }, - .count = 5, + .count = 7, }; if (hdr->ue_flags & LOG_FLAGS_IMG_HASH) { @@ -58,10 +70,21 @@ log_cbmem_append_body(struct log *log, const struct log_entry_hdr *hdr, } if (hdr->ue_flags & LOG_FLAGS_TLV_SUPPORT) { -#if MYNEWT_VAL(LOG_FLAGS_TLV_SUPPORT) && MYNEWT_VAL(LOG_TLV_NUM_ENTRIES) - sg.entries[3].flat_buf = &(struct log_tlv) {LOG_TLV_NUM_ENTRIES, LOG_NUM_ENTRIES_SIZE}; - sg.entries[3].flat_len = sizeof(struct log_tlv); - sg.entries[4].flat_len = LOG_NUM_ENTRIES_SIZE; +#if MYNEWT_VAL(LOG_FLAGS_TLV_SUPPORT) +#if MYNEWT_VAL(LOG_TLV_NUM_ENTRIES) + sg.entries[4].flat_buf = &(struct log_tlv) {LOG_NUM_ENTRIES_SIZE, LOG_TLV_NUM_ENTRIES}; + sg.entries[4].flat_len = sizeof(struct log_tlv); + sg.entries[3].flat_len = LOG_NUM_ENTRIES_SIZE; + num_tlvs++; +#endif +#if MYNEWT_VAL(LOG_TLV_NUM_TLVS) + /* Number of TLVs is only written if there are more than one TLVs */ + if (num_tlvs > 0) { + sg.entries[6].flat_buf = &(struct log_tlv) {LOG_NUM_TLVS_SIZE, LOG_TLV_NUM_TLVS}; + sg.entries[6].flat_len = sizeof(struct log_tlv); + sg.entries[5].flat_len = LOG_NUM_TLVS_SIZE; + } +#endif #endif } @@ -92,6 +115,7 @@ log_cbmem_append_mbuf_body(struct log *log, const struct log_entry_hdr *hdr, { int rc = 0; struct cbmem *cbmem; + uint16_t num_tlvs = 0; struct cbmem_scat_gath sg = { .entries = (struct cbmem_scat_gath_entry[]) { { @@ -105,16 +129,27 @@ log_cbmem_append_mbuf_body(struct log *log, const struct log_entry_hdr *hdr, { .om = om, }, + { + .flat_buf = &log->l_num_entries, + .flat_len = 0 + }, { .flat_buf = NULL, .flat_len = 0, }, + /* + * Number of tlvs will always get written at the end + */ { - .flat_buf = &log->l_num_entries, + .flat_buf = &num_tlvs, .flat_len = 0 }, + { + .flat_buf = NULL, + .flat_len = 0, + }, }, - .count = 5, + .count = 7, }; if (hdr->ue_flags & LOG_FLAGS_IMG_HASH) { @@ -122,11 +157,21 @@ log_cbmem_append_mbuf_body(struct log *log, const struct log_entry_hdr *hdr, } if (hdr->ue_flags & LOG_FLAGS_TLV_SUPPORT) { -#if MYNEWT_VAL(LOG_FLAGS_TLV_SUPPORT) && MYNEWT_VAL(LOG_FLAGS_NUM_ENTRIES) - sg.entries[3].flat_buf = &{LOG_TLV_NUM_ENTRIES, LOG_NUM_ENTRIES_SIZE}; - sg.entries[3].flat_len = sizeof(struct log_tlv); - sg.entries[4].flat_len = LOG_NUM_ENTRIES_SIZE; - log->l_num_entries++; +#if MYNEWT_VAL(LOG_FLAGS_TLV_SUPPORT) +#if MYNEWT_VAL(LOG_TLV_NUM_ENTRIES) + sg.entries[4].flat_buf = &(struct log_tlv) {LOG_NUM_ENTRIES_SIZE, LOG_TLV_NUM_ENTRIES}; + sg.entries[4].flat_len = sizeof(struct log_tlv); + sg.entries[3].flat_len = LOG_NUM_ENTRIES_SIZE; + num_tlvs++; +#endif +#if MYNEWT_VAL(LOG_TLV_NUM_TLVS) + /* Number of TLVs is only written if there are more than one TLVs */ + if (num_tlvs > 0) { + sg.entries[6].flat_buf = &(struct log_tlv) {LOG_NUM_TLVS_SIZE, LOG_TLV_NUM_TLVS}; + sg.entries[6].flat_len = sizeof(struct log_tlv); + sg.entries[5].flat_len = LOG_NUM_TLVS_SIZE; + } +#endif #endif } diff --git a/sys/log/full/src/log_fcb.c b/sys/log/full/src/log_fcb.c index 6f3564f2ec..d60f244e21 100644 --- a/sys/log/full/src/log_fcb.c +++ b/sys/log/full/src/log_fcb.c @@ -26,6 +26,7 @@ #include "flash_map/flash_map.h" #include "fcb/fcb.h" #include "log/log.h" +#include /* Assume the flash alignment requirement is no stricter than 8. */ #define LOG_FCB_MAX_ALIGN 8 @@ -275,8 +276,9 @@ log_fcb_start_append(struct log *log, int len, struct fcb_entry *loc) /** * Calculates the number of bytes that should be included after - * the entry header or trailer in the first write. Inclusion of bytes - * is necessary to satisfy the flash hardware's write alignment restrictions. + * the entry header for the first write or before the trailer in the second + * write. Inclusion of bytes is necessary to satisfy the flash hardware's + * write alignment restrictions. */ static int log_fcb_hdr_trailer_bytes(uint16_t align, uint16_t len) @@ -294,13 +296,228 @@ log_fcb_hdr_trailer_bytes(uint16_t align, uint16_t len) return align - mod; } +static int +log_fcb_write_mbuf(struct fcb_entry *loc, struct os_mbuf *om) +{ + int rc; + + while (om) { + rc = flash_area_write(loc->fe_area, loc->fe_data_off, om->om_data, + om->om_len); + if (rc != 0) { + return SYS_EIO; + } + loc->fe_data_off += om->om_len; + om = SLIST_NEXT(om, om_next); + } + + return 0; +} + +#if MYNEWT_VAL(LOG_FLAGS_TLV_SUPPORT) +static int +log_fcb_mbuf_single_tlv_write(struct os_mbuf *om, struct log_tlv *tlv, + void *val, uint8_t f_align, + struct fcb_entry *loc) +{ + uint16_t offset = 0; + int alignment = 0; + int rc = 0; + uint8_t buf[LOG_FCB_MAX_ALIGN] = {0}; + + /* Writes the following reverse TLVs, value first then length and + * then tag: + * + * Reverse TLV: + * --------------------------------------------------------- + * | Value | Value alignment | | TLV alignment | + * --------------------------------------------------------- + * TLV alignment is necessary here to aid in writing the next TLV + * from updated loc->fe_data_off. + * + * - Value is at alignment boundary + * - struct tlv is at alignment boundary + * + * Both can be read independently. + */ + rc = os_mbuf_append(om, val, tlv->len); + if (rc) { + return rc; + } + offset += tlv->len; + + /* Calculate value alignment */ + alignment = log_fcb_hdr_trailer_bytes(f_align, tlv->len); + rc = os_mbuf_append(om, buf, alignment); + if (rc) { + return rc; + } + offset += alignment; + + rc = os_mbuf_append(om, tlv, sizeof(*tlv)); + if (rc) { + return rc; + } + offset += sizeof(*tlv); + + /* Calculate tlv alignment */ + alignment = log_fcb_hdr_trailer_bytes(f_align, offset); + offset += alignment; + + rc = os_mbuf_append(om, buf, alignment); + if (rc) { + return rc; + } + + rc = log_fcb_write_mbuf(loc, om); + if (rc) { + return rc; + } + + return rc; +} + +static int +log_fcb_single_tlv_write(uint8_t *buf, uint16_t buflen, struct log_tlv *tlv, + void *val, uint8_t f_align, struct fcb_entry *loc) +{ + uint16_t offset = 0; + int alignment = 0; + int rc = 0; + + memset(buf, 0, buflen); + + /* Writes the following reverse TLVs, value first then length and + * then tag: + * + * Reverse TLV: + * --------------------------------------------------------- + * | Value | Value alignment | | TLV alignment | + * --------------------------------------------------------- + * TLV alignment is necessary here to aid in writing the next TLV + * from updated loc->fe_data_off. + * + * - Value is at alignment boundary + * - struct tlv is at alignment boundary + * + * Both can be read independently. + */ + memcpy(buf, val, tlv->len); + offset += tlv->len; + + /* Calculate value alignment */ + alignment = log_fcb_hdr_trailer_bytes(f_align, offset); + offset += alignment; + + memcpy(buf + offset, tlv, sizeof(*tlv)); + offset += sizeof(*tlv); + + /* Calculate tlv alignment */ + alignment = log_fcb_hdr_trailer_bytes(f_align, offset); + offset += alignment; + + rc = flash_area_write(loc->fe_area, loc->fe_data_off, buf, offset); + if (rc != 0) { + return rc; + } + + loc->fe_data_off += offset; + + return rc; +} + +static int +log_fcb_mbuf_tlvs_write(struct log *log, struct os_mbuf *om, + struct fcb_entry *loc) +{ + int rc = 0; + struct fcb *fcb; + struct fcb_log *fcb_log; + struct log_tlv tlv; + uint8_t num_tlvs = 0; + + fcb_log = (struct fcb_log *)log->l_arg; + fcb = &fcb_log->fl_fcb; + + (void)fcb; + (void)fcb_log; + (void)tlv; + (void)num_tlvs; + +#if MYNEWT_VAL(LOG_TLV_NUM_ENTRIES) + tlv.tag = LOG_TLV_NUM_ENTRIES; + tlv.len = LOG_NUM_ENTRIES_SIZE; + rc = log_fcb_mbuf_single_tlv_write(om, &tlv, &log->l_num_entries, + fcb->f_align, loc); + log->l_num_entries++; +#endif + + /* Always write the number of TLVS TLV at the end + * if num_tlvs > 1 + */ +#if MYNEWT_VAL(LOG_TLV_NUM_TLVS) + if (num_tlvs > 1) { + tlv.tag = LOG_TLV_NUM_TLVS; + tlv.len = LOG_NUM_TLVS_SIZE; + rc = log_fcb_mbuf_single_tlv_write(om, &tlv, &num_tlvs, + fcb->f_align, loc); + } +#endif + + return rc; +} + +static int +log_fcb_tlvs_write(struct log *log, uint8_t *buf, uint16_t buflen, + struct fcb_entry *loc) +{ + int rc = 0; + struct fcb *fcb; + struct fcb_log *fcb_log; + struct log_tlv tlv; + uint8_t num_tlvs = 0; + + fcb_log = (struct fcb_log *)log->l_arg; + fcb = &fcb_log->fl_fcb; + + (void)fcb; + (void)fcb_log; + (void)tlv; + (void)num_tlvs; + +#if MYNEWT_VAL(LOG_TLV_NUM_ENTRIES) + tlv.tag = LOG_TLV_NUM_ENTRIES; + tlv.len = LOG_NUM_ENTRIES_SIZE; + rc = log_fcb_single_tlv_write(buf, buflen, &tlv, &log->l_num_entries, + fcb->f_align, loc); + if (rc) { + return rc; + } + log->l_num_entries++; + num_tlvs++; +#endif + + /* Always write the number of TLVS TLV at the end + * if num_tlvs > 1 + */ +#if MYNEWT_VAL(LOG_TLV_NUM_TLVS) + if (num_tlvs > 1) { + tlv.tag = LOG_TLV_NUM_TLVS; + tlv.len = LOG_NUM_TLVS_SIZE; + rc = log_fcb_single_tlv_write(buf, buflen, &tlv, &num_tlvs, + fcb->f_align, loc); + } +#endif + + return rc; +} +#endif + 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 + sizeof(struct log_tlv) + LOG_NUM_ENTRIES_SIZE + - LOG_FCB_MAX_ALIGN * 2 - 1]; + uint8_t buf[LOG_FCB_FLAT_BUF_SIZE] = {0}; struct fcb *fcb; struct fcb_entry loc; struct fcb_log *fcb_log; @@ -311,16 +528,22 @@ log_fcb_append_body(struct log *log, const struct log_entry_hdr *hdr, int rc; uint16_t hdr_len; uint16_t trailer_len; + 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; + (void)trailer_alignment; + if (fcb->f_align > LOG_FCB_MAX_ALIGN) { return SYS_ENOTSUP; } hdr_len = log_hdr_len(hdr); - trailer_len = log_trailer_len(hdr); + trailer_len = log_trailer_len(log, hdr); rc = log_fcb_start_append(log, hdr_len + body_len + trailer_len, &loc); if (rc != 0) { @@ -366,22 +589,15 @@ log_fcb_append_body(struct log *log, const struct log_entry_hdr *hdr, body_len -= hdr_alignment; if (hdr->ue_flags & LOG_FLAGS_TLV_SUPPORT) { - memset(buf, 0, sizeof(buf)); +#if MYNEWT_VAL(LOG_FLAGS_TLV_SUPPORT) + /* This writes padding + trailer_alignment */ + /* Calculate trailer alignment */ trailer_alignment = log_fcb_hdr_trailer_bytes(fcb->f_align, chunk_sz + body_len); - if (trailer_alignment > trailer_len) { - chunk_sz = trailer_len; - } else { - chunk_sz = trailer_alignment; - } - -#if MYNEWT_VAL(LOG_FLAGS_TLV_SUPPORT) && MYNEWT_VAL(LOG_TLV_NUM_ENTRIES) - struct log_tlv tlv; - uint16_t offset = 0; - uint16_t padding = 0; if (body_len > 0) { padding = trailer_alignment ? fcb->f_align - trailer_alignment : 0; + /* Writes body - padding bytes */ rc = flash_area_write(loc.fe_area, loc.fe_data_off, u8p, body_len - padding); if (rc != 0) { @@ -391,24 +607,29 @@ log_fcb_append_body(struct log *log, const struct log_entry_hdr *hdr, loc.fe_data_off += body_len - padding; u8p = u8p + body_len - padding; + memset(buf, 0, sizeof(buf)); memcpy(buf, u8p, padding); offset = padding; - u8p = (void *)&tlv; - tlv.tag = LOG_TLV_NUM_ENTRIES; - tlv.len = LOG_NUM_ENTRIES_SIZE; - memcpy(buf + offset, u8p, sizeof(struct log_tlv)); - offset += sizeof(struct log_tlv); - - memcpy(buf + offset, &log->l_num_entries, LOG_NUM_ENTRIES_SIZE); - log->l_num_entries++; - offset += LOG_NUM_ENTRIES_SIZE; - + offset += trailer_alignment; + /* Writes the following: + * ----------------------------------------------------------------- + * | body: body_len - padding from end of body | trailer_alignment | + * ----------------------------------------------------------------- + */ rc = flash_area_write(loc.fe_area, loc.fe_data_off, buf, offset); if (rc != 0) { return rc; } loc.fe_data_off += offset; + + /* The first TLV gets appended after the padding + trailer_alignment + * Trailers start from updated loc.fe_data_off. + */ + rc = log_fcb_tlvs_write(log, buf, sizeof(buf), &loc); + if (rc) { + return rc; + } } #else if (body_len > 0) { @@ -446,25 +667,6 @@ log_fcb_append(struct log *log, void *buf, int len) len - hdr_len); } -static int -log_fcb_write_mbuf(struct fcb_entry *loc, struct os_mbuf *om) -{ - int rc; - - while (om) { - rc = flash_area_write(loc->fe_area, loc->fe_data_off, om->om_data, - om->om_len); - if (rc != 0) { - return SYS_EIO; - } - - loc->fe_data_off += om->om_len; - om = SLIST_NEXT(om, om_next); - } - - return 0; -} - static int log_fcb_append_mbuf_body(struct log *log, const struct log_entry_hdr *hdr, struct os_mbuf *om) @@ -485,7 +687,7 @@ log_fcb_append_mbuf_body(struct log *log, const struct log_entry_hdr *hdr, return SYS_ENOTSUP; } - len = log_hdr_len(hdr) + os_mbuf_len(om) + log_trailer_len(hdr); + len = log_hdr_len(hdr) + os_mbuf_len(om) + log_trailer_len(log, hdr); rc = log_fcb_start_append(log, len, &loc); if (rc != 0) { return rc; @@ -508,32 +710,22 @@ log_fcb_append_mbuf_body(struct log *log, const struct log_entry_hdr *hdr, loc.fe_data_off += LOG_IMG_HASHLEN; } - rc = log_fcb_write_mbuf(&loc, om); - if (rc != 0) { - return rc; - } - if (hdr->ue_flags & LOG_FLAGS_TLV_SUPPORT) { -#if MYNEWT_VAL(LOG_FLAGS_TLV_SUPPORT) && MYNEWT_VAL(LOG_TLV_NUM_ENTRIES) - struct log_tlv tlv; - tlv.tag = LOG_TLV_NUM_ENTRIES; - tlv.len = LOG_NUM_ENTRIES_SIZE; - /* Write TLV */ - rc = flash_area_write(loc.fe_area, loc.fe_data_off, &tlv, - sizeof(struct log_tlv)); +#if MYNEWT_VAL(LOG_FLAGS_TLV_SUPPORT) + /* The first TLV gets appended after the padding + trailer_alignment + * Trailers start from updated loc.fe_data_off. Write everything + * together + */ + rc = log_fcb_mbuf_tlvs_write(log, om, &loc); if (rc != 0) { return rc; } - loc.fe_data_off += sizeof(struct log_tlv);; - /* Write LOG_NUM_ENTRIES_SIZE bytes */ - rc = flash_area_write(loc.fe_area, loc.fe_data_off, - &hdr->ue_num_entries, LOG_NUM_ENTRIES_SIZE); +#endif + } else { + rc = log_fcb_write_mbuf(&loc, om); if (rc != 0) { return rc; } - loc.fe_data_off += LOG_NUM_ENTRIES_SIZE; - log->l_num_entries++; -#endif } rc = fcb_append_finish(fcb, &loc); @@ -884,6 +1076,18 @@ log_fcb_new_watermark_index(struct log *log, struct log_offset *log_offset, } } +static int +log_fcb_len_in_medium(struct log *log, uint16_t len) +{ + struct fcb_log *fl; + struct fcb *fcb; + + fl = (struct fcb_log *)log->l_arg; + fcb = &fl->fl_fcb; + + return fcb_len_in_flash(fcb, len); +} + static int log_fcb_set_watermark(struct log *log, uint32_t index) { @@ -1086,6 +1290,7 @@ const struct log_handler log_fcb_handler = { #endif #if MYNEWT_VAL(LOG_STORAGE_WATERMARK) .log_set_watermark = log_fcb_set_watermark, + .log_len_in_medium = log_fcb_len_in_medium, #endif .log_registered = log_fcb_registered, }; diff --git a/sys/log/full/src/log_fcb2.c b/sys/log/full/src/log_fcb2.c index 94413c4c65..9413fa1d22 100644 --- a/sys/log/full/src/log_fcb2.c +++ b/sys/log/full/src/log_fcb2.c @@ -217,23 +217,232 @@ log_fcb2_hdr_body_bytes(uint16_t align, uint16_t len) return align - mod; } +static int +log_fcb2_write_mbuf(struct fcb2_entry *loc, struct os_mbuf *om, int off) +{ + int rc; + + while (om) { + rc = fcb2_write(loc, off, om->om_data, om->om_len); + if (rc != 0) { + return SYS_EIO; + } + + off += om->om_len; + om = SLIST_NEXT(om, om_next); + } + + return SYS_EOK; +} + + +#if MYNEWT_VAL(LOG_FLAGS_TLV_SUPPORT) +static int +log_fcb2_mbuf_single_tlv_write(struct os_mbuf *om, struct log_tlv *tlv, + void *val, uint8_t f_align, + struct fcb2_entry *loc, int len) +{ + uint16_t offset = 0; + int alignment = 0; + int rc = 0; + uint8_t buf[LOG_FCB2_MAX_ALIGN] = {0}; + + /* Writes the following reverse TLVs, value first then length and + * then tag: + * + * Reverse TLV: + * --------------------------------------------------------- + * | Value | Value alignment | | TLV alignment | + * --------------------------------------------------------- + * TLV alignment is necessary here to aid in writing the next TLV + * from updated loc->fe_data_off. + * + * - Value is at alignment boundary + * - struct tlv is at alignment boundary + * + * Both can be read independently. + */ + rc = os_mbuf_append(om, val, tlv->len); + if (rc) { + return rc; + } + offset += tlv->len; + + /* Calculate value alignment */ + alignment = log_fcb2_hdr_body_bytes(f_align, tlv->len); + rc = os_mbuf_append(om, buf, alignment); + if (rc) { + return rc; + } + offset += alignment; + + rc = os_mbuf_append(om, tlv, sizeof(*tlv)); + if (rc) { + return rc; + } + offset += sizeof(*tlv); + + /* Calculate tlv alignment */ + alignment = log_fcb2_hdr_body_bytes(f_align, offset); + offset += alignment; + + rc = os_mbuf_append(om, buf, alignment); + if (rc) { + return rc; + } + + rc = log_fcb2_write_mbuf(loc, om, len); + if (rc) { + return rc; + } + + return rc; +} + +static int +log_fcb2_single_tlv_write(uint8_t *buf, uint16_t buflen, struct log_tlv *tlv, + void *val, uint8_t f_align, struct fcb2_entry *loc, + uint16_t *f_offset) +{ + uint16_t offset = 0; + int alignment = 0; + int rc = 0; + + memset(buf, 0, buflen); + + /* Writes the following reverse TLVs, value first then length and + * then tag: + * + * Reverse TLV: + * --------------------------------------------------------- + * | Value | Value alignment | | TLV alignment | + * --------------------------------------------------------- + * TLV alignment is necessary here to aid in writing the next TLV + * from updated loc.fe_data_off. + * + * - Value is at alignment boundary + * - struct tlv is at alignment boundary + * + * Both can be read independently. + */ + memcpy(buf, val, tlv->len); + offset += tlv->len; + + /* Calculate value alignment */ + alignment = log_fcb2_hdr_body_bytes(f_align, offset); + offset += alignment; + + memcpy(buf + offset, tlv, sizeof(*tlv)); + offset += sizeof(*tlv); + + /* Calculate tlv alignment */ + alignment = log_fcb2_hdr_body_bytes(f_align, offset); + offset += alignment; + + rc = fcb2_write(loc, *f_offset, buf, offset); + if (rc != 0) { + return rc; + } + + *f_offset += offset; + + return rc; +} + +static int +log_fcb2_tlvs_write(struct log *log, uint8_t *buf, uint16_t buflen, + struct fcb2_entry *loc, uint16_t *f_offset) +{ + int rc = 0; + struct log_tlv tlv; + uint8_t num_tlvs = 0; + + (void)tlv; +#if MYNEWT_VAL(LOG_TLV_NUM_ENTRIES) + tlv.tag = LOG_TLV_NUM_ENTRIES; + tlv.len = LOG_NUM_ENTRIES_SIZE; + rc = log_fcb2_single_tlv_write(buf, buflen, &tlv, &log->l_num_entries, + loc->fe_range->fsr_align, loc, f_offset); + log->l_num_entries++; + num_tlvs++; +#endif + + /* Always write the number of TLVS TLV at the end + * if num_tlvs > 1 + */ +#if MYNEWT_VAL(LOG_TLV_NUM_TLVS) + if (num_tlvs > 1) { + tlv.tag = LOG_TLV_NUM_TLVS; + tlv.len = LOG_NUM_TLVS_SIZE; + rc = log_fcb2_single_tlv_write(buf, buflen, &tlv, &num_tlvs, + loc->fe_range->fsr_align, loc, f_offset); + } +#endif + + return rc; +} + +static int +log_fcb2_mbuf_tlvs_write(struct log *log, struct os_mbuf *om, + struct fcb2_entry *loc, int len) +{ + int rc = 0; + struct fcb2 *fcb; + struct fcb_log *fcb_log; + struct log_tlv tlv; + uint8_t num_tlvs = 0; + + fcb_log = (struct fcb_log *)log->l_arg; + fcb = &fcb_log->fl_fcb; + + (void)fcb; + (void)fcb_log; + (void)tlv; + (void)num_tlvs; + +#if MYNEWT_VAL(LOG_TLV_NUM_ENTRIES) + tlv.tag = LOG_TLV_NUM_ENTRIES; + tlv.len = LOG_NUM_ENTRIES_SIZE; + rc = log_fcb2_mbuf_single_tlv_write(om, &tlv, &log->l_num_entries, + loc->fe_range->fsr_align, loc, len); + log->l_num_entries++; +#endif + + /* Always write the number of TLVS TLV at the end + * if num_tlvs > 1 + */ +#if MYNEWT_VAL(LOG_TLV_NUM_TLVS) + if (num_tlvs > 1) { + tlv.tag = LOG_TLV_NUM_TLVS; + tlv.len = LOG_NUM_TLVS_SIZE; + rc = log_fcb2_mbuf_single_tlv_write(om, &tlv, &num_tlvs, + loc->fe_range->fsr_align, + loc, len); + } +#endif + + return rc; +} +#endif + static int log_fcb2_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 + sizeof(struct log_tlv) - + LOG_NUM_ENTRIES_SIZE + LOG_FCB2_MAX_ALIGN * 2 - 1]; + uint8_t buf[LOG_FCB_FLAT_BUF_SIZE] = {0}; struct fcb2_entry loc; const uint8_t *u8p; int hdr_alignment; int trailer_alignment = 0; - int chunk_sz = 0; + uint16_t chunk_sz = 0; int rc; uint16_t hdr_len; uint16_t trailer_len; hdr_len = log_hdr_len(hdr); - trailer_len = log_trailer_len(hdr); + trailer_len = log_trailer_len(log, hdr); + + (void)trailer_alignment; rc = log_fcb2_start_append(log, hdr_len + body_len + trailer_len, &loc); if (rc != 0) { @@ -278,14 +487,8 @@ log_fcb2_append_body(struct log *log, const struct log_entry_hdr *hdr, memset(buf, 0, sizeof(buf)); /* Calculate trailer alignment */ trailer_alignment = log_fcb2_hdr_body_bytes(loc.fe_range->fsr_align, chunk_sz + body_len); - if (trailer_alignment > trailer_len) { - chunk_sz += trailer_len; - } else { - chunk_sz += trailer_alignment; - } -#if MYNEWT_VAL(LOG_FLAGS_TLV_SUPPORT) && MYNEWT_VAL(LOG_TLV_NUM_ENTRIES) - struct log_tlv tlv; +#if MYNEWT_VAL(LOG_FLAGS_TLV_SUPPORT) uint16_t offset = 0; uint16_t padding = 0; @@ -301,23 +504,25 @@ log_fcb2_append_body(struct log *log, const struct log_entry_hdr *hdr, u8p = u8p + body_len - padding; memcpy(buf, u8p, padding); offset = padding; - u8p = (void *)&tlv; - tlv.tag = LOG_TLV_NUM_ENTRIES; - tlv.len = LOG_NUM_ENTRIES_SIZE; - memcpy(buf + offset, u8p, sizeof(struct log_tlv)); - offset += sizeof(struct log_tlv); - - memcpy(buf + offset, &log->l_num_entries, LOG_NUM_ENTRIES_SIZE); - offset += LOG_NUM_ENTRIES_SIZE; - + offset += trailer_alignment; + /* Writes the following: + * ----------------------------------------------------------------- + * | body: body_len - padding from end of body | trailer_alignment | + * ----------------------------------------------------------------- + */ rc = fcb2_write(&loc, chunk_sz, buf, offset); if (rc != 0) { return rc; } - log->l_num_entries++; - chunk_sz += offset; + /* The first TLV gets appended after the padding + trailer_alignment + * Trailers start from updated chunk_sz offset. + */ + rc = log_fcb2_tlvs_write(log, buf, sizeof(buf), &loc, &chunk_sz); + if (rc) { + return rc; + } } #else if (body_len > 0) { @@ -357,24 +562,6 @@ log_fcb2_append(struct log *log, void *buf, int len) len - hdr_len); } -static int -log_fcb2_write_mbuf(struct fcb2_entry *loc, struct os_mbuf *om, int off) -{ - int rc; - - while (om) { - rc = fcb2_write(loc, off, om->om_data, om->om_len); - if (rc != 0) { - return SYS_EIO; - } - - off += om->om_len; - om = SLIST_NEXT(om, om_next); - } - - return off; -} - static int log_fcb2_append_mbuf_body(struct log *log, const struct log_entry_hdr *hdr, struct os_mbuf *om) @@ -395,7 +582,7 @@ log_fcb2_append_mbuf_body(struct log *log, const struct log_entry_hdr *hdr, } #endif - len = log_hdr_len(hdr) + os_mbuf_len(om) + log_trailer_len(hdr); + len = log_hdr_len(hdr) + os_mbuf_len(om) + log_trailer_len(log, hdr); rc = log_fcb2_start_append(log, len, &loc); if (rc != 0) { return rc; @@ -416,31 +603,22 @@ log_fcb2_append_mbuf_body(struct log *log, const struct log_entry_hdr *hdr, len += LOG_IMG_HASHLEN; } - len = log_fcb2_write_mbuf(&loc, om, len); - if (len < 0) { - return len; - } - if (hdr->ue_flags & LOG_FLAGS_TLV_SUPPORT) { -#if MYNEWT_VAL(LOG_FLAGS_TLV_SUPPORT) && MYNEWT_VAL(LOG_TLV_NUM_ENTRIES) - struct log_tlv tlv; - tlv.tag = LOG_TLV_NUM_ENTRIES; - tlv.len = LOG_NUM_ENTRIES_SIZE; - /* Write TLV */ - rc = fcb2_write(&loc, len, &tlv, sizeof(struct log_tlv)); +#if MYNEWT_VAL(LOG_FLAGS_TLV_SUPPORT) + /* The first TLV gets appended after the padding + trailer_alignment + * Trailers start from updated loc.fe_data_off. Write everything + * together + */ + rc = log_fcb2_mbuf_tlvs_write(log, om, &loc, len); if (rc != 0) { return rc; } - len += sizeof(struct log_tlv); - /* Write LOG_NUM_ENTRIES_SIZE bytes */ - rc = fcb2_write(&loc, len, - &hdr->ue_num_entries, LOG_NUM_ENTRIES_SIZE); +#endif + } else { + rc = log_fcb2_write_mbuf(&loc, om, len); if (rc != 0) { return rc; } - len += LOG_NUM_ENTRIES_SIZE; - log->l_num_entries++; -#endif } rc = fcb2_append_finish(&loc); @@ -451,6 +629,18 @@ log_fcb2_append_mbuf_body(struct log *log, const struct log_entry_hdr *hdr, return 0; } +static int +log_fcb2_len_in_medium(struct log *log, uint16_t len) +{ + struct fcb_log *fl; + struct fcb2 *fcb; + + fl = (struct fcb_log *)log->l_arg; + fcb = &fl->fl_fcb; + + return fcb2_len_in_flash(fcb->f_active.fe_range, len); +} + static int log_fcb2_append_mbuf(struct log *log, struct os_mbuf *om) { @@ -992,6 +1182,7 @@ const struct log_handler log_fcb_handler = { .log_walk = log_fcb2_walk, .log_flush = log_fcb2_flush, .log_read_entry_len = log_fcb2_read_entry_len, + .log_len_in_medium = log_fcb2_len_in_medium, #if MYNEWT_VAL(LOG_STORAGE_INFO) .log_storage_info = log_fcb2_storage_info, #endif diff --git a/sys/log/full/src/log_shell.c b/sys/log/full/src/log_shell.c index e86a90bd31..0acfaf0791 100644 --- a/sys/log/full/src/log_shell.c +++ b/sys/log/full/src/log_shell.c @@ -56,16 +56,23 @@ shell_log_dump_entry(struct log *log, struct log_offset *log_offset, bool read_hash = ueh->ue_flags & LOG_FLAGS_IMG_HASH; #if MYNEWT_VAL(LOG_FLAGS_TLV_SUPPORT) && MYNEWT_VAL(LOG_TLV_NUM_ENTRIES) bool read_num_entries = ueh->ue_flags & LOG_FLAGS_TLV_SUPPORT; - uint32_t entries = 0; #else bool read_num_entries = false; #endif + uint32_t entries = 0; dlen = min(len, 128); if (read_data) { -#if MYNEWT_VAL(LOG_FLAGS_TLV_SUPPORT) && MYNEWT_VAL(LOG_TLV_NUM_ENTRIES) - dlen -= sizeof(struct log_tlv) + LOG_NUM_ENTRIES_SIZE; +#if MYNEWT_VAL(LOG_FLAGS_TLV_SUPPORT) + dlen -= log_len_in_medium(log, sizeof(struct log_tlv)); + + rc = log_read_trailer(log, dptr, LOG_TLV_NUM_ENTRIES, &entries); + if (!rc) { + dlen -= log_len_in_medium(log, LOG_NUM_ENTRIES_SIZE); + } else { + console_printf("failed to read trailer\n"); + } #endif rc = log_read_body(log, dptr, data, 0, dlen); if (rc < 0) { @@ -81,13 +88,13 @@ shell_log_dump_entry(struct log *log, struct log_offset *log_offset, if (read_num_entries) { #if MYNEWT_VAL(LOG_FLAGS_TLV_SUPPORT) + dlen -= log_len_in_medium(log, sizeof(struct log_tlv)); rc = log_read_trailer(log, dptr, LOG_TLV_NUM_ENTRIES, &entries); if (!rc) { -#if MYNEWT_VAL(LOG_TLV_NUM_ENTRIES) - console_printf("[ne=%lu]", entries); -#endif + dlen -= log_len_in_medium(log, LOG_NUM_ENTRIES_SIZE); } #endif + console_printf("[ne=%u]", (unsigned int)entries); } console_printf(" [%llu] ", ueh->ue_ts); #if MYNEWT_VAL(LOG_SHELL_SHOW_INDEX)