start.S revision 154491
119304Speter/*-
219304Speter * Copyright (c) 2001 Doug Rabson
319304Speter * All rights reserved.
419304Speter *
519304Speter * Redistribution and use in source and binary forms, with or without
619304Speter * modification, are permitted provided that the following conditions
719304Speter * are met:
819304Speter * 1. Redistributions of source code must retain the above copyright
919304Speter *    notice, this list of conditions and the following disclaimer.
1019304Speter * 2. Redistributions in binary form must reproduce the above copyright
1119304Speter *    notice, this list of conditions and the following disclaimer in the
1219304Speter *    documentation and/or other materials provided with the distribution.
1319304Speter *
1419304Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1519304Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1619304Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1719304Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1819304Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1919304Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2019304Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2119304Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2219304Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2319304Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2419304Speter * SUCH DAMAGE.
2519304Speter *
2619304Speter *	$FreeBSD: head/sys/boot/ia64/efi/start.S 154491 2006-01-17 21:03:22Z marcel $
2719304Speter */
2819304Speter
2919304Speter	.text
3019304Speter
3119304Speter#include <machine/asm.h>
3219304Speter
3319304Speter#define EFI_SUCCESS		0
3419304Speter#define EFI_LOAD_ERROR		1
3519304Speter#define EFI_BUFFER_TOO_SMALL	5
3619304Speter
3719304Speter#define DT_NULL		0	/* Terminating entry. */
3819304Speter#define DT_NEEDED	1	/* String table offset of a needed shared
3919304Speter				   library. */
4019304Speter#define DT_PLTRELSZ	2	/* Total size in bytes of PLT relocations. */
4119304Speter#define DT_PLTGOT	3	/* Processor-dependent address. */
4219304Speter#define DT_HASH		4	/* Address of symbol hash table. */
4319304Speter#define DT_STRTAB	5	/* Address of string table. */
4419304Speter#define DT_SYMTAB	6	/* Address of symbol table. */
4519304Speter#define DT_RELA		7	/* Address of ElfNN_Rela relocations. */
4619304Speter#define DT_RELASZ	8	/* Total size of ElfNN_Rela relocations. */
4719304Speter#define DT_RELAENT	9	/* Size of each ElfNN_Rela relocation entry. */
4819304Speter#define DT_STRSZ	10	/* Size of string table. */
4919304Speter#define DT_SYMENT	11	/* Size of each symbol table entry. */
5019304Speter#define DT_INIT		12	/* Address of initialization function. */
5119304Speter#define DT_FINI		13	/* Address of finalization function. */
5219304Speter#define DT_SONAME	14	/* String table offset of shared object
5319304Speter				   name. */
5419304Speter#define DT_RPATH	15	/* String table offset of library path. */
5519304Speter#define DT_SYMBOLIC	16	/* Indicates "symbolic" linking. */
5619304Speter#define DT_REL		17	/* Address of ElfNN_Rel relocations. */
5719304Speter#define DT_RELSZ	18	/* Total size of ElfNN_Rel relocations. */
5819304Speter#define DT_RELENT	19	/* Size of each ElfNN_Rel relocation. */
5919304Speter#define DT_PLTREL	20	/* Type of relocation used for PLT. */
6019304Speter#define DT_DEBUG	21	/* Reserved (not used). */
6119304Speter#define DT_TEXTREL	22	/* Indicates there may be relocations in
6219304Speter				   non-writable segments. */
6319304Speter#define DT_JMPREL	23	/* Address of PLT relocations. */
6419304Speter
6519304Speter#define R_IA_64_NONE		0	/* None */
6619304Speter#define R_IA_64_DIR64LSB	0x27	/* word64 LSB	S + A */
6719304Speter#define R_IA_64_FPTR64LSB	0x47	/* word64 LSB	@fptr(S + A) */
6819304Speter#define R_IA_64_REL32LSB	0x6d	/* word32 LSB	BD + A */
6919304Speter#define R_IA_64_REL64LSB	0x6f	/* word64 LSB	BD + A */
7019304Speter#define	R_IA_64_IPLTLSB		0x81	/* function descriptor LSB speciaal */
7119304Speter
7219304SpeterENTRY(_start, 2)
7319304Speter	alloc	loc0=ar.pfs,2,3,3,0
7419304Speter	mov	loc1=rp
7519304Speter	movl	loc2=@gprel(ImageBase)
7619304Speter	;;
7719304Speter	add	loc2=gp,loc2
7819304Speter	;;
7919304Speter	mov	out0=loc2
8019304Speter	mov	out1=in1
8119304Speter	;;
8219304Speter	br.call.sptk.few rp=_reloc	// relocate image
8319304Speter
8419304Speter	cmp.ne	p6,p0=EFI_SUCCESS,r8	// did it work?
8519304Speter(p6)	br.cond.dpnt.few 9f
8619304Speter
8719304Speter	mov	out0=in0		// image_handle
8819304Speter	mov	out1=in1		// system_table
8919304Speter	br.call.sptk.few rp=efi_main
9019304Speter9:
9119304Speter	mov	ar.pfs=loc0
9219304Speter	mov	rp=loc1
9319304Speter	;;
9419304Speter	br.ret.sptk.few rp
9519304SpeterEND(_start)
9619304Speter
9719304Speter	// PLABEL for PE32+
9819304Speter	.section .plabel, "a"
9919304Speter	.align	16
10019304Speter	.global _start_plabel
10119304Speter_start_plabel:
10219304Speter	data16	@iplt(_start)
10319304Speter	.previous
10419304Speter
10519304Speter	// A PE32+ relocation entry for the plabel
10619304Speter	.section .reloc, "a"
10719304Speter	data4	_start_plabel
10819304Speter	data4	12
10919304Speter	data2	(10 << 12) + 0
11019304Speter	data2	(10 << 12) + 8
11119304Speter	.previous
11219304Speter
11319304Speter// in0:	image base
11419304Speter// in1:	system table
11519304Speter//
11619304Speter// XXX Assumes PLT relocations are of type Elf_Rela
11719304Speter//
11819304Speter// r2 = address of fptr_storage
11919304Speter// r3 = address of fptr_storage_end
12019304Speter// r4 = address of first free fptr
12119304Speter//
12219304Speter// r15 = r_offset
12319304Speter// r16 = r_info		-OR-	d_tag
12419304Speter// r17 = r_addend	-OR-	d_val (=d_ptr)
12519304Speter// r18 = address of .rela dynamic section
12619304Speter// r19 = size of .rela section
12719304Speter// r20 = size of .rela element (Elf_Rela)
12819304Speter// r21 = address of first PLT relocation
12919304Speter// r22 = size of PLT relocations
13019304Speter// r23 = relocation type
13119304Speter// r24 = address of symbol
13219304Speter// r28 = R_IA_64_IPLTLSB
13319304Speter// f8 = address of symbol table
13419304Speter// f9 = size of symtab element
13519304Speter
13619304SpeterSTATIC_ENTRY(_reloc, 2)
13719304Speter	alloc	loc0=ar.pfs,2,2,0,0
13819304Speter	;;
13919304Speter	mov	loc1=rp
14019304Speter	movl	r29=@gprel(_DYNAMIC)	// find _DYNAMIC etc.
14119304Speter	;;
14219304Speter	add	r15=r29,gp
14319304Speter	movl	r29=@gprel(fptr_storage)
14419304Speter	;;
14519304Speter	add	r2=r29,gp
14619304Speter	movl	r29=@gprel(fptr_storage_end)
14719304Speter	;;
14819304Speter	add	r3=r29,gp
14919304Speter	mov	r4=r2
15019304Speter	mov	r19=0
15119304Speter	mov	r22=0
15219304Speter	mov	r20=24
15319304Speter	mov	r28=R_IA_64_IPLTLSB
15419304Speter	;;
15519304Speter1:
15619304Speter	ld8	r16=[r15],8		// read r15->d_tag
15719304Speter	;;
15819304Speter	ld8	r17=[r15],8		// and r15->d_val
15919304Speter	;;
16019304Speter	cmp.eq	p6,p0=DT_NULL,r16	// done?
16119304Speter(p6)	br.cond.dpnt.few 2f
16219304Speter	;;
16319304Speter	cmp.eq	p6,p0=DT_RELA,r16	// rela section?
16419304Speter	;;
16519304Speter(p6)	add	r18=r17,in0
16619304Speter	cmp.eq	p6,p0=DT_RELASZ,r16	// rela section size?
16719304Speter	;;
16819304Speter(p6)	mov	r19=r17
16919304Speter	cmp.eq	p6,p0=DT_RELAENT,r16	// rela entry size?
17019304Speter	;;
17119304Speter(p6)	mov	r20=r17
17219304Speter	cmp.eq	p6,p0=DT_JMPREL,r16	// PLT relocs?
17319304Speter	;;
17419304Speter(p6)	add	r21=r17,in0
17519304Speter	cmp.eq	p6,p0=DT_PLTRELSZ,r16	// PLT relocs size?
17619304Speter	;;
17719304Speter(p6)	mov	r22=r17
17819304Speter	cmp.eq	p6,p0=DT_SYMTAB,r16	// symbol table?
17919304Speter	;;
18019304Speter(p6)	add	r29=r17,in0
18119304Speter	;;
18219304Speter(p6)	setf.sig f8=r29
18319304Speter	cmp.eq	p6,p0=DT_SYMENT,r16	// symbol entry size?
18419304Speter	;;
18519304Speter(p6)	setf.sig f9=r17
18619304Speter	br.dptk	1b
18719304Speter
18819304Speter2:
18919304Speter	cmp.lt	p6,p0=0,r19
19019304Speter(p6)	br.cond.dptk	3f
19119304Speter	;;
19219304Speter	mov	r19=r22
19319304Speter	mov	r18=r21
19419304Speter	mov	r21=0
19519304Speter	mov	r22=0
19619304Speter	;;
19719304Speter	cmp.lt	p6,p0=0,r19
19819304Speter(p6)	br.cond.dptk	3f
19919304Speter	;;
20019304Speter	mov	r8=EFI_SUCCESS
20119304Speter	br.dptk	9f
20219304Speter3:
20319304Speter	ld8	r29=[r18],8		// read r_offset
20419304Speter	;;
20519304Speter	ld8	r16=[r18],8		// read r_info
20619304Speter	add	r15=r29,in0		// relocate r_offset
20719304Speter	;;
20819304Speter	ld8	r17=[r18],8		// read r_addend
20919304Speter	sub	r19=r19,r20		// update relasz
21019304Speter	extr.u	r23=r16,0,32		// ELF64_R_TYPE(r16)
21119304Speter	;;
21219304Speter	cmp.eq	p6,p0=R_IA_64_NONE,r23
21319304Speter(p6)	br.cond.dpnt.few 2b
21419304Speter	;;
21519304Speter	cmp.eq	p6,p0=R_IA_64_REL32LSB,r23
21619304Speter(p6)	br.cond.dptk.few 3f
21719304Speter	;;
21819304Speter	cmp.eq	p6,p0=R_IA_64_REL64LSB,r23
21919304Speter(p6)	br.cond.dptk.few 4f
22019304Speter	;;
22119304Speter	extr.u	r29=r16,32,32		// ELF64_R_SYM(r16)
22219304Speter	;;
22319304Speter	setf.sig f10=r29		// so we can multiply
22419304Speter	;;
22519304Speter	xma.lu	f10=f10,f9,f8		// f10=symtab + r_sym*syment
22619304Speter	;;
22719304Speter	getf.sig r29=f10
22819304Speter	;;
22919304Speter	add	r29=8,r29		// address of st_value
23019304Speter	;;
23119304Speter	ld8	r29=[r29]		// read symbol value
23219304Speter	;;
23319304Speter	add	r24=r29,in0		// relocate symbol value
23419304Speter	;;
23519304Speter	cmp.eq	p6,p0=R_IA_64_DIR64LSB,r23
23619304Speter(p6)	br.cond.dptk.few 5f
23719304Speter	;;
23819304Speter	cmp.eq	p6,p0=R_IA_64_FPTR64LSB,r23
23919304Speter(p6)	br.cond.dptk.few 6f
24019304Speter	;;
24119304Speter	cmp.ne	p6,p0=r28,r23		// IPLTLSB
24219304Speter(p6)	br.cond.dptk.few 2b
24319304Speter
24419304Speter	// IPLTLSB
24519304Speter	add	r29=r24,r17		// S + A
24619304Speter	;;
24719304Speter	st8	[r15]=r29,8		// fdesc:FP
24819304Speter	;;
24919304Speter	st8	[r15]=gp		// fdesc:GP
25019304Speter	br.cond.sptk.few 2b
25119304Speter
25219304Speter	// REL32LSB
25319304Speter3:
25419304Speter	add	r29=in0,r17
25519304Speter	;;
25619304Speter	st4	[r15]=r29
25719304Speter	br.cond.sptk.few 2b
25819304Speter
25919304Speter	// REL64LSB
26019304Speter4:
26119304Speter	add	r29=in0,r17		// BD + A
26219304Speter	;;
26319304Speter	st8	[r15]=r29		// word64
26419304Speter	br.cond.sptk.few 2b
26519304Speter
26619304Speter	// DIR64LSB
26719304Speter5:
26819304Speter	add	r29=r24,r17		// S + A
26919304Speter	;;
27019304Speter	st8	[r15]=r29		// word64
27119304Speter	br.cond.sptk.few 2b
27219304Speter
27319304Speter6:
27419304Speter	mov	r29=r2			// FPTR64LSB
27519304Speter	;;
27619304Speter7:
27719304Speter	cmp.geu	p6,p0=r29,r4		// end of fptrs?
27819304Speter(p6)	br.cond.dpnt.few 8f		// can't find existing fptr
27919304Speter	ld8	r17=[r29]		// read function from fptr
28019304Speter	;;
28119304Speter	cmp.eq	p6,p0=r24,r17		// same function?
28219304Speter	;;
28319304Speter(p6)	st8	[r15]=r29		// reuse fptr
28419304Speter(p6)	br.cond.sptk.few 2b		// done
28519304Speter	add	r29=16,r29		// next fptr
28619304Speter	br.sptk.few 7b
28719304Speter8:
28819304Speter	mov	r8=EFI_BUFFER_TOO_SMALL	// failure return value
28919304Speter	cmp.geu	p6,p0=r4,r3		// space left?
29019304Speter(p6)	br.cond.dpnt.few 9f		// bail out
29119304Speter	st8	[r15]=r4		// install fptr
29219304Speter	;;
29319304Speter	st8	[r4]=r24,8		// write fptr address
29419304Speter	;;
29519304Speter	st8	[r4]=gp,8		// write fptr gp
29619304Speter	br.cond.sptk.few 2b
29719304Speter
29819304Speter9:
29919304Speter	mov	ar.pfs=loc0
30019304Speter	mov	rp=loc1
30119304Speter	;;
30219304Speter	br.ret.sptk.few rp
30319304SpeterEND(_reloc)
30419304Speter
30519304Speter	.data
30619304Speter	.align	16
30719304Speterfptr_storage:
308	.space	1024*16			// XXX
309fptr_storage_end:
310