summaryrefslogtreecommitdiff
path: root/kexec/arch/s390/kexec-elf-rel-s390.c
diff options
context:
space:
mode:
authorMichael Holzheu <holzheu@linux.vnet.ibm.com>2011-08-19 15:09:50 +0200
committerSimon Horman <horms@verge.net.au>2011-08-20 18:02:29 +0900
commitd866fa444cc47097c07b3d31c494fdacd977f6d8 (patch)
tree6c902b0b94b1f8fa02459e52c3af269c6a4066cd /kexec/arch/s390/kexec-elf-rel-s390.c
parent7c7caf11813cf9993201285886ba9661b3de2d18 (diff)
kexec-tools: Add s390 kdump support
This patch adds kdump support for s390 to the kexec tool and enables the "--load-panic" option. When loading the kdump kernel and ramdisk we add the address of the crashkernel memory to the normal load address. Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com> Signed-off-by: Simon Horman <horms@verge.net.au>
Diffstat (limited to 'kexec/arch/s390/kexec-elf-rel-s390.c')
-rw-r--r--kexec/arch/s390/kexec-elf-rel-s390.c66
1 files changed, 58 insertions, 8 deletions
diff --git a/kexec/arch/s390/kexec-elf-rel-s390.c b/kexec/arch/s390/kexec-elf-rel-s390.c
index ffa0347..80bcd1b 100644
--- a/kexec/arch/s390/kexec-elf-rel-s390.c
+++ b/kexec/arch/s390/kexec-elf-rel-s390.c
@@ -1,7 +1,7 @@
/*
* kexec/arch/s390/kexec-elf-rel-s390.c
*
- * (C) Copyright IBM Corp. 2005
+ * Copyright IBM Corp. 2005,2011
*
* Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
*
@@ -12,15 +12,65 @@
#include "../../kexec.h"
#include "../../kexec-elf.h"
-int machine_verify_elf_rel(struct mem_ehdr *UNUSED(ehdr))
+int machine_verify_elf_rel(struct mem_ehdr *ehdr)
{
- return 0;
+ if (ehdr->ei_data != ELFDATA2MSB)
+ return 0;
+ if (ehdr->ei_class != ELFCLASS64)
+ return 0;
+ if (ehdr->e_machine != EM_S390)
+ return 0;
+ return 1;
}
-void machine_apply_elf_rel(struct mem_ehdr *UNUSED(ehdr),
- unsigned long UNUSED(r_type),
- void *UNUSED(location),
- unsigned long UNUSED(address),
- unsigned long UNUSED(value))
+void machine_apply_elf_rel(struct mem_ehdr *ehdr,
+ unsigned long r_type,
+ void *loc,
+ unsigned long address,
+ unsigned long val)
{
+ switch (r_type) {
+ case R_390_8: /* Direct 8 bit. */
+ case R_390_12: /* Direct 12 bit. */
+ case R_390_16: /* Direct 16 bit. */
+ case R_390_20: /* Direct 20 bit. */
+ case R_390_32: /* Direct 32 bit. */
+ case R_390_64: /* Direct 64 bit. */
+ if (r_type == R_390_8)
+ *(unsigned char *) loc = val;
+ else if (r_type == R_390_12)
+ *(unsigned short *) loc = (val & 0xfff) |
+ (*(unsigned short *) loc & 0xf000);
+ else if (r_type == R_390_16)
+ *(unsigned short *) loc = val;
+ else if (r_type == R_390_20)
+ *(unsigned int *) loc =
+ (*(unsigned int *) loc & 0xf00000ff) |
+ (val & 0xfff) << 16 | (val & 0xff000) >> 4;
+ else if (r_type == R_390_32)
+ *(unsigned int *) loc = val;
+ else if (r_type == R_390_64)
+ *(unsigned long *) loc = val;
+ break;
+ case R_390_PC16: /* PC relative 16 bit. */
+ case R_390_PC16DBL: /* PC relative 16 bit shifted by 1. */
+ case R_390_PC32DBL: /* PC relative 32 bit shifted by 1. */
+ case R_390_PC32: /* PC relative 32 bit. */
+ case R_390_PC64: /* PC relative 64 bit. */
+ val -= address;
+ if (r_type == R_390_PC16)
+ *(unsigned short *) loc = val;
+ else if (r_type == R_390_PC16DBL)
+ *(unsigned short *) loc = val >> 1;
+ else if (r_type == R_390_PC32DBL)
+ *(unsigned int *) loc = val >> 1;
+ else if (r_type == R_390_PC32)
+ *(unsigned int *) loc = val;
+ else if (r_type == R_390_PC64)
+ *(unsigned long *) loc = val;
+ break;
+ default:
+ die("Unknown rela relocation: 0x%lx 0x%lx\n", r_type, address);
+ break;
+ }
}