| /* |
| * kexec/arch/s390/crashdump-s390.c |
| * |
| * Copyright IBM Corp. 2011 |
| * |
| * Author(s): Michael Holzheu <holzheu@linux.vnet.ibm.com> |
| */ |
| |
| #ifdef __s390x__ |
| #define _GNU_SOURCE |
| |
| #include <stdio.h> |
| #include <elf.h> |
| #include <limits.h> |
| #include <string.h> |
| #include "../../kexec.h" |
| #include "../../kexec-syscall.h" |
| #include "../../kexec/crashdump.h" |
| #include "kexec-s390.h" |
| |
| /* |
| * Create ELF core header |
| */ |
| static int create_elf_header(struct kexec_info *info, unsigned long crash_base, |
| unsigned long crash_end) |
| { |
| #ifdef WITH_ELF_HEADER |
| static struct memory_range crash_memory_range[MAX_MEMORY_RANGES]; |
| unsigned long elfcorehdr, elfcorehdr_size, bufsz; |
| struct crash_elf_info elf_info; |
| char str[COMMAND_LINESIZE]; |
| int ranges; |
| void *tmp; |
| |
| memset(&elf_info, 0, sizeof(elf_info)); |
| |
| elf_info.data = ELFDATA2MSB; |
| elf_info.machine = EM_S390; |
| elf_info.class = ELFCLASS64; |
| elf_info.get_note_info = get_crash_notes_per_cpu; |
| |
| if (get_memory_ranges_s390(crash_memory_range, &ranges, 0)) |
| return -1; |
| |
| if (crash_create_elf64_headers(info, &elf_info, crash_memory_range, |
| ranges, &tmp, &bufsz, |
| ELF_CORE_HEADER_ALIGN)) |
| return -1; |
| |
| elfcorehdr = add_buffer(info, tmp, bufsz, bufsz, 1024, |
| crash_base, crash_end, -1); |
| elfcorehdr_size = bufsz; |
| snprintf(str, sizeof(str), " elfcorehdr=%ld@%ldK\n", |
| elfcorehdr_size, elfcorehdr / 1024); |
| command_line_add(str); |
| #endif |
| return 0; |
| } |
| |
| /* |
| * Load additional segments for kdump kernel |
| */ |
| int load_crashdump_segments(struct kexec_info *info, unsigned long crash_base, |
| unsigned long crash_end) |
| { |
| unsigned long crash_size = crash_size = crash_end - crash_base + 1; |
| |
| if (create_elf_header(info, crash_base, crash_end)) |
| return -1; |
| elf_rel_build_load(info, &info->rhdr, (const char *) purgatory, |
| purgatory_size, crash_base + 0x2000, |
| crash_base + 0x10000, -1, 0); |
| elf_rel_set_symbol(&info->rhdr, "crash_base", &crash_base, |
| sizeof(crash_base)); |
| elf_rel_set_symbol(&info->rhdr, "crash_size", &crash_size, |
| sizeof(crash_size)); |
| info->entry = (void *) elf_rel_get_addr(&info->rhdr, "purgatory_start"); |
| return 0; |
| } |
| #else |
| /* |
| * kdump is not available for s390 |
| */ |
| int load_crashdump_segments(struct kexec_info *info, unsigned long crash_base, |
| unsigned long crash_end) |
| { |
| return -1; |
| } |
| #endif |