aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikunj A Dadhania <nikunj@linux.vnet.ibm.com>2013-12-06 10:10:01 +1100
committerAlexey Kardashevskiy <aik@ozlabs.ru>2014-02-04 19:49:46 +1100
commitc2358afb40d42fa1f9c6ffb59c32f803bb3aa44d (patch)
tree9545dd4d56240c0545193c94587ff2a043289985
parent41a34055032ac5c64811238fe72f514634285c09 (diff)
downloadSLOF-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.fs6
-rw-r--r--include/libelf.h1
-rw-r--r--lib/libelf/elf.c13
-rw-r--r--lib/libelf/elf64.c7
-rw-r--r--slof/fs/boot.fs56
-rw-r--r--slof/fs/loaders.fs12
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