Beispiel #1
0
static struct nvram_header *
BCMINITFN(nand_find_nvram)(hndnand_t *nfl, uint32 off)
{
	int blocksize = nfl->blocksize;
	unsigned char *buf = nflash_nvh;
	int rlen = sizeof(nflash_nvh);
	int len;

	for (; off < NFL_BOOT_SIZE; off += blocksize) {
		if (hndnand_checkbadb(nfl, off) != 0)
			continue;

		len = blocksize;
		if (len >= rlen)
			len = rlen;

		if (hndnand_read(nfl, off, len, buf) == 0)
			break;

		buf += len;
		rlen -= len;
		if (rlen == 0)
			return (struct nvram_header *)nflash_nvh;
	}

	return NULL;
}
Beispiel #2
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;
}
Beispiel #3
0
static int __init
nflash_mtd_init(void)
{
	int ret = 0;
	hndnand_t *info;
#ifdef CONFIG_MTD_PARTITIONS
	struct mtd_partition *parts;
	int i;
#endif

	memset(&nflash, 0, sizeof(struct nflash_mtd));

	/* attach to the backplane */
	if (!(nflash.sih = si_kattach(SI_OSH))) {
		printk(KERN_ERR "nflash: error attaching to backplane\n");
		ret = -EIO;
		goto fail;
	}

	/* Initialize serial flash access */
	if (!(info = hndnand_init(nflash.sih))) {
		printk(KERN_ERR "nflash: found no supported devices\n");
		ret = -ENODEV;
		goto fail;
	}
	nflash.nfl = info;

	/* Setup region info */
	nflash.region.offset = 0;
	nflash.region.erasesize = info->blocksize;
	nflash.region.numblocks = info->numblocks;
	if (nflash.region.erasesize > nflash.mtd.erasesize)
		nflash.mtd.erasesize = nflash.region.erasesize;
	/* At most 2GB is supported */
	nflash.mtd.size = (info->size >= (1 << 11)) ? (1 << 31) : (info->size << 20);
	nflash.mtd.numeraseregions = 1;
	nflash.map = (unsigned char *)kmalloc(info->numblocks, GFP_KERNEL);
	if (nflash.map)
		memset(nflash.map, 0, info->numblocks);

	/* Register with MTD */
	nflash.mtd.name = "nflash";
	nflash.mtd.type = MTD_NANDFLASH;
	nflash.mtd.flags = MTD_CAP_NANDFLASH;
	nflash.mtd.eraseregions = &nflash.region;
	nflash.mtd.erase = nflash_mtd_erase;
	nflash.mtd.read = nflash_mtd_read;
	nflash.mtd.write = nflash_mtd_write;
	nflash.mtd.writesize = info->pagesize;
	nflash.mtd.priv = &nflash;
	nflash.mtd.owner = THIS_MODULE;
	nflash.controller = nand_hwcontrol_lock_init();
	if (!nflash.controller)
		return -ENOMEM;

	/* Scan bad block */
	NFLASH_LOCK(&nflash);
	for (i = 0; i < info->numblocks; i++) {
		if (hndnand_checkbadb(nflash.nfl, (i * (uint64)info->blocksize)) != 0) {
			nflash.map[i] = 1;
		}
	}
	NFLASH_UNLOCK(&nflash);

#ifdef CONFIG_MTD_PARTITIONS
	parts = init_nflash_mtd_partitions(info, &nflash.mtd, nflash.mtd.size);
	if (!parts)
		goto fail;

	for (i = 0; parts[i].name; i++)
		;

	ret = add_mtd_partitions(&nflash.mtd, parts, i);
	if (ret) {
		printk(KERN_ERR "nflash: add_mtd failed\n");
		goto fail;
	}
	nflash_parts = parts;
#endif
	return 0;

fail:
	return ret;
}
Beispiel #4
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;
}
Beispiel #5
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);
}
Beispiel #6
0
static uint lookup_nflash_rootfs_offset(hndnand_t *nfl, struct mtd_info *mtd, int offset, size_t size)
{
	struct romfs_super_block *romfsb;
	struct cramfs_super *cramfsb;
	struct squashfs_super_block *squashfsb;
	struct trx_header *trx;
	unsigned char buf[NFL_SECTOR_SIZE];
	uint blocksize, mask, blk_offset, off, shift = 0;
	int ret;
	
	romfsb = (struct romfs_super_block *) buf;
	cramfsb = (struct cramfs_super *) buf;
	squashfsb = (struct squashfs_super_block *) buf;
	trx = (struct trx_header *) buf;


	/* Look at every block boundary till 16MB; higher space is reserved for application data. */
	blocksize = mtd->erasesize;
	printk("lookup_nflash_rootfs_offset: offset = 0x%x\n", offset);
	for (off = offset; off < NFL_BOOT_OS_SIZE; off += 4096) {
		mask = blocksize - 1;
		blk_offset = off & ~mask;
		if (hndnand_checkbadb(nfl, blk_offset) != 0)
			continue;
		memset(buf, 0xe5, sizeof(buf));
		if ((ret = hndnand_read(nfl, off, sizeof(buf), buf)) != sizeof(buf)) {
			printk(KERN_NOTICE
			       "%s: nflash_read return %d\n", mtd->name, ret);
			continue;
		}
			
		if (le32_to_cpu(trx->magic) == TRX_MAGIC)
		{
		
		printk(KERN_NOTICE "found trx at %X, len =%d\n",off,trx->len);
		int offset = le32_to_cpu(trx->offsets[2]) ? : le32_to_cpu(trx->offsets[1]);
		offset+=off;
		printk(KERN_NOTICE "scan filesys at %X\n",offset);

		if ((ret = hndnand_read(nfl, offset, sizeof(buf), buf)) != sizeof(buf)) {
			printk(KERN_NOTICE
			       "%s: nflash_read return %d\n", mtd->name, ret);
			continue;
		}
		
		if (*((__u32 *) buf) == SQUASHFS_MAGIC) {
			printk(KERN_NOTICE
			       "%s: squash filesystem with lzma found at offset %d\n",
			       mtd->name, off );
		int size = squashfsb->bytes_used;
		//part->size = part->size + 1024; /* uncomment for belkin v2000 ! */
		int len = offset + size;
		len +=  (mtd->erasesize - 1);
		len &= ~(mtd->erasesize - 1);
		ddwrtoffset = len;
		ddwrtsize = mtd->size - ddwrtoffset;
		return offset;
		}
		}

	}