Esempio n. 1
0
int mgos_upd_finalize(struct mgos_upd_hal_ctx *ctx) {
  struct boot_cfg cur_cfg, new_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 r;
  }
  LOG(LL_INFO,
      ("Boot cfg %d: 0x%llx, 0x%x, %s @ 0x%08x, %s", ctx->cur_boot_cfg_idx,
       cur_cfg.seq, (unsigned int) cur_cfg.flags, cur_cfg.app_image_file,
       (unsigned int) cur_cfg.app_load_addr, cur_cfg.fs_container_prefix));
  memset(&new_cfg, 0, sizeof(new_cfg));
  new_cfg.seq = cur_cfg.seq - 1;
  new_cfg.flags |= BOOT_F_FIRST_BOOT;
  if (ctx->app_image_file[0] != '\0') {
    strncpy(new_cfg.app_image_file, ctx->app_image_file,
            sizeof(new_cfg.app_image_file));
    new_cfg.app_load_addr = ctx->app_load_addr;
  } else {
    strcpy(new_cfg.app_image_file, cur_cfg.app_image_file);
    new_cfg.app_load_addr = cur_cfg.app_load_addr;
  }
  if (ctx->fs_container_file[0] != '\0') {
    int n = strlen(ctx->fs_container_file);
    do {
      n--;
    } while (ctx->fs_container_file[n] != '.');
    strncpy(new_cfg.fs_container_prefix, ctx->fs_container_file, n);
    new_cfg.flags |= BOOT_F_MERGE_SPIFFS;
  } else {
    strcpy(new_cfg.fs_container_prefix, cur_cfg.fs_container_prefix);
  }
  LOG(LL_INFO,
      ("Boot cfg %d: 0x%llx, 0x%x, %s @ 0x%08x, %s", ctx->new_boot_cfg_idx,
       new_cfg.seq, (unsigned int) new_cfg.flags, new_cfg.app_image_file,
       (unsigned int) new_cfg.app_load_addr, new_cfg.fs_container_prefix));
  r = write_boot_cfg(&new_cfg, ctx->new_boot_cfg_idx);
  if (r < 0) {
    ctx->status_msg = "Could not write new boot cfg";
    return r;
  }
  return 1;
}
Esempio n. 2
0
int mgos_upd_apply_update() {
  int boot_cfg_idx = g_boot_cfg_idx;
  struct boot_cfg *cfg = &g_boot_cfg;
  if (cfg->flags & BOOT_F_MERGE_SPIFFS) {
    int old_boot_cfg_idx = (boot_cfg_idx == 0 ? 1 : 0);
    struct boot_cfg old_boot_cfg;
    int r = read_boot_cfg(old_boot_cfg_idx, &old_boot_cfg);
    if (r < 0) return r;
    if (!cc32xx_fs_spiffs_container_mount("/old",
                                          old_boot_cfg.fs_container_prefix))
      return -123;
    if (mgos_upd_merge_fs("/old", "/")) {
      r = 0;
      cfg->flags &= ~(BOOT_F_MERGE_SPIFFS);
    } else {
      r = -124;
    }
    mgos_vfs_umount("/old");
  }
  return 0;
}
Esempio n. 3
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;
}
Esempio n. 4
0
int main(void) {
  MAP_IntVTableBaseSet((unsigned long) &int_vectors[0]);
  MAP_IntMasterEnable();
  PRCMCC3200MCUInit();

/* Console UART init. */
#ifndef NO_DEBUG
  MAP_PRCMPeripheralClkEnable(DEBUG_UART_PERIPH, PRCM_RUN_MODE_CLK);
#if MIOT_DEBUG_UART == 0
  MAP_PinTypeUART(PIN_55, PIN_MODE_3); /* UART0_TX */
  MAP_PinTypeUART(PIN_57, PIN_MODE_3); /* UART0_RX */
#else
  MAP_PinTypeUART(PIN_07, PIN_MODE_5); /* UART1_TX */
  MAP_PinTypeUART(PIN_08, PIN_MODE_5); /* UART1_RX */
#endif
  MAP_UARTConfigSetExpClk(
      DEBUG_UART_BASE, MAP_PRCMPeripheralClockGet(DEBUG_UART_PERIPH),
      MIOT_DEBUG_UART_BAUD_RATE,
      (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));
  MAP_UARTFIFOLevelSet(DEBUG_UART_BASE, UART_FIFO_TX1_8, UART_FIFO_RX4_8);
  MAP_UARTFIFODisable(DEBUG_UART_BASE);
#endif

  dbg_puts("\r\n\n");

  if (sl_Start(NULL, NULL, NULL) < 0) abort();
  dbg_putc('S');

  int cidx = get_active_boot_cfg_idx();
  if (cidx < 0) abort();
  dbg_putc('0' + cidx);
  struct boot_cfg cfg;
  if (read_boot_cfg(cidx, &cfg) < 0) abort();

  dbg_puts(cfg.app_image_file);
  dbg_putc('@');
  print_addr(cfg.app_load_addr);

  /*
   * Zero memory before loading.
   * This should provide proper initialisation for BSS, wherever it is.
   */
  uint32_t *pstart = (uint32_t *) 0x20000000;
  uint32_t *pend = (&_text_start - 0x100 /* our stack */);
  for (uint32_t *p = pstart; p < pend; p++) *p = 0;

  if (load_image(cfg.app_image_file, (_u8 *) cfg.app_load_addr) != 0) {
    abort();
  }

  dbg_putc('.');

  sl_Stop(0);
  print_addr(*(((uint32_t *) cfg.app_load_addr) + 1));
  dbg_puts("\r\n\n");

  MAP_IntMasterDisable();
  MAP_IntVTableBaseSet(cfg.app_load_addr);

  run(cfg.app_load_addr); /* Does not return. */

  abort();

  return 0; /* not reached */
}
Esempio n. 5
0
static enum cc3200_init_result cc3200_init(void *arg) {
  mongoose_init();
  if (miot_uart_init(0, miot_uart_default_config(), NULL, NULL) == NULL) {
    return CC3200_INIT_UART_INIT_FAILED;
  }
  if (miot_uart_init(1, miot_uart_default_config(), NULL, NULL) == NULL) {
    return CC3200_INIT_UART_INIT_FAILED;
  }

