You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by st...@apache.org on 2016/09/29 01:34:50 UTC

[43/49] incubator-mynewt-core git commit: directory re-org

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/encoding/tinycbor/src/cbortojson.c
----------------------------------------------------------------------
diff --git a/encoding/tinycbor/src/cbortojson.c b/encoding/tinycbor/src/cbortojson.c
new file mode 100644
index 0000000..953f2aa
--- /dev/null
+++ b/encoding/tinycbor/src/cbortojson.c
@@ -0,0 +1,686 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Intel Corporation
+**
+** Permission is hereby granted, free of charge, to any person obtaining a copy
+** of this software and associated documentation files (the "Software"), to deal
+** in the Software without restriction, including without limitation the rights
+** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+** copies of the Software, and to permit persons to whom the Software is
+** furnished to do so, subject to the following conditions:
+**
+** The above copyright notice and this permission notice shall be included in
+** all copies or substantial portions of the Software.
+**
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+** THE SOFTWARE.
+**
+****************************************************************************/
+
+#define _BSD_SOURCE 1
+#define _DEFAULT_SOURCE 1
+#define _GNU_SOURCE 1
+#define _POSIX_C_SOURCE 200809L
+#ifndef __STDC_LIMIT_MACROS
+#  define __STDC_LIMIT_MACROS 1
+#endif
+
+#include "cbor.h"
+#include "cborjson.h"
+#include "compilersupport_p.h"
+#include "math_support_p.h"
+
+#include <float.h>
+#include <inttypes.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/**
+ * \defgroup CborToJson Converting CBOR to JSON
+ * \brief Group of functions used to convert CBOR to JSON.
+ *
+ * This group contains two functions that are can be used to convert one
+ * CborValue object to an equivalent JSON representation. This module attempts
+ * to follow the recommendations from RFC 7049 section 4.1 "Converting from
+ * CBOR to JSON", though it has a few differences. They are noted below.
+ *
+ * These functions produce a "minified" JSON output, with no spacing,
+ * indentation or line breaks. If those are necessary, they need to be applied
+ * in a post-processing phase.
+ *
+ * Note that JSON cannot support all CBOR types with fidelity, so the
+ * conversion is usually lossy. For that reason, TinyCBOR supports adding a set
+ * of metadata JSON values that can be used by a JSON-to-CBOR converter to
+ * restore the original data types.
+ *
+ * The TinyCBOR library does not provide a way to convert from JSON
+ * representation back to encoded form. However, it provides a tool called
+ * \c json2cbor which can be used for that purpose. That tool supports the
+ * metadata format that these functions may produce.
+ *
+ * Either of the functions in this section will attempt to convert exactly one
+ * CborValue object to JSON. Those functions may return any error documented
+ * for the functions for CborParsing. In addition, if the C standard library
+ * stream functions return with error, the text conversion will return with
+ * error CborErrorIO.
+ *
+ * These functions also perform UTF-8 validation in CBOR text strings. If they
+ * encounter a sequence of bytes that not permitted in UTF-8, they will return
+ * CborErrorInvalidUtf8TextString. That includes encoding of surrogate points
+ * in UTF-8.
+ *
+ * \warning The metadata produced by these functions is not guaranteed to
+ * remain stable. A future update of TinyCBOR may produce different output for
+ * the same input and parsers may be unable to handle them.
+ *
+ * \sa CborParsing, CborPretty, cbor_parser_init()
+ */
+
+/**
+ * \addtogroup CborToJson
+ * @{
+ * <h2 class="groupheader">Conversion limitations</h2>
+ *
+ * When converting from CBOR to JSON, there may be information loss. This
+ * section lists the possible scenarios.
+ *
+ * \par Number precision:
+ * ALL JSON numbers, due to its JavaScript heritage, are IEEE 754
+ * double-precision floating point. This means JSON is not capable of
+ * representing integers numbers outside the range [-(2<sup>53</sup>)+1,
+ * 2<sup>53</sup>-1] and is not capable of representing NaN or infinite. If the
+ * CBOR data contains a number outside the valid range, the conversion will
+ * lose precision. If the input was NaN or infinite, the result of the
+ * conversion will be "null". In addition, the distinction between half-,
+ * single- and double-precision is lost.
+ *
+ * \par
+ * If enabled, the original value and original type are stored in the metadata.
+ *
+ * \par Non-native types:
+ * CBOR's type system is richer than JSON's, which means some data values
+ * cannot be represented when converted to JSON. The conversion silently turns
+ * them into strings: CBOR simple types become "simple(nn)" where \c nn is the
+ * simple type's value, with the exception of CBOR undefined, which becomes
+ * "undefined", while CBOR byte strings are converted to an Base16, Base64, or
+ * Base64url encoding
+ *
+ * \par
+ * If enabled, the original type is stored in the metadata.
+ *
+ * \par Presence of tags:
+ * JSON has no support for tagged values, so by default tags are dropped when
+ * converting to JSON. However, if the CborConvertObeyByteStringTags option is
+ * active (default), then certain known tags are honored and are used to format
+ * the conversion of the tagged byte string to JSON.
+ *
+ * \par
+ * If the CborConvertTagsToObjects option is active, then the tag and the
+ * tagged value are converted to to a JSON object. Otherwise, if enabled, the
+ * last (innermost) tag is stored in the metadata.
+ *
+ * \par Non-string keys in maps:
+ * JSON requires all Object keys to be strings, while CBOR does not. By
+ * default, if a non-string key is found, the conversion fails with error
+ * CborErrorJsonObjectKeyNotString. If the CborConvertStringifyMapKeys option
+ * is active, then the conversion attempts to create a string representation
+ * using CborPretty. Note that the \c json2cbor tool is not able to parse this
+ * back to the original form.
+ *
+ * \par Duplicate keys in maps:
+ * Neither JSON nor CBOR allow duplicated keys, but current TinyCBOR does not
+ * validate that this is the case. If there are duplicated keys in the input,
+ * they will be repeated in the output, which may JSON tools may flag as
+ * invalid. In addition to that, if the CborConvertStringifyMapKeys option is
+ * active, it is possible that a non-string key in a CBOR map will be converted
+ * to a string form that is identical to another key.
+ *
+ * \par
+ * When metadata support is active, the conversion will add extra key-value
+ * pairs to the JSON output so it can store the metadata. It is possible that
+ * the keys for the metadata clash with existing keys in the JSON map.
+ */
+
+extern FILE *open_memstream(char **bufptr, size_t *sizeptr);
+
+enum ConversionStatusFlags {
+    TypeWasNotNative            = 0x100,    /* anything but strings, boolean, null, arrays and maps */
+    TypeWasTagged               = 0x200,
+    NumberPrecisionWasLost      = 0x400,
+    NumberWasNaN                = 0x800,
+    NumberWasInfinite           = 0x1000,
+    NumberWasNegative           = 0x2000,   /* always used with NumberWasInifite or NumberWasTooBig */
+
+    FinalTypeMask               = 0xff
+};
+
+typedef struct ConversionStatus {
+    CborTag lastTag;
+    uint64_t originalNumber;
+    int flags;
+} ConversionStatus;
+
+static CborError value_to_json(FILE *out, CborValue *it, int flags, CborType type, ConversionStatus *status);
+
+static CborError dump_bytestring_base16(char **result, CborValue *it)
+{
+    static const char characters[] = "0123456789abcdef";
+    size_t i;
+    size_t n = 0;
+    uint8_t *buffer;
+    CborError err = cbor_value_calculate_string_length(it, &n);
+    if (err)
+        return err;
+
+    /* a Base16 (hex) output is twice as big as our buffer */
+    buffer = (uint8_t *)malloc(n * 2 + 1);
+    *result = (char *)buffer;
+
+    /* let cbor_value_copy_byte_string know we have an extra byte for the terminating NUL */
+    ++n;
+    err = cbor_value_copy_byte_string(it, buffer + n - 1, &n, it);
+    assert(err == CborNoError);
+
+    for (i = 0; i < n; ++i) {
+        uint8_t byte = buffer[n + i];
+        buffer[2*i]     = characters[byte >> 4];
+        buffer[2*i + 1] = characters[byte & 0xf];
+    }
+    return CborNoError;
+}
+
+static CborError generic_dump_base64(char **result, CborValue *it, const char alphabet[65])
+{
+    size_t n = 0, i;
+    uint8_t *buffer, *out, *in;
+    CborError err = cbor_value_calculate_string_length(it, &n);
+    if (err)
+        return err;
+
+    /* a Base64 output (untruncated) has 4 bytes for every 3 in the input */
+    size_t len = (n + 5) / 3 * 4;
+    out = buffer = (uint8_t *)malloc(len + 1);
+    *result = (char *)buffer;
+
+    /* we read our byte string at the tail end of the buffer
+     * so we can do an in-place conversion while iterating forwards */
+    in = buffer + len - n;
+
+    /* let cbor_value_copy_byte_string know we have an extra byte for the terminating NUL */
+    ++n;
+    err = cbor_value_copy_byte_string(it, in, &n, it);
+    assert(err == CborNoError);
+
+    uint_least32_t val = 0;
+    for (i = 0; n - i >= 3; i += 3) {
+        /* read 3 bytes x 8 bits = 24 bits */
+        if (false) {
+#ifdef __GNUC__
+        } else if (i) {
+            __builtin_memcpy(&val, in + i - 1, sizeof(val));
+            val = cbor_ntohl(val);
+#endif
+        } else {
+            val = (in[i] << 16) | (in[i + 1] << 8) | in[i + 2];
+        }
+
+        /* write 4 chars x 6 bits = 24 bits */
+        *out++ = alphabet[(val >> 18) & 0x3f];
+        *out++ = alphabet[(val >> 12) & 0x3f];
+        *out++ = alphabet[(val >> 6) & 0x3f];
+        *out++ = alphabet[val & 0x3f];
+    }
+
+    /* maybe 1 or 2 bytes left */
+    if (n - i) {
+        /* we can read in[i + 1] even if it's past the end of the string because
+         * we know (by construction) that it's a NUL byte */
+#ifdef __GNUC__
+        uint16_t val16;
+        __builtin_memcpy(&val16, in + i, sizeof(val16));
+        val = cbor_ntohs(val16);
+#else
+        val = (in[i] << 8) | in[i + 1];
+#endif
+        val <<= 8;
+
+        /* the 65th character in the alphabet is our filler: either '=' or '\0' */
+        out[4] = '\0';
+        out[3] = alphabet[64];
+        if (n - i == 2) {
+            /* write the third char in 3 chars x 6 bits = 18 bits */
+            out[2] = alphabet[(val >> 6) & 0x3f];
+        } else {
+            out[2] = alphabet[64];  /* filler */
+        }
+        out[1] = alphabet[(val >> 12) & 0x3f];
+        out[0] = alphabet[(val >> 18) & 0x3f];
+    } else {
+        out[0] = '\0';
+    }
+
+    return CborNoError;
+}
+
+static CborError dump_bytestring_base64(char **result, CborValue *it)
+{
+    static const char alphabet[] = "ABCDEFGH" "IJKLMNOP" "QRSTUVWX" "YZabcdef"
+                                   "ghijklmn" "opqrstuv" "wxyz0123" "456789+/" "=";
+    return generic_dump_base64(result, it, alphabet);
+}
+
+static CborError dump_bytestring_base64url(char **result, CborValue *it)
+{
+    static const char alphabet[] = "ABCDEFGH" "IJKLMNOP" "QRSTUVWX" "YZabcdef"
+                                   "ghijklmn" "opqrstuv" "wxyz0123" "456789-_";
+    return generic_dump_base64(result, it, alphabet);
+}
+
+static CborError add_value_metadata(FILE *out, CborType type, const ConversionStatus *status)
+{
+    int flags = status->flags;
+    if (flags & TypeWasTagged) {
+        /* extract the tagged type, which may be JSON native */
+        type = flags & FinalTypeMask;
+        flags &= ~(FinalTypeMask | TypeWasTagged);
+
+        if (fprintf(out, "\"tag\":\"%" PRIu64 "\"%s", status->lastTag,
+                    flags & ~TypeWasTagged ? "," : "") < 0)
+            return CborErrorIO;
+    }
+
+    if (!flags)
+        return CborNoError;
+
+    /* print at least the type */
+    if (fprintf(out, "\"t\":%d", type) < 0)
+        return CborErrorIO;
+
+    if (flags & NumberWasNaN)
+        if (fprintf(out, ",\"v\":\"nan\"") < 0)
+            return CborErrorIO;
+    if (flags & NumberWasInfinite)
+        if (fprintf(out, ",\"v\":\"%sinf\"", flags & NumberWasNegative ? "-" : "") < 0)
+            return CborErrorIO;
+    if (flags & NumberPrecisionWasLost)
+        if (fprintf(out, ",\"v\":\"%c%" PRIx64 "\"", flags & NumberWasNegative ? '-' : '+',
+                    status->originalNumber) < 0)
+            return CborErrorIO;
+    if (type == CborSimpleType)
+        if (fprintf(out, ",\"v\":%d", (int)status->originalNumber) < 0)
+            return CborErrorIO;
+    return CborNoError;
+}
+
+static CborError find_tagged_type(CborValue *it, CborTag *tag, CborType *type)
+{
+    CborError err = CborNoError;
+    *type = cbor_value_get_type(it);
+    while (*type == CborTagType) {
+        cbor_value_get_tag(it, tag);    /* can't fail */
+        err = cbor_value_advance_fixed(it);
+        if (err)
+            return err;
+
+        *type = cbor_value_get_type(it);
+    }
+    return err;
+}
+
+static CborError tagged_value_to_json(FILE *out, CborValue *it, int flags, ConversionStatus *status)
+{
+    CborTag tag;
+    CborError err;
+
+    if (flags & CborConvertTagsToObjects) {
+        cbor_value_get_tag(it, &tag);       /* can't fail */
+        err = cbor_value_advance_fixed(it);
+        if (err)
+            return err;
+
+        if (fprintf(out, "{\"tag%" PRIu64 "\":", tag) < 0)
+            return CborErrorIO;
+
+        CborType type = cbor_value_get_type(it);
+        err = value_to_json(out, it, flags, type, status);
+        if (err)
+            return err;
+        if (flags & CborConvertAddMetadata && status->flags) {
+            if (fprintf(out, ",\"tag%" PRIu64 "$cbor\":{", tag) < 0 ||
+                    add_value_metadata(out, type, status) != CborNoError ||
+                    fputc('}', out) < 0)
+                return CborErrorIO;
+        }
+        if (fputc('}', out) < 0)
+            return CborErrorIO;
+        status->flags = TypeWasNotNative | CborTagType;
+        return CborNoError;
+    }
+
+    CborType type;
+    err = find_tagged_type(it, &status->lastTag, &type);
+    if (err)
+        return err;
+    tag = status->lastTag;
+
+    /* special handling of byte strings? */
+    if (type == CborByteStringType && (flags & CborConvertByteStringsToBase64Url) == 0 &&
+            (tag == CborNegativeBignumTag || tag == CborExpectedBase16Tag || tag == CborExpectedBase64Tag)) {
+        char *str;
+        char *pre = "";
+
+        if (tag == CborNegativeBignumTag) {
+            pre = "~";
+            err = dump_bytestring_base64url(&str, it);
+        } else if (tag == CborExpectedBase64Tag) {
+            err = dump_bytestring_base64(&str, it);
+        } else { /* tag == CborExpectedBase16Tag */
+            err = dump_bytestring_base16(&str, it);
+        }
+        if (err)
+            return err;
+        err = fprintf(out, "\"%s%s\"", pre, str) < 0 ? CborErrorIO : CborNoError;
+        free(str);
+        status->flags = TypeWasNotNative | TypeWasTagged | CborByteStringType;
+        return err;
+    }
+
+    /* no special handling */
+    err = value_to_json(out, it, flags, type, status);
+    status->flags |= TypeWasTagged | type;
+    return err;
+}
+
+static CborError stringify_map_key(char **key, CborValue *it, int flags, CborType type)
+{
+    (void)flags;    /* unused */
+    (void)type;     /* unused */
+#ifdef WITHOUT_OPEN_MEMSTREAM
+    (void)key;      /* unused */
+    (void)it;       /* unused */
+    return CborErrorJsonNotImplemented;
+#else
+    size_t size;
+
+    FILE *memstream = open_memstream(key, &size);
+    if (memstream == NULL)
+        return CborErrorOutOfMemory;        /* could also be EMFILE, but it's unlikely */
+    CborError err = cbor_value_to_pretty_advance(memstream, it);
+
+    if (unlikely(fclose(memstream) < 0 || *key == NULL))
+        return CborErrorInternalError;
+    return err;
+#endif
+}
+
+static CborError array_to_json(FILE *out, CborValue *it, int flags, ConversionStatus *status)
+{
+    const char *comma = "";
+    while (!cbor_value_at_end(it)) {
+        if (fprintf(out, "%s", comma) < 0)
+            return CborErrorIO;
+        comma = ",";
+
+        CborError err = value_to_json(out, it, flags, cbor_value_get_type(it), status);
+        if (err)
+            return err;
+    }
+    return CborNoError;
+}
+
+static CborError map_to_json(FILE *out, CborValue *it, int flags, ConversionStatus *status)
+{
+    const char *comma = "";
+    CborError err;
+    while (!cbor_value_at_end(it)) {
+        char *key;
+        if (fprintf(out, "%s", comma) < 0)
+            return CborErrorIO;
+        comma = ",";
+
+        CborType keyType = cbor_value_get_type(it);
+        if (likely(keyType == CborTextStringType)) {
+            size_t n = 0;
+            err = cbor_value_dup_text_string(it, &key, &n, it);
+        } else if (flags & CborConvertStringifyMapKeys) {
+            err = stringify_map_key(&key, it, flags, keyType);
+        } else {
+            return CborErrorJsonObjectKeyNotString;
+        }
+        if (err)
+            return err;
+
+        /* first, print the key */
+        if (fprintf(out, "\"%s\":", key) < 0)
+            return CborErrorIO;
+
+        /* then, print the value */
+        CborType valueType = cbor_value_get_type(it);
+        err = value_to_json(out, it, flags, valueType, status);
+
+        /* finally, print any metadata we may have */
+        if (flags & CborConvertAddMetadata) {
+            if (!err && keyType != CborTextStringType) {
+                if (fprintf(out, ",\"%s$keycbordump\":true", key) < 0)
+                    err = CborErrorIO;
+            }
+            if (!err && status->flags) {
+                if (fprintf(out, ",\"%s$cbor\":{", key) < 0 ||
+                        add_value_metadata(out, valueType, status) != CborNoError ||
+                        fputc('}', out) < 0)
+                    err = CborErrorIO;
+            }
+        }
+
+        free(key);
+        if (err)
+            return err;
+    }
+    return CborNoError;
+}
+
+static CborError value_to_json(FILE *out, CborValue *it, int flags, CborType type, ConversionStatus *status)
+{
+    CborError err;
+    status->flags = 0;
+
+    switch (type) {
+    case CborArrayType:
+    case CborMapType: {
+        /* recursive type */
+        CborValue recursed;
+        err = cbor_value_enter_container(it, &recursed);
+        if (err) {
+            it->ptr = recursed.ptr;
+            return err;       /* parse error */
+        }
+        if (fputc(type == CborArrayType ? '[' : '{', out) < 0)
+            return CborErrorIO;
+
+        err = (type == CborArrayType) ?
+                  array_to_json(out, &recursed, flags, status) :
+                  map_to_json(out, &recursed, flags, status);
+        if (err) {
+            it->ptr = recursed.ptr;
+            return err;       /* parse error */
+        }
+
+        if (fputc(type == CborArrayType ? ']' : '}', out) < 0)
+            return CborErrorIO;
+        err = cbor_value_leave_container(it, &recursed);
+        if (err)
+            return err;       /* parse error */
+
+        status->flags = 0;    /* reset, there are never conversion errors for us */
+        return CborNoError;
+    }
+
+    case CborIntegerType: {
+        double num;     /* JS numbers are IEEE double precision */
+        uint64_t val;
+        cbor_value_get_raw_integer(it, &val);    /* can't fail */
+        num = (double)val;
+
+        if (cbor_value_is_negative_integer(it)) {
+            num = -num - 1;                     /* convert to negative */
+            if ((uint64_t)(-num - 1) != val) {
+                status->flags = NumberPrecisionWasLost | NumberWasNegative;
+                status->originalNumber = val;
+            }
+        } else {
+            if ((uint64_t)num != val) {
+                status->flags = NumberPrecisionWasLost;
+                status->originalNumber = val;
+            }
+        }
+        if (fprintf(out, "%.0f", num) < 0)  /* this number has no fraction, so no decimal points please */
+            return CborErrorIO;
+        break;
+    }
+
+    case CborByteStringType:
+    case CborTextStringType: {
+        char *str;
+        if (type == CborByteStringType) {
+            err = dump_bytestring_base64url(&str, it);
+            status->flags = TypeWasNotNative;
+        } else {
+            size_t n = 0;
+            err = cbor_value_dup_text_string(it, &str, &n, it);
+        }
+        if (err)
+            return err;
+        err = (fprintf(out, "\"%s\"", str) < 0) ? CborErrorIO : CborNoError;
+        free(str);
+        return err;
+    }
+
+    case CborTagType:
+        return tagged_value_to_json(out, it, flags, status);
+
+    case CborSimpleType: {
+        uint8_t simple_type;
+        cbor_value_get_simple_type(it, &simple_type);  /* can't fail */
+        status->flags = TypeWasNotNative;
+        status->originalNumber = simple_type;
+        if (fprintf(out, "\"simple(%" PRIu8 ")\"", simple_type) < 0)
+            return CborErrorIO;
+        break;
+    }
+
+    case CborNullType:
+        if (fprintf(out, "null") < 0)
+            return CborErrorIO;
+        break;
+
+    case CborUndefinedType:
+        status->flags = TypeWasNotNative;
+        if (fprintf(out, "\"undefined\"") < 0)
+            return CborErrorIO;
+        break;
+
+    case CborBooleanType: {
+        bool val;
+        cbor_value_get_boolean(it, &val);       /* can't fail */
+        if (fprintf(out, val ? "true" : "false") < 0)
+            return CborErrorIO;
+        break;
+    }
+
+    case CborDoubleType: {
+        double val;
+        if (false) {
+            float f;
+    case CborFloatType:
+            status->flags = TypeWasNotNative;
+            cbor_value_get_float(it, &f);
+            val = f;
+        } else if (false) {
+            uint16_t f16;
+    case CborHalfFloatType:
+            status->flags = TypeWasNotNative;
+            cbor_value_get_half_float(it, &f16);
+            val = decode_half(f16);
+        } else {
+            cbor_value_get_double(it, &val);
+        }
+
+        int r = fpclassify(val);
+        if (r == FP_NAN || r == FP_INFINITE) {
+            if (fprintf(out, "null") < 0)
+                return CborErrorIO;
+            status->flags |= r == FP_NAN ? NumberWasNaN :
+                                           NumberWasInfinite | (val < 0 ? NumberWasNegative : 0);
+        } else {
+            uint64_t ival = (uint64_t)fabs(val);
+            if ((double)ival == fabs(val)) {
+                /* print as integer so we get the full precision */
+                r = fprintf(out, "%s%" PRIu64, val < 0 ? "-" : "", ival);
+                status->flags |= TypeWasNotNative;   /* mark this integer number as a double */
+            } else {
+                /* this number is definitely not a 64-bit integer */
+                r = fprintf(out, "%." DBL_DECIMAL_DIG_STR "g", val);
+            }
+            if (r < 0)
+                return CborErrorIO;
+        }
+        break;
+    }
+
+    case CborInvalidType:
+        return CborErrorUnknownType;
+    }
+
+    return cbor_value_advance_fixed(it);
+}
+
+/**
+ * \enum CborToJsonFlags
+ * The CborToJsonFlags enum contains flags that control the conversion of CBOR to JSON.
+ *
+ * \value CborConvertAddMetadata        Adds metadata to facilitate restoration of the original CBOR data.
+ * \value CborConvertTagsToObjects      Converts CBOR tags to JSON objects
+ * \value CborConvertIgnoreTags         (default) Ignore CBOR tags, except for byte strings
+ * \value CborConvertObeyByteStringTags (default) Honor formatting of CBOR byte strings if so tagged
+ * \value CborConvertByteStringsToBase64Url Force the conversion of all CBOR byte strings to Base64url encoding, despite any tags
+ * \value CborConvertRequireMapStringKeys (default) Require CBOR map keys to be strings, failing the conversion if they are not
+ * \value CborConvertStringifyMapKeys   Convert non-string keys in CBOR maps to a string form
+ * \value CborConvertDefaultFlags       Default conversion flags.
+ */
+
+/**
+ * \fn CborError cbor_value_to_json(FILE *out, const CborValue *value, int flags)
+ *
+ * Converts the current CBOR type pointed by \a value to JSON and writes that
+ * to the \a out stream. If an error occurs, this function returns an error
+ * code similar to CborParsing. The \a flags parameter indicates one of the
+ * flags from CborToJsonFlags that control the conversion.
+ *
+ * \sa cbor_value_to_json_advance(), cbor_value_to_pretty()
+ */
+
+/**
+ * Converts the current CBOR type pointed by \a value to JSON and writes that
+ * to the \a out stream. If an error occurs, this function returns an error
+ * code similar to CborParsing. The \a flags parameter indicates one of the
+ * flags from CborToJsonFlags that control the conversion.
+ *
+ * If no error ocurred, this function advances \a value to the next element.
+ *
+ * \sa cbor_value_to_json(), cbor_value_to_pretty_advance()
+ */
+CborError cbor_value_to_json_advance(FILE *out, CborValue *value, int flags)
+{
+    ConversionStatus status;
+    return value_to_json(out, value, flags, cbor_value_get_type(value), &status);
+}
+
+/** @} */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/encoding/tinycbor/src/open_memstream.c
----------------------------------------------------------------------
diff --git a/encoding/tinycbor/src/open_memstream.c b/encoding/tinycbor/src/open_memstream.c
new file mode 100644
index 0000000..eaa53e5
--- /dev/null
+++ b/encoding/tinycbor/src/open_memstream.c
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Intel Corporation
+**
+** Permission is hereby granted, free of charge, to any person obtaining a copy
+** of this software and associated documentation files (the "Software"), to deal
+** in the Software without restriction, including without limitation the rights
+** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+** copies of the Software, and to permit persons to whom the Software is
+** furnished to do so, subject to the following conditions:
+**
+** The above copyright notice and this permission notice shall be included in
+** all copies or substantial portions of the Software.
+**
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+** THE SOFTWARE.
+**
+****************************************************************************/
+
+#define _BSD_SOURCE 1
+#define _DEFAULT_SOURCE 1
+#define _GNU_SOURCE 1
+
+#ifndef WITHOUT_OPEN_MEMSTREAM
+
+#include <sys/types.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined(__unix__) || defined(__APPLE__)
+#  include <unistd.h>
+#endif
+#ifdef __APPLE__
+typedef int RetType;
+typedef int LenType;
+#elif __GLIBC__
+typedef ssize_t RetType;
+typedef size_t LenType;
+#else
+#  error "Cannot implement open_memstream!"
+#endif
+
+#include "compilersupport_p.h"
+
+struct Buffer
+{
+    char **ptr;
+    size_t *len;
+    size_t alloc;
+};
+
+static RetType write_to_buffer(void *cookie, const char *data, LenType len)
+{
+    struct Buffer *b = (struct Buffer *)cookie;
+    char *ptr = *b->ptr;
+    size_t newsize;
+
+    errno = EFBIG;
+    if (unlikely(add_check_overflow(*b->len, len, &newsize)))
+        return -1;
+
+    if (newsize > b->alloc) {
+        // make room
+        size_t newalloc = newsize + newsize / 2 + 1;    // give 50% more room
+        ptr = realloc(ptr, newalloc);
+        if (ptr == NULL)
+            return -1;
+        b->alloc = newalloc;
+        *b->ptr = ptr;
+    }
+
+    memcpy(ptr + *b->len, data, len);
+    *b->len = newsize;
+    return len;
+}
+
+static int close_buffer(void *cookie)
+{
+    struct Buffer *b = (struct Buffer *)cookie;
+    if (*b->ptr)
+        (*b->ptr)[*b->len] = '\0';
+    free(b);
+    return 0;
+}
+
+FILE *open_memstream(char **bufptr, size_t *lenptr)
+{
+    struct Buffer *b = (struct Buffer *)malloc(sizeof(struct Buffer));
+    if (b == NULL)
+        return NULL;
+    b->alloc = 0;
+    b->len = lenptr;
+    b->ptr = bufptr;
+    *bufptr = NULL;
+    *lenptr = 0;
+
+#ifdef __APPLE__
+    return funopen(b, NULL, write_to_buffer, NULL, close_buffer);
+#elif __GLIBC__
+    static const cookie_io_functions_t vtable = {
+        NULL,
+        write_to_buffer,
+        NULL,
+        close_buffer
+    };
+    return fopencookie(b, "w", vtable);
+#endif
+}
+
+#endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/fs/fcb/README.md
----------------------------------------------------------------------
diff --git a/fs/fcb/README.md b/fs/fcb/README.md
new file mode 100644
index 0000000..5d13ccd
--- /dev/null
+++ b/fs/fcb/README.md
@@ -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.
+#
+-->
+
+# Flash circular buffer
+
+# Overview
+
+Storage of elements in flash in FIFO fashion. Elements are appended to the of the area until storage space is exhausted. Then the oldest sector should be erased and that can be used in storing new entries.
+
+# API
+
+fcb_init()
+  - initialize fcb for a given array of flash sectors
+
+fcb_append()
+  - reserve space to store an element
+fcb_append_finish()
+  - storage of the element is finished; can calculate CRC for it
+
+fcb_walk(cb, sector)
+  - call cb for every element in the buffer. Or for every element in
+    a particular flash sector, if sector is specified
+fcb_getnext(elem)
+  - return element following elem
+
+fcb_rotate()
+  - erase oldest used sector, and make it current
+
+# Usage
+
+To add an element to circular buffer:
+1. call fcb_append() to get location; if this fails due to lack of space,
+   call fcb_rotate()
+2. use flash_area_write() to write contents
+3. call fcb_append_finish() when done
+
+To read contents of the circular buffer:
+1. call fcb_walk() with callback
+2. within callback: copy in data from the element using flash_area_read(),
+   call fcb_rotate() when all elements from a given sector have been read

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/fs/fcb/include/fcb/fcb.h
----------------------------------------------------------------------
diff --git a/fs/fcb/include/fcb/fcb.h b/fs/fcb/include/fcb/fcb.h
new file mode 100644
index 0000000..a6b3f88
--- /dev/null
+++ b/fs/fcb/include/fcb/fcb.h
@@ -0,0 +1,134 @@
+/**
+ * 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 __SYS_FCB_H_
+#define __SYS_FCB_H_
+
+/*
+ * Flash circular buffer.
+ */
+#include <inttypes.h>
+#include <limits.h>
+
+#include <hal/flash_map.h>
+
+#include <os/os_mutex.h>
+
+#define FCB_MAX_LEN	(CHAR_MAX | CHAR_MAX << 7) /* Max length of element */
+
+/*
+ * Entry location is pointer to area (within fcb->f_sectors), and offset
+ * within that area.
+ */
+struct fcb_entry {
+    struct flash_area *fe_area;	/* ptr to area within fcb->f_sectors */
+    uint32_t fe_elem_off;	/* start of entry */
+    uint32_t fe_data_off;	/* start of data */
+    uint16_t fe_data_len;	/* size of data area */
+};
+
+struct fcb {
+    /* Caller of fcb_init fills this in */
+    uint32_t f_magic;		/* As placed on the disk */
+    uint8_t f_version;  	/* Current version number of the data */
+    uint8_t f_sector_cnt;	/* Number of elements in sector array */
+    uint8_t f_scratch_cnt;	/* How many sectors should be kept empty */
+    struct flash_area *f_sectors; /* Array of sectors, must be contiguous */
+
+    /* Flash circular buffer internal state */
+    struct os_mutex f_mtx;	/* Locking for accessing the FCB data */
+    struct flash_area *f_oldest;
+    struct fcb_entry f_active;
+    uint16_t f_active_id;
+    uint8_t f_align;		/* writes to flash have to aligned to this */
+};
+
+/*
+ * Error codes.
+ */
+#define FCB_OK		0
+#define FCB_ERR_ARGS	-1
+#define FCB_ERR_FLASH	-2
+#define FCB_ERR_NOVAR   -3
+#define FCB_ERR_NOSPACE	-4
+#define FCB_ERR_NOMEM	-5
+#define FCB_ERR_CRC	-6
+#define FCB_ERR_MAGIC   -7
+
+int fcb_init(struct fcb *fcb);
+
+/*
+ * fcb_log is needed as the number of entries in a log
+ */
+struct fcb_log {
+    struct fcb fl_fcb;
+    uint8_t fl_entries;
+};
+
+int log_fcb_init(struct fcb_log *fcblog, struct fcb *fcb, uint16_t entries);
+
+/*
+ * fcb_append() appends an entry to circular buffer. When writing the
+ * contents for the entry, use loc->fl_area and loc->fl_data_off with
+ * flash_area_write(). When you're finished, call fcb_append_finish() with
+ * loc as argument.
+ */
+int fcb_append(struct fcb *, uint16_t len, struct fcb_entry *loc);
+int fcb_append_finish(struct fcb *, struct fcb_entry *append_loc);
+
+/*
+ * Walk over all log entries in FCB, or entries in a given flash_area.
+ * cb gets called for every entry. If cb wants to stop the walk, it should
+ * return non-zero value.
+ *
+ * Entry data can be read using flash_area_read(), using
+ * loc->fe_area, loc->fe_data_off, and loc->fe_data_len as arguments.
+ */
+typedef int (*fcb_walk_cb)(struct fcb_entry *loc, void *arg);
+int fcb_walk(struct fcb *, struct flash_area *, fcb_walk_cb cb, void *cb_arg);
+int fcb_getnext(struct fcb *, struct fcb_entry *loc);
+
+/*
+ * Erases the data from oldest sector.
+ */
+int fcb_rotate(struct fcb *);
+
+/*
+ * Start using the scratch block.
+ */
+int fcb_append_to_scratch(struct fcb *);
+
+/*
+ * How many sectors are unused.
+ */
+int fcb_free_sector_cnt(struct fcb *fcb);
+
+/*
+ * Whether FCB has any data.
+ */
+int fcb_is_empty(struct fcb *fcb);
+
+int
+fcb_offset_last_n(struct fcb *fcb, uint8_t entries, uint32_t *last_n_off);
+
+/*
+ * Clears FCB passed to it
+ */
+int fcb_clear(struct fcb *fcb);
+
+#endif /* __SYS_FLASHVAR_H_ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/fs/fcb/pkg.yml
----------------------------------------------------------------------
diff --git a/fs/fcb/pkg.yml b/fs/fcb/pkg.yml
new file mode 100644
index 0000000..9b90bb9
--- /dev/null
+++ b/fs/fcb/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: fs/fcb
+pkg.description: Flash circular buffer.
+pkg.keywords:
+    - flash
+    - storage
+    - log
+
+pkg.deps:
+    - kernel/os
+    - encoding/crc

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/fs/fcb/src/fcb.c
----------------------------------------------------------------------
diff --git a/fs/fcb/src/fcb.c b/fs/fcb/src/fcb.c
new file mode 100644
index 0000000..fb85508
--- /dev/null
+++ b/fs/fcb/src/fcb.c
@@ -0,0 +1,258 @@
+/**
+ * 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 <limits.h>
+#include <stdlib.h>
+
+#include "fcb/fcb.h"
+#include "fcb_priv.h"
+#include "string.h"
+
+int
+fcb_init(struct fcb *fcb)
+{
+    struct flash_area *fap;
+    int rc;
+    int i;
+    int max_align = 1;
+    int align;
+    int oldest = -1, newest = -1;
+    struct flash_area *oldest_fap = NULL, *newest_fap = NULL;
+    struct fcb_disk_area fda;
+
+    if (!fcb->f_sectors || fcb->f_sector_cnt - fcb->f_scratch_cnt < 1) {
+        return FCB_ERR_ARGS;
+    }
+
+    /* Fill last used, first used */
+    for (i = 0; i < fcb->f_sector_cnt; i++) {
+        fap = &fcb->f_sectors[i];
+        align = flash_area_align(fap);
+        if (align > max_align) {
+            max_align = flash_area_align(fap);
+        }
+        rc = fcb_sector_hdr_read(fcb, fap, &fda);
+        if (rc <= 0) {
+            continue;
+        }
+        if (oldest < 0) {
+            oldest = newest = fda.fd_id;
+            oldest_fap = newest_fap = fap;
+            continue;
+        }
+        if (FCB_ID_GT(fda.fd_id, newest)) {
+            newest = fda.fd_id;
+            newest_fap = fap;
+        } else if (FCB_ID_GT(oldest, fda.fd_id)) {
+            oldest = fda.fd_id;
+            oldest_fap = fap;
+        }
+    }
+    if (oldest < 0) {
+        /*
+         * No initialized areas.
+         */
+        oldest_fap = newest_fap = &fcb->f_sectors[0];
+        rc = fcb_sector_hdr_init(fcb, oldest_fap, 0);
+        if (rc) {
+            return rc;
+        }
+        newest = oldest = 0;
+    }
+    fcb->f_align = max_align;
+    fcb->f_oldest = oldest_fap;
+    fcb->f_active.fe_area = newest_fap;
+    fcb->f_active.fe_elem_off = sizeof(struct fcb_disk_area);
+    fcb->f_active_id = newest;
+
+    while (1) {
+        rc = fcb_getnext_in_area(fcb, &fcb->f_active);
+        if (rc == FCB_ERR_NOVAR) {
+            rc = FCB_OK;
+            break;
+        }
+        if (rc != 0) {
+            break;
+        }
+    }
+    os_mutex_init(&fcb->f_mtx);
+    return rc;
+}
+
+int
+fcb_free_sector_cnt(struct fcb *fcb)
+{
+    int i;
+    struct flash_area *fa;
+
+    fa = fcb->f_active.fe_area;
+    for (i = 0; i < fcb->f_sector_cnt; i++) {
+        fa = fcb_getnext_area(fcb, fa);
+        if (fa == fcb->f_oldest) {
+            break;
+        }
+    }
+    return i;
+}
+
+int
+fcb_is_empty(struct fcb *fcb)
+{
+    return (fcb->f_active.fe_area == fcb->f_oldest &&
+      fcb->f_active.fe_elem_off == sizeof(struct fcb_disk_area));
+}
+
+/**
+ * Length of an element is encoded in 1 or 2 bytes.
+ * 1 byte for lengths < 128 bytes, and 2 bytes for < 16384.
+ */
+int
+fcb_put_len(uint8_t *buf, uint16_t len)
+{
+    if (len < CHAR_MAX) {
+        buf[0] = len;
+        return 1;
+    } else if (len < FCB_MAX_LEN) {
+        buf[0] = (len & 0x7f) | 0x80;
+        buf[1] = len >> 7;
+        return 2;
+    } else {
+        return FCB_ERR_ARGS;
+    }
+}
+
+int
+fcb_get_len(uint8_t *buf, uint16_t *len)
+{
+    int rc;
+
+    if (buf[0] & 0x80) {
+        if (buf[0] == 0xff && buf[1] == 0xff) {
+            return FCB_ERR_NOVAR;
+        }
+        *len = (buf[0] & 0x7f) | (buf[1] << 7);
+        rc = 2;
+    } else {
+        *len = buf[0];
+        rc = 1;
+    }
+    return rc;
+}
+
+/**
+ * Initialize erased sector for use.
+ */
+int
+fcb_sector_hdr_init(struct fcb *fcb, struct flash_area *fap, uint16_t id)
+{
+    struct fcb_disk_area fda;
+    int rc;
+
+    fda.fd_magic = fcb->f_magic;
+    fda.fd_ver = fcb->f_version;
+    fda._pad = 0xff;
+    fda.fd_id = id;
+
+    rc = flash_area_write(fap, 0, &fda, sizeof(fda));
+    if (rc) {
+        return FCB_ERR_FLASH;
+    }
+    return 0;
+}
+
+/**
+ * Checks whether FCB sector contains data or not.
+ * Returns <0 in error.
+ * Returns 0 if sector is unused;
+ * Returns 1 if sector has data.
+ */
+int
+fcb_sector_hdr_read(struct fcb *fcb, struct flash_area *fap,
+  struct fcb_disk_area *fdap)
+{
+    struct fcb_disk_area fda;
+    int rc;
+
+    if (!fdap) {
+        fdap = &fda;
+    }
+    rc = flash_area_read(fap, 0, fdap, sizeof(*fdap));
+    if (rc) {
+        return FCB_ERR_FLASH;
+    }
+    if (fdap->fd_magic == 0xffffffff) {
+        return 0;
+    }
+    if (fdap->fd_magic != fcb->f_magic) {
+        return FCB_ERR_MAGIC;
+    }
+    return 1;
+}
+
+/**
+ * Finds n-th element offset
+ * @param0 ptr to fcb
+ * @param1 n number of entries to calculate offset before
+ * @param2 ptr to the offset before to be returned
+ * @return 0 on success; non-zero on failure
+ */
+int
+fcb_offset_last_n(struct fcb *fcb, uint8_t entries, uint32_t *last_n_off)
+{
+    struct fcb_entry loc;
+    struct fcb_entry start;
+    int i;
+
+    i = 0;
+    memset(&loc, 0, sizeof(loc));
+    while (!fcb_getnext(fcb, &loc)) {
+        if (i == 0) {
+            /* Start from the beginning of fcb entries */
+            *last_n_off = loc.fe_elem_off;
+            start = loc;
+        }
+        /* Update last_n_off after n entries and keep updating */
+        if (i >= (entries - 1)) {
+            fcb_getnext(fcb, &start);
+            *last_n_off = start.fe_elem_off;
+        }
+        i++;
+    }
+
+    return 0;
+}
+
+/**
+ * Clear fcb
+ * @param fcb
+ * @return 0 on success; non-zero on failure
+ */
+int
+fcb_clear(struct fcb *fcb)
+{
+    int rc;
+
+    rc = 0;
+    while (!fcb_is_empty(fcb)) {
+        rc = fcb_rotate(fcb);
+        if (rc) {
+            break;
+        }
+    }
+    return rc;
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/fs/fcb/src/fcb_append.c
----------------------------------------------------------------------
diff --git a/fs/fcb/src/fcb_append.c b/fs/fcb/src/fcb_append.c
new file mode 100644
index 0000000..c7f5ddc
--- /dev/null
+++ b/fs/fcb/src/fcb_append.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 <stddef.h>
+
+#include "fcb/fcb.h"
+#include "fcb_priv.h"
+
+static struct flash_area *
+fcb_new_area(struct fcb *fcb, int cnt)
+{
+    struct flash_area *fa;
+    struct flash_area *rfa;
+    int i;
+
+    rfa = NULL;
+    i = 0;
+    fa = fcb->f_active.fe_area;
+    do {
+        fa = fcb_getnext_area(fcb, fa);
+        if (!rfa) {
+            rfa = fa;
+        }
+        if (fa == fcb->f_oldest) {
+            return NULL;
+        }
+    } while (i++ < cnt);
+    return rfa;
+}
+
+/*
+ * Take one of the scratch blocks into use, if at all possible.
+ */
+int
+fcb_append_to_scratch(struct fcb *fcb)
+{
+    struct flash_area *fa;
+    int rc;
+
+    fa = fcb_new_area(fcb, 0);
+    if (!fa) {
+        return FCB_ERR_NOSPACE;
+    }
+    rc = fcb_sector_hdr_init(fcb, fa, fcb->f_active_id + 1);
+    if (rc) {
+        return rc;
+    }
+    fcb->f_active.fe_area = fa;
+    fcb->f_active.fe_elem_off = sizeof(struct fcb_disk_area);
+    fcb->f_active_id++;
+    return FCB_OK;
+}
+
+int
+fcb_append(struct fcb *fcb, uint16_t len, struct fcb_entry *append_loc)
+{
+    struct fcb_entry *active;
+    struct flash_area *fa;
+    uint8_t tmp_str[2];
+    int cnt;
+    int rc;
+
+    cnt = fcb_put_len(tmp_str, len);
+    if (cnt < 0) {
+        return cnt;
+    }
+    cnt = fcb_len_in_flash(fcb, cnt);
+    len = fcb_len_in_flash(fcb, len) + fcb_len_in_flash(fcb, FCB_CRC_SZ);
+
+    rc = os_mutex_pend(&fcb->f_mtx, OS_WAIT_FOREVER);
+    if (rc && rc != OS_NOT_STARTED) {
+        return FCB_ERR_ARGS;
+    }
+    active = &fcb->f_active;
+    if (active->fe_elem_off + len + cnt > active->fe_area->fa_size) {
+        fa = fcb_new_area(fcb, fcb->f_scratch_cnt);
+        if (!fa || (fa->fa_size <
+            sizeof(struct fcb_disk_area) + len + cnt)) {
+            rc = FCB_ERR_NOSPACE;
+            goto err;
+        }
+        rc = fcb_sector_hdr_init(fcb, fa, fcb->f_active_id + 1);
+        if (rc) {
+            goto err;
+        }
+        fcb->f_active.fe_area = fa;
+        fcb->f_active.fe_elem_off = sizeof(struct fcb_disk_area);
+        fcb->f_active_id++;
+    }
+
+    rc = flash_area_write(active->fe_area, active->fe_elem_off, tmp_str, cnt);
+    if (rc) {
+        rc = FCB_ERR_FLASH;
+        goto err;
+    }
+    append_loc->fe_area = active->fe_area;
+    append_loc->fe_elem_off = active->fe_elem_off;
+    append_loc->fe_data_off = active->fe_elem_off + cnt;
+
+    active->fe_elem_off = append_loc->fe_data_off + len;
+
+    os_mutex_release(&fcb->f_mtx);
+
+    return FCB_OK;
+err:
+    os_mutex_release(&fcb->f_mtx);
+    return rc;
+}
+
+int
+fcb_append_finish(struct fcb *fcb, struct fcb_entry *loc)
+{
+    int rc;
+    uint8_t crc8;
+    uint32_t off;
+
+    rc = fcb_elem_crc8(fcb, loc, &crc8);
+    if (rc) {
+        return rc;
+    }
+    off = loc->fe_data_off + fcb_len_in_flash(fcb, loc->fe_data_len);
+
+    rc = flash_area_write(loc->fe_area, off, &crc8, sizeof(crc8));
+    if (rc) {
+        return FCB_ERR_FLASH;
+    }
+    return 0;
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/fs/fcb/src/fcb_elem_info.c
----------------------------------------------------------------------
diff --git a/fs/fcb/src/fcb_elem_info.c b/fs/fcb/src/fcb_elem_info.c
new file mode 100644
index 0000000..7e088ea
--- /dev/null
+++ b/fs/fcb/src/fcb_elem_info.c
@@ -0,0 +1,101 @@
+/**
+ * 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 <crc/crc8.h>
+
+#include "fcb/fcb.h"
+#include "fcb_priv.h"
+
+/*
+ * Given offset in flash area, fill in rest of the fcb_entry, and crc8 over
+ * the data.
+ */
+int
+fcb_elem_crc8(struct fcb *fcb, struct fcb_entry *loc, uint8_t *c8p)
+{
+    uint8_t tmp_str[FCB_TMP_BUF_SZ];
+    int cnt;
+    int blk_sz;
+    uint8_t crc8;
+    uint16_t len;
+    uint32_t off;
+    uint32_t end;
+    int rc;
+
+    if (loc->fe_elem_off + 2 > loc->fe_area->fa_size) {
+        return FCB_ERR_NOVAR;
+    }
+    rc = flash_area_read(loc->fe_area, loc->fe_elem_off, tmp_str, 2);
+    if (rc) {
+        return FCB_ERR_FLASH;
+    }
+
+    cnt = fcb_get_len(tmp_str, &len);
+    if (cnt < 0) {
+        return cnt;
+    }
+    loc->fe_data_off = loc->fe_elem_off + fcb_len_in_flash(fcb, cnt);
+    loc->fe_data_len = len;
+
+    crc8 = crc8_init();
+    crc8 = crc8_calc(crc8, tmp_str, cnt);
+
+    off = loc->fe_data_off;
+    end = loc->fe_data_off + len;
+    for (; off < end; off += blk_sz) {
+        blk_sz = end - off;
+        if (blk_sz > sizeof(tmp_str)) {
+            blk_sz = sizeof(tmp_str);
+        }
+
+        rc = flash_area_read(loc->fe_area, off, tmp_str, blk_sz);
+        if (rc) {
+            return FCB_ERR_FLASH;
+        }
+        crc8 = crc8_calc(crc8, tmp_str, blk_sz);
+    }
+    *c8p = crc8;
+
+    return 0;
+}
+
+int
+fcb_elem_info(struct fcb *fcb, struct fcb_entry *loc)
+{
+    int rc;
+    uint8_t crc8;
+    uint8_t fl_crc8;
+    uint32_t off;
+
+    rc = fcb_elem_crc8(fcb, loc, &crc8);
+    if (rc) {
+        return rc;
+    }
+    off = loc->fe_data_off + fcb_len_in_flash(fcb, loc->fe_data_len);
+
+    rc = flash_area_read(loc->fe_area, off, &fl_crc8, sizeof(fl_crc8));
+    if (rc) {
+        return FCB_ERR_FLASH;
+    }
+
+    if (fl_crc8 != crc8) {
+        return FCB_ERR_CRC;
+    }
+    return 0;
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/fs/fcb/src/fcb_getnext.c
----------------------------------------------------------------------
diff --git a/fs/fcb/src/fcb_getnext.c b/fs/fcb/src/fcb_getnext.c
new file mode 100644
index 0000000..be92979
--- /dev/null
+++ b/fs/fcb/src/fcb_getnext.c
@@ -0,0 +1,132 @@
+/**
+ * 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 <stddef.h>
+
+#include "fcb/fcb.h"
+#include "fcb_priv.h"
+
+int
+fcb_getnext_in_area(struct fcb *fcb, struct fcb_entry *loc)
+{
+    int rc;
+
+    rc = fcb_elem_info(fcb, loc);
+    if (rc == 0 || rc == FCB_ERR_CRC) {
+        do {
+            loc->fe_elem_off = loc->fe_data_off +
+              fcb_len_in_flash(fcb, loc->fe_data_len) +
+              fcb_len_in_flash(fcb, FCB_CRC_SZ);
+            rc = fcb_elem_info(fcb, loc);
+            if (rc != FCB_ERR_CRC) {
+                break;
+            }
+        } while (rc == FCB_ERR_CRC);
+    }
+    return rc;
+}
+
+struct flash_area *
+fcb_getnext_area(struct fcb *fcb, struct flash_area *fap)
+{
+    fap++;
+    if (fap >= &fcb->f_sectors[fcb->f_sector_cnt]) {
+        fap = &fcb->f_sectors[0];
+    }
+    return fap;
+}
+
+int
+fcb_getnext_nolock(struct fcb *fcb, struct fcb_entry *loc)
+{
+    int rc;
+
+    if (loc->fe_area == NULL) {
+        /*
+         * Find the first one we have in flash.
+         */
+        loc->fe_area = fcb->f_oldest;
+    }
+    if (loc->fe_elem_off == 0) {
+        /*
+         * If offset is zero, we serve the first entry from the area.
+         */
+        loc->fe_elem_off = sizeof(struct fcb_disk_area);
+        rc = fcb_elem_info(fcb, loc);
+        switch (rc) {
+        case 0:
+            return 0;
+        case FCB_ERR_CRC:
+            break;
+        default:
+            goto next_sector;
+        }
+    } else {
+        rc = fcb_getnext_in_area(fcb, loc);
+        if (rc == 0) {
+            return 0;
+        }
+        if (rc == FCB_ERR_NOVAR) {
+            goto next_sector;
+        }
+    }
+    while (rc == FCB_ERR_CRC) {
+        rc = fcb_getnext_in_area(fcb, loc);
+        if (rc == 0) {
+            return 0;
+        }
+
+        if (rc != FCB_ERR_CRC) {
+            /*
+             * Moving to next sector.
+             */
+next_sector:
+            if (loc->fe_area == fcb->f_active.fe_area) {
+                return FCB_ERR_NOVAR;
+            }
+            loc->fe_area = fcb_getnext_area(fcb, loc->fe_area);
+            loc->fe_elem_off = sizeof(struct fcb_disk_area);
+            rc = fcb_elem_info(fcb, loc);
+            switch (rc) {
+            case 0:
+                return 0;
+            case FCB_ERR_CRC:
+                break;
+            default:
+                goto next_sector;
+            }
+        }
+    }
+
+    return 0;
+}
+
+int
+fcb_getnext(struct fcb *fcb, struct fcb_entry *loc)
+{
+    int rc;
+
+    rc = os_mutex_pend(&fcb->f_mtx, OS_WAIT_FOREVER);
+    if (rc && rc != OS_NOT_STARTED) {
+        return FCB_ERR_ARGS;
+    }
+    rc = fcb_getnext_nolock(fcb, loc);
+    os_mutex_release(&fcb->f_mtx);
+
+    return rc;
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/fs/fcb/src/fcb_priv.h
----------------------------------------------------------------------
diff --git a/fs/fcb/src/fcb_priv.h b/fs/fcb/src/fcb_priv.h
new file mode 100644
index 0000000..b7a9e0b
--- /dev/null
+++ b/fs/fcb/src/fcb_priv.h
@@ -0,0 +1,57 @@
+/**
+ * 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 __SYS_FCB_PRIV_H_
+#define __SYS_FCB_PRIV_H_
+
+#define FCB_CRC_SZ	sizeof(uint8_t)
+#define FCB_TMP_BUF_SZ	32
+
+#define FCB_ID_GT(a, b) (((int16_t)(a) - (int16_t)(b)) > 0)
+
+struct fcb_disk_area {
+    uint32_t fd_magic;
+    uint8_t  fd_ver;
+    uint8_t  _pad;
+    uint16_t fd_id;
+};
+
+int fcb_put_len(uint8_t *buf, uint16_t len);
+int fcb_get_len(uint8_t *buf, uint16_t *len);
+
+static inline int
+fcb_len_in_flash(struct fcb *fcb, uint16_t len)
+{
+    if (fcb->f_align <= 1) {
+        return len;
+    }
+    return (len + (fcb->f_align - 1)) & ~(fcb->f_align - 1);
+}
+
+int fcb_getnext_in_area(struct fcb *fcb, struct fcb_entry *loc);
+struct flash_area *fcb_getnext_area(struct fcb *fcb, struct flash_area *fap);
+int fcb_getnext_nolock(struct fcb *fcb, struct fcb_entry *loc);
+
+int fcb_elem_info(struct fcb *, struct fcb_entry *);
+int fcb_elem_crc8(struct fcb *, struct fcb_entry *loc, uint8_t *crc8p);
+
+int fcb_sector_hdr_init(struct fcb *, struct flash_area *fap, uint16_t id);
+int fcb_sector_hdr_read(struct fcb *, struct flash_area *fap,
+  struct fcb_disk_area *fdap);
+
+#endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/fs/fcb/src/fcb_rotate.c
----------------------------------------------------------------------
diff --git a/fs/fcb/src/fcb_rotate.c b/fs/fcb/src/fcb_rotate.c
new file mode 100644
index 0000000..7b6df58
--- /dev/null
+++ b/fs/fcb/src/fcb_rotate.c
@@ -0,0 +1,56 @@
+/**
+ * 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 "fcb/fcb.h"
+#include "fcb_priv.h"
+
+int
+fcb_rotate(struct fcb *fcb)
+{
+    struct flash_area *fap;
+    int rc = 0;
+
+    rc = os_mutex_pend(&fcb->f_mtx, OS_WAIT_FOREVER);
+    if (rc && rc != OS_NOT_STARTED) {
+        return FCB_ERR_ARGS;
+    }
+
+    rc = flash_area_erase(fcb->f_oldest, 0, fcb->f_oldest->fa_size);
+    if (rc) {
+        rc = FCB_ERR_FLASH;
+        goto out;
+    }
+    if (fcb->f_oldest == fcb->f_active.fe_area) {
+        /*
+         * Need to create a new active area, as we're wiping the current.
+         */
+        fap = fcb_getnext_area(fcb, fcb->f_oldest);
+        rc = fcb_sector_hdr_init(fcb, fap, fcb->f_active_id + 1);
+        if (rc) {
+            goto out;
+        }
+        fcb->f_active.fe_area = fap;
+        fcb->f_active.fe_elem_off = sizeof(struct fcb_disk_area);
+        fcb->f_active_id++;
+    }
+    fcb->f_oldest = fcb_getnext_area(fcb, fcb->f_oldest);
+out:
+    os_mutex_release(&fcb->f_mtx);
+    return rc;
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/fs/fcb/src/fcb_walk.c
----------------------------------------------------------------------
diff --git a/fs/fcb/src/fcb_walk.c b/fs/fcb/src/fcb_walk.c
new file mode 100644
index 0000000..e557262
--- /dev/null
+++ b/fs/fcb/src/fcb_walk.c
@@ -0,0 +1,53 @@
+/**
+ * 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 "fcb/fcb.h"
+#include "fcb_priv.h"
+
+/*
+ * Call 'cb' for every element in flash circular buffer. If fap is specified,
+ * only elements with that flash_area are reported.
+ */
+int
+fcb_walk(struct fcb *fcb, struct flash_area *fap, fcb_walk_cb cb, void *cb_arg)
+{
+    struct fcb_entry loc;
+    int rc;
+
+    loc.fe_area = fap;
+    loc.fe_elem_off = 0;
+
+    rc = os_mutex_pend(&fcb->f_mtx, OS_WAIT_FOREVER);
+    if (rc && rc != OS_NOT_STARTED) {
+        return FCB_ERR_ARGS;
+    }
+    while ((rc = fcb_getnext_nolock(fcb, &loc)) != FCB_ERR_NOVAR) {
+        os_mutex_release(&fcb->f_mtx);
+        if (fap && loc.fe_area != fap) {
+            return 0;
+        }
+        rc = cb(&loc, cb_arg);
+        if (rc) {
+            return rc;
+        }
+        os_mutex_pend(&fcb->f_mtx, OS_WAIT_FOREVER);
+    }
+    os_mutex_release(&fcb->f_mtx);
+    return 0;
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/fs/fcb/test/pkg.yml
----------------------------------------------------------------------
diff --git a/fs/fcb/test/pkg.yml b/fs/fcb/test/pkg.yml
new file mode 100644
index 0000000..920cfa3
--- /dev/null
+++ b/fs/fcb/test/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: fs/fcb/test
+pkg.type: unittest
+pkg.description: "FCB unit tests."
+pkg.author: "Apache Mynewt <de...@mynewt.incubator.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps: 
+    - test/testutil
+    - fs/fcb
+
+pkg.deps.SELFTEST:
+    - sys/console/stub

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/fs/fcb/test/src/fcb_test.c
----------------------------------------------------------------------
diff --git a/fs/fcb/test/src/fcb_test.c b/fs/fcb/test/src/fcb_test.c
new file mode 100644
index 0000000..b172eb0
--- /dev/null
+++ b/fs/fcb/test/src/fcb_test.c
@@ -0,0 +1,672 @@
+/**
+ * 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 <stdio.h>
+#include <string.h>
+
+#include "syscfg/syscfg.h"
+#include "os/os.h"
+#include "testutil/testutil.h"
+
+#include "fcb/fcb.h"
+#include "fcb/../../src/fcb_priv.h"
+
+static struct fcb test_fcb;
+
+static struct flash_area test_fcb_area[] = {
+    [0] = {
+        .fa_flash_id = 0,
+        .fa_off = 0,
+        .fa_size = 0x4000, /* 16K */
+    },
+    [1] = {
+        .fa_flash_id = 0,
+        .fa_off = 0x4000,
+        .fa_size = 0x4000
+    },
+    [2] = {
+        .fa_flash_id = 0,
+        .fa_off = 0x8000,
+        .fa_size = 0x4000
+    },
+    [3] = {
+        .fa_flash_id = 0,
+        .fa_off = 0xc000,
+        .fa_size = 0x4000
+    }
+};
+
+static void
+fcb_test_wipe(void)
+{
+    int i;
+    int rc;
+    struct flash_area *fap;
+
+    for (i = 0; i < sizeof(test_fcb_area) / sizeof(test_fcb_area[0]); i++) {
+        fap = &test_fcb_area[i];
+        rc = flash_area_erase(fap, 0, fap->fa_size);
+        TEST_ASSERT(rc == 0);
+    }
+}
+
+TEST_CASE(fcb_test_len)
+{
+    uint8_t buf[3];
+    uint16_t len;
+    uint16_t len2;
+    int rc;
+
+    for (len = 0; len < FCB_MAX_LEN; len++) {
+        rc = fcb_put_len(buf, len);
+        TEST_ASSERT(rc == 1 || rc == 2);
+
+        rc = fcb_get_len(buf, &len2);
+        TEST_ASSERT(rc == 1 || rc == 2);
+
+        TEST_ASSERT(len == len2);
+    }
+}
+
+TEST_CASE(fcb_test_init)
+{
+    int rc;
+    struct fcb *fcb;
+
+    fcb = &test_fcb;
+    memset(fcb, 0, sizeof(*fcb));
+
+    rc = fcb_init(fcb);
+    TEST_ASSERT(rc == FCB_ERR_ARGS);
+
+    fcb->f_sectors = test_fcb_area;
+
+    rc = fcb_init(fcb);
+    TEST_ASSERT(rc == FCB_ERR_ARGS);
+
+    fcb->f_sector_cnt = 2;
+    rc = fcb_init(fcb);
+    TEST_ASSERT(rc == 0);
+}
+
+static int
+fcb_test_empty_walk_cb(struct fcb_entry *loc, void *arg)
+{
+    TEST_ASSERT(0);
+    return 0;
+}
+
+TEST_CASE(fcb_test_empty_walk)
+{
+    int rc;
+    struct fcb *fcb;
+
+    fcb_test_wipe();
+    fcb = &test_fcb;
+    memset(fcb, 0, sizeof(*fcb));
+
+    fcb->f_sector_cnt = 2;
+    fcb->f_sectors = test_fcb_area;
+
+    rc = fcb_init(fcb);
+    TEST_ASSERT(rc == 0);
+
+    rc = fcb_walk(fcb, 0, fcb_test_empty_walk_cb, NULL);
+    TEST_ASSERT(rc == 0);
+}
+
+static uint8_t
+fcb_test_append_data(int msg_len, int off)
+{
+    return (msg_len ^ off);
+}
+
+static int
+fcb_test_data_walk_cb(struct fcb_entry *loc, void *arg)
+{
+    uint16_t len;
+    uint8_t test_data[128];
+    int rc;
+    int i;
+    int *var_cnt = (int *)arg;
+
+    len = loc->fe_data_len;
+
+    TEST_ASSERT(len == *var_cnt);
+
+    rc = flash_area_read(loc->fe_area, loc->fe_data_off, test_data, len);
+    TEST_ASSERT(rc == 0);
+
+    for (i = 0; i < len; i++) {
+        TEST_ASSERT(test_data[i] == fcb_test_append_data(len, i));
+    }
+    (*var_cnt)++;
+    return 0;
+}
+
+TEST_CASE(fcb_test_append)
+{
+    int rc;
+    struct fcb *fcb;
+    struct fcb_entry loc;
+    uint8_t test_data[128];
+    int i;
+    int j;
+    int var_cnt;
+
+    fcb_test_wipe();
+    fcb = &test_fcb;
+    memset(fcb, 0, sizeof(*fcb));
+    fcb->f_sector_cnt = 2;
+    fcb->f_sectors = test_fcb_area;
+
+    rc = fcb_init(fcb);
+    TEST_ASSERT(rc == 0);
+
+    for (i = 0; i < sizeof(test_data); i++) {
+        for (j = 0; j < i; j++) {
+            test_data[j] = fcb_test_append_data(i, j);
+        }
+        rc = fcb_append(fcb, i, &loc);
+        TEST_ASSERT_FATAL(rc == 0);
+        rc = flash_area_write(loc.fe_area, loc.fe_data_off, test_data, i);
+        TEST_ASSERT(rc == 0);
+        rc = fcb_append_finish(fcb, &loc);
+        TEST_ASSERT(rc == 0);
+    }
+
+    var_cnt = 0;
+    rc = fcb_walk(fcb, 0, fcb_test_data_walk_cb, &var_cnt);
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(var_cnt == sizeof(test_data));
+}
+
+TEST_CASE(fcb_test_append_too_big)
+{
+    struct fcb *fcb;
+    int rc;
+    int len;
+    struct fcb_entry elem_loc;
+
+    fcb_test_wipe();
+    fcb = &test_fcb;
+    memset(fcb, 0, sizeof(*fcb));
+    fcb->f_sector_cnt = 2;
+    fcb->f_sectors = test_fcb_area;
+
+    rc = fcb_init(fcb);
+    TEST_ASSERT(rc == 0);
+
+    /*
+     * Max element which fits inside sector is
+     * sector size - (disk header + crc + 1-2 bytes of length).
+     */
+    len = fcb->f_active.fe_area->fa_size;
+
+    rc = fcb_append(fcb, len, &elem_loc);
+    TEST_ASSERT(rc != 0);
+
+    len--;
+    rc = fcb_append(fcb, len, &elem_loc);
+    TEST_ASSERT(rc != 0);
+
+    len -= sizeof(struct fcb_disk_area);
+    rc = fcb_append(fcb, len, &elem_loc);
+    TEST_ASSERT(rc != 0);
+
+    len = fcb->f_active.fe_area->fa_size -
+      (sizeof(struct fcb_disk_area) + 1 + 2);
+    rc = fcb_append(fcb, len, &elem_loc);
+    TEST_ASSERT(rc == 0);
+
+    rc = fcb_append_finish(fcb, &elem_loc);
+    TEST_ASSERT(rc == 0);
+
+    rc = fcb_elem_info(fcb, &elem_loc);
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(elem_loc.fe_data_len == len);
+}
+
+struct append_arg {
+    int *elem_cnts;
+};
+
+static int
+fcb_test_cnt_elems_cb(struct fcb_entry *loc, void *arg)
+{
+    struct append_arg *aa = (struct append_arg *)arg;
+    int idx;
+
+    idx = loc->fe_area - &test_fcb_area[0];
+    aa->elem_cnts[idx]++;
+    return 0;
+}
+
+TEST_CASE(fcb_test_append_fill)
+{
+    struct fcb *fcb;
+    int rc;
+    int i;
+    struct fcb_entry loc;
+    uint8_t test_data[128];
+    int elem_cnts[2] = {0, 0};
+    int aa_together_cnts[2];
+    struct append_arg aa_together = {
+        .elem_cnts = aa_together_cnts
+    };
+    int aa_separate_cnts[2];
+    struct append_arg aa_separate = {
+        .elem_cnts = aa_separate_cnts
+    };
+
+    fcb_test_wipe();
+    fcb = &test_fcb;
+    memset(fcb, 0, sizeof(*fcb));
+    fcb->f_sector_cnt = 2;
+    fcb->f_sectors = test_fcb_area;
+
+    rc = fcb_init(fcb);
+    TEST_ASSERT(rc == 0);
+
+    for (i = 0; i < sizeof(test_data); i++) {
+        test_data[i] = fcb_test_append_data(sizeof(test_data), i);
+    }
+
+    while (1) {
+        rc = fcb_append(fcb, sizeof(test_data), &loc);
+        if (rc == FCB_ERR_NOSPACE) {
+            break;
+        }
+        if (loc.fe_area == &test_fcb_area[0]) {
+            elem_cnts[0]++;
+        } else if (loc.fe_area == &test_fcb_area[1]) {
+            elem_cnts[1]++;
+        } else {
+            TEST_ASSERT(0);
+        }
+
+        rc = flash_area_write(loc.fe_area, loc.fe_data_off, test_data,
+          sizeof(test_data));
+        TEST_ASSERT(rc == 0);
+
+        rc = fcb_append_finish(fcb, &loc);
+        TEST_ASSERT(rc == 0);
+    }
+    TEST_ASSERT(elem_cnts[0] > 0);
+    TEST_ASSERT(elem_cnts[0] == elem_cnts[1]);
+
+    memset(&aa_together_cnts, 0, sizeof(aa_together_cnts));
+    rc = fcb_walk(fcb, NULL, fcb_test_cnt_elems_cb, &aa_together);
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(aa_together.elem_cnts[0] == elem_cnts[0]);
+    TEST_ASSERT(aa_together.elem_cnts[1] == elem_cnts[1]);
+
+    memset(&aa_separate_cnts, 0, sizeof(aa_separate_cnts));
+    rc = fcb_walk(fcb, &test_fcb_area[0], fcb_test_cnt_elems_cb,
+      &aa_separate);
+    TEST_ASSERT(rc == 0);
+    rc = fcb_walk(fcb, &test_fcb_area[1], fcb_test_cnt_elems_cb,
+      &aa_separate);
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(aa_separate.elem_cnts[0] == elem_cnts[0]);
+    TEST_ASSERT(aa_separate.elem_cnts[1] == elem_cnts[1]);
+
+}
+
+TEST_CASE(fcb_test_reset)
+{
+    struct fcb *fcb;
+    int rc;
+    int i;
+    struct fcb_entry loc;
+    uint8_t test_data[128];
+    int var_cnt;
+
+    fcb_test_wipe();
+    fcb = &test_fcb;
+    memset(fcb, 0, sizeof(*fcb));
+    fcb->f_sector_cnt = 2;
+    fcb->f_sectors = test_fcb_area;
+
+    rc = fcb_init(fcb);
+    TEST_ASSERT(rc == 0);
+
+    var_cnt = 0;
+    rc = fcb_walk(fcb, 0, fcb_test_data_walk_cb, &var_cnt);
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(var_cnt == 0);
+
+    rc = fcb_append(fcb, 32, &loc);
+    TEST_ASSERT(rc == 0);
+
+    /*
+     * No ready ones yet. CRC should not match.
+     */
+    var_cnt = 0;
+    rc = fcb_walk(fcb, 0, fcb_test_data_walk_cb, &var_cnt);
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(var_cnt == 0);
+
+    for (i = 0; i < sizeof(test_data); i++) {
+        test_data[i] = fcb_test_append_data(32, i);
+    }
+    rc = flash_area_write(loc.fe_area, loc.fe_data_off, test_data, 32);
+    TEST_ASSERT(rc == 0);
+
+    rc = fcb_append_finish(fcb, &loc);
+    TEST_ASSERT(rc == 0);
+
+    /*
+     * one entry
+     */
+    var_cnt = 32;
+    rc = fcb_walk(fcb, 0, fcb_test_data_walk_cb, &var_cnt);
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(var_cnt == 33);
+
+    /*
+     * Pretend reset
+     */
+    memset(fcb, 0, sizeof(*fcb));
+    fcb->f_sector_cnt = 2;
+    fcb->f_sectors = test_fcb_area;
+
+    rc = fcb_init(fcb);
+    TEST_ASSERT(rc == 0);
+
+    var_cnt = 32;
+    rc = fcb_walk(fcb, 0, fcb_test_data_walk_cb, &var_cnt);
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(var_cnt == 33);
+
+    rc = fcb_append(fcb, 33, &loc);
+    TEST_ASSERT(rc == 0);
+
+    for (i = 0; i < sizeof(test_data); i++) {
+        test_data[i] = fcb_test_append_data(33, i);
+    }
+    rc = flash_area_write(loc.fe_area, loc.fe_data_off, test_data, 33);
+    TEST_ASSERT(rc == 0);
+
+    rc = fcb_append_finish(fcb, &loc);
+    TEST_ASSERT(rc == 0);
+
+    var_cnt = 32;
+    rc = fcb_walk(fcb, 0, fcb_test_data_walk_cb, &var_cnt);
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(var_cnt == 34);
+
+    /*
+     * Add partial one, make sure that we survive reset then.
+     */
+    rc = fcb_append(fcb, 34, &loc);
+    TEST_ASSERT(rc == 0);
+
+    memset(fcb, 0, sizeof(*fcb));
+    fcb->f_sector_cnt = 2;
+    fcb->f_sectors = test_fcb_area;
+
+    rc = fcb_init(fcb);
+    TEST_ASSERT(rc == 0);
+
+    /*
+     * Walk should skip that.
+     */
+    var_cnt = 32;
+    rc = fcb_walk(fcb, 0, fcb_test_data_walk_cb, &var_cnt);
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(var_cnt == 34);
+
+    /* Add a 3rd one, should go behind corrupt entry */
+    rc = fcb_append(fcb, 34, &loc);
+    TEST_ASSERT(rc == 0);
+
+    for (i = 0; i < sizeof(test_data); i++) {
+        test_data[i] = fcb_test_append_data(34, i);
+    }
+    rc = flash_area_write(loc.fe_area, loc.fe_data_off, test_data, 34);
+    TEST_ASSERT(rc == 0);
+
+    rc = fcb_append_finish(fcb, &loc);
+    TEST_ASSERT(rc == 0);
+
+    /*
+     * Walk should skip corrupt entry, but report the next one.
+     */
+    var_cnt = 32;
+    rc = fcb_walk(fcb, 0, fcb_test_data_walk_cb, &var_cnt);
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(var_cnt == 35);
+}
+
+TEST_CASE(fcb_test_rotate)
+{
+    struct fcb *fcb;
+    int rc;
+    int old_id;
+    struct fcb_entry loc;
+    uint8_t test_data[128];
+    int elem_cnts[2] = {0, 0};
+    int cnts[2];
+    struct append_arg aa_arg = {
+        .elem_cnts = cnts
+    };
+
+    fcb_test_wipe();
+    fcb = &test_fcb;
+    memset(fcb, 0, sizeof(*fcb));
+    fcb->f_sector_cnt = 2;
+    fcb->f_sectors = test_fcb_area;
+
+    rc = fcb_init(fcb);
+    TEST_ASSERT(rc == 0);
+
+    old_id = fcb->f_active_id;
+    rc = fcb_rotate(fcb);
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(fcb->f_active_id == old_id + 1);
+
+    /*
+     * Now fill up the
+     */
+    while (1) {
+        rc = fcb_append(fcb, sizeof(test_data), &loc);
+        if (rc == FCB_ERR_NOSPACE) {
+            break;
+        }
+        if (loc.fe_area == &test_fcb_area[0]) {
+            elem_cnts[0]++;
+        } else if (loc.fe_area == &test_fcb_area[1]) {
+            elem_cnts[1]++;
+        } else {
+            TEST_ASSERT(0);
+        }
+
+        rc = flash_area_write(loc.fe_area, loc.fe_data_off, test_data,
+          sizeof(test_data));
+        TEST_ASSERT(rc == 0);
+
+        rc = fcb_append_finish(fcb, &loc);
+        TEST_ASSERT(rc == 0);
+    }
+    TEST_ASSERT(elem_cnts[0] > 0 && elem_cnts[0] == elem_cnts[1]);
+
+    old_id = fcb->f_active_id;
+    rc = fcb_rotate(fcb);
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(fcb->f_active_id == old_id); /* no new area created */
+
+    memset(cnts, 0, sizeof(cnts));
+    rc = fcb_walk(fcb, NULL, fcb_test_cnt_elems_cb, &aa_arg);
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(aa_arg.elem_cnts[0] == elem_cnts[0] ||
+      aa_arg.elem_cnts[1] == elem_cnts[1]);
+    TEST_ASSERT(aa_arg.elem_cnts[0] == 0 || aa_arg.elem_cnts[1] == 0);
+
+    /*
+     * One sector is full. The other one should have one entry in it.
+     */
+    rc = fcb_append(fcb, sizeof(test_data), &loc);
+    TEST_ASSERT(rc == 0);
+
+    rc = flash_area_write(loc.fe_area, loc.fe_data_off, test_data,
+      sizeof(test_data));
+    TEST_ASSERT(rc == 0);
+
+    rc = fcb_append_finish(fcb, &loc);
+    TEST_ASSERT(rc == 0);
+
+    old_id = fcb->f_active_id;
+    rc = fcb_rotate(fcb);
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(fcb->f_active_id == old_id);
+
+    memset(cnts, 0, sizeof(cnts));
+    rc = fcb_walk(fcb, NULL, fcb_test_cnt_elems_cb, &aa_arg);
+    TEST_ASSERT(rc == 0);
+    TEST_ASSERT(aa_arg.elem_cnts[0] == 1 || aa_arg.elem_cnts[1] == 1);
+    TEST_ASSERT(aa_arg.elem_cnts[0] == 0 || aa_arg.elem_cnts[1] == 0);
+}
+
+TEST_CASE(fcb_test_multiple_scratch)
+{
+    struct fcb *fcb;
+    int rc;
+    struct fcb_entry loc;
+    uint8_t test_data[128];
+    int elem_cnts[4];
+    int idx;
+    int cnts[4];
+    struct append_arg aa_arg = {
+        .elem_cnts = cnts
+    };
+
+    fcb_test_wipe();
+    fcb = &test_fcb;
+    memset(fcb, 0, sizeof(*fcb));
+    fcb->f_sector_cnt = 4;
+    fcb->f_scratch_cnt = 1;
+    fcb->f_sectors = test_fcb_area;
+
+    rc = fcb_init(fcb);
+    TEST_ASSERT(rc == 0);
+
+    /*
+     * Now fill up everything. We should be able to get 3 of the sectors
+     * full.
+     */
+    memset(elem_cnts, 0, sizeof(elem_cnts));
+    while (1) {
+        rc = fcb_append(fcb, sizeof(test_data), &loc);
+        if (rc == FCB_ERR_NOSPACE) {
+            break;
+        }
+        idx = loc.fe_area - &test_fcb_area[0];
+        elem_cnts[idx]++;
+
+        rc = flash_area_write(loc.fe_area, loc.fe_data_off, test_data,
+          sizeof(test_data));
+        TEST_ASSERT(rc == 0);
+
+        rc = fcb_append_finish(fcb, &loc);
+        TEST_ASSERT(rc == 0);
+    }
+
+    TEST_ASSERT(elem_cnts[0] > 0);
+    TEST_ASSERT(elem_cnts[0] == elem_cnts[1] && elem_cnts[0] == elem_cnts[2]);
+    TEST_ASSERT(elem_cnts[3] == 0);
+
+    /*
+     * Ask to use scratch block, then fill it up.
+     */
+    rc = fcb_append_to_scratch(fcb);
+    TEST_ASSERT(rc == 0);
+
+    while (1) {
+        rc = fcb_append(fcb, sizeof(test_data), &loc);
+        if (rc == FCB_ERR_NOSPACE) {
+            break;
+        }
+        idx = loc.fe_area - &test_fcb_area[0];
+        elem_cnts[idx]++;
+
+        rc = flash_area_write(loc.fe_area, loc.fe_data_off, test_data,
+          sizeof(test_data));
+        TEST_ASSERT(rc == 0);
+
+        rc = fcb_append_finish(fcb, &loc);
+        TEST_ASSERT(rc == 0);
+    }
+    TEST_ASSERT(elem_cnts[3] == elem_cnts[0]);
+
+    /*
+     * Rotate
+     */
+    rc = fcb_rotate(fcb);
+    TEST_ASSERT(rc == 0);
+
+    memset(&cnts, 0, sizeof(cnts));
+    rc = fcb_walk(fcb, NULL, fcb_test_cnt_elems_cb, &aa_arg);
+    TEST_ASSERT(rc == 0);
+
+    TEST_ASSERT(cnts[0] == 0);
+    TEST_ASSERT(cnts[1] > 0);
+    TEST_ASSERT(cnts[1] == cnts[2] && cnts[1] == cnts[3]);
+
+    rc = fcb_append_to_scratch(fcb);
+    TEST_ASSERT(rc == 0);
+    rc = fcb_append_to_scratch(fcb);
+    TEST_ASSERT(rc != 0);
+}
+
+TEST_SUITE(fcb_test_all)
+{
+    fcb_test_len();
+
+    fcb_test_init();
+
+    fcb_test_empty_walk();
+
+    fcb_test_append();
+
+    fcb_test_append_too_big();
+
+    fcb_test_append_fill();
+
+    fcb_test_reset();
+
+    fcb_test_rotate();
+
+    fcb_test_multiple_scratch();
+}
+
+#if MYNEWT_VAL(SELFTEST)
+
+int
+main(int argc, char **argv)
+{
+    tu_config.tc_print_results = 1;
+    tu_init();
+
+    fcb_test_all();
+
+    return tu_any_failed;
+}
+#endif
+

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/fs/nffs/pkg.yml
----------------------------------------------------------------------
diff --git a/fs/nffs/pkg.yml b/fs/nffs/pkg.yml
index 1a3f11d..19d91be 100644
--- a/fs/nffs/pkg.yml
+++ b/fs/nffs/pkg.yml
@@ -28,9 +28,10 @@ pkg.keywords:
 
 pkg.deps:
     - fs/fs
