~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/powerpc/kexec/elf_64.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 /*
  3  * Load ELF vmlinux file for the kexec_file_load syscall.
  4  *
  5  * Copyright (C) 2004  Adam Litke (agl@us.ibm.com)
  6  * Copyright (C) 2004  IBM Corp.
  7  * Copyright (C) 2005  R Sharada (sharada@in.ibm.com)
  8  * Copyright (C) 2006  Mohan Kumar M (mohan@in.ibm.com)
  9  * Copyright (C) 2016  IBM Corporation
 10  *
 11  * Based on kexec-tools' kexec-elf-exec.c and kexec-elf-ppc64.c.
 12  * Heavily modified for the kernel by
 13  * Thiago Jung Bauermann <bauerman@linux.vnet.ibm.com>.
 14  */
 15 
 16 #define pr_fmt(fmt)     "kexec_elf: " fmt
 17 
 18 #include <linux/elf.h>
 19 #include <linux/kexec.h>
 20 #include <linux/libfdt.h>
 21 #include <linux/module.h>
 22 #include <linux/of.h>
 23 #include <linux/of_fdt.h>
 24 #include <linux/slab.h>
 25 #include <linux/types.h>
 26 #include <asm/kexec_ranges.h>
 27 
 28 static void *elf64_load(struct kimage *image, char *kernel_buf,
 29                         unsigned long kernel_len, char *initrd,
 30                         unsigned long initrd_len, char *cmdline,
 31                         unsigned long cmdline_len)
 32 {
 33         int ret;
 34         unsigned long kernel_load_addr;
 35         unsigned long initrd_load_addr = 0, fdt_load_addr;
 36         void *fdt;
 37         const void *slave_code;
 38         struct elfhdr ehdr;
 39         char *modified_cmdline = NULL;
 40         struct crash_mem *rmem = NULL;
 41         struct kexec_elf_info elf_info;
 42         struct kexec_buf kbuf = { .image = image, .buf_min = 0,
 43                                   .buf_max = ppc64_rma_size };
 44         struct kexec_buf pbuf = { .image = image, .buf_min = 0,
 45                                   .buf_max = ppc64_rma_size, .top_down = true,
 46                                   .mem = KEXEC_BUF_MEM_UNKNOWN };
 47 
 48         ret = kexec_build_elf_info(kernel_buf, kernel_len, &ehdr, &elf_info);
 49         if (ret)
 50                 return ERR_PTR(ret);
 51 
 52         if (IS_ENABLED(CONFIG_CRASH_DUMP) && image->type == KEXEC_TYPE_CRASH) {
 53                 /* min & max buffer values for kdump case */
 54                 kbuf.buf_min = pbuf.buf_min = crashk_res.start;
 55                 kbuf.buf_max = pbuf.buf_max =
 56                                 ((crashk_res.end < ppc64_rma_size) ?
 57                                  crashk_res.end : (ppc64_rma_size - 1));
 58         }
 59 
 60         ret = kexec_elf_load(image, &ehdr, &elf_info, &kbuf, &kernel_load_addr);
 61         if (ret)
 62                 goto out;
 63 
 64         kexec_dprintk("Loaded the kernel at 0x%lx\n", kernel_load_addr);
 65 
 66         ret = kexec_load_purgatory(image, &pbuf);
 67         if (ret) {
 68                 pr_err("Loading purgatory failed.\n");
 69                 goto out;
 70         }
 71 
 72         kexec_dprintk("Loaded purgatory at 0x%lx\n", pbuf.mem);
 73 
 74         /* Load additional segments needed for panic kernel */
 75         if (IS_ENABLED(CONFIG_CRASH_DUMP) && image->type == KEXEC_TYPE_CRASH) {
 76                 ret = load_crashdump_segments_ppc64(image, &kbuf);
 77                 if (ret) {
 78                         pr_err("Failed to load kdump kernel segments\n");
 79                         goto out;
 80                 }
 81 
 82                 /* Setup cmdline for kdump kernel case */
 83                 modified_cmdline = setup_kdump_cmdline(image, cmdline,
 84                                                        cmdline_len);
 85                 if (!modified_cmdline) {
 86                         pr_err("Setting up cmdline for kdump kernel failed\n");
 87                         ret = -EINVAL;
 88                         goto out;
 89                 }
 90                 cmdline = modified_cmdline;
 91         }
 92 
 93         if (initrd != NULL) {
 94                 kbuf.buffer = initrd;
 95                 kbuf.bufsz = kbuf.memsz = initrd_len;
 96                 kbuf.buf_align = PAGE_SIZE;
 97                 kbuf.top_down = false;
 98                 kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
 99                 ret = kexec_add_buffer(&kbuf);
100                 if (ret)
101                         goto out;
102                 initrd_load_addr = kbuf.mem;
103 
104                 kexec_dprintk("Loaded initrd at 0x%lx\n", initrd_load_addr);
105         }
106 
107         ret = get_reserved_memory_ranges(&rmem);
108         if (ret)
109                 goto out;
110 
111         fdt = of_kexec_alloc_and_setup_fdt(image, initrd_load_addr,
112                                            initrd_len, cmdline,
113                                            kexec_extra_fdt_size_ppc64(image, rmem));
114         if (!fdt) {
115                 pr_err("Error setting up the new device tree.\n");
116                 ret = -EINVAL;
117                 goto out;
118         }
119 
120         ret = setup_new_fdt_ppc64(image, fdt, rmem);
121         if (ret)
122                 goto out_free_fdt;
123 
124         if (!IS_ENABLED(CONFIG_CRASH_HOTPLUG) || image->type != KEXEC_TYPE_CRASH)
125                 fdt_pack(fdt);
126 
127         kbuf.buffer = fdt;
128         kbuf.bufsz = kbuf.memsz = fdt_totalsize(fdt);
129         kbuf.buf_align = PAGE_SIZE;
130         kbuf.top_down = true;
131         kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
132         ret = kexec_add_buffer(&kbuf);
133         if (ret)
134                 goto out_free_fdt;
135 
136         /* FDT will be freed in arch_kimage_file_post_load_cleanup */
137         image->arch.fdt = fdt;
138 
139         fdt_load_addr = kbuf.mem;
140 
141         kexec_dprintk("Loaded device tree at 0x%lx\n", fdt_load_addr);
142 
143         slave_code = elf_info.buffer + elf_info.proghdrs[0].p_offset;
144         ret = setup_purgatory_ppc64(image, slave_code, fdt, kernel_load_addr,
145                                     fdt_load_addr);
146         if (ret)
147                 pr_err("Error setting up the purgatory.\n");
148 
149         goto out;
150 
151 out_free_fdt:
152         kvfree(fdt);
153 out:
154         kfree(rmem);
155         kfree(modified_cmdline);
156         kexec_free_elf_info(&elf_info);
157 
158         return ret ? ERR_PTR(ret) : NULL;
159 }
160 
161 const struct kexec_file_ops kexec_elf64_ops = {
162         .probe = kexec_elf_probe,
163         .load = elf64_load,
164 };
165 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php