1 // SPDX-License-Identifier: GPL-2.0
5 * Copyright (C) 2018 Linaro Limited
6 * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
8 * Most code is derived from arm64 port of kexec-tools
11 #define pr_fmt(fmt) "kexec_file: " fmt
13 #include <linux/ioport.h>
14 #include <linux/kernel.h>
15 #include <linux/kexec.h>
16 #include <linux/libfdt.h>
17 #include <linux/memblock.h>
18 #include <linux/of_fdt.h>
19 #include <linux/random.h>
20 #include <linux/slab.h>
21 #include <linux/string.h>
22 #include <linux/types.h>
23 #include <linux/vmalloc.h>
24 #include <asm/byteorder.h>
26 /* relevant device tree properties */
27 #define FDT_PROP_KEXEC_ELFHDR "linux,elfcorehdr"
28 #define FDT_PROP_MEM_RANGE "linux,usable-memory-range"
29 #define FDT_PROP_INITRD_START "linux,initrd-start"
30 #define FDT_PROP_INITRD_END "linux,initrd-end"
31 #define FDT_PROP_BOOTARGS "bootargs"
32 #define FDT_PROP_KASLR_SEED "kaslr-seed"
33 #define FDT_PROP_RNG_SEED "rng-seed"
34 #define RNG_SEED_SIZE 128
36 const struct kexec_file_ops
* const kexec_file_loaders
[] = {
41 int arch_kimage_file_post_load_cleanup(struct kimage
*image
)
43 vfree(image
->arch
.dtb
);
44 image
->arch
.dtb
= NULL
;
46 vfree(image
->arch
.elf_headers
);
47 image
->arch
.elf_headers
= NULL
;
48 image
->arch
.elf_headers_sz
= 0;
50 return kexec_image_post_load_cleanup_default(image
);
53 static int setup_dtb(struct kimage
*image
,
54 unsigned long initrd_load_addr
, unsigned long initrd_len
,
55 char *cmdline
, void *dtb
)
59 ret
= fdt_path_offset(dtb
, "/chosen");
65 ret
= fdt_delprop(dtb
, off
, FDT_PROP_KEXEC_ELFHDR
);
66 if (ret
&& ret
!= -FDT_ERR_NOTFOUND
)
68 ret
= fdt_delprop(dtb
, off
, FDT_PROP_MEM_RANGE
);
69 if (ret
&& ret
!= -FDT_ERR_NOTFOUND
)
72 if (image
->type
== KEXEC_TYPE_CRASH
) {
73 /* add linux,elfcorehdr */
74 ret
= fdt_appendprop_addrrange(dtb
, 0, off
,
75 FDT_PROP_KEXEC_ELFHDR
,
76 image
->arch
.elf_headers_mem
,
77 image
->arch
.elf_headers_sz
);
79 return (ret
== -FDT_ERR_NOSPACE
? -ENOMEM
: -EINVAL
);
81 /* add linux,usable-memory-range */
82 ret
= fdt_appendprop_addrrange(dtb
, 0, off
,
85 crashk_res
.end
- crashk_res
.start
+ 1);
87 return (ret
== -FDT_ERR_NOSPACE
? -ENOMEM
: -EINVAL
);
92 ret
= fdt_setprop_string(dtb
, off
, FDT_PROP_BOOTARGS
, cmdline
);
96 ret
= fdt_delprop(dtb
, off
, FDT_PROP_BOOTARGS
);
97 if (ret
&& (ret
!= -FDT_ERR_NOTFOUND
))
102 if (initrd_load_addr
) {
103 ret
= fdt_setprop_u64(dtb
, off
, FDT_PROP_INITRD_START
,
108 ret
= fdt_setprop_u64(dtb
, off
, FDT_PROP_INITRD_END
,
109 initrd_load_addr
+ initrd_len
);
113 ret
= fdt_delprop(dtb
, off
, FDT_PROP_INITRD_START
);
114 if (ret
&& (ret
!= -FDT_ERR_NOTFOUND
))
117 ret
= fdt_delprop(dtb
, off
, FDT_PROP_INITRD_END
);
118 if (ret
&& (ret
!= -FDT_ERR_NOTFOUND
))
123 ret
= fdt_delprop(dtb
, off
, FDT_PROP_KASLR_SEED
);
124 if (ret
== -FDT_ERR_NOTFOUND
)
129 if (rng_is_initialized()) {
130 u64 seed
= get_random_u64();
131 ret
= fdt_setprop_u64(dtb
, off
, FDT_PROP_KASLR_SEED
, seed
);
135 pr_notice("RNG is not initialised: omitting \"%s\" property\n",
136 FDT_PROP_KASLR_SEED
);
140 if (rng_is_initialized()) {
141 u8 rng_seed
[RNG_SEED_SIZE
];
142 get_random_bytes(rng_seed
, RNG_SEED_SIZE
);
143 ret
= fdt_setprop(dtb
, off
, FDT_PROP_RNG_SEED
, rng_seed
,
148 pr_notice("RNG is not initialised: omitting \"%s\" property\n",
154 return (ret
== -FDT_ERR_NOSPACE
) ? -ENOMEM
: -EINVAL
;
160 * More space needed so that we can add initrd, bootargs, kaslr-seed,
161 * rng-seed, userable-memory-range and elfcorehdr.
163 #define DTB_EXTRA_SPACE 0x1000
165 static int create_dtb(struct kimage
*image
,
166 unsigned long initrd_load_addr
, unsigned long initrd_len
,
167 char *cmdline
, void **dtb
)
174 cmdline_len
= cmdline
? strlen(cmdline
) : 0;
175 buf_size
= fdt_totalsize(initial_boot_params
)
176 + cmdline_len
+ DTB_EXTRA_SPACE
;
179 buf
= vmalloc(buf_size
);
183 /* duplicate a device tree blob */
184 ret
= fdt_open_into(initial_boot_params
, buf
, buf_size
);
188 ret
= setup_dtb(image
, initrd_load_addr
, initrd_len
,
192 if (ret
== -ENOMEM
) {
193 /* unlikely, but just in case */
194 buf_size
+= DTB_EXTRA_SPACE
;
209 static int prepare_elf_headers(void **addr
, unsigned long *sz
)
211 struct crash_mem
*cmem
;
212 unsigned int nr_ranges
;
215 phys_addr_t start
, end
;
217 nr_ranges
= 1; /* for exclusion of crashkernel region */
218 for_each_mem_range(i
, &memblock
.memory
, NULL
, NUMA_NO_NODE
,
219 MEMBLOCK_NONE
, &start
, &end
, NULL
)
222 cmem
= kmalloc(sizeof(struct crash_mem
) +
223 sizeof(struct crash_mem_range
) * nr_ranges
, GFP_KERNEL
);
227 cmem
->max_nr_ranges
= nr_ranges
;
229 for_each_mem_range(i
, &memblock
.memory
, NULL
, NUMA_NO_NODE
,
230 MEMBLOCK_NONE
, &start
, &end
, NULL
) {
231 cmem
->ranges
[cmem
->nr_ranges
].start
= start
;
232 cmem
->ranges
[cmem
->nr_ranges
].end
= end
- 1;
236 /* Exclude crashkernel region */
237 ret
= crash_exclude_mem_range(cmem
, crashk_res
.start
, crashk_res
.end
);
240 ret
= crash_prepare_elf64_headers(cmem
, true, addr
, sz
);
246 int load_other_segments(struct kimage
*image
,
247 unsigned long kernel_load_addr
,
248 unsigned long kernel_size
,
249 char *initrd
, unsigned long initrd_len
,
252 struct kexec_buf kbuf
;
253 void *headers
, *dtb
= NULL
;
254 unsigned long headers_sz
, initrd_load_addr
= 0, dtb_len
;
258 /* not allocate anything below the kernel */
259 kbuf
.buf_min
= kernel_load_addr
+ kernel_size
;
261 /* load elf core header */
262 if (image
->type
== KEXEC_TYPE_CRASH
) {
263 ret
= prepare_elf_headers(&headers
, &headers_sz
);
265 pr_err("Preparing elf core header failed\n");
269 kbuf
.buffer
= headers
;
270 kbuf
.bufsz
= headers_sz
;
271 kbuf
.mem
= KEXEC_BUF_MEM_UNKNOWN
;
272 kbuf
.memsz
= headers_sz
;
273 kbuf
.buf_align
= SZ_64K
; /* largest supported page size */
274 kbuf
.buf_max
= ULONG_MAX
;
275 kbuf
.top_down
= true;
277 ret
= kexec_add_buffer(&kbuf
);
282 image
->arch
.elf_headers
= headers
;
283 image
->arch
.elf_headers_mem
= kbuf
.mem
;
284 image
->arch
.elf_headers_sz
= headers_sz
;
286 pr_debug("Loaded elf core header at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
287 image
->arch
.elf_headers_mem
, headers_sz
, headers_sz
);
292 kbuf
.buffer
= initrd
;
293 kbuf
.bufsz
= initrd_len
;
294 kbuf
.mem
= KEXEC_BUF_MEM_UNKNOWN
;
295 kbuf
.memsz
= initrd_len
;
297 /* within 1GB-aligned window of up to 32GB in size */
298 kbuf
.buf_max
= round_down(kernel_load_addr
, SZ_1G
)
299 + (unsigned long)SZ_1G
* 32;
300 kbuf
.top_down
= false;
302 ret
= kexec_add_buffer(&kbuf
);
305 initrd_load_addr
= kbuf
.mem
;
307 pr_debug("Loaded initrd at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
308 initrd_load_addr
, initrd_len
, initrd_len
);
312 ret
= create_dtb(image
, initrd_load_addr
, initrd_len
, cmdline
, &dtb
);
314 pr_err("Preparing for new dtb failed\n");
318 dtb_len
= fdt_totalsize(dtb
);
320 kbuf
.bufsz
= dtb_len
;
321 kbuf
.mem
= KEXEC_BUF_MEM_UNKNOWN
;
322 kbuf
.memsz
= dtb_len
;
323 /* not across 2MB boundary */
324 kbuf
.buf_align
= SZ_2M
;
325 kbuf
.buf_max
= ULONG_MAX
;
326 kbuf
.top_down
= true;
328 ret
= kexec_add_buffer(&kbuf
);
331 image
->arch
.dtb
= dtb
;
332 image
->arch
.dtb_mem
= kbuf
.mem
;
334 pr_debug("Loaded dtb at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
335 kbuf
.mem
, dtb_len
, dtb_len
);