예제 #1
0
int mgos_upd_file_end(struct mgos_upd_hal_ctx *ctx,
                      const struct mgos_upd_file_info *fi, struct mg_str tail) {
  int r = tail.len;
  assert(tail.len == 0);
  if (ctx->cur_fn == (_u8 *) ctx->fs_container_file) {
    if (!cc32xx_vfs_dev_slfs_container_write_meta(
            ctx->cur_fh, FS_INITIAL_SEQ, ctx->fs_size, ctx->fs_block_size,
            ctx->fs_page_size, ctx->fs_erase_size)) {
      ctx->status_msg = "Failed to write fs meta";
      r = -1;
    }
  }
  if (sl_FsClose(ctx->cur_fh, NULL, NULL, 0) != 0) {
    ctx->status_msg = "Close failed";
    r = -1;
  } else {
    struct json_token sha1 = JSON_INVALID_TOKEN;
    json_scanf(ctx->cur_part.ptr, ctx->cur_part.len, "{cs_sha1: %T}", &sha1);
    if (!verify_checksum((const char *) ctx->cur_fn, fi->size, &sha1)) {
      ctx->status_msg = "Checksum mismatch";
      r = -1;
    }
  }
  ctx->cur_fh = -1;
  ctx->cur_fn = NULL;
  return r;
}
예제 #2
0
static int prepare_to_write(struct mgos_upd_hal_ctx *ctx,
                            const struct mgos_upd_file_info *fi,
                            const char *fname, uint32_t falloc,
                            struct json_token *part) {
  struct json_token expected_sha1 = JSON_INVALID_TOKEN;
  json_scanf(part->ptr, part->len, "{cs_sha1: %T}", &expected_sha1);
  if (verify_checksum(fname, fi->size, &expected_sha1)) {
    LOG(LL_INFO,
        ("Digest matched for %s %u (%.*s)", fname, (unsigned int) fi->size,
         (int) expected_sha1.len, expected_sha1.ptr));
    return 0;
  }
  LOG(LL_INFO, ("Storing %s %u -> %s %u (%.*s)", fi->name,
                (unsigned int) fi->size, fname, (unsigned int) falloc,
                (int) expected_sha1.len, expected_sha1.ptr));
  ctx->cur_fn = (const _u8 *) fname;
  sl_FsDel(ctx->cur_fn, 0);
  _i32 r = sl_FsOpen(ctx->cur_fn, FS_MODE_OPEN_CREATE(falloc, 0), NULL,
                     &ctx->cur_fh);
  if (r < 0) {
    ctx->status_msg = "Failed to create file";
    return r;
  }
  return 1;
}
static bool esp32_vfs_dev_partition_open(struct mgos_vfs_dev *dev,
                                         const char *opts) {
  char *label = NULL;
  int subtype = 0xff; /* any subtype */
  json_scanf(opts, strlen(opts), "{name: %Q, label: %Q, subtype: %d}", &label,
             &label, &subtype);
  if (label == NULL) {
    LOG(LL_ERROR, ("Must specify partition label"));
    return false;
  }
  const esp_partition_t *part =
      esp_partition_find_first(ESP_PARTITION_TYPE_DATA, subtype, label);
  if (part != NULL) {
    dev->dev_data = (void *) part;
  }
  free(label);
  return (part != NULL);
}
예제 #4
0
static int tcmp(const struct json_token *tok, const char *str) {
  struct mg_str s = {.p = tok->ptr, .len = tok->len};
  return mg_vcmp(&s, str);
}

