diff --git a/stand/kboot/Makefile b/stand/kboot/Makefile index 24ab77af66db..ce0868264acf 100644 --- a/stand/kboot/Makefile +++ b/stand/kboot/Makefile @@ -1,5 +1,6 @@ # $FreeBSD$ +LOADER_DISK_SUPPORT?= yes LOADER_CD9660_SUPPORT?= yes LOADER_MSDOS_SUPPORT?= no LOADER_EXT2FS_SUPPORT?= yes @@ -17,7 +18,7 @@ NEWVERSWHAT= "kboot loader" ${MACHINE_ARCH} INSTALLFLAGS= -b # Architecture-specific loader code -SRCS= vers.c main.c host_syscalls.c hostcons.c hostdisk.c kbootfdt.c gfx_fb_stub.c +SRCS= crt1.c vers.c main.c host_syscalls.c hostcons.c hostdisk.c kbootfdt.c gfx_fb_stub.c CFLAGS.gfx_fb_stub.c += -I${SRCTOP}/contrib/pnglite -I${SRCTOP}/sys/teken diff --git a/stand/kboot/arch/amd64/start_arch.h b/stand/kboot/arch/amd64/start_arch.h new file mode 100644 index 000000000000..57c514daf019 --- /dev/null +++ b/stand/kboot/arch/amd64/start_arch.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022, Netflix, Inc. + * + * SPDX-Licnse-Identifier: BSD-2-Clause + */ + +/* + * Provides a _start routine that calls a _start_c routine that takes a pointer + * to the stack as documented in crt1.c. We skip the pointer to _DYNAMIC since + * we don't support dynamic libraries, at all. And while _start_c is our own + * thing, we comport to the calling conventions that glibc and musl have and + * make sure the second argument (%esi) is 0 for _DYNAMIC placeholder. We + * likely could call main directly with only a few more lines of code, but this + * is simple enough and concentrates all the expressable in C stuff there. We + * also generate eh_frames should we need to debug things (it doesn't change the + * genreated code, but leaves enough breadcrumbs to keep gdb happy). + */ + +__asm__( +".text\n" /* ENTRY(_start) */ +".p2align 4,0x90\n" +".global _start\n" +".type _start, @function\n" +"_start:\n" +".cfi_startproc\n" +" xor %rbp, %rbp\n" /* Clear out the stack frame pointer */ +" mov %rsp, %rdi\n" /* Pass pointer to current stack with argc, argv and envp on it */ +" xor %rsi, %rsi\n" /* No dynamic pointer for us, to keep it simple */ +" andq $-16, %rsp\n" /* Align stack to 16-byte boundary */ +" call _start_c\n" /* Our MI code takes it from here and won't return */ +/* NORETURN */ +".size _start, . - _start\n" /* END(_start) */ +".cfi_endproc" +); diff --git a/stand/kboot/arch/powerpc64/start_arch.h b/stand/kboot/arch/powerpc64/start_arch.h new file mode 100644 index 000000000000..cd2fad433cde --- /dev/null +++ b/stand/kboot/arch/powerpc64/start_arch.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022 Netflix, Inc + * + * SPDX-Licnse-Identifier: BSD-2-Clause + */ + +/* + * Due to the PowerPC ABI, We can call main directly from here, so do so. + * + * Note: there may be some static initializers that aren't called, but we don't + * worry about that elsewhere. This is a stripped down environment. + * + * I think we could also do something like + * + * mflr r0 + * stw r0,4(r1) + * stwu r1,-16(r1) + * b _start_c + * + * But my powerpc assembler fu is quite lacking... + */ + +#define __unused __attribute__((__unused__)) + +void +_start(int argc, const char **argv, char **env, void *obj __unused, + void (*cleanup)(void) __unused) +{ + main(argc, argv, env); +} diff --git a/stand/kboot/crt1.c b/stand/kboot/crt1.c new file mode 100644 index 000000000000..c4525ad6c35e --- /dev/null +++ b/stand/kboot/crt1.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2022, Netflix, Inc. + * + * SPDX-Licnse-Identifier: BSD-2-Clause + */ + +/* + * MI part of the C startup code. We take a long * pointer (we assume long is + * the same size as a pointer, as the Linux world is wont to do). We get a + * pointer to the stack with the main args on it. We don't bother decoding the + * aux vector, but may need to do so in the future. + * + * The long *p points to: + * + * +--------------------+ + * | argc | Small address + * +--------------------+ + * | argv[0] | argv + * +--------------------+ + * | argv[1] | + * +--------------------+ + * ... + * +--------------------+ + * | NULL | &argv[argc] + * +--------------------+ + * | envp[0] | envp + * +--------------------+ + * | envp[1] | + * +--------------------+ + * ... + * +--------------------+ + * | NULL | + * +--------------------+ + * | aux type | AT_xxxx + * +--------------------+ + * | aux value | + * +--------------------+ + * | aux type | AT_xxxx + * +--------------------+ + * | aux value | + * +--------------------+ + * | aux type | AT_xxxx + * +--------------------+ + * | aux value | + * +--------------------+ + *... + * +--------------------+ + * | NULL | + * +--------------------+ + * + * The AUX vector contains additional information for the process to know from + * the kernel (not parsed currently). AT_xxxx constants are small (< 50). + */ + +extern void _start_c(long *); +extern int main(int, const char **, char **); + +#include "start_arch.h" + +void +_start_c(long *p) +{ + int argc; + const char **argv; + char **envp; + + argc = p[0]; + argv = (const char **)(p + 1); + envp = (char **)argv + argc + 1; + + /* Note: we don't ensure that fd 0, 1, and 2 are sane at this level */ + /* Also note: we expect main to exit, not return off the end */ + main(argc, argv, envp); +} diff --git a/stand/kboot/main.c b/stand/kboot/main.c index 9b99c859070b..90b31a611476 100644 --- a/stand/kboot/main.c +++ b/stand/kboot/main.c @@ -479,12 +479,6 @@ kboot_kseg_get(int *nseg, void **ptr) *ptr = &loaded_segments[0]; } -void -_start(int argc, const char **argv, char **env) -{ - main(argc, argv); -} - /* * 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