1 // SPDX-License-Identifier: GPL-2.0
3 * Load ELF vmlinux file for the kexec_file_load syscall.
5 * Copyright (c) 2019 Sven Schnelle <svens@stackframe.org>
9 #include <linux/kexec.h>
10 #include <linux/libfdt.h>
11 #include <linux/module.h>
12 #include <linux/of_fdt.h>
13 #include <linux/slab.h>
14 #include <linux/types.h>
16 static void *elf_load(struct kimage
*image
, char *kernel_buf
,
17 unsigned long kernel_len
, char *initrd
,
18 unsigned long initrd_len
, char *cmdline
,
19 unsigned long cmdline_len
)
22 unsigned long kernel_load_addr
;
24 struct kexec_elf_info elf_info
;
25 struct kexec_buf kbuf
= { .image
= image
, .buf_min
= 0,
28 ret
= kexec_build_elf_info(kernel_buf
, kernel_len
, &ehdr
, &elf_info
);
32 ret
= kexec_elf_load(image
, &ehdr
, &elf_info
, &kbuf
, &kernel_load_addr
);
36 image
->start
= __pa(elf_info
.ehdr
->e_entry
);
38 for (i
= 0; i
< image
->nr_segments
; i
++)
39 image
->segment
[i
].mem
= __pa(image
->segment
[i
].mem
);
41 pr_debug("Loaded the kernel at 0x%lx, entry at 0x%lx\n",
42 kernel_load_addr
, image
->start
);
46 kbuf
.bufsz
= kbuf
.memsz
= initrd_len
;
47 kbuf
.buf_align
= PAGE_SIZE
;
48 kbuf
.top_down
= false;
49 kbuf
.mem
= KEXEC_BUF_MEM_UNKNOWN
;
50 ret
= kexec_add_buffer(&kbuf
);
54 pr_debug("Loaded initrd at 0x%lx\n", kbuf
.mem
);
55 image
->arch
.initrd_start
= kbuf
.mem
;
56 image
->arch
.initrd_end
= kbuf
.mem
+ initrd_len
;
59 if (cmdline
!= NULL
) {
60 kbuf
.buffer
= cmdline
;
61 kbuf
.bufsz
= kbuf
.memsz
= ALIGN(cmdline_len
, 8);
62 kbuf
.buf_align
= PAGE_SIZE
;
63 kbuf
.top_down
= false;
64 kbuf
.buf_min
= PAGE0
->mem_free
+ PAGE_SIZE
;
65 kbuf
.buf_max
= kernel_load_addr
;
66 kbuf
.mem
= KEXEC_BUF_MEM_UNKNOWN
;
67 ret
= kexec_add_buffer(&kbuf
);
71 pr_debug("Loaded cmdline at 0x%lx\n", kbuf
.mem
);
72 image
->arch
.cmdline
= kbuf
.mem
;
78 const struct kexec_file_ops kexec_elf_ops
= {
79 .probe
= kexec_elf_probe
,
83 const struct kexec_file_ops
* const kexec_file_loaders
[] = {