mirror of
https://gitlab.com/qemu-project/openbios.git
synced 2024-02-13 08:34:06 +08:00
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 <mark.cave-ayland@siriusit.co.uk> git-svn-id: svn://coreboot.org/openbios/trunk/openbios-devel@828 f158a5a8-5612-0410-a976-696ce0be7e32
168 lines
4.1 KiB
C
168 lines
4.1 KiB
C
/*
|
|
*
|
|
*/
|
|
#undef BOOTSTRAP
|
|
#include "config.h"
|
|
#include "libopenbios/bindings.h"
|
|
#include "arch/common/nvram.h"
|
|
#include "drivers/drivers.h"
|
|
#include "libc/diskio.h"
|
|
#include "libc/vsprintf.h"
|
|
#include "libopenbios/sys_info.h"
|
|
#include "openprom.h"
|
|
#include "boot.h"
|
|
#include "context.h"
|
|
|
|
uint32_t kernel_image;
|
|
uint32_t kernel_size;
|
|
uint32_t qemu_cmdline;
|
|
uint32_t cmdline_size;
|
|
char boot_device;
|
|
void *elf_boot_notes = NULL;
|
|
const void *romvec;
|
|
|
|
void go(void)
|
|
{
|
|
ucell address, type, size;
|
|
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 @");
|
|
address = POP();
|
|
feval("saved-program-state >sps.file-type @");
|
|
type = POP();
|
|
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) {
|
|
case 0x0:
|
|
/* Start ELF boot image */
|
|
image_retval = start_elf((unsigned long)address,
|
|
(unsigned long)romvec);
|
|
|
|
break;
|
|
|
|
case 0x1:
|
|
/* Start ELF image */
|
|
image_retval = start_elf((unsigned long)address,
|
|
(unsigned long)romvec);
|
|
|
|
break;
|
|
|
|
case 0x5:
|
|
/* Start a.out image */
|
|
image_retval = start_elf((unsigned long)address,
|
|
(unsigned long)romvec);
|
|
|
|
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)
|
|
{
|
|
/* Boot preloaded kernel */
|
|
if (kernel_size) {
|
|
printk("[sparc] Kernel already loaded\n");
|
|
start_elf(kernel_image, (unsigned long)romvec);
|
|
}
|
|
}
|