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
;
91 if (fit_start_sector
% (1<<(PAGE_SHIFT
- SECTOR_SHIFT
)))
94 page
= read_mapping_page(mapping
, fit_start_sector
>> (PAGE_SHIFT
- SECTOR_SHIFT
), NULL
);
101 init_fit
= page_address(page
);
108 if (fdt_check_header(init_fit
)) {
113 dsectors
= get_capacity(state
->bdev
->bd_disk
);
115 dsectors
= (dsectors
>sectors
)?sectors
:dsectors
;
117 dsize
= dsectors
<< SECTOR_SHIFT
;
119 size
= fdt_totalsize(init_fit
);
121 /* silently skip non-external-data legacy FIT images */
122 if (size
> PAGE_SIZE
) {
128 state
->access_beyond_eod
= 1;
133 fit
= kmemdup(init_fit
, size
, GFP_KERNEL
);
138 config
= fdt_path_offset(fit
, FIT_CONFS_PATH
);
140 printk(KERN_ERR
"FIT: Cannot find %s node: %d\n", FIT_CONFS_PATH
, images
);
145 config_default
= fdt_getprop(fit
, config
, FIT_DEFAULT_PROP
, &config_default_len
);
147 if (!config_default
) {
148 printk(KERN_ERR
"FIT: Cannot find default configuration\n");
153 node
= fdt_subnode_offset(fit
, config
, config_default
);
155 printk(KERN_ERR
"FIT: Cannot find %s node: %d\n", config_default
, node
);
160 config_description
= fdt_getprop(fit
, node
, FIT_DESC_PROP
, &config_description_len
);
161 config_loadables
= fdt_getprop(fit
, node
, FIT_LOADABLE_PROP
, &config_loadables_len
);
163 printk(KERN_DEBUG
"FIT: Default configuration: \"%s\"%s%s%s\n", config_default
,
164 config_description
?" (":"", config_description
?:"", config_description
?")":"");
166 images
= fdt_path_offset(fit
, FIT_IMAGES_PATH
);
168 printk(KERN_ERR
"FIT: Cannot find %s node: %d\n", FIT_IMAGES_PATH
, images
);
173 fdt_for_each_subnode(node
, fit
, images
) {
174 image_name
= fdt_get_name(fit
, node
, &image_name_len
);
175 image_type
= fdt_getprop(fit
, node
, FIT_TYPE_PROP
, &image_type_len
);
176 image_offset_be
= fdt_getprop(fit
, node
, FIT_DATA_OFFSET_PROP
, NULL
);
177 image_pos_be
= fdt_getprop(fit
, node
, FIT_DATA_POSITION_PROP
, NULL
);
178 image_len_be
= fdt_getprop(fit
, node
, FIT_DATA_SIZE_PROP
, NULL
);
179 if (!image_name
|| !image_type
|| !image_len_be
)
182 image_len
= be32_to_cpu(*image_len_be
);
187 image_pos
= be32_to_cpu(*image_offset_be
) + size
;
188 else if (image_pos_be
)
189 image_pos
= be32_to_cpu(*image_pos_be
);
193 image_description
= fdt_getprop(fit
, node
, FIT_DESC_PROP
, &image_description_len
);
195 printk(KERN_DEBUG
"FIT: %16s sub-image 0x%08x..0x%08x \"%s\" %s%s%s\n",
196 image_type
, image_pos
, image_pos
+ image_len
- 1, image_name
,
197 image_description
?"(":"", image_description
?:"", image_description
?") ":"");
199 if (strcmp(image_type
, FIT_FILESYSTEM_PROP
))
202 if (image_pos
& ((1 << PAGE_SHIFT
)-1)) {
203 printk(KERN_ERR
"FIT: image %s start not aligned to page boundaries, skipping\n", image_name
);
207 if (image_len
& ((1 << PAGE_SHIFT
)-1)) {
208 printk(KERN_ERR
"FIT: sub-image %s end not aligned to page boundaries, skipping\n", image_name
);
212 start_sect
= image_pos
>> SECTOR_SHIFT
;
213 nr_sects
= image_len
>> SECTOR_SHIFT
;
214 imgmaxsect
= (imgmaxsect
< (start_sect
+ nr_sects
))?(start_sect
+ nr_sects
):imgmaxsect
;
216 if (start_sect
+ nr_sects
> dsectors
) {
217 state
->access_beyond_eod
= 1;
221 put_partition(state
, ++(*slot
), fit_start_sector
+ start_sect
, nr_sects
);
222 state
->parts
[*slot
].flags
= 0;
223 info
= &state
->parts
[*slot
].info
;
225 label_min
= min_t(int, sizeof(info
->volname
) - 1, image_name_len
);
226 strncpy(info
->volname
, image_name
, label_min
);
227 info
->volname
[label_min
] = '\0';
229 snprintf(tmp
, sizeof(tmp
), "(%s)", info
->volname
);
230 strlcat(state
->pp_buf
, tmp
, PAGE_SIZE
);
232 state
->parts
[*slot
].has_info
= true;
234 if (config_loadables
&& !strcmp(image_name
, config_loadables
)) {
235 printk(KERN_DEBUG
"FIT: selecting configured loadable \"%s\" to be root filesystem\n", image_name
);
236 state
->parts
[*slot
].flags
|= ADDPART_FLAG_ROOTDEV
;
240 if (add_remain
&& (imgmaxsect
+ MIN_FREE_SECT
) < dsectors
) {
241 put_partition(state
, ++(*slot
), fit_start_sector
+ imgmaxsect
, dsectors
- imgmaxsect
);
242 state
->parts
[*slot
].flags
= 0;
243 info
= &state
->parts
[*slot
].info
;
244 strcpy(info
->volname
, REMAIN_VOLNAME
);
245 snprintf(tmp
, sizeof(tmp
), "(%s)", REMAIN_VOLNAME
);
246 strlcat(state
->pp_buf
, tmp
, PAGE_SIZE
);
253 int fit_partition(struct parsed_partitions
*state
) {
255 return parse_fit_partitions(state
, 0, 0, &slot
, 0);