1// SPDX-License-Identifier: GPL-2.0
2#include <linux/elf.h>
3#include <asm/kexec.h>
4
5int arch_kexec_do_relocs(int r_type, void *loc, unsigned long val,
6			 unsigned long addr)
7{
8	switch (r_type) {
9	case R_390_NONE:
10		break;
11	case R_390_8:		/* Direct 8 bit.   */
12		*(u8 *)loc = val;
13		break;
14	case R_390_12:		/* Direct 12 bit.  */
15		*(u16 *)loc &= 0xf000;
16		*(u16 *)loc |= val & 0xfff;
17		break;
18	case R_390_16:		/* Direct 16 bit.  */
19		*(u16 *)loc = val;
20		break;
21	case R_390_20:		/* Direct 20 bit.  */
22		*(u32 *)loc &= 0xf00000ff;
23		*(u32 *)loc |= (val & 0xfff) << 16;	/* DL */
24		*(u32 *)loc |= (val & 0xff000) >> 4;	/* DH */
25		break;
26	case R_390_32:		/* Direct 32 bit.  */
27		*(u32 *)loc = val;
28		break;
29	case R_390_64:		/* Direct 64 bit.  */
30	case R_390_GLOB_DAT:
31	case R_390_JMP_SLOT:
32		*(u64 *)loc = val;
33		break;
34	case R_390_PC16:	/* PC relative 16 bit.	*/
35		*(u16 *)loc = (val - addr);
36		break;
37	case R_390_PC16DBL:	/* PC relative 16 bit shifted by 1.  */
38		*(u16 *)loc = (val - addr) >> 1;
39		break;
40	case R_390_PC32DBL:	/* PC relative 32 bit shifted by 1.  */
41		*(u32 *)loc = (val - addr) >> 1;
42		break;
43	case R_390_PC32:	/* PC relative 32 bit.	*/
44		*(u32 *)loc = (val - addr);
45		break;
46	case R_390_PC64:	/* PC relative 64 bit.	*/
47		*(u64 *)loc = (val - addr);
48		break;
49	case R_390_RELATIVE:
50		*(unsigned long *) loc = val;
51		break;
52	default:
53		return 1;
54	}
55	return 0;
56}
57