1
0
mirror of git://projects.qi-hardware.com/openwrt-xburst.git synced 2025-04-11 22:17:27 +03:00

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 

Thank you realopty for testing.


git-svn-id: svn://svn.openwrt.org/openwrt/trunk@22475 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
hauke 2010-08-03 20:35:53 +00:00
parent 9fa6262054
commit fa5411e7e4
2 changed files with 176 additions and 6 deletions
target/linux/brcm47xx
files-2.6.34/drivers/mtd/maps
files-2.6.35/drivers/mtd/maps

@ -52,6 +52,8 @@
#include <linux/ssb/ssb.h> #include <linux/ssb/ssb.h>
#endif #endif
#include <asm/io.h> #include <asm/io.h>
#include <asm/mach-bcm47xx/nvram.h>
#include <asm/fw/cfe/cfe_api.h>
#define TRX_MAGIC 0x30524448 /* "HDR0" */ #define TRX_MAGIC 0x30524448 /* "HDR0" */
@ -75,6 +77,11 @@ struct trx_header {
#define WINDOW_SIZE 0x400000 #define WINDOW_SIZE 0x400000
#define BUSWIDTH 2 #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 #ifdef CONFIG_SSB
extern struct ssb_bus ssb_bcm47xx; extern struct ssb_bus ssb_bcm47xx;
#endif #endif
@ -344,11 +351,87 @@ find_root(struct mtd_info *mtd, size_t size, struct mtd_partition *part)
return part->size; 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 struct mtd_partition * __init
init_mtd_partitions(struct mtd_info *mtd, size_t size) init_mtd_partitions(struct mtd_info *mtd, size_t size)
{ {
int cfe_size; int cfe_size;
int dual_image_offset = 0; 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) if ((cfe_size = find_cfe_size(mtd,size)) < 0)
return NULL; return NULL;
@ -374,7 +457,7 @@ init_mtd_partitions(struct mtd_info *mtd, size_t size)
if (cfe_size != 384 * 1024) { if (cfe_size != 384 * 1024) {
bcm47xx_parts[1].offset = bcm47xx_parts[0].size; bcm47xx_parts[1].offset = bcm47xx_parts[0].size;
bcm47xx_parts[1].size = bcm47xx_parts[3].offset - dual_image_offset - bcm47xx_parts[1].size = bcm47xx_parts[3].offset - dual_image_offset -
bcm47xx_parts[1].offset; bcm47xx_parts[1].offset - board_data_size;
} else { } else {
/* do not count the elf loader, which is on one block */ /* do not count the elf loader, which is on one block */
bcm47xx_parts[1].offset = bcm47xx_parts[0].size + 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[1].size = size -
bcm47xx_parts[0].size - bcm47xx_parts[0].size -
(2*bcm47xx_parts[3].size) - (2*bcm47xx_parts[3].size) -
mtd->erasesize; mtd->erasesize - board_data_size;
} }
/* find and size rootfs */ /* find and size rootfs */
find_root(mtd,size,&bcm47xx_parts[2]); 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; return bcm47xx_parts;
} }

@ -52,6 +52,8 @@
#include <linux/ssb/ssb.h> #include <linux/ssb/ssb.h>
#endif #endif
#include <asm/io.h> #include <asm/io.h>
#include <asm/mach-bcm47xx/nvram.h>
#include <asm/fw/cfe/cfe_api.h>
#define TRX_MAGIC 0x30524448 /* "HDR0" */ #define TRX_MAGIC 0x30524448 /* "HDR0" */
@ -75,6 +77,11 @@ struct trx_header {
#define WINDOW_SIZE 0x400000 #define WINDOW_SIZE 0x400000
#define BUSWIDTH 2 #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 #ifdef CONFIG_SSB
extern struct ssb_bus ssb_bcm47xx; extern struct ssb_bus ssb_bcm47xx;
#endif #endif
@ -344,11 +351,87 @@ find_root(struct mtd_info *mtd, size_t size, struct mtd_partition *part)
return part->size; 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 struct mtd_partition * __init
init_mtd_partitions(struct mtd_info *mtd, size_t size) init_mtd_partitions(struct mtd_info *mtd, size_t size)
{ {
int cfe_size; int cfe_size;
int dual_image_offset = 0; 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) if ((cfe_size = find_cfe_size(mtd,size)) < 0)
return NULL; return NULL;
@ -374,7 +457,7 @@ init_mtd_partitions(struct mtd_info *mtd, size_t size)
if (cfe_size != 384 * 1024) { if (cfe_size != 384 * 1024) {
bcm47xx_parts[1].offset = bcm47xx_parts[0].size; bcm47xx_parts[1].offset = bcm47xx_parts[0].size;
bcm47xx_parts[1].size = bcm47xx_parts[3].offset - dual_image_offset - bcm47xx_parts[1].size = bcm47xx_parts[3].offset - dual_image_offset -
bcm47xx_parts[1].offset; bcm47xx_parts[1].offset - board_data_size;
} else { } else {
/* do not count the elf loader, which is on one block */ /* do not count the elf loader, which is on one block */
bcm47xx_parts[1].offset = bcm47xx_parts[0].size + 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[1].size = size -
bcm47xx_parts[0].size - bcm47xx_parts[0].size -
(2*bcm47xx_parts[3].size) - (2*bcm47xx_parts[3].size) -
mtd->erasesize; mtd->erasesize - board_data_size;
} }
/* find and size rootfs */ /* find and size rootfs */
find_root(mtd,size,&bcm47xx_parts[2]); 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; return bcm47xx_parts;
} }