2 * Copyright (C) 2013 Gabor Juhos <juhosg@openwrt.org>
3 * Copyright (C) 2014 Felix Fietkau <nbd@nbd.name>
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published
7 * by the Free Software Foundation.
11 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13 #include <linux/module.h>
14 #include <linux/init.h>
15 #include <linux/kernel.h>
16 #include <linux/slab.h>
17 #include <linux/mtd/mtd.h>
18 #include <linux/mtd/partitions.h>
19 #include <linux/byteorder/generic.h>
24 #define TRX_MAGIC 0x30524448 /* "HDR0" */
35 read_trx_header(struct mtd_info
*mtd
, size_t offset
,
36 struct trx_header
*header
)
42 header_len
= sizeof(*header
);
43 ret
= mtd_read(mtd
, offset
, header_len
, &retlen
,
44 (unsigned char *) header
);
46 pr_debug("read error in \"%s\"\n", mtd
->name
);
50 if (retlen
!= header_len
) {
51 pr_debug("short read in \"%s\"\n", mtd
->name
);
59 mtdsplit_parse_trx(struct mtd_info
*master
,
60 const struct mtd_partition
**pparts
,
61 struct mtd_part_parser_data
*data
)
63 struct mtd_partition
*parts
;
64 struct trx_header hdr
;
70 size_t rootfs_size
= 0;
74 parts
= kzalloc(nr_parts
* sizeof(*parts
), GFP_KERNEL
);
78 /* find trx image on erase block boundaries */
79 for (offset
= 0; offset
< master
->size
; offset
+= master
->erasesize
) {
82 ret
= read_trx_header(master
, offset
, &hdr
);
86 if (hdr
.magic
!= cpu_to_le32(TRX_MAGIC
)) {
87 pr_debug("no valid trx header found in \"%s\" at offset %llx\n",
88 master
->name
, (unsigned long long) offset
);
92 trx_size
= le32_to_cpu(hdr
.len
);
93 if ((offset
+ trx_size
) > master
->size
) {
94 pr_debug("trx image exceeds MTD device \"%s\"\n",
102 pr_debug("no trx header found in \"%s\"\n", master
->name
);
107 trx_offset
= offset
+ hdr
.offset
[0];
108 rootfs_offset
= offset
+ hdr
.offset
[1];
109 rootfs_size
= master
->size
- rootfs_offset
;
110 trx_size
= rootfs_offset
- trx_offset
;
112 if (rootfs_size
== 0) {
113 pr_debug("no rootfs found in \"%s\"\n", master
->name
);
118 parts
[0].name
= KERNEL_PART_NAME
;
119 parts
[0].offset
= trx_offset
;
120 parts
[0].size
= trx_size
;
122 parts
[1].name
= ROOTFS_PART_NAME
;
123 parts
[1].offset
= rootfs_offset
;
124 parts
[1].size
= rootfs_size
;
134 static const struct of_device_id trx_parser_of_match_table
[] = {
135 { .compatible
= "openwrt,trx" },
138 MODULE_DEVICE_TABLE(of
, trx_parser_of_match_table
);
140 static struct mtd_part_parser trx_parser
= {
141 .owner
= THIS_MODULE
,
143 .of_match_table
= trx_parser_of_match_table
,
144 .parse_fn
= mtdsplit_parse_trx
,
145 .type
= MTD_PARSER_TYPE_FIRMWARE
,
148 static int __init
mtdsplit_trx_init(void)
150 register_mtd_parser(&trx_parser
);
155 module_init(mtdsplit_trx_init
);