kexec-tools: Introduce crashdump-elf.c and crash_create_elf32/64_headers()

This patch adds the new file crashdump-elf.c that implements a single generic
function which is used to create elf headers. The file gets included twice by
crash.c to create two functions from the same source. These two functions are 
named crash_create_elf32_headers() and crash_create_elf64_headers().

The new code differs from prepare_crash_memory_elf32/64_headers() in the sense
that both allocation and setup now are done in the same function.

This patch only adds the new code, following patches make sure the different
architecture-specific files make use of the new code.

Signed-off-by: Magnus Damm <[EMAIL PROTECTED]>
---

 kexec/crashdump-elf.c |  163 +++++++++++++++++++++++++++++++++++++++++++++++++
 kexec/crashdump.c     |   19 +++++
 kexec/crashdump.h     |   28 ++++++++
 3 files changed, 210 insertions(+)

--- /dev/null
+++ work/kexec/crashdump-elf.c  2006-11-17 15:17:08.000000000 +0900
@@ -0,0 +1,163 @@
+
+#if !defined(FUNCTION) || !defined(EHDR) || !defined(PHDR)
+#error FUNCTION, EHDR and PHDR must be defined
+#endif
+
+/* Prepares the crash memory headers and stores in supplied buffer. */
+int FUNCTION(struct kexec_info *info,
+            struct crash_elf_info *elf_info,
+            struct memory_range *range, int ranges,
+            void **buf, unsigned long *size)
+{
+       EHDR *elf;
+       PHDR *phdr;
+       int i, sz;
+       char *bufp;
+       long int nr_cpus = 0;
+       uint64_t notes_addr, notes_len;
+
+       nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
+       if (nr_cpus < 0) {
+               return -1;
+       }
+
+       sz = sizeof(EHDR) + nr_cpus * sizeof(PHDR) + ranges * sizeof(PHDR);
+
+       if (info->kern_size) {
+               sz += sizeof(PHDR);
+       }
+
+       if (elf_info->alignment) {
+               sz += elf_info->alignment - 1;
+               sz &= ~(elf_info->alignment - 1);
+       }
+
+       bufp = xmalloc(sz);
+       memset(bufp, 0, sz);
+
+       *buf = bufp;
+       *size = sz;
+
+       /* Setup ELF Header*/
+       elf = (EHDR *) bufp;
+       bufp += sizeof(EHDR);
+       memcpy(elf->e_ident, ELFMAG, SELFMAG);
+       elf->e_ident[EI_CLASS]  = elf_info->class;
+       elf->e_ident[EI_DATA]   = elf_info->data;
+       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  = elf_info->machine;
+       elf->e_version  = EV_CURRENT;
+       elf->e_entry    = 0;
+       elf->e_phoff    = sizeof(EHDR);
+       elf->e_shoff    = 0;
+       elf->e_flags    = 0;
+       elf->e_ehsize   = sizeof(EHDR);
+       elf->e_phentsize= sizeof(PHDR);
+       elf->e_phnum    = 0;
+       elf->e_shentsize= 0;
+       elf->e_shnum    = 0;
+       elf->e_shstrndx = 0;
+
+       /* PT_NOTE program headers. One per cpu */
+
+       for (i = 0; i < nr_cpus; i++) {
+               if (elf_info->get_note_info(i, &notes_addr, &notes_len) < 0) {
+                       /* This cpu is not present. Skip it. */
+                       continue;
+               }
+
+               phdr = (PHDR *) bufp;
+               bufp += sizeof(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)++;
+#ifdef DEBUG
+               printf("Elf header: p_type = %d, p_offset = 0x%lx "
+                       "p_paddr = 0x%lx p_vaddr = 0x%lx "
+                       "p_filesz = 0x%lx p_memsz = 0x%lx\n",
+                       phdr->p_type, phdr->p_offset, phdr->p_paddr,
+                       phdr->p_vaddr, phdr->p_filesz, phdr->p_memsz);
+#endif
+       }
+
+       /* Setup an PT_LOAD type program header for the region where
+        * Kernel is mapped if info->kern_size is non-zero.
+        */
+
+       if (info->kern_size) {
+               phdr = (PHDR *) bufp;
+               bufp += sizeof(PHDR);
+               phdr->p_type    = PT_LOAD;
+               phdr->p_flags   = PF_R|PF_W|PF_X;
+               phdr->p_offset  = phdr->p_paddr = info->kern_paddr_start;
+               phdr->p_vaddr   = info->kern_vaddr_start;
+               phdr->p_filesz  = phdr->p_memsz = info->kern_size;
+               phdr->p_align   = 0;
+               (elf->e_phnum)++;
+#ifdef DEBUG
+               printf("Kernel text Elf header: p_type = %d, p_offset = 0x%lx "
+                       "p_paddr = 0x%lx p_vaddr = 0x%lx "
+                       "p_filesz = 0x%lx p_memsz = 0x%lx\n",
+                       phdr->p_type, phdr->p_offset, phdr->p_paddr,
+                       phdr->p_vaddr, phdr->p_filesz, phdr->p_memsz);
+#endif
+       }
+
+       /* Setup PT_LOAD type program header for every system RAM chunk.
+        * A seprate program header for Backup Region*/
+       for (i = 0; i < ranges; i++, range++) {
+               unsigned long long mstart, mend;
+               if (range->type != RANGE_RAM)
+                       continue;
+               mstart = range->start;
+               mend = range->end;
+               if (!mstart && !mend)
+                       continue;
+               phdr = (PHDR *) bufp;
+               bufp += sizeof(PHDR);
+               phdr->p_type    = PT_LOAD;
+               phdr->p_flags   = PF_R|PF_W|PF_X;
+               phdr->p_offset  = mstart;
+
+               if (mstart == elf_info->backup_src_start 
+                   && mend == elf_info->backup_src_end)
+                       phdr->p_offset  = info->backup_start;
+
+               /* We already prepared the header for kernel text. Map
+                * rest of the memory segments to kernel linearly mapped
+                * memory region.
+                */
+               phdr->p_paddr = mstart;
+               phdr->p_vaddr = mstart + elf_info->page_offset;
+               phdr->p_filesz  = phdr->p_memsz = mend - mstart + 1;
+               /* Do we need any alignment of segments? */
+               phdr->p_align   = 0;
+
+               /* HIGMEM has a virtual address of -1 */
+
+               if (elf_info->lowmem_limit 
+                   && (mend > (elf_info->lowmem_limit - 1)))
+                       phdr->p_vaddr = -1;
+
+               /* Increment number of program headers. */
+               (elf->e_phnum)++;
+#ifdef DEBUG
+               printf("Elf header: p_type = %d, p_offset = 0x%lx "
+                       "p_paddr = 0x%lx p_vaddr = 0x%lx "
+                       "p_filesz = 0x%lx p_memsz = 0x%lx\n",
+                       phdr->p_type, phdr->p_offset, phdr->p_paddr,
+                       phdr->p_vaddr, phdr->p_filesz, phdr->p_memsz);
+#endif
+       }
+       return 0;
+}
--- 0002/kexec/crashdump.c
+++ work/kexec/crashdump.c      2006-11-17 15:00:02.000000000 +0900
@@ -25,9 +25,28 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include <elf.h>
 #include "kexec.h"
 #include "crashdump.h"
 
