This is an automated email from the ASF dual-hosted git repository.

vipulrahane pushed a commit to branch vipul/logging_num_entries_callbacks
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git

commit c0e4fa93c8fa40b378dab9acc305c5293d22ffd6
Author: Vipul Rahane <vipul.rah...@juul.com>
AuthorDate: Mon Mar 18 11:00:56 2024 -0700

    sys/log, fs/fcb: Add trailer per entry in logs
    
    - This support is added for fcb/fcb2 and cbmem
    - Trailer callbacks can be enabled using
      LOG_FLAGS_TRAILER_SUPPORT.
    - This is needed since we cannot update the log header
      without breaking backwards compatibility
    - Adding a trailer keeps the log header in place and the entry
      intact. On an upgrade or downgrade, log entries are still
      readable.
    - Trailer callbacks can be registered using log_trailer_cbs_register().
    - Trailer data is managed by the callbacks
    - Fix unittests and some minor inconsistencies in doxygen descriptions
      of the functions in the include headers for logs
---
 fs/fcb2/include/fcb/fcb2.h     |   9 ++
 fs/fcb2/src/fcb.c              |   9 ++
 fs/fcb2/src/fcb_priv.h         |   9 --
 hw/mcu/native/src/hal_flash.c  |   2 +-
 sys/log/full/include/log/log.h | 255 ++++++++++++++++++++++++++++++++++++++---
 sys/log/full/src/log.c         | 159 +++++++++++++++++++++++--
 sys/log/full/src/log_cbmem.c   |  97 ++++++++++++++--
 sys/log/full/src/log_fcb.c     | 207 ++++++++++++++++++++++++---------
 sys/log/full/src/log_fcb2.c    | 180 +++++++++++++++++++++++------
 sys/log/full/syscfg.yml        |  10 ++
 10 files changed, 790 insertions(+), 147 deletions(-)

diff --git a/fs/fcb2/include/fcb/fcb2.h b/fs/fcb2/include/fcb/fcb2.h
index e089fccbc..2f0c72090 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 e8a65ff12..0f1e31ee3 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 d02784fab..6f91ff09f 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/hw/mcu/native/src/hal_flash.c b/hw/mcu/native/src/hal_flash.c
index b39b5158c..439f9d4fa 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 5fb2587c2..5c99624c8 100644
--- a/sys/log/full/include/log/log.h
+++ b/sys/log/full/include/log/log.h
@@ -77,7 +77,74 @@ struct log_storage_info {
 };
 #endif
 
