diff options
author | Hauke Mehrtens <hauke@openwrt.org> | 2010-08-03 20:35:53 +0000 |
---|---|---|
committer | Hauke Mehrtens <hauke@openwrt.org> | 2010-08-03 20:35:53 +0000 |
commit | 40174d507da9231e212881ea42c6a37f57e75d51 (patch) | |
tree | da29a34d8c96d1f17c3083456ecb6c0f8473e510 /target/linux/brcm47xx | |
parent | b86926d93925c971f39a5298780b4656b5320f4e (diff) | |
download | upstream-40174d507da9231e212881ea42c6a37f57e75d51.tar.gz upstream-40174d507da9231e212881ea42c6a37f57e75d51.tar.bz2 upstream-40174d507da9231e212881ea42c6a37f57e75d51.zip |
brcm47xx: ignore some parts of flash on some netgear devices. This
space is used to store config values. When overwriting it the device
will not start any more.
closes #7630
Thank you realopty for testing.
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@22475 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/brcm47xx')
-rw-r--r-- | target/linux/brcm47xx/files-2.6.34/drivers/mtd/maps/bcm47xx-flash.c | 91 | ||||
-rw-r--r-- | target/linux/brcm47xx/files-2.6.35/drivers/mtd/maps/bcm47xx-flash.c | 91 |
2 files changed, 176 insertions, 6 deletions
diff --git a/target/linux/brcm47xx/files-2.6.34/drivers/mtd/maps/bcm47xx-flash.c b/target/linux/brcm47xx/files-2.6.34/drivers/mtd/maps/bcm47xx-flash.c index 61605d3f4a..3159bf3f64 100644 --- a/target/linux/brcm47xx/files-2.6.34/drivers/mtd/maps/bcm47xx-flash.c +++ b/target/linux/brcm47xx/files-2.6.34/drivers/mtd/maps/bcm47xx-flash.c @@ -52,6 +52,8 @@ #include <linux/ssb/ssb.h> #endif #include <asm/io.h> +#include <asm/mach-bcm47xx/nvram.h> +#include <asm/fw/cfe/cfe_api.h> #define TRX_MAGIC 0x30524448 /* "HDR0" */ @@ -75,6 +77,11 @@ struct trx_header { #define WINDOW_SIZE 0x400000 #define BUSWIDTH 2 +#define ROUTER_NETGEAR_WGR614L 1 +#define ROUTER_NETGEAR_WNR834B 2 +#define ROUTER_NETGEAR_WNDR3300 3 +#define ROUTER_NETGEAR_WNR3500L 4 + #ifdef CONFIG_SSB extern struct ssb_bus ssb_bcm47xx; #endif @@ -344,11 +351,87 @@ find_root(struct mtd_info *mtd, size_t size, struct mtd_partition *part) return part->size; } +static int get_router(void) +{ + char buf[20]; + u32 boardnum = 0; + u16 boardtype = 0; + u16 boardrev = 0; + u32 boardflags = 0; + u16 sdram_init = 0; + u16 cardbus = 0; + + if (nvram_getenv("boardnum", buf, sizeof(buf)) >= 0 || + cfe_getenv("boardnum", buf, sizeof(buf)) >= 0) + boardnum = simple_strtoul(buf, NULL, 0); + if (nvram_getenv("boardtype", buf, sizeof(buf)) >= 0 || + cfe_getenv("boardtype", buf, sizeof(buf)) >= 0) + boardtype = simple_strtoul(buf, NULL, 0); + if (nvram_getenv("boardrev", buf, sizeof(buf)) >= 0 || + cfe_getenv("boardrev", buf, sizeof(buf)) >= 0) + boardrev = simple_strtoul(buf, NULL, 0); + if (nvram_getenv("boardflags", buf, sizeof(buf)) >= 0 || + cfe_getenv("boardflags", buf, sizeof(buf)) >= 0) + boardflags = simple_strtoul(buf, NULL, 0); + if (nvram_getenv("sdram_init", buf, sizeof(buf)) >= 0 || + cfe_getenv("sdram_init", buf, sizeof(buf)) >= 0) + sdram_init = simple_strtoul(buf, NULL, 0); + if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0 || + cfe_getenv("cardbus", buf, sizeof(buf)) >= 0) + cardbus = simple_strtoul(buf, NULL, 0); + + if ((boardnum == 8 || boardnum == 01) + && boardtype == 0x0472 && cardbus == 1) { + /* Netgear WNR834B, Netgear WNR834Bv2 */ + return ROUTER_NETGEAR_WNR834B; + } + + if (boardnum == 01 && boardtype == 0x0472 && boardrev == 0x23) { + /* Netgear WNDR-3300 */ + return ROUTER_NETGEAR_WNDR3300; + } + + if ((boardnum == 83258 || boardnum == 01) + && boardtype == 0x048e + && (boardrev == 0x11 || boardrev == 0x10) + && boardflags == 0x750 + && sdram_init == 0x000A) { + /* Netgear WGR614v8/L/WW 16MB ram, cfe v1.3 or v1.5 */ + return ROUTER_NETGEAR_WGR614L; + } + + if ((boardnum == 1 || boardnum == 3500) + && boardtype == 0x04CF + && (boardrev == 0x1213 || boardrev == 02)) { + /* Netgear WNR3500v2/U/L */ + return ROUTER_NETGEAR_WNR3500L; + } + + return 0; +} + struct mtd_partition * __init init_mtd_partitions(struct mtd_info *mtd, size_t size) { int cfe_size; int dual_image_offset = 0; + /* e.g Netgear 0x003e0000-0x003f0000 : "board_data", we exclude this + * part from our mapping to prevent overwriting len/checksum on e.g. + * Netgear WGR614v8/L/WW + */ + int board_data_size = 0; + + switch (get_router()) { + case ROUTER_NETGEAR_WGR614L: + case ROUTER_NETGEAR_WNR834B: + case ROUTER_NETGEAR_WNDR3300: + case ROUTER_NETGEAR_WNR3500L: + /* Netgear: checksum is @ 0x003AFFF8 for 4M flash or checksum + * is @ 0x007AFFF8 for 8M flash + */ + board_data_size = 4 * mtd->erasesize; + break; + } if ((cfe_size = find_cfe_size(mtd,size)) < 0) return NULL; @@ -374,7 +457,7 @@ init_mtd_partitions(struct mtd_info *mtd, size_t size) if (cfe_size != 384 * 1024) { bcm47xx_parts[1].offset = bcm47xx_parts[0].size; bcm47xx_parts[1].size = bcm47xx_parts[3].offset - dual_image_offset - - bcm47xx_parts[1].offset; + bcm47xx_parts[1].offset - board_data_size; } else { /* do not count the elf loader, which is on one block */ bcm47xx_parts[1].offset = bcm47xx_parts[0].size + @@ -382,12 +465,14 @@ init_mtd_partitions(struct mtd_info *mtd, size_t size) bcm47xx_parts[1].size = size - bcm47xx_parts[0].size - (2*bcm47xx_parts[3].size) - - mtd->erasesize; + mtd->erasesize - board_data_size; } /* find and size rootfs */ find_root(mtd,size,&bcm47xx_parts[2]); - bcm47xx_parts[2].size = size - dual_image_offset - bcm47xx_parts[2].offset - bcm47xx_parts[3].size; + bcm47xx_parts[2].size = size - dual_image_offset - + bcm47xx_parts[2].offset - + bcm47xx_parts[3].size - board_data_size; return bcm47xx_parts; } diff --git a/target/linux/brcm47xx/files-2.6.35/drivers/mtd/maps/bcm47xx-flash.c b/target/linux/brcm47xx/files-2.6.35/drivers/mtd/maps/bcm47xx-flash.c index 61605d3f4a..3159bf3f64 100644 --- a/target/linux/brcm47xx/files-2.6.35/drivers/mtd/maps/bcm47xx-flash.c +++ b/target/linux/brcm47xx/files-2.6.35/drivers/mtd/maps/bcm47xx-flash.c @@ -52,6 +52,8 @@ #include <linux/ssb/ssb.h> #endif #include <asm/io.h> +#include <asm/mach-bcm47xx/nvram.h> +#include <asm/fw/cfe/cfe_api.h> #define TRX_MAGIC 0x30524448 /* "HDR0" */ @@ -75,6 +77,11 @@ struct trx_header { #define WINDOW_SIZE 0x400000 #define BUSWIDTH 2 +#define ROUTER_NETGEAR_WGR614L 1 +#define ROUTER_NETGEAR_WNR834B 2 +#define ROUTER_NETGEAR_WNDR3300 3 +#define ROUTER_NETGEAR_WNR3500L 4 + #ifdef CONFIG_SSB extern struct ssb_bus ssb_bcm47xx; #endif @@ -344,11 +351,87 @@ find_root(struct mtd_info *mtd, size_t size, struct mtd_partition *part) return part->size; } +static int get_router(void) +{ + char buf[20]; + u32 boardnum = 0; + u16 boardtype = 0; + u16 boardrev = 0; + u32 boardflags = 0; + u16 sdram_init = 0; + u16 cardbus = 0; + + if (nvram_getenv("boardnum", buf, sizeof(buf)) >= 0 || + cfe_getenv("boardnum", buf, sizeof(buf)) >= 0) + boardnum = simple_strtoul(buf, NULL, 0); + if (nvram_getenv("boardtype", buf, sizeof(buf)) >= 0 || + cfe_getenv("boardtype", buf, sizeof(buf)) >= 0) + boardtype = simple_strtoul(buf, NULL, 0); + if (nvram_getenv("boardrev", buf, sizeof(buf)) >= 0 || + cfe_getenv("boardrev", buf, sizeof(buf)) >= 0) + boardrev = simple_strtoul(buf, NULL, 0); + if (nvram_getenv("boardflags", buf, sizeof(buf)) >= 0 || + cfe_getenv("boardflags", buf, sizeof(buf)) >= 0) + boardflags = simple_strtoul(buf, NULL, 0); + if (nvram_getenv("sdram_init", buf, sizeof(buf)) >= 0 || + cfe_getenv("sdram_init", buf, sizeof(buf)) >= 0) + sdram_init = simple_strtoul(buf, NULL, 0); + if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0 || + cfe_getenv("cardbus", buf, sizeof(buf)) >= 0) + cardbus = simple_strtoul(buf, NULL, 0); + + if ((boardnum == 8 || boardnum == 01) + && boardtype == 0x0472 && cardbus == 1) { + /* Netgear WNR834B, Netgear WNR834Bv2 */ + return ROUTER_NETGEAR_WNR834B; + } + + if (boardnum == 01 && boardtype == 0x0472 && boardrev == 0x23) { + /* Netgear WNDR-3300 */ + return ROUTER_NETGEAR_WNDR3300; + } + + if ((boardnum == 83258 || boardnum == 01) + && boardtype == 0x048e + && (boardrev == 0x11 || boardrev == 0x10) + && boardflags == 0x750 + && sdram_init == 0x000A) { + /* Netgear WGR614v8/L/WW 16MB ram, cfe v1.3 or v1.5 */ + return ROUTER_NETGEAR_WGR614L; + } + + if ((boardnum == 1 || boardnum == 3500) + && boardtype == 0x04CF + && (boardrev == 0x1213 || boardrev == 02)) { + /* Netgear WNR3500v2/U/L */ + return ROUTER_NETGEAR_WNR3500L; + } + + return 0; +} + struct mtd_partition * __init init_mtd_partitions(struct mtd_info *mtd, size_t size) { int cfe_size; int dual_image_offset = 0; + /* e.g Netgear 0x003e0000-0x003f0000 : "board_data", we exclude this + * part from our mapping to prevent overwriting len/checksum on e.g. + * Netgear WGR614v8/L/WW + */ + int board_data_size = 0; + + switch (get_router()) { + case ROUTER_NETGEAR_WGR614L: + case ROUTER_NETGEAR_WNR834B: + case ROUTER_NETGEAR_WNDR3300: + case ROUTER_NETGEAR_WNR3500L: + /* Netgear: checksum is @ 0x003AFFF8 for 4M flash or checksum + * is @ 0x007AFFF8 for 8M flash + */ + board_data_size = 4 * mtd->erasesize; + break; + } if ((cfe_size = find_cfe_size(mtd,size)) < 0) return NULL; @@ -374,7 +457,7 @@ init_mtd_partitions(struct mtd_info *mtd, size_t size) if (cfe_size != 384 * 1024) { bcm47xx_parts[1].offset = bcm47xx_parts[0].size; bcm47xx_parts[1].size = bcm47xx_parts[3].offset - dual_image_offset - - bcm47xx_parts[1].offset; + bcm47xx_parts[1].offset - board_data_size; } else { /* do not count the elf loader, which is on one block */ bcm47xx_parts[1].offset = bcm47xx_parts[0].size + @@ -382,12 +465,14 @@ init_mtd_partitions(struct mtd_info *mtd, size_t size) bcm47xx_parts[1].size = size - bcm47xx_parts[0].size - (2*bcm47xx_parts[3].size) - - mtd->erasesize; + mtd->erasesize - board_data_size; } /* find and size rootfs */ find_root(mtd,size,&bcm47xx_parts[2]); - bcm47xx_parts[2].size = size - dual_image_offset - bcm47xx_parts[2].offset - bcm47xx_parts[3].size; + bcm47xx_parts[2].size = size - dual_image_offset - + bcm47xx_parts[2].offset - + bcm47xx_parts[3].size - board_data_size; return bcm47xx_parts; } |