diff options
-rw-r--r-- | kexec/arch/i386/crashdump-x86.c | 237 |
1 files changed, 29 insertions, 208 deletions
diff --git a/kexec/arch/i386/crashdump-x86.c b/kexec/arch/i386/crashdump-x86.c index 6e3e27b..1048c67 100644 --- a/kexec/arch/i386/crashdump-x86.c +++ b/kexec/arch/i386/crashdump-x86.c @@ -462,194 +462,29 @@ static int get_crash_notes(int cpu, uint64_t *addr, uint64_t *len) return get_crash_notes_per_cpu(cpu, addr, len); } -/* Prepares the crash memory elf64 headers and stores in supplied buffer. */ -static int prepare_crash_memory_elf64_headers(struct kexec_info *info, - void *buf, unsigned long size) +static struct crash_elf_info elf_info64 = { - Elf64_Ehdr *elf; - Elf64_Phdr *phdr; - int i; - char *bufp; - long int nr_cpus = 0; - uint64_t notes_addr, notes_len; - - bufp = (char*) buf; - - /* Setup ELF Header*/ - elf = (Elf64_Ehdr *) bufp; - bufp += sizeof(Elf64_Ehdr); - memcpy(elf->e_ident, ELFMAG, SELFMAG); - elf->e_ident[EI_CLASS] = ELFCLASS64; - elf->e_ident[EI_DATA] = ELFDATA2LSB; - elf->e_ident[EI_VERSION]= EV_CURRENT; - elf->e_ident[EI_OSABI] = ELFOSABI_NONE; - memset(elf->e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD); - elf->e_type = ET_CORE; - elf->e_machine = EM_386; - elf->e_version = EV_CURRENT; - elf->e_entry = 0; - elf->e_phoff = sizeof(Elf64_Ehdr); - elf->e_shoff = 0; - elf->e_flags = 0; - elf->e_ehsize = sizeof(Elf64_Ehdr); - elf->e_phentsize= sizeof(Elf64_Phdr); - elf->e_phnum = 0; - elf->e_shentsize= 0; - elf->e_shnum = 0; - elf->e_shstrndx = 0; - - /* PT_NOTE program headers. One per cpu*/ - nr_cpus = sysconf(_SC_NPROCESSORS_CONF); - if (nr_cpus < 0) { - return -1; - } - - for (i = 0; i < nr_cpus; i++) { - if (get_crash_notes(i, ¬es_addr, ¬es_len) < 0) { - /* This cpu is not present. Skip it. */ - continue; - } - phdr = (Elf64_Phdr *) bufp; - bufp += sizeof(Elf64_Phdr); - phdr->p_type = PT_NOTE; - phdr->p_flags = 0; - phdr->p_offset = phdr->p_paddr = notes_addr; - phdr->p_vaddr = 0; - phdr->p_filesz = phdr->p_memsz = notes_len; - /* Do we need any alignment of segments? */ - phdr->p_align = 0; - - /* Increment number of program headers. */ - (elf->e_phnum)++; - } - - /* Setup PT_LOAD type program header for every system RAM chunk. - * A seprate program header for Backup Region*/ - for (i = 0; i < CRASH_MAX_MEMORY_RANGES; i++) { - unsigned long long mstart, mend; - if (crash_memory_range[i].type != RANGE_RAM) - continue; - mstart = crash_memory_range[i].start; - mend = crash_memory_range[i].end; - if (!mstart && !mend) - continue; - phdr = (Elf64_Phdr *) bufp; - bufp += sizeof(Elf64_Phdr); - phdr->p_type = PT_LOAD; - phdr->p_flags = PF_R|PF_W|PF_X; - if (mstart == BACKUP_SRC_START && mend == BACKUP_SRC_END) - phdr->p_offset = info->backup_start; - else - phdr->p_offset = mstart; - /* Handle linearly mapped region.*/ - if (mend <= (MAXMEM - 1)) - phdr->p_vaddr = mstart + PAGE_OFFSET; - else - phdr->p_vaddr = -1ULL; - phdr->p_paddr = mstart; - phdr->p_filesz = phdr->p_memsz = mend - mstart + 1; - /* Do we need any alignment of segments? */ - phdr->p_align = 0; - - /* Increment number of program headers. */ - (elf->e_phnum)++; - } - return 0; -} - -/* Prepares the crash memory elf32 headers and stores in supplied buffer. */ -static int prepare_crash_memory_elf32_headers(struct kexec_info *info, - void *buf, unsigned long size) + class: ELFCLASS64, + data: ELFDATA2LSB, + machine: EM_386, + backup_src_start: BACKUP_SRC_START, + backup_src_end: BACKUP_SRC_END, + page_offset: PAGE_OFFSET, + lowmem_limit: MAXMEM, + get_note_info: get_crash_notes, +}; + +static struct crash_elf_info elf_info32 = { - Elf32_Ehdr *elf; - Elf32_Phdr *phdr; - int i; - char *bufp; - long int nr_cpus = 0; - uint64_t notes_addr, notes_len; - - bufp = (char*) buf; - - /* Setup ELF Header*/ - elf = (Elf32_Ehdr *) bufp; - bufp += sizeof(Elf32_Ehdr); - memcpy(elf->e_ident, ELFMAG, SELFMAG); - elf->e_ident[EI_CLASS] = ELFCLASS32; - elf->e_ident[EI_DATA] = ELFDATA2LSB; - elf->e_ident[EI_VERSION]= EV_CURRENT; - elf->e_ident[EI_OSABI] = ELFOSABI_NONE; - memset(elf->e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD); - elf->e_type = ET_CORE; - elf->e_machine = EM_386; - elf->e_version = EV_CURRENT; - elf->e_entry = 0; - elf->e_phoff = sizeof(Elf32_Ehdr); - elf->e_shoff = 0; - elf->e_flags = 0; - elf->e_ehsize = sizeof(Elf32_Ehdr); - elf->e_phentsize= sizeof(Elf32_Phdr); - elf->e_phnum = 0; - elf->e_shentsize= 0; - elf->e_shnum = 0; - elf->e_shstrndx = 0; - - /* PT_NOTE program headers. One per cpu*/ - nr_cpus = sysconf(_SC_NPROCESSORS_CONF); - if (nr_cpus < 0) { - return -1; - } - - for (i = 0; i < nr_cpus; i++) { - if (get_crash_notes(i, ¬es_addr, ¬es_len) < 0) { - /* This cpu is not present. Skip it. */ - continue; - } - phdr = (Elf32_Phdr *) bufp; - bufp += sizeof(Elf32_Phdr); - phdr->p_type = PT_NOTE; - phdr->p_flags = 0; - phdr->p_offset = phdr->p_paddr = notes_addr; - phdr->p_vaddr = 0; - phdr->p_filesz = phdr->p_memsz = notes_len; - /* Do we need any alignment of segments? */ - phdr->p_align = 0; - - /* Increment number of program headers. */ - (elf->e_phnum)++; - } - - /* Setup PT_LOAD type program header for every system RAM chunk. - * A seprate program header for Backup Region*/ - for (i = 0; i < CRASH_MAX_MEMORY_RANGES; i++) { - unsigned long long mstart, mend; - if (crash_memory_range[i].type != RANGE_RAM) - continue; - mstart = crash_memory_range[i].start; - mend = crash_memory_range[i].end; - if (!mstart && !mend) - continue; - phdr = (Elf32_Phdr *) bufp; - bufp += sizeof(Elf32_Phdr); - phdr->p_type = PT_LOAD; - phdr->p_flags = PF_R|PF_W|PF_X; - if (mstart == BACKUP_SRC_START && mend == BACKUP_SRC_END) - phdr->p_offset = info->backup_start; - else - phdr->p_offset = mstart; - /* Handle linearly mapped region.*/ - if (mend <= (MAXMEM - 1)) - phdr->p_vaddr = mstart + PAGE_OFFSET; - else - phdr->p_vaddr = UINT_MAX; - phdr->p_paddr = mstart; - phdr->p_filesz = phdr->p_memsz = mend - mstart + 1; - /* Do we need any alignment of segments? */ - phdr->p_align = 0; - /* Increment number of program headers. */ - (elf->e_phnum)++; - } - return 0; -} + class: ELFCLASS32, + data: ELFDATA2LSB, + machine: EM_386, + backup_src_start: BACKUP_SRC_START, + backup_src_end: BACKUP_SRC_END, + page_offset: PAGE_OFFSET, + lowmem_limit: MAXMEM, + get_note_info: get_crash_notes, +}; /* Loads additional segments in case of a panic kernel is being loaded. * One segment for backup region, another segment for storing elf headers @@ -661,7 +496,6 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline, void *tmp; unsigned long sz, elfcorehdr; int nr_ranges, align = 1024; - long int nr_cpus = 0; struct memory_range *mem_range, *memmap_p; if (get_crash_memory_ranges(&mem_range, &nr_ranges) < 0) @@ -687,29 +521,16 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline, return -1; /* Create elf header segment and store crash image data. */ - nr_cpus = sysconf(_SC_NPROCESSORS_CONF); - if (nr_cpus < 0) { - fprintf(stderr,"kexec_load (elf header segment)" - " failed: %s\n", strerror(errno)); - return -1; - } if (arch_options.core_header_type == CORE_TYPE_ELF64) { - sz = sizeof(Elf64_Ehdr) + - nr_cpus * sizeof(Elf64_Phdr) + - nr_ranges * sizeof(Elf64_Phdr); - } else { - sz = sizeof(Elf32_Ehdr) + - nr_cpus * sizeof(Elf32_Phdr) + - nr_ranges * sizeof(Elf32_Phdr); - } - sz = (sz + align - 1) & ~(align -1); - tmp = xmalloc(sz); - memset(tmp, 0, sz); - if (arch_options.core_header_type == CORE_TYPE_ELF64) { - if (prepare_crash_memory_elf64_headers(info, tmp, sz) < 0) + if (crash_create_elf64_headers(info, &elf_info64, + crash_memory_range, nr_ranges, + &tmp, &sz) < 0) return -1; - } else { - if (prepare_crash_memory_elf32_headers(info, tmp, sz) < 0) + } + else { + if (crash_create_elf32_headers(info, &elf_info32, + crash_memory_range, nr_ranges, + &tmp, &sz) < 0) return -1; } |