scoutos / prex-0.9.0 / usr / server / boot / boot.c @ 03e9c04a
History | View | Annotate | Download (7.23 KB)
1 |
/*-
|
---|---|
2 |
* Copyright (c) 2005-2007, Kohsuke Ohtani
|
3 |
* All rights reserved.
|
4 |
*
|
5 |
* Redistribution and use in source and binary forms, with or without
|
6 |
* modification, are permitted provided that the following conditions
|
7 |
* are met:
|
8 |
* 1. Redistributions of source code must retain the above copyright
|
9 |
* notice, this list of conditions and the following disclaimer.
|
10 |
* 2. Redistributions in binary form must reproduce the above copyright
|
11 |
* notice, this list of conditions and the following disclaimer in the
|
12 |
* documentation and/or other materials provided with the distribution.
|
13 |
* 3. Neither the name of the author nor the names of any co-contributors
|
14 |
* may be used to endorse or promote products derived from this software
|
15 |
* without specific prior written permission.
|
16 |
*
|
17 |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
18 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
20 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
21 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
22 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
23 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
24 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
25 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
26 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
27 |
* SUCH DAMAGE.
|
28 |
*/
|
29 |
|
30 |
/*
|
31 |
* main.c - bootstrap server
|
32 |
*/
|
33 |
|
34 |
/*
|
35 |
* A bootstrap server works to setup the POSIX environment for
|
36 |
* 'init' process. It sends a setup message to other servers in
|
37 |
* order to let them know that this task becomes 'init' process.
|
38 |
* The bootstrap server is gone after it launches (exec) the
|
39 |
* 'init' process.
|
40 |
*/
|
41 |
|
42 |
#include <sys/prex.h> |
43 |
#include <sys/mount.h> |
44 |
#include <sys/stat.h> |
45 |
#include <sys/fcntl.h> |
46 |
#include <sys/syslog.h> |
47 |
|
48 |
#include <ipc/fs.h> |
49 |
#include <ipc/exec.h> |
50 |
#include <ipc/proc.h> |
51 |
#include <ipc/ipc.h> |
52 |
|
53 |
#include <unistd.h> |
54 |
#include <string.h> |
55 |
#include <stdlib.h> |
56 |
#include <stdio.h> |
57 |
#include <signal.h> |
58 |
#include <errno.h> |
59 |
|
60 |
#ifdef DEBUG
|
61 |
#define DPRINTF(a) sys_log a
|
62 |
#else
|
63 |
#define DPRINTF(a)
|
64 |
#endif
|
65 |
|
66 |
static const char *initargs[] = { "1", NULL }; |
67 |
static const char *initenvs[] = { "TERM=vt100", "USER=root", NULL }; |
68 |
|
69 |
static char iobuf[BUFSIZ]; |
70 |
|
71 |
/*
|
72 |
* Base directories at root.
|
73 |
*/
|
74 |
static char *base_dir[] = { |
75 |
"/bin", /* applications */ |
76 |
"/boot", /* system servers */ |
77 |
"/dev", /* device files */ |
78 |
"/etc", /* shareable read-only data */ |
79 |
"/mnt", /* mount point for file systems */ |
80 |
"/private", /* user's private data */ |
81 |
"/tmp", /* temporary files */ |
82 |
NULL
|
83 |
}; |
84 |
|
85 |
static void |
86 |
wait_server(const char *name, object_t *pobj) |
87 |
{ |
88 |
int i, error = 0; |
89 |
|
90 |
/* Give chance to run other servers. */
|
91 |
thread_yield(); |
92 |
|
93 |
/*
|
94 |
* Wait for server loading. timeout is 1 sec.
|
95 |
*/
|
96 |
for (i = 0; i < 100; i++) { |
97 |
error = object_lookup((char *)name, pobj);
|
98 |
if (error == 0) |
99 |
break;
|
100 |
|
101 |
/* Wait 10msec */
|
102 |
timer_sleep(10, 0); |
103 |
thread_yield(); |
104 |
} |
105 |
if (error)
|
106 |
sys_panic("boot: server not found");
|
107 |
} |
108 |
|
109 |
static void |
110 |
send_bootmsg(object_t obj) |
111 |
{ |
112 |
struct msg m;
|
113 |
int error;
|
114 |
|
115 |
m.hdr.code = STD_BOOT; |
116 |
error = msg_send(obj, &m, sizeof(m));
|
117 |
if (error)
|
118 |
sys_panic("boot: server error");
|
119 |
} |
120 |
|
121 |
static void |
122 |
mount_fs(void)
|
123 |
{ |
124 |
char line[128]; |
125 |
FILE *fp; |
126 |
char *spec, *file, *type, *p;
|
127 |
char nodev[] = ""; |
128 |
int i;
|
129 |
|
130 |
DPRINTF(("boot: mounting file systems\n"));
|
131 |
|
132 |
/*
|
133 |
* Mount root.
|
134 |
*/
|
135 |
if (mount("", "/", "ramfs", 0, NULL) < 0) |
136 |
sys_panic("boot: mount failed");
|
137 |
|
138 |
/*
|
139 |
* Create some default directories.
|
140 |
*/
|
141 |
i = 0;
|
142 |
while (base_dir[i] != NULL) { |
143 |
if (mkdir(base_dir[i], 0) == -1) |
144 |
sys_panic("boot: mkdir failed");
|
145 |
i++; |
146 |
} |
147 |
|
148 |
/*
|
149 |
* Mount file system for /boot.
|
150 |
*/
|
151 |
if (mount("/dev/ram0", "/boot", "arfs", 0, NULL) < 0) |
152 |
sys_panic("boot: mount failed");
|
153 |
|
154 |
/*
|
155 |
* Mount file systems described in fstab.
|
156 |
*/
|
157 |
if ((fp = fopen("/boot/fstab", "r")) == NULL) |
158 |
sys_panic("boot: no fstab");
|
159 |
|
160 |
for (;;) {
|
161 |
if ((p = fgets(line, sizeof(line), fp)) == NULL) |
162 |
break;
|
163 |
spec = strtok(p, " \t\n");
|
164 |
if (spec == NULL || *spec == '#') |
165 |
continue;
|
166 |
file = strtok(NULL, " \t\n"); |
167 |
type = strtok(NULL, " \t\n"); |
168 |
if (!strcmp(file, "/") || !strcmp(file, "/boot")) |
169 |
continue;
|
170 |
if (!strcmp(spec, "none")) |
171 |
spec = nodev; |
172 |
|
173 |
/* We create the mount point automatically */
|
174 |
mkdir(file, 0);
|
175 |
mount(spec, file, type, 0, 0); |
176 |
} |
177 |
fclose(fp); |
178 |
} |
179 |
|
180 |
static int |
181 |
exec_init(object_t execobj) |
182 |
{ |
183 |
struct exec_msg msg;
|
184 |
int error, i, argc, envc;
|
185 |
size_t bufsz; |
186 |
char *dest;
|
187 |
char const *src; |
188 |
|
189 |
DPRINTF(("boot: execute init\n"));
|
190 |
|
191 |
/* Get arg/env buffer size */
|
192 |
bufsz = 0;
|
193 |
argc = 0;
|
194 |
while (initargs[argc]) {
|
195 |
bufsz += (strlen(initargs[argc]) + 1);
|
196 |
argc++; |
197 |
} |
198 |
envc = 0;
|
199 |
while (initenvs[envc]) {
|
200 |
bufsz += (strlen(initenvs[envc]) + 1);
|
201 |
envc++; |
202 |
} |
203 |
if (bufsz >= ARG_MAX)
|
204 |
sys_panic("boot: args too long");
|
205 |
|
206 |
/*
|
207 |
* Build exec message.
|
208 |
*/
|
209 |
dest = msg.buf; |
210 |
for (i = 0; i < argc; i++) { |
211 |
src = initargs[i]; |
212 |
while ((*dest++ = *src++) != 0); |
213 |
} |
214 |
for (i = 0; i < envc; i++) { |
215 |
src = initenvs[i]; |
216 |
while ((*dest++ = *src++) != 0); |
217 |
} |
218 |
msg.hdr.code = EXEC_EXECVE; |
219 |
msg.argc = argc; |
220 |
msg.envc = envc; |
221 |
msg.bufsz = bufsz; |
222 |
strlcpy(msg.cwd, "/", sizeof(msg.cwd)); |
223 |
strlcpy(msg.path, "/boot/init", sizeof(msg.path)); |
224 |
|
225 |
do {
|
226 |
error = msg_send(execobj, &msg, sizeof(msg));
|
227 |
/*
|
228 |
* If exec server can execute new process
|
229 |
* properly, it will terminate the caller task
|
230 |
* automatically. So, the control never comes
|
231 |
* here in that case.
|
232 |
*/
|
233 |
} while (error == EINTR);
|
234 |
return -1; |
235 |
} |
236 |
|
237 |
static void |
238 |
copy_file(char *src, char *dest) |
239 |
{ |
240 |
int fold, fnew, n;
|
241 |
struct stat stbuf;
|
242 |
mode_t mode; |
243 |
|
244 |
if ((fold = open(src, O_RDONLY)) == -1) |
245 |
return;
|
246 |
|
247 |
fstat(fold, &stbuf); |
248 |
mode = stbuf.st_mode; |
249 |
|
250 |
if ((fnew = creat(dest, mode)) == -1) { |
251 |
close(fold); |
252 |
return;
|
253 |
} |
254 |
while ((n = read(fold, iobuf, BUFSIZ)) > 0) { |
255 |
if (write(fnew, iobuf, (size_t)n) != n) {
|
256 |
close(fold); |
257 |
close(fnew); |
258 |
return;
|
259 |
} |
260 |
} |
261 |
close(fold); |
262 |
close(fnew); |
263 |
} |
264 |
|
265 |
int
|
266 |
main(int argc, char *argv[]) |
267 |
{ |
268 |
object_t execobj, procobj, fsobj; |
269 |
struct bind_msg bm;
|
270 |
struct msg m;
|
271 |
|
272 |
sys_log("Starting bootstrap server\n");
|
273 |
|
274 |
thread_setpri(thread_self(), PRI_DEFAULT); |
275 |
|
276 |
/*
|
277 |
* Wait until all required system servers
|
278 |
* become available.
|
279 |
*/
|
280 |
wait_server("!proc", &procobj);
|
281 |
wait_server("!fs", &fsobj);
|
282 |
wait_server("!exec", &execobj);
|
283 |
|
284 |
/*
|
285 |
* Send boot message to all servers.
|
286 |
* This is required to synchronize the server
|
287 |
* initialization without deadlock.
|
288 |
*/
|
289 |
send_bootmsg(execobj); |
290 |
send_bootmsg(procobj); |
291 |
send_bootmsg(fsobj); |
292 |
|
293 |
/*
|
294 |
* Request to bind a new capabilities for us.
|
295 |
*/
|
296 |
bm.hdr.code = EXEC_BINDCAP; |
297 |
strlcpy(bm.path, "/boot/boot", sizeof(bm.path)); |
298 |
msg_send(execobj, &bm, sizeof(bm));
|
299 |
|
300 |
/*
|
301 |
* Register this process as 'init'.
|
302 |
* We will become an init process later.
|
303 |
*/
|
304 |
m.hdr.code = PS_SETINIT; |
305 |
msg_send(procobj, &m, sizeof(m));
|
306 |
|
307 |
/*
|
308 |
* Initialize a library for file I/O.
|
309 |
*/
|
310 |
fslib_init(); |
311 |
|
312 |
/*
|
313 |
* Mount file systems.
|
314 |
*/
|
315 |
mount_fs(); |
316 |
|
317 |
/*
|
318 |
* Copy some files.
|
319 |
* Note that almost applications including 'init'
|
320 |
* does not have an access right to /boot directory...
|
321 |
*/
|
322 |
copy_file("/boot/rc", "/etc/rc"); |
323 |
copy_file("/boot/fstab", "/etc/fstab"); |
324 |
|
325 |
/*
|
326 |
* Exec first application.
|
327 |
*/
|
328 |
exec_init(execobj); |
329 |
|
330 |
sys_panic("boot: failed to exec init");
|
331 |
|
332 |
/* NOTREACHED */
|
333 |
return 0; |
334 |
} |