aboutsummaryrefslogtreecommitdiff
path: root/gnu-efi/gnu-efi-3.0/gnuefi/reloc_ia64.S
diff options
context:
space:
mode:
Diffstat (limited to 'gnu-efi/gnu-efi-3.0/gnuefi/reloc_ia64.S')
-rw-r--r--gnu-efi/gnu-efi-3.0/gnuefi/reloc_ia64.S227
1 files changed, 227 insertions, 0 deletions
diff --git a/gnu-efi/gnu-efi-3.0/gnuefi/reloc_ia64.S b/gnu-efi/gnu-efi-3.0/gnuefi/reloc_ia64.S
new file mode 100644
index 0000000..40203bf
--- /dev/null
+++ b/gnu-efi/gnu-efi-3.0/gnuefi/reloc_ia64.S
@@ -0,0 +1,227 @@
+/* reloc_ia64.S - position independent IA-64 ELF shared object relocator
+ Copyright (C) 1999 Hewlett-Packard Co.
+ Contributed by David Mosberger <davidm@hpl.hp.com>.
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+ * Neither the name of Hewlett-Packard Co. nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+*/
+
+/*
+ * This is written in assembly because the entire code needs to be position
+ * independent. Note that the compiler does not generate code that's position
+ * independent by itself because it relies on the global offset table being
+ * relocated.
+ */
+ .text
+ .psr abi64
+ .psr lsb
+ .lsb
+
+/*
+ * This constant determines how many R_IA64_FPTR64LSB relocations we
+ * can deal with. If you get EFI_BUFFER_TOO_SMALL errors, you may
+ * need to increase this number.
+ */
+#define MAX_FUNCTION_DESCRIPTORS 750
+
+#define ST_VALUE_OFF 8 /* offset of st_value in elf sym */
+
+#define EFI_SUCCESS 0
+#define EFI_LOAD_ERROR 1
+#define EFI_BUFFER_TOO_SMALL 5
+
+#define DT_NULL 0 /* Marks end of dynamic section */
+#define DT_RELA 7 /* Address of Rela relocs */
+#define DT_RELASZ 8 /* Total size of Rela relocs */
+#define DT_RELAENT 9 /* Size of one Rela reloc */
+#define DT_SYMTAB 6 /* Address of symbol table */
+#define DT_SYMENT 11 /* Size of one symbol table entry */
+
+#define R_IA64_NONE 0
+#define R_IA64_REL64MSB 0x6e
+#define R_IA64_REL64LSB 0x6f
+#define R_IA64_DIR64MSB 0x26
+#define R_IA64_DIR64LSB 0x27
+#define R_IA64_FPTR64MSB 0x46
+#define R_IA64_FPTR64LSB 0x47
+
+#define ldbase in0 /* load address (address of .text) */
+#define dyn in1 /* address of _DYNAMIC */
+
+#define d_tag r16
+#define d_val r17
+#define rela r18
+#define relasz r19
+#define relaent r20
+#define addr r21
+#define r_info r22
+#define r_offset r23
+#define r_addend r24
+#define r_type r25
+#define r_sym r25 /* alias of r_type ! */
+#define fptr r26
+#define fptr_limit r27
+#define symtab f8
+#define syment f9
+#define ftmp f10
+
+#define target r16
+#define val r17
+
+#define NLOC 0
+
+#define Pnull p6
+#define Prela p7
+#define Prelasz p8
+#define Prelaent p9
+#define Psymtab p10
+#define Psyment p11
+
+#define Pnone p6
+#define Prel p7
+#define Pfptr p8
+
+#define Pmore p6
+
+#define Poom p6 /* out-of-memory */
+
+ .global _relocate
+ .proc _relocate
+_relocate:
+ alloc r2=ar.pfs,2,0,0,0
+ movl fptr = @gprel(fptr_mem_base)
+ ;;
+ add fptr = fptr, gp
+ movl fptr_limit = @gprel(fptr_mem_limit)
+ ;;
+ add fptr_limit = fptr_limit, gp
+
+search_dynamic:
+ ld8 d_tag = [dyn],8
+ ;;
+ ld8 d_val = [dyn],8
+ cmp.eq Pnull,p0 = DT_NULL,d_tag
+(Pnull) br.cond.sptk.few apply_relocs
+ cmp.eq Prela,p0 = DT_RELA,d_tag
+ cmp.eq Prelasz,p0 = DT_RELASZ,d_tag
+ cmp.eq Psymtab,p0 = DT_SYMTAB,d_tag
+ cmp.eq Psyment,p0 = DT_SYMENT,d_tag
+ cmp.eq Prelaent,p0 = DT_RELAENT,d_tag
+ ;;
+(Prela) add rela = d_val, ldbase
+(Prelasz) mov relasz = d_val
+(Prelaent) mov relaent = d_val
+(Psymtab) add val = d_val, ldbase
+ ;;
+(Psyment) setf.sig syment = d_val
+ ;;
+(Psymtab) setf.sig symtab = val
+ br.sptk.few search_dynamic
+
+apply_loop:
+ ld8 r_offset = [rela]
+ add addr = 8,rela
+ sub relasz = relasz,relaent
+ ;;
+
+ ld8 r_info = [addr],8
+ ;;
+ ld8 r_addend = [addr]
+ add target = ldbase, r_offset
+
+ add rela = rela,relaent
+ extr.u r_type = r_info, 0, 32
+ ;;
+ cmp.eq Pnone,p0 = R_IA64_NONE,r_type
+ cmp.eq Prel,p0 = R_IA64_REL64LSB,r_type
+ cmp.eq Pfptr,p0 = R_IA64_FPTR64LSB,r_type
+(Prel) br.cond.sptk.few apply_REL64
+ ;;
+ cmp.eq Prel,p0 = R_IA64_DIR64LSB,r_type // treat DIR64 just like REL64
+
+(Pnone) br.cond.sptk.few apply_relocs
+(Prel) br.cond.sptk.few apply_REL64
+(Pfptr) br.cond.sptk.few apply_FPTR64
+
+ mov r8 = EFI_LOAD_ERROR
+ br.ret.sptk.few rp
+
+apply_relocs:
+ cmp.ltu Pmore,p0=0,relasz
+(Pmore) br.cond.sptk.few apply_loop
+
+ mov r8 = EFI_SUCCESS
+ br.ret.sptk.few rp
+
+apply_REL64:
+ ld8 val = [target]
+ ;;
+ add val = val,ldbase
+ ;;
+ st8 [target] = val
+ br.cond.sptk.few apply_relocs
+
+ // FPTR relocs are a bit more interesting: we need to lookup
+ // the symbol's value in symtab, allocate 16 bytes of memory,
+ // store the value in [target] in the first and the gp in the
+ // second dword.
+apply_FPTR64:
+ st8 [target] = fptr
+ extr.u r_sym = r_info,32,32
+ add target = 8,fptr
+ ;;
+
+ setf.sig ftmp = r_sym
+ mov r8=EFI_BUFFER_TOO_SMALL
+ ;;
+ cmp.geu Poom,p0 = fptr,fptr_limit
+
+ xma.lu ftmp = ftmp,syment,symtab
+(Poom) br.ret.sptk.few rp
+ ;;
+ getf.sig addr = ftmp
+ st8 [target] = gp
+ ;;
+ add addr = ST_VALUE_OFF, addr
+ ;;
+ ld8 val = [addr]
+ ;;
+ add val = val,ldbase
+ ;;
+ st8 [fptr] = val,16
+ br.cond.sptk.few apply_relocs
+
+ .endp _relocate
+
+ .data
+ .align 16
+fptr_mem_base:
+ .space MAX_FUNCTION_DESCRIPTORS*16
+fptr_mem_limit: