static int nvram_valid(struct nvram_header *header) { return (header->magic == NVRAM_MAGIC) && (header->len >= sizeof(struct nvram_header)) && (header->len <= NVRAM_SPACE) #if 0 && (nvram_calc_crc(header) == (uint8) header->crc_ver_init)) #endif ; }
/* XXX: not marking as RECLAIMTEXT allows this fucntion to be fc-sectioned out when not referenced */ int BCMINITFN(_nvram_commit)(struct nvram_header *header) { char *ptr, *end; int i; struct nvram_tuple *t; /* Regenerate header */ header->magic = NVRAM_MAGIC; header->crc_ver_init = (NVRAM_VERSION << 8); header->config_refresh = 0; /* for backward compatibility */ header->config_ncdl = 0; /* for backward compatibility */ /* Clear data area */ ptr = (char *) header + sizeof(struct nvram_header); bzero(ptr, NVRAM_SPACE - sizeof(struct nvram_header)); /* Leave space for a double NUL at the end */ end = (char *) header + NVRAM_SPACE - 2; /* Write out all tuples */ for (i = 0; i < ARRAYSIZE(nvram_hash); i++) { for (t = nvram_hash[i]; t; t = t->next) { if ((ptr + strlen(t->name) + 1 + strlen(t->value) + 1) > end) break; ptr += sprintf(ptr, "%s=%s", t->name, t->value) + 1; } } /* End with a double NUL */ ptr += 2; /* Set new length */ header->len = ROUNDUP(ptr - (char *) header, 4); /* Set new CRC8 */ header->crc_ver_init |= nvram_calc_crc(header); /* Reinitialize hash table */ return nvram_rehash(header); }
/* Probe for NVRAM header */ static int early_nvram_init(void) { struct nvram_header *header; chipcregs_t *cc; int i; uint32 base, off, lim; u32 *src, *dst; uint32 fltype; char *nvram_space_str; #ifdef NFLASH_SUPPORT hndnand_t *nfl_info = NULL; uint32 blocksize; #endif hndsflash_t *sfl_info = NULL; header = (struct nvram_header *)ram_nvram_buf; if (header->magic == NVRAM_MAGIC) { if (nvram_calc_crc(header) == (uint8) header->crc_ver_init) { nvram_inram = TRUE; goto found; } } if ((cc = si_setcore(sih, CC_CORE_ID, 0)) != NULL) { #ifdef NFLASH_SUPPORT if ((sih->ccrev == 38) && ((sih->chipst & (1 << 4)) != 0)) { fltype = NFLASH; base = KSEG1ADDR(SI_FLASH1); } else #endif { fltype = readl(&cc->capabilities) & CC_CAP_FLASH_MASK; base = KSEG1ADDR(SI_FLASH2); } switch (fltype) { case PFLASH: lim = SI_FLASH2_SZ; break; case SFLASH_ST: case SFLASH_AT: if ((sfl_info = hndsflash_init(sih)) == NULL) return -1; lim = sfl_info->size; break; #ifdef NFLASH_SUPPORT case NFLASH: if ((nfl_info = hndnand_init(sih)) == NULL) return -1; lim = SI_FLASH1_SZ; break; #endif case FLASH_NONE: default: return -1; } } else { /* extif assumed, Stop at 4 MB */ base = KSEG1ADDR(SI_FLASH1); lim = SI_FLASH1_SZ; } #ifdef NFLASH_SUPPORT if (nfl_info != NULL) { blocksize = nfl_info->blocksize; off = blocksize; for (; off < NFL_BOOT_SIZE; off += blocksize) { if (hndnand_checkbadb(nfl_info, off) != 0) continue; header = (struct nvram_header *) KSEG1ADDR(base + off); if (header->magic != NVRAM_MAGIC) continue; /* Read into the nand_nvram */ if ((header = nand_find_nvram(nfl_info, off)) == NULL) continue; if (nvram_calc_crc(header) == (uint8)header->crc_ver_init) goto found; } } else #endif /* NFLASH_SUPPORT */ { off = FLASH_MIN; #ifdef RTN66U_NVRAM_64K_SUPPORT header = (struct nvram_header *) KSEG1ADDR(base + lim - 0x8000); if(header->magic==0xffffffff) { header = (struct nvram_header *) KSEG1ADDR(base + 1 KB); if (nvram_calc_crc(header) == (uint8) header->crc_ver_init) { nvram_32_reset=1; goto found; } } #endif while (off <= lim) { /* Windowed flash access */ header = (struct nvram_header *) KSEG1ADDR(base + off - MAX_NVRAM_SPACE); if (header->magic == NVRAM_MAGIC) if (nvram_calc_crc(header) == (uint8) header->crc_ver_init) { goto found; } off += DEF_NVRAM_SPACE; } } /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */ header = (struct nvram_header *) KSEG1ADDR(base + 4 KB); if (header->magic == NVRAM_MAGIC) if (nvram_calc_crc(header) == (uint8) header->crc_ver_init) { goto found; } header = (struct nvram_header *) KSEG1ADDR(base + 1 KB); if (header->magic == NVRAM_MAGIC) if (nvram_calc_crc(header) == (uint8) header->crc_ver_init) { goto found; } return -1; found: src = (u32 *) header; dst = (u32 *) nvram_buf; for (i = 0; i < sizeof(struct nvram_header); i += 4) *dst++ = *src++; for (; i < header->len && i < MAX_NVRAM_SPACE; i += 4) *dst++ = ltoh32(*src++); nvram_space_str = early_nvram_get("nvram_space"); if (nvram_space_str) nvram_space = bcm_strtoul(nvram_space_str, NULL, 0); return 0; }
static int cfe_update(const char *keyword, const char *value) { struct nvram_header *header; uint8 crc; int ret; int found = 0; char *str, *end, *mv_target = NULL, *mv_start = NULL; if(keyword == NULL || *keyword == 0) return 0; if(cfe_buf == NULL||cfe_mtd == NULL) if((ret = cfe_init())) return ret; header = cfe_nvram_header; printk("cfe_update: before %x %x\n", header->len, cfe_nvram_header->crc_ver_init&0xff); str = (char *) &header[1]; end = (char *) header + cfe_embedded_size - 2; end[0] = end[1] = '\0'; for (; *str; str += strlen(str) + 1) { if(!found) { if(strncmp(str, keyword, strlen(keyword)) == 0 && str[strlen(keyword)] == '=') { printk("cfe_update: !!!! found !!!!\n"); found = 1; if(value != NULL && strlen(str) == strlen(keyword) + 1 + strlen(value)) {//string length is the same strcpy(str+strlen(keyword)+1, value); } else { mv_target = str; mv_start = str + strlen(str) + 1; } } } } /* str point to the end of all embedded nvram settings */ if(mv_target != NULL) { /* need to move string */ int str_len = strlen(mv_target); //printk("cfe_update: mv_target(%08x) mv_start(%08x) str(%08x) str_len(%d)\n", (unsigned int)mv_target, (unsigned int)mv_start, (unsigned int)str, str_len); if(value != NULL && (str + strlen(keyword) + 1 + strlen(value) + 1 - (str_len + 1)) > end) return -ENOSPC; memmove(mv_target, mv_start, str - mv_start); //printk("cfe_update: memmove done\n"); str -= (str_len + 1); /* /set str to the end for placing incoming keyword and value there */ } if(value == NULL) { //printk("cfe_update: do unset\n"); } else if(!found || mv_target != NULL) /*new or movement */ { /* append the keyword and value here */ //printk("cfe_update: str(%08x)\n", (unsigned int) str); if((str + strlen(keyword) + 1 + strlen(value) + 1) > end) return -ENOSPC; str += sprintf(str, "%s=%s", keyword, value) + 1; //printk("cfe_update: append string\n"); } /* calc length */ memset(str, 0, cfe_embedded_size+(char *)header - str); str += 2; header->len = ROUNDUP(str - (char *) header, 4); //printk("cfe_update: header len: %x\n", header->len); /*/calc crc */ crc = nvram_calc_crc(header); //printk("cfe_update: nvram_calc_crc(header) = 0x%02x\n", crc); header->crc_ver_init = (header->crc_ver_init & NVRAM_CRC_VER_MASK)|crc; //printk("cfe_update: after %x %x\n", header->crc_ver_init&0xFF, crc); return 0; }
/* Probe for NVRAM header */ static int early_nvram_init(void) { struct nvram_header *header; chipcregs_t *cc; struct sflash *info = NULL; int i; uint32 base, off, lim; u32 *src, *dst; uint32 fltype; #ifdef NFLASH_SUPPORT struct nflash *nfl_info = NULL; uint32 blocksize; #endif header = (struct nvram_header *)ram_nvram_buf; if ((cc = si_setcore(sih, CC_CORE_ID, 0)) != NULL) { #ifdef NFLASH_SUPPORT if ((sih->ccrev == 38) && ((sih->chipst & (1 << 4)) != 0)) { fltype = NFLASH; base = KSEG1ADDR(SI_FLASH1); } else #endif { fltype = readl(&cc->capabilities) & CC_CAP_FLASH_MASK; base = KSEG1ADDR(SI_FLASH2); } switch (fltype) { case PFLASH: lim = SI_FLASH2_SZ; break; case SFLASH_ST: case SFLASH_AT: if ((info = sflash_init(sih, cc)) == NULL) return -1; lim = info->size; break; #ifdef NFLASH_SUPPORT case NFLASH: if ((nfl_info = nflash_init(sih, cc)) == NULL) return -1; lim = SI_FLASH1_SZ; break; #endif case FLASH_NONE: default: return -1; } } else { /* extif assumed, Stop at 4 MB */ base = KSEG1ADDR(SI_FLASH1); lim = SI_FLASH1_SZ; } #ifdef NFLASH_SUPPORT if (nfl_info != NULL) { blocksize = nfl_info->blocksize; off = blocksize; while (off <= lim) { if (nflash_checkbadb(sih, cc, off) != 0) { off += blocksize; continue; } header = (struct nvram_header *) KSEG1ADDR(base + off); if (header->magic == NVRAM_MAGIC) if (nvram_calc_crc(header) == (uint8) header->crc_ver_init) { goto found; } off += blocksize; } } else #endif off = FLASH_MIN; #ifdef RTN66U_NVRAM_64K_SUPPORT header = (struct nvram_header *) KSEG1ADDR(base + lim - 0x8000); if(header->magic==0xffffffff) { header = (struct nvram_header *) KSEG1ADDR(base + 1 KB); if (nvram_valid(header)) goto found; } #endif while (off <= lim) { /* Windowed flash access */ header = (struct nvram_header *) KSEG1ADDR(base + off - NVRAM_SPACE); if (nvram_valid(header)) goto found; off <<= 1; } /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */ header = (struct nvram_header *) KSEG1ADDR(base + 4 KB); if (nvram_valid(header)) goto found; header = (struct nvram_header *) KSEG1ADDR(base + 1 KB); if (nvram_valid(header)) goto found; return -1; found: src = (u32 *) header; dst = (u32 *) nvram_buf; for (i = 0; i < sizeof(struct nvram_header); i += 4) *dst++ = *src++; for (; i < header->len && i < NVRAM_SPACE; i += 4) *dst++ = ltoh32(*src++); return 0; }
/* Probe for NVRAM header */ static int early_nvram_init(void) { struct nvram_header *header; int i; u32 *src, *dst; #ifdef CONFIG_MTD_NFLASH hndnand_t *nfl_info = NULL; uint32 blocksize; #endif char *nvram_space_str; int bootdev; uint32 flash_base; uint32 lim = SI_FLASH_WINDOW; uint32 off; hndsflash_t *sfl_info; header = (struct nvram_header *)ram_nvram_buf; if (header->magic == NVRAM_MAGIC) { if (nvram_calc_crc(header) == (uint8)header->crc_ver_init) { nvram_inram = TRUE; goto found; } } bootdev = soc_boot_dev((void *)sih); #ifdef CONFIG_MTD_NFLASH if (bootdev == SOC_BOOTDEV_NANDFLASH) { if ((nfl_info = hndnand_init(sih)) == NULL) return -1; flash_base = nfl_info->base; blocksize = nfl_info->blocksize; off = blocksize; for (; off < NFL_BOOT_SIZE; off += blocksize) { if (hndnand_checkbadb(nfl_info, off) != 0) continue; header = (struct nvram_header *)(flash_base + off); if (header->magic != NVRAM_MAGIC) continue; /* Read into the nand_nvram */ if ((header = nand_find_nvram(nfl_info, off)) == NULL) continue; if (nvram_calc_crc(header) == (uint8)header->crc_ver_init) goto found; } } else #endif if (bootdev == SOC_BOOTDEV_SFLASH || bootdev == SOC_BOOTDEV_ROM) { /* Boot from SFLASH or ROM */ if ((sfl_info = hndsflash_init(sih)) == NULL) return -1; lim = sfl_info->size; BUG_ON(request_resource(&iomem_resource, &norflash_region)); flash_base = sfl_info->base; BUG_ON(IS_ERR_OR_NULL((void *)flash_base)); off = FLASH_MIN; while (off <= lim) { /* Windowed flash access */ header = (struct nvram_header *)(flash_base + off - nvram_space); if (header->magic == NVRAM_MAGIC) if (nvram_calc_crc(header) == (uint8)header->crc_ver_init) { goto found; } off += DEF_NVRAM_SPACE; } } else { /* This is the case bootdev == SOC_BOOTDEV_PFLASH, not applied on NorthStar */ ASSERT(0); } /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */ header = (struct nvram_header *)(flash_base + 4 KB); if (header->magic == NVRAM_MAGIC) if (nvram_calc_crc(header) == (uint8)header->crc_ver_init) { goto found; } header = (struct nvram_header *)(flash_base + 1 KB); if (header->magic == NVRAM_MAGIC) if (nvram_calc_crc(header) == (uint8)header->crc_ver_init) { goto found; } return -1; found: src = (u32 *)header; dst = (u32 *)nvram_buf; for (i = 0; i < sizeof(struct nvram_header); i += 4) *dst++ = *src++; for (; i < header->len && i < MAX_NVRAM_SPACE; i += 4) *dst++ = ltoh32(*src++); nvram_space_str = early_nvram_get("nvram_space"); if (nvram_space_str) nvram_space = bcm_strtoul(nvram_space_str, NULL, 0); return 0; }
static struct nvram_header * BCMINITFN(find_nvram)(si_t *sih, bool embonly, bool *isemb) { struct nvram_header *nvh; uint32 off, lim = SI_FLASH2_SZ; uint32 flbase = SI_FLASH2; int bootdev; #ifdef NFLASH_SUPPORT hndnand_t *nfl_info = NULL; #endif #ifdef _CFE_ hndsflash_t *sfl_info = NULL; #endif bootdev = soc_boot_dev((void *)sih); #ifdef NFLASH_SUPPORT if (bootdev == SOC_BOOTDEV_NANDFLASH) { /* Init nand anyway */ nfl_info = hndnand_init(sih); if (nfl_info) flbase = nfl_info->phybase; } else #endif /* NFLASH_SUPPORT */ if (bootdev == SOC_BOOTDEV_SFLASH) { #ifdef _CFE_ /* Init nand anyway */ sfl_info = hndsflash_init(sih); if (sfl_info) { flbase = sfl_info->phybase; lim = sfl_info->size; } #else if (sih->ccrev == 42) flbase = SI_NS_NORFLASH; #endif } if (!embonly) { *isemb = FALSE; #ifdef NFLASH_SUPPORT if (nfl_info) { uint32 blocksize; blocksize = nfl_info->blocksize; off = blocksize; for (; off < nfl_boot_size(nfl_info); off += blocksize) { if (hndnand_checkbadb(nfl_info, off) != 0) continue; nvh = (struct nvram_header *)OSL_UNCACHED(flbase + off); if (nvh->magic != NVRAM_MAGIC) continue; /* Read into the nand_nvram */ if ((nvh = nand_find_nvram(nfl_info, off)) == NULL) continue; if (nvram_calc_crc(nvh) == (uint8)nvh->crc_ver_init) return nvh; } } else #endif /* NFLASH_SUPPORT */ { off = FLASH_MIN; while (off <= lim) { nvh = (struct nvram_header *) OSL_UNCACHED(flbase + off - MAX_NVRAM_SPACE); if (nvh->magic == NVRAM_MAGIC) { if (nvram_calc_crc(nvh) == (uint8) nvh->crc_ver_init) { return (nvh); } } off <<= 1; } } #ifdef BCMDBG printf("find_nvram: nvram not found, trying embedded nvram next\n"); #endif /* BCMDBG */ } /* * Provide feedback to user when nvram corruption detected. * Must be non-BCMDBG for customer release. */ printf("Corrupt NVRAM found, trying embedded NVRAM next.\n"); /* Now check embedded nvram */ *isemb = TRUE; nvh = (struct nvram_header *)OSL_UNCACHED(flbase + (4 * 1024)); if (nvh->magic == NVRAM_MAGIC) return (nvh); nvh = (struct nvram_header *)OSL_UNCACHED(flbase + 1024); if (nvh->magic == NVRAM_MAGIC) return (nvh); #ifdef _CFE_ nvh = (struct nvram_header *)embedded_nvram; if (nvh->magic == NVRAM_MAGIC) return (nvh); #endif printf("find_nvram: no nvram found\n"); return (NULL); }
/* Probe for NVRAM header */ static int early_nvram_init(void) { struct nvram_header *header; chipcregs_t *cc; struct sflash *info = NULL; int i; uint32 base, off, lim; u32 *src, *dst; if ((cc = si_setcore(sih, CC_CORE_ID, 0)) != NULL) { base = KSEG1ADDR(SI_FLASH2); switch (readl(&cc->capabilities) & CC_CAP_FLASH_MASK) { case PFLASH: lim = SI_FLASH2_SZ; break; case SFLASH_ST: case SFLASH_AT: if ((info = sflash_init(sih, cc)) == NULL) return -1; lim = info->size; break; case FLASH_NONE: default: return -1; } } else { /* extif assumed, Stop at 4 MB */ base = KSEG1ADDR(SI_FLASH1); lim = SI_FLASH1_SZ; } off = FLASH_MIN; while (off <= lim) { /* Windowed flash access */ header = (struct nvram_header *) KSEG1ADDR(base + off - NVRAM_SPACE); if (header->magic == NVRAM_MAGIC) if (nvram_calc_crc(header) == (uint8) header->crc_ver_init) { goto found; } off <<= 1; } /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */ header = (struct nvram_header *) KSEG1ADDR(base + 4 KB); if (header->magic == NVRAM_MAGIC) if (nvram_calc_crc(header) == (uint8) header->crc_ver_init) { goto found; } header = (struct nvram_header *) KSEG1ADDR(base + 1 KB); if (header->magic == NVRAM_MAGIC) if (nvram_calc_crc(header) == (uint8) header->crc_ver_init) { goto found; } return -1; found: src = (u32 *) header; dst = (u32 *) nvram_buf; for (i = 0; i < sizeof(struct nvram_header); i += 4) *dst++ = *src++; for (; i < header->len && i < NVRAM_SPACE; i += 4) *dst++ = ltoh32(*src++); return 0; }