177943Sdfr/*- 277943Sdfr * Copyright (c) 2001 Doug Rabson 377943Sdfr * All rights reserved. 477943Sdfr * 577943Sdfr * Redistribution and use in source and binary forms, with or without 677943Sdfr * modification, are permitted provided that the following conditions 777943Sdfr * are met: 877943Sdfr * 1. Redistributions of source code must retain the above copyright 977943Sdfr * notice, this list of conditions and the following disclaimer. 1077943Sdfr * 2. Redistributions in binary form must reproduce the above copyright 1177943Sdfr * notice, this list of conditions and the following disclaimer in the 1277943Sdfr * documentation and/or other materials provided with the distribution. 1377943Sdfr * 1477943Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1577943Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1677943Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1777943Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1877943Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1977943Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2077943Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2177943Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2277943Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2377943Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2477943Sdfr * SUCH DAMAGE. 2577943Sdfr * 2677943Sdfr * $FreeBSD$ 2777943Sdfr */ 2877943Sdfr 2977943Sdfr .text 3077943Sdfr 3177943Sdfr#include <machine/asm.h> 32154527Smarcel 3377943Sdfr#define EFI_SUCCESS 0 3477943Sdfr#define EFI_LOAD_ERROR 1 3577943Sdfr#define EFI_BUFFER_TOO_SMALL 5 36154527Smarcel 3777943Sdfr#define DT_NULL 0 /* Terminating entry. */ 3877943Sdfr#define DT_PLTRELSZ 2 /* Total size in bytes of PLT relocations. */ 3977943Sdfr#define DT_SYMTAB 6 /* Address of symbol table. */ 4077943Sdfr#define DT_RELA 7 /* Address of ElfNN_Rela relocations. */ 4177943Sdfr#define DT_RELASZ 8 /* Total size of ElfNN_Rela relocations. */ 4277943Sdfr#define DT_RELAENT 9 /* Size of each ElfNN_Rela relocation entry. */ 4377943Sdfr#define DT_SYMENT 11 /* Size of each symbol table entry. */ 4477943Sdfr#define DT_JMPREL 23 /* Address of PLT relocations. */ 4577943Sdfr 46154491Smarcel#define R_IA_64_NONE 0 /* None */ 47154491Smarcel#define R_IA_64_DIR64LSB 0x27 /* word64 LSB S + A */ 48154491Smarcel#define R_IA_64_FPTR64LSB 0x47 /* word64 LSB @fptr(S + A) */ 49154491Smarcel#define R_IA_64_REL32LSB 0x6d /* word32 LSB BD + A */ 50154491Smarcel#define R_IA_64_REL64LSB 0x6f /* word64 LSB BD + A */ 51154491Smarcel#define R_IA_64_IPLTLSB 0x81 /* function descriptor LSB speciaal */ 5277943Sdfr 5377943SdfrENTRY(_start, 2) 5477943Sdfr alloc loc0=ar.pfs,2,3,3,0 5577943Sdfr mov loc1=rp 5677943Sdfr movl loc2=@gprel(ImageBase) 5777943Sdfr ;; 5877943Sdfr add loc2=gp,loc2 5977943Sdfr ;; 6077943Sdfr mov out0=loc2 6177943Sdfr mov out1=in1 6295190Smarcel ;; 6377943Sdfr br.call.sptk.few rp=_reloc // relocate image 6477943Sdfr 6577943Sdfr cmp.ne p6,p0=EFI_SUCCESS,r8 // did it work? 6677943Sdfr(p6) br.cond.dpnt.few 9f 6777943Sdfr 6877943Sdfr mov out0=in0 // image_handle 6977943Sdfr mov out1=in1 // system_table 7077943Sdfr br.call.sptk.few rp=efi_main 7177943Sdfr9: 7277943Sdfr mov ar.pfs=loc0 7377943Sdfr mov rp=loc1 7477943Sdfr ;; 7577943Sdfr br.ret.sptk.few rp 7677943SdfrEND(_start) 7777943Sdfr 7877943Sdfr // PLABEL for PE32+ 7977943Sdfr .section .plabel, "a" 8077943Sdfr .align 16 81132437Smarcel .global _start_plabel 82132437Smarcel_start_plabel: 83132437Smarcel data16 @iplt(_start) 8477943Sdfr .previous 8577943Sdfr 8677943Sdfr // A PE32+ relocation entry for the plabel 8777943Sdfr .section .reloc, "a" 88132437Smarcel data4 _start_plabel 89132437Smarcel data4 12 90132437Smarcel data2 (10 << 12) + 0 91132437Smarcel data2 (10 << 12) + 8 9277943Sdfr .previous 9377943Sdfr 9495190Smarcel// in0: image base 9595190Smarcel// in1: system table 9695190Smarcel// 9795190Smarcel// XXX Assumes PLT relocations are of type Elf_Rela 9895190Smarcel// 9995190Smarcel// r2 = address of fptr_storage 10095190Smarcel// r3 = address of fptr_storage_end 10195190Smarcel// r4 = address of first free fptr 10295190Smarcel// 10395190Smarcel// r15 = r_offset 10495190Smarcel// r16 = r_info -OR- d_tag 10595190Smarcel// r17 = r_addend -OR- d_val (=d_ptr) 10695190Smarcel// r18 = address of .rela dynamic section 10795190Smarcel// r19 = size of .rela section 10895190Smarcel// r20 = size of .rela element (Elf_Rela) 10995190Smarcel// r21 = address of first PLT relocation 11095190Smarcel// r22 = size of PLT relocations 11195190Smarcel// r23 = relocation type 11295190Smarcel// r24 = address of symbol 113154491Smarcel// r28 = R_IA_64_IPLTLSB 11495190Smarcel// f8 = address of symbol table 11595190Smarcel// f9 = size of symtab element 11695190Smarcel 11777943SdfrSTATIC_ENTRY(_reloc, 2) 11895190Smarcel alloc loc0=ar.pfs,2,2,0,0 11995190Smarcel ;; 12077943Sdfr mov loc1=rp 12195190Smarcel movl r29=@gprel(_DYNAMIC) // find _DYNAMIC etc. 12277943Sdfr ;; 12395190Smarcel add r15=r29,gp 12495190Smarcel movl r29=@gprel(fptr_storage) 12595190Smarcel ;; 12695190Smarcel add r2=r29,gp 12795190Smarcel movl r29=@gprel(fptr_storage_end) 12895190Smarcel ;; 12995190Smarcel add r3=r29,gp 13095190Smarcel mov r4=r2 13185436Sdfr mov r19=0 13295190Smarcel mov r22=0 13395190Smarcel mov r20=24 134154491Smarcel mov r28=R_IA_64_IPLTLSB 13577943Sdfr ;; 13695190Smarcel1: 13795190Smarcel ld8 r16=[r15],8 // read r15->d_tag 13877943Sdfr ;; 13977943Sdfr ld8 r17=[r15],8 // and r15->d_val 14077943Sdfr ;; 14177943Sdfr cmp.eq p6,p0=DT_NULL,r16 // done? 14277943Sdfr(p6) br.cond.dpnt.few 2f 14377943Sdfr ;; 14495190Smarcel cmp.eq p6,p0=DT_RELA,r16 // rela section? 14595190Smarcel ;; 14695190Smarcel(p6) add r18=r17,in0 14795190Smarcel cmp.eq p6,p0=DT_RELASZ,r16 // rela section size? 14895190Smarcel ;; 14995190Smarcel(p6) mov r19=r17 15095190Smarcel cmp.eq p6,p0=DT_RELAENT,r16 // rela entry size? 15195190Smarcel ;; 15295190Smarcel(p6) mov r20=r17 15395190Smarcel cmp.eq p6,p0=DT_JMPREL,r16 // PLT relocs? 15495190Smarcel ;; 15595190Smarcel(p6) add r21=r17,in0 15695190Smarcel cmp.eq p6,p0=DT_PLTRELSZ,r16 // PLT relocs size? 15795190Smarcel ;; 15895190Smarcel(p6) mov r22=r17 15995190Smarcel cmp.eq p6,p0=DT_SYMTAB,r16 // symbol table? 16095190Smarcel ;; 16195190Smarcel(p6) add r29=r17,in0 16295190Smarcel ;; 16395190Smarcel(p6) setf.sig f8=r29 16495190Smarcel cmp.eq p6,p0=DT_SYMENT,r16 // symbol entry size? 16595190Smarcel ;; 16695190Smarcel(p6) setf.sig f9=r17 16795190Smarcel br.dptk 1b 16895190Smarcel 16995190Smarcel2: 17095190Smarcel cmp.lt p6,p0=0,r19 17195190Smarcel(p6) br.cond.dptk 3f 17295190Smarcel ;; 17395190Smarcel mov r19=r22 17495190Smarcel mov r18=r21 17595190Smarcel mov r21=0 17695190Smarcel mov r22=0 17795190Smarcel ;; 17895190Smarcel cmp.lt p6,p0=0,r19 17995190Smarcel(p6) br.cond.dptk 3f 18095190Smarcel ;; 18195190Smarcel mov r8=EFI_SUCCESS 18295190Smarcel br.dptk 9f 18395190Smarcel3: 18495190Smarcel ld8 r29=[r18],8 // read r_offset 18595190Smarcel ;; 18677943Sdfr ld8 r16=[r18],8 // read r_info 18795190Smarcel add r15=r29,in0 // relocate r_offset 18877943Sdfr ;; 18977943Sdfr ld8 r17=[r18],8 // read r_addend 19095190Smarcel sub r19=r19,r20 // update relasz 19177943Sdfr extr.u r23=r16,0,32 // ELF64_R_TYPE(r16) 19277943Sdfr ;; 193154491Smarcel cmp.eq p6,p0=R_IA_64_NONE,r23 19495190Smarcel(p6) br.cond.dpnt.few 2b 19577943Sdfr ;; 196154491Smarcel cmp.eq p6,p0=R_IA_64_REL32LSB,r23 197132437Smarcel(p6) br.cond.dptk.few 3f 198132437Smarcel ;; 199154491Smarcel cmp.eq p6,p0=R_IA_64_REL64LSB,r23 20077943Sdfr(p6) br.cond.dptk.few 4f 20177943Sdfr ;; 20295190Smarcel extr.u r29=r16,32,32 // ELF64_R_SYM(r16) 20377943Sdfr ;; 20495190Smarcel setf.sig f10=r29 // so we can multiply 20577943Sdfr ;; 20695190Smarcel xma.lu f10=f10,f9,f8 // f10=symtab + r_sym*syment 20777943Sdfr ;; 20895190Smarcel getf.sig r29=f10 20977943Sdfr ;; 21095190Smarcel add r29=8,r29 // address of st_value 21185436Sdfr ;; 21295190Smarcel ld8 r29=[r29] // read symbol value 21395190Smarcel ;; 21495190Smarcel add r24=r29,in0 // relocate symbol value 21595190Smarcel ;; 216154491Smarcel cmp.eq p6,p0=R_IA_64_DIR64LSB,r23 21785436Sdfr(p6) br.cond.dptk.few 5f 21885436Sdfr ;; 219154491Smarcel cmp.eq p6,p0=R_IA_64_FPTR64LSB,r23 22095190Smarcel(p6) br.cond.dptk.few 6f 22177943Sdfr ;; 22295190Smarcel cmp.ne p6,p0=r28,r23 // IPLTLSB 22395190Smarcel(p6) br.cond.dptk.few 2b 22477943Sdfr 22595190Smarcel // IPLTLSB 22695190Smarcel add r29=r24,r17 // S + A 22777943Sdfr ;; 22895190Smarcel st8 [r15]=r29,8 // fdesc:FP 22977943Sdfr ;; 23095190Smarcel st8 [r15]=gp // fdesc:GP 23195190Smarcel br.cond.sptk.few 2b 23277943Sdfr 233132437Smarcel // REL32LSB 234132437Smarcel3: 235132437Smarcel add r29=in0,r17 236132437Smarcel ;; 237132437Smarcel st4 [r15]=r29 238132437Smarcel br.cond.sptk.few 2b 239132437Smarcel 24095190Smarcel // REL64LSB 24195190Smarcel4: 24295190Smarcel add r29=in0,r17 // BD + A 24377943Sdfr ;; 24495190Smarcel st8 [r15]=r29 // word64 24595190Smarcel br.cond.sptk.few 2b 24695190Smarcel 24795190Smarcel // DIR64LSB 24895190Smarcel5: 24995190Smarcel add r29=r24,r17 // S + A 25077943Sdfr ;; 25195190Smarcel st8 [r15]=r29 // word64 25295190Smarcel br.cond.sptk.few 2b 25395190Smarcel 25495190Smarcel6: 25595190Smarcel mov r29=r2 // FPTR64LSB 25685436Sdfr ;; 25795190Smarcel7: 25895190Smarcel cmp.geu p6,p0=r29,r4 // end of fptrs? 25995190Smarcel(p6) br.cond.dpnt.few 8f // can't find existing fptr 26095190Smarcel ld8 r17=[r29] // read function from fptr 26185436Sdfr ;; 26295190Smarcel cmp.eq p6,p0=r24,r17 // same function? 26385436Sdfr ;; 26495190Smarcel(p6) st8 [r15]=r29 // reuse fptr 26595190Smarcel(p6) br.cond.sptk.few 2b // done 26695190Smarcel add r29=16,r29 // next fptr 26795190Smarcel br.sptk.few 7b 26895190Smarcel8: 26977943Sdfr mov r8=EFI_BUFFER_TOO_SMALL // failure return value 27095190Smarcel cmp.geu p6,p0=r4,r3 // space left? 27177943Sdfr(p6) br.cond.dpnt.few 9f // bail out 27295190Smarcel st8 [r15]=r4 // install fptr 27377943Sdfr ;; 27495190Smarcel st8 [r4]=r24,8 // write fptr address 27577943Sdfr ;; 27695190Smarcel st8 [r4]=gp,8 // write fptr gp 27795190Smarcel br.cond.sptk.few 2b 27877943Sdfr 27977943Sdfr9: 28077943Sdfr mov ar.pfs=loc0 28177943Sdfr mov rp=loc1 28277943Sdfr ;; 28377943Sdfr br.ret.sptk.few rp 28477943SdfrEND(_reloc) 28577943Sdfr 28677943Sdfr .data 28777943Sdfr .align 16 288107720Smarcelfptr_storage: 28977943Sdfr .space 1024*16 // XXX 290107720Smarcelfptr_storage_end: 291