enum mgos_upd_file_action mgos_upd_file_begin(
    struct mgos_upd_hal_ctx *ctx, const struct mgos_upd_file_info *fi) {
  struct mg_str part_name = MG_MK_STR("");
  enum mgos_upd_file_action ret = MGOS_UPDATER_SKIP_FILE;
  struct find_part_info find_part_info = {fi->name, &part_name, &ctx->cur_part};
  ctx->cur_part.len = part_name.len = 0;
  json_walk(ctx->parts->ptr, ctx->parts->len, find_part, &find_part_info);
  if (ctx->cur_part.len == 0) return ret;
  /* Drop any indexes from part name, we'll add our own. */
  while (1) {
    char c = part_name.p[part_name.len - 1];
    if (c != '.' && !(c >= '0' && c <= '9')) break;
    part_name.len--;
  }
  struct json_token type = JSON_INVALID_TOKEN;
  const char *fname = NULL;
  uint32_t falloc = 0;
  json_scanf(ctx->cur_part.ptr, ctx->cur_part.len,
             "{load_addr:%u, falloc:%u, type: %T}", &ctx->app_load_addr,
             &falloc, &type);

  if (falloc == 0) falloc = fi->size;
  if (tcmp(&type, "app") == 0) {
    struct boot_cfg cur_cfg;
    int r = read_boot_cfg(ctx->cur_boot_cfg_idx, &cur_cfg);
    if (r < 0) {
      ctx->status_msg = "Could not read current boot cfg";
      return MGOS_UPDATER_ABORT;
    }
#if CC3200_SAFE_CODE_UPDATE
    /*
     * When safe code update is enabled, we write code to a new file.
     * Otherwise we write to the same slot we're using currently, which is
     * unsafe, makes reverting code update not possible, but saves space.
     */
    create_fname(
        mg_mk_str_n(cur_cfg.app_image_file, strlen(cur_cfg.app_image_file) - 2),
        ctx->new_boot_cfg_idx, ctx->app_image_file,
        sizeof(ctx->app_image_file));
#else
    {
      strncpy(ctx->app_image_file, cur_cfg.app_image_file,
              sizeof(ctx->app_image_file));
    }
#endif
    if (ctx->app_load_addr >= 0x20000000) {
      fname = ctx->app_image_file;
    } else {
      ctx->status_msg = "Bad/missing app load_addr";
      ret = MGOS_UPDATER_ABORT;
    }
  } else if (tcmp(&type, "fs") == 0) {
    json_scanf(
        ctx->cur_part.ptr, ctx->cur_part.len,
        "{fs_size: %u, fs_block_size: %u, fs_page_size: %u, fs_erase_size: %u}",
        &ctx->fs_size, &ctx->fs_block_size, &ctx->fs_page_size,
        &ctx->fs_erase_size);
    if (ctx->fs_size > 0 && ctx->fs_block_size > 0 && ctx->fs_page_size > 0 &&
        ctx->fs_erase_size > 0) {
      char fs_container_prefix[MAX_FS_CONTAINER_PREFIX_LEN];
      create_fname(part_name, ctx->new_boot_cfg_idx, fs_container_prefix,
                   sizeof(fs_container_prefix));
      /* Delete container 1 (if any) so that 0 is the only one. */
      cc32xx_vfs_dev_slfs_container_delete_container(fs_container_prefix, 1);
      cc32xx_vfs_dev_slfs_container_fname(fs_container_prefix, 0,
                                          (_u8 *) ctx->fs_container_file);
      fname = ctx->fs_container_file;
      if (fi->size > ctx->fs_size) {
        /* Assume meta has already been added. */
        falloc = fi->size;
      } else {
        falloc = FS_CONTAINER_SIZE(fi->size);
      }
    } else {
      ctx->status_msg = "Missing FS parameters";
      ret = MGOS_UPDATER_ABORT;
    }
  }
  if (fname != NULL) {
    int r = prepare_to_write(ctx, fi, fname, falloc, &ctx->cur_part);
    if (r < 0) {
      LOG(LL_ERROR, ("err = %d", r));
      ret = MGOS_UPDATER_ABORT;
    } else {
      ret = (r > 0 ? MGOS_UPDATER_PROCESS_FILE : MGOS_UPDATER_SKIP_FILE);
    }
  }
  if (ret == MGOS_UPDATER_SKIP_FILE) {
    DBG(("Skipping %s %.*s", fi->name, (int) part_name.len, part_name.p));
  }
  return ret;
}

int mgos_upd_file_data(struct mgos_upd_hal_ctx *ctx,
                       const struct mgos_upd_file_info *fi,
                       struct mg_str data) {
  _i32 r = sl_FsWrite(ctx->cur_fh, fi->processed, (_u8 *) data.p, data.len);
  if (r != data.len) {
    ctx->status_msg = "Write failed";
    r = -1;
  }
  return r;
}
예제 #5
0
static void handle_update_req(struct clubby_event *evt, void *user_data) {
  char *zip_url;
  struct json_token section = JSON_INVALID_TOKEN;
  struct json_token blob_url = JSON_INVALID_TOKEN;
  struct json_token args = evt->request.args;

  (void) user_data;
  LOG(LL_DEBUG, ("Update request received: %.*s", evt->request.args.len,
                 evt->request.args.ptr));

  const char *reply = "Malformed request";

  if (evt->request.args.type != JSON_TYPE_OBJECT) {
    goto bad_request;
  }

  json_scanf(args.ptr, args.len, "{section: %T, blob_url: %T}", &section,
             &blob_url);

  /*
   * TODO(alashkin): enable update for another files, not
   * firmware only
   */
  if (section.len == 0 || section.type != JSON_TYPE_STRING ||
      strncmp(section.ptr, "firmware", section.len) != 0 || blob_url.len == 0 ||
      blob_url.type != JSON_TYPE_STRING) {
    goto bad_request;
  }

  LOG(LL_DEBUG, ("zip url: %.*s", blob_url.len, blob_url.ptr));

  sj_clubby_free_reply(s_clubby_reply);
  s_clubby_reply = sj_clubby_create_reply(evt);

  /*
   * If user setup callback for updater, just call it.
   * User can start update with Sys.updater.start()
   */

  zip_url = calloc(1, blob_url.len + 1);
  if (zip_url == NULL) {
    CONSOLE_LOG(LL_ERROR, ("Out of memory"));
    return;
  }

  memcpy(zip_url, blob_url.ptr, blob_url.len);

  if (!notify_js(UJS_GOT_REQUEST, zip_url)) {
    struct update_context *ctx = updater_context_create();
    if (ctx == NULL) {
      reply = "Failed to init updater";
    } else if (start_update_download(ctx, zip_url) < 0) {
      reply = ctx->status_msg;
    }
  }

  free(zip_url);

  return;

bad_request:
  CONSOLE_LOG(LL_ERROR, ("Failed to start update: %s", reply));
  sj_clubby_send_status_resp(evt, 1, reply);
}