/**
 * Deletes the main image version number from the boot vector.
 * This must be called by the app to confirm that it is ok to keep booting
 * to this image.
 *
 * @return                  0 on success; nonzero on failure.
 */
int
boot_vect_write_main(void)
{
    const struct flash_area *fap;
    uint32_t off;
    int rc;
    uint8_t val;

    /*
     * Write to slot 0.
     */
    rc = flash_area_open(FLASH_AREA_IMAGE_0, &fap);
    if (rc) {
        return rc;
    }

    off = fap->fa_size - sizeof(struct boot_img_trailer);
    off += (sizeof(uint32_t) + sizeof(uint8_t));
    rc = flash_area_read(fap, off, &val, sizeof(val));
    if (!rc && val == 0xff) {
        val = 0;
        rc = flash_area_write(fap, off, &val, sizeof(val));
    }
    return rc;
}
Example #2
0
/*
 * Read version from image header from flash area 'area_id'.
 * Returns -1 if area is not readable.
 * Returns 0 if image in slot is ok, and version string is valid.
 * Returns 1 if there is not a full image.
 * Returns 2 if slot is empty.
 */
int
imgr_read_ver(int area_id, struct image_version *ver)
{
    struct image_header hdr;
    int rc;
    const struct flash_area *fa;

    rc = flash_area_open(area_id, &fa);
    if (rc) {
        return -1;
    }
    rc = flash_area_read(fa, 0, &hdr, sizeof(hdr));
    if (rc) {
        return -1;
    }
    memset(ver, 0xff, sizeof(*ver));
    if (hdr.ih_magic == 0x96f3b83c) {
        memcpy(ver, &hdr.ih_ver, sizeof(*ver));
        rc = 0;
    } else {
        rc = 1;
    }
    flash_area_close(fa);
    return rc;
}
int
imgr_core_list(struct nmgr_jbuf *njb)
{
    const struct flash_area *fa;
    struct coredump_header hdr;
    struct json_encoder *enc;
    struct json_value jv;
    int rc;

    rc = flash_area_open(FLASH_AREA_CORE, &fa);
    if (rc) {
        rc = NMGR_ERR_EINVAL;
    } else {
        rc = flash_area_read(fa, 0, &hdr, sizeof(hdr));
        if (rc != 0) {
            rc = NMGR_ERR_EINVAL;
        } else if (hdr.ch_magic != COREDUMP_MAGIC) {
            rc = NMGR_ERR_ENOENT;
        } else {
            rc = 0;
        }
    }

    enc = &njb->njb_enc;

    json_encode_object_start(enc);
    JSON_VALUE_INT(&jv, rc);
    json_encode_object_entry(enc, "rc", &jv);
    json_encode_object_finish(enc);

    return 0;
}
static void
boot_test_util_write_swap_state(int flash_area_id,
                                const struct boot_swap_state *state)
{
    const struct flash_area *fap;
    int rc;

    rc = flash_area_open(flash_area_id, &fap);
    TEST_ASSERT_FATAL(rc == 0);

    switch (state->magic) {
    case 0:
        break;

    case BOOT_MAGIC_GOOD:
        rc = boot_write_magic(fap);
        TEST_ASSERT_FATAL(rc == 0);
        break;

    default:
        TEST_ASSERT_FATAL(0);
        break;
    }

    if (state->copy_done != 0xff) {
        rc = boot_write_copy_done(fap);
        TEST_ASSERT_FATAL(rc == 0);
    }

    if (state->image_ok != 0xff) {
        rc = boot_write_image_ok(fap);
        TEST_ASSERT_FATAL(rc == 0);
    }
}
Example #5
0
/*
 * Turn flash region into a set of areas for NFFS use.
 *
 * Limit the number of regions we return to be less than *cnt.
 * If sector count within region exceeds that, collect multiple sectors
 * to a region.
 */
