diff options
Diffstat (limited to 'drivers/mtd/bcm47xxpart.c')
-rw-r--r-- | drivers/mtd/bcm47xxpart.c | 52 |
1 files changed, 33 insertions, 19 deletions
diff --git a/drivers/mtd/bcm47xxpart.c b/drivers/mtd/bcm47xxpart.c index 63feb75cc8e0..9279a9174f84 100644 --- a/drivers/mtd/bcm47xxpart.c +++ b/drivers/mtd/bcm47xxpart.c | |||
@@ -19,6 +19,12 @@ | |||
19 | /* 10 parts were found on sflash on Netgear WNDR4500 */ | 19 | /* 10 parts were found on sflash on Netgear WNDR4500 */ |
20 | #define BCM47XXPART_MAX_PARTS 12 | 20 | #define BCM47XXPART_MAX_PARTS 12 |
21 | 21 | ||
22 | /* | ||
23 | * Amount of bytes we read when analyzing each block of flash memory. | ||
24 | * Set it big enough to allow detecting partition and reading important data. | ||
25 | */ | ||
26 | #define BCM47XXPART_BYTES_TO_READ 0x404 | ||
27 | |||
22 | /* Magics */ | 28 | /* Magics */ |
23 | #define BOARD_DATA_MAGIC 0x5246504D /* MPFR */ | 29 | #define BOARD_DATA_MAGIC 0x5246504D /* MPFR */ |
24 | #define POT_MAGIC1 0x54544f50 /* POTT */ | 30 | #define POT_MAGIC1 0x54544f50 /* POTT */ |
@@ -57,17 +63,15 @@ static int bcm47xxpart_parse(struct mtd_info *master, | |||
57 | struct trx_header *trx; | 63 | struct trx_header *trx; |
58 | int trx_part = -1; | 64 | int trx_part = -1; |
59 | int last_trx_part = -1; | 65 | int last_trx_part = -1; |
60 | int max_bytes_to_read = 0x8004; | 66 | int possible_nvram_sizes[] = { 0x8000, 0xF000, 0x10000, }; |
61 | 67 | ||
62 | if (blocksize <= 0x10000) | 68 | if (blocksize <= 0x10000) |
63 | blocksize = 0x10000; | 69 | blocksize = 0x10000; |
64 | if (blocksize == 0x20000) | ||
65 | max_bytes_to_read = 0x18004; | ||
66 | 70 | ||
67 | /* Alloc */ | 71 | /* Alloc */ |
68 | parts = kzalloc(sizeof(struct mtd_partition) * BCM47XXPART_MAX_PARTS, | 72 | parts = kzalloc(sizeof(struct mtd_partition) * BCM47XXPART_MAX_PARTS, |
69 | GFP_KERNEL); | 73 | GFP_KERNEL); |
70 | buf = kzalloc(max_bytes_to_read, GFP_KERNEL); | 74 | buf = kzalloc(BCM47XXPART_BYTES_TO_READ, GFP_KERNEL); |
71 | 75 | ||
72 | /* Parse block by block looking for magics */ | 76 | /* Parse block by block looking for magics */ |
73 | for (offset = 0; offset <= master->size - blocksize; | 77 | for (offset = 0; offset <= master->size - blocksize; |
@@ -82,7 +86,7 @@ static int bcm47xxpart_parse(struct mtd_info *master, | |||
82 | } | 86 | } |
83 | 87 | ||
84 | /* Read beginning of the block */ | 88 | /* Read beginning of the block */ |
85 | if (mtd_read(master, offset, max_bytes_to_read, | 89 | if (mtd_read(master, offset, BCM47XXPART_BYTES_TO_READ, |
86 | &bytes_read, (uint8_t *)buf) < 0) { | 90 | &bytes_read, (uint8_t *)buf) < 0) { |
87 | pr_err("mtd_read error while parsing (offset: 0x%X)!\n", | 91 | pr_err("mtd_read error while parsing (offset: 0x%X)!\n", |
88 | offset); | 92 | offset); |
@@ -96,20 +100,6 @@ static int bcm47xxpart_parse(struct mtd_info *master, | |||
96 | continue; | 100 | continue; |
97 | } | 101 | } |
98 | 102 | ||
99 | /* Standard NVRAM */ | ||
100 | if (buf[0x000 / 4] == NVRAM_HEADER || | ||
101 | buf[0x1000 / 4] == NVRAM_HEADER || | ||
102 | buf[0x8000 / 4] == NVRAM_HEADER || | ||
103 | (blocksize == 0x20000 && ( | ||
104 | buf[0x10000 / 4] == NVRAM_HEADER || | ||
105 | buf[0x11000 / 4] == NVRAM_HEADER || | ||
106 | buf[0x18000 / 4] == NVRAM_HEADER))) { | ||
107 | bcm47xxpart_add_part(&parts[curr_part++], "nvram", | ||
108 | offset, 0); | ||
109 | offset = rounddown(offset, blocksize); | ||
110 | continue; | ||
111 | } | ||
112 | |||
113 | /* | 103 | /* |
114 | * board_data starts with board_id which differs across boards, | 104 | * board_data starts with board_id which differs across boards, |
115 | * but we can use 'MPFR' (hopefully) magic at 0x100 | 105 | * but we can use 'MPFR' (hopefully) magic at 0x100 |
@@ -178,6 +168,30 @@ static int bcm47xxpart_parse(struct mtd_info *master, | |||
178 | continue; | 168 | continue; |
179 | } | 169 | } |
180 | } | 170 | } |
171 | |||
172 | /* Look for NVRAM at the end of the last block. */ | ||
173 | for (i = 0; i < ARRAY_SIZE(possible_nvram_sizes); i++) { | ||
174 | if (curr_part > BCM47XXPART_MAX_PARTS) { | ||
175 | pr_warn("Reached maximum number of partitions, scanning stopped!\n"); | ||
176 | break; | ||
177 | } | ||
178 | |||
179 | offset = master->size - possible_nvram_sizes[i]; | ||
180 | if (mtd_read(master, offset, 0x4, &bytes_read, | ||
181 | (uint8_t *)buf) < 0) { | ||
182 | pr_err("mtd_read error while reading at offset 0x%X!\n", | ||
183 | offset); | ||
184 | continue; | ||
185 | } | ||
186 | |||
187 | /* Standard NVRAM */ | ||
188 | if (buf[0] == NVRAM_HEADER) { | ||
189 | bcm47xxpart_add_part(&parts[curr_part++], "nvram", | ||
190 | master->size - blocksize, 0); | ||
191 | break; | ||
192 | } | ||
193 | } | ||
194 | |||
181 | kfree(buf); | 195 | kfree(buf); |
182 | 196 | ||
183 | /* | 197 | /* |