start.S revision 95190
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 95190 2002-04-21 08:49:47Z marcel $ 27 */ 28 29 .text 30 31#include <machine/asm.h> 32 33#define EFI_SUCCESS 0 34#define EFI_LOAD_ERROR 1 35#define EFI_BUFFER_TOO_SMALL 5 36 37#define DT_NULL 0 /* Terminating entry. */ 38#define DT_NEEDED 1 /* String table offset of a needed shared 39 library. */ 40#define DT_PLTRELSZ 2 /* Total size in bytes of PLT relocations. */ 41#define DT_PLTGOT 3 /* Processor-dependent address. */ 42#define DT_HASH 4 /* Address of symbol hash table. */ 43#define DT_STRTAB 5 /* Address of string table. */ 44#define DT_SYMTAB 6 /* Address of symbol table. */ 45#define DT_RELA 7 /* Address of ElfNN_Rela relocations. */ 46#define DT_RELASZ 8 /* Total size of ElfNN_Rela relocations. */ 47#define DT_RELAENT 9 /* Size of each ElfNN_Rela relocation entry. */ 48#define DT_STRSZ 10 /* Size of string table. */ 49#define DT_SYMENT 11 /* Size of each symbol table entry. */ 50#define DT_INIT 12 /* Address of initialization function. */ 51#define DT_FINI 13 /* Address of finalization function. */ 52#define DT_SONAME 14 /* String table offset of shared object 53 name. */ 54#define DT_RPATH 15 /* String table offset of library path. */ 55#define DT_SYMBOLIC 16 /* Indicates "symbolic" linking. */ 56#define DT_REL 17 /* Address of ElfNN_Rel relocations. */ 57#define DT_RELSZ 18 /* Total size of ElfNN_Rel relocations. */ 58#define DT_RELENT 19 /* Size of each ElfNN_Rel relocation. */ 59#define DT_PLTREL 20 /* Type of relocation used for PLT. */ 60#define DT_DEBUG 21 /* Reserved (not used). */ 61#define DT_TEXTREL 22 /* Indicates there may be relocations in 62 non-writable segments. */ 63#define DT_JMPREL 23 /* Address of PLT relocations. */ 64 65#define DT_COUNT 24 /* Number of defined d_tag values. */ 66 67#define R_IA64_NONE 0 /* None */ 68#define R_IA64_DIR64MSB 0x26 /* word64 MSB S + A */ 69#define R_IA64_DIR64LSB 0x27 /* word64 LSB S + A */ 70#define R_IA64_FPTR64MSB 0x46 /* word64 MSB @fptr(S + A) */ 71#define R_IA64_FPTR64LSB 0x47 /* word64 LSB @fptr(S + A) */ 72#define R_IA64_REL64MSB 0x6e /* word64 MSB BD + A */ 73#define R_IA64_REL64LSB 0x6f /* word64 LSB BD + A */ 74#define R_IA64_IPLTLSB 0x81 /* function descriptor LSB speciaal */ 75 76ENTRY(_start, 2) 77 alloc loc0=ar.pfs,2,3,3,0 78 mov loc1=rp 79 movl loc2=@gprel(ImageBase) 80 ;; 81 add loc2=gp,loc2 82 ;; 83 mov out0=loc2 84 mov out1=in1 85 ;; 86 br.call.sptk.few rp=_reloc // relocate image 87 88 cmp.ne p6,p0=EFI_SUCCESS,r8 // did it work? 89(p6) br.cond.dpnt.few 9f 90 91 mov out0=in0 // image_handle 92 mov out1=in1 // system_table 93 br.call.sptk.few rp=efi_main 949: 95 mov ar.pfs=loc0 96 mov rp=loc1 97 ;; 98 br.ret.sptk.few rp 99END(_start) 100 101 // PLABEL for PE32+ 102 .global _start_plabel 103 .section .plabel, "a" 104 .align 16 105_start_plabel: 106 .quad _start 107 .quad __gp 108 .previous 109 110 // A PE32+ relocation entry for the plabel 111 112 .section .reloc, "a" 113 .long _start_plabel 114 .long 12 115 .short (10 << 12) + 0 116 .short (10 << 12) + 8 117 .previous 118 119// in0: image base 120// in1: system table 121// 122// XXX Assumes PLT relocations are of type Elf_Rela 123// 124// r2 = address of fptr_storage 125// r3 = address of fptr_storage_end 126// r4 = address of first free fptr 127// 128// r15 = r_offset 129// r16 = r_info -OR- d_tag 130// r17 = r_addend -OR- d_val (=d_ptr) 131// r18 = address of .rela dynamic section 132// r19 = size of .rela section 133// r20 = size of .rela element (Elf_Rela) 134// r21 = address of first PLT relocation 135// r22 = size of PLT relocations 136// r23 = relocation type 137// r24 = address of symbol 138// r28 = R_IA64_IPLTLSB 139// f8 = address of symbol table 140// f9 = size of symtab element 141 142STATIC_ENTRY(_reloc, 2) 143 alloc loc0=ar.pfs,2,2,0,0 144 ;; 145 mov loc1=rp 146 movl r29=@gprel(_DYNAMIC) // find _DYNAMIC etc. 147 ;; 148 add r15=r29,gp 149 movl r29=@gprel(fptr_storage) 150 ;; 151 add r2=r29,gp 152 movl r29=@gprel(fptr_storage_end) 153 ;; 154 add r3=r29,gp 155 mov r4=r2 156 mov r19=0 157 mov r22=0 158 mov r20=24 159 mov r28=R_IA64_IPLTLSB 160 ;; 1611: 162 ld8 r16=[r15],8 // read r15->d_tag 163 ;; 164 ld8 r17=[r15],8 // and r15->d_val 165 ;; 166 cmp.eq p6,p0=DT_NULL,r16 // done? 167(p6) br.cond.dpnt.few 2f 168 ;; 169 cmp.eq p6,p0=DT_RELA,r16 // rela section? 170 ;; 171(p6) add r18=r17,in0 172 cmp.eq p6,p0=DT_RELASZ,r16 // rela section size? 173 ;; 174(p6) mov r19=r17 175 cmp.eq p6,p0=DT_RELAENT,r16 // rela entry size? 176 ;; 177(p6) mov r20=r17 178 cmp.eq p6,p0=DT_JMPREL,r16 // PLT relocs? 179 ;; 180(p6) add r21=r17,in0 181 cmp.eq p6,p0=DT_PLTRELSZ,r16 // PLT relocs size? 182 ;; 183(p6) mov r22=r17 184 cmp.eq p6,p0=DT_SYMTAB,r16 // symbol table? 185 ;; 186(p6) add r29=r17,in0 187 ;; 188(p6) setf.sig f8=r29 189 cmp.eq p6,p0=DT_SYMENT,r16 // symbol entry size? 190 ;; 191(p6) setf.sig f9=r17 192 br.dptk 1b 193 1942: 195 cmp.lt p6,p0=0,r19 196(p6) br.cond.dptk 3f 197 ;; 198 mov r19=r22 199 mov r18=r21 200 mov r21=0 201 mov r22=0 202 ;; 203 cmp.lt p6,p0=0,r19 204(p6) br.cond.dptk 3f 205 ;; 206 mov r8=EFI_SUCCESS 207 br.dptk 9f 2083: 209 ld8 r29=[r18],8 // read r_offset 210 ;; 211 ld8 r16=[r18],8 // read r_info 212 add r15=r29,in0 // relocate r_offset 213 ;; 214 ld8 r17=[r18],8 // read r_addend 215 sub r19=r19,r20 // update relasz 216 extr.u r23=r16,0,32 // ELF64_R_TYPE(r16) 217 ;; 218 cmp.eq p6,p0=R_IA64_NONE,r23 219(p6) br.cond.dpnt.few 2b 220 ;; 221 cmp.eq p6,p0=R_IA64_REL64LSB,r23 222(p6) br.cond.dptk.few 4f 223 ;; 224 extr.u r29=r16,32,32 // ELF64_R_SYM(r16) 225 ;; 226 setf.sig f10=r29 // so we can multiply 227 ;; 228 xma.lu f10=f10,f9,f8 // f10=symtab + r_sym*syment 229 ;; 230 getf.sig r29=f10 231 ;; 232 add r29=8,r29 // address of st_value 233 ;; 234 ld8 r29=[r29] // read symbol value 235 ;; 236 add r24=r29,in0 // relocate symbol value 237 ;; 238 cmp.eq p6,p0=R_IA64_DIR64LSB,r23 239(p6) br.cond.dptk.few 5f 240 ;; 241 cmp.eq p6,p0=R_IA64_FPTR64LSB,r23 242(p6) br.cond.dptk.few 6f 243 ;; 244 cmp.ne p6,p0=r28,r23 // IPLTLSB 245(p6) br.cond.dptk.few 2b 246 247 // IPLTLSB 248 add r29=r24,r17 // S + A 249 ;; 250 st8 [r15]=r29,8 // fdesc:FP 251 ;; 252 st8 [r15]=gp // fdesc:GP 253 br.cond.sptk.few 2b 254 255 // REL64LSB 2564: 257 add r29=in0,r17 // BD + A 258 ;; 259 st8 [r15]=r29 // word64 260 br.cond.sptk.few 2b 261 262 // DIR64LSB 2635: 264 add r29=r24,r17 // S + A 265 ;; 266 st8 [r15]=r29 // word64 267 br.cond.sptk.few 2b 268 2696: 270 mov r29=r2 // FPTR64LSB 271 ;; 2727: 273 cmp.geu p6,p0=r29,r4 // end of fptrs? 274(p6) br.cond.dpnt.few 8f // can't find existing fptr 275 ld8 r17=[r29] // read function from fptr 276 ;; 277 cmp.eq p6,p0=r24,r17 // same function? 278 ;; 279(p6) st8 [r15]=r29 // reuse fptr 280(p6) br.cond.sptk.few 2b // done 281 add r29=16,r29 // next fptr 282 br.sptk.few 7b 2838: 284 mov r8=EFI_BUFFER_TOO_SMALL // failure return value 285 cmp.geu p6,p0=r4,r3 // space left? 286(p6) br.cond.dpnt.few 9f // bail out 287 st8 [r15]=r4 // install fptr 288 ;; 289 st8 [r4]=r24,8 // write fptr address 290 ;; 291 st8 [r4]=gp,8 // write fptr gp 292 br.cond.sptk.few 2b 293 2949: 295 mov ar.pfs=loc0 296 mov rp=loc1 297 ;; 298 br.ret.sptk.few rp 299END(_reloc) 300 301 // in0: system table 302 // in1: character 303ENTRY(_putchar, 2) 304 alloc loc0=ar.pfs,2,3,2,0 305 mov loc1=rp 306 mov loc2=gp 307 add sp=-32,sp 308 ;; 309 add r14=64,in0 // r14 = &in1->ConOut 310 ;; 311 ld8 r14=[r14] // r14 = in1->ConOut 312 ;; 313 add r15=8,r14 // r15 = &r14->OutputString 314 mov out0=r14 315 mov out1=sp 316 mov r16=sp 317 ;; 318 ld8 r15=[r15] // r15 = r14->OutputString 319 st2 [r16]=in1,2 // write character 320 ;; 321 st2 [r16]=r0 // terminate 322 ld8 r17=[r15],8 // function address 323 ;; 324 ld8 gp=[r15] // function gp 325 mov b6=r17 // transfer to branch register 326 ;; 327 br.call.sptk.few rp=b6 // call function 328 ;; 329 mov gp=loc2 // restore gp 330 mov ar.pfs=loc0 331 mov rp=loc1 332 add sp=32,sp 333 ;; 334 br.ret.sptk.few rp 335 336END(_putchar) 337 338 // in0: system table 339 // in1: string 340ENTRY(_puts, 2) 341 alloc loc0=ar.pfs,3,2,2,0 342 mov loc1=rp 343 ;; 344 mov out0=in0 345 ;; 3461: ld1 out1=[in1],1 347 ;; 348 cmp.eq p6,p0=r0,out1 349(p6) br.cond.dpnt.few 9f 350 ;; 351 br.call.sptk.few rp=_putchar 352 ;; 353 br.cond.sptk.few 1b 3549: 355 mov ar.pfs=loc0 356 mov rp=loc1 357 ;; 358 br.ret.sptk.few rp 359END(_puts) 360 361 // in0: system table 362 // in1: number 363ENTRY(_puthex, 2) 364 alloc loc0=ar.pfs,2,3,2,0 365 mov loc1=rp 366 mov loc2=ar.lc 367 ;; 368 mov out0=in0 369 mov ar.lc=15 370 ;; 3711: extr.u out1=in1,60,4 372 ;; 373 cmp.leu p6,p7=10,out1 374 ;; 375(p6) add out1='a'-10,out1 376(p7) add out1='0',out1 377 dep.z in1=in1,4,60 378 ;; 379 br.call.sptk.few rp=_putchar 380 ;; 381 br.cloop.sptk.few 1b 382 ;; 383 mov out1='\r' 384 ;; 385 br.call.sptk.few rp=_putchar 386 ;; 387 mov out1='\n' 388 ;; 389 br.call.sptk.few rp=_putchar 390 ;; 3919: 392 mov ar.pfs=loc0 393 mov rp=loc1 394 mov ar.lc=loc2 395 ;; 396 br.ret.sptk.few rp 397END(_puthex) 398 399 .data 400 .align 16 401 402fptr_storage: 403 .space 1024*16 // XXX 404fptr_storage_end: 405