vmcore: allocate ELF note segment in the 2nd kernel vmalloc memory
[platform/adaptation/renesas_rcar/renesas_kernel.git] / fs / proc / vmcore.c
1 /*
2  *      fs/proc/vmcore.c Interface for accessing the crash
3  *                               dump from the system's previous life.
4  *      Heavily borrowed from fs/proc/kcore.c
5  *      Created by: Hariprasad Nellitheertha (hari@in.ibm.com)
6  *      Copyright (C) IBM Corporation, 2004. All rights reserved
7  *
8  */
9
10 #include <linux/mm.h>
11 #include <linux/kcore.h>
12 #include <linux/user.h>
13 #include <linux/elf.h>
14 #include <linux/elfcore.h>
15 #include <linux/export.h>
16 #include <linux/slab.h>
17 #include <linux/highmem.h>
18 #include <linux/printk.h>
19 #include <linux/bootmem.h>
20 #include <linux/init.h>
21 #include <linux/crash_dump.h>
22 #include <linux/list.h>
23 #include <asm/uaccess.h>
24 #include <asm/io.h>
25 #include "internal.h"
26
27 /* List representing chunks of contiguous memory areas and their offsets in
28  * vmcore file.
29  */
30 static LIST_HEAD(vmcore_list);
31
32 /* Stores the pointer to the buffer containing kernel elf core headers. */
33 static char *elfcorebuf;
34 static size_t elfcorebuf_sz;
35 static size_t elfcorebuf_sz_orig;
36
37 static char *elfnotes_buf;
38 static size_t elfnotes_sz;
39
40 /* Total size of vmcore file. */
41 static u64 vmcore_size;
42
43 static struct proc_dir_entry *proc_vmcore = NULL;
44
45 /*
46  * Returns > 0 for RAM pages, 0 for non-RAM pages, < 0 on error
47  * The called function has to take care of module refcounting.
48  */
49 static int (*oldmem_pfn_is_ram)(unsigned long pfn);
50
51 int register_oldmem_pfn_is_ram(int (*fn)(unsigned long pfn))
52 {
53         if (oldmem_pfn_is_ram)
54                 return -EBUSY;
55         oldmem_pfn_is_ram = fn;
56         return 0;
57 }
58 EXPORT_SYMBOL_GPL(register_oldmem_pfn_is_ram);
59
60 void unregister_oldmem_pfn_is_ram(void)
61 {
62         oldmem_pfn_is_ram = NULL;
63         wmb();
64 }
65 EXPORT_SYMBOL_GPL(unregister_oldmem_pfn_is_ram);
66
67 static int pfn_is_ram(unsigned long pfn)
68 {
69         int (*fn)(unsigned long pfn);
70         /* pfn is ram unless fn() checks pagetype */
71         int ret = 1;
72
73         /*
74          * Ask hypervisor if the pfn is really ram.
75          * A ballooned page contains no data and reading from such a page
76          * will cause high load in the hypervisor.
77          */
78         fn = oldmem_pfn_is_ram;
79         if (fn)
80                 ret = fn(pfn);
81
82         return ret;
83 }
84
85 /* Reads a page from the oldmem device from given offset. */
86 static ssize_t read_from_oldmem(char *buf, size_t count,
87                                 u64 *ppos, int userbuf)
88 {
89         unsigned long pfn, offset;
90         size_t nr_bytes;
91         ssize_t read = 0, tmp;
92
93         if (!count)
94                 return 0;
95
96         offset = (unsigned long)(*ppos % PAGE_SIZE);
97         pfn = (unsigned long)(*ppos / PAGE_SIZE);
98
99         do {
100                 if (count > (PAGE_SIZE - offset))
101                         nr_bytes = PAGE_SIZE - offset;
102                 else
103                         nr_bytes = count;
104
105                 /* If pfn is not ram, return zeros for sparse dump files */
106                 if (pfn_is_ram(pfn) == 0)
107                         memset(buf, 0, nr_bytes);
108                 else {
109                         tmp = copy_oldmem_page(pfn, buf, nr_bytes,
110                                                 offset, userbuf);
111                         if (tmp < 0)
112                                 return tmp;
113                 }
114                 *ppos += nr_bytes;
115                 count -= nr_bytes;
116                 buf += nr_bytes;
117                 read += nr_bytes;
118                 ++pfn;
119                 offset = 0;
120         } while (count);
121
122         return read;
123 }
124
125 /* Read from the ELF header and then the crash dump. On error, negative value is
126  * returned otherwise number of bytes read are returned.
127  */
128 static ssize_t read_vmcore(struct file *file, char __user *buffer,
129                                 size_t buflen, loff_t *fpos)
130 {
131         ssize_t acc = 0, tmp;
132         size_t tsz;
133         u64 start;
134         struct vmcore *m = NULL;
135
136         if (buflen == 0 || *fpos >= vmcore_size)
137                 return 0;
138
139         /* trim buflen to not go beyond EOF */
140         if (buflen > vmcore_size - *fpos)
141                 buflen = vmcore_size - *fpos;
142
143         /* Read ELF core header */
144         if (*fpos < elfcorebuf_sz) {
145                 tsz = min(elfcorebuf_sz - (size_t)*fpos, buflen);
146                 if (copy_to_user(buffer, elfcorebuf + *fpos, tsz))
147                         return -EFAULT;
148                 buflen -= tsz;
149                 *fpos += tsz;
150                 buffer += tsz;
151                 acc += tsz;
152
153                 /* leave now if filled buffer already */
154                 if (buflen == 0)
155                         return acc;
156         }
157
158         /* Read Elf note segment */
159         if (*fpos < elfcorebuf_sz + elfnotes_sz) {
160                 void *kaddr;
161
162                 tsz = min(elfcorebuf_sz + elfnotes_sz - (size_t)*fpos, buflen);
163                 kaddr = elfnotes_buf + *fpos - elfcorebuf_sz;
164                 if (copy_to_user(buffer, kaddr, tsz))
165                         return -EFAULT;
166                 buflen -= tsz;
167                 *fpos += tsz;
168                 buffer += tsz;
169                 acc += tsz;
170
171                 /* leave now if filled buffer already */
172                 if (buflen == 0)
173                         return acc;
174         }
175
176         list_for_each_entry(m, &vmcore_list, list) {
177                 if (*fpos < m->offset + m->size) {
178                         tsz = min_t(size_t, m->offset + m->size - *fpos, buflen);
179                         start = m->paddr + *fpos - m->offset;
180                         tmp = read_from_oldmem(buffer, tsz, &start, 1);
181                         if (tmp < 0)
182                                 return tmp;
183                         buflen -= tsz;
184                         *fpos += tsz;
185                         buffer += tsz;
186                         acc += tsz;
187
188                         /* leave now if filled buffer already */
189                         if (buflen == 0)
190                                 return acc;
191                 }
192         }
193
194         return acc;
195 }
196
197 static const struct file_operations proc_vmcore_operations = {
198         .read           = read_vmcore,
199         .llseek         = default_llseek,
200 };
201
202 static struct vmcore* __init get_new_element(void)
203 {
204         return kzalloc(sizeof(struct vmcore), GFP_KERNEL);
205 }
206
207 static u64 __init get_vmcore_size_elf64(char *elfptr, size_t elfsz)
208 {
209         int i;
210         u64 size;
211         Elf64_Ehdr *ehdr_ptr;
212         Elf64_Phdr *phdr_ptr;
213
214         ehdr_ptr = (Elf64_Ehdr *)elfptr;
215         phdr_ptr = (Elf64_Phdr*)(elfptr + sizeof(Elf64_Ehdr));
216         size = elfsz;
217         for (i = 0; i < ehdr_ptr->e_phnum; i++) {
218                 size += phdr_ptr->p_memsz;
219                 phdr_ptr++;
220         }
221         return size;
222 }
223
224 static u64 __init get_vmcore_size_elf32(char *elfptr, size_t elfsz)
225 {
226         int i;
227         u64 size;
228         Elf32_Ehdr *ehdr_ptr;
229         Elf32_Phdr *phdr_ptr;
230
231         ehdr_ptr = (Elf32_Ehdr *)elfptr;
232         phdr_ptr = (Elf32_Phdr*)(elfptr + sizeof(Elf32_Ehdr));
233         size = elfsz;
234         for (i = 0; i < ehdr_ptr->e_phnum; i++) {
235                 size += phdr_ptr->p_memsz;
236                 phdr_ptr++;
237         }
238         return size;
239 }
240
241 /**
242  * update_note_header_size_elf64 - update p_memsz member of each PT_NOTE entry
243  *
244  * @ehdr_ptr: ELF header
245  *
246  * This function updates p_memsz member of each PT_NOTE entry in the
247  * program header table pointed to by @ehdr_ptr to real size of ELF
248  * note segment.
249  */
250 static int __init update_note_header_size_elf64(const Elf64_Ehdr *ehdr_ptr)
251 {
252         int i, rc=0;
253         Elf64_Phdr *phdr_ptr;
254         Elf64_Nhdr *nhdr_ptr;
255
256         phdr_ptr = (Elf64_Phdr *)(ehdr_ptr + 1);
257         for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
258                 void *notes_section;
259                 u64 offset, max_sz, sz, real_sz = 0;
260                 if (phdr_ptr->p_type != PT_NOTE)
261                         continue;
262                 max_sz = phdr_ptr->p_memsz;
263                 offset = phdr_ptr->p_offset;
264                 notes_section = kmalloc(max_sz, GFP_KERNEL);
265                 if (!notes_section)
266                         return -ENOMEM;
267                 rc = read_from_oldmem(notes_section, max_sz, &offset, 0);
268                 if (rc < 0) {
269                         kfree(notes_section);
270                         return rc;
271                 }
272                 nhdr_ptr = notes_section;
273                 while (real_sz < max_sz) {
274                         if (nhdr_ptr->n_namesz == 0)
275                                 break;
276                         sz = sizeof(Elf64_Nhdr) +
277                                 ((nhdr_ptr->n_namesz + 3) & ~3) +
278                                 ((nhdr_ptr->n_descsz + 3) & ~3);
279                         real_sz += sz;
280                         nhdr_ptr = (Elf64_Nhdr*)((char*)nhdr_ptr + sz);
281                 }
282                 kfree(notes_section);
283                 phdr_ptr->p_memsz = real_sz;
284         }
285
286         return 0;
287 }
288
289 /**
290  * get_note_number_and_size_elf64 - get the number of PT_NOTE program
291  * headers and sum of real size of their ELF note segment headers and
292  * data.
293  *
294  * @ehdr_ptr: ELF header
295  * @nr_ptnote: buffer for the number of PT_NOTE program headers
296  * @sz_ptnote: buffer for size of unique PT_NOTE program header
297  *
298  * This function is used to merge multiple PT_NOTE program headers
299  * into a unique single one. The resulting unique entry will have
300  * @sz_ptnote in its phdr->p_mem.
301  *
302  * It is assumed that program headers with PT_NOTE type pointed to by
303  * @ehdr_ptr has already been updated by update_note_header_size_elf64
304  * and each of PT_NOTE program headers has actual ELF note segment
305  * size in its p_memsz member.
306  */
307 static int __init get_note_number_and_size_elf64(const Elf64_Ehdr *ehdr_ptr,
308                                                  int *nr_ptnote, u64 *sz_ptnote)
309 {
310         int i;
311         Elf64_Phdr *phdr_ptr;
312
313         *nr_ptnote = *sz_ptnote = 0;
314
315         phdr_ptr = (Elf64_Phdr *)(ehdr_ptr + 1);
316         for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
317                 if (phdr_ptr->p_type != PT_NOTE)
318                         continue;
319                 *nr_ptnote += 1;
320                 *sz_ptnote += phdr_ptr->p_memsz;
321         }
322
323         return 0;
324 }
325
326 /**
327  * copy_notes_elf64 - copy ELF note segments in a given buffer
328  *
329  * @ehdr_ptr: ELF header
330  * @notes_buf: buffer into which ELF note segments are copied
331  *
332  * This function is used to copy ELF note segment in the 1st kernel
333  * into the buffer @notes_buf in the 2nd kernel. It is assumed that
334  * size of the buffer @notes_buf is equal to or larger than sum of the
335  * real ELF note segment headers and data.
336  *
337  * It is assumed that program headers with PT_NOTE type pointed to by
338  * @ehdr_ptr has already been updated by update_note_header_size_elf64
339  * and each of PT_NOTE program headers has actual ELF note segment
340  * size in its p_memsz member.
341  */
342 static int __init copy_notes_elf64(const Elf64_Ehdr *ehdr_ptr, char *notes_buf)
343 {
344         int i, rc=0;
345         Elf64_Phdr *phdr_ptr;
346
347         phdr_ptr = (Elf64_Phdr*)(ehdr_ptr + 1);
348
349         for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
350                 u64 offset;
351                 if (phdr_ptr->p_type != PT_NOTE)
352                         continue;
353                 offset = phdr_ptr->p_offset;
354                 rc = read_from_oldmem(notes_buf, phdr_ptr->p_memsz, &offset, 0);
355                 if (rc < 0)
356                         return rc;
357                 notes_buf += phdr_ptr->p_memsz;
358         }
359
360         return 0;
361 }
362
363 /* Merges all the PT_NOTE headers into one. */
364 static int __init merge_note_headers_elf64(char *elfptr, size_t *elfsz,
365                                            char **notes_buf, size_t *notes_sz)
366 {
367         int i, nr_ptnote=0, rc=0;
368         char *tmp;
369         Elf64_Ehdr *ehdr_ptr;
370         Elf64_Phdr phdr;
371         u64 phdr_sz = 0, note_off;
372
373         ehdr_ptr = (Elf64_Ehdr *)elfptr;
374
375         rc = update_note_header_size_elf64(ehdr_ptr);
376         if (rc < 0)
377                 return rc;
378
379         rc = get_note_number_and_size_elf64(ehdr_ptr, &nr_ptnote, &phdr_sz);
380         if (rc < 0)
381                 return rc;
382
383         *notes_sz = roundup(phdr_sz, PAGE_SIZE);
384         *notes_buf = vzalloc(*notes_sz);
385         if (!*notes_buf)
386                 return -ENOMEM;
387
388         rc = copy_notes_elf64(ehdr_ptr, *notes_buf);
389         if (rc < 0)
390                 return rc;
391
392         /* Prepare merged PT_NOTE program header. */
393         phdr.p_type    = PT_NOTE;
394         phdr.p_flags   = 0;
395         note_off = sizeof(Elf64_Ehdr) +
396                         (ehdr_ptr->e_phnum - nr_ptnote +1) * sizeof(Elf64_Phdr);
397         phdr.p_offset  = roundup(note_off, PAGE_SIZE);
398         phdr.p_vaddr   = phdr.p_paddr = 0;
399         phdr.p_filesz  = phdr.p_memsz = phdr_sz;
400         phdr.p_align   = 0;
401
402         /* Add merged PT_NOTE program header*/
403         tmp = elfptr + sizeof(Elf64_Ehdr);
404         memcpy(tmp, &phdr, sizeof(phdr));
405         tmp += sizeof(phdr);
406
407         /* Remove unwanted PT_NOTE program headers. */
408         i = (nr_ptnote - 1) * sizeof(Elf64_Phdr);
409         *elfsz = *elfsz - i;
410         memmove(tmp, tmp+i, ((*elfsz)-sizeof(Elf64_Ehdr)-sizeof(Elf64_Phdr)));
411         memset(elfptr + *elfsz, 0, i);
412         *elfsz = roundup(*elfsz, PAGE_SIZE);
413
414         /* Modify e_phnum to reflect merged headers. */
415         ehdr_ptr->e_phnum = ehdr_ptr->e_phnum - nr_ptnote + 1;
416
417         return 0;
418 }
419
420 /**
421  * update_note_header_size_elf32 - update p_memsz member of each PT_NOTE entry
422  *
423  * @ehdr_ptr: ELF header
424  *
425  * This function updates p_memsz member of each PT_NOTE entry in the
426  * program header table pointed to by @ehdr_ptr to real size of ELF
427  * note segment.
428  */
429 static int __init update_note_header_size_elf32(const Elf32_Ehdr *ehdr_ptr)
430 {
431         int i, rc=0;
432         Elf32_Phdr *phdr_ptr;
433         Elf32_Nhdr *nhdr_ptr;
434
435         phdr_ptr = (Elf32_Phdr *)(ehdr_ptr + 1);
436         for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
437                 void *notes_section;
438                 u64 offset, max_sz, sz, real_sz = 0;
439                 if (phdr_ptr->p_type != PT_NOTE)
440                         continue;
441                 max_sz = phdr_ptr->p_memsz;
442                 offset = phdr_ptr->p_offset;
443                 notes_section = kmalloc(max_sz, GFP_KERNEL);
444                 if (!notes_section)
445                         return -ENOMEM;
446                 rc = read_from_oldmem(notes_section, max_sz, &offset, 0);
447                 if (rc < 0) {
448                         kfree(notes_section);
449                         return rc;
450                 }
451                 nhdr_ptr = notes_section;
452                 while (real_sz < max_sz) {
453                         if (nhdr_ptr->n_namesz == 0)
454                                 break;
455                         sz = sizeof(Elf32_Nhdr) +
456                                 ((nhdr_ptr->n_namesz + 3) & ~3) +
457                                 ((nhdr_ptr->n_descsz + 3) & ~3);
458                         real_sz += sz;
459                         nhdr_ptr = (Elf32_Nhdr*)((char*)nhdr_ptr + sz);
460                 }
461                 kfree(notes_section);
462                 phdr_ptr->p_memsz = real_sz;
463         }
464
465         return 0;
466 }
467
468 /**
469  * get_note_number_and_size_elf32 - get the number of PT_NOTE program
470  * headers and sum of real size of their ELF note segment headers and
471  * data.
472  *
473  * @ehdr_ptr: ELF header
474  * @nr_ptnote: buffer for the number of PT_NOTE program headers
475  * @sz_ptnote: buffer for size of unique PT_NOTE program header
476  *
477  * This function is used to merge multiple PT_NOTE program headers
478  * into a unique single one. The resulting unique entry will have
479  * @sz_ptnote in its phdr->p_mem.
480  *
481  * It is assumed that program headers with PT_NOTE type pointed to by
482  * @ehdr_ptr has already been updated by update_note_header_size_elf32
483  * and each of PT_NOTE program headers has actual ELF note segment
484  * size in its p_memsz member.
485  */
486 static int __init get_note_number_and_size_elf32(const Elf32_Ehdr *ehdr_ptr,
487                                                  int *nr_ptnote, u64 *sz_ptnote)
488 {
489         int i;
490         Elf32_Phdr *phdr_ptr;
491
492         *nr_ptnote = *sz_ptnote = 0;
493
494         phdr_ptr = (Elf32_Phdr *)(ehdr_ptr + 1);
495         for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
496                 if (phdr_ptr->p_type != PT_NOTE)
497                         continue;
498                 *nr_ptnote += 1;
499                 *sz_ptnote += phdr_ptr->p_memsz;
500         }
501
502         return 0;
503 }
504
505 /**
506  * copy_notes_elf32 - copy ELF note segments in a given buffer
507  *
508  * @ehdr_ptr: ELF header
509  * @notes_buf: buffer into which ELF note segments are copied
510  *
511  * This function is used to copy ELF note segment in the 1st kernel
512  * into the buffer @notes_buf in the 2nd kernel. It is assumed that
513  * size of the buffer @notes_buf is equal to or larger than sum of the
514  * real ELF note segment headers and data.
515  *
516  * It is assumed that program headers with PT_NOTE type pointed to by
517  * @ehdr_ptr has already been updated by update_note_header_size_elf32
518  * and each of PT_NOTE program headers has actual ELF note segment
519  * size in its p_memsz member.
520  */
521 static int __init copy_notes_elf32(const Elf32_Ehdr *ehdr_ptr, char *notes_buf)
522 {
523         int i, rc=0;
524         Elf32_Phdr *phdr_ptr;
525
526         phdr_ptr = (Elf32_Phdr*)(ehdr_ptr + 1);
527
528         for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
529                 u64 offset;
530                 if (phdr_ptr->p_type != PT_NOTE)
531                         continue;
532                 offset = phdr_ptr->p_offset;
533                 rc = read_from_oldmem(notes_buf, phdr_ptr->p_memsz, &offset, 0);
534                 if (rc < 0)
535                         return rc;
536                 notes_buf += phdr_ptr->p_memsz;
537         }
538
539         return 0;
540 }
541
542 /* Merges all the PT_NOTE headers into one. */
543 static int __init merge_note_headers_elf32(char *elfptr, size_t *elfsz,
544                                            char **notes_buf, size_t *notes_sz)
545 {
546         int i, nr_ptnote=0, rc=0;
547         char *tmp;
548         Elf32_Ehdr *ehdr_ptr;
549         Elf32_Phdr phdr;
550         u64 phdr_sz = 0, note_off;
551
552         ehdr_ptr = (Elf32_Ehdr *)elfptr;
553
554         rc = update_note_header_size_elf32(ehdr_ptr);
555         if (rc < 0)
556                 return rc;
557
558         rc = get_note_number_and_size_elf32(ehdr_ptr, &nr_ptnote, &phdr_sz);
559         if (rc < 0)
560                 return rc;
561
562         *notes_sz = roundup(phdr_sz, PAGE_SIZE);
563         *notes_buf = vzalloc(*notes_sz);
564         if (!*notes_buf)
565                 return -ENOMEM;
566
567         rc = copy_notes_elf32(ehdr_ptr, *notes_buf);
568         if (rc < 0)
569                 return rc;
570
571         /* Prepare merged PT_NOTE program header. */
572         phdr.p_type    = PT_NOTE;
573         phdr.p_flags   = 0;
574         note_off = sizeof(Elf32_Ehdr) +
575                         (ehdr_ptr->e_phnum - nr_ptnote +1) * sizeof(Elf32_Phdr);
576         phdr.p_offset  = roundup(note_off, PAGE_SIZE);
577         phdr.p_vaddr   = phdr.p_paddr = 0;
578         phdr.p_filesz  = phdr.p_memsz = phdr_sz;
579         phdr.p_align   = 0;
580
581         /* Add merged PT_NOTE program header*/
582         tmp = elfptr + sizeof(Elf32_Ehdr);
583         memcpy(tmp, &phdr, sizeof(phdr));
584         tmp += sizeof(phdr);
585
586         /* Remove unwanted PT_NOTE program headers. */
587         i = (nr_ptnote - 1) * sizeof(Elf32_Phdr);
588         *elfsz = *elfsz - i;
589         memmove(tmp, tmp+i, ((*elfsz)-sizeof(Elf32_Ehdr)-sizeof(Elf32_Phdr)));
590         memset(elfptr + *elfsz, 0, i);
591         *elfsz = roundup(*elfsz, PAGE_SIZE);
592
593         /* Modify e_phnum to reflect merged headers. */
594         ehdr_ptr->e_phnum = ehdr_ptr->e_phnum - nr_ptnote + 1;
595
596         return 0;
597 }
598
599 /* Add memory chunks represented by program headers to vmcore list. Also update
600  * the new offset fields of exported program headers. */
601 static int __init process_ptload_program_headers_elf64(char *elfptr,
602                                                 size_t elfsz,
603                                                 size_t elfnotes_sz,
604                                                 struct list_head *vc_list)
605 {
606         int i;
607         Elf64_Ehdr *ehdr_ptr;
608         Elf64_Phdr *phdr_ptr;
609         loff_t vmcore_off;
610         struct vmcore *new;
611
612         ehdr_ptr = (Elf64_Ehdr *)elfptr;
613         phdr_ptr = (Elf64_Phdr*)(elfptr + sizeof(Elf64_Ehdr)); /* PT_NOTE hdr */
614
615         /* Skip Elf header, program headers and Elf note segment. */
616         vmcore_off = elfsz + elfnotes_sz;
617
618         for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
619                 u64 paddr, start, end, size;
620
621                 if (phdr_ptr->p_type != PT_LOAD)
622                         continue;
623
624                 paddr = phdr_ptr->p_offset;
625                 start = rounddown(paddr, PAGE_SIZE);
626                 end = roundup(paddr + phdr_ptr->p_memsz, PAGE_SIZE);
627                 size = end - start;
628
629                 /* Add this contiguous chunk of memory to vmcore list.*/
630                 new = get_new_element();
631                 if (!new)
632                         return -ENOMEM;
633                 new->paddr = start;
634                 new->size = size;
635                 list_add_tail(&new->list, vc_list);
636
637                 /* Update the program header offset. */
638                 phdr_ptr->p_offset = vmcore_off + (paddr - start);
639                 vmcore_off = vmcore_off + size;
640         }
641         return 0;
642 }
643
644 static int __init process_ptload_program_headers_elf32(char *elfptr,
645                                                 size_t elfsz,
646                                                 size_t elfnotes_sz,
647                                                 struct list_head *vc_list)
648 {
649         int i;
650         Elf32_Ehdr *ehdr_ptr;
651         Elf32_Phdr *phdr_ptr;
652         loff_t vmcore_off;
653         struct vmcore *new;
654
655         ehdr_ptr = (Elf32_Ehdr *)elfptr;
656         phdr_ptr = (Elf32_Phdr*)(elfptr + sizeof(Elf32_Ehdr)); /* PT_NOTE hdr */
657
658         /* Skip Elf header, program headers and Elf note segment. */
659         vmcore_off = elfsz + elfnotes_sz;
660
661         for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
662                 u64 paddr, start, end, size;
663
664                 if (phdr_ptr->p_type != PT_LOAD)
665                         continue;
666
667                 paddr = phdr_ptr->p_offset;
668                 start = rounddown(paddr, PAGE_SIZE);
669                 end = roundup(paddr + phdr_ptr->p_memsz, PAGE_SIZE);
670                 size = end - start;
671
672                 /* Add this contiguous chunk of memory to vmcore list.*/
673                 new = get_new_element();
674                 if (!new)
675                         return -ENOMEM;
676                 new->paddr = start;
677                 new->size = size;
678                 list_add_tail(&new->list, vc_list);
679
680                 /* Update the program header offset */
681                 phdr_ptr->p_offset = vmcore_off + (paddr - start);
682                 vmcore_off = vmcore_off + size;
683         }
684         return 0;
685 }
686
687 /* Sets offset fields of vmcore elements. */
688 static void __init set_vmcore_list_offsets(size_t elfsz, size_t elfnotes_sz,
689                                            struct list_head *vc_list)
690 {
691         loff_t vmcore_off;
692         struct vmcore *m;
693
694         /* Skip Elf header, program headers and Elf note segment. */
695         vmcore_off = elfsz + elfnotes_sz;
696
697         list_for_each_entry(m, vc_list, list) {
698                 m->offset = vmcore_off;
699                 vmcore_off += m->size;
700         }
701 }
702
703 static void free_elfcorebuf(void)
704 {
705         free_pages((unsigned long)elfcorebuf, get_order(elfcorebuf_sz_orig));
706         elfcorebuf = NULL;
707         vfree(elfnotes_buf);
708         elfnotes_buf = NULL;
709 }
710
711 static int __init parse_crash_elf64_headers(void)
712 {
713         int rc=0;
714         Elf64_Ehdr ehdr;
715         u64 addr;
716
717         addr = elfcorehdr_addr;
718
719         /* Read Elf header */
720         rc = read_from_oldmem((char*)&ehdr, sizeof(Elf64_Ehdr), &addr, 0);
721         if (rc < 0)
722                 return rc;
723
724         /* Do some basic Verification. */
725         if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0 ||
726                 (ehdr.e_type != ET_CORE) ||
727                 !vmcore_elf64_check_arch(&ehdr) ||
728                 ehdr.e_ident[EI_CLASS] != ELFCLASS64 ||
729                 ehdr.e_ident[EI_VERSION] != EV_CURRENT ||
730                 ehdr.e_version != EV_CURRENT ||
731                 ehdr.e_ehsize != sizeof(Elf64_Ehdr) ||
732                 ehdr.e_phentsize != sizeof(Elf64_Phdr) ||
733                 ehdr.e_phnum == 0) {
734                 pr_warn("Warning: Core image elf header is not sane\n");
735                 return -EINVAL;
736         }
737
738         /* Read in all elf headers. */
739         elfcorebuf_sz_orig = sizeof(Elf64_Ehdr) +
740                                 ehdr.e_phnum * sizeof(Elf64_Phdr);
741         elfcorebuf_sz = elfcorebuf_sz_orig;
742         elfcorebuf = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
743                                               get_order(elfcorebuf_sz_orig));
744         if (!elfcorebuf)
745                 return -ENOMEM;
746         addr = elfcorehdr_addr;
747         rc = read_from_oldmem(elfcorebuf, elfcorebuf_sz_orig, &addr, 0);
748         if (rc < 0)
749                 goto fail;
750
751         /* Merge all PT_NOTE headers into one. */
752         rc = merge_note_headers_elf64(elfcorebuf, &elfcorebuf_sz,
753                                       &elfnotes_buf, &elfnotes_sz);
754         if (rc)
755                 goto fail;
756         rc = process_ptload_program_headers_elf64(elfcorebuf, elfcorebuf_sz,
757                                                   elfnotes_sz, &vmcore_list);
758         if (rc)
759                 goto fail;
760         set_vmcore_list_offsets(elfcorebuf_sz, elfnotes_sz, &vmcore_list);
761         return 0;
762 fail:
763         free_elfcorebuf();
764         return rc;
765 }
766
767 static int __init parse_crash_elf32_headers(void)
768 {
769         int rc=0;
770         Elf32_Ehdr ehdr;
771         u64 addr;
772
773         addr = elfcorehdr_addr;
774
775         /* Read Elf header */
776         rc = read_from_oldmem((char*)&ehdr, sizeof(Elf32_Ehdr), &addr, 0);
777         if (rc < 0)
778                 return rc;
779
780         /* Do some basic Verification. */
781         if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0 ||
782                 (ehdr.e_type != ET_CORE) ||
783                 !elf_check_arch(&ehdr) ||
784                 ehdr.e_ident[EI_CLASS] != ELFCLASS32||
785                 ehdr.e_ident[EI_VERSION] != EV_CURRENT ||
786                 ehdr.e_version != EV_CURRENT ||
787                 ehdr.e_ehsize != sizeof(Elf32_Ehdr) ||
788                 ehdr.e_phentsize != sizeof(Elf32_Phdr) ||
789                 ehdr.e_phnum == 0) {
790                 pr_warn("Warning: Core image elf header is not sane\n");
791                 return -EINVAL;
792         }
793
794         /* Read in all elf headers. */
795         elfcorebuf_sz_orig = sizeof(Elf32_Ehdr) + ehdr.e_phnum * sizeof(Elf32_Phdr);
796         elfcorebuf_sz = elfcorebuf_sz_orig;
797         elfcorebuf = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
798                                               get_order(elfcorebuf_sz_orig));
799         if (!elfcorebuf)
800                 return -ENOMEM;
801         addr = elfcorehdr_addr;
802         rc = read_from_oldmem(elfcorebuf, elfcorebuf_sz_orig, &addr, 0);
803         if (rc < 0)
804                 goto fail;
805
806         /* Merge all PT_NOTE headers into one. */
807         rc = merge_note_headers_elf32(elfcorebuf, &elfcorebuf_sz,
808                                       &elfnotes_buf, &elfnotes_sz);
809         if (rc)
810                 goto fail;
811         rc = process_ptload_program_headers_elf32(elfcorebuf, elfcorebuf_sz,
812                                                   elfnotes_sz, &vmcore_list);
813         if (rc)
814                 goto fail;
815         set_vmcore_list_offsets(elfcorebuf_sz, elfnotes_sz, &vmcore_list);
816         return 0;
817 fail:
818         free_elfcorebuf();
819         return rc;
820 }
821
822 static int __init parse_crash_elf_headers(void)
823 {
824         unsigned char e_ident[EI_NIDENT];
825         u64 addr;
826         int rc=0;
827
828         addr = elfcorehdr_addr;
829         rc = read_from_oldmem(e_ident, EI_NIDENT, &addr, 0);
830         if (rc < 0)
831                 return rc;
832         if (memcmp(e_ident, ELFMAG, SELFMAG) != 0) {
833                 pr_warn("Warning: Core image elf header not found\n");
834                 return -EINVAL;
835         }
836
837         if (e_ident[EI_CLASS] == ELFCLASS64) {
838                 rc = parse_crash_elf64_headers();
839                 if (rc)
840                         return rc;
841
842                 /* Determine vmcore size. */
843                 vmcore_size = get_vmcore_size_elf64(elfcorebuf, elfcorebuf_sz);
844         } else if (e_ident[EI_CLASS] == ELFCLASS32) {
845                 rc = parse_crash_elf32_headers();
846                 if (rc)
847                         return rc;
848
849                 /* Determine vmcore size. */
850                 vmcore_size = get_vmcore_size_elf32(elfcorebuf, elfcorebuf_sz);
851         } else {
852                 pr_warn("Warning: Core image elf header is not sane\n");
853                 return -EINVAL;
854         }
855         return 0;
856 }
857
858 /* Init function for vmcore module. */
859 static int __init vmcore_init(void)
860 {
861         int rc = 0;
862
863         /* If elfcorehdr= has been passed in cmdline, then capture the dump.*/
864         if (!(is_vmcore_usable()))
865                 return rc;
866         rc = parse_crash_elf_headers();
867         if (rc) {
868                 pr_warn("Kdump: vmcore not initialized\n");
869                 return rc;
870         }
871
872         proc_vmcore = proc_create("vmcore", S_IRUSR, NULL, &proc_vmcore_operations);
873         if (proc_vmcore)
874                 proc_vmcore->size = vmcore_size;
875         return 0;
876 }
877 module_init(vmcore_init)
878
879 /* Cleanup function for vmcore module. */
880 void vmcore_cleanup(void)
881 {
882         struct list_head *pos, *next;
883
884         if (proc_vmcore) {
885                 proc_remove(proc_vmcore);
886                 proc_vmcore = NULL;
887         }
888
889         /* clear the vmcore list. */
890         list_for_each_safe(pos, next, &vmcore_list) {
891                 struct vmcore *m;
892
893                 m = list_entry(pos, struct vmcore, list);
894                 list_del(&m->list);
895                 kfree(m);
896         }
897         free_elfcorebuf();
898 }
899 EXPORT_SYMBOL_GPL(vmcore_cleanup);