Subversion Repositories HelenOS

Rev

Rev 4348 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4348 Rev 4691
1
/*
1
/*
2
 * Copyright (c) 2008 Jiri Svoboda
2
 * Copyright (c) 2008 Jiri Svoboda
3
 * All rights reserved.
3
 * All rights reserved.
4
 *
4
 *
5
 * Redistribution and use in source and binary forms, with or without
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
6
 * modification, are permitted provided that the following conditions
7
 * are met:
7
 * are met:
8
 *
8
 *
9
 * - Redistributions of source code must retain the above copyright
9
 * - Redistributions of source code must retain the above copyright
10
 *   notice, this list of conditions and the following disclaimer.
10
 *   notice, this list of conditions and the following disclaimer.
11
 * - Redistributions in binary form must reproduce the above copyright
11
 * - Redistributions in binary form must reproduce the above copyright
12
 *   notice, this list of conditions and the following disclaimer in the
12
 *   notice, this list of conditions and the following disclaimer in the
13
 *   documentation and/or other materials provided with the distribution.
13
 *   documentation and/or other materials provided with the distribution.
14
 * - The name of the author may not be used to endorse or promote products
14
 * - The name of the author may not be used to endorse or promote products
15
 *   derived from this software without specific prior written permission.
15
 *   derived from this software without specific prior written permission.
16
 *
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 */
27
 */
28
 
28
 
29
/** @addtogroup loader
29
/** @addtogroup loader
30
 * @brief Loads and runs programs from VFS.
30
 * @brief Loads and runs programs from VFS.
31
 * @{
31
 * @{
32
 */
32
 */
33
/**
33
/**
34
 * @file
34
 * @file
35
 * @brief Loads and runs programs from VFS.
35
 * @brief Loads and runs programs from VFS.
36
 *
36
 *
37
 * The program loader is a special init binary. Its image is used
37
 * The program loader is a special init binary. Its image is used
38
 * to create a new task upon a @c task_spawn syscall. The syscall
38
 * to create a new task upon a @c task_spawn syscall. The syscall
39
 * returns the id of a phone connected to the newly created task.
39
 * returns the id of a phone connected to the newly created task.
40
 *
40
 *
41
 * The caller uses this phone to send the pathname and various other
41
 * The caller uses this phone to send the pathname and various other
42
 * information to the loader. This is normally done by the C library
42
 * information to the loader. This is normally done by the C library
43
 * and completely hidden from applications.
43
 * and completely hidden from applications.
44
 */
44
 */
45
 
45
 
46
#include <stdio.h>
46
#include <stdio.h>
47
#include <stdlib.h>
47
#include <stdlib.h>
48
#include <unistd.h>
48
#include <unistd.h>
49
#include <bool.h>
49
#include <bool.h>
50
#include <fcntl.h>
50
#include <fcntl.h>
51
#include <sys/types.h>
51
#include <sys/types.h>
52
#include <ipc/ipc.h>
52
#include <ipc/ipc.h>
53
#include <ipc/services.h>
53
#include <ipc/services.h>
54
#include <ipc/loader.h>
54
#include <ipc/loader.h>
-
 
55
#include <ipc/ns.h>
-
 
56
#include <macros.h>
55
#include <loader/pcb.h>
57
#include <loader/pcb.h>
56
#include <console.h>
-
 
57
#include <errno.h>
58
#include <errno.h>
58
#include <async.h>
59
#include <async.h>
-
 
60
#include <string.h>
59
#include <as.h>
61
#include <as.h>
60
 
62
 
61
#include <elf.h>
63
#include <elf.h>
62
#include <elf_load.h>
64
#include <elf_load.h>
63
 
65
 
64
#define DPRINTF(...)
66
#define DPRINTF(...)
65
 
67
 
66
void program_run(void *entry, pcb_t *pcb);
68
void program_run(void *entry, pcb_t *pcb);
67
 
69
 
