summaryrefslogtreecommitdiffstats
path: root/sys/boot/ia64/efi/start.S
blob: 9d28a968993c334ea055698f31e32507ff9730f9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
/*-
 * Copyright (c) 2001 Doug Rabson
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	$FreeBSD$
 */

	.text

#include <machine/asm.h>

#define EFI_SUCCESS		0
#define EFI_LOAD_ERROR		1
#define EFI_BUFFER_TOO_SMALL	5

#define DT_NULL		0	/* Terminating entry. */
#define DT_PLTRELSZ	2	/* Total size in bytes of PLT relocations. */
#define DT_SYMTAB	6	/* Address of symbol table. */
#define DT_RELA		7	/* Address of ElfNN_Rela relocations. */
#define DT_RELASZ	8	/* Total size of ElfNN_Rela relocations. */
#define DT_RELAENT	9	/* Size of each ElfNN_Rela relocation entry. */
#define DT_SYMENT	11	/* Size of each symbol table entry. */
#define DT_JMPREL	23	/* Address of PLT relocations. */

#define R_IA_64_NONE		0	/* None */
#define R_IA_64_DIR64LSB	0x27	/* word64 LSB	S + A */
#define R_IA_64_FPTR64LSB	0x47	/* word64 LSB	@fptr(S + A) */
#define R_IA_64_REL32LSB	0x6d	/* word32 LSB	BD + A */
#define R_IA_64_REL64LSB	0x6f	/* word64 LSB	BD + A */
#define	R_IA_64_IPLTLSB		0x81	/* function descriptor LSB speciaal */

ENTRY(_start, 2)
	alloc	loc0=ar.pfs,2,3,3,0
	mov	loc1=rp
	movl	loc2=@gprel(ImageBase)
	;;
	add	loc2=gp,loc2
	;;
	mov	out0=loc2
	mov	out1=in1
	;;
	br.call.sptk.few rp=_reloc	// relocate image
	
	cmp.ne	p6,p0=EFI_SUCCESS,r8	// did it work?
(p6)	br.cond.dpnt.few 9f

	mov	out0=in0		// image_handle
	mov	out1=in1		// system_table
	br.call.sptk.few rp=efi_main
9:
	mov	ar.pfs=loc0
	mov	rp=loc1
	;;
	br.ret.sptk.few rp
END(_start)

	// PLABEL for PE32+
	.section .plabel, "a"
	.align	16
	.global _start_plabel
_start_plabel:
	data16	@iplt(_start)
	.previous

	// A PE32+ relocation entry for the plabel
	.section .reloc, "a"
	data4	_start_plabel
	data4	12
	data2	(10 << 12) + 0
	data2	(10 << 12) + 8
	.previous

// in0:	image base
// in1:	system table
//
// XXX Assumes PLT relocations are of type Elf_Rela
//
// r2 = address of fptr_storage
// r3 = address of fptr_storage_end
// r4 = address of first free fptr
//
// r15 = r_offset
// r16 = r_info		-OR-	d_tag
// r17 = r_addend	-OR-	d_val (=d_ptr)
// r18 = address of .rela dynamic section
// r19 = size of .rela section
// r20 = size of .rela element (Elf_Rela)
// r21 = address of first PLT relocation
// r22 = size of PLT relocations
// r23 = relocation type
// r24 = address of symbol
// r28 = R_IA_64_IPLTLSB
// f8 = address of symbol table
// f9 = size of symtab element

STATIC_ENTRY(_reloc, 2)
	alloc	loc0=ar.pfs,2,2,0,0
	;;
	mov	loc1=rp
	movl	r29=@gprel(_DYNAMIC)	// find _DYNAMIC etc.
	;;
	add	r15=r29,gp
	movl	r29=@gprel(fptr_storage)
	;;
	add	r2=r29,gp
	movl	r29=@gprel(fptr_storage_end)
	;;
	add	r3=r29,gp
	mov	r4=r2
	mov	r19=0
	mov	r22=0
	mov	r20=24
	mov	r28=R_IA_64_IPLTLSB
	;;
1:
	ld8	r16=[r15],8		// read r15->d_tag
	;;
	ld8	r17=[r15],8		// and r15->d_val
	;;
	cmp.eq	p6,p0=DT_NULL,r16	// done?
(p6)	br.cond.dpnt.few 2f
	;;
	cmp.eq	p6,p0=DT_RELA,r16	// rela section?
	;;
(p6)	add	r18=r17,in0
	cmp.eq	p6,p0=DT_RELASZ,r16	// rela section size?
	;;
(p6)	mov	r19=r17
	cmp.eq	p6,p0=DT_RELAENT,r16	// rela entry size?
	;;
