From 1a93a83480dd99984f01b61ed215f014bca23fbf Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Fri, 18 Sep 2009 22:59:30 +0000 Subject: [PATCH] Allows to boot openSUSE from install CD-ROM Implements "init-program" using loader packages Write a first loader package: elf-loader Signed-off-by: Laurent Vivier git-svn-id: svn://coreboot.org/openbios/trunk/openbios-devel@578 f158a5a8-5612-0410-a976-696ce0be7e32 --- arch/ppc/qemu/init.c | 13 ++ forth/debugging/client.fs | 272 +++++++++++++++++++++++++++++++++++++- modules/build.xml | 1 + modules/init.c | 1 + modules/modules.h | 1 + 5 files changed, 284 insertions(+), 4 deletions(-) diff --git a/arch/ppc/qemu/init.c b/arch/ppc/qemu/init.c index 0865d1b..2375f33 100644 --- a/arch/ppc/qemu/init.c +++ b/arch/ppc/qemu/init.c @@ -439,6 +439,18 @@ id_cpu(void) for (;;); } +static void go( void ); + +static void +go( void ) +{ + ucell addr; + + addr = POP(); + + call_elf( 0, 0, addr); +} + void arch_of_init( void ) { @@ -688,4 +700,5 @@ arch_of_init( void ) device_end(); bind_func("platform-boot", boot ); + bind_func("(go)", go); } diff --git a/forth/debugging/client.fs b/forth/debugging/client.fs index d35b340..ac9d06c 100644 --- a/forth/debugging/client.fs +++ b/forth/debugging/client.fs @@ -23,8 +23,268 @@ variable file-size : load-size file-size @ ; +variable file-type + +0 constant elf +1 constant bootinfo +2 constant xcoff +3 constant pe + +\ Array indexes and values for e_type + +d# 16 constant EI_NIDENT + +0 constant EI_MAG0 + h# 7f constant ELFMAG0 + +1 constant EI_MAG1 + [CHAR] E constant ELFMAG1 + +2 constant EI_MAG2 + [CHAR] L constant ELFMAG2 + +3 constant EI_MAG3 + [CHAR] F constant ELFMAG3 + +4 constant EI_CLASS + 0 constant ELFCLASSNONE + 1 constant ELFCLASS32 + 2 constant ELFCLASS64 + +5 constant EI_DATA + 0 constant ELFDATANONE + 1 constant ELFDATA2LSB + 2 constant ELFDATA2MSB + +6 constant EI_VERSION + 0 constant EV_NONE + 1 constant EV_CURRENT + +\ Values for e_type + +0 constant ET_NONE +1 constant ET_REL +2 constant ET_EXEC +3 constant ET_DYN +4 constant ET_CORE + +\ Values for e_machine + +d# 2 constant EM_SPARC +d# 3 constant EM_386 +d# 6 constant EM_486 +d# 18 constant EM_SPARC32PLUS +d# 20 constant EM_PPC +d# 43 constant EM_SPARCV9 + +/l constant Elf32_Addr +/w constant Elf32_Half +/l constant Elf32_Off +/l constant Elf32_Sword +/l constant Elf32_Word +/l constant Elf32_Size + +struct ( ELF header ) + EI_NIDENT field >Elf32_Ehdr.e_ident ( File identification ) + Elf32_Half field >Elf32_Ehdr.e_type ( File type ) + Elf32_Half field >Elf32_Ehdr.e_machine ( Machine archicture ) + Elf32_Word field >Elf32_Ehdr.e_version ( ELF format version ) + Elf32_Addr field >Elf32_Ehdr.e_entry ( Entry point ) + Elf32_Off field >Elf32_Ehdr.e_phoff ( Program header file offset ) + Elf32_Off field >Elf32_Ehdr.e_shoff ( Section header file offset ) + Elf32_Word field >Elf32_Ehdr.e_flags ( Architecture specific flags ) + Elf32_Half field >Elf32_Ehdr.e_ehsize ( Size of ELF header in bytes ) + Elf32_Half field >Elf32_Ehdr.e_phentsize ( Size of program header entries ) + Elf32_Half field >Elf32_Ehdr.e_phnum ( Number of program header entry ) + Elf32_Half field >Elf32_Ehdr.e_shentsize ( Size of section header entry ) + Elf32_Half field >Elf32_Ehdr.e_shnum ( Number of section header entries ) + Elf32_Half field >Elf32_Ehdr.e_shstrndx ( Section name strings section ) +constant /Elf32_Ehdr + +: @e_ident ( base index -- byte ) + swap >Elf32_Ehdr.e_ident + c@ +; + +: @e_type ( base -- type ) + >Elf32_Ehdr.e_type w@ +; + +: @e_machine ( base -- type ) + >Elf32_Ehdr.e_machine w@ +; + +: @e_entry ( base -- entry ) + >Elf32_Ehdr.e_entry l@ +; + +: @e_phoff ( base -- poffset ) + >Elf32_Ehdr.e_phoff l@ +; + +: @e_phnum ( base -- pnum ) + >Elf32_Ehdr.e_phnum w@ +; + +: elf? + " load-base" evaluate + dup EI_MAG0 @e_ident + ELFMAG0 <> if drop false exit then + dup EI_MAG1 @e_ident + ELFMAG1 <> if drop false exit then + dup EI_MAG2 @e_ident + ELFMAG2 <> if drop false exit then + dup EI_MAG3 @e_ident + ELFMAG3 <> if drop false exit then + dup EI_CLASS @e_ident +[IFDEF] CONFIG_SPARC64 + ELFCLASS64 <> if drop false exit then +[ELSE] + ELFCLASS32 <> if drop false exit then +[THEN] + dup EI_DATA @e_ident + " little-endian?" evaluate if + ELFDATA2LSB <> if drop false exit then + else + ELFDATA2MSB <> if drop false exit then + then + dup @e_type + ET_EXEC <> if drop false exit then ( not executable ) + @e_machine +[IFDEF] CONFIG_PPC + EM_PPC <> if false exit then +[THEN] +[IFDEF] CONFIG_X86 + dup + EM_386 <> if + EM_486 <> if + false exit + then + else + drop + then +[THEN] +[IFDEF] CONFIG_SPARC32 + dup + EM_SPARC <> if + EM_SPARC32PLUS <> if + false exit + then + else + drop + then +[THEN] +[IFDEF] CONFIG_SPARC64 + EM_SPARCV9 <> if false exit then +[THEN] + true + ; + +variable elf-entry + +: init-program-elf + elf file-type ! + " /packages/elf-loader" open-dev dup if + dup + " init-program" rot $call-method + close-dev + else + drop + ." /packages/elf-loader is missing" cr + then +; + +: xcoff? + " load-base" evaluate w@ + h# 1df <> if + false + exit + then + true + ; + +: init-program-xcoff + xcoff file-type ! + " /packages/xcoff-loader" open-dev dup if + dup + " init-program" rot $call-method + close-dev + else + drop + ." /packages/xcoff-loader is missing" cr + then + ; + +: pe? + false +; + +: init-program-pe + pe file-type ! + " /packages/pe-loader" open-dev dup if + dup + " init-program" rot $call-method + close-dev + else + drop + ." /packages/pe-loader is missing" cr + then + ; + +: bootinfo? + " load-base" evaluate dup + " " comp 0= if + drop + true + exit + then + " " comp 0= if + true + exit + then + false + ; + +: init-program-bootinfo + bootinfo file-type ! + " /packages/bootinfo-loader" open-dev dup if + dup + " init-program" rot $call-method + close-dev + else + drop + ." /packages/bootinfo-loader is missing" cr + then + ; + +: init-program ( -- ) + elf? if + init-program-elf + exit + then + xcoff? if + init-program-xcoff + exit + then + pe? if + init-program-pe + exit + then + bootinfo? if + init-program-bootinfo + exit + then + ; + +: encode-bootpath ( str len -- ) + \ FIXME: need to extract bootargs from bootpath and set it in /chosen + " /chosen" (find-dev) if + " bootpath" rot (property) + then +; + : load ( "{params}" -- ) linefeed parse ( str len ) + 2dup encode-bootpath open-dev ( ihandle ) dup 0= if drop @@ -35,18 +295,22 @@ variable file-size dup ihandle>phandle " load" rot find-method ( xt 0|1 ) if swap call-package !load-size else cr ." Cannot find load for this package" 2drop then r> close-dev + init-program ; : go ( -- ) - ." go is not yet implemented" + elf file-type @ = if +[IFDEF] CONFIG_PPC + elf-entry @ " (go)" evaluate +[THEN] + else + ." go is not yet implemented" + then ; : state-valid ( -- a-addr ) ; -: init-program ( -- ) - ; - \ 7.6.3 Abort and resume diff --git a/modules/build.xml b/modules/build.xml index 8a55294..865df1e 100644 --- a/modules/build.xml +++ b/modules/build.xml @@ -24,6 +24,7 @@ + diff --git a/modules/init.c b/modules/init.c index 80bd92d..0b75044 100644 --- a/modules/init.c +++ b/modules/init.c @@ -42,4 +42,5 @@ modules_init( void ) #ifdef CONFIG_SUN_PARTS sunparts_init(); #endif + elf_loader_init(); } diff --git a/modules/modules.h b/modules/modules.h index fdeae8f..c8b2d5c 100644 --- a/modules/modules.h +++ b/modules/modules.h @@ -24,5 +24,6 @@ extern void macparts_init( void ); extern void pcparts_init( void ); extern void sunparts_init( void ); extern void cmdline_init( void ); +extern void elf_loader_init( void ); #endif /* _H_MODULES */