4 * Copyright (C) 2007 OpenWrt.org
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * TI AR7 flash partition table.
21 * Based on ar7 map by Felix Fietkau.
25 #include <linux/kernel.h>
26 #include <linux/slab.h>
28 #include <linux/mtd/mtd.h>
29 #include <linux/mtd/partitions.h>
30 #include <linux/bootmem.h>
31 #include <linux/squashfs_fs.h>
34 unsigned int checksum
;
39 static struct mtd_partition ar7_parts
[5];
41 static int create_mtd_partitions(struct mtd_info
*master
,
42 struct mtd_partition
**pparts
,
46 struct ar7_bin_rec header
;
47 unsigned int offset
, new_offset
, len
;
48 struct squashfs_super_block sb
;
49 unsigned int block_size
= 0x10000, pre_size
= 0x10000,
50 post_size
= 0, root_offset
= 0xe0000;
53 printk("Parsing AR7 partition map...\n");
55 ar7_parts
[0].name
= "loader";
56 ar7_parts
[0].offset
= 0;
57 ar7_parts
[0].size
= block_size
;
58 ar7_parts
[0].mask_flags
= MTD_WRITEABLE
;
60 ar7_parts
[1].name
= "config";
61 ar7_parts
[1].size
= block_size
;
62 ar7_parts
[1].mask_flags
= 0;
64 master
->read(master
, block_size
, 8, &len
, sig
);
65 if (strncmp(sig
, "TIENV0.8", 8)) {
66 ar7_parts
[1].offset
= master
->size
- block_size
;
67 post_size
= block_size
;
69 ar7_parts
[1].offset
= block_size
;
70 pre_size
= block_size
* 2;
73 ar7_parts
[2].name
= "linux";
74 ar7_parts
[2].offset
= pre_size
;
75 ar7_parts
[2].size
= master
->size
- block_size
* 2;
76 ar7_parts
[2].mask_flags
= 0;
79 master
->read(master
, offset
, sizeof(header
), &len
, (u_char
*)&header
);
80 if (header
.checksum
!= 0xfeedfa42) {
81 printk("Unknown magic: %08x\n", header
.checksum
);
83 while (header
.length
) {
84 offset
+= sizeof(header
) + header
.length
;
85 master
->read(master
, offset
, sizeof(header
),
86 &len
, (u_char
*)&header
);
88 root_offset
= offset
+ sizeof(header
) + 4;
91 ar7_parts
[p
].name
= "rootfs";
92 ar7_parts
[p
].offset
= root_offset
;
93 ar7_parts
[p
].size
= master
->size
- root_offset
- post_size
;
94 ar7_parts
[p
++].mask_flags
= 0;
96 master
->read(master
, root_offset
, sizeof(sb
), &len
, (u_char
*)&sb
);
97 if (sb
.s_magic
== SQUASHFS_MAGIC
) {
98 printk("Squashfs detected (size %Ld)\n", sb
.bytes_used
);
99 new_offset
= root_offset
+ sb
.bytes_used
;
101 if ((new_offset
% master
->erasesize
) > 0)
102 new_offset
+= master
->erasesize
-
103 (new_offset
% master
->erasesize
);
105 ar7_parts
[p
].name
= "rootfs_data";
106 ar7_parts
[p
].offset
= new_offset
;
107 ar7_parts
[p
].size
= master
->size
- new_offset
- post_size
;
108 ar7_parts
[p
- 1].size
-= ar7_parts
[p
].size
;
109 ar7_parts
[p
- 1].mask_flags
|= MTD_WRITEABLE
;
110 ar7_parts
[p
++].mask_flags
= 0;
112 printk("Squashfs not found. Moving rootfs partition to next erase block\n");
113 if ((root_offset
% master
->erasesize
) > 0)
114 root_offset
+= master
->erasesize
-
115 (root_offset
% master
->erasesize
);
117 ar7_parts
[p
].offset
= root_offset
;
118 ar7_parts
[p
].size
= master
->size
- root_offset
- post_size
;
124 static struct mtd_part_parser ar7_parser
= {
125 .owner
= THIS_MODULE
,
126 .parse_fn
= create_mtd_partitions
,
130 static int __init
ar7_parser_init(void)
132 return register_mtd_parser(&ar7_parser
);
135 module_init(ar7_parser_init
);
137 MODULE_LICENSE("GPL");
138 MODULE_AUTHOR("Felix Fietkau, Eugene Konev");
139 MODULE_DESCRIPTION("MTD partitioning for TI AR7");