diff --git a/src/system/boot/platform/openfirmware/arch/sparc/arch_start_kernel.S b/src/system/boot/platform/openfirmware/arch/sparc/arch_start_kernel.S index 54bc658dbc..a8346900ec 100644 --- a/src/system/boot/platform/openfirmware/arch/sparc/arch_start_kernel.S +++ b/src/system/boot/platform/openfirmware/arch/sparc/arch_start_kernel.S @@ -8,9 +8,40 @@ /* status_t arch_start_kernel(struct kernel_args *kernelArgs, addr_t kernelEntry, addr_t kernelStackTop); - r3 - kernelArgs - r4 - kernelEntry - r5 - kernelStackTop + o0 - kernelArgs + o1 - kernelEntry + o2 - kernelStackTop */ FUNCTION(arch_start_kernel): - return + save %sp, -176, %sp + + // Now we have + // - Kernel args in i0 + // - Kernel entry in i1 + // - Kernel stack top in i2 + + // Set the stack, adding the stack bias + sub %i2, 2047, %sp // apply stack bias + + // We need to call the kernel with: + // o0 = kernel args + // o1 = current CPU + mov %i0, %o0 + // Current CPU is always 0 on boot + mov %g0, %o1 + + // Jump into the kernel, store return address in o7 + jmpl %i1, %o7 + nop // branch delay slot... + + // We should never get here, but in case the kernel returns, attempt to + // exit cleanly. + + // Forward the return code to the caller + mov %o0, %i0 + + // Since we saved our context at the start of this function, + // a simple "return" should do the job and restore the previous register + // window and put us back on the old stack + return %i7 + 8 + nop // Branch delay slot... diff --git a/src/system/boot/platform/openfirmware/start.cpp b/src/system/boot/platform/openfirmware/start.cpp index ac3f5cde60..08ad90b367 100644 --- a/src/system/boot/platform/openfirmware/start.cpp +++ b/src/system/boot/platform/openfirmware/start.cpp @@ -45,13 +45,27 @@ call_ctors(void) } +static addr_t +get_kernel_entry(void) +{ + if (gKernelArgs.kernel_image->elf_class == ELFCLASS64) { + preloaded_elf64_image *image = static_cast( + gKernelArgs.kernel_image.Pointer()); + return image->elf_header.e_entry; + } else if (gKernelArgs.kernel_image->elf_class == ELFCLASS32) { + preloaded_elf32_image *image = static_cast( + gKernelArgs.kernel_image.Pointer()); + return image->elf_header.e_entry; + } + panic("Unknown kernel format! Not 32-bit or 64-bit!"); + return 0; +} + + extern "C" void platform_start_kernel(void) { - preloaded_elf32_image* image = static_cast( - gKernelArgs.kernel_image.Pointer()); - - addr_t kernelEntry = image->elf_header.e_entry; + addr_t kernelEntry = get_kernel_entry(); addr_t stackTop = gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size;