img_mgmt: add img_mgmt logging from mynewt-core
diff --git a/cmd/img_mgmt/include/img_mgmt/img_mgmt_impl.h b/cmd/img_mgmt/include/img_mgmt/img_mgmt_impl.h
index ab5a69b..ef249ac 100644
--- a/cmd/img_mgmt/include/img_mgmt/img_mgmt_impl.h
+++ b/cmd/img_mgmt/include/img_mgmt/img_mgmt_impl.h
@@ -163,6 +163,12 @@
 int
 img_mgmt_impl_log_upload_done(int status, const uint8_t *hashp);
 
+int
+img_mgmt_impl_log_pending(int status, const uint8_t *hash);
+
+int
+img_mgmt_impl_log_confirm(int status, const uint8_t *hash);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/cmd/img_mgmt/port/mynewt/pkg.yml b/cmd/img_mgmt/port/mynewt/pkg.yml
index b4c9f2c..abe4c81 100644
--- a/cmd/img_mgmt/port/mynewt/pkg.yml
+++ b/cmd/img_mgmt/port/mynewt/pkg.yml
@@ -26,6 +26,7 @@
 
 pkg.deps:
     - '@apache-mynewt-mcumgr/cmd/img_mgmt'
+    - '@apache-mynewt-core/sys/log/modlog'
 
 pkg.init:
     img_mgmt_module_init: 501
diff --git a/cmd/img_mgmt/port/mynewt/src/mynewt_img_mgmt.c b/cmd/img_mgmt/port/mynewt/src/mynewt_img_mgmt.c
index a66c0e4..6a1208e 100644
--- a/cmd/img_mgmt/port/mynewt/src/mynewt_img_mgmt.c
+++ b/cmd/img_mgmt/port/mynewt/src/mynewt_img_mgmt.c
@@ -540,17 +540,3 @@
     upload_state.sector_id = -1;
     upload_state.sector_end = 0;
 }
