/** * 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; }
/* * 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); } }
/* * 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; }
/** * 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 = §or; 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); }
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)); }
/* * 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; }