  if (strcmp(MIOT_APP, "mongoose-iot") != 0) {
    LOG(LL_INFO, ("%s %s (%s)", MIOT_APP, build_version, build_id));
  }
  LOG(LL_INFO,
      ("Mongoose IoT Firmware %s (%s)", mg_build_version, mg_build_id));
  LOG(LL_INFO, ("RAM: %d total, %d free", miot_get_heap_size(),
                miot_get_free_heap_size()));

  int r = start_nwp();
  if (r < 0) {
    LOG(LL_ERROR, ("Failed to start NWP: %d", r));
    return CC3200_INIT_FAILED_TO_START_NWP;
  }

  g_boot_cfg_idx = get_active_boot_cfg_idx();
  if (g_boot_cfg_idx < 0 || read_boot_cfg(g_boot_cfg_idx, &g_boot_cfg) < 0) {
    return CC3200_INIT_FAILED_TO_READ_BOOT_CFG;
  }

  LOG(LL_INFO, ("Boot cfg %d: 0x%llx, 0x%u, %s @ 0x%08x, %s", g_boot_cfg_idx,
                g_boot_cfg.seq, g_boot_cfg.flags, g_boot_cfg.app_image_file,
                g_boot_cfg.app_load_addr, g_boot_cfg.fs_container_prefix));

  if (g_boot_cfg.flags & BOOT_F_FIRST_BOOT) {
    /* Tombstone the current config. If anything goes wrong between now and
     * commit, next boot will use the old one. */
    uint64_t saved_seq = g_boot_cfg.seq;
    g_boot_cfg.seq = BOOT_CFG_TOMBSTONE_SEQ;
    write_boot_cfg(&g_boot_cfg, g_boot_cfg_idx);
    g_boot_cfg.seq = saved_seq;
  }

  r = cc3200_fs_init(g_boot_cfg.fs_container_prefix);
  if (r < 0) {
    LOG(LL_ERROR, ("FS init error: %d", r));
    return CC3200_INIT_FS_INIT_FAILED;
  } else {
    /*
     * We aim to maintain at most 3 FS containers at all times.
     * Delete inactive FS container in the inactive boot configuration.
     */
    struct boot_cfg cfg;
    int inactive_idx = (g_boot_cfg_idx == 0 ? 1 : 0);
    if (read_boot_cfg(inactive_idx, &cfg) >= 0) {
      fs_delete_inactive_container(cfg.fs_container_prefix);
    }
  }

#if MIOT_ENABLE_UPDATER
  if (g_boot_cfg.flags & BOOT_F_FIRST_BOOT) {
    LOG(LL_INFO, ("Applying update"));
    r = miot_upd_apply_update();
    if (r < 0) {
      LOG(LL_ERROR, ("Failed to apply update: %d", r));
      return CC3200_INIT_UPDATE_FAILED;
    }
  }
#endif

  enum miot_init_result ir = mg_init();
  if (ir != MIOT_INIT_OK) {
    LOG(LL_ERROR, ("%s init error: %d", "MG", ir));
    return CC3200_INIT_MG_INIT_FAILED;
  }

#if MIOT_ENABLE_JS
  struct v7 *v7 = s_v7 = init_v7(&arg);

