Merge changes I14921481,Icf51ed24,I5f3758a8

* changes:
  WindCharger: Adds shared name when editing sysvar/uboot env.
  WindCharger: Fixes up shared variable behavior.
  WindCharger: Refactors sysvar data access code.
diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
index a34f20f..10673b8 100755
--- a/common/cmd_nvedit.c
+++ b/common/cmd_nvedit.c
@@ -130,7 +130,7 @@
 			if (k < 0) {
 				continue;
 			}
-			if (is_sysvar_shared(name)) {
+			if (get_sysvar_shared(name)) {
 				puts(">>> ");
 			}
 			puts (name);
@@ -393,10 +393,16 @@
 		printf ("Usage:\n%s\n", cmdtp->usage);
 		return 1;
 	}
-	if (argc >= 2 && is_sysvar_shared(argv[1])) {
-		printf("ERR: %s is a sysvar-shared variable.\n"
-			"     Please use setvar/sysvar instead\n", argv[1]);
-		return 1;
+	if (argc >= 2) {
+		const char *name = get_sysvar_shared(argv[1]);
+		if (name) {
+			printf("ERR: %s is a sysvar-shared variable.\n"
+				"     Please edit '%s' using setvar/sysvar "
+				"instead\n",
+				argv[1],
+				name);
+			return 1;
+		}
 	}
 
 	return _do_setenv (flag, argc, argv);
diff --git a/common/cmd_sysvar.c b/common/cmd_sysvar.c
index 49bab01..134a370 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,76 +308,9 @@
   return ret;
 }
 
-/*
- * do_flsysvar - system variable debug functions
- */
-int do_flsysvar(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) {
-  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]);
-    } else if (argc == 3) {
-      /* delete a system variable(RO) */
-      return 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);
-    } else {
-      goto usage;
-    }
-  }
-
-  if (strcmp(argv[1], "save") == 0 && argc == 2) {
-    /* save system variables(RO) */
-    return sf_savevar(&ro_buf, SYSVAR_RO_BUF);
-  }
-
-  if (strcmp(argv[1], "dump") == 0 && argc == 3) {
-    if (strcmp(argv[2], "rw") == 0) {
-      /* dump data in data buffer(RW) */
-      sysvar_dump(&rw_buf, SYSVAR_RW_BUF, true);
-    } else if (strcmp(argv[2], "ro") == 0) {
-      /* dump data in data buffer(RO) */
-      sysvar_dump(&ro_buf, SYSVAR_RO_BUF, true);
-    } else {
-      goto usage;
-    }
-    return 0;
-  }
-
-  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);
-
-usage:
-  printf("Usage:\n%s\n", cmdtp->usage);
-  return 1;
-}
-
-U_BOOT_CMD(
-  sysvar, 4, 0, do_flsysvar,
-  "sysvar   - system variable debug functions\n",
-  "set name value\n"
-  "    - set system variable(RO) 'name' to 'value ...'\n"
-  "sysvar set name\n"
-  "    - delete system variable(RO) 'name'\n"
-  "sysvar set\n"
-  "    - delete all system variables(RO)\n"
-  "sysvar save\n"
-  "    - save system variables(RO) to SPI flash\n"
-  "sysvar dump rw|ro\n"
-  "    - dump data in data buffer\n"
-  "sysvar read 0|1|2|3\n"
-  "    - read data from SPI flash 0|1|2|3 to data buffer\n"
-  "sysvar write 0|1|2|3\n"
-  "    - write data from data buffer to SPI flash 0|1|2|3\n"
-  "sysvar erase 0|1|2|3\n"
-  "    - erase data on SPI flash 0|1|2|3\n"
-);
+////////////////////////////////////////////////////////////////////////////////
+//  Sysvar/Uboot Integration
+////////////////////////////////////////////////////////////////////////////////
 
 /*
  * sysvar_buf_init - Initializes a sysvar_buf struct.
@@ -661,7 +345,32 @@
   return SYSVAR_SUCCESS;
 }
 
-static void sysvar_env_init(struct sysvar_buf *buf) {
+/*
+ * sysvar_env_clear_shared - Takes sysvar buf and clears anything that may be
+ * mapped to the uboot env.  Does not delete any sysvar variables.
+ */
+static void sysvar_env_clear_shared(struct sysvar_buf *buf) {
+  struct sysvar_list *curr = buf->list->next;
+  while (curr != NULL) {
+    /* Only clear env variables for shared vars. */
+    set_sysvar_uboot(curr->name, NULL);
+    curr = curr->next;
+  }
+}
+
+/*
+ * sysvar_uboot_env_clear - Clears all potential uboot shared variables
+ * from the environment.
+ */
+void sysvar_uboot_env_clear(void) {
+  int i;
+  for (i = 0; i < ARRAY_SIZE(su_mappings); ++i) {
+    setenv(su_mappings[i].uboot_name, NULL);
+  }
+}
+
+/* Helper function for sysvar_uboot_env_load. */
+static void _sysvar_uboot_env_load(struct sysvar_buf *buf) {
   struct sysvar_list *curr = buf->list->next;
   while (curr != NULL) {
     /* Should only set env variables for special vars. */
@@ -670,28 +379,50 @@
   }
 }
 
+/*
+ * sysvar_uboot_env_load - Loads sysvar/uboot shared variables to the
+ * uboot environment.
+ */
+void sysvar_uboot_env_load(void) {
+  _sysvar_uboot_env_load(&ro_buf);
+  _sysvar_uboot_env_load(&rw_buf);
+}
+
 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");
