1818#include <linux/of.h>
1919#include <linux/libfdt.h>
2020#include <linux/types.h>
21+ #include <linux/memblock.h>
22+ #include <asm/setup.h>
2123
2224static int riscv_kexec_elf_load (struct kimage * image , struct elfhdr * ehdr ,
2325 struct kexec_elf_info * elf_info , unsigned long old_pbase ,
@@ -97,6 +99,79 @@ static int elf_find_pbase(struct kimage *image, unsigned long kernel_len,
9799 return ret ;
98100}
99101
102+ static int get_nr_ram_ranges_callback (struct resource * res , void * arg )
103+ {
104+ unsigned int * nr_ranges = arg ;
105+
106+ (* nr_ranges )++ ;
107+ return 0 ;
108+ }
109+
110+ static int prepare_elf64_ram_headers_callback (struct resource * res , void * arg )
111+ {
112+ struct crash_mem * cmem = arg ;
113+
114+ cmem -> ranges [cmem -> nr_ranges ].start = res -> start ;
115+ cmem -> ranges [cmem -> nr_ranges ].end = res -> end ;
116+ cmem -> nr_ranges ++ ;
117+
118+ return 0 ;
119+ }
120+
121+ static int prepare_elf_headers (void * * addr , unsigned long * sz )
122+ {
123+ struct crash_mem * cmem ;
124+ unsigned int nr_ranges ;
125+ int ret ;
126+
127+ nr_ranges = 1 ; /* For exclusion of crashkernel region */
128+ walk_system_ram_res (0 , -1 , & nr_ranges , get_nr_ram_ranges_callback );
129+
130+ cmem = kmalloc (struct_size (cmem , ranges , nr_ranges ), GFP_KERNEL );
131+ if (!cmem )
132+ return - ENOMEM ;
133+
134+ cmem -> max_nr_ranges = nr_ranges ;
135+ cmem -> nr_ranges = 0 ;
136+ ret = walk_system_ram_res (0 , -1 , cmem , prepare_elf64_ram_headers_callback );
137+ if (ret )
138+ goto out ;
139+
140+ /* Exclude crashkernel region */
141+ ret = crash_exclude_mem_range (cmem , crashk_res .start , crashk_res .end );
142+ if (!ret )
143+ ret = crash_prepare_elf64_headers (cmem , true, addr , sz );
144+
145+ out :
146+ kfree (cmem );
147+ return ret ;
148+ }
149+
150+ static char * setup_kdump_cmdline (struct kimage * image , char * cmdline ,
151+ unsigned long cmdline_len )
152+ {
153+ int elfcorehdr_strlen ;
154+ char * cmdline_ptr ;
155+
156+ cmdline_ptr = kzalloc (COMMAND_LINE_SIZE , GFP_KERNEL );
157+ if (!cmdline_ptr )
158+ return NULL ;
159+
160+ elfcorehdr_strlen = sprintf (cmdline_ptr , "elfcorehdr=0x%lx " ,
161+ image -> elf_load_addr );
162+
163+ if (elfcorehdr_strlen + cmdline_len > COMMAND_LINE_SIZE ) {
164+ pr_err ("Appending elfcorehdr=<addr> exceeds cmdline size\n" );
165+ kfree (cmdline_ptr );
166+ return NULL ;
167+ }
168+
169+ memcpy (cmdline_ptr + elfcorehdr_strlen , cmdline , cmdline_len );
170+ /* Ensure it's nul terminated */
171+ cmdline_ptr [COMMAND_LINE_SIZE - 1 ] = '\0' ;
172+ return cmdline_ptr ;
173+ }
174+
100175static void * elf_kexec_load (struct kimage * image , char * kernel_buf ,
101176 unsigned long kernel_len , char * initrd ,
102177 unsigned long initrd_len , char * cmdline ,
@@ -106,10 +181,12 @@ static void *elf_kexec_load(struct kimage *image, char *kernel_buf,
106181 unsigned long old_kernel_pbase = ULONG_MAX ;
107182 unsigned long new_kernel_pbase = 0UL ;
108183 unsigned long initrd_pbase = 0UL ;
109- void * fdt ;
184+ unsigned long headers_sz ;
185+ void * fdt , * headers ;
110186 struct elfhdr ehdr ;
111187 struct kexec_buf kbuf ;
112188 struct kexec_elf_info elf_info ;
189+ char * modified_cmdline = NULL ;
113190
114191 ret = kexec_build_elf_info (kernel_buf , kernel_len , & ehdr , & elf_info );
115192 if (ret )
@@ -130,6 +207,45 @@ static void *elf_kexec_load(struct kimage *image, char *kernel_buf,
130207 kbuf .image = image ;
131208 kbuf .buf_min = new_kernel_pbase + kernel_len ;
132209 kbuf .buf_max = ULONG_MAX ;
210+
211+ /* Add elfcorehdr */
212+ if (image -> type == KEXEC_TYPE_CRASH ) {
213+ ret = prepare_elf_headers (& headers , & headers_sz );
214+ if (ret ) {
215+ pr_err ("Preparing elf core header failed\n" );
216+ goto out ;
217+ }
218+
219+ kbuf .buffer = headers ;
220+ kbuf .bufsz = headers_sz ;
221+ kbuf .mem = KEXEC_BUF_MEM_UNKNOWN ;
222+ kbuf .memsz = headers_sz ;
223+ kbuf .buf_align = ELF_CORE_HEADER_ALIGN ;
224+ kbuf .top_down = true;
225+
226+ ret = kexec_add_buffer (& kbuf );
227+ if (ret ) {
228+ vfree (headers );
229+ goto out ;
230+ }
231+ image -> elf_headers = headers ;
232+ image -> elf_load_addr = kbuf .mem ;
233+ image -> elf_headers_sz = headers_sz ;
234+
235+ pr_debug ("Loaded elf core header at 0x%lx bufsz=0x%lx memsz=0x%lx\n" ,
236+ image -> elf_load_addr , kbuf .bufsz , kbuf .memsz );
237+
238+ /* Setup cmdline for kdump kernel case */
239+ modified_cmdline = setup_kdump_cmdline (image , cmdline ,
240+ cmdline_len );
241+ if (!modified_cmdline ) {
242+ pr_err ("Setting up cmdline for kdump kernel failed\n" );
243+ ret = - EINVAL ;
244+ goto out ;
245+ }
246+ cmdline = modified_cmdline ;
247+ }
248+
133249 /* Add the initrd to the image */
134250 if (initrd != NULL ) {
135251 kbuf .buffer = initrd ;
@@ -170,6 +286,7 @@ static void *elf_kexec_load(struct kimage *image, char *kernel_buf,
170286out_free_fdt :
171287 kvfree (fdt );
172288out :
289+ kfree (modified_cmdline );
173290 kexec_free_elf_info (& elf_info );
174291 return ret ? ERR_PTR (ret ) : NULL ;
175292}
0 commit comments