WindCharger: Refactors sysvar data access code.

Debug/printing code is now only part of uboot commands (do_fl*) for
sysvar.

sf_* functions are simply implementations that return error codes.

As per b/21089472

Change-Id: I5f3758a81cc8946d1e7794233903699f8e51e3e5
diff --git a/common/cmd_sysvar.c b/common/cmd_sysvar.c
index 49bab01..0353835 100644
--- a/common/cmd_sysvar.c
+++ b/common/cmd_sysvar.c
@@ -45,26 +45,69 @@
 };
 
 /*
- * print_msg - print the message string
+ * str_to_int - Converts a string into an int.
+ *
+ * Returns an error by setting "err" to something non-zero.
  */
-static void print_msg(char *msg, int idx) {
-  if (idx < 0) {
-    printf("SV: %s\n", msg);
-  } else {
-    printf("SV: System variables(%s) has been %s\n",
-          (idx < SYSVAR_RO_BUF) ? "RW" : "RO", msg);
+static int str_to_int(const char *str, int *err) {
+  int res = 0;
+  char *p;
+  for (p = str; *p != '\0'; ++p) {
+    switch (*p) {
+      case '0':
+      case '1':
+      case '2':
+      case '3':
+      case '4':
+      case '5':
+      case '6':
+      case '7':
+      case '8':
+      case '9':
+        res = res * 10 + (*p - '0');
+        break;
+      default:
+        if (err) {
+          *err = 1;
+        }
+        return res;
+    }
   }
+  return res;
 }
 
-/*
- * print_err - print the error message
- */
-static void print_err(char *err, int idx) {
-  if (idx < 0) {
-    printf("## Error: %s\n", err);
-  } else {
-    printf("## Error: failed to %s system variables(%s)\n",
-           err, (idx < SYSVAR_RO_BUF) ? "RW" : "RO");
+static void print_err(int code, void *arg) {
+  switch (code) {
+      case SYSVAR_CRC_ERR:
+        printf("## Error: CRC check failure on index %d\n", *(int*)arg);
+        break;
+      case SYSVAR_DELETE_ERR:
+        printf("## Error: failed to delete '%s'\n", (char*)arg);
+        break;
+      case SYSVAR_ERASE_ERR:
+        printf("## Error: erase failure on index %d\n", *(int*)arg);
+        break;
+      case SYSVAR_EXISTED_ERR:
+        printf("## Error: '%s' is already a read/write variable\n", (char*)arg);
+        break;
+      case SYSVAR_INDEX_ERR:
+        printf("## Error: invalid SPI flash device %d\n", *(int*)arg);
+        break;
+      case SYSVAR_READONLY_ERR:
+        printf("## Error: '%s' is a read only variable\n", (char*)arg);
+        break;
+      case SYSVAR_SET_ERR:
+        printf("## Error: '%s' not found\n", (char*)arg);
+        break;
+      case SYSVAR_SUCCESS:
+        break;
+      case SYSVAR_WRITE_ERR:
+        printf("## Error: unable to write to index %d\n", *(int*)arg);
+        break;
+      default:
+        /* Unknown error code. */
+        printf("## Error: code %d\n", code);
+        break;
   }
 }
 
@@ -72,10 +115,9 @@
  * data_recovery - system variables recovering routine
  */
 int data_recovery(struct sysvar_buf *buf, int idx) {
-  int i, j, ret, sector;
+  int i, j, ret = SYSVAR_SUCCESS, sector;
 
   /* load the system variables */
-  printf("SV: Recovering data");
   for (i = idx, j = idx + 1; i < idx + 2; i++, j--) {
     /* read the data from SPI flash */
     if (read_buff(flash_info, buf->data, sysvar_offset[i], buf->data_len))
@@ -87,33 +129,32 @@
       sector = __SYSVAR_ERASE_SECTOR(sysvar_offset[j]);
       ret = flash_erase(flash_info, sector, sector);
       if (ret) {
-        print_err("erase", j);
+        ret = SYSVAR_ERASE_ERR;
         goto recovery_err;
       }
 
       /* check crc32 and wc32 (write count) */
-      if (check_var(buf, SYSVAR_SAVE_MODE))
+      if (check_var(buf, SYSVAR_SAVE_MODE)) {
+        ret = SYSVAR_CRC_ERR;
         goto recovery_err;
+      }
 
       /* write system variables(RW) to SPI flash */
       ret = write_buff(flash_info, buf->data, sysvar_offset[j] + CFG_FLASH_BASE,
                        buf->data_len);
-      printf("\n");
       if (ret) {
-        print_err("write", j);
+        ret = SYSVAR_WRITE_ERR;
         goto recovery_err;
       }
 
       buf->loaded = true;
-      print_msg("Data recovery was completed", SYSVAR_MESSAGE);
-      return 0;
+      return SYSVAR_SUCCESS;
     }
   }
 
 recovery_err:
   clear_buf(buf);
-  printf("\n");
-  return 0;
+  return ret;
 }
 
 /*
@@ -137,9 +178,10 @@
   }
 
 load_err:
-  if (buf->failed[0] || buf->failed[1])
-    return data_recovery(buf, idx);
-  return 0;
+  if (buf->failed[0] || buf->failed[1]) {
+    return SYSVAR_LOAD_ERR;
+  }
+  return SYSVAR_SUCCESS;
 }
 
 /*
@@ -151,317 +193,28 @@
   /* save the system variables */
   for (j = 0; j < 2; j++) {
     i = idx[j];
-    printf("SV: Erasing SPI flash 0x%08lx - 0x%08lx\n",
-           sysvar_offset[i], sysvar_offset[i] + buf->data_len);
     sector = __SYSVAR_ERASE_SECTOR(sysvar_offset[i]);
     ret = flash_erase(flash_info, sector, sector);
     if (ret) {
-      print_err("erase", i);
-      return 1;
+      return SYSVAR_SAVE_ERR;
     }
 
     /* check crc32 and wc32 (write count) */
     if (check_var(buf, SYSVAR_SAVE_MODE)) {
-      print_err("save", SYSVAR_RO_BUF);
-      return 1;
+      return SYSVAR_CRC_ERR;
     }
 
     /* write system variables to SPI flash */
-    printf("SV: Writing to SPI flash");
     ret = write_buff(flash_info, buf->data, sysvar_offset[i] + CFG_FLASH_BASE,
                      buf->data_len);
-    printf("\n");
     if (ret) {
-      print_err("write", i);
-      return 1;
+      return SYSVAR_WRITE_ERR;
     }
   }
-  return 0;
+  return SYSVAR_SUCCESS;
 }
 
 /*
- * sf_loadvar - load the data from SPI flash to data buffer
- */
-int sf_loadvar(void) {
-  if (data_load(&rw_buf, SYSVAR_RW_BUF)) {
-    return 1;
-  }
-
-  /* move the data from data buffer to data list */
-  if (load_var(&rw_buf)) {
-    return 1;
-  }
-  rw_buf.loaded = true;
-  print_msg("loaded", SYSVAR_RW_BUF);
-
-  if (data_load(&ro_buf, SYSVAR_RO_BUF))
-    return 1;
-
-  /* move the data from data buffer to data list */
-  if (load_var(&ro_buf))
-    return 1;
-
-  ro_buf.loaded = true;
-  print_msg("loaded", SYSVAR_RO_BUF);
-  return 0;
-}
-
-/*
- * sf_savevar - save the data from data buffer to SPI flash
- */
-int sf_savevar(struct sysvar_buf *buf, int idx) {
-  int save_idx[2];
-
-  /* move the data from data list to data buffer */
-  if (save_var(buf))
-    return 1;
-
-  /* erase failed partition first
-   *  part0   part1       erase
-   *  -----   -----       -----
-   *    ok      ok        0, 1
-   *  failed    ok        0, 1
-   *    ok    failed      1, 0
-   *  failed  failed      0, 1
-   */
-  if (buf->failed[1]) {
-    save_idx[0] = idx + 1;
-    save_idx[1] = idx;
-  } else {
-    save_idx[0] = idx;
-    save_idx[1] = idx + 1;
-  }
-
-  /* save the data from data buffer to SPI flash */
-  if (data_save(buf, save_idx))
-    return 1;
-
-  printf("\n");
-  print_msg("saved", idx);
-  return 0;
-}
-
-/*
- * sf_getvar - get or print the system variable from data list
- */
-int sf_getvar(char *name, char *value, int len) {
-  struct sysvar_list *var = NULL;
-
-  if (name == NULL) {
-    /* print all system variables(RO) */
-    print_var(&ro_buf);
-    /* print all system variables(RW) */
-    print_var(&rw_buf);
-    return 0;
-  }
-
-  /* find the system variable(RO) */
-  var = find_var(&ro_buf, name);
-  if (var != NULL)
-    goto get_data;
-
-  /* find the system variable(RW) */
-  var = find_var(&rw_buf, name);
-  if (var != NULL)
-    goto get_data;
-
-  /* system variable not found */
-  printf("## SYSVAR: '%s' not found\n", name);
-  return 1;
-
-get_data:
-  return get_var(var, name, value, len);
-}
-
-/*
- * sf_setvar - add or delete the system variable in data list
- */
-int sf_setvar(struct sysvar_buf *buf, int idx, char *name, char *value) {
-  struct sysvar_list *var = NULL;
-  int ret = 0;
-
-  if (name != NULL) {
-    if (idx < SYSVAR_RO_BUF) {
-      /* read only variable? */
-      var = find_var(&ro_buf, name);
-    } else {
-      /* variable existed? */
-      var = find_var(&rw_buf, name);
-    }
-
-    if (var != NULL) {
-      if (idx < SYSVAR_RO_BUF) {
-        printf("## Error: '%s' is read only variable\n", name);
-        return 1;
-      } else {
-        printf("## Error: '%s' is not read only variable\n", name);
-        return 1;
-      }
-    }
-
-    var = find_var(buf, name);
-    if (var != NULL) {
-      /* delete system variable */
-      ret = delete_var(buf, var);
-      if (ret != SYSVAR_SUCCESS) {
-        printf("## Error: failed to delete '%s'\n", name);
-        return 1;
-      }
-
-      /* add system variable */
-      if (value != NULL) {
-        ret = set_var(buf, name, value);
-        if (ret == 0)
-          print_msg("added", idx);
-      } else {
-        print_msg("deleted", idx);
-      }
-    } else {
-      /* add system variable */
-      if (value != NULL) {
-        ret = set_var(buf, name, value);
-        if (ret == 0)
-          print_msg("added", idx);
-      } else {
-        printf("## Error: '%s' not found\n", name);
-        ret = 1;
-      }
-    }
-  } else {
-    /* delete all of system variables */
-    ret = clear_var(buf);
-    if (ret == 0)
-      print_msg("deleted", idx);
-  }
-  return ret;
-}
-
-/*
- * do_flloadvar - load system variables from SPI flash
- *
- * sf_loadvar command:
- *    sf_loadvar - load system variables from persistent storage
- */
-int do_flloadvar(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) {
-  /* load system variables from SPI flash */
-  return sf_loadvar();
-}
-
-U_BOOT_CMD(
-  loadvar, 1, 0, do_flloadvar,
-  "loadvar   - load system variables\n",
-  "    - load system variables from SPI flash\n"
-);
-
-/*
- * do_flsavevar - save system variables(RW) to SPI flash
- *
- * sf_savevar command:
- *    sf_savevar - save system variables(RW) to SPI flash
- */
-int do_flsavevar(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
-{
-  /* save system variables(RW) */
-  return sf_savevar(&rw_buf, SYSVAR_RW_BUF);
-}
-
-U_BOOT_CMD(
-  savevar, 1, 0, do_flsavevar,
-  "savevar   - save system variables(RW)\n",
-  "    - save system variables(RW) to SPI flash\n"
-);
-
-/*
- * do_flprintvar - print system variables
- *
- * printvar command:
- *    printvar name - print system variable with name
- *    printvar      - print all system variables
- */
-int do_flprintvar(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) {
-  char value[SYSVAR_VALUE];
-
-  if (argv[1] == NULL) {
-    /* print all system variables */
-    sf_getvar(NULL, NULL, 0);
-
-    printf("\nSV: System Variables(RO): %d/%d bytes\n",
-      ro_buf.used_len, ro_buf.total_len);
-    printf("SV: System Variables(RW): %d/%d bytes\n",
-      rw_buf.used_len, rw_buf.total_len);
-  } else {
-    /* get a system variable */
-    if (sf_getvar(argv[1], value, SYSVAR_VALUE) == 0) {
-      puts(argv[1]);
-      putc('=');
-      /* puts value in case CONFIG_SYS_PBSIZE < SYSVAR_VALUE */
-      puts(value);
-      putc('\n');
-      printf("\nSV: System Variable: %d bytes\n",
-        (int)(SYSVAR_NAME + 2 + strlen(value)));
-    }
-  }
-  return 0;
-}
-
-U_BOOT_CMD(
-  printvar, 2, 0, do_flprintvar,
-  "printvar   - print system variables\n",
-  "    - print values of all system variables\n"
-  "printvar name ...\n"
-  "    - print value of system variable 'name'\n"
-);
-
-int set_sysvar_uboot(const char *var, const char *name) {
-  const char *uboot_name = get_uboot_name(var);
-  if (uboot_name) {
-    setenv(uboot_name, name);
-  }
-}
-
-/*
- * do_flsetvar - add or delete system variables(RW)
- *
- * sf_setvar command:
- *    sf_setvar name value - add system variable with name:value
- *    sf_setvar name       - delete system variable with name
- *    sf_setvar            - delete all system variables
- */
-int do_flsetvar(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) {
-  int ret = 0;
-
-  if (argc == 3) {
-    /* add a system variable(RW) */
-    ret = sf_setvar(&rw_buf, SYSVAR_RW_BUF, argv[1], argv[2]);
-    if (ret == SYSVAR_SUCCESS) {
-      set_sysvar_uboot(argv[1], argv[2]);
-    }
-  } else if (argc == 2) {
-    /* delete a system variable(RW) */
-    ret = sf_setvar(&rw_buf, SYSVAR_RW_BUF, argv[1], NULL);
-    if (ret == SYSVAR_SUCCESS) {
-      set_sysvar_uboot(argv[1], NULL);
-    }
-  } else {
-    /* delete all system variables(RW) */
-    ret = sf_setvar(&rw_buf, SYSVAR_RW_BUF, NULL, NULL);
-    delete_uboot_vars();
-  }
-  return ret;
-}
-
-U_BOOT_CMD(
-  setvar, 3, 0, do_flsetvar,
-  "setvar   - set system variables(RW)\n",
-  "setvar name value ...\n"
-  "    - set system variable(RW) 'name' to 'value ...'\n"
-  "setvar name\n"
-  "    - delete system variable(RW) 'name'\n"
-  "setvar\n"
-  "    - delete all system variables(RW)\n"
-);
-
-/*
  * sysvar_dump - dump the data buffer in binary/ascii format
  */
 void sysvar_dump(struct sysvar_buf *buf, int idx, bool load) {
@@ -508,23 +261,16 @@
  */
 int sysvar_io(int argc, char *argv[]) {
   struct sysvar_buf *buf;
-  int i, idx, sector, ret = 0;
+  int i, idx, sector, ret = 0, str_to_int_err = 0;
 
-  if (strcmp(argv[1], "0") == 0) {
-    idx = 0;
+  idx = str_to_int(argv[1], &str_to_int_err);
+  if (str_to_int_err || idx < 0 || idx > 3) {
+    return SYSVAR_INDEX_ERR;
+  }
+  if (idx < 2) {
     buf = &rw_buf;
-  } else if (strcmp(argv[1], "1") == 0) {
-    idx = 1;
-    buf = &rw_buf;
-  } else if (strcmp(argv[1], "2") == 0) {
-    idx = 2;
-    buf = &ro_buf;
-  } else if (strcmp(argv[1], "3") == 0) {
-    idx = 3;
-    buf = &ro_buf;
   } else {
-    print_err("invalid SPI flash device", SYSVAR_MESSAGE);
-    return 1;
+    buf = &ro_buf;
   }
 
   if (strcmp(argv[0], "write") == 0) {
@@ -535,11 +281,16 @@
     /* write the data buffer to spi_flash */
     ret = write_buff(flash_info, buf->data, sysvar_offset[idx] + CFG_FLASH_BASE,
                      buf->data_len);
-    printf("\n");
+    if (ret) {
+      ret = SYSVAR_WRITE_ERR;
+    }
   } else if (strcmp(argv[0], "erase") == 0) {
     /* erase spi_flash */
     sector = __SYSVAR_ERASE_SECTOR(sysvar_offset[idx]);
     ret = flash_erase(flash_info, sector, sector);
+    if (ret) {
+      ret = SYSVAR_ERASE_ERR;
+    }
   }
 
   if (ret == 0) {
@@ -557,31 +308,327 @@
   return ret;
 }
 
+////////////////////////////////////////////////////////////////////////////////
+//  Sysvar Flash Impl Functions
+////////////////////////////////////////////////////////////////////////////////
+
+/*
+ * sf_loadvar - load the data from SPI flash to data buffer
+ */
+int sf_loadvar(struct sysvar_buf *buf, int idx) {
+  if (data_load(buf, idx)) {
+    /* TODO(awdavies): Inform the user of potential data recovery failure. */
+    data_recovery(buf, idx);
+  }
+
+  /* move the data from data buffer to data list */
+  if (load_var(buf)) {
+    return SYSVAR_LOAD_ERR;
+  }
+  buf->loaded = true;
+  return SYSVAR_SUCCESS;
+}
+
+/*
+ * sf_savevar - save the data from data buffer to SPI flash
+ */
+int sf_savevar(struct sysvar_buf *buf, int idx) {
+  int ret;
+  int save_idx[2];
+
+  /* move the data from data list to data buffer */
+  if (save_var(buf))
+    return SYSVAR_SAVE_ERR;
+
+  /* erase failed partition first
+   *  part0   part1       erase
+   *  -----   -----       -----
+   *    ok      ok        0, 1
+   *  failed    ok        0, 1
+   *    ok    failed      1, 0
+   *  failed  failed      0, 1
+   */
+  if (buf->failed[1]) {
+    save_idx[0] = idx + 1;
+    save_idx[1] = idx;
+  } else {
+    save_idx[0] = idx;
+    save_idx[1] = idx + 1;
+  }
+
+  /* save the data from data buffer to SPI flash */
+  if ((ret = data_save(buf, save_idx)))
+    return ret;
+  return SYSVAR_SUCCESS;
+}
+
+/*
+ * sf_getvar - get or print the system variable from data list
+ */
+int sf_getvar(char *name, char *value, int len) {
+  struct sysvar_list *var = NULL;
+
+  if (name == NULL) {
+    /* print all system variables(RO) */
+    print_var(&ro_buf);
+    /* print all system variables(RW) */
+    print_var(&rw_buf);
+    return SYSVAR_SUCCESS;
+  }
+
+  /* find the system variable(RO) */
+  var = find_var(&ro_buf, name);
+  if (var != NULL)
+    goto get_data;
+
+  /* find the system variable(RW) */
+  var = find_var(&rw_buf, name);
+  if (var != NULL)
+    goto get_data;
+
+  /* system variable not found */
+  return SYSVAR_GET_ERR;
+
+get_data:
+  return get_var(var, name, value, len);
+}
+
+/*
+ * sf_setvar - add or delete the system variable in data list
+ */
+int sf_setvar(struct sysvar_buf *buf, int idx, char *name, char *value) {
+  struct sysvar_list *var = NULL;
+  int ret = 0;
+
+  if (name != NULL) {
+    if (idx < SYSVAR_RO_BUF) {
+      /* read only variable? */
+      var = find_var(&ro_buf, name);
+    } else {
+      /* variable existed? */
+      var = find_var(&rw_buf, name);
+    }
+
+    if (var != NULL) {
+      if (idx < SYSVAR_RO_BUF) {
+        return SYSVAR_READONLY_ERR;
+      } else {
+        return SYSVAR_EXISTED_ERR;
+      }
+    }
+
+    var = find_var(buf, name);
+    if (var != NULL) {
+      /* delete system variable */
+      ret = delete_var(buf, var);
+      if (ret != SYSVAR_SUCCESS) {
+        return SYSVAR_DELETE_ERR;
+      }
+
+      /* add system variable */
+      if (value != NULL) {
+        ret = set_var(buf, name, value);
+      }
+    } else {
+      /* add system variable */
+      if (value != NULL) {
+        ret = set_var(buf, name, value);
+      } else {
+        ret = SYSVAR_SET_ERR;
+      }
+    }
+  } else {
+    /* delete all of system variables */
+    ret = clear_var(buf);
+  }
+  return ret;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//  Uboot Commands
+////////////////////////////////////////////////////////////////////////////////
+
+/*
+ * do_flloadvar - load system variables from SPI flash
+ *
+ * sf_loadvar command:
+ *    sf_loadvar - load system variables from persistent storage
+ */
+int do_flloadvar(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) {
+  /* load system variables from SPI flash */
+  int res, idx;
+  idx = SYSVAR_RW_BUF;
+  res = sf_loadvar(&rw_buf, idx);
+  print_err(res, &idx);
+  if (res != SYSVAR_SUCCESS) {
+    return res;
+  }
+  idx = SYSVAR_RO_BUF;
+  res = sf_loadvar(&ro_buf, idx);
+  print_err(res, &idx);
+  return res;
+}
+
+U_BOOT_CMD(
+  loadvar, 1, 0, do_flloadvar,
+  "loadvar   - load system variables\n",
+  "    - load system variables from SPI flash\n"
+);
+
+/*
+ * do_flsavevar - save system variables(RW) to SPI flash
+ */
+int do_flsavevar(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+  /* save system variables(RW) */
+  printf("SV: Saving. . .\n");
+  int idx = SYSVAR_RW_BUF;
+  int res = sf_savevar(&rw_buf, idx);
+  print_err(res, &idx);
+  return res;
+}
+
+U_BOOT_CMD(
+  savevar, 1, 0, do_flsavevar,
+  "savevar   - save system variables(RW)\n",
+  "    - save system variables(RW) to SPI flash\n"
+);
+
+/*
+ * do_flprintvar - print system variables
+ *
+ * printvar command:
+ *    printvar name - print system variable with name
+ *    printvar      - print all system variables
+ */
+int do_flprintvar(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) {
+  char value[SYSVAR_VALUE];
+
+  if (argv[1] == NULL) {
+    /* print all system variables */
+    sf_getvar(NULL, NULL, 0);
+
+    printf("\nSV: System Variables(RO): %d/%d bytes\n",
+      ro_buf.used_len, ro_buf.total_len);
+    printf("SV: System Variables(RW): %d/%d bytes\n",
+      rw_buf.used_len, rw_buf.total_len);
+  } else {
+    /* get a system variable */
+    if (sf_getvar(argv[1], value, SYSVAR_VALUE) == 0) {
+      puts(argv[1]);
+      putc('=');
+      /* puts value in case CONFIG_SYS_PBSIZE < SYSVAR_VALUE */
+      puts(value);
+      putc('\n');
+      printf("\nSV: System Variable: %d bytes\n",
+        (int)(SYSVAR_NAME + 2 + strlen(value)));
+    } else {
+      printf("## SYSVAR: '%s' not found\n", argv[1]);
+    }
+  }
+  return SYSVAR_SUCCESS;
+}
+
+U_BOOT_CMD(
+  printvar, 2, 0, do_flprintvar,
+  "printvar   - print system variables\n",
+  "    - print values of all system variables\n"
+  "printvar name ...\n"
+  "    - print value of system variable 'name'\n"
+);
+
+void set_sysvar_uboot(const char *var, const char *name) {
+  char *uboot_name = get_uboot_name(var);
+  if (uboot_name) {
+    setenv(uboot_name, name);
+  }
+}
+
+/*
+ * do_flsetvar - add or delete system variables(RW)
+ *
+ * setvar command:
+ *    setvar name value - add system variable with name:value
+ *    setvar name       - delete system variable with name
+ *    setvar            - delete all system variables
+ */
+int do_flsetvar(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) {
+  int ret = 0;
+
+  if (argc == 3) {
+    /* add a system variable(RW) */
+    printf("SV: adding %s\n", argv[1]);
+    ret = sf_setvar(&rw_buf, SYSVAR_RW_BUF, argv[1], argv[2]);
+    if (ret == SYSVAR_SUCCESS) {
+      set_sysvar_uboot(argv[1], argv[2]);
+    }
+  } else if (argc == 2) {
+    /* delete a system variable(RW) */
+    printf("SV: deleting %s\n", argv[1]);
+    ret = sf_setvar(&rw_buf, SYSVAR_RW_BUF, argv[1], NULL);
+    if (ret == SYSVAR_SUCCESS) {
+      set_sysvar_uboot(argv[1], NULL);
+    }
+  } else {
+    /* delete all system variables(RW) */
+    printf("SV: deleting all RW vars. . .\n");
+    ret = sf_setvar(&rw_buf, SYSVAR_RW_BUF, NULL, NULL);
+    delete_uboot_vars();
+  }
+  print_err(ret, argc > 1 ? argv[1] : NULL);
+  return ret;
+}
+
+U_BOOT_CMD(
+  setvar, 3, 0, do_flsetvar,
+  "setvar   - set system variables(RW)\n",
+  "setvar name value ...\n"
+  "    - set system variable(RW) 'name' to 'value ...'\n"
+  "setvar name\n"
+  "    - delete system variable(RW) 'name'\n"
+  "setvar\n"
+  "    - delete all system variables(RW)\n"
+);
+
 /*
  * do_flsysvar - system variable debug functions
  */
 int do_flsysvar(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) {
+  int ret = 0;
+  int idx;
+  void *err_arg = NULL;
   if (argc < 2)
     goto usage;
 
   if (strcmp(argv[1], "set") == 0) {
     if (argc == 4) {
       /* add a system variable(RO) */
-      return sf_setvar(&ro_buf, SYSVAR_RO_BUF, argv[2], argv[3]);
+      printf("SV: adding %s\n", argv[2]);
+      ret = sf_setvar(&ro_buf, SYSVAR_RO_BUF, argv[2], argv[3]);
     } else if (argc == 3) {
       /* delete a system variable(RO) */
-      return sf_setvar(&ro_buf, SYSVAR_RO_BUF, argv[2], NULL);
+      printf("SV: deleting %s\n", argv[2]);
+      ret = sf_setvar(&ro_buf, SYSVAR_RO_BUF, argv[2], NULL);
     } else if (argc == 2) {
       /* delete all system variables(RO) */
-      return sf_setvar(&ro_buf, SYSVAR_RO_BUF, NULL, NULL);
+      printf("SV: deleting all RO vars. . .\n");
+      ret = sf_setvar(&ro_buf, SYSVAR_RO_BUF, NULL, NULL);
     } else {
       goto usage;
     }
+    if (argc > 2) {
+      err_arg = argv[2];
+    }
+    goto err_handle;
   }
 
   if (strcmp(argv[1], "save") == 0 && argc == 2) {
     /* save system variables(RO) */
-    return sf_savevar(&ro_buf, SYSVAR_RO_BUF);
+    printf("SV: saving RO vars. . .\n");
+    idx = SYSVAR_RO_BUF;
+    ret = sf_savevar(&ro_buf, idx);
+    err_arg = &idx;
+    goto err_handle;
   }
 
   if (strcmp(argv[1], "dump") == 0 && argc == 3) {
@@ -594,14 +641,20 @@
     } else {
       goto usage;
     }
-    return 0;
+    return SYSVAR_SUCCESS;
   }
 
   if ((strcmp(argv[1], "read") == 0 && argc == 3) ||
       (strcmp(argv[1], "write") == 0 && argc == 3) ||
-      (strcmp(argv[1], "erase") == 0 && argc == 3))
-    return sysvar_io(argc - 1, argv + 1);
+      (strcmp(argv[1], "erase") == 0 && argc == 3)) {
+    ret = sysvar_io(argc - 1, argv + 1);
+    idx = str_to_int(argv[2], NULL);
+    err_arg = &idx;
+  }
 
+err_handle:
+  print_err(ret, err_arg);
+  return ret;
 usage:
   printf("Usage:\n%s\n", cmdtp->usage);
   return 1;
@@ -628,6 +681,10 @@
   "    - erase data on SPI flash 0|1|2|3\n"
 );
 
+////////////////////////////////////////////////////////////////////////////////
+//  Sysvar/Uboot Integration
+////////////////////////////////////////////////////////////////////////////////
+
 /*
  * sysvar_buf_init - Initializes a sysvar_buf struct.
  */
@@ -671,15 +728,16 @@
 }
 
 int sysvar_init(void) {
-  printf("sysvar_init. . .\n");
+  printf("sysvar_init. . . ");
   if (sysvar_buf_init(&rw_buf, false) || sysvar_buf_init(&ro_buf, true) ||
-      sf_loadvar()) {
+      sf_loadvar(&rw_buf, SYSVAR_RW_BUF) ||
+      sf_loadvar(&ro_buf, SYSVAR_RO_BUF)) {
     printf("init failure!\n");
     return SYSVAR_MEMORY_ERR;
   }
   sysvar_env_init(&rw_buf);
   sysvar_env_init(&ro_buf);
-  printf("init success!\n");
+  printf("success!\n");
   return SYSVAR_SUCCESS;
 }
 
@@ -711,3 +769,4 @@
     setenv(su_mappings[i].uboot_name, NULL);
   }
 }
+
diff --git a/common/hush.c b/common/hush.c
index feb5627..c8549ff 100755
--- a/common/hush.c
+++ b/common/hush.c
@@ -3194,7 +3194,11 @@
 				code = 0;
 				/* XXX hackish way to not allow exit from main loop */
 				if (inp->peek == file_peek) {
-					printf("exit not allowed from main input shell.\n");
+					/*
+					 * TODO(awdavies) Commented out due to negative sysvar ret
+					 * codes.
+					 */
+					/* printf("exit not allowed from main input shell.\n"); */
 					continue;
 				}
 				break;
diff --git a/include/sysvar.h b/include/sysvar.h
index 855a101..301ea55 100644
--- a/include/sysvar.h
+++ b/include/sysvar.h
@@ -68,6 +68,7 @@
 #define SYSVAR_READONLY_ERR -13
 #define SYSVAR_EXISTED_ERR  -14
 #define SYSVAR_DEBUG_ERR    -15
+#define SYSVAR_INDEX_ERR    -16
 
 #define PAGE_SIZE           256
 #define SYSVAR_VALUE        2048