-
-int
-img_mgmt_impl_log_upload_start(int status)
-{
-    return 0;
-}
-
-int
-img_mgmt_impl_log_upload_done(int status, const uint8_t *hashp)
-{
-    return 0;
-}
-
-
diff --git a/cmd/img_mgmt/port/mynewt/src/mynewt_img_mgmt_log.c b/cmd/img_mgmt/port/mynewt/src/mynewt_img_mgmt_log.c
new file mode 100644
index 0000000..ad4cfd8
--- /dev/null
+++ b/cmd/img_mgmt/port/mynewt/src/mynewt_img_mgmt_log.c
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "os/mynewt.h"
+#include "modlog/modlog.h"
+#include "cborattr/cborattr.h"
+#include "img_mgmt/img_mgmt.h"
+
+/**
+ * Log event types (all events are CBOR-encoded):
+ *
+ * upstart:
+ *     When: upon receiving an upload request with an offset of 0.
+ *     Structure:
+ *     {
+ *         "ev": "upstart",
+ *         "rc": <mgmt-error-code (int)>
+ *     }
+ *
+ * updone:
+ *     When: upon receiving an upload request containing the final chunk of an
+ *           image OR a failed upload request with a non-zero offset.
+ *     Structure:
+ *     {
+ *         "ev": "updone",
+ *         "rc": <mgmt-error-code (int)>
+ *         "hs": <image-hash (byte-string)> (only present on success)
+ *     }
+ *
+ * pend:
+ *     When: upon receiving a non-permanent `set-pending` request.
+ *     Structure:
+ *     {
+ *         "ev": "pend",
+ *         "rc": <mgmt-error-code (int)>,
+ *         "hs": <image-hash (byte-string)>
+ *     }
+ *
+ * conf:
+ *     When: upon receiving a `confirm` request OR a permanent `set-pending`
+ *           request.
+ *     Structure:
+ *     {
+ *         "ev": "conf",
+ *         "rc": <mgmt-error-code (int)>,
+ *         "hs": <image-hash (byte-string)> (only present for `set-pending`)
+ *     }
+ */
+
+#define IMG_MGMT_LOG_EV_UPSTART   "upstart"
+#define IMG_MGMT_LOG_EV_UPDONE    "updone"
+#define IMG_MGMT_LOG_EV_PEND      "pend"
+#define IMG_MGMT_LOG_EV_CONF      "conf"
+
+static int
+img_mgmt_log_gen(const char *ev, int status, const uint8_t *hash)
+{
+#if MYNEWT_VAL(LOG_VERSION) > 2 && \
+    LOG_MOD_LEVEL_IS_ACTIVE(MYNEWT_VAL(IMG_MGMT_LOG_LVL), LOG_LEVEL_INFO)
+
+    struct os_mbuf *om;
+    int rc;
+
+    const struct cbor_out_attr_t attrs[] = {
+        {
+            .attribute = "ev",
+            .val = {
+                .type = CborAttrTextStringType,
+                .string = ev,
+            },
+        },
+        {
+            .attribute = "rc",
+            .val = {
+                .type = CborAttrIntegerType,
+                .integer = status,
+            },
+        },
+        {
+            .attribute = "hs",
+            .val = {
+                .type = CborAttrByteStringType,
+                .bytestring.data = hash,
+                .bytestring.len = IMG_MGMT_HASH_LEN,
+            },
+            .omit = hash == NULL,    
+        },
+        { 0 }
+    };
+
+    rc = cbor_write_object_msys(attrs, &om);
+    if (rc != 0) {
+        return rc;
+    }
+
+    modlog_append_mbuf(MYNEWT_VAL(IMG_MGMT_LOG_MOD), LOG_LEVEL_INFO,
+                       LOG_ETYPE_CBOR, om);
+#endif
+
+    return 0;
+}
+
+int
+img_mgmt_impl_log_upload_start(int status)
+{
+    return img_mgmt_log_gen(IMG_MGMT_LOG_EV_UPSTART, status, NULL);
+}
+
+int
+img_mgmt_impl_log_upload_done(int status, const uint8_t *hash)
+{
+    return img_mgmt_log_gen(IMG_MGMT_LOG_EV_UPDONE, 0, hash);
+}
+
+int
+img_mgmt_impl_log_pending(int status, const uint8_t *hash)
+{
+    return img_mgmt_log_gen(IMG_MGMT_LOG_EV_PEND, status, hash);
+}
+
+int
+img_mgmt_impl_log_confirm(int status, const uint8_t *hash)
+{
+    return img_mgmt_log_gen(IMG_MGMT_LOG_EV_CONF, status, hash);
+}
diff --git a/cmd/img_mgmt/port/mynewt/syscfg.yml b/cmd/img_mgmt/port/mynewt/syscfg.yml
new file mode 100644
index 0000000..4d09eba
--- /dev/null
+++ b/cmd/img_mgmt/port/mynewt/syscfg.yml
@@ -0,0 +1,30 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#  http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+syscfg.defs:
+    IMG_MGMT_LOG_MOD:
+        description: 'Module ID for the image management structured log.'
+        value: 176
+    IMG_MGMT_LOG_LVL:
+        description: 'Minimum level for the image management structured log.'
+        value: 15  # Log disabled by default.
+
+syscfg.logs:
+    IMG_MGMT_LOG:
+        module: MYNEWT_VAL(IMG_MGMT_LOG_MOD)
+        level: MYNEWT_VAL(IMG_MGMT_LOG_LVL)
diff --git a/cmd/img_mgmt/src/img_mgmt_state.c b/cmd/img_mgmt/src/img_mgmt_state.c
index 16d0a3a..05798a8 100644
--- a/cmd/img_mgmt/src/img_mgmt_state.c
+++ b/cmd/img_mgmt/src/img_mgmt_state.c
@@ -120,7 +120,9 @@
 int
 img_mgmt_state_set_pending(int slot, int permanent)
 {
+    uint8_t hash[IMAGE_HASH_LEN];
     uint8_t state_flags;
+    const uint8_t *hashp;
     int rc;
 
     state_flags = img_mgmt_state_flags(slot);
@@ -129,15 +131,29 @@
      * run if it is a loader in a split image setup.
      */
     if (state_flags & IMG_MGMT_STATE_F_CONFIRMED && slot != 0) {
-        return MGMT_ERR_EBADSTATE;
+        rc = MGMT_ERR_EBADSTATE;
+        goto done;
     }
 
     rc = img_mgmt_impl_write_pending(slot, permanent);
     if (rc != 0) {
-        return MGMT_ERR_EUNKNOWN;
+        rc = MGMT_ERR_EUNKNOWN;
     }
 
-    return 0;
+done:
+    /* Log the image hash if we know it. */
+    rc = img_mgmt_read_info(slot, NULL, hash, NULL);
+    if (rc != 0) {
+        hashp = NULL;
+    } else {
+        hashp = hash;
+    }
+
+    if (permanent) {
+        return img_mgmt_impl_log_confirm(rc, hashp);
+    } else {
+        return img_mgmt_impl_log_pending(rc, hashp);
+    }
 }
 
 /**
@@ -151,15 +167,17 @@
 
     /* Confirm disallowed if a test is pending. */
     if (img_mgmt_state_any_pending()) {
-        return MGMT_ERR_EBADSTATE;
+        rc = MGMT_ERR_EBADSTATE;
+        goto err;
     }
 
     rc = img_mgmt_impl_write_confirmed();
     if (rc != 0) {
-        return MGMT_ERR_EUNKNOWN;
+        rc = MGMT_ERR_EUNKNOWN;
     }
 
-    return 0;
+err:
+    return img_mgmt_impl_log_confirm(rc, NULL);
 }
 
 /**