Commit 5fd13d973613d308663f97b51059ecd9179baf09
1 parent
7264f2928b
Exists in
smarc_8mq_lf_v2020.04
and in
20 other branches
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 |