68
/** Pathname of the file that will be loaded */
70
/** Pathname of the file that will be loaded */
69
static char *pathname = NULL;
71
static char *pathname = NULL;
70
 
72
 
71
/** The Program control block */
73
/** The Program control block */
72
static pcb_t pcb;
74
static pcb_t pcb;
73
 
75
 
74
/** Number of arguments */
76
/** Number of arguments */
75
static int argc = 0;
77
static int argc = 0;
76
/** Argument vector */
78
/** Argument vector */
77
static char **argv = NULL;
79
static char **argv = NULL;
78
/** Buffer holding all arguments */
80
/** Buffer holding all arguments */
79
static char *arg_buf = NULL;
81
static char *arg_buf = NULL;
80
 
82
 
-
 
83
/** Number of preset files */
-
 
84
static int filc = 0;
-
 
85
/** Preset files vector */
-
 
86
static fdi_node_t **filv = NULL;
-
 
87
/** Buffer holding all preset files */
-
 
88
static fdi_node_t *fil_buf = NULL;
-
 
89
 
81
static elf_info_t prog_info;
90
static elf_info_t prog_info;
82
static elf_info_t interp_info;
91
static elf_info_t interp_info;
83
 
92
 
84
static bool is_dyn_linked;
93
static bool is_dyn_linked;
85
 
94
 
86
/** Used to limit number of connections to one. */
95
/** Used to limit number of connections to one. */
87
static bool connected;
96
static bool connected;
88
 
97
 
89
static void loader_get_taskid(ipc_callid_t rid, ipc_call_t *request)
98
static void ldr_get_taskid(ipc_callid_t rid, ipc_call_t *request)
90
{
99
{
91
    ipc_callid_t callid;
100
    ipc_callid_t callid;
92
    task_id_t task_id;
101
    task_id_t task_id;
93
    size_t len;
102
    size_t len;
94
   
103
   
95
    task_id = task_get_id();
104
    task_id = task_get_id();
96
   
105
   
97
    if (!ipc_data_read_receive(&callid, &len)) {
106
    if (!ipc_data_read_receive(&callid, &len)) {
98
        ipc_answer_0(callid, EINVAL);
107
        ipc_answer_0(callid, EINVAL);
99
        ipc_answer_0(rid, EINVAL);
108
        ipc_answer_0(rid, EINVAL);
100
        return;
109
        return;
101
    }
110
    }
102
   
111
   
103
    if (len > sizeof(task_id))
112
    if (len > sizeof(task_id))
104
        len = sizeof(task_id);
113
        len = sizeof(task_id);
105
   
114
   
106
    ipc_data_read_finalize(callid, &task_id, len);
115
    ipc_data_read_finalize(callid, &task_id, len);
107
    ipc_answer_0(rid, EOK);
116
    ipc_answer_0(rid, EOK);
108
}
117
}
109
 
118
 
110
 
119
 
111
/** Receive a call setting pathname of the program to execute.
120
/** Receive a call setting pathname of the program to execute.
112
 *
121
 *
113
 * @param rid
122
 * @param rid
114
 * @param request
123
 * @param request
115
 */
124
 */
