2 * Copyright (c) 2015 The Linux Foundation
3 * Copyright (C) 2014 Gabor Juhos <juhosg@openwrt.org>
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 #include <linux/module.h>
19 #include <linux/mtd/mtd.h>
20 #include <linux/mtd/partitions.h>
21 #include <linux/types.h>
22 #include <linux/byteorder/generic.h>
23 #include <linux/slab.h>
24 #include <linux/of_fdt.h>
29 uint32_t magic
; /* magic word FDT_MAGIC */
30 uint32_t totalsize
; /* total size of DT block */
31 uint32_t off_dt_struct
; /* offset to structure */
32 uint32_t off_dt_strings
; /* offset to strings */
33 uint32_t off_mem_rsvmap
; /* offset to memory reserve map */
34 uint32_t version
; /* format version */
35 uint32_t last_comp_version
; /* last compatible version */
37 /* version 2 fields below */
38 uint32_t boot_cpuid_phys
; /* Which physical CPU id we're
40 /* version 3 fields below */
41 uint32_t size_dt_strings
; /* size of the strings block */
43 /* version 17 fields below */
44 uint32_t size_dt_struct
; /* size of the structure block */
48 mtdsplit_fit_parse(struct mtd_info
*mtd
,
49 const struct mtd_partition
**pparts
,
50 struct mtd_part_parser_data
*data
)
52 struct device_node
*np
= mtd_get_of_node(mtd
);
53 const char *cmdline_match
= NULL
;
54 struct fdt_header hdr
;
55 size_t hdr_len
, retlen
;
57 size_t fit_offset
, fit_size
;
58 size_t rootfs_offset
, rootfs_size
;
59 struct mtd_partition
*parts
;
62 of_property_read_string(np
, "openwrt,cmdline-match", &cmdline_match
);
63 if (cmdline_match
&& !strstr(saved_command_line
, cmdline_match
))
66 hdr_len
= sizeof(struct fdt_header
);
68 /* Parse the MTD device & search for the FIT image location */
69 for(offset
= 0; offset
+ hdr_len
<= mtd
->size
; offset
+= mtd
->erasesize
) {
70 ret
= mtd_read(mtd
, offset
, hdr_len
, &retlen
, (void*) &hdr
);
72 pr_err("read error in \"%s\" at offset 0x%llx\n",
73 mtd
->name
, (unsigned long long) offset
);
77 if (retlen
!= hdr_len
) {
78 pr_err("short read in \"%s\"\n", mtd
->name
);
82 /* Check the magic - see if this is a FIT image */
83 if (be32_to_cpu(hdr
.magic
) != OF_DT_HEADER
) {
84 pr_debug("no valid FIT image found in \"%s\" at offset %llx\n",
85 mtd
->name
, (unsigned long long) offset
);
89 /* We found a FIT image. Let's keep going */
94 fit_size
= be32_to_cpu(hdr
.totalsize
);
97 pr_err("FIT image in \"%s\" at offset %llx has null size\n",
98 mtd
->name
, (unsigned long long) fit_offset
);
102 /* Search for the rootfs partition after the FIT image */
103 ret
= mtd_find_rootfs_from(mtd
, fit_offset
+ fit_size
, mtd
->size
,
104 &rootfs_offset
, NULL
);
106 pr_info("no rootfs found after FIT image in \"%s\"\n",
111 rootfs_size
= mtd
->size
- rootfs_offset
;
113 parts
= kzalloc(2 * sizeof(*parts
), GFP_KERNEL
);
117 parts
[0].name
= KERNEL_PART_NAME
;
118 parts
[0].offset
= fit_offset
;
119 parts
[0].size
= mtd_rounddown_to_eb(fit_size
, mtd
) + mtd
->erasesize
;
121 parts
[1].name
= ROOTFS_PART_NAME
;
122 parts
[1].offset
= rootfs_offset
;
123 parts
[1].size
= rootfs_size
;
129 static const struct of_device_id mtdsplit_fit_of_match_table
[] = {
130 { .compatible
= "denx,fit" },
134 static struct mtd_part_parser uimage_parser
= {
135 .owner
= THIS_MODULE
,
137 .of_match_table
= mtdsplit_fit_of_match_table
,
138 .parse_fn
= mtdsplit_fit_parse
,
139 .type
= MTD_PARSER_TYPE_FIRMWARE
,
142 /**************************************************
144 **************************************************/
146 static int __init
mtdsplit_fit_init(void)
148 register_mtd_parser(&uimage_parser
);
153 module_init(mtdsplit_fit_init
);