Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mtd: bcm47xxpart: support layouts with multiple TRX partitions

Some devices may have an extra TRX partition used as failsafe one. If
we detect such partition we should set a proper name for it and don't
parse it.

Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
Acked-by: Marek Vasut <marek.vasut@gmail.com>
Signed-off-by: Brian Norris <computersforpeace@gmail.com>

authored by

Rafał Miłecki and committed by
Brian Norris
89a0d9a9 b522d7b0

+45 -9
+45 -9
drivers/mtd/bcm47xxpart.c
··· 9 9 * 10 10 */ 11 11 12 + #include <linux/bcm47xx_nvram.h> 12 13 #include <linux/module.h> 13 14 #include <linux/kernel.h> 14 15 #include <linux/slab.h> ··· 145 144 return curr_part; 146 145 } 147 146 147 + /** 148 + * bcm47xxpart_bootpartition - gets index of TRX partition used by bootloader 149 + * 150 + * Some devices may have more than one TRX partition. In such case one of them 151 + * is the main one and another a failsafe one. Bootloader may fallback to the 152 + * failsafe firmware if it detects corruption of the main image. 153 + * 154 + * This function provides info about currently used TRX partition. It's the one 155 + * containing kernel started by the bootloader. 156 + */ 157 + static int bcm47xxpart_bootpartition(void) 158 + { 159 + char buf[4]; 160 + int bootpartition; 161 + 162 + /* Check CFE environment variable */ 163 + if (bcm47xx_nvram_getenv("bootpartition", buf, sizeof(buf)) > 0) { 164 + if (!kstrtoint(buf, 0, &bootpartition)) 165 + return bootpartition; 166 + } 167 + 168 + return 0; 169 + } 170 + 148 171 static int bcm47xxpart_parse(struct mtd_info *master, 149 172 const struct mtd_partition **pparts, 150 173 struct mtd_part_parser_data *data) ··· 179 154 size_t bytes_read; 180 155 uint32_t offset; 181 156 uint32_t blocksize = master->erasesize; 182 - int trx_part = -1; 157 + int trx_parts[2]; /* Array with indexes of TRX partitions */ 158 + int trx_num = 0; /* Number of found TRX partitions */ 183 159 int possible_nvram_sizes[] = { 0x8000, 0xF000, 0x10000, }; 184 160 int err; 185 161 ··· 269 243 if (buf[0x000 / 4] == TRX_MAGIC) { 270 244 struct trx_header *trx; 271 245 272 - trx_part = curr_part; 246 + if (trx_num >= ARRAY_SIZE(trx_parts)) 247 + pr_warn("No enough space to store another TRX found at 0x%X\n", 248 + offset); 249 + else 250 + trx_parts[trx_num++] = curr_part; 273 251 bcm47xxpart_add_part(&parts[curr_part++], "firmware", 274 252 offset, 0); 275 253 ··· 359 329 } 360 330 361 331 /* If there was TRX parse it now */ 362 - if (trx_part >= 0) { 363 - int num_parts; 332 + for (i = 0; i < trx_num; i++) { 333 + struct mtd_partition *trx = &parts[trx_parts[i]]; 364 334 365 - num_parts = bcm47xxpart_parse_trx(master, &parts[trx_part], 366 - parts + curr_part, 367 - BCM47XXPART_MAX_PARTS - curr_part); 368 - if (num_parts > 0) 369 - curr_part += num_parts; 335 + if (i == bcm47xxpart_bootpartition()) { 336 + int num_parts; 337 + 338 + num_parts = bcm47xxpart_parse_trx(master, trx, 339 + parts + curr_part, 340 + BCM47XXPART_MAX_PARTS - curr_part); 341 + if (num_parts > 0) 342 + curr_part += num_parts; 343 + } else { 344 + trx->name = "failsafe"; 345 + } 370 346 } 371 347 372 348 *pparts = parts;