int
nffs_misc_desc_from_flash_area(int id, int *cnt, struct nffs_area_desc *nad)
{
    int i, j;
    const struct hal_flash *hf;
    const struct flash_area *fa;
    int max_cnt, move_on;
    int first_idx, last_idx;
    uint32_t start, size;
    uint32_t min_size;
    int rc;

    first_idx = last_idx = -1;
    max_cnt = *cnt;
    *cnt = 0;

    rc = flash_area_open(id, &fa);
    if (rc != 0) {
        return -1;
    }

    hf = hal_bsp_flash_dev(fa->fa_device_id);
    for (i = 0; i < hf->hf_sector_cnt; i++) {
        hf->hf_itf->hff_sector_info(hf, i, &start, &size);
        if (start >= fa->fa_off && start < fa->fa_off + fa->fa_size) {
            if (first_idx == -1) {
                first_idx = i;
            }
            last_idx = i;
            *cnt = *cnt + 1;
        }
    }
    if (*cnt > max_cnt) {
        min_size = fa->fa_size / max_cnt;
    } else {
        min_size = 0;
    }
    *cnt = 0;

    move_on = 1;
    for (i = first_idx, j = 0; i < last_idx + 1; i++) {
        hf->hf_itf->hff_sector_info(hf, i, &start, &size);
        if (move_on) {
            nad[j].nad_flash_id = fa->fa_device_id;
            nad[j].nad_offset = start;
            nad[j].nad_length = size;
            *cnt = *cnt + 1;
            move_on = 0;
        } else {
            nad[j].nad_length += size;
        }
        if (nad[j].nad_length >= min_size) {
            j++;
            move_on = 1;
        }
    }
    nad[*cnt].nad_length = 0;
    return 0;
}
/*
 * Read the image trailer from a given slot.
 */
static int
boot_vect_read_img_trailer(int slot, struct boot_img_trailer *bit)
{
    int rc;
    const struct flash_area *fap;
    uint32_t off;

    rc = flash_area_open(slot, &fap);
    if (rc) {
        return rc;
    }
    off = fap->fa_size - sizeof(struct boot_img_trailer);
    rc = flash_area_read(fap, off, bit, sizeof(*bit));
    flash_area_close(fap);

    return rc;
}
/**
 * Write the test image version number from the boot vector.
 *
 * @return                  0 on success; nonzero on failure.
 */
int
boot_vect_write_test(int slot)
{
    const struct flash_area *fap;
    uint32_t off;
    uint32_t magic;
    int rc;

    rc = flash_area_open(slot, &fap);
    if (rc) {
        return rc;
    }

    off = fap->fa_size - sizeof(struct boot_img_trailer);
    magic = BOOT_IMG_MAGIC;

    rc = flash_area_write(fap, off, &magic, sizeof(magic));
    flash_area_close(fap);

    return rc;
}
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) {
        rc = MGMT_ERR_EINVAL;
    } else {
        rc = flash_area_read(fa, 0, &hdr, sizeof(hdr));
        if (rc != 0) {
            rc = MGMT_ERR_EINVAL;
        } else if (hdr.ch_magic != COREDUMP_MAGIC) {
            rc = MGMT_ERR_ENOENT;
        } else {
            rc = 0;
        }
    }

    mgmt_cbuf_setoerr(cb, rc);
    return 0;
}
Example #9
0
/**
 * Flushes the log while restoring specified number of entries
 * using image scratch
 * @param src_fcb, dst_fcb
 * @return 0 on success; non-zero on error
 */
