1/*
2 * Copyright 2021 The Hafnium Authors.
3 *
4 * Use of this source code is governed by a BSD-style
5 * license that can be found in the LICENSE file or at
6 * https://opensource.org/licenses/BSD-3-Clause.
7 */
8
9.macro ffa_mem_perm_set start:req end:req perm:req
10	adrp x29, \start
11	add x29, x29, :lo12: \start
12
13	adrp x30, \end
14	add x30, x30, :lo12:\end
15
16	/* x30 = end - begin */
17	sub x30, x30, x29
18	/* x28 = x30 >> 12 (number of pages) */
19	mov x28, #12
20	lsrv x28, x30, x28
21
22	/* 0x84000089 is function identifier for FFA_MEM_PERM_SET_32 */
23	mov w0, #0x89
24	movk w0, #0x8400, lsl #16
25	mov x1, x29
26	mov x2, x28
27	mov w3, #\perm
28
29	svc #0
30
31	/* 0x84000061 is function identifier for FFA_SUCCESS_32 */
32	mov w1, #0x61
33	movk w1, #0x8400, lsl #16
34	cmp w1, w0
35	b.ne .
36.endm
37
38.section .init.entry, "ax"
39.global entry
40entry:
41	/* Linux aarch64 image header. */
42	b 0f
43	.word 0
44	.quad 0x1000      /* text_offset */
45	.quad image_size  /* image_size */
46	.quad 0           /* flags */
47	.quad 0           /* res2 */
48	.quad 0           /* res3 */
49	.quad 0           /* res4 */
50	.word 0x644d5241  /* magic */
51	.word 0
52
530:
54	/* Save data (fdt pointer or mem size) passed by hypervisor. */
55	mov x10, x0
56
57	/* Set everything other than text as RW, so that relocations can succeed. */
58	ffa_mem_perm_set rodata_begin image_end 5
59
60	/*
61	 * Calculate the difference between the actual load address and the
62	 * preferred one. We'll use this to relocate.
63	 */
64	adrp x25, entry
65	add x25, x25, :lo12:entry
66
67	ldr w29, =ORIGIN_ADDRESS
68
69	sub x25, x25, x29
70
71	/* Find where the relocations begin and end. */
72	adrp x29, rela_begin
73	add x29, x29, :lo12:rela_begin
74
75	adrp x30, rela_end
76	add x30, x30, :lo12:rela_end
77
78	/* Iterate over all relocations. */
791:	cmp x29, x30
80	b.eq 2f
81
82	ldp x26, x27, [x29], #16
83	ldr x28, [x29], #8
84
85	cmp w27, #1027 /* R_AARCH64_RELATIVE */
86	b.ne .
87
88	add x28, x28, x25
89	str x28, [x26, x25]
90	b 1b
91
92	/* Set everything between ro data and data begin as RO */
932:	ffa_mem_perm_set rodata_begin data_begin 7
94
95	/* set everthing else as RW */
96	ffa_mem_perm_set data_begin image_end 5
97
98	/* Zero out the bss section. */
99	adrp x29, bss_begin
100	add x29, x29, :lo12:bss_begin
101
102	adrp x30, bss_end
103	add x30, x30, :lo12:bss_end
104
1053:	cmp x29, x30
106	b.hs 4f
107
108	stp xzr, xzr, [x29], #16
109	b 3b
110
1114:	mov x0, x10
112
113	/* Branch to the entry point for the specific image. */
114	b image_entry
115
116.section .init.image_entry, "ax"
117.global image_entry
118image_entry:
119	/* Prepare the stack. */
120	adr x30, kstack + 4096
121	mov sp, x30
122
123	/* Call into C code. */
124	bl kmain
125
126	/* Loop forever waiting for interrupts. */
1270:	wfi
128	b 0b
129