git: f5ed1b0f84bf - main - kboot: Rework _start
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 15 Jul 2022 18:03:52 UTC
The branch main has been updated by imp:
URL: https://cgit.FreeBSD.org/src/commit/?id=f5ed1b0f84bf06839f0947981ebdb3646c3c433a
commit f5ed1b0f84bf06839f0947981ebdb3646c3c433a
Author: Warner Losh <imp@FreeBSD.org>
AuthorDate: 2022-07-14 03:41:17 +0000
Commit: Warner Losh <imp@FreeBSD.org>
CommitDate: 2022-07-15 18:00:49 +0000
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
---
stand/kboot/Makefile | 3 +-
stand/kboot/arch/amd64/start_arch.h | 34 +++++++++++++++
stand/kboot/arch/powerpc64/start_arch.h | 30 +++++++++++++
stand/kboot/crt1.c | 74 +++++++++++++++++++++++++++++++++
stand/kboot/main.c | 6 ---
5 files changed, 140 insertions(+), 7 deletions(-)
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