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