Contents of /trunk/mkinitrd-magellan/klibc/usr/klibc/libc_init.c
Parent Directory | 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)
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 | } |