1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <commonlib/bsd/compression.h>
4 #include <console/console.h>
7 #include <device/resource.h>
9 #include <commonlib/region.h>
11 #include <program_loading.h>
12 #include <timestamp.h>
17 /* Pack the device_tree and place it at given position. */
18 static void pack_fdt(struct region
*fdt
, struct device_tree
*dt
)
20 printk(BIOS_INFO
, "FIT: Flattening FDT to %p\n",
23 dt_flatten(dt
, (void *)fdt
->offset
);
24 prog_segment_loaded(fdt
->offset
, fdt
->size
, 0);
28 * Extract a node to given regions.
29 * Returns true on error, false on success.
31 static bool extract(struct region
*region
, struct fit_image_node
*node
)
33 void *dst
= (void *)region
->offset
;
34 const char *comp_name
;
37 if (node
->size
== 0) {
38 printk(BIOS_ERR
, "The %s size is 0\n", node
->name
);
42 switch (node
->compression
) {
43 case CBFS_COMPRESS_NONE
:
44 comp_name
= "Relocating uncompressed";
46 case CBFS_COMPRESS_LZMA
:
47 comp_name
= "Decompressing LZMA";
49 case CBFS_COMPRESS_LZ4
:
50 comp_name
= "Decompressing LZ4";
53 printk(BIOS_ERR
, "Unsupported compression\n");
57 printk(BIOS_INFO
, "FIT: %s %s to %p\n", comp_name
, node
->name
, dst
);
59 switch (node
->compression
) {
60 case CBFS_COMPRESS_NONE
:
61 memcpy(dst
, node
->data
, node
->size
);
62 true_size
= node
->size
;
64 case CBFS_COMPRESS_LZMA
:
65 timestamp_add_now(TS_ULZMA_START
);
66 true_size
= ulzman(node
->data
, node
->size
, dst
, region
->size
);
67 timestamp_add_now(TS_ULZMA_END
);
69 case CBFS_COMPRESS_LZ4
:
70 timestamp_add_now(TS_ULZ4F_START
);
71 true_size
= ulz4fn(node
->data
, node
->size
, dst
, region
->size
);
72 timestamp_add_now(TS_ULZ4F_END
);
79 printk(BIOS_ERR
, "%s decompression failed!\n",
87 static struct device_tree
*unpack_fdt(struct fit_image_node
*image_node
)
89 void *data
= image_node
->data
;
91 if (image_node
->compression
!= CBFS_COMPRESS_NONE
) {
92 /* TODO: This is an ugly heuristic for how much the size will
93 expand on decompression, fix once FIT images support storing
94 the real uncompressed size. */
95 struct region r
= { .offset
= 0, .size
= image_node
->size
* 5 };
96 data
= malloc(r
.size
);
97 r
.offset
= (uintptr_t)data
;
98 if (!data
|| extract(&r
, image_node
))
102 return fdt_unflatten(data
);
106 * Add coreboot tables, CBMEM information and optional board specific strapping
107 * IDs to the device tree loaded via FIT.
109 static void add_cb_fdt_data(struct device_tree
*tree
)
111 u32 addr_cells
= 1, size_cells
= 1;
112 u64 reg_addrs
[2], reg_sizes
[2];
116 static const char *firmware_path
[] = {"firmware", NULL
};
117 struct device_tree_node
*firmware_node
= dt_find_node(tree
->root
,
118 firmware_path
, &addr_cells
, &size_cells
, 1);
120 /* Need to add 'ranges' to the intermediate node to make 'reg' work. */
121 dt_add_bin_prop(firmware_node
, "ranges", NULL
, 0);
123 static const char *coreboot_path
[] = {"coreboot", NULL
};
124 struct device_tree_node
*coreboot_node
= dt_find_node(firmware_node
,
125 coreboot_path
, &addr_cells
, &size_cells
, 1);
127 dt_add_string_prop(coreboot_node
, "compatible", "coreboot");
129 /* Fetch CB tables from cbmem */
130 void *cbtable
= cbmem_find(CBMEM_ID_CBTABLE
);
132 printk(BIOS_WARNING
, "FIT: No coreboot table found!\n");
136 /* First 'reg' address range is the coreboot table. */
137 const struct lb_header
*header
= cbtable
;
138 reg_addrs
[0] = (uintptr_t)header
;
139 reg_sizes
[0] = header
->header_bytes
+ header
->table_bytes
;
141 /* Second is the CBMEM area (which usually includes the coreboot
143 if (cbmem_get_region(&baseptr
, &size
)) {
144 printk(BIOS_WARNING
, "FIT: CBMEM pointer/size not found!\n");
148 reg_addrs
[1] = (uintptr_t)baseptr
;
151 dt_add_reg_prop(coreboot_node
, reg_addrs
, reg_sizes
, 2, addr_cells
,
154 /* Expose board ID, SKU ID, and RAM code to payload.*/
155 if (board_id() != UNDEFINED_STRAPPING_ID
)
156 dt_add_u32_prop(coreboot_node
, "board-id", board_id());
158 if (sku_id() != UNDEFINED_STRAPPING_ID
)
159 dt_add_u32_prop(coreboot_node
, "sku-id", sku_id());
161 if (ram_code() != UNDEFINED_STRAPPING_ID
)
162 dt_add_u32_prop(coreboot_node
, "ram-code", ram_code());
166 * Parse the uImage FIT, choose a configuration and extract images.
168 void fit_payload(struct prog
*payload
, void *data
)
170 struct device_tree
*dt
= NULL
;
171 struct region kernel
= {0}, fdt
= {0}, initrd
= {0};
173 printk(BIOS_INFO
, "FIT: Examine payload %s\n", payload
->name
);
175 struct fit_config_node
*config
= fit_load(data
);
178 printk(BIOS_ERR
, "Could not load FIT\n");
182 dt
= unpack_fdt(config
->fdt
);
184 printk(BIOS_ERR
, "Failed to unflatten the FDT.\n");
188 struct fit_overlay_chain
*chain
;
189 list_for_each(chain
, config
->overlays
, list_node
) {
190 struct device_tree
*overlay
= unpack_fdt(chain
->overlay
);
191 if (!overlay
|| dt_apply_overlay(dt
, overlay
)) {
192 printk(BIOS_ERR
, "Failed to apply overlay %s!\n",
193 chain
->overlay
->name
);
199 /* Insert coreboot specific information */
202 /* Update device_tree */
203 #if defined(CONFIG_LINUX_COMMAND_LINE)
204 fit_update_chosen(dt
, (char *)CONFIG_LINUX_COMMAND_LINE
);
206 fit_update_memory(dt
);
208 /* Collect infos for fit_payload_arch */
209 kernel
.size
= config
->kernel
->size
;
210 fdt
.size
= dt_flat_size(dt
);
211 initrd
.size
= config
->ramdisk
? config
->ramdisk
->size
: 0;
213 /* Invoke arch specific payload placement and fixups */
214 if (!fit_payload_arch(payload
, config
, &kernel
, &fdt
, &initrd
)) {
215 printk(BIOS_ERR
, "Failed to find free memory region\n");
216 bootmem_dump_ranges();
220 /* Update ramdisk location in FDT */
222 fit_add_ramdisk(dt
, (void *)initrd
.offset
, initrd
.size
);
224 /* Repack FDT for handoff to kernel */
227 if (config
->ramdisk
&&
228 extract(&initrd
, config
->ramdisk
)) {
229 printk(BIOS_ERR
, "Failed to extract initrd\n");
230 prog_set_entry(payload
, NULL
, NULL
);
234 timestamp_add_now(TS_KERNEL_DECOMPRESSION
);
236 if (extract(&kernel
, config
->kernel
)) {
237 printk(BIOS_ERR
, "Failed to extract kernel\n");
238 prog_set_entry(payload
, NULL
, NULL
);
242 timestamp_add_now(TS_KERNEL_START
);