Commit 5fd13d973613d308663f97b51059ecd9179baf09

Authored by York Sun
1 parent 7264f2928b

spl: fit: Support both external and embedded data

SPL supports U-Boot image in FIT format which has data outside of
FIT structure. This adds support for embedded data for normal FIT
images.

Signed-off-by: York Sun <york.sun@nxp.com>
Reviewed-by: Tom Rini <trini@konsulko.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

Showing 2 changed files with 37 additions and 19 deletions Inline Diff

common/spl/spl_fit.c
1 /* 1 /*
2 * Copyright (C) 2016 Google, Inc 2 * Copyright (C) 2016 Google, Inc
3 * Written by Simon Glass <sjg@chromium.org> 3 * Written by Simon Glass <sjg@chromium.org>
4 * 4 *
5 * SPDX-License-Identifier: GPL-2.0+ 5 * SPDX-License-Identifier: GPL-2.0+
6 */ 6 */
7 7
8 #include <common.h> 8 #include <common.h>
9 #include <errno.h> 9 #include <errno.h>
10 #include <image.h> 10 #include <image.h>
11 #include <libfdt.h> 11 #include <libfdt.h>
12 #include <spl.h> 12 #include <spl.h>
13 13
14 #ifndef CONFIG_SYS_BOOTM_LEN 14 #ifndef CONFIG_SYS_BOOTM_LEN
15 #define CONFIG_SYS_BOOTM_LEN (64 << 20) 15 #define CONFIG_SYS_BOOTM_LEN (64 << 20)
16 #endif 16 #endif
17 17
18 /** 18 /**
19 * spl_fit_get_image_node(): By using the matching configuration subnode, 19 * spl_fit_get_image_node(): By using the matching configuration subnode,
20 * retrieve the name of an image, specified by a property name and an index 20 * retrieve the name of an image, specified by a property name and an index
21 * into that. 21 * into that.
22 * @fit: Pointer to the FDT blob. 22 * @fit: Pointer to the FDT blob.
23 * @images: Offset of the /images subnode. 23 * @images: Offset of the /images subnode.
24 * @type: Name of the property within the configuration subnode. 24 * @type: Name of the property within the configuration subnode.
25 * @index: Index into the list of strings in this property. 25 * @index: Index into the list of strings in this property.
26 * 26 *
27 * Return: the node offset of the respective image node or a negative 27 * Return: the node offset of the respective image node or a negative
28 * error number. 28 * error number.
29 */ 29 */
30 static int spl_fit_get_image_node(const void *fit, int images, 30 static int spl_fit_get_image_node(const void *fit, int images,
31 const char *type, int index) 31 const char *type, int index)
32 { 32 {
33 const char *name, *str; 33 const char *name, *str;
34 int node, conf_node; 34 int node, conf_node;
35 int len, i; 35 int len, i;
36 36
37 conf_node = fit_find_config_node(fit); 37 conf_node = fit_find_config_node(fit);
38 if (conf_node < 0) { 38 if (conf_node < 0) {
39 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT 39 #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
40 printf("No matching DT out of these options:\n"); 40 printf("No matching DT out of these options:\n");
41 for (node = fdt_first_subnode(fit, conf_node); 41 for (node = fdt_first_subnode(fit, conf_node);
42 node >= 0; 42 node >= 0;
43 node = fdt_next_subnode(fit, node)) { 43 node = fdt_next_subnode(fit, node)) {
44 name = fdt_getprop(fit, node, "description", &len); 44 name = fdt_getprop(fit, node, "description", &len);
45 printf(" %s\n", name); 45 printf(" %s\n", name);
46 } 46 }
47 #endif 47 #endif
48 return conf_node; 48 return conf_node;
49 } 49 }
50 50
51 name = fdt_getprop(fit, conf_node, type, &len); 51 name = fdt_getprop(fit, conf_node, type, &len);
52 if (!name) { 52 if (!name) {
53 debug("cannot find property '%s': %d\n", type, len); 53 debug("cannot find property '%s': %d\n", type, len);
54 return -EINVAL; 54 return -EINVAL;
55 } 55 }
56 56
57 str = name; 57 str = name;
58 for (i = 0; i < index; i++) { 58 for (i = 0; i < index; i++) {
59 str = strchr(str, '\0') + 1; 59 str = strchr(str, '\0') + 1;
60 if (!str || (str - name >= len)) { 60 if (!str || (str - name >= len)) {
61 debug("no string for index %d\n", index); 61 debug("no string for index %d\n", index);
62 return -E2BIG; 62 return -E2BIG;
63 } 63 }
64 } 64 }
65 65
66 debug("%s: '%s'\n", type, str); 66 debug("%s: '%s'\n", type, str);
67 node = fdt_subnode_offset(fit, images, str); 67 node = fdt_subnode_offset(fit, images, str);
68 if (node < 0) { 68 if (node < 0) {
69 debug("cannot find image node '%s': %d\n", str, node); 69 debug("cannot find image node '%s': %d\n", str, node);
70 return -EINVAL; 70 return -EINVAL;
71 } 71 }
72 72
73 return node; 73 return node;
74 } 74 }
75 75
76 static int get_aligned_image_offset(struct spl_load_info *info, int offset) 76 static int get_aligned_image_offset(struct spl_load_info *info, int offset)
77 { 77 {
78 /* 78 /*
79 * If it is a FS read, get the first address before offset which is 79 * If it is a FS read, get the first address before offset which is
80 * aligned to ARCH_DMA_MINALIGN. If it is raw read return the 80 * aligned to ARCH_DMA_MINALIGN. If it is raw read return the
81 * block number to which offset belongs. 81 * block number to which offset belongs.
82 */ 82 */
83 if (info->filename) 83 if (info->filename)
84 return offset & ~(ARCH_DMA_MINALIGN - 1); 84 return offset & ~(ARCH_DMA_MINALIGN - 1);
85 85
86 return offset / info->bl_len; 86 return offset / info->bl_len;
87 } 87 }
88 88
89 static int get_aligned_image_overhead(struct spl_load_info *info, int offset) 89 static int get_aligned_image_overhead(struct spl_load_info *info, int offset)
90 { 90 {
91 /* 91 /*
92 * If it is a FS read, get the difference between the offset and 92 * If it is a FS read, get the difference between the offset and
93 * the first address before offset which is aligned to 93 * the first address before offset which is aligned to
94 * ARCH_DMA_MINALIGN. If it is raw read return the offset within the 94 * ARCH_DMA_MINALIGN. If it is raw read return the offset within the
95 * block. 95 * block.
96 */ 96 */
97 if (info->filename) 97 if (info->filename)
98 return offset & (ARCH_DMA_MINALIGN - 1); 98 return offset & (ARCH_DMA_MINALIGN - 1);
99 99
100 return offset % info->bl_len; 100 return offset % info->bl_len;
101 } 101 }
102 102
103 static int get_aligned_image_size(struct spl_load_info *info, int data_size, 103 static int get_aligned_image_size(struct spl_load_info *info, int data_size,
104 int offset) 104 int offset)
105 { 105 {
106 data_size = data_size + get_aligned_image_overhead(info, offset); 106 data_size = data_size + get_aligned_image_overhead(info, offset);
107 107
108 if (info->filename) 108 if (info->filename)
109 return data_size; 109 return data_size;
110 110
111 return (data_size + info->bl_len - 1) / info->bl_len; 111 return (data_size + info->bl_len - 1) / info->bl_len;
112 } 112 }
113 113
114 /** 114 /**
115 * spl_load_fit_image(): load the image described in a certain FIT node 115 * spl_load_fit_image(): load the image described in a certain FIT node
116 * @info: points to information about the device to load data from 116 * @info: points to information about the device to load data from
117 * @sector: the start sector of the FIT image on the device 117 * @sector: the start sector of the FIT image on the device
118 * @fit: points to the flattened device tree blob describing the FIT 118 * @fit: points to the flattened device tree blob describing the FIT
119 * image 119 * image
120 * @base_offset: the beginning of the data area containing the actual 120 * @base_offset: the beginning of the data area containing the actual
121 * image data, relative to the beginning of the FIT 121 * image data, relative to the beginning of the FIT
122 * @node: offset of the DT node describing the image to load (relative 122 * @node: offset of the DT node describing the image to load (relative
123 * to @fit) 123 * to @fit)
124 * @image_info: will be filled with information about the loaded image 124 * @image_info: will be filled with information about the loaded image
125 * If the FIT node does not contain a "load" (address) property, 125 * If the FIT node does not contain a "load" (address) property,
126 * the image gets loaded to the address pointed to by the 126 * the image gets loaded to the address pointed to by the
127 * load_addr member in this struct. 127 * load_addr member in this struct.
128 * 128 *
129 * Return: 0 on success or a negative error number. 129 * Return: 0 on success or a negative error number.
130 */ 130 */
131 static int spl_load_fit_image(struct spl_load_info *info, ulong sector, 131 static int spl_load_fit_image(struct spl_load_info *info, ulong sector,
132 void *fit, ulong base_offset, int node, 132 void *fit, ulong base_offset, int node,
133 struct spl_image_info *image_info) 133 struct spl_image_info *image_info)
134 { 134 {
135 ulong offset; 135 int offset;
136 size_t length; 136 size_t length;
137 int len;
137 ulong load_addr, load_ptr; 138 ulong load_addr, load_ptr;
138 void *src; 139 void *src;
139 ulong overhead; 140 ulong overhead;
140 int nr_sectors; 141 int nr_sectors;
141 int align_len = ARCH_DMA_MINALIGN - 1; 142 int align_len = ARCH_DMA_MINALIGN - 1;
142 uint8_t image_comp = -1, type = -1; 143 uint8_t image_comp = -1, type = -1;
144 const void *data;
143 145
144 if (IS_ENABLED(CONFIG_SPL_OS_BOOT) && IS_ENABLED(CONFIG_SPL_GZIP)) { 146 if (IS_ENABLED(CONFIG_SPL_OS_BOOT) && IS_ENABLED(CONFIG_SPL_GZIP)) {
145 if (fit_image_get_comp(fit, node, &image_comp)) 147 if (fit_image_get_comp(fit, node, &image_comp))
146 puts("Cannot get image compression format.\n"); 148 puts("Cannot get image compression format.\n");
147 else 149 else
148 debug("%s ", genimg_get_comp_name(image_comp)); 150 debug("%s ", genimg_get_comp_name(image_comp));
149 151
150 if (fit_image_get_type(fit, node, &type)) 152 if (fit_image_get_type(fit, node, &type))
151 puts("Cannot get image type.\n"); 153 puts("Cannot get image type.\n");
152 else 154 else
153 debug("%s ", genimg_get_type_name(type)); 155 debug("%s ", genimg_get_type_name(type));
154 } 156 }
155 157
156 offset = fdt_getprop_u32(fit, node, "data-offset"); 158 if (fit_image_get_load(fit, node, &load_addr))
157 if (offset == FDT_ERROR)
158 return -ENOENT;
159 offset += base_offset;
160 length = fdt_getprop_u32(fit, node, "data-size");
161 if (length == FDT_ERROR)
162 return -ENOENT;
163 load_addr = fdt_getprop_u32(fit, node, "load");
164 if (load_addr == FDT_ERROR && image_info)
165 load_addr = image_info->load_addr; 159 load_addr = image_info->load_addr;
166 load_ptr = (load_addr + align_len) & ~align_len;
167 160
168 overhead = get_aligned_image_overhead(info, offset); 161 if (!fit_image_get_data_offset(fit, node, &offset)) {
169 nr_sectors = get_aligned_image_size(info, length, offset); 162 /* External data */
163 offset += base_offset;
164 if (fit_image_get_data_size(fit, node, &len))
165 return -ENOENT;
170 166
171 if (info->read(info, sector + get_aligned_image_offset(info, offset), 167 load_ptr = (load_addr + align_len) & ~align_len;
172 nr_sectors, (void*)load_ptr) != nr_sectors) 168 length = len;
173 return -EIO;
174 debug("image dst=%lx, offset=%lx, size=%lx\n", load_ptr, offset,
175 (unsigned long)length);
176 169
177 src = (void *)load_ptr + overhead; 170 overhead = get_aligned_image_overhead(info, offset);
171 nr_sectors = get_aligned_image_size(info, length, offset);
172
173 if (info->read(info,
174 sector + get_aligned_image_offset(info, offset),
175 nr_sectors, (void *)load_ptr) != nr_sectors)
176 return -EIO;
177
178 debug("External data: dst=%lx, offset=%x, size=%lx\n",
179 load_ptr, offset, (unsigned long)length);
180 src = (void *)load_ptr + overhead;
181 } else {
182 /* Embedded data */
183 if (fit_image_get_data(fit, node, &data, &length)) {
184 puts("Cannot get image data/size\n");
185 return -ENOENT;
186 }
187 debug("Embedded data: dst=%lx, size=%lx\n", load_addr,
188 (unsigned long)length);
189 src = (void *)data;
190 }
191
178 #ifdef CONFIG_SPL_FIT_IMAGE_POST_PROCESS 192 #ifdef CONFIG_SPL_FIT_IMAGE_POST_PROCESS
179 board_fit_image_post_process(&src, &length); 193 board_fit_image_post_process(&src, &length);
180 #endif 194 #endif
181 195
182 if (IS_ENABLED(CONFIG_SPL_OS_BOOT) && 196 if (IS_ENABLED(CONFIG_SPL_OS_BOOT) &&
183 IS_ENABLED(CONFIG_SPL_GZIP) && 197 IS_ENABLED(CONFIG_SPL_GZIP) &&
184 image_comp == IH_COMP_GZIP && 198 image_comp == IH_COMP_GZIP &&
185 type == IH_TYPE_KERNEL) { 199 type == IH_TYPE_KERNEL) {
186 if (gunzip((void *)load_addr, CONFIG_SYS_BOOTM_LEN, 200 if (gunzip((void *)load_addr, CONFIG_SYS_BOOTM_LEN,
187 src, &length)) { 201 src, &length)) {
188 puts("Uncompressing error\n"); 202 puts("Uncompressing error\n");
189 return -EIO; 203 return -EIO;
190 } 204 }
191 } else { 205 } else {
192 memcpy((void *)load_addr, src, length); 206 memcpy((void *)load_addr, src, length);
193 } 207 }
194 208
195 if (image_info) { 209 if (image_info) {
196 image_info->load_addr = load_addr; 210 image_info->load_addr = load_addr;
197 image_info->size = length; 211 image_info->size = length;
198 image_info->entry_point = fdt_getprop_u32(fit, node, "entry"); 212 image_info->entry_point = fdt_getprop_u32(fit, node, "entry");
199 } 213 }
200 214
201 return 0; 215 return 0;
202 } 216 }
203 217
204 int spl_load_simple_fit(struct spl_image_info *spl_image, 218 int spl_load_simple_fit(struct spl_image_info *spl_image,
205 struct spl_load_info *info, ulong sector, void *fit) 219 struct spl_load_info *info, ulong sector, void *fit)
206 { 220 {
207 int sectors; 221 int sectors;
208 ulong size; 222 ulong size;
209 unsigned long count; 223 unsigned long count;
210 struct spl_image_info image_info; 224 struct spl_image_info image_info;
211 int node, images, ret; 225 int node, images, ret;
212 int base_offset, align_len = ARCH_DMA_MINALIGN - 1; 226 int base_offset, align_len = ARCH_DMA_MINALIGN - 1;
213 int index = 0; 227 int index = 0;
214 228
215 /* 229 /*
216 * Figure out where the external images start. This is the base for the 230 * Figure out where the external images start. This is the base for the
217 * data-offset properties in each image. 231 * data-offset properties in each image.
218 */ 232 */
219 size = fdt_totalsize(fit); 233 size = fdt_totalsize(fit);
220 size = (size + 3) & ~3; 234 size = (size + 3) & ~3;
221 base_offset = (size + 3) & ~3; 235 base_offset = (size + 3) & ~3;
222 236
223 /* 237 /*
224 * So far we only have one block of data from the FIT. Read the entire 238 * So far we only have one block of data from the FIT. Read the entire
225 * thing, including that first block, placing it so it finishes before 239 * thing, including that first block, placing it so it finishes before
226 * where we will load the image. 240 * where we will load the image.
227 * 241 *
228 * Note that we will load the image such that its first byte will be 242 * Note that we will load the image such that its first byte will be
229 * at the load address. Since that byte may be part-way through a 243 * at the load address. Since that byte may be part-way through a
230 * block, we may load the image up to one block before the load 244 * block, we may load the image up to one block before the load
231 * address. So take account of that here by subtracting an addition 245 * address. So take account of that here by subtracting an addition
232 * block length from the FIT start position. 246 * block length from the FIT start position.
233 * 247 *
234 * In fact the FIT has its own load address, but we assume it cannot 248 * In fact the FIT has its own load address, but we assume it cannot
235 * be before CONFIG_SYS_TEXT_BASE. 249 * be before CONFIG_SYS_TEXT_BASE.
236 */ 250 */
237 fit = (void *)((CONFIG_SYS_TEXT_BASE - size - info->bl_len - 251 fit = (void *)((CONFIG_SYS_TEXT_BASE - size - info->bl_len -
238 align_len) & ~align_len); 252 align_len) & ~align_len);
239 sectors = get_aligned_image_size(info, size, 0); 253 sectors = get_aligned_image_size(info, size, 0);
240 count = info->read(info, sector, sectors, fit); 254 count = info->read(info, sector, sectors, fit);
241 debug("fit read sector %lx, sectors=%d, dst=%p, count=%lu\n", 255 debug("fit read sector %lx, sectors=%d, dst=%p, count=%lu\n",
242 sector, sectors, fit, count); 256 sector, sectors, fit, count);
243 if (count == 0) 257 if (count == 0)
244 return -EIO; 258 return -EIO;
245 259
246 /* find the node holding the images information */ 260 /* find the node holding the images information */
247 images = fdt_path_offset(fit, FIT_IMAGES_PATH); 261 images = fdt_path_offset(fit, FIT_IMAGES_PATH);
248 if (images < 0) { 262 if (images < 0) {
249 debug("%s: Cannot find /images node: %d\n", __func__, images); 263 debug("%s: Cannot find /images node: %d\n", __func__, images);
250 return -1; 264 return -1;
251 } 265 }
252 266
253 /* find the U-Boot image */ 267 /* find the U-Boot image */
254 node = spl_fit_get_image_node(fit, images, "firmware", 0); 268 node = spl_fit_get_image_node(fit, images, "firmware", 0);
255 if (node < 0) { 269 if (node < 0) {
256 debug("could not find firmware image, trying loadables...\n"); 270 debug("could not find firmware image, trying loadables...\n");
257 node = spl_fit_get_image_node(fit, images, "loadables", 0); 271 node = spl_fit_get_image_node(fit, images, "loadables", 0);
258 /* 272 /*
259 * If we pick the U-Boot image from "loadables", start at 273 * If we pick the U-Boot image from "loadables", start at
260 * the second image when later loading additional images. 274 * the second image when later loading additional images.
261 */ 275 */
262 index = 1; 276 index = 1;
263 } 277 }
264 if (node < 0) { 278 if (node < 0) {
265 debug("%s: Cannot find u-boot image node: %d\n", 279 debug("%s: Cannot find u-boot image node: %d\n",
266 __func__, node); 280 __func__, node);
267 return -1; 281 return -1;
268 } 282 }
269 283
270 /* Load the image and set up the spl_image structure */ 284 /* Load the image and set up the spl_image structure */
271 ret = spl_load_fit_image(info, sector, fit, base_offset, node, 285 ret = spl_load_fit_image(info, sector, fit, base_offset, node,
272 spl_image); 286 spl_image);
273 if (ret) 287 if (ret)
274 return ret; 288 return ret;
275 289
276 spl_image->os = IH_OS_U_BOOT; 290 spl_image->os = IH_OS_U_BOOT;
277 291
278 /* Figure out which device tree the board wants to use */ 292 /* Figure out which device tree the board wants to use */
279 node = spl_fit_get_image_node(fit, images, FIT_FDT_PROP, 0); 293 node = spl_fit_get_image_node(fit, images, FIT_FDT_PROP, 0);
280 if (node < 0) { 294 if (node < 0) {
281 debug("%s: cannot find FDT node\n", __func__); 295 debug("%s: cannot find FDT node\n", __func__);
282 return node; 296 return node;
283 } 297 }
284 298
285 /* 299 /*
286 * Read the device tree and place it after the image. 300 * Read the device tree and place it after the image.
287 * Align the destination address to ARCH_DMA_MINALIGN. 301 * Align the destination address to ARCH_DMA_MINALIGN.
288 */ 302 */
289 image_info.load_addr = spl_image->load_addr + spl_image->size; 303 image_info.load_addr = spl_image->load_addr + spl_image->size;
290 ret = spl_load_fit_image(info, sector, fit, base_offset, node, 304 ret = spl_load_fit_image(info, sector, fit, base_offset, node,
291 &image_info); 305 &image_info);
292 if (ret < 0) 306 if (ret < 0)
293 return ret; 307 return ret;
294 308
295 /* Now check if there are more images for us to load */ 309 /* Now check if there are more images for us to load */
296 for (; ; index++) { 310 for (; ; index++) {
297 node = spl_fit_get_image_node(fit, images, "loadables", index); 311 node = spl_fit_get_image_node(fit, images, "loadables", index);
298 if (node < 0) 312 if (node < 0)
299 break; 313 break;
300 314
301 ret = spl_load_fit_image(info, sector, fit, base_offset, node, 315 ret = spl_load_fit_image(info, sector, fit, base_offset, node,
302 &image_info); 316 &image_info);
303 if (ret < 0) 317 if (ret < 0)
304 continue; 318 continue;
305 319
306 /* 320 /*
307 * If the "firmware" image did not provide an entry point, 321 * If the "firmware" image did not provide an entry point,
308 * use the first valid entry point from the loadables. 322 * use the first valid entry point from the loadables.
309 */ 323 */
310 if (spl_image->entry_point == FDT_ERROR && 324 if (spl_image->entry_point == FDT_ERROR &&
311 image_info.entry_point != FDT_ERROR) 325 image_info.entry_point != FDT_ERROR)
312 spl_image->entry_point = image_info.entry_point; 326 spl_image->entry_point = image_info.entry_point;
313 } 327 }
doc/uImage.FIT/source_file_format.txt
1 U-Boot new uImage source file format (bindings definition) 1 U-Boot new uImage source file format (bindings definition)
2 ========================================================== 2 ==========================================================
3 3
4 Author: Marian Balakowicz <m8@semihalf.com> 4 Author: Marian Balakowicz <m8@semihalf.com>
5 External data additions, 25/1/16 Simon Glass <sjg@chromium.org> 5 External data additions, 25/1/16 Simon Glass <sjg@chromium.org>
6 6
7 1) Introduction 7 1) Introduction
8 --------------- 8 ---------------
9 9
10 Evolution of the 2.6 Linux kernel for embedded PowerPC systems introduced new 10 Evolution of the 2.6 Linux kernel for embedded PowerPC systems introduced new
11 booting method which requires that hardware description is available to the 11 booting method which requires that hardware description is available to the
12 kernel in the form of Flattened Device Tree. 12 kernel in the form of Flattened Device Tree.
13 13
14 Booting with a Flattened Device Tree is much more flexible and is intended to 14 Booting with a Flattened Device Tree is much more flexible and is intended to
15 replace direct passing of 'struct bd_info' which was used to boot pre-FDT 15 replace direct passing of 'struct bd_info' which was used to boot pre-FDT
16 kernels. 16 kernels.
17 17
18 However, U-Boot needs to support both techniques to provide backward 18 However, U-Boot needs to support both techniques to provide backward
19 compatibility for platforms which are not FDT ready. Number of elements 19 compatibility for platforms which are not FDT ready. Number of elements
20 playing role in the booting process has increased and now includes the FDT 20 playing role in the booting process has increased and now includes the FDT
21 blob. Kernel image, FDT blob and possibly ramdisk image - all must be placed 21 blob. Kernel image, FDT blob and possibly ramdisk image - all must be placed
22 in the system memory and passed to bootm as a arguments. Some of them may be 22 in the system memory and passed to bootm as a arguments. Some of them may be
23 missing: FDT is not present for legacy platforms, ramdisk is always optional. 23 missing: FDT is not present for legacy platforms, ramdisk is always optional.
24 Additionally, old uImage format has been extended to support multi sub-images 24 Additionally, old uImage format has been extended to support multi sub-images
25 but the support is limited by simple format of the legacy uImage structure. 25 but the support is limited by simple format of the legacy uImage structure.
26 Single binary header 'struct image_header' is not flexible enough to cover all 26 Single binary header 'struct image_header' is not flexible enough to cover all
27 possible scenarios. 27 possible scenarios.
28 28
29 All those factors combined clearly show that there is a need for new, more 29 All those factors combined clearly show that there is a need for new, more
30 flexible, multi component uImage format. 30 flexible, multi component uImage format.
31 31
32 32
33 2) New uImage format assumptions 33 2) New uImage format assumptions
34 -------------------------------- 34 --------------------------------
35 35
36 a) Implementation 36 a) Implementation
37 37
38 Libfdt has been selected for the new uImage format implementation as (1) it 38 Libfdt has been selected for the new uImage format implementation as (1) it
39 provides needed functionality, (2) is actively maintained and developed and 39 provides needed functionality, (2) is actively maintained and developed and
40 (3) increases code reuse as it is already part of the U-Boot source tree. 40 (3) increases code reuse as it is already part of the U-Boot source tree.
41 41
42 b) Terminology 42 b) Terminology
43 43
44 This document defines new uImage structure by providing FDT bindings for new 44 This document defines new uImage structure by providing FDT bindings for new
45 uImage internals. Bindings are defined from U-Boot perspective, i.e. describe 45 uImage internals. Bindings are defined from U-Boot perspective, i.e. describe
46 final form of the uImage at the moment when it reaches U-Boot. User 46 final form of the uImage at the moment when it reaches U-Boot. User
47 perspective may be simpler, as some of the properties (like timestamps and 47 perspective may be simpler, as some of the properties (like timestamps and
48 hashes) will need to be filled in automatically by the U-Boot mkimage tool. 48 hashes) will need to be filled in automatically by the U-Boot mkimage tool.
49 49
50 To avoid confusion with the kernel FDT the following naming convention is 50 To avoid confusion with the kernel FDT the following naming convention is
51 proposed for the new uImage format related terms: 51 proposed for the new uImage format related terms:
52 52
53 FIT - Flattened uImage Tree 53 FIT - Flattened uImage Tree
54 54
55 FIT is formally a flattened device tree (in the libfdt meaning), which 55 FIT is formally a flattened device tree (in the libfdt meaning), which
56 conforms to bindings defined in this document. 56 conforms to bindings defined in this document.
57 57
58 .its - image tree source 58 .its - image tree source
59 .itb - flattened image tree blob 59 .itb - flattened image tree blob
60 60
61 c) Image building procedure 61 c) Image building procedure
62 62
63 The following picture shows how the new uImage is prepared. Input consists of 63 The following picture shows how the new uImage is prepared. Input consists of
64 image source file (.its) and a set of data files. Image is created with the 64 image source file (.its) and a set of data files. Image is created with the
65 help of standard U-Boot mkimage tool which in turn uses dtc (device tree 65 help of standard U-Boot mkimage tool which in turn uses dtc (device tree
66 compiler) to produce image tree blob (.itb). Resulting .itb file is the 66 compiler) to produce image tree blob (.itb). Resulting .itb file is the
67 actual binary of a new uImage. 67 actual binary of a new uImage.
68 68
69 69
70 tqm5200.its 70 tqm5200.its
71 + 71 +
72 vmlinux.bin.gz mkimage + dtc xfer to target 72 vmlinux.bin.gz mkimage + dtc xfer to target
73 eldk-4.2-ramdisk --------------> tqm5200.itb --------------> bootm 73 eldk-4.2-ramdisk --------------> tqm5200.itb --------------> bootm
74 tqm5200.dtb /|\ 74 tqm5200.dtb /|\
75 ... | 75 ... |
76 'new uImage' 76 'new uImage'
77 77
78 - create .its file, automatically filled-in properties are omitted 78 - create .its file, automatically filled-in properties are omitted
79 - call mkimage tool on a .its file 79 - call mkimage tool on a .its file
80 - mkimage calls dtc to create .itb image and assures that 80 - mkimage calls dtc to create .itb image and assures that
81 missing properties are added 81 missing properties are added
82 - .itb (new uImage) is uploaded onto the target and used therein 82 - .itb (new uImage) is uploaded onto the target and used therein
83 83
84 84
85 d) Unique identifiers 85 d) Unique identifiers
86 86
87 To identify FIT sub-nodes representing images, hashes, configurations (which 87 To identify FIT sub-nodes representing images, hashes, configurations (which
88 are defined in the following sections), the "unit name" of the given sub-node 88 are defined in the following sections), the "unit name" of the given sub-node
89 is used as it's identifier as it assures uniqueness without additional 89 is used as it's identifier as it assures uniqueness without additional
90 checking required. 90 checking required.
91 91
92 92
93 3) Root node properties 93 3) Root node properties
94 ----------------------- 94 -----------------------
95 95
96 Root node of the uImage Tree should have the following layout: 96 Root node of the uImage Tree should have the following layout:
97 97
98 / o image-tree 98 / o image-tree
99 |- description = "image description" 99 |- description = "image description"
100 |- timestamp = <12399321> 100 |- timestamp = <12399321>
101 |- #address-cells = <1> 101 |- #address-cells = <1>
102 | 102 |
103 o images 103 o images
104 | | 104 | |
105 | o image@1 {...} 105 | o image@1 {...}
106 | o image@2 {...} 106 | o image@2 {...}
107 | ... 107 | ...
108 | 108 |
109 o configurations 109 o configurations
110 |- default = "conf@1" 110 |- default = "conf@1"
111 | 111 |
112 o conf@1 {...} 112 o conf@1 {...}
113 o conf@2 {...} 113 o conf@2 {...}
114 ... 114 ...
115 115
116 116
117 Optional property: 117 Optional property:
118 - description : Textual description of the uImage 118 - description : Textual description of the uImage
119 119
120 Mandatory property: 120 Mandatory property:
121 - timestamp : Last image modification time being counted in seconds since 121 - timestamp : Last image modification time being counted in seconds since
122 1970-01-01 00:00:00 - to be automatically calculated by mkimage tool. 122 1970-01-01 00:00:00 - to be automatically calculated by mkimage tool.
123 123
124 Conditionally mandatory property: 124 Conditionally mandatory property:
125 - #address-cells : Number of 32bit cells required to represent entry and 125 - #address-cells : Number of 32bit cells required to represent entry and
126 load addresses supplied within sub-image nodes. May be omitted when no 126 load addresses supplied within sub-image nodes. May be omitted when no
127 entry or load addresses are used. 127 entry or load addresses are used.
128 128
129 Mandatory node: 129 Mandatory node:
130 - images : This node contains a set of sub-nodes, each of them representing 130 - images : This node contains a set of sub-nodes, each of them representing
131 single component sub-image (like kernel, ramdisk, etc.). At least one 131 single component sub-image (like kernel, ramdisk, etc.). At least one
132 sub-image is required. 132 sub-image is required.
133 133
134 Optional node: 134 Optional node:
135 - configurations : Contains a set of available configuration nodes and 135 - configurations : Contains a set of available configuration nodes and
136 defines a default configuration. 136 defines a default configuration.
137 137
138 138
139 4) '/images' node 139 4) '/images' node
140 ----------------- 140 -----------------
141 141
142 This node is a container node for component sub-image nodes. Each sub-node of 142 This node is a container node for component sub-image nodes. Each sub-node of
143 the '/images' node should have the following layout: 143 the '/images' node should have the following layout:
144 144
145 o image@1 145 o image@1
146 |- description = "component sub-image description" 146 |- description = "component sub-image description"
147 |- data = /incbin/("path/to/data/file.bin") 147 |- data = /incbin/("path/to/data/file.bin")
148 |- type = "sub-image type name" 148 |- type = "sub-image type name"
149 |- arch = "ARCH name" 149 |- arch = "ARCH name"
150 |- os = "OS name" 150 |- os = "OS name"
151 |- compression = "compression name" 151 |- compression = "compression name"
152 |- load = <00000000> 152 |- load = <00000000>
153 |- entry = <00000000> 153 |- entry = <00000000>
154 | 154 |
155 o hash@1 {...} 155 o hash@1 {...}
156 o hash@2 {...} 156 o hash@2 {...}
157 ... 157 ...
158 158
159 Mandatory properties: 159 Mandatory properties:
160 - description : Textual description of the component sub-image 160 - description : Textual description of the component sub-image
161 - type : Name of component sub-image type, supported types are: 161 - type : Name of component sub-image type, supported types are:
162 "standalone", "kernel", "kernel_noload", "ramdisk", "firmware", "script", 162 "standalone", "kernel", "kernel_noload", "ramdisk", "firmware", "script",
163 "filesystem", "flat_dt" and others (see uimage_type in common/image.c). 163 "filesystem", "flat_dt" and others (see uimage_type in common/image.c).
164 - data : Path to the external file which contains this node's binary data. 164 - data : Path to the external file which contains this node's binary data.
165 - compression : Compression used by included data. Supported compressions 165 - compression : Compression used by included data. Supported compressions
166 are "gzip" and "bzip2". If no compression is used compression property 166 are "gzip" and "bzip2". If no compression is used compression property
167 should be set to "none". 167 should be set to "none".
168 168
169 Conditionally mandatory property: 169 Conditionally mandatory property:
170 - os : OS name, mandatory for types "kernel" and "ramdisk". Valid OS names 170 - os : OS name, mandatory for types "kernel" and "ramdisk". Valid OS names
171 are: "openbsd", "netbsd", "freebsd", "4_4bsd", "linux", "svr4", "esix", 171 are: "openbsd", "netbsd", "freebsd", "4_4bsd", "linux", "svr4", "esix",
172 "solaris", "irix", "sco", "dell", "ncr", "lynxos", "vxworks", "psos", "qnx", 172 "solaris", "irix", "sco", "dell", "ncr", "lynxos", "vxworks", "psos", "qnx",
173 "u_boot", "rtems", "unity", "integrity". 173 "u_boot", "rtems", "unity", "integrity".
174 - arch : Architecture name, mandatory for types: "standalone", "kernel", 174 - arch : Architecture name, mandatory for types: "standalone", "kernel",
175 "firmware", "ramdisk" and "fdt". Valid architecture names are: "alpha", 175 "firmware", "ramdisk" and "fdt". Valid architecture names are: "alpha",
176 "arm", "i386", "ia64", "mips", "mips64", "ppc", "s390", "sh", "sparc", 176 "arm", "i386", "ia64", "mips", "mips64", "ppc", "s390", "sh", "sparc",
177 "sparc64", "m68k", "microblaze", "nios2", "blackfin", "avr32", "st200", 177 "sparc64", "m68k", "microblaze", "nios2", "blackfin", "avr32", "st200",
178 "sandbox". 178 "sandbox".
179 - entry : entry point address, address size is determined by 179 - entry : entry point address, address size is determined by
180 '#address-cells' property of the root node. Mandatory for for types: 180 '#address-cells' property of the root node. Mandatory for for types:
181 "standalone" and "kernel". 181 "standalone" and "kernel".
182 - load : load address, address size is determined by '#address-cells' 182 - load : load address, address size is determined by '#address-cells'
183 property of the root node. Mandatory for types: "standalone" and "kernel". 183 property of the root node. Mandatory for types: "standalone" and "kernel".
184 184
185 Optional nodes: 185 Optional nodes:
186 - hash@1 : Each hash sub-node represents separate hash or checksum 186 - hash@1 : Each hash sub-node represents separate hash or checksum
187 calculated for node's data according to specified algorithm. 187 calculated for node's data according to specified algorithm.
188 188
189 189
190 5) Hash nodes 190 5) Hash nodes
191 ------------- 191 -------------
192 192
193 o hash@1 193 o hash@1
194 |- algo = "hash or checksum algorithm name" 194 |- algo = "hash or checksum algorithm name"
195 |- value = [hash or checksum value] 195 |- value = [hash or checksum value]
196 196
197 Mandatory properties: 197 Mandatory properties:
198 - algo : Algorithm name, supported are "crc32", "md5" and "sha1". 198 - algo : Algorithm name, supported are "crc32", "md5" and "sha1".
199 - value : Actual checksum or hash value, correspondingly 4, 16 or 20 bytes 199 - value : Actual checksum or hash value, correspondingly 4, 16 or 20 bytes
200 long. 200 long.
201 201
202 202
203 6) '/configurations' node 203 6) '/configurations' node
204 ------------------------- 204 -------------------------
205 205
206 The 'configurations' node is optional. If present, it allows to create a 206 The 'configurations' node is optional. If present, it allows to create a
207 convenient, labeled boot configurations, which combine together kernel images 207 convenient, labeled boot configurations, which combine together kernel images
208 with their ramdisks and fdt blobs. 208 with their ramdisks and fdt blobs.
209 209
210 The 'configurations' node has has the following structure: 210 The 'configurations' node has has the following structure:
211 211
212 o configurations 212 o configurations
213 |- default = "default configuration sub-node unit name" 213 |- default = "default configuration sub-node unit name"
214 | 214 |
215 o config@1 {...} 215 o config@1 {...}
216 o config@2 {...} 216 o config@2 {...}
217 ... 217 ...
218 218
219 219
220 Optional property: 220 Optional property:
221 - default : Selects one of the configuration sub-nodes as a default 221 - default : Selects one of the configuration sub-nodes as a default
222 configuration. 222 configuration.
223 223
224 Mandatory nodes: 224 Mandatory nodes:
225 - configuration-sub-node-unit-name : At least one of the configuration 225 - configuration-sub-node-unit-name : At least one of the configuration
226 sub-nodes is required. 226 sub-nodes is required.
227 227
228 228
229 7) Configuration nodes 229 7) Configuration nodes
230 ---------------------- 230 ----------------------
231 231
232 Each configuration has the following structure: 232 Each configuration has the following structure:
233 233
234 o config@1 234 o config@1
235 |- description = "configuration description" 235 |- description = "configuration description"
236 |- kernel = "kernel sub-node unit name" 236 |- kernel = "kernel sub-node unit name"
237 |- ramdisk = "ramdisk sub-node unit name" 237 |- ramdisk = "ramdisk sub-node unit name"
238 |- fdt = "fdt sub-node unit-name" 238 |- fdt = "fdt sub-node unit-name"
239 |- fpga = "fpga sub-node unit-name" 239 |- fpga = "fpga sub-node unit-name"
240 |- loadables = "loadables sub-node unit-name" 240 |- loadables = "loadables sub-node unit-name"
241 241
242 242
243 Mandatory properties: 243 Mandatory properties:
244 - description : Textual configuration description. 244 - description : Textual configuration description.
245 - kernel : Unit name of the corresponding kernel image (image sub-node of a 245 - kernel : Unit name of the corresponding kernel image (image sub-node of a
246 "kernel" type). 246 "kernel" type).
247 247
248 Optional properties: 248 Optional properties:
249 - ramdisk : Unit name of the corresponding ramdisk image (component image 249 - ramdisk : Unit name of the corresponding ramdisk image (component image
250 node of a "ramdisk" type). 250 node of a "ramdisk" type).
251 - fdt : Unit name of the corresponding fdt blob (component image node of a 251 - fdt : Unit name of the corresponding fdt blob (component image node of a
252 "fdt type"). 252 "fdt type").
253 - setup : Unit name of the corresponding setup binary (used for booting 253 - setup : Unit name of the corresponding setup binary (used for booting
254 an x86 kernel). This contains the setup.bin file built by the kernel. 254 an x86 kernel). This contains the setup.bin file built by the kernel.
255 - fpga : Unit name of the corresponding fpga bitstream blob 255 - fpga : Unit name of the corresponding fpga bitstream blob
256 (component image node of a "fpga type"). 256 (component image node of a "fpga type").
257 - loadables : Unit name containing a list of additional binaries to be 257 - loadables : Unit name containing a list of additional binaries to be
258 loaded at their given locations. "loadables" is a comma-separated list 258 loaded at their given locations. "loadables" is a comma-separated list
259 of strings. U-Boot will load each binary at its given start-address and 259 of strings. U-Boot will load each binary at its given start-address and
260 may optionaly invoke additional post-processing steps on this binary based 260 may optionaly invoke additional post-processing steps on this binary based
261 on its component image node type. 261 on its component image node type.
262 262
263 The FDT blob is required to properly boot FDT based kernel, so the minimal 263 The FDT blob is required to properly boot FDT based kernel, so the minimal
264 configuration for 2.6 FDT kernel is (kernel, fdt) pair. 264 configuration for 2.6 FDT kernel is (kernel, fdt) pair.
265 265
266 Older, 2.4 kernel and 2.6 non-FDT kernel do not use FDT blob, in such cases 266 Older, 2.4 kernel and 2.6 non-FDT kernel do not use FDT blob, in such cases
267 'struct bd_info' must be passed instead of FDT blob, thus fdt property *must 267 'struct bd_info' must be passed instead of FDT blob, thus fdt property *must
268 not* be specified in a configuration node. 268 not* be specified in a configuration node.
269 269
270 270
271 8) External data 271 8) External data
272 ---------------- 272 ----------------
273 273
274 The above format shows a 'data' property which holds the data for each image. 274 The above format shows a 'data' property which holds the data for each image.
275 It is also possible for this data to reside outside the FIT itself. This 275 It is also possible for this data to reside outside the FIT itself. This
276 allows the FIT to be quite small, so that it can be loaded and scanned 276 allows the FIT to be quite small, so that it can be loaded and scanned
277 without loading a large amount of data. Then when an image is needed it can 277 without loading a large amount of data. Then when an image is needed it can
278 be loaded from an external source. 278 be loaded from an external source.
279 279
280 In this case the 'data' property is omitted. Instead you can use: 280 In this case the 'data' property is omitted. Instead you can use:
281 281
282 - data-offset : offset of the data in a separate image store. The image 282 - data-offset : offset of the data in a separate image store. The image
283 store is placed immediately after the last byte of the device tree binary, 283 store is placed immediately after the last byte of the device tree binary,
284 aligned to a 4-byte boundary. 284 aligned to a 4-byte boundary.
285 - data-size : size of the data in bytes 285 - data-size : size of the data in bytes
286 286
287 The 'data-offset' property can be substituted with 'data-position', which 287 The 'data-offset' property can be substituted with 'data-position', which
288 defines an absolute position or address as the offset. This is helpful when 288 defines an absolute position or address as the offset. This is helpful when
289 booting U-Boot proper before performing relocation. 289 booting U-Boot proper before performing relocation.
290 290
291 Normal kernel FIT image has data embedded within FIT structure. U-Boot image
292 for SPL boot has external data. Existence of 'data-offset' can be used to
293 identify which format is used.
294
291 9) Examples 295 9) Examples
292 ----------- 296 -----------
293 297
294 Please see doc/uImage.FIT/*.its for actual image source files. 298 Please see doc/uImage.FIT/*.its for actual image source files.
295 299