Blame view

drivers/mtd/ar7part.c 4.1 KB
f0797881d   Matteo Croce   [MTD] AR7 mtd par...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  /*
   * Copyright © 2007 Eugene Konev <ejka@openwrt.org>
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   *
   * TI AR7 flash partition table.
   * Based on ar7 map by Felix Fietkau <nbd@openwrt.org>
   *
   */
  
  #include <linux/kernel.h>
  #include <linux/slab.h>
  
  #include <linux/mtd/mtd.h>
  #include <linux/mtd/partitions.h>
  #include <linux/bootmem.h>
  #include <linux/magic.h>
a0e5cc581   Paul Gortmaker   mtd: Add module.h...
30
  #include <linux/module.h>
f0797881d   Matteo Croce   [MTD] AR7 mtd par...
31
32
33
34
35
36
  
  #define AR7_PARTS	4
  #define ROOT_OFFSET	0xe0000
  
  #define LOADER_MAGIC1	le32_to_cpu(0xfeedfa42)
  #define LOADER_MAGIC2	le32_to_cpu(0xfeed1281)
986ee0139   David Woodhouse   [MTD] Clean up AR...
37
38
39
  #ifndef SQUASHFS_MAGIC
  #define SQUASHFS_MAGIC	0x73717368
  #endif
f0797881d   Matteo Croce   [MTD] AR7 mtd par...
40
41
42
43
44
  struct ar7_bin_rec {
  	unsigned int checksum;
  	unsigned int length;
  	unsigned int address;
  };
f0797881d   Matteo Croce   [MTD] AR7 mtd par...
45
46
  static int create_mtd_partitions(struct mtd_info *master,
  				 struct mtd_partition **pparts,
c79753301   Dmitry Eremin-Solenikov   mtd: abstract las...
47
  				 struct mtd_part_parser_data *data)
f0797881d   Matteo Croce   [MTD] AR7 mtd par...
48
49
  {
  	struct ar7_bin_rec header;
986ee0139   David Woodhouse   [MTD] Clean up AR...
50
51
  	unsigned int offset;
  	size_t len;
f0797881d   Matteo Croce   [MTD] AR7 mtd par...
52
53
54
55
  	unsigned int pre_size = master->erasesize, post_size = 0;
  	unsigned int root_offset = ROOT_OFFSET;
  
  	int retries = 10;
17b536cc4   Atsushi Nemoto   [MTD] mtdpart: Ma...
56
  	struct mtd_partition *ar7_parts;
f0797881d   Matteo Croce   [MTD] AR7 mtd par...
57

17b536cc4   Atsushi Nemoto   [MTD] mtdpart: Ma...
58
59
60
  	ar7_parts = kzalloc(sizeof(*ar7_parts) * AR7_PARTS, GFP_KERNEL);
  	if (!ar7_parts)
  		return -ENOMEM;
f0797881d   Matteo Croce   [MTD] AR7 mtd par...
61
62
63
64
65
66
67
68
69
70
71
72
  	ar7_parts[0].name = "loader";
  	ar7_parts[0].offset = 0;
  	ar7_parts[0].size = master->erasesize;
  	ar7_parts[0].mask_flags = MTD_WRITEABLE;
  
  	ar7_parts[1].name = "config";
  	ar7_parts[1].offset = 0;
  	ar7_parts[1].size = master->erasesize;
  	ar7_parts[1].mask_flags = 0;
  
  	do { /* Try 10 blocks starting from master->erasesize */
  		offset = pre_size;
329ad399a   Artem Bityutskiy   mtd: introduce mt...
73
74
  		mtd_read(master, offset, sizeof(header), &len,
  			 (uint8_t *)&header);
f0797881d   Matteo Croce   [MTD] AR7 mtd par...
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
  		if (!strncmp((char *)&header, "TIENV0.8", 8))
  			ar7_parts[1].offset = pre_size;
  		if (header.checksum == LOADER_MAGIC1)
  			break;
  		if (header.checksum == LOADER_MAGIC2)
  			break;
  		pre_size += master->erasesize;
  	} while (retries--);
  
  	pre_size = offset;
  
  	if (!ar7_parts[1].offset) {
  		ar7_parts[1].offset = master->size - master->erasesize;
  		post_size = master->erasesize;
  	}
  
  	switch (header.checksum) {
  	case LOADER_MAGIC1:
  		while (header.length) {
  			offset += sizeof(header) + header.length;
329ad399a   Artem Bityutskiy   mtd: introduce mt...
95
96
  			mtd_read(master, offset, sizeof(header), &len,
  				 (uint8_t *)&header);
f0797881d   Matteo Croce   [MTD] AR7 mtd par...
97
98
99
100
101
102
  		}
  		root_offset = offset + sizeof(header) + 4;
  		break;
  	case LOADER_MAGIC2:
  		while (header.length) {
  			offset += sizeof(header) + header.length;
329ad399a   Artem Bityutskiy   mtd: introduce mt...
103
104
  			mtd_read(master, offset, sizeof(header), &len,
  				 (uint8_t *)&header);
f0797881d   Matteo Croce   [MTD] AR7 mtd par...
105
106
  		}
  		root_offset = offset + sizeof(header) + 4 + 0xff;
986ee0139   David Woodhouse   [MTD] Clean up AR...
107
  		root_offset &= ~(uint32_t)0xff;
f0797881d   Matteo Croce   [MTD] AR7 mtd par...
108
109
110
111
112
113
  		break;
  	default:
  		printk(KERN_WARNING "Unknown magic: %08x
  ", header.checksum);
  		break;
  	}
329ad399a   Artem Bityutskiy   mtd: introduce mt...
114
  	mtd_read(master, root_offset, sizeof(header), &len, (u8 *)&header);
f0797881d   Matteo Croce   [MTD] AR7 mtd par...
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
  	if (header.checksum != SQUASHFS_MAGIC) {
  		root_offset += master->erasesize - 1;
  		root_offset &= ~(master->erasesize - 1);
  	}
  
  	ar7_parts[2].name = "linux";
  	ar7_parts[2].offset = pre_size;
  	ar7_parts[2].size = master->size - pre_size - post_size;
  	ar7_parts[2].mask_flags = 0;
  
  	ar7_parts[3].name = "rootfs";
  	ar7_parts[3].offset = root_offset;
  	ar7_parts[3].size = master->size - root_offset - post_size;
  	ar7_parts[3].mask_flags = 0;
  
  	*pparts = ar7_parts;
  	return AR7_PARTS;
  }
  
  static struct mtd_part_parser ar7_parser = {
  	.owner = THIS_MODULE,
  	.parse_fn = create_mtd_partitions,
  	.name = "ar7part",
  };
  
  static int __init ar7_parser_init(void)
  {
  	return register_mtd_parser(&ar7_parser);
  }
  
  module_init(ar7_parser_init);
  
  MODULE_LICENSE("GPL");
  MODULE_AUTHOR(	"Felix Fietkau <nbd@openwrt.org>, "
  		"Eugene Konev <ejka@openwrt.org>");
  MODULE_DESCRIPTION("MTD partitioning for TI AR7");