| /* Copyright 2015 Google Inc. All Rights Reserved. |
| * |
| * Note: flash_erase usage in here sends start and end as the same address. |
| * This is because the size of each sysvar env is a single erase-block (64k). |
| * The flash_erase function includes the addresses under the "last" param as |
| * part of the erase section, meaning inclusion of 0x8 as an address will erase |
| * 0x8 up to 0x9 (64k). 0x9 cannot be included as the end address because it is |
| * not in a sector boundary. |
| */ |
| #include <sysvar.h> |
| |
| #include <asm/io.h> |
| #include <common.h> |
| #include <config.h> |
| #include <command.h> |
| #include <flash.h> |
| |
| struct sysvar_uboot { |
| const char *sysvar_name; |
| const char *uboot_name; |
| }; |
| |
| static const struct sysvar_uboot su_mappings[] = { |
| { |
| .sysvar_name = ACTIVATED_KERNEL_NAME_SV, |
| .uboot_name = ACTIVATED_KERNEL_NAME_UB, |
| }, |
| { |
| .sysvar_name = MAC_ADDR1_SV, |
| .uboot_name = MAC_ADDR1_UB, |
| }, |
| { |
| .sysvar_name = FAILOVER_THRESHOLD_SV, |
| .uboot_name = FAILOVER_THRESHOLD_UB, |
| }, |
| }; |
| |
| // Some bit twiddling for erasing the correct sector on Atheros flash. This |
| // only erases multiples of 64kb. |
| #define __SYSVAR_ERASE_SECTOR(x) (((x) >> 16) & 0xff) |
| |
| // Board-based implementation supplies pointer to flash info. |
| extern flash_info_t flash_info[]; |
| struct sysvar_buf ro_buf; |
| struct sysvar_buf rw_buf; |
| |
| const long sysvar_offset[SYSVAR_SPI_BLOCK] = { |
| SYSVAR_RW_OFFSET0, SYSVAR_RW_OFFSET1, SYSVAR_RO_OFFSET0, SYSVAR_RO_OFFSET1 |
| }; |
| |
| /* |
| * str_to_int - Converts a string into an int. |
| * |
| * Returns an error by setting "err" to something non-zero. |
| */ |
| 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; |
| } |
| |
| 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; |
| } |
| } |
| |
| /* |
| * data_recovery - system variables recovering routine |
| */ |
| int data_recovery(struct sysvar_buf *buf, int idx) { |
| int i, j, ret = SYSVAR_SUCCESS, sector; |
| |
| /* load the system variables */ |
| 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)) |
| continue; |
| |
| /* check crc32 and wc32 (write count) */ |
| if (check_var(buf, SYSVAR_LOAD_MODE) == SYSVAR_SUCCESS) { |
| /* erase SPI flash */ |
| sector = __SYSVAR_ERASE_SECTOR(sysvar_offset[j]); |
| ret = flash_erase(flash_info, sector, sector); |
| if (ret) { |
| ret = SYSVAR_ERASE_ERR; |
| goto recovery_err; |
| } |
| |
| /* check crc32 and wc32 (write count) */ |
| 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); |
| if (ret) { |
| ret = SYSVAR_WRITE_ERR; |
| goto recovery_err; |
| } |
| |
| buf->loaded = true; |
| return SYSVAR_SUCCESS; |
| } |
| } |
| |
| recovery_err: |
| clear_buf(buf); |
| return ret; |
| } |
| |
| /* |
| * data_load - load the data from SPI flash to data buffer |
| */ |
| int data_load(struct sysvar_buf *buf, int idx) { |
| int i, j; |
| |
| /* load the system variables */ |
| for (i = idx, j = 0; i < idx + 2; i++, j++) { |
| buf->failed[j] = false; |
| |
| /* read the data from SPI flash */ |
| if (read_buff(flash_info, buf->data, sysvar_offset[i], buf->data_len)) { |
| buf->failed[j] = true; |
| } |
| |
| /* check crc32 and wc32 (write count) */ |
| if (check_var(buf, SYSVAR_LOAD_MODE)) |
| buf->failed[j] = true; |
| } |
| |
| load_err: |
| if (buf->failed[0] || buf->failed[1]) { |
| return SYSVAR_LOAD_ERR; |
| } |
| return SYSVAR_SUCCESS; |
| } |
| |
| /* |
| * data_save - save the data from data buffer to SPI flash |
| */ |
| int data_save(struct sysvar_buf *buf, int *idx) { |
| int i, j, ret, sector; |
| |
| /* save the system variables */ |
| for (j = 0; j < 2; j++) { |
| i = idx[j]; |
| sector = __SYSVAR_ERASE_SECTOR(sysvar_offset[i]); |
| ret = flash_erase(flash_info, sector, sector); |
| if (ret) { |
| return SYSVAR_SAVE_ERR; |
| } |
| |
| /* check crc32 and wc32 (write count) */ |
| if (check_var(buf, SYSVAR_SAVE_MODE)) { |
| return SYSVAR_CRC_ERR; |
| } |
| |
| /* write system variables to SPI flash */ |
| ret = write_buff(flash_info, buf->data, sysvar_offset[i] + CFG_FLASH_BASE, |
| buf->data_len); |
| if (ret) { |
| return SYSVAR_WRITE_ERR; |
| } |
| } |
| return SYSVAR_SUCCESS; |
| } |
| |
| /* |
| * sysvar_dump - dump the data buffer in binary/ascii format |
| */ |
| void sysvar_dump(struct sysvar_buf *buf, int idx, bool load) { |
| extern char console_buffer[]; |
| int start = 0; |
| |
| printf("System Variables(%s):\n", (idx < SYSVAR_RO_BUF) ? "RW" : "RO"); |
| printf("offset : 0x%08lx\n", sysvar_offset[idx]); |
| printf("size : %d bytes\n", buf->data_len); |
| printf("total : %d bytes\n", buf->total_len); |
| printf("used : %d bytes\n", buf->used_len); |
| printf("wc32 : 0x%08lx\n", get_wc32(buf)); |
| printf("crc32 : 0x%08lx\n", get_crc32(buf)); |
| |
| while (1) { |
| /* dump one page data in data buffer */ |
| dump_buf(buf, start, PAGE_SIZE); |
| /* continue to dump...? */ |
| readline("(n)ext, (p)rev, (f)irst, (l)ast ? >> "); |
| if (strcmp(console_buffer, "n") == 0) { |
| start += PAGE_SIZE; /* go to next page */ |
| if (start >= buf->data_len) |
| return; |
| } else if (strcmp(console_buffer, "p") == 0) { |
| start -= PAGE_SIZE; /* go to previous page */ |
| if (start < 0) |
| return; |
| } else if (strcmp(console_buffer, "f") == 0) { |
| if (start == 0) |
| return; |
| start = 0; /* go to first page */ |
| } else if (strcmp(console_buffer, "l") == 0) { |
| if (start == buf->data_len - PAGE_SIZE) |
| return; |
| start = buf->data_len - PAGE_SIZE; /* go to last page */ |
| } else { |
| return; |
| } |
| } |
| } |
| |
| /* |
| * sysvar_io - SPI flash IO operations |
| */ |
| int sysvar_io(int argc, char *argv[]) { |
| struct sysvar_buf *buf; |
| int i, idx, sector, ret = 0, str_to_int_err = 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 { |
| buf = &ro_buf; |
| } |
| |
| if (strcmp(argv[0], "write") == 0) { |
| /* fill data to data buffer */ |
| for (i = 0; i < buf->data_len; i++) |
| buf->data[i] = i; |
| |
| /* write the data buffer to spi_flash */ |
| ret = write_buff(flash_info, buf->data, sysvar_offset[idx] + CFG_FLASH_BASE, |
| buf->data_len); |
| 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) { |
| ret = read_buff(flash_info, buf->data, sysvar_offset[idx], buf->data_len); |
| if (ret == 0) |
| sysvar_dump(buf, idx, false); |
| } |
| |
| if (ret != 0) |
| printf("## Error: SPI flash %s failed at 0x%08lx\n", |
| argv[0], sysvar_offset[idx]); |
| |
| rw_buf.loaded = false; |
| ro_buf.loaded = false; |
| return ret; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // Sysvar/Uboot Integration |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| /* |
| * sysvar_buf_init - Initializes a sysvar_buf struct. |
| */ |
| static int sysvar_buf_init(struct sysvar_buf *buf, bool is_ro) { |
| if (buf == NULL) { |
| return SYSVAR_PARAM_ERR; |
| } |
| memset(buf, 0, sizeof(*buf)); |
| buf->list = (struct sysvar_list *)malloc(sizeof(struct sysvar_list)); |
| if (buf->list == NULL) { |
| printf("list allocation "); |
| return SYSVAR_MEMORY_ERR; |
| } |
| buf->data = (uchar *) map_physmem(is_ro ? SYSVAR_RO_MEM : SYSVAR_RW_MEM); |
| if (buf->data == NULL) { |
| printf("data allocation "); |
| free(buf->list); |
| return SYSVAR_MEMORY_ERR; |
| } |
| |
| buf->data_len = SYSVAR_BLOCK_SIZE; |
| buf->total_len = SYSVAR_BLOCK_SIZE - SYSVAR_HEAD; |
| buf->free_len = buf->total_len; |
| buf->readonly = is_ro; |
| |
| strncpy(buf->list->name, is_ro ? "ro" : "rw", SYSVAR_NAME); |
| buf->list->value = NULL; |
| buf->list->len = SYSVAR_NAME + 2; |
| buf->list->next = NULL; |
| buf->loaded = false; |
| return SYSVAR_SUCCESS; |
| } |
| |
| /* |
| * 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. */ |
| set_sysvar_uboot(curr->name, curr->value); |
| curr = curr->next; |
| } |
| } |
| |
| /* |
| * 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. . . "); |
| if (sysvar_buf_init(&rw_buf, false) || sysvar_buf_init(&ro_buf, true) || |
| sf_loadvar(&rw_buf, SYSVAR_RW_BUF) || |
| sf_loadvar(&ro_buf, SYSVAR_RO_BUF)) { |
| printf("init failure!\n"); |
| return SYSVAR_MEMORY_ERR; |
| } |
| sysvar_uboot_env_load(); |
| printf("success!\n"); |
| return SYSVAR_SUCCESS; |
| } |
| |
| /* |
| * 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) { |
| return su_mappings[i].sysvar_name; |
| } |
| if (strcmp(var, su_mappings[i].sysvar_name) == 0) { |
| return su_mappings[i].uboot_name; |
| } |
| } |
| return NULL; |
| } |
| |
| const char *get_uboot_name(const char *sysvar_name) { |
| int i; |
| for (i = 0; i < ARRAY_SIZE(su_mappings); ++i) { |
| if (strcmp(sysvar_name, su_mappings[i].sysvar_name) == 0) { |
| return su_mappings[i].uboot_name; |
| } |
| } |
| return 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]); |
| if (ret == SYSVAR_SUCCESS) { |
| set_sysvar_uboot(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); |
| if (ret == SYSVAR_SUCCESS) { |
| set_sysvar_uboot(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" |
| ); |