xref: /netbsd/sys/arch/ia64/stand/ia64/efi/start.S (revision 6550d01e)
1/*	$NetBSD: start.S,v 1.2 2006/04/22 07:58:53 cherry Exp $	*/
2
3/*-
4 * Copyright (c) 2001 Doug Rabson
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 *	$FreeBSD: src/sys/boot/efi/libefi/arch/ia64/start.S,v 1.7 2004/07/20 07:11:14 marcel Exp $
29 */
30
31	.text
32
33#include <machine/asm.h>
34
35#define EFI_SUCCESS		0
36#define EFI_LOAD_ERROR		1
37#define EFI_BUFFER_TOO_SMALL	5
38
39#define DT_NULL		0	/* Terminating entry. */
40#define DT_NEEDED	1	/* String table offset of a needed shared
41				   library. */
42#define DT_PLTRELSZ	2	/* Total size in bytes of PLT relocations. */
43#define DT_PLTGOT	3	/* Processor-dependent address. */
44#define DT_HASH		4	/* Address of symbol hash table. */
45#define DT_STRTAB	5	/* Address of string table. */
46#define DT_SYMTAB	6	/* Address of symbol table. */
47#define DT_RELA		7	/* Address of ElfNN_Rela relocations. */
48#define DT_RELASZ	8	/* Total size of ElfNN_Rela relocations. */
49#define DT_RELAENT	9	/* Size of each ElfNN_Rela relocation entry. */
50#define DT_STRSZ	10	/* Size of string table. */
51#define DT_SYMENT	11	/* Size of each symbol table entry. */
52#define DT_INIT		12	/* Address of initialization function. */
53#define DT_FINI		13	/* Address of finalization function. */
54#define DT_SONAME	14	/* String table offset of shared object
55				   name. */
56#define DT_RPATH	15	/* String table offset of library path. */
57#define DT_SYMBOLIC	16	/* Indicates "symbolic" linking. */
58#define DT_REL		17	/* Address of ElfNN_Rel relocations. */
59#define DT_RELSZ	18	/* Total size of ElfNN_Rel relocations. */
60#define DT_RELENT	19	/* Size of each ElfNN_Rel relocation. */
61#define DT_PLTREL	20	/* Type of relocation used for PLT. */
62#define DT_DEBUG	21	/* Reserved (not used). */
63#define DT_TEXTREL	22	/* Indicates there may be relocations in
64				   non-writable segments. */
65#define DT_JMPREL	23	/* Address of PLT relocations. */
66
67#define DT_COUNT	24	/* Number of defined d_tag values. */
68
69#define R_IA64_NONE		0	/* None */
70#define R_IA64_DIR64MSB		0x26	/* word64 MSB	S + A */
71#define R_IA64_DIR64LSB		0x27	/* word64 LSB	S + A */
72#define R_IA64_FPTR64MSB	0x46	/* word64 MSB	@fptr(S + A) */
73#define R_IA64_FPTR64LSB	0x47	/* word64 LSB	@fptr(S + A) */
74#define R_IA64_REL64MSB		0x6e	/* word64 MSB	BD + A */
75#define R_IA64_REL32LSB		0x6d	/* word32 LSB	BD + A */
76#define R_IA64_REL64LSB		0x6f	/* word64 LSB	BD + A */
77#define	R_IA64_IPLTLSB		0x81	/* function descriptor LSB speciaal */
78
79ENTRY(_start, 2)
80	alloc	loc0=ar.pfs,2,3,3,0
81	mov	loc1=rp
82	movl	loc2=@gprel(ImageBase)
83	;;
84	add	loc2=gp,loc2
85	;;
86	mov	out0=loc2
87	mov	out1=in1
88	;;
89	br.call.sptk.few rp=_reloc	// relocate image
90
91	cmp.ne	p6,p0=EFI_SUCCESS,r8	// did it work?
92(p6)	br.cond.dpnt.few 9f
93
94	mov	out0=in0		// image_handle
95	mov	out1=in1		// system_table
96	br.call.sptk.few rp=efi_main
979:
98	mov	ar.pfs=loc0
99	mov	rp=loc1
100	;;
101	br.ret.sptk.few rp
102END(_start)
103
104	// PLABEL for PE32+
105	.section .plabel, "a"
106	.align	16
107	.global _start_plabel
108_start_plabel:
109	data16	@iplt(_start)
110	.previous
111
112	// A PE32+ relocation entry for the plabel
113	.section .reloc, "a"
114	data4	_start_plabel
115	data4	12
116	data2	(10 << 12) + 0
117	data2	(10 << 12) + 8
118	.previous
119
120// in0:	image base
121// in1:	system table
122//
123// XXX Assumes PLT relocations are of type Elf_Rela
124//
125// r2 = address of fptr_storage
126// r3 = address of fptr_storage_end
127// r4 = address of first free fptr
128//
129// r15 = r_offset
130// r16 = r_info		-OR-	d_tag
131// r17 = r_addend	-OR-	d_val (=d_ptr)
132// r18 = address of .rela dynamic section
133// r19 = size of .rela section
134// r20 = size of .rela element (Elf_Rela)
135// r21 = address of first PLT relocation
136// r22 = size of PLT relocations
137// r23 = relocation type
138// r24 = address of symbol
139// r28 = R_IA64_IPLTLSB
140// f8 = address of symbol table
141// f9 = size of symtab element
142
143STATIC_ENTRY(_reloc, 2)
144	alloc	loc0=ar.pfs,2,2,0,0
145	;;
146	mov	loc1=rp
147	movl	r29=@gprel(_DYNAMIC)	// find _DYNAMIC etc.
148	;;
149	add	r15=r29,gp
150	movl	r29=@gprel(fptr_storage)
151	;;
152	add	r2=r29,gp
153	movl	r29=@gprel(fptr_storage_end)
154	;;
155	add	r3=r29,gp
156	mov	r4=r2
157	mov	r19=0
158	mov	r22=0
159	mov	r20=24
160	mov	r28=R_IA64_IPLTLSB
161	;;
1621:
163	ld8	r16=[r15],8		// read r15->d_tag
164	;;
165	ld8	r17=[r15],8		// and r15->d_val
166	;;
167	cmp.eq	p6,p0=DT_NULL,r16	// done?
168(p6)	br.cond.dpnt.few 2f
169	;;
170	cmp.eq	p6,p0=DT_RELA,r16	// rela section?
171	;;
172(p6)	add	r18=r17,in0
173	cmp.eq	p6,p0=DT_RELASZ,r16	// rela section size?
174	;;
175(p6)	mov	r19=r17
176	cmp.eq	p6,p0=DT_RELAENT,r16	// rela entry size?
177	;;
178(p6)	mov	r20=r17
179	cmp.eq	p6,p0=DT_JMPREL,r16	// PLT relocs?
180	;;
181(p6)	add	r21=r17,in0
182	cmp.eq	p6,p0=DT_PLTRELSZ,r16	// PLT relocs size?
183	;;
184(p6)	mov	r22=r17
185	cmp.eq	p6,p0=DT_SYMTAB,r16	// symbol table?
186	;;
187(p6)	add	r29=r17,in0
188	;;
189(p6)	setf.sig f8=r29
190	cmp.eq	p6,p0=DT_SYMENT,r16	// symbol entry size?
191	;;
192(p6)	setf.sig f9=r17
193	br.dptk	1b
194
1952:
196	cmp.lt	p6,p0=0,r19
197(p6)	br.cond.dptk	3f
198	;;
199	mov	r19=r22
200	mov	r18=r21
201	mov	r21=0
202	mov	r22=0
203	;;
204	cmp.lt	p6,p0=0,r19
205(p6)	br.cond.dptk	3f
206	;;
207	mov	r8=EFI_SUCCESS
208	br.dptk	9f
2093:
210	ld8	r29=[r18],8		// read r_offset
211	;;
212	ld8	r16=[r18],8		// read r_info
213	add	r15=r29,in0		// relocate r_offset
214	;;
215	ld8	r17=[r18],8		// read r_addend
216	sub	r19=r19,r20		// update relasz
217	extr.u	r23=r16,0,32		// ELF64_R_TYPE(r16)
218	;;
219	cmp.eq	p6,p0=R_IA64_NONE,r23
220(p6)	br.cond.dpnt.few 2b
221	;;
222	cmp.eq	p6,p0=R_IA64_REL32LSB,r23
223(p6)	br.cond.dptk.few 3f
224	;;
225	cmp.eq	p6,p0=R_IA64_REL64LSB,r23
226(p6)	br.cond.dptk.few 4f
227	;;
228	extr.u	r29=r16,32,32		// ELF64_R_SYM(r16)
229	;;
230	setf.sig f10=r29		// so we can multiply
231	;;
232	xma.lu	f10=f10,f9,f8		// f10=symtab + r_sym*syment
233	;;
234	getf.sig r29=f10
235	;;
236	add	r29=8,r29		// address of st_value
237	;;
238	ld8	r29=[r29]		// read symbol value
239	;;
240	add	r24=r29,in0		// relocate symbol value
241	;;
242	cmp.eq	p6,p0=R_IA64_DIR64LSB,r23
243(p6)	br.cond.dptk.few 5f
244	;;
245	cmp.eq	p6,p0=R_IA64_FPTR64LSB,r23
246(p6)	br.cond.dptk.few 6f
247	;;
248	cmp.ne	p6,p0=r28,r23		// IPLTLSB
249(p6)	br.cond.dptk.few 2b
250
251	// IPLTLSB
252	add	r29=r24,r17		// S + A
253	;;
254	st8	[r15]=r29,8		// fdesc:FP
255	;;
256	st8	[r15]=gp		// fdesc:GP
257	br.cond.sptk.few 2b
258
259	// REL32LSB
2603:
261	add	r29=in0,r17
262	;;
263	st4	[r15]=r29
264	br.cond.sptk.few 2b
265
266	// REL64LSB
2674:
268	add	r29=in0,r17		// BD + A
269	;;
270	st8	[r15]=r29		// word64
271	br.cond.sptk.few 2b
272
273	// DIR64LSB
2745:
275	add	r29=r24,r17		// S + A
276	;;
277	st8	[r15]=r29		// word64
278	br.cond.sptk.few 2b
279
2806:
281	mov	r29=r2			// FPTR64LSB
282	;;
2837:
284	cmp.geu	p6,p0=r29,r4		// end of fptrs?
285(p6)	br.cond.dpnt.few 8f		// can't find existing fptr
286	ld8	r17=[r29]		// read function from fptr
287	;;
288	cmp.eq	p6,p0=r24,r17		// same function?
289	;;
290(p6)	st8	[r15]=r29		// reuse fptr
291(p6)	br.cond.sptk.few 2b		// done
292	add	r29=16,r29		// next fptr
293	br.sptk.few 7b
2948:
295	mov	r8=EFI_BUFFER_TOO_SMALL	// failure return value
296	cmp.geu	p6,p0=r4,r3		// space left?
297(p6)	br.cond.dpnt.few 9f		// bail out
298	st8	[r15]=r4		// install fptr
299	;;
300	st8	[r4]=r24,8		// write fptr address
301	;;
302	st8	[r4]=gp,8		// write fptr gp
303	br.cond.sptk.few 2b
304
3059:
306	mov	ar.pfs=loc0
307	mov	rp=loc1
308	;;
309	br.ret.sptk.few rp
310END(_reloc)
311
312	.data
313	.align	16
314fptr_storage:
315	.space	1024*16			// XXX
316fptr_storage_end:
317