routed - Apply FreeBSD-SA-14:21.routed
[dragonfly.git] / sys / boot / efi / libefi / arch / ia64 / start.S
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: src/sys/boot/efi/libefi/arch/ia64/start.S,v 1.6 2002/12/10 04:14:01 marcel Exp $
27  * $DragonFly: src/sys/boot/efi/libefi/arch/ia64/start.S,v 1.1 2003/11/10 06:08:33 dillon Exp $
28  */
29
30         .text
31
32 #include <machine/asm.h>
33                 
34 #define EFI_SUCCESS             0
35 #define EFI_LOAD_ERROR          1
36 #define EFI_BUFFER_TOO_SMALL    5
37         
38 #define DT_NULL         0       /* Terminating entry. */
39 #define DT_NEEDED       1       /* String table offset of a needed shared
40                                    library. */
41 #define DT_PLTRELSZ     2       /* Total size in bytes of PLT relocations. */
42 #define DT_PLTGOT       3       /* Processor-dependent address. */
43 #define DT_HASH         4       /* Address of symbol hash table. */
44 #define DT_STRTAB       5       /* Address of string table. */
45 #define DT_SYMTAB       6       /* Address of symbol table. */
46 #define DT_RELA         7       /* Address of ElfNN_Rela relocations. */
47 #define DT_RELASZ       8       /* Total size of ElfNN_Rela relocations. */
48 #define DT_RELAENT      9       /* Size of each ElfNN_Rela relocation entry. */
49 #define DT_STRSZ        10      /* Size of string table. */
50 #define DT_SYMENT       11      /* Size of each symbol table entry. */
51 #define DT_INIT         12      /* Address of initialization function. */
52 #define DT_FINI         13      /* Address of finalization function. */
53 #define DT_SONAME       14      /* String table offset of shared object
54                                    name. */
55 #define DT_RPATH        15      /* String table offset of library path. */
56 #define DT_SYMBOLIC     16      /* Indicates "symbolic" linking. */
57 #define DT_REL          17      /* Address of ElfNN_Rel relocations. */
58 #define DT_RELSZ        18      /* Total size of ElfNN_Rel relocations. */
59 #define DT_RELENT       19      /* Size of each ElfNN_Rel relocation. */
60 #define DT_PLTREL       20      /* Type of relocation used for PLT. */
61 #define DT_DEBUG        21      /* Reserved (not used). */
62 #define DT_TEXTREL      22      /* Indicates there may be relocations in
63                                    non-writable segments. */
64 #define DT_JMPREL       23      /* Address of PLT relocations. */
65
66 #define DT_COUNT        24      /* Number of defined d_tag values. */
67         
68 #define R_IA64_NONE             0       /* None */
69 #define R_IA64_DIR64MSB         0x26    /* word64 MSB   S + A */
70 #define R_IA64_DIR64LSB         0x27    /* word64 LSB   S + A */
71 #define R_IA64_FPTR64MSB        0x46    /* word64 MSB   @fptr(S + A) */
72 #define R_IA64_FPTR64LSB        0x47    /* word64 LSB   @fptr(S + A) */
73 #define R_IA64_REL64MSB         0x6e    /* word64 MSB   BD + A */
74 #define R_IA64_REL64LSB         0x6f    /* word64 LSB   BD + A */
75 #define R_IA64_IPLTLSB          0x81    /* function descriptor LSB speciaal */
76
77 ENTRY(_start, 2)
78         alloc   loc0=ar.pfs,2,3,3,0
79         mov     loc1=rp
80         movl    loc2=@gprel(ImageBase)
81         ;;
82         add     loc2=gp,loc2
83         ;;
84         mov     out0=loc2
85         mov     out1=in1
86         ;;
87         br.call.sptk.few rp=_reloc      // relocate image
88         
89         cmp.ne  p6,p0=EFI_SUCCESS,r8    // did it work?
90 (p6)    br.cond.dpnt.few 9f
91
92         mov     out0=in0                // image_handle
93         mov     out1=in1                // system_table
94         br.call.sptk.few rp=efi_main
95 9:
96         mov     ar.pfs=loc0
97         mov     rp=loc1
98         ;;
99         br.ret.sptk.few rp
100 END(_start)
101
102         // PLABEL for PE32+
103         .global _start_plabel
104         .section .plabel, "a"
105         .align  16
106 _start_plabel:  
107         .quad   _start
108         .quad   __gp
109         .previous
110
111         // A PE32+ relocation entry for the plabel
112
113         .section .reloc, "a"
114         .long   _start_plabel
115         .long   12
116         .short  (10 << 12) + 0
117         .short  (10 << 12) + 8
118         .previous
119
120 // in0: image base
121 // in1: system table
122 //
123 // XXX Assumes PLT relocations are of type Elf_Rela
124 //
125 // r2 = address of fptr_storage
126 // r3 = address of fptr_storage_end
127 // r4 = address of first free fptr
128 //
129 // r15 = r_offset
130 // r16 = r_info         -OR-    d_tag
131 // r17 = r_addend       -OR-    d_val (=d_ptr)
132 // r18 = address of .rela dynamic section
133 // r19 = size of .rela section
134 // r20 = size of .rela element (Elf_Rela)
135 // r21 = address of first PLT relocation
136 // r22 = size of PLT relocations
137 // r23 = relocation type
138 // r24 = address of symbol
139 // r28 = R_IA64_IPLTLSB
140 // f8 = address of symbol table
141 // f9 = size of symtab element
142
143 STATIC_ENTRY(_reloc, 2)
144         alloc   loc0=ar.pfs,2,2,0,0
145         ;;
146         mov     loc1=rp
147         movl    r29=@gprel(_DYNAMIC)    // find _DYNAMIC etc.
148         ;;
149         add     r15=r29,gp
150         movl    r29=@gprel(fptr_storage)
151         ;;
152         add     r2=r29,gp
153         movl    r29=@gprel(fptr_storage_end)
154         ;;
155         add     r3=r29,gp
156         mov     r4=r2
157         mov     r19=0
158         mov     r22=0
159         mov     r20=24
160         mov     r28=R_IA64_IPLTLSB
161         ;;
162 1:
163         ld8     r16=[r15],8             // read r15->d_tag
164         ;;
165         ld8     r17=[r15],8             // and r15->d_val
166         ;;
167         cmp.eq  p6,p0=DT_NULL,r16       // done?
168 (p6)    br.cond.dpnt.few 2f
169         ;;
170         cmp.eq  p6,p0=DT_RELA,r16       // rela section?
171         ;;
172 (p6)    add     r18=r17,in0
173         cmp.eq  p6,p0=DT_RELASZ,r16     // rela section size?
174         ;;
175 (p6)    mov     r19=r17
176         cmp.eq  p6,p0=DT_RELAENT,r16    // rela entry size?
177         ;;
178 (p6)    mov     r20=r17
179         cmp.eq  p6,p0=DT_JMPREL,r16     // PLT relocs?
180         ;;
181 (p6)    add     r21=r17,in0
182         cmp.eq  p6,p0=DT_PLTRELSZ,r16   // PLT relocs size?
183         ;;
184 (p6)    mov     r22=r17
185         cmp.eq  p6,p0=DT_SYMTAB,r16     // symbol table?
186         ;;
187 (p6)    add     r29=r17,in0
188         ;;
189 (p6)    setf.sig f8=r29
190         cmp.eq  p6,p0=DT_SYMENT,r16     // symbol entry size?
191         ;;
192 (p6)    setf.sig f9=r17
193         br.dptk 1b
194
195 2:
196         cmp.lt  p6,p0=0,r19
197 (p6)    br.cond.dptk    3f
198         ;;
199         mov     r19=r22
200         mov     r18=r21
201         mov     r21=0
202         mov     r22=0
203         ;;
204         cmp.lt  p6,p0=0,r19
205 (p6)    br.cond.dptk    3f
206         ;;
207         mov     r8=EFI_SUCCESS
208         br.dptk 9f
209 3:
210         ld8     r29=[r18],8             // read r_offset
211         ;;
212         ld8     r16=[r18],8             // read r_info
213         add     r15=r29,in0             // relocate r_offset
214         ;;
215         ld8     r17=[r18],8             // read r_addend
216         sub     r19=r19,r20             // update relasz
217         extr.u  r23=r16,0,32            // ELF64_R_TYPE(r16)
218         ;;
219         cmp.eq  p6,p0=R_IA64_NONE,r23
220 (p6)    br.cond.dpnt.few 2b
221         ;;
222         cmp.eq  p6,p0=R_IA64_REL64LSB,r23
223 (p6)    br.cond.dptk.few 4f
224         ;;
225         extr.u  r29=r16,32,32           // ELF64_R_SYM(r16)
226         ;;
227         setf.sig f10=r29                // so we can multiply
228         ;;
229         xma.lu  f10=f10,f9,f8           // f10=symtab + r_sym*syment
230         ;;
231         getf.sig r29=f10
232         ;;
233         add     r29=8,r29               // address of st_value
234         ;;
235         ld8     r29=[r29]               // read symbol value
236         ;;
237         add     r24=r29,in0             // relocate symbol value
238         ;;
239         cmp.eq  p6,p0=R_IA64_DIR64LSB,r23
240 (p6)    br.cond.dptk.few 5f
241         ;;
242         cmp.eq  p6,p0=R_IA64_FPTR64LSB,r23
243 (p6)    br.cond.dptk.few 6f
244         ;;
245         cmp.ne  p6,p0=r28,r23           // IPLTLSB
246 (p6)    br.cond.dptk.few 2b
247
248         // IPLTLSB
249         add     r29=r24,r17             // S + A
250         ;;
251         st8     [r15]=r29,8             // fdesc:FP
252         ;;
253         st8     [r15]=gp                // fdesc:GP
254         br.cond.sptk.few 2b
255
256         // REL64LSB
257 4:
258         add     r29=in0,r17             // BD + A
259         ;;
260         st8     [r15]=r29               // word64
261         br.cond.sptk.few 2b
262
263         // DIR64LSB
264 5:
265         add     r29=r24,r17             // S + A
266         ;;
267         st8     [r15]=r29               // word64
268         br.cond.sptk.few 2b
269
270 6:
271         mov     r29=r2                  // FPTR64LSB
272         ;;
273 7:
274         cmp.geu p6,p0=r29,r4            // end of fptrs?
275 (p6)    br.cond.dpnt.few 8f             // can't find existing fptr
276         ld8     r17=[r29]               // read function from fptr
277         ;;
278         cmp.eq  p6,p0=r24,r17           // same function?
279         ;;
280 (p6)    st8     [r15]=r29               // reuse fptr
281 (p6)    br.cond.sptk.few 2b             // done
282         add     r29=16,r29              // next fptr
283         br.sptk.few 7b
284 8:
285         mov     r8=EFI_BUFFER_TOO_SMALL // failure return value
286         cmp.geu p6,p0=r4,r3             // space left?
287 (p6)    br.cond.dpnt.few 9f             // bail out
288         st8     [r15]=r4                // install fptr
289         ;;
290         st8     [r4]=r24,8              // write fptr address
291         ;;
292         st8     [r4]=gp,8               // write fptr gp
293         br.cond.sptk.few 2b
294
295 9:
296         mov     ar.pfs=loc0
297         mov     rp=loc1
298         ;;
299         br.ret.sptk.few rp
300 END(_reloc)
301
302         .data
303         .align  16
304 fptr_storage:
305         .space  1024*16                 // XXX
306 fptr_storage_end: