From f9bdcf050c2fe87defaf4bd15153fc70479f5cb2 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Sun, 1 Aug 2010 15:13:48 +0000 Subject: [PATCH] Rework the OpenBIOS internals so that boot, load and init-program now all use the unified libopenbios loader code with improved IEEE-1275 spec compliance. This patch implements the following: 1) Fix bootpath/bootargs handling so that default values are read from NVRAM, and allow multiple space-separated values to be specified. 2) With correct bootargs handling in place, move the ELF loader over to the new libopenbios unified loaders. 3) Remove all the loader code from all architecture directories sine we don't need it anymore. 4) Simplify the boot word so it invokes platform-specific code where required, then calls load and go as per the specification. Tested on all my available images for SPARC32, SPARC64 and PPC, and compile-tested on x86. Signed-off-by: Mark Cave-Ayland git-svn-id: svn://coreboot.org/openbios/trunk/openbios-devel@828 f158a5a8-5612-0410-a976-696ce0be7e32 --- arch/ppc/qemu/init.c | 19 +-- arch/ppc/qemu/main.c | 83 ++---------- arch/sparc32/boot.c | 232 ++++++++++++--------------------- arch/sparc32/boot.h | 1 + arch/sparc32/openbios.c | 61 +++++++-- arch/sparc64/boot.c | 95 ++------------ arch/sparc64/linux_load.c | 6 + arch/sparc64/openbios.c | 30 +---- arch/x86/boot.c | 86 +----------- forth/admin/userboot.fs | 13 +- forth/debugging/client.fs | 64 +++++++-- include/libopenbios/elf_load.h | 2 +- include/libopenbios/sys_info.h | 1 + libopenbios/elf_load.c | 4 +- libopenbios/load.c | 19 +++ 15 files changed, 253 insertions(+), 463 deletions(-) diff --git a/arch/ppc/qemu/init.c b/arch/ppc/qemu/init.c index 8e16120..f33c91a 100644 --- a/arch/ppc/qemu/init.c +++ b/arch/ppc/qemu/init.c @@ -527,7 +527,7 @@ arch_of_init( void ) uint64_t ram_size; const struct cpudef *cpu; char buf[64], qemu_uuid[16]; - const char *stdin_path, *stdout_path; + const char *stdin_path, *stdout_path, *boot_path; uint32_t temp = 0; ofmem_t *ofmem = ofmem_arch_get_private(); @@ -721,14 +721,17 @@ arch_of_init( void ) uint16_t boot_device = fw_cfg_read_i16(FW_CFG_BOOT_DEVICE); switch (boot_device) { case 'c': - push_str("hd:"); + boot_path = "hd"; break; default: case 'd': - push_str("cd:"); + boot_path = "cd"; break; } + /* Setup default boot devices */ + snprintf(buf, sizeof(buf), "%s:,\\\\:tbxi %s:,\\ppc\\bootinfo.txt", boot_path, boot_path); + push_str(buf); fword("encode-string"); push_str("boot-device"); fword("property"); @@ -737,16 +740,6 @@ arch_of_init( void ) push_str("/chosen"); fword("find-device"); - /* bootpath/bootargs should be set to NVRAM default */ - fword("boot-device"); - fword("encode-string"); - push_str("bootpath"); - fword("property"); - fword("boot-args"); - fword("encode-string"); - push_str("bootargs"); - fword("property"); - push_str(stdin_path); fword("open-dev"); fword("encode-int"); diff --git a/arch/ppc/qemu/main.c b/arch/ppc/qemu/main.c index 06e5692..42c0ddb 100644 --- a/arch/ppc/qemu/main.c +++ b/arch/ppc/qemu/main.c @@ -39,16 +39,9 @@ #define ELF_DPRINTF(fmt, args...) SUBSYS_DPRINTF("ELF", fmt, ##args) #define NEWWORLD_DPRINTF(fmt, args...) SUBSYS_DPRINTF("NEWWORLD", fmt, ##args) -static void -load(const char *path, const char *param) -{ - char buffer[1024]; - if (param) - sprintf(buffer, "load %s %s", path, param); - else - sprintf(buffer, "load %s", path); - feval(buffer); -} +struct sys_info sys_info; +void *elf_boot_notes = NULL; + static char * get_device( const char *path ) @@ -115,6 +108,7 @@ get_filename( const char * path , char **dirname) return filename; } + static void encode_bootpath( const char *spec, const char *args ) { @@ -123,6 +117,9 @@ encode_bootpath( const char *spec, const char *args ) char *filename, *directory; int partition; + if (spec) + return; + filename = get_filename(spec, &directory); partition = get_partition(spec); if (partition == -1) @@ -138,28 +135,6 @@ encode_bootpath( const char *spec, const char *args ) set_property( chosen_ph, "bootargs", args, strlen(args)+1 ); } -/************************************************************************/ -/* qemu booting */ -/************************************************************************/ -static void -try_path(const char *device, const char* filename, const char *param) -{ - char path[1024]; - - if (filename) - snprintf(path, sizeof(path), "%s%s", device, filename); - else - snprintf(path, sizeof(path), "%s", device); - - ELF_DPRINTF("Trying %s %s\n", path, param); - - load(path, param); - update_nvram(); - ELF_DPRINTF("Transfering control to %s %s\n", - path, param); - feval("go"); -} - #define OLDWORLD_BOOTCODE_BASEADDR (0x3f4000) static void @@ -203,46 +178,6 @@ oldworld_boot( void ) return; } -static void -newworld_boot( void ) -{ - static const char * const chrp_path[] = { "\\\\:tbxi", - "ppc\\bootinfo.txt", - NULL - }; - char *path = pop_fstr_copy(), *param; - int i; - - param = strchr(path, ' '); - if (param) { - *param = 0; - param++; - } - - if (!path) { - NEWWORLD_DPRINTF("Entering boot, no path\n"); - - /* No path specified, so grab defaults from /chosen */ - push_str("bootpath"); - push_str("/chosen"); - fword("(find-dev)"); - POP(); - fword("get-package-property"); - POP(); - path = pop_fstr_copy(); - - for (i = 0; chrp_path[i]; i++) - try_path(path, chrp_path[i], param); - - } else { - NEWWORLD_DPRINTF("Entering boot, path %s\n", path); - try_path(path, NULL, param); - for (i = 0; chrp_path[i]; i++) - try_path(path, chrp_path[i], param); - } - printk("*** Boot failure! No secondary bootloader specified ***\n"); -} - static void check_preloaded_kernel(void) { unsigned long kernel_image, kernel_size; @@ -281,8 +216,10 @@ boot( void ) if (boot_device == 'm') { check_preloaded_kernel(); } + if (boot_device == 'c') { oldworld_boot(); } - newworld_boot(); + + update_nvram(); } diff --git a/arch/sparc32/boot.c b/arch/sparc32/boot.c index d5d14db..47da183 100644 --- a/arch/sparc32/boot.c +++ b/arch/sparc32/boot.c @@ -9,10 +9,6 @@ #include "libc/diskio.h" #include "libc/vsprintf.h" #include "libopenbios/sys_info.h" -#include "libopenbios/elf_load.h" -#include "libopenbios/aout_load.h" -#include "libopenbios/fcode_load.h" -#include "libopenbios/forth_load.h" #include "openprom.h" #include "boot.h" #include "context.h" @@ -22,76 +18,16 @@ uint32_t kernel_size; uint32_t qemu_cmdline; uint32_t cmdline_size; char boot_device; -static const void *romvec; - -static int try_path(const char *path, char *param) -{ - void *boot_notes = NULL; - ucell valid; - ihandle_t dev; - - push_str(path); - fword("pathres-resolve-aliases"); - bootpath = pop_fstr_copy(); - printk("Trying %s (%s)\n", path, bootpath); - - /* Open device used by this path */ - dev = open_dev(path); - -#ifdef CONFIG_LOADER_ELF - /* ELF Boot loader */ - elf_load(&sys_info, path, param, &boot_notes); - feval("state-valid @"); - valid = POP(); - if (valid) - goto start_image; -#endif - - /* Linux loader (not using Forth) */ - linux_load(&sys_info, path, param); - -#ifdef CONFIG_LOADER_AOUT - /* a.out loader */ - aout_load(&sys_info, dev); - feval("state-valid @"); - valid = POP(); - if (valid) - goto start_image; -#endif - -#ifdef CONFIG_LOADER_FCODE - /* Fcode loader */ - fcode_load(dev); - feval("state-valid @"); - valid = POP(); - if (valid) - goto start_image; -#endif - -#ifdef CONFIG_LOADER_FORTH - /* Forth loader */ - forth_load(dev); - feval("state-valid @"); - valid = POP(); - if (valid) - goto start_image; -#endif - - close_dev(dev); - - return 0; - - -start_image: - go(); - return -1; -} - +void *elf_boot_notes = NULL; +const void *romvec; void go(void) { ucell address, type, size; - int image_retval = 0; + int image_retval = 0, proplen, unit, part; + phandle_t chosen; + char *prop, *id, bootid; + static char bootpathbuf[128], bootargsbuf[128], buf[128]; /* Get the entry point and the type (see forth/debugging/client.fs) */ feval("saved-program-state >sps.entry @"); @@ -101,6 +37,80 @@ void go(void) feval("saved-program-state >sps.file-size @"); size = POP(); + /* SPARC32 is slightly unusual in that before invoking any loaders, a romvec array + needs to be set up to pass certain parameters using a C struct. Hence this section + extracts the relevant boot information and places it in obp_arg. */ + + /* Get the name of the selected boot device, along with the device and unit number */ + chosen = find_dev("/chosen"); + prop = get_property(chosen, "bootpath", &proplen); + strncpy(bootpathbuf, prop, proplen); + prop = get_property(chosen, "bootargs", &proplen); + strncpy(bootargsbuf, prop, proplen); + + /* Set bootpath pointer used in romvec table to the bootpath */ + bootpath = bootpathbuf; + + if (!strcmp(bootpathbuf, "cdrom") || !strcmp(bootpathbuf, "disk")) { + + /* Controller currently always 0 */ + obp_arg.boot_dev_ctrl = 0; + + /* Grab the device and unit number string (in form unit,partition) */ + push_str(bootpathbuf); + feval("pathres-resolve-aliases ascii @ right-split 2drop"); + id = pop_fstr_copy(); + + /* A bit hacky, but we have no atoi() function */ + unit = id[0] - '0'; + part = id[2] - '0'; + + obp_arg.boot_dev_unit = unit; + obp_arg.dev_partition = part; + + /* Generate the "oldpath" + FIXME: hardcoding this looks almost definitely wrong. + With sd(0,2,0):b we get to see the solaris kernel though */ + if (!strcmp(bootpathbuf, "disk")) + bootid = 'd'; + else + bootid = 'b'; + + snprintf(buf, sizeof(buf), "sd(0,%d,%d):%c", unit, part, bootid); + + obp_arg.boot_dev[0] = buf[0]; + obp_arg.boot_dev[1] = buf[1]; + obp_arg.argv[0] = buf; + obp_arg.argv[1] = bootargsbuf; + + } else if (!strcmp(bootpathbuf, "floppy")) { + + obp_arg.boot_dev_ctrl = 0; + obp_arg.boot_dev_unit = 0; + obp_arg.dev_partition = 0; + + strcpy(buf, "fd()"); + + obp_arg.boot_dev[0] = buf[0]; + obp_arg.boot_dev[1] = buf[1]; + obp_arg.argv[0] = buf; + obp_arg.argv[1] = bootargsbuf; + + } else if (!strcmp(bootpathbuf, "net")) { + + obp_arg.boot_dev_ctrl = 0; + obp_arg.boot_dev_unit = 0; + obp_arg.dev_partition = 0; + + strcpy(buf, "le()"); + + obp_arg.boot_dev[0] = buf[0]; + obp_arg.boot_dev[1] = buf[1]; + obp_arg.argv[0] = buf; + obp_arg.argv[1] = bootargsbuf; + + } + printk("\nJumping to entry point " FMT_ucellx " for type " FMT_ucellx "...\n", address, type); switch (type) { @@ -149,89 +159,9 @@ void go(void) void boot(void) { - char *path = pop_fstr_copy(), *param, altpath[256]; - const char *oldpath = path; - int unit = 0; - int result; - - if(!path) { - /* No path specified, so grab defaults from firmware */ - switch (boot_device) { - case 'a': - path = strdup("/obio/SUNW,fdtwo"); - oldpath = "fd()"; - break; - case 'c': - path = strdup("disk"); - oldpath = "sd(0,0,0):d"; - break; - default: - case 'd': - path = strdup("cdrom"); - // FIXME: hardcoding this looks almost definitely wrong. - // With sd(0,2,0):b we get to see the solaris kernel though - //oldpath = "sd(0,2,0):d"; - oldpath = "sd(0,2,0):b"; - unit = 2; - break; - case 'n': - path = strdup("net"); - oldpath = "le()"; - break; - } - } - - obp_arg.boot_dev_ctrl = 0; - obp_arg.boot_dev_unit = unit; - obp_arg.dev_partition = 0; - obp_arg.boot_dev[0] = oldpath[0]; - obp_arg.boot_dev[1] = oldpath[1]; - obp_arg.argv[0] = oldpath; - obp_arg.argv[1] = (void *)(long)qemu_cmdline; - - param = strchr(path, ' '); - if(param) { - *param = '\0'; - param++; - } else if (cmdline_size) { - param = (char *)qemu_cmdline; - } else { - push_str("boot-args"); - push_str("/options"); - fword("(find-dev)"); - POP(); - fword("get-package-property"); - POP(); - param = pop_fstr_copy(); - obp_arg.argv[1] = param; - } - - romvec = init_openprom(); - + /* Boot preloaded kernel */ if (kernel_size) { printk("[sparc] Kernel already loaded\n"); start_elf(kernel_image, (unsigned long)romvec); } - - printk("[sparc] Booting file '%s' ", path); - if (param) - printk("with parameters '%s'\n", param); - else - printk("without parameters.\n"); - - result = try_path(path, param); - if (!result) { - push_str(path); - PUSH(':'); - fword("left-split"); - snprintf(altpath, sizeof(altpath), "%s:d", pop_fstr_copy()); - POP(); - POP(); - - try_path(altpath, param); - } - - printk("Unsupported image format\n"); - - free(path); } diff --git a/arch/sparc32/boot.h b/arch/sparc32/boot.h index ca4d0a9..f32ef05 100644 --- a/arch/sparc32/boot.h +++ b/arch/sparc32/boot.h @@ -30,6 +30,7 @@ void cls(void); // romvec.c extern struct linux_arguments_v0 obp_arg; +extern const void *romvec; // openbios.c extern int qemu_machine_type; diff --git a/arch/sparc32/openbios.c b/arch/sparc32/openbios.c index e7e3858..2132ca6 100644 --- a/arch/sparc32/openbios.c +++ b/arch/sparc32/openbios.c @@ -133,6 +133,9 @@ static void init_memory(void) static void arch_init( void ) { + static char cmdline[128]; + int size; + openbios_init(); modules_init(); ob_init_mmu(); @@ -151,23 +154,57 @@ arch_init( void ) #endif device_end(); + kernel_size = fw_cfg_read_i32(FW_CFG_KERNEL_SIZE); + if (kernel_size) + kernel_image = fw_cfg_read_i32(FW_CFG_KERNEL_ADDR); + + size = fw_cfg_read_i32(FW_CFG_CMDLINE_SIZE); + if (size) { + fw_cfg_read(FW_CFG_CMDLINE_DATA, cmdline, size); + } + cmdline[size] = '\0'; + qemu_cmdline = (uint32_t)cmdline; + + boot_device = fw_cfg_read_i16(FW_CFG_BOOT_DEVICE); + + /* Initialiase openprom romvec */ + romvec = init_openprom(); + + /* Setup nvram variables */ + push_str("/options"); + fword("find-device"); + + switch (boot_device) { + case 'a': + push_str("floppy"); + break; + case 'c': + push_str("disk"); + break; + default: + case 'd': + push_str("cdrom"); + break; + case 'n': + push_str("net"); + break; + } + + fword("encode-string"); + push_str("boot-device"); + fword("property"); + + push_str(""); + fword("encode-string"); + push_str("boot-file"); + fword("property"); + /* Set up other properties */ push_str("/chosen"); fword("find-device"); - /* bootpath/bootargs should be set to NVRAM default */ - fword("boot-device"); - fword("encode-string"); - push_str("bootpath"); - fword("property"); - fword("boot-args"); - fword("encode-string"); - push_str("bootargs"); - fword("property"); - - boot_device = fw_cfg_read_i16(FW_CFG_BOOT_DEVICE); - bind_func("platform-boot", boot ); + bind_func("(go)", go ); } int openbios(void) diff --git a/arch/sparc64/boot.c b/arch/sparc64/boot.c index e471259..c96d1c1 100644 --- a/arch/sparc64/boot.c +++ b/arch/sparc64/boot.c @@ -8,10 +8,6 @@ #include "libc/diskio.h" #include "libc/vsprintf.h" #include "libopenbios/sys_info.h" -#include "libopenbios/elf_load.h" -#include "libopenbios/aout_load.h" -#include "libopenbios/fcode_load.h" -#include "libopenbios/forth_load.h" #include "boot.h" uint64_t kernel_image; @@ -19,68 +15,10 @@ uint64_t kernel_size; uint64_t qemu_cmdline; uint64_t cmdline_size; char boot_device; -void *boot_notes = NULL; +void *elf_boot_notes = NULL; extern int sparc64_of_client_interface( int *params ); -static int try_path(const char *path, char *param) -{ - ucell valid; - ihandle_t dev; - - /* Open device used by this path */ - dev = open_dev(path); - -#ifdef CONFIG_LOADER_ELF - /* ELF Boot loader */ - elf_load(&sys_info, path, param, &boot_notes); - feval("state-valid @"); - valid = POP(); - if (valid) - goto start_image; -#endif - - /* Linux loader (not using Forth) */ - linux_load(&sys_info, path, param); - -#ifdef CONFIG_LOADER_AOUT - /* a.out loader */ - aout_load(&sys_info, dev); - feval("state-valid @"); - valid = POP(); - if (valid) - goto start_image; -#endif - -#ifdef CONFIG_LOADER_FCODE - /* Fcode loader */ - fcode_load(dev); - feval("state-valid @"); - valid = POP(); - if (valid) - goto start_image; -#endif - -#ifdef CONFIG_LOADER_FORTH - /* Forth loader */ - forth_load(dev); - feval("state-valid @"); - valid = POP(); - if (valid) - goto start_image; -#endif - - close_dev(dev); - - return 0; - - -start_image: - go(); - return -1; -} - - void go(void) { ucell address, type, size; @@ -99,7 +37,7 @@ void go(void) switch (type) { case 0x0: /* Start ELF boot image */ - image_retval = start_elf(address, (uint64_t)&boot_notes); + image_retval = start_elf(address, (uint64_t)&elf_boot_notes); break; case 0x1: @@ -136,19 +74,23 @@ void go(void) void boot(void) { - char *path=pop_fstr_copy(), *param; - char altpath[256]; - int result; + char *path, *param; + /* Copy the incoming path */ + fword("2dup"); + path = pop_fstr_copy(); + + /* Boot preloaded kernel */ if (kernel_size) { void (*entry)(unsigned long p1, unsigned long p2, unsigned long p3, - unsigned long p4, unsigned long p5);; + unsigned long p4, unsigned long p5); printk("[sparc64] Kernel already loaded\n"); entry = (void *) (unsigned long)kernel_image; entry(0, 0, 0, 0, (unsigned long)&sparc64_of_client_interface); } + /* Invoke Linux directly -- probably not supported */ if(!path) { /* No path specified, so grab defaults from /chosen */ push_str("bootpath"); @@ -175,20 +117,9 @@ void boot(void) POP(); param = pop_fstr_copy(); } - - printk("[sparc64] Booting file '%s' ", path); - if (param) - printk("with parameters '%s'\n", param); - else - printk("without parameters.\n"); - - result = try_path(path, param); - if (!result) { - snprintf(altpath, sizeof(altpath), "%s:f", path); - try_path(altpath, param); - } - - printk("Unsupported image format\n"); + + /* Invoke platform-specific Linux loader */ + linux_load(&sys_info, path, param); free(path); } diff --git a/arch/sparc64/linux_load.c b/arch/sparc64/linux_load.c index 07b2b42..9adf7b5 100644 --- a/arch/sparc64/linux_load.c +++ b/arch/sparc64/linux_load.c @@ -618,6 +618,12 @@ int linux_load(struct sys_info *info, const char *file, const char *cmdline) return LOADER_NOT_SUPPORT; } + debug("[sparc64] Booting kernel '%s' ", file); + if (cmdline) + debug("with parameters '%s'\n", cmdline); + else + debug("without parameters.\n"); + params = phys_to_virt(LINUX_PARAM_LOC); init_linux_params(params, &hdr); set_memory_size(params, info); diff --git a/arch/sparc64/openbios.c b/arch/sparc64/openbios.c index 1196ed5..169af92 100644 --- a/arch/sparc64/openbios.c +++ b/arch/sparc64/openbios.c @@ -374,7 +374,6 @@ void arch_nvram_get(char *data) { uint32_t size = 0; const struct cpudef *cpu; - const char *bootpath; char buf[256]; uint32_t temp; uint64_t ram_size; @@ -492,34 +491,15 @@ void arch_nvram_get(char *data) push_str("boot-device"); fword("property"); + push_str(obio_cmdline); + fword("encode-string"); + push_str("boot-file"); + fword("property"); + /* Set up other properties */ push_str("/chosen"); fword("find-device"); - if (boot_device == 'c') - bootpath = "disk:a"; - else - bootpath = "cdrom:a"; - push_str(bootpath); - fword("encode-string"); - push_str("bootpath"); - fword("property"); - - /* bootpath/bootargs should be set to NVRAM default */ - fword("boot-device"); - fword("encode-string"); - push_str("bootpath"); - fword("property"); - fword("boot-args"); - fword("encode-string"); - push_str("bootargs"); - fword("property"); - - push_str(obio_cmdline); - fword("encode-string"); - push_str("bootargs"); - fword("property"); - if (fw_cfg_read_i16(FW_CFG_NOGRAPHIC)) { stdin_path = stdout_path = "ttya"; } else { diff --git a/arch/x86/boot.c b/arch/x86/boot.c index d2238ac..4731710 100644 --- a/arch/x86/boot.c +++ b/arch/x86/boot.c @@ -12,71 +12,9 @@ #include "arch/common/nvram.h" #include "libc/diskio.h" #include "libopenbios/sys_info.h" -#include "libopenbios/elf_load.h" -#include "libopenbios/aout_load.h" -#include "libopenbios/fcode_load.h" -#include "libopenbios/forth_load.h" #include "boot.h" -void *boot_notes = NULL; - -static int try_path(const char *path, char *param) -{ - ucell valid; - ihandle_t dev; - - /* Open device used by this path */ - dev = open_dev(path); - -#ifdef CONFIG_LOADER_ELF - /* ELF Boot loader */ - elf_load(&sys_info, path, param, &boot_notes); - feval("state-valid @"); - valid = POP(); - if (valid) - goto start_image; -#endif - - /* Linux loader (not using Forth) */ - linux_load(&sys_info, path, param); - -#ifdef CONFIG_LOADER_AOUT - /* a.out loader */ - aout_load(&sys_info, dev); - feval("state-valid @"); - valid = POP(); - if (valid) - goto start_image; -#endif - -#ifdef CONFIG_LOADER_FCODE - /* Fcode loader */ - fcode_load(dev); - feval("state-valid @"); - valid = POP(); - if (valid) - goto start_image; -#endif - -#ifdef CONFIG_LOADER_FORTH - /* Forth loader */ - forth_load(dev); - feval("state-valid @"); - valid = POP(); - if (valid) - goto start_image; -#endif - - close_dev(dev); - - return 0; - - -start_image: - go(); - return -1; -} - +void *elf_boot_notes = NULL; void go(void) { @@ -133,24 +71,6 @@ void go(void) void boot(void) { - char *path=pop_fstr_copy(), *param; - - if(!path) { - printk("[x86] Booting default not supported.\n"); - return; - } - - param = strchr(path, ' '); - if(param) { - *param = '\0'; - param++; - } - - printk("[x86] Booting file '%s' with parameters '%s'\n",path, param); - - try_path(path, param); - - printk("Unsupported image format\n"); - - free(path); + /* No platform-specific boot code */ + return; } diff --git a/forth/admin/userboot.fs b/forth/admin/userboot.fs index 2de019c..626f888 100644 --- a/forth/admin/userboot.fs +++ b/forth/admin/userboot.fs @@ -1,16 +1,15 @@ \ 7.4.3.5 User commands for booting -: boot ( "{param-text}" -- ) - (encode-bootpath) +: boot ( "{param-text}" -- ) + (encode-bootpath) \ Setup bootpath/bootargs s" platform-boot" $find if - execute - else - 2drop - cr ." Booting " type cr - ." ... not supported on this system." cr + execute \ Execute platform-specific boot code then + $load \ load and go + go ; + \ : diagnostic-mode? ( -- diag? ) \ ; diff --git a/forth/debugging/client.fs b/forth/debugging/client.fs index 35a08ce..1d22a07 100644 --- a/forth/debugging/client.fs +++ b/forth/debugging/client.fs @@ -58,24 +58,55 @@ variable file-size : (encode-bootpath) ( "{params}" -- bootpath-str bootpath-len) \ Parse the current input buffer of a load/boot command and set both \ the bootargs and bootpath properties as appropriate. - bl parse dup if - 2dup encode-string - " /chosen" (find-dev) if - " bootpath" rot (property) - then - then - linefeed parse dup if - encode-string - " /chosen" (find-dev) if - " bootargs" rot (property) - then - else + cr + + \ bootpath + bl parse dup 0= if + + \ None specified. As per IEEE-1275 specification, search through each value + \ in boot-device and use the first that returns a valid ihandle on open. + s" boot-device" $find drop execute + bl left-split + begin + dup + while + 2dup s" Trying " type type s" ..." type cr + 2dup open-dev ?dup if + close-dev + 2swap drop 0 \ Fake end of string so we exit loop + else + 2drop + bl left-split + then + repeat 2drop + else + 0 0 2swap \ Fake (empty) parse string then + + \ Set the bootpath property + 2dup encode-string + " /chosen" (find-dev) if + " bootpath" rot (property) + then + + \ bootargs + linefeed parse dup 0= if + \ None specified, use default from nvram + 2drop s" boot-file" $find drop execute + then + + \ Set the bootargs property + encode-string + " /chosen" (find-dev) if + " bootargs" rot (property) + then + + \ Remove the remaining string + 2swap 2drop ; -: load ( "{params}" -- ) - (encode-bootpath) +: $load ( devstr len ) open-dev ( ihandle ) dup 0= if drop @@ -89,6 +120,11 @@ variable file-size init-program ; +: load ( "{params}" -- ) + (encode-bootpath) + $load +; + : dir ( "{paths}" -- ) linefeed parse split-path-device diff --git a/include/libopenbios/elf_load.h b/include/libopenbios/elf_load.h index f16ff2f..d387624 100644 --- a/include/libopenbios/elf_load.h +++ b/include/libopenbios/elf_load.h @@ -21,7 +21,7 @@ #include "asm/elf.h" #include "libopenbios/sys_info.h" -extern int elf_load(struct sys_info *info, const char *filename, const char *cmdline, void **boot_notes); +extern int elf_load(struct sys_info *info, ihandle_t dev, const char *cmdline, void **boot_notes); extern void elf_init_program(void); extern int is_elf(Elf_ehdr *ehdr); extern int find_elf(Elf_ehdr *ehdr); diff --git a/include/libopenbios/sys_info.h b/include/libopenbios/sys_info.h index f3c3b78..2eea9af 100644 --- a/include/libopenbios/sys_info.h +++ b/include/libopenbios/sys_info.h @@ -22,6 +22,7 @@ struct sys_info { unsigned long *dict_end; }; +extern void *elf_boot_notes; extern struct sys_info sys_info; void collect_elfboot_info(struct sys_info *info); diff --git a/libopenbios/elf_load.c b/libopenbios/elf_load.c index 7ffec06..51cc363 100644 --- a/libopenbios/elf_load.c +++ b/libopenbios/elf_load.c @@ -368,7 +368,7 @@ elf_readhdrs(int offset, Elf_ehdr *ehdr) } int -elf_load(struct sys_info *info, const char *filename, const char *cmdline, void **boot_notes) +elf_load(struct sys_info *info, ihandle_t dev, const char *cmdline, void **boot_notes) { Elf_ehdr ehdr; Elf_phdr *phdr = NULL; @@ -382,7 +382,7 @@ elf_load(struct sys_info *info, const char *filename, const char *cmdline, void /* Mark the saved-program-state as invalid */ feval("0 state-valid !"); - fd = open_io(filename); + fd = open_ih(dev); if (!fd) goto out; diff --git a/libopenbios/load.c b/libopenbios/load.c index 41b3a00..03f4259 100644 --- a/libopenbios/load.c +++ b/libopenbios/load.c @@ -20,6 +20,10 @@ #include "libopenbios/sys_info.h" #include "libopenbios/load.h" +#ifdef CONFIG_LOADER_ELF +#include "libopenbios/elf_load.h" +#endif + #ifdef CONFIG_LOADER_AOUT #include "libopenbios/aout_load.h" #endif @@ -38,6 +42,21 @@ struct sys_info sys_info; void load(ihandle_t dev) { /* Invoke the loaders on the specified device */ + char *param; + +#ifdef CONFIG_LOADER_ELF + + /* Grab the boot arguments */ + push_str("bootargs"); + push_str("/chosen"); + fword("(find-dev)"); + POP(); + fword("get-package-property"); + POP(); + param = pop_fstr_copy(); + + elf_load(&sys_info, dev, param, &elf_boot_notes); +#endif #ifdef CONFIG_LOADER_AOUT aout_load(&sys_info, dev);