aboutsummaryrefslogtreecommitdiff
path: root/slof/fs/elf.fs
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2010-12-01 09:51:44 +1100
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2010-12-01 09:51:44 +1100
commitaaad509cdca2ed5f2c92a26f5279ec0e89c4fd5f (patch)
treedfffc0d8f3d21f6736b7f09219c95e2370052d8a /slof/fs/elf.fs
downloadSLOF-aaad509cdca2ed5f2c92a26f5279ec0e89c4fd5f.zip
SLOF-aaad509cdca2ed5f2c92a26f5279ec0e89c4fd5f.tar.gz
SLOF-aaad509cdca2ed5f2c92a26f5279ec0e89c4fd5f.tar.bz2
Initial import of slof-JX-1.7.0-4
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'slof/fs/elf.fs')
-rw-r--r--slof/fs/elf.fs305
1 files changed, 305 insertions, 0 deletions
diff --git a/slof/fs/elf.fs b/slof/fs/elf.fs
new file mode 100644
index 0000000..8f1c7b7
--- /dev/null
+++ b/slof/fs/elf.fs
@@ -0,0 +1,305 @@
+\ *****************************************************************************
+\ * 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
+;