+    - encoding/crc
     - hw/hal
-    - libs/os
-    - libs/testutil
+    - kernel/os
+    - test/testutil
     - sys/log
     - sys/stats
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/fs/nffs/src/nffs_priv.h
----------------------------------------------------------------------
diff --git a/fs/nffs/src/nffs_priv.h b/fs/nffs/src/nffs_priv.h
index 1872633..27c284b 100644
--- a/fs/nffs/src/nffs_priv.h
+++ b/fs/nffs/src/nffs_priv.h
@@ -6,7 +6,7 @@
  * 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,
@@ -26,7 +26,7 @@
 #include "os/os_mempool.h"
 #include "nffs/nffs.h"
 #include "fs/fs.h"
-#include "util/crc16.h"
+#include "crc/crc16.h"
 #include "stats/stats.h"
 
 #define NFFS_HASH_SIZE               256

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/fs/nffs/test/pkg.yml
----------------------------------------------------------------------
diff --git a/fs/nffs/test/pkg.yml b/fs/nffs/test/pkg.yml
index f7a66f6..750247b 100644
--- a/fs/nffs/test/pkg.yml
+++ b/fs/nffs/test/pkg.yml
@@ -24,7 +24,7 @@ pkg.keywords:
 
 pkg.deps: 
     - fs/nffs