116
static void loader_set_pathname(ipc_callid_t rid, ipc_call_t *request)
125
static void ldr_set_pathname(ipc_callid_t rid, ipc_call_t *request)
117
{
126
{
118
    ipc_callid_t callid;
127
    ipc_callid_t callid;
119
    size_t len;
128
    size_t len;
120
    char *name_buf;
129
    char *name_buf;
121
   
130
   
122
    if (!ipc_data_write_receive(&callid, &len)) {
131
    if (!ipc_data_write_receive(&callid, &len)) {
123
        ipc_answer_0(callid, EINVAL);
132
        ipc_answer_0(callid, EINVAL);
124
        ipc_answer_0(rid, EINVAL);
133
        ipc_answer_0(rid, EINVAL);
125
        return;
134
        return;
126
    }
135
    }
127
   
136
   
128
    name_buf = malloc(len + 1);
137
    name_buf = malloc(len + 1);
129
    if (!name_buf) {
138
    if (!name_buf) {
130
        ipc_answer_0(callid, ENOMEM);
139
        ipc_answer_0(callid, ENOMEM);
131
        ipc_answer_0(rid, ENOMEM);
140
        ipc_answer_0(rid, ENOMEM);
132
        return;
141
        return;
133
    }
142
    }
134
   
143
   
135
    ipc_data_write_finalize(callid, name_buf, len);
144
    ipc_data_write_finalize(callid, name_buf, len);
136
    ipc_answer_0(rid, EOK);
145
    ipc_answer_0(rid, EOK);
137
   
146
   
138
    if (pathname != NULL) {
147
    if (pathname != NULL) {
139
        free(pathname);
148
        free(pathname);
140
        pathname = NULL;
149
        pathname = NULL;
141
    }
150
    }
142
   
151
   
143
    name_buf[len] = '\0';
152
    name_buf[len] = '\0';
144
    pathname = name_buf;
153
    pathname = name_buf;
145
}
154
}
146
 
155
 
147
/** Receive a call setting arguments of the program to execute.
156
/** Receive a call setting arguments of the program to execute.
148
 *
157
 *
149
 * @param rid
158
 * @param rid
150
 * @param request
159
 * @param request
151
 */
160
 */
152
static void loader_set_args(ipc_callid_t rid, ipc_call_t *request)
161
static void ldr_set_args(ipc_callid_t rid, ipc_call_t *request)
153
{
162
{
154
    ipc_callid_t callid;
163
    ipc_callid_t callid;
155
    size_t buf_size, arg_size;
164
    size_t buf_size, arg_size;
156
    char *p;
165
    char *p;
157
    int n;
166
    int n;
158
   
167
   
159
    if (!ipc_data_write_receive(&callid, &buf_size)) {
168
    if (!ipc_data_write_receive(&callid, &buf_size)) {
160
        ipc_answer_0(callid, EINVAL);
169
        ipc_answer_0(callid, EINVAL);
161
        ipc_answer_0(rid, EINVAL);
170
        ipc_answer_0(rid, EINVAL);
162
        return;
171
        return;
163
    }
172
    }
164
   
173
   
165
    if (arg_buf != NULL) {
174
    if (arg_buf != NULL) {
166
        free(arg_buf);
175
        free(arg_buf);
167
        arg_buf = NULL;
176
        arg_buf = NULL;
168
    }
177
    }
169
   
178
   
170
    if (argv != NULL) {
179
    if (argv != NULL) {
171
        free(argv);
180
        free(argv);
172
        argv = NULL;
181
        argv = NULL;
173
    }
182
    }
174
   
183
   
175
    arg_buf = malloc(buf_size + 1);
184
    arg_buf = malloc(buf_size + 1);
176
    if (!arg_buf) {
185
    if (!arg_buf) {
177
        ipc_answer_0(callid, ENOMEM);
186
        ipc_answer_0(callid, ENOMEM);
178
        ipc_answer_0(rid, ENOMEM);
187
        ipc_answer_0(rid, ENOMEM);
179
        return;
188
        return;
180
    }
189
    }
181
   
190
   
182
    ipc_data_write_finalize(callid, arg_buf, buf_size);
191
    ipc_data_write_finalize(callid, arg_buf, buf_size);
183
   
192
   
184
    arg_buf[buf_size] = '\0';
193
    arg_buf[buf_size] = '\0';
185
   
194
   
186
    /*
195
    /*
187
     * Count number of arguments
196
     * Count number of arguments
188
     */
197
     */
189
    p = arg_buf;
198
    p = arg_buf;
190
    n = 0;
199
    n = 0;
191
    while (p < arg_buf + buf_size) {
200
    while (p < arg_buf + buf_size) {
192
        arg_size = str_size(p);
201
        arg_size = str_size(p);
193
        p = p + arg_size + 1;
202
        p = p + arg_size + 1;
194
        ++n;
203
        ++n;
195
    }
204
    }
196
   
205
   
197
    /* Allocate argv */
206
    /* Allocate argv */
198
    argv = malloc((n + 1) * sizeof(char *));
207
    argv = malloc((n + 1) * sizeof(char *));
199
   
208
   
200
    if (argv == NULL) {
209
    if (argv == NULL) {
201
        free(arg_buf);
210
        free(arg_buf);
202
        ipc_answer_0(rid, ENOMEM);
211
        ipc_answer_0(rid, ENOMEM);
203
        return;
212
        return;
204
    }
213
    }
205
 
214
 
206
    /*
215
    /*
207
     * Fill argv with argument pointers
216
     * Fill argv with argument pointers
208
     */
217
     */
209
    p = arg_buf;
218
    p = arg_buf;
210
    n = 0;
219
    n = 0;
211
    while (p < arg_buf + buf_size) {
220
    while (p < arg_buf + buf_size) {
212
        argv[n] = p;
221
        argv[n] = p;
213
       
222
       
214
        arg_size = str_size(p);
223
        arg_size = str_size(p);
215
        p = p + arg_size + 1;
224
        p = p + arg_size + 1;
216
        ++n;
225
        ++n;
217
    }
226
    }
218
   
227
   
219
    argc = n;
228
    argc = n;
220
    argv[n] = NULL;
229
    argv[n] = NULL;
221
 
230
 
222
    ipc_answer_0(rid, EOK);
231
    ipc_answer_0(rid, EOK);
223
}
232
}
224
 
