blob: 12e3a75e70708754589e7ede33733aacaf7fbb15 [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 <stddef.h>
#include <limits.h>
#include "os/mynewt.h"
#include "hal/hal_bsp.h"
#include "flash_map/flash_map.h"
#include "bootutil/image.h"
#include "imgmgr/imgmgr.h"
#include "coredump/coredump.h"
uint8_t coredump_disabled;
static void
dump_core_tlv(const struct flash_area *fa, uint32_t *off,
struct coredump_tlv *tlv, void *data)
{
flash_area_write(fa, *off, tlv, sizeof(*tlv));
*off += sizeof(*tlv);
flash_area_write(fa, *off, data, tlv->ct_len);
*off += tlv->ct_len;
}
void
coredump_dump(void *regs, int regs_sz)
{
struct coredump_header hdr;
struct coredump_tlv tlv;
const struct flash_area *fa;
struct image_version ver;
const struct hal_bsp_mem_dump *mem, *cur;
int area_cnt, i;
uint8_t hash[IMGMGR_HASH_LEN];
uint32_t off;
uint32_t area_off, area_end;
int slot;
if (coredump_disabled) {
return;
}
if (flash_area_open(MYNEWT_VAL(COREDUMP_FLASH_AREA), &fa)) {
return;
}
if (flash_area_read(fa, 0, &hdr, sizeof(hdr))) {
return;
}
if (hdr.ch_magic == COREDUMP_MAGIC) {
/*
* Don't override corefile.
*/
return;
}
/* Don't overwrite an image that has any flags set (pending, active, or
* confirmed).
*/
slot = flash_area_id_to_image_slot(MYNEWT_VAL(COREDUMP_FLASH_AREA));
if (slot != -1) {
if (imgmgr_state_slot_in_use(slot)) {
return;
}
}
if (flash_area_erase(fa, 0, fa->fa_size)) {
return;
}
/*
* First put in data, followed by the header.
*/
tlv.ct_type = COREDUMP_TLV_REGS;
tlv._pad = 0;
tlv.ct_len = regs_sz;
tlv.ct_off = 0;
off = sizeof(hdr);
dump_core_tlv(fa, &off, &tlv, regs);
if (imgr_read_info(boot_current_slot, &ver, hash, NULL) == 0) {
tlv.ct_type = COREDUMP_TLV_IMAGE;
tlv.ct_len = IMGMGR_HASH_LEN;
dump_core_tlv(fa, &off, &tlv, hash);
}
mem = hal_bsp_core_dump(&area_cnt);
for (i = 0; i < area_cnt; i++) {
cur = &mem[i];
area_off = (uint32_t)cur->hbmd_start;
area_end = area_off + cur->hbmd_size;
while (area_off < area_end) {
tlv.ct_type = COREDUMP_TLV_MEM;
if (area_end - area_off > USHRT_MAX) {
tlv.ct_len = USHRT_MAX - 3; /* 0xfffc */
} else {
tlv.ct_len = area_end - area_off;
}
if (off + tlv.ct_len + sizeof(tlv) > fa->fa_size) {
if (off + sizeof(tlv) >= fa->fa_size) {
break;
}
tlv.ct_len = fa->fa_size - (off + sizeof(tlv));
}
tlv.ct_off = area_off;
dump_core_tlv(fa, &off, &tlv, (void *)area_off);
area_off += tlv.ct_len;
}
}
hdr.ch_magic = COREDUMP_MAGIC;
hdr.ch_size = off;
flash_area_write(fa, 0, &hdr, sizeof(hdr));
}