blob: 8f1c7b737168b11394ce679a662aa1ee483a14e9 [file] [log] [blame]
\ *****************************************************************************
\ * Copyright (c) 2004, 2008 IBM Corporation
\ * All rights reserved.
\ * This program and the accompanying materials
\ * are made available under the terms of the BSD License
\ * which accompanies this distribution, and is available at
\ * http://www.opensource.org/licenses/bsd-license.php
\ *
\ * Contributors:
\ * IBM Corporation - initial implementation
\ ****************************************************************************/
\ ELF 32 bit header
STRUCT
/l field ehdr>e_ident
/c field ehdr>e_class
/c field ehdr>e_data
/c field ehdr>e_version
/c field ehdr>e_pad
/l field ehdr>e_ident_2
/l field ehdr>e_ident_3
/w field ehdr>e_type
/w field ehdr>e_machine
/l field ehdr>e_version
/l field ehdr>e_entry
/l field ehdr>e_phoff
/l field ehdr>e_shoff
/l field ehdr>e_flags
/w field ehdr>e_ehsize
/w field ehdr>e_phentsize
/w field ehdr>e_phnum
/w field ehdr>e_shentsize
/w field ehdr>e_shnum
/w field ehdr>e_shstrndx
END-STRUCT
\ ELF 32 bit program header
STRUCT
/l field phdr>p_type
/l field phdr>p_offset
/l field phdr>p_vaddr
/l field phdr>p_paddr
/l field phdr>p_filesz
/l field phdr>p_memsz
/l field phdr>p_flags
/l field phdr>p_align
END-STRUCT
\ Provide word to load image to an offset of vaddr
0 value elf-segment-offset
: xlate-vaddr32 ( programm-header-addr -- addr )
phdr>p_vaddr l@ elf-segment-offset +
;
\ ELF 64 bit header
STRUCT
/l field ehdr64>e_ident
/c field ehdr64>e_class
/c field ehdr64>e_data
/c field ehdr64>e_version
/c field ehdr64>e_pad
/l field ehdr64>e_ident_2
/l field ehdr64>e_ident_3
/w field ehdr64>e_type
/w field ehdr64>e_machine
/l field ehdr64>e_version
cell field ehdr64>e_entry
cell field ehdr64>e_phoff
cell field ehdr64>e_shoff
/l field ehdr64>e_flags
/w field ehdr64>e_ehsize
/w field ehdr64>e_phentsize
/w field ehdr64>e_phnum
/w field ehdr64>e_shentsize
/w field ehdr64>e_shnum
/w field ehdr64>e_shstrndx
END-STRUCT
\ ELF 64 bit program header
STRUCT
/l field phdr64>p_type
/l field phdr64>p_flags
cell field phdr64>p_offset
cell field phdr64>p_vaddr
cell field phdr64>p_paddr
cell field phdr64>p_filesz
cell field phdr64>p_memsz
cell field phdr64>p_align
END-STRUCT
\ Claim memory for segment
\ Abort, if no memory available
false value elf-claim?
0 value last-claim
: claim-segment ( file-addr program-header-addr -- )
elf-claim? IF
>r
here last-claim , to last-claim \ Setup ptr to last claim
\ Put addr and size ain the data space
r@ phdr>p_vaddr l@ dup , r> phdr>p_memsz l@ dup , ( file-addr addr size )
0 ['] claim CATCH IF ABORT" Memory for ELF file already in use " THEN
THEN
2drop
;
: claim-segment64 ( file-addr program-header-addr -- )
elf-claim? IF
>r
here last-claim , to last-claim \ Setup ptr to last claim
\ Put addr and size ain the data space
r@ phdr64>p_vaddr @ dup , r> phdr64>p_memsz @ dup , ( file-addr addr size )
0 ['] claim CATCH IF ABORT" Memory for ELF file already in use " THEN
THEN
2drop
;
: load-segment ( file-addr program-header-addr -- )
>r
( file-addr R: program-header-addr )
\ Copy into storage
r@ phdr>p_offset l@ + r@ xlate-vaddr32 r@ phdr>p_filesz l@ move
( R: programm-header-addr )
\ Clear BSS
r@ xlate-vaddr32 r@ phdr>p_filesz l@ +
r@ phdr>p_memsz l@ r@ phdr>p_filesz l@ - erase
( R: programm-header-addr )
\ Flush cache
r@ xlate-vaddr32 r> phdr>p_memsz l@ dup 0= IF 2drop ELSE flushcache THEN
;
: load-segments ( file-addr -- )
( file-addr )
dup dup ehdr>e_phoff l@ + \ Calculate program header address
( file-addr program-header-addr )
over ehdr>e_phnum w@ 0 ?DO \ loop e_phnum times
( file-addr program-header-addr )
dup phdr>p_type l@ 1 = IF \ PT_LOAD ?
( file-addr program-header-addr )
2dup claim-segment \ claim segment
( file-addr program-header-addr )
2dup load-segment THEN \ copy segment
( file-addr program-header-addr )
over ehdr>e_phentsize w@ + LOOP \ step to next header
( file-addr program-header-addr )
over ehdr>e_entry l@
( file-addr program-header-addr )
nip nip \ cleanup
;
: load-segment64 ( file-addr program-header-addr -- )
>r
( file-addr R: program-header-addr )
\ Copy into storage
r@ phdr64>p_offset @ + r@ phdr64>p_vaddr @ r@ phdr64>p_filesz @ move
( R: programm-header-addr )
\ Clear BSS
r@ phdr64>p_vaddr @ r@ phdr64>p_filesz @ +
r@ phdr64>p_memsz @ r@ phdr64>p_filesz @ - erase
( R: programm-header-addr )
\ Flush cache
r@ phdr64>p_vaddr @ r> phdr64>p_memsz @ dup 0= IF 2drop ELSE flushcache THEN
;
: load-segments64 ( file-addr -- entry )
( file-addr )
dup dup ehdr64>e_phoff @ + \ Calculate program header address
( file-addr program-header-addr )
over ehdr64>e_phnum w@ 0 ?DO \ loop e_phnum times
( file-addr program-header-addr )
dup phdr64>p_type l@ 1 = IF \ PT_LOAD ?
( file-addr program-header-addr )
2dup claim-segment64 \ claim segment
( file-addr program-header-addr )
2dup load-segment64 THEN \ copy segment
( file-addr program-header-addr )
over ehdr64>e_phentsize w@ + LOOP \ step to next header
( file-addr program-header-addr )
over ehdr64>e_entry @
( file-addr program-header-addr entry )
nip nip \ cleanup
;
\ Return type of ELF image, abort if not valid
\ 1: 32 Bit PPC image
\ 2: 64 Bit PPC image
\ 5: 32 Bit SPU image
: elf-check-file ( file-addr -- image-type )
( file-addr )
dup ehdr>e_ident l@-be 7f454c46 <> IF
ABORT" Not an ELF executable"
THEN
( file-addr )
dup ehdr>e_data c@
?bigendian IF
2 <> ABORT" Not a Big Endian ELF file"
ELSE
2 = ABORT" Not a Little Endian ELF file"
THEN
( file-addr )
dup ehdr>e_type w@ 2 <> ABORT" Not an ELF executable"
( file-addr )
dup ehdr>e_machine w@
CASE
14 OF ehdr>e_class c@ ENDOF \ PPC 32 bit executable
15 OF ehdr>e_class c@ ENDOF \ PPC 64 bit executable
17 OF ehdr>e_class c@ 4 or ENDOF \ SPU 32 bit executable
dup OF drop ABORT" Not a PPC / SPU ELF executable" ENDOF
ENDCASE
;
: load-elf32 ( file-addr -- entry )
( file-addr)
load-segments
;
: load-elf32-claim ( file-addr -- claim-list entry )
true to elf-claim?
0 to last-claim
['] load-elf32 CATCH IF false to elf-claim? ABORT THEN
last-claim swap
false to elf-claim?
;
: load-elf64 ( file-addr -- entry )
( file-addr)
load-segments64
;
: load-elf64-claim ( file-addr -- claim-list entry )
true to elf-claim?
0 to last-claim
['] load-elf64 CATCH IF false to elf-claim? ABORT THEN
last-claim swap
false to elf-claim?
;
: load-elf-file ( file-addr -- entry 32-bit )
( file-addr )
dup elf-check-file
( file-addr 1|2|x )
CASE
1 OF 0 to elf-segment-offset load-elf32 true ENDOF
2 OF 0 to elf-segment-offset load-elf64 false ENDOF
5 OF load-elf32 true ENDOF
dup OF true ABORT" load-elf-file: Not valid image" ENDOF
ENDCASE
;
\ Method to load SPU image
: elf-spu-load ( ls-start-addr file-addr -- entry )
swap to elf-segment-offset
load-elf-file drop
;
\ Release memory claimed before
: elf-release ( claim-list -- )
BEGIN
dup cell+ ( claim-list claim-list-addr )
dup @ swap cell+ @ ( claim-list claim-list-addr claim-list-sz )
release ( claim-list )
@ dup 0= ( Next-element )
UNTIL
drop
;