Merge pull request #27 from vrahane/mynewt_mcumgr

Update mynewt port of mcumgr and various fixes
diff --git a/README-mynewt.md b/README-mynewt.md
index 9e65ea8..30c7b41 100644
--- a/README-mynewt.md
+++ b/README-mynewt.md
@@ -16,8 +16,8 @@
 This is done by adding the necessary dependencies to your app or target.  The following list of dependencies adds support for the SMP transfer encoding, the Bluetooth and shell transports, and all the built-in command handlers:
 
 ```
-    - '@apache-mynewt-core/mgmt/newtmgr/transport/ble'
-    - '@apache-mynewt-core/mgmt/newtmgr/transport/nmgr_shell'
+    - '@apache-mynewt-core/mgmt/smp/transport/ble'
+    - '@apache-mynewt-core/mgmt/smp/transport/smp_shell'
     - '@mynewt-mcumgr/cmd/fs_mgmt'
     - '@mynewt-mcumgr/cmd/img_mgmt'
     - '@mynewt-mcumgr/cmd/os_mgmt'
diff --git a/cborattr/Kconfig b/cborattr/Kconfig
new file mode 100644
index 0000000..ed54c7a
--- /dev/null
+++ b/cborattr/Kconfig
@@ -0,0 +1,22 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE image
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this image
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this image 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.
+
+config CBORATTR_MAX_SIZE
+    int "Maximum chunk size for image uploads"
+    default 512
+    help
+      The maximum size of a CBOR attribute during decoding
diff --git a/cborattr/include/cborattr/cborattr.h b/cborattr/include/cborattr/cborattr.h
index 1cc14b3..30e2612 100644
--- a/cborattr/include/cborattr/cborattr.h
+++ b/cborattr/include/cborattr/cborattr.h
@@ -26,7 +26,11 @@
 #include <ctype.h>
 #include <stdio.h>
 #include <sys/types.h>
-#include "cbor.h"
+#include "tinycbor/cbor.h"
+
+#ifdef MYNEWT
+#include <os/os_mbuf.h>
+#endif
 
 #ifdef __cplusplus
 extern "C" {
@@ -117,6 +121,43 @@
     bool nodefault;
 };
 
+#ifndef __ZEPHYR__
+/** An array value to be encoded as CBOR. */
+struct cbor_out_arr_val_t {
+    struct cbor_out_val_t *elems;
+    size_t len;
+};
+
+/** A single value to be encoded as CBOR. */
+struct cbor_out_val_t {
+    /** The type of data. */
+    CborAttrType type;
+
+    /** The data value. */
+    union {
+        long long int integer;
+        long long unsigned int uinteger;
+        double real;
+        float fval;
+        const char *string;
+        bool boolean;
+        struct {
+            const uint8_t *data;
+            size_t len;
+        } bytestring;
+        struct cbor_out_arr_val_t array;
+        struct cbor_out_attr_t *obj; /* Terminated with a type=0 entry. */
+    };
+};
+
+/** An object key-value pair to be encoded as CBOR. */
+struct cbor_out_attr_t {
+    const char *attribute;      /** The attribute name (key). */
+    struct cbor_out_val_t val;  /** The attribute value. */
+    bool omit;                  /** Attribute ignored if true. */
+};
+#endif
+
 /*
  * Use the following macros to declare template initializers for
  * CborAttrStructObjectType arrays. Writing the equivalents out by hand is
@@ -144,7 +185,33 @@
 
 int cbor_read_flat_attrs(const uint8_t *data, int len,
                          const struct cbor_attr_t *attrs);
+#ifdef MYNEWT
+int cbor_read_mbuf_attrs(struct os_mbuf *m, uint16_t off, uint16_t len,
+                         const struct cbor_attr_t *attrs);
 
+/**
+ * @brief Encodes a CBOR representation of the specified key-value map.
+ *
+ * @param enc                   The CBOR encoder to write to.
+ * @param attrs                 The key-value map to encode.
+ *
+ * @return                      0 on success; SYS_E[...] error on failure.
+ */
+int cbor_write_object(struct CborEncoder *enc,
+                      const struct cbor_out_attr_t *attrs);
+
+/**
+ * @brief Encodes a CBOR representation of the specified key-value map into an
+ * msys mbuf chain.
+ *
+ * @param attrs                 The key-value map to encode.
+ * @param out_om                On success, points to the populate mbuf chain.
+ *
+ * @return                      0 on success; SYS_E[...] error on failure.
+ */
+int cbor_write_object_msys(const struct cbor_out_attr_t *attrs,
+                           struct os_mbuf **out_om);
+#endif
 #ifdef __cplusplus
 }
 #endif
diff --git a/cborattr/pkg.yml b/cborattr/pkg.yml
index 8495f95..67a197f 100644
--- a/cborattr/pkg.yml
+++ b/cborattr/pkg.yml
@@ -24,6 +24,6 @@
 pkg.keywords:
 
 pkg.deps:
-    - "encoding/tinycbor"
+    - "@apache-mynewt-core/encoding/tinycbor"
 
 pkg.cflags.FLOAT_USER: -DFLOAT_SUPPORT
diff --git a/cborattr/src/cborattr.c b/cborattr/src/cborattr.c
index c76ecc8..68c18a8 100644
--- a/cborattr/src/cborattr.c
+++ b/cborattr/src/cborattr.c
@@ -19,10 +19,21 @@
 
 //#include <syscfg/syscfg.h>
 #include "cborattr/cborattr.h"
-#include "cbor.h"
-#include "cbor_buf_reader.h"
+#include "tinycbor/cbor.h"
+#include "tinycbor/cbor_buf_reader.h"
 
-#define CBORATTR_MAX_SIZE 512
+#ifdef MYNEWT
+#include "tinycbor/cbor_mbuf_reader.h"
+#include "tinycbor/cbor_mbuf_writer.h"
+#include "os/os_mbuf.h"
+#define CBORATTR_MAX_SIZE MYNEWT_VAL(CBORATTR_MAX_SIZE)
+#else
+#define CBORATTR_MAX_SIZE CONFIG_CBORATTR_MAX_SIZE
+#endif
+
+
+static int cbor_write_val(struct CborEncoder *enc,
+                          const struct cbor_out_val_t *val);
 
 /* this maps a CborType to a matching CborAtter Type. The mapping is not
  * one-to-one because of signedness of integers
@@ -180,6 +191,7 @@
         }
     }
 
+    
     if (cbor_value_is_map(root_value)) {
         err |= cbor_value_enter_container(root_value, &cur_value);
     } else {
@@ -386,14 +398,18 @@
     CborError err;
 
     cbor_buf_reader_init(&reader, data, len);
+#ifdef __ZEPHYR__
     err = cbor_parser_cust_reader_init(&reader.r, 0, &parser, &value);
+#else
+    err = cbor_parser_init(&reader.r, 0, &parser, &value);
+#endif
     if (err != CborNoError) {
         return -1;
     }
     return cbor_read_object(&value, attrs);
 }
 
-#if 0
+#ifdef MYNEWT
 /*
  * Read in cbor key/values from os_mbuf pointed by m, and fill them
  * into attrs.
@@ -421,4 +437,186 @@
     }
     return cbor_read_object(&value, attrs);
 }
+
+static int
+cbor_write_arr_val(struct CborEncoder *enc,
+                   const struct cbor_out_arr_val_t *arr)
+{
+    struct CborEncoder arr_enc;
+    size_t i;
+    int rc;
+
+    rc = cbor_encoder_create_array(enc, &arr_enc, arr->len);
+    if (rc != 0) {
+        return SYS_ENOMEM;
+    }
+
+    for (i = 0; i < arr->len; i++) {
+        rc = cbor_write_val(&arr_enc, &arr->elems[i]);
+        if (rc != 0) {
+            return SYS_ENOMEM;
+        }
+    }
+
+    rc = cbor_encoder_close_container(enc, &arr_enc);
+    if (rc != 0) {
+        return SYS_ENOMEM;
+    }
+
+    return 0;
+}
+
+static int
+cbor_write_val(struct CborEncoder *enc, const struct cbor_out_val_t *val)
+{
+    int len;
+    int rc;
+
+    switch (val->type) {
+    case CborAttrNullType:
+        rc = cbor_encode_null(enc);
+        break;
+
+    case CborAttrBooleanType:
+        rc = cbor_encode_boolean(enc, val->boolean);
+        break;
+
+    case CborAttrIntegerType:
+        rc = cbor_encode_int(enc, val->integer);
+        break;
+
+    case CborAttrUnsignedIntegerType:
+        rc = cbor_encode_uint(enc, val->uinteger);
+        break;
+
+#if FLOAT_SUPPORT
+    case CborAttrFloatType:
+        rc = cbor_encode_float(enc, val->fval);
+        break;
+
+    case CborAttrDoubleType:
+        rc = cbor_encode_double(enc, val->real);
+        break;
+#endif
+
+    case CborAttrByteStringType:
+        if (val->bytestring.data == NULL &&
+            val->bytestring.len != 0) {
+
+            return SYS_EINVAL;
+        }
+
+        rc = cbor_encode_byte_string(enc, val->bytestring.data,
+                                     val->bytestring.len);
+        break;
+
+    case CborAttrTextStringType:
+        if (val->string == NULL) {
+            len = 0;
+        } else {
+            len = strlen(val->string);
+        }
+        rc = cbor_encode_text_string(enc, val->string, len);
+        break;
+
+    case CborAttrObjectType:
+        rc = cbor_write_object(enc, val->obj);
+        break;
+
+    case CborAttrArrayType:
+        rc = cbor_write_arr_val(enc, &val->array);
+        break;
+
+    default:
+        return SYS_ENOTSUP;
+    }
+
+    if (rc != 0) {
+        return SYS_ENOMEM;
+    }
+
+    return 0;
+}
+
+static int
+cbor_write_attr(struct CborEncoder *enc, const struct cbor_out_attr_t *attr)
+{
+    int len;
+    int rc;
+
+    if (attr->omit) {
+        return 0;
+    }
+
+    if (!attr->attribute) {
+        rc = SYS_EINVAL;
+        return rc;
+    }
+
+    len = strlen(attr->attribute);
+    rc = cbor_encode_text_string(enc, attr->attribute, len);
+    if (rc != 0) {
+        return rc;
+    } 
+
+    rc = cbor_write_val(enc, &attr->val);
+    if (rc != 0) {
+        return rc;
+    } 
+
+    return 0;
+}
+
+int
+cbor_write_object(struct CborEncoder *enc, const struct cbor_out_attr_t *attrs)
+{
+    const struct cbor_out_attr_t *attr;
+    struct CborEncoder map;
+    int rc;
+
+    rc = cbor_encoder_create_map(enc, &map, CborIndefiniteLength);
+    if (rc != 0) {
+        return SYS_ENOMEM;
+    }
+
+    for (attr = attrs; attr->val.type != 0; attr++) {
+        rc = cbor_write_attr(&map, attr);
+        if (rc != 0) {
+            return rc;
+        }
+    }
+
+    rc = cbor_encoder_close_container(enc, &map);
+    if (rc != 0) {
+        return SYS_ENOMEM;
+    }
+
+    return 0;
+}
+
+int
+cbor_write_object_msys(const struct cbor_out_attr_t *attrs,
+                       struct os_mbuf **out_om)
+{
+    struct cbor_mbuf_writer writer;
+    struct CborEncoder encoder;
+    int rc;
+
+    *out_om = os_msys_get_pkthdr(0, 0);
+    if (*out_om == NULL) {
+        return SYS_ENOMEM;
+    }
+
+    cbor_mbuf_writer_init(&writer, *out_om);
+    cbor_encoder_init(&encoder, &writer.enc, 0);
+
+    rc = cbor_write_object(&encoder, attrs);
+    if (rc != 0) {
+        os_mbuf_free_chain(*out_om);
+        *out_om = NULL;
+        return rc;
+    }
+
+    return 0;
+}
 #endif
diff --git a/cborattr/test/pkg.yml b/cborattr/test/pkg.yml
index 071ca5f..eb8d547 100644
--- a/cborattr/test/pkg.yml
+++ b/cborattr/test/pkg.yml
@@ -23,8 +23,10 @@
 pkg.keywords:
 
 pkg.deps:
-    - '@mynewt-mcumgr/ext/tinycbor'
-    - '@mynewt-mcumgr/cborattr'
+    - '@apache-mynewt-core/encoding/tinycbor'
+    - '@apache-mynewt-mcumgr/cborattr'
 
 pkg.deps.SELFTEST:
-    - sys/console/stub
+    - '@apache-mynewt-core/sys/console/stub'
+    - '@apache-mynewt-core/sys/log/full'
+    - '@apache-mynewt-core/test/testutil'
diff --git a/cborattr/test/src/test_cborattr.h b/cborattr/test/src/test_cborattr.h
index 815048f..1a6012b 100644
--- a/cborattr/test/src/test_cborattr.h
+++ b/cborattr/test/src/test_cborattr.h
@@ -35,6 +35,8 @@
  */
 const uint8_t *test_str1(int *len);
 
+void cborattr_test_util_encode(const struct cbor_out_attr_t *attrs,
+                               const uint8_t *expected, int len);
 /*
  * Testcases
  */
diff --git a/cborattr/test/src/test_cborattr_utils.c b/cborattr/test/src/test_cborattr_utils.c
index 0a43766..d520e06 100644
--- a/cborattr/test/src/test_cborattr_utils.c
+++ b/cborattr/test/src/test_cborattr_utils.c
@@ -33,3 +33,18 @@
     *len = sizeof(test_data1);
     return (test_data1);
 }
+
+void
+cborattr_test_util_encode(const struct cbor_out_attr_t *attrs,
+                          const uint8_t *expected, int len)
+{
+    struct os_mbuf *om;
+    int rc;
+
+    rc = cbor_write_object_msys(attrs, &om);
+    TEST_ASSERT_FATAL(rc == 0);
+
+    TEST_ASSERT(os_mbuf_cmpf(om, 0, expected, len) == 0);
+
+    os_mbuf_free_chain(om);
+}
diff --git a/cborattr/test/src/testcases/cborattr_encode_omit.c b/cborattr/test/src/testcases/cborattr_encode_omit.c
new file mode 100644
index 0000000..7d6b91f
--- /dev/null
+++ b/cborattr/test/src/testcases/cborattr_encode_omit.c
@@ -0,0 +1,140 @@
+/*
+ * 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 "test_cborattr.h"
+
+TEST_CASE_SELF(test_cborattr_encode_omit)
+{
+    /* Omit everything except the "str" value. */
+    const struct cbor_out_attr_t attrs[11] = {
+        {
+            .attribute = "null",
+            .val = {
+                .type = CborAttrNullType,
+            },
+            .omit = true,
+        },
+        {
+            .attribute = "bool",
+            .val = {
+                .type = CborAttrBooleanType,
+                .boolean = true,
+            },
+            .omit = true,
+        },
+        {
+            .attribute = "int",
+            .val = {
+                .type = CborAttrIntegerType,
+                .integer = -99,
+            },
+            .omit = true,
+        },
+        {
+            .attribute = "uint",
+            .val = {
+                .type = CborAttrUnsignedIntegerType,
+                .integer = 8442,
+            },
+            .omit = true,
+        },
+        {
+            .attribute = "float",
+            .val = {
+                .type = CborAttrFloatType,
+                .fval = 8.0,
+            },
+            .omit = true,
+        },
+        {
+            .attribute = "double",
+            .val = {
+                .type = CborAttrDoubleType,
+                .real = 16.0,
+            },
+            .omit = true,
+        },
+        {
+            .attribute = "bytes",
+            .val = {
+                .type = CborAttrByteStringType,
+                .bytestring.data = (uint8_t[]) {1, 2, 3},
+                .bytestring.len = 3,
+            },
+            .omit = true,
+        },
+        {
+            .attribute = "str",
+            .val = {
+                .type = CborAttrTextStringType,
+                .string = "mystr",
+            },
+        },
+        {
+            .attribute = "arr",
+            .val = {
+                .type = CborAttrArrayType,
+                .array = {
+                    .elems = (struct cbor_out_val_t[]) {
+                        [0] = {
+                            .type = CborAttrUnsignedIntegerType,
+                            .integer = 4355,
+                        },
+                        [1] = {
+                            .type = CborAttrBooleanType,
+                            .integer = false,
+                        },
+                    },
+                    .len = 2,
+                },
+            },
+            .omit = true,
+        },
+        {
+            .attribute = "obj",
+            .val = {
+                .type = CborAttrObjectType,
+                .obj = (struct cbor_out_attr_t[]) {
+                    {
+                        .attribute = "inner_str",
+                        .val = {
+                            .type = CborAttrTextStringType,
+                            .string = "mystr2",
+                        },
+                    },
+                    {
+                        .attribute = "inner_int",
+                        .val = {
+                            .type = CborAttrIntegerType,
+                            .integer = 123,
+                        },
+                    },
+                    { 0 }
+                },
+            },
+            .omit = true,
+        },
+        { 0 }
+    };
+    const uint8_t exp[] = {
+        0xbf, 0x63, 0x73, 0x74, 0x72, 0x65, 0x6d, 0x79,
+        0x73, 0x74, 0x72, 0xff,
+    };
+
+    cborattr_test_util_encode(attrs, exp, sizeof exp);
+}
diff --git a/cborattr/test/src/testcases/cborattr_encode_simple.c b/cborattr/test/src/testcases/cborattr_encode_simple.c
new file mode 100644
index 0000000..1ddcf3c
--- /dev/null
+++ b/cborattr/test/src/testcases/cborattr_encode_simple.c
@@ -0,0 +1,143 @@
+/*
+ * 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 "test_cborattr.h"
+
+TEST_CASE_SELF(test_cborattr_encode_simple)
+{
+    const struct cbor_out_attr_t attrs[] = {
+        {
+            .attribute = "null",
+            .val = {
+                .type = CborAttrNullType,
+            },
+        },
+        {
+            .attribute = "bool",
+            .val = {
+                .type = CborAttrBooleanType,
+                .boolean = true,
+            },
+        },
+        {
+            .attribute = "int",
+            .val = {
+                .type = CborAttrIntegerType,
+                .integer = -99,
+            },
+        },
+        {
+            .attribute = "uint",
+            .val = {
+                .type = CborAttrUnsignedIntegerType,
+                .integer = 8442,
+            },
+        },
+        {
+            .attribute = "float",
+            .val = {
+                .type = CborAttrFloatType,
+                .fval = 8.0,
+            },
+        },
+        {
+            .attribute = "double",
+            .val = {
+                .type = CborAttrDoubleType,
+                .real = 16.0,
+            },
+        },
+        {
+            .attribute = "bytes",
+            .val = {
+                .type = CborAttrByteStringType,
+                .bytestring.data = (uint8_t[]) {1, 2, 3},
+                .bytestring.len = 3,
+            },
+        },
+        {
+            .attribute = "str",
+            .val = {
+                .type = CborAttrTextStringType,
+                .string = "mystr",
+            },
+        },
+        {
+            .attribute = "arr",
+            .val = {
+                .type = CborAttrArrayType,
+                .array = {
+                    .elems = (struct cbor_out_val_t[]) {
+                        [0] = {
+                            .type = CborAttrUnsignedIntegerType,
+                            .integer = 4355,
+                        },
+                        [1] = {
+                            .type = CborAttrBooleanType,
+                            .integer = false,
+                        },
+                    },
+                    .len = 2,
+                },
+            },
+        },
+        {
+            .attribute = "obj",
+            .val = {
+                .type = CborAttrObjectType,
+                .obj = (struct cbor_out_attr_t[]) {
+                    {
+                        .attribute = "inner_str",
+                        .val = {
+                            .type = CborAttrTextStringType,
+                            .string = "mystr2",
+                        },
+                    },
+                    {
+                        .attribute = "inner_int",
+                        .val = {
+                            .type = CborAttrIntegerType,
+                            .integer = 123,
+                        },
+                    },
+                    { 0 }
+                },
+            },
+        },
+        { 0 }
+    };
+    const uint8_t exp[] = {
+        0xbf, 0x64, 0x6e, 0x75, 0x6c, 0x6c, 0xf6, 0x64,
+        0x62, 0x6f, 0x6f, 0x6c, 0xf5, 0x63, 0x69, 0x6e,
+        0x74, 0x38, 0x62, 0x64, 0x75, 0x69, 0x6e, 0x74,
+        0x19, 0x20, 0xfa, 0x65, 0x66, 0x6c, 0x6f, 0x61,
+        0x74, 0xfa, 0x41, 0x00, 0x00, 0x00, 0x66, 0x64,
+        0x6f, 0x75, 0x62, 0x6c, 0x65, 0xfb, 0x40, 0x30,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x62,
+        0x79, 0x74, 0x65, 0x73, 0x43, 0x01, 0x02, 0x03,
+        0x63, 0x73, 0x74, 0x72, 0x65, 0x6d, 0x79, 0x73,
+        0x74, 0x72, 0x63, 0x61, 0x72, 0x72, 0x82, 0x19,
+        0x11, 0x03, 0xf4, 0x63, 0x6f, 0x62, 0x6a, 0xbf,
+        0x69, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x5f, 0x73,
+        0x74, 0x72, 0x66, 0x6d, 0x79, 0x73, 0x74, 0x72,
+        0x32, 0x69, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x5f,
+        0x69, 0x6e, 0x74, 0x18, 0x7b, 0xff, 0xff,
+    };
+
+    cborattr_test_util_encode(attrs, exp, sizeof exp);
+}
diff --git a/cmd/fs_mgmt/src/fs_mgmt_config.h b/cmd/fs_mgmt/include/fs_mgmt/fs_mgmt_config.h
similarity index 100%
rename from cmd/fs_mgmt/src/fs_mgmt_config.h
rename to cmd/fs_mgmt/include/fs_mgmt/fs_mgmt_config.h
diff --git a/cmd/fs_mgmt/port/mynewt/pkg.yml b/cmd/fs_mgmt/port/mynewt/pkg.yml
new file mode 100644
index 0000000..10e2dbe
--- /dev/null
+++ b/cmd/fs_mgmt/port/mynewt/pkg.yml
@@ -0,0 +1,27 @@
+#
+# 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.
+#
+
+pkg.name: cmd/fs_mgmt/port/mynewt
+pkg.description: 'File system command handlers for mcumgr.'
+pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps:
+    - '@apache-mynewt-mcumgr/cmd/fs'
diff --git a/cmd/fs_mgmt/src/fs_mgmt.c b/cmd/fs_mgmt/src/fs_mgmt.c
index 2d43ac1..0904795 100644
--- a/cmd/fs_mgmt/src/fs_mgmt.c
+++ b/cmd/fs_mgmt/src/fs_mgmt.c
@@ -23,7 +23,7 @@
 #include "mgmt/mgmt.h"
 #include "fs_mgmt/fs_mgmt.h"
 #include "fs_mgmt/fs_mgmt_impl.h"
-#include "fs_mgmt_config.h"
+#include "fs_mgmt/fs_mgmt_config.h"
 
 static mgmt_handler_fn fs_mgmt_file_download;
 static mgmt_handler_fn fs_mgmt_file_upload;
diff --git a/cmd/img_mgmt/include/img_mgmt/img_mgmt.h b/cmd/img_mgmt/include/img_mgmt/img_mgmt.h
index 0f7f2bc..333caca 100644
--- a/cmd/img_mgmt/include/img_mgmt/img_mgmt.h
+++ b/cmd/img_mgmt/include/img_mgmt/img_mgmt.h
@@ -21,12 +21,37 @@
 #define H_IMG_MGMT_
 
 #include <inttypes.h>
+#include "img_mgmt_config.h"
+#include "mgmt/mgmt.h"
+
 struct image_version;
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#define IMG_MGMT_HASH_STR         48
+#define IMG_MGMT_HASH_LEN         32
+#define IMG_MGMT_DATA_SHA_LEN     32 /* SHA256 */
+
+/*
+ * Image state flags
+ */
+#define IMG_MGMT_STATE_F_PENDING    0x01
+#define IMG_MGMT_STATE_F_CONFIRMED  0x02
+#define IMG_MGMT_STATE_F_ACTIVE     0x04
+#define IMG_MGMT_STATE_F_PERMANENT  0x08
+
+#define IMG_MGMT_VER_MAX_STR_LEN    25  /* 255.255.65535.4294967295\0 */
+
+/*
+ * Swap Types for image management state machine
+ */
+#define IMG_MGMT_SWAP_TYPE_NONE     0
+#define IMG_MGMT_SWAP_TYPE_TEST     1
+#define IMG_MGMT_SWAP_TYPE_PERM     2
+#define IMG_MGMT_SWAP_TYPE_REVERT   3
+
 /**
  * Command IDs for image management group.
  */
@@ -44,11 +69,201 @@
 #define IMG_MGMT_ID_UPLOAD_STATUS_ONGOING       1
 #define IMG_MGMT_ID_UPLOAD_STATUS_COMPLETE      2
 
+extern int boot_current_slot;
+extern struct img_mgmt_state g_img_mgmt_state;
+
+/** Represents an individual upload request. */
+struct img_mgmt_upload_req {
+    unsigned long long int off;     /* -1 if unspecified */
+    unsigned long long int size;    /* -1 if unspecified */
+    size_t data_len;
+    size_t data_sha_len;
+    uint8_t img_data[IMG_MGMT_UL_CHUNK_SIZE];
+    uint8_t data_sha[IMG_MGMT_DATA_SHA_LEN];
+    bool upgrade;                   /* Only allow greater version numbers. */
+};
+
+/** Global state for upload in progress. */
+struct img_mgmt_state {
+    /** Flash area being written; -1 if no upload in progress. */
+    int area_id;
+    /** Flash offset of next chunk. */
+    uint32_t off;
+    /** Total size of image data. */
+    uint32_t size;
+    /** Hash of image data; used for resumption of a partial upload. */
+    uint8_t data_sha_len;
+    uint8_t data_sha[IMG_MGMT_DATA_SHA_LEN];
+#if IMG_MGMT_LAZY_ERASE
+    int sector_id;
+    uint32_t sector_end;
+#endif
+};
+
+/** Describes what to do during processing of an upload request. */
+struct img_mgmt_upload_action {
+    /** The total size of the image. */
+    unsigned long long size;
+    /** The number of image bytes to write to flash. */
+    int write_bytes;
+    /** The flash area to write to. */
+    int area_id;
+    /** Whether to process the request; false if offset is wrong. */
+    bool proceed;
+    /** Whether to erase the destination flash area. */
+    bool erase;
+};
+
 /**
  * @brief Registers the image management command handler group.
  */ 
 void img_mgmt_register_group(void);
 
+/**
+ * @brief Read info of an image give the slot number
+ *
+ * @param image_slot     Image slot to read info from
+ * @param image_version  Image version to be filled up
+ * @param hash           Ptr to the read image hash
+ * @param flags          Ptr to flags filled up from the image
+ */
+int img_mgmt_read_info(int image_slot, struct image_version *ver,
+                       uint8_t *hash, uint32_t *flags);
+
+/**
+ * @brief Get the current running image version
+ *
+ * @param image_version Given image version
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int img_mgmt_my_version(struct image_version *ver);
+
+/**
+ * @brief Get image version in string from image_version
+ *
+ * @param image_version Structure filled with image version
+ *                      information
+ * @param dst           Destination string created from the given
+ *                      in image version
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int img_mgmt_ver_str(const struct image_version *ver, char *dst);
+
+/**
+ * @brief Check if the image slot is in use
+ *
+ * @param slot Slot to check if its in use
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int img_mgmt_slot_in_use(int slot);
+
+/**
+ * @brief Collects information about the specified image slot
+ *
+ * @param query_slot Slot to read state flags from
+ *
+ * @return return the state flags
+ */
+uint8_t img_mgmt_state_flags(int query_slot);
+
+/**
+ * @brief Sets the pending flag for the specified image slot.  That is, the system
+ * will swap to the specified image on the next reboot.  If the permanent
+ * argument is specified, the system doesn't require a confirm after the swap
+ * occurs.
+ *
+ * @param slot       Image slot to set pending
+ * @param permanent  If set no confirm is required after image swap
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int img_mgmt_state_set_pending(int slot, int permanent);
+
+/**
+ * Confirms the current image state.  Prevents a fallback from occurring on the
+ * next reboot if the active image is currently being tested.
+ *
+ * @return 0 on success, non -zero on failure
+ */
+int img_mgmt_state_confirm(void);
+
+/** @brief Generic callback function for events */
+typedef void (*img_mgmt_dfu_cb)(void);
+
+/** Callback function pointers */
+typedef struct {
+    img_mgmt_dfu_cb dfu_started_cb;
+    img_mgmt_dfu_cb dfu_stopped_cb;
+    img_mgmt_dfu_cb dfu_pending_cb;
+    img_mgmt_dfu_cb dfu_confirmed_cb;
+} img_mgmt_dfu_callbacks_t;
+
+/** @typedef img_mgmt_upload_fn
+ * @brief Application callback that is executed when an image upload request is
+ * received.
+ *
+ * The callback's return code determines whether the upload request is accepted
+ * or rejected.  If the callback returns 0, processing of the upload request
+ * proceeds.  If the callback returns nonzero, the request is rejected with a
+ * response containing an `rc` value equal to the return code.
+ *
+ * @param offset                The offset specified by the incoming request.
+ * @param size                  The total size of the image being uploaded.
+ * @param arg                   Optional argument specified when the callback
+ *                                  was configured.
+ *
+ * @return                      0 if the upload request should be accepted;
+ *                              nonzero to reject the request with the
+ *                                  specified status.
+ */
+typedef int img_mgmt_upload_fn(uint32_t offset, uint32_t size, void *arg);
+
+/**
+ * @brief Configures a callback that gets called whenever a valid image upload
+ * request is received.
+ *
+ * The callback's return code determines whether the upload request is accepted
+ * or rejected.  If the callback returns 0, processing of the upload request
+ * proceeds.  If the callback returns nonzero, the request is rejected with a
+ * response containing an `rc` value equal to the return code.
+ *
+ * @param cb                    The callback to execute on rx of an upload
+ *                                  request.
+ * @param arg                   Optional argument that gets passed to the
+ *                                  callback.
+ */
+void img_mgmt_set_upload_cb(img_mgmt_upload_fn *cb, void *arg);
+void img_mgmt_register_callbacks(const img_mgmt_dfu_callbacks_t *cb_struct);
+void img_mgmt_dfu_stopped(void);
+void img_mgmt_dfu_started(void);
+void img_mgmt_dfu_pending(void);
+void img_mgmt_dfu_confirmed(void);
+
+#if IMG_MGMT_VERBOSE_ERR
+int img_mgmt_error_rsp(struct mgmt_ctxt *ctxt, int rc, const char *rsn);
+extern const char *img_mgmt_err_str_app_reject;
+extern const char *img_mgmt_err_str_hdr_malformed;
+extern const char *img_mgmt_err_str_magic_mismatch;
+extern const char *img_mgmt_err_str_no_slot;
+extern const char *img_mgmt_err_str_flash_open_failed;
+extern const char *img_mgmt_err_str_flash_erase_failed;
+extern const char *img_mgmt_err_str_flash_write_failed;
+extern const char *img_mgmt_err_str_downgrade;
+#else
+#define img_mgmt_error_rsp(ctxt, rc, rsn)             (rc)
+#define img_mgmt_err_str_app_reject                   NULL
+#define img_mgmt_err_str_hdr_malformed                NULL
+#define img_mgmt_err_str_magic_mismatch               NULL
+#define img_mgmt_err_str_no_slot                      NULL
+#define img_mgmt_err_str_flash_open_failed            NULL
+#define img_mgmt_err_str_flash_erase_failed           NULL
+#define img_mgmt_err_str_flash_write_failed           NULL
+#define img_mgmt_err_str_downgrade                    NULL
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/cmd/img_mgmt/src/img_mgmt_config.h b/cmd/img_mgmt/include/img_mgmt/img_mgmt_config.h
similarity index 82%
rename from cmd/img_mgmt/src/img_mgmt_config.h
rename to cmd/img_mgmt/include/img_mgmt/img_mgmt_config.h
index a520372..66fb218 100644
--- a/cmd/img_mgmt/src/img_mgmt_config.h
+++ b/cmd/img_mgmt/include/img_mgmt/img_mgmt_config.h
@@ -25,10 +25,14 @@
 #include "syscfg/syscfg.h"
 
 #define IMG_MGMT_UL_CHUNK_SIZE  MYNEWT_VAL(IMG_MGMT_UL_CHUNK_SIZE)
+#define IMG_MGMT_VERBOSE_ERR    MYNEWT_VAL(IMG_MGMT_VERBOSE_ERR)
+#define IMG_MGMT_LAZY_ERASE     MYNEWT_VAL(IMG_MGMT_LAZY_ERASE)
 
 #elif defined __ZEPHYR__
 
 #define IMG_MGMT_UL_CHUNK_SIZE  CONFIG_IMG_MGMT_UL_CHUNK_SIZE
+#define IMG_MGMT_VERBOSE_ERR    CONFIG_IMG_MGMT_VERBOSE_ERR
+#define IMG_MGMT_LAZY_ERASE     CONFIG_IMG_MGMT_LAZY_ERASE
 
 #else
 
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 d0898ef..0cb91a9 100644
--- a/cmd/img_mgmt/include/img_mgmt/img_mgmt_impl.h
+++ b/cmd/img_mgmt/include/img_mgmt/img_mgmt_impl.h
@@ -27,6 +27,10 @@
 #ifndef H_IMG_MGMT_IMPL_
 #define H_IMG_MGMT_IMPL_
 
+#include <stdbool.h>
+#include <inttypes.h>
+#include "img_mgmt/img_mgmt.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -100,6 +104,64 @@
  */
 int img_mgmt_impl_swap_type(void);
 
+/**
+ * Collects information about the specified image slot.
+ *
+ * @return                      Flags of the specified image slot
+ */
+uint8_t img_mgmt_state_flags(int query_slot);
+
+/**
+ * Erases image data at given offset
+ *
+ * @param offset                The offset within slot 1 to erase at.
+ * @param num_bytes             The number of bytes to erase.
+ * @return                      0 on success, MGMT_ERR_[...] code on failure.
+ */
+int img_mgmt_impl_erase_image_data(unsigned int off, unsigned int num_bytes);
+
+/**
+ * Erases a flash sector as image upload crosses a sector boundary.
+ * Erasing the entire flash size at one time can take significant time,
+ *   causing a bluetooth disconnect or significant battery sag.
+ * Instead we will erase immediately prior to crossing a sector.
+ * We could check for empty to increase efficiency, but instead we always erase
+ *   for consistency and simplicity.
+ *
+ * @param off      Offset that is about to be written
+ * @param len      Number of bytes to be written
+ *
+ * @return         0 if success 
+ *                 ERROR_CODE if could not erase sector
+ */
+int img_mgmt_impl_erase_if_needed(uint32_t off, uint32_t len);
+
+/**
+ * Verifies an upload request and indicates the actions that should be taken
+ * during processing of the request.  This is a "read only" function in the
+ * sense that it doesn't write anything to flash and doesn't modify any global
+ * variables.
+ *
+ * @param req                   The upload request to inspect.
+ * @param action                On success, gets populated with information
+ *                                  about how to process the request.
+ *
+ * @return                      0 if processing should occur;
+ *                              A MGMT_ERR code if an error response should be
+ *                                  sent instead.
+ */
+int img_mgmt_impl_upload_inspect(const struct img_mgmt_upload_req *req,
+                                 struct img_mgmt_upload_action *action,
+                                 const char **errstr);
+
+int img_mgmt_impl_log_upload_start(int status);
+
+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/pkg.yml b/cmd/img_mgmt/pkg.yml
index fd27c07..82353bd 100644
--- a/cmd/img_mgmt/pkg.yml
+++ b/cmd/img_mgmt/pkg.yml
@@ -24,7 +24,10 @@
 pkg.keywords:
 
 pkg.deps:
+    - '@apache-mynewt-mcumgr/cmd/img_mgmt/port/mynewt'
     - '@apache-mynewt-core/boot/split'
     - '@apache-mynewt-core/encoding/base64'
     - '@apache-mynewt-core/sys/flash_map'
-    - '@mynewt-mcumgr/mgmt'
+    - '@apache-mynewt-mcumgr/mgmt'
+    - '@apache-mynewt-mcumgr/cborattr'
+    - '@apache-mynewt-mcumgr/util'
diff --git a/cmd/img_mgmt/port/mynewt/pkg.yml b/cmd/img_mgmt/port/mynewt/pkg.yml
new file mode 100644
index 0000000..abe4c81
--- /dev/null
+++ b/cmd/img_mgmt/port/mynewt/pkg.yml
@@ -0,0 +1,32 @@
+#
+# 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.
+#
+
+pkg.name: cmd/img_mgmt/port/mynewt
+pkg.description: 'Image management command handlers for
+                  Apache Mynewt for mcumgr.'
+pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+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 c645d1b..20b07e4 100644
--- a/cmd/img_mgmt/port/mynewt/src/mynewt_img_mgmt.c
+++ b/cmd/img_mgmt/port/mynewt/src/mynewt_img_mgmt.c
@@ -21,7 +21,240 @@
 #include "mgmt/mgmt.h"
 #include "img_mgmt/img_mgmt_impl.h"
 #include "img_mgmt/img_mgmt.h"
-#include "img_mgmt_priv.h"
+#include "split/split.h"
+#include "flash_map/flash_map.h"
+#include "sysflash/sysflash.h"
+#include "img_mgmt/image.h"
+
+static struct {
+    int sector_id;
+    uint32_t sector_end;
+} upload_state;
+
+static int
+img_mgmt_find_best_area_id(void)
+{
+    struct image_version ver;
+    int best = -1;
+    int i;
+    int rc;
+
+    for (i = 0; i < 2; i++) {
+        rc = img_mgmt_read_info(i, &ver, NULL, NULL);
+        if (rc < 0) {
+            continue;
+        }
+        if (rc == 0) {
+            /* Image in slot is ok. */
+            if (img_mgmt_slot_in_use(i)) {
+                /* Slot is in use; can't use this. */
+                continue;
+            } else {
+                /*
+                 * Not active slot, but image is ok. Use it if there are
+                 * no better candidates.
+                 */
+                best = i;
+            }
+            continue;
+        }
+        best = i;
+        break;
+    }
+    if (best >= 0) {
+        best = flash_area_id_from_image_slot(best);
+    }
+    return best;
+}
+
+/**
+ * Compares two image version numbers in a semver-compatible way.
+ *
+ * @param a                     The first version to compare.
+ * @param b                     The second version to compare.
+ *
+ * @return                      -1 if a < b
+ * @return                       0 if a = b
+ * @return                       1 if a > b
+ */
+static int
+img_mgmt_vercmp(const struct image_version *a, const struct image_version *b)
+{
+    if (a->iv_major < b->iv_major) {
+        return -1;
+    } else if (a->iv_major > b->iv_major) {
+        return 1;
+    }
+
+    if (a->iv_minor < b->iv_minor) {
+        return -1;
+    } else if (a->iv_minor > b->iv_minor) {
+        return 1;
+    }
+
+    if (a->iv_revision < b->iv_revision) {
+        return -1;
+    } else if (a->iv_revision > b->iv_revision) {
+        return 1;
+    }
+
+    /* Note: For semver compatibility, don't compare the 32-bit build num. */
+
+    return 0;
+}
+
+
+/**
+ * Verifies an upload request and indicates the actions that should be taken
+ * during processing of the request.  This is a "read only" function in the
+ * sense that it doesn't write anything to flash and doesn't modify any global
+ * variables.
+ *
+ * @param req                   The upload request to inspect.
+ * @param action                On success, gets populated with information
+ *                                  about how to process the request.
+ *
+ * @return                      0 if processing should occur;
+ *                              A MGMT_ERR code if an error response should be
+ *                                  sent instead.
+ */
+int
+img_mgmt_impl_upload_inspect(const struct img_mgmt_upload_req *req,
+                             struct img_mgmt_upload_action *action,
+                             const char **errstr)
+{
+    const struct image_header *hdr;
+    const struct flash_area *fa;
+    struct image_version cur_ver;
+    uint8_t rem_bytes;
+    bool empty;
+    int rc;
+
+    memset(action, 0, sizeof *action);
+
+    if (req->off == -1) {
+        /* Request did not include an `off` field. */
+        *errstr = img_mgmt_err_str_hdr_malformed;
+        return MGMT_ERR_EINVAL;
+    }
+
+    if (req->off == 0) {
+        /* First upload chunk. */
+        if (req->data_len < sizeof(struct image_header)) {
+            /*
+             * Image header is the first thing in the image.
+             */
+            *errstr = img_mgmt_err_str_hdr_malformed;
+            return MGMT_ERR_EINVAL;
+        }
+
+        if (req->size == -1) {
+            /* Request did not include a `len` field. */
+            *errstr = img_mgmt_err_str_hdr_malformed;
+            return MGMT_ERR_EINVAL;
+        }
+        action->size = req->size;
+
+        hdr = (struct image_header *)req->img_data;
+        if (hdr->ih_magic != IMAGE_MAGIC) {
+            *errstr = img_mgmt_err_str_magic_mismatch;
+            return MGMT_ERR_EINVAL;
+        }
+
+        if (req->data_sha_len > IMG_MGMT_DATA_SHA_LEN) {
+            return MGMT_ERR_EINVAL;
+        }
+
+        /*
+         * If request includes proper data hash we can check whether there is
+         * upload in progress (interrupted due to e.g. link disconnection) with
+         * the same data hash so we can just resume it by simply including
+         * current upload offset in response.
+         */
+        if ((req->data_sha_len > 0) && (g_img_mgmt_state.area_id != -1)) {
+            if ((g_img_mgmt_state.data_sha_len == req->data_sha_len) &&
+                            !memcmp(g_img_mgmt_state.data_sha, req->data_sha,
+                                                        req->data_sha_len)) {
+                return 0;
+            }
+        }
+
+        action->area_id = img_mgmt_find_best_area_id();
+        if (action->area_id < 0) {
+            /* No slot where to upload! */
+            *errstr = img_mgmt_err_str_no_slot;
+            return MGMT_ERR_ENOMEM;
+        }
+
+        if (req->upgrade) {
+            /* User specified upgrade-only.  Make sure new image version is
+             * greater than that of the currently running image.
+             */
+            rc = img_mgmt_my_version(&cur_ver);
+            if (rc != 0) {
+                return MGMT_ERR_EUNKNOWN;
+            }
+
+            if (img_mgmt_vercmp(&cur_ver, &hdr->ih_ver) >= 0) {
+                *errstr = img_mgmt_err_str_downgrade;
+                return MGMT_ERR_EBADSTATE;
+            }
+        }
+
+#if MYNEWT_VAL(IMG_MGMT_LAZY_ERASE)
+        (void) empty;
+#else
+        rc = flash_area_open(action->area_id, &fa);
+        if (rc) {
+            *errstr = img_mgmt_err_str_flash_open_failed;
+            return MGMT_ERR_EUNKNOWN;
+        }
+
+        rc = flash_area_is_empty(fa, &empty);
+        flash_area_close(fa);
+        if (rc) {
+            return MGMT_ERR_EUNKNOWN;
+        }
+
+        action->erase = !empty;
+#endif
+    } else {
+        /* Continuation of upload. */
+        action->area_id = g_img_mgmt_state.area_id;
+        action->size = g_img_mgmt_state.size;
+
+        if (req->off != g_img_mgmt_state.off) {
+            /*
+             * Invalid offset. Drop the data, and respond with the offset we're
+             * expecting data for.
+             */
+            return 0;
+        }
+    }
+
+    /* Calculate size of flash write. */
+    action->write_bytes = req->data_len;
+    if (req->off + req->data_len < action->size) {
+        /*
+         * Respect flash write alignment if not in the last block
+         */
+        rc = flash_area_open(action->area_id, &fa);
+        if (rc) {
+            *errstr = img_mgmt_err_str_flash_open_failed;
+            return MGMT_ERR_EUNKNOWN;
+        }
+
+        rem_bytes = req->data_len % flash_area_align(fa);
+        flash_area_close(fa);
+
+        if (rem_bytes) {
+            action->write_bytes -= rem_bytes;
+        }
+    }
+
+    action->proceed = true;
+    return 0;
+}
 
 int
 img_mgmt_impl_erase_slot(void)
@@ -58,19 +291,19 @@
     int split_app_active;
     int rc;
 
-    state_flags = imgmgr_state_flags(slot);
+    state_flags = img_mgmt_state_flags(slot);
     split_app_active = split_app_active_get();
 
     /* Unconfirmed slots are always runable.  A confirmed slot can only be
      * run if it is a loader in a split image setup.
      */
-    if (state_flags & IMGMGR_STATE_F_CONFIRMED &&
+    if (state_flags & IMG_MGMT_STATE_F_CONFIRMED &&
         (slot != 0 || !split_app_active)) {
 
         return MGMT_ERR_EBADSTATE;
     }
 
-    rc = imgr_read_info(slot, NULL, NULL, &image_flags);
+    rc = img_mgmt_read_info(slot, NULL, NULL, &image_flags);
     if (rc != 0) {
         return MGMT_ERR_EUNKNOWN;
     }
@@ -112,6 +345,8 @@
 int
 img_mgmt_impl_write_confirmed(void)
 {
+    int rc;
+
     /* Confirm the unified image or loader in slot 0. */
     rc = boot_set_confirmed();
     if (rc != 0) {
@@ -142,7 +377,7 @@
     int area_id;
     int rc;
 
-    area_id = flash_area_id_from_image_slot(image_slot);
+    area_id = flash_area_id_from_image_slot(slot);
     rc = flash_area_open(area_id, &fa);
     if (rc != 0) {
         return MGMT_ERR_EUNKNOWN;
@@ -157,6 +392,54 @@
     return 0;
 }
 
+#if MYNEWT_VAL(IMG_MGMT_LAZY_ERASE)
+int
+img_mgmt_impl_write_image_data(unsigned int offset, const void *data,
+                               unsigned int num_bytes, bool last)
+{
+    const struct flash_area *fa;
+    struct flash_area sector;
+    int rc;
+
+    rc = flash_area_open(FLASH_AREA_IMAGE_1, &fa);
+    if (rc != 0) {
+        return MGMT_ERR_EUNKNOWN;
+    }
+
+    /* Check if there any unerased target sectors, if not clean them. */
+    while ((fa->fa_off + offset + num_bytes) > upload_state.sector_end) {
+        rc = flash_area_getnext_sector(fa->fa_id, &upload_state.sector_id,
+                                       &sector);
+        if (rc) {
+            goto err;
+        }
+        rc = flash_area_erase(&sector, 0, sector.fa_size);
+        if (rc) {
+            goto err;
+        }
+        upload_state.sector_end = sector.fa_off + sector.fa_size;
+    }
+
+    if (last) {
+        upload_state.sector_id = -1;
+        upload_state.sector_end = 0;
+    }
+
+    rc = flash_area_write(fa, offset, data, num_bytes);
+    flash_area_close(fa);
+    if (rc != 0) {
+        return MGMT_ERR_EUNKNOWN;
+    }
+
+    return 0;
+
+err:
+    upload_state.sector_id = -1;
+    upload_state.sector_end = 0;
+    return MGMT_ERR_EUNKNOWN;
+}
+
+#else
 int
 img_mgmt_impl_write_image_data(unsigned int offset, const void *data,
                                unsigned int num_bytes, bool last)
@@ -177,8 +460,60 @@
 
     return 0;
 }
+#endif
 
 int
+img_mgmt_impl_erase_image_data(unsigned int off, unsigned int num_bytes)
+{
+    const struct flash_area *fa;
+    int rc;
+
+    rc = flash_area_open(FLASH_AREA_IMAGE_1, &fa);
+    if (rc != 0) {
+        return MGMT_ERR_EUNKNOWN;
+    }
+
+    rc = flash_area_erase(fa, off, num_bytes);
+    flash_area_close(fa);
+    if (rc != 0) {
+        return MGMT_ERR_EUNKNOWN;
+    }
+
+    return 0;
+}
+
+#if MYNEWT_VAL(IMG_MGMT_LAZY_ERASE)
+int
+img_mgmt_impl_erase_if_needed(uint32_t off, uint32_t len)
+{
+    int rc = 0;
+    struct flash_area sector;
+    const struct flash_area *cfa;
+
+    rc = flash_area_open(FLASH_AREA_IMAGE_1, &cfa);
+    if (rc != 0) {
+        return MGMT_ERR_EUNKNOWN;
+    }
+
+    while ((cfa->fa_off + off + len) > g_img_mgmt_state.sector_end) {
+        rc = flash_area_getnext_sector(cfa->fa_id, &g_img_mgmt_state.sector_id, &sector);
+        if (rc) {
+            goto done;
+        }
+        rc = flash_area_erase(&sector, 0, sector.fa_size);
+        if (rc) {
+            goto done;
+        }
+        g_img_mgmt_state.sector_end = sector.fa_off + sector.fa_size;
+    }
+
+done:
+    flash_area_close(cfa);
+    return rc;
+}
+#endif
+    
+int
 img_mgmt_impl_swap_type(void)
 {
     switch (boot_swap_type()) {
@@ -199,16 +534,12 @@
 void
 img_mgmt_module_init(void)
 {
-    int rc;
-
     /* Ensure this function only gets called by sysinit. */
     SYSINIT_ASSERT_ACTIVE();
 
-    rc = img_mgmt_register_group();
-    SYSINIT_PANIC_ASSERT(rc == 0);
+    img_mgmt_register_group();
 
-#if MYNEWT_VAL(IMGMGR_CLI)
-    rc = imgr_cli_register();
-    SYSINIT_PANIC_ASSERT(rc == 0);
-#endif
+    /* setup for lazy sector by sector erase */
+    upload_state.sector_id = -1;
+    upload_state.sector_end = 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.c b/cmd/img_mgmt/src/img_mgmt.c
index 3c90c3a..edaa1f8 100644
--- a/cmd/img_mgmt/src/img_mgmt.c
+++ b/cmd/img_mgmt/src/img_mgmt.c
@@ -28,12 +28,16 @@
 #include "img_mgmt/img_mgmt.h"
 #include "img_mgmt/img_mgmt_impl.h"
 #include "img_mgmt_priv.h"
-#include "img_mgmt_config.h"
-
-#define IMG_MGMT_DATA_SHA_LEN 32
+#include "img_mgmt/img_mgmt_config.h"
 
 static mgmt_handler_fn img_mgmt_upload;
 static mgmt_handler_fn img_mgmt_erase;
+static img_mgmt_upload_fn *img_mgmt_upload_cb;
+static void *img_mgmt_upload_arg;
+
+const img_mgmt_dfu_callbacks_t *img_mgmt_dfu_callbacks_fn;
+
+struct img_mgmt_state g_img_mgmt_state;
 
 static const struct mgmt_handler img_mgmt_handlers[] = {
     [IMG_MGMT_ID_STATE] = {
@@ -59,20 +63,16 @@
     .mg_group_id = MGMT_GROUP_ID_IMAGE,
 };
 
-static struct {
-    /* Whether an upload is currently in progress. */
-    bool uploading;
-
-    /** Expected offset of next upload request. */
-    size_t off;
-
-    /** Total length of image currently being uploaded. */
-    size_t len;
-
-    /** Hash of image data; used for resume of a partial upload. */
-    uint8_t data_sha_len;
-    uint8_t data_sha[IMG_MGMT_DATA_SHA_LEN];
-} img_mgmt_ctxt;
+#if IMG_MGMT_VERBOSE_ERR
+const char *img_mgmt_err_str_app_reject = "app reject";
+const char *img_mgmt_err_str_hdr_malformed = "header malformed";
+const char *img_mgmt_err_str_magic_mismatch = "magic mismatch";
+const char *img_mgmt_err_str_no_slot = "no slot";
+const char *img_mgmt_err_str_flash_open_failed = "fa open fail";
+const char *img_mgmt_err_str_flash_erase_failed = "fa erase fail";
+const char *img_mgmt_err_str_flash_write_failed = "fa write fail";
+const char *img_mgmt_err_str_downgrade = "downgrade";
+#endif
 
 /**
  * Finds the TLVs in the specified image slot, if any.
@@ -108,6 +108,30 @@
 img_mgmt_read_info(int image_slot, struct image_version *ver, uint8_t *hash,
                    uint32_t *flags)
 {
+
+#if MYNEWT_VAL(IMG_MGMT_DUMMY_HDR)
+    uint8_t dummy_hash[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+                            0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
+ 
+    if (!hash && !ver && !flags) {
+        return 0;
+    }
+
+    if (hash) {
+        memcpy(hash, dummy_hash, IMG_MGMT_HASH_LEN);
+    }
+
+    if (ver) {
+        memset(ver, 0xff, sizeof *ver);
+    }
+
+    if (flags) {
+        *flags = 0;
+    }
+
+    return 0;
+#endif
+
     struct image_header hdr;
     struct image_tlv tlv;
     size_t data_off;
@@ -229,6 +253,21 @@
     return -1;
 }
 
+#if IMG_MGMT_VERBOSE_ERR
+int
+img_mgmt_error_rsp(struct mgmt_ctxt *ctxt, int rc, const char *rsn)
+{
+    /*
+     * This is an error response so returning a different error when failed to
+     * encode other error probably does not make much sense - just ignore errors
+     * here.
+     */
+    cbor_encode_text_stringz(&ctxt->encoder, "rsn");
+    cbor_encode_text_stringz(&ctxt->encoder, rsn);
+    return rc;
+}
+#endif
+
 /**
  * Command handler: image erase
  */
@@ -253,121 +292,62 @@
         return MGMT_ERR_ENOMEM;
     }
 
-    /* reset uploading information on erase */
-    img_mgmt_ctxt.uploading = false;
-
     return 0;
 }
 
-/**
- * Encodes an image upload response.
- */
 static int
-img_mgmt_encode_upload_rsp(struct mgmt_ctxt *ctxt, int status)
+img_mgmt_upload_good_rsp(struct mgmt_ctxt *ctxt)
 {
-    CborError err;
+    CborError err = CborNoError;
 
-    err = 0;
     err |= cbor_encode_text_stringz(&ctxt->encoder, "rc");
-    err |= cbor_encode_int(&ctxt->encoder, status);
+    err |= cbor_encode_int(&ctxt->encoder, MGMT_ERR_EOK);
     err |= cbor_encode_text_stringz(&ctxt->encoder, "off");
-    err |= cbor_encode_int(&ctxt->encoder, img_mgmt_ctxt.off);
+    err |= cbor_encode_int(&ctxt->encoder, g_img_mgmt_state.off);
 
     if (err != 0) {
         return MGMT_ERR_ENOMEM;
     }
-    return 0;
-}
-
-/* check if header for first packet is valid */
-static int
-img_mgmt_check_header(const uint8_t *req_data, size_t len)
-{
-    struct image_header hdr;
-
-    if (len < sizeof(hdr)) {
-        return MGMT_ERR_EINVAL;
-    }
-
-    memcpy(&hdr, req_data, sizeof(hdr));
-    if (hdr.ih_magic != IMAGE_MAGIC) {
-        return MGMT_ERR_EINVAL;
-    }
 
     return 0;
 }
 
 /**
- * Compares two image version numbers in a semver-compatible way.
+ * Logs an upload request if necessary.
  *
- * @param a                     The first version to compare.
- * @param b                     The second version to compare.
+ * @param is_first              Whether the request includes the first chunk of
+ *                                  the image.
+ * @param is_last               Whether the request includes the last chunk of
+ *                                  the image.
+ * @param status                The result of processing the upload request
+ *                                  (MGMT_ERR code).
  *
- * @return                      -1 if a < b
- * @return                       0 if a = b
- * @return                       1 if a > b
+ * @return                      0 on success; nonzero on failure.
  */
 static int
-imgr_vercmp(const struct image_version *a, const struct image_version *b)
+img_mgmt_upload_log(bool is_first, bool is_last, int status)
 {
-    if (a->iv_major < b->iv_major) {
-        return -1;
-    } else if (a->iv_major > b->iv_major) {
-        return 1;
-    }
-
-    if (a->iv_minor < b->iv_minor) {
-        return -1;
-    } else if (a->iv_minor > b->iv_minor) {
-        return 1;
-    }
-
-    if (a->iv_revision < b->iv_revision) {
-        return -1;
-    } else if (a->iv_revision > b->iv_revision) {
-        return 1;
-    }
-
-    /* Note: For semver compativility, don't compare the 32-bit build num. */
-
-    return 0;
-}
-
-/**
- * Processes an upload request specifying an offset of 0 (i.e., the first image
- * chunk).  The caller is responsible for encoding the response.
- */
-static int
-img_mgmt_upload_first_chunk(struct mgmt_ctxt *ctxt, const uint8_t *req_data,
-                            size_t len, const uint8_t *data_sha,
-                            size_t data_sha_len)
-{
+    uint8_t hash[IMAGE_HASH_LEN];
+    const uint8_t *hashp;
     int rc;
 
-    if (img_mgmt_slot_in_use(1)) {
-        /* No free slot. */
-        return MGMT_ERR_ENOMEM;
+    if (is_first) {
+        return img_mgmt_impl_log_upload_start(status);
     }
 
-    rc = img_mgmt_impl_erase_slot();
-    if (rc != 0) {
-        return rc;
+    if (is_last || status != 0) {
+        /* Log the image hash if we know it. */
+        rc = img_mgmt_read_info(1, NULL, hash, NULL);
+        if (rc != 0) {
+            hashp = NULL;
+        } else {
+            hashp = hash;
+        }
+
+        return img_mgmt_impl_log_upload_done(status, hashp);
     }
 
-    img_mgmt_ctxt.uploading = true;
-    img_mgmt_ctxt.off = 0;
-    img_mgmt_ctxt.len = 0;
-
-    /*
-     * We accept SHA trimmed to any length by client since it's up to client
-     * to make sure provided data are good enough to avoid collisions when
-     * resuming upload.
-     */
-    img_mgmt_ctxt.data_sha_len = data_sha_len;
-    memcpy(img_mgmt_ctxt.data_sha, data_sha, data_sha_len);
-    memset(&img_mgmt_ctxt.data_sha[data_sha_len], 0,
-           IMG_MGMT_DATA_SHA_LEN - data_sha_len);
-
+    /* Nothing to log. */
     return 0;
 }
 
@@ -378,157 +358,219 @@
 img_mgmt_upload(struct mgmt_ctxt *ctxt)
 {
     struct mgmt_evt_op_cmd_status_arg cmd_status_arg;
-    uint8_t img_mgmt_data[IMG_MGMT_UL_CHUNK_SIZE];
-    uint8_t data_sha[IMG_MGMT_DATA_SHA_LEN];
-    size_t data_sha_len = 0;
-    struct image_version cur_ver;
-    struct image_header new_hdr;
-    unsigned long long len;
-    unsigned long long off;
-    size_t data_len;
-    size_t new_off;
-    bool upgrade;
-    bool last;
-    int rc;
+    struct img_mgmt_upload_req req = {
+        .off = -1,
+        .size = -1,
+        .data_len = 0,
+        .data_sha_len = 0,
+        .upgrade = false,
+    };
 
-    const struct cbor_attr_t upload_attr[] = {
+    const struct cbor_attr_t off_attr[] = {
         [0] = {
             .attribute = "data",
             .type = CborAttrByteStringType,
-            .addr.bytestring.data = img_mgmt_data,
-            .addr.bytestring.len = &data_len,
-            .len = sizeof(img_mgmt_data)
+            .addr.bytestring.data = req.img_data,
+            .addr.bytestring.len = &req.data_len,
+            .len = sizeof(req.img_data)
         },
         [1] = {
             .attribute = "len",
             .type = CborAttrUnsignedIntegerType,
-            .addr.uinteger = &len,
+            .addr.uinteger = &req.size,
             .nodefault = true
         },
         [2] = {
             .attribute = "off",
             .type = CborAttrUnsignedIntegerType,
-            .addr.uinteger = &off,
+            .addr.uinteger = &req.off,
             .nodefault = true
         },
         [3] = {
             .attribute = "sha",
             .type = CborAttrByteStringType,
-            .addr.bytestring.data = data_sha,
-            .addr.bytestring.len = &data_sha_len,
-            .len = sizeof(data_sha)
+            .addr.bytestring.data = req.data_sha,
+            .addr.bytestring.len = &req.data_sha_len,
+            .len = sizeof(req.data_sha)
         },
         [4] = {
             .attribute = "upgrade",
             .type = CborAttrBooleanType,
-            .addr.boolean = &upgrade,
+            .addr.boolean = &req.upgrade,
             .dflt.boolean = false,
         },
         [5] = { 0 },
     };
+    int rc;
+    const char *errstr = NULL;
+    struct img_mgmt_upload_action action;
+    bool last = false;
 
-    len = ULLONG_MAX;
-    off = ULLONG_MAX;
-    data_len = 0;
-    rc = cbor_read_object(&ctxt->it, upload_attr);
-    if (rc || off == ULLONG_MAX) {
+    rc = cbor_read_object(&ctxt->it, off_attr);
+    if (rc != 0) {
         return MGMT_ERR_EINVAL;
     }
 
-    if (off == 0) {
-        /* Total image length is a required field in the first request. */
-        if (len == ULLONG_MAX) {
-            return MGMT_ERR_EINVAL;
-        }
+    /* Determine what actions to take as a result of this request. */
+    rc = img_mgmt_impl_upload_inspect(&req, &action, &errstr);
+    if (rc != 0) {
+        img_mgmt_dfu_stopped();
+        return rc;
+    }
 
-        rc = img_mgmt_check_header(img_mgmt_data, data_len);
-        if (rc) {
-            return rc;
-        }
+    if (!action.proceed) {
+        /* Request specifies incorrect offset.  Respond with a success code and
+         * the correct offset.
+         */
+        return img_mgmt_upload_good_rsp(ctxt);
+    }
 
-        /* Reject if SHA len is to big */
-        if (data_sha_len > IMG_MGMT_DATA_SHA_LEN) {
-            return MGMT_ERR_EINVAL;
+    /* Request is valid.  Give the application a chance to reject this upload
+     * request.
+     */
+    if (img_mgmt_upload_cb != NULL) {
+        rc = img_mgmt_upload_cb(req.off, action.size, img_mgmt_upload_arg);
+        if (rc != 0) {
+            errstr = img_mgmt_err_str_app_reject;
+            goto end;
         }
+    }
 
+    /* Remember flash area ID and image size for subsequent upload requests. */
+    g_img_mgmt_state.area_id = action.area_id;
+    g_img_mgmt_state.size = action.size;
+
+    if (req.off == 0) {
+        /*
+         * New upload.
+         */
+        g_img_mgmt_state.off = 0;
+
+        img_mgmt_dfu_started();
         cmd_status_arg.status = IMG_MGMT_ID_UPLOAD_STATUS_START;
 
         /*
-         * If request includes proper data hash we can check whether there is
-         * upload in progress (interrupted due to e.g. link disconnection) with
-         * the same data hash so we can just resume it by simply including
-         * current upload offset in response.
+         * We accept SHA trimmed to any length by client since it's up to client
+         * to make sure provided data are good enough to avoid collisions when
+         * resuming upload.
          */
-         if ((data_sha_len > 0) && img_mgmt_ctxt.uploading) {
-            if ((img_mgmt_ctxt.data_sha_len == data_sha_len) &&
-                    !memcmp(img_mgmt_ctxt.data_sha, data_sha, data_sha_len)) {
-                goto done;
-            }
-        }
+        g_img_mgmt_state.data_sha_len = req.data_sha_len;
+        memcpy(g_img_mgmt_state.data_sha, req.data_sha, req.data_sha_len);
+        memset(&g_img_mgmt_state.data_sha[req.data_sha_len], 0,
+               IMG_MGMT_DATA_SHA_LEN - req.data_sha_len);
 
-        if (upgrade) {
-            /* User specified upgrade-only.  Make sure new image version is
-             * greater than that of the currently running image.
-             */
-            rc = img_mgmt_read_info(0, &cur_ver, NULL, NULL);
+#if IMG_MGMT_LAZY_ERASE
+        /* setup for lazy sector by sector erase */
+        g_img_mgmt_state.sector_id = -1;
+        g_img_mgmt_state.sector_end = 0;
+#else
+        /* erase the entire req.size all at once */
+        if (action.erase) {
+            rc = img_mgmt_impl_erase_image_data(0, req.size);
             if (rc != 0) {
-                return MGMT_ERR_EUNKNOWN;
-            }
-
-            memcpy(&new_hdr, img_mgmt_data, sizeof new_hdr);
-
-            if (imgr_vercmp(&cur_ver, &new_hdr.ih_ver) >= 0) {
-                return MGMT_ERR_EBADSTATE;
+                rc = MGMT_ERR_EUNKNOWN;
+                errstr = img_mgmt_err_str_flash_erase_failed;
+                goto end;
             }
         }
+#endif
+    }
 
-        rc = img_mgmt_upload_first_chunk(ctxt, img_mgmt_data, data_len,
-                                         data_sha, data_sha_len);
+    /* Write the image data to flash. */
+    if (req.data_len != 0) {
+#if IMG_MGMT_LAZY_ERASE
+        /* erase as we cross sector boundaries */
+        if (img_mgmt_impl_erase_if_needed(req.off, action.write_bytes) != 0) {
+            rc = MGMT_ERR_EUNKNOWN;
+            errstr = img_mgmt_err_str_flash_erase_failed;
+            goto end;
+        }
+#endif
+        /* If this is the last chunk */
+        if (g_img_mgmt_state.off + req.data_len == g_img_mgmt_state.size) {
+            last = true;
+        }
+
+        rc = img_mgmt_impl_write_image_data(req.off, req.img_data, action.write_bytes, last);
         if (rc != 0) {
-            return rc;
-        }
-        img_mgmt_ctxt.len = len;
-    } else {
-        if (!img_mgmt_ctxt.uploading) {
-            return MGMT_ERR_EINVAL;
-        }
-
-        cmd_status_arg.status = IMG_MGMT_ID_UPLOAD_STATUS_ONGOING;
-
-        if (off != img_mgmt_ctxt.off) {
-            /* Invalid offset.  Drop the data and send the expected offset. */
-            goto done;
+            rc = MGMT_ERR_EUNKNOWN;
+            errstr = img_mgmt_err_str_flash_write_failed;
+            goto end;
+        } else {
+            g_img_mgmt_state.off += action.write_bytes;
+            if (g_img_mgmt_state.off == g_img_mgmt_state.size) {
+                /* Done */
+                img_mgmt_dfu_pending();
+                cmd_status_arg.status = IMG_MGMT_ID_UPLOAD_STATUS_ONGOING;
+                g_img_mgmt_state.area_id = -1;
+            }
         }
     }
 
-    new_off = img_mgmt_ctxt.off + data_len;
-    if (new_off > img_mgmt_ctxt.len) {
-        /* Data exceeds image length. */
-        return MGMT_ERR_EINVAL;
-    }
-    last = new_off == img_mgmt_ctxt.len;
+end:
 
-    if (data_len > 0) {
-        rc = img_mgmt_impl_write_image_data(off, img_mgmt_data, data_len,
-                                            last);
-        if (rc != 0) {
-            return rc;
-        }
-    }
-
-    img_mgmt_ctxt.off = new_off;
-    if (last) {
-        /* Upload complete. */
-        img_mgmt_ctxt.uploading = false;
-
-        cmd_status_arg.status = IMG_MGMT_ID_UPLOAD_STATUS_COMPLETE;
-    }
-
-done:
+    img_mgmt_upload_log(req.off == 0, g_img_mgmt_state.off == g_img_mgmt_state.size, rc);
     mgmt_evt(MGMT_EVT_OP_CMD_STATUS, MGMT_GROUP_ID_IMAGE, IMG_MGMT_ID_UPLOAD,
              &cmd_status_arg);
 
-    return img_mgmt_encode_upload_rsp(ctxt, 0);
+    if (rc != 0) {
+        img_mgmt_dfu_stopped();
+        return img_mgmt_error_rsp(ctxt, rc, errstr);
+    }
+
+    return img_mgmt_upload_good_rsp(ctxt);
+}
+
+void
+img_mgmt_dfu_stopped(void)
+{
+    if (img_mgmt_dfu_callbacks_fn && img_mgmt_dfu_callbacks_fn->dfu_stopped_cb) {
+        img_mgmt_dfu_callbacks_fn->dfu_stopped_cb();
+    }
+}
+
+void
+img_mgmt_dfu_started(void)
+{
+    if (img_mgmt_dfu_callbacks_fn && img_mgmt_dfu_callbacks_fn->dfu_started_cb) {
+        img_mgmt_dfu_callbacks_fn->dfu_started_cb();
+    }
+}
+
+void
+img_mgmt_dfu_pending(void)
+{
+    if (img_mgmt_dfu_callbacks_fn && img_mgmt_dfu_callbacks_fn->dfu_pending_cb) {
+        img_mgmt_dfu_callbacks_fn->dfu_pending_cb();
+    }
+}
+
+void
+img_mgmt_dfu_confirmed(void)
+{
+    if (img_mgmt_dfu_callbacks_fn && img_mgmt_dfu_callbacks_fn->dfu_confirmed_cb) {
+        img_mgmt_dfu_callbacks_fn->dfu_confirmed_cb();
+    }
+}
+
+void
+img_mgmt_set_upload_cb(img_mgmt_upload_fn *cb, void *arg)
+{
+    img_mgmt_upload_cb = cb;
+    img_mgmt_upload_arg = arg;
+}
+
+void
+img_mgmt_register_callbacks(const img_mgmt_dfu_callbacks_t *cb_struct)
+{
+    img_mgmt_dfu_callbacks_fn = cb_struct;
+}
+
+
+int
+img_mgmt_my_version(struct image_version *ver)
+{
+    return img_mgmt_read_info(boot_current_slot, ver, NULL, NULL);
 }
 
 void
diff --git a/cmd/img_mgmt/src/img_mgmt_priv.h b/cmd/img_mgmt/src/img_mgmt_priv.h
index a8a3a28..7e6e784 100644
--- a/cmd/img_mgmt/src/img_mgmt_priv.h
+++ b/cmd/img_mgmt/src/img_mgmt_priv.h
@@ -26,11 +26,6 @@
 extern "C" {
 #endif
 
-#define IMG_MGMT_SWAP_TYPE_NONE     0
-#define IMG_MGMT_SWAP_TYPE_TEST     1
-#define IMG_MGMT_SWAP_TYPE_PERM     2
-#define IMG_MGMT_SWAP_TYPE_REVERT   3
-
 /*
  * Response to list:
  * {
@@ -82,9 +77,6 @@
 int img_mgmt_core_load(struct mgmt_ctxt *);
 int img_mgmt_find_by_hash(uint8_t *find, struct image_version *ver);
 int img_mgmt_find_by_ver(struct image_version *find, uint8_t *hash);
-int img_mgmt_read_info(int image_slot, struct image_version *ver,
-                       uint8_t *hash, uint32_t *flags);
-int img_mgmt_slot_in_use(int slot);
 int img_mgmt_state_read(struct mgmt_ctxt *ctxt);
 int img_mgmt_state_write(struct mgmt_ctxt *njb);
 int img_mgmt_ver_str(const struct image_version *ver, char *dst);
diff --git a/cmd/img_mgmt/src/img_mgmt_state.c b/cmd/img_mgmt/src/img_mgmt_state.c
index 299169b..05798a8 100644
--- a/cmd/img_mgmt/src/img_mgmt_state.c
+++ b/cmd/img_mgmt/src/img_mgmt_state.c
@@ -18,7 +18,7 @@
  */
 
 #include <assert.h>
-#include "cbor.h"
+#include "tinycbor/cbor.h"
 #include "cborattr/cborattr.h"
 #include "mgmt/mgmt.h"
 #include "img_mgmt/img_mgmt.h"
@@ -26,17 +26,10 @@
 #include "img_mgmt_priv.h"
 #include "img_mgmt/img_mgmt_impl.h"
 
-#define IMG_MGMT_STATE_F_PENDING    0x01
-#define IMG_MGMT_STATE_F_CONFIRMED  0x02
-#define IMG_MGMT_STATE_F_ACTIVE     0x04
-#define IMG_MGMT_STATE_F_PERMANENT  0x08
-
-#define IMG_MGMT_VER_MAX_STR_LEN    25  /* 255.255.65535.4294967295\0 */
-
 /**
  * Collects information about the specified image slot.
  */
-static uint8_t
+uint8_t
 img_mgmt_state_flags(int query_slot)
 {
     uint8_t flags;
@@ -127,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);
@@ -136,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);
+    }
 }
 
 /**
@@ -158,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);
 }
 
 /**
diff --git a/cmd/img_mgmt/src/stubs.c b/cmd/img_mgmt/src/stubs.c
deleted file mode 100644
index fa440dc..0000000
--- a/cmd/img_mgmt/src/stubs.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * These stubs get linked in when there is no equivalent OS-specific
- * implementation.
- */
-
-#include "mgmt/mgmt.h"
-#include "img_mgmt/img_mgmt_impl.h"
-
-int __attribute__((weak))
-img_mgmt_impl_erase_slot(void)
-{
-    return MGMT_ERR_ENOTSUP;
-}
-
-int __attribute__((weak))
-img_mgmt_impl_write_pending(int slot, bool permanent)
-{
-    return MGMT_ERR_ENOTSUP;
-}
-
-int __attribute__((weak))
-img_mgmt_impl_write_confirmed(void)
-{
-    return MGMT_ERR_ENOTSUP;
-}
-
-int __attribute__((weak))
-img_mgmt_impl_read(int slot, unsigned int offset, void *dst,
-                   unsigned int num_bytes)
-{
-    return MGMT_ERR_ENOTSUP;
-}
-
-int __attribute__((weak))
-img_mgmt_impl_write_image_data(unsigned int offset, const void *data,
-                               unsigned int num_bytes, bool last)
-{
-    return MGMT_ERR_ENOTSUP;
-}
-
-int __attribute__((weak))
-img_mgmt_impl_swap_type(void)
-{
-    return MGMT_ERR_ENOTSUP;
-}
diff --git a/cmd/img_mgmt/syscfg.yml b/cmd/img_mgmt/syscfg.yml
index 92e11dc..250637c 100644
--- a/cmd/img_mgmt/syscfg.yml
+++ b/cmd/img_mgmt/syscfg.yml
@@ -25,12 +25,31 @@
             command.
         value: 512
 
-    OS_MGMT_TASKSTAT:
+    IMG_MGMT_LAZY_ERASE:
         description: >
-            Enable support for taskstat command.
-        value: 1
+            During a firmware upgrade, erase flash a sector at a time
+            prior to writing to it, rather than all at once at start
+        value: 0
 
-    OS_MGMT_ECHO:
+    IMG_MGMT_VERBOSE_ERR:
         description: >
-            Enable support for echo command.
-        value: 1
+            Enable verbose logging during a firmware upgrade
+        value: 0
+
+    IMG_MGMT_DUMMY_HDR:
+        description: 'Returns dummy image header data for imgr functions,
+                      useful when there are no images present, Eg: unit
+                      tests'
+        value: 0
+
+syscfg.vals.IMGMGR_MAX_CHUNK_SIZE:
+    IMG_MGMT_UL_CHUNK_SIZE: MYNEWT_VAL(IMGMGR_MAX_CHUNK_SIZE)
+
+syscfg.vals.IMGMGR_LAZY_ERASE:
+    IMG_MGMT_LAZY_ERASE: MYNEWT_VAL(IMGMGR_LAZY_ERASE)
+
+syscfg.vals.IMGMGR_VERBOSE_ERR:
+    IMG_MGMT_VERBOSE_ERR: MYNEWT_VAL(IMGMGR_VERBOSE_ERR)
+
+syscfg.vals.IMGMGR_DUMMY_HDR:
+    IMG_MGMT_DUMMY_HDR: MYNEWT_VAL(IMGMGR_DUMMY_HDR)
diff --git a/cmd/log_mgmt/Kconfig b/cmd/log_mgmt/Kconfig
new file mode 100644
index 0000000..14c5614
--- /dev/null
+++ b/cmd/log_mgmt/Kconfig
@@ -0,0 +1,52 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE log
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this log
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this log 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.
+
+menuconfig MCUMGR_CMD_LOG_MGMT
+    bool "Enable mcumgr handlers for log management"
+    help
+      Enables mcumgr handlers for log management
+
+if MCUMGR_CMD_LOG_MGMT
+config LOG_MGMT_MAX_RSP_LEN
+    int "Maximum MCUmgr response len for log downloads"
+    default 512
+    help
+      Limits the maximum response len for log downloads, in bytes.
+
+config LOG_MGMT_NAME_LEN
+    int "Maximum log name length"
+    default 64
+    help
+      Limits the maximum length of log names, in bytes.  If a log's name length
+      exceeds this number, it gets truncated in management responses. A buffer
+      of this size gets allocated on the stack during handling of all log
+      management commands.
+
+config LOG_MGMT_CHUNK_LEN
+    int "Maximum log chunk length"
+    default 128
+    help
+      Limits the maximum length of log entry bodies chunks, so, every log entry gets
+      read in chunks upto a point where the entire entry is read. Also, a buffer gets
+      allocated on the stack with this size.
+
+config LOG_READ_WATERMARK_UPDATE
+    bool "Enable reading of log watermark update"
+    help
+      Enables reading of log watermark update 
+
+endif
diff --git a/cmd/log_mgmt/include/log_mgmt/log_mgmt.h b/cmd/log_mgmt/include/log_mgmt/log_mgmt.h
index 01df2e5..0229e20 100644
--- a/cmd/log_mgmt/include/log_mgmt/log_mgmt.h
+++ b/cmd/log_mgmt/include/log_mgmt/log_mgmt.h
@@ -43,6 +43,15 @@
 /** @brief Log entries are persisted across reboots. */
 #define LOG_MGMT_TYPE_STORAGE    2
 
+/* @brief Flags used to indicate type of data in reserved payload. */
+#define LOG_MGMT_FLAGS_IMG_HASH  (1 << 0)
+
+/* @brief Log entry types. */
+#define LOG_MGMT_ETYPE_STRING         0
+#define LOG_MGMT_ETYPE_CBOR           1
+#define LOG_MGMT_ETYPE_BINARY         2
+
+
 /** @brief Generic descriptor for an OS-specific log. */
 struct log_mgmt_log {
     const char *name;
@@ -57,6 +66,12 @@
     size_t len;
     uint8_t module;
     uint8_t level;
+    uint8_t type:4;
+    uint8_t flags:4;
+    const uint8_t *imghash;
+    size_t offset;
+    size_t chunklen;
+    void *ctxt;
 };
 
 /** @brief Indicates which log entries to operate on. */
diff --git a/cmd/log_mgmt/src/log_mgmt_config.h b/cmd/log_mgmt/include/log_mgmt/log_mgmt_config.h
similarity index 74%
rename from cmd/log_mgmt/src/log_mgmt_config.h
rename to cmd/log_mgmt/include/log_mgmt/log_mgmt_config.h
index 572fb00..844d92f 100644
--- a/cmd/log_mgmt/src/log_mgmt_config.h
+++ b/cmd/log_mgmt/include/log_mgmt/log_mgmt_config.h
@@ -24,15 +24,18 @@
 
 #include "syscfg/syscfg.h"
 
-#define LOG_MGMT_CHUNK_SIZE MYNEWT_VAL(LOG_MGMT_CHUNK_SIZE)
+#define LOG_MGMT_CHUNK_LEN MYNEWT_VAL(LOG_MGMT_CHUNK_LEN)
 #define LOG_MGMT_NAME_LEN   MYNEWT_VAL(LOG_MGMT_NAME_LEN)
-#define LOG_MGMT_BODY_LEN   MYNEWT_VAL(LOG_MGMT_BODY_LEN)
+#define LOG_MGMT_MAX_RSP_LEN   MYNEWT_VAL(LOG_MGMT_MAX_RSP_LEN)
+#define LOG_MGMT_WATERMARK_UPDATE MYNEWT_VAL(LOG_READ_WATERMARK_UPDATE)
+#define LOG_MGMT_IMG_HASHLEN 4
 
 #elif defined __ZEPHYR__
 
-#define LOG_MGMT_CHUNK_SIZE CONFIG_LOG_MGMT_CHUNK_SIZE
+#define LOG_MGMT_CHUNK_LEN CONFIG_LOG_MGMT_CHUNK_LEN
 #define LOG_MGMT_NAME_LEN   CONFIG_LOG_MGMT_NAME_LEN
-#define LOG_MGMT_BODY_LEN   CONFIG_LOG_MGMT_BODY_LEN
+#define LOG_MGMT_MAX_RSP_LEN   CONFIG_LOG_MGMT_MAX_RSP_LEN
+#define LOG_MGMT_WATERMARK_UPDATE CONFIG_LOG_READ_WATERMARK_UPDATE
 
 #else
 
diff --git a/cmd/log_mgmt/include/log_mgmt/log_mgmt_impl.h b/cmd/log_mgmt/include/log_mgmt/log_mgmt_impl.h
index b3f6b12..0a62652 100644
--- a/cmd/log_mgmt/include/log_mgmt/log_mgmt_impl.h
+++ b/cmd/log_mgmt/include/log_mgmt/log_mgmt_impl.h
@@ -35,7 +35,7 @@
 struct log_mgmt_entry;
 struct log_mgmt_log;
 
-typedef int log_mgmt_foreach_entry_fn(const struct log_mgmt_entry *entry,
+typedef int log_mgmt_foreach_entry_fn(struct log_mgmt_entry *entry,
                                       void *arg);
 
 /**
@@ -113,6 +113,17 @@
  */
 int log_mgmt_impl_clear(const char *log_name);
 
+/**
+ * @brief set watermark for specified log index
+ *
+ * @param log                   Log pointer
+ * @param index                 Log ndex
+ *
+ * @return                      0 on success, non-zero on failure
+ */
+int
+log_mgmt_impl_set_watermark(struct log_mgmt_log *log, int index);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/cmd/log_mgmt/pkg.yml b/cmd/log_mgmt/pkg.yml
new file mode 100644
index 0000000..2c6f470
--- /dev/null
+++ b/cmd/log_mgmt/pkg.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.
+#
+
+pkg.name: cmd/log_mgmt
+pkg.description: 'OS management command handlers for mcumgr.'
+pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps:
+    - '@apache-mynewt-core/kernel/os'
+    - '@apache-mynewt-core/sys/log/full'
+    - '@apache-mynewt-mcumgr/cmd/log_mgmt/port/mynewt'
+    - '@apache-mynewt-mcumgr/mgmt'
diff --git a/cmd/log_mgmt/port/mynewt/pkg.yml b/cmd/log_mgmt/port/mynewt/pkg.yml
new file mode 100644
index 0000000..6996e7d
--- /dev/null
+++ b/cmd/log_mgmt/port/mynewt/pkg.yml
@@ -0,0 +1,31 @@
+#
+# 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.
+#
+
+pkg.name: cmd/log_mgmt/port/mynewt
+pkg.description: 'Log management command handlers for mcumgr.'
+pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps:
+    - '@apache-mynewt-mcumgr/cmd/log_mgmt'
+    - '@apache-mynewt-mcumgr/mgmt'
+
+pkg.init:
+    log_mgmt_module_init: 501
diff --git a/cmd/log_mgmt/port/mynewt/src/mynewt_log_mgmt.c b/cmd/log_mgmt/port/mynewt/src/mynewt_log_mgmt.c
index f81e591..da68acb 100644
--- a/cmd/log_mgmt/port/mynewt/src/mynewt_log_mgmt.c
+++ b/cmd/log_mgmt/port/mynewt/src/mynewt_log_mgmt.c
@@ -21,11 +21,11 @@
 #include "mgmt/mgmt.h"
 #include "log_mgmt/log_mgmt.h"
 #include "log_mgmt/log_mgmt_impl.h"
-#include "../../../src/log_mgmt_config.h"
+#include "log_mgmt/log_mgmt_config.h"
 
 struct mynewt_log_mgmt_walk_arg {
     log_mgmt_foreach_entry_fn *cb;
-    uint8_t body[LOG_MGMT_BODY_LEN];
+    uint8_t chunk[LOG_MGMT_CHUNK_LEN];
     void *arg;
 };
 
@@ -48,6 +48,27 @@
 }
 
 int
+log_mgmt_impl_set_watermark(struct log_mgmt_log *log, int index)
+{
+#if MYNEWT_VAL(LOG_STORAGE_WATERMARK)
+    struct log *tmplog;
+    int i;
+
+    tmplog = NULL;
+    for (i = 0; i <= index; i++) {
+        tmplog = log_list_get_next(tmplog);
+        if (tmplog == NULL) {
+            return MGMT_ERR_ENOENT;
+        }
+    }
+
+    return log_set_watermark(tmplog, index);
+#else
+    return MGMT_ERR_ENOTSUP;
+#endif
+}
+
+int
 log_mgmt_impl_get_log(int idx, struct log_mgmt_log *out_log)
 {
     struct log *log;
@@ -62,7 +83,7 @@
     }
 
     out_log->name = log->l_name;
-    out_log->type = log->l_handler->type;
+    out_log->type = log->l_log->log_type;
     return 0;
 }
 
@@ -103,21 +124,18 @@
 
 static int
 mynewt_log_mgmt_walk_cb(struct log *log, struct log_offset *log_offset,
-                        const void *desciptor, uint16_t len)
+                        const struct log_entry_hdr *leh,
+                        const void *dptr, uint16_t len)
 {
     struct mynewt_log_mgmt_walk_arg *mynewt_log_mgmt_walk_arg;
     struct log_mgmt_entry entry;
-    struct log_entry_hdr ueh;
     int read_len;
+    int offset;
     int rc;
 
+    rc = 0;
     mynewt_log_mgmt_walk_arg = log_offset->lo_arg;
 
-    rc = log_read(log, desciptor, &ueh, 0, sizeof ueh);
-    if (rc != sizeof ueh) {
-        return MGMT_ERR_EUNKNOWN;
-    }
-
     /* If specified timestamp is nonzero, it is the primary criterion, and the
      * specified index is the secondary criterion.  If specified timetsamp is
      * zero, specified index is the only criterion.
@@ -127,32 +145,54 @@
      * Else: encode entries whose timestamp >= specified timestamp and whose
      *      index >= specified index
      */
-
     if (log_offset->lo_ts == 0) {
-        if (log_offset->lo_index > ueh.ue_index) {
+        if (log_offset->lo_index > leh->ue_index) {
             return 0;
         }
-    } else if (ueh.ue_ts < log_offset->lo_ts   ||
-               (ueh.ue_ts == log_offset->lo_ts &&
-                ueh.ue_index < log_offset->lo_index)) {
+    } else if (leh->ue_ts < log_offset->lo_ts   ||
+               (leh->ue_ts == log_offset->lo_ts &&
+                leh->ue_index < log_offset->lo_index)) {
         return 0;
     }
 
-    read_len = min(len - sizeof ueh, LOG_MGMT_BODY_LEN - sizeof ueh);
-    rc = log_read(log, desciptor, mynewt_log_mgmt_walk_arg->body, sizeof ueh,
-                  read_len);
-    if (rc < 0) {
-        return MGMT_ERR_EUNKNOWN;
+    entry.ts = leh->ue_ts;
+    entry.index = leh->ue_index;
+    entry.module = leh->ue_module;
+    entry.level = leh->ue_level;
+
+#if MYNEWT_VAL(LOG_VERSION) < 3
+    entry.type = LOG_ETYPE_STRING;
+    entry.flags = 0;
+#else
+    entry.type = leh->ue_etype;
+    entry.flags = leh->ue_flags;
+    entry.imghash = (leh->ue_flags & LOG_FLAGS_IMG_HASH) ?
+        leh->ue_imghash : NULL;
+#endif
+    entry.len = len;
+    entry.data = mynewt_log_mgmt_walk_arg->chunk;
+
+    for (offset = 0; offset < len; offset += LOG_MGMT_CHUNK_LEN) {
+        if (len - offset < LOG_MGMT_CHUNK_LEN) {
+            read_len = len - offset;
+        } else {
+            read_len = LOG_MGMT_CHUNK_LEN;
+        }
+        entry.offset = offset;
+        entry.chunklen = read_len;
+
+        rc = log_read_body(log, dptr, mynewt_log_mgmt_walk_arg->chunk, offset,
+                           read_len);
+        if (rc < 0) {
+            return MGMT_ERR_EUNKNOWN;
+        }
+        rc = mynewt_log_mgmt_walk_arg->cb(&entry, mynewt_log_mgmt_walk_arg->arg);
+        if (rc) {
+            break;
+        }
     }
 
-    entry.ts = ueh.ue_ts;
-    entry.index = ueh.ue_index;
-    entry.module = ueh.ue_module;
-    entry.level = ueh.ue_level;
-    entry.len = rc;
-    entry.data = mynewt_log_mgmt_walk_arg->body;
-
-    return mynewt_log_mgmt_walk_arg->cb(&entry, mynewt_log_mgmt_walk_arg->arg);
+    return rc;
 }
 
 int
@@ -180,7 +220,7 @@
         offset.lo_index = filter->min_index;
         offset.lo_data_len = 0;
 
-        return log_walk(log, mynewt_log_mgmt_walk_cb, &offset);
+        return log_walk_body(log, mynewt_log_mgmt_walk_cb, &offset);
     }
 
     return MGMT_ERR_ENOENT;
@@ -204,3 +244,12 @@
 
     return 0;
 }
+
+void
+log_mgmt_module_init(void)
+{
+    /* Ensure this function only gets called by sysinit. */
+    SYSINIT_ASSERT_ACTIVE();
+
+    log_mgmt_register_group();
+}
diff --git a/cmd/log_mgmt/port/mynewt/syscfg.yml b/cmd/log_mgmt/port/mynewt/syscfg.yml
new file mode 100644
index 0000000..7ab39d9
--- /dev/null
+++ b/cmd/log_mgmt/port/mynewt/syscfg.yml
@@ -0,0 +1,42 @@
+# 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:
+    LOG_MGMT_CHUNK_LEN:
+        description: >
+            Limits the maximum length of log entry bodies chunks, so, every log entry gets
+            read in chunks upto a point where the entire entry is read. Also, a buffer gets
+            allocated on the stack with this size.
+        value: 128
+
+    LOG_MGMT_MAX_RSP_LEN:
+        description: >
+            Limits the maximum chunk len for log downloads, in bytes.
+        value: 512
+
+    LOG_MGMT_NAME_LEN:
+        description: >
+            Limits the maximum length of log names, in bytes. If a log's name length
+            exceeds this number, it gets truncated in management responses. A buffer
+            of this size gets allocated on the stack during handling of all log
+            management commands.
+        value: 64
+
+# For backwards compatibility with log nmgr
+syscfg.vals.LOG_NMGR_MAX_RSP_LEN:
+    LOG_MGMT_MAX_RSP_SIZE: MYNEWT_VAL(LOG_NMGR_MAX_RSP_LEN)
diff --git a/cmd/log_mgmt/port/zephyr/src/zephyr_log_mgmt.c b/cmd/log_mgmt/port/zephyr/src/zephyr_log_mgmt.c
index 94e49db..8ddc012 100644
--- a/cmd/log_mgmt/port/zephyr/src/zephyr_log_mgmt.c
+++ b/cmd/log_mgmt/port/zephyr/src/zephyr_log_mgmt.c
@@ -22,7 +22,7 @@
 #include <mgmt/mgmt.h>
 #include <log_mgmt/log_mgmt.h>
 #include <log_mgmt/log_mgmt_impl.h>
-#include "../../../src/log_mgmt_config.h"
+#include "log_mgmt/log_mgmt_config.h"
 
 struct zephyr_log_mgmt_walk_arg {
     log_mgmt_foreach_entry_fn *cb;
diff --git a/cmd/log_mgmt/src/log_mgmt.c b/cmd/log_mgmt/src/log_mgmt.c
index a3c0cac..4d3f88f 100644
--- a/cmd/log_mgmt/src/log_mgmt.c
+++ b/cmd/log_mgmt/src/log_mgmt.c
@@ -22,18 +22,33 @@
 
 #include "mgmt/mgmt.h"
 #include "cborattr/cborattr.h"
-#include "cbor_cnt_writer.h"
+#include "tinycbor/cbor_cnt_writer.h"
 #include "log_mgmt/log_mgmt.h"
 #include "log_mgmt/log_mgmt_impl.h"
-#include "log_mgmt_config.h"
+#include "log_mgmt/log_mgmt_config.h"
+#include "log/log.h"
 
+/* Log mgmt encoder context used for multiple calls of the
+ * entry encode function since the function gets called twice,
+ * once for counter encoder and the second time for the actual
+ * encoding
+ */
+struct log_mgmt_enc_ctxt
+{
+    CborEncoder mapenc;
+    CborEncoder msgenc;
+};
+    
 /** Context used during walks. */
 struct log_walk_ctxt {
     /* The number of bytes encoded to the response so far. */
     size_t rsp_len;
-
     /* The encoder to use to write the current log entry. */
     struct CborEncoder *enc;
+    /* Counter per encoder to understand if we are encoding the first chunk */
+    uint32_t counter;
+    /* Log management encode context containing map and msg encoder */
+    struct log_mgmt_enc_ctxt lmec;
 };
 
 static mgmt_handler_fn log_mgmt_show;
@@ -58,71 +73,181 @@
     .mg_handlers_count = LOG_MGMT_HANDLER_CNT,
     .mg_group_id = MGMT_GROUP_ID_LOG,
 };
-
+    
 static int
 log_mgmt_encode_entry(CborEncoder *enc, const struct log_mgmt_entry *entry,
-                      size_t *out_len)
+                      size_t *out_len, struct log_mgmt_enc_ctxt *lmec)
 {
-    CborEncoder entry_enc;
-    CborError err;
+    CborError err = CborNoError;
+    uint16_t chunklen;
+    uint16_t len;
+    int off;
+    uint16_t bytes_encoded;
 
-    err = 0;
-    err |= cbor_encoder_create_map(enc, &entry_enc, 5);
-    err |= cbor_encode_text_stringz(&entry_enc, "msg");
-    err |= cbor_encode_byte_string(&entry_enc, entry->data, entry->len);
-    err |= cbor_encode_text_stringz(&entry_enc, "ts");
-    err |= cbor_encode_int(&entry_enc, entry->ts);
-    err |= cbor_encode_text_stringz(&entry_enc, "level");
-    err |= cbor_encode_uint(&entry_enc, entry->level);
-    err |= cbor_encode_text_stringz(&entry_enc, "index");
-    err |= cbor_encode_uint(&entry_enc, entry->index);
-    err |= cbor_encode_text_stringz(&entry_enc, "module");
-    err |= cbor_encode_uint(&entry_enc, entry->module);
-    err |= cbor_encoder_close_container(enc, &entry_enc);
+    len = cbor_encode_bytes_written(enc);
 
-    if (err != 0) {
-        return MGMT_ERR_ENOMEM;
-    }
+    bytes_encoded = 0;
+    /* If offset is 0, we encode the keys for maps and other fields which are
+     * necessary per entry since only the keys need to be encoded only in the
+     * for the first offset
+     */
+    if (entry->offset == 0) {
+        err |= cbor_encoder_create_map(enc, &lmec->mapenc, CborIndefiniteLength);
+    
+#if MYNEWT_VAL(LOG_VERSION) > 2
+        switch (entry->type) {
+        case LOG_MGMT_ETYPE_CBOR:
+            err |= cbor_encode_text_stringz(&lmec->mapenc, "type");
+            err |= cbor_encode_text_stringz(&lmec->mapenc, "cbor");
+            break;
+        case LOG_MGMT_ETYPE_BINARY:
+            err |= cbor_encode_text_stringz(&lmec->mapenc, "type");
+            err |= cbor_encode_text_stringz(&lmec->mapenc, "bin");
+            break;
+        case LOG_MGMT_ETYPE_STRING:
+            err |= cbor_encode_text_stringz(&lmec->mapenc, "type");
+            err |= cbor_encode_text_stringz(&lmec->mapenc, "str");
+            break;
+        default:
+            return MGMT_ERR_ECORRUPT;
+        }
+#endif
+        err |= cbor_encode_text_stringz(&lmec->mapenc, "ts");
+        err |= cbor_encode_int(&lmec->mapenc, entry->ts);
+        err |= cbor_encode_text_stringz(&lmec->mapenc, "level");
+        err |= cbor_encode_uint(&lmec->mapenc, entry->level);
+        err |= cbor_encode_text_stringz(&lmec->mapenc, "index");
+        err |= cbor_encode_uint(&lmec->mapenc, entry->index);
+        err |= cbor_encode_text_stringz(&lmec->mapenc, "module");
+        err |= cbor_encode_uint(&lmec->mapenc, entry->module);
+        if (entry->flags & LOG_MGMT_FLAGS_IMG_HASH) {
+            err |= cbor_encode_text_stringz(&lmec->mapenc, "imghash");
+            err |= cbor_encode_byte_string(&lmec->mapenc, entry->imghash,
+                                           LOG_MGMT_IMG_HASHLEN);
+        }
 
-    if (out_len != NULL) {
-        *out_len = cbor_encode_bytes_written(enc);
-    }
+#if MYNEWT_VAL(LOG_VERSION) > 2
+        err |= cbor_encode_text_stringz(&lmec->mapenc, "msg");
+   
+        /*
+         * Write entry data as byte string. Since this may not fit into single
+         * chunk of data we will write as indefinite-length byte string which is
+         * basically a indefinite-length container with definite-length strings
+         * inside.
+         */
+        err |= cbor_encoder_create_indef_byte_string(&lmec->mapenc, &lmec->msgenc);
+        if (out_len != NULL) {
+            for (off = 0; off < entry->len; off += entry->chunklen) {
+                chunklen = entry->chunklen;
+                if (entry->chunklen > entry->len - off) {
+                    chunklen = entry->len - off;
+                }
+                err |= cbor_encode_byte_string(&lmec->msgenc, entry->data, chunklen);
+                bytes_encoded += chunklen;
+            }
+        } else {
+            err |= cbor_encode_byte_string(&lmec->msgenc, entry->data, entry->chunklen);
+            bytes_encoded = entry->chunklen;
+        }
+#else
+        err |= cbor_encode_text_stringz(&lmec->mapenc, "msg");
+        err |= cbor_encode_text_stringz(&lmec->mapenc, (char *)data);
+#endif
+    } else {
+        /*
+         * The else case is executed for non-first chunks of data to be encoded
+         *
+         * Write entry data as byte string. Since this may not fit into single
+         * chunk of data we will write as indefinite-length byte string which is
+         * basically a indefinite-length container with definite-length strings
+         * inside.
+         */
+        err |= cbor_encode_byte_string(&lmec->msgenc, entry->data, entry->chunklen);
+        bytes_encoded = entry->chunklen;
+   }
 
-    return 0;
+   /*
+    * Containers need to get closed when encoding is done, the only way to know at
+    * this point in the code that encoding is done is using the number of bytes
+    * that got encoded and comparing it to the length of the entry
+    */ 
+   if (entry->offset + bytes_encoded >= entry->len) {
+       err |= cbor_encoder_close_container(&lmec->mapenc, &lmec->msgenc);
+       err |= cbor_encoder_close_container(enc, &lmec->mapenc);
+   }
+        
+   if (out_len) {
+       *out_len = cbor_encode_bytes_written(enc) - len;
+   }
+    
+   if (err != 0) {
+       return MGMT_ERR_ENOMEM;
+   }
+
+   return MGMT_ERR_EOK;
 }
 
 static int
-log_mgmt_cb_encode(const struct log_mgmt_entry *entry, void *arg)
+log_mgmt_cb_encode(struct log_mgmt_entry *entry, void *arg)
 {
     struct CborCntWriter cnt_writer;
+    struct log_mgmt_enc_ctxt *lmec;
     struct log_walk_ctxt *ctxt;
     CborEncoder cnt_encoder;
     size_t entry_len;
     int rc;
 
     ctxt = arg;
+    lmec = &ctxt->lmec;
 
-    /*** First, determine if this entry would fit. */
+    if (entry->offset == 0) {
+        /* 
+         * First, determine if this entry would fit using
+         * a counter encoder
+         */
+    
+        cbor_cnt_writer_init(&cnt_writer);
+#ifdef __ZEPHYR__
+        cbor_encoder_cust_writer_init(&cnt_encoder, &cnt_writer.enc, 0);
+#else
+        cbor_encoder_init(&cnt_encoder, &cnt_writer.enc, 0);
+#endif
+        rc = log_mgmt_encode_entry(&cnt_encoder, entry, &entry_len, lmec);
+        if (rc != 0) {
+            return rc;
+        }
+    
+        /*
+         * Check if the response is too long. If more than one entry is in the
+         * response we will not add the current one and will return ENOMEM. If this
+         * is just a single entry we add the generic too long message text.
+         */
+        /* `+ 1` to account for the CBOR array terminator. */
+        if (ctxt->rsp_len + entry_len + 1 > LOG_MGMT_MAX_RSP_LEN) {
+            /*
+             * Is this just a single entry? If so, encode the generic error
+             * message in the "msg" field of the response
+             */
+            if (ctxt->counter == 0) {
+#if MYNEWT_VAL(LOG_VERSION) > 2
+                entry->type = LOG_ETYPE_STRING;
+#endif
+                snprintf((char *)entry->data, LOG_MGMT_MAX_RSP_LEN,
+                         "error: entry too large (%d bytes)", entry_len);
+            }
+    
+            return MGMT_ERR_EMSGSIZE;
+        }
+        ctxt->rsp_len += entry_len;
+    }
 
-    cbor_cnt_writer_init(&cnt_writer);
-    cbor_encoder_cust_writer_init(&cnt_encoder, &cnt_writer.enc, 0);
-    rc = log_mgmt_encode_entry(&cnt_encoder, entry, &entry_len);
+    /*** The entry fits. Now encode it. */
+    rc = log_mgmt_encode_entry(ctxt->enc, entry, NULL, lmec);
     if (rc != 0) {
         return rc;
     }
 
-    /* `+ 1` to account for the CBOR array terminator. */
-    if (ctxt->rsp_len + entry_len + 1 > LOG_MGMT_CHUNK_SIZE) {
-        return MGMT_ERR_EMSGSIZE;
-    }
-    ctxt->rsp_len += entry_len;
-
-    /*** The entry fits.  Now encode it. */
-
-    rc = log_mgmt_encode_entry(ctxt->enc, entry, NULL);
-    if (rc != 0) {
-        return rc;
-    }
+    ctxt->counter++;
 
     return 0;
 }
@@ -153,6 +278,7 @@
     rc = log_mgmt_impl_foreach_entry(log->name, &filter,
                                      log_mgmt_cb_encode, &ctxt);
     if (rc != 0 && rc != MGMT_ERR_EMSGSIZE) {
+        cbor_encoder_close_container(enc, &entries);
         return rc;
     }
 
@@ -182,6 +308,7 @@
 
     rc = log_encode_entries(log, &logs, timestamp, index);
     if (rc != 0) {
+        cbor_encoder_close_container(ctxt, &logs);
         return rc;
     }
 
@@ -261,32 +388,43 @@
             /* Log list fully iterated. */
             if (name_len != 0) {
                 /* Client specified log name, but the log wasn't found. */
+                cbor_encoder_close_container(&ctxt->encoder, &logs);
                 return MGMT_ERR_ENOENT;
             } else {
                 break;
             }
         } else if (rc != 0) {
-            return rc;
+            goto err;
         }
 
         /* Stream logs cannot be read. */
         if (log.type != LOG_MGMT_TYPE_STREAM) {
             if (name_len == 0 || strcmp(name, log.name) == 0) {
                 rc = log_encode(&log, &logs, timestamp, index);
-                if (rc != 0) {
-                    return rc;
+
+#if LOG_MGMT_READ_WATERMARK_UPDATE
+                if (rc == 0 || rc == OS_ENOMEM) {
+                    log_mgmt_impl_set_watermark(&log, index);
+                }
+#endif
+                if (rc) {
+                    goto err;
                 }
 
+#if LOG_MGMT_READ_WATERMARK_UPDATE
+                log_mgmt_impl_set_watermark(&log, index);
+#endif
                 /* If the client specified this log, he isn't interested in the
                  * remaining ones.
                  */
-                if (name_len != 0) {
+                if (name_len > 0) {
                     break;
                 }
             }
         }
     }
 
+err:
     err |= cbor_encoder_close_container(&ctxt->encoder, &logs);
     err |= cbor_encode_text_stringz(&ctxt->encoder, "rc");
     err |= cbor_encode_int(&ctxt->encoder, rc);
@@ -323,6 +461,7 @@
             break;
         }
         if (rc != 0) {
+            cbor_encoder_close_container(&ctxt->encoder, &modules);
             return rc;
         }
 
@@ -366,6 +505,7 @@
             break;
         }
         if (rc != 0) {
+            cbor_encoder_close_container(&ctxt->encoder, &log_list);
             return rc;
         }
 
@@ -408,6 +548,7 @@
             break;
         }
         if (rc != 0) {
+            cbor_encoder_close_container(&ctxt->encoder, &level_map);
             return rc;
         }
 
diff --git a/cmd/log_mgmt/src/stubs.c b/cmd/log_mgmt/src/stubs.c
index 7ce61cf..05706e5 100644
--- a/cmd/log_mgmt/src/stubs.c
+++ b/cmd/log_mgmt/src/stubs.c
@@ -63,3 +63,9 @@
 {
     return MGMT_ERR_ENOTSUP;
 }
+
+int __attribute__((weak))
+log_mgmt_impl_set_watermark(struct log_mgmt_log *log, int index)
+{
+    return MGMT_ERR_ENOTSUP;
+}
diff --git a/cmd/os_mgmt/src/os_mgmt_config.h b/cmd/os_mgmt/include/os_mgmt/os_mgmt_config.h
similarity index 100%
rename from cmd/os_mgmt/src/os_mgmt_config.h
rename to cmd/os_mgmt/include/os_mgmt/os_mgmt_config.h
diff --git a/cmd/os_mgmt/pkg.yml b/cmd/os_mgmt/pkg.yml
index c1389c4..7e79da1 100644
--- a/cmd/os_mgmt/pkg.yml
+++ b/cmd/os_mgmt/pkg.yml
@@ -25,3 +25,12 @@
 
 pkg.deps:
     - '@apache-mynewt-core/kernel/os'
+    - '@apache-mynewt-mcumgr/cmd/os_mgmt/port/mynewt'
+    - '@apache-mynewt-mcumgr/mgmt'
+    - '@apache-mynewt-mcumgr/cborattr'
+
+pkg.ign_files:
+    - "stubs.c"
+
+pkg.init:
+    os_mgmt_module_init: 501
diff --git a/cmd/os_mgmt/port/mynewt/pkg.yml b/cmd/os_mgmt/port/mynewt/pkg.yml
new file mode 100644
index 0000000..4ddee67
--- /dev/null
+++ b/cmd/os_mgmt/port/mynewt/pkg.yml
@@ -0,0 +1,29 @@
+#
+# 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.
+#
+
+pkg.name: cmd/os_mgmt/port/mynewt
+pkg.description: 'OS management command handlers for mcumgr.'
+pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps:
+    - '@apache-mynewt-mcumgr/cmd/os_mgmt'
+    - '@apache-mynewt-mcumgr/mgmt'
+    - '@apache-mynewt-core/sys/reboot'
diff --git a/cmd/os_mgmt/port/mynewt/src/mynewt_os_mgmt.c b/cmd/os_mgmt/port/mynewt/src/mynewt_os_mgmt.c
index ccb94f0..46fd612 100644
--- a/cmd/os_mgmt/port/mynewt/src/mynewt_os_mgmt.c
+++ b/cmd/os_mgmt/port/mynewt/src/mynewt_os_mgmt.c
@@ -24,6 +24,8 @@
 #include "reboot/log_reboot.h"
 #endif
 #include "os_mgmt/os_mgmt_impl.h"
+#include "os_mgmt/os_mgmt.h"
+#include "mgmt/mgmt.h"
 
 static struct os_callout mynewt_os_mgmt_reset_callout;
 
@@ -102,15 +104,22 @@
 int
 os_mgmt_impl_reset(unsigned int delay_ms)
 {
-    int rc;
-
-    os_callout_init(&mynewt_os_mgmt_reset_callout, mgmt_evq_get(),
-                    nmgr_reset_tmo, NULL);
+#if MYNEWT_VAL(LOG_SOFT_RESET)
+    struct log_reboot_info info = {
+        .reason = HAL_RESET_REQUESTED,
+        .file = NULL,
+        .line = 0,
+        .pc = 0,
+    };
+#endif
+    os_callout_init(&mynewt_os_mgmt_reset_callout, os_eventq_dflt_get(),
+                    mynewt_os_mgmt_reset_tmo, NULL);
 
 #if MYNEWT_VAL(LOG_SOFT_RESET)
-    log_reboot(HAL_RESET_REQUESTED);
+    log_reboot(&info);
 #endif
-    os_callout_reset(&nmgr_reset_callout, delay_ms * OS_TICKS_PER_SEC / 1000);
+    os_callout_reset(&mynewt_os_mgmt_reset_callout,
+                     delay_ms * OS_TICKS_PER_SEC / 1000);
 
     return 0;
 }
diff --git a/cmd/os_mgmt/src/os_mgmt.c b/cmd/os_mgmt/src/os_mgmt.c
index f19418d..9b17e0b 100644
--- a/cmd/os_mgmt/src/os_mgmt.c
+++ b/cmd/os_mgmt/src/os_mgmt.c
@@ -19,30 +19,30 @@
 
 #include <assert.h>
 #include <string.h>
-#include "cbor.h"
+#include "tinycbor/cbor.h"
 #include "cborattr/cborattr.h"
 #include "mgmt/mgmt.h"
 #include "os_mgmt/os_mgmt.h"
 #include "os_mgmt/os_mgmt_impl.h"
-#include "os_mgmt_config.h"
+#include "os_mgmt/os_mgmt_config.h"
 
-#ifdef OS_MGMT_ECHO
+#if OS_MGMT_ECHO
 static mgmt_handler_fn os_mgmt_echo;
 #endif
 
 static mgmt_handler_fn os_mgmt_reset;
 
-#ifdef OS_MGMT_TASKSTAT
+#if OS_MGMT_TASKSTAT
 static mgmt_handler_fn os_mgmt_taskstat_read;
 #endif
 
 static const struct mgmt_handler os_mgmt_group_handlers[] = {
-#ifdef OS_MGMT_ECHO
+#if OS_MGMT_ECHO
     [OS_MGMT_ID_ECHO] = {
         os_mgmt_echo, os_mgmt_echo
     },
 #endif
-#ifdef OS_MGMT_TASKSTAT
+#if OS_MGMT_TASKSTAT
     [OS_MGMT_ID_TASKSTAT] = {
         os_mgmt_taskstat_read, NULL
     },
@@ -64,7 +64,7 @@
 /**
  * Command handler: os echo
  */
-#ifdef OS_MGMT_ECHO
+#if OS_MGMT_ECHO
 static int
 os_mgmt_echo(struct mgmt_ctxt *ctxt)
 {
@@ -102,7 +102,7 @@
 }
 #endif
 
-#ifdef OS_MGMT_TASKSTAT
+#if OS_MGMT_TASKSTAT
 /**
  * Encodes a single taskstat entry.
  */
@@ -175,6 +175,7 @@
 
         rc = os_mgmt_taskstat_encode_one(&tasks_map, &task_info);
         if (rc != 0) {
+            cbor_encoder_close_container(&ctxt->encoder, &tasks_map);
             return rc;
         }
     }
@@ -202,3 +203,9 @@
 {
     mgmt_register_group(&os_mgmt_group);
 }
+
+void
+os_mgmt_module_init(void)
+{
+    os_mgmt_register_group();
+}
diff --git a/cmd/os_mgmt/syscfg.yml b/cmd/os_mgmt/syscfg.yml
index 7ecb7c0..ef6bb0b 100644
--- a/cmd/os_mgmt/syscfg.yml
+++ b/cmd/os_mgmt/syscfg.yml
@@ -24,3 +24,13 @@
             milliseconds before performing the reset.  This delay allows time
             for the mcumgr response to be delivered.
         value: 250
+
+    OS_MGMT_TASKSTAT:
+        description: >
+            Enable support for taskstat command.
+        value: 1
+
+    OS_MGMT_ECHO:
+        description: >
+            Enable support for echo command.
+        value: 1
diff --git a/cmd/stat_mgmt/src/stat_mgmt_config.h b/cmd/stat_mgmt/include/stat_mgmt/stat_mgmt_config.h
similarity index 100%
rename from cmd/stat_mgmt/src/stat_mgmt_config.h
rename to cmd/stat_mgmt/include/stat_mgmt/stat_mgmt_config.h
diff --git a/cmd/stat_mgmt/pkg.yml b/cmd/stat_mgmt/pkg.yml
new file mode 100644
index 0000000..2b43f56
--- /dev/null
+++ b/cmd/stat_mgmt/pkg.yml
@@ -0,0 +1,29 @@
+#
+# 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.
+#
+
+pkg.name: cmd/stat_mgmt
+pkg.description: 'Stat management command handlers for mcumgr.'
+pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps:
+    - '@apache-mynewt-core/kernel/os'
+    - '@apache-mynewt-mcumgr/cmd/stat_mgmt/port/mynewt'
+    - '@apache-mynewt-mcumgr/mgmt'
diff --git a/cmd/stat_mgmt/port/mynewt/pkg.yml b/cmd/stat_mgmt/port/mynewt/pkg.yml
new file mode 100644
index 0000000..fc9e87d
--- /dev/null
+++ b/cmd/stat_mgmt/port/mynewt/pkg.yml
@@ -0,0 +1,31 @@
+#
+# 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.
+#
+
+pkg.name: cmd/stat_mgmt/port/mynewt
+pkg.description: 'Statistics management command handlers for mcumgr.'
+pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps:
+    - '@apache-mynewt-mcumgr/cmd/stat_mgmt'
+    - '@apache-mynewt-mcumgr/mgmt'
+
+pkg.init:
+    stat_mgmt_module_init: 501
diff --git a/cmd/stat_mgmt/port/mynewt/src/mynewt_stat_mgmt.c b/cmd/stat_mgmt/port/mynewt/src/mynewt_stat_mgmt.c
new file mode 100644
index 0000000..d9231ae
--- /dev/null
+++ b/cmd/stat_mgmt/port/mynewt/src/mynewt_stat_mgmt.c
@@ -0,0 +1,116 @@
+/*
+ * 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 "stats/stats.h"
+#include "mgmt/mgmt.h"
+#include "sysinit/sysinit.h"
+#include "stat_mgmt/stat_mgmt.h"
+#include "stat_mgmt/stat_mgmt_impl.h"
+#include "stat_mgmt/stat_mgmt_config.h"
+
+struct mynewt_stat_mgmt_walk_arg {
+    stat_mgmt_foreach_entry_fn *cb;
+    void *arg;
+};
+
+int
+stat_mgmt_impl_get_group(int idx, const char **out_name)
+{
+    const struct stats_hdr *cur;
+    int i;
+    int rc;
+
+    rc = MGMT_ERR_ENOENT;
+
+    cur = NULL;
+    i = 0;
+    STAILQ_FOREACH(cur, &g_stats_registry, s_next) {
+        if (i == idx) {
+            rc = 0;
+            break;
+        }
+        i++;
+    }
+
+    if (!rc) {
+        *out_name = cur->s_name;
+    }
+
+    return rc;
+}
+
+static int
+mynewt_stat_mgmt_walk_cb(struct stats_hdr *hdr, void *arg,
+                         char *name, uint16_t off)
+{
+    struct mynewt_stat_mgmt_walk_arg *walk_arg;
+    struct stat_mgmt_entry entry;
+    void *stat_val;
+
+    walk_arg = arg;
+
+    stat_val = (uint8_t *)hdr + off;
+    switch (hdr->s_size) {
+    case sizeof (uint16_t):
+        entry.value = *(uint16_t *) stat_val;
+        break;
+    case sizeof (uint32_t):
+        entry.value = *(uint32_t *) stat_val;
+        break;
+    case sizeof (uint64_t):
+        entry.value = *(uint64_t *) stat_val;
+        break;
+    default:
+        return MGMT_ERR_EUNKNOWN;
+    }
+    entry.name = name;
+
+    return walk_arg->cb(&entry, walk_arg->arg);
+}
+
+int
+stat_mgmt_impl_foreach_entry(const char *group_name,
+                             stat_mgmt_foreach_entry_fn *cb,
+                             void *arg)
+{
+    struct mynewt_stat_mgmt_walk_arg walk_arg;
+    struct stats_hdr *hdr;
+
+    hdr = stats_group_find(group_name);
+    if (hdr == NULL) {
+        return MGMT_ERR_ENOENT;
+    }
+
+    walk_arg = (struct mynewt_stat_mgmt_walk_arg) {
+        .cb = cb,
+        .arg = arg,
+    };
+
+    return stats_walk(hdr, mynewt_stat_mgmt_walk_cb, &walk_arg);
+}
+
+void
+stat_mgmt_module_init(void)
+{
+    /* Ensure this function only gets called by sysinit. */
+    SYSINIT_ASSERT_ACTIVE();
+
+    stat_mgmt_register_group();
+}
diff --git a/cmd/stat_mgmt/src/stat_mgmt.c b/cmd/stat_mgmt/src/stat_mgmt.c
index 7eac3f9..57ef216 100644
--- a/cmd/stat_mgmt/src/stat_mgmt.c
+++ b/cmd/stat_mgmt/src/stat_mgmt.c
@@ -24,7 +24,7 @@
 #include "cborattr/cborattr.h"
 #include "stat_mgmt/stat_mgmt.h"
 #include "stat_mgmt/stat_mgmt_impl.h"
-#include "stat_mgmt_config.h"
+#include "stat_mgmt/stat_mgmt_config.h"
 
 static mgmt_handler_fn stat_mgmt_show;
 static mgmt_handler_fn stat_mgmt_list;
@@ -68,7 +68,7 @@
 static int
 stat_mgmt_show(struct mgmt_ctxt *ctxt)
 {
-    char stat_name[CONFIG_STAT_MGMT_MAX_NAME_LEN];
+    char stat_name[STAT_MGMT_MAX_NAME_LEN];
     CborEncoder map_enc;
     CborError err;
     int rc;
@@ -100,17 +100,13 @@
 
     rc = stat_mgmt_impl_foreach_entry(stat_name, stat_mgmt_cb_encode,
                                       &map_enc);
-    if (rc != 0) {
-        return rc;
-    }
 
     err |= cbor_encoder_close_container(&ctxt->encoder, &map_enc);
-
     if (err != 0) {
-        return MGMT_ERR_ENOMEM;
+        rc = MGMT_ERR_ENOMEM;
     }
 
-    return 0;
+    return rc;
 }
 
 /**
@@ -125,7 +121,9 @@
     int rc;
     int i;
 
-    err = 0;
+    err = CborNoError;
+    err |= cbor_encode_text_stringz(&ctxt->encoder, "rc");
+    err |= cbor_encode_int(&ctxt->encoder, MGMT_ERR_EOK);
     err |= cbor_encode_text_stringz(&ctxt->encoder, "stat_list");
     err |= cbor_encoder_create_array(&ctxt->encoder, &arr_enc,
                                      CborIndefiniteLength);
@@ -140,6 +138,7 @@
             break;
         } else if (rc != 0) {
             /* Error. */
+            cbor_encoder_close_container(&ctxt->encoder, &arr_enc);
             return rc;
         }
 
diff --git a/cmd/stat_mgmt/syscfg.yml b/cmd/stat_mgmt/syscfg.yml
new file mode 100644
index 0000000..5fd9f06
--- /dev/null
+++ b/cmd/stat_mgmt/syscfg.yml
@@ -0,0 +1,26 @@
+# 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:
+    STAT_MGMT_MAX_NAME_LEN:
+        description: >
+            Limits the maximum stat group name length in mcumgr requests, in bytes.
+            A buffer of this size gets allocated on the stack during handling of all
+            stat read commands.  If a stat group's name exceeds this limit, it will
+            be impossible to retrieve its values with a stat show command.
+        value: 32
diff --git a/mgmt/include/mgmt/mgmt.h b/mgmt/include/mgmt/mgmt.h
index b17d693..66d8c45 100644
--- a/mgmt/include/mgmt/mgmt.h
+++ b/mgmt/include/mgmt/mgmt.h
@@ -21,12 +21,15 @@
 #define H_MGMT_MGMT_
 
 #include <inttypes.h>
-#include "cbor.h"
+#include "tinycbor/cbor.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+/* MTU for newtmgr responses */
+#define MGMT_MAX_MTU            1024
+
 /** Opcodes; encoded in first byte of header. */
 #define MGMT_OP_READ            0
 #define MGMT_OP_READ_RSP        1
@@ -60,6 +63,7 @@
 #define MGMT_ERR_EBADSTATE      6       /* Current state disallows command. */
 #define MGMT_ERR_EMSGSIZE       7       /* Response too large. */
 #define MGMT_ERR_ENOTSUP        8       /* Command not supported. */
+#define MGMT_ERR_ECORRUPT       9       /* Corrupt */
 #define MGMT_ERR_EPERUSER       256
 
 #define MGMT_HDR_SIZE           8
@@ -87,6 +91,8 @@
     uint8_t  nh_id;             /* Message ID within group */
 };
 
+#define nmgr_hdr mgmt_hdr
+
 /*
  * MGMT_EVT_OP_CMD_STATUS argument
  */
diff --git a/mgmt/pkg.yml b/mgmt/pkg.yml
index 94839bd..607df9a 100644
--- a/mgmt/pkg.yml
+++ b/mgmt/pkg.yml
@@ -26,4 +26,3 @@
 pkg.deps:
     - '@apache-mynewt-core/encoding/tinycbor'
     - '@apache-mynewt-core/kernel/os'
-    - '@mynewt-mcumgr/mgmt'
diff --git a/mgmt/src/mgmt.c b/mgmt/src/mgmt.c
index 9287272..351f353 100644
--- a/mgmt/src/mgmt.c
+++ b/mgmt/src/mgmt.c
@@ -18,7 +18,7 @@
  */
 
 #include <string.h>
-#include "cbor.h"
+#include "tinycbor/cbor.h"
 #include "mgmt/endian.h"
 #include "mgmt/mgmt.h"
 
@@ -70,6 +70,35 @@
     streamer->cfg->free_buf(buf, streamer->cb_arg);
 }
 
+static struct mgmt_group *
+mgmt_find_group(uint16_t group_id, uint16_t command_id)
+{
+    struct mgmt_group *group;
+
+    /*
+     * Find the group with the specified group id, if one exists
+     * check the handler for the command id and make sure
+     * that is not NULL. If that is not set, look for the group
+     * with a command id that is set
+     */
+    for (group = mgmt_group_list; group != NULL; group = group->mg_next) {
+        if (group->mg_group_id == group_id) {
+            if (command_id >= group->mg_handlers_count) {
+                return NULL;
+            }
+
+            if (!group->mg_handlers[command_id].mh_read &&
+                !group->mg_handlers[command_id].mh_write) {
+                continue;
+            }
+
+            break;
+        }
+    }
+
+    return group;
+}
+
 void
 mgmt_register_group(struct mgmt_group *group)
 {
@@ -81,31 +110,13 @@
     mgmt_group_list_end = group;
 }
 
-static struct mgmt_group *
-mgmt_find_group(uint16_t group_id)
-{
-    struct mgmt_group *group;
-
-    for (group = mgmt_group_list; group != NULL; group = group->mg_next) {
-        if (group->mg_group_id == group_id) {
-            return group;
-        }
-    }
-
-    return NULL;
-}
-
 const struct mgmt_handler *
 mgmt_find_handler(uint16_t group_id, uint16_t command_id)
 {
     const struct mgmt_group *group;
 
-    group = mgmt_find_group(group_id);
-    if (group == NULL) {
-        return NULL;
-    }
-
-    if (command_id >= group->mg_handlers_count) {
+    group = mgmt_find_group(group_id, command_id);
+    if (!group) {
         return NULL;
     }
 
@@ -145,13 +156,21 @@
 {
     int rc;
 
+#ifdef __ZEPHYR__
     rc = cbor_parser_cust_reader_init(streamer->reader, 0, &ctxt->parser,
                                       &ctxt->it);
+#else
+    rc = cbor_parser_init(streamer->reader, 0, &ctxt->parser, &ctxt->it);
+#endif
     if (rc != CborNoError) {
         return mgmt_err_from_cbor(rc);
     }
 
+#ifdef __ZEPHYR__
     cbor_encoder_cust_writer_init(&ctxt->encoder, streamer->writer, 0);
+#else
+    cbor_encoder_init(&ctxt->encoder, streamer->writer, 0);
+#endif
 
     return 0;
 }
diff --git a/omp/include/omp/omp.h b/omp/include/omp/omp.h
new file mode 100644
index 0000000..82502af
--- /dev/null
+++ b/omp/include/omp/omp.h
@@ -0,0 +1,109 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file
+ * @brief OMP - OIC Management Protocol.
+ *
+ * OMP is an OIC implementation of SMP, a basic protocol that sits on top of
+ * the mgmt layer. SMP requests and responses have the following format:
+ *
+ *     [Offset 0]: Mgmt header
+ *     [Offset 8]: CBOR map of command-specific key-value pairs.
+ *
+ * SMP request packets may contain multiple concatenated requests.  Each
+ * request must start at an offset that is a multiple of 4, so padding should
+ * be inserted between requests as necessary.  Requests are processed
+ * sequentially from the start of the packet to the end.  Each response is sent
+ * individually in its own packet.  If a request elicits an error response,
+ * processing of the packet is aborted.
+ */
+
+#ifndef H_OMP_
+#define H_OMP_
+
+#include "mgmt/mgmt.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct omp_streamer;
+struct mgmt_hdr;
+
+/**
+ * @brief Transmits an OMP response.
+ *
+ * @param stmr                  The OMP Streamer struct.
+ * @param retval                The return value for the request.
+ * @param arg                   Optional streamer argument.
+ */
+typedef void omp_tx_rsp_fn(struct omp_streamer *stmr, int retval, void* arg);
+
+/**
+ * @brief Decodes, encodes, and transmits OMP requests and responses.
+ *        Holds the callback pointer and the response CBOR encoder provided by
+ *        underlying OIC implementation.
+ */
+struct omp_streamer {
+    struct mgmt_streamer mgmt_stmr;
+    struct CborEncoder *rsp_encoder;
+    omp_tx_rsp_fn *tx_rsp_cb;
+};
+
+/**
+ * @brief Stores the streamer, management context and request.
+ */
+struct omp_state {
+    struct omp_streamer omp_stmr;
+    struct mgmt_ctxt *m_ctxt;
+    void *request;
+};
+
+
+/**
+ * @brief Processes a single OMP request packet and sends all corresponding
+ *        responses.
+ *
+ * Processes all OMP requests in an incoming packet.  Requests are processed
+ * sequentially from the start of the packet to the end.  Each response is sent
+ * individually in its own packet.  If a request elicits an error response,
+ * processing of the packet is aborted.  This function consumes the supplied
+ * request buffer regardless of the outcome.//encoder
+ *
+ * @param omgr_st               The OMP State struct
+ * @param req                   The request packet to process.
+ *
+ * @return                      0 on success, MGMT_ERR_[...] code on failure.
+ */
+int omp_impl_process_request_packet(struct omp_state *omgr_st, void *req);
+
+/**
+ * @brief Read the management header out from a cbor value
+ *
+ * @param cv      Ptr to CoberValue
+ * @param out_hdr Ptr to management header to be filled in
+ */ 
+int omp_read_hdr(struct CborValue *cv, struct mgmt_hdr *out_hdr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H_OMP_ */
diff --git a/cmd/img_mgmt/src/img_mgmt_config.h b/omp/include/omp/omp_priv.h
similarity index 61%
copy from cmd/img_mgmt/src/img_mgmt_config.h
copy to omp/include/omp/omp_priv.h
index a520372..4147cb7 100644
--- a/cmd/img_mgmt/src/img_mgmt_config.h
+++ b/omp/include/omp/omp_priv.h
@@ -17,25 +17,25 @@
  * under the License.
  */
 
-#ifndef H_IMG_MGMT_CONFIG_
-#define H_IMG_MGMT_CONFIG_
+#ifndef H_OMP_PRIV
+#define H_OMP_PRIV
 
-#if defined MYNEWT
+#include "mgmt/mgmt.h"
 
-#include "syscfg/syscfg.h"
-
-#define IMG_MGMT_UL_CHUNK_SIZE  MYNEWT_VAL(IMG_MGMT_UL_CHUNK_SIZE)
-
-#elif defined __ZEPHYR__
-
-#define IMG_MGMT_UL_CHUNK_SIZE  CONFIG_IMG_MGMT_UL_CHUNK_SIZE
-
-#else
-
-/* No direct support for this OS.  The application needs to define the above
- * settings itself.
- */
-
+#ifdef __cplusplus
+extern "C" {
 #endif
 
+int omp_encode_mgmt_hdr(struct CborEncoder *enc, struct mgmt_hdr hdr);
+int omp_send_err_rsp(struct CborEncoder *enc,
+                     const struct mgmt_hdr *hdr,
+                     int mgmt_status);
+int omp_process_mgmt_hdr(struct mgmt_hdr *req_hdr,
+                         struct mgmt_hdr *rsp_hdr,
+                         struct mgmt_ctxt *ctxt);
+
+#ifdef __cplusplus
+}
 #endif
+
+#endif /* H_OMP_IMPL */
diff --git a/omp/pkg.yml b/omp/pkg.yml
new file mode 100644
index 0000000..af293f4
--- /dev/null
+++ b/omp/pkg.yml
@@ -0,0 +1,34 @@
+#
+# 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.
+#
+
+pkg.name: omp
+pkg.description: Server-side SMP functionality for OIC
+pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+    - omp
+    - oicmgr
+    - mgmt
+
+pkg.deps:
+    - "@apache-mynewt-core/kernel/os"
+    - "@apache-mynewt-mcumgr/mgmt"
+    - "@apache-mynewt-mcumgr/cborattr"
+pkg.apis:
+    - smp
diff --git a/omp/port/mynewt/pkg.yml b/omp/port/mynewt/pkg.yml
new file mode 100644
index 0000000..8f7946b
--- /dev/null
+++ b/omp/port/mynewt/pkg.yml
@@ -0,0 +1,28 @@
+#
+# 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.
+#
+
+pkg.name: omp/port/mynewt
+pkg.description: 'OIC Management Protocol.'
+pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps:
+    - '@apache-mynewt-mcumgr/omp'
+    - '@apache-mynewt-mcumgr/mgmt'
diff --git a/omp/port/mynewt/src/mynewt_omp.c b/omp/port/mynewt/src/mynewt_omp.c
new file mode 100644
index 0000000..38b1ef4
--- /dev/null
+++ b/omp/port/mynewt/src/mynewt_omp.c
@@ -0,0 +1,91 @@
+/*
+ * 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 <assert.h>
+#include <string.h>
+
+#include "os/mynewt.h"
+
+#include <mgmt/mgmt.h>
+#include <cborattr/cborattr.h>
+#include <tinycbor/cbor.h>
+
+#include "omp/omp.h"
+#include "omp/omp_priv.h"
+
+int
+omp_impl_process_request_packet(struct omp_state *omgr_st, void *req_buf)
+{
+    struct mgmt_ctxt ctxt;
+    struct omp_streamer *streamer;
+    struct mgmt_hdr req_hdr, rsp_hdr;
+    struct os_mbuf *req_m;
+    int rc = 0;
+
+    assert(omgr_st);
+    assert(req_buf);
+
+    streamer = &omgr_st->omp_stmr;
+    omgr_st->m_ctxt = &ctxt;
+
+    req_m = (struct os_mbuf *) req_buf;
+
+    rc = mgmt_streamer_init_reader(&streamer->mgmt_stmr, req_m);
+    if (rc != 0) {
+        rc = MGMT_ERR_EINVAL;
+        return rc;
+
+    }
+
+    rc = omp_read_hdr(&ctxt.it, &req_hdr);
+    if (rc != 0) {
+        rc = MGMT_ERR_EINVAL;
+        return rc;
+
+    }
+
+    memcpy(&rsp_hdr, &req_hdr, sizeof(struct mgmt_hdr));
+
+    rc = mgmt_streamer_init_reader(&streamer->mgmt_stmr, req_m);
+    if (rc != 0) {
+        rc = MGMT_ERR_EINVAL;
+        return rc;
+
+    }
+
+    rc = cbor_encoder_create_map(streamer->rsp_encoder,
+                                 &ctxt.encoder,
+                                 CborIndefiniteLength);
+    if (rc != 0) {
+        rc = MGMT_ERR_EINVAL;
+        return rc;
+    }
+
+    rc = omp_process_mgmt_hdr(&req_hdr, &rsp_hdr, &ctxt);
+
+    cbor_encoder_close_container(streamer->rsp_encoder, &ctxt.encoder);
+    if (rc != 0) {
+        rc = MGMT_ERR_EINVAL;
+        return rc;
+
+    }
+
+    streamer->tx_rsp_cb(streamer, rc, NULL);
+    return 0;
+}
diff --git a/omp/src/omp.c b/omp/src/omp.c
new file mode 100644
index 0000000..fb1cc1e
--- /dev/null
+++ b/omp/src/omp.c
@@ -0,0 +1,157 @@
+/*
+ * 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 <assert.h>
+#include <string.h>
+
+#include "os/mynewt.h"
+
+#include <mgmt/mgmt.h>
+#include <cborattr/cborattr.h>
+#include <tinycbor/cbor.h>
+
+#include "omp/omp_priv.h"
+
+int
+omp_encode_mgmt_hdr(struct CborEncoder *enc, struct mgmt_hdr hdr)
+{
+    int rc;
+
+    rc = cbor_encode_text_string(enc, "_h", 2);
+    if (rc != 0) {
+        return MGMT_ERR_ENOMEM;
+    }
+
+    hdr.nh_len = htons(hdr.nh_len);
+    hdr.nh_group = htons(hdr.nh_group);
+
+    /* Encode the MGMT header in the response. */
+    rc = cbor_encode_byte_string(enc, (void *)&hdr, sizeof hdr);
+    if (rc != 0) {
+        return MGMT_ERR_ENOMEM;
+    }
+
+    return 0;
+}
+
+int
+omp_send_err_rsp(struct CborEncoder *enc,
+                 const struct mgmt_hdr *hdr,
+                 int mgmt_status)
+{
+    int rc;
+
+    rc = omp_encode_mgmt_hdr(enc, *hdr);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = cbor_encode_text_stringz(enc, "rc");
+    if (rc != 0) {
+        return MGMT_ERR_ENOMEM;
+    }
+
+    rc = cbor_encode_int(enc, mgmt_status);
+    if (rc != 0) {
+        return MGMT_ERR_ENOMEM;
+    }
+
+    return 0;
+}
+
+int
+omp_read_hdr(struct CborValue *cv, struct mgmt_hdr *out_hdr)
+{
+    size_t hlen;
+    int rc;
+
+    struct cbor_attr_t attrs[] = {
+        [0] = {
+            .attribute = "_h",
+            .type = CborAttrByteStringType,
+            .addr.bytestring.data = (void *)out_hdr,
+            .addr.bytestring.len = &hlen,
+            .nodefault = 1,
+            .len = sizeof *out_hdr,
+        },
+        [1] = { 0 }
+    };
+
+    rc = cbor_read_object(cv, attrs);
+    if (rc != 0 || hlen != sizeof *out_hdr) {
+        return MGMT_ERR_EINVAL;
+    }
+
+    out_hdr->nh_len = ntohs(out_hdr->nh_len);
+    out_hdr->nh_group = ntohs(out_hdr->nh_group);
+
+    return 0;
+}
+
+int
+omp_process_mgmt_hdr(struct mgmt_hdr *req_hdr,
+                     struct mgmt_hdr *rsp_hdr,
+                     struct mgmt_ctxt *ctxt)
+{
+    int rc = 0;
+    const struct mgmt_handler *handler;
+    mgmt_handler_fn *handler_fn = NULL;
+
+    handler = mgmt_find_handler(req_hdr->nh_group, req_hdr->nh_id);
+    if (handler == NULL) {
+        rc = MGMT_ERR_ENOENT;
+        return rc;
+    }
+
+    switch (req_hdr->nh_op) {
+    case MGMT_OP_READ:
+        rsp_hdr->nh_op = MGMT_OP_READ_RSP;
+        handler_fn = handler->mh_read;
+        break;
+
+    case MGMT_OP_WRITE:
+        rsp_hdr->nh_op = MGMT_OP_WRITE_RSP;
+        handler_fn = handler->mh_write;
+        break;
+
+    default:
+        rc = MGMT_ERR_EINVAL;
+    }
+
+    if (handler_fn) {
+        rc = handler_fn(ctxt);
+    } else {
+        rc = MGMT_ERR_ENOTSUP;
+    }
+
+    /* Encode the MGMT header in the response. */
+
+    if (rc != 0) {
+        if (handler_fn) {
+            rc = omp_send_err_rsp(&ctxt->encoder, rsp_hdr, rc);
+        }
+    } else {
+        rc = omp_encode_mgmt_hdr(&ctxt->encoder, *rsp_hdr);
+        if (rc != 0) {
+            rc = MGMT_ERR_ENOMEM;
+        }
+    }
+
+    return mgmt_err_from_cbor(rc);
+}
diff --git a/repository.yml b/repository.yml
index c2495ce..908f4f2 100644
--- a/repository.yml
+++ b/repository.yml
@@ -17,7 +17,7 @@
 # under the License.
 #
 
-repo.name: mynewt-mcumgr
+repo.name: apache-mynewt-mcumgr
 repo.versions:
     "0.0.0": "master"
 
diff --git a/samples/omp_svr/mynewt/pkg.yml b/samples/omp_svr/mynewt/pkg.yml
new file mode 100644
index 0000000..f9d725e
--- /dev/null
+++ b/samples/omp_svr/mynewt/pkg.yml
@@ -0,0 +1,70 @@
+# 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.
+#
+pkg.name: samples/omp_svr/mynewt
+pkg.type: app
+pkg.description: Simple BLE peripheral running an mcumgr OMP server.
+pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps: 
+    - '@apache-mynewt-core/mgmt/smp/transport/smp_shell'
+    - '@apache-mynewt-core/sys/console/full'
+    - '@apache-mynewt-core/sys/log/full'
+    - '@apache-mynewt-core/sys/stats/full'
+    - '@apache-mynewt-mcumgr/cmd/fs_mgmt'
+    - '@apache-mynewt-mcumgr/cmd/img_mgmt'
+    - '@apache-mynewt-mcumgr/cmd/os_mgmt'
+    - "@apache-mynewt-mcumgr/cmd/stat_mgmt"
+    - "@apache-mynewt-mcumgr/mgmt"
+    - '@apache-mynewt-mcumgr/smp'
+    - "@apache-mynewt-core/sys/reboot"
+    # - "@apache-mynewt-core/boot/split"
+    - "@apache-mynewt-core/sys/log/modlog"
+    - "@apache-mynewt-core/sys/id"
+    - "@apache-mynewt-core/sys/shell"
+    - "@apache-mynewt-core/sys/config"
+    - "@apache-mynewt-core/kernel/os"
+    - "@apache-mynewt-core/mgmt/oicmgr"
+    - "@apache-mynewt-core/sys/sysinit"
+    - "@apache-mynewt-core/mgmt/smp/smp_os"
+    - "@apache-mynewt-core/net/oic"
+
+pkg.deps.!BSP_SIMULATED:
+    - '@mcuboot/boot/bootutil'
+    - '@apache-mynewt-core/mgmt/smp/transport/ble'
+    - '@apache-mynewt-nimble/nimble/controller'
+    - '@apache-mynewt-nimble/nimble/host'
+    - '@apache-mynewt-nimble/nimble/host/util'
+    - '@apache-mynewt-nimble/nimble/host/services/gap'
+    - '@apache-mynewt-nimble/nimble/host/services/gatt'
+    - '@apache-mynewt-nimble/nimble/host/store/config'
+    - '@apache-mynewt-nimble/nimble/transport/ram'
+
+pkg.deps.BSP_SIMULATED:
+    - '@apache-mynewt-core/boot/stub'
+
+pkg.ign_files.BSP_SIMULATED:
+    - "misc.c"
+    - "gatt_svr.c"
+
+pkg.deps.CONFIG_NFFS:
+    - "@apache-mynewt-core/fs/nffs"
+
+pkg.deps.CONFIG_FCB:
+    - "@apache-mynewt-core/fs/fcb"
diff --git a/samples/omp_svr/mynewt/src/gatt_svr.c b/samples/omp_svr/mynewt/src/gatt_svr.c
new file mode 100644
index 0000000..ec74376
--- /dev/null
+++ b/samples/omp_svr/mynewt/src/gatt_svr.c
@@ -0,0 +1,58 @@
+/*
+ * 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 <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include "bsp/bsp.h"
+#include "host/ble_hs.h"
+#include "host/ble_uuid.h"
+#include "omp_svr.h"
+
+void
+gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg)
+{
+    char buf[BLE_UUID_STR_LEN];
+
+    switch (ctxt->op) {
+    case BLE_GATT_REGISTER_OP_SVC:
+        MODLOG_DFLT(DEBUG, "registered service %s with handle=%d\n",
+                    ble_uuid_to_str(ctxt->svc.svc_def->uuid, buf),
+                    ctxt->svc.handle);
+        break;
+
+    case BLE_GATT_REGISTER_OP_CHR:
+        MODLOG_DFLT(DEBUG, "registering characteristic %s with "
+                           "def_handle=%d val_handle=%d\n",
+                    ble_uuid_to_str(ctxt->chr.chr_def->uuid, buf),
+                    ctxt->chr.def_handle,
+                    ctxt->chr.val_handle);
+        break;
+
+    case BLE_GATT_REGISTER_OP_DSC:
+        MODLOG_DFLT(DEBUG, "registering descriptor %s with handle=%d\n",
+                    ble_uuid_to_str(ctxt->dsc.dsc_def->uuid, buf),
+                    ctxt->dsc.handle);
+        break;
+
+    default:
+        assert(0);
+        break;
+    }
+}
diff --git a/samples/omp_svr/mynewt/src/main.c b/samples/omp_svr/mynewt/src/main.c
new file mode 100644
index 0000000..5938b47
--- /dev/null
+++ b/samples/omp_svr/mynewt/src/main.c
@@ -0,0 +1,553 @@
+/**
+ * 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 <bsp/bsp.h>
+#include <hal/hal_gpio.h>
+#include <hal/hal_flash.h>
+#include <console/console.h>
+#include <log/log.h>
+#include <stats/stats.h>
+#include <config/config.h>
+#if MYNEWT_VAL(SPLIT_LOADER)
+#include "split/split.h"
+#endif
+#include <bootutil/image.h>
+#include <img_mgmt/img_mgmt.h>
+#include <mgmt/mgmt.h>
+#include <assert.h>
+#include <string.h>
+#include <reboot/log_reboot.h>
+#include <oic/oc_api.h>
+#include <cborattr/cborattr.h>
+
+#ifndef ARCH_sim
+/* BLE */
+#include "nimble/ble.h"
+#include "host/ble_hs.h"
+#include "host/util/util.h"
+#include "services/gap/ble_svc_gap.h"
+
+#include <oic/oc_gatt.h>
+
+/* Application-specified header. */
+#include "omp_svr.h"
+
+#else
+#include <mcu/mcu_sim.h>
+#endif /* !ARCH_sim */
+
+/* Task 1 */
+#define TASK1_PRIO (8)
+#define TASK1_STACK_SIZE    OS_STACK_ALIGN(192)
+#define MAX_CBMEM_BUF 600
+static struct os_task task1;
+static volatile int g_task1_loops;
+
+/* Task 2 */
+#define TASK2_PRIO (9)
+#define TASK2_STACK_SIZE    OS_STACK_ALIGN(64)
+static struct os_task task2;
+
+static volatile int g_task2_loops;
+
+/* Global test semaphore */
+static struct os_sem g_test_sem;
+
+/* For LED toggling */
+static int g_led_pin;
+
+STATS_SECT_START(gpio_stats)
+STATS_SECT_ENTRY(toggles)
+STATS_SECT_END
+
+static STATS_SECT_DECL(gpio_stats) g_stats_gpio_toggle;
+
+STATS_NAME_START(gpio_stats)
+STATS_NAME(gpio_stats, toggles)
+STATS_NAME_END(gpio_stats)
+
+static char *test_conf_get(int argc, char **argv, char *val, int max_len);
+static int test_conf_set(int argc, char **argv, char *val);
+static int test_conf_commit(void);
+static int test_conf_export(void (*export_func)(char *name, char *val),
+  enum conf_export_tgt tgt);
+
+static struct conf_handler test_conf_handler = {
+    .ch_name = "test",
+    .ch_get = test_conf_get,
+    .ch_set = test_conf_set,
+    .ch_commit = test_conf_commit,
+    .ch_export = test_conf_export
+};
+
+static uint8_t test8;
+static uint8_t test8_shadow;
+static char test_str[32];
+
+static char *
+test_conf_get(int argc, char **argv, char *buf, int max_len)
+{
+    if (argc == 1) {
+        if (!strcmp(argv[0], "8")) {
+            return conf_str_from_value(CONF_INT8, &test8, buf, max_len);
+        } else if (!strcmp(argv[0], "str")) {
+            return test_str;
+        }
+    }
+    return NULL;
+}
+
+static int
+test_conf_set(int argc, char **argv, char *val)
+{
+    if (argc == 1) {
+        if (!strcmp(argv[0], "8")) {
+            return CONF_VALUE_SET(val, CONF_INT8, test8_shadow);
+        } else if (!strcmp(argv[0], "str")) {
+            return CONF_VALUE_SET(val, CONF_STRING, test_str);
+        }
+    }
+    return OS_ENOENT;
+}
+
+static int
+test_conf_commit(void)
+{
+    test8 = test8_shadow;
+
+    return 0;
+}
+
+static int
+test_conf_export(void (*func)(char *name, char *val), enum conf_export_tgt tgt)
+{
+    char buf[4];
+
+    conf_str_from_value(CONF_INT8, &test8, buf, sizeof(buf));
+    func("test/8", buf);
+    func("test/str", test_str);
+    return 0;
+}
+
+#ifndef ARCH_sim
+static int omp_svr_gap_event(struct ble_gap_event *event, void *arg);
+
+/**
+ * Logs information about a connection to the console.
+ */
+static void
+omp_svr_print_conn_desc(struct ble_gap_conn_desc *desc)
+{
+    MODLOG_DFLT(INFO, "handle=%d our_ota_addr_type=%d our_ota_addr=",
+                desc->conn_handle, desc->our_ota_addr.type);
+    print_addr(desc->our_ota_addr.val);
+    MODLOG_DFLT(INFO, " our_id_addr_type=%d our_id_addr=",
+                desc->our_id_addr.type);
+    print_addr(desc->our_id_addr.val);
+    MODLOG_DFLT(INFO, " peer_ota_addr_type=%d peer_ota_addr=",
+                desc->peer_ota_addr.type);
+    print_addr(desc->peer_ota_addr.val);
+    MODLOG_DFLT(INFO, " peer_id_addr_type=%d peer_id_addr=",
+                desc->peer_id_addr.type);
+    print_addr(desc->peer_id_addr.val);
+    MODLOG_DFLT(INFO, " conn_itvl=%d conn_latency=%d supervision_timeout=%d "
+                "encrypted=%d authenticated=%d bonded=%d\n",
+                desc->conn_itvl, desc->conn_latency,
+                desc->supervision_timeout,
+                desc->sec_state.encrypted,
+                desc->sec_state.authenticated,
+                desc->sec_state.bonded);
+}
+
+/**
+ * Enables advertising with the following parameters:
+ *     o General discoverable mode.
+ *     o Undirected connectable mode.
+ */
+static void
+omp_svr_advertise(void)
+{
+    uint8_t own_addr_type;
+    struct ble_gap_adv_params adv_params;
+    struct ble_hs_adv_fields fields;
+    const char *name;
+    int rc;
+
+    /* Figure out address to use while advertising (no privacy for now) */
+    rc = ble_hs_id_infer_auto(0, &own_addr_type);
+    if (rc != 0) {
+        MODLOG_DFLT(ERROR, "error determining address type; rc=%d\n", rc);
+        return;
+    }
+
+    /**
+     *  Set the advertisement data included in our advertisements:
+     *     o Flags (indicates advertisement type and other general info).
+     *     o Advertising tx power.
+     *     o Device name.
+     *     o 16-bit service UUIDs (alert notifications).
+     */
+
+    memset(&fields, 0, sizeof fields);
+
+    /* Advertise two flags:
+     *     o Discoverability in forthcoming advertisement (general)
+     *     o BLE-only (BR/EDR unsupported).
+     */
+    fields.flags = BLE_HS_ADV_F_DISC_GEN |
+                   BLE_HS_ADV_F_BREDR_UNSUP;
+
+    /* Indicate that the TX power level field should be included; have the
+     * stack fill this value automatically.  This is done by assiging the
+     * special value BLE_HS_ADV_TX_PWR_LVL_AUTO.
+     */
+    fields.tx_pwr_lvl_is_present = 1;
+    fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO;
+
+    name = ble_svc_gap_device_name();
+    fields.name = (uint8_t *)name;
+    fields.name_len = strlen(name);
+    fields.name_is_complete = 1;
+
+    fields.uuids16 = (ble_uuid16_t[]){
+        BLE_UUID16_INIT(GATT_SVR_SVC_ALERT_UUID)
+    };
+    fields.num_uuids16 = 1;
+    fields.uuids16_is_complete = 1;
+
+    rc = ble_gap_adv_set_fields(&fields);
+    if (rc != 0) {
+        MODLOG_DFLT(ERROR, "error setting advertisement data; rc=%d\n", rc);
+        return;
+    }
+
+    /* Begin advertising. */
+    memset(&adv_params, 0, sizeof adv_params);
+    adv_params.conn_mode = BLE_GAP_CONN_MODE_UND;
+    adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
+    rc = ble_gap_adv_start(own_addr_type, NULL, BLE_HS_FOREVER,
+                           &adv_params, omp_svr_gap_event, NULL);
+    if (rc != 0) {
+        MODLOG_DFLT(ERROR, "error enabling advertisement; rc=%d\n", rc);
+        return;
+    }
+}
+
+/**
+ * The nimble host executes this callback when a GAP event occurs.  The
+ * application associates a GAP event callback with each connection that forms.
+ * omp_svr uses the same callback for all connections.
+ *
+ * @param event                 The type of event being signalled.
+ * @param ctxt                  Various information pertaining to the event.
+ * @param arg                   Application-specified argument; unuesd by
+ *                                  omp_svr.
+ *
+ * @return                      0 if the application successfully handled the
+ *                                  event; nonzero on failure.  The semantics
+ *                                  of the return code is specific to the
+ *                                  particular GAP event being signalled.
+ */
+static int
+omp_svr_gap_event(struct ble_gap_event *event, void *arg)
+{
+    struct ble_gap_conn_desc desc;
+    int rc;
+
+    switch (event->type) {
+    case BLE_GAP_EVENT_CONNECT:
+        /* A new connection was established or a connection attempt failed. */
+        MODLOG_DFLT(INFO, "connection %s; status=%d ",
+                    event->connect.status == 0 ? "established" : "failed",
+                    event->connect.status);
+        if (event->connect.status == 0) {
+            rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
+            assert(rc == 0);
+            omp_svr_print_conn_desc(&desc);
+
+        }
+        MODLOG_DFLT(INFO, "\n");
+
+        if (event->connect.status != 0) {
+            /* Connection failed; resume advertising. */
+            omp_svr_advertise();
+        }
+        return 0;
+
+    case BLE_GAP_EVENT_DISCONNECT:
+        MODLOG_DFLT(INFO, "disconnect; reason=%d ", event->disconnect.reason);
+        omp_svr_print_conn_desc(&event->disconnect.conn);
+        MODLOG_DFLT(INFO, "\n");
+
+        /* Connection terminated; resume advertising. */
+        omp_svr_advertise();
+        return 0;
+
+    case BLE_GAP_EVENT_CONN_UPDATE:
+        /* The central has updated the connection parameters. */
+        MODLOG_DFLT(INFO, "connection updated; status=%d ",
+                    event->conn_update.status);
+        rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
+        assert(rc == 0);
+        omp_svr_print_conn_desc(&desc);
+        MODLOG_DFLT(INFO, "\n");
+        return 0;
+
+    case BLE_GAP_EVENT_ADV_COMPLETE:
+        MODLOG_DFLT(INFO, "advertise complete; reason=%d",
+                    event->adv_complete.reason);
+        omp_svr_advertise();
+        return 0;
+
+    case BLE_GAP_EVENT_ENC_CHANGE:
+        /* Encryption has been enabled or disabled for this connection. */
+        MODLOG_DFLT(INFO, "encryption change event; status=%d ",
+                    event->enc_change.status);
+        rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
+        assert(rc == 0);
+        omp_svr_print_conn_desc(&desc);
+        MODLOG_DFLT(INFO, "\n");
+        return 0;
+
+    case BLE_GAP_EVENT_SUBSCRIBE:
+        MODLOG_DFLT(INFO, "subscribe event; conn_handle=%d attr_handle=%d "
+                          "reason=%d prevn=%d curn=%d previ=%d curi=%d\n",
+                    event->subscribe.conn_handle,
+                    event->subscribe.attr_handle,
+                    event->subscribe.reason,
+                    event->subscribe.prev_notify,
+                    event->subscribe.cur_notify,
+                    event->subscribe.prev_indicate,
+                    event->subscribe.cur_indicate);
+        return 0;
+
+    case BLE_GAP_EVENT_MTU:
+        MODLOG_DFLT(INFO, "mtu update event; conn_handle=%d cid=%d mtu=%d\n",
+                    event->mtu.conn_handle,
+                    event->mtu.channel_id,
+                    event->mtu.value);
+        return 0;
+
+    case BLE_GAP_EVENT_REPEAT_PAIRING:
+        /* We already have a bond with the peer, but it is attempting to
+         * establish a new secure link.  This app sacrifices security for
+         * convenience: just throw away the old bond and accept the new link.
+         */
+
+        /* Delete the old bond. */
+        rc = ble_gap_conn_find(event->repeat_pairing.conn_handle, &desc);
+        assert(rc == 0);
+        ble_store_util_delete_peer(&desc.peer_id_addr);
+
+        /* Return BLE_GAP_REPEAT_PAIRING_RETRY to indicate that the host should
+         * continue with the pairing operation.
+         */
+        return BLE_GAP_REPEAT_PAIRING_RETRY;
+    }
+
+    return 0;
+}
+
+static void
+omp_svr_on_reset(int reason)
+{
+    MODLOG_DFLT(ERROR, "Resetting state; reason=%d\n", reason);
+}
+
+static void
+omp_svr_on_sync(void)
+{
+    int rc;
+
+    /* Make sure we have proper identity address set (public preferred) */
+    rc = ble_hs_util_ensure_addr(0);
+    assert(rc == 0);
+
+    /* Begin advertising. */
+    omp_svr_advertise();
+}
+#endif /* ARCH_sim */
+
+void
+task1_handler(void *arg)
+{
+    struct os_task *t;
+    int prev_pin_state, curr_pin_state;
+    struct image_version ver;
+    char ver_str[IMG_MGMT_VER_MAX_STR_LEN];
+    int rc;
+
+    /* Set the led pin for the E407 devboard */
+    g_led_pin = LED_BLINK_PIN;
+    hal_gpio_init_out(g_led_pin, 1);
+
+    if (img_mgmt_read_info(0, &ver, NULL, NULL) == 0) {
+        rc = img_mgmt_ver_str(&ver, ver_str);
+        assert(rc == 0);
+        console_printf("\nOMP_SVR %s\n", ver_str);
+    } else {
+        console_printf("\nOMP_SVR\n");
+    }
+
+    while (1) {
+        t = os_sched_get_current_task();
+        assert(t->t_func == task1_handler);
+
+        ++g_task1_loops;
+
+        /* Wait one second */
+        os_time_delay(OS_TICKS_PER_SEC);
+
+        /* Toggle the LED */
+        prev_pin_state = hal_gpio_read(g_led_pin);
+        curr_pin_state = hal_gpio_toggle(g_led_pin);
+        MODLOG_DFLT(INFO, "GPIO %d: %u to %u\n", g_led_pin,
+                    prev_pin_state, curr_pin_state);
+        STATS_INC(g_stats_gpio_toggle, toggles);
+
+        /* Release semaphore to task 2 */
+        os_sem_release(&g_test_sem);
+    }
+}
+
+void
+task2_handler(void *arg)
+{
+    struct os_task *t;
+
+    while (1) {
+        /* just for debug; task 2 should be the running task */
+        t = os_sched_get_current_task();
+        assert(t->t_func == task2_handler);
+
+        /* Increment # of times we went through task loop */
+        ++g_task2_loops;
+
+        /* Wait for semaphore from ISR */
+        os_sem_pend(&g_test_sem, OS_TIMEOUT_NEVER);
+    }
+}
+
+/*
+ * OIC platform/resource registration.
+ */
+static void
+omgr_app_init(void)
+{
+    oc_init_platform("MyNewt", NULL, NULL);
+}
+
+static const oc_handler_t omgr_oc_handler = {
+    .init = omgr_app_init,
+};
+
+/**
+ * init_tasks
+ *
+ * Called by main.c after sysinit(). This function performs initializations
+ * that are required before tasks are running.
+ *
+ * @return int 0 success; error otherwise.
+ */
+static void
+init_tasks(void)
+{
+    os_stack_t *pstack;
+    /* Initialize global test semaphore */
+    os_sem_init(&g_test_sem, 0);
+
+    pstack = malloc(sizeof(os_stack_t)*TASK1_STACK_SIZE);
+    assert(pstack);
+
+    os_task_init(&task1, "task1", task1_handler, NULL,
+            TASK1_PRIO, OS_WAIT_FOREVER, pstack, TASK1_STACK_SIZE);
+
+    pstack = malloc(sizeof(os_stack_t)*TASK2_STACK_SIZE);
+    assert(pstack);
+
+    os_task_init(&task2, "task2", task2_handler, NULL,
+            TASK2_PRIO, OS_WAIT_FOREVER, pstack, TASK2_STACK_SIZE);
+
+    oc_main_init((oc_handler_t *)&omgr_oc_handler);
+}
+
+/**
+ * main
+ *
+ * The main task for the project. This function initializes the packages, calls
+ * init_tasks to initialize additional tasks (and possibly other objects),
+ * then starts serving events from default event queue.
+ *
+ * @return int NOTE: this function should never return!
+ */
+int
+main(int argc, char **argv)
+{
+    int rc;
+
+#ifdef ARCH_sim
+    mcu_sim_parse_args(argc, argv);
+#endif
+    sysinit();
+
+#ifndef ARCH_sim
+    oc_ble_coap_gatt_srv_init();
+
+    /* Initialize the NimBLE host configuration. */
+    ble_hs_cfg.reset_cb = omp_svr_on_reset;
+    ble_hs_cfg.sync_cb = omp_svr_on_sync;
+    ble_hs_cfg.gatts_register_cb = gatt_svr_register_cb;
+    ble_hs_cfg.store_status_cb = ble_store_util_status_rr;
+
+    /* Set the default device name. */
+    rc = ble_svc_gap_device_name_set("mynewt-omp-svr");
+    assert(rc == 0);
+#endif
+
+    rc = conf_register(&test_conf_handler);
+    assert(rc == 0);
+
+    stats_init(STATS_HDR(g_stats_gpio_toggle),
+               STATS_SIZE_INIT_PARMS(g_stats_gpio_toggle, STATS_SIZE_32),
+               STATS_NAME_INIT_PARMS(gpio_stats));
+
+    stats_register("gpio_toggle", STATS_HDR(g_stats_gpio_toggle));
+
+    reboot_start(hal_reset_cause());
+
+#if MYNEWT_VAL(SPLIT_LOADER)
+    {
+        void *entry;
+        rc = split_app_go(&entry, true);
+        if(rc == 0) {
+            hal_system_start(entry);
+        }
+    }
+#endif
+
+    init_tasks();
+
+    while (1) {
+        os_eventq_run(os_eventq_dflt_get());
+    }
+    /* Never returns */
+
+    return rc;
+}
diff --git a/cmd/img_mgmt/src/img_mgmt_config.h b/samples/omp_svr/mynewt/src/misc.c
similarity index 64%
copy from cmd/img_mgmt/src/img_mgmt_config.h
copy to samples/omp_svr/mynewt/src/misc.c
index a520372..27ab0aa 100644
--- a/cmd/img_mgmt/src/img_mgmt_config.h
+++ b/samples/omp_svr/mynewt/src/misc.c
@@ -17,25 +17,27 @@
  * under the License.
  */
 
-#ifndef H_IMG_MGMT_CONFIG_
-#define H_IMG_MGMT_CONFIG_
+#include "omp_svr.h"
 
-#if defined MYNEWT
-
-#include "syscfg/syscfg.h"
-
-#define IMG_MGMT_UL_CHUNK_SIZE  MYNEWT_VAL(IMG_MGMT_UL_CHUNK_SIZE)
-
-#elif defined __ZEPHYR__
-
-#define IMG_MGMT_UL_CHUNK_SIZE  CONFIG_IMG_MGMT_UL_CHUNK_SIZE
-
-#else
-
-/* No direct support for this OS.  The application needs to define the above
- * settings itself.
+/**
+ * Utility function to log an array of bytes.
  */
+void
+print_bytes(const uint8_t *bytes, int len)
+{
+    int i;
 
-#endif
+    for (i = 0; i < len; i++) {
+        MODLOG_DFLT(INFO, "%s0x%02x", i != 0 ? ":" : "", bytes[i]);
+    }
+}
 
-#endif
+void
+print_addr(const void *addr)
+{
+    const uint8_t *u8p;
+
+    u8p = addr;
+    MODLOG_DFLT(INFO, "%02x:%02x:%02x:%02x:%02x:%02x",
+                u8p[5], u8p[4], u8p[3], u8p[2], u8p[1], u8p[0]);
+}
diff --git a/samples/omp_svr/mynewt/src/omp_svr.h b/samples/omp_svr/mynewt/src/omp_svr.h
new file mode 100644
index 0000000..69c40e7
--- /dev/null
+++ b/samples/omp_svr/mynewt/src/omp_svr.h
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+#ifndef H_OMP_SVR_
+#define H_OMP_SVR_
+
+#include <stdbool.h>
+#include "nimble/ble.h"
+#include "modlog/modlog.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ble_hs_cfg;
+struct ble_gatt_register_ctxt;
+
+/** GATT server. */
+#define GATT_SVR_SVC_ALERT_UUID               0x1811
+#define GATT_SVR_CHR_SUP_NEW_ALERT_CAT_UUID   0x2A47
+#define GATT_SVR_CHR_NEW_ALERT                0x2A46
+#define GATT_SVR_CHR_SUP_UNR_ALERT_CAT_UUID   0x2A48
+#define GATT_SVR_CHR_UNR_ALERT_STAT_UUID      0x2A45
+#define GATT_SVR_CHR_ALERT_NOT_CTRL_PT        0x2A44
+
+void gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg);
+int gatt_svr_init(void);
+
+/** Misc **/
+void print_bytes(const uint8_t *bytes, int len);
+void print_addr(const void *addr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/samples/omp_svr/mynewt/syscfg.yml b/samples/omp_svr/mynewt/syscfg.yml
new file mode 100644
index 0000000..1c35a78
--- /dev/null
+++ b/samples/omp_svr/mynewt/syscfg.yml
@@ -0,0 +1,59 @@
+# 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.
+#
+
+# Package: apps/omp_svr
+
+syscfg.vals:
+    # Log reboot messages to a flash circular buffer.
+    REBOOT_LOG_FCB: 1
+    LOG_FCB: 1
+    CONFIG_FCB: 1
+    
+    # Enable shell commands.
+    STATS_CLI: 1
+    LOG_CLI: 1
+    SHELL_TASK: 1
+
+    # Enable MCUmgr commands.
+    STATS_MGMT: 1
+    LOG_MGMT: 1
+    CONFIG_MGMT: 1
+
+    # OS main/default task
+    OS_MAIN_STACK_SIZE: 468
+
+    # Lots of smaller mbufs are required for smp using typical BLE ATT MTU
+    # values.
+    MSYS_1_BLOCK_COUNT: 22
+    MSYS_1_BLOCK_SIZE: 110
+
+    OC_SERVER: 1
+    #Enables OIC transport over nlip serial
+    OC_TRANSPORT_SERIAL: 1
+    # Enables API to send delayed responses
+    OC_SEPARATE_RESPONSES: '0'
+
+syscfg.vals.!BSP_SIMULATED:
+    # Disable central and observer roles.
+    BLE_ROLE_BROADCASTER: 1
+    BLE_ROLE_CENTRAL: 0
+    BLE_ROLE_OBSERVER: 0
+    BLE_ROLE_PERIPHERAL: 1
+
+    # Enable gatt tranport
+    OC_TRANSPORT_GATT: 1
diff --git a/samples/smp_svr/mynewt/pkg.yml b/samples/smp_svr/mynewt/pkg.yml
index 5ab44e3..f2f8f78 100644
--- a/samples/smp_svr/mynewt/pkg.yml
+++ b/samples/smp_svr/mynewt/pkg.yml
@@ -23,20 +23,29 @@
 pkg.keywords:
 
 pkg.deps: 
-    - '@apache-mynewt-core/boot/bootutil'
-    - '@apache-mynewt-core/mgmt/newtmgr/transport/ble'
-    - '@apache-mynewt-core/mgmt/newtmgr/transport/nmgr_shell'
-    - '@apache-mynewt-core/net/nimble/controller'
-    - '@apache-mynewt-core/net/nimble/host'
-    - '@apache-mynewt-core/net/nimble/host/services/ans'
-    - '@apache-mynewt-core/net/nimble/host/services/gap'
-    - '@apache-mynewt-core/net/nimble/host/services/gatt'
-    - '@apache-mynewt-core/net/nimble/host/store/config'
-    - '@apache-mynewt-core/net/nimble/transport/ram'
+    - '@apache-mynewt-core/mgmt/smp/transport/smp_shell'
     - '@apache-mynewt-core/sys/console/full'
     - '@apache-mynewt-core/sys/log/full'
     - '@apache-mynewt-core/sys/stats/full'
-    - '@mynewt-mcumgr/cmd/fs_mgmt'
-    - '@mynewt-mcumgr/cmd/img_mgmt'
-    - '@mynewt-mcumgr/cmd/os_mgmt'
-    - '@mynewt-mcumgr/smp'
+    - '@apache-mynewt-mcumgr/cmd/fs_mgmt'
+    - '@apache-mynewt-mcumgr/cmd/img_mgmt'
+    - '@apache-mynewt-mcumgr/cmd/os_mgmt'
+    - '@apache-mynewt-mcumgr/smp'
+
+pkg.deps.!BSP_SIMULATED:
+    - '@mcuboot/boot/bootutil'
+    - '@apache-mynewt-core/mgmt/smp/transport/ble'
+    - '@apache-mynewt-nimble/nimble/controller'
+    - '@apache-mynewt-nimble/nimble/host'
+    - '@apache-mynewt-nimble/nimble/host/util'
+    - '@apache-mynewt-nimble/nimble/host/services/ans'
+    - '@apache-mynewt-nimble/nimble/host/services/gap'
+    - '@apache-mynewt-nimble/nimble/host/services/gatt'
+    - '@apache-mynewt-nimble/nimble/host/store/config'
+    - '@apache-mynewt-nimble/nimble/transport/ram'
+
+pkg.deps.BSP_SIMULATED:
+    - '@apache-mynewt-core/boot/stub'
+
+pkg.ign_files.BSP_SIMULATED:
+    - "gatt_svr.c"
diff --git a/samples/smp_svr/mynewt/src/gatt_svr.c b/samples/smp_svr/mynewt/src/gatt_svr.c
new file mode 100644
index 0000000..5d4fa7a
--- /dev/null
+++ b/samples/smp_svr/mynewt/src/gatt_svr.c
@@ -0,0 +1,204 @@
+/*
+ * 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 <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include "bsp/bsp.h"
+#include "host/ble_hs.h"
+#include "host/ble_uuid.h"
+#include "smp_svr.h"
+
+/**
+ * The vendor specific security test service consists of two characteristics:
+ *     o random-number-generator: generates a random 32-bit number each time
+ *       it is read.  This characteristic can only be read over an encrypted
+ *       connection.
+ *     o static-value: a single-byte characteristic that can always be read,
+ *       but can only be written over an encrypted connection.
+ */
+
+/* 59462f12-9543-9999-12c8-58b459a2712d */
+static const ble_uuid128_t gatt_svr_svc_sec_test_uuid =
+    BLE_UUID128_INIT(0x2d, 0x71, 0xa2, 0x59, 0xb4, 0x58, 0xc8, 0x12,
+                     0x99, 0x99, 0x43, 0x95, 0x12, 0x2f, 0x46, 0x59);
+
+/* 5c3a659e-897e-45e1-b016-007107c96df6 */
+static const ble_uuid128_t gatt_svr_chr_sec_test_rand_uuid =
+        BLE_UUID128_INIT(0xf6, 0x6d, 0xc9, 0x07, 0x71, 0x00, 0x16, 0xb0,
+                         0xe1, 0x45, 0x7e, 0x89, 0x9e, 0x65, 0x3a, 0x5c);
+
+/* 5c3a659e-897e-45e1-b016-007107c96df7 */
+static const ble_uuid128_t gatt_svr_chr_sec_test_static_uuid =
+        BLE_UUID128_INIT(0xf7, 0x6d, 0xc9, 0x07, 0x71, 0x00, 0x16, 0xb0,
+                         0xe1, 0x45, 0x7e, 0x89, 0x9e, 0x65, 0x3a, 0x5c);
+
+static uint8_t gatt_svr_sec_test_static_val;
+
+static int
+gatt_svr_chr_access_sec_test(uint16_t conn_handle, uint16_t attr_handle,
+                             struct ble_gatt_access_ctxt *ctxt,
+                             void *arg);
+
+static const struct ble_gatt_svc_def gatt_svr_svcs[] = {
+    {
+        /*** Service: Security test. */
+        .type = BLE_GATT_SVC_TYPE_PRIMARY,
+        .uuid = &gatt_svr_svc_sec_test_uuid.u,
+        .characteristics = (struct ble_gatt_chr_def[]) { {
+            /*** Characteristic: Random number generator. */
+            .uuid = &gatt_svr_chr_sec_test_rand_uuid.u,
+            .access_cb = gatt_svr_chr_access_sec_test,
+            .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC,
+        }, {
+            /*** Characteristic: Static value. */
+            .uuid = &gatt_svr_chr_sec_test_static_uuid.u,
+            .access_cb = gatt_svr_chr_access_sec_test,
+            .flags = BLE_GATT_CHR_F_READ |
+                     BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_ENC,
+        }, {
+            0, /* No more characteristics in this service. */
+        } },
+    },
+
+    {
+        0, /* No more services. */
+    },
+};
+
+static int
+gatt_svr_chr_write(struct os_mbuf *om, uint16_t min_len, uint16_t max_len,
+                   void *dst, uint16_t *len)
+{
+    uint16_t om_len;
+    int rc;
+
+    om_len = OS_MBUF_PKTLEN(om);
+    if (om_len < min_len || om_len > max_len) {
+        return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
+    }
+
+    rc = ble_hs_mbuf_to_flat(om, dst, max_len, len);
+    if (rc != 0) {
+        return BLE_ATT_ERR_UNLIKELY;
+    }
+
+    return 0;
+}
+
+static int
+gatt_svr_chr_access_sec_test(uint16_t conn_handle, uint16_t attr_handle,
+                             struct ble_gatt_access_ctxt *ctxt,
+                             void *arg)
+{
+    const ble_uuid_t *uuid;
+    int rand_num;
+    int rc;
+
+    uuid = ctxt->chr->uuid;
+
+    /* Determine which characteristic is being accessed by examining its
+     * 128-bit UUID.
+     */
+
+    if (ble_uuid_cmp(uuid, &gatt_svr_chr_sec_test_rand_uuid.u) == 0) {
+        assert(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR);
+
+        /* Respond with a 32-bit random number. */
+        rand_num = rand();
+        rc = os_mbuf_append(ctxt->om, &rand_num, sizeof rand_num);
+        return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
+    }
+
+    if (ble_uuid_cmp(uuid, &gatt_svr_chr_sec_test_static_uuid.u) == 0) {
+        switch (ctxt->op) {
+        case BLE_GATT_ACCESS_OP_READ_CHR:
+            rc = os_mbuf_append(ctxt->om, &gatt_svr_sec_test_static_val,
+                                sizeof gatt_svr_sec_test_static_val);
+            return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
+
+        case BLE_GATT_ACCESS_OP_WRITE_CHR:
+            rc = gatt_svr_chr_write(ctxt->om,
+                                    sizeof gatt_svr_sec_test_static_val,
+                                    sizeof gatt_svr_sec_test_static_val,
+                                    &gatt_svr_sec_test_static_val, NULL);
+            return rc;
+
+        default:
+            assert(0);
+            return BLE_ATT_ERR_UNLIKELY;
+        }
+    }
+
+    /* Unknown characteristic; the nimble stack should not have called this
+     * function.
+     */
+    assert(0);
+    return BLE_ATT_ERR_UNLIKELY;
+}
+
+void
+gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg)
+{
+    char buf[BLE_UUID_STR_LEN];
+
+    switch (ctxt->op) {
+    case BLE_GATT_REGISTER_OP_SVC:
+        MODLOG_DFLT(DEBUG, "registered service %s with handle=%d\n",
+                    ble_uuid_to_str(ctxt->svc.svc_def->uuid, buf),
+                    ctxt->svc.handle);
+        break;
+
+    case BLE_GATT_REGISTER_OP_CHR:
+        MODLOG_DFLT(DEBUG, "registering characteristic %s with "
+                           "def_handle=%d val_handle=%d\n",
+                    ble_uuid_to_str(ctxt->chr.chr_def->uuid, buf),
+                    ctxt->chr.def_handle,
+                    ctxt->chr.val_handle);
+        break;
+
+    case BLE_GATT_REGISTER_OP_DSC:
+        MODLOG_DFLT(DEBUG, "registering descriptor %s with handle=%d\n",
+                    ble_uuid_to_str(ctxt->dsc.dsc_def->uuid, buf),
+                    ctxt->dsc.handle);
+        break;
+
+    default:
+        assert(0);
+        break;
+    }
+}
+
+int
+gatt_svr_init(void)
+{
+    int rc;
+
+    rc = ble_gatts_count_cfg(gatt_svr_svcs);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = ble_gatts_add_svcs(gatt_svr_svcs);
+    if (rc != 0) {
+        return rc;
+    }
+
+    return 0;
+}
diff --git a/samples/smp_svr/mynewt/src/main.c b/samples/smp_svr/mynewt/src/main.c
index 19d5f91..43d75d9 100755
--- a/samples/smp_svr/mynewt/src/main.c
+++ b/samples/smp_svr/mynewt/src/main.c
@@ -23,17 +23,24 @@
 #include <errno.h>
 #include "sysinit/sysinit.h"
 #include "bsp/bsp.h"
-#include "bsp/bsp.h"
 #include "config/config.h"
 #include "console/console.h"
 #include "hal/hal_gpio.h"
 #include "hal/hal_system.h"
 #include "os/os.h"
+#include "modlog/modlog.h"
 
+#ifndef ARCH_sim
 /* BLE */
 #include "nimble/ble.h"
 #include "host/ble_hs.h"
 #include "services/gap/ble_svc_gap.h"
+#include "smp_svr.h"
+#include "host/util/util.h"
+
+#else
+#include <mcu/mcu_sim.h>
+#endif  /* !ARCH_sim */
 
 /* smp_svr uses the first "peruser" log module. */
 #define SMP_SVR_LOG_MODULE  (LOG_MODULE_PERUSER + 0)
@@ -45,6 +52,7 @@
 /** Log data. */
 struct log smp_svr_log;
 
+#ifndef ARCH_sim
 static int smp_svr_gap_event(struct ble_gap_event *event, void *arg);
 
 void
@@ -92,11 +100,19 @@
 static void
 smp_svr_advertise(void)
 {
+    uint8_t own_addr_type;
     struct ble_gap_adv_params adv_params;
     struct ble_hs_adv_fields fields;
     const char *name;
     int rc;
 
+
+    /* Figure out address to use while advertising (no privacy for now) */
+    rc = ble_hs_id_infer_auto(0, &own_addr_type);
+    if (rc != 0) {
+        MODLOG_DFLT(ERROR, "error determining address type; rc=%d\n", rc);
+        return;
+    }
     /**
      *  Set the advertisement data included in our advertisements:
      *     o Flags (indicates advertisement type and other general info).
@@ -126,12 +142,6 @@
     fields.name_len = strlen(name);
     fields.name_is_complete = 1;
 
-    fields.uuids16 = (ble_uuid16_t[]){
-        BLE_UUID16_INIT(GATT_SVR_SVC_ALERT_UUID)
-    };
-    fields.num_uuids16 = 1;
-    fields.uuids16_is_complete = 1;
-
     rc = ble_gap_adv_set_fields(&fields);
     if (rc != 0) {
         SMP_SVR_LOG(ERROR, "error setting advertisement data; rc=%d\n", rc);
@@ -142,7 +152,7 @@
     memset(&adv_params, 0, sizeof adv_params);
     adv_params.conn_mode = BLE_GAP_CONN_MODE_UND;
     adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
-    rc = ble_gap_adv_start(BLE_OWN_ADDR_PUBLIC, NULL, BLE_HS_FOREVER,
+    rc = ble_gap_adv_start(own_addr_type, NULL, BLE_HS_FOREVER,
                            &adv_params, smp_svr_gap_event, NULL);
     if (rc != 0) {
         SMP_SVR_LOG(ERROR, "error enabling advertisement; rc=%d\n", rc);
@@ -181,10 +191,6 @@
             rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
             assert(rc == 0);
             smp_svr_print_conn_desc(&desc);
-
-#if MYNEWT_VAL(SMP_SVR_LE_PHY_SUPPORT)
-            phy_conn_changed(event->connect.conn_handle);
-#endif
         }
         SMP_SVR_LOG(INFO, "\n");
 
@@ -199,10 +205,6 @@
         smp_svr_print_conn_desc(&event->disconnect.conn);
         SMP_SVR_LOG(INFO, "\n");
 
-#if MYNEWT_VAL(SMP_SVR_LE_PHY_SUPPORT)
-        phy_conn_changed(CONN_HANDLE_INVALID);
-#endif
-
         /* Connection terminated; resume advertising. */
         smp_svr_advertise();
         return 0;
@@ -269,9 +271,16 @@
 static void
 smp_svr_on_sync(void)
 {
+    int rc;
+
+    /* Make sure we have proper identity address set (public preferred) */
+    rc = ble_hs_util_ensure_addr(0);
+    assert(rc == 0);
+
     /* Begin advertising. */
     smp_svr_advertise();
 }
+#endif /* !ARCH_sim */
 
 /**
  * main
@@ -282,10 +291,13 @@
  * @return int NOTE: this function should never return!
  */
 int
-main(void)
+main(int argc, char **argv)
 {
+#ifndef ARCH_sim
     int rc;
-
+#else
+    mcu_sim_parse_args(argc, argv);
+#endif
     /* Initialize OS */
     sysinit();
 
@@ -293,9 +305,8 @@
     log_register("smp_svr", &smp_svr_log, &log_console_handler, NULL,
                  LOG_SYSLEVEL);
 
+#ifndef ARCH_sim
     /* Initialize the NimBLE host configuration. */
-    log_register("ble_hs", &ble_hs_log, &log_console_handler, NULL,
-                 LOG_SYSLEVEL);
     ble_hs_cfg.reset_cb = smp_svr_on_reset;
     ble_hs_cfg.sync_cb = smp_svr_on_sync;
     ble_hs_cfg.gatts_register_cb = gatt_svr_register_cb;
@@ -307,7 +318,7 @@
     /* Set the default device name. */
     rc = ble_svc_gap_device_name_set("smp_svr");
     assert(rc == 0);
-
+#endif
     conf_load();
 
     /*
diff --git a/samples/smp_svr/mynewt/src/smp_svr.h b/samples/smp_svr/mynewt/src/smp_svr.h
new file mode 100644
index 0000000..52b7b5e
--- /dev/null
+++ b/samples/smp_svr/mynewt/src/smp_svr.h
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+#ifndef SMP_SVR_
+#define SMP_SVR_
+
+#include <stdbool.h>
+#include "nimble/ble.h"
+#include "modlog/modlog.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ble_hs_cfg;
+struct ble_gatt_register_ctxt;
+
+/** GATT server. */
+#define GATT_SVR_SVC_ALERT_UUID               0x1811
+#define GATT_SVR_CHR_SUP_NEW_ALERT_CAT_UUID   0x2A47
+#define GATT_SVR_CHR_NEW_ALERT                0x2A46
+#define GATT_SVR_CHR_SUP_UNR_ALERT_CAT_UUID   0x2A48
+#define GATT_SVR_CHR_UNR_ALERT_STAT_UUID      0x2A45
+#define GATT_SVR_CHR_ALERT_NOT_CTRL_PT        0x2A44
+
+void gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg);
+int gatt_svr_init(void);
+
+/** Misc. */
+void print_bytes(const uint8_t *bytes, int len);
+void print_addr(const void *addr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/samples/smp_svr/mynewt/syscfg.yml b/samples/smp_svr/mynewt/syscfg.yml
index 99b4dc4..bd48253 100644
--- a/samples/smp_svr/mynewt/syscfg.yml
+++ b/samples/smp_svr/mynewt/syscfg.yml
@@ -19,21 +19,33 @@
 # Package: apps/bleprph
 
 syscfg.vals:
-    # Disable central and observer roles.
-    BLE_ROLE_BROADCASTER: 1
-    BLE_ROLE_CENTRAL: 0
-    BLE_ROLE_OBSERVER: 0
-    BLE_ROLE_PERIPHERAL: 1
 
     # Log reboot messages to a flash circular buffer.
     REBOOT_LOG_FCB: 1
     LOG_FCB: 1
     CONFIG_FCB: 1
 
+    # Enable shell commands.
+    STATS_CLI: 1
+    LOG_CLI: 1
+    SHELL_TASK: 1
+
+    # Enable MCUmgr commands.
+    STATS_MGMT: 1
+    LOG_MGMT: 1
+    CONFIG_MGMT: 1
+
     # OS main/default task
     OS_MAIN_STACK_SIZE: 468
 
-    # Lots of smaller mbufs are required for newtmgr using typical BLE ATT MTU
+    # Lots of smaller mbufs are required for smp using typical BLE ATT MTU
     # values.
     MSYS_1_BLOCK_COUNT: 22
     MSYS_1_BLOCK_SIZE: 110
+
+syscfg.vals.!BSP_SIMULATED:
+    # Disable central and observer roles.
+    BLE_ROLE_BROADCASTER: 1
+    BLE_ROLE_CENTRAL: 0
+    BLE_ROLE_OBSERVER: 0
+    BLE_ROLE_PERIPHERAL: 1
diff --git a/smp/pkg.yml b/smp/pkg.yml
index b9fcc78..0be9c3e 100644
--- a/smp/pkg.yml
+++ b/smp/pkg.yml
@@ -24,17 +24,10 @@
 pkg.keywords:
 
 pkg.deps:
-    - '@apache-mynewt-core/encoding/cborattr'
+    - '@apache-mynewt-mcumgr/cborattr'
     - '@apache-mynewt-core/kernel/os'
     - '@apache-mynewt-core/util/mem'
-    - '@mynewt-mcumgr/mgmt'
-    - '@mynewt-mcumgr/smp'
-
-pkg.deps.NEWTMGR_BLE_HOST:
-    - '@apache-mynewt-core/mgmt/newtmgr/transport/ble'
+    - '@apache-mynewt-mcumgr/mgmt'
 
 pkg.apis:
-    - newtmgr
-
-pkg.init:
-    smp_pkg_init: 500
+    - smp
diff --git a/smp/src/smp.c b/smp/src/smp.c
index 9b929ca..fae40aa 100644
--- a/smp/src/smp.c
+++ b/smp/src/smp.c
@@ -25,7 +25,7 @@
 #include "mgmt/endian.h"
 #include "mgmt/mgmt.h"
 #include "smp/smp.h"
-#include "cbor.h"
+#include "tinycbor/cbor.h"
 
 static int
 smp_align4(int x)
diff --git a/util/pkg.yml b/util/pkg.yml
new file mode 100644
index 0000000..c0ce5b6
--- /dev/null
+++ b/util/pkg.yml
@@ -0,0 +1,28 @@
+#
+# 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.
+#
+
+pkg.name: util 
+pkg.description: >
+    Library containing utility functions including
+    but not limited to  convert integer to strings
+pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+    - lltos
+    - ultos