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
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>
27 /* List representing chunks of contiguous memory areas and their offsets in
30 static LIST_HEAD(vmcore_list);
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;
37 static char *elfnotes_buf;
38 static size_t elfnotes_sz;
40 /* Total size of vmcore file. */
41 static u64 vmcore_size;
43 static struct proc_dir_entry *proc_vmcore = NULL;
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.
49 static int (*oldmem_pfn_is_ram)(unsigned long pfn);
51 int register_oldmem_pfn_is_ram(int (*fn)(unsigned long pfn))
53 if (oldmem_pfn_is_ram)
55 oldmem_pfn_is_ram = fn;
58 EXPORT_SYMBOL_GPL(register_oldmem_pfn_is_ram);
60 void unregister_oldmem_pfn_is_ram(void)
62 oldmem_pfn_is_ram = NULL;
65 EXPORT_SYMBOL_GPL(unregister_oldmem_pfn_is_ram);
67 static int pfn_is_ram(unsigned long pfn)
69 int (*fn)(unsigned long pfn);
70 /* pfn is ram unless fn() checks pagetype */
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.
78 fn = oldmem_pfn_is_ram;
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)
89 unsigned long pfn, offset;
91 ssize_t read = 0, tmp;
96 offset = (unsigned long)(*ppos % PAGE_SIZE);
97 pfn = (unsigned long)(*ppos / PAGE_SIZE);
100 if (count > (PAGE_SIZE - offset))
101 nr_bytes = PAGE_SIZE - offset;
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);
109 tmp = copy_oldmem_page(pfn, buf, nr_bytes,
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.
128 static ssize_t read_vmcore(struct file *file, char __user *buffer,
129 size_t buflen, loff_t *fpos)
131 ssize_t acc = 0, tmp;
134 struct vmcore *m = NULL;
136 if (buflen == 0 || *fpos >= vmcore_size)
139 /* trim buflen to not go beyond EOF */
140 if (buflen > vmcore_size - *fpos)
141 buflen = vmcore_size - *fpos;
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))
153 /* leave now if filled buffer already */
158 /* Read Elf note segment */
159 if (*fpos < elfcorebuf_sz + elfnotes_sz) {
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))
171 /* leave now if filled buffer already */
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);
188 /* leave now if filled buffer already */
197 static const struct file_operations proc_vmcore_operations = {
199 .llseek = default_llseek,
202 static struct vmcore* __init get_new_element(void)
204 return kzalloc(sizeof(struct vmcore), GFP_KERNEL);
207 static u64 __init get_vmcore_size_elf64(char *elfptr, size_t elfsz)
211 Elf64_Ehdr *ehdr_ptr;
212 Elf64_Phdr *phdr_ptr;
214 ehdr_ptr = (Elf64_Ehdr *)elfptr;
215 phdr_ptr = (Elf64_Phdr*)(elfptr + sizeof(Elf64_Ehdr));
217 for (i = 0; i < ehdr_ptr->e_phnum; i++) {
218 size += phdr_ptr->p_memsz;
224 static u64 __init get_vmcore_size_elf32(char *elfptr, size_t elfsz)
228 Elf32_Ehdr *ehdr_ptr;
229 Elf32_Phdr *phdr_ptr;
231 ehdr_ptr = (Elf32_Ehdr *)elfptr;
232 phdr_ptr = (Elf32_Phdr*)(elfptr + sizeof(Elf32_Ehdr));
234 for (i = 0; i < ehdr_ptr->e_phnum; i++) {
235 size += phdr_ptr->p_memsz;
242 * update_note_header_size_elf64 - update p_memsz member of each PT_NOTE entry
244 * @ehdr_ptr: ELF header
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
250 static int __init update_note_header_size_elf64(const Elf64_Ehdr *ehdr_ptr)
253 Elf64_Phdr *phdr_ptr;
254 Elf64_Nhdr *nhdr_ptr;
256 phdr_ptr = (Elf64_Phdr *)(ehdr_ptr + 1);
257 for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
259 u64 offset, max_sz, sz, real_sz = 0;
260 if (phdr_ptr->p_type != PT_NOTE)
262 max_sz = phdr_ptr->p_memsz;
263 offset = phdr_ptr->p_offset;
264 notes_section = kmalloc(max_sz, GFP_KERNEL);
267 rc = read_from_oldmem(notes_section, max_sz, &offset, 0);
269 kfree(notes_section);
272 nhdr_ptr = notes_section;
273 while (real_sz < max_sz) {
274 if (nhdr_ptr->n_namesz == 0)
276 sz = sizeof(Elf64_Nhdr) +
277 ((nhdr_ptr->n_namesz + 3) & ~3) +
278 ((nhdr_ptr->n_descsz + 3) & ~3);
280 nhdr_ptr = (Elf64_Nhdr*)((char*)nhdr_ptr + sz);
282 kfree(notes_section);
283 phdr_ptr->p_memsz = real_sz;
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
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
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.
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.
307 static int __init get_note_number_and_size_elf64(const Elf64_Ehdr *ehdr_ptr,
308 int *nr_ptnote, u64 *sz_ptnote)
311 Elf64_Phdr *phdr_ptr;
313 *nr_ptnote = *sz_ptnote = 0;
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)
320 *sz_ptnote += phdr_ptr->p_memsz;
327 * copy_notes_elf64 - copy ELF note segments in a given buffer
329 * @ehdr_ptr: ELF header
330 * @notes_buf: buffer into which ELF note segments are copied
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.
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.
342 static int __init copy_notes_elf64(const Elf64_Ehdr *ehdr_ptr, char *notes_buf)
345 Elf64_Phdr *phdr_ptr;
347 phdr_ptr = (Elf64_Phdr*)(ehdr_ptr + 1);
349 for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
351 if (phdr_ptr->p_type != PT_NOTE)
353 offset = phdr_ptr->p_offset;
354 rc = read_from_oldmem(notes_buf, phdr_ptr->p_memsz, &offset, 0);
357 notes_buf += phdr_ptr->p_memsz;
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)
367 int i, nr_ptnote=0, rc=0;
369 Elf64_Ehdr *ehdr_ptr;
371 u64 phdr_sz = 0, note_off;
373 ehdr_ptr = (Elf64_Ehdr *)elfptr;
375 rc = update_note_header_size_elf64(ehdr_ptr);
379 rc = get_note_number_and_size_elf64(ehdr_ptr, &nr_ptnote, &phdr_sz);
383 *notes_sz = roundup(phdr_sz, PAGE_SIZE);
384 *notes_buf = vzalloc(*notes_sz);
388 rc = copy_notes_elf64(ehdr_ptr, *notes_buf);
392 /* Prepare merged PT_NOTE program header. */
393 phdr.p_type = PT_NOTE;
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;
402 /* Add merged PT_NOTE program header*/
403 tmp = elfptr + sizeof(Elf64_Ehdr);
404 memcpy(tmp, &phdr, sizeof(phdr));
407 /* Remove unwanted PT_NOTE program headers. */
408 i = (nr_ptnote - 1) * sizeof(Elf64_Phdr);
410 memmove(tmp, tmp+i, ((*elfsz)-sizeof(Elf64_Ehdr)-sizeof(Elf64_Phdr)));
411 memset(elfptr + *elfsz, 0, i);
412 *elfsz = roundup(*elfsz, PAGE_SIZE);
414 /* Modify e_phnum to reflect merged headers. */
415 ehdr_ptr->e_phnum = ehdr_ptr->e_phnum - nr_ptnote + 1;
421 * update_note_header_size_elf32 - update p_memsz member of each PT_NOTE entry
423 * @ehdr_ptr: ELF header
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
429 static int __init update_note_header_size_elf32(const Elf32_Ehdr *ehdr_ptr)
432 Elf32_Phdr *phdr_ptr;
433 Elf32_Nhdr *nhdr_ptr;
435 phdr_ptr = (Elf32_Phdr *)(ehdr_ptr + 1);
436 for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
438 u64 offset, max_sz, sz, real_sz = 0;
439 if (phdr_ptr->p_type != PT_NOTE)
441 max_sz = phdr_ptr->p_memsz;
442 offset = phdr_ptr->p_offset;
443 notes_section = kmalloc(max_sz, GFP_KERNEL);
446 rc = read_from_oldmem(notes_section, max_sz, &offset, 0);
448 kfree(notes_section);
451 nhdr_ptr = notes_section;
452 while (real_sz < max_sz) {
453 if (nhdr_ptr->n_namesz == 0)
455 sz = sizeof(Elf32_Nhdr) +
456 ((nhdr_ptr->n_namesz + 3) & ~3) +
457 ((nhdr_ptr->n_descsz + 3) & ~3);
459 nhdr_ptr = (Elf32_Nhdr*)((char*)nhdr_ptr + sz);
461 kfree(notes_section);
462 phdr_ptr->p_memsz = real_sz;
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
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
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.
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.
486 static int __init get_note_number_and_size_elf32(const Elf32_Ehdr *ehdr_ptr,
487 int *nr_ptnote, u64 *sz_ptnote)
490 Elf32_Phdr *phdr_ptr;
492 *nr_ptnote = *sz_ptnote = 0;
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)
499 *sz_ptnote += phdr_ptr->p_memsz;
506 * copy_notes_elf32 - copy ELF note segments in a given buffer
508 * @ehdr_ptr: ELF header
509 * @notes_buf: buffer into which ELF note segments are copied
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.
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.
521 static int __init copy_notes_elf32(const Elf32_Ehdr *ehdr_ptr, char *notes_buf)
524 Elf32_Phdr *phdr_ptr;
526 phdr_ptr = (Elf32_Phdr*)(ehdr_ptr + 1);
528 for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
530 if (phdr_ptr->p_type != PT_NOTE)
532 offset = phdr_ptr->p_offset;
533 rc = read_from_oldmem(notes_buf, phdr_ptr->p_memsz, &offset, 0);
536 notes_buf += phdr_ptr->p_memsz;
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)
546 int i, nr_ptnote=0, rc=0;
548 Elf32_Ehdr *ehdr_ptr;
550 u64 phdr_sz = 0, note_off;
552 ehdr_ptr = (Elf32_Ehdr *)elfptr;
554 rc = update_note_header_size_elf32(ehdr_ptr);
558 rc = get_note_number_and_size_elf32(ehdr_ptr, &nr_ptnote, &phdr_sz);
562 *notes_sz = roundup(phdr_sz, PAGE_SIZE);
563 *notes_buf = vzalloc(*notes_sz);
567 rc = copy_notes_elf32(ehdr_ptr, *notes_buf);
571 /* Prepare merged PT_NOTE program header. */
572 phdr.p_type = PT_NOTE;
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;
581 /* Add merged PT_NOTE program header*/
582 tmp = elfptr + sizeof(Elf32_Ehdr);
583 memcpy(tmp, &phdr, sizeof(phdr));
586 /* Remove unwanted PT_NOTE program headers. */
587 i = (nr_ptnote - 1) * sizeof(Elf32_Phdr);
589 memmove(tmp, tmp+i, ((*elfsz)-sizeof(Elf32_Ehdr)-sizeof(Elf32_Phdr)));
590 memset(elfptr + *elfsz, 0, i);
591 *elfsz = roundup(*elfsz, PAGE_SIZE);
593 /* Modify e_phnum to reflect merged headers. */
594 ehdr_ptr->e_phnum = ehdr_ptr->e_phnum - nr_ptnote + 1;
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,
604 struct list_head *vc_list)
607 Elf64_Ehdr *ehdr_ptr;
608 Elf64_Phdr *phdr_ptr;
612 ehdr_ptr = (Elf64_Ehdr *)elfptr;
613 phdr_ptr = (Elf64_Phdr*)(elfptr + sizeof(Elf64_Ehdr)); /* PT_NOTE hdr */
615 /* Skip Elf header, program headers and Elf note segment. */
616 vmcore_off = elfsz + elfnotes_sz;
618 for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
619 u64 paddr, start, end, size;
621 if (phdr_ptr->p_type != PT_LOAD)
624 paddr = phdr_ptr->p_offset;
625 start = rounddown(paddr, PAGE_SIZE);
626 end = roundup(paddr + phdr_ptr->p_memsz, PAGE_SIZE);
629 /* Add this contiguous chunk of memory to vmcore list.*/
630 new = get_new_element();
635 list_add_tail(&new->list, vc_list);
637 /* Update the program header offset. */
638 phdr_ptr->p_offset = vmcore_off + (paddr - start);
639 vmcore_off = vmcore_off + size;
644 static int __init process_ptload_program_headers_elf32(char *elfptr,
647 struct list_head *vc_list)
650 Elf32_Ehdr *ehdr_ptr;
651 Elf32_Phdr *phdr_ptr;
655 ehdr_ptr = (Elf32_Ehdr *)elfptr;
656 phdr_ptr = (Elf32_Phdr*)(elfptr + sizeof(Elf32_Ehdr)); /* PT_NOTE hdr */
658 /* Skip Elf header, program headers and Elf note segment. */
659 vmcore_off = elfsz + elfnotes_sz;
661 for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
662 u64 paddr, start, end, size;
664 if (phdr_ptr->p_type != PT_LOAD)
667 paddr = phdr_ptr->p_offset;
668 start = rounddown(paddr, PAGE_SIZE);
669 end = roundup(paddr + phdr_ptr->p_memsz, PAGE_SIZE);
672 /* Add this contiguous chunk of memory to vmcore list.*/
673 new = get_new_element();
678 list_add_tail(&new->list, vc_list);
680 /* Update the program header offset */
681 phdr_ptr->p_offset = vmcore_off + (paddr - start);
682 vmcore_off = vmcore_off + size;
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)
694 /* Skip Elf header, program headers and Elf note segment. */
695 vmcore_off = elfsz + elfnotes_sz;
697 list_for_each_entry(m, vc_list, list) {
698 m->offset = vmcore_off;
699 vmcore_off += m->size;
703 static void free_elfcorebuf(void)
705 free_pages((unsigned long)elfcorebuf, get_order(elfcorebuf_sz_orig));
711 static int __init parse_crash_elf64_headers(void)
717 addr = elfcorehdr_addr;
719 /* Read Elf header */
720 rc = read_from_oldmem((char*)&ehdr, sizeof(Elf64_Ehdr), &addr, 0);
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) ||
734 pr_warn("Warning: Core image elf header is not sane\n");
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));
746 addr = elfcorehdr_addr;
747 rc = read_from_oldmem(elfcorebuf, elfcorebuf_sz_orig, &addr, 0);
751 /* Merge all PT_NOTE headers into one. */
752 rc = merge_note_headers_elf64(elfcorebuf, &elfcorebuf_sz,
753 &elfnotes_buf, &elfnotes_sz);
756 rc = process_ptload_program_headers_elf64(elfcorebuf, elfcorebuf_sz,
757 elfnotes_sz, &vmcore_list);
760 set_vmcore_list_offsets(elfcorebuf_sz, elfnotes_sz, &vmcore_list);
767 static int __init parse_crash_elf32_headers(void)
773 addr = elfcorehdr_addr;
775 /* Read Elf header */
776 rc = read_from_oldmem((char*)&ehdr, sizeof(Elf32_Ehdr), &addr, 0);
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) ||
790 pr_warn("Warning: Core image elf header is not sane\n");
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));
801 addr = elfcorehdr_addr;
802 rc = read_from_oldmem(elfcorebuf, elfcorebuf_sz_orig, &addr, 0);
806 /* Merge all PT_NOTE headers into one. */
807 rc = merge_note_headers_elf32(elfcorebuf, &elfcorebuf_sz,
808 &elfnotes_buf, &elfnotes_sz);
811 rc = process_ptload_program_headers_elf32(elfcorebuf, elfcorebuf_sz,
812 elfnotes_sz, &vmcore_list);
815 set_vmcore_list_offsets(elfcorebuf_sz, elfnotes_sz, &vmcore_list);
822 static int __init parse_crash_elf_headers(void)
824 unsigned char e_ident[EI_NIDENT];
828 addr = elfcorehdr_addr;
829 rc = read_from_oldmem(e_ident, EI_NIDENT, &addr, 0);
832 if (memcmp(e_ident, ELFMAG, SELFMAG) != 0) {
833 pr_warn("Warning: Core image elf header not found\n");
837 if (e_ident[EI_CLASS] == ELFCLASS64) {
838 rc = parse_crash_elf64_headers();
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();
849 /* Determine vmcore size. */
850 vmcore_size = get_vmcore_size_elf32(elfcorebuf, elfcorebuf_sz);
852 pr_warn("Warning: Core image elf header is not sane\n");
858 /* Init function for vmcore module. */
859 static int __init vmcore_init(void)
863 /* If elfcorehdr= has been passed in cmdline, then capture the dump.*/
864 if (!(is_vmcore_usable()))
866 rc = parse_crash_elf_headers();
868 pr_warn("Kdump: vmcore not initialized\n");
872 proc_vmcore = proc_create("vmcore", S_IRUSR, NULL, &proc_vmcore_operations);
874 proc_vmcore->size = vmcore_size;
877 module_init(vmcore_init)
879 /* Cleanup function for vmcore module. */
880 void vmcore_cleanup(void)
882 struct list_head *pos, *next;
885 proc_remove(proc_vmcore);
889 /* clear the vmcore list. */
890 list_for_each_safe(pos, next, &vmcore_list) {
893 m = list_entry(pos, struct vmcore, list);
899 EXPORT_SYMBOL_GPL(vmcore_cleanup);