233
 
-
 
234
/** Receive a call setting preset files of the program to execute.
-
 
235
 *
-
 
236
 * @param rid
-
 
237
 * @param request
-
 
238
 */
-
 
239
static void ldr_set_files(ipc_callid_t rid, ipc_call_t *request)
-
 
240
{
-
 
241
    ipc_callid_t callid;
-
 
242
    size_t buf_size;
-
 
243
    if (!ipc_data_write_receive(&callid, &buf_size)) {
-
 
244
        ipc_answer_0(callid, EINVAL);
-
 
245
        ipc_answer_0(rid, EINVAL);
-
 
246
        return;
-
 
247
    }
-
 
248
   
-
 
249
    if ((buf_size % sizeof(fdi_node_t)) != 0) {
-
 
250
        ipc_answer_0(callid, EINVAL);
-
 
251
        ipc_answer_0(rid, EINVAL);
-
 
252
        return;
-
 
253
    }
-
 
254
   
-
 
255
    if (fil_buf != NULL) {
-
 
256
        free(fil_buf);
-
 
257
        fil_buf = NULL;
-
 
258
    }
-
 
259
   
-
 
260
    if (filv != NULL) {
-
 
261
        free(filv);
-
 
262
        filv = NULL;
-
 
263
    }
-
 
264
   
-
 
265
    fil_buf = malloc(buf_size);
-
 
266
    if (!fil_buf) {
-
 
267
        ipc_answer_0(callid, ENOMEM);
-
 
268
        ipc_answer_0(rid, ENOMEM);
-
 
269
        return;
-
 
270
    }
-
 
271
   
-
 
272
    ipc_data_write_finalize(callid, fil_buf, buf_size);
-
 
273
   
-
 
274
    int count = buf_size / sizeof(fdi_node_t);
-
 
275
   
-
 
276
    /* Allocate filvv */
-
 
277
    filv = malloc((count + 1) * sizeof(fdi_node_t *));
-
 
278
   
-
 
279
    if (filv == NULL) {
-
 
280
        free(fil_buf);
-
 
281
        ipc_answer_0(rid, ENOMEM);
-
 
282
        return;
-
 
283
    }
-
 
284
   
-
 
285
    /*
-
 
286
     * Fill filv with argument pointers
-
 
287
     */
-
 
288
    int i;
-
 
289
    for (i = 0; i < count; i++)
-
 
290
        filv[i] = &fil_buf[i];
-
 
291
   
-
 
292
    filc = count;
-
 
293
    filv[count] = NULL;
-
 
294
   
-
 
295
    ipc_answer_0(rid, EOK);
-
 
296
}
-
 