+/* include "crashdump-elf.c" twice to create two functions from one */
+
+#define FUNCTION crash_create_elf64_headers
+#define EHDR Elf64_Ehdr 
+#define PHDR Elf64_Phdr
+#include "crashdump-elf.c"
+#undef PHDR
+#undef EHDR
+#undef FUNCTION
+
+#define FUNCTION crash_create_elf32_headers
+#define EHDR Elf32_Ehdr 
+#define PHDR Elf32_Phdr
+#include "crashdump-elf.c"
+#undef PHDR
+#undef EHDR
+#undef FUNCTION
+
 /* Returns the physical address of start of crash notes buffer for a cpu. */
 int get_crash_notes_per_cpu(int cpu, uint64_t *addr, uint64_t *len)
 {
--- 0002/kexec/crashdump.h
+++ work/kexec/crashdump.h      2006-11-17 15:17:21.000000000 +0900
@@ -8,4 +8,32 @@ extern int get_crash_notes_per_cpu(int c
 /* Expecting ELF headers to fit in 4K. Increase it if you need more. */
 #define KCORE_ELF_HEADERS_SIZE  4096
 
+/* structure passed to crash_create_elf32/64_headers() */
+
+struct crash_elf_info {
+       unsigned long class;
+       unsigned long data;
+       unsigned long machine;
+
+       unsigned long alignment;
+
+       unsigned long backup_src_start;
+       unsigned long backup_src_end;
+
+       unsigned long page_offset;
+       unsigned long lowmem_limit;
+
+       int (*get_note_info)(int cpu, uint64_t *addr, uint64_t *len);
+};
+
+int crash_create_elf32_headers(struct kexec_info *info,
+                              struct crash_elf_info *elf_info,
+                              struct memory_range *range, int ranges,
+                              void **buf, unsigned long *size);
+
+int crash_create_elf64_headers(struct kexec_info *info,
+                              struct crash_elf_info *elf_info,
+                              struct memory_range *range, int ranges,
+                              void **buf, unsigned long *size);
+
 #endif /* CRASHDUMP_H */
_______________________________________________
fastboot mailing list
[email protected]
https://lists.osdl.org/mailman/listinfo/fastboot

Reply via email to