2 * Copyright (C) 2013 Gabor Juhos <juhosg@openwrt.org>
3 * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
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>
23 #define TRX_MAGIC 0x30524448 /* "HDR0" */
34 read_trx_header(struct mtd_info
*mtd
, size_t offset
,
35 struct trx_header
*header
)
41 header_len
= sizeof(*header
);
42 ret
= mtd_read(mtd
, offset
, header_len
, &retlen
,
43 (unsigned char *) header
);
45 pr_debug("read error in \"%s\"\n", mtd
->name
);
49 if (retlen
!= header_len
) {
50 pr_debug("short read in \"%s\"\n", mtd
->name
);
58 mtdsplit_parse_trx(struct mtd_info
*master
,
59 struct mtd_partition
**pparts
,
60 struct mtd_part_parser_data
*data
)
62 struct mtd_partition
*parts
;
63 struct trx_header hdr
;
69 size_t rootfs_size
= 0;
73 parts
= kzalloc(nr_parts
* sizeof(*parts
), GFP_KERNEL
);
77 /* find trx image on erase block boundaries */
78 for (offset
= 0; offset
< master
->size
; offset
+= master
->erasesize
) {
81 ret
= read_trx_header(master
, offset
, &hdr
);
85 if (hdr
.magic
!= cpu_to_le32(TRX_MAGIC
)) {
86 pr_debug("no valid trx header found in \"%s\" at offset %llx\n",
87 master
->name
, (unsigned long long) offset
);
91 trx_size
= le32_to_cpu(hdr
.len
);
92 if ((offset
+ trx_size
) > master
->size
) {
93 pr_debug("trx image exceeds MTD device \"%s\"\n",
101 pr_debug("no trx header found in \"%s\"\n", master
->name
);
106 trx_offset
= offset
+ hdr
.offset
[0];
107 rootfs_offset
= offset
+ hdr
.offset
[1];
108 rootfs_size
= master
->size
- rootfs_offset
;
109 trx_size
= rootfs_offset
- trx_offset
;
111 if (rootfs_size
== 0) {
112 pr_debug("no rootfs found in \"%s\"\n", master
->name
);
117 parts
[0].name
= KERNEL_PART_NAME
;
118 parts
[0].offset
= trx_offset
;
119 parts
[0].size
= trx_size
;
121 parts
[1].name
= ROOTFS_PART_NAME
;
122 parts
[1].offset
= rootfs_offset
;
123 parts
[1].size
= rootfs_size
;
133 static struct mtd_part_parser trx_parser
= {
134 .owner
= THIS_MODULE
,
136 .parse_fn
= mtdsplit_parse_trx
,
137 .type
= MTD_PARSER_TYPE_FIRMWARE
,
140 static int __init
mtdsplit_trx_init(void)
142 register_mtd_parser(&trx_parser
);
147 module_init(mtdsplit_trx_init
);