(p6)	mov	r20=r17
	cmp.eq	p6,p0=DT_JMPREL,r16	// PLT relocs?
	;;
(p6)	add	r21=r17,in0
	cmp.eq	p6,p0=DT_PLTRELSZ,r16	// PLT relocs size?
	;;
(p6)	mov	r22=r17
	cmp.eq	p6,p0=DT_SYMTAB,r16	// symbol table?
	;;
(p6)	add	r29=r17,in0
	;;
(p6)	setf.sig f8=r29
	cmp.eq	p6,p0=DT_SYMENT,r16	// symbol entry size?
	;;
(p6)	setf.sig f9=r17
	br.dptk	1b

2:
	cmp.lt	p6,p0=0,r19
(p6)	br.cond.dptk	3f
	;;
	mov	r19=r22
	mov	r18=r21
	mov	r21=0
	mov	r22=0
	;;
	cmp.lt	p6,p0=0,r19
(p6)	br.cond.dptk	3f
	;;
	mov	r8=EFI_SUCCESS
	br.dptk	9f
3:
	ld8	r29=[r18],8		// read r_offset
	;;
	ld8	r16=[r18],8		// read r_info
	add	r15=r29,in0		// relocate r_offset
	;;
	ld8	r17=[r18],8		// read r_addend
	sub	r19=r19,r20		// update relasz
	extr.u	r23=r16,0,32		// ELF64_R_TYPE(r16)
	;;
	cmp.eq	p6,p0=R_IA_64_NONE,r23
(p6)	br.cond.dpnt.few 2b
	;;
	cmp.eq	p6,p0=R_IA_64_REL32LSB,r23
(p6)	br.cond.dptk.few 3f
	;;
	cmp.eq	p6,p0=R_IA_64_REL64LSB,r23
(p6)	br.cond.dptk.few 4f
	;;
	extr.u	r29=r16,32,32		// ELF64_R_SYM(r16)
	;;
	setf.sig f10=r29		// so we can multiply
	;;
	xma.lu	f10=f10,f9,f8		// f10=symtab + r_sym*syment
	;;
	getf.sig r29=f10
	;;
	add	r29=8,r29		// address of st_value
	;;
	ld8	r29=[r29]		// read symbol value
	;;
	add	r24=r29,in0		// relocate symbol value
	;;
	cmp.eq	p6,p0=R_IA_64_DIR64LSB,r23
(p6)	br.cond.dptk.few 5f
	;;
	cmp.eq	p6,p0=R_IA_64_FPTR64LSB,r23
(p6)	br.cond.dptk.few 6f
	;;
	cmp.ne	p6,p0=r28,r23		// IPLTLSB
(p6)	br.cond.dptk.few 2b

	// IPLTLSB
	add	r29=r24,r17		// S + A
	;;
	st8	[r15]=r29,8		// fdesc:FP
	;;
	st8	[r15]=gp		// fdesc:GP
	br.cond.sptk.few 2b

	// REL32LSB
3:
	add	r29=in0,r17
	;;
	st4	[r15]=r29
	br.cond.sptk.few 2b

	// REL64LSB
4:
	add	r29=in0,r17		// BD + A
	;;
	st8	[r15]=r29		// word64
	br.cond.sptk.few 2b

	// DIR64LSB
5:
	add	r29=r24,r17		// S + A
	;;
	st8	[r15]=r29		// word64
	br.cond.sptk.few 2b

6:
	mov	r29=r2			// FPTR64LSB
	;;
7:
	cmp.geu	p6,p0=r29,r4		// end of fptrs?
(p6)	br.cond.dpnt.few 8f		// can't find existing fptr
	ld8	r17=[r29]		// read function from fptr
	;;
	cmp.eq	p6,p0=r24,r17		// same function?
	;;
(p6)	st8	[r15]=r29		// reuse fptr
(p6)	br.cond.sptk.few 2b		// done
	add	r29=16,r29		// next fptr
	br.sptk.few 7b
8:
	mov	r8=EFI_BUFFER_TOO_SMALL	// failure return value
	cmp.geu	p6,p0=r4,r3		// space left?
(p6)	br.cond.dpnt.few 9f		// bail out
	st8	[r15]=r4		// install fptr
	;;
	st8	[r4]=r24,8		// write fptr address
	;;
	st8	[r4]=gp,8		// write fptr gp
	br.cond.sptk.few 2b

9:
	mov	ar.pfs=loc0
	mov	rp=loc1
	;;
	br.ret.sptk.few rp
END(_reloc)

	.data
	.align	16
fptr_storage:
	.space	1024*16			// XXX
fptr_storage_end:
OpenPOWER on IntegriCloud