blob: 858a1daaf266cb433c71ac6fba3b25276f6808b4 [file] [log] [blame]
/*
* 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"
#if MYNEWT_VAL(IMGMGR_COREDUMP)
#include <limits.h>
#include "flash_map/flash_map.h"
#include "mgmt/mgmt.h"
#include "coredump/coredump.h"
#include "cborattr/cborattr.h"
#include "imgmgr/imgmgr.h"
#include "imgmgr_priv.h"
int
imgr_core_list(struct mgmt_cbuf *cb)
{
const struct flash_area *fa;
struct coredump_header hdr;
int rc;
rc = flash_area_open(MYNEWT_VAL(COREDUMP_FLASH_AREA), &fa);
if (rc != 0) {
return MGMT_ERR_EUNKNOWN;
}
rc = flash_area_read(fa, 0, &hdr, sizeof(hdr));
if (rc != 0) {
return MGMT_ERR_EINVAL;
}
if (hdr.ch_magic != COREDUMP_MAGIC) {
return MGMT_ERR_ENOENT;
}
rc = mgmt_cbuf_setoerr(cb, 0);
if (rc != 0) {
return rc;
}
return 0;
}
int
imgr_core_load(struct mgmt_cbuf *cb)
{
unsigned long long off = UINT_MAX;
const struct cbor_attr_t dload_attr[2] = {
[0] = {
.attribute = "off",
.type = CborAttrUnsignedIntegerType,
.addr.uinteger = &off
},
[1] = { 0 },
};
int rc;
int sz;
const struct flash_area *fa;
uint8_t data[MYNEWT_VAL(IMGMGR_MAX_CHUNK_SIZE)];
struct coredump_header *hdr;
CborError g_err = CborNoError;
hdr = (struct coredump_header *)data;
rc = cbor_read_object(&cb->it, dload_attr);
if (rc || off == UINT_MAX) {
return MGMT_ERR_EINVAL;
}
rc = flash_area_open(MYNEWT_VAL(COREDUMP_FLASH_AREA), &fa);
if (rc) {
return MGMT_ERR_EINVAL;
}
rc = flash_area_read(fa, 0, hdr, sizeof(*hdr));
if (rc) {
rc = MGMT_ERR_EINVAL;
goto err_close;
}
if (hdr->ch_magic != COREDUMP_MAGIC) {
rc = MGMT_ERR_ENOENT;
goto err_close;
}
if (off > hdr->ch_size) {
off = hdr->ch_size;
}
sz = hdr->ch_size - off;
if (sz > sizeof(data)) {
sz = sizeof(data);
}
rc = flash_area_read(fa, off, data, sz);
if (rc) {
rc = MGMT_ERR_EINVAL;
goto err_close;
}
g_err |= cbor_encode_text_stringz(&cb->encoder, "rc");
g_err |= cbor_encode_int(&cb->encoder, MGMT_ERR_EOK);
g_err |= cbor_encode_text_stringz(&cb->encoder, "off");
g_err |= cbor_encode_int(&cb->encoder, off);
g_err |= cbor_encode_text_stringz(&cb->encoder, "data");
g_err |= cbor_encode_byte_string(&cb->encoder, data, sz);
/* Only include length in first response. */
if (off == 0) {
g_err |= cbor_encode_text_stringz(&cb->encoder, "len");
g_err |= cbor_encode_uint(&cb->encoder, hdr->ch_size);
}
flash_area_close(fa);
if (g_err) {
return MGMT_ERR_ENOMEM;
}
return 0;
err_close:
flash_area_close(fa);
return rc;
}
/*
* Erase the area if it has a coredump, or the header is empty.
*/
int
imgr_core_erase(struct mgmt_cbuf *cb)
{
struct coredump_header hdr;
const struct flash_area *fa;
int rc;
rc = flash_area_open(MYNEWT_VAL(COREDUMP_FLASH_AREA), &fa);
if (rc != 0) {
return MGMT_ERR_EINVAL;
}
rc = flash_area_read(fa, 0, &hdr, sizeof(hdr));
if (rc == 0 &&
(hdr.ch_magic == COREDUMP_MAGIC || hdr.ch_magic == 0xffffffff)) {
rc = flash_area_erase(fa, 0, fa->fa_size);
if (rc != 0) {
return MGMT_ERR_EINVAL;
}
}
flash_area_close(fa);
rc = mgmt_cbuf_setoerr(cb, rc);
if (rc != 0) {
return rc;
}
return 0;
}
#endif