-typedef int (*log_walk_func_t)(struct log *, struct log_offset *log_offset,
+/** @typedef log_trailer_append_func_t
+ * @brief Callback that is executed each time the corresponding log entry is
+ * appended to
+ *
+ * @param log                   The log that was just appended to
+ * @param buf                   Buffer to append trailer to
+ * @param buflen                Pointer to the length of the trailer to be 
filled up
+ *                              optionally
+ * @param loc                   Argument pointing to the location of
+ *                              the entry
+ * @param f_offset              Pointer to the offset(optional) at which 
append should
+ *                              happen
+ *
+ * @return                      0 on success, non-zero on failure
+ */
+typedef int log_trailer_append_func_t(struct log *log, uint8_t *buf,
+                                      uint16_t *buflen, void *loc,
+                                      uint16_t *f_offset);
+
+/** @typedef log_mbuf_trailer_append_func_t
+ * @brief Callback that is executed each time the corresponding log entry is
+ * appended to
+ *
+ * @param log                   The log that was just appended to
+ * @param om                    Pointer to the mbuf that contains the log entry
+ * @param loc                   Argument pointing to the location of
+ *                              the entry
+ * @param f_offset              The offset(optional) at which append should
+ *                              happen
+ *
+ * @return                      0 on success, non-zero on failure
+ */
+typedef int log_trailer_mbuf_append_func_t(struct log *log, struct os_mbuf *om,
+                                           void *loc, uint16_t f_offset);
+
+/** @typedef log_process_trailer_func_t
+ * @brief Callback that is executed each time a trailer is processed
+ *
+ * @param log                   The log that was just appended to
+ * @param arg                   Optional argument to read trailer into
+ * @param dptr                  Pointer to the data buffer
+ * @param len                   Length of the trailer
+ *
+ * @return                      0 on success, non-zero on failure
+ */
+typedef int log_process_trailer_func_t(struct log *log, void *arg, const void 
*dptr,
+                                       uint16_t len);
+
+/** @typedef log_trailer_len_func_t
+ * @brief Callback used to read length of trailer in a log entry
+ *
+ * @param log                   The log the trailer is to be read from
+ * @param hdr                   Log entry header of the log entry the log is
+ *                              read from
+ * @return                      Length of the appended trailer
+ */
+typedef uint16_t log_trailer_len_func_t(struct log *log, const struct 
log_entry_hdr *hdr);
+
+/** @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
+ *
+ * @return                      0 on success, non-zero on failure.
+ */
+typedef int log_trailer_reset_data_func_t(struct log *log);
+
+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,
@@ -99,13 +166,16 @@ 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 *);
+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);
 #endif
 typedef int (*lh_registered_func_t)(struct 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 +188,8 @@ 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;
+    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
@@ -131,8 +203,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*/
-#define LOG_FLAGS_IMG_HASH (1 << 0)
+/* Flags used to indicate type of data in reserved payload */
+#define LOG_FLAGS_IMG_HASH           (1 << 0)
+#define LOG_FLAGS_TRAILER_SUPPORT    (1 << 1)
 
 #if MYNEWT_VAL(LOG_VERSION) == 3
 struct log_entry_hdr {
@@ -140,16 +213,38 @@ struct log_entry_hdr {
     uint32_t ue_index;
     uint8_t ue_module;
     uint8_t ue_level;
-    uint8_t ue_etype:4;
-    uint8_t ue_flags:4;
+    uint8_t ue_etype : 4;
+    uint8_t ue_flags : 4;
     uint8_t ue_imghash[4];
-}__attribute__((__packed__));
+} __attribute__((__packed__));
 #else
 #error "Unsupported log version"
 #endif
 
 #define LOG_BASE_ENTRY_HDR_SIZE (15)
 
+/* Assume the flash alignment requirement is no stricter than 32. */
+#define LOG_FCB_MAX_ALIGN    32
+#define LOG_FCB2_MAX_ALIGN   32
+
+
+#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_EXT_HDR_SIZE LOG_BASE_ENTRY_HDR_SIZE + LOG_IMG_HASHLEN + \
+    LF_MAX_ALIGN
+
+#ifndef LOG_FCB_FLAT_BUF_SIZE
+/* Assuming the trailer fits in this, an arbitrary value */
+#define LOG_FCB_FLAT_BUF_SIZE (LOG_FCB_EXT_HDR_SIZE > LF_MAX_ALIGN * 3) ? \
+    LOG_FCB_EXT_HDR_SIZE : LF_MAX_ALIGN * 3
+#endif
+
+#define LOG_MAX_TRAILER_LEN    MYNEWT_VAL(LOG_MAX_TRAILER_LEN)
+
 #define LOG_MODULE_STR(module)      log_module_get_name(module)
 
 #if MYNEWT_VAL(LOG_LEVEL) <= LOG_LEVEL_DEBUG
@@ -204,6 +299,28 @@ STATS_SECT_END
 #define LOG_STATS_INCN(log, name, cnt)
 #endif
 
+/* Trailer support callbacks */
+struct log_trailer_handler {
+    /* Trailer length callback used to get the length of the trailer from 
provided
+     * log entry
+     */
+    log_trailer_len_func_t *log_trailer_len;
+    /* Trailer append callback used to append trailer to the log entry */
+    log_trailer_append_func_t *log_trailer_append;
+    /* Trailer process callback used to process trailer from the log entry
+     * which gets called at various places where the log entry gets read
+     */
+    log_process_trailer_func_t *log_process_trailer;
+    /* Trailer mbuf append callback used to append trailer to the log entry
+     * using the mbufs
+     */
+    log_trailer_mbuf_append_func_t *log_trailer_mbuf_append;
+    /* 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 *log_trailer_reset_data;
+};
+
 struct log {
     const char *l_name;
     const struct log_handler *l_log;
@@ -219,6 +336,8 @@ struct log {
 #if MYNEWT_VAL(LOG_STATS)
     STATS_SECT_DECL(logs) l_stats;
 #endif
+    /* Gets set when trailer callbacks are registered */
+    struct log_trailer_handler *l_th;
 };
 
 /* Log system level functions (for all logs.) */
@@ -514,6 +633,18 @@ 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);
 
+/**
+ * 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
+log_read_entry_len(struct log *log, const void *dptr);
+
 /**
  * @brief Reads a single log entry header.
  *
@@ -531,7 +662,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
@@ -679,9 +810,9 @@ uint8_t log_get_level(const struct log *log);
 void log_set_max_entry_len(struct log *log, uint16_t max_entry_len);
 
 /**
- * Return last entry index in log.
+ * @brief Return last entry index in log.
  *
- * @param log Log to check last entry index from.
+ * @param log    Log to check last entry index from.
  *
  * @return last entry index
  */
@@ -689,13 +820,13 @@ uint32_t log_get_last_index(struct log *log);
 
 #if MYNEWT_VAL(LOG_STORAGE_INFO)
 /**
- * Return information about log storage
+ * @brief Return information about log storage
  *
  * This return information about size and usage of storage on top of which log
  * instance is created.
  *
- * @param log   The log to query.
- * @param info  The destination to write information to.
+ * @param log    The log to query.
+ * @param info   The destination to write information to.
  *
  * @return 0 on success, error code otherwise
  *
@@ -704,10 +835,10 @@ int log_storage_info(struct log *log, struct 
log_storage_info *info);
 #endif
 
 /**
- * Assign a callback function to be notified when the log is about to be 
rotated.
+ * @brief Assign a callback function to be notified when the log is about to 
be rotated.
  *
- * @param log   The log
- * @param cb    The callback function to be executed.
+ * @param log    The log
+ * @param cb     The callback function to be executed.
  */
 void
 log_set_rotate_notify_cb(struct log *log, log_notify_rotate_cb *cb);