  ir = miot_init_js_all(v7);
  if (ir != MIOT_INIT_OK) {
    LOG(LL_ERROR, ("%s init error: %d", "JS", ir));
    return CC3200_INIT_MG_INIT_JS_FAILED;
  }
#endif

#if MIOT_ENABLE_JS
  miot_prompt_init(v7, get_cfg()->debug.stdout_uart);
#endif
  return CC3200_INIT_OK;
}
Esempio n. 6
0
static int sj_init() {
  struct v7 *v7 = s_v7;

  LOG(LL_INFO, ("Mongoose IoT Firmware %s", build_id));
  LOG(LL_INFO,
      ("RAM: %d total, %d free", sj_get_heap_size(), sj_get_free_heap_size()));

  int r = start_nwp();
  if (r < 0) {
    LOG(LL_ERROR, ("Failed to start NWP: %d", r));
    return 0;
  }

  int boot_cfg_idx = get_active_boot_cfg_idx();
  if (boot_cfg_idx < 0) return 0;
  struct boot_cfg boot_cfg;
  if (read_boot_cfg(boot_cfg_idx, &boot_cfg) < 0) return 0;

  LOG(LL_INFO, ("Boot cfg %d: 0x%llx, 0x%u, %s @ 0x%08x, %s", boot_cfg_idx,
                boot_cfg.seq, boot_cfg.flags, boot_cfg.app_image_file,
                boot_cfg.app_load_addr, boot_cfg.fs_container_prefix));

  uint64_t saved_seq = 0;
  if (boot_cfg.flags & BOOT_F_FIRST_BOOT) {
    /* Tombstone the current config. If anything goes wrong between now and
     * commit, next boot will use the old one. */
    saved_seq = boot_cfg.seq;
    boot_cfg.seq = BOOT_CFG_TOMBSTONE_SEQ;
    write_boot_cfg(&boot_cfg, boot_cfg_idx);
  }

  r = init_fs(boot_cfg.fs_container_prefix);
  if (r < 0) {
    LOG(LL_ERROR, ("FS init error: %d", r));
    if (boot_cfg.flags & BOOT_F_FIRST_BOOT) {
      revert_update(boot_cfg_idx, &boot_cfg);
    }
    return 0;
  }

  if (boot_cfg.flags & BOOT_F_FIRST_BOOT) {
    LOG(LL_INFO, ("Applying update"));
    if (apply_update(boot_cfg_idx, &boot_cfg) < 0) {
      revert_update(boot_cfg_idx, &boot_cfg);
    }
  }

  mongoose_init();

#ifndef CS_DISABLE_JS
  v7 = s_v7 = init_v7(&v7);

  /* Disable GC during JS API initialization. */
  v7_set_gc_enabled(v7, 0);
  sj_gpio_api_setup(v7);
  sj_i2c_api_setup(v7);
  sj_wifi_api_setup(v7);
  sj_timers_api_setup(v7);
#endif

  sj_v7_ext_api_setup(v7);
  sj_init_sys(v7);
  sj_wifi_init(v7);
#ifndef DISABLE_C_CLUBBY
  sj_clubby_init();
#endif

  sj_http_api_setup(v7);

#if !defined(DISABLE_C_CLUBBY) && !defined(CS_DISABLE_JS)
  sj_clubby_api_setup(v7);
#endif

  /* Common config infrastructure. Mongoose & v7 must be initialized. */
  init_device(v7);

  sj_updater_post_init(v7);
#ifndef DISABLE_C_CLUBBY
  init_updater_clubby(v7);
#endif

#ifndef CS_DISABLE_JS
  /* SJS initialized, enable GC back, and trigger it */
  v7_set_gc_enabled(v7, 1);
  v7_gc(v7, 1);

  v7_val_t res;
  if (v7_exec_file(v7, "sys_init.js", &res) != V7_OK) {
    fprintf(stderr, "Error: ");
    v7_fprint(stderr, v7, res);
  }
#endif

  LOG(LL_INFO, ("%s init done, RAM: %d free", "Sys", sj_get_free_heap_size()));

  if (!sj_app_init(v7)) {
    LOG(LL_ERROR, ("App init failed"));
    abort();
  }
  LOG(LL_INFO, ("%s init done, RAM: %d free", "App", sj_get_free_heap_size()));

  if (boot_cfg.flags & BOOT_F_FIRST_BOOT) {
    boot_cfg.seq = saved_seq;
    commit_update(boot_cfg_idx, &boot_cfg);
    clubby_updater_finish(0);
  } else {
    /*
     * If there is no update reply state, this will just be ignored.
     * But if there is, then update was rolled back and reply will be sent.
     */
    clubby_updater_finish(-1);
  }

#ifndef CS_DISABLE_JS
  sj_prompt_init(v7);
#endif
  return 1;
}