start.S revision 85436
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: head/sys/boot/ia64/efi/start.S 85436 2001-10-24 20:14:49Z dfr $ 2777943Sdfr */ 2877943Sdfr 2977943Sdfr .text 3077943Sdfr 3177943Sdfr#include <sys/cdefs.h> 3277943Sdfr#include <machine/asm.h> 3377943Sdfr 3477943Sdfr#define EFI_SUCCESS 0 3577943Sdfr#define EFI_LOAD_ERROR 1 3677943Sdfr#define EFI_BUFFER_TOO_SMALL 5 3777943Sdfr 3877943Sdfr#define DT_NULL 0 /* Terminating entry. */ 3977943Sdfr#define DT_NEEDED 1 /* String table offset of a needed shared 4077943Sdfr library. */ 4177943Sdfr#define DT_PLTRELSZ 2 /* Total size in bytes of PLT relocations. */ 4277943Sdfr#define DT_PLTGOT 3 /* Processor-dependent address. */ 4377943Sdfr#define DT_HASH 4 /* Address of symbol hash table. */ 4477943Sdfr#define DT_STRTAB 5 /* Address of string table. */ 4577943Sdfr#define DT_SYMTAB 6 /* Address of symbol table. */ 4677943Sdfr#define DT_RELA 7 /* Address of ElfNN_Rela relocations. */ 4777943Sdfr#define DT_RELASZ 8 /* Total size of ElfNN_Rela relocations. */ 4877943Sdfr#define DT_RELAENT 9 /* Size of each ElfNN_Rela relocation entry. */ 4977943Sdfr#define DT_STRSZ 10 /* Size of string table. */ 5077943Sdfr#define DT_SYMENT 11 /* Size of each symbol table entry. */ 5177943Sdfr#define DT_INIT 12 /* Address of initialization function. */ 5277943Sdfr#define DT_FINI 13 /* Address of finalization function. */ 5377943Sdfr#define DT_SONAME 14 /* String table offset of shared object 5477943Sdfr name. */ 5577943Sdfr#define DT_RPATH 15 /* String table offset of library path. */ 5677943Sdfr#define DT_SYMBOLIC 16 /* Indicates "symbolic" linking. */ 5777943Sdfr#define DT_REL 17 /* Address of ElfNN_Rel relocations. */ 5877943Sdfr#define DT_RELSZ 18 /* Total size of ElfNN_Rel relocations. */ 5977943Sdfr#define DT_RELENT 19 /* Size of each ElfNN_Rel relocation. */ 6077943Sdfr#define DT_PLTREL 20 /* Type of relocation used for PLT. */ 6177943Sdfr#define DT_DEBUG 21 /* Reserved (not used). */ 6277943Sdfr#define DT_TEXTREL 22 /* Indicates there may be relocations in 6377943Sdfr non-writable segments. */ 6477943Sdfr#define DT_JMPREL 23 /* Address of PLT relocations. */ 6577943Sdfr 6677943Sdfr#define DT_COUNT 24 /* Number of defined d_tag values. */ 6777943Sdfr 6877943Sdfr#define R_IA64_NONE 0 /* None */ 6977943Sdfr#define R_IA64_DIR64MSB 0x26 /* word64 MSB S + A */ 7077943Sdfr#define R_IA64_DIR64LSB 0x27 /* word64 LSB S + A */ 7177943Sdfr#define R_IA64_FPTR64MSB 0x46 /* word64 MSB @fptr(S + A) */ 7277943Sdfr#define R_IA64_FPTR64LSB 0x47 /* word64 LSB @fptr(S + A) */ 7377943Sdfr#define R_IA64_REL64MSB 0x6e /* word64 MSB BD + A */ 7477943Sdfr#define R_IA64_REL64LSB 0x6f /* word64 LSB BD + A */ 7585436Sdfr#define R_IA64_IPLTLSB 0x81 /* function descriptor LSB speciaal */ 7677943Sdfr 7777943SdfrENTRY(_start, 2) 7877943Sdfr alloc loc0=ar.pfs,2,3,3,0 7977943Sdfr mov loc1=rp 8077943Sdfr movl loc2=@gprel(ImageBase) 8177943Sdfr ;; 8277943Sdfr add loc2=gp,loc2 8377943Sdfr ;; 8477943Sdfr mov out0=loc2 8577943Sdfr mov out1=in1 8677943Sdfr ;; 8777943Sdfr br.call.sptk.few rp=_reloc // relocate image 8877943Sdfr 8977943Sdfr cmp.ne p6,p0=EFI_SUCCESS,r8 // did it work? 9077943Sdfr(p6) br.cond.dpnt.few 9f 9177943Sdfr 9277943Sdfr mov out0=in0 // image_handle 9377943Sdfr mov out1=in1 // system_table 9477943Sdfr br.call.sptk.few rp=efi_main 9577943Sdfr9: 9677943Sdfr mov ar.pfs=loc0 9777943Sdfr mov rp=loc1 9877943Sdfr ;; 9977943Sdfr br.ret.sptk.few rp 10077943SdfrEND(_start) 10177943Sdfr 10277943Sdfr // PLABEL for PE32+ 10377943Sdfr .global _start_plabel 10477943Sdfr .section .plabel, "a" 10577943Sdfr .align 16 10677943Sdfr_start_plabel: 10777943Sdfr .quad _start 10877943Sdfr .quad __gp 10977943Sdfr .previous 11077943Sdfr 11177943Sdfr // A PE32+ relocation entry for the plabel 11277943Sdfr 11377943Sdfr .section .reloc, "a" 11477943Sdfr .long _start_plabel 11577943Sdfr .long 12 11677943Sdfr .short (10 << 12) + 0 11777943Sdfr .short (10 << 12) + 8 11877943Sdfr .previous 11977943Sdfr 12077943Sdfr // in0: image base 12177943Sdfr // in1: system table 12285436Sdfr // 12385436Sdfr // This assumes that the pltrel section immediately follows 12485436Sdfr // the rela section. 12577943SdfrSTATIC_ENTRY(_reloc, 2) 12677943Sdfr alloc loc0=ar.pfs,2,2,2,0 12777943Sdfr mov loc1=rp 12877943Sdfr ;; 12977943Sdfr movl r15=@gprel(_DYNAMIC) // find _DYNAMIC etc. 13077943Sdfr movl r2=@gprel(fptr_storage) 13177943Sdfr movl r3=@gprel(fptr_storage_end) 13277943Sdfr ;; 13377943Sdfr add r15=r15,gp // relocate _DYNAMIC etc. 13477943Sdfr add r2=r2,gp 13577943Sdfr add r3=r3,gp 13685436Sdfr mov r19=0 13777943Sdfr ;; 13877943Sdfr1: ld8 r16=[r15],8 // read r15->d_tag 13977943Sdfr ;; 14077943Sdfr ld8 r17=[r15],8 // and r15->d_val 14177943Sdfr ;; 14277943Sdfr cmp.eq p6,p0=DT_NULL,r16 // done? 14377943Sdfr(p6) br.cond.dpnt.few 2f 14477943Sdfr ;; 14577943Sdfr cmp.eq p6,p0=DT_RELA,r16 14677943Sdfr ;; 14777943Sdfr(p6) add r18=r17,in0 // found rela section 14877943Sdfr ;; 14977943Sdfr cmp.eq p6,p0=DT_RELASZ,r16 15077943Sdfr ;; 15185436Sdfr(p6) add r19=r17,r19 // found rela size 15277943Sdfr ;; 15385436Sdfr cmp.eq p6,p0=DT_PLTRELSZ,r16 15485436Sdfr ;; 15585436Sdfr(p6) add r19=r17,r19 // found pltrel size 15685436Sdfr ;; 15777943Sdfr cmp.eq p6,p0=DT_SYMTAB,r16 15877943Sdfr ;; 15977943Sdfr(p6) add r20=r17,in0 // found symbol table 16077943Sdfr ;; 16177943Sdfr(p6) setf.sig f8=r20 16277943Sdfr ;; 16377943Sdfr cmp.eq p6,p0=DT_SYMENT,r16 16477943Sdfr ;; 16577943Sdfr(p6) setf.sig f9=r17 // found symbol entry size 16677943Sdfr ;; 16777943Sdfr cmp.eq p6,p0=DT_RELAENT,r16 16877943Sdfr ;; 16977943Sdfr(p6) mov r22=r17 // found rela entry size 17077943Sdfr ;; 17177943Sdfr br.sptk.few 1b 17277943Sdfr 17377943Sdfr2: 17477943Sdfr ld8 r15=[r18],8 // read r_offset 17577943Sdfr ;; 17677943Sdfr ld8 r16=[r18],8 // read r_info 17777943Sdfr add r15=r15,in0 // relocate r_offset 17877943Sdfr ;; 17977943Sdfr ld8 r17=[r18],8 // read r_addend 18077943Sdfr sub r19=r19,r22 // update relasz 18177943Sdfr 18277943Sdfr extr.u r23=r16,0,32 // ELF64_R_TYPE(r16) 18377943Sdfr ;; 18477943Sdfr cmp.eq p6,p0=R_IA64_NONE,r23 18577943Sdfr(p6) br.cond.dpnt.few 3f 18677943Sdfr ;; 18777943Sdfr cmp.eq p6,p0=R_IA64_DIR64LSB,r23 18877943Sdfr ;; 18977943Sdfr(p6) br.cond.dptk.few 4f 19077943Sdfr ;; 19177943Sdfr cmp.eq p6,p0=R_IA64_FPTR64LSB,r23 19277943Sdfr ;; 19377943Sdfr(p6) br.cond.dptk.few 5f 19477943Sdfr ;; 19577943Sdfr cmp.eq p6,p0=R_IA64_REL64LSB,r23 19677943Sdfr ;; 19777943Sdfr(p6) br.cond.dptk.few 4f 19877943Sdfr ;; 19985436Sdfr mov r24=R_IA64_IPLTLSB 20085436Sdfr ;; 20185436Sdfr cmp.eq p6,p0=r24,r23 20285436Sdfr ;; 20385436Sdfr(p6) br.cond.dptk.few 5f 20485436Sdfr ;; 20577943Sdfr 20677943Sdfr3: cmp.ltu p6,p0=0,r19 // more? 20777943Sdfr(p6) br.cond.dptk.few 2b // loop 20877943Sdfr 20977943Sdfr mov r8=EFI_SUCCESS // success return value 21077943Sdfr ;; 21177943Sdfr br.cond.sptk.few 9f // done 21277943Sdfr 21385436Sdfr4: // DIR64LSB or REL64LSB 21477943Sdfr ld8 r16=[r15] // read value 21577943Sdfr ;; 21677943Sdfr add r16=r16,in0 // relocate it 21777943Sdfr ;; 21877943Sdfr st8 [r15]=r16 // and store it back 21977943Sdfr br.cond.sptk.few 3b 22077943Sdfr 22185436Sdfr5: // FPTR64LSB or IPLTLSB 22285436Sdfr extr.u r24=r16,32,32 // ELF64_R_SYM(r16) 22377943Sdfr ;; 22485436Sdfr setf.sig f10=r24 // so we can multiply 22577943Sdfr ;; 22677943Sdfr xma.lu f10=f10,f9,f8 // f10=symtab + r_sym*syment 22777943Sdfr ;; 22877943Sdfr getf.sig r16=f10 22985436Sdfr ;; 23085436Sdfr mov r24=R_IA64_IPLTLSB 23185436Sdfr ;; 23285436Sdfr cmp.ne p6,p0=r24,r23 // IPLTLSB doesn't need an @fptr 23385436Sdfr(p6) br.cond.sptk.few 6f 23485436Sdfr ;; 23585436Sdfr add r16=8,r16 // address of st_value 23685436Sdfr ;; 23785436Sdfr ld8 r16=[r16] // read symbol value 23885436Sdfr ;; 23985436Sdfr add r16=r16,in0 // relocate symbol value 24085436Sdfr ;; 24185436Sdfr st8 [r15]=r16,8 // update plt target 24285436Sdfr ;; 24385436Sdfr st8 [r15]=gp // and gp 24485436Sdfr br.cond.sptk.few 3b 24585436Sdfr ;; 24685436Sdfr6: 24777943Sdfr mov r8=EFI_BUFFER_TOO_SMALL // failure return value 24877943Sdfr ;; 24977943Sdfr cmp.geu p6,p0=r2,r3 // space left? 25077943Sdfr(p6) br.cond.dpnt.few 9f // bail out 25177943Sdfr 25277943Sdfr st8 [r15]=r2 // install fptr 25377943Sdfr add r16=8,r16 // address of st_value 25477943Sdfr ;; 25577943Sdfr ld8 r16=[r16] // read symbol value 25677943Sdfr ;; 25777943Sdfr add r16=r16,in0 // relocate symbol value 25877943Sdfr ;; 25977943Sdfr st8 [r2]=r16,8 // write fptr address 26077943Sdfr ;; 26177943Sdfr st8 [r2]=gp,8 // write fptr gp 26277943Sdfr br.cond.sptk.few 3b 26377943Sdfr 26477943Sdfr9: 26577943Sdfr mov ar.pfs=loc0 26677943Sdfr mov rp=loc1 26777943Sdfr ;; 26877943Sdfr br.ret.sptk.few rp 26977943Sdfr 27077943SdfrEND(_reloc) 27177943Sdfr 27277943Sdfr // in0: system table 27377943Sdfr // in1: character 27477943SdfrENTRY(_putchar, 2) 27577943Sdfr alloc loc0=ar.pfs,2,3,2,0 27677943Sdfr mov loc1=rp 27777943Sdfr mov loc2=gp 27877943Sdfr add sp=-32,sp 27977943Sdfr ;; 28077943Sdfr add r14=64,in0 // r14 = &in1->ConOut 28177943Sdfr ;; 28277943Sdfr ld8 r14=[r14] // r14 = in1->ConOut 28377943Sdfr ;; 28477943Sdfr add r15=8,r14 // r15 = &r14->OutputString 28577943Sdfr mov out0=r14 28677943Sdfr mov out1=sp 28777943Sdfr mov r16=sp 28877943Sdfr ;; 28977943Sdfr ld8 r15=[r15] // r15 = r14->OutputString 29077943Sdfr st2 [r16]=in1,2 // write character 29177943Sdfr ;; 29277943Sdfr st2 [r16]=r0 // terminate 29377943Sdfr ld8 r17=[r15],8 // function address 29477943Sdfr ;; 29577943Sdfr ld8 gp=[r15] // function gp 29677943Sdfr mov b6=r17 // transfer to branch register 29777943Sdfr ;; 29877943Sdfr br.call.sptk.few rp=b6 // call function 29977943Sdfr ;; 30077943Sdfr mov gp=loc2 // restore gp 30177943Sdfr mov ar.pfs=loc0 30277943Sdfr mov rp=loc1 30377943Sdfr add sp=32,sp 30477943Sdfr ;; 30577943Sdfr br.ret.sptk.few rp 30677943Sdfr 30777943SdfrEND(_putchar) 30877943Sdfr 30977943Sdfr // in0: system table 31077943Sdfr // in1: string 31177943SdfrENTRY(_puts, 2) 31277943Sdfr alloc loc0=ar.pfs,3,2,2,0 31377943Sdfr mov loc1=rp 31477943Sdfr ;; 31577943Sdfr mov out0=in0 31677943Sdfr ;; 31777943Sdfr1: ld1 out1=[in1],1 31877943Sdfr ;; 31977943Sdfr cmp.eq p6,p0=r0,out1 32077943Sdfr(p6) br.cond.dpnt.few 9f 32177943Sdfr ;; 32277943Sdfr br.call.sptk.few rp=_putchar 32377943Sdfr ;; 32477943Sdfr br.cond.sptk.few 1b 32577943Sdfr9: 32677943Sdfr mov ar.pfs=loc0 32777943Sdfr mov rp=loc1 32877943Sdfr ;; 32977943Sdfr br.ret.sptk.few rp 33077943SdfrEND(_puts) 33177943Sdfr 33277943Sdfr // in0: system table 33377943Sdfr // in1: number 33477943SdfrENTRY(_puthex, 2) 33577943Sdfr alloc loc0=ar.pfs,2,3,2,0 33677943Sdfr mov loc1=rp 33777943Sdfr mov loc2=ar.lc 33877943Sdfr ;; 33977943Sdfr mov out0=in0 34077943Sdfr mov ar.lc=15 34177943Sdfr ;; 34277943Sdfr1: extr.u out1=in1,60,4 34377943Sdfr ;; 34477943Sdfr cmp.leu p6,p7=10,out1 34577943Sdfr ;; 34677943Sdfr(p6) add out1='a'-10,out1 34777943Sdfr(p7) add out1='0',out1 34877943Sdfr dep.z in1=in1,4,60 34977943Sdfr ;; 35077943Sdfr br.call.sptk.few rp=_putchar 35177943Sdfr ;; 35277943Sdfr br.cloop.sptk.few 1b 35377943Sdfr ;; 35477943Sdfr mov out1='\r' 35577943Sdfr ;; 35677943Sdfr br.call.sptk.few rp=_putchar 35777943Sdfr ;; 35877943Sdfr mov out1='\n' 35977943Sdfr ;; 36077943Sdfr br.call.sptk.few rp=_putchar 36177943Sdfr ;; 36277943Sdfr9: 36377943Sdfr mov ar.pfs=loc0 36477943Sdfr mov rp=loc1 36577943Sdfr mov ar.lc=loc2 36677943Sdfr ;; 36777943Sdfr br.ret.sptk.few rp 36877943SdfrEND(_puthex) 36977943Sdfr 37077943Sdfr .data 37177943Sdfr .align 16 37277943Sdfr 37377943Sdfrfptr_storage: 37477943Sdfr .space 1024*16 // XXX 37577943Sdfrfptr_storage_end: 376