@@ -731,12 +862,98 @@ int log_set_watermark(struct log *log, uint32_t index);
 /**
  * Fill log current image hash
  *
- * @param hdr Ptr to the header
+ * @param hdr    Ptr to the header
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int log_fill_current_img_hash(struct log_entry_hdr *hdr);
+
+/**
+ * @brief 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);
+
+/**
+ * @brief Reads the trailer length
+ *
+ * @param hdr    Ptr to the header
+ *
+ * @return Length of the trailer
+ */
+uint16_t log_trailer_len(struct log *log, const struct log_entry_hdr *hdr);
+
+/**
+ * @brief Append trailer to the log entry
+ *
+ * @param log        Pointer to the log
+ * @param buf        Pointer to the buffer containing trailer
+ * @param buflen     Pointer to the length of the trailer
+ * @param loc        Pointer to the log entry
+ * @param f_offset   Pointer to the offset(optional) at which append should
+ *                   happen, gets updated once append is successful
+ * @return 0 on success, non-zero on failure
+ */
+int log_trailer_append(struct log *log, uint8_t *buf, uint16_t *buflen,
+                       void *loc, uint16_t *f_offset);
+
+/**
+ * @brief Append trailer in an mbuf to the log entry
+ *
+ * @param log        Pointer to the log
+ * @param om         Pointer to the os_mbuf
+ * @param loc        Pointer to the log entry
+ * @param f_offset   The offset(optional) at which append should
+ *                   happen
+ * @return 0 on success; nonzero on failure.
+ */
+int log_mbuf_trailer_append(struct log *log, struct os_mbuf *om, void *loc,
+                            uint16_t f_offset);
+
+/**
+ * @brief Reads the final log entry's header and processes trailer if the flag
+ * indicates so from the specified log.
+ *
+ * @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);
+
+/**
+ * @brief Reset log trailer data
+ *
+ * @param log   The log to reset trailer data for
  *
  * @return 0 on success, non-zero on failure
  */
-int
-log_fill_current_img_hash(struct log_entry_hdr *hdr);
+int log_trailer_reset_data(struct log *log);
+
+/**
+ * @brief Register trailer callbacks
+ *
+ * @param log    The log to read from.
+ * @param lth    The trailer handler to register.
+ * @param data   Pointer to the trailer data.
+ * @param trailer_len   Length of the trailer data.
+ *
+ * @return 0 on success; nonzero on failure.
+ */
+static inline void
+log_trailer_cbs_register(struct log *log, struct log_trailer_handler *lth)
+{
+    if (!lth || !log) {
+        return;
+    }
+
+    log->l_th = lth;
+}
 
 /* Handler exports */
 #if MYNEWT_VAL(LOG_CONSOLE)
diff --git a/sys/log/full/src/log.c b/sys/log/full/src/log.c
index 23dece179..3b2d7b7dc 100644
--- a/sys/log/full/src/log.c
+++ b/sys/log/full/src/log.c
@@ -294,14 +294,18 @@ log_find(const char *name)
     return log;
 }
 
+/* Argument for header/trailer walks */
 struct log_read_hdr_arg {
     struct log_entry_hdr *hdr;
     int read_success;
+#if MYNEWT_VAL(LOG_FLAGS_TRAILER_SUPPORT)
+    bool trailer_exists;
+#endif
 };
 
 static int
-log_read_hdr_walk(struct log *log, struct log_offset *log_offset, const void 
*dptr,
-                  uint16_t len)
+log_read_hdr_trailer_walk(struct log *log, struct log_offset *log_offset,
+                          const void *dptr, uint16_t len)
 {
     struct log_read_hdr_arg *arg;
     int rc;
@@ -320,21 +324,41 @@ log_read_hdr_walk(struct log *log, struct log_offset 
*log_offset, const void *dp
         }
     }
 
+    if (arg->hdr->ue_flags & LOG_FLAGS_TRAILER_SUPPORT && log->l_th) {
+#if MYNEWT_VAL(LOG_FLAGS_TRAILER_SUPPORT)
+        if (log->l_th->log_process_trailer) {
+            rc = log->l_th->log_process_trailer(log, NULL, dptr, len);
+            if (!rc) {
+                arg->read_success = 1;
+                arg->trailer_exists = true;
+            } else {
+                arg->read_success = 0;
+                arg->trailer_exists = false;
+            }
+        }
+    } else {
+        arg->trailer_exists = false;
+#endif
+    }
+
     /* Abort the walk; only one header needed. */
     return 1;
 }
 
 /**
- * Reads the final log entry's header from the specified log.
+ * Reads the final log entry's header and processes trailer if the flag
+ * indicates so from the specified log.
  *
  * @param log                   The log to read from.
  * @param out_hdr               On success, the last entry header gets written
- *                                  here.
+ *                              here.
+ * @param trailer_exists        Pointer to a boolean
  *
  * @return                      0 on success; nonzero on failure.
  */
-static int
-log_read_last_hdr(struct log *log, struct log_entry_hdr *out_hdr)
+int
+log_read_last_hdr_trailer(struct log *log, struct log_entry_hdr *out_hdr,
+                          bool *trailer_exists)
 {
     struct log_read_hdr_arg arg;
     struct log_offset log_offset = {};
@@ -346,12 +370,21 @@ log_read_last_hdr(struct log *log, struct log_entry_hdr 
*out_hdr)
     log_offset.lo_ts = -1;
     log_offset.lo_index = 0;
     log_offset.lo_data_len = 0;
+#if MYNEWT_VAL(LOG_FLAGS_TRAILER_SUPPORT)
+    arg.trailer_exists = false;
+#endif
 
-    log_walk(log, log_read_hdr_walk, &log_offset);
+    log_walk(log, log_read_hdr_trailer_walk, &log_offset);
     if (!arg.read_success) {
         return -1;
     }
 
+#if MYNEWT_VAL(LOG_FLAGS_TRAILER_SUPPORT)
+    if (trailer_exists) {
+        *trailer_exists = arg.trailer_exists;
+    }
+#endif
+
     return 0;
 }
 