297
 
225
/** Load the previously selected program.
298
/** Load the previously selected program.
226
 *
299
 *
227
 * @param rid
300
 * @param rid
228
 * @param request
301
 * @param request
229
 * @return 0 on success, !0 on error.
302
 * @return 0 on success, !0 on error.
230
 */
303
 */
231
static int loader_load(ipc_callid_t rid, ipc_call_t *request)
304
static int ldr_load(ipc_callid_t rid, ipc_call_t *request)
232
{
305
{
233
    int rc;
306
    int rc;
234
   
307
   
235
    rc = elf_load_file(pathname, 0, 0, &prog_info);
308
    rc = elf_load_file(pathname, 0, 0, &prog_info);
236
    if (rc != EE_OK) {
309
    if (rc != EE_OK) {
237
        DPRINTF("Failed to load executable '%s'.\n", pathname);
310
        DPRINTF("Failed to load executable '%s'.\n", pathname);
238
        ipc_answer_0(rid, EINVAL);
311
        ipc_answer_0(rid, EINVAL);
239
        return 1;
312
        return 1;
240
    }
313
    }
241
   
314
   
242
    elf_create_pcb(&prog_info, &pcb);
315
    elf_create_pcb(&prog_info, &pcb);
243
   
316
   
244
    pcb.argc = argc;
317
    pcb.argc = argc;
245
    pcb.argv = argv;
318
    pcb.argv = argv;
246
   
319
   
-
 
320
    pcb.filc = filc;
-
 
321
    pcb.filv = filv;
-
 
322
   
247
    if (prog_info.interp == NULL) {
323
    if (prog_info.interp == NULL) {
248
        /* Statically linked program */
324
        /* Statically linked program */
249
        is_dyn_linked = false;
325
        is_dyn_linked = false;
250
        ipc_answer_0(rid, EOK);
326
        ipc_answer_0(rid, EOK);
251
        return 0;
327
        return 0;
252
    }
328
    }
253
   
329
   
254
    printf("Load ELF interpreter '%s'\n", prog_info.interp);
330
    printf("Load ELF interpreter '%s'\n", prog_info.interp);
255
    rc = elf_load_file(prog_info.interp, 0, 0, &interp_info);
331
    rc = elf_load_file(prog_info.interp, 0, 0, &interp_info);
256
    if (rc != EE_OK) {
332
    if (rc != EE_OK) {
257
        DPRINTF("Failed to load interpreter '%s.'\n",
333
        DPRINTF("Failed to load interpreter '%s.'\n",
258
            prog_info.interp);
334
            prog_info.interp);
259
        ipc_answer_0(rid, EINVAL);
335
        ipc_answer_0(rid, EINVAL);
260
        return 1;
336
        return 1;
261
    }
337
    }
262
   
338
   
263
    printf("Run interpreter.\n");
339
    printf("Run interpreter.\n");
264
    printf("entry point: 0x%lx\n", interp_info.entry);
340
    printf("entry point: 0x%lx\n", interp_info.entry);
265
    printf("pcb address: 0x%lx\n", &pcb);
341
    printf("pcb address: 0x%lx\n", &pcb);
266
    printf("prog dynamic: 0x%lx\n", prog_info.dynamic);
342
    printf("prog dynamic: 0x%lx\n", prog_info.dynamic);
267
 
343
 
268
    is_dyn_linked = true;
344
    is_dyn_linked = true;
269
    ipc_answer_0(rid, EOK);
345
    ipc_answer_0(rid, EOK);
270
   
346
   
271
    return 0;
347
    return 0;
272
}
348
}
273
 
