static void flash_init(void) { newflash_probe_t fprobe; int bootdev; uint32 bootsz, *bisz; cfe_driver_t *drv = NULL; int j = 0; fl_size_t max_image_size = 0; int rom_envram_size; #if defined(DUAL_IMAGE) || defined(FAILSAFE_UPGRADE) int need_commit = 0; #endif #ifdef CFG_NFLASH hndnand_t *nfl_info = NULL; #endif #if CFG_SFLASH hndsflash_t *sfl_info = NULL; #endif memset(&fprobe, 0, sizeof(fprobe)); bootdev = soc_boot_dev((void *)sih); if(!nvram_match("nospare", "0")) nospare = 1; else nospare = 0; #ifdef CFG_NFLASH if (bootdev == SOC_BOOTDEV_NANDFLASH) { nfl_info = hndnand_init(sih); if (!nfl_info) return; fprobe.flash_phys = nfl_info->phybase; drv = &nflashdrv; } else #endif /* CFG_NFLASH */ #if CFG_SFLASH if (bootdev == SOC_BOOTDEV_SFLASH) { sfl_info = hndsflash_init(sih); if (!sfl_info) return; fprobe.flash_phys = sfl_info->phybase; drv = &sflashdrv; } else #endif #if CFG_FLASH { /* This might be wrong, but set pflash * as default if nothing configured */ chipcregs_t *cc; if ((cc = (chipcregs_t *)si_setcoreidx(sih, SI_CC_IDX)) == NULL) return; fprobe.flash_phys = SI_FLASH2; fprobe.flash_flags = FLASH_FLG_BUS16 | FLASH_FLG_DEV16; if (!(R_REG(NULL, &cc->flash_config) & CC_CFG_DS)) fprobe.flash_flags = FLASH_FLG_BUS8 | FLASH_FLG_DEV16; drv = &newflashdrv; } #endif /* CFG_FLASH */ ASSERT(drv); /* Default is 256K boot partition */ bootsz = 256 * 1024; /* Do we have a self-describing binary image? */ bisz = (uint32 *)UNCADDR(fprobe.flash_phys + BISZ_OFFSET); if (bisz[BISZ_MAGIC_IDX] == BISZ_MAGIC) { int isz = bisz[BISZ_DATAEND_IDX] - bisz[BISZ_TXTST_IDX]; if (isz > (1024 * 1024)) bootsz = 2048 * 1024; else if (isz > (512 * 1024)) bootsz = 1024 * 1024; else if (isz > (256 * 1024)) bootsz = 512 * 1024; else if (isz <= (128 * 1024)) bootsz = 128 * 1024; } printf("Boot partition size = %d(0x%x)\n", bootsz, bootsz); #if CFG_NFLASH if (nfl_info) { fl_size_t flash_size = 0; if (bootsz > nfl_info->blocksize) { /* Prepare double space in case of bad blocks */ bootsz = (bootsz << 1); } else { /* CFE occupies at least one block */ bootsz = nfl_info->blocksize; } /* Because sometimes we want to program the entire device */ fprobe.flash_nparts = 0; cfe_add_device(drv, 0, 0, &fprobe); #if defined(FAILSAFE_UPGRADE) || defined(DUAL_IMAGE) max_image_size = calculate_max_image_size("nflash0", nfl_boot_size(nfl_info), 0, &need_commit, nfl_boot_os_size(nfl_info)); #endif /* Because sometimes we want to program the entire device */ /* Because CFE can only boot from the beginning of a partition */ j = 0; fprobe.flash_parts[j].fp_size = bootsz; fprobe.flash_parts[j++].fp_name = "boot"; fprobe.flash_parts[j].fp_size = (nfl_boot_size(nfl_info) - bootsz); fprobe.flash_parts[j++].fp_name = "nvram"; fprobe.flash_parts[j].fp_size = sizeof(struct trx_header); fprobe.flash_parts[j++].fp_name = "trx"; fprobe.flash_parts[j].fp_size = max_image_size ? max_image_size - sizeof(struct trx_header) : 0; fprobe.flash_parts[j++].fp_name = "os"; #if defined(FAILSAFE_UPGRADE) || defined(DUAL_IMAGE) if (max_image_size) { fprobe.flash_parts[j].fp_size = sizeof(struct trx_header); fprobe.flash_parts[j++].fp_name = "trx2"; fprobe.flash_parts[j].fp_size = max_image_size; fprobe.flash_parts[j++].fp_name = "os2"; } #endif fprobe.flash_nparts = j; cfe_add_device(drv, 0, 0, &fprobe); /* Because CFE can only flash an entire partition */ j = 0; fprobe.flash_parts[j].fp_size = bootsz; fprobe.flash_parts[j++].fp_name = "boot"; fprobe.flash_parts[j].fp_size = (nfl_boot_size(nfl_info) - bootsz); fprobe.flash_parts[j++].fp_name = "nvram"; fprobe.flash_parts[j].fp_size = max_image_size; fprobe.flash_parts[j++].fp_name = "trx"; #if defined(FAILSAFE_UPGRADE) || defined(DUAL_IMAGE) if (max_image_size) { fprobe.flash_parts[j].fp_size = nfl_boot_os_size(nfl_info) - nfl_boot_size(nfl_info) - max_image_size; fprobe.flash_parts[j++].fp_name = "trx2"; } #endif flash_size = get_flash_size("nflash0") - nfl_boot_os_size(nfl_info); #ifdef DUAL_TRX fprobe.flash_parts[j].fp_size = NFL_BOOT_OS_SIZE; fprobe.flash_parts[j++].fp_name = "trx2"; flash_size -= NFL_BOOT_OS_SIZE; #endif if (flash_size > 0) { fprobe.flash_parts[j].fp_size = flash_size; fprobe.flash_parts[j++].fp_name = "brcmnand"; } fprobe.flash_nparts = j; cfe_add_device(drv, 0, 0, &fprobe); /* Change nvram device name for NAND boot */ flashdrv_nvram = "nflash0.nvram"; } else #endif /* CFG_NFLASH */ { /* Because sometimes we want to program the entire device */ fprobe.flash_nparts = 0; cfe_add_device(drv, 0, 0, &fprobe); #ifdef CFG_ROMBOOT if (board_bootdev_rom(sih)) { rom_envram_size = ROM_ENVRAM_SPACE; } else #endif { rom_envram_size = 0; } #if defined(FAILSAFE_UPGRADE) || defined(DUAL_IMAGE) /* If the kernel is not in nand flash, split up the sflash */ if (soc_knl_dev((void *)sih) != SOC_KNLDEV_NANDFLASH) { max_image_size = calculate_max_image_size("flash0", bootsz, MAX_NVRAM_SPACE+rom_envram_size, &need_commit, 0); } #endif /* Because CFE can only boot from the beginning of a partition */ j = 0; fprobe.flash_parts[j].fp_size = bootsz; fprobe.flash_parts[j++].fp_name = "boot"; fprobe.flash_parts[j].fp_size = sizeof(struct trx_header); fprobe.flash_parts[j++].fp_name = "trx"; fprobe.flash_parts[j].fp_size = max_image_size ? max_image_size - sizeof(struct trx_header) : 0; fprobe.flash_parts[j++].fp_name = "os"; #if defined(FAILSAFE_UPGRADE) || defined(DUAL_IMAGE) if (max_image_size) { fprobe.flash_parts[j].fp_size = sizeof(struct trx_header); fprobe.flash_parts[j++].fp_name = "trx2"; fprobe.flash_parts[j].fp_size = 0; fprobe.flash_parts[j++].fp_name = "os2"; } #endif #ifdef CFG_ROMBOOT if (rom_envram_size) { fprobe.flash_parts[j].fp_size = rom_envram_size; fprobe.flash_parts[j++].fp_name = "envram"; } #endif #ifdef BCM_DEVINFO fprobe.flash_parts[j].fp_size = 0x80000; fprobe.flash_parts[j++].fp_name = "fs_rw"; fprobe.flash_parts[j].fp_size = 0x10000; fprobe.flash_parts[j++].fp_name = "devinfo"; #endif /* BCM_DEVINFO */ fprobe.flash_parts[j].fp_size = MAX_NVRAM_SPACE; fprobe.flash_parts[j++].fp_name = "nvram"; fprobe.flash_nparts = j; cfe_add_device(drv, 0, 0, &fprobe); /* Because CFE can only flash an entire partition */ j = 0; fprobe.flash_parts[j].fp_size = bootsz; fprobe.flash_parts[j++].fp_name = "boot"; fprobe.flash_parts[j].fp_size = max_image_size; fprobe.flash_parts[j++].fp_name = "trx"; #if defined(FAILSAFE_UPGRADE) || defined(DUAL_IMAGE) if (max_image_size) { fprobe.flash_parts[j].fp_size = 0; fprobe.flash_parts[j++].fp_name = "trx2"; } #endif #ifdef CFG_ROMBOOT if (rom_envram_size) { fprobe.flash_parts[j].fp_size = rom_envram_size; fprobe.flash_parts[j++].fp_name = "envram"; } #endif #ifdef BCM_DEVINFO fprobe.flash_parts[j].fp_size = 0x80000; fprobe.flash_parts[j++].fp_name = "fs_rw"; fprobe.flash_parts[j].fp_size = 0x10000; fprobe.flash_parts[j++].fp_name = "devinfo"; #endif /* BCM_DEVINFO */ fprobe.flash_parts[j].fp_size = MAX_NVRAM_SPACE; fprobe.flash_parts[j++].fp_name = "nvram"; fprobe.flash_nparts = j; cfe_add_device(drv, 0, 0, &fprobe); } #if (CFG_FLASH || CFG_SFLASH) flash_memory_size_config(sih, (void *)&fprobe); #endif /* (CFG_FLASH || CFG_SFLASH) */ #ifdef CFG_NFLASH /* If boot from sflash, try to init partition for JFFS2 anyway */ if (nfl_info == NULL) flash_nflash_init(); #endif /* CFG_NFLASH */ #if defined(FAILSAFE_UPGRADE) || defined(DUAL_IMAGE) if (need_commit) nvram_commit(); #endif }
/* 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; }
/* 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 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); }