diff options
-rw-r--r-- | kexec/arch/ppc64/crashdump-ppc64.c | 95 | ||||
-rw-r--r-- | kexec/arch/ppc64/include/arch/options.h | 2 | ||||
-rw-r--r-- | kexec/arch/ppc64/kexec-ppc64.c | 10 | ||||
-rw-r--r-- | kexec/arch/ppc64/kexec-ppc64.h | 6 |
4 files changed, 110 insertions, 3 deletions
diff --git a/kexec/arch/ppc64/crashdump-ppc64.c b/kexec/arch/ppc64/crashdump-ppc64.c index e949198..a213166 100644 --- a/kexec/arch/ppc64/crashdump-ppc64.c +++ b/kexec/arch/ppc64/crashdump-ppc64.c @@ -257,6 +257,101 @@ static int add_cmdline_param(char *cmdline, unsigned long addr, return 0; } +/* 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) +{ + Elf64_Ehdr *elf; + Elf64_Phdr *phdr; + int i; + char *bufp; + long int nr_cpus = 0; + unsigned long notes_addr; + + 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] = ELFDATA2MSB; + 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_PPC64; + 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; + + /* Need to find a better way to determine per cpu notes section size. */ +#define MAX_NOTE_BYTES 1024 + for (i = 0; i < nr_cpus; i++) { + if (get_crash_notes_per_cpu(i, ¬es_addr) < 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 = MAX_NOTE_BYTES; + /* 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; + mstart = crash_memory_range[i].start; + mend = crash_memory_range[i].end; + if (!mstart && !mend) + break; + 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_START && mend == BACKUP_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; + /* Do we need any alignment of segments? */ + phdr->p_align = 0; + + /* Increment number of program headers. */ + (elf->e_phnum)++; + } + return 0; +} + /* Loads additional segments in case of a panic kernel is being loaded. * One segment for backup region, another segment for storing elf headers * for crash memory image. diff --git a/kexec/arch/ppc64/include/arch/options.h b/kexec/arch/ppc64/include/arch/options.h index 3fb04a7..973cd4f 100644 --- a/kexec/arch/ppc64/include/arch/options.h +++ b/kexec/arch/ppc64/include/arch/options.h @@ -2,9 +2,11 @@ #define KEXEC_ARCH_PPC64_OPTIONS_H #define OPT_ARCH_MAX (OPT_MAX+0) +#define OPT_ELF64_CORE (OPT_MAX+1) #define KEXEC_ARCH_OPTIONS \ KEXEC_OPTIONS \ + { "elf64-core-headers", 0, 0, OPT_ELF64_CORE }, \ #define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR "" diff --git a/kexec/arch/ppc64/kexec-ppc64.c b/kexec/arch/ppc64/kexec-ppc64.c index c880b7a..e7a93f4 100644 --- a/kexec/arch/ppc64/kexec-ppc64.c +++ b/kexec/arch/ppc64/kexec-ppc64.c @@ -578,17 +578,18 @@ int file_types = sizeof(file_type) / sizeof(file_type[0]); void arch_usage(void) { fprintf(stderr, " --devicetreeblob=<filename> Specify device tree blob file.\n"); + fprintf(stderr, " --elf64-core-headers Prepare core headers in ELF64 format\n"); } -static struct { -} arch_options = { +struct arch_options_t arch_options = { + .core_header_type = CORE_TYPE_ELF64, }; int arch_process_options(int argc, char **argv) { static const struct option options[] = { KEXEC_ARCH_OPTIONS - { 0, 0, NULL, 0 }, + { 0, 0, NULL, 0 }, }; static const char short_options[] = KEXEC_ARCH_OPT_STR; int opt; @@ -598,6 +599,9 @@ int arch_process_options(int argc, char **argv) switch(opt) { default: break; + case OPT_ELF64_CORE: + arch_options.core_header_type = CORE_TYPE_ELF64; + break; } } /* Reset getopt for the next pass; called in other source modules */ diff --git a/kexec/arch/ppc64/kexec-ppc64.h b/kexec/arch/ppc64/kexec-ppc64.h index df13488..07a2210 100644 --- a/kexec/arch/ppc64/kexec-ppc64.h +++ b/kexec/arch/ppc64/kexec-ppc64.h @@ -4,6 +4,8 @@ #define MAX_MEMORY_RANGES 256 /* TO FIX - needs to be dynamically set */ #define MAXBYTES 128 #define MAX_LINE 160 +#define CORE_TYPE_ELF32 1 +#define CORE_TYPE_ELF64 2 int setup_memory_ranges(unsigned long kexec_flags); @@ -26,6 +28,10 @@ struct bootblock { boot_physid; }; +struct arch_options_t { + int core_header_type; +}; + struct exclude_range { unsigned long long start, end; }; |