static int
log_fcb_rtr_erase(struct log *log, void *arg)
{
    struct fcb_log *fcb_log;
    struct fcb fcb_scratch;
    struct fcb *fcb;
    const struct flash_area *ptr;
    uint32_t offset;
    int rc;

    rc = 0;
    offset = 0;
    if (!log) {
        rc = -1;
        goto err;
    }

    fcb_log = (struct fcb_log *)arg;
    fcb = fcb_log->fl_fcb;

    memset(&fcb_scratch, 0, sizeof(fcb_scratch));

    if (flash_area_open(FLASH_AREA_IMAGE_SCRATCH, &ptr)) {
        goto err;
    }
    sector = *ptr;
    fcb_scratch.f_sectors = &sector;
    fcb_scratch.f_sector_cnt = 1;
    fcb_scratch.f_magic = 0x7EADBADF;
    fcb_scratch.f_version = 0;

    rc = fcb_init(&fcb_scratch);
    if (rc) {
        goto err;
    }

    rc = fcb_clear(&fcb_scratch);
    if (rc) {
        goto err;
    }

    /* Calculate offset of n-th last entry */
    rc = fcb_offset_last_n(fcb, fcb_log->fl_entries, &offset);
    if (rc) {
        goto err;
    }

    /* Copy to scratch */
    rc = log_fcb_copy(log, fcb, &fcb_scratch, offset);
    if (rc) {
        goto err;
    }

    /* Flush log */
    rc = log_fcb_flush(log);
    if (rc) {
        goto err;
    }

    /* Copy back from scratch */
    rc = log_fcb_copy(log, &fcb_scratch, fcb, 0);

err:
    return (rc);
}
Example #10
0
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 bsp_mem_dump *mem, *cur;
    int area_cnt, i;
    uint8_t hash[IMGMGR_HASH_LEN];
    uint32_t off;
    uint32_t area_off, area_end;

    if (coredump_disabled) {
        return;
    }
    if (flash_area_open(FLASH_AREA_CORE, &fa)) {
        return;
    }

    if (flash_area_read(fa, 0, &hdr, sizeof(hdr))) {
        return;
    }
    if (hdr.ch_magic == COREDUMP_MAGIC) {
        /*
         * Don't override corefile.
         */
        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(bsp_imgr_current_slot(), &ver, hash) == 0) {
        tlv.ct_type = COREDUMP_TLV_IMAGE;
        tlv.ct_len = IMGMGR_HASH_LEN;

        dump_core_tlv(fa, &off, &tlv, hash);
    }

    mem = bsp_core_dump(&area_cnt);
    for (i = 0; i < area_cnt; i++) {
        cur = &mem[i];
        area_off = (uint32_t)cur->bmd_start;
        area_end = area_off + cur->bmd_size;
        while (area_off < area_end) {
            tlv.ct_type = COREDUMP_TLV_MEM;
            if (cur->bmd_size > USHRT_MAX) {
                tlv.ct_len = SHRT_MAX + 1;
            } else {
                tlv.ct_len = cur->bmd_size;
            }
            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));
}
Example #11
0
/*
 * Read version and build hash from image located slot "image_slot".  Note:
 * this is a slot index, not a flash area ID.
 *
 * @param image_slot
 * @param ver (optional)
 * @param hash (optional)
 * @param flags
 *
 * Returns -1 if area is not readable.
 * Returns 0 if image in slot is ok, and version string is valid.
 * Returns 1 if there is not a full image.
 * Returns 2 if slot is empty. XXXX not there yet
 */
int
imgr_read_info(int image_slot, struct image_version *ver, uint8_t *hash,
               uint32_t *flags)
{
    struct image_header *hdr;
    struct image_tlv *tlv;
    int rc = -1;
    int rc2;
    const struct flash_area *fa;
    uint8_t data[sizeof(struct image_header)];
    uint32_t data_off, data_end;
    int area_id;

    area_id = flash_area_id_from_image_slot(image_slot);

    hdr = (struct image_header *)data;
    rc2 = flash_area_open(area_id, &fa);
    if (rc2) {
        return -1;
    }
    rc2 = flash_area_read(fa, 0, hdr, sizeof(*hdr));
    if (rc2) {
        goto end;
    }

    if (ver != NULL) {
        memset(ver, 0xff, sizeof(*ver));
        if (hdr->ih_magic == IMAGE_MAGIC) {
            memcpy(ver, &hdr->ih_ver, sizeof(*ver));
        } else if (hdr->ih_magic == 0xffffffff) {
            rc = 2;
            goto end;
        } else {
            rc = 1;
            goto end;
        }
    }

    if(flags) {
        *flags = hdr->ih_flags;
    }
    /*
     * Build ID is in a TLV after the image.
     */
    data_off = hdr->ih_hdr_size + hdr->ih_img_size;
    data_end = data_off + hdr->ih_tlv_size;

    if (data_end > fa->fa_size) {
        rc = 1;
        goto end;
    }
    tlv = (struct image_tlv *)data;
    while (data_off + sizeof(*tlv) <= data_end) {
        rc2 = flash_area_read(fa, data_off, tlv, sizeof(*tlv));
        if (rc2) {
            goto end;
        }
        if (tlv->it_type == 0xff && tlv->it_len == 0xffff) {
            break;
        }
        if (tlv->it_type != IMAGE_TLV_SHA256 ||
          tlv->it_len != IMGMGR_HASH_LEN) {
            data_off += sizeof(*tlv) + tlv->it_len;
            continue;
        }
        data_off += sizeof(*tlv);
        if (hash) {
            if (data_off + IMGMGR_HASH_LEN > data_end) {
                goto end;
            }
            rc2 = flash_area_read(fa, data_off, hash, IMGMGR_HASH_LEN);
            if (rc2) {
                goto end;
            }
        }
        rc = 0;
        goto end;
    }
    rc = 1;
end:
    flash_area_close(fa);
    return rc;
}