-    - libs/testutil
+    - test/testutil
 
 pkg.deps.SELFTEST:
-    - libs/console/stub
+    - sys/console/stub

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/hw/bsp/arduino_primo_nrf52/pkg.yml
----------------------------------------------------------------------
diff --git a/hw/bsp/arduino_primo_nrf52/pkg.yml b/hw/bsp/arduino_primo_nrf52/pkg.yml
index c000e94..4c58540 100644
--- a/hw/bsp/arduino_primo_nrf52/pkg.yml
+++ b/hw/bsp/arduino_primo_nrf52/pkg.yml
@@ -41,7 +41,7 @@ pkg.cflags:
 
 pkg.deps:
     - hw/mcu/nordic/nrf52xxx
-    - libs/baselibc
+    - libc/baselibc
 
 pkg.deps.BLE_DEVICE:
     - hw/drivers/nimble/nrf52

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/hw/bsp/bmd300eval/pkg.yml
----------------------------------------------------------------------
diff --git a/hw/bsp/bmd300eval/pkg.yml b/hw/bsp/bmd300eval/pkg.yml
index d58bd63..93fa47e 100644
--- a/hw/bsp/bmd300eval/pkg.yml
+++ b/hw/bsp/bmd300eval/pkg.yml
@@ -40,7 +40,7 @@ pkg.cflags:
 
 pkg.deps:
     - hw/mcu/nordic/nrf52xxx
