aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikunj A Dadhania <nikunj@linux.vnet.ibm.com>2014-03-07 11:51:56 +0530
committerAlexey Kardashevskiy <aik@ozlabs.ru>2014-03-18 17:06:47 +1100
commitc3d633a04491a959dd021a9199e3199fc3ad8a41 (patch)
tree88f7dd9e16c6b58cef6dd77e335085bad456995d
parent4099049c2588cc4ab4ce0fb7b96f8033ab03f538 (diff)
downloadSLOF-c3d633a04491a959dd021a9199e3199fc3ad8a41.zip
SLOF-c3d633a04491a959dd021a9199e3199fc3ad8a41.tar.gz
SLOF-c3d633a04491a959dd021a9199e3199fc3ad8a41.tar.bz2
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 <nikunj@linux.vnet.ibm.com>
-rw-r--r--include/libelf.h1
-rw-r--r--lib/libelf/elf.c6
-rw-r--r--lib/libelf/elf32.c7
-rw-r--r--slof/entry.S23
-rw-r--r--slof/fs/boot.fs38
-rw-r--r--slof/fs/loaders.fs5
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