chiark / gitweb /
[PATCH] klibc: update to version 0.196
[elogind.git] / klibc / klibc / libc_init.c
1 /*
2  * libc_init.c
3  *
4  * This function takes the raw data block set up by the ELF loader
5  * in the kernel and parses it.  It is invoked by crt0.S which makes
6  * any necessary adjustments and passes calls this function using
7  * the standard C calling convention.
8  *
9  * The arguments are:
10  *  uintptr_t *elfdata   -- The ELF loader data block; usually from the stack.
11  *                          Basically a pointer to argc.
12  *  void (*onexit)(void) -- Function to install into onexit
13  */
14
15 #include <stddef.h>
16 #include <stdlib.h>
17 #include <stdint.h>
18 #include <klibc/compiler.h>
19 #include <elf.h>
20
21 /* This file is included from __static_init.c or __shared_init.c */
22 #ifndef SHARED
23 # error "SHARED should be defined to 0 or 1"
24 #endif
25
26 char **environ;
27 unsigned int __page_size, __page_shift;
28
29 struct auxentry {
30   uintptr_t type;
31   uintptr_t v;
32 };
33
34 __noreturn __libc_init(uintptr_t *elfdata, void (*onexit)(void))
35 {
36   int argc;
37   char **argv, **envp, **envend;
38   struct auxentry *auxentry;
39 #if SHARED
40   typedef int (*main_t)(int, char **, char **);
41   main_t MAIN = NULL;
42 #else
43   extern int main(int, char **, char **);
44 #define MAIN main
45 #endif
46   unsigned int page_size = 0, page_shift = 0;
47
48   (void)onexit;                 /* For now, we ignore this... */
49
50   argc = (int)*elfdata++;
51   argv = (char **)elfdata;
52   envp = argv+(argc+1);
53
54   /* The auxillary entry vector is after all the environment vars */
55   for ( envend = envp ; *envend ; envend++ );
56   auxentry = (struct auxentry *)(envend+1);
57
58   while ( auxentry->type ) {
59     switch ( auxentry->type ) {
60 #if SHARED
61     case AT_ENTRY:
62       MAIN = (main_t)(auxentry->v);
63       break;
64 #endif
65     case AT_PAGESZ:
66       page_size = (int)(auxentry->v);
67       break;
68     }
69     auxentry++;
70   }
71
72   __page_size = page_size;
73
74 #if defined(__i386__) || defined(__x86_64__)
75   asm("bsrl %1,%0" : "=r" (page_shift) : "rm" (page_size));
76 #else
77   while ( page_size > 1 ) {
78     page_shift++;
79     page_size >>= 1;
80   }
81 #endif
82   __page_shift = page_shift;
83
84   environ = envp;
85   exit(MAIN(argc, argv, envp));
86 }