-    - libs/baselibc
+    - libc/baselibc
 
 pkg.deps.BLE_DEVICE:
     - hw/drivers/nimble/nrf52

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/hw/bsp/nrf51-arduino_101/pkg.yml
----------------------------------------------------------------------
diff --git a/hw/bsp/nrf51-arduino_101/pkg.yml b/hw/bsp/nrf51-arduino_101/pkg.yml
index cbe5db9..37bd2bb 100644
--- a/hw/bsp/nrf51-arduino_101/pkg.yml
+++ b/hw/bsp/nrf51-arduino_101/pkg.yml
@@ -38,7 +38,7 @@ pkg.cflags:
 
 pkg.deps:
     - hw/mcu/nordic/nrf51xxx
-    - libs/baselibc
+    - libc/baselibc
 
 pkg.deps.BLE_DEVICE:
     - hw/drivers/nimble/nrf51

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/hw/bsp/nrf51-blenano/pkg.yml
----------------------------------------------------------------------
diff --git a/hw/bsp/nrf51-blenano/pkg.yml b/hw/bsp/nrf51-blenano/pkg.yml
index ac54b16..87b1dbc 100644
--- a/hw/bsp/nrf51-blenano/pkg.yml
+++ b/hw/bsp/nrf51-blenano/pkg.yml
@@ -40,7 +40,7 @@ pkg.cflags:
 
 pkg.deps:
     - hw/mcu/nordic/nrf51xxx
