Magellan Linux

Contents of /trunk/mkinitrd-magellan/klibc/usr/klibc/libc_init.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 532 - (show annotations) (download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 8 months ago) by niro
File MIME type: text/plain
File size: 2500 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd

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 /*
16 * Several Linux ABIs don't pass the onexit pointer, and the ones that
17 * do never use it. Therefore, unless USE_ONEXIT is defined, we just
18 * ignore the onexit pointer.
19 */
20 /* #define USE_ONEXIT */
21
22 #include <stddef.h>
23 #include <stdlib.h>
24 #include <stdint.h>
25 #include <klibc/compiler.h>
26 #include <elf.h>
27 #include "atexit.h"
28
29 /* This file is included from __static_init.c or __shared_init.c */
30 #ifndef SHARED
31 # error "SHARED should be defined to 0 or 1"
32 #endif
33
34 char **environ;
35 unsigned int __page_size, __page_shift;
36
37 struct auxentry {
38 uintptr_t type;
39 uintptr_t v;
40 };
41
42 __noreturn __libc_init(uintptr_t * elfdata, void (*onexit) (void))
43 {
44 int argc;
45 char **argv, **envp, **envend;
46 struct auxentry *auxentry;
47 #if SHARED
48 typedef int (*main_t) (int, char **, char **);
49 main_t MAIN = NULL;
50 #else
51 extern int main(int, char **, char **);
52 #define MAIN main
53 #endif
54 unsigned int page_size = 0, page_shift = 0;
55
56 #ifdef USE_ONEXIT
57 if (onexit) {
58 static struct atexit at_exit;
59
60 at_exit.fctn = (void (*)(int, void *))onexit;
61 /* at_exit.next = NULL already */
62 __atexit_list = &at_exit;
63 }
64 #else
65 (void)onexit; /* Ignore this... */
66 #endif
67
68 argc = (int)*elfdata++;
69 argv = (char **)elfdata;
70 envp = argv + (argc + 1);
71
72 /* The auxillary entry vector is after all the environment vars */
73 for (envend = envp; *envend; envend++) ;
74 auxentry = (struct auxentry *)(envend + 1);
75
76 while (auxentry->type) {
77 switch (auxentry->type) {
78 #if SHARED
79 case AT_ENTRY:
80 MAIN = (main_t) (auxentry->v);
81 break;
82 #endif
83 case AT_PAGESZ:
84 page_size = (unsigned int)(auxentry->v);
85 break;
86 }
87 auxentry++;
88 }
89
90 __page_size = page_size;
91
92 #if __GNUC__ >= 4
93 /* unsigned int is 32 bits on all our architectures */
94 page_shift = __builtin_clz(page_size) ^ 31;
95 #elif defined(__i386__) || defined(__x86_64__)
96 asm("bsrl %1,%0": "=r"(page_shift):"r"(page_size));
97 #else
98 while (page_size > 1) {
99 page_shift++;
100 page_size >>= 1;
101 }
102 #endif
103 __page_shift = page_shift;
104
105 environ = envp;
106 exit(MAIN(argc, argv, envp));
107 }