diff options
author | Nikunj A Dadhania <nikunj@linux.vnet.ibm.com> | 2013-12-06 10:10:01 +1100 |
---|---|---|
committer | Alexey Kardashevskiy <aik@ozlabs.ru> | 2014-02-04 19:49:46 +1100 |
commit | c2358afb40d42fa1f9c6ffb59c32f803bb3aa44d (patch) | |
tree | 9545dd4d56240c0545193c94587ff2a043289985 | |
parent | 41a34055032ac5c64811238fe72f514634285c09 (diff) | |
download | SLOF-c2358afb40d42fa1f9c6ffb59c32f803bb3aa44d.zip SLOF-c2358afb40d42fa1f9c6ffb59c32f803bb3aa44d.tar.gz SLOF-c2358afb40d42fa1f9c6ffb59c32f803bb3aa44d.tar.bz2 |
Add support for 64bit LE ABI v1 and v2 support
Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
--
v2: With the parameters changed for go-64, kernel loading from commandline broke
v3: (client-exec) calls start-elf64 directly, fix args
-rw-r--r-- | board-qemu/slof/OF.fs | 6 | ||||
-rw-r--r-- | include/libelf.h | 1 | ||||
-rw-r--r-- | lib/libelf/elf.c | 13 | ||||
-rw-r--r-- | lib/libelf/elf64.c | 7 | ||||
-rw-r--r-- | slof/fs/boot.fs | 56 | ||||
-rw-r--r-- | slof/fs/loaders.fs | 12 |
6 files changed, 77 insertions, 18 deletions
diff --git a/board-qemu/slof/OF.fs b/board-qemu/slof/OF.fs index a4f1064..061df66 100644 --- a/board-qemu/slof/OF.fs +++ b/board-qemu/slof/OF.fs @@ -240,14 +240,12 @@ set-default-console 0 VALUE direct-ram-boot-base 0 VALUE direct-ram-boot-size -CREATE boot-opd 10 ALLOT : (boot-ram) direct-ram-boot-size 0<> IF ." Booting from memory..." cr - direct-ram-boot-base boot-opd ! - 0 boot-opd 8 + ! - s" boot-opd to go-entry" evaluate + s" go-args 2@ " evaluate + direct-ram-boot-base 0 0 s" true state-valid ! " evaluate s" disable-watchdog go-64" evaluate THEN diff --git a/include/libelf.h b/include/libelf.h index 495d697..ee55375 100644 --- a/include/libelf.h +++ b/include/libelf.h @@ -89,6 +89,7 @@ unsigned long elf_load_segments64(void *file_addr, signed long offset, long elf_get_base_addr(void *file_addr); long elf_get_base_addr32(void *file_addr); long elf_get_base_addr64(void *file_addr); +uint32_t elf_get_eflags_64(void *file_addr); void elf_relocate64(void *file_addr, signed long offset); diff --git a/lib/libelf/elf.c b/lib/libelf/elf.c index 1340103..27fd51d 100644 --- a/lib/libelf/elf.c +++ b/lib/libelf/elf.c @@ -80,7 +80,9 @@ elf_check_file(unsigned long *file_addr) * @param pre_load handler that is called before copying a segment * @param post_load handler that is called after copying a segment * @return 1 for a 32 bit file - * 2 for a 64 bit file + * 2 for a 64 bit BE file + * 3 for a 64 bit LE ABIv1 file + * 3 for a 64 bit LE ABIv2 file * anything else means an error during load */ int @@ -89,6 +91,7 @@ elf_load_file(void *file_addr, unsigned long *entry, void (*post_load)(void*, long)) { int type = elf_check_file(file_addr); + struct ehdr *ehdr = (struct ehdr *) file_addr; switch (type) { case 1: @@ -96,9 +99,15 @@ elf_load_file(void *file_addr, unsigned long *entry, break; case 2: *entry = elf_load_segments64(file_addr, 0, pre_load, post_load); + if (ehdr->ei_data != ELFDATA2MSB) { + uint32_t flags = elf_get_eflags_64(file_addr); + if ((flags & 0x3) == 2) + type = 4; /* LE64 ABIv2 */ + else + type = 3; /* LE64 ABIv1 */ + } break; } - return type; } diff --git a/lib/libelf/elf64.c b/lib/libelf/elf64.c index faddbfb..62ac885 100644 --- a/lib/libelf/elf64.c +++ b/lib/libelf/elf64.c @@ -462,3 +462,10 @@ elf_byteswap_header64(void *file_addr) phdr = (struct phdr64 *)(((uint8_t *)phdr) + ehdr->e_phentsize); } } + +uint32_t elf_get_eflags_64(void *file_addr) +{ + struct ehdr64 *ehdr = (struct ehdr64 *) file_addr; + + return ehdr->e_flags; +} diff --git a/slof/fs/boot.fs b/slof/fs/boot.fs index c9cc3b1..97eca1e 100644 --- a/slof/fs/boot.fs +++ b/slof/fs/boot.fs @@ -70,13 +70,51 @@ defer go ( -- ) THEN -6d boot-exception-handler ABORT ; -: go-64 ( -- ) - state-valid @ IF - 0 ciregs >r3 ! 0 ciregs >r4 ! - go-args 2@ go-entry start-elf64 client-data - claim-list elf-release 0 to claim-list - THEN - -6d boot-exception-handler ABORT + +: go-64 ( args len entry r2 r12 -- ) + 0 ciregs >r3 ! 0 ciregs >r4 ! + start-elf64 client-data + claim-list elf-release 0 to claim-list +; + +: go-64-be ( -- ) + state-valid @ IF + go-args 2@ + go-entry @ + go-entry 8 + @ + 0 go-64 + THEN + -6d boot-exception-handler ABORT +; + +\ FIXME : how to do this correctly, currently this hangs. +: set-le ( -- ) + ." Changing endianness " + msr@ 1 or msr! + ." done " + msr@ . cr +; + +: go-64-lev1 + state-valid @ IF + go-args 2@ + go-entry @ xbflip + go-entry 8 + @ xbflip + 0 + \ set-le + go-64 + THEN + -6d boot-exception-handler ABORT +; + +: go-64-lev2 + state-valid @ IF + go-args 2@ + go-entry 0 go-entry + \ set-le + go-64 + THEN + -6d boot-exception-handler ABORT ; : load-elf-init ( arg len file-addr -- success ) @@ -91,7 +129,9 @@ defer go ( -- ) ( arg len true claim-list entry elftype ) CASE 1 OF ['] go-32 ENDOF ( arg len true claim-list entry go ) - 2 OF ['] go-64 ENDOF ( arg len true claim-list entry go ) + 2 OF ['] go-64-be ENDOF ( arg len true claim-list entry go ) + 3 OF ['] go-64-lev1 ENDOF ( arg len true claim-list entry go ) + 4 OF ['] go-64-lev2 ENDOF ( arg len true claim-list entry go ) dup OF ['] no-go to go 2drop 3drop false EXIT ENDOF ( false ) ENDCASE diff --git a/slof/fs/loaders.fs b/slof/fs/loaders.fs index 97545b7..3603dd4 100644 --- a/slof/fs/loaders.fs +++ b/slof/fs/loaders.fs @@ -19,9 +19,11 @@ CREATE load-list 2 cells allot load-list 2 cells erase msr@ 7fffffffffffffff and 2000 or ciregs >srr1 ! call-client ; -: start-elf64 ( arg len entry -- ) - msr@ 2000 or ciregs >srr1 ! - dup 8 + @ ciregs >r2 ! @ call-client \ entry point is pointer to .opd +: start-elf64 ( arg len entry r2 r12 -- ) + msr@ 2000 or ciregs >srr1 ! + ciregs >r12 ! + ciregs >r2 ! + call-client \ entry point is pointer to .opd ; : set-bootpath @@ -47,7 +49,9 @@ CREATE load-list 2 cells allot load-list 2 cells erase s" snk" romfs-lookup 0<> IF \ Load SNK client 15 MiB after Paflof... FIXME: Hard-coded offset is ugly! paflof-start f00000 + - elf-load-file-to-addr drop start-elf64 client-data + elf-load-file-to-addr drop \ FIXME - check this for LE, currently its BE only + dup @ swap 8 + @ 0 \ populate entry r2 r12 + start-elf64 client-data ELSE 2drop false THEN |