@@ -396,8 +429,13 @@ log_register(const char *name, struct log *log, const 
struct log_handler *lh,
      * monotonically increasing.
      */
     if (log->l_log->log_type == LOG_TYPE_STORAGE) {
-        rc = log_read_last_hdr(log, &hdr);
+        memset(&hdr, 0, sizeof(hdr));
+        rc = log_read_last_hdr_trailer(log, &hdr, NULL);
         if (rc == 0) {
+            /* If this is a persisted log, read the index from its most
+             * recent entry. We need to ensure the index of all subsequently
+             * written entries is monotonically increasing.
+             */
             OS_ENTER_CRITICAL(sr);
 #if MYNEWT_VAL(LOG_GLOBAL_IDX)
             if (hdr.ue_index > g_log_info.li_next_index) {
@@ -439,13 +477,82 @@ log_set_append_cb(struct log *log, log_append_cb *cb)
 uint16_t
 log_hdr_len(const struct log_entry_hdr *hdr)
 {
+    uint16_t len;
+
+    len = LOG_BASE_ENTRY_HDR_SIZE;
     if (hdr->ue_flags & LOG_FLAGS_IMG_HASH) {
-        return LOG_BASE_ENTRY_HDR_SIZE + LOG_IMG_HASHLEN;
+        len += LOG_IMG_HASHLEN;
     }
 
-    return LOG_BASE_ENTRY_HDR_SIZE;
+    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;
+}
+
+#if MYNEWT_VAL(LOG_FLAGS_TRAILER_SUPPORT)
+int
+log_trailer_reset_data(struct log *log)
+{
+    if (log->l_th) {
+        if (log->l_th->log_trailer_reset_data) {
+            return log->l_th->log_trailer_reset_data(log);
+        } else {
+            return SYS_ENOTSUP;
+        }
+    }
+    return SYS_ENOTSUP;
+}
+
+uint16_t
+log_trailer_len(struct log *log, const struct log_entry_hdr *hdr)
+{
+    if (log->l_th) {
+        if (log->l_th->log_trailer_len) {
+            return log->l_th->log_trailer_len(log, hdr);
+        } else {
+            return 0;
+        }
+    }
+    return 0;
+}
+
+int
+log_trailer_append(struct log *log, uint8_t *buf, uint16_t *buflen,
+                   void *loc, uint16_t *f_offset)
+{
+    if (log->l_th) {
+        if (log->l_th->log_trailer_append) {
+            return log->l_th->log_trailer_append(log, buf, buflen, loc, 
f_offset);
+        } else {
+            return SYS_ENOTSUP;
+        }
+    }
+    return SYS_ENOTSUP;
+}
+
+int
+log_mbuf_trailer_append(struct log *log, struct os_mbuf *om, void *loc,
+                        uint16_t f_offset)
+{
+    if (log->l_th) {
+        if (log->l_th->log_trailer_mbuf_append) {
+            return log->l_th->log_trailer_mbuf_append(log, om, loc, f_offset);
+        } else {
+            return SYS_ENOTSUP;
+        }
+    }
+    return SYS_ENOTSUP;
+}
+#endif
+
 void
 log_set_rotate_notify_cb(struct log *log, log_notify_rotate_cb *cb)
 {
@@ -571,6 +678,12 @@ log_append_prepare(struct log *log, uint8_t module, 
uint8_t level,
     }
 #endif
 
+#if MYNEWT_VAL(LOG_FLAGS_TRAILER_SUPPORT)
+    if (log->l_th) {
+        ue->ue_flags |= LOG_FLAGS_TRAILER_SUPPORT;
+    }
+#endif
+
 err:
     return (rc);
 }
@@ -671,7 +784,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);
@@ -938,6 +1051,20 @@ err:
     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 +1084,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 +1152,14 @@ log_flush(struct log *log)
 {
     int rc;
 
+#if MYNEWT_VAL(LOG_FLAGS_TRAILER_SUPPORT)
+    /* 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);
+#endif
+
     rc = log->l_log->log_flush(log);
     if (rc != 0) {
         goto err;
diff --git a/sys/log/full/src/log_cbmem.c b/sys/log/full/src/log_cbmem.c
index 02cd3503f..438ebc225 100644
--- a/sys/log/full/src/log_cbmem.c
+++ b/sys/log/full/src/log_cbmem.c
@@ -25,8 +25,19 @@ static int
 log_cbmem_append_body(struct log *log, const struct log_entry_hdr *hdr,
                       const void *body, int body_len)
 {
+    int rc = 0;
     struct cbmem *cbmem;
+#if MYNEWT_VAL(LOG_FLAGS_TRAILER_SUPPORT)
+    uint8_t trailer[LOG_MAX_TRAILER_LEN] = {0};
+    uint16_t trailer_len = 0;
+    struct cbmem_scat_gath *sg = (struct cbmem_scat_gath *)&trailer[0];
+
+    trailer_len = log_trailer_len(log, hdr);
+
+    *sg = (struct cbmem_scat_gath) {
+#else
     struct cbmem_scat_gath sg = {
+#endif
         .entries = (struct cbmem_scat_gath_entry[]) {
             {
                 .flat_buf = hdr,
@@ -40,21 +51,61 @@ log_cbmem_append_body(struct log *log, const struct 
log_entry_hdr *hdr,
                 .flat_buf = body,
                 .flat_len = body_len,
             },
+#if MYNEWT_VAL(LOG_FLAGS_TRAILER_SUPPORT)
+            {
+                .flat_buf = trailer,
+                .flat_len = 0
+            },
+            {
+                .flat_buf = NULL,
+                .flat_len = 0,
+            },
         },
-        .count = 3,
+        .count = 5,
+#else
+            {
+                .flat_buf = NULL,
+                .flat_len = 0,
+            },
+        },
+        .count = 4,
+#endif
     };
 
+#if MYNEWT_VAL(LOG_FLAGS_TRAILER_SUPPORT)
+    if (hdr->ue_flags & LOG_FLAGS_IMG_HASH) {
+        sg->entries[1].flat_len = LOG_IMG_HASHLEN;
+    }
+
+    if (hdr->ue_flags & LOG_FLAGS_TRAILER_SUPPORT) {
+        rc = log_trailer_append(log, trailer, &trailer_len, NULL, NULL);
+        if (rc && rc != SYS_ENOTSUP) {
+            return rc;
+        } else if (!rc) {
+            sg->count += ((trailer_len - sizeof(sg->count)) / 
sizeof(sg->entries[0]));
+            sg->entries[3].flat_len = trailer_len;
+        }
+    }
+
+    cbmem = (struct cbmem *) log->l_arg;
+
+    rc = cbmem_append_scat_gath(cbmem, sg);
+#else
     if (hdr->ue_flags & LOG_FLAGS_IMG_HASH) {
         sg.entries[1].flat_len = LOG_IMG_HASHLEN;
     }
+
     cbmem = (struct cbmem *) log->l_arg;
 
-    return cbmem_append_scat_gath(cbmem, &sg);
+    rc = cbmem_append_scat_gath(cbmem, &sg);
+#endif
+
+    return rc;
 }
 
 static int
 log_cbmem_append(struct log *log, void *buf, int len)
-{   
+{
     uint16_t hdr_len;
 
     hdr_len = log_hdr_len(buf);
@@ -67,6 +118,7 @@ static int
 log_cbmem_append_mbuf_body(struct log *log, const struct log_entry_hdr *hdr,
                            struct os_mbuf *om)
 {
+    int rc = 0;
     struct cbmem *cbmem;
     struct cbmem_scat_gath sg = {
         .entries = (struct cbmem_scat_gath_entry[]) {
@@ -88,9 +140,21 @@ log_cbmem_append_mbuf_body(struct log *log, const struct 
log_entry_hdr *hdr,
     if (hdr->ue_flags & LOG_FLAGS_IMG_HASH) {
         sg.entries[1].flat_len = LOG_IMG_HASHLEN;
     }
+
+#if MYNEWT_VAL(LOG_FLAGS_TRAILER_SUPPORT)
+    if (hdr->ue_flags & LOG_FLAGS_TRAILER_SUPPORT) {
+        rc = log_mbuf_trailer_append(log, om, NULL, 0);
+        if (rc) {
+            return rc;
+        }
+    }
+#endif
+
     cbmem = (struct cbmem *) log->l_arg;
 
-    return cbmem_append_scat_gath(cbmem, &sg);
+    rc = cbmem_append_scat_gath(cbmem, &sg);
+
+    return rc;
 }
 
 static int
@@ -110,25 +174,25 @@ log_cbmem_append_mbuf(struct log *log, struct os_mbuf *om)
      * We do a pull up twice, once so that the base header is
      * contiguous, so that we read the flags correctly, second
      * time is so that we account for the image hash as well.
-     */    
+     */
 
     os_mbuf_pullup(om, LOG_BASE_ENTRY_HDR_SIZE);
-   
-    /* 
+
+    /*
      * We can just pass the om->om_data ptr as the log_entry_hdr
      * because the log_entry_hdr is a packed struct and does not
      * cause any alignment or padding issues
-     */  
+     */
     hdr_len = log_hdr_len((struct log_entry_hdr *)om->om_data);
-    
+
     os_mbuf_pullup(om, hdr_len);
-    
+
     memcpy(&hdr, om->om_data, hdr_len);
 
     os_mbuf_adj(om, hdr_len);
 
     rc = log_cbmem_append_mbuf_body(log, &hdr, om);
-    
+
     os_mbuf_prepend(om, hdr_len);
 
     memcpy(om->om_data, &hdr, hdr_len);
@@ -136,6 +200,16 @@ log_cbmem_append_mbuf(struct log *log, struct os_mbuf *om)
     return rc;
 }
 
+static uint16_t
+log_cbmem_read_entry_len(struct log *log, const void *dptr)
+{
+    struct cbmem_entry_hdr *hdr;
+
+    hdr = (struct cbmem_entry_hdr *) dptr;
+
+    return hdr->ceh_len;
+}
+
 static int
 log_cbmem_read(struct log *log, const void *dptr, void *buf, uint16_t offset,
         uint16_t len)
@@ -264,6 +338,7 @@ log_cbmem_storage_info(struct log *log, struct 
log_storage_info *info)
 const struct log_handler log_cbmem_handler = {
     .log_type = LOG_TYPE_MEMORY,
     .log_read = log_cbmem_read,
+    .log_read_entry_len = log_cbmem_read_entry_len,
     .log_read_mbuf = log_cbmem_read_mbuf,
     .log_append = log_cbmem_append,
     .log_append_body = log_cbmem_append_body,
diff --git a/sys/log/full/src/log_fcb.c b/sys/log/full/src/log_fcb.c
index 48bcfc329..17d4ceffb 100644
--- a/sys/log/full/src/log_fcb.c
+++ b/sys/log/full/src/log_fcb.c
@@ -27,9 +27,6 @@
 #include "fcb/fcb.h"
 #include "log/log.h"
 
-/* Assume the flash alignment requirement is no stricter than 32. */
-#define LOG_FCB_MAX_ALIGN   32
-
 static int log_fcb_rtr_erase(struct log *log);
 
 static int
@@ -324,20 +321,33 @@ err:
     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_write_mbuf(struct fcb_entry *loc, struct os_mbuf *om)
 {
-    uint8_t mod;
+    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_hdr_trailer_bytes(uint16_t align, uint16_t len)
+{
+    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,27 +359,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;
+    uint16_t trailer_len = 0;
+#if MYNEWT_VAL(LOG_FLAGS_TRAILER_SUPPORT)
+    int trailer_alignment = 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;
+    (void)trailer_len;
+
     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 MYNEWT_VAL(LOG_FLAGS_TRAILER_SUPPORT)
+    trailer_len = log_trailer_len(log, hdr);
+#endif
+
+    rc = log_fcb_start_append(log, hdr_len + body_len + trailer_len, &loc);
     if (rc != 0) {
         return rc;
     }
@@ -379,7 +402,7 @@ log_fcb_append_body(struct log *log, const struct 
log_entry_hdr *hdr,
      * 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_trailer_bytes(fcb->f_align, hdr_len);
     if (hdr_alignment > body_len) {
         chunk_sz = hdr_len + body_len;
     } else {
@@ -397,6 +420,7 @@ 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);
 
     rc = fcb_write(fcb, &loc, buf, chunk_sz);
@@ -409,10 +433,52 @@ log_fcb_append_body(struct log *log, const struct 
log_entry_hdr *hdr,
     u8p += hdr_alignment;
     body_len -= hdr_alignment;
 
-    if (body_len > 0) {
-        rc = fcb_write(fcb, &loc, u8p, body_len);
-        if (rc != 0) {
-            return rc;
+#if MYNEWT_VAL(LOG_FLAGS_TRAILER_SUPPORT)
+    if (hdr->ue_flags & LOG_FLAGS_TRAILER_SUPPORT) {
+        /* This writes padding + trailer_alignment */
+
+        /* Calculate trailer alignment */
+        trailer_alignment = log_fcb_hdr_trailer_bytes(fcb->f_align, chunk_sz + 
body_len);
+
+        if (body_len > 0) {
+            padding = trailer_alignment ? fcb->f_align - trailer_alignment : 0;
+            /* Writes body - padding bytes */
+            rc = fcb_write(fcb, &loc, u8p, body_len - padding);
+            if (rc != 0) {
+                return rc;
+            }
+
+            u8p = u8p + body_len - padding;
+            memset(buf, 0, sizeof(buf));
+            memcpy(buf, u8p, padding);
+            offset = padding;
+            offset += trailer_alignment;
+            /* Writes the following:
+             * 
-----------------------------------------------------------------
+             * | body: body_len - padding from end of body | trailer_alignment 
|
+             * 
-----------------------------------------------------------------
+             */
+            rc = fcb_write(fcb, &loc, buf, offset);
+            if (rc != 0) {
+                return rc;
+            }
+
+            /* The first trailer gets appended after the padding + 
trailer_alignment
+             * Trailers start from updated loc.fe_data_off. Hence the offset 
is NULL.
+             */
+            rc = log_trailer_append(log, buf, &trailer_len, &loc, NULL);
+            if (rc && rc != SYS_ENOTSUP) {
+                return rc;
+            }
+        }
+    } else
+#endif
+    {
+        if (body_len > 0) {
+            rc = fcb_write(fcb, &loc, u8p, body_len);
+            if (rc != 0) {
+                return rc;
+            }
         }
     }
 
@@ -435,25 +501,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)
@@ -474,7 +521,11 @@ log_fcb_append_mbuf_body(struct log *log, const struct 
log_entry_hdr *hdr,
         return SYS_ENOTSUP;
     }
 
+#if MYNEWT_VAL(LOG_FLAGS_TRAILER_SUPPORT)
+    len = log_hdr_len(hdr) + os_mbuf_len(om) + log_trailer_len(log, hdr);
+#else
     len = log_hdr_len(hdr) + os_mbuf_len(om);
+#endif
     rc = log_fcb_start_append(log, len, &loc);
     if (rc != 0) {
         return rc;
@@ -496,9 +547,24 @@ 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 MYNEWT_VAL(LOG_FLAGS_TRAILER_SUPPORT)
+    if (hdr->ue_flags & LOG_FLAGS_TRAILER_SUPPORT) {
+        /* The trailer gets appended after the padding + trailer_alignment
+         * Trailers start from updated loc.fe_data_off. Write everything
+         * together
+         */
+        rc = log_mbuf_trailer_append(log, om, &loc, 0);
+        if (rc && rc != SYS_ENOTSUP) {
+            return rc;
+        }
+    } else
+#endif
+    {
+        rc = log_fcb_write_mbuf(&loc, om);
+        if (rc != 0) {
+            return rc;
+        }
     }
 
     rc = fcb_append_finish(fcb, &loc);
@@ -551,6 +617,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)
@@ -862,6 +942,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)
 {
@@ -909,8 +1001,8 @@ log_fcb_copy_entry(struct log *log, struct fcb_entry 
*entry,
                    struct fcb *dst_fcb)
 {
     struct log_entry_hdr ueh;
-    char data[MYNEWT_VAL(LOG_FCB_COPY_MAX_ENTRY_LEN) + LOG_BASE_ENTRY_HDR_SIZE 
+
-              LOG_IMG_HASHLEN];
+    char data[MYNEWT_VAL(LOG_FCB_COPY_MAX_ENTRY_LEN) +
+              LOG_BASE_ENTRY_HDR_SIZE + LOG_IMG_HASHLEN];
     uint16_t hdr_len;
     int dlen;
     int rc;
@@ -924,7 +1016,6 @@ log_fcb_copy_entry(struct log *log, struct fcb_entry 
*entry,
     }
 
     hdr_len = log_hdr_len(&ueh);
-
     dlen = min(entry->fe_data_len, MYNEWT_VAL(LOG_FCB_COPY_MAX_ENTRY_LEN) +
                hdr_len);
 
@@ -1057,23 +1148,25 @@ err:
 }
 
 const struct log_handler log_fcb_handler = {
-    .log_type             = LOG_TYPE_STORAGE,
-    .log_read             = log_fcb_read,
-    .log_read_mbuf        = log_fcb_read_mbuf,
-    .log_append           = log_fcb_append,
-    .log_append_body      = log_fcb_append_body,
-    .log_append_mbuf      = log_fcb_append_mbuf,
+    .log_type = LOG_TYPE_STORAGE,
+    .log_read = log_fcb_read,
+    .log_read_mbuf = log_fcb_read_mbuf,
+    .log_append = log_fcb_append,
+    .log_append_body = log_fcb_append_body,
+    .log_append_mbuf = log_fcb_append_mbuf,
     .log_append_mbuf_body = log_fcb_append_mbuf_body,
-    .log_walk             = log_fcb_walk,
-    .log_walk_sector      = log_fcb_walk_area,
-    .log_flush            = log_fcb_flush,
+    .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,
+    .log_storage_info = log_fcb_storage_info,
 #endif
 #if MYNEWT_VAL(LOG_STORAGE_WATERMARK)
-    .log_set_watermark    = log_fcb_set_watermark,
+    .log_set_watermark = log_fcb_set_watermark,
+    .log_len_in_medium = log_fcb_len_in_medium,
 #endif
-    .log_registered       = log_fcb_registered,
+    .log_registered = log_fcb_registered,
 };
 
 #endif
diff --git a/sys/log/full/src/log_fcb2.c b/sys/log/full/src/log_fcb2.c
index 2bb2e604e..c03b06462 100644
--- a/sys/log/full/src/log_fcb2.c
+++ b/sys/log/full/src/log_fcb2.c
@@ -27,9 +27,6 @@
 #include "log/log.h"
 #include "fcb/fcb2.h"
 
-/* Assume the flash alignment requirement is no stricter than 32. */
-#define LOG_FCB2_MAX_ALIGN   32
-
 static int log_fcb2_rtr_erase(struct log *log);
 
 /**
@@ -206,14 +203,14 @@ err:
  * to satisfy the flash hardware's write alignment restrictions.
  */
 static int
-log_fcb2_hdr_body_bytes(uint8_t align, uint8_t hdr_len)
+log_fcb2_hdr_body_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;
     }
@@ -221,25 +218,52 @@ log_fcb2_hdr_body_bytes(uint8_t align, uint8_t hdr_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;
+}
+
 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 +
-                LOG_FCB2_MAX_ALIGN - 1];
+    uint8_t buf[LOG_FCB_FLAT_BUF_SIZE] = {0};
     struct fcb2_entry loc;
     const uint8_t *u8p;
     int hdr_alignment;
-    int chunk_sz;
+    uint16_t chunk_sz = 0;
     int rc;
     uint16_t hdr_len;
-
     hdr_len = log_hdr_len(hdr);
+#if MYNEWT_VAL(LOG_FLAGS_TRAILER_SUPPORT)
+    uint16_t trailer_len;
+    int trailer_alignment = 0;
+
+    trailer_len = log_trailer_len(log, hdr);
 
+    rc = log_fcb2_start_append(log, hdr_len + body_len + trailer_len, &loc);
+    if (rc != 0) {
+        return rc;
+    }
+#else
     rc = log_fcb2_start_append(log, hdr_len + body_len, &loc);
     if (rc != 0) {
         return rc;
     }
+#endif
 
     /* 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
@@ -275,11 +299,64 @@ log_fcb2_append_body(struct log *log, const struct 
log_entry_hdr *hdr,
 
     u8p += hdr_alignment;
     body_len -= hdr_alignment;
+#if MYNEWT_VAL(LOG_FLAGS_TRAILER_SUPPORT)
+    if (hdr->ue_flags & LOG_FLAGS_TRAILER_SUPPORT) {
+        memset(buf, 0, sizeof(buf));
+        /* Calculate trailer alignment */
+        trailer_alignment = log_fcb2_hdr_body_bytes(loc.fe_range->fsr_align, 
chunk_sz + body_len);
+
+        uint16_t offset = 0;
+        uint16_t padding = 0;
+
+        if (body_len > 0) {
+            padding = trailer_alignment ? loc.fe_range->fsr_align - 
trailer_alignment : 0;
+            rc = fcb2_write(&loc, chunk_sz, u8p, body_len - padding);
+            if (rc != 0) {
+                return rc;
+            }
 
-    if (body_len > 0) {
-        rc = fcb2_write(&loc, chunk_sz, u8p, body_len);
-        if (rc != 0) {
-            return rc;
+            chunk_sz += body_len - padding;
+
+            u8p = u8p + body_len - padding;
+            memcpy(buf, u8p, padding);
+            offset = padding;
+            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;
+            }
+
+            chunk_sz += offset;
+
+            /* The first trailer gets appended after the padding + 
trailer_alignment
+             * Trailers start from updated chunk_sz offset.
+             */
+            rc = log_trailer_append(log, buf, &trailer_len, &loc, &chunk_sz);
+            if (rc && rc != SYS_ENOTSUP) {
+                return rc;
+            }
+        }
+        if (body_len > 0) {
+            rc = fcb2_write(&loc, chunk_sz, u8p, body_len);
+            if (rc != 0) {
+                return rc;
+            }
+            chunk_sz += body_len;
+        }
+    } else
+#endif
+    {
+        if (body_len > 0) {
+            rc = fcb2_write(&loc, chunk_sz, u8p, body_len);
+            if (rc != 0) {
+                return rc;
+            }
+            chunk_sz += body_len;
         }
     }
 
@@ -302,30 +379,12 @@ 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 0;
-}
-
 static int
 log_fcb2_append_mbuf_body(struct log *log, const struct log_entry_hdr *hdr,
                           struct os_mbuf *om)
 {
     struct fcb2_entry loc;
-    int len;
+    int len = 0;
     int rc;
 
 #if 0 /* XXXX */
@@ -339,8 +398,10 @@ log_fcb2_append_mbuf_body(struct log *log, const struct 
log_entry_hdr *hdr,
         return SYS_ENOTSUP;
     }
 #endif
-
-    len = log_hdr_len(hdr) + os_mbuf_len(om);
+#if MYNEWT_VAL(LOG_FLAGS_TRAILER_SUPPORT)
+    len += log_trailer_len(log, hdr);
+#endif
+    len = len + log_hdr_len(hdr) + os_mbuf_len(om);
     rc = log_fcb2_start_append(log, len, &loc);
     if (rc != 0) {
         return rc;
@@ -360,9 +421,24 @@ log_fcb2_append_mbuf_body(struct log *log, const struct 
log_entry_hdr *hdr,
         }
         len += LOG_IMG_HASHLEN;
     }
-    rc = log_fcb2_write_mbuf(&loc, om, len);
-    if (rc != 0) {
-        return rc;
+
+#if MYNEWT_VAL(LOG_FLAGS_TRAILER_SUPPORT)
+    if (hdr->ue_flags & LOG_FLAGS_TRAILER_SUPPORT) {
+        /* The trailer gets appended after the padding + trailer_alignment
+         * Trailers start from updated loc.fe_data_off. Write everything
+         * together
+         */
+        rc = log_mbuf_trailer_append(log, om, &loc, len);
+        if (rc != 0) {
+            return rc;
+        }
+    } else
+#endif
+    {
+        rc = log_fcb2_write_mbuf(&loc, om, len);
+        if (rc != 0) {
+            return rc;
+        }
     }
 
     rc = fcb2_append_finish(&loc);
@@ -373,6 +449,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)
 {
@@ -415,6 +503,20 @@ log_fcb2_append_mbuf(struct log *log, struct os_mbuf *om)
     return rc;
 }
 
+static uint16_t
+log_fcb2_read_entry_len(struct log *log, const void *dptr)
+{
+    struct fcb2_entry *loc;
+
+    loc = (struct fcb2_entry *)dptr;
+
+    if (!log || !dptr) {
+        return 0;
+    }
+
+    return loc->fe_data_len;
+}
+
 static int
 log_fcb2_read(struct log *log, const void *dptr, void *buf, uint16_t off, 
uint16_t len)
 {
@@ -901,6 +1003,8 @@ const struct log_handler log_fcb_handler = {
     .log_append_mbuf_body = log_fcb2_append_mbuf_body,
     .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/syscfg.yml b/sys/log/full/syscfg.yml
index dc228d218..3eeae0871 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_SUPPORT:
+        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
@@ -196,6 +202,10 @@ syscfg.defs:
         restrictions:
             - LOG_FCB_BOOKMARKS
             - LOG_FCB
+    LOG_MAX_TRAILER_LEN:
+        description: >
+            Maximum length of trailer that can be appended to a log entry
+        value: "LF_MAX_ALIGN * 3"
 
 syscfg.vals.CONSOLE_TICKS:
     LOG_CONSOLE_PRETTY_WITH_TIMESTAMP: 0


Reply via email to