Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 2726 → Rev 2782

/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*)
}
}