-    - libs/baselibc
+    - libc/baselibc
 
 pkg.deps.BLE_DEVICE:
     - hw/drivers/nimble/nrf51

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/hw/bsp/nrf51dk-16kbram/pkg.yml
----------------------------------------------------------------------
diff --git a/hw/bsp/nrf51dk-16kbram/pkg.yml b/hw/bsp/nrf51dk-16kbram/pkg.yml
index 164e710..ef80ad5 100644
--- a/hw/bsp/nrf51dk-16kbram/pkg.yml
+++ b/hw/bsp/nrf51dk-16kbram/pkg.yml
@@ -39,7 +39,7 @@ pkg.cflags:
 
 pkg.deps:
     - hw/mcu/nordic/nrf51xxx
-    - libs/baselibc
+    - libc/baselibc
 
 pkg.deps.BLE_DEVICE:
     - hw/drivers/nimble/nrf51

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/hw/bsp/nrf51dk/pkg.yml
----------------------------------------------------------------------
diff --git a/hw/bsp/nrf51dk/pkg.yml b/hw/bsp/nrf51dk/pkg.yml
index 8df1bac..e9e741d 100644
--- a/hw/bsp/nrf51dk/pkg.yml
+++ b/hw/bsp/nrf51dk/pkg.yml
@@ -39,7 +39,7 @@ pkg.cflags:
 
 pkg.deps:
     - hw/mcu/nordic/nrf51xxx
