2 * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
3 * Copyright (C) 2015 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
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 #include <linux/module.h>
12 #include <linux/init.h>
13 #include <linux/kernel.h>
14 #include <linux/slab.h>
15 #include <linux/mtd/mtd.h>
16 #include <linux/mtd/partitions.h>
17 #include <linux/byteorder/generic.h>
22 #define EVA_NR_PARTS 2
23 #define EVA_MAGIC 0xfeed1281
24 #define EVA_FOOTER_SIZE 0x18
25 #define EVA_DUMMY_SQUASHFS_SIZE 0x100
27 struct eva_image_header
{
32 static int mtdsplit_parse_eva(struct mtd_info
*master
,
33 const struct mtd_partition
**pparts
,
34 struct mtd_part_parser_data
*data
)
36 struct mtd_partition
*parts
;
37 struct eva_image_header hdr
;
39 unsigned long kernel_size
, rootfs_offset
;
42 err
= mtd_read(master
, 0, sizeof(hdr
), &retlen
, (void *) &hdr
);
46 if (retlen
!= sizeof(hdr
))
49 if (le32_to_cpu(hdr
.magic
) != EVA_MAGIC
)
52 kernel_size
= le32_to_cpu(hdr
.size
) + EVA_FOOTER_SIZE
;
54 /* rootfs starts at the next 0x10000 boundary: */
55 rootfs_offset
= round_up(kernel_size
, 0x10000);
57 /* skip the dummy EVA squashfs partition (with wrong endianness): */
58 rootfs_offset
+= EVA_DUMMY_SQUASHFS_SIZE
;
60 if (rootfs_offset
>= master
->size
)
63 err
= mtd_check_rootfs_magic(master
, rootfs_offset
, NULL
);
67 parts
= kzalloc(EVA_NR_PARTS
* sizeof(*parts
), GFP_KERNEL
);
71 parts
[0].name
= KERNEL_PART_NAME
;
73 parts
[0].size
= kernel_size
;
75 parts
[1].name
= ROOTFS_PART_NAME
;
76 parts
[1].offset
= rootfs_offset
;
77 parts
[1].size
= master
->size
- rootfs_offset
;
83 static const struct of_device_id mtdsplit_eva_of_match_table
[] = {
84 { .compatible
= "avm,eva-firmware" },
88 static struct mtd_part_parser mtdsplit_eva_parser
= {
91 .of_match_table
= mtdsplit_eva_of_match_table
,
92 .parse_fn
= mtdsplit_parse_eva
,
93 .type
= MTD_PARSER_TYPE_FIRMWARE
,
96 static int __init
mtdsplit_eva_init(void)
98 register_mtd_parser(&mtdsplit_eva_parser
);
103 subsys_initcall(mtdsplit_eva_init
);