/tags/0.3.0/boot/arch/ia64/loader/gefi/gnuefi/reloc_ia32.c |
---|
0,0 → 1,103 |
/* reloc_ia32.c - position independent x86 ELF shared object relocator |
Copyright (C) 1999 Hewlett-Packard Co. |
Contributed by David Mosberger <davidm@hpl.hp.com>. |
This file is part of GNU-EFI, the GNU EFI development environment. |
GNU EFI is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
the Free Software Foundation; either version 2, or (at your option) |
any later version. |
GNU EFI is distributed in the hope that it will be useful, |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
GNU General Public License for more details. |
You should have received a copy of the GNU General Public License |
along with GNU EFI; see the file COPYING. If not, write to the Free |
Software Foundation, 59 Temple Place - Suite 330, Boston, MA |
02111-1307, USA. */ |
#include <elf.h> |
#include <link.h> /* get _DYNAMIC decl and ElfW and ELFW macros */ |
#undef NULL |
#define uint64_t efi_uint64_t |
#define int64_t efi_int64_t |
#define uint32_t efi_uint32_t |
#define int32_t efi_int32_t |
#define uint16_t efi_uint16_t |
#define int16_t efi_int16_t |
#define uint8_t efi_uint8_t |
#define int8_t efi_int8_t |
#undef NULL |
#define uint64_t efi_uint64_t |
#define int64_t efi_int64_t |
#define uint32_t efi_uint32_t |
#define int32_t efi_int32_t |
#define uint16_t efi_uint16_t |
#define int16_t efi_int16_t |
#define uint8_t efi_uint8_t |
#define int8_t efi_int8_t |
#include <efi.h> |
#include <efilib.h> |
int |
_relocate (long ldbase, ElfW(Dyn) *dyn, EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) |
{ |
extern EFI_STATUS efi_main (EFI_HANDLE, EFI_SYSTEM_TABLE *); |
long relsz = 0, relent = 0; |
ElfW(Rel) *rel = 0; |
int i; |
for (i = 0; dyn[i].d_tag != DT_NULL; ++i) { |
switch (dyn[i].d_tag) { |
case DT_REL: |
rel = (ElfW(Rel)*) ((long) dyn[i].d_un.d_ptr + ldbase); |
break; |
case DT_RELSZ: |
relsz = dyn[i].d_un.d_val; |
break; |
case DT_RELENT: |
relent = dyn[i].d_un.d_val; |
break; |
case DT_RELA: |
break; |
default: |
break; |
} |
} |
while (relsz > 0) { |
if (!rel || relent == 0) |
return EFI_LOAD_ERROR; |
/* apply the relocs */ |
switch (ELF32_R_TYPE (rel->r_info)) { |
case R_386_NONE: |
break; |
case R_386_RELATIVE: |
{ |
long *addr; |
addr = (long *) (ldbase + rel->r_offset); |
*addr += ldbase; |
break; |
} |
default: |
return EFI_LOAD_ERROR; |
} |
rel = (ElfW(Rel)*) ((char *) rel + relent); |
relsz -= relent; |
} |
return EFI_SUCCESS; |
} |
/tags/0.3.0/boot/arch/ia64/loader/gefi/gnuefi/crt0-efi-ia32.S |
---|
0,0 → 1,62 |
/* crt0-efi-ia32.S - x86 EFI startup code. |
Copyright (C) 1999 Hewlett-Packard Co. |
Contributed by David Mosberger <davidm@hpl.hp.com>. |
This file is part of GNU-EFI, the GNU EFI development environment. |
GNU EFI is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
the Free Software Foundation; either version 2, or (at your option) |
any later version. |
GNU EFI is distributed in the hope that it will be useful, |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
GNU General Public License for more details. |
You should have received a copy of the GNU General Public License |
along with GNU EFI; see the file COPYING. If not, write to the Free |
Software Foundation, 59 Temple Place - Suite 330, Boston, MA |
02111-1307, USA. */ |
.text |
.align 4 |
.globl _start |
_start: |
pushl %ebp |
movl %esp,%ebp |
pushl 12(%ebp) # copy "image" argument |
pushl 8(%ebp) # copy "systab" argument |
call 0f |
0: popl %eax |
movl %eax,%ebx |
addl $ImageBase-0b,%eax # %eax = ldbase |
addl $_DYNAMIC-0b,%ebx # %ebx = _DYNAMIC |
pushl %ebx # pass _DYNAMIC as second argument |
pushl %eax # pass ldbase as first argument |
call _relocate |
popl %ebx |
popl %ebx |
testl %eax,%eax |
jne .exit |
call efi_main # call app with "image" and "systab" argument |
.exit: leave |
ret |
// hand-craft a dummy .reloc section so EFI knows it's a relocatable executable: |
.data |
dummy: .long 0 |
#define IMAGE_REL_ABSOLUTE 0 |
.section .reloc, "a" |
.long dummy // Page RVA |
.long 10 // Block Size (2*4+2) |
.word (IMAGE_REL_ABSOLUTE<<12) + 0 // reloc for dummy |
/tags/0.3.0/boot/arch/ia64/loader/gefi/gnuefi/elf_ia32_efi.lds |
---|
0,0 → 1,62 |
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") |
OUTPUT_ARCH(i386) |
ENTRY(_start) |
SECTIONS |
{ |
. = 0; |
ImageBase = .; |
.hash : { *(.hash) } /* this MUST come first! */ |
. = ALIGN(4096); |
.text : |
{ |
*(.text) |
*(.text.*) |
*(.gnu.linkonce.t.*) |
} |
.reloc : |
{ |
*(.reloc) |
} |
. = ALIGN(4096); |
.data : |
{ |
*(.rodata*) |
*(.data) |
*(.data1) |
*(.data.*) |
*(.sdata) |
*(.got.plt) |
*(.got) |
/* the EFI loader doesn't seem to like a .bss section, so we stick |
it all into .data: */ |
*(.sbss) |
*(.scommon) |
*(.dynbss) |
*(.bss) |
*(COMMON) |
} |
. = ALIGN(4096); |
.dynamic : { *(.dynamic) } |
. = ALIGN(4096); |
.rel : |
{ |
*(.rel.data) |
*(.rel.data.*) |
*(.rel.got) |
*(.rel.stab) |
*(.data.rel.ro.local) |
*(.data.rel.local) |
*(.data.rel.ro) |
*(.data.rel*) |
} |
. = ALIGN(4096); |
.dynsym : { *(.dynsym) } |
. = ALIGN(4096); |
.dynstr : { *(.dynstr) } |
. = ALIGN(4096); |
/DISCARD/ : |
{ |
*(.rel.reloc) |
*(.eh_frame) |
} |
} |
/tags/0.3.0/boot/arch/ia64/loader/gefi/gnuefi/reloc_ia64.S |
---|
0,0 → 1,212 |
/* 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>. |
This file is part of GNU-EFI, the GNU EFI development environment. |
GNU EFI is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
the Free Software Foundation; either version 2, or (at your option) |
any later version. |
GNU EFI is distributed in the hope that it will be useful, |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
GNU General Public License for more details. |
You should have received a copy of the GNU General Public License |
along with GNU EFI; see the file COPYING. If not, write to the Free |
Software Foundation, 59 Temple Place - Suite 330, Boston, MA |
02111-1307, USA. */ |
/* |
* 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: |
/tags/0.3.0/boot/arch/ia64/loader/gefi/gnuefi/crt0-efi-ia64.S |
---|
0,0 → 1,74 |
/* crt0-efi-ia64.S - IA-64 EFI startup code. |
Copyright (C) 1999 Hewlett-Packard Co. |
Contributed by David Mosberger <davidm@hpl.hp.com>. |
This file is part of GNU-EFI, the GNU EFI development environment. |
GNU EFI is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
the Free Software Foundation; either version 2, or (at your option) |
any later version. |
GNU EFI is distributed in the hope that it will be useful, |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
GNU General Public License for more details. |
You should have received a copy of the GNU General Public License |
along with GNU EFI; see the file COPYING. If not, write to the Free |
Software Foundation, 59 Temple Place - Suite 330, Boston, MA |
02111-1307, USA. */ |
.text |
.psr abi64 |
.psr lsb |
.lsb |
.proc _start |
_start: |
alloc loc0=ar.pfs,2,2,2,0 |
mov loc1=rp |
movl out0=@gprel(ImageBase) // out0 <- ImageBase (ldbase) |
;; |
add out0=out0,gp |
movl out1=@gprel(_DYNAMIC) // out1 <- _DYNAMIC |
;; // avoid WAW on CFM |
add out1=out1,gp |
br.call.sptk.few rp=_relocate |
.Lret0: |
cmp.ne p6,p0=r0,r8 // r8 == EFI_SUCCESS? |
(p6) br.cond.sptk.few .exit // no -> |
.Lret1: |
mov out0=in0 // image handle |
mov out1=in1 // systab |
br.call.sptk.few rp=efi_main |
.Lret2: |
.exit: |
mov ar.pfs=loc0 |
mov rp=loc1 |
;; |
br.ret.sptk.few rp |
.endp _start |
// PE32+ wants a PLABEL, not the code address of the entry point: |
.align 16 |
.global _start_plabel |
.section .plabel, "a" |
_start_plabel: |
data8 _start |
data8 __gp |
// hand-craft a .reloc section for the plabel: |
#define IMAGE_REL_BASED_DIR64 10 |
.section .reloc, "a" |
data4 _start_plabel // Page RVA |
data4 12 // Block Size (2*4+2*2) |
data2 (IMAGE_REL_BASED_DIR64<<12) + 0 // reloc for plabel's entry point |
data2 (IMAGE_REL_BASED_DIR64<<12) + 8 // reloc for plabel's global pointer |
/tags/0.3.0/boot/arch/ia64/loader/gefi/gnuefi/Makefile |
---|
0,0 → 1,44 |
# |
# Copyright (C) 1999-2001 Hewlett-Packard Co. |
# Contributed by David Mosberger <davidm@hpl.hp.com> |
# Contributed by Stephane Eranian <eranian@hpl.hp.com> |
# |
# This file is part of the gnu-efi package. |
# |
# GNU-EFI is free software; you can redistribute it and/or modify |
# it under the terms of the GNU General Public License as published by |
# the Free Software Foundation; either version 2, or (at your option) |
# any later version. |
# |
# GNU-EFI is distributed in the hope that it will be useful, |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
# GNU General Public License for more details. |
# |
# You should have received a copy of the GNU General Public License |
# along with GNU-EFI; see the file COPYING. If not, write to the Free |
# Software Foundation, 59 Temple Place - Suite 330, Boston, MA |
# 02111-1307, USA. |
# |
include ../Make.defaults |
CDIR=$(TOPDIR)/.. |
FILES = reloc_$(ARCH) |
OBJS = $(FILES:%=%.o) |
TARGETS = crt0-efi-$(ARCH).o libgnuefi.a |
all: $(TARGETS) |
libgnuefi.a: libgnuefi.a($(OBJS)) |
clean: |
rm -f $(TARGETS) *~ *.o $(OBJS) |
install: |
mkdir -p $(INSTALLROOT)/lib |
$(INSTALL) -m 644 $(TARGETS) $(INSTALLROOT)/lib |
$(INSTALL) -m 644 elf_$(ARCH)_efi.lds $(INSTALLROOT)/lib |
include ../Make.rules |
/tags/0.3.0/boot/arch/ia64/loader/gefi/gnuefi/elf_ia64_efi.lds |
---|
0,0 → 1,70 |
OUTPUT_FORMAT("elf64-ia64-little") |
OUTPUT_ARCH(ia64) |
ENTRY(_start_plabel) |
SECTIONS |
{ |
. = 0; |
ImageBase = .; |
.hash : { *(.hash) } /* this MUST come first! */ |
. = ALIGN(4096); |
.text : |
{ |
*(.text) |
*(.text.*) |
*(.gnu.linkonce.t.*) |
} |
. = ALIGN(4096); |
__gp = ALIGN (8) + 0x200000; |
.sdata : |
{ |
*(.got.plt) |
*(.got) |
*(.srodata) |
*(.sdata) |
*(.sbss) |
*(.scommon) |
} |
. = ALIGN(4096); |
.data : |
{ |
*(.rodata*) |
*(.ctors) |
*(.data*) |
*(.gnu.linkonce.d*) |
*(.plabel) /* data whose relocs we want to ignore */ |
/* the EFI loader doesn't seem to like a .bss section, so we stick |
it all into .data: */ |
*(.dynbss) |
*(.bss) |
*(COMMON) |
} |
. = ALIGN(4096); |
.dynamic : { *(.dynamic) } |
. = ALIGN(4096); |
.rela : |
{ |
*(.rela.text) |
*(.rela.data*) |
*(.rela.sdata) |
*(.rela.got) |
*(.rela.gnu.linkonce.d*) |
*(.rela.stab) |
*(.rela.ctors) |
} |
. = ALIGN(4096); |
.reloc : /* This is the PECOFF .reloc section! */ |
{ |
*(.reloc) |
} |
. = ALIGN(4096); |
.dynsym : { *(.dynsym) } |
. = ALIGN(4096); |
.dynstr : { *(.dynstr) } |
/DISCARD/ : |
{ |
*(.rela.plabel) |
*(.rela.reloc) |
*(.IA_64.unwind*) |
*(.IA64.unwind*) |
} |
} |