-    - libs/baselibc
+    - libc/baselibc
 
 pkg.deps.BLE_DEVICE:
     - hw/drivers/nimble/nrf51

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/hw/bsp/nrf52dk/pkg.yml
----------------------------------------------------------------------
diff --git a/hw/bsp/nrf52dk/pkg.yml b/hw/bsp/nrf52dk/pkg.yml
index 69e520a..ee9095b 100644
--- a/hw/bsp/nrf52dk/pkg.yml
+++ b/hw/bsp/nrf52dk/pkg.yml
@@ -40,7 +40,7 @@ pkg.cflags:
 
 pkg.deps:
     - hw/mcu/nordic/nrf52xxx
-    - libs/baselibc
+    - libc/baselibc
 
 pkg.deps.BLE_DEVICE:
     - hw/drivers/nimble/nrf52

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/hw/bsp/nrf52pdk/pkg.yml
----------------------------------------------------------------------
diff --git a/hw/bsp/nrf52pdk/pkg.yml b/hw/bsp/nrf52pdk/pkg.yml
index c9c55f5..47c411c 100644
--- a/hw/bsp/nrf52pdk/pkg.yml
+++ b/hw/bsp/nrf52pdk/pkg.yml
@@ -39,7 +39,7 @@ pkg.cflags:
 
 pkg.deps:
     - hw/mcu/nordic/nrf52xxx
-    - libs/baselibc
+    - libc/baselibc
 
 pkg.deps.BLE_DEVICE:
     - hw/drivers/nimble/nrf52

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/hw/bsp/nucleo-f401re/pkg.yml
----------------------------------------------------------------------
diff --git a/hw/bsp/nucleo-f401re/pkg.yml b/hw/bsp/nucleo-f401re/pkg.yml
index b579be1..bb36d88 100644
--- a/hw/bsp/nucleo-f401re/pkg.yml
+++ b/hw/bsp/nucleo-f401re/pkg.yml
@@ -36,4 +36,4 @@ pkg.debugscript: "nucleo-f401re_debug.sh"
 pkg.cflags: -DSTM32F401xE
 pkg.deps:
     - hw/mcu/stm/stm32f4xx
-    - libs/baselibc
+    - libc/baselibc

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/hw/bsp/olimex_stm32-e407_devboard/pkg.yml
----------------------------------------------------------------------
diff --git a/hw/bsp/olimex_stm32-e407_devboard/pkg.yml b/hw/bsp/olimex_stm32-e407_devboard/pkg.yml
index a8c5b6e..6d34817 100644
--- a/hw/bsp/olimex_stm32-e407_devboard/pkg.yml
+++ b/hw/bsp/olimex_stm32-e407_devboard/pkg.yml
@@ -40,7 +40,7 @@ pkg.cflags:
     - '-DHAL_DMA_MODULE_ENABLED'
 pkg.deps:
     - hw/mcu/stm/stm32f4xx
