diff --git a/stand/powerpc/kboot/Makefile b/stand/powerpc/kboot/Makefile --- a/stand/powerpc/kboot/Makefile +++ b/stand/powerpc/kboot/Makefile @@ -17,9 +17,10 @@ INSTALLFLAGS= -b # Architecture-specific loader code -SRCS= conf.c vers.c main.c ppc64_elf_freebsd.c -SRCS+= host_syscall.S hostcons.c hostdisk.c kerneltramp.S kbootfdt.c -SRCS+= ucmpdi2.c gfx_fb.c +SRCS= host_init.S host_syscall.S +SRCS+= conf.c vers.c main.c ppc64_elf_freebsd.c +SRCS+= hostcons.c hostdisk.c kerneltramp.S +SRCS+= kbootfdt.c ucmpdi2.c gfx_fb.c CFLAGS.gfx_fb.c += -I${SRCTOP}/contrib/pnglite CFLAGS.gfx_fb.c += -I${SRCTOP}/sys/teken diff --git a/stand/powerpc/kboot/host_init.S b/stand/powerpc/kboot/host_init.S new file mode 100644 --- /dev/null +++ b/stand/powerpc/kboot/host_init.S @@ -0,0 +1,51 @@ +/* + * + * $FreeBSD$ + */ + +#include + +/* + * Linux-style entry point: + * r1: Initial sp + * r2: Intialized by ENTRY macro + * r3: Need to load argc + * r4: Need to load argv + * r5: Need to load envp + * r6: Need to load auxv + * r7: atexit pointer or 0 + */ +ENTRY(_start) + /* Use r6 to traverse the stack. */ + mr %r6, %r1 + + /* Set up initial stack frame. */ + addi %r1, %r1, -16 + /* Ensure we're aligned. */ + clrrwi %r1, %r1, 4 + + li %r0, 0 + /* Ensure the backchain is disconnected. */ + stw %r0, 0(%r1) + + lwz %r3, 0(%r6) /* argc */ + addi %r6, %r6, 4 /* next dword */ + mr %r4, %r6 /* argv */ + mulli %r5, %r3, 4 /* compute argv size */ + add %r6, %r6, %r5 /* skip over argv */ + addi %r6, %r6, 4 /* next dword */ + mr %r5, %r6 /* envp */ + /* + * Don't bother with auxv for now. If we end up needing it, it's a + * word past the first null pointer in envp. + */ + li %r6, 0 + + /* This appears to be set to &_start on PPC32. We don't care. */ + li %r7, 0 + + bl main + /* Exit via syscall. */ + b host_exit + +END(_start) diff --git a/stand/powerpc/kboot/host_syscall.S b/stand/powerpc/kboot/host_syscall.S --- a/stand/powerpc/kboot/host_syscall.S +++ b/stand/powerpc/kboot/host_syscall.S @@ -5,6 +5,12 @@ #include +ENTRY(host_exit) + li %r0, 1 # SYS_exit + sc + trap +END(host_exit) + ENTRY(host_read) li %r0, 3 # SYS_read sc @@ -42,7 +48,7 @@ bso 1f blr 1: - li %r3, 0 + li %r3, -1 blr END(host_open) diff --git a/stand/powerpc/kboot/ldscript.powerpc b/stand/powerpc/kboot/ldscript.powerpc --- a/stand/powerpc/kboot/ldscript.powerpc +++ b/stand/powerpc/kboot/ldscript.powerpc @@ -18,7 +18,7 @@ *(.gnu.linkonce.t*) } =0 _etext = .; - .interp : { *(.interp) } + /DISCARD/ : { *(.interp) } .hash : { *(.hash) } .dynsym : { *(.dynsym) } .dynstr : { *(.dynstr) } @@ -42,24 +42,25 @@ .rela.plt : { *(.rela.plt) } .rela.sbss : { *(.rela.sbss) } .rela.sbss2 : { *(.rela.sbss2) } - .text : - { - *(.text) - /* .gnu.warning sections are handled specially by elf32.em. */ - *(.gnu.warning) - *(.gnu.linkonce.t*) - } =0 - _etext = .; - PROVIDE (etext = .); .init : { *(.init) } =0 .fini : { *(.fini) } =0 + + /* + * If the linker wants rodata, ensure it is page aligned. + * + * This works around a PS3 petitboot bug where alignment would be ignored + * and the last text page would have its execution permission removed. + */ + . = ((. + 0x1000) & ~(0x1000 - 1)); .rodata : { *(.rodata) *(.gnu.linkonce.r*) } .rodata1 : { *(.rodata1) } .sbss2 : { *(.sbss2) } + .eh_frame_hdr : { *(.eh_frame_hdr) } /* Adjust the address for the data segment to the next page up. */ . = ((. + 0x1000) & ~(0x1000 - 1)); .data : { + *(.data.rel.ro) /* Skip extra section creation */ *(.data) *(.gnu.linkonce.d*) CONSTRUCTORS diff --git a/stand/powerpc/kboot/main.c b/stand/powerpc/kboot/main.c --- a/stand/powerpc/kboot/main.c +++ b/stand/powerpc/kboot/main.c @@ -250,11 +250,12 @@ } int -main(int argc, const char **argv) +main(int argc, const char **argv, char **envp) { void *heapbase; const size_t heapsize = 15*1024*1024; const char *bootdev; + char **env; /* * Set the heap to one page after the end of the loader. @@ -262,6 +263,12 @@ heapbase = host_getmem(heapsize); setheap(heapbase, heapbase + heapsize); + /* + * Copy out environment. + */ + for (env = envp; *env != NULL; env++) + putenv(*env); + /* * Set up console. */ @@ -480,23 +487,6 @@ *ptr = &loaded_segments[0]; } -void -_start(int argc, const char **argv, char **env) -{ -// This makes error "variable 'sp' is uninitialized" be just a warning on clang. -// Initializing 'sp' is not desired here as it would overwrite "r1" original value -#if defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic warning "-Wuninitialized" -#endif - register volatile void **sp asm("r1"); - main((int)sp[0], (const char **)&sp[1]); -#if defined(__clang__) -#pragma clang diagnostic pop -#endif - -} - /* * Since proper fdt command handling function is defined in fdt_loader_cmd.c, * and declaring it as extern is in contradiction with COMMAND_SET() macro