1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Copyright (C) 2021 Daniel Golle
6 * headers extracted from U-Boot mkimage sources
7 * (C) Copyright 2008 Semihalf
8 * (C) Copyright 2000-2005
9 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
11 * based on existing partition parsers
12 * Copyright (C) 1991-1998 Linus Torvalds
13 * Re-organised Feb 1998 Russell King
16 #define pr_fmt(fmt) fmt
18 #include <linux/types.h>
20 #include <linux/of_device.h>
21 #include <linux/of_fdt.h>
22 #include <linux/libfdt.h>
26 #define FIT_IMAGES_PATH "/images"
27 #define FIT_CONFS_PATH "/configurations"
29 /* hash/signature/key node */
30 #define FIT_HASH_NODENAME "hash"
31 #define FIT_ALGO_PROP "algo"
32 #define FIT_VALUE_PROP "value"
33 #define FIT_IGNORE_PROP "uboot-ignore"
34 #define FIT_SIG_NODENAME "signature"
35 #define FIT_KEY_REQUIRED "required"
36 #define FIT_KEY_HINT "key-name-hint"
39 #define FIT_CIPHER_NODENAME "cipher"
40 #define FIT_ALGO_PROP "algo"
43 #define FIT_DATA_PROP "data"
44 #define FIT_DATA_POSITION_PROP "data-position"
45 #define FIT_DATA_OFFSET_PROP "data-offset"
46 #define FIT_DATA_SIZE_PROP "data-size"
47 #define FIT_TIMESTAMP_PROP "timestamp"
48 #define FIT_DESC_PROP "description"
49 #define FIT_ARCH_PROP "arch"
50 #define FIT_TYPE_PROP "type"
51 #define FIT_OS_PROP "os"
52 #define FIT_COMP_PROP "compression"
53 #define FIT_ENTRY_PROP "entry"
54 #define FIT_LOAD_PROP "load"
56 /* configuration node */
57 #define FIT_KERNEL_PROP "kernel"
58 #define FIT_FILESYSTEM_PROP "filesystem"
59 #define FIT_RAMDISK_PROP "ramdisk"
60 #define FIT_FDT_PROP "fdt"
61 #define FIT_LOADABLE_PROP "loadables"
62 #define FIT_DEFAULT_PROP "default"
63 #define FIT_SETUP_PROP "setup"
64 #define FIT_FPGA_PROP "fpga"
65 #define FIT_FIRMWARE_PROP "firmware"
66 #define FIT_STANDALONE_PROP "standalone"
68 #define FIT_MAX_HASH_LEN HASH_MAX_DIGEST_SIZE
70 #define MIN_FREE_SECT 16
71 #define REMAIN_VOLNAME "rootfs_data"
73 int parse_fit_partitions(struct parsed_partitions
*state
, u64 fit_start_sector
, u64 sectors
, int *slot
, int add_remain
)
75 struct address_space
*mapping
= state
->bdev
->bd_inode
->i_mapping
;
78 struct partition_meta_info
*info
;
79 char tmp
[sizeof(info
->volname
)];
80 u64 dsize
, dsectors
, imgmaxsect
= 0;
81 u32 size
, image_pos
, image_len
;
82 const u32
*image_offset_be
, *image_len_be
, *image_pos_be
;
83 int ret
= 1, node
, images
, config
;
84 const char *image_name
, *image_type
, *image_description
, *config_default
,
85 *config_description
, *config_loadables
;
86 int image_name_len
, image_type_len
, image_description_len
, config_default_len
,
87 config_description_len
, config_loadables_len
;
88 sector_t start_sect
, nr_sects
;
90 struct device_node
*np
= NULL
;
93 const char *select_rootfs
= NULL
;
95 int loadables_rem_len
, loadable_len
;
97 if (fit_start_sector
% (1<<(PAGE_SHIFT
- SECTOR_SHIFT
)))
100 page
= read_mapping_page(mapping
, fit_start_sector
>> (PAGE_SHIFT
- SECTOR_SHIFT
), NULL
);
107 init_fit
= page_address(page
);
114 if (fdt_check_header(init_fit
)) {
119 dsectors
= get_capacity(state
->bdev
->bd_disk
);
121 dsectors
= (dsectors
>sectors
)?sectors
:dsectors
;
123 dsize
= dsectors
<< SECTOR_SHIFT
;
124 size
= fdt_totalsize(init_fit
);
126 /* silently skip non-external-data legacy FIT images */
127 if (size
> PAGE_SIZE
) {
133 state
->access_beyond_eod
= 1;
138 fit
= kmemdup(init_fit
, size
, GFP_KERNEL
);
143 np
= of_find_node_by_path("/chosen");
145 bootconf
= of_get_property(np
, "bootconf", NULL
);
149 config
= fdt_path_offset(fit
, FIT_CONFS_PATH
);
151 printk(KERN_ERR
"FIT: Cannot find %s node: %d\n", FIT_CONFS_PATH
, images
);
156 config_default
= fdt_getprop(fit
, config
, FIT_DEFAULT_PROP
, &config_default_len
);
158 if (!config_default
&& !bootconf
) {
159 printk(KERN_ERR
"FIT: Cannot find default configuration\n");
164 node
= fdt_subnode_offset(fit
, config
, bootconf
?:config_default
);
166 printk(KERN_ERR
"FIT: Cannot find %s node: %d\n", bootconf
?:config_default
, node
);
171 config_description
= fdt_getprop(fit
, node
, FIT_DESC_PROP
, &config_description_len
);
172 config_loadables
= fdt_getprop(fit
, node
, FIT_LOADABLE_PROP
, &config_loadables_len
);
174 printk(KERN_DEBUG
"FIT: %s configuration: \"%s\"%s%s%s\n",
175 bootconf
?"Selected":"Default", bootconf
?:config_default
,
176 config_description
?" (":"", config_description
?:"", config_description
?")":"");
178 if (!config_loadables
|| !config_loadables_len
) {
179 printk(KERN_ERR
"FIT: No loadables configured in \"%s\"\n", bootconf
?:config_default
);
184 images
= fdt_path_offset(fit
, FIT_IMAGES_PATH
);
186 printk(KERN_ERR
"FIT: Cannot find %s node: %d\n", FIT_IMAGES_PATH
, images
);
191 fdt_for_each_subnode(node
, fit
, images
) {
192 image_name
= fdt_get_name(fit
, node
, &image_name_len
);
193 image_type
= fdt_getprop(fit
, node
, FIT_TYPE_PROP
, &image_type_len
);
194 image_offset_be
= fdt_getprop(fit
, node
, FIT_DATA_OFFSET_PROP
, NULL
);
195 image_pos_be
= fdt_getprop(fit
, node
, FIT_DATA_POSITION_PROP
, NULL
);
196 image_len_be
= fdt_getprop(fit
, node
, FIT_DATA_SIZE_PROP
, NULL
);
197 if (!image_name
|| !image_type
|| !image_len_be
)
200 image_len
= be32_to_cpu(*image_len_be
);
205 image_pos
= be32_to_cpu(*image_offset_be
) + size
;
206 else if (image_pos_be
)
207 image_pos
= be32_to_cpu(*image_pos_be
);
211 image_description
= fdt_getprop(fit
, node
, FIT_DESC_PROP
, &image_description_len
);
213 printk(KERN_DEBUG
"FIT: %16s sub-image 0x%08x..0x%08x \"%s\" %s%s%s\n",
214 image_type
, image_pos
, image_pos
+ image_len
- 1, image_name
,
215 image_description
?"(":"", image_description
?:"", image_description
?") ":"");
217 if (strcmp(image_type
, FIT_FILESYSTEM_PROP
))
220 /* check if sub-image is part of configured loadables */
222 loadable
= config_loadables
;
223 loadables_rem_len
= config_loadables_len
;
224 while (loadables_rem_len
> 1) {
225 loadable_len
= strnlen(loadable
, loadables_rem_len
- 1) + 1;
226 loadables_rem_len
-= loadable_len
;
227 if (!strncmp(image_name
, loadable
, loadable_len
)) {
231 loadable
+= loadable_len
;
236 if (image_pos
& ((1 << PAGE_SHIFT
)-1)) {
237 printk(KERN_ERR
"FIT: image %s start not aligned to page boundaries, skipping\n", image_name
);
241 if (image_len
& ((1 << PAGE_SHIFT
)-1)) {
242 printk(KERN_ERR
"FIT: sub-image %s end not aligned to page boundaries, skipping\n", image_name
);
246 start_sect
= image_pos
>> SECTOR_SHIFT
;
247 nr_sects
= image_len
>> SECTOR_SHIFT
;
248 imgmaxsect
= (imgmaxsect
< (start_sect
+ nr_sects
))?(start_sect
+ nr_sects
):imgmaxsect
;
250 if (start_sect
+ nr_sects
> dsectors
) {
251 state
->access_beyond_eod
= 1;
255 put_partition(state
, ++(*slot
), fit_start_sector
+ start_sect
, nr_sects
);
256 state
->parts
[*slot
].flags
= ADDPART_FLAG_READONLY
;
257 state
->parts
[*slot
].has_info
= true;
258 info
= &state
->parts
[*slot
].info
;
260 label_min
= min_t(int, sizeof(info
->volname
) - 1, image_name_len
);
261 strncpy(info
->volname
, image_name
, label_min
);
262 info
->volname
[label_min
] = '\0';
264 snprintf(tmp
, sizeof(tmp
), "(%s)", info
->volname
);
265 strlcat(state
->pp_buf
, tmp
, PAGE_SIZE
);
267 /* Mark first loadable listed to be mounted as rootfs */
268 if (!strcmp(image_name
, config_loadables
)) {
269 select_rootfs
= image_name
;
270 state
->parts
[*slot
].flags
|= ADDPART_FLAG_ROOTDEV
;
275 printk(KERN_DEBUG
"FIT: selecting configured loadable \"%s\" to be root filesystem\n", select_rootfs
);
277 if (add_remain
&& (imgmaxsect
+ MIN_FREE_SECT
) < dsectors
) {
278 put_partition(state
, ++(*slot
), fit_start_sector
+ imgmaxsect
, dsectors
- imgmaxsect
);
279 state
->parts
[*slot
].flags
= 0;
280 info
= &state
->parts
[*slot
].info
;
281 strcpy(info
->volname
, REMAIN_VOLNAME
);
282 snprintf(tmp
, sizeof(tmp
), "(%s)", REMAIN_VOLNAME
);
283 strlcat(state
->pp_buf
, tmp
, PAGE_SIZE
);
290 int fit_partition(struct parsed_partitions
*state
) {
292 return parse_fit_partitions(state
, 0, 0, &slot
, 0);