char const *nvram_get(int index, char *name) { int idx; static char const *ret; RANV_PRINT("--> nvram_get %d %s\n", index, name); RANV_CHECK_INDEX(NULL); down(&nvram_sem); RANV_CHECK_VALID(); counter++; idx = cache_idx(index, name); if (-1 != idx) { if (fb[index].cache[idx].value) { //duplicate the value in case caller modify it //ret = strdup(fb[index].cache[idx].value); ret = fb[index].cache[idx].value; up(&nvram_sem); return ret; } } //printk("nvram_get: not found\n"); //no default value set? //btw, we don't return NULL anymore! up(&nvram_sem); return NULL; }
static int ra_nvram_close(int index) { int i; RANV_PRINT("--> nvram_close %d\n", index); RANV_CHECK_INDEX(-1); if (!fb[index].valid) return 0; down(&nvram_sem); //free cache for (i = 0; i < MAX_CACHE_ENTRY; i++) { if (fb[index].cache[i].name) { kfree(fb[index].cache[i].name); fb[index].cache[i].name = NULL; } if (fb[index].cache[i].value) { kfree(fb[index].cache[i].value); fb[index].cache[i].value = NULL; } } up(&nvram_sem); return 0; }
int nvram_set(int index, char *name, char *value) { int idx; RANV_PRINT("--> nvram_set %d %s=%s\n", index, name, value); RANV_CHECK_INDEX(-1); down(&nvram_sem); RANV_CHECK_VALID(); counter++; idx = cache_idx(index, name); if (-1 == idx) { //find the first empty room for (idx = 0; idx < MAX_CACHE_ENTRY; idx++) { if (!fb[index].cache[idx].name) { break; } } //no any empty room if (idx == MAX_CACHE_ENTRY) { RANV_ERROR("run out of env cache, please increase MAX_CACHE_ENTRY\n"); up(&nvram_sem); return -1; } fb[index].cache[idx].name = kstrdup(name, GFP_KERNEL); fb[index].cache[idx].value = kstrdup(value, GFP_KERNEL); } else { //abandon the previous value kfree(fb[index].cache[idx].value); fb[index].cache[idx].value = kstrdup(value, GFP_KERNEL); } fb[index].dirty = 1; up(&nvram_sem); return 0; }
/* * clear flash by writing all 1's value */ int nvram_clear(int index) { unsigned long to; int len; RANV_PRINT("--> nvram_clear %d\n", index); RANV_CHECK_INDEX(-1); ra_nvram_close(index); down(&nvram_sem); //construct all 1s env block len = fb[index].flash_max_len - sizeof(fb[index].env.crc); if (!fb[index].env.data) { fb[index].env.data = (char *)kmalloc(len, GFP_KERNEL); if (!fb[index].env.data) return -ENOMEM; } memset(fb[index].env.data, 0xFF, len); //calculate crc fb[index].env.crc = (unsigned long)nv_crc32(0, (unsigned char *)fb[index].env.data, len); //write crc to flash to = fb[index].flash_offset; len = sizeof(fb[index].env.crc); ra_mtd_write_nm(RALINK_NVRAM_MTDNAME, to, len, (unsigned char *)&fb[index].env.crc); //write all 1s data to flash to = to + len; len = fb[index].flash_max_len - len; ra_mtd_write_nm(RALINK_NVRAM_MTDNAME, to, len, (unsigned char *)fb[index].env.data); RANV_PRINT("clear flash from 0x%x for 0x%x bytes\n", (unsigned int)to, len); fb[index].dirty = 0; fb[index].valid = 1; up(&nvram_sem); return 0; }
int nvram_getall(int index, char *buf) { int i, len; char *p; RANV_CHECK_INDEX(-1); down(&nvram_sem); RANV_CHECK_VALID(); len = fb[index].flash_max_len - sizeof(fb[index].env.crc); if (!fb[index].env.data) { fb[index].env.data = (char *)kmalloc(len, GFP_KERNEL); if (!fb[index].env.data) return -ENOMEM; } memset(fb[index].env.data, 0, len); p = buf; for (i = 0; i < MAX_CACHE_ENTRY; i++) { int l, ret __maybe_unused; if (!fb[index].cache[i].name || !fb[index].cache[i].value) break; l = strlen(fb[index].cache[i].name) + strlen(fb[index].cache[i].value) + 2; if (p - fb[index].env.data + 2 >= fb[index].flash_max_len) { RANV_ERROR("ENV_BLK_SIZE 0x%x is not enough!", ENV_BLK_SIZE); up(&nvram_sem); return -1; } ret = snprintf(p, l, "%s=%s", fb[index].cache[i].name, fb[index].cache[i].value); p += l; } *p = '\0'; //ending null up(&nvram_sem); return 0; }
int nvram_commit(int index) { unsigned long to; int i, len; char *p; RANV_PRINT("--> nvram_commit %d\n", index); RANV_CHECK_INDEX(-1); down(&nvram_sem); RANV_CHECK_VALID(); counter++; if (!fb[index].dirty) { RANV_PRINT("nothing to be committed\n"); up(&nvram_sem); return 0; } //construct env block len = fb[index].flash_max_len - sizeof(fb[index].env.crc); if (!fb[index].env.data) { fb[index].env.data = (char *)kmalloc(len, GFP_KERNEL); if (!fb[index].env.data) return -ENOMEM; } memset(fb[index].env.data, 0, len); p = fb[index].env.data; for (i = 0; i < MAX_CACHE_ENTRY; i++) { int l; if (!fb[index].cache[i].name || !fb[index].cache[i].value) break; l = strlen(fb[index].cache[i].name) + strlen(fb[index].cache[i].value) + 2; if (p - fb[index].env.data + 2 >= fb[index].flash_max_len) { RANV_ERROR("ENV_BLK_SIZE 0x%x is not enough!", ENV_BLK_SIZE); up(&nvram_sem); return -1; } snprintf(p, l, "%s=%s", fb[index].cache[i].name, fb[index].cache[i].value); p += l; } *p = '\0'; //ending null //calculate crc fb[index].env.crc = (unsigned long)nv_crc32(0, (unsigned char *)fb[index].env.data, len); //write crc to flash to = fb[index].flash_offset; len = sizeof(fb[index].env.crc); ra_mtd_write_nm(RALINK_NVRAM_MTDNAME, to, len, (unsigned char *)&fb[index].env.crc); //write data to flash to = to + len; len = fb[index].flash_max_len - len; ra_mtd_write_nm(RALINK_NVRAM_MTDNAME, to, len, (unsigned char *)fb[index].env.data); fb[index].dirty = 0; up(&nvram_sem); return 0; }
static int init_nvram_block(int index) { unsigned long from; int i, j, len; char *p, *q; i = index; RANV_PRINT("--> nvram_init %d\n", index); RANV_CHECK_INDEX(-1); if (fb[index].valid) return -EINVAL; //read crc from flash from = fb[i].flash_offset; len = sizeof(fb[i].env.crc); ra_mtd_read_nm(RALINK_NVRAM_MTDNAME, from, len, (unsigned char *)&fb[i].env.crc); //read data from flash from = from + len; len = fb[i].flash_max_len - len; fb[i].env.data = (char *)kmalloc(len, GFP_KERNEL); if (!fb[i].env.data) return -ENOMEM; ra_mtd_read_nm(RALINK_NVRAM_MTDNAME, from, len, (unsigned char *)fb[i].env.data); //check crc if (nv_crc32(0, fb[i].env.data, len) != fb[i].env.crc) { RANV_PRINT("Bad CRC %x, ignore values in flash.\n", (unsigned int)fb[i].env.crc); memset(fb[index].env.data, 0, len); //kfree(fb[i].env.data); fb[i].valid = 1; fb[i].dirty = 0; return -1; } //parse env to cache p = fb[i].env.data; for (j = 0; j < MAX_CACHE_ENTRY; j++) { if (NULL == (q = strchr(p, '='))) { RANV_PRINT("parsed failed - cannot find '='\n"); break; } *q = '\0'; //strip '=' fb[i].cache[j].name = kstrdup(p, GFP_KERNEL); //printk(" %d '%s'->", i, p); p = q + 1; //value if (NULL == (q = strchr(p, '\0'))) { RANV_PRINT("parsed failed - cannot find '\\0'\n"); break; } fb[i].cache[j].value = kstrdup(p, GFP_KERNEL); //printk("'%s'\n", p); p = q + 1; //next entry if (p - fb[i].env.data + 1 >= len) { //end of block break; } if (*p == '\0') { //end of env break; } } if (j == MAX_CACHE_ENTRY) RANV_PRINT("run out of env cache, please increase MAX_CACHE_ENTRY\n"); fb[i].valid = 1; fb[i].dirty = 0; return 0; }