+  sysvar_uboot_env_load();
+  printf("success!\n");
   return SYSVAR_SUCCESS;
 }
 
-int is_sysvar_shared(const char *var) {
+/*
+ * get_sysvar_shared - Determines if there's a mapping from sysvar -> uboot or
+ * vice versa.
+ *
+ * If there is a mapping:
+ *   If given a sysvar name, returns the uboot env name that the sysvar name
+ *   maps to.  If given a uboot env name, returns the sysvar name that it maps
+ *   to.
+ *
+ * If there is no mapping, returns NULL.
+ */
+const char *get_sysvar_shared(const char *var) {
   int i;
   for (i = 0; i < ARRAY_SIZE(su_mappings); ++i) {
-    if (strcmp(var, su_mappings[i].uboot_name) == 0 ||
-        strcmp(var, su_mappings[i].sysvar_name) == 0) {
-      return true;
+    if (strcmp(var, su_mappings[i].uboot_name) == 0) {
+      return su_mappings[i].sysvar_name;
+    }
+    if (strcmp(var, su_mappings[i].sysvar_name) == 0) {
+      return su_mappings[i].uboot_name;
     }
   }
-  return false;
+  return NULL;
 }
 
 const char *get_uboot_name(const char *sysvar_name) {
@@ -704,10 +435,381 @@
   return NULL;
 }
 
-void delete_uboot_vars(void) {
-  int i;
-  for (i = 0; i < ARRAY_SIZE(su_mappings); ++i) {
-    setenv(su_mappings[i].sysvar_name, NULL);
-    setenv(su_mappings[i].uboot_name, NULL);
+/*
+ * set_sysvar_uboot - Sets the given variable to the value specified in the
+ * uboot env if sysvar name is shared with uboot.
+ */
+void set_sysvar_uboot(const char *var, const char *value) {
+  char *uboot_name = get_uboot_name(var);
+  if (uboot_name) {
+    printf(">>> mapping SV:'%s' to UB:'%s' . . .\n", var, uboot_name);
+    setenv(uboot_name, value);
   }
 }
+
+////////////////////////////////////////////////////////////////////////////////
+//  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"
+);
+
+/*
+ * 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");
+    sysvar_env_clear_shared(&rw_buf);
+    ret = sf_setvar(&rw_buf, SYSVAR_RW_BUF, NULL, NULL);
+  }
+  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) */
+      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) */
+      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) */
+      printf("SV: deleting all RO vars. . .\n");
+      sysvar_env_clear_shared(&ro_buf);
+      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) */
+    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) {
+    if (strcmp(argv[2], "rw") == 0) {
+      /* dump data in data buffer(RW) */
+      sysvar_dump(&rw_buf, SYSVAR_RW_BUF, true);
+    } else if (strcmp(argv[2], "ro") == 0) {
+      /* dump data in data buffer(RO) */
+      sysvar_dump(&ro_buf, SYSVAR_RO_BUF, true);
+    } else {
+      goto usage;
+    }
+    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)) {
+    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;
+}
+
+U_BOOT_CMD(
+  sysvar, 4, 0, do_flsysvar,
+  "sysvar   - system variable debug functions\n",
+  "set name value\n"
+  "    - set system variable(RO) 'name' to 'value ...'\n"
+  "sysvar set name\n"
+  "    - delete system variable(RO) 'name'\n"
+  "sysvar set\n"
+  "    - delete all system variables(RO)\n"
+  "sysvar save\n"
+  "    - save system variables(RO) to SPI flash\n"
+  "sysvar dump rw|ro\n"
+  "    - dump data in data buffer\n"
+  "sysvar read 0|1|2|3\n"
+  "    - read data from SPI flash 0|1|2|3 to data buffer\n"
+  "sysvar write 0|1|2|3\n"
+  "    - write data from data buffer to SPI flash 0|1|2|3\n"
+  "sysvar erase 0|1|2|3\n"
+  "    - erase data on SPI flash 0|1|2|3\n"
+);
diff --git a/common/env_dataflash.c b/common/env_dataflash.c
index 0b77d99..aa4f4fa 100755
--- a/common/env_dataflash.c
+++ b/common/env_dataflash.c
@@ -58,9 +58,11 @@
 /* env must be copied to do not alter env structure in memory*/
 unsigned char temp[CFG_ENV_SIZE];
 int i;
-	/* Delete special sysvar-only variables. */
-	delete_uboot_vars();
+	/* Deletes anything that can be shared with sysvar, then restores it. */
+	sysvar_uboot_env_clear();
 	memcpy(temp, env_ptr, CFG_ENV_SIZE);
+	env_restore_defaults();
+	sysvar_uboot_env_load();
 	return write_dataflash (CFG_ENV_ADDR, (unsigned long)temp, CFG_ENV_SIZE);
 }
 
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/common.h b/include/common.h
index 2d7aa6c..9865222 100755
--- a/include/common.h
+++ b/include/common.h
@@ -219,9 +219,10 @@
 #define MAC_ADDR1_SV "MAC_ADDR1"
 #define MAC_ADDR1_UB "ethaddr"
 int sysvar_init(void);
-int is_sysvar_shared(const char *var);
+const char *get_sysvar_shared(const char *var);
 const char *get_uboot_name(const char *sysvar_name);
-void delete_uboot_vars(void);
+void sysvar_uboot_env_clear(void);
+void sysvar_uboot_env_load(void);
 
 /* common/env_common.c */
 int env_restore_defaults(void);
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