mirror of
https://gitlab.com/qemu-project/openbios.git
synced 2024-02-13 08:34:06 +08:00
This patch originally started as a fix for PPC, in that the NVRAM initialiser wasn't been run on startup (this is why printenv on PPC always showed much much less than on SPARC). However, it also showed up some inconsistent logic for boot device selection, which must also happen *before* boot is called in order for load to work correctly. With this patch applied, bootpath and bootargs are set from boot-device and boot-args respectively on startup for SPARC32, SPARC64 and PPC. Note: there is a small chance SPARC32 may break on some images - please let me know if it does. Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@siriusit.co.uk> git-svn-id: svn://coreboot.org/openbios/trunk/openbios-devel@805 f158a5a8-5612-0410-a976-696ce0be7e32
196 lines
4.1 KiB
C
196 lines
4.1 KiB
C
/*
|
|
*
|
|
*/
|
|
#undef BOOTSTRAP
|
|
#include "config.h"
|
|
#include "libopenbios/bindings.h"
|
|
#include "arch/common/nvram.h"
|
|
#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"
|
|
|
|
struct sys_info sys_info;
|
|
uint64_t kernel_image;
|
|
uint64_t kernel_size;
|
|
uint64_t qemu_cmdline;
|
|
uint64_t cmdline_size;
|
|
char boot_device;
|
|
void *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;
|
|
int image_retval = 0;
|
|
|
|
/* Get the entry point and the type (see forth/debugging/client.fs) */
|
|
feval("saved-program-state >sps.entry @");
|
|
address = POP();
|
|
feval("saved-program-state >sps.file-type @");
|
|
type = POP();
|
|
feval("saved-program-state >sps.file-size @");
|
|
size = POP();
|
|
|
|
printk("\nJumping to entry point " FMT_ucellx " for type " FMT_ucellx "...\n", address, type);
|
|
|
|
switch (type) {
|
|
case 0x0:
|
|
/* Start ELF boot image */
|
|
image_retval = start_elf(address, (uint64_t)&boot_notes);
|
|
break;
|
|
|
|
case 0x1:
|
|
/* Start ELF image */
|
|
image_retval = start_client_image(address, (uint64_t)&sparc64_of_client_interface);
|
|
break;
|
|
|
|
case 0x5:
|
|
/* Start a.out image */
|
|
image_retval = start_client_image(address, (uint64_t)&sparc64_of_client_interface);
|
|
break;
|
|
|
|
case 0x10:
|
|
/* Start Fcode image */
|
|
printk("Evaluating FCode...\n");
|
|
PUSH(address);
|
|
PUSH(1);
|
|
fword("byte-load");
|
|
image_retval = 0;
|
|
break;
|
|
|
|
case 0x11:
|
|
/* Start Forth image */
|
|
PUSH(address);
|
|
PUSH(size);
|
|
fword("eval2");
|
|
image_retval = 0;
|
|
break;
|
|
}
|
|
|
|
printk("Image returned with return value %#x\n", image_retval);
|
|
}
|
|
|
|
|
|
void boot(void)
|
|
{
|
|
char *path=pop_fstr_copy(), *param;
|
|
char altpath[256];
|
|
int result;
|
|
|
|
if (kernel_size) {
|
|
void (*entry)(unsigned long p1, unsigned long p2, unsigned long p3,
|
|
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);
|
|
}
|
|
|
|
if(!path) {
|
|
/* 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();
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
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");
|
|
|
|
free(path);
|
|
}
|