diff options
Diffstat (limited to 'drivers/mtd/bcm47xxpart.c')
-rw-r--r-- | drivers/mtd/bcm47xxpart.c | 43 |
1 files changed, 37 insertions, 6 deletions
diff --git a/drivers/mtd/bcm47xxpart.c b/drivers/mtd/bcm47xxpart.c index cc13ea5ce4d5..c0720c1ee4c9 100644 --- a/drivers/mtd/bcm47xxpart.c +++ b/drivers/mtd/bcm47xxpart.c | |||
@@ -15,6 +15,8 @@ | |||
15 | #include <linux/mtd/mtd.h> | 15 | #include <linux/mtd/mtd.h> |
16 | #include <linux/mtd/partitions.h> | 16 | #include <linux/mtd/partitions.h> |
17 | 17 | ||
18 | #include <uapi/linux/magic.h> | ||
19 | |||
18 | /* | 20 | /* |
19 | * NAND flash on Netgear R6250 was verified to contain 15 partitions. | 21 | * NAND flash on Netgear R6250 was verified to contain 15 partitions. |
20 | * This will result in allocating too big array for some old devices, but the | 22 | * This will result in allocating too big array for some old devices, but the |
@@ -39,7 +41,8 @@ | |||
39 | #define ML_MAGIC1 0x39685a42 | 41 | #define ML_MAGIC1 0x39685a42 |
40 | #define ML_MAGIC2 0x26594131 | 42 | #define ML_MAGIC2 0x26594131 |
41 | #define TRX_MAGIC 0x30524448 | 43 | #define TRX_MAGIC 0x30524448 |
42 | #define SQSH_MAGIC 0x71736873 /* shsq */ | 44 | #define SHSQ_MAGIC 0x71736873 /* shsq (weird ZTE H218N endianness) */ |
45 | #define UBI_EC_MAGIC 0x23494255 /* UBI# */ | ||
43 | 46 | ||
44 | struct trx_header { | 47 | struct trx_header { |
45 | uint32_t magic; | 48 | uint32_t magic; |
@@ -50,7 +53,7 @@ struct trx_header { | |||
50 | uint32_t offset[3]; | 53 | uint32_t offset[3]; |
51 | } __packed; | 54 | } __packed; |
52 | 55 | ||
53 | static void bcm47xxpart_add_part(struct mtd_partition *part, char *name, | 56 | static void bcm47xxpart_add_part(struct mtd_partition *part, const char *name, |
54 | u64 offset, uint32_t mask_flags) | 57 | u64 offset, uint32_t mask_flags) |
55 | { | 58 | { |
56 | part->name = name; | 59 | part->name = name; |
@@ -58,6 +61,26 @@ static void bcm47xxpart_add_part(struct mtd_partition *part, char *name, | |||
58 | part->mask_flags = mask_flags; | 61 | part->mask_flags = mask_flags; |
59 | } | 62 | } |
60 | 63 | ||
64 | static const char *bcm47xxpart_trx_data_part_name(struct mtd_info *master, | ||
65 | size_t offset) | ||
66 | { | ||
67 | uint32_t buf; | ||
68 | size_t bytes_read; | ||
69 | |||
70 | if (mtd_read(master, offset, sizeof(buf), &bytes_read, | ||
71 | (uint8_t *)&buf) < 0) { | ||
72 | pr_err("mtd_read error while parsing (offset: 0x%X)!\n", | ||
73 | offset); | ||
74 | goto out_default; | ||
75 | } | ||
76 | |||
77 | if (buf == UBI_EC_MAGIC) | ||
78 | return "ubi"; | ||
79 | |||
80 | out_default: | ||
81 | return "rootfs"; | ||
82 | } | ||
83 | |||
61 | static int bcm47xxpart_parse(struct mtd_info *master, | 84 | static int bcm47xxpart_parse(struct mtd_info *master, |
62 | struct mtd_partition **pparts, | 85 | struct mtd_partition **pparts, |
63 | struct mtd_part_parser_data *data) | 86 | struct mtd_part_parser_data *data) |
@@ -73,8 +96,12 @@ static int bcm47xxpart_parse(struct mtd_info *master, | |||
73 | int last_trx_part = -1; | 96 | int last_trx_part = -1; |
74 | int possible_nvram_sizes[] = { 0x8000, 0xF000, 0x10000, }; | 97 | int possible_nvram_sizes[] = { 0x8000, 0xF000, 0x10000, }; |
75 | 98 | ||
76 | if (blocksize <= 0x10000) | 99 | /* |
77 | blocksize = 0x10000; | 100 | * Some really old flashes (like AT45DB*) had smaller erasesize-s, but |
101 | * partitions were aligned to at least 0x1000 anyway. | ||
102 | */ | ||
103 | if (blocksize < 0x1000) | ||
104 | blocksize = 0x1000; | ||
78 | 105 | ||
79 | /* Alloc */ | 106 | /* Alloc */ |
80 | parts = kzalloc(sizeof(struct mtd_partition) * BCM47XXPART_MAX_PARTS, | 107 | parts = kzalloc(sizeof(struct mtd_partition) * BCM47XXPART_MAX_PARTS, |
@@ -186,8 +213,11 @@ static int bcm47xxpart_parse(struct mtd_info *master, | |||
186 | * we want to have jffs2 (overlay) in the same mtd. | 213 | * we want to have jffs2 (overlay) in the same mtd. |
187 | */ | 214 | */ |
188 | if (trx->offset[i]) { | 215 | if (trx->offset[i]) { |
216 | const char *name; | ||
217 | |||
218 | name = bcm47xxpart_trx_data_part_name(master, offset + trx->offset[i]); | ||
189 | bcm47xxpart_add_part(&parts[curr_part++], | 219 | bcm47xxpart_add_part(&parts[curr_part++], |
190 | "rootfs", | 220 | name, |
191 | offset + trx->offset[i], | 221 | offset + trx->offset[i], |
192 | 0); | 222 | 0); |
193 | i++; | 223 | i++; |
@@ -205,7 +235,8 @@ static int bcm47xxpart_parse(struct mtd_info *master, | |||
205 | } | 235 | } |
206 | 236 | ||
207 | /* Squashfs on devices not using TRX */ | 237 | /* Squashfs on devices not using TRX */ |
208 | if (buf[0x000 / 4] == SQSH_MAGIC) { | 238 | if (le32_to_cpu(buf[0x000 / 4]) == SQUASHFS_MAGIC || |
239 | buf[0x000 / 4] == SHSQ_MAGIC) { | ||
209 | bcm47xxpart_add_part(&parts[curr_part++], "rootfs", | 240 | bcm47xxpart_add_part(&parts[curr_part++], "rootfs", |
210 | offset, 0); | 241 | offset, 0); |
211 | continue; | 242 | continue; |