2 * Copyright (C) 2014 Gabor Juhos <juhosg@openwrt.org>
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 as published
6 * by the Free Software Foundation.
10 #include <linux/module.h>
11 #include <linux/init.h>
12 #include <linux/kernel.h>
13 #include <linux/slab.h>
14 #include <linux/mtd/mtd.h>
15 #include <linux/mtd/partitions.h>
17 #include <asm/unaligned.h>
21 #define LZMA_NR_PARTS 2
22 #define LZMA_PROPERTIES_SIZE 5
25 u8 props
[LZMA_PROPERTIES_SIZE
];
30 static int mtdsplit_parse_lzma(struct mtd_info
*master
,
31 const struct mtd_partition
**pparts
,
32 struct mtd_part_parser_data
*data
)
34 struct lzma_header hdr
;
35 size_t hdr_len
, retlen
;
38 struct mtd_partition
*parts
;
41 hdr_len
= sizeof(hdr
);
42 err
= mtd_read(master
, 0, hdr_len
, &retlen
, (void *) &hdr
);
46 if (retlen
!= hdr_len
)
49 /* verify LZMA properties */
50 if (hdr
.props
[0] >= (9 * 5 * 5))
53 t
= get_unaligned_le32(&hdr
.props
[1]);
54 if (!is_power_of_2(t
))
57 t
= get_unaligned_le32(&hdr
.size_high
);
61 err
= mtd_find_rootfs_from(master
, master
->erasesize
, master
->size
,
62 &rootfs_offset
, NULL
);
66 parts
= kzalloc(LZMA_NR_PARTS
* sizeof(*parts
), GFP_KERNEL
);
70 parts
[0].name
= KERNEL_PART_NAME
;
72 parts
[0].size
= rootfs_offset
;
74 parts
[1].name
= ROOTFS_PART_NAME
;
75 parts
[1].offset
= rootfs_offset
;
76 parts
[1].size
= master
->size
- rootfs_offset
;
82 static const struct of_device_id mtdsplit_lzma_of_match_table
[] = {
83 { .compatible
= "lzma" },
86 MODULE_DEVICE_TABLE(of
, mtdsplit_lzma_of_match_table
);
88 static struct mtd_part_parser mtdsplit_lzma_parser
= {
91 .of_match_table
= mtdsplit_lzma_of_match_table
,
92 .parse_fn
= mtdsplit_parse_lzma
,
93 .type
= MTD_PARSER_TYPE_FIRMWARE
,
96 static int __init
mtdsplit_lzma_init(void)
98 register_mtd_parser(&mtdsplit_lzma_parser
);
103 subsys_initcall(mtdsplit_lzma_init
);