1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright © 2007 Eugene Konev <ejka@openwrt.org>
5 * TI AR7 flash partition table.
6 * Based on ar7 map by Felix Fietkau <nbd@openwrt.org>
9 #include <linux/kernel.h>
10 #include <linux/slab.h>
12 #include <linux/mtd/mtd.h>
13 #include <linux/mtd/partitions.h>
14 #include <linux/memblock.h>
15 #include <linux/module.h>
17 #include <uapi/linux/magic.h>
20 #define ROOT_OFFSET 0xe0000
22 #define LOADER_MAGIC1 le32_to_cpu(0xfeedfa42)
23 #define LOADER_MAGIC2 le32_to_cpu(0xfeed1281)
26 unsigned int checksum
;
31 static int create_mtd_partitions(struct mtd_info
*master
,
32 const struct mtd_partition
**pparts
,
33 struct mtd_part_parser_data
*data
)
35 struct ar7_bin_rec header
;
38 unsigned int pre_size
= master
->erasesize
, post_size
= 0;
39 unsigned int root_offset
= ROOT_OFFSET
;
42 struct mtd_partition
*ar7_parts
;
44 ar7_parts
= kcalloc(AR7_PARTS
, sizeof(*ar7_parts
), GFP_KERNEL
);
47 ar7_parts
[0].name
= "loader";
48 ar7_parts
[0].offset
= 0;
49 ar7_parts
[0].size
= master
->erasesize
;
50 ar7_parts
[0].mask_flags
= MTD_WRITEABLE
;
52 ar7_parts
[1].name
= "config";
53 ar7_parts
[1].offset
= 0;
54 ar7_parts
[1].size
= master
->erasesize
;
55 ar7_parts
[1].mask_flags
= 0;
57 do { /* Try 10 blocks starting from master->erasesize */
59 mtd_read(master
, offset
, sizeof(header
), &len
,
61 if (!strncmp((char *)&header
, "TIENV0.8", 8))
62 ar7_parts
[1].offset
= pre_size
;
63 if (header
.checksum
== LOADER_MAGIC1
)
65 if (header
.checksum
== LOADER_MAGIC2
)
67 pre_size
+= master
->erasesize
;
72 if (!ar7_parts
[1].offset
) {
73 ar7_parts
[1].offset
= master
->size
- master
->erasesize
;
74 post_size
= master
->erasesize
;
77 switch (header
.checksum
) {
79 while (header
.length
) {
80 offset
+= sizeof(header
) + header
.length
;
81 mtd_read(master
, offset
, sizeof(header
), &len
,
84 root_offset
= offset
+ sizeof(header
) + 4;
87 while (header
.length
) {
88 offset
+= sizeof(header
) + header
.length
;
89 mtd_read(master
, offset
, sizeof(header
), &len
,
92 root_offset
= offset
+ sizeof(header
) + 4 + 0xff;
93 root_offset
&= ~(uint32_t)0xff;
96 printk(KERN_WARNING
"Unknown magic: %08x\n", header
.checksum
);
100 mtd_read(master
, root_offset
, sizeof(header
), &len
, (u8
*)&header
);
101 if (header
.checksum
!= SQUASHFS_MAGIC
) {
102 root_offset
+= master
->erasesize
- 1;
103 root_offset
&= ~(master
->erasesize
- 1);
106 ar7_parts
[2].name
= "linux";
107 ar7_parts
[2].offset
= pre_size
;
108 ar7_parts
[2].size
= master
->size
- pre_size
- post_size
;
109 ar7_parts
[2].mask_flags
= 0;
111 ar7_parts
[3].name
= "rootfs";
112 ar7_parts
[3].offset
= root_offset
;
113 ar7_parts
[3].size
= master
->size
- root_offset
- post_size
;
114 ar7_parts
[3].mask_flags
= 0;
120 static struct mtd_part_parser ar7_parser
= {
121 .parse_fn
= create_mtd_partitions
,
124 module_mtd_part_parser(ar7_parser
);
126 MODULE_LICENSE("GPL");
127 MODULE_AUTHOR( "Felix Fietkau <nbd@openwrt.org>, "
128 "Eugene Konev <ejka@openwrt.org>");
129 MODULE_DESCRIPTION("MTD partitioning for TI AR7");