-    - libs/baselibc
+    - libc/baselibc
 
 pkg.deps.ADC_1:
     - hw/drivers/adc/adc_stm32f4

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/hw/bsp/stm32f4discovery/pkg.yml
----------------------------------------------------------------------
diff --git a/hw/bsp/stm32f4discovery/pkg.yml b/hw/bsp/stm32f4discovery/pkg.yml
index 04e74d3..b6b6e36 100644
--- a/hw/bsp/stm32f4discovery/pkg.yml
+++ b/hw/bsp/stm32f4discovery/pkg.yml
@@ -36,4 +36,4 @@ pkg.debugscript: "stm32f4discovery_debug.sh"
 pkg.cflags: -DSTM32F407xx
 pkg.deps:
     - hw/mcu/stm/stm32f4xx
-    - libs/baselibc
+    - libc/baselibc

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6a7432f4/hw/cmsis-core/pkg.yml
----------------------------------------------------------------------
diff --git a/hw/cmsis-core/pkg.yml b/hw/cmsis-core/pkg.yml
new file mode 100644
index 0000000..0903256
--- /dev/null
+++ b/hw/cmsis-core/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: hw/cmsis-core
+pkg.description: CMSIS-CORE abstraction layer for Cortex-M processors.
+pkg.author: "Keil"
+pkg.homepage: "http://www.keil.com/pack/doc/CMSIS/Core/html/index.html"
+pkg.keywords:
+    - cmsis
+    - core
+pkg.type: sdk