349
 
274
 
350
 
275
/** Run the previously loaded program.
351
/** Run the previously loaded program.
276
 *
352
 *
277
 * @param rid
353
 * @param rid
278
 * @param request
354
 * @param request
279
 * @return 0 on success, !0 on error.
355
 * @return 0 on success, !0 on error.
280
 */
356
 */
281
static void loader_run(ipc_callid_t rid, ipc_call_t *request)
357
static void ldr_run(ipc_callid_t rid, ipc_call_t *request)
282
{
358
{
283
    const char *cp;
359
    const char *cp;
284
   
360
   
285
    /* Set the task name. */
361
    /* Set the task name. */
286
    cp = str_rchr(pathname, '/');
362
    cp = str_rchr(pathname, '/');
287
    cp = (cp == NULL) ? pathname : (cp + 1);
363
    cp = (cp == NULL) ? pathname : (cp + 1);
288
    task_set_name(cp);
364
    task_set_name(cp);
289
   
365
   
290
    if (is_dyn_linked == true) {
366
    if (is_dyn_linked == true) {
291
        /* Dynamically linked program */
367
        /* Dynamically linked program */
292
        DPRINTF("Run ELF interpreter.\n");
368
        DPRINTF("Run ELF interpreter.\n");
293
        DPRINTF("Entry point: 0x%lx\n", interp_info.entry);
369
        DPRINTF("Entry point: 0x%lx\n", interp_info.entry);
294
        console_close();
-
 
295
       
370
       
296
        ipc_answer_0(rid, EOK);
371
        ipc_answer_0(rid, EOK);
297
        program_run(interp_info.entry, &pcb);
372
        program_run(interp_info.entry, &pcb);
298
    } else {
373
    } else {
299
        /* Statically linked program */
374
        /* Statically linked program */
300
        console_close();
-
 
301
        ipc_answer_0(rid, EOK);
375
        ipc_answer_0(rid, EOK);
302
        program_run(prog_info.entry, &pcb);
376
        program_run(prog_info.entry, &pcb);
303
    }
377
    }
304
 
378
   
305
    /* Not reached */
379
    /* Not reached */
306
}
380
}
307
 
381
 
308
/** Handle loader connection.
382
/** Handle loader connection.
309
 *
383
 *
310
 * Receive and carry out commands (of which the last one should be
384
 * Receive and carry out commands (of which the last one should be
311
 * to execute the loaded program).
385
 * to execute the loaded program).
312
 */
386
 */
