diff options
author | 2023-10-10 14:33:42 +0000 | |
---|---|---|
committer | 2023-10-10 14:33:42 +0000 | |
commit | af1a266670d040d2f4083ff309d732d648afba2a (patch) | |
tree | 2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/openbios/arch/sparc32/boot.c | |
parent | e02cda008591317b1625707ff8e115a4841aa889 (diff) |
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/openbios/arch/sparc32/boot.c')
-rw-r--r-- | roms/openbios/arch/sparc32/boot.c | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/roms/openbios/arch/sparc32/boot.c b/roms/openbios/arch/sparc32/boot.c new file mode 100644 index 000000000..bb5a57929 --- /dev/null +++ b/roms/openbios/arch/sparc32/boot.c @@ -0,0 +1,208 @@ +/* + * + */ +#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/initprogram.h" +#include "libopenbios/ofmem.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 initrd_image; +uint32_t initrd_size; +uint32_t qemu_cmdline; +uint32_t cmdline_size; +char boot_device; +const void *romvec; + +static struct linux_mlist_v0 *totphyslist, *availlist, *prommaplist; + +void setup_romvec(void) +{ + /* 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 function + extracts the relevant boot information and places it in obp_arg. */ + + int intprop, proplen, target, device, i; + unsigned int *intprop_ptr; + phandle_t chosen; + char *prop, *id, *name; + static char bootpathbuf[128], bootargsbuf[128], buf[128]; + struct linux_mlist_v0 **pp; + + /* Get the stdin and stdout paths */ + chosen = find_dev("/chosen"); + intprop = get_int_property(chosen, "stdin", &proplen); + PUSH(intprop); + fword("get-instance-path"); + ((struct linux_romvec *)romvec)->pv_stdin = pop_fstr_copy(); + + intprop = get_int_property(chosen, "stdout", &proplen); + PUSH(intprop); + fword("get-instance-path"); + ((struct linux_romvec *)romvec)->pv_stdout = pop_fstr_copy(); + + /* Get the name of the selected boot device, along with the device and unit number */ + 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 */ + push_str(bootpathbuf); + fword("pathres-resolve-aliases"); + bootpath = pop_fstr_copy(); + printk("bootpath: %s\n", bootpath); + + /* Now do some work to get hold of the target, partition etc. */ + push_str(bootpathbuf); + feval("open-dev"); + feval("ihandle>boot-device-handle drop to my-self"); + push_str("name"); + fword("get-my-property"); + POP(); + name = pop_fstr_copy(); + + if (!strncmp(name, "sd", 2)) { + + /* + Old-style SunOS disk paths are given in the form: + + sd(c,t,d):s + + where: + c = controller (Nth controller in system, usually 0) + t = target (my-unit phys.hi) + d = device/LUN (my-unit phys.lo) + s = slice/partition (my-args) + */ + + /* Controller currently always 0 */ + obp_arg.boot_dev_ctrl = 0; + + /* Get the target, device and slice */ + fword("my-unit"); + target = POP(); + device = POP(); + + fword("my-args"); + id = pop_fstr_copy(); + + if (id != NULL) { + snprintf(buf, sizeof(buf), "sd(0,%d,%d):%c", target, device, id[0]); + obp_arg.dev_partition = id[0] - 'a'; + } else { + snprintf(buf, sizeof(buf), "sd(0,%d,%d)", target, device); + obp_arg.dev_partition = 0; + } + + obp_arg.boot_dev_unit = target; + + 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 (!strncmp(name, "SUNW,fdtwo", 10)) { + + 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 (!strncmp(name, "le", 2)) { + + 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; + + } + + /* Generate the totphys (total memory available) list */ + prop = get_property(s_phandle_memory, "reg", &proplen); + intprop_ptr = (unsigned int *)prop; + + for (pp = &totphyslist, i = 0; i < (proplen / sizeof(int)); pp = &(**pp).theres_more, i+=3) { + *pp = (struct linux_mlist_v0 *)malloc(sizeof(struct linux_mlist_v0)); + (**pp).theres_more = NULL; + (**pp).start_adr = (char *)intprop_ptr[1]; + (**pp).num_bytes = intprop_ptr[2]; + + intprop_ptr += 3; + } + + /* Generate the avail (physical memory available) list */ + prop = get_property(s_phandle_memory, "available", &proplen); + intprop_ptr = (unsigned int *)prop; + + for (pp = &availlist, i = 0; i < (proplen / sizeof(int)); pp = &(**pp).theres_more, i+=3) { + *pp = (struct linux_mlist_v0 *)malloc(sizeof(struct linux_mlist_v0)); + (**pp).theres_more = NULL; + (**pp).start_adr = (char *)intprop_ptr[1]; + (**pp).num_bytes = intprop_ptr[2]; + + intprop_ptr += 3; + } + + /* Generate the prommap (taken virtual memory) list from inverse of available */ + prop = get_property(s_phandle_mmu, "available", &proplen); + intprop_ptr = (unsigned int *)prop; + + for (pp = &prommaplist, i = 0; i < (proplen / sizeof(int)); pp = &(**pp).theres_more, i+=3) { + *pp = (struct linux_mlist_v0 *)malloc(sizeof(struct linux_mlist_v0)); + (**pp).theres_more = NULL; + (**pp).start_adr = (char *)(intprop_ptr[1] + intprop_ptr[2]); + + if (i + 3 < (proplen / sizeof(int))) { + /* Size from next entry */ + (**pp).num_bytes = (intprop_ptr[4] + intprop_ptr[5]) - (intprop_ptr[1] + intprop_ptr[2]); + } else { + /* Tail (size from top of virtual memory) */ + (**pp).num_bytes = ofmem_arch_get_virt_top() - 1 - (intprop_ptr[1] + intprop_ptr[2]) + 1; + } + + intprop_ptr += 3; + } + + /* Finally set the memory properties */ + ((struct linux_romvec *)romvec)->pv_v0mem.v0_totphys = &totphyslist; + ((struct linux_romvec *)romvec)->pv_v0mem.v0_available = &availlist; + ((struct linux_romvec *)romvec)->pv_v0mem.v0_prommap = &prommaplist; +} + + +void boot(void) +{ + /* Boot preloaded kernel */ + if (kernel_size) { + printk("[sparc] Kernel already loaded\n"); + + PUSH(kernel_image); + feval("load-state >ls.entry !"); + + arch_init_program(); + start_elf(); + } +} |