162306a36Sopenharmony_ci/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * C Run Time support for NOLIBC
462306a36Sopenharmony_ci * Copyright (C) 2023 Zhangjin Wu <falcon@tinylab.org>
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#ifndef _NOLIBC_CRT_H
862306a36Sopenharmony_ci#define _NOLIBC_CRT_H
962306a36Sopenharmony_ci
1062306a36Sopenharmony_cichar **environ __attribute__((weak));
1162306a36Sopenharmony_ciconst unsigned long *_auxv __attribute__((weak));
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_cistatic void __stack_chk_init(void);
1462306a36Sopenharmony_cistatic void exit(int);
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci__attribute__((weak))
1762306a36Sopenharmony_civoid _start_c(long *sp)
1862306a36Sopenharmony_ci{
1962306a36Sopenharmony_ci	long argc;
2062306a36Sopenharmony_ci	char **argv;
2162306a36Sopenharmony_ci	char **envp;
2262306a36Sopenharmony_ci	const unsigned long *auxv;
2362306a36Sopenharmony_ci	/* silence potential warning: conflicting types for 'main' */
2462306a36Sopenharmony_ci	int _nolibc_main(int, char **, char **) __asm__ ("main");
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci	/* initialize stack protector */
2762306a36Sopenharmony_ci	__stack_chk_init();
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci	/*
3062306a36Sopenharmony_ci	 * sp  :    argc          <-- argument count, required by main()
3162306a36Sopenharmony_ci	 * argv:    argv[0]       <-- argument vector, required by main()
3262306a36Sopenharmony_ci	 *          argv[1]
3362306a36Sopenharmony_ci	 *          ...
3462306a36Sopenharmony_ci	 *          argv[argc-1]
3562306a36Sopenharmony_ci	 *          null
3662306a36Sopenharmony_ci	 * environ: environ[0]    <-- environment variables, required by main() and getenv()
3762306a36Sopenharmony_ci	 *          environ[1]
3862306a36Sopenharmony_ci	 *          ...
3962306a36Sopenharmony_ci	 *          null
4062306a36Sopenharmony_ci	 * _auxv:   _auxv[0]      <-- auxiliary vector, required by getauxval()
4162306a36Sopenharmony_ci	 *          _auxv[1]
4262306a36Sopenharmony_ci	 *          ...
4362306a36Sopenharmony_ci	 *          null
4462306a36Sopenharmony_ci	 */
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	/* assign argc and argv */
4762306a36Sopenharmony_ci	argc = *sp;
4862306a36Sopenharmony_ci	argv = (void *)(sp + 1);
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	/* find environ */
5162306a36Sopenharmony_ci	environ = envp = argv + argc + 1;
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci	/* find _auxv */
5462306a36Sopenharmony_ci	for (auxv = (void *)envp; *auxv++;)
5562306a36Sopenharmony_ci		;
5662306a36Sopenharmony_ci	_auxv = auxv;
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	/* go to application */
5962306a36Sopenharmony_ci	exit(_nolibc_main(argc, argv, envp));
6062306a36Sopenharmony_ci}
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci#endif /* _NOLIBC_CRT_H */
63