Statistics
| Branch: | Revision:

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
}