1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2020 Arm Limited
5 * Based on arch/arm64/kernel/machine_kexec_file.c:
6 * Copyright (C) 2018 Linaro Limited
8 * And arch/powerpc/kexec/file_load.c:
9 * Copyright (C) 2016 IBM Corporation
12 #include <linux/kernel.h>
13 #include <linux/kexec.h>
14 #include <linux/memblock.h>
15 #include <linux/libfdt.h>
17 #include <linux/of_fdt.h>
18 #include <linux/random.h>
19 #include <linux/types.h>
21 /* relevant device tree properties */
22 #define FDT_PROP_KEXEC_ELFHDR "linux,elfcorehdr"
23 #define FDT_PROP_MEM_RANGE "linux,usable-memory-range"
24 #define FDT_PROP_INITRD_START "linux,initrd-start"
25 #define FDT_PROP_INITRD_END "linux,initrd-end"
26 #define FDT_PROP_BOOTARGS "bootargs"
27 #define FDT_PROP_KASLR_SEED "kaslr-seed"
28 #define FDT_PROP_RNG_SEED "rng-seed"
29 #define RNG_SEED_SIZE 128
32 * Additional space needed for the FDT buffer so that we can add initrd,
33 * bootargs, kaslr-seed, rng-seed, useable-memory-range and elfcorehdr.
35 #define FDT_EXTRA_SPACE 0x1000
38 * fdt_find_and_del_mem_rsv - delete memory reservation with given address and size
40 * @fdt: Flattened device tree for the current kernel.
41 * @start: Starting address of the reserved memory.
42 * @size: Size of the reserved memory.
44 * Return: 0 on success, or negative errno on error.
46 static int fdt_find_and_del_mem_rsv(void *fdt, unsigned long start, unsigned long size)
48 int i, ret, num_rsvs = fdt_num_mem_rsv(fdt);
50 for (i = 0; i < num_rsvs; i++) {
51 u64 rsv_start, rsv_size;
53 ret = fdt_get_mem_rsv(fdt, i, &rsv_start, &rsv_size);
55 pr_err("Malformed device tree.\n");
59 if (rsv_start == start && rsv_size == size) {
60 ret = fdt_del_mem_rsv(fdt, i);
62 pr_err("Error deleting device tree reservation.\n");
74 * get_addr_size_cells - Get address and size of root node
76 * @addr_cells: Return address of the root node
77 * @size_cells: Return size of the root node
79 * Return: 0 on success, or negative errno on error.
81 static int get_addr_size_cells(int *addr_cells, int *size_cells)
83 struct device_node *root;
85 root = of_find_node_by_path("/");
89 *addr_cells = of_n_addr_cells(root);
90 *size_cells = of_n_size_cells(root);
98 * do_get_kexec_buffer - Get address and size of device tree property
100 * @prop: Device tree property
101 * @len: Size of @prop
102 * @addr: Return address of the node
103 * @size: Return size of the node
105 * Return: 0 on success, or negative errno on error.
107 static int do_get_kexec_buffer(const void *prop, int len, unsigned long *addr,
110 int ret, addr_cells, size_cells;
112 ret = get_addr_size_cells(&addr_cells, &size_cells);
116 if (len < 4 * (addr_cells + size_cells))
119 *addr = of_read_number(prop, addr_cells);
120 *size = of_read_number(prop + 4 * addr_cells, size_cells);
126 * ima_get_kexec_buffer - get IMA buffer from the previous kernel
127 * @addr: On successful return, set to point to the buffer contents.
128 * @size: On successful return, set to the buffer size.
130 * Return: 0 on success, negative errno on error.
132 int ima_get_kexec_buffer(void **addr, size_t *size)
135 unsigned long tmp_addr;
139 if (!IS_ENABLED(CONFIG_HAVE_IMA_KEXEC))
142 prop = of_get_property(of_chosen, "linux,ima-kexec-buffer", &len);
146 ret = do_get_kexec_buffer(prop, len, &tmp_addr, &tmp_size);
150 *addr = __va(tmp_addr);
157 * ima_free_kexec_buffer - free memory used by the IMA buffer
159 int ima_free_kexec_buffer(void)
164 struct property *prop;
166 if (!IS_ENABLED(CONFIG_HAVE_IMA_KEXEC))
169 prop = of_find_property(of_chosen, "linux,ima-kexec-buffer", NULL);
173 ret = do_get_kexec_buffer(prop->value, prop->length, &addr, &size);
177 ret = of_remove_property(of_chosen, prop);
181 return memblock_free(addr, size);
186 * remove_ima_buffer - remove the IMA buffer property and reservation from @fdt
188 * @fdt: Flattened Device Tree to update
189 * @chosen_node: Offset to the chosen node in the device tree
191 * The IMA measurement buffer is of no use to a subsequent kernel, so we always
192 * remove it from the device tree.
194 static void remove_ima_buffer(void *fdt, int chosen_node)
201 if (!IS_ENABLED(CONFIG_HAVE_IMA_KEXEC))
204 prop = fdt_getprop(fdt, chosen_node, "linux,ima-kexec-buffer", &len);
208 ret = do_get_kexec_buffer(prop, len, &addr, &size);
209 fdt_delprop(fdt, chosen_node, "linux,ima-kexec-buffer");
213 ret = fdt_find_and_del_mem_rsv(fdt, addr, size);
215 pr_debug("Removed old IMA buffer reservation.\n");
218 #ifdef CONFIG_IMA_KEXEC
220 * setup_ima_buffer - add IMA buffer information to the fdt
221 * @image: kexec image being loaded.
222 * @fdt: Flattened device tree for the next kernel.
223 * @chosen_node: Offset to the chosen node.
225 * Return: 0 on success, or negative errno on error.
227 static int setup_ima_buffer(const struct kimage *image, void *fdt,
232 if (!image->ima_buffer_size)
235 ret = fdt_appendprop_addrrange(fdt, 0, chosen_node,
236 "linux,ima-kexec-buffer",
237 image->ima_buffer_addr,
238 image->ima_buffer_size);
242 ret = fdt_add_mem_rsv(fdt, image->ima_buffer_addr,
243 image->ima_buffer_size);
247 pr_debug("IMA buffer at 0x%llx, size = 0x%zx\n",
248 image->ima_buffer_addr, image->ima_buffer_size);
252 #else /* CONFIG_IMA_KEXEC */
253 static inline int setup_ima_buffer(const struct kimage *image, void *fdt,
258 #endif /* CONFIG_IMA_KEXEC */
261 * of_kexec_alloc_and_setup_fdt - Alloc and setup a new Flattened Device Tree
263 * @image: kexec image being loaded.
264 * @initrd_load_addr: Address where the next initrd will be loaded.
265 * @initrd_len: Size of the next initrd, or 0 if there will be none.
266 * @cmdline: Command line for the next kernel, or NULL if there will
268 * @extra_fdt_size: Additional size for the new FDT buffer.
270 * Return: fdt on success, or NULL errno on error.
272 void *of_kexec_alloc_and_setup_fdt(const struct kimage *image,
273 unsigned long initrd_load_addr,
274 unsigned long initrd_len,
275 const char *cmdline, size_t extra_fdt_size)
278 int ret, chosen_node;
282 fdt_size = fdt_totalsize(initial_boot_params) +
283 (cmdline ? strlen(cmdline) : 0) +
286 fdt = kvmalloc(fdt_size, GFP_KERNEL);
290 ret = fdt_open_into(initial_boot_params, fdt, fdt_size);
292 pr_err("Error %d setting up the new device tree.\n", ret);
296 /* Remove memory reservation for the current device tree. */
297 ret = fdt_find_and_del_mem_rsv(fdt, __pa(initial_boot_params),
298 fdt_totalsize(initial_boot_params));
299 if (ret == -EINVAL) {
300 pr_err("Error removing memory reservation.\n");
304 chosen_node = fdt_path_offset(fdt, "/chosen");
305 if (chosen_node == -FDT_ERR_NOTFOUND)
306 chosen_node = fdt_add_subnode(fdt, fdt_path_offset(fdt, "/"),
308 if (chosen_node < 0) {
313 ret = fdt_delprop(fdt, chosen_node, FDT_PROP_KEXEC_ELFHDR);
314 if (ret && ret != -FDT_ERR_NOTFOUND)
316 ret = fdt_delprop(fdt, chosen_node, FDT_PROP_MEM_RANGE);
317 if (ret && ret != -FDT_ERR_NOTFOUND)
320 /* Did we boot using an initrd? */
321 prop = fdt_getprop(fdt, chosen_node, "linux,initrd-start", NULL);
323 u64 tmp_start, tmp_end, tmp_size;
325 tmp_start = fdt64_to_cpu(*((const fdt64_t *) prop));
327 prop = fdt_getprop(fdt, chosen_node, "linux,initrd-end", NULL);
333 tmp_end = fdt64_to_cpu(*((const fdt64_t *) prop));
336 * kexec reserves exact initrd size, while firmware may
337 * reserve a multiple of PAGE_SIZE, so check for both.
339 tmp_size = tmp_end - tmp_start;
340 ret = fdt_find_and_del_mem_rsv(fdt, tmp_start, tmp_size);
342 ret = fdt_find_and_del_mem_rsv(fdt, tmp_start,
343 round_up(tmp_size, PAGE_SIZE));
349 if (initrd_load_addr) {
350 ret = fdt_setprop_u64(fdt, chosen_node, FDT_PROP_INITRD_START,
355 ret = fdt_setprop_u64(fdt, chosen_node, FDT_PROP_INITRD_END,
356 initrd_load_addr + initrd_len);
360 ret = fdt_add_mem_rsv(fdt, initrd_load_addr, initrd_len);
365 ret = fdt_delprop(fdt, chosen_node, FDT_PROP_INITRD_START);
366 if (ret && (ret != -FDT_ERR_NOTFOUND))
369 ret = fdt_delprop(fdt, chosen_node, FDT_PROP_INITRD_END);
370 if (ret && (ret != -FDT_ERR_NOTFOUND))
374 if (image->type == KEXEC_TYPE_CRASH) {
375 /* add linux,elfcorehdr */
376 ret = fdt_appendprop_addrrange(fdt, 0, chosen_node,
377 FDT_PROP_KEXEC_ELFHDR,
378 image->elf_load_addr,
379 image->elf_headers_sz);
384 * Avoid elfcorehdr from being stomped on in kdump kernel by
385 * setting up memory reserve map.
387 ret = fdt_add_mem_rsv(fdt, image->elf_load_addr,
388 image->elf_headers_sz);
392 /* add linux,usable-memory-range */
393 ret = fdt_appendprop_addrrange(fdt, 0, chosen_node,
396 crashk_res.end - crashk_res.start + 1);
403 ret = fdt_setprop_string(fdt, chosen_node, FDT_PROP_BOOTARGS, cmdline);
407 ret = fdt_delprop(fdt, chosen_node, FDT_PROP_BOOTARGS);
408 if (ret && (ret != -FDT_ERR_NOTFOUND))
413 ret = fdt_delprop(fdt, chosen_node, FDT_PROP_KASLR_SEED);
414 if (ret == -FDT_ERR_NOTFOUND)
419 if (rng_is_initialized()) {
420 u64 seed = get_random_u64();
422 ret = fdt_setprop_u64(fdt, chosen_node, FDT_PROP_KASLR_SEED, seed);
426 pr_notice("RNG is not initialised: omitting \"%s\" property\n",
427 FDT_PROP_KASLR_SEED);
431 if (rng_is_initialized()) {
434 ret = fdt_setprop_placeholder(fdt, chosen_node, FDT_PROP_RNG_SEED,
435 RNG_SEED_SIZE, &rng_seed);
438 get_random_bytes(rng_seed, RNG_SEED_SIZE);
440 pr_notice("RNG is not initialised: omitting \"%s\" property\n",
444 ret = fdt_setprop(fdt, chosen_node, "linux,booted-from-kexec", NULL, 0);
448 remove_ima_buffer(fdt, chosen_node);
449 ret = setup_ima_buffer(image, fdt, fdt_path_offset(fdt, "/chosen"));