load modules common to all linux revisions
[cinitramfs.git] / init.c
blob7b620a42d6b31af69dc0cc714d95eceb240128d5
1 /*******************************************************************************
2 this code is protected by the GNU affero GPLv3
3 author:Sylvain BERTRAND <sylvain.bertrand AT gmail dot com>
4 *******************************************************************************/
5 /*
6 we use libraries based on C posix runtime, then we need this to fetch
7 environment variables from the C posix runtime
8 */
9 #include <stdlib.h>
11 #include <ulinux/compiler_types.h>
12 #include <ulinux/sysc.h>
13 #include <ulinux/types.h>
14 #include <ulinux/error.h>
15 #include <ulinux/fs.h>
16 #include <ulinux/signal/signal.h>
17 #include <ulinux/utils/mem.h>
18 #include <ulinux/utils/ascii/string/string.h>
20 #define INIT_C
21 #include "out.h"
22 #include "ulinux_namespace.h"
23 #include "modules.h"
24 #include "uevents.h"
25 #include "ramfs.h"
26 #include "globals.h"
27 #undef INIT_C
29 static void sigs_setup(void)
31 ul mask=(~0);
32 l r;
34 OUT(PRE "setting up signals...\n");
35 r=rt_sigprocmask(SIG_BLOCK,&mask,0,sizeof(mask));
36 if(ISERR(r)){
37 OUT("ERROR:unable to block all signals (except KILL and STOP)\n");
38 exit_group(-1);
40 OUT("done\n");
43 static void sysfs_mount(void)
45 OUT(PRE "mounting sysfs...\n");
46 l r=mount(0,"/sys","sysfs",MS_NOATIME|MS_NODIRATIME,0);
47 if(ISERR(r)){
48 OUT("ERROR(%ld):unable to mount sysfs\n",r);
49 exit_group(-1);
53 static void sysfs_umount(void)
55 OUT(PRE "umounting sysfs...\n");
56 l r=umount("/sys");
57 if(ISERR(r)){
58 OUT("ERROR(%ld):unable to umount sysfs\n",r);
59 exit_group(-1);
63 static void proc_mount(void)
65 OUT(PRE "mounting proc...\n");
66 l r=mount(0,"/proc","proc",MS_NOATIME|MS_NODIRATIME,0);
67 if(ISERR(r)){
68 OUT("ERROR(%ld):unable to mount proc\n",r);
69 exit_group(-1);
73 static void proc_umount(void)
75 OUT(PRE "umounting proc...\n");
76 l r=umount("/proc");
77 if(ISERR(r)){
78 OUT("ERROR(%ld):unable to umount proc\n",r);
79 exit_group(-1);
83 static void devtmpfs_mount(void)
85 OUT(PRE "mounting devtmpfs...\n");
86 l r=mount(0,"/dev","devtmpfs",MS_NOATIME|MS_NODIRATIME,0);
87 if(ISERR(r)){
88 OUT("ERROR(%ld):unable to mount devtmpfs\n",r);
89 exit_group(-1);
93 static void devtmpfs_umount(void)
95 OUT(PRE "umounting devtmpfs...\n");
96 l r=umount("/dev");
97 if(ISERR(r)){
98 OUT("ERROR(%ld):unable to umount devtmpfs\n",r);
99 exit_group(-1);
103 static void newroot_mount(void)
105 OUT(PRE "mounting root device %s on /newroot, root file system is %s...\n",
106 root_dev_path,root_fs_type);
107 l r=mount(root_dev_path,"/newroot",root_fs_type,MS_NOATIME|MS_NODIRATIME,0);
108 if(ISERR(r)){
109 OUT("ERROR(%ld):unable to mount root\n",r);
110 exit_group(-1);
114 static void newroot_chdir()
116 OUT(PRE "chdir to /newroot...");
117 l r=chdir("/newroot");
118 if(ISERR(r)){
119 OUT("ERROR(%ld):unable to chdir to /newroot\n",r);
120 exit_group(-1);
122 OUT("done\n");
125 static void newroot_move(void)
127 OUT(PRE "mount moving . (/newroot) to / ...");
128 l r=mount(".","/",0,MS_MOVE,0);
129 if(ISERR(r)){
130 OUT("ERROR(%ld):unable to mount move . (/newroot) to /\n",r);
131 exit_group(-1);
133 OUT("done\n");
136 static void newroot_chroot(void)
138 OUT(PRE "chroot to . (/newroot)...");
139 l r=chroot(".");
140 if(ISERR(r)){
141 OUT("ERROR(%ld):unable to chroot to . (/newroot)\n",r);
142 exit_group(-1);
144 OUT("done\n");
147 /*this parameter *must* be around*/
148 #define PARAM_NAME "cinitramfs_root_uuid"
149 static void root_uuid_get(i argc, c **argv)
151 u8 arg;
153 /*we should use libc getenv to be friendly with the C runtime*/
154 root_uuid=(u8*)getenv(PARAM_NAME);
155 if(root_uuid) return;
157 /*it's not in the environment, then could be in argv, see
158 Documentation/kernel-parameters.txt*/
160 if(argc==1) goto fatal_err;
162 arg=1;
163 loop{
164 if(strncmp(argv[arg],PARAM_NAME,sizeof(PARAM_NAME)-1)==0) break;
165 if(++arg==argc) goto fatal_err;
167 root_uuid=(u8*)argv[arg];
168 loop if(*root_uuid++==(u8)'=') break;/*lookup for the key/value separator*/
169 return;
171 fatal_err:
172 OUT(PRE "ERROR:unable to find " PARAM_NAME "\n");
173 exit_group(-1);
175 #undef PARAM_NAME
177 static void command_line_parse(i argc, c **argv)
179 root_uuid_get(argc, argv);
183 fds 0,1 and 2 are rw /dev/console, see linux/init/main.
184 Since we use standard C libs, be nice with the C runtime and use main instead of
185 _start entry point.
187 i main(i argc,c **argv)
189 u8 r0;
190 l r1;
191 #ifndef QUIET
192 static u8 dprintf_buf[DPRINTF_BUF_SZ];
193 g_dprintf_buf=dprintf_buf;
194 #endif
195 sigs_setup();
196 command_line_parse(argc,argv);
197 uevents_setup();
198 sysfs_mount();
199 proc_mount();
200 devtmpfs_mount();
201 modules_setup();
202 modules_probe_static();
203 modules_probe_drivers();
204 r0=uevents_process();
205 if(r0==ROOT_NOT_FOUND){
206 OUT(PRE "terminating cinitramfs since no proper root was found\n");
207 exit_group(-1);
209 /*from here, we located our root*/
210 uevents_cleanup();
211 modules_probe_name(root_fs_type);
212 modules_cleanup();
213 newroot_mount();
214 devtmpfs_umount();
215 proc_umount();
216 sysfs_umount();
217 ramfs_cleanup();
219 newroot_chdir();
220 newroot_move();
221 newroot_chroot();
223 r1=execve("/bin/init");
224 if(ISERR(r1)){OUT("ERROR(%ld):unable to execve /bin/init\n",r1);}
225 exit_group(-1);
226 /*unreachable*/