kernel: mtdsplit: modify rootfs helpers to provide partition type
[openwrt.git] / target / linux / generic / files / drivers / mtd / mtdsplit / mtdsplit_eva.c
1 /*
2  *  Copyright (C) 2012 John Crispin <blogic@openwrt.org>
3  *  Copyright (C) 2015 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
4  *
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.
8  *
9  */
10
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>
18
19 #include "mtdsplit.h"
20
21 #define EVA_NR_PARTS            2
22 #define EVA_MAGIC               0xfeed1281
23 #define EVA_FOOTER_SIZE         0x18
24 #define EVA_DUMMY_SQUASHFS_SIZE 0x100
25
26 struct eva_image_header {
27         uint32_t        magic;
28         uint32_t        size;
29 };
30
31 static int mtdsplit_parse_eva(struct mtd_info *master,
32                                 struct mtd_partition **pparts,
33                                 struct mtd_part_parser_data *data)
34 {
35         struct mtd_partition *parts;
36         struct eva_image_header hdr;
37         size_t retlen;
38         unsigned long kernel_size, rootfs_offset;
39         int err;
40
41         err = mtd_read(master, 0, sizeof(hdr), &retlen, (void *) &hdr);
42         if (err)
43                 return err;
44
45         if (retlen != sizeof(hdr))
46                 return -EIO;
47
48         if (le32_to_cpu(hdr.magic) != EVA_MAGIC)
49                 return -EINVAL;
50
51         kernel_size = le32_to_cpu(hdr.size) + EVA_FOOTER_SIZE;
52
53         /* rootfs starts at the next 0x10000 boundary: */
54         rootfs_offset = round_up(kernel_size, 0x10000);
55
56         /* skip the dummy EVA squashfs partition (with wrong endianness): */
57         rootfs_offset += EVA_DUMMY_SQUASHFS_SIZE;
58
59         if (rootfs_offset >= master->size)
60                 return -EINVAL;
61
62         err = mtd_check_rootfs_magic(master, rootfs_offset, NULL);
63         if (err)
64                 return err;
65
66         parts = kzalloc(EVA_NR_PARTS * sizeof(*parts), GFP_KERNEL);
67         if (!parts)
68                 return -ENOMEM;
69
70         parts[0].name = KERNEL_PART_NAME;
71         parts[0].offset = 0;
72         parts[0].size = kernel_size;
73
74         parts[1].name = ROOTFS_PART_NAME;
75         parts[1].offset = rootfs_offset;
76         parts[1].size = master->size - rootfs_offset;
77
78         *pparts = parts;
79         return EVA_NR_PARTS;
80 }
81
82 static struct mtd_part_parser mtdsplit_eva_parser = {
83         .owner = THIS_MODULE,
84         .name = "eva-fw",
85         .parse_fn = mtdsplit_parse_eva,
86         .type = MTD_PARSER_TYPE_FIRMWARE,
87 };
88
89 static int __init mtdsplit_eva_init(void)
90 {
91         register_mtd_parser(&mtdsplit_eva_parser);
92
93         return 0;
94 }
95
96 subsys_initcall(mtdsplit_eva_init);