From c3d633a04491a959dd021a9199e3199fc3ad8a41 Mon Sep 17 00:00:00 2001 From: Nikunj A Dadhania Date: Fri, 7 Mar 2014 11:51:56 +0530 Subject: ELF: Enter LE binary in LE mode Trampoline code in the LE binary were helping fix this. This patch now takes care of switching the mode to LE for LE elf binaries. Signed-off-by: Nikunj A Dadhania --- include/libelf.h | 1 + lib/libelf/elf.c | 6 +++++- lib/libelf/elf32.c | 7 +++++++ slof/entry.S | 23 +++++++++++++++++++++++ slof/fs/boot.fs | 38 +++++++++++++++++++++++++------------- slof/fs/loaders.fs | 5 ++--- 6 files changed, 63 insertions(+), 17 deletions(-) diff --git a/include/libelf.h b/include/libelf.h index ee55375..5fbf279 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_32(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 30137f8..db2d2ab 100644 --- a/lib/libelf/elf.c +++ b/lib/libelf/elf.c @@ -82,7 +82,8 @@ elf_check_file(unsigned long *file_addr) * @return 1 for a 32 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 + * 4 for a 64 bit LE ABIv2 file + * 5 for a 32 bit LE ABIv1 file * anything else means an error during load */ int @@ -96,6 +97,9 @@ elf_load_file(void *file_addr, unsigned long *entry, switch (type) { case 1: *entry = elf_load_segments32(file_addr, 0, pre_load, post_load); + if (ehdr->ei_data != ELFDATA2MSB) { + type = 5; /* LE32 ABIv1 */ + } break; case 2: *entry = elf_load_segments64(file_addr, 0, pre_load, post_load); diff --git a/lib/libelf/elf32.c b/lib/libelf/elf32.c index ecd9c74..fea5cf4 100644 --- a/lib/libelf/elf32.c +++ b/lib/libelf/elf32.c @@ -146,6 +146,13 @@ elf_get_base_addr32(void *file_addr) return 0; } +uint32_t elf_get_eflags_32(void *file_addr) +{ + struct ehdr32 *ehdr = (struct ehdr32 *) file_addr; + + return ehdr->e_flags; +} + void elf_byteswap_header32(void *file_addr) { diff --git a/slof/entry.S b/slof/entry.S index bbaca9f..dcff57b 100644 --- a/slof/entry.S +++ b/slof/entry.S @@ -178,7 +178,30 @@ call_client: mflr 4 mtctr 3 bl swap_ci_regs + /* Check if LE loading */ + cmpwi 0,13,1 + beq 0f bctrl + b 1f +0: /* handle LE */ + mfmsr 13 + xori 13,13,1 + mtsrr1 13 + mfctr 13 + mr 12,13 + mtsrr0 13 + rfid +#if 0 /* in case we return back, still to be tested */ + .long 0x05009f42; /* bcl 20,31,$+4 */ + .long 0xa602c87d; /* mflr r14 */ + .long 0x1c00ce39; /* addi r14,r14,28 */ + .long 0xa600e07d; /* mfmsr r15 */ + .long 0x0100ef69; /* xori r15,r15,1 */ + .long 0xa603da7d; /* mtsrr0 r14 */ + .long 0xa603fb7d; /* mtsrr1 r15 */ + .long 0x2400004c; /* rfid */ +#endif +1: bl swap_ci_regs mtlr 4 li 3, -1 # client app return diff --git a/slof/fs/boot.fs b/slof/fs/boot.fs index 97eca1e..9a0ded0 100644 --- a/slof/fs/boot.fs +++ b/slof/fs/boot.fs @@ -71,28 +71,40 @@ defer go ( -- ) -6d boot-exception-handler ABORT ; -: go-64 ( args len entry r2 r12 -- ) +: go-64 ( args len entry r2 -- ) 0 ciregs >r3 ! 0 ciregs >r4 ! start-elf64 client-data claim-list elf-release 0 to claim-list ; +: set-le ( -- ) + 1 ciregs >r13 ! +; + +: set-be ( -- ) + 0 ciregs >r13 ! +; + : go-64-be ( -- ) state-valid @ IF + set-be go-args 2@ go-entry @ go-entry 8 + @ - 0 go-64 + 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-32-be + set-be + go-32 +; + +: go-32-lev1 + set-le + go-32 ; : go-64-lev1 @@ -100,8 +112,7 @@ defer go ( -- ) go-args 2@ go-entry @ xbflip go-entry 8 + @ xbflip - 0 - \ set-le + set-le go-64 THEN -6d boot-exception-handler ABORT @@ -110,8 +121,8 @@ defer go ( -- ) : go-64-lev2 state-valid @ IF go-args 2@ - go-entry 0 go-entry - \ set-le + go-entry 0 + set-le go-64 THEN -6d boot-exception-handler ABORT @@ -128,10 +139,11 @@ defer go ( -- ) ( arg len true claim-list entry elftype ) CASE - 1 OF ['] go-32 ENDOF ( arg len true claim-list entry go ) + 1 OF ['] go-32-be 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 ) + 5 OF ['] go-32-lev1 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 3603dd4..276ba6b 100644 --- a/slof/fs/loaders.fs +++ b/slof/fs/loaders.fs @@ -19,9 +19,8 @@ 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 r2 r12 -- ) +: start-elf64 ( arg len entry r2 -- ) msr@ 2000 or ciregs >srr1 ! - ciregs >r12 ! ciregs >r2 ! call-client \ entry point is pointer to .opd ; @@ -50,7 +49,7 @@ CREATE load-list 2 cells allot load-list 2 cells erase \ Load SNK client 15 MiB after Paflof... FIXME: Hard-coded offset is ugly! paflof-start f00000 + elf-load-file-to-addr drop \ FIXME - check this for LE, currently its BE only - dup @ swap 8 + @ 0 \ populate entry r2 r12 + dup @ swap 8 + @ \ populate entry r2 start-elf64 client-data ELSE 2drop false -- cgit v1.1