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 int fit_partition(struct parsed_partitions
*state
)
72 struct address_space
*mapping
= state
->bdev
->bd_inode
->i_mapping
;
73 struct page
*page
= read_mapping_page(mapping
, 0, NULL
);
75 struct partition_meta_info
*info
;
76 char tmp
[sizeof(info
->volname
)];
78 u32 size
, image_pos
, image_len
;
79 const u32
*image_offset_be
, *image_len_be
, *image_pos_be
;
80 int ret
= 1, node
, images
, config
, slot
;
81 const char *image_name
, *image_type
, *image_description
, *config_default
,
82 *config_description
, *config_loadables
;
83 int image_name_len
, image_type_len
, image_description_len
, config_default_len
,
84 config_description_len
, config_loadables_len
;
85 sector_t start_sect
, nr_sects
;
91 init_fit
= page_address(page
);
98 if (fdt_check_header(init_fit
)) {
103 dsectors
= get_capacity(state
->bdev
->bd_disk
);
104 dsize
= dsectors
<< SECTOR_SHIFT
;
105 printk(KERN_DEBUG
"FIT: volume size: %llu sectors (%llu bytes)\n", dsectors
, dsize
);
107 size
= fdt_totalsize(init_fit
);
108 printk(KERN_DEBUG
"FIT: FDT structure size: %u bytes\n", size
);
109 if (size
> PAGE_SIZE
) {
110 printk(KERN_ERR
"FIT: FDT structure beyond page boundaries, use 'mkimage -E ...'!\n");
117 state
->access_beyond_eod
= (size
>= dsize
);
121 fit
= kmemdup(init_fit
, size
, GFP_KERNEL
);
126 config
= fdt_path_offset(fit
, FIT_CONFS_PATH
);
128 printk(KERN_ERR
"FIT: Cannot find %s node: %d\n", FIT_CONFS_PATH
, images
);
133 config_default
= fdt_getprop(fit
, config
, FIT_DEFAULT_PROP
, &config_default_len
);
135 if (!config_default
) {
136 printk(KERN_ERR
"FIT: Cannot find default configuration\n");
141 node
= fdt_subnode_offset(fit
, config
, config_default
);
143 printk(KERN_ERR
"FIT: Cannot find %s node: %d\n", config_default
, node
);
148 config_description
= fdt_getprop(fit
, node
, FIT_DESC_PROP
, &config_description_len
);
149 config_loadables
= fdt_getprop(fit
, node
, FIT_LOADABLE_PROP
, &config_loadables_len
);
151 printk(KERN_DEBUG
"FIT: Default configuration: %s%s%s%s\n", config_default
,
152 config_description
?" (":"", config_description
?:"", config_description
?")":"");
154 images
= fdt_path_offset(fit
, FIT_IMAGES_PATH
);
156 printk(KERN_ERR
"FIT: Cannot find %s node: %d\n", FIT_IMAGES_PATH
, images
);
162 fdt_for_each_subnode(node
, fit
, images
) {
163 image_name
= fdt_get_name(fit
, node
, &image_name_len
);
164 image_type
= fdt_getprop(fit
, node
, FIT_TYPE_PROP
, &image_type_len
);
165 image_offset_be
= fdt_getprop(fit
, node
, FIT_DATA_OFFSET_PROP
, NULL
);
166 image_pos_be
= fdt_getprop(fit
, node
, FIT_DATA_POSITION_PROP
, NULL
);
167 image_len_be
= fdt_getprop(fit
, node
, FIT_DATA_SIZE_PROP
, NULL
);
168 if (!image_name
|| !image_type
|| !image_len_be
)
171 image_len
= be32_to_cpu(*image_len_be
);
176 image_pos
= be32_to_cpu(*image_offset_be
) + size
;
177 else if (image_pos_be
)
178 image_pos
= be32_to_cpu(*image_pos_be
);
182 image_description
= fdt_getprop(fit
, node
, FIT_DESC_PROP
, &image_description_len
);
184 printk(KERN_DEBUG
"FIT: %16s sub-image 0x%08x - 0x%08x '%s' %s%s%s\n",
185 image_type
, image_pos
, image_pos
+ image_len
, image_name
,
186 image_description
?"(":"", image_description
?:"", image_description
?") ":"");
188 if (strcmp(image_type
, FIT_FILESYSTEM_PROP
))
191 if (image_pos
& ((1 << PAGE_SHIFT
)-1)) {
192 printk(KERN_ERR
"FIT: image %s start not aligned to page boundaries, skipping\n", image_name
);
196 if (image_len
& ((1 << PAGE_SHIFT
)-1)) {
197 printk(KERN_ERR
"FIT: sub-image %s end not aligned to page boundaries, skipping\n", image_name
);
201 start_sect
= image_pos
>> SECTOR_SHIFT
;
202 nr_sects
= image_len
>> SECTOR_SHIFT
;
204 if (start_sect
+ nr_sects
> dsectors
) {
205 state
->access_beyond_eod
= 1;
209 put_partition(state
, slot
, start_sect
, nr_sects
);
210 state
->parts
[slot
].flags
= 0;
211 info
= &state
->parts
[slot
].info
;
213 label_min
= min_t(int, sizeof(info
->volname
) - 1, image_name_len
);
214 strncpy(info
->volname
, image_name
, label_min
);
215 info
->volname
[label_min
] = '\0';
217 snprintf(tmp
, sizeof(tmp
), "(%s)", info
->volname
);
218 strlcat(state
->pp_buf
, tmp
, PAGE_SIZE
);
220 state
->parts
[slot
].has_info
= true;
222 if (config_loadables
&& !strcmp(image_name
, config_loadables
)) {
223 printk(KERN_DEBUG
"FIT: selecting configured loadable %s to be root filesystem\n", image_name
);
224 state
->parts
[slot
].flags
|= ADDPART_FLAG_ROOTDEV
;