start.S revision 77943
1/*-
2 * Copyright (c) 2001 Doug Rabson
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 *	$FreeBSD: head/sys/boot/ia64/efi/start.S 77943 2001-06-09 16:49:51Z dfr $
27 */
28
29	.text
30
31#include <sys/cdefs.h>
32#include <machine/asm.h>
33
34#define EFI_SUCCESS		0
35#define EFI_LOAD_ERROR		1
36#define EFI_BUFFER_TOO_SMALL	5
37
38#define DT_NULL		0	/* Terminating entry. */
39#define DT_NEEDED	1	/* String table offset of a needed shared
40				   library. */
41#define DT_PLTRELSZ	2	/* Total size in bytes of PLT relocations. */
42#define DT_PLTGOT	3	/* Processor-dependent address. */
43#define DT_HASH		4	/* Address of symbol hash table. */
44#define DT_STRTAB	5	/* Address of string table. */
45#define DT_SYMTAB	6	/* Address of symbol table. */
46#define DT_RELA		7	/* Address of ElfNN_Rela relocations. */
47#define DT_RELASZ	8	/* Total size of ElfNN_Rela relocations. */
48#define DT_RELAENT	9	/* Size of each ElfNN_Rela relocation entry. */
49#define DT_STRSZ	10	/* Size of string table. */
50#define DT_SYMENT	11	/* Size of each symbol table entry. */
51#define DT_INIT		12	/* Address of initialization function. */
52#define DT_FINI		13	/* Address of finalization function. */
53#define DT_SONAME	14	/* String table offset of shared object
54				   name. */
55#define DT_RPATH	15	/* String table offset of library path. */
56#define DT_SYMBOLIC	16	/* Indicates "symbolic" linking. */
57#define DT_REL		17	/* Address of ElfNN_Rel relocations. */
58#define DT_RELSZ	18	/* Total size of ElfNN_Rel relocations. */
59#define DT_RELENT	19	/* Size of each ElfNN_Rel relocation. */
60#define DT_PLTREL	20	/* Type of relocation used for PLT. */
61#define DT_DEBUG	21	/* Reserved (not used). */
62#define DT_TEXTREL	22	/* Indicates there may be relocations in
63				   non-writable segments. */
64#define DT_JMPREL	23	/* Address of PLT relocations. */
65
66#define DT_COUNT	24	/* Number of defined d_tag values. */
67
68#define R_IA64_NONE		0	/* None */
69#define R_IA64_DIR64MSB		0x26	/* word64 MSB	S + A */
70#define R_IA64_DIR64LSB		0x27	/* word64 LSB	S + A */
71#define R_IA64_FPTR64MSB	0x46	/* word64 MSB	@fptr(S + A) */
72#define R_IA64_FPTR64LSB	0x47	/* word64 LSB	@fptr(S + A) */
73#define R_IA64_REL64MSB		0x6e	/* word64 MSB	BD + A */
74#define R_IA64_REL64LSB		0x6f	/* word64 LSB	BD + A */
75
76ENTRY(_start, 2)
77	alloc	loc0=ar.pfs,2,3,3,0
78	mov	loc1=rp
79	movl	loc2=@gprel(ImageBase)
80	;;
81	br.sptk.few 9f
82	add	loc2=gp,loc2
83	;;
84	mov	out0=loc2
85	mov	out1=in1
86	;;
87	br.call.sptk.few rp=_reloc	// relocate image
88
89	cmp.ne	p6,p0=EFI_SUCCESS,r8	// did it work?
90(p6)	br.cond.dpnt.few 9f
91
92	mov	out0=in0		// image_handle
93	mov	out1=in1		// system_table
94	br.call.sptk.few rp=efi_main
959:
96	mov	ar.pfs=loc0
97	mov	rp=loc1
98	;;
99	br.ret.sptk.few rp
100END(_start)
101
102	// PLABEL for PE32+
103	.global _start_plabel
104	.section .plabel, "a"
105	.align	16
106_start_plabel:
107	.quad	_start
108	.quad	__gp
109	.previous
110
111	// A PE32+ relocation entry for the plabel
112
113	.section .reloc, "a"
114	.long	_start_plabel
115	.long	12
116	.short	(10 << 12) + 0
117	.short	(10 << 12) + 8
118	.previous
119
120	// in0:	image base
121	// in1:	system table
122STATIC_ENTRY(_reloc, 2)
123	alloc	loc0=ar.pfs,2,2,2,0
124	mov	loc1=rp
125	;;
126	movl	r15=@gprel(_DYNAMIC)	// find _DYNAMIC etc.
127	movl	r2=@gprel(fptr_storage)
128	movl	r3=@gprel(fptr_storage_end)
129	;;
130	add	r15=r15,gp		// relocate _DYNAMIC etc.
131	add	r2=r2,gp
132	add	r3=r3,gp
133	;;
1341:	ld8	r16=[r15],8		// read r15->d_tag
135	;;
136	ld8	r17=[r15],8		// and r15->d_val
137	;;
138	cmp.eq	p6,p0=DT_NULL,r16	// done?
139(p6)	br.cond.dpnt.few 2f
140	;;
141	cmp.eq	p6,p0=DT_RELA,r16
142	;;
143(p6)	add	r18=r17,in0		// found rela section
144	;;
145	cmp.eq	p6,p0=DT_RELASZ,r16
146	;;
147(p6)	mov	r19=r17			// found rela size
148	;;
149	cmp.eq	p6,p0=DT_SYMTAB,r16
150	;;
151(p6)	add	r20=r17,in0		// found symbol table
152	;;
153(p6)	setf.sig f8=r20
154	;;
155	cmp.eq	p6,p0=DT_SYMENT,r16
156	;;
157(p6)	setf.sig f9=r17			// found symbol entry size
158	;;
159	cmp.eq	p6,p0=DT_RELAENT,r16
160	;;
161(p6)	mov	r22=r17			// found rela entry size
162	;;
163	br.sptk.few 1b
164
1652:
166	ld8	r15=[r18],8		// read r_offset
167	;;
168	ld8	r16=[r18],8		// read r_info
169	add	r15=r15,in0		// relocate r_offset
170	;;
171	ld8	r17=[r18],8		// read r_addend
172	sub	r19=r19,r22		// update relasz
173
174	extr.u	r23=r16,0,32		// ELF64_R_TYPE(r16)
175	;;
176	cmp.eq	p6,p0=R_IA64_NONE,r23
177(p6)	br.cond.dpnt.few 3f
178	;;
179	cmp.eq	p6,p0=R_IA64_DIR64LSB,r23
180	;;
181(p6)	br.cond.dptk.few 4f
182	;;
183	cmp.eq	p6,p0=R_IA64_FPTR64LSB,r23
184	;;
185(p6)	br.cond.dptk.few 5f
186	;;
187	cmp.eq	p6,p0=R_IA64_REL64LSB,r23
188	;;
189(p6)	br.cond.dptk.few 4f
190	;;
191
1923:	cmp.ltu	p6,p0=0,r19		// more?
193(p6)	br.cond.dptk.few 2b		// loop
194
195	mov	r8=EFI_SUCCESS		// success return value
196	;;
197	br.cond.sptk.few 9f		// done
198
1994:
200	ld8	r16=[r15]		// read value
201	;;
202	add	r16=r16,in0		// relocate it
203	;;
204	st8	[r15]=r16		// and store it back
205	br.cond.sptk.few 3b
206
2075:
208	extr.u	r23=r16,32,32		// ELF64_R_SYM(r16)
209	;;
210	setf.sig f10=r23		// so we can multiply
211	;;
212	xma.lu	f10=f10,f9,f8		// f10=symtab + r_sym*syment
213	;;
214	getf.sig r16=f10
215	mov	r8=EFI_BUFFER_TOO_SMALL	// failure return value
216	;;
217	cmp.geu	p6,p0=r2,r3		// space left?
218(p6)	br.cond.dpnt.few 9f		// bail out
219
220	st8	[r15]=r2		// install fptr
221	add	r16=8,r16		// address of st_value
222	;;
223	ld8	r16=[r16]		// read symbol value
224	;;
225	add	r16=r16,in0		// relocate symbol value
226	;;
227	st8	[r2]=r16,8		// write fptr address
228	;;
229	st8	[r2]=gp,8		// write fptr gp
230	br.cond.sptk.few 3b
231
2329:
233	mov	ar.pfs=loc0
234	mov	rp=loc1
235	;;
236	br.ret.sptk.few rp
237
238END(_reloc)
239
240	// in0:	system table
241	// in1:	character
242ENTRY(_putchar, 2)
243	alloc	loc0=ar.pfs,2,3,2,0
244	mov	loc1=rp
245	mov	loc2=gp
246	add	sp=-32,sp
247	;;
248	add	r14=64,in0		// r14 = &in1->ConOut
249	;;
250	ld8	r14=[r14]		// r14 = in1->ConOut
251	;;
252	add	r15=8,r14		// r15 = &r14->OutputString
253	mov	out0=r14
254	mov	out1=sp
255	mov	r16=sp
256	;;
257	ld8	r15=[r15]		// r15 = r14->OutputString
258	st2	[r16]=in1,2		// write character
259	;;
260	st2	[r16]=r0		// terminate
261	ld8	r17=[r15],8		// function address
262	;;
263	ld8	gp=[r15]		// function gp
264	mov	b6=r17			// transfer to branch register
265	;;
266	br.call.sptk.few rp=b6		// call function
267	;;
268	mov	gp=loc2			// restore gp
269	mov	ar.pfs=loc0
270	mov	rp=loc1
271	add	sp=32,sp
272	;;
273	br.ret.sptk.few rp
274
275END(_putchar)
276
277	// in0:	system table
278	// in1:	string
279ENTRY(_puts, 2)
280	alloc	loc0=ar.pfs,3,2,2,0
281	mov	loc1=rp
282	;;
283	mov	out0=in0
284	;;
2851:	ld1	out1=[in1],1
286	;;
287	cmp.eq	p6,p0=r0,out1
288(p6)	br.cond.dpnt.few 9f
289	;;
290	br.call.sptk.few rp=_putchar
291	;;
292	br.cond.sptk.few 1b
2939:
294	mov	ar.pfs=loc0
295	mov	rp=loc1
296	;;
297	br.ret.sptk.few rp
298END(_puts)
299
300	// in0:	system table
301	// in1:	number
302ENTRY(_puthex, 2)
303	alloc	loc0=ar.pfs,2,3,2,0
304	mov	loc1=rp
305	mov	loc2=ar.lc
306	;;
307	mov	out0=in0
308	mov	ar.lc=15
309	;;
3101:	extr.u	out1=in1,60,4
311	;;
312	cmp.leu	p6,p7=10,out1
313	;;
314(p6)	add	out1='a'-10,out1
315(p7)	add	out1='0',out1
316	dep.z	in1=in1,4,60
317	;;
318	br.call.sptk.few rp=_putchar
319	;;
320	br.cloop.sptk.few 1b
321	;;
322	mov	out1='\r'
323	;;
324	br.call.sptk.few rp=_putchar
325	;;
326	mov	out1='\n'
327	;;
328	br.call.sptk.few rp=_putchar
329	;;
3309:
331	mov	ar.pfs=loc0
332	mov	rp=loc1
333	mov	ar.lc=loc2
334	;;
335	br.ret.sptk.few rp
336END(_puthex)
337
338	.data
339	.align	16
340
341fptr_storage:
342	.space	1024*16			// XXX
343fptr_storage_end:
344