kboot: Rework _start

Split _start into _start and _start_c (inspired by musl and the powerpc
impl is copied from there). This allows us to actually get the command
line arguments on all the platforms. We have a very simplified startup
that supports only static linking.

Sponsored by:		Netflix
This commit is contained in:
Warner Losh 2022-07-13 21:41:17 -06:00
parent c1bbe71104
commit f5ed1b0f84
5 changed files with 140 additions and 7 deletions

View File

@ -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

View File

@ -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"
);

View File

@ -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);
}

74
stand/kboot/crt1.c Normal file
View File

@ -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);
}

View File

@ -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