313
static void loader_connection(ipc_callid_t iid, ipc_call_t *icall)
387
static void ldr_connection(ipc_callid_t iid, ipc_call_t *icall)
314
{
388
{
315
    ipc_callid_t callid;
389
    ipc_callid_t callid;
316
    ipc_call_t call;
390
    ipc_call_t call;
317
    int retval;
391
    int retval;
318
   
392
   
319
    /* Already have a connection? */
393
    /* Already have a connection? */
320
    if (connected) {
394
    if (connected) {
321
        ipc_answer_0(iid, ELIMIT);
395
        ipc_answer_0(iid, ELIMIT);
322
        return;
396
        return;
323
    }
397
    }
324
   
398
   
325
    connected = true;
399
    connected = true;
326
   
400
   
327
    /* Accept the connection */
401
    /* Accept the connection */
328
    ipc_answer_0(iid, EOK);
402
    ipc_answer_0(iid, EOK);
329
   
403
   
330
    /* Ignore parameters, the connection is already open */
404
    /* Ignore parameters, the connection is already open */
331
    (void) iid;
405
    (void) iid;
332
    (void) icall;
406
    (void) icall;
333
   
407
   
334
    while (1) {
408
    while (1) {
335
        callid = async_get_call(&call);
409
        callid = async_get_call(&call);
336
       
410
       
337
        switch (IPC_GET_METHOD(call)) {
411
        switch (IPC_GET_METHOD(call)) {
338
        case IPC_M_PHONE_HUNGUP:
412
        case IPC_M_PHONE_HUNGUP:
339
            exit(0);
413
            exit(0);
340
        case LOADER_GET_TASKID:
414
        case LOADER_GET_TASKID:
341
            loader_get_taskid(callid, &call);
415
            ldr_get_taskid(callid, &call);
342
            continue;
416
            continue;
343
        case LOADER_SET_PATHNAME:
417
        case LOADER_SET_PATHNAME:
344
            loader_set_pathname(callid, &call);
418
            ldr_set_pathname(callid, &call);
345
            continue;
419
            continue;
346
        case LOADER_SET_ARGS:
420
        case LOADER_SET_ARGS:
347
            loader_set_args(callid, &call);
421
            ldr_set_args(callid, &call);
-
 
422
            continue;
-
 
423
        case LOADER_SET_FILES:
-
 
424
            ldr_set_files(callid, &call);
348
            continue;
425
            continue;
349
        case LOADER_LOAD:
426
        case LOADER_LOAD:
350
            loader_load(callid, &call);
427
            ldr_load(callid, &call);
351
            continue;
428
            continue;
352
        case LOADER_RUN:
429
        case LOADER_RUN:
353
            loader_run(callid, &call);
430
            ldr_run(callid, &call);
354
            /* Not reached */
431
            /* Not reached */
355
        default:
432
        default:
356
            retval = ENOENT;
433
            retval = ENOENT;
357
            break;
434
            break;
358
        }
435
        }
359
        if ((callid & IPC_CALLID_NOTIFICATION) == 0 &&
436
        if ((callid & IPC_CALLID_NOTIFICATION) == 0 &&
360
            IPC_GET_METHOD(call) != IPC_M_PHONE_HUNGUP) {
437
            IPC_GET_METHOD(call) != IPC_M_PHONE_HUNGUP) {
361
            DPRINTF("Responding EINVAL to method %d.\n",
438
            DPRINTF("Responding EINVAL to method %d.\n",
362
                IPC_GET_METHOD(call));
439
                IPC_GET_METHOD(call));
363
            ipc_answer_0(callid, EINVAL);
440
            ipc_answer_0(callid, EINVAL);
364
        }
441
        }
365
    }
442
    }
366
}
443
}
367
 
444
 
368
/** Program loader main function.
445
/** Program loader main function.
369
 */
446
 */
370
int main(int argc, char *argv[])
447
int main(int argc, char *argv[])
371
{
448
{
372
    ipcarg_t phonead;
449
    ipcarg_t phonead;
-
 
450
    task_id_t id;
-
 
451
    int rc;
373
   
452
 
374
    connected = false;
453
    connected = false;
375
   
454
 
-
 
455
    /* Introduce this task to the NS (give it our task ID). */
-
 
456
    id = task_get_id();
-
 
457
    rc = async_req_2_0(PHONE_NS, NS_ID_INTRO, LOWER32(id), UPPER32(id));
-
 
458
    if (rc != EOK)
-
 
459
        return -1;
-
 
460
 
376
    /* Set a handler of incomming connections. */
461
    /* Set a handler of incomming connections. */
377
    async_set_client_connection(loader_connection);
462
    async_set_client_connection(ldr_connection);
378
   
463
   
379
    /* Register at naming service. */
464
    /* Register at naming service. */
380
    if (ipc_connect_to_me(PHONE_NS, SERVICE_LOAD, 0, 0, &phonead) != 0)
465
    if (ipc_connect_to_me(PHONE_NS, SERVICE_LOAD, 0, 0, &phonead) != 0)
381
        return -1;
466
        return -2;
382
   
467
 
383
    async_manager();
468
    async_manager();
384
   
469
   
385
    /* Never reached */
470
    /* Never reached */
386
    return 0;
471
    return 0;
387
}
472
}
388
 
473
 
389
/** @}
474
/** @}
390
 */
475
 */
391
 
476